commit b642da811ea0e34345d73427b91078dfb7ae9b90 Author: Andrew Plotkin Date: Thu Nov 16 18:19:54 2023 -0500 Initial commit. diff --git a/64/how-to-make-disks b/64/how-to-make-disks new file mode 100644 index 0000000..7dc70f6 --- /dev/null +++ b/64/how-to-make-disks @@ -0,0 +1,110 @@ +To Build a Classic Game Disk for Commodore 64 + +Using the TFTP disk on the Commmodore, FORMAT a new disk. +Load "C64" from the TFTP disk. +Take out the TFTP disk and insert the formatted disk, SAVE "STORY" to the +new disk. +LOAD TFTP and RUN it. Place the new disk in drive 8. TN20 from the 20 +both the interpreter and the game file (image is for FOOBLITZKY). + +The first use of TFTP requires that the Commodore be kick started - that +means that you must start the transfer, but after about 10 seconds if using +2 lines, 40 seconds if using 1 line, CTRL-Z out of the TN20, RESET and start +it again. There is no need to restart anything on the Commodore, it is still +waiting for you. Just start the transfer from the 20 again and everything will +go ok this time. The reason to wait is that sometimes it actually works on the +first try (not often, but sometimes) so you have to make sure it failed. +Also, the first transfer is the only time you need do this, every other file +will transfer immediately as long as you continue to do transfers and do not +reboot the machine or use it for other purposes. + +Note: The Commodore screen will go blank during the transfer, the only way to +make sure the transfer is progressing is to look at the 20 terminal (if you +have 2 lines), or to look at the drives, if the light comes on periodically +the transfer is working. After the transfer is through the screen will come +back telling you all is ok and the next available sector on the disk. + +If the drive light starts blinking rapidly something is wrong - check that the +disk is not write protected & the drive is closed, otherwise the disk was +not formatted correctly, try again. Note that the transfer may otherwise +appear to go fine (A's appearing on 20 terminal). The transfer doesn't +recognize disk write problems. + +If the transfer fails on the Commodore end or if after starting it you realize +you hit the wrong key, you must reboot the machine and reload in TFTP. + + + +TO TRANSFER WITH ONE LINE you start the TFTP on the Commodore up to the point +where it says hit return and the screen will go blank. Then reset the terminal +on the 20 to 1200 baud. (type TE SP 1200 and you will get gibberish on the +screen then reset the terminal speed to 1200 itself). This is easier for the +first transfer where you must cancel and restart the 20. Then type TN20, Send, +the filename, and the line is TTY- (TTY dash) ; the full is +TTY-SET-SPEED. You will then be asked the speed. Type 1200 and the +computer will respond that it will begin sending in 30 seconds. Remove the +line from the terminal and attach it to the Commodore, hit on the +Commodore , wait 40 seconds. If the drive light is not coming on +detach the line and reattach it to the 20 terminal. Type CTRL-Z and RESET +then restart the TN20 and follow through with the same responses. This time +the Commodore drive light should start coming on periodically. If not something +is wrong, check all connections on the Commodore, make sure that the black box +and connecting cable are securely attached. IF MORE THAN 1 FILE IS BEING +TRANSFERRED YOU WILL NOT NEED TO START THE TRANSFER TWICE FOR FILES AFTER THE +FIRST HAS BEEN SENT. + + +COMMODORE EZIP + +Building a Commodore 128 disk. + +Use SPLIT on the 20 to split the game at 88064 giving you .PRE and .PUR +files. The game name must have a .ZIP extension, but don't type it in. +(SPLIT filename/88064) + +Format the disk using the FORMAT program on the C-128 TFTP disk. The name +on side 1 must be the game name and on side 2 "SIDE 2". + +Load "TFTP-EZIP" from the TFTP disk, press E to transfer the interpreter, +1 to transfer the .PRE file to side 1, then flip the disk and press 2 to +transfer the .PUR file. + +Remember: The C-64 has to be kick-started for transfers, just start the +transfer, wait 10 secs (if using 2 lines, 35 seconds if using 1 line) then +CTRL-Z to abort on the 20 and without restarting on the Commodore, reset the 20 +and send the file again. This needs to be done for the 1st transfer only, and +sometimes that actually works too. +The baud rate is 1200. +Use the C64 in micro room with the RS232 box to make the transfer. + + + +LOWER CASE EZIP (LZIP) + +Building a Commodore 64 disk. + +Use NSPLIT on the 20 to split the game at 44800 giving you .PRE and .PUR +files. (NSPLIT filename/44800) +Format the disk using the FORMAT program on the C-128 TFTP disk. The name +on side 1 must be "Infocom-s1" and on side 2 "Infocom-s2". +Load "LZIP-LOAD" from the TFTP disk, save it to the game disk on side 1 as +"STORY". (LOAD "LZIP-LOAD",8 SAVE "STORY",8) +Load "TFTP" from the TFTP disk, then: +on side 1: + (L) transfer the Lzip interpreter + (E) transfer the CBD Ezip interpreter + (1) transfer the .PRE file +flip the disk to side 2 and: + (F) transfer the FASTCODE.BIN file + (3) transfer the .PUR file (special for this disk so 3 not 2) + +Remember: The C-64 has to be kick-started for transfers, just start the +transfer, wait 10 secs (if using 2 lines, 35 seconds if using 1 line) then +CTRL-Z to abort on the 20 and without restarting on the Commodore, reset the 20 +and send the file again. This needs to be done for the 1st transfer only, and +sometimes that actually works too. +The baud rate is 1200. + + + + diff --git a/64/lzip/bugger.asm b/64/lzip/bugger.asm new file mode 100644 index 0000000..9217af9 --- /dev/null +++ b/64/lzip/bugger.asm @@ -0,0 +1,216 @@ + PAGE + SBTTL "--- DEBUGGER: APPLE ---" + + ; -------------- + ; APPLE DEBUGGER + ; -------------- + + ; ENTRY: BREAKPOINT ID IN [A] + + ; SMALL DEBUGGER DBG1 (CONVERTS) DBG2 (JUST DISPLAYS) [A] + +DBG1: PHA + LSR A + LSR A + LSR A + LSR A + JSR NIB1 + PLA + +NIB1: AND #%00001111 + TAY + LDA HCHARS,Y + JSR CHROUT + RTS + +DBG2: CMP #' ' + BEQ DBG3 + JSR CHROUT + LDA #' ' +DBG3: JSR CHROUT + RTS + +HCHARS: DB "0123456789ABCDEF" + + END + + + +BLINE: DB "B: OP: PC: S: V: 1: 2: 3: 4: 5: 6: " + DB EOL +BLINL EQU $-BLINE + + +DOBUG: ;RTS + + STA DHOLD + + LDA SHFLAG + AND #%00000100 ; CTRL KEY PRESSED? + BEQ TEST2 ; CONTINUE IF NOT + RTS ; AND EXIT + +TEST2: LDA DHOLD + CMP #0 + BNE BUGIT + RTS + + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + +BUGIT: +; SEC +; JSR PLOT ; GET GAME POSITION +; STX OLDX +; STY OLDY +; LDX #23 +; LDY #0 +; CLC +; JSR PLOT ; AND SET DUBUG ONE + +; LDA DHOLD + LDX #2 ; INIT "CURSOR" + 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 BLINE,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 [ZSP] + LDA ZSP + JSR HEX + + LDX #29 ; CURSOR FOR [MPC] + LDA MPCH + JSR HEX + LDA MPCM + JSR HEX + LDA MPCL + JSR HEX + + LDX #38 + LDA BONE + JSR HEX + + LDX #43 + LDA BTWO + JSR HEX + + LDX #48 + LDA BTHREE + JSR HEX + + LDX #53 + LDA BFOUR + JSR HEX + + LDX #58 + LDA BFIVE + JSR HEX + + LDX #63 + LDA BSIX + JSR HEX + +PPP: LDX #0 +DBG1: LDA BLINE,X ; PRINT DEBUGGER TEXT + JSR CHROUT + INX + CPX #BLINL + BCC DBG1 + + LDA #0 + STA NDX ; CLEAR +; JSR GETIN +; CMP #0 +; BEQ WOK ; IF NO KEY, CONTINUE +WAITT: JSR GETIN ; NOW WAIT FOR ANOTHER KEY + CMP #0 + BEQ WAITT +WOK: NOP + + CMP #'Q' + BNE LLETEX + BRK + +LLETEX: +; LDX OLDX +; LDY OLDY +; CLC +; JSR PLOT ; NOW BACK TO OUR REGULARLY SCHEDULED PROGRAM + 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 BLINE,X + INX + RTS + +HCHARS: DB "0123456789ABCDEF" + +BONE: DB 0 +BTWO: DB 0 +BTHREE: DB 0 +BFOUR: DB 0 +BFIVE: DB 0 +BSIX: DB 0 +DHOLD: DB 0 + + + END + diff --git a/64/lzip/cold.asm b/64/lzip/cold.asm new file mode 100644 index 0000000..feee904 --- /dev/null +++ b/64/lzip/cold.asm @@ -0,0 +1,110 @@ + PAGE + SBTTL "--- MACHINE COLDSTART: CBM64 ---" + + ORG EZIP + + ; --------- + ; COLDSTART + ; --------- + +COLD: LDA R6510 + AND #%11111110 ; SWITCH OUT BASIC ROM + ORA #%00000110 ; KERNAL AND I/O IN + STA R6510 + + LDA #1 ; WHITE + STA COLOR ; TEXT + LDA #12 ; GRAY + STA EXTCOL ; BORDER + STA BGCOLO ; AND BACKGROUND + + LDA #$0E + JSR CHROUT ; USE UPPER/LOWER CHARS + LDA #$80 ; PROHIBIT FURTHER + STA MODE ; CHARSET CHANGES + + LDA #0 + STA MSGFLG ; DISABLE KERNAL MESSAGES + + ; INITIALIZE THE SOUND SYSTEM + + LDX #$1C ; CLEAR + LDA #0 ; ALL +CLD0: STA FRELO1,X ; SID REGISTERS + DEX + BPL CLD0 + + LDA #2 ; SET VOICE #1 + STA PWLO1 ; PULSE WIDTH + LDA #8 ; FOR A + STA PWHI1 ; 50% DUTY CYCLE + + LDA #%10000000 ; DISABLE OUTPUT + STA SIGVOL ; FROM VOICE #3 + + LDA #$EE + STA FRELO3 ; SET VOICE #3 TO + STA FREHI3 ; AN AMUSING FREQUENCY + + LDA #%10000000 ; SPECIFY NOISY WAVEFORM + STA VCREG3 ; FOR RANDOMNESS + + ; INITIALIZE THE SPRITE CURSOR + + LDX #63 ; CLEAR SPRITE #13 RAM + LDA #0 +CN0: STA CURSOR,X + DEX + BPL CN0 + + STA XXPAND ; NORMAL HORIZONTAL + STA YXPAND ; AND VERTICAL SPRITE SIZE + STA SPBGPR ; MAXIMUM SPRITE PRIORITY + STA SPMC ; HI-RES SPRITES + STA SP0COL ; BLACK CURSOR + + JSR MEMCHK ; CHECK FOR EXPANSION RAM + JMP WARM1 + + ; --------------- + ; WARMSTART ENTRY + ; --------------- + +SLOAD: DB "The story is loading ..." + DB EOL +SLOADL EQU $-SLOAD + +WARM1: CLD + LDX #$FF + TXS ; RESET MACHINE STACK + JSR CLALL ; CLOSE EVERYTHING + + JSR CLS ; CLEAR SCREEN, ETC. + + LDY #8 ; POSITION "STORY LOADING" MESSAGE + LDX #11 ; AT (8,11) + CLC + JSR PLOT + + LDX #LOW SLOAD + LDA #HIGH SLOAD + LDY #SLOADL + JSR DLINE ; "THE STORY IS LOADING ..." + + LDA #8 ; MAKE BOOT DRIVE + JSR DOPEN ; AND OPEN IT + + LDA XEXIST ; EXPANSION RAM? + BEQ NOX + LDA #0 ; IF YES TURN OFF FAST, LESS CONFUSING + STA FAST + JMP WARM2 + +NOX: LDA FAST ; FAST DISK? + BEQ WARM2 ; NO, CONTINUE + JSR FINIT ; ELSE INIT FAST DISK + + ; FALL THROUGH TO ZIP WARMSTART AT "WARM2" + + END + diff --git a/64/lzip/disk.asm b/64/lzip/disk.asm new file mode 100644 index 0000000..0c63902 --- /dev/null +++ b/64/lzip/disk.asm @@ -0,0 +1,237 @@ + PAGE + SBTTL "--- DISK ACCESS: CBM64 ---" + + ; -------------- + ; OPEN DRIVE [A] + ; -------------- + + ; ENTRY: DISK ID (8 OR 9 BINARY) IN [A] + +I0: DB "I0" +I0L EQU $-I0 + +DOPEN: STA DRIVE ; SAVE DRIVE ID HERE + JSR DCLOSE ; CLOSE COMMAND & DATA CHANNELS + + LDA #15 ; LOGICAL FILE # + TAY ; SECONDARY ADDRESS + LDX DRIVE ; DEVICE # (8 OR 9) + JSR SETLFS ; SET UP LOGICAL FILE + + LDX #LOW I0 ; POINT TO FILENAME + LDY #HIGH I0 ; "I0:" + LDA #I0L ; LENGTH OF FILENAME + JSR SETNAM + + JMP OPEN ; OPEN THE DISK (CARRY CLEAR IF OK) + + ; -------------------------- + ; OPEN DIRECT ACCESS CHANNEL + ; -------------------------- + +POUND: DB "#" +POUNDL EQU $-POUND + +AOPEN: LDA #0 + STA SPENA ; SHUT OFF CURSOR DMA + + JSR ACLOSE ; CLOSE FIRST + + LDA #2 ; D/A CHANNEL ID + TAY ; SECONDARY ID + LDX DRIVE + JSR SETLFS + + LDX #LOW POUND ; POINT TO FILENAME + LDY #HIGH POUND ; "#" + LDA #POUNDL + JSR SETNAM + + JMP OPEN ; OPEN CHANNEL (CARRY CLEAR IF OK) + + ; ------------------- + ; CLOSE CURRENT DRIVE + ; ------------------- + +DCLOSE: LDA #15 ; CLOSE COMMAND CHANNEL + JSR CLOSE + + ; FALL THROUGH ... + + ; --------------------- + ; CLOSE THE D/A CHANNEL + ; --------------------- + +ACLOSE: LDA #2 ; AND THE + JMP CLOSE ; DATA CHANNEL + + ; ---------------- + ; DIVIDE [A] BY 10 + ; ---------------- + + ; EXIT: QUOTIENT IN [X], REMAINDER IN [A] + +DIV10: LDX #0 ; START WITH ZERO QUOTIENT + +D10L: CMP #10 ; IF DIVISOR < 10, + BCC D10EX ; WE'RE DONE + SBC #10 ; ELSE SUBTRACT ANOTHER 10 + INX ; UPDATE QUOTIENT + BNE D10L ; BRANCH ALWAYS + +D10EX: RTS + + ; --------------- + ; SEND Ux COMMAND + ; --------------- + + ; ENTRY: ASCII "1" OR "2" IN [A] + +COMLIN: DB "U" +DCOMM: DB "*" + DB ":2,0," +DTRAK: DB "***," +DSECT: DB "***" + DB EOL +CMLL EQU $-COMLIN + +SENDU: STA DCOMM ; INSERT COMMAND ("1" OR "2") IN STRING + + ; CONVERT [TRACK] AND [SECTOR] TO ASCII IN [COMLIN] + + LDA TRACK + LDY #2 +TCON: JSR DIV10 ; DIVIDE BY 10 + ORA #'0' ; CONVERT TO ASCII + STA DTRAK,Y ; STORE INTO STRING + TXA ; GET QUOTIENT INTO [A] + DEY ; ZERO-FILL USUSED BYTES + BPL TCON + + LDA SECTOR ; SAME FOR SECTOR ID + LDY #2 +SCON: JSR DIV10 + ORA #'0' + STA DSECT,Y + TXA + DEY + BPL SCON + + ; SEND COMMAND + + JSR CLRCHN + LDX #15 ; OUTPUT TO THE + JSR CHKOUT ; COMMAND CHANNEL + BCS UEX ; EXIT W/CARRY SET IF ERROR + + LDY #0 +SCM0: LDA COMLIN,Y ; SEND THE COMMAND LINE + JSR CHROUT ; TO THE DRIVE CHANNEL + INY ; A BYTE AT A TIME + CPY #CMLL + BCC SCM0 + CLC ; SUCCESS! +UEX: RTS + + ; ---------------------- + ; SET THE BUFFER POINTER + ; ---------------------- + +BPLINE: DB "B-P:2,0" + DB EOL +BPLL EQU $-BPLINE + +SETBP: JSR CLRCHN + LDX #15 ; OUTPUT TO + JSR CHKOUT ; COMMAND CHANNEL + BCS BEX ; CARRY SET IF ERROR + + LDY #0 +SBPL: LDA BPLINE,Y + JSR CHROUT + INY + CPY #BPLL + BCC SBPL + CLC +BEX: RTS + + ; ------------------------------ + ; READ/WRITE A BLOCK TO [IOBUFF] + ; ------------------------------ + + ; ENTRY: [TRACK] = TRACK # (1-35) + ; [SECTOR] = SECTOR # (0-15) + ; [DRIVE] = DRIVE ID (8 OR 9) + ; CARRY CLEAR TO READ, CARRY SET TO WRITE + +DISK: BCS DWRITE ; WRITE IF CARRY SET + + ; READ A DISK BLOCK + + LDA FASTEN ; FAST-READ AVAILABLE? (LC-A) + BEQ SLOW ; USE SLOW CODE IF NOT (LC-A) + LDA FAST ; FAST-READ ENGAGED? (LC-A) + BEQ SLOW ; NO, USE SLOW (LC-A) + + JMP DOFAST ; ELSE USE FAST-READ ROUTINES (LC-A) + +SLOW: JSR AOPEN ; OPEN THE ACCESS CHANNEL + BCS BADISK + + LDA #'1' ; SEND A "U1" COMMAND + JSR SENDU + BCS BADISK ; CARRY SET IF ERROR + + JSR SETBP ; SET THE BUFFER POINTER + BCS BADISK ; CARRY SET IF ERROR + + JSR CLRCHN + LDX #2 ; INPUT FROM + JSR CHKIN ; DATA CHANNEL + BCS BADISK + + LDY #0 +READ1: JSR CHRIN ; GET A BYTE + STA IOBUFF,Y ; MOVE TO I/O BUFFER + INY + BNE READ1 ; DO 256 BYTES + + BEQ SHUTD ; THEN EXIT + + ; WRITE A BLOCK + +DWRITE: JSR AOPEN ; OPEN THE ACCESS CHANNEL + BCS BADISK + + JSR SETBP ; SET THE BUFFER POINTER + BCS BADISK ; CARRY SET IF ERROR + + JSR CLRCHN + LDX #2 ; OUTPUT TO + JSR CHKOUT ; DATA CHANNEL + BCS BADISK ; CARRY SET IF ERROR + + LDY #0 +WRITE1: LDA IOBUFF,Y ; SEND CONTENTS OF [IOBUFF] + JSR CHROUT ; TO THE DRIVE + INY + BNE WRITE1 ; WRITE 256 BYTES + + LDA #'2' ; ISSUE A "U2" COMMAND + JSR SENDU + BCS BADISK ; CARRY SET IF ERROR + +SHUTD: JSR READST + AND #%10000011 + BNE BADISK + + JSR CLRCHN + CLC ; CARRY CLEAR FOR SUCCESS + RTS + +BADISK: JSR CLRCHN + SEC + RTS ; OR SET IF ERROR + + END + diff --git a/64/lzip/dispatch.asm b/64/lzip/dispatch.asm new file mode 100644 index 0000000..9f6afe0 --- /dev/null +++ b/64/lzip/dispatch.asm @@ -0,0 +1,217 @@ + PAGE + SBTTL "--- OPCODE DISPATCH TABLES ---" + + + ; 0-OPS + +OPT0H: DB HIGH ZRTRUE ;0 + DB HIGH ZRFALS ;1 + DB HIGH ZPRI ;2 + DB HIGH ZPRR ;3 + DB HIGH ZNOOP ;4 + DB HIGH ZSAVE ;5 + DB HIGH ZREST ;6 + DB HIGH ZSTART ;7 + DB HIGH ZRSTAK ;8 + DB HIGH POPVAL ;9 + DB HIGH ZQUIT ;10 + DB HIGH ZCRLF ;11 + DB HIGH ZUSL ;12 + DB HIGH ZVER ;13 + DB HIGH BADOP0 ;14 + DB HIGH BADOP0 ;15 + +OPT0L: DB LOW ZRTRUE ;0 + DB LOW ZRFALS ;1 + DB LOW ZPRI ;2 + DB LOW ZPRR ;3 + DB LOW ZNOOP ;4 + DB LOW ZSAVE ;5 + DB LOW ZREST ;6 + DB LOW ZSTART ;7 + DB LOW ZRSTAK ;8 + DB LOW POPVAL ;9 + DB LOW ZQUIT ;10 + DB LOW ZCRLF ;11 + DB LOW ZUSL ;12 + DB LOW ZVER ;13 + DB LOW BADOP0 ;14 + DB LOW BADOP0 ;15 + + ; 1-OPS + +OPT1H: DB HIGH ZZERO ;0 + DB HIGH ZNEXT ;1 + DB HIGH ZFIRST ;2 + DB HIGH ZLOC ;3 + DB HIGH ZPTSIZ ;4 + DB HIGH ZINC ;5 + DB HIGH ZDEC ;6 + DB HIGH ZPRB ;7 + DB HIGH ZCALL1 ;8 (EZIP) + DB HIGH ZREMOV ;9 + DB HIGH ZPRD ;10 + DB HIGH ZRET ;11 + DB HIGH ZJUMP ;12 + DB HIGH ZPRINT ;13 + DB HIGH ZVALUE ;14 + DB HIGH ZBCOM ;15 + +OPT1L: DB LOW ZZERO ;0 + DB LOW ZNEXT ;1 + DB LOW ZFIRST ;2 + DB LOW ZLOC ;3 + DB LOW ZPTSIZ ;4 + DB LOW ZINC ;5 + DB LOW ZDEC ;6 + DB LOW ZPRB ;7 + DB LOW ZCALL1 ;8 (EZIP) + DB LOW ZREMOV ;9 + DB LOW ZPRD ;10 + DB LOW ZRET ;11 + DB LOW ZJUMP ;12 + DB LOW ZPRINT ;13 + DB LOW ZVALUE ;14 + DB LOW ZBCOM ;15 + + ; 2-OPS + +OPT2H: DB HIGH BADOP2 ;0 (UNDEFINED) + DB HIGH ZEQUAL ;1 + DB HIGH ZLESS ;2 + DB HIGH ZGRTR ;3 + DB HIGH ZDLESS ;4 + DB HIGH ZIGRTR ;5 + DB HIGH ZIN ;6 + DB HIGH ZBTST ;7 + DB HIGH ZBOR ;8 + DB HIGH ZBAND ;9 + DB HIGH ZFSETP ;10 + DB HIGH ZFSET ;11 + DB HIGH ZFCLR ;12 + DB HIGH ZSET ;13 + DB HIGH ZMOVE ;14 + DB HIGH ZGET ;15 + DB HIGH ZGETB ;16 + DB HIGH ZGETP ;17 + DB HIGH ZGETPT ;18 + DB HIGH ZNEXTP ;19 + DB HIGH ZADD ;20 + DB HIGH ZSUB ;21 + DB HIGH ZMUL ;22 + DB HIGH ZDIV ;23 + DB HIGH ZMOD ;24 + DB HIGH ZCALL2 ;25 (EZIP) + DB HIGH BADOP2 ;26 + DB HIGH BADOP2 ;27 + DB HIGH BADOP2 ;28 + DB HIGH BADOP2 ;29 + DB HIGH BADOP2 ;30 + DB HIGH BADOP2 ;31 + +OPT2L: DB LOW BADOP2 ;0 (UNDEFINED) + DB LOW ZEQUAL ;1 + DB LOW ZLESS ;2 + DB LOW ZGRTR ;3 + DB LOW ZDLESS ;4 + DB LOW ZIGRTR ;5 + DB LOW ZIN ;6 + DB LOW ZBTST ;7 + DB LOW ZBOR ;8 + DB LOW ZBAND ;9 + DB LOW ZFSETP ;10 + DB LOW ZFSET ;11 + DB LOW ZFCLR ;12 + DB LOW ZSET ;13 + DB LOW ZMOVE ;14 + DB LOW ZGET ;15 + DB LOW ZGETB ;16 + DB LOW ZGETP ;17 + DB LOW ZGETPT ;18 + DB LOW ZNEXTP ;19 + DB LOW ZADD ;20 + DB LOW ZSUB ;21 + DB LOW ZMUL ;22 + DB LOW ZDIV ;23 + DB LOW ZMOD ;24 + DB LOW ZCALL2 ;25 (EZIP) + DB LOW BADOP2 ;26 + DB LOW BADOP2 ;27 + DB LOW BADOP2 ;28 + DB LOW BADOP2 ;29 + DB LOW BADOP2 ;30 + DB LOW BADOP2 ;31 + + ; X-OPS + +OPTXH: DB HIGH ZCALL ;0 + DB HIGH ZPUT ;1 + DB HIGH ZPUTB ;2 + DB HIGH ZPUTP ;3 + DB HIGH ZREAD ;4 + DB HIGH ZPRC ;5 + DB HIGH ZPRN ;6 + DB HIGH ZRAND ;7 + DB HIGH ZPUSH ;8 + DB HIGH ZPOP ;9 + DB HIGH ZSPLIT ;10 + DB HIGH ZSCRN ;11 + + ; (EZIPS FROM HERE ON) + DB HIGH ZXCALL ;12 + DB HIGH ZCLR ;13 + DB HIGH ZERASE ;14 + DB HIGH ZCURST ;15 + DB HIGH ZCURGT ;16 (NOT IMPLEMENTED) + DB HIGH ZLIGHT ;17 + DB HIGH ZBUFOUT ;18 + DB HIGH ZDIRT ;19 + DB HIGH ZDIRIN ;20 (NOT IMPLEMENTED) + DB HIGH ZSOUND ;21 + DB HIGH ZINPUT ;22 + DB HIGH ZINTBL ;23 + DB HIGH BADOPX ;24 + DB HIGH BADOPX ;25 + DB HIGH BADOPX ;26 + DB HIGH BADOPX ;27 + DB HIGH BADOPX ;28 + DB HIGH BADOPX ;29 + DB HIGH BADOPX ;30 + DB HIGH BADOPX ;31 + +OPTXL: DB LOW ZCALL ;0 + DB LOW ZPUT ;1 + DB LOW ZPUTB ;2 + DB LOW ZPUTP ;3 + DB LOW ZREAD ;4 + DB LOW ZPRC ;5 + DB LOW ZPRN ;6 + DB LOW ZRAND ;7 + DB LOW ZPUSH ;8 + DB LOW ZPOP ;9 + DB LOW ZSPLIT ;10 + DB LOW ZSCRN ;11 + + ; (EZIPS FROM HERE ON) + DB LOW ZXCALL ;12 + DB LOW ZCLR ;13 + DB LOW ZERASE ;14 + DB LOW ZCURST ;15 + DB LOW ZCURGT ;16 (NOT IMPLEMENTED) + DB LOW ZLIGHT ;17 + DB LOW ZBUFOUT ;18 + DB LOW ZDIRT ;19 + DB LOW ZDIRIN ;20 (NOT IMPLEMENTED) + DB LOW ZSOUND ;21 + DB LOW ZINPUT ;22 + DB LOW ZINTBL ;23 + DB LOW BADOPX ;24 + DB LOW BADOPX ;25 + DB LOW BADOPX ;26 + DB LOW BADOPX ;27 + DB LOW BADOPX ;28 + DB LOW BADOPX ;29 + DB LOW BADOPX ;30 + DB LOW BADOPX ;31 + + END diff --git a/64/lzip/eq.asm b/64/lzip/eq.asm new file mode 100644 index 0000000..d4856be --- /dev/null +++ b/64/lzip/eq.asm @@ -0,0 +1,194 @@ + PAGE + SBTTL "--- MEMORY ORGANIZATION ---" + + +TRUE EQU $FF +FALSE EQU 0 +LO EQU 0 +HI EQU 1 + + ; ALL THE VARIOUS BUFFERS NEEDED + +IOBUFF EQU MSTART ; PAGENG BUFFER + +ZSTKBL EQU MSTART+$100 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) +ZSTKTL EQU ZSTKBL+$100 ; TOP, LO +ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI +ZSTKTH EQU ZSTKBL+$300 ; TOP, HI + +NEXTPNT EQU MSTART+$500 ; PAGING TABLES +PREVPNT EQU NEXTPNT+$80 +VPAGEH EQU PREVPNT+$80 +VPAGEL EQU VPAGEH+$80 + +LOCALS EQU MSTART+$700 ; LOCAL VARIABLE STORAGE (30 BYTES) +BUFSAV EQU LOCALS+$20 ; AUXILIARY INPUT BUFFER (80 BYTES) + +EZIP EQU MSTART+$800 +ZBEGIN EQU EZIP+$2A00 ; START OF PRELOAD + + +; --------------------- +; 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 DB II 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 +ZINTWD EQU 30 ; INTERPRETER ID WORD (SUPPLIED BY EZIP) +ZSCRWD EQU 32 ; SCREEN PARAMETER WORD ( " " " ) + + + ; THESE ARE THE FLAGS & REGISTERS USED TO ACCESS THE 256K + ; EXPANSION RAM FOR THE C64 IF IT IS ATTACHED + +XFLAGS EQU $DF00 ; THE PAGE THE FLAGS ARE ON +XFER EQU 1 ; (BYTE) WRITE TO THIS TO DO TRANSFER +XBUFF EQU 2 ; (WORD) ADDR OF TRANSFER BUFFER IN MAIN MEMORY +XRAM EQU 4 ; (WORD) ADDR OF BUFFER IN XPANSION RAM (XRAM) +XBANK EQU 6 ; (BYTE) WHICH BANK OF XPANSION RAM +XSIZ EQU 7 ; (WORD) SIZE OF TRANSFER IN BYTES +XINT EQU 9 ; (BYTE) SET FOR NO INTERRUPTS DURING TRANSFERS +XINCR EQU 10 ; (BYTE) SET FOR POINTERS TO INCREMENT + + + SBTTL "--- ZIP Z-PAGE VARIABLES ---" + + +OPCODE EQU ZEROPG ; (BYTE) CURRENT OPCODE +VALUE EQU OPCODE+1 ; OPCODE+21 ; (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 +L EQU VALUE+8 ; (WORD) GEN-PURPOSE REGISTER #4 +ZPC EQU VALUE+10 ;ZSP+4 ; (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] +ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE +ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +ZPNTH EQU ZPCPNT+1 ; (BYTE) +ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +MPC EQU ZPCPNT+3 ; (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] +MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE +MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +MPNTH EQU MPCPNT+1 ; (BYTE) +MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +ZCODE EQU MPCPNT+3 ; (BYTE) 1ST ABSOLUTE PAGE OF PRELOAD +ZPURE EQU ZCODE+1 ; (BYTE) 1ST VIRTUAL PAGE OF "PURE" Z-CODE +GLOBAL EQU ZCODE+2 ; (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 ; (9 BYTES) INPUT BUFFER +;OUT EQU IN+9 ; (9 BYTES) OUTPUT BUFFER +SOURCE EQU GLOBAL+8 ; OUT+9 ; (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 +DBLOCK EQU SOURCE+19 ; (WORD) Z-BLOCK TO READ +DBUFF EQU DBLOCK+2 ; (WORD) RAM PG TO ACCESS (LSB = 0) +;PAGEOT EQU DBLOCK+4 ; (WORD) ZPCH,M OF 1ST VIRTUAL PAGE + +DIRFLG EQU DBUFF+2 ; (BYTE) OUTPUT TO SCREEN (0) TABLE (1) FLAG +DIRTBL EQU DBUFF+3 ; (WORD) CONTAINS TBLE TO STORE CHARS TO +DIRITM EQU DBUFF+5 ; (WORD) OFFSET IN OUTPUT TBL (DIRTBL) +DIRCNT EQU DBUFF+7 ; (WORD) COUNT OF CHARS IN TBL (DIRTBL) +BUFFLG EQU DBUFF+9 ; (BYTE) DISPLAY BUFFERED (0) UNBUFFERED (1) +CHRMAX EQU DBUFF+10 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD +;XSIZE EQU DBUFF+11 ; (BYTE) SCREEN WIDTH FOR TESTS (LC-A) + +RAND1 EQU CHRMAX+1 ; (BYTE) RANDOM # +SPLITF EQU CHRMAX+2 ; (BYTE) WHICH WINDOW TO WRITE IN +RDTBL1 EQU CHRMAX+3 ; (WORD) READ TABLE 1 (ABSOLUTE- EZIP) +RDTBL2 EQU RDTBL1+2 ; (WORD) READ TABLE 2 +LENGTH EQU RDTBL1+4 ; (BYTE) CHAR POSITION ON THE SCREEN +CHRCNT EQU LENGTH+1 ; (BYTE) CHAR POSITION IN [LBUFF] +OLDLEN EQU CHRCNT+1 ; (BYTE) OLD LINE LENGTH +OLDEND EQU OLDLEN+1 ; (BYTE) OLD LAST CHAR IN [LBUFF] +SCRIPT EQU OLDEND+1 ; (BYTE) SCRIPT ENABLE FLAG +LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER +LMAX EQU LINCNT+1 ; (BYTE) MAX # LINES/SCREEN +IOCHAR EQU LINCNT+2 ; (BYTE) CHARACTER BUFFER +SLINE EQU IOCHAR+1 ; (BYTE) BORDERLINE FOR SPLIT +SPSTAT EQU IOCHAR+2 ; (BYTE) SPLIT SCREEN STATUS FLAG +LFROM EQU SPSTAT+1 ; (WORD) "FROM" LINE ADDRESS +LTO EQU LFROM+2 ; (WORD) "TO" LINE ADDRESS +PRLEN EQU LTO+2 ; (BYTE) SCRIPT LINE LENGTH +SECTOR EQU PRLEN+1 ; (BYTE) TARGET SECTOR +TRACK EQU SECTOR+1 ; (BYTE) TARGET TRACK +GPOSIT EQU SECTOR+2 ; (BYTE) DEFAULT SAVE POSITION +GDRIVE EQU GPOSIT+1 ; (BYTE) DEFAULT SAVE DRIVE +TPOSIT EQU GDRIVE+1 ; (BYTE) TEMP SAVE POSITION +TDRIVE EQU TPOSIT+1 ; (BYTE) TEMP SAVE DRIVE +DRIVE EQU TDRIVE+1 ; (BYTE) CURRENT DRIVE +SIDEFLG EQU DRIVE+1 ; (BYTE) =1 IF WE ARE ON SIDE 1 2 IF SIDE 2 +SRHOLD EQU SIDEFLG+1 ; (BYTE) +TIMER EQU SRHOLD+1 ; (WORD) TIMED INPUT COUNTER +ZSP EQU TIMER+2 ; (WORD) +OLDZSP EQU ZSP+2 ; (WORD) +SCREENF EQU OLDZSP+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT +SCRIPTF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR PRINTER OUTPUT +TABLEF EQU SCRIPTF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT +VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH +PSTAT EQU TABLEF+4 ; (BYTE) PRINTER STATUS + +DVD EQU TABLEF+5 ; (WORD) DISK DIVIDEND +DSOR EQU TABLEF+7 ; (WORD) DISK DIVISOR +DTEMP EQU TABLEF+9 ; (WORD) DISK TEMP VARIABLE + +SAVSIZ EQU TABLEF+11 ; (BYTE) # OF SECTORS PER SAVE +NUMSAV EQU SAVSIZ+1 ; (BYTE) # SAVES OF THIS GAME POSSIBLE +OLDX EQU SAVSIZ+2 ; (BYTE) +OLDY EQU SAVSIZ+3 ; (BYTE) SCREEN COORDS. +;TOP EQU SAVSIZ+4 ; (BYTE) HOLDS WTOP (LC-A) + +NARGS EQU SAVSIZ+4 ; (BYTE) # ARGUMENTS +ARG1 EQU NARGS+2 ; (WORD) ARGUMENT #1 +ARG2 EQU NARGS+4 ; (WORD) ARGUMENT #2 +ARG3 EQU NARGS+6 ; (WORD) ARGUMENT #3 +ARG4 EQU NARGS+8 ; (WORD) ARGUMENT #4 +ARG5 EQU NARGS+10 ; (WORD) +ARG6 EQU NARGS+12 ; (WORD) +ARG7 EQU NARGS+14 ; (WORD) +ARG8 EQU NARGS+16 ; (WORD) +ABYTE EQU NARGS+18 ; (BYTE) X-OP ARGUMENT BYTE +BBYTE EQU NARGS+19 ; (BYTE) XCALL ARG BYTE (EZIP) +ADEX EQU NARGS+20 ; (BYTE) X-OP ARGUMENT INDEX +RNUM1 EQU NARGS+21 ; (BYTE) FOR RANDOM - DON'T USE +RNUM2 EQU NARGS+22 ; (BYTE) FOR RANDOM - DON'T USE + +; THE REST OF THE VARIABLES (THAT WOULDN'T FIT) ARE AT THE END OF IO.ASM + +LASTZP EQU RNUM2+1 ; CHECK FOR OVER ZERO PAGE + + END diff --git a/64/lzip/ezip.asm b/64/lzip/ezip.asm new file mode 100644 index 0000000..363a1a2 --- /dev/null +++ b/64/lzip/ezip.asm @@ -0,0 +1,77 @@ + + + TITLE "EZIP/6502 INFOCOM, INC. --- EQUATES" + + ; -------------------------- + ; EZIP/6502 2.0 + ; Z-CODE INTERPRETER PROGRAM + ; FOR APPLE IIE/IIC + ; -------------------------- + + ; INFOCOM, INC. + ; 125 CAMBRIDGEPARK DRIVE + ; CAMBRIDGE, MA 02140 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + +DEBUG EQU 1 ; ASSEMBLY FLAG FOR DEBUGGER (1 = YES) + + ; ----------- + ; 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 -- IMPURE CODE TOO LARGE (BM 1/20/86) + ; 14 -- DRIVE ACCESS + ; 15 -- NOT AN EZIP GAME + ; 16 -- ILLEGAL EXTENDED RANGE X-OP + + INCLUD EQ.SRC + + + TITLE "ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT SHELL" + INCLUD HARDEQ.SRC + INCLUD RWTS.SRC + INCLUD ZDOS.SRC + INCLUD MACHINE.SRC + INCLUD COLD.SRC + + TITLE "ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE" + INCLUD WARM.SRC + INCLUD MAIN.SRC + INCLUD SUBS.SRC + INCLUD DISPATCH.SRC + + TITLE "ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS" + INCLUD OPS012.SRC + INCLUD OPSX.SRC + INCLUD READ.SRC + + TITLE "ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT" + + INCLUD XPAGING.SRC + INCLUD ZSTRING.SRC + INCLUD OBJECTS.SRC + + TITLE "ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT SHELL" + + INCLUD IO.SRC ; (EZIP SO COLD IS ON 1ST TRACK) + + IF DEBUG + INCLUD BUGGER.SRC + ENDIF + + END + diff --git a/64/lzip/fast.asm b/64/lzip/fast.asm new file mode 100644 index 0000000..1a4436c --- /dev/null +++ b/64/lzip/fast.asm @@ -0,0 +1,205 @@ + PAGE + SBTTL "--- FAST DISK READ: CBM64 ---" + + ; -------------- + ; INIT FAST READ + ; -------------- + +FINIT: LDA #2 + TAY + LDX #8 + JSR SETLFS + LDA #2 + LDX #LOW DNAME + LDY #HIGH DNAME + JSR SETNAM + JSR OPEN + + LDX #15 + JSR CHKOUT + + LDY #10 ; SEND "U1:2,0,20,0" +FNT0: LDA DCMND,Y ; U1:CHANNEL,DRIVE,TRACK,BLOCK + JSR CHROUT + DEY + BPL FNT0 + + JSR CLRCHN ; RESET CHANNEL + LDX #15 + JSR CHKOUT + + LDA #'U' ; SEND "U3" COMMAND + JSR CHROUT + LDA #'3' + JSR CHROUT + + LDA #$FF + STA FASTEN ; SET "FAST-READ ENABLED" FLAG + JMP CLRCHN ; CLEAR & RETURN + +DNAME: DB "#2" + +;DCMND: DB "1,1,0,2:1U" +DCMND: DB "0,02,0,2:1U" ; THIS IS IN REVERSE + + ; ---------------------- + ; FAST-READ A DISK BLOCK + ; ---------------------- + + ; ENTRY: TARGET TRACK IN [TRACK] + ; TARGET SECTOR IN [SECTOR] + ; EXIT: DATA IN [IOBUFF] + +DOFAST: LDA TRACK ; SPECIFY + JSR SNDBYT ; TRACK & + LDA SECTOR ; SECTOR TO READ + JSR SNDBYT + + LDA #0 + STA FINDEX ; INIT LOOP INDEX + +DFST1: JSR ZOOM ; GET A BYTE FROM DISK + LDY FINDEX + STA IOBUFF,Y ; MOVE TO [IOBUFF] + INC FINDEX + BNE DFST1 ; FILL THE BUFFER + CLC + RTS + + ; ------------------- + ; DISENGAGE FAST-READ + ; ------------------- + +FOFF: LDA FASTEN ; IF ALREADY OFF, MESSES THINGS UP (LC-A) + BNE TRNOFF ; (LC-A) + RTS ; TO TURN OFF AGAIN, SO DON'T (LC-A) + +TRNOFF: LDA #0 + STA FASTEN ; CLEAR "FAST-READ ENABLED" FLAG + JSR SNDBYT ; SEND "TRACK 0" + LDA #8 + JSR DOPEN ; CLOSE & OPEN BOOT DRIVE + JSR AOPEN ; OPEN DATA CHANNEL + + LDX #15 + JSR CHKOUT ; OUTPUT TO COMMAND CHANNEL + + LDA #'U' ; SEND "UI" TO RE-INIT DRIVE + JSR CHROUT + LDA #'I' + JSR CHROUT + + JMP CLRCHN ; CLEAR & RETURN + + ; ----------------------- + ; GET FAST BYTE FROM DISK + ; ----------------------- + +ZOOM: LDA #$80 + STA FDATA + +GETBIT: LDA CI2PRA + ORA #$10 + STA CI2PRA + +GETBO0: LDA CI2PRA + TAY + AND #$80 + BNE GETBO0 + TYA + AND #$EF + STA CI2PRA + +GETBO1: LDA CI2PRA + TAY + AND #$80 + BEQ GETBO1 + +GETBO2: TYA + ORA #$10 + STA CI2PRA + + LDX #7 +GETBO3: DEX + BNE GETBO3 + LDA CI2PRA + TAY + AND #$EF + STA CI2PRA + TYA + ASL A + ROR FDATA + BCC GETBO2 + + LDA FDATA + EOR #$FF + RTS + + ; ----------------- + ; SEND BYTE TO DISK + ; ----------------- + +SNDBYT: STA FDATA + + LDX #8 +BIT: JSR SCLK1 + +WAITD: JSR SETTLE + AND #$80 + BNE WAITD + JSR SCLK0 + +SNDBO1: JSR SETTLE + TAY + AND #$80 + BEQ SNDBO1 + + TYA + ORA #$10 + LSR FDATA + BCC SNDBO2 + ORA #$20 + +SNDBO2: STA CI2PRA + + LDY #7 +SNDBO3: DEY + BNE SNDBO3 + JSR SCLK0 + + DEX + BNE BIT + RTS + + ; --------------------------- + ; WAIT FOR I/O PORT TO SETTLE + ; --------------------------- + +SETTLE: LDA CI2PRA + CMP CI2PRA + BNE SETTLE + RTS + + ; --------------- + ; SET CLKOUT TO 1 + ; --------------- + +SCLK1: LDA CI2PRA + ORA #$10 + AND #$DF + BNE PUTPRT + + ; --------------- + ; SET CLKOUT TO 0 + ; --------------- + +SCLK0: LDA CI2PRA + AND #$CF + +PUTPRT: STA CI2PRA + NOP + NOP + RTS + + END + diff --git a/64/lzip/fast.lzip b/64/lzip/fast.lzip new file mode 100644 index 0000000..489672d --- /dev/null +++ b/64/lzip/fast.lzip @@ -0,0 +1,200 @@ + PAGE + SBTTL "--- FAST DISK READ: CBM64 ---" + + ; -------------- + ; INIT FAST READ + ; -------------- + +FINIT: LDA #2 + TAY + LDX #8 + JSR SETLFS + LDA #2 + LDX #LOW DNAME + LDY #HIGH DNAME + JSR SETNAM + JSR OPEN + + LDX #15 + JSR CHKOUT + + LDY #9 ; SEND "U1:2,0,1,1" +FNT0: LDA DCMND,Y + JSR CHROUT + DEY + BPL FNT0 + + JSR CLRCHN ; RESET CHANNEL + LDX #15 + JSR CHKOUT + + LDA #'U' ; SEND "U3" COMMAND + JSR CHROUT + LDA #'3' + JSR CHROUT + + LDA #$FF + STA FASTEN ; SET "FAST-READ ENABLED" FLAG + JMP CLRCHN ; CLEAR & RETURN + +DNAME: DB "#2" + +DCMND: DB "1,1,0,2:1U" + + ; ---------------------- + ; FAST-READ A DISK BLOCK + ; ---------------------- + + ; ENTRY: TARGET TRACK IN [TRACK] + ; TARGET SECTOR IN [SECTOR] + ; EXIT: DATA IN [IOBUFF] + +DOFAST: LDA TRACK ; SPECIFY + JSR SNDBYT ; TRACK & + LDA SECTOR ; SECTOR TO READ + JSR SNDBYT + + LDA #0 + STA FINDEX ; INIT LOOP INDEX + +DFST1: JSR ZOOM ; GET A BYTE FROM DISK + LDY FINDEX + STA IOBUFF,Y ; MOVE TO [IOBUFF] + INC FINDEX + BNE DFST1 ; FILL THE BUFFER + CLC + RTS + + ; ------------------- + ; DISENGAGE FAST-READ + ; ------------------- + +FOFF: LDA #0 + STA FASTEN ; CLEAR "FAST-READ ENABLED" FLAG + JSR SNDBYT ; SEND "TRACK 0" + LDA #8 + JSR DOPEN ; CLOSE & OPEN BOOT DRIVE + JSR AOPEN ; OPEN DATA CHANNEL + + LDX #15 + JSR CHKOUT ; OUTPUT TO COMMAND CHANNEL + + LDA #'U' ; SEND "UI" TO RE-INIT DRIVE + JSR CHROUT + LDA #'I' + JSR CHROUT + + JMP CLRCHN ; CLEAR & RETURN + + ; ----------------------- + ; GET FAST BYTE FROM DISK + ; ----------------------- + +ZOOM: LDA #$80 + STA FDATA + +GETBIT: LDA CI2PRA + ORA #$10 + STA CI2PRA + +GETBO0: LDA CI2PRA + TAY + AND #$80 + BNE GETBO0 + TYA + AND #$EF + STA CI2PRA + +GETBO1: LDA CI2PRA + TAY + AND #$80 + BEQ GETBO1 + +GETBO2: TYA + ORA #$10 + STA CI2PRA + + LDX #7 +GETBO3: DEX + BNE GETBO3 + LDA CI2PRA + TAY + AND #$EF + STA CI2PRA + TYA + ASL A + ROR FDATA + BCC GETBO2 + + LDA FDATA + EOR #$FF + RTS + + ; ----------------- + ; SEND BYTE TO DISK + ; ----------------- + +SNDBYT: STA FDATA + + LDX #8 +BIT: JSR SCLK1 + +WAITD: JSR SETTLE + AND #$80 + BNE WAITD + JSR SCLK0 + +SNDBO1: JSR SETTLE + TAY + AND #$80 + BEQ SNDBO1 + + TYA + ORA #$10 + LSR FDATA + BCC SNDBO2 + ORA #$20 + +SNDBO2: STA CI2PRA + + LDY #7 +SNDBO3: DEY + BNE SNDBO3 + JSR SCLK0 + + DEX + BNE BIT + RTS + + ; --------------------------- + ; WAIT FOR I/O PORT TO SETTLE + ; --------------------------- + +SETTLE: LDA CI2PRA + CMP CI2PRA + BNE SETTLE + RTS + + ; --------------- + ; SET CLKOUT TO 1 + ; --------------- + +SCLK1: LDA CI2PRA + ORA #$10 + AND #$DF + BNE PUTPRT + + ; --------------- + ; SET CLKOUT TO 0 + ; --------------- + +SCLK0: LDA CI2PRA + AND #$CF + +PUTPRT: STA CI2PRA + NOP + NOP + RTS + + END + diff --git a/64/lzip/hardeq.asm b/64/lzip/hardeq.asm new file mode 100644 index 0000000..bb823c9 --- /dev/null +++ b/64/lzip/hardeq.asm @@ -0,0 +1,197 @@ + PAGE + SBTTL "--- HARDWARE EQUATES: CBM64 ---" + + + ; --------- + ; CONSTANTS + ; --------- + +EZIPID EQU 8 ; ID BYTE STATING THIS IS A C-64 EZIP +VERSID EQU 'A' ; VERSION OF INTERPRETER + +YSIZE EQU 24 +XSIZE EQU 39 +TOPSIZ EQU 40 ; LC-A TOP SCREEN IS 1 LARGER + +KERNAL EQU %00000010 ; ORA IT IN TO TURN KERNAL (ROM) ON $E000-$FFFF +RAM EQU %11111101 ; AND IT IN TO TURN RAM ON INSTEAD OF KERNAL +XWRITE EQU 252 ; CODE TO WRITE TO EXPANSION RAM +XREAD EQU 253 ; AND TO READ FROM IT + +; THE FIRST 43.5K (SIDE1) MUST +; BE RAM RESIDENT (394=$18A PAGES) + +PSIDE1 EQU 175 ; 43.75 K IS ON SIDE 1 OF DISK + +; PBEGIN IS FIRST PAGENG BUFFER (RAM PAGE UNDER KERNAL) + +SWAPMEM EQU $E0 ; SPEEDUP +PBEGIN EQU $FA ; (LC-A) +NUMBUFS EQU $FF-$FA ; (LC-A) + +EOL EQU $0D ; EOL CHAR +SPACE EQU $20 ; SPACE CHAR +BACKSP EQU $14 ; BACKSPACE +LF EQU $0A ; LINE FEED +LEFT EQU $9D ; ARROW KEYS +RIGHT EQU $1D +UP EQU $91 +DOWN EQU $11 + + ; ----------------- + ; MONITOR VARIABLES + ; ----------------- + +QUOTMOD EQU $D4 ; QUOTES SENT TO SCREEN TURN ON STRANGE + ; MODE, THIS FLAG SET TO 0 SHOULD + ; TURN THAT MODE OFF ($D4 = LZIP) + + ; --------- + ; ZERO-PAGE + ; --------- + +D6510 EQU $00 ; 6510 DATA DIRECTION REGISTER +R6510 EQU $01 ; 6510 I/O PORT +RAMFLG EQU $01 ; IT SETS ON RAM OR ROM +FAST EQU $02 ; FAST-READ AVAILABLE FLAG +STKEY EQU $91 ; STOP KEY FLAG +MSGFLG EQU $9D ; KERNAL MESSAGE CONTROL FLAG +TIME EQU $A2 ; SYSTEM JIFFY TIMER +LSTX EQU $C5 ; LAST KEY PRESSED +NDX EQU $C6 ; # CHARS IN KEYBOARD BUFFER +RVS EQU $C7 ; REVERSE CHARACTER FLAG +SFDX EQU $CB ; CURRENT KEYPRESS +BLNSW EQU $CC ; CURSOR BLINK SWITCH +PNTR EQU $D3 ; CURSOR COLUMN IN LOGICAL LINE +TBLX EQU $D6 ; CURRENT CURSOR ROW +LDTB1 EQU $D9 ; 25-BYTE LINE LINK TABLE +KEYTAB EQU $F5 ; KEYBOARD DECODE TABLE VECTOR + +FDATA EQU $FB ; FAST-READ DATA BUFFER +FINDEX EQU $FC ; FAST-READ BUFFER INDEX +FASTEN EQU $FD ; FAST-READ ENABLED FLAG + + ; ----------- + ; PAGES 2 & 3 + ; ----------- + +LBUFF EQU $0200 ; 89-BYTE LINE BUFFER +KEYD EQU $0277 ; KEYBOARD QUEUE +COLOR EQU $0286 ; FOREGROUND COLOR FOR TEXT +HIBASE EQU $0288 ; TOP PAGE OF SCREEN RAM +XMAX EQU $0289 ; MAXIMUM KEYBOARD QUEUE SIZE +RPTFLG EQU $028A ; KEY REPEAT FLAG +SHFLAG EQU $028D ; SHIFT KEY FLAG +KEYLOG EQU $028F ; VECTOR TO KEY-TABLE SETUP ROUTINE +MODE EQU $0291 ; CHARSET MODE SWITCH +CINV EQU $0314 ; SYSTEM 60HZ IRQ VECTOR +CBINV EQU $0316 ; BRK INSTRUCTION VECTOR +NMINV EQU $0318 ; NMI INTERRUPT VECTOR +SPRT13 EQU $0340 +CURSOR EQU SPRT13 ; CURSOR RAM +SCREEN EQU $0400 ; SCREEN RAM +COLRAM EQU $D800 ; COLOR RAM +SPT0 EQU $07F8 + + + ; ------ + ; VIC-II + ; ------ + + ; SPRITE POSITION REGISTERS + +SP0X EQU $D000 ; SPRITE #0 X-POS +SP0Y EQU $D001 ; SPRITE #0 Y-POS + +MSIGX EQU $D010 ; HIGH BITS OF SPRITE X-POSITIONS + + ; VARIOUS CONTROL REGISTERS + +SCROLY EQU $D011 ; Y-SCROLL & VIDEO CONTROL +RASTER EQU $D012 ; RASTER COMPARE +SPENA EQU $D015 ; SPRITE ENABLE +SCROLX EQU $D016 ; X-SCROLL & VIDEO CONTROL +YXPAND EQU $D017 ; SPRITE Y-EXPANSION +VMCSB EQU $D018 ; MEMORY CONTROL +VICIRQ EQU $D019 ; CHIP INTERRUPT FLAGS +IRQMSK EQU $D01A ; IRQ MASKS +SPBGPR EQU $D01B ; SPRITE/FOREGROUND PRIORITY +SPMC EQU $D01C ; MULTICOLOR SPRITE CONTROL +XXPAND EQU $D01D ; SPRITE X-EXPANSION + + ; COLOR REGISTERS + +EXTCOL EQU $D020 ; BORDER COLOR +BGCOLO EQU $D021 ; BACKGROUND COLOR +SP0COL EQU $D027 + + + ; --- + ; SID + ; --- + + ; VOICE #1 REGISTERS + +FRELO1 EQU $D400 ; FREQ +FREHI1 EQU $D401 ; FREQ HIGH BIT +PWLO1 EQU $D402 ; PULSE WIDTH +PWHI1 EQU $D403 ; PULSE WIDTH HIGH NIBBLE +VCREG1 EQU $D404 ; CONTROL +ATDCY1 EQU $D405 ; ATTACK/DECAY +SUREL1 EQU $D406 ; SUSTAIN/RELEASE + + + ; VOICE #2 REGISTERS + +FRELO2 EQU $D407 ; FREQ +FREHI2 EQU $D408 ; FREQ HIGH BIT +PWLO2 EQU $D409 ; PULSE WIDTH +PWHI2 EQU $D40A ; PULSE WIDTH HIGH NIBBLE +VCREG2 EQU $D40B ; CONTROL +ATDCY2 EQU $D40C ; ATTACK/DECAY +SUREL2 EQU $D40D ; SUSTAIN/RELEASE + + ; VOICE #3 REGISTERS + +FRELO3 EQU $D40E ; FREQ +FREHI3 EQU $D40F ; FREQ HIGH BIT +PWLO3 EQU $D410 ; PULSE WIDTH +PWHI3 EQU $D411 ; PULSE WIDTH HIGH NIBBLE +VCREG3 EQU $D412 ; VOICE CONTROL +ATDCY3 EQU $D413 ; ATTACK/DECAY +SUREL3 EQU $D414 ; SUSTAIN/RELEASE + + ; MISCELLANEOUS REGISTERS + +CUTLO EQU $D415 ; FILTER CUTOFF, LOW BITS +CUTHI EQU $D416 ; FILTER CUTOFF, HIGH BYTE +RESON EQU $D417 ; RESONANCE CONTROL +SIGVOL EQU $D418 ; VOLUME/FILTER CONTROL +RAND EQU $D41B ; RANDOM NUMBER +CI2PRA EQU $DD00 ; DATA PORT A + + ; ------------------- + ; KERNAL JUMP VECTORS + ; ------------------- + +CHKIN EQU $FFC6 ; OPEN CHANNEL FOR INPUT +CHKOUT EQU $FFC9 ; OPEN CHANNEL FOR OUTPUT +CHRIN EQU $FFCF ; INPUT CHARACTER FROM CHANNEL +CHROUT EQU $FFD2 ; OUTPUT CHARACTER TO CHANNEL +CINT EQU $FF81 ;; INIT SCREEN EDITOR +CLALL EQU $FFE7 ; CLOSE ALL CHANNELS & FILES +CLOSE EQU $FFC3 ; CLOSE A FILE +CLRCHN EQU $FFCC ; CLEAR CHANNEL +GETIN EQU $FFE4 ; GET CHAR FROM KEYBOARD QUEUE +IOINIT EQU $FF84 ;; INIT I/O +OPEN EQU $FFC0 ; OPEN A FILE +PLOT EQU $FFF0 ; READ/SET CURSOR POSITION +RAMTAS EQU $FF87 ;; INIT RAM +READST EQU $FFB7 ; READ I/O STATUS +SCNKEY EQU $FF9F ;; SCAN KEYBOARD +SETLFS EQU $FFBA ; SET FILE ATTRIBUTES +SETMSG EQU $FF90 ;; SET KERNAL MESSAGES +SETNAM EQU $FFBD ; SET FILENAME + + END + diff --git a/64/lzip/io.asm b/64/lzip/io.asm new file mode 100644 index 0000000..84e3a67 --- /dev/null +++ b/64/lzip/io.asm @@ -0,0 +1,861 @@ + PAGE + SBTTL "--- GAME I/O: C128 ---" + +; -------------- +; INTERNAL ERROR +; -------------- +; ENTRY: ERROR CODE IN [A] +; EXIT: HA! + +ERRM: DB "Internal error " +ENUMB: DB "00. " +ERRML EQU $-ERRM + +ZERROR: LDY #1 ; CONVERT ERROR BYTE IN [A] +ZERR0: LDX #0 ; TO ASCII AT "ENUMB" +ZERR1: CMP #10 + BCC ZERR2 + SBC #10 + INX + BNE ZERR1 +ZERR2: ORA #'0' + STA ENUMB,Y + TXA + DEY + BPL ZERR0 + +; JSR ZCRLF ; CLEAR BUFFER (LC-A) + LDX #LOW ERRM + LDA #HIGH ERRM + LDY #ERRML + JSR DLINE ; PRINT ERROR MESSAGE + + ; FALL THROUGH + + +; ---- +; QUIT +; ---- + +ZQUIT: JSR ZCRLF ; FLUSH BUFFER + + LDX #LOW ENDM + LDA #HIGH ENDM + LDY #ENDML + JSR DLINE ; "END OF SESSION" + JMP DOWARM + + +; ------- +; RESTART +; ------- + +ZSTART: JSR ZCRLF ; FLUSH BUFFER +DOWARM: LDA FAST ; FAST-READ? (LC-A...) + BEQ DOW0 ; NO + JSR FOFF ; ELSE DISENGAGE + +DOW0: LDA #'1' ; NEED SIDE 1 AGAIN + STA DSIDE + LDA #1 ; SET FOR SUCCESS + STA SIDEFLG + + JSR ASKFOR1 + BCC DOW1 + JMP DSKERR ; OOPS + +DOW1: LDA ZBEGIN+ZSCRIP+1 ; SET CURRENT PRINTER STATUS + AND #%00000001 ; SO RETAINED THRU RESTART + STA SFLAG ; (...LC-A) + JMP WARM1 ; AND DO WARMSTART + +ENDM: DB "End of session." + DB EOL + DB EOL +RSTRT: DB "Press [RETURN] to restart." + DB EOL +ENDML EQU $-ENDM +RSTRTL EQU $-RSTRT + + +; -------------------------- +; RETURN TOP RAM PAGE IN [A] +; -------------------------- + +MEMTOP: LDA #PBEGIN-$10 ; FOR NOW, ASSUME LAST "BUFFER" + RTS ; OF AUX MEMORY + + +; ------------------- +; Z-PRINT A CHARACTER +; ------------------- +; ENTRY: ASCII CHAR IN [A] +; +; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, +; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN +; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME +; (DIROUT CHANGES 6/24/85) + +COUT: STA IOCHAR ; HOLD IT A SEC + LDX TABLEF ; OUTPUT TO TABLE? + BEQ COUT4 ; NO + JMP TBLRTN ; YES, DO IT (TBL ONLY 4.7.86 Le) +COUT4: LDX SCREENF ; OUTPUT TO SCREEN? + BNE COUT5 ; YES + LDX SCRIPTF ; OUTPUT TO PRINTER? + BNE COUT5 ; YES + RTS ; NO, SO DONE +COUT5: LDA IOCHAR ; RETRIEVE CHAR + LDX BUFFLG ; UNBUFFERED OUTPUT? + BNE UNBUFR ; YES, PLACE ON SCREEN IMMED. + CMP #EOL ; IF ASCII EOL, + BNE COUT0 + JMP ZCRLF ; DO IT +COUT0: CMP #SPACE ; IGNORE ALL OTHER + BCC CEX ; CONTROLS + +COUT3: LDX CHRCNT ; GET LINE POINTER + STA LBUFF,X ; ADD CHAR TO BUFFER + + LDY LENGTH ; GET LINE LENGTH COUNTER + LDA SPLITF ; (LC-A) + BNE COUT6 ; (LC-A) + CPY #XSIZE ; END OF SCREEN LINE? + BCC COUT2 + JMP FLUSH ; YES, FLUSH THE LINE + +COUT6: CPY #TOPSIZ ; TOP SCREEN 1 LARGER (LC-A) + BCS COUT2 ; (LC-A) + JMP FLUSH ; END OF LINE (LC-A) + +COUT2: INC LENGTH ; ELSE UPDATE + INC CHRCNT +CEX: RTS + + +; -------------------------- +; DIRECT, UNBUFFERED DISPLAY +; -------------------------- + +UNBUFR: STA IOCHAR ; HOLD IN CASE NEED TO PRINT + CMP #SPACE ; IGNORE CONTROLS + BCC UNBEX + + SEC + JSR PLOT + LDA SPLITF ; CHECK WHICH WINDOW + BEQ UNBBOT ; BOTTOM WINDOW + + CPY #TOPSIZ ; CHECK IF BEYOND SCREEN (40 COL TOP LC-A) + BCS UNBEX ; YES, LEAVE + CPX SLINE ; CHECK IF WITHIN WINDOW + BCS UNBEX ; NO, JUST LEAVE + BCC UNBDIS ; YES, GO DISPLAY + +UNBBOT: CPY #XSIZE ; CHECK IF BEYOND SCREEN + BCS UNBEX ; YES, LEAVE + CPX SLINE + BCC UNBEX ; NOT WITHIN WINDOW, LEAVE + +UNBDIS: LDA SCREENF ; DISPLAY TO SCREEN? + BEQ UNBPRN ; NO, CHECK IF PRINTING + LDA IOCHAR + JSR LETTER ; DO VOODOO AND DISPLAY + +UNBPRN: LDA SPLITF ; SPLIT (NON-TEXT) SCREEN + BNE UNBEX ; DON'T PRINT + + ;SEND CHAR TO PRINTER + + LDA #1 ; SET FOR PRINT RTN + STA PRLEN + LDA IOCHAR + STA LBUFF + JSR PPRINT ; AND GO ATTEMPT IT + LDA #0 ; MAKE SURE NO LEFTOVER + STA PRLEN +UNBEX: JMP NEWLOG ; AND DISCONNECT SCREEN LINES (LC-A) + + +; --------------- +; OUTPUT TO TABLE +; --------------- + +TBLRTN: TAX ; HOLD CHAR A SEC. + + ;PUT BYTE IN TABLE AT CURRENT OFFSET + + LDA DIRITM+LO ; ADD IN OFFSET + CLC + ADC DIRTBL+LO + STA I+LO + LDA DIRITM+HI + ADC DIRTBL+HI + STA I+HI + LDY #0 + TXA ; PICK UP ASCII CHAR + STA (I),Y ; STORE IT IN TBL @ BYTE ALIGNED @ + +;SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER + + INC DIRITM+LO ; INC OFFSET TO NEXT BYTE + BNE TBLRTS + INC DIRITM+HI +TBLRTS: RTS + + +; ------------------- +; FLUSH OUTPUT BUFFER +; ------------------- +; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: LDA #SPACE ; SPACE + STX OLDEND ; SAVE CURRENT END OF LINE +FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR + BEQ FL1 ; IN THE LINE + DEX + BNE FL0 ; IF NONE FOUND, + LDX #XSIZE ; FLUSH ENTIRE LINE + LDA SPLITF ; (LC-A) + BEQ FL1 ; (LC-A) + LDX #TOPSIZ ; TOP SCREEN 40 COL! (LC-A) +FL1: STX OLDLEN ; SAVE OLD LINE POS HERE + STX CHRCNT ; MAKE IT THE NEW LINE LENGTH + JSR ZCRLF ; PRINT LINE UP TO LAST SPACE + +; START NEW LINE WITH REMAINDER OF OLD + + LDX OLDLEN ; GET OLD LINE POS + LDY #0 ; START NEW LINE AT BEGINNING +FL2: INX + CPX OLDEND ; CONTINUE IF + BCC FL3 ; INSIDE OR + BEQ FL3 ; AT END OF LINE + STY LENGTH ; ELSE SET NEW LINE LENGTH + STY CHRCNT + RTS +FL3: LDA LBUFF,X ; GET CHAR FROM OLD LINE + STA LBUFF,Y ; MOVE TO START OF NEW LINE + INY ; UPDATE LENGTH OF NEW LINE + BNE FL2 ; (ALWAYS) + + +; --------------- +; CARRIAGE RETURN +; --------------- + +ZCRLF: LDX CHRCNT + LDA SPLITF + BEQ ZC0 ; SCROLLING SCREEN + + ; SCREEN 1 (TOP) + CPX #TOPSIZ ; 40 COL WIDE HERE (LC-A) + BCS ZC1 ; LET OS PUT IN +ZC0: LDA #EOL ; ELSE PUT IT IN + STA LBUFF,X ; TO END LINE + INC CHRCNT ; UPDATE LINE LENGTH + +ZC1: LDA SCREENF ; CHECK IF DISPLAYING TO SCREEN + BEQ CR1 ; NO, GO HANDLE IF PRINTING + LDA SPLITF ; IN TOP SCREEN? + BNE ZCRLF0 ; YES + INC LINCNT ; NEW LINE GOING OUT +ZCRLF0: LDX LINCNT ; IS IT TIME TO + INX ; (A LINE FOR "MORE") + CPX LMAX ; PRINT "MORE" YET? + BCC CR1 ; NO, CONTINUE + + ; SCREEN FULL; PRINT "MORE" + + LDA #0 + STA LINCNT ; RESET LINE COUNTER + STA COLOR ; PRINT "MORE" IN BLACK + STA NDX ; CLEAR QUEUE + + SEC + JSR PLOT ; GET CURSOR POSITION + STY OLDX + STX OLDY + + LDX #LOW MORE + LDA #HIGH MORE + LDY #MOREL + JSR DLINE ; PRINT "MORE" DIRECTLY + +ZCR0: JSR GETIN ; GET ANY KEYPRESS + TAX + BEQ ZCR0 + + LDY OLDX + LDX OLDY + CLC + JSR PLOT ; RESTORE CURSOR + + LDA #1 + STA COLOR ; SWITCH BACK TO WHITE + + LDX #LOW MCLR + LDA #HIGH MCLR + LDY #MOREL + JSR DLINE ; RUB OUT "MORE" + + LDY OLDX + LDX OLDY + CLC + JSR PLOT ; RESTORE CURSOR AGAIN + +CR1: JSR LINOUT ; DISPLAY LINE + LDA #0 + STA LENGTH ; AND RESET LINE COUNT + STA CHRCNT + RTS + + +LINOUT: LDY CHRCNT ; IF BUFFER EMPTY, + BEQ LINEX ; DON'T PRINT ANYTHING + STY PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + LDA SCREENF ; DISPLAY TO SCREEN? + BEQ LOUT1 ; NO, GO CHECK IF PRINT + +LOUT2: LDX #0 ; SEND CONTENTS OF [LBUFF] +LOUT: LDA LBUFF,X ; TO SCREEN + JSR CHAR + INX + DEY + BNE LOUT + +LOUT1: LDA SPLITF ; DON'T PRINT IF SPLIT (NON-TEXT) SCREEN (EZIP) + BNE LINEX + JSR PPRINT ; PRINT [LBUFF] IF ENABLED +LINEX: RTS ; AND RETURN + + +; ---------------------- +; UPDATE THE STATUS LINE +; ---------------------- +; NOT APPLICABLE IN EZIP. +ZUSL: RTS + + +; ------ +; BUFOUT +; ------ +; INPUT: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE +; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO + +ZBUFOUT: LDX ARG1+LO + BNE ZBUF1 ; SET TO BUFFERED OUTPUT + JSR LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) + + LDX #0 + STX CHRCNT + INX + STX BUFFLG ; SET FUTURE OUTPUT TO BE UNBUFFERED + RTS +ZBUF1: DEX + BNE ZBUFEX ; INVALID + STX BUFFLG ; SET TO BUFFERED +ZBUFEX: RTS + + +; ------ +; DIROUT +; ------ +; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT +; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT +; MULTIPLE DEVICE USAGE IS POSSIBLE. + +ZDIRT: LDX ARG1+LO + BMI DIRRES ; NEGATIVE VALUE, DESELECTING + DEX + BEQ DIR1 ; 1 = SET OUTPUT TO SCREEN + DEX + BEQ DIR2 ; 2 = SCRIPTING + DEX + BEQ DIR3 ; 3 = TABLE + DEX + BEQ DIR4 ; 4 = RECORDING DEVICE (NOT IMPLEMENTED) +DIR4: RTS ; INVALID VALUE +DIRRES: INX + BEQ DRES1 ; -1 = RESET TO SCREEN + INX + BEQ DRES2 + INX + BEQ DRES3 + INX + BEQ DRES4 +DRES4: RTS ; INVALID VALUE, JUST LEAVE + +DIR1: INX ; 1, TURN SCREEN OUTPUT ON + STX SCREENF + RTS + +DRES1: STX SCREENF ; 0, TURN SCREEN OFF + RTS + +DIR2: INX + STX SCRIPTF ; SET SCRIPT FLAG ON + LDA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO + ORA #%00000001 + STA ZBEGIN+ZSCRIP+1 + RTS ; YES, READY TO LEAVE + +DRES2: STX SCRIPTF ; TURN PRINTER OFF + LDA ZBEGIN+ZSCRIP+1 ; AND TURN OFF GAME FLAG TOO + AND #%11111110 + STA ZBEGIN+ZSCRIP+1 + RTS + +DIR3: INX + STX TABLEF ; TURN TABLE OUTPUT FLAG ON + LDA ARG2+HI ; SET UP TBL + CLC + ADC ZCODE + LDX ARG2+LO ; TO STORE CHARS IN + STX DIRTBL+LO + STA DIRTBL+HI + LDA #2 + STA DIRITM+LO + LDA #0 + STA DIRITM+HI + RTS + +DRES3: LDA TABLEF ; IF OFF ALREADY (LZIP) + BEQ OUT3 ; LEAVE AS IS (LZIP) + + STX TABLEF ; TURN TBL OUTPUT OFF + LDA DIRITM+LO ; MARK END OF CHARS IN TBL + CLC ; WITH A NULL CHAR + ADC DIRTBL+LO + STA I+LO + LDA DIRITM+HI + ADC DIRTBL+HI + STA I+HI ; ALIGNED AT EOL + LDA #0 + TAY + STA (I),Y ; PLACE 0 IN TBL + LDY #1 ; GET CHAR COUNT + LDA DIRITM+LO ; (2 LESS THAN [DIRITM]) + SEC + SBC #2 + STA (DIRTBL),Y + BCS RESET0 + DEC DIRITM+HI +RESET0: LDA DIRITM+HI + DEY + STA (DIRTBL),Y ; STORE CHAR COUNT IN TBL + LDA #0 ; CLEAR COUNT FOR NEXT TIME + STA DIRFLG ; SET OUTPUT TO SCREEN +OUT3: RTS + + +; ------ +; CURSET +; ------ +; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW +; AND AT COLUMN (ARG2) + +ZCURST: LDA ZBEGIN+ZMODE + AND #%00010000 + BEQ ZCUREX ; NOT ENABLED + LDA SPLITF + BEQ ZCUREX ; OOPS, IN SCROLLING TOP + LDA BUFFLG + BEQ ZCUREX ; OOPS, UNBUFFERED + + LDX ARG1+LO ; GET LINE + DEX ; ZERO ALIGN IT + LDY ARG2+LO ; GET COLUMN + DEY ; ZERO ALIGN IT + CLC + JSR PLOT ; MOVE THE CURSOR +ZCUREX: RTS + + +; -------------- +; CURGET & DIRIN +; -------------- +; NOT YET IMPLEMENTED, BUT RESERVED + +ZCURGT: +ZDIRIN: RTS + + +; ------ +; HLIGHT +; ------ + +ZLIGHT: LDA ZBEGIN+ZMODE ; CHECK IF ENABLED + AND #%00001010 + BEQ ZLEX ; NOPE + + LDX ARG1+LO ; GET CHOICE OF MODE + BNE ZL1 + + LDA #146 ; REVERSE OFF + JSR HLIGHT + LDA #130 ; UNDERLINE OFF + JMP HLIGHT +ZLEX: RTS + +ZL1: CPX #1 ; INVERSE? + BNE ZL2 + + LDA #$12 ; INVERSE + JMP HLIGHT + +ZL2: CPX #4 ; UNDERLINE? + BNE ZLEX ; NO OTHER ON C128 + + LDA #$02 ; UNDERLINE + +HLIGHT: STA IOCHAR ; HOLD COMMAND CHAR + LDA SCREENF ; IF NOT PRINTING TO + BNE DOLIGHT ; SCREEN OR PRINTER, SKIP THIS + LDA SCRIPTF + BNE DOLIGHT + RTS +DOLIGHT: LDA IOCHAR + LDX BUFFLG + BEQ BUFFD + JMP CHROUT ; UNBUFFERED, CHANGE IMMEDIATELY + +BUFFD: LDX CHRCNT ; BUFFERED, PLACE + STA LBUFF,X ; DISPLAY BUFFER + INC CHRCNT ; INC CHRCNT BUT NOT! LINE LENGTH + RTS + + +; ----- +; ERASE +; ----- + +ZERASE: LDA ZBEGIN+ZMODE ; ENABLED? + AND #%00010000 + BEQ ZEROUT ; NO + LDA ARG1+LO + CMP #1 + BNE ZEROUT ; INVALID + + SEC ; CLEAR TO END OF LINE + JSR PLOT + STX OLDX + STY OLDY + +ZERLP: INY + CPY #XSIZE ; WHOLE LINE DONE? + BCS ZERDUN + LDA #SPACE + JSR CHROUT + JMP ZERLP + +ZERDUN: LDX SPLITF ; ONE MORE FOR TOP SCREEN (LC-A) + BEQ ZERDUN1 ; (LC-A) + LDA #SPACE ; (LC-A) + JSR CHROUT ; (LC-A) +ZERDUN1:LDX OLDX ; RESET CURSOR + LDY OLDY + CLC + JSR PLOT + JMP NEWLOG ; MAKE SURE LINES UNCONNECTED (LC-A) +ZEROUT: RTS + + +; ----- +; CLEAR +; ----- + +ZCLR: LDA ZBEGIN+ZMODE + AND #%00000001 + BEQ ZEROUT ; NOT ENABLED + LDA ARG1+LO ; CHECK WHAT TO DO + BEQ CLR0 ; BOTTOM SCREEN + CMP #1 + BEQ CLR1 ; TOP SCREEN + CMP #$FF + BNE ZEROUT ; INVALID + +; UNSPLIT SCREEN & CLEAR IT + + JSR NORL ; RESET TO FULL + JMP CLS ; & CLEAR IT + +CLR0: ; CLEAR BOTTOM SCREEN + + LDX SLINE + LDA LOLINE,X + TAY ; LOW OFFSET IN Y + LDA HILINE,X + STA I+HI + SEC + SBC #HIGH SCREEN ; GET OFFSET INTO + CLC ; COLOR RAM + ADC #HIGH COLRAM + STA J+HI + + LDA #0 + STA I+LO + STA J+LO + STA SPENA ; KILL CURSOR + + LDA #YSIZE + SEC + SBC SLINE + STA K ; K = # LINES TO CLEAR + + LDX #XSIZE + JSR CLRSCR ; GO CLEAR BOTTOM SCREEN + LDX #YSIZE ; PLACE CURSOR AT BOTTOM OF SCREEN + JMP DOSCRN + +CLR1: LDA #HIGH SCREEN ; START AT TOP + STA I+HI + LDA #HIGH COLRAM + STA J+HI + LDY #0 ; Y = OFFSET + STY I+LO + STY J+LO + STY SPENA ; KILL CURSOR + + LDA SLINE + STA K ; K = #LINES TO CLEAR + + LDX #TOPSIZ + JSR CLRSCR + LDX SLINE + JMP DOSCRN + + ; ENTER: [Y] SET TO STARTING PAGE OFFSET + (KEEPS TRACK OF PAGE BOUNDARIES) + +CLRSCR: STX L ; X TO KEEP TRACK OF WHERE ARE IN LINE + +ALOOP: LDA #SPACE ; CLR LINE + STA (I),Y + LDA #1 ; WHITE BACKGRND + STA (J),Y + DEX + BNE CLROK + DEC K + BEQ CLRDUN + + LDX L +CLROK: INY + BNE ALOOP + INC I+HI ; NEXT PAGE + INC J+HI + BNE ALOOP ; JMP + +CLRDUN: RTS + + +; ----- +; INPUT +; ----- + +ZINPUT: LDA ARG1+LO + CMP #1 ; KEYBOARD? + BEQ ZINP7 + JMP RET0 ; NO, INVALID + +ZINP7: LDX #0 + STX LINCNT ; RESET LINE COUNT + STX LENGTH ; SET LINE COUNT TO 0 + STX CHRCNT + STX NDX ; CLEAR INPUT QUEUE + INX + STX SPENA ; TURN CURSOR DMA ON (1) + + DEC NARGS + BNE ZINP8 + JMP ZINP3 ; NO TIME LIMIT + +ZINP8: LDA ARG2+LO ; GET DELAY WANTED + STA I+HI + LDA #0 ; SET FCN IF IS ONE + STA J+HI + STA J+LO + DEC NARGS + BEQ ZINP4 ; NO FCN + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI + +ZINP4: JSR CURSON ; INIT CURSOR (LC-A) + JSR TIMEIN ; GO GET A KEY WITHIN TIME DELAY + BCC ZINP5 ; OK, RETURN IT TO GAME + JMP RET0 ; OOPS + +ZINP3: JSR GETKEY ; OK, FIND WHICH CHAR WAS PRESSED + +ZINP5: ;CHECK FOR "ARROWS", CONVERT FOR USE (EZIP) + + LDX #ENDKEY ; GET LENGTH OF LIST +MASK0: CMP HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + BEQ MASK1 ; FOUND IT + DEX + BPL MASK0 ; CHECK THEM ALL + BMI MASK2 ; NOT FOUND, OK +MASK1: LDA WANT,X ; GET KEY TO USE INSTEAD + +MASK2: LDX #0 + JMP PUTBYT ; RETURN CHAR +ZINPEX: JMP RET0 ; OOPS + +HAVE: DB $14,$11,$1D,$91,$5E,$9D ; BACKSP,DOWN,RIGHT,UP,UP,LEFT ARROWS +WANT: DB 08,13,07,14,14,11 +ENDKEY EQU $-WANT-1 + + + ; GET A KEY WITHIN A TIME FRAME + +TIMEIN: LDA I+HI + STA I+LO ; RESET EA TIME THRU + +TIME1: LDA #249 ; = 7, TIME COUNTS UP + STA TIME +TIME2: LDA TIME + BNE TIME2 + + JSR GETIN ; GET A KEY + CMP #0 + BEQ TIME3 ; NO KEY YET + JSR GOTKEY + JMP TGOOD ; [A] NOW HAS PROPER CODE + +TIME3: INC BLINK+LO ; TIME TO BLINK YET? + BNE NOBLNK ; NOT TILL BOTH BLINK TIMERS + INC BLINK+HI ; ARE ZERO + BNE NOBLNK + + LDA #CYCLE ; RESET MSB OF BLINK COUNTER + STA BLINK+HI ; FOR SHORT BLINK INTERVAL + + LDA CURSOR ; FLIP THE CURSOR + EOR #$FF ; SHAPE + STA CURSOR ; AND UPDATE IT + +NOBLNK: DEC I+LO + BNE TIME1 ; SOME TIME LEFT, TRY AGAIN + + ; TIME OUT, CHECK IF THERE IS A FCN TO CALL + + LDA J+LO ; FCN IN J IF THERE IS ONE + ORA J+HI + BEQ TBAD ; NO FCN, SEND 0 FOR FAILED + JSR INTCLL ; INTERNAL CALL + LDA VALUE+LO ; GET RESULTS + BEQ TIMEIN ; TRY AGAIN + +TBAD: SEC + RTS ; ABORT +TGOOD: CLC + RTS + + + +INTCLL: LDA #HIGH ZIRET ; SET ZRETURN TO RETURN HERE + STA PATCHI+HI + LDA #LOW ZIRET + STA PATCHI+LO + LDA I+HI ; SAVE VALUES FOR CALLING RTN + PHA + LDA J+HI + PHA + LDA J+LO + PHA + LDX OLDZSP+LO ; STUFF TAKEN FROM CALL. + LDA OLDZSP+HI + JSR PUSHXA + LDA ZPCL + JSR PUSHXA + LDX ZPCM + LDA ZPCH + JSR PUSHXA + +; FORM QUAD ALIGNED ADDR FROM [ARG3] + + LDA #0 + ASL J+LO ; *4 + ROL J+HI + ROL A + STA ZPCH + ASL J+LO + ROL J+HI + ROL ZPCH + LDA J+HI ; PICK UP NEW LOW BYTES + STA ZPCM + LDA J+LO + STA ZPCL + JSR VLDZPC + JSR NEXTPC ; FETCH # LOCALS TO PASS + STA J+LO ; SAVE HERE FOR COUNTING + STA J+HI ; AND HERE FOR LATER REFERENCE + BEQ INT2 ; SKIP IF NO LOCALS + LDA #0 + STA I+LO ; ELSE INIT STORAGE INDEX +INT1: LDY I+LO + LDX LOCALS+LO,Y ; GET LSB OF LOCAL INTO [X] + LDA LOCALS+HI,Y ; AND MSB INTO [A] + 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 INT1 ; YES, KEEP LOOPING +INT2: LDX J+HI ; # OF LOCALS + TXA + JSR PUSHXA + LDA ZSP+LO + STA OLDZSP+LO + LDA ZSP+HI + STA OLDZSP+HI + JMP MLOOP ; GO DO FCN + + ; RETURN FROM FCN WILL COME HERE + +ZIRET: LDA #HIGH PUTVAL ; REPAIR ZRETURN + STA PATCHI+HI + LDA #LOW PUTVAL + STA PATCHI+LO + PLA ; GET RID OF RTS FROM ZRET + PLA + PLA ; RESTORE FOR CALLING RTN + STA J+LO + PLA + STA J+HI + PLA + STA I+HI + RTS ; GO BACK TO CALLER + + +IN: DB 00,00,00,00,00,00,00,00,00 +OUT: DB 00,00,00,00,00,00,00,00,00 + +QUOT: DB 00,00 ; RDTBL1+4 ; (WORD) QUOTIENT FOR DIVISION +REMAIN: DB 00,00 ; QUOT+2 ; (WORD) REMAINDER FOR DIVISION +MTEMP: DB 00,00 ; REMAIN+2 ; (WORD) MATH TEMPORARY REGISTER +QSIGN: DB 00 ; MTEMP+2 ; (BYTE) SIGN OF QUOTIENT +RSIGN: DB 00 ; QSIGN+1 ; (BYTE) SIGN OF REMAINDER +DIGITS: DB 00 ; RSIGN+1 ; (BYTE) DIGIT COUNT FOR "PRINTN" +BLINK: DB 00,00 ; (WORD) COUNT CYCLE BETWEEN CURSOR BLINKS +ULINE: DB 00 ; (BYTE) UNDERLINE VALUE FOR CURSOR + +XEXIST: DB 00 ; (BYTE) FLAG = IF THERE IS 256K EXPANSION RAM + ; (0 = NO, 1 = YES) +RESFLG: DB 00 ; (0 = NO, 1 = YES) FLAG FOR XRAM LOAD + + +MORE: DB "[MORE]" +MOREL EQU $-MORE +MCLR: DB " " + + END diff --git a/64/lzip/lzip.asm b/64/lzip/lzip.asm new file mode 100644 index 0000000..cca38eb --- /dev/null +++ b/64/lzip/lzip.asm @@ -0,0 +1,101 @@ + + + TITLE "LOWER CASE EZIP/6502 INFOCOM, INC. --- EQUATES" + + ; -------------------------- + ; LOWER CASE EZIP/6502 VERSION A + ; Z-CODE INTERPRETER PROGRAM + ; FOR COMMODORE 64 + ; -------------------------- + + ; INFOCOM, INC. + ; 125 CAMBRIDGEPARK DRIVE + ; CAMBRIDGE, MA 02140 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + +MSTART EQU $800 ; START OF FREE PROGRAM RAM +ZEROPG EQU $03 ; START OF FREE Z-PAGE RAM +ZPGTOP EQU $8F ; END OF FREE Z-PAGE RAM + +DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER (1=YES,0=NO) +TESTING EQU 1 ; ASS. FLG FOR TESTING MSG + + + ; CHANGES FOR LOWER CASE + ; + ; - SCREEN CONTROLS ADAPTED FROM C64 ZIP + ; - GETBYT, NEXTPC, GETDSK SET TO USE MEMORY ARRANGEMENT OF + ; $800 = BUFFERS, FOLLOWED BY LCEZIP, THEN GAME PRELOAD + ; UP TO $CFFF (GIVING A PRELOAD SIZE LIMIT OF 38K) + ; AND SWITCHING OUT KERNAL FROM $E000-$FFFF TO USE THE + ; RAM UNDERNEATH FOR PAGING, SO ALL MEMORY USE IN THE 3 + ; MENTIONED RTNS CHECKS FOR START OF PAGING, ALL OTHER MEMORY + ; ACCESS (AS BEFORE) ASSUMES DIRECT ACCESS ALLOWED. + ; - "PLOT" GIVES Y = WIDTH, X = LENGTH C-64 & LC-A USE + ; X = WIDTH, Y = LENGTH + + + ; ----------- + ; 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 -- PRELOAD/IMPURE TOO LARGE + ; 14 -- DRIVE ACCESS + ; 15 -- Z-STACK DESTROYED + ; 16 -- NOT AN EZIP GAME + + ; NOTE: DISK ACCESS IS SET SO THAT SIDE 1 STARTS ON TRACK 3 + ; SIDE 2 ON TRACK 1 AND SAVES STARTING ON TRACK 1. THIS IS IN + ; THE CODE IN ZDOS.ASM (APPEARS NOWHERE ELSE 3/18/86 LE) + + INCLUD SHAKE.ASM + INCLUD EQ.ASM + + TITLE "LC EZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT INIT" + INCLUD HARDEQ.ASM + INCLUD COLD.ASM + + TITLE "LC EZIP/6502 INFOCOM, INC. --- INIT & MAINLINE" + INCLUD WARM.ASM + INCLUD MAIN.ASM + INCLUD SUBS.ASM + INCLUD DISPATCH.ASM + + TITLE "LC EZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS" + INCLUD OPS012.ASM + INCLUD OPSX.ASM + INCLUD READ.ASM + + TITLE "LC EZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT" + INCLUD XPAGING.ASM + INCLUD ZSTRING.ASM + INCLUD OBJECTS.ASM + + TITLE "LC EZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT I/O" + + INCLUD IO.ASM + INCLUD MACHINE.ASM + INCLUD ZDOS.ASM + INCLUD DISK.ASM + INCLUD FAST.ASM + + IF DEBUG + INCLUD BUGGER.ASM + ENDIF + + END + diff --git a/64/lzip/machine.asm b/64/lzip/machine.asm new file mode 100644 index 0000000..c9f0755 --- /dev/null +++ b/64/lzip/machine.asm @@ -0,0 +1,696 @@ + + PAGE + SBTTL "--- MACHINE-DEPENDENT I/O: CBM64 ---" + + ; ---------------------------- + ; FETCH ASCII KEYCODE INTO [A] + ; ---------------------------- + + ; EXIT: ASCII IN [A] & [IOCHAR] + +CYCLE EQU $E0 ; SHORT BLINK CYCLE + + ; FIRST INITIALIZE THE CURSOR + +CURSON: LDX #$FF + STX CURSOR ; FORCE THE CURSOR "ON" + INX ; = 0 + STX BLINK+LO ; RESET THE BLINK COUNTER + STX BLINK+HI ; FOR A LONG DELAY + + SEC ; GET CURSOR POSITION + JSR PLOT ; [Y]=XPOS, [X]=YPOS + + TXA ; CALC SPRITE Y-POS + ASL A + ASL A + ASL A + CLC + ADC #57 + STA SP0Y + + TYA ; GET X-POS INTO [A] + CMP #40 ; STRIP OFF + BCC NOLOG ; LOGICAL LINE OFFSET + SBC #40 + +NOLOG: LDX #0 + CMP #29 ; IF X-POS < 29 + BCC CURX ; MSB OF SPRITE POS IS ZERO + INX ; ELSE SET BIT 0 +CURX: STX MSIGX ; OF X-POS MSB + + ASL A ; CALC LSB OF SPRITE X-POS + ASL A + ASL A + CLC + ADC #24 + STA SP0X + RTS + + + ; AND THE RTN TO GET A PROPER KEY + +GETKEY: JSR CURSON ; INIT CURSOR +GETK1: JSR GETIN ; GET A KEY + TAX ; SAVE HERE + + INC BLINK+LO ; TIME TO BLINK YET? + BNE NOBLIN ; NOT TILL BOTH BLINK TIMERS + INC BLINK+HI ; ARE ZERO + BNE NOBLIN + + LDA #CYCLE ; RESET MSB OF BLINK COUNTER + STA BLINK+HI ; FOR SHORT BLINK INTERVAL + + LDA CURSOR ; FLIP THE CURSOR + EOR #$FF ; SHAPE + STA CURSOR ; AND UPDATE IT + +NOBLIN: TXA ; KEY BEING PRESSED? + BEQ GETK1 ; NOT IF CODE WAS ZERO + + ; CONVERT & MASK KEYCODE IN [A] + +GOTKEY: ; ENTRY POINT FROM INPUT + + CMP #'A' ; CONVERT UNSHIFTED ALPHA + BCC MASK ; TO ASCII LOWER CASE + CMP #'Z'+1 + BCS MASK + ADC #$20 + JMP TICK ; SKIP REST OF MALARKY (LC-A) + +MASK: LDX #GLISTL ; PASS ON ANY GOOD KEYS (LC-A) +GOODL: CMP GOODLST,X ; LOCATED IN BAD RANGE (LC-A) + BEQ TICK ; (LC-A) + DEX ; (LC-A) + BPL GOODL ; (LC-A) + + AND #%01111111 ; SCREEN OUT SHIFTS + + CMP #SPACE ; ANYTHING ELSE < "SPACE" + BCC BADKEY ; IS BAD + + LDX #BLISTL ; IGNORE OBSTINATE NON ALLOWED KEYS +BADL: CMP BADLIST,X + BEQ BADKEY + DEX + BPL BADL + + CMP #'z'+1 ; PASS L-C ALPHA + BCS BADKEY + CMP #'a' + BCS TICK + + CMP #'Z'+1 ; PASS U-C ALPHA + BCC TICK ; AND OTHER ASCII CHARS + +BADKEY: JSR BOOP ; REJECT BAD KEYPRESS + JMP GETK1 ; AND TRY AGAIN + + ; "CLICK" THE KEY (LC-A = JUST LEAVE I HATE CLICKING) + +TICK: STA IOCHAR ;HOLD ON TO IT + ADC RAND ;FUTZ WITH RANDOM + STA RAND + EOR RASTER + STA RASTER + LDA IOCHAR ; GET CHAR INTO [A] + RTS ; AND RETURN IT + + + +GOODLST: DB EOL,BACKSP,$11,$1D,$91,$5E,$9D ; DOWN,RIGHT,UP,UP,LEFT ARROWS +GLISTL EQU $-GOODLST-1 + +BADLIST: DB '%','&','+','=','@','<','>' +BLISTL EQU $-BADLIST-1 + + ; ------------------------- + ; OUTPUT AN ASCII CHARACTER + ; ------------------------- + +LETTER: CMP #'a' ; LOWER-CASE? + BCC LET0 ; NO, CONTINUE + CMP #'z'+1 + BCS LETEX ; CTRL CHARS + AND #%01011111 ; ELSE MASK FOR LOWER-CASE + JMP CHROUT + +LET0: CMP #'A' ; UPPER-CASE? + BCC LETEX + CMP #'Z'+1 + BCS LETEX + ORA #%00100000 ; MAKE UPPER +LETEX: JMP CHROUT + + + ; ----------------- + ; PRINT CHAR IN [A] + ; ----------------- + +CHAR: STA IOCHAR ; SAVE HERE + TXA ; SAVE [X] AND [Y] + PHA + TYA + PHA + + SEC ; GET CURSOR X- AND Y-POS + JSR PLOT ; INTO [Y] AND [X], RESPECTIVELY + TYA + CMP #40 ; STRIP OFF THE + BCC CHKEOL ; LOGICAL LINE OFFSET + SBC #40 ; UPDATE [Y] IF NECESSARY + TAY + +CHKEOL: LDA IOCHAR ; RESTORE CHAR + CMP #EOL ; IS IT EOL? + BEQ OUTEOL ; YES, SPECIAL HANDLING + + ; HANDLE A NON-EOL CHAR + + CPX #YSIZE-1 ; ON LAST SCREEN LINE? + BCC NOSCRL ; NO, NO SCROLL NEEDED + CPY #XSIZE ; LAST CHAR ON LINE? + BCC NOSCRL ; NO, DON'T SCROLL + + ; SCROLL THE SCREEN (BOTTOM SCREEN ONLY) + +DOSCRL: DEX ; PUSH CURSOR UP ONE LINE + CLC + JSR PLOT ; RESET THE CURSOR + + 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] = XSIZE + +SRL2: LDX #XSIZE + LDA #SPACE +SRL3: STA SCREEN+960,X ; CLEAR LAST LINE + DEX ; OF SCREEN RAM + BPL SRL3 + +NOSCRL: LDA IOCHAR ; RESTORE CHAR + CMP #$22 + BNE NOQUOT + JSR LETTER ; QUOTE MARKS SCREW + LDA #0 ; UP SYSTEM, SO + STA QUOTMOD ; TURN OFF QUOTE MODE FLAG + JMP CHDUN + +NOQUOT: JSR LETTER ; OFF TO THE SCREEN! +CHDUN: PLA ; RESTORE [X] AND [Y] + TAY + PLA + TAX + RTS + + + + + + + ; HANDLE EOL + +OUTEOL: CPX #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] + LDX #0 ; RESET LINE COUNT + STX LENGTH + STX CHRCNT + STX LINCNT ; RESET LINE COUNT + STX NDX ; CLEAR INPUT QUEUE + INX ; = 1 + STX SPENA ; ENABLE CURSOR DMA + + DEC NARGS ; CHECK IF TIME LIMIT (EZIP) + DEC NARGS + BEQ INP2 ; NO + LDA ARG3+LO ; GET DELAY WANTED + STA I+HI + LDA #0 + STA J+HI + STA J+LO + DEC NARGS ; IS THERE A FCN? + BEQ INP4 ; NO + LDA ARG4+LO ; YES, SET IT + STA J+LO + LDA ARG4+HI + STA J+HI + +INP4: JSR CURSON ; INIT CURSOR + JSR TIMEIN ; AND GET A KEY WITHIN TIME LIMIT + BCC INP5 + JMP LEXBAD ; ELSE ABORT + +INP5: LDY #0 + STY CHARCNT + BEQ INLP1 ; (JMP) [A] NOW HAS A CHAR + +INP2: LDY #0 ; AND CHAR COUNT + STY CHARCNT + +INLOOP: JSR GETKEY ; GET ASCII INTO [A] AND [IOCHAR] +INLP1: CMP #UP + BEQ CBAD ; CLEAR OFF ARROWS (EZIP) + CMP #$5E ; UP + BEQ CBAD + CMP #DOWN + BEQ CBAD + CMP #LEFT + BEQ CBAD + CMP #RIGHT + BEQ CBAD + CMP #EOL ; EOL? + BEQ ENDLIN ; LINE DONE IF SO + CMP #BACKSP ; BACKSPACE? + BEQ BACKUP ; SPECIAL HANDLING + + LDY CHARCNT + STA LBUFF,Y ; ELSE ADD CHAR TO INPUT BUFFER + INC CHARCNT ; NEXT POSITION IN LINE +SHOWIT: JSR CHAR ; SEND TO SCREEN + LDY CHARCNT + CPY #77 ; ALL THE CHARS ALLOWED? + 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 BEEP ; ELSE COMPLAIN + JMP NOMORE ; AND INSIST + + ; HANDLE BACKSPACE + +BACKUP: DEC CHARCNT ; BACK UP THE POINTER + BPL SHOWIT ; JMP + LDY #0 ; RESET POINTER + STY CHARCNT +CBAD: JSR BEEP ; ELSE SCREAM WITH PAIN + JMP INLOOP ; AND WAIT FOR SOMETHING BETTER + + ; HANDLE END OF LINE + +ENDLIN: LDY CHARCNT + STA LBUFF,Y ; SHIP EOL TO BUFFER + INY ; UPDATE INDEX + STY LINLEN ; SAVE HERE FOR "READ" + STY PRLEN ; AND HERE FOR "PPRINT" + + LDX #0 + STX SPENA ; DISABLE CURSOR DMA + 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 #'A' ; IF CHAR IS ALPHA, + BCC LEX2 ; CONVERT TO LOWER CASE + CMP #'Z'+1 + BCS LEX2 + ADC #$20 +LEX2: STA (RDTBL1),Y ; MOVE CHAR TO INPUT BUFFER AT [ARG1] + DEY ; LOOP TILL + BNE LEX0 ; ALL CHARS MOVED + JSR PPRINT ; SCRIPT [LBUFF] IF ENABLED + LDA LINLEN ; RESTORE # CHARS + RTS ; INTO [A] +LEXBAD: LDA #0 ; TIME OUT OCCURRED (EZIP) + RTS ; ZERO CHARS OBTAINED + +CHARCNT: DB 0 + +; ----------------------- +; 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] + ; NOW WITH IMPROVED ERROR PROTECTION! (BM 11/24/84) + +SFLAG: DB 0 ; FOR RESTART + +PPRINT: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? + BEQ PEX ; NO, SCRAM IMMEDIATELY + + LDA ZBEGIN+ZSCRIP+1 ; CHECK SCRIPT FLAG + AND #%00000001 ; SCRIPTING ON? + BEQ PP3 ; NO, CHECK FOR "UNSCRIPT" + + LDA PSTAT ; CHECK PRINTER STATUS + BMI PEX ; CAN'T OPEN IF NEGATIVE + BNE PP1 ; ALREADY OPEN, SCRIPT THE LINE + + ; OPEN THE PRINTER FOR OUTPUT + + LDA FAST ; FAST-READ? (LC-A) + BEQ PP0 ; NO (LC-A) + JSR FOFF ; ELSE DISENGAGE (LC-A) + LDA #8 ; & RESET DRIVE (LC-A) + JSR DOPEN ; (LC-A) + +PP0: LDX #0 ; (LC-A) + STX FAST ; BYE FAST DRIVE! (LC-A) + + LDX #1 + STX PSTAT ; SET STATUS TO "PRINTER OPENED" (1) + + LDA #4 ; LOGICAL FILE #4 + TAX ; DEVICE #4 + LDY #7 ; ALLOW UPPER/LOWER CASE + JSR SETLFS ; SET UP LOGICAL FILE + LDA #0 + JSR SETNAM ; NO FILENAME REQUIRED + JSR OPEN ; OPEN THE CHANNEL + BCC PP1 ; OPEN OKAY IF CARRY CLEAR + +PPERR: LDA #$FF ; ELSE SET PRINTER STATUS + STA PSTAT ; TO "CAN'T OPEN" + BNE PP5 ; AND SIMULATE AN "UNSCRIPT" + +PP1: LDX #4 ; SET PRINTER CHANNEL + JSR CHKOUT ; TO "OUTPUT" + + LDY #0 ; INIT INDEX +PP2: LDA LBUFF,Y + CMP #$0D + BEQ PP6 + AND #%01111111 + CMP #$20 + BCC PP4 ; NO CONTROLS +PP6: JSR LETTER + BCS PPERR ; ERROR IF CARRY SET +PP4: INY + DEC PRLEN + BNE PP2 + BEQ PEX ; RESET & RETURN + + ; CHECK FOR "UNSCRIPT" + +PP3: LDA PSTAT ; CHECK PRINTER STATUS + BEQ PEX ; EXIT IF PRINTER WAS OFF + BMI PEX ; OR UNOPENABLE + +PCLOSE: LDA #0 ; RESET PRINTER STATUS FLAG + STA PSTAT ; TO "CLOSED" + + ; ENTRY FOR PRINTER ERROR + +PP5: LDA #4 + JSR CLOSE ; CLOSE THE PRINTER CHANNEL + + LDA FAST ; (LC-A) + BEQ PEX ; (LC-A) + LDA #8 ; (LC-A) + JSR DOPEN ; (LC-A) + JMP FINIT ; (LC-A) +PEX: JMP CLRCHN + + + ; ------------ + ; SPLIT SCREEN + ; ------------ + + ; SPLIT SCREEN AT LINE [ARG1] + ; DISABLE SPLIT IF [ARG1] = 0 + ; IGNORE IF SPLIT ALREADY ENABLED OR [ARG1] >= 23 + + ; ON C-128, I AM USING KERNAL RTNS TO ACCESS SCREEN MEMORY + ; AS SCREEN MEMORY IS IN ITS OWN WORLD. IN ORDER NOT TO + ; SCROLL THE TOP WINDOW WHEN SCREEN IS SPLIT, THE C-128 + ; TOP OF SCREEN INDICATOR MUST BE USED, BUT: NO ACCESS IS + ; ALLOWED ABOVE THAT INDICATOR. THAT INDICATOR (WTOP) WILL + ; THEREFORE BE SET ONLY WHEN SCROLLING MIGHT OCCUR, LEAVING + ; [WTOP] SET TO #0 OTHERWISE. THE SPLIT LINE IS KEPT TRACK + ; OF IN [TOP]. + +ZSPLIT: LDA ZBEGIN+ZMODE + AND #%00100000 ;CHECK IF ENABLED (EZIP) + BEQ ZSPOUT ;NOT, LEAVE + LDX ARG1+LO ;GET # OF LINES FOR SCREEN + BEQ NORL ;IF 0 THEN RESTORE SCREEN + CPX #24 ;IS SPLIT REALLY = WHOLE SCREEN + BCS ZSPOUT ;YES, IGNORE + + STX SLINE ; SET THE TOP OF THE SECOND SCREEN + STX SPSTAT ; NON ZERO = SCREEN IS SPLIT + CPX LINCNT ; IS SCROLLING SCREEN NOW LESS THAN LINCNT? + BCC ZSPL3 ; NO + STX LINCNT ; YES + +ZSPL3: LDA #YSIZE-1 ; CALCULATE # LINES TO SCROLL + SEC ; BEFORE "MORE" APPEARS: + SBC SLINE ; LMAX = YSIZE-SLINE-1 + STA LMAX + DEC LMAX + +ZSPOUT: RTS + + ; -------------------- + ; DISABLE SPLIT SCREEN + ; -------------------- + +NORL: JSR TOBOT + +SPLOFF: LDX #0 + STX SLINE ; SPLIT AT LINE 1 + STX SPSTAT ; TURN OFF STATUS FLAG + STX LINCNT ; RESET LINE COUNT + LDA #24 + STA LMAX ; SET MAXIMUM LINE SCROLL + RTS + + +; ------ +; SCREEN +; ------ +; GO TO TOP WINDOW (TOP OF SCREEN) IF [A] = 1 +; GO TO BOTTOM OF SCREEN IF [A] = 0 +; IGNORE IF SPLIT NOT ENABLED OR [A] <> 0 OR 1 +; FLAG SPLITF WILL BE SET FOR OUTPUT TO DETERMINE +; IF AND WHICH WINDOW TO DISPLAY TO +; (0=BOTTOM 1=TOP) + +ZSCRN: LDA ZBEGIN+ZMODE + AND #%00000001 ; CHECK IF ENABLED (EZIP) + BEQ ZSPOUT ; NOT, LEAVE + LDA SPSTAT ; CHECK IF SCREEN IS SPLIT + BEQ ZSPOUT ; NO, SO JUST LEAVE + + LDA ARG1+LO ; CHECK WHICH WINDOW + BNE SCRN1 ; TOP SCREEN + LDA #$FF ; SCROLLING SCREEN SO + STA SCRIPT ; ALLOW SCRIPTING + + LDA #0 + STA SPLITF ; SET FLAG TO SPLIT SCREEN (0) +TOBOT: JSR ZSPL3 + LDX #23 ; BOTTOM OF SCREEN + JMP DOSCRN ; JMP TO RTN + +SCRN1: CMP #01 + BNE ZSPOUT ; INVALID SCREEN ID + + STA SPLITF ; SET FLAG TO UNSCROLLING SCREEN (1) + LDA #0 + STA SCRIPT ; SET SCRIPTNG OFF, NOT ALLOWED THIS SCREEN + +TOTOP: LDX #24 + STX LMAX + LDX #0 ; TOP, NON SCROLLING SCREEN + +DOSCRN: LDY #0 + STY LINCNT + CLC + JSR PLOT ; SET CURSOR (+ LEAVE) + JMP NEWLOG + + + ; ----- + ; SOUND + ; ----- + ; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID + ; (EZIP) + +ZSOUND: LDA ZBEGIN+ZMODE + AND #%00100000 + BEQ ZSOEX ; NOT ENABLED + LDX ARG1+LO ; GET SOUND WANTED + DEX + BNE ZSO1 + JMP BEEP +ZSO1: DEX + BEQ BOOP +ZSOEX: RTS ; INVALID + +BOOP: LDA #96 ; FREQ LSB + STA FRELO1 + LDA #22 ; MSB + STA FREHI1 + LDA #$F2 + STA TIME + JMP SOUND + +BEEP: LDA #60 ; FREQ LSB + STA FRELO1 + LDA #50 ; MSB + STA FREHI1 + LDA #$FC + STA TIME + +SOUND: LDA #%11110000 + STA SUREL1 ; FULL SUSTAIN + LDA #%10001111 + STA SIGVOL ; FULL VOLUME + LDA #%01000001 + STA VCREG1 ; START PULSE + +RAZZ: LDA TIME + BNE RAZZ + + STA VCREG1 ; STOP PULSE + LDA #%10000000 + STA SIGVOL ; VOLUME OFF + RTS + + +; -------------------------------- +; RETURN RANDOM BYTES IN [A] & [X] +; -------------------------------- + +RANDOM: INC RAND ; RANDOM FROM APPLE (11/4/86 LD) + DEC RASTER + LDA RAND + ADC RNUM1 + TAX + LDA RASTER + SBC RNUM2 + STA RNUM1 + STX RNUM2 + RTS + + + ; ------------------------ + ; CLEAR SCREEN & COLOR RAM + ; ------------------------ + + +CLS: LDA #HIGH SCREEN ; POINT [I] TO + STA I+HI ; SCREEN RAM + LDA #HIGH COLRAM ; POINT [J] TO + STA J+HI ; COLOR RAM + + LDY #0 ; RESET PAGE INDEX + STY I+LO ; BOTH RAMS START + STY J+LO ; ON PAGE BOUNDARIES + STY SPENA ; MAKE SURE CURSOR IS DEAD! + + LDX #4 ; CLEAR 4 PAGES +CLS0: LDA #SPACE ; SPACE CHAR + STA (I),Y ; FOR SCREEN + LDA #1 ; "WHITE" CODE + STA (J),Y ; FOR COLOR RAM + INY + BNE CLS0 + INC I+HI ; POINT TO + INC J+HI ; NEXT PAGE + DEX ; 4 PAGES DONE? + BNE CLS0 ; LOOP TILL EMPTY + + LDA #13 ; RESET THE + STA SPT0 ; SPRITE RAM POINTER + + JSR TOTOP ; SET CURSOR TO (0,1) + JSR SPLOFF ; DISABLE SPLIT SCREEN + + SEI + LDA #LOW DORTI ; POINT THE SYSTEM NMI VECTOR + STA NMINV+LO ; TO A SIMPLE "RTI" INSTRUCTION + LDA #HIGH DORTI ; TO DISABLE THE STOP/RESTORE EXIT + STA NMINV+HI + CLI + + ; FALL THROUGH ... + + ; ---------------------------- + ; RESET THE LOGICAL LINE TABLE + ; ---------------------------- + +NEWLOG: LDX #24 +NLG0: LDA HILINE,X ; GET MSB OF LINE ADDRESS + ORA #%10000000 ; SET THE HIGH BIT + STA LDTB1,X ; STORE IN THE LINE TABLE + DEX + BPL NLG0 + RTS + +DORTI: RTI ; RTI INSTRUCTION FOR NMI + + ; ------------------- + ; LINE ADDRESS TABLES + ; ------------------- + +LOLINE: DB $00,$28,$50,$78,$A0,$C8,$F0,$18 + DB $40,$68,$90,$B8,$E0,$08,$30,$58 + DB $80,$A8,$D0,$F8,$20,$48,$70,$98 + DB $C0 + +HILINE: DB $04,$04,$04,$04,$04,$04,$04,$05 + DB $05,$05,$05,$05,$05,$06,$06,$06 + DB $06,$06,$06,$06,$07,$07,$07,$07 + DB $07 + + END diff --git a/64/lzip/main.asm b/64/lzip/main.asm new file mode 100644 index 0000000..09485e1 --- /dev/null +++ b/64/lzip/main.asm @@ -0,0 +1,261 @@ + PAGE + SBTTL "--- MAIN LOOP ---" + +MLOOP: LDA #0 + STA NARGS ; RESET # ARGUMENTS + JSR NEXTPC + STA OPCODE ; SAVE IT HERE + + IF DEBUG + LDA ZPCPNT+HI + STA BONE + LDA ZPCPNT+LO + STA BTWO + LDA MPCPNT+HI + STA BTHREE + LDA MPCPNT+LO + STA BFOUR + LDA #0 ; BREAKPOINT #0 + JSR DOBUG + LDA OPCODE + TAY + ENDIF + + ; DECODE AN OPCODE + + 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: CMP #236 ; XCALL? + BEQ OPXCLL ; YES, PROCESS SEPARATELY + 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: AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPTXL,Y + STA GOX+1+LO + LDA OPTXH,Y + STA GOX+1+HI +GOX: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #1 -- ILLEGAL X-OP *** + +BADOPX: LDA #1 + JMP ZERROR + + ; HANDLE AN XCALL OPCODE + +OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + STA ABYTE + JSR NEXTPC + STA BBYTE + LDA ABYTE ; ONE TO START WITH + LDX #0 + STX ADEX ; INIT ARGUMENT INDEX + BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP +XCALL1: LDA ABYTE ; GET ARG BYTE + ASL A ; SHIFT NEXT 2 BITS + ASL A ; INTO BITS 7 & 6 + STA ABYTE ; HOLD FOR LATER +XCALL2: AND #%11000000 ; MASK OUT GARBAGE + BNE XCALL3 + JSR GETLNG ; 00 = LONG IMMEDIATE + JMP XCNXT +XCALL3: CMP #%01000000 ; SHORT IMMED? + BNE XCALL4 ; NO, TRY ANOTHER + JSR GETSHT ; 01 = SHORT IMMED. + JMP XCNXT +XCALL4: CMP #%10000000 ; LAST TEST + BNE OPX4 ; 11 = NO MORE ARGS + JSR GETVAR ; 10 = VARIABLE +XCNXT: LDX ADEX + LDA VALUE+LO + STA ARG1+LO,X + LDA VALUE+HI + STA ARG1+HI,X + INC NARGS + INX + INX + STX ADEX + CPX #16 + BEQ OPX4 ; DONE, GO DO IT + CPX #8 ; DONE 1ST MODE BYTE? + BNE XCALL1 ; NOT QUITE YET + LDA BBYTE ; SET UP FOR NEXT + STA ABYTE ; MODE BYTE + JMP XCALL2 ; GO DO IT + + + +; ------------- +; HANDLE A 0-OP +; ------------- + +OP0: AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT0L,Y + STA GO0+1+LO + LDA OPT0H,Y + STA GO0+1+HI +GO0: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #2 -- ILLEGAL 0-OP *** + +BADOP0: LDA #2 + JMP ZERROR + + + +; ------------- +; HANDLE A 1-OP +; ------------- + +OP1: AND #%00110000 ; ISOLATE ARGUMENT BITS + BNE OP1A + + ;JSR GETLNG ; 00 = LONG IMMEDIATE + + JSR NEXTPC + JMP OP1A1 +OP1A: AND #%00100000 ; TEST AGAIN + BNE OP1B + + ;JSR GETSHT ; 01 = SHORT IMMEDIATE + +OP1A1: STA ARG1+HI + JSR NEXTPC + STA ARG1+LO + INC NARGS + JMP OP1EX1 +OP1B: JSR GETVAR ; 10 = VARIABLE +OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] +OP1EX1: LDA OPCODE + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT1L,Y + STA GO1+1+LO + LDA OPT1H,Y + STA GO1+1+HI +GO1: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 + + STA ARG1+HI + JSR NEXTPC + STA ARG1+LO + INC NARGS + JMP OP2B1 +OP2A: JSR GETVAR ; 1 = VARIABLE +OP2B: JSR V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] +OP2B1: LDA OPCODE ; RESTORE OPCODE BYTE + AND #%00100000 ; ISOLATE 2ND ARG BIT + BNE OP2C + + ;JSR GETSHT ; 0 = SHORT IMMEDIATE + + STA ARG2+HI + JSR NEXTPC + STA ARG2+LO + JMP OP2D1 +OP2C: JSR GETVAR ; 1 = VARIABLE +OP2D: LDA VALUE+LO ; MOVE 2ND [VALUE] + STA ARG2+LO ; INTO [ARG2] + LDA VALUE+HI + STA ARG2+HI +OP2D1: INC NARGS ; UPDATE ARGUMENT COUNT + + ; EXECUTE A 2-OP OR EXTENDED 2-OP + +OP2EX: LDA OPCODE + AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT2L,Y + STA GO2+1+LO + LDA OPT2H,Y + STA GO2+1+HI +GO2: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 diff --git a/64/lzip/objects.asm b/64/lzip/objects.asm new file mode 100644 index 0000000..db68095 --- /dev/null +++ b/64/lzip/objects.asm @@ -0,0 +1,198 @@ + PAGE + SBTTL "--- OBJECT & PROPERTY HANDLERS ---" + + +; ******************************************** +; AN ASSUMPTION HAS BEEN MADE WITH EZIP OBJECT +; HANDLING. THAT IS THAT ALL THIS STUFF IS +; BEFORE PURBOT AND IS IN MAIN MEMORY +; AND THEREFORE DIRECT ACCESSING IS JUST FINE +; LINDE +; ******************************************** +; ---------------------------------- +; GET ABSOLUTE ADDRESS OF OBJECT [A] +; ---------------------------------- +; ENTER: OBJECT IN A/X (LO/HI) +; EXIT: ADDRESS IN [I] +; (EZIP VERSION) + +OBJLOC: STX I+HI ; SAVE MSB FOR SHIFTING + ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) + STA I+LO + ROL I+HI + LDX I+HI + ASL A + ROL I+HI ; *4 + ASL A + ROL I+HI ; *8 + ASL A + ROL I+HI ; *16 + SEC + SBC I+LO ; -(*2) + STA I+LO ; SO IS *14 TOTAL + LDA I+HI + STX I+HI + SBC I+HI + STA I+HI + LDA I+LO + CLC + ADC #112 ; ADD OBJECT TABLE OFFSET + BCC OBJ3 + INC I+HI +OBJ3: 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC + LDY #12 ; (EZIP) + 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 #%00111111 ; MASK OUT LENGTH BITS (EZIP) + RTS + + +; ------------------------------- +; FETCH # BYTES IN PROPERTY VALUE +; ------------------------------- +; ENTRY: LIKE "PROPB" EXIT +; (EZIP) + +PROPL: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + RTS + +SHORT: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE + LDA #2 ; BIT 6 = 1, LENGTH =2 + RTS +ONE: LDA #1 ; BIT 6 = 0, LENGTH =1 + RTS + + +; ---------------------- +; POINT TO NEXT PROPERTY +; ---------------------- +; ENTRY: LIKE "PROPB" EXIT + +PROPNX: JSR PROPL ; GET LENGTH OF CURRENT PROP + TAX ; SAVE HERE +PPX: INY ; LOOP UNTIL + BNE PPY + INC I+LO + BNE PPY + INC I+HI +PPY: DEX ; [Y] POINTS TO + BNE PPX ; START OF NEXT PROP + INY ; CORRECT ALIGNMENT + RTS + + +; ----------------------------------------- +; CALL PROPNX, THEN ALIGN [I] AT THAT ENTRY +; ----------------------------------------- +; EXIT: [I] IS ALIGNED AT CURRENT PROPERTY +; [Y] IS ZEROED +; (EZIP) + +NEXTPI: JSR PROPNX ; GET ALIGNMENT OF NEXT PROPERTY INTO [Y] + TYA ; ADD OFFSET TO NEXT PROP + CLC ; TO [I] SO I POINTS DIRECTLY + ADC I+LO ; AT IT + STA I+LO + BCC NXTPI1 + INC I+HI ; ADD IN CARRY +NXTPI1: LDY #0 ; CLEAR [Y] AS IT IS USED AS AN INDEX + 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 ; (EZIP) + LDX ARG1+HI + 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 + CMP #$10 ; CHECK IF IN 2ND WORD + BCC FLS ; YES, GO ALIGN FOR THAT + SBC #16 ; ELSE ALIGN TO 3RD WORD + TAX + LDA I+LO + CLC + ADC #4 ; 3RD FLAG WORD + STA I+LO + BCC FLS0 + INC I+HI + JMP FLS0 ; (END EZIP CHGS) +FLS: 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 diff --git a/64/lzip/ops012.asm b/64/lzip/ops012.asm new file mode 100644 index 0000000..56e4ead --- /dev/null +++ b/64/lzip/ops012.asm @@ -0,0 +1,1168 @@ + 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: LDX #5 ;MOVE ZPC INTO MPC +ZPRI1: + LDA ZPC,X + STA MPC,X + DEX + BPL ZPRI1 ;NO NEED TO VALIDATE AS ZPC WAS VALID ANYWAY + JSR PZSTR ; PRINT THE Z-STRING AT [MPC] + LDX #5 ; COPY STATE OF [MPC] +ZPRI2: LDA MPC,X ; INTO [ZPC] + STA ZPC,X + DEX + BPL ZPRI2 + 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 ZCRLF ; DISPLAY VERSION NUMBER, GET SIDE 1 + LDX #3 + LDA #0 +ZVR: STA K+LO,X ; CLEAR [K], [L] + 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 ZBEGIN+ZLENTH ; GET MSB + STA I+HI ; AND + LDA ZBEGIN+ZLENTH+1 ; LSB OF Z-CODE LENGTH IN BYTES + ASL A ; MULTIPLY BY + ROL I+HI ; FOUR + ROL K+LO + ASL A + STA I+LO + ROL I+HI ; TO GET # BYTES + ROL K+LO ; IN GAME + LDA #0 ; START AT BEGINNING + STA DBLOCK+LO + STA DBLOCK+HI + JMP READIN ; READ FIRST BLOCK IN + +VSUM: LDA MPCL ; NEW PAGE? + BNE VSUM2 ; NO, CONTINUE +READIN: LDA #HIGH IOBUFF ; FAKE READ OUT SO + STA DBUFF+HI ; IT DOESN'T MOVE BUFFER + JSR GETDSK ; GO READ A PAGE + BCC VSUM2 + JMP DSKERR ; BAD DISK!!!!! + +VSUM2: LDY MPCL ; GET THIS BYTE + LDA IOBUFF,Y + INC MPCL ; SET FOR NEXT BYTE + BNE VSUM3 + INC MPCM + BNE VSUM3 + INC MPCH +VSUM3: CLC + ADC L+LO ; ADD IT TO SUM + STA L+LO ; IN [J] + BCC VSUM1 + INC L+HI +VSUM1: LDA MPCL ; END OF Z-CODE YET? + CMP I+LO ; CHECK LSB + BNE VSUM + LDA MPCM ; MIDDLE BYTE + CMP I+HI + BNE VSUM + LDA MPCH ; AND HIGH BIT + CMP K+LO + BNE VSUM + + LDA ZBEGIN+ZCHKSM+1 ; GET LSB OF CHECKSUM + CMP L+LO ; DOES IT MATCH? + BNE BADVER ; NO, PREDICATE FAILS + LDA ZBEGIN+ZCHKSM ; ELSE CHECK MSB + CMP L+HI ; LOOK GOOD? + BNE BADVER ; IF MATCHED, + JMP PREDS ; GAME IS OKAY +BADVER: JMP PREDF + + + + 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC ; GET OBJECT ADDR INTO [I] + LDY #8 ; POINT TO "NEXT" SLOT (EZIP) + BNE FIRST1 ; JMP + + +; ------ +; FIRST? +; ------ +; RETURN "FIRST" POINTER IN OBJECT [ARG1] ; +; FAIL IF LAST AND RETURN ZERO +; (EZIP ALTERATIONS) + +ZFIRST: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET OBJECT ADDR INTO [I] + LDY #10 ; POINT TO "FIRST" SLOT +FIRST1: LDA (I),Y ; GET CONTENTS OF SLOT + TAX + INY + LDA (I),Y ; INTO A,X + JSR PUTBYT ; PASS IT TO VARIABLE + LDA VALUE+LO ; EXAMINE THE VALUE JUST "PUT" + BNE PFINE + LDA VALUE+HI + BEQ PYUCK ; FAIL IF IT WAS ZERO +PFINE: JMP PREDS ; ELSE REJOICE + + +; --- +; LOC +; --- +; RETURN THE OBJECT CONTAINING OBJECT [ARG1] ; +; RETURN ZERO IF NONE +; (EZIP ALTERED) + +ZLOC: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + LDY #6 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET THE WORD + TAX + INY + LDA (I),Y + 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 + LDA (I),Y ; OF PROPERTY AT [I] INTO [A] + BMI PTZ2 ; BIT 7 = 1, LENGTH LOW 2 BYTES + AND #%01000000 + BEQ PTZ1 ; BIT 6 = 0, LENGTH = 1 + LDA #2 ; BIT 6 = 1, LENGTH = 2 + BNE PTZ3 ; JMP +PTZ1: LDA #1 + BNE PTZ3 ; JMP +PTZ2: AND #%00111111 ; SIZE > 2 +PTZ3: LDX #0 ; CLEAR FOR PUTBYT + JMP PUTBYT + + +; --- +; INC +; --- +; INCREMENT VARIABLE [ARG1] + +ZINC: LDA ARG1+LO + JSR VARGET ; FETCH VARIABLE INTO [VALUE] + INC VALUE+LO + BNE ZINC1 + INC VALUE+HI +ZINC1: JMP ZD0 + + +; --- +; DEC +; --- +; DECREMENT VARIABLE [ARG1] + +ZDEC: LDA ARG1+LO + JSR VARGET ; FETCH VAR INTO [VALUE] + LDA VALUE+LO + SEC + SBC #1 + STA VALUE+LO + LDA VALUE+HI + SBC #0 + STA VALUE+HI +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 +; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO +; 2) MOVES AND COMPARES 2 BYTES) + +ZREMOV: LDA ARG1+LO ; GET SOURCE OBJECT ADDR + LDX ARG1+HI + 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 #7 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET THE DATA + STA K ; HOLD IT + DEY + LDA (I),Y + TAX ; X = HI + LDA K ; A = LO + ORA (I),Y ; COMPARE BYTES + BEQ REMVEX ; SCRAM IF NO OBJECT + LDA K ; PICK UP, DESTROYED BY ORA + JSR OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [I] + LDY #10 ; POINT TO "FIRST" SLOT + LDA (I),Y ; GRAB DATA + TAX + INY + LDA (I),Y ; A=LO, X=HI + CMP ARG1+LO ; IS THIS THE FIRST? + BNE REMVC1 ; NO, KEEP SEARCHING + CPX ARG1+HI ; HM? + BNE REMVC1 + LDY #8 ; ELSE COPY SOURCE'S "NEXT" SLOT + LDA (J),Y + INY ; INTO DEST'S "FIRST" SLOT ([Y] = 10) + INY + STA (I),Y + DEY ; BACK UP TO GET HIGH BYTE + LDA (J),Y + INY + INY + STA (I),Y + BNE REMVC2 ; BRANCH ALWAYS +REMVC1: JSR OBJLOC + LDY #8 ; GET "NEXT" + LDA (I),Y + TAX + INY + LDA (I),Y + CMP ARG1+LO ; FOUND IT? + BNE REMVC1 ; NO, KEEP TRYING + CPX ARG1+HI + BNE REMVC1 + LDY #8 ; WHEN FOUND + LDA (J),Y ; MOVE "NEXT" SLOT OF SOURCE (THIS OBJECT) + STA (I),Y ; TO "NEXT" SLOT OF DEST + ;(OBJECT THAT REFERENCED THIS ONE) + INY + LDA (J),Y + STA (I),Y +REMVC2: LDA #0 + LDY #6 ; CLEAR "LOC" + STA (J),Y + INY + STA (J),Y + INY ; AND "NEXT" SLOTS ([Y] = 5) + STA (J),Y ; OF SOURCE OBJECT (ARG1) + INY + STA (J),Y +REMVEX: RTS + + +; ------ +; PRINTD +; ------ +; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + +ZPRD: LDA ARG1+LO + LDX ARG1+HI ; (EZIP) + + ; ENTRY POINT FOR "USL" + +PRNTDC: JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + LDY #12 ; GET PROP TABLE POINTER (EZIP) + 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+LO ; RE-SYNC THE + STA ZSP+LO ; Z-STACK POINTER + LDA OLDZSP+HI + STA ZSP+HI + 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 + + ;EZIP STX OLDZSP + + STA ZPCL + JSR POPVAL + STX OLDZSP+LO + STA OLDZSP+HI + JSR VLDZPC ;MAKE VALID + JSR A12VAL ; MOVE [ARG1] TO [VALUE] +PATCHI EQU $+1 ; FOR ZINPUT RTN (IF A FCN CALL) (EZIP) + 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 (QUAD) 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 + + + + PAGE + SBTTL "--- 2-OPS ---" + + +; ----- +; LESS? +; ----- +; [ARG1] HIGH [ARG2]? + +ZLESS: JSR A12VAL ; MOVE [ARG1] TO [VALUE] + JMP DLS0 ; MOVE [ARG2] TO [I] & COMPARE + + +; ------ +; DLESS? +; ------ +; DECREMENT [ARG1] ; SUCCEED IF HIGH [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] LOW [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 + + +; ----------------- +; SIGNED COMPARISON +; ----------------- +; ENTRY: VALUES IN [VALUE] AND [I] + +COMPAR: LDA I+HI + EOR VALUE+HI + BPL SCMP + LDA I+HI + CMP VALUE+HI + BCC PGOOD + JMP PREDF + +SCMP: LDA VALUE+HI + CMP I+HI + BNE SCEX + LDA VALUE+LO + CMP I+LO +SCEX: BCC PGOOD + JMP PREDF + + +; --- +; IN? +; --- +; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? + +ZIN: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [I] + LDY #6 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET DATA + CMP ARG2+HI ; IS IT THERE? + BNE PBAD ; NO + INY + LDA (I),Y + CMP ARG2+LO + 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 [ARG2] SET IN OBJECT [ARG1]? + +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] +; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + +ZMOVE: JSR ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS + + ; NOW, IF IT IS ANYWHERE + + LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET SOURCE OBJECT ADDR INTO [I] + LDA I+LO ; COPY SOURCE (ARG1) ADDRESS + STA J+LO ; INTO [J] + LDA I+HI + STA J+HI + LDA ARG2+HI ; GET DEST OBJECT ID + LDY #6 ; POINT TO "LOC" SLOT OF SOURCE + STA (I),Y ; AND MOVE IT IN + TAX ; (MOVE ARG2 INTO PARENT SLOT OF ARG1) + LDA ARG2+LO + INY + STA (I),Y ; X/A (HI/LO) SET FOR OBJLOC + JSR OBJLOC ; GET ADDR OF DEST OBJECT INTO [I] (GET PARENT) + + ; NOW SWAP IN NEW VALUE + + LDY #10 ; POINT TO "FIRST" SLOT + LDA (I),Y ; OF PARENT (ARG2) + STA K+HI ; SAVE HERE FOR A MOMENT + LDA ARG1+HI ; GET SOURCE OBJECT ID + STA (I),Y ; MAKE IT "FIRST" OF PARENT + INY + LDA (I),Y + TAX + LDA ARG1+LO + STA (I),Y + TXA + ORA K+HI ; CHECK OLD "FIRST" OF DEST/PARENT + BEQ ZMVEX ; SCRAM IF ZERO + TXA ; GET LO BYTE AGAIN + LDY #9 ; MAKE OLD "FIRST" OF PARENT + STA (J),Y ; THE "NEXT" (SIBLING) OF THIS OBJECT (ARG1) + DEY ; I.E. ADD THIS ONE AT THE TOP OF LIST + LDA K+HI ; & GET HIGH BYTE + STA (J),Y +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 + LDA #0 + 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 + ADC #0 ; PICK UP CARRY FROM MPCM + STA MPCH ; TO GET TOP BIT + JMP VLDMPC + + +; ---- +; GETP +; ---- +; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 + +ZGETP: JSR PROPB +GETP1: JSR PROPN ; GET ADDR OF PROP TBL + CMP ARG2+LO ; GET PROP ID + BEQ GETP3 ; FOUND IT + BCC GETP2 ; NOT THERE + JSR NEXTPI ; GET NEXT PROP, ALIGN [I] TO IT (EZIP) + JMP GETP1 ; TRY AGAIN WITH NEXT PROP + + ; PROPERTY NOT THERE, GET DEFAULT + +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 ; GET LENGTH OF PROP INTO [A] + INY ; MAKE [Y] POINT TO 1ST BYTE OF PROP + CMP #1 ; IF LENGTH =1 + BEQ GETPB ; GET A BYTE PROPERTY + CMP #2 ; IF LENGTH = 2 + 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 + + IF 0 + +; ----- +; GETPT +; ----- +; RETURN POINTER TO PROP TABLE [ARG2] +; IN OBJECT [ARG1] + +ZGETPT: JSR PROPB ; GET ADDR OF PROP TBL +GETPT1: JSR PROPN ; RETURNS OFFSET IN [Y] + CMP ARG2+LO ; CHECK ID + BEQ GETPT2 + BCC DORET ; BEYOND IT, SO NOT THERE + JSR NEXTPI ; GET NEXT PROPERTY, ALIGN [I] TO IT (EZIP) + JMP GETPT1 +GETPT2: JSR PROPL ; ALIGN Y @ LAST SIZE BYTE (EZIP) + INY ; INC TO POINT AT PROPERTY VALUE (EZIP) + +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 + + ENDIF + +; ----- +; GETPT +; ----- +; RETURN POINTER TO PROP TABLE [ARG2] +; IN OBJECT [ARG1] + +ZGETPT: LDA ARG1+LO + LDX ARG1+HI ; (EZIP) + JSR OBJLOC + LDY #12 ; (EZIP) + 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 + +GETPT1: LDA (I),Y + AND #%00111111 ; MASK OUT LENGTH BITS (EZIP) + + CMP ARG2+LO ; CHECK ID + BEQ GETPT2 + BCS DDD + JMP DORET ; BEYOND IT, SO NOT THERE + +DDD: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT0 ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + JMP AAA + +SHORT0: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE0 + LDA #2 ; BIT 6 = 1, LENGTH =2 + JMP AAA +ONE0: LDA #1 ; BIT 6 = 0, LENGTH =1 + +AAA: TAX ; SAVE HERE +PPPX: INY ; LOOP UNTIL + BNE PPPY + INC I+HI +PPPY: DEX ; [Y] POINTS TO + BNE PPPX ; START OF NEXT PROP + INY ; CORRECT ALIGNMENT + TYA ; ADD OFFSET TO NEXT PROP + CLC ; TO [I] SO I POINTS DIRECTLY + ADC I+LO ; AT IT + STA I+LO + BCC CCCC1 + INC I+HI ; ADD IN CARRY +CCCC1: LDY #0 ; CLEAR [Y] AS IT IS USED AS AN INDEX + + JMP GETPT1 + +GETPT2: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT1 ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + JMP BBB + +SHORT1: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE1 + LDA #2 ; BIT 6 = 1, LENGTH =2 + JMP BBB +ONE1: LDA #1 ; BIT 6 = 0, LENGTH =1 + +BBB: INY ; INC TO POINT AT PROPERTY VALUE (EZIP) +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 [AR +; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO + +ZNEXTP: JSR PROPB ; ALIGN [I] AT PROPERTY TBL'S 1ST ENTRY + 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 NEXTPI ; ELSE TRY NEXT PROPERTY (EZIP) + JMP NXTP1 +NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +NXTP3: JSR PROPN ; GET THE PROPERTY # + LDX #0 ; FOR PUTBYT (EZIP) + 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 diff --git a/64/lzip/opsx.asm b/64/lzip/opsx.asm new file mode 100644 index 0000000..3f2f46f --- /dev/null +++ b/64/lzip/opsx.asm @@ -0,0 +1,442 @@ + 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!) + + +; ------------------- +; XCALL, CALL1, CALL2 +; ------------------- + +ZXCALL: ; DROP THROUGH +ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +ZCALL2: + + +; ---- +; CALL +; ---- +; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +; ([ARG5]-[ARG8] FOR XCALL (EZIP)) + +ZCALL: LDA ARG1+LO + ORA ARG1+HI ; IS CALL ADDRESS ZERO? + BNE DOCALL ; NO, CONTINUE + LDX #0 + JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER + LDA OLDZSP+HI + JSR PUSHXA + LDA ZPCL ; AND LSB OF [ZPC] + JSR PUSHXA ; ON THE Z-STACK ([X] NOT USED HERE - EZIP) + 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 + ASL ARG1+LO ; MULTIPLY [ARG1] + ROL ARG1+HI ; (BY 2) + ROL A ; HIGH BIT INTO [A] + STA ZPCH ; NEW HIGH BIT OF [ZPC] + ASL ARG1+LO ; BY 4 (EZIP) + ROL ARG1+HI + ROL ZPCH + LDA ARG1+HI ; GET NEW LOW BYTES + STA ZPCM + LDA ARG1+LO + STA ZPCL + JSR VLDZPC + JSR NEXTPC ; FETCH # LOCALS TO PASS + STA J+LO ; SAVE HERE FOR COUNTING + STA J+HI ; AND HERE FOR LATER REFERENCE + BEQ ZCLL2 ; SKIP IF NO LOCALS + LDA #0 + STA I+LO ; ELSE INIT STORAGE INDEX +ZCLL1: LDY I+LO + LDX LOCALS+LO,Y ; GET LSB OF LOCAL INTO [X] + LDA LOCALS+HI,Y ; AND MSB INTO [A] + 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 ZCLL1 ; YES, KEEP LOOPING + + ; MOVE UP TO 3 ARGUMENTS TO [LOCALS] ( 7 FOR XCALL (EZIP)) + +ZCLL2: 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 + DEC NARGS ; MORE (THAT MEANS IT'S AN XCALL) + BEQ ZCALL3 ; NO, JUST A CALL + LDA ARG5+LO ; MOVE [ARG5] TO LOCAL #4 + STA LOCALS+LO+6 + LDA ARG5+HI + STA LOCALS+HI+6 + DEC NARGS ; MORE? + BEQ ZCALL3 ; NO + LDA ARG6+LO ; MOVE [ARG6] TO LOCAL #5 + STA LOCALS+LO+8 + LDA ARG6+HI + STA LOCALS+HI+8 + DEC NARGS ; MORE? + BEQ ZCALL3 ; NO + LDA ARG7+LO ; MOVE [ARG7] TO LOCAL #6 + STA LOCALS+LO+10 + LDA ARG7+HI + STA LOCALS+HI+10 + DEC NARGS ; MORE? + BEQ ZCALL3 ; NO + LDA ARG8+LO ; MOVE [ARG8] TO LOCAL #7 + STA LOCALS+LO+12 + LDA ARG8+HI + STA LOCALS+HI+12 +ZCALL3: LDX J+HI ; RETRIEVE # LOCALS + TXA ; DUPE FOR NO GOOD REASON + JSR PUSHXA ; PUSH # LOCALS ONTO Z-STACK + LDA ZSP+HI ; REMEMBER WHERE + STA OLDZSP+HI ; WE CAME FROM + LDA ZSP+LO + STA OLDZSP+LO + 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 ; GET PROP TBL ADDR + +PUTP1: JSR PROPN ; GET ID + CMP ARG2+LO + BEQ PUTP2 + BCC PNERR ; ERROR IF LOWER + JSR NEXTPI ; TRY NEXT PROPERTY, ALIGN [I] AT IT (EZIP) + JMP PUTP1 +PUTP2: JSR PROPL ; GET PROPERTY LENGTH INTO [A] + INY ; MAKE [Y] POINT TO 1ST PROPERTY BYTE + CMP #1 ; IF LENGTH = 1 + BEQ PUTP3 ; PUT A BYTE + CMP #2 ; PUT A WORD IF [A] = 2 + 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 DB II 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 DB II + 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 ; IF VALUE IS ZERO + ORA ARG1+HI + BNE ZRAND1 + STA SRHOLD+LO ; RETURN TO RANDOM RANDOM + STA SRHOLD+HI ; CLEAR INDICATOR + JMP RET0 ; AND RETURN THRU HERE SO ALIGNED +ZRAND1: LDA SRHOLD+LO ; ARE WE NONRAMDOM INCREMENTING? (EZIP) + ORA SRHOLD+HI + BNE ZRAND3 ; YUP + LDA ARG1+HI + BPL ZRAND2 ; GENERATE A RANDOM # + EOR #$FF ; SET UP TO INCREMENT FROM 1 THRU INT + STA SRHOLD+HI ; GET ABSOLUTE + LDA ARG1+LO + EOR #$FF + STA SRHOLD+LO + INC SRHOLD+LO + LDA #0 ; W/ NO RAMDOMNESS + STA RAND1+LO + STA RAND1+HI + BEQ ZRAND3 ; JMP (END EZIP) +ZRAND2: 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 + CLC + ADC #1 ; ADD 1 + STA VALUE+LO ; INTO [VALUE] + LDA REMAIN+HI + ADC #0 + STA VALUE+HI + JMP PUTVAL ; AND RETURN RESULT + + ; NON RANDOM INCREMENTING + +ZRAND3: LDA SRHOLD+HI ; RESET TOP OF COUNT IF NECESSARY + CMP ARG1+HI ; SO ALWAYS W/IN RANGE OF CALL + BCC ZRAND7 + BNE ZRAND6 + LDA ARG1+LO + CMP SRHOLD+LO + BCS ZRAND7 + +ZRAND6: LDA ARG1+HI ; NEW LOWER, SO SUBSTITUTE + STA SRHOLD+HI + LDA ARG1+LO + STA SRHOLD+LO + +ZRAND7: LDA RAND1+HI ; (EZIP) + CMP SRHOLD+HI + BCC ZRAND4 + LDA RAND1+LO + CMP SRHOLD+LO + BCC ZRAND4 + BEQ ZRAND4 + LDA #1 ; WENT THRU ALL + STA RAND1+LO ; START AGAIN + LDA #0 + STA RAND1+HI +ZRAND4: LDA RAND1+LO + STA VALUE+LO + LDA RAND1+HI + STA VALUE+HI + INC RAND1+LO ; FOR NEXT TIME + BNE ZRAND5 + INC RAND1+HI +ZRAND5: JMP PUTVAL ; (END EZIP) + + +; ---- +; 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 + + +; ------ +; INTBL? +; ------ + +ZINTBL: LDA ARG2+LO ; PICK UP TBL ADDR + STA MPCL + LDA ARG2+HI + STA MPCM + LDA #0 + STA MPCH ; ONLY A WORD ADDR, SO IN 1ST 64K + JSR VLDMPC +INTLP: JSR GETBYT ; GET A WORD ENTRY FROM TBL + STA I+HI + JSR GETBYT + CMP ARG1+LO ; DOES IT = THE VALUE LOOKING FOR? + BNE INTNXT ; NO + LDA I+HI + CMP ARG1+HI + BEQ INTFND ; YES, FOUND IT +INTNXT: DEC ARG3+LO + BNE INTLP + LDA ARG3+HI + BEQ INTNF ; NOT FOUND + DEC ARG3+HI + JMP INTLP ; GO DO SOME MORE +INTFND: SEC + LDA MPCL + SBC #2 + STA MPCL + BCS INTEX + DEC MPCM ; ONCE AGAIN, RETURNING WORD SO 64K LIMIT +INTEX: STA VALUE+LO ; AND SET TO RETURN THE VALUE + LDA MPCM + STA VALUE+HI + JSR PUTVAL ; SEND IT BACK + JMP PREDS ; AND SCREEM SUCCESS +INTNF: LDA #0 ; 0 = NOT FOUND + STA VALUE+LO + STA VALUE+HI + JSR PUTVAL + JMP PREDF ; FAILED! + + END diff --git a/64/lzip/read.asm b/64/lzip/read.asm new file mode 100644 index 0000000..31a98a0 --- /dev/null +++ b/64/lzip/read.asm @@ -0,0 +1,453 @@ + PAGE + SBTTL "--- READ HANDLER ---" + + +; ---- +; READ +; ---- +; READ LINE INTO TABLE [ARG1] ; PARSE INTO TABLE [ARG2] + +ZREAD: ;JSR ZUSL ; UPDATE THE STATUS LINE (NOT IN EZIP) + LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + CLC ; ABSOLUTE + ADC ZCODE + STA RDTBL1+HI ; AND PLACE IT HERE TO USE + LDA ARG1+LO + STA RDTBL1+LO ; LSBS NEED NOT CHANGE + LDA ARG2+HI + CLC + ADC ZCODE + STA RDTBL2+HI + LDA ARG2+LO + STA RDTBL2+LO + + LDY #0 ; GET SIZE OF INPUT BUFFER + LDA (RDTBL1),Y + CMP #79 ; IF OVER 78, CUT DOWN TO 78 + BCC LEAVIT ; LEAVE IT AS IT IS, IT IS LESS + LDA #78 +LEAVIT: STA CHRMAX ; SET COUNTER FOR INPUT + JSR INPUT ; READ LINE; RETURN LENGTH IN [A] + + ; IF TIMEOUT, [A]=0 SO WILL QUIT W/NO RESULTS + + STA LINLEN ; SAVE # CHARS IN LINE + LDA #0 + STA WRDLEN ; INIT # CHARS IN WORD COUNTER + LDY #1 ; POINT TO "# WORDS READ" SLOT + STA (RDTBL2),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 (RDTBL2),Y ; AND READ IT + BEQ RDERR ; (5/14/85 - FORCE # WORDS TO + CMP #60 ; BE BETWEEN 1 AND 59 + BCC RD0 +RDERR: LDA #59 + STA (RDTBL2),Y ; Le) +RD0: INY ; (Y = 1) POINT TO "# WORDS READ" SLOT + CMP (RDTBL2),Y ; TOO MANY WORDS? + BCC RLEX ; YES, SO LEAVE, IGNORING THE REST + +; BCS RL1 ; CHANGED 5.2.85 IN ZIP & EZIP +; ; *** ERROR #13: PARSER OVERFLOW *** +; +; LDA #13 +; JMP ZERROR + +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 #9 ; 9 CHARS DONE? (EZIP) + 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 #8 ; 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 (RDTBL1),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 (RDTBL1),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 DB II IN [IN] TO Z-STRING + JSR FINDW ; AND LOOK IT UP IN VOCABULARY + LDY #1 + LDA (RDTBL2),Y ; FETCH THE # WORDS READ + CLC + ADC #1 ; INCREMENT IT + STA (RDTBL2),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 RDTBL2+LO ; LSB OF RESULT TABLE BASE + CLC + ADC RESULT ; AND CURRENT POINTER + STA ENTRY+LO ; SAVE IN [ENTRY] + LDA RDTBL2+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 (RDTBL1),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? +; --------------------------------- +; ------------------ +; NORMAL BREAK CHARS +; ------------------ + +BRKTBL: DB '!?,.' ; IN ORDER OF + DB $0D ; DB ENDING FREQUENCY + DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED +NBRKS EQU $-BRKTBL ; # NORMAL BREAKS + +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 + + +; --------------------- +; IS CHAR IN [A] A SIB? +; --------------------- + +SIB: STA IOCHAR ; SAVE TEST CHAR + LDA ZBEGIN+ZVOCAB ; GET 1ST BYTE IN VOCAB TABLE + LDY ZBEGIN+ZVOCAB+1 + STA MPCM + STY MPCL + LDA #0 + STA MPCH + JSR VLDMPC ; GET CORRECT PAGE + JSR GETBYT ; HAS # SIBS + STA J ; USE AS AN INDEX +SBL: JSR GETBYT ; GET NEXT SIB + CMP IOCHAR ; MATCHED? + BEQ FBRK0 ; YES, REPORT IT + DEC J + BNE SBL ; ELSE KEEP LOOPING + LDA IOCHAR + CLC ; NO MATCH, SO + RTS ; EXIT WITH CARRY CLEAR +FBRK0: LDA IOCHAR +FBRK: SEC ; EXIT WITH CARRY SET + RTS ; IF MATCHED WITH A BREAK CHAR + + +; ----------------- +; VOCABULARY SEARCH +; ----------------- +; ENTRY: 6-BYTE TARGET Z-WORD IN [OUT] +; EXIT: VIRTUAL ENTRY ADDRESS IN [VALUE] IF FOUND ; +; OTHERWISE [VALUE] = 0 + +VWLEN EQU I +VWCUR EQU J+HI + +FINDW: LDA ZBEGIN+ZVOCAB ; GET VIRTUAL ADDR OF VOCAB TBL + LDY ZBEGIN+ZVOCAB+1 + STA MPCM + STY MPCL + LDA #0 + STA MPCH + JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # SIBS + CLC + ADC MPCL ; GET ACTUAL BASE ADDR OF VOCAB ENTRIES + STA MPCL + BCC FWL0 + INC MPCM +FWL0: JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # BYTES PER ENTRY (AND MOVE TO NEXT BYTE) + STA ESIZE ; SAVE IT HERE + STA VWLEN+0 ; AND HERE + LDA #0 ; CLEAR REST OF COUNTER + STA VWLEN+1 + STA VWLEN+2 + + JSR GETBYT ;GET # OF ENTRIES IN TBL (MSB) + STA NENTS+HI ; AND STUFF IT IN [NENTS] + JSR GETBYT ; DON'T FORGET THE LSB! + STA NENTS+LO + LDA #0 ; FIND SIZE OF VAOCAB TBL + STA VOCEND ; TO LOCATE THE END OF IT + STA VOCEND+1 + STA VOCEND+2 + LDX ESIZE + +FWL1: CLC + LDA VOCEND ; (# OF ENTRIES) * (ENTRY SIZE) + ADC NENTS+LO + STA VOCEND + LDA VOCEND+1 + ADC NENTS+HI + STA VOCEND+1 + LDA VOCEND+2 + ADC #0 ; PICK UP CARRY + STA VOCEND+2 + DEX + BNE FWL1 + + CLC + LDA VOCEND ; AND ADD LENGTH TO START OF TBL + ADC MPCL ; TO GET END OF TBL + STA VOCEND + LDA VOCEND+1 + ADC MPCM + STA VOCEND+1 + LDA VOCEND+2 + ADC MPCH + STA VOCEND+2 ; TO SAVE FOR TESTING IF PAST END + + LDA VOCEND ; SUBTRACT [ESIZE] SO THAT + SEC ; [VOCEND] POINTS TO REAL LAST ENTRY + SBC ESIZE + STA VOCEND + LDA VOCEND+1 + SBC #0 + STA VOCEND+1 + +; NOP +; NOP +; NOP +; NOP +; NOP +; NOP + + ; BEGIN THE SEARCH! [MPC] NOW POINTS TO 1ST ENTRY + + LSR NENTS+HI ; 2 ALIGN # OF ENTRIES + ROR NENTS+LO +FWCALC: ASL VWLEN+0 ; CALCULATE INITIAL OFFSET FOR SEARCH + ROL VWLEN+1 + ROL VWLEN+2 + LSR NENTS+HI + ROR NENTS+LO + BNE FWCALC + +; LDA NENTS+HI +; BNE FWCALC ; DOUBLE-CHECK + + CLC ; ADD 1ST OFFSET INTO START OF VOCABULARL + LDA MPCL ; WHICH IS CURRENTLY IN MPC + ADC VWLEN+0 + STA MPCL + LDA MPCM + ADC VWLEN+1 + STA MPCM + LDA MPCH + ADC VWLEN+2 + STA MPCH + + SEC ; AVOID FENCE-POST BUG FOR + LDA MPCL ; EXACT-POWER-OF-2 TBL (DUNCAN) + SBC ESIZE + STA MPCL + BCS FWLOOP + LDA MPCM + SEC + SBC #1 + STA MPCM + BCS FWLOOP + LDA MPCH + SBC #0 + STA MPCH + +FWLOOP: LSR VWLEN+2 ; SET FOR NEXT OFFSET, + ROR VWLEN+1 ; WHICH IS HALF THIS ONE + ROR VWLEN+0 + + LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + + JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET 1ST BYTE OF ENTRY + + CMP OUT ; MATCH 1ST BYTE OF TARGET? + BCC WNEXT ; LESS + BNE FWPREV ; GREATER + JSR GETBYT + CMP OUT+1 ; 2ND BYTE MATCHED? + BCC WNEXT + BNE FWPREV ; NOPE + JSR GETBYT + CMP OUT+2 ; 3RD BYTE? + BCC WNEXT + BNE FWPREV ; SORRY ... + JSR GETBYT + CMP OUT+3 ; 4TH BYTE + BCC WNEXT + BNE FWPREV + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BCC WNEXT + BNE FWPREV ; SORRY ... + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + BCS FWPREV ; ELSE BACK UP ... + +WNEXT: LDA VWCUR+0 ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + ADC VWLEN+1 + + BCS WNXT2 ; SAVES CODE (?) + + STA MPCM + + LDA #0 + STA MPCH + +; LDA VWCUR+2 +; ADC VWLEN+2 +; STA MPCH + +; LDA MPCH +; CMP VOCEND+2 ; GONE PAST END? +; BEQ WNXT0 ; MAYBE +; BCS WNXT2 ; YES +; BCC FWMORE ; NO +WNXT0: LDA MPCM + CMP VOCEND+1 + BEQ WNXT1 ; MAYBE + BCS WNXT2 ; YES + BCC FWMORE ; NO +WNXT1: LDA MPCL + CMP VOCEND + BCC FWMORE ; NO + BEQ FWMORE ; NO, EQUAL +WNXT2: LDA VOCEND ; YES, SO POINT TO END OF TBL + STA MPCL + LDA VOCEND+1 + STA MPCM + LDA VOCEND+2 + STA MPCH + JMP FWMORE + +FWPREV: LDA VWCUR+0 ; TO MOVE DOWN, JUST SUBTRACT + SEC ; OFFSET FROM START OF THIS + SBC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + SBC VWLEN+1 + STA MPCM + LDA VWCUR+2 + SBC VWLEN+2 + STA MPCH + +FWMORE: LDA VWLEN+2 ; IF OFFSET HIGH GELOW 1 WORD, CONTINUE + BNE FWM1 + LDA VWLEN+1 + BNE FWM1 + LDA VWLEN+0 + CMP ESIZE + BCC FWFAIL +FWM1: JMP FWLOOP ; AND TRY AGAIN + +FWFAIL: LDA #0 ; NOT FOUND + STA VALUE+LO + STA VALUE+HI + RTS ; THEN RETURN WITH [VALUE] = 0 + +FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD + STA VALUE+LO + LDA VWCUR+1 + STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY + RTS ; WORD VALUE RETURNABLE + + END diff --git a/64/lzip/shake.asm b/64/lzip/shake.asm new file mode 100644 index 0000000..99da159 --- /dev/null +++ b/64/lzip/shake.asm @@ -0,0 +1,191 @@ + PAGE + SBTTL "--- CBM64 FAST DISK HANDSHAKE ROUTINES ---" + + ; NOTE: WHEN MAKING THIS ALONE FOR SIDE 2 OF THE LZIP DISK + ; (FASTCODE.BIN) XASM WILL MAKE A 512 BYTE .BIN FILE, USE + ; DDT TO CUT IT BACK TO THE APPROPRIATE 256 BYTE SIZE + ; DDT SHAKE.BIN + ; + ; SAVE 1 FASTCODE.BIN + + + ; ------------------ + ; 1541 DRIVE EQUATES + ; ------------------ + +PB EQU $1800 +JOBS EQU $00 +HDRS EQU $06 +DATA EQU $0A +INDEX EQU $0B + +DATIN EQU $01 +DATOUT EQU $02 +CLKIN EQU $04 +CLKOUT EQU $08 +ATNIN EQU $80 + +READ EQU $80 +WRITE EQU $90 +VERIFY EQU $A0 +SEEK EQU $B0 +SECSEK EQU SEEK+8 +BUMP EQU $C0 +JUMPC EQU $D0 +EXEC EQU $E0 + +BUF1 EQU $0300 +BUF2 EQU $0400 +BUF3 EQU $0500 +BUF4 EQU $0600 +BUF5 EQU $0700 + +DSKCNT EQU $1C00 ; DISK CONTROLLER PORT ADDRESS + + ORG BUF3 + +INIT0: LDA PB + AND #$FF-DATOUT-CLKOUT + STA PB + + JSR CLK0 + +CMDWT: LDA DSKCNT ; READ CONTROLLER + AND #%11110111 ; CLEAR BIT 3 + STA DSKCNT ; TO SHUT OFF THE DAMNED LITTLE RED LIGHT + + JSR BYTGET ; GET TRACK ID (1-35) + TAX ; SAVE HERE + BEQ CMDEND ; IF ZERO + CMP #$FF ; OR $FF, + BEQ CMDEND ; DISENGAGE + STA HDRS ; ELSE SET TRACK # + + JSR BYTGET ; GET SECTOR # + STA HDRS+1 ; AND SET IT + + LDA DSKCNT ; TURN BACK ON + ORA #%00001000 ; THE STUPID LITTLE + STA DSKCNT ; RED LIGHT + + JSR RDFILE ; GET THE DATA + + JMP CMDWT ; WAIT FOR NEXT TRACK/SECTOR + +CMDEND: RTS ; EXIT HARD LOOP + +DEBNC: LDA PB ; WAIT FOR SERIAL LINE + CMP PB ; TO SETTLE DOWN + BNE DEBNC + RTS + +CLK0: JSR DEBNC + AND #CLKIN + BNE CLK0 + RTS + +BYTGET: LDA #$80 + STA DATA + +GTBIT: JSR DEBNC + TAY + AND #CLKIN + BEQ GTBIT + SEI + TYA + ORA #DATOUT + STA PB + + JSR CLK0 + LDA PB + AND #$FF-DATOUT + STA PB + +GTBO0: JSR DEBNC + TAY + AND #CLKIN + BEQ GTBO0 + JSR CLK0 + CLI + TYA + LSR A + ROR DATA + BCC GTBIT + + LDA DATA + RTS + +BYTSND: LDX #8 + STA DATA + +BITSND: LDA PB + TAY + AND #CLKIN + BEQ BITSND + TYA + ORA #DATOUT + STA PB + SEI + +BSND0: LDA PB + TAY + AND #CLKIN + BNE BSND0 + +BSND1: TYA + AND #$FF-DATOUT + STA PB + +SPEED: LDA PB + TAY + AND #CLKIN + BEQ SPEED + + TYA + LSR DATA + BCC BSND2 + ORA #DATOUT + +BSND2: STA PB + +BSND3: LDA PB + TAY + AND #CLKIN + BNE BSND3 + TYA + AND #$FF-DATOUT + STA PB + + DEX + BNE SPEED + CLI + RTS + +RDFILE: LDA #READ + STA JOBS + +TSTDO3: LDA JOBS + BMI TSTDO3 + +TSTDO5: LDA #0 + STA INDEX + +TSTDO4: LDY INDEX + LDA BUF1,Y + JSR BYTSND + INC INDEX + BNE TSTDO4 + RTS + + ; FILL REMAINDER OF SECTOR + ; WITH JUNK + + DB 0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0 + DB 0,0 + + END + diff --git a/64/lzip/subs.asm b/64/lzip/subs.asm new file mode 100644 index 0000000..fb2cf4b --- /dev/null +++ b/64/lzip/subs.asm @@ -0,0 +1,351 @@ + 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 LOW = 16, + BCS GETVRG ; IT'S GLOBAL + +; HANDLE A LOCAL VARIABLE + +GETVRL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA LOCALS-2+LO,X ; GRAB LSB + STA VALUE+LO + LDA LOCALS-2+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] +; ---------------------------------- +; ZSTACK DOUBLED IN SIZE FOR EZIP +; SO THIS RTN ALL NEW + +POPVAL: LDA ZSP+LO ; IF ZSP+LO IS 0 + BNE POP1 + STA ZSP+HI ; MUST DEC. HI (HI = 0 OR 1 ONLY) +POP1: DEC ZSP+LO ; THEN DEC ZSP LO + BNE POP2 + ORA ZSP+HI ; LO + HI BOTH 0? + BEQ UNDER ; UNDERFLOW IF ZERO! +POP2: LDY ZSP+LO + LDA ZSP+HI + BEQ POP3 ; BOTTOM HALF OF ZSTACK + LDA ZSTKTL,Y ; GET VALUE FROM TOP HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKTH,Y + STA VALUE+HI + RTS + +POP3: LDA ZSTKBL,Y ; GET VALUE FROM BOTTOM HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKBH,Y + STA VALUE+HI + 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: ;STX VALUE+LO ; KLUDGE 4.7.86 Le + ;STA VALUE+HI + + PHA ; HOLD VALUE IN [A] A SEC. + LDY ZSP+LO + LDA ZSP+HI + BEQ PSHBOT ; ON BOTTOM HALF OF STACK + TXA ; **** + STA ZSTKTL,Y ; PUSH VALUE ONTO TOP HALF OF STACK + PLA + STA ZSTKTH,Y + JMP PSHUPD ; NOW UPDATE POINTER + +PSHBOT: TXA ; PLACE VALUE ON ZSTACK + STA ZSTKBL,Y + PLA + STA ZSTKBH,Y +PSHUPD: INC ZSP+LO ; UPDATE ZSTACK POINTER + BNE PSHEX + LDA ZSP+LO + ORA ZSP+HI + BNE OVER ; OVERFLOW IF $200 + INC ZSP+HI ; TO 1 +PSHEX: 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 + +; FLUSH TOP WORD OFF STACK +; AND REPLACE WITH [VALUE] + + LDA ZSP+LO ; IF ZSP+LO =0 + BNE VAR1 ; THEN HI =1 (GUARDED ELSEWHERE) + STA ZSP+HI ; DECREMENT HI (ONLY 0 OR 1) +VAR1: DEC ZSP+LO ; NOW DEC LOW BYTE + BNE PSHVAL + ORA ZSP+HI + BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + BNE PSHVAL ; JMP + + ; RETURN A ZERO +RET0: LDA #0 + LDX #0 + + ; RETURN WORD IN [A], [X] (LO,HI) (EZIP EXPANDED TO A WORD) +PUTBYT: STA VALUE+LO + STX 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: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA VALUE+LO ; GRAB LSB + STA LOCALS-2+LO,X ; SAVE IN LOCAL TABLE + LDA VALUE+HI ; DO SAME TO + STA LOCALS-2+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 PREDB7 ; 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 +PREDB7: 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: LDA VALUE+LO ; SUBTRACT 2 FROM OFFSET + SEC ; IN [VALUE] + SBC #2 + TAX ;SAVE LO BYTE + LDA VALUE+HI + SBC #0 + STA I+LO ;MSB OF OFFSET = LSB OF [I] + LDY #0 ; CLEAR THE MSB + STY I+HI ; OF [I] + ASL A ; EXTEND THE SIGN OF OFFSET + ROL I+HI ; INTO MSB OF [I] + ASL A + ROL I+HI ; (EZIP) + TXA ; GET LSB OF OFFSET + 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 PREDB6 + LDA I+LO ; ELSE CALC NEW UPPER BITS + CLC + ADC ZPCM + STA ZPCM + LDA I+HI + ADC ZPCH + AND #%00000011 ; USE ONLY BIT 0 (& 1 - EZIP) + STA ZPCH + JMP VLDZPC ;MAKE VALID +PREDB6: + + ; FALL THROUGH ... + +; ---- +; NOOP +; ---- + +ZNOOP: RTS + + +; ---------------------- +; MOVE [ARG1] TO [VALUE] +; ---------------------- + +A12VAL: LDA ARG1+LO + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + RTS + + +; ----------------------------------- +; INDICATE STATUS LINE REFRESH NEEDED +; ----------------------------------- + +REFRSH: LDA ZBEGIN+ZSCRIP+1 ; PICK UP LOW BYTE OF FLAG WORD + ORA #%00000100 ; SET BIT 2 + STA ZBEGIN+ZSCRIP+1 ; AND PUT IT BACK + RTS + + END diff --git a/64/lzip/warm.asm b/64/lzip/warm.asm new file mode 100644 index 0000000..4deb2d8 --- /dev/null +++ b/64/lzip/warm.asm @@ -0,0 +1,159 @@ + PAGE + SBTTL "--- WARMSTART ROUTINE ---" + + ; ------------- + ; ZIP WARMSTART + ; ------------- + +WARM2: LDA #0 ; CLEAR ALL Z-PAGE VARIABLES + LDX #ZEROPG +ST0: STA 0,X + INX + CPX #ZPGTOP + BCC ST0 + + INC ZSP+LO ; INIT Z-STACK POINTERS + INC OLDZSP+LO ; TO "1" + INC SCRIPT ; ENABLE SCRIPTING + INC SCREENF ; TURN DISPLAY ON + INC SIDEFLG ; SET SIDE 1 + INC ZPURE ; TO FAKE OUT GETDSK SO READS 1ST SECTOR + + ; 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 + + JSR GETDSK ; [DBLOCK] SET TO Z-BLOCK 0 + BCC CHKGAM + JMP DSKERR ; BAD DISK READ + + ; EXTRACT GAME DATA FROM Z-CODE HEADER + +CHKGAM: LDA ZBEGIN+ZVERS ; (EZIP) IS GAME AN EZIP? + CMP #4 + BEQ YESEZ ; YES, CONTINUE + +; *** ERROR #16 -- NOT AN EZIP GAME *** + LDA #16 + JMP ZERROR + +; *** ERROR #0 -- INSUFFICIENT RAM *** +NORAM: LDX #5 + LDY #0 + JSR PLOT + LDA #0 + JMP ZERROR + +YESEZ: LDX ZBEGIN+ZENDLD ; MSB OF ENDLOAD POINTER + INX ; ADD 1 TO GET + STX ZPURE ; 1ST "PURE" PAGE OF Z-CODE + + TXA ; MAKE SURE FITS IN MEMORY + CLC + ADC ZCODE ; SIZE OF PRELOAD + START IN MEMORY + STA J ; SHOULD BE A VALUE = TO OR LT MEMTOP + JSR MEMTOP + CMP J + BEQ ITFITS + BCC NORAM ; OOPS + +ITFITS: LDA ZBEGIN+ZMODE ; ENABLE SPLIT-SCREEN, + ORA #%00111011 ; INVERSE, CURSOR CONTROL, + STA ZBEGIN+ZMODE ; SOUND (EZIP) + LDA #EZIPID ; SET INTERPRETER ID + STA ZBEGIN+ZINTWD + LDA #VERSID + STA ZBEGIN+ZINTWD+1 + LDA #$18 ; AND SCREEN PARAMETERS + STA ZBEGIN+ZSCRWD + LDA #40 + STA ZBEGIN+ZSCRWD+1 + 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+ZOBJEC ; NOT TO MENTION + CLC ; THE OBJECT TABLE + ADC ZCODE + STA OBJTAB+HI + LDA ZBEGIN+ZOBJEC+1 ; LSB SAME + STA OBJTAB+LO + + ; FIND SIZE AND NUMBER OF SAVES + + LDA ZBEGIN+ZPURBT ; SIZE OF IMPURE +SIZE0: ADC #6 ; PLUS ZSTACK &... + STA SAVSIZ ; HOW MANY PAGES PER SAVE + + LDX #0 + STX NUMSAV +SIZE1: INC NUMSAV ; INC NUMSAVE WITH EACH + CLC ; POSSIBLE SAVE + ADC SAVSIZ + BCC SIZE1 +SIZE2: INC NUMSAV ; TOTAL SIZE IS 170K, ($298) + CLC + ADC SAVSIZ ; SO DO LOOP FOR 1ST & 2ND $100 + BCC SIZE2 +SIZE3: CMP #$98 + BCS SIZE4 ; BEYOND TOTAL DISK SIZE + INC NUMSAV + CLC + ADC SAVSIZ + BCC SIZE3 + +SIZE4: LDA NUMSAV + CMP #$0A ; MAX OF 9 FOR EASE OF USE + BCC SIZE5 + LDA #9 + STA NUMSAV +SIZE5: CLC + ADC #'0' + STA POSTOP ; SET POSITION MSG + + LDY #1 ; POSITION MESSAGE + LDX #14 + CLC + JSR PLOT + + LDX #LOW TMSG + LDA #HIGH TMSG + LDY #TMSGL + JSR DLINE + + JMP ENDTST + +TMSG: DB "(Please be patient, this takes a while)" + DB EOL +TMSGL EQU $-TMSG + +ENDTST: JSR INITPAG + JSR CLS ; GET RID OF "LOADING" MSG + LDA ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + STA ZPCM ; MSB + LDA ZBEGIN+ZGO+1 ; AND LSB + STA ZPCL ; HIGH BIT ALREADY ZEROED + JSR VLDZPC ;MACKE ZPC VALID + + LDA SFLAG ; CHECK IF RESTART & WERE PRINTING + CMP #1 + BNE EX2 ; NO + STA SCRIPTF ; YES, TURN SCRIPT FLAG ON + ORA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO + STA ZBEGIN+ZSCRIP+1 + +EX2: JSR CLS ; CLEAR SCREEN ... + + ; ... AND FALL INTO MAIN LOOP + + END diff --git a/64/lzip/xpaging.asm b/64/lzip/xpaging.asm new file mode 100644 index 0000000..8b49e37 --- /dev/null +++ b/64/lzip/xpaging.asm @@ -0,0 +1,615 @@ + + PAGE + SBTTL "--- TIME-STAMP PAGING ROUTINE ---" + + + ; ------ + ; GETBYT + ; ------ + +GETBYT: LDA MPCPNT+HI + CMP #SWAPMEM ; SPEEDUP + BCC GETB1 + SEI + LDA RAMFLG ; SWAP IN RAM + AND #RAM + STA RAMFLG + +GETB1: LDY MPCL + LDA (MPCPNT),Y ;GET THE BYTE + + TAX + SEI + LDA RAMFLG ; RESET TO KERNAL ROM + ORA #KERNAL + STA RAMFLG + CLI + TXA + + INC MPCL ;POINT TO NEXT BYTE + BNE GETGOT ;IF NO CROSS WE ARE STILL VALID + JSR CRSMPC +GETGOT: TAY ;SET FLAGS + RTS ;RED SLIPPER TIME + + + ; ------ + ; NEXTPC + ; ------ + + ; LIKE GETBYT + +NEXTPC: LDA ZPCPNT+HI + CMP #SWAPMEM ; SPEEDUP + BCC NEXT1 + SEI + LDA RAMFLG ; SWAP IN RAM + AND #RAM + STA RAMFLG + +NEXT1: LDY ZPCL + LDA (ZPCPNT),Y + + TAX + SEI + LDA RAMFLG ; RESET TO KERNAL ROM + ORA #KERNAL + STA RAMFLG + CLI + TXA + + INC ZPCL + BNE NXTGOT + JSR CRSZPC +NXTGOT: TAY + 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 + JMP VLDMPC + + +; THE FIRST 86K (SIDE1) MUST +; BE RAM RESIDENT (344=$158 PAGES) +; +; PAGES V$0 TO ($FE-VBEGIN) ARE IN MAIN (BANK1) +; PAGES ($FE-VBEGIN) TO V$158 ARE IN AUX (BANK0) +; PAGENG BUFFERS ARE IN HIGH AUX +; +WANTED: DB 00,00 +; +CURRENT: DB 00 +NEXT: DB 00 +NSUBA: DB 00 +PSUBA: DB 00 +NSUBCUR: DB 00 +; +YTEMP: DB 00 +ATEMP: DB 00 +NSUBY: DB 00 +; + + +; MAKE [MPCPNT],[MPCBNK] POINT TO +; THE RAM PAGE AND BANK THAT HOLDS +; THE V-PAGE MPCH,M +; +VLDMPC: LDA MPCH + BNE VLD1 ;NOT IN FIRST V-64K + LDA MPCM + CMP ZPURE ;IS IT PRELOAD + BCS VLD1 ;NO + ADC #HIGH ZBEGIN ;ADD OFFSET TO GET RAM PAGE + STA MPCPNT+HI + CMP #$D0 ; SKIP $D0-$DF ; SPEEDUP + BCC NOMUCK + ADC #$0F ; 1 LESS AS CARRY SET + STA MPCPNT+HI +NOMUCK: RTS + +VLD1: ;MUST BE PAGED + LDA MPCH + LDY MPCM + JSR PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + CLC + ADC #PBEGIN + STA MPCPNT+HI + + ;TEST FOR MUCK + + LDA MUCKFLG + BEQ NOMUCK + JMP VLDZPC ;MAY HAVE MUCKED ZPC SO GO FIX + + ;SAME IDEA AS VLDMPC + +VLDZPC: LDA ZPCH + BNE VLDZ1 ;NOT IN FIRST V-64K + LDA ZPCM + CMP ZPURE ;IS IT PRELOAD + BCS VLDZ1 ;NO + ADC #HIGH ZBEGIN ;ADD OFFSET TO GET RAM PAGE + STA ZPCPNT+HI + CMP #$D0 ; SKIP $D0-$DF ; SPEEDUP + BCC NOZMUCK + ADC #$0F ; 1 LESS AS CARRY SET + STA ZPCPNT+HI +NOZMUCK: RTS + +VLDZ1: ;MUST BE PAGED + LDA ZPCH + LDY ZPCM + JSR PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + CLC + ADC #PBEGIN + STA ZPCPNT+HI + + ;TEST MUCKING + + LDA MUCKFLG + BEQ NOZMUCK + JMP VLDMPC ;MAY HAVE MUCKED MPC SO GO FIX + + +; FIND V-PAGE A,Y IF IT IS IN MEM +; AND RETURN WITH LINKED LIST +; PROPERLY MAINTAINED +; IF V-PAGE A,Y NOT IN MEM +; GET FROM DISK AND PUT IN RIGHT +; PLACE + +MUCKFLG: DB 00 ; 00 IF PAGING BUFFERS NOT MUCKED + + +PAGE: STA WANTED+HI + STY WANTED+LO + + ; CLEAR MUCK FLAG + + LDX #0 + STX MUCKFLG + + JSR WHERE + BCC TOUGH ;PAGE IS RESIDENT IN PAGENG SPACE + + ; PAGE MUST BE BROUGHT IN FROM DISK + + LDX CURRENT ;GET BUFFER TO PUT PAGE INTO + LDA NEXTPNT,X ;BY LOOKING AT NEXT POINTER + STA CURRENT ;MAKE IT THE CURRENT BUFFER + TAX + LDA WANTED+HI ;LET BUFFER MAP KNOW + STA VPAGEH,X ;WHICH PAGE + LDA WANTED+LO ;IS GOING TO + STA VPAGEL,X ;BE THERE + TAY + TXA + PHA ;SAVE BUFFER + LDA WANTED+HI + + ; Y = WANTED+LO + ; X = BUFFER + + JSR GETVPAGE ;PUT V-PAGE A,Y INTO PAGENG BUFFER X + + ;INDICATE A MUCKING + + DEC MUCKFLG + PLA ;RESTOR BUFFER NUMBER + RTS + + ; THIS IS WHERE THINGS GET WEIRD + +TOUGH: STA NEXT + CMP CURRENT ;GETS REALY FUCKED IF CURRENT=NEXT + BNE T1 + RTS ;DO NOT CHANGE POINTERS IF IT DOES, ALL IS WELL + +; Y=NEXT(CURRENT) +; DO THE RIGHT THING TO THE POINTERS +; ASK LIM TO EXPLAIN ,HA HA. + +T1: LDY CURRENT + LDA NEXTPNT,Y + STA NSUBCUR + LDA NEXT + JSR DETATCH + LDY CURRENT + LDA NEXT + JSR INSERT + LDA NEXT + STA CURRENT +T2: RTS + + ; GET A PAGE IN BANK 1, PREPAGED + + ; TEMPORARY NOTE: GET A PAGED PAGE [A,Y] >(DBLOCK) + ; FROM DISK & PUT IN PAGING BUFFER [X] (MUST BE MADE ABSOLUTE) + +GETVPAGE: STA DBLOCK+HI + STY DBLOCK+LO + TXA ; OFFSET INTO CORRECT RAM PAGE + CLC + ADC #PBEGIN ; MAKE ABSOLUTE + STA DBUFF+HI + + LDA XEXIST ; IF XRAM EXISTS, IT'S ALL IN THERE + BNE GETXPAGE ; SO GET IT FROM THERE + + JSR GETDSK + BCC T2 ; RTS + JMP DSKERR ; COULDN'T READ DISK + +GETXPAGE: LDA DBLOCK+LO + SEC ; SIDE 2, SO SUBTRACT SIDE 1 + SBC ZPURE ; AMOUNT SO GET ACCURATE + PHA ; CALCULATION WHERE SECTOR IS + LDA DBLOCK+HI + SBC #0 ; PICK UP CARRY + TAX + PLA ; [A] = LOW, [X] = HIGH + + STX XFLAGS+XBANK ; BANK CURRENTLY WRITING TO + STA XFLAGS+XRAM+HI ; BLOCK IN XRAM + LDA #0 + STA XFLAGS+XRAM+LO + STA XFLAGS+XINT ; NO INTERRUPTS + STA XFLAGS+XINCR ; INCREMENT ADDR POINTERS + STA XFLAGS+XSIZ+LO ; AMOUNT TO WRITE IS 1 PG + LDA #1 + STA XFLAGS+XSIZE+HI + LDA #HIGH IOBUFF + STA XFLAGS+XBUFF+HI + LDA #LOW IOBUFF + STA XFLAGS+XBUFF+LO + LDA #XREAD ; READ FROM XRAM + STA XFLAGS+XFER ; THIS WRITE DOES ACTUAL TRANSFER + + JMP GOT ; AND TRANSFER IT PROPERLY TO PAGING + + +; PREV(A)=Y +; PREV(NEXT(Y))=A +; NEXT(A)=NEXT(Y) +; NEXT(Y)=A + + ; INSERT A BEFORE Y + +INSERT: STA ATEMP + STY YTEMP + TAX + TYA + STA PREVPNT,X + + LDA NEXTPNT,Y + STA NSUBY + TXA + LDX NSUBY + STA PREVPNT,X + + TXA + LDX ATEMP + STA NEXTPNT,X + + LDA ATEMP + STA NEXTPNT,Y + RTS + + +; DETATCH BUFFER HIGH ALOW +; NEXT(PREV(A))=NEXT(A) +; PREV(NEXT(A))=PREV(A) + +DETATCH: TAX + LDA NEXTPNT,X + STA NSUBA + LDA PREVPNT,X + STA PSUBA + TAX + LDA NSUBA + STA NEXTPNT,X + LDA PSUBA + LDX NSUBA + STA PREVPNT,X + RTS + + +; RETURN BUFFER OF PAGE [WANTED] +; IN [A] ELSE SEC (Y=WANTED+LO) +; (CHECKING FOR PAGED BUFFER ALREADY RESIDENT) + +WHERE: LDX #NUMBUFS-1 +WHLOOP: + LDA WANTED+HI + CMP VPAGEH,X ;HIGH SAME + BEQ WHGOT +WHNOGOT: + DEX + BPL WHLOOP + SEC + RTS +WHGOT: + TYA + CMP VPAGEL,X + BNE WHNOGOT + TXA + CLC + RTS + + + ; SETS UP PAGING SYSTEM - CALLED FROM WARM + +INITPAG: LDX #NUMBUFS-1 + STX CURRENT + LDA #$FF +INILP: + STA VPAGEH,X + DEX + BPL INILP + LDX #0 + LDY #1 +INILP2: + TYA + STA PREVPNT,X + INX + INY + CPX #NUMBUFS + BCC INILP2 + LDA #00 + DEX + STA PREVPNT,X + LDX #0 + LDY #$FF + LDA #NUMBUFS-1 +INILP3: + STA NEXTPNT,X + INX + INY + TYA + CPX #NUMBUFS + BCC INILP3 + + ; FALL THRU TO GETSIDE1 +; +; GET SIDE 1 LOADS ALL CODE FROM +; DISK SIDE 1 INTO ITS CORRECT +; PLACE + +; THE FIRST VPAGE MUST ALREADY BE +; RESIDENT AT [ZBEGIN] + +GETSIDE1: LDA DBLOCK+LO ; INCREMENT NOT CORRECT, SO + CMP ZPURE ; (LAST PRELOAD PG YET? + BCS FIN ; YES) + LDX DBLOCK+HI ; REFIGURE EACH TIME FOR NOW + LDY #3 ; SIDE 1 STARTS ON TRACK 3 + JSR SETTS ; GO GET TRACK & SECTOR + JSR GETRES ; AND GO READ THE DISK + BCC GETSIDE1 + JMP DSKERR ; OH SHIT + + +FIN: ; ALL DONE WITH LOADING SIDE1 NOW + JSR CLS ; CLEAR THE SCREEN FOR NEATNESS + LDX #2 + LDY #0 + CLC + JSR PLOT + JSR SIDE2 ;CODE EXISTS ON SIDE2 AND WE HAVE SIDE 1 + + LDA RESFLG ; IF A RESTART (NOT COLD), DON'T NEED XRAM LOAD + BNE FIN2 ; (1=RESTART) + LDA XEXIST ; IS THERE EXPANSION RAM? + BNE LDXRAM ; YES, GO FILL IT +FIN2: RTS + + + ; COPY ALL OF SIDE 2 TO XRAM TO USE AS RAM DISK FOR FASTER DISK ACCESS + +LDXRAM: LDA ZBEGIN+ZLENTH+1 ; GET LENGTH OF GAME (QUADS) + STA J+LO + LDA ZBEGIN+ZLENTH+0 + LDY #5 +SLP: LSR A ; CONVERT QUADS TO PAGES WITH /64 + ROR J+LO + DEY + BPL SLP + STA J+HI + SEC ; NOW SUBTRACT WHAT HAS ALREADY BEEN LOADED + LDA J+LO + SBC #LOW PSIDE1 + STA J+LO + LDA J+HI + SBC #HIGH PSIDE1 + STA J+HI + +; [J] HAS # PAGES IN GAME ROUNDED +; DOWN, AND LESS WHAT IS ALREADY IN +; SO WE NEED ONLY LOAD [J] MORE +; PAGES + + INC J+LO ; SEEMS TO HELP + INC J+LO + + LDA #0 + STA I+HI ; XRAM PAGE COUNTER + STA I+LO + STA L+LO ; BANK TO START ON + + LDX #LOW LMSG ; TELL LOADING SIDE2 INTO XRAM + LDA #HIGH LMSG + LDY #LMSGL + JSR DLINE + +FILL: JSR DECJ ; C=0 IF [J] GOES LT 0 + BCC FILLED + LDA #HIGH IOBUFF + STA DBUFF+HI ; FAKE GETDSK OUT + JSR GETDSK + BCC FILL0 + JMP DSKERR ; OH SHIT + +FILLED: LDA #1 + STA RESFLG ; SET RESTART FLAG ON FOR XRAM LOAD + RTS + +FILL0: LDA I+HI + STA XFLAGS+XRAM+HI ; WHERE TO WRITE IN XRAM + LDA I+LO + STA XFLAGS+XRAM+LO + LDA #0 + STA XFLAGS+XINT ; NO INTERRUPTS + STA XFLAGS+XINCR ; INCREMENT ADDR POINTERS + STA XFLAGS+XSIZ+LO ; AMOUNT TO WRITE IS 1 PG + LDA #1 + STA XFLAGS+XSIZE+HI + LDA L+LO + STA XFLAGS+XBANK ; BANK CURRENTLY WRITING TO + LDA #HIGH IOBUFF ; ALWAYS WRITE FROM IOBUFF + STA XFLAGS+XBUFF+HI + LDA #LOW IOBUFF + STA XFLAGS+XBUFF+LO + LDA #XWRITE ; WRITE TEST TO XRAM + STA XFLAGS+XFER ; THIS WRITE DOES ACTUAL TRANSFER + + INC I+HI ; NEXT PAGE + BNE FILL + INC L+LO ; NEXT BANK + JMP FILL + + + +LMSG: DB EOL,EOL,"Side 2 being loaded into expansion ram" + DB EOL,EOL,"This will take about 10 minutes" + DB EOL +LMSGL EQU $-LMSG + +;DECJ RETURNS C=0 WHEN J=$FFFF + +DECJ: LDA J+LO + SEC + SBC #1 + STA J+LO + LDA J+HI + SBC #0 + STA J+HI + RTS + + + + ; CHECK IF THERE IS EXPANSION RAM ON THIS MACHINE + +MEMCHK: LDA #$55 ; FIRST CHECK IF MACHINE HAS XRAM + LDX #0 ; BANK 0 + STX XEXIST ; SET TO NO + JSR CHKX + BCS MEMXNO + LDA #$AA + LDX #1 + JSR CHKX + BCS MEMXNO + LDA #$FE ; CHECK FOR 3 BANKS WORTH (NEED 170K) + LDX #2 + JSR CHKX + BCS MEMXNO + LDA #1 + STA XEXIST ; YES, THERE IS EXPANSION RAM PRESENT + +MEMXNO: RTS ; OF AUX MEMORY + + ; CHECK FOR THE PRECENCE OF A 256K EXPANSION RAM + ; SET ALL THE FLAGS WRITE & SEE IF READ BACK WHAT WROTE + +CHKX: STX L+LO ; SAVE BANK TO TEST FOR THIS TIME + STA IOCHAR ; HOLD FOR CMP + LDY #0 +CLOOP1: STA IOBUFF,Y + INY + BNE CLOOP1 + + LDA #0 + STA XFLAGS+XRAM+HI + STA XFLAGS+XRAM+LO + STA XFLAGS+XINT + STA XFLAGS+XINCR + STA XFLAGS+XSIZ+LO + LDA #1 + STA XFLAGS+XSIZE+HI + LDA L+LO + STA XFLAGS+XBANK + LDA #HIGH IOBUFF + STA XFLAGS+XBUFF+HI + LDA #LOW IOBUFF + STA XFLAGS+XBUFF+LO + LDA #XWRITE ; WRITE TEST TO XRAM + STA XFLAGS+XFER ; THIS WRITE DOES ACTUAL TRANSFER + + LDA #0 ; CLEAR IOBUFF BEFORE READ + LDY #0 ; SO SURE IT GETS DONE +CLOOP2: STA IOBUFF,Y + INY + BNE CLOOP2 + + LDA #0 + STA XFLAGS+XRAM+HI + STA XFLAGS+XRAM+LO + STA XFLAGS+XINT + STA XFLAGS+XINCR + STA XFLAGS+XSIZ+LO + LDA #1 + STA XFLAGS+XSIZE+HI + LDA L+LO + STA XFLAGS+XBANK + LDA #HIGH IOBUFF + STA XFLAGS+XBUFF+HI + LDA #LOW IOBUFF + STA XFLAGS+XBUFF+LO + LDA #XREAD ; READ WHAT JUST WROTE + STA XFLAGS+XFER ; THIS WRITE DOES ACTUAL TRANSFER + + LDA IOCHAR ; SEE IF READ BACK RIGHT THING + LDY #0 +CLOOP3: CMP IOBUFF,Y + BNE CNOX + INY + BNE CLOOP3 + CLC + RTS +CNOX: SEC ; NOT THERE + RTS + + +; TAKE CARE OF CROSSING A PAGE + +CRSMPC: + PHA + INC MPCM + BNE CRS1 + INC MPCH +CRS1: JSR VLDMPC + PLA + RTS + +;SAME AS CRSMPC + +CRSZPC: + PHA + INC ZPCM + BNE CRSZ1 + INC ZPCH +CRSZ1: JSR VLDZPC + PLA + RTS + + PAGE + + END diff --git a/64/lzip/zdos.asm b/64/lzip/zdos.asm new file mode 100644 index 0000000..50c1596 --- /dev/null +++ b/64/lzip/zdos.asm @@ -0,0 +1,814 @@ + + PAGE + SBTTL "--- Z-DOS: CBM64 ---" + + + ; --------------------- + ; GET Z-BLOCK FROM DISK + ; --------------------- + + ; ENTRY: Z-BLOCK # IN [BLOCK] + ; TARGET PAGE IN [DBUFF+HI] + + ; NOTE: USING VARIABLE SECTORS PER TRACK TO GET 170K ON DISK + +GETDSK: LDA #8 + STA DRIVE ; GAME ALWAYS PLAYS FROM DRIVE #8 + + LDA DBLOCK+HI ; SIDE 1 OR 2? + BNE SID2 + + LDA DBLOCK+LO + CMP ZPURE + BCC GETSD1 + +SID2: LDA SIDEFLG ; ON SIDE 2? + CMP #2 + BEQ GETSD2 ; YES + JSR SIDE2 ; NO, ASK FOR IT + +GETSD2: LDA DBLOCK+LO + SEC ; SIDE 2, SO SUBTRACT SIDE 1 + SBC ZPURE ; AMOUNT SO GET ACCURATE + PHA ; CALCULATION OF TRACK & SECTOR + LDA DBLOCK+HI + SBC #0 ; PICK UP CARRY + TAX + PLA + LDY #1 ; SIDE 2 STARTS ON TRACK 1 + JSR SETTS ; SET TRACK & SECTOR + + JMP GETRES ; AND GO READ + +GETSD1: LDA SIDEFLG ; ARE WE ON SIDE 1 + CMP #1 + BEQ SID1 + JSR SIDE1 + +SID1: LDA DBLOCK+LO + LDX DBLOCK+HI + LDY #3 ; SIDE 1 STARTS ON TRACK 3 + JSR SETTS ; GO GET TRACK & SECTOR + + ; AND GO READ THE DISK + +GETRES: CLC ; CARRY CLEAR = "READ BLOCK" + JSR DISK ; GO DO IT! + BCC GOT + RTS ; ERROR IF CARRY SET + +GOT: LDA DBUFF+HI ; CHECK IF HIGH MEM + CMP #SWAPMEM ; SPEEDUP + BCC GOT1 ; NO + + SEI + LDA RAMFLG ; SWAP IN RAM + AND #RAM + STA RAMFLG + +GOT1: LDY #0 ; MOVE CONTENTS OF [IOBUFF] +GDKL: LDA IOBUFF,Y ; TO THE + STA (DBUFF),Y ; TARGET PAGE IN [DBUFF] + INY + BNE GDKL + + SEI + LDA RAMFLG ; RESET TO KERNAL ROM + ORA #KERNAL + STA RAMFLG + CLI + + INC DBUFF+HI ; POINT TO NEXT PAGE + + LDA DBUFF+HI ; SPEEDUP + CMP #$D0 ; SKIP OVER IO & COLOR RAM SPACE + BNE GDKM + CLC + ADC #$10 + STA DBUFF+HI +GDKM: JMP NXTDBL ; POINT TO NEXT DBLOCK, SECTOR & TRACK + + + ; SET TRACK & SECTOR FROM A,X DBLOCK (A=LO) Y = STARTING TRACK + +SETTS: STY TRACK + DEY + +TRKLP: CMP TRKTBL,Y ; CHECK IF REMAINDER LESS + BCS DOIT ; THAN 1 TRACK + CPX #0 + BEQ TRKDUN ; YES + +DOIT: SEC ; SUBTRACT ANOTHER TRACKS WORTH + SBC TRKTBL,Y ; FROM THE SECTORS PER TRACK TABLE + BCS TRK1 + DEX ; BORROWED +TRK1: INC TRACK + INY ; NEXT TRACK IN TABLE + BNE TRKLP ; JMP + +TRKDUN: STA SECTOR + LDA TRACK + CMP #20 ; TRK 20, SECT 0 IS FAST CODE, SKIP OVER + BNE NOT20 + INC SECTOR ; NO HARM IN FALLING THRU +NOT20: CMP #18 ; IF ON TRACK 18, SKIP OVER 1ST SECTOR + BNE TRKOVR + INC SECTOR +TRKOVR: RTS + + + ; THIS SETUP OF SECTOR 0, TRK 18 ONLY BEING SKIPPED IS FOR SIDE 2. + ; ON SIDE 1, ALL OF TRK 17 AND SECTORS 0 & 1 ARE UNAVAILABLE WITH + ; AN LZIP DISK BEING USED BY THE FILE "STORY" AND ITS DIRECTORY + ; ENTRY - HOWEVER AS THE GAME IS SPLIT AT 43.5K, THESE SECTIONS OF + ; THE DISK ARE NEVER REACHED SO THE "STORY" FILE IS SAFE AND BOTH + ; SIDES OF THE DISK MAY BE ACCESSED THE SAME MAKING LIFE EASIER - + ; SHOULD THE SPLIT BECOME MUCH LARGER FOR LZIP GAME - ALL BETS ARE OFF + ; (LSD - 12/1/86) + ; TRACK 20 SECTOR 0 IS FOR FAST CODE, MUST BE THERE FOR 2 DRIVE SAVE + ; AND USING FAST CODE, ON BOTH SIDE1 & SIDE2! (LSD 1/9/87) + +TRKTBL: DB 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21 + DB 18,19,18,19,19,19,19 + DB 18,18,18,18,18,18 + DB 17,17,17,17,17 + + ; *** ERROR #12: DISK ADDRESS OUT OF RANGE *** + +TRKERR: LDA #12 + JMP ZERROR + + ; *** ERROR #14: DRIVE ACCESS *** + +DSKERR: LDA #14 + JMP ZERROR + + + + ; -------------------- + ; PUT [DBLOCK] TO DISK + ; -------------------- + + ; ENTRY: [DBLOCK] & [DRIVE] ASSIGNED + ; PAGE TO WRITE IN [DBUFF] + +PUTDSK: LDA DBUFF+HI ; CHECK IF HIGH MEM + CMP #SWAPMEM ; SPEEDUP + BCC PTKL0 ; NO + + SEI + LDA RAMFLG ; SWAP IN RAM + AND #RAM + STA RAMFLG + +PTKL0: LDY #0 ; MOVE PAGE AT [DBUFF] +PTKL: LDA (DBUFF),Y ; INTO + STA IOBUFF,Y ; [IOBUFF] FOR I/O + INY + BNE PTKL + + SEI + LDA RAMFLG ; RESET TO KERNAL ROM + ORA #KERNAL + STA RAMFLG + CLI + + SEC ; CARRY SET = "WRITE BLOCK" + JSR DISK + BCS WRTERR ; CARRY SET IF ERROR + + INC DBUFF+HI ; NEXT MEMORY PAGE + + LDA DBUFF+HI ; SPEEDUP + CMP #$D0 ; SKIP OVER IO & COLOR RAM SPACE + BNE NXTDBL + CLC + ADC #$10 + STA DBUFF+HI + +NXTDBL: INC DBLOCK+LO ; POINT TO NEXT VIRTUAL PAGE + BNE DBLOK + INC DBLOCK+HI +DBLOK: INC SECTOR ; NEXT SECTOR + LDY TRACK ; CHECK IF NEXT TRACK + DEY + LDA SECTOR + CMP TRKTBL,Y + BCC SECTOK + + INC TRACK ; YES, RESET + LDA #0 + STA SECTOR + LDA TRACK + CMP #18 ; IF ON TRACK 18, SKIP OVER 1ST SECTOR (0) + BNE NOT18 ; (DISK DIRECTORY) + INC SECTOR +NOT18: CMP #20 ; TRK 20, SECT 0 ALSO (FAST CODE) + BNE SECTOK + INC SECTOR +SECTOK: CLC +WRTERR: RTS + + + + ; -------------------- + ; PROMPT FOR GAME DISK + ; -------------------- + + ; EZIP USES BOTH SIDES OF DISK + + +GAME: DB EOL + DB "Insert Side " +DSIDE: DB "* of the STORY" + DB EOL + DB "disk into Drive #8." + DB EOL +GAMEL EQU $-GAME +SD: DB "INFOCOM-S" + + +SIDE1: LDA #'1' ; ASK FOR SIDE 1 + STA DSIDE + LDA #1 ; SET FOR SUCCESS + STA SIDEFLG + + LDA FAST ; FAST-READ (LC-A) + BEQ SL0 ; NO (LC-A) + JSR FOFF ; ELSE DISENGAGE (LC-A) + +SL0: JSR ASKFOR1 ; SEPARATE CAUSE RESTART HANDLES DIFF (LC-A) + BCS SL1 + JMP ASK2 ; GOOD, FINISH UP (LC-A) +SL1: JMP DSKERR ; OOPS (LC-A) + +ASKFOR1: LDX #LOW GAME + LDA #HIGH GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + LDX #0 ; READ DIRECTORY + STX SECTOR ; MUST BE "INFOCOM-S1" + LDX #$12 + STX TRACK + + LDA #8 ; MAKE SURE WE'RE ON + STA DRIVE ; THE GAME DRIVE + JSR DOPEN + + CLC ; CARRY CLEAR = "READ BLOCK" + JSR DISK ; GO DO IT! + BCC SL3 + RTS ; ERROR IF CARRY SET (LC-A) + +SL3: LDY #$99 ; OFFSET IN DIRECTORY SECTOR + LDX #9 + LDA #"1" + BNE SL8 +SL7: LDA SD,X ; "INFOCOM-S1" +SL8: CMP IOBUFF,Y ; DIR ENTRY CORRECT? + BNE ASKFOR1 ; NO, GO ASK AGAIN + DEY + DEX + BPL SL7 + CLC + RTS ; GOOD (LC-A) + +SIDE2: LDA #'2' ; ASK FOR SIDE 2 + STA DSIDE + LDA #2 + STA SIDEFLG ; SET FOR SUCCESS + + LDA FAST ; FAST-READ (LC-A) + BEQ SL9 ; NO (LC-A) + JSR FOFF ; ELSE DISENGAGE (LC-A) + +SL9: LDA RESFLG ; IF USING EXPANSION RAM AND IT IS + BNE ASK2 ; FILLED, DON'T NEED DISK + + LDA DRIVE ; GET LAST DRIVE USED + PHA ; HOLD IT A SEC + + LDA #8 ; MAKE SURE WE'RE ON + STA DRIVE ; THE BOOT DRIVE + JSR DOPEN + + PLA ; IF SAVED/RESTORED + CMP #9 ; TO DRIVE 2, DON'T ASK + BEQ ASK2 ; NOTE: THIS IS OK W/ VERIFY CAUSE ASKS + ; FOR SIDE 1 FIRST, RESETTING DRIVE TO 1 +SL2: LDX #LOW GAME + LDA #HIGH GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + + LDX #0 ; READ DIRECTORY + STX SECTOR ; MUST BE "INFOCOM-S2" + LDX #$12 + STX TRACK + CLC + JSR DISK + BCC SL4 + JMP SL2 ; BAD READ, GO ASK AGAIN + +SL4: LDY #$99 ; OFFSET IN DIRECTORY SECTOR + LDX #9 + LDA #"2" + BNE SL6 +SL5: LDA SD,X +SL6: CMP IOBUFF,Y ; DIR ENTRY CORRECT? + BNE SL2 ; NO, GO ASK AGAIN + DEY + DEX + BPL SL5 + +ASK2: LDA #EOL + JSR CHROUT + ;JSR RETURN ; DEBUG + + LDA FAST ; FAST-READ? (LC-A) + BEQ ASK3 ; NO (LC-A) + JSR FINIT ; ELSE RE-INIT FAST CODE (LC-A) + +ASK3: LDA #$FF ; RE-ENABLE + STA SCRIPT ; SCRIPTING + RTS + + + ; ----------------------------- + ; SET UP SAVE & RESTORE SCREENS + ; ----------------------------- + +SAVRES: JSR ZCRLF ; CLEAR THE BUFFER + LDX #0 + STX SCRIPT ; DISABLE SCRIPTING + STX LINCNT + RTS + + ; ----------------- + ; DISPLAY A DEFAULT + ; ----------------- + + ; ENTRY: DEFAULT (0-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 + JSR DLINE ; PRINT THE STRING + + LDX #0 ; (LC-A) + STX NDX ; CLEAR QUEUE + INX + STX SPENA ; ALLOW CURSOR + RTS + + + ; ----------------------------- + ; GET SAVE & RESTORE PARAMETERS + ; ----------------------------- + +POSIT: DB EOL + DB "Position 1-" +POSTOP: DB "*" +POSITL EQU $-POSIT + +WDRIV: DB EOL + DB "Drive 8 or 9" +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 POSITION + +CHANGE: 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 NUMSAV ; IF BELOW "6" + 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 LETTER ; AND DISPLAY IT + + ; GET DRIVE ID + + LDX #LOW WDRIV + LDA #HIGH WDRIV + LDY #WDRIVL + JSR DLINE ; "DRIVE 8 OR 9" + + LDA GDRIVE ; SHOW DEFAULT + CLC ; CONVERT 0 OR 1 + ADC #7 ; TO 7 OR 8 + JSR DODEF ; SO DEFAULT WILL BE CORRECT + +GETDRV: JSR GETKEY ; GET A KEYPRESS + CMP #EOL ; IF [RETURN], + BEQ DRVSET ; USE DEFAULT + SEC + SBC #'8' ; 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 #'8' ; CONVERT TO ASCII 8 OR 9 + STA SAVDRI ; STORE IN DRIVE STRING + STA MDRI ; AND IN TEMP STRING + JSR LETTER ; AND SHOW NEW SETTING + + LDX #LOW MIND ; SHOW TEMPORARY SETTINGS + LDA #HIGH MIND + LDY #MINDL + JSR DLINE + + LDX #0 ; (LC-A) + STX NDX ; CLEAR QUEUE + INX + STX SPENA ; ALLOW CURSOR + +GETYES: JSR GETKEY + CMP #'Y' ; IF REPLY IS "Y" + BEQ ALLSET ; ACCEPT RESPONSES + CMP #'y' + BEQ ALLSET + + CMP #'N' ; IF REPLY IS N, + BEQ RETRY ; DO A RETRY + CMP #'n' + BEQ RETRY + + JSR BOOP ; INSIST ON Y/RETURN + JMP GETYES ; OR N + +RETRY: LDX #LOW NO ; ELSE PRINT "NO" + LDA #HIGH NO + LDY #NOL + JSR DLINE + JMP PARAMS ; AND TRY AGAIN + +ALLSET: LDA #0 ; (LC-A) + STA SPENA ; (LC-A) + LDX #LOW YES ; PRINT "YES" + LDA #HIGH YES + LDY #YESL + JSR DLINE + + ; CALC START POSITION OF SAVE + + LDA #0 ; SET FOR POSITION 1 + STA DBLOCK+LO + STA DBLOCK+HI + + LDX TPOSIT ; GET # OF SAVES IN TO MOVE + BEQ FINDTS +CALC: CLC ; AND FIND WHAT SECTOR TO START WITH + ADC SAVSIZ + BCC CALC1 + INC DBLOCK+HI +CALC1: DEX + BNE CALC + STA DBLOCK+LO ; IN THE FORM OF DBLOCKS + +FINDTS: LDA DBLOCK+LO + LDX DBLOCK+HI + LDY #1 + JSR SETTS ; GET TRACK & SECTOR + +SREADY: LDX #LOW INSM + LDA #HIGH INSM + LDY #INSML + JSR DLINE ; "INSERT SAVE DISK IN DRIVE X." + JSR RETURN ; "PRESS [RETURN] TO CONTINUE." + + LDA FAST ; FAST-READ (LC-A) + BEQ TRYOPN ; NO (LC-A) + JSR FOFF ; ELSE DISENGAGE (LC-A) + +TRYOPN: LDA TDRIVE ; TRY TO OPEN SPECIFIED DRIVE + CLC + ADC #8 + JSR DOPEN ; THE DEFAULT DRIVE + RTS ; CARRY SET IF ERROR + + ; --------------------- + ; "PRESS RETURN" PROMPT + ; --------------------- + +RETURN: LDX #LOW RTN + LDA #HIGH RTN + LDY #RTNL + JSR DLINE ; SHOW PROMPT + + ; ENTRY FOR QUIT/RESTART + +GETRET: JSR GETIN ; WAIT FOR [RETURN] + CMP #0 + BEQ GETRET ; GET A CHAR 1ST + AND #%01111111 ; CLEAR SHIFT + CMP #EOL + BEQ RETEX + JSR BOOP ; ACCEPT NO + JMP GETRET ; SUBSTITUTES! + +RETEX: RTS + +RTN: DB EOL + DB "Press [RETURN] to continue." + DB EOL,EOL +RTNL EQU $-RTN + + + ; --------- + ; SAVE GAME + ; --------- + +SAV: DB "Save Position" + DB EOL +SAVL EQU $-SAV + +SVING: 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 DLINE ; "SAVE POSITION" + + JSR PARAMS ; GET PARAMETERS + BCC DOSAVE ; ERROR IF CARRY SET + +BADSAV: JSR SIDE2 ; PROMPT FOR GAME DISK + JSR REFRSH ; TELL GAME TO REDO STATUS LINES + JMP RET0 ; AND FAIL + +DOSAVE: 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+LO ; MOVE [ZSP] + STA BUFSAV+2 + LDA ZSP+HI + STA BUFSAV+3 + LDA OLDZSP+LO + STA BUFSAV+4 + LDA OLDZSP+HI ; MOVE [OLDZSP] + STA BUFSAV+5 + + LDX #2 ; MOVE CONTENTS OF [ZPC] +ZPCSAV: LDA ZPC,X ; TO BYTES 5-7 + STA BUFSAV+6,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 + BCS BADSAV ; CATCH WRITE ERROR HERE + + ; WRITE CONTENTS OF Z-STACK TO DISK + +ZSOK: LDA #HIGH ZSTKBL ; POINT TO 1ST PAGE + STA DBUFF+HI + LDA #4 ; DO ALL 4 PAGES + STA L ; SET COUNTER +ZSOKLP: JSR PUTDSK ; WRITE THEM + BCS BADSAV + DEC L + BNE ZSOKLP + + ; 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 REFRSH ; SET TO REDO STATUS LINE + LDA TDRIVE ; IF SAVE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TPOSIT + STA GPOSIT + LDA #1 ; SET TO MARK + LDX #0 + JMP PUTBYT ; SUCCESS + + + ; ------------ + ; RESTORE GAME + ; ------------ + +RES: DB "Restore Position" + DB EOL +RESL EQU $-RES + +RSING: DB EOL + DB "Restoring position " +RSPOS: DB "* ..." + DB EOL +RSINGL EQU $-RSING + +ZREST: JSR SAVRES + + LDX #LOW RES + LDA #HIGH RES + LDY #RESL + JSR DLINE ; "RESTORE POSITION" + + JSR PARAMS ; GET PARAMETERS + BCS BADRES ; ERROR IF CARRY SET + + 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 GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + BCS BADRES + + 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 RGHT ; CONTINUE IF BOTH BYTES MATCH + + ; HANDLE INCORRECT SAVE DISK + +WRONG: LDX #31 ; RESTORE ALL SAVED LOCALS +WR0: LDA $0100,X + STA LOCALS,X + DEX + BPL WR0 + +BADRES: JSR SIDE2 ; PROMPT FOR GAME DISK + JSR REFRSH ; FIX STATUS LINE(S) + JMP RET0 ; AND FAIL + + ; CONTINUE RESTORE + +RGHT: LDA ZBEGIN+ZSCRIP ; SAVE BOTH FLAG BYTES + STA I+LO + LDA ZBEGIN+ZSCRIP+1 + STA I+HI + + LDA #HIGH ZSTKBL ; RETRIEVE OLD CONTENTS OF + STA DBUFF+HI ; Z-STACK + LDA #4 ; DO 4 PAGES + STA L ; SET COUNTER +ZROKLP: JSR GETRES ; GET 4 PAGES OF Z-STACK + BCC ZROKL1 + JMP DSKERR ; IF HERE, MIX OF GOOD & BAD SO DIE + +ZROKL1: DEC L + BNE ZROKLP + + LDA ZCODE + STA DBUFF+HI + JSR GETRES ; GET 1ST BLOCK OF PRELOAD + BCC ZROKL2 + JMP DSKERR + +ZROKL2: 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 GETRES ; FETCH THE REMAINDER + BCC LREST0 + JMP DSKERR + +LREST0: DEC I+LO ; OF THE PRELOAD + BNE LREST + + ; RESTORE THE STATE OF THE SAVED GAME + + LDA BUFSAV+2 ; RESTORE THE [ZSP] + STA ZSP+LO + LDA BUFSAV+3 + STA ZSP+HI + LDA BUFSAV+4 + STA OLDZSP+LO + LDA BUFSAV+5 ; AND THE [OLDZSP] + STA OLDZSP+HI + + LDX #2 ; RESTORE THE [ZPC] +RESZPC: LDA BUFSAV+6,X + STA ZPC,X + DEX + BPL RESZPC + + LDA #$18 ; SET SCREEN PARAMETERS + STA ZBEGIN+ZSCRWD ; IN CASE RESTORING + LDA #40 ; FROM C128 SAVE (1/20/87 LSD) + STA ZBEGIN+ZSCRWD+1 + + JSR SIDE2 ; PROMPT FOR GAME DISK + + LDA #' ' ; THIS IS A DISGUSTING KLUDGE + JSR CHROUT ; AS FAST CODE IS A PAIN, TURNING IT + LDA #EOL ; ON THEN IMMEDIATELY USING IT HERE + JSR CHROUT ; DOESN'T WORK SO BUFFER IT WITH CHROUT'S + + JSR VLDZPC ; MAKE VALID AFTER GET CORRECT DISK BACK + JSR REFRSH ; SET TO REDO STATUS LINE + + LDA TDRIVE ; IF RESTORE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TPOSIT ; NEXT TIME + STA GPOSIT + LDA #2 ; SET TO + LDX #0 + JMP PUTBYT ; SUCCESS + + END + diff --git a/64/lzip/zstring.asm b/64/lzip/zstring.asm new file mode 100644 index 0000000..0279b31 --- /dev/null +++ b/64/lzip/zstring.asm @@ -0,0 +1,434 @@ + 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 + ROL A + STA MPCH + ASL MPCL ; QUAD-ALIGN ADDRESS!(EZIP) + ROL MPCM + ROL MPCH + JMP VLDMPC +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 SETFWD ; 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 + JSR VLDMPC + JMP PZTOP ; CONTINUE INNOCENTLY + + +; ---------------------- +; RETURN CURRENT CHARSET +; ---------------------- + +GETSET: LDA TSET + BPL GS + LDA PSET + RTS +GS: LDY #$FF + STY TSET + RTS + + +; ------------------------- +; POINT [I] AT FWORD STRING +; ------------------------- + +SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS + ASL A + STA MPCL + LDA I+HI + ROL A + STA MPCM + LDA #0 + ROL A + STA MPCH + JMP VLDMPC + + +; ----------------- +; 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 + LDX #$08 ; WITH PAD CHARS ($05) +CZSL: STA OUT,X + DEX + BPL CZSL + LDA #9 ; 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 9 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 + STA OUT+2 ; MOVE CRUSHED Z-WORD + STX OUT+3 ; INTO PLACE + LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) + ASL A ; SHIFT BITS + ASL A + ASL A + ASL A + ROL OUT+6 ; ALONG WITH 7TH Z-CHAR + ASL A + ROL OUT+6 + ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR + STA OUT+5 ; SAVE HERE + LDA OUT+6 ; GRAB 7TH Z-CHAR + ORA #%10000000 ; SET HIGH BIT + STA OUT+4 ; MOVE CRUSHED Z-WORD 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 + diff --git a/64/zip/bugger.src b/64/zip/bugger.src new file mode 100644 index 0000000..5ddd1e9 --- /dev/null +++ b/64/zip/bugger.src @@ -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+960 + +DOBUG: PHA ; SAVE BREAKPOINT ID + LDA SHFLAG + AND #%00000100 ; CTRL KEY PRESSED? + BEQ BUGIT ; CONTINUE IF NOT + PLA ; ELSE RESET STACK + RTS ; AND EXIT + +BUGIT: LDX #39 +DBG0: LDA #SPACE + STA BUGLIN,X ; CLEAR SCREEN LINE + LDA #0 + STA COLRAM+960,X ; BLACKEN COLOR RAM + 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 BUFSIZ + JSR HEX + + LDX #34 ; CURSOR FOR [MPC] + LDA MPCH + JSR HEX + LDA MPCM + JSR HEX + LDA MPCL + JSR HEX + +WAITT: LDA SHFLAG ; LOGO KEY PRESSED? + AND #%00000010 + BEQ WAITT +LETGO: LDA SHFLAG ; WAIT FOR RELEASE + AND #%00000010 + BNE LETGO + 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 + diff --git a/64/zip/c64-d.zip b/64/zip/c64-d.zip new file mode 100644 index 0000000..f97e5c1 Binary files /dev/null and b/64/zip/c64-d.zip differ diff --git a/64/zip/c64zip-d.src b/64/zip/c64zip-d.src new file mode 100644 index 0000000..3830977 --- /dev/null +++ b/64/zip/c64zip-d.src @@ -0,0 +1,7195 @@ + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- EQUATES PAGE 1 + + + + 0000 ; -------------------------- + 0000 ; ZIP/6502 2.0 VERSION C + 0000 ; Z-CODE INTERPRETER PROGRAM + 0000 ; FOR COMMODORE 64 + 0000 ; -------------------------- + + 0000 ; INFOCOM, INC. + 0000 ; 55 WHEELER STREET + 0000 ; CAMBRIDGE, MA 02136 + + 0000 ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + + 0800 MSTART EQU $0800 ; START OF FREE PROGRAM RAM + 0003 ZEROPG EQU $03 ; START OF FREE Z-PAGE RAM + 008F ZPGTOP EQU $8F ; END OF FREE Z-PAGE RAM + + 0000 DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER + + 0000 ; ----------- + 0000 ; ERROR CODES + 0000 ; ----------- + + 0000 ; 00 -- INSUFFICIENT RAM + 0000 ; 01 -- ILLEGAL X-OP + 0000 ; 02 -- ILLEGAL 0-OP + 0000 ; 03 -- ILLEGAL 1-OP + 0000 ; 04 -- ILLEGAL 2-OP + 0000 ; 05 -- Z-STACK UNDERFLOW + 0000 ; 06 -- Z-STACK OVERFLOW + 0000 ; 07 -- ILLEGAL PROPERTY LENGTH (GETP) + 0000 ; 08 -- DIVISION BY ZERO + 0000 ; 09 -- ILLEGAL ARGUMENT COUNT (EQUAL?) + 0000 ; 10 -- ILLEGAL PROPERTY ID (PUTP) + 0000 ; 11 -- ILLEGAL PROPERTY LENGTH (PUTP) + 0000 ; 12 -- DISK ADDRESS OUT OF RANGE + 0000 ; 13 -- PARSER OVERFLOW + 0000 ; 14 -- DRIVE ACCESS + 0000 ; 15 -- Z-STACK DESTROYED + + INCLUD SHAKE.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- EQUATES PAGE 2 +--- CBM64 FAST DISK HANDSHAKE ROUTINES --- + + + 0000 ; ------------------ + 0000 ; 1541 DRIVE EQUATES + 0000 ; ------------------ + + 1800 PB EQU $1800 + 0000 JOBS EQU $00 + 0006 HDRS EQU $06 + 000A DATA EQU $0A + 000B INDEX EQU $0B + + 0001 DATIN EQU $01 + 0002 DATOUT EQU $02 + 0004 CLKIN EQU $04 + 0008 CLKOUT EQU $08 + 0080 ATNIN EQU $80 + + 0080 READ EQU $80 + 0090 WRITE EQU $90 + 00A0 VERIFY EQU $A0 + 00B0 SEEK EQU $B0 + 00B8 SECSEK EQU SEEK+8 + 00C0 BUMP EQU $C0 + 00D0 JUMPC EQU $D0 + 00E0 EXEC EQU $E0 + + 0300 BUF1 EQU $0300 + 0400 BUF2 EQU $0400 + 0500 BUF3 EQU $0500 + 0600 BUF4 EQU $0600 + 0700 BUF5 EQU $0700 + + 1C00 DSKCNT EQU $1C00 ; DISK CONTROLLER PORT ADDRESS + + 0500 ORG BUF3 + + 0500 AD0018 INIT0: LDA PB + 0503 29F5 AND #$FF-DATOUT-CLKOUT + 0505 8D0018 STA PB + + 0508 203C05 JSR CLK0 + + 050B AD001C CMDWT: LDA DSKCNT ; READ CONTROLLER + 050E 29F7 AND #%11110111 ; CLEAR BIT 3 + 0510 8D001C STA DSKCNT ; TO SHUT OFF THE DAMNED LITTLE RED LIGHT + + 0513 204405 JSR BYTGET ; GET TRACK ID (1-35) + 0516 AA TAX ; SAVE HERE + 0517 F019 BEQ CMDEND ; IF ZERO + 0519 C9FF CMP #$FF ; OR $FF, + 051B F015 BEQ CMDEND ; DISENGAGE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- EQUATES PAGE 3 +--- CBM64 FAST DISK HANDSHAKE ROUTINES --- + + 051D 8506 STA HDRS ; ELSE SET TRACK # + + 051F 204405 JSR BYTGET ; GET SECTOR # + 0522 8507 STA HDRS+1 ; AND SET IT + + 0524 AD001C LDA DSKCNT ; TURN BACK ON + 0527 0908 ORA #%00001000 ; THE STUPID LITTLE + 0529 8D001C STA DSKCNT ; RED LIGHT + + 052C 20BD05 JSR RDFILE ; GET THE DATA + + 052F 4C0B05 JMP CMDWT ; WAIT FOR NEXT TRACK/SECTOR + + 0532 60 CMDEND: RTS ; EXIT HARD LOOP + + 0533 AD0018 DEBNC: LDA PB ; WAIT FOR SERIAL LINE + 0536 CD0018 CMP PB ; TO SETTLE DOWN + 0539 D0F8 BNE DEBNC + 053B 60 RTS + + 053C 203305 CLK0: JSR DEBNC + 053F 2904 AND #CLKIN + 0541 D0F9 BNE CLK0 + 0543 60 RTS + + 0544 A980 BYTGET: LDA #$80 + 0546 850A STA DATA + + 0548 203305 GTBIT: JSR DEBNC + 054B A8 TAY + 054C 2904 AND #CLKIN + 054E F0F8 BEQ GTBIT + 0550 78 SEI + 0551 98 TYA + 0552 0902 ORA #DATOUT + 0554 8D0018 STA PB + + 0557 203C05 JSR CLK0 + 055A AD0018 LDA PB + 055D 29FD AND #$FF-DATOUT + 055F 8D0018 STA PB + + 0562 203305 GTBO0: JSR DEBNC + 0565 A8 TAY + 0566 2904 AND #CLKIN + 0568 F0F8 BEQ GTBO0 + 056A 203C05 JSR CLK0 + 056D 58 CLI + 056E 98 TYA + 056F 4A LSR A + 0570 660A ROR DATA + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- EQUATES PAGE 4 +--- CBM64 FAST DISK HANDSHAKE ROUTINES --- + + 0572 90D4 BCC GTBIT + + 0574 A50A LDA DATA + 0576 60 RTS + + 0577 A208 BYTSND: LDX #8 + 0579 850A STA DATA + + 057B AD0018 BITSND: LDA PB + 057E A8 TAY + 057F 2904 AND #CLKIN + 0581 F0F8 BEQ BITSND + 0583 98 TYA + 0584 0902 ORA #DATOUT + 0586 8D0018 STA PB + 0589 78 SEI + + 058A AD0018 BSND0: LDA PB + 058D A8 TAY + 058E 2904 AND #CLKIN + 0590 D0F8 BNE BSND0 + + 0592 98 BSND1: TYA + 0593 29FD AND #$FF-DATOUT + 0595 8D0018 STA PB + + 0598 AD0018 SPEED: LDA PB + 059B A8 TAY + 059C 2904 AND #CLKIN + 059E F0F8 BEQ SPEED + + 05A0 98 TYA + 05A1 460A LSR DATA + 05A3 9002 BCC BSND2 + 05A5 0902 ORA #DATOUT + + 05A7 8D0018 BSND2: STA PB + + 05AA AD0018 BSND3: LDA PB + 05AD A8 TAY + 05AE 2904 AND #CLKIN + 05B0 D0F8 BNE BSND3 + 05B2 98 TYA + 05B3 29FD AND #$FF-DATOUT + 05B5 8D0018 STA PB + + 05B8 CA DEX + 05B9 D0DD BNE SPEED + 05BB 58 CLI + 05BC 60 RTS + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- EQUATES PAGE 5 +--- CBM64 FAST DISK HANDSHAKE ROUTINES --- + + 05BD A980 RDFILE: LDA #READ + 05BF 8500 STA JOBS + + 05C1 A500 TSTDO3: LDA JOBS + 05C3 30FC BMI TSTDO3 + + 05C5 A900 TSTDO5: LDA #0 + 05C7 850B STA INDEX + + 05C9 A40B TSTDO4: LDY INDEX + 05CB B90003 LDA BUF1,Y + 05CE 207705 JSR BYTSND + 05D1 E60B INC INDEX + 05D3 D0F4 BNE TSTDO4 + 05D5 60 RTS + + 05D6 ; FILL REMAINDER OF SECTOR + 05D6 ; WITH JUNK + + 05D6 00000000 DB 0,0,0,0,0,0,0,0 + 05DE 00000000 DB 0,0,0,0,0,0,0,0 + 05E6 00000000 DB 0,0,0,0,0,0,0,0 + 05EE 00000000 DB 0,0,0,0,0,0,0,0 + 05F6 00000000 DB 0,0,0,0,0,0,0,0 + 05FE 0000 DB 0,0 + + END + INCLUD EQ.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- EQUATES PAGE 6 +--- MEMORY ORGANIZATION --- + + + 00FF TRUE EQU $FF + 0000 FALSE EQU 0 + 0000 LO EQU 0 + 0001 HI EQU 1 + + 0800 IOBUFF EQU MSTART ; 256-BYTE DISK BUFFER + 0900 ZSTAKL EQU MSTART+$100 ; Z-STACK LSBS + 0A00 ZSTAKH EQU MSTART+$200 ; Z-STACK MSBS + 0B00 PTABL EQU MSTART+$300 ; PAGING TABLE LSBS ($A0 BYTES) + 0BA0 PTABH EQU MSTART+$3A0 ; PAGING TABLE MSBS ($A0 BYTES) + 0C50 LRUMAP EQU MSTART+$450 ; TIMESTAMP MAP ($A0 BYTES) (BM 11/24/84) + 0D00 LOCALS EQU MSTART+$500 ; LOCAL VARIABLE STORAGE (32 BYTES) + 0D20 BUFSAV EQU MSTART+$520 ; I/O AUX BUFFER (80 BYTES) + + 0E00 ZIP EQU MSTART+$600 ; START OF EXECUTABLE CODE + 2A00 ZBEGIN EQU ZIP+$1C00 ; START OF Z-CODE (ASSUME 7K ZIP) + + 0600 ; --------------------- + 0600 ; Z-CODE HEADER OFFSETS + 0600 ; --------------------- + + 0000 ZVERS EQU 0 ; VERSION BYTE + 0001 ZMODE EQU 1 ; MODE SELECT BYTE + 0002 ZID EQU 2 ; GAME ID WORD + 0004 ZENDLD EQU 4 ; START OF NON-PRELOADED Z-CODE + 0006 ZGO EQU 6 ; EXECUTION ADDRESS + 0008 ZVOCAB EQU 8 ; START OF VOCABULARY TABLE + 000A ZOBJEC EQU 10 ; START OF OBJECT TABLE + 000C ZGLOBA EQU 12 ; START OF GLOBAL VARIABLE TABLE + 000E ZPURBT EQU 14 ; START OF "PURE" Z-CODE + 0010 ZSCRIP EQU 16 ; FLAG WORD + 0012 ZSERIA EQU 18 ; 3-WORD ASCII SERIAL NUMBER + 0018 ZFWORD EQU 24 ; START OF FWORDS TABLE + 001A ZLENTH EQU 26 ; LENGTH OF Z-PROGRAM IN WORDS + 001C ZCHKSM EQU 28 ; Z-CODE CHECKSUM WORD + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- EQUATES PAGE 7 +--- ZIP Z-PAGE VARIABLES --- + + + 0003 OPCODE EQU ZEROPG ; (BYTE) CURRENT OPCODE + 0004 NARGS EQU OPCODE+1 ; (BYTE) # ARGUMENTS + 0005 ARG1 EQU OPCODE+2 ; (WORD) ARGUMENT #1 + 0007 ARG2 EQU OPCODE+4 ; (WORD) ARGUMENT #2 + 0009 ARG3 EQU OPCODE+6 ; (WORD) ARGUMENT #3 + 000B ARG4 EQU OPCODE+8 ; (WORD) ARGUMENT #4 + 000D ABYTE EQU OPCODE+10 ; (BYTE) X-OP ARGUMENT BYTE + 000E ADEX EQU OPCODE+11 ; (BYTE) X-OP ARGUMENT INDEX + + 000F VALUE EQU OPCODE+12 ; (WORD) VALUE RETURN REGISTER + 0011 I EQU VALUE+2 ; (WORD) GEN-PURPOSE REGISTER #1 + 0013 J EQU VALUE+4 ; (WORD) GEN-PURPOSE REGISTER #2 + 0015 K EQU VALUE+6 ; (WORD) GEN-PURPOSE REGISTER #3 + + 0017 ZSP EQU VALUE+8 ; (BYTE) Z-STACK POINTER + 0018 OLDZSP EQU ZSP+1 ; (BYTE) OLD Z-STACK POINTER + + 0019 ZPC EQU ZSP+2 ; (3 BYTES) ZIP PROGRAM COUNTER + 0019 ZPCL EQU ZPC ; (BYTE) LOW 8 BITS OF [ZPC] + 001A ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] + 001B ZPCH EQU ZPC+2 ; (BYTE) HIGH BIT OF [ZPC] + 001C ZPCFLG EQU ZPC+3 ; (BYTE) FLAG: "TRUE" IF [ZPCPNT] VALID + 001D ZPCPNT EQU ZPC+4 ; (WORD) ABS POINTER TO CURRENT Z-PAGE + + 001F MPC EQU ZPC+6 ; (3 BYTES) MEMORY PROGRAM COUNTER + 001F MPCL EQU MPC ; (BYTE) LOW 8 BITS OF [MPC] + 0020 MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] + 0021 MPCH EQU MPC+2 ; (BYTE) HIGH BIT OF [MPC] + 0022 MPCFLG EQU MPC+3 ; (BYTE) FLAG: "TRUE" IF [MPCPNT] VALID + 0023 MPCPNT EQU MPC+4 ; (WORD) ABS POINTER TO CURRENT M-PAGE + + 0025 LRU EQU MPC+6 ; (BYTE) PAGING INDEX + 0026 ZCODE EQU LRU+1 ; (BYTE) 1ST ABSOLUTE PAGE OF PRELOAD + 0027 ZPURE EQU LRU+2 ; (BYTE) 1ST VIRTUAL PAGE OF "PURE" Z-CODE + 0028 PAGE0 EQU LRU+3 ; (BYTE) 1ST PAGE OF ACTUAL SWAPPING SPACE + 0029 PMAX EQU LRU+4 ; (BYTE) MAXIMUM # OF SWAPPING PAGES + 002A ZPAGE EQU LRU+5 ; (BYTE) CURRENT SWAPPING PAGE + 002B TARGET EQU LRU+6 ; (WORD) TARGET PAGE FOR SWAPPING + 002D STAMP EQU LRU+8 ; (BYTE) CURRENT TIMESTAMP (BM 11/24/84) + 002E SWAP EQU LRU+9 ; (BYTE) EARLIEST PAGE (BM 11/24/84) + + 002F GLOBAL EQU LRU+10 ; (WORD) GLOBAL VARIABLE POINTER + 0031 VOCAB EQU GLOBAL+2 ; (WORD) VOCAB TABLE POINTER + 0033 FWORDS EQU GLOBAL+4 ; (WORD) F-WORDS TABLE POINTER + 0035 OBJTAB EQU GLOBAL+6 ; (WORD) OBJECT TABLE POINTER + + 0600 ; Z-STRING MANIPULATION VARIABLES + + 0037 IN EQU GLOBAL+8 ; (6 BYTES) INPUT BUFFER + 003D OUT EQU IN+6 ; (6 BYTES) OUTPUT BUFFER + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- EQUATES PAGE 8 +--- ZIP Z-PAGE VARIABLES --- + + + 0043 SOURCE EQU OUT+6 ; (BYTE) SOURCE BUFFER POINTER + 0044 RESULT EQU SOURCE+1 ; (BYTE) RESULT TABLE POINTER + 0045 LINLEN EQU SOURCE+2 ; (BYTE) LENGTH OF CURRENT LINE + 0046 WRDLEN EQU SOURCE+3 ; (BYTE) LENGTH OF CURRENT WORD + 0047 ENTRY EQU SOURCE+4 ; (WORD) ADDR OF CURRENT RESULT ENTRY + 0049 NENTS EQU SOURCE+6 ; (WORD) # ENTRIES IN VOCAB TABLE + 004B ESIZE EQU SOURCE+8 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES + 004C PSET EQU SOURCE+9 ; (BYTE) PERMANENT CHARSET + 004D TSET EQU SOURCE+10 ; (BYTE) TEMPORARY CHARSET + 004E ZCHAR EQU SOURCE+11 ; (BYTE) CURRENT Z-CHAR + 004F OFFSET EQU SOURCE+12 ; (BYTE) F-WORD TABLE OFFSET + 0050 ZFLAG EQU SOURCE+13 ; (BYTE) Z-WORD ACCESS FLAG + 0051 ZWORD EQU SOURCE+14 ; (WORD) CURRENT Z-WORD + 0053 CONCNT EQU SOURCE+16 ; (BYTE) Z-STRING SOURCE COUNTER + 0054 CONIN EQU SOURCE+17 ; (BYTE) CONVERSION SOURCE INDEX + 0055 CONOUT EQU SOURCE+18 ; (BYTE) CONVERSION DEST INDEX + + 0056 QUOT EQU SOURCE+19 ; (WORD) QUOTIENT FOR DIVISION + 0058 REMAIN EQU QUOT+2 ; (WORD) REMAINDER FOR DIVISION + 005A MTEMP EQU QUOT+4 ; (WORD) MATH TEMPORARY REGISTER + 005C QSIGN EQU QUOT+6 ; (BYTE) SIGN OF QUOTIENT + 005D RSIGN EQU QUOT+7 ; (BYTE) SIGN OF REMAINDER + 005E DIGITS EQU QUOT+8 ; (BYTE) DIGIT COUNT FOR "PRINTN" + + 005F TIMEFL EQU QUOT+9 ; (BYTE) "TRUE" IF TIME MODE + 0060 LENGTH EQU TIMEFL+1 ; (BYTE) LENGTH OF LINE IN [LINBUF] + 0061 OLDLEN EQU TIMEFL+2 ; (BYTE) OLD LINE LENGTH + 0062 SCRIPT EQU TIMEFL+3 ; (BYTE) SCRIPT ENABLE FLAG + 0063 OLDX EQU TIMEFL+4 ; (BYTE) OLD CURSOR X + 0064 OLDY EQU TIMEFL+5 ; (BYTE) OLD CURSOR Y + 0065 LINCNT EQU TIMEFL+6 ; (BYTE) LINE COUNTER + 0066 LMAX EQU TIMEFL+7 ; (BYTE) MAX # LINES/SCREEN + + 0067 IOCHAR EQU TIMEFL+8 ; (BYTE) CHARACTER BUFFER + 0068 SLINE EQU IOCHAR+1 ; (BYTE) BORDERLINE FOR SPLIT + 0069 SPSTAT EQU IOCHAR+2 ; (BYTE) SPLIT SCREEN STATUS FLAG + 006A LFROM EQU IOCHAR+3 ; (WORD) "FROM" LINE ADDRESS + 006C LTO EQU IOCHAR+5 ; (WORD) "TO" LINE ADDRESS + 006E PSTAT EQU IOCHAR+7 ; (BYTE) PRINTER STATUS FLAG + 006F PRLEN EQU IOCHAR+8 ; (BYTE) SCRIPT LINE LENGTH + + 0070 DBLOCK EQU IOCHAR+9 ; (WORD) Z-BLOCK TO READ + 0072 DBUFF EQU DBLOCK+2 ; (WORD) RAM PAGE TO ACCESS (LSB = 0) + 0074 TRACK EQU DBLOCK+4 ; (BYTE) TARGET TRACK + 0075 SECTOR EQU DBLOCK+5 ; (BYTE) TARGET SECTOR + 0076 GPOSIT EQU DBLOCK+6 ; (BYTE) DEFAULT SAVE POSITION + 0077 GDRIVE EQU DBLOCK+7 ; (BYTE) DEFAULT SAVE DRIVE + 0078 TPOSIT EQU DBLOCK+8 ; (BYTE) TEMP SAVE POSITION + 0079 TDRIVE EQU DBLOCK+9 ; (BYTE) TEMP SAVE DRIVE + 007A DRIVE EQU DBLOCK+10 ; (BYTE) CURRENT DRIVE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- EQUATES PAGE 9 +--- ZIP Z-PAGE VARIABLES --- + + + 007B BLINK EQU DBLOCK+11 ; (WORD) CURSOR BLINK TIMER + + 007D DVD EQU DBLOCK+13 ; (WORD) DISK DIVIDEND + 007F DSOR EQU DBLOCK+15 ; (WORD) DISK DIVISOR + 0081 DTEMP EQU DBLOCK+17 ; (WORD) DISK TEMP VARIABLE + + END + + INCLUD HARDEQ.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 10 +--- HARDWARE EQUATES: CBM64 --- + + + 0600 ; --------- + 0600 ; CONSTANTS + 0600 ; --------- + + 0027 XSIZE EQU 39 ; X-SIZE OF SCREEN + 0018 YSIZE EQU 24 ; Y-SIZE OF SCREEN + + 000D EOL EQU $0D ; EOL CHAR + 0020 SPACE EQU $20 ; SPACE CHAR + 0014 BACKSP EQU $14 ; BACKSPACE + + 0600 ; --------- + 0600 ; ZERO-PAGE + 0600 ; --------- + + 0000 D6510 EQU $00 ; 6510 DATA DIRECTION REGISTER + 0001 R6510 EQU $01 ; 6510 I/O PORT + 0002 FAST EQU $02 ; FAST-READ AVAILABLE FLAG + 0091 STKEY EQU $91 ; STOP KEY FLAG + 009D MSGFLG EQU $9D ; KERNAL MESSAGE CONTROL FLAG + 00A2 TIME EQU $A2 ; SYSTEM JIFFY TIMER + 00C5 LSTX EQU $C5 ; LAST KEY PRESSED + 00C6 NDX EQU $C6 ; # CHARS IN KEYBOARD BUFFER + 00C7 RVS EQU $C7 ; REVERSE CHARACTER FLAG + 00CB SFDX EQU $CB ; CURRENT KEYPRESS + 00CC BLNSW EQU $CC ; CURSOR BLINK SWITCH + 00D3 PNTR EQU $D3 ; CURSOR COLUMN IN LOGICAL LINE + 00D6 TBLX EQU $D6 ; CURRENT CURSOR ROW + 00D9 LDTB1 EQU $D9 ; 25-BYTE LINE LINK TABLE + 00F5 KEYTAB EQU $F5 ; KEYBOARD DECODE TABLE VECTOR + + 00FB FDATA EQU $FB ; FAST-READ DATA BUFFER + 00FC FINDEX EQU $FC ; FAST-READ BUFFER INDEX + 00FD FASTEN EQU $FD ; FAST-READ ENABLED FLAG + + 0600 ; ----------- + 0600 ; PAGES 2 & 3 + 0600 ; ----------- + + 0200 LBUFF EQU $0200 ; 89-BYTE LINE BUFFER + 0277 KEYD EQU $0277 ; KEYBOARD QUEUE + 0286 COLOR EQU $0286 ; FOREGROUND COLOR FOR TEXT + 0288 HIBASE EQU $0288 ; TOP PAGE OF SCREEN RAM + 0289 XMAX EQU $0289 ; MAXIMUM KEYBOARD QUEUE SIZE + 028A RPTFLG EQU $028A ; KEY REPEAT FLAG + 028D SHFLAG EQU $028D ; SHIFT KEY FLAG + 028F KEYLOG EQU $028F ; VECTOR TO KEY-TABLE SETUP ROUTINE + 0291 MODE EQU $0291 ; CHARSET MODE SWITCH + 0314 CINV EQU $0314 ; SYSTEM 60HZ IRQ VECTOR + 0316 CBINV EQU $0316 ; BRK INSTRUCTION VECTOR + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 11 +--- HARDWARE EQUATES: CBM64 --- + + 0318 NMINV EQU $0318 ; NMI INTERRUPT VECTOR + 0340 SPRT13 EQU $0340 ; SPRITE #13 DATA + 0380 SPRT14 EQU $0380 ; SPRITE #14 DATA + 03C0 SPRT15 EQU $03C0 ; SPRITE #15 DATA + + 0340 CURSOR EQU SPRT13 ; CURSOR RAM + 0400 SCREEN EQU $0400 ; SCREEN RAM + D800 COLRAM EQU $D800 ; COLOR RAM + 07F8 SPT0 EQU $07F8 ; SPRITE #0 PNTR + 07F9 SPT1 EQU $07F9 ; SPRITE #1 PNTR + 07FA SPT2 EQU $07FA ; SPRITE #2 PNTR + 07FB SPT3 EQU $07FB ; SPRITE #3 PNTR + 07FC SPT4 EQU $07FC ; SPRITE #4 PNTR + 07FD SPT5 EQU $07FD ; SPRITE #5 PNTR + 07FE SPT6 EQU $07FE ; SPRITE #6 PNTR + 07FF SPT7 EQU $07FF ; SPRITE #7 PNTR + + 0600 ; ------ + 0600 ; VIC-II + 0600 ; ------ + + 0600 ; SPRITE POSITION REGISTERS + + D000 SP0X EQU $D000 ; SPRITE #0 X-POS + D001 SP0Y EQU $D001 ; SPRITE #0 Y-POS + D002 SP1X EQU $D002 ; SPRITE #1 X-POS + D003 SP1Y EQU $D003 ; SPRITE #1 Y-POS + D004 SP2X EQU $D004 ; SPRITE #2 X-POS + D005 SP2Y EQU $D005 ; SPRITE #2 Y-POS + D006 SP3X EQU $D006 ; SPRITE #3 X-POS + D007 SP3Y EQU $D007 ; SPRITE #3 Y-POS + D008 SP4X EQU $D008 ; SPRITE #4 X-POS + D009 SP4Y EQU $D009 ; SPRITE #4 Y-POS + D00A SP5X EQU $D00A ; SPRITE #5 X-POS + D00B SP5Y EQU $D00B ; SPRITE #5 Y-POS + D00C SP6X EQU $D00C ; SPRITE #6 X-POS + D00D SP6Y EQU $D00D ; SPRITE #6 Y-POS + D00E SP7X EQU $D00E ; SPRITE #7 X-POS + D00F SP7Y EQU $D00F ; SPRITE #7 Y-POS + D010 MSIGX EQU $D010 ; HIGH BITS OF SPRITE X-POSITIONS + + 0600 ; VARIOUS CONTROL REGISTERS + + D011 SCROLY EQU $D011 ; Y-SCROLL & VIDEO CONTROL + D012 RASTER EQU $D012 ; RASTER COMPARE + D015 SPENA EQU $D015 ; SPRITE ENABLE + D016 SCROLX EQU $D016 ; X-SCROLL & VIDEO CONTROL + D017 YXPAND EQU $D017 ; SPRITE Y-EXPANSION + D018 VMCSB EQU $D018 ; MEMORY CONTROL + D019 VICIRQ EQU $D019 ; CHIP INTERRUPT FLAGS + D01A IRQMSK EQU $D01A ; IRQ MASKS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 12 +--- HARDWARE EQUATES: CBM64 --- + + D01B SPBGPR EQU $D01B ; SPRITE/FOREGROUND PRIORITY + D01C SPMC EQU $D01C ; MULTICOLOR SPRITE CONTROL + D01D XXPAND EQU $D01D ; SPRITE X-EXPANSION + + 0600 ; COLOR REGISTERS + + D020 EXTCOL EQU $D020 ; BORDER COLOR + D021 BGCOLO EQU $D021 ; BACKGROUND COLOR + D027 SP0COL EQU $D027 ; SPRITE #0 COLOR + D028 SP1COL EQU $D028 ; SPRITE #1 COLOR + D029 SP2COL EQU $D029 ; SPRITE #2 COLOR + D02A SP3COL EQU $D02A ; SPRITE #3 COLOR + D02B SP4COL EQU $D02B ; SPRITE #4 COLOR + D02C SP5COL EQU $D02C ; SPRITE #5 COLOR + D02D SP6COL EQU $D02D ; SPRITE #6 COLOR + D02E SP7COL EQU $D02E ; SPRITE #7 COLOR + + 0600 ; --- + 0600 ; SID + 0600 ; --- + + 0600 ; VOICE #1 REGISTERS + + D400 FRELO1 EQU $D400 ; FREQ + D401 FREHI1 EQU $D401 ; FREQ HIGH BIT + D402 PWLO1 EQU $D402 ; PULSE WIDTH + D403 PWHI1 EQU $D403 ; PULSE WIDTH HIGH NIBBLE + D404 VCREG1 EQU $D404 ; CONTROL + D405 ATDCY1 EQU $D405 ; ATTACK/DECAY + D406 SUREL1 EQU $D406 ; SUSTAIN/RELEASE + + 0600 ; VOICE #2 REGISTERS + + D407 FRELO2 EQU $D407 ; FREQ + D408 FREHI2 EQU $D408 ; FREQ HIGH BIT + D409 PWLO2 EQU $D409 ; PULSE WIDTH + D40A PWHI2 EQU $D40A ; PULSE WIDTH HIGH NIBBLE + D40B VCREG2 EQU $D40B ; CONTROL + D40C ATDCY2 EQU $D40C ; ATTACK/DECAY + D40D SUREL2 EQU $D40D ; SUSTAIN/RELEASE + + 0600 ; VOICE #3 REGISTERS + + D40E FRELO3 EQU $D40E ; FREQ + D40F FREHI3 EQU $D40F ; FREQ HIGH BIT + D410 PWLO3 EQU $D410 ; PULSE WIDTH + D411 PWHI3 EQU $D411 ; PULSE WIDTH HIGH NIBBLE + D412 VCREG3 EQU $D412 ; VOICE CONTROL + D413 ATDCY3 EQU $D413 ; ATTACK/DECAY + D414 SUREL3 EQU $D414 ; SUSTAIN/RELEASE + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 13 +--- HARDWARE EQUATES: CBM64 --- + + 0600 ; MISCELLANEOUS REGISTERS + + D415 CUTLO EQU $D415 ; FILTER CUTOFF, LOW BITS + D416 CUTHI EQU $D416 ; FILTER CUTOFF, HIGH BYTE + D417 RESON EQU $D417 ; RESONANCE CONTROL + D418 SIGVOL EQU $D418 ; VOLUME/FILTER CONTROL + D41B RAND EQU $D41B ; RANDOM NUMBER + DD00 CI2PRA EQU $DD00 ; DATA PORT A + + 0600 ; ------------------- + 0600 ; KERNAL JUMP VECTORS + 0600 ; ------------------- + + FFC6 CHKIN EQU $FFC6 ; OPEN CHANNEL FOR INPUT + FFC9 CHKOUT EQU $FFC9 ; OPEN CHANNEL FOR OUTPUT + FFCF CHRIN EQU $FFCF ; INPUT CHARACTER FROM CHANNEL + FFD2 CHROUT EQU $FFD2 ; OUTPUT CHARACTER TO CHANNEL + FF81 CINT EQU $FF81 ; INIT SCREEN EDITOR + FFE7 CLALL EQU $FFE7 ; CLOSE ALL CHANNELS & FILES + FFC3 CLOSE EQU $FFC3 ; CLOSE A FILE + FFCC CLRCHN EQU $FFCC ; CLEAR CHANNEL + FFE4 GETIN EQU $FFE4 ; GET CHAR FROM KEYBOARD QUEUE + FF84 IOINIT EQU $FF84 ; INIT I/O + FFC0 OPEN EQU $FFC0 ; OPEN A FILE + FFF0 PLOT EQU $FFF0 ; READ/SET CURSOR POSITION + FF87 RAMTAS EQU $FF87 ; INIT RAM + FFB7 READST EQU $FFB7 ; READ I/O STATUS + FF9F SCNKEY EQU $FF9F ; SCAN KEYBOARD + FFBA SETLFS EQU $FFBA ; SET FILE ATTRIBUTES + FF90 SETMSG EQU $FF90 ; SET KERNAL MESSAGES + FFBD SETNAM EQU $FFBD ; SET FILENAME + + END + INCLUD COLD.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 14 +--- MACHINE COLDSTART: CBM64 --- + + + 0E00 ORG ZIP + + 0E00 ; --------- + 0E00 ; COLDSTART + 0E00 ; --------- + + 0E00 A501 COLD: LDA R6510 + 0E02 29FE AND #%11111110 ; SWITCH OUT BASIC ROM + 0E04 8501 STA R6510 ; KERNAL ROM & I/O ENABLED + + 0E06 A901 LDA #1 ; WHITE + 0E08 8D8602 STA COLOR ; TEXT + 0E0B A90C LDA #12 ; GRAY + 0E0D 8D20D0 STA EXTCOL ; BORDER + 0E10 8D21D0 STA BGCOLO ; AND BACKGROUND + + 0E13 A90E LDA #$0E + 0E15 20D2FF JSR CHROUT ; USE UPPER/LOWER CHARS + 0E18 A980 LDA #$80 ; PROHIBIT FURTHER + 0E1A 8D9102 STA MODE ; CHARSET CHANGES + + 0E1D A900 LDA #0 + 0E1F 859D STA MSGFLG ; DISABLE KERNAL MESSAGES + 0E21 8D0322 STA SFLAG ; NO PREVIOUS SCRIPTING (BM 5/14/85) + + 0E24 ; INITIALIZE THE SOUND SYSTEM + + 0E24 A21C LDX #$1C ; CLEAR + 0E26 A900 LDA #0 ; ALL + 0E28 9D00D4 CLD0: STA FRELO1,X ; SID REGISTERS + 0E2B CA DEX + 0E2C 10FA BPL CLD0 + + 0E2E A902 LDA #2 ; SET VOICE #1 + 0E30 8D02D4 STA PWLO1 ; PULSE WIDTH + 0E33 A908 LDA #8 ; FOR A + 0E35 8D03D4 STA PWHI1 ; 50% DUTY CYCLE + + 0E38 A980 LDA #%10000000 ; DISABLE OUTPUT + 0E3A 8D18D4 STA SIGVOL ; FROM VOICE #3 + + 0E3D A9EE LDA #$EE + 0E3F 8D0ED4 STA FRELO3 ; SET VOICE #3 TO + 0E42 8D0FD4 STA FREHI3 ; AN AMUSING FREQUENCY + + 0E45 A980 LDA #%10000000 ; SPECIFY NOISY WAVEFORM + 0E47 8D12D4 STA VCREG3 ; FOR RANDOMNESS + + 0E4A ; INITIALIZE THE SPRITE CURSOR + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 15 +--- MACHINE COLDSTART: CBM64 --- + + 0E4A A23F LDX #63 ; CLEAR SPRITE #13 RAM + 0E4C A900 LDA #0 + 0E4E 9D4003 CN0: STA CURSOR,X + 0E51 CA DEX + 0E52 10FA BPL CN0 + + 0E54 8D1DD0 STA XXPAND ; NORMAL HORIZONTAL + 0E57 8D17D0 STA YXPAND ; AND VERTICAL SPRITE SIZE + 0E5A 8D1BD0 STA SPBGPR ; MAXIMUM SPRITE PRIORITY + 0E5D 8D1CD0 STA SPMC ; HI-RES SPRITES + 0E60 8D27D0 STA SP0COL ; BLACK CURSOR + + 0E63 4C7F0E JMP WARM1 + + 0E66 ; --------------- + 0E66 ; WARMSTART ENTRY + 0E66 ; --------------- + + 0E66 54686520 SLOAD: DB "The story is loading ..." + 0E7E 0D DB EOL + 0019 SLOADL EQU $-SLOAD + + 0E7F D8 WARM1: CLD + 0E80 A2FF LDX #$FF + 0E82 9A TXS ; RESET MACHINE STACK + 0E83 20E7FF JSR CLALL ; CLOSE EVERYTHING + + 0E86 200E23 JSR CLS ; CLEAR SCREEN, ETC. + + 0E89 A008 LDY #8 ; POSITION "STORY LOADING" MESSAGE + 0E8B A20B LDX #11 ; AT (8,11) + 0E8D 18 CLC + 0E8E 20F0FF JSR PLOT + + 0E91 A266 LDX #LOW SLOAD + 0E93 A90E LDA #HIGH SLOAD + 0E95 A019 LDY #SLOADL + 0E97 20F021 JSR DLINE ; "THE STORY IS LOADING ..." + + 0E9A A908 LDA #8 ; MAKE BOOT DRIVE + 0E9C 209D27 JSR DOPEN ; AND OPEN IT + + 0E9F A502 LDA FAST ; FAST DISK? + 0EA1 F003 BEQ WARM2 ; NO, CONTINUE + 0EA3 20C128 JSR FINIT ; ELSE INIT FAST DISK + + 0EA6 ; FALL THROUGH TO ZIP WARMSTART AT "WARM2" + + END + + INCLUD WARM.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 16 +--- WARMSTART ROUTINE --- + + + 0EA6 ; ------------- + 0EA6 ; ZIP WARMSTART + 0EA6 ; ------------- + + 0EA6 A900 WARM2: LDA #0 ; CLEAR ALL Z-PAGE VARIABLES + 0EA8 A203 LDX #ZEROPG + 0EAA 9500 ST0: STA 0,X + 0EAC E8 INX + 0EAD E08F CPX #ZPGTOP + 0EAF 90F9 BCC ST0 + + 0EB1 ; INIT THE PAGING TABLES + + 0EB1 AA TAX ; = 0 + 0EB2 A9FF LDA #$FF + 0EB4 9D000B ST1A: STA PTABL,X + 0EB7 9DA00B STA PTABH,X + 0EBA E8 INX + 0EBB E0A0 CPX #$A0 + 0EBD 90F5 BCC ST1A + + 0EBF ; INIT THE TIMESTAMP MAP (BM 11/24/84)\ + + 0EBF A900 LDA #0 + 0EC1 AA TAX + 0EC2 9D500C ST1B: STA LRUMAP,X + 0EC5 E8 INX + 0EC6 E0A0 CPX #$A0 + 0EC8 90F8 BCC ST1B + + 0ECA E617 INC ZSP ; INIT Z-STACK POINTERS + 0ECC E618 INC OLDZSP ; TO "1" + 0ECE E62D INC STAMP ; INIT TIMESTAMP (BM 11/24/84) + + 0ED0 ; GRAB THE FIRST BLOCK OF PRELOAD + + 0ED0 A92A LDA #HIGH ZBEGIN ; MSB OF PRELOAD START ADDRESS + 0ED2 8526 STA ZCODE ; FREEZE IT HERE + 0ED4 8573 STA DBUFF+HI ; LSB IS ALWAYS ZERO + 0ED6 208A23 JSR GETDSK ; [DBLOCK] SET TO Z-BLOCK 0 + + 0ED9 ; EXTRACT GAME DATA FROM Z-CODE HEADER + + 0ED9 AE042A LDX ZBEGIN+ZENDLD ; MSB OF ENDLOAD POINTER + 0EDC E8 INX ; ADD 1 TO GET + 0EDD 8627 STX ZPURE ; 1ST "PURE" PAGE OF Z-CODE + + 0EDF 8A TXA ; ADD START PAGE OF PRELOAD + 0EE0 18 CLC ; TO CALC ABSOLUTE START ADDRESS + 0EE1 6526 ADC ZCODE ; OF PAGING SPACE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 17 +--- WARMSTART ROUTINE --- + + 0EE3 8528 STA PAGE0 + + 0EE5 203B1E JSR MEMTOP ; RETURNS TOP RAM PAGE IN [A] + 0EE8 38 SEC + 0EE9 E528 SBC PAGE0 ; SUBTRACT ADDRESS OF PAGING SPACE + 0EEB F002 BEQ NORAM + 0EED B005 BCS SETNP ; ERROR IF NOT ENOUGH RAM + + 0EEF ; *** ERROR #0 -- INSUFFICIENT RAM *** + + 0EEF A900 NORAM: LDA #0 + 0EF1 4CC41D JMP ZERROR + + 0EF4 C9A0 SETNP: CMP #$A0 ; DON'T ALLOW MORE THAN $A0 PAGES + 0EF6 9002 BCC SETA0 + 0EF8 A9A0 LDA #$A0 + 0EFA 8529 SETA0: STA PMAX ; SET # SWAPPING PAGES + + 0EFC AD012A LDA ZBEGIN+ZMODE + 0EFF 0920 ORA #%00100000 ; ENABLE SPLIT-SCREEN + 0F01 8D012A STA ZBEGIN+ZMODE + + 0F04 2902 AND #%00000010 ; ISOLATE STATUS-FORMAT BIT + 0F06 855F STA TIMEFL ; 0=SCORE, NZ=TIME + + 0F08 AD0C2A LDA ZBEGIN+ZGLOBA ; GET MSB OF GLOBAL TABLE ADDR + 0F0B 18 CLC ; CONVERT TO + 0F0C 6526 ADC ZCODE ; ABSOLUTE ADDRESS + 0F0E 8530 STA GLOBAL+HI + 0F10 AD0D2A LDA ZBEGIN+ZGLOBA+1 ; LSB NEEDN'T CHANGE + 0F13 852F STA GLOBAL+LO + + 0F15 AD182A LDA ZBEGIN+ZFWORD ; DO SAME FOR FWORDS TABLE + 0F18 18 CLC + 0F19 6526 ADC ZCODE + 0F1B 8534 STA FWORDS+HI + 0F1D AD192A LDA ZBEGIN+ZFWORD+1 ; NO CHANGE FOR LSB + 0F20 8533 STA FWORDS+LO + + 0F22 AD082A LDA ZBEGIN+ZVOCAB ; NOW DO VOCABULARY TABLE + 0F25 18 CLC + 0F26 6526 ADC ZCODE + 0F28 8532 STA VOCAB+HI + 0F2A AD092A LDA ZBEGIN+ZVOCAB+1 ; LSB SAME + 0F2D 8531 STA VOCAB+LO + + 0F2F AD0A2A LDA ZBEGIN+ZOBJEC ; NOT TO MENTION + 0F32 18 CLC ; THE OBJECT TABLE + 0F33 6526 ADC ZCODE + 0F35 8536 STA OBJTAB+HI + 0F37 AD0B2A LDA ZBEGIN+ZOBJEC+1 ; LSB SAME + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 18 +--- WARMSTART ROUTINE --- + + 0F3A 8535 STA OBJTAB+LO + + 0F3C ; FETCH THE REST OF THE PRELOAD + + 0F3C A570 LDPRE: LDA DBLOCK+LO ; CHECK CURRENT BLOCK # + 0F3E C527 CMP ZPURE ; LOADED LAST PRELOAD PAGE YET? + 0F40 B006 BCS WARMEX ; YES, TIME TO PLAY! + 0F42 208A23 JSR GETDSK ; ELSE GRAB NEXT Z-BLOCK + 0F45 4C3C0F JMP LDPRE + + 0F48 AD062A WARMEX: LDA ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + 0F4B 851A STA ZPCM ; MSB + 0F4D AD072A LDA ZBEGIN+ZGO+1 ; AND LSB + 0F50 8519 STA ZPCL ; HIGH BIT ALREADY ZEROED + + 0F52 E662 INC SCRIPT ; ENABLE SCRIPTING + 0F54 AD112A LDA ZBEGIN+ZSCRIP+1 ; STUFF IN THE + 0F57 0D0322 ORA SFLAG ; PREVIOUS SCRIPT MODE + 0F5A 8D112A STA ZBEGIN+ZSCRIP+1 ; (BM 5/14/85) + + 0F5D 200E23 JSR CLS ; CLEAR SCREEN, DISABLE SPLIT + + 0F60 ; ... AND FALL INTO MAIN LOOP + + END + INCLUD MAIN.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 19 +--- MAIN LOOP --- + + + 0F60 A900 MLOOP: LDA #0 + 0F62 8504 STA NARGS ; RESET # ARGUMENTS + 0F64 20E419 JSR NEXTPC ; GET NEXT INSTRUCTION INTO [A] + 0F67 8503 STA OPCODE ; SAVE IT HERE + + 0F69 IF DEBUG + 0F69 STA MBYTE + 0F69 LDA #0 ; BREAKPOINT #0 + 0F69 JSR DOBUG + 0F69 LDA MBYTE + 0F69 ENDIF + + 0F69 ; DECODE AN OPCODE + + 0F69 AA TAX ; SET FLAGS + 0F6A 3003 BMI DC0 ; IF POSITIVE, + 0F6C 4C2A10 JMP OP2 ; IT'S A 2-OP + + 0F6F C9B0 DC0: CMP #$B0 + 0F71 B003 BCS DC1 + 0F73 4CFB0F JMP OP1 ; OR MAYBE A 1-OP + + 0F76 C9C0 DC1: CMP #$C0 + 0F78 B003 BCS OPEXT + 0F7A 4CEC0F JMP OP0 ; PERHAPS A 0-OP + + 0F7D ; -------------- + 0F7D ; HANDLE AN X-OP + 0F7D ; -------------- + + 0F7D 20E419 OPEXT: JSR NEXTPC ; GRAB THE ARGUMENT ID BYTE + 0F80 850D STA ABYTE ; HOLD IT HERE + + 0F82 A200 LDX #0 + 0F84 860E STX ADEX ; INIT ARGUMENT INDEX + 0F86 F006 BEQ OPX1 ; JUMP TO TOP OF LOOP + + 0F88 A50D OPX0: LDA ABYTE ; GET ARG BYTE + 0F8A 0A ASL A ; SHIFT NEXT 2 ARG BITS + 0F8B 0A ASL A ; INTO BITS 7 & 6 + 0F8C 850D STA ABYTE ; HOLD FOR LATER + + 0F8E 29C0 OPX1: AND #%11000000 ; MASK OUT GARBAGE BITS + 0F90 D006 BNE OPX2 + 0F92 207610 JSR GETLNG ; 00 = LONG IMMEDIATE + 0F95 4CA90F JMP OPXNXT + + 0F98 C940 OPX2: CMP #%01000000 ; IS IT A SHORT IMMEDIATE? + 0F9A D006 BNE OPX3 ; NO, KEEP GUESSING + 0F9C 207210 JSR GETSHT ; 01 = SHORT IMMEDIATE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 20 +--- MAIN LOOP --- + + 0F9F 4CA90F JMP OPXNXT + + 0FA2 C980 OPX3: CMP #%10000000 ; LAST TEST + 0FA4 D017 BNE OPX4 ; 11 = NO MORE ARGUMENTS + 0FA6 208A10 JSR GETVAR ; 10 = VARIABLE + + 0FA9 A60E OPXNXT: LDX ADEX ; RETRIEVE ARGUMENT INDEX + 0FAB A50F LDA VALUE+LO ; GRAB LSB OF VALUE + 0FAD 9505 STA ARG1+LO,X ; STORE IN ARGUMENT TABLE + 0FAF A510 LDA VALUE+HI ; GRAB MSB OF VALUE + 0FB1 9506 STA ARG1+HI,X ; STORE THAT, TOO + + 0FB3 E604 INC NARGS ; UPDATE ARGUMENT COUNTER + + 0FB5 E8 INX + 0FB6 E8 INX + 0FB7 860E STX ADEX ; UPDATE INDEX + 0FB9 E008 CPX #8 ; DONE 4 ARGUMENTS YET? + 0FBB 90CB BCC OPX0 ; NO, GET SOME MORE + + 0FBD ; ALL X-OP ARGUMENTS READY + + 0FBD A503 OPX4: LDA OPCODE ; IS THIS + 0FBF C9E0 CMP #$E0 ; AN EXTENDED 2-OP? + 0FC1 B003 BCS DOXOP ; NO, IT'S A REAL X-OP + 0FC3 4C5310 JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + + 0FC6 A234 DOXOP: LDX #LOW OPTX ; GET ADDR OF X-OP TABLE + 0FC8 A012 LDY #HIGH OPTX ; INTO [X/Y] + 0FCA 291F AND #%00011111 ; ISOLATE OP ID BITS + 0FCC C90C CMP #NOPSX ; IS IT A LEGAL X-OP? + 0FCE 9005 BCC DODIS ; YUP; TIME TO DISPATCH IT + + 0FD0 ; *** ERROR #1 -- ILLEGAL X-OP *** + + 0FD0 A901 LDA #1 + 0FD2 4CC41D JMP ZERROR + + 0FD5 ; --------------- + 0FD5 ; OPCODE DISPATCH + 0FD5 ; --------------- + + 0FD5 ; ENTRY: MASKED OPCODE INDEX IN [A] + 0FD5 ; OP-TABLE ADDR IN X/Y (LSB/MSB) + + 0FD5 8611 DODIS: STX I+LO ; SAVE TABLE ADDRESS + 0FD7 8412 STY I+HI ; IN A POINTER + + 0FD9 0A ASL A ; WORD-ALIGN THE OP INDEX + 0FDA A8 TAY + 0FDB B111 LDA (I),Y ; GET LSB OF DISPATCH ADDRESS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 21 +--- MAIN LOOP --- + + 0FDD 8DE70F STA GO+LO ; INSTALL AS JSR OPERAND + 0FE0 C8 INY + 0FE1 B111 LDA (I),Y ; SAME WITH MSB + 0FE3 8DE80F STA GO+HI + + 0FE6 20 DB $20 ; 6502 "JSR" OPCODE + 0FE7 0000 GO: DW $0000 ; DUMMY OPERAND BYTES + + 0FE9 4C600F JMP MLOOP ; GO BACK FOR ANOTHER OPCODE + + 0FEC ; ------------- + 0FEC ; HANDLE A 0-OP + 0FEC ; ------------- + + 0FEC A2C6 OP0: LDX #LOW OPT0 ; GET 0-OP TABLE ADDR + 0FEE A011 LDY #HIGH OPT0 ; INTO [X/Y] + 0FF0 290F AND #%00001111 ; ISOLATE 0-OP ID BITS + 0FF2 C90E CMP #NOPS0 ; OUT OF RANGE? + 0FF4 90DF BCC DODIS ; NO, DISPATCH IT + + 0FF6 ; *** ERROR #2 -- ILLEGAL 0-OP *** + + 0FF6 A902 LDA #2 + 0FF8 4CC41D JMP ZERROR + + 0FFB ; ------------- + 0FFB ; HANDLE A 1-OP + 0FFB ; ------------- + + 0FFB 2930 OP1: AND #%00110000 ; ISOLATE ARGUMENT BITS + 0FFD D006 BNE OP1A + 0FFF 207610 JSR GETLNG ; 00 = LONG IMMEDIATE + 1002 4C1610 JMP OP1EX + + 1005 C910 OP1A: CMP #%00010000 ; TEST AGAIN + 1007 D006 BNE OP1B + 1009 207210 JSR GETSHT ; 01 = SHORT IMMEDIATE + 100C 4C1610 JMP OP1EX + + 100F C920 OP1B: CMP #%00100000 ; ONE MORE TEST + 1011 D012 BNE BADOP1 ; UNDEFINED STATE! + 1013 208A10 JSR GETVAR ; 10 = VARIABLE + + 1016 206710 OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] + 1019 A2E2 LDX #LOW OPT1 ; GET ADDR OF 1-OP TABLE + 101B A011 LDY #HIGH OPT1 ; INTO [X/Y] + 101D A503 LDA OPCODE ; RESTORE OPCODE + 101F 290F AND #%00001111 ; ISOLATE OP ID BITS + 1021 C910 CMP #NOPS1 ; IF WITHIN RANGE, + 1023 90B0 BCC DODIS ; EXECUTE THE 1-OP + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 22 +--- MAIN LOOP --- + + 1025 ; *** ERROR #3 -- ILLEGAL 1-OP *** + + 1025 A903 BADOP1: LDA #3 + 1027 4CC41D JMP ZERROR + + 102A ; ------------- + 102A ; HANDLE A 2-OP + 102A ; ------------- + + 102A 2940 OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT + 102C D006 BNE OP2A + 102E 207210 JSR GETSHT ; 0 = SHORT IMMEDIATE + 1031 4C3710 JMP OP2B + 1034 208A10 OP2A: JSR GETVAR ; 1 = VARIABLE + 1037 206710 OP2B: JSR V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] + + 103A A503 LDA OPCODE ; RESTORE OPCODE BYTE + 103C 2920 AND #%00100000 ; ISOLATE 2ND ARG BIT + 103E D006 BNE OP2C + 1040 207210 JSR GETSHT ; 0 = SHORT IMMEDIATE + 1043 4C4910 JMP OP2D + 1046 208A10 OP2C: JSR GETVAR ; 1 = VARIABLE + 1049 A50F OP2D: LDA VALUE+LO ; MOVE 2ND [VALUE] + 104B 8507 STA ARG2+LO ; INTO [ARG2] + 104D A510 LDA VALUE+HI + 104F 8508 STA ARG2+HI + 1051 E604 INC NARGS ; UPDATE ARGUMENT COUNT + + 1053 ; EXECUTE A 2-OP OR EXTENDED 2-OP + + 1053 A202 OP2EX: LDX #LOW OPT2 ; LSB OF DISPATCH TABLE + 1055 A012 LDY #HIGH OPT2 ; MSB + 1057 A503 LDA OPCODE ; RESTORE OPCODE BYTE + 1059 291F AND #%00011111 ; ISOLATE OP ID BITS + 105B C919 CMP #NOPS2 + 105D B003 BCS BADOP2 ; ERROR IF OUT OF RANGE + 105F 4CD50F JMP DODIS ; ELSE DISPATCH + + 1062 ; *** ERROR #4 -- ILLEGAL 2-OP **** + + 1062 A904 BADOP2: LDA #4 + 1064 4CC41D JMP ZERROR + + 1067 ; -------------------------------------- + 1067 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] + 1067 ; -------------------------------------- + + 1067 A50F V2A1: LDA VALUE+LO + 1069 8505 STA ARG1+LO + 106B A510 LDA VALUE+HI + 106D 8506 STA ARG1+HI + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 23 +--- MAIN LOOP --- + + 106F E604 INC NARGS + 1071 60 RTS + + END + INCLUD SUBS.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 24 +--- OPCODE SUPPORT SUBROUTINES --- + + + 1072 ; ----------------------- + 1072 ; FETCH A SHORT IMMEDIATE + 1072 ; ----------------------- + + 1072 A900 GETSHT: LDA #0 ; MSB IS ZERO + 1074 F003 BEQ GETV ; FETCH LSB FROM Z-CODE + + 1076 ; ---------------------- + 1076 ; FETCH A LONG IMMEDIATE + 1076 ; ---------------------- + + 1076 20E419 GETLNG: JSR NEXTPC ; GRAB MSB + + 1079 8510 GETV: STA VALUE+HI + 107B 20E419 JSR NEXTPC ; GRAB LSB + 107E 850F STA VALUE+LO + 1080 60 RTS + + 1081 ; ---------------- + 1081 ; FETCH A VARIABLE + 1081 ; ---------------- + + 1081 ; FROM INSIDE AN OPCODE (VARIABLE ID IN [A]) + + 1081 AA VARGET: TAX ; IF NON-ZERO, + 1082 D00B BNE GETVR1 ; ACCESS A VARIABLE + + 1084 20B010 JSR POPVAL ; ELSE PULL VAR OFF Z-STACK + 1087 4CC610 JMP PSHVAL ; WITHOUT ALTERING STACK + + 108A ; FROM THE MAIN LOOP (VARIABLE ID IN Z-CODE) + + 108A 20E419 GETVAR: JSR NEXTPC ; GRAB VAR-TYPE BYTE + 108D F021 BEQ POPVAL ; VALUE IS ON Z-STACK + + 108F ; IS VARIABLE LOCAL OR GLOBAL? + + 108F C910 GETVR1: CMP #$10 ; IF >= 16, + 1091 B010 BCS GETVRG ; IT'S GLOBAL + + 1093 ; HANDLE A LOCAL VARIABLE + + 1093 38 GETVRL: SEC + 1094 E901 SBC #1 ; FORM A ZERO-ALIGNED + 1096 0A ASL A ; WORD INDEX + 1097 AA TAX ; INTO THE [LOCALS] TABLE + + 1098 BD000D LDA LOCALS+LO,X ; GRAB LSB + 109B 850F STA VALUE+LO + 109D BD010D LDA LOCALS+HI,X ; AND MSB + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 25 +--- OPCODE SUPPORT SUBROUTINES --- + + 10A0 8510 STA VALUE+HI + 10A2 60 RTS + + 10A3 ; HANDLE A GLOBAL VARIABLE + + 10A3 201411 GETVRG: JSR GVCALC ; GET ADDRESS OF GLOBAL INTO [I] + 10A6 B111 LDA (I),Y ; MSB OF GLOBAL ([Y] = 0) + 10A8 8510 STA VALUE+HI + 10AA C8 INY ; = 1 + 10AB B111 LDA (I),Y ; LSB OF GLOBAL + 10AD 850F STA VALUE+LO ; SAVE IT + 10AF 60 RTS ; AND WE'RE DONE + + 10B0 ; ---------------------------------- + 10B0 ; POP Z-STACK INTO [VALUE] AND [X/A] + 10B0 ; ---------------------------------- + + 10B0 C617 POPVAL: DEC ZSP + 10B2 F00D BEQ UNDER ; UNDERFLOW IF ZERO! + + 10B4 A417 LDY ZSP ; READ STACK POINTER + 10B6 BE0009 LDX ZSTAKL,Y ; GRAB LSB OF STACK VALUE + 10B9 860F STX VALUE+LO ; GIVE TO [VALUE] + 10BB B9000A LDA ZSTAKH,Y ; ALSO GRAB MSB + 10BE 8510 STA VALUE+HI ; A SIMILAR FATE + 10C0 60 RTS + + 10C1 ; *** ERROR #5 -- Z-STACK UNDERFLOW *** + + 10C1 A905 UNDER: LDA #5 + 10C3 4CC41D JMP ZERROR + + 10C6 ; ----------------------- + 10C6 ; PUSH [VALUE] TO Z-STACK + 10C6 ; ----------------------- + + 10C6 A60F PSHVAL: LDX VALUE+LO + 10C8 A510 LDA VALUE+HI + + 10CA ; --------------------- + 10CA ; PUSH [X/A] TO Z-STACK + 10CA ; --------------------- + + 10CA A417 PUSHXA: LDY ZSP ; READ STACK POINTER + 10CC 99000A STA ZSTAKH,Y ; PUSH MSB IN [A] + 10CF 8A TXA + 10D0 990009 STA ZSTAKL,Y ; AND LSB IN [X] + + 10D3 E617 INC ZSP ; UPDATE Z-STACK POINTER + 10D5 F001 BEQ OVER ; OVERFLOW IF ZEROED! + 10D7 60 RTS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 26 +--- OPCODE SUPPORT SUBROUTINES --- + + + 10D8 ; *** ERROR #6 -- Z-STACK OVERFLOW *** + + 10D8 A906 OVER: LDA #6 + 10DA 4CC41D JMP ZERROR + + 10DD ; -------------- + 10DD ; RETURN A VALUE + 10DD ; -------------- + + 10DD ; FROM WITHIN AN OPCODE (VARIABLE ID IN [A]) + + 10DD AA VARPUT: TAX ; IF ZERO, + 10DE D013 BNE PUTVR1 + + 10E0 C617 DEC ZSP ; FLUSH TOP WORD OFF STACK + 10E2 D0E2 BNE PSHVAL ; AND REPLACE WITH [VALUE] + 10E4 F0DB BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + + 10E6 ; RETURN A ZERO + + 10E6 A900 RET0: LDA #0 + + 10E8 ; RETURN BYTE IN [A] + + 10E8 850F PUTBYT: STA VALUE+LO + 10EA A900 LDA #0 + 10EC 8510 STA VALUE+HI ; CLEAR MSB + + 10EE ; RETURN [VALUE] + + 10EE 20E419 PUTVAL: JSR NEXTPC ; GET VARIABLE ID BYTE + 10F1 F0D3 BEQ PSHVAL ; [VALUE] GOES TO Z-STACK + + 10F3 ; LOCAL OR GLOBAL VARIABLE? + + 10F3 C910 PUTVR1: CMP #$10 ; IF >= 16, + 10F5 B010 BCS PUTVLG ; IT'S GLOBAL + + 10F7 ; PUT A LOCAL VARIABLE + + 10F7 38 PUTVLL: SEC + 10F8 E901 SBC #1 ; FORM A ZERO-ALIGNED + 10FA 0A ASL A ; WORD INDEX + 10FB AA TAX ; INTO THE [LOCALS] TABLE + + 10FC A50F LDA VALUE+LO ; GRAB LSB + 10FE 9D000D STA LOCALS+LO,X ; SAVE IN LOCAL TABLE + 1101 A510 LDA VALUE+HI ; DO SAME TO + 1103 9D010D STA LOCALS+HI,X ; MSB + 1106 60 RTS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 27 +--- OPCODE SUPPORT SUBROUTINES --- + + + 1107 ; RETURN A GLOBAL VARIABLE + + 1107 201411 PUTVLG: JSR GVCALC + 110A A510 LDA VALUE+HI ; GET MSB + 110C 9111 STA (I),Y ; STORE AS 1ST BYTE ([Y] = 0) + 110E C8 INY ; = 1 + 110F A50F LDA VALUE+LO ; NOW GET LSB + 1111 9111 STA (I),Y ; STORE AS 2ND BYTE + 1113 60 RTS + + 1114 ; ----------------------- + 1114 ; CALC GLOBAL WORD OFFSET + 1114 ; ----------------------- + + 1114 ; ENTRY: VAR-ID BYTE (16-255) IN [A] + 1114 ; EXIT: ABSOLUTE ADDRESS OF GLOBAL VAR IN [I] + 1114 ; [Y] = 0 FOR INDEXING + + 1114 38 GVCALC: SEC + 1115 E910 SBC #$10 ; FORM A ZERO-ALIGNED INDEX + 1117 A000 LDY #0 ; MAKE SURE MSB OF OFFSET AND [Y] + 1119 8412 STY I+HI ; ARE CLEARED + + 111B 0A ASL A ; MULTIPLY OFFSET BY 2 + 111C 2612 ROL I+HI ; TO WORD-ALIGN IT + + 111E 18 CLC ; ADD OFFSET TO ADDR OF GLOBAL TABLE + 111F 652F ADC GLOBAL+LO ; TO FORM THE ABSOLUTE + 1121 8511 STA I+LO ; ADDRESS OF THE + 1123 A512 LDA I+HI ; DESIRED GLOBAL VARIABLE + 1125 6530 ADC GLOBAL+HI ; STORE ADDRESS BACK IN [VAL] + 1127 8512 STA I+HI ; AS A POINTER + + 1129 60 WCEX: RTS + + 112A ; --------------- + 112A ; PREDICATE FAILS + 112A ; --------------- + + 112A 20E419 PREDF: JSR NEXTPC ; GET 1ST BRANCH BYTE + 112D 100C BPL PREDB ; DO BRANCH IF BIT 7 OFF + + 112F ; ----------------------- + 112F ; IGNORE PREDICATE BRANCH + 112F ; ----------------------- + + 112F ; ENTRY: 1ST BRANCH BYTE IN [A] + + 112F 2940 PREDNB: AND #%01000000 ; TEST BIT 6 + 1131 D0F6 BNE WCEX ; SHORT BRANCH IF SET + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 28 +--- OPCODE SUPPORT SUBROUTINES --- + + 1133 4CE419 JMP NEXTPC ; ELSE SKIP OVER 2ND BRANCH BYTE + + 1136 ; ------------------ + 1136 ; PREDICATE SUCCEEDS + 1136 ; ------------------ + + 1136 20E419 PREDS: JSR NEXTPC ; GET 1ST BRANCH BYTE + 1139 10F4 BPL PREDNB ; DON'T BRANCH IF BIT 7 CLEAR + + 113B ; -------------------------- + 113B ; PERFORM A PREDICATE BRANCH + 113B ; -------------------------- + + 113B ; ENTRY: 1ST PRED BYTE IN [A] + + 113B AA PREDB: TAX ; SAVE HERE + 113C 2940 AND #%01000000 ; LONG OR SHORT BRANCH? + 113E F00B BEQ PREDLB ; LONG IF BIT 6 IS CLEAR + + 1140 ; HANDLE A SHORT BRANCH + + 1140 8A TXA ; RESTORE PRED BYTE + 1141 293F AND #%00111111 ; FORM SHORT OFFSET + 1143 850F STA VALUE+LO ; USE AS LSB OF BRANCH OFFSET + 1145 A900 LDA #0 + 1147 8510 STA VALUE+HI ; MSB OF OFFSET IS ZERO + 1149 F013 BEQ PREDB1 ; DO THE BRANCH + + 114B ; HANDLE A LONG BRANCH + + 114B 8A PREDLB: TXA ; RESTORE 1ST PRED BYTE + 114C 293F AND #%00111111 ; FORM MSB OF OFFSET + + 114E AA TAX ; SAVE HERE FOR REFERENCE + + 114F 2920 AND #%00100000 ; CHECK SIGN OF 14-BIT VALUE + 1151 F004 BEQ DOB2 ; POSITIVE IF ZERO, SO USE [X] + + 1153 8A TXA ; ELSE RESTORE BYTE + 1154 09E0 ORA #%11100000 ; EXTEND THE SIGN BIT + 1156 AA TAX ; BACK HERE FOR STORAGE + + 1157 8610 DOB2: STX VALUE+HI + 1159 20E419 JSR NEXTPC ; FETCH LSB OF 14-BIT OFFSET + 115C 850F STA VALUE+LO + + 115E ; BRANCH TO Z-ADDRESS IN [VALUE] + + 115E A510 PREDB1: LDA VALUE+HI ; CHECK MSB OF OFFSET + 1160 D00E BNE PREDB3 ; DO BRANCH IF NZ + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 29 +--- OPCODE SUPPORT SUBROUTINES --- + + 1162 A50F LDA VALUE+LO ; IF LSB IS NON-ZERO, + 1164 D003 BNE PREDB2 ; MAKE SURE IT ISN'T 1 + 1166 4C5712 JMP ZRFALS ; ELSE DO AN "RFALSE" + + 1169 C901 PREDB2: CMP #1 ; IF OFFSET = 1 + 116B D003 BNE PREDB3 + 116D 4C4C12 JMP ZRTRUE ; DO AN "RTRUE" + + 1170 ; ENTRY POINT FOR "JUMP" + + 1170 20AA11 PREDB3: JSR DECVAL ; SUBTRACT 2 FROM THE OFFSET + 1173 20AA11 JSR DECVAL ; IN [VALUE] + + 1176 A900 LDA #0 ; CLEAR THE MSB + 1178 8512 STA I+HI ; OF [I] + + 117A A510 LDA VALUE+HI ; MAKE MSB OF OFFSET + 117C 8511 STA I+LO ; THE LSB OF [I] + 117E 0A ASL A ; EXTEND THE SIGN OF OFFSET + 117F 2612 ROL I+HI ; INTO MSB OF [I] + + 1181 A50F LDA VALUE+LO ; GET LSB OF OFFSET + 1183 18 CLC + 1184 6519 ADC ZPCL ; ADD LOW 8 BITS OF ZPC + 1186 9006 BCC PREDB5 ; IF OVERFLOWED, + + 1188 E611 INC I+LO ; UPDATE UPPER 9 BITS + 118A D002 BNE PREDB5 + 118C E612 INC I+HI + + 118E 8519 PREDB5: STA ZPCL ; UPDATE ZPC + + 1190 A511 LDA I+LO ; IF UPPER 9 BITS ARE ZERO, + 1192 0512 ORA I+HI ; NO NEED TO CHANGE PAGES + 1194 F013 BEQ ZNOOP + + 1196 A511 LDA I+LO ; ELSE CALC NEW UPPER BITS + 1198 18 CLC + 1199 651A ADC ZPCM + 119B 851A STA ZPCM + + 119D A512 LDA I+HI + 119F 651B ADC ZPCH + 11A1 2901 AND #%00000001 ; USE ONLY BIT 0 + 11A3 851B STA ZPCH + + 11A5 A900 LDA #0 + 11A7 851C STA ZPCFLG ; [ZPC] NO LONGER VALID + + 11A9 ; FALL THROUGH ... + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 30 +--- OPCODE SUPPORT SUBROUTINES --- + + 11A9 ; ---- + 11A9 ; NOOP + 11A9 ; ---- + + 11A9 60 ZNOOP: RTS + + 11AA ; ----------------- + 11AA ; DECREMENT [VALUE] + 11AA ; ----------------- + + 11AA A50F DECVAL: LDA VALUE+LO + 11AC 38 SEC + 11AD E901 SBC #1 + 11AF 850F STA VALUE+LO + 11B1 B002 BCS DVX + 11B3 C610 DEC VALUE+HI + 11B5 60 DVX: RTS + + 11B6 ; ----------------- + 11B6 ; INCREMENT [VALUE] + 11B6 ; ----------------- + + 11B6 E60F INCVAL: INC VALUE+LO + 11B8 D002 BNE IVX + 11BA E610 INC VALUE+HI + 11BC 60 IVX: RTS + + 11BD ; ---------------------- + 11BD ; MOVE [ARG1] TO [VALUE] + 11BD ; ---------------------- + + 11BD A505 A12VAL: LDA ARG1+LO + 11BF 850F STA VALUE+LO + 11C1 A506 LDA ARG1+HI + 11C3 8510 STA VALUE+HI + 11C5 60 RTS + + END + INCLUD DISPATCH.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 31 +--- OPCODE DISPATCH TABLES --- + + + 11C6 ; 0-OPS + + 11C6 4C12 OPT0: DW ZRTRUE ; 0 + 11C8 5712 DW ZRFALS ; 1 + 11CA 5B12 DW ZPRI ; 2 + 11CC 7812 DW ZPRR ; 3 + 11CE A911 DW ZNOOP ; 4 + 11D0 6426 DW ZSAVE ; 5 + 11D2 FF26 DW ZREST ; 6 + 11D4 091E DW ZSTART ; 7 + 11D6 8112 DW ZRSTAK ; 8 + 11D8 B010 DW POPVAL ; 9 + 11DA E51D DW ZQUIT ; 10 + 11DC 831E DW ZCRLF ; 11 + 11DE 081F DW ZUSL ; 12 + 11E0 8712 DW ZVER ; 13 + + 000E NOPS0 EQU 14 ; NUMBER OF 0-OPS + + 11E2 ; 1-OPS + + 11E2 E512 OPT1: DW ZZERO ; 0 + 11E4 EE12 DW ZNEXT ; 1 + 11E6 F712 DW ZFIRST ; 2 + 11E8 0A13 DW ZLOC ; 3 + 11EA 1613 DW ZPTSIZ ; 4 + 11EC 3313 DW ZINC ; 5 + 11EE 3E13 DW ZDEC ; 6 + 11F0 4B13 DW ZPRB ; 7 + 11F2 2510 DW BADOP1 ; 8 (UNDEFINED) + 11F4 5913 DW ZREMOV ; 9 + 11F6 9B13 DW ZPRD ; 10 + 11F8 B813 DW ZRET ; 11 + 11FA 0014 DW ZJUMP ; 12 + 11FC 0614 DW ZPRINT ; 13 + 11FE 1414 DW ZVALUE ; 14 + 1200 1C14 DW ZBCOM ; 15 + + 0010 NOPS1 EQU 16 ; NUMBER OF 1-OPS + + 1202 ; 2-OPS + + 1202 6210 OPT2: DW BADOP2 ; 0 (UNDEFINED) + 1204 CA16 DW ZEQUAL ; 1 + 1206 2C14 DW ZLESS ; 2 + 1208 4014 DW ZGRTR ; 3 + 120A 3214 DW ZDLESS ; 4 + 120C 4B14 DW ZIGRTR ; 5 + 120E 7B14 DW ZIN ; 6 + 1210 8B14 DW ZBTST ; 7 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE PAGE 32 +--- OPCODE DISPATCH TABLES --- + + 1212 9E14 DW ZBOR ; 8 + 1214 AA14 DW ZBAND ; 9 + 1216 B614 DW ZFSETP ; 10 + 1218 CA14 DW ZFSET ; 11 + 121A DD14 DW ZFCLR ; 12 + 121C F414 DW ZSET ; 13 + 121E 0115 DW ZMOVE ; 14 + 1220 2B15 DW ZGET ; 15 + 1222 3B15 DW ZGETB ; 16 + 1224 5815 DW ZGETP ; 17 + 1226 A015 DW ZGETPT ; 18 + 1228 CD15 DW ZNEXTP ; 19 + 122A EC15 DW ZADD ; 20 + 122C F915 DW ZSUB ; 21 + 122E 0616 DW ZMUL ; 22 + 1230 2A16 DW ZDIV ; 23 + 1232 3416 DW ZMOD ; 24 + + 0019 NOPS2 EQU 25 ; NUMBER OF 2-OPS + + 1234 ; X-OPS + + 1234 FD16 OPTX: DW ZCALL ; 0 + 1236 9217 DW ZPUT ; 1 + 1238 A017 DW ZPUTB ; 2 + 123A BB17 DW ZPUTP ; 3 + 123C 6718 DW ZREAD ; 4 + 123E EC17 DW ZPRC ; 5 + 1240 F117 DW ZPRN ; 6 + 1242 3618 DW ZRAND ; 7 + 1244 5818 DW ZPUSH ; 8 + 1246 5F18 DW ZPOP ; 9 + 1248 7A22 DW ZSPLIT ; 10 + 124A BE22 DW ZSCRN ; 11 + + 000C NOPSX EQU 12 ; NUMBER OF X-OPS + + END + + INCLUD OPS0.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 33 +--- 0-OPS --- + + + 124C ; ----- + 124C ; RTRUE + 124C ; ----- + + 124C ; SIMULATE A "RETURN 1" + + 124C A201 ZRTRUE: LDX #1 + + 124E A900 ZRT0: LDA #0 + + 1250 8605 ZRT1: STX ARG1+LO ; GIVE TO + 1252 8506 STA ARG1+HI ; [ARG1] + 1254 4CB813 JMP ZRET ; AND DO THE RETURN + + 1257 ; ------ + 1257 ; RFALSE + 1257 ; ------ + + 1257 ; SIMULATE A "RETURN 0" + + 1257 A200 ZRFALS: LDX #0 + 1259 F0F3 BEQ ZRT0 + + 125B ; ------ + 125B ; PRINTI + 125B ; ------ + + 125B ; PRINT Z-STRING FOLLOWING THE OPCODE + + 125B A51B ZPRI: LDA ZPCH ; MOVE [ZPC] INTO [MPC] + 125D 8521 STA MPCH + 125F A51A LDA ZPCM + 1261 8520 STA MPCM + 1263 A519 LDA ZPCL + 1265 851F STA MPCL + + 1267 A900 LDA #0 + 1269 8522 STA MPCFLG ; [MPC] NO LONGER VALID + + 126B 200D1B JSR PZSTR ; PRINT THE Z-STRING AT [MPC] + + 126E A205 LDX #5 ; COPY STATE OF [MPC] + 1270 B51F PRIL: LDA MPC,X ; INTO [ZPC] + 1272 9519 STA ZPC,X + 1274 CA DEX + 1275 10F9 BPL PRIL + 1277 60 RTS + + 1278 ; ------ + 1278 ; PRINTR + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 34 +--- 0-OPS --- + + 1278 ; ------ + + 1278 ; DO A "PRINTI," FOLLOWED BY "CRLF" AND "RTRUE" + + 1278 205B12 ZPRR: JSR ZPRI + 127B 20831E JSR ZCRLF + 127E 4C4C12 JMP ZRTRUE + + 1281 ; ------ + 1281 ; RSTACK + 1281 ; ------ + + 1281 ; "RETURN" WITH VALUE ON STACK + + 1281 20B010 ZRSTAK: JSR POPVAL ; GET VALUE INTO [X/A] + 1284 4C5012 JMP ZRT1 ; AND GIVE IT TO "RETURN" + + 1287 ; ------ + 1287 ; VERIFY + 1287 ; ------ + + 1287 ; VERIFY GAME CODE ON DISK + + 1287 202F1E ZVER: JSR VERNUM ; DISPLAY ZIP VERSION NUMBER + + 128A A203 LDX #3 + 128C A900 LDA #0 + 128E 9513 ZVR: STA J+LO,X ; CLEAR [J], [K] + 1290 951F STA MPC,X ; [MPC] AND [MPCFLG] + 1292 CA DEX + 1293 10F9 BPL ZVR + + 1295 A940 LDA #64 ; POINT [MPC] TO Z-ADDRESS $00040 + 1297 851F STA MPCL ; 1ST 64 BYTES AREN'T CHECKED + + 1299 AD1A2A LDA ZBEGIN+ZLENTH ; GET LENGTH OF Z-CODE + 129C 8512 STA I+HI ; IN WORDS + 129E AD1B2A LDA ZBEGIN+ZLENTH+1 ; FIRST MSB + 12A1 8511 STA I+LO ; THEN LSB + + 12A3 0611 ASL I+LO ; CONVERT Z-CODE LENGTH + 12A5 2612 ROL I+HI ; TO # BYTES + 12A7 2615 ROL K+LO ; TOP BIT IN [K+LO] + + 12A9 A916 LDA #K+HI ; PATCH THE "GETBYT" ROUTINE + 12AB 8D251A STA PATCH ; TO USE [K+HI]=0 INSTEAD OF [ZPURE] + + 12AE 201A1A VSUM: JSR GETBYT ; GET A Z-BYTE INTO [A] + 12B1 18 CLC + 12B2 6513 ADC J+LO ; ADD IT TO SUM + 12B4 8513 STA J+LO ; IN [J] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 35 +--- 0-OPS --- + + 12B6 9002 BCC VSUM0 + 12B8 E614 INC J+HI + + 12BA A51F VSUM0: LDA MPCL ; END OF Z-CODE YET? + 12BC C511 CMP I+LO ; CHECK LSB + 12BE D0EE BNE VSUM + + 12C0 A520 LDA MPCM ; MIDDLE BYTE + 12C2 C512 CMP I+HI + 12C4 D0E8 BNE VSUM + + 12C6 A521 LDA MPCH ; AND HIGH BIT + 12C8 C515 CMP K+LO + 12CA D0E2 BNE VSUM + + 12CC A927 LDA #ZPURE ; UNPATCH "GETBYT" + 12CE 8D251A STA PATCH + + 12D1 AD1D2A LDA ZBEGIN+ZCHKSM+1 ; GET LSB OF CHECKSUM + 12D4 C513 CMP J+LO ; DOES IT MATCH? + 12D6 D00A BNE BADVER ; NO, PREDICATE FAILS + + 12D8 AD1C2A LDA ZBEGIN+ZCHKSM ; ELSE CHECK MSB + 12DB C514 CMP J+HI ; LOOK GOOD? + 12DD D003 BNE BADVER ; IF MATCHED, + 12DF 4C3611 JMP PREDS ; GAME IS OKAY + + 12E2 4C2A11 BADVER: JMP PREDF + + END + INCLUD OPS1.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 36 +--- 1-OPS --- + + + 12E5 ; ----- + 12E5 ; ZERO? + 12E5 ; ----- + + 12E5 ; [ARG1] = 0? + + 12E5 A505 ZZERO: LDA ARG1+LO + 12E7 0506 ORA ARG1+HI + 12E9 F01C BEQ PFINE + + 12EB 4C2A11 PYUCK: JMP PREDF + + 12EE ; ----- + 12EE ; NEXT? + 12EE ; ----- + + 12EE ; RETURN "NEXT" POINTER IN OBJECT [ARG1]; + 12EE ; FAIL IF LAST AND RETURN ZERO + + 12EE A505 ZNEXT: LDA ARG1+LO + 12F0 20181D JSR OBJLOC ; GET OBJECT ADDR INTO [I] + 12F3 A005 LDY #5 ; POINT TO "NEXT" SLOT + 12F5 D007 BNE FIRST1 + + 12F7 ; ------ + 12F7 ; FIRST? + 12F7 ; ------ + + 12F7 ; RETURN "FIRST" POINTER IN OBJECT [ARG1]; + 12F7 ; FAIL IF LAST AND RETURN ZERO + + 12F7 A505 ZFIRST: LDA ARG1+LO + 12F9 20181D JSR OBJLOC ; GET OBJECT ADDR INTO [I] + 12FC A006 LDY #6 ; POINT TO "FIRST" SLOT + + 12FE B111 FIRST1: LDA (I),Y ; GET CONTENTS OF SLOT + 1300 20E810 JSR PUTBYT ; PASS IT TO VARIABLE + + 1303 A50F LDA VALUE+LO ; EXAMINE THE VALUE JUST "PUT" + 1305 F0E4 BEQ PYUCK ; FAIL IF IT WAS ZERO + + 1307 4C3611 PFINE: JMP PREDS ; ELSE REJOICE + + 130A ; --- + 130A ; LOC + 130A ; --- + + 130A ; RETURN THE OBJECT CONTAINING OBJECT [ARG1]; + 130A ; RETURN ZERO IF NONE + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 37 +--- 1-OPS --- + + 130A A505 ZLOC: LDA ARG1+LO + 130C 20181D JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + 130F A004 LDY #4 ; POINT TO "LOC" SLOT + 1311 B111 LDA (I),Y ; GET THE BYTE + 1313 4CE810 JMP PUTBYT ; AND SHIP IT OUT + + 1316 ; ------ + 1316 ; PTSIZE + 1316 ; ------ + + 1316 ; RETURN LENGTH OF PROP TABLE [ARG1] IN BYTES + + 1316 A506 ZPTSIZ: LDA ARG1+HI ; MOVE ABS ADDR OF + 1318 18 CLC ; THE PROP TABLE + 1319 6526 ADC ZCODE ; INTO [I] + 131B 8512 STA I+HI + + 131D A505 LDA ARG1+LO ; DECREMENT THE + 131F 38 SEC ; ADDRESS + 1320 E901 SBC #1 ; WHILE MOVING LSB + 1322 8511 STA I+LO + 1324 B002 BCS PTZ0 + 1326 C612 DEC I+HI + + 1328 A000 PTZ0: LDY #0 ; GET THE LENGTH + 132A 20621D JSR PROPL ; OF PROPERTY AT [I] INTO [A] + + 132D 18 CLC + 132E 6901 ADC #1 ; INCREMENT RESULT + 1330 4CE810 JMP PUTBYT ; AND RETURN IT + + 1333 ; --- + 1333 ; INC + 1333 ; --- + + 1333 ; INCREMENT VARIABLE [ARG1] + + 1333 A505 ZINC: LDA ARG1+LO + 1335 208110 JSR VARGET ; FETCH VARIABLE INTO [VALUE] + 1338 20B611 JSR INCVAL ; INCREMENT IT + 133B 4C4613 JMP ZD0 + + 133E ; --- + 133E ; DEC + 133E ; --- + + 133E ; DECREMENT VARIABLE [ARG1] + + 133E A505 ZDEC: LDA ARG1+LO + 1340 208110 JSR VARGET ; FETCH VAR INTO [VALUE] + 1343 20AA11 JSR DECVAL ; DECREMENT IT + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 38 +--- 1-OPS --- + + + 1346 A505 ZD0: LDA ARG1+LO ; PUT RESULT BACK + 1348 4CDD10 JMP VARPUT ; INTO THE SAME VARIABLE + + 134B ; ------ + 134B ; PRINTB + 134B ; ------ + + 134B ; PRINT Z-STRING AT [ARG1] + + 134B A505 ZPRB: LDA ARG1+LO + 134D 8511 STA I+LO + 134F A506 LDA ARG1+HI + 1351 8512 STA I+HI + + 1353 20E11A JSR SETWRD ; MOVE Z-ADDR TO [MPC] + 1356 4C0D1B JMP PZSTR ; AND PRINT + + 1359 ; ------ + 1359 ; REMOVE + 1359 ; ------ + + 1359 ; MOVE OBJECT [ARG1] INTO PSEUDO-OBJECT #0 + + 1359 A505 ZREMOV: LDA ARG1+LO ; GET SOURCE OBJECT ADDR + 135B 20181D JSR OBJLOC ; INTO [I] + + 135E A511 LDA I+LO ; COPY THE SOURCE ADDR + 1360 8513 STA J+LO ; INTO [J] + 1362 A512 LDA I+HI ; FOR LATER REFERENCE + 1364 8514 STA J+HI + + 1366 A004 LDY #4 ; POINT TO "LOC" SLOT + 1368 B111 LDA (I),Y ; GET THE DATA + 136A F02E BEQ REMVEX ; SCRAM IF NO OBJECT + + 136C 20181D JSR OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [I] + 136F A006 LDY #6 ; POINT TO "FIRST" SLOT + 1371 B111 LDA (I),Y ; GRAB DATA + 1373 C505 CMP ARG1+LO ; IS THIS THE FIRST? + 1375 D009 BNE REMVC1 ; NO, KEEP SEARCHING + + 1377 A005 LDY #5 ; ELSE COPY SOURCE'S "NEXT" SLOT + 1379 B113 LDA (J),Y + 137B C8 INY ; INTO DEST'S "FIRST" SLOT ([Y] = 6) + 137C 9111 STA (I),Y + 137E D011 BNE REMVC2 ; BRANCH ALWAYS + + 1380 20181D REMVC1: JSR OBJLOC + 1383 A005 LDY #5 ; GET "NEXT" + 1385 B111 LDA (I),Y + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 39 +--- 1-OPS --- + + 1387 C505 CMP ARG1+LO ; FOUND IT? + 1389 D0F5 BNE REMVC1 ; NO, KEEP TRYING + + 138B A005 LDY #5 ; WHEN FOUND + 138D B113 LDA (J),Y ; MOVE "NEXT" SLOT OF SOURCE + 138F 9111 STA (I),Y ; TO "NEXT" SLOT OF DEST + + 1391 A900 REMVC2: LDA #0 + 1393 A004 LDY #4 ; CLEAR "LOC" + 1395 9113 STA (J),Y + 1397 C8 INY ; AND "NEXT" SLOTS ([Y] = 5) + 1398 9113 STA (J),Y ; OF SOURCE OBJECT + + 139A 60 REMVEX: RTS + + 139B ; ------ + 139B ; PRINTD + 139B ; ------ + + 139B ; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + + 139B A505 ZPRD: LDA ARG1+LO + + 139D ; ENTRY POINT FOR "USL" + + 139D 20181D PRNTDC: JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + 13A0 A007 LDY #7 ; GET PROP TABLE POINTER + 13A2 B111 LDA (I),Y ; FETCH MSB + 13A4 AA TAX ; SAVE IT HERE + 13A5 C8 INY + 13A6 B111 LDA (I),Y ; FETCH LSB + 13A8 8511 STA I+LO ; STORE LSB + 13AA 8612 STX I+HI ; AND MSB + + 13AC E611 INC I+LO ; POINT PAST THE + 13AE D002 BNE PDC0 ; LENGTH BYTE + 13B0 E612 INC I+HI + + 13B2 20E11A PDC0: JSR SETWRD ; CALC Z-STRING ADDR + 13B5 4C0D1B JMP PZSTR ; AND PRINT IT + + 13B8 ; ------ + 13B8 ; RETURN + 13B8 ; ------ + + 13B8 ; RETURN FROM "CALL" WITH VALUE [ARG1] + + 13B8 A518 ZRET: LDA OLDZSP ; RE-SYNC THE + 13BA 8517 STA ZSP ; Z-STACK POINTER + + 13BC 20B010 JSR POPVAL ; POP # LOCALS INTO [X/A] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 40 +--- 1-OPS --- + + 13BF 8612 STX I+HI ; SAVE HERE + + 13C1 ; MAKE SURE [X] WAS COMPLEMENT OF [A] (BM 11/24/84) + + 13C1 49FF EOR #$FF ; COMPLEMENT [A] + 13C3 C512 CMP I+HI ; MATCHED? + 13C5 D034 BNE STKERR ; ERROR IF NOT + + 13C7 8A TXA ; SET FLAGS; ANY LOCALS? + 13C8 F019 BEQ RET2 ; SKIP IF NOT + + 13CA ; RESTORE PUSHED LOCALS + + 13CA CA DEX ; ZERO-ALIGN + 13CB 8A TXA ; AND + 13CC 0A ASL A ; WORD-ALIGN # LOCALS + 13CD 8511 STA I+LO ; FOR USE AS A STORAGE INDEX + + 13CF 20B010 RET1: JSR POPVAL ; POP A LOCAL INTO [X/A] + + 13D2 A411 LDY I+LO ; RETRIEVE STORAGE INDEX + 13D4 99010D STA LOCALS+HI,Y ; STORE MSB OF LOCAL + 13D7 8A TXA ; MOVE LSB + 13D8 99000D STA LOCALS+LO,Y ; AND STORE THAT TOO + + 13DB C611 DEC I+LO + 13DD C611 DEC I+LO ; UPDATE STORAGE INDEX + + 13DF C612 DEC I+HI ; AND LOCALS COUNT + 13E1 D0EC BNE RET1 ; POP TILL NO MORE LOCALS + + 13E3 ; RESTORE OTHER VARIABLES + + 13E3 20B010 RET2: JSR POPVAL ; POP [ZPCH] AND [ZPCM] + 13E6 861A STX ZPCM + 13E8 851B STA ZPCH + + 13EA 20B010 JSR POPVAL ; POP AND RESTORE + 13ED 8618 STX OLDZSP + 13EF 8519 STA ZPCL + + 13F1 A900 LDA #0 + 13F3 851C STA ZPCFLG ; ZPC CHANGED! + + 13F5 20BD11 JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 13F8 4CEE10 JMP PUTVAL ; AND RETURN IT + + 13FB ; *** ERROR #15: Z-STACK DESTROYED *** + + 13FB A90F STKERR: LDA #15 ; (BM 11/24/84) + 13FD 4CC41D JMP ZERROR + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 41 +--- 1-OPS --- + + + 1400 ; ---- + 1400 ; JUMP + 1400 ; ---- + + 1400 ; JUMP TO Z-LOCATION IN [ARG1] + + 1400 20BD11 ZJUMP: JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 1403 4C7011 JMP PREDB3 ; A BRANCH THAT ALWAYS SUCCEEDS + + 1406 ; ----- + 1406 ; PRINT + 1406 ; ----- + + 1406 ; PRINT Z-STRING AT WORD POINTER [ARG1] + + 1406 A505 ZPRINT: LDA ARG1+LO + 1408 8511 STA I+LO + 140A A506 LDA ARG1+HI + 140C 8512 STA I+HI + + 140E 20FB1A JSR SETSTR ; CALC STRING ADDRESS + 1411 4C0D1B JMP PZSTR ; AND PRINT IT + + 1414 ; ----- + 1414 ; VALUE + 1414 ; ----- + + 1414 ; RETURN VALUE OF VARIABLE [ARG1] + + 1414 A505 ZVALUE: LDA ARG1+LO + 1416 208110 JSR VARGET ; GET THE VALUE + 1419 4CEE10 JMP PUTVAL ; EASY ENOUGH + + 141C ; ---- + 141C ; BCOM + 141C ; ---- + + 141C ; COMPLEMENT [ARG1] + + 141C A505 ZBCOM: LDA ARG1+LO + 141E 49FF EOR #$FF + 1420 AA TAX + 1421 A506 LDA ARG1+HI + 1423 49FF EOR #$FF + + 1425 ; FALL THROUGH ... + + 1425 ; --------------------- + 1425 ; RETURN VALUE IN [X/A] + 1425 ; --------------------- + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 42 +--- 1-OPS --- + + + 1425 860F VEXIT: STX VALUE+LO + 1427 8510 STA VALUE+HI + 1429 4CEE10 JMP PUTVAL + + END + INCLUD OPS2.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 43 +--- 2-OPS --- + + + 142C ; ----- + 142C ; LESS? + 142C ; ----- + + 142C ; [ARG1] < [ARG2]? + + 142C 20BD11 ZLESS: JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 142F 4C3514 JMP DLS0 ; MOVE [ARG2] TO [I] & COMPARE + + 1432 ; ------ + 1432 ; DLESS? + 1432 ; ------ + + 1432 ; DECREMENT [ARG1]; SUCCEED IF < [ARG2] + + 1432 203E13 ZDLESS: JSR ZDEC ; MOVES ([ARG1]-1) TO [VALUE] + + 1435 A507 DLS0: LDA ARG2+LO ; MOVE [ARG2] TO [I] + 1437 8511 STA I+LO + 1439 A508 LDA ARG2+HI + 143B 8512 STA I+HI + + 143D 4C5E14 JMP COMPAR ; COMPARE & RETURN + + 1440 ; ----- + 1440 ; GRTR? + 1440 ; ----- + + 1440 ; [ARG1] > [ARG2]? + + 1440 A505 ZGRTR: LDA ARG1+LO ; MOVE [ARG1] TO [I] + 1442 8511 STA I+LO + 1444 A506 LDA ARG1+HI + 1446 8512 STA I+HI + + 1448 4C5614 JMP A2VAL ; MOVE [ARG2] TO [VALUE] & COMPARE + + 144B ; ------ + 144B ; IGRTR? + 144B ; ------ + + 144B ; INCREMENT [ARG1]; SUCCEED IF GREATER THAN [ARG2] + + 144B 203313 ZIGRTR: JSR ZINC ; GET ([ARG1]+1) INTO [VALUE] + + 144E A50F LDA VALUE+LO ; MOVE [VALUE] TO [I] + 1450 8511 STA I+LO + 1452 A510 LDA VALUE+HI + 1454 8512 STA I+HI + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 44 +--- 2-OPS --- + + 1456 A507 A2VAL: LDA ARG2+LO ; MOVE [ARG2] TO [VALUE] + 1458 850F STA VALUE+LO + 145A A508 LDA ARG2+HI + 145C 8510 STA VALUE+HI + + 145E 206514 COMPAR: JSR SCOMP ; COMPARE [VALUE] AND [I] + 1461 9038 BCC PGOOD + 1463 B023 BCS PBAD + + 1465 ; ----------------- + 1465 ; SIGNED COMPARISON + 1465 ; ----------------- + + 1465 ; ENTRY: VALUES IN [VALUE] AND [I] + + 1465 A512 SCOMP: LDA I+HI + 1467 4510 EOR VALUE+HI + 1469 1005 BPL SCMP + 146B A512 LDA I+HI + 146D C510 CMP VALUE+HI + 146F 60 RTS + + 1470 A510 SCMP: LDA VALUE+HI + 1472 C512 CMP I+HI + 1474 D004 BNE SCEX + 1476 A50F LDA VALUE+LO + 1478 C511 CMP I+LO + 147A 60 SCEX: RTS + + 147B ; --- + 147B ; IN? + 147B ; --- + + 147B ; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? + + 147B A505 ZIN: LDA ARG1+LO + 147D 20181D JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [I] + + 1480 A004 LDY #4 ; POINT TO "LOC" SLOT + 1482 B111 LDA (I),Y ; GET DATA + 1484 C507 CMP ARG2+LO ; IS IT THERE? + 1486 F013 BEQ PGOOD ; YES, SUCCEED + + 1488 4C2A11 PBAD: JMP PREDF ; TOO BAD, CHUM ... + + 148B ; ---- + 148B ; BTST + 148B ; ---- + + 148B ; IS EVERY "ON" BIT IN [ARG1] + 148B ; ALSO "ON" IN [ARG2]? + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 45 +--- 2-OPS --- + + + 148B A507 ZBTST: LDA ARG2+LO ; FIRST CHECK LSBS + 148D 2505 AND ARG1+LO + 148F C507 CMP ARG2+LO ; LSBS MATCH? + 1491 D0F5 BNE PBAD ; NO, EXIT NOW + + 1493 A508 LDA ARG2+HI ; ELSE CHECK MSBS + 1495 2506 AND ARG1+HI + 1497 C508 CMP ARG2+HI ; MATCHED? + 1499 D0ED BNE PBAD ; SORRY ... + + 149B 4C3611 PGOOD: JMP PREDS + + 149E ; --- + 149E ; BOR + 149E ; --- + + 149E ; RETURN [ARG1] "OR" [ARG2] + + 149E A505 ZBOR: LDA ARG1+LO + 14A0 0507 ORA ARG2+LO + 14A2 AA TAX + 14A3 A506 LDA ARG1+HI + 14A5 0508 ORA ARG2+HI + 14A7 4C2514 JMP VEXIT + + 14AA ; ---- + 14AA ; BAND + 14AA ; ---- + + 14AA ; RETURN [ARG1] "AND" [ARG2] + + 14AA A505 ZBAND: LDA ARG1+LO + 14AC 2507 AND ARG2+LO + 14AE AA TAX + 14AF A506 LDA ARG1+HI + 14B1 2508 AND ARG2+HI + 14B3 4C2514 JMP VEXIT + + 14B6 ; ----- + 14B6 ; FSET? + 14B6 ; ----- + + 14B6 ; IS FLAG [ARG1] SET IN OBJECT [ARG2]? + + 14B6 20741D ZFSETP: JSR FLAGSU ; GET BITS INTO [K] AND [J] + 14B9 A516 LDA K+HI ; DO MSBS + 14BB 2514 AND J+HI + 14BD 8516 STA K+HI + + 14BF A515 LDA K+LO ; DO LSBS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 46 +--- 2-OPS --- + + 14C1 2513 AND J+LO + + 14C3 0516 ORA K+HI ; ANY BITS ON? + 14C5 D0D4 BNE PGOOD ; TARGET BIT MUST BE ON + 14C7 4C2A11 JMP PREDF + + 14CA ; ---- + 14CA ; FSET + 14CA ; ---- + + 14CA ; SET FLAG [ARG2] IN OBJECT [ARG1] + + 14CA 20741D ZFSET: JSR FLAGSU ; GET BITS INTO [K] & [J], ADDR IN [I] + + 14CD A000 LDY #0 + 14CF A516 LDA K+HI ; FIRST DO MSBS + 14D1 0514 ORA J+HI + 14D3 9111 STA (I),Y + + 14D5 C8 INY + 14D6 A515 LDA K+LO ; THEN LSBS + 14D8 0513 ORA J+LO + 14DA 9111 STA (I),Y + 14DC 60 RTS + + 14DD ; ------ + 14DD ; FCLEAR + 14DD ; ------ + + 14DD ; CLEAR FLAG [ARG2] IN OBJECT [ARG1] + + 14DD 20741D ZFCLR: JSR FLAGSU ; GETS BITS INTO [J] & [K], ADDR IN [I] + + 14E0 A000 LDY #0 + 14E2 A514 LDA J+HI ; FETCH MSB + 14E4 49FF EOR #$FF ; COMPLEMENT IT + 14E6 2516 AND K+HI ; RUB OUT FLAG + 14E8 9111 STA (I),Y + + 14EA C8 INY + 14EB A513 LDA J+LO ; SAME FOR LSB + 14ED 49FF EOR #$FF + 14EF 2515 AND K+LO + 14F1 9111 STA (I),Y + 14F3 60 RTS + + 14F4 ; --- + 14F4 ; SET + 14F4 ; --- + + 14F4 ; SET VARIABLE [ARG1] EQUAL TO [ARG2] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 47 +--- 2-OPS --- + + + 14F4 A507 ZSET: LDA ARG2+LO ; MOVE THE VALUE + 14F6 850F STA VALUE+LO ; INTO [VALUE] + 14F8 A508 LDA ARG2+HI + 14FA 8510 STA VALUE+HI + + 14FC A505 LDA ARG1+LO ; GET VARIABLE ID + 14FE 4CDD10 JMP VARPUT ; AND CHANGE THE VARIABLE + + 1501 ; ---- + 1501 ; MOVE + 1501 ; ---- + + 1501 ; MOVE OBJECT [ARG1] INTO OBJECT [ARG2] + + 1501 205913 ZMOVE: JSR ZREMOV ; REMOVE FIRST + + 1504 A505 LDA ARG1+LO + 1506 20181D JSR OBJLOC ; GET SOURCE OBJECT ADDR INTO [I] + + 1509 A511 LDA I+LO ; COPY SOURCE ADDRESS + 150B 8513 STA J+LO ; INTO [J] + 150D A512 LDA I+HI + 150F 8514 STA J+HI + + 1511 A507 LDA ARG2+LO ; GET DEST OBJECT ID + 1513 A004 LDY #4 ; POINT TO "LOC" SLOT OF SOURCE + 1515 9111 STA (I),Y ; AND MOVE IT IN + + 1517 20181D JSR OBJLOC ; GET ADDR OF DEST OBJECT INTO [I] + + 151A A006 LDY #6 ; POINT TO "FIRST" SLOT + 151C B111 LDA (I),Y ; GET "FIRST" OF DEST + 151E AA TAX ; SAVE HERE FOR A MOMENT + + 151F A505 LDA ARG1+LO ; GET SOURCE OBJECT ID + 1521 9111 STA (I),Y ; MAKE IT "FIRST" OF DEST + + 1523 8A TXA ; RESTORE "FIRST" OF DEST + 1524 F004 BEQ ZMVEX ; SCRAM IF ZERO + + 1526 A005 LDY #5 ; MAKE "FIRST" OF DEST + 1528 9113 STA (J),Y ; THE "NEXT" OF SOURCE + + 152A 60 ZMVEX: RTS + + 152B ; --- + 152B ; GET + 152B ; --- + + 152B ; RETURN ITEM [ARG2] IN WORD-TABLE [ARG1] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 48 +--- 2-OPS --- + + + 152B 204015 ZGET: JSR WCALC ; CALC ADDRESS + 152E 201A1A JSR GETBYT ; GET 1ST BYTE (MSB) + + 1531 8510 DOGET: STA VALUE+HI ; SAVE MSB + 1533 201A1A JSR GETBYT ; GET LSB + 1536 850F STA VALUE+LO ; SAVE AND + 1538 4CEE10 JMP PUTVAL ; HAND IT OVER + + 153B ; ---- + 153B ; GETB + 153B ; ---- + + 153B ; RETURN ITEM [ARG2] IN BYTE-TABLE AT [ARG1] + + 153B 204415 ZGETB: JSR BCALC + 153E F0F1 BEQ DOGET ; [A] = 0, SO CLEAR MSB OF [VALUE] + + 1540 ; -------------------- + 1540 ; CALC TABLE ADDRESSES + 1540 ; -------------------- + + 1540 ; WORD-ALIGNED ENTRY + + 1540 0607 WCALC: ASL ARG2+LO ; WORD-ALIGN FOR + 1542 2608 ROL ARG2+HI ; WORD ACCESS + + 1544 ; BYTE-ALIGNED ENTRY + + 1544 A507 BCALC: LDA ARG2+LO ; ADD BASE ADDR OF TABLE + 1546 18 CLC ; TO ITEM + 1547 6505 ADC ARG1+LO ; INDEX + 1549 851F STA MPCL + + 154B A508 LDA ARG2+HI ; SAME FOR MSBS + 154D 6506 ADC ARG1+HI + 154F 8520 STA MPCM + + 1551 A900 LDA #0 + 1553 8521 STA MPCH ; CLEAR TOP BIT + 1555 8522 STA MPCFLG ; & INVALIDATE [MPC] + 1557 60 RTS + + 1558 ; ---- + 1558 ; GETP + 1558 ; ---- + + 1558 ; RETURN PROPERTY [ARG2] OF OBJECT [ARG1]; + 1558 ; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 + + 1558 20411D ZGETP: JSR PROPB + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 49 +--- 2-OPS --- + + + 155B 205D1D GETP1: JSR PROPN + 155E C507 CMP ARG2+LO + 1560 F01B BEQ GETP3 + 1562 9006 BCC GETP2 + + 1564 206A1D JSR PROPNX + 1567 4C5B15 JMP GETP1 ; TRY AGAIN WITH NEXT PROP + + 156A A507 GETP2: LDA ARG2+LO ; GET PROPERTY # + 156C 38 SEC ; ZERO-ALIGN IT + 156D E901 SBC #1 + 156F 0A ASL A ; WORD-ALIGN IT + 1570 A8 TAY ; USE AS AN INDEX + 1571 B135 LDA (OBJTAB),Y ; GET MSB OF PROPERTY + 1573 8510 STA VALUE+HI + 1575 C8 INY + 1576 B135 LDA (OBJTAB),Y ; DO SAME WITH LSB + 1578 850F STA VALUE+LO + 157A 4CEE10 JMP PUTVAL ; RETURN DEFAULT IN [VALUE] + + 157D 20621D GETP3: JSR PROPL + 1580 C8 INY ; MAKE [Y] POINT TO 1ST BYTE OF PROP + 1581 AA TAX ; (SET FLAGS) IF LENGTH IN [A] = 0 + 1582 F009 BEQ GETPB ; GET A BYTE PROPERTY + 1584 C901 CMP #1 ; IF LENGTH = 1 + 1586 F00B BEQ GETPW ; GET A WORD PROPERTY + + 1588 ; *** ERROR #7: PROPERTY LENGTH *** + + 1588 A907 LDA #7 + 158A 4CC41D JMP ZERROR + + 158D ; GET A 1-BYTE PROPERTY + + 158D B111 GETPB: LDA (I),Y ; GET LSB INTO [A] + 158F A200 LDX #0 ; CLEAR MSB IN [X] + 1591 F006 BEQ ETPEX + + 1593 ; GET A 2-BYTE PROPERTY + + 1593 B111 GETPW: LDA (I),Y ; GET MSB + 1595 AA TAX ; INTO [X] + 1596 C8 INY ; POINT TO LSB + 1597 B111 LDA (I),Y ; GET IT INTO [A] + + 1599 850F ETPEX: STA VALUE+LO ; STORE LSB + 159B 8610 STX VALUE+HI ; AND MSB + 159D 4CEE10 JMP PUTVAL + + 15A0 ; ----- + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 50 +--- 2-OPS --- + + 15A0 ; GETPT + 15A0 ; ----- + + 15A0 ; RETURN POINTER TO PROP TABLE [ARG2] + 15A0 ; IN OBJECT [ARG1] + + 15A0 20411D ZGETPT: JSR PROPB + + 15A3 205D1D GETPT1: JSR PROPN ; RETURNS OFFSET IN [Y] + 15A6 C507 CMP ARG2+LO + 15A8 F008 BEQ GETPT2 + 15AA 901E BCC DORET + 15AC 206A1D JSR PROPNX ; TRY NEXT PROPERTY + 15AF 4CA315 JMP GETPT1 + + 15B2 E611 GETPT2: INC I+LO + 15B4 D002 BNE GETPT3 + 15B6 E612 INC I+HI + + 15B8 98 GETPT3: TYA ; FETCH OFFSET + 15B9 18 CLC + 15BA 6511 ADC I+LO ; ADD LSB OF TABLE ADDRESS + 15BC 850F STA VALUE+LO + + 15BE A512 LDA I+HI ; AND MSB + 15C0 6900 ADC #0 + 15C2 38 SEC ; STRIP OFF + 15C3 E526 SBC ZCODE ; RELATIVE POINTER + 15C5 8510 STA VALUE+HI + 15C7 4CEE10 JMP PUTVAL ; AND RETURN + + 15CA 4CE610 DORET: JMP RET0 ; ELSE RETURN A ZERO + + 15CD ; ----- + 15CD ; NEXTP + 15CD ; ----- + + 15CD ; RETURN INDEX # OF PROP FOLLOWING PROP [ARG2] IN OBJECT [ARG1]; + 15CD ; RETURN ZERO IF LAST; RETURN FIRST IF [ARG2]=0; ERROR IF NONE + + 15CD 20411D ZNEXTP: JSR PROPB + 15D0 A507 LDA ARG2+LO ; IF [ARG2]=0 + 15D2 F012 BEQ NXTP3 ; RETURN "FIRST" SLOT + + 15D4 205D1D NXTP1: JSR PROPN ; FETCH PROPERTY # + 15D7 C507 CMP ARG2+LO ; COMPARE TO TARGET # + 15D9 F008 BEQ NXTP2 ; FOUND IT! + 15DB 90ED BCC DORET ; LAST PROP, SO RETURN ZERO + 15DD 206A1D JSR PROPNX ; ELSE TRY NEXT PROPERTY + 15E0 4CD415 JMP NXTP1 + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 51 +--- 2-OPS --- + + 15E3 206A1D NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY + + 15E6 205D1D NXTP3: JSR PROPN ; GET THE PROPERTY # + 15E9 4CE810 JMP PUTBYT ; AND RETURN IT + + 15EC ; --- + 15EC ; ADD + 15EC ; --- + + 15EC ; RETURN [ARG1] + [ARG2] + + 15EC A505 ZADD: LDA ARG1+LO ; ADD LSBS + 15EE 18 CLC + 15EF 6507 ADC ARG2+LO + 15F1 AA TAX ; SAVE LSB HERE + 15F2 A506 LDA ARG1+HI ; ADD MSBS + 15F4 6508 ADC ARG2+HI + 15F6 4C2514 JMP VEXIT + + 15F9 ; --- + 15F9 ; SUB + 15F9 ; --- + + 15F9 ; RETURN [ARG1] - [ARG2] + + 15F9 A505 ZSUB: LDA ARG1+LO ; SUBTRACT LSBS + 15FB 38 SEC + 15FC E507 SBC ARG2+LO + 15FE AA TAX ; SAVE LSB HERE + 15FF A506 LDA ARG1+HI ; SUBTRACT MSBS + 1601 E508 SBC ARG2+HI + 1603 4C2514 JMP VEXIT ; EXIT WITH [X]=LSB, [A]=MSB + + 1606 ; --- + 1606 ; MUL + 1606 ; --- + + 1606 ; RETURN [ARG1] * [ARG2] + + 1606 20C016 ZMUL: JSR MINIT ; INIT THINGS + + 1609 665B ZMLOOP: ROR MTEMP+HI + 160B 665A ROR MTEMP+LO + 160D 6608 ROR ARG2+HI + 160F 6607 ROR ARG2+LO + 1611 900D BCC ZMNEXT + + 1613 A505 LDA ARG1+LO + 1615 18 CLC + 1616 655A ADC MTEMP+LO + 1618 855A STA MTEMP+LO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 52 +--- 2-OPS --- + + 161A A506 LDA ARG1+HI + 161C 655B ADC MTEMP+HI + 161E 855B STA MTEMP+HI + + 1620 CA ZMNEXT: DEX + 1621 10E6 BPL ZMLOOP + + 1623 A607 LDX ARG2+LO ; PUT LSB OF PRODUCT + 1625 A508 LDA ARG2+HI ; AND MSB + 1627 4C2514 JMP VEXIT ; WHERE "VEXIT" EXPECTS THEM + + 162A ; --- + 162A ; DIV + 162A ; --- + + 162A ; RETURN QUOTIENT OF [ARG1] / [ARG2] + + 162A 203E16 ZDIV: JSR DIVIDE + 162D A656 LDX QUOT+LO + 162F A557 LDA QUOT+HI + 1631 4C2514 JMP VEXIT + + 1634 ; --- + 1634 ; MOD + 1634 ; --- + + 1634 ; RETURN REMAINDER OF [ARG1] / [ARG2] + + 1634 203E16 ZMOD: JSR DIVIDE + 1637 A658 LDX REMAIN+LO ; FETCH THE REMAINDER + 1639 A559 LDA REMAIN+HI ; IN [REMAIN] + 163B 4C2514 JMP VEXIT ; AND RETURN IT + + 163E ; --------------- + 163E ; SIGNED DIVISION + 163E ; --------------- + + 163E ; ENTRY: DIVIDEND IN [ARG1], DIVISOR IN [ARG2] + 163E ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] + + 163E A506 DIVIDE: LDA ARG1+HI ; SIGN OF REMAINDER + 1640 855D STA RSIGN ; IS THE SIGN OF THE DIVIDEND + 1642 4508 EOR ARG2+HI ; SIGN OF QUOTIENT IS POSITIVE + 1644 855C STA QSIGN ; IF SIGNS OF TERMS ARE THE SAME + + 1646 A505 LDA ARG1+LO ; MOVE [ARG1] TO [QUOT] + 1648 8556 STA QUOT+LO + 164A A506 LDA ARG1+HI + 164C 8557 STA QUOT+HI ; IF DIVIDEND IS POSITIVE + 164E 1003 BPL ABSDIV ; MOVE DIVISOR + 1650 207C16 JSR ABQUOT ; ELSE CALC ABS(DIVIDEND) FIRST + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 53 +--- 2-OPS --- + + + 1653 A507 ABSDIV: LDA ARG2+LO + 1655 8558 STA REMAIN+LO + 1657 A508 LDA ARG2+HI + 1659 8559 STA REMAIN+HI ; IF REMAINDER IS POSITIVE + 165B 1003 BPL GODIV ; WE'RE READY TO DIVIDE + 165D 206E16 JSR ABREM ; ELSE CALC ABS(DIVISOR) + + 1660 208A16 GODIV: JSR UDIV ; DO UNSIGNED DIVIDE + + 1663 A55C LDA QSIGN ; SHOULD QUOTIENT BE FLIPPED? + 1665 1003 BPL RFLIP ; NO, TEST REMAINDER + 1667 207C16 JSR ABQUOT ; ELSE GET ABSOLUTE VALUE + + 166A A55D RFLIP: LDA RSIGN ; SHOULD EMAINDER BE FLIPPED? + 166C 100D BPL DIVEX ; NO, WE'RE DONE + + 166E ; ELSE FALL THROUGH ... + + 166E ; ---------------- + 166E ; CALC ABS(REMAIN) + 166E ; ---------------- + + 166E A900 ABREM: LDA #0 + 1670 38 SEC + 1671 E558 SBC REMAIN+LO + 1673 8558 STA REMAIN+LO + 1675 A900 LDA #0 + 1677 E559 SBC REMAIN+HI + 1679 8559 STA REMAIN+HI + + 167B 60 DIVEX: RTS + + 167C ; -------------- + 167C ; CALC ABS(QUOT) + 167C ; -------------- + + 167C A900 ABQUOT: LDA #0 + 167E 38 SEC + 167F E556 SBC QUOT+LO + 1681 8556 STA QUOT+LO + 1683 A900 LDA #0 + 1685 E557 SBC QUOT+HI + 1687 8557 STA QUOT+HI + 1689 60 RTS + + 168A ; ----------------- + 168A ; UNSIGNED DIVISION + 168A ; ----------------- + + 168A ; ENTRY: DIVIDEND IN [QUOT], DIVISOR IN [REMAIN] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 54 +--- 2-OPS --- + + 168A ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] + + 168A A558 UDIV: LDA REMAIN+LO ; CHECK [REMAIN] + 168C 0559 ORA REMAIN+HI ; BEFORE PROCEEDING + 168E F02B BEQ DIVERR ; CAN'T DIVIDE BY ZERO! + + 1690 20C016 JSR MINIT ; SET IT ALL UP + + 1693 2656 UDLOOP: ROL QUOT+LO + 1695 2657 ROL QUOT+HI + 1697 265A ROL MTEMP+LO + 1699 265B ROL MTEMP+HI + + 169B A55A LDA MTEMP+LO + 169D 38 SEC + 169E E558 SBC REMAIN+LO + 16A0 A8 TAY ; SAVE HERE + 16A1 A55B LDA MTEMP+HI + 16A3 E559 SBC REMAIN+HI + 16A5 9004 BCC UDNEXT + 16A7 845A STY MTEMP+LO + 16A9 855B STA MTEMP+HI + + 16AB CA UDNEXT: DEX + 16AC D0E5 BNE UDLOOP + + 16AE 2656 ROL QUOT+LO ; SHIFT LAST CARRY FOR QUOTIENT + 16B0 2657 ROL QUOT+HI + + 16B2 A55A LDA MTEMP+LO ; MOVE REMAINDER + 16B4 8558 STA REMAIN+LO ; INTO [REMAIN] + 16B6 A55B LDA MTEMP+HI + 16B8 8559 STA REMAIN+HI + 16BA 60 RTS + + 16BB ; *** ERROR #8: DIVISION BY ZERO *** + + 16BB A908 DIVERR: LDA #8 + 16BD 4CC41D JMP ZERROR + + 16C0 ; --------- + 16C0 ; MATH INIT + 16C0 ; --------- + + 16C0 A210 MINIT: LDX #16 ; INIT LOOPING INDEX + 16C2 A900 LDA #0 + 16C4 855A STA MTEMP+LO ; CLEAR TEMP + 16C6 855B STA MTEMP+HI ; REGISTER + 16C8 18 CLC ; AND CARRY + 16C9 60 RTS + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 55 +--- 2-OPS --- + + END + INCLUD OPSX.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 56 +--- X-OPS --- + + + 16CA ; ------ + 16CA ; EQUAL? + 16CA ; ------ + + 16CA ; IS [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? + + 16CA C604 ZEQUAL: DEC NARGS ; DOUBLE-CHECK # ARGS + 16CC D005 BNE DOEQ ; MUST BE AT LEAST TWO, OR ... + + 16CE ; *** ERROR #9: NOT ENOUGH "EQUAL?" ARGS *** + + 16CE A909 LDA #9 + 16D0 4CC41D JMP ZERROR + + 16D3 A505 DOEQ: LDA ARG1+LO ; FETCH LSB + 16D5 A606 LDX ARG1+HI ; AND MSB OF [ARG1] + + 16D7 C507 CMP ARG2+LO ; TEST LSB OF [ARG2] + 16D9 D004 BNE TRY2 ; NO GOOD, LOOK FOR ANOTHER ARG + 16DB E408 CPX ARG2+HI ; ELSE TRY MSB OF [ARG2] + 16DD F018 BEQ EQOK ; MATCHED! + + 16DF C604 TRY2: DEC NARGS ; OUT OF ARGS YET? + 16E1 F017 BEQ EQBAD ; YES, WE FAILED + + 16E3 C509 CMP ARG3+LO ; TRY LSB OF [ARG3] + 16E5 D004 BNE TRY3 ; NO GOOD, LOOK FOR ANOTHER ARG + 16E7 E40A CPX ARG3+HI ; HOW ABOUT MSB OF [ARG3]? + 16E9 F00C BEQ EQOK ; YAY! + + 16EB C604 TRY3: DEC NARGS ; OUT OF ARGS YET? + 16ED F00B BEQ EQBAD ; IF NOT ... + + 16EF C50B CMP ARG4+LO ; TRY [ARG4] + 16F1 D007 BNE EQBAD ; SORRY, CHUM + 16F3 E40C CPX ARG4+HI ; MSB MATCHED? + 16F5 D003 BNE EQBAD ; TOO BAD + + 16F7 4C3611 EQOK: JMP PREDS ; FINALLY MATCHED! + + 16FA 4C2A11 EQBAD: JMP PREDF ; FAILURE (SNIFF!) + + 16FD ; ---- + 16FD ; CALL + 16FD ; ---- + + 16FD ; BRANCH TO FUNCTION AT ([ARG1]*2), PASSING + 16FD ; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] + + 16FD A505 ZCALL: LDA ARG1+LO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 57 +--- X-OPS --- + + 16FF 0506 ORA ARG1+HI ; IS CALL ADDRESS ZERO? + 1701 D003 BNE DOCALL ; NO, CONTINUE + + 1703 4CE810 JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] + + 1706 A618 DOCALL: LDX OLDZSP ; SAVE OLD STACK POINTER + 1708 A519 LDA ZPCL ; AND LSB OF [ZPC] + 170A 20CA10 JSR PUSHXA ; ON THE Z-STACK + + 170D A61A LDX ZPCM ; SAVE MIDDLE 8 BITS + 170F A51B LDA ZPCH ; AND TOP BIT OF [ZPC] + 1711 20CA10 JSR PUSHXA ; AS WELL + + 1714 ; FORM 16-BIT ADDRESS FROM [ARG1] + + 1714 A900 LDA #0 ; CLEAR HIGH BIT FOR ROTATE + 1716 851C STA ZPCFLG ; AND INVALIDATE [ZPC] + + 1718 0605 ASL ARG1+LO ; MULTIPLY [ARG1] + 171A 2606 ROL ARG1+HI ; BY TWO + 171C 2A ROL A ; HIGH BIT INTO [A] + 171D 851B STA ZPCH ; NEW HIGH BIT OF [ZPC] + + 171F A506 LDA ARG1+HI ; GET NEW LOW BYTES + 1721 851A STA ZPCM + 1723 A505 LDA ARG1+LO + 1725 8519 STA ZPCL + + 1727 20E419 JSR NEXTPC ; FETCH # LOCALS TO PASS + 172A 8513 STA J+LO ; SAVE HERE FOR COUNTING + 172C 8514 STA J+HI ; AND HERE FOR LATER REFERENCE + 172E F02B BEQ ZCALL2 ; SKIP IF NO LOCALS + + 1730 A900 LDA #0 + 1732 8511 STA I+LO ; ELSE INIT STORAGE INDEX + + 1734 A411 ZCALL1: LDY I+LO + 1736 BE000D LDX LOCALS+LO,Y ; GET LSB OF LOCAL INTO [X] + 1739 B9010D LDA LOCALS+HI,Y ; AND MSB INTO [A] + 173C 8411 STY I+LO ; SAVE THE INDEX + 173E 20CA10 JSR PUSHXA ; PUSH LOCAL IN [X/A] ONTO Z-STACK + + 1741 20E419 JSR NEXTPC ; GET MSB OF NEW LOCAL + 1744 8512 STA I+HI ; SAVE IT HERE + 1746 20E419 JSR NEXTPC ; NOW GET LSB + + 1749 A411 LDY I+LO ; RESTORE INDEX + 174B 99000D STA LOCALS+LO,Y ; STORE LSB INTO [LOCALS] + 174E A512 LDA I+HI ; RETRIEVE MSB + 1750 99010D STA LOCALS+HI,Y ; STORE IT INTO [LOCALS] + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 58 +--- X-OPS --- + + 1753 C8 INY + 1754 C8 INY ; UPDATE + 1755 8411 STY I+LO ; THE STORAGE INDEX + + 1757 C613 DEC J+LO ; ANY MORE LOCALS? + 1759 D0D9 BNE ZCALL1 ; YES, KEEP LOOPING + + 175B ; MOVE UP TO 3 ARGUMENTS TO [LOCALS] + + 175B C604 ZCALL2: DEC NARGS ; EXTRA ARGS IN THIS CALL? + 175D F026 BEQ ZCALL3 ; NO, CONTINUE + + 175F A507 LDA ARG2+LO ; MOVE [ARG2] TO LOCAL #1 + 1761 8D000D STA LOCALS+LO + 1764 A508 LDA ARG2+HI + 1766 8D010D STA LOCALS+HI + + 1769 C604 DEC NARGS ; ANY LEFT? + 176B F018 BEQ ZCALL3 ; NO, SCRAM + + 176D A509 LDA ARG3+LO ; MOVE [ARG3] TO LOCAL #2 + 176F 8D020D STA LOCALS+LO+2 + 1772 A50A LDA ARG3+HI + 1774 8D030D STA LOCALS+HI+2 + + 1777 C604 DEC NARGS ; ANY LEFT? + 1779 F00A BEQ ZCALL3 ; NO, EXUENT + + 177B A50B LDA ARG4+LO ; MOVE [ARG4] TO LOCAL #3 + 177D 8D040D STA LOCALS+LO+4 + 1780 A50C LDA ARG4+HI + 1782 8D050D STA LOCALS+HI+4 + + 1785 A614 ZCALL3: LDX J+HI ; RETRIEVE # LOCALS + 1787 8A TXA ; DUPE INTO [A] + 1788 49FF EOR #$FF ; COMPLEMENT FOR ERROR CHECK (BM 11/24/84) + 178A 20CA10 JSR PUSHXA ; PUSH # LOCALS ONTO Z-STACK + + 178D A517 LDA ZSP ; REMEMBER WHERE + 178F 8518 STA OLDZSP ; WE CAME FROM + + 1791 60 RTS ; WHEW! + + 1792 ; --- + 1792 ; PUT + 1792 ; --- + + 1792 ; SET ITEM [ARG2] IN WORD-TABLE [ARG1] EQUAL TO [ARG3] + + 1792 0607 ZPUT: ASL ARG2+LO ; WORD-ALIGN [ARG2] + 1794 2608 ROL ARG2+HI + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 59 +--- X-OPS --- + + + 1796 20A817 JSR PCALC ; GET ITEM ADDR INTO [I] + 1799 A50A LDA ARG3+HI ; STORE MSB OF [ARG3] + 179B 9111 STA (I),Y ; INTO MSB OF TABLE POSITION + 179D C8 INY ; POINT TO LSB + 179E D003 BNE PUTLSB ; BRANCH ALWAYS + + 17A0 ; ---- + 17A0 ; PUTB + 17A0 ; ---- + + 17A0 ; SET ITEM [ARG2] IN BYTE-TABLE [ARG1] EQUAL TO [ARG3] + + 17A0 20A817 ZPUTB: JSR PCALC + + 17A3 ; ENTRY FOR "PUT" + + 17A3 A509 PUTLSB: LDA ARG3+LO ; GET LSB OF [ARG3] + 17A5 9111 STA (I),Y ; STORE IN TABLE AT [Y] + 17A7 60 RTS + + 17A8 ; --------------------------- + 17A8 ; CALC ITEM ADDRESS FOR "PUT" + 17A8 ; --------------------------- + + 17A8 A507 PCALC: LDA ARG2+LO ; ADD ITEM OFFSET IN [ARG2] + 17AA 18 CLC ; TO TABLE ADDR IN [ARG1] + 17AB 6505 ADC ARG1+LO ; TO FORM A POINTER + 17AD 8511 STA I+LO ; IN [I] + + 17AF A508 LDA ARG2+HI ; SAME FOR MSB + 17B1 6506 ADC ARG1+HI + 17B3 18 CLC + 17B4 6526 ADC ZCODE ; MAKE IT ABSOLUTE + 17B6 8512 STA I+HI + + 17B8 A000 LDY #0 ; ZERO FOR INDEXING + 17BA 60 RTS + + 17BB ; ---- + 17BB ; PUTP + 17BB ; ---- + + 17BB ; SET PROPERTY [ARG2] IN OBJECT [ARG1] EQUAL TO [ARG3] + + 17BB 20411D ZPUTP: JSR PROPB + + 17BE 205D1D PUTP1: JSR PROPN + 17C1 C507 CMP ARG2+LO + 17C3 F008 BEQ PUTP2 + 17C5 901B BCC PNERR ; ERROR IF LOWER + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 60 +--- X-OPS --- + + + 17C7 206A1D JSR PROPNX ; TRY NEXT PROPERTY + 17CA 4CBE17 JMP PUTP1 + + 17CD 20621D PUTP2: JSR PROPL + 17D0 C8 INY ; MAKE [Y] POINT TO 1ST PROPERTY BYTE + 17D1 AA TAX ; (SET FLAGS) IF LENGTH IN [A] = 0 + 17D2 F009 BEQ PUTP3 ; PUT A BYTE + 17D4 C901 CMP #1 ; PUT A WORD IF [A] = 1 + 17D6 D00F BNE PLERR ; ELSE LENGTH IS BAD + + 17D8 A50A LDA ARG3+HI ; GET MSB OF PROPERTY + 17DA 9111 STA (I),Y ; AND STORE IN OBJECT + 17DC C8 INY ; POINT TO LSB SLOT + + 17DD A509 PUTP3: LDA ARG3+LO ; FETCH LSB + 17DF 9111 STA (I),Y ; AND STORE IN OBJECT + 17E1 60 RTS + + 17E2 ; *** ERROR #10: BAD PROPERTY NUMBER *** + + 17E2 A90A PNERR: LDA #10 + 17E4 4CC41D JMP ZERROR + + 17E7 ; *** ERROR #11: PUTP PROPERTY LENGTH *** + + 17E7 A90B PLERR: LDA #11 + 17E9 4CC41D JMP ZERROR + + 17EC ; ------ + 17EC ; PRINTC + 17EC ; ------ + + 17EC ; PRINT CHAR WITH ASCII VALUE IN [ARG1] + + 17EC A505 ZPRC: LDA ARG1+LO ; GRAB THE CHAR + 17EE 4C451E JMP COUT ; AND SHIP IT OUT + + 17F1 ; ------ + 17F1 ; PRINTN + 17F1 ; ------ + + 17F1 ; PRINT VALUE OF [ARG1] AS A SIGNED INTEGER + + 17F1 A505 ZPRN: LDA ARG1+LO ; MOVE [ARG1] TO [QUOT] + 17F3 8556 STA QUOT+LO + 17F5 A506 LDA ARG1+HI + 17F7 8557 STA QUOT+HI + + 17F9 ; PRINT [QUOT] + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 61 +--- X-OPS --- + + 17F9 A557 NUMBER: LDA QUOT+HI ; IF VALUE IS POSITIVE + 17FB 1008 BPL DIGCNT ; CONTINUE + + 17FD A92D LDA #$2D ; ELSE START WITH A MINUS SIGN + 17FF 20451E JSR COUT + + 1802 207C16 JSR ABQUOT ; AND CALC ABS([QUOT]) + + 1805 ; COUNT # OF DECIMAL DIGITS + + 1805 A900 DIGCNT: LDA #0 ; RESET + 1807 855E STA DIGITS ; DIGIT INDEX + + 1809 A556 DGC: LDA QUOT+LO ; IS QUOTIENT + 180B 0557 ORA QUOT+HI ; ZERO YET? + 180D F012 BEQ PRNTN3 ; YES, READY TO PRINT + + 180F A90A LDA #10 ; ELSE DIVIDE [QUOT] + 1811 8558 STA REMAIN+LO ; BY 10 (LSB) + 1813 A900 LDA #0 + 1815 8559 STA REMAIN+HI ; 10 (MSB) + + 1817 208A16 JSR UDIV ; UNSIGNED DIVIDE + + 181A A558 LDA REMAIN+LO ; FETCH LSB OF REMAINDER (THE DIGIT) + 181C 48 PHA ; SAVE IT ON STACK + 181D E65E INC DIGITS ; UPDATE DIGIT COUNT + 181F D0E8 BNE DGC ; LOOP TILL QUOTIENT=0 + + 1821 A55E PRNTN3: LDA DIGITS ; IF DIGIT COUNT IS NZ + 1823 D005 BNE PRNTN4 ; CONTINUE + + 1825 A930 LDA #'0' ; ELSE PRINT "0" + 1827 4C451E JMP COUT ; AND RETURN + + 182A 68 PRNTN4: PLA ; PULL A DIGIT OFF THE STACK + 182B 18 CLC + 182C 6930 ADC #'0' ; CONVERT TO ASCII + 182E 20451E JSR COUT ; AND PRINT IT + 1831 C65E DEC DIGITS ; OUT OF DIGITS YET? + 1833 D0F5 BNE PRNTN4 ; NO, KEEP LOOPING + 1835 60 RTS + + 1836 ; ------ + 1836 ; RANDOM + 1836 ; ------ + + 1836 ; RETURN A RANDOM VALUE BETWEEN 0 AND [ARG1] + + 1836 A505 ZRAND: LDA ARG1+LO ; MAKE [ARG1] THE DIVISOR + 1838 8507 STA ARG2+LO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 62 +--- X-OPS --- + + 183A A506 LDA ARG1+HI + 183C 8508 STA ARG2+HI + + 183E 203E1E JSR RANDOM ; GET RANDOM BYTES INTO [A] AND [X] + 1841 8605 STX ARG1+LO ; MAKE THEM THE DIVIDEND + 1843 297F AND #$7F ; MAKE SURE MSB IS POSITIVE + 1845 8506 STA ARG1+HI + + 1847 203E16 JSR DIVIDE ; SIGNED DIVIDE, [ARG1] / [ARG2] + + 184A A558 LDA REMAIN+LO ; MOVE REMAINDER + 184C 850F STA VALUE+LO ; INTO [VALUE] + 184E A559 LDA REMAIN+HI + 1850 8510 STA VALUE+HI + + 1852 20B611 JSR INCVAL ; INCREMENT [VALUE] + 1855 4CEE10 JMP PUTVAL ; AND RETURN RESULT + + 1858 ; ---- + 1858 ; PUSH + 1858 ; ---- + + 1858 ; PUSH [ARG1] ONTO THE Z-STACK + + 1858 A605 ZPUSH: LDX ARG1+LO + 185A A506 LDA ARG1+HI + 185C 4CCA10 JMP PUSHXA + + 185F ; --- + 185F ; POP + 185F ; --- + + 185F ; POP WORD OFF Z-STACK, STORE IN VARIABLE [ARG1] + + 185F 20B010 ZPOP: JSR POPVAL ; VALUE INTO [VALUE] + 1862 A505 LDA ARG1+LO ; GET VARIABLE ID + 1864 4CDD10 JMP VARPUT ; AND CHANGE THE VARIABLE + + END + INCLUD READ.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 63 +--- READ HANDLER --- + + + 1867 ; ---- + 1867 ; READ + 1867 ; ---- + + 1867 ; READ LINE INTO TABLE [ARG1]; PARSE INTO TABLE [ARG2] + + 1867 20081F ZREAD: JSR ZUSL ; UPDATE THE STATUS LINE + + 186A A506 LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + 186C 18 CLC ; ABSOLUTE + 186D 6526 ADC ZCODE ; LSBS NEED NOT CHANGE + 186F 8506 STA ARG1+HI + + 1871 A508 LDA ARG2+HI + 1873 18 CLC + 1874 6526 ADC ZCODE + 1876 8508 STA ARG2+HI + + 1878 208D21 JSR INPUT ; READ LINE; RETURN LENGTH IN [A] + 187B 8545 STA LINLEN ; SAVE # CHARS IN LINE + + 187D A900 LDA #0 + 187F 8546 STA WRDLEN ; INIT # CHARS IN WORD COUNTER + + 1881 A001 LDY #1 ; POINT TO "# WORDS READ" SLOT + 1883 9107 STA (ARG2),Y ; AND CLEAR IT ([A] = 0) + + 1885 8443 STY SOURCE ; INIT SOURCE TABLE PNTR ([Y] = 1) + 1887 C8 INY ; = 2 + 1888 8444 STY RESULT ; AND RESULT TABLE POINTER + + 188A ; MAIN LOOP STARTS HERE + + 188A A000 READL: LDY #0 ; POINT TO "MAX WORDS" SLOT + 188C B107 LDA (ARG2),Y ; AND READ IT + 188E F004 BEQ RLERR ; PATCH IF ZERO + 1890 C93C CMP #60 ; OKAY IF < 60 + 1892 9004 BCC RL0 + + 1894 A93B RLERR: LDA #59 ; MAXIMUM VALUE IS 59 (BM 5/14/85) + 1896 9107 STA (ARG2),Y + + 1898 C8 RL0: INY ; POINT TO "# WORDS READ" SLOT + 1899 D107 CMP (ARG2),Y ; TOO MANY WORDS? + 189B 9006 BCC RLEX ; EXIT IF SO (BM 5/1/85) + + 189D A545 RL1: LDA LINLEN + 189F 0546 ORA WRDLEN ; OUT OF CHARS AND WORDS? + 18A1 D001 BNE RL2 ; NOT YET + 18A3 60 RLEX: RTS ; ELSE EXIT + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 64 +--- READ HANDLER --- + + + 18A4 A546 RL2: LDA WRDLEN ; GET WORD LENGTH + 18A6 C906 CMP #6 ; 6 CHARS DONE? + 18A8 9003 BCC RL3 ; NO, KEEP GOING + 18AA 203B19 JSR FLUSHW ; ELSE FLUSH REMAINDER OF WORD + + 18AD A546 RL3: LDA WRDLEN ; GET WORD LENGTH AGAIN + 18AF D024 BNE READL2 ; CONTINUE IF NOT FIRST CHAR + + 18B1 ; START A NEW WORD + + 18B1 A205 LDX #5 ; CLEAR Z-WORD INPUT BUFFER + 18B3 9537 RLL: STA IN,X ; [A] = 0 + 18B5 CA DEX + 18B6 10FB BPL RLL + + 18B8 202D19 JSR EFIND ; GET BASE ADDRESS INTO [ENTRY] + 18BB A543 LDA SOURCE ; STORE THE START POS OF THE WORD + 18BD A003 LDY #3 ; INTO THE "WORD START" SLOT + 18BF 9147 STA (ENTRY),Y ; OF THE RESULT TABLE + + 18C1 A8 TAY + 18C2 B105 LDA (ARG1),Y ; GET A CHAR FROM SOURCE BUFFER + 18C4 206819 JSR SIB ; IS IT A SELF-INSERTING BREAK? + 18C7 B026 BCS DOSIB ; YES IF CARRY WAS SET + + 18C9 205619 JSR NORM ; IS IT A "NORMAL" BREAK? + 18CC 9007 BCC READL2 ; NO, CONTINUE + + 18CE E643 INC SOURCE ; ELSE FLUSH THE STRANDED BREAK + 18D0 C645 DEC LINLEN ; UPDATE # CHARS LEFT IN LINE + 18D2 4C8A18 JMP READL ; AND LOOP + + 18D5 A545 READL2: LDA LINLEN ; OUT OF CHARS YET? + 18D7 F01E BEQ READL3 ; LOOKS THAT WAY + + 18D9 A443 LDY SOURCE + 18DB B105 LDA (ARG1),Y ; ELSE GRAB NEXT CHAR + 18DD 205119 JSR BREAK ; IS IT A BREAK? + 18E0 B015 BCS READL3 ; YES IF CARRY WAS SET + + 18E2 A646 LDX WRDLEN ; ELSE STORE THE CHAR + 18E4 9537 STA IN,X ; INTO THE INPUT BUFFER + + 18E6 C645 DEC LINLEN ; ONE LESS CHAR IN LINE + 18E8 E646 INC WRDLEN ; ONE MORE IN WORD + 18EA E643 INC SOURCE ; POINT TO NEXT CHAR IN SOURCE + 18EC 4C8A18 JMP READL ; AND LOOP BACK + + 18EF 8537 DOSIB: STA IN ; PUT THE BREAK INTO 1ST WORD SLOT + 18F1 C645 DEC LINLEN ; ONE LESS CHAR IN LINE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 65 +--- READ HANDLER --- + + 18F3 E646 INC WRDLEN ; ONE MORE IN WORD BUFFER + 18F5 E643 INC SOURCE ; POINT TO NEXT SOURCE CHAR + + 18F7 A546 READL3: LDA WRDLEN ; ANY CHARS IN WORD YET? + 18F9 F08F BEQ READL ; APPARENTLY NOT, SO LOOP BACK + + 18FB 202D19 JSR EFIND ; GET ENTRY ADDR INTO [ENTRY] + 18FE A546 LDA WRDLEN ; GET ACTUAL LNGTH OF WORD + 1900 A002 LDY #2 ; STORE IT IN "WORD LENGTH" SLOT + 1902 9147 STA (ENTRY),Y ; OF THE CURRENT ENTRY + + 1904 20291C JSR CONZST ; CONVERT ASCII IN [IN] TO Z-STRING + 1907 207A19 JSR FINDW ; AND LOOK IT UP IN VOCABULARY + + 190A A001 LDY #1 + 190C B107 LDA (ARG2),Y ; FETCH THE # WORDS READ + 190E 18 CLC + 190F 6901 ADC #1 ; INCREMENT IT + 1911 9107 STA (ARG2),Y ; AND UPDATE + + 1913 202D19 JSR EFIND ; MAKE [ENTRY] POINT TO ENTRY + + 1916 A000 LDY #0 + 1918 8446 STY WRDLEN ; CLEAR # CHARS IN WORD + 191A A510 LDA VALUE+HI ; GET MSB OF VOCAB ENTRY ADDRESS + 191C 9147 STA (ENTRY),Y ; AND STORE IN 1ST SLOT OF ENTRY + 191E C8 INY + 191F A50F LDA VALUE+LO ; ALSO STORE LSB IN 2ND SLOT + 1921 9147 STA (ENTRY),Y + + 1923 A544 LDA RESULT ; UPDATE THE + 1925 18 CLC ; RESULT TABLE POINTER + 1926 6904 ADC #4 ; SO IT POINTS TO THE + 1928 8544 STA RESULT ; NEXT ENTRY + + 192A 4C8A18 JMP READL ; AND LOOP BACK + + 192D ; ----------------------------------- + 192D ; FIND BASE ADDR OF RESULT ENTRY SLOT + 192D ; ----------------------------------- + + 192D A507 EFIND: LDA ARG2+LO ; LSB OF RESULT TABLE BASE + 192F 18 CLC + 1930 6544 ADC RESULT ; AND CURRENT POINTER + 1932 8547 STA ENTRY+LO ; SAVE IN [ENTRY] + 1934 A508 LDA ARG2+HI ; ALSO ADD MSB + 1936 6900 ADC #0 + 1938 8548 STA ENTRY+HI + 193A 60 RTS + + 193B ; ---------- + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 66 +--- READ HANDLER --- + + 193B ; FLUSH WORD + 193B ; ---------- + + 193B A545 FLUSHW: LDA LINLEN ; ANY CHARS LEFT IN LINE? + 193D F011 BEQ FLEX ; NO, SCRAM + + 193F A443 LDY SOURCE ; GET CURRENT CHAR POINTER + 1941 B105 LDA (ARG1),Y ; AND GRAB A CHAR + 1943 205119 JSR BREAK ; IS IT A BREAK? + 1946 B008 BCS FLEX ; EXIT IF SO + 1948 C645 DEC LINLEN ; ELSE UPDATE CHAR COUNT + 194A E646 INC WRDLEN ; AND WORD-CHAR COUNT + 194C E643 INC SOURCE ; AND CHAR POINTER + 194E D0EB BNE FLUSHW ; AND LOOP BACK (ALWAYS) + + 1950 60 FLEX: RTS + + 1951 ; --------------------------------- + 1951 ; IS CHAR IN [A] ANY TYPE OF BREAK? + 1951 ; --------------------------------- + + 1951 206819 BREAK: JSR SIB ; CHECK FOR A SIB FIRST + 1954 B022 BCS FBRK ; EXIT NOW IF MATCHED + + 1956 ; ELSE FALL THROUGH ... + + 1956 ; -------------------------------- + 1956 ; IS CHAR IN [A] A "NORMAL" BREAK? + 1956 ; -------------------------------- + + 1956 A205 NORM: LDX #NBRKS-1 ; NUMBER OF "NORMAL" BREAKS + 1958 DD6219 NBL: CMP BRKTBL,X ; MATCHED? + 195B F01B BEQ FBRK ; YES, EXIT + 195D CA DEX + 195E 10F8 BPL NBL ; NO, KEEP LOOKING + 1960 18 CLC ; NO MATCH, CLEAR CARRY + 1961 60 RTS ; AND RETURN + + 1962 ; ------------------ + 1962 ; NORMAL BREAK CHARS + 1962 ; ------------------ + + 1962 213F2C2E BRKTBL: DB "!?,." ; IN ORDER OF + 1966 0D DB EOL ; ASCENDING FREQUENCY + 1967 20 DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED + + 0006 NBRKS EQU $-BRKTBL ; # NORMAL BREAKS + + 1968 ; --------------------- + 1968 ; IS CHAR IN [A] A SIB? + 1968 ; --------------------- + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 67 +--- READ HANDLER --- + + + 1968 AA SIB: TAX ; SAVE TEST CHAR + 1969 A000 LDY #0 ; 1ST BYTE IN VOCAB TABLE + 196B B131 LDA (VOCAB),Y ; HAS # SIBS + 196D A8 TAY ; USE AS AN INDEX + 196E 8A TXA ; RESTORE TEST CHAR + 196F D131 SBL: CMP (VOCAB),Y ; MATCHED? + 1971 F005 BEQ FBRK ; YES, REPORT IT + 1973 88 DEY + 1974 D0F9 BNE SBL ; ELSE KEEP LOOPING + 1976 18 CLC ; NO MATCH, SO + 1977 60 RTS ; EXIT WITH CARRY CLEAR + + 1978 38 FBRK: SEC ; EXIT WITH CARRY SET + 1979 60 RTS ; IF MATCHED WITH A BREAK CHAR + + 197A ; ----------------- + 197A ; VOCABULARY SEARCH + 197A ; ----------------- + + 197A ; ENTRY: 4-BYTE TARGET Z-WORD IN [OUT] + 197A ; EXIT: ABS ENTRY ADDRESS IN [VALUE] IF FOUND; + 197A ; OTHERWISE [VALUE] = 0 + + 197A A000 FINDW: LDY #0 ; GET # SIBS + 197C B131 LDA (VOCAB),Y ; IN VOCAB TABLE + 197E 18 CLC ; INCREMENT IT + 197F 6901 ADC #1 ; FOR PROPER ALIGNMENT + 1981 6531 ADC VOCAB+LO ; NOW ADD THE BASE ADDR OF THE TABLE + 1983 850F STA VALUE+LO ; TO GET THE ACTUAL BASE ADDR + 1985 A532 LDA VOCAB+HI ; OF THE VOCAB ENTRIES + 1987 6900 ADC #0 ; WHICH IS SAVED + 1989 8510 STA VALUE+HI ; IN [VALUE] + + 198B B10F LDA (VALUE),Y ; GET # BYTES PER ENTRY ([Y] = 0) + 198D 854B STA ESIZE ; SAVE IT HERE + + 198F 20B611 JSR INCVAL ; POINT TO NEXT BYTE + 1992 B10F LDA (VALUE),Y ; GET # ENTRIES IN TABLE (MSB) + 1994 854A STA NENTS+HI ; AND STUFF IT IN [NENTS] + + 1996 20B611 JSR INCVAL ; NEXT BYTE + 1999 B10F LDA (VALUE),Y ; DON'T FORGET THE LSB! + 199B 8549 STA NENTS+LO + + 199D 20B611 JSR INCVAL ; [VALUE] NOW POINTS TO 1ST ENTRY + + 19A0 ; BEGIN THE SEARCH! + + 19A0 A000 FWL1: LDY #0 + 19A2 B10F LDA (VALUE),Y ; GET 1ST BYTE OF ENTRY + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS PAGE 68 +--- READ HANDLER --- + + 19A4 C53D CMP OUT ; MATCHED 1ST BYTE OF TARGET? + 19A6 D015 BNE WNEXT ; NO, SKIP TO NEXT WORD + + 19A8 C8 INY + 19A9 B10F LDA (VALUE),Y + 19AB C53E CMP OUT+1 ; 2ND BYTE MATCHED? + 19AD D00E BNE WNEXT ; NOPE + + 19AF C8 INY + 19B0 B10F LDA (VALUE),Y + 19B2 C53F CMP OUT+2 ; 3RD BYTE? + 19B4 D007 BNE WNEXT ; SORRY ... + + 19B6 C8 INY + 19B7 B10F LDA (VALUE),Y + 19B9 C540 CMP OUT+3 ; LAST BYTE + 19BB F01F BEQ FWSUCC ; FOUND IT! + + 19BD A54B WNEXT: LDA ESIZE ; GET ENTRY SIZE + 19BF 18 CLC ; AND ADD IT TO ENTRY ADDRESS + 19C0 650F ADC VALUE+LO ; TO MAKE [VALUE] + 19C2 850F STA VALUE+LO ; POINT TO THE NEXT ENTRY + 19C4 9002 BCC WNX + 19C6 E610 INC VALUE+HI + + 19C8 A549 WNX: LDA NENTS+LO ; DECREMENT THE + 19CA 38 SEC ; ENTRY COUNTER + 19CB E901 SBC #1 + 19CD 8549 STA NENTS+LO + 19CF B002 BCS WNX1 + 19D1 C64A DEC NENTS+HI + + 19D3 054A WNX1: ORA NENTS+HI ; KEEP SEARCHING + 19D5 D0C9 BNE FWL1 ; UNTIL COUNT IS ZERO + + 19D7 850F STA VALUE+LO + 19D9 8510 STA VALUE+HI + 19DB 60 RTS ; THEN RETURN WITH [VALUE] = 0 + + 19DC ; ENTRY MATCHED! + + 19DC A510 FWSUCC: LDA VALUE+HI ; CONVERT ABSOLUTE ENTRY ADDRESS + 19DE 38 SEC ; IN [VALUE] + 19DF E526 SBC ZCODE ; TO RELATIVE Z-ADDRESS + 19E1 8510 STA VALUE+HI ; LSB NEEDN'T CHANGE + 19E3 60 RTS + + END + + INCLUD PAGING.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 69 +--- TIME-STAMP PAGING ROUTINE (BM 11/24/84) --- + + + 19E4 ; ------------------------- + 19E4 ; FETCH NEXT BYTE OF Z-CODE + 19E4 ; ------------------------- + + 19E4 ; EXIT: BYTE AT [ZPC] IN [A] & [Y]; FLAGS SET + + 19E4 A51C NEXTPC: LDA ZPCFLG ; IS [ZPCPNT] VALID? + 19E6 D01E BNE NPC2 ; YES, GET THE BYTE + + 19E8 ; Z-PAGE HAS CHANGED! + + 19E8 A51A LDA ZPCM ; GET TOP + 19EA A41B LDY ZPCH ; 9 BITS OF [ZPC] + 19EC D008 BNE NPC0 ; SWAP PAGE IF TOP BIT IS SET + + 19EE C527 CMP ZPURE ; IS THIS PAGE PRELOADED? + 19F0 B004 BCS NPC0 ; NO, SWAP IT IN + + 19F2 6526 ADC ZCODE ; ELSE MAKE IT ABSOLUTE + 19F4 D007 BNE NPC1 ; AND GIVE IT TO [ZPCPNT] + + 19F6 A200 NPC0: LDX #0 + 19F8 8622 STX MPCFLG ; INVALIDATE [MPC] + 19FA 20501A JSR PAGE ; AND GET ABS PAGE ADDR INTO [A] + + 19FD 851E NPC1: STA ZPCPNT+HI ; SET ABS PAGE ADDRESS + 19FF A2FF LDX #$FF + 1A01 861C STX ZPCFLG ; VALIDATE [ZPCPNT] + 1A03 E8 INX ; = 0 + 1A04 861D STX ZPCPNT+LO ; CLEAR LSB OF POINTER + + 1A06 A419 NPC2: LDY ZPCL ; FETCH PAGE INDEX + 1A08 B11D LDA (ZPCPNT),Y ; GET Z-BYTE + + 1A0A E619 INC ZPCL ; END OF PAGE YET? + 1A0C D00A BNE NPC3 ; NO, EXIT + + 1A0E A000 LDY #0 + 1A10 841C STY ZPCFLG ; ELSE INVALIDATE [ZPCPNT] + + 1A12 E61A INC ZPCM ; POINT [ZPC] TO + 1A14 D002 BNE NPC3 ; THE NEXT + 1A16 E61B INC ZPCH ; Z-PAGE + + 1A18 A8 NPC3: TAY ; SET FLAGS + 1A19 60 RTS ; AND RETURN + + 1A1A ; ------------------------------- + 1A1A ; GET NEXT BYTE OF VIRTUAL MEMORY + 1A1A ; ------------------------------- + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 70 +--- TIME-STAMP PAGING ROUTINE (BM 11/24/84) --- + + + 1A1A ; EXIT: BYTE AT [MPC] IN [A] & [Y]; FLAGS SET + + 1A1A A522 GETBYT: LDA MPCFLG ; IS [MPCPNT] VALID? + 1A1C D01E BNE GTBT2 ; YES, GET THE BYTE + + 1A1E ; Z-PAGE HAS CHANGED! + + 1A1E A520 LDA MPCM ; GET TOP + 1A20 A421 LDY MPCH ; 9 BITS OF [MPC] + 1A22 D008 BNE GTBT0 ; SWAP PAGE IF TOP BIT IS SET + + 1A25 PATCH EQU $+1 ; PATCH POINT FOR "VERIFY" + + 1A24 C527 CMP ZPURE ; IS THIS PAGE PRELOADED? + 1A26 B004 BCS GTBT0 ; NO, SWAP IT IN + + 1A28 6526 ADC ZCODE ; ELSE MAKE IT ABSOLUTE + 1A2A D007 BNE GTBT1 ; AND GIVE IT TO [MPCPNT] + + 1A2C A200 GTBT0: LDX #0 + 1A2E 861C STX ZPCFLG ; INVALIDATE [ZPC] + 1A30 20501A JSR PAGE ; AND GET ABS PAGE ADDR INTO [A] + + 1A33 8524 GTBT1: STA MPCPNT+HI ; SET ABS PAGE ADDRESS + 1A35 A2FF LDX #$FF + 1A37 8622 STX MPCFLG ; VALIDATE [MPCPNT] + 1A39 E8 INX ; = 0 + 1A3A 8623 STX MPCPNT+LO ; CLEAR LSB OF POINTER + + 1A3C A41F GTBT2: LDY MPCL ; FETCH PAGE INDEX + 1A3E B123 LDA (MPCPNT),Y ; GET Z-BYTE + + 1A40 E61F INC MPCL ; END OF PAGE YET? + 1A42 D00A BNE GTBT3 ; NO, EXIT + + 1A44 A000 LDY #0 + 1A46 8422 STY MPCFLG ; ELSE INVALIDATE [MPCPNT] + + 1A48 E620 INC MPCM ; POINT [MPC] TO + 1A4A D002 BNE GTBT3 ; THE NEXT + 1A4C E621 INC MPCH ; Z-PAGE + + 1A4E A8 GTBT3: TAY ; SET FLAGS + 1A4F 60 RTS ; AND RETURN + + 1A50 ; ------------------------ + 1A50 ; LOCATE A SWAPABLE Z-PAGE + 1A50 ; ------------------------ + + 1A50 ; ENTRY: TARGET Z-PAGE IN [A/Y] (9 BITS) + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 71 +--- TIME-STAMP PAGING ROUTINE (BM 11/24/84) --- + + 1A50 ; EXIT: ABSOLUTE PAGE IN [A] + + 1A50 852B PAGE: STA TARGET+LO ; SAVE THE + 1A52 842C STY TARGET+HI ; TARGET Z-PAGE HERE + + 1A54 ; IS THIS Z-PAGE ALREADY PAGED IN? + + 1A54 A200 LDX #0 + 1A56 862A STX ZPAGE ; START AT BUFFER #0 + + 1A58 DD000B PG1: CMP PTABL,X ; LSB MATCHED? + 1A5B D008 BNE PG2 ; NO, TRY NEXT BUFFER + 1A5D 98 TYA ; ELSE CHECK + 1A5E DDA00B CMP PTABH,X ; TOP BIT + 1A61 F02B BEQ PG4 ; MATCHED! BUFFER IN [ZPAGE] + 1A63 A52B LDA TARGET+LO ; ELSE RESTORE LSB + 1A65 E62A PG2: INC ZPAGE ; UPDATE TALLY + 1A67 E8 INX + 1A68 E429 CPX PMAX ; OUT OF BUFFERS YET? + 1A6A 90EC BCC PG1 ; NO, KEEP SEARCHING + + 1A6C ; SWAP IN THE TARGET PAGE + + 1A6C 20C71A PG3: JSR EARLY ; GET EARLIEST PAGE + 1A6F A62E LDX SWAP ; INTO [SWAP] & [X] + 1A71 862A STX ZPAGE ; SAVE FOR LATER + + 1A73 A52B LDA TARGET+LO ; ASSIGN THE TARGET PAGE + 1A75 9D000B STA PTABL,X ; TO THE EARLIEST BUFFER + 1A78 8570 STA DBLOCK+LO ; ALSO GIVE IT TO ZDOS + + 1A7A A52C LDA TARGET+HI ; SAME FOR TOP BIT + 1A7C 2901 AND #%00000001 ; USE ONLY BIT 0 + 1A7E 9DA00B STA PTABH,X + 1A81 8571 STA DBLOCK+HI + + 1A83 8A TXA + 1A84 18 CLC + 1A85 6528 ADC PAGE0 ; CALC ABS ADDR OF BUFFER + 1A87 8573 STA DBUFF+HI ; GIVE IT TO ZDOS + + 1A89 208A23 JSR GETDSK ; SWAP IN THE NEW PAGE + 1A8C B034 BCS DISKE ; ERROR IF CARRY SET + + 1A8E ; UPDATE THE TIMESTAMP + + 1A8E A42A PG4: LDY ZPAGE ; GET THE BUFFER INDEX + 1A90 B9500C LDA LRUMAP,Y ; GET THIS BUFFER'S STAMP + 1A93 C52D CMP STAMP ; SAME AS CURRENT STAMP? + 1A95 F025 BEQ PG8 ; YES, EXIT + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 72 +--- TIME-STAMP PAGING ROUTINE (BM 11/24/84) --- + + 1A97 E62D INC STAMP ; UPDATE STAMP + 1A99 D01C BNE PG7 ; CONTINUE IF NO OVERFLOW + + 1A9B ; HANDLE STAMP OVERFLOW + + 1A9B 20C71A JSR EARLY ; GET EARLIEST STAMP INTO [LRU] + + 1A9E A200 LDX #0 ; INIT INDEX + 1AA0 BD500C PG5: LDA LRUMAP,X ; GET A STAMP READING + 1AA3 F006 BEQ PG6 ; EXIT IF ALREADY ZERO + 1AA5 38 SEC ; ELSE SUBTRACT OFF + 1AA6 E525 SBC LRU ; THE EARLIEST TIMESTAMP + 1AA8 9D500C STA LRUMAP,X ; AND REPLACE THE STAMP + 1AAB E8 PG6: INX + 1AAC E429 CPX PMAX ; END OF SWAPPING SPACE? + 1AAE 90F0 BCC PG5 ; LOOP TILL ALL STAMPS FIXED + + 1AB0 A900 LDA #0 ; TURN BACK THE CLOCK + 1AB2 38 SEC ; TO REFLECT NEW + 1AB3 E525 SBC LRU ; STAMP READING + 1AB5 852D STA STAMP + + 1AB7 A52D PG7: LDA STAMP ; FETCH STAMP + 1AB9 99500C STA LRUMAP,Y ; STAMP TARGET PAGE WITH IT + + 1ABC A52A PG8: LDA ZPAGE ; GET BUFFER INDEX + 1ABE 18 CLC ; MAKE IT + 1ABF 6528 ADC PAGE0 ; ABSOLUTE + 1AC1 60 RTS ; AND RETURN IT IN [A] + + 1AC2 ; *** ERROR #14: DRIVE ACCESS *** + + 1AC2 A90E DISKE: LDA #14 + 1AC4 4CC41D JMP ZERROR + + 1AC7 ; ------------------------- + 1AC7 ; LOCATE EARLIEST TIMESTAMP + 1AC7 ; ------------------------- + + 1AC7 ; EXIT: [LRU] - EARLIEST TIMESTAMP + 1AC7 ; [SWAP] = INDEX TO EARLIEST BUFFER + + 1AC7 A200 EARLY: LDX #0 ; INIT INDEX + 1AC9 862E STX SWAP ; AND [SWAP] + 1ACB AD500C LDA LRUMAP ; GET STAMP OF BUFFER #0 + 1ACE E8 INX ; START COMPARE WITH BUFFER #1 + 1ACF DD500C EAR0: CMP LRUMAP,X ; IS THIS STAMP EARLIER THAN [A]? + 1AD2 9005 BCC EAR1 ; NO, TRY NEXT STAMP + 1AD4 BD500C LDA LRUMAP,X ; ELSE FETCH EARLIER ENTRY + 1AD7 862E STX SWAP ; AND REMEMBER WHERE WE FOUND IT + 1AD9 E8 EAR1: INX ; POINT TO NEXT STAMP + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 73 +--- TIME-STAMP PAGING ROUTINE (BM 11/24/84) --- + + 1ADA E429 CPX PMAX ; OUT OF STAMPS YET? + 1ADC 90F1 BCC EAR0 ; LOOP TILL EMPTY + + 1ADE 8525 STA LRU ; SAVE EARLIEST STAMP HERE + 1AE0 60 RTS + + 1AE1 ; ------------------------- + 1AE1 ; POINT [MPC] TO V-ADDR [I] + 1AE1 ; ------------------------- + + 1AE1 A511 SETWRD: LDA I+LO + 1AE3 851F STA MPCL + 1AE5 A512 LDA I+HI + 1AE7 8520 STA MPCM + + 1AE9 A900 LDA #0 + 1AEB 8521 STA MPCH ; ZERO TOP BIT + 1AED 8522 STA MPCFLG ; INVALIDATE [MPC] + 1AEF 60 RTS + + 1AF0 ; ---------------------------- + 1AF0 ; GET Z-WORD AT [MPC] INTO [I] + 1AF0 ; ---------------------------- + + 1AF0 201A1A GETWRD: JSR GETBYT + 1AF3 8512 STA I+HI + 1AF5 201A1A JSR GETBYT + 1AF8 8511 STA I+LO + 1AFA 60 RTS + + END + INCLUD ZSTRING.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 74 +--- Z-STRING HANDLERS --- + + + 1AFB ; ----------------------- + 1AFB ; POINT TO ZSTRING IN [I] + 1AFB ; ----------------------- + + 1AFB A511 SETSTR: LDA I+LO ; WORD-ALIGN THE ADDRESS + 1AFD 0A ASL A + 1AFE 851F STA MPCL + 1B00 A512 LDA I+HI + 1B02 2A ROL A + 1B03 8520 STA MPCM + 1B05 A900 LDA #0 + 1B07 8522 STA MPCFLG ; [MPC] IS CHANGING! + 1B09 2A ROL A + 1B0A 8521 STA MPCH + + 1B0C 60 ZSTEX: RTS + + 1B0D ; ----------------------- + 1B0D ; PRINT Z-STRING AT [MPC] + 1B0D ; ----------------------- + + 1B0D A200 PZSTR: LDX #0 + 1B0F 864C STX PSET ; ASSUME PERMANENT CHARSET + 1B11 8650 STX ZFLAG ; CLEAR BYTE FLAG + 1B13 CA DEX ; = $FF + 1B14 864D STX TSET ; NO TEMPSET ACTIVE + + 1B16 20E11B PZTOP: JSR GETZCH ; GET A Z-CHAR + 1B19 B0F1 BCS ZSTEX ; END OF STRING IF CARRY IS SET + + 1B1B 854E STA ZCHAR ; ELSE SAVE CHAR HERE + 1B1D AA TAX ; SET FLAGS + 1B1E F041 BEQ BLANK ; PRINT SPACE IF CHAR = 0 + + 1B20 C904 CMP #4 ; IS THIS AN F-WORD? + 1B22 905B BCC DOFREQ ; APPARENTLY SO + + 1B24 C906 CMP #6 ; PERHAPS A SHIFT CODE? + 1B26 903D BCC NEWSET ; YES, CHANGE CHARSETS + + 1B28 20D51B JSR GETSET ; ELSE GET CHARSET + 1B2B AA TAX ; SET FLAGS + 1B2C D00B BNE SET1 ; SKIP IF NOT CHARSET #0 + + 1B2E ; PRINT A LOWER-CASE CHAR (CHARSET #0) + + 1B2E A95B LDA #$61-6 ; ASCII "a" MINUS Z-OFFSET + + 1B30 18 TOASC: CLC + 1B31 654E ADC ZCHAR ; ADD Z-CHAR INDEX + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 75 +--- Z-STRING HANDLERS --- + + + 1B33 20451E SHOVE: JSR COUT ; SHOW THE CHAR + 1B36 4C161B JMP PZTOP ; AND GRAB NEXT CHAR + + 1B39 ; PRINT AN UPPER-CASE CHAR (CHARSET #1) + + 1B39 C901 SET1: CMP #1 ; MAKE SURE IT'S SET #1 + 1B3B D004 BNE SET2 ; ELSE MUST BE SET #2 + + 1B3D A93B LDA #$41-6 ; ASCII "A" MINUS Z-OFFSET + 1B3F D0EF BNE TOASC ; SAME AS SET #0 + + 1B41 ; PRINT FROM CHARSET #2 + + 1B41 A54E SET2: LDA ZCHAR ; RETRIEVE THE Z-CHAR + 1B43 38 SEC + 1B44 E906 SBC #6 ; ZERO-ALIGN IT + 1B46 F007 BEQ DIRECT ; IF ZERO, IT'S A "DIRECT" ASCII + + 1B48 AA TAX ; OTHERWISE USE CODE AS AN INDEX + 1B49 BDFE1C LDA CHRTBL,X ; INTO THE CHARSET TABLE + 1B4C 4C331B JMP SHOVE ; AND PRINT THE CHAR + + 1B4F ; DECODE A "DIRECT" ASCII CHAR + + 1B4F 20E11B DIRECT: JSR GETZCH ; FETCH NEXT Z-CHAR + 1B52 0A ASL A + 1B53 0A ASL A + 1B54 0A ASL A + 1B55 0A ASL A + 1B56 0A ASL A ; SHIFT INTO POSITION + 1B57 854E STA ZCHAR ; AND SAVE HERE + 1B59 20E11B JSR GETZCH ; GRAB YET ANOTHER Z-CHAR + 1B5C 054E ORA ZCHAR ; SUPERIMPOSE THE 2ND BYTE + 1B5E 4C331B JMP SHOVE ; AND PRINT THE RESULT + + 1B61 ; PRINT A SPACE + + 1B61 A920 BLANK: LDA #SPACE ; ASCII SPACE CHAR + 1B63 D0CE BNE SHOVE + + 1B65 ; CHANGE CHARSET + + 1B65 38 NEWSET: SEC ; CONVERT THE SHIFT CODE + 1B66 E903 SBC #3 ; TO 1 OR 2 + 1B68 A8 TAY + 1B69 20D51B JSR GETSET ; IS MODE TEMPORARY? + 1B6C D005 BNE TOPERM ; YES, DO A PERMSHIFT + 1B6E 844D STY TSET ; ELSE JUST A TEMPSHIFT + 1B70 4C161B JMP PZTOP ; AND CONTINUE + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 76 +--- Z-STRING HANDLERS --- + + 1B73 844C TOPERM: STY PSET ; SET PERM CHARSET + 1B75 C54C CMP PSET ; SAME AS BEFORE? + 1B77 F09D BEQ PZTOP ; YES, CONTINUE + 1B79 A900 LDA #0 + 1B7B 854C STA PSET ; ELSE RESET CHARSET + 1B7D F097 BEQ PZTOP ; BEFORE LOOPING BACK + + 1B7F ; PRINT AN F-WORD + + 1B7F 38 DOFREQ: SEC + 1B80 E901 SBC #1 ; ZERO-ALIGN THE CODE + 1B82 0A ASL A ; AND MULTIPLY TIMES 64 + 1B83 0A ASL A ; TO OBTAIN THE SEGMENT OFFSET + 1B84 0A ASL A ; INTO THE F-WORDS TABLE + 1B85 0A ASL A + 1B86 0A ASL A + 1B87 0A ASL A + 1B88 854F STA OFFSET ; SAVE OFFSET FOR LATER + + 1B8A 20E11B JSR GETZCH ; NOW GET THE F-WORD POINTER + 1B8D 0A ASL A ; WORD-ALIGN IT + 1B8E 18 CLC ; AND + 1B8F 654F ADC OFFSET ; ADD THE SEGMENT OFFSET + 1B91 A8 TAY ; TO GET THE OFFSET OF THE F-WORD + 1B92 B133 LDA (FWORDS),Y ; FROM THE START OF THE F-WORDS TABLE + 1B94 8512 STA I+HI ; SAVE MSB OF F-WORD ADDRESS + 1B96 C8 INY + 1B97 B133 LDA (FWORDS),Y ; ALSO SAVE LSB + 1B99 8511 STA I+LO ; Z-ADDRESS OF F-WORD IS IN [I] + + 1B9B ; SAVE THE STATE OF CURRENT Z-STRING + + 1B9B A521 LDA MPCH + 1B9D 48 PHA + 1B9E A520 LDA MPCM + 1BA0 48 PHA + 1BA1 A51F LDA MPCL + 1BA3 48 PHA + 1BA4 A54C LDA PSET + 1BA6 48 PHA + 1BA7 A550 LDA ZFLAG + 1BA9 48 PHA + 1BAA A552 LDA ZWORD+HI + 1BAC 48 PHA + 1BAD A551 LDA ZWORD+LO + 1BAF 48 PHA + + 1BB0 20FB1A JSR SETSTR ; PRINT THE Z-STRING + 1BB3 200D1B JSR PZSTR ; IN [I] + + 1BB6 ; RESTORE OLD Z-STRING + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 77 +--- Z-STRING HANDLERS --- + + + 1BB6 68 PLA + 1BB7 8551 STA ZWORD+LO + 1BB9 68 PLA + 1BBA 8552 STA ZWORD+HI + 1BBC 68 PLA + 1BBD 8550 STA ZFLAG + 1BBF 68 PLA + 1BC0 854C STA PSET + 1BC2 68 PLA + 1BC3 851F STA MPCL + 1BC5 68 PLA + 1BC6 8520 STA MPCM + 1BC8 68 PLA + 1BC9 8521 STA MPCH + + 1BCB A2FF LDX #$FF + 1BCD 864D STX TSET ; DISABLE TEMP CHARSET + 1BCF E8 INX ; = 0 + 1BD0 8622 STX MPCFLG ; [MPC] HAS CHANGED + 1BD2 4C161B JMP PZTOP ; CONTINUE INNOCENTLY + + 1BD5 ; ---------------------- + 1BD5 ; RETURN CURRENT CHARSET + 1BD5 ; ---------------------- + + 1BD5 A54D GETSET: LDA TSET + 1BD7 1003 BPL GS + 1BD9 A54C LDA PSET + 1BDB 60 RTS + + 1BDC A0FF GS: LDY #$FF + 1BDE 844D STY TSET + 1BE0 60 RTS + + 1BE1 ; ----------------- + 1BE1 ; FETCH NEXT Z-CHAR + 1BE1 ; ----------------- + + 1BE1 A550 GETZCH: LDA ZFLAG ; WHICH BYTE IS THIS? + 1BE3 1002 BPL GTZ0 ; $FF = LAST + 1BE5 38 SEC ; SET CARRY TO INDICATE + 1BE6 60 RTS ; NO MORE CHARS + + 1BE7 D013 GTZ0: BNE GETZ1 ; NOT FIRST CHAR, EITHER + + 1BE9 ; GET A Z-WORD INTO [ZWORD], RETURN 1ST CHAR IN TRIPLET + + 1BE9 E650 INC ZFLAG ; UPDATE CHAR COUNT + + 1BEB 201A1A JSR GETBYT ; GET TRIPLET AT [MPC] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 78 +--- Z-STRING HANDLERS --- + + 1BEE 8552 STA ZWORD+HI ; INTO [ZWORD] + 1BF0 201A1A JSR GETBYT + 1BF3 8551 STA ZWORD+LO + + 1BF5 A552 LDA ZWORD+HI + 1BF7 4A LSR A + 1BF8 4A LSR A ; SHIFT 1ST CHAR INTO PLACE + 1BF9 4C251C JMP GTEXIT ; AND RETURN IT + + 1BFC 38 GETZ1: SEC + 1BFD E901 SBC #1 + 1BFF D016 BNE GETZ2 ; LAST CHAR IN TRIPLET IF ZERO + 1C01 A902 LDA #2 ; ELSE + 1C03 8550 STA ZFLAG ; RESET CHAR INDEX + + 1C05 A551 LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET + 1C07 8511 STA I+LO ; MOVE HERE FOR SHIFTING + 1C09 A552 LDA ZWORD+HI ; GET TOP HALF + + 1C0B 0611 ASL I+LO ; SHIFT THE TOP 3 BITS OF LOWER HALF + 1C0D 2A ROL A ; INTO THE BOTTOM OF THE TOP HALF + 1C0E 0611 ASL I+LO + 1C10 2A ROL A + 1C11 0611 ASL I+LO + 1C13 2A ROL A + 1C14 4C251C JMP GTEXIT + + 1C17 A900 GETZ2: LDA #0 ; SET FLAG TO INDICATE + 1C19 8550 STA ZFLAG ; END OF TRIPLET + + 1C1B A552 LDA ZWORD+HI ; TEST TOP HALF OF TRIPLET + 1C1D 1004 BPL GETZ3 ; CONTINUE IF NOT END OF STRING + 1C1F A9FF LDA #$FF ; ELSE + 1C21 8550 STA ZFLAG ; INDICATE LAST TRIPLET IN STRING + + 1C23 A551 GETZ3: LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET + + 1C25 291F GTEXIT: AND #%00011111 ; MASK OUT GARBAGE BITS + 1C27 18 CLC + 1C28 60 RTS + + 1C29 ; --------------------------------- + 1C29 ; CONVERT [IN] TO Z-STRING IN [OUT] + 1C29 ; --------------------------------- + + 1C29 A905 CONZST: LDA #$05 ; FILL OUTPUT BUFFER + 1C2B AA TAX ; WITH PAD CHARS ($05) + 1C2C 953D CZSL: STA OUT,X + 1C2E CA DEX + 1C2F 10FB BPL CZSL + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 79 +--- Z-STRING HANDLERS --- + + 1C31 A906 LDA #6 ; INIT + 1C33 8553 STA CONCNT ; CHAR COUNT + + 1C35 A900 LDA #0 ; CLEAR + 1C37 8554 STA CONIN ; SOURCE AND + 1C39 8555 STA CONOUT ; OUTPUT INDEXES + + 1C3B A654 CONTOP: LDX CONIN ; FETCH SOURCE INDEX + 1C3D E654 INC CONIN ; AND UPDATE + 1C3F B537 LDA IN,X ; GRAB AN ASCII CHAR + 1C41 854E STA ZCHAR ; SAVE IT HERE + 1C43 D004 BNE NEXTZ ; CONTINUE IF CHAR WAS NZ + + 1C45 A905 LDA #5 ; ELSE SHIP OUT + 1C47 D02C BNE CSHIP ; A PAD CHAR + + 1C49 A54E NEXTZ: LDA ZCHAR + 1C4B 20BF1C JSR SAYSET ; WHICH CHARSET TO USE? + 1C4E F020 BEQ CSET0 ; LOWER-CASE IF ZERO + + 1C50 18 CLC ; ELSE DO A TEMP-SHIFT + 1C51 6903 ADC #3 ; 4 = CHARSET 1, 5 = CHARSET 2 + 1C53 A655 LDX CONOUT ; FETCH OUTPUT INDEX + 1C55 953D STA OUT,X ; SEND THE SHIFT CHAR + + 1C57 E655 INC CONOUT ; UPDATE INDEX + 1C59 C653 DEC CONCNT ; AND CHAR COUNT + 1C5B D003 BNE CTEST ; IF OUT OF CHARS + 1C5D 4CD81C JMP ZCRUSH ; CRUSH 'EM! + + 1C60 A54E CTEST: LDA ZCHAR ; TEST CHAR AGAIN + 1C62 20BF1C JSR SAYSET + 1C65 C902 CMP #2 + 1C67 F019 BEQ CSET2 ; CHARSET #2 + + 1C69 ; HANDLE CHARSET #1 (UPPER CASE ALPHA) + + 1C69 A54E LDA ZCHAR + 1C6B 38 SEC + 1C6C E93B SBC #$41-6 ; CONVERT TO Z-CHAR + 1C6E 1005 BPL CSHIP ; AND SEND TO OUTPUT + + 1C70 ; HANDLE CHARSET #0 (LOWER CASE ALPHA) + + 1C70 A54E CSET0: LDA ZCHAR + 1C72 38 SEC + 1C73 E95B SBC #$61-6 ; CONVERT TO Z-CHAR + + 1C75 ; SHIP Z-CHAR TO OUTPUT BUFFER + + 1C75 A655 CSHIP: LDX CONOUT ; FETCH OUTPUT INDEX + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 80 +--- Z-STRING HANDLERS --- + + 1C77 953D STA OUT,X + + 1C79 E655 INC CONOUT ; UPDATE INDEX + 1C7B C653 DEC CONCNT ; DONE 6 CHARS YET? + 1C7D D0BC BNE CONTOP ; NO, LOOP BACK + 1C7F 4CD81C JMP ZCRUSH ; ELSE CRUSH + + 1C82 ; HANDLE CHARSET #2 (MISCELLANEOUS) + + 1C82 A54E CSET2: LDA ZCHAR ; GRAB CHAR + 1C84 20AF1C JSR CTABLE ; IS IT IN CHARSET #3 TABLE? + 1C87 D0EC BNE CSHIP ; YES, SEND IT TO OUTPUT + + 1C89 ; SEND A "DIRECT" ASCII CHAR + + 1C89 A906 LDA #6 ; ASCII ALERT! + 1C8B A655 LDX CONOUT + 1C8D 953D STA OUT,X + + 1C8F E655 INC CONOUT ; UPDATE INDEX + 1C91 C653 DEC CONCNT ; AND CHAR COUNT + 1C93 F043 BEQ ZCRUSH ; BUFFER FULL! + + 1C95 ; SEND 1ST HALF OF "DIRECT" + + 1C95 A54E LDA ZCHAR + 1C97 4A LSR A + 1C98 4A LSR A + 1C99 4A LSR A + 1C9A 4A LSR A + 1C9B 4A LSR A + 1C9C 2903 AND #%00000011 ; MASK GARBAGE + 1C9E A655 LDX CONOUT + 1CA0 953D STA OUT,X + + 1CA2 E655 INC CONOUT + 1CA4 C653 DEC CONCNT + 1CA6 F030 BEQ ZCRUSH ; BUFFER FULL! + + 1CA8 ; SEND 2ND HALF OF "DIRECT" + + 1CA8 A54E LDA ZCHAR ; GET CHAR YET AGAIN + 1CAA 291F AND #%00011111 ; MASK JUNK + 1CAC 4C751C JMP CSHIP ; AND SHIP IT OUT + + 1CAF ; --------------------- + 1CAF ; IS [A] IN CHARSET #3? + 1CAF ; --------------------- + + 1CAF ; EXIT: [A] = CHAR CODE IF FOUND, Z-FLAG CLEARED + 1CAF ; Z-FLAG SET IF NOT FOUND + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 81 +--- Z-STRING HANDLERS --- + + + 1CAF A219 CTABLE: LDX #25 + 1CB1 DDFE1C CNL: CMP CHRTBL,X + 1CB4 F004 BEQ CNOK + 1CB6 CA DEX + 1CB7 D0F8 BNE CNL + 1CB9 60 RTS ; Z-FLAG SET IF NO MATCH + + 1CBA 8A CNOK: TXA ; CHAR CODE IS INDEX + 1CBB 18 CLC + 1CBC 6906 ADC #6 ; PLUS 6 + 1CBE 60 RTS + + 1CBF ; ----------------------------- + 1CBF ; RETURN CHARSET OF CHAR IN [A] + 1CBF ; ----------------------------- + + 1CBF C961 SAYSET: CMP #'a' + 1CC1 9007 BCC SAY1 + 1CC3 C97B CMP #'z'+1 + 1CC5 B003 BCS SAY1 + 1CC7 A900 LDA #0 ; IT'S CHARSET #0 + 1CC9 60 RTS + + 1CCA C941 SAY1: CMP #'A' + 1CCC 9007 BCC SAY2 + 1CCE C95B CMP #'Z'+1 + 1CD0 B003 BCS SAY2 + 1CD2 A901 LDA #1 ; IT'S CHARSET #1 + 1CD4 60 RTS + + 1CD5 A902 SAY2: LDA #2 ; IT'S CHARSET #2 + 1CD7 60 RTS + + 1CD8 ; ---------------------- + 1CD8 ; CRUSH Z-CHARS IN [OUT] + 1CD8 ; ---------------------- + + 1CD8 A53E ZCRUSH: LDA OUT+1 ; GET 2ND Z-CHAR + 1CDA 0A ASL A ; SHIFT BITS INTO POSITION + 1CDB 0A ASL A + 1CDC 0A ASL A + 1CDD 0A ASL A + 1CDE 263D ROL OUT ; ALONG WITH 1ST Z-CHAR + 1CE0 0A ASL A + 1CE1 263D ROL OUT + 1CE3 053F ORA OUT+2 ; SUPERIMPOSE 3RD Z-CHAR + 1CE5 853E STA OUT+1 + + 1CE7 A541 LDA OUT+4 ; GET 5TH Z-CHAR + 1CE9 0A ASL A ; SHIFT BITS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 82 +--- Z-STRING HANDLERS --- + + 1CEA 0A ASL A + 1CEB 0A ASL A + 1CEC 0A ASL A + 1CED 2640 ROL OUT+3 ; ALONG WITH 4TH Z-CHAR + 1CEF 0A ASL A + 1CF0 2640 ROL OUT+3 + 1CF2 0542 ORA OUT+5 ; SUPERIMPOSE 6TH Z-CHAR + 1CF4 AA TAX ; SAVE HERE + 1CF5 A540 LDA OUT+3 ; GRAB 4TH Z-CHAR + 1CF7 0980 ORA #%10000000 ; SET HIGH BIT + 1CF9 853F STA OUT+2 ; MOVE CRUSHED Z-WORD + 1CFB 8640 STX OUT+3 ; INTO PLACE + 1CFD 60 RTS + + 1CFE ; ----------------------- + 1CFE ; CHARSET #2 DECODE TABLE + 1CFE ; ----------------------- + + 1CFE 00 CHRTBL: DB 0 ; DUMMY BYTE FOR "DIRECT" + 1CFF 0D DB $0D ; EOL + 1D00 30313233 DB "0123456789.,!?_#" + 1D10 27 DB $27 ; SINGLE QUOTE + 1D11 22 DB $22 ; DOUBLE QUOTE + 1D12 2F5C2D3A DB "/\-:()" + + END + INCLUD OBJECTS.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 83 +--- OBJECT & PROPERTY HANDLERS --- + + + 1D18 ; ---------------------------------- + 1D18 ; GET ABSOLUTE ADDRESS OF OBJECT [A] + 1D18 ; ---------------------------------- + + 1D18 ; EXIT: ADDRESS IN [I] + + 1D18 8511 OBJLOC: STA I+LO ; SAVE LSB FOR ADDING + + 1D1A A200 LDX #0 ; CLEAR MSB + 1D1C 8612 STX I+HI ; FOR SHIFTING + + 1D1E 0A ASL A ; MULTIPLY BY 8 + 1D1F 2612 ROL I+HI + 1D21 0A ASL A + 1D22 2612 ROL I+HI + 1D24 0A ASL A + 1D25 2612 ROL I+HI + + 1D27 18 CLC ; ADD TO ITSELF + 1D28 6511 ADC I+LO ; TO GET TIMES 9 + 1D2A 9002 BCC OBJ1 + 1D2C E612 INC I+HI + + 1D2E 18 OBJ1: CLC + 1D2F 6935 ADC #53 ; NOW ADD 53 + 1D31 9002 BCC OBJ2 ; (THE OBJECT TABLE OFFSET) + 1D33 E612 INC I+HI + + 1D35 18 OBJ2: CLC ; NEXT ADD THE ABS ADDR + 1D36 6535 ADC OBJTAB+LO ; OF THE OBJECT TABLE + 1D38 8511 STA I+LO + + 1D3A A512 LDA I+HI + 1D3C 6536 ADC OBJTAB+HI + 1D3E 8512 STA I+HI + 1D40 60 RTS + + 1D41 ; ----------------------------- + 1D41 ; GET ADDRESS OF PROPERTY TABLE + 1D41 ; ----------------------------- + + 1D41 ; EXIT: [I] HAS ABSOLUTE ADDR OF PROPERTY TABLE + 1D41 ; [Y] HAS OFFSET TO START OF PROP IDS + + 1D41 A505 PROPB: LDA ARG1+LO + 1D43 20181D JSR OBJLOC + 1D46 A007 LDY #7 + 1D48 B111 LDA (I),Y ; GET MSB OF P-TABLE ADDRESS + 1D4A 18 CLC + 1D4B 6526 ADC ZCODE ; MAKE IT ABSOLUTE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 84 +--- OBJECT & PROPERTY HANDLERS --- + + 1D4D AA TAX ; AND SAVE HERE + 1D4E C8 INY + 1D4F B111 LDA (I),Y ; NOW GET LSB + 1D51 8511 STA I+LO + 1D53 8612 STX I+HI ; [I] NOW POINTS TO PROP TABLE + + 1D55 A000 LDY #0 + 1D57 B111 LDA (I),Y ; GET LENGTH OF SHORT DESC + 1D59 0A ASL A ; WORD-ALIGN IT + 1D5A A8 TAY ; EXPECTED HERE + 1D5B C8 INY ; POINT JUST PAST THE DESCRIPTION + 1D5C 60 RTS + + 1D5D ; ------------------- + 1D5D ; FETCH A PROPERTY ID + 1D5D ; ------------------- + + 1D5D ; ENTRY: LIKE "PROPB" EXIT + + 1D5D B111 PROPN: LDA (I),Y + 1D5F 291F AND #%00011111 ; MASK OUT LENGTH BITS + 1D61 60 RTS + + 1D62 ; ------------------------------- + 1D62 ; FETCH # BYTES IN PROPERTY VALUE + 1D62 ; ------------------------------- + + 1D62 ; ENTRY: LIKE "PROPB" EXIT + + 1D62 B111 PROPL: LDA (I),Y + 1D64 4A LSR A ; LENGTH IS IN + 1D65 4A LSR A ; BITS 7-5 + 1D66 4A LSR A ; SO SHIFT INTO PLACE + 1D67 4A LSR A + 1D68 4A LSR A + 1D69 60 RTS + + 1D6A ; ---------------------- + 1D6A ; POINT TO NEXT PROPERTY + 1D6A ; ---------------------- + + 1D6A ; ENTRY: LIKE "PROPB" EXIT + + 1D6A 20621D PROPNX: JSR PROPL ; GET LENGTH OF CURRENT PROP + 1D6D AA TAX ; SAVE HERE + + 1D6E C8 PPX: INY ; LOOP UNTIL + 1D6F CA DEX ; [Y] POINTS TO + 1D70 10FC BPL PPX ; START OF NEXT PROP + 1D72 C8 INY ; CORRECT ALIGNMENT + 1D73 60 RTS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 85 +--- OBJECT & PROPERTY HANDLERS --- + + + 1D74 ; ---------------- + 1D74 ; GET OBJECT FLAGS + 1D74 ; ---------------- + + 1D74 ; ENTRY: OBJECT # IN [ARG1], FLAG # IN [ARG2] + 1D74 ; EXIT: FLAG WORD IN [K], BIT ID IN [J], + 1D74 ; FLAG WORD ADDRESS IN [I] + + 1D74 A505 FLAGSU: LDA ARG1+LO + 1D76 20181D JSR OBJLOC ; GET OBJECT ADDR IN [I] + + 1D79 A507 LDA ARG2+LO ; LOOK AT FLAG ID + 1D7B C910 CMP #$10 ; FIRST SET OF FLAGS? + 1D7D 900F BCC FLS1 ; YES, ADDR IN [I] IS CORRECT + + 1D7F E910 SBC #16 ; ELSE ZERO-ALIGN FLAG INDEX + 1D81 AA TAX ; SAVE IT HERE + + 1D82 A511 LDA I+LO ; ADD 2 TO ADDRESS IN [I] + 1D84 18 CLC ; TO POINT TO ADDRESS OF + 1D85 6902 ADC #2 ; 2ND FLAG WORD + 1D87 8511 STA I+LO + 1D89 9002 BCC FLS0 + 1D8B E612 INC I+HI + + 1D8D 8A FLS0: TXA ; RESTORE INDEX + + 1D8E 8515 FLS1: STA K+LO ; SAVE FLAG ID HERE + + 1D90 A201 LDX #1 ; INIT THE + 1D92 8613 STX J+LO ; FLAG WORD TO + 1D94 CA DEX ; $0001 + 1D95 8614 STX J+HI + + 1D97 A90F LDA #15 ; SUBTRACT THE BIT POSITION + 1D99 38 SEC ; FROM 15 + 1D9A E515 SBC K+LO ; TO GET THE SHIFT LOOP + 1D9C AA TAX ; INDEX + 1D9D F007 BEQ FLS2 ; EXIT NOW IF NO SHIFT NEEDED + + 1D9F 0613 FLSL: ASL J+LO ; SHIFT THE BIT + 1DA1 2614 ROL J+HI ; INTO POSITION + 1DA3 CA DEX + 1DA4 D0F9 BNE FLSL + + 1DA6 A000 FLS2: LDY #0 ; MOVE THE FLAG WORD + 1DA8 B111 LDA (I),Y ; INTO [J] + 1DAA 8516 STA K+HI ; FIRST THE MSB + 1DAC C8 INY + 1DAD B111 LDA (I),Y + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 86 +--- OBJECT & PROPERTY HANDLERS --- + + 1DAF 8515 STA K+LO ; THEN THE LSB + 1DB1 60 RTS + + END + + INCLUD IO.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 87 +--- GAME I/O: CBM64 --- + + + 1DB2 ; -------------- + 1DB2 ; INTERNAL ERROR + 1DB2 ; -------------- + + 1DB2 ; ENTRY: ERROR CODE IN [A] + + 1DB2 496E7465 ERRM: DB "Internal error " + 1DC1 30302E ENUMB: DB "00." + 0012 ERRML EQU $-ERRM + + 1DC4 A001 ZERROR: LDY #1 ; CONVERT ERROR BYTE IN [A] + 1DC6 20DD27 ECON: JSR DIV10 ; TO ASCII DECIMAL IN [ENUMB] + 1DC9 0930 ORA #'0' + 1DCB 99C11D STA ENUMB,Y + 1DCE 8A TXA + 1DCF 88 DEY + 1DD0 10F4 BPL ECON + + 1DD2 20CCFF JSR CLRCHN + 1DD5 20831E JSR ZCRLF ; CLEAR BUFFER + 1DD8 A900 LDA #0 + 1DDA 8562 STA SCRIPT ; DISABLE SCRIPTING + + 1DDC A2B2 LDX #LOW ERRM + 1DDE A91D LDA #HIGH ERRM + 1DE0 A012 LDY #ERRML + 1DE2 20F021 JSR DLINE + + 1DE5 ; FALL THROUGH ... + + 1DE5 ; ---- + 1DE5 ; QUIT + 1DE5 ; ---- + + 1DE5 20831E ZQUIT: JSR ZCRLF ; FLUSH BUFFER + + 1DE8 A2FB LDX #LOW TOQ + 1DEA A91D LDA #HIGH TOQ + 1DEC A00E LDY #TOQL + 1DEE 20F021 JSR DLINE ; "END OF STORY" + + 1DF1 A502 LDA FAST ; FAST-READ ENGAGED? + 1DF3 F003 BEQ FREEZE + 1DF5 202629 JSR FOFF ; DISENGAGE IF SO + 1DF8 4CF81D FREEZE: JMP FREEZE ; AND STOP + + 1DFB 456E6420 TOQ: DB "End of story." + 1E08 0D DB EOL + 000E TOQL EQU $-TOQ + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 88 +--- GAME I/O: CBM64 --- + + 1E09 ; ------- + 1E09 ; RESTART + 1E09 ; ------- + + 1E09 20831E ZSTART: JSR ZCRLF + + 1E0C A502 LDA FAST ; FAST-READ? + 1E0E F003 BEQ DOSTRT ; NO, GO + 1E10 202629 JSR FOFF ; ELSE DISENGAGE + + 1E13 AD112A DOSTRT: LDA ZBEGIN+ZSCRIP+1 ; SAVE SCRIPT STATE + 1E16 2901 AND #%00000001 ; FOR LATER + 1E18 8D0322 STA SFLAG ; (BM 5/14/85) + + 1E1B 4C7F0E JMP WARM1 ; AND DO A WARMSTART + + 1E1E ; -------------------- + 1E1E ; PRINT VERSION NUMBER + 1E1E ; -------------------- + + 1E1E 43424D20 VERS: DB "CBM 64 Version D" + 1E2E 0D DB EOL + 0011 VERSL EQU $-VERS + + 1E2F 20831E VERNUM: JSR ZCRLF + + 1E32 A21E LDX #LOW VERS + 1E34 A91E LDA #HIGH VERS + 1E36 A011 LDY #VERSL + 1E38 4CF021 JMP DLINE + + 1E3B ; -------------------------- + 1E3B ; RETURN TOP RAM PAGE IN [A] + 1E3B ; -------------------------- + + 1E3B A9CF MEMTOP: LDA #$CF ; IT'S A GIVEN + 1E3D 60 RTS + + 1E3E ; -------------------------------- + 1E3E ; RETURN RANDOM BYTES IN [A] & [X] + 1E3E ; -------------------------------- + + 1E3E AD1BD4 RANDOM: LDA RAND ; SOMETHING FROM HERE + 1E41 AE12D0 LDX RASTER ; AND HERE + 1E44 60 RTS + + 1E45 ; ------------------- + 1E45 ; Z-PRINT A CHARACTER + 1E45 ; ------------------- + + 1E45 ; ENTRY: ASCII CHAR IN [A] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 89 +--- GAME I/O: CBM64 --- + + + 1E45 C90D COUT: CMP #EOL ; IF EOL, + 1E47 F03A BEQ ZCRLF ; DO IT! + 1E49 C920 CMP #SPACE ; IGNORE ALL OTHER + 1E4B 900B BCC CEX ; CONTROLS + + 1E4D A660 LDX LENGTH ; ELSE GET LINE POINTER + 1E4F 9D0002 STA LBUFF,X ; ADD CHAR TO BUFFER + 1E52 E027 CPX #XSIZE ; END OF LINE? + 1E54 B003 BCS FLUSH ; YES, FLUSH THE LINE + 1E56 E660 INC LENGTH ; ELSE UPDATE POINTER + + 1E58 60 CEX: RTS + + 1E59 ; ------------------- + 1E59 ; FLUSH OUTPUT BUFFER + 1E59 ; ------------------- + + 1E59 ; ENTRY: LENGTH OF BUFFER IN [X] + + 1E59 A920 FLUSH: LDA #SPACE + + 1E5B DD0002 FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR + 1E5E F005 BEQ FL1 ; IN THE LINE + 1E60 CA DEX + 1E61 D0F8 BNE FL0 ; IF NONE FOUND, + 1E63 A227 LDX #XSIZE ; FLUSH ENTIRE LINE + + 1E65 8661 FL1: STX OLDLEN ; SAVE OLD LINE POS HERE + 1E67 8660 STX LENGTH ; MAKE IT THE NEW LINE LENGTH + + 1E69 20831E JSR ZCRLF ; PRINT LINE UP TO LAST SPACE + + 1E6C ; START NEW LINE WITH REMAINDER OF OLD + + 1E6C A661 LDX OLDLEN ; GET OLD LINE POS + 1E6E A000 LDY #0 ; START NEW LINE AT BEGINNING + 1E70 E8 FL2: INX + 1E71 E027 CPX #XSIZE ; CONTINUE IF + 1E73 9005 BCC FL3 ; INSIDE OR + 1E75 F003 BEQ FL3 ; AT END OF LINE + 1E77 8460 STY LENGTH ; ELSE SET NEW LINE LENGTH + 1E79 60 RTS + + 1E7A BD0002 FL3: LDA LBUFF,X ; GET CHAR FROM OLD LINE + 1E7D 990002 STA LBUFF,Y ; MOVE TO START OF NEW LINE + 1E80 C8 INY ; UPDATE LENGTH OF NEW LINE + 1E81 D0ED BNE FL2 + + 1E83 ; --------------- + 1E83 ; CARRIAGE RETURN + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 90 +--- GAME I/O: CBM64 --- + + 1E83 ; --------------- + + 1E83 E665 ZCRLF: INC LINCNT ; NEW LINE GOING OUT + 1E85 A565 LDA LINCNT ; IS IT TIME TO + 1E87 C566 CMP LMAX ; PRINT "MORE" YET? + 1E89 9041 BCC CR1 ; NO, CONTINUE + + 1E8B ; SCREEN FULL; PRINT "MORE" + + 1E8B 20081F JSR ZUSL ; UPDATE STATUS LINE + + 1E8E A900 LDA #0 + 1E90 8565 STA LINCNT ; RESET LINE COUNTER + 1E92 8D8602 STA COLOR ; PRINT "MORE" IN BLACK + 1E95 85C6 STA NDX ; CLEAR QUEUE + + 1E97 38 SEC + 1E98 20F0FF JSR PLOT ; GET CURSOR POSITION + 1E9B 8463 STY OLDX + 1E9D 8664 STX OLDY + + 1E9F A2EF LDX #LOW MORE + 1EA1 A91E LDA #HIGH MORE + 1EA3 A006 LDY #MOREL + 1EA5 20F021 JSR DLINE ; PRINT "MORE" DIRECTLY + + 1EA8 20E4FF ZCR0: JSR GETIN ; GET ANY KEYPRESS + 1EAB AA TAX + 1EAC F0FA BEQ ZCR0 + + 1EAE A463 LDY OLDX + 1EB0 A664 LDX OLDY + 1EB2 18 CLC + 1EB3 20F0FF JSR PLOT ; RESTORE CURSOR + + 1EB6 A901 LDA #1 + 1EB8 8D8602 STA COLOR ; SWITCH BACK TO WHITE + + 1EBB A2F5 LDX #LOW MCLR + 1EBD A91E LDA #HIGH MCLR + 1EBF A006 LDY #MOREL + 1EC1 20F021 JSR DLINE ; RUB OUT "MORE" + + 1EC4 A463 LDY OLDX + 1EC6 A664 LDX OLDY + 1EC8 18 CLC + 1EC9 20F0FF JSR PLOT ; RESTORE CURSOR AGAIN + + 1ECC A660 CR1: LDX LENGTH + 1ECE A90D LDA #EOL ; INSTALL EOL AT + 1ED0 9D0002 STA LBUFF,X ; END OF CURRENT LINE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 91 +--- GAME I/O: CBM64 --- + + 1ED3 E660 INC LENGTH ; UPDATE LINE LENGTH + + 1ED5 A460 LINOUT: LDY LENGTH ; IF BUFFER EMPTY, + 1ED7 F011 BEQ LINEX ; DON'T PRINT ANYTHING + + 1ED9 846F STY PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + 1EDB A200 LDX #0 ; SEND CONTENTS OF [LBUFF] + 1EDD BD0002 LOUT: LDA LBUFF,X ; TO SCREEN + 1EE0 202821 JSR CHAR + 1EE3 E8 INX + 1EE4 88 DEY + 1EE5 D0F6 BNE LOUT + + 1EE7 200422 JSR PPRINT ; PRINT [LBUFF] IF ENABLED + + 1EEA A900 LINEX: LDA #0 ; RESET LINE LENGTH + 1EEC 8560 STA LENGTH ; TO ZERO + 1EEE 60 RTS ; AND RETURN + + 1EEF 5B4D4F52 MORE: DB "[MORE]" + 0006 MOREL EQU $-MORE + + 1EF5 20202020 MCLR: DB " " + + 1EFB ; ---------------------- + 1EFB ; UPDATE THE STATUS LINE + 1EFB ; ---------------------- + + 1EFB 53636F72 SCORE: DB "Score: " + 0007 SCOREL EQU $-SCORE + + 1F02 54696D65 CLOCK: DB "Time: " + 0006 CLOCKL EQU $-CLOCK + + 1F08 38 ZUSL: SEC ; SAVE THE CURRENT + 1F09 20F0FF JSR PLOT ; CURSOR POSITION + 1F0C 8463 STY OLDX + 1F0E 8664 STX OLDY + + 1F10 A560 LDA LENGTH ; SAVE ALL + 1F12 48 PHA ; STRING-PRINTING + 1F13 A521 LDA MPCH ; VARIABLES + 1F15 48 PHA + 1F16 A520 LDA MPCM + 1F18 48 PHA + 1F19 A51F LDA MPCL + 1F1B 48 PHA + 1F1C A54D LDA TSET + 1F1E 48 PHA + 1F1F A54C LDA PSET + 1F21 48 PHA + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 92 +--- GAME I/O: CBM64 --- + + 1F22 A552 LDA ZWORD+HI + 1F24 48 PHA + 1F25 A551 LDA ZWORD+LO + 1F27 48 PHA + 1F28 A550 LDA ZFLAG + 1F2A 48 PHA + 1F2B A55E LDA DIGITS + 1F2D 48 PHA + + 1F2E A227 LDX #XSIZE + 1F30 BD0002 USL0: LDA LBUFF,X ; MOVE CONTENTS OF [LBUFF] + 1F33 9D200D STA BUFSAV,X ; TO [BUFSAV] + 1F36 A920 LDA #SPACE ; CLEAR + 1F38 9D0002 STA LBUFF,X ; [LBUFF] WITH SPACES + 1F3B CA DEX + 1F3C 10F2 BPL USL0 + + 1F3E A900 LDA #0 + 1F40 8560 STA LENGTH ; RESET LINE LENGTH + 1F42 8562 STA SCRIPT ; DISABLE SCRIPTING + 1F44 8D8602 STA COLOR ; PRINT STATUS LINE IN BLACK + + 1F47 A913 LDA #$13 ; HOME THE + 1F49 20D2FF JSR CHROUT ; CURSOR + 1F4C A912 LDA #$12 ; PRINT IN + 1F4E 20D2FF JSR CHROUT ; INVERSE VIDEO + + 1F51 ; PRINT ROOM DESCRIPTION + + 1F51 A910 LDA #16 ; GLOBAL VAR #16 (ROOM ID) + 1F53 20A310 JSR GETVRG ; GET IT INTO [VALUE] + 1F56 A50F LDA VALUE+LO + 1F58 209D13 JSR PRNTDC ; PRINT SHORT ROOM DESCRIPTION + + 1F5B A918 LDA #24 ; MOVE LINE INDEX UP + 1F5D 8560 STA LENGTH ; TO TIME/SCORE POSITION + + 1F5F A911 LDA #17 ; GLOBAL VAR #17 (SCORE/HOURS) + 1F61 20A310 JSR GETVRG ; GET IT INTO [VALUE] + + 1F64 A55F LDA TIMEFL ; GET MODE FLAG + 1F66 D032 BNE DOTIME ; USE TIME MODE IF NON-ZERO + + 1F68 ; PRINT "SCORE" + + 1F68 A953 LDA #'S' + 1F6A 20451E JSR COUT + 1F6D A963 LDA #'c' + 1F6F 20451E JSR COUT + 1F72 A96F LDA #'o' + 1F74 20451E JSR COUT + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 93 +--- GAME I/O: CBM64 --- + + 1F77 A972 LDA #'r' + 1F79 20451E JSR COUT + 1F7C A965 LDA #'e' + 1F7E 20451E JSR COUT + 1F81 A93A LDA #':' + 1F83 20451E JSR COUT + 1F86 A920 LDA #SPACE + 1F88 20451E JSR COUT + + 1F8B A50F LDA VALUE+LO ; MOVE SCORE VALUE + 1F8D 8556 STA QUOT+LO ; INTO [QUOT] + 1F8F A510 LDA VALUE+HI ; FOR PRINTING + 1F91 8557 STA QUOT+HI + 1F93 20F917 JSR NUMBER ; PRINT SCORE VALUE IN DECIMAL + + 1F96 A92F LDA #'/' ; PRINT A SLASH + 1F98 D035 BNE MOVMIN ; BRANCH ALWAYS + + 1F9A ; PRINT "TIME" + + 1F9A A954 DOTIME: LDA #'T' + 1F9C 20451E JSR COUT + 1F9F A969 LDA #'i' + 1FA1 20451E JSR COUT + 1FA4 A96D LDA #'m' + 1FA6 20451E JSR COUT + 1FA9 A965 LDA #'e' + 1FAB 20451E JSR COUT + 1FAE A93A LDA #':' + 1FB0 20451E JSR COUT + 1FB3 A920 LDA #SPACE + 1FB5 20451E JSR COUT + + 1FB8 A50F LDA VALUE+LO ; 00 IS REALLY 24 + 1FBA D002 BNE DT0 + 1FBC A918 LDA #24 + 1FBE C90D DT0: CMP #13 ; IS HOURS > 12, + 1FC0 9002 BCC DT1 + 1FC2 E90C SBC #12 ; CONVERT TO 1-12 + 1FC4 8556 DT1: STA QUOT+LO ; MOVE FOR PRINTING + 1FC6 A900 LDA #0 + 1FC8 8557 STA QUOT+HI ; CLEAR MSB + 1FCA 20F917 JSR NUMBER + + 1FCD A93A LDA #':' ; COLON + + 1FCF 20451E MOVMIN: JSR COUT ; PRINT SLASH OR COLON + + 1FD2 A912 LDA #18 ; GLOBAL VAR #18 (MOVES/MINUTES) + 1FD4 20A310 JSR GETVRG ; GET IT INTO [VALUE] + 1FD7 A50F LDA VALUE+LO ; MOVE TO [QUOT] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 94 +--- GAME I/O: CBM64 --- + + 1FD9 8556 STA QUOT+LO ; FOR EVENTUAL PRINTING + 1FDB A510 LDA VALUE+HI + 1FDD 8557 STA QUOT+HI + + 1FDF A55F LDA TIMEFL ; WHICH MODE? + 1FE1 D006 BNE DOMINS ; TIME IF NZ + + 1FE3 ; PRINT NUMBER OF MOVES + + 1FE3 20F917 JSR NUMBER ; SHOW # MOVES + 1FE6 4C1520 JMP STATEX ; ALL DONE + + 1FE9 ; PRINT MINUTES + + 1FE9 A50F DOMINS: LDA VALUE+LO ; CHECK MINUTES + 1FEB C90A CMP #10 ; IF MORE THAN TEN + 1FED B005 BCS DOM0 ; CONTINUE + + 1FEF A930 LDA #'0' ; ELSE PRINT A + 1FF1 20451E JSR COUT ; PADDING "0" FIRST + + 1FF4 20F917 DOM0: JSR NUMBER ; SHOW MINUTES + + 1FF7 A920 LDA #SPACE + 1FF9 20451E JSR COUT ; SEPARATE THINGS + + 1FFC A911 LDA #17 ; CHECK "HOURS" AGAIN + 1FFE 20A310 JSR GETVRG + 2001 A50F LDA VALUE+LO + 2003 C90C CMP #12 ; PAST NOON? + 2005 B004 BCS DOPM ; YES, PRINT "PM" + + 2007 A941 LDA #'A' ; ELSE PRINT "AM" + 2009 D002 BNE DOXM ; BRANCH ALWAYS + + 200B A950 DOPM: LDA #'P' + + 200D 20451E DOXM: JSR COUT + 2010 A94D LDA #'M' + 2012 20451E JSR COUT + + 2015 ; STATUS LINE READY + + 2015 A928 STATEX: LDA #40 ; PRINT THE ENTIRE + 2017 8560 STA LENGTH ; STATUS LINE + 2019 20CC1E JSR CR1 + + 201C A227 LDX #XSIZE ; RESTORE OLD [LBUFF] + 201E BD200D USLX: LDA BUFSAV,X + 2021 9D0002 STA LBUFF,X + 2024 CA DEX + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 95 +--- GAME I/O: CBM64 --- + + 2025 10F7 BPL USLX + + 2027 68 PLA ; RESTORE ALL + 2028 855E STA DIGITS ; SAVED VARIABLES + 202A 68 PLA + 202B 8550 STA ZFLAG + 202D 68 PLA + 202E 8551 STA ZWORD+LO + 2030 68 PLA + 2031 8552 STA ZWORD+HI + 2033 68 PLA + 2034 854C STA PSET + 2036 68 PLA + 2037 854D STA TSET + 2039 68 PLA + 203A 851F STA MPCL + 203C 68 PLA + 203D 8520 STA MPCM + 203F 68 PLA + 2040 8521 STA MPCH + 2042 68 PLA + 2043 8560 STA LENGTH + + 2045 A664 LDX OLDY ; RESTORE CURSOR + 2047 A463 LDY OLDX + 2049 18 CLC + 204A 20F0FF JSR PLOT + + 204D A2FF LDX #$FF + 204F 8662 STX SCRIPT ; RE-ENABLE SCRIPTING + 2051 E8 INX ; = 0 + 2052 8622 STX MPCFLG ; INVALIDATE [MPC] + 2054 E8 INX ; = 1 + 2055 8E8602 STX COLOR ; PRINT IN WHITE AGAIN + 2058 60 RTS + + END + INCLUD MACHINE.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 96 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + + 2059 ; ---------------------------- + 2059 ; FETCH ASCII KEYCODE INTO [A] + 2059 ; ---------------------------- + + 2059 ; EXIT: ASCII IN [A] & [IOCHAR] + + 00E0 CYCLE EQU $E0 ; SHORT BLINK CYCLE + + 2059 8A GETKEY: TXA ; SAVE [X] & [Y] + 205A 48 PHA + 205B 98 TYA + 205C 48 PHA + + 205D A2FF GKEY0: LDX #$FF + 205F 8E4003 STX CURSOR ; FORCE THE CURSOR "ON" + 2062 E8 INX ; = 0 + 2063 867B STX BLINK+LO ; RESET THE BLINK COUNTER + 2065 867C STX BLINK+HI ; FOR A LONG DELAY + + 2067 38 SEC ; GET CURSOR POSITION + 2068 20F0FF JSR PLOT ; [Y]=XPOS, [X]=YPOS + + 206B 8A TXA ; CALC SPRITE Y-POS + 206C 0A ASL A + 206D 0A ASL A + 206E 0A ASL A + 206F 18 CLC + 2070 6939 ADC #57 + 2072 8D01D0 STA SP0Y + + 2075 98 TYA ; GET X-POS INTO [A] + 2076 C928 CMP #40 ; STRIP OFF + 2078 9002 BCC NOLOG ; LOGICAL LINE OFFSET + 207A E928 SBC #40 + + 207C A200 NOLOG: LDX #0 + 207E C91D CMP #29 ; IF X-POS < 29 + 2080 9001 BCC CURX ; MSB OF SPRITE POS IS ZERO + 2082 E8 INX ; ELSE SET BIT 0 + 2083 8E10D0 CURX: STX MSIGX ; OF X-POS MSB + + 2086 0A ASL A ; CALC LSB OF SPRITE X-POS + 2087 0A ASL A + 2088 0A ASL A + 2089 18 CLC + 208A 6918 ADC #24 + 208C 8D00D0 STA SP0X + + 208F 20E4FF GKEY1: JSR GETIN ; GET A KEY + 2092 AA TAX ; SAVE HERE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 97 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + + 2093 E67B INC BLINK+LO ; TIME TO BLINK YET? + 2095 D010 BNE NOBLIN ; NOT TILL BOTH BLINK TIMERS + 2097 E67C INC BLINK+HI ; ARE ZERO + 2099 D00C BNE NOBLIN + + 209B A9E0 LDA #CYCLE ; RESET MSB OF BLINK COUNTER + 209D 857C STA BLINK+HI ; FOR SHORT BLINK INTERVAL + + 209F AD4003 LDA CURSOR ; FLIP THE CURSOR + 20A2 49FF EOR #$FF ; SHAPE + 20A4 8D4003 STA CURSOR ; AND UPDATE IT + + 20A7 8A NOBLIN: TXA ; KEY BEING PRESSED? + 20A8 F0E5 BEQ GKEY1 ; NOT IF CODE WAS ZERO + + 20AA ; CONVERT & MASK KEYCODE IN [A] + + 20AA C941 CMP #'A' ; CONVERT UNSHIFTED ALPHA + 20AC 9006 BCC MASK ; TO ASCII LOWER CASE + 20AE C95B CMP #'Z'+1 + 20B0 B002 BCS MASK + 20B2 6920 ADC #$20 + + 20B4 297F MASK: AND #%01111111 ; SCREEN OUT SHIFTS + + 20B6 C90D CMP #EOL ; EOL? + 20B8 F02A BEQ TICK + 20BA C914 CMP #BACKSP ; BACKSPACE? + 20BC F026 BEQ TICK + 20BE C920 CMP #SPACE ; ANYTHING ELSE < "SPACE" + 20C0 901C BCC BADKEY ; IS BAD + + 20C2 C93C CMP #'<' ; CHANGE "<" + 20C4 D004 BNE MASK0 ; TO "," + 20C6 A92C LDA #',' + 20C8 D01A BNE TICK + + 20CA C93E MASK0: CMP #'>' ; CHANGE ">" + 20CC D004 BNE MASK1 ; TO "." + 20CE A92E LDA #'.' + 20D0 D012 BNE TICK + + 20D2 C97B MASK1: CMP #'z'+1 ; PASS L-C ALPHA + 20D4 B008 BCS BADKEY + 20D6 C961 CMP #'a' + 20D8 B00A BCS TICK + + 20DA C95B CMP #'Z'+1 ; PASS U-C ALPHA + 20DC 9006 BCC TICK ; AND OTHER ASCII CHARS + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 98 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + 20DE 20E422 BADKEY: JSR BOOP ; REJECT BAD KEYPRESS + 20E1 4C5D20 JMP GKEY0 ; AND TRY AGAIN + + 20E4 ; "CLICK" THE KEY + + 20E4 8567 TICK: STA IOCHAR ; SAVE KEYCODE HERE + + 20E6 A91E LDA #30 + 20E8 8D00D4 STA FRELO1 ; FREQ LSB + 20EB A986 LDA #134 + 20ED 8D01D4 STA FREHI1 ; FREQ MSB + 20F0 A900 LDA #0 + 20F2 A8 TAY ; SET UP CLICK DELAY + 20F3 8D06D4 STA SUREL1 ; ZERO SUSTAIN + 20F6 A98F LDA #%10001111 + 20F8 8D18D4 STA SIGVOL ; FULL VOLUME, VOICE #3 OFF + 20FB A911 LDA #%00010001 + 20FD 8D04D4 STA VCREG1 ; ACTIVATE TRIANGLE WAVE + + 2100 88 CLICK: DEY ; [Y] = 0 ON ENTRY + 2101 D0FD BNE CLICK + + 2103 8C04D4 STY VCREG1 ; STOP THE SOUND + 2106 A980 LDA #%10000000 ; ZERO VOLUME + 2108 8D18D4 STA SIGVOL ; WITH VOICE #3 OFF + + 210B 68 PLA ; RESTORE [X] & [Y] + 210C A8 TAY + 210D 68 PLA + 210E AA TAX + 210F A567 LDA IOCHAR ; RESTORE CODE INTO [A] + 2111 60 RTS + + 2112 ; ------------------------- + 2112 ; OUTPUT AN ASCII CHARACTER + 2112 ; ------------------------- + + 2112 C961 LETTER: CMP #'a' ; LOWER-CASE? + 2114 9005 BCC LET0 ; NO, CONTINUE + 2116 295F AND #%01011111 ; ELSE MASK FOR LOWER-CASE + 2118 4CD2FF JMP CHROUT + + 211B C941 LET0: CMP #'A' ; UPPER-CASE? + 211D 9006 BCC LETEX + 211F C95B CMP #'Z'+1 + 2121 B002 BCS LETEX + 2123 0920 ORA #%00100000 ; MAKE UPPER + 2125 4CD2FF LETEX: JMP CHROUT + + 2128 ; ----------------- + 2128 ; PRINT CHAR IN [A] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 99 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + 2128 ; ----------------- + + 2128 8567 CHAR: STA IOCHAR ; SAVE HERE + 212A 8A TXA ; SAVE [X] AND [Y] + 212B 48 PHA + 212C 98 TYA + 212D 48 PHA + + 212E 38 SEC ; GET CURSOR X- AND Y-POS + 212F 20F0FF JSR PLOT ; INTO [Y] AND [X], RESPECTIVELY + 2132 98 TYA + 2133 C928 CMP #40 ; STRIP OFF THE + 2135 9003 BCC CHKEOL ; LOGICAL LINE OFFSET + 2137 E928 SBC #40 ; UPDATE [Y] IF NECESSARY + 2139 A8 TAY + + 213A A567 CHKEOL: LDA IOCHAR ; RESTORE CHAR + 213C C90D CMP #EOL ; IS IT EOL? + 213E F047 BEQ OUTEOL ; YES, SPECIAL HANDLING + + 2140 ; HANDLE A NON-EOL CHAR + + 2140 E017 CPX #YSIZE-1 ; ON LAST SCREEN LINE? + 2142 9039 BCC NOSCRL ; NO, NO SCROLL NEEDED + 2144 C027 CPY #XSIZE ; LAST CHAR ON LINE? + 2146 9035 BCC NOSCRL ; NO, DON'T SCROLL + + 2148 ; SCROLL THE SCREEN + + 2148 CA DOSCRL: DEX ; PUSH CURSOR UP ONE LINE + 2149 18 CLC + 214A 20F0FF JSR PLOT ; RESET THE CURSOR + + 214D A668 LDX SLINE ; GET CURRENT SCROLL LINE + + 214F E018 SRL0: CPX #YSIZE + 2151 F020 BEQ SRL2 ; SCROLL DONE + + 2153 BD5823 LDA LOLINE,X ; GET ADDR OF DEST LINE + 2156 856C STA LTO+LO ; INTO [LTO] + 2158 BD7123 LDA HILINE,X + 215B 856D STA LTO+HI + + 215D E8 INX + 215E BD5823 LDA LOLINE,X ; GET ADDR OF SOURCE LINE + 2161 856A STA LFROM+LO ; INTO [LFROM] + 2163 BD7123 LDA HILINE,X + 2166 856B STA LFROM+HI + + 2168 A027 LDY #XSIZE + 216A B16A SRL1: LDA (LFROM),Y ; MOVE SOURCE LINE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 100 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + 216C 916C STA (LTO),Y ; TO DEST LINE + 216E 88 DEY + 216F 10F9 BPL SRL1 + + 2171 30DC BMI SRL0 ; LOOP TILL [X] = YSIZE + + 2173 A227 SRL2: LDX #XSIZE + 2175 A920 LDA #SPACE + 2177 9DC007 SRL3: STA SCREEN+960,X ; CLEAR LAST LINE + 217A CA DEX ; OF SCREEN RAM + 217B 10FA BPL SRL3 + + 217D A567 NOSCRL: LDA IOCHAR ; RESTORE CHAR + 217F 201221 JSR LETTER ; OFF TO THE SCREEN! + 2182 68 PLA ; RESTORE [X] AND [Y] + 2183 A8 TAY + 2184 68 PLA + 2185 AA TAX + 2186 60 RTS + + 2187 ; HANDLE EOL + + 2187 E017 OUTEOL: CPX #YSIZE-1 ; LAST SCREEN LINE? + 2189 90F2 BCC NOSCRL ; NO, DON'T SCROLL + 218B B0BB BCS DOSCRL ; ELSE SCROLL + + 218D ; --------------------- + 218D ; FETCH A LINE OF INPUT + 218D ; --------------------- + + 218D ; ENTRY: ABS ADDR OF READ BUFFER IN [ARG1] + 218D ; EXIT: # CHARS READ IN [A] + + 218D 20D51E INPUT: JSR LINOUT ; FLUSH [LBUFF] + + 2190 205524 JSR CURSON ; ACTIVATE CURSOR, CLEAR KEY QUEUE + + 2193 A000 LDY #0 + 2195 8465 STY LINCNT ; RESET LINE COUNT + + 2197 205920 INLOOP: JSR GETKEY ; GET ASCII INTO [A] AND [IOCHAR] + + 219A C90D CMP #EOL ; EOL? + 219C F02A BEQ ENDLIN ; LINE DONE IF SO + 219E C914 CMP #BACKSP ; BACKSPACE? + 21A0 F01C BEQ BACKUP ; SPECIAL HANDLING + + 21A2 990002 STA LBUFF,Y ; ELSE ADD CHAR TO INPUT BUFFER + 21A5 C8 INY ; NEXT POSITION IN LINE + + 21A6 202821 SHOWIT: JSR CHAR ; SEND TO SCREEN + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 101 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + + 21A9 C04D CPY #77 ; 2 SCREEN LINES FULL? + 21AB 90EA BCC INLOOP ; NO, GET ANOTHER CHAR + + 21AD ; HANDLE LINE OVERFLOW + + 21AD 205920 NOMORE: JSR GETKEY + 21B0 C90D CMP #EOL ; IF EOL, + 21B2 F014 BEQ ENDLIN ; WRAP UP THE LINE + 21B4 C914 CMP #BACKSP ; BACKSPACE + 21B6 F006 BEQ BACKUP ; IS OKAY TOO + 21B8 20E422 JSR BOOP ; ELSE COMPLAIN + 21BB 4CAD21 JMP NOMORE ; AND INSIST + + 21BE ; HANDLE BACKSPACE + + 21BE 88 BACKUP: DEY ; BACK UP THE POINTER + 21BF 10E5 BPL SHOWIT ; SEND BS IF NOT START OF LINE + 21C1 20E422 JSR BOOP ; ELSE SCREAM WITH PAIN + 21C4 A000 LDY #0 ; RESET POINTER + 21C6 F0CF BEQ INLOOP ; AND WAIT FOR SOMETHING BETTER + + 21C8 ; HANDLE END OF LINE + + 21C8 990002 ENDLIN: STA LBUFF,Y ; SHIP EOL TO BUFFER + 21CB C8 INY ; UPDATE INDEX + 21CC 8445 STY LINLEN ; SAVE HERE FOR "READ" + 21CE 846F STY PRLEN ; AND HERE FOR "PPRINT" + 21D0 A200 LDX #0 + 21D2 8E15D0 STX SPENA ; DISABLE CURSOR DMA + 21D5 202821 JSR CHAR ; AND SEND EOL TO SCREEN + + 21D8 ; MOVE [LBUFF] TO [ARG1] W/LC CONVERSION + + 21D8 B9FF01 LEX1: LDA LBUFF-1,Y ; GET A CHAR FROM [LBUFF] + 21DB C941 CMP #'A' ; IF CHAR IS ALPHA, + 21DD 9006 BCC LEX2 ; CONVERT TO LOWER CASE + 21DF C95B CMP #'Z'+1 + 21E1 B002 BCS LEX2 + 21E3 6920 ADC #$20 + 21E5 9105 LEX2: STA (ARG1),Y ; MOVE CHAR TO INPUT BUFFER AT [ARG1] + 21E7 88 DEY ; LOOP TILL + 21E8 10EE BPL LEX1 ; ALL CHARS MOVED + + 21EA 200422 JSR PPRINT ; SCRIPT [LBUFF] IF ENABLED + + 21ED A545 LDA LINLEN ; RESTORE # CHARS + 21EF 60 RTS ; INTO [A] + + 21F0 ; ----------------------- + 21F0 ; DIRECT PRINT LINE [X/A] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 102 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + 21F0 ; ----------------------- + + 21F0 ; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB) + 21F0 ; STRING LENGTH IN [Y] + + 21F0 8EF921 DLINE: STX STRING+LO ; DROP STRING ADDRESS + 21F3 8DFA21 STA STRING+HI ; INTO DUMMY BYTES + + 21F6 A200 LDX #0 ; INIT CHAR-FETCH INDEX + + 21F8 BD DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE + 21F9 0000 STRING: DW $0000 ; DUMMY OPERAND BYTES + 21FB 202821 JSR CHAR + 21FE E8 INX + 21FF 88 DEY ; LOOP TILL + 2200 D0F6 BNE DOUT ; OUT OF CHARS + 2202 60 RTS + + 2203 ; ----------------------- + 2203 ; SEND [LBUFF] TO PRINTER + 2203 ; ----------------------- + + 2203 ; ENTRY: LENTH OF LINE IN [PRLEN] + 2203 ; NOW WITH IMPROVED ERROR PROTECTION! (BM 11/24/84) + + 2203 00 SFLAG: DB 0 ; PREVIOUS SCRIPT MODE (BM 5/14/85) + + 2204 A562 PPRINT: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? + 2206 F06F BEQ PEX ; NO, SCRAM IMMEDIATELY + + 2208 AD112A LDA ZBEGIN+ZSCRIP+1 ; CHECK SCRIPT FLAG + 220B 2901 AND #%00000001 ; SCRIPTING ON? + 220D F04D BEQ PP3 ; NO, CHECK FOR "UNSCRIPT" + + 220F A56E LDA PSTAT ; CHECK PRINTER STATUS + 2211 3064 BMI PEX ; CAN'T OPEN IF NEGATIVE + 2213 D02F BNE PP1 ; ALREADY OPEN, SCRIPT THE LINE + + 2215 ; OPEN THE PRINTER FOR OUTPUT + + 2215 A502 LDA FAST ; FAST-READ ENGAGED? + 2217 F008 BEQ PP0 ; NO, IGNORE + 2219 202629 JSR FOFF ; ELSE DISENGAGE + 221C A908 LDA #8 + 221E 209D27 JSR DOPEN ; AND RESET THE DRIVE + + 2221 A200 PP0: LDX #0 + 2223 8602 STX FAST ; BYE, FAST DRIVE! + 2225 E8 INX ; = 1 + 2226 866E STX PSTAT ; SET STATUS TO "PRINTER OPENED" (1) + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 103 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + 2228 A904 LDA #4 ; LOGICAL FILE #4 + 222A AA TAX ; DEVICE #4 + 222B A007 LDY #7 ; ALLOW UPPER/LOWER CASE + 222D 20BAFF JSR SETLFS ; SET UP LOGICAL FILE + 2230 B00C BCS PPERR ; ERROR IF CARRY SET + 2232 A900 LDA #0 + 2234 20BDFF JSR SETNAM ; NO FILENAME REQUIRED + 2237 B005 BCS PPERR ; ERROR IF CARRY SET + 2239 20C0FF JSR OPEN ; OPEN THE CHANNEL + 223C 9006 BCC PP1 ; OPEN OKAY IF CARRY CLEAR + + 223E A9FF PPERR: LDA #$FF ; ELSE SET PRINTER STATUS + 2240 856E STA PSTAT ; TO "CAN'T OPEN" + 2242 D022 BNE PP5 ; AND SIMULATE AN "UNSCRIPT" + + 2244 A204 PP1: LDX #4 ; SET PRINTER CHANNEL + 2246 20C9FF JSR CHKOUT ; TO "OUTPUT" + 2249 B0F3 BCS PPERR ; ERROR IF CARRY SET + + 224B A000 LDY #0 ; INIT INDEX + 224D B90002 PP2: LDA LBUFF,Y + 2250 201221 JSR LETTER + 2253 B0E9 BCS PPERR ; ERROR IF CARRY SET + 2255 C8 INY + 2256 C66F DEC PRLEN + 2258 D0F3 BNE PP2 + 225A F01B BEQ PEX ; RESET & RETURN + + 225C ; CHECK FOR "UNSCRIPT" + + 225C A56E PP3: LDA PSTAT ; CHECK PRINTER STATUS + 225E F017 BEQ PEX ; EXIT IF PRINTER WAS OFF + 2260 3015 BMI PEX ; OR UNOPENABLE + + 2262 A900 PCLOSE: LDA #0 ; RESET PRINTER STATUS FLAG + 2264 856E STA PSTAT ; TO "CLOSED" + + 2266 ; ENTRY FOR PRINTER ERROR + + 2266 A904 PP5: LDA #4 + 2268 20C3FF JSR CLOSE ; CLOSE THE PRINTER CHANNEL + + 226B A502 LDA FAST ; FAST-READ AVAILABLE? + 226D F008 BEQ PEX ; NO, EXIT + 226F A908 LDA #8 ; ELSE + 2271 209D27 JSR DOPEN ; RESET BOOT DRIVE + 2274 4CC128 JMP FINIT ; RE-ENGAGE FAST-READ & RETURN + + 2277 4CCCFF PEX: JMP CLRCHN + + 227A ; ------------ + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 104 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + 227A ; SPLIT SCREEN + 227A ; ------------ + + 227A ; SPLIT SCREEN AT LINE [ARG1] + 227A ; DISABLE SPLIT IF [ARG1] = 0 + 227A ; IGNORE IF SPLIT ALREADY ENABLED OR [ARG1] >= 20 + + 227A A605 ZSPLIT: LDX ARG1+LO ; IF [ARG1] = 0, + 227C F02F BEQ OFFSPL ; TURN OFF SPLIT SCREEN + + 227E A569 LDA SPSTAT ; SPLIT ALREADY ENABLED? + 2280 D02A BNE SPLEX ; IGNORE REQUEST IF SO + + 2282 E014 CPX #20 ; IF [ARG1] >= 20, + 2284 B026 BCS SPLEX ; IGNORE + + 2286 E8 INX + 2287 8668 STX SLINE ; ELSE SET NEW SPLIT LINE + 2289 8669 STX SPSTAT ; SET "SPLIT ENABLED" FLAG + + 228B BD5823 SPL0: LDA LOLINE,X ; MAKE [LFROM] POINT TO + 228E 856A STA LFROM+LO ; LINE [X] IN WINDOW + 2290 BD7123 LDA HILINE,X + 2293 856B STA LFROM+HI + + 2295 A027 LDY #XSIZE ; CLEAR LINE [X] + 2297 A920 LDA #SPACE + 2299 916A SPL1: STA (LFROM),Y + 229B 88 DEY + 229C 10FB BPL SPL1 + + 229E CA DEX ; DONE ALL LINES? + 229F D0EA BNE SPL0 ; LOOP TILL WINDOW CLEARED + 22A1 8665 STX LINCNT ; RESET LINE COUNT TO ZERO + + 22A3 A917 SPCALC: LDA #YSIZE-1 ; CALCULATE # LINES TO SCROLL + 22A5 38 SEC ; BEFORE "MORE" APPEARS: + 22A6 E568 SBC SLINE ; LMAX = YSIZE-SLINE-1 + 22A8 8566 STA LMAX + 22AA C666 DEC LMAX + + 22AC 60 SPLEX: RTS + + 22AD ; -------------------- + 22AD ; DISABLE SPLIT SCREEN + 22AD ; -------------------- + + 22AD 20D422 OFFSPL: JSR TOBOT + + 22B0 A201 SPLOFF: LDX #1 + 22B2 8668 STX SLINE ; SPLIT AT LINE 1 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 105 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + 22B4 CA DEX ; = 0 + 22B5 8669 STX SPSTAT ; TURN OFF STATUS FLAG + 22B7 8665 STX LINCNT ; RESET LINE COUNT + 22B9 A915 LDA #21 + 22BB 8566 STA LMAX ; SET MAXIMUM LINE SCROLL + 22BD 60 RTS + + 22BE ; ------ + 22BE ; SCREEN + 22BE ; ------ + + 22BE ; GO TO TOP WINDOW IF [A] = 0 + 22BE ; GO TO BOTTOM IF [A] = 1 + 22BE ; IGNORE IF SPLIT NOT ENABLED OR [A] <> 0 OR 1 + + 22BE A569 ZSCRN: LDA SPSTAT ; IF SPLIT NOT ENABLED, + 22C0 F0EA BEQ SPLEX ; IGNORE REQUEST + + 22C2 A505 LDA ARG1+LO ; IF [ARG1] = 0, + 22C4 0506 ORA ARG1+HI + 22C6 F00C BEQ TOBOT ; GO TO BOTTOM WINDOW + 22C8 C901 CMP #1 ; IF [ARG1] <> 1, + 22CA D0E0 BNE SPLEX ; IGNORE THE REQUEST + + 22CC ; SET TO TOP WINDOW + + 22CC A215 TOTOP: LDX #21 ; TEMPORARILY RESET + 22CE 8666 STX LMAX ; [LMAX] TO KILL "MORE" + 22D0 A201 LDX #1 ; Y-POS = 1 + 22D2 D005 BNE DOSCRN + + 22D4 ; SET TO BOTTOM WINDOW + + 22D4 20A322 TOBOT: JSR SPCALC ; RE-CALC [LMAX] + 22D7 A217 LDX #23 ; Y-POS = 23 + + 22D9 A000 DOSCRN: LDY #0 ; X-POS = 0 + 22DB 8465 STY LINCNT ; RESET LINE COUNT + 22DD 18 CLC + 22DE 20F0FF JSR PLOT ; SET CURSOR TO X=[Y], Y=[X] + 22E1 4C4A23 JMP NEWLOG ; RESET LINE TABLE & RETURN + + 22E4 ; --------- + 22E4 ; RAZZ USER + 22E4 ; --------- + + 22E4 A900 BOOP: LDA #$00 + 22E6 8D00D4 STA FRELO1 ; FREQ LSB + 22E9 A905 LDA #$05 + 22EB 8D01D4 STA FREHI1 ; FREQ MSB + 22EE A9F0 LDA #%11110000 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 106 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + 22F0 8D06D4 STA SUREL1 ; FULL SUSTAIN + 22F3 A98F LDA #%10001111 + 22F5 8D18D4 STA SIGVOL ; FULL VOLUME + 22F8 A941 LDA #%01000001 + 22FA 8D04D4 STA VCREG1 ; START PULSE + + 22FD A9FC LDA #252 ; WAIT 4 JIFFIES + 22FF 85A2 STA TIME + 2301 A5A2 RAZZ: LDA TIME + 2303 D0FC BNE RAZZ + + 2305 8D04D4 STA VCREG1 ; STOP PULSE + 2308 A980 LDA #%10000000 + 230A 8D18D4 STA SIGVOL ; VOLUME OFF + 230D 60 RTS + + 230E ; ------------------------ + 230E ; CLEAR SCREEN & COLOR RAM + 230E ; ------------------------ + + 230E A904 CLS: LDA #HIGH SCREEN ; POINT [I] TO + 2310 8512 STA I+HI ; SCREEN RAM + 2312 A9D8 LDA #HIGH COLRAM ; POINT [J] TO + 2314 8514 STA J+HI ; COLOR RAM + + 2316 A000 LDY #0 ; RESET PAGE INDEX + 2318 8411 STY I+LO ; BOTH RAMS START + 231A 8413 STY J+LO ; ON PAGE BOUNDARIES + 231C 8C15D0 STY SPENA ; MAKE SURE CURSOR IS DEAD! + + 231F A204 LDX #4 ; CLEAR 4 PAGES + 2321 A920 CLS0: LDA #SPACE ; SPACE CHAR + 2323 9111 STA (I),Y ; FOR SCREEN + 2325 A901 LDA #1 ; "WHITE" CODE + 2327 9113 STA (J),Y ; FOR COLOR RAM + 2329 C8 INY + 232A D0F5 BNE CLS0 + 232C E612 INC I+HI ; POINT TO + 232E E614 INC J+HI ; NEXT PAGE + 2330 CA DEX ; 4 PAGES DONE? + 2331 D0EE BNE CLS0 ; LOOP TILL EMPTY + + 2333 A90D LDA #13 ; RESET THE + 2335 8DF807 STA SPT0 ; SPRITE RAM POINTER + + 2338 20CC22 JSR TOTOP ; SET CURSOR TO (0,1) + 233B 20B022 JSR SPLOFF ; DISABLE SPLIT SCREEN + + 233E 78 SEI + 233F A957 LDA #LOW DORTI ; POINT THE SYSTEM NMI VECTOR + 2341 8D1803 STA NMINV+LO ; TO A SIMPLE "RTI" INSTRUCTION + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 107 +--- MACHINE-DEPENDENT I/O: CBM64 --- + + 2344 A923 LDA #HIGH DORTI ; TO DISABLE THE STOP/RESTORE EXIT + 2346 8D1903 STA NMINV+HI + 2349 58 CLI + + 234A ; FALL THROUGH ... + + 234A ; ---------------------------- + 234A ; RESET THE LOGICAL LINE TABLE + 234A ; ---------------------------- + + 234A A218 NEWLOG: LDX #24 + 234C BD7123 NLG0: LDA HILINE,X ; GET MSB OF LINE ADDRESS + 234F 0980 ORA #%10000000 ; SET THE HIGH BIT + 2351 95D9 STA LDTB1,X ; STORE IN THE LINE TABLE + 2353 CA DEX + 2354 10F6 BPL NLG0 + 2356 60 RTS + + 2357 40 DORTI: RTI ; RTI INSTRUCTION FOR NMI + + 2358 ; ------------------- + 2358 ; LINE ADDRESS TABLES + 2358 ; ------------------- + + 2358 00285078 LOLINE: DB $00,$28,$50,$78,$A0,$C8,$F0,$18 + 2360 406890B8 DB $40,$68,$90,$B8,$E0,$08,$30,$58 + 2368 80A8D0F8 DB $80,$A8,$D0,$F8,$20,$48,$70,$98 + 2370 C0 DB $C0 + + 2371 04040404 HILINE: DB $04,$04,$04,$04,$04,$04,$04,$05 + 2379 05050505 DB $05,$05,$05,$05,$05,$06,$06,$06 + 2381 06060606 DB $06,$06,$06,$06,$07,$07,$07,$07 + 2389 07 DB $07 + + END + INCLUD ZDOS.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 108 +--- Z-DOS: CBM64 --- + + + 238A ; --------------------- + 238A ; GET Z-BLOCK FROM DISK + 238A ; --------------------- + + 238A ; ENTRY: Z-BLOCK # IN [BLOCK] + 238A ; TARGET PAGE IN [DBUFF+HI] + + 238A D8 GETDSK: CLD + 238B A908 LDA #8 + 238D 857A STA DRIVE ; GAME ALWAYS PLAYS FROM DRIVE #8 + + 238F A570 LDA DBLOCK+LO ; Z-BLOCK ID IS DIVIDEND + 2391 857D STA DVD+LO + 2393 A571 LDA DBLOCK+HI + 2395 2901 AND #%00000001 ; MASK ALL BUT BIT 0 + 2397 857E STA DVD+HI ; FOR 128K VIRTUAL LIMIT + + 2399 A900 LDA #0 + 239B 8580 STA DSOR+HI ; CLEAR MSB DIVISOR + 239D 8581 STA DTEMP+LO ; AND TEMP VARIABLE + 239F 8582 STA DTEMP+HI + + 23A1 A211 LDX #17 ; USE 17 SECTORS/TRACK + 23A3 867F STX DSOR+LO ; LSB OF DIVISOR + 23A5 CA DEX ; (= 16) INIT DIVIDE INDEX + 23A6 18 CLC + + 23A7 267D DVLP: ROL DVD+LO + 23A9 267E ROL DVD+HI + 23AB 2681 ROL DTEMP+LO + 23AD 2682 ROL DTEMP+HI + + 23AF A581 LDA DTEMP+LO + 23B1 38 SEC + 23B2 E57F SBC DSOR+LO + 23B4 A8 TAY + 23B5 A582 LDA DTEMP+HI + 23B7 E580 SBC DSOR+HI + 23B9 9004 BCC DVLP1 + 23BB 8481 STY DTEMP+LO + 23BD 8582 STA DTEMP+HI + + 23BF CA DVLP1: DEX + 23C0 D0E5 BNE DVLP + + 23C2 267D ROL DVD+LO ; SHIFT LAST CARRY + 23C4 267E ROL DVD+HI ; INTO QUOTIENT + + 23C6 A581 LDA DTEMP+LO ; REMAINDER IN [DTEMP] + 23C8 8575 STA SECTOR ; IS SECTOR ID (0-16) + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 109 +--- Z-DOS: CBM64 --- + + + 23CA A57D LDA DVD+LO ; QUOTIENT IN [DVD] IS TRACK ID + 23CC 18 CLC + 23CD 6905 ADC #5 ; Z-CODE STARTS ON TRACK 5 + + 23CF C911 CMP #17 ; BELOW TRACK 17? + 23D1 900F BCC DVLP2 ; YES, WE'RE DONE + 23D3 18 CLC ; ELSE SKIP OVER + 23D4 6901 ADC #1 ; TRACK 17 + 23D6 C924 CMP #36 ; OUT OF RANGE? + 23D8 B042 BCS TRKERR ; IF > 35, TRACK ERROR + 23DA C912 CMP #18 ; IS THIS TRACK 18? + 23DC D004 BNE DVLP2 ; NO, EXIT + 23DE E675 INC SECTOR ; ELSE SKIP OVER + 23E0 E675 INC SECTOR ; 1ST 2 SECTORS + 23E2 8574 DVLP2: STA TRACK + + ; LDA DBLOCK+LO ; GET LSB OF BLOCK ID + ; AND #%00001111 ; MASK TO GET + ; STA SECTOR ; SECTOR # (0-15) + + ; LDA DBLOCK+HI ; GET MSB OF BLOCK ID + ; AND #%00001111 ; MASK OUT GARBAGE IN BITS 7-4 + ; ASL A ; SHIFT THE LOW NIBBLE + ; ASL A ; INTO THE HIGH NIBBLE + ; ASL A + ; ASL A + ; STA TRACK ; AND SAVE IT HERE FOR A MOMENT + + ; LDA DBLOCK+LO ; GET LSB OF BLOCK ID AGAIN + ; AND #%11110000 ; MASK OUT SECTOR # + ; LSR A ; SHIFT THE HIGH NIBBLE + ; LSR A ; INTO THE LOW NIBBLE + ; LSR A + ; LSR A + ; ORA TRACK ; SUPERIMPOSE NEW HIGH NIBBLE + + ; CLC + ; ADC #5 ; Z-CODE STARTS ON TRACK 5 + + ; CMP #17 ; BELOW TRACK 17? + ; BCC TKOK ; USE AS-IS IF SO + ; CLC ; ELSE SKIP OVER + ; ADC #1 ; TRACK 17 + ; CMP #36 ; ANYTHING HIGHER THAN TRACK 35 + ; BCS TRKERR ; IS AN ERROR + ; CMP #18 ; IS THIS TRACK 18? + ; BNE TKOK ; NO, WE'RE DONE + ; INC SECTOR ; ELSE ADD 2 TO + ; INC SECTOR ; [SECTOR] TO AVOID DIRECTORY + ;TKOK: STA TRACK + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 110 +--- Z-DOS: CBM64 --- + + + 23E4 ; ENTRY FOR "RESTORE" ([TRACK], [SECTOR] & [DRIVE] PRE-ASSIGNED) + + 23E4 18 GETRES: CLC ; CARRY CLEAR = "READ BLOCK" + 23E5 205528 JSR DISK ; GO DO IT! + 23E8 B037 BCS DSKERR ; ERROR IF CARRY SET + + 23EA A000 LDY #0 ; MOVE CONTENTS OF [IOBUFF] + 23EC B90008 GDKL: LDA IOBUFF,Y ; TO THE + 23EF 9172 STA (DBUFF),Y ; TARGET PAGE IN [DBUFF] + 23F1 C8 INY + 23F2 D0F8 BNE GDKL + + 23F4 E670 INC DBLOCK+LO ; POINT TO NEXT + 23F6 D002 BNE GDEX ; Z-BLOCK + 23F8 E671 INC DBLOCK+HI + + 23FA 4C0D24 GDEX: JMP NXTSEC ; POINT TO NEXT SECTOR & PAGE + + 23FD ; -------------------- + 23FD ; PUT [DBLOCK] TO DISK + 23FD ; -------------------- + + 23FD ; ENTRY: [TRACK], [SECTOR] & [DRIVE] ASSIGNED + 23FD ; PAGE TO WRITE IN [DBUFF] + + 23FD A000 PUTDSK: LDY #0 ; MOVE PAGE AT [DBUFF] + 23FF B172 PTKL: LDA (DBUFF),Y ; INTO + 2401 990008 STA IOBUFF,Y ; [IOBUFF] FOR I/O + 2404 C8 INY + 2405 D0F8 BNE PTKL + + 2407 38 SEC ; CARRY SET = "WRITE BLOCK" + 2408 205528 JSR DISK + 240B B00E BCS WRTERR ; CARRY SET IF ERROR + + 240D E675 NXTSEC: INC SECTOR ; POINT TO NEXT SECTOR + 240F A575 LDA SECTOR + 2411 290F AND #%00001111 ; OVEFLOWED? + 2413 D002 BNE SECTOK ; CONTINUE IF NOT + 2415 E674 INC TRACK ; ELSE UPDATE TRACK # + 2417 8575 SECTOK: STA SECTOR ; AND SECTOR # + + 2419 E673 INC DBUFF+HI ; POINT TO NEXT RAM PAGE + 241B 60 WRTERR: RTS + + 241C ; *** ERROR #12: DISK ADDRESS OUT OF RANGE *** + + 241C A90C TRKERR: LDA #12 + 241E 4CC41D JMP ZERROR + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 111 +--- Z-DOS: CBM64 --- + + 2421 ; *** ERROR #14: DRIVE ACCESS *** + + 2421 A90E DSKERR: LDA #14 + 2423 4CC41D JMP ZERROR + + 2426 ; ----------------------------- + 2426 ; SET UP SAVE & RESTORE SCREENS + 2426 ; ----------------------------- + + 2426 20831E SAVRES: JSR ZCRLF ; CLEAR THE BUFFER + 2429 200E23 JSR CLS + + 242C A200 LDX #0 + 242E 8662 STX SCRIPT ; DISABLE SCRIPTING + 2430 A000 LDY #0 + 2432 18 CLC + 2433 4CF0FF JMP PLOT ; HOME CURSOR & RETURN + + 2436 ; ----------------- + 2436 ; DISPLAY A DEFAULT + 2436 ; ----------------- + + 2436 ; ENTRY: DEFAULT (0-8) IN [A] + + 2436 20284465 DEFAL: DB " (Default is " + 2443 2A293A DEFNUM: DB "*):" + 0010 DEFALL EQU $-DEFAL + + 2446 18 DODEF: CLC + 2447 6931 ADC #'1' ; CONVERT TO ASCII 1-9 + 2449 8D4324 STA DEFNUM ; INSERT IN STRING + + 244C A236 LDX #LOW DEFAL + 244E A924 LDA #HIGH DEFAL + 2450 A010 LDY #DEFALL + 2452 20F021 JSR DLINE ; PRINT THE STRING + + 2455 ; FALL THROUGH ... + + 2455 ; -------------------------------- + 2455 ; ACTIVATE CURSOR, CLEAR KEY QUEUE + 2455 ; -------------------------------- + + 2455 A200 CURSON: LDX #0 + 2457 86C6 STX NDX ; CLEAR KEY QUEUE + 2459 E8 INX + 245A 8E15D0 STX SPENA ; ENABLE CURSOR + 245D 60 RTS + + 245E ; ----------------------------- + 245E ; GET SAVE & RESTORE PARAMETERS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 112 +--- Z-DOS: CBM64 --- + + 245E ; ----------------------------- + + 245E 0D POSIT: DB EOL + 245F 506F7369 DB "Position 1-5" + 000D POSITL EQU $-POSIT + + 246B 0D WDRIV: DB EOL + 246C 44726976 DB "Drive 8 or 9" + 000D WDRIVL EQU $-WDRIV + + 2478 0D MIND: DB EOL + 2479 0D DB EOL + 247A 506F7369 DB "Position " + 2483 2A3B2044 MPOS: DB "*; Drive #" + 248D 2A2E MDRI: DB "*." + 248F 0D DB EOL + 2490 41726520 DB "Are you sure? (Y or N):" + 002F MINDL EQU $-MIND + + 24A7 0D INSM: DB EOL + 24A8 496E7365 DB "Insert SAVE disk into Drive #" + 24C5 2A2E SAVDRI: DB "*." + 0020 INSML EQU $-INSM + + 24C7 594553 YES: DB 'YES' + 24CA 0D DB EOL + 0004 YESL EQU $-YES + + 24CB 4E4F NO: DB 'NO' + 24CD 0D DB EOL + 0003 NOL EQU $-NO + + 24CE A25E PARAMS: LDX #LOW POSIT + 24D0 A924 LDA #HIGH POSIT + 24D2 A00D LDY #POSITL + 24D4 20F021 JSR DLINE ; "POSITION (1-5)" + + 24D7 ; GET GAME POSITION + + 24D7 A576 CHANGE: LDA GPOSIT ; SHOW THE CURRENT + 24D9 204624 JSR DODEF ; DEFAULT POSITION + + 24DC 205920 GETPOS: JSR GETKEY ; WAIT FOR A KEY + 24DF C90D CMP #EOL ; IF [RETURN], + 24E1 F00D BEQ POSSET ; USE DEFAULT + 24E3 38 SEC + 24E4 E931 SBC #'1' ; ELSE CONVERT ASCII TO BINARY + 24E6 C905 CMP #5 ; IF BELOW "6" + 24E8 9008 BCC SETPOS ; MAKE IT THE NEW DEFAULT + 24EA 20E422 JSR BOOP ; ELSE RAZZ + 24ED 4CDC24 JMP GETPOS ; AND TRY AGAIN + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 113 +--- Z-DOS: CBM64 --- + + + 24F0 A576 POSSET: LDA GPOSIT ; USE DEFAULT + + 24F2 8578 SETPOS: STA TPOSIT ; USE KEYPRESS + 24F4 18 CLC + 24F5 6931 ADC #'1' ; CONVERT TO ASCII "1"-"5" + 24F7 8D8324 STA MPOS ; STORE IN TEMP STRING + 24FA 8D5E26 STA SVPOS + 24FD 8DF926 STA RSPOS + 2500 201221 JSR LETTER ; AND DISPLAY IT + + 2503 ; GET DRIVE ID + + 2503 A26B LDX #LOW WDRIV + 2505 A924 LDA #HIGH WDRIV + 2507 A00D LDY #WDRIVL + 2509 20F021 JSR DLINE ; "DRIVE 8 OR 9" + + 250C A577 LDA GDRIVE ; SHOW DEFAULT + 250E 18 CLC ; CONVERT 0 OR 1 + 250F 6907 ADC #7 ; TO 7 OR 8 + 2511 204624 JSR DODEF ; SO DEFAULT WILL BE CORRECT + + 2514 205920 GETDRV: JSR GETKEY ; GET A KEYPRESS + 2517 C90D CMP #EOL ; IF [RETURN], + 2519 F00D BEQ DRVSET ; USE DEFAULT + 251B 38 SEC + 251C E938 SBC #'8' ; CONVERT TO BINARY 0 OR 1 + 251E C902 CMP #2 ; IF WITHIN RANGE, + 2520 9008 BCC SETDRV ; SET NEW DEFAULT + 2522 20E422 JSR BOOP + 2525 4C1425 JMP GETDRV ; ELSE TRY AGAIN + + 2528 A577 DRVSET: LDA GDRIVE ; USE DEFAULT + + 252A 8579 SETDRV: STA TDRIVE ; USE [A] + 252C 18 CLC + 252D 6938 ADC #'8' ; CONVERT TO ASCII 8 OR 9 + 252F 8DC524 STA SAVDRI ; STORE IN DRIVE STRING + 2532 8D8D24 STA MDRI ; AND IN TEMP STRING + 2535 201221 JSR LETTER ; AND SHOW NEW SETTING + + 2538 A278 LDX #LOW MIND ; SHOW TEMPORARY SETTINGS + 253A A924 LDA #HIGH MIND + 253C A02F LDY #MINDL + 253E 20F021 JSR DLINE + + 2541 205524 JSR CURSON + + 2544 205920 GETYES: JSR GETKEY + 2547 C959 CMP #'Y' ; IF REPLY IS "Y" + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 114 +--- Z-DOS: CBM64 --- + + 2549 F01E BEQ ALLSET ; ACCEPT RESPONSES + 254B C979 CMP #'y' + 254D F01A BEQ ALLSET + + 254F C94E CMP #'N' ; IF REPLY IS N, + 2551 F00A BEQ RETRY ; DO A RETRY + 2553 C96E CMP #'n' + 2555 F006 BEQ RETRY + + 2557 20E422 JSR BOOP ; INSIST ON Y/RETURN + 255A 4C4425 JMP GETYES ; OR N + + 255D A2CB RETRY: LDX #LOW NO ; ELSE PRINT "NO" + 255F A924 LDA #HIGH NO + 2561 A003 LDY #NOL + 2563 20F021 JSR DLINE + 2566 4CCE24 JMP PARAMS ; AND TRY AGAIN + + 2569 A900 ALLSET: LDA #0 + 256B 8D15D0 STA SPENA ; CURSOR OFF + + 256E A2C7 LDX #LOW YES ; PRINT "YES" + 2570 A924 LDA #HIGH YES + 2572 A004 LDY #YESL + 2574 20F021 JSR DLINE + + 2577 A579 LDA TDRIVE ; MAKE THE TEMPORARY DRIVE + 2579 8577 STA GDRIVE ; THE DEFAULT DRIVE + 257B A578 LDA TPOSIT ; AND THE TEMP POSITION + 257D 8576 STA GPOSIT ; THE DEFAULT POSITION + + 257F ; CALC TRACK & SECTOR OF GAME POSITION + + 257F 0A ASL A ; * 2 + 2580 8574 STA TRACK ; SAVE HERE FOR A MOMENT + 2582 0A ASL A ; * 4 + 2583 18 CLC + 2584 6574 ADC TRACK ; * 6 (6 TRACKS PER POSITION) + 2586 8574 STA TRACK + 2588 E674 INC TRACK ; 1ST TRACK IS 1! + 258A A900 LDA #0 + 258C 8575 STA SECTOR ; ALWAYS START ON SECTOR #0 + + 258E A502 LDA FAST ; FAST-READ ENABLED? + 2590 F003 BEQ PRY1 ; NO, CONTINUE + 2592 202629 JSR FOFF ; ELSE DISENGAGE FAST-READ + + 2595 A577 PRY1: LDA GDRIVE ; TRY TO OPEN SPECIFIED DRIVE + 2597 18 CLC + 2598 6908 ADC #8 + 259A 209D27 JSR DOPEN ; THE DEFAULT DRIVE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 115 +--- Z-DOS: CBM64 --- + + 259D B00D BCS PARERR ; CARRY SET IF ERROR + + 259F A2A7 SREADY: LDX #LOW INSM + 25A1 A924 LDA #HIGH INSM + 25A3 A020 LDY #INSML + 25A5 20F021 JSR DLINE ; "INSERT SAVE DISK IN DRIVE X." + 25A8 20AD25 JSR RETURN ; "PRESS [RETURN] TO CONTINUE." + 25AB 18 CLC ; FOR SUCCESS + 25AC 60 PARERR: RTS + + 25AD ; --------------------- + 25AD ; "PRESS RETURN" PROMPT + 25AD ; --------------------- + + 25AD A2CC RETURN: LDX #LOW RTN + 25AF A925 LDA #HIGH RTN + 25B1 A01D LDY #RTNL + 25B3 20F021 JSR DLINE ; SHOW PROMPT + + 25B6 ; ENTRY FOR QUIT/RESTART + + 25B6 205524 GETRET: JSR CURSON ; ENABLE CURSOR + + 25B9 205920 GTRT: JSR GETKEY ; WAIT FOR [RETURN] + 25BC C90D CMP #EOL + 25BE F006 BEQ RETEX + 25C0 20E422 JSR BOOP ; ACCEPT NO + 25C3 4CB925 JMP GTRT ; SUBSTITUTES! + + 25C6 A900 RETEX: LDA #0 + 25C8 8D15D0 STA SPENA ; KILL CURSOR + 25CB 60 RTS + + 25CC 0D RTN: DB EOL + 25CD 50726573 DB "Press [RETURN] to continue." + 25E8 0D DB EOL + 001D RTNL EQU $-RTN + + 25E9 ; -------------------- + 25E9 ; PROMPT FOR GAME DISK + 25E9 ; -------------------- + + 25E9 0D GAME: DB EOL + 25EA 496E7365 DB "Insert STORY disk into drive #8." + 0021 GAMEL EQU $-GAME + + 260A A908 TOBOOT: LDA #8 + 260C 209D27 JSR DOPEN ; CLOSE OLD, OPEN BOOT DRIVE + + 260F A2E9 LDX #LOW GAME + 2611 A925 LDA #HIGH GAME + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 116 +--- Z-DOS: CBM64 --- + + 2613 A021 LDY #GAMEL + 2615 20F021 JSR DLINE ; "INSERT STORY DISK IN DRIVE #8." + + 2618 20AD25 JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + + 261B A502 LDA FAST ; FAST-READ ENABLED? + 261D F003 BEQ TBT0 ; NO, SCRAM + 261F 20C128 JSR FINIT ; ELSE RE-INIT FAST CODE + + 2622 A9FF TBT0: LDA #$FF ; RE-ENABLE + 2624 8562 STA SCRIPT ; SCRIPTING + 2626 4C0E23 JMP CLS ; CLEAR SCREEN & RETURN + + 2629 ; ------------------------- + 2629 ; SET UP PHONEY STATUS LINE + 2629 ; ------------------------- + + 2629 ; ENTRY: TEXT SET UP FOR "DLINE" + + 2629 20F021 SROOM: JSR DLINE + + 262C A227 LDX #39 ; INVERT & BLACKEN TOP LINE + 262E BD0004 SRLP: LDA SCREEN,X + 2631 0980 ORA #%10000000 + 2633 9D0004 STA SCREEN,X + 2636 A900 LDA #0 + 2638 9D00D8 STA COLRAM,X + 263B CA DEX + 263C 10F0 BPL SRLP + 263E 60 RTS + + 263F ; --------- + 263F ; SAVE GAME + 263F ; --------- + + 263F 53617665 SAV: DB "Save Position" + 264C 0D DB EOL + 000E SAVL EQU $-SAV + + 264D 0D SVING: DB EOL + 264E 53617669 DB "Saving position " + 265E 2A202E2E SVPOS: DB "* ..." + 2663 0D DB EOL + 0017 SVINGL EQU $-SVING + + 2664 202624 ZSAVE: JSR SAVRES ; SET UP SCREEN + + 2667 A23F LDX #LOW SAV + 2669 A926 LDA #HIGH SAV + 266B A00E LDY #SAVL + 266D 202926 JSR SROOM ; "SAVE POSITION" + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 117 +--- Z-DOS: CBM64 --- + + + 2670 20CE24 JSR PARAMS ; GET PARAMETERS + 2673 9006 BCC DOSAVE ; ERROR IF CARRY SET + + 2675 200A26 BADSAV: JSR TOBOOT ; GET BOOT DISK + 2678 4C2A11 JMP PREDF ; PREDICATE FAILS + + 267B A24D DOSAVE: LDX #LOW SVING + 267D A926 LDA #HIGH SVING + 267F A017 LDY #SVINGL + 2681 20F021 JSR DLINE ; "SAVING POSITION X ..." + + 2684 ; SAVE GAME PARAMETERS IN [BUFSAV] + + 2684 AD022A LDA ZBEGIN+ZID ; MOVE GAME ID + 2687 8D200D STA BUFSAV+0 ; INTO 1ST 2 BYTES + 268A AD032A LDA ZBEGIN+ZID+1 ; OF THE AUX LINE BUFFER + 268D 8D210D STA BUFSAV+1 + + 2690 A517 LDA ZSP ; MOVE [ZSP] + 2692 8D220D STA BUFSAV+2 ; TO 3RD BYTE + 2695 A518 LDA OLDZSP ; MOVE [OLDZSP] + 2697 8D230D STA BUFSAV+3 ; TO 4TH + + 269A A202 LDX #2 ; MOVE CONTENTS OF [ZPC] + 269C B519 ZPCSAV: LDA ZPC,X ; TO BYTES 5-7 + 269E 9D240D STA BUFSAV+4,X ; OF [BUFSAV] + 26A1 CA DEX + 26A2 10F8 BPL ZPCSAV + + 26A4 ; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK + + 26A4 A90D LDA #HIGH LOCALS + 26A6 8573 STA DBUFF+HI ; POINT TO THE PAGE + 26A8 20FD23 JSR PUTDSK ; AND WRITE IT OUT + 26AB B0C8 BCS BADSAV ; CATCH WRITE ERROR HERE + + 26AD ; WRITE CONTENTS OF Z-STACK TO DISK + + 26AD A909 LDA #HIGH ZSTAKL ; POINT TO 1ST PAGE + 26AF 8573 STA DBUFF+HI + 26B1 20FD23 JSR PUTDSK ; WRITE 1ST AND + 26B4 B0BF BCS BADSAV + 26B6 20FD23 JSR PUTDSK ; 2ND PAGE OF Z-STACK + 26B9 B0BA BCS BADSAV + + 26BB ; WRITE ENTIRE GAME PRELOAD TO DISK + + 26BB A526 LDA ZCODE ; POINT TO 1ST PAGE + 26BD 8573 STA DBUFF+HI ; OF PRELOAD + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 118 +--- Z-DOS: CBM64 --- + + 26BF AE0E2A LDX ZBEGIN+ZPURBT ; GET # IMPURE PAGES + 26C2 E8 INX ; USE FOR INDEXING + 26C3 8611 STX I+LO + + 26C5 20FD23 LSAVE: JSR PUTDSK + 26C8 B0AB BCS BADSAV + 26CA C611 DEC I+LO + 26CC D0F7 BNE LSAVE + + 26CE 200A26 JSR TOBOOT ; PROMPT FOR GAME DISK + 26D1 4C3611 JMP PREDS ; ELSE PREDICATE SUCCEEDS + + 26D4 ; ------------ + 26D4 ; RESTORE GAME + 26D4 ; ------------ + + 26D4 52657374 RES: DB "Restore Position" + 26E4 0D DB EOL + 0011 RESL EQU $-RES + + 26E5 0D RSING: DB EOL + 26E6 52657374 DB "Restoring position " + 26F9 2A202E2E RSPOS: DB "* ..." + 26FE 0D DB EOL + 001A RSINGL EQU $-RSING + + 26FF 202624 ZREST: JSR SAVRES + + 2702 A2D4 LDX #LOW RES + 2704 A926 LDA #HIGH RES + 2706 A011 LDY #RESL + 2708 202926 JSR SROOM ; "RESTORE POSITION" + + 270B 20CE24 JSR PARAMS ; GET PARAMETERS + 270E B036 BCS BADRES ; ERROR IF CARRY SET + + 2710 A2E5 LDX #LOW RSING + 2712 A926 LDA #HIGH RSING + 2714 A01A LDY #RSINGL + 2716 20F021 JSR DLINE ; "RESTORING POSITION X ..." + + 2719 ; SAVE LOCALS IN CASE OF ERROR + + 2719 A21F LDX #31 + 271B BD000D LOCSAV: LDA LOCALS,X ; COPY ALL LOCALS + 271E 9D0001 STA $0100,X ; TO BOTTOM OF MACHINE STACK + 2721 CA DEX + 2722 10F7 BPL LOCSAV + + 2724 A90D LDA #HIGH LOCALS + 2726 8573 STA DBUFF+HI + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 119 +--- Z-DOS: CBM64 --- + + 2728 20E423 JSR GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + + 272B AD200D LDA BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID + 272E CD022A CMP ZBEGIN+ZID ; MATCH THE CURRENT ID? + 2731 D008 BNE WRONG ; WRONG DISK IF NOT + + 2733 AD210D LDA BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE? + 2736 CD032A CMP ZBEGIN+ZID+1 + 2739 F011 BEQ RIGHT ; CONTINUE IF BOTH BYTES MATCH + + 273B ; HANDLE INCORRECT SAVE DISK + + 273B A21F WRONG: LDX #31 ; RESTORE ALL SAVED LOCALS + 273D BD0001 WR0: LDA $0100,X + 2740 9D000D STA LOCALS,X + 2743 CA DEX + 2744 10F7 BPL WR0 + + 2746 200A26 BADRES: JSR TOBOOT ; PROMPT FOR GAME DISK + 2749 4C2A11 JMP PREDF ; PREDICATE FAILS + + 274C ; CONTINUE RESTORE + + 274C AD102A RIGHT: LDA ZBEGIN+ZSCRIP ; SAVE BOTH FLAG BYTES + 274F 8511 STA I+LO + 2751 AD112A LDA ZBEGIN+ZSCRIP+1 + 2754 8512 STA I+HI + + 2756 A909 LDA #HIGH ZSTAKL ; RETRIEVE OLD CONTENTS OF + 2758 8573 STA DBUFF+HI ; Z-STACK + 275A 20E423 JSR GETRES ; GET 1ST BLOCK OF Z-STACK + 275D 20E423 JSR GETRES ; AND 2ND BLOCK + + 2760 A526 LDA ZCODE + 2762 8573 STA DBUFF+HI + 2764 20E423 JSR GETRES ; GET 1ST BLOCK OF PRELOAD + + 2767 A511 LDA I+LO ; RESTORE THE STATE + 2769 8D102A STA ZBEGIN+ZSCRIP ; OF THE FLAG WORD + 276C A512 LDA I+HI + 276E 8D112A STA ZBEGIN+ZSCRIP+1 + + 2771 AD0E2A LDA ZBEGIN+ZPURBT ; GET # PAGES TO LOAD + 2774 8511 STA I+LO + + 2776 20E423 LREST: JSR GETRES ; FETCH THE REMAINDER + 2779 C611 DEC I+LO ; OF THE PRELOAD + 277B D0F9 BNE LREST + + 277D ; RESTORE THE STATE OF THE SAVED GAME + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 120 +--- Z-DOS: CBM64 --- + + 277D AD220D LDA BUFSAV+2 ; RESTORE THE [ZSP] + 2780 8517 STA ZSP + 2782 AD230D LDA BUFSAV+3 ; AND THE [OLDZSP] + 2785 8518 STA OLDZSP + + 2787 A202 LDX #2 ; RESTORE THE [ZPC] + 2789 BD240D RESZPC: LDA BUFSAV+4,X + 278C 9519 STA ZPC,X + 278E CA DEX + 278F 10F8 BPL RESZPC + + 2791 A900 LDA #FALSE + 2793 851C STA ZPCFLG ; INVALIDATE [ZPC] + + 2795 200A26 JSR TOBOOT ; PROMPT FOR GAME DISK + 2798 4C3611 JMP PREDS ; PREDICATE SUCCEEDS + + END + INCLUD DISK.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 121 +--- DISK ACCESS: CBM64 --- + + + 279B ; -------------- + 279B ; OPEN DRIVE [A] + 279B ; -------------- + + 279B ; ENTRY: DISK ID (8 OR 9 BINARY) IN [A] + + 279B 4930 I0: DB "I0" + 0002 I0L EQU $-I0 + + 279D 857A DOPEN: STA DRIVE ; SAVE DRIVE ID HERE + 279F 20D327 JSR DCLOSE ; CLOSE COMMAND & DATA CHANNELS + + 27A2 A90F LDA #15 ; LOGICAL FILE # + 27A4 A8 TAY ; SECONDARY ADDRESS + 27A5 A67A LDX DRIVE ; DEVICE # (8 OR 9) + 27A7 20BAFF JSR SETLFS ; SET UP LOGICAL FILE + + 27AA A29B LDX #LOW I0 ; POINT TO FILENAME + 27AC A027 LDY #HIGH I0 ; "I0:" + 27AE A902 LDA #I0L ; LENGTH OF FILENAME + 27B0 20BDFF JSR SETNAM + + 27B3 4CC0FF JMP OPEN ; OPEN THE DISK (CARRY CLEAR IF OK) + + 27B6 ; -------------------------- + 27B6 ; OPEN DIRECT ACCESS CHANNEL + 27B6 ; -------------------------- + + 27B6 23 POUND: DB "#" + 0001 POUNDL EQU $-POUND + + 27B7 A900 AOPEN: LDA #0 + 27B9 8D15D0 STA SPENA ; SHUT OFF CURSOR DMA + + 27BC 20D827 JSR ACLOSE ; CLOSE FIRST + + 27BF A902 LDA #2 ; D/A CHANNEL ID + 27C1 A8 TAY ; SECONDARY ID + 27C2 A67A LDX DRIVE + 27C4 20BAFF JSR SETLFS + + 27C7 A2B6 LDX #LOW POUND ; POINT TO FILENAME + 27C9 A027 LDY #HIGH POUND ; "#" + 27CB A901 LDA #POUNDL + 27CD 20BDFF JSR SETNAM + + 27D0 4CC0FF JMP OPEN ; OPEN CHANNEL (CARRY CLEAR IF OK) + + 27D3 ; ------------------- + 27D3 ; CLOSE CURRENT DRIVE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 122 +--- DISK ACCESS: CBM64 --- + + 27D3 ; ------------------- + + 27D3 A90F DCLOSE: LDA #15 ; CLOSE COMMAND CHANNEL + 27D5 20C3FF JSR CLOSE + + 27D8 ; FALL THROUGH ... + + 27D8 ; --------------------- + 27D8 ; CLOSE THE D/A CHANNEL + 27D8 ; --------------------- + + 27D8 A902 ACLOSE: LDA #2 ; AND THE + 27DA 4CC3FF JMP CLOSE ; DATA CHANNEL + + 27DD ; ---------------- + 27DD ; DIVIDE [A] BY 10 + 27DD ; ---------------- + + 27DD ; EXIT: QUOTIENT IN [X], REMAINDER IN [A] + + 27DD A200 DIV10: LDX #0 ; START WITH ZERO QUOTIENT + + 27DF C90A D10L: CMP #10 ; IF DIVISOR < 10, + 27E1 9005 BCC D10EX ; WE'RE DONE + 27E3 E90A SBC #10 ; ELSE SUBTRACT ANOTHER 10 + 27E5 E8 INX ; UPDATE QUOTIENT + 27E6 D0F7 BNE D10L ; BRANCH ALWAYS + + 27E8 60 D10EX: RTS + + 27E9 ; --------------- + 27E9 ; SEND Ux COMMAND + 27E9 ; --------------- + + 27E9 ; ENTRY: ASCII "1" OR "2" IN [A] + + 27E9 55 COMLIN: DB "U" + 27EA 2A DCOMM: DB "*" + 27EB 3A322C30 DB ":2,0," + 27F0 2A2A2A2C DTRAK: DB "***," + 27F4 2A2A2A DSECT: DB "***" + 27F7 0D DB EOL + 000F CMLL EQU $-COMLIN + + 27F8 8DEA27 SENDU: STA DCOMM ; INSERT COMMAND ("1" OR "2") IN STRING + + 27FB ; CONVERT [TRACK] AND [SECTOR] TO ASCII IN [COMLIN] + + 27FB A574 LDA TRACK + 27FD A002 LDY #2 + 27FF 20DD27 TCON: JSR DIV10 ; DIVIDE BY 10 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 123 +--- DISK ACCESS: CBM64 --- + + 2802 0930 ORA #'0' ; CONVERT TO ASCII + 2804 99F027 STA DTRAK,Y ; STORE INTO STRING + 2807 8A TXA ; GET QUOTIENT INTO [A] + 2808 88 DEY ; ZERO-FILL USUSED BYTES + 2809 10F4 BPL TCON + + 280B A575 LDA SECTOR ; SAME FOR SECTOR ID + 280D A002 LDY #2 + 280F 20DD27 SCON: JSR DIV10 + 2812 0930 ORA #'0' + 2814 99F427 STA DSECT,Y + 2817 8A TXA + 2818 88 DEY + 2819 10F4 BPL SCON + + 281B ; SEND COMMAND + + 281B 20CCFF JSR CLRCHN + 281E A20F LDX #15 ; OUTPUT TO THE + 2820 20C9FF JSR CHKOUT ; COMMAND CHANNEL + 2823 B00E BCS UEX ; EXIT W/CARRY SET IF ERROR + + 2825 A000 LDY #0 + 2827 B9E927 SCM0: LDA COMLIN,Y ; SEND THE COMMAND LINE + 282A 20D2FF JSR CHROUT ; TO THE DRIVE CHANNEL + 282D C8 INY ; A BYTE AT A TIME + 282E C00F CPY #CMLL + 2830 90F5 BCC SCM0 + 2832 18 CLC ; SUCCESS! + 2833 60 UEX: RTS + + 2834 ; ---------------------- + 2834 ; SET THE BUFFER POINTER + 2834 ; ---------------------- + + 2834 422D503A BPLINE: DB "B-P:2,0" + 283B 0D DB EOL + 0008 BPLL EQU $-BPLINE + + 283C 20CCFF SETBP: JSR CLRCHN + 283F A20F LDX #15 ; OUTPUT TO + 2841 20C9FF JSR CHKOUT ; COMMAND CHANNEL + 2844 B00E BCS BEX ; CARRY SET IF ERROR + + 2846 A000 LDY #0 + 2848 B93428 SBPL: LDA BPLINE,Y + 284B 20D2FF JSR CHROUT + 284E C8 INY + 284F C008 CPY #BPLL + 2851 90F5 BCC SBPL + 2853 18 CLC + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 124 +--- DISK ACCESS: CBM64 --- + + 2854 60 BEX: RTS + + 2855 ; ------------------------------ + 2855 ; READ/WRITE A BLOCK TO [IOBUFF] + 2855 ; ------------------------------ + + 2855 ; ENTRY: [TRACK] = TRACK # (1-35) + 2855 ; [SECTOR] = SECTOR # (0-15) + 2855 ; [DRIVE] = DRIVE ID (8 OR 9) + 2855 ; CARRY CLEAR TO READ, CARRY SET TO WRITE + + 2855 B033 DISK: BCS DWRITE ; WRITE IF CARRY SET + + 2857 ; READ A DISK BLOCK + + 2857 A5FD LDA FASTEN ; FAST-READ AVAILABLE? + 2859 F007 BEQ SLOW ; USE SLOW CODE IF NOT + 285B A502 LDA FAST ; FAST-READ ENGAGED? + 285D F003 BEQ SLOW ; NO, USE SLOW + + 285F 4C0A29 JMP DOFAST ; ELSE USE FAST-READ ROUTINES + + 2862 20B727 SLOW: JSR AOPEN ; OPEN THE ACCESS CHANNEL + 2865 B055 BCS BADISK + + 2867 A931 LDA #'1' ; SEND A "U1" COMMAND + 2869 20F827 JSR SENDU + 286C B04E BCS BADISK ; CARRY SET IF ERROR + + 286E 203C28 JSR SETBP ; SET THE BUFFER POINTER + 2871 B049 BCS BADISK ; CARRY SET IF ERROR + + 2873 20CCFF JSR CLRCHN + 2876 A202 LDX #2 ; INPUT FROM + 2878 20C6FF JSR CHKIN ; DATA CHANNEL + 287B B03F BCS BADISK + + 287D A000 LDY #0 + 287F 20CFFF READ1: JSR CHRIN ; GET A BYTE + 2882 990008 STA IOBUFF,Y ; MOVE TO I/O BUFFER + 2885 C8 INY + 2886 D0F7 BNE READ1 ; DO 256 BYTES + + 2888 F026 BEQ SHUTD ; THEN EXIT + + 288A ; WRITE A BLOCK + + 288A 20B727 DWRITE: JSR AOPEN ; OPEN THE ACCESS CHANNEL + 288D B02D BCS BADISK + + 288F 203C28 JSR SETBP ; SET THE BUFFER POINTER + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 125 +--- DISK ACCESS: CBM64 --- + + 2892 B028 BCS BADISK ; CARRY SET IF ERROR + + 2894 20CCFF JSR CLRCHN + 2897 A202 LDX #2 ; OUTPUT TO + 2899 20C9FF JSR CHKOUT ; DATA CHANNEL + 289C B01E BCS BADISK ; CARRY SET IF ERROR + + 289E A000 LDY #0 + 28A0 B90008 WRITE1: LDA IOBUFF,Y ; SEND CONTENTS OF [IOBUFF] + 28A3 20D2FF JSR CHROUT ; TO THE DRIVE + 28A6 C8 INY + 28A7 D0F7 BNE WRITE1 ; WRITE 256 BYTES + + 28A9 A932 LDA #'2' ; ISSUE A "U2" COMMAND + 28AB 20F827 JSR SENDU + 28AE B00C BCS BADISK ; CARRY SET IF ERROR + + 28B0 20B7FF SHUTD: JSR READST + 28B3 2983 AND #%10000011 + 28B5 D005 BNE BADISK + + 28B7 20CCFF JSR CLRCHN + 28BA 18 CLC ; CARRY CLEAR FOR SUCCESS + 28BB 60 RTS + + 28BC 20CCFF BADISK: JSR CLRCHN + 28BF 38 SEC + 28C0 60 RTS ; OR SET IF ERROR + + END + INCLUD FAST.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 126 +--- FAST DISK READ: CBM64 --- + + + 28C1 ; -------------- + 28C1 ; INIT FAST READ + 28C1 ; -------------- + + 28C1 A902 FINIT: LDA #2 + 28C3 A8 TAY + 28C4 A208 LDX #8 + 28C6 20BAFF JSR SETLFS + 28C9 A902 LDA #2 + 28CB A2FE LDX #LOW DNAME + 28CD A028 LDY #HIGH DNAME + 28CF 20BDFF JSR SETNAM + 28D2 20C0FF JSR OPEN + + 28D5 A20F LDX #15 + 28D7 20C9FF JSR CHKOUT + + 28DA A009 LDY #9 ; SEND "U1:2,0,1,1" + 28DC B90029 FNT0: LDA DCMND,Y + 28DF 20D2FF JSR CHROUT + 28E2 88 DEY + 28E3 10F7 BPL FNT0 + + 28E5 20CCFF JSR CLRCHN ; RESET CHANNEL + 28E8 A20F LDX #15 + 28EA 20C9FF JSR CHKOUT + + 28ED A955 LDA #'U' ; SEND "U3" COMMAND + 28EF 20D2FF JSR CHROUT + 28F2 A933 LDA #'3' + 28F4 20D2FF JSR CHROUT + + 28F7 A9FF LDA #$FF + 28F9 85FD STA FASTEN ; SET "FAST-READ ENABLED" FLAG + 28FB 4CCCFF JMP CLRCHN ; CLEAR & RETURN + + 28FE 2332 DNAME: DB "#2" + + 2900 312C312C DCMND: DB "1,1,0,2:1U" + + 290A ; ---------------------- + 290A ; FAST-READ A DISK BLOCK + 290A ; ---------------------- + + 290A ; ENTRY: TARGET TRACK IN [TRACK] + 290A ; TARGET SECTOR IN [SECTOR] + 290A ; EXIT: DATA IN [IOBUFF] + + 290A A574 DOFAST: LDA TRACK ; SPECIFY + 290C 208829 JSR SNDBYT ; TRACK & + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 127 +--- FAST DISK READ: CBM64 --- + + 290F A575 LDA SECTOR ; SECTOR TO READ + 2911 208829 JSR SNDBYT + + 2914 A900 LDA #0 + 2916 85FC STA FINDEX ; INIT LOOP INDEX + + 2918 204729 DFST1: JSR ZOOM ; GET A BYTE FROM DISK + 291B A4FC LDY FINDEX + 291D 990008 STA IOBUFF,Y ; MOVE TO [IOBUFF] + 2920 E6FC INC FINDEX + 2922 D0F4 BNE DFST1 ; FILL THE BUFFER + 2924 18 CLC + 2925 60 RTS + + 2926 ; ------------------- + 2926 ; DISENGAGE FAST-READ + 2926 ; ------------------- + + 2926 A900 FOFF: LDA #0 + 2928 85FD STA FASTEN ; CLEAR "FAST-READ ENABLED" FLAG + 292A 208829 JSR SNDBYT ; SEND "TRACK 0" + 292D A908 LDA #8 + 292F 209D27 JSR DOPEN ; CLOSE & OPEN BOOT DRIVE + 2932 20B727 JSR AOPEN ; OPEN DATA CHANNEL + + 2935 A20F LDX #15 + 2937 20C9FF JSR CHKOUT ; OUTPUT TO COMMAND CHANNEL + + 293A A955 LDA #'U' ; SEND "UI" TO RE-INIT DRIVE + 293C 20D2FF JSR CHROUT + 293F A949 LDA #'I' + 2941 20D2FF JSR CHROUT + + 2944 4CCCFF JMP CLRCHN ; CLEAR & RETURN + + 2947 ; ----------------------- + 2947 ; GET FAST BYTE FROM DISK + 2947 ; ----------------------- + + 2947 A980 ZOOM: LDA #$80 + 2949 85FB STA FDATA + + 294B AD00DD GETBIT: LDA CI2PRA + 294E 0910 ORA #$10 + 2950 8D00DD STA CI2PRA + + 2953 AD00DD GETBO0: LDA CI2PRA + 2956 A8 TAY + 2957 2980 AND #$80 + 2959 D0F8 BNE GETBO0 + 295B 98 TYA + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 128 +--- FAST DISK READ: CBM64 --- + + 295C 29EF AND #$EF + 295E 8D00DD STA CI2PRA + + 2961 AD00DD GETBO1: LDA CI2PRA + 2964 A8 TAY + 2965 2980 AND #$80 + 2967 F0F8 BEQ GETBO1 + + 2969 98 GETBO2: TYA + 296A 0910 ORA #$10 + 296C 8D00DD STA CI2PRA + + 296F A207 LDX #7 + 2971 CA GETBO3: DEX + 2972 D0FD BNE GETBO3 + 2974 AD00DD LDA CI2PRA + 2977 A8 TAY + 2978 29EF AND #$EF + 297A 8D00DD STA CI2PRA + 297D 98 TYA + 297E 0A ASL A + 297F 66FB ROR FDATA + 2981 90E6 BCC GETBO2 + + 2983 A5FB LDA FDATA + 2985 49FF EOR #$FF + 2987 60 RTS + + 2988 ; ----------------- + 2988 ; SEND BYTE TO DISK + 2988 ; ----------------- + + 2988 85FB SNDBYT: STA FDATA + + 298A A208 LDX #8 + 298C 20C229 BIT: JSR SCLK1 + + 298F 20B929 WAITD: JSR SETTLE + 2992 2980 AND #$80 + 2994 D0F9 BNE WAITD + 2996 20CB29 JSR SCLK0 + + 2999 20B929 SNDBO1: JSR SETTLE + 299C A8 TAY + 299D 2980 AND #$80 + 299F F0F8 BEQ SNDBO1 + + 29A1 98 TYA + 29A2 0910 ORA #$10 + 29A4 46FB LSR FDATA + 29A6 9002 BCC SNDBO2 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O PAGE 129 +--- FAST DISK READ: CBM64 --- + + 29A8 0920 ORA #$20 + + 29AA 8D00DD SNDBO2: STA CI2PRA + + 29AD A007 LDY #7 + 29AF 88 SNDBO3: DEY + 29B0 D0FD BNE SNDBO3 + 29B2 20CB29 JSR SCLK0 + + 29B5 CA DEX + 29B6 D0D4 BNE BIT + 29B8 60 RTS + + 29B9 ; --------------------------- + 29B9 ; WAIT FOR I/O PORT TO SETTLE + 29B9 ; --------------------------- + + 29B9 AD00DD SETTLE: LDA CI2PRA + 29BC CD00DD CMP CI2PRA + 29BF D0F8 BNE SETTLE + 29C1 60 RTS + + 29C2 ; --------------- + 29C2 ; SET CLKOUT TO 1 + 29C2 ; --------------- + + 29C2 AD00DD SCLK1: LDA CI2PRA + 29C5 0910 ORA #$10 + 29C7 29DF AND #$DF + 29C9 D005 BNE PUTPRT + + 29CB ; --------------- + 29CB ; SET CLKOUT TO 0 + 29CB ; --------------- + + 29CB AD00DD SCLK0: LDA CI2PRA + 29CE 29CF AND #$CF + + 29D0 8D00DD PUTPRT: STA CI2PRA + 29D3 EA NOP + 29D4 EA NOP + 29D5 60 RTS + + END + + 29D6 IF DEBUG + 29D6 INCLUD BUGGER.ASM + 29D6 ENDIF + + 0000 END + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. PAGE 130 +---- SYMBOL TABLE ---- + +A12VAL 11BD BYTGET 0544 CURSOR 0340 DORET 15CA FINIT 28C1 +A2VAL 1456 BYTSND 0577 CURX 2083 DORTI 2357 FIRST1 12FE +ABQUOT 167C CBINV 0316 CUTHI D416 DOSAVE 267B FL0 1E5B +ABREM 166E CEX 1E58 CUTLO D415 DOSCRL 2148 FL1 1E65 +ABSDIV 1653 CHANGE 24D7 CYCLE 00E0 DOSCRN 22D9 FL2 1E70 +ABYTE 000D CHAR 2128 CZSL 1C2C DOSIB 18EF FL3 1E7A +ACLOSE 27D8 CHKEOL 213A D10EX 27E8 DOSTRT 1E13 FLAGSU 1D74 +ADEX 000E CHKIN FFC6 D10L 27DF DOTIME 1F9A FLEX 1950 +ALLSET 2569 CHKOUT FFC9 D6510 0000 DOUT 21F8 FLS0 1D8D +AOPEN 27B7 CHRIN FFCF DATA 000A DOXM 200D FLS1 1D8E +ARG1 0005 CHROUT FFD2 DATIN 0001 DOXOP 0FC6 FLS2 1DA6 +ARG2 0007 CHRTBL 1CFE DATOUT 0002 DRIVE 007A FLSL 1D9F +ARG3 0009 CI2PRA DD00 DBLOCK 0070 DRVSET 2528 FLUSH 1E59 +ARG4 000B CINT FF81 DBUFF 0072 DSECT 27F4 FLUSHW 193B +ATDCY1 D405 CINV 0314 DC0 0F6F DSKCNT 1C00 FNT0 28DC +ATDCY2 D40C CLALL FFE7 DC1 0F76 DSKERR 2421 FOFF 2926 +ATDCY3 D413 CLD0 0E28 DCLOSE 27D3 DSOR 007F FREEZE 1DF8 +ATNIN 0080 CLICK 2100 DCMND 2900 DT0 1FBE FREHI1 D401 +BACKSP 0014 CLK0 053C DCOMM 27EA DT1 1FC4 FREHI2 D408 +BACKUP 21BE CLKIN 0004 DEBNC 0533 DTEMP 0081 FREHI3 D40F +BADISK 28BC CLKOUT 0008 DEBUG 0000 DTRAK 27F0 FRELO1 D400 +BADKEY 20DE CLOCK 1F02 DECVAL 11AA DVD 007D FRELO2 D407 +BADOP1 1025 CLOCKL 0006 DEFAL 2436 DVLP 23A7 FRELO3 D40E +BADOP2 1062 CLOSE FFC3 DEFALL 0010 DVLP1 23BF FWL1 19A0 +BADRES 2746 CLRCHN FFCC DEFNUM 2443 DVLP2 23E2 FWORDS 0033 +BADSAV 2675 CLS 230E DFST1 2918 DVX 11B5 FWSUCC 19DC +BADVER 12E2 CLS0 2321 DGC 1809 DWRITE 288A GAME 25E9 +BCALC 1544 CMDEND 0532 DIGCNT 1805 EAR0 1ACF GAMEL 0021 +BEX 2854 CMDWT 050B DIGITS 005E EAR1 1AD9 GDEX 23FA +BGCOLO D021 CMLL 000F DIRECT 1B4F EARLY 1AC7 GDKL 23EC +BIT 298C CN0 0E4E DISK 2855 ECON 1DC6 GDRIVE 0077 +BITSND 057B CNL 1CB1 DISKE 1AC2 EFIND 192D GETBIT 294B +BLANK 1B61 CNOK 1CBA DIV10 27DD ENDLIN 21C8 GETBO0 2953 +BLINK 007B COLD 0E00 DIVERR 16BB ENTRY 0047 GETBO1 2961 +BLNSW 00CC COLOR 0286 DIVEX 167B ENUMB 1DC1 GETBO2 2969 +BOOP 22E4 COLRAM D800 DIVIDE 163E EOL 000D GETBO3 2971 +BPLINE 2834 COMLIN 27E9 DLINE 21F0 EQBAD 16FA GETBYT 1A1A +BPLL 0008 COMPAR 145E DLS0 1435 EQOK 16F7 GETDRV 2514 +BREAK 1951 CONCNT 0053 DNAME 28FE ERRM 1DB2 GETDSK 238A +BRKTBL 1962 CONIN 0054 DOB2 1157 ERRML 0012 GETIN FFE4 +BSND0 058A CONOUT 0055 DOCALL 1706 ESIZE 004B GETKEY 2059 +BSND1 0592 CONTOP 1C3B DODEF 2446 ETPEX 1599 GETLNG 1076 +BSND2 05A7 CONZST 1C29 DODIS 0FD5 EXEC 00E0 GETP1 155B +BSND3 05AA COUT 1E45 DOEQ 16D3 EXTCOL D020 GETP2 156A +BUF1 0300 CR1 1ECC DOFAST 290A FALSE 0000 GETP3 157D +BUF2 0400 CSET0 1C70 DOFREQ 1B7F FAST 0002 GETPB 158D +BUF3 0500 CSET2 1C82 DOGET 1531 FASTEN 00FD GETPOS 24DC +BUF4 0600 CSHIP 1C75 DOM0 1FF4 FBRK 1978 GETPT1 15A3 +BUF5 0700 CTABLE 1CAF DOMINS 1FE9 FDATA 00FB GETPT2 15B2 +BUFSAV 0D20 CTEST 1C60 DOPEN 279D FINDEX 00FC GETPT3 15B8 +BUMP 00C0 CURSON 2455 DOPM 200B FINDW 197A GETPW 1593 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. PAGE 131 +---- SYMBOL TABLE ---- + +GETRES 23E4 IVX 11BC MPCL 001F OP1 0FFB PNTR 00D3 +GETRET 25B6 J 0013 MPCM 0020 OP1A 1005 POPVAL 10B0 +GETSET 1BD5 JOBS 0000 MPCPNT 0023 OP1B 100F POSIT 245E +GETSHT 1072 JUMPC 00D0 MPOS 2483 OP1EX 1016 POSITL 000D +GETV 1079 K 0015 MSGFLG 009D OP2 102A POSSET 24F0 +GETVAR 108A KEYD 0277 MSIGX D010 OP2A 1034 POUND 27B6 +GETVR1 108F KEYLOG 028F MSTART 0800 OP2B 1037 POUNDL 0001 +GETVRG 10A3 KEYTAB 00F5 MTEMP 005A OP2C 1046 PP0 2221 +GETVRL 1093 LBUFF 0200 NARGS 0004 OP2D 1049 PP1 2244 +GETWRD 1AF0 LDPRE 0F3C NBL 1958 OP2EX 1053 PP2 224D +GETYES 2544 LDTB1 00D9 NBRKS 0006 OPCODE 0003 PP3 225C +GETZ1 1BFC LENGTH 0060 NDX 00C6 OPEN FFC0 PP5 2266 +GETZ2 1C17 LET0 211B NENTS 0049 OPEXT 0F7D PPERR 223E +GETZ3 1C23 LETEX 2125 NEWLOG 234A OPT0 11C6 PPRINT 2204 +GETZCH 1BE1 LETTER 2112 NEWSET 1B65 OPT1 11E2 PPX 1D6E +GKEY0 205D LEX1 21D8 NEXTPC 19E4 OPT2 1202 PREDB 113B +GKEY1 208F LEX2 21E5 NEXTZ 1C49 OPTX 1234 PREDB1 115E +GLOBAL 002F LFROM 006A NLG0 234C OPX0 0F88 PREDB2 1169 +GO 0FE7 LINCNT 0065 NMINV 0318 OPX1 0F8E PREDB3 1170 +GODIV 1660 LINEX 1EEA NO 24CB OPX2 0F98 PREDB5 118E +GPOSIT 0076 LINLEN 0045 NOBLIN 20A7 OPX3 0FA2 PREDF 112A +GS 1BDC LINOUT 1ED5 NOL 0003 OPX4 0FBD PREDLB 114B +GTBIT 0548 LMAX 0066 NOLOG 207C OPXNXT 0FA9 PREDNB 112F +GTBO0 0562 LO 0000 NOMORE 21AD OUT 003D PREDS 1136 +GTBT0 1A2C LOCALS 0D00 NOPS0 000E OUTEOL 2187 PRIL 1270 +GTBT1 1A33 LOCSAV 271B NOPS1 0010 OVER 10D8 PRLEN 006F +GTBT2 1A3C LOLINE 2358 NOPS2 0019 PAGE 1A50 PRNTDC 139D +GTBT3 1A4E LOUT 1EDD NOPSX 000C PAGE0 0028 PRNTN3 1821 +GTEXIT 1C25 LREST 2776 NORAM 0EEF PARAMS 24CE PRNTN4 182A +GTRT 25B9 LRU 0025 NORM 1956 PARERR 25AC PROPB 1D41 +GTZ0 1BE7 LRUMAP 0C50 NOSCRL 217D PATCH 1A25 PROPL 1D62 +GVCALC 1114 LSAVE 26C5 NPC0 19F6 PB 1800 PROPN 1D5D +HDRS 0006 LSTX 00C5 NPC1 19FD PBAD 1488 PROPNX 1D6A +HI 0001 LTO 006C NPC2 1A06 PCALC 17A8 PRY1 2595 +HIBASE 0288 MASK 20B4 NPC3 1A18 PCLOSE 2262 PSET 004C +HILINE 2371 MASK0 20CA NUMBER 17F9 PDC0 13B2 PSHVAL 10C6 +I 0011 MASK1 20D2 NXTP1 15D4 PEX 2277 PSTAT 006E +I0 279B MCLR 1EF5 NXTP2 15E3 PFINE 1307 PTABH 0BA0 +I0L 0002 MDRI 248D NXTP3 15E6 PG1 1A58 PTABL 0B00 +IN 0037 MEMTOP 1E3B NXTSEC 240D PG2 1A65 PTKL 23FF +INCVAL 11B6 MIND 2478 OBJ1 1D2E PG3 1A6C PTZ0 1328 +INDEX 000B MINDL 002F OBJ2 1D35 PG4 1A8E PUSHXA 10CA +INIT0 0500 MINIT 16C0 OBJLOC 1D18 PG5 1AA0 PUTBYT 10E8 +INLOOP 2197 MLOOP 0F60 OBJTAB 0035 PG6 1AAB PUTDSK 23FD +INPUT 218D MODE 0291 OFFSET 004F PG7 1AB7 PUTLSB 17A3 +INSM 24A7 MORE 1EEF OFFSPL 22AD PG8 1ABC PUTP1 17BE +INSML 0020 MOREL 0006 OLDLEN 0061 PGOOD 149B PUTP2 17CD +IOBUFF 0800 MOVMIN 1FCF OLDX 0063 PLERR 17E7 PUTP3 17DD +IOCHAR 0067 MPC 001F OLDY 0064 PLOT FFF0 PUTPRT 29D0 +IOINIT FF84 MPCFLG 0022 OLDZSP 0018 PMAX 0029 PUTVAL 10EE +IRQMSK D01A MPCH 0021 OP0 0FEC PNERR 17E2 PUTVLG 1107 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. PAGE 132 +---- SYMBOL TABLE ---- + +PUTVLL 10F7 RSIGN 005D SHOVE 1B33 SPSTAT 0069 TRY3 16EB +PUTVR1 10F3 RSING 26E5 SHOWIT 21A6 SPT0 07F8 TSET 004D +PWHI1 D403 RSINGL 001A SHUTD 28B0 SPT1 07F9 TSTDO3 05C1 +PWHI2 D40A RSPOS 26F9 SIB 1968 SPT2 07FA TSTDO4 05C9 +PWHI3 D411 RTN 25CC SIGVOL D418 SPT3 07FB TSTDO5 05C5 +PWLO1 D402 RTNL 001D SLINE 0068 SPT4 07FC UDIV 168A +PWLO2 D409 RVS 00C7 SLOAD 0E66 SPT5 07FD UDLOOP 1693 +PWLO3 D410 SAV 263F SLOADL 0019 SPT6 07FE UDNEXT 16AB +PYUCK 12EB SAVDRI 24C5 SLOW 2862 SPT7 07FF UEX 2833 +PZSTR 1B0D SAVL 000E SNDBO1 2999 SREADY 259F UNDER 10C1 +PZTOP 1B16 SAVRES 2426 SNDBO2 29AA SRL0 214F USL0 1F30 +QSIGN 005C SAY1 1CCA SNDBO3 29AF SRL1 216A USLX 201E +QUOT 0056 SAY2 1CD5 SNDBYT 2988 SRL2 2173 V2A1 1067 +R6510 0001 SAYSET 1CBF SOURCE 0043 SRL3 2177 VALUE 000F +RAMTAS FF87 SBL 196F SP0COL D027 SRLP 262E VARGET 1081 +RAND D41B SBPL 2848 SP0X D000 SROOM 2629 VARPUT 10DD +RANDOM 1E3E SCEX 147A SP0Y D001 ST0 0EAA VCREG1 D404 +RASTER D012 SCLK0 29CB SP1COL D028 ST1A 0EB4 VCREG2 D40B +RAZZ 2301 SCLK1 29C2 SP1X D002 ST1B 0EC2 VCREG3 D412 +RDFILE 05BD SCM0 2827 SP1Y D003 STAMP 002D VERIFY 00A0 +READ 0080 SCMP 1470 SP2COL D029 STATEX 2015 VERNUM 1E2F +READ1 287F SCNKEY FF9F SP2X D004 STKERR 13FB VERS 1E1E +READL 188A SCOMP 1465 SP2Y D005 STKEY 0091 VERSL 0011 +READL2 18D5 SCON 280F SP3COL D02A STRING 21F9 VEXIT 1425 +READL3 18F7 SCORE 1EFB SP3X D006 SUREL1 D406 VICIRQ D019 +READST FFB7 SCOREL 0007 SP3Y D007 SUREL2 D40D VMCSB D018 +REMAIN 0058 SCREEN 0400 SP4COL D02B SUREL3 D414 VOCAB 0031 +REMVC1 1380 SCRIPT 0062 SP4X D008 SVING 264D VSUM 12AE +REMVC2 1391 SCROLX D016 SP4Y D009 SVINGL 0017 VSUM0 12BA +REMVEX 139A SCROLY D011 SP5COL D02C SVPOS 265E WAITD 298F +RES 26D4 SECSEK 00B8 SP5X D00A SWAP 002E WARM1 0E7F +RESL 0011 SECTOK 2417 SP5Y D00B TARGET 002B WARM2 0EA6 +RESON D417 SECTOR 0075 SP6COL D02D TBLX 00D6 WARMEX 0F48 +RESULT 0044 SEEK 00B0 SP6X D00C TBT0 2622 WCALC 1540 +RESZPC 2789 SENDU 27F8 SP6Y D00D TCON 27FF WCEX 1129 +RET0 10E6 SET1 1B39 SP7COL D02E TDRIVE 0079 WDRIV 246B +RET1 13CF SET2 1B41 SP7X D00E TICK 20E4 WDRIVL 000D +RET2 13E3 SETA0 0EFA SP7Y D00F TIME 00A2 WNEXT 19BD +RETEX 25C6 SETBP 283C SPACE 0020 TIMEFL 005F WNX 19C8 +RETRY 255D SETDRV 252A SPBGPR D01B TOASC 1B30 WNX1 19D3 +RETURN 25AD SETLFS FFBA SPCALC 22A3 TOBOOT 260A WR0 273D +RFLIP 166A SETMSG FF90 SPEED 0598 TOBOT 22D4 WRDLEN 0046 +RIGHT 274C SETNAM FFBD SPENA D015 TOPERM 1B73 WRITE 0090 +RL0 1898 SETNP 0EF4 SPL0 228B TOQ 1DFB WRITE1 28A0 +RL1 189D SETPOS 24F2 SPL1 2299 TOQL 000E WRONG 273B +RL2 18A4 SETSTR 1AFB SPLEX 22AC TOTOP 22CC WRTERR 241B +RL3 18AD SETTLE 29B9 SPLOFF 22B0 TPOSIT 0078 XMAX 0289 +RLERR 1894 SETWRD 1AE1 SPMC D01C TRACK 0074 XSIZE 0027 +RLEX 18A3 SFDX 00CB SPRT13 0340 TRKERR 241C XXPAND D01D +RLL 18B3 SFLAG 2203 SPRT14 0380 TRUE 00FF YES 24C7 +RPTFLG 028A SHFLAG 028D SPRT15 03C0 TRY2 16DF YESL 0004 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502-C INFOCOM, INC. PAGE 133 +---- SYMBOL TABLE ---- + +YSIZE 0018 ZEQUAL 16CA ZLESS 142C ZPOP 185F ZRT0 124E +YXPAND D017 ZEROPG 0003 ZLOC 130A ZPRB 134B ZRT1 1250 +ZADD 15EC ZERROR 1DC4 ZMLOOP 1609 ZPRC 17EC ZRTRUE 124C +ZBAND 14AA ZFCLR 14DD ZMNEXT 1620 ZPRD 139B ZSAVE 2664 +ZBCOM 141C ZFIRST 12F7 ZMOD 1634 ZPRI 125B ZSCRIP 0010 +ZBEGIN 2A00 ZFLAG 0050 ZMODE 0001 ZPRINT 1406 ZSCRN 22BE +ZBOR 149E ZFSET 14CA ZMOVE 1501 ZPRN 17F1 ZSERIA 0012 +ZBTST 148B ZFSETP 14B6 ZMUL 1606 ZPRR 1278 ZSET 14F4 +ZCALL 16FD ZFWORD 0018 ZMVEX 152A ZPTSIZ 1316 ZSP 0017 +ZCALL1 1734 ZGET 152B ZNEXT 12EE ZPURBT 000E ZSPLIT 227A +ZCALL2 175B ZGETB 153B ZNEXTP 15CD ZPURE 0027 ZSTAKH 0A00 +ZCALL3 1785 ZGETP 1558 ZNOOP 11A9 ZPUSH 1858 ZSTAKL 0900 +ZCHAR 004E ZGETPT 15A0 ZOBJEC 000A ZPUT 1792 ZSTART 1E09 +ZCHKSM 001C ZGLOBA 000C ZOOM 2947 ZPUTB 17A0 ZSTEX 1B0C +ZCODE 0026 ZGO 0006 ZPAGE 002A ZPUTP 17BB ZSUB 15F9 +ZCR0 1EA8 ZGRTR 1440 ZPC 0019 ZQUIT 1DE5 ZUSL 1F08 +ZCRLF 1E83 ZID 0002 ZPCFLG 001C ZRAND 1836 ZVALUE 1414 +ZCRUSH 1CD8 ZIGRTR 144B ZPCH 001B ZREAD 1867 ZVER 1287 +ZD0 1346 ZIN 147B ZPCL 0019 ZREMOV 1359 ZVERS 0000 +ZDEC 133E ZINC 1333 ZPCM 001A ZREST 26FF ZVOCAB 0008 +ZDIV 162A ZIP 0E00 ZPCPNT 001D ZRET 13B8 ZVR 128E +ZDLESS 1432 ZJUMP 1400 ZPCSAV 269C ZRFALS 1257 ZWORD 0051 +ZENDLD 0004 ZLENTH 001A ZPGTOP 008F ZRSTAK 1281 ZZERO 12E5 + +***** NO ERRORS DETECTED ***** diff --git a/64/zip/cold.src b/64/zip/cold.src new file mode 100644 index 0000000..853d40f --- /dev/null +++ b/64/zip/cold.src @@ -0,0 +1,103 @@ + PAGE + SBTTL "--- MACHINE COLDSTART: CBM64 ---" + + ORG ZIP + + ; --------- + ; COLDSTART + ; --------- + +COLD: LDA R6510 + AND #%11111110 ; SWITCH OUT BASIC ROM + STA R6510 ; KERNAL ROM & I/O ENABLED + + LDA #1 ; WHITE + STA COLOR ; TEXT + LDA #12 ; GRAY + STA EXTCOL ; BORDER + STA BGCOLO ; AND BACKGROUND + + LDA #$0E + JSR CHROUT ; USE UPPER/LOWER CHARS + LDA #$80 ; PROHIBIT FURTHER + STA MODE ; CHARSET CHANGES + + LDA #0 + STA MSGFLG ; DISABLE KERNAL MESSAGES + STA SFLAG ; NO PREVIOUS SCRIPTING (BM 5/14/85) + + ; INITIALIZE THE SOUND SYSTEM + + LDX #$1C ; CLEAR + LDA #0 ; ALL +CLD0: STA FRELO1,X ; SID REGISTERS + DEX + BPL CLD0 + + LDA #2 ; SET VOICE #1 + STA PWLO1 ; PULSE WIDTH + LDA #8 ; FOR A + STA PWHI1 ; 50% DUTY CYCLE + + LDA #%10000000 ; DISABLE OUTPUT + STA SIGVOL ; FROM VOICE #3 + + LDA #$EE + STA FRELO3 ; SET VOICE #3 TO + STA FREHI3 ; AN AMUSING FREQUENCY + + LDA #%10000000 ; SPECIFY NOISY WAVEFORM + STA VCREG3 ; FOR RANDOMNESS + + ; INITIALIZE THE SPRITE CURSOR + + LDX #63 ; CLEAR SPRITE #13 RAM + LDA #0 +CN0: STA CURSOR,X + DEX + BPL CN0 + + STA XXPAND ; NORMAL HORIZONTAL + STA YXPAND ; AND VERTICAL SPRITE SIZE + STA SPBGPR ; MAXIMUM SPRITE PRIORITY + STA SPMC ; HI-RES SPRITES + STA SP0COL ; BLACK CURSOR + + JMP WARM1 + + ; --------------- + ; WARMSTART ENTRY + ; --------------- + +SLOAD: DB "The story is loading ..." + DB EOL +SLOADL EQU $-SLOAD + +WARM1: CLD + LDX #$FF + TXS ; RESET MACHINE STACK + JSR CLALL ; CLOSE EVERYTHING + + JSR CLS ; CLEAR SCREEN, ETC. + + LDY #8 ; POSITION "STORY LOADING" MESSAGE + LDX #11 ; AT (8,11) + CLC + JSR PLOT + + LDX #LOW SLOAD + LDA #HIGH SLOAD + LDY #SLOADL + JSR DLINE ; "THE STORY IS LOADING ..." + + LDA #8 ; MAKE BOOT DRIVE + JSR DOPEN ; AND OPEN IT + + LDA FAST ; FAST DISK? + BEQ WARM2 ; NO, CONTINUE + JSR FINIT ; ELSE INIT FAST DISK + + ; FALL THROUGH TO ZIP WARMSTART AT "WARM2" + + END + diff --git a/64/zip/disk.src b/64/zip/disk.src new file mode 100644 index 0000000..fc66c28 --- /dev/null +++ b/64/zip/disk.src @@ -0,0 +1,237 @@ + PAGE + SBTTL "--- DISK ACCESS: CBM64 ---" + + ; -------------- + ; OPEN DRIVE [A] + ; -------------- + + ; ENTRY: DISK ID (8 OR 9 BINARY) IN [A] + +I0: DB "I0" +I0L EQU $-I0 + +DOPEN: STA DRIVE ; SAVE DRIVE ID HERE + JSR DCLOSE ; CLOSE COMMAND & DATA CHANNELS + + LDA #15 ; LOGICAL FILE # + TAY ; SECONDARY ADDRESS + LDX DRIVE ; DEVICE # (8 OR 9) + JSR SETLFS ; SET UP LOGICAL FILE + + LDX #LOW I0 ; POINT TO FILENAME + LDY #HIGH I0 ; "I0:" + LDA #I0L ; LENGTH OF FILENAME + JSR SETNAM + + JMP OPEN ; OPEN THE DISK (CARRY CLEAR IF OK) + + ; -------------------------- + ; OPEN DIRECT ACCESS CHANNEL + ; -------------------------- + +POUND: DB "#" +POUNDL EQU $-POUND + +AOPEN: LDA #0 + STA SPENA ; SHUT OFF CURSOR DMA + + JSR ACLOSE ; CLOSE FIRST + + LDA #2 ; D/A CHANNEL ID + TAY ; SECONDARY ID + LDX DRIVE + JSR SETLFS + + LDX #LOW POUND ; POINT TO FILENAME + LDY #HIGH POUND ; "#" + LDA #POUNDL + JSR SETNAM + + JMP OPEN ; OPEN CHANNEL (CARRY CLEAR IF OK) + + ; ------------------- + ; CLOSE CURRENT DRIVE + ; ------------------- + +DCLOSE: LDA #15 ; CLOSE COMMAND CHANNEL + JSR CLOSE + + ; FALL THROUGH ... + + ; --------------------- + ; CLOSE THE D/A CHANNEL + ; --------------------- + +ACLOSE: LDA #2 ; AND THE + JMP CLOSE ; DATA CHANNEL + + ; ---------------- + ; DIVIDE [A] BY 10 + ; ---------------- + + ; EXIT: QUOTIENT IN [X], REMAINDER IN [A] + +DIV10: LDX #0 ; START WITH ZERO QUOTIENT + +D10L: CMP #10 ; IF DIVISOR < 10, + BCC D10EX ; WE'RE DONE + SBC #10 ; ELSE SUBTRACT ANOTHER 10 + INX ; UPDATE QUOTIENT + BNE D10L ; BRANCH ALWAYS + +D10EX: RTS + + ; --------------- + ; SEND Ux COMMAND + ; --------------- + + ; ENTRY: ASCII "1" OR "2" IN [A] + +COMLIN: DB "U" +DCOMM: DB "*" + DB ":2,0," +DTRAK: DB "***," +DSECT: DB "***" + DB EOL +CMLL EQU $-COMLIN + +SENDU: STA DCOMM ; INSERT COMMAND ("1" OR "2") IN STRING + + ; CONVERT [TRACK] AND [SECTOR] TO ASCII IN [COMLIN] + + LDA TRACK + LDY #2 +TCON: JSR DIV10 ; DIVIDE BY 10 + ORA #'0' ; CONVERT TO ASCII + STA DTRAK,Y ; STORE INTO STRING + TXA ; GET QUOTIENT INTO [A] + DEY ; ZERO-FILL USUSED BYTES + BPL TCON + + LDA SECTOR ; SAME FOR SECTOR ID + LDY #2 +SCON: JSR DIV10 + ORA #'0' + STA DSECT,Y + TXA + DEY + BPL SCON + + ; SEND COMMAND + + JSR CLRCHN + LDX #15 ; OUTPUT TO THE + JSR CHKOUT ; COMMAND CHANNEL + BCS UEX ; EXIT W/CARRY SET IF ERROR + + LDY #0 +SCM0: LDA COMLIN,Y ; SEND THE COMMAND LINE + JSR CHROUT ; TO THE DRIVE CHANNEL + INY ; A BYTE AT A TIME + CPY #CMLL + BCC SCM0 + CLC ; SUCCESS! +UEX: RTS + + ; ---------------------- + ; SET THE BUFFER POINTER + ; ---------------------- + +BPLINE: DB "B-P:2,0" + DB EOL +BPLL EQU $-BPLINE + +SETBP: JSR CLRCHN + LDX #15 ; OUTPUT TO + JSR CHKOUT ; COMMAND CHANNEL + BCS BEX ; CARRY SET IF ERROR + + LDY #0 +SBPL: LDA BPLINE,Y + JSR CHROUT + INY + CPY #BPLL + BCC SBPL + CLC +BEX: RTS + + ; ------------------------------ + ; READ/WRITE A BLOCK TO [IOBUFF] + ; ------------------------------ + + ; ENTRY: [TRACK] = TRACK # (1-35) + ; [SECTOR] = SECTOR # (0-15) + ; [DRIVE] = DRIVE ID (8 OR 9) + ; CARRY CLEAR TO READ, CARRY SET TO WRITE + +DISK: BCS DWRITE ; WRITE IF CARRY SET + + ; READ A DISK BLOCK + + LDA FASTEN ; FAST-READ AVAILABLE? + BEQ SLOW ; USE SLOW CODE IF NOT + LDA FAST ; FAST-READ ENGAGED? + BEQ SLOW ; NO, USE SLOW + + JMP DOFAST ; ELSE USE FAST-READ ROUTINES + +SLOW: JSR AOPEN ; OPEN THE ACCESS CHANNEL + BCS BADISK + + LDA #'1' ; SEND A "U1" COMMAND + JSR SENDU + BCS BADISK ; CARRY SET IF ERROR + + JSR SETBP ; SET THE BUFFER POINTER + BCS BADISK ; CARRY SET IF ERROR + + JSR CLRCHN + LDX #2 ; INPUT FROM + JSR CHKIN ; DATA CHANNEL + BCS BADISK + + LDY #0 +READ1: JSR CHRIN ; GET A BYTE + STA IOBUFF,Y ; MOVE TO I/O BUFFER + INY + BNE READ1 ; DO 256 BYTES + + BEQ SHUTD ; THEN EXIT + + ; WRITE A BLOCK + +DWRITE: JSR AOPEN ; OPEN THE ACCESS CHANNEL + BCS BADISK + + JSR SETBP ; SET THE BUFFER POINTER + BCS BADISK ; CARRY SET IF ERROR + + JSR CLRCHN + LDX #2 ; OUTPUT TO + JSR CHKOUT ; DATA CHANNEL + BCS BADISK ; CARRY SET IF ERROR + + LDY #0 +WRITE1: LDA IOBUFF,Y ; SEND CONTENTS OF [IOBUFF] + JSR CHROUT ; TO THE DRIVE + INY + BNE WRITE1 ; WRITE 256 BYTES + + LDA #'2' ; ISSUE A "U2" COMMAND + JSR SENDU + BCS BADISK ; CARRY SET IF ERROR + +SHUTD: JSR READST + AND #%10000011 + BNE BADISK + + JSR CLRCHN + CLC ; CARRY CLEAR FOR SUCCESS + RTS + +BADISK: JSR CLRCHN + SEC + RTS ; OR SET IF ERROR + + END + diff --git a/64/zip/dispatch.src b/64/zip/dispatch.src new file mode 100644 index 0000000..1cf14cc --- /dev/null +++ b/64/zip/dispatch.src @@ -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 + diff --git a/64/zip/eq.src b/64/zip/eq.src new file mode 100644 index 0000000..26360ab --- /dev/null +++ b/64/zip/eq.src @@ -0,0 +1,152 @@ + PAGE + SBTTL "--- MEMORY ORGANIZATION ---" + +TRUE EQU $FF +FALSE EQU 0 +LO EQU 0 +HI EQU 1 + +IOBUFF EQU MSTART ; 256-BYTE DISK BUFFER +ZSTAKL EQU MSTART+$100 ; Z-STACK LSBS +ZSTAKH EQU MSTART+$200 ; Z-STACK MSBS +PTABL EQU MSTART+$300 ; PAGING TABLE LSBS ($A0 BYTES) +PTABH EQU MSTART+$3A0 ; PAGING TABLE MSBS ($A0 BYTES) +LRUMAP EQU MSTART+$450 ; TIMESTAMP MAP ($A0 BYTES) (BM 11/24/84) +LOCALS EQU MSTART+$500 ; LOCAL VARIABLE STORAGE (32 BYTES) +BUFSAV EQU MSTART+$520 ; I/O AUX BUFFER (80 BYTES) + +ZIP EQU MSTART+$600 ; START OF EXECUTABLE CODE +ZBEGIN EQU ZIP+$1D00 ; START OF Z-CODE + + ; --------------------- + ; 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) PAGING INDEX +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 (BM 11/24/84) +SWAP EQU LRU+9 ; (BYTE) EARLIEST PAGE (BM 11/24/84) + +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 +OLDX EQU TIMEFL+4 ; (BYTE) OLD CURSOR X +OLDY EQU TIMEFL+5 ; (BYTE) OLD CURSOR Y +LINCNT EQU TIMEFL+6 ; (BYTE) LINE COUNTER +LMAX EQU TIMEFL+7 ; (BYTE) MAX # LINES/SCREEN + +IOCHAR EQU TIMEFL+8 ; (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) +TRACK EQU DBLOCK+4 ; (BYTE) TARGET TRACK +SECTOR EQU DBLOCK+5 ; (BYTE) 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 + +DVD EQU DBLOCK+13 ; (WORD) DISK DIVIDEND +DSOR EQU DBLOCK+15 ; (WORD) DISK DIVISOR +DTEMP EQU DBLOCK+17 ; (WORD) DISK TEMP VARIABLE + + END + diff --git a/64/zip/fast.src b/64/zip/fast.src new file mode 100644 index 0000000..489672d --- /dev/null +++ b/64/zip/fast.src @@ -0,0 +1,200 @@ + PAGE + SBTTL "--- FAST DISK READ: CBM64 ---" + + ; -------------- + ; INIT FAST READ + ; -------------- + +FINIT: LDA #2 + TAY + LDX #8 + JSR SETLFS + LDA #2 + LDX #LOW DNAME + LDY #HIGH DNAME + JSR SETNAM + JSR OPEN + + LDX #15 + JSR CHKOUT + + LDY #9 ; SEND "U1:2,0,1,1" +FNT0: LDA DCMND,Y + JSR CHROUT + DEY + BPL FNT0 + + JSR CLRCHN ; RESET CHANNEL + LDX #15 + JSR CHKOUT + + LDA #'U' ; SEND "U3" COMMAND + JSR CHROUT + LDA #'3' + JSR CHROUT + + LDA #$FF + STA FASTEN ; SET "FAST-READ ENABLED" FLAG + JMP CLRCHN ; CLEAR & RETURN + +DNAME: DB "#2" + +DCMND: DB "1,1,0,2:1U" + + ; ---------------------- + ; FAST-READ A DISK BLOCK + ; ---------------------- + + ; ENTRY: TARGET TRACK IN [TRACK] + ; TARGET SECTOR IN [SECTOR] + ; EXIT: DATA IN [IOBUFF] + +DOFAST: LDA TRACK ; SPECIFY + JSR SNDBYT ; TRACK & + LDA SECTOR ; SECTOR TO READ + JSR SNDBYT + + LDA #0 + STA FINDEX ; INIT LOOP INDEX + +DFST1: JSR ZOOM ; GET A BYTE FROM DISK + LDY FINDEX + STA IOBUFF,Y ; MOVE TO [IOBUFF] + INC FINDEX + BNE DFST1 ; FILL THE BUFFER + CLC + RTS + + ; ------------------- + ; DISENGAGE FAST-READ + ; ------------------- + +FOFF: LDA #0 + STA FASTEN ; CLEAR "FAST-READ ENABLED" FLAG + JSR SNDBYT ; SEND "TRACK 0" + LDA #8 + JSR DOPEN ; CLOSE & OPEN BOOT DRIVE + JSR AOPEN ; OPEN DATA CHANNEL + + LDX #15 + JSR CHKOUT ; OUTPUT TO COMMAND CHANNEL + + LDA #'U' ; SEND "UI" TO RE-INIT DRIVE + JSR CHROUT + LDA #'I' + JSR CHROUT + + JMP CLRCHN ; CLEAR & RETURN + + ; ----------------------- + ; GET FAST BYTE FROM DISK + ; ----------------------- + +ZOOM: LDA #$80 + STA FDATA + +GETBIT: LDA CI2PRA + ORA #$10 + STA CI2PRA + +GETBO0: LDA CI2PRA + TAY + AND #$80 + BNE GETBO0 + TYA + AND #$EF + STA CI2PRA + +GETBO1: LDA CI2PRA + TAY + AND #$80 + BEQ GETBO1 + +GETBO2: TYA + ORA #$10 + STA CI2PRA + + LDX #7 +GETBO3: DEX + BNE GETBO3 + LDA CI2PRA + TAY + AND #$EF + STA CI2PRA + TYA + ASL A + ROR FDATA + BCC GETBO2 + + LDA FDATA + EOR #$FF + RTS + + ; ----------------- + ; SEND BYTE TO DISK + ; ----------------- + +SNDBYT: STA FDATA + + LDX #8 +BIT: JSR SCLK1 + +WAITD: JSR SETTLE + AND #$80 + BNE WAITD + JSR SCLK0 + +SNDBO1: JSR SETTLE + TAY + AND #$80 + BEQ SNDBO1 + + TYA + ORA #$10 + LSR FDATA + BCC SNDBO2 + ORA #$20 + +SNDBO2: STA CI2PRA + + LDY #7 +SNDBO3: DEY + BNE SNDBO3 + JSR SCLK0 + + DEX + BNE BIT + RTS + + ; --------------------------- + ; WAIT FOR I/O PORT TO SETTLE + ; --------------------------- + +SETTLE: LDA CI2PRA + CMP CI2PRA + BNE SETTLE + RTS + + ; --------------- + ; SET CLKOUT TO 1 + ; --------------- + +SCLK1: LDA CI2PRA + ORA #$10 + AND #$DF + BNE PUTPRT + + ; --------------- + ; SET CLKOUT TO 0 + ; --------------- + +SCLK0: LDA CI2PRA + AND #$CF + +PUTPRT: STA CI2PRA + NOP + NOP + RTS + + END + diff --git a/64/zip/hardeq.src b/64/zip/hardeq.src new file mode 100644 index 0000000..a95948f --- /dev/null +++ b/64/zip/hardeq.src @@ -0,0 +1,189 @@ + PAGE + SBTTL "--- HARDWARE EQUATES: CBM64 ---" + + ; --------- + ; CONSTANTS + ; --------- + +XSIZE EQU 39 ; X-SIZE OF SCREEN +YSIZE EQU 24 ; Y-SIZE OF SCREEN + +EOL EQU $0D ; EOL CHAR +SPACE EQU $20 ; SPACE CHAR +BACKSP EQU $14 ; BACKSPACE + + ; --------- + ; ZERO-PAGE + ; --------- + +D6510 EQU $00 ; 6510 DATA DIRECTION REGISTER +R6510 EQU $01 ; 6510 I/O PORT +FAST EQU $02 ; FAST-READ AVAILABLE FLAG +STKEY EQU $91 ; STOP KEY FLAG +MSGFLG EQU $9D ; KERNAL MESSAGE CONTROL FLAG +TIME EQU $A2 ; SYSTEM JIFFY TIMER +LSTX EQU $C5 ; LAST KEY PRESSED +NDX EQU $C6 ; # CHARS IN KEYBOARD BUFFER +RVS EQU $C7 ; REVERSE CHARACTER FLAG +SFDX EQU $CB ; CURRENT KEYPRESS +BLNSW EQU $CC ; CURSOR BLINK SWITCH +PNTR EQU $D3 ; CURSOR COLUMN IN LOGICAL LINE +TBLX EQU $D6 ; CURRENT CURSOR ROW +LDTB1 EQU $D9 ; 25-BYTE LINE LINK TABLE +KEYTAB EQU $F5 ; KEYBOARD DECODE TABLE VECTOR + +FDATA EQU $FB ; FAST-READ DATA BUFFER +FINDEX EQU $FC ; FAST-READ BUFFER INDEX +FASTEN EQU $FD ; FAST-READ ENABLED FLAG + + ; ----------- + ; PAGES 2 & 3 + ; ----------- + +LBUFF EQU $0200 ; 89-BYTE LINE BUFFER +KEYD EQU $0277 ; KEYBOARD QUEUE +COLOR EQU $0286 ; FOREGROUND COLOR FOR TEXT +HIBASE EQU $0288 ; TOP PAGE OF SCREEN RAM +XMAX EQU $0289 ; MAXIMUM KEYBOARD QUEUE SIZE +RPTFLG EQU $028A ; KEY REPEAT FLAG +SHFLAG EQU $028D ; SHIFT KEY FLAG +KEYLOG EQU $028F ; VECTOR TO KEY-TABLE SETUP ROUTINE +MODE EQU $0291 ; CHARSET MODE SWITCH +CINV EQU $0314 ; SYSTEM 60HZ IRQ VECTOR +CBINV EQU $0316 ; BRK INSTRUCTION VECTOR +NMINV EQU $0318 ; NMI INTERRUPT VECTOR +SPRT13 EQU $0340 ; SPRITE #13 DATA +SPRT14 EQU $0380 ; SPRITE #14 DATA +SPRT15 EQU $03C0 ; SPRITE #15 DATA + +CURSOR EQU SPRT13 ; CURSOR RAM +SCREEN EQU $0400 ; SCREEN RAM +COLRAM EQU $D800 ; COLOR RAM +SPT0 EQU $07F8 ; SPRITE #0 PNTR +SPT1 EQU $07F9 ; SPRITE #1 PNTR +SPT2 EQU $07FA ; SPRITE #2 PNTR +SPT3 EQU $07FB ; SPRITE #3 PNTR +SPT4 EQU $07FC ; SPRITE #4 PNTR +SPT5 EQU $07FD ; SPRITE #5 PNTR +SPT6 EQU $07FE ; SPRITE #6 PNTR +SPT7 EQU $07FF ; SPRITE #7 PNTR + + ; ------ + ; VIC-II + ; ------ + + ; SPRITE POSITION REGISTERS + +SP0X EQU $D000 ; SPRITE #0 X-POS +SP0Y EQU $D001 ; SPRITE #0 Y-POS +SP1X EQU $D002 ; SPRITE #1 X-POS +SP1Y EQU $D003 ; SPRITE #1 Y-POS +SP2X EQU $D004 ; SPRITE #2 X-POS +SP2Y EQU $D005 ; SPRITE #2 Y-POS +SP3X EQU $D006 ; SPRITE #3 X-POS +SP3Y EQU $D007 ; SPRITE #3 Y-POS +SP4X EQU $D008 ; SPRITE #4 X-POS +SP4Y EQU $D009 ; SPRITE #4 Y-POS +SP5X EQU $D00A ; SPRITE #5 X-POS +SP5Y EQU $D00B ; SPRITE #5 Y-POS +SP6X EQU $D00C ; SPRITE #6 X-POS +SP6Y EQU $D00D ; SPRITE #6 Y-POS +SP7X EQU $D00E ; SPRITE #7 X-POS +SP7Y EQU $D00F ; SPRITE #7 Y-POS +MSIGX EQU $D010 ; HIGH BITS OF SPRITE X-POSITIONS + + ; VARIOUS CONTROL REGISTERS + +SCROLY EQU $D011 ; Y-SCROLL & VIDEO CONTROL +RASTER EQU $D012 ; RASTER COMPARE +SPENA EQU $D015 ; SPRITE ENABLE +SCROLX EQU $D016 ; X-SCROLL & VIDEO CONTROL +YXPAND EQU $D017 ; SPRITE Y-EXPANSION +VMCSB EQU $D018 ; MEMORY CONTROL +VICIRQ EQU $D019 ; CHIP INTERRUPT FLAGS +IRQMSK EQU $D01A ; IRQ MASKS +SPBGPR EQU $D01B ; SPRITE/FOREGROUND PRIORITY +SPMC EQU $D01C ; MULTICOLOR SPRITE CONTROL +XXPAND EQU $D01D ; SPRITE X-EXPANSION + + ; COLOR REGISTERS + +EXTCOL EQU $D020 ; BORDER COLOR +BGCOLO EQU $D021 ; BACKGROUND COLOR +SP0COL EQU $D027 ; SPRITE #0 COLOR +SP1COL EQU $D028 ; SPRITE #1 COLOR +SP2COL EQU $D029 ; SPRITE #2 COLOR +SP3COL EQU $D02A ; SPRITE #3 COLOR +SP4COL EQU $D02B ; SPRITE #4 COLOR +SP5COL EQU $D02C ; SPRITE #5 COLOR +SP6COL EQU $D02D ; SPRITE #6 COLOR +SP7COL EQU $D02E ; SPRITE #7 COLOR + + ; --- + ; SID + ; --- + + ; VOICE #1 REGISTERS + +FRELO1 EQU $D400 ; FREQ +FREHI1 EQU $D401 ; FREQ HIGH BIT +PWLO1 EQU $D402 ; PULSE WIDTH +PWHI1 EQU $D403 ; PULSE WIDTH HIGH NIBBLE +VCREG1 EQU $D404 ; CONTROL +ATDCY1 EQU $D405 ; ATTACK/DECAY +SUREL1 EQU $D406 ; SUSTAIN/RELEASE + + ; VOICE #2 REGISTERS + +FRELO2 EQU $D407 ; FREQ +FREHI2 EQU $D408 ; FREQ HIGH BIT +PWLO2 EQU $D409 ; PULSE WIDTH +PWHI2 EQU $D40A ; PULSE WIDTH HIGH NIBBLE +VCREG2 EQU $D40B ; CONTROL +ATDCY2 EQU $D40C ; ATTACK/DECAY +SUREL2 EQU $D40D ; SUSTAIN/RELEASE + + ; VOICE #3 REGISTERS + +FRELO3 EQU $D40E ; FREQ +FREHI3 EQU $D40F ; FREQ HIGH BIT +PWLO3 EQU $D410 ; PULSE WIDTH +PWHI3 EQU $D411 ; PULSE WIDTH HIGH NIBBLE +VCREG3 EQU $D412 ; VOICE CONTROL +ATDCY3 EQU $D413 ; ATTACK/DECAY +SUREL3 EQU $D414 ; SUSTAIN/RELEASE + + ; MISCELLANEOUS REGISTERS + +CUTLO EQU $D415 ; FILTER CUTOFF, LOW BITS +CUTHI EQU $D416 ; FILTER CUTOFF, HIGH BYTE +RESON EQU $D417 ; RESONANCE CONTROL +SIGVOL EQU $D418 ; VOLUME/FILTER CONTROL +RAND EQU $D41B ; RANDOM NUMBER +CI2PRA EQU $DD00 ; DATA PORT A + + ; ------------------- + ; KERNAL JUMP VECTORS + ; ------------------- + +CHKIN EQU $FFC6 ; OPEN CHANNEL FOR INPUT +CHKOUT EQU $FFC9 ; OPEN CHANNEL FOR OUTPUT +CHRIN EQU $FFCF ; INPUT CHARACTER FROM CHANNEL +CHROUT EQU $FFD2 ; OUTPUT CHARACTER TO CHANNEL +CINT EQU $FF81 ; INIT SCREEN EDITOR +CLALL EQU $FFE7 ; CLOSE ALL CHANNELS & FILES +CLOSE EQU $FFC3 ; CLOSE A FILE +CLRCHN EQU $FFCC ; CLEAR CHANNEL +GETIN EQU $FFE4 ; GET CHAR FROM KEYBOARD QUEUE +IOINIT EQU $FF84 ; INIT I/O +OPEN EQU $FFC0 ; OPEN A FILE +PLOT EQU $FFF0 ; READ/SET CURSOR POSITION +RAMTAS EQU $FF87 ; INIT RAM +READST EQU $FFB7 ; READ I/O STATUS +SCNKEY EQU $FF9F ; SCAN KEYBOARD +SETLFS EQU $FFBA ; SET FILE ATTRIBUTES +SETMSG EQU $FF90 ; SET KERNAL MESSAGES +SETNAM EQU $FFBD ; SET FILENAME + + END + diff --git a/64/zip/io.src b/64/zip/io.src new file mode 100644 index 0000000..d84d8e5 --- /dev/null +++ b/64/zip/io.src @@ -0,0 +1,448 @@ + PAGE + SBTTL "--- GAME I/O: CBM64 ---" + + ; -------------- + ; INTERNAL ERROR + ; -------------- + + ; ENTRY: ERROR CODE IN [A] + +ERRM: DB "Internal error " +ENUMB: DB "00." +ERRML EQU $-ERRM + +ZERROR: LDY #1 ; CONVERT ERROR BYTE IN [A] +ECON: JSR DIV10 ; TO ASCII DECIMAL IN [ENUMB] + ORA #'0' + STA ENUMB,Y + TXA + DEY + BPL ECON + + JSR CLRCHN + JSR ZCRLF ; CLEAR BUFFER + LDA #0 + STA SCRIPT ; DISABLE SCRIPTING + + LDX #LOW ERRM + LDA #HIGH ERRM + LDY #ERRML + JSR DLINE + + ; FALL THROUGH ... + + ; ---- + ; QUIT + ; ---- + +ZQUIT: JSR ZCRLF ; FLUSH BUFFER + + LDX #LOW TOQ + LDA #HIGH TOQ + LDY #TOQL + JSR DLINE ; "END OF STORY" + + LDA FAST ; FAST-READ ENGAGED? + BEQ FREEZE + JSR FOFF ; DISENGAGE IF SO +FREEZE: JMP FREEZE ; AND STOP + +TOQ: DB "End of session." + DB EOL +TOQL EQU $-TOQ + + ; ------- + ; RESTART + ; ------- + +ZSTART: JSR ZCRLF + + LDA FAST ; FAST-READ? + BEQ DOSTRT ; NO, GO + JSR FOFF ; ELSE DISENGAGE + +DOSTRT: LDA ZBEGIN+ZSCRIP+1 ; SAVE SCRIPT STATE + AND #%00000001 ; FOR LATER + STA SFLAG ; (BM 5/14/85) + + JMP WARM1 ; AND DO A WARMSTART + + ; -------------------- + ; PRINT VERSION NUMBER + ; -------------------- + +VERS: DB "C64 Version F" + DB EOL +VERSL EQU $-VERS + +VERNUM: JSR ZCRLF + + LDX #LOW VERS + LDA #HIGH VERS + LDY #VERSL + JMP DLINE + + ; -------------------------- + ; RETURN TOP RAM PAGE IN [A] + ; -------------------------- + +MEMTOP: LDA #$CF ; IT'S A GIVEN + RTS + + ; -------------------------------- + ; RETURN RANDOM BYTES IN [A] & [X] + ; -------------------------------- + +RANDOM: LDA RAND ; SOMETHING FROM HERE + LDX RASTER ; AND HERE + RTS + + ; ------------------- + ; Z-PRINT A CHARACTER + ; ------------------- + + ; ENTRY: ASCII CHAR IN [A] + +COUT: CMP #EOL ; IF EOL, + BEQ ZCRLF ; DO IT! + CMP #SPACE ; IGNORE ALL OTHER + BCC CEX ; CONTROLS + + LDX LENGTH ; ELSE GET LINE POINTER + STA LBUFF,X ; ADD CHAR TO BUFFER + CPX #XSIZE ; END OF LINE? + BCS FLUSH ; YES, FLUSH THE LINE + INC LENGTH ; ELSE UPDATE POINTER + +CEX: RTS + + ; ------------------- + ; FLUSH OUTPUT BUFFER + ; ------------------- + + ; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: LDA #SPACE + +FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR + BEQ FL1 ; IN THE LINE + DEX + BNE FL0 ; IF NONE FOUND, + LDX #XSIZE ; FLUSH ENTIRE LINE + +FL1: STX OLDLEN ; SAVE OLD LINE POS HERE + STX LENGTH ; MAKE IT THE NEW LINE LENGTH + + JSR ZCRLF ; PRINT LINE UP TO LAST SPACE + + ; START NEW LINE WITH REMAINDER OF OLD + + LDX OLDLEN ; GET OLD LINE POS + LDY #0 ; START NEW LINE AT BEGINNING +FL2: INX + CPX #XSIZE ; CONTINUE IF + BCC FL3 ; INSIDE OR + BEQ FL3 ; AT END OF LINE + STY LENGTH ; ELSE SET NEW LINE LENGTH + RTS + +FL3: LDA LBUFF,X ; GET CHAR FROM OLD LINE + STA LBUFF,Y ; MOVE TO START OF NEW LINE + INY ; UPDATE LENGTH OF NEW LINE + BNE FL2 + + ; --------------- + ; CARRIAGE RETURN + ; --------------- + +ZCRLF: INC LINCNT ; NEW LINE GOING OUT + LDA LINCNT ; IS IT TIME TO + CMP LMAX ; PRINT "MORE" YET? + BCC CR1 ; NO, CONTINUE + + ; SCREEN FULL; PRINT "MORE" + + JSR ZUSL ; UPDATE STATUS LINE + + LDA #0 + STA LINCNT ; RESET LINE COUNTER + STA COLOR ; PRINT "MORE" IN BLACK + STA NDX ; CLEAR QUEUE + + SEC + JSR PLOT ; GET CURSOR POSITION + STY OLDX + STX OLDY + + LDX #LOW MORE + LDA #HIGH MORE + LDY #MOREL + JSR DLINE ; PRINT "MORE" DIRECTLY + +ZCR0: JSR GETIN ; GET ANY KEYPRESS + TAX + BEQ ZCR0 + + LDY OLDX + LDX OLDY + CLC + JSR PLOT ; RESTORE CURSOR + + LDA #1 + STA COLOR ; SWITCH BACK TO WHITE + + LDX #LOW MCLR + LDA #HIGH MCLR + LDY #MOREL + JSR DLINE ; RUB OUT "MORE" + + LDY OLDX + LDX OLDY + CLC + JSR PLOT ; RESTORE CURSOR AGAIN + +CR1: LDX LENGTH + LDA #EOL ; INSTALL EOL AT + STA LBUFF,X ; END OF CURRENT LINE + INC LENGTH ; UPDATE LINE LENGTH + +LINOUT: LDY LENGTH ; IF BUFFER EMPTY, + BEQ LINEX ; DON'T PRINT ANYTHING + + STY PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + LDX #0 ; SEND CONTENTS OF [LBUFF] +LOUT: LDA LBUFF,X ; TO SCREEN + JSR CHAR + INX + DEY + BNE LOUT + + JSR PPRINT ; PRINT [LBUFF] IF ENABLED + +LINEX: LDA #0 ; RESET LINE LENGTH + STA LENGTH ; TO ZERO + RTS ; AND RETURN + +MORE: DB "[MORE]" +MOREL EQU $-MORE + +MCLR: DB " " + + ; ---------------------- + ; UPDATE THE STATUS LINE + ; ---------------------- + +SCORE: DB "Score: " +SCOREL EQU $-SCORE + +CLOCK: DB "Time: " +CLOCKL EQU $-CLOCK + +ZUSL: SEC ; SAVE THE CURRENT + JSR PLOT ; CURSOR POSITION + STY OLDX + STX OLDY + + LDA LENGTH ; SAVE ALL + PHA ; STRING-PRINTING + LDA MPCH ; VARIABLES + PHA + LDA MPCM + PHA + LDA MPCL + PHA + LDA TSET + PHA + LDA PSET + PHA + LDA ZWORD+HI + PHA + LDA ZWORD+LO + PHA + LDA ZFLAG + PHA + LDA DIGITS + PHA + + LDX #XSIZE +USL0: LDA LBUFF,X ; MOVE CONTENTS OF [LBUFF] + STA BUFSAV,X ; TO [BUFSAV] + LDA #SPACE ; CLEAR + STA LBUFF,X ; [LBUFF] WITH SPACES + DEX + BPL USL0 + + LDA #0 + STA LENGTH ; RESET LINE LENGTH + STA SCRIPT ; DISABLE SCRIPTING + STA COLOR ; PRINT STATUS LINE IN BLACK + + LDA #$13 ; HOME THE + JSR CHROUT ; CURSOR + LDA #$12 ; PRINT IN + JSR CHROUT ; INVERSE VIDEO + + ; PRINT ROOM DESCRIPTION + + LDA #16 ; GLOBAL VAR #16 (ROOM ID) + JSR GETVRG ; GET IT INTO [VALUE] + LDA VALUE+LO + JSR PRNTDC ; PRINT SHORT ROOM DESCRIPTION + + LDA #24 ; MOVE LINE INDEX UP + STA LENGTH ; TO TIME/SCORE POSITION + + LDA #17 ; GLOBAL VAR #17 (SCORE/HOURS) + JSR GETVRG ; GET IT INTO [VALUE] + + LDA TIMEFL ; GET MODE FLAG + BNE DOTIME ; USE TIME MODE IF NON-ZERO + + ; PRINT "SCORE" + + LDA #'S' + JSR COUT + LDA #'c' + JSR COUT + LDA #'o' + JSR COUT + LDA #'r' + JSR COUT + LDA #'e' + JSR COUT + LDA #':' + JSR COUT + LDA #SPACE + JSR COUT + + LDA VALUE+LO ; MOVE SCORE VALUE + STA QUOT+LO ; INTO [QUOT] + LDA VALUE+HI ; FOR PRINTING + STA QUOT+HI + JSR NUMBER ; PRINT SCORE VALUE IN DECIMAL + + LDA #'/' ; PRINT A SLASH + BNE MOVMIN ; BRANCH ALWAYS + + ; PRINT "TIME" + +DOTIME: LDA #'T' + JSR COUT + LDA #'i' + JSR COUT + LDA #'m' + JSR COUT + LDA #'e' + JSR COUT + LDA #':' + JSR COUT + LDA #SPACE + JSR COUT + + LDA VALUE+LO ; 00 IS REALLY 24 + BNE DT0 + LDA #24 +DT0: CMP #13 ; IS HOURS > 12, + BCC DT1 + SBC #12 ; CONVERT TO 1-12 +DT1: STA QUOT+LO ; MOVE FOR PRINTING + LDA #0 + STA QUOT+HI ; CLEAR MSB + JSR NUMBER + + LDA #':' ; COLON + +MOVMIN: JSR COUT ; PRINT SLASH OR COLON + + LDA #18 ; GLOBAL VAR #18 (MOVES/MINUTES) + JSR GETVRG ; GET IT INTO [VALUE] + LDA VALUE+LO ; MOVE TO [QUOT] + STA QUOT+LO ; FOR EVENTUAL PRINTING + LDA VALUE+HI + STA QUOT+HI + + LDA TIMEFL ; WHICH MODE? + BNE DOMINS ; TIME IF NZ + + ; PRINT NUMBER OF MOVES + + JSR NUMBER ; SHOW # MOVES + JMP STATEX ; ALL DONE + + ; PRINT MINUTES + +DOMINS: LDA VALUE+LO ; CHECK MINUTES + CMP #10 ; IF MORE THAN TEN + BCS DOM0 ; CONTINUE + + LDA #'0' ; ELSE PRINT A + JSR COUT ; PADDING "0" FIRST + +DOM0: JSR NUMBER ; SHOW MINUTES + + LDA #SPACE + JSR COUT ; SEPARATE THINGS + + LDA #17 ; CHECK "HOURS" AGAIN + JSR GETVRG + LDA VALUE+LO + CMP #12 ; PAST NOON? + BCS DOPM ; YES, PRINT "PM" + + LDA #'A' ; ELSE PRINT "AM" + BNE DOXM ; BRANCH ALWAYS + +DOPM: LDA #'P' + +DOXM: JSR COUT + LDA #'M' + JSR COUT + + ; STATUS LINE READY + +STATEX: LDA #40 ; PRINT THE ENTIRE + STA LENGTH ; STATUS LINE + JSR CR1 + + LDX #XSIZE ; RESTORE OLD [LBUFF] +USLX: LDA BUFSAV,X + STA LBUFF,X + DEX + BPL USLX + + PLA ; RESTORE ALL + STA DIGITS ; SAVED VARIABLES + PLA + STA ZFLAG + PLA + STA ZWORD+LO + PLA + STA ZWORD+HI + PLA + STA PSET + PLA + STA TSET + PLA + STA MPCL + PLA + STA MPCM + PLA + STA MPCH + PLA + STA LENGTH + + LDX OLDY ; RESTORE CURSOR + LDY OLDX + CLC + JSR PLOT + + LDX #$FF + STX SCRIPT ; RE-ENABLE SCRIPTING + INX ; = 0 + STX MPCFLG ; INVALIDATE [MPC] + INX ; = 1 + STX COLOR ; PRINT IN WHITE AGAIN + RTS + + END + diff --git a/64/zip/machine.src b/64/zip/machine.src new file mode 100644 index 0000000..8be0eda --- /dev/null +++ b/64/zip/machine.src @@ -0,0 +1,611 @@ + PAGE + SBTTL "--- MACHINE-DEPENDENT I/O: CBM64 ---" + + ; ---------------------------- + ; FETCH ASCII KEYCODE INTO [A] + ; ---------------------------- + + ; EXIT: ASCII IN [A] & [IOCHAR] + +CYCLE EQU $E0 ; SHORT BLINK CYCLE + +GETKEY: TXA ; SAVE [X] & [Y] + PHA + TYA + PHA + +GKEY0: LDX #$FF + STX CURSOR ; FORCE THE CURSOR "ON" + INX ; = 0 + STX BLINK+LO ; RESET THE BLINK COUNTER + STX BLINK+HI ; FOR A LONG DELAY + + SEC ; GET CURSOR POSITION + JSR PLOT ; [Y]=XPOS, [X]=YPOS + + TXA ; CALC SPRITE Y-POS + ASL A + ASL A + ASL A + CLC + ADC #57 + STA SP0Y + + TYA ; GET X-POS INTO [A] + CMP #40 ; STRIP OFF + BCC NOLOG ; LOGICAL LINE OFFSET + SBC #40 + +NOLOG: LDX #0 + CMP #29 ; IF X-POS < 29 + BCC CURX ; MSB OF SPRITE POS IS ZERO + INX ; ELSE SET BIT 0 +CURX: STX MSIGX ; OF X-POS MSB + + ASL A ; CALC LSB OF SPRITE X-POS + ASL A + ASL A + CLC + ADC #24 + STA SP0X + +GKEY1: JSR GETIN ; GET A KEY + TAX ; SAVE HERE + + INC BLINK+LO ; TIME TO BLINK YET? + BNE NOBLIN ; NOT TILL BOTH BLINK TIMERS + INC BLINK+HI ; ARE ZERO + BNE NOBLIN + + LDA #CYCLE ; RESET MSB OF BLINK COUNTER + STA BLINK+HI ; FOR SHORT BLINK INTERVAL + + LDA CURSOR ; FLIP THE CURSOR + EOR #$FF ; SHAPE + STA CURSOR ; AND UPDATE IT + +NOBLIN: TXA ; KEY BEING PRESSED? + BEQ GKEY1 ; NOT IF CODE WAS ZERO + + ; CONVERT & MASK KEYCODE IN [A] + + CMP #'A' ; CONVERT UNSHIFTED ALPHA + BCC MASK ; TO ASCII LOWER CASE + CMP #'Z'+1 + BCS MASK + ADC #$20 + +MASK: AND #%01111111 ; SCREEN OUT SHIFTS + + CMP #EOL ; EOL? + BEQ TICK + CMP #BACKSP ; BACKSPACE? + BEQ TICK + CMP #SPACE ; ANYTHING ELSE < "SPACE" + BCC BADKEY ; IS BAD + + CMP #'<' ; CHANGE "<" + BNE MASK0 ; TO "," + LDA #',' + BNE TICK + +MASK0: CMP #'>' ; CHANGE ">" + BNE MASK1 ; TO "." + LDA #'.' + BNE TICK + +MASK1: CMP #'z'+1 ; PASS L-C ALPHA + BCS BADKEY + CMP #'a' + BCS TICK + + CMP #'Z'+1 ; PASS U-C ALPHA + BCC TICK ; AND OTHER ASCII CHARS + +BADKEY: JSR BOOP ; REJECT BAD KEYPRESS + JMP GKEY0 ; AND TRY AGAIN + + ; "CLICK" THE KEY + +TICK: STA IOCHAR ; SAVE KEYCODE HERE + + LDA #30 + STA FRELO1 ; FREQ LSB + LDA #134 + STA FREHI1 ; FREQ MSB + LDA #0 + TAY ; SET UP CLICK DELAY + STA SUREL1 ; ZERO SUSTAIN + LDA #%10001111 + STA SIGVOL ; FULL VOLUME, VOICE #3 OFF + LDA #%00010001 + STA VCREG1 ; ACTIVATE TRIANGLE WAVE + +CLICK: DEY ; [Y] = 0 ON ENTRY + BNE CLICK + + STY VCREG1 ; STOP THE SOUND + LDA #%10000000 ; ZERO VOLUME + STA SIGVOL ; WITH VOICE #3 OFF + + PLA ; RESTORE [X] & [Y] + TAY + PLA + TAX + LDA IOCHAR ; RESTORE CODE INTO [A] + RTS + + ; ------------------------- + ; OUTPUT AN ASCII CHARACTER + ; ------------------------- + +LETTER: CMP #'a' ; LOWER-CASE? + BCC LET0 ; NO, CONTINUE + CMP #'z'+1 + BCS LET1 + AND #%01011111 ; ELSE MASK FOR LOWER-CASE + JMP CHROUT + +LET0: CMP #'A' ; UPPER-CASE? + BCC LET1 + CMP #'Z'+1 + BCS LET1 + ORA #%00100000 ; MAKE UPPER + JMP CHROUT + +LET1: CMP #$5F ; SB _ + BNE LET2 + LDA #$AF ; MAKE IT THAT + BNE LETEX +LET2: CMP #$7C ; SB | + BNE LETEX + LDA #$7D ; MAKE IT THAT +LETEX: JMP CHROUT + + ; ----------------- + ; PRINT CHAR IN [A] + ; ----------------- + +CHAR: STA IOCHAR ; SAVE HERE + TXA ; SAVE [X] AND [Y] + PHA + TYA + PHA + + SEC ; GET CURSOR X- AND Y-POS + JSR PLOT ; INTO [Y] AND [X], RESPECTIVELY + TYA + CMP #40 ; STRIP OFF THE + BCC CHKEOL ; LOGICAL LINE OFFSET + SBC #40 ; UPDATE [Y] IF NECESSARY + TAY + +CHKEOL: LDA IOCHAR ; RESTORE CHAR + CMP #EOL ; IS IT EOL? + BEQ OUTEOL ; YES, SPECIAL HANDLING + + ; HANDLE A NON-EOL CHAR + + CPX #YSIZE-1 ; ON LAST SCREEN LINE? + BCC NOSCRL ; NO, NO SCROLL NEEDED + CPY #XSIZE ; LAST CHAR ON LINE? + BCC NOSCRL ; NO, DON'T SCROLL + + ; SCROLL THE SCREEN + +DOSCRL: DEX ; PUSH CURSOR UP ONE LINE + CLC + JSR PLOT ; RESET THE CURSOR + + 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 #SPACE +SRL3: STA SCREEN+960,X ; CLEAR LAST LINE + DEX ; OF SCREEN RAM + BPL SRL3 + +NOSCRL: LDA IOCHAR ; RESTORE CHAR + JSR LETTER ; OFF TO THE SCREEN! + PLA ; RESTORE [X] AND [Y] + TAY + PLA + TAX + RTS + + ; HANDLE EOL + +OUTEOL: CPX #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] + + JSR CURSON ; ACTIVATE CURSOR, CLEAR KEY QUEUE + + LDY #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" + LDX #0 + STX SPENA ; DISABLE CURSOR DMA + JSR CHAR ; AND SEND EOL TO SCREEN + + ; MOVE [LBUFF] TO [ARG1] W/LC CONVERSION + +LEX1: LDA LBUFF-1,Y ; GET A CHAR FROM [LBUFF] + AND #%01111111 ; MAKE POSITIVE + 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 + BNE LEX1 ; ALL CHARS MOVED ("BNE" 8/14/85 BM) + + 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] + ; NOW WITH IMPROVED ERROR PROTECTION! (BM 11/24/84) + +SFLAG: DB 0 ; PREVIOUS SCRIPT MODE (BM 5/14/85) + +PPRINT: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? + BEQ PEX ; NO, SCRAM IMMEDIATELY + + LDA ZBEGIN+ZSCRIP+1 ; CHECK SCRIPT FLAG + AND #%00000001 ; SCRIPTING ON? + BEQ PP3 ; NO, CHECK FOR "UNSCRIPT" + + LDA PSTAT ; CHECK PRINTER STATUS + BMI PEX ; CAN'T OPEN IF NEGATIVE + BNE PP1 ; ALREADY OPEN, SCRIPT THE LINE + + ; OPEN THE PRINTER FOR OUTPUT + + LDA FAST ; FAST-READ ENGAGED? + BEQ PP0 ; NO, IGNORE + JSR FOFF ; ELSE DISENGAGE + LDA #8 + JSR DOPEN ; AND RESET THE DRIVE + +PP0: LDX #0 + STX FAST ; BYE, FAST DRIVE! + INX ; = 1 + STX PSTAT ; SET STATUS TO "PRINTER OPENED" (1) + + LDA #4 ; LOGICAL FILE #4 + TAX ; DEVICE #4 + LDY #7 ; ALLOW UPPER/LOWER CASE + JSR SETLFS ; SET UP LOGICAL FILE + BCS PPERR ; ERROR IF CARRY SET + LDA #0 + JSR SETNAM ; NO FILENAME REQUIRED + BCS PPERR ; ERROR IF CARRY SET + JSR OPEN ; OPEN THE CHANNEL + BCC PP1 ; OPEN OKAY IF CARRY CLEAR + +PPERR: LDA #$FF ; ELSE SET PRINTER STATUS + STA PSTAT ; TO "CAN'T OPEN" + BNE PP5 ; AND SIMULATE AN "UNSCRIPT" + +PP1: LDX #4 ; SET PRINTER CHANNEL + JSR CHKOUT ; TO "OUTPUT" + BCS PPERR ; ERROR IF CARRY SET + + LDY #0 ; INIT INDEX +PP2: LDA LBUFF,Y + JSR LETTER + BCS PPERR ; ERROR IF CARRY SET + INY + DEC PRLEN + BNE PP2 + BEQ PEX ; RESET & RETURN + + ; CHECK FOR "UNSCRIPT" + +PP3: LDA PSTAT ; CHECK PRINTER STATUS + BEQ PEX ; EXIT IF PRINTER WAS OFF + BMI PEX ; OR UNOPENABLE + +PCLOSE: LDA #0 ; RESET PRINTER STATUS FLAG + STA PSTAT ; TO "CLOSED" + + ; ENTRY FOR PRINTER ERROR + +PP5: LDA #4 + JSR CLOSE ; CLOSE THE PRINTER CHANNEL + + LDA FAST ; FAST-READ AVAILABLE? + BEQ PEX ; NO, EXIT + LDA #8 ; ELSE + JSR DOPEN ; RESET BOOT DRIVE + JMP FINIT ; RE-ENGAGE FAST-READ & RETURN + +PEX: JMP CLRCHN + + ; ------------ + ; 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 #SPACE +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 TOBOT + +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 + RTS + + ; ------ + ; 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 TOBOT ; GO TO BOTTOM WINDOW + CMP #1 ; IF [ARG1] <> 1, + BNE SPLEX ; IGNORE THE REQUEST + + ; SET TO TOP WINDOW + +TOTOP: LDX #21 ; TEMPORARILY RESET + STX LMAX ; [LMAX] TO KILL "MORE" + LDX #1 ; Y-POS = 1 + BNE DOSCRN + + ; SET TO BOTTOM WINDOW + +TOBOT: JSR SPCALC ; RE-CALC [LMAX] + LDX #23 ; Y-POS = 23 + +DOSCRN: LDY #0 ; X-POS = 0 + STY LINCNT ; RESET LINE COUNT + CLC + JSR PLOT ; SET CURSOR TO X=[Y], Y=[X] + JMP NEWLOG ; RESET LINE TABLE & RETURN + + ; --------- + ; RAZZ USER + ; --------- + +BOOP: LDA #$00 + STA FRELO1 ; FREQ LSB + LDA #$05 + STA FREHI1 ; FREQ MSB + LDA #%11110000 + STA SUREL1 ; FULL SUSTAIN + LDA #%10001111 + STA SIGVOL ; FULL VOLUME + LDA #%01000001 + STA VCREG1 ; START PULSE + + LDA #252 ; WAIT 4 JIFFIES + STA TIME +RAZZ: LDA TIME + BNE RAZZ + + STA VCREG1 ; STOP PULSE + LDA #%10000000 + STA SIGVOL ; VOLUME OFF + RTS + + ; ------------------------ + ; CLEAR SCREEN & COLOR RAM + ; ------------------------ + +CLS: LDA #HIGH SCREEN ; POINT [I] TO + STA I+HI ; SCREEN RAM + LDA #HIGH COLRAM ; POINT [J] TO + STA J+HI ; COLOR RAM + + LDY #0 ; RESET PAGE INDEX + STY I+LO ; BOTH RAMS START + STY J+LO ; ON PAGE BOUNDARIES + STY SPENA ; MAKE SURE CURSOR IS DEAD! + + LDX #4 ; CLEAR 4 PAGES +CLS0: LDA #SPACE ; SPACE CHAR + STA (I),Y ; FOR SCREEN + LDA #1 ; "WHITE" CODE + STA (J),Y ; FOR COLOR RAM + INY + BNE CLS0 + INC I+HI ; POINT TO + INC J+HI ; NEXT PAGE + DEX ; 4 PAGES DONE? + BNE CLS0 ; LOOP TILL EMPTY + + LDA #13 ; RESET THE + STA SPT0 ; SPRITE RAM POINTER + + JSR TOTOP ; SET CURSOR TO (0,1) + JSR SPLOFF ; DISABLE SPLIT SCREEN + + SEI + LDA #LOW DORTI ; POINT THE SYSTEM NMI VECTOR + STA NMINV+LO ; TO A SIMPLE "RTI" INSTRUCTION + LDA #HIGH DORTI ; TO DISABLE THE STOP/RESTORE EXIT + STA NMINV+HI + CLI + + ; FALL THROUGH ... + + ; ---------------------------- + ; RESET THE LOGICAL LINE TABLE + ; ---------------------------- + +NEWLOG: LDX #24 +NLG0: LDA HILINE,X ; GET MSB OF LINE ADDRESS + ORA #%10000000 ; SET THE HIGH BIT + STA LDTB1,X ; STORE IN THE LINE TABLE + DEX + BPL NLG0 + RTS + +DORTI: RTI ; RTI INSTRUCTION FOR NMI + + ; ------------------- + ; LINE ADDRESS TABLES + ; ------------------- + +LOLINE: DB $00,$28,$50,$78,$A0,$C8,$F0,$18 + DB $40,$68,$90,$B8,$E0,$08,$30,$58 + DB $80,$A8,$D0,$F8,$20,$48,$70,$98 + DB $C0 + +HILINE: DB $04,$04,$04,$04,$04,$04,$04,$05 + DB $05,$05,$05,$05,$05,$06,$06,$06 + DB $06,$06,$06,$06,$07,$07,$07,$07 + DB $07 + + END + diff --git a/64/zip/main.src b/64/zip/main.src new file mode 100644 index 0000000..788d6ca --- /dev/null +++ b/64/zip/main.src @@ -0,0 +1,211 @@ + 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 + STA MBYTE + LDA #0 ; BREAKPOINT #0 + JSR DOBUG + LDA MBYTE + 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 + diff --git a/64/zip/objects.src b/64/zip/objects.src new file mode 100644 index 0000000..63a9585 --- /dev/null +++ b/64/zip/objects.src @@ -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 + diff --git a/64/zip/ops0.src b/64/zip/ops0.src new file mode 100644 index 0000000..dc74821 --- /dev/null +++ b/64/zip/ops0.src @@ -0,0 +1,135 @@ + 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 ZIP VERSION NUMBER + + 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 ZBEGIN+ZLENTH ; GET LENGTH OF Z-CODE + STA I+HI ; IN WORDS + LDA ZBEGIN+ZLENTH+1 ; FIRST MSB + STA I+LO ; THEN LSB + + ASL I+LO ; CONVERT Z-CODE LENGTH + ROL I+HI ; TO # BYTES + ROL K+LO ; TOP BIT IN [K+LO] + + LDA #K+HI ; PATCH THE "GETBYT" ROUTINE + STA PATCH ; TO USE [K+HI]=0 INSTEAD OF [ZPURE] + +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 ; MIDDLE BYTE + CMP I+HI + BNE VSUM + + LDA MPCH ; AND HIGH BIT + CMP K+LO + BNE VSUM + + 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 + diff --git a/64/zip/ops1.src b/64/zip/ops1.src new file mode 100644 index 0000000..76d3099 --- /dev/null +++ b/64/zip/ops1.src @@ -0,0 +1,315 @@ + 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 + + ; MAKE SURE [X] WAS COMPLEMENT OF [A] (BM 11/24/84) + + EOR #$FF ; COMPLEMENT [A] + CMP I+HI ; MATCHED? + BNE STKERR ; ERROR IF NOT + + 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 + + ; *** ERROR #15: Z-STACK DESTROYED *** + +STKERR: LDA #15 ; (BM 11/24/84) + JMP ZERROR + + ; ---- + ; 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 + diff --git a/64/zip/ops2.src b/64/zip/ops2.src new file mode 100644 index 0000000..7d3be0a --- /dev/null +++ b/64/zip/ops2.src @@ -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 + diff --git a/64/zip/opsx.src b/64/zip/opsx.src new file mode 100644 index 0000000..791e928 --- /dev/null +++ b/64/zip/opsx.src @@ -0,0 +1,349 @@ + 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 INTO [A] + EOR #$FF ; COMPLEMENT FOR ERROR CHECK (BM 11/24/84) + 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 + + \ No newline at end of file diff --git a/64/zip/paging.src b/64/zip/paging.src new file mode 100644 index 0000000..75048ae --- /dev/null +++ b/64/zip/paging.src @@ -0,0 +1,271 @@ + 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 EARLY2 ; GET EARLIEST NON-ZERO 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 + LDY ZPAGE ; AND PAGE INDEX (BM 8/27/85) + 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 + + ; ---------------------------------- + ; LOCATE EARLIEST NON-ZERO TIMESTAMP + ; (BM/LS 8/27/85) + ; ---------------------------------- + +EARLY2: LDX #0 + STX SWAP ; INIT INDEX + +E2A: LDA LRUMAP,X ; GET STAMP OF 1ST BUFFER + BNE E2B ; NON-ZERO, SO IT'S OKAY + INX ; ELSE SKIP TO NEXT BUFFER + CPX PMAX ; OUT OF BUFFERS? + BCC E2A ; NO, KEEP LOOKING + BCS E2E ; ELSE WE MUST USE 0 + +E2B: INX ; START COMPARE WITH NEXT BUFFER + +E2C: CMP LRUMAP,X ; IS THIS STAMP EARLIER THAN [A]? + BCC E2D ; IF SMALLER, TRY NEXT STAMP + LDY LRUMAP,X ; IS TEST STAMP 0? + BEQ E2D ; YES, USE OLD + TYA ; ELSE USE NEW + STX SWAP ; UPDATE BUFFER INDEX + +E2D: INX ; POINT TO NEXT BUFFER + CPX PMAX ; OUT OF BUFFERS? + BCC E2C ; NO, LOOP TILL EMPTY + +E2E: STA LRU ; [A] HAS EARLIEST STAMP + 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 + + \ No newline at end of file diff --git a/64/zip/read.src b/64/zip/read.src new file mode 100644 index 0000000..04814ad --- /dev/null +++ b/64/zip/read.src @@ -0,0 +1,306 @@ + 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 ; PATCH IF ZERO + CMP #60 ; OKAY IF < 60 + BCC RL0 + +RLERR: LDA #59 ; MAXIMUM VALUE IS 59 (BM 5/14/85) + STA (ARG2),Y + +RL0: INY ; 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 EOL ; 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 + diff --git a/64/zip/shake.src b/64/zip/shake.src new file mode 100644 index 0000000..667f7f8 --- /dev/null +++ b/64/zip/shake.src @@ -0,0 +1,183 @@ + PAGE + SBTTL "--- CBM64 FAST DISK HANDSHAKE ROUTINES ---" + + ; ------------------ + ; 1541 DRIVE EQUATES + ; ------------------ + +PB EQU $1800 +JOBS EQU $00 +HDRS EQU $06 +DATA EQU $0A +INDEX EQU $0B + +DATIN EQU $01 +DATOUT EQU $02 +CLKIN EQU $04 +CLKOUT EQU $08 +ATNIN EQU $80 + +READ EQU $80 +WRITE EQU $90 +VERIFY EQU $A0 +SEEK EQU $B0 +SECSEK EQU SEEK+8 +BUMP EQU $C0 +JUMPC EQU $D0 +EXEC EQU $E0 + +BUF1 EQU $0300 +BUF2 EQU $0400 +BUF3 EQU $0500 +BUF4 EQU $0600 +BUF5 EQU $0700 + +DSKCNT EQU $1C00 ; DISK CONTROLLER PORT ADDRESS + + ORG BUF3 + +INIT0: LDA PB + AND #$FF-DATOUT-CLKOUT + STA PB + + JSR CLK0 + +CMDWT: LDA DSKCNT ; READ CONTROLLER + AND #%11110111 ; CLEAR BIT 3 + STA DSKCNT ; TO SHUT OFF THE DAMNED LITTLE RED LIGHT + + JSR BYTGET ; GET TRACK ID (1-35) + TAX ; SAVE HERE + BEQ CMDEND ; IF ZERO + CMP #$FF ; OR $FF, + BEQ CMDEND ; DISENGAGE + STA HDRS ; ELSE SET TRACK # + + JSR BYTGET ; GET SECTOR # + STA HDRS+1 ; AND SET IT + + LDA DSKCNT ; TURN BACK ON + ORA #%00001000 ; THE STUPID LITTLE + STA DSKCNT ; RED LIGHT + + JSR RDFILE ; GET THE DATA + + JMP CMDWT ; WAIT FOR NEXT TRACK/SECTOR + +CMDEND: RTS ; EXIT HARD LOOP + +DEBNC: LDA PB ; WAIT FOR SERIAL LINE + CMP PB ; TO SETTLE DOWN + BNE DEBNC + RTS + +CLK0: JSR DEBNC + AND #CLKIN + BNE CLK0 + RTS + +BYTGET: LDA #$80 + STA DATA + +GTBIT: JSR DEBNC + TAY + AND #CLKIN + BEQ GTBIT + SEI + TYA + ORA #DATOUT + STA PB + + JSR CLK0 + LDA PB + AND #$FF-DATOUT + STA PB + +GTBO0: JSR DEBNC + TAY + AND #CLKIN + BEQ GTBO0 + JSR CLK0 + CLI + TYA + LSR A + ROR DATA + BCC GTBIT + + LDA DATA + RTS + +BYTSND: LDX #8 + STA DATA + +BITSND: LDA PB + TAY + AND #CLKIN + BEQ BITSND + TYA + ORA #DATOUT + STA PB + SEI + +BSND0: LDA PB + TAY + AND #CLKIN + BNE BSND0 + +BSND1: TYA + AND #$FF-DATOUT + STA PB + +SPEED: LDA PB + TAY + AND #CLKIN + BEQ SPEED + + TYA + LSR DATA + BCC BSND2 + ORA #DATOUT + +BSND2: STA PB + +BSND3: LDA PB + TAY + AND #CLKIN + BNE BSND3 + TYA + AND #$FF-DATOUT + STA PB + + DEX + BNE SPEED + CLI + RTS + +RDFILE: LDA #READ + STA JOBS + +TSTDO3: LDA JOBS + BMI TSTDO3 + +TSTDO5: LDA #0 + STA INDEX + +TSTDO4: LDY INDEX + LDA BUF1,Y + JSR BYTSND + INC INDEX + BNE TSTDO4 + RTS + + ; FILL REMAINDER OF SECTOR + ; WITH JUNK + + DB 0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0 + DB 0,0 + + END + diff --git a/64/zip/subs.src b/64/zip/subs.src new file mode 100644 index 0000000..b2fec65 --- /dev/null +++ b/64/zip/subs.src @@ -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 + diff --git a/64/zip/warm.src b/64/zip/warm.src new file mode 100644 index 0000000..4bfcbea --- /dev/null +++ b/64/zip/warm.src @@ -0,0 +1,130 @@ + PAGE + SBTTL "--- WARMSTART ROUTINE ---" + + ; ------------- + ; ZIP WARMSTART + ; ------------- + +WARM2: LDA #0 ; CLEAR ALL Z-PAGE VARIABLES + LDX #ZEROPG +ST0: STA 0,X + INX + CPX #ZPGTOP + BCC ST0 + + ; INIT THE PAGING TABLES + + TAX ; = 0 + LDA #$FF +ST1A: STA PTABL,X + STA PTABH,X + INX + CPX #$A0 + BCC ST1A + + ; INIT THE TIMESTAMP MAP (BM 11/24/84)\ + + LDA #0 + TAX +ST1B: STA LRUMAP,X + INX + CPX #$A0 + BCC ST1B + + INC ZSP ; INIT Z-STACK POINTERS + INC OLDZSP ; TO "1" + INC STAMP ; INIT TIMESTAMP (BM 11/24/84) + + ; 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 + 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: CMP #$A0 ; DON'T ALLOW MORE THAN $A0 PAGES + BCC SETA0 + LDA #$A0 +SETA0: 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 + + INC SCRIPT ; ENABLE SCRIPTING + LDA ZBEGIN+ZSCRIP+1 ; STUFF IN THE + ORA SFLAG ; PREVIOUS SCRIPT MODE + STA ZBEGIN+ZSCRIP+1 ; (BM 5/14/85) + + JSR CLS ; CLEAR SCREEN, DISABLE SPLIT + + ; ... AND FALL INTO MAIN LOOP + + END + diff --git a/64/zip/zdos.src b/64/zip/zdos.src new file mode 100644 index 0000000..2efba4d --- /dev/null +++ b/64/zip/zdos.src @@ -0,0 +1,635 @@ + PAGE + SBTTL "--- Z-DOS: CBM64 ---" + + ; --------------------- + ; GET Z-BLOCK FROM DISK + ; --------------------- + + ; ENTRY: Z-BLOCK # IN [BLOCK] + ; TARGET PAGE IN [DBUFF+HI] + +GETDSK: CLD + LDA #8 + STA DRIVE ; GAME ALWAYS PLAYS FROM DRIVE #8 + + LDA DBLOCK+LO ; Z-BLOCK ID IS DIVIDEND + STA DVD+LO + LDA DBLOCK+HI + AND #%00000001 ; MASK ALL BUT BIT 0 + STA DVD+HI ; FOR 128K VIRTUAL LIMIT + + LDA #0 + STA DSOR+HI ; CLEAR MSB DIVISOR + STA DTEMP+LO ; AND TEMP VARIABLE + STA DTEMP+HI + + LDX #17 ; USE 17 SECTORS/TRACK + STX DSOR+LO ; LSB OF DIVISOR + DEX ; (= 16) INIT DIVIDE INDEX + CLC + +DVLP: ROL DVD+LO + ROL DVD+HI + ROL DTEMP+LO + ROL DTEMP+HI + + LDA DTEMP+LO + SEC + SBC DSOR+LO + TAY + LDA DTEMP+HI + SBC DSOR+HI + BCC DVLP1 + STY DTEMP+LO + STA DTEMP+HI + +DVLP1: DEX + BNE DVLP + + ROL DVD+LO ; SHIFT LAST CARRY + ROL DVD+HI ; INTO QUOTIENT + + LDA DTEMP+LO ; REMAINDER IN [DTEMP] + STA SECTOR ; IS SECTOR ID (0-16) + + LDA DVD+LO ; QUOTIENT IN [DVD] IS TRACK ID + CLC + ADC #5 ; Z-CODE STARTS ON TRACK 5 + + CMP #17 ; BELOW TRACK 17? + BCC DVLP2 ; YES, WE'RE DONE + CLC ; ELSE SKIP OVER + ADC #1 ; TRACK 17 + CMP #36 ; OUT OF RANGE? + BCS TRKERR ; IF > 35, TRACK ERROR + CMP #18 ; IS THIS TRACK 18? + BNE DVLP2 ; NO, EXIT + INC SECTOR ; ELSE SKIP OVER + INC SECTOR ; 1ST 2 SECTORS +DVLP2: STA TRACK + +; LDA DBLOCK+LO ; GET LSB OF BLOCK ID +; AND #%00001111 ; MASK TO GET +; STA SECTOR ; SECTOR # (0-15) + +; LDA DBLOCK+HI ; GET MSB OF BLOCK ID +; AND #%00001111 ; MASK OUT GARBAGE IN BITS 7-4 +; ASL A ; SHIFT THE LOW NIBBLE +; ASL A ; INTO THE HIGH NIBBLE +; ASL A +; ASL A +; STA TRACK ; AND SAVE IT HERE FOR A MOMENT + +; LDA DBLOCK+LO ; GET LSB OF BLOCK ID AGAIN +; AND #%11110000 ; MASK OUT SECTOR # +; LSR A ; SHIFT THE HIGH NIBBLE +; LSR A ; INTO THE LOW NIBBLE +; LSR A +; LSR A +; ORA TRACK ; SUPERIMPOSE NEW HIGH NIBBLE + +; CLC +; ADC #5 ; Z-CODE STARTS ON TRACK 5 + +; CMP #17 ; BELOW TRACK 17? +; BCC TKOK ; USE AS-IS IF SO +; CLC ; ELSE SKIP OVER +; ADC #1 ; TRACK 17 +; CMP #36 ; ANYTHING HIGHER THAN TRACK 35 +; BCS TRKERR ; IS AN ERROR +; CMP #18 ; IS THIS TRACK 18? +; BNE TKOK ; NO, WE'RE DONE +; INC SECTOR ; ELSE ADD 2 TO +; INC SECTOR ; [SECTOR] TO AVOID DIRECTORY +;TKOK: STA TRACK + + ; ENTRY FOR "RESTORE" ([TRACK], [SECTOR] & [DRIVE] PRE-ASSIGNED) + +GETRES: CLC ; CARRY CLEAR = "READ BLOCK" + JSR DISK ; GO DO IT! + BCS DSXERR ; ERROR IF CARRY SET + + LDY #0 ; MOVE CONTENTS OF [IOBUFF] +GDKL: LDA IOBUFF,Y ; TO THE + STA (DBUFF),Y ; TARGET PAGE IN [DBUFF] + INY + BNE GDKL + + INC DBLOCK+LO ; POINT TO NEXT + BNE GDEX ; Z-BLOCK + INC DBLOCK+HI + +GDEX: JMP NXTSEC ; POINT TO NEXT SECTOR & PAGE + + ; -------------------- + ; PUT [DBLOCK] TO DISK + ; -------------------- + + ; ENTRY: [TRACK], [SECTOR] & [DRIVE] ASSIGNED + ; PAGE TO WRITE IN [DBUFF] + +PUTDSK: LDY #0 ; MOVE PAGE AT [DBUFF] +PTKL: LDA (DBUFF),Y ; INTO + STA IOBUFF,Y ; [IOBUFF] FOR I/O + INY + BNE PTKL + + SEC ; CARRY SET = "WRITE BLOCK" + JSR DISK + BCS WRTERR ; CARRY SET IF ERROR + +NXTSEC: INC SECTOR ; POINT TO NEXT SECTOR + LDA SECTOR + AND #%00001111 ; OVEFLOWED? + BNE SECTOK ; CONTINUE IF NOT + INC TRACK ; ELSE UPDATE TRACK # +SECTOK: STA SECTOR ; AND SECTOR # + + INC DBUFF+HI ; POINT TO NEXT RAM PAGE +WRTERR: RTS + + ; *** ERROR #12: DISK ADDRESS OUT OF RANGE *** + +TRKERR: LDA #12 + BNE QERR + + ; *** ERROR #14: DRIVE ACCESS *** + +DSXERR: LDA #14 + +QERR: JMP ZERROR + + ; ----------------------------- + ; SET UP SAVE & RESTORE SCREENS + ; ----------------------------- + +SAVRES: JSR ZCRLF ; CLEAR THE BUFFER + JSR CLS + + LDX #0 + STX SCRIPT ; DISABLE SCRIPTING + LDY #0 + CLC + JMP PLOT ; HOME CURSOR & RETURN + + ; ----------------- + ; DISPLAY A DEFAULT + ; ----------------- + + ; ENTRY: DEFAULT (0-8) IN [A] + +DEFAL: DB " (Default = " +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 + JSR DLINE ; PRINT THE STRING + + ; FALL THROUGH ... + + ; -------------------------------- + ; ACTIVATE CURSOR, CLEAR KEY QUEUE + ; -------------------------------- + +CURSON: LDX #0 + STX NDX ; CLEAR KEY QUEUE + INX + STX SPENA ; ENABLE CURSOR + RTS + + ; ----------------------------- + ; GET SAVE & RESTORE PARAMETERS + ; ----------------------------- + +POSIT: DB EOL + DB "Position 1-5" +POSITL EQU $-POSIT + +WDRIV: DB EOL + DB "Drive 8 or 9" +WDRIVL EQU $-WDRIV + +MIND: DB EOL + DB EOL + DB "Position " +MPOS: DB "*, Drive " +MDRI: DB "*." + DB EOL + DB "Are you sure? (Y/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 POSITION + +CHANGE: 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 "6" + 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 LETTER ; AND DISPLAY IT + + ; GET DRIVE ID + + LDX #LOW WDRIV + LDA #HIGH WDRIV + LDY #WDRIVL + JSR DLINE ; "DRIVE 8 OR 9" + + LDA GDRIVE ; SHOW DEFAULT + CLC ; CONVERT 0 OR 1 + ADC #7 ; TO 7 OR 8 + JSR DODEF ; SO DEFAULT WILL BE CORRECT + +GETDRV: JSR GETKEY ; GET A KEYPRESS + CMP #EOL ; IF [RETURN], + BEQ DRVSET ; USE DEFAULT + SEC + SBC #'8' ; 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 #'8' ; CONVERT TO ASCII 8 OR 9 + STA SAVDRI ; STORE IN DRIVE STRING + STA MDRI ; AND IN TEMP STRING + JSR LETTER ; AND SHOW NEW SETTING + + LDX #LOW MIND ; SHOW TEMPORARY SETTINGS + LDA #HIGH MIND + LDY #MINDL + JSR DLINE + + JSR CURSON + +GETYES: JSR GETKEY + CMP #'Y' ; IF REPLY IS "Y" + BEQ ALLSET ; ACCEPT RESPONSES + CMP #'y' + BEQ ALLSET + + CMP #'N' ; IF REPLY IS N, + BEQ RETRY ; DO A RETRY + CMP #'n' + BEQ RETRY + + JSR BOOP ; INSIST ON Y/RETURN + JMP GETYES ; OR N + +RETRY: LDX #LOW NO ; ELSE PRINT "NO" + LDA #HIGH NO + LDY #NOL + JSR DLINE + JMP PARAMS ; AND TRY AGAIN + +ALLSET: LDA #0 + STA SPENA ; CURSOR OFF + + LDX #LOW YES ; PRINT "YES" + LDA #HIGH YES + LDY #YESL + JSR DLINE + + LDA TDRIVE ; MAKE THE TEMPORARY DRIVE + STA GDRIVE ; THE DEFAULT DRIVE + LDA TPOSIT ; AND THE TEMP POSITION + STA GPOSIT ; THE DEFAULT POSITION + + ; CALC TRACK & SECTOR OF GAME POSITION + + ASL A ; * 2 + STA TRACK ; SAVE HERE FOR A MOMENT + ASL A ; * 4 + CLC + ADC TRACK ; * 6 (6 TRACKS PER POSITION) + STA TRACK + INC TRACK ; 1ST TRACK IS 1! + LDA #0 + STA SECTOR ; ALWAYS START ON SECTOR #0 + + LDA FAST ; FAST-READ ENABLED? + BEQ PRY1 ; NO, CONTINUE + JSR FOFF ; ELSE DISENGAGE FAST-READ + +PRY1: LDA GDRIVE ; TRY TO OPEN SPECIFIED DRIVE + CLC + ADC #8 + JSR DOPEN ; THE DEFAULT DRIVE + BCS PARERR ; CARRY SET IF ERROR + +SREADY: LDX #LOW INSM + LDA #HIGH INSM + LDY #INSML + JSR DLINE ; "INSERT SAVE DISK IN DRIVE X." + JSR RETURN ; "PRESS [RETURN] TO CONTINUE." + CLC ; FOR SUCCESS +PARERR: RTS + + ; --------------------- + ; "PRESS RETURN" PROMPT + ; --------------------- + +RETURN: LDX #LOW RTN + LDA #HIGH RTN + LDY #RTNL + JSR DLINE ; SHOW PROMPT + + ; ENTRY FOR QUIT/RESTART + +GETRET: JSR CURSON ; ENABLE CURSOR + +GTRT: JSR GETKEY ; WAIT FOR [RETURN] + CMP #EOL + BEQ RETEX + JSR BOOP ; ACCEPT NO + JMP GTRT ; SUBSTITUTES! + +RETEX: LDA #0 + STA SPENA ; KILL CURSOR + RTS + +RTN: DB EOL + DB "Press [RETURN] to continue." + DB EOL + DB ">" +RTNL EQU $-RTN + + ; -------------------- + ; PROMPT FOR GAME DISK + ; -------------------- + +GAME: DB EOL + DB "Insert STORY disk into Drive 8." +GAMEL EQU $-GAME + +TOBOOT: LDA #8 + JSR DOPEN ; CLOSE OLD, OPEN BOOT DRIVE + + LDX #LOW GAME + LDA #HIGH GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK IN DRIVE #8." + + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + + LDA FAST ; FAST-READ ENABLED? + BEQ TBT0 ; NO, SCRAM + JSR FINIT ; ELSE RE-INIT FAST CODE + +TBT0: LDA #$FF ; RE-ENABLE + STA SCRIPT ; SCRIPTING + JMP CLS ; CLEAR SCREEN & RETURN + + ; ------------------------- + ; SET UP PHONEY STATUS LINE + ; ------------------------- + + ; ENTRY: TEXT SET UP FOR "DLINE" + +SROOM: JSR DLINE + + LDX #39 ; INVERT & BLACKEN TOP LINE +SRLP: LDA SCREEN,X + ORA #%10000000 + STA SCREEN,X + LDA #0 + STA COLRAM,X + DEX + BPL SRLP + RTS + + ; --------- + ; SAVE GAME + ; --------- + +SAV: DB "Save Position" + DB EOL +SAVL EQU $-SAV + +SVING: 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 + BCC DOSAVE ; ERROR IF CARRY SET + +BADSAV: JSR TOBOOT ; GET BOOT DISK + JMP PREDF ; PREDICATE FAILS + +DOSAVE: 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 + BCS BADSAV ; CATCH WRITE ERROR HERE + + ; WRITE CONTENTS OF Z-STACK TO DISK + + 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 TOBOOT ; PROMPT FOR GAME DISK + JMP PREDS ; ELSE PREDICATE SUCCEEDS + + ; ------------ + ; RESTORE GAME + ; ------------ + +RES: DB "Restore Position" + DB EOL +RESL EQU $-RES + +RSING: 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 + BCS BADRES ; ERROR IF CARRY SET + + 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 GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + + 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 INCORRECT SAVE DISK + +WRONG: LDX #31 ; RESTORE ALL SAVED LOCALS +WR0: LDA $0100,X + STA LOCALS,X + DEX + BPL WR0 + +BADRES: JSR TOBOOT ; PROMPT FOR GAME DISK + 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 GETRES ; GET 1ST BLOCK OF Z-STACK + JSR GETRES ; AND 2ND BLOCK + + LDA ZCODE + STA DBUFF+HI + JSR GETRES ; GET 1ST BLOCK OF PRELOAD + + 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 GETRES ; FETCH THE REMAINDER + 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 #FALSE + STA ZPCFLG ; INVALIDATE [ZPC] + + JSR TOBOOT ; PROMPT FOR GAME DISK + JMP PREDS ; PREDICATE SUCCEEDS + + END + diff --git a/64/zip/zip.src b/64/zip/zip.src new file mode 100644 index 0000000..f33f7d7 --- /dev/null +++ b/64/zip/zip.src @@ -0,0 +1,80 @@ + TITLE "ZIP/6502-C INFOCOM, INC. --- EQUATES" + + ; -------------------------- + ; ZIP/6502 2.0 VERSION F + ; Z-CODE INTERPRETER PROGRAM + ; FOR COMMODORE 64 + ; -------------------------- + + ; INFOCOM, INC. + ; 55 WHEELER STREET + ; CAMBRIDGE, MA 02136 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + +MSTART EQU $0800 ; START OF FREE PROGRAM RAM +ZEROPG EQU $03 ; START OF FREE Z-PAGE RAM +ZPGTOP EQU $8F ; END OF FREE Z-PAGE RAM + +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 + ; 15 -- Z-STACK DESTROYED + + INCLUD SHAKE.ASM + INCLUD EQ.ASM + + TITLE "ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT INIT" + INCLUD HARDEQ.ASM + INCLUD COLD.ASM + + TITLE "ZIP/6502-C INFOCOM, INC. --- INIT & MAINLINE" + INCLUD WARM.ASM + INCLUD MAIN.ASM + INCLUD SUBS.ASM + INCLUD DISPATCH.ASM + + TITLE "ZIP/6502-C INFOCOM, INC. --- OPCODE EXECUTORS" + INCLUD OPS0.ASM + INCLUD OPS1.ASM + INCLUD OPS2.ASM + INCLUD OPSX.ASM + INCLUD READ.ASM + + TITLE "ZIP/6502-C INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT" + INCLUD PAGING.ASM + INCLUD ZSTRING.ASM + INCLUD OBJECTS.ASM + + TITLE "ZIP/6502-C INFOCOM, INC. --- MACHINE DEPENDENT I/O" + INCLUD IO.ASM + INCLUD MACHINE.ASM + INCLUD ZDOS.ASM + INCLUD DISK.ASM + INCLUD FAST.ASM + + IF DEBUG + INCLUD BUGGER.ASM + ENDIF + + TITLE "ZIP/6502-C INFOCOM, INC." + END + diff --git a/64/zip/zstring.src b/64/zip/zstring.src new file mode 100644 index 0000000..6045eb9 --- /dev/null +++ b/64/zip/zstring.src @@ -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 + diff --git a/acorn/--read.me b/acorn/--read.me new file mode 100644 index 0000000..927b049 --- /dev/null +++ b/acorn/--read.me @@ -0,0 +1,13 @@ +******* Directory Update and Source File Archive Record ****** + + Date of Last Change Version Letter Who Made the Change + ___________________ _____________ ____________________ + +1) 1.15.85 A Le +2) +3) +4) +5) +6) +7) +8) diff --git a/acorn/cold.asm b/acorn/cold.asm new file mode 100644 index 0000000..39cd0c7 --- /dev/null +++ b/acorn/cold.asm @@ -0,0 +1,52 @@ + PAGE + SBTTL "--- MACHINE COLDSTART: ACORN ---" + + ORG ZIP + + ;COLDSTART + +COLD: LDA #MODE ;SET SCREEN TO MODE 7 + JSR VDU + LDA #7 + JSR VDU + + LDA #229 ;SET ESCAPE KEY TO ASCII CODE ($1B) + LDX #1 + JSR OSBYTE + + LDA #4 ;DISABLE CURSOR EDIT KEYS + LDX #1 + JSR OSBYTE + + JMP WARM1 + + + ;*************** + ;WARMSTART ENTRY + ;*************** + +SLOAD: DB "The story is loading ..." +; DB EOL +SLOADL EQU $-SLOAD + +WARM1: CLD ;INSURE BINARY + LDX #$FF ;RESET MACHINE STACK + TXS + JSR CLS ;CLEAR SCREEN + + LDA #MVTXC ;ALIGN "STORY LOADING" + JSR VDU + LDA #6 ;COL 6 + JSR VDU + LDA #11 ;LINE 11 + JSR VDU + + LDX #LOW SLOAD + LDA #HIGH SLOAD + LDY #SLOADL + JSR DLINE ;"THE STORY IS LOADING ..." + + ;FALL THROUGH TO ZIP WARMSTART AT WARM2 + + END + \ No newline at end of file diff --git a/acorn/disk.asm b/acorn/disk.asm new file mode 100644 index 0000000..0aacaf3 --- /dev/null +++ b/acorn/disk.asm @@ -0,0 +1,53 @@ + PAGE + SBTTL "DISK ACCESS: ACORN" + + ;**************************** + ;READ/WRITE A BLOCK TO IOBUFF + ;**************************** + + ;ENTRY: TRACK SET TO TRACK # (0-79) + ; SECTOR SET TO SECTOR # (0-7) + ; DRIVE SET TO 0 OR 1 + ; CARRY CLEAR TO READ, SET TO WRITE + + ;NOTE: PARAMS (NUMBER OF PARAMETERS) PERMANENTLY 3 + ; L (SECTOR LENGTH) PERMANENTLY $21 (ACORN CODE = 256 + 1) + +DISK: BCS DWRITE + LDA #RDCMD ;SET INSTRUCTION BYTE TO READ A BLOCK + STA COMMD + JMP TODISK ;ALWAYS BRANCH +DWRITE: LDA #WTCMD ;ELSE SET TO WRITE A BLOCK + STA COMMD + +TODISK: LDA #0 ;MAKE SURE RESULT BYTE IS CLEAR + STA RWRSLT + LDA #3 ;SET PARAMETER COUNT TO 3 + STA PARAM + LDA #$21 ;SET SECTOR LENGTH TO 256 + STA L + + LDA #0 + STA MEMADD+2 ;SET MEMORY ADDR TO RECEIVE BLOCK (IOBUFF) + STA MEMADD+3 + LDY #HIGH IOBUFF + LDX #LOW IOBUFF + STY MEMADD+1 ;4 BYTES = LOW HIGHER HIGHER HIGHEST + STX MEMADD ;USE ONLY 2 BYTES SO 1ST 2 - LOWEST. + + ;READ/WRITE A SECTOR + + LDY #HIGH SECBLK ;GET INSTRUCTION BLOCK + LDX #LOW SECBLK + LDA #$7F ;TELL OSWORD TO R/W A SECTOR + JSR OSWORD + + LDA RWRSLT ;OK? + CMP #0 + BNE BADWRT ;NO, FAILED + CLC + RTS ;RET OK +BADWRT: SEC + RTS ;RET CARRY SET = NO GOOD + + END diff --git a/acorn/dispatch.asm b/acorn/dispatch.asm new file mode 100644 index 0000000..1cf14cc --- /dev/null +++ b/acorn/dispatch.asm @@ -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 + diff --git a/acorn/eq.asm b/acorn/eq.asm new file mode 100644 index 0000000..990ae4a --- /dev/null +++ b/acorn/eq.asm @@ -0,0 +1,162 @@ + PAGE + SBTTL "--- MEMORY ORGANIZATION ---" + +TRUE EQU $FF +FALSE EQU 0 +LO EQU 0 +HI EQU 1 + +IOBUFF EQU $500 ; 256-BYTE DISK BUFFER +ZSTAKL EQU IOBUFF+$100 ; Z-STACK LSBS +ZSTAKH EQU IOBUFF+$200 ; Z-STACK MSBS +PTABL EQU IOBUFF+$300 ; PAGING TABLE LSBS +PTABH EQU IOBUFF+$400 ; PAGING TABLE MSBS +LOCALS EQU IOBUFF+$500 ; LOCAL VARIABLE STORAGE (32 BYTES) +BUFSAV EQU IOBUFF+$520 ; I/O AUX BUFFER (80 BYTES) + +ZIP EQU MSTART ; START OF EXECUTABLE CODE +ZBEGIN EQU ZIP+$1800 ; START OF Z-CODE (ASSUME 6K ZIP) + + ; --------------------- + ; 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) PAGING INDEX +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 + +GLOBAL EQU LRU+8 ; (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 +OLDX EQU TIMEFL+4 ; (BYTE) OLD CURSOR X +OLDY EQU TIMEFL+5 ; (BYTE) OLD CURSOR Y +LINCNT EQU TIMEFL+6 ; (BYTE) LINE COUNTER +;LMAX EQU TIMEFL+7 ; (BYTE) MAX # LINES/SCREEN + +IOCHAR EQU TIMEFL+7 ; (BYTE) CHARACTER BUFFER +;SLINE EQU IOCHAR+1 ; (BYTE) BORDERLINE FOR SPLIT +;SPSTAT EQU IOCHAR+2 ; (BYTE) SPLIT SCREEN STATUS FLAG +LFROM EQU IOCHAR+1 ; (WORD) "FROM" LINE ADDRESS +LTO EQU IOCHAR+3 ; (WORD) "TO" LINE ADDRESS +PSTAT EQU IOCHAR+5 ; (BYTE) PRINTER STATUS FLAG +;STRING EQU IOCHAR+3 ; (WORD) STRING ADDRESS +;STRLEN EQU IOCHAR+5 ; (BYTE) STRING LENGTH +PRLEN EQU IOCHAR+6 ; (BYTE) SCRIPT LINE LENGTH +;LENDEX EQU IOCHAR+7 ; (BYTE) LINE PRINTING INDEX + +DBLOCK EQU IOCHAR+7 ; (WORD) Z-BLOCK TO READ +DBUFF EQU DBLOCK+2 ; (WORD) RAM PAGE TO ACCESS (LSB = 0) +GPOSIT EQU DBLOCK+4 ; (BYTE) DEFAULT SAVE POSITION +GDRIVE EQU DBLOCK+5 ; (BYTE) DEFAULT SAVE DRIVE +TPOSIT EQU DBLOCK+6 ; (BYTE) TEMP SAVE POSITION +TDRIVE EQU DBLOCK+7 ; (BYTE) TEMP SAVE DRIVE +CFLAG EQU DBLOCK+8 ; (BYTE) CURSOR ON/OFF FLAG +;BLINK EQU DBLOCK+8 ; (WORD) CURSOR BLINK TIMER + +SECBLK EQU DBLOCK+8 ; (LBL) DISK R/W INSTRUCTION BLOCK +DRIVE EQU SECBLK ; (BYTE) CURRENT DRIVE +MEMADD EQU SECBLK+1 ; (DBLWORD) MEMORY ADDRESS TO R/W TO/FROM +PARAM EQU SECBLK+5 ; (BYTE) # OF PARAMETERS, ALWAYS 3 +COMMD EQU SECBLK+6 ; (BYTE) READ ($53) WRITE ($4B) +TRACK EQU SECBLK+7 ; (BYTE) TARGET TRACK +SECTOR EQU SECBLK+8 ; (BYTE) TARGET SECTOR +L EQU SECBLK+9 ; (BYTE) SECTOR LENGTH, ALWAYS $21 (= 256) +RWRSLT EQU SECBLK+10 ; (BYTE) R/W FAILED/SUCCEEDED + +HOLDX EQU SECBLK+11 ; (BYTE) HOLD FOR SCROLL +NDEX EQU HOLDX+1 ; (BYTE) HOLD FOR SCROLL + +RAND1 EQU HOLDX+2 ; (BYTE) RANDOM BYTE #1 +RAND2 EQU RAND1+1 ; (BYTE) RANDOM BYTE #2 +RNDFLG EQU RAND1+2 ; (BYTE) FLAG FOR 1ST CHAR ENTERED. + + END + diff --git a/acorn/hardeq.asm b/acorn/hardeq.asm new file mode 100644 index 0000000..bfd4ac7 --- /dev/null +++ b/acorn/hardeq.asm @@ -0,0 +1,62 @@ + PAGE + SBTTL "--- HARDWARE EQUATES: ACORN ---" + + ;VDU + +;ENABLE EQU 2 ;ENABLE PRINTER +;DISABL EQU 3 ;DISABLE PRINTER +BELL EQU 7 ;MAKE SHORT SOUND +;FRWRD EQU 9 ;FORWARDSPACE CURSOR ONE CHAR +CLSCR EQU 12 ;CLEAR TEXT AREA +MODE EQU 22 ;SELECT SCREEN MODE +CURSOR EQU 23 ;TURN CURSOR ON/OFF +HOME EQU 30 ;HOME TEXT CURSOR +MVTXC EQU 31 ;MOVE TEXT CURSOR TO X,Y +BACKSP EQU 127 ;($7F) BACKSPACE & DELETE +BLUE EQU 134 ;SET CHARS TO BLUE (USED FOR STATUS LINE) + + ;OSBYTE CALLS + +OUTSTR EQU 3 ;SET OUTPUT STREAM +TYPE EQU 5 ;SELECT PRINTER TYPE + ;(SEND TO PARALLEL OR RS423 SERIAL OUTPUT) +IGNORE EQU 6 ;SET PRINTER IGNORE CHAR +BAUD EQU 8 ;SET RS423 TRANSMIT BAUD RATE +RDCPOS EQU 134 ;READ TEXT CURSOR POSITION +RDCHAR EQU 135 ;READ CHAR @ CURSOR POSITION +TV EQU 144 ;ALTER TV DISPLAY INTERLACE +ESCASC EQU 229 ;SET ESC TO RET ASCII CODE INSTEAD OF DOING ITS THING + + + ;CONSTANTS + +XSIZE EQU 39 ;X-SIZE (COLUMNS)OF SCREEN +YSIZE EQU 25 ;Y-SIZE (LINES) OF SCREEN + +EOL EQU $0D ;END OF LINE (RET) CHAR +SPACE EQU $20 ;SPACE CHAR + +OFF EQU 1 ;TV INTERLACE +RDCMD EQU $53 ;READ SECTOR +WTCMD EQU $4B ;WRITE SECTOR + +LMAX EQU 24 ;MAX LINES ON SCREEN LESS STATUS LINE + + + ;OS CALLS + +OSRDCH EQU $FFE0 ;READ A CHAR FROM KEYBOARD (INPUT STREAM) +OSWRCH EQU $FFEE ;WRITE A CHAR TO SCREEN (INPUT STREAM) +OSWORD EQU $FFF1 ;MISC. - USED TO WRITE TO DISK +OSBYTE EQU $FFF4 ;MISC. INCLUDING VDU + +VDU EQU OSWRCH ;VDU SENDS COMMANDS TO SCREEN + + +LBUFF EQU $0C00 ;89-BYTE LINE BUFFER +SBUFF EQU $0C77 ;40-BYTE SCROLL BUFFER + ;(HOLDS 1 SCREEN LINE FOR SCROLLING TRANSFER) + +SCREEN EQU $7C00 ;SCREEN RAM + + END diff --git a/acorn/io.asm b/acorn/io.asm new file mode 100644 index 0000000..ab0f637 --- /dev/null +++ b/acorn/io.asm @@ -0,0 +1,444 @@ + PAGE + SBTTL 'GAME I/O' + + +;INTERNAL ERROR + + ;ENTRY: ERROR CODE IN A + +ERRM: DB "INTERNAL ERROR " +ENUMB: DB "00." +ERRML EQU $-ERRM + +ZERROR: LDY #1 ;CONVERT ERROR BYTE IN A +ECON: JSR DIV10 ;TO ASCII DECIMAL IN ENUMB + ORA #'0' ;DIV10 RETS REMAINDER IN A (LSD) + STA ENUMB,Y + TXA ;AND QUOTIENT IN X (WILL BE MSD) + DEY + BPL ECON ;DO BOTH DIGITS + + JSR ZCRLF ;CLEAR BUFFER + LDA #0 + STA SCRIPT ;DISABLE SCRIPTING + + LDX #LOW ERRM ;PRINT MSG + LDA #HIGH ERRM + LDY #ERRML + JSR DLINE + + ;FALL THROUGH ... + +;QUIT/RESTART + +ZSTART: ;FLUSH BUFFER, DEMAND TO RESTART, GO TO WARM START + + JSR ZCRLF ;FLUSH BUFFER + LDX #LOW TORES + LDA #HIGH TORES + LDY #TORESL + JSR DLINE ;"PRESS TO RESTART" + + JSR GETRET ;WAIT FOR + JMP WARM1 ;AND DO WARMSTART + + +TORES: DB "End of story." + DB EOL + DB "Press to restart." + DB EOL +TORESL EQU $-TORES + +ZQUIT EQU ZSTART ;0-OP + + + +;PRINT VERSION # + +VERS: DB "ACORN Version A" + DB EOL +VERSL EQU $-VERS + +VERNUM: JSR ZCRLF ;CLEAR BUFFER + LDX #LOW VERS + LDA #HIGH VERS + LDY #VERSL + JMP DLINE ;DISPL VERSION # (RET TO CALLING FROM DLINE) + + + ;************************ + ;RETURN TOP RAM PAGE IN A + ;************************ + +MEMTOP: LDA #$7B ;IT'S A GIVEN + RTS + + + ;**************************** + ;RETURN RANDOM BYTES IN A & X + ;**************************** + +RANDOM: LDA #3 ; READ INTERVAL TIMER + LDX #LOW CLOCK + LDY #HIGH CLOCK + JSR OSWORD + LDA CLOCK + ADC RAND1 + TAX + LDA CLOCK+1 + SBC RAND2 + STA RAND1 + STX RAND2 + CLC + RTS + + ; CLOCK = LSB, CLOCK+4 = MSB + +CLOCK: DB 0,0,0,0,0 + + ;******************* + ;Z-PRINT A CHARACTER MOVE A (1) CHAR TO LBUFF, IF EOL REACHED + ;******************* (CHAR OR ACTUAL), DISPLAY/PRINT LINE + + ;ENTRY: ASCII CHAR IN A + +COUT: CMP #EOL ;IF EOL + BNE COUT1 + JMP ZCRLF +COUT1: CMP #SPACE ;IGNORE ALL OTHER CONTROLS + BCC CEX ;(OUT) + +COUT2: LDX LENGTH ;ELSE GET LINE POINTER + STA LBUFF,X ;ADD CHAR TO BUFFER + CPX #XSIZE ;END OF LINE? + BCC COUT3 + JMP FLUSH +COUT3: INC LENGTH ;ELSE UPDATE POINTER +CEX: RTS + + ;******************* + ;FLUSH OUTPUT BUFFER - PRINT UP THRU LAST FULL WORD (MARKED BY BLANK) + ;******************* IF NO BLANK PRINT ENTIRE BUFFR + ; MOVE ANY REMAINING CHARS TO TOP OF BUFFER FOR + ; NEXT LINE + + ;ENTRY: LENGTH OF BUFFER IN X + +FLUSH: LDA #SPACE + +FL0: CMP LBUFF,X ;FIND LAST SPACE CHAR + BEQ FL1 ;IN THE LINE + DEX + BNE FL0 + LDX #XSIZE ;IF NONE FOUND, FLUSH ENTIRE LINE + +FL1: STX OLDLEN ;SAVE OLD LINE END POS HERE + STX LENGTH ;MAKE IT NEW LINE LENGTH + JSR ZCRLF ;PRINT LINE UP TO LAST SPACE + + ;START NEW LINE WITH REMAINDER OF OLD + + LDX OLDLEN ;GET OLD LINE POS + LDY #0 ;START NEW LINE AT BEGINNING +FL2: INX + CPX #XSIZE ;CONTINUE IF + BCC FL3 ;INSIDE OR + BEQ FL3 ;AT END OF LINE (ie NOT ENTIRE LINE) + STY LENGTH ;ELSE SET NEW LINE LENGTH TO 0 + RTS + +FL3: LDA LBUFF,X ;GET CHAR FROM OLD LINE + STA LBUFF,Y ;MOVE TO START OF NEW LINE + INY ;UPDATE LENGTH OF NEW LINE + BNE FL2 ;MOVE ALL CHARS + + + ;************** + ;CARRIAGE RETURN + ;************** + +ZCRLF: INC LINCNT ;NEW LINE GOING OUT + LDA LINCNT ;IS IT TIME TO + CMP #LMAX ;PRINT "MORE" YET? + BCC CR1 ;NO, CONTINUE + + ;SCREEN FULL; PRINT "MORE" + + JSR ZUSL ;UPDATE STATUS LINE + LDX #LOW MORE + LDA #HIGH MORE + LDY #MOREL + JSR DLINE ;DISPLAY "MORE" + + JSR OSRDCH ;WAIT FOR ANY CHAR + + ;ERASE "MORE" + + LDY #MOREL ;GET # CHARS DISPLAYED +ZCR0: LDA #BACKSP + JSR OSWRCH ;BACK UP ERASING AS GO + DEY + BNE ZCR0 ;COVER ALL LETTERS + + LDA #1 + STA LINCNT ;RESET FOR NEW SCREEN FULL + + ;AND GO DO MORE + +CR1: LDX LENGTH + LDA #EOL ;INSTALL EOL AT + STA LBUFF,X ;END OF CURRENT LINE + INC LENGTH ;UPDATE LINE LENGTH + +LINOUT: LDY LENGTH ;IF BUFFER EMPTY + BEQ LINEX ;DON'T PRINT ANYTHING + + STY PRLEN ;SAVE LENGTH FOR "PPRINT" + LDX #0 ;SEND CONTENTS OF LBUFF TO SCREEN +LOUT: LDA LBUFF,X + JSR CHAR + INX + DEY + BNE LOUT ;DO ALL CHARS + + JSR PPRINT ;PRINT LBUFF IF ENABLED + +LINEX: LDA #0 ;RESET LINE LENGTH TO TOP + STA LENGTH + RTS ;AND RETURN + +MORE: DB "-MORE-" +MOREL EQU $-MORE + + + ;********************** + ;UPDATE THE STATUS LINE + ;********************** + +ZUSL: LDA LENGTH ;SAVE ALL STRING-PRINTING VARIABLES + PHA + LDA MPCH + PHA + LDA MPCM + PHA + LDA MPCL + PHA + LDA TSET + PHA + LDA PSET + PHA + LDA ZWORD+HI + PHA + LDA ZWORD+LO + PHA + LDA ZFLAG + PHA + LDA DIGITS + PHA + + LDX #XSIZE +USL0: LDA LBUFF,X ;MOVE CONTENTS OF LBUFF + STA BUFSAV,X ;TO BUFSAV + LDA #SPACE ;CLEAR LBUFF WITH SPACES + STA LBUFF,X + DEX + BPL USL0 + + LDA #0 + STA LENGTH ;RESET LINE LENGTH + STA SCRIPT ;DISABLE SCRIPTING + + LDA #RDCPOS ;GET CURSOR POSITION + JSR OSBYTE + STX OLDX ;SAVE REGULAR POSITION OF CURSOR + STY OLDY + + LDA #HOME ;HOME CURSOR + JSR VDU + LDA #BLUE ;SET STATUS LINE TO BLUE SO STANDS OUT + JSR COUT ;PLACE COLOR CONTROL IN LBUFF SO WHEN PRINTS + ;WILL BE INCLUDED IN LINE COUNT + ;(NO NEED TO RESET, COMMAND AFFECTS 1 LINE ONLY) + ;MOVE ROOM DESCRIPTION TO LBUFF + + LDA #16 ;GLOBAL VAR #16 9ROOM ID) + JSR GETVRG ;GET IT INTO VALUE + LDA VALUE+LO + JSR PRNTDC ;PRINT SHORT ROOM DESC. + + LDA #23 ;MOVE LINE INDEX UP + STA LENGTH ;TO TIME/SCORE POSITION + LDA #SPACE + JSR COUT ; OUTPUT A SPACE FOR SAFETY + + LDA #17 ;GLOBAL VAR #17 (SCORE/HOURS) + JSR GETVRG ;GET IT INTO VALUE + + LDA TIMEFL ;GET MODE FLAG + BNE DOTIME ;USE TIME MODE IF NON-ZERO + + ;PRINT 'SCORE' (DO BY HAND NO REGISTERS PRESERVED THRU COUT) + + LDA #'S' + JSR COUT + LDA #'c' + JSR COUT + LDA #'o' + JSR COUT + LDA #'r' + JSR COUT + LDA #'e' + JSR COUT + LDA #':' + JSR COUT + LDA #SPACE + JSR COUT + + LDA VALUE+LO ;MOVE SCORE VALUE + STA QUOT+LO ;INTO QUOT + LDA VALUE+HI ;FOR PRINTING + STA QUOT+HI + JSR NUMBER ;CONVERT TO DECIMAL, MOVE TO LBUFF ("PRINT") + + LDA #'/' ;PRINT A SLASH + BNE MOVMIN ;BRANCH ALWAYS + + + ;PRINT 'TIME' + +DOTIME: LDA #'T' + JSR COUT + LDA #'i' + JSR COUT + LDA #'m' + JSR COUT + LDA #'e' + JSR COUT + LDA #':' + JSR COUT + LDA #SPACE + JSR COUT + + LDA VALUE+LO ;00 IS REALLY 24 + BNE DTO + LDA #24 +DTO: CMP #13 ;HOURS > 12? + BCC DT1 ;NO, SKIP THIS + SBC #12 ;CONVERT TO 1-12 +DT1: STA QUOT+LO ;MOVE FOR PRINTING + LDA #0 + STA QUOT+HI ;CLEAR MSB + JSR NUMBER + + LDA #':' ;COLON + +MOVMIN: JSR COUT ;PRINT SLASH OR COLON + + LDA #18 ;GLOBAL VAR #18 (MOVES/MINUTES) + JSR GETVRG ;MOVE TO VALUE + LDA VALUE+LO ;MOVE TO QUOT + STA QUOT+LO + LDA VALUE+HI + STA QUOT+HI + + LDA TIMEFL ;WHICH MODE? + BNE DOMINS ;TIME IF NZ + + ;PRINT # OF MOVES + + JSR NUMBER ;CONVERT & MOVE TO LBUFF + JMP STATEX ;ALL DONE + + ;PRINT MINUTES + +DOMINS: LDA VALUE+LO ;CHECK MINUTES + CMP #10 ;IF OVER 10 + BCS DOMO ;CONTINUE + LDA #'0' ;ELSE PRINT A + JSR COUT ;PADDING "0" FIRST + +DOMO: JSR NUMBER ;CONVERT, MOVE TO PRINT + LDA #SPACE + JSR COUT ;SEPARATE THINGS + + LDA #17 ;CHECK 'HOURS' AGAIN + JSR GETVRG + LDA VALUE+LO + CMP #12 ;PAST NOON + BCS DOPM ;YES, "PM" + + LDA #'a' ;ELSE "AM" + BNE DOXM ;BRANCH ALWAYS + +DOPM: LDA #'p' + +DOXM: JSR COUT + LDA #'m' + JSR COUT + + ;STATUS LINE READY + +STATEX: LDA #40 ;PRINT THE ENTIRE STATUS LINE ***LINE LENGTH PROB?**** + STA LENGTH + JSR CR1 + + LDX #XSIZE ;RESTORE OLD LBUFF +USLX: LDA BUFSAV,X + STA LBUFF,X + DEX + BPL USLX ;MOVE ALL CHARS + + PLA ;RESTORE ALL SAVED VARIABLES + STA DIGITS + PLA + STA ZFLAG + PLA + STA ZWORD+LO + PLA + STA ZWORD+HI + PLA + STA PSET + PLA + STA TSET + PLA + STA MPCL + PLA + STA MPCM + PLA + STA MPCH + PLA + STA LENGTH + + ;RESTORE CURSOR + LDA #MVTXC ;MOVE TEXT CURSOR + JSR VDU + LDA OLDX ;TO OLD COORDINATES + JSR VDU + LDA OLDY + JSR VDU + + LDX #$FF + STX SCRIPT ;RE-ENABLE SCRIPTING + INX + STX MPCFLG ;(0) INVALIDATE MPC + RTS + + + ;**************** + ;DIVIDE [A] BY 10 + ;**************** + + ;EXIT: QUOTIENT IN X, REMAINDER IN A + +DIV10: LDX #0 ;START WITH ZERO QUOTIENT + +D10L: CMP #10 ;IF DIVISOR < 10, + BCC D10EX ;WE'RE DONE + SBC #10 ;ELSE SUBTRACT ANOTHER 10 + INX ;UPDATE QUOTIENT + BNE D10L ;BRANCH ALWAYS + +D10EX: RTS + + + END diff --git a/acorn/machine.asm b/acorn/machine.asm new file mode 100644 index 0000000..9465a56 --- /dev/null +++ b/acorn/machine.asm @@ -0,0 +1,300 @@ + PAGE + SBTTL 'MACHINE DEPENDENT I/O' + +GETKEY: TXA ;SAVE X AND Y + PHA + TYA + PHA + +GKEY0: JSR OSRDCH ;GET A CHAR + + ;CHECK TO MAKE SURE KEY IS VALID, ONLY ACCEPT IT IF IT IS + +GKEY3: AND #$7F ;SCREEN OUT SHIFTS + + CMP #EOL ;CHECK FOR GOOD (BAD) CHAR + BEQ OK + CMP #BACKSP + BEQ OK + CMP #SPACE + BCC BADKEY ;IF < SPACE, BAD + CMP #$40 ;@ + BEQ BADKEY + + CMP #$25 ;% + BCC OK ;BELOW RANGE + CMP #$27 ;' + BEQ OK ;GOOD CHAR + CMP #$2C ;+ +1 + BCS MASK0 ;NOT IN THIS GROUP, TRY OTHER + + ORA #$10 ;SET BIT 4, CHANGE %&()*+ TO 5689:; + ;(FROM BAD TO GOOD CHAR AS SAME KEY LOCATION) + JMP OK ;GOOD, DONE NOW + +MASK0: CMP #$3C ;< + BCC OK ;LESS + CMP #$3F ;> +1 + BCS MASK1 ;OK, GO DO LETTERS + + AND #$2F ;CLEAR BIT 4, CHANGE <=> TO ,-. + BNE OK ;BRANCH ALWAYS, DONE + +MASK1: CMP #'z'+1 + BCS BADKEY ;IF > BAD + CMP #'a' + BCS OK ;IF > OK + CMP #'Z'+1 + BCC OK ;IF < OK + +BADKEY: JSR BOOP ;BAD KEY, GIVE WARNING NOISE + JMP GKEY0 ;TRY AGAIN + +OK: STA IOCHAR ;HOLD ON TO IT + + ADC RAND1 + STA RAND2 + LSR A + STA RAND1 + + PLA + TAY + PLA + TAX + LDA IOCHAR ;RETRIEVE IT + RTS + +BOOP: LDA #BELL ;(DOES NOT WORK, STOLE SOUND GENERATION MEMORY) + JSR OSWRCH + RTS + + + ;PUT A CHAR TO SCREEN (PHYSICALLY), HANDLE EOL, SCROLLING IF NECESSARY + +CHAR: STA IOCHAR ;PRESERVE X,Y SAVE A TO USE + TXA + PHA + TYA + PHA + + LDA #RDCPOS ;READ TEXT CURSOR POS. + JSR OSBYTE ;GIVES X,Y + + LDA IOCHAR + CMP #EOL + BEQ OUTEOL ;EOL = SPECIAL HANDLING + + CMP #BACKSP ;IF DEL CHAR DON'T SCROLL + BEQ NOSCRL + + CPY #YSIZE-1 ;ON LAST SCREEN LINE? + BCC NOSCRL ;NO, NO SCROLL NEEDED + CPX #XSIZE ;LAST CHAR ON LINE? + BCC NOSCRL ;NO, NO SCROLL YET + +DOSCRL: LDA #11 ;MOVE CURSOR UP 1 LINE + JSR VDU ;FOR ALIGNMENT AFTER SCROLL + + LDX #1 ;START TRANSFERING FROM LINE 1 +SRL0: CPX #YSIZE + BEQ SRL2 + + LDA LOLINE,X ;GET ADDR OF DEST LINE + STA LTO+LO ;INTO [LTO] + LDA HILINE,X + STA LTO+HI + + INX ;NEXT LINE + 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 ;CLEAR LAST LINE + LDA #SPACE ;OF SCREEN RAM +SRL3: STA SCREEN+960,X + DEX + BPL SRL3 + + ;DROP THRU TO SEND CHAR OUT NOW + +NOSCRL: LDA IOCHAR + JSR OSWRCH ;SEND CHAR TO SCREEN + CMP #EOL ;IF CR + BNE NS1 + LDA #$0A ;SEND LF + JSR OSWRCH +NS1: PLA + TAY + PLA + TAX + LDA IOCHAR + RTS + +OUTEOL: CPY #YSIZE-1 ;LAST LINE ON SCREEN? + BCC NOSCRL ;NO + BCS DOSCRL ;YES, SO SCROLL + +;******* + +INPUT: ;FETCH A LINE OF INPUT FOR READ RTN + + ;ENTRY: ABS ADDR OF READ BUFFR IN ARG1 + ;EXIT: # CHARS READ IN A + + JSR LINOUT ;FLUSH LBUFF + LDY #0 + STY LINCNT ;RESET LINE COUNT + +INLOOP: JSR GETKEY ;GET ASCII INTO A + CMP #EOL ;? + BEQ ENDLIN ;LINE DONE IF SO + CMP #BACKSP ;BACKSPACE? + BEQ BACKUP ;SPECIAL HANDLING + + STA LBUFF,Y ;ELSE ADD CHAR TO INPUT BUFFR + INY ;NEXT POSITION IN LINE + +SHOWIT: JSR CHAR ;DISPLAY CHAR + CPY #77 ;2 SCREEN LINES FULL? + BCC INLOOP ;NO, KEEP GOING + + ;HANDLE LINE OVERFLOW +NOMORE: JSR GETKEY + CMP #EOL ;IF EOL, WRAP UP THE LINE + BEQ ENDLIN + CMP #BACKSP ;BACKSPACE OK TOO + BEQ BACKUP + JSR BOOP ;ELSE COMPLAIN + JMP NOMORE ;AND INSIST + + ;HANDLE BACKSPACE +BACKUP: DEY ;BACKUP THE POINTER + BPL SHOWIT ;SEND BS IF NOT START OF LINE + JSR BOOP ;ELSE SAY BAD + LDY #0 ;RESET POINTER + BEQ INLOOP ;AND TRY AGAIN + + ;END OF LINE +ENDLIN: STA LBUFF,Y ;PLACE IN BUFFER + INY ;UPDATE INDEX + STY LINLEN ;SAVE FOR "READ" + STY PRLEN ;AND "PRINT" + JSR CHAR ;SEND EOL TO SCREEN + + ;MOVE LBUFF TO ARG1 W/LOWER CASE CONVERSION +LEX1: LDA LBUFF-1,Y ;GET A CHAR FROM LBUFF + 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 BUFF AT ARG1 + DEY ;LOOP TILL ALL CHARS MOVED + BPL LEX1 + + JSR PPRINT ;SCRIPT LBUFF IF ENABLED + + LDA LINLEN ;RESTORE # CHARS + RTS ;INTO A + +DLINE: ;DISPLAY A STRING + ;ENTRY: STRING ADDR X=LSB A=MSB + ; STRING LENGTH IN Y + + STX STRNG+LO ;DROP STRING ADDRESS + STA STRNG+HI ;INTO DUMMY BYTES + LDX #0 ;INIT INDEX + +DOUT: DB $BD ;6502 "LDA nnnn,X" OPCODE +STRNG: DW $0000 ;DUMMY OPERAND BYTES + JSR CHAR + INX ;NEXT CHAR + DEY ;DECREMENT CHAR COUNT + BNE DOUT ;LOOP TILL OUT OF CHARS + RTS + + + ;CLEAR SCREEN + +CLS: LDA #HIGH SCREEN + STA I+HI + LDA #0 + STA I+LO + TAY + LDX #$04 +CLS0: STA (I),Y + INY + BNE CLS0 + INC I+HI + DEX + BNE CLS0 + + LDA #MVTXC ;ALIGN CURSOR AT + JSR VDU ;TOP OF SCREEN + LDA #0 ;COL 0 + JSR VDU + LDA #1 ;TOP LINE + JMP VDU + + ;***** + ;PRINT ON PRINTER + ;***** + +PPRINT: LDA SCRIPT ;SCRIPTING INTERNALLY ENABLED? + BEQ PEX ;NO, LEAVE + LDA ZBEGIN+ZSCRIP+1 ;CHECK SCRIPT FLAG + AND #%00000001 ;SCRIPTING ON? + BEQ PEX ;NO, LEAVE + + LDA #OUTSTR ;SET OUTPUT STREAM + LDX #2 ;TO PRINTER + JSR OSBYTE + LDA #IGNORE ;SET TO PRINT + LDX #0 ;LINE FEEDS + JSR OSBYTE + + LDY #0 ;PRINT OUT LINE +POUT: LDA LBUFF,Y + JSR OSWRCH + INY + DEC PRLEN + BNE POUT ;DO WHOLE LINE + + LDA #OUTSTR ;RESET OUTPUT STREAM + LDA #4 ;TO VIDEO + JSR OSBYTE +PEX: RTS ;AND LEAVE + + + ; ************ + ;NO SPLIT SCREEN OPTION IS BEING INCLUDED SO I AM INSERTING + ; ************ RETURNS FOR THE ROUTINES + +ZSPLIT: RTS + +ZSCRN: RTS + + ;******************* + ;LINE ADDRESS TABLES + ;******************* + +LOLINE: DB $00,$28,$50,$78,$A0,$C8,$F0,$18 + DB $40,$68,$90,$B8,$E0,$08,$30,$58 + DB $80,$A8,$D0,$F8,$20,$48,$70,$98 + DB $C0 + +HILINE: DB $7C,$7C,$7C,$7C,$7C,$7C,$7C,$7D + DB $7D,$7D,$7D,$7D,$7D,$7E,$7E,$7E + DB $7E,$7E,$7E,$7E,$7F,$7F,$7F,$7F + DB $7F + + END diff --git a/acorn/main.asm b/acorn/main.asm new file mode 100644 index 0000000..31fc478 --- /dev/null +++ b/acorn/main.asm @@ -0,0 +1,215 @@ + PAGE + SBTTL "--- MAIN LOOP ---" + +MLOOP: LDA #0 + STA NARGS ; RESET # ARGUMENTS + + INC RAND1 + DEC RAND2 + + JSR NEXTPC ; GET NEXT INSTRUCTION INTO [A] + STA OPCODE ; SAVE IT HERE + + IF DEBUG + STA MBYTE + LDA #0 ; BREAKPOINT #0 + JSR DOBUG + LDA MBYTE + 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 + diff --git a/acorn/objects.asm b/acorn/objects.asm new file mode 100644 index 0000000..63a9585 --- /dev/null +++ b/acorn/objects.asm @@ -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 + diff --git a/acorn/ops0.asm b/acorn/ops0.asm new file mode 100644 index 0000000..dc74821 --- /dev/null +++ b/acorn/ops0.asm @@ -0,0 +1,135 @@ + 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 ZIP VERSION NUMBER + + 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 ZBEGIN+ZLENTH ; GET LENGTH OF Z-CODE + STA I+HI ; IN WORDS + LDA ZBEGIN+ZLENTH+1 ; FIRST MSB + STA I+LO ; THEN LSB + + ASL I+LO ; CONVERT Z-CODE LENGTH + ROL I+HI ; TO # BYTES + ROL K+LO ; TOP BIT IN [K+LO] + + LDA #K+HI ; PATCH THE "GETBYT" ROUTINE + STA PATCH ; TO USE [K+HI]=0 INSTEAD OF [ZPURE] + +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 ; MIDDLE BYTE + CMP I+HI + BNE VSUM + + LDA MPCH ; AND HIGH BIT + CMP K+LO + BNE VSUM + + 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 + diff --git a/acorn/ops1.asm b/acorn/ops1.asm new file mode 100644 index 0000000..7cdd795 --- /dev/null +++ b/acorn/ops1.asm @@ -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 + diff --git a/acorn/ops2.asm b/acorn/ops2.asm new file mode 100644 index 0000000..7d3be0a --- /dev/null +++ b/acorn/ops2.asm @@ -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 + diff --git a/acorn/opsx.asm b/acorn/opsx.asm new file mode 100644 index 0000000..35fccc4 --- /dev/null +++ b/acorn/opsx.asm @@ -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 + + \ No newline at end of file diff --git a/acorn/paging.asm b/acorn/paging.asm new file mode 100644 index 0000000..5aed122 --- /dev/null +++ b/acorn/paging.asm @@ -0,0 +1,205 @@ + PAGE + SBTTL "--- PAGING ROUTINES ---" + + ; ------------------------- + ; FETCH NEXT BYTE OF Z-CODE + ; ------------------------- + + ; EXIT: BYTE AT [ZPC] IN [A] & [Y], FLAGS SET + +NEXTPC: LDA ZPCFLG ; HAS PAGE CHANGED? + BEQ NEWZ ; APPARENTLY SO + +NPC: LDY ZPCL + LDA (ZPCPNT),Y ; GRAB A Z-BYTE + + IF DEBUG + STA MBYTE + LDA #1 ; BREAKPOINT #1 + JSR DOBUG + LDA MBYTE + ENDIF + + INC ZPCL + BNE NXTX + + LDY #0 + STY ZPCFLG + + INC ZPCM ; POINT [ZPC] TO NEXT PAGE + BNE NXTX + INC ZPCH + +NXTX: TAY ; SET FLAGS + RTS + + ; -------------- + ; SWITCH Z-PAGES + ; -------------- + +NEWZ: LDA ZPCM ; GET LSB OF TARGET INTO [A] + LDY ZPCH ; AND MSB INTO [Y] + BNE NZ0 ; SWAP IF MSB <> 0 + + CMP ZPURE ; IS PAGE IN PRELOAD? + BCS NZ0 ; NO, SWAP IT IN + + ADC ZCODE ; ELSE CALC ABSOLUTE PAGE + BNE NZ1 ; AND GIVE IT TO [ZPCPNT] + +NZ0: LDX #0 + STX MPCFLG ; INVALIDATE [MPC] + JSR PAGE ; LOCATE PAGE [A/Y] IN SWAPPING SPACE + +NZ1: STA ZPCPNT+HI ; AND UPDATE MSB OF POINTER + LDX #$FF + STX ZPCFLG ; VALIDATE [ZPC] + INX ; (= 0) CLEAR LSB + STX ZPCPNT+LO ; OF [ZPCPNT] + BEQ NPC ; GET THE BYTE + + ; ------------------------------- + ; GET NEXT BYTE OF VIRTUAL MEMORY + ; ------------------------------- + + ; EXIT: BYTE AT [MPC] IN [A] & [Y], FLAGS SET + +GETBYT: LDA MPCFLG ; [MPC] VALID? + BEQ NEWM ; NO, SWITCH PAGES + +GTB: LDY MPCL ; GRAB NEXT BYTE + LDA (MPCPNT),Y + + IF DEBUG + STA MBYTE + LDA #2 ; BREAKPOINT #2 + JSR DOBUG + LDA MBYTE + ENDIF + + INC MPCL ; END OF THIS PAGE? + BNE NXMX ; NO, CONTINUE + + LDY #0 ; ELSE INVALIDATE + STY MPCFLG ; [MPC] + + INC MPCM ; POINT [MPC] TO + BNE NXMX ; NEXT PAGE + INC MPCH + +NXMX: TAY ; SET FLAGS + RTS + + ; -------------- + ; SWITCH M-PAGES + ; -------------- + +NEWM: LDA MPCM ; GET LSB AND + LDY MPCH ; MSB OF TARGET PAGE + BNE NM0 ; SWAP IF MSB <> 0 + +PATCH EQU $+1 ; PATCH POINT FOR "VERIFY" + + CMP ZPURE ; TARGET IN PRELOAD? + BCS NM0 ; NO, SWAP IT IN + + ADC ZCODE ; ELSE MAKE IT ABSOLUTE + BNE NM1 ; AND GIVE TO [MPCPNT] + +NM0: LDX #0 + STX ZPCFLG ; INVALIDATE [ZPC] + JSR PAGE ; GET PAGE OF TARGET BLOCK IN [A/Y] + +NM1: STA MPCPNT+HI ; SET MSB OF POINTER + LDX #$FF + STX MPCFLG ; [MPC] IS NOW VALID + INX ; CLEAR LSB + STX MPCPNT+LO ; OF [MPCPNT] + BEQ GTB + + ; ------------------------------- + ; LOCATE A PAGE OF VIRTUAL MEMORY + ; ------------------------------- + + ; ENTRY: TARGET PAGE IN [A/Y] (LSB/MSB) + ; EXIT: ABSOLUTE PAGE ADDRESS IN [A] + +PAGE: STA TARGET+LO ; SAVE THE + STY TARGET+HI ; TARGET PAGE FOR REFERENCE + + LDX #0 ; INIT INDEX + STX ZPAGE ; KEEP A RUNNING TALLY + +PG1: CMP PTABL,X ; SEARCH FOR LSB IN [A] + BEQ PG3 ; IF FOUND, CHECK MSB + +PG2: INC ZPAGE ; UPDATE TALLY + INX + CPX PMAX ; OUT OF PAGING SPACE? + BCC PG1 ; NO, KEEP LOOKING + BCS SWAP ; ELSE PAGE MUST BE SWAPPED IN + +PG3: TYA ; GET MSB OF TARGET + CMP PTABH,X ; MATCHED? + BEQ PFOUND ; YES, PAGE IS IN [ZPAGE] + LDA TARGET+LO ; ELSE RESTORE LSB OF TARGET + JMP PG2 ; AND RESUME SEARCH + + ; SWAP IN TARGET PAGE IN [TARGET] + +SWAP: LDX LRU ; SPLICE THE + LDA TARGET+LO ; TARGET PAGE + STA PTABL,X ; INTO THE PAGING TABLES + STA DBLOCK+LO ; AND GIVE IT TO ZDOS + + LDA TARGET+HI ; SAME FOR MSB + STA PTABH,X + STA DBLOCK+HI + + TXA + STA ZPAGE ; SAVE FOR "PFOUND" + CLC + ADC PAGE0 ; MAKE IT ABSOLUTE + STA DBUFF+HI ; GIVE PAGE ADDRESS TO ZDOS + + JSR GETDSK ; GET BLOCK INTO SWAPPING SPACE + + INC LRU ; UPDATE PAGE POINTER + LDA LRU + CMP PMAX ; TOP OF PAGING SPACE? + BCC PFOUND ; NO, EXIT + LDA #0 + STA LRU ; ELSE RESET POINTER + +PFOUND: LDA ZPAGE ; GET SWAPPING PAGE INDEX + CLC + ADC PAGE0 ; MAKE IT ABSOLUTE + RTS ; AND RETURN IT IN [A] + + ; ------------------------- + ; 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 + + \ No newline at end of file diff --git a/acorn/read.asm b/acorn/read.asm new file mode 100644 index 0000000..69003ce --- /dev/null +++ b/acorn/read.asm @@ -0,0 +1,304 @@ + 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 + INY ; POINT TO "# WORDS READ" SLOT + CMP (ARG2),Y ; TOO MANY WORDS? + BCS RL1 ; NOT YET + + ; *** ERROR #13: PARSER OVERFLOW *** + + LDA #13 + JMP ZERROR + +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 EOL ; 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 + diff --git a/acorn/subs.asm b/acorn/subs.asm new file mode 100644 index 0000000..b2fec65 --- /dev/null +++ b/acorn/subs.asm @@ -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 + diff --git a/acorn/tftpsrc.rno b/acorn/tftpsrc.rno new file mode 100644 index 0000000..709b747 --- /dev/null +++ b/acorn/tftpsrc.rno @@ -0,0 +1 @@ + ORG $1900 JMP PRGM ;COMMENTS: ; TFTP ; ; BOTH ZIP AND GAME ; ARE PHYSICALLY WRITTEN BY ; SECTORS THEN THE DIRECTORY IS SET ; TO FOOL SYSTEM TO SEE ZIP (!BOOT) ; AS A FILE SO IT WILL AUTO BOOT ; ; THE GAME IS WRITTEN USING ONLY ; 8 SECTORS PER TRACK TO MAKE IT ; EASIER ON THE INT. MATH. TO MAKE ; THE AUTO BOOT WORK !BOOT (ZIP) ; WAS MADE A FULL 10 SECTORS PER ; TRACK SO IT WOULD BE LIKE A FILE CMDCHR EQU $7E CMDDAT EQU 0 CMDACK EQU 2 CMDNAK EQU 5 CMDEOF EQU 4 BLKHDR: DFB 1,0,$0FE,$0FF BKHDSZ EQU *-BLKHDR ;ALL FILE INFO FOR !BOOT ;LOAD,LOAD,EXEC,EXEC ;LENGTH,LENGTH (FILLED BY PRGM) ;HIGH BITS, START SECTOR ;(I'M NOT SURE WHY BUT HIGH BITS ;NEED TO BE CC) FILELN: DFB 00,$11,00,$11 ZPSIZE: DFB 00,00,$CC,02 FLNSZ EQU *-FILELN SECBLK EQU 0 ;BLK FOR SEC R/W DRIVE EQU SECBLK MEMADD EQU SECBLK+1 PARAMS EQU SECBLK+5 COMMD EQU SECBLK+6 TRACK EQU SECBLK+7 SECTOR EQU SECBLK+8 SECLNG EQU SECBLK+9 RESULT EQU SECBLK+10 ;RET HERE CHKSMH EQU RESULT+1 ;CHECK SUM CHKSML EQU RESULT+2 MHOLDH EQU RESULT+3 ;MSG TO PRINT MHOLDL EQU RESULT+4 MLENG EQU RESULT+5 ;MSG LENGTH TRYHLD EQU RESULT+6 ;HOLD LOOP CNT WCHFIL EQU RESULT+7 ;AS 1 SCT = 256 BYTES SPERT EQU RESULT+9 ;SECTORS PER TRACK (DIFFERS) ;*****MESSAGES******* MRATE ASC "BAUD RATE = 4800" DFB $0D,$0A MRATEL EQU *-MRATE MDRV ASC "PLACE GAME DISK IN DRIVE 1" DFB $0D,$0A ASC "HIT ANY KEY TO CONTINUE" MDRVL EQU *-MDRV MGO ASC " OK, STARTED" DFB $0D,$0A MGOL EQU *-MGO MFILE ASC "TRANSFER (Z)IP / (G)AME" DFB $0D,$0A MFILEL EQU *-MFILE MBADWR ASC "BAD WRITE" DFB $0D,$0A MBADWL EQU *-MBADWR MOK ASC "DONE" DFB $0D,$0A MOKL EQU *-MOK F ASC ":1.ZORK" DFB &0D ;*********** BUFFR EQU $0C00 ;*********** READ EQU $53 ;SECTOR READ WRITE EQU $4B ;SECTOR WRITE BOOT EQU 6 ;6TH BYTE IN. FLSIZE EQU $0D ;MIDDLE SIZE BYTE ;SIZE IN BYTES ;*****SET UP FEATURES***** RATE EQU 6 ;BAUD RATE 4800 ;*****SYSTEM EQUATES***** OSFIND EQU $FFCE OSRDCH EQU $FFE0 OSWRCH EQU $FFEE OSWORD EQU $FFF1 OSBYTE EQU $FFF4 ;*********************************** PRGM LDA #229 ;ESCAPE KEY LDX #1 ;TO GIVE JSR OSBYTE ;ASCII CODE ;SET BAUD RATE ;FIRST TELL USER ;INCIDENTALLY, A RANGE OF RATES IS POSSIBLE I CHOSE ;THE MOST APPROPRIATE I BELIEVE ;(USING DEFAULT DATA FORMAT 8 BITS, 2 STOP, NO PARITY) ASKBD LDY #MRATE LDA #MRATEL ;LENGTH JSR TPE LDX #RATE ;BAUD RATE = 4800 LDY #0 LDA #7 ;SET RECEIVE JSR OSBYTE LDX #RATE LDY #0 LDA #8 ;SET SEND JSR OSBYTE ;ASK WHICH FILE LDY #MFILE LDA #MFILEL ;LENGTH JSR TPE FLOOP JSR OSRDCH ;GET ANSWER CMP #'G' BEQ FOK CMP #'Z' BNE FLOOP ;SAYWHAT? FOK STA WCHFIL ;SAVE WHICH FILE ;TELL USER DRIVE # LDY #MDRV LDA #MDRVL JSR TPE JSR OSRDCH ;WAIT FOR 'EM LDY #MGO LDA #MGOL JSR TPE ;NOW GO DO APPROPRIATE TRANSFER LDA WCHFIL CMP #'Z' BEQ WRZIP JMP WRGAME ;*********************** WRZIP ;CREATE ZIP ON DISK ;AS !BOOT FILE SO CAN ;AUTO BOOT CREATE LDY #F LDA #&80 ;(OPEN TO WRT) JSR OSFIND ;DROP THRU FOR REST OF OPERATION ;************************ WRGAME ;WRITE ->DISK BY SECTORS ;******INIT INSTRUCTION BLOCK ;SET UP SECTOR WRITE, LDA #1 ;DRIVE STA DRIVE LDA #0 STA MEMADD+2 ;MEMORY ADDR STA MEMADD+3 LDX #>BUFFR LDY #SECBLK LDA #&7F ;SECTOR WRITE INDICATOR JSR OSWORD ;WRITE SECTOR TO DISK LDA RESULT CMP #0 BEQ WRTOK ;SUCCESS DEC TRYHLD ;CHECK IF TRIED 2CE BNE WRTD ;NOT YET, TRY AGAIN JMP BADWRT ;"FAILED" WRTOK ;INC SECTOR/TRACK FOR NEXT BLOCK INC SECTOR LDA SPERT CMP SECTOR ;ALL SECTORS? BNE UNDR ;NO, SKIP ALONG INC TRACK ;YES, NXT TRK LDA #0 ;START WITH SECTOR #0 EACH TRACK STA SECTOR UNDR JSR SNDACK ;SEND ACK INC ZPSIZE+1 ;COUNT SECTORS (ONLY WILL BE USED W/ZIP) JMP GNXT ;GET NEXT BLK ;**********END OF WRITE LOOP ;************************** ;HERE FOLLOW GENERAL ROUTINES BADWRT ;DID NOT WRITE SUC. TO DSK JSR SETVID ;SET OUTPUT STREAM TO VIDEO LDY #MBADWR LDA #MBADWL ;MSG LENGTH JSR TPE RTS ;LEAVE PRGM DONE ;SEND EOF ACK & DISP "DONE" JSR SNDACK ;SEND ACK LDA WCHFIL ;CHECK, IF ZIP CMP #'Z' ;SET AUTO BOOT BNE OUT ;OTHERWISE, SKIP, DON'T BOTHER ;SET AUTO BOOT BYTE AT BIT ;4,5 OF BYTE 6 SCT 1 TRK 0 ;2 = AUTO *RUN THE FILE LDA #0 STA RESULT ;CLEAR RESULT STA TRACK ;TRACK 0 LDA #1 STA SECTOR ;SECTOR 1 LDA #READ ;SET INST BLK TO READ STA COMMD LDY #SECBLK LDA #$7F ;R/W SECTOR JSR OSWORD ;READ SCTR 1 TRK 0 LDX #BOOT ;OFFSET OF AUTO BOOT BYTE LDA BUFFR,X ;GET BYTE TO SET AND #%11001111 ;CLEAR AUTO BITS ORA #%00100000 ;SET TO *RUN STA BUFFR,X ;NOW SET LOAD & EXEC ADDRESSES ;FILE LENGTH AND START SECTOR LDX #0 ;OFFSET IN DATA LDY #8 ;OFFSET IN BUFR DLOOP LDA FILELN,X ;MOVE DATA IN STA BUFFR,Y ;TO BUFFR THAT INY ;WILL BE SECTOR INX ;1 - TRACK 0 CPX #FLNSZ ;(DIRECTORY INFO) BNE DLOOP LDA #WRITE STA COMMD LDA #0 STA RESULT LDY #SECBLK ;BACK OUT TO LDA #$7F ;DISK JSR OSWORD ;DO IT OUT LDY #MOK LDA #MOKL JSR TPE RTS ;RETURN OUT ;***** RECEIV ;SET IN&OUT STREAM->RS423 ;RET C=0 IF OK C=1 IF DONE ;IF PROB, REPEAT RECEIV JSR SETRS ;GET&CHECK HEADER RCVHDR JSR OSRDCH ;GET CHAR BCS RCVHDR CMP #CMDCHR ;CMD CHAR? BNE RCVHDR ;NO, TRY AGIN JSR OSRDCH ;NEXT CHAR BCS RCVHDR ;BAD CMP #CMDEOF ;END OF FILE? BNE DAT ;NO, KEEP GOING SEC RTS ;EOF ;CHECK IF DATA DAT CMP #CMDDAT ;DATA INDICATOR? BNE RCVHDR ;NO,TRY AGAIN ;CONTINUE, GET REST OF HEADER LDX #0 ;CLEAR INDEX HDRNX JSR OSRDCH ;GET NEXT HDR BYTE CMP BLKHDR,X ;DOES IT MATCH CORRECT SEQUENCE? BNE RBERR ;ERR IF NOT INX CPX #BKHDSZ ;DONE? BMI HDRNX ;LOOP IF NOT ;GET BLOCK, COMPUTING WORD CHECKSUM LDY #0 ;CLEAR INDEX STY CHKSMH STY CHKSML ;AND CHECKSUM NXBYTE JSR OSRDCH ;GET NEXT BYTE STA BUFFR,Y ;STORE CLC ;CLEAR FOR ADD ADC CHKSML ;ADD TO CURNT STA CHKSML BCC RBNX1 INC CHKSMH ;HIGHER BYTE RBNX1 INY ;BUMP INDEX BNE NXBYTE ;256 TIMES ;COMPARE CHECKSUM JSR OSRDCH ;GET HI BYTE CMP CHKSMH ;SAME? BNE RBERR ;NO, ERROR JSR OSRDCH ;GET LOW BYTE CMP CHKSML ;SAME? BNE RBERR ;NO, ERROR CLC RTS ;RET, BLOCK OK RBERR ;ERROR IN RECEIVING BLOCK JSR SNDNAK ;SEND NAK JMP RECEIV ;GO GET BLOCK AGAIN ;***** SNDACK LDA #CMDCHR JSR OSWRCH ;SEND CMD CHR LDA #CMDACK JSR OSWRCH ;AND ACK JSR SETVID ;SET STREAM TO VIDEO LDA #'A' ;ACK TO VID JSR OSWRCH RTS SNDNAK LDA #CMDCHR ;SEND CMD CHR JSR OSWRCH LDA #CMDNAK ;AND NAK JSR OSWRCH JSR SETVID ;SET OUTPUT STREAM TO VIDEO LDA #'N' ;NAK TO SCREEN JSR OSWRCH RTS ;***** SETVID ;GET CHAR FROM KEYBOARD ;(ENABLE RS423) LDA #2 LDX #2 JSR OSBYTE ;OUTPUT TO SCREEN ONLY LDA #3 LDX #4 JSR OSBYTE RTS SETRS ;GET CHAR FROM RS423 LDA #2 LDX #1 JSR OSBYTE ;OUTPUT TO RS423 LDA #3 LDX #7 JSR OSBYTE RTS ;***** TPE ;DISP MSG TO SCREEN STX MHOLDH ;SAVE MSG LOC STY MHOLDL STA MLENG ;SAVE LENGTH LDY #0 ;CLEAR INDEX TLOOP LDA (MHOLDH),Y JSR OSWRCH ;DISP A CHAR INY CPY MLENG BNE TLOOP RTS ;ALL DONE DONE  \ No newline at end of file diff --git a/acorn/warm.asm b/acorn/warm.asm new file mode 100644 index 0000000..972dda8 --- /dev/null +++ b/acorn/warm.asm @@ -0,0 +1,109 @@ + PAGE + SBTTL "--- WARMSTART ROUTINE ---" + + ; ------------- + ; ZIP WARMSTART + ; ------------- + +WARM2: LDA #0 ; CLEAR ALL Z-PAGE VARIABLES + LDX #ZEROPG +ST0: STA 0,X + INX + CPX #ZPGTOP + BCC ST0 + + ; INIT THE PAGING TABLE + + TAX ; = 0 + LDA #$FF +ST1: STA PTABL,X + STA PTABH,X + INX + BNE ST1 + + INC ZSP ; INIT Z-STACK POINTERS + INC OLDZSP ; TO "1" + INC SCRIPT ; ENABLE SCRIPTING + + ; 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 + 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 + 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 + + JSR CLS ; CLEAR SCREEN, DISABLE SPLIT + + ; ... AND FALL INTO MAIN LOOP + + END + diff --git a/acorn/zdos.asm b/acorn/zdos.asm new file mode 100644 index 0000000..6ce074d --- /dev/null +++ b/acorn/zdos.asm @@ -0,0 +1,530 @@ + PAGE + SBTTL 'ZDOS' + + ;********************* + ;GET Z-BLOCK FROM DISK + ;********************* + ; (GET ACTUAL 256 BYTE BLOCK (= 1 SECTOR) + ; OF GAME FROM DISK) + + ;ENTRY: Z-BLOCK # IN DBLOCK + ; TARGET PAGE IN DBUFF+HI + +GETDSK: ;SET DRIVE + + ;USING ONLY 8 SECTORS PER TRACK SO, USING 9 LSBITS OF DBLOCK(WORD) + ;BITS 0-2 = SECTOR BITS 3-8 = TRACK + + LDA DBLOCK+LO ;GET LSB OF BLOCK ID + AND #%00000111 ;MASK FOR SECTOR # + STA SECTOR + + LDA DBLOCK+HI ;GET MSB OF BLOCK ID + AND #%00000001 ;ONLY BIT 0 APPLIES, CLEAR OTHERS + ASL A ;SHIFT LEFT TO BIT 5 + ASL A + ASL A + ASL A + ASL A + STA TRACK ;HOLD A SEC + + LDA DBLOCK+LO ;GET LSB OF BLOCK AGAIN + LSR A ;SHIFT OVER TRACK # FOR USE + LSR A ;(COVERING SECTOR) + LSR A + ORA TRACK ;ADD HIGH BIT + CLC + ADC #4 ;ZCODE STARTS ON TRACK 4. ADD OFFSET TO + ;ALIGN # + CMP #80 ;HIGHEST TRACK IS 79 + BCS TRKERR + STA TRACK ;SAVE TRACK FOR REAL + + ;ENTRY FOR "RESTORE" (TRACK, SECTOR, DRIVE PRE-ASSIGNED) + ;(SETS TO READ DISK AND MOVES EACH BLOCK TO MEMORY) + +GETRES: CLC ;CARRY CLEAR = READ BLOCK + JSR DISK ;GO READ THE BLOCK + BCS DSKERR ;CARRY = ERROR + + LDY #0 ;ELSE, MOVE CONTENTS OF IOBUFF +GDKL: LDA IOBUFF,Y ;TO TARGET PAGE IN DBUFF + STA (DBUFF),Y + INY + BNE GDKL ;LOOP TO DO ALL 256 BYTES + + INC DBLOCK+LO ;POINT TO NEXT Z-BLOCK + BNE GDEX ;NO OVERFLOW + INC DBLOCK+HI ;OTHERWISE INC HI BYTE ALSO +GDEX: JMP NXTSEC ;POINT TO NEXT SECTOR & PAGE + + + ;****************** + ;PUT DBLOCK TO DISK + ;****************** + ;(WHEN SAVE GAME, SETS TO WRITE TO DISK + ;AFTER MOVING MEMORY PAGE TO TRANSFER BUFFER (IOBUFF)) + + ;ENTRY: TRACK, SECTOR, DRIVE ASSIGNED + ; PAGE TO WRITE IN DBUFF + +PUTDSK: LDY #0 ;MOVE PAGE AT DBUFF TO IOBUFF FOR I/O +PTKL: LDA (DBUFF),Y + STA IOBUFF,Y + INY + BNE PTKL ;LOOP TILL ALL 256 BYTES DONE + + SEC ;CARRY SET = WRITE BLOCK + JSR DISK ;GO WRITE + BCS DSKERR ;CARRY = ERROR + +NXTSEC: INC SECTOR ;POINT TO NEXT SECTOR + LDA SECTOR + AND #%00000111 ;OVERFLOWED (ZERO RESULT) + BNE SECTOK ;NO, CONT + INC TRACK ;ELSE UPDATE TRACK # +SECTOK: STA SECTOR ;AND SECTOR # + + INC DBUFF+HI ;POINT TO NEXT RAM PAGE + RTS + + + ;*** ERROR 12: DISK ADDRESS OUT OF RANGE *** + +TRKERR: LDA #12 + JMP ZERROR + + ;*** ERROR 14: DISK ACCESS *** + +DSKERR: LDA #14 + JMP ZERROR + + + ;SET UP SAVE & RESTORE SCREENS + +SAVRES: JSR ZCRLF ;CLEAR THE BUFFER + JSR CLS ;CLEAR SCREEN + LDX #0 + STX SCRIPT ;DISABLE SCRIPTING (SAVE CMDS SHOULD + ;NOT GO ON PAPER) + RTS + + ;DISPLAY A DEFAULT + + ;ENTRY: DEFAULT IN A + +DEFAL: DB " (Default is " +DEFNUM: DB "*):" +DEFALL EQU $-DEFAL + +DODEF: CLC + ADC #'0' ;CONVERT TO ASCII + STA DEFNUM ;INSERT IN STRING + + LDX #LOW DEFAL + LDA #HIGH DEFAL + LDY #DEFALL + JSR DLINE ;DISPLAY + RTS + + + ; ***************************** + ; GET SAVE & RESTORE PARAMETERS + ; ***************************** + + ;THESE INCLUDE POSITION (1-5 AS CHOSEN BE PLAYER), DRIVE (0-1 AS + ;CHOSEN BY PLAYER), TRACK AND SECTOR (CALCULATED FROM POSITION) + +POSIT: DB EOL + DB "Position 1-5" +POSITL EQU $-POSIT + +WDRIV: DB EOL + DB "Drive 0, 1, 2, or 3" +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 POSITION + +CHANGE: LDA GPOSIT ;SHOW CURRENT + CLC + ADC #1 ;SO 0 = '1' + JSR DODEF ;DEFAULT POSITION + +GETPOS: JSR GETKEY ;WAIT FOR A KEY + CMP #EOL ;IF [RET] + BEQ POSSET ;USE DEFAULT + SEC + SBC #'1' ;ELSE CONVERT ASCII TO BINARY + CMP #5 ;IF BELOW "6" + 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 OSWRCH ;AND DISPLAY IT + + ;GET DRIVE ID + + LDX #LOW WDRIV + LDA #HIGH WDRIV + LDY #WDRIVL + JSR DLINE ;"DRIVE 0 1 2 3" + + LDA GDRIVE ;SHOW DEFAULT + JSR DODEF + +GETDRV: JSR GETKEY ;GET A KEYPRESS + CMP #EOL ;IF [RET] + BEQ DRVSET ;USE DEFAULT + SEC + SBC #'0' ;CONVERT TO BINARY + CMP #4 ;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 #'0' ;CONVERT TO ASCII + STA SAVDRI ;STORE TO DRIVE STRING + STA MDRI ;AND IN TEMP STRING + JSR OSWRCH ;AND SHOW NEW SETTING + + LDX #LOW MIND ;SHOW TEMP SETTINGS + LDA #HIGH MIND + LDY #MINDL + JSR DLINE + +GETYES: JSR GETKEY + CMP #'Y' ;IF REPLY IS "Y" + BEQ ALLSET ;ACCEPT RESPONSES + CMP #'y' + BEQ ALLSET + + CMP #'N' ;IF REPLY IS "N" + BEQ RETRY ;TRY AGAIN + CMP #'n' + BEQ RETRY + + JSR BOOP ;INSIST ON Y/N + JMP GETYES + +RETRY: LDX #LOW NO ;PRINT NO + LDA #HIGH NO + LDY #NOL + JSR DLINE + JMP PARAMS ;AND TRY AGAIN (LOOPS BACK) + +ALLSET: LDX #LOW YES ;PRINT "YES" + LDA #HIGH YES + LDY #YESL + JSR DLINE + + LDA TDRIVE ;MAKE THE TEMP DRIVE + STA GDRIVE ;THE DEFAULT DRIVE + STA DRIVE ;SET FOR ACTUAL WRITE + LDA TPOSIT ;AND TEMP POSITION + STA GPOSIT ;THE DEFAULT POSITION + + ;CALC TRACK & SECTOR OF GAME POSITION ON SAVE DISK + ;EACH POSITION REQUIRES 12 TRACKS (8 SECTORS EA) + + ;A = POSITION# + ASL A ; * 2 + ASL A ; * 4 + STA TRACK ; SAVE HERE A SEC + ASL A ; * 8 + CLD + ADC TRACK ; * 12 + STA TRACK + LDA #0 + STA SECTOR ;ALWAYS START @ SECTOR #0 + + LDX #LOW INSM + LDA #HIGH INSM + LDY #INSML + JSR DLINE ;"INSERT SAVE DISK IN DRIVE X." + JSR RETURN ;"HIT [RET] TO CONTINUE." + CLC ;FOR SUCCESS + RTS + + + ;********************* + ;"PRESS RETURN" PROMPT + ;********************* + +RETURN: LDX #LOW RTN + LDA #HIGH RTN + LDY #RTNL + JSR DLINE + + ;ENTRY FOR QUIT/RESTART (INTERNAL OF 'RETURN') +GETRET: JSR GETKEY ;WAIT FOR + CMP #EOL + BEQ RETEX ;GOT IT + JSR BOOP ;ACCEPT NO SUBSTITUTES + JMP GETRET +RETEX: RTS + +RTN: DB EOL + DB "Press to continue." + DB EOL +RTNL EQU $-RTN + + + ;******************** + ;PROMPT FOR GAME DISK + ;******************** + +GAME: DB EOL + DB "Insert STORY disk into drive #0." +GAMEL EQU $-GAME + +TOBOOT: LDX #LOW GAME + LDA #HIGH GAME + LDY #GAMEL + JSR DLINE ;"INSERT DISK" + JSR RETURN ;"PRESS [RET]" + + LDA #$FF ;RE-ENABLE SCRIPTING + STA SCRIPT + JMP CLS ;CLEAR SCREEN & RETURN + + + ; ********* + ; SAVE GAME + ; ********* + +SAV: DB "Save Position" + DB EOL +SAVL EQU $-SAV + +SVING: DB EOL + DB "Saving position " +SVPOS: DB "* ..." + DB EOL +SVINGL EQU $-SVING + + ;(ZSAVE IS A 0-OP) + +ZSAVE: JSR SAVRES ;SET UP SCREEN + + LDX #LOW SAV + LDA HIGH SAV +` LDY #SAVL + JSR DLINE ;"SAVE POSITION" + + JSR PARAMS ;GET PARAMETERS + BCC DOSAVE ;ERROR IF CARRY SET + +BADSAV: LDA #0 ;RESET DRIVE TO GAME DRIVE + STA DRIVE + JSR TOBOOT ;GET BOOT DISK + JMP PREDF ;PREDICATE FAILS + +DOSAVE: 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 Z-STACK POINTER + STA BUFSAV+2 ;TO 3RD BYTE + LDA OLDZSP ;MOVE OLD ZSP + STA BUFSAV+3 ;TO 4TH + + LDX #2 ;MOVE CONTERNTS OF ZPC +ZPCSAV: LDA ZPC,X ;TO BYTES 5-7 + STA BUFSAV+4,X ;OF BUFSAV + DEX + BPL ZPCSAV ;3 BYTES, 3 TIMES + + ;WRITE LOCALS/BUFSAV PAGE TO DISK + + LDA #HIGH LOCALS + STA DBUFF+HI ;POINT TO THE PAGE + JSR PUTDSK ;AND WRITE IT OUT + BCS BADSAV ;CATCH WRITE ERROR HERE + + ;WRITE CONTENTS OF Z-STCK TO DISK + + LDA #HIGH ZSTAKL ;POINT TO 1ST PAGE + STA DBUFF+HI + JSR PUTDSK ;WRITE 1ST AND + JSR PUTDSK ;2ND PAGE OF Z-STACK + + ;WRITE ENTIRE GAME PRELOAD TO DISLK + + LDA ZCODE ;POINT TO 1ST PAGE + STA DBUFF+HI ;OF PRELOAD (HIGH ONLY, PAGE ALIGNED) + + LDX ZBEGIN+ZPURBT ;GET # IMPURE PAGES + INX ;USE FOR INDEXING + STX I+LO + +LSAVE: JSR PUTDSK + DEC I+LO + BNE LSAVE ;DO ALL PAGES OF PRELOAD + + LDA #0 ;RESET TO GAME DRIVE + STA DRIVE + + JSR TOBOOT ;PROMPT FOR GAME DISK + JMP PREDS ;ELSE PREDICATE SUCCEEDS + + + ; ************ + ; RESTORE GAME + ; ************ + +RES: DB "Restore Position" + DB EOL +RESL EQU $-RES + +RSING: DB EOL + DB "Restoring position " +RSPOS: DB "* ..." + DB EOL +RSINGL EQU $-RSING + +ZREST: JSR SAVRES ;SET UP SCREEN + + LDX #LOW RES + LDA #HIGH RES + LDY #RESL + JSR DLINE ;"RESTORE POSITION" + + JSR PARAMS ;GET PARAMETERS + BCS BADRES ;ERROR IF CARRY SET + + 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 ;ALL + + LDA #HIGH LOCALS + STA DBUFF+HI + JSR GETRES ;RETRIEVE 1ST BLOCK OF PRELOAD + + 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 2ND BYTE? + CMP ZBEGIN+ZID+1 + BEQ RIGHT ;CONTINUE IF BOTH BYTES MATCH + + ;HANDLE INCORRECT SAVE DISK + +WRONG: LDX #31 ;RESTORE ALL SAVED LOCALS +WR0: LDA $0100,X + STA LOCALS,X + DEX + BPL WR0 ;ALL + +BADRES: LDA #0 ;RESET TO GAME DRIVE + STA DRIVE + JSR TOBOOT ;PROMPT FOR GAME DISK + 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 GETRES ;GET 1ST BLOCK OF Z-STACK + JSR GETRES ;AND 2ND BLOCK + + LDA ZCODE + STA DBUFF+HI + JSR GETRES ;GET 1ST BLOCK OF PRELOAD + + LDA I+LO ;RSTORE 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 GETRES ;FETCH THE REMAINDER + 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 #FALSE + STA ZPCFLG ;INVALIDATE ZPC + + LDA #0 ;RESET TO GAME DRIVE + STA DRIVE + + JSR TOBOOT ;PROMPT FOR GAME DISK + JMP PREDS ;PREDICATE SUCCEEDS + + END diff --git a/acorn/zip.asm b/acorn/zip.asm new file mode 100644 index 0000000..d4b3bd9 --- /dev/null +++ b/acorn/zip.asm @@ -0,0 +1,79 @@ + TITLE "ZIP/6502 INFOCOM, INC. --- EQUATES" + + ; -------------------------- + ; ZIP/6502 2.0 + ; Z-CODE INTERPRETER PROGRAM + ; FOR BBC ACORN + ; -------------------------- + + ; INFOCOM, INC. + ; 55 WHEELER STREET + ; CAMBRIDGE, MA 02136 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + +MSTART EQU $1100 ; START OF FREE PROGRAM RAM +ZEROPG EQU $00 ; START OF FREE Z-PAGE RAM +ZPGTOP EQU $8F ; END OF FREE Z-PAGE RAM + +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 SHAKE.ASM NOT APPLICABLE TO ACORN + INCLUD EQ.ASM + + TITLE "ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT INIT" + INCLUD HARDEQ.ASM ; M + INCLUD COLD.ASM ; M + + 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 I/O" + INCLUD IO.ASM ; M + INCLUD MACHINE.ASM ; M + INCLUD ZDOS.ASM ; M + INCLUD DISK.ASM ; M + + IF DEBUG + INCLUD BUGGER.ASM ; M + ENDIF + + TITLE "ZIP/6502 INFOCOM, INC." + END + diff --git a/acorn/zstring.asm b/acorn/zstring.asm new file mode 100644 index 0000000..6045eb9 --- /dev/null +++ b/acorn/zstring.asm @@ -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 + diff --git a/amiga/--read.me b/amiga/--read.me new file mode 100644 index 0000000..0ee2cfa --- /dev/null +++ b/amiga/--read.me @@ -0,0 +1,46 @@ + +PS: -- DIRECTORY CONTENTS AND COMMENTS +---------------------------------------------------------------------- + + 68KZIP.ASM and AMIGAZIP.C are the ZIP/EZIP sources. + + INTUITION.BUGS -- as reported to tech support. + + PATCHES.BUGS details several changes to the supplied "include" files + needed for successful compilation. + + SUPPORT.INFO -- for customer support, lists some potential user + problems and answers. + + AHEAD.C -- support for buffered type-ahead. Not yet integrated + into the I/O sources or tested. + +Development for the Amiga involves three machines, the DEC20, a Compaq, +and an Amiga. The Compaq is the primary machine. All development tools, +various header and include files, and the sources reside there. + +The DEC20 is used mainly for convenience in editing the large source +files, and for backups. Files are moved to and from the Compaq with +Kermit. + +The Amiga itself is presently used only for executing and testing +the program. A native version of the developement system does exist, +but without a (working) hard disk, forget it. + +An executable program file is transferred by running Crosstalk on the +Compaq and Read on the Amiga. It must have been converted to hex format, +since Read only accepts 7-bit data. + +------------ + +See also for backups of all Compaq batch files, +and notes on use. + +------------ + +When Kermiting to the Compaq, first split the 68K source file on the 20 +into four parts, ZIP1.ASM through ZIP4.ASM, to facilitate editing. +Transfer these along with ZIP0.ASM, the master include file. + +Old ZIPx.ASM files should first be deleted from the Compaq directory, +or the new ones will be renamed ("&" chars added) during transfer. diff --git a/amiga/amigazip.c b/amiga/amigazip.c new file mode 100644 index 0000000..4e1c919 --- /dev/null +++ b/amiga/amigazip.c @@ -0,0 +1,2100 @@ + +/*------------------------------------------------------*/ +/* AMIGA ZIP/EZIP INTERFACE */ +/*------------------------------------------------------*/ + +/* MODIFICATION HISTORY + + 25 OCT 85 init_script () uses PRT: file. Close_Device was + crashing when two games run simultaneously. + + 29 OCT 85 drive_default() strips savename of leading spaces + 29 OCT 85 get_control_seq() ignores garbage seqs + + 04 NOV 85 write_cursor_pos() takes no params (same as read) + 04 NOV 85 extra error checking in make_icon_file() + + 22 JUL 87 changed scripting EOL seq from Esc-E to CRLF, + wasn't working under AmigaDOS 1.2 + added unhide_screen for Alertbox problem + set NOCAREREFRESH flag to avoid border flicker + added stash_put(), stash_get() for typeahead, + used by get_control_seq() and read_console(), + read_cursor_pos() still NOT working as advertised + 26 AUG 87 added volume control to md_sound (in SOUND.C) +*/ + +#include "exec\types.h" +#include "exec\exec.h" + +#include "libraries\dos.h" +#include "libraries\dosextens.h" + +#include "intuition\intuition.h" /* for AllocRemember */ +#include "intuition\intuibas.h" + +#include "workbench\icon.h" +#include "workbench\workbench.h" /* for disk objects */ + +#define CHAR unsigned char +#define INT short /* must be 16 bits for 68K compatibility */ +#define LONG long +#define BOOL INT + +#define VOID int +#define GLOBAL /**/ +#define FOREVER for(;;) + +/* This switch controls conditional ZIP/EZIP compilation */ +/* (now defined in batch file, where compiler is invoked) */ + +/* #define EZIP 0 */ /* set for EZIP, otherwise classic */ + +#define ZDEBUG 0 /* set for debugging */ +#define bug_DiskFull 0 /* set if crashes system - FIXED */ + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ + +#if EZIP + +struct Screen *ZScreen; +struct TextAttr ZTextAttr; /* defined in \graphics\text.h */ + +#endif + +/* Use altered IOStdReq structure, "data" field type APTR changed to STRPTR. + Otherwise the compiler forces string pointers to be even-aligned. */ + +struct IOStdReq_MUNGED ZIOStdReq; /* for general console I/O */ +struct IOStdReq_MUNGED ZRDStdReq; /* for queued reads */ + +struct MsgPort ZMsgPort; /* for console I/O */ +struct Window *ZWindow; + + CHAR single_char[2]; /* for queued reads */ + +/* scripting variables -- two methods possible */ + + LONG print_file; /* scripting refnum */ +/* +struct IOStdReq_MUNGED SIOStdReq; +struct MsgPort SMsgPort; +*/ + INT prt_inited = 0; /* set when printer opened */ + INT prt_active = 0; /* set when scripting is active */ + +/* cursor variables */ + + INT y_res, y_char; /* rows = y_res / y_char */ + INT x_res, x_char; + +GLOBAL INT rows, cur_row; /* cur_row in 0 .. rows-1 */ +GLOBAL INT columns, cur_column; + +GLOBAL INT split_row; /* first row in scrolling area */ + +/* This buffer is accessed by the kernel. Careful about changing its size */ + +GLOBAL CHAR savename[64]; /* buffer for file_select dialog */ +GLOBAL CHAR saveback[64]; /* buffer for default name */ + + INT max_index; /* number of available color indices */ + INT v_fore = 1; /* text color */ + INT v_back = 0; /* all other colors */ + INT reversed = 0; /* reversed video? (MONO ONLY) */ + + +GLOBAL INT ms_tick; /* millisecs per timer tick */ +GLOBAL INT ms_total; /* millisecs since cursor was turned on */ + INT curs_on; /* set if currently showing */ + +/* These vars are used to pass results back to a kernal routine, */ +/* since function returns are limited to an error code (by convention) */ + + LONG temp_channel; + LONG temp_memory; + +/* These vars increase the speed of disk reads (by avoiding extra seeks) */ + + LONG old_offset = -1; /* initialize to invalid values */ + LONG old_channel = -1; + +/* memory usage can be controlled by user, by supplying a free byte + count in the CLI command line. Useful if another task will be launched + subsequently. Otherwise game takes as much memory as it can use. */ + + LONG mem_freereq; /* set during init */ + +struct IntuitionBase *IntuitionBase; + +struct IconBase *IconBase; +struct DiskObject *diskobj; /* SAVE file icon info */ + +struct Remember *RememberKey; + +/* set when console-device forces a scroll, unknown to kernel (happens + when last column is filled) */ + + INT auto_CR = 0; /* DEAD, SEE window_resized () */ + +/* DEAD, SEE bug_DiskFull + + If a NEW save file is being created, check disk free space before + each write call. Prevents a useless Retry/Abort dialog (and in the + case of make_icon_file, a crash). +*/ + BOOL disk_newsave; + LONG disk_free; + +/************************************************************************/ +/* Externals */ +/************************************************************************/ + +/* +extern LONG trap1 (); +extern VOID START (); +*/ + +CHAR stash_get (); + +/************************************************************************/ +/* Low Level Console Device I/O */ +/************************************************************************/ + +/*------------------------------*/ +/* write_console */ +/*------------------------------*/ +VOID +write_console (string, len) /* send raw string to console device */ + +CHAR *string; +INT len; +{ + ZIOStdReq.io_Data = (STRPTR) string; + ZIOStdReq.io_Length = len; + + ZIOStdReq.io_Command = CMD_WRITE; + DoIO (&ZIOStdReq); /* works OK for writes */ +} + +/*------------------------------*/ +/* queue_read */ +/*------------------------------*/ + +VOID +queue_read () +{ + ZRDStdReq.io_Command = CMD_READ; + ZRDStdReq.io_Data = &single_char[0]; /* must be aligned */ + ZRDStdReq.io_Length = 1; + + SendIO (&ZRDStdReq); /* due to bug in DoIO */ +} + + +/*------------------------------*/ +/* read_console */ +/*------------------------------*/ + +CHAR +read_console () /* get a char from console device */ +{ + CHAR c; + +/** while (GetMsg (&ZMsgPort) == NULL); **/ /* busy loop */ + + c = stash_get(); /* any saved typeahead? */ + if (!c) { + WaitPort (&ZMsgPort); /* no, sleep tastefully til keydown */ + GetMsg (&ZMsgPort); /* got one, remove msg from queue */ + c = single_char[0]; /* value was left here */ + queue_read (); /* start the next read */ + } + return (c); +} + + +/*------------------------------*/ +/* send_control_seq */ +/*------------------------------*/ + +#define begin_mark '\233' /* 0x9B (one byte only) */ + +VOID +send_control_seq (string) /* write it, prefixed with control char */ + +CHAR *string; +{ + CHAR temp[64]; /* string must be even aligned */ + + temp[0] = begin_mark; + temp[1] = 0; + + strcat (&temp, string); + write_console (temp, strlen (temp)); +} + +/*------------------------------*/ +/* get_control_seq */ /* read chars into buffer */ +/*------------------------------*/ + +VOID +get_control_seq (buffer, end_mark) + +CHAR *buffer; +CHAR end_mark; +{ + CHAR c; + INT i, j; + +/* We are waiting for a certain sequence, which always begins with $9B and + ends with the given end_mark. Must ignore (1) other sequences which may be + generated at any time by pressing special keys, and (2) normal keys. + + Other seqs also start with $9B but (hopefully) don't contain end_mark. + Known examples are cursor keys (A-D), functions (0~-9~), and Help key (?~). +*/ + + while ((c = read_console ()) != begin_mark) { + stash_put(c); /* not what we want -- but save it! */ + } + i = 0; /* new sequence starting */ + while ((c = read_console ()) != end_mark) { + if (c != begin_mark) { + buffer[i] = c; + i++; + } + else { /* some other seq, ignore */ + for (j=0; jWScreen); /* (a system call) */ +} + +/*------------------------------*/ +/* random_seed */ +/*------------------------------*/ +LONG +random_seed () +{ + LONG seconds, micros; + + CurrentTime (&seconds, µs); + + return (micros); +} + + +/*------------------------------*/ +/* highlight */ +/*------------------------------*/ +VOID +highlight (mode) + +INT mode; +{ + switch (mode) + { + case 0: /* normal text, no effects */ + + send_control_seq ("0m"); + break; + case 1: /* inverse video */ + + send_control_seq ("7m"); + break; + case 2: /* bold */ + + send_control_seq ("1m"); + break; + case 4: /* italic (underline) */ + + send_control_seq ("4m"); + break; + } +} + +/*------------------------------*/ +/* get_size_msg */ +/*------------------------------*/ + +/* DEAD -- seems to prevent console-device from getting size update. + Replaced by "window_resized" routine following. + + The message is not needed anyway, since the ZWindow data structure is + always updated as a side-effect of sizing events. + + To use this routine, must have initialized NewZWindow.IDCMPFlags to NEWSIZE. +*/ + +VOID +get_size_msg () /* get (any pending) IDCMP message */ +{ +/* struct Message *sizeMsg; + + sizeMsg = (struct Message *) GetMsg (ZWindow->UserPort); + + if (sizeMsg) + { + *** here we refresh window and update related vars *** + + ReplyMsg (sizeMsg); *** release the message *** + } +*/ +} + +/*------------------------------*/ +/* window_resized */ +/*------------------------------*/ +INT +window_resized () /* update globals, return window column width */ + +/* this routine is called - + [] during init + [] after every line output (this takes care of MOREs) + [] after a RDLINE input +*/ + +{ + +/* determine size of current font */ + + /* (DONE ONCE ONLY DURING INIT, SETS Y_CHAR AND X_CHAR) */ + +/* determine usable size of window */ + + y_res = ZWindow->Height - ZWindow->BorderTop - ZWindow->BorderBottom; + x_res = ZWindow->Width - ZWindow->BorderLeft - ZWindow->BorderRight; + +/* Calculate rows and columns. To prevent undesired AMIGA auto wrapping, we + pretend that the column width is one less than it really is. +*/ + rows = y_res / y_char; + columns = (x_res / x_char) - 1; + + if (cur_row >= rows) cur_row = rows - 1; + if (cur_column >= columns) cur_column = columns - 1; + + return (columns); /* updates kernel folding routines */ +} + +/************************************************************************/ +/* Cursor Positioning */ +/************************************************************************/ + +/* ALL absolute cursor positioning should go through these two routines. + Since the kernel uses "cur_row" and "cur_column" to track cursor position, + always use those globals instead of passing parameters. + + Note that the interpreter defines the cursor home position as (0,0) + while the console device (as well as the ZIP spec) defines it as (1,1). +*/ + +/*------------------------------*/ +/* read_cursor_pos */ +/*------------------------------*/ + +VOID +read_cursor_pos () /* read, unparse, and digitize cursor position, + store in globals */ +{ + CHAR cursor_info[64]; + + CHAR *startx,*endx; /* string limits */ + CHAR *starty,*endy; + + int x_value,y_value; /* careful of type here */ + +/* Fix for type-ahead problem: get_control_seq() stores extra chars + in a special buffer, and read_console() always checks that buffer. + + Old fix: avoid all reading from the console device [messes up + type-ahead, and seems sometimes to be itself screwed up by normal + user input]. Assume cursor is always in "normal" position prior + to special operations (when cursor is read). +*/ + cur_row = rows - 1; cur_column = 0; + return (0); /* STILL FAKE IT; REST IS HANGING */ + +/* read in string representing cursor position -- format is ;R */ + + send_control_seq ("6n"); + get_control_seq (&cursor_info, 'R'); + +/* setup pointers to x and y strings, and make them asciz */ + + endy = (char *) strchr (&cursor_info, ';'); + endx = (char *) strchr (&cursor_info, 'R'); + + starty = (char *) &cursor_info; endy[0] = 0; + startx = (char *) &endy[1]; endx[0] = 0; + +/* convert decimal strings to integers, normalize (cur_row in 0 .. rows-1), + leave results in globals (global type may be different -- INT) */ + + stcd_i (starty, &y_value); cur_row = y_value - 1; + stcd_i (startx, &x_value); cur_column = x_value - 1; +} + +/*------------------------------*/ +/* write_cursor_pos */ +/*------------------------------*/ + +VOID +write_cursor_pos () /* set the cursor position */ +{ + int x_new, y_new; /* correct type for library call */ + + CHAR cursor_info[64]; + CHAR x_str[32]; + CHAR y_str[32]; + +/* normalize co-ords (1-origin), convert integers to strings */ + + y_new = cur_row + 1; /* these are values to set */ + x_new = cur_column + 1; + + stcu_d (&y_str, y_new, 32); + stcu_d (&x_str, x_new, 32); + +/* combine and transmit the strings */ + + cursor_info[0] = 0; /* asciz */ + + strcat (&cursor_info, &y_str); + strcat (&cursor_info, ";"); + strcat (&cursor_info, &x_str); + strcat (&cursor_info, "H"); + + send_control_seq (&cursor_info); +} + + +/*------------------------------*/ +/* amiga_scroll */ +/*------------------------------*/ + +VOID +amiga_scroll () /* method depends on cursor position */ +{ + CHAR char_seq[2]; + + read_cursor_pos (); /* get cursor pos into globals */ + + if (cur_row < rows - 1) /* not at bottom of screen? */ + { + char_seq[0] = 13; + char_seq[1] = 10; /* CR, tack on a LF */ + write_console (&char_seq, 2); + } + else /* at bottom, delete split line to scroll */ + { + cur_row = split_row; cur_column = 0; + write_cursor_pos (); + + send_control_seq ("M"); + + cur_row = rows - 1; + write_cursor_pos (); + } +} + +/************************************************************************/ +/* Screen Handling */ +/************************************************************************/ + +/*------------------------------*/ +/* clear_eol */ +/*------------------------------*/ +VOID +clear_eol () +{ + send_control_seq ("K"); /* clear to EOL */ +} + +/*------------------------------*/ +/* clear_lines */ +/*------------------------------*/ +VOID +clear_lines (row1, row2) /* EZIP, also CZIP (OPSPLIT) */ + +INT row1, row2; +{ + INT old_row, old_column; + INT i; + + read_cursor_pos (); + old_row = cur_row; old_column = cur_column; + + for (i=row1; i and are the special chars */ + +/* if one or more directories were given, find the last one */ + + special = (CHAR *) strrchr (pathname, '/'); + +/* otherwise, see if a drive was given */ + + if (special == NULL) + special = (CHAR *) stpchr (pathname, ':'); + + if (special != NULL) /* found one, skip over the delimiter */ + special++; + + return (special); /* pointer to bare filename, or NULL */ +} + +/*------------------------------*/ +/* drive_default */ +/*------------------------------*/ + +/* If savename lacks a drive/directory spec but saveback includes one + (the default), prefix it to savename. + + Also, take this opportunity to remove any leading/trailing spaces from + savename. +*/ + +VOID +drive_default () +{ + CHAR *barename; + CHAR temp[64]; + +/* check whether savename includes a drive/directory */ + + barename = (CHAR *) divide_pathname (&savename); + + if (barename == NULL) /* Nope */ + { + strip_spaces (&savename); + +/* check whether a default drive/directory exists */ + + strcpy (&temp, &saveback); + + barename = (CHAR *) divide_pathname (&temp); + + if (barename != NULL) /* Yep */ + { +/* and prefix the default drive/directory onto savename */ + + *barename = 0; /* chop off default filename */ + strcat (&temp, &savename); + strcpy (&savename, &temp); + } + } + +/* user DID supply a drive/directory, just check for spaces in filename */ + + else + { + strip_spaces (barename); + } +} + +#if bug_DiskFull /* BUG GONE, THIS IS DEAD CODE */ + +/*------------------------------*/ +/* disk_bytes_avail */ +/*------------------------------*/ + +LONG +disk_bytes_avail () /* returns number of available bytes on save disk, + -1 if error. Must call AFTER save file is created */ +{ + LONG filelock; + LONG avail; + + INT pad1; +struct InfoData ZInfoData; /* information about the save disk */ + INT pad2; + +struct InfoData *ZInfoDataPtr; /* pointer to the above */ + LONG ptr; + + +/* Must first obtain a "lock" for a valid file on the desired disk. + We conveniently use the save file (thus it must already exist). */ + + filelock = Lock (&savename, ACCESS_READ); + + if (!filelock) /* if error, exit now */ + return (-1); + +/* The InfoData structure must be longword aligned (for AmigaDOS). + Adjust alignment with the pad bytes, if necessary. */ + + pad1 = pad2 = 0; /* make the Compiler stop whining */ + + ptr = (LONG) &ZInfoData; + ptr = ptr>>2; ptr = ptr<<2; + ZInfoDataPtr = (struct InfoData *) ptr; + +/* Determine how much space remains on the save disk. */ + + if (Info (filelock, ZInfoDataPtr)) + { + avail = + (ZInfoDataPtr->id_NumBlocks + - ZInfoDataPtr->id_NumBlocksUsed) /* free blks */ + * ZInfoDataPtr->id_BytesPerBlock; + } + else avail = -1; /* something wrong, fail */ + + UnLock (filelock); /* make sure to undo this lock */ + + return (avail); +} + +#endif /* bug_DiskFull */ + +/************************************************************************/ +/* Disk I/O */ +/************************************************************************/ + + +/*------------------------------*/ +/* read_file */ +/*------------------------------*/ + +LONG +read_file (channel, offset, length, buffer) + +LONG channel; +LONG offset, length; +CHAR *buffer; +{ + LONG former_pos; + LONG actual_len; + LONG error; + +/* disk access speed is increased, if unnecessary seeks are eliminated */ + + if ((channel != old_channel) || (offset != old_offset)) + { + former_pos = Seek (channel, offset, -1); /* AmigaDOS */ + if (former_pos == -1) + { + old_offset = -1; /* force seek next time */ + return (IoErr ()); + } + } + + old_channel = channel; + old_offset = offset + length; + + actual_len = Read (channel, buffer, length); + if (actual_len == -1) + { + old_offset = -1; /* force seek next time */ + error = IoErr (); + } + +/* Check the number of bytes actually read. This will detect certain + invalid save files (for example, files where Amiga crashed during their + creation, for whatever reason). + + We allow for a special case of actual length being 256 less than expected. + The kernel does paging in 512 byte blocks, while the Amiga TFTP utility + transfers data files in 256 byte blocks. +*/ + else if ((actual_len == length) || (actual_len == (length - 256))) + + error = 0; /* zero means no error */ + + else + { + old_offset = -1; + error = 1; /* length error */ + } + + return (error); +} + + +/*------------------------------*/ +/* write_file */ +/*------------------------------*/ + +LONG +write_file (channel, offset, length, buffer) + +LONG channel; +LONG offset, length; +CHAR *buffer; +{ + LONG error; + +/* Errors: zero means none, 999 means disk full, otherwise IOErr () */ + +#if bug_DiskFull + + if (disk_newsave) /* FALSE if writing over old file */ + { + disk_free = disk_free - length; + if (disk_free < 0) + return (999); /* not enough room for write */ + } +#endif + error = Seek (channel, offset, -1); + if (error == -1) + return IoErr (); + + error = Write (channel, buffer, length); + if (error == -1) + return IoErr (); + + else if (error != length) /* (should have been caught above) */ + return (999); + + else return (0); /* no error */ +} + + +/*------------------------------*/ +/* create_file */ +/*------------------------------*/ + +LONG +create_file () /* create (if needed), and open, a SAVE file */ +{ +/* two ways to enter this routine: if disk_newsave is TRUE, we are creating + a new save file, otherwise we are writing over an old one */ + + temp_channel = Open (&savename, MODE_NEWFILE); + +#if bug_DiskFull /* avoid a write error */ + + if ((temp_channel) && (disk_newsave)) + { +/* we just created the file, but must close it momentarily to get disk info. + Otherwise the Lock call fails */ + + Close (temp_channel); + +/* determine how much free space is on the disk, so file_write can fail + gracefully if necessary */ + + disk_free = disk_bytes_avail (); + + temp_channel = Open (&savename, MODE_NEWFILE); + } +#endif /* bug_DiskFull */ + + if (!temp_channel) + return (IoErr ()); + else + return (0); /* zero means OK */ +} + + +/*------------------------------*/ +/* open_file */ +/*------------------------------*/ + +LONG +open_file () /* open an file to RESTORE from */ +{ + temp_channel = Open (&savename, MODE_OLDFILE); + + if (!temp_channel) + return (IoErr ()); + else + return (0); /* zero means OK */ +} + +/*------------------------------*/ +/* close_file */ +/*------------------------------*/ + +LONG +close_file (channel) + +LONG channel; +{ + Close (channel); + + return (0); /* no error codes? */ +} + + +/*------------------------------*/ +/* delete_file */ +/*------------------------------*/ + +LONG +delete_file () +{ + LONG success; /* actually BOOLEAN */ + + success = DeleteFile (&savename); + + if (success) + return (0); + else return (1); +} + + +/*------------------------------*/ +/* exist_file */ +/*------------------------------*/ + +LONG +exist_file () /* called before every SAVE */ +{ + LONG filelock; + LONG exists; + + filelock = Lock (&savename, ACCESS_WRITE); + exists = filelock; /* non-zero if already exists */ + + if (exists) + { + disk_newsave = FALSE; + UnLock (filelock); /* if does exist, undo the lock */ + } + else disk_newsave = TRUE; /* set the global */ + + return (exists); +} + +/*------------------------------*/ +/* open_game */ +/*------------------------------*/ + +LONG +open_game() +{ + CHAR *gamename; + + gamename = "Story.Data"; /* always call it this */ + + temp_channel = Open (gamename, MODE_OLDFILE); + + if (temp_channel == 0) + return (IoErr ()); + else return (0); /* zero means OK */ +} + +/*------------------------------*/ +/* close_game */ +/*------------------------------*/ + +LONG +close_game (channel) + +LONG channel; +{ + Close (channel); + + return (0); /* no errors in AmigaDOS ? */ +} + + +/*------------------------------*/ +/* make_icon_file */ +/*------------------------------*/ + +LONG +make_icon_file () /* create a new save file icon, */ + /* called only after a successful SAVE */ +{ + LONG error; + LONG object; +/* INT len; */ + +/* diskobj (should have been) read into memory during init */ + + if (diskobj == NULL) + error = 1; + + else + { + +#if bug_DiskFull + +/* PROBLEM: PutDiskObj is crashing the machine when a disk-full error occurs. + First, make sure we have enough room for a new icon file. +*/ + +#define MaxIconSize 1024 /* actually ours is under 400 */ + + if (disk_newsave) /* if OLD save, space not an issue */ + { + disk_free = disk_bytes_avail (); + if (disk_free < MaxIconSize) return (1); + } + +/* (Alternate fix. The preceeding code fixes this problem better.) + + Do some preliminary error checking: Attempt to create a file with the + desired name, and put 1K of random data into it. +*/ + strcat (&savename, ".info"); /* desired name */ + error = create_file (); /* --> temp_channel */ + + if (!error) + { + error = write_file (temp_channel, 0, 1024, &savename); + + close_file (temp_channel); /* (no error codes) */ + + if (!error) + error = delete_file (); /* <-- savename */ + else delete_file (); + } + + len = strlen (&savename); + savename[len-5] = 0; /* chop off the ".info" */ + + if (error) /* if ANY error, fail now */ + return (error); + +#endif /* bug_diskfull */ + + +/* Everything seems OK, go ahead and make the Save icon */ + + diskobj->do_CurrentX = NO_ICON_POSITION; + diskobj->do_CurrentY = NO_ICON_POSITION; + + /* write icon file via same path as save file */ + + object = PutDiskObject (&savename, diskobj); + + if (object == NULL) + error = IoErr (); + else error = 0; + } + + return (error); +} + +/************************************************************************/ +/* Scripting */ +/************************************************************************/ + +/*------------------------------*/ +/* raw_script */ +/*------------------------------*/ + +INT +raw_script (buffer, length) /* send data to the printer device */ + +LONG buffer, length; +{ + INT error; + LONG seconds1, micros1; + LONG seconds2, micros2; + LONG actual_len; + +/* A problem: AmigaDOS (rev 1.0) isn't passing back printer error codes. + Each attempt to print when the printer isn't ready causes a 30 second + timeout. A series of these effectively hangs the game. + + To fix, use the delay to infer an error. If no error code is returned + but the delay exceeds 30 seconds, consider the printer not ready. +*/ + + CurrentTime (&seconds1, µs1); /* starting time */ + + actual_len = Write (print_file, buffer, length); + if (actual_len == length) + error = 0; + else error = 1; + +/* SIOStdReq.io_Data = (APTR) buffer; + SIOStdReq.io_Length = length; + + SIOStdReq.io_Command = CMD_WRITE; + DoIO (&SIOStdReq); + error = (SIOStdReq.io_Error); +*/ + CurrentTime (&seconds2, µs2); + + if (!error) /* says no error, but is it lying? */ + { + if ((seconds2 - seconds1) >= (30 - 1)) + error = 99; + } + + return (error); /* error code, zero if OK */ +} + +/*------------------------------*/ +/* script_init */ +/*------------------------------*/ + +/* + Two approaches to printing were tried; neither returns errors. The hairy + one crashes (CloseDevice) when multi-tasked, so use the simple one. +*/ + +LONG +script_init (open) /* initialize/uninitialize the printer */ + +INT open; +{ + LONG error; + + if (open) + { + print_file = Open ("PRT:", MODE_OLDFILE); + + if (print_file) /* zero means error */ + error = 0; + else error = 1; + +/* OpenDevice ("printer.device", 0, &SIOStdReq, 0); +*/ + /* set up the message port in the I/O request */ + +/* SMsgPort.mp_Node.ln_Type = NT_MSGPORT; + SMsgPort.mp_Flags = 0; + SMsgPort.mp_SigBit = AllocSignal (-1); + SMsgPort.mp_SigTask = (struct Task *) FindTask (NULL); + + AddPort (&SMsgPort); + SIOStdReq.io_Message.mn_ReplyPort = &SMsgPort; +*/ } + + else + { + if (print_file) /* call only if once opened */ + Close (print_file); + + error = 0; /* no close errors? */ + + /* clean up the various structures we created */ + +/* RemPort (&SMsgPort); + + FreeSignal (SMsgPort.mp_SigBit); + + CloseDevice (&SIOStdReq); +*/ } + + return (error); /* zero if none */ +} + +/*------------------------------*/ +/* script_open */ +/*------------------------------*/ + +INT +script_open (start) /* kernel issued request to start/stop scripting, + return status, either active or inactive */ +INT start; +{ + CHAR reset_seq[2]; + LONG error; + +/* starting, may need to open/reset the printer */ + + if (start) + { + if (!prt_inited) /* device never opened, do so now */ + { + error = script_init (TRUE); + + if (!error) + prt_inited = TRUE; /* okay, opened */ + } + + if (prt_inited && !prt_active) /* new start, reset printer */ + { + + reset_seq[0] = '\33'; /* ESC ($1B) */ + reset_seq[1] = 'c'; /* 'c' means reset */ + + error = raw_script (&reset_seq, 2); + + if (!error) + prt_active = TRUE; /* okay, active */ + } + } + + else /* if stop, flag it and shut down */ + { + prt_active = FALSE; + + if (prt_inited) + { + script_init (FALSE); prt_inited = FALSE; + } + } + + return (prt_active); +} + +/*------------------------------*/ +/* script_line */ +/*------------------------------*/ + +INT +script_line (buffer, length) /* script a line, tack on an EOL, + return error code (zero if none) */ +LONG buffer, length; +{ + CHAR eol_seq[2]; + INT error; + + if (length > 0) + error = raw_script (buffer, length); + else error = 0; + +/* The EOL seq used to be an "ISO standard" Esc-E (1B45), but under + AmigaDOS 1.2 this seems to have no effect. Changing to CRLF (0D0A) + works under both 1.1 and 1.2 except that the spacing is too wide + (resembles triple, used to resemble double). It appears that AmigaDOS + (/not/ the printer) automatically makes the initial CR a CRLF. So, + we will output only the CR and hope all printers are happy. + + By the way, a way to check script spacing is to compare it to what + AmigaDOS does after typing "TYPE textfile TO PRT:". Also, some + printer behavior can be controlled from User Preferences, like + margins and 6- or 8-line spacing. +*/ + if (!error) + { + eol_seq[0] = 0x0D; +/** eol_seq[1] = 0x0A; **/ + + error = raw_script (&eol_seq, 1); + } + return (error); +} + +/************************************************************************/ +/* Memory Management */ +/************************************************************************/ + +/* memory fudge factor -- leave this much free for transient use, + unless over-ridden by user. Resizing of windows especially triggers + large dynamic allocation requests. */ + +#if EZIP /* must be < 64K for 256K machine to load EZIP at all */ +#define mem_system 32*1024 /* enough for one other window */ + +#else +#define mem_system 64*1024 /* enough for several windows */ +#endif + +#define mem_default -1 /* user didn't specify memory use */ + +/*------------------------------*/ +/* c_maxmem */ +/*------------------------------*/ + +LONG +c_maxmem (game_total) /* return size of available memory pool */ + /* may be "doctored" (up or down) upon user request */ + +LONG game_total; /* maximum (buffered) memory we can use */ +{ + LONG game_used; + LONG mem_avail, mem_return; + + CHAR message[64]; + LONG len; + + mem_avail = (AvailMem (MEMF_PUBLIC)); + + if (mem_freereq == mem_default) + mem_return = mem_avail - mem_system; /* adjust it */ + else + { +/* got a request, use it */ + + if (mem_freereq < 0) mem_freereq = 0; + if (mem_freereq > mem_avail) mem_freereq = mem_avail; + + mem_return = mem_avail - mem_freereq; /* "doctor" it */ + +/* Request was made, so report our status to user. Want to show + the actual amount we will use here (if less than returned value). */ + + if (game_total > mem_return) + game_used = mem_return; + else + game_used = game_total; + + stcu_d (&message[0], game_used, 32); + strcat (&message, " bytes used"); + + /* if free will be more than requested, show why */ + + if (game_used == game_total) + strcat (&message, " (maximum)"); + strcat (&message, ", "); + + len = strlen (&message); + stcu_d (&message[len], (mem_avail - game_used), 32); + strcat (&message, " bytes free"); + + cur_row = 0; cur_column = 0; + write_cursor_pos (); /* top line for special msg */ + + len = strlen (&message); + line_out (&message, len); + + cur_row = rows - 1; /* reset cursor */ + write_cursor_pos (); + } + + return (mem_return); +} + +/*------------------------------*/ +/* c_getmem */ +/*------------------------------*/ + +LONG +c_getmem (nbytes) + +LONG nbytes; +{ +/* return (AllocMem (nbytes, MEMF_PUBLIC)); */ /* zero if failed */ + +/* This routine calls the AllocMem function, and also allocates a LINK NODE, + which saves the data needed for automatic de-allocation when we terminate. +*/ + + return (AllocRemember (&RememberKey, nbytes, MEMF_PUBLIC)); +} + +/************************************************************************/ +/* Initializations */ +/************************************************************************/ + +#if EZIP + +#define Peek1 (8+3) /* ZScreen scanlines showing behind ZWindow */ +#define Peek2 (8+5) /* WBScreen scanlines showing behind ZScreen */ + +/* The first margin is needed for the ZScreen slider and show/hide boxes. + Without these functions, task switching is crippled. + + The second margin is needed because of an Intuition problem that causes + all system alert boxes (e.g. insert disk X, disk X full, etc) to appear in + the WB screen, normally hidden by EZIP. This space permits the words + "System Alert" to show through to the user. +*/ + +#else + +#define Peek1 0 +#define Peek2 0 + +#endif + +/*------------------------------*/ +/* window_init */ +/*------------------------------*/ +INT +window_init (open) + +BOOL open; /* close if FALSE */ +{ + +#if EZIP +struct NewScreen NewZScreen; +#endif + +struct NewWindow NewZWindow; + + if (open) + { + +#if EZIP /* first create a custom screen */ + + ZTextAttr.ta_Name = "topaz.font"; + ZTextAttr.ta_YSize = TOPAZ_EIGHTY; /* EZIP */ + ZTextAttr.ta_Style = FS_NORMAL; + ZTextAttr.ta_Flags = FPF_ROMFONT; + + NewZScreen.LeftEdge = 0; /* required by Amiga */ + NewZScreen.Width = 640; /* high-res */ + + NewZScreen.TopEdge = 0 + Peek2; + NewZScreen.Height = 200 - Peek2; + NewZScreen.Depth = 1; /* 2 colors only */ + + NewZScreen.DetailPen = 0; + NewZScreen.BlockPen = 1; + NewZScreen.ViewModes = HIRES; + + NewZScreen.Type = CUSTOMSCREEN; + NewZScreen.Font = &ZTextAttr; + NewZScreen.DefaultTitle = NULL; + NewZScreen.Gadgets = NULL; + NewZScreen.CustomBitMap = NULL; + + ZScreen = (struct Screen *) OpenScreen (&NewZScreen); + + if (ZScreen == NULL) + return (1); /* nonzero means error, exit */ +#endif + /* create a window */ + + NewZWindow.LeftEdge = 0; /* full width initially */ + NewZWindow.Width = 640; + + NewZWindow.TopEdge = 0 + Peek1; /* (careful) */ + NewZWindow.Height = 200 - Peek2 - Peek1; + + NewZWindow.DetailPen = 0; + NewZWindow.BlockPen = 1; + NewZWindow.Title = NULL; +#if EZIP + NewZWindow.Flags = + BORDERLESS | SMART_REFRESH | ACTIVATE | + NOCAREREFRESH; + + NewZWindow.Type = CUSTOMSCREEN; + NewZWindow.Screen = ZScreen; +#else + NewZWindow.Flags = + WINDOWSIZING | WINDOWDRAG | WINDOWDEPTH | + SMART_REFRESH | ACTIVATE | NOCAREREFRESH; + + NewZWindow.Type = WBENCHSCREEN; + NewZWindow.Screen = NULL; +#endif + + NewZWindow.IDCMPFlags = NULL; + NewZWindow.FirstGadget = NULL; + NewZWindow.CheckMark = NULL; + NewZWindow.BitMap = NULL; + +#if EZIP + /* sizing ignored in EZIP */ +#else + NewZWindow.MinWidth = 200; + NewZWindow.MinHeight = 50; /* 4 lines for MORE algorithm */ + + NewZWindow.MaxWidth = 640; + NewZWindow.MaxHeight = 200 - Peek2 - Peek1; +#endif + ZWindow = (struct Window *) OpenWindow (&NewZWindow); + + if (ZWindow == NULL) + return (2); /* nonzero means error, exit */ + } + + else /* closing, clean up */ + { + if (ZWindow) + CloseWindow (ZWindow); +#if EZIP + if (ZScreen) + CloseScreen (ZScreen); +#endif + } + + return (0); +} + +/*------------------------------*/ +/* z_init */ +/*------------------------------*/ +INT +z_init () +{ + INT error; + + CHAR cur_prefs[1]; + CHAR old_YSize; + +/* open the Intuition Library */ + + IntuitionBase = (struct IntuitionBase *) + OpenLibrary ("intuition.library", 0); + + if (IntuitionBase == 0) + return (103); + +/* close the WorkBench screen, to free up memory */ + +#if EZIP /* (ZIP uses it, can't close it) */ +/* CloseWorkBench (); */ +#endif + +/* check/adjust the default font */ + + GetPrefs (&cur_prefs, 1); /* get user's default size */ + old_YSize = cur_prefs[0]; /* 9 or 8 */ + +#if EZIP + +/* temporarily adjust Prefs, if necessary, to ensure 80 columns + (seems that this must be done before creating the Custom screen) */ + + if (old_YSize != TOPAZ_EIGHTY) + { + cur_prefs[0] = TOPAZ_EIGHTY; + SetPrefs (&cur_prefs, 1, FALSE); /* force to 8 */ + } +#endif + +/* create and open a game window (and custom screen, for EZIP) */ + + error = window_init (TRUE); + if (error) + return (104); + +/* create a console device, attaching it to our window */ + + ZIOStdReq.io_Data = (CHAR *) ZWindow; + + if (OpenDevice ("console.device", 0, &ZIOStdReq, 0) != 0) + return (105); + +#if EZIP + +/* undo the temporary font setting, if it was changed above */ + + if (old_YSize != TOPAZ_EIGHTY) + { + cur_prefs[0] = old_YSize; + SetPrefs (&cur_prefs, 1, FALSE); /* restore user's choice */ + } +#endif + +/* initialize our internal text size variables */ + +#if EZIP + y_char = TOPAZ_EIGHTY; /* always 8 (80 columns) */ + x_char = 8; + +#else /* use the default fontsize */ + + y_char = old_YSize; /* either 8 or 9 */ + + if (old_YSize != TOPAZ_EIGHTY) + x_char = 10; /* can only be Topaz 60 */ + else x_char = 8; +#endif + + window_resized (); /* set up rows/columns globals */ + +/* set up the message port in the I/O request */ + + ZMsgPort.mp_Node.ln_Type = NT_MSGPORT; + ZMsgPort.mp_Flags = 0; + ZMsgPort.mp_SigBit = AllocSignal (-1); + ZMsgPort.mp_SigTask = (struct Task *) FindTask (NULL); + + AddPort (&ZMsgPort); + ZIOStdReq.io_Message.mn_ReplyPort = &ZMsgPort; + +/* and start reading ... */ + + ZRDStdReq = ZIOStdReq; /* copy the whole structure */ + queue_read (); + +/* etcetera */ + + split_row = 1; /* default for ZIP */ + + cur_row = rows - 1; cur_column = 0; + write_cursor_pos (); + + strcpy (saveback, "Story.Save"); /* initial default */ + + RememberKey = NULL; /* set up for memory allocation */ + +/* Get the Save Icon info during init. This avoids having to access the game + disk later, when it may have been removed from the drive */ + + IconBase = (struct IconBase *) OpenLibrary ("icon.library", 0); + + if (IconBase == NULL) + diskobj = NULL; + else + { + /* if info file not found, just return diskobj NULL */ + + diskobj = (struct DiskObject *) GetDiskObject ("Icon.Data"); + } + +#if EZIP + +/* Prevent a bug that puts garbage in the input line. Switching between + screens (EZIP and WB) seems to trigger unrequested "Raw Input Event" + reports of event types 17/18 (undocumented types). + + Disk event messages (type 16) were also appearing infrequently. +*/ + +send_control_seq ("17}"); /* "reset raw events" */ +send_control_seq ("18}"); +send_control_seq ("16}"); + +#endif + return (0); +} + +/*------------------------------*/ +/* z_exit */ +/*------------------------------*/ + +/* Clean up everything, in reverse order of creation. Any memory allocated + but not freed will be lost to eternity. +*/ + +VOID +z_exit () +{ + +/* be sure to shut down scripting, if indeed no one else did */ + + if (prt_inited) + script_init (FALSE); + +/* free the save file icon stuff, if it existed */ + + if (diskobj != NULL) + FreeDiskObject (diskobj); + + if (IconBase != NULL) + CloseLibrary (IconBase); + +/* de-allocate all memory claimed by 68K kernel initializations */ + + if (RememberKey != NULL) + FreeRemember (&RememberKey, TRUE); + +/* clean up the various console device structures */ + + RemPort (&ZMsgPort); + + FreeSignal (ZMsgPort.mp_SigBit); + + CloseDevice (&ZIOStdReq); + +/* close our window (and screen, for EZIP) */ + + window_init (FALSE); + +/* try to re-open WorkBench, if we closed it */ + +#if EZIP +/* OpenWorkBench (); */ +#endif + +/* lastly close the Intuition library */ + + CloseLibrary (IntuitionBase); +} + +/************************************************************************/ +/* Diagnostics (Temporary) */ +/************************************************************************/ + +#if ZDEBUG + +/*------------------------------*/ +/* z_test */ +/*------------------------------*/ + +z_test() +{ + CHAR mychr; + CHAR mystr[32]; + + c_maxmem (); c_getmem (16); /* test memory functions */ + c_getmem (16); c_maxmem (); + + FOREVER /* do input, output, scroll, until 'quit' */ + { + mychr = char_in (); + + if (mychr == 'q') break; /* leave the loop */ + + else if (mychr == 'z') /* print a string */ + { + strcpy (mystr, "xyz"); + line_out (mystr, strlen (mystr)); + + char_out (13); + } + else char_out (mychr); /* echo the char */ + } +} +#endif + +/************************************************************************/ +/* Top Level */ +/************************************************************************/ + +/*------------------------------*/ +/* main */ +/*------------------------------*/ + +INT +main (argc, argv) + +LONG argc; +CHAR *argv[]; /* an array of pointers */ +{ + INT error; + CHAR *arg1; + CHAR char1, char2; + +/* The only valid command line argument is F/n, where n is the minimum + number of bytes to leave in the free memory pool. + + If the argument is missing, or not a number, or if the game is run from + WorkBench, leave the default (mem_system, defined in c_maxmem). + + The game takes as much memory as it can use, within the above limit. +*/ + + mem_freereq = mem_default; /* assume no memory arg */ + + if ((argc > 1) && (argv != 0)) /* got one */ + { + arg1 = (CHAR *) argv[1]; + + char1 = *arg1++; + char2 = *arg1++; + + /* string should start with "F/" */ + + if ( + ((char1 == 'F') || (char1 == 'f')) + && (char2 == '/') + ) + + { + /* okay, convert string to a number */ + + if (stcd_i (arg1, &mem_freereq ) == 0) + + /* error, it's not a number */ + + mem_freereq = mem_default; + } + } + +/* set up the world */ + + error = z_init (); /* returns zero if OK */ + + if (!error) + { +#if ZDEBUG + z_test (); /* quick I/O test */ +#endif + START (); /* enter the ZIP kernel */ + } + + z_exit (); /* clean up the world */ + + return (error); /* fall back into controlling process */ +} + diff --git a/amiga/aterm.doc b/amiga/aterm.doc new file mode 100644 index 0000000..db7bb0e --- /dev/null +++ b/amiga/aterm.doc @@ -0,0 +1,434 @@ + + Aterm Users Guide + ----------------- + +OVERVIEW: + + Aterm is a general purpose terminal program that incorporates the basic +necessities, such as ASCII and protocol file transfer ability, as well as +features to make life easier for the user. Following is a list of the main +features of Aterm: + + > Baud rates - 300, 1200, 2400, 4800, 9600 + - initial rate set from Preferences. + + > File transfers - ASCII transmit/capture to any device. + Prompted transmit with user definable prompt. + - XMODEM (checksum) + - XMODEM (CRC) + - SuperKermit (Sliding Windows Kermit) + + > Duplex control - Full, Half, Echo. + + > Function keys - User definable. + - May be saved/loaded along with other parameters. + - Function keys may be chained/loaded from key + defintion. + - Function key files may be in S: directory. + - Provision for default function key file. + + > Autochop - Uses "hunk-end" padding during XMODEM send to + eliminate need for chopping at receiving end. + - Automatic pad stripping on XMODEM downloads. + - Properly pads/strips executable and ARCed files. + + > Flow control - Xon/Xoff selectable (enabled/disabled) + + > CHAT mode - A split screen mode that allows entry of one line + of text, which is sent as a "block" when a + is entered. Prevents mixing of incoming/outgoing + lines when used in CO. + + > Clock - Clock runs in title bar if present in + C: directory. + + > Phone book - Stores numbers (up to 10 per phone book file). + - Autodial from phone list. + - Optionally loads Function Key file from list. + + *============================* + +HARDWARE REQUIRED: + + Any RS232 modem that can be controlled with ASCII text strings, ie. Hayes or +compatible. Please note that Aterm does not require any other RS232 lines than +TXD, RXD, and SIGNAL GROUND. No other lines (DSR, CTS, CD, etc.) are checked. + + You may have to set your modem DIP switches to simulate DTR being present. + + + *============================* + +INSTALLING ATERM: + + There are a few configurations that you may want to use, depending solely +upon your personal preferences. + + 1. Aterm, AtermClock, Init.Key, and any other Function Key or Phone Book + files in CD (current directory). + + 2. Aterm in any other directory. + AtermClock in C: directory. + Init.Key and other FKey or Phone Book files in S: directory. + + 3. Aterm and AtermClock in C: directory. + Init.Key and other FKey or Phone Book files in S: directory. + + If you use Aterm a lot, option 3 is the easiest way to go. + + A brief explanation of the operation as applied to AtermClock and FKey files +will help you decide how to configure the environment. + + When Aterm loads, it will attempt to load AtermClock, which runs as a +separate task, from the current directory. If it not present in the CD, Aterm +will attempt to load it from the C: directory. (This is the 'c' directory on +your boot disk if you have not used ASSIGN to change it) If it is still not +found, Aterm will decide that you did not want the clock, and will tell you it +could not be found. Running without the clock in no way impacts Aterm's +operation. + + Aterm then attempts to load a file called Init.Key from the current +directory. If not found, it will try to load it from the S: directory. +(The 's' directory on your boot disk if you have not used ASSIGN to change it) +If it is not found, Aterm will set its own defaults, with the exception of the +baud rate, which will take the value specified by your Preferences (from a file +called 'system-configuration'). + + I use the last option, but you may prefer to use one of the others. I have +Aterm in my C: directory, with the name Aterm. While you can name Aterm +anything you desire, AtermClock and Init.Key must be as specified, or they will +not be found by Aterm. + + *============================* + + OPERATION + +GETTING STARTED: + +Invoke Aterm by the following methods... (assuming it is named Aterm) + +If Aterm is in the C: directory or if it is in the current directory: + +RUN Aterm + +If it is in another directory... (assume it is in DF1: directory 'terminals') + +RUN DF1:terminals/Aterm + + + NOTE: Capitals are optional. + + NOTE: The RUN is optional, but if used, greatly enhances the use of Aterm. It + will allow you to run other programs from the CLI, which may be seen by + simply clicking on the 'push to back' gadget on Aterm's screen. To return to + Aterm, click on the same gadget in the CLI screen. The CLI window may also be + left in front and resized. I often edit or print files, compile, or rearrange + disks while uploading or downloading. Unlike some commercial terminal + programs, Aterm does not make a pig of itself by hogging the printer port + (or any other system resources it isn't currently using). + + At this time, Aterm will load, then try to load the clock and default +function key file, and you will see a title screen. Provided your modem is +hooked up and powered on, you may now start to use it. + + The only way to have an Init.Key file is to create one with Aterm. To do +this, simply use the right (menu) button on the mouse to set up the parameters +that you will want to use. The settable parameters are: + + Prompt - Settable from the 'File' menu. + + Baud - Select the baud rate from the 'Baud' menu if you want Aterm to come up + with a different setting than that specified in your Preferences. + + Mode - Half, Full, or Echo, settable from the 'Mode' menu. + + Autochop - On/Off, settable from the 'Miscellaneous' menu. + + Xon/Xoff - On/Off, settable from the 'Miscellaneous' menu. + + Protocol - XMODEM, XMODEM CRC, Kermit, from the 'Miscellaneous' menu. + + You may also wish to define some function keys at this time. + + When you have everything set to your satisfaction, select 'FKey Save' from +the 'Miscellaneous' menu. You will be prompted for the file name you wish to +save the file under. Type one of the following, ending your input with a +. + +Init.Key + +S:Init.Key + +DF1:terminal/Init.Key + + Depending on your preferred configuration as outlined above. + + ---------------------------- + + At this time, you may also wish to set up a Phone Book. To do so, select +"Phone Book" from the Miscellaneous menu. You will be presented with a +contrasting window with a number of features. For now, we will just make a +default Phone Book file. + + The default Phone Book file is called Term.Phn, and will be found in the +S: directory along with the Init.key file, if you have decided to put it +there. You can have a Phone Book in any directory, but in order to have it +come up without having to type in the name, it should be "S:Term.Phn". + + Move the mouse pointer to the box immediately following "Dial Prefix:", +and click the left button. A cursor should appear in the box. The dial +prefix will be dependent upon the modem you are using. If it is one that +requires no prefix, simply use the and 'X' keys together to +erase the contents of the box. You may also enter any CTRL keys in the +normal way, including carriage returns (CTRL M). The prefix will be used for +all numbers on the list. + + Now enter the names of the BBS's or services you wish to call under the +"Name:" column, and the numbers for them under "Number:", using the mouse +pointer and left button to select each field in turn. + + When you are done, click the "Save" box, and your file will be saved under +the name "S:Term.Phn". More on the interaction between the Phone Book and +Function Key files later. + + ---------------------------- + + Next, a step by step tour of the items in the menus. + + Please note that any menu items followed by the symbol may be + selected by holding down the right key, and typing the key that is + shown immediately after the symbol in the menu. ie. C will + initiate ASCII capture mode, or terminate it if it is already capturing. + +File: + + ASCII Capture: You will be asked for a file name. The file named will be + opened for writing, and anything appearing on your screen will be written to + the file. CTRL characters are for the most part suppressed so that the file + may be edited with ED. If no path is given, the file will be written to your + current directory. Good results are obtained by capturing to RAM:, but care + must be taken to ensure that you have enough memory to hold the data. + You may capture to RAM:, DF0:, DF1:, DH0: PRT:, or any other device that + may be added to the Amiga at a later date. + To end the ASCII capture, you simply select ASCII capture again. + + ASCII Transmit: You will be asked for a file name. The file named will be + opened for reading, and the contents of the file will be sent out on the + modem port. If no path is given, the file must be in the current directory. + The ASCII transmit will be terminated when the file has been sent in its + entirety, and may be terminated earlier by selecting ASCII Transmit again. + The Promt character, if enabled acts as a 'throttle', and each time a + carriage return is sent from the file, Aterm will wait for the prompt + character before sending the next line. See entry for 'Prompt' below. + + Binary Receive: You will be asked for a file name. The file named will be + opened for writing, and as the file is received (using the protocol selected + in the 'Miscellaneous' menu), it will be written. The file may contain any + sort of data, and it will not be changed in any way. As with ASCII Capture, + you may Receive to any device (except the printer). + To abort the transfer early, press the key. The host may 'lock up' at + this time, but will usually respond to a few s, CTRL Zz, or CTRL Xs. + + Binary Transmit: You will be asked for a file name. The named file will be + opened for reading, and the contents of it will be sent unchanged to the host + or other terminal program via the protocol selected. Please note that the + host or other terminal program must be using the same protocol as you are. + The protocol used is dependent upon the setting of the protocol selection + in the Miscellaneous menu. + The transfer may be aborted early by pressing the key. + + Prompt: The prompt character is a user definable character that is used to + 'pace' the ASCII Transmit operation. If a 'full blast' transmission is + desired, simply type a '0' to set the prompt character to its "inactive" + state. To set it to any other character, press the key desired when asked to + supply a character. A common character to use is . The operation of + the prompted ASCII Transmit is as follows... Aterm will transmit 1 line of + the file, then wait until it receives the prompt character from the modem. + When The prompt character is received, the next line will be sent. + This helps to ensure that the host or other terminal is ready to receive + more data. + +Baud: + + Use the mouse to select any baud rate from 300 to 9600 baud. + +Mode: + + Half: Half duplex (not really duplex, but 'local echo', but who's being + picky?), will cause all characters sent to the modem to also be printed to + the screen. Use this setting if the host or other terminal does not echo + your own characters to you. + + Full: Use when the host or other terminal echos your characters to you. All + characters you type will be sent to the modem only, and you are depending on + the other end to send them back so you can see them. Switch to this setting + if you are getting double characters, ie. HHeelllloo.. + + Echo: Sends any characters received from the modem back out to the modem. + Use this setting if you wish to echo characters to the other end. Be careful + with this one, as it has some strange side effects if enabled during up or + downloads, or whenever you are connected to a host or other terminal that + also echos your characters. + +Miscellaneous: + + FKey Load: You will be asked for a file name. This file will be used as a + function key definition and 'settings' file. The file MUST be one previously + generated by Aterm with the FKey Save function. As with Init.Key, it may + either be in the current directory or the S: directory. If it is in neither, + you will have to specify the complete path. + + FKey Save: You will be asked for a file name. Your current function key + definitions and menu settings will be written to the named file. Please note + that if you want the file anywhere but the current directory, that you will + need to specify the path, ie. S:name or DF1:term/name. + + Define FKey: You will be asked for a function key string definition. This is + a string of characters that you wish to be sent when a function key is + pressed. First, you must tell Aterm which function key to define. This is + done by pressing the appropriate function key. You may only define the + function keys on the top row, and they are limited to 40 characters each. + There is a way to have a longer definition, as well as being able to define + more keys, but this will be covered in a later section. All characters are + legal in a function key definition, including all CTRL characters, , + , , etc. To end the definition, press any function key. The + reason for splitting the extra options in the definition is that they are + temporary 'quick and dirty' solutions, and will be changed in future + revisions to Aterm. + + Auto Chop: Set this to 'ON' to download executable, ARCed and text files. + Set to 'OFF" for 'problem files' that may have been uploaded with a program + that does not properly pad the end of the file. Files such as icons, + graphics, instrument, etc, may be chopped too short if they are autochopped. + In this case it it better to leave them unchopped and to attempt to chop them + to the right length offline. + + Xon/Xoff: Set this 'ON' for flow control. If you are sending to a host, it + will sometimes require you to wait while it is busy doing something else. To + signal that this is the case, it will send you an 'Xoff' ( CTRL S ), and when + it is ready for more data, it will send you an 'Xon' ( CTRL Q ). Sometimes, + however, especially when dealing with a packet switching network, certain + conditions may cause the network to send an 'Xoff', without a corresponding + 'Xon'. This will lock up the terminal program, and will mean that to recover, + you will have to reboot the Amiga , to recover. Line noise + may also send you an unintentional CTRL S. In these cases, select 'OFF' for + this option. + + Protocol: + + XModem: This is the 'plain' checksum Xmodem. + + Xmodem CRC: This is a better XModem protocol, with better error checking. + If you select this option, and the other side does not support it, there + will be a delay, then both sides will go back to the 'plain' XModem. To + avoid this delay, set Xmodem to match the other side. + + Kermit: This is an implementation of Sliding Windows Kermit, and is + superior in speed and error checking to XModem, especially over packet + switching networks. When a file transfer is started, both ends will + "negotiate for parameters", using the best of the Kermit protocols that + both ends can handle. Thus, this implementation may interact with any + lesser versions, using the best parameters that the lesser version can + handle. The authors would appreciate hearing about any compatibility + problems encountered with lesser versions. + + CHAT Mode: This gives you a 'split screen', a window along the bottom of the + screen that you can type a line of text into. The text you type is held in a + buffer and will only be sent when you end the line with a . While the + line is being typed, the upper part of the screen will still show any + characters arriving from the modem port. While the line is being sent, no + characters arriving from the modem will be printed. This does wonders for the + readability of the screen while participating in real time CO. When + connected to another terminal, and you are chatting, the worst that can + happen is that your line interrupts the other line only once, instead of + having your characters and those from the other side mixed randomly + throughout the line. + + Phone Book: Allows you to enter names and numbers of services or BBS's that + you call frequently. More than one phone book file may be accessed. Enter the + name of the file in the "File:" box. + + There is an interaction between Function Key files and Phone Book entries. + Though you can load Function Key files from the menu, you can also load them + from the Phone Book. Simply make sure that the name of the Function Key file + is the same as the name in the "Name:" field of the number you want to dial. + For instance, if there is a Function Key file called "CIS" either in the + current directory or in the S: directory, AND if an entry in the Phone Book + "Name:" field is "CIS", then when you click on the DIAL box to the left of + that name, Aterm will attempt to load the file "CIS" as a Function Key + file, first from the current directory, then from the S: directory. + + NOTE: If for any reason you do not wish to load a Function Key file, just + precede the name with a space in the "Name:" field. Aterm will take this as + a signal that you do not want a Function Key file, and will not even look for + it. + + *============================* + + ADDENDUM + +FKEY OPTIONS: + + In addition to the standard characters allowed in function keys, there are a +few special keys that will, when the function key is sent, perform some special +tasks. These are designed to extend the function keys, making them for all +practical purposes, of unlimited length, and giving you the ability to change +your key definitions automatically as you move from area to area within a +network or bulletin board. + + NOTE: The method used to implement these special functions is temporary, + constituting a 'quick and dirty' solution. The authors would be glad to hear + from Aterm users about any ideas on implementation of this feature. + + The special options are , , and . + + In all cases, these must be the last thing defined as part of a function key +definition (you'll see why in a moment). They are activated as follows. + + Select 'Define FKey' from the menu (or use the D ). + Press the function key to be defined. + Enter whatever text you want sent to the modem prior to the execution of the + special command. + Press the key. + Now press one of... + Any number key (1-0) + The 'l' key (lower case L) + The 'L' key (upper case l) + + The visual indication of these will be (in the same order)... + (where n is the number pressed) + + + + The meanings and additional information to be supplied for each + function are: + + - This will cause the currently defined function key specified by 'n' to + be sent/executed. '0' specifies FKey 10. + + - This one MUST be followed by the name of a file that contains a + function key definition. Upon executing the this command, Aterm will attempt + to load this file as a function key definition. Handy for 'switching the + context' of your function keys when going to a different section of a + network or BBS. + + - MUST be followed by a single digit (1-0), then immediately by a + file name. The file named must be a function key definition file. Aterm will + attempt to load this file as a function key definition file, and if loaded, + will then execute the newly defined key specified by the number immediately + after the symbol. + + NOTE: If you wish to include a real character in a function key + defintiton, just press the key twice. + + The best way to find out about the uses for these functions is to play with +them. + + *============================* + +Aterm Documentation file (C) November 1986 by Larry Phillips + +Documentation Revisions for Aterm 7.3 (C) Dec. 1986 by Larry Phillips + +Compuserve 76703,4322 + \ No newline at end of file diff --git a/amiga/ax.asm b/amiga/ax.asm new file mode 100644 index 0000000..0e2512d --- /dev/null +++ b/amiga/ax.asm @@ -0,0 +1,100 @@ + + TTL XZIP INTERPRETER FOR COMMODORE AMIGA + +** NOLIST * DON'T LIST THE SYSTEM EQUATES +** INCLUDE '' +** LIST + + SECTION ZDATA,DATA * DEFINE TWO SEGS FOR AMIGA + DC.W 0 + SECTION ZCODE,CODE + NOP + SECTION ZDATA * AND START IN DATA ... + + XREF _columns + XREF _cur_column + XREF _rows + XREF _cur_row + XREF _split_row + XREF _wind1 + +** XREF _w0font +** XREF _w1font + XREF _color * color/mono flag + + XREF _marg_left + XREF _marg_right + XREF _xmouse * mouse position (char units, zero origin) + XREF _ymouse + + XREF _game_ref + XREF _save_ref + XREF _savename + XREF _saveback + XREF _actlen +** XREF _undoflag * [no menus for Amiga] + + SECTION ZCODE + + XDEF _ZSTART +** XDEF _mov_mem * (char *p1, *p2; LONG len) +** XDEF _clr_mem * (char *p1; LONG len) + +** XREF _write_cursor_pos * dead, access vars directly +** XREF _read_cursor_pos + XREF _erase_eol + XREF _clear_lines + + XREF _setup_input + XREF _event_in * was _char_in, MacttyIn + XREF _char_out + XREF _line_out + + XREF _highlight + XREF _set_color +** XREF _op_picinf +** XREF _op_display + XREF _german_convert + + XREF _open_game + XREF _close_game + +** XREF _file_select * [currently in 68K] + XREF _new_default + XREF _drive_default + XREF _make_icon_file + + XREF _exist_file + XREF _create_file + XREF _open_file + XREF _close_file + XREF _delete_file + XREF _read_file + XREF _write_file + + XREF _script_open * PrInit + XREF _script_line * PrLine + + XREF _random_seed + XREF _md_sound + XREF _window_resized + XREF _unhide_screen + + XREF _c_getmem + XREF _c_maxmem +** XREF MacInit +** XREF QuitGame + + XREF _end_sound * END-OF-SOUND CHECK + XREF _int_key + +* ---------------------------------------------------------------------------- +* PROGRAM +* ---------------------------------------------------------------------------- + + INCLUDE "AX1.asm" + INCLUDE "AX2.asm" + INCLUDE "AX3.asm" + INCLUDE "AX4.asm" + + END diff --git a/amiga/ax1.asm b/amiga/ax1.asm new file mode 100644 index 0000000..c50387a --- /dev/null +++ b/amiga/ax1.asm @@ -0,0 +1,1291 @@ + +* ___________________________________________________________________________ +* +* XZIP INTERPRETER FOR THE COMMODORE AMIGA +* +* INFOCOM, INC. COMPANY CONFIDENTIAL -- NOT FOR DISTRIBUTION +* +* WRITTEN BY DUNCAN BLANCHARD +* ___________________________________________________________________________ +* + +* ASSEMBLY FLAGS + +* THE FIRST TWO FLAGS EXIST ONLY FOR HISTORICAL REASONS +* [XZIP CAN'T BE CONDITIONALLY ASSEMBLED AS EZIP OR CLASSIC ZIP] + +EZIP EQU 0 * [ASSEMBLES EZIP CODE WHEN CLEAR] +CZIP EQU -1 * [ASSEMBLES CLASSIC CODE WHEN CLEAR] +DEBUG EQU -1 * ASSEMBLES DEBUGGING CODE WHEN CLEAR + +* --------------------------------------------------------------------------- +* XZIP-AMIGA MODIFICATION HISTORY: +* --------------------------------------------------------------------------- +* +* 09 NOV 87 DBB PORTED FROM MAC +* 17 NOV 87 DBB FIXED OPPRNT/OPINTBL TO USE PAGING +* FIXED [MORE] TO RTS WHEN 1 OR 0 LINES IN W0 +* 08 JAN 88 DBB NEW CURSOR-CONTROL ROUTINES ('C') +* FIXED PRINTT/COPYT PAGING BUG +* 'F/n' COMMAND SWITCH CAN BE IN ANY POS NOW ('C') +* SUPPORT ANY SCREENSIZE (e.g. 256-LINE EURO) ('C') +* IN SAVE/RESTORE, PREFIX DEFAULT NAME WITH CWD +* DURING 68K INIT, PRELOAD PAGE BUFFERS +* XZIP 'A' FROZEN +* 22 JAN 88 DBB ADDED OPSOUND 'COUNT' ARG +* ADDED SOUND INTERRUPTS (GAMINT) +* XZIP 'B' FROZEN + +* XZIP-MAC MODIFICATION HISTORY: +* +* 14 JUL 87 DBB PORTED FROM ST +* 14 SEP 87 DBB XZIP 'A' FROZEN +* 05 OCT 87 DBB (PASCAL) ROW/COL VARS ALLOW BIG-SCREEN WINDOW +* TIMEOUT COUNTER STOPS WHEN DA ACTIVE +* PUTLIN1 <-> PUTLIN +* OPINPUT/OPPRNT CALL PUTLIN (FIX HINT-WRAP BUG) +* FKEYS THAT AREN'T TCHARS REJECTED IN OPREAD +* ADDED UNDO AND MOUSE SUPPORT CHECKS +* 1-CHAR INPUT DISABLES MENU "CMD-STRINGS" +* 13 OCT 87 DBB DESKTOP RESTORE SETS SL REFRESH BIT +* BUFFER NOW DUMPED IN CURSET/SPLIT/SCREEN +* 14 OCT 87 DBB TO ALLOW SCREEN1 BUFFERING: +* BUFFER ALSO ZEROED FOR ABOVE 3 (CURSOR MOVED) +* SIZEQP NO LONGER SHRINKS BUF SIZE (ST ITALIC HACK) +* XZIP 'B' FROZEN + +* XZIP-ATARI MODIFICATION HISTORY: +* +* 02 FEB 87 DBB MODIFIED EZIP +* 21 MAY 87 DBB ADDED LOWCORE, MOUSE VARS +* 02 JUN 87 DBB MOVED DUPNAM CHECK (_exist_file) INTO C +* 25 JUN 87 DBB CHANGED OPFONT TO IGNORE REDUNDANT FONT CHANGES +* FIXED STACK BUG, RESTORE VS. TIMER INTERRUPT +* 13 JUL 87 DBB BUFFER FLUSHED IN OPSCRN, OPDIRO, OPERASE, OPCLEAR +* CHKDSK MODIFIED FOR FULL PRELOAD SITUATION, +* RESTART, $VER MAKE SPECIAL CHECKS FOR GAME DISK +* XZIP 'A' FROZEN + +* ZIP/EZIP (ATARI) MODIFICATION HISTORY: +* +* 02 AUG 85 ZIP A FROZEN +* 09 AUG 85 CLSGAM CHECKS WHETHER GAME FILE WAS OPENED +* 09 AUG 85 REBUILT OBJECT FILE WITH NEW LIBRARIES, +* INCREASED MACHINE STACK TO 2K (IN ZIPSTART) +* 09 AUG 85 ZIP B FROZEN +* EZIP A FROZEN +* 10 FEB 86 PURE PRELOAD MAY EXCEED 32K (PUT, PUTB, PTSIZE) +* OPSPLT (EZIP) NO LONGER CLEARS SCREEN +* 10 APR 86 CHANGED PUTCHR (SPECIAL HANDLING FOR TABLE OUTPUT) +* ADDED SCRNAM, SCRIPTS SAVE/RESTORE FILENAMES +* 18 APR 86 CHANGED NXTLIN/BUFOUT/LINOUT. BUFOUT CALLS NXTLIN +* SO [MORE] IS TIMED CORRECTLY DURING BOLDFACE, ETC +* CHANGED OPATTR AND DQUE INIT, FOR ITALICS HACK +* FIXED GETMEM, PREVENTS ST BUG WITH ODD MEM REQUEST +* 08 MAY 86 FIXED QUECHR (QCX2A), ALLOW FOR EMPTY [DUMPED] BUFFER +* CHANGED OPREAD, ONLY OVERFLOW WORDS ARE FLUSHED +* 13 MAY 86 LINES(A6) NOW NORMALLY RESET TO ZERO, UPDATED INCHR +* OPINPUT CHECKS VOBUFF(A6) +* OPSPLIT CHECKS MAXIMUM SIZE OF split_row +* NXTLIN TURNS OFF HIGHLIGHTING BEFORE PRINTING [MORE] +* COMBINED READLN AND INCHR +* EZIP B FROZEN + +* XZIP: SUGGESTIONS FOR FURTHER OVERHAUL +* +* - MAKE ALL OPERATORS TAKE ARGS IN SLOTS (INDEXED OFF A6, NOT A0) RATHER +* THAN REGISTERS, NOW THAT MANY ARE OPTIONALS. PASS A1 -> FIRST ARG +* FOR CONVENIENCE ((A1)++). REDUCES NEED TO SAVE/RESTORE ARGS, SIMPLIFIES +* USAGE. +* +* - IMPLEMENT HIGHLIGHTING USING SPECIAL CHARS, PUT DIRECTLY INTO THE OUTPUT +* STREAM/BUFFER. LOW-LEVEL OUTPUT ROUTINE SCANS FOR THESE SPECIALS. +* AVOIDS NEED FOR MUCH SPECIAL FLUSHING OF BUFFER. +* + +* --------------------------------------------------------------------------- +* REGISTER CONVENTIONS +* --------------------------------------------------------------------------- + +* GENERALLY, SINGLE ARGUMENTS ARE PASSED IN D0 OR A0. SINGLE VALUES ARE +* LIKEWISE RETURNED IN D0 OR A0. IN ANY CASE, THESE ARE SCRATCH REGISTERS +* AND NEED NOT BE PRESERVED. ALL OTHER REGISTERS, EXCEPT WHERE OTHERWISE +* SPECIFIED, MUST BE PRESERVED ACROSS EACH SUBROUTINE CALL. NOTE THAT +* TOP-LEVEL ROUTINES, OPx ROUTINES, ARE EXCLUDED FROM THIS RESTRICTION. + +* DEDICATED REGISTERS: +* A7 = SYSTEM SP +* A6 = FRAME POINTER FOR ZIP VARIABLES *** STATIC *** +* A5 = unused (SYSTEM FRAME PTR ON MAC) +* A4 = VIRTUAL SP + +* --------------------------------------------------------------------------- +* INDEXING BASE FOR THE DISPATCH TABLE +* --------------------------------------------------------------------------- + +ZBASE NOP + +** DATA * ST LATTICE: BEGIN THE DATA SEGMENT +** DC.W 0 * (KLUGE TO AVOID AN OBSCURE LINKER BUG ASSOCIATED +** CODE * WITH SUCCESSIVE 'DC' STATEMENTS) + +* --------------------------------------------------------------------------- +* GENERAL MACRO DEFINITIONS +* --------------------------------------------------------------------------- + +* MACRO ZERO +* MOVEQ #0,%1 * CLEAR A REGISTER QUICKLY (BOTH WORDS) +* ENDM + +* MACRO SOB * SUBTRACT ONE AND BRANCH IF NOT ZERO +* SUBQ.W #1,%1 +* BNE.S %2 +* ENDM + +* PRIOR TO CALLING A PASCAL FUNCTION, MUST MAKE SPACE ON THE STACK +* FOR THE RESULT (WORD OR LONG) +* >> FOR 'C' FUNCTIONS THIS IS A NOP << + +RESWORD MACRO +** SUBQ.L #2,SP * QUICKER INSTR +** TST.W -(SP) + ENDM + +RESLONG MACRO +** SUBQ.L #4,SP + ENDM + +* AFTER CALLING A PASCAL FUNCTION, POP THE RESULT FROM THE STACK INTO D0. +* >> IN 'C' THE RESULT IS ALWAYS PASSED IN D0, BUT FLAGS MAY NOT BE SET << + +POPWORD MACRO +** MOVE.W (SP)+,D0 + TST.W D0 * [C ONLY: SET FLAGS] + ENDM + +POPLONG MACRO +** MOVE.L (SP)+,D0 + TST.L D0 + ENDM + +* WHEN CALLING ANY EXTERNAL ROUTINE, THESE ARE THE REGISTERS THAT +* NEED TO BE PRESERVED. + +SAVEREGS MACRO + MOVEM.L D1/A1,-(SP) * NOT SAVED BY AMIGA LATTICE +** MOVEM.L D1-D2/A1,-(SP) * NOT SAVED BY MAC PASCAL + ENDM + +RESTREGS MACRO + MOVEM.L (SP)+,D1/A1 * (DON'T AFFECT FLAGS) +** MOVEM.L (SP)+,D1-D2/A1 * (DON'T AFFECT FLAGS) + ENDM + +FLUSH MACRO + ADDA.W #\1,SP * ARG1 = BYTES (2, 4, ETC) + ENDM + +* --------------------------------------------------------------------------- +* GENERAL EQUATES +* --------------------------------------------------------------------------- + +ARG1 EQU 2 * ARGUMENT OFFSETS IN ARGUMENT BLOCK +ARG2 EQU 4 +ARG3 EQU 6 +ARG4 EQU 8 + + IFEQ EZIP + +VCHARS EQU 9 * MAX CHARS IN AN EZIP VOCAB WORD +ZCHARS EQU 6 * EZIP: BYTES PER ZWORD + +OPLEN EQU 63*2 * OBJECT PROPERTY DEFAULT TABLE LENGTH +OLEN EQU 14 * OBJECT LENGTH + +LOC EQU 6 * PARENT +NEXT EQU 8 * NEXT SIBLING +FIRST EQU 10 * FIRST CHILD +PROP EQU 12 * PROPERTY TABLE POINTER + +PMASK EQU $003F * PROPERTY NUMBER IS LOW 6 BITS (OF FIRST ID BYTE) +PLBIT EQU 6 * PROPERTY LENGTH BIT (IF LENGTH IS TWO OR ONE) + + ENDC + IFEQ CZIP + +VCHARS EQU 6 * MAX CHARS IN A ZIP VOCAB WORD +ZCHARS EQU 4 * CZIP: BYTES PER ZWORD + +OPLEN EQU 31*2 * OBJECT PROPERTY DEFAULT TABLE LENGTH +OLEN EQU 9 * OBJECT LENGTH + +LOC EQU 4 * PARENT +NEXT EQU 5 * NEXT SIBLING +FIRST EQU 6 * FIRST CHILD +PROP EQU 7 * PROPERTY TABLE POINTER + +PMASK EQU $001F * PROPERTY NUMBER IS LOW 5 BITS (OF SINGLE ID BYTE) +PLBIT EQU 5 * PROPERTY LENGTH BIT (LOWEST OF 3 LENGTH BITS) + + ENDC + +* --------------------------------------------------------------------------- +* ZIP VARIABLES - INDEXED OFF A6 +* --------------------------------------------------------------------------- + +ZORKID EQU 0-2 * UNIQUE GAME AND VERSION ID +TIMEMD EQU ZORKID-2 * HOURS/MINUTES MODE FLAG +ENDLOD EQU TIMEMD-2 * END OF PRELOAD (FIRST PAGED BLOCK NUMBER) +PURBOT EQU ENDLOD-2 * END OF IMPURE (FIRST PURE BLOCK NUMBER) + +VOCTAB EQU PURBOT-4 * VOCABULARY TABLE POINTER +OBJTAB EQU VOCTAB-4 * OBJECT TABLE POINTER +GLOTAB EQU OBJTAB-4 * GLOBAL TABLE POINTER +WRDTAB EQU GLOTAB-4 * FREQUENT WORD TABLE POINTER + +RBRKS EQU WRDTAB-4 * POINTER TO STRING OF READ-BREAK CHARS +ESIBKS EQU RBRKS-4 * END OF SELF-INSERTING BREAK CHARS (+1) + +VWLEN EQU ESIBKS-2 * NUMBER OF BYTES IN A VOCAB WORD ENTRY +VWORDS EQU VWLEN-2 * NUMBER OF VOCABULARY WORDS +VOCBEG EQU VWORDS-4 * POINTER TO FIRST VOCAB WORD +VOCEND EQU VOCBEG-4 * POINTER TO LAST VOCAB WORD + +PAGTAB EQU VOCEND-4 * POINTER TO PAGE INFORMATION TABLE +PAGES EQU PAGTAB-4 * POINTER TO START OF PAGE BUFFERS + +PAGTOT EQU PAGES-2 * NUMBER OF PAGE BUFFERS +MAXLOD EQU PAGTOT-2 * TOTAL BLOCKS IN GAME +MAXFLG EQU MAXLOD-2 * FLAG SET IF GAME FILE IS WHOLLY PRELOADED + +TOPSP EQU MAXFLG-4 * TOP OF SYSTEM STACK +STKBOT EQU TOPSP-4 * BOTTOM OF GAME STACK + +ZPC1 EQU STKBOT-2 * ZORK PC, BLOCK POINTER (RELATIVE ADDRESS) +ZPC2 EQU ZPC1-2 * ZORK PC, BYTE POINTER +NARGS EQU ZPC2-2 * (LOW BYTE) OPTIONAL ARG COUNT +ZLOCS EQU NARGS-4 * POINTER TO LOCALS (ABSOLUTE ADDRESS) + +RSEED1 EQU ZLOCS-2 * RANDOM NUMBER SEED, HIGH WORD +RSEED2 EQU RSEED1-2 * LOW WORD +RCYCLE EQU RSEED2-2 * ZERO MEANS NORMAL, OTHERWISE TOP OF SEQUENCE +RCONST EQU RCYCLE-2 * CURRENT PLACE IN SEQUENCE + +BUFFER EQU RCONST-4 * START OF PRELOADED GAME CODE +ARGBLK EQU BUFFER-18 * 8 ARGS MAX FOR EZIP, PLUS COUNT +DEFBLK EQU ARGBLK-10 * DEFAULT ARGUMENT BLOCK (4 ARGS + COUNT) + +*** + +RDWSTR EQU DEFBLK-10 * ASCIZ STRING BUFFER (9 CHARS MAX FOR EZIP) +RDZSTR EQU RDWSTR-6 * ZSTR BUFFER (3 WORDS MAX FOR EZIP) + +RDBOS EQU RDZSTR-4 * BEGINNING OF INPUT STRING BUFFER +RDEOS EQU RDBOS-4 * END OF INPUT STRING BUFFER (+1) +RDRET EQU RDEOS-4 * RETURN TABLE + +VWSORT EQU RDRET-2 * FLAG: SET IF VOCTAB SORTED +VWBOFF EQU VWSORT-2 * INITIAL OFFSET FOR BINARY SEARCH + +WRDOFF EQU VWBOFF-2 * OFFSET INTO WORD TABLE FOR CURRENT SET + +* VIRTUAL I/O DEVICES + +VOCONS EQU WRDOFF-2 * SET FOR SCREEN OUTPUT +VOPRNT EQU VOCONS-2 * SET FOR SCRIPTING +VOSTAT EQU VOPRNT-2 * SET FOR STATUS LINE OUTPUT +VOTABL EQU VOSTAT-2 * SET FOR TABLE OUTPUT +VOFILE EQU VOTABL-2 * SET FOR FILE OUTPUT + +VIKEYB EQU VOFILE-2 * SET FOR KEYBOARD INPUT +VIFILE EQU VIKEYB-2 * SET FOR FILE INPUT + +VOBUFF EQU VIFILE-2 * SET IF OUTPUT TO SCREEN IS BUFFERED +VIECHO EQU VOBUFF-2 * SET IF INPUT IS ECHOED + +DQUE EQU VIECHO-4 * DISPLAY QUE PARAMETER BLOCK +SQUE EQU DQUE-4 * SCRIPT QUE PARAMETER BLOCK + +TABOUT EQU SQUE-4 * POINTS TO CURRENT TABLE OUTPUT BUFFER (EZIP) +TABPTR EQU TABOUT-4 * POINTS TO NEXT TABLE POSITION + +CURPAG EQU TABPTR-4 * CURRENT PAGE (WHERE ZPC IS) POINTER +CURBLK EQU CURPAG-2 * CURRENT BLOCK, USUALLY SAME AS ZPC1 +CURTAB EQU CURBLK-4 * CURRENT PAGE TABLE POINTER + +RTIME EQU CURTAB-4 * REFERENCE TIME, NOW USES 2 WORDS +LPAGE EQU RTIME-2 * LAST REFERENCED PAGE NUMBER +LPLOC EQU LPAGE-4 * AND ITS CORE LOCATION +LPTAB EQU LPLOC-4 * AND ITS TABLE POINTER + +TWAIT EQU LPTAB-2 * DELAY, IN 1/10'S SEC, BETWEEN TIMEOUTS +TFUNC EQU TWAIT-2 * FUNCTION TO CALL UPON TIMEOUT +TCLOCK EQU TFUNC-4 * REF TIME (60THS) OF LAST CHANGE IN TCOUNT +TCOUNT EQU TCLOCK-2 * DELAY REMAINING (10THS) + +SFUNC EQU TCOUNT-2 * FUNCTION TO CALL UPON SOUND-END +SCOUNT EQU SFUNC-2 * #OPS TO WAIT BEFORE NEXT SOUND-END CHECK +*** + +* WIND1 * [DEAD, CALL GETSCRN] +ROW0 EQU SCOUNT-2 * WINDOW 0 (SAVED) CURSOR POSITION +COL0 EQU ROW0-2 +ROW1 EQU COL0-2 * WINDOW 1 (SAVED) CURSOR POSITION +COL1 EQU ROW1-2 + +LINES EQU COL1-2 * LINES DISPLAYED SINCE LAST INPUT +INLAST EQU LINES-2 * INPUT SETS IT, OUTPUT CLEARS IT, QUIT CHECKS +CHRTOT EQU INLAST-2 * TOTAL CHARS INPUT SO FAR DURING OPREAD + +GAMFIL EQU CHRTOT-2 * REF NUMBER OF OPENED GAME FILE +SAVFIL EQU GAMFIL-2 * REF NUMBER OF OPENED SAVE FILE + +MSAVEB EQU SAVFIL-4 * PTR TO A RAM BUFFER FOR ISAVE/IRESTORE +MSAVEF EQU MSAVEB-2 * FLAG, SET FOR ISAVE/IRESTORE + +*** + +FONT EQU MSAVEF-2 * NONZERO WHEN USING SPECIAL (MONOSPACED) FONT +MACBUF EQU FONT-4 * NEW VALUE FOR ENDBUF WHEN FONTSIZE CHANGES + +APPARM EQU MACBUF-4 * HANDLE TO APPLICATION PARAMETERS +SHOWVE EQU APPARM-4 * POINTER TO "VERSION" STRING, ZERO IF NONE + +*** + +DBZPC1 EQU SHOWVE-2 * HALT WHEN ZPC REACHES THIS ADDRESS +DBZPC2 EQU DBZPC1-2 +DBINST EQU DBZPC2-2 * HALT WHEN NEXT INSTRUCTION HAS THIS VALUE + +DBTOT1 EQU DBINST-4 * TOTAL EXECUTION COUNT +DBTOT2 EQU DBTOT1-4 * DESIRED EXECUTION COUNT + +*** + +ZVLEN EQU 0-DBTOT2 * TOTAL LENGTH OF ZIP'S VARIABLES FRAME + +*-------------------------------------------------------------------------- +* GENERALIZED OUTPUT-FOLDING PARAMETER BLOCK +*-------------------------------------------------------------------------- + +* THE QUECHR ROUTINE IS CALLED WITH A POINTER TO A STRUCTURE CONTAINING +* THE VARIABLES BELOW. THIS ARRANGEMENT ALLOWS FOR THE EXISTANCE OF MORE THAN +* ONE STRUCTURE, USEFUL IF DISPLAYED TEXT AND SCRIPTED TEXT ARE TO FOLD AT +* DIFFERENT POINTS. + +* THE STRUCTURE IDENTIFIES TWO ACTION ROUTINES. THE OUTPUT FUNCTION +* DUMPS THE BUFFER WHEN IT BECOMES FULL. THE SIZE FUNCTION ALLOWS FOR THE +* HANDLING OF PROPORTIONALLY SPACED TEXT. + +* THE LAST TWO VARIABLES ARE CURRENTLY IGNORED, BUT MIGHT BE USEFUL +* FOR IMPLEMENTING RECALCULATION OF THE FOLD POINTS FOR A PARAGRAPH OF TEXT, +* AS WHEN A WINDOW CHANGES SIZE. + +* DATA STRUCTURE FOR QUEUE-PARAMETERS BLOCK: + +BUFPTR EQU 0 * START OF BUFFER +BUFSIZ EQU 4 * MAXIMUM UNITS IN BUFFER + +NXTPTR EQU 6 * CURRENT POSITION WITHIN BUFFER +CURSIZ EQU 10 * CURRENT UNITS IN BUFFER + +SIZFUN EQU 12 * GIVEN A CHAR, RETURNS UNIT SIZE +OUTFUN EQU 16 * GIVEN BUFPTR & ENDPTR, DUMPS BUFFER, ADDS CR +RETFUN EQU 20 * (UNUSED -- THIS SHOULD ADD THE CR) + +DUMPED EQU 24 * WAS BUFFER EMPTIED (WITHOUT CR) BEFORE FULL? +AUTOCR EQU 25 * APPEND A CR TO EACH BUFFER DUMP? *** YES +KEEPSP EQU 26 * DON'T DISCARD TRAILING SPACE? *** NO + +QPLEN EQU 28 * LENGTH OF BLOCK (ALWAYS EVEN) + +* --------------------------------------------------------------------------- +* ZIP DEBUGGING -- INCLUDE FOR DEVELOPMENT ONLY +* --------------------------------------------------------------------------- + +* GO UNTIL ONE OF THE FOLLOWING CONDITIONS OCCURS: +* () ZPC REACHES A GIVEN ADDRESS +* () ZPC POINTS TO A GIVEN INSTRUCTION +* () A GIVEN NUMBER OF INSTRUCTIONS ARE EXECUTED + + IFEQ DEBUG + +DBTEST RTS + + ENDC * END OF CONDITIONAL ASSEMBLY + + + PAGE +* --------------------------------------------------------------------------- +* INITIALIZATIONS +* --------------------------------------------------------------------------- + +* LOW-CORE GAME VARIABLES + +PVERS1 EQU 0 * ZVERSION VERSION BYTE +PVERS2 EQU 1 * ZVERSION MODE BYTE +PZRKID EQU 2 * ZORK ID +PENDLD EQU 4 * ENDLOD (BYTE OFFSET) +PSTART EQU 6 * START +PVOCTB EQU 8 * VOCTAB +POBJTB EQU 10 * OBJTAB +PGLOTB EQU 12 * GLOTAB +PPURBT EQU 14 * PURBOT +PFLAGS EQU 16 * USER FLAGS WORD +PSERNM EQU 18 * SERIAL NUMBER (6 BYTES) +PWRDTB EQU 24 * WRDTAB +PLENTH EQU 26 * LENGTH (EZIP QUADS, ZIP WORDS) +PCHKSM EQU 28 * CHECKSUM (ALL BYTES STARTING WITH BYTE 64) +PINTWD EQU 30 * INTERPRETER ID/VERSION +PSCRWD EQU 32 * SCREEN SIZE, ROWS/COLUMNS + +* FOR XZIP: + +PHWRD EQU 2*17 * WIDTH OF DISPLAY, IN PIXEL UNITS +PVWRD EQU 2*18 * HEIGHT OF DISPLAY, IN PIXEL UNITS +PFWRD EQU 2*19 * FONT HEIGHT, WIDTH +PLMRG EQU 2*20 * LEFT MARGIN, IN PIXEL UNITS +PRMRG EQU 2*21 * RIGHT MARGIN, IN PIXEL UNITS +PCLRWRD EQU 2*22 * COLOR, BACKGROUND/FOREGROUND +PTCHARS EQU 2*23 * BYTE PTR, TABLE OF TERMINATING CHARACTERS +PCRCNT EQU 2*24 * CR COUNTER +PCRFUNC EQU 2*25 * CR FUNCTION +PCHRSET EQU 2*26 * BYTE PTR, CHAR SET TABLE +PLCTBL EQU 2*27 * BYTE PTR, LOW-CORE VARS EXTENSION TABLE + +* LOW CORE EXTENSION TABLE VARIABLES +* (WORD OFFSETS -- ACCESS THROUGH 'LOWCORE' ROUTINE) + +PLCLEN EQU 0 * TABLE LENGTH, IN WORDS +PMLOCX EQU 1 * MOUSE LOCATION WHEN LAST CLICKED +PMLOCY EQU 2 + +* "PFLAGS" BIT DEFINITIONS + +FSCRI EQU 0 * INTERPRETER CURRENTLY SCRIPTING +FFIXE EQU 1 * FIXED-WIDTH FONT NEEDED +FSTAT EQU 2 * REQUEST FOR STATUS LINE REFRESH +FDISP EQU 3 * GAME USES DISPLAY OPS +FUNDO EQU 4 * GAME USES UNDO +FMOUS EQU 5 * GAME USES MOUSE +FCOLO EQU 6 * GAME USES COLOR + +* MICRO'S ID CODE, INTERPRETER VERSION LETTER (WAS IN OPVERI, DEAD) + + SECTION ZDATA +INTWRD DC.B 4 * MACHINE ID FOR COMMODORE AMIGA + DC.B 'B' * XZIP INTERPRETER VERSION +SUBVER DC.W 0 * INTRPRETER SUB-VERSION, ZERO TO DISABLE + SECTION ZCODE + +* INITIAL SET OF READ BREAK CHARS -- SPACE, TAB, CR, <.>, <,>, + + SECTION ZDATA +IRBRKS DC.B $20,$09,$0D,$2E,$2C,$3F,0 * ASCIZ + SECTION ZCODE + +ZMVERS EQU 5 * XZIP Z-MACHINE VERSION NUMBER +STKLEN EQU 512*2 * LENGTH OF GAME STACK (MULTIPLE OF 512) +PAGMIN EQU 2 * MINIMUM # PAGES (NEEDED BY $VER) + +* ---------------------- +* _ZSTART +* ---------------------- + +_ZSTART LINK A6,#-ZVLEN * CREATE A FRAME FOR ZIP VARIABLES + MOVE.L A6,A0 * TOP OF FRAME + + MOVE.W #ZVLEN/2,D0 +STRX1 CLR.W -(A0) * ALL INITIAL VALUES ARE ZERO + SUBQ.W #1,D0 + BNE STRX1 + + MOVE.L SP,TOPSP(A6) * SAVE THE SP FOR RESTARTS + LEA ZVARS,A0 + MOVE.L A6,(A0) * COPY A6 FOR EXTERNAL CALLS INTO ZIP ROUTINES + +*** careful about error msgs before screen & buffers are initialized ... + + MOVE.W #1,VOCONS(A6) * OUTPUT ERRORS TO SCREEN FOR NOW (NO BUFFER) + MOVE.W #1,VIECHO(A6) * INPUT IS NORMALLY ECHOED + +*** MOVE.W #1,WIND1(A6) * AVOID PUTCHR/TSTSCR (CZIP ONLY) BUG DURING INIT + BSR SYSIN1 * OPEN GAME FILE, WINDOW, ETC + +*** READ GAME BLOCK 0 INTO A TEMP STACK BUFFER ... + + SUBA.W #512,SP * CREATE THE BUFFER + MOVE.L SP,A4 * SAVE POINTER HERE FOR NOW + + MOVE.L A4,A0 + CLR.W D0 * BLOCK 0 + BSR GETBLK * GET IT + +*** CHECK FOR ID CODE ... + + CMPI.B #ZMVERS,(A4) * PROPER Z-MACHINE VERSION? + BEQ.S STRX3 * YES + +STRX2 CLR.W D0 * SOMETHING WRONG, DIE + LEA MSGZMV,A0 + BRA FATAL * 'Wrong Z-machine' + SECTION ZDATA +MSGZMV DC.B 'Wrong Z-machine version',0 + SECTION ZCODE + +STRX3 MOVE.W PZRKID(A4),ZORKID(A6) * UNIQUE GAME ID, CHECKED BY "RESTORE" + + IFEQ CZIP + BTST #0,PVERS2(A4) * PROPER BYTE-SWAP MODE? + BNE.S STRX2 * NO, FAIL + + CLR.W TIMEMD(A6) * ASSUME SCORE-MODE FOR STATUS LINE + BTST #1,PVERS2(A4) * TIME MODE REQUESTED? + BEQ.S STRX6 * NO + ADDQ.W #1,TIMEMD(A6) * YES, SET TIME-MODE FLAG + ENDC + + MOVEQ #0,D0 + MOVE.W PPURBT(A4),D0 * GET PURBOT (BYTES) + BSR BYTBLK * ROUND UP TO NEXT BLOCK BOUNDARY + MOVE.W D0,PURBOT(A6) * HERE FOR UNDO, BELOW ... + +* Allocate an "undo" buffer, if indicated. This allocation currently occurs +* /before/ the preload/paging allocations. This might want to be modified +* so that it gets skipped if it would leave either () not enough for preload, +* or () a critically low (defined in some heuristic way) amount for paging. +* [Generally not a problem on 512K machines.] + + MOVEQ #0,D1 * ASSUME NO UNDO + MOVE.W PFLAGS(A4),D0 + BTST #FUNDO,D0 * DOES THIS GAME USE UNDO? + BEQ.S STRX3B * NO + +STRX3A MOVE.W PURBOT(A6),D0 * BLOCKS + ADDQ.L #STKLEN/512,D0 + BSR BLKBYT * TOTAL BYTES NEEDED FOR AN UNDO-SAVE + BSR GETM * GET IT, WITHOUT ERROR TRAPPING + BEQ.S STRX3B * ZERO: NOT ENOUGH MEM + + CLR.W (A0) * OK, MARK THE BUFFER AS EMPTY + MOVE.L A0,MSAVEB(A6) * AND STORE PTR + MOVEQ #1,D1 * SUCCESS +STRX3B MOVE.W D1,D0 + BSR SETUNDO * SET FLAG FOR PASCAL (MENU DISPLAY) + +*** CHECK MEMORY, SET ENDLOD & PAGTOT, DO PRELOAD + +STRX4 BSR MEMAVAIL * DETERMINE HOW MUCH FREE MEMORY EXISTS + MOVE.L D0,D7 * REMEMBER THE AMOUNT + + MOVEQ #0,D0 + MOVE.W PLENTH(A4),D0 * LENGTH OF GAME FILE (WORDS OR QUADS) + ADD.L D0,D0 + IFEQ EZIP + ADD.L D0,D0 * BYTES + ENDC + + MOVE.L D0,D1 + BSR BYTBLK * TOTAL BLOCKS IN GAME FILE + MOVE.W D0,MAXLOD(A6) * SAVE FOR DEBUGGING (& TABLE INITS) + MOVE.L D1,D0 + + CMP.L D7,D0 * ENOUGH ROOM TO PRELOAD ENTIRE GAME? + BLT.S LOAD1 * YES + + MOVEQ #0,D0 + MOVE.W PENDLD(A4),D0 * LENGTH OF PRELOAD SEGMENT (BYTES) + CMP.L D7,D0 * ENOUGH ROOM FOR IT? + BLT.S LOAD2 * YES + + BRA MEMERROR * NO, FAIL + +* WE HAVE MEGA-MEMORY, PRELOAD EVERYTHING ... + +LOAD1 BSR BYTBLK * LENGTH OF GAME FILE (IN BLOCKS) + MOVE.W D0,ENDLOD(A6) * MAXIMIZE THE PRELOAD + + MOVE.W #PAGMIN,PAGTOT(A6) * MINIMIZE THE PAGING SPACE (FOR $VER) + MOVE.W #1,MAXFLG(A6) * SET FLAG + BRA.S LOAD3 + +* WE HAVE LIMITED MEMORY, PRELOAD ONLY WHAT'S NEEDED + +LOAD2 SUB.L D0,D7 * FIRST DETERMINE MEMORY LEFT AFTER PRELOAD + BSR BYTBLK + MOVE.W D0,ENDLOD(A6) * LENGTH OF PRELOAD (IN BLOCKS) + + DIVU #512+8,D7 * PAGES AVAIL (ALLOW 8 BYTES PER TABLE ENTRY) + CMPI.W #2,D7 + BGE.S LOADX1 + MOVEQ #2,D7 * MUST HAVE AT LEAST TWO (FOR $VERIFY) +LOADX1 MOVE.W D7,PAGTOT(A6) * MAXIMIZE THE PAGING SPACE + +LOAD3 MOVE.W ENDLOD(A6),D0 * SPACE NEEDED FOR PRELOAD, IN BLOCKS + BSR BLKBYT * CONVERT TO BYTES + BSR GETMEM * GET IT + + MOVE.L A0,BUFFER(A6) * SAVE POINTER + MOVE.L A0,A4 * ALSO HERE FOR REMAINING INIT + + MOVE.W ENDLOD(A6),D1 * NUMBER OF BLOCKS TO PRELOAD + CLR.W D0 * STARTING WITH BLOCK 0 + BSR GTBLKS * READ THEM IN + +*** CLR.W WIND1(A6) * RESTORE NORMAL VALUE (AFTER PREV KLUGE) + +*** ABSOLUTIZE MAJOR TABLE POINTERS + +STRX6 MOVE.W PVOCTB(A4),D0 * RELATIVE VOCAB TABLE POINTER + BSR RELABS * ABSOLUTIZE IT + MOVE.L A0,VOCTAB(A6) * AND SAVE IT + + MOVE.W POBJTB(A4),D0 * RELATIVE OBJECT TABLE POINTER + BSR RELABS + MOVE.L A0,OBJTAB(A6) + + MOVE.W PGLOTB(A4),D0 * RELATIVE GLOBAL TABLE POINTER + BSR RELABS + MOVE.L A0,GLOTAB(A6) + + MOVE.W PWRDTB(A4),D0 * RELATIVE WORD TABLE POINTER + BSR RELABS + MOVE.L A0,WRDTAB(A6) + +*** ALLOCATE MEMORY FOR Z STACK + + MOVE.L #STKLEN,D0 + BSR GETMEM + MOVE.L A0,STKBOT(A6) * THIS WILL BE BOTTOM OF GAME STACK + +*** INITIALIZE LINE BUFFER, SCRIPT BUFFER + +SCRLEN EQU 80 * LENGTH OF SCRIPT BUFFER (FIXED FOR NOW) +MAXLEN EQU 256 * MAX LENGTH OF LINE BUFFER + + BSR MAXSCRN * GET SCREEN WIDTH (COLS) IN D1 +* *** MOVE.W #MAXLEN,D1 * [MAC XZIP: NO RE-SIZEABLE WINDOW] + MOVE.W D1,D2 + LEA LINOUT,A1 * SCREEN DISPLAY FUNCTION + LEA CHSIZ,A2 + + BSR INITQP * SET UP DISPLAY QUEUE STUFF + MOVE.L A0,DQUE(A6) * SAVE BLOCK POINTER + + MOVE.W #SCRLEN,D1 * SCRIPTING SIZE, NEVER CHANGES + MOVE.W D1,D2 + LEA SCROUT,A1 * SCRIPTING DISPLAY FUNCTION + LEA CHSIZ,A2 + + BSR INITQP * SET UP SCRIPT QUEUE STUFF + MOVE.L A0,SQUE(A6) * SAVE THIS POINTER TOO + +* AND SET UP MACBUF ... + +* ALLOCATE AND SET UP BREAK-CHAR TABLE + + MOVE.L #64,D0 * MAX BREAK CHARS + BSR GETMEM * ALLOCATE BUFFER FOR BREAK-CHAR TABLE + MOVE.L A0,RBRKS(A6) + + MOVE.L VOCTAB(A6),A1 * (DEFAULT) VOCAB TABLE + CLR.W D0 + MOVE.B (A1)+,D0 * FIRST BYTE OF VOCTAB IS # OF SI BREAK CHARS + BRA.S STRX11 * (ZERO CHECK) + +STRX10 MOVE.B (A1)+,(A0)+ * TRANSFER SI BREAKS FIRST +STRX11 DBF D0,STRX10 + MOVE.L A0,ESIBKS(A6) * REMEMBER END OF SI BREAKS + + LEA IRBRKS,A2 * THESE ARE THE "NORMAL" BREAK CHARS +STRX12 MOVE.B (A2)+,(A0)+ * TRANSFER THEM TOO + BNE STRX12 * ASCIZ + +*** ALLOCATE MEMORY FOR PAGE TABLE & BUFFERS + + MOVE.W PAGTOT(A6),D0 * PREVIOUSLY CALCULATED NUMBER OF PAGE BUFFERS + MULU #8,D0 * 8-BYTE TABLE ENTRY FOR EACH PAGE + ADDQ.L #2,D0 * ALLOW FOR THE END MARK + BSR GETMEM + MOVE.L A0,PAGTAB(A6) * THIS WILL BE START OF PAGE TABLE + + MOVE.W PAGTOT(A6),D0 * PREVIOUSLY CALCULATED NUMBER OF PAGE BUFFERS + MULU #512,D0 * 512 BYTES EACH + BSR GETMEM + MOVE.L A0,PAGES(A6) * PAGES THEMSELVES WILL START HERE + +*** INITIALIZE THE PAGE TABLE + + MOVE.W PAGTOT(A6),D0 * PREVIOUSLY CALCULATED NUMBER OF PAGE BUFFERS + MOVE.L PAGTAB(A6),A0 + +STRX16 MOVE.W #-2,(A0)+ * BLOCK (NO BLOCK "$FFFE") + CLR.L (A0)+ * REF TIME IS ZERO + CLR.W (A0)+ * THIS SLOT UNUSED (BUT 8 BYTES SPEEDS CALCS) + SUBQ.W #1,D0 + BNE STRX16 + MOVE.W #-1,(A0) * MARK THE END OF THE TABLE (NO BLOCK "$FFFF") + + MOVE.W #-1,CURBLK(A6) * MUST INIT THESE PAGING VARS TOO! + MOVE.W #-1,LPAGE(A6) + +* 'PRIME' THE BUFFERS WITH THE FIRST N PAGES +* [MIGHT BE A BIT FASTER IF WE LOADED BUFFERS AND MUNGED TABLES DIRECTLY, +* TO AVOID ALL THE IMPLICIT LRU SEARCHING.] +* [BE SURE MAXLOD IS INITED] + +STRX16A MOVE.W ENDLOD(A6),D1 * FIRST PAGE TO GET + MOVE.W D1,D2 + ADD.W PAGTOT(A6),D2 * LAST PAGE TO GET (+1) + + CMP.W MAXLOD(A6),D1 * BUT WAS THE WHOLE FILE PRELOADED? + BEQ.S STRX17 * YES, SKIP OUT + + CMP.W MAXLOD(A6),D2 * (MAKE SURE WE NEVER READ TOO FAR) + BLE.S STRX16B + MOVE.W MAXLOD(A6),D2 + +STRX16B CMP.W D2,D1 * DONE? + BGE.S STRX17 * YES + + MOVE.W D1,D0 + BSR GETPAG * FETCH A PAGE INTO NEXT AVAILABLE BUFFER + ADDQ.W #1,D1 + BRA.S STRX16B * LOOP + +* ETCETERA ... + +STRX17 BSR GTSEED * INITIALIZE THE RANDOM NUMBER SEEDS + MOVE.W D0,RSEED1(A6) + SWAP D0 + MOVE.W D0,RSEED2(A6) * PUT HIGH WORD HERE, "RELATIVELY CONSTANT" + + MOVE.W #1,VOBUFF(A6) * BEGIN BUFFERING OUTPUT + + BSR ENDTITLE * PAUSE FOR TITLE SCREEN, IF SHOWING + BRA.S START1 + +* ---------------------- +* RESTRT +* ---------------------- + +* RESTART EXECUTION HERE + +RESTRT MOVE.L BUFFER(A6),A0 + MOVE.W PFLAGS(A0),-(SP) * PRESERVE THE USER FLAGS (SCRIPT ETC) + + CLR.W D0 * REREAD ALL OF THE IMPURE STUFF + MOVE.W PURBOT(A6),D1 + BSR GTBLKS + + MOVE.L BUFFER(A6),A0 + MOVE.W (SP)+,PFLAGS(A0) * RESTORE FLAGS + +START1 MOVE.L TOPSP(A6),SP * RESET SYSTEM STACK POINTER + + MOVE.L DQUE(A6),A0 + MOVE.L BUFPTR(A0),NXTPTR(A0) * INITIALIZE OUTPUT BUFFER POINTER + + MOVE.L STKBOT(A6),A4 + ADDA.W #STKLEN,A4 * INITIALIZE GAME STACK POINTER + MOVE.L A4,ZLOCS(A6) * INITIALIZE POINTER TO LOCALS/FRAME + MOVE.L BUFFER(A6),A2 + + IFEQ EZIP +*** ORI.B #2,PVERS2(A2) * DISPLAY + ORI.B #32+16+8+4,PVERS2(A2) * SOUND, MONOSPACE, ITALIC, BOLD + + MOVEQ #0,D0 + MOVEQ #0,D1 + BSR MDCOLOR * GET DEFAULT COLORS (BACK/FORE) + MOVE.W D0,PCLRWRD(A2) * STORE HERE + TST.W D1 * CHECK COLOR/MONO FLAG + BEQ.S STR1X2 + ORI.B #1,PVERS2(A2) * [AMIGA:] COLOR PALETTE AVAILABLE + +STR1X2 MOVE.W INTWRD,PINTWD(A2) * SET INTERPRETER ID/VERSION WORD + CLR.W RCYCLE(A6) * ALWAYS RESTART WITH NORMAL RANDOMNESS + + MOVE.W #$0101,PFWRD(A2) * AMIGA XZIP: 1 CHAR UNIT = 1 PIXEL + BSR MAXSCRN * SCREEN SIZE + MOVE.W D0,PVWRD(A2) + MOVE.W D1,PHWRD(A2) + + ASL.W #8,D0 * ROWS IN HIGH BYTE, COLUMNS IN LOW + MOVE.B D1,D0 + MOVE.W D0,PSCRWD(A2) * SET SCREEN-PARAMETERS WORD + + BSR EZERR * CHECK OBJTAB ALIGNMENT + ENDC + IFEQ CZIP + BSET #5,PVERS2(A2) * SPLIT-SCREEN IS AVAILABLE + ENDC + + MOVE.W PSTART(A2),D0 * GET STARTING LOCATION + BSR BSPLTB * SPLIT BLOCK AND BYTE POINTERS + + MOVE.W D0,ZPC1(A6) * INITIALIZE THE ZPC + MOVE.W D1,ZPC2(A6) + BSR NEWZPC * GET THE PAGE TO EXECUTE + +* SYSIN2 SHOULD BE THE /LAST/ CALL BEFORE NXTINS, BECAUSE OF STACK HACKING +* (FOR KLUDGY TIMEOUTS) IN OPREST. + + BSR SYSIN2 * MAC -- BUT LOAD A SAVED GAME IF REQUESTED + BRA NXTINS * TALLY HO + + IFEQ EZIP + +* ---------------------- +* EZERR +* ---------------------- + +* MAKE SURE OBJ TABLE IS WORD ALIGNED FOR EZIP/XZIP + +EZERR MOVE.L BUFFER(A6),A0 + MOVE.W POBJTB(A0),D0 * OBJECT TABLE BASE + BTST #0,D0 * WORD ALIGNED? + BNE.S EZERX1 * NO, FAIL + RTS + +EZERX1 CLR.W D0 + LEA MSGEZR,A0 + BRA FATAL * 'OBJTAB alignment error' + + SECTION ZDATA +MSGEZR DC.B 'OBJTAB alignment error',0 + SECTION ZCODE + + ENDC + + PAGE +* --------------------------------------------------------------------------- +* MISC FUNCTIONS +* --------------------------------------------------------------------------- + +* ------------------------------ +* COPYB +* ------------------------------ + +* COPY BYTES +* GIVEN A0 -> SRC, D0 = LEN, A1 -> DEST + +CPBX1 MOVE.B (A0)+,(A1)+ * COPY THEM +COPYB DBF D0,CPBX1 * ZERO CHECK << ENTRY POINT >> + RTS + +* ------------------------------ +* COPYS +* ------------------------------ + +* COPY A STRING, AND TACK ON A NULL BYTE +* GIVEN A0 -> SRC, A1 -> DEST, D0 = LEN, D1 = MAX LEN + +COPYS CMP.W D1,D0 * LEN WITHIN MAX? + BLE.S CPSX1 + MOVE.W D1,D0 * NO, TRUNCATE IT +CPSX1 BRA.S CPSX3 * ZERO CHECK + +CPSX2 MOVE.B (A0)+,(A1)+ +CPSX3 DBF D0,CPSX2 + CLR.B (A1) * ASCIZ + RTS + +* -------------------------- +* COMPS +* -------------------------- + +* COMPARE STRINGS, PTRS IN A0 AND A1, LENGTHS IN D0.W +* RETURN FLAGS, 'EQ' IF SAME + +COMPS TST.W D0 + BLE.S CMPSX4 * ZERO CHECK +CMPSX2 CMP.B (A0)+,(A1)+ + BNE.S CMPSX4 * MISMATCH, RETURN "DIFFERENT" + SUBQ.W #1,D0 + BNE.S CMPSX2 * IF DONE, RETURN "SAME" +CMPSX4 RTS + +* ---------------------- +* STRLEN +* ---------------------- + +* FIND LENGTH OF AN NULL-TERMINATED STRING, POINTER IN A0 +* RETURN POINTER IN A0, LENGTH IN D0 + +STRLEN MOVE.L A0,-(SP) * SAVE START +STRLX1 TST.B (A0)+ * SEARCH FOR NULL + BNE.S STRLX1 + MOVE.L A0,D0 * FOUND IT + SUBQ.L #1,D0 * BACKUP TO THE NULL + MOVE.L (SP)+,A0 * RETURN ORIGINAL POINTER + SUB.L A0,D0 * RETURN LENGTH + RTS + +* ------------------------------ +* RELABS +* ------------------------------ + +* CONVERT A RELATIVE (BYTE) PTR (D0.W) TO ABSOLUTE (A0) + +RELABS SWAP D0 + CLR.W D0 * ZERO THE HIGH WORD (NO SIGN-EXTENDING) + SWAP D0 * [14 cycles vs 16] + MOVE.L BUFFER(A6),A0 + ADDA.L D0,A0 * ABSOLUTIZE THE LOCATION + RTS + +* ---------------------- +* BLKBYT +* ---------------------- + +* GIVEN A ZIP BLOCK COUNT IN D0.W, RETURN A BYTE COUNT IN D0.L + +BLKBYT EXT.L D0 * CLEAR HIGH WORD + SWAP D0 + LSR.L #7,D0 * x512 + RTS + +* ---------------------- +* BYTBLK +* ---------------------- + +* GIVEN A BYTE COUNT IN D0.L, RETURN A ZIP BLOCK COUNT IN D0.W, ROUNDING UP + +BYTBLK MOVE.W D0,-(SP) * SAVE LOW WORD + LSR.L #8,D0 + LSR.L #1,D0 * EXTRACT BLOCK NUMBER + + ANDI.W #$01FF,(SP)+ * EXACT MULTIPLE OF 512? + BEQ.S BYTBX1 * YES + ADDQ.W #1,D0 * NO, ROUND UP TO NEXT BLOCK +BYTBX1 RTS + +* ---------------------- +* LOWCORE +* ---------------------- + +* USE THIS ROUTINE TO ACCESS LOW-CORE EXTENSION-TABLE VARS + +* GIVEN D0 = VAR (WORD OFFSET) +* RETURN A0 (MAY BE ODD) -> VAR, AND FLAGS (ZERO IF INVALID VAR) + +LOWCORE MOVEM.L D1,-(SP) + MOVE.W D0,D1 + MOVE.L BUFFER(A6),A0 + MOVEQ #0,D0 * GET EXTENSION TABLE OFFSET (MAY BE >32K, ODD) + MOVE.W PLCTBL(A0),D0 * EXISTS? + BEQ.S LWCX1 * NO, ERROR + + ADDA.L D0,A0 * TABLE BASE + BSR GTAWRD * TABLE LEN (WORDS) + CMP.W D0,D1 * ENOUGH? + BGT.S LWCX1 * NO, ERROR + + SUBQ.L #2,A0 + ADD.W D1,D1 * BYTE OFFSET + ADDA.W D1,A0 * POINT TO DESIRED VAR + BRA.S LWCX2 * NONZERO FLAGS + +LWCX1 MOVEQ #0,D0 * ZERO FLAGS +LWCX2 MOVEM.L (SP)+,D1 * DON'T DISTURB FLAGS + RTS + +* ---------------------- +* GTAWRD +* ---------------------- + +* GET CORE WORD, ABSOLUTE POINTER IN A0, RETURN THE WORD IN D0, UPDATE POINTER + +GTAWRD + MOVE.B (A0)+,D0 * GET HIGH-ORDER BYTE, ADVANCE A0 + ASL.W #8,D0 * POSITION IT + MOVE.B (A0)+,D0 * GET LOW-ORDER BYTE, ADVANCE A0 + RTS + +* ---------------------- +* PTAWRD +* ---------------------- + +* UPDATE CORE WORD, ABSOLUTE POINTER IN A0, NEW VALUE IN D0 + +PTAWRD + MOVE.B D0,1(A0) * STORE LOW-ORDER BYTE + ASR.W #8,D0 + MOVE.B D0,(A0) * STORE HIGH-ORDER BYTE + RTS + +* --------------------------------------------------------------------------- +* LOW LEVEL ZIP FUNCTIONS +* --------------------------------------------------------------------------- + +* ---------------------- +* GETBYT +* ---------------------- + +* GET A BYTE FROM GAME, BLOCK-POINTER IN D0, BYTE-POINTER IN D1, RESULT IN D2 +* UPDATE D0 AND D1 TO REFLECT BYTE GOTTEN + +GETBYT MOVE.W D0,-(SP) + CMP.W ENDLOD(A6),D0 * IS THIS A PRELOADED LOCATION? + BGE.S GETBX1 * NO + + BSR BLKBYT * YES, RECONSTRUCT POINTER (MAY EXCEED 32K) + OR.W D1,D0 + + CLR.W D2 * CLEAR THE UNWANTED HIGH BYTE + MOVE.L BUFFER(A6),A0 * ABSOLUTE POINTER + MOVE.B 0(A0,D0.L),D2 * GET THE DESIRED BYTE + BRA.S GETBX2 + +GETBX1 BSR GETPAG * FIND THE PROPER PAGE (POINTER RETURNED IN A0) + CLR.W D2 * CLEAR THE UNWANTED HIGH BYTE + MOVE.B 0(A0,D1.W),D2 * GET THE DESIRED BYTE + +GETBX2 MOVE.W (SP)+,D0 + ADDQ.W #1,D1 * UPDATE BYTE-POINTER + CMPI.W #512,D1 * END OF PAGE? + BNE.S GETBX3 * NO, DONE + + CLR.W D1 * YES, CLEAR BYTE-POINTER + ADDQ.W #1,D0 * AND UPDATE BLOCK-POINTER +GETBX3 RTS + +* ---------------------- +* GETWRD +* ---------------------- + +* GET A WORD FROM GAME, BLOCK-POINTER IN D0, BYTE-POINTER IN D1, RESULT IN D2 + +GETWRD BSR GETBYT * GET HIGH-ORDER BYTE + ASL.W #8,D2 * POSITION IT + MOVE.W D2,-(SP) * SAVE IT + + BSR GETBYT * GET LOW-ORDER BYTE + OR.W (SP)+,D2 * OR IN THE OTHER BYTE + RTS + +* ---------------------- +* NXTBYT +* ---------------------- + +* GET THE NEXT BYTE, RETURN IT IN D0 + +NXTBYT MOVE.L CURPAG(A6),A0 * INDEX INTO CURRENT PAGE + ADDA.W ZPC2(A6),A0 + CLR.W D0 * CLEAR HIGH REGISTER AND + MOVE.B (A0),D0 * GET THE NEXT BYTE + + ADDQ.W #1,ZPC2(A6) * UPDATE PC + CMPI.W #512,ZPC2(A6) * END OF PAGE? + BLT.S NXTBX1 * NO + + MOVE.W D0,-(SP) + BSR NEWZPC * YES, UPDATE PAGE + MOVE.W (SP)+,D0 +NXTBX1 RTS * AND RETURN + +* ---------------------- +* NXTWRD +* ---------------------- + +* GET THE NEXT WORD, RETURN IT IN D0 + +NXTWRD BSR NXTBYT * GET HIGH-ORDER BYTE + ASL.W #8,D0 * SHIFT TO PROPER POSITION + MOVE.W D0,-(SP) * SAVE IT + + BSR NXTBYT * GET LOW-ORDER BYTE + OR.W (SP)+,D0 * OR IN THE OTHER BYTE + RTS + +* ---------------------- +* GETARG +* ---------------------- + +* GET AN ARGUMENT GIVEN ITS TYPE IN D0 + +GETARG SUBQ.W #1,D0 * EXAMINE ARGUMENT + BLT.S NXTWRD * 0 MEANT LONG IMMEDIATE + BEQ.S NXTBYT * 1 MEANT SHORT IMMEDIATE + + BSR NXTBYT * 2 MEANT VARIABLE, GET THE VAR + TST.W D0 * STACK? + BNE.S GETV1 * NO, JUST GET THE VAR'S VALUE + MOVE.W (A4)+,D0 * YES, POP THE STACK + RTS + +* ---------------------- +* GETVAR +* ---------------------- + +* GET VALUE OF A VARIABLE, VAR IN D0, VALUE RETURNED IN D0 + +GETVAR TST.W D0 * STACK? + BNE.S GETV1 * NO + MOVE.W (A4),D0 * YES, GET TOP-OF-STACK (DON'T POP) + RTS + +GETV1 CMPI.W #16,D0 * LOCAL? + BGE.S GETVX2 * NO + MOVE.L ZLOCS(A6),A0 * YES, POINT TO PROPER STACK ELEMENT + ADD.W D0,D0 + SUBA.W D0,A0 * LOCALS BUILD DOWN + MOVE.W (A0),D0 * GET IT + RTS + +GETVX2 SUB.W #16,D0 * GLOBAL, ADJUST FOR LOCALS + MOVE.L GLOTAB(A6),A0 * POINT TO PROPER GLOBAL TABLE ELEMENT + ADD.W D0,D0 + ADDA.W D0,A0 + BRA GTAWRD * GET IT AND RETURN + +* ---------------------- +* PUTVAR +* ---------------------- + +* UPDATE VALUE OF A VARIABLE, VAR IN D0, NEW VALUE IN D1 + +PUTVAR TST.W D0 * STACK? + BNE.S PUTVX1 * NO + MOVE.W D1,(A4) * YES, UPDATE TOP-OF-STACK (DON'T PUSH) + RTS + +PUTVX1 CMPI.W #16,D0 * LOCAL? + BGE.S PUTVX2 * NO + MOVE.L ZLOCS(A6),A0 * YES, POINT TO PROPER STACK ELEMENT + ADD.W D0,D0 + SUBA.W D0,A0 * LOCALS BUILD DOWN + MOVE.W D1,(A0) * UPDATE IT + RTS + +PUTVX2 SUB.W #16,D0 * GLOBAL, ADJUST FOR LOCALS + MOVE.L GLOTAB(A6),A0 * POINT TO PROPER GLOBAL TABLE ELEMENT + ADD.W D0,D0 + ADDA.W D0,A0 + MOVE.W D1,D0 + BRA PTAWRD * UPDATE IT AND RETURN + +* ---------------------- +* PUTVAL, BYTVAL +* ---------------------- + +* RETURN VAL IN D0 TO LOCATION SPECIFIED BY NEXTBYTE +* DESTROYS D1, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION + +BYTVAL ANDI.W #$00FF,D0 * ENTER HERE TO CLEAR HIGH BYTE +PUTVAL MOVE.W D0,D1 * NORMAL ENTRY + BSR NXTBYT * GET VAR TO USE + TST.W D0 * STACK? + BNE.S PUTVAR * NO, GO STORE VALUE + MOVE.W D1,-(A4) * YES, PUSH ONTO STACK + RTS + +* ---------------------- +* PFALSE, PTRUE +* ---------------------- + +* PREDICATE HANDLERS TRUE AND FALSE +* DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FUNCTIONS + +PFALSE CLR.W D1 * PREDICATE WAS FALSE, CLEAR FLAG + BRA.S PTRUE1 + +PTRUE MOVEQ #1,D1 * PREDICATE WAS TRUE, SET FLAG +PTRUE1 BSR NXTBYT * GET FIRST (OR ONLY) PREDICATE JUMP BYTE + BCLR #7,D0 * NORMAL POLARITY PREDICATE? + BEQ.S PTRUX1 * NO, LEAVE FLAG ALONE + ADDQ.W #1,D1 * YES, INCREMENT FLAG + +PTRUX1 BCLR #6,D0 * ONE-BYTE JUMP OFFSET? + BNE.S PTRUX3 * YES + + ASL.W #8,D0 * NO, TWO-BYTE, POSITION HIGH-ORDER OFFSET BYTE + MOVE.W D0,D2 + BSR NXTBYT * GET LOW-ORDER BYTE + OR.W D2,D0 * OR IN HIGH-ORDER BITS + BTST #13,D0 * IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)? + BEQ.S PTRUX3 * NO + ORI.W #$C000,D0 * YES, MAKE 16-BIT NUMBER NEGATIVE + +PTRUX3 SUBQ.W #1,D1 * TEST FLAG + BEQ.S PTRUX6 * WAS 1, THAT MEANS DO NOTHING + TST.W D0 * ZERO JUMP? + BNE.S PTRUX4 * NO + BRA OPRFAL * YES, THAT MEANS DO AN RFALSE + +PTRUX4 SUBQ.W #1,D0 * ONE JUMP? + BNE.S PTRUX5 * NO + BRA OPRTRU * YES, THAT MEANS DO AN RTRUE + +PTRUX5 SUBQ.W #1,D0 * ADJUST OFFSET + ADD.W D0,ZPC2(A6) * ADD TO PC + BRA NEWZPC * AND UPDATE ZPC STUFF +PTRUX6 RTS + +* ---------------------- +* BSPLTB +* ---------------------- + +* SPLIT BYTE-POINTER IN D0.W (16 BIT UNSIGNED) +* INTO BLOCK NUMBER IN D0 & BYTE OFFSET IN D1 + +BSPLTB MOVE.W D0,D1 + LSR.W #8,D0 * EXTRACT THE 7 BLOCK BITS (64K RANGE) + LSR.W #1,D0 + ANDI.W #$01FF,D1 * EXTRACT THE 9 OFFSET BITS (0-511) + IFEQ DEBUG + CMP.W MAXLOD(A6),D0 * VALID BLOCK NUMBER? + BCC BLKERR * BHS * NO, FAIL + ENDC + RTS + +* ---------------------- +* BSPLIT +* ---------------------- + +* SPLIT WORD-POINTER IN D0.W (16 BIT UNSIGNED) +* INTO BLOCK NUMBER IN D0 & BYTE OFFSET IN D1 + +BSPLIT MOVE.W D0,D1 + LSR.W #8,D0 * EXTRACT THE 8 BLOCK BITS (128K RANGE) + ANDI.W #$00FF,D1 * EXTRACT THE 8 OFFSET BITS (0-255) + ADD.W D1,D1 * CONVERT OFFSET TO BYTES + IFEQ DEBUG + CMP.W MAXLOD(A6),D0 * VALID BLOCK NUMBER? + BCC BLKERR * BHS * NO, FAIL + ENDC + RTS + +* ---------------------- +* BSPLTQ +* ---------------------- + +* SPLIT QUAD-POINTER IN D0.W (16 BIT UNSIGNED) +* INTO BLOCK NUMBER IN D0 & BYTE OFFSET IN D1 -- EZIP ONLY + +BSPLTQ MOVE.W D0,D1 + LSR.W #7,D0 * EXTRACT THE 9 BLOCK BITS (256K RANGE) + ANDI.W #$007F,D1 * EXTRACT THE 7 OFFSET BITS (0-127) + ADD.W D1,D1 * CONVERT OFFSET TO BYTES + ADD.W D1,D1 + IFEQ DEBUG + CMP.W MAXLOD(A6),D0 * VALID BLOCK NUMBER? + BCC BLKERR * BHS * NO, FAIL + ENDC + RTS + +* ---------------------- +* BLKERR +* ---------------------- + + IFEQ DEBUG +BLKERR LEA MSGBLK,A0 + BRA FATAL * 'Block range error' + + SECTION ZDATA +MSGBLK DC.B 'Block range error',0 + SECTION ZCODE + + ENDC + diff --git a/amiga/ax2.asm b/amiga/ax2.asm new file mode 100644 index 0000000..00b5d29 --- /dev/null +++ b/amiga/ax2.asm @@ -0,0 +1,3069 @@ + + PAGE +* ---------------------------------------------------------------------------- +* ARITHMETIC OPERATIONS +* ---------------------------------------------------------------------------- + +* ---------------------- +* OPADD +* ---------------------- + +OPADD ADD.W D1,D0 * ADD OPR1 AND OPR2 + BRA PUTVAL * RETURN THE VALUE + +* ---------------------- +* OPSUB +* ---------------------- + +OPSUB SUB.W D1,D0 * SUBTRACT OPR2 FROM OPR1 + BRA PUTVAL * RETURN THE VALUE + +* ---------------------- +* OPMUL +* ---------------------- + +OPMUL MULS D1,D0 * MULTIPLY OPR1 BY OPR2 (16 BIT SIGNED) + BRA PUTVAL * RETURN THE PRODUCT, IGNORING OVERFLOW + +* ---------------------- +* OPDIV +* ---------------------- + +* DIVIDE BY ZERO, MOD ZERO, & RANDOM ZERO GENERATE 68K HARDWARE TRAPS ... + +OPDIV EXT.L D0 * SIGN-EXTEND OPR1 TO 32 BITS + DIVS D1,D0 * DIVIDE OPR2 INTO OPR1 + BRA PUTVAL * RETURN THE QUOTIENT, IGNORING REMAINDER + +* ---------------------- +* OPMOD +* ---------------------- + +OPMOD EXT.L D0 * SIGN-EXTEND OPR1 TO 32 BITS + DIVS D1,D0 * DIVIDE OPR2 INTO OPR1 + SWAP D0 * GET REMAINDER + BRA PUTVAL * RETURN IT + +* ---------------------- +* OPRAND +* ---------------------- + +OPRAND TST.W D7 * (GARBAGE FOR ST ASSEMBLER) + + IFEQ EZIP + TST.W D0 * DISABLE RANDOMNESS NOW? + BLT.S RANDX1 * YES + BEQ.S RANDX2 * ZERO, RE-ENABLE RANDOMNESS + + TST.W RCYCLE(A6) * IS RANDOMNESS ALREADY DISABLED? + BNE.S RANDX3 * YES + ENDC + +* NORMAL RANDOMNESS, GENERATE A VALUE + + MOVE.W RSEED2(A6),D1 * GET BOTH SEEDS + SWAP D1 + MOVE.W RSEED1(A6),D1 + MOVE.W D1,RSEED2(A6) * UPDATE LOW SEED + SWAP D1 + + LSR.L #1,D1 * SHIFT BOTH RIGHT BY 1 BIT + EOR.W D1,RSEED1(A6) * GENERATE OUTPUT & UPDATE HIGH SEED + MOVE.W RSEED1(A6),D1 * GET NEW HIGH SEED + + ANDI.L #$00007FFF,D1 * CLEAR HIGH BIT TO PREVENT POSSIBLE OVERFLOW + DIVU D0,D1 * DIVIDE ARG INTO RANDOM NUMBER + SWAP D1 * GET REMAINDER + ADDQ.W #1,D1 * MUST BE BETWEEN 1 AND N, INCLUSIVE + MOVE.W D1,D0 + BRA PUTVAL * RETURN THE VALUE + + IFEQ EZIP + +*** GENERATE A NON-RANDOM SEQUENCE HENCEFORTH + +RANDX1 NEG.W D0 * THIS SPECIFIES UPPER LIMIT OF SEQUENCE +RANDX2 MOVE.W D0,RCYCLE(A6) * STORE IT + BRA.S RANDX4 * AND INITIALIZE COUNTER (SEQ BEGINS NEXT PASS) + +RANDX3 MOVE.W RCONST(A6),D0 * GENERATE NEXT VALUE IN SEQUENCE + ADDQ.W #1,D0 + CMP.W RCYCLE(A6),D0 * EXCEEDED THE UPPER LIMIT YET? + BLE.S RANDX4 * NO + MOVEQ #1,D0 * YES, RESTART THE SEQUENCE + +RANDX4 MOVE.W D0,RCONST(A6) * UPDATE COUNTER + BRA PUTVAL * RETURN THE VALUE + ENDC + +* ---------------------- +* OPQLES +* ---------------------- + +OPQLES CMP.W D1,D0 * IS OPR1 LESS THAN OPR2? + BLT PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + +* ---------------------- +* OPQGRT +* ---------------------- + +OPQGRT CMP.W D1,D0 * IS OPR1 GREATER THAN OPR2? + BGT PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PRECICATE FALSE + +* ---------------------- +* OPBTST +* ---------------------- + +* LOGICAL OPERATIONS + +OPBTST NOT.W D0 * TURN OFF ALL BITS IN OPR2 THAT ARE ON IN OPR1 + AND.W D0,D1 + BEQ PTRUE * SUCCESS IF OPR2 COMPLETELY CLEARED + BRA PFALSE + +* ---------------------- +* OPBOR +* ---------------------- + +OPBOR OR.W D1,D0 * LOGICAL "OR" + BRA PUTVAL * RETURN THE VALUE + +* ---------------------- +* OPBCOM +* ---------------------- + +OPBCOM NOT.W D0 * LOGICAL COMPLEMENT + BRA PUTVAL * RETURN THE VALUE + +* ---------------------- +* OPBAND +* ---------------------- + +OPBAND AND.W D1,D0 * LOGICAL "AND" + BRA PUTVAL * RETURN THE VALUE + +* ---------------------- +* OPSHIFT +* ---------------------- + +OPSHIFT + TST.W D1 * NEGATIVE? + BLT.S SHFX1 * YES + LSL.W D1,D0 * NO, LOGICAL LEFT SHIFT + BRA PUTVAL +SHFX1 NEG.W D1 + LSR.W D1,D0 * LOGICAL RIGHT SHIFT + BRA PUTVAL + +* ---------------------- +* OPASHIFT +* ---------------------- + +OPASHIFT + TST.W D1 * NEGATIVE? + BLT.S ASHFX1 * YES + ASL.W D1,D0 * NO, ARITHMETIC LEFT SHIFT + BRA PUTVAL +ASHFX1 NEG.W D1 + ASR.W D1,D0 * ARITHMETIC RIGHT SHIFT + BRA PUTVAL + +* ---------------------- +* OPQEUQ +* ---------------------- + +* GENERAL PREDICATES + +OPQEQU NOP * TELL CALLER TO USE ARGBLK + MOVE.W (A0)+,D1 * NUMBER OF OPERANDS + MOVE.W (A0)+,D0 * OPR1 + SUBQ.W #1,D1 + +QEQUX1 CMP.W (A0)+,D0 * IS NEXT OPR EQUAL TO OPR1? + BEQ.S QEQUX2 * YES + SUBQ.W #1,D1 * NO, BUT LOOP IF MORE OPERANDS + BNE.S QEQUX1 + + BRA PFALSE * PREDICATE FALSE +QEQUX2 BRA PTRUE * PREDICATE TRUE + + +* ---------------------- +* OPQZER +* ---------------------- + +OPQZER TST.W D0 * IS OPR ZERO? + BEQ PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + + + PAGE +* ---------------------------------------------------------------------------- +* OBJECT-RELATED PRIMITIVES +* ---------------------------------------------------------------------------- + +* ---------------------- +* OBJLOC +* ---------------------- + +* GIVEN OBJECT NUMBER IN D0.W, RETURN OBJECT LOCATION IN A0 + +OBJLOC MULU #OLEN,D0 * CALCULATE OBJECT OFFSET + MOVE.L OBJTAB(A6),A0 + ADDA.L D0,A0 * INDEX INTO OBJECT TABLE + ADDA.W #OPLEN-OLEN,A0 * SKIPPING OVER THE DEFAULT PROPERTY TABLE + RTS + +* ---------------------- +* FSTPRP +* ---------------------- + +* GIVEN OBJECT LOCATION IN A0, RETURN POINTER TO FIRST PROPERTY IN A0 + +FSTPRP ADDA.W #PROP,A0 * POINT TO PROPERTY TABLE SLOT + MOVEQ #0,D0 + BSR GTAWRD * GET ITS LOCATION + MOVE.L BUFFER(A6),A0 * ABSOLUTIZE THE LOCATION + ADDA.L D0,A0 + + CLR.W D0 + MOVE.B (A0)+,D0 * LENGTH OF SHORT DESCRIPTION IN WORDS + ADD.W D0,D0 + ADDA.W D0,A0 * ADJUST POINTER TO SKIP IT + RTS + +* ---------------------- +* NXTPRP +* ---------------------- + +* GIVEN POINTER TO A PROPERTY ID IN A0, UPDATE IT TO POINT TO NEXT PROPERTY ID + + IFEQ EZIP + +NXTPRP MOVE.B (A0)+,D0 * GET (FIRST) PROPERTY ID BYTE + BTST #7,D0 * PROPERTY LENGTH GREATER THAN 2? + BNE.S NXTPX4 * YES + + BTST #6,D0 * NO, PROPERTY LENGTH 2? + BEQ.S NXTPX2 * NO, PROPERTY LENGTH IS 1 + ADDQ.L #1,A0 +NXTPX2 ADDQ.L #1,A0 * UPDATE POINTER + RTS + +NXTPX4 MOVE.B (A0)+,D0 * GET (SECOND) PROPERTY LENGTH BYTE (LOW 6 BITS) + ANDI.W #$003F,D0 * CLEAR OFF HIGH BITS + ADDA.W D0,A0 * UPDATE POINTER + RTS + ENDC + IFEQ CZIP + +NXTPRP CLR.W D0 + MOVE.B (A0)+,D0 * GET PROPERTY ID BYTE + ASR.W #5,D0 * EXTRACT PROPERTY LENGTH-1 (HIGH 3 BITS) + ADDQ.W #1,D0 * ADJUST FOR EXTRA LENGTH BYTE + ADDA.W D0,A0 * UPDATE POINTER + RTS + ENDC + +* ---------------------------------------------------------------------------- +* OBJECT OPERATIONS +* ---------------------------------------------------------------------------- + +* ---------------------- +* OPMOVE +* ---------------------- + +* MOVE (OBJ1 INTO OBJ2) + +OPMOVE MOVEM.W D1/D0,-(SP) * PROTECT OPERANDS FROM REMOVE CALL + BSR OPREMO * REMOVE OBJ1 FROM WHEREVER IT IS + + MOVE.W 2(SP),D0 * OBJ2 + BSR OBJLOC * FIND ITS LOCATION + MOVE.L A0,A1 * SAVE IT + MOVE.W (SP),D0 * OBJ1 + BSR OBJLOC * FIND ITS LOCATION + + MOVEM.W (SP)+,D0/D1 * RESTORE THE OBJ NUMBERS + + IFEQ EZIP + MOVE.W FIRST(A1),NEXT(A0) * PUT OBJ2'S CHILD INTO OBJ1'S SIBLING SLOT + MOVE.W D1,LOC(A0) * PUT OBJ2 IN OBJ1'S PARENT SLOT + MOVE.W D0,FIRST(A1) * PUT OBJ1 IN OBJ2'S CHILD SLOT + ENDC + IFEQ CZIP + MOVE.B FIRST(A1),NEXT(A0) * PUT OBJ2'S CHILD INTO OBJ1'S SIBLING SLOT + MOVE.B D1,LOC(A0) * PUT OBJ2 IN OBJ1'S PARENT SLOT + MOVE.B D0,FIRST(A1) * PUT OBJ1 IN OBJ2'S CHILD SLOT + ENDC + RTS + +* ---------------------- +* OPREMO +* ---------------------- + +* REMOVE (OBJ FROM ITS PARENT) + + IFEQ EZIP + +OPREMO MOVE.W D0,D1 * SAVE OBJ + BSR OBJLOC * FIND ITS LOCATION + MOVE.L A0,A1 + MOVE.W LOC(A1),D0 * GET ITS PARENT + BEQ.S REMOX3 * IF NO PARENT, WE'RE DONE + + BSR OBJLOC * FIND PARENT'S LOCATION + MOVE.W FIRST(A0),D0 * GET PARENT'S FIRST CHILD + CMP.W D0,D1 * IS IT OBJ? + BNE.S REMOX1 * NO + + MOVE.W NEXT(A1),FIRST(A0) * YES, CHANGE IT TO OBJ'S SIBLING + BRA.S REMOX2 * AND EXIT + +REMOX1 BSR OBJLOC * FIND LOCATION OF CURRENT SIBLING + MOVE.W NEXT(A0),D0 * GET NEXT SIBLING IN CHAIN + CMP.W D0,D1 * IS IT OBJ? + BNE.S REMOX1 * NO, CONTINUE SEARCH + + MOVE.W NEXT(A1),NEXT(A0) * YES, CHANGE IT TO OBJ'S SIBLING +REMOX2 CLR.W LOC(A1) * OBJ NOW HAS NO PARENT + CLR.W NEXT(A1) * OR SIBLING +REMOX3 RTS + + ENDC + IFEQ CZIP + +OPREMO MOVE.W D0,D1 * SAVE OBJ + BSR OBJLOC * FIND ITS LOCATION + MOVE.L A0,A1 + MOVE.B LOC(A1),D0 * GET ITS PARENT + BEQ.S REMOX3 * IF NO PARENT, WE'RE DONE + + ANDI.W #$00FF,D0 * CLEAR UNWANTED BYTE + BSR OBJLOC * FIND PARENT'S LOCATION + MOVE.B FIRST(A0),D0 * GET PARENT'S FIRST CHILD + CMP.B D0,D1 * IS IT OBJ? + BNE.S REMOX1 * NO + + MOVE.B NEXT(A1),FIRST(A0) * YES, CHANGE IT TO OBJ'S SIBLING + BRA.S REMOX2 * AND EXIT + +REMOX1 ANDI.W #$00FF,D0 * CLEAR UNWANTED BYTE + BSR OBJLOC * FIND LOCATION OF CURRENT SIBLING + MOVE.B NEXT(A0),D0 * GET NEXT SIBLING IN CHAIN + CMP.B D0,D1 * IS IT OBJ? + BNE.S REMOX1 * NO, CONTINUE SEARCH + + MOVE.B NEXT(A1),NEXT(A0) * YES, CHANGE IT TO OBJ'S SIBLING +REMOX2 CLR.B LOC(A1) * OBJ NOW HAS NO PARENT + CLR.B NEXT(A1) * OR SIBLING +REMOX3 RTS + ENDC + +* ---------------------- +* OPLOC +* ---------------------- + +* LOC (RETURN CONTAINER OF OBJ) + +OPLOC BSR OBJLOC * FIND OBJ'S LOCATION + + IFEQ EZIP + MOVE.W LOC(A0),D0 * GET PARENT + ENDC + IFEQ CZIP + CLR.W D0 + MOVE.B LOC(A0),D0 * GET PARENT, CLEARING UNUSED BYTE + ENDC + BRA PUTVAL * RETURN THE VALUE + +* ---------------------- +* OPQFIR +* ---------------------- + +* FIRST? (RETURN FIRST CHILD OF OBJ, FAIL IF NONE) + +OPQFIR BSR OBJLOC * FIND OBJ'S LOCATION + + IFEQ EZIP + MOVE.W FIRST(A0),D0 * GET FIRST CHILD + ENDC + IFEQ CZIP + CLR.W D0 + MOVE.B FIRST(A0),D0 * GET FIRST CHILD, CLEARING UNUSED BYTE + ENDC + MOVE.W D0,-(SP) + BSR PUTVAL * RETURN THE VALUE + TST.W (SP)+ * NONZERO? + BNE PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + +* ---------------------- +* OPQNEX +* ---------------------- + +* NEXT? (RETURN THE NEXT SIBLING OF OBJ, FAIL IF NONE) + +OPQNEX BSR OBJLOC * FIND OBJ'S LOCATION + + IFEQ EZIP + MOVE.W NEXT(A0),D0 * GET SIBLING + ENDC + IFEQ CZIP + CLR.W D0 + MOVE.B NEXT(A0),D0 * GET SIBLING, CLEARING UNUSED BYTE + ENDC + MOVE.W D0,-(SP) + BSR PUTVAL * RETURN THE VALUE + TST.W (SP)+ * NONZERO? + BNE PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + +* ---------------------- +* OPQIN +* ---------------------- + +* IN? (IS OBJ1 CONTAINED IN OBJ2?) + +OPQIN BSR OBJLOC * FIND OBJ1'S LOCATION + + IFEQ EZIP + CMP.W LOC(A0),D1 * IS OBJ1'S PARENT OBJ2? + ENDC + IFEQ CZIP + CMP.B LOC(A0),D1 * IS OBJ1'S PARENT OBJ2? + ENDC + BEQ PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + +* ---------------------- +* OPGETP +* ---------------------- + +* GETP (GET SPECIFIED PROPERTY OF OBJ, DEFAULT IF NONE) + +OPGETP BSR OBJLOC * FIND OBJ'S LOCATION + BSR FSTPRP * GET POINTER TO FIRST PROPERTY + BRA.S GETPX2 * SKIP NEXT LINE FIRST TIME THROUGH LOOP + +GETPX1 BSR NXTPRP * POINT TO NEXT PROPERTY +GETPX2 MOVE.B (A0),D0 * GET PROPERTY IDENTIFIER + ANDI.W #PMASK,D0 * CLEAN OFF (EZIP MODE AND) LENGTH BITS + + CMP.W D1,D0 * COMPARE PROPERTY NUMBER WITH DESIRED ONE + BGT.S GETPX1 * IF GREATER, LOOP (TABLE SORTED IN REVERSE) + BLT.S GETPX3 * IF LESS, NO SUCH PROPERTY, USE DEFAULT + +* (ASSUMIMG NO 2ND EZIP LENGTH BYTE EXISTS HERE) + + BTST #PLBIT,(A0)+ * GOT IT, EXAMINE (LOW MODE OR) LOWEST LEN BIT + BNE.S GETPX4 * ONE MEANS WORD VALUE, OTHERWISE BYTE VALUE + + MOVE.B (A0),D0 * GET THE BYTE + BRA BYTVAL * AND RETURN IT + +GETPX3 SUBQ.W #1,D1 * PROPERTY NOT FOUND, USE DEFAULT PROP TABLE + ADD.W D1,D1 * WORD OFFSET + MOVE.L OBJTAB(A6),A0 * GET BASE OF DEFAULT TABLE + ADDA.W D1,A0 * POINT TO THE DEFAULT PROPERTY + +GETPX4 BSR GTAWRD * GET THE WORD VALUE + BRA PUTVAL * AND RETURN IT + +* ---------------------- +* OPPUTP +* ---------------------- + +* PUTP (CHANGE VALUE OF SPECIFIED PROPERTY OF OBJ, ERROR IF BAD PROP NUMBER) + +OPPUTP BSR OBJLOC * FIND OBJ'S LOCATION + BSR FSTPRP * GET POINTER TO FIRST PROPERTY + BRA.S PUTPX2 * SKIP NEXT LINE FIRST TIME THROUGH LOOP + +PUTPX1 BSR NXTPRP * POINT TO NEXT PROPERTY +PUTPX2 MOVE.B (A0),D0 * GET PROPERTY IDENTIFIER + ANDI.W #PMASK,D0 * CLEAN OFF (EZIP MODE AND) LENGTH BITS + + CMP.W D1,D0 * COMPARE PROPERTY NUMBER WITH DESIRED ONE + BGT.S PUTPX1 * IF GREATER, LOOP (TABLE SORTED IN REVERSE) + BEQ.S PUTPX3 * IF EQUAL, GOT IT + + CLR.W D0 * OTHERWISE, FATAL ERROR + LEA MSGPUP,A0 + BRA FATAL * 'Non-existant put property' + + SECTION ZDATA +MSGPUP DC.B 'Non-existant put property',0 + SECTION ZCODE + +* (ASSUMING NO 2ND EZIP LENGTH BYTE EXISTS HERE) + +PUTPX3 BTST #PLBIT,(A0)+ * EXAMINE (LOW MODE OR) LOWEST LENGTH BIT + BNE.S PUTPX4 * ZERO MEANS BYTE VALUE, OTHERWISE WORD VALUE + + MOVE.B D2,(A0) * STORE THE NEW BYTE + RTS + +PUTPX4 MOVE.W D2,D0 + BRA PTAWRD * STORE THE NEW WORD + +* ---------------------- +* OPNEXT +* ---------------------- + +* NEXTP (RETURN NUMBER OF NEXT PROP FOLLOWING GIVEN PROP IN OBJ) + +OPNEXT BSR OBJLOC * FIND OBJ'S LOCATION + BSR FSTPRP * GET POINTER TO FIRST PROPERTY + TST.W D1 * WERE WE GIVEN ZERO AS PROP? + BEQ.S NEXTX4 * YES, JUST RETURN FIRST PROPERTY NUMBER + BRA.S NEXTX2 * SKIP NEXT LINE FIRST TIME THROUGH LOOP + +NEXTX1 BSR NXTPRP * POINT TO NEXT PROPERTY +NEXTX2 MOVE.B (A0),D0 * GET PROPERTY IDENTIFIER + ANDI.W #PMASK,D0 * CLEAN OFF (EZIP MODE AND) LENGTH BITS + + CMP.W D1,D0 * COMPARE PROPERTY NUMBER WITH DESIRED ONE + BGT.S NEXTX1 * IF GREATER, LOOP (TABLE SORTED IN REVERSE) + BEQ.S NEXTX3 * IF EQUAL, GOT IT + + CLR.W D0 * OTHERWISE, FATAL ERROR + LEA MSGNXP,A0 + BRA FATAL * 'Non-existant next property' + + SECTION ZDATA +MSGNXP DC.B 'Non-existant next property',0 + SECTION ZCODE + +NEXTX3 BSR NXTPRP * POINT TO NEXT PROPERTY +NEXTX4 MOVE.B (A0),D0 * GET PROPERTY IDENTIFIER + ANDI.W #PMASK,D0 * EXTRACT PROPERTY NUMBER + BRA PUTVAL * AND RETURN IT + +* ---------------------- +* FLGLOC +* ---------------------- + +* PRIMITIVE TO LOCATE A FLAG BIT +* GIVEN A POINTER TO FIRST FLAGS BYTE IN A0, TARGET FLAG NUMBER (0-47) IN D0 +* RETURN POINTER TO TARGET FLAGS BYTE IN A0, TARGET BIT NUMBER (7-0) IN D0 + +FLGLOC MOVE.W D0,-(SP) + LSR.W #3,D0 * EXTRACT BYTE OFFSET + ADD.W D0,A0 * ADJUST FLAGS POINTER + + MOVE.W (SP)+,D0 + NOT.W D0 * FIX THE 3 LOW-ORDER BITS + ANDI.W #$0007,D0 * MASK OFF THE REST + RTS + +* ADDQ.L #1,A0 * POINT TO NEXT FLAGS BYTE +* SUBQ.W #8,D0 * WAS TARGET FLAG IN PREVIOUS BYTE? +* BGE.S FLGLOC * NO +* SUBQ.L #1,A0 * YES, POINT TO PREVIOUS FLAGS BYTE +* NEG.W D0 * AND COMPUTE THE TARGET BIT NUMBER (7-0) +* SUBQ.W #1,D0 +* RTS + +* ---------------------- +* OPQFSE +* ---------------------- + +* FSET? (IS FLAG SET IN OBJ?) + +OPQFSE BSR OBJLOC * FIND OBJ'S LOCATION + MOVE.W D1,D0 + BSR FLGLOC * DETERMINE PROPER FLAGS BYTE & BIT NUMBER + BTST D0,(A0) * IS THE SPECIFIED BIT SET? + BNE PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + +* ---------------------- +* OPFSET +* ---------------------- + +* FSET (SET A FLAG IN OBJ) + +OPFSET BSR OBJLOC * FIND OBJ'S LOCATION + MOVE.W D1,D0 + BSR FLGLOC * DETERMINE PROPER FLAGS BYTE & BIT NUMBER + BSET D0,(A0) * SET THE SPECIFIED BIT + RTS + +* ---------------------- +* OPFCLE +* ---------------------- + +* FCLEAR (CLEAR A FLAG IN OBJ) + +OPFCLE BSR OBJLOC * FIND OBJ'S LOCATION + MOVE.W D1,D0 + BSR FLGLOC * DETERMINE PROPER FLAGS BYTE & BIT NUMBER + BCLR D0,(A0) * CLEAR THE SPECIFIED BIT + RTS + + PAGE +* ---------------------------------------------------------------------------- +* TABLE OPERATIONS +* ---------------------------------------------------------------------------- + +* ---------------------- +* OPGET +* ---------------------- + +* GET (GET THE ITEM'TH WORD FROM TABLE) + +OPGET ASL.W #1,D1 * WORD OFFSET + ADD.W D1,D0 * INDEX INTO TABLE + BSR BSPLTB * SPLIT THE POINTER + BSR GETWRD * GET THE WORD + MOVE.W D2,D0 + BRA PUTVAL * AND RETURN IT + +* ---------------------- +* OPGETB +* ---------------------- + +* GETB (GET THE ITEM'TH BYTE FROM TABLE) + +OPGETB ADD.W D1,D0 * INDEX INTO TABLE + BSR BSPLTB * SPLIT THE POINTER + BSR GETBYT * GET THE BYTE + MOVE.W D2,D0 + BRA BYTVAL * AND RETURN IT + +* ---------------------- +* OPPUT +* ---------------------- + +* NOTE: PROPERTY TABLE POINTERS IN THE NEXT FOUR ROUTINES NOW !MAY! +* EXCEED 32K, SO SIGN-EXTENSIONS MUST BE AVOIDED. + +* A "TABLE" ARGUMENT IS A 16-BIT UNSIGNED BYTE POINTER + +* PUT (REPLACE THE ITEM'TH WORD IN TABLE) + +OPPUT ASL.W #1,D1 * WORD OFFSET + ADD.W D1,D0 * INDEX INTO TABLE + ANDI.L #$FFFF,D0 * MAKE THE SUM A LONGWORD + MOVE.L D0,A0 + ADD.L BUFFER(A6),A0 * ABSOLUTIZE POINTER + MOVE.W D2,D0 + BRA PTAWRD * STORE THE WORD + +* ---------------------- +* OPPUTB +* ---------------------- + +* PUTB (REPLACE THE ITEM'TH BYTE IN TABLE) + +OPPUTB ADD.W D1,D0 * INDEX INTO TABLE + ANDI.L #$FFFF,D0 * MAKE THE SUM A LONGWORD + MOVE.L BUFFER(A6),A0 + MOVE.B D2,0(A0,D0.L) * STORE THE BYTE + RTS + +* ---------------------- +* OPGTPT +* ---------------------- + +* GETPT (GET POINTER TO PROPERTY TABLE FOR GIVEN OBJ, PROP) + +OPGTPT BSR OBJLOC * FIND OBJ'S LOCATION + BSR FSTPRP * GET POINTER TO FIRST PROPERTY + BRA.S GTPTX2 * SKIP NEXT LINE FIRST TIME THROUGH LOOP + +GTPTX1 BSR NXTPRP * POINT TO NEXT PROPERTY +GTPTX2 MOVE.B (A0),D0 * GET (FIRST) PROPERTY ID BYTE + ANDI.W #PMASK,D0 * CLEAN OFF MODE/LENGTH BITS + + CMP.W D1,D0 * COMPARE PROPERTY NUMBER WITH DESIRED ONE + BGT.S GTPTX1 * IF GREATER, LOOP (TABLE SORTED IN REVERSE) + BEQ.S GTPTX3 * IF EQUAL, GOT IT + + CLR.W D0 * OTHERWISE, RETURN ZERO FOR NO SUCH PROPERTY + BRA.S GTPTX5 + + IFEQ EZIP +GTPTX3 MOVE.B (A0)+,D0 * GET (FIRST) PROPERTY ID BYTE + BTST #7,D0 * IS THERE A SECOND LENGTH BYTE? + BEQ.S GTPTX4 * NO + ADDQ.L #1,A0 * YES, SKIP IT TOO + ENDC + IFEQ CZIP + +GTPTX3 ADDQ.L #1,A0 * POINT TO PROPERTY VALUE + ENDC + +GTPTX4 MOVE.L A0,D0 + SUB.L BUFFER(A6),D0 * RE-RELATIVIZE POINTER +GTPTX5 BRA PUTVAL * AND RETURN IT + +* ---------------------- +* OPPTSI +* ---------------------- + +* PTSIZE (GIVEN POINTER TO PROPERTY TABLE, RETURN ITS SIZE) + +OPPTSI MOVE.L BUFFER(A6),A0 + ANDI.L #$FFFF,D0 * MAKE THE TABLE PTR A LONGWORD + ADDA.L D0,A0 * ABSOLUTIZE THE TABLE POINTER + + IFEQ EZIP + MOVE.B -1(A0),D0 * GET MODE/ID BYTE OR LEN BYTE (EITHER WORKS!) + BTST #7,D0 * PROPERTY LENGTH GREATER THAN 2? + BNE.S PTSIX4 * YES + + BTST #6,D0 * NO, PROPERTY LENGTH 2? + BNE.S PTSIX2 * YES + MOVEQ #1,D0 * NO, PROPERTY LENGTH IS 1 + BRA PUTVAL * RETURN IT + +PTSIX2 MOVEQ #2,D0 + BRA PUTVAL * RETURN IT + +PTSIX4 ANDI.W #PMASK,D0 * LENGTH IS LOW 6 BITS + BRA PUTVAL * RETURN IT + ENDC + IFEQ CZIP + CLR.W D0 + MOVE.B -1(A0),D0 * GET THE PROP IDENTIFIER BYTE + ASR.W #5,D0 * EXTRACT LENGTH BITS + ADDQ.W #1,D0 * ADJUST TO ACTUAL LENGTH + BRA PUTVAL * RETURN IT + ENDC + +* ---------------------------------------------------------------------------- +* BLOCK OPERATIONS +* ---------------------------------------------------------------------------- + +* ---------------------- +* OPINTBL +* ---------------------- + +* INTBL? (SEARCH TABLE FOR A VALUE) + +OPINTBL NOP * USE AN ARGUMENT BLOCK + LEA DEFBLK(A6),A1 * DEFAULT ARGBLK + MOVE.W #4,(A1) * 4 ARGS MAX + MOVE.W #128+2,ARG4(A1) * DEFAULT -- WORD SEARCH, RECORD LENGTH = 2 + BSR SETDEF * SET UP DEFAULTS + + MOVE.L A0,A1 + MOVE.W ARG4(A1),D3 + ANDI.W #127,D3 * RECORD LENGTH + ANDI.W #128,ARG4(A1) * SEARCH MODE BIT -- WORD 1, BYTE 0 + BRA.S ITBX4 * >>> ZERO CHECK <<< + +ITBX1 MOVE.W ARG2(A1),D0 * RELATIVE BYTE ADDRESS OF TABLE + BSR BSPLTB * SPLIT IT [D0,D1] + TST.W ARG4(A1) * WORD SEARCH? + BEQ.S ITBX2 * NO, BYTE + BSR GETWRD + CMP.W ARG1(A1),D2 * MATCH? + BEQ.S ITBX5 * YES + BRA.S ITBX3 +ITBX2 BSR GETBYT + CMP.B ARG1+1(A1),D2 * MATCH? + BEQ.S ITBX5 * YES + +ITBX3 ADD.W D3,ARG2(A1) * NO, SKIP TO NEXT RECORD +ITBX4 SUBQ.W #1,ARG3(A1) * ANY MORE RECORDS? + BGE.S ITBX1 * YES, CONTINUE SEARCHING + + CLR.W D0 * FAILED, RETURN ZERO + BSR PUTVAL + BRA PFALSE * PREDICATE FALSE + +ITBX5 MOVE.W ARG2(A1),D0 * SUCCESS, RETURN THE RELATIVE POINTER + BSR PUTVAL + BRA PTRUE * PREDICATE TRUE + +* ---------------------- +* OPCOPYT +* ---------------------- + +* COPYT (COPY OR CLEAR A TABLE) + +OPCOPYT NOP * ASK FOR ARGBLK [JUST TO FREE UP REGS] + MOVE.L A0,A2 + + MOVE.W ARG1(A2),D0 + CMP.W ARG2(A2),D0 + BEQ CPYTX8 * SAME, EXIT + + MOVE.W ARG3(A2),D1 * CHECK LENGTH: + BEQ CPYTX8 * ZERO, EXIT + BGT.S CPYTX1 * POSITIVE + NEG.W ARG3(A2) * NEGATIVE, MAKE POSITIVE + +CPYTX1 TST.W ARG2(A2) * DEST + BEQ.S CPYTX6 * IF ZERO, SPECIAL CASE + TST.W D1 * WAS LEN NEG? + BLT.S CPYTX4 * IF SO, DO /NOT/ CHECK FOR OVERLAP + +*** MOVE.W ARG1(A2),D0 * SRC + CMP.W ARG2(A2),D0 * ANY "FORWARD OVERLAP"? + BHI.S CPYTX4 * NO + + ADD.W ARG3(A2),D0 * MAYBE, SRC END (+1) + CMP.W ARG2(A2),D0 * ANY "FORWARD OVERLAP"? + BLS.S CPYTX4 * NO + +* "FORWARD OVERLAP" DOES EXIST, DO A REVERSE COPY + +CPYTX2 MOVE.W ARG2(A2),D0 * DEST + ADD.W ARG3(A2),D0 * END (+1) + BSR RELABS * ABSOLUTIZE IT [MUST BE PRELOAD] + MOVE.L A0,A1 + + MOVE.W ARG1(A2),D3 * SRC + ADD.W ARG3(A2),D3 * END (+1) + +CPYTX3 SUBQ.W #1,D3 * [PREDECREMENT] + MOVE.W D3,D0 + BSR BSPLTB * --> D0/D1 = BLK/OFF + + BSR GETBYT * --> D0/D1 = NEW BLK/OFF, D2 = DATA + MOVE.B D2,-(A1) * [PREDECREMENT] + SUBQ.W #1,ARG3(A2) + BNE.S CPYTX3 * LOOP [UNSIGNED TEST] + RTS + +* DO A NORMAL COPY + +CPYTX4 MOVE.W ARG2(A2),D0 * DEST + BSR RELABS * ABSOLUTIZE IT [MUST BE PRELOAD] + MOVE.L A0,A1 + + MOVE.W ARG1(A2),D0 + BSR BSPLTB * --> D0/D1 = BLK/OFF + +CPYTX5 BSR GETBYT * --> D0/D1 = NEW BLK/OFF, D2 = DATA + MOVE.B D2,(A1)+ + SUBQ.W #1,ARG3(A2) + BNE.S CPYTX5 * LOOP [UNSIGNED TEST] + RTS + +* NO DEST, JUST CLEAR THE SOURCE TABLE + +CPYTX6 MOVE.W ARG1(A2),D0 * SRC + BSR RELABS * ABSOLUTIZE IT [MUST BE PRELOAD] +CPYTX7 CLR.B (A0)+ + SUBQ.W #1,ARG3(A2) + BNE.S CPYTX7 * LOOP [UNSIGNED TEST] +CPYTX8 RTS + +* ---------------------- +* OPPRNT +* ---------------------- + +* PRINTT (DISPLAY A TABLE IN BLOCK FORMAT) + +OPPRNT NOP * USE AN ARGUMENT BLOCK + LEA DEFBLK(A6),A1 * DEFAULT ARGBLK + MOVE.W #3,(A1) * 3 ARGS MAX + MOVE.W #1,ARG3(A1) * DEFAULT # LINES = 1 + BSR SETDEF * SET UP DEFAULT + MOVE.L A0,A2 + + TST.W ARG2(A2) + BLE.S PRNTX3 * BAD COL COUNT, EXIT + TST.W ARG3(A2) + BLE.S PRNTX3 * BAD ROW COUNT, EXIT + + BSR PUTLIN * MAKE SURE BUFFER IS EMPTY + BSR GETCURS + MOVE.W D1,A1 * INITIAL CURSOR COLUMN -- SAVE HERE + +* WE NOW USE VIRTUAL MEMORY CALLS TO FETCH TABLE DATA + +PRNTX1 MOVE.W ARG2(A2),D3 * COLS PER ROW + MOVE.W ARG1(A2),D0 * TABLE BASE / START OF CURRENT ROW + BSR BSPLTB * --> D0/D1 = BLK/OFF + +PRNTX2 BSR GETBYT * --> D0/D1 = NEW BLK/OFF, D2 = CHAR + EXG D0,D2 + BSR PUTCHR * QUEUE/SCRIPT CHAR, ETC + EXG D0,D2 + + SUBQ.W #1,D3 * ANY MORE COLS IN THIS ROW? + BGT.S PRNTX2 * YES, LOOP + +* BEFORE, WE SAVED THE CURRENT FONT AND ENABLED FONT1, TO BE SURE THE CR +* WAS CORRECTLY INTERPRETED. BUT (IN OTHER CONTEXTS) IT STILL GOT +* MISINTERPRETED. NOWADAYS, #13 ALWAYS MEANS CR, REGARDLESS OF CONTEXT +* (SEE CharOut). A BETTER SOLUTION WILL REQUIRE SOME STICKY RETHINKING. + + SUBQ.W #1,ARG3(A2) * ANY MORE ROWS IN TABLE? + BEQ.S PRNTX3 * NO, DONE + BSR PUTNEW * YES, CR, SCROLL IF NEEDED [PUTCHR #13] + + MOVEQ #-1,D0 * KEEP CURRENT ROW + MOVE.W A1,D1 * BUT RESET COLUMN TO ORIGINAL VALUE + BSR SETCURS + + MOVE.W ARG2(A2),D0 + ADD.W D0,ARG1(A2) * START OF NEXT LINE + BRA.S PRNTX1 * LOOP +PRNTX3 RTS + + PAGE +* ---------------------------------------------------------------------------- +* VARIABLE OPERATIONS +* ---------------------------------------------------------------------------- + +* ---------------------- +* OPVALU +* ---------------------- + +* VALUE (GET VALUE OF VARIABLE) + +OPVALU BSR GETVAR * GET THE VALUE + BRA PUTVAL * AND RETURN IT + +* ---------------------- +* OPSET +* ---------------------- + +* SET (VAR TO VALUE) + +OPSET BRA PUTVAR * STORE THE VALUE + +* ---------------------- +* OPPUSH +* ---------------------- + +* PUSH (A VALUE ONTO THE GAME STACK) + +OPPUSH MOVE.W D0,-(A4) * PUSH THE VALUE + RTS + +* ---------------------- +* OPPOP +* ---------------------- + +* POP (A VALUE OFF THE GAME STACK INTO VAR) + +OPPOP MOVE.W (A4)+,D1 * POP A VALUE + BRA PUTVAR * AND STORE IT + +* ---------------------- +* OPINC +* ---------------------- + +* INC (INCREMENT VAR) + +OPINC MOVE.W D0,D1 * SAVE A COPY HERE + BSR GETVAR * GET THE VARIABLE'S VALUE + ADDQ.W #1,D0 * INCREMENT IT + EXG D0,D1 * POSITION IT + BRA PUTVAR * AND STORE THE NEW VALUE + +* ---------------------- +* OPDEC +* ---------------------- + +* DEC (DECREMENT VAR) + +OPDEC MOVE.W D0,D1 * SAVE A COPY HERE + BSR GETVAR * GET THE VARIABLE'S VALUE + SUBQ.W #1,D0 * DECREMENT IT + EXG D0,D1 * POSITION IT + BRA PUTVAR * AND STORE NEW VALUE + +* ---------------------- +* OPQIGR +* ---------------------- + +* IGRTR? (INCREMENT VAR & TEST IF GREATER THAN VAL) + +OPQIGR MOVE.W D1,D2 * MOVE VAL HERE + MOVE.W D0,D1 * COPY VAR HERE + BSR GETVAR * GET THE VARIABLE'S VALUE + ADDQ.W #1,D0 * INCREMENT IT + EXG D0,D1 * POSITION IT + + CMP.W D2,D1 * NEW VALUE GREATER THAN VAL? + BGT.S QIG2 * YES +QIG1 BSR PUTVAR * NO, STORE THE NEW VALUE + BRA PFALSE * AND RETURN PREDICATE FALSE + +QIG2 BSR PUTVAR * STORE THE NEW VALUE + BRA PTRUE * AND RETURN PREDICATE TRUE + +* ---------------------- +* OPQDLE +* ---------------------- + +* DLESS? (DECREMENT VAR & TEST IF LESS THAN VAL) + +OPQDLE MOVE.W D1,D2 * MOVE VAL HERE + MOVE.W D0,D1 * COPY VAR HERE + BSR GETVAR * GET THE VARIABLE'S VALUE + SUBQ.W #1,D0 * DECREMENT IT + EXG D0,D1 * POSITION IT + + CMP.W D2,D1 * NEW VALUE LESS THAN VAL? + BLT.S QIG2 * YES + BRA.S QIG1 * NO + +* --------------------------------------------------------------------------- +* READ/INPUT OPERATIONS +* --------------------------------------------------------------------------- + +* ------------------------------ +* OPREAD +* ------------------------------ + +* READ (A LINE OF INPUT AND MASTICATE IT) + +OPREAD NOP * USE AN ARGUMENT BLOCK + LEA DEFBLK(A6),A1 * USE A DEFAULT ARGBLK, TOO + MOVE.W #4,(A1) * 4 ARGS MAX + CLR.W ARG2(A1) * DEFAULT LEXV -- ZERO MEANS DON'T + MOVE.W #-1,ARG3(A1) * DEFAULT TIMOUT INTERVAL -- NEG MEANS DON'T + CLR.W ARG4(A1) * DEFAULT TIMOUT HANDLER FUNCTION + BSR SETDEF * SET UP DEFAULTS + + ADDQ.L #2,A0 * SKIP COUNT SLOT + MOVE.W (A0)+,D0 * INBUF + MOVE.W (A0)+,D3 * [LEXV] + MOVE.W (A0)+,TWAIT(A6) * [TIME] + MOVE.W (A0)+,TFUNC(A6) * [HANDLER] + + BSR RELABS * ABSOLUTIZE THE INBUF PTR + MOVE.L A0,A2 * KEEP IT HERE + BSR TRESET * RESET THE TIMER, IF NEEDED + + IFEQ CZIP + MOVEM.L D3/A2,-(SP) + BSR OPUSL * UPDATE STATUS LINE + MOVEM.L (SP)+,D3/A2 + ENDC + + CLR.W LINES(A6) * RESET COUNTER (PREVENTS A SPURIOUS [MORE]) + BSR PUTLIN1 * THEN FORCE OUT ANY QUEUED TEXT (THE PROMPT) + +*** GATHER AND LOWER-CASIFY THE INPUT LINE ... + + MOVE.L A2,A0 * START OF INPUT LINE BUFFER + MOVEQ #0,D0 + MOVE.B (A0)+,D0 * 1ST HEADER BYTE == MAX LENGTH + MOVEQ #0,D1 + MOVE.B (A0)+,D1 * 2ND HEADER BYTE == CURRENT LEN + BSR READLN * GET IT + + MOVE.W D0,D2 * RETURN D0: TERM CHAR + MOVE.L A0,D0 * RETURN A0: END OF ACTUAL INPUT (+1) + MOVE.L A2,A0 + ADDQ.L #2,A0 * START OF INPUT, SKIP HEADER + + SUB.L A0,D0 * NEW TOTAL LENGTH + MOVE.B D0,1(A2) * STORE THE NEW LENGTH IN THE HEADER + BSR LCASE * AND LOWER-CASIFY EVERYTHING + +*** TOKENIZE AND LOOKUP THE INPUT ... + + MOVE.W D3,D0 * LEXV ARG + BEQ.S RDX4 * ZERO MEANS EXIT IMMEDIATELY + BSR RELABS * ABSOLUTIZE + MOVE.L A0,A3 + + MOVE.L VOCTAB(A6),A1 * OPREAD: USE "STANDARD" VOCAB TABLE + MOVEQ #0,D1 * OPREAD: NO PRESERVE FLAG + BSR LEX + +RDX4 MOVE.W D2,D0 + BRA BYTVAL * RETURN THE TERM CHARACTER + +* ------------------------------ +* OPLEX +* ------------------------------ + +* TOKENIZE AND LOOKUP A LINE OF INPUT +* (FIND EACH WORD, CONVERT IT TO ZWORD, AND STORE OFFSET INFO IN LEXV) + +OPLEX NOP * USE AN ARGUMENT BLOCK + LEA DEFBLK(A6),A1 * USE A DEFAULT ARGBLK, TOO + MOVE.W #4,(A1) * 4 ARGS MAX + CLR.W ARG3(A1) * DEFAULT VOC TABLE (FLAG) + CLR.W ARG4(A1) * DEFAULT PRESERVE FLAG = OFF + BSR SETDEF * SET UP DEFAULTS + + MOVE.L A0,A1 * ARGBLK + TST.W (A1)+ * SKIP ACTUAL ARG COUNT (NOT NEEDED) + MOVE.W (A1)+,D0 * ARG1 == INBUF + BSR RELABS * ABSOLUTIZE + MOVE.L A0,A2 * AND PASS IT HERE + MOVE.W (A1)+,D0 * ARG2 == LEXV + BSR RELABS * ABSOLUTIZE + MOVE.L A0,A3 * AND PASS IT HERE + + MOVE.L VOCTAB(A6),A0 * "STANDARD" VOCTAB + MOVE.W (A1)+,D0 * USE A SPECIAL VOCTAB? + BEQ.S LXX0 * NO + BSR RELABS * YES, ABSOLUTIZE +LXX0 EXG A0,A1 * PASS VOCTAB IN A1 + MOVE.W (A0)+,D1 * AND PASS "PRESERVE" FLAG HERE + +* INTERNAL ENTRY POINT +* GIVEN A1 -> VOCAB TABLE, A2 -> INBUF, A3 -> LEXV, D1 = PRESERVE FLAG + +LEX MOVE.L D2,-(SP) + MOVE.L A1,A0 + BSR INITLX * SETUP VOCAB VARS (FOR LOOKUP) + + MOVE.L A2,RDBOS(A6) * REMEMBER INPUT BUFFER BASE + MOVEQ #0,D0 + MOVE.B 1(A2),D0 * >> ACTUAL LEN OF INPUT << + ADDQ.L #2,A2 * SKIP HEADER (MAX LEN, CUR LEN) + ADD.L A2,D0 + MOVE.L D0,RDEOS(A6) * REMEMBER END OF INPUT + + MOVE.L A3,RDRET(A6) * REMEMBER RETURN BUFFER BASE + CLR.B 1(A3) * BUFFER INITIALLY EMPTY + ADDQ.L #2,A3 * SKIP HEADER (MAX WORDS, NWORDS) + +* LOOP STARTS HERE, A2 -> CURRENT INBUF, A3 -> CURRENT LEXV + +LXX2 MOVE.L A2,A0 * CURRENT INPUT START + MOVE.L RDEOS(A6),D0 + SUB.L A2,D0 * CURRENT REMAINING LENGTH + BEQ.S LXX8 * NOTHING, EXIT + BSR ZWSTR * FIND NEXT WORD, AND CONVERT IT + + MOVE.L A0,A2 * RETURN: START OF CURRENT WORD + MOVE.W D0,D2 * RETURN: LENGTH OF CURRENT WORD, OR ZERO + BEQ.S LXX8 * NOTHING, EXIT + +*** BUILD THE LEX (RETURN) TABLE ... + + MOVE.L RDRET(A6),A0 * RETURN TABLE POINTER + MOVE.B (A0)+,D0 * MAX WORDS ALLOWED + CMP.B (A0),D0 * ROOM FOR ANOTHER? + BEQ.S LXX6 * NO, ERROR + ADDQ.B #1,(A0) * INCREMENT FOUND-WORD COUNT + + LEA RDZSTR(A6),A0 * ZWORD WAS LEFT HERE + BSR LOOKUP * SEARCH VOCAB TABLE FOR IT, RETURN OFFSET + TST.W D0 * WORD FOUND? + BNE.S LXX3 * YES + TST.W D1 * NO, PRESERVE OLD INFO? >> OFFSET ONLY << + BNE.S LXX4 * YES + +LXX3 MOVE.L A3,A0 * CURRENT RETURN SLOT + BSR PTAWRD * STORE THE OFFSET IN RETURN TABLE + +LXX4 MOVE.B D2,2(A3) * STORE WORD LENGTH IN RETURN TABLE + MOVE.L A2,D0 + SUB.L RDBOS(A6),D0 * CALCULATE STARTING BYTE OFFSET OF WORD + MOVE.B D0,3(A3) * STORE IT TOO + + ADDQ.L #4,A3 * ADVANCE RETURN TABLE PTR + ADDA.W D2,A2 * ADVANCE INPUT PTR + BRA LXX2 * GO FOR THE NEXT WORD + +*** ERROR, RETURN BUFFER IS FULL, TELL USER, THEN EXIT + +LXX6 MOVE.L A2,A0 * START OF FLUSHED STRING + MOVE.L RDEOS(A6),A1 * END (+1) + BSR RDERR * ECHO IT IN ERROR MESSAGE + +LXX8 MOVE.L (SP)+,D2 * CLEAN UP AND EXIT + RTS + +* ------------------------------ +* OPZWSTR +* ------------------------------ + +* IDENTIFY THE NEXT WORD (START/END), AND CONVERT IT TO A ZWORD + +OPZWSTR + ADD.W D2,D0 * INPUT BUFFER: BASE + OFFSET + BSR RELABS * ABSOLUTIZE IT + MOVEQ #VCHARS,D0 * MAX LEN -- IGNORE 2ND ARG (SPEC ERROR) + BSR ZWSTR * GO FOR IT + +* (IGNORE RETURNED INFO; WE'RE INTERESTED IN INITIAL WORD ONLY) + + MOVE.W D3,D0 * REQUESTED ZWORD BUFFER + BSR RELABS * ABSOLUTIZE IT + MOVE.L A0,A1 + LEA RDZSTR(A6),A0 * ZWORD WAS LEFT HERE + MOVEQ #ZCHARS,D0 + BRA COPYB * COPY ZWORD TO FINAL DEST, AND EXIT + +* INTERNAL ENTRY POINT +* GIVEN A0 -> INPUT START, D0.W = INPUT LENGTH (TOTAL) +* RETURN A0 -> FIRST WORD START, D0.W = FIRST WORD LENGTH, OR ZERO + +ZWSTR BSR FINDBK * FIND NEXT BREAK CHAR + TST.W D0 + BEQ.S ZWSX1 * EXIT IF NOTHING + + MOVEM.L D0-D1/A0-A1,-(SP) * SAVE RESULTS + LEA RDWSTR(A6),A1 * TEMP STRING BUFFER + MOVEQ #VCHARS,D1 * MAX LENGTH + BSR COPYS * COPY FIRST WORD, MAKE ASCIZ + + LEA RDWSTR(A6),A1 + LEA RDZSTR(A6),A0 * TEMP OUTPUT BUFFER + BSR ZWORD * CONVERT STRING, LEAVE ZWORD IN BUFFER + MOVEM.L (SP)+,D0-D1/A0-A1 * RESTORE RESULTS +ZWSX1 RTS + +* ------------------------------ +* OPINPUT +* ------------------------------ + +* WAIT FOR A KEY (NO ECHO), HANDLE OPTIONAL TIMEOUTS + +OPINPUT NOP * USE ARGBLK + LEA DEFBLK(A6),A1 * USE A DEFAULT ARGBLK, TOO + MOVE.W #3,(A1) * 3 ARGS MAX + MOVE.W #-1,ARG2(A1) * DEFAULT TIMOUT INTERVAL -- "DON'T" + CLR.W ARG3(A1) * DEFAULT TIMOUT HANDLER FUNCTION + BSR SETDEF * SET UP DEFAULTS + ADDQ.L #ARG2,A0 * SKIP COUNT AND DEVICE + MOVE.W (A0)+,TWAIT(A6) * DELAY IN 1/10'S SECOND + MOVE.W (A0)+,TFUNC(A6) * FUNCTION TO CALL UPON TIMEOUT + BSR TRESET * RESET THE TIMER, IF NEEDED + + CLR.W LINES(A6) * RESET COUNTER, PREVENTS A SPURIOUS [MORE] + TST.W VOBUFF(A6) * BUFFERED OUTPUT? + BEQ.S INPX1 * NO + BSR PUTLIN * YES, EMPTY THE BUFFER + +INPX1 MOVEQ #0,D0 * SINGLE CHAR [SUPPRESS MENU CMD-STRINGS] + BSR INPUT * GET KEY + CMPI.B #1,D0 * CONTINUE AFTER TIMEOUT? + BEQ.S INPX1 * YES + BRA BYTVAL * OTHERWISE, RETURN KEY + +* INTERNAL ENTRY POINT >> CALLED ALSO FROM READLN; HANDLES TIMEOUTS << +* GIVEN D0.W = LINE-INPUT FLAG (ZERO IF SINGLE-CHAR INPUT) +* WAIT FOR A KEY, RETURN D0.B = VALUE +* IN CASE OF A TIMEOUT, RETURN D0.B = 0 (ABORT) OR 1 (KEEP WAITING) +* IF WAITING, RETURN D0 (HI WORD) = NONZERO TO REDRAW INPUT LINE + +INPUT MOVEM.L D1-D2,-(SP) + MOVE.W D0,D2 * SAVE FLAG HERE + MOVEQ #1,D0 * START OF INPUT + MOVE.W D2,D1 * CHAR/LINE + BSR SETUPI + +INPX4 BSR GAMINT1 * CHECK FOR GAME INTERRUPT (SOUND, ETC) + + BSR ITTYIN * CHECK FOR A KEY << DON'T WAIT! >> + TST.B D0 * GOT ONE? + BEQ.S INPX6 * NOTHING YET + + MOVE.W D0,-(SP) + CLR.W D0 * END OF INPUT + MOVE.W D2,D1 * CHAR/LINE + BSR SETUPI + MOVE.W (SP)+,D0 + BRA.S INPX8 * EXIT WITH KEY + +INPX6 TST.W TWAIT(A6) * TIMOUTS IN EFFECT? + BLT.S INPX4 * NO, JUST LOOP + BSR TCHECK * TIME (10'S) REMAINING BEFORE NEXT TIMEOUT + TST.W D0 * HAS IT RUN OUT? + BGT.S INPX4 * NO, CONTINUE LOOP + + BSR TNEXT * YES: UPDATE TIMER + CLR.W D0 * END OF INPUT (FOR THE MOMENT...) + MOVE.W D2,D1 * CHAR/LINE + BSR SETUPI + + BSR GETCURS + MOVE.W D1,D2 * REMEMBER CURRENT CURSOR POS (COLUMN) + + MOVE.W TFUNC(A6),D0 * TIMEOUT FUNCTION + BSR INCALL * CALL IT (INTERNALLY) + TST.W D0 * IT RETURNS A BOOLEAN -- ABORT INPUT? + BNE.S INPX7 * YES + + BSR PUTLIN * [XZIPTEST:] DUMP ANY NEW OUTPUT + BSR GETCURS + SUB.W D2,D1 * DID CURSOR POS (COLUMN) CHANGE? + MOVE.W D1,D0 * ZERO IF NO + SWAP D0 * RETURN THIS FLAG IN HIGH WORD + MOVE.W #1,D0 * 1 MEANS KEEP WAITING + BRA.S INPX8 + +INPX7 MOVEQ #0,D0 * NULL CHAR MEANS ABORT INPUT +INPX8 MOVEM.L (SP)+,D1-D2 + RTS + +* --------------------------------------------------------------------------- +* READ/INPUT PRIMITIVES +* --------------------------------------------------------------------------- + +* ------------------------------ +* READLN +* ------------------------------ + +* GATHER A LINE OF INPUT +* GIVEN A0 -> INPUT BUFFER, D0 = MAX LENGTH, D1 = CURRENT LENGTH +* RETURN A0 -> END OF ACTUAL INPUT (+1), D0 = TERM CHAR + +EOLCHR EQU $0D * CARRIAGE RETURN +DELCH1 EQU $08 * BACKSPACE +DELCH2 EQU $7F * ALSO ACCEPT "DELETE" + +READLN MOVEM.L D1-D4/A1-A3,-(SP) + MOVE.L A0,A1 * A1 -> START + MOVE.L A0,A2 + ADDA.W D1,A2 * A2 -> CURRENT POSITION (MAY BE FULL) + MOVE.L A0,A3 + ADDA.W D0,A3 * A3 -> END (+1) + + BSR GETCURS + MOVE.W D1,D3 * REMEMBER "REAL" START POS (COLUMN) + BSR MAXSCRN + MOVE.W D1,D4 * AND MAX LINE LEN + +RDLX1 MOVE.L BUFFER(A6),A0 + MOVE.W PTCHARS(A0),D0 * TABLE OF TERMINATING CHARS + BSR RELABS * ABSOLUTIZE + MOVE.L A0,D2 * KEEP PTR HERE + +*** WAIT FOR A KEY, CHECK FOR A TCHAR ... + +RDLX2 MOVEQ #1,D0 * LINE INPUT [ALLOW MENU CMD-STRINGS] + BSR INPUT * NO ECHO, HANDLE TIMEOUTS +*** BSR TTYIN + TST.B D0 * WAS THERE A TIME-OUT AND AN ABORT? + BEQ.S RDLX10 * YES, BREAK + CMPI.B #1,D0 * WAS THERE A TIME-OUT WITHOUT AN ABORT? + BEQ.S RDLX9A * YES, DO INPUT-ECHO HACK + CMPI.B #EOLCHR,D0 * CR? + BEQ.S RDLX10 * YES, BREAK + + MOVE.L D2,A0 * TCHARS TABLE + MOVEQ #0,D1 * FLAG FOR "FUNCTION-KEY TCHARS" +RDLX4 CMPI.B #255,(A0) * CONSIDER ALL FKEYS TO BE TCHARS? + BNE.S RDLX5 * NO + MOVEQ #1,D1 * YES, SET FLAG +RDLX5 CMP.B (A0),D0 * CHECK TABLE FOR THIS CHAR + BEQ.S RDLX10 * >> FOUND IT, BREAK << + TST.B (A0)+ * END OF TABLE? + BNE RDLX4 * NO, CONTINUE SEARCH + +* LAST CHANCE TO BE A TCHAR ... + + CMPI.B #127,D0 * SPECIAL CASE: IS THIS CHAR AN FKEY? + BLS.S RDLX6 * NO + + TST.W D1 * YES: "FUNCTION-KEY TCHARS" ACTIVE? + BNE.S RDLX10 * YES, BREAK + BRA.S RDLX9 * RDLX2 * NO >> REJECT KEY << + +* NOT A TCHAR, CHECK FOR A BACKSPACE ... + +RDLX6 CMPI.B #DELCH1,D0 * BACKSPACE? + BEQ.S RDLX8 * YES + CMPI.B #DELCH2,D0 * DELETE? + BEQ.S RDLX8 * YES + +*** NORMAL CHARACTER, HANDLE IT ... + + CMPA.L A3,A2 * BUFFER OVERFLOW? + BCC.S RDLX9 * BHS * YES, IGNORE CHAR, JUST BEEP + + MOVE.B D0,(A2)+ * STORE CHAR + BSR TTYOUT * AND ECHO IT + BRA.S RDLX2 + +* HANDLE A BACKSPACE + +RDLX8 CMPA.L A1,A2 * BUFFER UNDERFLOW? + BLS.S RDLX9 * YES, JUST BEEP + SUBQ.L #1,A2 * NO, BACK UP BUFFER POINTER + MOVEQ #DELCH1,D0 + BSR TTYOUT * AND ECHO A BS + BRA RDLX2 + +* ERROR, BEEP -- BUFFER TOO FULL/EMPTY. DISCARD CHAR, NO ECHO. + +RDLX9 MOVEQ #1,D0 + BSR DOSOUND * BEEP AT USER + BRA RDLX2 * AND KEEP WAITING + +* TIMEOUT OCCURRED (NO ABORT) +* RE-ECHO ENTIRE INPUT LINE, BUT ONLY IF GAME WROTE AFTER THE OLD ONE +* WE ASSUME GAME PRINTED A FRESH CR, AND A PROMPT (>) IF NEEDED + +RDLX9A SWAP D0 * "REDRAW" FLAG IS IN HIGH HALF OF REGISTER + TST.W D0 * DID CURSOR POSITION CHANGE DURING TIMEOUT? + BEQ RDLX2 * NO, DON'T REDRAW + + MOVE.L A1,-(SP) * SAVE START PTR + BRA.S RDLX9C +RDLX9B MOVE.B (A1)+,D0 + BSR TTYOUT * ECHO ONE-AT-A-TIME, SO WILL WRAP IF NEEDED +RDLX9C CMPA.L A2,A1 * ANY MORE? + BLT.S RDLX9B * YES + MOVE.L (SP)+,A1 + BRA RDLX2 * START WAITING AGAIN + +*** DONE, HANDLE THE TERMINATING CHAR <<< DON'T STORE IN BUFFER >>> + +RDLX10 MOVE.W D0,D2 * SAVE TCHAR + CMPI.B #EOLCHR,D2 * WAS THE CHAR A RETURN? + BNE.S RDLX12 * NO >>> SKIP THE ECHO? <<< + BSR TTYOUT * YES, ECHO IT + +RDLX12 CMPA.L A3,A2 * ANY ROOM LEFT? + BCC.S RDLX14 * BHS * NO (SIGH) + CLR.B (A2) * INPUT SHOULD BE FOLLOWED BY A BREAK (ZWSTR) + +RDLX14 BSR GETSCRN * ARE WE IN WINDOW 1? + BNE.S RDLX20 * YES, IGNORE [MORE] COUNTER + +* ADJUST THE [MORE] COUNTER + + MOVE.L A2,D0 + SUB.L A1,D0 * LENGTH OF INPUT + ADD.W D3,D0 * TAKING INTO ACCOUNT INITIAL COLUMN + + CMPI.B #EOLCHR,D2 * WAS THE CHAR A RETURN? + BNE.S RDLX18 * NO +RDLX16 ADDQ.W #1,LINES(A6) * ADJUST THE [MORE] COUNTER +RDLX18 SUB.W D4,D0 * SCREEN WIDTH (40-80) + BGE.S RDLX16 * ONCE FOR EACH ADDITIONAL SCREEN LINE + +* SCRIPT THE USER INPUT LINE (IF SCRIPTING IS ACTIVE) +* AVOID PROBLEMS WITH BACKSPACES, BY WAITING UNTIL INPUT IS COMPLETE + +RDLX20 +* MOVEQ #0,D1 + CMPI.B #EOLCHR,D2 * BUT WAS THE CHAR A RETURN? + BNE.S RDLX22 * NO, AVOID SCRIPTING [XZIP] + MOVEQ #1,D1 * YES, (AND ADD A CR) + + MOVE.L A1,A0 * START OF LINE + MOVE.L A2,D0 + SUB.L A1,D0 * LENGTH + BSR SCRINP + +RDLX22 MOVE.W D2,D0 * RETURN TERM CHAR + MOVE.L A2,A0 * RETURN END-OF-INPUT (+1) POINTER + MOVEM.L (SP)+,D1-D4/A1-A3 + RTS + +* --------------------------- +* LCASE +* --------------------------- + +* LOWER-CASIFY A LINE OF INPUT, A0 -> INPUT, D0.W = LEN + +LCASE BRA.S LCSX3 +LCSX1 CMPI.B #'A',(A0) * UPPERCASE CHAR? + BLT.S LCSX2 * NO + CMPI.B #'Z',(A0) * MAYBE? + BGT.S LCSX2 * NO + ADDI.B #32,(A0) * YES, LOWER-CASIFY IT +LCSX2 ADDQ.L #1,A0 +LCSX3 DBF D0,LCSX1 * ZERO CHECK << ENTRY POINT >> + RTS + +* ------------------------------ +* FINDBK +* ------------------------------ + +* FIND THE NEXT BREAK CHARACTER +* GIVEN A0 -> INPUT START, D0.W = INPUT LENGTH +* RETURN A0 -> FIRST WORD START, D0.W = FIRST WORD LENGTH, OR ZERO + +FINDBK MOVEM.L D1/A1-A3,-(SP) + MOVE.L A0,A2 + ADDA.W D0,A2 * END OF INPUT (+1) + CLR.W D1 * COUNT OF SIGNIFICANT CHARS + +FBX1 MOVE.L A0,A1 * REMEMBER START OF CURRENT WORD +FBX2 CMPA.L A0,A2 * END OF INPUT STRING? + BEQ.S FBX8 * YES + MOVE.B (A0)+,D0 * NO, PICK UP NEXT CHAR + + MOVE.L RBRKS(A6),A3 * LIST OF READ-BREAK CHARACTERS + CMPI.B #127,D0 * BUT IS THIS A FUNCTION KEY? + BHI.S FBX6 * YES, CONSIDER IT A S.I. BREAK (?) +FBX4 CMP.B (A3),D0 * SEARCH LIST FOR CHAR << XZIP: "NULL" TOO >> + BEQ.S FBX6 * FOUND IT + TST.B (A3)+ * END OF (ASCIZ) LIST? + BNE FBX4 * NO, CONTINUE SEARCH + ADDQ.W #1,D1 * YES, NOT A BREAK, BUMP COUNT + BRA FBX2 + +*** BREAK CHAR FOUND ... + +FBX6 TST.W D1 * WORD READ /BEFORE/ THIS BREAK? + BNE.S FBX8 * YES, GO FOR IT + CMPA.L ESIBKS(A6),A3 * NO, BUT WAS THIS A SELF-INSERTING BREAK? + BCC.S FBX1 * BHS * NO, JUST SKIP IT, LOOP FOR NEXT + ADDQ.W #1,D1 * YES, BUMP COUNT AND GO FOR ZWORD + +*** CLEAN UP AND EXIT ... + +FBX8 MOVE.L A1,A0 * RETURN START OF CURRENT WORD + MOVE.W D1,D0 * RETURN LENGTH OF CURRENT WORD + MOVEM.L (SP)+,D1/A1-A3 + RTS + +* ------------------------------ +* RDERR +* ------------------------------ + +* TOO MANY WORDS FOUND IN THE INPUT BUFFER, INFORM LOSER +* A0 -> START OF EXCESS INPUT, A1 -> END OF INPUT (+1) + +RDERR MOVE.L A0,-(SP) * SAVE ARG HERE + BSR PUTNEW + LEA MSGIO1,A0 + BSR OUTMSG0 * '[Too many words ... "' + SECTION ZDATA +MSGIO1 DC.B '[Too many words typed, discarding ',$22,0 + SECTION ZCODE + + MOVE.L (SP)+,A0 * START OF FLUSHED WORD/STRING + MOVE.B (A1),-(SP) * SAVE TERMINAL BYTE, TO BE SAFE + CLR.B (A1) * MAKE STRING ASCIZ + BSR OUTMSG0 * ECHO IT + MOVE.B (SP)+,(A1) * RESTORE THIS BYTE + + LEA MSGIO2,A0 + BSR OUTMSG * '."]' + SECTION ZDATA +MSGIO2 DC.B '.',$22,']',0 + SECTION ZCODE + + BSR PUTNEW * FINAL CR + RTS + +* --------------------------- +* INITLX +* --------------------------- + +* INIT VOCABULARY VARS, GIVEN A VOCAB TABLE POINTER IN A0 +* (CALLED AT BEGINNING OF EACH "LEX" CALL) + +INITLX MOVEM.L D1-D2/A1-A2,-(SP) + CLR.W D0 + MOVE.B (A0)+,D0 * THIS BYTE IS THE # OF SI BREAKS + ADDA.W D0,A0 * SKIP THEM (READ DURING STARTUP ONLY) + + CLR.W D0 + MOVE.B (A0)+,D0 * THIS BYTE IS THE LENGTH OF EACH VOCTAB ENTRY + MOVE.W D0,VWLEN(A6) * SAVE IT + + MOVE.B (A0)+,D0 * THIS WORD IS # OF VOCTAB ENTRIES + ASL.W #8,D0 + MOVE.B (A0)+,D0 + MOVE.L A0,VOCBEG(A6) * THIS IS BEGINNING OF ACTUAL VOCABULARY + + TST.W D0 * IF POSITIVE #, TABLE IS SORTED + BGT.S INLX4 + NEG.W D0 * OTHERWISE, NOT SORTED, POSITIVIZE COUNT + CLR.W D1 * AND INDICATE UNSORTED TABLE + BRA.S INLX6 + +* SORTED TABLE -- CALCULATE INITIAL OFFSET FOR BINARY SEARCH + +INLX4 MOVE.W D0,D2 + MOVE.W VWLEN(A6),D1 * NUMBER OF BYTES PER VOCAB ENTRY + ASR.W #1,D2 +INLX5 ASL.W #1,D1 + ASR.W #1,D2 + BNE INLX5 + MOVE.W D1,VWBOFF(A6) * SAVE INITIAL BINARY SEARCH OFFSET + + MOVEQ #1,D1 * INDICATE A SORTED TABLE +INLX6 MOVE.W D0,VWORDS(A6) * SAVE COUNT + MOVE.W D1,VWSORT(A6) * SAVE FLAG + + SUBQ.W #1,D0 + MULS VWLEN(A6),D0 + ADD.L VOCBEG(A6),D0 * CALCULATE POINTER TO LAST ENTRY + MOVE.L D0,VOCEND(A6) * SAVE IT + + MOVEM.L (SP)+,D1-D2/A1-A2 + RTS + +* ------------------------------ +* LOOKUP +* ------------------------------ + +* SEARCH (CURRENT) VOCAB TABLE FOR A ZWORD, POINTER TO ZWORD IN A0 +* RETURN ZWORD'S TABLE ADDR (RELATIVIZED) IN D0.W, NULL IF NOT FOUND + +LOOKUP MOVEM.L D1/A1-A3,-(SP) + MOVE.L A0,A3 * SAVE POINTER TO GIVEN ZWORD HERE + MOVE.L VOCBEG(A6),A2 * BEGINNING OF (CURRENT) VOCABULARY TABLE + + TST.W VWORDS(A6) * EMPTY TABLE? + BEQ.S LKX14 * YES, RETURN ZERO + TST.W VWSORT(A6) * SORTED TABLE? + BNE.S LKX2 * YES + +LKX1 MOVE.L A2,A0 * NO, MUST DO LINEAR SEARCH + MOVE.L A3,A1 + BSR VCOMP * COMPARE GIVEN WORD TO CURRENT WORD + BEQ.S LKX12 * SAME, WE'VE FOUND IT + + ADDA.W VWLEN(A6),A2 * NEXT TABLE ITEM + CMPA.L VOCEND(A6),A2 * HAVE WE MOVED PAST END OF TABLE? + BLS LKX1 * NO + BRA.S LKX14 * YES, WORD NOT FOUND, RETURN ZERO + +*** SORTED TABLE + +LKX2 MOVE.W VWBOFF(A6),D1 * INITIAL OFFSET FOR BINARY SEARCH + ADDA.W D1,A2 * INITIAL POINTER INTO TABLE + SUBA.W VWLEN(A6),A2 * AVOID FENCE-POST BUG, EXACT-POWER-OF-2 TABLE + +LKX4 ASR.W #1,D1 * NEXT OFFSET WILL BE HALF OF PREVIOUS ONE + MOVE.L A2,A0 + MOVE.L A3,A1 + BSR VCOMP * COMPARE GIVEN WORD TO CURRENT WORD + BHI.S LKX8 * GREATER, MOVE DOWN + BEQ.S LKX12 * SAME, WE'VE FOUND IT +*** BCS.S LKX6 * (BLO) * LESS, MOVE UP + +LKX6 ADDA.W D1,A2 * TO MOVE UP, ADD OFFSET + CMPA.L VOCEND(A6),A2 * HAVE WE MOVED PAST END OF TABLE? + BLS.S LKX10 * NO + MOVE.L VOCEND(A6),A2 * YES, POINT TO END OF TABLE + BRA.S LKX10 +LKX8 SUBA.W D1,A2 * TO MOVE DOWN, JUST SUBTRACT OFFSET + +LKX10 CMP.W VWLEN(A6),D1 * IS OFFSET RESOLUTION AT LEAST ONE WORD? + BGE LKX4 * YES, CONTINUE LOOP + BRA.S LKX14 * NO, WORD NOT FOUND + +*** DONE, WINNING VOCAB POINTER LEFT IN A2 + +LKX12 MOVE.L A2,D0 + SUB.L BUFFER(A6),D0 * RELATIVIZE THE ZWORD'S VOCAB TABLE OFFSET + BRA.S LKX16 + +LKX14 MOVEQ #0,D0 * WORD NOT FOUND, RETURN ZERO +LKX16 MOVEM.L (SP)+,D1/A1-A3 + RTS + +* ------------------------------ +* VCOMP +* ------------------------------ + +* COMPARE GIVEN ZWORD (A1) TO CURRENT TABLE ZWORD (A0) +* RETURN WITH FLAGS + +VCOMP MOVEQ #ZCHARS-1,D0 * CHECK THREE WORDS +VCPX1 CMPM.B (A1)+,(A0)+ + DBNE D0,VCPX1 * TAKE BRANCH IF EQUAL + RTS + +* UNROLL THE LOOP (RUNS A BIT FASTER) + +** CMPM.B (A1)+,(A0)+ * CHECK FIRST WORD +** BNE.S VCPX2 * DIFFERENT, EXIT +** CMPM.B (A1)+,(A0)+ +** BNE.S VCPX2 + +** CMPM.B (A1)+,(A0)+ * CHECK SECOND WORD +** BNE.S VCPX2 * DIFFERENT, EXIT +** CMPM.B (A1)+,(A0)+ +** BNE.S VCPX2 + +** IFEQ EZIP +** CMPM.B (A1)+,(A0)+ * CHECK THIRD WORD +** BNE.S VCPX2 * DIFFERENT, EXIT +** CMPM.B (A1)+,(A0)+ +** BNE.S VCPX2 +** ENDC + +* VCPX2 RTS * OTHERWISE SAME, EXIT + + +* ------------------------------ +* TIMEOUT PRIMITIVES +* ------------------------------ + +* NOTE: FOR THE AMIGA, INSTEAD OF A SIMPLE "BUSY LOOP," THIS TIMEOUT +* IMPLEMENTATION EXPECTS THE KEY-CHECKING ROUTINE TO SLEEP WHEN NOTHING +* IS HAPPENING, WAKING ONLY EVERY 1/10 SEC TO RETURN A NULL EVENT. + +* ---------------------- +* TRESET, TNEXT +* ---------------------- + +* RESET THE TIMEOUT COUNTDOWN VARS + +TRESET TST.W TWAIT(A6) * BUT ARE TIMOUTS IN EFFECT? + BLT.S TNEX1 * NO, EXIT + +*** BSR TIME60 +*** MOVE.L D0,TCLOCK(A6) * INITIAL REFERENCE TIME (IN 60THS) + +TNEXT MOVE.W TWAIT(A6),TCOUNT(A6) * TOTAL DELAY (IN 10THS) +TNEX1 RTS + +* ---------------------- +* TCHECK +* ---------------------- + +* UPDATE THE TIMEOUT COUNTER [AMIGA: BUT IGNORE CLOCK] +* RETURN TIME REMAINING (ZERO IF NONE) & FLAGS + +* THE TIMEOUT COUNTDOWN MECHANISM IS CHANGED A BIT; IT NOW FUNCTIONS ONLY +* WHEN THE BUSY LOOP IS RUNNING. IT'S SUSPENDED IF THE LOOP STOPS FOR +* MORE THAT 1/10 SEC (E.G. WHEN A DESK ACCESSORY IS UP, OR A MENU IS PULLED +* DOWN. OTHERWISE, A TIMEOUT COULD OCCUR IN THE BACKGROUND, AND A NOXIOUS +* EVENT COULD SPILL OUT THE MOMENT THE GAME IS SWITCHED BACK IN.) + +TCHECK +*** BSR TIME60 * CURRENT TIME (IN 60THS) +*** SUB.L TCLOCK(A6),D0 * ELAPSED TIME, SINCE LAST CHECK +*** CMPI.L #12,D0 +*** BGE.S TCHX2 * ET >= 2/10, RESET CLOCK, DON'T TOUCH COUNTER +*** SUBQ.L #6,D0 +*** BLT.S TCHX3 * ET < 1/10, DO NOTHING + + SUBQ.W #1,TCOUNT(A6) * 1/10 <= ET < 2/10, UPDATE CLOCK & COUNTER +*** MOVEQ #6,D0 +*** TCHX2 ADD.L D0,TCLOCK(A6) + +TCHX3 MOVE.W TCOUNT(A6),D0 * RETURN COUNTER/FLAGS + RTS + + + PAGE +* --------------------------------------------------------------------------- +* I/O OPERATIONS -- OUTPUT +* --------------------------------------------------------------------------- + +* ---------------------- +* OPUSL +* ---------------------- + +* OPUSL (UPDATE STATUS LINE) + + IFEQ EZIP +OPUSL BRA OPERR * DEAD INSTRUCTION + ENDC + +* ---------------------- +* OPPRNC +* ---------------------- + +* PRINTC (PRINT CHAR WHOSE ASCII VALUE IS GIVEN) + +OPPRNC BRA PUTCHR * HANDLE IT + +* ---------------------- +* OPPRNN +* ---------------------- + +* PRINTN (PRINT A NUMBER, USING CURRENT CHARACTER OUTPUT FUNCTION) + +OPPRNN MOVE.W D0,D1 * NON-ZERO NUMBER? + BNE.S PRNNX1 * YES + MOVE.B #'0',D0 * ZERO, SPECIAL CASE + BRA PUTCHR * PRINT A ZERO + +PRNNX1 BGT.S PRNNX2 * POSITIVE? + MOVE.B #'-',D0 * NO, PRINT A MINUS SIGN + BSR PUTCHR + NEG.W D1 * AND MAKE NUMBER POSITIVE + +PRNNX2 CLR.W D2 * COUNT OF DIGITS ON STACK + BRA.S PRNNX4 * START WITH GREATER-THAN-10 TEST + +PRNNX3 EXT.L D1 * CLEAR HIGH WORD FOR DIVISION + DIVU #10,D1 * EXTRACT A DIGIT (THE REMAINDER) + SWAP D1 + MOVE.W D1,-(SP) * PUSH IT + SWAP D1 + ADDQ.W #1,D2 * BUMP COUNT + +PRNNX4 CMPI.W #10,D1 * ANY MORE DIGITS TO EXTRACT? + BGE PRNNX3 * YES + MOVE.W D1,D0 * NO, POSITION LAST (FIRST) DIGIT + BRA.S PRNNX6 + +PRNNX5 MOVE.W (SP)+,D0 * POP NEXT DIGIT +PRNNX6 ADDI.B #'0',D0 * ASCIIZE IT + BSR PUTCHR * PRINT NEXT DIGIT + SUBQ.W #1,D2 * ANY DIGITS LEFT ON STACK? + BGE PRNNX5 * YES + RTS + +* ---------------------- +* OPPRIN +* ---------------------- + +* PRINT (THE STRING POINTED TO) + + IFEQ EZIP +OPPRIN BSR BSPLTQ * SPLIT THE BLOCK AND OFFSET (QUAD) + ENDC + IFEQ CZIP +OPPRIN BSR BSPLIT * SPLIT THE BLOCK AND OFFSET (WORD) + ENDC + BRA PUTSTR * PRINT THE STRING + +* ---------------------- +* OPPRNB +* ---------------------- + +* PRINTB (THE STRING POINTED TO) + +OPPRNB BSR BSPLTB * SPLIT THE BLOCK AND OFFSET (BYTE) + BRA PUTSTR * PRINT THE STRING + +* ---------------------- +* OPPRND +* ---------------------- + +* PRINTD (PRINT OBJ'S SHORT DESCRIPTION) + +OPPRND BSR OBJLOC * FIND OBJECT'S LOCATION + ADDA.W #PROP,A0 * PROPERTY TABLE POINTER (ZIP/EZIP) + BSR GTAWRD * GET IT + + ADDQ.W #1,D0 * POINT TO SHORT DESCRIPTION STRING + BSR BSPLTB * SPLIT THE POINTER + BRA PUTSTR * AND PRINT THE STRING + +* ---------------------- +* OPPRNI +* ---------------------- + +* PRINTI (PRINT THE STRING FOLLOWING THIS INSTRUCTION) + +OPPRNI MOVE.W ZPC1(A6),D0 * GET POINTER TO STRING + MOVE.W ZPC2(A6),D1 + BSR PUTSTR * PRINT IT + MOVE.W D0,ZPC1(A6) * AND UPDATE ZPC + MOVE.W D1,ZPC2(A6) + BRA NEWZPC + +* ---------------------- +* OPPRNR +* ---------------------- + +* PRINTR (PRINTI FOLLOWED BY RTRUE) + +OPPRNR BSR OPPRNI * DO A PRINTI + BSR OPCRLF * A CRLF + BRA OPRTRU * AND AN RTRUE + +* ---------------------- +* OPCRLF +* ---------------------- + +* CRLF (DO A NEWLINE) + +OPCRLF BRA PUTNEW * DO A NEWLINE + + +* ---------------------- +* OPSPLT +* ---------------------- + +* SPLIT THE SCREEN INTO TWO PARTS, SCREEN 0 (BOTTOM) AND 1 (TOP) +* GIVEN D0 = LINES IN TOP PART + +OPSPLT MOVE.W D0,D2 * SAVE SPLIT COUNT HERE + BSR PUTLIN1 * EMPTY (&ZERO) BUFFER IF NEEDED + + BSR MAXSCRN + MOVE.W D0,D3 * SAVE TOTAL ROWS HERE + CMP.W D3,D2 + BLE.S SPLTX1 + MOVE.W D3,D2 * CAN'T TAKE MORE THAN FULL SCREEN + +SPLTX1 TST.W D2 * IS THE COUNT ZERO? + BNE.S SPLTX2 + MOVEQ #0,D0 * YES, "AUTO-REVERT" TO SCREEN 0 + BSR SETSCRN + +SPLTX2 MOVE.W D2,D0 + BSR SETSPLT * REMEMBER NEW SIZE + BSR GETSCRN * CURENTLY IN SCREEN 1 (TOP)? + BEQ.S SPLTX3 * NO + + MOVEQ #1,D0 * YES, HOME THE CURSOR IMMEDIATELY + MOVEQ #1,D1 + BSR SETCURS + BRA.S SPLTX5 * DONE + +* MAKE SURE THE CURSOR WILL BE HOMED UPON NEXT (FIRST) SWITCH TO SCREEN 1 + +SPLTX3 MOVEQ #1,D0 * (THESE VARS ARE 1-ORIGIN TOO) + MOVE.W D0,ROW1(A6) + MOVE.W D0,COL1(A6) + +* Cursor is logically in Screen 0, but may need to "push it down" to keep +* it physically in Screen 0. (But make sure it's not off screen!) + + BSR GETCURS * (ROW, 1-ORIGIN) + CMP.W D2,D0 * DID SCREEN 1 "OVERGROW" US? + BGT.S SPLTX5 * NO, DONE + + ADDQ.W #1,D2 * YES, MOVE TO TOP OF W0 (1-ORIGIN) + CMP.W D3,D2 * BUT OFF BOTTOM? (W0 = ENTIRE SCREEN) + BLE.S SPLTX4 * NO + SUBQ.W #1,D2 * YES, BACKUP (EVEN THO NOW IN WINDOW 1) + +SPLTX4 MOVE.W D2,D0 + MOVEQ #1,D1 + BSR SETCURS * "PUSH DOWN" THE CURSOR +SPLTX5 RTS + +* ---------------------- +* OPSCRN +* ---------------------- + +* MAKE OUTPUT FALL INTO SPECIFIED WINDOW + +OPSCRN MOVE.W D0,D1 * SAVE ARG + BSR PUTLIN1 * EMPTY(&ZERO) BUFFER IF NEEDED + + TST.W D1 * WINDOW 0 (BOTTOM)? + BEQ.S SCRNX1 * YES + SUBQ.W #1,D1 * WINDOW 1? + BEQ.S SCRNX3 * YES + BRA.S SCRNX5 * "IGNORE OTHER ARGS" + +* SWITCH TO WINDOW 0 + +SCRNX1 BSR GETSCRN * BUT ALREADY IN W0? + BEQ.S SCRNX5 * YES, DONE + +* "SAVE W1 CURSOR POS, RESTORE OLD W0 CURSOR POS" + + BSR GETCURS * GET W1 CURSOR POS [1-ORIGIN] + MOVE.W D0,ROW1(A6) * AND STORE IT + MOVE.W D1,COL1(A6) + + MOVEQ #0,D0 * SWITCH TO WINDOW 0 + BSR SETSCRN + + MOVE.W ROW0(A6),D0 + MOVE.W COL0(A6),D1 + BSR SETCURS * RESTORE FORMER POS [1-ORIGIN] + BRA.S SCRNX5 * DONE + +* SWITCH TO WINDOW 1 + +SCRNX3 BSR GETSPLT * BUT HAS THE SCREEN BEEN SPLIT? + TST.W D0 + BEQ.S SCRNX5 * NO, ERROR, SKIP OUT + + BSR GETSCRN * YES, BUT ALREADY IN W1? + BNE.S SCRNX5 * YES, DONE + +* "SAVE W0 CURSOR POS, RESTORE OLD W1 CURSOR POS" + + BSR GETCURS * GET W0 CURSOR POS [1-ORIGIN] + MOVE.W D0,ROW0(A6) * AND STORE IT + MOVE.W D1,COL0(A6) + + MOVEQ #1,D0 * SWITCH TO WINDOW 1 + BSR SETSCRN + + MOVE.W ROW1(A6),D0 * [THESE NOW INITED IN OPSPLIT] + MOVE.W COL1(A6),D1 + BSR SETCURS * RESTORE FORMER POS [1-ORIGIN] +SCRNX5 RTS + +* ---------------------- +* OPBUFO +* ---------------------- + +* SET BUFFERING OF OUTPUT ACCORDING TO INT + +* >>> OBSOLETE OP -- AMIGA XZIP RUNS /MUCH/ FASTER WITHOUT IT <<< + +OPBUFO RTS + + SUBQ.W #1,D0 * NORMAL BUFFERING? + BEQ.S BUFOX1 * YES + ADDQ.W #1,D0 * NO BUFFERING, OUTPUT DIRECTLY TO SCREEN? + BEQ.S BUFOX2 * YES + BRA.S BUFOX3 * ELSE DO NOTHING + +BUFOX1 MOVE.W #1,VOBUFF(A6) * TURN ON BUFFERING + BRA.S BUFOX3 +BUFOX2 BSR PUTLIN * FIRST EMPTY THE CURRENT OUTPUT BUFFER + CLR.W VOBUFF(A6) * THEN TURN OFF BUFFERING +BUFOX3 RTS + + +* ---------------------- +* TABCHR +* ---------------------- + +* TABLE OUTPUT FUNCTION --- PUT THE CHAR IN D0 IN THE DEFINED TABLE + +TABCHR MOVE.L TABPTR(A6),A0 * CURRENT POSITION IN TABLE + MOVE.B D0,(A0)+ * STORE CHAR + MOVE.L A0,TABPTR(A6) * UPDATE POINTER + RTS + +* ---------------------- +* OPDIRO +* ---------------------- + +* REDIRECT OUTPUT (TABLE OR NORMAL) ACCORDING TO INT + +OPDIRO NOP * TELL CALLER TO USE ARGBLK + MOVE.W ARG1(A0),D0 * VIRTUAL OUTPUT DEVICE -- NEGATIVE? + BLT.S DIRX0 * YES, MEANS TURN IT OFF + + SUBQ.W #1,D0 * TURN ON SCREEN? + BEQ.S DIRX1 * YES + SUBQ.W #1,D0 * TURN ON PRINTER? + BEQ.S DIRX3 * YES + SUBQ.W #1,D0 * TURN ON TABLE? + BEQ DIRX5 * YES + RTS * UNKNOWN DEVICE, IGNORE REQUEST + +DIRX0 ADDQ.W #1,D0 * TURN OFF SCREEN? + BEQ.S DIRX2 * YES + ADDQ.W #1,D0 * TURN OFF PRINTER? + BEQ.S DIRX4 * YES + ADDQ.W #1,D0 * TURN OFF TABLE? + BEQ DIRX6 * YES + RTS * UNKNOWN DEVICE, IGNORE REQUEST + +*** TURN SCREEN OUTPUT ON, OFF + +DIRX1 MOVE.W #1,VOCONS(A6) + BRA DIRX7 +DIRX2 BSR PUTLIN * BUT FIRST DUMP BUFFER, IF NEEDED + CLR.W VOCONS(A6) + BRA DIRX7 + +*** TURN SCRIPTING OUTPUT ON, OFF + +DIRX3 TST.W VOPRNT(A6) * ALREADY ON? + BNE.S DIRX7 * YES + + MOVE.W #1,D0 + MOVE.W D0,VOPRNT(A6) + BSR SCRINIT * OPEN SCRIPT CHANNEL (IF NEEDED) + TST.W D0 + BEQ.S DIRX3A * ERROR + + MOVE.L BUFFER(A6),A0 + BSET #0,PFLAGS+1(A0) * SET PRELOAD FLAG FOR GAME'S USE + BRA.S DIRX7 +DIRX3A BSR SCRERR * UNDO EVERYTHING, SHOW MESSAGE + BRA.S DIRX7 + +DIRX4 TST.W VOPRNT(A6) * ALREADY OFF? + BEQ.S DIRX7 * YES + + MOVEQ #0,D0 + MOVE.W D0,VOPRNT(A6) + BSR SCRINIT * CLOSE SCRIPT CHANNEL (IF NEEDED) + + MOVE.L BUFFER(A6),A0 + BCLR #0,PFLAGS+1(A0) * CLEAR THE PRELOAD FLAG + BRA.S DIRX7 + +*** TURN TABLE ON, OFF + +DIRX5 MOVEQ #0,D0 + MOVE.W ARG2(A0),D0 * GET RELATIVE TABLE POINTER + ADD.L BUFFER(A6),D0 * ABSOLUTIZE + MOVE.L D0,TABOUT(A6) * REMEMBER START OF TABLE + + ADDQ.L #2,D0 * SKIP LENGTH SLOT + MOVE.L D0,TABPTR(A6) * FIRST CHAR WILL GO HERE + + MOVE.W #1,VOTABL(A6) * SET TABLE-OUTPUT FLAG + BRA.S DIRX7 + +DIRX6 TST.W VOTABL(A6) * MAKE SURE A TABLE DOES EXIST + BEQ.S DIRX7 * NO TABLE, IGNORE REQUEST + CLR.W VOTABL(A6) * OK, TURN OFF TABLE-OUTPUT FLAG + + MOVE.L TABOUT(A6),A0 * COMPUTE LENGTH OF CURRENT TABLE CONTENTS + MOVE.L TABPTR(A6),D0 + SUB.L A0,D0 + SUBQ.W #2,D0 * ADJUST FOR LENGTH SLOT + BSR PTAWRD * AND STORE LENGTH IN LENGTH SLOT + +DIRX7 RTS + +* REDIRECT INPUT (NORMAL OR COMMAND FILE) ACCORDING TO INT + +* ---------------------- +* OPDIRI +* ---------------------- + +OPDIRI NOP * TELL CALLER TO USE ARGBLK +*** 0 MEANS KEYBOARD, 1 MEANS SPECIAL FILE -- NOT IMPLEMENTED + RTS + +* ---------------------- +* OPSOUND +* ---------------------- + +* MAKE A SOUND +* ARG1 = ID: 1=BEEP, 2=BOOP, 3+ ARE SPECIAL, 0=MRU +* [ARG2] = ACTION: 1=INIT, [2=START], 3=STOP, 4=CLEANUP +* [ARG3] = COUNT (HIBYTE): -1=INFINITE, [0=USE MIDI COUNT], 1-254=FINITE +* VOL (LOBYTE): 0=MIN, 8=MAX, [-1=USE MIDI VOLUME] +* [ARG4] = INTERRUPT FUNCTION + +OPSOUND NOP * REQUEST AN ARGBLK + LEA DEFBLK(A6),A1 * USE A DEFAULT ARGBLK, TOO + MOVE.W #4,(A1) * 4 ARGS MAX + MOVE.W #2,ARG2(A1) * DEFAULT ACTION = "START" + MOVE.W #$00FF,ARG3(A1) * DEFAULT COUNT=0/VOL=-1 (USE MIDI DATA) + CLR.W ARG4(A1) * DEFAULT INTERRUPT HANDLER = NONE + BSR SETDEF * SET UP DEFAULTS + + MOVE.W ARG4(A0),SFUNC(A6) * SAVE INTERRUPT HERE + MOVE.W ARG3(A0),D2 * COUNT/VOL + MOVE.W D2,D3 + EXT.W D2 * VOL (16 BITS) + LSR.W #8,D3 * COUNT (16 BITS, UNLESS -1) + CMPI.B #$FF,D3 * -1? + BNE.S OPSDX1 + EXT.W D3 * YES, MAKE 16 BITS + +OPSDX1 MOVE.W ARG2(A0),D1 * ACTION + MOVE.W ARG1(A0),D0 * SOUND ID + BRA DOSOUND + +* --------------------------------------------------------------------------- +* MORE I/O OPERATIONS -- SCREEN HANDLING +* --------------------------------------------------------------------------- + +* ---------------------- +* OPCLEAR +* ---------------------- + +* CLEAR A WINDOW, OR ENTIRE SCREEN + +OPCLEAR MOVE.W D0,D1 + BSR PUTLIN * FIRST EMPTY BUFFER, IF NEEDED + + ADDQ.W #1,D1 * ENTIRE SCREEN? + BEQ.S CLRX1 * YES + SUBQ.W #1,D1 * WINDOW 0 ONLY? + BEQ.S CLRX2 * YES + SUBQ.W #1,D1 * WINDOW 1 ONLY? + BEQ.S CLRX3 * YES + BRA.S CLRX9 * INVALID ARG, IGNORE IT + +CLRX1 CLR.W D0 + BSR SETSPLT * UNSPLIT THE SCREEN, FALL THRU + +* WINDOW 0 (BOTTOM) + +CLRX2 BSR MAXSCRN + MOVE.W D0,D1 * LAST ROW OF WINDOW 0 (INCLUSIVE) + BSR GETSPLT + ADDQ.W #1,D0 * FIRST ROW (1-ORIGIN) + BSR MDCLEAR * CLEAR THEM + + BSR GETSCRN * IN WINDOW 0 CURRENTLY? + BNE.S CLRX9 * NO + BSR MAXSCRN + MOVE.W D0,D2 * YES, GET MAX ROWS + + BSR GETMARG + MOVE.W D0,D1 + ADDQ.W #1,D1 * FIRST COL (1-ORIGIN) + BSR GETSPLT + ADDQ.W #1,D0 * FIRST ROW (1-ORIGIN) + + CMP.W D2,D0 * BUT MAKE SURE NOT OFF BOTTOM OF SCREEN! + BLE.S CLRX2A + MOVE.W D2,D0 * WE ARE, FUDGE IT +CLRX2A BSR SETCURS + + CLR.W LINES(A6) * RESET THE COUNTER FOR SCROLLING + BRA.S CLRX9 + +* WINDOW 1 (TOP) + +CLRX3 BSR GETSPLT + MOVE.W D0,D1 * LAST ROW OF WINDOW 1 (INCLUSIVE) + MOVEQ #1,D0 * FIRST ROW (1-ORIGIN) + BSR MDCLEAR * CLEAR THEM + + BSR GETSCRN * IN WINDOW 1 CURRENTLY? + BEQ.S CLRX9 * NO + + BSR GETMARG + MOVE.W D0,D1 + ADDQ.W #1,D1 * FIRST COL (1-ORIGIN) + MOVEQ #1,D0 * FIRST ROW (1-ORIGIN) + BSR SETCURS +CLRX9 RTS + +* ---------------------- +* OPERASE +* ---------------------- + +* ERASE (CURRENT LINE, STARTING AT CURSOR) + +OPERASE SUBQ.W #1,D0 + BNE.S ERAX1 * "IGNORE ARG IF NOT 1" + BSR PUTLIN * EMPTY BUFFER, IF NEEDED + BSR MDERASE +ERAX1 RTS + +* ---------------------- +* OPCURS +* ---------------------- + +* SET CURSOR TO LINE INT1, COLUMN INT2 [ARGS ARE 1-ORIGIN] + +OPCURS MOVE.W D0,D2 * PROTECT ARG + BSR PUTLIN1 * EMPTY(&ZERO) BUFFER IF NEEDED + MOVE.W D2,D0 + BRA SETCURS * D0 = ROW, D1 = COL + +* ---------------------- +* OPCURG +* ---------------------- + +* GET CURSOR POSITION [1-ORIGIN] + +OPCURG BSR RELABS * TABLE FOR RETURN VALUES + MOVE.L A0,A1 + BSR GETCURS + MOVE.L A1,A0 + BSR PTAWRD * STORE ROW + MOVE.L A1,A0 + ADDQ.L #2,A0 + MOVE.W D1,D0 + BRA PTAWRD * STORE COLUMN + +* ---------------------- +* OPATTR +* ---------------------- + +* HIGHLIGHT (SET CHAR ATTRIBUTES) + +OPATTR MOVE.L D0,D1 + BSR PUTLIN * EMPTY THE LINE BUFFER (IN OLD MODE) + + MOVE.W D1,D0 + BRA MDATTR * 1 INVERSE, 2 BOLD, 4 ITALIC (8 MONO) + +* ---------------------- +* OPFONT +* ---------------------- + +OPFONT MOVE.W D0,D1 * NEW FONT NUMBER + BSR GETFONT * OLD FONT NUMBER (IN CURRENT WINDOW) + MOVE.W D0,D2 + CMP.W D1,D2 * >>> IS THE FONT REALLY CHANGING? <<< + BEQ.S FONTX2 * NO, DON'T EMPTY BUFFER + +*?* BSR GETSCRN * BUT ARE WE IN WINDOW 1? +*?* BNE.S FONTX1 * YES + BSR PUTLIN * EMPTY THE LINE BUFFER (IN OLD FONT) + +FONTX1 MOVE.W D1,D0 + BSR SETFONT * SET NEW FONT NUMBER +FONTX2 MOVE.W D2,D0 + BRA PUTVAL * RETURN OLD FONT NUMBER + +* ---------------------- +* OPCOLOR +* ---------------------- + +OPCOLOR MOVE.W D0,D2 * PROTECT THIS ARG + BSR PUTLIN * EMPTY THE LINE BUFFER + MOVE.W D2,D0 + BRA MDCOLOR + +* ---------------------- +* OPPICI +* ---------------------- + +* GET PICTURE INFO (SIZE) + +OPPICI EXG D0,D1 * TABLE OFFSET + BSR RELABS * ABSOLUTIZE + MOVE.W D1,D0 * PICTURE ID + BSR PICINF * GET SIZE INFO, STORE IN TABLE + BLT.S OPICX1 * NEG RESULT MEANS ERROR + BRA PTRUE +OPICX1 BRA PFALSE + +* ---------------------- +* OPDISP, OPDCLR +* ---------------------- + +* DISPLAY [OR CLEAR] A PICTURE + +OPDCLR MOVEQ #1,D3 * "CLEAR" FLAG ON + BRA.S DISPX1 + +OPDISP MOVEQ #0,D3 * "CLEAR" FLAG OFF +DISPX1 BRA PICDISP + +* ---------------------- +* OPMARG +* ---------------------- + +* SET MARGINS + +OPMARG MOVE.W D0,D2 * SAVE ARGS + MOVE.W D1,D3 + BSR SETMARG * UPDATE DISPLAY VARS + + MOVE.L BUFFER(A6),A0 * UPDATE GAME VARS + MOVE.W D2,PLMRG(A0) * (MAC: 1 CHAR = 1 PIXEL UNIT) + MOVE.W D3,PRMRG(A0) + + MOVEQ #-1,D0 * [DON'T CHANGE ROW] + MOVE.W D2,D1 * SET COLUMN TO NEW LEFT MARGIN + ADDQ.W #1,D1 * [1-ORIGIN] + BSR SETCURS + + BSR MAXSCRN + MOVE.W D1,D0 * MAX COLUMNS + SUB.W D2,D0 + SUB.W D3,D0 * COMPUTE NEW LINE LENGTH + MOVE.L DQUE(A6),A0 + BRA SIZEQP * AND UPDATE WORD-WRAP + + PAGE +* ---------------------------------------------------------------------------- +* CONTROL OPERATIONS +* ---------------------------------------------------------------------------- + +MAXLOCS EQU 15 * MAXIMUM LOCALS; VARS 16-255 ARE GLOBAL +CVFLAG EQU $0100 * FLAG SET (HIGH BYTE) IF CALL RETURNS A VALUE + +* ---------------------- +* OPICALL, ETC +* ---------------------- + +* CALL (A FUNCTION WITH OPTIONAL ARGUMENTS), NO RETURNED VALUE + +OPICAL1 LEA ARGBLK(A6),A0 * MUST SET UP AN ARGUMENT BLOCK FOR 1-OP + MOVE.W #1,(A0) * ONE ARG (THE FUNCTION) + MOVE.W D0,ARG1(A0) + +OPICAL2 +OPIXCAL +OPICALL NOP * TELL CALLER TO USE ARGBLK + MOVEQ #0,D3 * FLAG -- DON'T RETURN A VALUE + BRA.S CALLX1 + +* ---------------------- +* OPCALL, ETC +* ---------------------- + +* CALL (A FUNCTION WITH OPTIONAL ARGUMENTS) + +OPCAL1 LEA ARGBLK(A6),A0 * MUST SET UP AN ARGUMENT BLOCK FOR 1-OP + MOVE.W #1,(A0) * ONE ARG (THE FUNCTION) + MOVE.W D0,ARG1(A0) + +OPCAL2 +OPXCAL +OPCALL NOP * TELL CALLER TO USE ARGBLK + MOVE.W #CVFLAG,D3 * FLAG (HIGH BYTE) -- RETURN A VALUE + +*** COMMON ENTRY POINT, A0 -> ARGBLK, D3 (HIGH BYTE) = RETURN-VALUE FLAG + +CALLX1 MOVE.L A0,A2 + MOVE.W (A2)+,D2 * ARG COUNT + MOVE.W (A2)+,D0 * FUNCTION TO CALL -- IS IT ZERO? + BNE.S CALLX2 * NO + + TST.W D3 * SPECIAL CASE -- RETURN A VALUE? + BEQ.S CALLX9 * NO, JUST EXIT +* CLR.W D0 * YES, RETURN A ZERO + BRA PUTVAL + +*** BUILD A STACK FRAME, THEN UPDATE THE ZPC AND STATE VARS ... + +CALLX2 MOVE.W ZPC1(A6),-(A4) * SAVE OLD ZPC + MOVE.W ZPC2(A6),-(A4) + MOVE.B NARGS+1(A6),D3 * SAVE OLD "OPTIONALS" COUNT ... + MOVE.W D3,-(A4) * ALONG WITH /NEW/ RETURN FLAG + +* >>> old locs pointer (rel) now stacked as word, instead of long <<< +* >>> new locs pointer now points to (pseudo) loc 0, instead of 1 <<< + + MOVE.L ZLOCS(A6),D1 * OLD LOCALS/FRAME POINTER + SUB.L STKBOT(A6),D1 * BUT RELATIVIZE IT, IN CASE OF GAME SAVE + MOVE.W D1,-(A4) * SAVE IT + MOVE.L A4,ZLOCS(A6) * NEW LOCALS/FRAME POINTER + + SUBQ.W #1,D2 * NUMBER OF PARAMETERS ("OPTIONALS") + MOVE.B D2,NARGS+1(A6) * REMEMBER IT (BYTE) + + BSR BSPLTQ * SPLIT THE FUNCTION POINTER (IN D0) + MOVE.W D0,ZPC1(A6) * MAKE IT THE NEW ZPC + MOVE.W D1,ZPC2(A6) + BSR NEWZPC * UPDATE ZPC STUFF + +*** GET FUNCTION HEADER + + BSR NXTBYT * TOTAL # DEFINED LOCALS + MOVE.W D0,D1 + CMPI.W #MAXLOCS,D1 * VALID? + BLS.S CALLX3 + LEA MSGCA1,A0 * TOO MANY LOCALS DEFINED + BSR ZWARN * SHOW A WARNING + MOVEQ #MAXLOCS,D1 * (CUT BACK -- CAN'T BE TOUCHED ANYWAY) + +CALLX3 CMP.W D2,D1 * VALID? + BCC.S CALLX4 * BHS + LEA MSGCA2,A0 * TOO MANY OPTIONALS SUPPLIED + BSR ZWARN * SHOW A WARNING + MOVE.W D1,D2 * (CUT BACK -- WON'T BE TOUCHED ANYWAY) + +CALLX4 SUB.W D2,D1 * THIS IS NUMBER OF "DEFAULT" VALUES + BRA.S CALLX6 + + SECTION ZDATA +MSGCA1 DC.B 'Bad loc num',0 +MSGCA2 DC.B 'Bad optional num',0 + SECTION ZCODE + +*** BUILD & INITIALIZE A LOCALS FRAME ... + +CALLX5 MOVE.W (A2)+,-(A4) * POSITION THE OPTIONAL VALUES FIRST +CALLX6 DBF D2,CALLX5 * ZERO CHECK -- ANY MORE? + MOVEQ #0,D0 + BRA.S CALLX8 + +CALLX7 MOVE.W D0,-(A4) * CLEAR THE REMAINING DEFAULT VALUES [XZIP] +CALLX8 DBF D1,CALLX7 * ZERO CHECK -- ANY MORE? +CALLX9 RTS * DONE + +* ---------------------- +* OPASSN +* ---------------------- + +* ASSIGNED? (A LOCAL AN OPTIONAL VALUE) + +OPASSN CMP.B NARGS+1(A6),D0 * WAS THIS LOCAL ASSIGNED A VALUE? + BGT PFALSE * NO, VALUE DEFAULTED TO ZERO + BRA PTRUE * YES + +* ---------------------- +* OPRETU +* ---------------------- + +* RETURN (FROM CURRENT FUNCTION CALL) + +OPRETU MOVE.L ZLOCS(A6),A4 * OLD TOP-OF-STACK + MOVEQ #0,D1 + MOVE.W (A4)+,D1 * RESTORE OLD LOCALS POINTER + ADD.L STKBOT(A6),D1 * ABSOLUTIZE IT + MOVE.L D1,ZLOCS(A6) + + MOVE.W (A4)+,D2 * RESTORE RETURN FLAG, OPTS COUNT + MOVE.B D2,NARGS+1(A6) + MOVE.W (A4)+,ZPC2(A6) * RESTORE OLD ZPC + MOVE.W (A4)+,ZPC1(A6) + IFEQ EZIP + BLT INRETU * SPECIAL INTERNAL CALL/RETURN, HANDLE IT + ENDC + MOVE.W D0,D1 * PROTECT VALUE (IF ANY -- XZIP) + BSR NEWZPC * UPDATE ZPC STUFF + MOVE.W D1,D0 + + ANDI.W #CVFLAG,D2 * WAS THIS A RETURN-VALUE CALL? (XZIP) + BNE PUTVAL * YES, RETURN THE VALUE + RTS * NO, JUST EXIT + +* ---------------------- +* OPRTRU +* ---------------------- + +* RTRUE + +OPRTRU MOVEQ #1,D0 * RETURN A "1" + BRA.S OPRETU + +* ---------------------- +* OPRFAL +* ---------------------- + +* RFALSE + +OPRFAL CLR.W D0 * RETURN A "0" + BRA.S OPRETU + +* ---------------------- +* OPRSTA +* ---------------------- + +* RSTACK (RETURN STACK) + +OPRSTA MOVE.W (A4)+,D0 * POP A VALUE + BRA OPRETU * AND RETURN IT + +* ---------------------- +* OPFSTA +* ---------------------- + +* FSTACK (FLUSH A VALUE OFF THE STACK) *** DEAD -- XZIP + +* OPFSTA +* ADDQ.L #2,A4 * FLUSH ONE WORD +* RTS + +* ---------------------- +* OPJUMP +* ---------------------- + +* JUMP (TO A NEW LOCATION) + +OPJUMP SUBQ.W #2,D0 * ADJUST OFFSET + ADD.W D0,ZPC2(A6) * ADD OFFSET TO CURRENT ZPC + BRA NEWZPC * NORMALIZE IT & UPDATE ZPC STUFF + +* ---------------------- +* OPNOOP +* ---------------------- + +* NOOP (NO OPERATION) + +OPNOOP RTS * DO NOTHING + +* ---------------------- +* OPCATCH +* ---------------------- + +* CATCH + +OPCATCH MOVE.L ZLOCS(A6),D0 * THE CURRENT "FRAME POINTER" + SUB.L STKBOT(A6),D0 * RELATIVIZE IT + BRA PUTVAL + +* ---------------------- +* OPTHROW +* ---------------------- + +* THROW (NON-LOCAL RETURN) + +OPTHROW EXT.L D1 * A PREVIOUS FRAME PTR + ADD.L STKBOT(A6),D1 * ABSOLUTIZE + CMP.L ZLOCS(A6),D1 * VALID FRAME? + BLT.S THRX1 * ERROR + MOVE.L D1,ZLOCS(A6) * OK, FLUSH ANY INTERMEDIATE FRAMES + BRA OPRETU * AND RETURN VAL (STILL IN D0) + +THRX1 CLR.W D0 + LEA MSGTHR,A0 + BRA FATAL + SECTION ZDATA +MSGTHR DC.B 'Bad Throw',0 + SECTION ZCODE + +* ---------------------- +* INCALL +* ---------------------- + + IFEQ EZIP + +* INTERNALLY CALL A FUNCTION, FUNCTION IN D0, RETURN VALUE IN D0 + +INCALL MOVEM.L D1-D7/A1-A3,-(SP) * SAVE EVERYTHING + + MOVE.W ZPC1(A6),-(SP) + MOVE.W #-1,ZPC1(A6) * FAKE ZPC1, SIGNALS AN INTERNAL CALL/RETURN + + LEA ARGBLK(A6),A0 * SET UP ARGBLK FOR OPCALL + MOVE.W D0,ARG1(A0) * FUNCTION TO CALL + MOVE.W #1,(A0) * ONE ARG (FUNCTION ITSELF) + + BSR OPCALL * CALL THE TIMEOUT FUNCTION + BRA NXTINS * GO EXECUTE IT + +* ---------------------- +* INRETU +* ---------------------- + +* JUMP BACK TO HERE UPON NEXT OPRETURN ... + +INRETU ADDQ.L #4,SP * CAREFUL -- FLUSH TOP RETURN ADDR (NXTINS) + MOVE.W (SP)+,ZPC1(A6) * FIX THE ZPC + + MOVE.W D0,D1 + BSR NEWZPC * RESTORE THE PROPER PAGE + MOVE.W D1,D0 + + MOVEM.L (SP)+,D1-D7/A1-A3 + RTS * RETURN TO ORIGINAL CALLER + ENDC + + PAGE +* ---------------------------------------------------------------------------- +* GAME COMMANDS +* ---------------------------------------------------------------------------- + +* ------------------------------ +* PRIMITIVES FOR SAVE/RESTORE +* ------------------------------ + +* SAVE STATE VARIABLES ON GAME STACK + +SAVSTA MOVE.W ZPC1(A6),-(A4) + MOVE.W ZPC2(A6),-(A4) + + MOVE.L STKBOT(A6),A0 + MOVE.L ZLOCS(A6),D0 * RELATIVIZE THIS ONE + SUB.L A0,D0 + MOVE.W D0,-(A4) + MOVE.W ZORKID(A6),-(A4) + + MOVE.L A4,D0 + SUB.L A0,D0 * RELATIVIZE GAME SP, TOO + MOVE.W D0,(A0) * AND SAVE IT IN KNOWN LOCATION + ADDA.W #8,A4 * RESET THE GAME SP + RTS + +* RESTORE STATE VARIABLES FROM GAME STACK, RETURN ZORKID IN D0 AND FLAGS + +RESSTA MOVE.L STKBOT(A6),A0 + MOVEQ #0,D0 + MOVE.W (A0),D0 * RESTORE GAME SP FROM KNOWN LOCATION + ADD.L A0,D0 * RE-ABSOLUTIZE IT + MOVE.L D0,A4 + + MOVE.W (A4)+,-(SP) * GET THE SAVED ZORKID + MOVEQ #0,D0 + MOVE.W (A4)+,D0 * RESTORE OLD LOCALS POINTER + ADD.L A0,D0 * RE-ABSOLUTIZE IT + MOVE.L D0,ZLOCS(A6) + + MOVE.W (A4)+,ZPC2(A6) * RESTORE OTHER STUFF + MOVE.W (A4)+,ZPC1(A6) + + MOVE.W (SP)+,D0 + CMP.W ZORKID(A6),D0 * IS ID THE SAME AS OURS? + RTS * (RETURN WITH FLAGS) + +* ---------------------- +* OPISAV +* ---------------------- + +* ISAVE (SAVE TO MEMORY BUFFER) + +OPISAV BSR SAVSTA * SAVE STATE VARIABLES ON GAME STACK + MOVE.L MSAVEB(A6),D2 * PTR, ISAVE BUFFER + BEQ SAVERR * ERROR, BUFFER DOESN'T EXIST + MOVE.L STKBOT(A6),A0 + MOVE.L D2,A1 + MOVE.L #STKLEN,D0 + BSR MOVMEM * SAVE THE STACK (FAST BLOCKMOVE) + + MOVE.L BUFFER(A6),A0 * BEGINNING OF IMPURE STUFF IN CORE + MOVE.L D2,A1 + ADDA.W #STKLEN,A1 * START WRITING AFTER STACK + MOVE.W PURBOT(A6),D0 * IMPURE BLOCKS + BSR BLKBYT + BSR MOVMEM * SAVE IMPURE DATA (FAST BLOCKMOVE) + BRA SAVEOK * SUCCESS + +* ---------------------- +* OPSAVE +* ---------------------- + +PSNLEN EQU 32 * MAX LENGTH OF SUGGESTED NAME + +* SAVE (STATE OF GAME, OR SELECTED "PARTIAL" DATA) + +OPSAVE NOP + TST.W (A0) * PARTIAL SAVE (ANY ARGS)? + BEQ SVX2 * NO + +*** HANDLE A PARTIAL SAVE, A0 -> ARGBLK *** + + MOVE.L A0,A2 + CLR.W D0 + BSR CHKDSK * CHECK FOR GAME DISK AND CLOSE GAME FILE + + MOVE.W ARG3(A2),D0 * "SUGGESTED" NAME, BYTE 0 = LENGTH + BSR RELABS + MOVE.L A0,A1 * SAVE HERE, & PASS TO FSEL + MOVEQ #1,D0 * OPSAVE + MOVEQ #1,D1 * PARTIAL + BSR GETSFL * GET A NAME FOR THE SAVE FILE + BNE SVX14 * CANCELLED + + BSR NEWSFL * CREATE (IF NEEDED) AND OPEN THE FILE + BNE SVX14 * ERROR, JUST EXIT (NEED NOT DELETE) + +* WRITE SUGGESTED NAME TO FILE + + MOVEQ #0,D0 + MOVEQ #PSNLEN,D1 * MAX LENGTH OF SUGGESTED NAME + MOVE.L A1,A0 * STARTS HERE (WITH LENGTH BYTE) + BSR SFWRIT + BNE SVX12 * ERROR, CLOSE AND DELETE THE FILE + +* WRITE DATA TO FILE + + MOVE.W ARG1(A2),D0 * BASE OF PARTIAL SAVE + BSR RELABS * ABSOLUTIZE + MOVEQ #PSNLEN,D0 * FILE OFFSET + MOVEQ #0,D1 + MOVE.W ARG2(A2),D1 * LENGTH OF PARTIAL SAVE DATA + BSR SFWRIT + BNE SVX12 * ERROR, CLOSE AND DELETE THE FILE + + BSR DEFOLD * OK >>> BUT RESTORE "NORMAL" FILE NAMES <<< + BRA SVX10 * AND CLEAN UP + +*** ENTER HERE FOR "STANDARD" SAVE *** + +SVX2 CLR.W D0 + BSR CHKDSK * CHECK FOR GAME DISK AND CLOSE GAME FILE + + MOVEQ #1,D0 * OPSAVE + CLR.W D1 * STANDARD + BSR GETSFL * GET A NAME FOR THE SAVE FILE + BNE SVX14 * CANCELLED + + BSR NEWSFL * CREATE (IF NEEDED) AND OPEN THE FILE + BNE SVX14 * ERROR, JUST EXIT (NEED NOT DELETE) + +* SAVE GAME STACK, THEN IMPURE PRELOAD + + BSR SAVSTA * SAVE STATE VARIABLES ON GAME STACK + MOVE.L STKBOT(A6),A0 + CLR.W D0 * THIS WILL BE BLOCK ZERO + MOVEQ #STKLEN/512,D1 * BLOCK LENGTH OF STACK + BSR PTSBKS * WRITE IT OUT + BNE SVX12 * ERROR, CLOSE AND DELETE THE FILE + + MOVE.L BUFFER(A6),A0 * BEGINNING OF IMPURE STUFF IN CORE + MOVEQ #STKLEN/512,D0 * START WRITING AFTER STACK + MOVE.W PURBOT(A6),D1 * NUMBER OF IMPURE BLOCKS + BSR PTSBKS + BNE SVX12 * ERROR, CLOSE AND DELETE THE FILE + +* SAVE SUCCEEDED + +SVX10 BSR CLSSFL * SUCCESS, CLOSE THE FILE [NO ERRORS] + BSR DEFNEW * UPDATE PREVIOUS DEFAULT NAMES + BSR MAKEICON * [AMIGA: ATTACH AN ICON TO THIS FILE] + MOVEQ #1,D0 + BSR CHKDSK * MAKE SURE GAME DISK IS BACK IN DRIVE + +SAVEOK MOVEQ #1,D0 * RETURN "SAVE OK" + BRA PUTVAL + +* SAVE FAILED FOR SOME REASON ... + +SVX12 BSR CLSSFL * CLOSE THE BAD FILE + BSR DELSFL * AND DELETE THE BAD FILE FROM THE DIRECTORY + +SVX14 BSR DEFOLD * INSTALL PREVIOUS DEFAULT NAMES + MOVEQ #1,D0 + BSR CHKDSK * MAKE SURE GAME DISK IS BACK IN DRIVE + +SAVERR CLR.W D0 * RETURN "SAVE FAILED" + BRA PUTVAL + +* ---------------------- +* OPIRES +* ---------------------- + +* IRESTORE (RESTORE FROM MEMORY BUFFER) + +OPIRES MOVE.L MSAVEB(A6),D2 * PTR, ISAVE BUFFER + BEQ RESERR * ERROR, BUFFER DOESN'T EXIST + MOVE.L D2,A0 + TST.W (A0) + BEQ RESERR * ERROR, NO PREVIOUS ISAVE! + MOVE.L STKBOT(A6),A1 + MOVE.L #STKLEN,D0 + BSR MOVMEM * RESTORE THE GAME STACK (FAST BLOCKMOVE) + + BSR RESSTA * UNSTACK THE OLD STATE INFO + BNE RESX15 * ERROR, WRONG ZORKID + + MOVE.L D2,A0 + ADDA.W #STKLEN,A0 * START READING AFTER STACK + MOVE.L BUFFER(A6),A1 * BEGINNING OF IMPURE STUFF IN CORE + MOVE.W PURBOT(A6),D0 * IMPURE BLOCKS + BSR BLKBYT + BSR MOVMEM * RESTORE IMPURE DATA (FAST BLOCKMOVE) + BRA RESTOK * SUCCESS + +* ---------------------- +* OPREST +* ---------------------- + +* RESTORE (STATE OF GAME, OR SELECTED "PARTIAL" DATA) + +OPREST NOP + TST.W (A0) * PARTIAL RESTORE (ANY ARGS)? + BEQ RESX2 * NO + +*** HANDLE A PARTIAL RESTORE, A0 -> ARGBLK *** + + MOVE.L A0,A2 + CLR.W D0 + BSR CHKDSK * CHECK FOR GAME DISK AND CLOSE GAME FILE + + MOVE.W ARG3(A2),D0 * "SUGGESTED" NAME, BYTE 0 = LENGTH + BSR RELABS + MOVE.L A0,A1 * SAVE HERE, & PASS TO FSEL + MOVEQ #0,D0 * RESTORE + MOVEQ #1,D1 * PARTIAL + BSR GETSFL * GET A NAME FOR THE SAVE FILE + BNE RESX13 * CANCELLED + + BSR OPNSFL * OPEN THE FILE + BNE RESX13 * ERROR + +* READ (PREVIOUS) SUGGESTED NAME FROM FILE, & CHECK FOR A MATCH + + MOVEQ #0,D0 + MOVEQ #PSNLEN,D1 * MAX LENGTH OF SUGGESTED NAME + MOVE.L STKBOT(A6),A0 * (GRAB TEMP BUFFER AT BASE OF ZSTACK) + BSR SFREAD + BNE RESX12 * ERROR, CLOSE THE FILE (NOT FATAL) + + MOVE.L A1,A0 * CURRENT NAME STARTS HERE (WITH LENGTH BYTE) + MOVE.L STKBOT(A6),A1 + MOVEQ #1,D0 * COUNT LENGTH BYTE + ADD.B (A0),D0 + BSR COMPS * COMPARE THE STRINGS + BNE RESX12 * DIFFERENT, ERROR, CLOSE THE FILE + +* READ DATA FROM FILE + + MOVE.W ARG1(A2),D0 * BASE OF PARTIAL SAVE + BSR RELABS * ABSOLUTIZE + MOVEQ #PSNLEN,D0 * FILE OFFSET + MOVEQ #0,D1 + MOVE.W ARG2(A2),D1 * LENGTH OF PARTIAL SAVE DATA + BSR SFREAD * [RETURNS ACTUAL BYTES READ IN D1] + BNE RESX12 * ERROR, CLOSE THE FILE + + BSR DEFOLD * >>> RESTORE "NON-PARTIAL" FILE NAMES <<< + BSR CLSSFL * CLOSE THE FILE + MOVEQ #1,D0 + BSR CHKDSK * MAKE SURE GAME DISK IS BACK IN DRIVE + +*** [SYSTEM STACK HACKING AND CALL TO NEWZPC NOT NEEDED AFTER PARTIAL OP] + + MOVE.W D1,D0 * RETURN "ACTUAL BYTES READ" + BRA PUTVAL + +*** ENTER HERE FOR "STANDARD" RESTORE *** + +RESX2 CLR.W D0 + BSR CHKDSK * CHECK FOR GAME DISK AND CLOSE GAME FILE + + CLR.W D0 * RESTORE + CLR.W D1 * STANDARD + BSR GETSFL * GET A NAME FOR THE SAVE FILE + BNE RESX13 * CANCELLED + +*** ENTER HERE IF DOING SPECIAL RESTORE DURING LAUNCH *** + +RES1 BSR OPNSFL * OPEN THE FILE + BNE RESX13 * ERROR + + CLR.W D0 * FIRST READ IN STACK + MOVEQ #STKLEN/512,D1 * BLOCK LENGTH OF STACK + MOVE.L STKBOT(A6),A0 * PUT IT HERE + BSR GTSBKS + BNE RESX16 * DIE IF DISK ERROR + + BSR RESSTA * UNSTACK THE OLD STATE INFO + BNE RESX14 * ERROR, WRONG ZORKID + + MOVE.L BUFFER(A6),A0 + MOVE.W PFLAGS(A0),-(SP) * PRESERVE THE FLAGS (SCRIPT ETC) + + MOVEQ #STKLEN/512,D0 * READ IMPURE STUFF STARTING AFTER STACK + MOVE.W PURBOT(A6),D1 * LENGTH OF IMPURE STUFF + BSR GTSBKS + BNE RESX16 * DIE IF DISK ERROR + + MOVE.L BUFFER(A6),A0 + MOVE.W (SP)+,PFLAGS(A0) * RESTORE THE OLD FLAGS + +* RESTORE SUCCEEDED + +RESX10 BSR CLSSFL * CLOSE THE FILE + BSR DEFNEW * UPDATE PREVIOUS DEFAULT NAMES + MOVEQ #1,D0 + BSR CHKDSK * (1) MAKE SURE GAME DISK IS BACK IN DRIVE + +* A subtle bug was found in ZIP20 when certain calls that reset the game +* state (the ZPC and stack) occurred during a timer interrupt. Since control +* never returned to the code that caused the interrupt, the system (machine) +* stack never got cleaned up. After several such calls it overflowed. + +* The questionable calls include (a successful) Restore or Irestore (Undo), +* and Restart. The first two are handled here, the last elsewhere. + +RESTOK MOVE.L TOPSP(A6),SP * MAKE SURE THE SYSTEM STACK IS CLEAN + PEA NXTINS * AND HACK IT SO WE WILL RETURN TO MAIN LOOP + + BSR NEWZPC * (2) GET THE PROPER ZPC PAGE + MOVEQ #2,D0 * RETURN "RESTORE OK" + BRA PUTVAL + +* SOMETHING WRONG, FAIL ... + +RESX12 BSR CLSSFL * CLOSE THE FILE +RESX13 BSR DEFOLD * INSTALL PREVIOUS DEFAULT NAMES + MOVEQ #1,D0 + BSR CHKDSK * MAKE SURE GAME DISK IS BACK IN DRIVE + +RESERR CLR.W D0 * RETURN "RESTORE FAILED" + BRA PUTVAL + +* FATAL ERROR: BAD ZORKID + +RESX14 MOVE.W D0,-(SP) + BSR CLSSFL * CLOSE THE BAD FILE + MOVE.W (SP)+,D0 * BAD VERSION ID + +RESX15 LEA MSGRE2,A0 + BRA FATAL * 'Wrong save file version' + SECTION ZDATA +MSGRE2 DC.B 'Wrong save file version',0 + SECTION ZCODE + +* FATAL ERROR: RESTORE READ ERROR + +RESX16 MOVE.W D0,-(SP) + BSR CLSSFL * CLOSE THE BAD FILE AND DIE + MOVE.W (SP)+,D0 * ERROR CODE + + LEA MSGRE1,A0 + BRA FATAL * 'Save file read error' + SECTION ZDATA +MSGRE1 DC.B 'Save file read error',0 + SECTION ZCODE + +* ---------------------- +* OPRSTT +* ---------------------- + +* RESTART (THE GAME) + +OPRSTT BSR PUTNEW * FORCE OUT ANY QUEUED TEXT + CLR.W LINES(A6) * RESET THE [MORE] COUNTER + + TST.W GAMFIL(A6) * GAME FILE ALREADY OPEN? + BNE.S RSTTX1 * YES + MOVEQ #1,D0 + BSR CHKDSK1 * NO, OPEN IT NOW (PROMPTING AS NEEDED) + +RSTTX1 MOVEQ #-1,D0 + BSR OPCLEAR * CLEAR (AND UNSPLIT) SCREEN + BRA RESTRT * SKIP MOST INITIALIZATIONS + +* ---------------------- +* OPQUIT +* ---------------------- + +* QUIT + +OPQUIT BRA FINISH * DIE PEACEFULLY + +* ---------------------- +* OPVERI +* ---------------------- + +* VERIFY (GAME FILE) + +OPVERI + IFEQ CZIP * VERSION INFO FOR ZIP ONLY + LEA MSGVER,A0 + BSR OUTMSG0 * 'Macintosh interpreter version ' + SECTION ZDATA +MSGVER DC.B 'Macintosh interpreter version ',0 + SECTION ZCODE + + MOVE.W INTWRD,D0 * DISPLAY THE LETTER (LOW BYTE) + BSR OPPRNC + BSR OPCRLF + ENDC + + TST.W SUBVER * DISPLAY SUB-VERSION ONLY IF NON-ZERO + BEQ.S VERX0 + + LEA MSGVR2,A0 + BSR OUTMSG0 * 'Sub-version ' + SECTION ZDATA +MSGVR2 DC.B 'Sub-version ',0 + SECTION ZCODE + + MOVE.W SUBVER,D0 * DISPLAY THE SUB-VERSION NUMBER + BSR OPPRNN + BSR OPCRLF + +VERX0 TST.W GAMFIL(A6) * GAME FILE ALREADY OPEN? + BNE.S VERX05 * YES + MOVEQ #1,D0 + BSR CHKDSK1 * NO, OPEN IT NOW (PROMPTING AS NEEDED) + +VERX05 MOVE.L BUFFER(A6),A0 + MOVE.W PLENTH(A0),D0 * GET LENGTH OF GAME FILE + + IFEQ EZIP + BSR BSPLTQ + ENDC + IFEQ CZIP + BSR BSPLIT + ENDC + MOVE.W D0,D4 * THIS IS FINAL BLOCK + MOVE.W D1,D5 * FINAL BYTE + + CLR.W D0 * STARTING BLOCK NUMBER + MOVEQ #64,D1 * STARTING BYTE NUMBER + CLR.W D3 * CHECKSUM HERE + MOVE.W ENDLOD(A6),-(SP) + CLR.W ENDLOD(A6) * FORCE LOADING FROM DISK + +VERX1 BSR GETBYT * GET NEXT BYTE + ADD.W D2,D3 * ADD IN TO CHECKSUM + CMP.W D0,D4 * DONE YET? + BNE VERX1 * NO + CMP.W D1,D5 * MAYBE + BNE VERX1 * NO + + MOVE.W (SP)+,ENDLOD(A6) * YES, RESTORE PROPER ENDLOD + + MOVE.L BUFFER(A6),A0 + MOVE.W PCHKSM(A0),D0 * GET THE REAL CHECKSUM + CMP.W D0,D3 + BNE.S VERX2 * ERROR + + BRA PTRUE * SUCCESS +VERX2 BRA PFALSE * FAILURE + +* ---------------------- +* OPORIG +* ---------------------- + +* ORIGINAL (NOT A COPY) GAME DISK? + +OPORIG BRA PTRUE * NO COPY-PROTECTION, SO ALWAYS TRUE + diff --git a/amiga/ax3.asm b/amiga/ax3.asm new file mode 100644 index 0000000..187c7c3 --- /dev/null +++ b/amiga/ax3.asm @@ -0,0 +1,1118 @@ + + PAGE +* --------------------------------------------------------------------------- +* MAIN LOOP, DISPATCHING +* --------------------------------------------------------------------------- + +* OPERATORS WHICH ACCEPT A VARIABLE NUMBER OF ARGUMENTS (OPQEQU, OPCALL, ETC) +* ARE IDENTIFIED BY AN INITIAL NOP. THEIR ARGUMENTS ARE PASSED IN AN ARGUMENT +* BLOCK, WITH THE NUMBER OF ARGUMENTS AS THE FIRST ENTRY. ALL OTHER OPERATORS +* RECEIVE THEIR ARGUMENTS IN REGISTERS. + +NOOP EQU $4E71 * MARKS ROUTINES WHICH TAKE OPTIONAL ARGS + +*** Alternate NXTINS dispatch mechanism. Would require that all entries in +*** dispatch table (ZIPOPS) be relative to ZIPOPS. + +*** LEA ZIPOPS,A1 +*** MOVE.W xxxOPS-ZIPOPS(A1,D0.W),D2 * GET THE OPx ROUTINE OFFSET +*** JSR 0(A1,D2.W) * CALL THE OPERATOR ROUTINE +*** BRA NXTINS + +* ---------------------- +* NXTINS +* ---------------------- + +NXTINS BSR GAMINT * CHECK FOR GAME INTERRUPT (SOUND, ETC) + BSR NXTBYT * GET THE NEXT INSTRUCTION BYTE + + IFEQ DEBUG + BSR DBTEST + ENDC + CMPI.B #$80,D0 * IS IT A 2 OP? + BCS NXT2 * BLO * YES + + CMPI.B #$B0,D0 * IS IT A 1 OP? + BCS NXT1 * BLO * YES + + CMPI.B #$C0,D0 * IS IT A 0 OP? + BCC NXT4 * BHS * NO, MUST BE AN EXTENDED OP + +*** HANDLE A ZERO-OP + +NXT0 CMPI.B #190,D0 * SPECIAL "EXTOP" OPCODE? + BEQ.S N0X1 * YES + + ANDI.W #$0F,D0 * 0 OP, EXTRACT OPERATOR CODE, "xxxx oooo" + ADD.W D0,D0 * WORD OFFSET + + LEA ZEROPS,A1 + MOVE.W 0(A1,D0.W),D2 * GET THE OPx ROUTINE OFFSET + LEA ZBASE,A1 + + JSR 0(A1,D2.W) * CALL THE OPERATOR ROUTINE + BRA NXTINS + +N0X1 BSR NXTBYT * NEXT BYTE IS SPECIAL "EXTOP" + ANDI.W #$3F,D0 * EXTRACT OPERATOR CODE, "xxoo oooo" + MOVEQ #64,D2 * MAXIMUM 2OPS/XOPS + ADD.W D0,D2 * ADJUST OPCODE INTO "EXTOP" RANGE + BRA NXT4A * THEN HANDLE AS AN XOP + +*** HANDLE A ONE-OP + +NXT1 MOVE.W D0,D2 * 1 OP, MAKE A COPY, "xxmm oooo" + ANDI.W #$0F,D2 * EXTRACT OPERATOR CODE + ADD.W D2,D2 * WORD OFFSET + + LSR.W #4,D0 * EXTRACT MODE BITS + ANDI.W #3,D0 + BSR GETARG * GET THE ARGUMENT + + LEA ONEOPS,A1 + MOVE.W 0(A1,D2.W),D2 * GET THE OPx ROUTINE OFFSET + LEA ZBASE,A1 + + JSR 0(A1,D2.W) * CALL THE OPERATOR ROUTINE + BRA NXTINS + +*** HANDLE A TWO-OP + +NXT2 MOVE.W D0,D2 * 2 OP, MAKE A COPY, "xmmo oooo" + + MOVEQ #1,D0 * ASSUME FIRST ARG IS AN IMMEDIATE + BTST #6,D2 * IS IT INSTEAD A VARIABLE? + BEQ.S N2X1 * NO + MOVEQ #2,D0 * YES, CHANGE MODE +N2X1 BSR GETARG * GET THE FIRST ARG + MOVE.W D0,D1 + + MOVEQ #1,D0 * ASSUME SECOND ARG IS AN IMMEDIATE + BTST #5,D2 * IS IT INSTEAD A VAR? + BEQ.S N2X2 * NO + MOVEQ #2,D0 * YES, CHANGE MODE +N2X2 BSR GETARG * GET THE SECOND ARG + EXG D0,D1 * POSITION THE ARGS + + ANDI.W #$1F,D2 * EXTRACT OPERATOR CODE + ADD.W D2,D2 * WORD OFFSET + + LEA TWOOPS,A1 + MOVE.W 0(A1,D2.W),D2 * GET THE OPx ROUTINE OFFSET + LEA ZBASE,A1 + LEA 0(A1,D2.W),A1 * CALCULATE THE OPx ROUTINE ADDRESS + + CMPI.W #NOOP,(A1) * BUT DOES THE OPERATOR EXPECT AN ARGBLK? + BNE.S N2X3 * NO + + LEA ARGBLK+6(A6),A0 * YES, MOVE ARGS TO ARGBLK + MOVE.W D1,-(A0) + MOVE.W D0,-(A0) + MOVE.W #2,-(A0) * ALWAYS 2 ARGS + +N2X3 JSR (A1) * CALL THE OPERATOR ROUTINE + BRA NXTINS + +*** HANDLE AN EXTENDED-OP ... + +NXT4 MOVE.W D0,D2 * EXTENDED OP, SAVE A COPY, "xxoo oooo" + ANDI.W #$3F,D2 * EXTRACT OPERATOR CODE + + CMPI.B #236,D0 * IS THIS AN XCALL ($EC)? + BEQ.S N4X1 * YES + CMPI.B #250,D0 * IS THIS AN IXCALL ($FA)? + BNE.S NXT4A * NO + +* GET THE 4 (OR 8) MODE SPECIFIERS, EXTRACT AND STACK THEM ... + +N4X1 MOVEQ #8,D3 * SPECIAL XOP, 8 MODE SPECIFIERS + BSR NXTBYT * GET THE FIRST MODE BYTE, "aabb ccdd" + MOVE.W D0,D1 + BSR NXTBYT * GET THE SECOND MODE BYTE, "eeff gghh" + + MOVE.W D0,-(SP) * SAVE hh + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE gg + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE ff + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE ee + + MOVE.W D1,D0 + BRA.S N4X2 + +* ENTRY POINT TO DECODE SPECIAL "EXTOP" +* D2 = STRIPPED OPCODE (MAY BE 64+) + +NXT4A MOVEQ #4,D3 * 4 MODE SPECIFIERS + BSR NXTBYT * GET THE MODE BYTE, "aabb ccdd" + +N4X2 MOVE.W D0,-(SP) * SAVE dd + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE cc + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE bb + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE aa + +* DECODE ARGUMENTS, STORE IN ARGBLK + + CLR.W D4 * KEEP A COUNT OF ACTUAL ARGUMENTS + LEA ARGBLK+2(A6),A1 * ARGUMENT BLOCK, SKIP OVER COUNT SLOT + +N4X3 MOVE.W (SP)+,D0 * POP NEXT MODE SPECIFIER + ANDI.W #3,D0 * EXTRACT MODE BITS + CMPI.W #3,D0 * ARE THERE ANY MORE ARGUMENTS? + BEQ.S N4X4 * NO + + ADDQ.W #1,D4 * YES, COUNT THIS ONE + BSR GETARG * DECODE AND FETCH IT + MOVE.W D0,(A1)+ * STORE IT IN ARGUMENT BLOCK + + SUBQ.W #1,D3 * GO FOR MORE + BNE N4X3 + BRA.S N4X5 + +N4X4 SUBQ.W #1,D3 * NUMBER OF EXTRA MODE SPECIFIERS + ADD.W D3,D3 + ADDA.W D3,SP * FLUSH THEM + +N4X5 LEA ARGBLK(A6),A0 * PASS ARGBLK POINTER TO THE OPERATOR HERE ... + MOVE.W D4,(A0) * STORE NUMBER OF ARGUMENTS + +* CALCULATE THE OPERATOR ROUTINE ADDRESS + + ADD.W D2,D2 * WORD OFFSET + LEA EXTOPS,A1 + MOVE.W 0(A1,D2.W),D2 * GET THE OPx ROUTINE OFFSET + LEA ZBASE,A1 + LEA 0(A1,D2.W),A1 * CALCULATE THE OPx ROUTINE ADDRESS + + CMPI.W #NOOP,(A1) * BUT DOES THE OPERATOR EXPECT AN ARGBLK? + BEQ.S N4X6 * YES + + ADDQ.L #2,A0 * NO, PASS ARGS IN REGISTERS + MOVE.W (A0)+,D0 + MOVE.W (A0)+,D1 + MOVE.W (A0)+,D2 + MOVE.W (A0)+,D3 * MAXIMUM OF FOUR + +N4X6 JSR (A1) * CALL THE OPERATOR ROUTINE + BRA NXTINS + +* ---------------------- +* SETDEF +* ---------------------- + +* SET UP DEFAULT ARGS IN ARGBLK[], USING VALUES FROM DEFBLK[] +* CALLED BY INDIVIDUAL OPERATORS, SINCE DEFAULT COUNT/VALUES MAY VARY +* CALLED AT BEGINNING OF OPS, SO NEED NOT SAVE REGISTERS +* GIVEN A0 -> ARGBLK, A1 -> DEFBLK, (A1) = MAX ARGS, RETURN A0 -> ARGBLK + +SETDEF MOVE.L A0,A2 + MOVE.W (A0)+,D0 * ACTUAL # ARGS PASSED (REQS PLUS OPTS) + MOVE.W (A1)+,D1 * MAX # ARGS POSSIBLE + SUB.W D0,D1 * DIFFERENCE IS # DEFAULTS TO SET + BLE.S SDFX4 * NONE + + ADD.W D0,D0 * SKIP THIS MANY BYTES + ADDA.W D0,A0 + ADDA.W D0,A1 +SDFX2 MOVE.W (A1)+,(A0)+ * COPY A DEFAULT VALUE + SUBQ.W #1,D1 + BNE.S SDFX2 + +SDFX4 MOVE.L A2,A0 * RETURN ARGBLK PTR INTACT + RTS + + PAGE +* --------------------------------------------------------------------------- +* DISPATCH TABLES +* --------------------------------------------------------------------------- + +* UNIMPLEMENTED OPCODES DISPATCH TO HERE ... + +OPERR CLR.W D0 + LEA MSGBAD,A0 + BRA FATAL * 'Bad operation' + + SECTION ZDATA +MSGBAD DC.B 'Bad operation',0 + SECTION ZCODE + + SECTION ZDATA +ZEROPS DC.W OPRTRU-ZBASE * 176 + DC.W OPRFAL-ZBASE * 177 + DC.W OPPRNI-ZBASE * 178 + DC.W OPPRNR-ZBASE * 179 + DC.W OPNOOP-ZBASE * 180 + DC.W OPERR-ZBASE + DC.W OPERR-ZBASE + DC.W OPRSTT-ZBASE * 183 + DC.W OPRSTA-ZBASE * 184 + DC.W OPCATCH-ZBASE * 185 XZIP + DC.W OPQUIT-ZBASE * 186 + DC.W OPCRLF-ZBASE * 187 + DC.W OPUSL-ZBASE * 188 + DC.W OPVERI-ZBASE * 189 + DC.W OPERR-ZBASE * 190 XZIP ("EXTOP") + DC.W OPORIG-ZBASE * 191 XZIP + +ONEOPS DC.W OPQZER-ZBASE * 128 + DC.W OPQNEX-ZBASE * 129 + DC.W OPQFIR-ZBASE * 130 + DC.W OPLOC-ZBASE * 131 + DC.W OPPTSI-ZBASE * 132 + DC.W OPINC-ZBASE * 133 + DC.W OPDEC-ZBASE * 134 + DC.W OPPRNB-ZBASE * 135 + DC.W OPCAL1-ZBASE * 136 EZIP + DC.W OPREMO-ZBASE * 137 + DC.W OPPRND-ZBASE * 138 + DC.W OPRETU-ZBASE * 139 + DC.W OPJUMP-ZBASE * 140 + DC.W OPPRIN-ZBASE * 141 + DC.W OPVALU-ZBASE * 142 + DC.W OPICAL1-ZBASE * 143 XZIP + +TWOOPS: +EXTOPS: DC.W OPERR-ZBASE * 0 (OR 192+0) + DC.W OPQEQU-ZBASE * 1 + DC.W OPQLES-ZBASE * 2 + DC.W OPQGRT-ZBASE * 3 + DC.W OPQDLE-ZBASE * 4 + DC.W OPQIGR-ZBASE * 5 + DC.W OPQIN-ZBASE * 6 + DC.W OPBTST-ZBASE * 7 + DC.W OPBOR-ZBASE * 8 + DC.W OPBAND-ZBASE * 9 + DC.W OPQFSE-ZBASE * 10 + DC.W OPFSET-ZBASE * 11 + DC.W OPFCLE-ZBASE * 12 + DC.W OPSET-ZBASE * 13 + DC.W OPMOVE-ZBASE * 14 + DC.W OPGET-ZBASE * 15 + DC.W OPGETB-ZBASE * 16 + DC.W OPGETP-ZBASE * 17 + DC.W OPGTPT-ZBASE * 18 + DC.W OPNEXT-ZBASE * 19 + DC.W OPADD-ZBASE * 20 + DC.W OPSUB-ZBASE * 21 + DC.W OPMUL-ZBASE * 22 + DC.W OPDIV-ZBASE * 23 + DC.W OPMOD-ZBASE * 24 + DC.W OPCAL2-ZBASE * 25 EZIP + DC.W OPICAL2-ZBASE * 26 XZIP + DC.W OPCOLOR-ZBASE * 27 XZIP + DC.W OPTHROW-ZBASE * 28 XZIP + DC.W OPERR-ZBASE + DC.W OPERR-ZBASE + DC.W OPERR-ZBASE + + DC.W OPCALL-ZBASE * 224 (192+32) + DC.W OPPUT-ZBASE * 225 + DC.W OPPUTB-ZBASE * 226 + DC.W OPPUTP-ZBASE * 227 + DC.W OPREAD-ZBASE * 228 + DC.W OPPRNC-ZBASE * 229 + DC.W OPPRNN-ZBASE * 230 + DC.W OPRAND-ZBASE * 231 + DC.W OPPUSH-ZBASE * 232 + DC.W OPPOP-ZBASE * 233 + DC.W OPSPLT-ZBASE * 234 + DC.W OPSCRN-ZBASE * 235 + DC.W OPXCAL-ZBASE * 236 EZIP + DC.W OPCLEAR-ZBASE * 237 EZIP + DC.W OPERASE-ZBASE * 238 EZIP + DC.W OPCURS-ZBASE * 239 EZIP + DC.W OPCURG-ZBASE * 240 XZIP + DC.W OPATTR-ZBASE * 241 EZIP + DC.W OPBUFO-ZBASE * 242 EZIP + DC.W OPDIRO-ZBASE * 243 EZIP + DC.W OPDIRI-ZBASE * 244 EZIP + DC.W OPSOUND-ZBASE * 245 EZIP + DC.W OPINPUT-ZBASE * 246 EZIP + DC.W OPINTBL-ZBASE * 247 EZIP + DC.W OPBCOM-ZBASE * 248 XZIP + DC.W OPICALL-ZBASE * 249 XZIP + DC.W OPIXCAL-ZBASE * 250 XZIP + DC.W OPLEX-ZBASE * 251 XZIP + DC.W OPZWSTR-ZBASE * 252 XZIP + DC.W OPCOPYT-ZBASE * 253 XZIP + DC.W OPPRNT-ZBASE * 254 XZIP + DC.W OPASSN-ZBASE * 255 XZIP + +* "EXTOPS" (XZIP) + + DC.W OPSAVE-ZBASE * 256 (192+64) + DC.W OPREST-ZBASE * 257 + DC.W OPSHIFT-ZBASE * 258 XZIP + DC.W OPASHIFT-ZBASE * 259 XZIP + DC.W OPFONT-ZBASE * 260 XZIP + DC.W OPDISP-ZBASE * 261 XZIP + DC.W OPPICI-ZBASE * 262 XZIP + DC.W OPDCLR-ZBASE * 263 XZIP + DC.W OPMARG-ZBASE * 264 XZIP + DC.W OPISAV-ZBASE * 265 XZIP + DC.W OPIRES-ZBASE * 266 XZIP + DC.W OPERR-ZBASE + DC.W OPERR-ZBASE + DC.W OPERR-ZBASE + DC.W OPERR-ZBASE + DC.W OPERR-ZBASE + DC.W OPERR-ZBASE + + SECTION ZCODE + + PAGE +* ---------------------------------------------------------------------------- +* STRING FUNCTIONS +* ---------------------------------------------------------------------------- + +* ZSTR CHARACTER CONVERSION VECTOR + + SECTION ZDATA +ZCHRS DC.B 'abcdefghijklmnopqrstuvwxyz' * CHAR SET 1 + DC.B 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' * CHAR SET 2 + DC.B ' 0123456789.,!?_#' * CHAR SET 3 + + DC.B $27,$22 * <'>,<"> + DC.B '/\-:()' + DC.B 0 * ASCIZ + SECTION ZCODE + +* ---------------------- +* PUTSTR +* ---------------------- + +* OUTPUT A ZSTR, BLOCK-POINTER IN D0, BYTE-POINTER IN D1 +* RETURN UPDATED POINTER + +PUTSTR MOVEM.L D2-D5,-(SP) + CLR.W D4 * TEMP CS STARTS AT 0 + CLR.W D5 * PERM CS STARTS AT 0 + +PSX1 BSR GETWRD * GET NEXT STRING WORD + MOVEM.W D0-D2,-(SP) * SAVE POINTER & COPY OF STRING WORD + + MOVEQ #2,D3 * 3 BYTES IN WORD +PSX2 MOVE.W D2,-(SP) * PUSH CURRENT BYTE + ASR.W #5,D2 * SHIFT TO NEXT BYTE + DBF D3,PSX2 * LOOP UNTIL DONE + + MOVEQ #2,D3 * RETRIEVE THE 3 BYTES ... +PSX3 MOVE.W (SP)+,D2 * GET NEXT BYTE + ANDI.W #$001F,D2 * CLEAR UNWANTED BITS + TST.W D4 * IN WORD MODE? (NEGATIVE D4) + BPL.S PSX4 * NO + + ASL.W #1,D2 * YES, CALCULATE WORD OFFSET + MOVE.L WRDTAB(A6),A0 * GET WORD TABLE POINTER + ADD.W WRDOFF(A6),D2 * USE PROPER 32 WORD BLOCK + ADDA.W D2,A0 * INDEX INTO WORD TABLE + BSR GTAWRD * GET A POINTER TO THE WORD ITSELF + BSR BSPLIT * SPLIT IT + BSR PUTSTR * AND PRINT IT + BRA PSX15 * CONTINUE WHERE WE LEFT OFF WITH TEMP CS RESET + +PSX4 CMPI.W #3,D4 * CS 3 (ASCII MODE) SELECTED? + BLT.S PSX6 * NO, NORMAL CS + BGT.S PSX5 * NO, BUT WE'RE ALREADY IN ASCII MODE + BSET #14,D4 * YES (MAKE D4 LARGE POSITIVE) + MOVE.B D2,D4 * SAVE HIGH-ORDER ASCII BITS (3!) HERE + BRA.S PSX16 * AND GO GET NEXT BYTE +PSX5 ANDI.W #$0007,D4 * EXTRACT PREVIOUSLY SAVED HIGH-ORDER BITS + ASL.W #5,D4 * POSITION THEM + OR.W D2,D4 * OR IN LOW-ORDER BITS + MOVE.W D4,D0 + BRA.S PSX14 * GO PRINT THE CHARACTER + +PSX6 CMPI.W #6,D2 * SPECIAL CODE (0 TO 5)? + BLT.S PSX9 * YES, SPACE, WORD, OR SHIFT + CMPI.W #2,D4 * MIGHT ALSO BE SPECIAL IF IN CS 2 + BNE.S PSX8 * BUT WE'RE NOT + + CMPI.W #7,D2 * CS 2, SPECIAL CODE FOR CRLF? + BEQ.S PSX7 * YES + BGT.S PSX8 * NO, NOT ASCII MODE, EITHER? + ADDQ.W #1,D4 * YES IT IS, SWITCH TO ASCII MODE (CS 3) + BRA.S PSX16 * AND GO GET NEXT BYTE +PSX7 BSR PUTNEW * CRLF REQUESTED, DO A NEWLINE + BRA.S PSX15 + +PSX8 MOVE.W D4,D1 * NORMAL CHARACTER, GET CS + MULU #26,D1 * CALCULATE OFFSET FOR THIS CS + ADD.W D2,D1 * ADD IN CHARACTER OFFSET (+6) + + LEA ZCHRS,A0 + MOVE.B -6(A0,D1.W),D0 * GET THE CHARACTER FROM CONVERSION VECTOR + BRA.S PSX14 * GO PRINT IT + +PSX9 TST.W D2 * IS IT A SPACE? + BNE.S PSX10 * NO + MOVEQ #32,D0 * YES, GO PRINT A SPACE + BRA.S PSX14 + +PSX10 CMPI.W #3,D2 * IS IT A WORD? + BGT.S PSX11 * NO, MUST BE A SHIFT + BSET #15,D4 * SWITCH TO WORD MODE (NEG D4) FOR NEXT BYTE + SUBQ.W #1,D2 * CALCULATE WORD-TABLE BLOCK OFFSET + ASL.W #6,D2 * 64 BYTES IN A BLOCK + MOVE.W D2,WRDOFF(A6) * SAVE IT AND LOOP + BRA.S PSX16 + +PSX11 SUBQ.W #3,D2 * CALCULATE NEW CS + TST.W D4 * TEMPORARY SHIFT (FROM CS 0)? + BNE.S PSX12 * NO + MOVE.W D2,D4 * YES, JUST SAVE NEW TEMP CS + BRA.S PSX16 + +PSX12 CMP.W D2,D4 * IS THIS THE CURRENT CS? + BEQ.S PSX13 * YES, DO A PERM SHIFT TO IT + CLR.W D4 * OTHERWISE, PERM SHIFT TO CS 0 +PSX13 MOVE.W D4,D5 * TEMP AND PERM CS'S ARE THE SAME NOW + BRA.S PSX16 + +PSX14 BSR PUTCHR * OUTPUT THE CHARACTER +PSX15 MOVE.W D5,D4 * RESET TEMP CS TO PERM CS +PSX16 DBF D3,PSX3 * LOOP FOR NEXT BYTE + + MOVEM.W (SP)+,D0-D2 * RESTORE POINTERS & ORIGINAL STRING WORD + TST.W D2 * END-OF-STRING (HIGH BIT SET)? + BPL PSX1 * NO, GO GET NEXT WORD + MOVEM.L (SP)+,D2-D5 * YES, CLEAN UP & RETURN UPDATED POINTER + RTS + +* ---------------------- +* CHRCS +* ---------------------- + +* GIVEN AN ASCII CHARACTER IN D0, RETURN THE CHARACTER SET # IN D0 + +CHRCS TST.B D0 * IS THIS A NULL? + BNE.S CHRCX1 * NO + MOVEQ #3,D0 * YES, RETURN DUMMY CS NUMBER + BRA.S CHRCX4 + +CHRCX1 CMPI.B #'a',D0 * LOWERCASE CHAR? + BLT.S CHRCX2 * NO + CMPI.B #'z',D0 + BGT.S CHRCX2 * NO + CLR.W D0 * YES, RETURN CS 0 + BRA.S CHRCX4 + +CHRCX2 CMPI.B #'A',D0 * UPPERCASE CHAR? + BLT.S CHRCX3 * NO + CMPI.B #'Z',D0 + BGT.S CHRCX3 * NO + MOVEQ #1,D0 * YES, RETURN CS 1 + BRA.S CHRCX4 + +CHRCX3 MOVEQ #2,D0 * OTHERWISE CALL IT CS 2 +CHRCX4 RTS + +* ---------------------- +* CHRBYT +* ---------------------- + +* GIVEN AN ASCII CHARACTER IN D0, RETURN ZSTR BYTE VALUE IN D0 (6 TO 31, OR 0) + +CHRBYT LEA ZCHRS,A0 * POINT TO CONVERSION VECTOR + +CHRBX1 CMP.B (A0)+,D0 * FOUND THE CHARACTER? + BEQ.S CHRBX2 * YES + TST.B (A0) * END OF STRING? + BNE CHRBX1 * NO, CONTINUE SEARCH + CLR.W D0 * YES, RETURN ZERO FOR FAILURE + BRA.S CHRBX4 + +CHRBX2 MOVE.L A0,D0 * CALCULATE OFFSET OF CHAR INTO VECTOR + LEA ZCHRS,A0 + SUB.L A0,D0 + ADDQ.W #5,D0 * ADJUST OFFSET SO FIRST CHAR IS 6 + +CHRBX3 CMPI.W #32,D0 * IN BASE CODE RANGE (6-31)? + BLT.S CHRBX4 * YES + SUBI.W #26,D0 * SUBTRACT MULTIPLES OF 26 UNTIL BASE CODE + BRA CHRBX3 +CHRBX4 RTS + +* ---------------------- +* ZWORD +* ---------------------- + +* GIVEN UP TO 6 (EZIP 9) ASCIZ CHARACTERS, BUFFER POINTER IN A1, +* CONVERT THEM TO A TWO (EZIP THREE) WORD ZSTR, BUFFER POINTER IN A0 + +PADCHR EQU 5 * ZSTR PADDING CHAR (SHIFT 2) + +ZWORD MOVEM.L D1-D2/A2,-(SP) + MOVE.L A0,A2 + MOVE.W #VCHARS,D2 * NUMBER OF PACKED CHARS IN A ZSTR (6 OR 9) + +ZWX1 CLR.W D1 + MOVE.B (A1)+,D1 * GET NEXT CHARACTER, END-OF-STRING? + BEQ.S ZWX4 * YES + + MOVE.W D1,D0 + BSR CHRCS * FIND THE CS NUMBER FOR THIS CHAR + TST.W D0 * CS 0? + BEQ.S ZWX2 * YES + ADDQ.W #3,D0 * NO, CALCULATE TEMP SHIFT BYTE + MOVE.W D0,-(SP) * SAVE THE SHIFT BYTE + SUBQ.W #1,D2 * REDUCE BYTE COUNT, DONE YET? + BEQ.S ZWX6 * YES + +ZWX2 MOVE.W D1,D0 + BSR CHRBYT * FIND THE PROPER BYTE VALUE FOR THIS CHAR + TST.W D0 * IN NORMAL CS'S? + BNE.S ZWX3 * YES + + MOVEQ #6,D0 * NO, USE ASCII SHIFT + MOVE.W D0,-(SP) + SUBQ.W #1,D2 * DONE YET? + BEQ.S ZWX6 * YES + + MOVE.W D1,D0 * NO, SAVE HIGH-ORDER ASCII BITS (3) + ASR.W #5,D0 + MOVE.W D0,-(SP) + SUBQ.W #1,D2 * DONE YET? + BEQ.S ZWX6 * YES + + MOVE.W D1,D0 * NO, SAVE LOW-ORDER ASCII BITS (5) + ANDI.W #$001F,D0 +ZWX3 MOVE.W D0,-(SP) * SAVE THIS BYTE + + SUBQ.W #1,D2 * AND LOOP UNTIL ZWORD FULL + BNE ZWX1 + BRA.S ZWX6 + +ZWX4 MOVE.W #PADCHR,-(SP) * END OF STRING, SAVE A PAD BYTE + SUBQ.W #1,D2 * LOOP UNTIL ZSTR FULL + BNE ZWX4 + +*** BUILD A ZSTR FROM THE SAVED BYTES ... + +ZWX6 MOVE.W #VCHARS*2,D2 * 6 OR 9 CHARS (WORDS) ON STACK + MOVE.L SP,A0 * DON'T DISTURB SP YET (IN CASE OF INTERRUPTS) + ADDA.W D2,A0 + MOVE.W #VCHARS/3,D1 * 2 OR 3 TIMES THROUGH LOOP + +ZWX7 MOVE.W -(A0),D0 + ASL.W #5,D0 + OR.W -(A0),D0 + ASL.W #5,D0 + OR.W -(A0),D0 + MOVE.W D0,(A2)+ * STORE A PACKED ZWORD IN RETURN BUFFER + + SUBQ.W #1,D1 + BNE ZWX7 * GO FOR NEXT + + BSET #7,-2(A2) * SET HIGH-ORDER BIT IN LAST ZWORD + ADDA.W D2,SP * AND FLUSH THE STACK + + MOVEM.L (SP)+,D1-D2/A2 + RTS + + + PAGE +*-------------------------------------------------------------------------- +* GENERALIZED OUTPUT FOLDING ROUTINE +*-------------------------------------------------------------------------- + +* ---------------------- +* INITQP +* ---------------------- + +* ALLOCATE AND INITIALIZE A QUEUE PARAMETER BLOCK, +* D1 IS MAXIMUM SIZE OF BUFFER (IN BYTES), D2 IS INITIAL UNIT SIZE +* A1 -> LINE OUTPUT FUNCTION, A2 -> UNIT SIZE FUNCTION +* RETURN A0 -> PARAMETER BLOCK + +INITQP MOVE.W D1,D0 + ADD.W #QPLEN,D0 * TOTAL SPACE TO ALLOCATE + EXT.L D0 + BSR GETMEM * GET IT + + MOVE.L A0,D0 * PARAMETERS BLOCK WILL START HERE + ADD.L #QPLEN,D0 + MOVE.L D0,BUFPTR(A0) * LINE BUFFER STARTS HERE + MOVE.L D0,NXTPTR(A0) * ALSO CURRENT POINTER + + MOVE.L A1,OUTFUN(A0) * INITIALIZE LINE OUTPUT FUNCTION + MOVE.L A2,SIZFUN(A0) * INITIALIZE CHAR SIZE FUNCTION + + CLR.W CURSIZ(A0) * ALWAYS EMPTY INITIALLY + CLR.B DUMPED(A0) * THIS ONE IS SET ONLY BY PUTLIN + MOVE.W D2,D0 * UNIT CAPACITY OF BUFFER ... [FALL THRU] + +* CHANGE THE LINE WRAP POINT, A0 -> PARAMETER BLOCK, DO = NEW LENGTH (UNITS) +* RETURN A0 -> PARAMETER BLOCK + +SIZEQP +*** IN THE FUTURE, IF EXTRA ROOM IS NEEDED FOR ITALICS, CALLER SHOULD +*** (TEMPORARILY) INCREMENT CURSIZ. MUST LEAVE BUFSIZ AT MAX SO BUFFERING +*** CAN WORK CORRECTLY IN SCREEN 1, IF USED. +*** SUBQ.W #1,D0 * >>> ALLOW FOR ATARI ITALICS HACK <<< + + MOVE.W D0,BUFSIZ(A0) * STORE IT + RTS + +* ---------------------- +* QUECHR +* ---------------------- + +* QUEUE THE CHAR IN D0 FOR OUTPUT, A0 POINTS TO QUEUE-PARAMETERS BLOCK + +QUECHR MOVEM.L D4/A1-A4,-(SP) + MOVE.W D0,D4 + MOVE.L A0,A4 + + MOVE.W CURSIZ(A4),D0 + CMP.W BUFSIZ(A4),D0 * BUFFER FULL YET? + BLT QCX8 * NO +*** BGT QCX0 * OVERFULL (DEQUE THE LAST CHAR AND REENTER) + + CMPI.B #32,D4 * YES, BUT DID A SPACE CAUSE OVERFLOW? + BNE.S QCX1 * NO + + MOVE.L NXTPTR(A4),D0 * YES, JUST PRINT THE WHOLE BUFFER + MOVE.L BUFPTR(A4),A0 + + MOVE.L OUTFUN(A4),A3 + JSR (A3) + + CLR.W CURSIZ(A4) * RESET LENGTH COUNTER + MOVE.L BUFPTR(A4),NXTPTR(A4) * RESET CURRENT CHAR POINTER + CLR.B DUMPED(A4) * STARTING A FRESH LINE + BRA.S QCX9 * EXIT, IGNORING SPACE + +* FOLDING ROUTINE, SEARCH FOR MOST-RECENT SPACE ... + +QCX1 MOVE.L BUFPTR(A4),A1 * BEGINNING OF BUFFER + MOVE.L NXTPTR(A4),A2 * END OF BUFFER (+1) + BRA.S QCX2A * ALLOW FOR EMPTY [DUMPED] BUFFER + +QCX2 CMPI.B #32,-(A2) * SEARCH FOR SPACE BACKWARDS FROM END + BEQ.S QCX4 * FOUND ONE +QCX2A CMPA.L A1,A2 * REACHED BEGINNING OF BUFFER? + BGT QCX2 * NOT YET + +* NO SPACES FOUND, DUMP WHOLE BUFFER ... + +QCX3 TST.B DUMPED(A4) * BUT WAS THIS BUFFER ALREADY PARTLY EMPTIED? + BNE.S QCX5 * YES, CARRY EVERYTHING OVER TO NEXT LINE + + MOVE.L NXTPTR(A4),A2 * OTHERWISE, OUTPUT EVERYTHING + BRA.S QCX5 + +* SPACE WAS FOUND, DUMP THE BUFFER (THROUGH SPACE) ... + +QCX4 MOVE.L A2,A0 * POINTER TO THE SPACE + ADDQ.L #1,A2 * POINTER PAST THE SPACE + + CMPA.L A1,A0 * DEGENERATE CASE WITH SPACE AT BUFPTR? + BEQ QCX3 * YES, OUTPUT WHOLE LINE + +QCX5 MOVE.L A2,D0 * LAST CHAR TO PRINT (+1) + MOVE.L A1,A0 * START OF BUFFER + + MOVE.L OUTFUN(A4),A3 * GO DUMP IT, ADDING A CR + JSR (A3) + +* SHIFT ANY REMAINING CHARS TO FRONT OF BUFFER ... + + CLR.W CURSIZ(A4) * ZERO THE UNIT COUNT + CLR.B DUMPED(A4) * START WITH A FRESH BUFFER + BRA.S QCX7 + +QCX6 MOVE.B (A2)+,D0 + MOVE.B D0,(A1)+ * COPY NEXT CHAR TO BEGINNING OF BUF + + MOVE.L SIZFUN(A4),A0 * CHAR STILL IN D0 + JSR (A0) + ADD.W D0,CURSIZ(A4) * UPDATE THE UNIT COUNT + +QCX7 CMPA.L NXTPTR(A4),A2 * ANY MORE CHARS AFTER SPACE? + BLT QCX6 * YES + MOVE.L A1,NXTPTR(A4) * NO, STORE NEW CURRENT POINTER HERE + +* FINALLY, STORE THE NEW CHAR AND EXIT ... + +QCX8 MOVE.L NXTPTR(A4),A0 + MOVE.B D4,(A0)+ * STORE THE NEW CHARACTER IN BUFFER + MOVE.L A0,NXTPTR(A4) * AND UPDATE POINTER + + MOVE.W D4,D0 + MOVE.L SIZFUN(A4),A0 + JSR (A0) * GET UNIT SIZE OF NEW CHAR + ADD.W D0,CURSIZ(A4) * AND UPDATE COUNTER + +QCX9 MOVEM.L (SP)+,D4/A1-A4 + RTS + +*-------------------------------------------------------------------------- +* MAIN OUTPUT HANDLER +*-------------------------------------------------------------------------- + +* !ALL! OUTPUT GENERATED BY THE GAME (AND THE USER) SHOULD BE CHANNELED +* THROUGH THE FOLLOWING TWO ROUTINES, WHICH REDIRECT IT APPROPRIATELY. + +* CALL GERMAN-CHAR CHECK HERE, SINCE ALL THE PRINTx OPCODES (8 OR SO) +* ARE CHANNELED THROUGH HERE. + +* ---------------------- +* PUTNEW +* ---------------------- + +* OUTPUT A NEWLINE + +PUTNEW MOVEQ #13,D0 * JUST FALL THROUGH WITH A CR + +* ---------------------- +* PUTCHR +* ---------------------- + +* OUTPUT THE CHAR IN D0 (TO THE REQUESTED DEVICES) + +PUTCHR CMPI.B #9,D0 * TAB? (OLD ZORK BUG, DISPLAYS GARBAGE) + BNE.S PCX1 + MOVEQ #32,D0 * YES, MAP TO A SPACE + +PCX1 BSR GERCHR * IF GERMAN CHAR, CONVERT TO KEYCODE + +*** STATUS LINE OUTPUT (ZIP INTERNAL FUNCTION ONLY) ... + + IFEQ CZIP + TST.W VOSTAT(A6) * SPECIAL OUTPUT TO SL HANDLER? + BNE PUTSL * YES (ABORT PUTCHR) + ENDC + +*** TABLE OUTPUT ... + + IFEQ EZIP + TST.W VOTABL(A6) * TABLE OUTPUT? + BNE TABCHR * YES (ABORT PUTCHR PER "DIROUT" SPEC) + ENDC + + MOVE.W D0,-(SP) * OTHERWISE, SAVE THE CHAR HERE + +*** SCRIPT (BEFORE SCREEN, SO "OPEN" ERROR DISPLAYS IN CORRECT SEQUENCE) + + IFEQ EZIP + TST.W VOPRNT(A6) * SCRIPTING ACTIVE? + ENDC + IFEQ CZIP + BSR TSTSCR * CHECK FOR SCRIPTING REQUEST -- ACTIVE? + ENDC + BEQ.S PCX2 * NO + + MOVE.W (SP),D0 * SCRIPT THIS CHAR + BSR SCRCHR + +*** SCREEN DISPLAY ... + +PCX2 TST.W VOCONS(A6) * CONSOLE OUTPUT ACTIVE? + BEQ.S PCX3 * NO + + MOVE.W (SP),D0 * YES, DISPLAY THE CHAR + BSR QDCHR + +*** FILE OUTPUT ... + +PCX3 NOP * NOT IMPLEMENTED + + TST.W (SP)+ * FLUSH CHAR FROM STACK + RTS + +*-------------------------------------------------------------------------- +* TERMINAL DISPLAY FUNCTIONS +*-------------------------------------------------------------------------- + +* ---------------------- +* QDCHR +* ---------------------- + +* QUEUE/DISPLAY THE CHAR IN D0 + +QDCHR TST.W VOBUFF(A6) * IS BUFFERING TURNED OFF? + BEQ OUTCHR * YES, GO TO SCREEN (THIS HANDLES CR'S ALSO) + + CMPI.B #13,D0 * CR? + BEQ NEWLIN * YES, DUMP THE BUFFER + + MOVE.L DQUE(A6),A0 * OTHERWISE, GO QUEUE IT + BRA QUECHR + +* ---------------------- +* NEWLIN +* ---------------------- + +* GO TO NEW LINE, OUTPUTTING CURRENT BUFFER +* (THIS ROUTINE NOW CALLED ONLY FROM THE PRECEEDING ROUTINE) + +NEWLIN MOVE.L A4,-(SP) + MOVE.L DQUE(A6),A4 * SCREEN BUFFER + + MOVE.L BUFPTR(A4),A0 * START OF LINE + MOVE.L NXTPTR(A4),D0 * END OF CURRENT LINE + BSR LINOUT * CHECK "MORE", OUTPUT LINE, ADD A CR + + MOVE.L BUFPTR(A4),NXTPTR(A4) * RESET CHARACTER POINTER + CLR.W CURSIZ(A4) * RESET UNIT COUNT + CLR.B DUMPED(A4) * NO OUTPUT ON NEW LINE YET + + MOVE.L (SP)+,A4 + RTS + +* ---------------------- +* PUTLIN +* ---------------------- + +* OUTPUT CURRENT BUFFER, WITHOUT A NEWLINE +* (ASSUMES SOMETHING LIKE OPREAD WILL SUPPLY THE NEWLINE) + +PUTLIN1 MOVE.L DQUE(A6),A0 + CLR.W CURSIZ(A0) * RESET UNIT COUNT (BUFFER EMPTY) + +* ENTER HERE IF BUFFERING WILL LATER RESUME FROM CURRENT POINT + +PUTLIN MOVE.L A4,-(SP) + MOVE.L DQUE(A6),A4 * SCREEN BUFFER + + MOVE.L BUFPTR(A4),A0 * START OF LINE + MOVE.L NXTPTR(A4),D0 * END OF CURRENT LINE + BSR BUFOUT * OUTPUT IT (NO CR, BUT DOES CHECK [MORE]) + + MOVE.L BUFPTR(A4),NXTPTR(A4) * RESET CHARACTER POINTER + MOVE.B #1,DUMPED(A4) * REMEMBER BUFFER IS PARTLY DUMPED + MOVE.L (SP)+,A4 + RTS + +*-------------------------------------------------------------------------- +* SCRIPT BUFFERING +*-------------------------------------------------------------------------- + +* ---------------------- +* SCRCHR +* ---------------------- + +* /ALL/ SCRIPT OUTPUT IS CHANNELED THROUGH HERE + +* QUEUE THE CHAR IN D0 FOR SCRIPTING (UNLESS SCREEN 1 IS ACTIVE; IF SO, +* TEMPORARILY SUPPRESS SCRIPTING) + +SCRCHR MOVEM.W D0,-(SP) * SAVE CHAR, BUT DON'T DISTURB FLAGS + BSR GETSCRN * ARE WE IN WINDOW 1? + MOVEM.W (SP)+,D0 + BEQ.S SCRCX1 * NO + RTS * YES, AVOID SCRIPTING + +SCRCX1 CMPI.B #13,D0 * CR? + BEQ.S SCRLIN * YES, DUMP SCRIPT BUFFER + + MOVE.L SQUE(A6),A0 * SCRIPTING PARAMETERS BLOCK + BRA QUECHR * GO QUEUE CHAR + +* GOT A NEWLINE -- SCRIPT THE CURRENT BUFFER + +SCRLIN MOVE.L A4,-(SP) + MOVE.L SQUE(A6),A4 * SCRIPTING PARAMETERS BLOCK + + MOVE.L BUFPTR(A4),A0 * START OF LINE + MOVE.L NXTPTR(A4),D0 * END OF CURRENT LINE + BSR SCROUT * OUTPUT LINE, ADD A CR ... + + MOVE.L BUFPTR(A4),NXTPTR(A4) * RESET CHARACTER POINTER + CLR.W CURSIZ(A4) * RESET UNIT COUNT + + MOVE.L (SP)+,A4 + RTS + +* ---------------------- +* SCRINP +* ---------------------- + +* OUTPUT A USER INPUT LINE TO THE TRANSCRIPT (IF SCRIPTING) +* START IN A0, LENGTH IN D0, FLAG IN D1 (NONZERO) FOR CR + +SCRINP MOVEM.L A2/D2,-(SP) + MOVE.L A0,A2 * PROTECT ARGS + MOVE.W D0,D2 + + IFEQ EZIP + TST.W VOPRNT(A6) * SCRIPTING? + ENDC + IFEQ CZIP + BSR TSTSCR * CHECK FOR SCRIPT REQUEST -- ACTIVE? + ENDC + BEQ.S SCRIX3 * NO, EXIT + + TST.W D2 * LENGTH OF INPUT + BEQ.S SCRIX2 * ZERO, JUST DO THE CR + +SCRIX1 MOVE.B (A2)+,D0 * SCRIPT NEXT CHAR + BSR SCRCHR * (USE BUFFERING, SO WRAP IS CORRECT) + SUBQ.W #1,D2 + BNE.S SCRIX1 + +SCRIX2 TST.W D1 * CR REQUESTED? + BEQ.S SCRIX3 * NO + MOVEQ #13,D0 * YES, ADD THE CR + BSR SCRCHR + +SCRIX3 MOVEM.L (SP)+,D2/A2 + RTS + +* ---------------------- +* SCRNAM +* ---------------------- + +* ECHO THE SAVE/RESTORE FILENAME TO THE TRANSCRIPT (IF SCRIPTING) +* (USER SELECTED IT THRU A SPECIAL DIALOG) +* A0 -> NAME, D0 = LEN + +SCRNAM TST.W VOPRNT(A6) * SCRIPTING? + BEQ.S SCNMX1 * NO, EXIT + MOVE.L D1,-(SP) + MOVEM.L A0/D0,-(SP) + + LEA MSGSCN,A0 * 'File: ' + BSR STRLEN * LEAVE LENGTH OF STRING IN D0 + CLR.W D1 * NO CR YET + BSR SCRINP + SECTION ZDATA +MSGSCN DC.B 'File: ',0 * (PHRASE OKAY FOR BOTH SAVE & RESTORE) + SECTION ZCODE + + MOVEM.L (SP)+,A0/D0 * NAME & LEN + MOVEQ #1,D1 * END WITH CR + BSR SCRINP + + MOVE.L (SP)+,D1 +SCNMX1 RTS + + PAGE +* ---------------------------------------------------------------------------- +* PAGING ROUTINES +* ---------------------------------------------------------------------------- + +* ---------------------- +* NEWZPC +* ---------------------- + +* NORMALIZE ZPC & (IF NECESSARY) GET PROPER PAGE + +NEWZPC MOVE.W ZPC2(A6),D0 * LOW ORDER ZPC + ASR.W #8,D0 * EXTRACT REQUIRED BLOCK ADJUSTMENT (+ OR -) + ASR.W #1,D0 + + ADD.W D0,ZPC1(A6) * AND ADJUST HIGH ORDER ZPC + ANDI.W #$01FF,ZPC2(A6) * NORMALIZE LOW ORDER ZPC + +* GET THE INDICATED PAGE + + MOVE.W ZPC1(A6),D0 + CMP.W CURBLK(A6),D0 * HAS THE BLOCK CHANGED? + BEQ.S NZX4 * NO, EXIT + MOVE.W D0,CURBLK(A6) * YES, REMEMBER NEW BLOCK + + TST.L CURTAB(A6) * IS OLD PAGE PRELOADED? + BEQ.S NZX2 * YES + MOVE.L CURTAB(A6),A0 * NO, RESTORE CURRENT REF TIME FOR OLD PAGE + MOVE.L RTIME(A6),2(A0) + +NZX2 CMP.W ENDLOD(A6),D0 * IS NEW PAGE PRELOADED? + BLT.S NZX3 * YES + BSR GETPAG * NO, GET THE NEW PAGE + MOVE.L A0,CURPAG(A6) * REMEMBER NEW PAGE POINTER + + MOVE.L LPTAB(A6),A0 * GET NEW TABLE POINTER + MOVE.L A0,CURTAB(A6) * SAVE THIS POINTER FOR LATER + MOVE.L #-1,2(A0) * FAKE A HIGH RTIME TO PROTECT ZPC PAGE FOR US + BRA.S NZX4 + +NZX3 BSR BLKBYT * CALCULATE PRELOAD PAGE ADDRESS + ADD.L BUFFER(A6),D0 * ABSOLUTIZE + MOVE.L D0,CURPAG(A6) * REMEMBER NEW PAGE POINTER + CLR.L CURTAB(A6) * ZERO TABLE POINTER MEANS PAGE IS PRELOADED + +NZX4 RTS + +* ---------------------- +* GETPAG +* ---------------------- + +* GET THE PAGE WHOSE NUMBER IS IN D0, RETURN A POINTER TO IT IN A0 + +GETPAG CMP.W LPAGE(A6),D0 * IS THIS THE SAME PAGE AS LAST REFERENCED? + BEQ.S GPX4 * YES, RETURN ITS LOCATION + + MOVE.W D0,LPAGE(A6) * SAVE NEW PAGE NUMBER + ADDQ.L #1,RTIME(A6) * UPDATE REFERENCE COUNT + MOVE.L PAGTAB(A6),A0 * PAGE INFORMATION TABLE + +GPX1 CMP.W (A0),D0 * SEARCH FOR DESIRED BLOCK + BNE.S GPX3 * NOT IT + + CMP.W CURBLK(A6),D0 * FOUND IT, BUT IS IT THE CURRENT ZPC PAGE? + BEQ.S GPX2 * YES, DON'T TOUCH REF TIME (PAGE IS PROTECTED) + MOVE.L RTIME(A6),2(A0) * NO, UPDATE ITS REFERENCE TIME + +GPX2 MOVE.L A0,LPTAB(A6) * SAVE THE TABLE POINTER + MOVE.L A0,D0 + SUB.L PAGTAB(A6),D0 * BUFFER NUMBER x8 + ASL.L #6,D0 * CALCULATE CORE ADDRESS OF PAGE + ADD.L PAGES(A6),D0 + MOVE.L D0,LPLOC(A6) * SAVE IT + BRA.S GPX4 * AND RETURN IT + +GPX3 ADDQ.L #8,A0 * SKIP OVER REFERENCE TIME, ETC. + CMPI.W #-1,(A0) * END OF TABLE? + BNE GPX1 * NO, CONTINUE SEARCH + +* DESIRED PAGE NOT RESIDENT, MUST READ IT FROM DISK + + MOVE.L A1,-(SP) + BSR FINDPG * FIND AN OLD PAGE + MOVE.L A0,LPLOC(A6) * SAVE ITS PAGE POINTER + MOVE.L A1,LPTAB(A6) * SAVE ITS PAGTAB POINTER + + MOVE.W LPAGE(A6),D0 * NEW PAGE NUMBER FOR GETBLK + MOVE.W D0,(A1)+ * SAVE PAGE NUMBER IN FIRST SLOT + MOVE.L RTIME(A6),(A1) * SAVE CURRENT REF TIME + + BSR GETBLK * GET THE BLOCK + MOVE.L (SP)+,A1 * CLEAN UP + +GPX4 MOVE.L LPLOC(A6),A0 * RETURN THE PAGE POINTER + RTS + +* ---------------------- +* FINDPG +* ---------------------- + +* FIND A GOOD (LRU) PAGE, RETURN PAGE POINTER IN A0 & PAGTAB POINTER IN A1 + +FINDPG MOVE.L PAGTAB(A6),A0 + ADDQ.L #2,A0 * SKIP OVER FIRST PAGE NUMBER + MOVE.L #-1,D0 * FAKE A BEST-CASE REFERENCE COUNT + +FDPGX1 CMP.L (A0),D0 * COMPARE PREV OLDEST REF TIME WITH THIS ONE + BLS.S FDPGX2 * STILL THE OLDEST + + MOVE.L (A0),D0 * NEW OLDEST, SAVE THIS REFERENCE COUNT + MOVE.L A0,A1 * AND PAGTAB LOCATION (+2) + +FDPGX2 ADDQ.L #6,A0 * SKIP OVER REF TIME, ETC. + CMPI.W #-1,(A0)+ * END OF TABLE? + BNE FDPGX1 * NO + + SUBQ.L #2,A1 * RETURN THE PAGTAB LOCATION HERE + MOVE.L A1,D0 + SUB.L PAGTAB(A6),D0 * BUFFER NUMBER x8 + ASL.L #6,D0 * CALCULATE CORE ADDRESS OF PAGE + ADD.L PAGES(A6),D0 + MOVE.L D0,A0 * AND RETURN IT HERE + RTS + diff --git a/amiga/ax4.asm b/amiga/ax4.asm new file mode 100644 index 0000000..ecf29f0 --- /dev/null +++ b/amiga/ax4.asm @@ -0,0 +1,1502 @@ + + PAGE +* ---------------------------------------------------------------------- +* MACHINE DEPENDENT ROUTINES -- AMIGA XZIP +* ---------------------------------------------------------------------- + +* SET THE SPLIT SIZE, D0 = LINES IN TOP SCREEN (0 IF UNSPLIT) + +SETSPLT MOVE.W D0,_split_row + RTS + +* RETURN D0 = SPLIT SIZE + +GETSPLT MOVE.W _split_row,D0 + RTS + +* SET THE ACTIVE SCREEN, D0 = NEW VALUE (0 OR 1) + +SETSCRN MOVE.W D0,_wind1 + RTS + +* RETURN D0 = CURRENTLY ACTIVE GAME SCREEN, PLUS FLAGS + +GETSCRN MOVE.W _wind1,D0 + RTS + +* SET CURSOR POSITION ("IN SCREEN 1 ONLY" - SPEC) +* GIVEN D0.W = ROW, D1.W = COL (-1 MEANS DON'T CHANGE) + +SETCURS +*** TST.W D0 * USE OLD VAL? +*** BLT.S SCURX1 * YES +*** TST.W D1 * MAYBE? +*** BGE.S SCURX2 * NO +*** SCURX1 +*** MOVEM.W D0-D1,-(SP) +*** BSR GETCURS * AMIGA: MUST FIRST UPDATE OLD CURSOR VALS +*** MOVEM.W (SP)+,D0-D1 + +SCURX2 SUBQ.W #1,D0 * >> GIVEN 1-ORIGIN << + BLT.S SCURX3 + MOVE.W D0,_cur_row * >> STORE 0-ORIGIN << +SCURX3 SUBQ.W #1,D1 + BLT.S SCURX4 + MOVE.W D1,_cur_column + +SCURX4 +*** SAVEREGS +*** JSR _write_cursor_pos +*** RESTREGS + RTS + +* RETURN CURSOR POSITION ("IN SCREEN 1 ONLY" - SPEC) +* RETURN D0.W = ROW, D1.W = COL + +GETCURS +*** SAVEREGS +*** JSR _read_cursor_pos +*** RESTREGS + + MOVE.W _cur_row,D0 * >> STORED AS 0-ORIGIN << + ADDQ.W #1,D0 * >> RETURN AS 1-ORIGIN << + MOVE.W _cur_column,D1 + ADDQ.W #1,D1 + RTS + +* GET FULL-SCREEN DIMENSIONS, RETURN D0.W = ROWS, D1.W = COLS + +MAXSCRN MOVE.W _rows,D0 + MOVE.W _columns,D1 + RTS + +* SET THE LEFT AND RIGHT MARGINS +* D0.W = LEFT, D1.W = RIGHT (DEFAULTS ARE BOTH 0) + +SETMARG MOVE.W D0,_marg_left + MOVE.W D1,_marg_right + RTS + +* RETURN THE LEFT AND RIGHT MARGINS + +GETMARG MOVE.W _marg_left,D0 + MOVE.W _marg_right,D1 + RTS + +* SET AN "UNDO-SUPPORTED" FLAG FOR PASCAL + +SETUNDO RTS * [AMIGA: NOT USED] + +* SET FONT (IN CURRENT WINDOW), D0.W = ID [MAC: "IN ALL WINDOWS" ] + +ALTCHR EQU 128 * HACK IN HiLight FOR ALT CHARSET +STDCHR EQU 0 * REVERT TO NORMAL (PLAIN) + +SETFONT CMPI.W #3,D0 * ALT CHARSET? + BNE.S SFNTX1 + MOVE.W #ALTCHR,D0 * YES + BRA MDATTR +SFNTX1 MOVEQ #STDCHR,D0 * ANYTHING ELSE MEANS NORMAL + BRA MDATTR + +* RETURN FONT (IN CURRENT WINDOW), D0.W = ID + +GETFONT MOVEQ #-1,D0 + BSR MDATTR + ANDI.W #ALTCHR,D0 * IN ALT CHARSET? + BNE.S GFNTX1 * YES + MOVEQ #1,D0 * ANYTHING ELSE MEANS NORMAL FONT + RTS + +GFNTX1 MOVEQ #3,D0 + RTS + +* CLEAR FROM CURSOR TO END OF CURRENT LINE + +MDERASE SAVEREGS + JSR _erase_eol + RESTREGS + RTS + +* CLEAR SEVERAL LINES +* GIVEN D0.W = FIRST (1-ORIGIN), D1.W = LAST (INCLUSIVE) + +MDCLEAR SAVEREGS + MOVE.L D1,-(SP) * >> MAKE LAST+1, 0-ORIGIN << + SUBQ.W #1,D0 * >> MAKE 0-ORIGIN << + MOVE.L D0,-(SP) + JSR _clear_lines + FLUSH 8 + RESTREGS + RTS + +* SET/GET SCREEN COLORS +* GIVEN D0.W = FORE, D1.W = BACK (ZERO = NO CHANGE) +* RETURN D0.W = DEFBACK/DEFFORE, D1.W = COLOR/MONO FLAG + +MDCOLOR SAVEREGS + RESWORD + MOVE.L D1,-(SP) + MOVE.L D0,-(SP) + JSR _set_color + FLUSH 8 + POPWORD + RESTREGS + MOVE.W _color,D1 + RTS + +* SET THE HIGHLIGHT ATTRIBUTES, ARGBIT(S) IN D0.W +* IF D0 = -1, JUST RETURN OLD ATTRIBUTES >> AMIGA: NOT IMPLEMENTED << + +MDATTR SAVEREGS + RESWORD + MOVE.L D0,-(SP) + JSR _highlight + FLUSH 4 + POPWORD * OLD ATTRIBUTES + RESTREGS + RTS + +* LOOKUP PICTURE SIZE INFO +* GIVEN D0.W = ID, A0 -> TABLE FOR RESULTS (WIDTH, HEIGHT) +* IF ID = 0, RETURN MAX ID IN TABLE WORD 0 +* IF ID IS IN ERROR, RETURN FLAGS NEGATIVE, ELSE ZERO + +PICINF MOVEQ #-1,D0 * [MAC: NOT IMPLEMENTED] + RTS + +** MOVE.L A1,A0 +** BSR PTAWRD * STORE WIDTH (OR MAX ID) +** TST.W D2 * WAS REQUEST FOR MAX ID ONLY? +** BEQ.S OPICX1 * YES + +** MOVE.L A1,A0 +** ADDQ.L #2,A0 +** MOVE.W D1,D0 +** BSR PTAWRD * STORE HEIGHT + +* DISPLAY [OR CLEAR] A PICTURE +* D0.W = ID (1-ORIG), D1,D2 = XPOS,YPOS (1-ORIG), D3 = FLAG, SET TO CLEAR + +PICDISP RTS + +* IF A TITLE SCREEN WAS DRAWN, WAIT FOR A KEY. DON'T ERASE SCREEN, LET +* GAME. (OTHERWISE MAY CAUSE A FLASH AS GAME SETS UP ITS SCREEN COLORS.) +* COME HERE AFTER GAME HAS BEEN LOADED BUT BEFORE STARTING. + +ENDTITLE + RTS + +* ---------------------- +* GERCHR +* ---------------------- + +* GIVEN A CHAR IN D0, CHECK IF IT'S AN XZIP (EXTENSION) GERMAN CHAR +* IF SO, CONVERT THE BYTE TO ITS NATIVE KEYCODE, IF ANY + +GERCHR TST.B D0 * HIGH BIT SET? + BGE.S GERCX4 * NO, CAN'T BE AN GERMAN CHAR (EXIT) + + MOVE.W D0,-(SP) * SAVE CHAR HERE + BSR GETFONT + SUBQ.W #1,D0 * CURRENTLY IN FONT 1 (NORMAL)? + BNE.S GERCX3 * NO, CAN'T BE A GERMAN CHAR (EXIT) + + MOVE.W (SP),D0 * (COPY FROM STACK) + SAVEREGS + RESWORD + CLR.L -(SP) * CONVERT /TO/ NATIVE + MOVE.L D0,-(SP) + JSR _german_convert + FLUSH 8 + POPWORD + RESTREGS + TST.B D0 * WAS IT GERMAN? + BEQ.S GERCX3 * NO + MOVE.W D0,(SP) * YES, REPLACE OLD VALUE +GERCX3 MOVE.W (SP)+,D0 * RETURN CHAR +GERCX4 RTS + + + +* ---------------------- +* SYSIN1 +* ---------------------- + +* MISC SYSTEM INITIALIZATION + +SYSIN1 BSR OPNGAM + BNE.S SYSX1 * ERROR + RTS * OK + +SYSX1 LEA MSGOPN,A0 + BRA FATAL * 'Story file open error.' + + SECTION ZDATA +MSGOPN DC.B 'Story file open error.',0 + SECTION ZCODE + +* ---------------------- +* GETM, GETMEM +* ---------------------- + +* ALLOCATE MEMORY, NUMBER OF BYTES REQUESTED IN D0.L, RETURN POINTER IN A0 +* (GETMEM TRAPS ERRORS, GETM DOESN'T) + +GETM SAVEREGS + BTST #0,D0 * ODD REQUEST? + BEQ.S GETMX1 * NO + ADDQ.L #1,D0 * YES, ROUND UP (FIXES ST GEMDOS-48 BUG) + +GETMX1 RESLONG + MOVE.L D0,-(SP) * REQUEST + JSR _c_getmem + FLUSH 4 + POPLONG + MOVE.L D0,A0 * RESULT, ZERO IF ERROR + RESTREGS + RTS + +* ALLOCATE MEMORY AS ABOVE, AND CHECK FOR ERROR + +GETMEM BSR GETM + MOVE.L A0,D0 * GOT IT? + BEQ.S MEMERROR * ZERO MEANS FAILURE + RTS + +MEMERROR + CLR.W D0 + LEA MSGME1,A0 + BRA FATAL * 'Memory block allocation error' + + SECTION ZDATA +MSGME1 DC.B 'Memory block allocation error',0 + SECTION ZCODE + +* ---------------------- +* MEMAVAIL +* ---------------------- + +* INQUIRE AVAILABLE MEMORY +* GIVEN D0.L = MAX GAME LEN + OVERHEAD (BYTES) +* RETURN D0.L = NUMBER OF BYTES AVAILABLE (MAY BE FUDGED) + +MEMSYS EQU 0 *** 40*512 * SYS OVERHEAD [moved to high-level] +MEMGAM EQU 280*1024 * XZIP GAME MAX (256 + PAGTAB + MISC) + +MEMAVAIL + SAVEREGS + RESLONG + MOVE.L #MEMGAM,D0 * CRUDE UPPER LIMIT, PRELOAD+PAGES + MOVE.L D0,-(SP) + JSR _c_maxmem + FLUSH 4 + POPLONG +** SUB.L #MEMSYS,D0 + RESTREGS + RTS + +* ---------------------- +* GTSEED +* ---------------------- + +* RETURN A RANDOM NUMBER SEED IN D0, DIFFERENT EACH COLDSTART + +GTSEED SAVEREGS + RESLONG + JSR _random_seed + POPLONG + RESTREGS + RTS + +* ---------------------- +* TIME60 +* ---------------------- + +* ELAPSED TIME (IN 60THS SECOND) SINCE SYSTEM STARTUP + +TIME60 MOVEQ #0,D0 + RTS + +* ---------------------- +* CHSIZ +* ---------------------- + +* GIVEN AN ASCII CHAR, RETURN ITS UNIT WIDTH (IN CURRENT FONT) + +CHSIZ MOVEQ #1,D0 * [MAC: ALWAYS ONE, FOR NOW] + RTS + +* ---------------------- +* DOSOUND +* ---------------------- + +* AMIGA: ADJUST ARGS +* VOLUME: 0-64, -1=USE MIDI VOL +* COUNT: 0=INFINITE, 1-254=FINITE, -1=USE MIDI COUNT + +DOSOUND TST.W D2 + BLT.S DOSDX1 + ASL.W #3,D2 * MAP 0-8 TO 0-64 + +DOSDX1 TST.W D3 + BGT.S DOSDX2 * IF 1-254, JUST PASS ALONG + ADDQ.W #1,D3 * MAP -1 TO 0 + BEQ.S DOSDX2 + MOVEQ #-1,D3 * MAP 0 TO -1 + +DOSDX2 SAVEREGS + MOVE.L D3,-(SP) * COUNT + MOVE.L D2,-(SP) * VOLUME + MOVE.L D1,-(SP) * ACTION + MOVE.L D0,-(SP) * ID + JSR _md_sound + FLUSH 16 + RESTREGS + RTS + +* ---------------------- +* GAMINT, GAMINT1 +* ---------------------- + +* PERIODICALLY CHECK FOR GAME INTERRUPTS + +* NOTE: BECAUSE THE INTERPRETER AS A WHOLE IS /NOT/ RE-ENTRANT, THIS +* ROUTINE CHOULD BE CALLED ONLY FROM THE TOP OF THE MAIN LOOP (NXTINS), AND +* (PERHAPS) FROM OPREAD/OPINPUT (SO SOUNDS CAN CHAIN BETWEEN MOVES). +* BUT IT SHOULD /NOT/ BE CALLED FROM ITTYIN, SINCE THAT IS ALSO CALLED +* FROM [MORE], AND THE INTERPRETER STATE IS UNDEFINED. + +SKPCNT EQU 50 * 2500 ops/sec (max) ==> 50 ints/sec (max) + +* ENTRY POINT FROM MAIN LOOP +* To avoid cutting into interpreter performance too much, we keep a +* simple counter, and only occasionally perform the (somewhat costlier) +* check for a sound interrupt. + +GAMINT SUBQ.W #1,SCOUNT(A6) * TIME FOR A SOUND CHECK? + BLE.S GAMIX1 + RTS * NO, QUICK EXIT +GAMIX1 MOVE.W #SKPCNT,SCOUNT(A6) * YES, RESET COUNTER AND FALL THRU + +* ENTRY POINT FROM INPUT-WAIT LOOP +* While awaiting Amiga input, we awaken only 10 times/sec anyway, so check +* for sound every time. Might actually prefer it be a bit more frequent. +* Note: called from OPREAD/OPINPUT; probably safe to call interrupt function +* as long as it doesn't itself call OPREAD/OPINPUT. + +GAMINT1 SAVEREGS + +* (could check first for valid SFUNC(A6), skip end-check if none, +* but then end event would hang around unreported ...) + + RESWORD + JSR _end_sound * END-OF-SOUND CHECK + POPWORD * NON-ZERO IF END DETECTED + BEQ.S GAMIX3 + + MOVE.W SFUNC(A6),D0 * SOUND-INTERRUPT FUNCTION ("START NEXT") + BEQ.S GAMIX3 * NONE + BSR INCALL * CALL IT (INTERNALLY) +*** TST.W D0 * (NO RETURN VAL) + +GAMIX3 +*** JSR _int_key * TYPE-AHEAD CHECK (here or from real int?) + RESTREGS + RTS + +* ---------------------- +* FINISH +* ---------------------- + +* RESTART THE SYSTEM (RETURN TO THE DESKTOP) + +FINISH MOVEQ #0,D0 * LAST-USED SOUND ID + MOVEQ #4,D1 * CLEANUP + MOVEQ #-1,D2 * (DEF VOL) + MOVEQ #-2,D3 * (DEF REPEAT) + BSR DOSOUND * MAKE SURE IT'S GONE + + MOVEQ #0,D0 + BSR SCRINIT * MAKE SURE SCRIPTING'S OFF + + TST.W INLAST(A6) * HAS THERE BEEN INPUT SINCE LAST OUTPUT? + BNE FINIX3 * YES, JUST EXIT + + BSR PUTNEW * NO, MUST FIRST PAUSE FOR A PROMPT + LEA MSGKEY,A0 + BSR OUTMSG0 * 'Press any key to exit ' + + SECTION ZDATA +MSGKEY DC.B 'Press any key to exit ',0 + SECTION ZCODE + +** AMIGA: MUST SKIP THIS WHILE NO NULL-KEYS +** MOVEQ #1,D0 * [ALWAYS SETUP AROUND ITTYIN] +** MOVEQ #0,D1 * SINGLE CHAR +** BSR SETUPI +**FINIX2 BSR ITTYIN * FIRST CHECK FOR ANY TYPED-AHEAD KEYS ... +** TST.B D0 * AND DISCARD THEM +** BNE FINIX2 * UNTIL NO MORE +** MOVEQ #0,D0 +** MOVEQ #0,D1 * SINGLE CHAR +** BSR SETUPI + BSR TTYIN * THEN WAIT FOR ONE MORE + +FINIX3 BSR CLSGAM * CLOSE GAME FILE + UNLK A6 * FLUSH THE ZIP'S STACK FRAME + RTS * RETURN TO ORIGINAL CALLER + + + PAGE +* ----------------------------------------------- +* SCREEN/KEY I/O +* ----------------------------------------------- + +* ---------------------- +* SETUPI +* ---------------------- + +* MUST "BRACKET" CALLS TO TTYIN OR INCHR WITH CALLS TO HERE +* ACTIVATES/DEACTIVATES BLINKING CURSOR AND MENU COMMAND-STRINGS +* D0.W = 1 TO BEGIN CURSOR, 0 TO END +* D1.W = 1 IF STRING INPUT, 0 IF SINGLE-CHAR INPUT + +SETUPI TST.W D0 * STARTING INPUT? + BEQ.S SETUX1 * NO, ENDING + MOVE.W #1,INLAST(A6) * SET INPUT FLAG + CLR.W LINES(A6) * RESET THE [MORE] COUNTER + +SETUX1 SAVEREGS + EXT.L D1 + MOVE.L D1,-(SP) + EXT.L D0 + MOVE.L D0,-(SP) * [PASCAL: MOVE.B FOR BOOLS] + JSR _setup_input + FLUSH 8 + RESTREGS + RTS + +* ---------------------- +* INCHR +* ---------------------- + +* INPUT A CHAR AND ECHO IT, RETURN CHAR IN D0 *** DEAD, USE READLN *** +* [CAREFUL WITH CR AND BACKSPACE] + +INCHR BSR TTYIN * GET CHAR + TST.W VIECHO(A6) * IS ECHOING TURNED OFF? + BEQ.S INCHX1 * YES, JUST EXIT + + MOVE.W D0,-(SP) + BSR TTYOUT * ECHO CHAR + MOVE.W (SP)+,D0 +INCHX1 RTS + +* ---------------------- +* TTYIN, ITTYIN +* ---------------------- + +* INPUT A SINGLE CHAR (XZIP: or mouse clicks), NO ECHO +* IF NONE AVAILABLE, RETURN A ZERO IMMEDIATELY + +ITTYIN SAVEREGS + RESWORD + JSR _event_in + POPWORD + RESTREGS + ANDI.W #$00FF,D0 + BEQ.S ITTYX3 * [AMIGA:] NULL EVENTS ARE FOR TIMING + CMPI.B #253,D0 * MOUSE BUTTON CLICK? (SINGLE OR DOUBLE) + BEQ.S ITTYX6 * YES + CMPI.B #254,D0 + BEQ.S ITTYX6 * YES + + CMPI.B #127,D0 * [ALL: MAP 'DEL' TO 'BS'] + BNE.S ITTYX1 + MOVEQ #8,D0 + +ITTYX1 CMPI.B #3,D0 * [MAC: MAP 'ENTER' TO 'RETURN'] + BNE.S ITTYX2 + MOVEQ #13,D0 + +ITTYX2 CMPI.B #13,D0 * CR,BS ARE ONLY VALID CONTROL CHARS + BEQ.S ITTYX3 + CMPI.B #8,D0 + BEQ.S ITTYX3 + + CMPI.B #31,D0 * DISCARD OTHERS (TAB, CLR, ETC) + BLS ITTYIN * (LOOP BACK FOR ANOTHER) +ITTYX3 RTS * RETURN CHAR OR FKEY + +* HERE AFTER MOUSE EVENT, STORE POSITION IN GLOBALS + +ITTYX6 MOVE.W D0,-(SP) * SAVE MOUSE CODE (SINGLE OR DOUBLE) + +*** ["BZ" ISN'T SETTING THE MOUSE BIT; DEPEND FOR NOW ON LOWCORE ERR-CHECK] +*** MOVE.L BUFFER(A6),A0 +*** MOVE.W PFLAGS(A0),D0 +*** BTST #FMOUS,D0 * BUT DOES GAME USE MOUSE? +*** BEQ.S ITTYX8 * NO + + MOVEQ #PMLOCX,D0 * LOWCORE-EXTENSION VAR FOR MOUSE XPOS + BSR LOWCORE * GET ITS ADDR + BEQ.S ITTYX8 * ERROR (TABLE UNDEFINED, OR TOO SMALL) + MOVE.W _xmouse,D0 +** ADDQ.W #1,D0 * (MAKE 1-ORIGIN) + BSR PTAWRD * STORE MOUSE X POSITION + + MOVEQ #PMLOCY,D0 + BSR LOWCORE + BEQ.S ITTYX8 * ERROR + MOVE.W _ymouse,D0 +** ADDQ.W #1,D0 * (MAKE 1-ORIGIN) + BSR PTAWRD * STORE MOUSE Y POSITION + BRA.S ITTYX9 + +ITTYX8 CLR.W (SP) * ERROR, DISCARD MOUSE EVENT +ITTYX9 MOVE.W (SP)+,D0 * RETURN MOUSE CODE + RTS + +* ENTER HERE TO LOOP UNTIL A CHAR IS AVAILABLE + +TTYIN MOVEM.L D1-D2,-(SP) + MOVEQ #1,D0 * SET UP FOR INPUT + MOVEQ #0,D1 * SINGLE CHAR + BSR SETUPI + +TTYX1 BSR ITTYIN + TST.B D0 + BEQ.S TTYX1 * IF NONE, KEEP WAITING + + MOVE.W D0,D2 + MOVEQ #0,D0 * FINISHED INPUT + MOVEQ #0,D1 * SINGLE CHAR + BSR SETUPI + MOVE.W D2,D0 * RETURN THE CHAR + MOVEM.L (SP)+,D1-D2 + RTS + +* ---------------------- +* OUTCHR +* ---------------------- + +* OUTPUT THE CHAR (OR CR) IN D0.B (SCROLLING IF NECESSARY) + +OUTCHR CMPI.B #13,D0 * [DON'T PAUSE AT FINISH JUST FOR CR'S] + BEQ.S TTYOUT + CLR.W INLAST(A6) * CURRENT I/O IS OUTPUT + +TTYOUT SAVEREGS + MOVEQ #0,D1 + MOVE.B D0,D1 * CLEAR HIGH BYTE + + CMPI.B #13,D1 * IS THIS A CR? + BNE.S TTYOX1 + BSR CRCHECK * YES, CHECK FOR POSSIBLE INTERRUPT (XZIP) + +TTYOX1 MOVE.L D1,-(SP) + JSR _char_out + FLUSH 4 + RESTREGS + RTS + +* ---------------------- +* CRCHECK +* ---------------------- + +* XZIP: WE'RE ABOUT TO OUTPUT A CARRIAGE RETURN; CHECK FOR A SPECIAL INTERRUPT + +CRCHECK MOVE.L BUFFER(A6),A0 + MOVE.L A0,D0 * CHECK IF VALID (MAY BE HERE AFTER INIT ERROR) + BEQ.S CRCHX6 + TST.W PCRCNT(A0) * CR COUNTER ACTIVE? + BEQ.S CRCHX6 * NO + SUBQ.W #1,PCRCNT(A0) * YES, DECREMENT IT; REACHED ZERO? + BNE.S CRCHX6 * NO + +* AN INTERRUPT IS REQUESTED; INTERNALLY CALL THE INTERRUPT FUNCTION. + +* Problem: register A4, dedicated to the game SP, is needed for this call +* but is NOT currently valid. That's because some of the I/O handlers +* "borrow" it, assuming that such an value would never be needed during I/O. +* Is this a good reason to avoid dedicating any other registers? + + MOVE.L A4,-(SP) + MOVE.L STKBOT(A6),A4 * FAKE A SMALL GAME STACK + ADDA.W #100,A4 * AT THE BOTTOM OF THE REAL ONE + + MOVE.W PCRFUNC(A0),D0 + BSR INCALL * AND HANDLE THE INTERRUPT + MOVE.L (SP)+,A4 +CRCHX6 RTS + +* ---------------------- +* NXTLIN +* ---------------------- + +* CHECK FOR END-OF-PAGE CONDITION + +NXTLIN MOVEM.L D1-D2,-(SP) + BSR MAXSCRN + MOVE.W D0,D1 * TOTAL LINES + BSR GETSPLT + SUB.W D0,D1 * LINES AVAILABLE FOR SCROLLING + SUBQ.W #1,D1 * ALLOW ONE LINE FOR [MORE] ITSELF + BLE.S NXTLX6 * DEGENERATE CASE, DON'T PAUSE + + CMP.W LINES(A6),D1 * PAGE FULL YET? + BGT.S NXTLX6 * NO, EXIT + + IFEQ CZIP + BSR OPUSL * UPDATE STATUS LINE NOW + ENDC + +*** MOVE.W _v_italic,-(SP) * SAVE ITALICS STATUS HERE +*** TST.W (SP) * CURRENTLY IN ITALIC MODE? +*** BEQ.S NXTLX1 * NO +*** CLR.L -(SP) * YES, SWITCH TO NORMAL FOR [MORE] +*** JSR _highlight * 0 NORMAL, 4 ITALIC +*** ADDQ.L #4,SP + +NXTLX1 LEA MSGMOR,A0 * DISPLAY A PROMPT (NO CR) + MOVEQ #6,D0 + BSR PRINT * WRITE DIRECTLY TO SCREEN + SECTION ZDATA +MSGMOR DC.B '[MORE]',0 + SECTION ZCODE + + BSR TTYIN * AND WAIT FOR A KEY, NO ECHO + + MOVEQ #6,D1 * PROMPT LENGTH +NXTLX2 MOVEQ #8,D0 + BSR TTYOUT * BACKUP CURSOR + SUBQ.W #1,D1 + BNE.S NXTLX2 + + +*** TST.W (SP) * FORMERLY IN ITALICS MODE? +*** BEQ.S NXTLX4 * NO +*** MOVEQ #4,D0 * YES, RESUME +*** MOVE.L D0,-(SP) +*** JSR _highlight * 0 NORMAL, 4 ITALIC +*** ADDQ.L #4,SP + +NXTLX4 MOVE.W #1,LINES(A6) * RESET COUNTER, ALLOWING ONE OVERLAP LINE +NXTLX6 MOVEM.L (SP)+,D1-D2 + RTS + +* ---------------------- +* PRINT +* ---------------------- + +* OUTPUT A STRING, POINTER IN A0, LENGTH IN D0.W + +PRINT CLR.W INLAST(A6) * CURRENT I/O IS OUTPUT + TST.W D0 + BEQ.S PRINTX1 * SKIP OUT IF NULL + SAVEREGS + MOVE.L D0,-(SP) * AND LENGTH + MOVE.L A0,-(SP) * PASS THE STRING POINTER + JSR _line_out + FLUSH 8 + RESTREGS +PRINTX1 RTS + +* ---------------------- +* BUFOUT +* ---------------------- + +* OUTPUT THE LINE BUFFER, BEGINNING AND END IN A0, D0 +* FIRST CHECK FOR END-OF-SCREEN CONDITION (UNLESS IN WINDOW 1) + +BUFOUT MOVEM.L D0/A0,-(SP) + BSR GETSCRN * IN WINDOW 1? + BNE.S BUFUX1 * YES, SKIP THE SCREEN CHECK + BSR NXTLIN * PAUSE FOR [MORE] IF NECESSARY + +BUFUX1 MOVEM.L (SP)+,D0/A0 + SUB.L A0,D0 * CURRENT LENGTH OF BUFFER IN D0.W + BLE.S BUFUX2 * EXIT IF NOTHING + BSR PRINT * OTHERWISE, DISPLAY IT +BUFUX2 RTS + +* ---------------------- +* LINOUT +* ---------------------- + +* OUTPUT THE LINE BUFFER THEN ADD A CR, BEGINNING AND END IN A0, D0 +* ALSO UPDATE THE CUMULATIVE LINE COUNTER + +LINOUT BSR BUFOUT * DISPLAY IT + MOVEQ #13,D0 + BSR OUTCHR * AND TACK ON A CR + + BSR GETSCRN * IN WINDOW 1? + BNE.S LINOX1 * YES, IGNORE COUNTER + ADDQ.W #1,LINES(A6) * OTHERWISE UPDATE THE [MORE] COUNTER +LINOX1 RTS + + + PAGE +*---------------------------------------------------------------------------- +* ZIP MESSAGES +*---------------------------------------------------------------------------- + +* ---------------------- +* OUTMSG +* ---------------------- + +* OUTPUT AN ASCIZ MESSAGE, POINTER IN A0 + +OUTMSG0 MOVE.L A1,-(SP) + MOVE.L A0,A1 * STRING POINTER + +OUTMX1 CLR.W D0 + MOVE.B (A1)+,D0 * GET NEXT CHAR, END OF STRING? + BEQ.S OUTMX2 * YES + + BSR PUTCHR * NO, DISPLAY/QUEUE IT + BRA OUTMX1 + +OUTMX2 TST.W VOBUFF(A6) * ARE WE BUFFERING OUTPUT? + BEQ.S OUTMX3 * NO + BSR PUTLIN * YES, EMPTY THE BUFFER NOW + +OUTMX3 MOVE.L (SP)+,A1 + RTS + +* OUTPUT AN ASCIZ MESSAGE, POINTER IN A0 (NULL IF NONE) +* THEN APPEND A CR + +OUTMSG MOVE.L A0,D0 * ANY MESSAGE? + BEQ.S OUTMX9 * NO, JUST A CR + BSR OUTMSG0 * YES, OUTPUT THE STRING +OUTMX9 BRA PUTNEW + +* ---------------------- +* ZWARN +* ---------------------- + +* PRINT AN INTERPRETER WARNING, A0 -> MESSAGE + +ZWARN MOVE.L A0,-(SP) + BSR PUTNEW * CR + LEA MSGZWR,A0 + BSR OUTMSG0 * MESSAGE HEADER + + SECTION ZDATA +MSGZWR DC.B $2A,$2A,$2A * [***] + DC.B ' Interpreter warning: ',0 + SECTION ZCODE + + MOVE.L (SP)+,A0 * MESSAGE + BRA OUTMSG + +* ---------------------- +* FATAL +* ---------------------- + +* PRINT A FATAL ERROR HEADER, CODE NUMBER AND MESSAGE (LAST TWO ARE OPTIONALS) +* ERROR CODE IN D0.W, STRING IN A0, ZERO MEANS NONE + +FATAL MOVE.L A0,A1 * [TRASHES THESE REGS, BUT DOESN'T MATTER] + MOVE.W D0,D1 + BSR PUTNEW * NEW LINE + + LEA MSGFTL,A0 * PRINT A STANDARD ERROR HEADER, NO CR + BSR OUTMSG0 * 'Internal Error ' + + SECTION ZDATA +MSGFTL DC.B 'Internal Error ',0 + SECTION ZCODE + + TST.W D1 * GOT A NUMBER? + BEQ.S FATLX1 * NO + MOVE.B #'#',D0 * YES, PRINT A PREFIX + BSR PUTCHR + MOVE.W D1,D0 * PRINT THE ERROR NUMBER + BSR OPPRNN + +FATLX1 BSR PUTNEW * ANOTHER CR + MOVE.L A1,D0 * GOT A MESSAGE? + BEQ.S FATLX2 + MOVE.L A1,A0 * YES, DISPLAY IT + BSR OUTMSG +FATLX2 BRA FINISH * WAIT FOR FINAL KEY, AND EXIT + +* -------------------------------------------------------------- +* SCRIPTING STUFF +* -------------------------------------------------------------- + +* ---------------------- +* SCRINIT +* ---------------------- + +* OPEN/CLOSE SCRIPTING DEVICE (D0.W SET FOR OPEN) +* RETURN ACTIVE/INACTIVE STATUS FLAG + +SCRINIT SAVEREGS + RESWORD + EXT.L D0 * 1 FOR OPEN, ZERO FOR CLOSE + MOVE.L D0,-(SP) + JSR _script_open + FLUSH 4 + POPWORD * STATUS (ERRCODE WOULD BE BETTER ...) + RESTREGS + RTS + +* ---------------------- +* SCRERR +* ---------------------- + +* SCRIPT ERROR HANDLER +* WANT TO TERMINATE SCRIPTING ATTEMPTS (UNTIL NEXT SCRIPT COMMAND) +* DE-ACTIVATE PRINTER, ADJUST ZIP INTERNAL VARIABLES + +SCRERR SAVEREGS + CLR.W D0 * ZERO FOR CLOSE + BSR SCRINIT * DEACTIVATE THE DEVICE + + MOVE.L BUFFER(A6),A0 + BCLR #FSCRI,PFLAGS+1(A0) * FORCE SCRIPT BIT OFF (ZIP + EZIP) + IFEQ EZIP + CLR.W VOPRNT(A6) * TURN OFF EZIP'S FLAG + ENDC + + LEA MSGPRR,A0 + BSR OUTMSG + BSR PUTNEW + + SECTION ZDATA +MSGPRR DC.B '[Printer not ready, scripting halted]',0 + SECTION ZCODE + + RESTREGS + RTS + +* ---------------------- +* SCROUT +* ---------------------- + +* SCRIPT OUT A LINE, START IN A0, END IN D0, THEN TACK ON A CR/LF + +SCROUT SAVEREGS + SUB.L A0,D0 * LENGTH OF STRING + + MOVE.L D0,-(SP) + MOVE.L A0,-(SP) + JSR _script_line + FLUSH 8 + + TST.W D0 * ERROR? + BEQ.S SCOTX1 * NO + BSR SCRERR * YES, CLEAN UP AND DEACTIVATE + +SCOTX1 RESTREGS + RTS + +* -------------------------------------------------------------- +* *** PURE HACKERY *** +* -------------------------------------------------------------- + +* THIS ROUTINE EXISTS TO ALLOW MACINTOSH USERS TO LAUNCH DIRECTLY INTO +* A SAVED GAME (BY DOUBLE-CLICKING IT), SKIPPING THE NORMAL GAME +* OPENING. IT CAN FUNCTION AT MOST ONCE. + +* WE USED TO FORCE A "VERSION" DISPLAY (BY FAKING INPUT). THIS PREVENTED +* AN OPENING SCREEN THAT (IN SOME ZIP GAMES) SAID NOTHING BUT "OK". BUT +* SOME LATER GAMES PRINT LENGTHY DESCS, AND A "VERSION" LOOKS BAD. + +SYSIN2 +** MOVE.L APPARM(A6),D0 * GET THE "FINDER PARAMETERS" HANDLE +** BEQ.S SS2X1 * EXIT IF BEEN HERE ALREADY (HANDLE IS NULL) +** CLR.L APPARM(A6) * MARK HANDLE, SO THIS CODE ONLY RUNS ONCE! +** +** MOVE.L D0,A0 +** MOVE.L (A0),A0 * EXTRACT THE POINTER +** TST.W 2(A0) * WAS ZIP LAUNCHED VIA A SAVED GAME? +** BEQ.S SS2X1 * NO, NORMAL LAUNCH, JUST MARK THE HANDLE +** BSR FNDRSF * COPY FINDER INFO INTO SF REPLY RECORD + +** MOVE.L BUFFER(A6),A0 +** BSET #FSTAT,PFLAGS+1(A0) * REQUEST STATUS LINE BE REDRAWN + +* WARNING: HACKING (FOR TIMEOUTS) IN RES1 MEANS THAT CONTROL MAY NEVER +* RETURN HERE (IT JUMPS TO DISPATCH). DON'T ADD CODE BEYOND THIS POINT!. + +** BSR RES1 * DO A SPECIAL RESTORE, SKIPPING NORMAL DIALOG +SS2X1 RTS + +* GIVEN A0 -> "FINDER PARAMETERS BLOCK" (AS FROM GetAppParm), +* COPY THE SAVED GAME INFO (NAME AND VOL) INTO OUR RESTORE VARS +* (USE ONLY FIRST GAME, IF MORE THAN ONE IS INDICATED) + +FNDRSF +** MOVEM.L D1/A1-A2,-(SP) +** MOVE.L A0,A2 * PARAMS PTR HERE + +** LEA 12(A2),A0 * COPY FILE NAME +** LEA filename,A1 +** MOVEQ #1,D0 * ALLOW FOR LENGTH BYTE +** ADD.B (A0),D0 * IN FIRST BYTE [MAC PASCAL] +** MOVEQ #64,D1 * MAX LEN (OF filename) +** BSR COPYS + +** MOVE.W 4(A2),filevol * AND COPY VOLUME REFNUM +** MOVEM.L (SP)+,D1/A1-A2 + RTS + + + PAGE +* --------------------------------------------------------------------------- +* DISK I/O ROUTINES +* --------------------------------------------------------------------------- + +* GENERAL CONVENTION FOR DISK ROUTINE RESULTS: +* IF ROUTINE SUCCEEDS, RETURN WITH FLAGS INDICATING "ZERO" +* OTHERWISE, CALLER TRAPS ERRORS WITH A CONDITIONAL BRANCH ("BNE.S ERROR") + + +* OPEN THE GAME FILE, STORE REFNUM, RETURN FLAGS +* (THIS ROUTINE CALLED DURING INIT *AND* DURING SAVE/RESTORE) + +OPNGAM SAVEREGS + JSR _open_game * OPEN THE GAME FILE, LEAVE REFNUM + TST.L D0 * RETURN ZERO FLAG FOR OKAY, ELSE ERROR +OPNGX1 RESTREGS + RTS + +* CLOSE THE GAME FILE, RETURN FLAGS + +CLSGAM SAVEREGS + JSR _close_game * CLOSE THE GAME FILE + TST.L D0 * RETURN THE RESULT CODE + RESTREGS + RTS + +* ---------------------- +* GETBLK +* ---------------------- + +* GET A GAME FILE BLOCK, BLOCK NUMBER IN D0, CORE TARGET LOCATION IN A0 + +GETBLK MOVEM.L D1,-(SP) + MOVEQ #1,D1 * ONE BLOCK + BSR GTBLKS + MOVEM.L (SP)+,D1 * (DOESN'T ALTER FLAGS) + RTS + +* GET A SERIES OF GAME FILE BLOCKS +* FIRST BLOCK NUMBER IN D0, CORE TARGET LOCATION IN A0, TOTAL BLOCKS IN D1 + +GTBLKS SAVEREGS + BSR BLKBYT * CONVERT BLOCKS TO BYTES + EXG D1,D0 + BSR BLKBYT + EXG D1,D0 + RESWORD + MOVE.L A0,-(SP) * BUFFER + MOVE.L D1,-(SP) * LENGTH IN BYTES + MOVE.L D0,-(SP) * OFFSET IN BYTES + MOVE.L _game_ref,D0 * [OK TO TRASH D0 NOW] + MOVE.L D0,-(SP) + JSR _read_file + FLUSH 16 + POPWORD * ERROR ON READ? + BNE.S GTBKX2 * YES, FAIL +GTBKX1 RESTREGS + RTS + +* TST.W DSKERR(A6) * BUT WERE WE ASKED TO RETURN WITH FLAGS? +* BNE GTBKX1 * YES + +GTBKX2 LEA MSGREA,A0 * ERROR CODE IN D0 + BRA FATAL * 'Story file read error.' + + SECTION ZDATA +MSGREA DC.B 'Story file read error.',0 + SECTION ZCODE + + + PAGE +* -------------------------------------------------------------------------- +* SAVE/RESTORE -- DISK I/O ROUTINES +* -------------------------------------------------------------------------- + +* ---------------------- +* DKSWAP +* ---------------------- + +* PRELIMINARY DIALOG FOR SAVE/RESTORE +* PROMPT USER TO SWAP DISKS AND IDENTIFY DRIVE BEING USED +* RETURN LETTER IN D0, ZERO FOR DEFAULT + +* >>> THIS FUNCTION NOW HANDLED WITHIN FILE-SELECT CALL <<< + +* ---------------------- +* DUPNAM +* ---------------------- + +* DUPLICATE NAME CHECK/DIALOG (FOR SAVES ONLY) +* CHECK FOR FILENAME CONFLICT, IF SO, PROMPT USER FOR INSTRUCTIONS +* RETURN ZERO TO PROCEED NORMALLY, OTHERWISE ABORT + +DUPNAM + SAVEREGS + RESWORD + JSR _exist_file + POPWORD + MOVE.W D0,D1 * RESULT + BEQ.S DUPX3 * ZERO MEANS NONE + +DUPX1 LEA MSGDUP,A0 + BSR OUTMSG0 * PROMPT, DON'T ADD A CR + + SECTION ZDATA +MSGDUP DC.B 'You are about to write over an existing file. ' + DC.B 'Proceed? (Y/N) ',0 + SECTION ZCODE + + BSR TTYIN * GET A CHAR + CLR.W D1 * ASSUME A NORMAL SAVE + + CMPI.B #'Y',D0 * PROCEED? + BEQ.S DUPX2 * YES + CMPI.B #'y',D0 + BEQ.S DUPX2 * YES + + MOVEQ #1,D1 * NO, ABORT (ANY KEY BESIDES 'Y') + MOVE.B #'N',D0 +DUPX2 BSR PUTCHR + BSR PUTNEW * FOLLOW WITH A CR + +DUPX3 MOVE.W D1,D0 * RETURN FLAGS FOR RESULT + RESTREGS + RTS + +* ---------------------- +* GETSFL +* ---------------------- + +* POLL USER FOR A FILE NAME, DRIVE, DIRECTORY, ETC (LEAVE IN GLOBAL) +* GIVEN: +* D0.W = SET IF SAVE, 0 IF RESTORE, +* D1.W = SET IF PARTIAL, 0 IF NORMAL, +* A0 -> XZIP "SUGGESTED" NAME (BYTE 0 IS LEN) +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +GETSFL MOVEM.L D2-D3/A1,-(SP) + MOVE.W D0,D2 * REPOSITION THESE VALS + MOVE.W D1,D3 + + TST.W D3 + BEQ.S GTSFX2 * IF NORMAL, NO SPECIAL NAME + MOVEQ #0,D0 * IF PARTIAL, SUGGEST SPECIAL NAME TO USER +*** MOVEQ #1,D0 + MOVE.B (A0)+,D0 * SRC: LTABLE FORMAT (1ST BYTE IS LEN) +*** ADD.B (A0),D0 + MOVEQ #12+1,D1 * MAX LEN (FOR GENERIC ST/PC DOS) + LEA _savename,A1 * DEST: 'C' FORMAT (ASCIZ) + BSR COPYS + +GTSFX2 SAVEREGS + RESWORD + MOVE.L D2,-(SP) * SAVE/RESTORE + MOVE.L D3,-(SP) * NORMAL/PARTIAL [PASCAL: PASS BOOL @ODD ADDR] + JSR _file_select + FLUSH 8 + POPWORD + RESTREGS + + MOVE.W D0,D1 * FSEL RESULT, NON-ZERO IF CANCEL OR ERROR + BNE.S GTSFX8 + + LEA _savename,A0 * SIMPLE NAME (NO DISK/PATH SPEC) + BSR STRLEN * FIND LEN ('C' FORMAT) + BSR SCRNAM * ECHO NAME TO TRANSCRIPT + + TST.W D2 * WAS THIS A SAVE? + BEQ.S GTSFX8 * NO + BSR DUPNAM * YES, CHECK FOR DUPLICATE FILENAME + MOVE.W D0,D1 * NON-ZERO IF USER SAYS ABORT + +GTSFX8 MOVEM.L (SP)+,D2-D3/A1 + TST.W D1 * FINAL RESULT, RETURN FLAGS + RTS + +* ---------------------- +* NEWSFL +* ---------------------- + +* CREATE (IF NECESSARY) AND OPEN A SAVE FILE, USING GLOBAL FILENAME +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +NEWSFL SAVEREGS + RESWORD + JSR _create_file + POPWORD + RESTREGS + BEQ.S NEWSX2 * ZERO MEANS NO ERROR + +* CMPI.W #-44,D0 * ST: DISK IS WRITE-PROTECTED? (SAY SO) +* CMPI.W #-48,D0 * ST: NAME EXISTS ALREADY? (IGNORE) + + MOVE.W D0,-(SP) + BSR WPRCHK * IF WRITE-PROTECT ERROR, INFORM USER + MOVE.W (SP)+,D0 + +NEWSX2 RTS * RETURN FLAGS + +* ---------------------- +* OPNSFL +* ---------------------- + +* OPEN A (RESTORE) FILE, USING GLOBAL FILENAME, LEAVE CHANNEL IN GLOBAL +* RETURN WITH FLAGS, ZERO IF NO ERROR + +OPNSFL SAVEREGS + RESWORD + JSR _open_file + POPWORD * ZERO MEANS NO ERROR + RESTREGS + RTS + +* ---------------------- +* GTSBKS, SFREAD +* ---------------------- + +* GET A SERIES OF SAVE FILE BLOCKS +* FIRST BLOCK NUMBER IN D0, # OF BLOCKS IN D1, CORE TARGET LOCATION IN A0 +* RETURN WITH FLAGS, NONZERO IF ERROR + +GTSBKS BSR BLKBYT * CONVERT BLOCKS TO BYTES + EXG D1,D0 + BSR BLKBYT + EXG D1,D0 + +* ENTER HERE: BYTE OFFSET IN D0, BYTE LENGTH IN D1 +* RETURN FLAGS, >> ALSO D1 = ACTUAL BYTES READ << + +SFREAD SAVEREGS + RESWORD + MOVE.L A0,-(SP) * BUFFER POINTER + MOVE.L D1,-(SP) * LENGTH IN BYTES + MOVE.L D0,-(SP) * OFFSET IN BYTES + MOVE.L _save_ref,D0 + MOVE.L D0,-(SP) + JSR _read_file + FLUSH 16 + POPWORD + RESTREGS + MOVE.L _actlen,D1 + TST.W D0 * NONZERO MEANS ERROR + RTS + +* ---------------------- +* PTSBKS, SFWRIT +* ---------------------- + +* WRITE A SERIES OF SAVE FILE BLOCKS, +* FIRST BLOCK OFFSET IN D0, NUMBER OF BLOCKS IN D1, CORE LOCATION IN A0, +* RETURN WITH FLAGS, NONZERO IF ERROR + +PTSBKS BSR BLKBYT * CONVERT BLOCKS TO BYTES + EXG D1,D0 + BSR BLKBYT + EXG D1,D0 + +* ENTER HERE: BYTE OFFSET IN D0, BYTE LENGTH IN D1 +* RETURN FLAGS, >> ALSO D1 = ACTUAL BYTES READ << + +SFWRIT SAVEREGS + RESWORD + MOVE.L A0,-(SP) * BUFFER POINTER + MOVE.L D1,-(SP) * LENGTH IN BYTES + MOVE.L D0,-(SP) * OFFSET IN BYTES + MOVE.L _save_ref,D0 + MOVE.L D0,-(SP) + JSR _write_file + FLUSH 16 + POPWORD + RESTREGS + + MOVE.W D0,D1 * ANY ERROR? + BEQ.S PTSBX2 * NO + + CMPI.W #999,D0 * Amiga: DISK-FULL ERROR? + BEQ.S PTSBX1 * YES, INFORM USER + + BSR WPRCHK * ALSO CHECK FOR WRITE-PROTECT ERROR + BRA.S PTSBX2 + +PTSBX1 LEA MSGFUL,A0 + BSR OUTMSG * 'Not enough room on disk.' + + SECTION ZDATA +MSGFUL DC.B 'Not enough room on disk.',0 + SECTION ZCODE + +PTSBX2 MOVE.W D1,D0 + MOVE.L _actlen,D1 * COUNT + TST.W D0 * FLAGS, NONZERO MEANS ERROR + RTS + +* ---------------------- +* WPRCHK +* ---------------------- + +* CHECK FOR DISK WRITE-PROTECT ERROR, GIVEN D0 = RESULT CODE +* (MAY BE CALLED DURING FILE CREATE /OR/ FILE WRITE) + +WPRCHK + CMPI.W #13,D0 * Amiga: WRITE-PROTECT ERROR? + BNE.S WPRCX1 + + LEA MSGWPR,A0 * INFORM USER + BSR OUTMSG * 'Disk is write-protected.' +WPRCX1 RTS + + SECTION ZDATA +MSGWPR DC.B 'Disk is write-protected.',0 + SECTION ZCODE + +* ---------------------- +* CLSSFL +* ---------------------- + +* CLOSE A SAVE FILE, CHANNEL IN GLOBAL +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +CLSSFL SAVEREGS + RESWORD + JSR _close_file + POPWORD * NON-ZERO IF ERROR + RESTREGS + RTS + +* ---------------------- +* DELSFL +* ---------------------- + +* DELETE A BAD SAVE FILE, MUST HAVE BEEN ALREADY CLOSED (OR NOT OPENED) +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +DELSFL SAVEREGS + RESWORD + JSR _delete_file + POPWORD * NON-ZERO IF ERROR + RESTREGS + RTS + +* ---------------------- +* DEFOLD +* ---------------------- + +DEFOLD CLR.W D0 * RETRIEVE PREVIOUS DEFAULT NAMES + BRA DEFNX1 +DEFNEW MOVEQ #1,D0 * UPDATE PREVIOUS DEFAULT NAMES + +DEFNX1 SAVEREGS + MOVE.L D0,-(SP) * [PASCAL: PASS BOOL @ODD ADDR] + JSR _new_default * (COPIES SOME GLOBAL STRINGS) + FLUSH 4 + RESTREGS + RTS + +* ---------------------- +* CHKDSK, CHKDSK1 +* ---------------------- + +* [MAC: THIS CALL ISN'T NEEDED, SINCE THE OS DOES A GOOD JOB OF KEEPING +* TRACK OF WHEN THE GAME DISK HAS BEEN EJECTED, AND ASKING FOR IT WHEN +* NECESSARY.] + +CHKDSK +CHKDSK1 + RTS + +* ASSOCIATE AN ICON WITH A NEWLY-CREATED SAVE FILE + +MAKEICON + SAVEREGS + JSR _make_icon_file + TST.W D0 * IF NON-ZERO, SHOW ERROR MSG + BEQ.S MAKIX1 + + LEA MSGMKI,A0 * (NON-FATAL, SAVE IS STILL GOOD) + BSR OUTMSG + + SECTION ZDATA +MSGMKI DC.B '[No icon]',0 * TERSE (SINCE MAY BE DELIBERATE) + SECTION ZCODE + +MAKIX1 RESTREGS + RTS + +* MAX FILENAME LENGTH (ACTUALLY *+5, ALLOWING FOR ".Info" FILE) + +FNAMELEN EQU 48 * 'C' BUFFER IS 64-80 + +* ALTERNATE FILE-SELECTION ROUTINE (AMIGA -- IGNORES THE STACK PARAMETERS) + +_file_select + SAVEREGS + LEA MSGIN1,A0 * PROMPT FOR A FILENAME + BSR OUTMSG + + LEA MSGIN2,A0 + BSR OUTMSG0 + + LEA _saveback,A0 * ALREADY ASCIZ + BSR OUTMSG0 + + LEA MSGIN3,A0 + BSR OUTMSG0 + BSR PUTLIN * MUST FLUSH BUFFER + + SECTION ZDATA +MSGIN1 DC.B 'Enter a file name.',0 +MSGIN2 DC.B '(Default is "',0 +MSGIN3 DC.B '") >',0 + SECTION ZCODE + +* [READLN] +* [GIVEN A0 -> INPUT BUFFER, D0 = MAX LENGTH, D1 = CURRENT LENGTH] +* [RETURN A0 -> END OF ACTUAL INPUT (+1), D0 = TERM CHAR] + + LEA _savename,A1 * STORE HERE + MOVE.L A1,A0 + MOVEQ #FNAMELEN,D0 * MAX LENGTH OF NAME + CLR.W D1 * BUFFER IS CURRENTLY EMPTY + BSR READLN * COLLECT A RESPONSE + + CMPA.L A0,A1 * ANYTHING? + BEQ.S FSELX1 * ZERO, MEANS USE DEFAULT + + CLR.B (A0) * MAKE THE STRING ASCIZ + BRA.S FSELX2 + +FSELX1 CLR.L -(SP) * COPY _saveback TO _savename + JSR _new_default + FLUSH 4 + +FSELX2 JSR _drive_default * PREFIX WITH DEFAULT DRIVE (IF NONE GIVEN) + RESTREGS + CLR.W D0 * (ALWAYS) RETURN ZERO FOR OKAY + RTS + + + PAGE +* ---------------------------------------------------------------------------- +* 68000 CALLS FROM C (XDEFS REQUIRED) +* ---------------------------------------------------------------------------- + + SECTION ZDATA +ZVARS DC.L 0 * CORRECT A6 STORED HERE, MUST RESTORE IF NEEDED + SECTION ZCODE + +* PROCEDURE OutBufLen (charCount: INTEGER) -- ADJUST MAC FOLDING +* RESET ENDBUF (WHEN NEXT EMPTIED, TO PREVENT BUGS) + +* OUTBUFLEN +* MOVE.L ZVARS,A0 * GET ZIP'S VALUE OF A6 +* MOVE.W 4(SP),CURSIZ +* MOVE.L D0,MACBUF(A0) +* RTS + +* ---------------------------------------------------------------------------- +* FAST MEMORY ROUTINES +* USED FOR ST SCROLLING, ALSO FOR ISAVE/IRESTORE +* ---------------------------------------------------------------------------- + +* THIS ROUTINE PERFORMS A FAST BLOCKMOVE. ASSUMPTIONS ARE: +* () COPY MUST BE FROM HIGH TO LOW MEMORY IF IT OVERLAPS ("SCROLL UP") +* () MAX LENGTH IS 256K (32K x 16), DUE TO USE OF "DBxx" + +MMSRC EQU 8+0 * 8 = 4 (REG) + 4 (RTS) +MMDEST EQU 8+4 +MMLEN EQU 8+8 + +_mov_mem + MOVE.L A1,-(SP) + MOVE.L MMSRC(SP),A0 + MOVE.L MMDEST(SP),A1 + MOVE.L MMLEN(SP),D0 + BEQ.S MMX0 * ZERO LENGTH, EXIT + BSR MOVMEM +MMX0 MOVE.L (SP)+,A1 + RTS + +* ALTERNATE ENTRY POINT (FOR 68K USERS), JUST TAKES ARGS IN REGS +* A0 -> SOURCE, A1 -> DEST, D0.L = LENGTH + +MOVMEM MOVE.L D1,-(SP) + MOVE.W A0,D1 * CHECK FOR ODD-ALIGNED SRC ADDRESS + ANDI.W #1,D1 + BNE.S MMX3 * IF SO, MUST USE SLOWER CODE + MOVE.W A1,D1 * CHECK DEST ADDRESS, TOO + ANDI.W #1,D1 + BNE.S MMX3 + + MOVE.L D0,D1 + ASR.L #4,D1 * DIVIDE BY 16: QUOTIENT HERE + BRA.S MMX2 * ENTER LOOP AT DBRA + +* PHASE 1 COPY -- MAXIMIZE SPEED + +MMX1 MOVE.L (A0)+,(A1)+ * COPY 16 BYTES ("UNROLL" FOUR ITERATIONS) + MOVE.L (A0)+,(A1)+ + MOVE.L (A0)+,(A1)+ + MOVE.L (A0)+,(A1)+ +MMX2 DBRA D1,MMX1 * LOOP (32K IS MAX COUNT) + + ANDI.L #$0F,D0 * DIVIDE BY 16: REMAINDER + BEQ.S MMX5 * FALL THROUGH IF ANYTHING LEFT + +* PHASE 2 COPY -- HANDLE EXTRA BYTES OR ODD CASES + +MMX3 MOVE.B (A0)+,(A1)+ * COPY ONE BYTE + SUBQ.L #1,D0 + BNE.S MMX3 * LOOP (NO MAX COUNT) + +MMX5 MOVE.L (SP)+,D1 * DONE + RTS + + +CMSRC EQU 12+0 * 12 = 8 (REGS) + 4 (RTS) +CMLEN EQU 12+4 + +_clr_mem + MOVEM.L D1/A1,-(SP) + MOVE.L CMLEN(SP),D0 + BEQ.S CMX5 * ZERO, EXIT + MOVE.L CMSRC(SP),A0 + + MOVE.W A0,D1 * CHECK FOR ODD SRC ADDRESS + ANDI.W #1,D1 + BNE.S CMX3 + + MOVE.L D0,D1 + ASR.L #4,D1 * DIVIDE BY 16: QUOTIENT + BRA.S CMX2 * ENTER LOOP AT DBRA + +* PHASE 1 "CLEAR" -- MAXIMIZE SPEED + +CMX1 CLR.L (A0)+ * CLEAR 16 BYTES ("UNROLL" FOUR ITERATIONS) + CLR.L (A0)+ + CLR.L (A0)+ + CLR.L (A0)+ +CMX2 DBRA D1,CMX1 * LOOP (32K IS MAXIMUM COUNT) + + ANDI.L #$0F,D0 * DIVIDE BY 16: REMAINDER + BEQ.S CMX5 * FALL THROUGH IF ANYTHING LEFT + +* PHASE 2 "CLEAR" -- HANDLE EXTRA BYTES OR ODD CASES + +CMX3 CLR.B (A0)+ * CLEAR ONE BYTE + SUBQ.L #1,D0 + BNE.S CMX3 * LOOP (NO MAXIMUM COUNT) + +CMX5 MOVEM.L (SP)+,D1/A1 + RTS diff --git a/amiga/batch/batch.info b/amiga/batch/batch.info new file mode 100644 index 0000000..743ccef --- /dev/null +++ b/amiga/batch/batch.info @@ -0,0 +1,46 @@ + +HOW TO BUILD THE COMMODORE AMIGA ZIP/EZIP (USING BATCH FILES) +-------------------------------------------------------------- + + The Amiga development tools currently run on the micro group's Compaq. + + [] Enter the /EDIT directory + + [] BZA (assemble 68K source) + (make sure flag in source is set for ZIP or EZIP) + + [] BZCNOS (compile C source, two phases) + (make sure flag in batch file is set for ZIP or EZIP) + + [] BZLNOS (link, "No Symbols" -- no debugging info) + + [] BZHEX (hexify the .LD file) + + [] run "READ zipXX serial" on the Amiga + + [] run XTALK on the PC: + + sp 9600 + go local + + send ZIP.HEX + +Possible alternate to last three steps -- [dbb 9/26/86] + + (On Amiga) READ ram:file serial + (On PC) CONVERT < file.ld > AUX (hexify, output directly to port) + + (On Amiga) LIST ram:file + (On PC) DIR file.ld (compare lengths) + +HOW TO CREATE LIST FILES +------------------------ + + [] BZALST (for 68K, creates ZIP.LIS) + + [] BZC + BZOMD AMIGAZIP (for C, creates AMIGAZIP.LIS) + + A problem with BZC is it causes a subsequent link attempt to fail + (error 21, whatever that means). + diff --git a/amiga/batch/bga.bat b/amiga/batch/bga.bat new file mode 100644 index 0000000..640fae1 --- /dev/null +++ b/amiga/batch/bga.bat @@ -0,0 +1 @@ +assem %1.asm -o %1.o diff --git a/amiga/batch/bgc.bat b/amiga/batch/bgc.bat new file mode 100644 index 0000000..5e56648 --- /dev/null +++ b/amiga/batch/bgc.bat @@ -0,0 +1,5 @@ +echo off +echo --- Compile %1.C to .O +echo on +lc1m -d -i\include\ %1 +lc2m -s %1 diff --git a/amiga/batch/bgcnos.bat b/amiga/batch/bgcnos.bat new file mode 100644 index 0000000..7a86990 --- /dev/null +++ b/amiga/batch/bgcnos.bat @@ -0,0 +1,5 @@ +echo off +echo --- Compile %1.C to .O +echo on +lc1m -i\include\ %1 +lc2m %1 diff --git a/amiga/batch/bghex.bat b/amiga/batch/bghex.bat new file mode 100644 index 0000000..aa02631 --- /dev/null +++ b/amiga/batch/bghex.bat @@ -0,0 +1 @@ +convert < %1.ld > %1.hex \ No newline at end of file diff --git a/amiga/batch/bgl.bat b/amiga/batch/bgl.bat new file mode 100644 index 0000000..ccf69dc --- /dev/null +++ b/amiga/batch/bgl.bat @@ -0,0 +1 @@ +alink \lib\lstartup.obj+_main.o+%1.o library=\lib\lc.lib+\lib\amiga.lib to %1.ld diff --git a/amiga/batch/bgl2.bat b/amiga/batch/bgl2.bat new file mode 100644 index 0000000..6212084 --- /dev/null +++ b/amiga/batch/bgl2.bat @@ -0,0 +1 @@ +alink \lib\lstartup.obj+_main.o+%1.o+%2.o library=\lib\lc.lib+\lib\amiga.lib to %1.ld diff --git a/amiga/batch/bgl2nos.bat b/amiga/batch/bgl2nos.bat new file mode 100644 index 0000000..7d4c208 --- /dev/null +++ b/amiga/batch/bgl2nos.bat @@ -0,0 +1 @@ +alink \lib\lstartup.obj+%1.o+%2.o library=\lib\lc.lib+\lib\amiga.lib to %1.ld diff --git a/amiga/batch/bglnos.bat b/amiga/batch/bglnos.bat new file mode 100644 index 0000000..90b050c --- /dev/null +++ b/amiga/batch/bglnos.bat @@ -0,0 +1 @@ +alink \lib\lstartup.obj+%1.o library=\lib\lc.lib+\lib\amiga.lib to %1.ld diff --git a/amiga/batch/bgomd.bat b/amiga/batch/bgomd.bat new file mode 100644 index 0000000..63f2602 --- /dev/null +++ b/amiga/batch/bgomd.bat @@ -0,0 +1 @@ +omd >%1.lis -L3000 %1.o %1.c diff --git a/amiga/batch/bza.bat b/amiga/batch/bza.bat new file mode 100644 index 0000000..a9cab99 --- /dev/null +++ b/amiga/batch/bza.bat @@ -0,0 +1 @@ +assem zip0.asm -o zip.o diff --git a/amiga/batch/bza2.bat b/amiga/batch/bza2.bat new file mode 100644 index 0000000..34b855f --- /dev/null +++ b/amiga/batch/bza2.bat @@ -0,0 +1 @@ +assem 68kzip.asm -o zip.o diff --git a/amiga/batch/bzalst.bat b/amiga/batch/bzalst.bat new file mode 100644 index 0000000..3bdea94 --- /dev/null +++ b/amiga/batch/bzalst.bat @@ -0,0 +1 @@ +assem zip0.asm -o zip.o -l zip.lis diff --git a/amiga/batch/bzc.bat b/amiga/batch/bzc.bat new file mode 100644 index 0000000..0d5e79a --- /dev/null +++ b/amiga/batch/bzc.bat @@ -0,0 +1,8 @@ +echo off +if not exist path.set setpath %0 %1 +del path.set +echo --- Make AMIGAZIP.C to .O +if not %1/==/ goto :Link +lc1m -d -dEZIP=1 -i\include\ AMIGAZIP +lc2m -s AMIGAZIP +:Link diff --git a/amiga/batch/bzcnos_c.bat b/amiga/batch/bzcnos_c.bat new file mode 100644 index 0000000..2fe1eab --- /dev/null +++ b/amiga/batch/bzcnos_c.bat @@ -0,0 +1,8 @@ +echo off +if not exist path.set setpath %0 %1 +del path.set +echo --- Make AMIGAZIP.C to .O +if not %1/==/ goto :Link +lc1m -dEZIP=0 -i\include\ AMIGAZIP +lc2m AMIGAZIP +:Link diff --git a/amiga/batch/bzcnos_e.bat b/amiga/batch/bzcnos_e.bat new file mode 100644 index 0000000..f4cca9a --- /dev/null +++ b/amiga/batch/bzcnos_e.bat @@ -0,0 +1,8 @@ +echo off +if not exist path.set setpath %0 %1 +del path.set +echo --- Make AMIGAZIP.C to .O +if not %1/==/ goto :Link +lc1m -dEZIP=1 -i\include\ AMIGAZIP +lc2m AMIGAZIP +:Link diff --git a/amiga/batch/bzhex.bat b/amiga/batch/bzhex.bat new file mode 100644 index 0000000..160e6ec --- /dev/null +++ b/amiga/batch/bzhex.bat @@ -0,0 +1 @@ +convert < zip.ld > zip.hex \ No newline at end of file diff --git a/amiga/batch/bzl.bat b/amiga/batch/bzl.bat new file mode 100644 index 0000000..c1dcd6c --- /dev/null +++ b/amiga/batch/bzl.bat @@ -0,0 +1 @@ +alink \lib\lstartup.obj+_main.o+amigazip.o+zip.o+sound.o library=\lib\lc.lib+\lib\amiga.lib to zip.ld diff --git a/amiga/batch/bzlnos.bat b/amiga/batch/bzlnos.bat new file mode 100644 index 0000000..80f02e9 --- /dev/null +++ b/amiga/batch/bzlnos.bat @@ -0,0 +1 @@ +alink \lib\lstartup.obj+amigazip.o+zip.o+sound.o library=\lib\lc.lib+\lib\amiga.lib to zip.ld diff --git a/amiga/batch/bzomd.bat b/amiga/batch/bzomd.bat new file mode 100644 index 0000000..e520ebf --- /dev/null +++ b/amiga/batch/bzomd.bat @@ -0,0 +1 @@ +omd68k >%1.lis -L3000 %1.o %1.c diff --git a/amiga/bugfix.asm b/amiga/bugfix.asm new file mode 100644 index 0000000..af303b0 --- /dev/null +++ b/amiga/bugfix.asm @@ -0,0 +1,129 @@ +* ---------------------- +* OPCOPYT +* ---------------------- + +* COPYT (COPY OR CLEAR A TABLE) + +OPCOPYT NOP * ASK FOR ARGBLK [JUST TO FREE UP REGS] + MOVE.L A0,A2 + + MOVE.W ARG1(A2),D0 + CMP.W ARG2(A2),D0 + BEQ CPYTX8 * SAME, EXIT + + MOVE.W ARG3(A2),D1 * CHECK LENGTH: + BEQ CPYTX8 * ZERO, EXIT + BGT.S CPYTX1 * POSITIVE + NEG.W ARG3(A2) * NEGATIVE, MAKE POSITIVE + +CPYTX1 TST.W ARG2(A2) * DEST + BEQ.S CPYTX6 * IF ZERO, SPECIAL CASE + TST.W D1 * WAS LEN NEG? + BLT.S CPYTX4 * IF SO, DO /NOT/ CHECK FOR OVERLAP + +*** MOVE.W ARG1(A2),D0 * SRC + CMP.W ARG2(A2),D0 * ANY "FORWARD OVERLAP"? + BHI.S CPYTX4 * NO + + ADD.W ARG3(A2),D0 * MAYBE, SRC END (+1) + CMP.W ARG2(A2),D0 * ANY "FORWARD OVERLAP"? + BLS.S CPYTX4 * NO + +* "FORWARD OVERLAP" DOES EXIST, DO A REVERSE COPY + +CPYTX2 MOVE.W ARG2(A2),D0 * DEST + ADD.W ARG3(A2),D0 * END (+1) + BSR RELABS * ABSOLUTIZE IT [MUST BE PRELOAD] + MOVE.L A0,A1 + + MOVE.W ARG1(A2),D3 * SRC + ADD.W ARG3(A2),D3 * END (+1) + +CPYTX3 SUBQ.W #1,D3 * [PREDECREMENT] + MOVE.W D3,D0 + BSR BSPLTB * --> D0/D1 = BLK/OFF + + BSR GETBYT * --> D0/D1 = NEW BLK/OFF, D2 = DATA + MOVE.B D2,-(A1) * [PREDECREMENT] + SUBQ.W #1,ARG3(A2) + BNE.S CPYTX3 * LOOP [UNSIGNED TEST] + RTS + +* DO A NORMAL COPY + +CPYTX4 MOVE.W ARG2(A2),D0 * DEST + BSR RELABS * ABSOLUTIZE IT [MUST BE PRELOAD] + MOVE.L A0,A1 + + MOVE.W ARG1(A2),D0 + BSR BSPLTB * --> D0/D1 = BLK/OFF + +CPYTX5 BSR GETBYT * --> D0/D1 = NEW BLK/OFF, D2 = DATA + MOVE.B D2,(A1)+ + SUBQ.W #1,ARG3(A2) + BNE.S CPYTX5 * LOOP [UNSIGNED TEST] + RTS + +* NO DEST, JUST CLEAR THE SOURCE TABLE + +CPYTX6 MOVE.W ARG1(A2),D0 * SRC + BSR RELABS * ABSOLUTIZE IT [MUST BE PRELOAD] +CPYTX7 CLR.B (A0)+ + SUBQ.W #1,ARG3(A2) + BNE.S CPYTX7 * LOOP [UNSIGNED TEST] +CPYTX8 RTS + +* ---------------------- +* OPPRNT +* ---------------------- + +* PRINTT (DISPLAY A TABLE IN BLOCK FORMAT) + +OPPRNT NOP * USE AN ARGUMENT BLOCK + LEA DEFBLK(A6),A1 * DEFAULT ARGBLK + MOVE.W #3,(A1) * 3 ARGS MAX + MOVE.W #1,ARG3(A1) * DEFAULT # LINES = 1 + BSR SETDEF * SET UP DEFAULT + MOVE.L A0,A2 + + TST.W ARG2(A2) + BLE.S PRNTX3 * BAD COL COUNT, EXIT + TST.W ARG3(A2) + BLE.S PRNTX3 * BAD ROW COUNT, EXIT + + BSR PUTLIN * MAKE SURE BUFFER IS EMPTY + BSR GETCURS + MOVE.W D1,A1 * INITIAL CURSOR COLUMN -- SAVE HERE + +* WE NOW USE VIRTUAL MEMORY CALLS TO FETCH TABLE DATA + +PRNTX1 MOVE.W ARG2(A2),D3 * COLS PER ROW + MOVE.W ARG1(A2),D0 * TABLE BASE / START OF CURRENT ROW + BSR BSPLTB * --> D0/D1 = BLK/OFF + +PRNTX2 BSR GETBYT * --> D0/D1 = NEW BLK/OFF, D2 = CHAR + EXG D0,D2 + BSR PUTCHR * QUEUE/SCRIPT CHAR, ETC + EXG D0,D2 + + SUBQ.W #1,D3 * ANY MORE COLS IN THIS ROW? + BGT.S PRNTX2 * YES, LOOP + +* BEFORE, WE SAVED THE CURRENT FONT AND ENABLED FONT1, TO BE SURE THE CR +* WAS CORRECTLY INTERPRETED. BUT (IN OTHER CONTEXTS) IT STILL GOT +* MISINTERPRETED. NOWADAYS, #13 ALWAYS MEANS CR, REGARDLESS OF CONTEXT +* (SEE CharOut). A BETTER SOLUTION WILL REQUIRE SOME STICKY RETHINKING. + + SUBQ.W #1,ARG3(A2) * ANY MORE ROWS IN TABLE? + BEQ.S PRNTX3 * NO, DONE + BSR PUTNEW * YES, CR, SCROLL IF NEEDED [PUTCHR #13] + + MOVEQ #-1,D0 * KEEP CURRENT ROW + MOVE.W A1,D1 * BUT RESET COLUMN TO ORIGINAL VALUE + BSR SETCURS + + MOVE.W ARG2(A2),D0 + ADD.W D0,ARG1(A2) * START OF NEXT LINE + BRA.S PRNTX1 * LOOP +PRNTX3 RTS + diff --git a/amiga/cwd.c b/amiga/cwd.c new file mode 100644 index 0000000..d6007ed --- /dev/null +++ b/amiga/cwd.c @@ -0,0 +1,85 @@ + +/* Find the pathname of the current working directory. Uses a recursive + call to a function named followpath. Its job is to continue to call the + ParentDir function until it obtains a lock value of zero, and to append + (to a global string) the name of the directory it pops into at each step. + In the root directory, the lock gives us the volume name of the disk + (how do we get the drive name instead?). The program appends a colon + after the volume name and a slash after each subdirectory along the way + to the one we're in currently. [Taken from example in Peck p36.] +*/ + +#include "libraries/dos.h" +#include "libraries/dosextens.h" +#include "exec/memory.h" + +extern struct FileLock *Lock(), *ParentDir(); + +char pathname[101]; + +main() /* cwd() */ +{ + struct FileLock *cwdlock; + pathname[0] = 0; /* start with null string */ + + /* get a read lock on the current directory */ + cwdlock = Lock ("", ACCESS_READ); + + if (cwdlock != 0) + followpath (cwdlock, 0); + + /* NOTE: followpath unlocks the lock */ + + printf ("path is %1s\n", pathname); /* if main(), display result */ +} + +int followpath (lock, printslash) +struct FileLock *lock; +int printslash; +{ + struct FileInfoBlock *myinfo; + struct FileLock *newlock; + int success, error; + + /* if we reach the end of the road, just exit */ + if (!lock) return (0); + + /* see if this dir has a parent; might fail because of an I/O error + or bacause somebody took out the disk */ + newlock = ParentDir (lock); + error = IoErr (); + + /* recursively call this same function to follow path up to the root */ + if (!error) + error = followpath (newlock, 1); + + if (!error) { + /* alloc memory AFTER the recursion, to reduce chance of error */ + myinfo = (struct FileInfoBlock *) + AllocMem (sizeof(struct FileInfoBlock), MEMF_CLEAR); + + if (myinfo == 0) error = -1; + else { + success = Examine (lock, myinfo); + + if (!success) error = -1; + else { + strcat (pathname, myinfo->fib_FileName); /* dir name */ + + if (newlock == 0) /* actually vol name */ + strcat (pathname, ":"); + else if (printslash) + strcat (pathname, "/"); + } + + FreeMem (myinfo, sizeof(struct FileInfoBlock)); + } + } + + UnLock (lock); + + if (error) /* make null the global string */ + pathname[0] = 0; + + return (error); /* (zero if ok) */ +} diff --git a/amiga/fileio.c b/amiga/fileio.c new file mode 100644 index 0000000..41201f3 --- /dev/null +++ b/amiga/fileio.c @@ -0,0 +1,3727 @@ + +/* *** main.c *************************************************************** + * + * File IO Suite -- Example Main + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 4 Feb 87 RJ Real release + * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release + * 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2 + * 1 Feb 86 =RJ Mical= Created this file. + * + * *********************************************************************** */ + + +#define FILEIO_SOURCEFILE +#include "fileio.h" + + +BOOL TestFileIO(); + + +struct NewScreen NewFileIOScreen = + { + 0, 0, /* LeftEdge, TopEdge */ + 320, 200, /* Width, Height */ + 2, /* Depth */ + 0, 1, /* Detail/BlockPens */ + NULL, /* ViewPort Modes (must set/clear HIRES as needed) */ + CUSTOMSCREEN, + &SafeFont, /* Font */ + (UBYTE *)"Example FileIO Program's Screen", + NULL, /* Gadgets */ + NULL, /* CustomBitMap */ + }; + +struct NewWindow NewFileIOWindow = + { + 0, 12, /* LeftEdge, TopEdge */ + 320, 150, /* Width, Height */ + -1, -1, /* Detail/BlockPens */ + NEWSIZE | MOUSEBUTTONS | VANILLAKEY | MENUPICK | CLOSEWINDOW + | DISKINSERTED, + /* IDCMP Flags */ + WINDOWSIZING | WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE + | SIZEBRIGHT | SMART_REFRESH | RMBTRAP | ACTIVATE | NOCAREREFRESH, + /* Window Specification Flags */ + NULL, /* FirstGadget */ + NULL, /* Checkmark */ + (UBYTE *)"FileIO Requester Window", /* WindowTitle */ + NULL, /* Screen */ + NULL, /* SuperBitMap */ + 96, 30, /* MinWidth, MinHeight */ + 640, 200, /* MaxWidth, MaxHeight */ + WBENCHSCREEN, + }; + + + +VOID main(argc, argv) +LONG argc; +char **argv; +{ + struct Screen *screen; + struct Window *window; + struct FileIOSupport *fileio1, *fileio2; + BOOL mainswitch, ioswitch, mainsuccess; + LONG class; + struct IntuiMessage *message; + SHORT pick; + + mainsuccess = FALSE; + + screen = NULL; + window = NULL; + fileio1 = fileio2 = NULL; + + IntuitionBase = (struct IntuitionBase *) + OpenLibrary("intuition.library", 0); + GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0); + DosBase = (struct DosLibrary *)OpenLibrary("dos.library", 0); + IconBase = (struct IconBase *)OpenLibrary("icon.library", 0); + + if ( (IntuitionBase == NULL) + || (GfxBase == NULL) + || (DosBase == NULL) + || (IconBase == NULL) ) + goto MAIN_DONE; + + if (argv) + { + /* OK, we started from CLI */ + if (argc > 1) + { + if (screen = OpenScreen(&NewFileIOScreen)) + { + NewFileIOWindow.Screen = screen; + NewFileIOWindow.Type = CUSTOMSCREEN; + } + } + } + + window = OpenWindow(&NewFileIOWindow); + + fileio1 = GetFileIOSupport(); + fileio2 = GetFileIOSupport(); + + if ((window == NULL) || (fileio1 == NULL) || (fileio2 == NULL)) + goto MAIN_DONE; + + SetFlag(fileio2->Flags, WBENCH_MATCH | MATCH_OBJECTTYPE); + fileio2->DiskObjectType = WBTOOL; + fileio2->ReqTitle = (UBYTE *)"- Workbench Tools and Drawers -"; + + SetAPen(window->RPort, 1); + Move(window->RPort, 25, 40); + Text(window->RPort, "= Click for FileIO Requester =", 30); + + mainswitch = TRUE; + pick = 0; + + while (mainswitch) + { + WaitPort(window->UserPort); + + ioswitch = FALSE; + while (message = GetMsg(window->UserPort)) + { + class = message->Class; + ReplyMsg(message); + + switch (class) + { + case CLOSEWINDOW: + mainswitch = FALSE; + break; + case DISKINSERTED: + /* You should clear the GOOD_FILENAMES flag whenever you + * detect that a new disk was inserted. + */ + ClearFlag(fileio1->Flags, GOOD_FILENAMES); + ClearFlag(fileio2->Flags, GOOD_FILENAMES); + + /* While I'm here, I'll demo another feature for you. */ + ToggleFlag(fileio1->Flags, USE_VOLUME_NAMES); + ToggleFlag(fileio2->Flags, USE_VOLUME_NAMES); + + break; + default: + /* If any other event occurs, bring up that old requester! */ + ioswitch = TRUE; + break; + } + } + + if (ioswitch) + { + if (pick == 0) + { + if (TestFileIO(fileio1, window)) + /* Oops, disk swapped, so restart the other */ + ClearFlag(fileio2->Flags, GOOD_FILENAMES); + } + else + { + if (TestFileIO(fileio2, window)) + /* Oops, disk swapped, so restart the other */ + ClearFlag(fileio1->Flags, GOOD_FILENAMES); + } + pick = 1 - pick; + } + } + + mainsuccess = TRUE; + +MAIN_DONE: + if (NOT mainsuccess) Alert(ALERT_NO_MEMORY, NULL); + + if (fileio1) ReleaseFileIO(fileio1); + if (fileio2) ReleaseFileIO(fileio2); + + if (window) CloseWindow(window); + if (screen) CloseScreen(screen); + + if (IntuitionBase) CloseLibrary(IntuitionBase); + if (GfxBase) CloseLibrary(GfxBase); + if (DosBase) CloseLibrary(DosBase); + if (IconBase) CloseLibrary(IconBase); +} + + + +BOOL TestFileIO(fileio, window) +struct FileIOSupport *fileio; +struct Window *window; +/* This guy calls GetFileIOName(), displays the file name selected by the + * user, and returns TRUE if the user swapped disks during GetFileIOName() + * (else returns FALSE) + */ +{ + UBYTE name[80]; + + if (GetFileIOName(fileio, window)) + { + /* If user was positive, display the name */ + CopyString(&name[0], "["); + BuildFileIOPathname(fileio, &name[1]); + ConcatString(&name[0], "]"); + AlertGrunt(&name[0], window); + } + + if (FlagIsSet(fileio->Flags, DISK_HAS_CHANGED)) + { + ClearFlag(fileio->Flags, DISK_HAS_CHANGED); + return(TRUE); + } + else return(FALSE); +} + + +/* *** fileio.c ************************************************************* + * + * File IO Suite -- Primary FileIO Requester Routines + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? Thanks. + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 20 Oct 87 - RJ Added RENAME_RAMDISK to fix what seems to + * be a bug in either AmigaDOS or Workbench. + * 26 Aug 87 RJ Added test for 0 GadgetID at end of + * GetFileIOName() + * 4 Feb 87 RJ Real release + * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release + * 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2 + * 1 Feb 86 =RJ Mical= Created this file. + * + * *********************************************************************** */ + + +#define FILEIO_SOURCEFILE +#include "fileio.h" + + +/* These routines can be found in filesupp.c */ +extern HandleGadget(); +extern StartOpenRequester(); +extern DiskInserted(); +extern PropMouseMoves(); + + + +/* *** GetFileIOSupport() *************************************************** + * + * NAME + * GetFileIOSupport -- Allocate and initialize a FileIOSupport structure + * + * + * SYNOPSIS + * struct FileIOSupport *GetFileIOSupport(); + * + * + * FUNCTION + * Allocates and initializes a FileIOSupport structure for use with + * calls to GetFileIOName(). + * + * You may want to further initialize the structure before calling + * GetFileIOName(). Refer to the FileIO documentation for more + * information. + * + * When you're done with the structure, call ReleaseFileIO(). + * + * + * INPUTS + * None + * + * + * RESULT + * If all goes well, returns the address of a FileIOSupport structure. + * If anything goes wrong (usually out of memory), returns NULL. + * + * + * EXAMPLE + * struct FileIOSupport *fileio; + * fileio = GetFileIOSupport(); + * GetFileIOName(fileio, window); + * ReleaseFileIO(fileio); + * + * + * BUGS + * None known + * + * + * SEE ALSO + * GetFileIOName(), ReleaseFileIO() + */ +struct FileIOSupport *GetFileIOSupport() +{ + struct FileIOSupport *fileio; + + if (fileio = (struct FileIOSupport *)AllocMem( + sizeof(struct FileIOSupport), MEMF_CLEAR)) + { + /* Anything special to initialize? */ + SetFlag(fileio->Flags, USE_VOLUME_NAMES | RENAME_RAMDISK); + } + return(fileio); +} + + + +/* *** GetFileIOName() ****************************************************** + * + * NAME + * GetFileIOName -- Gets a file name for input/output from the user + * + * + * SYNOPSIS + * BOOL GetFileIOName(FileIO, Window); + * + * + * FUNCTION + * This routine creates a filename requester which allows the user + * to browse through the AmigaDOS filesystem and select one of + * the filenames found there. + * + * The FileIO argument is a pointer to a FileIOSupport structure, + * which is allocated and initialized for you via a call to + * GetFileIOSupport(). + * You may preset the FileIO parameters before calling this routine, + * or you may leave them set at their default values. See the FileIO + * documentation for complete details. + * + * The Window argument is the pointer to the window structure returned + * by a call to Intuition's OpenWindow() function. As this routine + * opens a requester and requesters open in windows, you must have + * already opened a window before calling this routine, even if it's + * a window opened for no other purpose than to call this routine. + * + * This routine returns a BOOL value of TRUE or FALSE, depending on + * whether the user chose to accept or cancel the filename selection + * operation. If TRUE, the filename selected by the user can be + * found in the FileIO structure FileName[] field. This filename + * will have all leading and trailing blanks removed (in case the + * user typed in a filename with extraneous spaces). Likewise, + * the pathname to the disk and drawer can be found in the text + * fields DiskName[] and DrawerName[]. You can construct + * the pathname using these text strings. Also, you can call + * BuildFileIOPathname() to build the pathname automatically. + * + * There's a *lot* more to be said about this function. Please + * read the documentation. + * + * NOTE: This routine is not re-entrant. What this means + * is that if you have created a program that has more than one task, + * this routine cannot be called by more than one task at a time. + * This is not a problem for the grand majority of programs. + * But if you have some application that would require calling this + * routine asynchronously from multiple tasks, you'll have to + * implement some quick semaphore arrangement to avoid collisions. + * No big deal, actually. See Exec semaphores for everything you need. + * + * + * INPUTS + * FileIO = pointer to a FileIOSupport structure, as allocated + * via a call to GetFileIOSupport() + * Window = pointer to a Window structure, as created via a call + * to Intuition's OpenWindow() + * + * + * RESULT + * TRUE if the user decided that the filename selection was successful, + * FALSE if the user chose to cancel the operation + * + * + * EXAMPLE + * if (GetFileIOName(fileio, window)) + * ProcessFileName(&fileio->FileName[0]); + * + * + * BUGS + * None known, though there could be some, and the disk selection + * subsystem logic is not perfectly polished (though it's believed + * to be bug-free). + * + * + * SEE ALSO + * BuildFileIOPathname(), GetFileIOSupport(), ReleaseFileIO() + */ +BOOL GetFileIOName(fileio, window) +struct FileIOSupport *fileio; +struct Window *window; +{ + UBYTE *newtext; + + if ((fileio == NULL) || (window == NULL)) return(FALSE); + + OpenSaveLock = CurrentDir(NULL); + CurrentDir(OpenSaveLock); + fileio->DOSLock = OpenSaveLock; + + /* Get easily-accessible copies of the values that are referenced + * most often + */ + OpenReq = &OpenReqSupport.Requester; + OpenReqWindow = OpenReqSupport.Window = window; + OpenReqFileIO = fileio; + + /* Set up the DoRequest() handlers */ + OpenReqSupport.GadgetHandler = HandleGadget; + OpenReqSupport.StartRequest = StartOpenRequester; + OpenReqSupport.NewDiskHandler = DiskInserted; + OpenReqSupport.MouseMoveHandler = PropMouseMoves; + + /* Init the string gadget buffers */ + OpenNameTextInfo.Buffer = &fileio->FileName[0]; + OpenDrawerTextInfo.Buffer = &fileio->DrawerName[0]; + OpenDiskTextInfo.Buffer = &fileio->DiskName[0]; + + /* Initialize the requester title */ + if ((ReqTitleText.IText = fileio->ReqTitle) == NULL) + ReqTitleText.IText = DefaultReqTitle; + ReqTitleText.LeftEdge + = (OPEN_WIDTH - IntuiTextLength(&ReqTitleText)) >> 1; + + /* If this fileio doesn't have valid filenames, + * then refresh the whole thing + */ + if (FlagIsClear(fileio->Flags, GOOD_FILENAMES)) + { + ResetNameText(TRUE); + ResetDrawerText(TRUE); + BuildVolumeTable(fileio); + CopyString(&OpenReqFileIO->DiskName[0], CurrentVolumeName()); + } + + ResetNameText(FALSE); + ResetDrawerText(FALSE); + ResetDiskText(FALSE); + + StuffSelectNames(0); + InitOpenProp(TRUE); + + /* Reset the double-click time variables */ + OpenClickSeconds = OpenClickMicros = 0; + + + /* And now, do that requester. */ + DoRequest(&OpenReqSupport); + /* Back, eh? Wasn't that easy? */ + + + if (FlagIsSet(fileio->Flags, LOCK_GOTTEN)) + { + UnLock(fileio->DOSLock); + ClearFlag(fileio->Flags, LOCK_GOTTEN); + } + + CurrentDir(OpenSaveLock); + OpenReqFileIO = NULL; + + /* Strip any excess leading and trailing blanks off the final name */ + newtext = StripOuterSpace(&fileio->FileName[0], " "); + CopyString(&fileio->FileName[0], newtext); + + if ((OpenReqSupport.SelectedGadgetID) + && (OpenReqSupport.SelectedGadgetID != OPENGADGET_CANCEL)) + return(TRUE); + return(FALSE); +} + + + +/* *** BuildFileIOPathname() ************************************************ + * + * NAME + * BuildFileIOPathname -- Build a file pathname using a FileIO struct + * + * + * SYNOPSIS + * BuildFileIOPathname(FileIOSupport, Buffer); + * + * + * FUNCTION + * Builds the text for a pathname using the FileName[], DrawerName[] and + * DiskName[] fields of the specified FileIOSupport structure + * after the support structure has been used in a successful call + * to GetFileIOName(). Writes the text into the Buffer. + * + * + * INPUTS + * FileIOSupport = the address of a FileIOSupport structure + * Buffer = address of the buffer to receive the file pathname + * + * + * RESULT + * None + * + * + * SEE ALSO + * GetFileIOName() + */ +VOID BuildFileIOPathname(fileio, buffer) +struct FileIOSupport *fileio; +UBYTE *buffer; +{ + StripOuterSpace(&fileio->DiskName[0], " "); + StripOuterSpace(&fileio->DrawerName[0], " "); + StripOuterSpace(&fileio->FileName[0], " "); + + CopyString(buffer, &fileio->DiskName[0]); + if (StringLength(&fileio->DrawerName[0])) + { + ConcatString(buffer, &fileio->DrawerName[0]); + ConcatString(buffer, "/"); + } + ConcatString(buffer, &fileio->FileName[0]); +} + + + +/* *** AddFileIOName() ****************************************************** + * + * NAME + * AddFileIOName -- Add a file name to the names in a FileIOSupport + * + * + * SYNOPSIS + * AddFileIOName(FileIOSupport, FileName); + * + * + * FUNCTION + * This routine adds a file name to the list of file names currently + * in the specified FileIOSupport structure. The next time the + * FileIOSupport structure is used for a call to GetFileIOName(), the + * new file name will apppear alphabetized in with the other file names. + * + * This routine will most often be used after a call to GetFileIOName() + * or some other routine where the user is allowed to specify the name + * of a file to be opened for output. If the file is opened + * successfully, this routine will make sure that the name of the file + * is in the FileIOSupport structure. This is important if the output + * file has been newly created; otherwise, without calling this + * routine, the next time the FileIOSupport structure is used the new + * file name would not appear even though the file exists. If the name + * is already in the list when you call AddFileIOName() then nothing + * happens. This allows you to call AddFileIOName() without worrying + * about duplicate name redundancy. + * + * Here's a typical sequence of events leading up to a call to + * AddFileIOName(): + * + * First, get a FileIOSupport structure: + * fileio = GetFileIOSupport(...); + * + * When the user wants to write data, use GetFileIOName() + * to provide a convenient and consistent interface to + * the filesystem: + * goodfile = GetFileIOName(...); + * + * If the user has selected a name for output (in this example, + * goodfile will equal TRUE if the user selected a name), then + * open the file (possibly creating it) and then call + * AddFileIOName() to make sure the name is in the FileIOSupport + * structure's list: + * if (goodfile) + * { + * UBYTE filename[80]; + * + * BuildFileIOPathname(fileio, &filename[0]); + * ... open filename, write it, close it ... + * if (filename opened successfully) + * AddFileIOName(fileio, &filename[0]); + * } + * + * + * INPUTS + * FileIOSupport = the address of a FileIOSupport structure + * FileName = the address of null-terminated text that is + * either a simple file name or a valid AmigaDOS pathname. + * + * + * RESULT + * None + * + * + * SEE ALSO + * GetFileIOName() + * GetFileIOSupport() + */ +VOID AddFileIOName(fileio, filename) +struct FileIOSupport *fileio; +UBYTE *filename; +{ + SHORT index, i, length; + struct Remember *remember, *oldremember; + UBYTE *nextentry; + struct Remember *namekey; + + /* Does the filename start with a volume name? If so, skip over it */ + index = IndexString(filename, ":"); + if (index >= 0) filename += index + 1; + + /* Does the filename start with a directory name? If so, skip over it */ + do + { + index = IndexString(filename, "/"); + if (index >= 0) filename += index + 1; + } + while (index >= 0); + + if (*filename == 0) return; + + /* Here, filename points to what is presumed to be a valid file name. + * If it's found among the FileIOSupport's names, exit. + * If it's not found in the list, add it. + * + * The current file names are stored in the fileio's Remember list. + */ + remember = fileio->NameKey; + oldremember = NULL; + while (remember) + { + i = CompareUpperStrings(filename, remember->Memory); + if (i < 0) goto ADD_FILENAME; + if (i == 0) return; + oldremember = remember; + remember = remember->NextRemember; + } + +ADD_FILENAME: + /* Name not on list, so add it now */ + length = StringLength(filename); + + namekey = NULL; + if (nextentry = AllocRemember(&namekey, length + 1 + 1, NULL)) + { + CopyString(nextentry, filename); + *(nextentry + length + 1) = 0; + if (oldremember) oldremember->NextRemember = namekey; + else fileio->NameKey = namekey; + /* This assignment is valid whether or not remember is NULL */ + namekey->NextRemember = remember; + fileio->NameCount++; + } +} + + + +/* *** ReleaseFileIO() ****************************************************** + * + * NAME + * ReleaseFileIO -- Release the FileIO structure and all local memory + * + * + * SYNOPSIS + * ReleaseFileIO(FileIO); + * + * + * FUNCTION + * Releases the FileIO structure by freeing all local memory attached + * to the structure and then freeing the structure itself. + * + * + * INPUTS + * FileIO = the address of a FileIO structure + * + * + * RESULT + * None + * + * + * SEE ALSO + * GetFileIOSupport() + */ +VOID ReleaseFileIO(fileio) +struct FileIOSupport *fileio; +{ + if (fileio) + { + FreeRemember(&fileio->VolumeKey, TRUE); + FreeRemember(&fileio->NameKey, TRUE); + FreeMem(fileio, sizeof(struct FileIOSupport)); + } +} + + + +/* *** filesupp.c *********************************************************** + * + * File IO Suite -- Open Requester Routines + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? Thanks. + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 20 Oct 87 - RJ Added RENAME_RAMDISK to fix what seems to + * be a bug in either AmigaDOS or Workbench. + * 27 Sep 87 RJ In order to show the correct DiskName during + * WarmStartFileIO(), that routine now + * refreshes the gadgets both before and after + * the BuildNameTable() process. + * 4 Feb 87 RJ Real release + * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release + * 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2 + * 1 Feb 86 =RJ Mical= Created this file. + * + * *********************************************************************** */ + + +#define FILEIO_SOURCEFILE +#include "fileio.h" + + +/* I think these are silly, but I put them here anyway to avoid compiler + * warnings. + */ +VOID InitOpenProp(); +VOID StuffSelectNames(); + + + +/* ======================================================================= */ +/* === ResetText Routines ================================================ */ +/* ======================================================================= */ + +VOID ResetTextGrunt(info, resetbuffer) +struct StringInfo *info; +BOOL resetbuffer; +/* Reset the string position variables, and reset the buffer itself if + * resetbuffer is TRUE. + */ +{ + info->BufferPos = info->DispPos = 0; + if (resetbuffer) info->Buffer[0] = '\0'; +} + +VOID ResetNameText(resetbuffer) +BOOL resetbuffer; +{ + ResetTextGrunt(&OpenNameTextInfo, resetbuffer); +} + +VOID ResetDrawerText(resetbuffer) +BOOL resetbuffer; +{ + ResetTextGrunt(&OpenDrawerTextInfo, resetbuffer); +} + +VOID ResetDiskText(resetbuffer) +BOOL resetbuffer; +{ + ResetTextGrunt(&OpenDiskTextInfo, resetbuffer); +} + + + +/* ======================================================================= */ +/* === WarmStart Initializer ============================================= */ +/* ======================================================================= */ + +VOID WarmStartFileIO(fileio) +struct FileIOSupport *fileio; +/* This routine establishes a lock on the current disk and drawer, + * resets all of the subsystem control variables, + * gets the file names for the current disk and drawer, + * initializes the proportional gadget, + * and then refreshes the requester. + */ +{ + ULONG lock; + + /* If the fileio already had a lock, release it before proceeding */ + if (FlagIsSet(fileio->Flags, LOCK_GOTTEN)) + { + UnLock(fileio->DOSLock); + ClearFlag(fileio->Flags, LOCK_GOTTEN); + fileio->DOSLock = OpenSaveLock; + CurrentDir(OpenSaveLock); + } + + /* Build the lock name using the current disk and drawer names */ + if (StringLength(&fileio->DiskName[0])) + CopyString(&OpenLockName[0], &fileio->DiskName[0]); + else + CopyString(&OpenLockName[0], CurrentVolumeName()); + + /* If the programmer wants us to sidestep the "RAM DISK:" bug, + * then by all means oblige her or him. + */ + if (FlagIsSet(fileio->Flags, RENAME_RAMDISK) + && CompareUpperStrings(&OpenLockName[0], + "RAM DISK:") == 0) + { + /* Everyone seems suspicious of "RAM Disk:" */ + OpenLockName[3] = ':'; + OpenLockName[4] = '\0'; + } + + ConcatString(&OpenLockName[0], &fileio->DrawerName[0]); + + /* Can we get a lock on this name? */ + if (lock = Lock(&OpenLockName[0], ACCESS_READ)) + { + /* Got it! */ + SetFlag(fileio->Flags, LOCK_GOTTEN); + fileio->DOSLock = lock; + CurrentDir(lock); + } + else + { + /* Hey, bad break, this name just won't do. But the rest of these + * routines need a valid directory, so go back home. + */ + Alert(ALERT_BAD_DIRECTORY, OpenReqWindow); + CopyString(&fileio->DiskName[0], &CurrentDiskString[0]); + ResetDiskText(FALSE); + ResetDrawerText(TRUE); + } + + /* Reset the fileio name selection variables */ + fileio->CurrentPick = -1; + fileio->NameStart = 0; + fileio->NameCount = 0; + + /* Reset the text and gadgets */ + InitOpenProp(TRUE); /* Initialize the prop gadget */ + StuffSelectNames(-1); /* Display all of the names */ + BuildNameTable(OpenReqFileIO); /* Get the file names */ + StuffSelectNames(1); /* Display the file names */ +} + + + +/* ======================================================================= */ +/* === Select Name Routines ============================================== */ +/* ======================================================================= */ + +VOID BlankSelectText(index) +SHORT index; +/* This routine truns the SelectText at index into blanks */ +{ + UBYTE *ptr; + SHORT blanklength; + + ptr = &OpenSelectBuffers[index][0]; + for (blanklength = VISIBLE_SELECT_LENGTH - 1; blanklength; blanklength--) + *ptr++ = ' '; + *ptr = '\0'; + + OpenSelectText[index].FrontPen = 1; + OpenSelectText[index].BackPen = 0; +} + + + +VOID DrawSelectNames() +{ + struct Layer *layer; + + Forbid(); + if (layer = OpenReq->ReqLayer) + if (layer->rp) + PrintIText(layer->rp, + &OpenSelectText[NAME_ENTRY_COUNT - 1], + OPENSELECT_LEFT, OPENSELECT_TOP); + Permit(); +} + + + +VOID StuffSelectNames(refreshcount) +SHORT refreshcount; +/* This routine stuffs the Open Requester's filename gadgets with + * names from the fileio structure, starting from the + * fileio->NameStart name. If the refreshcount is nonzero, the gadgets + * will be refreshed too. + */ +{ + SHORT i, end, bufferpos; + SHORT length, blanklength; + UBYTE *ptr, *ptr2; + struct Remember *remember; + struct Layer *layer; + + if (OpenReqFileIO->NameCount + > OpenReqFileIO->NameStart + NAME_ENTRY_COUNT) + end = OpenReqFileIO->NameStart + NAME_ENTRY_COUNT; + else end = OpenReqFileIO->NameCount; + + bufferpos = 0; + + /* The current file names are stored in the fileio's Remember list */ + remember = OpenReqFileIO->NameKey; + for (i = 0; i < OpenReqFileIO->NameStart; i++) + remember = remember->NextRemember; + + for (i = OpenReqFileIO->NameStart; i < end; i++) + { + ptr = &OpenSelectBuffers[bufferpos][0]; + ptr2 = remember->Memory; + + length = StringLength(ptr2); + if (length >= VISIBLE_SELECT_LENGTH) + length = VISIBLE_SELECT_LENGTH - 1; + blanklength = (VISIBLE_SELECT_LENGTH - 1) - length; + + /* By filling up the IntuiText with blanks after the characters, + * the text, when printed, will overstrike any characters that were + * there before. + */ + for ( ; length; length--) *ptr++ = *ptr2++; + for ( ; blanklength; blanklength--) *ptr++ = ' '; + *ptr = '\0'; + + /* If this is the selected text, then use "highlight" pens */ + if (i == OpenReqFileIO->CurrentPick) + { + OpenSelectText[bufferpos].FrontPen = -2; + OpenSelectText[bufferpos].BackPen = -1; + } + else + { + OpenSelectText[bufferpos].FrontPen = 1; + OpenSelectText[bufferpos].BackPen = 0; + } + + bufferpos++; + remember = remember->NextRemember; + } + + /* Now, for all lines that have no entries, fill with blanks */ + for ( ; bufferpos < NAME_ENTRY_COUNT; bufferpos++) + BlankSelectText(bufferpos); + + /* Finally, redraw the lot */ + if (refreshcount) + { + Forbid(); + if (layer = OpenReq->ReqLayer) + if (layer->rp) + RefreshGList(&OpenSelectNameGadget, OpenReqWindow, OpenReq, + refreshcount); + DrawSelectNames(); + Permit(); + } +} + + + +VOID SetNameStart() +/* This little guy sets the NameStart based on the current + * prop gadget setting. + */ +{ + if (OpenReqFileIO->NameCount <= NAME_ENTRY_COUNT) + OpenReqFileIO->NameStart = 0; + else + OpenReqFileIO->NameStart = (OpenPropInfo.VertPot + * (OpenReqFileIO->NameCount - NAME_ENTRY_COUNT + 1)) >> 16; +} + + + +VOID StripLastDrawer() +/* This guy strips the end drawer reference off of the drawer string, + * which includes nulling out the string if there's only one to strip. + */ +{ + UBYTE *ptr; + SHORT index; + + ptr = OpenDrawerTextInfo.Buffer; + index = IndexString(ptr, "/"); + if (index != -1) + { + /* OK, there's more than one drawer reference, so get the ptr + index + * to the last one. + */ + do + ptr += (index + 1); + while ((index = IndexString(ptr, "/")) != -1); + } + else index = 0; + /* Zammo! */ + *(ptr + index) = '\0'; +} + + + +BOOL DirectoryName() +/* Returns TRUE if the selected name was a directory-type reference + * (up or down), else returns FALSE for a normal filename. + */ +{ + struct Remember *nextentry; + SHORT i; + UBYTE entryflags; + + if (OpenReqFileIO->NameCount) + { + /* Find the selected entry in the key list */ + nextentry = OpenReqFileIO->NameKey; + for (i = OpenReqFileIO->CurrentPick; i > 0; i--) + nextentry = nextentry->NextRemember; + i = StringLength(nextentry->Memory) + 1; + entryflags = *(nextentry->Memory + i); + + if (FlagIsSet(entryflags, NAMED_DIRECTORY | NAMED_PREVIOUS)) + return(TRUE); + + /* else just a normal file name was selected, so fall out to ... */ + } + return(FALSE); +} + + + +VOID StuffFileName() +/* If the selected name is a normal filename, stuffs the filename into the + * Name gadget. If the selected name is a directory reference, + * adjusts the drawer gadget accordingly. + * Returns TRUE if the selected name was a directory-type reference + * (up or down), else returns FALSE for a normal filename. + */ +{ + struct Remember *nextentry; + SHORT i; + UBYTE entryflags; + + if (OpenReqFileIO->NameCount) + { + /* Find the selected entry in the key list */ + nextentry = OpenReqFileIO->NameKey; + for (i = OpenReqFileIO->CurrentPick; i; i--) + nextentry = nextentry->NextRemember; + i = StringLength(nextentry->Memory) + 1; + entryflags = *(nextentry->Memory + i); + + if (FlagIsSet(entryflags, NAMED_DIRECTORY)) + { + /* If there's already a drawer reference, build a proper + * extension before adding the new to the end. + */ + if (StringLength(OpenDrawerTextInfo.Buffer)) + ConcatString(OpenDrawerTextInfo.Buffer, "/"); + + ConcatString(OpenDrawerTextInfo.Buffer, + nextentry->Memory + DIR_TEXT_SIZE); + + ResetDrawerText(FALSE); + ResetNameText(TRUE); + } + else if (FlagIsSet(entryflags, NAMED_PREVIOUS)) + { + /* Remove the last drawer reference */ + StripLastDrawer(); + ResetDrawerText(FALSE); + ResetNameText(TRUE); + } + else + { + /* Just a normal old file name was selected */ + CopyString(OpenNameTextInfo.Buffer, nextentry->Memory); + ResetNameText(FALSE); + } + } +} + + + +/* ======================================================================= */ +/* === Proportional Gadget Routines ====================================== */ +/* ======================================================================= */ + +VOID SetOpenPropPot(resetpos) +BOOL resetpos; +/* This routine resets the vertical pot of the proportional gadget + * with respect to the current number of displayable file names. + */ +{ + LONG slack, result; + + slack = OpenReqFileIO->NameCount - NAME_ENTRY_COUNT; + + if (slack > 0) + { + result = ((LONG)OpenReqFileIO->NameStart << 16) / slack; + if (result > 0xFFFF) result = 0xFFFF; + OpenPropInfo.VertPot = result; + } + else + OpenPropInfo.VertPot = 0; + + if (resetpos) OpenPropImage.TopEdge = 0; +} + + + +VOID InitOpenProp(resetpos) +BOOL resetpos; +/* This routine initializes the variable imagery of the proportional + * gadget and then initializes the gadget's vertical pot. + * The BOOL arg resetpos describes whether you want the call to + * SetOpenPropPot() to reset the prop's knob position. + */ +{ + LONG namecount, height; + SHORT i, i2; + + namecount = OpenReqFileIO->NameCount; + + if (namecount <= NAME_ENTRY_COUNT) + { + OpenPropInfo.VertBody = 0xFFFF; + ClearFlag(OpenPropInfo.Flags, FREEVERT); + height = OPENPROP_MAXHEIGHT; + } + else + { + OpenPropInfo.VertBody = ((LONG)NAME_ENTRY_COUNT << 16) / namecount; + SetFlag(OpenPropInfo.Flags, FREEVERT); + height = (OPENPROP_MAXHEIGHT * NAME_ENTRY_COUNT) / namecount; + if (height < OPENPROP_MINHEIGHT) height = OPENPROP_MINHEIGHT; + } + + OpenPropImage.Height = height; + for (i = 0; i < OPENPROP_TOPHEIGHT; i++) + { + OpenPropData[i] = OpenPropTop[i]; + OpenPropData[i + height] = OpenPropTop[i + OPENPROP_TOPHEIGHT]; + } + + for (i = OPENPROP_TOPHEIGHT; i < height - OPENPROP_BOTTOMHEIGHT; i++) + { + OpenPropData[i] = OpenPropBottom[0]; + OpenPropData[i + height] = OpenPropBottom[OPENPROP_BOTTOMHEIGHT]; + } + + i2 = 0; + for (i = height - OPENPROP_BOTTOMHEIGHT; i < height; i++) + { + OpenPropData[i] = OpenPropBottom[i2]; + OpenPropData[i + height] = OpenPropBottom[i2 + OPENPROP_BOTTOMHEIGHT]; + i2++; + } + + SetOpenPropPot(resetpos); +} + + + + +/* ======================================================================= */ +/* === Requester Handler Routines ======================================== */ +/* ======================================================================= */ + +VOID StartOpenRequester() +/* Called after the requester has been opened. */ +{ + ActivateGadget(&OpenNameTextGadget, OpenReqWindow, OpenReq); + + if (FlagIsClear(OpenReqFileIO->Flags, GOOD_FILENAMES)) + WarmStartFileIO(OpenReqFileIO); + else DrawSelectNames(); +} + + + +SHORT HandleSelect(y, seconds, micros) +SHORT y; +LONG seconds, micros; +/* This routine accepts that a GADGETDOWN occured at the given + * pointer y offset. This is translated into the ordinal number of the + * filename selected by the user, and this is assigned to the + * CurrentPick variable of the OpenReqFileIO structure. + * Returns: + * 1 = DirectoryName() returned TRUE (selection was directory name) + * 0 = new name selected, DirectoryName() returned FALSE (normal name) + * -1 = same name selected, double-clicked + * -2 = same name selected, not double-clicked + */ +{ + SHORT returnvalue, oldy; + LONG oldseconds, oldmicros; + + y -= (OpenReq->TopEdge + OPENSELECT_TOP); + y = y / OPEN_LINEHEIGHT; + y += OpenReqFileIO->NameStart; + if (y >= OpenReqFileIO->NameCount) + y = OpenReqFileIO->NameCount - 1; + + oldseconds = OpenClickSeconds; + oldmicros = OpenClickMicros; + OpenClickSeconds = seconds; + OpenClickMicros = micros; + + oldy = OpenReqFileIO->CurrentPick; + OpenReqFileIO->CurrentPick = y; + + if (DirectoryName()) + { + returnvalue = 1; + } + else + { + if (y == oldy) + { + /* User has selected the same name again. + * Was it done quickly enough to count as a + * double-click selection? + */ + if (FlagIsClear(OpenReqFileIO->Flags, DOUBLECLICK_OFF) + && DoubleClick(oldseconds, oldmicros, + OpenClickSeconds, OpenClickMicros)) + returnvalue = -1; + else returnvalue = -2; + } + else + { + /* Do this work, what there is of it, only if the user + * hasn't reselected an already-selected name. + */ + returnvalue = 0; + } + } + + return(returnvalue); +} + + + +LONG HandleGadget(gadget, x, y, seconds, micros) +struct Gadget *gadget; +SHORT x, y; +LONG seconds, micros; +/* This routine handles one gadget selection */ +{ + BOOL softbuild, hardbuild; + SHORT count; + LONG returnvalue; + + /* softbuild causes the file names to be refreshed. + * hardbuild causes the entire requester to be reestablished. + * either or both can be set. + */ + softbuild = hardbuild = FALSE; + + /* count refers to the count that will be sent to StuffSelectNames(). + * The default is 2, as you can see. + */ + count = 2; + + /* If the selection of any gadget causes us to want the requester to + * go away, set the returnvalue non-zero. + */ + returnvalue = 0; + + switch (gadget->GadgetID) + { + case OPENGADGET_SELECTNAME: + if (OpenReqFileIO->NameCount) + { + /* So our big name gadget was selected, eh? Well, which one + * was the user really pointing at? + */ + y = HandleSelect(y, seconds, micros); + if (y < 0) + { + /* The user has reselected the old name */ + if (y == -1) returnvalue = -1; + } + else + { + /* The user has selected a new name */ + StuffFileName(); + softbuild = TRUE; + if (y == 1) hardbuild = TRUE; + count = 5; + } + } + break; + case OPENGADGET_UPGADGET: + if (OpenReqFileIO->NameStart) + { + OpenReqFileIO->NameStart--; + softbuild = TRUE; + } + break; + case OPENGADGET_DOWNGADGET: + if (OpenReqFileIO->NameStart + NAME_ENTRY_COUNT + < OpenReqFileIO->NameCount) + { + OpenReqFileIO->NameStart++; + softbuild = TRUE; + } + break; + case OPENGADGET_PROPGADGET: + if (OpenReqFileIO->NameCount > NAME_ENTRY_COUNT) + { + SetNameStart(); + softbuild = TRUE; + } + break; + case OPENGADGET_NEXTDISK: + /* Next disk! Wholly mackerel! First, if no "next" then split */ + if (OpenReqFileIO->VolumeCount <= 1) break; + + OpenReqFileIO->VolumeIndex++; + if (OpenReqFileIO->VolumeIndex >= OpenReqFileIO->VolumeCount) + OpenReqFileIO->VolumeIndex = 0; + CopyString(&OpenReqFileIO->DiskName[0], CurrentVolumeName()); + ResetDiskText(FALSE); + ResetDrawerText(TRUE); + + /* Refresh the display so the user can see what's been done, as + * well as having the display refreshed all over again (hardbuild) + * below after the new filenames are retrieved. + */ + softbuild = TRUE; + count = 5; + + /* Intentionally fall into DRAWER/DISKTEXT */ + + case OPENGADGET_DRAWERTEXT: + case OPENGADGET_DISKTEXT: + ResetNameText(TRUE); + hardbuild = TRUE; + break; + default: + break; + } + + /* These are split intentionally, because setters of hardbuild might + * want a softbuild done first, to show why a hardbuild is being done! + */ + if (hardbuild) SetWaitPointer(OpenReqWindow); + if (softbuild) + { + SetOpenPropPot(); + StuffSelectNames(count); + } + if (hardbuild) + WarmStartFileIO(OpenReqFileIO); /* Restart the lock etc. */ + + return(returnvalue); +} + + + +VOID DiskInserted() +/* This routine is called by the RequesterSupport code whenever a new disk + * has been inserted. This allows the user to swap disks while the + * requester is displayed. Unfortunately, I have no way of knowing which + * disk swapped, so I have to restart the requester more or less. + * Not too bad, but a little unpleasant. + */ +{ + SetWaitPointer(OpenReqWindow); + SetFlag(OpenReqFileIO->Flags, DISK_HAS_CHANGED); + BuildVolumeTable(OpenReqFileIO); + CopyString(&OpenReqFileIO->DiskName[0], CurrentVolumeName()); + WarmStartFileIO(OpenReqFileIO); +} + + + +VOID PropMouseMoves() +/* This routine is called by RequesterSupport whenever the mouse moves + * while a FOLLOWMOUSE gadget is set. The only FOLLOWMOUSE gadget is + * the prop gadget, so... + */ +{ + /* ... if there's more names than the number of visible names, + * then reset the name start and redisplay the names. + */ + if (OpenReqFileIO->NameCount > NAME_ENTRY_COUNT) + { + SetNameStart(); + StuffSelectNames(2); + } +} + + +/* *** opendata.c *********************************************************** + * + * File IO Suite -- Open Requester Data + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? Thanks. + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 18 Aug 87 RJ Removed SELECTED from most string gadgets + * 18 Aug 87 RJ Added KeyHandler field to ReqSupport + * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release + * 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2 + * 1 Feb 86 =RJ Mical= Created this file. + * + * *********************************************************************** */ + + +#define FILEIO_SOURCEFILE +#include "fileio.h" + + + + +struct TextAttr SafeFont = + { + (UBYTE *)"topaz.font", + TOPAZ_EIGHTY, + 0, + 0, + }; + + + +/* This is where the Select text is kept! This array of text will be + * redrawn every time we want Intuition to redraw the lowly SelectGadget. + * The strings themselves are kept in OpenSelectBuffers where + * the open routines make sure that the buffers are padded with + * blanks and are always null-terminated. Ha ha! Like madmen + * dancing, like crazy monkeys. + */ +UBYTE OpenSelectBuffers[NAME_ENTRY_COUNT][VISIBLE_SELECT_LENGTH]; +struct IntuiText OpenSelectText[NAME_ENTRY_COUNT] = + { + { + 1, 0, + JAM2, + 1, 1 + (OPEN_LINEHEIGHT * 0), + &SafeFont, + &OpenSelectBuffers[0][0], + NULL, + }, + + { + 1, 0, + JAM2, + 1, 1 + (OPEN_LINEHEIGHT * 1), + &SafeFont, + &OpenSelectBuffers[1][0], + &OpenSelectText[0], + }, + + { + 1, 0, + JAM2, + 1, 1 + (OPEN_LINEHEIGHT * 2), + &SafeFont, + &OpenSelectBuffers[2][0], + &OpenSelectText[1], + }, + + { + 1, 0, + JAM2, + 1, 1 + (OPEN_LINEHEIGHT * 3), + &SafeFont, + &OpenSelectBuffers[3][0], + &OpenSelectText[2], + }, + + { + 1, 0, + JAM2, + 1, 1 + (OPEN_LINEHEIGHT * 4), + &SafeFont, + &OpenSelectBuffers[4][0], + &OpenSelectText[3], + }, + + { + 1, 0, + JAM2, + 1, 1 + (OPEN_LINEHEIGHT * 5), + &SafeFont, + &OpenSelectBuffers[5][0], + &OpenSelectText[4], + }, + + }; + + + + +/* === Backdrop Gadget =================================================== */ +/* We shouldn't need this gadget. It's sole purpose is to allow the user + * to cancel the filename building operation by clicking outside any of + * the regular requester gadgets. Why, we may ask, don't we just make + * the requester a NOISYREQ and detect SELECTDOWN. Well, we tried that, + * and either there's something wrong with our brains or 1.2 Intuition has + * a bug that doesn't broadcast SELECTDOWN to requester listeners. + * It broadcasts SELECTUP, MENUDOWN and MENUUP jes' fine, but no DOWN. + * Bummer. So anyway, now we got an imageless, highlightless gadget that + * fills up the entire requester but, being at the back of the list, won't + * be hit unless all other gadgets are missed. + * Having a wonderful time, wish you were here. + */ +struct Gadget BackdropGadget = + { + NULL, + 0, 0, + OPEN_WIDTH, OPEN_HEIGHT, + GADGHNONE, /* Flags */ + GADGIMMEDIATE, /* Activation */ + REQGADGET | BOOLGADGET, /* Type */ + NULL, /* GadgetRender */ + NULL, /* SelectRender */ + NULL, + NULL, NULL, + OPENGADGET_BACKDROP, + NULL, + }; + + + +/* === OK, Cancel, and NextDisk Gadgets ================================== */ +SHORT BoolCluster3Pairs[] = + { + 0, -3, + 55, -3, + 57, -1, + 57, 19, + 55, 21, + -1, 21, + -3, 19, + -3, -1, + -1, -3, + }; + +SHORT BoolCluster2Pairs[] = + { + -2, -1, + 56, -1, + 56, 19, + -2, 19, + -2, -1, + }; + +SHORT BoolClusterPairs[] = + { + -1, -2, + 55, -2, + 55, 20, + -1, 20, + -1, -2, + }; + +struct Border BoolCluster3Border = + { + 1, 1, + 2, 0, + JAM1, + 9, + &BoolCluster3Pairs[0], + NULL, + }; + +struct Border BoolCluster2Border = + { + 1, 1, + 1, 0, + JAM1, + 5, + &BoolCluster2Pairs[0], + &BoolCluster3Border, + }; + +struct Border BoolClusterBorder = + { + 1, 1, + 1, 0, + JAM1, + 5, + &BoolClusterPairs[0], + &BoolCluster2Border, + }; + +struct IntuiText NextDisk2Text = + { + 1, 0, + JAM2, + 13, 11, + &SafeFont, + (UBYTE *)"DISK", + NULL, + }; + +struct IntuiText NextDiskText = + { + 1, 0, + JAM2, + 13, 3, + &SafeFont, + (UBYTE *)"NEXT", + &NextDisk2Text, + }; + +struct IntuiText CancelText = + { + 1, 0, + JAM2, + 5, 7, + &SafeFont, + (UBYTE *)"CANCEL", + NULL, + }; + +struct IntuiText OK2Text = + { + 1, 0, + JAM2, + 17, 7, + &SafeFont, + (UBYTE *)"OK!", + NULL, + }; + + +struct Gadget NextDiskGadget = + { + &BackdropGadget, + 197, 82 + REQTITLE_HEIGHT, + 57, 21, + GADGHCOMP, /* Flags */ + RELVERIFY, /* Activation */ + REQGADGET | BOOLGADGET, /* Type */ + (APTR)&BoolClusterBorder, /* GadgetRender */ + NULL, /* SelectRender */ + &NextDiskText, + NULL, NULL, + OPENGADGET_NEXTDISK, + NULL, + }; + +struct Gadget CancelGadget = + { + &NextDiskGadget, + 114, 82 + REQTITLE_HEIGHT, + 57, 21, + GADGHCOMP, /* Flags */ + RELVERIFY | ENDGADGET, /* Activation */ + REQGADGET | BOOLGADGET, /* Type */ + (APTR)&BoolClusterBorder, /* GadgetRender */ + NULL, /* SelectRender */ + &CancelText, + NULL, NULL, + OPENGADGET_CANCEL, + NULL, + }; + +struct Gadget OKGadget = + { + &CancelGadget, + 32, 82 + REQTITLE_HEIGHT, + 57, 21, + GADGHCOMP, /* Flags */ + RELVERIFY | ENDGADGET, /* Activation */ + REQGADGET | BOOLGADGET, /* Type */ + (APTR)&BoolClusterBorder, + NULL, /* Renders */ + &OK2Text, + NULL, NULL, + OPENGADGET_OK, + NULL, + }; + + + +/* === OpenUp ============================================================= */ + +struct Image OpenUpImage = + { + 1, -1, + 15, 14, + 2, + &OpenUpData[0], + 0x03, 0x00, + NULL, + }; + +struct Gadget OpenUpGadget = + { + &OKGadget, + 134, 14 + REQTITLE_HEIGHT, + 15, 12, + GADGIMAGE | GADGHNONE, /* Flags */ + GADGIMMEDIATE, /* Activation */ + REQGADGET | BOOLGADGET, /* Type */ + (APTR)&OpenUpImage, + NULL, /* Renders */ + NULL, + NULL, NULL, + OPENGADGET_UPGADGET, + NULL, + }; + + + +/* === OpenDown =========================================================== */ + +struct Image OpenDownImage = + { + 1, -1, + 15, 14, + 2, + &OpenDownData[0], + 0x03, 0x00, + NULL, + }; + +struct Gadget OpenDownGadget = + { + &OpenUpGadget, + 134, 64 + REQTITLE_HEIGHT, + 15, 12, + GADGIMAGE | GADGHNONE, /* Flags */ + GADGIMMEDIATE, /* Activation */ + REQGADGET | BOOLGADGET, /* Type */ + (APTR)&OpenDownImage, + NULL, /* Renders */ + NULL, + NULL, NULL, + OPENGADGET_DOWNGADGET, + NULL, + }; + + +/* === OpenDrawerText ==================================================== */ + +struct StringInfo OpenDrawerTextInfo = + { + NULL, /* Must be supplied from the appropriate FileIOSupport structure */ + &OpenUndoBuffer[0], + 0, + MAX_NAME_LENGTH, + 0, + 0,0,0,0,0,0,0,0, + }; + +struct Gadget OpenDrawerTextGadget = + { + &OpenDownGadget, + 157, 41 + REQTITLE_HEIGHT, + 122, 10, + GADGHCOMP, /* Flags */ + RELVERIFY | STRINGCENTER, /* Activation */ + REQGADGET | STRGADGET, /* Type */ + NULL, NULL, /* Renders */ + NULL, + NULL, + (APTR)&OpenDrawerTextInfo, + OPENGADGET_DRAWERTEXT, + NULL, + }; + + +/* === OpenDiskText ====================================================== */ + +struct StringInfo OpenDiskTextInfo = + { + NULL, /* Must be supplied from the appropriate FileIOSupport structure */ + &OpenUndoBuffer[0], + 0, + MAX_NAME_LENGTH, + 0, + 0,0,0,0,0,0,0,0, + }; + +struct Gadget OpenDiskTextGadget = + { + &OpenDrawerTextGadget, + 157, 65 + REQTITLE_HEIGHT, + 122, 10, + GADGHCOMP, /* Flags */ + RELVERIFY | STRINGCENTER, /* Activation */ + REQGADGET | STRGADGET, /* Type */ + NULL, NULL, /* Renders */ + NULL, + NULL, + (APTR)&OpenDiskTextInfo, + OPENGADGET_DISKTEXT, + NULL, + }; + + + +/* === OpenNameText ====================================================== */ + +struct StringInfo OpenNameTextInfo = + { + NULL, /* Must be supplied from the appropriate FileIOSupport structure */ + &OpenUndoBuffer[0], + 0, + MAX_NAME_LENGTH, + 0, + 0,0,0,0,0,0,0,0, + }; + +struct Gadget OpenNameTextGadget = + { + &OpenDiskTextGadget, + 157, 16 + REQTITLE_HEIGHT, + 122, 10, + GADGHCOMP | SELECTED, /* Flags */ + RELVERIFY | ENDGADGET | STRINGCENTER, /* Activation */ + REQGADGET | STRGADGET, /* Type */ + NULL, NULL, /* Renders */ + NULL, + NULL, + (APTR)&OpenNameTextInfo, + OPENGADGET_NAMETEXT, + NULL, + }; + + +/* === OpenProp =========================================================== */ +/* OpenPropData[] is in chipdata.c */ + +struct Image OpenPropImage = + { + 1, 0, + 11, 8, + 2, + &OpenPropData[0], + 0x03, 0x00, + NULL, + }; + +struct PropInfo OpenPropInfo = + { + FREEVERT | PROPBORDERLESS, + 0, 0, /* Pots should be reinitialized on the fly */ + 0, 0, /* Bodies should be reinitialized on the fly */ + 0, 0, 0, 0, 0, 0, + }; + +struct Gadget OpenPropGadget = + { + &OpenNameTextGadget, + 136, 30 + REQTITLE_HEIGHT, /* Left, Top */ + 13, 30, /* Width, Height */ + GADGIMAGE | GADGHNONE, /* Flags */ + GADGIMMEDIATE | RELVERIFY | FOLLOWMOUSE, /* Activation */ + REQGADGET | PROPGADGET, /* Type */ + (APTR)&OpenPropImage, + NULL, /* Renders */ + NULL, + NULL, + (APTR)&OpenPropInfo, + OPENGADGET_PROPGADGET, + NULL, + }; + + + + + +/* === OpenSelectName ==================================================== */ + +struct Gadget OpenSelectNameGadget = + { + &OpenPropGadget, + OPENSELECT_LEFT, OPENSELECT_TOP, /* Left, Top */ + OPENSELECT_WIDTH, OPENSELECT_HEIGHT, /* Width, Height */ + GADGHNONE, /* Flags */ + GADGIMMEDIATE, /* Activation */ + REQGADGET | BOOLGADGET, /* Type */ + NULL, NULL, /* Renders */ + NULL, /* Text */ + NULL, NULL, + OPENGADGET_SELECTNAME, + NULL, + }; + + + +/* === Requester Details ================================================= */ +/* This data is used to render the requester more prettily. */ + +/* === Line Pairs === */ +SHORT Req3BorderData[] = + { + 1, 0, + OPEN_WIDTH - 2, 0, + OPEN_WIDTH - 2, 1, + OPEN_WIDTH - 1, 1, + OPEN_WIDTH - 1, 108 + REQTITLE_HEIGHT, + OPEN_WIDTH - 2, 108 + REQTITLE_HEIGHT, + OPEN_WIDTH - 2, 109 + REQTITLE_HEIGHT, + 1, 109 + REQTITLE_HEIGHT, + 1, 108 + REQTITLE_HEIGHT, + 0, 108 + REQTITLE_HEIGHT, + 0, 1, + 1, 1, + 1, 0, + }; + +SHORT Req2BorderData[] = + { + 1 + 1, 0 + 1, + OPEN_WIDTH - 2 - 1, 0 + 1, + OPEN_WIDTH - 2 - 1, 1 + 1, + OPEN_WIDTH - 1 - 1, 1 + 1, + OPEN_WIDTH - 1 - 1, 108 - 1 + REQTITLE_HEIGHT, + OPEN_WIDTH - 2 - 1, 108 - 1 + REQTITLE_HEIGHT, + OPEN_WIDTH - 2 - 1, 109 - 1 + REQTITLE_HEIGHT, + 1 + 1, 109 - 1 + REQTITLE_HEIGHT, + 1 + 1, 108 - 1 + REQTITLE_HEIGHT, + 0 + 1, 108 - 1 + REQTITLE_HEIGHT, + 0 + 1, 1 + 1, + 1 + 1, 1 + 1, + 1 + 1, 0 + 1, + }; + +SHORT ReqBorderData[] = + { + 1 + 2, 0 + 2, + OPEN_WIDTH - 2 - 2, 0 + 2, + OPEN_WIDTH - 2 - 2, 1 + 2, + OPEN_WIDTH - 1 - 2, 1 + 2, + OPEN_WIDTH - 1 - 2, 108 - 2 + REQTITLE_HEIGHT, + OPEN_WIDTH - 2 - 2, 108 - 2 + REQTITLE_HEIGHT, + OPEN_WIDTH - 2 - 2, 109 - 2 + REQTITLE_HEIGHT, + 1 + 2, 109 - 2 + REQTITLE_HEIGHT, + 1 + 2, 108 - 2 + REQTITLE_HEIGHT, + 0 + 2, 108 - 2 + REQTITLE_HEIGHT, + 0 + 2, 1 + 2, + 1 + 2, 1 + 2, + 1 + 2, 0 + 2, + }; + +SHORT SelectBorderData[] = + { + 8, 14 + REQTITLE_HEIGHT, + 129, 14 + REQTITLE_HEIGHT, + 130, 15 + REQTITLE_HEIGHT, + 130, 74 + REQTITLE_HEIGHT, + 129, 75 + REQTITLE_HEIGHT, + 8, 75 + REQTITLE_HEIGHT, + 7, 74 + REQTITLE_HEIGHT, + 7, 15 + REQTITLE_HEIGHT, + 8, 14 + REQTITLE_HEIGHT, + }; + +SHORT TextBorderData[] = + { + -1, -2, + 120, -2, + 121, -1, + 121, 8, + 120, 9, + -1, 9, + -2, 8, + -2, -1, + -1, -2, + }; + +SHORT PropBorderData[] = + { + 0, -3, + 16, -3, + 16, 32, + 0, 32, + 0, -2, + 15, -2, + 15, -1, + 17, -1, + 17, 30, + 15, 30, + 15, 31, + 1, 31, + 1, 30, + -1, 30, + -1, -1, + -1, 1, + }; + + +/* === Borders === */ +struct Border Req3Border = + { + 0, 0, + 1, 0, + JAM1, + 13, + &Req3BorderData[0], + NULL, + }; + +struct Border Req2Border = + { + 0, 0, + 2, 0, + JAM1, + 13, + &Req2BorderData[0], + &Req3Border, + }; + +struct Border ReqBorder = + { + 0, 0, + 1, 0, + JAM1, + 13, + &ReqBorderData[0], + &Req2Border, + }; + +struct Border SelectBorder = + { + 0, 0, + 1, 0, + JAM1, + 9, + &SelectBorderData[0], + &ReqBorder, + }; + +struct Border Text3Border = + { + 157, 65 + REQTITLE_HEIGHT, + 1, 0, + JAM1, + 9, + &TextBorderData[0], + &SelectBorder, + }; + +struct Border Text2Border = + { + 157, 41 + REQTITLE_HEIGHT, + 1, 0, + JAM1, + 9, + &TextBorderData[0], + &Text3Border, + }; + +struct Border TextBorder = + { + 157, 16 + REQTITLE_HEIGHT, + 1, 0, + JAM1, + 9, + &TextBorderData[0], + &Text2Border, + }; + +struct Border PropBorder = + { + 134, 30 + REQTITLE_HEIGHT, + 1, 0, + JAM1, + 16, + &PropBorderData[0], + &TextBorder, + }; + +/* === RJ wants to know: Some Requester Text For You? === */ +UBYTE *DefaultReqTitle = (UBYTE *)"File IO Requester"; +struct IntuiText ReqTitleText = + { + 1, 0, + JAM2, + 0, 5, /* The x-coordinate is initialized to center the title */ + &SafeFont, + NULL, /* Points to the title supplied in the FileIOSupport */ + NULL, + }; + +struct IntuiText SelectText = + { + 1, 0, + JAM2, + 18, 6 + REQTITLE_HEIGHT, + &SafeFont, + (UBYTE *)"Select a Name", + &ReqTitleText, + }; + +struct IntuiText Type3Text = + { + 1, 0, + JAM2, + 201, 55 + REQTITLE_HEIGHT, + &SafeFont, + (UBYTE *)"Disk", + &SelectText, + }; + +struct IntuiText Type2Text = + { + 1, 0, + JAM2, + 193, 31 + REQTITLE_HEIGHT, + &SafeFont, + (UBYTE *)"Drawer", + &Type3Text, + }; + +struct IntuiText TypeText = + { + 1, 0, + JAM2, + 161, 6 + REQTITLE_HEIGHT, + &SafeFont, + (UBYTE *)"Or Type a Name", + &Type2Text, + }; + + + +/* === Main Data ======================================================== */ +struct ReqSupport OpenReqSupport = + { + + /* struct Requester Requester; */ + { + /* struct Requester *OlderRequest;*/ + NULL, + + /* SHORT LeftEdge, TopEdge;*/ + OPEN_LEFT, OPEN_TOP, + + /* SHORT Width, Height;*/ + OPEN_WIDTH, OPEN_HEIGHT, + + /* SHORT RelLeft, RelTop;*/ + 0, 0, + + /* struct Gadget *ReqGadget;*/ + &OpenSelectNameGadget, + + /* struct Border *ReqBorder;*/ + &PropBorder, + + /* struct IntuiText *ReqText;*/ + &TypeText, + + /* USHORT Flags;*/ + NOISYREQ, + + /* UBYTE BackFill;*/ + 0, + + /* struct ClipRect ReqCRect;*/ + { NULL }, + + /* struct BitMap *ImageBMap;*/ + NULL, + + /* struct BitMap ReqBMap;*/ + { NULL }, + + }, /* end of Requester structure */ + + /* struct Window *Window; */ + NULL, + + /* LONG (*StartRequest)(); */ + NULL, + + /* LONG (*ReqHandler)(); */ + NULL, + + /* LONG (*NewDiskHandler)(); */ + NULL, + + /* LONG (*KeyHandler)(); */ + NULL, + + /* LONG (*MouseMoveHandler)(); */ + NULL, + + /* SHORT SelectedGadgetID; */ + 0, +}; + +struct Requester *OpenReq = NULL; +struct Window *OpenReqWindow = NULL; +struct FileIOSupport *OpenReqFileIO = NULL; +UBYTE OpenUndoBuffer[MAX_NAME_LENGTH]; +UBYTE OpenLockName[128] = {0}; + +ULONG OpenSaveLock = NULL; + +UBYTE CurrentDiskString[] = ":"; + +LONG OpenClickSeconds; +LONG OpenClickMicros; + + +/* *** chipdata.c *********************************************************** + * + * File IO Suite -- Chip Memory Data Declarations + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 4 Feb 87 RJ Real release + * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release + * 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2 + * 1 Feb 86 =RJ Mical= Created this file. + * + * *********************************************************************** */ + + +#define FILEIO_SOURCEFILE +/* This prevents eglobfio.c from being included */ +#define EGLOBAL_FILEIO_CANCEL +#include "fileio.h" + + + +/* === WaitPointer Imagery =============================================== */ +USHORT ElecArtsWaitPointer[(ELECARTSPOINT_HEIGHT * 2) + 4] = + { + 0x0000, 0x0000, + + 0x6700, 0xC000, + 0xCFA0, 0xC700, + 0xBFF0, 0x0FA0, + 0x70F8, 0x3FF0, + 0x7DFC, 0x3FF8, + 0xFBFC, 0x7FF8, + 0x70FC, 0x3FF8, + 0x7FFE, 0x3FFC, + 0x7F0E, 0x3FFC, + 0x3FDF, 0x1FFE, + 0x7FBE, 0x3FFC, + 0x3F0E, 0x1FFC, + 0x1FFC, 0x07F8, + 0x07F8, 0x01E0, + 0x01E0, 0x0080, + 0x07C0, 0x0340, + 0x0FE0, 0x07C0, + 0x0740, 0x0200, + 0x0000, 0x0000, + 0x0070, 0x0020, + 0x0078, 0x0038, + 0x0038, 0x0010, + + 0x0000, 0x0000, + }; + + + +/* === Open Requester Imagery ============================================ */ +USHORT OpenPropData[OPENPROP_MAXHEIGHT * 2]; + +USHORT OpenPropTop[OPENPROP_TOPHEIGHT * 2] = + { + /* plane 0 */ + 0x7FC0, + 0xE0E0, + + /* plane 1 */ + 0x0000, + 0x1F00, + }; + + +USHORT OpenPropBottom[OPENPROP_BOTTOMHEIGHT * 2] = + { + /* plane 0 */ + 0xC060, + 0xC060, + 0xC060, + 0xC060, + 0xE0E0, + 0x7FC0, + + /* plane 1 */ + 0x3F80, + 0x3F80, + 0x3F80, + 0x3F80, + 0x1F00, + 0x0000, + }; + + +USHORT OpenUpData[] = + { + /* plane 0 */ + 0x0100, + 0x739C, + 0x87C2, + 0x8FE2, + 0x9FF2, + 0xBFFA, + 0x8382, + 0x8382, + 0x8382, + 0x8382, + 0x8382, + 0x7BBC, + 0x0380, + 0x0380, + + /* plane 1 */ + 0x0000, + 0x0000, + 0x600C, + 0x4004, + 0x0000, + 0x0000, + 0x0000, + 0x783C, + 0x783C, + 0x783C, + 0x783C, + 0x0000, + 0x0000, + 0x0000, + }; + +USHORT OpenDownData[] = + { + /* plane 0 */ + 0x0380, + 0x0380, + 0x7BBC, + 0x8382, + 0x8382, + 0x8382, + 0x8382, + 0x8382, + 0xBFFA, + 0x9FF2, + 0x8FE2, + 0x87C2, + 0x739C, + 0x0100, + + /* plane 1 */ + 0x0000, + 0x0000, + 0x0000, + 0x783C, + 0x783C, + 0x783C, + 0x783C, + 0x0000, + 0x0000, + 0x0000, + 0x4004, + 0x600C, + 0x0000, + 0x0000, + }; + + +/* *** volname.c ************************************************************ + * + * File IO Suite -- Volume Name Construction Routines + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? Thanks. + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 27 Sep 87 RJ Leave VolumeIndex alone as much as possible. + * Also, after building a new volume table, try + * to look up the old volume name among the + * new volume entries and set VolumeIndex + * if possible. + * 4 Feb 87 RJ Real release + * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release + * 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2 + * 1 Feb 86 =RJ Mical= Created this file. + * + * *********************************************************************** */ + + +#define FILEIO_SOURCEFILE +#include "fileio.h" +#include + + +/* Lattice doesn't accept the ID_DOS_DISK which looks like this: + * #define ID_DOS_DISK ('DOS\0') + * so I make up my own. + */ +#define X_ID_DOS_DISK (((LONG)'D'<<24)|((LONG)'O'<<16)|('S'<<8)|('\0')) + + +BOOL DOSDisk(device) +struct DeviceList *device; +/* This little routine dips its gnarled toes directly into the + * scary murky depths of AmigaDOS interior. + * If it survives, it returns TRUE or FALSE depending on whether or + * the specified device is a DOS disk. + * Jeez, Look at the structure names in this routine! Whew! You almost + * gotta be a computer scientist to understand this stuff. + */ +{ + struct MsgPort *port; + BOOL result; + struct InfoData *info; + struct StandardPacket *packet; + + + result = FALSE; + + /* Allocate the data structures required to communicate with AmigaDOS */ + info = (struct InfoData *)AllocMem(sizeof(struct InfoData), MEMF_CLEAR); + packet = (struct StandardPacket *)AllocMem(sizeof(struct StandardPacket), + MEMF_CLEAR); + + /* Grab us a message port for the reply from DOS */ + port = CreatePort(NULL, 0); + + if (port && info && packet) + { + /* OK, everything is set so here we go! */ + + /* Set up the StandardPacket's Exec message */ + packet->sp_Msg.mn_Node.ln_Type = NT_MESSAGE; + packet->sp_Msg.mn_Node.ln_Name = (char *)&packet->sp_Pkt; + packet->sp_Msg.mn_ReplyPort = port; + + /* Set up the StandardPacket's DOS data */ + packet->sp_Pkt.dp_Link = &packet->sp_Msg; + packet->sp_Pkt.dp_Type = ACTION_DISK_INFO; + packet->sp_Pkt.dp_Arg1 = ((LONG)info >> 2); + packet->sp_Pkt.dp_Port = port; + + /* Now, ask the device whether or not it's a DOS disk */ + PutMsg(device->dl_Task, &packet->sp_Msg); + /* zzz */ + WaitPort(port); + + /* Well? */ + if (info->id_DiskType == X_ID_DOS_DISK) result = TRUE; + } + + if (port) DeletePort(port); + if (info) FreeMem(info, sizeof(struct InfoData)); + if (packet) FreeMem(packet, sizeof(struct StandardPacket)); + + return(result); +} + + + +VOID BuildVolumeTable(fileio) +struct FileIOSupport *fileio; +/* This routine builds an alphabetically-sorted list of all active volumes. + * The names can be either the device names or the volume names, depending + * on whether you set USE_VOLUME_NAMES. + */ +{ + struct DosInfo *dosinfo; + struct DeviceList *masterlist, *devlist, *worklist; + struct MsgPort *handler; + LONG yuck; + UBYTE *nameptr, *textptr; + UBYTE len; + SHORT i; + struct Remember **key, *localkey, *keyptr; + + if (DosBase == NULL) return; + + key = &fileio->VolumeKey; + FreeRemember(key, TRUE); + localkey = NULL; + +/* FORMERLY: fileio->VolumeCount = fileio->VolumeIndex = 0; + * Instead, try leaving index where it was, clipping as needed at the end + */ + fileio->VolumeCount = 0; + + /* First, feel through from DosBase down to the device list, dancing + * all the while with the bcpl pointers. + */ + yuck = (LONG)((struct RootNode *)DosBase->dl_Root)->rn_Info; + dosinfo = (struct DosInfo *)(yuck << 2); /* reality pointer */ + yuck = (LONG)dosinfo->di_DevInfo; + masterlist = (struct DeviceList *)(yuck << 2); /* reality pointer */ + + devlist = masterlist; + + + while (devlist) + { + /* First, find each device that's active (dl_Task is not NULL) */ + if ((devlist->dl_Type == DLT_DEVICE) && (devlist->dl_Task)) + { + /* OK, got a device. Now ask it if it's a DOS disk. */ + if (NOT DOSDisk(devlist)) goto NEXT_DEVICE; + + /* OK, got a device that's a DOS disk. Now find the name. + * If USE_VOLUME_NAMES is clear, use the device name, + * else look up the volume name. + */ + nameptr = (UBYTE *)devlist->dl_Name; + if (FlagIsSet(fileio->Flags, USE_VOLUME_NAMES)) + { + /* Use the handler for this volume to find the matching device */ + handler = (struct MsgPort *)devlist->dl_Task; + + worklist = masterlist; + while (worklist) + { + if ((worklist->dl_Type == DLT_VOLUME) + && (worklist->dl_Task == handler)) + { + nameptr = (UBYTE *)worklist->dl_Name; + goto GOT_NAME; + } + + yuck = worklist->dl_Next; + worklist = (struct DeviceList *)(yuck << 2); + } + /* If we get to the end of this loop and fall out, then what? + * Got an active device but no matching volume? OK. + */ + } + +GOT_NAME: + yuck = (LONG)nameptr; + nameptr = (UBYTE *)(yuck << 2); + len = *nameptr++; + + if ((textptr = AllocRemember(&localkey, len + 2, NULL)) == NULL) + { + Alert(ALERT_OUTOFMEM, NULL); + goto DEVICES_DONE; + } + + fileio->VolumeCount++; + for (i = 0; i < len; i++) *textptr++ = *nameptr++; + *textptr++ = ':'; + *textptr = '\0'; + MakeEntry(localkey->Memory, key, NULL); + } + +NEXT_DEVICE: + yuck = devlist->dl_Next; + devlist = (struct DeviceList *)(yuck << 2); + } + + +DEVICES_DONE: + + FreeRemember(&localkey, TRUE); + + /* Safety measure */ + if (fileio->VolumeIndex >= fileio->VolumeCount) + fileio->VolumeIndex = fileio->VolumeCount - 1; + + keyptr = fileio->VolumeKey; + nameptr = &fileio->DiskName[0]; + i = 0; + while (keyptr) + { + if (StringsEqual(keyptr->Memory, nameptr)) + { + fileio->VolumeIndex = i; + goto DONE; + } + keyptr = keyptr->NextRemember; + i++; + } + + fileio->VolumeIndex = 0; + +DONE: ; +} + + +UBYTE *CurrentVolumeName() +/* This routine returns a pointer the name of the current volume */ +{ + SHORT i; + struct Remember *remember; + + /* If there's no active volumes then return the "safe" volume name */ + if (OpenReqFileIO->VolumeCount < 1) + return(&CurrentDiskString[0]); + + /* Safety measure */ + if (OpenReqFileIO->VolumeIndex >= OpenReqFileIO->VolumeCount) + OpenReqFileIO->VolumeIndex = 0; + + /* Finally, look up the name */ + remember = OpenReqFileIO->VolumeKey; + for (i = 0; i < OpenReqFileIO->VolumeIndex; i++) + remember = remember->NextRemember; + return(remember->Memory); +} + + +/* *** filename.c *********************************************************** + * + * File IO Suite -- File Name Construction Routines + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? Thanks. + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 4 Feb 87 RJ Real release + * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release + * 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2 + * 1 Feb 86 =RJ Mical= Created this file. + * + * *********************************************************************** */ + + +#define FILEIO_SOURCEFILE +#include "fileio.h" +#include + + +#define FRIENDLY_NOT 0 +#define FRIENDLY_DRAWER 1 +#define FRIENDLY_OTHER 2 + + + +VOID BuildNameTable(fileio) +struct FileIOSupport *fileio; +/* This routine searches through the fileio lock for all file entries, + * and builds a list of the names found. + * If the user wants Workbench-style pattern matching, filenames are + * passed through a filter before being added to the list. + * All directory entries are added to the list. + */ +{ + struct FileInfoBlock *fileinfo; + UBYTE *ptr; + UBYTE workname[MAX_NAME_LENGTH + 5]; /* the extra 5 are for the ".info" */ + struct Remember **key; + ULONG lock; + SHORT i, flags, type; + SHORT pick; + + fileio->NameCount = 0; + lock = fileio->DOSLock; + key = &fileio->NameKey; + FreeRemember(key, TRUE); + ClearFlag(fileio->Flags, GOOD_FILENAMES); + + if ((fileinfo = (struct FileInfoBlock *)AllocMem( + sizeof(struct FileInfoBlock), MEMF_CLEAR)) == NULL) + goto BUILD_EXIT; + + SetWaitPointer(OpenReqWindow); + + /* Now, first, before we might be interrupted by MessageInterrupt(), + * check whether or not we're looking in a drawer and, if so, add the + * entry that allows the user to ascend one drawer. + */ + if (StringLength(&OpenReqFileIO->DrawerName[0])) + { + MakeEntry("\253\253 PRIOR DRAWER", key, NAMED_PREVIOUS); + /* bump the master count */ + fileio->NameCount++; + } + + /* starting from Examine() until ExNext() is NULL */ + if (Examine(lock, fileinfo)) + while (ExNext(lock, fileinfo)) + { + /* Default: this entry is a normal file */ + flags = NULL; + CopyString(&workname[0], fileinfo->fib_FileName); + +#ifdef WBENCH_CODE + /* Now, does the caller want Workbench-style pattern matching? */ + if (FlagIsSet(fileio->Flags, WBENCH_MATCH)) + { + /* start from location 1 to avoid matching the ".info" file */ + if (ptr = FindSuffix(&workname[1], ".info")) + { + *ptr = '\0'; /* strip the suffix off that baby */ + + /* Get the friendliness quotient of this .info file */ + type = FriendlyInfoType(&workname[0], fileio); + + /* If just not friendly, forget about it */ + if (type == FRIENDLY_NOT) goto NEXT_LOCK; + + /* If this was a drawer, set the fileinfo as a directory */ + if (type == FRIENDLY_DRAWER) + fileinfo->fib_DirEntryType = 1; + } + else goto NEXT_LOCK; + } +#endif /* ... of WBENCH_CODE conditional */ + + if (fileinfo->fib_DirEntryType >= 0) + { + /* This entry is a directory */ + flags = NAMED_DIRECTORY; + + /* If you change the following text, change DIR_TEXT_SIZE too */ + for (i = StringLength(&workname[0]); i >= 0; i--) + workname[i + DIR_TEXT_SIZE] = workname[i]; + workname[0] = '\273'; + workname[1] = '\273'; + workname[2] = ' '; + } + + pick = MakeEntry(&workname[0], key, flags); + /* bump the master count */ + fileio->NameCount++; + + if (pick <= fileio->CurrentPick) + fileio->CurrentPick++; + + InitOpenProp(FALSE); + StuffSelectNames(2); + +NEXT_LOCK: + /* If there's a message pending, split with what we've got */ + if (MessageInterrupt()) goto EXAMINE_DONE; + } + + SetFlag(fileio->Flags, GOOD_FILENAMES); + + +EXAMINE_DONE: + + if (OpenReqWindow) ClearPointer(OpenReqWindow); + FreeMem(fileinfo, sizeof(struct FileInfoBlock)); + + +BUILD_EXIT: ; +} + + + +VOID PropInterrupt() +/* This routine is called by MessageInterrupt() if the prop gadget + * is played with while the file name table is being built. + * As long as the user is using the proportional gadget, hang around here. + */ +{ + struct IntuiMessage *message; + struct Gadget *gadget; + BOOL mousemove; + + FOREVER + { + WaitPort(OpenReqWindow->UserPort); + mousemove = FALSE; + + while (message = GetMsg(OpenReqWindow->UserPort)) + { + switch (message->Class) + { + case GADGETUP: + gadget = (struct Gadget *)message->IAddress; + switch (gadget->GadgetID) + { + case OPENGADGET_PROPGADGET: + ReplyMsg(message); + HandleGadget(gadget, 0, 0, 0, 0); + return; + + default: + goto MESSAGE_RETURN; + } + break; + + case MOUSEMOVE: + ReplyMsg(message); + mousemove = TRUE; + break; + + default: + goto MESSAGE_RETURN; + + } + } + + if (mousemove) PropMouseMoves(); + } + +MESSAGE_RETURN: + /* Pretend we didn't see this message */ + AddHead(&OpenReqWindow->UserPort->mp_MsgList, message); +} + + + +BOOL MessageInterruptGrunt(message) +struct IntuiMessage *message; +/* Test if there's a gadget type of message at the window port, + * react to it if there is one, and return TRUE if the message is + * one that should interrupt the building of the file name list. + */ +{ + ULONG class; + SHORT x, y; + struct Gadget *gadget; + LONG seconds, micros; + + class = message->Class; + if ((class == GADGETDOWN) || (class == GADGETUP)) + { + gadget = (struct Gadget *)message->IAddress; + x = message->MouseX; + y = message->MouseY; + seconds = message->Seconds; + micros = message->Micros; + OpenReqSupport.SelectedGadgetID = gadget->GadgetID; + + switch (gadget->GadgetID) + { + case OPENGADGET_SELECTNAME: + y = HandleSelect(y, seconds, micros); + if ((y == -1) || (y == 1)) + { + /* Pretend we didn't see this message */ + AddHead(&OpenReqWindow->UserPort->mp_MsgList, message); + return(TRUE); + } + + StuffFileName(); + StuffSelectNames(5); + goto REPLY_AND_RETURN_FALSE; + + case OPENGADGET_UPGADGET: + case OPENGADGET_DOWNGADGET: + goto REPLY_AND_RETURN_FALSE; + + case OPENGADGET_PROPGADGET: + HandleGadget(gadget, x, y, seconds, micros); + if (class == GADGETDOWN) PropInterrupt(); + goto REPLY_AND_RETURN_FALSE; + + default: + /* Do nothing, fall into the message's AddHead() below. + * This includes the gadgets OK, CANCEL, NEXTDISK, + * DISKNAME, DRAWERNAME, FILENAME, and BACKDROP. + */ + break; + } + } + + /* Pretend we didn't see this message */ + AddHead(&OpenReqWindow->UserPort->mp_MsgList, message); + return(TRUE); + +REPLY_AND_RETURN_FALSE: + ReplyMsg(message); + return(FALSE); +} + + + +BOOL MessageInterrupt() +/* Call MessageInterruptGrunt() with each message. + * Return TRUE if the message is one that should interrupt the building + * of the file name list, else return FALSE. + */ +{ + struct IntuiMessage *message; + + while (message = GetMsg(OpenReqWindow->UserPort)) + { + if (MessageInterruptGrunt(message)) + return(TRUE); + } + return(FALSE); +} + + + +SHORT MakeEntry(name, startkey, flags) +UBYTE *name; +struct Remember **startkey; +UBYTE flags; +{ + SHORT length, pos; + struct Remember *localkey, *nextkey, *oldkey; + UBYTE *ptr; + + /* length equals the length of the text plus one for the + * terminating NULL + */ + length = StringLength(name) + 1; + localkey = NULL; + /* Alloc one larger than length to make room for the flag byte */ + ptr = AllocRemember(&localkey, length + 1, NULL); + if (ptr == NULL) return(32767); + CopyString(ptr, name); + *(ptr + length) = flags; + nextkey = *startkey; + pos = 0; + oldkey = NULL; + while (nextkey) + { + if (CompareUpperStrings(nextkey->Memory, name) >= 0) + goto DONE; + + oldkey = nextkey; + nextkey = nextkey->NextRemember; + pos++; + } + +DONE: + if (oldkey) oldkey->NextRemember = localkey; + else *startkey = localkey; + localkey->NextRemember = nextkey; + return(pos); +} + + + + +#ifdef WBENCH_CODE + +SHORT FriendlyInfoType(infoname, fileio) +UBYTE *infoname; +struct FileIOSupport *fileio; +/* This routine looks at the .info file that's named infoname and + * tests to see if its object type and tool type match the specifications + * in the fileio structure. Returns TRUE if everything matches. + * If the .info file couldn't be opened or if the requirements don't + * match, FALSE is returned. + */ +{ + struct DiskObject *object; + SHORT result; + + result = FRIENDLY_NOT; + if (object = GetDiskObject(infoname)) + { + if ((object->do_Type == WBDRAWER) || (object->do_Type == WBGARBAGE)) + result = FRIENDLY_DRAWER; + else if (object->do_Type == WBDISK) + result = FRIENDLY_NOT; + else + { + if (FlagIsSet(fileio->Flags, MATCH_OBJECTTYPE)) + if (object->do_Type != fileio->DiskObjectType) goto FRIEND_DONE; + + result = FRIENDLY_OTHER; + + if (FlagIsSet(fileio->Flags, MATCH_TOOLTYPE)) + { + if (NOT MatchToolValue( + FindToolType(object->do_ToolTypes, "FILETYPE"), + &fileio->ToolType[0])) + result = FRIENDLY_NOT; + } + } + } + +FRIEND_DONE: + if (object) FreeDiskObject(object); + return(result); +} + +#endif /* ... of WBENCH_CODE conditional */ + + + + +/* *** strings.c ************************************************************ + * + * String Manipulation Routines + * + * Copyright (C) 1986, 1987, Robert J. Mical + * + * CONFIDENTIAL and PROPRIETARY + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 4 Feb 87 RJ Real release + * 2 Feb 87 RJ Added StripOuterSpace() + * 16 May 86 RJ Just more stuff + * 1 June 1985 =RJ Mical= Created this file from a weird distant echo. + * + * *********************************************************************** */ + + +#include "exec/types.h" + +#define FOREVER for(;;) + + +/* copy these and define them as 'extern' in your global include file + * in order to use these routines in your code. + */ +SHORT CompareUpperStrings(); +UBYTE *FindSuffix(); +SHORT GetAtom(); +SHORT IndexString(); +SHORT StringLength(); +BOOL StringsEqual(); +UBYTE *StripLeadingSpace(); +UBYTE *StripOuterSpace(); + + + +SHORT CompareUpperStrings(s, t) +UBYTE *s, *t; +/* Compare s to t, making alphabet characters uppercase. Return value: + * s < t -1 + * s == t 0 + * s > t 1 + */ +{ + SHORT sc, tc; + + FOREVER + { + sc = *s++; + if ((sc >= 'a') && (sc <= 'z')) sc = sc - 'a' + 'A'; + tc = *t++; + if ((tc >= 'a') && (tc <= 'z')) tc = tc - 'a' + 'A'; + + if (sc < tc) return(-1); + if (sc > tc) return(1); + if (sc == '\0') return(0); + } + return(0); +} + + + +VOID CopyString(tostring, fromstring) +UBYTE *tostring, *fromstring; +{ + while (*tostring++ = *fromstring++) ; +} + + + +VOID ConcatString(firststring, addstring) +UBYTE *firststring, *addstring; +{ + SHORT length1; + + length1 = StringLength(firststring); + firststring += length1; + CopyString(firststring, addstring); +} + + + +UBYTE *FindSuffix(string, suffix) +UBYTE *string; +UBYTE *suffix; +{ + SHORT stringlength, suffixlength; + + if ( (stringlength = StringLength(string)) + >= (suffixlength = StringLength(suffix)) ) + { + if (StringsEqual(string + stringlength - suffixlength, suffix)) + return (string + stringlength - suffixlength); + } + return(NULL); +} + + + +SHORT IndexString(lookin, lookfor) +UBYTE *lookin, *lookfor; +/* This routines looks in the lookin string for the lookfor string. + * Returns the position of the lookfor string in lookin, or + * returns -1 if the lookfor string was not found. + */ +{ + SHORT index; + UBYTE *workin, *workfor; + + index = 0; + + while (*lookin) + { + workin = lookin; + workfor = lookfor; + while ((*workfor) && (*workin) && (*workfor == *workin)) + { + workfor++; + workin++; + } + if (*workfor == '\0') return(index); + lookin++; + index++; + } + + return(-1); +} + + + +SHORT StringLength(text) +UBYTE *text; +{ + SHORT length; + + length = 0; + while (*text++) length++; + return(length); +} + + + +BOOL StringsEqual(text1, text2) +UBYTE *text1, *text2; +{ + while (*text1 == *text2) + { + if (*text1 == '\0') return(TRUE); + text1++; + text2++; + } + + return(FALSE); +} + + + +UBYTE *StripLeadingSpace(text, space) +UBYTE *text, *space; +/* This routine "strips" the leading occurrences of the space string + * characters from the text string by finding the first character + * of the text string that is not contained in the space string. + * The return value is a pointer to the first non-space character in text. + * If text is the null string or if text consists of nothing + * but space characters, NULL is returned. + * If space is the NULL string, text is returned. + */ +{ + if (space == NULL) return(text); + if (*space == '\0') return(text); + + while (*text && (*text == *space)) text++; + + if (*text) return(text); + return(NULL); +} + + + +UBYTE *StripOuterSpace(text, space) +UBYTE *text, *space; +/* This routine "strips" the leading and trailing occurrences of the space + * string characters from the text string. + * The return value is a pointer to the first non-space character in text, + * and a null byte is stored after the text's last non-space character. + */ +{ + UBYTE *workspace, *lastspace; + + if (text == NULL) return(NULL); + + if ((workspace = StripLeadingSpace(text, space)) == NULL) + { + *text = '\0'; + return(text); + } + + lastspace = workspace + StringLength(workspace) - 1; + while ((lastspace >= workspace) && (*lastspace == *space)) lastspace--; + *(lastspace + 1) = '\0'; + return(workspace); +} + + + + +/* *** pointers.c *********************************************************** + * + * Intuition Pointers Routines + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? Thanks. + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release + * 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2 + * 1 Feb 86 =RJ Mical= Created this file. + * + * *********************************************************************** */ + + +#define FILEIO_SOURCEFILE +#include "fileio.h" + + +extern USHORT ElecArtsWaitPointer[]; + + +VOID SetWaitPointer(window) +struct Window *window; +{ + /* This one is the default because it's my favorite */ + SetPointer(window, &ElecArtsWaitPointer[0], ELECARTSPOINT_HEIGHT, + 16, ELECARTSPOINT_XOFF, ELECARTSPOINT_YOFF); +} + + +/* *** alerts.c ************************************************************* + * + * Alert and Abort AutoRequest Routines + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 27 Sep 87 RJ Removed reference to alerts.h, brought + * declarations into this file + * 4 Feb 87 RJ Real release + * 11 Jul 86 RJ >:-{)* Prepare (clean house) for release + * 1 Feb 86 =RJ Mical= Created this file with fond memories + * + * *********************************************************************** */ + + +#include + + +#define ALERT_TEXT_TOP 6 +#define ALERT_TEXT_LEFT 6 + + +extern struct TextAttr SafeFont; + + +UBYTE *AlertStrings[] = + { + /* "Longest allowed string -----------|" */ + (UBYTE *)"Really broken. Stop all and reboot", + (UBYTE *)"Out of memory! Sheesh.", + (UBYTE *)"Invalid Disk or Drawer Selection", + }; + + +struct IntuiText AlertText = + { + AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, + AUTOLEFTEDGE + ALERT_TEXT_LEFT, AUTOTOPEDGE + ALERT_TEXT_TOP, + &SafeFont, + NULL, NULL, + }; + + +struct IntuiText AlertOKText = + { + AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, + AUTOLEFTEDGE, AUTOTOPEDGE, + &SafeFont, + (UBYTE *)"OK", + NULL, + }; + + + +VOID AlertGrunt(text, window) +UBYTE *text; +struct Window *window; +{ + AlertText.IText = text; + AutoRequest(window, &AlertText, NULL, + &AlertOKText, 0, 0, 320, 48 + ALERT_TEXT_TOP); +} + + + +VOID Alert(abortNumber, window) +USHORT abortNumber; +struct Window *window; +{ + AlertGrunt(AlertStrings[abortNumber], window); +} + + + +VOID Abort(abortNumber, window) +USHORT abortNumber; +struct Window *window; +{ + Alert(abortNumber, window); +/*??? FOREVER Alert(ALERT_ABORT, window);*/ + FOREVER Alert(0, window); +} + + +/* *** reqsupp.c ************************************************************ + * + * Requester Support Routine + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 4 Feb 87 RJ Real release + * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release + * 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2 + * 1 Feb 86 =RJ Mical= Created this file. + * + * *********************************************************************** */ + + +#include +#include + + +struct IntuiMessage *GetMsg(); + + + +/* *** DoRequest() ********************************************************** + * + * NAME + * DoRequest -- Creates and manages a requester + * + * + * SYNOPSIS + * DoRequest(ReqSupport); + * + * + * FUNCTION + * Creates a requester according to the specifications laid out + * by you in a ReqSupport structure, and manages the interaction + * with the requester for you. In the end this routine returns control + * to you with an identifier describing which gadget the user selected + * to terminate the requester; this identifier can be found in the + * SelectedGadgetID field of your ReqSupport structure. + * + * Note that if anything goes wrong while trying to create the + * requester (usually out of memory) this routine returns + * immediately with the SelectedGadgetID field set to zero. + * Because of this, you should either avoid GadgetIDs of zero + * or at least you should have your Cancel Gadget have an + * ID of zero. + * + * You can specify routines that will be called when certain events + * occur while the requester is displayed. For instance, you can + * specify that a particular routine be called every time the + * user selects any of the requester gadgets. See the documentation + * and the ReqSupport structure for details about what + * routine vectors you can supply. + * + * + * INPUTS + * ReqSupport = pointer to a ReqSupport structure + * + * + * RESULT + * Returns the identifier of the gadget that ended the requester + * in the ReqSupport's SelectedGadgetID field. + * If anything goes wrong (usually out of memory) the SelectedGadgetID + * field is set to zero. + */ +VOID DoRequest(reqsupp) +struct ReqSupport *reqsupp; +{ + ULONG class; + SHORT x, y; + struct IntuiMessage *message; + struct Gadget *gadget; + ULONG saveidcmp; + BOOL IAintGotNoSatisfaction, mousemoved; + struct Window *window; + LONG seconds, micros; + + window = reqsupp->Window; + + saveidcmp = window->IDCMPFlags; + /* If you change the list of IDCMP flags, check the effect it has + * on the switch / case statements of MessageInterrupt() in filename.c + */ + ModifyIDCMP(window, + GADGETUP | GADGETDOWN | REQSET | REQCLEAR + | MOUSEMOVE | DISKINSERTED); + + if (Request(&reqsupp->Requester, window) == FALSE) + { + reqsupp->SelectedGadgetID = 0; + goto JUMP_SHIP; + } + + IAintGotNoSatisfaction = TRUE; + + while (IAintGotNoSatisfaction) + { + Wait(1 << window->UserPort->mp_SigBit); + + mousemoved = FALSE; + + while (message = GetMsg(window->UserPort)) + { + gadget = (struct Gadget *)message->IAddress; + class = message->Class; + x = message->MouseX; + y = message->MouseY; + seconds = message->Seconds; + micros = message->Micros; + ReplyMsg(message); + + if (IAintGotNoSatisfaction) switch (class) + { + case REQSET: + /* Does the caller have some startup + * stuff to perform now that the + * requester has been opened? + */ + if (reqsupp->StartRequest) + (*reqsupp->StartRequest)(); + break; + case DISKINSERTED: + if (reqsupp->NewDiskHandler) (*reqsupp->NewDiskHandler)(); + break; + case MOUSEMOVE: + mousemoved = TRUE; + break; + case GADGETDOWN: + case GADGETUP: + reqsupp->SelectedGadgetID = gadget->GadgetID; + if (reqsupp->GadgetHandler) + { + if ((*reqsupp->GadgetHandler)(gadget, + x, y, seconds, micros)) + { + EndRequest(&reqsupp->Requester, window); + IAintGotNoSatisfaction = FALSE; + } + } + break; + case REQCLEAR: + IAintGotNoSatisfaction = FALSE; + break; + } + } + + if (mousemoved && reqsupp->MouseMoveHandler && IAintGotNoSatisfaction) + (*reqsupp->MouseMoveHandler)(); + } + +JUMP_SHIP: + ModifyIDCMP(window, saveidcmp); +} + + + +/* *** globfio.c ************************************************************ + * + * File IO Suite -- Global Variable Definitions + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * (available soon if not already) + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 27 Sep 87 RJ Changed name of this file from global.c + * 4 Feb 87 RJ Real release + * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release + * 3 May 86 RJ Fix prop gadget for both 1.1 and 1.2 + * 1 Feb 86 =RJ Mical= Created this file. + * + * *********************************************************************** */ + + +/* This prevents eglobfio.c from being included */ +#define EGLOBAL_FILEIO_CANCEL +#define FILEIO_SOURCEFILE +#include "fileio.h" + + + +/* === System Global Variables ========================================== */ +struct IntuitionBase *IntuitionBase = NULL; +struct GfxBase *GfxBase = NULL; +struct DosLibrary *DosBase = NULL; +struct IconBase *IconBase = NULL; + + +#ifndef EGLOBAL_FILEIO_C +#define EGLOBAL_FILEIO_C + + +/* *** eglobfio.c *********************************************************** + * + * File IO Suite -- External Global Variable Definitions + * from Book 1 of the Amiga Programmers' Suite by RJ Mical + * (available soon if not already) + * + * Copyright (C) 1986, 1987, Robert J. Mical + * All Rights Reserved. + * + * Created for Amiga developers. + * Any or all of this code can be used in any program as long as this + * entire copyright notice is retained, ok? + * + * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. + * All copyright notices and all file headers must be retained intact. + * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the + * resultant object code may be included in any software product. However, no + * portion of the source listings or documentation of the Amiga Programmer's + * Suite Book 1 may be distributed or sold for profit or in a for-profit + * product without the written authorization of the author, RJ Mical. + * + * HISTORY NAME DESCRIPTION + * ----------- -------------- -------------------------------------------- + * 27 Sep 87 RJ Changed name of this file from eglobal.c + * 4 Feb 87 RJ Real release + * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release + * 3 May 86 RJ Fix prop gadget for both 1.1 and 1.2 + * 1 Feb 86 =RJ Mical= Created this file. + * + * *********************************************************************** */ + + + +/* === System Global Variables ========================================== */ +extern struct IntuitionBase *IntuitionBase; +extern struct GfxBase *GfxBase; +extern struct DosLibrary *DosBase; +extern struct IconBase *IconBase; + +extern struct TextAttr SafeFont; +extern struct Gadget OKGadget, CancelGadget; + + + +/* === Open Requester Declarations ======================================= */ +/* The global declaration of these can be found in opendata.c */ +extern struct Requester *OpenReq; +extern struct ReqSupport OpenReqSupport; +extern struct Window *OpenReqWindow; +extern struct FileIOSupport *OpenReqFileIO; + +extern struct StringInfo OpenNameTextInfo; +extern struct StringInfo OpenDrawerTextInfo; +extern struct StringInfo OpenDiskTextInfo; +extern struct Gadget OpenNameTextGadget; +extern struct Gadget OpenDiskTextGadget; +extern struct Gadget OpenDrawerTextGadget; +extern struct PropInfo OpenPropInfo; +extern struct Image OpenPropImage; +extern struct Gadget OpenSelectNameGadget; + +extern UBYTE OpenUndoBuffer[]; +extern UBYTE OpenSelectBuffers[NAME_ENTRY_COUNT][VISIBLE_SELECT_LENGTH]; +extern struct IntuiText OpenSelectText[NAME_ENTRY_COUNT]; +extern UBYTE OpenLockName[]; + +extern struct IntuiText ReqTitleText; +extern UBYTE *DefaultReqTitle; + +extern ULONG OpenSaveLock; + +extern UBYTE CurrentDiskString[]; + +extern LONG OpenClickSeconds; +extern LONG OpenClickMicros; + +/* The global declaration of these can be found in chipdata.c */ +extern USHORT OpenUpData[]; +extern USHORT OpenDownData[]; +extern USHORT OpenPropData[]; +extern USHORT OpenPropTop[]; +extern USHORT OpenPropBottom[]; + + + +#endif /* of EGLOBAL_FILEIO_C */ + diff --git a/amiga/frag-ahead.c b/amiga/frag-ahead.c new file mode 100644 index 0000000..9196269 --- /dev/null +++ b/amiga/frag-ahead.c @@ -0,0 +1,144 @@ + +CHAR ahead_buffer[64]; /* our type-ahead buffer */ +INT aheads = 0; /* number of chars currently in buffer */ + +/* A buffer to save typed-ahead chars, in addition to the OS facility for + this purpose, is desirable. This is because writing and reading escape + sequences to the Amiga console device (for display control) interferes + with normal type-ahead. + + Without our own buffer, type-ahead between escape seqs would be lost. +*/ + +/*------------------------------*/ +/* queue_ahead */ +/*------------------------------*/ + +/* Temporarily save a typed-ahead char. Useful whenever the char would + otherwise be throw away, such as when reading escape seqs from the console + device, or after a [MORE] prompt. +*/ + +VOID +queue_ahead (the_char) + +CHAR the_char; +{ + if (aheads < sizeof (ahead_buffer)) /* only if there's room */ + { + ahead_buffer[aheads] = the_char; + aheads++; + } +} + +/*------------------------------*/ +/* deque_ahead */ +/*------------------------------*/ +CHAR +deque_ahead () /* return the oldest typed-ahead char, zero if none */ +{ + CHAR the_char; + INT i; + + if (aheads == 0) + the_char = 0; /* empty buffer, return null */ + else + { + the_char = ahead_buffer[0]; /* get first-in char */ + aheads--; + + for (i=0; iis_Node.ln_Type = NT_INTERRUPT; + p->is_Node.ln_Pri = -60; /* not time-critical */ + p->is_Node.ln_Name = "zir"; + /** p->is_Data = 0; **/ /* currently unused */ + p->is_Code = VertBServer; + + /* put the new interrupt server into action */ + AddIntServer (INTB_VERTB, p); + inited = 1; + } + else { + if (inited) + RemIntServer (INTB_VERTB, p); + } +} + +/*------------------------------*/ +/* VertBServer */ +/*------------------------------*/ + +/* This routine runs at the interrupt level. Happily, registers D0-D1/ + A0-A1 are scratch in interrupt protocol as well as the Lattice compiler. + Also, references to global vars are OK since in Lattice they are absolute, + rather than keyed off any special register. System calls are OK (unless + otherwise advertised), since standard "glue" code saves register A6 then + loads a dispatch vector from an absolute location, or from one of the + call's parameters in some cases (CheckIO?). +*/ + +extern void int_sound(); + +LONG VertBServer() /* run our interrupt routines */ +{ + int_sound(); + int_key(); + return (0); /* and continue down server chain */ +} + +/*------------------------------*/ +/* int_key */ +/*------------------------------*/ + +/* Should this run as a machine interrupt or a game pseudo-interrupt? + Some ops ($VERIFY) take a long time. */ + +void int_key() +{ +/* On the Amiga, if event messages (i.e. typed-ahead keys) aren't replied + quickly by the application and are allowed to accumulate, the OS + allocates extra buffers which /never/ get released (Peck p155). + + This can cause nasty fragmentation of free memory and break OPSOUND + (since it dynamically allocates and releases large blocks). + + One fix: reply every message immediately, and store type-ahead in our + own small queue. Should also properly decode FKey and mouse events. + + (If /currently/ awaiting input, just exit) */ +} + + +/============================= in sound.c =================================/ + +/* Use of sound synchronization flags: + (1) audion - sets start, clears stop + (2) machine (true) interrupt - if ON-OFF and done, sets stop + (3) game interrupt - if ON-ON, clears both + + In routines (1) and (3), the two flags are best changed simultaneously, + to avoid the chance of an in-between interrupt by (2). +*/ + +struct SyncFlag { + UBYTE start; + UBYTE stop; + } sf[SCHANS] = {0}; + + +/*** in audion() ***/ + + UWORD *p; + + curIOA->ioa_Request.io_Command = CMD_WRITE; + curIOA->ioa_Request.io_Flags = ADIOF_PERVOL |IOF_QUICK; + BeginIO((struct IORequest *)curIOA); + + /* write to both flags simultaneously */ + p = (UWORD *) &sf[m2chn]; + *p = 0x0100; /* start=ON, stop=OFF */ + + +/*------------------------------*/ +/* do_Finish */ +/*------------------------------*/ + +/* send ADCMD_FINISH message (separate routine since multiple calls) */ + +do_Finish (curIOA, chan) +struct IOAudio *curIOA; +UBYTE chan; +{ + UWORD *p = (UWORD *) &sf[chan]; + *p = 0; /* turn off both flags simultaneously */ + + curIOA->ioa_Request.io_Flags = ADIOF_PERVOL | IOF_QUICK; + curIOA->ioa_Request.io_Command = ADCMD_FINISH; + BeginIO ((struct IORequest *)curIOA); +} + +/*------------------------------*/ +/* md_sound */ +/*------------------------------*/ + +/* id=1-n or 0(mru), action=1-4, + volume=0-64 or -1(midi), repeat=1-n, 0(infinite) or -1(midi) */ + + WORD i, err; + + [remove vol2, rep2 refs] + + +/*------------------------------*/ +/* int_sound */ +/*------------------------------*/ + +/* Machine interrupt - check for end of sound. + This interrupt routine is active at all times, for simplicity. + + If a sound has been started (on any channel) and we have NOT previously + detected its completion, we check now. If we detect its completion, + we set the appropriate global "stop" flag. +*/ + +void int_sound() +{ + register UBYTE *p; /* (tighten up code) */ + register int i; +/* struct IORequest *result; */ + + p = (UBYTE *) &sf[0]; + for (i=0; i 50 ints/sec (max) + +* ENTRY POINT FROM MAIN LOOP +* To avoid cutting into interpreter performance too much, we keep a +* simple counter, and only occasionally perform the (somewhat costlier) +* check for a sound interrupt. + +GAMINT SUBQ.W #1,SCOUNT(A6) * TIME FOR A SOUND CHECK? + BLE.S GAMIX1 + RTS * NO, QUICK EXIT +GAMIX1 MOVE.W #SKPCNT,SCOUNT(A6) * YES, RESET COUNTER AND FALL THRU + +* ENTRY POINT FROM INPUT-WAIT LOOP +* While awaiting Amiga input, we awaken only 10 times/sec anyway, so check +* for sound every time. Might actually prefer it be a bit more frequent. +* Note: called from OPREAD/OPINPUT; safe to call interrupt function? + +GAMINT1 SAVEREGS + +* (could check first for valid SFUNC(A6), skip end-check if none, +* but then end event would hang around unreported ...) + + RESWORD + JSR _end_sound * END-OF-SOUND CHECK + POPWORD * NON-ZERO IF END DETECTED + BEQ.S GAMIX3 + + MOVE.W SFUNC(A6),D0 * SOUND-INTERRUPT FUNCTION ("START NEXT") + BSR INCALL * CALL IT (INTERNALLY) +*** TST.W D0 * (NO RETURN VAL) + +GAMIX3 +*** JSR _int_key * TYPE-AHEAD CHECK (here or from real int?) + RESTREGS + RTS + +* ---------------------- +* OPSOUND +* ---------------------- + +* MAKE A SOUND +* ARG1 = ID: 1=BEEP, 2=BOOP, 3+ ARE SPECIAL, 0=MRU +* [ARG2] = ACTION: 1=INIT, [2=START], 3=STOP, 4=CLEANUP +* [ARG3] = COUNT (HIBYTE): -1=INFINITE, [0=USE MIDI COUNT], 1-254=FINITE +* VOL (LOBYTE): 0=MIN, 8=MAX, [-1=USE MIDI VOLUME] +* [ARG4] = INTERRUPT FUNCTION + +OPSOUND NOP * REQUEST AN ARGBLK + LEA DEFBLK(A6),A1 * USE A DEFAULT ARGBLK, TOO + MOVE.W #4,(A1) * 4 ARGS MAX + MOVE.W #2,ARG2(A1) * DEFAULT ACTION = "START" + MOVE.W #$00FF,ARG3(A1) * DEFAULT COUNT=0/VOL=-1 (USE MIDI DATA) + CLR.W ARG4(A1) * DEFAULT INTERRUPT HANDLER = NONE + BSR SETDEF * SET UP DEFAULTS + + MOVE.W ARG4(A0),SFUNC(A6) * SAVE INTERRUPT HERE + MOVE.W ARG3(A0),D2 * COUNT/VOL + MOVE.W D2,D3 + EXT.W D2 * VOL (16 BITS) + LSR.W #8,D3 * COUNT (16 BITS, UNLESS -1) + CMPI.B #$FF,D3 * -1? + BNE.S OPSDX1 + EXT.W D3 * YES, MAKE 16 BITS + +OPSDX1 MOVE.W ARG2(A0),D1 * ACTION + MOVE.W ARG1(A0),D0 * SOUND ID + BRA DOSOUND + +* ---------------------- +* DOSOUND +* ---------------------- + +* AMIGA: ADJUST ARGS +* VOLUME: 0-64, -1=USE MIDI VOL +* COUNT: 0=INFINITE, 1-254=FINITE, -1=USE MIDI COUNT + +DOSOUND TST.W D2 + BLT.S D0SDX1 + ASL.W #3,D2 * MAP 0-8 TO 0-64 + +DOSDX1 TST.W D3 + BGT.S DOSDX2 * IF 1-254, JUST PASS ALONG + ADDQ.W #1,D3 * MAP -1 TO 0 + BEQ.S DOSDX2 + MOVEQ #-1,D3 * MAP 0 TO -1 + +DOSDX2 SAVEREGS + MOVE.L D3,-(SP) * COUNT + MOVE.L D2,-(SP) * VOLUME + MOVE.L D1,-(SP) * ACTION + MOVE.L D0,-(SP) * ID + JSR _md_sound + FLUSH 16 + RESTREGS + RTS + diff --git a/amiga/frag-strip.c b/amiga/frag-strip.c new file mode 100644 index 0000000..bee1f78 --- /dev/null +++ b/amiga/frag-strip.c @@ -0,0 +1,26 @@ +/*------------------------------*/ +/* strip_spaces */ +/*------------------------------*/ + +/* Remove any leading and/or trailing spaces from savenames, before + the file is created. AmigaDOS permits them, but they lead to confusing + RESTORE errors. (We continue to allow embedded spaces.) */ + +VOID +strip_spaces (filename) +register CHAR *filename; +{ + register CHAR *p; + + p = filename; + while (*p == 32) /* skip over any leading spaces */ + p++; + if (filename != p) + strcpy (filename, p); /* move the string up */ + + p = filename + strlen (filename); + while ((p != filename) && (*(p-1) == 32)) + p--; + *p = 0; /* chop off any trailing spaces */ +} + diff --git a/amiga/gfx.a b/amiga/gfx.a new file mode 100644 index 0000000..af5101f --- /dev/null +++ b/amiga/gfx.a @@ -0,0 +1,864 @@ + +* ---------------------------------------------- +* GRAPHICS ROUTINES FOR AMIGA YZIP +* ---------------------------------------------- + +*------------------------------* +* UncompH +*------------------------------* + +U_INB EQU 0 +U_OUTB EQU 4 +U_HTREE EQU 8 +U_PICX EQU 12 * pixel width +U_MLEN EQU 16 * after unhuff, before de-run +U_OLEN EQU 20 * "interrupt count" +U_FCALL EQU 24 * raised by caller, initially +U_LCALL EQU 25 * raised by callee, when done +U_REGS EQU 26 + +*** ULONG /*int*/ uncompress_huff (inbuf, outbuf, huff_tree, midlen, pic_x) +*** unsigned char *inbuf, *outbuf, *huff_tree; +*** ULONG midlen, pic_x; + +* FUNCTION UncompH (ucr: uncompRecPtr): LONGINT; + +* THERE ARE TWO NEW PARAMETERS: A FIRST-CALL FLAG AND AN INTERRUPT COUNT. +* AFTER AN INTERRUPT WE RETURN TO THE CALLER (SINCE THE NEXT STEP IS MODE- +* DEPENDENT). ALL PARAMS ARE NOW PASSED IN A RECORD, SO THEY WILL REMAIN +* VALID ACROSS MULTIPLE CALLS TO UNCOMPH. + +* THE OUTPUT BUFFER LENGTH MUST BE >= (U_OLEN + U_PICX + 128). + +* STEPS IN PICTURE DECOMPRESSION (undo in reverse order): +* 1. Each line of the picture is exclusive-or'ed with the previous line. +* 2. A run-length encoding is applied, as follows: byte values 0 +* through 15 represent colors; byte values 16 through 127 are repetition +* counts (16 will never actually appear) Thus: 3 occurrences of byte +* value 2 will turn into 2 17 (subtract 15 from the 17 to find that the +* two should be repeated 2 MORE times). +* 3. Optionally, the whole thing is Huffman-coded, using an encoding +* specified in the header file. + +* This routine does all three steps simultaneously--unhuf, then undo rle and +* xor steps. Stores extra line of 0s at beginning of outbuf, for xor step. +* Returns number of decompressed bytes. + +_UncompH + MOVEM.L D2-D7/A2-A4/A6,-(SP) * [40 BYTES] + MOVE.L 40+4(SP),A6 * PARAMBLOCK PTR + + TST.B U_FCALL(A6) * FIRST TIME THROUGH? + BEQ.S UNCHX4 * NO + CLR.B U_FCALL(A6) * YES, RESET FLAG + MOVEQ #0,D0 * [DEFAULT RETURN VAL] + +* LOAD REGS FROM PARAMBLOCK + +*** MOVE.L U_ILEN(A6),D1 * [INLEN -- NO LONGER USED] +*** BLE.S UNCHX9 * ERROR + MOVE.L U_MLEN(A6),D3 * "midlen" (AFTER dehuff, but BEFORE derun) + BLE.S UNCHX9 * ERROR + MOVE.L U_INB(A6),A4 * INBUF + MOVE.L U_HTREE(A6),A0 * HUFFTREE (256 BYTES MAX) + +* ZERO FIRST LINE OF OUTBUF + + MOVE.L U_OUTB(A6),A1 * OUTBUF(1) + MOVE.L A1,A2 + MOVE.L U_PICX(A6),D1 + BLE.S UNCHX9 * ERROR +UNCHX2 CLR.B (A2)+ * CLEAR OUTBUF(1), ADVANCE TO OUTBUF(2) + SUBQ.W #1,D1 + BGT.S UNCHX2 + + MOVE.L U_OLEN(A6),D1 + BLE.S UNCHX9 * ERROR + MOVE.L A2,A3 + ADD.L D1,A3 * OUTBUF(3) IS INTERRUPT POINT + + BSR UNCOMP * DIVE IN + BRA.S UNCHX9 +UNCHX4 BSR UNCOMP2 * CONTINUE + +UNCHX9 MOVEM.L (SP)+,D2-D7/A2-A4/A6 + RTS * RETURN RESULT (IN D0), 'C' STYLE + + +* FOR AMIGA, this table maps nibbles (0000 abcd) to bytes (abcd abcd), +* to facilitate 320 -> 640 scaling. Keep proximate to UNCOMP. + +NYBBYT DC.B $00,$11,$22,$33 + DC.B $44,$55,$66,$77 + DC.B $88,$99,$AA,$BB + DC.B $CC,$DD,$EE,$FF + +* DC.B $00,$03,$0C,$0F * map to (aabb ccdd) +* DC.B $30,$33,$3C,$3F +* DC.B $C0,$C3,$CC,$CF +* DC.B $F0,$F3,$FC,$FF + +*------------------------------* +* UNCOMP, UNCOMP2 +*------------------------------* + +* GIVEN +* A1 -> OUTBUF1 (PREV ROW) A2 -> OUTBUF2 A3 -> OUTBUF3 (END+1) +* A4 -> INBUF A6 -> PARAMS A0 -> HUFFTREE +* D3.L = MIDLEN [AFTER UNHUFF, BEFORE UNRUN] +* USES +* D4.B = INCHR D5.B = CBIT D7.L [not .B] = CNODE D6.B = LASTPIX +* D1.B = 16 D2.B = 128+16 +* RETURNS +* D0.L = #BYTES WRITTEN TO OUTBUF +* +* COMMENTED-OUT LINES BELOW REFLECT OPTIMIZATIONS FOR SPEED. + +UNCOMP MOVEQ #16,D1 + MOVE.B #128+16,D2 + MOVEQ #0,D7 * INIT CNODE + +UNCPX0 MOVEQ #7,D5 * RESET CBIT +*** MOVE.B #128,D5 + MOVE.B (A4)+,D4 * Get the next inchr + +* [innermost unhuff loop begins here -- 5 ops, 40 cycles] + +* Since the bit of interest runs from 7 down to 0, we can avoid an explicit +* bit test by shifting bits off the left end of the register, one at a time, +* into the Carry flag (Thanks Mike M). The fast way to shift a register +* left by one is to add it to itself. + +UNCPX1 ADD.B D4,D4 * IF (chr & cbit) SET X FLAG [4] + +* We can check the Carry flag but avoid an expensive branch by taking advantage +* of the ADDX instruction. Also, adding D7 to itself here eliminates the need +* to do it separately later. + + ADDX.B D7,D7 * cnode = (cnode * 2) + X [4] + MOVE.B 0(A0,D7.W),D7 * cnode = huff_tree[cnode] [14] + BMI.S UNCPX3 * if (cnode >= 128) IT'S A TERMINAL [8/] + +* We /could/ avoid this conditional branch by unrolling 8 iterations of the loop, +* but would then have to remember where to jump back in ... probably not worth it. + + DBF D5,UNCPX1 * cbit >>= 1 (next bit) [10/] [40 tot] + BRA.S UNCPX0 * if done with this char, go to next + + +* X21 ADD.B D4,D4 * IF (chr & cbit) SET X FLAG [4] +* ADDX.B D7,D7 * cnode = (cnode * 2) + X [4] +* MOVE.B 0(A0,D7.W),D7 * cnode = huff_tree[cnode] [14] +* BPL.S X22 * if (cnode >= 128) IT'S A TERMINAL [10/] [32 tot] +* BSR.B UNCPX3 * [18] [16 RTS] +* X22 ADD.B D4,D4 +* ADDX.B D7,D7 +* MOVE.B 0(A0,D7.W),D7 +* BPL.S X23 +* BSR UNCPX3 +* X23 etc + +* SLOWER METHOD(S), HERE FOR DOCUMENTATION ONLY ... + +* UNCPX1 +*** MOVE.B D4,D0 +*** AND.B D5,D0 +* BTST D5,D4 * IF (chr & cbit) [6] +* BEQ.S UNCPX2 * [8/10] +* ADDQ.B #1,D7 * [4] +* UNCPX2 +* MOVE.B 0(A0,D7.W),D7 * THEN cnode = huff_tree[cnode + 1] [14] +*** CMP.B #128,D7 * if (cnode < 128) +*** BCC.S UNCPX3 * BHS +* BMI.S UNCPX3 * [FLAG /ALREADY/ SET] [8/] +* ADD.B D7,D7 * THEN cnode *= 2; [4] +*** LSR.B #1,D5 +* SUBQ.B #1,D5 * cbit >>= 1 (next bit) [4] +* BPL.S UNCPX1 * bne * [10/] [56/58 tot] +* BRA.S UNCPX0 * if done with this char, go to next + +* [cnode >= 128] here we undo both runlength and xor + +UNCPX3 SUB.B D2,D7 * ELSE cnode -= (128+16) (this is a terminal) + BPL.S UNCPX4 +*** ADD.B #16,D7 + ADD.B D1,D7 * [RESTORE TO RANGE 0..15] + +*** SUB.B #128,D7 +*** CMPI.B #16,D7 * if (cnode < 16) +*** BCC.S UNCPX4 * BHS + +* It's a color id, output/xor it + +* AMIGA: map 0000abcd to aabbccdd, to facilitate 320 -> 640 scaling + MOVE.B NYBBYT(PC,D7.W),D7 + +*** MOVE.B (A1)+,(A2) * [SLOWER by 4 cycles!] +*** EOR.B D7,(A2)+ + MOVE.B (A1)+,D0 * *p++ = cnode ^ *outbuf++ + EOR.B D7,D0 + MOVE.B D0,(A2)+ + + MOVE.B D7,D6 * lastpix = cnode; + BRA.S UNCPX7 + +* Otherwise, run/xor LAST color id + +UNCPX4 +*** SUBI.B #15+1,D7 * for (j = 0; j < (cnode - 15); j++) +UNCPX5 MOVE.B (A1)+,D0 * *p++ = lastpix ^ *outbuf++ + EOR.B D6,D0 + MOVE.B D0,(A2)+ + DBF D7,UNCPX5 * [USES D7.W] + +UNCPX7 SUBQ.L #1,D3 * if (--midlen <= 0) break [DONE] + BEQ.S UNCPX15 + + CMPA.L A3,A2 * IF OUTLEN_INTERRUPT break + BCC.S UNCPX20 * BHS + +UNCPX8 MOVEQ #0,D7 * RESET cnode = 0 +*** LSR.B #1,D5 + SUBQ.B #1,D5 * cbit >>= 1 (next bit) + BPL UNCPX1 * bne * STILL IN RANGE 7..0 + BRA UNCPX0 * if done with this char, go to next + +* HERE FOR FINAL EXIT + +UNCPX10 MOVE.B #1,U_LCALL(A6) * TELL CALLER WE'RE DONE + RTS + +* HERE FOR SEMI-FINAL EXIT + +UNCPX15 CLR.L U_HTREE(A6) * "NO MORE TO DECOMPRESS/DERUN" +UNCPX16 MOVE.L A1,D0 + SUB.L U_OUTB(A6),D0 * #BYTES IN FINAL OUTBUF + +* BUT DID A LONG FINAL RUN EXCEED U_OLEN? (e.g. 1.5 x U_OLEN, OR 3 ROWS) + + CMP.L U_OLEN(A6),D0 + BLE.S UNCPX10 * NO, DONE + +* HERE FOR TEMPORARY EXIT + +UNCPX20 MOVEM.L D3-D6/A2-A4,U_REGS(A6) * SAVE OUR STATE + MOVE.L U_OLEN(A6),D0 * RETURN #BYTES IN FULL OUTBUF + RTS + +* HERE TO RESUME AFTER TEMPORARY OR SEMI-FINAL EXIT + +UNCOMP2 MOVEM.L U_REGS(A6),D3-D6/A2-A4 * RESTORE CRITICAL VARS + +* COPY LAST ROW OF BYTES, PLUS ANY OVERRUN, BACK TO THE BASE OF THE BUFFER, +* SO XOR WILL KEEP WORKING. COULD DO SLIGHTLY LESS WORK BY COPYING /EXACTLY/ +* ONE ROW'S WORTH TO /NEAR/ THE BASE, BUT COPYING THE EXTRA BYTES: +* - PREVENTS A PROBLEM IN THE (POSSIBLE) CASE OF OVERRUN > 1 ROW, AND +* - HELPS ENSURE BLOCKMOVE IS EVEN-ALIGNED. + + MOVE.L U_PICX(A6),D1 + MOVE.L U_OLEN(A6),D2 + + MOVE.L A3,A0 + SUB.L D1,A0 * SRC: LAST ROW + MOVE.L A0,A1 + SUB.L D2,A1 * DST: BUFFER BASE + MOVE.L A2,D0 + SUB.L A3,D0 + ADD.L D1,D0 * ROWBYTES, PLUS #BYTES OVERRUN + BSR MOVMEM + +* NOTE: FOR THE QUICKEST BLOCKMOVE, BOTH SRC AND DST MUST BE EVEN-ALIGNED. +* THIS MEANS THE CALLER SHOULD ENSURE THAT U_OLEN IS EVEN, WHETHER OR NOT +* U_PICX IS. + + SUB.L D2,A2 * RESET OUTBUF PTRS: 1ST ROW + EXTRA + MOVE.L A2,A1 + SUB.L D1,A1 * BASE + EXTRA + + MOVE.L U_HTREE(A6),D0 * RESTORE REMAINING REGS + BEQ.S UNCPX16 * IF ZERO, LAST EXIT WAS SEMI-FINAL + MOVE.L D0,A0 + + MOVEQ #16,D1 + MOVE.B #128+16,D2 + BRA.S UNCPX8 * PICK UP WHERE WE LEFT OFF + + +* ---------------------- +* QuadPic +* ---------------------- + +* PROCEDURE QuadPic (p: QuadPicRecPtr); +* This routine unpacks a sequence of color id bytes into an Amiga-format +* bitmap (multiple color planes). We assume id values between 0-15, and +* a 16-color bitmap (four planes). + +* >>> IDEA: during decompression, store /2/ data nibbles in each byte; +* 0000abcd --> aabbccdd. QuadPic can then automatically scale +* horizontally by 2x (320 --> 640). + +* We currently expect to work always with an integral number of rows, although +* not necessarily the entire screen. Return updated ptr in pDst. + +* Note: writing directly to screen memory would avoid the need for a 2nd +* offscreen buffer and two extra CopyBits (Blitter) calls; however: +* - Copybits handles non-byte-aligned destRects +* - Copybits handles clipping. +* - Copybits (b/w) is fast; even two extra calls don't really hurt us. + +* ALL PARAMS ARE NOW PASSED IN A RECORD, SO THEY WILL REMAIN VALID ACROSS MULTIPLE +* CALLS TO QuadPic. + +M_SRCX EQU 0 * color ids, 2 bytes/pixel +M_SRCY EQU 2 +M_FLAGS EQU 4 * 0001=TRANS, 0002=BUMPDEST, 0004=SCALE +M_DSTRB EQU 6 * rowBytes, per plane +M_PSRC EQU 8 +M_PDST1 EQU 12 * return [updated] ptrs here +M_PDST2 EQU 16 +M_PDST3 EQU 20 +M_PDST4 EQU 24 + +_QuadPic + MOVEM.L D2-D7/A2-A6,-(SP) * [44 BYTES] + MOVE.L 44+4(SP),A6 * PARAMBLOCK PTR + + MOVE.W M_SRCY(A6),D7 + BLE.S QDPCX9 + MOVE.W M_SRCX(A6),D6 + BLE.S QDPCX9 + +* CALC D6.W = SRC ROWLEN (BYTES)/4, ROUNDED UP (2 PIXELS/BYTE) + + MOVE.W D6,D0 + ASR.W #2,D6 * DIVIDE BY 4 + ANDI.W #$0003,D0 + BEQ.S QDPCX1 + ADDQ.W #1,D6 * ROUND UP + +QDPCX1 LEA M_PSRC(A6),A5 + MOVE.L (A5)+,A0 * UNLOAD REMAINING PARAMS + MOVE.L (A5)+,A1 + MOVE.L (A5)+,A2 + MOVE.L (A5)+,A3 + MOVE.L (A5)+,A4 + +QDPCX2 MOVEM.L D6-D7/A0-A4,-(SP) + BSR QuadRow + MOVEM.L (SP)+,D6-D7/A0-A4 + + ADD.W M_SRCX(A6),A0 * NEXT SRC (START OF ROW) + MOVE.W M_DSTRB(A6),D0 + ADDA.W D0,A1 * NEXT DST (START OF ROW) + ADDA.W D0,A2 + ADDA.W D0,A3 + ADDA.W D0,A4 + + SUBQ.W #1,D7 + BGT.S QDPCX2 * LOOP + + MOVE.W M_FLAGS(A6),D0 + BTST #0002,D0 * return updated dst ptrs? + BEQ.S QDPCX9 * NO + + LEA M_PDST1(A6),A5 + MOVE.L A1,(A5)+ + MOVE.L A2,(A5)+ + MOVE.L A3,(A5)+ + MOVE.L A4,(A5)+ + +QDPCX9 MOVEM.L (SP)+,D2-D7/A2-A6 + RTS * RETURN, 'C' STYLE + + +* QuadRow: UNPACK COLOR IDS (2-15) INTO MULTIPLE (4) PLANES +* ALSO HANDLE 0=TRANSPARENT, IF ENCOUNTERED + +* NOTE: IF THE ORIGINAL PIXEL WIDTH (320 MAX) WASN'T A MULTIPLE OF 4, +* QuadRow WRITES ENOUGH EXTRA (GARBAGE) PIXELS TO FILL OUT THE DST BYTE(S). +* WE CURRENTLY EXPECT SOMEBODY /ELSE/ TO CLIP THEM. + +* GIVEN A0 -> SRC, A1/A2/A3/A4 -> DST, +* D6.W = SRC ROWLEN (BYTES)/4, ROUNDED UP (2 PIXELS/BYTE) +* [ D5.L -> BITTAB ] +* USES D0.B = SRCPIX, D1/D2/D3/D4.B = DSTPIX +* [ D7.B = MASK, A5.L -> BITTAB (INDEXED) ] + +QuadRow + MOVE.W M_FLAGS(A6),D0 +*** BTST #0001,D0 +*** BEQ QuadRow2 * FASTER CASE IF NON-TRANSPARENT + + BTST #0004,D0 * USE 2 NIBBLES TO SCALE 2X? + BEQ QuadRow1x * NO + + BRA QDRWX9 * ENTER LOOP AT DBF + +* [VERSION 2 - HANDLES TRANS] +* INSTEAD OF INDEXING INTO LOOKUP TABLES, SHIFT BITS DIRECTLY FROM THE +* SRC ID INTO THE DST REGS. FOR A TRANSPARENT ID, JUST ROTATE THE DST REGS. + +* GET TRANSPARENT DEFAULTS (FOR NEXT 8/4 IDS) + +QDRWX0 MOVE.B (A1),D1 * [8] + MOVE.B (A2),D2 + MOVE.B (A3),D3 + MOVE.B (A4),D4 + +QDRWX1 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDRWX1A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + ADD.B D0,D0 * AND AGAIN (DUPLICATE PIXEL) + ADDX.B D1,D1 + ADD.B D0,D0 + ADDX.B D2,D2 + ADD.B D0,D0 + ADDX.B D3,D3 + ADD.B D0,D0 + ADDX.B D4,D4 + + BRA.S QDRWX2 * [64 + 10] + +QDRWX1A ROL.B #2,D1 + ROL.B #2,D2 + ROL.B #2,D3 + ROL.B #2,D4 * [40] + +QDRWX2 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDRWX2A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + ADD.B D0,D0 * AND AGAIN (DUPLICATE PIXEL) + ADDX.B D1,D1 + ADD.B D0,D0 + ADDX.B D2,D2 + ADD.B D0,D0 + ADDX.B D3,D3 + ADD.B D0,D0 + ADDX.B D4,D4 + + BRA.S QDRWX3 * [64 + 10] + +QDRWX2A ROL.B #2,D1 + ROL.B #2,D2 + ROL.B #2,D3 + ROL.B #2,D4 * [40] + +QDRWX3 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDRWX3A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + ADD.B D0,D0 * AND AGAIN (DUPLICATE PIXEL) + ADDX.B D1,D1 + ADD.B D0,D0 + ADDX.B D2,D2 + ADD.B D0,D0 + ADDX.B D3,D3 + ADD.B D0,D0 + ADDX.B D4,D4 + + BRA.S QDRWX4 * [64 + 10] + +QDRWX3A ROL.B #2,D1 + ROL.B #2,D2 + ROL.B #2,D3 + ROL.B #2,D4 * [40] + +QDRWX4 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDRWX4A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + ADD.B D0,D0 * AND AGAIN (DUPLICATE PIXEL) + ADDX.B D1,D1 + ADD.B D0,D0 + ADDX.B D2,D2 + ADD.B D0,D0 + ADDX.B D3,D3 + ADD.B D0,D0 + ADDX.B D4,D4 + + BRA.S QDRWX5 * [64 + 10] + +QDRWX4A ROL.B #2,D1 + ROL.B #2,D2 + ROL.B #2,D3 + ROL.B #2,D4 * [40] + +* [ ... AFTER 4 REPS OF THE ABOVE, WRITE OUT DST BYTES + +QDRWX5 MOVE.B D1,(A1)+ + MOVE.B D2,(A2)+ + MOVE.B D3,(A3)+ + MOVE.B D4,(A4)+ + +QDRWX9 DBF D6,QDRWX0 + RTS + +* CYCLES PER PIXEL PAIR = 16+74 (NON-TRANS), OR 18+40 (TRANS) +* R/W OVERHEAD, EVERY 4 PAIRS, = 64 (AVG 16 PER PAIR) +* >>>>>> TOTAL = 106 (NON-TRANS), OR 74 (TRANS) +* ADDITIONAL OVERHEAD: 2 BLITTER CALLS, MULTIPLE DECOMP/SHOW CALLS + +* -------------------- +* QuadRow1x +* -------------------- + +* IDENTICAL TO QuadRow, EXCEPT DON'T SCALE (IGNORE /LOW/ NIBBLES) + +QuadRow1x + BRA QDR1X9 * ENTER LOOP AT DBF + +* [VERSION 2 - HANDLES TRANS] +* INSTEAD OF INDEXING INTO LOOKUP TABLES, SHIFT BITS DIRECTLY FROM THE +* SRC ID INTO THE DST REGS. FOR A TRANSPARENT ID, JUST ROTATE THE DST REGS. + +* GET TRANSPARENT DEFAULTS (FOR NEXT 8 /*4*/ IDS) + +QDR1X0 MOVE.B (A1),D1 * [8] + MOVE.B (A2),D2 + MOVE.B (A3),D3 + MOVE.B (A4),D4 + +QDR1X1 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDR1X1A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + BRA.S QDR1X2 * [64 + 10] + +QDR1X1A ROL.B #1,D1 + ROL.B #1,D2 + ROL.B #1,D3 + ROL.B #1,D4 * [40] + +QDR1X2 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDR1X2A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + BRA.S QDR1X3 * [64 + 10] + +QDR1X2A ROL.B #1,D1 + ROL.B #1,D2 + ROL.B #1,D3 + ROL.B #1,D4 * [40] + +QDR1X3 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDR1X3A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + BRA.S QDR1X4 * [64 + 10] + +QDR1X3A ROL.B #1,D1 + ROL.B #1,D2 + ROL.B #1,D3 + ROL.B #1,D4 * [40] + +QDR1X4 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDR1X4A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + BRA.S QDR1X5 * [64 + 10] + +QDR1X4A ROL.B #1,D1 + ROL.B #1,D2 + ROL.B #1,D3 + ROL.B #1,D4 * [40] + +QDR1X5 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDR1X5A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + BRA.S QDR1X6 * [64 + 10] + +QDR1X5A ROL.B #1,D1 + ROL.B #1,D2 + ROL.B #1,D3 + ROL.B #1,D4 * [40] + +QDR1X6 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDR1X6A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + BRA.S QDR1X7 * [64 + 10] + +QDR1X6A ROL.B #1,D1 + ROL.B #1,D2 + ROL.B #1,D3 + ROL.B #1,D4 * [40] + +QDR1X7 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDR1X7A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + BRA.S QDR1X8 * [64 + 10] + +QDR1X7A ROL.B #1,D1 + ROL.B #1,D2 + ROL.B #1,D3 + ROL.B #1,D4 * [40] + +QDR1X8 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDR1X8A * TRANSPARENT ID, GOTO NEXT [10/8] + + ADD.B D0,D0 * WRITE PIXEL, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 * WRITE PIXEL, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL, 4TH PLANE + ADDX.B D4,D4 + + BRA.S QDR1X99 * [64 + 10] + +QDR1X8A ROL.B #1,D1 + ROL.B #1,D2 + ROL.B #1,D3 + ROL.B #1,D4 * [40] + +* [ ... AFTER 8 /*4*/ REPS OF THE ABOVE, WRITE OUT DST BYTES + +QDR1X99 MOVE.B D1,(A1)+ + MOVE.B D2,(A2)+ + MOVE.B D3,(A3)+ + MOVE.B D4,(A4)+ + +QDR1X9 DBF D6,QDR1X0 + RTS + + + +* ALTERNATE VERSIONS OF QUADROW ... + + IFEQ CZIP + +* [VERSION 3] + +* >>> IDEA: OPERATE ON 4 BYTES IN D1/D2.W +* REQUIRES THAT REGS BE UNPACKED BEFORE WRITING TO DST. + +* >>> IDEA: OPERATE ON 4 /WORDS/ IN D1/D2/D3/D4.W. +* REQUIRES THAT DST ROW(S) BE /WORD/ ALIGNED. + + +* [VERSION 2.5] +* >>> IDEA: USE AN EXTRA ASR (NOT ROR!) TO REPLICATE HIGH BIT (320 --> 640) +* XXX NO! MUST ALWAYS WRITE BITS LEFT-TO-RIGHT (SHIFT LEFT) + + +* [VERSION 2B - !TRANS] +* INSTEAD OF INDEXING INTO LOOKUP TABLES, SHIFT BITS DIRECTLY FROM THE +* SRC ID INTO THE DST REGS. + +QDRWX0 + +QDRWX1 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + + ADD.B D0,D0 * WRITE PIXEL-PAIR, 1ST PLANE [4] + ADDX.B D1,D1 + ADD.B D0,D0 + ADDX.B D1,D1 + ADD.B D0,D0 * WRITE PIXEL-PAIR, 2ND PLANE + ADDX.B D2,D2 + ADD.B D0,D0 + ADDX.B D2,D2 + + ADD.B D0,D0 * WRITE PIXEL-PAIR, 3RD PLANE + ADDX.B D3,D3 + ADD.B D0,D0 + ADDX.B D3,D3 + ADD.B D0,D0 * WRITE PIXEL-PAIR, 4TH PLANE + ADDX.B D4,D4 + ADD.B D0,D0 + ADDX.B D4,D4 + +* [ ... AFTER 4 REPS OF THE ABOVE, WRITE OUT DST BYTES + + MOVE.B D1,(A1)+ * [8] + MOVE.B D2,(A2)+ + MOVE.B D3,(A3)+ + MOVE.B D4,(A4)+ + + +* IF !TRANS, CYCLES PER PIXEL PAIR = 72 +* R/W OVERHEAD = 32 (AVG 8 PER PAIR) +* >>>>>> TOTAL = 80 +* ADDITIONAL OVERHEAD: 1 BLITTER CALL, ETC + + +* [VERSION 1 - HANDLES TRANS] +* GET BIT PATTERNS FROM CONSTANT TABLES, TO AVOID SHIFTING + +QDRWX0 MOVE.B (A1),D1 * [8] + MOVE.B (A2),D2 + MOVE.B (A3),D3 + MOVE.B (A4),D4 + +QDRWX1 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + BEQ.S QDRWX2 * TRANSPARENT ID, GOTO NEXT [10/8] + + MOVEQ #$7F,D7 * [4] +* MOVEQ #$3F,D7 + AND.B D7,D1 * ZERO THIS BIT [BIT PAIR] [4] + AND.B D7,D2 + AND.B D7,D3 + AND.B D7,D4 + +* (GIVEN D5 -> BASE OF 16x4 TABLE OF BITS [BIT PAIRS]) +* >>> PROBLEM: EACH BIT-PAIR NEEDS A DIFFERENT TABLE ... + + MOVE.L D5,A5 * [4] +* ADD.B D0,D0 * [PRE-SCALE IDS IN DECOMP] +* ADD.B D0,D0 + ADDA.W D0,A5 * [8] + + OR.B (A5)+,D1 * [8] + OR.B (A5)+,D2 + OR.B (A5)+,D3 + OR.B (A5)+,D4 + +* [ ... AFTER 4 REPS OF THE ABOVE, WRITE OUT DST BYTES + + MOVE.B D1,(A1)+ + MOVE.B D2,(A2)+ + MOVE.B D3,(A3)+ + MOVE.B D4,(A4)+ + + +* CYCLES PER PIXEL PAIR = 80 (NON-TRANS), OR 18 (TRANS) +* R/W OVERHEAD, EVERY 4 PAIRS, = 64 (AVG 16 PER PAIR) +* >>>>>> TOTAL = 96 (NON-TRANS), OR 34 (TRANS) +* ADDITIONAL OVERHEAD: 2 BLITTER CALLS, MULTIPLE DECOMP/SHOW CALLS + +* NOTE: 96 * 64000 = 6.1M (MAX) CYCLES PER SCREEN +* 68000 CLOCK RATE ~= 6M CYCLES/SEC + + +* [VERSION 1B - !TRANS] +* GET BIT PATTERNS FROM CONSTANT TABLES, TO AVOID SHIFTING + +QDRWX0 MOVEQ #0,D1 * [4] + MOVEQ #0,D2 + MOVEQ #0,D3 + MOVEQ #0,D4 + +QDRWX1 MOVE.B (A0)+,D0 * GET NEXT SRC PIXEL [PAIR] [8] + +* (GIVEN D5 -> BASE OF 16x4 TABLE OF BITS [BIT PAIRS]) +* >>> PROBLEM: EACH BIT-PAIR NEEDS A DIFFERENT TABLE ... + + MOVE.L D5,A5 * [4] +* ADD.B D0,D0 * [PRE-SCALE IDS IN DECOMP] +* ADD.B D0,D0 + ADDA.W D0,A5 * [8] + + OR.B (A5)+,D1 * [8] + OR.B (A5)+,D2 + OR.B (A5)+,D3 + OR.B (A5)+,D4 + +* [ ... AFTER 4 REPS OF THE ABOVE, WRITE OUT DST BYTES + + MOVE.B D1,(A1)+ * [8] + MOVE.B D2,(A2)+ + MOVE.B D3,(A3)+ + MOVE.B D4,(A4)+ + + +* IF !TRANS, CYCLES PER PIXEL PAIR = 52 +* R/W OVERHEAD = 48 (AVG 12 PER PAIR) +* >>>>>> TOTAL = 64 +* ADDITIONAL OVERHEAD: 1 BLITTER CALL, ETC + +* NOTE: 64 * 64000 = 4.1M CYCLES PER SCREEN +* 68000 CLOCK RATE ~= 6M CYCLES/SEC + + ENDC \ No newline at end of file diff --git a/amiga/gfx.c b/amiga/gfx.c new file mode 100644 index 0000000..eb2ff5e --- /dev/null +++ b/amiga/gfx.c @@ -0,0 +1,1085 @@ + +/************************************************************************ + + Amiga YZIP Graphics Routines + + July 5, 1988 version 1.0 by Clarence K. Din + Aug 29, 1988 GR.C working with DRIVE.C to display pictures + from the Shogun picture file... Revision 7 + Sept 26, 1988 GR.C memory error crashes fixed... Revision 8 + (very slow picture rendering; IFF will be used) + + 1-23-89 version 2.0 -- dbb + 4-13-89 added gh.scale, ge.picXD, qpr.flags + in ShowGFX, relaxed draw_offscrn criteria + +*************************************************************************/ + +#include "yzip.h" + +extern WORD first_row, last_row, /* bounds of current YZIP window */ + first_col, last_col; +extern WORD cur_col, cur_row; + +extern struct windowRec *curwp; +extern int Hirez; + +extern struct Remember *RememberKey; +extern struct Screen *ZScreen; +extern struct RastPort *ZRastPort; + + +#define NIL 0 +#define NOERR 0 /* our result convention for YZIP */ + +/* typedef unsigned short *UWptr; */ +/* typedef unsigned char *UBptr; */ + +#define MAXGFXCOLORS 16 /* current max number of colors */ +#define GFXPLANES 4 /* # bitplanes to support MAXGFXCOLORS */ + +#define GHEADLEN 16 /* length of master header */ +#define LBYTES 3 /* #length bytes at each dataOff */ + +/* Header flags... */ +#define HF_GDIR 1 /* file has a global directory */ +#define HF_EHUFF 2 /* dir entries include Huff ptrs (may be 0) */ +#define HF_GHUFF 4 /* file header includes global Huff ptr */ +#define HF_NOPAL 8 /* no palettes exist (Apple II) */ + +/* Entry flags... */ +#define EF_TRANS 1 /* picture uses color 0 (transparent) */ +#define EF_PHUFF 2 /* picture is huffman-coded */ +#define EF_XOR2 4 /* picture was XORed on alternate lines */ +#define EF_MONO 8 /* two-color picture */ + +#define EF_IFF 32 /* picture is IFFed */ + +/* PICSET stuff */ +/* Note: could instead get picset buflen from gfx_Header (adjusted for each + game), OR could set it arbitrarily large, based on available memory. */ + +#define PSMAXLEN 5*1024 /* default buflen */ +#define MAXITEMLEN 1024 /* prevent loading of "too big" pics */ +#define PSCRITLEN 256 /* abort picset loading if out of space */ + + +struct gHeader { /* master header info */ + UWORD fileID, + flags; + ULONG huffOff; + UWORD nPics, /* #pic entries in this file */ + ngPics, /* #pic entries in global file */ + dirEntryLen; + BOOL scale; /* if set, Amiga gfx scaled 2x horizontally */ + WORD initSuccess; /* flag set after inits */ +}; + +struct gEntry { /* directory info for current pic */ + UWORD picID, + picX, /* unscaled (320 max) */ + picY, + eFlags; + ULONG dataOff, + palOff, + huffOff; +/* additional fields for Amiga: */ + UWORD picXD, /* optionally scaled for display (640 max) */ + picYD; /* (same as picY) */ +}; + +struct gPalette { + ULONG palOff; /* the one currently installed */ +/** int palSize; **/ /* (these now locals) */ +/** char palData[16]; **/ +}; + +struct gHuffTree { + ULONG huffOff; /* the one currently loaded */ + char huffTree[256]; +}; + +struct gData { + ULONG minSize, /* fully compressed size */ + midSize, /* after dehuff, before derun */ + maxSize; /* fully decompressed size (expected) */ + char *pMin; /* (points into either gd or ps buffer) */ + +/* for the Amiga, a separate buffer is pre-allocated, big enough for the + entire (compressed) image, and with enough space leftover for + incremental decompression. */ + + char *buffer; + ULONG bufLen; +}; + +struct gPicset { /* picture buffering vars */ + char *basePtr; /* overall ptr; id stuff starts here */ + LONG baseLen; /* overall (allocated) len */ + WORD goodCount; /* #pics currently cached */ + + char *p; /* search results returned here */ + LONG len; + }; + +/*------------------------------*/ +/* gfx globals */ +/*------------------------------*/ + +int gchan; /* gfx file handle */ +UBYTE *pDir; /* gfx directory, in core */ + +/* this is a small buffer in Chip memory, for an incremental off-screen + bitmap (move into gData?) */ + +UBYTE *altPtr; +ULONG altLen; + +struct gHeader gh; +struct gEntry ge; +struct gPalette gp; +struct gHuffTree gt; +struct gData gd; +struct gPicset ps; + + +/*------------------------------*/ +/* utility calls */ +/*------------------------------*/ + +/* A handy routine to seek/read within the GFX file. + Return 0 if no error. */ + +int doRead (off, len, p) /* off == -1 means skip the seek */ +int off, len; char *p; +{ + int n; + + if (off != -1) { + n = Seek(gchan, off, -1); /* under 4.0, LSeek? */ + if (n < 0) return (-1); + } + + n = Read(gchan, p, len); + if (n != len) return (-1); + + return (0); /* no error */ +} + +int BAND (x,y) /* do a simple bitwise AND, Pascal-style */ +int x, y; +{ + return (x & y); +} + +int RoundUp (n) +int n; +{ + if (n & 1) + return(n+1); + else return(n); +} + +int RoundDown (n) +int n; +{ + if (n & 1) + return(n-1); + else return(n); +} + +/*------------------------------*/ +/* InitGFX */ +/*------------------------------*/ + +#define PICFILE "Pic.Data" +#define MINBUFLEN 25*1024; /* biggest pic ~20K?; extra for decomp */ +#define ALTBUFLEN 2*1024; /* 160 bytes per full 16-color line */ + +int InitGFX (start) +int start; +{ + ULONG dirLen; + UBYTE temp1[4]; /* buffer for reading Byte val(s) */ + UWORD temp2[4]; /* buffer for reading Word val(s) */ + +/** gh.initSuccess = 0; + pDir = 0; **/ /* (automatic) */ + + if (start) + { + /** gh.nPics = 0; **/ /* (default for PICINF) */ + + gchan = Open (PICFILE, MODE_OLDFILE); + if (!gchan) + return (-1); + + if (doRead (-1, 2, &temp1)) /* get id/flags */ + return (-1); + /** gh.fileID = temp1[0]; **/ /* (not used on Amiga) */ + gh.flags = temp1[1]; + + if (doRead (-1, 2, &temp2)) /* get global hoff, if any */ + return (-1); + gh.huffOff = 2 * temp2[0]; /* make byte offset */ + + if (doRead (-1, 4, &temp2)) /* get loc/ext pic count */ + return (-1); + gh.nPics = temp2[0]; + /** gh.ngPics = temp2[1]; **/ /* (not used on Amiga) */ + + + if (doRead (-1, 1, &temp1)) /* get dir entry size */ + return (-1); + gh.dirEntryLen = temp1[0]; + + /* alloc space for the directory, and read it in */ + /* (make sure c_getmem/RememberKey has been inited) */ + + dirLen = gh.nPics * gh.dirEntryLen; + pDir = (unsigned char *) c_getmem (dirLen); + if (!pDir) + return (-1); + if (doRead (GHEADLEN, dirLen, pDir)) + return (-1); + + /* alloc space for reading picfile (and incremental decompression) */ + + gd.bufLen = MINBUFLEN; + gd.buffer = (unsigned char *) c_getmem (gd.bufLen); + if (!gd.buffer) + return (-1); + + /* alloc small amount of Chip mem for off-screen bitmap */ + + altLen = ALTBUFLEN; + altPtr = (unsigned char *) AllocRemember ( + &RememberKey, altLen, MEMF_CHIP); + if (!altPtr) + return (-1); + + /** gp.palOff = 0; + gt.huffOff = 0; **/ /* (automatic) */ + + if (Hirez) gh.scale = TRUE; /* scale gfx 2x */ + gh.initSuccess = TRUE; /* "vital" inits completed */ + + /* show a splash screen if it exists (NOT IN SPEC) */ + /** opDisplay (1, 0, 0, 0); **/ + + /* and init picset stuff (a failure here is not fatal) */ + /* if error, just return basePtr NULL */ + + ps.baseLen = PSMAXLEN; + ps.basePtr = (char *) c_getmem (ps.baseLen); + ps.goodCount = 0; + } + else /* cleanup */ + { + if (gchan) { + Close(gchan); + gchan = 0; + } + + /* all mem (pDir etc) now freed thru RememberKey ... */ + } + return(0); +} + +/*------------------------------*/ +/* binary_search */ +/*------------------------------*/ + +/* search a directory for a given id [first word of each entry], + return ptr, or null if not found */ + +UWORD *binary_search (dir, e_count, e_size /*words*/, id) +UWORD *dir; +int e_count, e_size, id; +{ + register int top, bot, cur; + register int cid; + register UWORD *p; + + bot = 0; + top = e_count; + while (top > bot) { + cur = bot + ((top - bot) >> 1); /* DIV 2, round DOWN */ + p = &dir[cur * e_size]; + + if ((cid = *p) == id) + return (p); + + if (cid < id) + bot = cur + 1; + else top = cur; + } + return (0); +} + +/*------------------------------*/ +/* ReadGFXEntry */ +/*------------------------------*/ + +void doCopy (p1, p2, n) /* copy n bytes */ +register char *p1, *p2; int n; +{ + while (n-- > 0) *p2++ = *p1++; +} + +int ReadGFXEntry (id) +int id; +{ + UBYTE *pEnt; + + if (!gh.initSuccess) + return(-1); /* make sure picfile opened okay */ + + if (id == ge.picID) + return (0); /* same id as last time, done! */ + + pEnt = (UBYTE *)binary_search(pDir, gh.nPics, gh.dirEntryLen/2, id); + if (!pEnt) + return(-1); /* bad id */ + +/* Extract data from the directory buffer */ + + doCopy (pEnt, &ge.picID, 8); pEnt += 8; + +/** doCopy (pEnt, &ge.picID, 2); pEnt += 2; + doCopy (pEnt, &ge.picX, 2); pEnt += 2; + doCopy (pEnt, &ge.picY, 2); pEnt += 2; + doCopy (pEnt, &ge.eFlags, 2); pEnt += 2; **/ + +/* copy dataOff, palOff into 4-byte fields */ + + ge.dataOff = 0; + doCopy (pEnt, (UBYTE *)(&ge.dataOff) + 1, 3); pEnt += 3; + + ge.palOff = 0; + doCopy (pEnt, (UBYTE *)(&ge.palOff) + 1, 3); pEnt += 3; + + if (BAND (gh.flags, HF_EHUFF+HF_GHUFF) == HF_EHUFF) + { + ge.huffOff = 0; + doCopy (pEnt, (UBYTE *)(&ge.huffOff) + 2, 2); pEnt += 2; + ge.huffOff *= 2; + } + else ge.huffOff = gh.huffOff; + + if (gh.scale) + ge.picXD = ge.picX * 2; /* scaled up */ + else ge.picXD = ge.picX; + ge.picYD = ge.picY; + + return(0); +} + +/*------------------------------*/ +/* ReadGFXPalette */ +/*------------------------------*/ + +int ReadGFXPalette () +{ + UWORD palSize; + UBYTE palData[3*MAXGFXCOLORS], temp1[4]; + int c, n; + int firstId, lastId; /* color range to install */ + + if (ge.palOff && (ge.palOff != gp.palOff)) + { + if (doRead (ge.palOff, 1, &temp1)) /* read size byte */ + return (-1); + palSize = temp1[0]; /* (coerce) */ + + /* since gfx never uses colors 0-1, actual max size is 14 */ + if (palSize > MAXGFXCOLORS) + return (-1); /* should never happen */ + + if (doRead (-1, 3*palSize, &palData)) /* read in palette */ + return (-1); + + firstId = 2; /* gfx always skips 0-1 */ + lastId = firstId + palSize; /* (actually last+1) */ + if (lastId > MAXGFXCOLORS) + lastId = MAXGFXCOLORS; + +/** LoadRGB4(vp,&colortable[0],16); + SetAPen(ZRastPort,1); **/ /* ?? */ + + /* Install new colors. Note that Amiga takes only 4 bits each + for R-G-B. The picture file has 8 bits for each, so we use the + most-significant 4 (the low 4 are currently zeroes anyway). */ + + c = 0; + for (n=firstId; nViewPort), n, + palData[c+0] >> 4, /* pass 4 bits only */ + palData[c+1] >> 4, + palData[c+2] >> 4); + c+=3; + } + gp.palOff = ge.palOff; /* remember which palette this is */ + } + +/* also read new hufftree, if necessary */ + + if (BAND(ge.eFlags, EF_PHUFF)) /* is /this/ pic huffed? */ + if (gt.huffOff != ge.huffOff) /* tree already loaded? */ + { + if (doRead (ge.huffOff, 256, >.huffTree)) + return (-1); + + gt.huffOff = ge.huffOff; + } + + return (0); /* all okay */ +} + +/*------------------------------*/ +/* ReadGFXData */ +/*------------------------------*/ + +/* Read in (or find in PICSET) the data (compressed) for one picture. + We currently use a single large buffer, to avoid multiple disk hits. + It's preallocated, to guarantee we won't fail due to memory + fragmentation, etc. (On the Amiga, this buffer is not shared with the + alternate BitMap, since that must be "Chip" memory.) */ + +int ReadGFXData () +{ + if (searchPicset (ge.picID)) { /* first, check cache */ + gd.minSize = ps.len; + gd.pMin = ps.p; + } + else + { + /* read raw length bytes */ + + gd.minSize = 0; + if (doRead (ge.dataOff, LBYTES, ((UBYTE *)&gd.minSize)+1)) + return (-1); + + if (gd.minSize > gd.bufLen) + return (-2); /* buffer too small ... */ + + /* read in the compressed data ... */ + + /** gd.pMin = altPtr + (altLen - RoundUp (gd.minSize)); **/ + /** gd.pMin = altPtr; **/ /* [Amiga - altPtr for BM only] */ + gd.pMin = gd.buffer; /* use "home" buffer */ + + if (doRead (-1, gd.minSize, gd.pMin)) + return (-4); + } + +/* extract intermediate length bytes (present only for huffed data, which + we currently assume it always to be). These bytes /are/ included in + minSize. */ + + gd.midSize = 0; + doCopy (gd.pMin, ((UBYTE *) &gd.midSize)+1, LBYTES); + +/** gd.minSize -= LBYTES; **/ /* DON'T hack this */ + gd.pMin += LBYTES; /* hack the ptr */ + + return(0); +} + +/*------------------------------*/ +/* ShowGFX */ +/*------------------------------*/ + +/* incrementally decompress/display a picture */ + +struct uncompRec { /* this block passed to UncompH */ + UBYTE *inbuf, + *outbuf, + *huffTree; + ULONG picX, /* pixel width, unscaled [320 = full] */ + midSize, /* after unhuff, before derun */ + outLen; /* #valid output bytes to return this pass */ + UBYTE firstCall, /* raised by caller, initially */ + lastCall; /* raised by callee, when done */ + LONG saveRegs[16]; /* private storage for callee */ +}; + +struct quadpicRec { /* this block passed to QuadPic */ + UWORD srcX, /* color ids (2 dup pixels/byte) */ + srcY; + UWORD flags; /* 1=trans, 2=bumpDest, 4=scale */ + UWORD dstRB; /* rowBytes, pre plane */ + UBYTE *pSrc, + *pDst1, /* [updated ptrs returned here] */ + *pDst2, + *pDst3, + *pDst4; +}; + +struct BlitPicRec { /* this block passed to BlitPic */ + struct BitMap *altBM, + *screenBM; + int sizeX, /* src-dst sizes always equ (unlike Mac!) */ + sizeY, + offX, /* offset within (screen) bitmap */ + offY; +}; + + +int ShowGFX (ypos, xpos) +int ypos, xpos; /* absolutized */ +{ + struct BitMap *Zbm; +/* unroll vars */ + UWORD subRows, sr1, sr2; /* #rows handled per loop */ + UWORD picRB; /* rowBytes, per plane (Amiga: scaled 2x) */ + int draw_offscrn; +/* UncompH vars */ + struct uncompRec ucr; + ULONG uncompRet, max2; + int transFlag; +/* QuadPic vars */ + struct quadpicRec qpr; +/* BlitPic vars */ + struct BitMap bm; + struct BlitPicRec bpr; + ULONG planeBytes; /* total bytes, per plane */ + +/* For now we've stopped supporting the not-huffed case. If this becomes + a problem, need only create an UNCOMPNH based on UncompH. */ + + if (BAND (ge.eFlags, EF_PHUFF) == 0) + return (-1); + + if (BAND (ge.eFlags, EF_TRANS)) + transFlag = 1; + else transFlag = 0; + +/* Note: decompH prefers an even-aligned output buffer AND an even number + of rows. QuadPic might, for speed, require even-aligned input/output + buffers. The blitter, I think, doesn't care. */ + +/* SETUP FOR LOOP: */ + + Zbm = ZRastPort->BitMap; + +/* If we can draw directly into screen memory, we completely do away with + one (or two) blitter calls per increment. QuadPic can do so if no + shifting or clipping is required. (In practice, the only important case + of this is full screen pics.) */ + + draw_offscrn = TRUE; +/* [xpos is relative to ZWindow, whose Amiga x offset is always zero] */ + if (xpos & 0x0007 == 0) /* no (bit) shifting? */ + if (ge.picXD & 0x0007 == 0) /* no (bit) clipping? */ + if (xpos >= 0) + if (xpos + ge.picXD <= last_col) /* no game clipping? */ + if (ypos >= 0) + if (ypos + ge.picYD <= last_row) + if (Zbm->Depth == GFXPLANES) /* correct depth? */ + draw_offscrn = FALSE; + +/* (a) calc unroll increment */ + +/* calc decompH max output rows, in the unused tail end of gd.buffer. + (notice if data is in picset buf, gd.buffer is actually /all/ unused). + Allow 1 extra row for XOR, and up to 128 bytes for overruns. */ + + sr1 = (((gd.bufLen - gd.minSize) - 128) / ge.picX) - 1; + subRows = sr1; + + if (draw_offscrn) { + + /* calc QuadPic max output rows (rowbytes even, in case QuadPic + requires). + >>> compiler check -- be sure 2x mult not optimized away! <<< */ + + picRB = ((ge.picXD + 15) / 16) * 2; /* single plane */ + sr2 = altLen / (picRB * GFXPLANES); + + if (sr2 < sr1) /* use the smaller */ + subRows = sr2; + } + + if (subRows < 2) /* not enough space */ + return (-1); + + if (subRows >= ge.picY) { /* "small pic", do one-fell-swoop */ + subRows = ge.picY; + + /* if subRows > X, or gd.maxSize > (10K?), force to be incremental + (not now necessary, since gd.buflen is relatively small) */ + } + else { /* even, for UncompH */ + /** if (subRows >= 4 && !draw_offscrn) + /-* even this case looks a bit jerky *-/ + subRows = 4; + else **/ + subRows = 2; + + /* sr > 2 is faster, but less smooth ... If blitting, also want to + minimize flashing ... */ + /** subRows = RoundDown (subRows); **/ + } + +/* (b) setup uncompRec */ + + ucr.inbuf = gd.pMin; + ucr.outbuf = gd.buffer + RoundUp (gd.minSize); /* /tail/ end */ + ucr.huffTree = gt.huffTree; + ucr.picX = ge.picX; /* pixel width [320 = full] */ + ucr.midSize = gd.midSize; /* after unhuff, before derun */ + ucr.outLen = ge.picX * subRows; /* "interrupt count" */ + ucr.firstCall = 1; /* raised by caller, initially */ + ucr.lastCall = 0; /* raised by callee, when done */ + +/* (c) setup our bitmap, and BlitPicRec */ + + if (draw_offscrn) { + planeBytes = picRB * subRows; + + bm.BytesPerRow = picRB; + bm.Rows = subRows; + bm.Flags = 0; /* ? */ + bm.Depth = GFXPLANES; + bm.pad = 0; /* (in case ever defined) */ + bm.Planes[0] = altPtr; + bm.Planes[1] = bm.Planes[0] + planeBytes; + bm.Planes[2] = bm.Planes[1] + planeBytes; + bm.Planes[3] = bm.Planes[2] + planeBytes; + + bpr.altBM = &bm; + bpr.screenBM = Zbm; + bpr.sizeX = ge.picXD; /* sizeX is scaled */ + bpr.sizeY = subRows; + bpr.offX = xpos; + bpr.offY = ypos; /* /initial/ offY */ + } + +/* (d) setup QuadPicRec */ + + qpr.srcX = ge.picX; /* color ids (2 dup pixels/byte) */ + qpr.srcY = subRows; + + qpr.flags = 0; + if (transFlag) qpr.flags |= 0x0001; /* id 0 is transparent */ + if (gh.scale) qpr.flags |= 0x0004; /* scale 2x */ + + qpr.dstRB = picRB; /* rowBytes, per plane */ + qpr.pSrc = ucr.outbuf + ge.picX; /* skipping XOR row */ + +/* Notice that because of the way QuadPic unpacks bits from the high end, + we pass the bitplane ptrs in reversed order. */ + + qpr.pDst1 = bm.Planes[3]; + qpr.pDst2 = bm.Planes[2]; + qpr.pDst3 = bm.Planes[1]; + qpr.pDst4 = bm.Planes[0]; + + if (!draw_offscrn) { + qpr.flags |= 0x0002; /* bump Dst ptrs */ + qpr.dstRB = Zbm->BytesPerRow; + qpr.pDst1 = Zbm->Planes[3]; + qpr.pDst2 = Zbm->Planes[2]; + qpr.pDst3 = Zbm->Planes[1]; + qpr.pDst4 = Zbm->Planes[0]; + } + +/* TOP OF LOOP: */ + + max2 = 0; + while (!ucr.lastCall) { + +/* (1) decompress a few rows into (unused sect of) gd.buffer */ + + uncompRet = UncompH (&ucr); + max2 += uncompRet; + + if (ucr.lastCall) /* final chunk may have fewer rows */ + if (subRows < ge.picY) { /* unless only 1 pass */ + subRows = uncompRet / ge.picX; + + /* update derivative vars */ + qpr.srcY = subRows; + /** bm.Rows = subRows; **/ + bpr.sizeY = subRows; + } + +/* (2a) if in transparent mode, first copy screen to off-screen .. */ + + if (draw_offscrn && transFlag) { + if (BlitPic (&bpr, 0)) /* NOT toSBM */ + return; /* fell off screen, ABORT */ + + /* since the blitter is asynchronous and writes into the + same buffers that QuadPic will immediately read from, + must ensure that it finishes first! */ + + WaitBlit (); + } + +/* (2) unpack the rows (into off-screen bitmap, or directly to screen) */ + + QuadPic (&qpr); + +/* (3) blit the rows to the main screen */ + + if (draw_offscrn) { + if (BlitPic (&bpr, 1)) /* toSBM */ + return; /* fell off screen, ABORT */ + + bpr.offY += subRows; /* next increment */ + } + } +/** end of loop **/ + +/** if (max2 != ge.picX * ge.picY) **/ + /* (error, but ignore -- nothing more to be done!) */ + + return(0); +} + +/*------------------------------*/ +/* BlitPic */ +/*------------------------------*/ + +/* This routine uses the Amiga's hardware blitter to copy bits to OR from + the screen. Return an error if /entire/ image got clipped. + + The blitter does two things that would be painstaking for us to do + (in QuadPic), and probably slower too: + - moves an image to an arbitrary pixel alignment + - clips an image to an arbitrary pixel width + + In certain situations that don't require the above capabilities (such as + when drawing a full-screen pic), QuadPic can output directly to screen + memory, completely bypassing the alternate bitmap and this blitter + call (1 or 2 per increment). */ + +int BlitPic (bp, toSBM) +register struct BlitPicRec *bp; +int toSBM; /* if FALSE, to altBM */ +{ + int maxX, maxY; /* space between offset and window bounds */ + int sX, sY, oX, oY; /* local copies, for clipping & hacking */ + +/* DON'T hack the vertical offset to take into account the screen's + Title bar. */ + + oX = bp->offX; + oY = (bp->offY) /* + Peek1*/ ; /* 12 or whatever */ + sX = bp->sizeX; + sY = bp->sizeY; + +/* Since BltBitMap internally performs NO bounds checking, we must + clip carefully (we check the screen rect only; our alternate-screen + rect should always be valid). + We actually clip to the current YZIP window (per the spec). This + /should/ always lie within the physical screen/window (the kernel + ensures this). */ + + maxX = last_col - (bp->offX); + maxY = last_row - (bp->offY); /* (note: no Peek1 ...) */ + + if (sX > maxX) sX = maxX; + if (sY > maxY) sY = maxY; + + if (sX <= 0 || sY <= 0) + return (-1); /* don't pass BltBitMap neg OR 0 */ + + if (toSBM) + BltBitMap ( /* (return val not useful; ignore) */ + bp->altBM, 0, 0, + bp->screenBM, oX, oY, + sX, sY, + 0x00C0, /* logic function = "std copy" */ + 0x00FF, /* "all bitplanes" */ + altPtr /* >>> "dummy" ptr to Chip mem <<< */ + ); + else /* just reverse first 6 args */ + BltBitMap ( + bp->screenBM, oX, oY, + bp->altBM, 0, 0, + sX, sY, + 0x00C0, /* logic function = "std copy" */ + 0x00FF, /* "all bitplanes" */ + altPtr /* >>> "dummy" ptr to Chip mem <<< */ + ); + + return (0); + +/*** if (BAND (ge.eFlags, EF_TRANS)) + mode = 0x60; /-* "transparent mode" (??) *-/ + else mode = 0xC0; + + ClipBlit (offrp, 0, 0, + ZRastPort, xpos, ypos, + ge.picXD, ge.picYD, mode); ***/ +} + +/*------------------------------*/ +/* opDisplay */ +/*------------------------------*/ + +/* position given in pixel units, 0-origin, relative to current window */ +/* (result for debugging only, not used by 68K) */ + +int /*void*/ opDisplay (id, ypos, xpos, erase) +WORD id, ypos, xpos, erase; +{ + WORD gc; + WORD y2, x2; /* for Erase */ + +/* -2 (after 0-origining) means only read palette (NOT IMPLEMENTED) */ + +/* if we get a negative coordinate, don't suppress the pic, just display + it at 0,0 (clipped if necessary) */ + + /* if (ypos < -1 || xpos < -1) + return (-1); */ + if (ypos < -1) ypos = 0; + if (xpos < -1) xpos = 0; + +/* -1 (after 0-origining) means use cursor position */ + + if (ypos == -1) + ypos = cur_row; + else ypos += first_row; + + if (xpos == -1) + xpos = cur_col; + else xpos += first_col; + +/* call this BEFORE (Erase or) any dy/dx references */ + + if (ReadGFXEntry (id) != NOERR) + return (-2); + +/* this Erase call is used in YZT and Arthur */ + + if (erase) + { + /** EraseGFX (ypos, xpos); **/ + + y2 = ypos + ge.picYD; + x2 = xpos + ge.picXD; /* scaled */ + + if (y2 > last_row) y2 = last_row; /* clip to cur wind */ + if (x2 > last_col) x2 = last_col; + + erase_rect (ypos, xpos, y2, x2); + return (0); + } + + if (ReadGFXPalette () != NOERR) + return (-3); + else { + if (ReadGFXData () != NOERR) + return (-4); + else { + ShowGFX (ypos, xpos); + + /* if drawn successfully and in a scrolling window, + store a "gfx scroll-away count" */ + + if (curwp) + if (curwp->attr & WFSCRL) { + gc = ypos + ge.picYD; /* absolute bot */ + if (gc > last_row) + gc = last_row; /* [clipped] */ + gc -= first_row; /* re-relativize */ + + /* avoid storing if another gfx already below us! */ + if (curwp->gcnt < gc) + curwp->gcnt = gc; + } + } + + } + + return(0); +} + +/*------------------------------*/ +/* opPicInf */ +/*------------------------------*/ + +/* Fill in the given table [2 WORDS] with size (in pixels) of the given + picture. If invalid id, return a negative result. */ + +int opPicInf (id, tbl) +WORD id, *tbl; +{ + if (id == 0) + { + tbl[0] = gh.nPics; /* highest (?) id */ + return(0); + } + + if (ReadGFXEntry (id) == NOERR) + { + tbl[0] = ge.picYD; + tbl[1] = ge.picXD; /* [Amiga - always scaled] */ + return (0); + } + else /* failed */ + { + tbl[0] = 16; /* but, return some defaults */ + tbl[1] = 16; /* for games that don't trap */ + return (-1); + } +} + +/************************************************************************ + Picset support +************************************************************************/ + +/*------------------------------*/ +/* psRead */ +/*------------------------------*/ + +/* read data for given id into buffer at p, if enough space available. + return data length, or -1 if error, -2 if space critically low */ + +LONG psRead (id, p, avail) +WORD id; char *p; LONG avail; +{ + LONG ilen; + +/* get dataOff (write new routine? this one does some extra work) */ + if (ReadGFXEntry (id)) + goto PSRERR; + +/* read length bytes for the (compressed) data */ + ilen = 0; + if (doRead (ge.dataOff, LBYTES, ((UBYTE *) &ilen) + 1)) + goto PSRERR; + +/* since our buffer is relatively small, we reserve it for smaller pics */ + if (ilen > MAXITEMLEN) + goto PSRERR; + + if (ilen > avail) { /* not enough room */ + if (avail > PSCRITLEN) + goto PSRERR; /* (but do keep trying) */ + + /* space is critically low; since no more pics are likely to fit, + avoid further disk hits */ + /** goto PSRERR2; **/ + return (-2); + } + +/* read (compressed) data into the picset buf */ + if (doRead (-1, ilen, p)) + goto PSRERR; + + return (ilen); /* all okay */ +PSRERR: + return (-1); +} + +/*------------------------------*/ +/* getPicset */ +/*------------------------------*/ + +/* Preload the requested set of pics (or as many as will fit) + + Note: PICSET currently caches /compressed/ picture data, trading off + space against display speed (would reverse this to do animation, + for example). Also, palette data is not touched by the caching. This + is okay for small pics that share someone else's palette. + + The format of the info at basePtr is as follows (every psEntry may not + be used): + - an array of psEntry's + - raw data +*/ + +struct psEntry { /* one entry for each pic in the set */ + WORD id; + char *data; /* (absolute) start of data */ + LONG len; /* data length (in bytes) */ + }; + +VOID getPicset (tbl, count) +WORD *tbl; WORD count; /* #pics in table */ +{ + register struct psEntry *curEntry; + char *curBase; + WORD curId; + LONG headerLen, curSize, avail; + + if (!ps.basePtr) /* valid buffer? */ + return; + ps.goodCount = 0; + curEntry = (struct psEntry *) ps.basePtr; /* initial entry */ + + headerLen = sizeof(struct psEntry) * count; + curBase = ps.basePtr + headerLen; + + avail = ps.baseLen - headerLen; /* space remaining at curBase */ + if (avail <= 0) + return; + + while (count-- > 0) { + /* get next id in set */ + curId = *tbl++; /* now guaranteed even-aligned... */ + + curSize = psRead (curId, curBase, avail); + if (curSize >= 0) { + curEntry->id = curId; + curEntry->data = curBase; /* data ptr */ + curEntry->len = curSize; /* length (bytes) */ + + /* keep curBase even aligned, for max I/O speed */ + curSize = RoundUp (curSize); + curBase += curSize; + avail -= curSize; + + ps.goodCount++; + curEntry += 1; /* skip to next entry */ + } + else + /* if error, nothing written into header */ + { + /* if (debug) [beep]; */ + + if (curSize == -2) + count = 0; /* abort loop */ + } + } +} + +/*------------------------------*/ +/* searchPicset */ +/*------------------------------*/ + +/* Check the current picset for the given id; + return True if found (and return ptr/len in globals) */ + +int /*BOOL*/ searchPicset (targId) +WORD targId; +{ + register struct psEntry *curEntry; + WORD n; + + if (!ps.basePtr) + return (FALSE); + + n = ps.goodCount; /* # cached pics */ + curEntry = (struct psEntry *) ps.basePtr; + + while (n-- > 0) { + if (curEntry->id == targId) /* found it, return info */ + { + ps.p = curEntry->data; + ps.len = curEntry->len; + + return (TRUE); /* success */ + } + else + curEntry += 1; /* skip to next entry */ + } + return (FALSE); +} diff --git a/amiga/intuition.bugs b/amiga/intuition.bugs new file mode 100644 index 0000000..540ae28 --- /dev/null +++ b/amiga/intuition.bugs @@ -0,0 +1,86 @@ + +Amiga problems/bugs +----------------------------------------------------------------- + + [] RAW Input Events + +I sometimes get unrequested "RAW Input Event" messages from the +Console Device (8 number fields, separated by semicolons). +Unrequested, meaning that my program never sent a "{" +message. It's a problem since my program doesn't normally try to +intercept such a message, and it appears on the screen as garbage. + +The unrequested message seems to be triggered by switching the active +window, from mine to another then back to mine. + +The first of the 8 numbers (event class) is usually 17 or 18. +The list I have of event classes only goes as high as 16. + +Once, I got a message starting with 16 ("disk inserted"). On that +occasion, a disk had been inserted in the process of launching my +program. + +WORKAROUND -- sending two messages to the console device during my +program initialization seems to fix the problem. Messages are "16}" +and "17}". + + ---- + + [] AmigaDOS alerts + [] CloseWorkBench (), OpenWorkBench () + +My program opens a custom screen, and the Open and Close Workbench calls +normally work as they were intended to. However, if something my program +does triggers an AmigaDOS alert box ("insert disk X", "disk X full", etc), +the box does not appear in my screen. Rather it opens a blank Workbench +screen (no disk icons, no menus) and draws the box there. + +The blank Workbench screen never goes away. When my program calls +OpenWorkBench just before terminating, the Workbench screen still shows no +disk icons. The user is left with a blank Workbench screen and must +reboot the machine. + +WORKAROUND -- none known, just don't ever CloseWorkBench (). + + ---- + +On the phone, I brought up a more general problem with AmigaDOS +alerts. The alert box always appears in the Workbench screen, even if +that screen is hidden by my custom screen. Alerts should appear +either on top of everything, or (preferably) on top of everything in +the screen of the program that caused them. + +WORKAROUND -- a dirty fix, but avoid opening a full-size custom +screen. Alert boxes seem to always appear at the very top of the +Workbench screen. If the top of the Workbench peeks through, then the +user at least has a chance to notice the alert box. + +A related problem -- when a screen is less than full-size, it is +possible to slide it completely off the bottom of the display (must first +slide the mouse pointer off the top of the screen). The screen cannot +be recovered. + + ---- + + [] Seek (), Read () + +The AmigaDOS Seek routine is very slow. My program reads constantly +from a data file which can be entirely loaded into memory, if space allows, +or randomly accessed off disk. In the second case, Read () seems +acceptably fast but Seek () seems to causes excessive disk head motion. + +One special situation where Seek () should cause NO head motion, but +does, is when the current file position is already correct. + +WORKAROUND -- for the special case, just keep track of the current +file position yourself, and avoid unnecessary calls to Seek (). + + ---- + + [] Low-memory errors + +When free memory is low, attempting to resize a window frequently +crashes the system. Attempting to DISCARD a file, too. + +WORKAROUND -- none known + diff --git a/amiga/kermit.doc b/amiga/kermit.doc new file mode 100644 index 0000000..3b6412d --- /dev/null +++ b/amiga/kermit.doc @@ -0,0 +1,265 @@ +INTRODUCTION + +This version of Amiga Kermit is a port of the Unix C-Kermit which attempts +to reproduce as much of the functionality of Unix version as possible. I +had two main goals in porting C-Kermit: I wanted a reliable remote file +transfer utility, and I wanted to investigate the use of the AmigaDOS +and Exec environments, hopefully adding to level of publicly held Amiga +programming knowledge. + +Amiga Kermit currently provides a line oriented user interface. I am not +a mouse and menu fanatic, but I have seen many programs which have been +considerably enhanced by their use. There are several places in Kermit +where a menu interface would be an asset. However, in this version of +Kermit, I have concentrated on the functional aspects. + +As I have stated before, this is a port of the Unix C-Kermit. The file +ckuker.doc contains detailed documentation on the use of C-Kermit, and +Kermit's internal help can be used as a reference too. The main +difference between this version and the Unix C-Kermit is that the DIAL +and SCRIPT commands are as yet unimplemented. Therefore, only Amiga +specific features are noted below. + +INVOKING C-KERMIT + +Amiga Kermit is usually invoked from a CLI process. Currently unresolved +problems will cause it to crash under the Workbench, see ckiker.bwr for +details. From a CLI window, you generally enter: + KERMIT +or + RUN KERMIT +to execute Kermit and start up the Kermit command interpreter. Kermit +will create its own window and greet you with: + + C-Kermit, 4D(060) 18 Apr 86, Commodore Amiga + Type ? for help + + C-Kermit> + +The cursor will appear following the C-Kermit> prompt. Typing ? will +produce a list of the items that can be entered at any point. Typing ? +here will produce a list of commands: + + C-Kermit>? Command, one of the following: + ! bye close connect + cwd dial directory echo + exit finish get help + log quit receive remote + script send server set + show space statistics take + +Typing ? at various points during command entry will help you navigate +through the command processor. The 'help' command is also quite useful. +Typing 'help' alone gets information about command entry: + + C-Kermit>help + + Type ? for a list of commands, type 'help x' for any command x. + While typing commands, use the following special characters: + + DEL, RUBOUT, BACKSPACE, CTRL-H: Delete the most recent character typed. + CTRL-W: Delete the most recent word typed. + CTRL-U: Delete the current line. + CTRL-R: Redisplay the current line. + ? (question mark) display help on the current command or field. + ESC (Escape or Altmode) Attempt to complete the current field. + \ (backslash) include the following character literally. + + From system level, type 'kermit -h' to get help about command line args. + +but 'help' can be used with command lines to get command descriptions. For +example: + + C-Kermit>help bye + Shut down and log out a remote Kermit server + +The Kermit command processor is normally exited with the 'QUIT' command. +During Kermit protocol, you can type CTRL-C or CTRL-D to interrupt and +exit Kermit. Depending on the version of the C runtime libraries used +to link Kermit, the interrupt may also be active during command input, but +it is disabled during connect mode. You will get a requestor when the +interrupt is activated to allow you to choose to continue Kermit. However, +any serial read or write that was interrupted will still be aborted. + +Kermit can also be used without the command processor by specifying an +action on the command line. You can enter 'kermit -h' at the CLI prompt +to get a list of command line options. However, unless input is redirected, +or the -q (quiet) option is specified, Kermit will still create a window +for protocol monitoring and interruption. 'KERMIT <*' can be used to +run Kermit completely within the CLI window; however, this does not allow +you to enter control characters, and no console input is seen until you +enter return. Input and output can be redirected to files to take advantage +of C-Kermit command line file transfer options. Unfortunately, AmigaDOS +does not implement pipes (yet). + +KERMIT SERIAL INITIALIZATION AND SETTINGS + +Amiga Kermit uses the serial device. Three sources are used to initialize +the serial parameters. First, the default serial configuration, as set by +Preferences, is copied. This includes baud rate, and under version 1.2 of +the Workbench, parity, modem control (7-wire vs. 3-wire), and flow control. +Second, command line parameters can be used to override these settings. +For example: + kermit -b 1200 -p e +can be used to select 1200 baud and even parity independently of the +Preferences settings. Finally, if the command processor is used, Kermit +looks for a ".kermrc" initialization file, first in the "s:" directory, then +in the current directory, providing that the disk containing each directory +is present in the Amiga. The ".kermrc" file contains C-Kermit commands +which can be used to initialize the C-Kermit environment as desired. + +Amiga Kermit has certain peculiarities about its settings. The line is +always 'serial.device', the name of the device driver being used, and Kermit +will not allow you to 'SET LINE' to anything else. The modem control mode +is currently selected by 'SET MODEM type', which has two choices: 'DIRECT', +for 3-wire control, and 'GENERIC', for 7-wire control. Because of the way +the serial device operates, this setting only has an effect when the serial +device is opened after previously being closed, which occurs only when +Kermit starts or after 'H' is used to hang up and exit connect mode. + +Kermit allows you to set any baud rate between 110 and 292000 baud; however, +it will complain if the baud rate is nonstandard (I added this feature after +several attempts to use my modem at 12000 baud). Rates of 110 and 111 baud +are implemented as 112 baud. Extremely high baud rates are of limited +utility. Rates above 38400 baud can be used for connect mode, but they +result in high error retry rates during data packet transfer and require +good cabling (plus who can you talk to at 57600 baud?). Because +of protocol overhead, 38400 baud between two Amigas will get an effective +transfer rate of less than 6000 baud (still two times faster than a 1541 +disk drive). Also, if a break is sent looped back to the Amiga while +the serial device is set to a very high baud rate (>100K baud), the Amiga +will hang up, apparently overwhelmed by framing errors. + +Amiga Kermit uses the serial device in shared mode. This allows other +programs, like dialers, to use the serial line at the same time, without +exiting Kermit. However, to avoid confusion, Kermit should not be in +connect, server, or file transfer mode while another program is active. +Note that Kermit always does its own parity generation and stripping, so +it always sets the serial device to use eight bit characters with no parity. + +WILDCARDING + +Both the SEND command invoked from the Amiga and a GET sent to an Amiga +in server mode use allow wildcarding, but in the Unix style. Thus, '*' +wildcard matches an arbitrary string while '?' matches an arbitrary +character. Therefore, to get all the C source files which begin with 'cki' +from the Amiga server, you could use the command: + + C-Kermit>GET cki*.c + +Multiple '*' wildcards can be used in a pattern; however, beware that +most Unix C-Kermit's may not completely support this form. Also, the +wildcarding that is used in local and remote server commands that invoke +AmigaDOS commands is the AmigaDOS form. + +LOCAL AND REMOTE COMMANDS + +Amiga Kermit provides several ways to invoke AmigaDOS commands from within +Kermit. Entering '!' at the Kermit prompt will create a CLI process running +in its own window, and wait for it to terminate. The form '! command' will +invoke the given command command with its output going to Kermit's window. +However, there is currently no way to pause the output of commands invoked +this way, other than the stopgap use of the right mouse button. The form +'REMOTE HOST command' can be sent to the Amiga server to execute the given +command remotely on the Amiga. There is also no input stream available for +commands invoked in either the '! command' or 'REMOTE HOST command' forms, +which can cause problems with some commands that expect input. + +In addition to the methods given above, various AmigaDOS commands are +invoked by local Kermit commands, and generic remote commands. These +are listed below: + + AmigaDOS command Local command Remote generic command + DELETE files --none-- REMOTE DELETE files + TYPE files --none-- REMOTE TYPE files + INFO SPACE REMOTE SPACE + LIST obj DIRECTORY obj REMOTE DIRECTORY + STATUS --none-- REMOTE WHO + +Any parameters to these commands are expected to use AmigaDOS conventions, +including AmigaDOS wildcarding. Note that in order to pass a '?' through +the C-Kermit command processor, it must be prefixed with a '\'. + +You can change the current directory of the Kermit process locally with the +CWD command and remotely with REMOTE CWD. The local CWD command prints +out the name of the current directory afterwards. If no new directory +is given, the current directory is not changed, so CWD alone can be used +to determine where the current directory is. + +SERVER MODE + +Amiga Kermit completely implements server mode, including the ability +to execute CLI commands remotely. Currently CLI commands are executed +with their standard output directed to RAM:PIPE-HOLDER, which is then +written back to the commanding Kermit after the command completes. + +There are a few limitations on the commands that can be executed remotely. +First of all, if they produce voluminous output, the output should be +redirected (redirection is supported on the REMOTE HOST command line) +to avoid using all free memory for the output file. However, the +commanding Kermit will probably timeout in the middle of the execution +of any such command. The best way to use these commands is to + REMOTE HOST RUN command >outfile parameters +then use REMOTE WHO (which invokes STATUS) to monitor the command for +completion. + +The input stream for remote commands is NIL:, which is not handled +intelligently by all Amiga commands. For example, 'REMOTE HOST diskcopy +df0: to df1:' hangs indefinitely while waiting for NIL: to press return. +Finally, since each command is executed in a separate CLI, commands that +set unshared process parameters, like 'cd', will have null effect (but +'REMOTE CWD dir' can be used instead). + +While server mode is active, AmigaDOS requestors are disabled. This +avoids requiring operator intervention to reset a requestore when the Amiga +server is told to use a file on a disk that does not exist or is write +protected. However, disabled requestors are currently not inherited by the +CLI processes that the server creates to execute remote commands. +Therefore, a remote AmigaDOS command can still cause the server to become +hung. + +To shut down the Amiga server, enter BYE or FINISH at the commanding +Kermit. FINISH exits to whatever level the server was invoked from, +while BYE exits Amiga Kermit altogether. + +CONNECT MODE + +Connect mode on Amiga Kermit currently provides you with a 23 line by +77 column screen. The Amiga console device is used to provide almost +ANSI terminal emulation. While you are in connect mode, you can give +single character commands which are prefixed by an escape character +which can be set from within C-Kermit. By default, the escape +character is CTRL-\. You can use 'H' to close the serial device +and exit connect mode, which makes the DTR line drop causing most modems +to hang up the phone line. + +In addition to the standard connect mode commands, extra logging control +has been added. If a session log file is open, the 'Q' sequence +allows you to temporarily suspend logging. The 'R' sequence +resumes logging if it has been suspended. + +Features have also been added to prevent deadlocks while in connect mode +due to spurious XOFF's or bad modem control line states. When connect +mode is unable to send serial output, keyboard characters are queued until +they can be transmitted. Queuing continues as long as space is available +in the output buffer. If the buffer, which is 64 characters long, fills up, +the next keyboard input is discarded and the display 'beeps'. To get out +of a deadlock situation, you can either exit connect mode, or send a break. +In either case, the output queue is flushed, and current serial output +character is given one second to finish transmitting. If it does not +complete, the output is aborted, and XOFF mode reset as appropriate. Then +connect mode is exited or a break is sent, as specified. When output +characters are queued, connect status (accessed by 'S') will +indicate the number of queued output characters. + + +I hope that you find Kermit a useful. If you have problems or suggestions +related to Amiga Kermit, please contact me at the address below. I will +be continuing to enhance Amiga Kermit, so new versions will be available +from time to time. + +Jack J. Rouse +106 Rubin Ct. Apt. A4 +Cary, NC 27511 +(919) 467-8000 (work) +(919) 481-1395 (home) diff --git a/amiga/patches.bugs b/amiga/patches.bugs new file mode 100644 index 0000000..7da0e62 --- /dev/null +++ b/amiga/patches.bugs @@ -0,0 +1,64 @@ + +PATCHES TO AMIGA-SUPPLIED INCLUDE FILES +============================================================================== + +[] Workbench/Workbench.h +------------------------------ + +WAS + enum WBObjectType wo_type; + + (in struct DiskObject) + +PROBLEM + Amiga expects this field in the icon data file to be 16 bits wide, + but Lattice 68K treats type "enum" as 32 bits. + + Assignments to subsequent fields end up mis-aligned. + +FIX + short dummy; + + +[] Exec/Types.h, Exec/IO.h +------------------------------ + +WAS + typedef unsigned char *STRPTR; /* string pointer */ + typedef STRPTR *APTR; /* absolute memory pointer */ + +PROBLEM + Exec/IO.h defines a structure IOStdReq, which contains the field + io_Data, of type APTR. + + My routine "write_console" calls DoIO (IOStdReq), with the io_Data + field holding a pointer to the text buffer. (It's not a pointer to + a pointer, as implied by the typedef). + + If the buffer starts at an odd address, the compiler generates code + to round down the pointer. Ouch. + +FIX + typedef unsigned char *APTR; /* absolute memory pointer */ + +BETTER FIX (10/30) + + In Exec/IO.h, define a new structure IOStdReq_MUNGED. The io_Data + field is of type STRPTR. Use this structure for AmigaZIP globals. + + +[] Workbench/Workbench.h +------------------------------ + +WAS + UWORD woIconDisk:1; + + (four fields of this form, in struct WBObject) + +PROBLEM + Didn't compile. + +FIX + UWORD woIconDisk; + + diff --git a/amiga/production.info b/amiga/production.info new file mode 100644 index 0000000..d841c2d --- /dev/null +++ b/amiga/production.info @@ -0,0 +1,31 @@ + +How to make a master Amiga game disk +-------------------------------------------------------------------- + +Notes: When removing a disk from an Amiga disk drive, always wait +several seconds and watch the red access light to make sure the system +is done with it. + +Under AmigaDOS (the CLI or Command Line Interpreter), the internal drive +is "df0:" and the external is "df1:". + + +1. Make a copy of the Amiga Create disk. It's not necessary to format + the blank disk, as this happens automatically. + + The copy can be done within CLI by typing "diskcopy from df0: to df1:" + and following the prompts, or from Workbench by just dragging disk icons. + +2. Run TFTP. See the note TFTP.INFO. + +3. Make the data file READ-ONLY: + + Remove TFTP disk, and insert Workbench disk in drive 0. + + >protect df1:Story.Data r + +4. Rename the game disk (e.g., Zork 1 Disk) and the interpreter file + (e.g., Zork 1). + +5. Remove the finished disk ond open the Write-Protect tab. + diff --git a/amiga/production.old b/amiga/production.old new file mode 100644 index 0000000..db25085 --- /dev/null +++ b/amiga/production.old @@ -0,0 +1,48 @@ +How to download a game to the Amiga (via a PC) +-------------------------------------------------------------------- + +1. Transfer the game file to the PC with Kermit. + +2. CONVERT < GAME.ZIP > GAME.HEX (hexify it) + +3. SPLIT GAME.HEX 100000 Q (split into smaller files) + +4. On the Amiga, make a disk copy of the Create disk + + Open the CLI on the Workbench disk + >diskcopy from df0: to df1: + + A prompt appears, put Create disk in drive 0 and an unformatted + disk in drive 1 (format is automatic). Hit RETURN. + +5. (Repeat the following once for each file created in Step 3) + + On Amiga: (Workbench disk is still in drive 0, CLI is open) + + Put Transfer Disk in drive 1. + >cd df1: (change to Transfer Disk) + >read Game.00x serial (x is 1, 2, or 3) + + On the PC: + + XTALK + sp 96 (speed 9600) + go lo (go local) + (hit the home key, #7 on right) + se GAME.00x (send a file) + quit (when done) + +6. On Amiga: (when drive lights go out) + + Remove Workbench disk, insert copy of Create disk in drive 0. + + >join Game.001 Game.002 Game.003 AS df0:Story.Data + +7. On Amiga: (when drive lights go out) + + Remove Transfer disk, insert Workbench disk in drive 1. + + >protect df0:Story.Data r (make the game READ-ONLY) + +8. Remove the new game disk ond open the Write-Protect tab. + diff --git a/amiga/ref.txt b/amiga/ref.txt new file mode 100644 index 0000000..f26e8c9 --- /dev/null +++ b/amiga/ref.txt @@ -0,0 +1,69 @@ +This booklet tells you how to run your Infocom story on your computer, and provides a few other handy bits of information. + +I. What You Need +Required: +% Apple Macintosh computer with 512K + or more of memory + +Optional: +% System Disk or other startup disk +% Blank 3-1/2 inch disks (for saving your position in the story) +% Compatible printer (for SCRIPTing) +% Second disk drive (for convenience when saving your position in the story) + +II. Copying Your Original Disk + It is always advisable to make a copy of the disk that came in your package. This ensures that you will not accidentally erase or damage the only copy you have of the story. See your hardware manual for instructions on how to copy disks. + You can move the story to a hard disk by copying each file (there may be just one) and folder, except for the System Folder, into a folder of your choice on the hard disk. + Remember, any copy of your original story disk may only be used in accordance with the licensing agreement found in your package. + +III. Getting Started + The System file included on this disk is recommended for use with the Macintosh 512K, XL, 512KE, and Plus. If you are using a different model (e.g. a Macintosh SE or II), or if you have a hard disk, you should start your computer with your usual system startup disk. Otherwise, it's OK to use the story disk as the startup disk. + Due to disk space limitations, the story disk may include a MiniFinder instead of the regular Finder. The MiniFinder is faster but does not have all of the Finder's features, such as copying and deleting files. To change to the regular Finder, insert a disk that has one and click on the Finder button. + To begin the story, just insert the story disk and double-click on the storybook icon. + +IV. Talking to the Story + Whenever you see the prompt (>), the story is waiting for you to enter a command. If you make a mistake, use the backspace key to erase the error. After you have typed your command, press the Return key. The story will respond and the prompt (>) will reappear. + If a description will not fit on a screen all at once, [MORE] will appear at the bottom of the screen. After reading the screen, press any key to see the rest of the description. + +V. The Status Line + At the top of the screen is an area reserved for the status line. This area is used to display your present location in the story and is updated after each move. The status line may also display (depending on the story) various other types of information including score, total moves, time, or character attributes. + +VI. SCRIPTing + You can use the SCRIPT command to print out a transcript of your moves at any point in the story. The SCRIPT function is an optional feature which is not necessary to complete the story and may not be available with all hardware. + + 1. Turn on the printer and make sure it is ready. + 2. Type SCRIPT at the prompt (>) to start the transcript. To stop the transcript, type UNSCRIPT. + 3. SCRIPT and UNSCRIPT may be used as often as desired. +VII. Saving a Story Position + You can save your current position in the story to any disk, space permitting, including a hard drive. It may be convenient to use a separate disk just for your saves. + + 1. Type SAVE at the prompt (>). The standard dialog box for saving files will be displayed. + 2. Select the disk you want to save to. If it is already named in the dialog box (at the upper right), skip to step 3. If you have a single disk drive, click on the EJECT button, remove the story disk from the drive, and insert the save disk. If you have two drives, insert your save disk in the second drive. If necessary, click on the DRIVE button until the name of the desired disk appears in the box. + 3. Choose a file name under which to save your position and type it into the box. (The colon character (:) can't be used in a file name.) After typing in the file name, click on the OK button or press the Return key. If you want to cancel the save operation, click on the CANCEL button. + The disk drive will spin for several seconds and if all is well, the story will respond with a message such as COMPLETED. If it responds with FAILED, consult the Troubleshooting section. + After saving your story position, you may continue the story. + +VIII. Restoring a Saved + Story Position + To return to a previously saved position in the story, type RESTORE at the prompt (>). A standard dialog box will appear, showing a list of your saved positions on the most recently used disk. If you want to restore from a different disk, change disks (or drives) as described in Section VII. + Click once on the name of the position you want to restore, then click on the OPEN button. You can also just double-click on the position name. If you want to cancel the restore operation, click on the CANCEL button. + +IX. Troubleshooting +Load, SAVE, RESTORE and +Other Problems + If the story fails to load properly, or SAVE/RESTORE or SCRIPT fails, check each of the following items. If none of these offers a solution, consult your Apple dealer for assistance. + + 1. Inspect all disks carefully for any visible damage. + 2. For SCRIPTing, make sure the printer is connected properly, enabled for printing, not out of paper, etc. + 3. Try again. The problem may be only momentary. If all else fails, you can call the Infocom Technical Hotline at (617) +576-3190. Please note that this number is for technical problems only, not hints. + +The $VERIFY Procedure + You can check to see if your disk is damaged by using the $VERIFY command. + 1. Type $VERIFY at the story prompt (>) and press the Return key. If your story is currently frozen (i.e. you are unable to type from the keyboard) you will have restart it first. + 2. After you successfully issue the $VERIFY command, the disk will spin for a minute or so and a message similar to one of the following will appear: + + GOODPThe disk has not been damaged and the data is intact. If you are having problems, they are most likely hardware related. It is also possible that there is a bug in the program. If you suspect that there is a bug call the Infocom Technical Hotline. + NO GOODPThis indicates either disk damage or hardware trouble. Repeat the $VERIFY procedure several times. If possible, repeat the $VERIFY procedure on another computer (such as your dealerUs). If you ever receive a positive reply, the data is intact and you must look elsewhere for any problems you are encountering. + If you repeatedly get a negative response on more than one computer, the disk has most likely been damaged. Please send the disk only to Infocom for testing and replacement. To return your disk follow the directions in the instruction manual. + diff --git a/amiga/refcard.old b/amiga/refcard.old new file mode 100644 index 0000000..fdcc3f1 --- /dev/null +++ b/amiga/refcard.old @@ -0,0 +1,260 @@ +@Style[TabWidth 8 chars] +@Style[Spacing 2 lines] +@Style[Indent 8 chars] +@Style[Justification no] +@Verbatim{ +Interactive Fiction Reference Card for the + +Commodore {R} Amiga {R} +__________________________________________________________ +} +This booklet tells you how to run your Infocom story on your computer, +and provides a few other handy bits of information. + +@Verbatim{ +I. What You Need + +Required + + [] Amiga computer + +Optional + + [] Extra 3 1/2 inch disks (for SAVEs) + + [] Second disk drive (for convenience with SAVEs) + + [] Compatible printer (for SCRIPTing) + + +II. Making a Backup Copy } + +In accordance with the licensing agreement in your package, we recommend +that you make a backup copy of the original story disk for your personal +use. See your hardware manual for instructions on how to make disk +copies. Store your original disk in a safe place and always start the +story from the backup. + +@Verbatim{ +III. Starting the Story +} + +Turn on the Amiga and wait for the Workbench to appear. Insert the story +disk and open the disk icon into a window, then double- click on the +story icon. + +The story can also be started from within the Command Line Interpreter +(CLI) by typing its name. + +@Verbatim{ +IV. Talking to the Story +} + +Whenever you see the prompt (>), the story is waiting for your +instructions. You may type a full line of instructions at a time. If +you make a mistake, use the backspace key to erase the error. When you +have finished typing in your instructions, press the RETURN key. The +story will respond and the prompt (>) will reappear. + +If a description will not fit on the screen all at once, [MORE] will +appear at the bottom of the screen. After reading the screen, press any +key to see the rest of the description. + +@Verbatim{ +V. The Status Line +} + +At the top of the screen is a status line. This line is updated after +every move to show your current position in the story. Depending upon +the type of story, it may also show other information. + +@Verbatim{ +Score and Moves +} + +In stories that keep a score, such as the @U{Zork} underground +adventures, the right side of the status line will show something like +this: +@Verbatim{ + + Score: 245/920 +} + +The first number is your score and the second is the total number of +moves you have made. In the example above, you have 245 points in 920 +moves. + +@Verbatim{ +Time +} + +In stories that keep track of the time, such as the mystery thriller +@U{Deadline}, the right side of the status line will look something like +the following: +@Verbatim{ + + Time: 9:22 a.m. + +This shows the current time of day in the story. + + +VI. SCRIPTing +} + +You can use the SCRIPT command to print out a transcript of your moves +as you go along. SCRIPTing is an optional feature which is not +necessary to complete the story and may not be available with certain +hardware. + +1. Connect the printer to the appropriate port at the back of the +computer. Use the Preferences tool (see Section IX below) to make sure +the system is configured correctly for your printer. + +2. Turn on the printer and make sure it is ready. + +3. Type SCRIPT at the prompt (>) to start the transcript. To stop the +transcript, type UNSCRIPT. + +4. SCRIPT and UNSCRIPT may be used as often as desired. + + +If a problem occurs with the printer, the story will "timeout" (appear +to hang) for 30 seconds or so, then a printer error message will appear. +If you don't correct the problem before the 30 seconds are up, +scripting is automatically cancelled. + +@Verbatim{ +VII. Saving a Story Position +} + +You can save your current story position to a disk in any drive, space +permitting. The save disk must have been previously initialized. No +other data on the save disk will be affected. + + +1. Type SAVE at the prompt (>). A message will appear asking you to +type in a name for the save file. + +2. If you want to SAVE to the story disk itself, just enter a file name. +If you want to SAVE to another disk, you must prefix the file name with +either the name of the second disk (e.g., Saves:) or the name of the +drive containing it (e.g., df0:). The prefix is needed even if the two +disks were swapped using a single drive. + + +The disk drive will spin for several seconds. If all is well, the story +will respond: +@Verbatim{ + + OK + +If it responds: + + FAILED + +consult the Troubleshooting section below. +} +After saving your position, you may continue with the story. + + +Note: The file Icon.Data is used to create icons for new save files. If +you delete or rename this file, new save files will not be visible in +the save disk under Workbench. + +@Verbatim{ +VIII. Restoring a Saved Story Position +} + +You can return to a previously saved story position at any time. Type +RESTORE at the prompt (>), and enter the name of the save file, as in +Section VII. + +If you want to return to the most recently saved or restored position +(the one displayed as the default), you can just press the RETURN key. +@Verbatim{ +IX. Amiga Preferences +} + +Several aspects of the story presentation can be changed using the Amiga +Preferences tool, including text size (60 or 80 columns) and color. The +size can be changed only before the story is started. You also use +Preferences to specify your type of printer and the port to which it is +connected. The Amiga supports both parallel and serial devices. + +@Verbatim{ +X. Memory Usage and Multi-tasking +} + +On a multi-tasking computer such as the Amiga, tasks must share the +available memory. Some tasks may require that a certain amount of free +memory be available at all times. Also, actions like opening, resizing +and hiding windows can require large amounts of memory. + +When the Infocom story loads, it will always leave a specified amount of +memory free. The default minimum amount is 64 Kbytes. This can be +changed by starting the story from the CLI with a special argument of +the form F/n, where n is the new minimum number of bytes to leave free +(for example, Deadline F/32000). If you supply an argument, memory use +statistics will be displayed when the story loads. + +You may need to increase the amount of free memory if, for example, you +are running several tasks and switching between them causes the system +to hang. On the other hand, you can probably decrease free memory if +you are running only the story. This may reduce or eliminate the amount +of disk activity on versions of the Amiga with limited memory. + +@Verbatim{ +XI. Troubleshooting +} + +A. If the story fails to load properly, or if SAVE, RESTORE, or SCRIPT +fails, check each of the following items. If none of these offers a +solution, consult your Commodore Amiga dealer for assistance. + +1. Inspect all disks carefully for any visible damage. + +2. For SAVEs, make sure the save disk is not write-protected (the small +opening in the corner of the disk should be covered). + +3. For SCRIPTing, make sure the printer is connected properly, enabled +for printing, not out of paper, etc. + +4. Try again; the problem may only be momentary. + + +If all else fails, you can call the Infocom Technical Hotline at (617) +576-3190. Please note that this number is for technical problems only. + + +B. If the story produces an error message, run the following procedure: + +Restart the story. When the initial screen appears, type $VERIFY. The +disk drive will spin for a minute or so, and a message similar to one of +the following will appear. + +1. "DISK CORRECT." The disk has not been damaged; the data is intact. +This may indicate a problem with your hardware (usually with the disk +drive). It is also possible the story contains a bug. If you suspect a +bug, call the Infocom Technical Hotline number. + + +2. "DISK FAILED" or "DISK READ ERROR." This reply indicates either +hardware trouble or disk damage. Repeat the $VERIFY process several +times. Also try the $VERIFY process on another computer (such as your +dealer's). If the story ever replies "DISK CORRECT," the problem is in +your hardware. + +If you repeatedly get an error message on more than one computer, the +disk has most likely been damaged. Please send the +@U{disk only} to Infocom for testing and replacement. + +--------------------------------------------------------- + +Amiga is a registered trademark of Commodore Business Machines, Inc. + +@U{Zork} and @U{Deadline} are registered trademarks of Infocom, Inc. + + +Infocom logo + +Infocom, Inc., 125 CambridgePark Drive, Cambridge, MA 02140 \ No newline at end of file diff --git a/amiga/refcard.txt b/amiga/refcard.txt new file mode 100644 index 0000000..bd11eb1 --- /dev/null +++ b/amiga/refcard.txt @@ -0,0 +1,347 @@ +Interactive Fiction Reference Card for the + +Commodore Amiga [TM] +__________________________________________________________ + + This booklet tells you how to run your Infocom story on your computer, + +and provides a few other handy bits of information. + + +I. What You Need + +Required + + [] Amiga computer + + [] (for Interactive Fiction PLUS only) A monitor that supports an + +80-column display, such as an RGB-type monitor. + +Optional + + [] 256K memory expansion cartridge (for faster execution, + +recommended for Interactive Fiction PLUS) + + [] Extra 3 1/2-inch double-sided disks (for SAVEs) + + [] Second disk drive (for convenience with SAVEs) + + [] Compatible printer (for SCRIPTing) + + +II. Making a Backup Copy + + In accordance with the licensing agreement in your package, we + +recommend that you make a backup copy of the original story disk for + +your personal use. See your hardware manual for instructions on how + +to make disk copies. Store your original disk in a safe place and + +always start the story from the backup. + + +III. Starting the Story + + Turn on the Amiga and wait for the Workbench to appear. Insert + +the story disk and open the disk icon into a window, then double-click + +on the story icon. + + The story can also be started from within the Command Line + +Interpreter (CLI). If the default drive and directory are not the + +same as the story's, they must first be changed with the "CD" command + +(for example, CD df1:). Then type in the story name. + + +IV. Talking to the Story + + Whenever you see the prompt (>), the story is waiting for your + +instructions. If you make a mistake, use the backspace key to erase the + +error. When you have finished typing in your instructions, press the + +RETURN key. The story will respond and the prompt (>) will reappear. + + If a description will not fit on the screen all at once, + +"[MORE]" will appear at the bottom of the screen. After reading the + +screen, press any key to see the rest of the description. + + +V. The Status Line + + At the top of the screen is a status line. This line is + +updated after every move to show your current position in the story. + +Depending upon the type of story, it may also show other information. + + +Score and Moves + + In stories that keep a score, such as the ZORK [R] underground + +adventures, the right side of the status line will show something like + +this: + + Score: 245/920 + + The first number is your score and the second is the total + +number of moves you have made. In the example above, you have 245 + +points in 920 moves. + +Time + + In stories that keep track of the time, such as the mystery + +thriller DEADLINE [R], the right side of the status line will look + +something like the following: + + Time: 9:22 a.m. + +This shows the current time of day in the story. + + +VI. SCRIPTing + + You can use the SCRIPT command to print out a transcript of + +your moves as you go along. SCRIPTing is an optional feature which is + +not necessary to complete the story and may not be available with + +certain hardware. + + 1. Connect the printer to the appropriate port at the back of the + +computer. Use the Preferences tool (see Section IX below) to make sure + +the system is configured correctly for your printer. + + 2. Turn on the printer and make sure it is ready. + + 3. Type SCRIPT at the prompt (>) to start the transcript. To stop the + +transcript, type UNSCRIPT. + + 4. SCRIPT and UNSCRIPT may be used as often as desired. + + + If a problem occurs with the printer, the story will "timeout" + +(appear to hang) for 30 seconds or so, then a printer error message + +will appear. If you don't correct the problem before the 30 seconds + +are up, scripting is automatically cancelled. + + +VII. Saving a Story Position + + You can save your current story position to a disk in any + +drive, space permitting. The save disk must have been previously + +initialized, and must not be write-protected. No other data on the + +save disk will be affected. + + + 1. Type SAVE at the prompt (>). A message will appear asking you to + +choose a name for the save file. + + 2. If you want to SAVE to the story disk itself, just enter a file + +name and press RETURN. + + 3. If you want to SAVE to another disk, you must prefix the file name + +with either the name of the second disk (e.g., Saves:) or the name of + +the drive containing it (e.g., df0:). The prefix is needed even if + +the two disks were swapped using a single drive. If the save succeeds, + +the prefix becomes the default, and need not be typed again for the next save. + + + The disk drive will spin for several seconds. If all is well, + +the story will respond: + + OK + +If it responds: + + FAILED + +consult the Troubleshooting section below. + +After saving your position, you may continue with the story. + + + Note: The file "Icon.Data" is used to create icons for new save + +files. If you delete this file, new save files will not have visible icons. + + +VIII. Restoring a Saved Story Position + + You can return to a previously saved story position at any + +time. Type RESTORE at the prompt (>). The most recently saved or + +restored position will be displayed as the default. Then enter the + +name of a save file, as in Section VII. + + If you want to return to the default position, you can just + +press the RETURN key. + + +IX. Amiga Preferences + + Several aspects of the story presentation can be changed using + +the Amiga Preferences tool, including text size (60 or 80 columns, except + +for Interactive Fiction PLUS, which requires 80 columns) and + +color. The size can be changed only before the story is started. You + +also use Preferences to specify your type of printer and the port to + +which it is connected. The Amiga supports both parallel and serial + +devices. + +X. Memory Usage and Multi-tasking + + On a multi-tasking computer such as the Amiga, tasks must + +share the available memory. Some tasks may require that a certain + +amount of free memory be available at all times. Also, actions like + +opening, resizing and hiding windows can temporarily require large + +amounts of memory. + + When the Infocom story loads, it will always leave a specified + +amount of memory free. The default minimum amount is 64 Kbytes + +(32 Kbytes for Interactive Fiction PLUS). This + +can be changed by starting the story from the CLI with a special + +argument of the form "F/n," where n is the new minimum number of bytes + +to leave free (for example, Deadline F/32000). If you supply an + +argument, memory use statistics will be displayed when the story + +loads. + + You may need to increase the amount of free memory if, for + +example, you are running several tasks and switching between them + +fails or causes the system to hang. On the other hand, you can + +probably decrease free memory if you are running only the story. This + +may reduce or eliminate disk activity on versions of the Amiga with + +limited memory. + + +XI. Troubleshooting + +A. If the story fails to load properly, or if SAVE, RESTORE, or SCRIPT + +fails, check each of the following items. If none of these offers a + +solution, consult your Commodore Amiga dealer for assistance. + + 1. Inspect all disks carefully for any visible damage. + + 2. For SAVEs, make sure the save disk is not write-protected (the small + +opening in the corner of the disk should be covered). + + 3. For SCRIPTing, make sure the printer is connected properly, enabled + +for printing, not out of paper, etc. + + 4. Try again; the problem may only be momentary. + + + If all else fails, you can call the Infocom Technical Hotline + +at (617) 576-3190. Please note that this number is for technical + +problems only, not hints. + + +B. If the story produces an error message, run the following procedure: + + Restart the story. When the initial screen appears, type + +$VERIFY. The disk drive will spin for a minute or so, and a message + +similar to one of the following will appear. + + 1. "DISK CORRECT." The disk has not been damaged; the data is intact. + +This may indicate a problem with your hardware (usually with the disk + +drive). It is also possible the story contains a bug. If you suspect a + +bug, call the Infocom Technical Hotline number. + + + 2. "DISK FAILED" or "DISK READ ERROR." This reply indicates either + +hardware trouble or disk damage. Repeat the $VERIFY process several + +times. Also try the $VERIFY process on another computer (such as your + +dealer's). If the story ever replies "DISK CORRECT," the problem is in + +your hardware. + + If you repeatedly get an error message on more than one + +computer, the disk has most likely been damaged. Please send the + +DISK ONLY to Infocom for testing and replacement. + +--------------------------------------------------------- + +Amiga is a registered trademark of Commodore-Amiga, Inc. + +ZORK and DEADLINE are registered trademarks, and Interactive Fiction + +PLUS is a trademark, of Infocom, Inc. + + +Infocom logo + +Infocom, Inc., 125 CambridgePark Drive, Cambridge, MA 02140 \ No newline at end of file diff --git a/amiga/shersound.list b/amiga/shersound.list new file mode 100644 index 0000000..276e329 --- /dev/null +++ b/amiga/shersound.list @@ -0,0 +1,135 @@ + + init 10124 + join 1072 + mkdata 5212 + + midi.asm 90 + midi.o 256 + midi 80 (.mid file w/ segment header) + test 80 (similar to midi - 3 diffs) + +MP = "midi pitch," $4A standard +MR = "midi ref," $32 standard (MP-$18) + + 3. armor.dat 18 + fan.mid 11 MP + armor 33290 MR 3C00 (15.4K) + + 4. badviol.dat 20 + badv.mid 11 MP + badvio 38650 MR 2800 (10.2K) + + 5. bark.dat 21 + (clk.mid) + bark.bin 6508 MR 3C00 + + 6. splash.dat 19 + (clk.mid) + splash 53130 MR 3002 (12.3K) + + 7. clock.dat 19 + clk.mid 11 MP + benclk 38180 MR 4164 (16.7K) + + benclk1 (unused) 46908 MR 4178 + + 8. crowd.dat 21 + crowd.mid 11 MP-2 + crowd1 (chopped) 25830 MR 2800 + + 9. fanfare.dat 24 + (clk.mid) + fanfare.bin 56602 MR 25E4 (9.7K) + + 10. growl.dat 20 + growl.mid 11 MP + growl 50488 MR 4178 (16.8K) + + 11. heart1.dat 21 + heart1.mid 11 MP-6 + heart 14010 MR 47FE (18.4K) + + 12. heart2.dat 20 + (growl.mid) + (heart) + + 13. heart3.dat 21 + heart3.mid 11 MP+5 + (heart) + + + + 14. horse.dat 20 + horse.mid 11 MP-2 + horse (chopped) 9705 MR 2400 (sr/2) + + horse-or1 40010 MR 47FE + horsie 40080 (same, plus garbage header) + + 15. violin.dat 24 + (clk.mid) + violin.bin 48218 MR 25E4 + + violin (unused) 52832 MR 3764 + violinb2 (unused) 16464 MR 6C81 (27.8K) (garbage hdr) + + 16. snore.dat 22 + (clk.mid) + snore.bin 49930 MR 2D00 (11.5K) + + 17. clock2.dat 19 + (clk.mid) + ben2 (shortened) 25454 MR 4164 + + + music.dat (unused) 30 (similar to armor.dat) + (clk.mid) + (armor) + + boating.dat (unused) 44 + water.mid 23 MR, MR-2, MR-2 + (splash) + birdie.bin (unused) 49930 MR 3C00 + windy.bin (unused) 56970 MR 3C00 + + + 52 files - 1 directory - 1592 blocks used + + + +Sorted by sr: + + violinb2 (unused) 16464 MR 6C81 (27.8K) (garbage hdr) + heart 14010 MR 47FE (18.4K) + horse-or1 (unused) 40010 MR 47FE + growl 50488 MR 4178 (16.8K) + benclk1 (unused) 46908 MR 4178 + benclk 38180 MR 4164 (16.7K) + ben2 (chopped) 25454 MR 4164 + armor 33290 MR 3C00 (15.4K) + bark.bin 6508 MR 3C00 + violin (unused) 52832 MR 3764 (14.2K) + splash 53130 MR 3002 (12.3K) + snore.bin 49930 MR 2D00 (11.5K) + badvio 38650 MR 2800 (10.2K) + crowd1 61050 MR 2800 + fanfare.bin 56602 MR 25E4 (9.7K) + violin.bin 48218 MR 25E4 + horse (-ss1) (chopped) 9705 MR 2400 (9.2K) (sr/2) + + +Sorted by filesize: + + fanfare.bin 56602 + splash 53130 + snore.bin 49930 + violin.bin 48218 + badvio 38650 + armor 33290 + crowd1 (chopped) 25830 + ben2 (chopped) 25454 + growl (-ss1) 25244 + benclk (-ss1) 19090 + horse (-ss1) (chopped) 9705 + heart (-ss1) 7005 + bark.bin 6508 diff --git a/amiga/sift.c b/amiga/sift.c new file mode 100644 index 0000000..7adbbc8 --- /dev/null +++ b/amiga/sift.c @@ -0,0 +1,68 @@ +#include "lattice/stdio.h" +#include "libraries/dos.h" + +#define FMSIZE 100 /* Amiga: not in above includes */ +#define BLKSIZE 512 + +FILE *fopen(); /* extern */ +FILE *in_fp, *out_fp; + +main(argc, argv) +int argc; char *argv[]; +{ + char in_fname[FMSIZE], out_fname[FMSIZE], buffer[BLKSIZE]; + int i, runlen; + + if (argc != 3) + { + fprintf(stderr, "\nusage: sift -- \ +copy to filename.out, discarding every n+1 byte\n"); + cleanup(1); + } + + if ((in_fp = fopen(argv[1], "rb")) == NULL) + { + fprintf(stderr, "\nError opening <%s>\n", argv[1]); + cleanup(2); + } + + sscanf(argv[2], "%d", &runlen); + if ((runlen < 1) || (runlen > BLKSIZE)) + { + fprintf(stderr, "\nrun length out of range\n"); + cleanup(3); + } + + strcpy (out_fname, argv[1]); + strcat (out_fname, ".out"); + + printf("Creating <%s>\n", out_fname); + if ((out_fp = fopen(out_fname, "wb")) == NULL) + { + fprintf(stderr, "\nError opening <%s>\n", out_fname); + cleanup(4); + } + + while (!feof(in_fp)) { + i = fread (buffer, 1, runlen, in_fp); + + if (fwrite(buffer, 1, i, out_fp) != i) + { + fprintf(stderr, "\nError writing file <%s>\n", out_fname); + cleanup(5); + } + + i = fread (buffer, 1, 1, in_fp); /* skip this byte */ + } + + cleanup(0); +} + +cleanup (exitval) +int exitval; +{ + if (in_fp) fclose(in_fp); + if (out_fp) fclose(out_fp); + + exit (exitval); +} diff --git a/amiga/sound.c b/amiga/sound.c new file mode 100644 index 0000000..1afc4db --- /dev/null +++ b/amiga/sound.c @@ -0,0 +1,812 @@ + +/* "The Amiga sound routines are compiled independently, then linked to + the rest of the program" + + By Don Harlow; hacked by Duncan Blanchard +*/ + +#define SDEADCODE 0 /* exclude unused code */ + +#include "exec/types.h" +#include "exec/memory.h" + +/* The SOUND switch can be turned off (in the batch file) at compile time + for games that don't use special sounds. Takes a 10K bite from the space + occupied by the interpreter on disk and in memory. */ + +#if SOUND + +#include "lattice/stdio.h" /* (Amiga-format pathnames) */ +#include "lattice/fcntl.h" +#include "lattice/math.h" +#include "devices/audio.h" +#include "devices/timer.h" +#include "sound.h" + +#define NFILES 16 /* max # midi sound files */ +#define SCHANS 4 /* max # Amiga audio channels */ +#define S_ON on_off +#define S_OFF !on_off +#define SOUNDDIR "Sound/" + +extern VOID *AllocMem(); /* APTR? CHAR *? */ +extern VOID FreeMem(); +extern LONG OpenDevice(); +extern VOID CloseDevice(); +extern VOID BeginIO(); +extern LONG CheckIO(); +extern double pow(); + +extern UBYTE *soundbuf; /* data buffer, 64K preallocated */ + +UBYTE *sndfile[NFILES+1] = { 0 }; /* sound file buffer ptrs */ +UWORD sflen[NFILES+1]; /* and lengths */ +UBYTE *midifile = 0; /* midi file buffer ptr */ +UWORD mflen; /* and length */ + +/* Use of sound synchronization flags (one per channel): + - set by audion + - cleared by game interrupt +*/ +UBYTE sf[SCHANS] = {0}; + +/****************************************************** + +(From AUDONOFF.C) + +Wednesday 10-Jun-87 13:02:04 + +*******************************************************/ + +#define SOUNDPREC 75 /* precedence = "medium high" */ + +struct IOAudio *IOA[SCHANS]; +WORD dev_error; + +UWORD percalc(); +void clear_ioBlock(); + +/*------------------------------*/ +/* audion */ +/*------------------------------*/ + +/* vol = 0..63, or -1 for "hardwired" value from midi file */ +/* repeat = 1..n, 0 for indefinite, or -1 for "hardwired" val */ + +WORD audion(on_off, vol, rep) +WORD on_off, vol, rep; +{ + struct IOAudio *curIOA; +static UBYTE chan_req[SCHANS] = {1,2,4,8}; +static UWORD old_mcp[SCHANS] = {0,0,0,0}; /* midi channel/pitch */ + UWORD cur_mcp; + WORD i,j; + UBYTE m8chn,m4chn,m2chn; /* n bits of channel data */ + UBYTE oldstat = 0; + UBYTE mpitch, spitch; /* added - dbb */ + UWORD sr; + UBYTE *cursnd; /* sound file buffer ptr */ + WORD vol2, rep2; + int err; /* for ADCMD_ALLOCATE */ + +/** (unused) **/ +/* UBYTE flag, status = 0; */ /* dead */ +/* WORD n; + ULONG cur_mcp1; + ULONG timey; + UBYTE oneflg = 0; + UWORD pval = 400; + UWORD psav = pval; +static UWORD pvalue[SCHANS] = {300,280,200,180}; + ULONG Timex; + UBYTE sound_data[128]; +*/ + if (S_ON) { + for(i=0; iioa_Length = (ULONG)i; (?) dbb */ + + for (i = 0; i < SCHANS; i++) { + curIOA = IOA[i]; + curIOA->ioa_Data = &chan_req[i]; + curIOA->ioa_Length = (ULONG)sizeof(chan_req[i]); + curIOA->ioa_Request.io_Message.mn_Node.ln_Pri = SOUNDPREC; + curIOA->ioa_Request.io_Command = ADCMD_ALLOCATE; + + /* (following is from Peck p285) */ + + /* if chan not avail don't wait, return err */ + curIOA->ioa_Request.io_Flags = ADIOF_NOWAIT | IOF_QUICK; + BeginIO(curIOA); + + err = WaitIO(curIOA); + if (!(curIOA->ioa_Request.io_Flags & IOF_QUICK)) + /* was not quick I/O after all */ + GetMsg (curIOA->ioa_Request.io_Message.mn_ReplyPort); + if (err) { + clear_ioBlock(); + return (-1); /* "chan alloc err" */ + } + } + for (i = 1; i < SCHANS; i++) + IOA[i]->ioa_AllocKey = IOA[0]->ioa_AllocKey; + } + + if (S_OFF) { + midifile += 6; /* from init(); undone below [dbb] */ +/** mflen -= 6; **/ /* already hacked in init [dbb] */ + } + + for (j = 0; j < mflen; j += 3) { + m8chn = midifile[j]; + +/* "this section generally ignored" */ + if (m8chn <= 0x80) { + if (j >= mflen) /* [mflen not mult of 3?] */ + break; /* [gone] */ + /* use 0 for last file byte */ + j -= 1; /* retrieve last byte */ + m8chn = oldstat; /* process last midi channel */ + } + else if (m8chn != 0xff) + oldstat = m8chn; + + cur_mcp = (m8chn << 8) + midifile[j+1]; + m4chn = (m8chn & 0xf); /* mask out high nibble */ + m2chn = (m4chn & 3); + curIOA = IOA[m2chn]; + + if ((m8chn >= 0x80) && (m8chn <= 0x9f) + && (midifile[j+2] /*volume*/ > 0)) { + + /* bug fixed - following used '&&' */ + if ((old_mcp[m2chn] & 0xff00) == (cur_mcp & 0xff00)) { + do_Finish (curIOA, m2chn); + old_mcp[m2chn] = 0; /* but next line ?? **/ + } +/* old_mcp contains the channel assignment and the midi pitch */ + old_mcp[m2chn] = cur_mcp; + +/* setup the paramblock for a new start */ + cursnd = sndfile[m4chn]; + + if (rep == -1) /* use val from data file */ + rep2 = (UWORD) *cursnd; + else rep2 = rep; + curIOA->ioa_Cycles = rep2; + +/* make mystery adjustment to pitch-request byte. */ +/* But DON'T change value in original buffer. Otherwise, when sound is + started and stopped more than once (without reloading from disk in between), + it "drawls" out slowly the second time. [dbb]. */ + + mpitch = midifile[j+1]; + if (m8chn == 0x90) + mpitch -= 24; /* was +=12 */ + else if (m8chn == 0x91) + mpitch -= 24; + else if (m8chn == 0x92) + mpitch -= 12; + + spitch = *(cursnd + 1); + sr = *(UWORD *)(cursnd + 2); + curIOA->ioa_Period = percalc (sr, mpitch, spitch); + + if (vol == -1) /* use val from data file */ + vol2 = midifile[j+2]; + else vol2 = vol; + curIOA->ioa_Volume = vol2; + + curIOA->ioa_Length = (ULONG) *(UWORD *)(cursnd + 6); + curIOA->ioa_Data = cursnd + 8; + +/* make sure node type is NT_MESSAGE (set also by system at start of sound, + changed at end). Our end-of-sound detector depends on this. */ + curIOA->ioa_Request.io_Message.mn_Node.ln_Type + = NT_MESSAGE; + + curIOA->ioa_Request.io_Flags = ADIOF_PERVOL | IOF_QUICK; + curIOA->ioa_Request.io_Command = CMD_WRITE; + BeginIO((struct IORequest *)curIOA); + + sf[m2chn] = 1; /* set STARTED flag */ + } + else { + for (i = 0; i < SCHANS; i++) { + if (old_mcp[m2chn] == cur_mcp) { + old_mcp[m2chn] = 0; + do_Finish (curIOA, i); + /* [exit loop after 1st match] */ + break; + } + } + } + } + +/* above code demonstrates how to change period value once sound started */ + + if (S_OFF) { + for (i = 0; i < SCHANS; i++) { + curIOA = IOA[i]; + do_Finish (curIOA, i); + + /* bug: must ADCMD_FREE also ??? */ + } + + /* must messages be ack'd before releasing the mem? [dbb] */ + clear_ioBlock(); + midifile -= 6; /* undo hack above, before FreeMem [dbb] */ + /** mflen += 6; **/ /* already hacked in init [dbb] */ + } + return(ALL_OK); +} + +/*------------------------------*/ +/* do_Finish */ +/*------------------------------*/ + +/* send ADCMD_FINISH message (separate routine since multiple calls) */ + +do_Finish (curIOA, chan) +struct IOAudio *curIOA; +UBYTE chan; +{ + sf[chan] = 0; /* turn off STARTED flag */ + + curIOA->ioa_Request.io_Flags = ADIOF_PERVOL | IOF_QUICK; + curIOA->ioa_Request.io_Command = ADCMD_FINISH; + BeginIO ((struct IORequest *)curIOA); +} + +/*------------------------------*/ +/* percalc */ +/*------------------------------*/ + +/* percalc - all args/val now integers; floating point used internally */ + +#define SCONST 3579.49 +#define CHROMA 1.05946309 + +UWORD percalc (samp, midval, refval) +UWORD samp; UBYTE midval, refval; +/* samp = initial (original) sampling rate; + midval = desired midi pitch; refval = initial midi frequency; + per = (3579.49/(samp/1000)) / (CHROMA ^ delta) */ +{ + BYTE delta; + float per; + double pitch; + + per = (float)SCONST / ((float)samp / (float)1000); + delta = midval - refval; + if (delta) { + pitch = pow ((double)CHROMA, (double)delta); + per /= pitch; + } + return ((UWORD)per); +} + +/*------------------------------*/ +/* clear_ioBlock */ +/*------------------------------*/ + +void clear_ioBlock() +{ + struct IOAudio *curIOA; + WORD i; + + if (!dev_error) + CloseDevice((struct IORequest *)IOA[0]); + for (i = 0; i < SCHANS; i++) + if (curIOA = IOA[i]) { + FreeMem((char *)curIOA, (LONG)sizeof(struct IOAudio)); + IOA[i] = 0; /* mark it free [dbb] */ + } +} + +/****************************************************** + +(From INITONOF.C) + +Wednesday 10-Jun-87 13:00:31 + +*******************************************************/ + +WORD fdr[NFILES+1], fdr1 = -1; +UBYTE fname[NFILES+1][15]; /* sound file names */ +UBYTE chan[NFILES+1]; /* sound channel to use */ + +void process(); +WORD get_name(); +void get_all_names(); +void get_midi_name(); +WORD get_file(); +WORD get_all_files(); +WORD get_midi_file(); +void cleanup(), close_files(); + +/*------------------------------*/ +/* init */ +/*------------------------------*/ + +/* allocate memory, read files, setup pointers */ + +WORD init (effect, on_off) +UBYTE *effect; +UWORD on_off; +{ + static UWORD store; + WORD n, i, err; + UBYTE ch, fullname[32]; + WORD num_snd; + +/** (unused) **/ +/* WORD synth_num, sound_error; + UBYTE *file_1; +*/ + if (S_ON) { + for (i = 0; i <= NFILES; i++) + fdr[i] = -1; /* all files start unopened */ + + strcpy (fullname, SOUNDDIR); /* always look in subdir */ + strcat (fullname, effect); + + fdr1 = open(fullname, O_RDONLY); /* open master file */ + if (fdr1 < 0) /* no files open, no buffers allocated */ + return(MAIN_FILE_ERROR); + + /* get file names */ + + n = read (fdr1, &ch, 1); /* 1st byte is # sound files */ + num_snd = (WORD)ch; + get_all_names (num_snd); /* get names of sound files */ + + n = read (fdr1, &ch, 1); /* check for synthesis file */ + if (ch) /* 1=yes 0=no */ + process(); + get_midi_name(); /* get name of midi file */ + + /* get file data */ + + err = get_all_files(num_snd); /* read the sound data */ + if (err) { + close_files(); + cleanup(); + return (SOUND_FILE_ERROR); + } + + err = get_midi_file(); /* read the midi data */ + if (err) { + close_files(); + cleanup(); + return (MIDI_FILE_ERROR); + } + + store = mflen; /* save orig length of midi file */ + mflen = 3; /* "only 3 bytes in this incarnation" */ + close_files(); /* close all files */ + } + +/** want only last three bytes [moved to audion() -- dbb] **/ +/** if (S_OFF) midifile += 6; **/ +/** now called separately -- [dbb] **/ +/** sound_error = audion(on_off); + if (sound_error) return(sound_error); **/ + + if (S_OFF) { + mflen = store; /* (first) restore actual len */ + cleanup(); /* deallocate buffers */ + } + return (ALL_OK); +} + +/* subroutines :::::::::::::::::::::::::::: */ + +void process() +{ +} + +/*------------------------------*/ +/* get_name */ +/*------------------------------*/ + +/* get_name() + Gets a file name into memory + Parameters: location where name is to be stored + Returns: length of name +*/ + +WORD get_name (buf) +UBYTE *buf; +{ + WORD n, j=0; + UBYTE ch; + + do { + n = read (fdr1, &ch, 1); + buf[j++] = ch; + } + while (ch != '\0'); + return ((WORD)(j-1)); +} + +/* Get names of all data files into an array in memory */ + +void get_all_names (tot) +WORD tot; /* number of names to get */ +{ + WORD i,n; + + for (i = 0; i < tot; i++) { + n = read (fdr1, &chan[i], 1); /* sound channel to use */ + n = get_name (&fname[i]); + } +} + +/* Get midi data file name into memory */ + +void get_midi_name() +{ + get_name (&fname[NFILES]); +} + +/*------------------------------*/ +/* get_file */ +/*------------------------------*/ + +/* get_file() + open a data file, allocate memory, read it in + Parameters: index of the file + Returns: error, or 0 if none +*/ + +WORD get_file(k) +WORD k; +{ + UWORD n; + UBYTE *loc, fullname[32]; + + strcpy (fullname, SOUNDDIR); /* always look in subdir */ + strcat (fullname, fname[k]); + fdr[k] = open (fullname, O_RDONLY); + if (fdr[k] == -1) + return(-1); /* "file not found" */ + n = read (fdr[k], &sflen[k], 2); /* the "defined length" */ + + if (k == 0) /* use standard buffer */ + loc = soundbuf; + else loc = (UBYTE *)AllocMem ((LONG)sflen[k], (MEMF_CHIP | MEMF_CLEAR)); + if (!loc) { + return (-2); /* "alloc error" */ + } + + sndfile[k] = (UBYTE *)loc; +/*** sndfile[chan[k]] = (UBYTE *)loc; ***/ /* [correct?] */ + + n = read (fdr[k], loc, (UWORD)sflen[k]); + return (0); +} + +/* get_all_files() + Loads all apposite sound data files into memory + Parameters: number of files to load + Returns: error, or 0 if none +*/ + +WORD get_all_files (tot) +WORD tot; +{ + WORD i, err; + + for (i = 0; i < tot; i++) { + err = get_file (i); + if (err) break; + } + return(err); +} + +/* get_midi_file() + Load the midi data file into memory + Parameters: none + Returns: error, or 0 if none +*/ + +WORD get_midi_file() +{ + WORD err; + + err = get_file (NFILES); + if (!err) { + midifile = sndfile[NFILES]; + mflen = sflen[NFILES]; + } + return (err); +} + +/*------------------------------*/ +/* close_files */ +/*------------------------------*/ + +/* Close all open files */ + +void close_files() +{ + WORD i, n; + + for (i = 0; i <= NFILES; i++) + if (fdr[i] != -1) { + n = close (fdr[i]); + fdr[i] = -1; + } + if (fdr1 != -1) { + n = close (fdr1); + fdr1 = -1; + } +} + +/* Free up memory allocated for buffers */ + +void cleanup() +{ + WORD i; + + /* i=0 uses global "soundbuf" (64K preallocated) */ + sndfile[0] = 0; + + for (i=1; i < NFILES; i++) + if (sndfile[i]) { + FreeMem ((char *)sndfile[i], (LONG)sflen[i]); + sndfile[i] = 0; /* [dbb] */ + } + if (midifile) { + FreeMem ((char *)midifile, (LONG)mflen); + midifile = 0; /* [dbb] */ + } +} + +#endif /* SOUND */ + +/****************************************************** + + Game Interface + +*******************************************************/ + +extern void bell_sound(); + +#define S_INIT 1 /* load data from disk */ +#define S_START 2 +#define S_STOP 3 /* stopped but ready to restart */ +#define S_CLEANUP 4 /* release the memory used */ + +#define S_BEEP 1 +#define S_BOOP 2 + +#define M_ON 1 +#define M_OFF 0 + +#if SOUND + +/*------------------------------*/ +/* md_sound */ +/*------------------------------*/ + +/* id=1-n or 0(mru), action=1-4, + volume=0-64 or -1(midi), repeat=1-n, 0(infinite) or -1(midi) */ + +WORD md_sound (id, action, vol, rep) +WORD id, action, vol, rep; +{ + static WORD last_id = 0; + static WORD inited = 0, started = 0; + char name[32]; + WORD i, err; + + if (id == 1 || id == 2) { + bell_sound(id); /* 1=beep, 2=boop */ + return(0); + } + if (id == 0) { /* use MRU effect */ + if (last_id == 0) return (0); /* none, exit */ + else id = last_id; + } + else if (id != last_id) { /* first get rid of old, if any */ + md_sound (last_id, S_CLEANUP, vol, rep); /* (recurse) */ + last_id = id; + } + +/* Use id to make generic names (don't want names to give away plot!) */ + + i = stccpy (name, "S", 32); /* make "[SOUND/] Sx.NAM" */ +/** stcu_d (&name[i], id, 16); **/ /* Lattice bug: i is one too high */ + stcu_d (&name[1], id, 16); + strcat (name, ".NAM"); + + if (action == S_INIT || action == S_START) { + if (!inited) { +/*** showdbg (S_INIT, name, vol, rep); ***/ + err = init (name, M_ON); + if (err != ALL_OK) { + showerr (err); /* inform user */ + return (err); + } + inited = 1; + } + } + if (action == S_START) { + md_sound (id, S_STOP, vol, rep); /* reset (if restarting) */ +/*** showdbg (S_START, name, vol, rep); ***/ + err = audion (M_ON, vol, rep); + if (err != ALL_OK) { + showerr (err); /* inform user */ + return (err); + } + started = 1; + } + if (action == S_STOP || action == S_CLEANUP) { + if (started) { + audion (M_OFF, vol, rep); /* stop sound */ + started = 0; + } + } + if (action == S_CLEANUP) { /* free resources */ + if (inited) { + init (name, M_OFF); + inited = 0; + } + last_id = 0; /* back to original state */ + } + return (ALL_OK); +} + +/*------------------------------*/ +/* showerr */ +/*------------------------------*/ + +showerr (err) /* inform user of problem */ +WORD err; +{ + +} + +/*------------------------------*/ +/* end_sound */ +/*------------------------------*/ + +/* This "pseudo-interrupt" is called from the 68K kernel and returns TRUE + to report the end of a sound (on ANY channel...) */ + +BOOL end_sound () +{ + register UBYTE *p; + register int i; + BOOL result = FALSE; + +/* When sound ends, system changes node type to either NT_FREEMSG or + to NT_REPLYMSG. We use this to detect end-of-sound. + + (A CheckIO call merely checks for node type NT_REPLYMSG. But a + reply port must have been attached to the message structure, I think, + for that type to ever be returned.) */ + + p = (UBYTE *) &sf[0]; + for (i=0; iioa_Request.io_Message.mn_Node.ln_Type + != NT_MESSAGE) { /* stopped? */ + *p = 0; /* turn off flag */ + result = TRUE; + } + } + p++; + } + return (result); +} + +#else /* if !SOUND */ /* stub routines */ + +WORD md_sound (id) +WORD id; +{ + bell_sound(id); /* 1=beep, 2=boop */ + return(0); +} + +BOOL end_sound () +{ + return (FALSE); +} + +#endif /* SOUND */ + +#if SDEADCODE /* routines currently unused */ + +/*------------------------------*/ +/* showdbg */ +/*------------------------------*/ + +showdbg (action, name, vol, rep) /* show debug info */ +WORD action, vol, rep; +char *name; +{ + char s[80], sn[16]; + + if (action == S_INIT) { + strcpy (s, "S_INIT ("); + strcat (s, name); /* show filename */ + strcat (s, ") "); + line_out (s, strlen(s)); + } + if (action == S_START) { + strcpy (s, "S_START ("); + stci_d (sn, vol, 16); /* show volume */ + strcat (s, sn); + strcat (s, ", "); + stci_d (sn, rep, 16); /* show reps */ + strcat (s, sn); + strcat (s, ")"); + line_out (s, strlen(s)); + char_out (13); + } +} + +/*------------------------------*/ +/* change_vol */ +/*------------------------------*/ + +/* THIS ROUTINE NOT CURRENTLY USED; VOLUME SET ONLY AT START/STOP. + IN PRACTICE I THINK THE AUDIBLE DIFFERENCE WILL BE MINOR. */ + +/* Change sound volume (under game control). On Amiga the volume + may range from 0-63 (64?). */ + +VOID change_vol (soundvol) /* called only /after/ sound is started */ +WORD soundvol; +{ + register struct IOAudio *curIOA; +/* WORD i; */ + +/* Change applies to channel 0 only (until I figure out how audion() + extracts channel info from the midi file). */ + + curIOA = IOA[0]; + if (curIOA) { + curIOA->ioa_Request.io_Flags = ADIOF_PERVOL; + curIOA->ioa_Volume = soundvol; + BeginIO((struct IORequest *)curIOA); + } +} + +/*------------------------------*/ +/* int_sound */ +/*------------------------------*/ + +/* Machine interrupt - check for end of sound. + This interrupt routine is active at all times, for simplicity. + + If a sound has been started (on any channel) and we have NOT previously + detected its completion, we check now. If we detect its completion, + we set the appropriate global "stop" flag. +*/ + +void int_sound() +{ +} +#endif /* SDEADCODE */ + diff --git a/amiga/sound.h b/amiga/sound.h new file mode 100644 index 0000000..e757987 --- /dev/null +++ b/amiga/sound.h @@ -0,0 +1,18 @@ + +/**************************************************** + +Date and time of latest revision: + + +Tuesday 09-Jun-87 16:27:50 + +*******************************************************/ + + + +#define ALL_OK 0 +#define MAIN_FILE_ERROR 1 +#define SOUND_FILE_ERROR 2 +#define MIDI_FILE_ERROR 3 +#define NO_IO_REQUEST_BLOCK 4 +#define NO_AUDIO_DEVICE 5 diff --git a/amiga/sound.readme b/amiga/sound.readme new file mode 100644 index 0000000..ec86add --- /dev/null +++ b/amiga/sound.readme @@ -0,0 +1,99 @@ + +/**************************************************** + +Date and time of latest revision: + + +Wednesday 10-Jun-87 13:37:37 + +*******************************************************/ + + +USING THE AMIGA SOUND EFFECTS ROUTINE + + There are three source routines enclosed for your edification: + + 1) ONOFF.C -- a shell program that produces a couple of sound + effects, each one at two separate lengths. This is included + as an example of how to call sound effects and the sort of + error checking you might wish to do. + 2) INITONOFF.C -- loads the sound effect files from disk into + memory. + 3) AUDONOFF.C -- makes the actual noise. + + ERRLIST.H is an include file that contains the six error codes +returned from init(). It should be included in your main program. + + We have also included INITONOFF.O and AUDONOFF.O as compiled by the +Manx Aztec C compiler v. 3.40 for the Amiga. The sound effect files are +.DAT files set up by Russell. + + If you are not using Aztec, you will probably wish to recompile +INITONOFF.C and AUDONOFF.C using your own (Lattice?) compiler. This should +be a fairly straightforward (*) procedure. We have made liberal use of the +defines in "exec/types.h" and, to our knowledge, the declaration "int" appears +nowhere in either of these files. Furthermore, we have done a liberal amount +of type-casting. So it should suffice simply to recompile with Lattice, and +then link the resulting object files with your program. + + Linking in Aztec is fairly straightforward. We use: + + ln onoff.o initonoff.o audonoff.o -lm -lc + + This produces an executable file called ONOFF. In Lattice, if memory +serves me, you'll have to link with Lstartup.obj, c.lib, and amiga.lib. The +Aztec library m.lib contains the floating point routines necessary for Russell's +routine percalc() (in AUDONOFF.C); I don't know if Lattice has a comparable +library, and it may eventuate that you have to rewrite this routine to use +Amiga's floating point libraries. + + As you can see from the sample program ONOFF.C, calling a sound is +simple. Use the routine init(), which returns a SHORT value: + + error = init(soundname,toggle) + + "error" is one of the six codes in ERRLIST.H; a non-zero value signals +some problem with opening files or allocating memory. "soundname" is a string +containing the name of the sound effect file in question; this is declared as +UBYTE *soundname. "toggle" is a WORD: 1 = turn on sound, 0 = turn off sound. + + Russell's sounds come in two categories: (1) sounds that play a finite +number of times (usually once) and then turn themselves off; and (2) sounds +that cycle indefinitely. An indicator of the type of sound is built into +the sound file, and is transparent to the user. However, you should know that +with this version of the sound tool, EVEN THOUGH THE SOUND TURNS ITSELF OFF, +YOU ARE NOT DONE WITH IT. + + When you want the sound "orgasm.dat", you turn the sound on with +error = init("orgasm.dat",ON);. The init() routine will then open the +necessary files, allocate the necessary memory for the sound, read it into +memory, and close the files; it will then call audion() (in AUDONOFF) to +play the sound. + + 1) The sound may be an infinitely-cycling sound. Control of the pro- +gram will be returned to you, but the sound will go on forever; you can sit +and listen to it for hours. To get rid of it, you will want to transmit +error = init("orgasm.dat",OFF), which will call audion() to turn off the +sound, and will then free up the space in which the sound buffer is contained. + + 2) The sound may play only once, twice, etc. In this case, you'll +hear it once or twice, and then it will stop. However, nothing has been +automatically freed up; the next time you try to turn a sound on, your program +might conceivably suffer a horrible death. So, before you next call +error = init("hackdeath.dat",ON), be sure to call error = init("orgasm.dat",OFF) +so that all the allocated memory is released and nothing goes wrong. + + Note that any sound, of any duration, may be turned off at any time. +Even one-shot sounds may be turned off in the middle, if you so desire, by the +call error = init("one_shot.dat",OFF), though it is usually better practice +to let the little suckers run to completion. + + If you have any questions, call Don Harlow, at Activision ext. 5478. +Good luck! + +---------------------------------------------------------------------------- + +(*) I have threatened Jeff Steinwedel with a horrible death should I ever again +hear him tell anyone that I would be glad to take on some project that looks +totally "straightforward". When you find that this recompilation takes six +man-days, you may wish to threaten ME with a similar death... -- DH diff --git a/amiga/sound.spec b/amiga/sound.spec new file mode 100644 index 0000000..11aeec6 --- /dev/null +++ b/amiga/sound.spec @@ -0,0 +1,51 @@ + + SOUND id [,action, vol]: INT EXT:245 (ZIP, XZIP) + + Id specifies the sound. If zero, the last specified id is used. +BEEP (1) and BOOP (2) are defined for all micros. + + Action (1-4) is INIT, START (the default), STOP, or CLEANUP. + + Volume can range from 0-8. The default is the value defined in +each midi data file (normally the maximum). + + INIT + ------------ + Getting ready to produce a sound takes significant time, mostly to +read the data from disk. The samples for Lurking Horror take, on +average (for a 37K file), six seconds each to load. + + Once loaded, a sound can be started and stopped multiple times +without any noticeable delay. + + Sometimes it may be desirable to INIT a sound in advance, then +print things on the screen ("The doorbell chimes") and start the +sound without the awkward delay. Alternately, the sound could begin +/before/ the relevant description. + + INIT is optional. If omitted before a START, it will occur +implicitly. + + START + ------------ + Russell's sounds come in two categories: sounds that play a finite +number of times (usually once) and then turn themselves off, and +sounds that cycle indefinitely. In either case, control returns to +the game (on the Amiga, anyway) as soon as the sound starts. + + STOP + ------------ + STOP is useful for "environmental sounds" in the second +catagory above; for example, a noise that ends only when you leave a +particular room, and resumes when you reenter it. + + STOP is not required for "one-shot" sounds in the first catagory, +but it's desirable to use it anyway. Otherwise (on the Amiga) a +concurrent process may be blocked from access to the audio hardware. + + CLEANUP + ------------ + CLEANUP releases the memory buffers that were loaded during INIT. + + CLEANUP is optional. If omitted, it will occur implicitly before +the next INIT. diff --git a/amiga/split.c b/amiga/split.c new file mode 100644 index 0000000..1b1aca0 --- /dev/null +++ b/amiga/split.c @@ -0,0 +1,84 @@ +#include +#include + +#define BLKSIZE 512 + +main(argc, argv) +int argc; +char *argv[]; + { + FILE *in_fp, *out_fp, *fopen(); + char in_fname[FMSIZE], out_fname[FMSIZE], buffer[BLKSIZE]; + long maxsize, cursize; + int i, fnum, bytes; + + if (argc < 3 || argc > 4) + { + fprintf(stderr, "\nusage: split [].\n"); + exit(1); + } + + if ((in_fp = fopen(argv[1], "rb")) == NULL) + { + fprintf(stderr, "\nError opening <%s>\n", argv[1]); + exit(2); + } + + sscanf(argv[2], "%ld", &maxsize); + + if (maxsize == 0) + { + fprintf(stderr, "\nIllegal %ld.\n", maxsize); + exit(3); + } + + for (i = 0; in_fname[i] = argv[1][i]; ++i) + if (in_fname[i] == '.') + break; + + in_fname[i] = 0; + + for (fnum = 0, out_fp = NULL; feof(in_fp) == 0;) + { + if (out_fp == NULL) + { + ++fnum; + sprintf(out_fname, "%s.%03d", in_fname, fnum); + printf("Creating <%s>\n", out_fname); + + if ((out_fp = fopen(out_fname, "wb")) == NULL) + { + fprintf(stderr, "\nError opening <%s>\n", out_fname); + exit(4); + } + + cursize = 0; + } + + if ((maxsize - cursize) <= (long) BLKSIZE) + bytes = (int) (maxsize - cursize); + else + bytes = BLKSIZE; + + i = fread(buffer, 1, bytes, in_fp); + + if (fwrite(buffer, 1, i, out_fp) != i) + { + fprintf(stderr, "\nError writing file <%s>\n", out_fname); + exit(5); + } + + if ((cursize += (long) i) >= maxsize) /* can't be greater than */ + { + if (argc >= 4) /* any final char? */ + fwrite(argv[3], 1, 1, out_fp); + fclose(out_fp); + out_fp = NULL; + } + } + + fclose(in_fp); + printf("File <%s> split into %d files.\n", argv[1], fnum); + + exit(0); + } diff --git a/amiga/split.notes b/amiga/split.notes new file mode 100644 index 0000000..7591a4f --- /dev/null +++ b/amiga/split.notes @@ -0,0 +1,20 @@ + + I tried porting SPLIT.C on the Atari ST under two different +compilers, Alcyon (developers) and Lattice. Alcyon worked, Lattice didn't. + +Lattice +------- + o The fopen/fread/fwrite group is oriented towards text files, + and seems to choke when dealing with binary, even when the fopen + call uses the argument "rb"/"wb". A comment in the Lattice reference, + p103, about setting a global to force binary mode, seemed to have + no effect. + + o Also, fprintf calls seem to choke on the "\n" character. + +Alcyon +------ + o Syntax change: fopen(name, xb) --> fopenb(name, x) + + o the linker names three undefined symbols (seem to be library + functions), but it does not seem to affect the program. diff --git a/amiga/ss48 b/amiga/ss48 new file mode 100644 index 0000000..ad65af7 --- /dev/null +++ b/amiga/ss48 @@ -0,0 +1,29 @@ +Addbuffers df0: 10 +c:SetPatch >NIL: ;patch system functions +cd c: +echo "A500/A2000 Workbench disk. Release 1.3 version 34.20*N" +Sys:System/FastMemFirst ; move C00000 memory to last in list +BindDrivers +mount dh0: +MOUNT DH1: +echo " Mounting the PHOENIX ELECTRONICS INC. PHD-48 meg HardDrive" +ECHO " WITH WORKBENCH 1.3 AND FAST FILE SYSTEM" +ECHO " THE MOUNTLIST HAS TWO PARTITIONS" +cd dh0: +info +avail +setclock load ;load system time from real time clock (A1000 owners should + ;replace the SetClock load with Date +FF >NIL: -0 ;speed up Text +resident CLI L:Shell-Seg SYSTEM pure add; activate Shell +resident c:Execute pure +mount newcon: +; +failat 11 +run execute s:StartupII ;This lets resident be used for rest of script +wait >NIL: 5 mins ;wait for StartupII to complete (will signal when done) +; +SYS:System/SetMap usa1 ;Activate the ()/* on keypad +path ram: c: sys:utilities sys:system s: sys:prefs add ;set path for Workbench +LoadWB delay ;wait for inhibit to end before continuing +endcli >NIL: diff --git a/amiga/startupii b/amiga/startupii new file mode 100644 index 0000000..4077755 --- /dev/null +++ b/amiga/startupii @@ -0,0 +1,23 @@ +resident c:Resident pure +resident c:List pure ;pre-load LIST and CD +resident c:CD pure +resident c:Mount pure ;the next 3 are loaded for speed during startup +resident c:Assign pure +resident c:Makedir pure +;make IF, ENDIF, ELSE, SKIP, ENDSKIP, and ECHO resident if +;you use scripts much, and can afford the ram. +;also make Failat, WAIT, and ENDCLI resident if you use IconX a lot +makedir ram:t +assign T: ram:t ;set up T: directory for scripts +makedir ram:env ; set up ENV: directory +assign ENV: ram:env +makedir ram:clipboards ;set up CLIPS: assign +assign CLIPS: ram:clipboards +mount speak: ;just mounting doesn't take much ram at all +mount aux: +mount pipe: +resident Mount remove ;if you have enough ram, keep these resident +resident Assign remove ;by removing these lines +resident Makedir remove +; +break 1 C ;signal to other process its ok to finish diff --git a/amiga/support.info b/amiga/support.info new file mode 100644 index 0000000..492dd8c --- /dev/null +++ b/amiga/support.info @@ -0,0 +1,138 @@ + +Amiga problems, additional information +--------------------------------------------------------------------------- + +PROBLEM + + "When I run the story and try to change the window size, it crashes." + +DIAGNOSIS + + User probably has a 256K Amiga (the basic model) and is running out of + +memory. Opening or resizing any window (or hiding certain windows like the + +story's) temporarily uses a lot of memory. + + When memory is too low to comply, these actions SHOULD just be ignored. + +Because of a bug in Amiga, sometimes they cause a crash. + +FIX + + Don't change the window, or upgrade to 512K. + +------- + +PROBLEM + + "RESTORE says it can't locate my save file." + +DIAGNOSIS + + Careful of sub-directories (folders). If you started the story + +from within a sub-directory, save files will be put, by default, into the + +same sub-directory. If you save to a second disk and later want to + +restore from the first, you must explicitly specify the sub-directory. + +FIX + + Prefix the name of the restore file with a full pathname. + +For example, "df0:Gamedir/Savefile.Save" specifies the internal drive + +and the Gamedir subdirectory (yes, with a forward slash). + +------- + +PROBLEM + + "When I type the story name into the CLI, it says 'unknown command' + +or 'Story file open error'." + +DIAGNOSIS + + The story disk is not in the default drive. Or the story file is in + +a subdirectory which is not the default. The story name has to be typed into + +the CLI (command line interpreter) without any drive or directory prefixes. + +(For example, "df1:Zork1" will fail.) + +FIX + + Use the "cd" command to change the default drive/directory first. + +For example, "cd df1:" if the story disk is in the external drive. Or move + +the disk to the default drive. + +------- + +PROBLEM + + Run two games (or same game twice), when I quit the second one the + +machine crashes. + +DIAGNOSIS + + Bug. + +FIX + + Works in interpreter releases higher that 'A'. + +------- + +PROBLEM + + Says "Not enough available memory" or "Memory block allocation error." + +DIAGNOSIS/FIX + + In the first case, the story isn't finding the minimum amount of memory + +it needs to load. You can free up memory by quitting any other programs + +that may be running, and by closing all unnecessary windows. Or, you can + +make more memory available with the "F/" option (see refcard section X). + +TO MAXIMIZE THE MEMORY AVAILABLE TO THE STORY, START IT WITH "F/2000." + + In the second case, the story is finding enough free memory, but it's + +"fragmented" (not in one block). This can be caused moving things around + +on the desktop, or by opening and closing windows, or by running a program + +that doesn't completely "clean up" after itself. If the fixes for the first + +case don't work, try rebooting the machine. + +------- + +PROBLEM + + "When I click on an icon for a save file, an error message says + +'No default tool for this icon.'" + +DIAGNOSIS/FIX + + The desktop icon for a save file is useful for copying the file + +to another disk or deleting it, but the interpreter doesn't support + +clicking it to start the game from the saved position, a la Macintosh. + +To restore a saved file, user must first start the game in the + +usual way, and then type RESTORE. + diff --git a/amiga/temp.zil b/amiga/temp.zil new file mode 100644 index 0000000..8df8190 --- /dev/null +++ b/amiga/temp.zil @@ -0,0 +1,24 @@ +[from defs.zil] + + + + ,GL-SPACE-WIDTH>> + <- .N>> + + + + + > !\a> + + > + > + ) + > + + > + + + + + diff --git a/amiga/temp_s2.c b/amiga/temp_s2.c new file mode 100644 index 0000000..6891ee4 --- /dev/null +++ b/amiga/temp_s2.c @@ -0,0 +1,110 @@ +/****************************************************** + + Game Interface + +*******************************************************/ + +extern void bell_sound(); + +#define S_INIT 1 /* load data from disk */ +#define S_START 2 +#define S_STOP 3 /* stopped but ready to restart */ +#define S_CLEANUP 4 /* release the memory used */ + +#define S_BEEP 1 +#define S_BOOP 2 + +#define M_ON 1 +#define M_OFF 0 + +/*------------------------------*/ +/* md_sound */ +/*------------------------------*/ + +/* id=1-n or 0(mru), action=1-4, + volume=0-64 or -1(midi), repeat=1-n, 0(infinite) or -1(midi) */ + +WORD md_sound (id, action, vol, rep) +WORD id, action, vol, rep; +{ + static WORD last_id = 0; + static WORD inited = 0, started = 0; + char name[32]; + WORD i, err; + + if (id == 1 || id == 2) { + bell_sound(id); /* 1=beep, 2=boop */ + return(0); + } + if (id == 0) { /* use MRU effect */ + if (last_id == 0) return (0); /* none, exit */ + else id = last_id; + } + else if (id != last_id) { /* first get rid of old, if any */ + md_sound (last_id, S_CLEANUP, vol, rep); /* (recurse) */ + last_id = id; + } + +/* Use id to make generic names (don't want names to give away plot!) */ + + i = stccpy (name, "S", 32); /* make "[SOUND/] Sx.NAM" */ +/** stcu_d (&name[i], id, 16); **/ /* Lattice bug: i is one too high */ + stcu_d (&name[1], id, 16); + strcat (name, ".NAM"); + + if (action == S_INIT || action == S_START) { + if (!inited) { + err = init (name, M_ON); + if (err != ALL_OK) { + showerr (err); /* inform user */ + return (err); + } + inited = 1; + } + } + if (action == S_START) { + md_sound (id, S_STOP, vol, rep); /* reset (if restarting) */ + err = audion (M_ON, vol, rep); + if (err != ALL_OK) { + showerr (err); /* inform user */ + return (err); + } + started = 1; + } + if (action == S_STOP || action == S_CLEANUP) { + if (started) { + audion (M_OFF, vol, rep); /* stop sound */ + started = 0; + } + } + if (action == S_CLEANUP) { /* free resources */ + if (inited) { + init (name, M_OFF); + inited = 0; + } + last_id = 0; /* back to original state */ + } + return (ALL_OK); +} + +/*------------------------------*/ +/* showerr */ +/*------------------------------*/ + +showerr (err) /* inform user of problem */ +WORD err; +{ + +} + +/*------------------------------*/ +/* end_sound */ +/*------------------------------*/ + +/* This "pseudo-interrupt" is called from the 68K kernel. + Check for end-of-sound flag; if detected, reset it and return TRUE. */ + +BOOL end_sound () +{ +} + diff --git a/amiga/temp_sound.asm b/amiga/temp_sound.asm new file mode 100644 index 0000000..2929996 --- /dev/null +++ b/amiga/temp_sound.asm @@ -0,0 +1,142 @@ + +*********************** ax1 ****************************** + + XREF _german_convert + XREF _end_sound * END-OF-SOUND CHECK + +* 16 FEB 88 DBB ADDED SOUND, SOUND INTERRUPTS (GAMINT) +* FIXED COPYT/PRINTT PAGING BUG +* XZIP 'B' FROZEN + +SFUNC EQU TCOUNT-2 * FUNCTION TO CALL UPON SOUND-END +SCOUNT EQU SFUNC-2 * #OPS TO WAIT BEFORE NEXT SOUND-END CHECK + + +*********************** ax2 ****************************** + +**** OPINPUT **** + +INPX4 BSR GAMINT1 * CHECK FOR GAME INTERRUPT (SOUND, ETC) + + BSR ITTYIN * CHECK FOR A KEY << DON'T WAIT! >> + + + +* ---------------------- +* OPSOUND +* ---------------------- + +* MAKE A SOUND +* ARG1 = ID: 1=BEEP, 2=BOOP, 3+ ARE SPECIAL, 0=MRU +* [ARG2] = ACTION: 1=INIT, [2=START], 3=STOP, 4=CLEANUP +* [ARG3] = COUNT (HIBYTE): -1=INFINITE, [0=USE MIDI COUNT], 1-254=FINITE +* VOL (LOBYTE): 0=MIN, 8=MAX, [-1=USE MIDI VOLUME] +* [ARG4] = INTERRUPT FUNCTION + +OPSOUND NOP * REQUEST AN ARGBLK + LEA DEFBLK(A6),A1 * USE A DEFAULT ARGBLK, TOO + MOVE.W #4,(A1) * 4 ARGS MAX + MOVE.W #2,ARG2(A1) * DEFAULT ACTION = "START" + MOVE.W #$00FF,ARG3(A1) * DEFAULT COUNT=0/VOL=-1 (USE MIDI DATA) + CLR.W ARG4(A1) * DEFAULT INTERRUPT HANDLER = NONE + BSR SETDEF * SET UP DEFAULTS + + MOVE.W ARG4(A0),SFUNC(A6) * SAVE INTERRUPT HERE + MOVE.W ARG3(A0),D2 * COUNT/VOL + MOVE.W D2,D3 + EXT.W D2 * VOL (16 BITS) + LSR.W #8,D3 * COUNT (16 BITS, UNLESS -1) + CMPI.B #$FF,D3 * -1? + BNE.S OPSDX1 + EXT.W D3 * YES, MAKE 16 BITS + +OPSDX1 MOVE.W ARG2(A0),D1 * ACTION + MOVE.W ARG1(A0),D0 * SOUND ID + BRA DOSOUND + + +*********************** ax3 ****************************** + +NXTINS BSR GAMINT * CHECK FOR GAME INTERRUPT (SOUND, ETC) + BSR NXTBYT * GET THE NEXT INSTRUCTION BYTE + +*********************** ax4 ****************************** + +* ---------------------- +* DOSOUND +* ---------------------- + +* AMIGA: ADJUST ARGS +* VOLUME: 0-64, -1=USE MIDI VOL +* COUNT: 0=INFINITE, 1-254=FINITE, -1=USE MIDI COUNT + +DOSOUND TST.W D2 + BLT.S DOSDX1 + ASL.W #3,D2 * MAP 0-8 TO 0-64 + +DOSDX1 TST.W D3 + BGT.S DOSDX2 * IF 1-254, JUST PASS ALONG + ADDQ.W #1,D3 * MAP -1 TO 0 + BEQ.S DOSDX2 + MOVEQ #-1,D3 * MAP 0 TO -1 + +DOSDX2 SAVEREGS + MOVE.L D3,-(SP) * COUNT + MOVE.L D2,-(SP) * VOLUME + MOVE.L D1,-(SP) * ACTION + MOVE.L D0,-(SP) * ID + JSR _md_sound + FLUSH 16 + RESTREGS + RTS + +* ---------------------- +* GAMINT, GAMINT1 +* ---------------------- + +* PERIODICALLY CHECK FOR GAME INTERRUPTS + +* NOTE: BECAUSE THE INTERPRETER AS A WHOLE IS /NOT/ RE-ENTRANT, THIS +* ROUTINE CHOULD BE CALLED ONLY FROM THE TOP OF THE MAIN LOOP (NXTINS), AND +* (PERHAPS) FROM OPREAD/OPINPUT (SO SOUNDS CAN CHAIN BETWEEN MOVES). +* BUT IT SHOULD /NOT/ BE CALLED FROM ITTYIN, SINCE THAT IS ALSO CALLED +* FROM [MORE], AND THE INTERPRETER STATE IS UNDEFINED. + +SKPCNT EQU 50 * 2500 ops/sec (max) ==> 50 ints/sec (max) + +* ENTRY POINT FROM MAIN LOOP +* To avoid cutting into interpreter performance too much, we keep a +* simple counter, and only occasionally perform the (somewhat costlier) +* check for a sound interrupt. + +GAMINT SUBQ.W #1,SCOUNT(A6) * TIME FOR A SOUND CHECK? + BLE.S GAMIX1 + RTS * NO, QUICK EXIT +GAMIX1 MOVE.W #SKPCNT,SCOUNT(A6) * YES, RESET COUNTER AND FALL THRU + +* ENTRY POINT FROM INPUT-WAIT LOOP +* While awaiting Amiga input, we awaken only 10 times/sec anyway, so check +* for sound every time. Might actually prefer it be a bit more frequent. +* Note: called from OPREAD/OPINPUT; probably safe to call interrupt function +* as long as it doesn't itself call OPREAD/OPINPUT. + +GAMINT1 SAVEREGS + +* (could check first for valid SFUNC(A6), skip end-check if none, +* but then end event would hang around unreported ...) + + RESWORD + JSR _end_sound * END-OF-SOUND CHECK + POPWORD * NON-ZERO IF END DETECTED + BEQ.S GAMIX3 + + MOVE.W SFUNC(A6),D0 * SOUND-INTERRUPT FUNCTION ("START NEXT") + BEQ.S GAMIX3 * NONE + BSR INCALL * CALL IT (INTERNALLY) +*** TST.W D0 * (NO RETURN VAL) + +GAMIX3 +*** JSR _int_key * TYPE-AHEAD CHECK (here or from real int?) + RESTREGS + RTS + diff --git a/amiga/tftp.c b/amiga/tftp.c new file mode 100644 index 0000000..4e348ff --- /dev/null +++ b/amiga/tftp.c @@ -0,0 +1,322 @@ + +/*------------------------------------------------------*/ +/* File transfer program using TFTP format */ +/*------------------------------------------------------*/ + +#define CHAR unsigned char +#define INT short /* 16 bits for 68K compatibility */ +#define LONG long + +#define BOOL short /* 1 or 0 */ +#define TRUE 1 +#define FALSE 0 + +#define VOID int +#define GLOBAL /**/ + +#define FOREVER for(;;) + +#define SHOW (val, fmt) printf ("%s=fmt\n", "val", val) + +/* SHOW (ch, %02x); */ /* prints "ch = [hex value of ch]" */ + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ + + LONG game_channel; /* refnum */ + + unsigned short checksum1; /* given */ + unsigned short checksum2; /* computed */ + +/************************************************************************/ +/* Error Handling */ +/************************************************************************/ + +/*------------------------------*/ +/* show_msg */ +/*------------------------------*/ +VOID +show_msg (str) /* write to console window */ + +CHAR *str; +{ + line_out (str, strlen (str)); +} + +VOID +show_msgCR (str) /* adding a CR */ + +CHAR *str; +{ + line_out (str, strlen (str)); + char_out (13); +} + +VOID +show_CR () /* CR only */ +{ + char_out (13); +} + +/************************************************************************/ +/* Low Level Functions */ +/************************************************************************/ + +#define CHCMD 126 +#define CHDTA 0 +#define CHEOF 4 + +#define CHACK 2 +#define CHNAK 5 + + +/*------------------------------*/ +/* SendCmd */ +/*------------------------------*/ + +VOID +SendCmd (ch) + +CHAR ch; /* ACK or NAK */ +{ + CHAR buff[2]; + + buff[0] = CHCMD; + buff[1] = ch; + + write_serial (&buff, 2); +} + +/*------------------------------*/ +/* SendAck */ +/*------------------------------*/ +VOID +SendAck () + +{ + char_out ('A'); + + SendCmd (CHACK); /* do last, triggers next transmission */ +} + +/*------------------------------*/ +/* SendNak */ +/*------------------------------*/ +VOID +SendNak (code) + +CHAR code; /* 1 = CMD error, 2 = HEADER error, 3 = checksum error */ +{ + CHAR string1[64], string2[64]; + + char_out ('N'); + + if (code != 3) /* echo the error code */ + char_out (code + '0'); + else /* show the two sums */ + { + stci_d (&string1, checksum1, 64); + stci_d (&string2, checksum2, 64); + + strcat (&string1, "/"); + strcat (&string1, &string2); + strcat (&string1, "/"); + + show_msg (&string1); + } + + SendCmd (CHNAK); /* do last, triggers next transmission */ +} + +/*------------------------------*/ +/* GetCh */ +/*------------------------------*/ +CHAR +GetCh () /* read a generic char from port */ + +{ + CHAR buff[2]; + +/* CHAR hex1, hex2; */ + + read_serial (&buff, 1); + +/* for debugging, echo char (high + low nibble) to screen */ + +/* hex1 = buff[0]; hex1 = hex1 >> 4; + hex2 = buff[0]; hex2 = hex2 & 15; + + char_out (hex1 + '0'); + char_out (hex2 + '0'); + char_out (','); +*/ + return (buff[0]); +} + +/*------------------------------*/ +/* GetCmd */ +/*------------------------------*/ +CHAR +GetCmd () + +{ + while (GetCh () != CHCMD) /* wait for header code */ + { + } + + return (GetCh ()); /* DATA or EOF */ +} + +/*------------------------------*/ +/* GetHdr */ +/*------------------------------*/ +BOOL +GetHdr () /* called after DATA command is received */ + +{ + if (GetCh () != 1) return (FALSE); + if (GetCh () != 0) return (FALSE); + if (GetCh () != 254) return (FALSE); + if (GetCh () != 255) return (FALSE); + + return (TRUE); +} + +/*--------------------------------------*/ +/* GetBlock (formerly RECV) */ +/*--------------------------------------*/ +BOOL +GetBlock (buffer) /* get block (256 bytes) plus checksum, verify it */ + +CHAR *buffer; +{ + INT i; + CHAR *temp; + +/* temp = buffer; + for (i=0; i<256; i++) + *temp++ = GetCh (); +*/ + read_serial (buffer, 256); /* read block in one gulp */ + +/* temp = (CHAR *) &checksum1; + for (i=0; i<2; i++) + *temp++ = GetCh (); +*/ + read_serial (&checksum1, 2); /* read checksum */ + + checksum2 = 0; + temp = buffer; + + for (i=0; i<256; i++) + checksum2 += *temp++; /* compute our checksum */ + + if (checksum1 == checksum2) + return (TRUE); + else + return (FALSE); +} + +/*------------------------------*/ +/* GetFile */ +/*------------------------------*/ +INT +GetFile () /* return zero for success */ + +{ + CHAR command; + CHAR block[256]; + + while ((command = GetCmd ()) != CHEOF) + { + if (command != CHDTA) + SendNak (1); + + else if (! (GetHdr () )) /* data coming, suck up header */ + SendNak (2); + + else if (! (GetBlock (&block) )) + SendNak (3); /* must be checksum error */ + + else /* write block to disk, exit if error */ + { + if (write_game (game_channel, 256, &block) != 0) + { + show_msgCR ("Disk write error"); + return (1); + } + SendAck (); /* okay, loop back for next */ + } + } + + SendAck (); /* acknowledge the EOF */ + return (0); +} + + +/************************************************************************/ +/* Top Level */ +/************************************************************************/ + +/*------------------------------*/ +/* TFTP */ +/*------------------------------*/ +VOID +TFTP () +{ + INT error; + CHAR *gamename; + + show_msgCR (" ****** TFTP for Commodore Amiga ******"); + show_CR (); + + init_serial (TRUE); /* open serial channel */ + + gamename = "df1:Story.Data"; + error = open_game (gamename, &game_channel); + + if (error) + { + show_msg ("File open error: "); + show_msgCR (gamename); + } + else + { + show_msg ("Writing to file "); + show_msg (gamename); + show_msg (", strike any key to begin ..."); + + char_in (); char_out (13); + + error = GetFile (); + close_game (game_channel); + } + + init_serial (FALSE); /* close the serial port */ + + show_CR (); + if (!error) show_msg ("Transfer complete. "); + + show_msg ("Strike any key to exit ... "); + char_in (); +} + +/*------------------------------*/ +/* main */ +/*------------------------------*/ +INT +main () +{ + INT error; + + error = z_init (); /* zero if OK */ + + if (!error) + TFTP (); /* perform the file transfer */ + + z_exit (); /* clean up */ + + return (error); +} + diff --git a/amiga/tftp.info b/amiga/tftp.info new file mode 100644 index 0000000..485096e --- /dev/null +++ b/amiga/tftp.info @@ -0,0 +1,21 @@ + +HOW TO USE THE AMIGA TFTP +------------------------------------------------------------------------------- + +1. The DEC20-Amiga connection should NOT have pins 2-3 reversed. + Because the serial port on the Amiga is female, it may be convenient + to use two crossover cables, which cancel each other out. + +2. Boot the Workbench/TFTP disk in drive 0. Workbench normally sets + the serial port to 9600 baud. This setting can be changed with the + Amiga Preferences tool. + +3. Put a copy of the Amiga Create disk in drive 1. + +4. Run TFTP in the usual way. TFTP will create a file on the disk + in drive 1 called "Story.Data". + + Note: if an error occurs, Amiga TFTP shows an 'N' followed by some + diagnostics. '1' means bad command, '2' means bad header bytes, and + a string of numbers of the form 'x/y' indicates mismatched checksums. + diff --git a/amiga/tftp_io.c b/amiga/tftp_io.c new file mode 100644 index 0000000..c37a868 --- /dev/null +++ b/amiga/tftp_io.c @@ -0,0 +1,799 @@ + +/*------------------------------------------------------*/ +/* AMIGA GENERIC INTERFACE (TFTP) */ +/*------------------------------------------------------*/ + +#include "exec\types.h" +#include "exec\exec.h" + +#include "libraries\dos.h" +#include "libraries\dosextens.h" + +#include "intuition\intuition.h" /* for AllocRemember */ +#include "intuition\intuibase.h" + +#include "devices\serial.h" /* for serial port I/O */ + +#define CHAR unsigned char +#define INT short /* 16 bits for 68K compatibility */ +#define LONG long + +#define VOID int +#define GLOBAL /**/ + +#define FOREVER for(;;) + + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ + +struct IOExtSer XIOExtSer; /* for serial device, IOStdReq+ */ +struct MsgPort XMsgPort; + + LONG con_file; /* console file refnum */ +/* LONG ser_file; */ /* serial file refnum */ + +/* This slot returns file refnums to caller (function returns an error code). + Better solution -- return refnum through a VAR type parameter */ + + LONG temp_channel; + + INT columns, cur_column; /* cursor info */ + INT rows, cur_row; /* cur_row in 0 .. rows-1 */ + + INT split_row; /* first row in scrolling area */ + + CHAR savename[64]; /* buffer for file_select dialog */ + CHAR saveback[64]; /* buffer for default name */ + +/* These vars increase the speed of disk reads */ + + LONG old_channel = -1; + LONG old_offset = -1; + +struct IntuitionBase *IntuitionBase; +struct Remember *RememberKey; + +/************************************************************************/ +/* Low Level Console Device I/O */ +/************************************************************************/ + +/*------------------------------*/ +/* write_console */ +/*------------------------------*/ +VOID +write_console (string, len) /* send raw string to console device */ + +CHAR *string; +INT len; +{ + Write (con_file, string, len); /* AmigaDOS write */ +} + +/*------------------------------*/ +/* read_console */ +/*------------------------------*/ +CHAR +read_console () /* get a char from console device */ +{ + CHAR the_char; + +/* RAW read always completes after a single character */ + + Read (con_file, &the_char, 1); + return (the_char); +} + +/*------------------------------*/ +/* send_control_seq */ +/*------------------------------*/ + +#define begin_mark '\233' /* 0x9B (one byte only) */ + +VOID +send_control_seq (string) /* write it, prefixed with control char */ + +CHAR *string; +{ + CHAR temp; + + temp = begin_mark; + + write_console (&temp, 1); + write_console (string, strlen (string)); +} + +/*------------------------------*/ +/* get_control_seq */ /* read chars into buffer */ +/*------------------------------*/ + +VOID +get_control_seq (buffer, end_mark) + +CHAR *buffer; +CHAR end_mark; +{ + CHAR the_char; + INT i; + + while ((the_char = read_console ()) != begin_mark) + { + /* ignore any prior chars, also starting mark */ + } + + i = 0; + while ((the_char = read_console ()) != end_mark) + { + buffer[i] = the_char; + i++; + } + + buffer[i] = end_mark; /* end with the ending mark */ + buffer[i+1] = 0; /* make it ASCIZ */ +} + +/************************************************************************/ +/* Low Level Functions */ +/************************************************************************/ + + + +/************************************************************************/ +/* Cursor Positioning */ +/************************************************************************/ + +/* ALL absolute cursor positioning should go through these two routines */ + +/*------------------------------*/ +/* read_cursor_pos */ +/*------------------------------*/ + +VOID +read_cursor_pos () /* read, unparse, and digitize cursor position, + store in globals */ +{ + CHAR cursor_info[64]; + + CHAR *startx,*endx; /* string limits */ + CHAR *starty,*endy; + + int x_value,y_value; /* careful of type here */ + +/* read in string representing cursor position -- format is ;R */ + + send_control_seq ("6n"); + get_control_seq (&cursor_info, 'R'); + +/* setup pointers to x and y strings, and make them asciz */ + + endy = (CHAR *) strchr (&cursor_info, ';'); + endx = (CHAR *) strchr (&cursor_info, 'R'); + + starty = (CHAR *) &cursor_info; endy[0] = 0; + startx = endy + 1; endx[0] = 0; + +/* convert decimal strings to integers, + normalize (cur_row in 0 .. rows - 1), + leave results in globals (global type may be different) */ + + stcd_i (starty, &y_value); cur_row = y_value - 1; + stcd_i (startx, &x_value); cur_column = x_value - 1; +} + +/*------------------------------*/ +/* write_cursor_pos */ +/*------------------------------*/ + +VOID +write_cursor_pos (x_new, y_new) /* reset the cursor position */ + +INT x_new,y_new; +{ + CHAR cursor_info[64]; + CHAR x_str[32]; + CHAR y_str[32]; + +/* normalize co-ords (y_new in 0 .. rows - 1), convert integers to strings */ + + stcu_d (&x_str, x_new + 1, 32); + stcu_d (&y_str, y_new + 1, 32); + +/* combine and transmit the strings */ + + cursor_info[0] = 0; /* asciz */ + + strcat (&cursor_info, &y_str); + strcat (&cursor_info, ";"); + strcat (&cursor_info, &x_str); + strcat (&cursor_info, "H"); + + send_control_seq (&cursor_info); +} + + +/*------------------------------*/ +/* amiga_scroll */ +/*------------------------------*/ + +VOID +amiga_scroll () /* method depends on cursor position */ +{ + CHAR char_seq[2]; + + read_cursor_pos (); /* get cursor pos into globals */ + + if (cur_row < rows) /* not at bottom of screen? */ + { + char_seq[0] = 13; + char_seq[1] = 10; /* CR, tack on a LF */ + write_console (&char_seq, 2); + } + else /* at bottom, delete top line to scroll */ + { + write_cursor_pos (0, split_row); + send_control_seq ("M"); + write_cursor_pos (0, cur_row); + } +} + +/************************************************************************/ +/* Screen Handling */ +/************************************************************************/ + +/*------------------------------*/ +/* clear_eol */ +/*------------------------------*/ +VOID +clear_eol () +{ + send_control_seq ("K"); /* clear to EOL */ +} + +/*------------------------------*/ +/* clear_screen */ +/*------------------------------*/ +VOID +clear_screen () +{ + write_cursor_pos (0,0); + + send_control_seq ("J"); + + write_cursor_pos (0,1); /* move cursor to second row */ +} + +/*------------------------------*/ +/* line_out */ +/*------------------------------*/ + +VOID +line_out (string, len) /* draw a string at current position, */ + +CHAR *string; +INT len; +{ + write_console (string, len); +} + +/*------------------------------*/ +/* char_out */ +/*------------------------------*/ + +VOID +char_out (the_char) /* if CR or BS, special case, else draw the char */ + +CHAR the_char; +{ + CHAR char_seq[4]; + + if (the_char == 13) + { + amiga_scroll (); + } + + else if (the_char == 8) + { + char_seq[0] = 8; + char_seq[1] = 32; /* erase the current char */ + char_seq[2] = 8; + write_console (&char_seq, 3); + } + + else write_console (&the_char, 1); +} + +/*------------------------------*/ +/* char_in */ +/*------------------------------*/ +CHAR +char_in () /* wait for keyboard input */ +{ + CHAR the_char; + + the_char = read_console (); + + if (the_char == begin_mark) + { + the_char = 'X'; /* don't echo begin_mark! */ + } + + return (the_char); +} + +/************************************************************************/ +/* File Selection */ +/************************************************************************/ + + +/*------------------------------*/ +/* file_select */ +/*------------------------------*/ +INT +file_select (opsave, drive) /* get file and pathspec from user, */ + /* combine and leave in SAVENAME */ + +INT opsave; /* zero if restore, otherwise save */ +CHAR drive; /* drive to use, zero for default */ +{ + + +} + +/*------------------------------*/ +/* new_default */ +/*------------------------------*/ + +VOID +new_default (okay) /* called at end of each SAVE/RESTORE */ + +INT okay; +{ + if (okay) /* dest <- source */ + { + strcpy (saveback, savename); /* update old defaults */ + } + else + { + strcpy (savename, saveback); /* retrieve old defaults */ + } +} + +/************************************************************************/ +/* Serial Port I/O */ +/************************************************************************/ + +/*------------------------------*/ +/* init_serial */ +/*------------------------------*/ + +VOID +init_serial (open) /* initialize/uninitialize the serial port */ + +INT open; +{ + if (open) + { + if (OpenDevice ("serial.device", 0, &XIOExtSer, 0) != 0) + { + /* error */ + } + /* set up the message port in the I/O request */ + + XMsgPort.mp_Node.ln_Type = NT_MSGPORT; + XMsgPort.mp_Flags = 0; + XMsgPort.mp_SigBit = AllocSignal (-1); + XMsgPort.mp_SigTask = (struct Task *) FindTask (NULL); + + AddPort (&XMsgPort); + XIOExtSer.IOSer.io_Message.mn_ReplyPort = &XMsgPort; + + /* configure the port to read 8 data bits */ + XIOExtSer.io_ReadLen = 8; + + /* disable xON-xOFF (causes loss of valid data) */ + XIOExtSer.io_SerFlags |= SERF_XDISABLED; + +/* XIOExtSer.io_WBufLen = 2; (was zero) */ + XIOExtSer.io_BrkTime = (30 * 1000 * 1000); + + XIOExtSer.IOSer.io_Command = SDCMD_SETPARAMS; + DoIO (&XIOExtSer); + } + + else /* clean up the various structures we created */ + { + RemPort (&XMsgPort); + + FreeSignal (XMsgPort.mp_SigBit); + + CloseDevice (&XIOExtSer); + } +} + +/*------------------------------*/ +/* read_serial */ +/*------------------------------*/ + +LONG +read_serial (buffer, length) + +CHAR *buffer; +LONG length; +{ +/* LONG result; + + result = Read (ser_file, buffer, length); + + if (result < 0) + return (result); + else return (0); +*/ + XIOExtSer.IOSer.io_Data = (APTR) buffer; + XIOExtSer.IOSer.io_Length = length; + + XIOExtSer.IOSer.io_Command = CMD_READ; + DoIO (&XIOExtSer); + +/* SendIO (&XIOExtSer); */ /* due to bug in DoIO */ +} + +/*------------------------------*/ +/* write_serial */ +/*------------------------------*/ + +LONG +write_serial (buffer, length) + +CHAR *buffer; +LONG length; +{ +/* if (Write (ser_file, buffer, length) == -1) + return IoErr (); + else return (0); +*/ + XIOExtSer.IOSer.io_Data = (APTR) buffer; + XIOExtSer.IOSer.io_Length = length; + + XIOExtSer.IOSer.io_Command = CMD_WRITE; + DoIO (&XIOExtSer); +} + + + +/************************************************************************/ +/* Disk I/O */ +/************************************************************************/ + + +/*------------------------------*/ +/* read_file */ +/*------------------------------*/ + +LONG +read_file (channel, offset, length, buffer) + +LONG channel; +LONG offset, length; +CHAR *buffer; +{ + +/* disk access speed is increased, if unnecessary seeks are eliminated */ + + if (! ((channel == old_channel) & (offset == old_offset))) + { + if (Seek (channel, offset, -1) == -1) /* AmigaDOS */ + { + old_offset = -1; /* force seek next time */ + return IoErr (); + } + } + + old_channel = channel; + old_offset = offset + length; + + if (Read (channel, buffer, length) == -1) + return IoErr (); + else return (0); /* zero means no error */ +} + + +/*------------------------------*/ +/* write_file */ +/*------------------------------*/ + +LONG +write_file (channel, offset, length, buffer) + +LONG channel; +LONG offset, length; +CHAR *buffer; +{ + if (Seek (channel, offset, -1) == -1) /* AmigaDOS */ + return IoErr (); + + if (Write (channel, buffer, length) == -1) + return IoErr (); + else return (0); /* zero means no error */ +} + + +/*------------------------------*/ +/* create_file */ +/*------------------------------*/ + +LONG +create_file () /* create AND OPEN a new file, */ + /* leave channel in temporary var */ +{ + temp_channel = Open (savename, MODE_NEWFILE); + + if (temp_channel == 0) + return (IoErr ()); + else return (0); /* zero means OK */ +} + + +/*------------------------------*/ +/* open_file */ +/*------------------------------*/ + +LONG +open_file () /* open an existing file, return channel */ +{ + temp_channel = Open (savename, MODE_OLDFILE); + + if (temp_channel == 0) + return (IoErr ()); + else return (0); /* zero means OK */ +} + +/*------------------------------*/ +/* close_file */ +/*------------------------------*/ + +LONG +close_file (channel) + +LONG channel; +{ + Close (channel); + + return (0); /* no error codes? */ +} + + +/*------------------------------*/ +/* delete_file */ +/*------------------------------*/ + +LONG +delete_file () +{ + LONG success; /* actually BOOLEAN */ + + success = DeleteFile (savename); + + if (success) + return (0); + else return (1); +} + + +/*------------------------------*/ +/* exist_file */ +/*------------------------------*/ + +LONG +exist_file () +{ + LONG filelock; + + filelock = Lock (savename, ACCESS_WRITE); + + if (filelock == 0) /* file does not exist */ + return (0); + + UnLock (filelock); /* exists, undo lock */ + + return (1); /* and indicate duplicate file */ +} + +/*------------------------------*/ +/* open_game */ +/*------------------------------*/ + +LONG +open_game (gamename, channel) + +CHAR *gamename; +LONG *channel; /* return file refnum through this ptr */ +{ + *channel = Open (gamename, MODE_NEWFILE); + + if (*channel == 0) + return (IoErr ()); + else return (0); /* zero means OK */ +} + +/*------------------------------*/ +/* close_game */ +/*------------------------------*/ + +LONG +close_game (channel) + +LONG channel; +{ + Close (channel); + + return (0); /* no errors in AmigaDOS ? */ +} + +/*------------------------------*/ +/* write_game */ +/*------------------------------*/ + +LONG +write_game (channel, length, buffer) /* no Seeking for TFTP */ + +LONG channel; +LONG length; +CHAR *buffer; +{ +/* if (Seek (channel, offset, -1) == -1) + return IoErr (); +*/ + if (Write (channel, buffer, length) != length) + return IoErr (); + else return (0); /* zero means no error */ +} + + + +/************************************************************************/ +/* Memory Management */ +/************************************************************************/ + +/*------------------------------*/ +/* c_maxmem */ +/*------------------------------*/ + +LONG +c_maxmem () /* return size of available memory pool */ +{ + return (AvailMem (MEMF_PUBLIC)); +} + +/*------------------------------*/ +/* c_getmem */ +/*------------------------------*/ + +LONG +c_getmem (nbytes) + +LONG nbytes; +{ +/* return (AllocMem (nbytes, MEMF_PUBLIC)); */ /* zero if failed */ + +/* This routine calls the AllocMem function, but also allocates a LINK NODE + and saves the data needed for automatic de-allocation when the program ends. +*/ + + return (AllocRemember (&RememberKey, nbytes, MEMF_PUBLIC)); +} + +/************************************************************************/ +/* Initializations */ +/************************************************************************/ + +/*------------------------------*/ +/* z_init */ +/*------------------------------*/ +INT +z_init () +{ + CHAR *name; + +/* open the console device */ + + name = "raw:0/0/640/200/"; /* untitled */ + + if ((con_file = Open (name, MODE_NEWFILE )) == 0) + { + return (101); + } + +/* and the serial device */ + +/* ser_file = Open ("SER:", MODE_OLDFILE); */ + +/* and the Intuition Library */ + + IntuitionBase = (struct IntuitionBase *) + OpenLibrary ("intuition.library", 0); + + if (IntuitionBase == 0) + return (103); + + RememberKey = 0; /* set up for memory allocation */ + + strcpy (saveback, "Story.Save"); /* initial default */ + + rows = 100; /* force normal scrolling always */ + + return (0); +} + +/*------------------------------*/ +/* z_exit */ +/*------------------------------*/ + +VOID +z_exit () +{ + +/* De-allocate the various pieces of memory we allocated */ + + FreeRemember (&RememberKey, TRUE); + + CloseLibrary (IntuitionBase); + +/* Close (ser_file); */ + Close (con_file); +} + +/************************************************************************/ +/* Diagnostics (Temporary) */ +/************************************************************************/ + +/*------------------------------*/ +/* z_test */ +/*------------------------------*/ + +z_test() +{ + CHAR mychr; + + c_maxmem (); c_getmem (16); /* test memory functions */ + c_getmem (16); c_maxmem (); + + FOREVER /* do input, output, scroll, until 'quit' */ + { + mychr = char_in (); + + if (mychr == 'q') break; /* leave the loop */ + + else if (mychr == 'z') /* print a string */ + { + line_out ("xyz", 3); + char_out (13); + } + + else char_out (mychr); /* echo the char */ + } +} + +/************************************************************************/ +/* Top Level */ +/************************************************************************/ + +/*------------------------------*/ +/* dummy_main */ +/*------------------------------*/ +INT +dummy_main () +{ + INT error; + + error = z_init (); /* zero if OK */ + +/* if (!error) */ +/* z_test (); */ +/* START (); */ + + z_exit (); /* clean up */ + + return (error); +} + diff --git a/amiga/tftp_tst.c b/amiga/tftp_tst.c new file mode 100644 index 0000000..ae4cf73 --- /dev/null +++ b/amiga/tftp_tst.c @@ -0,0 +1,82 @@ + +/*------------------------------------------------------*/ +/* TFTP test program */ +/*------------------------------------------------------*/ + +#define CHAR unsigned char +#define INT short /* 16 bits for 68K compatibility */ +#define LONG long + +#define BOOL short /* 1 or 0 */ +#define TRUE 1 +#define FALSE 0 + +#define VOID int +#define GLOBAL /**/ + +#define FOREVER for(;;) + + +/************************************************************************/ +/* Error Handling */ +/************************************************************************/ + +/*------------------------------*/ +/* show_message */ +/*------------------------------*/ +VOID +show_message (str) /* display in console window */ + +CHAR *str; +{ + line_out (str, strlen (str)); + + char_out (13); /* add the CR */ +} + +/************************************************************************/ +/* Top Level */ +/************************************************************************/ + +/*------------------------------*/ +/* main +/*------------------------------*/ +VOID +main () +{ + CHAR c[4]; + + z_init (); + init_serial (TRUE); + + show_message ("TFTP Test Program, strike any key to begin ... "); + + char_in (); + + show_message ("Reading SERIAL.DEVICE: "); + +/* LONG file; + + file = open ("SER:", 2); + if (file == -1) + show_message (" Serial device open error\n"); + else +*/ + FOREVER + { + read_serial (&c, 3); + + c[3] = 0; /* asciz */ + show_message (&c); + + if (c[0] == 'Q') break; + } + + show_message ("Transfer complete, strike any key to exit ..."); + + char_in (); + + init_serial (FALSE); + + z_exit (); +} diff --git a/amiga/xzip.c b/amiga/xzip.c new file mode 100644 index 0000000..247e08c --- /dev/null +++ b/amiga/xzip.c @@ -0,0 +1,22 @@ + +#include "exec/types.h" +#include "exec/exec.h" +#include "exec/libraries.h" /* for Library.lib_Version */ +#include "libraries/dos.h" +#include "libraries/dosextens.h" + +#include "intuition/intuition.h" /* for AllocRemember */ +#include "intuition/intuitionbase.h" + +#include "workbench/icon.h" +#include "workbench/workbench.h" /* for disk objects */ + +#include "graphics/text.h" /* SetSoftStyle flags */ +#include "graphics/rastport.h" /* SetDrMode flags */ +#include "graphics/gfxbase.h" /* for screen size vars */ + +#include "hardware/intbits.h" /* for interrupt flag */ + +#include "xzip1.c" +#include "xzip2.c" +#include "xzip3.c" diff --git a/amiga/xzip1.c b/amiga/xzip1.c new file mode 100644 index 0000000..6bd62ba --- /dev/null +++ b/amiga/xzip1.c @@ -0,0 +1,1030 @@ + +/*------------------------------------------------------*/ +/* AMIGA XZIP INTERFACE */ +/*------------------------------------------------------*/ + +/* XZIP MODIFICATION HISTORY + + 11 Nov 87 ported from EZIP code + stash_get now called from event_in NOT read_console + (to avoid infinite loop w/ get_control_seq) + begin_mark must be /unsigned/ (UCHAR); + read_cursor_pos() & get_control_seq now work + + ZIP/EZIP MODIFICATION HISTORY + + 25 OCT 85 init_script () uses PRT: file. Close_Device was + crashing when two games run simultaneously. + + 29 OCT 85 drive_default() strips savename of leading spaces + 29 OCT 85 get_control_seq() ignores garbage seqs + + 04 NOV 85 write_cursor_pos() takes no params (same as read) + 04 NOV 85 extra error checking in make_icon_file() + + 22 JUL 87 changed scripting EOL seq from Esc-E to CRLF, + wasn't working under AmigaDOS 1.2 + added unhide_screen for Alertbox problem + set NOCAREREFRESH flag to avoid border flicker + added stash_put(), stash_get() for typeahead; + read_cursor_pos() still NOT working as advertised + 26 AUG 87 added volume control to md_sound (in SOUND.C) + 01 Nov 87 switched to Native development +*/ + +#define VOID int /* "void" would require forward declares */ +#define GLOBAL /**/ + +/* /-* already defined in exec/types.h) *-/ +typedef long LONG; /-* 32 bits *-/ +typedef unsigned long ULONG; +typedef short WORD; /-* 16 bits *-/ +typedef unsigned short UWORD; +typedef char BYTE; /-* 8 bits *-/ +typedef unsigned char UBYTE; + +typedef unsigned char *STRPTR; +typedef STRPTR *APTR; +typedef short BOOL; +typedef unsigned char TEXT; + +#define TRUE 1 +#define FALSE 0 +#define NULL 0 +*/ + +typedef unsigned char CHAR; /* always unsigned for us */ +typedef unsigned char UCHAR; + +/* This switch controls conditional ZIP/EZIP compilation */ +/* (WAS defined in batch file, where compiler is invoked) */ +/* (For XZIP must always be true) */ + +#define EZIP 1 /* set for EZIP, otherwise classic */ + +#define ZDEBUG 0 /* set for debugging */ +#define bug_DiskFull 0 /* set if crashes system - FIXED */ +#define DEADCODE 0 /* set to re-include */ + +#define ERR 1 +#define NOERR 0 + +/* color equates */ + +#define MINCOLORS 2 /* default blue/white */ +#define MAXCOLORS 8 /* total XZIP color ids */ +#define BASE_ID 2 +#define LAST_ID 9 + +#define DEF_FORE 9 /* default Amiga foreground = white */ +#define DEF_BACK 6 /* default Amiga background = blue */ + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ + +#if EZIP +struct Screen *ZScreen; +struct TextFont *sysfont, *altfont; +#endif + +/* Use altered IOStdReq structure, "data" field type APTR changed to STRPTR. + Otherwise the compiler forces string pointers to be even-aligned. + >>> CHANGED BACK FOR NATIVE DEVELOPMENT - dbb <<< */ + +struct IOStdReq/*_MUNGED*/ ZIOStdReq; /* for Console device */ +/** (now DEAD) +struct IOStdReq/-*_MUNGED*-/ ZRDStdReq; /-* for queued reads *-/ +struct MsgPort ZMsgPort; **/ + +struct Window *ZWindow; +struct RastPort *ZRastPort; + +struct Device *ConsoleDevice; /* for library vector */ + +/* scripting variables -- two methods possible */ + + LONG print_file; /* scripting refnum */ +/** +struct IOStdReq_MUNGED SIOStdReq; /-* not used *-/ +struct MsgPort SMsgPort; **/ + + WORD prt_inited = 0; /* set when printer opened */ + WORD prt_active = 0; /* set when scripting is active */ + +/* cursor variables */ + + WORD y_res, y_char; /* rows = y_res / y_char */ + WORD x_res, x_char; + +GLOBAL WORD rows, cur_row; /* cur_row in 0 .. rows-1 */ +GLOBAL WORD columns, cur_column; +GLOBAL WORD marg_left = 0, marg_right = 0; + +GLOBAL WORD split_row; /* first row in scrolling area */ +GLOBAL WORD wind1; /* 1=TOP, 0=BOTTOM */ + +/* This buffer is accessed by the kernel. Careful about changing its size */ + +GLOBAL CHAR savename[80]; /* buffer for file_select dialog */ +GLOBAL CHAR saveback[80]; /* buffer for default name */ + +GLOBAL LONG game_ref; +GLOBAL LONG save_ref; + + CHAR *gamename = "Story.Data"; /* (on default drive) */ + CHAR *saveinit = "Story.Save"; /* (add default prefix) */ + CHAR *execname = NULL; /* zip name, get from OS */ + +GLOBAL LONG actlen = 0; /* for reporting r/w transfer len */ + +/* These vars are used to avoid unnecessary Seeking (e.g. when reading + sequential blocks during $verify). AmigaDOS Seeking causes head + movement even when it shouldn't and thrashes the disk badly. */ + + LONG old_offset = -1; /* init to invalid vals */ + LONG old_channel = -1; + +/* memory usage can be controlled by user, by supplying a free byte + count in the CLI command line. Useful if another task will be launched + subsequently. Otherwise game takes as much memory as it can use. */ + + LONG mem_freereq; /* set during init */ + + LONG IntuitionBase; + LONG GfxBase; /* for ZRastPort calls */ +/** LONG DiskfontBase; **/ /* for OpenDiskFont -- DEAD */ + + LONG IconBase; +struct DiskObject *diskobj; /* SAVE file icon info */ + +struct Remember *RememberKey; + +/* DEAD, SEE bug_DiskFull + + If a NEW save file is being created, check disk free space before + each write call. Prevents a useless Retry/Abort dialog (and in the + case of make_icon_file, a crash). +*/ + BOOL disk_newsave; + LONG disk_free; + +GLOBAL WORD xmouse, ymouse; /* 1-origin */ + +/* Amiga RGB values for the 8 XZIP colors, ordered so that the first three + correspond to the usual Workbench defaults. The values were determined + empirically. */ + + UWORD colortable[] = { + 0x005A, 0x0FFF, 0x0000, 0x00C0, /* blue, white, black, green */ + 0x0E00, 0x0EE0, 0x0F0F, 0x00EE /* red, yellow, magenta, cyan */ + }; + +/* This table relates XZIP color ordering to the above Amiga ordering */ + + UBYTE colormap[] = { + -1, -1, /* (placeholders -- never read) */ + 2, 4, 3, 5, /* black, red, green, yellow */ + 0, 6, 7, 1 /* blue, magenta, cyan, white */ + }; + + BOOL color = FALSE; /* default */ + + CHAR *cno = "Couldn't open: "; /* prefix for fatalmsg() */ + CHAR *cnc = "Couldn't create "; + + UBYTE *soundbuf; /* preallocate to avoid fragmentation */ + +/************************************************************************/ +/* Externals */ +/************************************************************************/ + +/* +extern LONG trap1 (); +extern VOID START (); +*/ + +/************************************************************************/ +/* Misc Functions */ +/************************************************************************/ + +/*------------------------------*/ +/* delay */ +/*------------------------------*/ + +delay (n) /* in 1/10 secs */ +WORD n; +{ + Delay (n * 5); /* AmigaDOS function, in 1/50 secs */ + +/** ULONG secs, mics, sfinal, mfinal; + BOOL done = FALSE; + + CurrentTime (&secs, &mics); + sfinal = secs + n; mfinal = mics; /-* n in whole secs *-/ + while (!done) { + CurrentTime (&secs, &mics); + if (secs == sfinal && mics >= mfinal) + done = TRUE; + if (secs > sfinal) + done = TRUE; + } **/ +} + +/*------------------------------*/ +/* unhide_screen */ +/*------------------------------*/ + +/* [EZIP only] Fixes a bug under AmigaDOS 1.2. When a System Alert box + occurs, the Workbench screen pops to the front [?why?] and the box appears + in it. But after the user responds to the alert, the Workbench screen + does not automatically unhide the game screen. This is likely to make + users think the game has gone away. Ugh. */ + +unhide_screen() /* [call just before start of input] */ +{ +#if EZIP + ScreenToFront (ZScreen); /* NOP if already at front */ +#endif +} + +/*------------------------------*/ +/* bell_sound */ +/*------------------------------*/ +VOID +bell_sound (tone) + +WORD tone; /* 1 for beep, 2 for boop */ +{ +/* no internal bell, just ignore beep; flash screen for boop */ + + if (tone == 2) + DisplayBeep (ZWindow->WScreen); /* (a system call) */ +} + +/*------------------------------*/ +/* random_seed */ +/*------------------------------*/ +ULONG +random_seed () +{ + ULONG secs, mics; + + CurrentTime (&secs, &mics); + + /* low 20 bits (significant in mics) are the most random */ + return (secs + mics); +} + +/*------------------------------*/ +/* window_resized */ +/*------------------------------*/ +WORD +window_resized () /* update globals, return window column width */ + +/* this routine is called - + [] during init + [] (CZIP) after a RDLINE input + [] (CZIP) after every line output (this takes care of MOREs) +*/ + +{ +/* determine size of current font */ + + /* (DONE ONCE ONLY, DURING INIT; SETS Y_CHAR AND X_CHAR) */ + +/* determine usable size of window */ + + y_res = ZWindow->Height - ZWindow->BorderTop - ZWindow->BorderBottom; + x_res = ZWindow->Width - ZWindow->BorderLeft - ZWindow->BorderRight; + +/* Calculate rows and columns. To prevent undesired AMIGA auto wrapping, + (CZIP only) we pretend that the column width is one less than it really is. +*/ + rows = y_res / y_char; + columns = (x_res / x_char) /**-1**/; + +/** if (cur_row >= rows) cur_row = rows - 1; /-* CZIP *-/ + if (cur_column >= columns) cur_column = columns - 1; +**/ + return (columns); /* updates kernel folding routines */ +} + +/************************************************************************/ +/* Memory Management */ +/************************************************************************/ + +/* memory fudge factor -- leave this much free for transient use, + (unless over-ridden by the F/n command switch). Resizing of windows + especially triggers large dynamic allocation requests. Also, opening + a script channel uses some 25K. (We now pre-allocate a main sound + buffer.) +*/ + +#define MEM_SYSTEM 64*1024 /* normal XZIP */ + +/** #if EZIP +#define MEM_SYSTEM 32*1024 /-* allow loading on 256K machine *-/ +#else /-* if ZIP *-/ +#define MEM_SYSTEM 64*1024 /-* enough for several windows *-/ +#endif **/ + +#define MEM_DEFAULT -1 /* user didn't specify memory use */ + +/*------------------------------*/ +/* c_maxmem */ +/*------------------------------*/ + +/* Return size of available memory pool, may be "doctored" (up or down) + upon user request. This routine should be called after every + significant allocation has been made except for the page buffers. */ + +LONG +c_maxmem (game_total) +LONG game_total; /* max memory (for buffers) we can use */ +{ + LONG game_used; + LONG mem_avail, mem_return; + + CHAR message[64]; + LONG len; + + mem_avail = (AvailMem (MEMF_PUBLIC)); + + if (mem_freereq == MEM_DEFAULT) + mem_return = mem_avail - MEM_SYSTEM; /* adjust it */ + else + { +/* got a request, use it */ + + if (mem_freereq < 0) mem_freereq = 0; + if (mem_freereq > mem_avail) mem_freereq = mem_avail; + + mem_return = mem_avail - mem_freereq; /* "doctor" it */ + +/* Request was made, so report our status to user. Want to show + the actual amount we will use here (if less than returned value). */ + + if (game_total > mem_return) + game_used = mem_return; + else + game_used = game_total; + + stcu_d (&message[0], game_used, 32); + strcat (&message, " bytes used"); + + /* if free will be more than requested, show why */ + + if (game_used == game_total) + strcat (&message, " (maximum)"); + strcat (&message, ", "); + + len = strlen (&message); + stcu_d (&message[len], (mem_avail - game_used), 32); + strcat (&message, " bytes free"); + + len = strlen (&message); + line_out (&message, len); + char_out (13); + char_out (13); + } + + return (mem_return); +} + +/*------------------------------*/ +/* c_getmem */ +/*------------------------------*/ + +LONG c_getmem (nbytes) /* return zero if failed */ +LONG nbytes; +{ +/** return (AllocMem (nbytes, MEMF_PUBLIC)); **/ + +/* This routine calls the AllocMem function, and also allocates a "link node," + which allows automatic de-allocation when we terminate. + We don't normally require any particular memory type (e.g., public or chip). +*/ + return (AllocRemember (&RememberKey, nbytes, MEMF_CLEAR)); +} + +/************************************************************************/ +/* Initializations */ +/************************************************************************/ + +#if EZIP + +#define Peek1 (8+4) /*8+3*/ /* ZScreen scanlines showing behind ZWindow */ +#define Peek2 0 /*8+5*/ /* WBScreen scanlines showing behind ZScreen */ + +/* The first margin is needed for the ZScreen slider and show/hide boxes. + Without these functions, task switching is crippled. + + The second margin is needed because of an Intuition problem that causes + all system alert boxes (e.g. insert disk X, disk X full, etc) to appear in + the WB screen, normally hidden by EZIP. This space permits the words + "System Alert" to show through to the user. >>> FIXED IN WB 1.2 <<< +*/ +#else +#define Peek1 0 +#define Peek2 0 +#endif + +#define NOTYET 0 /* to be defined at runtime */ + +/*------------------------------*/ +/* window_init */ +/*------------------------------*/ + +WORD set_color (); /* forward */ + +struct TextAttr sysTextAttr = { + "topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT + }; +/*** +struct TextAttr altTextAttr = { + "BZ Font.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_DISKFONT + }; +***/ /* no longer used */ + +WORD window_init (open, wcolor) +BOOL open, wcolor; /* close if false */ +{ +static struct NewScreen ns = { + 0, 0 + Peek2, /* LeftEdge, TopEdge */ + 640, 200 - Peek2, /* Width (high-res), Height >> defaults << */ + 1, /* Depth (default = 2 colors) */ + 0, 1, /* DetailPen, BlockPen */ + HIRES, /* ViewModes */ + CUSTOMSCREEN, /* Type */ + &sysTextAttr, /* Font (topaz 80) */ + NULL, /* DefaultTitle */ + NULL, /* Gadgets */ + NULL /* CustomBitMap */ + }; + +static struct NewWindow nw = { + 0, 0 + Peek1, /* LeftEdge, TopEdge */ + NOTYET, NOTYET, /* derive from ns */ /* Width, Height */ +/** 640, (200 - Peek2) - Peek1, **/ + 0, 1, /* DetailPen, BlockPen */ + RAWKEY | MOUSEBUTTONS | INTUITICKS, /* IDCMPFlags */ + BORDERLESS | SMART_REFRESH | + ACTIVATE | NOCAREREFRESH, /* Flags */ + NULL, /* FirstGadget */ + NULL, /* CheckMark */ + NULL, /* Title */ + NOTYET, /* Screen */ + NULL, /* BitMap */ + 0, 0, 0, 0, /* (min+max sizes, unused) */ + CUSTOMSCREEN /* Type */ + }; + + struct GfxBase *gb = (struct GfxBase *) GfxBase; + + if (open) + { + /* first create a custom screen ... */ + + if (gb->LibNode.lib_Version >= 33) { + /* must be running under system 1.2+ to use size fields */ + + ns.Height = gb->NormalDisplayRows - Peek2; + ns.Width = gb->NormalDisplayColumns; /* (pixels) */ + } + else { + /* under system 1.1, deduce size from this flag */ + + if ((gb->DisplayFlags) & PAL) + ns.Height = 256 - Peek2; + /** else ns.Height = 200 - Peek2; **/ /* default */ + /** ns.Width = 640; **/ /* default */ + } + + if (wcolor) ns.Depth = 3; /* support 8 colors */ + ns.DefaultTitle = (UBYTE *) execname; /* null, or our name */ + + ZScreen = (struct Screen *) OpenScreen (&ns); + if (ZScreen == NULL) { + fatalmsg (cnc); fatalmsg ("Screen"); + return (ERR); + } + + /* then create a window (taking size from screen) ... */ + + nw.Height = ns.Height - Peek1; + nw.Width = ns.Width; + nw.Screen = ZScreen; + + ZWindow = (struct Window *) OpenWindow (&nw); + if (ZWindow == NULL) { + fatalmsg (cnc); fatalmsg ("Window"); + return (ERR); + } + + ZRastPort = ZWindow->RPort; + SetDrMd (ZRastPort, JAM2); /* always draw fore AND back */ + + if (wcolor) { + /* install our colors in the screen's table */ + LoadRGB4 (&(ZScreen->ViewPort), colortable, MAXCOLORS); + + /* make sure defaults are showing (fixes a glitch + in LoadRGB4; must call /after/ ZRastPort inited */ + set_color (1, 1); + } + } + + else /* closing, clean up */ + { + if (ZWindow) + CloseWindow (ZWindow); + if (ZScreen) + CloseScreen (ZScreen); + } + + return (NOERR); +} + +/*------------------------------*/ +/* z_init */ +/*------------------------------*/ + +#define ZHLEN 64 /* file header len (bytes) */ +#define PFLAGS 8 /* flags word (in header) */ +#define FCOLO 64 /* color-requested bit */ +#define FSOUN 128 /* sound-requested bit */ + +LONG open_game (); /* forward */ +LONG close_game (); +LONG read_file (); + +WORD z_init () +{ + WORD err; + CHAR cur_prefs[1]; + CHAR old_YSize; + UWORD zheader[ZHLEN/2]; + + CHAR *il = "intuition.library"; + CHAR *gl = "graphics.library"; +/** CHAR *dl = "diskfont.library"; **/ + CHAR *icl = "icon.library"; + CHAR *cd = "console.device"; + +/* open the libraries we'll need */ + + IntuitionBase = (LONG) OpenLibrary (il, 0); + if (IntuitionBase == 0) { + fatalmsg (cno); fatalmsg (il); + return (ERR); + } + + GfxBase = (LONG) OpenLibrary (gl, 0); + if (GfxBase == 0) { + fatalmsg (cno); fatalmsg (gl); + return (ERR); + } + +/** DiskfontBase = (LONG) OpenLibrary (dl, 0); + if (DiskfontBase == 0) { + fatalmsg (cno); fatalmsg (dl); + return (ERR); + } **/ + +/* could close the WorkBench screen, to free up memory */ +/** CloseWorkBench (); **/ /* rude for user though */ + +/* check/adjust the default font */ + + GetPrefs (&cur_prefs, 1); /* get user's default size */ + old_YSize = cur_prefs[0]; /* 9 or 8 */ + +#if EZIP + +/* temporarily adjust Prefs, if necessary, to ensure 80 columns + (seems that this must be done before creating the Custom screen) */ + + if (old_YSize != TOPAZ_EIGHTY) + { + cur_prefs[0] = TOPAZ_EIGHTY; + SetPrefs (&cur_prefs, 1, FALSE); /* force to 8 */ + } +#endif + +/* read the game file header and see if color is desired */ + + err = open_game(); + if (err == 0) { + err = read_file (game_ref, 0, ZHLEN, &zheader); + close_game(); + } + if (err) { + fatalmsg (cno); fatalmsg (gamename); + return (ERR); + } + + color = zheader[PFLAGS] & FCOLO; /* nonzero if bit set */ + +/* create and open a game window (and custom screen, for EZIP) */ + + err = window_init (TRUE, color); + if (err) + return (ERR); /* (fatalmsg already called) */ + +/** sysfont = OpenDiskFont (&sysTextAttr); /-* 2nd time, actually *-/ + altfont = OpenDiskFont (&altTextAttr); /-* ZERO if error *-/ +**/ + setup_fonts (); /* our replacement for OpenDiskFont */ + +/* don't CREATE a console device, just get its library vector */ + + if (OpenDevice (cd, -1, &ZIOStdReq, 0) != 0) { + fatalmsg (cno); fatalmsg (cd); + return (ERR); + } + ConsoleDevice = ZIOStdReq.io_Device; + +/* create a console device, attaching it to our window */ +/** ZIOStdReq.io_Data = (LONG) ZWindow; + if (OpenDevice (cd, 0, &ZIOStdReq, 0) != 0) + return (ERR); +**/ + +#if EZIP +/* undo the temporary font setting, if it was changed above */ + + if (old_YSize != TOPAZ_EIGHTY) + { + cur_prefs[0] = old_YSize; + SetPrefs (&cur_prefs, 1, FALSE); /* restore user's choice */ + } +#endif + +/* initialize our internal text size variables */ + +#if EZIP + y_char = TOPAZ_EIGHTY; /* always 8 (80 columns) */ + x_char = 8; + +#else /* use the default fontsize */ + + y_char = old_YSize; /* either 8 or 9 */ + + if (old_YSize != TOPAZ_EIGHTY) + x_char = 10; /* can only be Topaz 60 */ + else x_char = 8; +#endif + + window_resized (); /* set up rows/columns globals */ + +/* set up the message port in the I/O request -- DEAD */ + +/** ZMsgPort.mp_Node.ln_Type = NT_MSGPORT; + ZMsgPort.mp_Flags = 0; + ZMsgPort.mp_SigBit = AllocSignal (-1); + ZMsgPort.mp_SigTask = (struct Task *) FindTask (NULL); + + AddPort (&ZMsgPort); + ZIOStdReq.io_Message.mn_ReplyPort = &ZMsgPort; **/ + +/* and start reading -- DEAD */ + +/** ZRDStdReq = ZIOStdReq; /-* copy the whole structure *-/ + queue_read (); **/ + +/* etcetera */ + +#if EZIP +#else + split_row = 1; /* default for ZIP (0 for EZIP) */ +#endif +/** cur_row = 0; cur_column = 0; **/ /* (automatic) */ +/** write_cursor_pos (); **/ + +/* default path+name for initial save */ + + getcwd (saveback); + strcat (saveback, saveinit); + +/** RememberKey = NULL; **/ /* (automatic) */ + +/* Get the Save Icon info during init. This avoids having to access the game + disk later, when it may have been removed from the drive */ + + IconBase = (LONG) OpenLibrary (icl, 0); + if (IconBase == NULL) + diskobj = NULL; /* (not a fatal error) */ + else + { + diskobj = (struct DiskObject *) GetDiskObject ("Icon.Data"); + + /* if info file not found, just return diskobj NULL */ + } + +/*** init_interrupt (1); ***/ /* (sound etc) */ + + if (zheader[PFLAGS] & FSOUN) { + +/* pre-allocate a 64K buffer for our "standard" single channel of sound data. + We would prefer to allocate sound buffers dynamically and free them when + not in use, but doing so risks failure. One reason is that Amiga free + memory tends to fragment, making it impossible later on to get the large + blocks our sound requires. */ + + soundbuf = (UBYTE *)AllocRemember /* auto cleanup */ + (&RememberKey, 64*1024, (MEMF_CHIP | MEMF_CLEAR)); + } + return (0); +} + +/*------------------------------*/ +/* setup_fonts */ +/*------------------------------*/ + +/* This routine inits the sysfont and altfont vars. For the system font, +we just pick up the pointer from our RastPort. Don't need to call +Open[Disk]Font a second time; it was called implicitly when our custom +screen/window was created. + + Setup for our alternate font is trickier. We do /not/ want to use +OpenDiskFont because of the assumptions it makes about where to find +the file (a system-wide FONTS: directory), and also about the existence +of a name file and a separate data subdirectory. Instead, we simulate +that call by reading the alternate data file into memory ourself, +and patching up a few pointers. +*/ + +#define ALTNAME "Graphic.Data" +/* don't call it "Font.Data" since user might be lead to needlessly copy + it into font directory */ + +VOID +setup_fonts () +{ + LONG fd, len, actual_len, *lp; + WORD *wp; + register char *p, *segbase; + + sysfont = ZRastPort->Font; + +/* if an alternate font doesn't exist, just leave altfont NULL */ + + fd = Open (ALTNAME, MODE_OLDFILE); + if (!fd) return (1); /* if error, just exit */ + + Seek (fd, 0, OFFSET_END); + len = Seek (fd, 0, OFFSET_BEGINNING); /* get length */ + +/* Allocate memory for font data; deallocation will be handled automatically + (by FreeRemember) upon program exit. */ + + p = (char *) c_getmem (len); + if (p) { + actual_len = Read (fd, p, len); + if (actual_len == len) { + + segbase = p + 0x20; /* skip seg header stuff */ + altfont = (struct TextFont *) (segbase + 0x3A); + +/* absolutize some ptrs, all relative to segbase */ + + lp = (LONG *) (segbase + 0x44); + *lp += (LONG) segbase; /* font name string (NULL) */ + + lp = (LONG *) (segbase + 0x5C); + *lp += (LONG) segbase; /* packed char data */ + + lp = (LONG *) (segbase + 0x62); + *lp += (LONG) segbase; /* char offsets array */ + +/* also patch this one; not sure what it is (disk vs ROM font?) */ + + wp = (WORD *) (segbase + 0x58); + *wp = 0x0001; + } + } + Close (fd); +} + +#if DEADCODE /* currently require no true interrupts */ + +/*------------------------------*/ +/* VertBServer */ +/*------------------------------*/ + +/* This routine runs at the interrupt level. Happily, registers D0-D1/ + A0-A1 are scratch in interrupt protocol as well as the Lattice compiler. + Also, references to global vars are OK since in Lattice they are absolute, + rather than keyed off any special register. System calls are OK (unless + otherwise advertised), since standard "glue" code saves register A6 then + loads a dispatch vector from an absolute location, or from one of the + call's parameters in some cases (CheckIO?). +*/ + +extern void int_sound(); + +LONG VertBServer() /* run our interrupt routines */ +{ + int_sound(); + int_key(); + return (0); /* and continue down server chain */ +} + +/*------------------------------*/ +/* init_interrupt */ +/*------------------------------*/ + +/* Install our interrupt(s) on the vertical-blank interrupt chain (one of + the simpler ways to do Amiga interrupts). Executes up to 60 times/sec, + low priority. */ + +init_interrupt (start) +int start; +{ + static BOOL inited = 0; + static struct Interrupt zir; /* should be MEMF_PUBLIC? */ + register struct Interrupt *p = &zir; /* (tighten up code) */ + + if (start) { + p->is_Node.ln_Type = NT_INTERRUPT; + p->is_Node.ln_Pri = -60; /* not time-critical */ + p->is_Node.ln_Name = "zir"; + /** p->is_Data = 0; **/ /* currently unused */ + p->is_Code = (void *) VertBServer; + + /* put the new interrupt server into action */ + AddIntServer (INTB_VERTB, p); + inited = 1; + } + else { + if (inited) + RemIntServer (INTB_VERTB, p); + } +} +#endif /* DEADCODE */ + +/*------------------------------*/ +/* z_exit */ +/*------------------------------*/ + +/* Clean up everything, in reverse order of creation. Any memory allocated + but not freed will be lost to eternity. +*/ + +VOID +z_exit () +{ +/** init_interrupt (0); **/ /* remove our interrupt */ + +/** shut down scripting, if no one else did **/ +/** if (prt_inited) + script_init (FALSE); **/ /* now in 68K */ + +/* free the save file icon stuff, if it existed */ + if (diskobj) + FreeDiskObject (diskobj); + if (IconBase) + CloseLibrary (IconBase); + +/* de-allocate all memory claimed by 68K kernel initializations */ + if (RememberKey) + FreeRemember (&RememberKey, TRUE); + +/* close the various Console Device structures */ + +/** RemPort (&ZMsgPort); **/ +/** FreeSignal (ZMsgPort.mp_SigBit); **/ /* DEAD */ + + if (ConsoleDevice) + CloseDevice (&ZIOStdReq); /* looks odd, but correct */ + +/* close our window (and screen, for EZIP) */ + +/** if (altfont) { /-* DEAD, see setup_fonts *-/ + CloseFont (altfont); + /-* RemFont (altfont); *-/ /-* only if AvailFonts/AddFont used *-/ + } + if (sysfont) + CloseFont (sysfont); /-* necessary? opened twice *-/ +**/ + window_init (FALSE, color); + +/* try to re-open WorkBench, if we closed it */ + +#if EZIP +/** OpenWorkBench (); **/ +#endif + +/* lastly, close the libraries we opened */ + +/** if (DiskfontBase) CloseLibrary (DiskfontBase); **/ + if (GfxBase) CloseLibrary (GfxBase); + if (IntuitionBase) CloseLibrary (IntuitionBase); +} + +/*------------------------------*/ +/* fatalmsg */ +/*------------------------------*/ + +/* Display a fatal error message. For initialization errors, we don't want + to assume that our normal output window is operational, so we send the + message to the window of our controlling process -- either (1) the CLI, + or (2) the temporary window opened by our Workbench startup code. + + Just before we exit, pause long enough so that (in case 2) the message + can be read before the window is closed. Don't try to getc() a key; + might hang if temp window not opened, and inappropriate in case 1. */ + +fatalmsg (s) +char *s; +{ + if (s) + printf (s); + else { + printf ("\n"); + delay (20); /* two secs */ + } +} + +/************************************************************************/ +/* Top Level */ +/************************************************************************/ + +/*------------------------------*/ +/* parse_args */ +/*------------------------------*/ + +parse_args (argc, argv) +LONG argc; +CHAR *argv[]; /* an array of pointers */ +{ + CHAR *argx; + CHAR char1, char2; + int i; + +/* The only valid command line argument is F/n, where n is the minimum + number of bytes to leave in the free memory pool. + + If the argument is missing, or not a number, or if the game is run from + WorkBench, leave the default (MEM_SYSTEM, defined in c_maxmem). + + The game takes as much memory as it can use, within the above limit. +*/ + + mem_freereq = MEM_DEFAULT; /* assume no memory arg */ + +/* A general problem: the name of an executable file containing spaces + (more than one word) is not collected into one string! */ + +/** if ((argc >= 1) && (argv != 0)) + execname = (char *) argv[0]; /-* (used in window title) *-/ +**/ + if ((argc > 1) && (argv != 0)) /* got one */ + for (i=1; ifib_FileName); /* dir name */ + + if (newlock == 0) /* (actually vol name) */ + strcat (path, ":"); + else if (showslash) + strcat (path, "/"); + } + FreeMem (myinfo, sizeof(struct FileInfoBlock)); + } + } + UnLock (lock); + + if (error) /* make null the global string */ + path[0] = 0; + return (error); /* (zero if ok) */ +} + +/*------------------------------*/ +/* geterr */ +/*------------------------------*/ + +/* This is a front end for IoErr. It should be called /only/ when we know + an error occurred, and so expect a nonzero result. But IoErr sometimes + returns a zero anyway (e.g., after Create with a bad pathname). In + this case we return -1, so 68K stuff will know something went wrong. */ + +LONG geterr () +{ + LONG err = IoErr (); + + if (!err) err = -1; /* make sure it's nonzero */ + return (err); +} + +/************************************************************************/ +/* File Selection */ +/************************************************************************/ + +/*------------------------------*/ +/* file_select */ +/*------------------------------*/ +WORD +file_select (opsave, drive) /* get file and pathspec from user, */ + /* combine and leave in SAVENAME */ + +WORD opsave; /* zero if restore, otherwise save */ +CHAR drive; /* drive to use, zero for default */ +{ + /* AMIGA LACKS AN OS ROUTINE - IMPLEMENTED IN KERNEL */ +} + +/*------------------------------*/ +/* new_default */ +/*------------------------------*/ + +VOID +new_default (okay) /* called at end of each SAVE/RESTORE */ + +BOOL okay; +{ + if (okay) /* dest <- source */ + { + strcpy (&saveback, &savename); /* update old defaults */ + } + else + { + strcpy (&savename, &saveback); /* retrieve old defaults */ + } +} + +/*------------------------------*/ +/* strip_spaces */ +/*------------------------------*/ + +/* Remove any leading and/or trailing spaces from savenames, before + the file is created. AmigaDOS permits them, but they lead to confusing + RESTORE errors. + + Note that we continue to allow embedded spaces. +*/ + +VOID +strip_spaces (filename) + +CHAR *filename; +{ + CHAR *leading; + WORD len; + + leading = filename; + while (*leading++ == 32) /* skip over a leading space */ + { + strcpy (filename, leading); /* move the string up */ + --leading; + } + + len = strlen (filename); + while (len && (filename[len-1] == 32)) + { + filename[len-1] = 0; /* chop off any trailing spaces */ + --len; + } +} + +/*------------------------------*/ +/* divide_pathname */ +/*------------------------------*/ + +/* Check whether a given filename is prefixed with a drive or directory name. + If so, return a pointer to the bare filename, otherwise return NULL. + + Path syntax for Amiga is "DFn:PATH1/PATH2/PATHn/filename". +*/ + +CHAR * +divide_pathname (pathname) + +CHAR *pathname; +{ + CHAR *special; /* <:> and are the special chars */ + +/* if one or more directories were given, find the last one */ + + special = (CHAR *) strrchr (pathname, '/'); + +/* otherwise, see if a drive was given */ + + if (special == NULL) + special = (CHAR *) stpchr (pathname, ':'); + + if (special != NULL) /* found one, skip over the delimiter */ + special++; + + return (special); /* pointer to bare filename, or NULL */ +} + +/*------------------------------*/ +/* drive_default */ +/*------------------------------*/ + +/* If savename lacks a drive/directory spec but saveback includes one + (the default), prefix it to savename. + + Also, take this opportunity to remove any leading/trailing spaces from + savename. +*/ + +VOID +drive_default () +{ + CHAR *barename; + CHAR temp[64]; + +/* check whether savename includes a drive/directory */ + + barename = (CHAR *) divide_pathname (&savename); + + if (barename == NULL) /* Nope */ + { + strip_spaces (&savename); + +/* check whether a default drive/directory exists */ + + strcpy (&temp, &saveback); + + barename = (CHAR *) divide_pathname (&temp); + + if (barename != NULL) /* Yep */ + { +/* and prefix the default drive/directory onto savename */ + + *barename = 0; /* chop off default filename */ + strcat (&temp, &savename); + strcpy (&savename, &temp); + } + } + +/* user DID supply a drive/directory, just check for spaces in filename */ + + else + { + strip_spaces (barename); + } +} + +#if bug_DiskFull /* BUG GONE, THIS IS DEAD CODE */ + +/*------------------------------*/ +/* disk_bytes_avail */ +/*------------------------------*/ + +LONG +disk_bytes_avail () /* returns number of available bytes on save disk, + -1 if error. Must call AFTER save file is created */ +{ + struct FileLock *filelock; + LONG avail; + + WORD pad1; +struct InfoData ZInfoData; /* information about the save disk */ + WORD pad2; + +struct InfoData *ZInfoDataPtr; /* pointer to the above */ + LONG ptr; + + +/* Must first obtain a "lock" for a valid file on the desired disk. + We conveniently use the save file (thus it must already exist). */ + + filelock = Lock (&savename, ACCESS_READ); + + if (!filelock) /* if error, exit now */ + return (-1); + +/* The InfoData structure must be longword aligned (for AmigaDOS). + Adjust alignment with the pad bytes, if necessary. */ + + pad1 = pad2 = 0; /* make the Compiler stop whining */ + + ptr = (LONG) &ZInfoData; + ptr = ptr>>2; ptr = ptr<<2; + ZInfoDataPtr = (struct InfoData *) ptr; + +/* Determine how much space remains on the save disk. */ + + if (Info (filelock, ZInfoDataPtr)) + { + avail = + (ZInfoDataPtr->id_NumBlocks + - ZInfoDataPtr->id_NumBlocksUsed) /* free blks */ + * ZInfoDataPtr->id_BytesPerBlock; + } + else avail = -1; /* something wrong, fail */ + + UnLock (filelock); /* make sure to undo this lock */ + + return (avail); +} + +#endif /* bug_DiskFull */ + +/************************************************************************/ +/* Disk I/O */ +/************************************************************************/ + +/*------------------------------*/ +/* read_file */ +/*------------------------------*/ + +LONG +read_file (channel, offset, length, buffer) + +LONG channel; +LONG offset, length; +CHAR *buffer; +{ + LONG former_pos; + LONG actual_len; + LONG error; + +/* disk thrashing is reduced if unnecessary seeks are avoided */ + + if ((channel != old_channel) || (offset != old_offset)) + { + former_pos = Seek (channel, offset, -1); /* AmigaDOS */ + if (former_pos == -1) + { + old_offset = -1; /* force seek next time */ + return (geterr()); + } + } + + old_channel = channel; + old_offset = offset + length; + + actual_len = Read (channel, buffer, length); + if (actual_len == -1) + { + old_offset = -1; /* force seek next time */ + error = geterr(); + } + +/* Check the number of bytes actually read. This will detect certain + invalid save files (for example, files where Amiga crashed during their + creation, for whatever reason). + + We allow for a special case of actual length being 256 less than expected. + The kernel does paging in 512 byte blocks, while the Amiga TFTP utility + transfers data files in 256 byte blocks. +*/ + else if ((actual_len == length) || (actual_len == (length - 256))) + + error = 0; /* zero means no error */ + + else + { + old_offset = -1; + error = 1; /* length error */ + } + + actlen = actual_len; /* save as global (for 68K) */ + return (error); +} + + +/*------------------------------*/ +/* write_file */ +/*------------------------------*/ + +LONG +write_file (channel, offset, length, buffer) + +LONG channel; +LONG offset, length; +CHAR *buffer; +{ + LONG error, actual_len; + +/* Errors: zero means none, 999 means disk full, otherwise geterr() */ + +#if bug_DiskFull + + if (disk_newsave) /* FALSE if writing over old file */ + { + disk_free = disk_free - length; + if (disk_free < 0) + return (999); /* not enough room for write */ + } +#endif + error = Seek (channel, offset, -1); + if (error == -1) + return geterr(); + + actual_len = Write (channel, buffer, length); + if (actual_len == -1) + return geterr(); + + else if (actual_len != length) /* (should have been caught above) */ + return (999); + + actlen = actual_len; /* save as global (for 68K) */ + return (0); /* no error */ +} + + +/*------------------------------*/ +/* create_file */ +/*------------------------------*/ + +LONG +create_file () /* create (if needed), and open, a SAVE file */ +{ + register LONG fd; + +/* two ways to enter this routine: if disk_newsave is TRUE, we are creating + a new save file, otherwise we are writing over an old one */ + + fd = Open (&savename, MODE_NEWFILE); + +#if bug_DiskFull /* avoid a write error */ + + if (fd && disk_newsave) + { +/* we just created the file, but must close it momentarily to get disk info. + Otherwise the Lock call fails */ + + Close (fd); + +/* determine how much free space is on the disk, so file_write can fail + gracefully if necessary */ + + disk_free = disk_bytes_avail (); + + fd = Open (&savename, MODE_NEWFILE); + } +#endif /* bug_DiskFull */ + + save_ref = fd; /* save global */ + if (!fd) + return (geterr()); + else + return (0); /* zero means OK */ +} + + +/*------------------------------*/ +/* open_file */ +/*------------------------------*/ + +LONG +open_file () /* open an file to RESTORE from */ +{ + LONG fd; + + fd = Open (&savename, MODE_OLDFILE); + + save_ref = fd; + if (!fd) + return (geterr()); + else + return (0); /* zero means OK */ +} + +/*------------------------------*/ +/* close_file */ +/*------------------------------*/ + +LONG +close_file () /* close a SAVE file */ +{ + if (save_ref) { + Close (save_ref); + save_ref = 0; + } + + old_channel = -1; /* make sure to reset this one */ + return (0); /* no error codes? */ +} + + +/*------------------------------*/ +/* delete_file */ +/*------------------------------*/ + +LONG +delete_file () +{ + LONG success; /* actually BOOLEAN */ + + success = DeleteFile (&savename); + + if (success) + return (0); + else return (1); +} + + +/*------------------------------*/ +/* exist_file */ +/*------------------------------*/ + +LONG +exist_file () /* called before every SAVE */ +{ + struct FileLock *fl; + + fl = Lock (&savename, ACCESS_WRITE); + if (fl) /* non-zero if already exists */ + { + disk_newsave = FALSE; /* set the global */ + UnLock (fl); /* remove the lock */ + } + else disk_newsave = TRUE; + + return ((LONG) fl); +} + +/*------------------------------*/ +/* open_game */ +/*------------------------------*/ + +LONG +open_game() +{ + game_ref = Open (gamename, MODE_OLDFILE); + + if (game_ref == 0) + return (geterr()); + else return (0); /* zero means OK */ +} + +/*------------------------------*/ +/* close_game */ +/*------------------------------*/ + +LONG +close_game () +{ + if (game_ref) { + Close (game_ref); + game_ref = 0; + } + old_channel = -1; /* make sure to reset this one */ + return (0); +} + + +/*------------------------------*/ +/* make_icon_file */ +/*------------------------------*/ + +LONG +make_icon_file () /* create a new save file icon, */ + /* called only after a successful SAVE */ +{ + LONG error; + LONG object; +/* WORD len; */ + +/* diskobj (should have been) read into memory during init */ + + if (diskobj == NULL) + error = 1; + else + { + +#if bug_DiskFull + +/* PROBLEM: PutDiskObj is crashing the machine when a disk-full error occurs. + First, make sure we have enough room for a new icon file. +*/ + +#define MaxIconSize 1024 /* actually ours is under 400 */ + + if (disk_newsave) /* if OLD save, space not an issue */ + { + disk_free = disk_bytes_avail (); + if (disk_free < MaxIconSize) return (1); + } + +/* (Alternate fix. The preceeding code fixes this problem better.) + + Do some preliminary error checking: Attempt to create a file with the + desired name, and put 1K of random data into it. +*/ + strcat (&savename, ".info"); /* desired name */ + error = create_file (); /* --> save_ref */ + + if (!error) + { + error = write_file (save_ref, 0, 1024, &savename); + + close_file (save_ref); /* (no error codes) */ + + if (!error) + error = delete_file (); /* <-- savename */ + else delete_file (); + } + + len = strlen (&savename); + savename[len-5] = 0; /* chop off the ".info" */ + + if (error) /* if ANY error, fail now */ + return (error); + +#endif /* bug_diskfull */ + + +/* Everything seems OK, go ahead and make the Save icon */ + + diskobj->do_CurrentX = NO_ICON_POSITION; + diskobj->do_CurrentY = NO_ICON_POSITION; + + /* write icon file via same path as save file */ + + object = PutDiskObject (&savename, diskobj); + + if (object == NULL) + error = geterr(); + else error = 0; + } + + return (error); +} + +/************************************************************************/ +/* Scripting */ +/************************************************************************/ + +/*------------------------------*/ +/* raw_script */ +/*------------------------------*/ + +WORD +raw_script (buffer, length) /* send data to the printer device */ + +LONG buffer, length; +{ + WORD error; + LONG seconds1, micros1; + LONG seconds2, micros2; + LONG actual_len; + +/* A problem: AmigaDOS (rev 1.0) isn't passing back printer error codes. + Each attempt to print when the printer isn't ready causes a 30 second + timeout. A series of these effectively hangs the game. + + To fix, use the delay to infer an error. If no error code is returned + but the delay exceeds 30 seconds, consider the printer not ready. +*/ + + CurrentTime (&seconds1, µs1); /* starting time */ + + actual_len = Write (print_file, buffer, length); + if (actual_len == length) + error = 0; + else error = 1; + +/* SIOStdReq.io_Data = (APTR) buffer; + SIOStdReq.io_Length = length; + + SIOStdReq.io_Command = CMD_WRITE; + DoIO (&SIOStdReq); + error = (SIOStdReq.io_Error); +*/ + CurrentTime (&seconds2, µs2); + + if (!error) /* says no error, but is it lying? */ + { + if ((seconds2 - seconds1) >= (30 - 1)) + error = 99; + } + + return (error); /* error code, zero if OK */ +} + +/*------------------------------*/ +/* script_init */ +/*------------------------------*/ + +/* + Two approaches to printing were tried; neither returns errors. The hairy + one crashes (CloseDevice) when multi-tasked, so use the simple one. +*/ + +LONG +script_init (open) /* initialize/uninitialize the printer */ + +WORD open; +{ + LONG error; + + if (open) + { + print_file = Open ("PRT:", MODE_OLDFILE); + + if (print_file) /* zero means error */ + error = 0; + else error = 1; + +/** OpenDevice ("printer.device", 0, &SIOStdReq, 0); + + /-* set up the message port in the I/O request *-/ + + SMsgPort.mp_Node.ln_Type = NT_MSGPORT; + SMsgPort.mp_Flags = 0; + SMsgPort.mp_SigBit = AllocSignal (-1); + SMsgPort.mp_SigTask = (struct Task *) FindTask (NULL); + + AddPort (&SMsgPort); + SIOStdReq.io_Message.mn_ReplyPort = &SMsgPort; +**/ } + + else + { + if (print_file) /* call only if once opened */ + Close (print_file); + + error = 0; /* no close errors? */ + + /* clean up the various structures we created */ + +/** RemPort (&SMsgPort); + FreeSignal (SMsgPort.mp_SigBit); + + CloseDevice (&SIOStdReq); +**/ } + + return (error); /* zero if none */ +} + +/*------------------------------*/ +/* script_open */ +/*------------------------------*/ + +WORD +script_open (start) /* kernel issued request to start/stop scripting, + return status, either active or inactive */ +WORD start; +{ + CHAR reset_seq[2]; + LONG error; + +/* starting, may need to open/reset the printer */ + + if (start) + { + if (!prt_inited) /* device never opened, do so now */ + { + error = script_init (TRUE); + + if (!error) + prt_inited = TRUE; /* okay, opened */ + } + + if (prt_inited && !prt_active) /* new start, reset printer */ + { + + reset_seq[0] = '\33'; /* ESC ($1B) */ + reset_seq[1] = 'c'; /* 'c' means reset */ + + error = raw_script (&reset_seq, 2); + + if (!error) + prt_active = TRUE; /* okay, active */ + } + } + + else /* if stop, flag it and shut down */ + { + prt_active = FALSE; + + if (prt_inited) + { + script_init (FALSE); prt_inited = FALSE; + } + } + + return (prt_active); +} + +/*------------------------------*/ +/* script_line */ +/*------------------------------*/ + +WORD +script_line (buffer, length) /* script a line, tack on an EOL, + return error code (zero if none) */ +LONG buffer, length; +{ + CHAR eol_seq[2]; + WORD error; + + if (length > 0) + error = raw_script (buffer, length); + else error = 0; + +/* The EOL seq used to be an "ISO standard" Esc-E (1B45), but under + AmigaDOS 1.2 this seems to have no effect. Changing to CRLF (0D0A) + works under both 1.1 and 1.2 except that the spacing is too wide + (resembles triple, used to resemble double). It appears that AmigaDOS + (/not/ the printer) automatically makes the initial CR a CRLF. So, + we will output only the CR and hope all printers are happy. + + By the way, a way to check script spacing is to compare it to what + AmigaDOS does after typing "TYPE textfile TO PRT:". Also, some + printer behavior can be controlled from User Preferences, like + margins and 6- or 8-line spacing. +*/ + if (!error) + { + eol_seq[0] = 0x0D; +/** eol_seq[1] = 0x0A; **/ + + error = raw_script (&eol_seq, 1); + } + return (error); +} + diff --git a/amiga/xzip3.c b/amiga/xzip3.c new file mode 100644 index 0000000..e7f96cd --- /dev/null +++ b/amiga/xzip3.c @@ -0,0 +1,891 @@ + +#define TOPAZ8_BASE 6 /* 80-col font baseline */ + +/************************************************************************/ +/* Low Level Console Device I/O */ +/************************************************************************/ + +#if DEADCODE + +/*------------------------------*/ +/* write_console */ +/*------------------------------*/ +VOID +write_console (str, len) /* send raw string to console device */ + +CHAR *str; +WORD len; +{ + /** DEAD **/ +} + +/*------------------------------*/ +/* queue_read */ +/*------------------------------*/ + +VOID +queue_read () +{ + /** DEAD **/ +} + +/*------------------------------*/ +/* read_console */ +/*------------------------------*/ + +VOID /*CHAR*/ +read_console () /* get a char from console device */ +{ + /** DEAD **/ +} + +/*------------------------------*/ +/* send_control_seq */ +/*------------------------------*/ + +#define begin_mark 0x009B /* one unsigned byte, was '\233' */ + +VOID +send_control_seq (str) /* write it, prefixed with control char */ +CHAR *str; +{ + /** DEAD **/ +} + +/*------------------------------*/ +/* get_control_seq */ /* read chars into buffer */ +/*------------------------------*/ + +VOID +get_control_seq (buffer, end_mark) +UCHAR *buffer; +UCHAR end_mark; +{ + /** DEAD **/ +} + +/*------------------------------*/ +/* stash_put */ +/*------------------------------*/ + +/** +#define STASH_SIZE 64 /-* max size *-/ + +CHAR stash[STASH_SIZE]; /-* typeahead saved here *-/ +WORD stash_len = 0; **/ + +/* The next two calls are used to maintain a typeahead buffer, saving +keys that would otherwise be thrown away. This situation occurs only +because of the awful way the cursor position is read -- a special escape +sequence is sent to the console device and the position is reported +back via the input stream, mixed with any typeahead. */ + +stash_put (c) /* DEAD -- not needed */ +CHAR c; +{ +/** if (stash_len < STASH_SIZE) { + stash[stash_len] = c; + stash_len++; + } **/ +} + +/*------------------------------*/ +/* stash_get */ +/*------------------------------*/ + +CHAR stash_get () /* return a char, or NULL if none */ +{ +/** CHAR c = 0; + WORD i; + + if (stash_len) { /-* any saved typeahead? *-/ + c = stash[0]; /-* yes, return it FIFO *-/ + stash_len--; + for (i=0; i clip_len) + len = clip_len; + +/** old_endmark = str[len]; + str[len] = 0; **/ /* make it asciz */ + + x_align = x_char * cur_column; + y_align = (y_char * cur_row) + TOPAZ8_BASE; /* allow for baseline */ + + Move (ZRastPort, x_align, y_align); + Text (ZRastPort, str, len); + + cur_column += len; +/** str[len] = old_endmark; **/ +} + +/*------------------------------*/ +/* char_out */ +/*------------------------------*/ + +VOID +char_out (c) /* if CR or BS, special case, else draw the char */ +CHAR c; +{ + CHAR temp[2]; /* even-aligned */ + + if (c == 13) + { + cur_column = marg_left; + if (cur_row < rows - 1) + cur_row++; + else + amiga_scroll (); + } + + else if (c == 8) + { + BS_cursor(); + char_out (32); + BS_cursor(); + } + else /* normal char, draw it */ + { + if (cur_column >= columns) /* first goto next line */ + char_out (13); + temp[0] = c; + line_out (&temp, 1); + } +} + +/*------------------------------*/ +/* BS_cursor */ +/*------------------------------*/ +VOID +BS_cursor () +{ + if (cur_column > marg_left) + cur_column--; /* normal BS */ + else if (cur_row > 0) { + cur_column = (columns - marg_right) - 1; + cur_row--; /* backup a line */ + } +} + +/************************************************************************/ +/* Input handling */ +/************************************************************************/ + +/* Maintain a blinking cursor. This routine is called from setup_input() + and from intuitick(), every 1/10 sec while we await input */ + +#define ONTICK 0 +#define OFFTICK 7 /* duty cycle is 70% */ +#define MAXTICK 10 /* ... of one second */ + +/*------------------------------*/ +/* blink_cursor */ +/*------------------------------*/ + +VOID blink_cursor (arg) /* 1= starting, -1= ending, 0= waiting */ +WORD arg; +{ + static WORD ticks; + static BOOL curs_on = FALSE; /* initially off */ + int old_hl; /* save current here */ +/** static BOOL blinky = FALSE; **/ /* Amiga (CLI) default is NO blink */ + + switch (arg) { + case 1: + ticks = ONTICK; + break; + case -1: + ticks = OFFTICK; + break; +/** case 0: /-* not handled *-/ + if (blinky) { /-* should make this a global option *-/ + ticks++; + if (ticks >= MAXTICK) /-* wrap around *-/ + ticks = ONTICK; + } + break; **/ + } + + if ((ticks == ONTICK) && !curs_on) { /* show cursor */ + old_hl = highlight (-1); + highlight (1); /* inverse vid */ + char_out (32); + highlight (old_hl); + curs_on = TRUE; + } + if ((ticks == OFFTICK) && curs_on) { /* erase cursor */ + char_out (8); + curs_on = FALSE; + } +} + +/*------------------------------*/ +/* setup_input */ +/*------------------------------*/ + +VOID setup_input (start, single) /* show/hide cursor */ +BOOL start, single; /* if single, don't allow "menu strings" */ +{ + if (start) { + unhide_screen (); /* just in case ... */ + blink_cursor (1); + } + else + blink_cursor (-1); +} + +/*------------------------------*/ +/* german_convert */ +/*------------------------------*/ + +/* Convert a German extension char from/to its native Amiga code to/from + the common XZIP code. If the given char is not in the German set, + return NULL. */ + +UBYTE german_convert (c, from_native) +UBYTE c; +BOOL from_native; /* true for input, false for output */ +{ + register UBYTE *p; + register int off1, off2; + UBYTE c2 = 0; + + static UBYTE gtab[] = /* German conversion table for the Amiga */ + { + 0xE4, 155, /* ae (umlaute a) */ + 0xF6, 156, /* oe (umlaute o) */ + 0xFC, 157, /* ue (umlaute u) */ + 0xC4, 158, /* AE */ + 0xD6, 159, /* OE */ + 0xDC, 160, /* UE */ + 0xDF, 161, /* ss */ + 0xBB, 162, /* >> (left quote) */ + 0xAB, 163, /* << (right quote) */ + 0, 0 }; /* zero marks end of table */ + + if (from_native) + { off1 = 0; off2 = 1; } + else + { off1 = 1; off2 = 0; } + + p = gtab; + + while (*p != 0) { + if (p[off1] == c) { /* found it? */ + c2 = p[off2]; /* yes, return corresponding value */ + break; + } + p += 2; + } + return (c2); +} + +/*------------------------------*/ +/* map_fkey */ +/*------------------------------*/ + +/* map an FKey to its XZIP value. Return NULL if not found. */ + +UBYTE map_fkey (raw) +UBYTE raw; +{ + register UBYTE *p; + UBYTE c = 0; + +/* FKey translation table for the Amiga. The values on the left are raw + keycodes which (for the following groups of keys) I believe are invariant + across the various international Amiga keyboards. */ + + static UBYTE keytab[] = + { + 0x4C, 129, /* up arrow */ + 0x4D, 130, /* down arrow */ + 0x4F, 131, /* left arrow */ + 0x4E, 132, /* right arrow */ + 0x50, 133, /* F1 */ + 0x51, 134, /* F2 */ + 0x52, 135, /* F3 */ + 0x53, 136, /* F4 */ + 0x54, 137, /* F5 */ + 0x55, 138, /* F6 */ + 0x56, 139, /* F7 */ + 0x57, 140, /* F8 */ + 0x58, 141, /* F9 */ + 0x59, 142, /* F10 */ + /* no F11, F12 */ + 0, 0 }; /* zero marks end of table */ + + p = keytab; + + while (*p != 0) { + if (*p++ == raw) { /* found it? */ + c = *p; /* yes, pick up XZIP value */ + break; + } + p++; + } + return (c); +} + +/*------------------------------*/ +/* raw_key */ +/*------------------------------*/ + +/* Use the system KeyMap to convert a raw keycode to the correct ascii + value (or for certain keys, a console-device-style escape sequence). + (see Enhancer1.2 booklet p66). Then adjust as required any value that + should fall into the extended (128+) XZIP character set. */ + +#define KBLEN 32 /* (known max is 4) */ + +UBYTE raw_key (msg) +struct IntuiMessage *msg; +{ + UBYTE keycode, c, kbuffer[KBLEN]; + static struct InputEvent iev = {NULL, IECLASS_RAWKEY, 0,0,0}; + int len; + +/* copy input event info */ + + keycode = msg->Code; + iev.ie_Code = keycode; + iev.ie_Qualifier = msg->Qualifier; + +/* To support deadkeys (1.2 only), get previous codes from location + pointed to by IAddress. (This pointer not valid after IntuiMessage + is replied ?) */ + + iev.ie_position.ie_addr = *((APTR *) msg->IAddress); + +/* convert key to ascii (must have previously opened console device) */ + + len = RawKeyConvert (&iev, &kbuffer, KBLEN, NULL); + +/* translate special keys ... */ + + if (len <= 0) return (0); /* key-up event, deadkey, etc */ + + if (len > 1) { /* FKey, cursor key, (Help) */ + c = map_fkey (keycode); + return (c); + } + + c = kbuffer[0]; /* length is 1 exactly */ + +/* Check if c is a number; if so, THEN check if it came from the keypad + (some international keyboards assign special chars to shifted keypads) */ + + if ((c >= '0') && (c <= '9')) + if (keycode >= 0x0F) { /* keypad '0' */ + c += 145 - '0'; + return (c); + } + +/* Check if c is a "post-deadkey" (or an actual international key) */ + + if (c >= 128) { + c = german_convert (c, TRUE); /* 0 if not */ +/** return (c); **/ + } + + return (c); +} + +/*------------------------------*/ +/* mouse_buttons */ +/*------------------------------*/ + +/* this routine monitors only the mouse "selection" button (the left one) */ + +UBYTE mouse_buttons (im) +struct IntuiMessage *im; +{ + UBYTE retval = 0; /* default val */ + ULONG cursecs, curmics; +static ULONG oldsecs = 0, oldmics = 0; + + switch (im->Code) { + + case SELECTDOWN: /* button just pressed */ + xmouse = (im->MouseX / x_char) + 1; + ymouse = (im->MouseY / y_char) + 1; + + cursecs = im->Seconds; + curmics = im->Micros; + +/* use a system call to check if it's a double */ + + if (DoubleClick (oldsecs, oldmics, cursecs, curmics)) { + oldsecs = 0; oldmics = 0; + retval = 253; /* double click */ + } + else { + oldsecs = cursecs; oldmics = curmics; + retval = 254; /* single click */ + } + break; + +/** case SELECTUP: /-* button just released *-/ + retval = 0; + break; **/ + } + return (retval); +} + +/*------------------------------*/ +/* intuiticks */ +/*------------------------------*/ + +/* this routine called every 1/10 sec (approx) */ + +UBYTE intuiticks (im) +struct IntuiMessage *im; +{ + blink_cursor (0); /* maintain the cursor */ + return (255); /* return a special code (for timeouts) */ +} + +/*------------------------------*/ +/* event_multi */ +/*------------------------------*/ + +UBYTE event_multi () /* wait for an input event */ +{ + struct IntuiMessage *msg, localmsg; + int i; + UBYTE *s, *d, val; + +/* must be sure that a task's port is empty before the task can be put + to sleep (Peck p202) */ + + msg = (struct IntuiMessage *) GetMsg (ZWindow->UserPort); + if (msg == NULL) { + WaitPort (ZWindow->UserPort); /* sleep */ + msg = (struct IntuiMessage *) GetMsg (ZWindow->UserPort); + } + +/* copy the contents of the message to our own area, so we can reply it + as quickly as possible (Peck p155) */ + + s = (UBYTE *) msg; + d = (UBYTE *) &localmsg; + for (i=0; iClass != RAWKEY) { + ReplyMsg (msg); /* return block to system */ + msg = NULL; + } + + switch (localmsg.Class) { + + case RAWKEY: + val = raw_key (&localmsg); + break; + case MOUSEBUTTONS: + val = mouse_buttons (&localmsg); + break; + case INTUITICKS: + val = intuiticks (&localmsg); + break; + +/** case SIZEVERIFY: /-* unused cases *-/ + val = size_verify (&localmsg); + break; + case NEWSIZE: + val = new_size (&localmsg); + break; + case REFRESHWINDOW: + val = refresh_window (&localmsg); + break; + case MOUSEMOVE: + val = mouse_move (&localmsg); + break; + case GADGETDOWN: + val = gadget_down (&localmsg); + break; + case GADGETUP: + val = gadget_up (&localmsg); + break; + case REQSET: + val = req_set (&localmsg); + break; + case MENUPICK: + val = menu_pick (&localmsg); + break; + case CLOSEWINDOW: + val = close_window (&localmsg); + break; + case REQVERIFY: + val = req_verify (&localmsg); + break; + case REQCLEAR: + val = req_clear (&localmsg); + break; + case MENUVERIFY: + val = menu_verify (&localmsg); + break; + case NEWPREFS: + val = new_prefs (&localmsg); + break; + case DISKINSERTED: + val = disk_inserted (&localmsg); + break; + case DISKREMOVED: + val = disk_removed (&localmsg); + break; + case WBENCHMESSAGE: + val = wbench_message (&localmsg); + break; + case ACTIVEWINDOW: + val = active_window (&localmsg); + break; + case INACTIVEWINDOW: + val = inactive_window (&localmsg); + break; + case DELTAMOVE: + val = delta_move (&localmsg); + break; + case VANILLAKEY: + val = vanilla_key (&localmsg); + break; +**/ /* end of unused cases */ + default: + val = 0; + break; + } + + if (msg) ReplyMsg (msg); /* reply now, if not done earlier */ + + return (val); +} + +/*------------------------------*/ +/* event_in */ +/*------------------------------*/ + +UBYTE event_in () /* wait for keyboard (or mouse) input */ +{ + UBYTE c = 0; + +/*** c = stash_get(); /-* any saved typeahead? *-/ + if (!c) + c = read_console (); /-* no, get a live key *-/ +***/ + while (c == 0) /* return only when something happens */ + c = event_multi (); + + if (c == 255) c = 0; /* timer event, return as NULL */ + return (c); +} + +/*------------------------------*/ +/* int_key */ +/*------------------------------*/ + +/* Should this run as a machine interrupt or a game pseudo-interrupt? + Some ops ($VERIFY) take a long time. */ + +int_key() +{ +/* On the Amiga, if event messages (i.e. typed-ahead keys) aren't replied + quickly by the application and are allowed to accumulate, the OS + allocates extra buffers which /never/ get released (Peck p155). + + This can cause nasty fragmentation of free memory and break OPSOUND + (since it dynamically allocates and releases large blocks). + + One fix: reply every message immediately, and store type-ahead in our + own small queue. Should also properly decode FKey and mouse events. + + (If /currently/ awaiting input, just exit) */ +} + +/************************************************************************/ +/* More Output Routines */ +/************************************************************************/ + +int hl_mode = 0; /* current mode (in kernel format) */ + +/*------------------------------*/ +/* highlight */ +/*------------------------------*/ +int +highlight (mode) /* if mode = -1, return current mode */ +WORD mode; +{ +static WORD sd_cur = 0; /* initial SetDrMode */ +static WORD ss_cur = FS_NORMAL; /* initial SetSoftStyle */ +static WORD font_cur = 0; /* topaz 80 */ + + WORD sd_mode = 0; + WORD ss_mode = FS_NORMAL; + WORD font_mode = 0; +struct TextFont *tf; + + if (mode == -1) return (hl_mode); + else hl_mode = mode; /* remember it */ + + switch (mode) + { + case 0: /* normal text, no effects */ + break; + case 1: /* inverse video */ + sd_mode = INVERSVID; + break; + case 2: /* bold */ + ss_mode = FSF_BOLD; + break; + case 4: /* underlineD (italic) */ + ss_mode = FSF_UNDERLINED; + /** ss_mode = FSF_ITALIC; **/ /* causes spacing problem) */ + break; + case 128: /* use alt charset */ + font_mode = 1; + break; + } + + if (sd_mode != sd_cur) { + SetDrMd (ZRastPort, JAM2 + sd_mode); + sd_cur = sd_mode; /* remember current */ + } + + if (ss_mode != ss_cur) { + SetSoftStyle (ZRastPort, ss_mode, 0xFF); /* only 1 at a time */ + ss_cur = ss_mode; + } + + if (font_mode != font_cur) { + + if (font_mode) tf = altfont; + else tf = sysfont; + + if (tf) SetFont (ZRastPort, tf); + font_cur = font_mode; + } +} + +/*------------------------------*/ +/* set_color */ +/*------------------------------*/ + +WORD set_color (fore, back) /* return system defaults */ +WORD fore, back; +{ + /* ignore if display doesn't support colors */ + if (color) { + set_back (back); /* first, since may have side effect! */ + set_fore (fore); + } + + return ((DEF_BACK << 8) | DEF_FORE); +} + +/*------------------------------*/ +/* set_fore */ +/*------------------------------*/ + +set_fore (id) +register WORD id; +{ + register WORD pen; + + if (id == 1) + id = DEF_FORE; /* use default */ + + if (id >= BASE_ID && id <= LAST_ID) { + pen = colormap[id]; /* convert XZIP id to pen # */ + SetAPen (ZRastPort, pen); /* and reset foreground pen */ + } +} + +/*------------------------------*/ +/* set_back */ +/*------------------------------*/ + +/* Note: In general, we want the edges of a screen to be the same color + as our background (otherwise it looks bad). Since the edges are rendered + using pen 0, we will always use pen 0 for our background, and change + its RGB definition as required. This means that, like the ST, there can + be only one "primary" background color at a time (although "secondary" + backgrounds would be easy enough to support if XZIP recognized the + concept). */ + +set_back (id) +register WORD id; +{ + register WORD pen, i2, oRGB, nRGB; + int seq[4]; + + if (id == 1) + id = DEF_BACK; + + if (id < BASE_ID || id > LAST_ID) + return (0); /* (no change) */ + + pen = colormap[id]; /* convert XZIP id to pen number */ + + if (pen != 0) { + /* find current id of pen 0 */ + for (i2=BASE_ID; i2<=LAST_ID; i2++) { + if (colormap[i2] == 0) break; + } + + /* swap id entries, RGB entries */ + colormap[i2] = colormap[id]; + colormap[id] = 0; + + oRGB = colortable[0]; + nRGB = colortable[pen]; + colortable[0] = nRGB; + colortable[pen] = oRGB; + + /* and install new colors (would be simpler to reload whole table, + but that seems to have the side effect of changing the foreground + color to the last entry in the table (??)) */ + /** LoadRGB4 (&(ZScreen->ViewPort), colortable, MAXCOLORS); **/ + + unpack_RGB (nRGB, &seq); + SetRGB4 (&(ZScreen->ViewPort), 0, seq[1], seq[2], seq[3]); + + unpack_RGB (oRGB, &seq); + SetRGB4 (&(ZScreen->ViewPort), pen, seq[1], seq[2], seq[3]); + } +} + +unpack_RGB (val, p) /* unpack 4 nybbles into array at p */ +register int val, *p; +{ + register int i; + + for (i=3; i>=0; i--) { + p[i] = val & 0x000F; /* rightmost nybble */ + val >>= 4; + } +} diff --git a/amiga/yzip-fileio.c b/amiga/yzip-fileio.c new file mode 100644 index 0000000..0f16bdc --- /dev/null +++ b/amiga/yzip-fileio.c @@ -0,0 +1,251 @@ + +/* ************************************************************************* + * + * yzip-fileio.c + * + * *********************************************************************** */ + +/* This is YZIP's interface to fileio. Collecting all YZIP extensions + * together in this file should make upgrading to a new version of fileio + * easier, if one becomes available. + */ + +#define FILEIO_SOURCEFILE +#include "fileio.h" + +/* externs (from lattice lib; also used in z-inits) */ + +extern stpchr (); +extern strrchr (); + +/* user globals */ + +struct FileIOSupport *Zfileio = NULL; + + +/*------------------------------*/ +/* fsel_init */ +/*------------------------------*/ + +/* (returns no result, just leaves Zfileio null if error) */ + +VOID fsel_init (init, ref_icon, curdir) +BOOL init; /* False to cleanup */ +struct DiskObject *ref_icon; /* our template */ +char *curdir; +{ + char *p1, c; + + if (init) { + Zfileio = GetFileIOSupport(); + if (Zfileio == NULL) + return; + + unBuildFileIOPathname (Zfileio, curdir); + Zfileio->FileName[0] = 0; /* (but no fname) */ + + SetFlag (Zfileio->Flags, USE_VOLUME_NAMES); + + /*** SetFlag (Zfileio->Flags, WBENCH_MATCH | MATCH_OBJECTTYPE); + Zfileio->DiskObjectType = WBTOOL; ***/ + + /* In our preloaded icon template, patch the "type string" + slightly, so the Fileio display will list the user's subsequent + Saves, but /avoid/ including the template file itself. */ + + p1 = (char *) FindToolType ( + ref_icon->do_ToolTypes, "FILETYPE"); + + if (p1 != NULL) /* found a valid string? */ + if ((c = *p1) != 0) { + if (c >= 0x60) + c -= 0x20; /* toggle case */ + else c += 0x20; + *p1 = c; + + /* copy the patched string into the fileio record, and + use it for all saves. Notice this means we can customize + the type-string for each sku we ship by simply + editing the special icon ... */ + + CopyString (&Zfileio->ToolType[0], p1); + SetFlag (Zfileio->Flags, + WBENCH_MATCH | MATCH_TOOLTYPE); + } + /* if a valid type string wasn't found (i.e. it's been deliberately + removed from the special icon by a user), we just avoid setting + the match-flags, so FileIO does no filtering at all. + Might come in handy someday ... */ + + } /* end of init */ + else { /* cleanup */ + if (Zfileio) + ReleaseFileIO (Zfileio); + } +} + +/*------------------------------*/ +/* fsel_do */ +/*------------------------------*/ + +/* call GetFileIOName(), leave full path+name in given buffer. + * return values: + * 1 if Cancelled + * 0 (meaning "no error" to YZIP) if name gotten + * -1 if FileIO call not available + */ +int fsel_do (opsave, partial, Zfullname, ZWind) +BOOL opsave; /* if zero, this is a Restore */ +BOOL partial; +char *Zfullname; +struct Window *ZWind; +{ + BOOL result; + struct FileIOSupport tfio; /* temp */ + BOOL new_fname = FALSE, + new_dir = FALSE; + + if (!Zfileio) + return (-1); + +/* [Initially, Zfullname contains the Current Dir] */ + + if (opsave) { + Zfileio->ReqTitle = (UBYTE *)"Save to file:"; + + /* For a save dialog, we want the "Type a Name" field to wake up + * empty, so the user won't have to tediously erase it. + * We don't disturb the Disk/Drawer fields. + */ + Zfileio->FileName[0] = 0; + Zfileio->CurrentPick = -1; /* "none" */ + } + + else { + Zfileio->ReqTitle = (UBYTE *)"Restore from file:"; + + /* Check whether disk/drawer matches last /successful/ call. + If changed, copy fields back into the fileio record as defaults, + and invalidate fileio's display list. */ + + unBuildFileIOPathname (&tfio, Zfullname); + if (!StringsEqual (&Zfileio->DiskName[0], &tfio.DiskName[0])) + { + CopyString (&Zfileio->DiskName[0], &tfio.DiskName[0]); + new_dir = TRUE; + } + if (!StringsEqual (&Zfileio->DrawerName[0], &tfio.DrawerName[0])) + { + CopyString (&Zfileio->DrawerName[0], &tfio.DrawerName[0]); + new_dir = TRUE; + } + + /* also check for fname match */ + + if (!StringsEqual (&Zfileio->FileName[0], &tfio.FileName[0])) + { + CopyString (&Zfileio->FileName[0], &tfio.FileName[0]); + new_fname = TRUE; + } + + if (new_dir) + ClearFlag (Zfileio->Flags, GOOD_FILENAMES); + if (new_dir || new_fname) + Zfileio->CurrentPick = -1; /* "none" */ + } + +/* go for it ... */ + + result = GetFileIOName (Zfileio, ZWind); + if (result) /* 1 means not cancelled */ + BuildFileIOPathname (Zfileio, Zfullname); + +/* This would only be neccessary only if we had /another/ fileio structure + besides Zfileio. */ + +/* if (FlagIsSet (Zfileio->Flags, DISK_HAS_CHANGED)) + * /-* Oops, disk swapped, so restart the other *-/ + * { + * ClearFlag (Zfileio->Flags, DISK_HAS_CHANGED); + * ClearFlag (Xfileio->Flags, GOOD_FILENAMES); + * } + */ + if (!result) + return (1); /* (map False to 1) */ + else return (0); /* (and True to 0) */ +} + +/*------------------------------*/ +/* fsel_written */ +/*------------------------------*/ + +/* This is called after a new Save file has been successfully created. */ + +fsel_written (Zfullname) +char *Zfullname; +{ + if (Zfileio) + AddFileIOName (Zfileio, Zfullname); +} + +/*------------------------------*/ +/* fsel_diskevent */ +/*------------------------------*/ + +/* This is called anytime the YZIP main event loop detects that a + * new disk was inserted. + */ + +fsel_diskevent () +{ + if (Zfileio) + ClearFlag (Zfileio->Flags, GOOD_FILENAMES); +} + +/*------------------------------*/ +/* unBuildFileIOPathname */ +/*------------------------------*/ + +/* given a full path in buffer, + split it up and copy it into the disk-drawer-name fields of fileio */ + +unBuildFileIOPathname (fio, buffer) +struct FileIOSupport *fio; +UBYTE *buffer; +{ + char *p1, *p2, *p3; + char *base1, *base2, *base3; + char local[128]; + + p1 = &fio->DiskName[0]; + p2 = &fio->DrawerName[0]; + p3 = &fio->FileName[0]; + +/* To avoid leaving trash in the input buffer, make a local copy of it. */ + + base1 = &local[0]; + CopyString (base1, buffer); + + base2 = (char *) stpchr (base1, ':'); /* find first colon */ + if (!base2) { + base2 = base1; + *p1 = 0; + } + else { + *base2++ = 0; + CopyString (p1, base1); /* copy DiskName */ + ConcatString (p1, ":"); /* and colon */ + } + + base3 = (char *) strrchr (base2, '/'); /* find LAST slash */ + if (!base3) { + base3 = base2; + *p2 = 0; + } + else { + *base3++ = 0; + CopyString (p2, base2); /* copy DrawerName */ + } /* (but not slash) */ + + CopyString (p3, base3); /* copy FileName */ +} diff --git a/amiga/yzip.c b/amiga/yzip.c new file mode 100644 index 0000000..0421f52 --- /dev/null +++ b/amiga/yzip.c @@ -0,0 +1,9 @@ + +#include "yzip.h" + +#include "yzip1.c" +#include "yzip3.c" + +/** #include "yzip2.c" **/ +/** #include "gfx.c" **/ + diff --git a/amiga/yzip.h b/amiga/yzip.h new file mode 100644 index 0000000..bd46a4a --- /dev/null +++ b/amiga/yzip.h @@ -0,0 +1,121 @@ + +/*------------------------------------------------------*/ +/* General header file for YZIP */ +/*------------------------------------------------------*/ + +#ifndef YZIP_H +#define YZIP_H /* else (been here before,) ignore it all */ + +/*------------------------------*/ +/* system includes */ +/*------------------------------*/ + +#include "exec/types.h" +#include "exec/exec.h" +#include "exec/libraries.h" /* for Library.lib_Version */ +#include "libraries/dos.h" +#include "libraries/dosextens.h" + +#include "intuition/intuition.h" /* for AllocRemember */ +#include "intuition/intuitionbase.h" + +#include "workbench/icon.h" +#include "workbench/workbench.h" /* for disk objects */ + +#include "graphics/text.h" /* SetSoftStyle flags */ +#include "graphics/rastport.h" /* SetDrMode flags */ +#include "graphics/gfxbase.h" /* for screen size vars */ + +#include "hardware/intbits.h" /* for interrupt flag */ + +/*------------------------------*/ +/* YZIP typedefs */ +/*------------------------------*/ + +#define VOID int /* "void" requires many forward declares */ +#define GLOBAL /**/ + +/** /-* already defined in exec/types.h) *-/ +typedef long LONG; /-* 32 bits *-/ +typedef unsigned long ULONG; +typedef short WORD; /-* 16 bits *-/ +typedef unsigned short UWORD; +typedef char BYTE; /-* 8 bits *-/ +typedef unsigned char UBYTE; + +typedef unsigned char *STRPTR; +typedef STRPTR *APTR; +typedef short BOOL; +typedef unsigned char TEXT; + +#define TRUE 1 +#define FALSE 0 +#define NULL 0 +**/ + +typedef unsigned char CHAR; /* always unsigned for us */ +typedef unsigned char UCHAR; + +#define ERR 1 +#define NOERR 0 + +/*------------------------------*/ +/* YZIP switches */ +/*------------------------------*/ + +/* This switch controls conditional ZIP/EZIP compilation */ +/* (WAS defined in batch file, where compiler is invoked) */ +/* (For XZIP must always be true) */ + +#define EZIP 1 /* set for EZIP, otherwise classic */ + +#define ZDEBUG 0 /* set for debugging */ +#define bug_DiskFull 0 /* set if crashes system - FIXED */ +#define DEADCODE 0 /* set to re-include */ + +/*------------------------------*/ +/* color stuff */ +/*------------------------------*/ + +#define MAXCOLORS 11 /*8*/ /* total YZIP color ids (w/3 grays) */ +#define BASE_ID 2 +#define LAST_ID BASE_ID+MAXCOLORS-1 /*9*/ + +#define DEF_FORE 9 /* default Amiga foreground = white */ +#define DEF_BACK 11 /*6*/ /* default Amiga background = med gray */ + +/*------------------------------*/ +/* window stuff */ +/*------------------------------*/ + +#define AM_YSIZ 200 /* hardwired for YZIP */ +#define AM_XSIZ 640 + +#if EZIP + +/** #define Peek1 0 **/ /* (for YZIP, now a var) */ + /*8+4*/ /*8+3*/ /* ZScreen scanlines showing behind ZWindow */ +#define Peek2 0 /*8+5*/ /* WBScreen scanlines showing behind ZScreen */ + +/* The first margin is needed for the ZScreen slider and show/hide boxes. + Without these functions, task switching is crippled. + + The second margin is needed because of an Intuition problem that causes + all system alert boxes (e.g. insert disk X, disk X full, etc) to appear in + the WB screen, normally hidden by EZIP. This space permits the words + "System Alert" to show through to the user. >>> FIXED IN WB 1.2 <<< +*/ +#else +/** #define Peek1 0 **/ +#define Peek2 0 +#endif + +/* The size of the hidden titlebar is a compromise: big enough to grab + easily, but not enough to interfere with game (e.g. Z0 compass). */ + +#define HIDDEN_TBAR_HEIGHT 4 + + + +#endif /* ... end of YZIP_H conditional */ + diff --git a/amiga/yzip1.c b/amiga/yzip1.c new file mode 100644 index 0000000..04de5e4 --- /dev/null +++ b/amiga/yzip1.c @@ -0,0 +1,1036 @@ + +/*------------------------------------------------------*/ +/* AMIGA YZIP INTERFACE */ +/*------------------------------------------------------*/ + +/* YZIP MODIFICATION HISTORY + + 05 Jan 89 ported (68K) from Mac YZIP + pixelized cursor vars + added first/last row/col vars (cur window) + 08 Feb 89 added curwind arg to set_color + added curs_vis global, checked in blink_cursor + +/* XZIP MODIFICATION HISTORY + + 11 Nov 87 ported from EZIP code + stash_get now called from event_in NOT read_console + (to avoid infinite loop w/ get_control_seq) + begin_mark must be /unsigned/ (UCHAR); + read_cursor_pos() & get_control_seq now work + + ZIP/EZIP MODIFICATION HISTORY + + 25 OCT 85 init_script () uses PRT: file. Close_Device was + crashing when two games run simultaneously. + + 29 OCT 85 drive_default() strips savename of leading spaces + 29 OCT 85 get_control_seq() ignores garbage seqs + + 04 NOV 85 write_cursor_pos() takes no params (same as read) + 04 NOV 85 extra error checking in make_icon_file() + + 22 JUL 87 changed scripting EOL seq from Esc-E to CRLF, + wasn't working under AmigaDOS 1.2 + added unhide_screen for Alertbox problem + set NOCAREREFRESH flag to avoid border flicker + added stash_put(), stash_get() for typeahead; + read_cursor_pos() still NOT working as advertised + 26 AUG 87 added volume control to md_sound (in SOUND.C) + 01 Nov 87 switched to Native development +*/ + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ + +/* this now a var, so can tweak during debugging */ + + int Peek1 = 0; /* scanlines to allow for title bar */ + +#if EZIP +struct Screen *ZScreen; +struct TextFont *sysfont, *altfont; +#endif + +struct Window *ZWindow; +struct RastPort *ZRastPort; + +struct Device *ConsoleDevice; /* for library vector */ + +/* Use altered IOStdReq structure, "data" field type APTR changed to STRPTR. + Otherwise the compiler forces string pointers to be even-aligned. + >>> CHANGED BACK FOR NATIVE DEVELOPMENT - dbb <<< */ + +struct IOStdReq/*_MUNGED*/ ZIOStdReq; /* for Console device */ +/** (now DEAD) +struct IOStdReq/-*_MUNGED*-/ ZRDStdReq; /-* for queued reads *-/ +struct MsgPort ZMsgPort; **/ + +/* cursor variables (all now in pixels) */ + +GLOBAL WORD y_char, x_char; + WORD y_res, x_res; /* YZIP: same as tot_rows/cols */ +GLOBAL WORD tot_cols, tot_rows; /* (was columns, rows) */ + +GLOBAL WORD cur_col, cur_row; /* always in 0 .. tot-1 */ +GLOBAL WORD first_row, last_row, /* bounds of current YZIP window */ + first_col, last_col; +GLOBAL WORD marg_left = 0, marg_right = 0; + +GLOBAL WORD curs_vis = 1; /* zero to suppress totally */ + +GLOBAL WORD xmouse, ymouse; /* 1-origin */ + +/* memory usage can be controlled by user, by supplying a free byte + count in the CLI command line. Useful if another task will be launched + subsequently. Otherwise game takes as much memory as it can use. */ + + LONG mem_freereq; /* set during init */ + + CHAR *execname = NULL; /* zip name, get from OS */ + + LONG IntuitionBase; + LONG GfxBase; /* for ZRastPort calls */ +/** LONG DiskfontBase; **/ /* for OpenDiskFont -- DEAD */ + LONG DosBase; + LONG IconBase; + +struct DiskObject *diskobj; /* SAVE file icon info */ +struct Remember *RememberKey; + +/* Amiga RGB values for the 8 XZIP colors, ordered so that the first three + correspond to the usual Workbench defaults. The values were determined + empirically. */ + + UWORD colortable[] = { + 0x005A, 0x0FFF, + 0x0000, 0x00C0, /* blue, white, black, green */ + 0x0E00, 0x0EE0, + 0x0F0F, 0x00EE, /* red, yellow, magenta, cyan */ + 0x0AAA, 0x7777, + 0x0444 /* lt, med, dk gray */ + }; + +/* This table relates XZIP color ordering to the above Amiga ordering */ + + UBYTE colormap[] = { + -1, -1, /* (placeholders -- never read) */ + 2, 4, 3, 5, /* black, red, green, yellow */ + 0, 6, 7, 1, /* blue, magenta, cyan, white */ + 8, 9, 10 /* lt, med, dk gray */ + }; + + BOOL tty_color = FALSE; /* default */ + + CHAR *cno = "Couldn't open: "; /* prefix for fatalmsg() */ + CHAR *cnc = "Couldn't create "; + + UBYTE *soundbuf; /* preallocate to avoid fragmentation */ + +/************************************************************************/ +/* Externals */ +/************************************************************************/ + +extern CHAR *gamename; +extern LONG game_ref; +extern CHAR savename[]; +extern CHAR saveback[]; + +/* (extern /functions/ apparently automatic under current Lattice) */ + +/** +extern LONG trap1 (); +extern VOID ZSTART (); + +extern fsel_init (); +extern int fsel_do (); +extern fsel_written (); +extern fsel_diskevent (); +**/ + +/************************************************************************/ +/* Misc Functions */ +/************************************************************************/ + +/*------------------------------*/ +/* delay */ +/*------------------------------*/ + +delay (n) /* in 1/10 secs */ +WORD n; +{ + Delay (n * 5); /* AmigaDOS function, in 1/50 secs */ + +/** ULONG secs, mics, sfinal, mfinal; + BOOL done = FALSE; + + CurrentTime (&secs, &mics); + sfinal = secs + n; mfinal = mics; /-* n in whole secs *-/ + while (!done) { + CurrentTime (&secs, &mics); + if (secs == sfinal && mics >= mfinal) + done = TRUE; + if (secs > sfinal) + done = TRUE; + } **/ +} + +/*------------------------------*/ +/* unhide_screen */ +/*------------------------------*/ + +/* [EZIP only] Fixes a bug under AmigaDOS 1.2. When a System Alert box + occurs, the Workbench screen pops to the front [?why?] and the box appears + in it. But after the user responds to the alert, the Workbench screen + does not automatically unhide the game screen. This is likely to make + users think the game has gone away. Ugh. */ + +unhide_screen() /* [call just before start of input] */ +{ +#if EZIP + ScreenToFront (ZScreen); /* NOP if already at front */ +#endif +} + +/*------------------------------*/ +/* bell_sound */ +/*------------------------------*/ +VOID +bell_sound (tone) + +WORD tone; /* 1 for beep, 2 for boop */ +{ +/* no internal bell, just ignore beep; flash screen for boop */ + + if (tone == 2) + DisplayBeep (ZWindow->WScreen); /* (a system call) */ +} + +/*------------------------------*/ +/* random_seed */ +/*------------------------------*/ +ULONG +random_seed () +{ + ULONG secs, mics; + + CurrentTime (&secs, &mics); + + /* low 20 bits (significant in mics) are the most random */ + return (secs + mics); +} + +/*------------------------------*/ +/* window_resized */ +/*------------------------------*/ +WORD +window_resized () /* update globals, return window column width */ + +/* this routine is called - + [] during init + [] (CZIP) after a RDLINE input + [] (CZIP) after every line output (this takes care of MOREs) +*/ + +{ +/* determine size of current font */ + + /* (DONE ONCE ONLY, DURING INIT; SETS Y_CHAR AND X_CHAR) */ + +/* determine usable size of window */ + + y_res = ZWindow->Height - ZWindow->BorderTop - ZWindow->BorderBottom; + x_res = ZWindow->Width - ZWindow->BorderLeft - ZWindow->BorderRight; + +/* For YZIP, we secretly steal the title bar area and add it to y_res. + The handful of calls that operate directly on our RastPort/BitMap must + take this into account. We let the system continue to think it owns + the title bar area as usual, in order that screen gadgets will function + normally (sliding, depth gadgets). */ + +/** x_res = AM_XSIZ; + y_res = AM_YSIZ; **/ /* (independent of hack_wsize()) */ +/** y_res += Peek1; **/ + +/* Calculate rows and columns. To prevent undesired AMIGA auto wrapping, + (CZIP only) we pretend that the column width is one less than it really is. +*/ + tot_rows = y_res; /* /y_char */ + tot_cols = x_res; /* /x_char */ + +/** if (cur_row >= tot_rows) cur_row = tot_rows - 1; /-* CZIP *-/ + if (cur_col >= tot_cols) cur_col = tot_cols - 1; +**/ + last_row = tot_rows; /* initial window bounds */ + last_col = tot_cols; + + return (tot_cols); /* updates kernel folding routines */ +} + +/************************************************************************/ +/* Memory Management */ +/************************************************************************/ + +/* memory fudge factor -- leave this much free for transient use, + (unless over-ridden by the F/n command switch). Resizing of windows + especially triggers large dynamic allocation requests. Also, opening + a script channel uses some 25K. (We now pre-allocate a main sound + buffer.) +*/ + +#define MEM_SYSTEM 64*1024 /* normal XZIP */ + +/** #if EZIP +#define MEM_SYSTEM 32*1024 /-* allow loading on 256K machine *-/ +#else /-* if ZIP *-/ +#define MEM_SYSTEM 64*1024 /-* enough for several windows *-/ +#endif **/ + +#define MEM_DEFAULT -1 /* user didn't specify memory use */ + +/*------------------------------*/ +/* c_maxmem */ +/*------------------------------*/ + +/* Return size of available memory pool, may be "doctored" (up or down) + upon user request. This routine should be called after every + significant allocation has been made except for the page buffers. */ + +LONG +c_maxmem (game_total) +LONG game_total; /* max memory (for buffers) we can use */ +{ + LONG game_used; + LONG mem_avail, mem_return; + + CHAR message[64]; + LONG len; + + mem_avail = (AvailMem (MEMF_PUBLIC)); + + if (mem_freereq == MEM_DEFAULT) + mem_return = mem_avail - MEM_SYSTEM; /* adjust it */ + else + { +/* got a request, use it */ + + if (mem_freereq < 0) mem_freereq = 0; + if (mem_freereq > mem_avail) mem_freereq = mem_avail; + + mem_return = mem_avail - mem_freereq; /* "doctor" it */ + +/* Request was made, so report our status to user. Want to show + the actual amount we will use here (if less than returned value). */ + + if (game_total > mem_return) + game_used = mem_return; + else + game_used = game_total; + + stcu_d (&message[0], game_used, 32); + strcat (&message, " bytes used"); + + /* if free will be more than requested, show why */ + + if (game_used == game_total) + strcat (&message, " (maximum)"); + strcat (&message, ", "); + + len = strlen (&message); + stcu_d (&message[len], (mem_avail - game_used), 32); + strcat (&message, " bytes free"); + + len = strlen (&message); + line_out (&message, len); + char_out (13); + char_out (13); + } + + return (mem_return); +} + +/*------------------------------*/ +/* c_getmem */ +/*------------------------------*/ + +LONG c_getmem (nbytes) /* return zero if failed */ +LONG nbytes; +{ +/** return (AllocMem (nbytes, MEMF_PUBLIC)); **/ + +/* This routine calls the AllocMem function, and also allocates a "link node," + which allows automatic de-allocation when we terminate. + We don't normally require any particular memory type (e.g., public or chip). +*/ + return (AllocRemember (&RememberKey, nbytes, MEMF_CLEAR)); +} + +/************************************************************************/ +/* Initializations */ +/************************************************************************/ + +#define NOTYET 0 /* (slot to be defined at runtime) */ + +/*------------------------------*/ +/* window_init */ +/*------------------------------*/ + +WORD set_color (); /* forward */ + +struct TextAttr sysTextAttr = { + "topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT + }; +/*** +struct TextAttr altTextAttr = { + "BZ Font.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_DISKFONT + }; +***/ /* no longer used */ + +WORD window_init (open, zplanes, wcolor) +BOOL open; /* cleanup if false */ +int zplanes; /* 4 (gfx), 3 (text color only), 1 (otherwise) */ +BOOL wcolor; /* if True, load our default (8) text colors */ +{ +static struct NewScreen ns = { + 0, 0 + Peek2, /* LeftEdge, TopEdge */ + AM_XSIZ, AM_YSIZ-Peek2, /* Width (high-res), Height >> defaults << */ + 1, /* Depth (default = 2 colors) */ + 0, 1, /* DetailPen, BlockPen */ + HIRES, /* ViewModes */ + CUSTOMSCREEN, /* Type */ + &sysTextAttr, /* Font (topaz 80) */ + NULL, /* DefaultTitle */ + NULL, /* Gadgets */ + NULL /* CustomBitMap */ + }; + +static struct NewWindow nw = { + 0, NOTYET, /* 0 + Peek1 */ /* LeftEdge, TopEdge */ + NOTYET, NOTYET, /* derive from ns */ /* Width, Height */ +/** AM_XSIZ, (AM_YSIZ - Peek2) - Peek1, **/ + 0, 1, /* DetailPen, BlockPen */ +/* IDCMP Flags: */ + RAWKEY | MOUSEBUTTONS | INTUITICKS + | DISKINSERTED, /* (for FileIO) */ +/* Window Flags: */ + BORDERLESS | SMART_REFRESH + | ACTIVATE | NOCAREREFRESH +/* In YZIP this prevents the right mouse button from "dropping down" + a blank menu strip and wiping out one or two scanlines at the top that + we (may) have stolen. (Okay as long as we're not using menus anyway.) */ + | RMBTRAP, + NULL, /* FirstGadget */ + NULL, /* CheckMark */ + NULL, /* Title */ + NOTYET, /* Screen */ + NULL, /* BitMap */ + 0, 0, 0, 0, /* (min+max sizes, unused) */ + CUSTOMSCREEN /* Type */ + }; + + struct GfxBase *gb = (struct GfxBase *) GfxBase; + + if (open) + { + /* first create a custom screen ... */ + + if (gb->LibNode.lib_Version >= 33) { + /* must be running under system 1.2+ to use size fields */ + + /* Lattice 4.0 bug (3.x OK): when Peek2 = 0, + this assignment vanishes! */ + /** ns.Height = gb->NormalDisplayRows - Peek2; **/ + /*** ns.Height = gb->NormalDisplayRows; + ns.Width = gb->NormalDisplayColumns; ***/ + + /* For YZIP (w/gfx), back to the future! */ + ns.Height = AM_YSIZ; + ns.Width = AM_XSIZ; + } + else { + /* FileIO now /requires/ 1.2. (Could support 1.1 by + avoiding FileIO ...) */ + fatalmsg ("Requires AmigaDOS 1.2 or higher"); + return (ERR); + + /* under system 1.1, deduce size from this flag */ + + /*** if ((gb->DisplayFlags) & PAL) + ns.Height = 256 - Peek2; ***/ + /** else ns.Height = AM_YSIZ-Peek2; **/ /* default */ + /** ns.Width = 640; **/ /* default */ + } + + ns.Depth = zplanes; + ns.DefaultTitle = (UBYTE *) execname; /* null, or our name */ + + ZScreen = (struct Screen *) OpenScreen (&ns); + if (ZScreen == NULL) { + fatalmsg (cnc); fatalmsg ("Screen"); + return (ERR); + } + + /* then create a window (taking size from screen) ... */ + + nw.Height = ns.Height - Peek1; + /** nw.Height -= Peek1; **/ /* (avoid lattice bug when = 0) */ + nw.TopEdge = ns.TopEdge + Peek1; + + nw.Width = ns.Width; + nw.Screen = ZScreen; + + ZWindow = (struct Window *) OpenWindow (&nw); + if (ZWindow == NULL) { + fatalmsg (cnc); fatalmsg ("Window"); + return (ERR); + } + + ZRastPort = ZWindow->RPort; + SetDrMd (ZRastPort, JAM2); /* always draw fore AND back */ + + if (wcolor) /* (AND zplanes >= 3) */ { + + /* DEAD -- install our colors in the screen's table */ + /** LoadRGB4 (&(ZScreen->ViewPort), + colortable, MAXCOLORS); **/ + + /* initialize the default fgPen to 1; seems to otherwise + default to the end of the palette (7 or 15). */ + + SetAPen (ZRastPort, 1); + set_color (1, 1, 0); /* set YZIP text defaults */ + } + } + + else /* closing, clean up */ + { + if (ZWindow) + CloseWindow (ZWindow); + if (ZScreen) + CloseScreen (ZScreen); + } + + return (NOERR); +} + +/*------------------------------*/ +/* z_init */ +/*------------------------------*/ + +#define ZHLEN 64 /* file header len (bytes) */ +#define PFLAGS 8 /* flags word (in header) */ + +#define FDISP 08 /* DISPLAY-requested bit */ +#define FCOLO 64 /* color-requested bit */ +#define FSOUN 128 /* sound-requested bit */ + +LONG open_game (); /* forward */ +LONG close_game (); +LONG read_file (); + +WORD z_init () +{ + WORD err; + CHAR cur_prefs[1]; + CHAR old_YSize; + UWORD zheader[ZHLEN/2]; + int tty_gfx; + int zplanes; + + CHAR *SAVEINIT = "Save1"; + + CHAR *il = "intuition.library"; + CHAR *gl = "graphics.library"; +/** CHAR *dl = "diskfont.library"; **/ + CHAR *cd = "console.device"; + CHAR *icl = "icon.library"; + CHAR *dsl = "dos.library"; + +/* open the libraries we'll need */ + + IntuitionBase = (LONG) OpenLibrary (il, 0); + if (IntuitionBase == 0) { + fatalmsg (cno); fatalmsg (il); + return (ERR); + } + + GfxBase = (LONG) OpenLibrary (gl, 0); + if (GfxBase == 0) { + fatalmsg (cno); fatalmsg (gl); + return (ERR); + } + +/** DiskfontBase = (LONG) OpenLibrary (dl, 0); + if (DiskfontBase == 0) { + fatalmsg (cno); fatalmsg (dl); + return (ERR); + } **/ + +/* could close the WorkBench screen, to free up memory */ +/** CloseWorkBench (); **/ /* rude for user though */ + +/* check/adjust the default font */ + + GetPrefs (&cur_prefs, 1); /* get user's default size */ + old_YSize = cur_prefs[0]; /* 9 or 8 */ + +#if EZIP + +/* temporarily adjust Prefs, if necessary, to ensure 80 columns + (seems that this must be done before creating the Custom screen) */ + + if (old_YSize != TOPAZ_EIGHTY) + { + cur_prefs[0] = TOPAZ_EIGHTY; + SetPrefs (&cur_prefs, 1, FALSE); /* force to 8 */ + } +#endif + +/* read the game file header and see if color is desired */ + + err = open_game(); + if (err == 0) { + err = read_file (game_ref, 0, ZHLEN, &zheader); + close_game(); + } + if (err) { + fatalmsg (cno); fatalmsg (gamename); + return (ERR); + } + +/* these flags are nonzero (not 1/0) if the feature is requested */ + + tty_color = zheader[PFLAGS] & FCOLO; /* 8-color text req */ + tty_gfx = zheader[PFLAGS] & FDISP; /* 16-color gfx req */ + +/* create and open a game window (and custom screen, for EZIP) */ + + if (tty_gfx) + zplanes = 4; + else if (tty_color) + zplanes = 3; + else zplanes = 1; + + err = window_init (TRUE, zplanes, tty_color); + if (err) + return (ERR); /* (fatalmsg already called) */ + +/** sysfont = OpenDiskFont (&sysTextAttr); /-* 2nd time, actually *-/ + altfont = OpenDiskFont (&altTextAttr); /-* ZERO if error *-/ +**/ + setup_fonts (); /* our replacement for OpenDiskFont */ + +/* don't CREATE a console device, just get its library vector */ + + if (OpenDevice (cd, -1, &ZIOStdReq, 0) != 0) { + fatalmsg (cno); fatalmsg (cd); + return (ERR); + } + ConsoleDevice = ZIOStdReq.io_Device; + +/* create a console device, attaching it to our window */ +/** ZIOStdReq.io_Data = (LONG) ZWindow; + if (OpenDevice (cd, 0, &ZIOStdReq, 0) != 0) + return (ERR); +**/ + +#if EZIP +/* undo the temporary font setting, if it was changed above */ + + if (old_YSize != TOPAZ_EIGHTY) + { + cur_prefs[0] = old_YSize; + SetPrefs (&cur_prefs, 1, FALSE); /* restore user's choice */ + } +#endif + +/* initialize our internal text size variables */ + +#if EZIP + y_char = TOPAZ_EIGHTY; /* always 8 (80 columns) */ + x_char = 8; + +#else /* use the default fontsize */ + + y_char = old_YSize; /* either 8 or 9 */ + + if (old_YSize != TOPAZ_EIGHTY) + x_char = 10; /* can only be Topaz 60 */ + else x_char = 8; +#endif + + window_resized (); /* set up rows/columns globals */ + +/* set up the message port in the I/O request -- DEAD */ + +/** ZMsgPort.mp_Node.ln_Type = NT_MSGPORT; + ZMsgPort.mp_Flags = 0; + ZMsgPort.mp_SigBit = AllocSignal (-1); + ZMsgPort.mp_SigTask = (struct Task *) FindTask (NULL); + + AddPort (&ZMsgPort); + ZIOStdReq.io_Message.mn_ReplyPort = &ZMsgPort; **/ + +/* and start reading -- DEAD */ +/** ZRDStdReq = ZIOStdReq; /-* copy the whole structure *-/ + queue_read (); **/ + +/** cur_row = 0; cur_col = 0; **/ /* (automatic) */ +/** write_cursor_pos (); **/ + +/* default path+name for initial save */ + + getcwd (savename); /* default for FileIO */ + strcpy (saveback, savename); + strcat (saveback, SAVEINIT); /* default for old prompt */ + +/** RememberKey = NULL; **/ /* (automatic) */ + +/* Get the Save Icon info during init. This avoids having to access the game + disk later, when it may have been removed from the drive */ + + IconBase = (LONG) OpenLibrary (icl, 0); + + if (IconBase == NULL) + DosBase = NULL; + else + /* This one is for RJMical's FileIO only */ + DosBase = (LONG) OpenLibrary (dsl, 0); + + if (DosBase == NULL) + diskobj = NULL; /* (not a fatal error) */ + else + { + diskobj = (struct DiskObject *) GetDiskObject ("Icon.Data"); + + /* if info file not found, just return diskobj NULL. + Two effects: + - new saves will not have icons attached to them. + - the FileIO interface will be disabled, and we + will fall back into the old PC-style interface. + If any bugs or incompatibilities develop with the + FileIO interface, we can always instruct users to + do this deliberately. */ + + if (diskobj) + fsel_init (1, diskobj, &savename); + } + +/*** init_interrupt (1); ***/ /* (sound etc) */ + + if (zheader[PFLAGS] & FSOUN) { + +/* pre-allocate a 64K buffer for our "standard" single channel of sound data. + We would prefer to allocate sound buffers dynamically and free them when + not in use, but doing so risks failure. One reason is that Amiga free + memory tends to fragment, making it impossible later on to get the large + blocks our sound requires. */ + +/* >>> patch out, never used these days ... <<< */ +/*** soundbuf = (UBYTE *)AllocRemember + (&RememberKey, 64*1024, (MEMF_CHIP | MEMF_CLEAR)); +***/ + } + + if (tty_gfx) /* opDisplay requested */ + InitGFX (1); + + return (0); +} + +/*------------------------------*/ +/* setup_fonts */ +/*------------------------------*/ + +/* This routine inits the sysfont and altfont vars. For the system font, +we just pick up the pointer from our RastPort. Don't need to call +Open[Disk]Font a second time; it was called implicitly when our custom +screen/window was created. + + Setup for our alternate font is trickier. We do /not/ want to use +OpenDiskFont because of the assumptions it makes about where to find +the file (a system-wide FONTS: directory), and also about the existence +of a name file and a separate data subdirectory. Instead, we simulate +that call by reading the alternate data file into memory ourself, +and patching up a few pointers. +*/ + +#define ALTNAME "Char.Data" +/* don't call it "Font.Data" since user might be lead to needlessly copy it + into font directory, or "Graphic.Data" now that we have real gfx. */ + +VOID setup_fonts () +{ + LONG fd, len, actual_len, *lp; + WORD *wp; + register char *p, *segbase; + + sysfont = ZRastPort->Font; + +/* if an alternate font doesn't exist, just leave altfont NULL */ + + fd = Open (ALTNAME, MODE_OLDFILE); + if (!fd) return (1); /* if error, just exit */ + + Seek (fd, 0, OFFSET_END); + len = Seek (fd, 0, OFFSET_BEGINNING); /* get length */ + +/* Allocate memory for font data; deallocation will be handled automatically + (by FreeRemember) upon program exit. */ + + p = (char *) c_getmem (len); + if (p) { + actual_len = Read (fd, p, len); + if (actual_len == len) { + + segbase = p + 0x20; /* skip seg header stuff */ + altfont = (struct TextFont *) (segbase + 0x3A); + +/* absolutize some ptrs, all relative to segbase */ + + lp = (LONG *) (segbase + 0x44); + *lp += (LONG) segbase; /* font name string (NULL) */ + + lp = (LONG *) (segbase + 0x5C); + *lp += (LONG) segbase; /* packed char data */ + + lp = (LONG *) (segbase + 0x62); + *lp += (LONG) segbase; /* char offsets array */ + +/* also patch this one; not sure what it is (disk vs ROM font?) */ + + wp = (WORD *) (segbase + 0x58); + *wp = 0x0001; + } + } + Close (fd); +} + +#if DEADCODE /* currently require no true interrupts */ + +/*------------------------------*/ +/* VertBServer */ +/*------------------------------*/ + +/* This routine runs at the interrupt level. Happily, registers D0-D1/ + A0-A1 are scratch in interrupt protocol as well as the Lattice compiler. + Also, references to global vars are OK since in Lattice they are absolute, + rather than keyed off any special register. System calls are OK (unless + otherwise advertised), since standard "glue" code saves register A6 then + loads a dispatch vector from an absolute location, or from one of the + call's parameters in some cases (CheckIO?). +*/ + +extern void int_sound(); + +LONG VertBServer() /* run our interrupt routines */ +{ + int_sound(); + int_key(); + return (0); /* and continue down server chain */ +} + +/*------------------------------*/ +/* init_interrupt */ +/*------------------------------*/ + +/* Install our interrupt(s) on the vertical-blank interrupt chain (one of + the simpler ways to do Amiga interrupts). Executes up to 60 times/sec, + low priority. */ + +init_interrupt (start) +int start; +{ + static BOOL inited = 0; + static struct Interrupt zir; /* should be MEMF_PUBLIC? */ + register struct Interrupt *p = &zir; /* (tighten up code) */ + + if (start) { + p->is_Node.ln_Type = NT_INTERRUPT; + p->is_Node.ln_Pri = -60; /* not time-critical */ + p->is_Node.ln_Name = "zir"; + /** p->is_Data = 0; **/ /* currently unused */ + p->is_Code = (void *) VertBServer; + + /* put the new interrupt server into action */ + AddIntServer (INTB_VERTB, p); + inited = 1; + } + else { + if (inited) + RemIntServer (INTB_VERTB, p); + } +} +#endif /* DEADCODE */ + +/*------------------------------*/ +/* z_exit */ +/*------------------------------*/ + +/* Clean up everything, in reverse order of creation. Any memory allocated + but not freed will be lost to eternity. +*/ + +VOID +z_exit () +{ + InitGFX (0); /* cleanup graphics */ + +/** init_interrupt (0); **/ /* remove our interrupt */ + +/** shut down scripting, if no one else did **/ +/** if (prt_inited) + script_init (FALSE); **/ /* now in 68K */ + +/* free the Fileio and save file icon stuff, if it existed */ + fsel_init (0); + if (diskobj) + FreeDiskObject (diskobj); + + if (DosBase) + CloseLibrary (DosBase); + if (IconBase) + CloseLibrary (IconBase); + +/* de-allocate all memory claimed by 68K kernel initializations */ + if (RememberKey) + FreeRemember (&RememberKey, TRUE); + +/* close the various Console Device structures */ + +/** RemPort (&ZMsgPort); **/ +/** FreeSignal (ZMsgPort.mp_SigBit); **/ /* DEAD */ + + if (ConsoleDevice) + CloseDevice (&ZIOStdReq); /* looks odd, but correct */ + +/* close our window (and screen, for EZIP) */ + +/** if (altfont) { /-* DEAD, see setup_fonts *-/ + CloseFont (altfont); + /-* RemFont (altfont); *-/ /-* only if AvailFonts/AddFont used *-/ + } + if (sysfont) + CloseFont (sysfont); /-* necessary? opened twice *-/ +**/ + window_init (FALSE, 0, 0); + +/* try to re-open WorkBench, if we closed it */ + +#if EZIP +/** OpenWorkBench (); **/ +#endif + +/* lastly, close the libraries we opened */ + +/** if (DiskfontBase) CloseLibrary (DiskfontBase); **/ + if (GfxBase) CloseLibrary (GfxBase); + if (IntuitionBase) CloseLibrary (IntuitionBase); +} + +/*------------------------------*/ +/* fatalmsg */ +/*------------------------------*/ + +/* Display a fatal error message. For initialization errors, we don't want + to assume that our normal output window is operational, so we send the + message to the window of our controlling process -- either (1) the CLI, + or (2) the temporary window opened by our Workbench startup code. + + Just before we exit, pause long enough so that (in case 2) the message + can be read before the window is closed. Don't try to getc() a key; + might hang if temp window not opened, and inappropriate in case 1. */ + +fatalmsg (s) +char *s; +{ + if (s) + printf (s); + else { + printf ("\n"); + delay (20); /* two secs */ + } +} + +/************************************************************************/ +/* Top Level */ +/************************************************************************/ + +/*------------------------------*/ +/* parse_args */ +/*------------------------------*/ + +parse_args (argc, argv) +LONG argc; +CHAR *argv[]; /* an array of pointers */ +{ + CHAR *argx; + CHAR char1, char2; + int i; + +/* The only valid command line argument is F/n, where n is the minimum + number of bytes to leave in the free memory pool. + + If the argument is missing, or not a number, or if the game is run from + WorkBench, leave the default (MEM_SYSTEM, defined in c_maxmem). + + The game takes as much memory as it can use, within the above limit. +*/ + + mem_freereq = MEM_DEFAULT; /* assume no memory arg */ + +/* A general problem: the name of an executable file containing spaces + (more than one word) is not collected into one string! */ + +/** if ((argc >= 1) && (argv != 0)) + execname = (char *) argv[0]; /-* (used in window title) *-/ +**/ + if ((argc > 1) && (argv != 0)) /* got one */ + for (i=1; ifib_FileName); /* dir name */ + + if (newlock == 0) /* (actually vol name) */ + strcat (path, ":"); + else if (showslash) + strcat (path, "/"); + } + FreeMem (myinfo, sizeof(struct FileInfoBlock)); + } + } + UnLock (lock); + + if (error) /* make null the global string */ + path[0] = 0; + return (error); /* (zero if ok) */ +} + +/*------------------------------*/ +/* geterr */ +/*------------------------------*/ + +/* This is a front end for IoErr. It should be called /only/ when we know + an error occurred, and so expect a nonzero result. But IoErr sometimes + returns a zero anyway (e.g., after Create with a bad pathname). In + this case we return -1, so 68K stuff will know something went wrong. */ + +LONG geterr () +{ + LONG err = IoErr (); + + if (!err) err = -1; /* make sure it's nonzero */ + return (err); +} + +/************************************************************************/ +/* File Selection */ +/************************************************************************/ + +/*------------------------------*/ +/* file_select */ +/*------------------------------*/ +WORD +file_select (opsave, partial) /* get file and pathspec from user, */ + /* combine and leave in SAVENAME */ +BOOL opsave; /* zero if restore, otherwise save */ +BOOL partial; +{ +/* The Amiga lacks OS support for this function. We originally implemented + a simple prompt in the 68K kernel. For YZIP, we have added RJ Mical's + nifty FileIO routines. These now constitute our normal file interface. + + If FileIO fails to initialize for some reason, or if the user + disables it deliberately by deleting our template icon, this returns -1, + which tells the kernel to fall back into our old-style prompt. */ + + return ((WORD) fsel_do (opsave, partial, &savename, ZWindow)); +} + +/*------------------------------*/ +/* new_default */ +/*------------------------------*/ + +VOID +new_default (okay) /* called at end of each SAVE/RESTORE */ + +BOOL okay; +{ + if (okay) /* dest <- source */ + { + strcpy (&saveback, &savename); /* update old defaults */ + + /* take this opportunity to update FileIO's records. (Actually, + this call is required only after a save ... ) */ + fsel_written (&savename); + } + else + { + strcpy (&savename, &saveback); /* retrieve old defaults */ + } +} + +/*------------------------------*/ +/* strip_spaces */ +/*------------------------------*/ + +/* Remove any leading and/or trailing spaces from savenames, before + the file is created. AmigaDOS permits them, but they lead to confusing + RESTORE errors. + + Note that we continue to allow embedded spaces. +*/ + +VOID +strip_spaces (filename) + +CHAR *filename; +{ + WORD len; + + while (*filename == 32) + strcpy (filename, filename+1); /* move the string up */ + + len = strlen (filename); + while (len && (filename[len-1] == 32)) + { + filename[len-1] = 0; /* chop off any trailing spaces */ + --len; + } +} + +/*------------------------------*/ +/* divide_pathname */ +/*------------------------------*/ + +/* Check whether a given filename is prefixed with a drive or directory name. + If so, return a pointer to the bare filename, otherwise return NULL. + + Path syntax for Amiga is "DFn:PATH1/PATH2/PATHn/filename". +*/ + +CHAR * +divide_pathname (pathname) + +CHAR *pathname; +{ + CHAR *special; /* <:> and are the special chars */ + +/* if one or more directories were given, find the last one */ + + special = (CHAR *) strrchr (pathname, '/'); + +/* otherwise, see if a drive was given */ + + if (special == NULL) + special = (CHAR *) stpchr (pathname, ':'); + + if (special != NULL) /* found one, skip over the delimiter */ + special++; + + return (special); /* pointer to bare filename, or NULL */ +} + +/*------------------------------*/ +/* drive_default */ +/*------------------------------*/ + +/* If savename lacks a drive/directory spec but saveback includes one + (the default), prefix it to savename. + + Also, take this opportunity to remove any leading/trailing spaces from + savename. +*/ + +VOID +drive_default () +{ + CHAR *barename; + CHAR temp[64]; + +/* check whether savename includes a drive/directory */ + + barename = (CHAR *) divide_pathname (&savename); + + if (barename == NULL) /* Nope */ + { + strip_spaces (&savename); + +/* check whether a default drive/directory exists */ + + strcpy (&temp, &saveback); + + barename = (CHAR *) divide_pathname (&temp); + + if (barename != NULL) /* Yep */ + { +/* and prefix the default drive/directory onto savename */ + + *barename = 0; /* chop off default filename */ + strcat (&temp, &savename); + strcpy (&savename, &temp); + } + } + +/* user DID supply a drive/directory, just check for spaces in filename */ + + else + { + strip_spaces (barename); + } +} + +#if bug_DiskFull /* BUG GONE, THIS IS DEAD CODE */ + +/*------------------------------*/ +/* disk_bytes_avail */ +/*------------------------------*/ + +LONG +disk_bytes_avail () /* returns number of available bytes on save disk, + -1 if error. Must call AFTER save file is created */ +{ + struct FileLock *filelock; + LONG avail; + + WORD pad1; +struct InfoData ZInfoData; /* information about the save disk */ + WORD pad2; + +struct InfoData *ZInfoDataPtr; /* pointer to the above */ + LONG ptr; + + +/* Must first obtain a "lock" for a valid file on the desired disk. + We conveniently use the save file (thus it must already exist). */ + + filelock = Lock (&savename, ACCESS_READ); + + if (!filelock) /* if error, exit now */ + return (-1); + +/* The InfoData structure must be longword aligned (for AmigaDOS). + Adjust alignment with the pad bytes, if necessary. */ + + pad1 = pad2 = 0; /* make the Compiler stop whining */ + + ptr = (LONG) &ZInfoData; + ptr = ptr>>2; ptr = ptr<<2; + ZInfoDataPtr = (struct InfoData *) ptr; + +/* Determine how much space remains on the save disk. */ + + if (Info (filelock, ZInfoDataPtr)) + { + avail = + (ZInfoDataPtr->id_NumBlocks + - ZInfoDataPtr->id_NumBlocksUsed) /* free blks */ + * ZInfoDataPtr->id_BytesPerBlock; + } + else avail = -1; /* something wrong, fail */ + + UnLock (filelock); /* make sure to undo this lock */ + + return (avail); +} + +#endif /* bug_DiskFull */ + +/************************************************************************/ +/* Disk I/O */ +/************************************************************************/ + +/*------------------------------*/ +/* read_file */ +/*------------------------------*/ + +LONG +read_file (channel, offset, length, buffer) + +LONG channel; +LONG offset, length; +CHAR *buffer; +{ + LONG former_pos, actual_len, err_len; + LONG error; + +/* (Amiga) disk thrashing is reduced if unnecessary seeks are avoided */ + + if ((channel != old_channel) || (offset != old_offset)) + { + former_pos = Seek (channel, offset, -1); /* AmigaDOS */ + if (former_pos == -1) + { + old_offset = -1; /* force seek next time */ + return (geterr()); + } + } + + old_channel = channel; + old_offset = offset + length; + actual_len = Read (channel, buffer, length); + +/* Check the number of bytes actually read. This will detect certain + invalid save files (for example, files where Amiga crashed during their + creation, for whatever reason). +*/ + if (actual_len == length) + error = 0; /* no error */ + else { + old_offset = -1; /* force seek next time */ + if (actual_len == -1) + error = geterr(); + else + error = 1; /* length error */ + +/* [Old] We allow for a special case of actual length being 256 less than + expected. The kernel does paging in 512 byte blocks, while the Amiga + TFTP utility transfers data files in 256 byte blocks. + + [New] Since files transfered with Kermit aren't padded at all, we + allow for a /game/ file read to return up to 511 bytes less than + the request, without reporting an error. +*/ + if (channel == game_ref) { + err_len = length - actual_len; + if ((err_len >= 0) && (err_len < 512)) + error = 0; /* no error */ + } + } + + actlen = actual_len; /* save as global (for 68K) */ + return (error); +} + + +/*------------------------------*/ +/* write_file */ +/*------------------------------*/ + +LONG +write_file (channel, offset, length, buffer) + +LONG channel; +LONG offset, length; +CHAR *buffer; +{ + LONG error, actual_len; + +/* Errors: zero means none, 999 means disk full, otherwise geterr() */ + +#if bug_DiskFull + + if (disk_newsave) /* FALSE if writing over old file */ + { + disk_free = disk_free - length; + if (disk_free < 0) + return (999); /* not enough room for write */ + } +#endif + error = Seek (channel, offset, -1); + if (error == -1) + return geterr(); + + actual_len = Write (channel, buffer, length); + if (actual_len == -1) + return geterr(); + + else if (actual_len != length) /* (should have been caught above) */ + return (999); + + actlen = actual_len; /* save as global (for 68K) */ + return (0); /* no error */ +} + + +/*------------------------------*/ +/* create_file */ +/*------------------------------*/ + +LONG +create_file () /* create (if needed), and open, a SAVE file */ +{ + register LONG fd; + +/* two ways to enter this routine: if disk_newsave is TRUE, we are creating + a new save file, otherwise we are writing over an old one */ + + fd = Open (&savename, MODE_NEWFILE); + +#if bug_DiskFull /* avoid a write error */ + + if (fd && disk_newsave) + { +/* we just created the file, but must close it momentarily to get disk info. + Otherwise the Lock call fails */ + + Close (fd); + +/* determine how much free space is on the disk, so file_write can fail + gracefully if necessary */ + + disk_free = disk_bytes_avail (); + + fd = Open (&savename, MODE_NEWFILE); + } +#endif /* bug_DiskFull */ + + save_ref = fd; /* save global */ + if (!fd) + return (geterr()); + else + return (0); /* zero means OK */ +} + + +/*------------------------------*/ +/* open_file */ +/*------------------------------*/ + +LONG +open_file () /* open an file to RESTORE from */ +{ + LONG fd; + + fd = Open (&savename, MODE_OLDFILE); + + save_ref = fd; + if (!fd) + return (geterr()); + else + return (0); /* zero means OK */ +} + +/*------------------------------*/ +/* close_file */ +/*------------------------------*/ + +LONG +close_file () /* close a SAVE file */ +{ + if (save_ref) { + Close (save_ref); + save_ref = 0; + } + + old_channel = -1; /* make sure to reset this one */ + return (0); /* no error codes? */ +} + + +/*------------------------------*/ +/* delete_file */ +/*------------------------------*/ + +LONG +delete_file () +{ + LONG success; /* actually BOOLEAN */ + + success = DeleteFile (&savename); + + if (success) + return (0); + else return (1); +} + + +/*------------------------------*/ +/* exist_file */ +/*------------------------------*/ + +LONG +exist_file () /* called before every SAVE */ +{ + struct FileLock *fl; + + fl = Lock (&savename, ACCESS_WRITE); + if (fl) /* non-zero if already exists */ + { + disk_newsave = FALSE; /* set the global */ + UnLock (fl); /* remove the lock */ + } + else disk_newsave = TRUE; + + return ((LONG) fl); +} + +/*------------------------------*/ +/* open_game */ +/*------------------------------*/ + +LONG +open_game() +{ + game_ref = Open (gamename, MODE_OLDFILE); + + if (game_ref == 0) + return (geterr()); + else return (0); /* zero means OK */ +} + +/*------------------------------*/ +/* close_game */ +/*------------------------------*/ + +LONG +close_game () +{ + if (game_ref) { + Close (game_ref); + game_ref = 0; + } + old_channel = -1; /* make sure to reset this one */ + return (0); +} + + +/*------------------------------*/ +/* make_icon_file */ +/*------------------------------*/ + +LONG +make_icon_file () /* create a new save file icon, */ + /* called only after a successful SAVE */ +{ + LONG error; + LONG object; +/* WORD len; */ + +/* diskobj (should have been) read into memory during init */ + + if (diskobj == NULL) + error = 1; + else + { + +#if bug_DiskFull + +/* PROBLEM: PutDiskObj is crashing the machine when a disk-full error occurs. + First, make sure we have enough room for a new icon file. +*/ + +#define MaxIconSize 1024 /* actually ours is under 400 */ + + if (disk_newsave) /* if OLD save, space not an issue */ + { + disk_free = disk_bytes_avail (); + if (disk_free < MaxIconSize) return (1); + } + +/* (Alternate fix. The preceeding code fixes this problem better.) + + Do some preliminary error checking: Attempt to create a file with the + desired name, and put 1K of random data into it. +*/ + strcat (&savename, ".info"); /* desired name */ + error = create_file (); /* --> save_ref */ + + if (!error) + { + error = write_file (save_ref, 0, 1024, &savename); + + close_file (save_ref); /* (no error codes) */ + + if (!error) + error = delete_file (); /* <-- savename */ + else delete_file (); + } + + len = strlen (&savename); + savename[len-5] = 0; /* chop off the ".info" */ + + if (error) /* if ANY error, fail now */ + return (error); + +#endif /* bug_diskfull */ + + +/* Everything seems OK, go ahead and make the Save icon */ + + diskobj->do_CurrentX = NO_ICON_POSITION; + diskobj->do_CurrentY = NO_ICON_POSITION; + + /* write icon file via same path as save file */ + + object = PutDiskObject (&savename, diskobj); + + if (object == NULL) + error = geterr(); + else error = 0; + } + + return (error); +} + +/************************************************************************/ +/* Scripting */ +/************************************************************************/ + +/* scripting globals -- two methods possible */ + + LONG print_file; /* scripting refnum */ +/** +struct IOStdReq_MUNGED SIOStdReq; /-* not used *-/ +struct MsgPort SMsgPort; **/ + + WORD prt_inited = 0; /* set when printer opened */ + WORD prt_active = 0; /* set when scripting is active */ + + +/*------------------------------*/ +/* raw_script */ +/*------------------------------*/ + +WORD +raw_script (buffer, length) /* send data to the printer device */ + +LONG buffer, length; +{ + WORD error; + LONG seconds1, micros1; + LONG seconds2, micros2; + LONG actual_len; + +/* A problem: AmigaDOS (rev 1.0) isn't passing back printer error codes. + Each attempt to print when the printer isn't ready causes a 30 second + timeout. A series of these effectively hangs the game. + + To fix, use the delay to infer an error. If no error code is returned + but the delay exceeds 30 seconds, consider the printer not ready. +*/ + + CurrentTime (&seconds1, µs1); /* starting time */ + + actual_len = Write (print_file, buffer, length); + if (actual_len == length) + error = 0; + else error = 1; + +/* SIOStdReq.io_Data = (APTR) buffer; + SIOStdReq.io_Length = length; + + SIOStdReq.io_Command = CMD_WRITE; + DoIO (&SIOStdReq); + error = (SIOStdReq.io_Error); +*/ + CurrentTime (&seconds2, µs2); + + if (!error) /* says no error, but is it lying? */ + { + if ((seconds2 - seconds1) >= (30 - 1)) + error = 99; + } + + return (error); /* error code, zero if OK */ +} + +/*------------------------------*/ +/* script_init */ +/*------------------------------*/ + +/* + Two approaches to printing were tried; neither returns errors. The hairy + one crashes (CloseDevice) when multi-tasked, so use the simple one. +*/ + +LONG +script_init (open) /* initialize/uninitialize the printer */ + +WORD open; +{ + LONG error; + + if (open) + { + print_file = Open ("PRT:", MODE_OLDFILE); + + if (print_file) /* zero means error */ + error = 0; + else error = 1; + +/** OpenDevice ("printer.device", 0, &SIOStdReq, 0); + + /-* set up the message port in the I/O request *-/ + + SMsgPort.mp_Node.ln_Type = NT_MSGPORT; + SMsgPort.mp_Flags = 0; + SMsgPort.mp_SigBit = AllocSignal (-1); + SMsgPort.mp_SigTask = (struct Task *) FindTask (NULL); + + AddPort (&SMsgPort); + SIOStdReq.io_Message.mn_ReplyPort = &SMsgPort; +**/ } + + else + { + if (print_file) /* call only if once opened */ + Close (print_file); + + error = 0; /* no close errors? */ + + /* clean up the various structures we created */ + +/** RemPort (&SMsgPort); + FreeSignal (SMsgPort.mp_SigBit); + + CloseDevice (&SIOStdReq); +**/ } + + return (error); /* zero if none */ +} + +/*------------------------------*/ +/* script_open */ +/*------------------------------*/ + +WORD +script_open (start) /* kernel issued request to start/stop scripting, + return status, either active or inactive */ +WORD start; +{ + CHAR reset_seq[2]; + LONG error; + +/* starting, may need to open/reset the printer */ + + if (start) + { + if (!prt_inited) /* device never opened, do so now */ + { + error = script_init (TRUE); + + if (!error) + prt_inited = TRUE; /* okay, opened */ + } + + if (prt_inited && !prt_active) /* new start, reset printer */ + { + + reset_seq[0] = '\33'; /* ESC ($1B) */ + reset_seq[1] = 'c'; /* 'c' means reset */ + + error = raw_script (&reset_seq, 2); + + if (!error) + prt_active = TRUE; /* okay, active */ + } + } + + else /* if stop, flag it and shut down */ + { + prt_active = FALSE; + + if (prt_inited) + { + script_init (FALSE); prt_inited = FALSE; + } + } + + return (prt_active); +} + +/*------------------------------*/ +/* script_line */ +/*------------------------------*/ + +WORD +script_line (buffer, length) /* script a line, tack on an EOL, + return error code (zero if none) */ +LONG buffer, length; +{ + CHAR eol_seq[2]; + WORD error; + + if (length > 0) + error = raw_script (buffer, length); + else error = 0; + +/* The EOL seq used to be an "ISO standard" Esc-E (1B45), but under + AmigaDOS 1.2 this seems to have no effect. Changing to CRLF (0D0A) + works under both 1.1 and 1.2 except that the spacing is too wide + (resembles triple, used to resemble double). It appears that AmigaDOS + (/not/ the printer) automatically makes the initial CR a CRLF. So, + we will output only the CR and hope all printers are happy. + + By the way, a way to check script spacing is to compare it to what + AmigaDOS does after typing "TYPE textfile TO PRT:". Also, some + printer behavior can be controlled from User Preferences, like + margins and 6- or 8-line spacing. +*/ + if (!error) + { + eol_seq[0] = 0x0D; +/** eol_seq[1] = 0x0A; **/ + + error = raw_script (&eol_seq, 1); + } + return (error); +} + diff --git a/amiga/yzip3.c b/amiga/yzip3.c new file mode 100644 index 0000000..71adaff --- /dev/null +++ b/amiga/yzip3.c @@ -0,0 +1,1048 @@ + +#define TOPAZ8_BASE 6 /* 80-col font baseline */ + +/************************************************************************/ +/* Low Level Console Device I/O */ +/************************************************************************/ + +#if DEADCODE + +/*------------------------------*/ +/* write_console */ +/*------------------------------*/ +VOID +write_console (str, len) /* send raw string to console device */ + +CHAR *str; +WORD len; +{ + /** DEAD **/ +} + +/*------------------------------*/ +/* queue_read */ +/*------------------------------*/ + +VOID +queue_read () +{ + /** DEAD **/ +} + +/*------------------------------*/ +/* read_console */ +/*------------------------------*/ + +VOID /*CHAR*/ +read_console () /* get a char from console device */ +{ + /** DEAD **/ +} + +/*------------------------------*/ +/* send_control_seq */ +/*------------------------------*/ + +#define begin_mark 0x009B /* one unsigned byte, was '\233' */ + +VOID +send_control_seq (str) /* write it, prefixed with control char */ +CHAR *str; +{ + /** DEAD **/ +} + +/*------------------------------*/ +/* get_control_seq */ /* read chars into buffer */ +/*------------------------------*/ + +VOID +get_control_seq (buffer, end_mark) +UCHAR *buffer; +UCHAR end_mark; +{ + /** DEAD **/ +} + +/*------------------------------*/ +/* stash_put */ +/*------------------------------*/ + +/** +#define STASH_SIZE 64 /-* max size *-/ + +CHAR stash[STASH_SIZE]; /-* typeahead saved here *-/ +WORD stash_len = 0; **/ + +/* The next two calls are used to maintain a typeahead buffer, saving +keys that would otherwise be thrown away. This situation occurs only +because of the awful way the cursor position is read -- a special escape +sequence is sent to the console device and the position is reported +back via the input stream, mixed with any typeahead. */ + +stash_put (c) /* DEAD -- not needed */ +CHAR c; +{ +/** if (stash_len < STASH_SIZE) { + stash[stash_len] = c; + stash_len++; + } **/ +} + +/*------------------------------*/ +/* stash_get */ +/*------------------------------*/ + +CHAR stash_get () /* return a char, or NULL if none */ +{ +/** CHAR c = 0; + WORD i; + + if (stash_len) { /-* any saved typeahead? *-/ + c = stash[0]; /-* yes, return it FIFO *-/ + stash_len--; + for (i=0; i last_col) end_col = last_col; + } + +/* YZIP note: could use RectFill here, but its modes are confusing, as well + as its attempt to draw boundary lines (!) (Mortimer p279). A simple + hack for erasing to the background color is to just scroll the offending + bits into oblivion. */ + + ZScrlRast (0, y_char, /* dx, dy */ + start_col, cur_row, /* xmin, ymin */ + end_col-1, cur_row + y_char-1); /* xmax, ymax */ + +/** Move (ZRastPort, x_align, y_align); + ClearEOL (ZRastPort); **/ + +/** send_control_seq ("K"); **/ /* clear to EOL */ +} + +/*------------------------------*/ +/* clear_window */ +/*------------------------------*/ +VOID +clear_window (arg) /* was clear_lines */ +WORD arg; +{ + WORD top, left, bot, right; + + if (arg == -1) { /* clear entire screen */ + top = 0; left = 0; + bot = tot_rows; right = tot_cols; + } + else { + top = first_row; left = first_col; + bot = last_row; right = last_col; + } + +/* As before, we accomplish the RectFill with a scroll. */ + + ZScrlRast (0, bot-top, /* dx, dy */ + left, top, /* xmin, ymin */ + right-1, bot-1); /* xmax, ymax */ +} + +/*------------------------------*/ +/* line_out */ +/*------------------------------*/ + +VOID +line_out (str, len) /* draw a string at current position, */ + /* first check length and clip if required */ +CHAR *str; +WORD len; /* (in chars) */ +{ + WORD x_align, y_align; + WORD pix_len, clip_len; +/** CHAR old_endmark; **/ + + clip_len = (last_col /*columns*/ - cur_col) / x_char; + if (len > clip_len) + len = clip_len; + pix_len = len * x_char; + +/** old_endmark = str[len]; + str[len] = 0; **/ /* make it asciz */ + + x_align = cur_col /* * x_char */; + y_align = (cur_row /* *y_char*/) + TOPAZ8_BASE; /* allow for baseline */ + +/* for YZIP, hack the vertical pos */ + + Move (ZRastPort, x_align, y_align - Peek1); + Text (ZRastPort, str, len); + + cur_col += pix_len; +/** str[len] = old_endmark; **/ +} + +/*------------------------------*/ +/* char_out */ +/*------------------------------*/ + +VOID +char_out (c) /* if CR or BS, special case, else draw the char */ +CHAR c; +{ + CHAR temp[2]; /* even-aligned */ + + if (c == 13) + { + cur_col = first_col + marg_left; + cur_row += y_char; + if (last_row - cur_row >= y_char) + return; /* not yet at bottom */ + else { + cur_row -= y_char; + amiga_scroll (y_char); + } + } + + else if (c == 8) + { + BS_cursor(); + char_out (32); + BS_cursor(); + } + else /* normal char, draw it */ + { + if (cur_col >= last_col /*columns*/) /* first goto next line */ + char_out (13); + temp[0] = c; + line_out (&temp, 1); + } +} + +/*------------------------------*/ +/* BS_cursor */ +/*------------------------------*/ +VOID +BS_cursor () +{ + if (cur_col >= first_col + marg_left + x_char) + cur_col -= x_char; /* normal BS */ + else if (cur_row >= first_row + y_char ) { + +/* YZIP: need a static global for backups across lines ... */ + cur_col = (last_col /*columns*/ - marg_right) - x_char; + cur_row -= y_char; /* backup a line */ + } +} + +/************************************************************************/ +/* Input handling */ +/************************************************************************/ + +/* Maintain a blinking cursor. This routine is called from setup_input() + and from intuitick(), every 1/10 sec while we await input */ + +#define ONTICK 0 +#define OFFTICK 7 /* duty cycle is 70% */ +#define MAXTICK 10 /* ... of one second */ + +/*------------------------------*/ +/* blink_cursor */ +/*------------------------------*/ + +VOID blink_cursor (arg) /* 1= starting, -1= ending, 0= waiting */ +WORD arg; +{ + static WORD ticks; + static BOOL curs_on = FALSE; /* initially off */ + int old_hl; /* save current here */ +/** static BOOL blinky = FALSE; **/ /* Amiga (CLI) default is NO blink */ + + if (!curs_vis) + return; /* cursor suppressed, avoid displaying */ + + switch (arg) { + case 1: + ticks = ONTICK; + break; + case -1: + ticks = OFFTICK; + break; +/** case 0: /-* not handled *-/ + if (blinky) { /-* should make this a global option *-/ + ticks++; + if (ticks >= MAXTICK) /-* wrap around *-/ + ticks = ONTICK; + } + break; **/ + } + +/* Since our cursor is currently always non-blinking, for now we'll call + hack_wsize() from setup_input() only, to make things simpler. */ + + if ((ticks == ONTICK) && !curs_on) { /* show cursor */ + /** hack_wsize (0); **/ /* normalize for output! */ + old_hl = highlight (-1); + highlight (1); /* inverse vid */ + char_out (32); + + highlight (old_hl); + /** hack_wsize (1); **/ + curs_on = TRUE; + } + if ((ticks == OFFTICK) && curs_on) { /* erase cursor */ + /** hack_wsize (0); **/ /* normalize for output! */ + char_out (8); + /** hack_wsize (1); **/ + curs_on = FALSE; + } +} + +/*------------------------------*/ +/* setup_input */ +/*------------------------------*/ + +VOID setup_input (start, single) /* show/hide cursor */ +BOOL start, single; /* if single, don't allow "menu strings" */ +{ + if (start) { + unhide_screen (); /* just in case ... */ + blink_cursor (1); /* for now, OUTSIDE hack_wsize() */ + hack_wsize (1); + } + else { + hack_wsize (0); + blink_cursor (-1); + } +} + +/*------------------------------*/ +/* hack_wsize */ +/*------------------------------*/ + +/* To allow YZIP to use the entire screen (i.e. draw into the titlebar area) + and at the same time to allow the titlebar gadgets to work in the usual + way, this routine hacks the window's vertical size to include/exclude + the titlebar (or a portion thereof). + + This routine is called from setup_input(); could be temporarily undone + from blink_cursor() if necessary. We hope it causes no strange + side effects. + + The altered state currently exists /only/ during input. This can cause + problems when running a debugger. It may also be seen by users as + having slightly strange responsiveness. IDEA: could call from output + bottlenecks instead, but would cut more into performance. + + Ideally, we'd like to do a one-time hack to some piece of the + window/rastport/layer structure to effect this behavior. Possible? +*/ + +hack_wsize (start_input) +BOOL start_input; +{ + int y_htb; + struct Layer *lp; + + if (start_input) + y_htb = HIDDEN_TBAR_HEIGHT; + else y_htb = -HIDDEN_TBAR_HEIGHT; + +/* could replace all of the following with MoveWindow/SizeWindow, EXCEPT + that those calls don't take effect immediately! */ + + ZWindow->TopEdge += y_htb; + ZWindow->Height -= y_htb; + + ZWindow->MinHeight -= y_htb; /* do these for good measure */ + ZWindow->MaxHeight -= y_htb; + ZWindow->GZZHeight -= y_htb; + +/* apparently we must also hack some layer stuff too. Careful ... */ + + if (lp = ZWindow->RPort->Layer) + { + lp->bounds.MinY += y_htb; /* (top edge) */ + lp->ClipRect->bounds.MinY += y_htb; + + /* other ClipRect ptrs? ClipRegion? */ + } +} + +/*------------------------------*/ +/* german_convert */ +/*------------------------------*/ + +/* Convert a German extension char from/to its native Amiga code to/from + the common XZIP code. If the given char is not in the German set, + return NULL. */ + +UBYTE german_convert (c, from_native) +UBYTE c; +BOOL from_native; /* true for input, false for output */ +{ + register UBYTE *p, *p2; + UBYTE c2 = 0; + + static UBYTE gtab[] = /* German conversion table for the Amiga */ + { + 0xE4, 155, /* ae (umlaute a) */ + 0xF6, 156, /* oe (umlaute o) */ + 0xFC, 157, /* ue (umlaute u) */ + 0xC4, 158, /* AE */ + 0xD6, 159, /* OE */ + 0xDC, 160, /* UE */ + 0xDF, 161, /* ss */ + 0xBB, 162, /* >> (left quote) */ + 0xAB, 163, /* << (right quote) */ + 0, 0 }; /* zero marks end of table */ + + if (from_native) { + p = >ab[0]; p2 = >ab[1]; + } + else { + p2 = >ab[0]; p = >ab[1]; + } + + while (*p != 0) { + if (*p == c) { /* found it? */ + c2 = *p2; /* yes, return corresponding value */ + break; + } + p += 2; + p2 += 2; + } + return (c2); +} + +/*------------------------------*/ +/* map_fkey */ +/*------------------------------*/ + +/* map an FKey to its XZIP value. Return NULL if not found. */ + +UBYTE map_fkey (raw) +UBYTE raw; +{ + register UBYTE *p; + UBYTE c = 0; + +/* FKey translation table for the Amiga. The values on the left are raw + keycodes which (for the following groups of keys) I believe are invariant + across the various international Amiga keyboards. */ + + static UBYTE keytab[] = + { + 0x4C, 129, /* up arrow */ + 0x4D, 130, /* down arrow */ + 0x4F, 131, /* left arrow */ + 0x4E, 132, /* right arrow */ + 0x50, 133, /* F1 */ + 0x51, 134, /* F2 */ + 0x52, 135, /* F3 */ + 0x53, 136, /* F4 */ + 0x54, 137, /* F5 */ + 0x55, 138, /* F6 */ + 0x56, 139, /* F7 */ + 0x57, 140, /* F8 */ + 0x58, 141, /* F9 */ + 0x59, 142, /* F10 */ + /* no F11, F12 */ + 0, 0 }; /* zero marks end of table */ + + p = keytab; + + while (*p != 0) { + if (*p++ == raw) { /* found it? */ + c = *p; /* yes, pick up XZIP value */ + break; + } + p++; + } + return (c); +} + +/*------------------------------*/ +/* raw_key */ +/*------------------------------*/ + +/* Use the system KeyMap to convert a raw keycode to the correct ascii + value (or for certain keys, a console-device-style escape sequence). + (see Enhancer1.2 booklet p66). Then adjust as required any value that + should fall into the extended (128+) XZIP character set. */ + +#define KBLEN 32 /* (known max is 4) */ + +UBYTE raw_key (msg) +struct IntuiMessage *msg; +{ + UBYTE keycode, c, kbuffer[KBLEN]; + static struct InputEvent iev = {NULL, IECLASS_RAWKEY, 0,0,0}; + int len; + +/* copy input event info */ + + keycode = msg->Code; + iev.ie_Code = keycode; + iev.ie_Qualifier = msg->Qualifier; + +/* To support deadkeys (1.2 only), get previous codes from location + pointed to by IAddress. (This pointer not valid after IntuiMessage + is replied ?) */ + + iev.ie_position.ie_addr = *((APTR *) msg->IAddress); + +/* convert key to ascii (must have previously opened console device) */ + + len = RawKeyConvert (&iev, &kbuffer, KBLEN, NULL); + +/* translate special keys ... */ + + if (len <= 0) return (0); /* key-up event, deadkey, etc */ + + if (len > 1) { /* FKey, cursor key, (Help) */ + c = map_fkey (keycode); + return (c); + } + + c = kbuffer[0]; /* length is 1 exactly */ + +/* Check if c is a number; if so, THEN check if it came from the keypad + (some international keyboards assign special chars to shifted keypads) */ + + if ((c >= '0') && (c <= '9')) + if (keycode >= 0x0F) { /* keypad '0' */ + c += 145 - '0'; + return (c); + } + +/* Check if c is a "post-deadkey" (or an actual international key) */ + + if (c >= 128) { + c = german_convert (c, TRUE); /* 0 if not */ +/** return (c); **/ + } + + return (c); +} + +/*------------------------------*/ +/* mouse_buttons */ +/*------------------------------*/ + +/* this routine monitors only the mouse "selection" button (the left one) */ + +UBYTE mouse_buttons (im) +struct IntuiMessage *im; +{ + UBYTE retval = 0; /* default val */ + ULONG cursecs, curmics; +static ULONG oldsecs = 0, oldmics = 0; + + switch (im->Code) { + + case SELECTDOWN: /* button just pressed */ + xmouse = (im->MouseX /* /x_char */) + 1; + ymouse = (im->MouseY /* /y_char */) + 1 + /* since we're doing input, must include this fudge factor */ + + HIDDEN_TBAR_HEIGHT; + + cursecs = im->Seconds; + curmics = im->Micros; + + /* use a system call to check if it's a double */ + + if (DoubleClick (oldsecs, oldmics, cursecs, curmics)) { + oldsecs = 0; oldmics = 0; + retval = 253; /* double click */ + } + else { + oldsecs = cursecs; oldmics = curmics; + retval = 254; /* single click */ + } + break; + +/** case SELECTUP: /-* button just released *-/ + retval = 0; + break; **/ + } + return (retval); +} + +/*------------------------------*/ +/* intuiticks */ +/*------------------------------*/ + +/* this routine called every 1/10 sec (approx) */ + +UBYTE intuiticks (im) +struct IntuiMessage *im; +{ + blink_cursor (0); /* maintain the cursor */ + return (255); /* return a special code (for timeouts) */ +} + +/*------------------------------*/ +/* event_multi */ +/*------------------------------*/ + +/* Note: returns 0 for a null event, 255 for a timer event */ + +UBYTE event_multi () /* wait for an input event */ +{ + struct IntuiMessage *msg, localmsg; + int i; + UBYTE *s, *d, val; + +/* must be sure that a task's port is empty before the task can be put + to sleep (Peck p202) */ + + msg = (struct IntuiMessage *) GetMsg (ZWindow->UserPort); + if (msg == NULL) { + WaitPort (ZWindow->UserPort); /* sleep */ + msg = (struct IntuiMessage *) GetMsg (ZWindow->UserPort); + } + +/* copy the contents of the message to our own area, so we can reply it + as quickly as possible (Peck p155) */ + + s = (UBYTE *) msg; + d = (UBYTE *) &localmsg; + for (i=0; iClass != RAWKEY) { + ReplyMsg (msg); /* return block to system */ + msg = NULL; + } + + switch (localmsg.Class) { + + case RAWKEY: + val = raw_key (&localmsg); + break; + case MOUSEBUTTONS: + val = mouse_buttons (&localmsg); + break; + case INTUITICKS: + val = intuiticks (&localmsg); + break; + case DISKINSERTED: + /* val = disk_inserted (&localmsg); */ + fsel_diskevent (); /* keep FileIO happy */ + val = 0; + break; + +/** case SIZEVERIFY: /-* unused cases *-/ + val = size_verify (&localmsg); + break; + case NEWSIZE: + val = new_size (&localmsg); + break; + case REFRESHWINDOW: + val = refresh_window (&localmsg); + break; + case MOUSEMOVE: + val = mouse_move (&localmsg); + break; + case GADGETDOWN: + val = gadget_down (&localmsg); + break; + case GADGETUP: + val = gadget_up (&localmsg); + break; + case REQSET: + val = req_set (&localmsg); + break; + case MENUPICK: + val = menu_pick (&localmsg); + break; + case CLOSEWINDOW: + val = close_window (&localmsg); + break; + case REQVERIFY: + val = req_verify (&localmsg); + break; + case REQCLEAR: + val = req_clear (&localmsg); + break; + case MENUVERIFY: + val = menu_verify (&localmsg); + break; + case NEWPREFS: + val = new_prefs (&localmsg); + break; + case DISKREMOVED: + val = disk_removed (&localmsg); + break; + case WBENCHMESSAGE: + val = wbench_message (&localmsg); + break; + case ACTIVEWINDOW: + val = active_window (&localmsg); + break; + case INACTIVEWINDOW: + val = inactive_window (&localmsg); + break; + case DELTAMOVE: + val = delta_move (&localmsg); + break; + case VANILLAKEY: + val = vanilla_key (&localmsg); + break; +**/ /* end of unused cases */ + default: + val = 0; + break; + } + + if (msg) ReplyMsg (msg); /* reply now, if not done earlier */ + + return (val); +} + +/*------------------------------*/ +/* event_in */ +/*------------------------------*/ + +UBYTE event_in () /* wait for keyboard (or mouse) input */ +{ + UBYTE c = 0; + +/*** c = stash_get(); /-* any saved typeahead? *-/ + if (!c) + c = read_console (); /-* no, get a live key *-/ +***/ + while (c == 0) /* return only when something happens */ + c = event_multi (); + + if (c == 255) c = 0; /* timer event, return as NULL */ + return (c); +} + +/*------------------------------*/ +/* int_key */ +/*------------------------------*/ + +/* Should this run as a machine interrupt or a game pseudo-interrupt? + Some ops ($VERIFY) take a long time. */ + +int_key() +{ +/* On the Amiga, if event messages (i.e. typed-ahead keys) aren't replied + quickly by the application and are allowed to accumulate, the OS + allocates extra buffers which /never/ get released (Peck p155). + + This can cause nasty fragmentation of free memory and break OPSOUND + (since it dynamically allocates and releases large blocks). + + One fix: reply every message immediately, and store type-ahead in our + own small queue. Should also properly decode FKey and mouse events. + + (If /currently/ awaiting input, just exit) */ +} + +/************************************************************************/ +/* More Output Routines */ +/************************************************************************/ + +/*------------------------------*/ +/* highlight */ +/*------------------------------*/ + +int +highlight (mode) /* if mode = -1, just return current mode */ +WORD mode; +{ +static WORD old_mode = 0; /* (in kernel format) */ +static WORD sd_old = 0; /* initial SetDrMode */ +static WORD ss_old = FS_NORMAL; /* initial SetSoftStyle */ + + WORD sd_mode = 0; + WORD ss_mode = FS_NORMAL; + + if (mode == -1) return (old_mode); + else old_mode = mode; /* remember it */ + + switch (mode) + { + case 0: /* normal text, no effects */ + break; + case 1: /* inverse video */ + sd_mode = INVERSVID; + break; + case 2: /* bold */ + ss_mode = FSF_BOLD; + break; + case 4: /* underlined (italic) */ + ss_mode = FSF_UNDERLINED; + /** ss_mode = FSF_ITALIC; **/ /* causes spacing problem) */ + break; + } + + if (sd_mode != sd_old) { + SetDrMd (ZRastPort, JAM2 + sd_mode); + sd_old = sd_mode; /* remember current */ + } + + if (ss_mode != ss_old) { + SetSoftStyle (ZRastPort, ss_mode, 0xFF); /* only 1 at a time */ + ss_old = ss_mode; + } +} + +/*------------------------------*/ +/* zfont */ +/*------------------------------*/ + +#define ZSYSFONT 1 +#define ZALTFONT 3 + +int +zfont (new_font) /* if -1, just return current font */ +WORD new_font; +{ +static WORD old_font = ZSYSFONT; /* (initially, topaz 80) */ +struct TextFont *tf; + + if (new_font == -1) return (old_font); + + if (new_font != old_font) { + + if (new_font == ZALTFONT) tf = altfont; + else tf = sysfont; + + if (tf) SetFont (ZRastPort, tf); + old_font = new_font; /* remember it */ + } +} + +/*------------------------------*/ +/* set_color */ +/*------------------------------*/ + +/* Under YZIP, the various fore/back text colors are now supported using + only the first two "pens" (all other pens are used for graphics). + Therefore, the 2 text colors are now "global", meaning they /can't/ be + changed for a single word on the screen, or for a certain window. + + As a hack to support the above, for YZIP we now get a current-window arg. + We allow text colors to be changed only in window 0, and ignore + requests in other windows (except for the special case of bg = -1), + since it only succeeds in making the screen flash. */ + +WORD set_color (fore, back, curwind) /* return system defaults */ +WORD fore, back, curwind; +{ + /* ignore if display doesn't support colors */ + if (tty_color) { + if (curwind == 0) { + set_back (back); /* first; may have side effect! */ + set_fore (fore); + } + else if (back == -1) /* special case */ + set_back (back); + } + + return ((DEF_BACK << 8) | DEF_FORE); +} + +/*------------------------------*/ +/* set_fore */ +/*------------------------------*/ + +static WORD of_id = 0; /*DEF_FORE*/ +static WORD ob_id = 0; /*DEF_BACK*/ /* (might NOT init be YZIP default) */ + +set_fore (id) +register WORD id; +{ + register WORD pen, foreRGB; + int seq[4]; + + if (id == 1) + id = DEF_FORE; /* use default */ + + if (id != of_id) /* changed? */ + if (id >= BASE_ID && id <= LAST_ID) { + of_id = id; /* remember new one */ + pen = colormap[id]; /* convert XZIP id to pen # */ + + /* For YZIP, this routine now changes Color Register #1 (as opposed + to Pen A, which can be set to any register, but is now always + implicitly set to register 1). + Might now make sense to get rid of colorMap (?). */ + + foreRGB = colortable[pen]; + unpack_RGB (foreRGB, &seq); + SetRGB4 (&(ZScreen->ViewPort), 1, seq[1], seq[2], seq[3]); + + /** SetAPen (ZRastPort, 1); **/ /* (once, in init) */ + } +} + +/*------------------------------*/ +/* set_back */ +/*------------------------------*/ + +/* Note: In general, we want the edges of a screen to be the same color as + our background (otherwise it looks bad). Since the edges are apparently + always rendered using pen 0 (changable?), we will always use that pen + for our background (as opposed to "BPen"), and change its RGB definition + as required. + + Consequently, like on the ST, there can be only one "primary" + background color at a time (although "secondary" backgrounds would be + easy enough to support if XZIP recognized the concept). */ + +set_back (id) +register WORD id; +{ + register WORD pen, backRGB; + int seq[4]; + + if (id == 1) + id = DEF_BACK; + + if (id >= BASE_ID && id <= LAST_ID) { + + if (id == ob_id) /* same, done */ + return (0); + ob_id = id; /* remember new one */ + + pen = colormap[id]; /* convert XZIP id to pen # */ + backRGB = colortable[pen]; + + unpack_RGB (backRGB, &seq); + SetRGB4 (&(ZScreen->ViewPort), 0, seq[1], seq[2], seq[3]); + + SetBPen (ZRastPort, 0); + } + + if (id == -1) { /* "set to current screen bg" */ + pen = ReadPixel (ZRastPort, + cur_col, cur_row /* +Peek1? */ ); + + /* "secondary background" -- Use one of 14 gfx colors, not 2 + text colors. Set the background /pen/ to match the desired pen, + so that these background bits will remain undisturbed on screen + after primary background (pen 0) changes to something else. */ + + SetBPen (ZRastPort, pen); + + /** backRGB = GetRGB4 (ZScreen->ViewPort.ColorMap, pen); + if (backRGB == -1) + return (-1); /-* error *-/ + unpack_RGB (backRGB, &seq); + SetRGB4 (&(ZScreen->ViewPort), 0, seq[1], seq[2], seq[3]); + **/ + + ob_id = -1; /* invalidate it */ + } +} + +unpack_RGB (val, p) /* unpack 4 nybbles into array at p */ +register int val, *p; +{ + register int i; + + for (i=3; i>=0; i--) { + p[i] = val & 0x000F; /* rightmost nybble */ + val >>= 4; + } +} diff --git a/amiga/zip.asm b/amiga/zip.asm new file mode 100644 index 0000000..e106fdc --- /dev/null +++ b/amiga/zip.asm @@ -0,0 +1,17 @@ + + TTL COMMODORE AMIGA Z-LANGUAGE INTERPRETER + +* --------------------------------------------------------------------------- +* ASSEMBLY FLAGS +* --------------------------------------------------------------------------- + +EZIP EQU 0 * ASSEMBLES EZIP CODE WHEN CLEAR +CZIP EQU -1 * ASSEMBLES CLASSIC ZIP CODE WHEN CLEAR +DEBUG EQU -1 * ASSEMBLES DEBUGGING CODE WHEN CLEAR + + INCLUDE "ZIP1.ASM" * + INCLUDE "ZIP2.ASM" * "OPADD ..." + INCLUDE "ZIP3.ASM" * "ZIP MAIN ..." + INCLUDE "ZIP4.ASM" * "MACHINE-DEP ..." + + END diff --git a/amiga/zip1.asm b/amiga/zip1.asm new file mode 100644 index 0000000..e19bb9a --- /dev/null +++ b/amiga/zip1.asm @@ -0,0 +1,1049 @@ + + SECTION ZCODE,CODE * DEFINE TWO SEGMENTS + NOP + SECTION ZDATA,DATA + DC.W 0 + SECTION ZCODE * AND START IN CODE SEGMENT + +* ___________________________________________________________________________ +* +* Z-LANGUAGE INTERPRETER FOR COMMODORE AMIGA +* +* INFOCOM, INC. COMPANY CONFIDENTIAL -- NOT FOR DISTRIBUTION +* ___________________________________________________________________________ +* + +* WRITTEN BY: Duncan Blanchard +* +* MODIFICATION HISTORY: +* +* 18 OCT 85 ZIP A FROZEN +* 29 OCT 85 FILE_SELECT LIMITS SAVE NAME TO 25 CHARS +* 29 OCT 85 SCRERR DISPLAYS A PRINTER ERROR MESSAGE UPON FAILURE +* ZIP B FROZEN +* EZIP A FROZEN +* 10 FEB 86 CHANGED PUT, PUTB, PTSIZE (PURE PRELOAD > 32K) +* 10 APR 86 CHANGED PUTCHR (SPECIAL HANDLING FOR TABLE OUTPUT) + +* 07 MAY 86 CHANGED NXTLIN/BUFOUT/LINOUT. BUFOUT CALLS NXTLIN +* SO [MORE] IS TIMED CORRECTLY DURING BOLDFACE, ETC +* CHANGED OPREAD, ONLY OVERFLOW WORDS ARE FLUSHED +* 08 MAY 86 FIXED QUECHR (QCX2A), ALLOW FOR EMPTY [DUMPED] BUFFER +* EZIP B FROZEN +* 01 JUL 87 EXPANDED OPSOUND +* 22 JUL 87 ADDED UNHIDE [SCREEN] TO RDLINE, FOR ALERTBOX BUG +* SCRIPTING FIX, ETC, IN AMIGAZIP +* EZIP C FROZEN +* 26 AUG 87 ADDED VOLUME ARG TO OPSOUND +* ZIP C FROZEN + +* --------------------------------------------------------------------------- +* REGISTER CONVENTIONS +* --------------------------------------------------------------------------- + +* GENERALLY, SINGLE ARGUMENTS ARE PASSED IN D0 OR A0. SINGLE VALUES ARE +* LIKEWISE RETURNED IN D0 OR A0. IN ANY CASE, THESE ARE SCRATCH REGISTERS +* AND NEED NOT BE PRESERVED. ALL OTHER REGISTERS, EXCEPT WHERE OTHERWISE +* SPECIFIED, MUST BE PRESERVED ACROSS EACH SUBROUTINE CALL. NOTE THAT +* TOP-LEVEL ROUTINES, OPx ROUTINES, ARE EXCLUDED FROM THIS RESTRICTION. + +* DEDICATED REGISTERS: +* A7 = SYSTEM SP +* A6 = FRAME POINTER FOR ZIP VARIABLES *** STATIC *** +* A5 = unused in this version +* A4 = VIRTUAL SP + +* --------------------------------------------------------------------------- +* GENERAL MACRO DEFINITIONS +* --------------------------------------------------------------------------- + +* MACRO ZERO +* MOVEQ #0,%1 * CLEAR A REGISTER QUICKLY (BOTH WORDS) +* ENDM + +* MACRO SOB * SUBTRACT ONE AND BRANCH IF NOT ZERO +* SUBQ.W #1,%1 +* BNE %2 +* ENDM + +* --------------------------------------------------------------------------- +* GENERAL EQUATES +* --------------------------------------------------------------------------- + +ARG1 EQU 2 * ARGUMENT OFFSETS IN ARGBLOCK (COUNT IS AT 0) +ARG2 EQU 4 +ARG3 EQU 6 +ARG4 EQU 8 + + IFEQ EZIP + +VCHARS EQU 9 * MAX CHARS IN AN EZIP VOCAB WORD + +OPLEN EQU 63*2 * OBJECT PROPERTY DEFAULT TABLE LENGTH +OLEN EQU 14 * OBJECT LENGTH + +LOC EQU 6 * PARENT +NEXT EQU 8 * NEXT SIBLING +FIRST EQU 10 * FIRST CHILD +PROP EQU 12 * PROPERTY TABLE POINTER + +PMASK EQU $003F * PROPERTY NUMBER IS LOW 6 BITS (OF FIRST ID BYTE) +PLBIT EQU 6 * PROPERTY LENGTH BIT (IF LENGTH IS TWO OR ONE) + + ENDC + IFEQ CZIP + +VCHARS EQU 6 * MAX CHARS IN A ZIP VOCAB WORD + +OPLEN EQU 31*2 * OBJECT PROPERTY DEFAULT TABLE LENGTH +OLEN EQU 9 * OBJECT LENGTH + +LOC EQU 4 * PARENT +NEXT EQU 5 * NEXT SIBLING +FIRST EQU 6 * FIRST CHILD +PROP EQU 7 * PROPERTY TABLE POINTER + +PMASK EQU $001F * PROPERTY NUMBER IS LOW 5 BITS (OF SINGLE ID BYTE) +PLBIT EQU 5 * PROPERTY LENGTH BIT (LOWEST OF 3 LENGTH BITS) + + ENDC + +* --------------------------------------------------------------------------- +* EXTERNALS +* --------------------------------------------------------------------------- + +* EXTERNALLY DEFINED VARIABLES + + XREF _columns * TOTAL COLUMNS IN DISPLAY + XREF _cur_column * 0 .. COLUMNS -1 + + XREF _rows * TOTAL ROWS IN DISPLAY + XREF _cur_row * 0 .. ROWS -1 + XREF _split_row * FIRST ROW IN SCROLLING WINDOW + + XREF _savename + XREF _saveback + +** XREF _ms_tick +** XREF _ms_total +** XREF _otim_addr + + XREF _temp_channel + XREF _temp_memory + +* EXTERNALLY DEFINED ROUTINES + + XREF _line_out * VOID line_out (STRPTR, LEN) + XREF _char_out * VOID char_out (CHAR) + XREF _char_in * CHAR char_in () + + XREF _show_status * VOID show_status (str1, len1, str2, len2) + XREF _show_more + XREF _highlight + + XREF _clear_screen + XREF _clear_lines + XREF _clear_eol + +* CALL THESE ROUTINES WHENEVER THE KERNEL ACCESSES THE CURRENT ROW/COLUMN +* (ENSURES CO-ORDINATION WITH THE CONSOLE DEVICE CURSOR FUNCTIONS) + + XREF _read_cursor_pos + XREF _write_cursor_pos + + XREF _exist_file + XREF _create_file + XREF _open_file + XREF _close_file + XREF _delete_file + + XREF _read_file + XREF _write_file + + XREF _open_game * LONG open_game () + XREF _close_game * LONG close_game (refnum) + +*** XREF _file_select * MOVED INTO 68K FOR NOW + XREF _new_default + XREF _drive_default + XREF _make_icon_file + + XREF _c_getmem + XREF _c_maxmem + + XREF _script_open + XREF _script_line + + XREF _random_seed + XREF _window_resized + XREF _md_sound + XREF _unhide_screen + +* EXTERNALLY REFERENCED ROUTINES + + XDEF _START + + XDEF _trap1 + XDEF _trap2 + XDEF _trap13 + XDEF _trap14 + + +* --------------------------------------------------------------------------- +* ZIP VARIABLES - INDEXED OFF A6 +* --------------------------------------------------------------------------- + +ZORKID EQU 0-2 * UNIQUE GAME AND VERSION ID +TIMEMD EQU ZORKID-2 * HOURS/MINUTES MODE FLAG +ENDLOD EQU TIMEMD-2 * END OF PRELOAD (FIRST PAGED BLOCK NUMBER) +PURBOT EQU ENDLOD-2 * END OF IMPURE (FIRST PURE BLOCK NUMBER) + +VOCTAB EQU PURBOT-4 * VOCABULARY TABLE POINTER +OBJTAB EQU VOCTAB-4 * OBJECT TABLE POINTER +GLOTAB EQU OBJTAB-4 * GLOBAL TABLE POINTER +WRDTAB EQU GLOTAB-4 * FREQUENT WORD TABLE POINTER + +RBRKS EQU WRDTAB-4 * POINTER TO STRING OF READ-BREAK CHARS +ESIBKS EQU RBRKS-4 * END OF SELF-INSERTING BREAK CHARS (+1) + +VWLEN EQU ESIBKS-2 * NUMBER OF BYTES IN A VOCAB WORD ENTRY +VWORDS EQU VWLEN-2 * NUMBER OF VOCABULARY WORDS +VOCBEG EQU VWORDS-4 * POINTER TO FIRST VOCAB WORD +VOCEND EQU VOCBEG-4 * POINTER TO LAST VOCAB WORD + +PAGTAB EQU VOCEND-4 * POINTER TO PAGE INFORMATION TABLE +PAGES EQU PAGTAB-4 * POINTER TO START OF PAGE BUFFERS + +PAGTOT EQU PAGES-2 * NUMBER OF PAGE BUFFERS +MAXGAM EQU PAGTOT-4 * LARGEST POSS. PRELOAD (BYTES, ROUNDED UP) +MINGAM EQU MAXGAM-4 * SMALLEST POSS. PRELOAD + +TOPSP EQU MINGAM-4 * TOP OF SYSTEM STACK +STKBOT EQU TOPSP-4 * BOTTOM OF GAME STACK + +ZPC1 EQU STKBOT-2 * ZORK PC, BLOCK POINTER (RELATIVE ADDRESS) +ZPC2 EQU ZPC1-2 * ZORK PC, BYTE POINTER +ZLOCS EQU ZPC2-4 * POINTER TO LOCALS (ABSOLUTE ADDRESS) + +RSEED1 EQU ZLOCS-2 * RANDOM NUMBER SEED, HIGH WORD +RSEED2 EQU RSEED1-2 * LOW WORD +RCYCLE EQU RSEED2-2 * ZERO MEANS RANDOM, OTHERWISE SEQUENCE LIMIT +RCOUNT EQU RCYCLE-2 * CURRENT POSITION IN SEQUENCE + +BUFFER EQU RCOUNT-4 * START OF PRELOADED GAME CODE +ARGBLK EQU BUFFER-18 * 8 ARGS MAX (FOR EZIP), PLUS COUNT + +*** + +RDWSTR EQU ARGBLK-10 * ASCIZ STRING BUFFER (9 CHARS MAX FOR EZIP) +RDZSTR EQU RDWSTR-6 * ZSTR BUFFER (3 WORDS MAX FOR EZIP) + +RDBOS EQU RDZSTR-4 * BEGINNING OF INPUT STRING BUFFER +RDEOS EQU RDBOS-4 * END OF INPUT STRING BUFFER (+1) +RDRET EQU RDEOS-4 * RETURN TABLE + +RDNWDS EQU RDRET-2 * NUMBER (BYTE) OF WORDS ACTUALLY READ +RDBOW EQU RDNWDS-4 * BEGINNING OF CURRENT INPUT WORD +WRDOFF EQU RDBOW-2 * OFFSET INTO WORD TABLE FOR CURRENT SET + +* VIRTUAL I/O DEVICES + +VOCONS EQU WRDOFF-2 * SET FOR SCREEN OUTPUT +VOPRNT EQU VOCONS-2 * SET FOR SCRIPTING +VOSTAT EQU VOPRNT-2 * SET FOR STATUS LINE OUTPUT +VOTABL EQU VOSTAT-2 * SET FOR TABLE OUTPUT +VOFILE EQU VOTABL-2 * SET FOR FILE OUTPUT + +VIKEYB EQU VOFILE-2 * SET FOR KEYBOARD INPUT +VIFILE EQU VIKEYB-2 * SET FOR FILE INPUT + +VOBUFF EQU VIFILE-2 * SET IF OUTPUT TO SCREEN IS BUFFERED +VIECHO EQU VOBUFF-2 * SET IF INPUT IS ECHOED + +DQUE EQU VIECHO-4 * DISPLAY QUE PARAMETER BLOCK +SQUE EQU DQUE-4 * SCRIPT QUE PARAMETER BLOCK + +TABOUT EQU SQUE-4 * POINTS TO TABLE-OUTPUT BUFFER (EZIP) +TABPTR EQU TABOUT-4 * POINTS TO NEXT POSITION IN TABLE + +CURPAG EQU TABPTR-4 * CURRENT PAGE (WHERE ZPC IS) POINTER +CURBLK EQU CURPAG-2 * CURRENT BLOCK, USUALLY SAME AS ZPC1 +CURTAB EQU CURBLK-4 * CURRENT PAGE TABLE POINTER + +RTIME EQU CURTAB-4 * REFERENCE TIME (NOW USES 4 BYTES) +LPAGE EQU RTIME-2 * LAST REFERENCED PAGE NUMBER +LPLOC EQU LPAGE-4 * AND ITS CORE LOCATION +LPTAB EQU LPLOC-4 * AND ITS TABLE POINTER + +TIMOUT EQU LPTAB-2 * OPTIONAL TIMOUT FUNCTION (EZIP), ZERO IF NONE +TDELAY EQU TIMOUT-2 * DELAY BEFORE TIMEOUT +TFUNC EQU 0 * (((DEAD))) +TBEGIN EQU TDELAY-4 * REFERENCE TIMEBASE FOR PENDING TIMEOUT + +*** + +WIND1 EQU TBEGIN-2 * NON-ZERO IF CURRENTLY IN WINDOW 1 +OLDWX EQU WIND1-2 * X-CURSOR IN WINDOW 0 (BEFORE SPLIT) +OLDWY EQU OLDWX-2 * Y-CURSOR IN WINDOW 0 (BEFORE SPLIT) + +LINES EQU OLDWY-2 * SCREEN LINES DISPLAYED SINCE LAST INPUT +INLAST EQU LINES-2 * INPUT SETS IT, OUTPUT CLEARS IT, QUIT CHECKS +CHRTOT EQU INLAST-2 * TOTAL CHARS INPUT SO FAR DURING OPREAD + +FONT EQU CHRTOT-2 * NONZERO WHEN USING SPECIAL (MONOSPACED) FONT +MACBUF EQU FONT-4 * NEW VALUE FOR ENDBUF WHEN FONTSIZE CHANGES + +SLPTR EQU MACBUF-4 * CURRENT POSITION WITHIN STATUS LINE BUFFER +LOCPTR EQU SLPTR-4 * START OF STATUS LOCATION STRING +SCOPTR EQU LOCPTR-4 * START OF STATUS SCORE STRING + +APPARM EQU SCOPTR-4 * HANDLE TO APPLICATION PARAMETERS +SHOWVE EQU APPARM-4 * POINTER TO "VERSION" STRING, ZERO IF NONE + +GAMFIL EQU SHOWVE-4 * REF NUMBER OF OPENED GAME FILE +SAVFIL EQU GAMFIL-4 * REF NUMBER OF OPENED SAVE FILE + +*** + +DBZPC1 EQU SAVFIL-2 * HALT WHEN ZPC REACHES THIS ADDRESS +DBZPC2 EQU DBZPC1-2 +DBINST EQU DBZPC2-2 * HALT WHEN NEXT INSTRUCTION HAS THIS VALUE + +DBTOT1 EQU DBINST-4 * TOTAL EXECUTION COUNT +DBTOT2 EQU DBTOT1-4 * DESIRED EXECUTION COUNT + +*** + +ZVLEN EQU 0-DBTOT2 * TOTAL LENGTH OF ZIP'S VARIABLES FRAME + +* --------------------------------------------------------------------------- +* ZIP DEBUGGING -- FOR DEVELOPEMENT ONLY +* --------------------------------------------------------------------------- + + IFEQ DEBUG + +* GO UNTIL ONE OF THE FOLLOWING CONDITIONS OCCURS: +* () ZPC REACHES A GIVEN ADDRESS +* () ZPC POINTS TO A GIVEN INSTRUCTION +* () A GIVEN NUMBER OF INSTRUCTIONS ARE EXECUTED + +DBTEST RTS + + ENDC * END OF CONDITIONAL ASSEMBLY + + + PAGE +* --------------------------------------------------------------------------- +* INITIALIZATIONS +* --------------------------------------------------------------------------- + +PVERS1 EQU 0 * ZVERSION VERSION BYTE +PVERS2 EQU 1 * ZVERSION MODE BYTE +PZRKID EQU 2 * ZORK ID +PENDLD EQU 4 * ENDLOD (RELATIVE BYTE POINTER) +PSTART EQU 6 * START +PVOCTB EQU 8 * VOCTAB +POBJTB EQU 10 * OBJTAB +PGLOTB EQU 12 * GLOTAB +PPURBT EQU 14 * PURBOT +PFLAGS EQU 16 * USER FLAGS WORD +PSERNM EQU 18 * SERIAL NUMBER (6 BYTES) +PWRDTB EQU 24 * WRDTAB +PLENTH EQU 26 * LENGTH (EZIP QUADS, ZIP WORDS) +PCHKSM EQU 28 * CHECKSUM (ALL BYTES STARTING WITH BYTE 64) + +PINTWD EQU 30 * INTERPRETER ID/VERSION +PSCRWD EQU 32 * SCREEN SIZE, ROWS/COLUMNS + + IFEQ EZIP +ZMVERS EQU 4 * EZIP Z-MACHINE VERSION NUMBER +STKLEN EQU 512*2 * LENGTH OF GAME STACK (MULTIPLE OF 512) + ENDC + IFEQ CZIP +ZMVERS EQU 3 * CLASSIC Z-MACHINE VERSION NUMBER +STKLEN EQU 512*1 * LENGTH OF GAME STACK + ENDC + +* MICRO'S ID CODE, ZIP'S VERSION LETTER (SEE ALSO OPVERI) + + SECTION ZDATA + IFEQ EZIP +INTWRD DC.B 4 * MACHINE ID FOR COMMODORE AMIGA + DC.B 'C' * EZIP INTERPRETER VERSION +SUBVER DC.W 0 * INTRPRETER SUB-VERSION, ZERO TO DISABLE + ENDC + IFEQ CZIP +INTWRD DC.B 0 * (UNUSED) + DC.B 'C' * INTERPRETER VERSION +SUBVER DC.W 0 * INTRPRETER SUB-VERSION, ZERO TO DISABLE + ENDC + +* INITIAL SET OF READ BREAK CHARS -- SPACE, TAB, CR, <.>, <,>, + +IRBRKS DC.W $2009,$0D2E,$2C3F,0 * ASCIZ + SECTION ZCODE + +* --------------------------------------------------------------------------- + +_START LINK A6,#-ZVLEN * CREATE A FRAME FOR ZIP VARIABLES + MOVE.L A6,A0 * TOP OF FRAME + + MOVE.W #ZVLEN/2,D0 +STRX1 CLR.W -(A0) * ALL INITIAL VALUES ARE ZERO + SUBQ.W #1,D0 + BNE.S STRX1 + + MOVE.L SP,TOPSP(A6) * SAVE THE SP FOR RESTARTS + LEA ZVARS,A0 + MOVE.L A6,(A0) * KEEP A COPY OF A6 IN A KNOWN PLACE + +* Careful about error msgs before all buffers are initialized. +* For example, a call to TSTSCR (via PUTCHR) before the preload data is +* read into BUFFER would access an invalid pointer. + +* Send any output directly to screen (VOBUFF off), until QUECHR stuff set up. + + MOVE.W #1,VOCONS(A6) * CONSOLE OUTPUT NORMALLY ACTIVE + MOVE.W #1,VIECHO(A6) * INPUT IS NORMALLY ECHOED + +* Avoid the TSTSCR bug by pretending we're in window 1 (never scripts). + + MOVE.W #1,WIND1(A6) * IN WINDOW 1 UNTIL PRELOAD COMPLETED + BSR SYSINI * OPEN THE GAME FILE + + IFEQ EZIP + MOVE.W _columns,D0 + CMPI.W #80-1,D0 * 80 COLUMNS MINIMUM, LESS FUDGE (AMIGA) + BGE STRX2 * OK + + LEA MSG80C,A0 * NOT ENOUGH, INFORM USER AND QUIT + BSR OUTMSG + BRA FINISH + + SECTION ZDATA +MSG80C DC.B 'Your screen resolution is too low to continue. ' + DC.B 'You must increase the resolution before starting the story.' + DC.B 0 + SECTION ZCODE + ENDC + +*** READ GAME BLOCK 0 INTO A TEMP STACK BUFFER + +STRX2 SUBA.W #512,SP * CREATE A TEMP BUFFER + MOVE.L SP,A4 * SAVE POINTER HERE FOR NOW + + MOVE.L A4,A0 + CLR.W D0 * BLOCK 0 + BSR GETBLK * GET IT + +*** CHECK MACHINE VERSION NUMBER + + CMPI.B #ZMVERS,(A4) * PROPER Z-MACHINE VERSION? + BEQ.S STRX4 * YES + +STRX3 CLR.W D0 * SOMETHING WRONG, DIE + LEA MSGZMV,A0 + BRA FATAL * 'Wrong Z-machine' + + SECTION ZDATA +MSGZMV DC.B 'Wrong Z-machine version',0 + SECTION ZCODE + +STRX4 MOVE.W PZRKID(A4),ZORKID(A6) * UNIQUE GAME ID, CHECKED BY "RESTORE" + + IFEQ CZIP + BTST #0,PVERS2(A4) * PROPER BYTE-SWAP MODE? + BNE STRX3 * NO, FAIL + + CLR.W TIMEMD(A6) * ASSUME SCORE-MODE FOR STATUS LINE + BTST #1,PVERS2(A4) * TIME MODE REQUESTED? + BEQ.S STRX6 * NO + ADDQ.W #1,TIMEMD(A6) * YES, SET TIME-MODE FLAG + ENDC + + +*** DETERMINE OUR MEMORY REQUIREMENTS + +STRX6 MOVEQ #0,D0 + MOVE.W PLENTH(A4),D0 * LENGTH OF GAME FILE (WORDS OR QUADS) + ADD.L D0,D0 + IFEQ EZIP + ADD.L D0,D0 * BYTES + ENDC + BSR ROUNDUP + MOVE.L D0,MAXGAM(A6) + + MOVEQ #0,D0 + MOVE.W PENDLD(A4),D0 * "NORMAL" LENGTH OF PRELOAD (BYTES) + BSR ROUNDUP + MOVE.L D0,MINGAM(A6) + +*** INQUIRE FREE MEMORY (AMIGA -- SUPPLY OUR MAXIMUM REQUIREMENT ...) + + MOVE.L MAXGAM(A6),D0 + ADD.L #STKLEN+1024+512,D0 * PLUS ZSTACK, 2 PAGES, MISC + BSR MEMAVAIL * DETERMINE HOW MUCH FREE MEMORY EXISTS + MOVE.L D0,D7 * SAVE THE NUMBER HERE + +* THE FOUR POSSIBLE MEMORY SITUATIONS ... +* +* (1) MEMAVAIL exceeds PLENTH. Preload the entire game, and create +* two page buffers (minimum needed for $VER). +* +* (2) MEMAVAIL exceeds ENDLOD by at least (say) 40 pages. Preload through +* ENDLOD, and create as many page buffers as possible. +* +* (3) MEMAVAIL barely exceeds ENDLOD. In this situation, performance +* degrades sharply. To free up some memory, preload only through the +* beginning of the vocabulary table, and create as many page buffers +* as possible. +* +* (4) MEMAVAIL does not exceed ENDLOD. Life is tough. +* + + CMP.L MAXGAM(A6),D7 * ENOUGH ROOM TO PRELOAD ENTIRE GAME? + BGE.S LOAD2C * YES + + MOVE.L D7,D0 + SUBI.L #40*512,D0 * ALLOW ABOUT 40 PAGES OVERHEAD + CMP.L MINGAM(A6),D0 * ENOUGH ROOM FOR A "COMFORTABLE FIT"? + BGE.S LOAD2B * YES + + CMP.L MINGAM(A6),D7 * ENOUGH ROOM FOR A "TIGHT FIT"? + BGE.S LOAD2A * YES + + BRA MEMERR * NO, FAIL + +* PATCH MINGAM(A6) SO THAT VOCAB TABLE IS NOT PRELOADED + +LOAD2A MOVEQ #0,D0 + MOVE.W PVOCTB(A4),D0 * START OF VOCAB TABLE + ADD.L #64,D0 * BUT, BE CAREFUL TO INCLUDE THE VOCTAB HEADER + BSR ROUNDUP + MOVE.L D0,MINGAM(A6) * AND FALL THROUGH ... + +* GIVEN MINGAM, SET ENDLOD AND MAXIMIZE PAGTOT + +LOAD2B MOVE.L MINGAM(A6),D0 + BSR BYTBLK + MOVE.W D0,ENDLOD(A6) * LENGTH OF PRELOAD (IN BLOCKS) + + MOVE.L D7,D0 + SUB.L MINGAM(A6),D0 * MEMORY REMAINING AFTER PRELOAD + DIVU #512+8,D0 * PAGES AVAIL (ALLOW 8 BYTES PER TABLE ENTRY) + CMPI.W #2,D0 + BGE.S LOAD2X + MOVEQ #2,D0 * ENSURE THAT WE HAVE AT LEAST TWO +LOAD2X MOVE.W D0,PAGTOT(A6) * SAVE FOR LATER + BRA.S LOAD3 + +* GIVEN MAXGAM, SET ENDLOD AND MINIMIZE PAGTOT + +LOAD2C MOVE.L MAXGAM(A6),D0 + BSR BYTBLK * LENGTH OF GAME FILE (IN BLOCKS) + MOVE.W D0,ENDLOD(A6) * PRELOAD EVERYTHING + + MOVE.W #2,PAGTOT(A6) * TWO PAGES ONLY (FOR $VERIFY) + + +*** GIVEN ENDLOD, ALLOCATE SOME MEMORY AND DO THE PRELOAD + +LOAD3 + IFEQ DEBUG + MOVE.W ENDLOD(A6),D0 + BSR OPPRNN * SHOW PRELOAD + MOVE.B #'/',D0 + BSR PUTCHR + MOVE.W PAGTOT(A6),D0 * SHOW PAGE COUNT + BSR OPPRNN + BSR PUTNEW + ENDC + + MOVE.W ENDLOD(A6),D0 * SPACE NEEDED FOR PRELOAD (IN BLOCKS) + BSR BLKBYT * CONVERT TO BYTES + BSR GETMEM + MOVE.L A0,BUFFER(A6) * KEEP POINTER HERE + + MOVE.W ENDLOD(A6),D1 * NUMBER OF BLOCKS TO PRELOAD + CLR.W D0 * STARTING WITH BLOCK 0 + BSR GTBLKS * READ THEM IN + + MOVE.L BUFFER(A6),A4 * USE PRELOAD BUFFER FOR REMAINING INITS + ADDA.W #512,SP * FLUSH THE TEMP BUFFER + + CLR.W WIND1(A6) * RESTORE NORMAL VALUE (FOR PUTCHR/TSTSCR) + +* ------------------------------------------------------------------------ + +*** INITIALIZE MAJOR TABLE POINTERS + + MOVEQ #0,D0 + MOVE.W PVOCTB(A4),D0 * RELATIVE VOCAB TABLE POINTER + ADD.L A4,D0 * ABSOLUTIZE IT + MOVE.L D0,VOCTAB(A6) * AND SAVE IT + + MOVEQ #0,D0 + MOVE.W POBJTB(A4),D0 * RELATIVE OBJECT TABLE POINTER + ADD.L A4,D0 + MOVE.L D0,OBJTAB(A6) + + MOVEQ #0,D0 + MOVE.W PGLOTB(A4),D0 * RELATIVE GLOBAL TABLE POINTER + ADD.L A4,D0 + MOVE.L D0,GLOTAB(A6) + + MOVEQ #0,D0 + MOVE.W PWRDTB(A4),D0 * RELATIVE WORD TABLE POINTER + ADD.L A4,D0 + MOVE.L D0,WRDTAB(A6) + + MOVEQ #0,D0 + MOVE.W PPURBT(A4),D0 * GET PURBOT BYTE POINTER + BSR BYTBLK * ROUND UP TO NEXT BLOCK BOUNDARY + MOVE.W D0,PURBOT(A6) * AND SAVE IT + +*** ALLOCATE MEMORY FOR Z STACK + + MOVE.L #STKLEN,D0 + BSR GETMEM + MOVE.L A0,STKBOT(A6) * THIS WILL BE BOTTOM OF GAME STACK + +*** INITIALIZE LINE BUFFER, SCRIPT BUFFER + +SCRLEN EQU 80 * LENGTH OF SCRIPT BUFFER (CONST FOR NOW) +MAXLEN EQU 256 * MAX LENGTH OF LINE BUFFER + + MOVE.W #MAXLEN,D1 + MOVE.W _columns,D2 * CURRENT WIDTH OF SCREEN DISPLAY + LEA LINOUT,A1 * SCREEN DISPLAY FUNCTION + LEA CHSIZ,A2 + + BSR INITQP * SET UP DISPLAY QUEUE STUFF + MOVE.L A0,DQUE(A6) * SAVE BLOCK POINTER + + MOVE.W #SCRLEN,D1 * SCRIPTING SIZE, NEVER CHANGES + MOVE.W D1,D2 + LEA SCROUT,A1 * SCRIPTING DISPLAY FUNCTION + LEA CHSIZ,A2 + + BSR INITQP * SET UP SCRIPT QUEUE STUFF + MOVE.L A0,SQUE(A6) * SAVE THIS POINTER TOO + + MOVE.W #1,VOBUFF(A6) * OKAY NOW TO BEGIN BUFFERING OUTPUT + +*** ALLOCATE MEMORY FOR BREAK-CHAR TABLE, INIT VOCABULARY VARS + + MOVE.L #64,D0 * MAX BREAK CHARS + BSR GETMEM + MOVE.L A0,RBRKS(A6) * THIS WILL BE START OF SI BREAK CHARS + + MOVE.L VOCTAB(A6),A1 + CLR.W D0 + MOVE.B (A1)+,D0 * FIRST BYTE OF VOCTAB IS # OF SI BREAK CHARS +STRX10 MOVE.B (A1)+,(A0)+ * TRANSFER THEM + SUBQ.W #1,D0 + BNE.S STRX10 + + MOVE.L A0,ESIBKS(A6) * REMEMBER END OF SI BREAKS + LEA IRBRKS,A2 * THESE ARE THE NORMAL BREAK CHARS +STRX12 MOVE.B (A2)+,(A0)+ * TRANSFER THEM TOO + BNE.S STRX12 * ASCIZ + + CLR.W D0 + MOVE.B (A1)+,D0 * THIS BYTE IS THE LENGTH OF EACH VOCTAB ENTRY + MOVE.W D0,VWLEN(A6) * SAVE IT + + MOVE.B (A1)+,D0 * THIS WORD IS THE NUMBER OF VOCTAB ENTRIES + ASL.W #8,D0 + MOVE.B (A1)+,D0 + MOVE.W D0,VWORDS(A6) * SAVE IT + + SUBA.L BUFFER(A6),A1 * RELATIVIZE NEXT TWO POINTERS + MOVE.L A1,VOCBEG(A6) * THIS IS BEGINNING OF ACTUAL VOCABULARY + SUBQ.W #1,D0 * CALCULATE POINTER TO LAST VOCAB ENTRY + MULU VWLEN(A6),D0 + ADDA.L D0,A1 + MOVE.L A1,VOCEND(A6) * AND SAVE IT + +*** ALLOCATE MEMORY FOR PAGE TABLE & BUFFERS + + MOVE.W PAGTOT(A6),D0 * PREVIOUSLY CALCULATED NUMBER OF PAGE BUFFERS + MULU #8,D0 * 8-BYTE TABLE ENTRY FOR EACH PAGE + ADDQ.L #2,D0 * ALLOW FOR THE END MARK + BSR GETMEM + MOVE.L A0,PAGTAB(A6) * THIS WILL BE START OF PAGE TABLE + + MOVE.W PAGTOT(A6),D0 * PREVIOUSLY CALCULATED NUMBER OF PAGE BUFFERS + MULU #512,D0 * 512 BYTES EACH + BSR GETMEM + MOVE.L A0,PAGES(A6) * PAGES THEMSELVES WILL START HERE + +*** INITIALIZE THE PAGE TABLE + + MOVE.W PAGTOT(A6),D0 * PREVIOUSLY CALCULATED NUMBER OF PAGE BUFFERS + MOVE.L PAGTAB(A6),A0 + +STRX16 MOVE.W #-2,(A0)+ * BLOCK (NO BLOCK "$FFFE") + CLR.L (A0)+ * REF TIME IS ZERO + CLR.W (A0)+ * THIS SLOT UNUSED (BUT 8 BYTES SPEEDS CALCS) + SUBQ.W #1,D0 + BNE.S STRX16 + MOVE.W #-1,(A0) * MARK THE END OF THE TABLE (NO BLOCK "$FFFF") + + MOVE.W #-1,CURBLK(A6) * MUST INIT THESE PAGING VARS TOO! + MOVE.W #-1,LPAGE(A6) + +* ETCETERA ... + + BSR GTSEED * INITIALIZE THE RANDOM NUMBER SEEDS + MOVE.W D0,RSEED1(A6) + SWAP D0 + MOVE.W D0,RSEED2(A6) * PUT HIGH WORD HERE (RELATIVELY CONSTANT) + + BRA.S START1 + +* RESTART EXECUTION HERE + +RESTRT MOVE.L BUFFER(A6),A0 + MOVE.W PFLAGS(A0),-(SP) * PRESERVE THE USER FLAGS (SCRIPT ETC) + + CLR.W D0 * REREAD ALL OF THE IMPURE STUFF + MOVE.W PURBOT(A6),D1 + BSR GTBLKS + + MOVE.L BUFFER(A6),A0 + MOVE.W (SP)+,PFLAGS(A0) * RESTORE USER FLAGS + +START1 MOVE.L TOPSP(A6),SP * RE-INITIALIZE SYSTEM STACK POINTER + + MOVE.L DQUE(A6),A0 + MOVE.L BUFPTR(A0),NXTPTR(A0) * INITIALIZE OUTPUT BUFFER POINTER + + MOVE.L STKBOT(A6),A4 + ADDA.W #STKLEN,A4 * INITIALIZE GAME STACK POINTER + + MOVE.L A4,ZLOCS(A6) * INITIALIZE POINTER TO LOCALS + SUBQ.L #2,ZLOCS(A6) * IF ANY, THEY WOULD START AT FIRST SLOT + + MOVE.L BUFFER(A6),A2 + + IFEQ EZIP +* ORI.B #32 * NO SOUND (AMIGA) + ORI.B #16+8+4+2+1,PVERS2(A2) * CURSOR/HIGHLIGHTS/SPLIT + LEA INTWRD,A0 + MOVE.B (A0)+,PINTWD(A2) * STORE THE MACHINE ID + MOVE.B (A0),PINTWD+1(A2) * AND THE INTERPRETER VERSION + + MOVE.W _rows,D0 + MOVE.W _columns,D1 + ASL.W #8,D0 * ROWS IN HIGH BYTE, COLUMNS IN LOW + MOVE.B D1,D0 + MOVE.W D0,PSCRWD(A2) * SET SCREEN-PARAMETERS WORD + + CLR.W RCYCLE(A6) * ALWAYS RESTART WITH NORMAL RANDOMNESS + + CLR.W _split_row * NO STATUS LINE INITIALLY + BSR EZERR * CHECK OBJTAB ALIGNMENT + ENDC + IFEQ CZIP + BSET #5,PVERS2(A2) * SPLIT-SCREEN IS AVAILABLE + MOVE.W #1,_split_row * ALLOW FOR ONE STATUS LINE + ENDC + + MOVE.W PSTART(A2),D0 * GET STARTING LOCATION + BSR BSPLTB * SPLIT BLOCK AND BYTE POINTERS + + MOVE.W D0,ZPC1(A6) * INITIALIZE THE ZPC + MOVE.W D1,ZPC2(A6) + BSR NEWZPC * GET THE FIRST PAGE TO EXECUTE + + BSR BOOTSV * MAC -- BUT LOAD A SAVED GAME IF REQUESTED + BRA NXTINS * TALLY HO + + IFEQ EZIP + +* MAKE SURE OBJ TABLE IS WORD ALIGNED FOR EZIP + +EZERR MOVE.L BUFFER(A6),A0 + MOVE.W POBJTB(A0),D0 * OBJECT TABLE BASE + BTST #0,D0 * WORD ALIGNED? + BNE.S EZERX1 * NO, FAIL + RTS + +EZERX1 CLR.W D0 + LEA MSGEZR,A0 + BRA FATAL * 'OBJTAB alignment error' + + SECTION ZDATA +MSGEZR DC.B 'OBJTAB alignment error',0 + SECTION ZCODE + + ENDC + + PAGE +* --------------------------------------------------------------------------- +* LOW LEVEL FUNCTIONS +* --------------------------------------------------------------------------- + +* GIVEN A ZIP BLOCK COUNT IN D0.W, RETURN A BYTE COUNT IN D0.L + +BLKBYT EXT.L D0 * CLEAR HIGH WORD + SWAP D0 + LSR.L #7,D0 * x512 + RTS + +* GIVEN A BYTE COUNT IN D0.L, RETURN A ZIP BLOCK COUNT IN D0.W, ROUNDING UP + +BYTBLK BSR ROUNDUP + LSR.L #8,D0 + LSR.L #1,D0 * EXTRACT BLOCK NUMBER + RTS + +* GIVEN A BYTE COUNT IN D0.L, ROUND UP TO NEAREST MULTIPLE OF 512 + +ROUNDUP + MOVE.W D0,-(SP) + ANDI.W #$01FF,(SP)+ * ARE THERE ANY FRACTIONAL BYTES? + BEQ.S RDUP1 * NO + + ANDI.W #$FE00,D0 * YES, REMOVE THE FRACTIONAL BYTES + ADDI.L #$0200,D0 * AND ROUND UP +RDUP1 RTS + +* GET CORE WORD, ABSOLUTE POINTER IN A0, RETURN THE WORD IN D0, UPDATE POINTER + +GTAWRD + MOVE.B (A0)+,D0 * GET HIGH-ORDER BYTE, ADVANCE A0 + ASL.W #8,D0 * POSITION IT + MOVE.B (A0)+,D0 * GET LOW-ORDER BYTE, ADVANCE A0 + RTS + +* UPDATE CORE WORD, ABSOLUTE POINTER IN A0, NEW VALUE IN D0 + +PTAWRD + MOVE.B D0,1(A0) * STORE LOW-ORDER BYTE + ASR.W #8,D0 + MOVE.B D0,(A0) * STORE HIGH-ORDER BYTE + RTS + +* GET A BYTE FROM GAME, BLOCK-POINTER IN D0, BYTE-POINTER IN D1, RESULT IN D2 +* UPDATE D0 AND D1 TO REFLECT BYTE GOTTEN + +GETBYT MOVE.W D0,-(SP) + CMP.W ENDLOD(A6),D0 * IS THIS A PRELOADED LOCATION? + BGE.S GETBX1 * NO + + BSR BLKBYT * YES, RECONSTRUCT POINTER (MAY EXCEED 32K) + OR.W D1,D0 + + CLR.W D2 * CLEAR THE UNWANTED HIGH BYTE + MOVE.L BUFFER(A6),A0 * ABSOLUTE POINTER + MOVE.B 0(A0,D0.L),D2 * GET THE DESIRED BYTE + BRA.S GETBX2 + +GETBX1 BSR GETPAG * FIND THE PROPER PAGE (POINTER RETURNED IN A0) + CLR.W D2 * CLEAR THE UNWANTED HIGH BYTE + MOVE.B 0(A0,D1.W),D2 * GET THE DESIRED BYTE + +GETBX2 MOVE.W (SP)+,D0 + ADDQ.W #1,D1 * UPDATE BYTE-POINTER + CMPI.W #512,D1 * END OF PAGE? + BNE.S GETBX3 * NO, DONE + + CLR.W D1 * YES, CLEAR BYTE-POINTER + ADDQ.W #1,D0 * AND UPDATE BLOCK-POINTER +GETBX3 RTS + +* GET A WORD FROM GAME, BLOCK-POINTER IN D0, BYTE-POINTER IN D1, RESULT IN D2 + +GETWRD BSR GETBYT * GET HIGH-ORDER BYTE + ASL.W #8,D2 * POSITION IT + MOVE.W D2,-(SP) * SAVE IT + + BSR GETBYT * GET LOW-ORDER BYTE + OR.W (SP)+,D2 * OR IN THE OTHER BYTE + RTS + +* GET THE NEXT BYTE, RETURN IT IN D0 + +NXTBYT MOVE.L CURPAG(A6),A0 * INDEX INTO CURRENT PAGE + ADDA.W ZPC2(A6),A0 + CLR.W D0 * CLEAR HIGH REGISTER AND + MOVE.B (A0),D0 * GET THE NEXT BYTE + + ADDQ.W #1,ZPC2(A6) * UPDATE PC + CMPI.W #512,ZPC2(A6) * END OF PAGE? + BLT.S NXTBX1 * NO + + MOVE.W D0,-(SP) + BSR NEWZPC * YES, UPDATE PAGE + MOVE.W (SP)+,D0 +NXTBX1 RTS * AND RETURN + +* GET THE NEXT WORD, RETURN IT IN D0 + +NXTWRD BSR NXTBYT * GET HIGH-ORDER BYTE + ASL.W #8,D0 * SHIFT TO PROPER POSITION + MOVE.W D0,-(SP) * SAVE IT + + BSR NXTBYT * GET LOW-ORDER BYTE + OR.W (SP)+,D0 * OR IN THE OTHER BYTE + RTS + +* GET AN ARGUMENT GIVEN ITS TYPE IN D0 + +GETARG SUBQ.W #1,D0 * EXAMINE ARGUMENT + BLT.S NXTWRD * 0 MEANT LONG IMMEDIATE + BEQ.S NXTBYT * 1 MEANT SHORT IMMEDIATE + + BSR NXTBYT * 2 MEANT VARIABLE, GET THE VAR + TST.W D0 * STACK? + BNE.S GETV1 * NO, JUST GET THE VAR'S VALUE + MOVE.W (A4)+,D0 * YES, POP THE STACK + RTS + +* GET VALUE OF A VARIABLE, VAR IN D0, VALUE RETURNED IN D0 + +GETVAR TST.W D0 * STACK? + BNE.S GETV1 * NO + MOVE.W (A4),D0 * YES, GET TOP-OF-STACK (DON'T POP) + RTS + +GETV1 CMPI.W #16,D0 * LOCAL? + BGE.S GETVX2 * NO + MOVE.L ZLOCS(A6),A0 * YES, POINT TO PROPER STACK ELEMENT + SUBQ.W #1,D0 * ADJUST FOR NULL VAR + ADD.W D0,D0 + SUBA.W D0,A0 * LOCALS BUILD DOWN + MOVE.W (A0),D0 * GET IT + RTS + +GETVX2 SUB.W #16,D0 * GLOBAL, ADJUST FOR LOCALS + MOVE.L GLOTAB(A6),A0 * POINT TO PROPER GLOBAL TABLE ELEMENT + ADD.W D0,D0 + ADDA.W D0,A0 + BRA GTAWRD * GET IT AND RETURN + +* UPDATE VALUE OF A VARIABLE, VAR IN D0, NEW VALUE IN D1 + +PUTVAR TST.W D0 * STACK? + BNE.S PUTVX1 * NO + MOVE.W D1,(A4) * YES, UPDATE TOP-OF-STACK (DON'T PUSH) + RTS + +PUTVX1 CMPI.W #16,D0 * LOCAL? + BGE.S PUTVX2 * NO + MOVE.L ZLOCS(A6),A0 * YES, POINT TO PROPER STACK ELEMENT + SUBQ.W #1,D0 * ADJUST FOR NULL VAR + ADD.W D0,D0 + SUBA.W D0,A0 * LOCALS BUILD DOWN + MOVE.W D1,(A0) * UPDATE IT + RTS + +PUTVX2 SUB.W #16,D0 * GLOBAL, ADJUST FOR LOCALS + MOVE.L GLOTAB(A6),A0 * POINT TO PROPER GLOBAL TABLE ELEMENT + ADD.W D0,D0 + ADDA.W D0,A0 + MOVE.W D1,D0 + BRA PTAWRD * UPDATE IT AND RETURN + +* RETURN VAL IN D0 TO LOCATION SPECIFIED BY NEXTBYTE +* DESTROYS D1, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION + +BYTVAL ANDI.W #$00FF,D0 * ENTER HERE TO CLEAR HIGH BYTE +PUTVAL MOVE.W D0,D1 * NORMAL ENTRY + BSR NXTBYT * GET VAR TO USE + TST.W D0 * STACK? + BNE.S PUTVAR * NO, GO STORE VALUE + MOVE.W D1,-(A4) * YES, PUSH ONTO STACK + RTS + +* PREDICATE HANDLERS TRUE AND FALSE +* DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FUNCTIONS + +PFALSE CLR.W D1 * PREDICATE WAS FALSE, CLEAR FLAG + BRA.S PTRUE1 + +PTRUE MOVEQ #1,D1 * PREDICATE WAS TRUE, SET FLAG +PTRUE1 BSR NXTBYT * GET FIRST (OR ONLY) PREDICATE JUMP BYTE + BCLR #7,D0 * NORMAL POLARITY PREDICATE? + BEQ.S PTRUX1 * NO, LEAVE FLAG ALONE + ADDQ.W #1,D1 * YES, INCREMENT FLAG + +PTRUX1 BCLR #6,D0 * ONE-BYTE JUMP OFFSET? + BNE.S PTRUX3 * YES + + ASL.W #8,D0 * NO, TWO-BYTE, POSITION HIGH-ORDER OFFSET BYTE + MOVE.W D0,D2 + BSR NXTBYT * GET LOW-ORDER BYTE + OR.W D2,D0 * OR IN HIGH-ORDER BITS + BTST #13,D0 * IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)? + BEQ.S PTRUX3 * NO + ORI.W #$C000,D0 * YES, MAKE 16-BIT NUMBER NEGATIVE + +PTRUX3 SUBQ.W #1,D1 * TEST FLAG + BEQ.S PTRUX6 * WAS 1, THAT MEANS DO NOTHING + TST.W D0 * ZERO JUMP? + BNE.S PTRUX4 * NO + BRA OPRFAL * YES, THAT MEANS DO AN RFALSE + +PTRUX4 SUBQ.W #1,D0 * ONE JUMP? + BNE.S PTRUX5 * NO + BRA OPRTRU * YES, THAT MEANS DO AN RTRUE + +PTRUX5 SUBQ.W #1,D0 * ADJUST OFFSET + ADD.W D0,ZPC2(A6) * ADD TO PC + BRA NEWZPC * AND UPDATE ZPC STUFF +PTRUX6 RTS + +* SPLIT BYTE-POINTER IN D0.W (16 BIT UNSIGNED) +* INTO BLOCK NUMBER IN D0 & BYTE OFFSET IN D1 + +BSPLTB MOVE.W D0,D1 + LSR.W #8,D0 * EXTRACT THE 7 BLOCK BITS (64K RANGE) + LSR.W #1,D0 + ANDI.W #$01FF,D1 * EXTRACT THE 9 OFFSET BITS (0-511) + IFEQ DEBUG + BSR BLKCHK * CHECK FOR VALID BLOCK + ENDC + RTS + +* SPLIT WORD-POINTER IN D0.W (16 BIT UNSIGNED) +* INTO BLOCK NUMBER IN D0 & BYTE OFFSET IN D1 + +BSPLIT MOVE.W D0,D1 + LSR.W #8,D0 * EXTRACT THE 8 BLOCK BITS (128K RANGE) + ANDI.W #$00FF,D1 * EXTRACT THE 8 OFFSET BITS (0-255) + ADD.W D1,D1 * CONVERT OFFSET TO BYTES + IFEQ DEBUG + BSR BLKCHK * CHECK FOR VALID BLOCK + ENDC + RTS + +* SPLIT QUAD-POINTER IN D0.W (16 BIT UNSIGNED) +* INTO BLOCK NUMBER IN D0 & BYTE OFFSET IN D1 -- EZIP ONLY + +BSPLTQ MOVE.W D0,D1 + LSR.W #7,D0 * EXTRACT THE 9 BLOCK BITS (256K RANGE) + ANDI.W #$007F,D1 * EXTRACT THE 7 OFFSET BITS (0-127) + ADD.W D1,D1 * CONVERT OFFSET TO BYTES + ADD.W D1,D1 + IFEQ DEBUG + BSR BLKCHK * CHECK FOR VALID BLOCK + ENDC + RTS + + IFEQ DEBUG +BLKCHK +* CMP.W MAXLOD(A6),D0 * VALID BLOCK NUMBER? +* BCC BLKERR * BHS * NO, FAIL + RTS + +BLKERR LEA MSGBLK,A0 + BRA FATAL * 'Block range error' + + SECTION ZDATA +MSGBLK DC.B 'Block range error',0 + SECTION ZCODE + + ENDC diff --git a/amiga/zip2.asm b/amiga/zip2.asm new file mode 100644 index 0000000..75337c4 --- /dev/null +++ b/amiga/zip2.asm @@ -0,0 +1,2025 @@ + + PAGE +* ---------------------------------------------------------------------------- +* ARITHMETIC OPERATIONS +* ---------------------------------------------------------------------------- + +OPADD ADD.W D1,D0 * ADD OPR1 AND OPR2 + BRA PUTVAL * RETURN THE VALUE + +OPSUB SUB.W D1,D0 * SUBTRACT OPR2 FROM OPR1 + BRA PUTVAL * RETURN THE VALUE + +OPMUL MULS D1,D0 * MULTIPLY OPR1 BY OPR2 (16 BIT SIGNED) + BRA PUTVAL * RETURN THE PRODUCT, IGNORING OVERFLOW + +* DIVIDE BY ZERO, MOD ZERO, & RANDOM ZERO GENERATE 68K ERROR TRAPS ... + +OPDIV EXT.L D0 * SIGN-EXTEND OPR1 TO 32 BITS + DIVS D1,D0 * DIVIDE OPR2 INTO OPR1 + BRA PUTVAL * RETURN THE QUOTIENT, IGNORING REMAINDER + +OPMOD EXT.L D0 * SIGN-EXTEND OPR1 TO 32 BITS + DIVS D1,D0 * DIVIDE OPR2 INTO OPR1 + SWAP D0 * GET REMAINDER + BRA PUTVAL * RETURN IT + +OPRAND + + IFEQ EZIP + TST.W D0 * DISABLE RANDOMNESS NOW? + BLT RANDX1 * YES + BEQ.S RANDX2 * ZERO, RE-ENABLE RANDOMNESS + + TST.W RCYCLE(A6) * IS RANDOMNESS ALREADY DISABLED? + BNE.S RANDX3 * YES + ENDC + +* NORMAL RANDOMNESS, GENERATE A RANDOM VALUE + + MOVE.W RSEED2(A6),D1 * GET BOTH SEEDS + SWAP D1 + MOVE.W RSEED1(A6),D1 + MOVE.W D1,RSEED2(A6) * UPDATE LOW SEED + SWAP D1 + + LSR.L #1,D1 * SHIFT BOTH RIGHT BY 1 BIT + EOR.W D1,RSEED1(A6) * UPDATE HIGH SEED + MOVE.W RSEED1(A6),D1 * THIS IS THE RANDOM VALUE + BRA RANDX4 + + IFEQ EZIP + +* RANDOMNESS DISABLED, GENERATE A CYCLIC VALUE + +RANDX1 NEG.W D0 * THIS SPECIFIES UPPER LIMIT OF SEQUENCE +RANDX2 MOVE.W D0,RCYCLE(A6) * STORE IT (ZERO FOR NORMAL) + MOVE.W D0,RCOUNT(A6) * INITIALIZE COUNTER (SEQ BEGINS NEXT PASS) + MOVEQ #1,D0 + BRA.S RANDX5 * ALWAYS RETURN A ONE (IGNORED?) + +RANDX3 ADDQ.W #1,RCOUNT(A6) * GENERATE NEXT VALUE IN SEQUENCE (0 TO N-1) + MOVE.W RCOUNT(A6),D1 + CMP.W RCYCLE(A6),D1 * EXCEEDED THE UPPER LIMIT YET? + BLT.S RANDX4 * NO + CLR.W D1 * YES, RESTART THE SEQUENCE + MOVE.W D1,RCOUNT(A6) + ENDC + +* TRANSFORM RANDOM VALUE TO REQUESTED RANGE, AND RETURN IT + +RANDX4 ANDI.L #$00007FFF,D1 * CLEAR HIGH BIT TO PREVENT POSSIBLE OVERFLOW + DIVU D0,D1 * DIVIDE ARG INTO RANDOM NUMBER + SWAP D1 * GET REMAINDER + ADDQ.W #1,D1 * MUST BE BETWEEN 1 AND N, INCLUSIVE + MOVE.W D1,D0 +RANDX5 BRA PUTVAL * RETURN THE VALUE + + +OPQLES CMP.W D1,D0 * IS OPR1 LESS THAN OPR2? + BLT PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + +OPQGRT CMP.W D1,D0 * IS OPR1 GREATER THAN OPR2? + BGT PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PRECICATE FALSE + + +* LOGICAL OPERATIONS + +OPBTST NOT.W D0 * TURN OFF ALL BITS IN OPR2 THAT ARE ON IN OPR1 + AND.W D0,D1 + BEQ PTRUE * SUCCESS IF OPR2 COMPLETELY CLEARED + BRA PFALSE + +OPBOR OR.W D1,D0 * LOGICAL "OR" + BRA PUTVAL * RETURN THE VALUE + +OPBCOM NOT.W D0 * LOGICAL COMPLEMENT + BRA PUTVAL * RETURN THE VALUE + +OPBAND AND.W D1,D0 * LOGICAL "AND" + BRA PUTVAL * RETURN THE VALUE + + +* GENERAL PREDICATES + +OPQEQU NOP * TELL CALLER TO USE ARGBLK + MOVE.W (A0)+,D1 * NUMBER OF OPERANDS + MOVE.W (A0)+,D0 * OPR1 + SUBQ.W #1,D1 + +QEQUX1 CMP.W (A0)+,D0 * IS NEXT OPR EQUAL TO OPR1? + BEQ.S QEQUX2 * YES + SUBQ.W #1,D1 * NO, BUT LOOP IF MORE OPERANDS + BNE.S QEQUX1 + + BRA PFALSE * PREDICATE FALSE +QEQUX2 BRA PTRUE * PREDICATE TRUE + + +OPQZER TST.W D0 * IS OPR ZERO? + BEQ PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + + + PAGE +* ---------------------------------------------------------------------------- +* OBJECT-RELATED PRIMITIVES +* ---------------------------------------------------------------------------- + +* GIVEN OBJECT NUMBER IN D0.W, RETURN OBJECT LOCATION IN A0 + +OBJLOC MULU #OLEN,D0 * CALCULATE OBJECT OFFSET + MOVE.L OBJTAB(A6),A0 + ADDA.L D0,A0 * INDEX INTO OBJECT TABLE + ADDA.W #OPLEN-OLEN,A0 * SKIPPING OVER THE DEFAULT PROPERTY TABLE + RTS + +* GIVEN OBJECT LOCATION IN A0, RETURN POINTER TO FIRST PROPERTY IN A0 + +FSTPRP ADDA.W #PROP,A0 * POINT TO PROPERTY TABLE SLOT + MOVEQ #0,D0 + BSR GTAWRD * GET ITS LOCATION + MOVE.L BUFFER(A6),A0 * ABSOLUTIZE THE LOCATION + ADDA.L D0,A0 + + CLR.W D0 + MOVE.B (A0)+,D0 * LENGTH OF SHORT DESCRIPTION IN WORDS + ADD.W D0,D0 + ADDA.W D0,A0 * ADJUST POINTER TO SKIP IT + RTS + +* GIVEN POINTER TO A PROPERTY ID IN A0, UPDATE IT TO POINT TO NEXT PROPERTY ID + + IFEQ EZIP + +NXTPRP MOVE.B (A0)+,D0 * GET (FIRST) PROPERTY ID BYTE + BTST #7,D0 * PROPERTY LENGTH GREATER THAN 2? + BNE.S NXTPX4 * YES + + BTST #6,D0 * NO, PROPERTY LENGTH 2? + BEQ.S NXTPX2 * NO, PROPERTY LENGTH IS 1 + ADDQ.L #1,A0 +NXTPX2 ADDQ.L #1,A0 * UPDATE POINTER + RTS + +NXTPX4 MOVE.B (A0)+,D0 * GET (SECOND) PROPERTY LENGTH BYTE (LOW 6 BITS) + ANDI.W #$003F,D0 * CLEAR OFF HIGH BITS + ADDA.W D0,A0 * UPDATE POINTER + RTS + ENDC + IFEQ CZIP + +NXTPRP CLR.W D0 + MOVE.B (A0)+,D0 * GET PROPERTY ID BYTE + ASR.W #5,D0 * EXTRACT PROPERTY LENGTH-1 (HIGH 3 BITS) + ADDQ.W #1,D0 * ADJUST FOR EXTRA LENGTH BYTE + ADDA.W D0,A0 * UPDATE POINTER + RTS + ENDC + + +* ---------------------------------------------------------------------------- +* OBJECT OPERATIONS +* ---------------------------------------------------------------------------- + +* MOVE (OBJ1 INTO OBJ2) + +OPMOVE MOVEM.W D1/D0,-(SP) * PROTECT OPERANDS FROM REMOVE CALL + BSR OPREMO * REMOVE OBJ1 FROM WHEREVER IT IS + + MOVE.W 2(SP),D0 * OBJ2 + BSR OBJLOC * FIND ITS LOCATION + MOVE.L A0,A1 * SAVE IT + MOVE.W (SP),D0 * OBJ1 + BSR OBJLOC * FIND ITS LOCATION + + MOVEM.W (SP)+,D0/D1 * RESTORE THE OBJ NUMBERS + + IFEQ EZIP + MOVE.W FIRST(A1),NEXT(A0) * PUT OBJ2'S CHILD INTO OBJ1'S SIBLING SLOT + MOVE.W D1,LOC(A0) * PUT OBJ2 IN OBJ1'S PARENT SLOT + MOVE.W D0,FIRST(A1) * PUT OBJ1 IN OBJ2'S CHILD SLOT + ENDC + IFEQ CZIP + MOVE.B FIRST(A1),NEXT(A0) * PUT OBJ2'S CHILD INTO OBJ1'S SIBLING SLOT + MOVE.B D1,LOC(A0) * PUT OBJ2 IN OBJ1'S PARENT SLOT + MOVE.B D0,FIRST(A1) * PUT OBJ1 IN OBJ2'S CHILD SLOT + ENDC + RTS + +* REMOVE (OBJ FROM ITS PARENT) + + IFEQ EZIP + +OPREMO MOVE.W D0,D1 * SAVE OBJ + BSR OBJLOC * FIND ITS LOCATION + MOVE.L A0,A1 + MOVE.W LOC(A1),D0 * GET ITS PARENT + BEQ.S REMOX3 * IF NO PARENT, WE'RE DONE + + BSR OBJLOC * FIND PARENT'S LOCATION + MOVE.W FIRST(A0),D0 * GET PARENT'S FIRST CHILD + CMP.W D0,D1 * IS IT OBJ? + BNE.S REMOX1 * NO + + MOVE.W NEXT(A1),FIRST(A0) * YES, CHANGE IT TO OBJ'S SIBLING + BRA.S REMOX2 * AND EXIT + +REMOX1 BSR OBJLOC * FIND LOCATION OF CURRENT SIBLING + MOVE.W NEXT(A0),D0 * GET NEXT SIBLING IN CHAIN + CMP.W D0,D1 * IS IT OBJ? + BNE.S REMOX1 * NO, CONTINUE SEARCH + + MOVE.W NEXT(A1),NEXT(A0) * YES, CHANGE IT TO OBJ'S SIBLING +REMOX2 CLR.W LOC(A1) * OBJ NOW HAS NO PARENT + CLR.W NEXT(A1) * OR SIBLING +REMOX3 RTS + + ENDC + IFEQ CZIP + +OPREMO MOVE.W D0,D1 * SAVE OBJ + BSR OBJLOC * FIND ITS LOCATION + MOVE.L A0,A1 + MOVE.B LOC(A1),D0 * GET ITS PARENT + BEQ.S REMOX3 * IF NO PARENT, WE'RE DONE + + ANDI.W #$00FF,D0 * CLEAR UNWANTED BYTE + BSR OBJLOC * FIND PARENT'S LOCATION + MOVE.B FIRST(A0),D0 * GET PARENT'S FIRST CHILD + CMP.B D0,D1 * IS IT OBJ? + BNE.S REMOX1 * NO + + MOVE.B NEXT(A1),FIRST(A0) * YES, CHANGE IT TO OBJ'S SIBLING + BRA.S REMOX2 * AND EXIT + +REMOX1 ANDI.W #$00FF,D0 * CLEAR UNWANTED BYTE + BSR OBJLOC * FIND LOCATION OF CURRENT SIBLING + MOVE.B NEXT(A0),D0 * GET NEXT SIBLING IN CHAIN + CMP.B D0,D1 * IS IT OBJ? + BNE.S REMOX1 * NO, CONTINUE SEARCH + + MOVE.B NEXT(A1),NEXT(A0) * YES, CHANGE IT TO OBJ'S SIBLING +REMOX2 CLR.B LOC(A1) * OBJ NOW HAS NO PARENT + CLR.B NEXT(A1) * OR SIBLING +REMOX3 RTS + ENDC + +* LOC (RETURN CONTAINER OF OBJ) + +OPLOC BSR OBJLOC * FIND OBJ'S LOCATION + + IFEQ EZIP + MOVE.W LOC(A0),D0 * GET PARENT + ENDC + IFEQ CZIP + CLR.W D0 + MOVE.B LOC(A0),D0 * GET PARENT, CLEARING UNUSED BYTE + ENDC + BRA PUTVAL * RETURN THE VALUE + +* FIRST? (RETURN FIRST CHILD OF OBJ, FAIL IF NONE) + +OPQFIR BSR OBJLOC * FIND OBJ'S LOCATION + + IFEQ EZIP + MOVE.W FIRST(A0),D0 * GET FIRST CHILD + ENDC + IFEQ CZIP + CLR.W D0 + MOVE.B FIRST(A0),D0 * GET FIRST CHILD, CLEARING UNUSED BYTE + ENDC + MOVE.W D0,-(SP) + BSR PUTVAL * RETURN THE VALUE + TST.W (SP)+ * NONZERO? + BNE PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + +* NEXT? (RETURN THE NEXT SIBLING OF OBJ, FAIL IF NONE) + +OPQNEX BSR OBJLOC * FIND OBJ'S LOCATION + + IFEQ EZIP + MOVE.W NEXT(A0),D0 * GET SIBLING + ENDC + IFEQ CZIP + CLR.W D0 + MOVE.B NEXT(A0),D0 * GET SIBLING, CLEARING UNUSED BYTE + ENDC + MOVE.W D0,-(SP) + BSR PUTVAL * RETURN THE VALUE + TST.W (SP)+ * NONZERO? + BNE PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + +* IN? (IS OBJ1 CONTAINED IN OBJ2?) + +OPQIN BSR OBJLOC * FIND OBJ1'S LOCATION + + IFEQ EZIP + CMP.W LOC(A0),D1 * IS OBJ1'S PARENT OBJ2? + ENDC + IFEQ CZIP + CMP.B LOC(A0),D1 * IS OBJ1'S PARENT OBJ2? + ENDC + BEQ PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + +* GETP (GET SPECIFIED PROPERTY OF OBJ, DEFAULT IF NONE) + +OPGETP BSR OBJLOC * FIND OBJ'S LOCATION + BSR FSTPRP * GET POINTER TO FIRST PROPERTY + BRA.S GETPX2 * SKIP NEXT LINE FIRST TIME THROUGH LOOP + +GETPX1 BSR NXTPRP * POINT TO NEXT PROPERTY +GETPX2 MOVE.B (A0),D0 * GET PROPERTY IDENTIFIER + ANDI.W #PMASK,D0 * CLEAN OFF (EZIP MODE AND) LENGTH BITS + + CMP.W D1,D0 * COMPARE PROPERTY NUMBER WITH DESIRED ONE + BGT.S GETPX1 * IF GREATER, LOOP (TABLE SORTED IN REVERSE) + BLT.S GETPX3 * IF LESS, NO SUCH PROPERTY, USE DEFAULT + +* *** ASSUME NO 2ND EZIP LENGTH BYTE EXISTS HERE! *** + + BTST #PLBIT,(A0)+ * GOT IT, EXAMINE (LOW MODE OR) LOWEST LEN BIT + BNE.S GETPX4 * ONE MEANS WORD VALUE, OTHERWISE BYTE VALUE + + MOVE.B (A0),D0 * GET THE BYTE + BRA BYTVAL * AND RETURN IT + +GETPX3 SUBQ.W #1,D1 * PROPERTY NOT FOUND, USE DEFAULT PROP TABLE + ADD.W D1,D1 * WORD OFFSET + MOVE.L OBJTAB(A6),A0 * GET BASE OF DEFAULT TABLE + ADDA.W D1,A0 * POINT TO THE DEFAULT PROPERTY + +GETPX4 BSR GTAWRD * GET THE WORD VALUE + BRA PUTVAL * AND RETURN IT + +* PUTP (CHANGE VALUE OF SPECIFIED PROPERTY OF OBJ, ERROR IF BAD PROP NUMBER) + +OPPUTP BSR OBJLOC * FIND OBJ'S LOCATION + BSR FSTPRP * GET POINTER TO FIRST PROPERTY + BRA.S PUTPX2 * SKIP NEXT LINE FIRST TIME THROUGH LOOP + +PUTPX1 BSR NXTPRP * POINT TO NEXT PROPERTY +PUTPX2 MOVE.B (A0),D0 * GET PROPERTY IDENTIFIER + ANDI.W #PMASK,D0 * CLEAN OFF (EZIP MODE AND) LENGTH BITS + + CMP.W D1,D0 * COMPARE PROPERTY NUMBER WITH DESIRED ONE + BGT.S PUTPX1 * IF GREATER, LOOP (TABLE SORTED IN REVERSE) + BEQ.S PUTPX3 * IF EQUAL, GOT IT + + CLR.W D0 * OTHERWISE, FATAL ERROR + LEA MSGPUP,A0 + BRA FATAL * 'Non-existant put property' + + SECTION ZDATA +MSGPUP DC.B 'Non-existant put property',0 + SECTION ZCODE + +* *** ASSUME NO 2ND EZIP LENGTH BYTE EXISTS HERE! *** + +PUTPX3 BTST #PLBIT,(A0)+ * EXAMINE (LOW MODE OR) LOWEST LENGTH BIT + BNE.S PUTPX4 * ZERO MEANS BYTE VALUE, OTHERWISE WORD VALUE + + MOVE.B D2,(A0) * STORE THE NEW BYTE + RTS + +PUTPX4 MOVE.W D2,D0 + BRA PTAWRD * STORE THE NEW WORD + +* NEXTP (RETURN NUMBER OF NEXT PROP FOLLOWING GIVEN PROP IN OBJ) + +OPNEXT BSR OBJLOC * FIND OBJ'S LOCATION + BSR FSTPRP * GET POINTER TO FIRST PROPERTY + TST.W D1 * WERE WE GIVEN ZERO AS PROP? + BEQ.S NEXTX4 * YES, JUST RETURN FIRST PROPERTY NUMBER + BRA.S NEXTX2 * SKIP NEXT LINE FIRST TIME THROUGH LOOP + +NEXTX1 BSR NXTPRP * POINT TO NEXT PROPERTY +NEXTX2 MOVE.B (A0),D0 * GET PROPERTY IDENTIFIER + ANDI.W #PMASK,D0 * CLEAN OFF (EZIP MODE AND) LENGTH BITS + + CMP.W D1,D0 * COMPARE PROPERTY NUMBER WITH DESIRED ONE + BGT.S NEXTX1 * IF GREATER, LOOP (TABLE SORTED IN REVERSE) + BEQ.S NEXTX3 * IF EQUAL, GOT IT + + CLR.W D0 * OTHERWISE, FATAL ERROR + LEA MSGNXP,A0 + BRA FATAL * 'Non-existant next property' + + SECTION ZDATA +MSGNXP DC.B 'Non-existant next property',0 + SECTION ZCODE + +NEXTX3 BSR NXTPRP * POINT TO NEXT PROPERTY +NEXTX4 MOVE.B (A0),D0 * GET PROPERTY IDENTIFIER + ANDI.W #PMASK,D0 * EXTRACT PROPERTY NUMBER + BRA PUTVAL * AND RETURN IT + +* ----------------------------------------------------------------------------- +* PRIMITIVE TO LOCATE A FLAG BIT +* ----------------------------------------------------------------------------- + +* GIVEN A POINTER TO FIRST FLAGS BYTE IN A0, TARGET FLAG NUMBER (0-47) IN D0 +* RETURN POINTER TO TARGET FLAGS BYTE IN A0, TARGET BIT NUMBER (7-0) IN D0 + +FLGLOC MOVE.W D0,-(SP) + LSR.W #3,D0 * EXTRACT BYTE OFFSET + ADD.W D0,A0 * ADJUST FLAGS POINTER + + MOVE.W (SP)+,D0 + NOT.W D0 * FIX THE 3 LOW-ORDER BITS + ANDI.W #$0007,D0 * MASK OFF THE REST + RTS + +* ADDQ.L #1,A0 * POINT TO NEXT FLAGS BYTE +* SUBQ.W #8,D0 * WAS TARGET FLAG IN PREVIOUS BYTE? +* BGE.S FLGLOC * NO + +* SUBQ.L #1,A0 * YES, POINT TO PREVIOUS FLAGS BYTE +* NEG.W D0 * AND COMPUTE THE TARGET BIT NUMBER (7-0) +* SUBQ.W #1,D0 +* RTS + +* FSET? (IS FLAG SET IN OBJ?) + +OPQFSE BSR OBJLOC * FIND OBJ'S LOCATION + MOVE.W D1,D0 + BSR FLGLOC * DETERMINE PROPER FLAGS BYTE & BIT NUMBER + BTST D0,(A0) * IS THE SPECIFIED BIT SET? + BNE PTRUE * YES, PREDICATE TRUE + BRA PFALSE * NO, PREDICATE FALSE + +* FSET (SET A FLAG IN OBJ) + +OPFSET BSR OBJLOC * FIND OBJ'S LOCATION + MOVE.W D1,D0 + BSR FLGLOC * DETERMINE PROPER FLAGS BYTE & BIT NUMBER + BSET D0,(A0) * SET THE SPECIFIED BIT + RTS + +* FCLEAR (CLEAR A FLAG IN OBJ) + +OPFCLE BSR OBJLOC * FIND OBJ'S LOCATION + MOVE.W D1,D0 + BSR FLGLOC * DETERMINE PROPER FLAGS BYTE & BIT NUMBER + BCLR D0,(A0) * CLEAR THE SPECIFIED BIT + RTS + + + PAGE +* ---------------------------------------------------------------------------- +* TABLE OPERATIONS +* ---------------------------------------------------------------------------- + +* GET (GET THE ITEM'TH WORD FROM TABLE) +* BECAUSE WE ARE NOT NECESSARILY LOOKING AT PRELOADED STUFF, WE SPLIT +* THE POINTER AND GO THROUGH PAGING + +OPGET ASL.W #1,D1 * WORD OFFSET + ADD.W D1,D0 * INDEX INTO TABLE + BSR BSPLTB * SPLIT THE POINTER + BSR GETWRD * GET THE WORD + MOVE.W D2,D0 + BRA PUTVAL * AND RETURN IT + +* GETB (GET THE ITEM'TH BYTE FROM TABLE) + +OPGETB ADD.W D1,D0 * INDEX INTO TABLE + BSR BSPLTB * SPLIT THE POINTER + BSR GETBYT * GET THE BYTE + MOVE.W D2,D0 + BRA BYTVAL * AND RETURN IT + +* PUT (REPLACE THE ITEM'TH WORD IN TABLE) +* BY DEFINITION, PUT CAN AFFECT ONLY PRELOADED AND IMPURE DATA + +* A "TABLE" ARGUMENT IS A 16-BIT UNSIGNED BYTE POINTER, AND !MAY! +* IN SOME CASES EXCEED 32K. + +OPPUT ASL.W #1,D1 * WORD OFFSET + ADD.W D1,D0 * INDEX INTO TABLE + ANDI.L #$FFFF,D0 * ZERO THE HIGH WORD + MOVE.L D0,A0 + ADD.L BUFFER(A6),A0 * ABSOLUTIZE POINTER + MOVE.W D2,D0 + BRA PTAWRD * STORE THE WORD + +* PUTB (REPLACE THE ITEM'TH BYTE IN TABLE) + +OPPUTB ADD.W D1,D0 * INDEX INTO TABLE + ANDI.L #$FFFF,D0 * MAKE THE SUM A LONGWORD + MOVE.L BUFFER(A6),A0 + MOVE.B D2,0(A0,D0.L) * STORE THE BYTE + RTS + +* GETPT (GET POINTER TO PROPERTY TABLE FOR GIVEN OBJ, PROP) + +OPGTPT BSR OBJLOC * FIND OBJ'S LOCATION + BSR FSTPRP * GET POINTER TO FIRST PROPERTY + BRA.S GTPTX2 * SKIP NEXT LINE FIRST TIME THROUGH LOOP + +GTPTX1 BSR NXTPRP * POINT TO NEXT PROPERTY +GTPTX2 MOVE.B (A0),D0 * GET (FIRST) PROPERTY ID BYTE + ANDI.W #PMASK,D0 * CLEAN OFF MODE/LENGTH BITS + + CMP.W D1,D0 * COMPARE PROPERTY NUMBER WITH DESIRED ONE + BGT.S GTPTX1 * IF GREATER, LOOP (TABLE SORTED IN REVERSE) + BEQ.S GTPTX3 * IF EQUAL, GOT IT + + CLR.W D0 * OTHERWISE, RETURN ZERO FOR NO SUCH PROPERTY + BRA.S GTPTX5 + + IFEQ EZIP +GTPTX3 MOVE.B (A0)+,D0 * GET (FIRST) PROPERTY ID BYTE + BTST #7,D0 * IS THERE A SECOND LENGTH BYTE? + BEQ.S GTPTX4 * NO + ADDQ.L #1,A0 * YES, SKIP IT TOO + ENDC + IFEQ CZIP + +GTPTX3 ADDQ.L #1,A0 * POINT TO PROPERTY VALUE + ENDC + +GTPTX4 MOVE.L A0,D0 + SUB.L BUFFER(A6),D0 * RE-RELATIVIZE POINTER +GTPTX5 BRA PUTVAL * AND RETURN IT + +* PTSIZE (GIVEN POINTER TO PROPERTY TABLE, RETURN ITS SIZE) + +OPPTSI MOVE.L BUFFER(A6),A0 + ANDI.L #$FFFF,D0 * MAKE THE TABLE PTR A LONGWORD + ADDA.L D0,A0 * ABSOLUTIZE THE TABLE POINTER + + IFEQ EZIP + MOVE.B -1(A0),D0 * GET MODE/ID BYTE OR LEN BYTE (EITHER WORKS!) + BTST #7,D0 * PROPERTY LENGTH GREATER THAN 2? + BNE.S PTSIX4 * YES + + BTST #6,D0 * NO, PROPERTY LENGTH 2? + BNE.S PTSIX2 * YES + MOVEQ #1,D0 * NO, PROPERTY LENGTH IS 1 + BRA PUTVAL * RETURN IT + +PTSIX2 MOVEQ #2,D0 + BRA PUTVAL * RETURN IT + +PTSIX4 ANDI.W #PMASK,D0 * LENGTH IS LOW 6 BITS + BRA PUTVAL * RETURN IT + ENDC + IFEQ CZIP + CLR.W D0 + MOVE.B -1(A0),D0 * GET THE PROP IDENTIFIER BYTE + ASR.W #5,D0 * EXTRACT LENGTH BITS + ADDQ.W #1,D0 * ADJUST TO ACTUAL LENGTH + BRA PUTVAL * RETURN IT + ENDC + + IFEQ EZIP + +* INTBL? (IS ANY IN TABLE OF LENGTH INT?) + +OPINTBL NOP * USE ARGBLOCK + MOVE.W ARG2(A0),D0 * RELATIVE BYTE ADDRESS OF TABLE + BSR BSPLTB * SPLIT IT + MOVE.W ARG1(A0),D3 * VALUE TO SEARCH FOR (WORD) + MOVE.W ARG3(A0),D4 * LENGTH OF TABLE (WORDS) + +ITBX1 BSR GETWRD * GET NEXT TABLE ITEM IN D2 + CMP.W D2,D3 * MATCH? + BEQ.S ITBX2 * YES + SUBQ.W #1,D4 * END OF TABLE? + BGT ITBX1 * NO, CONTINUE SEARCH + + CLR.W D0 * FAILED, RETURN ZERO + BSR PUTVAL + BRA PFALSE * PREDICATE FALSE + +ITBX2 ASL.W #8,D0 * SUCCESS, UNSPLIT THE POINTER + ASL.W #1,D0 + ADD.W D1,D0 + SUBQ.W #2,D0 * BACK UP TWO BYTES, SINCE GETWRD ADVANCES + BSR PUTVAL * RETURN THE RELATIVE POINTER + BRA PTRUE * PREDICATE TRUE + + ENDC + IFEQ CZIP +OPINTBL BRA OPERR * THIS FUNCTION UNDEFINED IN ZIP + ENDC + + PAGE +* ---------------------------------------------------------------------------- +* VARIABLE OPERATIONS +* ---------------------------------------------------------------------------- + +* VALUE (GET VALUE OF VARIABLE) + +OPVALU BSR GETVAR * GET THE VALUE + BRA PUTVAL * AND RETURN IT + +* SET (VAR TO VALUE) + +OPSET BRA PUTVAR * STORE THE VALUE + +* PUSH (A VALUE ONTO THE GAME STACK) + +OPPUSH MOVE.W D0,-(A4) * PUSH THE VALUE + RTS + +* POP (A VALUE OFF THE GAME STACK INTO VAR) + +OPPOP MOVE.W (A4)+,D1 * POP A VALUE + BRA PUTVAR * AND STORE IT + +* INC (INCREMENT VAR) + +OPINC MOVE.W D0,D1 * SAVE A COPY HERE + BSR GETVAR * GET THE VARIABLE'S VALUE + ADDQ.W #1,D0 * INCREMENT IT + EXG D0,D1 * POSITION IT + BRA PUTVAR * AND STORE THE NEW VALUE + +* DEC (DECREMENT VAR) + +OPDEC MOVE.W D0,D1 * SAVE A COPY HERE + BSR GETVAR * GET THE VARIABLE'S VALUE + SUBQ.W #1,D0 * DECREMENT IT + EXG D0,D1 * POSITION IT + BRA PUTVAR * AND STORE NEW VALUE + +* IGRTR? (INCREMENT VAR & TEST IF GREATER THAN VAL) + +OPQIGR MOVE.W D1,D2 * MOVE VAL HERE + MOVE.W D0,D1 * COPY VAR HERE + BSR GETVAR * GET THE VARIABLE'S VALUE + ADDQ.W #1,D0 * INCREMENT IT + EXG D0,D1 * POSITION IT + + CMP.W D2,D1 * NEW VALUE GREATER THAN VAL? + BGT.S QIG2 * YES +QIG1 BSR PUTVAR * NO, STORE THE NEW VALUE + BRA PFALSE * AND RETURN PREDICATE FALSE + +QIG2 BSR PUTVAR * STORE THE NEW VALUE + BRA PTRUE * AND RETURN PREDICATE TRUE + +* DLESS? (DECREMENT VAR & TEST IF LESS THAN VAL) + +OPQDLE MOVE.W D1,D2 * MOVE VAL HERE + MOVE.W D0,D1 * COPY VAR HERE + BSR GETVAR * GET THE VARIABLE'S VALUE + SUBQ.W #1,D0 * DECREMENT IT + EXG D0,D1 * POSITION IT + + CMP.W D2,D1 * NEW VALUE LESS THAN VAL? + BLT.S QIG2 * YES + BRA.S QIG1 * NO + + +* --------------------------------------------------------------------------- +* I/O OPERATIONS -- INPUT +* --------------------------------------------------------------------------- + +* READ (A LINE OF INPUT AND TOKENIZE IT) + +OPREAD NOP * USE AN ARGUMENT BLOCK + + MOVEQ #0,D0 + MOVE.W ARG1(A0),D0 * INPUT BUFFER POINTER + ADD.L BUFFER(A6),D0 * ABSOLUTIZE IT + MOVE.L D0,RDBOS(A6) * SAVE IT + + MOVEQ #0,D1 + MOVE.W ARG2(A0),D1 * RETURN BUFFER POINTER + ADD.L BUFFER(A6),D1 * ABSOLUTIZE IT + MOVE.L D1,RDRET(A6) * SAVE IT + + IFEQ CZIP + BSR OPUSL * UPDATE STATUS LINE + ENDC + +*** GATHER THE INPUT LINE ... + +** JSR RESETMORE * PREVENT AN UNNEEDED **MORE** + + IFEQ DEBUG + MOVE.L DBTOT1(A6),D0 * TOTAL PAGE FAULTS + BSR OPPRNN * SHOW USER (LOW WORD ONLY) + MOVE.B #'>',D0 + BSR OPPRNC + ENDC + + MOVE.W #1,LINES(A6) * RESET COUNTER, PREVENTS A DEGENERATE [MORE] + BSR PUTLIN * THEN FORCE OUT ANY QUEUED TEXT (THE PROMPT) + + MOVE.L RDBOS(A6),A0 * BEGINNING OF INPUT LINE BUFFER + CLR.W D0 + MOVE.B (A0)+,D0 * BUFFER LENGTH (MAX CHARACTERS TO GET) + +* LIMIT USER INPUT TO ONE LINE MAX (TO AVOID SCROLLING THE STATUS LINE) + + MOVE.W _columns,D1 + SUBQ.W #1,D1 * ALLOW FOR PROMPT (>) IN FIRST COLUMN + CMP.W D0,D1 * LESS THAN BUFFER SIZE? + BGE.S RDX0 * NO + MOVE.W D1,D0 * YES, USE THE SMALLER VALUE + +RDX0 MOVEQ #1,D1 * REQUEST LOWER-CASE CONVERSIONS + MOVE.L A0,-(SP) + BSR RDLINE + + MOVE.L (SP)+,A0 + ADDA.W D0,A0 * END OF CURRENT INPUT LINE + MOVE.L A0,RDEOS(A6) * SAVE IT + +*** WORDIFY THE INPUT LINE ... + + MOVE.L A4,-(SP) * SAVE THE GAME SP + MOVE.L RDBOS(A6),A2 + ADDQ.L #1,A2 * START OF INPUT BUFFER, SKIP LENGTH BYTE + + MOVE.L RDRET(A6),A4 + ADDQ.L #2,A4 * RETURN BUFFER, SKIP MAX WORDS AND NWORDS + CLR.B RDNWDS(A6) * NO WORDS FOUND INITIALLY + +RDX1 LEA RDWSTR(A6),A3 * HERE FOR NEXT WORD, POINT TO EMPTY BUFFER + MOVE.L A2,RDBOW(A6) * BEGINNING OF NEXT WORD + +RDX2 CMPA.L RDEOS(A6),A2 * END OF INPUT STRING? + BNE.S RDX3 * NO + LEA RDWSTR(A6),A0 * YES, GET WORD STRING POINTER + CMPA.L A3,A0 * WAS A WORD FOUND? + BEQ RDX10 * NO, WE'RE DONE + BRA.S RDX8 * YES, MUST STILL LOOKUP WORD + +RDX3 MOVE.B (A2)+,D0 * GET NEXT CHAR FROM INPUT BUFFER + MOVE.L RBRKS(A6),A1 * POINTER, LIST OF READ-BREAK CHARACTERS + +RDX4 CMP.B (A1)+,D0 * SEARCH LIST FOR THIS ONE + BEQ.S RDX5 * FOUND IT + TST.B (A1) * END OF LIST? + BNE.S RDX4 * NO, CONTINUE SEARCH + + LEA RDWSTR(A6),A0 * IT'S NOT A BREAK CHAR + ADDA.W #VCHARS,A0 * END OF WORD STRING BUFFER (ZIP OR EZIP) + CMPA.L A0,A3 * FULL YET? + BEQ.S RDX2 * YES, FLUSH CHAR & LOOP UNTIL BREAK IS FOUND + MOVE.B D0,(A3)+ * NO, TACK THIS CHAR ONTO STRING + BRA.S RDX2 * AND LOOP FOR NEXT + +*** BREAK CHAR FOUND ... + +RDX5 LEA RDWSTR(A6),A0 + CMPA.L A3,A0 * WORD READ BEFORE THIS BREAK? + BNE.S RDX7 * YES, GO FOR IT + CMPA.L ESIBKS(A6),A1 * NO, BUT WAS THIS A SELF-INSERTING BREAK? + BHI.S RDX1 * NO, GO FOR NEXT WORD + + MOVE.B D0,(A3)+ * YES, STORE THE BREAK IN WORD STRING + BRA.S RDX8 * AND GO FOR THE ZWORD + +RDX7 SUBQ.L #1,A2 * UNREAD TERMINATING BREAK IN CASE IT WAS SI +RDX8 ADDQ.B #1,RDNWDS(A6) * INCREMENT FOUND WORD COUNT + MOVE.B RDNWDS(A6),D0 * GET NEW COUNT + + MOVE.L RDRET(A6),A0 * RETURN TABLE POINTER (1ST BYTE MAX WORDS) + CMP.B (A0),D0 * FOUND WORD COUNT GREATER THAN MAX ALLOWED? + BLE.S RDX9 * NO + + BSR PUTNEW * YES, INFORM LOSER + LEA MSGIO1,A0 + BSR OUTMSG0 * '[Too many words ...' + + SECTION ZDATA +MSGIO1 DC.B '[Too many words typed, discarding "',0 + SECTION ZCODE + + MOVE.L RDEOS(A6),A1 * END OF INPUT STRING (+1) + MOVE.B (A1),-(SP) * SAVE THIS BYTE TO BE SAFE + CLR.B (A1) * MAKE STRING ASCIZ + + MOVE.L RDBOW(A6),A0 * START OF FLUSHED WORD/STRING + BSR OUTMSG0 * ECHO IT + MOVE.B (SP)+,(A1) * RESTORE LAST BYTE + + LEA MSGIO2,A0 + BSR OUTMSG * '."]' + + SECTION ZDATA +MSGIO2 DC.B '."]',0 + SECTION ZCODE + + BSR PUTNEW + SUBQ.B #1,RDNWDS(A6) * THE LATEST WORD IS FLUSHED + BRA RDX10 * AND WE'RE DONE + +*** BUILD THE ZWORD TABLE ... + +RDX9 MOVE.L A2,D0 * CALCULATE NUMBER OF CHARS IN CURRENT WORD + SUB.L RDBOW(A6),D0 + MOVE.B D0,2(A4) * STORE THE NUMBER IN RETURN TABLE + + MOVE.L RDBOW(A6),D0 * CALCULATE BYTE OFFSET OF BEGINNING OF WORD + SUB.L RDBOS(A6),D0 + MOVE.B D0,3(A4) * STORE THAT NUMBER TOO + + CLR.B (A3) * MAKE WORD STRING ASCIZ + LEA RDWSTR(A6),A1 + LEA RDZSTR(A6),A0 + BSR ZWORD * AND CONVERT TO (2 OR 3 WORD) ZWORD + + LEA RDZSTR(A6),A0 + BSR LOOKUP * SEARCH VOCAB TABLE FOR ZWORD, RETURN OFFSET + + MOVE.L A4,A0 * CURRENT RETURN TABLE SLOT + BSR PTAWRD * STORE THE OFFSET + ADDQ.L #4,A4 * UPDATE THE TABLE POINTER FOR NEXT WORD + BRA RDX1 * GO FOR IT + +RDX10 MOVE.L RDRET(A6),A0 * DONE, GET RETURN TABLE POINTER + MOVE.B RDNWDS(A6),1(A0) * STORE THE NUMBER OF WORDS FOUND + + MOVE.L (SP)+,A4 * RESTORE THE GAME SP + RTS + +* --------------------------------------------------------------------------- +* READ PRIMITIVES +* --------------------------------------------------------------------------- + +* GATHER A LINE OF INPUT, BUFFER IN A0, BUFFER LENGTH IN D0 +* IF D1 IS NON-ZERO, CONVERT ALL UPPERCASE LETTERS TO LOWER CASE +* RETURN LENGTH OF INPUT IN D0 + +EOLCHR EQU $0D * CARRIAGE RETURN IS END-OF-LINE +DELCHR EQU $08 * BACKSPACE IS DELETE + +RDLINE MOVEM.L A1-A3,-(SP) + CLR.W CHRTOT(A6) * INIT COUNT OF CHARS READ (FOR BACKSPACE) + + MOVE.L A0,A1 * START OF BUFFER IN A1 + MOVE.L A1,A2 * KEEP CURRENT BUFFER POINTER IN A2 + MOVE.L A2,A3 + ADDA.W D0,A3 * END OF BUFFER (+1) IN A3 + + BSR UNHIDE * AMIGA: MAKE SURE GAME-SCREEN IS IN FRONT + +RDLX1 BSR GETCHR * INPUT A CHARACTER +RDLX2 CMPI.B #EOLCHR,D0 * END OF LINE? + BEQ.S RDLX6 * YES + + CMPI.B #DELCHR,D0 * BACKSPACE? + BNE.S RDLX3 * NO, NORMAL CHAR + + CMPA.L A1,A2 * YES, ANYTHING TO DELETE? + BEQ RDLX1 * NO, JUST LOOP + + SUBQ.L #1,A2 * YES, BACK UP BUFFER POINTER + SUBQ.W #1,CHRTOT(A6) * AND DECREASE COUNTER + BRA.S RDLX1 + +RDLX3 MOVE.B D0,(A2)+ * STORE CHAR + ADDQ.W #1,CHRTOT(A6) * AND BUMP CHAR COUNTER + + CMPA.L A3,A2 * BUFFER FULL YET? + BLT RDLX1 * NO, LOOP UNTIL EOL + +* BUFFER FULL, WAIT FOR CR OR BS ... + + CLR.W VIECHO(A6) * TURN OFF ECHO TEMPORARILY +RDLX4 BSR GETCHR * GET A CHAR + + CMPI.B #EOLCHR,D0 * END OF LINE? + BEQ.S RDLX5 * YES + CMPI.B #DELCHR,D0 * BACKSPACE? + BEQ.S RDLX5 * YES + + MOVEQ #2,D0 * BOOP AT USER + BSR DOSOUND + BRA.S RDLX4 * REJECT EVERYTHING ELSE, JUST WAIT + +RDLX5 MOVE.W D0,-(SP) + BSR TTYOUT * GOT CR OR BACKSPACE, NOW ECHO IT + MOVE.W (SP)+,D0 + + MOVE.W #1,VIECHO(A6) * RESTORE NORMAL ECHO + BRA RDLX2 * AND HANDLE THE CHAR + +* END OF INPUT, SCRIPT IT ** THEN ** CHECK FOR LOWER CASE + +RDLX6 MOVE.L A1,A0 * SCRIPT THE INPUT LINE IF REQUIRED + MOVE.L A2,D0 + BSR SCRINP + + BSR RESIZE * CHECK IF WINDOW SIZE WAS CHANGED + + TST.W D1 * WERE LOWER-CASE CONVERSIONS REQUESTED? + BEQ.S RDLX9 * NO + MOVE.L A1,A0 * YES, BUFFER STARTS HERE + +RDLX7 CMPA.L A2,A0 * ANY MORE CHARS IN BUFFER? + BGE.S RDLX9 * NO + MOVE.B (A0),D0 * YES, GET NEXT + + CMPI.B #'A',D0 * UPPERCASE CHAR? + BLT.S RDLX8 * NO + CMPI.B #'Z',D0 + BGT.S RDLX8 * NO + + ADDI.B #32,D0 * YES, LOWERCASIFY IT +RDLX8 MOVE.B D0,(A0)+ * STORE AND ADVANCE + BRA.S RDLX7 + +RDLX9 MOVE.L A2,D0 + SUB.L A1,D0 * RETURN LENGTH OF INPUT + MOVEM.L (SP)+,A1-A3 + RTS + + +* SEARCH VOCAB TABLE FOR A ZWORD, POINTER TO ZWORD IN A0 +* RETURN ZWORD'S TABLE OFFSET (RELATIVIZED) IN D0.W, NULL IF NOT FOUND + +* NEW APPROACH: USE PAGING CALLS, SO THAT VOCAB TABLE MAY BE NON-PRELOADED +* VOCBEG(A6) AND VOCEND(A6) ARE NOW RELATIVE POINTERS + +LOOKUP MOVEM.L D1-D3/A1-A2,-(SP) + MOVE.L A0,A1 * SAVE POINTER TO GIVEN ZWORD HERE + + MOVE.W VWORDS(A6),D0 * NUMBER OF VOCABULARY WORDS + MOVE.W VWLEN(A6),D3 * NUMBER OF BYTES PER VOCAB ENTRY + + ASR.W #1,D0 +LKX2 ASL.W #1,D3 * CALCULATE INITIAL OFFSET FOR BINARY SEARCH + ASR.W #1,D0 + BNE.S LKX2 + + MOVE.L VOCBEG(A6),A2 * (RELATIVE) BEGINNING OF VOCAB WORD TABLE + ADDA.W D3,A2 * ADD INITIAL OFFSET + SUBA.W VWLEN(A6),A2 * AVOID FENCE-POST BUG FOR EXACT-POWER-OF-2 TABLE + +LKX4 ASR.W #1,D3 * NEXT OFFSET WILL BE HALF OF PREVIOUS ONE + MOVE.W A2,D0 + BSR BSPLTB * COMPUTE BLOCK AND BYTE OFFSET IN D0/D1 + + BSR GETWRD * GET FIRST WORD FROM VOCAB TABLE IN D2 + CMP.W (A1),D2 * COMPARE IT TO DESIRED ONE + BCS.S LKX6 * BLO * LESS, WE'LL HAVE TO MOVE UP + BHI.S LKX8 * GREATER, WE'LL HAVE TO MOVE DOWN + + BSR GETWRD * SAME, GET SECOND WORD + CMP.W 2(A1),D2 * COMPARE IT TO DESIRED ONE + BCS.S LKX6 * BLO * LESS, WE'LL HAVE TO MOVE UP + BHI.S LKX8 * GREATER, WE'LL HAVE TO MOVE DOWN + + IFEQ EZIP + BSR GETWRD * SAME, GET THIRD WORD + CMP.W 4(A1),D2 * COMPARE IT TO DESIRED ONE + BCS.S LKX6 * BLO * LESS, WE'LL HAVE TO MOVE UP + BHI.S LKX8 * GREATER, WE'LL HAVE TO MOVE DOWN + ENDC + MOVE.W A2,D0 * SAME, WE'VE FOUND IT, RETURN IT + BRA.S LKX12 + +LKX6 ADDA.W D3,A2 * TO MOVE UP, ADD OFFSET + CMPA.L VOCEND(A6),A2 * HAVE WE MOVED PAST END OF TABLE? + BLS.S LKX10 * NO + MOVE.L VOCEND(A6),A2 * YES, POINT TO END OF TABLE + BRA.S LKX10 + +LKX8 SUBA.W D3,A2 * TO MOVE DOWN, JUST SUBTRACT OFFSET +LKX10 CMP.W VWLEN(A6),D3 * IS OFFSET RESOLUTION AT LEAST ONE WORD? + BGE LKX4 * YES, CONTINUE LOOP + CLR.W D0 * NO, WORD NOT FOUND, SO RETURN ZERO + +LKX12 MOVEM.L (SP)+,D1-D3/A1-A2 + RTS + + + PAGE + + IFEQ EZIP +OPUSL BRA OPERR * NOT AN INSTRUCTION + + ENDC + IFEQ CZIP + +* --------------------------------------------------------------------------- +* STATUS LINE EQUATES +* --------------------------------------------------------------------------- + +MOVVAR EQU 18 * NUMBER-OF-MOVES GLOBAL +SCRVAR EQU 17 * SCORE VARIABLE +RMVAR EQU 16 * CURRENT ROOM VARIABLE + + SECTION ZDATA +ZSCORE DC.B 'Score: ',0 +ZTIME DC.B 'Time: ',0 + SECTION ZCODE + +* --------------------------------------------------------------------------- +* STATUS LINE PRIMITIVES +* --------------------------------------------------------------------------- + +* STATUS LINE OUTPUT FUNCTION -- QUEUE THE CHARACTER IN D0 +* (CALLED THROUGH OPPRND AND OPPRNN) + +PUTSL MOVE.L SLPTR(A6),A0 * GET CURRENT SL POSITION + MOVE.B D0,(A0)+ * QUEUE THE CHAR + MOVE.L A0,SLPTR(A6) * UPDATE CURRENT SL POSITION + RTS + +* GIVEN A ASCIZ POINTER IN A1, QUEUE THE STRING IN THE STATUS LINE + +QSTR1 BSR PUTSL * QUEUE A CHAR +QSTR MOVE.B (A1)+,D0 * GET NEXT CHARACTER, END OF STRING? + BNE.S QSTR1 * NO + RTS + +* USL (UPDATE STATUS LINE) (DESTROYS REGISTERS) + +OPUSL MOVE.W #1,VOSTAT(A6) * SWITCH ALL OUTPUT TO STATUS LINE + + SUBA.W #256,SP * CREATE A TEMP BUFFER FOR SL + MOVE.L SP,LOCPTR(A6) * LOCATION STRING STARTS HERE + MOVE.L SP,SLPTR(A6) * INIT OUTPUT POINTER + + MOVE.B #' ',D0 + BSR PUTSL * INDENT BY ONE SPACE + + MOVEQ #RMVAR,D0 + BSR GETVAR * GET CURRENT ROOM + BSR OPPRND * QUEUE ITS SHORT DESCRIPTION + +* QUEUE THE SCORE/TIME STRING ... + + MOVE.L SLPTR(A6),SCOPTR(A6) * SCORE STRING STARTS HERE + + TST.W TIMEMD(A6) * ARE WE IN TIME MODE? + BNE.S USLX2 * YES + + LEA ZSCORE,A1 * NO, SCORE MODE + BSR QSTR * QUEUE "SCORE" + MOVEQ #SCRVAR,D0 + BSR GETVAR * GET THE SCORE + BSR OPPRNN * AND QUEUE IT + + MOVE.B #'/',D0 + BSR PUTSL * QUEUE A SEPARATOR (/) + + MOVEQ #MOVVAR,D0 + BSR GETVAR * GET THE NUMBER OF MOVES + BSR OPPRNN * AND QUEUE IT + BRA.S USLX6 + +USLX2 LEA ZTIME,A1 + BSR QSTR * QUEUE "TIME" + + MOVEQ #SCRVAR,D0 + BSR GETVAR * GET HOUR + MOVE.B #'a',D2 * ASSUME AM + CMPI.W #12,D0 * PM? + BLT.S USLX4 * NO + BEQ.S USLX3 * YES, BUT 12 PM IS SPECIAL + SUBI.W #12,D0 * CONVERT TO 12-HOUR TIME + +USLX3 MOVE.B #'p',D2 * CHANGE OUR EARLIER ASSUMPTION TO PM +USLX4 TST.W D0 * BUT 00 SHOULD BE 12 AM + BNE.S USLX5 + MOVEQ #12,D0 +USLX5 MOVE.W D2,-(SP) * PROTECT AM/PM INDICATOR + BSR OPPRNN * QUEUE THE HOUR + MOVE.B #':',D0 + BSR PUTSL * QUEUE A SEPARATOR (:) + MOVEQ #MOVVAR,D0 + BSR GETVAR * GET MINUTES + EXT.L D0 + DIVU #10,D0 * OUTPUT MINUTES IN TWO DIGITS + MOVE.L D0,-(SP) * SAVE SECOND DIGIT (REMAINDER) + ADDI.B #'0',D0 + BSR PUTSL * QUEUE FIRST DIGIT (QUOTIENT) + MOVE.L (SP)+,D0 + SWAP D0 * RESTORE SECOND DIGIT + ADDI.B #'0',D0 + BSR PUTSL * QUEUE SECOND DIGIT + MOVEQ #32,D0 + BSR PUTSL * SPACE + MOVE.W (SP)+,D0 + BSR PUTSL * AM OR PM + MOVE.B #'m',D0 + BSR PUTSL + +USLX6 MOVE.B #' ',D0 + BSR PUTSL * END SCORE/TIME WITH ONE BLANK SPACE + +*** DISPLAY THE STRINGS, POINTERS IN A0-A1, LENGTHS IN D0-D1 + + MOVE.L LOCPTR(A6),A0 + MOVE.L SCOPTR(A6),A1 + MOVE.L A1,D0 + MOVE.L SLPTR(A6),D1 + + SUB.L A0,D0 * LENGTH OF LOCATION STRING + SUB.L A1,D1 * LENGTH OF SCORE STRING + BSR STLINE * GO DIRECTLY TO SCREEN DISPLAY + + ADDA.W #256,SP * FLUSH THE TEMP BUFFER + CLR.W VOSTAT(A6) * TURN OFF STATUS LINE OUTPUT + RTS + + ENDC + + + PAGE +* --------------------------------------------------------------------------- +* I/O OPERATIONS -- OUTPUT +* --------------------------------------------------------------------------- + +* PRINTC (PRINT CHAR WHOSE ASCII VALUE IS GIVEN) + +OPPRNC BRA PUTCHR * HANDLE IT + +* PRINTN (PRINT A NUMBER, USING CURRENT CHARACTER OUTPUT FUNCTION) + +OPPRNN MOVE.W D0,D1 * NON-ZERO NUMBER? + BNE.S PRNNX1 * YES + MOVE.B #'0',D0 * ZERO, SPECIAL CASE + BRA PUTCHR * PRINT A ZERO + +PRNNX1 BGT.S PRNNX2 * POSITIVE? + MOVE.B #'-',D0 * NO, PRINT A MINUS SIGN + BSR PUTCHR + NEG.W D1 * AND MAKE NUMBER POSITIVE + +PRNNX2 CLR.W D2 * COUNT OF DIGITS ON STACK + BRA.S PRNNX4 * START WITH GREATER-THAN-10 TEST + +PRNNX3 EXT.L D1 * CLEAR HIGH WORD FOR DIVISION + DIVU #10,D1 * EXTRACT A DIGIT (THE REMAINDER) + SWAP D1 + MOVE.W D1,-(SP) * PUSH IT + SWAP D1 + ADDQ.W #1,D2 * BUMP COUNT + +PRNNX4 CMPI.W #10,D1 * ANY MORE DIGITS TO EXTRACT? + BGE PRNNX3 * YES + MOVE.W D1,D0 * NO, POSITION LAST (FIRST) DIGIT + BRA.S PRNNX6 + +PRNNX5 MOVE.W (SP)+,D0 * POP NEXT DIGIT +PRNNX6 ADDI.B #'0',D0 * ASCIIZE IT + BSR PUTCHR * PRINT NEXT DIGIT + SUBQ.W #1,D2 * ANY DIGITS LEFT ON STACK? + BGE PRNNX5 * YES + RTS + +* PRINT (THE STRING POINTED TO) + + IFEQ EZIP +OPPRIN BSR BSPLTQ * SPLIT THE BLOCK AND OFFSET (QUAD) + ENDC + IFEQ CZIP +OPPRIN BSR BSPLIT * SPLIT THE BLOCK AND OFFSET (WORD) + ENDC + BRA PUTSTR * PRINT THE STRING + +* PRINTB (THE STRING POINTED TO) + +OPPRNB BSR BSPLTB * SPLIT THE BLOCK AND OFFSET (BYTE) + BRA PUTSTR * PRINT THE STRING + +* PRINTD (PRINT OBJ'S SHORT DESCRIPTION) + +OPPRND BSR OBJLOC * FIND OBJECT'S LOCATION + ADDA.W #PROP,A0 * PROPERTY TABLE POINTER (ZIP/EZIP) + BSR GTAWRD * GET IT + + ADDQ.W #1,D0 * POINT TO SHORT DESCRIPTION STRING + BSR BSPLTB * SPLIT THE POINTER + BRA PUTSTR * AND PRINT THE STRING + +* PRINTI (PRINT THE STRING FOLLOWING THIS INSTRUCTION) + +OPPRNI MOVE.W ZPC1(A6),D0 * GET POINTER TO STRING + MOVE.W ZPC2(A6),D1 + BSR PUTSTR * PRINT IT + MOVE.W D0,ZPC1(A6) * AND UPDATE ZPC + MOVE.W D1,ZPC2(A6) + BRA NEWZPC + +* PRINTR (PRINTI FOLLOWED BY RTRUE) + +OPPRNR BSR OPPRNI * DO A PRINTI + BSR OPCRLF * A CRLF + BRA OPRTRU * AND AN RTRUE + +* CRLF (DO A NEWLINE) + +OPCRLF BRA PUTNEW * DO A NEWLINE + + + PAGE +* --------------------------------------------------------------------------- +* MORE ZIP I/O +* --------------------------------------------------------------------------- + +* SPLIT/UNSPLIT THE SCREEN + +OPSPLT + + IFEQ CZIP + ADDQ.W #1,D0 * ALLOW ROOM FOR STATUS LINE + ENDC + +* MOVE.W _split_row,D1 * GET OLD VALUE + MOVE.W D0,_split_row * RESET SPLIT POINT + +* *** AUTO-CLEARING FUNCTION HAS BEEN REMOVED FROM EZIP SPEC ... + +* CMP.W D1,D0 * IS WINDOW 1 GROWING? +* BLE SPLTX1 * NO, DO NOT CLEAR + + IFEQ CZIP + +* ALWAYS CLEAR WINDOW 1 (ZIP ONLY!) + + MOVE.L D0,-(SP) * LAST ROW TO CLEAR (+1) + MOVEQ #1,D1 + MOVE.L D1,-(SP) * FIRST ROW, ALLOW FOR STATUS LINE + JSR _clear_lines + ADDQ.W #8,SP * FLUSH STACK (4 ACTUAL) + ENDC + +SPLTX1 RTS + +* MAKE OUTPUT FALL INTO SPECIFIED WINDOW + +OPSCRN TST.W D0 * OUTPUT TO WINDOW 0? + BEQ.S SCRNX1 * YES + CMPI.W #1,D0 * OUTPUT TO WINDOW 1? + BEQ.S SCRNX2 * YES + BRA.S SCRNX5 * INVALID ARG, DO NOTHING + +* MOVE CURSOR INTO WINDOW 0, RESTORE OLD CURSOR POSITION + +SCRNX1 TST.W WIND1(A6) * ALREADY IN WINDOW 0? + BEQ.S SCRNX5 * YES, DO NOTHING + + CLR.W WIND1(A6) * NO + MOVE.W OLDWY(A6),D0 * ROW TO RESTORE + MOVE.W OLDWX(A6),D1 * COLUMN TO RESTORE + BRA.S SCRNX4 + +* MOVE CURSOR INTO WINDOW 1, SAVE OLD CURSOR POSITION IF REQUIRED + +SCRNX2 TST.W WIND1(A6) * ALREADY IN WINDOW 1? + BNE.S SCRNX3 * YES + + MOVE.W #1,WIND1(A6) * NO, MUST SAVE OLD POSITION + BSR GETCUR + + MOVE.W D0,OLDWY(A6) * REMEMBER OLD ROW + MOVE.W D1,OLDWX(A6) * REMEMBER OLD COLUMN + +SCRNX3 CLR.W D0 * MOVE CURSOR TO TOP LEFT + CLR.W D1 + + IFEQ CZIP + ADD.W #1,D0 * ALLOW FOR STATUS LINE + ENDC + +SCRNX4 BSR SETCUR * UPDATE CURSOR POSITION +SCRNX5 RTS + +* --------------------------------------------------------------------------- +* TIMEOUT PRIMITIVES +* --------------------------------------------------------------------------- + +* RESET THE TIMEOUT COUNTER + +TRESET BSR TIME60 * GET A REFERENCE TIME (IN 60THS) + MOVE.L D0,TBEGIN(A6) * SAVE IT + RTS + +* RETURN THE TIME REMAINING BEFORE NEXT TIMEOUT (ZERO/NEGATIVE IF NONE) + +TCHECK BSR TIME60 * YES, GET CURRENT TIME (IN 60THS) + SUB.L TBEGIN(A6),D0 * THIS IS CURRENT DELAY + DIVU #6,D0 * SWITCH TO 10THS + SUB.W TDELAY(A6),D0 * CALCULATE THE TIME REMAINING + NEG.W D0 + RTS + +* --------------------------------------------------------------------------- +* EZIP I/O +* --------------------------------------------------------------------------- + + IFEQ EZIP + +* SET BUFFERING OF OUTPUT ACCORDING TO INT + +OPBUFO SUBQ.W #1,D0 * NORMAL BUFFERING? + BEQ.S BUFOX1 * YES + ADDQ.W #1,D0 * NO BUFFERING, OUTPUT DIRECTLY TO SCREEN? + BEQ.S BUFOX2 * YES + BRA.S BUFOX3 * ELSE DO NOTHING + +BUFOX1 MOVE.W #1,VOBUFF(A6) * TURN ON BUFFERING + BRA.S BUFOX3 + +* NOTE: IF OUTPUT IS GOING INTO MAIN WINDOW (WINDOW 0), MUST EMPTY THE +* BUFFER WITHOUT CHANGING THE BUFFER COUNTER. + +* IF OUTPUT IS GOING INTO THE SPLIT SCREEN (WINDOW 1), ** NO ** BUFFER +* ACTIVITY (EMPTYING OR ADDING, SEE ALSO QUECHR) SHOULD CHANGE THE COUNTER. + +BUFOX2 +* TST.W WIND1(A6) * ARE WE IN WINDOW 1? *** DEAD, SEE QUECHR +* BEQ.S BUFX2A * NO +* BSR PUTLIN * YES, FIRST EMPTY THE CURRENT OUTPUT BUFFER +* BRA.S BUFX2B * (AND ** DO ** RESET THE COUNTER) + +BUFX2A BSR PUTLIN1 * FIRST EMPTY THE CURRENT OUTPUT BUFFER +BUFX2B CLR.W VOBUFF(A6) * THEN TURN OFF BUFFERING +BUFOX3 RTS + + +* TABLE OUTPUT FUNCTION --- PUT THE CHAR IN D0 IN THE DEFINED TABLE + +TABCHR MOVE.L TABPTR(A6),A0 * CURRENT POSITION IN TABLE + MOVE.B D0,(A0)+ * STORE CHAR + MOVE.L A0,TABPTR(A6) * UPDATE POINTER + RTS + +* REDIRECT OUTPUT (TABLE OR NORMAL) ACCORDING TO INT + +OPDIRO NOP * TELL CALLER TO USE ARGBLK + MOVE.W ARG1(A0),D0 * VIRTUAL OUTPUT DEVICE -- NEGATIVE? + BLT DIRX0 * YES, MEANS TURN IT OFF + + SUBQ.W #1,D0 * TURN ON SCREEN? + BEQ.S DIRX1 * YES + SUBQ.W #1,D0 * TURN ON PRINTER? + BEQ.S DIRX3 * YES + SUBQ.W #1,D0 * TURN ON TABLE? + BEQ.S DIRX5 * YES + BRA DIRX7 * UNKNOWN DEVICE, IGNORE REQUEST + +DIRX0 ADDQ.W #1,D0 * TURN OFF SCREEN? + BEQ.S DIRX2 * YES + ADDQ.W #1,D0 * TURN OFF PRINTER? + BEQ.S DIRX4 * YES + ADDQ.W #1,D0 * TURN OFF TABLE? + BEQ.S DIRX6 * YES + BRA DIRX7 * UNKNOWN DEVICE, IGNORE REQUEST + +*** TURN SCREEN OUTPUT ON, OFF + +DIRX1 MOVE.W #1,VOCONS(A6) + BRA DIRX7 +DIRX2 CLR.W VOCONS(A6) + BRA DIRX7 + +*** TURN SCRIPTING OUTPUT ON, OFF + +DIRX3 MOVE.W #1,VOPRNT(A6) + + MOVE.L BUFFER(A6),A0 + BSET #0,PFLAGS+1(A0) * SET THIS FLAG (ZIP/EZIP) FOR GAME'S USE + + BSR TSTSCR * ACTIVATE THE PRINTER (USES GAME FLAG) + BRA DIRX7 + +DIRX4 CLR.W VOPRNT(A6) + + MOVE.L BUFFER(A6),A0 + BCLR #0,PFLAGS+1(A0) * CLEAR THIS FLAG (ZIP/EZIP) FOR GAME'S USE + + BSR TSTSCR * DE-ACTIVATE THE PRINTER (USES GAME FLAG) + BRA DIRX7 + +*** TURN TABLE ON, OFF + +DIRX5 MOVEQ #0,D0 + MOVE.W ARG2(A0),D0 * GET RELATIVE TABLE POINTER + ADD.L BUFFER(A6),D0 * ABSOLUTIZE + MOVE.L D0,TABOUT(A6) * REMEMBER START OF TABLE + + ADDQ.L #2,D0 * SKIP LENGTH SLOT + MOVE.L D0,TABPTR(A6) * FIRST CHAR WILL GO HERE + + MOVE.W #1,VOTABL(A6) * SET TABLE-OUTPUT FLAG + BRA DIRX7 + +DIRX6 TST.W VOTABL(A6) * MAKE SURE A TABLE DOES EXIST + BEQ.S DIRX7 * NO TABLE, IGNORE REQUEST + CLR.W VOTABL(A6) * OK, TURN OFF TABLE-OUTPUT FLAG + + MOVE.L TABOUT(A6),A0 * COMPUTE LENGTH OF CURRENT TABLE CONTENTS + MOVE.L TABPTR(A6),D0 + SUB.L A0,D0 + SUBQ.W #2,D0 * ADJUST FOR LENGTH SLOT + BSR PTAWRD * AND STORE LENGTH IN LENGTH SLOT + +DIRX7 RTS + +* REDIRECT INPUT (NORMAL OR COMMAND FILE) ACCORDING TO INT + +OPDIRI NOP * TELL CALLER TO USE ARGBLK + +*** 0 MEANS KEYBOARD, 1 MEANS SPECIAL FILE + + RTS + +* INPUT (AN ASCII KEY, WITHOUT ECHO) + +OPINPUT NOP * TELL CALLER TO USE ARGBLK + BSR PUTLIN * EMPTY THE BUFFER + +* CLR.W TIMOUT(A6) * ASSUME NO TIMEOUTS +* CMPI.W #3,(A0) * ARE OPTIONAL TIMEOUTS IN EFFECT? +* BNE.S INPTX1 * NO + +* MOVE.W #1,TIMOUT(A6) +* MOVE.W ARG2(A0),TDELAY(A6) * DELAY IN 10THS OF A SECOND +* MOVE.W ARG3(A0),TFUNC(A6) * FUNCTION TO CALL UPON TIMEOUT +* BSR TRESET * RESET THE TIMER + + +* MAIN LOOP STARTS HERE ... + +INPTX1 BSR TTYIN * WAIT FOR A KEY + + +* TST.B D0 +* BNE.S INPTX2 * GOT SOMETHING, EXIT + +* TST.W TIMOUT(A6) * TIMOUTS IN EFFECT? +* BEQ.S INPTX1 * NO + +* BSR TCHECK * GET TIME REMAINING BEFORE NEXT TIMEOUT +* TST.W D0 * HAS IT RUN OUT? +* BGT.S INPTX1 * NO +* BSR TRESET * YES, RESET TIMER + +* MOVE.W TFUNC(A6),D0 * CALL THE TIMEOUT FUNCTION +* BSR INCALL +* TST.W D0 * RETURNED VALUE -- ABORT INPUT? +* BEQ.S INPTX1 * NO, CONTINUE WAITING + +INPTX2 BRA PUTVAL * RETURN ASCII VALUE + +* --------------------------------------------------------------------------- + +* CLEAR A WINDOW, OR ENTIRE SCREEN + +OPCLEAR SUBQ.W #1,D0 * WINDOW 1 ONLY? + BEQ.S CLRX2 * YES + ADDQ.W #1,D0 * WINDOW 0 ONLY? + BEQ.S CLRX1 * YES + + ADDQ.W #1,D0 * ENTIRE SCREEN? + BNE.S CLRX4 * INVALID ARG, DO NOTHING + + CLR.W D0 * YES, + BSR OPSPLT * FIRST UNSPLIT THE SCREEN (IF NEEDED) + +*** ERROR OCCURS IN OPENING AMFV SCREEN, IF CURSOR NOT RESET ... + +CLRX1 MOVE.W _rows,D0 + SUBQ.W #1,D0 * cur_row in (0 .. rows-1) + CLR.W D1 + BSR SETCUR * RESET CURSOR TO "NORMAL" POSITION + + MOVE.W _split_row,D0 * CLEAR WINDOW 0 + MOVE.W _rows,D1 + BRA.S CLRX3 + +*** MOVE CURSOR TO "TOPLEFT" POSITION? (NOT IN SPEC) + +CLRX2 CLR.W D0 * CLEAR WINDOW 1 + MOVE.W _split_row,D1 + +* FIRST ROW TO CLEAR IN D0, LAST (+1) IN D1 + +CLRX3 MOVE.L D1,-(SP) + MOVE.L D0,-(SP) + JSR _clear_lines * DO IT + ADDQ.W #8,SP * FLUSH STACK (4 ACTUAL) + +CLRX4 RTS + +* ERASE (CURRENT LINE, STARTING AT CURSOR) + +OPERASE SUBQ.W #1,D0 + BNE.S ERASX1 * IGNORE ARG IF NOT 1 + JSR _clear_eol +ERASX1 RTS + +* SET CURSOR TO LINE INT1, COLUMN INT2 + +OPCURS TST.W WIND1(A6) * CURRENTLY IN WINDOW 1? + BNE.S CURSX1 * YES + ADD.W _split_row,D0 * NO, MUST MAKE LINE RELATIVE TO WINDOW 0 + +CURSX1 SUBQ.W #1,D0 * MAKE LINE AND COLUMN ZERO-ORIGIN + SUBQ.W #1,D1 + MOVE.W D0,_cur_row * RESET THE GLOBALS + MOVE.W D1,_cur_column + + MOVEM.L A4-A6,-(SP) * (THE ONLY VULNERABLE REGS) + JSR _write_cursor_pos + MOVEM.L (SP)+,A4-A6 + + RTS + +* GET CURSOR POSITION + +OPCURG BRA OPERR + +*** THIS IS NOT CURRENTLY A DEFINED OPERATION *** + +* MOVEM.L A4-A6,-(SP) +* JSR _read_cursor_pos +* MOVEM.L (SP)+,A4-A6 + +* MOVE.W _cur_row,D0 * GET THE GLOBALS +* MOVE.W _cur_column,D1 + +* ADDQ.W #1,D0 * MAKE LINE AND COLUMN ONE-ORIGIN +* ADDQ.W #1,D1 + +* TST.W WIND1(A6) * CURRENTLY IN WINDOW 1? +* BNE.S CURGX1 * YES +* SUB.W _split_row,D0 * NO, MUST MAKE LINE RELATIVE TO WINDOW 0 + +*CURGX1 ASL.W #8,D0 * RETURN LINE IN HIGH BYTE, COLUMN IN LOW (?) +* MOVE.B D1,D0 +* BRA PUTVAL + +* HIGHLIGHT (SET CHAR ATTRIBUTES) + +OPATTR MOVE.L D0,-(SP) + BSR PUTLIN1 * MUST FIRST DUMP THE LINE BUFFER + + JSR _highlight * 1 INVERSE, 2 BOLD, 4 ITALIC + ADDQ.W #4,SP * FLUSH STACK (2 ACTUAL) + RTS + + ENDC + IFEQ CZIP * THESE FUNCTIONS ARE UNDEFINED IN ZIP + +OPCLEAR BRA OPERR +OPERASE BRA OPERR + +OPCURS BRA OPERR +OPCURG BRA OPERR +OPATTR BRA OPERR + +OPBUFO BRA OPERR +OPDIRO BRA OPERR +OPDIRI BRA OPERR +OPINPUT BRA OPERR + + ENDC + +* MAKE A SOUND (NOW IN ZIP TOO) +* ARG1 = ID: 1=BEEP, 2=BOOP, 3+ ARE SPECIAL, 0=MRU +* [ARG2] = ACTION: 1=INIT, [2=START], 3=STOP, 4=CLEANUP +* [ARG3] = VOLUME: 0=MIN, 8=MAX, [-1=USE MIDI VOLUME] + +OPSOUND NOP * REQUEST AN ARGBLK + MOVE.W ARG1(A0),D0 * SOUND ID + + MOVEQ #2,D1 * DEFAULT ACTION = START + CMPI.W #2,(A0) + BLT.S SOUNX1 + MOVE.W ARG2(A0),D1 * GIVEN ACTION + +SOUNX1 MOVEQ #-1,D2 * DEFAULT VOL = MIDI VOL + CMPI.W #3,(A0) + BLT.S SOUNX2 + MOVE.W ARG3(A0),D2 * GIVEN VOLUME +SOUNX2 BRA DOSOUND + + PAGE +* ---------------------------------------------------------------------------- +* CONTROL OPERATIONS +* ---------------------------------------------------------------------------- + +* CALL (A FUNCTION WITH OPTIONAL ARGUMENTS) + + IFEQ EZIP + +OPCAL1 LEA ARGBLK(A6),A0 * MUST SET UP AN ARGUMENT BLOCK FOR THIS ONE + MOVE.W #1,(A0) * ONE ARG + MOVE.W D0,ARG1(A0) + +OPCAL2 NOP * TELL CALLER TO USE ARGBLK +OPXCAL NOP * TELL CALLER TO USE ARGBLK +OPCALL NOP * TELL CALLER TO USE ARGBLK + + ENDC + IFEQ CZIP + +OPCAL1 BRA OPERR * FIRST THREE ARE UNDEFINED IN ZIP +OPCAL2 BRA OPERR +OPXCAL BRA OPERR + +OPCALL NOP * TELL CALLER TO USE ARGBLK + ENDC + +* POINTER TO ARGBLK IS IN A0 ... + + MOVE.W (A0)+,D2 + MOVE.W (A0)+,D0 * FUNCTION TO CALL -- IS IT ZERO? + BNE.S CALLX1 * NO + + CLR.W D0 * YES, SIMPLY RETURN A ZERO + BRA PUTVAL + +*** BUILD A STACK FRAME, THEN UPDATE THE ZPC ... + +CALLX1 MOVE.L A0,A1 + SUBQ.W #1,D2 * THIS IS NUMBER OF OPTIONAL LOCALS + + MOVE.W ZPC1(A6),-(A4) * SAVE OLD ZPC + MOVE.W ZPC2(A6),-(A4) + +* (The relativized locs pointer ought to be stacked as a word instead of +* a long. Changing now would make previous saved games incompatible.) + + MOVE.L ZLOCS(A6),D1 * SAVE OLD LOCALS POINTER + SUB.L STKBOT(A6),D1 * BUT RELATIVIZE IT IN CASE OF SAVE + MOVE.L D1,-(A4) + IFEQ EZIP + BSR BSPLTQ * SPLIT THE FUNCTION POINTER + ENDC + IFEQ CZIP + BSR BSPLIT * SPLIT THE FUNCTION POINTER + ENDC + MOVE.W D0,ZPC1(A6) * MAKE IT THE NEW ZPC + MOVE.W D1,ZPC2(A6) + BSR NEWZPC * UPDATE ZPC STUFF + +* (The new locs pointer ought to point to pseudo-loc 0, not 1. Ditto above.) + + MOVE.L A4,ZLOCS(A6) * LOCALS WILL START AT NEXT STACK SLOT + SUBQ.L #2,ZLOCS(A6) * POINT TO LOCAL 1, IF ANY + +*** CREATE SPACE FOR & INITIALIZE THE LOCALS ... + + BSR NXTBYT * GET ACTUAL NUMBER OF DEFINED LOCALS + MOVE.W D0,D1 + BEQ.S CALLX4 * EXIT IF NONE + +CALLX2 BSR NXTWRD * GET THE NEXT LOCAL DEFAULT VALUE + SUBQ.W #1,D2 * BUT ARE THERE ANY MORE OPTIONAL VALUES? + BLT.S CALLX3 * NO, USE THE DEFAULT + MOVE.W (A1)+,D0 * OTHERWISE USE THE OPTIONAL + +CALLX3 MOVE.W D0,-(A4) * CREATE LOCAL SPACE & INITIALIZE IT + SUBQ.W #1,D1 * ANY MORE LOCALS? + BGT.S CALLX2 * YES, LOOP +CALLX4 RTS + +* RETURN (FROM CURRENT FUNCTION CALL) + +OPRETU MOVE.L ZLOCS(A6),A4 * RESTORE OLD TOP OF STACK + ADDQ.L #2,A4 + + MOVE.L (A4)+,D1 * RESTORE OLD LOCALS POINTER + ADD.L STKBOT(A6),D1 * ABSOLUTIZE IT + MOVE.L D1,ZLOCS(A6) + + MOVE.W (A4)+,ZPC2(A6) * RESTORE OLD ZPC + MOVE.W (A4)+,ZPC1(A6) + IFEQ EZIP + BLT INRETU * SPECIAL INTERNAL CALL/RETURN, HANDLE IT + ENDC + MOVE.W D0,D1 * PROTECT VALUE + BSR NEWZPC * UPDATE ZPC STUFF + MOVE.W D1,D0 + BRA PUTVAL * RETURN THE VALUE + +* RTRUE + +OPRTRU MOVEQ #1,D0 * RETURN A "1" + BRA.S OPRETU + +* RFALSE + +OPRFAL CLR.W D0 * RETURN A "0" + BRA.S OPRETU + +* JUMP (TO A NEW LOCATION) + +OPJUMP SUBQ.W #2,D0 * ADJUST OFFSET + ADD.W D0,ZPC2(A6) * ADD OFFSET TO CURRENT ZPC + BRA NEWZPC * NORMALIZE IT & UPDATE ZPC STUFF + +* RSTACK (RETURN STACK) + +OPRSTA MOVE.W (A4)+,D0 * POP A VALUE + BRA OPRETU * AND RETURN IT + +* FSTACK (FLUSH A VALUE OFF THE STACK) + +OPFSTA ADDQ.L #2,A4 * FLUSH ONE WORD + RTS + +* NOOP (NO OPERATION) + +OPNOOP RTS * DO NOTHING + +* --------------------------------------------------------------------------- + + IFEQ EZIP + +* INTERNALLY CALL A FUNCTION, FUNCTION IN D0, RETURN VALUE IN D0 + +INCALL MOVEM.L D1-D7/A1-A3,-(SP) + + MOVE.W ZPC1(A6),-(SP) + MOVE.W #-1,ZPC1(A6) * FAKE ZPC1, SIGNALS AN INTERNAL CALL/RETURN + + LEA ARGBLK(A6),A0 * SET UP ARGBLK FOR OPCALL + MOVE.W D0,ARG1(A0) * FUNCTION TO CALL + MOVE.W #1,(A0) * ONE ARG + + BSR OPCALL * CALL THE TIMEOUT FUNCTION + BRA NXTINS * GO EXECUTE IT + +* JUMP BACK TO HERE UPON NEXT OPRETURN ... + +INRETU ADDQ.W #4,SP * CAREFUL -- FLUSH TOP RETURN ADDR (NXTINS) + MOVE.W (SP)+,ZPC1(A6) * FIX THE ZPC + + MOVE.W D0,D1 + BSR NEWZPC * RESTORE THE PROPER PAGE + MOVE.W D1,D0 + + MOVEM.L (SP)+,D1-D7/A1-A3 + RTS * RETURN TO ORIGINAL CALLER + ENDC + + + PAGE +* ---------------------------------------------------------------------------- +* GAME COMMANDS +* ---------------------------------------------------------------------------- + +* SAVE (THE CURRENT STATE OF THE GAME) + +OPSAVE CLR.W D0 + BSR CHKDSK * CHECK FOR GAME DISK AND CLOSE GAME FILE + + BSR GETSFL * GET A NAME FOR THE SAVE FILE + BNE.S SVX4 * CANCELLED + + BSR NEWSFL * CREATE (IF NEEDED) AND OPEN THE FILE + BNE.S SVX4 * ERROR, JUST EXIT (NEED NOT DELETE) + +* SUCCESS, SAVE STATE VARIABLES ON GAME STACK ... + + MOVE.W ZPC1(A6),-(A4) + MOVE.W ZPC2(A6),-(A4) + MOVE.L ZLOCS(A6),-(A4) + + MOVE.L STKBOT(A6),D0 + SUB.L D0,(A4) * RELATIVIZE THIS ONE + MOVE.W ZORKID(A6),-(A4) + + MOVE.L D0,A0 + MOVE.L A4,(A0) * SAVE GAME SP IN KNOWN LOCATION + SUB.L D0,(A0) * RELATIVIZE IT TOO + + MOVE.L STKBOT(A6),A0 + CLR.W D0 * THIS WILL BE BLOCK ZERO + MOVEQ #STKLEN/512,D1 * BLOCK LENGTH OF STACK + BSR PTSBKS * WRITE IT OUT + BNE.S SVX2 * ERROR, CLOSE AND DELETE THE FILE + + ADDA.W #10,A4 * RESET THE STACK POINTER + MOVE.L BUFFER(A6),A0 * BEGINNING OF IMPURE STUFF IN CORE + + MOVEQ #STKLEN/512,D0 * START WRITING AFTER STACK + MOVE.W PURBOT(A6),D1 * NUMBER OF IMPURE BLOCKS + BSR PTSBKS + BNE.S SVX2 * ERROR, CLOSE AND DELETE THE FILE + + BSR CLSSFL * SUCCESS, CLOSE THE FILE + BNE.S SVX3 * ERROR, DELETE IT AND FAIL + +SVX1 BSR DEFNEW * UPDATE PREVIOUS DEFAULT NAMES + + MOVEQ #1,D0 + BSR CHKDSK * MAKE SURE GAME DISK IS BACK IN DRIVE + + BSR MAKEICON * ATTACH AN ICON TO THIS FILE + + IFEQ EZIP + MOVEQ #1,D0 * RETURN "SAVE OK" + BRA PUTVAL + ENDC + IFEQ CZIP + BRA PTRUE * RETURN PREDICATE TRUE + ENDC + +* SAVE FAILED FOR SOME REASON, HANDLE IT ... + +SVX2 BSR CLSSFL * CLOSE THE BAD FILE +SVX3 BSR DELSFL * DELETE THE BAD FILE FROM THE DIRECTORY + +SVX4 BSR DEFOLD * INSTALL PREVIOUS DEFAULT NAMES + + MOVEQ #1,D0 + BSR CHKDSK * MAKE SURE GAME DISK IS BACK IN DRIVE + + IFEQ EZIP + CLR.W D0 * RETURN "SAVE FAILED" + BRA PUTVAL + ENDC + IFEQ CZIP + BRA PFALSE * RETURN PREDICATE FALSE + ENDC + + +* RESTORE (A PREVIOUSLY SAVED GAME STATE) + +OPREST CLR.W D0 + BSR CHKDSK * FIRST CHECK FOR PRESENCE OF GAME DISK + +* SKIP NEXT CALL IF DOING SPECIAL RESTORE DURING LAUNCH ... + + BSR GETRFL * GET NAME OF A RESTORE FILE + BNE RESX1 * CANCELLED + + BSR OPNSFL * OPEN THE FILE + BNE RESX1 * ERROR + + CLR.W D0 * FIRST READ IN STACK + MOVEQ #STKLEN/512,D1 * BLOCK LENGTH OF STACK + MOVE.L STKBOT(A6),A0 * PUT IT HERE + BSR GTSBKS + BNE RESX3 * DIE IF DISK ERROR + + MOVE.L STKBOT(A6),A0 + MOVE.L (A0),A4 * RESTORE GAME SP + ADD.L A0,A4 * RE-ABSOLUTIZE IT + + MOVE.W (A4)+,D0 * GET THE SAVED ZORKID + CMP.W ZORKID(A6),D0 * IS IT THE SAME AS OURS? + BNE.S RESX2 * NO, DIE + + MOVE.L (A4)+,D0 * YES, RESTORE OLD LOCALS POINTER + ADD.L STKBOT(A6),D0 * RE-ABSOLUTIZE THIS ONE + MOVE.L D0,ZLOCS(A6) + + MOVE.W (A4)+,ZPC2(A6) * RESTORE OTHER STUFF + MOVE.W (A4)+,ZPC1(A6) + + MOVE.L BUFFER(A6),A0 + MOVE.W PFLAGS(A0),-(SP) * BUT PRESERVE THE FLAGS (SCRIPT ETC) + + MOVEQ #STKLEN/512,D0 * READ IMPURE STUFF STARTING AFTER STACK + MOVE.W PURBOT(A6),D1 * LENGTH OF IMPURE STUFF + BSR GTSBKS + BNE.S RESX3 * DIE IF DISK ERROR + + MOVE.L BUFFER(A6),A0 + MOVE.W (SP)+,PFLAGS(A0) * RESTORE THE OLD FLAGS + BSR CLSSFL * CLOSE THE FILE + + BSR NEWZPC * THEN GET THE PROPER ZPC PAGE + BSR DEFNEW * UPDATE PREVIOUS DEFAULT NAMES + + MOVEQ #1,D0 + BSR CHKDSK * MAKE SURE GAME DISK IS BACK IN DRIVE + + IFEQ EZIP + MOVEQ #2,D0 * RETURN "RESTORE OK" + BRA PUTVAL + ENDC + IFEQ CZIP + BRA PTRUE * RETURN PREDICATE TRUE + ENDC + +* SOMETHING WRONG, FAIL ... + +RESX1 BSR DEFOLD * INSTALL PREVIOUS DEFAULT NAMES + + MOVEQ #1,D0 + BSR CHKDSK * MAKE SURE GAME DISK IS BACK IN DRIVE + + IFEQ EZIP + CLR.W D0 * RETURN "RESTORE FAILED" + BRA PUTVAL + ENDC + IFEQ CZIP + BRA PFALSE * RETURN PREDICATE FALSE + ENDC + +* FATAL ERROR, DIE ... + +RESX2 MOVE.W D0,-(SP) + BSR CLSSFL * CLOSE THE BAD FILE + + MOVE.W (SP)+,D0 * BAD VERSION ID + LEA MSGRE2,A0 + BRA FATAL * 'Wrong save file version' + + SECTION ZDATA +MSGRE2 DC.B 'Wrong save file version',0 + SECTION ZCODE + +RESX3 MOVE.W D0,-(SP) + BSR CLSSFL * CLOSE THE BAD FILE AND DIE + + MOVE.W (SP)+,D0 * ERROR CODE + LEA MSGRE1,A0 + BRA FATAL * 'Save file read error' + + SECTION ZDATA +MSGRE1 DC.B 'Save file read error',0 + SECTION ZCODE + +* RESTART (THE GAME) + +OPRSTT BSR PUTNEW * FORCE OUT ANY QUEUED TEXT + CLR.W LINES(A6) * RESET LINE COUNTER + + JSR _clear_screen + BRA RESTRT * SKIP INITIALIZATIONS AND FILE OPENING + +* QUIT + +OPQUIT BRA FINISH * DIE PEACEFULLY + +* VERIFY (GAME FILE) + +OPVERI + + IFEQ CZIP * VERSION INFO FOR ZIP ONLY + LEA MSGVER,A0 + BSR OUTMSG0 * 'Amiga interpreter version ' + SECTION ZDATA +MSGVER DC.B 'Amiga interpreter version ',0 + SECTION ZCODE + + LEA INTWRD,A0 + MOVE.B 1(A0),D0 * DISPLAY THE LETTER (LOW BYTE) + BSR OPPRNC + BSR OPCRLF + ENDC + + LEA SUBVER,A0 + TST.W (A0) * DISPLAY SUB-VERSION ONLY IF NON-ZERO + BEQ.S VERX0 + + LEA MSGVR2,A0 + BSR OUTMSG0 * 'Sub-version ' + SECTION ZDATA +MSGVR2 DC.B 'Sub-version ',0 + SECTION ZCODE + + MOVE.W SUBVER,D0 * DISPLAY THE SUB-VERSION NUMBER + BSR OPPRNN + BSR OPCRLF + +VERX0 MOVE.L BUFFER(A6),A0 + MOVE.W PLENTH(A0),D0 * GET LENGTH OF GAME FILE + + IFEQ EZIP + BSR BSPLTQ + ENDC + IFEQ CZIP + BSR BSPLIT + ENDC + MOVE.W D0,D4 * THIS IS FINAL BLOCK + MOVE.W D1,D5 * FINAL BYTE + + CLR.W D0 * STARTING BLOCK NUMBER + MOVEQ #64,D1 * STARTING BYTE NUMBER + CLR.W D3 * CHECKSUM HERE + MOVE.W ENDLOD(A6),-(SP) + CLR.W ENDLOD(A6) * FORCE LOADING FROM DISK + +VERX1 BSR GETBYT * GET NEXT BYTE + ADD.W D2,D3 * ADD IN TO CHECKSUM + CMP.W D0,D4 * DONE YET? + BNE.S VERX1 * NO + CMP.W D1,D5 * MAYBE + BNE.S VERX1 * NO + + MOVE.W (SP)+,ENDLOD(A6) * YES, RESTORE PROPER ENDLOD + + MOVE.L BUFFER(A6),A0 + MOVE.W PCHKSM(A0),D0 * GET THE REAL CHECKSUM + CMP.W D0,D3 + BNE.S VERX2 * ERROR + + BRA PTRUE * SUCCESS +VERX2 BRA PFALSE * FAILURE + diff --git a/amiga/zip3.asm b/amiga/zip3.asm new file mode 100644 index 0000000..ad6d075 --- /dev/null +++ b/amiga/zip3.asm @@ -0,0 +1,978 @@ + + PAGE +* --------------------------------------------------------------------------- +* ZIP MAIN INSTRUCTION-FETCH CYCLE +* --------------------------------------------------------------------------- + +* OPERATORS WHICH ACCEPT A VARIABLE NUMBER OF ARGUMENTS (OPQEQU, OPCALL, ETC) +* ARE IDENTIFIED BY AN INITIAL NOP. THEIR ARGUMENTS ARE PASSED IN AN ARGUMENT +* BLOCK, WITH THE NUMBER OF ARGUMENTS AS THE FIRST ENTRY. ALL OTHER OPERATORS +* RECEIVE THEIR ARGUMENTS IN REGISTERS. + +NOOP EQU $4E71 * MARKS ROUTINES WHICH TAKE OPTIONAL ARGS + +NXTINS BSR NXTBYT * GET THE OPERATION BYTE + + IFEQ DEBUG + BSR DBTEST + ENDC + CMPI.B #$80,D0 * IS IT A 2 OP? + BCS.S NXT2 * BLO * YES + + CMPI.B #$B0,D0 * IS IT A 1 OP? + BCS.S NXT1 * BLO * YES + + CMPI.B #$C0,D0 * IS IT A 0 OP? + BCC NXT4 * BHS * NO, MUST BE AN EXTENDED OP + +* --------------------------------------------------------------------------- + +NXT0 ANDI.W #$0F,D0 * 0 OP, EXTRACT OPERATOR CODE, "xxxx oooo" + ADD.W D0,D0 * WORD OFFSET + + LEA ZEROPS,A1 + ADDA.W 0(A1,D0.W),A1 * CALCULATE THE OPERATOR ROUTINE ADDRESS + PEA NXTINS * LEAVE RETURN ADDRESS ON STACK + JMP (A1) * CALL THE OPERATOR ROUTINE + +* --------------------------------------------------------------------------- + +NXT1 MOVE.W D0,D2 * 1 OP, MAKE A COPY, "xxmm oooo" + ANDI.W #$0F,D2 * EXTRACT OPERATOR CODE + ADD.W D2,D2 * WORD OFFSET + + LSR.W #4,D0 * EXTRACT MODE BITS + ANDI.W #3,D0 + BSR GETARG * GET THE ARGUMENT + + LEA ONEOPS,A1 + ADDA.W 0(A1,D2.W),A1 * CALCULATE THE OPERATOR ROUTINE ADDRESS + PEA NXTINS * LEAVE RETURN ADDRESS ON STACK + JMP (A1) * CALL THE OPERATOR ROUTINE + +* --------------------------------------------------------------------------- + +NXT2 MOVE.W D0,D2 * 2 OP, MAKE A COPY, "xmmo oooo" + + MOVEQ #1,D0 * ASSUME FIRST ARG IS AN IMMEDIATE + BTST #6,D2 * IS IT INSTEAD A VARIABLE? + BEQ.S N2X1 * NO + MOVEQ #2,D0 * YES, CHANGE MODE +N2X1 BSR GETARG * GET THE FIRST ARG + MOVE.W D0,D1 + + MOVEQ #1,D0 * ASSUME SECOND ARG IS AN IMMEDIATE + BTST #5,D2 * IS IT INSTEAD A VAR? + BEQ.S N2X2 * NO + MOVEQ #2,D0 * YES, CHANGE MODE +N2X2 BSR GETARG * GET THE SECOND ARG + EXG D0,D1 * POSITION THE ARGS + + ANDI.W #$1F,D2 * EXTRACT OPERATOR CODE + ADD.W D2,D2 * WORD OFFSET + + LEA TWOOPS,A1 + ADDA.W 0(A1,D2.W),A1 * CALCULATE THE OPERATOR ROUTINE ADDRESS + CMPI.W #NOOP,(A1) * BUT DOES THE OPERATOR EXPECT AN ARGBLK? + BNE.S N2X3 * NO + + LEA ARGBLK+6(A6),A0 * YES, MOVE ARGS TO ARGBLK + MOVE.W D1,-(A0) + MOVE.W D0,-(A0) + MOVE.W #2,-(A0) * ALWAYS 2 ARGS + +N2X3 PEA NXTINS * LEAVE RETURN ADDRESS ON STACK + JMP (A1) * CALL THE OPERATOR ROUTINE + +* --------------------------------------------------------------------------- + +NXT4 MOVE.W D0,D2 * EXTENDED OP, SAVE A COPY, "xxoo oooo" + +*** GET THE 4 (OR 8) MODE SPECIFIERS, EXTRACT AND STACK THEM ... + + IFEQ EZIP + CMPI.B #$EC,D0 * IS THIS AN XCALL (236)? + BNE.S N4X1 * NO + MOVEQ #8,D3 * YES, 8 MODE SPECIFIERS + + BSR NXTBYT * GET THE FIRST MODE BYTE, "aabb ccdd" + MOVE.W D0,D1 + BSR NXTBYT * GET THE SECOND MODE BYTE, "eeff gghh" + + MOVE.W D0,-(SP) * SAVE hh + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE gg + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE ff + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE ee + + MOVE.W D1,D0 + BRA.S N4X2 + ENDC + +N4X1 MOVEQ #4,D3 * 4 MODE SPECIFIERS + BSR NXTBYT * GET THE MODE BYTE, "aabb ccdd" + +N4X2 MOVE.W D0,-(SP) * SAVE dd + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE cc + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE bb + LSR.W #2,D0 + MOVE.W D0,-(SP) * SAVE aa + +*** DECODE ARGUMENTS, STORE IN ARGBLK + + CLR.W D4 * KEEP A COUNT OF ACTUAL ARGUMENTS + LEA ARGBLK+2(A6),A1 * ARGUMENT BLOCK, SKIP OVER COUNT SLOT + +N4X3 MOVE.W (SP)+,D0 * POP NEXT MODE SPECIFIER + ANDI.W #3,D0 * EXTRACT MODE BITS + CMPI.W #3,D0 * ARE THERE ANY MORE ARGUMENTS? + BEQ.S N4X4 * NO + + ADDQ.W #1,D4 * YES, COUNT THIS ONE + BSR GETARG * DECODE AND FETCH IT + MOVE.W D0,(A1)+ * STORE IT IN ARGUMENT BLOCK + + SUBQ.W #1,D3 * GO FOR MORE + BNE.S N4X3 + BRA.S N4X5 + +N4X4 SUBQ.W #1,D3 * NUMBER OF EXTRA MODE SPECIFIERS + ADD.W D3,D3 + ADDA.W D3,SP * FLUSH THEM + +N4X5 LEA ARGBLK(A6),A0 * PASS ARGBLK POINTER TO THE OPERATOR HERE ... + MOVE.W D4,(A0) * STORE NUMBER OF ARGUMENTS + +*** CALCULATE THE OPERATOR ROUTINE ADDRESS + + ANDI.W #$3F,D2 * EXTRACT OPERATOR CODE + ADD.W D2,D2 * WORD OFFSET + + LEA EXTOPS,A1 + ADDA.W 0(A1,D2.W),A1 * CALCULATE THE OPERATOR ROUTINE ADDRESS + CMPI.W #NOOP,(A1) * BUT DOES THE OPERATOR EXPECT AN ARGBLK? + BEQ.S N4X6 * YES + + ADDQ.L #2,A0 * NO, PASS ARGS IN REGISTERS + MOVE.W (A0)+,D0 + MOVE.W (A0)+,D1 + MOVE.W (A0)+,D2 + MOVE.W (A0)+,D3 * MAXIMUM OF FOUR + +N4X6 PEA NXTINS * LEAVE RETURN ADDRESS ON STACK + JMP (A1) * CALL THE OPERATOR ROUTINE + + + PAGE +* --------------------------------------------------------------------------- +* DISPATCH TABLES +* --------------------------------------------------------------------------- + +* UNIMPLEMENTED OPCODES DISPATCH TO HERE ... + +OPERR CLR.W D0 * (MAY BE GARBAGE) + LEA MSGBAD,A0 + BRA FATAL * 'Bad operation' + + SECTION ZDATA +MSGBAD DC.B 'Bad operation',0 + SECTION ZCODE + +* FOLLOWING MUST BE IN CODE SECTION, DUE TO OFFSET COMPUTATIONS ... + +ZEROPS DC.W OPRTRU-ZEROPS * 176 + DC.W OPRFAL-ZEROPS * 177 + DC.W OPPRNI-ZEROPS * 178 + DC.W OPPRNR-ZEROPS * 179 + DC.W OPNOOP-ZEROPS * 180 + DC.W OPSAVE-ZEROPS * 181 + DC.W OPREST-ZEROPS * 182 + DC.W OPRSTT-ZEROPS * 183 + DC.W OPRSTA-ZEROPS * 184 + DC.W OPFSTA-ZEROPS * 185 + DC.W OPQUIT-ZEROPS * 186 + DC.W OPCRLF-ZEROPS * 187 + DC.W OPUSL-ZEROPS * 188 + DC.W OPVERI-ZEROPS * 189 + DC.W OPERR-ZEROPS * 190 + DC.W OPERR-ZEROPS * 191 + +ONEOPS DC.W OPQZER-ONEOPS * 128 + DC.W OPQNEX-ONEOPS * 129 + DC.W OPQFIR-ONEOPS * 130 + DC.W OPLOC-ONEOPS * 131 + DC.W OPPTSI-ONEOPS * 132 + DC.W OPINC-ONEOPS * 133 + DC.W OPDEC-ONEOPS * 134 + DC.W OPPRNB-ONEOPS * 135 + DC.W OPCAL1-ONEOPS * 136 EZIP + DC.W OPREMO-ONEOPS * 137 + DC.W OPPRND-ONEOPS * 138 + DC.W OPRETU-ONEOPS * 139 + DC.W OPJUMP-ONEOPS * 140 + DC.W OPPRIN-ONEOPS * 141 + DC.W OPVALU-ONEOPS * 142 + DC.W OPBCOM-ONEOPS * 143 + +TWOOPS: +EXTOPS: DC.W OPERR-EXTOPS * 0 + DC.W OPQEQU-EXTOPS * 1 + DC.W OPQLES-EXTOPS * 2 + DC.W OPQGRT-EXTOPS * 3 + DC.W OPQDLE-EXTOPS * 4 + DC.W OPQIGR-EXTOPS * 5 + DC.W OPQIN-EXTOPS * 6 + DC.W OPBTST-EXTOPS * 7 + DC.W OPBOR-EXTOPS * 8 + DC.W OPBAND-EXTOPS * 9 + DC.W OPQFSE-EXTOPS * 10 + DC.W OPFSET-EXTOPS * 11 + DC.W OPFCLE-EXTOPS * 12 + DC.W OPSET-EXTOPS * 13 + DC.W OPMOVE-EXTOPS * 14 + DC.W OPGET-EXTOPS * 15 + DC.W OPGETB-EXTOPS * 16 + DC.W OPGETP-EXTOPS * 17 + DC.W OPGTPT-EXTOPS * 18 + DC.W OPNEXT-EXTOPS * 19 + DC.W OPADD-EXTOPS * 20 + DC.W OPSUB-EXTOPS * 21 + DC.W OPMUL-EXTOPS * 22 + DC.W OPDIV-EXTOPS * 23 + DC.W OPMOD-EXTOPS * 24 + DC.W OPCAL2-EXTOPS * 25 EZIP + DC.W OPERR-EXTOPS * 26 + DC.W OPERR-EXTOPS + DC.W OPERR-EXTOPS + DC.W OPERR-EXTOPS + DC.W OPERR-EXTOPS + DC.W OPERR-EXTOPS + + DC.W OPCALL-EXTOPS * 224 + DC.W OPPUT-EXTOPS * 225 + DC.W OPPUTB-EXTOPS * 226 + DC.W OPPUTP-EXTOPS * 227 + DC.W OPREAD-EXTOPS * 228 + DC.W OPPRNC-EXTOPS * 229 + DC.W OPPRNN-EXTOPS * 230 + DC.W OPRAND-EXTOPS * 231 + DC.W OPPUSH-EXTOPS * 232 + DC.W OPPOP-EXTOPS * 233 + DC.W OPSPLT-EXTOPS * 234 + DC.W OPSCRN-EXTOPS * 235 + DC.W OPXCAL-EXTOPS * 236 EZIP + DC.W OPCLEAR-EXTOPS * 237 EZIP + DC.W OPERASE-EXTOPS * 238 EZIP + DC.W OPCURS-EXTOPS * 239 EZIP + DC.W OPCURG-EXTOPS * 240 EZIP + DC.W OPATTR-EXTOPS * 241 EZIP + DC.W OPBUFO-EXTOPS * 242 EZIP + DC.W OPDIRO-EXTOPS * 243 EZIP + DC.W OPDIRI-EXTOPS * 244 EZIP + DC.W OPSOUND-EXTOPS * 245 EZIP + DC.W OPINPUT-EXTOPS * 246 EZIP + DC.W OPINTBL-EXTOPS * 247 EZIP + DC.W OPERR-EXTOPS + DC.W OPERR-EXTOPS + DC.W OPERR-EXTOPS * 250 + DC.W OPERR-EXTOPS + DC.W OPERR-EXTOPS + DC.W OPERR-EXTOPS + DC.W OPERR-EXTOPS + DC.W OPERR-EXTOPS * 255 + + + PAGE +* ---------------------------------------------------------------------------- +* STRING FUNCTIONS +* ---------------------------------------------------------------------------- + +* ZSTR CHARACTER CONVERSION VECTOR + + SECTION ZDATA + +ZCHRS DC.B 'abcdefghijklmnopqrstuvwxyz' * CHAR SET 1 + DC.B 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' * CHAR SET 2 + DC.B ' 0123456789.,!?_#' * CHAR SET 3 + + DC.B $27,$22 * <'>,<"> + DC.B '/\-:()' + DC.B 0 * ASCIZ + SECTION ZCODE + +* OUTPUT A ZSTR, BLOCK-POINTER IN D0, BYTE-POINTER IN D1 +* RETURN UPDATED POINTER + +PUTSTR MOVEM.L D2-D5,-(SP) + CLR.W D4 * TEMP CS STARTS AT 0 + CLR.W D5 * PERM CS STARTS AT 0 + +PSX1 BSR GETWRD * GET NEXT STRING WORD + MOVEM.W D0-D2,-(SP) * SAVE POINTER & COPY OF STRING WORD + + MOVEQ #2,D3 * 3 BYTES IN WORD +PSX2 MOVE.W D2,-(SP) * PUSH CURRENT BYTE + ASR.W #5,D2 * SHIFT TO NEXT BYTE + DBF D3,PSX2 * LOOP UNTIL DONE + + MOVEQ #2,D3 * RETRIEVE THE 3 BYTES ... +PSX3 MOVE.W (SP)+,D2 * GET NEXT BYTE + ANDI.W #$001F,D2 * CLEAR UNWANTED BITS + TST.W D4 * IN WORD MODE? (NEGATIVE D4) + BPL.S PSX4 * NO + + ASL.W #1,D2 * YES, CALCULATE WORD OFFSET + MOVE.L WRDTAB(A6),A0 * GET WORD TABLE POINTER + ADD.W WRDOFF(A6),D2 * USE PROPER 32 WORD BLOCK + ADDA.W D2,A0 * INDEX INTO WORD TABLE + BSR GTAWRD * GET A POINTER TO THE WORD ITSELF + BSR BSPLIT * SPLIT IT + BSR PUTSTR * AND PRINT IT + BRA PSX15 * CONTINUE WHERE WE LEFT OFF WITH TEMP CS RESET + +PSX4 CMPI.W #3,D4 * CS 3 (ASCII MODE) SELECTED? + BLT.S PSX6 * NO, NORMAL CS + BGT.S PSX5 * NO, BUT WE'RE ALREADY IN ASCII MODE + BSET #14,D4 * YES (MAKE D4 LARGE POSITIVE) + MOVE.B D2,D4 * SAVE HIGH-ORDER ASCII BITS (2) HERE + BRA.S PSX16 * AND GO GET NEXT BYTE +PSX5 ANDI.W #$0003,D4 * EXTRACT PREVIOUSLY SAVED HIGH-ORDER BITS + ASL.W #5,D4 * POSITION THEM + OR.W D2,D4 * OR IN LOW-ORDER BITS + MOVE.W D4,D0 + BRA.S PSX14 * GO PRINT THE CHARACTER + +PSX6 CMPI.W #6,D2 * SPECIAL CODE (0 TO 5)? + BLT.S PSX9 * YES, SPACE, WORD, OR SHIFT + CMPI.W #2,D4 * MIGHT ALSO BE SPECIAL IF IN CS 2 + BNE.S PSX8 * BUT WE'RE NOT + + CMPI.W #7,D2 * CS 2, SPECIAL CODE FOR CRLF? + BEQ.S PSX7 * YES + BGT.S PSX8 * NO, NOT ASCII MODE, EITHER? + ADDQ.W #1,D4 * YES IT IS, SWITCH TO ASCII MODE (CS 3) + BRA.S PSX16 * AND GO GET NEXT BYTE +PSX7 BSR PUTNEW * CRLF REQUESTED, DO A NEWLINE + BRA.S PSX15 + +PSX8 MOVE.W D4,D1 * NORMAL CHARACTER, GET CS + MULU #26,D1 * CALCULATE OFFSET FOR THIS CS + ADD.W D2,D1 * ADD IN CHARACTER OFFSET (+6) + + LEA ZCHRS,A0 + MOVE.B -6(A0,D1.W),D0 * GET THE CHARACTER FROM CONVERSION VECTOR + BRA.S PSX14 * GO PRINT IT + +PSX9 TST.W D2 * IS IT A SPACE? + BNE.S PSX10 * NO + MOVEQ #32,D0 * YES, GO PRINT A SPACE + BRA.S PSX14 + +PSX10 CMPI.W #3,D2 * IS IT A WORD? + BGT.S PSX11 * NO, MUST BE A SHIFT + BSET #15,D4 * SWITCH TO WORD MODE (NEG D4) FOR NEXT BYTE + SUBQ.W #1,D2 * CALCULATE WORD-TABLE BLOCK OFFSET + ASL.W #6,D2 * 64 BYTES IN A BLOCK + MOVE.W D2,WRDOFF(A6) * SAVE IT AND LOOP + BRA.S PSX16 + +PSX11 SUBQ.W #3,D2 * CALCULATE NEW CS + TST.W D4 * TEMPORARY SHIFT (FROM CS 0)? + BNE.S PSX12 * NO + MOVE.W D2,D4 * YES, JUST SAVE NEW TEMP CS + BRA.S PSX16 + +PSX12 CMP.W D2,D4 * IS THIS THE CURRENT CS? + BEQ.S PSX13 * YES, DO A PERM SHIFT TO IT + CLR.W D4 * OTHERWISE, PERM SHIFT TO CS 0 +PSX13 MOVE.W D4,D5 * TEMP AND PERM CS'S ARE THE SAME NOW + BRA.S PSX16 + +PSX14 BSR PUTCHR * OUTPUT THE CHARACTER +PSX15 MOVE.W D5,D4 * RESET TEMP CS TO PERM CS +PSX16 DBF D3,PSX3 * LOOP FOR NEXT BYTE + + MOVEM.W (SP)+,D0-D2 * RESTORE POINTERS & ORIGINAL STRING WORD + TST.W D2 * END-OF-STRING (HIGH BIT SET)? + BPL PSX1 * NO, GO GET NEXT WORD + MOVEM.L (SP)+,D2-D5 * YES, CLEAN UP & RETURN UPDATED POINTER + RTS + +* GIVEN AN ASCII CHARACTER IN D0, RETURN THE CHARACTER SET # IN D0 + +CHRCS TST.B D0 * IS THIS A NULL? + BNE.S CHRCX1 * NO + MOVEQ #3,D0 * YES, RETURN DUMMY CS NUMBER + BRA.S CHRCX4 + +CHRCX1 CMPI.B #'a',D0 * LOWERCASE CHAR? + BLT.S CHRCX2 * NO + CMPI.B #'z',D0 + BGT.S CHRCX2 * NO + CLR.W D0 * YES, RETURN CS 0 + BRA.S CHRCX4 + +CHRCX2 CMPI.B #'A',D0 * UPPERCASE CHAR? + BLT.S CHRCX3 * NO + CMPI.B #'Z',D0 + BGT.S CHRCX3 * NO + MOVEQ #1,D0 * YES, RETURN CS 1 + BRA.S CHRCX4 + +CHRCX3 MOVEQ #2,D0 * OTHERWISE CALL IT CS 2 +CHRCX4 RTS + +* GIVEN AN ASCII CHARACTER IN D0, RETURN ZSTR BYTE VALUE IN D0 (6 TO 31, OR 0) + +CHRBYT LEA ZCHRS,A0 * POINT TO CONVERSION VECTOR + +CHRBX1 CMP.B (A0)+,D0 * FOUND THE CHARACTER? + BEQ.S CHRBX2 * YES + TST.B (A0) * END OF STRING? + BNE.S CHRBX1 * NO, CONTINUE SEARCH + CLR.W D0 * YES, RETURN ZERO FOR FAILURE + BRA.S CHRBX4 + +CHRBX2 MOVE.L A0,D0 * CALCULATE OFFSET OF CHAR INTO VECTOR + LEA ZCHRS,A0 + SUB.L A0,D0 + ADDQ.W #5,D0 * ADJUST OFFSET SO FIRST CHAR IS 6 + +CHRBX3 CMPI.W #32,D0 * IN BASE CODE RANGE (6-31)? + BLT.S CHRBX4 * YES + SUBI.W #26,D0 * SUBTRACT MULTIPLES OF 26 UNTIL BASE CODE + BRA.S CHRBX3 +CHRBX4 RTS + + +* GIVEN UP TO 6 (EZIP 9) ASCIZ CHARACTERS, BUFFER POINTER IN A1, +* CONVERT THEM TO A TWO (EZIP THREE) WORD ZSTR, BUFFER POINTER IN A0 + +PADCHR EQU 5 * ZSTR PADDING CHAR (SHIFT 2) + +ZWORD MOVEM.L D1-D2/A2,-(SP) + MOVE.L A0,A2 + MOVE.W #VCHARS,D2 * NUMBER OF PACKED CHARS IN A ZSTR (6 OR 9) + +ZWX1 CLR.W D1 + MOVE.B (A1)+,D1 * GET NEXT CHARACTER, END-OF-STRING? + BEQ.S ZWX4 * YES + + MOVE.W D1,D0 + BSR CHRCS * FIND THE CS NUMBER FOR THIS CHAR + TST.W D0 * CS 0? + BEQ.S ZWX2 * YES + ADDQ.W #3,D0 * NO, CALCULATE TEMP SHIFT BYTE + MOVE.W D0,-(SP) * SAVE THE SHIFT BYTE + SUBQ.W #1,D2 * REDUCE BYTE COUNT, DONE YET? + BEQ.S ZWX6 * YES + +ZWX2 MOVE.W D1,D0 + BSR CHRBYT * FIND THE PROPER BYTE VALUE FOR THIS CHAR + TST.W D0 * IN NORMAL CS'S? + BNE.S ZWX3 * YES + + MOVEQ #6,D0 * NO, USE ASCII SHIFT + MOVE.W D0,-(SP) + SUBQ.W #1,D2 * DONE YET? + BEQ.S ZWX6 * YES + + MOVE.W D1,D0 * NO, SAVE HIGH-ORDER ASCII BITS (3) + ASR.W #5,D0 + MOVE.W D0,-(SP) + SUBQ.W #1,D2 * DONE YET? + BEQ.S ZWX6 * YES + + MOVE.W D1,D0 * NO, SAVE LOW-ORDER ASCII BITS (5) + ANDI.W #$001F,D0 +ZWX3 MOVE.W D0,-(SP) * SAVE THIS BYTE + + SUBQ.W #1,D2 * AND LOOP UNTIL ZWORD FULL + BNE ZWX1 + BRA.S ZWX6 + +ZWX4 MOVE.W #PADCHR,-(SP) * END OF STRING, SAVE A PAD BYTE + SUBQ.W #1,D2 * LOOP UNTIL ZSTR FULL + BNE.S ZWX4 + +*** BUILD A ZSTR FROM THE SAVED BYTES ... + +ZWX6 MOVE.W #VCHARS*2,D2 * 6 OR 9 CHARS (WORDS) ON STACK + MOVE.L SP,A0 * DON'T DISTURB SP YET (IN CASE OF INTERRUPTS) + ADDA.W D2,A0 + MOVE.W #VCHARS/3,D1 * 2 OR 3 TIMES THROUGH LOOP + +ZWX7 MOVE.W -(A0),D0 + ASL.W #5,D0 + OR.W -(A0),D0 + ASL.W #5,D0 + OR.W -(A0),D0 + MOVE.W D0,(A2)+ * STORE A PACKED ZWORD IN RETURN BUFFER + + SUBQ.W #1,D1 + BNE.S ZWX7 * GO FOR NEXT + + BSET #7,-2(A2) * SET HIGH-ORDER BIT IN LAST ZWORD + ADDA.W D2,SP * AND FLUSH THE STACK + + MOVEM.L (SP)+,D1-D2/A2 + RTS + + + PAGE +*-------------------------------------------------------------------------- +* GENERALIZED OUTPUT FOLDING ROUTINE +*-------------------------------------------------------------------------- + +* THE QUECHR ROUTINE IS CALLED WITH A POINTER TO A STRUCTURE CONTAINING +* THE VARIABLES BELOW. THIS ARRANGEMENT ALLOWS FOR THE EXISTANCE OF MORE THAN +* ONE STRUCTURE, USEFUL IF DISPLAYED TEXT AND SCRIPTED TEXT ARE TO FOLD AT +* DIFFERENT POINTS. + +* THE STRUCTURE IDENTIFIES TWO ACTION ROUTINES. THE OUTPUT FUNCTION +* DUMPS THE BUFFER WHEN IT BECOMES FULL. THE SIZE FUNCTION ALLOWS FOR THE +* HANDLING OF PROPORTIONALLY SPACED TEXT. + +* THE LAST TWO VARIABLES ARE CURRENTLY IGNORED, BUT MIGHT BE USEFUL +* FOR IMPLEMENTING RECALCULATION OF THE FOLD POINTS FOR A PARAGRAPH OF TEXT, +* AS WHEN A WINDOW CHANGES SIZE. + + +* DATA STRUCTURE FOR QUEUE-PARAMETERS BLOCK + +BUFPTR EQU 0 * START OF BUFFER +BUFSIZ EQU 4 * MAXIMUM UNITS IN BUFFER + +NXTPTR EQU 6 * CURRENT POSITION WITHIN BUFFER +CURSIZ EQU 10 * CURRENT UNITS IN BUFFER + +SIZFUN EQU 12 * GIVEN A CHAR, RETURNS UNIT SIZE +OUTFUN EQU 16 * GIVEN BUFPTR & ENDPTR, DUMPS BUFFER, ADDS CR +RETFUN EQU 20 * (UNUSED -- THIS SHOULD ADD THE CR) + +DUMPED EQU 24 * WAS BUFFER EMPTIED (WITHOUT CR) BEFORE FULL? +AUTOCR EQU 25 * APPEND A CR TO EACH BUFFER DUMP? *** YES +KEEPSP EQU 26 * DON'T DISCARD TRAILING SPACE? *** NO + +QPLEN EQU 28 * LENGTH OF BLOCK (ALWAYS EVEN) + + +* ALLOCATE AND INITIALIZE A QUEUE PARAMETER BLOCK, +* D1 IS MAXIMUM SIZE OF BUFFER (IN BYTES), D2 IS INITIAL UNIT SIZE +* A1 POINTS TO LINE OUTPUT FUNCTION, A2 POINTS TO UNIT SIZE FUNCTION +* RETURN BLOCK POINTER IN A0 + +INITQP MOVE.W D1,D0 + ADD.W #QPLEN,D0 * TOTAL SPACE TO ALLOCATE + EXT.L D0 + BSR GETMEM * GET IT + + MOVE.L A0,D0 * PARAMETERS BLOCK WILL START HERE + ADD.L #QPLEN,D0 + MOVE.L D0,BUFPTR(A0) * LINE BUFFER STARTS HERE + MOVE.L D0,NXTPTR(A0) * ALSO CURRENT POINTER + + MOVE.W D2,BUFSIZ(A0) * UNIT CAPACITY OF BUFFER + CLR.W CURSIZ(A0) * ALWAYS EMPTY INITIALLY + + MOVE.L A1,OUTFUN(A0) * INITIALIZE LINE OUTPUT FUNCTION + MOVE.L A2,SIZFUN(A0) * INITIALIZE CHAR SIZE FUNCTION + + CLR.B DUMPED(A0) * THIS ONE IS SET ONLY BY PUTLIN + RTS * RETURN THE POINTER IN A0 + + +* QUEUE THE CHAR IN D0 FOR OUTPUT, A0 POINTS TO QUEUE-PARAMETERS BLOCK + +QUECHR MOVEM.L D4/A1-A4,-(SP) + MOVE.W D0,D4 + MOVE.L A0,A4 + + MOVE.W CURSIZ(A4),D0 + CMP.W BUFSIZ(A4),D0 * BUFFER FULL YET? + BLT QCX8 * NO +*** BGT QCX0 * OVERFULL (DEQUE THE LAST CHAR AND REENTER) + + CMPI.B #32,D4 * YES, BUT DID A SPACE CAUSE OVERFLOW? + BNE.S QCX1 * NO + + MOVE.L NXTPTR(A4),D0 * YES, JUST PRINT THE WHOLE BUFFER + MOVE.L BUFPTR(A4),A0 + + MOVE.L OUTFUN(A4),A3 + JSR (A3) + + CLR.W CURSIZ(A4) * RESET LENGTH COUNTER + MOVE.L BUFPTR(A4),NXTPTR(A4) * RESET CURRENT CHAR POINTER + CLR.B DUMPED(A4) * STARTING A FRESH LINE + BRA.S QCX9 * EXIT, IGNORING SPACE + +* FOLDING ROUTINE, SEARCH FOR MOST-RECENT SPACE ... + +QCX1 MOVE.L BUFPTR(A4),A1 * BEGINNING OF BUFFER + MOVE.L NXTPTR(A4),A2 * END OF BUFFER (+1) + BRA.S QCX2A * ALLOW FOR EMPTY [DUMPED] BUFFER + +QCX2 CMPI.B #32,-(A2) * SEARCH FOR SPACE BACKWARDS FROM END + BEQ.S QCX4 * FOUND ONE +QCX2A CMPA.L A1,A2 * REACHED BEGINNING OF BUFFER? + BGT QCX2 * NOT YET + +* NO SPACES FOUND, DUMP WHOLE BUFFER ... + +QCX3 TST.B DUMPED(A4) * BUT WAS THIS BUFFER ALREADY PARTLY EMPTIED? + BNE.S QCX5 * YES, CARRY EVERYTHING OVER TO NEXT LINE + + MOVE.L NXTPTR(A4),A2 * OTHERWISE, OUTPUT EVERYTHING + BRA.S QCX5 + +* SPACE WAS FOUND, DUMP THE BUFFER (THROUGH SPACE) ... + +QCX4 MOVE.L A2,A0 * POINTER TO THE SPACE + ADDQ.L #1,A2 * POINTER PAST THE SPACE + + CMPA.L A1,A0 * DEGENERATE CASE WITH SPACE AT BUFPTR? + BEQ.S QCX3 * YES, OUTPUT WHOLE LINE + +QCX5 MOVE.L A2,D0 * LAST CHAR TO PRINT (+1) + MOVE.L A1,A0 * START OF BUFFER + + MOVE.L OUTFUN(A4),A3 * GO DUMP IT, ADDING A CR + JSR (A3) + +* SHIFT ANY REMAINING CHARS TO FRONT OF BUFFER ... + + CLR.W CURSIZ(A4) * ZERO THE UNIT COUNT + CLR.B DUMPED(A4) * START WITH A FRESH BUFFER + BRA.S QCX7 + +QCX6 MOVE.B (A2)+,D0 + MOVE.B D0,(A1)+ * COPY NEXT CHAR TO BEGINNING OF BUF + + MOVE.L SIZFUN(A4),A0 * CHAR STILL IN D0 + JSR (A0) + ADD.W D0,CURSIZ(A4) * UPDATE THE UNIT COUNT + +QCX7 CMPA.L NXTPTR(A4),A2 * ANY MORE CHARS AFTER SPACE? + BLT QCX6 * YES + MOVE.L A1,NXTPTR(A4) * NO, STORE NEW CURRENT POINTER HERE + +* FINALLY, STORE THE NEW CHAR AND EXIT ... + +QCX8 MOVE.L NXTPTR(A4),A0 + MOVE.B D4,(A0)+ * STORE THE NEW CHARACTER IN BUFFER + MOVE.L A0,NXTPTR(A4) * AND UPDATE POINTER + + TST.W WIND1(A6) * BUT IF WE'RE IN SPLIT SCREEN, + BNE.S QCX9 * DON'T TOUCH COUNTER (SEE ALSO OPBUFO) + + MOVE.W D4,D0 + MOVE.L SIZFUN(A4),A0 + JSR (A0) * GET UNIT SIZE OF NEW CHAR + ADD.W D0,CURSIZ(A4) * AND UPDATE COUNTER + +QCX9 MOVEM.L (SP)+,D4/A1-A4 + RTS + +*-------------------------------------------------------------------------- +* MAIN OUTPUT HANDLER +*-------------------------------------------------------------------------- + +* !ALL! OUTPUT GENERATED BY THE GAME (AND THE USER) SHOULD BE CHANNELED +* THROUGH THE FOLLOWING TWO ROUTINES, WHICH REDIRECT IT APPROPRIATELY. + + +* OUTPUT A NEWLINE + +PUTNEW MOVEQ #13,D0 * JUST FALL THROUGH WITH A CR + +* OUTPUT THE CHAR IN D0 (TO THE REQUESTED DEVICES) + +PUTCHR CMPI.B #9,D0 * TAB? (OLD ZORK BUG, DISPLAYS GARBAGE) + BNE.S PCX1 + MOVEQ #32,D0 * YES, MAP TO A SPACE +PCX1 + +*** STATUS LINE OUTPUT (ZIP INTERNAL FUNCTION ONLY) ... + + IFEQ CZIP + TST.W VOSTAT(A6) * SPECIAL OUTPUT TO SL HANDLER? + BNE PUTSL * YES (ABORT PUTCHR) + ENDC + +*** TABLE OUTPUT ... + + IFEQ EZIP + TST.W VOTABL(A6) * TABLE OUTPUT? + BNE TABCHR * YES (ABORT PUTCHR PER "DIROUT" SPEC) + ENDC + + MOVE.W D0,-(SP) * OTHERWISE, SAVE THE CHAR HERE + +*** SCRIPT (BEFORE SCREEN, TO PERMIT ERROR HANDLING) ... + + TST.W WIND1(A6) * BUT ARE WE IN WINDOW 1? + BNE.S PCX2 * YES, TEMPORARILY AVOID SCRIPTING + + IFEQ EZIP + TST.W VOPRNT(A6) * SCRIPTING ACTIVE? + ENDC + IFEQ CZIP + BSR TSTSCR * CHECK FOR SCRIPTING REQUEST -- ACTIVE? + ENDC + BEQ.S PCX2 * NO + + MOVE.W (SP),D0 * SCRIPT THIS CHAR + BSR SCRCHR + +*** SCREEN DISPLAY ... + +PCX2 TST.W VOCONS(A6) * CONSOLE OUTPUT ACTIVE? + BEQ.S PCX3 * NO + + MOVE.W (SP),D0 * YES, DISPLAY THE CHAR + BSR QDCHR + +*** FILE OUTPUT ... + +PCX3 NOP * NOT IMPLEMENTED + + TST.W (SP)+ * FLUSH CHAR FROM STACK + RTS + + +*-------------------------------------------------------------------------- +* TERMINAL DISPLAY FUNCTIONS +*-------------------------------------------------------------------------- + +* QUEUE/DISPLAY THE CHAR IN D0 + +QDCHR TST.W VOBUFF(A6) * IS BUFFERING TURNED OFF? + BEQ OUTCHR * YES, GO TO SCREEN (THIS HANDLES CR'S ALSO) + + CMPI.B #13,D0 * CR? + BEQ.S NEWLIN * YES, DUMP THE BUFFER + + MOVE.L DQUE(A6),A0 * OTHERWISE, GO QUEUE IT + BRA QUECHR + +* GO TO NEW LINE, OUTPUTTING CURRENT BUFFER +* (THIS ROUTINE NOW CALLED ONLY FROM THE PRECEEDING ROUTINE) + +NEWLIN MOVE.L A4,-(SP) + MOVE.L DQUE(A6),A4 * SCREEN BUFFER + + MOVE.L BUFPTR(A4),A0 * START OF LINE + MOVE.L NXTPTR(A4),D0 * END OF CURRENT LINE + BSR LINOUT * CHECK "MORE", OUTPUT LINE, ADD A CR + + MOVE.L BUFPTR(A4),NXTPTR(A4) * RESET CHARACTER POINTER + CLR.W CURSIZ(A4) * RESET UNIT COUNT + CLR.B DUMPED(A4) * NO OUTPUT ON NEW LINE YET + + MOVE.L (SP)+,A4 + RTS + +* OUTPUT CURRENT BUFFER, WITHOUT A NEWLINE +* (ASSUMES SOMETHING LIKE OPREAD WILL SUPPLY THE NEWLINE) + +PUTLIN MOVE.L DQUE(A6),A0 + CLR.W CURSIZ(A0) * RESET UNIT COUNT (BUFFER EMPTY) + +* ENTER HERE IF BUFFERING WILL LATER RESUME FROM CURRENT POINT + +PUTLIN1 MOVE.L A4,-(SP) + MOVE.L DQUE(A6),A4 * SCREEN BUFFER + + MOVE.L BUFPTR(A4),A0 * START OF LINE + MOVE.L NXTPTR(A4),D0 * END OF CURRENT LINE + BSR BUFOUT * OUTPUT IT (NO "MORE", NO CR) + + MOVE.L BUFPTR(A4),NXTPTR(A4) * RESET CHARACTER POINTER + MOVE.B #1,DUMPED(A4) * REMEMBER BUFFER IS PARTLY DUMPED + MOVE.L (SP)+,A4 + RTS + + +* INPUT A CHARACTER FROM TERMINAL + +GETCHR BRA INCHR * JUST GET IT + + +*-------------------------------------------------------------------------- +* SCRIPT BUFFERING +*-------------------------------------------------------------------------- + +* QUEUE THE CHAR IN D0 FOR SCRIPTING + +SCRCHR CMPI.B #13,D0 * CR? + BEQ.S SCRLIN * YES, GO DUMP SCRIPT BUFFER + + MOVE.L SQUE(A6),A0 * SCRIPTING PARAMETERS BLOCK + BRA QUECHR * GO QUEUE IT + +* SCRIPT A NEWLINE, OUTPUTTING CURRENT SCRIPT BUFFER + +SCRLIN MOVE.L A4,-(SP) + MOVE.L SQUE(A6),A4 * SCRIPTING PARAMETERS BLOCK + + MOVE.L BUFPTR(A4),A0 * START OF LINE + MOVE.L NXTPTR(A4),D0 * END OF CURRENT LINE + BSR SCROUT * OUTPUT LINE, ADD A CR ... + + MOVE.L BUFPTR(A4),NXTPTR(A4) * RESET CHARACTER POINTER + CLR.W CURSIZ(A4) * RESET UNIT COUNT + + MOVE.L (SP)+,A4 + RTS + +* SCRIPT THE USER INPUT LINE, START IN A0, END IN D0 +* (WAIT UNTIL USER INPUT IS FINISHED TO AVOID PROBLEMS WITH BACKSPACES) + +SCRINP MOVEM.L A1/D1,-(SP) + MOVE.L A0,A1 * PROTECT ARGS + MOVE.L D0,D1 + + IFEQ EZIP + TST.W VOPRNT(A6) * SCRIPTING? + ENDC + IFEQ CZIP + BSR TSTSCR * CHECK FOR SCRIPT REQUEST -- ACTIVE? + ENDC + BEQ.S SCRIX3 * NO, EXIT + + SUB.L A1,D1 * LENGTH OF INPUT -- ANYTHING? + BEQ.S SCRIX2 * NO, JUST DO THE CR + +SCRIX1 MOVE.B (A1)+,D0 * SCRIPT NEXT CHAR + BSR SCRCHR * (GO THRU BUFFER SO WRAPPING IS CORRECT) + SUBQ.W #1,D1 + BGT SCRIX1 + +SCRIX2 MOVEQ #13,D0 * ALWAYS END WITH A CR + BSR SCRCHR + +SCRIX3 MOVEM.L (SP)+,D1/A1 + RTS + + + PAGE +* ---------------------------------------------------------------------------- +* PAGING ROUTINES +* ---------------------------------------------------------------------------- + +* NORMALIZE ZPC & (IF NECESSARY) GET PROPER PAGE + +NEWZPC MOVE.W ZPC2(A6),D0 * LOW ORDER ZPC + ASR.W #8,D0 * EXTRACT REQUIRED BLOCK ADJUSTMENT (+ OR -) + ASR.W #1,D0 + + ADD.W D0,ZPC1(A6) * AND ADJUST HIGH ORDER ZPC + ANDI.W #$01FF,ZPC2(A6) * NORMALIZE LOW ORDER ZPC + +* GET THE INDICATED PAGE + + MOVE.W ZPC1(A6),D0 + CMP.W CURBLK(A6),D0 * HAS THE BLOCK CHANGED? + BEQ.S NZX4 * NO, EXIT + MOVE.W D0,CURBLK(A6) * YES, REMEMBER NEW BLOCK + + TST.L CURTAB(A6) * IS OLD PAGE PRELOADED? + BEQ.S NZX2 * YES + MOVE.L CURTAB(A6),A0 * NO, RESTORE CURRENT REF TIME FOR OLD PAGE + MOVE.L RTIME(A6),2(A0) + +NZX2 CMP.W ENDLOD(A6),D0 * IS NEW PAGE PRELOADED? + BLT.S NZX3 * YES + BSR GETPAG * NO, GET THE NEW PAGE + MOVE.L A0,CURPAG(A6) * REMEMBER NEW PAGE POINTER + + MOVE.L LPTAB(A6),A0 * GET NEW TABLE POINTER + MOVE.L A0,CURTAB(A6) * SAVE THIS POINTER FOR LATER + MOVE.L #-1,2(A0) * FAKE A HIGH RTIME TO PROTECT ZPC PAGE FOR US + BRA.S NZX4 + +NZX3 BSR BLKBYT * CALCULATE PRELOAD PAGE ADDRESS + ADD.L BUFFER(A6),D0 * ABSOLUTIZE + MOVE.L D0,CURPAG(A6) * REMEMBER NEW PAGE POINTER + CLR.L CURTAB(A6) * ZERO TABLE POINTER MEANS PAGE IS PRELOADED + +NZX4 RTS + +* GET THE PAGE WHOSE NUMBER IS IN D0, RETURN A POINTER TO IT IN A0 + +GETPAG CMP.W LPAGE(A6),D0 * IS THIS THE SAME PAGE AS LAST REFERENCED? + BEQ.S GPX4 * YES, RETURN ITS LOCATION + + MOVE.W D0,LPAGE(A6) * SAVE NEW PAGE NUMBER + ADDQ.L #1,RTIME(A6) * UPDATE REFERENCE COUNT + MOVE.L PAGTAB(A6),A0 * PAGE INFORMATION TABLE + +GPX1 CMP.W (A0),D0 * SEARCH FOR DESIRED BLOCK + BNE.S GPX3 * NOT IT + + CMP.W CURBLK(A6),D0 * FOUND IT, BUT IS IT THE CURRENT ZPC PAGE? + BEQ.S GPX2 * YES, DON'T TOUCH REF TIME (PAGE IS PROTECTED) + MOVE.L RTIME(A6),2(A0) * NO, UPDATE ITS REFERENCE TIME + +GPX2 MOVE.L A0,LPTAB(A6) * SAVE THE TABLE POINTER + MOVE.L A0,D0 + SUB.L PAGTAB(A6),D0 * BUFFER NUMBER x8 + ASL.L #6,D0 * CALCULATE CORE ADDRESS OF PAGE + ADD.L PAGES(A6),D0 + MOVE.L D0,LPLOC(A6) * SAVE IT + BRA.S GPX4 * AND RETURN IT + +GPX3 ADDQ.L #8,A0 * SKIP OVER REFERENCE TIME, ETC. + CMPI.W #-1,(A0) * END OF TABLE? + BNE.S GPX1 * NO, CONTINUE SEARCH + +* DESIRED PAGE NOT RESIDENT, MUST READ IT FROM DISK + + MOVE.L A1,-(SP) + BSR FINDPG * FIND AN OLD PAGE + MOVE.L A0,LPLOC(A6) * SAVE ITS PAGE POINTER + MOVE.L A1,LPTAB(A6) * SAVE ITS PAGTAB POINTER + + MOVE.W LPAGE(A6),D0 * NEW PAGE NUMBER FOR GETBLK + MOVE.W D0,(A1)+ * SAVE PAGE NUMBER IN FIRST SLOT + MOVE.L RTIME(A6),(A1) * SAVE CURRENT REF TIME + + BSR GETBLK * GET THE BLOCK + MOVE.L (SP)+,A1 * CLEAN UP + + IFEQ DEBUG + ADDQ.L #1,DBTOT1(A6) * TOTAL PAGE FAULTS + ENDC + +GPX4 MOVE.L LPLOC(A6),A0 * RETURN THE PAGE POINTER + RTS + +* FIND A GOOD (LRU) PAGE, RETURN PAGE POINTER IN A0 & PAGTAB POINTER IN A1 + +FINDPG MOVE.L PAGTAB(A6),A0 + ADDQ.L #2,A0 * SKIP OVER FIRST PAGE NUMBER + MOVE.L #-1,D0 * FAKE A BEST-CASE REFERENCE COUNT + +FDPGX1 CMP.L (A0),D0 * COMPARE PREV OLDEST REF TIME WITH THIS ONE + BLS.S FDPGX2 * STILL THE OLDEST + + MOVE.L (A0),D0 * NEW OLDEST, SAVE THIS REFERENCE COUNT + MOVE.L A0,A1 * AND PAGTAB LOCATION (+2) + +FDPGX2 ADDQ.L #6,A0 * SKIP OVER REF TIME, ETC. + CMPI.W #-1,(A0)+ * END OF TABLE? + BNE.S FDPGX1 * NO + + SUBQ.L #2,A1 * RETURN THE PAGTAB LOCATION HERE + MOVE.L A1,D0 + SUB.L PAGTAB(A6),D0 * BUFFER NUMBER x8 + ASL.L #6,D0 * CALCULATE CORE ADDRESS OF PAGE + ADD.L PAGES(A6),D0 + MOVE.L D0,A0 * AND RETURN IT HERE + RTS + diff --git a/amiga/zip4.asm b/amiga/zip4.asm new file mode 100644 index 0000000..569a83e --- /dev/null +++ b/amiga/zip4.asm @@ -0,0 +1,1052 @@ + + PAGE +* ---------------------------------------------------------------------- +* MACHINE-DEPENDENT ROUTINES +* ---------------------------------------------------------------------- + +* MISC SYSTEM INITIALIZATION + +SYSINI +* LEA _curs_interrupt,A0 * SET UP OUR CURSOR TIMER +* MOVE.L A0,_curs_addr + + BSR OPNGAM * OPEN THE GAME FILE, SET UP GAMFIL(A6) + BNE.S SYSIX1 * ERROR, ABORT + RTS + +SYSIX1 LEA MSGOPN,A0 * ERROR CODE IN D0 + BRA FATAL * 'Story file open error' + + SECTION ZDATA +MSGOPN DC.B 'Story file open error',0 + SECTION ZCODE + +* ALLOCATE SOME MEMORY (NON-RELOCATABLE), NUMBER OF BYTES REQUESTED IN D0.L +* RETURN POINTER IN A0 + +GETMEM MOVEM.L D1-D7/A1-A5,-(SP) + + MOVE.L D0,-(SP) * BYTES NEEDED + JSR _c_getmem + ADDQ.W #4,SP * FLUSH STACK + + TST.L D0 * GOT IT? + BEQ.S GETMX1 * NO + MOVE.L D0,A0 * YES, RETURN POINTER + + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +GETMX1 CLR.W D0 + LEA MSGGTM,A0 + BRA FATAL * 'Memory block allocation error' + + SECTION ZDATA +MSGGTM DC.B 'Memory block allocation error',0 + SECTION ZCODE + +* DETERMINE AVAILABLE MEMORY +* GIVEN MAX GAME LENGTH + OVERHEAD (BYTES) IN D0.L +* RETURN BYTES AVAILABLE IN D0.L + +MEMSYS EQU 0 * FUDGE FACTOR FOR RUNTIME OVERHEAD + +MEMAVAIL + MOVEM.L D1-D7/A1-A5,-(SP) + MOVE.L D0,-(SP) + JSR _c_maxmem + ADDQ.W #4,SP + MOVEM.L (SP)+,D1-D7/A1-A5 + +* SUB.L #MEMSYS,D0 * (MOVED INTO HIGH-LEVEL INTERFACE) + RTS + +* HERE IF INIT FINDS TOO LITTLE MEMORY FOR PRELOAD + +MEMERR CLR.W D0 + LEA MSGME1,A0 + BRA FATAL * 'Not enough available memory' + + SECTION ZDATA +MSGME1 DC.B 'Not enough available memory',0 + SECTION ZCODE + +* PRODUCE A SOUND + +DOSOUND + MOVEM.L D1-D7/A1-A5,-(SP) + MOVE.L D2,-(SP) * VOLUME + MOVE.L D1,-(SP) * ACTION + MOVE.L D0,-(SP) * ID + JSR _md_sound + ADDA.W #12,SP + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* RETURN A RANDOM NUMBER SEED IN D0, DIFFERENT EACH TIME BOOTED + +GTSEED + MOVEM.L D1-D7/A1-A5,-(SP) + JSR _random_seed + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* RETURN TIME IN 60THS SECOND SINCE SYSTEM STARTUP + +TIME60 + CLR.L D0 *** EZIP ONLY *** + RTS + +* GIVEN AN ASCII CHAR, RETURN ITS UNIT WIDTH (IN CURRENT FONT) + +CHSIZ MOVEQ #1,D0 *** ALWAYS ONE, FOR NOW + RTS + +* GET THE CURRENT CURSOR POSITION, RETURN ROW/D0, COLUMN/D1 + +GETCUR MOVEM.L D1-D7/A1-A6,-(SP) + JSR _read_cursor_pos * READ THE CONSOLE DEVICE + MOVEM.L (SP)+,D1-D7/A1-A6 + + MOVE.W _cur_row,D0 * RETRIEVE VALUES FROM GLOBALS + MOVE.W _cur_column,D1 + RTS + +* SET THE CURRENT CURSOR POSITION, GIVEN ROW/D0, COLUMN/D1 + +SETCUR MOVE.W D0,_cur_row * FIRST SET THE GLOBALS + MOVE.W D1,_cur_column + + MOVEM.L D1-D7/A1-A6,-(SP) + JSR _write_cursor_pos * INFORM THE CONSOLE DEVICE + MOVEM.L (SP)+,D1-D7/A1-A6 + RTS + + +* RESTART THE SYSTEM (RETURN TO THE DESKTOP) + +FINISH MOVEQ #0,D0 * LAST-USED SOUND ID + MOVEQ #4,D1 * CLEANUP + BSR DOSOUND * MAKE SURE IT'S GONE + + TST.L GAMFIL(A6) * GAME FILE OPEN? + BEQ.S FINIX1 * NO + BSR CLSGAM * YES, CLOSE THE GAME FILE + BEQ.S FINIX1 * OK IF ZERO + + LEA MSGCLS,A0 * ERROR, INFORM USER + BSR OUTMSG * 'Story file close error' + SECTION ZDATA +MSGCLS DC.B 'Story file close error',0 + SECTION ZCODE + +FINIX1 TST.W INLAST(A6) * HAS THERE BEEN INPUT SINCE LAST OUTPUT? + BNE.S FINIX2 * YES, JUST EXIT + + BSR PUTNEW * NO, MUST FIRST PAUSE FOR A PROMPT + LEA MSGKEY,A0 + BSR OUTMSG0 * 'Strike any key to exit ' + + SECTION ZDATA +MSGKEY DC.B 'Strike any key to exit ',0 + SECTION ZCODE + +* OUGHT TO FLUSH TYPED-AHEAD KEYS (IF ANY) ... + + BSR TTYIN * WAIT FOR A KEY +FINIX2 UNLK A6 * FLUSH THE ZIP'S STACK FRAME + RTS * RETURN FROM WHENCE WE CAME + + + PAGE +* ----------------------------------------------- +* SCREEN/KEY I/O +* ----------------------------------------------- + +* CALLS TO TTYIN OR INCHR SHOULD BE BRACKETED BY CALLS TO SETUP_INPUT +* IT SHOWS/HIDES THE INPUT CURSOR AND DOES OTHER STUFF +* D0 = 1 FOR BEGIN, 0 FOR END + +SETUPI + RTS + + +* OUTPUT THE STATUS LINE, STRINGS IN A0-A1, LENGTHS IN D0-D1 + +STLINE MOVEM.L D2-D7/A2-A5,-(SP) + + MOVE.L D1,-(SP) * LEN2, STR2 + MOVE.L A1,-(SP) + MOVE.L D0,-(SP) * LEN1, STR1 + MOVE.L A0,-(SP) + JSR _show_status + + ADDA.W #16,SP * FLUSH STACK (14 ACTUAL) + MOVEM.L (SP)+,D2-D7/A2-A5 + RTS + +* INPUT A CHAR AND ECHO IT, RETURN CHAR IN D0 +* SPECIAL HANDLING FOR BACKSPACE + +INCHR BSR TTYIN * GET CHAR + TST.W VIECHO(A6) * IS ECHOING TURNED OFF? + BEQ.S INCHX2 * YES, JUST EXIT + + CMPI.B #8,D0 * BACKSPACE? + BNE.S INCHX1 * NO, ECHO + TST.W CHRTOT(A6) * YES, BUT HAS ALL USER INPUT BEEN DELETED? + BEQ.S INCHX2 * YES, JUST EXIT + +INCHX1 MOVE.W D0,-(SP) + BSR TTYOUT * ECHO THE CHAR HERE + MOVE.W (SP)+,D0 +INCHX2 RTS + +* INPUT A SINGLE CHAR, NO ECHO (NULL MEANS EDIT OPERATION) + +TTYIN MOVE.W #1,INLAST(A6) * CURRENT I/O IS INPUT + MOVE.W #1,LINES(A6) * RESET COUNTER, ALLOWING FOR THIS LINE + + MOVEM.L D1-D7/A1-A5,-(SP) + +TTYX1 JSR _char_in + ANDI.W #$00FF,D0 * CLEAR UNWANTED BYTE + + CMPI.B #$0D,D0 * PASS ALONG THE STANDARD CONTROL CHARS + BEQ.S TTYX2 + CMPI.B #$08,D0 + BEQ.S TTYX2 + + CMPI.B #$20,D0 * FILTER OUT AND IGNORE OTHER CONTROL CHARS + BLT TTYX1 + CMPI.B #$7F,D0 + BGT TTYX1 + + CMPI.B #$7F,D0 + BNE TTYX2 + MOVEQ #8,D0 * MAP "DELETE" TO "BACKSPACE" + +TTYX2 MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* OUTPUT THE CHAR (OR CR) IN D0.B (SCROLLING IF NECESSARY) + +OUTCHR CLR.W INLAST(A6) * CURRENT I/O IS OUTPUT + +TTYOUT MOVEM.L D1-D7/A1-A5,-(SP) +* *** ANDI.W #$00FF,D0 * CLEAR UNWANTED BYTE + + MOVE.L D0,-(SP) + JSR _char_out + ADDQ.W #4,SP * FLUSH STACK (2 ACTUAL) + + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* CHECK FOR END-OF-PAGE CONDITION [COUNTER IS UPDATED ELSEWHERE] + +NXTLIN MOVE.W _rows,D0 + SUB.W _split_row,D0 * LINES AVAILABLE FOR DISPLAY + SUBQ.W #1,D0 * ALLOW SPACE FOR [MORE] + + CMP.W LINES(A6),D0 * PAGE FULL YET? + BNE NXTLX2 * NO + + MOVEM.L D1-D7/A1-A5,-(SP) + IFEQ CZIP + BSR OPUSL * YES, UPDATE STATUS LINE NOW + ENDC + JSR _show_more * DISPLAY A PROMPT AND WAIT + MOVEM.L (SP)+,D1-D7/A1-A5 + + MOVE.W #1,LINES(A6) * RESET COUNTER, ALLOWING FOR ONE PREVIOUS LINE +NXTLX2 RTS + +* OUTPUT A STRING, POINTER IN A0, LENGTH IN D0.W + +PRINT CLR.W INLAST(A6) * CURRENT I/O IS OUTPUT + MOVEM.L D1-D7/A1-A5,-(SP) + + MOVE.L D0,-(SP) * LENGTH IN BYTES + MOVE.L A0,-(SP) * POINTER + JSR _line_out + ADDQ.W #8,SP * FLUSH STACK (6 ACTUAL) + + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* OUTPUT THE LINE BUFFER, BEGINNING AND END IN A0, D0 +* FIRST CHECK FOR END-OF-SCREEN CONDITION (UNLESS IN WINDOW 1) + +BUFOUT TST.W WIND1(A6) * IN WINDOW 1? + BNE BUFUX1 * YES, SKIP THE SCREEN CHECK + + MOVEM.L D0/A0,-(SP) + BSR NXTLIN * PAUSE FOR [MORE] IF NECESSARY + MOVEM.L (SP)+,D0/A0 + +BUFUX1 SUB.L A0,D0 * CURRENT LENGTH OF BUFFER IN D0.W + BLE BUFUX2 * EXIT IF ZERO + BSR PRINT * OTHERWISE, DISPLAY IT +BUFUX2 RTS + +* OUTPUT THE LINE BUFFER THEN ADD A CR, BEGINNING AND END IN A0, D0 +* ALSO UPDATE THE CUMULATIVE LINE COUNTER + +LINOUT BSR BUFOUT * DISPLAY IT + MOVEQ #13,D0 + BSR OUTCHR * AND TACK ON A CR + + TST.W WIND1(A6) * IN WINDOW 1? + BNE LINOX1 * YES, IGNORE COUNTER + + ADDQ.W #1,LINES(A6) * OTHERWISE UPDATE THE COUNTER +LINOX1 BRA RESIZE * CHECK LINE LENGTH + +* CHECK WHETHER DISPLAY WINDOW WAS RESIZED, AND ADJUST FOLDING ACCORDINGLY + +RESIZE + IFEQ CZIP * (ONLY CZIP WINDOWS CHANGE SIZE) + + MOVEM.L D1-D7/A1-A5,-(SP) + JSR _window_resized * GET WINDOW WIDTH + MOVEM.L (SP)+,D1-D7/A1-A5 + + MOVE.L DQUE(A6),A0 + MOVE.W D0,BUFSIZ(A0) * NEW WIDTH (CHANGED OR NOT) + ENDC + RTS + +* MAKE SURE GAME SCREEN WAS NOT LEFT HIDDEN BY AN SYSTEM ALERT + +UNHIDE + IFEQ EZIP * (ONLY EZIP USES A SECOND SCREEN) + MOVEM.L D1-D7/A1-A5,-(SP) + JSR _unhide_screen + MOVEM.L (SP)+,D1-D7/A1-A5 + ENDC + RTS + + PAGE +*---------------------------------------------------------------------------- +* ZIP MESSAGES +*---------------------------------------------------------------------------- + +* OUTPUT AN ASCIZ MESSAGE, POINTER IN A0 + +OUTMSG0 MOVEM.L A1-A2,-(SP) + MOVE.L A0,A1 * STRING POINTER + +OUTMX1 CLR.W D0 + MOVE.B (A1)+,D0 * GET NEXT CHAR, END OF STRING? + BEQ.S OUTMX2 * YES + + BSR PUTCHR * NO, DISPLAY/QUEUE IT + BRA.S OUTMX1 + +OUTMX2 TST.W VOBUFF(A6) * ARE WE BUFFERING OUTPUT? + BEQ.S OUTMX3 * NO + BSR PUTLIN1 * YES, EMPTY THE BUFFER + +OUTMX3 MOVEM.L (SP)+,A1-A2 + RTS + +* OUTPUT AN ASCIZ MESSAGE, POINTER IN A0 (NULL IF NONE) +* THEN APPEND A CR + +OUTMSG MOVE.L A0,D0 * ANY MESSAGE? + BEQ.S OUTMX9 * NO, JUST A CR + BSR OUTMSG0 * YES, OUTPUT THE STRING +OUTMX9 BRA PUTNEW + +* PRINT A FATAL ERROR HEADER, CODE NUMBER AND MESSAGE (LAST TWO ARE OPTIONALS) +* ERROR CODE IN D0, STRING IN A0, ZERO MEANS NONE + +FATAL MOVE.L A0,-(SP) + MOVE.W D0,-(SP) + BSR PUTNEW * NEW LINE + + LEA MSGFTL,A0 * PRINT A STANDARD ERROR HEADER, NO CR + BSR OUTMSG0 * 'Internal Error ' + + SECTION ZDATA +MSGFTL DC.B 'Internal Error ',0 + SECTION ZCODE + + MOVE.W (SP)+,D1 * GOT A NUMBER? + BEQ.S FATLX1 * NO + + MOVE.B #'#',D0 * YES, PRINT A PREFIX + BSR PUTCHR + + MOVE.W D1,D0 * PRINT THE ERROR NUMBER + BSR OPPRNN + +FATLX1 BSR PUTNEW + MOVE.L (SP)+,D0 * GOT A MESSAGE? + BEQ.S FATLX2 * NO + + MOVE.L D0,A0 * YES, DISPLAY THE STRING + BSR OUTMSG +FATLX2 BRA FINISH * GO WAIT FOR A FINAL KEY + +* -------------------------------------------------------------- +* SCRIPTING STUFF +* -------------------------------------------------------------- + +* TEST THE SCRIPT BIT, UPDATE THE SCRIPTING DEVICE AS NEEDED +* RETURN WITH FLAGS (NON-ZERO IF ACTIVE) + +TSTSCR MOVE.L BUFFER(A6),A0 + MOVE.B PFLAGS+1(A0),D0 + ANDI.W #1,D0 * MASK OFF SCRIPT BIT + BNE.S TSCRX1 * 1 MEANS SCRIPT REQUESTED + + BSR.S SCROPN * 0 MEANS OFF, DEACTIVATE THE SCRIPTING DEVICE + BRA.S TSCRX2 * RETURN (FLAGS CAN ONLY BE ZERO ...) + +TSCRX1 BSR SCROPN * ACTIVATE THE SCRIPTING DEVICE + BNE.S TSCRX2 * OK, ACTIVE + + BSR SCRERR * INACTIVE, MEANS ERROR OCCURRED, UNDO ALL + CLR.W D0 * CLEAR FLAGS +TSCRX2 RTS * RETURN WITH FLAGS + + +* TEST STATUS OF SCRIPTING DEVICE, RETURN FLAGS (ZERO IF NOT READY) + +SCRCHK +* *** MOVEM.L D1-D7/A1-A5,-(SP) +* *** * -1 MEANS PRINTER READY, 0 UNAVAILABLE +* *** MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* OPEN/CLOSE SCRIPTING DEVICE (D0.W SET FOR OPEN) +* RETURN ACTIVE/INACTIVE STATUS (D0.W SET FOR ACTIVE) + +SCROPN MOVEM.L D1-D7/A1-A5,-(SP) + EXT.L D0 * 1 FOR OPEN, ZERO FOR CLOSE + MOVE.L D0,-(SP) + JSR _script_open + ADDQ.W #4,SP + TST.W D0 * RETURN ACTIVE/INACTIVE + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* SCRIPT ERROR HANDLER +* WANT TO TERMINATE SCRIPTING ATTEMPTS (UNTIL NEXT SCRIPT COMMAND) +* DE-ACTIVATE PRINTER, ADJUST ZIP INTERNAL VARIABLES + +SCRERR MOVEM.L D1-D7/A1-A5,-(SP) + CLR.W D0 * ZERO FOR CLOSE + BSR SCROPN * DEACTIVATE THE DEVICE + + MOVE.L BUFFER(A6),A0 + BCLR #0,PFLAGS+1(A0) * FORCE SCRIPT BIT OFF (ZIP + EZIP) + + IFEQ EZIP + CLR.W VOPRNT(A6) * TURN OFF EZIP'S FLAG + ENDC + + LEA MSGPRR,A0 + BSR OUTMSG + BSR PUTNEW + + SECTION ZDATA +MSGPRR DC.B '*** Printer not ready, scripting terminated ***',0 + SECTION ZCODE + + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + + +* SCRIPT OUT A LINE, START IN A0, END IN D0, THEN TACK ON A CR/LF + +SCROUT MOVEM.L D1-D7/A1-A5,-(SP) + SUB.L A0,D0 * LENGTH OF STRING + + MOVE.L D0,-(SP) + MOVE.L A0,-(SP) + JSR _script_line + ADDQ.W #8,SP * FLUSH STACK (6 ACTUAL) + + TST.W D0 * ERROR? + BEQ.S SCOTX1 * NO + BSR SCRERR * YES, CLEAN UP AND DEACTIVATE + +SCOTX1 MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* -------------------------------------------------------------- +* *** PURE HACKERY *** +* -------------------------------------------------------------- + +* THE FOLLOWING ROUTINES EXIST TO ALLOW MACINTOSH USERS TO RESTORE A SAVED GAME +* FROM THE DESKTOP (FINDER) LEVEL, SKIPPING THE NORMAL GAME OPENING. THESE +* ROUTINES WILL FUNCTION AT MOST ONE TIME, AS THE GAME BOOTS. + +* RESTORE A SAVE FILE CHOSEN FROM THE FINDER + +BOOTSV + RTS + +* FORCE A DISPLAY OF THE VERSION INFORMATION (IGNORE IF SHOWVE IS NULL) +* RETURN THE "VERSION" STRING IN D0 (ONE CHAR AT A TIME), CR WHEN DONE +* THE STRING IS RETURNED THRU INCHR AND PRETENDS TO BE KEYBOARD INPUT + +SHOWTX + RTS * RETURN WITH FLAGS SET CORRECTLY + +* DELETE CHARS (THE PROMPT ">") FROM THE OUTPUT BUFFER, IF NECESSARY +* THIS IS CALLED JUST BEFORE FAKING THE "VERSION" COMMAND + +DELPRO + RTS + + + + PAGE +* --------------------------------------------------------------------------- +* DISK I/O ROUTINES +* --------------------------------------------------------------------------- + +* GENERAL CONVENTION FOR DISK ROUTINE RESULTS: +* IF ROUTINE SUCCEEDS, RETURN WITH FLAGS INDICATING "ZERO" +* OTHERWISE, CALLER TRAPS ERRORS WITH A CONDITIONAL BRANCH ("BNE.S ERROR") + + +* OPEN THE GAME FILE, STORE REFNUM, RETURN FLAGS +* (THIS ROUTINE CALLED DURING INIT *AND* DURING SAVE/RESTORE) + +OPNGAM MOVEM.L D1-D7/A1-A5,-(SP) + + JSR _open_game * OPEN THE GAME FILE + TST.L D0 + BNE OPNGX1 * ERROR + +* SUCCESS, SAVE THE GAME FILE REFERENCE NUMBER + + MOVE.L _temp_channel,GAMFIL(A6) + CLR.L D0 * RETURN ZERO FLAG FOR OKAY + +OPNGX1 MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + + +* CLOSE THE GAME FILE, RETURN FLAGS + +CLSGAM MOVEM.L D1-D7/A1-A5,-(SP) + + MOVE.L GAMFIL(A6),-(SP) + JSR _close_game * CLOSE THE GAME FILE + ADDQ.W #4,SP * FLUSH STACK (2 ACTUAL) + + CLR.L GAMFIL(A6) * ALWAYS ZERO WHEN FILE NOT OPEN + TST.L D0 * RETURN THE RESULT CODE + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* GET A GAME FILE BLOCK, BLOCK NUMBER IN D0, CORE TARGET LOCATION IN A0 + +GETBLK MOVEM.L D1,-(SP) + MOVEQ #1,D1 * ONE BLOCK + BSR GTBLKS + MOVEM.L (SP)+,D1 * (MOVEM DOES NOT ALTER FLAGS) + RTS + +* GET A SERIES OF GAME FILE BLOCKS +* FIRST BLOCK NUMBER IN D0, CORE TARGET LOCATION IN A0, NUMBER OF BLOCKS IN D1 + +GTBLKS MOVEM.L D2-D7/A1-A5,-(SP) + + BSR BLKBYT * CONVERT BLOCKS TO BYTES + EXG D1,D0 + BSR BLKBYT + EXG D1,D0 + + MOVE.L A0,-(SP) * BUFFER POINTER + MOVE.L D1,-(SP) * LENGTH IN BYTES + MOVE.L D0,-(SP) * OFFSET IN BYTES + + MOVE.L GAMFIL(A6),-(SP) + JSR _read_file + ADDA.W #16,SP * FLUSH STACK (14 ACTUAL) + TST.L D0 * ERROR ON READ? + BNE.S GTBKX2 * YES, FAIL + +GTBKX1 MOVEM.L (SP)+,D2-D7/A1-A5 + RTS + +* TST.W DSKERR(A6) * BUT WERE WE ASKED TO RETURN WITH FLAGS? +* BNE.S GTBKX1 * YES + +GTBKX2 LEA MSGREA,A0 * ERROR CODE IN D0 + BRA FATAL * 'Game file read error' + + SECTION ZDATA +MSGREA DC.B 'Story file read error',0 + SECTION ZCODE + + + PAGE +* -------------------------------------------------------------------------- +* SAVE FILE DISK I/O ROUTINES +* -------------------------------------------------------------------------- + +* PRELIMINARY DIALOG FOR SAVE/RESTORE +* PROMPT USER TO SWAP DISKS AND IDENTIFY DRIVE BEING USED +* RETURN LETTER IN D0, ZERO FOR DEFAULT + +DKSWAP MOVE.W D1,-(SP) + CLR.W D1 * DRIVE SELECTED, ASSUME DEFAULT + + LEA MSGDKS,A0 + BSR OUTMSG0 * PROMPT, DON'T ADD A CR + + SECTION ZDATA +MSGDKS DC.B 'Insert your SAVE disk in any drive,' + DC.B ' then enter the letter of the drive: ',0 + SECTION ZCODE + +DKSX1 BSR TTYIN * GET A CHAR + CMPI.B #13,D0 * USE THE DEFAULT? + BEQ.S DKSX3 * YES + + CMPI.B #$60,D0 * UPPERCASE? + BLT DKSX2 * YES + SUBI.B #$20,D0 * NO, MAKE IT UPPERCASE + +DKSX2 CMPI.B #'A',D0 * VALID DRIVE LETTER? + BLT DKSX1 * NO + CMPI.B #'Z',D0 + BGT DKSX1 * NO + + MOVE.W D0,D1 * YES, SAVE IT AND ECHO IT + BSR PUTCHR +DKSX3 BSR PUTNEW * FOLLOW WITH A CR + + MOVE.W D1,D0 * RETURN THE DRIVE LETTER + MOVE.W (SP)+,D1 + RTS + + +* DUPLICATE FILE NAME DIALOG (SAVE ONLY) +* CHECK FOR FILENAME CONFLICT, IF SO, PROMPT USER FOR INSTRUCTIONS +* RETURN NON-ZERO TO ABORT + +DUPNAM MOVEM.L D1-D7/A1-A5,-(SP) + + JSR _exist_file + TST.L D0 * DOES THE FILE ALREADY EXIST? + BEQ DUPX3 * NO, PROCEED NORMALLY + +* DUPLICATE NAME DETECTED, PROMPT USER FOR INSTRUCTIONS + + LEA MSGDUP,A0 + BSR OUTMSG0 * PROMPT, NO CR + BSR PUTLIN * *** RESET THE BUFFERING COUNTER *** + + SECTION ZDATA +MSGDUP DC.B 'You are about to write over an existing file. ' + DC.B 'Proceed? (Y/N) >',0 + +YNBUFF DC.B 0,0,0,0 * RESPONSE GOES HERE + SECTION ZCODE + + LEA YNBUFF,A0 + MOVEQ #3,D0 * THREE CHAR LIMIT + MOVEQ #1,D1 * REQUEST LOWER-CASE CONVERSIONS + BSR RDLINE * COLLECT A RESPONSE + + LEA YNBUFF,A0 + MOVE.W D0,D1 * COUNT OF ACTUAL CHARS + CLR.W D0 * ASSUME A POSITIVE RESPONSE + +DUPX1 SUBQ.W #1,D1 * ANY CHARS LEFT TO CHECK? + BLT.S DUPX2 * NO, RETURN A NEGATIVE RESPONSE + + CMPI.B #'y',(A0) * POSITIVE RESPONSE? + BEQ.S DUPX3 * YES (IGNORE ANY FOLLOWING CHARS) + + CMPI.B #' ',(A0)+ * OTHERWISE, LOOK AT NEXT CHAR? + BEQ.S DUPX1 * (ONLY IF THIS ONE WAS A BLANK) + +DUPX2 MOVEQ #1,D0 * ANYTHING ELSE MEANS NEGATIVE +DUPX3 TST.W D0 * RETURN FLAGS FOR RESULT + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + + +* GET A FILE NAME UNDER WHICH TO SAVE A GAME, LEAVE NAME IN GLOBAL +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +GETSFL MOVEM.L D1-D7/A1-A5,-(SP) +* BSR DKSWAP * PROMPT FOR ID OF SAVE DISK +* MOVE.W D0,-(SP) + + CLR.L -(SP) * *** ALWAYS USE DEFAULT SAVE DISK *** + MOVEQ #1,D0 + MOVE.L D0,-(SP) * SAVE, NOT RESTORE + JSR _file_select + ADDQ.W #8,SP * FLUSH STACK (4 ACTUAL) + + TST.W D0 * NON-ZERO IF CANCEL OR ERROR + BNE.S GTSFX1 + + BSR DUPNAM * CHECK IF GIVEN FILENAME ALREADY EXISTS + TST.W D0 * NON-ZERO IF DUPLICATE + +GTSFX1 MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + + +* CREATE (IF NECESSARY) AND OPEN A SAVE FILE, USING GLOBAL FILENAME +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +NEWSFL MOVEM.L D1-D7/A1-A5,-(SP) + JSR _create_file + TST.L D0 + BNE NEWSX1 * NON-ZERO MEANS ERROR + +* SUCCESS, SAVE THE REFERENCE NUMBER + + MOVE.L _temp_channel,SAVFIL(A6) + CLR.L D0 * RETURN ZERO FOR OK + BRA.S NEWSX2 + +* CMPI.W #-44,D0 * ERROR, DISK IS WRITE-PROTECTED? (SAY SO) +* CMPI.W #-48,D0 * ERROR, NAME EXISTS ALREADY? (IGNORE) + +NEWSX1 MOVE.L D0,-(SP) + BSR WPRCHK * IF WRITE-PROTECT ERROR, INFORM USER + MOVE.L (SP)+,D0 * RETURN WITH FLAGS + +NEWSX2 MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + + +* WRITE A SERIES OF SAVE FILE BLOCKS, +* FIRST BLOCK OFFSET IN D0, NUMBER OF BLOCKS IN D1, CORE LOCATION IN A0, +* FILE REF NUMBER IN SAVFIL(A6) +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +PTSBKS MOVEM.L D2-D7/A1-A5,-(SP) + + BSR BLKBYT * CONVERT BLOCKS TO BYTES + EXG D1,D0 + BSR BLKBYT + EXG D1,D0 + + MOVE.L A0,-(SP) * BUFFER POINTER + MOVE.L D1,-(SP) * LENGTH IN BYTES + MOVE.L D0,-(SP) * OFFSET IN BYTES + + MOVE.L SAVFIL(A6),-(SP) + JSR _write_file + ADDA.W #16,SP * FLUSH STACK + + MOVE.L D0,-(SP) * ERROR? + BEQ.S PTSBX2 * NO + + CMPI.W #999,D0 * DISK FULL ERROR? + BEQ.S PTSBX1 * YES + + BSR WPRCHK * IF WRITE-PROTECT ERROR, INFORM USER + BRA.S PTSBX2 + +PTSBX1 LEA MSGFUL,A0 + BSR OUTMSG * 'Not enough room on disk' + + SECTION ZDATA +MSGFUL DC.B 'Not enough room on disk',0 + SECTION ZCODE + +PTSBX2 MOVE.L (SP)+,D0 * RETURN FLAGS + MOVEM.L (SP)+,D2-D7/A1-A5 + RTS + + +* CHECK FOR DISK WRITE-PROTECT ERROR (DURING FILE CREATE AND/OR WRITE) + +WPRCHK +* CMPI.W #-13,D0 * ERROR BECAUSE DISK IS WRITE-PROTECTED? +* BNE.S WPRCX1 * NO + +* LEA MSGWPR,A0 * YES, INFORM USER +* BSR OUTMSG * 'Disk is write-protected' +WPRCX1 RTS + + SECTION ZDATA +MSGWPR DC.B 'Disk is write-protected',0 + SECTION ZCODE + + +* CLOSE A SAVE FILE, CHANNEL IN SAVFIL(A6) +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +CLSSFL MOVEM.L D1-D7/A1-A5,-(SP) + + MOVE.L SAVFIL(A6),-(SP) + JSR _close_file + ADDQ.W #4,SP * FLUSH STACK (2 ACTUAL) + + TST.L D0 * NON-ZERO IF ERROR + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + + +* DELETE A BAD SAVE FILE, MUST HAVE BEEN ALREADY CLOSED (OR NOT OPENED) +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +DELSFL MOVEM.L D1-D7/A1-A5,-(SP) + JSR _delete_file + TST.L D0 * NON-ZERO IF ERROR + + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* ---------------------------------------------------------------------------- +* *** RESTORE FILE ROUTINES *** +* ---------------------------------------------------------------------------- + +* GET A FILE NAME FROM WHICH TO RESTORE AN OLD SAVE FILE, LEAVE NAME IN GLOBAL +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +GETRFL MOVEM.L D1-D7/A1-A5,-(SP) +* BSR DKSWAP * PROMPT FOR LETTER OF SAVE DRIVE +* MOVE.W D0,-(SP) + CLR.L -(SP) * *** ALWAYS USE DEFAULT *** + + CLR.L -(SP) * RESTORE, NOT SAVE + JSR _file_select + ADDQ.W #8,SP * FLUSH STACK (4 ACTUAL) + + TST.W D0 * NON-ZERO IF CANCEL OR ERROR + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + + +* OPEN AN OLD SAVE FILE, USING GLOBAL FILENAME, LEAVE CHANNEL IN SAVFIL(A6) +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +OPNSFL MOVEM.L D1-D7/A1-A5,-(SP) + JSR _open_file + TST.L D0 + BNE OPNSX1 * NON-ZERO MEANS ERROR + + MOVE.L _temp_channel,SAVFIL(A6) + CLR.L D0 * OK, RETURN ZERO FLAGS + BRA.S OPNSX2 + +OPNSX1 LEA MSGOSF,A0 * FAILED, INFORM USER + BSR OUTMSG + + SECTION ZDATA +MSGOSF DC.B 'Couldn' + DC.B $27 + DC.B 't locate save file',0 + SECTION ZCODE + + MOVEQ #1,D0 * SET FLAGS FOR ERROR + +OPNSX2 MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + + +* GET A SERIES OF SAVE FILE BLOCKS +* FIRST BLOCK NUMBER IN D0, # OF BLOCKS IN D1, CORE TARGET LOCATION IN A0 +* RETURN WITH FLAGS SET, ZERO IF NO ERROR + +GTSBKS MOVEM.L D2-D7/A1-A5,-(SP) + + BSR BLKBYT * CONVERT BLOCKS TO BYTES + EXG D1,D0 + BSR BLKBYT + EXG D1,D0 + + MOVE.L A0,-(SP) * BUFFER POINTER + MOVE.L D1,-(SP) * LENGTH IN BYTES + MOVE.L D0,-(SP) * OFFSET IN BYTES + + MOVE.L SAVFIL(A6),-(SP) + JSR _read_file + ADDA.W #16,SP * FLUSH STACK + + TST.L D0 * ZERO MEANS NO ERROR + MOVEM.L (SP)+,D2-D7/A1-A5 + RTS + + +DEFOLD CLR.W D0 * RETRIEVE PREVIOUS DEFAULT NAMES + BRA.S DEFNX1 +DEFNEW MOVEQ #1,D0 * UPDATE PREVIOUS DEFAULT NAMES + +DEFNX1 MOVEM.L D1-D7/A1-A5,-(SP) + MOVE.L D0,-(SP) + JSR _new_default * COPY TWO FILE-RELATED STRINGS + ADDQ.W #4,SP * FLUSH STACK (2 ACTUAL) + MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* ASSOCIATE AN ICON WITH A NEWLY-CREATED SAVE FILE + +MAKEICON + MOVEM.L D1-D7/A1-A5,-(SP) + JSR _make_icon_file + TST.W D0 * IF NON-ZERO, SHOW ERROR MSG + BEQ.S MAKIX1 + + LEA MSGMKI,A0 * (NON-FATAL, SAVE IS STILL GOOD) + BSR OUTMSG + + SECTION ZDATA +MSGMKI DC.B '*** Couldn' + DC.B $27 + DC.B 't create icon file ***',0 + SECTION ZCODE + +MAKIX1 MOVEM.L (SP)+,D1-D7/A1-A5 + RTS + +* CHECK FOR GAME DISK IN DEFAULT DRIVE BEFORE/AFTER SAVE/RESTORE +* CLOSE GAME FILE BEFORE, RE-OPEN IT AFTER + +CHKDSK RTS *** NOT NEEDED UNDER AMIGADOS *** + + MOVEM.L D1/A1,-(SP) + MOVE.W D0,D1 * ZERO MEANS BEFORE + +CHKDX1 TST.W D1 * STARTING THE SAVE/RESTORE? + BNE.S CHKDX2 * NO, ENDING + + BSR CLSGAM + BEQ.S CHKDX4 * OK, FILE CLOSED, PROCEED + BRA.S CHKDX3 * ERROR + +CHKDX2 BSR OPNGAM + BEQ.S CHKDX4 * OK IF IT OPENS, CARRY ON + +CHKDX3 LEA MSGNOD,A0 * FAILED, ASK FOR GAME DISK + BSR OUTMSG0 * PROMPT (DON'T ADD A CR) + + SECTION ZDATA +MSGNOD DC.B 'Insert the story disk and strike any key to continue ',0 + SECTION ZCODE + + BSR TTYIN * WAIT FOR A KEY + BSR PUTNEW * GO TO NEXT LINE + BRA.S CHKDX1 * TRY AGAIN + +CHKDX4 MOVEM.L (SP)+,D1/A1 + RTS + + +* MAXIMUM FILE NAME LENGTH (ACTUALLY ~30, MUST ALLOW FOR ".Info" ICON FILE) + +FNAMELEN EQU 25 + +* ALTERNATE FILE-SELECTION ROUTINE (AMIGA -- IGNORES THE STACK PARAMETERS) + +_file_select + MOVEM.L D1-D7/A1-A5,-(SP) + + LEA MSGIN1,A0 * PROMPT FOR A FILENAME + BSR OUTMSG + + LEA MSGIN2,A0 + BSR OUTMSG0 + + LEA _saveback,A0 * ALREADY ASCIZ + BSR OUTMSG0 + + LEA MSGIN3,A0 + BSR OUTMSG0 * problem: buffer is not flushed here ... + BSR PUTLIN + + SECTION ZDATA +MSGIN1 DC.B 'Insert your save disk then enter a file name.',0 +MSGIN2 DC.B '(Default is "',0 +MSGIN3 DC.B '") >',0 + SECTION ZCODE + + LEA _savename,A0 + MOVEQ #FNAMELEN,D0 * MAX LENGTH OF NAME (BUFFER LENGTH 64) + CLR.W D1 * NO LOWER-CASE CONVERSIONS THIS TIME + BSR RDLINE * COLLECT A RESPONSE + + TST.W D0 * LENGTH OF INPUT + BEQ.S FSELX1 * ZERO, MEANS USE DEFAULT + + LEA _savename,A0 + CLR.B 0(A0,D0.W) * MAKE THE STRING ASCIZ + BRA.S FSELX2 + +FSELX1 CLR.L -(SP) * COPY _saveback TO _savename + JSR _new_default + ADDQ.W #4,SP + +FSELX2 JSR _drive_default * PREFIX WITH DEFAULT DRIVE (IF NONE GIVEN) + + MOVEM.L (SP)+,D1-D7/A1-A5 + CLR.W D0 * (ALWAYS) RETURN ZERO FOR OKAY + RTS + + + PAGE +* ---------------------------------------------------------------------------- +* 68000 CALLS FROM C (XDEFS ARE REQUIRED) +* ---------------------------------------------------------------------------- + + SECTION ZDATA +RTADDR DC.L 0 + SECTION ZCODE + +_trap1 LEA RTADDR,A0 + MOVE.L (SP)+,(A0) * SAVE RETURN ADDR + TRAP #1 * MAKE A GEMDOS CALL (ARGS ON STACK) + MOVE.L RTADDR,-(SP) + RTS + +_trap2 LEA RTADDR,A0 + MOVE.L (SP)+,(A0) * SAVE RETURN ADDR + TRAP #2 + MOVE.L RTADDR,-(SP) + RTS + +_trap13 LEA RTADDR,A0 + MOVE.L (SP)+,(A0) * SAVE RETURN ADDR + TRAP #13 + MOVE.L RTADDR,-(SP) + RTS + +_trap14 LEA RTADDR,A0 + MOVE.L (SP)+,(A0) * SAVE RETURN ADDR + TRAP #14 + MOVE.L RTADDR,-(SP) + RTS + + + SECTION ZDATA +ZVARS DC.L 0 * ZIP VALUE FOR A6 IS STORED HERE + SECTION ZCODE + +* OPUSL1 NOP + +* IFEQ CZIP +* MOVEM.L D3-D7/A2-A6,-(SP) * PRESERVE PASCAL'S REGISTERS +* MOVE.L ZVARS,A6 * SET UP ZIP'S FRAME POINTER +* BSR OPUSL +* MOVEM.L (SP)+,D3-D7/A2-A6 +* ENDC +* RTS + + +* PROCEDURE OUTBUFLEN (charCount: INTEGER) -- adjust folding + +* THIS WILL RESET ENDBUF (WHEN NEXT EMPTIED, TO PREVENT BUGS) + +* OUTBUFLEN +* MOVE.L ZVARS,A0 * SET UP ZIP'S FRAME POINTER +* MOVE.W 4(SP),CURSIZ +* MOVE.L D0,MACBUF(A0) +* RTS diff --git a/apple/apple-g.zip b/apple/apple-g.zip new file mode 100644 index 0000000..177ac32 Binary files /dev/null and b/apple/apple-g.zip differ diff --git a/apple/apple-h.zip b/apple/apple-h.zip new file mode 100644 index 0000000..5b9859a Binary files /dev/null and b/apple/apple-h.zip differ diff --git a/apple/applezip.sed b/apple/applezip.sed new file mode 100644 index 0000000..67270ee --- /dev/null +++ b/apple/applezip.sed @@ -0,0 +1,41 @@ +/^*/ { + s/\*\(.*\)/;\1/p + } + +/^[^ *;]/ { + s/\([^ ]*\)[ ]*\([^ ]*\)[ ]*\([^ ]*\)[ ]*\(.*\)/\1: \2 \3 \4/p + } + +/^ / { + s/[ ]*\([^ ]*\)[ ]*\([^ ]*\)[ ]*\(.*\)/ \1 \2 \3/p + } + +/=/ { + s/^\([^ :]*\)[ :]*=\(.*\)/\1 EQU\2/p + } + +// { + s/>\([ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*\)/LOW \1/p + } + +/PAG/ { + s/PAG[^E]/PAGE/p + } + +/ASC/ { + s/ASC[ ]*/DB /p + } + +/DFB/ { + s/DFB[ ]*/DB /p + } + +/\*[+-]/ { + s/\*+/$+/p + s/\*-/$-/p + } + diff --git a/apple/ezip/bugger.asm b/apple/ezip/bugger.asm new file mode 100644 index 0000000..df6a8a5 --- /dev/null +++ b/apple/ezip/bugger.asm @@ -0,0 +1,219 @@ + PAGE + SBTTL "--- DEBUGGER: APPLE ---" + + ; -------------- + ; APPLE DEBUGGER + ; -------------- + + ; ENTRY: BREAKPOINT ID IN [A] + +BLINE: DB "B: OP: PC: S: V: 1: 2: 3: 4: 5: 6: 7: 8: 9: " + DB EOL +BLINL EQU $-BLINE + +BUGLIN EQU LSTLNE + +DOBUG: LDX KBD ; WAS CTRL-S PRESSED? + CPX #$13 + BNE DO1 + RTS ; YES, SO LEAVE + +DO1: CMP #0 + BEQ BUGIT + RTS + + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + +BUGIT: LDX #2 ; INIT "CURSOR" + 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 BLINE,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 [ZSP] + LDA ZSP + JSR HEX + + LDX #29 ; CURSOR FOR [MPC] + LDA MPCH + JSR HEX + LDA MPCM + JSR HEX + LDA MPCL + JSR HEX + + LDX #38 + LDA BONE + JSR HEX + + LDX #43 + LDA BTWO + JSR HEX + + LDX #48 + LDA BTHREE + JSR HEX + + LDX #53 + LDA BFOUR + JSR HEX + + LDX #58 + LDA BFIVE + JSR HEX + + LDX #63 + LDA BSIX + JSR HEX + + LDX #68 + LDA BSEVEN + JSR HEX + + LDX #73 + LDA BEIGHT + JSR HEX + + LDX #78 + LDA BNINE + JSR HEX + +; TO SEND TO PRINTER IF WANTED +; LDA CSW+LO +; PHA +; LDA CSW+HI +; PHA +; LDA EH +; PHA +; LDA ALTCSW+LO +; STA CSW+LO +; LDA ALTCSW+HI +; STA CSW+HI +; +; LDA PSTAT +; BNE PPP +; +; LDA #$C1 +; STA CSW+HI +; LDA #$00 +; STA CSW+LO +; +; LDA #$89 +; JSR MCOUT +; LDA CSW+HI +; STA ALTCSW+HI +; LDA CSW+LO +; STA ALTCSW+LO +; LDA #$B8 +; JSR MCOUT +; LDA #$B0 +; JSR MCOUT +; LDA #$CE +; JSR MCOUT +; LDA #$8D +; JSR MCOUT + +PPP: LDX #2 +DBG1: LDA BLINE,X ; PRINT DEBUGGER TEXT +; JSR MCOUT + JSR CHAR + INX + CPX #BLINL + BCC DBG1 + +; PLA +; STA EH +; PLA +; STA CSW+HI +; PLA +; STA CSW+LO + +; BIT KBD +; BPL LETEX ; NO KEY PRESSED + + BIT ANYKEY ; CLEAR IT +BUGWAT: BIT KBD ; WAIT FOR A KEY + BPL BUGWAT + + LDA KBD + CMP #$8D + BNE LETEX + BRK + +LETEX: BIT ANYKEY ; CLEAR FOR NEXT ONE + 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 + ORA #%10000000 + STA BLINE,X + INX + RTS + +HCHARS: DB "0123456789ABCDEF" + +BONE: DB 0 +BTWO: DB 0 +BTHREE: DB 0 +BFOUR: DB 0 +BFIVE: DB 0 +BSIX: DB 0 +BSEVEN: DB 0 +BEIGHT: DB 0 +BNINE: DB 0 + + END + diff --git a/apple/ezip/cold.asm b/apple/ezip/cold.asm new file mode 100644 index 0000000..977d55b --- /dev/null +++ b/apple/ezip/cold.asm @@ -0,0 +1,55 @@ + PAGE + SBTTL "--- MACHINE COLDSTART: APPLE II ---" + + ; --------- + ; COLDSTART + ; --------- + + +SIG: DB 0 ; IIc FLAG +STRYSL: DB 0 ; BOOT SLOT +STRYDR: DB 0 ; BOOT DRIVE + + ; FINISH LOADING THE ZIP + +COLD: LDA BSLOT ; SET UP + STA DCBSLT ; CURRENT AND + STA DCBPSL ; PREVIOUS SLOT IDS + + LDA #>COUT1 ; SET SCREEN OUTPUT + STA CSW+HI ; IN CASE OF PR#6 + LDA #ZRTRUE ;0 + DB >ZRFALS ;1 + DB >ZPRI ;2 + DB >ZPRR ;3 + DB >ZNOOP ;4 + DB >ZSAVE ;5 + DB >ZREST ;6 + DB >ZSTART ;7 + DB >ZRSTAK ;8 + DB >POPVAL ;9 + DB >ZQUIT ;10 + DB >ZCRLF ;11 + DB >ZUSL ;12 + DB >ZVER ;13 + DB >BADOP0 ;14 + DB >BADOP0 ;15 + +OPT0L: DB ZZERO ;0 + DB >ZNEXT ;1 + DB >ZFIRST ;2 + DB >ZLOC ;3 + DB >ZPTSIZ ;4 + DB >ZINC ;5 + DB >ZDEC ;6 + DB >ZPRB ;7 + DB >ZCALL1 ;8 (EZIP) + DB >ZREMOV ;9 + DB >ZPRD ;10 + DB >ZRET ;11 + DB >ZJUMP ;12 + DB >ZPRINT ;13 + DB >ZVALUE ;14 + DB >ZBCOM ;15 + +OPT1L: DB BADOP2 ;0 (UNDEFINED) + DB >ZEQUAL ;1 + DB >ZLESS ;2 + DB >ZGRTR ;3 + DB >ZDLESS ;4 + DB >ZIGRTR ;5 + DB >ZIN ;6 + DB >ZBTST ;7 + DB >ZBOR ;8 + DB >ZBAND ;9 + DB >ZFSETP ;10 + DB >ZFSET ;11 + DB >ZFCLR ;12 + DB >ZSET ;13 + DB >ZMOVE ;14 + DB >ZGET ;15 + DB >ZGETB ;16 + DB >ZGETP ;17 + DB >ZGETPT ;18 + DB >ZNEXTP ;19 + DB >ZADD ;20 + DB >ZSUB ;21 + DB >ZMUL ;22 + DB >ZDIV ;23 + DB >ZMOD ;24 + DB >ZCALL2 ;25 (EZIP) + DB >BADOP2 ;26 + DB >BADOP2 ;27 + DB >BADOP2 ;28 + DB >BADOP2 ;29 + DB >BADOP2 ;30 + DB >BADOP2 ;31 + +OPT2L: DB ZCALL ;0 + DB >ZPUT ;1 + DB >ZPUTB ;2 + DB >ZPUTP ;3 + DB >ZREAD ;4 + DB >ZPRC ;5 + DB >ZPRN ;6 + DB >ZRAND ;7 + DB >ZPUSH ;8 + DB >ZPOP ;9 + DB >ZSPLIT ;10 + DB >ZSCRN ;11 + + ; (EZIPS FROM HERE ON) + DB >ZXCALL ;12 + DB >ZCLR ;13 + DB >ZERASE ;14 + DB >ZCURST ;15 + DB >ZCURGT ;16 (NOT IMPLEMENTED) + DB >ZLIGHT ;17 + DB >ZBUFOUT ;18 + DB >ZDIRT ;19 + DB >ZDIRIN ;20 (NOT IMPLEMENTED) + DB >ZSOUND ;21 + DB >ZINPUT ;22 + DB >ZINTBL ;23 + DB >BADOPX ;24 + DB >BADOPX ;25 + DB >BADOPX ;26 + DB >BADOPX ;27 + DB >BADOPX ;28 + DB >BADOPX ;29 + DB >BADOPX ;30 + DB >BADOPX ;31 + +OPTXL: DB ERRM + LDY #ERRML + JSR DLINE ; PRINT ERROR MESSAGE + JMP ZQUIT1 + + +; ---- +; QUIT +; ---- + +ZQUIT: JSR ZCRLF ; FLUSH BUFFER +ZQUIT1: LDX #ENDM + LDY #ENDML + JSR DLINE ; "END OF STORY" +FREEZE: JMP FREEZE ; AND STOP + +ENDM: DB "End of session." + DB EOL +ENDML EQU $-ENDM + + +; ------- +; RESTART +; ------- + +ZSTART: LDX #0 + STX WTOP ; RESET FULL SCREEN FOR CLEAR + LDA SCRIPTF ; PRINTING? + BEQ REX ; NO + DEX ; = $FF + STX PSTAT ; MAKE TO CONTINUE PRINTING AFTER RESTART +REX: JSR SIDE1 ; NEED SIDE 1 AGAIN + JMP WARM ; AND DO WARMSTART + + +; -------------------------- +; RETURN TOP RAM PAGE IN [A] +; -------------------------- + +MEMTOP: LDA #$FB ; FOR NOW, ASSUME LAST "BUFFER" + RTS ; OF AUX MEMORY + + +; -------------------------------- +; RETURN RANDOM BYTES IN [A] & [X] +; -------------------------------- + +RANDOM: INC RNUM1 + DEC RNUM2 + LDA RNUM1 ; GENERATED BY MONITOR GETBYT + ADC RAND1 + TAX + LDA RNUM2 + SBC RAND2 + STA RAND1 + STX RAND2 + RTS + + +; ------------------- +; Z-PRINT A CHARACTER +; ------------------- +; ENTRY: ASCII CHAR IN [A] +; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, +; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN +; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME +; (DIROUT CHANGES 6/24/85) + +COUT: STA IOCHAR ; HOLD IT A SEC + LDX TABLEF ; OUTPUT TO TABLE? + BEQ COUT4 ; NO + JMP TBLRTN ; YES, DO IT (TBL ONLY) +COUT4: LDX SCREENF ; OUTPUT TO SCREEN? + BNE COUT5 ; YES + LDX SCRIPTF ; OUTPUT TO PRINTER? + BNE COUT5 ; YES + RTS ; NO, SO DONE +COUT5: LDA IOCHAR ; RETRIEVE CHAR + LDX BUFFLG ; UNBUFFERED OUTPUT? + BNE UNBUFR ; YES, PLACE ON SCREEN IMMED. + CMP #$0D ; IF ASCII EOL, + BNE COUT0 + JMP ZCRLF ; DO IT +COUT0: CMP #SPACE ; IGNORE ALL OTHER + BCC CEX ; CONTROLS + LDX INVFLG ; CHECK IF NORMAL + BPL COUT3 ; OR INVERSE + ORA #%10000000 ; SET HIGH BIT FOR NORMAL +COUT3: LDX CHRCNT ; GET LINE POINTER + STA LBUFF,X ; ADD CHAR TO BUFFER + LDY LENGTH ; GET LINE LENGTH COUNTER + CPY XSIZE ; END OF SCREEN LINE? + BCC COUT2 + JMP FLUSH ; YES, FLUSH THE LINE +COUT2: INC LENGTH ; ELSE UPDATE + INC CHRCNT +CEX: RTS + + +; -------------------------- +; DIRECT, UNBUFFERED DISPLAY +; -------------------------- + +UNBUFR: STA IOCHAR ; HOLD IN CASE NEED TO PRINT + CMP #SPACE ; IGNORE CONTROLS + BCC UNBEX + LDA EHZ ; CHECK IF BEYOND SCREEN + CMP #80 + BCS UNBEX ; YES, LEAVE + LDA CHZ ; CHECK FOR IIE ALSO + CMP #80 + BCS UNBEX + + LDA SPLITF ; CHECK WHICH WINDOW + BEQ UNBBOT ; BOTTOM WINDOW + LDA CV ; CHECK IF WITHIN WINDOW + CMP WTOP + BCS UNBEX ; NO, JUST LEAVE + BCC UNBDIS ; YES, GO DISPLAY + +UNBBOT: LDA CV + CMP WTOP + BCC UNBEX ; NOT WITHIN WINDOW, LEAVE + +UNBDIS: LDA SCREENF ; DISPLAY TO SCREEN? + BEQ UNBPRN ; NO, CHECK IF PRINTING + LDA IOCHAR + ORA #%10000000 ; SET BIT 7 FOR NORMAL DISPLAY IF WANTED + JSR MCOUT +UNBPRN: LDA SPLITF ; SPLIT (NON-TEXT) SCREEN + BNE UNBEX ; DON'T PRINT + +;SEND CHAR TO PRINTER + + LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? + BEQ UNBEX ; NO + LDA SCRIPTF ; SCRIPTING ON ? + BEQ UNBEX ; NO + LDA CSW+LO ; SAVE NORMAL OUTPUT HOOK + PHA + LDA CSW+HI + PHA + LDA EHZ ; + CURRENT CURSOR POSITION + PHA + LDA CHZ ; AND FOR IIE ALSO + PHA + LDA ALTCSW+LO + STA CSW+LO + LDA ALTCSW+HI + STA CSW+HI + LDA IOCHAR ; GET CHAR + JSR MCOUT ; PRINT IT @ CURRENT EH + PLA ; RESET TO NORMAL + STA CHZ + PLA + STA EHZ ; IIe USES CH ALSO + PLA + STA CSW+HI + PLA + STA CSW+LO +UNBEX: RTS + + +; --------------- +; OUTPUT TO TABLE +; --------------- + +TBLRTN: TAX ; HOLD CHAR A SEC. + + ;PUT BYTE IN TABLE AT CURRENT OFFSET + + LDA DIRITM+LO ; ADD IN OFFSET + CLC + ADC DIRTBL+LO + STA I+LO + LDA DIRITM+HI + ADC DIRTBL+HI + STA I+HI + LDY #0 + TXA ; PICK UP DB II CHAR + STA (I),Y ; STORE IT IN TBL @ BYTE ALIGNED @ + +;SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER + + INC DIRITM+LO ; INC OFFSET TO NEXT BYTE + BNE TBLRTS + INC DIRITM+HI +TBLRTS: RTS + + +; ------------------- +; FLUSH OUTPUT BUFFER +; ------------------- +; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: LDA #$A0 ; SPACE + STX OLDEND ; SAVE CURRENT END OF LINE +FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR + BEQ FL1 ; IN THE LINE + DEX + BNE FL0 ; IF NONE FOUND, + LDX XSIZE ; FLUSH ENTIRE LINE +FL1: STX OLDLEN ; SAVE OLD LINE POS HERE + STX CHRCNT ; MAKE IT THE NEW LINE LENGTH + JSR ZCRLF ; PRINT LINE UP TO LAST SPACE + +; START NEW LINE WITH REMAINDER OF OLD + + LDX OLDLEN ; GET OLD LINE POS + LDY #0 ; START NEW LINE AT BEGINNING +FL2: INX + CPX OLDEND ; CONTINUE IF + BCC FL3 ; INSIDE OR + BEQ FL3 ; AT END OF LINE + STY LENGTH ; ELSE SET NEW LINE LENGTH + STY CHRCNT + RTS +FL3: LDA LBUFF,X ; GET CHAR FROM OLD LINE + STA LBUFF,Y ; MOVE TO START OF NEW LINE + INY ; UPDATE LENGTH OF NEW LINE + BNE FL2 ; (ALWAYS) + + +; --------------- +; CARRIAGE RETURN +; --------------- + +ZCRLF: + LDX CHRCNT + LDA #$8D ; INSTALL EOL AT + STA LBUFF,X ; END OF CURRENT LINE + INC CHRCNT ; UPDATE LINE LENGTH + LDA SCREENF ; CHECK IF DISPLAYING TO SCREEN + BEQ ZCRLFX ; NO, GO HANDLE IF PRINTING + LDA SPLITF ; AT SPLIT SCREEN + BNE ZCRLF0 ; YES + INC LINCNT ; NEW LINE GOING OUT +ZCRLF0: LDX LINCNT ; IS IT TIME TO + INX ; (A LINE FOR "MORE") + CPX WBOTM ; PRINT "MORE" YET? + BCC ZCRLFX ; NO, CONTINUE + LDA WTOP + STA LINCNT ; RESET LINE COUNTER + INC LINCNT ; LEAVE 1 LINE ON SCREEN + BIT ANYKEY ; CLEAN STROBE SO GET CLEAN READING + LDA #>MORE + LDX #ZIRET ; SET ZRETURN TO RETURN HERE + STA PATCHI+HI + LDA #PUTVAL ; REPAIR ZRETURN + STA PATCHI+HI + LDA #SLOTM + LDY #SLOTML + JSR DLINE + LDA #0 ;ACTUALLY SLOT 1 + JSR DODEF ;DISPLAY IT AS DEFAULT + JSR GETKEY + CMP #EOL + BEQ PC1 ;USE DEFAULT + SEC + SBC #'0' + CMP #8 ;1-7 + BCS PCHK ;OOPS + BCC PC2 ;SKIP AROUND DEFAULT +PC1: LDA #1 ;WHICH IS 1 +PC2: CLC + ADC #$C0 + STA ALTCSW+HI + JSR PISSER ;SEND HIGH CRLOW TO SCREEN FOR NEATNESS + INC PSTAT ;SET TO ON + LDA CSW+LO ;SAVE NORMAL OUTPUT HOOK + PHA + LDA CSW+HI + PHA + LDA ALTCSW+LO ;LOAD SCRIPTING HOOK + STA CSW+LO + LDA ALTCSW+HI + STA CSW+HI + LDA #$89 ; OUTPUT PRINTER SETUP SEQUENCE + JSR MCOUT ; START WITH COMMAND CHAR HIGH CTRL-ILOW + LDA #$B8 ; 8 (80 COL WIDE) + JSR MCOUT + LDA #$B0 ; 0 + JSR MCOUT + LDA #$CE ; N (LF AFTER CR) + JSR MCOUT + LDA CSW+LO ; SAVE REAL PRINTER OUTPUT + STA ALTCSW+LO ; LOC. FOR NEXT TIME + LDA CSW+HI + STA ALTCSW+HI + PLA ; RESET NORMAL OUTPUT + STA CSW+HI + PLA + STA CSW+LO + +; PRINTER SETUP ON THE IIc COPIES THE ROM INTERRUPT VECTOR +; FROM $FFFE IN ROM TO BOTH MAIN & AUX. RAM PAGES @ $FFFE +; THAT PAGE IN MAIN RAM CONTAINS THE MONITOR STUFF SO IS OK +; BUT THAT PAGE IN AUX. RAM IS BEING USED TO CONTAIN A PAGE +; OF GAME CODE. THE FOLLOWING RTN CAUSES THE NEXT USE OF THAT +; PAGE TO READ IT IN NEW FROM THE DISK SO THAT THE VALUES +; WILL ALL BE CORRECT. (6/14/85 Le) +; +; THAT PAGE IS SECTOR $4F IN RAMDSK +; AND IT IS NOT USED +; ASK 85 + + RTS + + +; ------------ +; SPLIT SCREEN +; ------------ +; SPLIT SCREEN AT LINE [ARG1] +; DISABLE SPLIT IF [ARG1] = 0 +; IGNORE IF SPLIT ALREADY ENABLED OR [ARG1] LOW = 20 + +ZSPLIT: LDA ZBEGIN+ZMODE + AND #%00100000 ;CHECK IF ENABLED (EZIP) + BEQ ZSPOUT ;NOT, LEAVE + + LDA ARG1+LO ;GET # OF LINES FOR SCREEN + BEQ NORL ;IF 0 THEN RESTORE SCREEN + CMP #24 ;IS SPLIT REALLY = WHOLE SCREEN + BCS ZSPOUT ;YES, IGNORE + LDX SPSTAT ;CHECK IF ALREADY ENABLED + BEQ ZSPL1 ; NO + LDA WTOP ; BOTTOM OF SCREEN 1 + SEC + SBC ARG1+LO ; COMPARE NEW SIZE, IF EXISTING SIZE + BCS ZSPL2 ; LOW = DON'T CLEAR, SCREEN SHRINKING +ZSPL1: LDA ARG1+LO ; CLEAR LINES OF NEW, OR BEING ADDED + STA SPSTAT ;NON ZERO = SCREEN IS SPLIT +ZSPL2: LDA #$18 ;RESTORE BOTTOM FOR SCROLL + STA WBOTM + LDA ARG1+LO ; GET BOTTOM OF SPLIT SCREEN (AGAIN) + STA WTOP ;MAKE THAT THE TOP OF THE SECOND SCREEN + CMP LINCNT ; IS SCROLLING SCREEN NOW LESS THAN LINCNT? + BCC ZSPL3 ; NO + STA LINCNT ; YES +ZSPL3: LDA #0 + STA CHZ + STA EHZ + LDA #$17 + STA CV ;RESTORE CURSOR AFTER HOME CALL + JSR BASCAL ;HIGH CRLOW TO MAKE CV WORK +ZSPOUT: RTS + +NORL: ;RESTORE SCREEN TO FULL SCREEN MODE + + LDA #0 ;PUT CURSOR AT TOP OF SCREEN + STA WTOP ;RESTORE FULL SCREEN ALIGNMENT + STA LINCNT + STA SPSTAT ;FLAG NOT SPLIT + RTS + + +; ------ +; SCREEN +; ------ +; GO TO TOP WINDOW (TOP OF SCREEN) IF [A] = 1 +; GO TO BOTTOM OF SCREEN IF [A] = 0 +; IGNORE IF SPLIT NOT ENABLED OR [A] HIGH LOW 0 OR 1 +; FLAG SPLITF WILL BE SET FOR OUTPUT TO DETERMINE +; IF AND WHICH WINDOW TO DISPLAY TO +; (0=BOTTOM 1=TOP) + +ZSCRN: LDA ZBEGIN+ZMODE + AND #%00000001 ;CHECK IF ENABLED (EZIP) + BEQ ZSPOUT ;NOT, LEAVE + LDA SPSTAT ;CHECK IF SCREEN IS SPLIT + BEQ ZSPOUT ;NO, SO JUST LEAVE + LDA ARG1+LO ;CHECK WHICH WINDOW + BNE SCRN1 ;TOP SCREEN + LDA #$FF ; SCROLLING SCREEN SO + STA SCRIPT ; ALLOW SCRIPTING + LDA #0 + STA SPLITF ;SET FLAG TO SPLIT SCREEN (0) + + LDA LENGTH ; get saved cursor horizontal + STA EHZ ; and use it + STA CHZ ; and use it + + LDA #$17 ; assume last line (?) + STA CV + + JMP SCRNP ;JMP TO HIGH CRLOW RTN +SCRN1: CMP #01 + BNE ZSPOUT ;INVALID SCREEN ID + STA SPLITF ;SET FLAG TO UNSCROLLING SCREEN (1) + LDA #0 + STA SCRIPT ; SET SCRIPTNG OFF, NOT ALLOWED THIS SCREEN + STA CHZ + STA EHZ + STA CV ;ALIGN AT TOP OF SCREEN +SCRNP: JMP BASCAL ;SET CURSOR (+ LEAVE) + + +; ------------ +; CLEAR SCREEN +; ------------ + +CLS EQU HOME ;CLEAR & HOME CURSOR + +PISSER: LDA #$8D + JMP MCOUT + + +; ----- +; SOUND +; ----- +; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID +; (EZIP) + +ZSOUND: LDA ZBEGIN+ZMODE + AND #%00100000 + BEQ ZSOEX ; NOT ENABLED + LDX ARG1+LO ; GET SOUND WANTED + DEX + BEQ BEEP + DEX + BNE ZSOEX ; INVALID + LDY #$FF ; DURATION ($C0 = .1 SEC) +BOOP: LDA #$10 ; TONE ($0C = 1 KHZ) + JSR MWAIT + LDA SPKR ; TOGGLE SPEAKER + DEY + BNE BOOP +ZSOEX: RTS + +BEEP: JMP BELL ; QUICK BEEP ( 1KHZ @ .1 SEC) + + + ; ------------------------ + ; CHECK IF 128 K OF MEMORY + ; ------------------------ + + ; EXIT: CARRY SET IF NOT 128K, CLEAR IF THERE IS + +MEMCHK: LDA #0 ; START @ 0 + STA TSTVAL +MLOOP1: LDY #0 +MLOOP2: STA $1000,Y ; WRITE [TSTVAL] TO + INY ; MAIN MEMORY + BNE MLOOP2 + INC TSTVAL + LDA TSTVAL + STA WRTBNK+AUX ; SET TO AUX MEMORY + +MLOOP3: STA $1000,Y ; WRITE NEXT VALUE + INY ; TO AUX MEMOYR + BNE MLOOP3 + STA WRTBNK+MAIN ; SET TO MAIN MEMORY + DEC TSTVAL ; RESET TO [TSTVAL] WRITTEN TO MAIN + +MLOOP4: LDA $1000,Y ; CHECK IF WHAT WRITTEN + CMP TSTVAL ; 1ST TO MAIN MEM PG $10 + BNE NO128 ; IS STILL THERE + INY + BNE MLOOP4 + INC TSTVAL + STA RDBNK+AUX ; & SET TO AUX MEMORY + +MLOOP5: LDA $1000,Y ; & SEE IF WHAT WROTE + CMP TSTVAL ; TO AUX MEM IS STILL THERE + BNE NO128 + INY + BNE MLOOP5 + STA RDBNK+MAIN ; RESET TO MAIN MEM + LDA TSTVAL ; LAST THING WAS INC'D + BNE MLOOP1 ; GO TRY W/ NEXT SET OF VALUES, DO 0,1 -LOW FF,O + CLC + RTS ; SIGNAL OK +NO128: STA RDBNK+MAIN ; RESET TO MAIN MEM + SEC + RTS ; OOPS, ONLY 64K + + END + diff --git a/apple/ezip/main.asm b/apple/ezip/main.asm new file mode 100644 index 0000000..665158b --- /dev/null +++ b/apple/ezip/main.asm @@ -0,0 +1,318 @@ + PAGE + SBTTL "--- MAIN LOOP ---" + +MLOOP: LDA #0 + STA NARGS ; RESET # ARGUMENTS + + ; FASTPC - GET NEXT INSTRUCTION + + LDY ZPCBNK ; THIS IS ANDREW'S CODE - AARRRGGGG! + STA RDBNK,Y + LDY ZPCL + LDA (ZPCPNT),Y + STA RDBNK+MAIN + INC ZPCL + BNE GOTIT1 + JSR CRSZPC +GOTIT1: TAY + + STA OPCODE ; SAVE IT HERE + + + IF DEBUG + LDA VALUE+HI + STA BONE + LDA VALUE+LO + STA BTWO + LDA #0 ; BREAKPOINT #0 + JSR DOBUG + LDA OPCODE + TAY + ENDIF + + + ; DECODE AN OPCODE + + 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: CMP #236 ; XCALL? + BEQ OPXCLL ; YES, PROCESS SEPARATELY + 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: AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPTXL,Y + STA GOX+1+LO + LDA OPTXH,Y + STA GOX+1+HI +GOX: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #1 -- ILLEGAL X-OP *** + +BADOPX: LDA #1 + JMP ZERROR + + ; HANDLE AN XCALL OPCODE + +OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + STA ABYTE + JSR NEXTPC + STA BBYTE + LDA ABYTE ; ONE TO START WITH + LDX #0 + STX ADEX ; INIT ARGUMENT INDEX + BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP +XCALL1: LDA ABYTE ; GET ARG BYTE + ASL A ; SHIFT NEXT 2 BITS + ASL A ; INTO BITS 7 & 6 + STA ABYTE ; HOLD FOR LATER +XCALL2: AND #%11000000 ; MASK OUT GARBAGE + BNE XCALL3 + JSR GETLNG ; 00 = LONG IMMEDIATE + JMP XCNXT +XCALL3: CMP #%01000000 ; SHORT IMMED? + BNE XCALL4 ; NO, TRY ANOTHER + JSR GETSHT ; 01 = SHORT IMMED. + JMP XCNXT +XCALL4: CMP #%10000000 ; LAST TEST + BNE OPX4 ; 11 = NO MORE ARGS + JSR GETVAR ; 10 = VARIABLE +XCNXT: LDX ADEX + LDA VALUE+LO + STA ARG1+LO,X + LDA VALUE+HI + STA ARG1+HI,X + INC NARGS + INX + INX + STX ADEX + CPX #16 + BEQ OPX4 ; DONE, GO DO IT + CPX #8 ; DONE 1ST MODE BYTE? + BNE XCALL1 ; NOT QUITE YET + LDA BBYTE ; SET UP FOR NEXT + STA ABYTE ; MODE BYTE + JMP XCALL2 ; GO DO IT + + + +; ------------- +; HANDLE A 0-OP +; ------------- + +OP0: AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT0L,Y + STA GO0+1+LO + LDA OPT0H,Y + STA GO0+1+HI +GO0: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #2 -- ILLEGAL 0-OP *** + +BADOP0: LDA #2 + JMP ZERROR + + + +; ------------- +; HANDLE A 1-OP +; ------------- + +OP1: AND #%00110000 ; ISOLATE ARGUMENT BITS + BNE OP1A + + ;JSR GETLNG ; 00 = LONG IMMEDIATE + + ; FASTPC - GET HI OF ARG1 + + LDY ZPCBNK + STA RDBNK,Y + LDY ZPCL + LDA (ZPCPNT),Y + STA RDBNK+MAIN + INC ZPCL + BNE GOTIT2 + JSR CRSZPC +GOTIT2: TAY + + JMP OP1A1 +OP1A: AND #%00100000 ; TEST AGAIN + BNE OP1B + + ;JSR GETSHT ; 01 = SHORT IMMEDIATE + +OP1A1: STA ARG1+HI + + ; FASTPC - GET ARG1+LO + + LDY ZPCBNK + STA RDBNK,Y + LDY ZPCL + LDA (ZPCPNT),Y + STA RDBNK+MAIN + INC ZPCL + BNE GOTIT3 + JSR CRSZPC +GOTIT3: TAY + + STA ARG1+LO + INC NARGS + JMP OP1EX1 +OP1B: JSR GETVAR ; 10 = VARIABLE +OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] +OP1EX1: LDA OPCODE + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT1L,Y + STA GO1+1+LO + LDA OPT1H,Y + STA GO1+1+HI +GO1: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 + + STA ARG1+HI + + ; FASTPC - + + LDY ZPCBNK + STA RDBNK,Y + LDY ZPCL + LDA (ZPCPNT),Y + STA RDBNK+MAIN + INC ZPCL + BNE GOTIT4 + JSR CRSZPC +GOTIT4: TAY + + STA ARG1+LO + INC NARGS + JMP OP2B1 +OP2A: JSR GETVAR ; 1 = VARIABLE +OP2B: JSR V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] +OP2B1: LDA OPCODE ; RESTORE OPCODE BYTE + AND #%00100000 ; ISOLATE 2ND ARG BIT + BNE OP2C + + ;JSR GETSHT ; 0 = SHORT IMMEDIATE + + STA ARG2+HI + + ; FASTPC - + + LDY ZPCBNK + STA RDBNK,Y + LDY ZPCL + LDA (ZPCPNT),Y + STA RDBNK+MAIN + INC ZPCL + BNE GOTIT5 + JSR CRSZPC +GOTIT5: TAY + + STA ARG2+LO + JMP OP2D1 +OP2C: JSR GETVAR ; 1 = VARIABLE +OP2D: LDA VALUE+LO ; MOVE 2ND [VALUE] + STA ARG2+LO ; INTO [ARG2] + LDA VALUE+HI + STA ARG2+HI +OP2D1: INC NARGS ; UPDATE ARGUMENT COUNT + + ; EXECUTE A 2-OP OR EXTENDED 2-OP + +OP2EX: LDA OPCODE + AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT2L,Y + STA GO2+1+LO + LDA OPT2H,Y + STA GO2+1+HI +GO2: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 diff --git a/apple/ezip/objects.asm b/apple/ezip/objects.asm new file mode 100644 index 0000000..db68095 --- /dev/null +++ b/apple/ezip/objects.asm @@ -0,0 +1,198 @@ + PAGE + SBTTL "--- OBJECT & PROPERTY HANDLERS ---" + + +; ******************************************** +; AN ASSUMPTION HAS BEEN MADE WITH EZIP OBJECT +; HANDLING. THAT IS THAT ALL THIS STUFF IS +; BEFORE PURBOT AND IS IN MAIN MEMORY +; AND THEREFORE DIRECT ACCESSING IS JUST FINE +; LINDE +; ******************************************** +; ---------------------------------- +; GET ABSOLUTE ADDRESS OF OBJECT [A] +; ---------------------------------- +; ENTER: OBJECT IN A/X (LO/HI) +; EXIT: ADDRESS IN [I] +; (EZIP VERSION) + +OBJLOC: STX I+HI ; SAVE MSB FOR SHIFTING + ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) + STA I+LO + ROL I+HI + LDX I+HI + ASL A + ROL I+HI ; *4 + ASL A + ROL I+HI ; *8 + ASL A + ROL I+HI ; *16 + SEC + SBC I+LO ; -(*2) + STA I+LO ; SO IS *14 TOTAL + LDA I+HI + STX I+HI + SBC I+HI + STA I+HI + LDA I+LO + CLC + ADC #112 ; ADD OBJECT TABLE OFFSET + BCC OBJ3 + INC I+HI +OBJ3: 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC + LDY #12 ; (EZIP) + 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 #%00111111 ; MASK OUT LENGTH BITS (EZIP) + RTS + + +; ------------------------------- +; FETCH # BYTES IN PROPERTY VALUE +; ------------------------------- +; ENTRY: LIKE "PROPB" EXIT +; (EZIP) + +PROPL: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + RTS + +SHORT: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE + LDA #2 ; BIT 6 = 1, LENGTH =2 + RTS +ONE: LDA #1 ; BIT 6 = 0, LENGTH =1 + RTS + + +; ---------------------- +; POINT TO NEXT PROPERTY +; ---------------------- +; ENTRY: LIKE "PROPB" EXIT + +PROPNX: JSR PROPL ; GET LENGTH OF CURRENT PROP + TAX ; SAVE HERE +PPX: INY ; LOOP UNTIL + BNE PPY + INC I+LO + BNE PPY + INC I+HI +PPY: DEX ; [Y] POINTS TO + BNE PPX ; START OF NEXT PROP + INY ; CORRECT ALIGNMENT + RTS + + +; ----------------------------------------- +; CALL PROPNX, THEN ALIGN [I] AT THAT ENTRY +; ----------------------------------------- +; EXIT: [I] IS ALIGNED AT CURRENT PROPERTY +; [Y] IS ZEROED +; (EZIP) + +NEXTPI: JSR PROPNX ; GET ALIGNMENT OF NEXT PROPERTY INTO [Y] + TYA ; ADD OFFSET TO NEXT PROP + CLC ; TO [I] SO I POINTS DIRECTLY + ADC I+LO ; AT IT + STA I+LO + BCC NXTPI1 + INC I+HI ; ADD IN CARRY +NXTPI1: LDY #0 ; CLEAR [Y] AS IT IS USED AS AN INDEX + 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 ; (EZIP) + LDX ARG1+HI + 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 + CMP #$10 ; CHECK IF IN 2ND WORD + BCC FLS ; YES, GO ALIGN FOR THAT + SBC #16 ; ELSE ALIGN TO 3RD WORD + TAX + LDA I+LO + CLC + ADC #4 ; 3RD FLAG WORD + STA I+LO + BCC FLS0 + INC I+HI + JMP FLS0 ; (END EZIP CHGS) +FLS: 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 diff --git a/apple/ezip/ops012.asm b/apple/ezip/ops012.asm new file mode 100644 index 0000000..dfd3adf --- /dev/null +++ b/apple/ezip/ops012.asm @@ -0,0 +1,1150 @@ + 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: LDX #5 ;MOVE ZPC INTO MPC +ZPRI1: + LDA ZPC,X + STA MPC,X + DEX + BPL ZPRI1 ;NO NEED TO VALIDATE AS ZPC WAS VALID ANYWAY + JSR PZSTR ; PRINT THE Z-STRING AT [MPC] + LDX #5 ; COPY STATE OF [MPC] +ZPRI2: LDA MPC,X ; INTO [ZPC] + STA ZPC,X + DEX + BPL ZPRI2 + 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 ZCRLF ; DISPLAY VERSION NUMBER, GET SIDE 1 + LDX #3 + LDA #0 + STA IOCHAR ; COFFEE FLAG +ZVR: STA K+LO,X ; CLEAR [K], [L] + 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 ZBEGIN+ZLENTH ; GET MSB + STA I+HI ; AND + LDA ZBEGIN+ZLENTH+1 ; LSB OF Z-CODE LENGTH IN BYTES + ASL A ; MULTIPLY BY + ROL I+HI ; FOUR + ROL K+LO + ASL A + STA I+LO + ROL I+HI ; TO GET # BYTES + ROL K+LO ; IN GAME + LDA #0 ; START AT BEGINNING + STA DBLOCK+LO + STA DBLOCK+HI + JMP READIN ; READ FIRST BLOCK IN +VSUM: LDA MPCL ; NEW PAGE? + BNE VSUM2 ; NO, CONTINUE +READIN: LDA #>IOBUFF ; FAKE READ OUT SO + STA DBUFF+HI ; IT DOESN'T MOVE BUFFER + LDA #MAIN + STA DSKBNK ; SET FOR MAIN BANK + JSR GETDSK ; GO READ A PAGE + + LDA IOCHAR ; CHECK COFFEE FLAG + BNE VSUM2 ; ALL DONE + LDA SIDEFLG + CMP #2 ; IF ON SIDE 2 + BNE VSUM2 + LDA #>COFMSG ; FIRST SECTOR, TELL THEM + LDX # 2 BYTES + AND #%01000000 + BEQ PTZ1 ; BIT 6 = 0, LENGTH = 1 + LDA #2 ; BIT 6 = 1, LENGTH = 2 + BNE PTZ3 ; JMP +PTZ1: LDA #1 + BNE PTZ3 ; JMP +PTZ2: AND #%00111111 ; ELSE PICK UP SIZE > 2 +PTZ3: LDX #0 ; CLEAR FOR PUTBYT + JMP PUTBYT + + +; --- +; INC +; --- +; INCREMENT VARIABLE [ARG1] + +ZINC: LDA ARG1+LO + JSR VARGET ; FETCH VARIABLE INTO [VALUE] + INC VALUE+LO + BNE ZINC1 + INC VALUE+HI +ZINC1: JMP ZD0 + + +; --- +; DEC +; --- +; DECREMENT VARIABLE [ARG1] + +ZDEC: LDA ARG1+LO + JSR VARGET ; FETCH VAR INTO [VALUE] + LDA VALUE+LO + SEC + SBC #1 + STA VALUE+LO + LDA VALUE+HI + SBC #0 + STA VALUE+HI +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 +; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO +; 2) MOVES AND COMPARES 2 BYTES) + +ZREMOV: LDA ARG1+LO ; GET SOURCE OBJECT ADDR + LDX ARG1+HI + 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 #7 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET THE DATA + STA K ; HOLD IT + DEY + LDA (I),Y + TAX ; X = HI + LDA K ; A = LO + ORA (I),Y ; COMPARE BYTES + BEQ REMVEX ; SCRAM IF NO OBJECT + LDA K ; PICK UP, DESTROYED BY ORA + JSR OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [I] + LDY #10 ; POINT TO "FIRST" SLOT + LDA (I),Y ; GRAB DATA + TAX + INY + LDA (I),Y ; A=LO, X=HI + CMP ARG1+LO ; IS THIS THE FIRST? + BNE REMVC1 ; NO, KEEP SEARCHING + CPX ARG1+HI ; HM? + BNE REMVC1 + LDY #8 ; ELSE COPY SOURCE'S "NEXT" SLOT + LDA (J),Y + INY ; INTO DEST'S "FIRST" SLOT ([Y] = 10) + INY + STA (I),Y + DEY ; BACK UP TO GET HIGH BYTE + LDA (J),Y + INY + INY + STA (I),Y + BNE REMVC2 ; BRANCH ALWAYS +REMVC1: JSR OBJLOC + LDY #8 ; GET "NEXT" + LDA (I),Y + TAX + INY + LDA (I),Y + CMP ARG1+LO ; FOUND IT? + BNE REMVC1 ; NO, KEEP TRYING + CPX ARG1+HI + BNE REMVC1 + LDY #8 ; WHEN FOUND + LDA (J),Y ; MOVE "NEXT" SLOT OF SOURCE (THIS OBJECT) + STA (I),Y ; TO "NEXT" SLOT OF DEST + ;(OBJECT THAT REFERENCED THIS ONE) + INY + LDA (J),Y + STA (I),Y +REMVC2: LDA #0 + LDY #6 ; CLEAR "LOC" + STA (J),Y + INY + STA (J),Y + INY ; AND "NEXT" SLOTS ([Y] = 5) + STA (J),Y ; OF SOURCE OBJECT (ARG1) + INY + STA (J),Y +REMVEX: RTS + + +; ------ +; PRINTD +; ------ +; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + +ZPRD: LDA ARG1+LO + LDX ARG1+HI ; (EZIP) + + ; ENTRY POINT FOR "USL" + +PRNTDC: JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + LDY #12 ; GET PROP TABLE POINTER (EZIP) + 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+LO ; RE-SYNC THE + STA ZSP+LO ; Z-STACK POINTER + LDA OLDZSP+HI + STA ZSP+HI + 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 + + ;EZIP STX OLDZSP + + STA ZPCL + JSR POPVAL + STX OLDZSP+LO + STA OLDZSP+HI + JSR VLDZPC ;MAKE VALID + JSR A12VAL ; MOVE [ARG1] TO [VALUE] +PATCHI EQU $+1 ; FOR ZINPUT RTN (IF A FCN CALL) (EZIP) + 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 (QUAD) 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 + + + + PAGE + SBTTL "--- 2-OPS ---" + + +; ----- +; LESS? +; ----- +; [ARG1] HIGH [ARG2]? + +ZLESS: JSR A12VAL ; MOVE [ARG1] TO [VALUE] + JMP DLS0 ; MOVE [ARG2] TO [I] & COMPARE + + +; ------ +; DLESS? +; ------ +; DECREMENT [ARG1] ; SUCCEED IF HIGH [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] LOW [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 + + +; ----------------- +; SIGNED COMPARISON +; ----------------- +; ENTRY: VALUES IN [VALUE] AND [I] + +COMPAR: LDA I+HI + EOR VALUE+HI + BPL SCMP + LDA I+HI + CMP VALUE+HI + BCC PGOOD + JMP PREDF + +SCMP: LDA VALUE+HI + CMP I+HI + BNE SCEX + LDA VALUE+LO + CMP I+LO +SCEX: BCC PGOOD + JMP PREDF + + +; --- +; IN? +; --- +; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? + +ZIN: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [I] + LDY #6 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET DATA + CMP ARG2+HI ; IS IT THERE? + BNE PBAD ; NO + INY + LDA (I),Y + CMP ARG2+LO + 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 [ARG2] SET IN OBJECT [ARG1]? + +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] +; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + +ZMOVE: JSR ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS + + ; NOW, IF IT IS ANYWHERE + + LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET SOURCE OBJECT ADDR INTO [I] + LDA I+LO ; COPY SOURCE (ARG1) ADDRESS + STA J+LO ; INTO [J] + LDA I+HI + STA J+HI + LDA ARG2+HI ; GET DEST OBJECT ID + LDY #6 ; POINT TO "LOC" SLOT OF SOURCE + STA (I),Y ; AND MOVE IT IN + TAX ; (MOVE ARG2 INTO PARENT SLOT OF ARG1) + LDA ARG2+LO + INY + STA (I),Y ; X/A (HI/LO) SET FOR OBJLOC + JSR OBJLOC ; GET ADDR OF DEST OBJECT INTO [I] (GET PARENT) + + ; NOW SWAP IN NEW VALUE + + LDY #10 ; POINT TO "FIRST" SLOT + LDA (I),Y ; OF PARENT (ARG2) + STA K+HI ; SAVE HERE FOR A MOMENT + LDA ARG1+HI ; GET SOURCE OBJECT ID + STA (I),Y ; MAKE IT "FIRST" OF PARENT + INY + LDA (I),Y + TAX + LDA ARG1+LO + STA (I),Y + TXA + ORA K+HI ; CHECK OLD "FIRST" OF DEST/PARENT + BEQ ZMVEX ; SCRAM IF ZERO + TXA ; GET LO BYTE AGAIN + LDY #9 ; MAKE OLD "FIRST" OF PARENT + STA (J),Y ; THE "NEXT" (SIBLING) OF THIS OBJECT (ARG1) + DEY ; I.E. ADD THIS ONE AT THE TOP OF LIST + LDA K+HI ; & GET HIGH BYTE + STA (J),Y +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 + LDA #0 + 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 + ADC #0 ; PICK UP CARRY FROM MPCM + STA MPCH ; TO GET TOP BIT + JMP VLDMPC + + +; ---- +; GETP +; ---- +; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 + +ZGETP: JSR PROPB +GETP1: JSR PROPN ; GET ADDR OF PROP TBL + CMP ARG2+LO ; GET PROP ID + BEQ GETP3 ; FOUND IT + BCC GETP2 ; NOT THERE + JSR NEXTPI ; GET NEXT PROP, ALIGN [I] TO IT (EZIP) + JMP GETP1 ; TRY AGAIN WITH NEXT PROP + + ; PROPERTY NOT THERE, GET DEFAULT + +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 ; GET LENGTH OF PROP INTO [A] + INY ; MAKE [Y] POINT TO 1ST BYTE OF PROP + CMP #1 ; IF LENGTH =1 + BEQ GETPB ; GET A BYTE PROPERTY + CMP #2 ; IF LENGTH = 2 + 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: LDA ARG1+LO + LDX ARG1+HI ; (EZIP) + JSR OBJLOC + LDY #12 ; (EZIP) + 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 + +GETPT1: LDA (I),Y + AND #%00111111 ; MASK OUT LENGTH BITS (EZIP) + + CMP ARG2+LO ; CHECK ID + BEQ GETPT2 + BCS DDD + JMP DORET ; BEYOND IT, SO NOT THERE + +DDD: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT0 ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + JMP AAA + +SHORT0: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE0 + LDA #2 ; BIT 6 = 1, LENGTH =2 + JMP AAA +ONE0: LDA #1 ; BIT 6 = 0, LENGTH =1 + +AAA: TAX ; SAVE HERE +PPPX: INY ; LOOP UNTIL + BNE PPPY + INC I+HI +PPPY: DEX ; [Y] POINTS TO + BNE PPPX ; START OF NEXT PROP + INY ; CORRECT ALIGNMENT + TYA ; ADD OFFSET TO NEXT PROP + CLC ; TO [I] SO I POINTS DIRECTLY + ADC I+LO ; AT IT + STA I+LO + BCC CCCC1 + INC I+HI ; ADD IN CARRY +CCCC1: LDY #0 ; CLEAR [Y] AS IT IS USED AS AN INDEX + + JMP GETPT1 + +GETPT2: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT1 ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + JMP BBB + +SHORT1: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE1 + LDA #2 ; BIT 6 = 1, LENGTH =2 + JMP BBB +ONE1: LDA #1 ; BIT 6 = 0, LENGTH =1 + +BBB: INY ; INC TO POINT AT PROPERTY VALUE (EZIP) + +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 [AR +; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO + +ZNEXTP: JSR PROPB ; ALIGN [I] AT PROPERTY TBL'S 1ST ENTRY + 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 NEXTPI ; ELSE TRY NEXT PROPERTY (EZIP) + JMP NXTP1 +NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +NXTP3: JSR PROPN ; GET THE PROPERTY # + LDX #0 ; FOR PUTBYT (EZIP) + 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 diff --git a/apple/ezip/opsx.asm b/apple/ezip/opsx.asm new file mode 100644 index 0000000..3cbce51 --- /dev/null +++ b/apple/ezip/opsx.asm @@ -0,0 +1,440 @@ + 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!) + + +; ------------------- +; XCALL, CALL1, CALL2 +; ------------------- + +ZXCALL: ; DROP THROUGH +ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +ZCALL2: + + +; ---- +; CALL +; ---- +; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +; ([ARG5]-[ARG8] FOR XCALL (EZIP)) + +ZCALL: LDA ARG1+LO + ORA ARG1+HI ; IS CALL ADDRESS ZERO? + BNE DOCALL ; NO, CONTINUE + LDX #0 + JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER + LDA OLDZSP+HI + JSR PUSHXA + LDA ZPCL ; AND LSB OF [ZPC] + JSR PUSHXA ; ON THE Z-STACK ([X] NOT USED HERE - EZIP) + 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 + ASL ARG1+LO ; MULTIPLY [ARG1] + ROL ARG1+HI ; (BY 2) + ROL A ; HIGH BIT INTO [A] + STA ZPCH ; NEW HIGH BIT OF [ZPC] + ASL ARG1+LO ; BY 4 (EZIP) + ROL ARG1+HI + ROL ZPCH + LDA ARG1+HI ; GET NEW LOW BYTES + STA ZPCM + LDA ARG1+LO + STA ZPCL + JSR VLDZPC + JSR NEXTPC ; FETCH # LOCALS TO PASS + STA J+LO ; SAVE HERE FOR COUNTING + STA J+HI ; AND HERE FOR LATER REFERENCE + BEQ ZCLL2 ; SKIP IF NO LOCALS + LDA #0 + STA I+LO ; ELSE INIT STORAGE INDEX +ZCLL1: LDY I+LO + LDX LOCALS+LO,Y ; GET LSB OF LOCAL INTO [X] + LDA LOCALS+HI,Y ; AND MSB INTO [A] + 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 ZCLL1 ; YES, KEEP LOOPING + + ; MOVE UP TO 3 ARGUMENTS TO [LOCALS] ( 7 FOR XCALL (EZIP)) + +ZCLL2: 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 + DEC NARGS ; MORE (THAT MEANS IT'S AN XCALL) + BEQ ZCALL3 ; NO, JUST A CALL + LDA ARG5+LO ; MOVE [ARG5] TO LOCAL #4 + STA LOCALS+LO+6 + LDA ARG5+HI + STA LOCALS+HI+6 + DEC NARGS ; MORE? + BEQ ZCALL3 ; NO + LDA ARG6+LO ; MOVE [ARG6] TO LOCAL #5 + STA LOCALS+LO+8 + LDA ARG6+HI + STA LOCALS+HI+8 + DEC NARGS ; MORE? + BEQ ZCALL3 ; NO + LDA ARG7+LO ; MOVE [ARG7] TO LOCAL #6 + STA LOCALS+LO+10 + LDA ARG7+HI + STA LOCALS+HI+10 + DEC NARGS ; MORE? + BEQ ZCALL3 ; NO + LDA ARG8+LO ; MOVE [ARG8] TO LOCAL #7 + STA LOCALS+LO+12 + LDA ARG8+HI + STA LOCALS+HI+12 +ZCALL3: LDX J+HI ; RETRIEVE # LOCALS + TXA ; DUPE FOR NO GOOD REASON + JSR PUSHXA ; PUSH # LOCALS ONTO Z-STACK + LDA ZSP+HI ; REMEMBER WHERE + STA OLDZSP+HI ; WE CAME FROM + LDA ZSP+LO + STA OLDZSP+LO + 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 ; GET PROP TBL ADDR + +PUTP1: JSR PROPN ; GET ID + CMP ARG2+LO + BEQ PUTP2 + BCC PNERR ; ERROR IF LOWER + JSR NEXTPI ; TRY NEXT PROPERTY, ALIGN [I] AT IT (EZIP) + JMP PUTP1 +PUTP2: JSR PROPL ; GET PROPERTY LENGTH INTO [A] + INY ; MAKE [Y] POINT TO 1ST PROPERTY BYTE + CMP #1 ; IF LENGTH = 1 + BEQ PUTP3 ; PUT A BYTE + CMP #2 ; PUT A WORD IF [A] = 2 + 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 DB II 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 DB II + 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 ; IF VALUE IS ZERO + ORA ARG1+HI + BNE ZRAND1 + STA SRHOLD+LO ; RETURN TO RANDOM RANDOM + STA SRHOLD+HI ; CLEAR INDICATOR + JMP RET0 ; AND RETURN THRU HERE SO ALIGNED +ZRAND1: LDA SRHOLD+LO ; ARE WE NONRAMDOM INCREMENTING? (EZIP) + ORA SRHOLD+HI + BNE ZRAND3 ; YUP + LDA ARG1+HI + BPL ZRAND2 ; GENERATE A RANDOM # + EOR #$FF ; SET UP TO INCREMENT FROM 1 THRU INT + STA SRHOLD+HI ; GET ABSOLUTE + LDA ARG1+LO + EOR #$FF + STA SRHOLD+LO + INC SRHOLD+LO + LDA #0 ; W/ NO RAMDOMNESS + STA RAND1+LO + STA RAND1+HI + BEQ ZRAND3 ; JMP (END EZIP) +ZRAND2: 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 + CLC + ADC #1 ; ADD 1 + STA VALUE+LO ; INTO [VALUE] + LDA REMAIN+HI + ADC #0 + STA VALUE+HI + JMP PUTVAL ; AND RETURN RESULT + + ; NON RANDOM INCREMENTING + +ZRAND3: LDA ARG1+LO ; RESET TOP OF COUNT W/ EACH ENTRY + STA SRHOLD+LO ; SO ALWAYS W/IN RANGE OF CALL + LDA ARG1+HI + STA SRHOLD+HI + + LDA RAND1+HI ; (EZIP) + CMP SRHOLD+HI + BCC ZRAND4 + LDA RAND1+LO + CMP SRHOLD+LO + BCC ZRAND4 + BEQ ZRAND4 + LDA #1 ; WENT THRU ALL + STA RAND1+LO ; START AGAIN + LDA #0 + STA RAND1+HI +ZRAND4: LDA RAND1+LO + STA VALUE+LO + LDA RAND1+HI + STA VALUE+HI + INC RAND1+LO ; FOR NEXT TIME + BNE ZRAND5 + INC RAND1+HI +ZRAND5: JMP PUTVAL ; (END EZIP) + + +; ---- +; 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 + + +; ------ +; INTBL? +; ------ + +ZINTBL: LDA ARG2+LO ; PICK UP TBL ADDR + STA MPCL + LDA ARG2+HI + STA MPCM + LDA #0 + STA MPCH ; ONLY A WORD ADDR, SO IN 1ST 64K + JSR VLDMPC +INTLP: JSR GETBYT ; GET A WORD ENTRY FROM TBL + STA I+HI + JSR GETBYT + CMP ARG1+LO ; DOES IT = THE VALUE LOOKING FOR? + BNE INTNXT ; NO + LDA I+HI + CMP ARG1+HI + BEQ INTFND ; YES, FOUND IT +INTNXT: DEC ARG3+LO + BNE INTLP + LDA ARG3+HI + BEQ INTNF ; NOT FOUND + DEC ARG3+HI + JMP INTLP ; GO DO SOME MORE +INTFND: SEC + LDA MPCL +; +; 5/26/87 jdarnold - changed from 1 to 2, cuz that's how it was in +; the commodore version +; + SBC #2 + + STA MPCL + BCS INTEX + DEC MPCM ; ONCE AGAIN, RETURNING WORD SO 64K LIMIT +INTEX: STA VALUE+LO ; AND SET TO RETURN THE VALUE + LDA MPCM + STA VALUE+HI + JSR PUTVAL ; SEND IT BACK + JMP PREDS ; AND SCREEM SUCCESS +INTNF: LDA #0 ; 0 = NOT FOUND + STA VALUE+LO + STA VALUE+HI + JSR PUTVAL + JMP PREDF ; FAILED! + + END diff --git a/apple/ezip/read.asm b/apple/ezip/read.asm new file mode 100644 index 0000000..79e18ab --- /dev/null +++ b/apple/ezip/read.asm @@ -0,0 +1,453 @@ + PAGE + SBTTL "--- READ HANDLER ---" + + +; ---- +; READ +; ---- +; READ LINE INTO TABLE [ARG1] ; PARSE INTO TABLE [ARG2] + +ZREAD: ;JSR ZUSL ; UPDATE THE STATUS LINE (NOT IN EZIP) + LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + CLC ; ABSOLUTE + ADC ZCODE + STA RDTBL1+HI ; AND PLACE IT HERE TO USE + LDA ARG1+LO + STA RDTBL1+LO ; LSBS NEED NOT CHANGE + LDA ARG2+HI + CLC + ADC ZCODE + STA RDTBL2+HI + LDA ARG2+LO + STA RDTBL2+LO + + LDY #0 ; GET SIZE OF INPUT BUFFER + LDA (RDTBL1),Y + CMP #79 ; IF OVER 78, CUT DOWN TO 78 + BCC LEAVIT ; LEAVE IT AS IT IS, IT IS LESS + LDA #78 +LEAVIT: STA CHRMAX ; SET COUNTER FOR INPUT + JSR INPUT ; READ LINE; RETURN LENGTH IN [A] + + ; IF TIMEOUT, [A]=0 SO WILL QUIT W/NO RESULTS + + STA LINLEN ; SAVE # CHARS IN LINE + LDA #0 + STA WRDLEN ; INIT # CHARS IN WORD COUNTER + LDY #1 ; POINT TO "# WORDS READ" SLOT + STA (RDTBL2),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 (RDTBL2),Y ; AND READ IT + BEQ RDERR ; (5/14/85 - FORCE # WORDS TO + CMP #59 ; BE BETWEEN 1 AND 59) + BCC RD0 +RDERR: LDA #58 ; (5/16/86 - MAKE IT 58, 59 LOST) + STA (RDTBL2),Y ; Le) +RD0: INY ; (Y = 1) POINT TO "# WORDS READ" SLOT + CMP (RDTBL2),Y ; TOO MANY WORDS? + BCC RLEX ; YES, SO LEAVE, IGNORING THE REST + +; BCS RL1 ; CHANGED 5.2.85 IN ZIP & EZIP +; ; *** ERROR #13: PARSER OVERFLOW *** +; +; LDA #13 +; JMP ZERROR + +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 #9 ; 9 CHARS DONE? (EZIP) + 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 #8 ; 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 (RDTBL1),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 (RDTBL1),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 DB II IN [IN] TO Z-STRING + JSR FINDW ; AND LOOK IT UP IN VOCABULARY + LDY #1 + LDA (RDTBL2),Y ; FETCH THE # WORDS READ + CLC + ADC #1 ; INCREMENT IT + STA (RDTBL2),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 RDTBL2+LO ; LSB OF RESULT TABLE BASE + CLC + ADC RESULT ; AND CURRENT POINTER + STA ENTRY+LO ; SAVE IN [ENTRY] + LDA RDTBL2+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 (RDTBL1),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? +; --------------------------------- +; ------------------ +; NORMAL BREAK CHARS +; ------------------ + +BRKTBL: DB '!?,.' ; IN ORDER OF + DB $0D ; DB ENDING FREQUENCY + DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED +NBRKS EQU $-BRKTBL ; # NORMAL BREAKS + +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 + + +; --------------------- +; IS CHAR IN [A] A SIB? +; --------------------- + +SIB: STA IOCHAR ; SAVE TEST CHAR + LDA ZBEGIN+ZVOCAB ; GET 1ST BYTE IN VOCAB TABLE + LDY ZBEGIN+ZVOCAB+1 + STA MPCM + STY MPCL + LDA #0 + STA MPCH + JSR VLDMPC ; GET CORRECT PAGE + JSR GETBYT ; HAS # SIBS + STA J ; USE AS AN INDEX +SBL: JSR GETBYT ; GET NEXT SIB + CMP IOCHAR ; MATCHED? + BEQ FBRK0 ; YES, REPORT IT + DEC J + BNE SBL ; ELSE KEEP LOOPING + LDA IOCHAR + CLC ; NO MATCH, SO + RTS ; EXIT WITH CARRY CLEAR +FBRK0: LDA IOCHAR +FBRK: SEC ; EXIT WITH CARRY SET + RTS ; IF MATCHED WITH A BREAK CHAR + + +; ----------------- +; VOCABULARY SEARCH +; ----------------- +; ENTRY: 6-BYTE TARGET Z-WORD IN [OUT] +; EXIT: VIRTUAL ENTRY ADDRESS IN [VALUE] IF FOUND ; +; OTHERWISE [VALUE] = 0 + +VWLEN EQU I +VWCUR EQU J+HI + +FINDW: LDA ZBEGIN+ZVOCAB ; GET VIRTUAL ADDR OF VOCAB TBL + LDY ZBEGIN+ZVOCAB+1 + STA MPCM + STY MPCL + LDA #0 + STA MPCH + JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # SIBS + CLC + ADC MPCL ; GET ACTUAL BASE ADDR OF VOCAB ENTRIES + STA MPCL + BCC FWL0 + INC MPCM +FWL0: JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # BYTES PER ENTRY (AND MOVE TO NEXT BYTE) + STA ESIZE ; SAVE IT HERE + STA VWLEN+0 ; AND HERE + LDA #0 ; CLEAR REST OF COUNTER + STA VWLEN+1 + STA VWLEN+2 + + JSR GETBYT ;GET # OF ENTRIES IN TBL (MSB) + STA NENTS+HI ; AND STUFF IT IN [NENTS] + JSR GETBYT ; DON'T FORGET THE LSB! + STA NENTS+LO + LDA #0 ; FIND SIZE OF VAOCAB TBL + STA VOCEND ; TO LOCATE THE END OF IT + STA VOCEND+1 + STA VOCEND+2 + LDX ESIZE + +FWL1: CLC + LDA VOCEND ; (# OF ENTRIES) * (ENTRY SIZE) + ADC NENTS+LO + STA VOCEND + LDA VOCEND+1 + ADC NENTS+HI + STA VOCEND+1 + LDA VOCEND+2 + ADC #0 ; PICK UP CARRY + STA VOCEND+2 + DEX + BNE FWL1 + + CLC + LDA VOCEND ; AND ADD LENGTH TO START OF TBL + ADC MPCL ; TO GET END OF TBL + STA VOCEND + LDA VOCEND+1 + ADC MPCM + STA VOCEND+1 + LDA VOCEND+2 + ADC MPCH + STA VOCEND+2 ; TO SAVE FOR TESTING IF PAST END + + LDA VOCEND ; SUBTRACT [ESIZE] SO THAT + SEC ; [VOCEND] POINTS TO REAL LAST ENTRY + SBC ESIZE + STA VOCEND + LDA VOCEND+1 + SBC #0 + STA VOCEND+1 + +; NOP +; NOP +; NOP +; NOP +; NOP +; NOP + + ; BEGIN THE SEARCH! [MPC] NOW POINTS TO 1ST ENTRY + + LSR NENTS+HI ; 2 ALIGN # OF ENTRIES + ROR NENTS+LO +FWCALC: ASL VWLEN+0 ; CALCULATE INITIAL OFFSET FOR SEARCH + ROL VWLEN+1 + ROL VWLEN+2 + LSR NENTS+HI + ROR NENTS+LO + BNE FWCALC + +; LDA NENTS+HI +; BNE FWCALC ; DOUBLE-CHECK + + CLC ; ADD 1ST OFFSET INTO START OF VOCABULARL + LDA MPCL ; WHICH IS CURRENTLY IN MPC + ADC VWLEN+0 + STA MPCL + LDA MPCM + ADC VWLEN+1 + STA MPCM + LDA MPCH + ADC VWLEN+2 + STA MPCH + + SEC ; AVOID FENCE-POST BUG FOR + LDA MPCL ; EXACT-POWER-OF-2 TBL (DUNCAN) + SBC ESIZE + STA MPCL + BCS FWLOOP + LDA MPCM + SEC + SBC #1 + STA MPCM + BCS FWLOOP + LDA MPCH + SBC #0 + STA MPCH + +FWLOOP: LSR VWLEN+2 ; SET FOR NEXT OFFSET, + ROR VWLEN+1 ; WHICH IS HALF THIS ONE + ROR VWLEN+0 + + LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + + JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET 1ST BYTE OF ENTRY + + CMP OUT ; MATCH 1ST BYTE OF TARGET? + BCC WNEXT ; LESS + BNE FWPREV ; GREATER + JSR GETBYT + CMP OUT+1 ; 2ND BYTE MATCHED? + BCC WNEXT + BNE FWPREV ; NOPE + JSR GETBYT + CMP OUT+2 ; 3RD BYTE? + BCC WNEXT + BNE FWPREV ; SORRY ... + JSR GETBYT + CMP OUT+3 ; 4TH BYTE + BCC WNEXT + BNE FWPREV + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BCC WNEXT + BNE FWPREV ; SORRY ... + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + BCS FWPREV ; ELSE BACK UP ... + +WNEXT: LDA VWCUR+0 ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + ADC VWLEN+1 + + BCS WNXT2 ; SAVES CODE (?) + + STA MPCM + + LDA #0 + STA MPCH + +; LDA VWCUR+2 +; ADC VWLEN+2 +; STA MPCH + +; LDA MPCH +; CMP VOCEND+2 ; GONE PAST END? +; BEQ WNXT0 ; MAYBE +; BCS WNXT2 ; YES +; BCC FWMORE ; NO +WNXT0: LDA MPCM + CMP VOCEND+1 + BEQ WNXT1 ; MAYBE + BCS WNXT2 ; YES + BCC FWMORE ; NO +WNXT1: LDA MPCL + CMP VOCEND + BCC FWMORE ; NO + BEQ FWMORE ; NO, EQUAL +WNXT2: LDA VOCEND ; YES, SO POINT TO END OF TBL + STA MPCL + LDA VOCEND+1 + STA MPCM + LDA VOCEND+2 + STA MPCH + JMP FWMORE + +FWPREV: LDA VWCUR+0 ; TO MOVE DOWN, JUST SUBTRACT + SEC ; OFFSET FROM START OF THIS + SBC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + SBC VWLEN+1 + STA MPCM + LDA VWCUR+2 + SBC VWLEN+2 + STA MPCH + +FWMORE: LDA VWLEN+2 ; IF OFFSET HIGH GELOW 1 WORD, CONTINUE + BNE FWM1 + LDA VWLEN+1 + BNE FWM1 + LDA VWLEN+0 + CMP ESIZE + BCC FWFAIL +FWM1: JMP FWLOOP ; AND TRY AGAIN + +FWFAIL: LDA #0 ; NOT FOUND + STA VALUE+LO + STA VALUE+HI + RTS ; THEN RETURN WITH [VALUE] = 0 + +FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD + STA VALUE+LO + LDA VWCUR+1 + STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY + RTS ; WORD VALUE RETURNABLE + + END diff --git a/apple/ezip/rwts.asm b/apple/ezip/rwts.asm new file mode 100644 index 0000000..3e2d58d --- /dev/null +++ b/apple/ezip/rwts.asm @@ -0,0 +1,992 @@ + PAGE + SBTTL "--- BOOT CODE & RWTS: APPLE II ---" + + +; --------- +; BOOT CODE +; --------- +; LOADS ALL OF TRACK 0 INTO RAM AT $800 TO $1800, +; THEN JUMPS THROUGH [COLD] + + ORG BORG ; (EZIP) + DB 01 ; MAGICAL MYSTERY BYTE + + ; BOOT BEGINS HERE + +BOOT: ;THIS LABLE NEVER USED BUT MUST BE HERE + LDA BADDR+HI ; CHECK MSB OF BOOT ADDRESS + CMP #$09 ; 1ST ENTRY INTO BOOT? + BNE BOOTS0 ; NO, CONTINUE + + ; CALC ADDRESS OF ROM SECTOR READ ROUTINE + + LDA #$D0 + STA BADDR+HI + +;MOVMON + LDA $C089 ;SET TO READ ROM WRITE RAM + LDA $C089 ; MUST READ TWICE TO TURN SWITCH ON + LDY #0 ; COPY MONITOR RTNS TO RAM + LDA #$F8 ; SO DON'T NEED TO ACCESS ROM + STA I+HI + LDA #0 + STA I+LO +BOOTLP: LDA (I),Y ; READ FROM ROM + STA (I),Y ; WRITE TO RAM + INY + BNE BOOTLP ; 256 COUNT + INC I+HI ; THROUGH PG $FF + BNE BOOTLP + LDA $C08B ; SET TO R/W RAM, BANK 1 + LDA $C08B ; MUST READ 2CE + LDA BSLOT ; GET SLOT ID * 16 + STA DCBSLT ; MAKE IT THE DEFAULT TARGET + STA DCBPSL ; AND THE "OLD" SLOT + LSR A ; DIVIDE BY 16 + LSR A + LSR A + LSR A + ORA #%11000000 ; MAKE IT $C0nn + STA I+HI ; USE AS MSB OF ADDRESS + LDA #$5C ; LSB IS ALWAYS $5C + STA I+LO + LDA #1 + STA DCBSEC +BOOTS0: LDX DCBSEC + INC DCBSEC + CPX #$10 + BCS BOOTS1 + LDA ILEAVE,X + STA BSECT + LDX BSLOT + JMP (I) +BOOTS1: JSR INIT + JMP COLD ; LOAD REMAINDER OF ZIP + + +; --------------------- +; SECTOR INTERLEAVE MAP +; --------------------- +; USED BY "BOOT" (AND "RWTS" (NOT THIS W/ EZIP)) +; MUST BE IN 1ST PAGE! + +ILEAVE: DB $00,$04,$08,$0C,$01,$05,$09,$0D + DB $02,$06,$0A,$0E,$03,$07,$0B,$0F +; +; +; RAMDSK +; THIS CODE IS DESIGNED TO RESIDE +; IN MAIN 48K *ABOVE PAGE 2* +; +; ON ENTRY IT ASSUMES THAT MAIN +; BANK 1 IS ENABLED +; A = SECTOR - $00=LOW $4F +; Y = PAGE TO READ/WRITE +; TO/FROM +; X = ON ENTRY 1=WRITE +; 0=READ +; RMDBNK - 48K BANK TO READ TO +; AUX OR MAIN +; THE RAMDISK CAN ONLY WRITE FROM +; MAIN MEMORY (ACTUALLY FROM THE BANK THIS CODE IS IN) +; SECTOR MAP +; $00=LOW $0F IN MAIN BANK 2 +; $10=LOW $1F IN AUX BANK 2 +; $20=LOW $4F IN AUX BANK 1 + + +RMDBNK: DB 00 ;RREMEMBER WHAT BANK THIS IS IN WHEN YOU SET IT + +RAMDSK: STY WRTBNK+MAIN ;WRITE TO MAIN 48K BANK (WHERE THIS CODE IS) + STY WRDADD+1+HI ;SAVE HIGH ADDRESS FOR EITHER + STY RAMLOOP+1+HI ;READ OR WRITE + + CMP #$10 + BCS RAM1 + LDY BNK2SET ;IN MAIN BANK 2 + LDY BNK2SET ;ENABLE BANK 2 WITH TWO READS + ADC #$D0 ;C=0 , ALIGN SECTOR INTO RAM + BNE RAMDO + +RAM1: STA ALTZP+AUX ;IT IS IN AUX RAM + CMP #$20 ;BANK 1 OR 2 ??? + BCS RAM2 + LDY BNK2SET ;IN AUX BANK 2 + LDY BNK2SET ;ENABLE BANK 2 + ADC #$C0 ;ALIGN + BNE RAMDO + +RAM2: ADC #$AF ;C=1 ; IN AUX BANK 1 + +RAMDO: DEX ; SEE IF X WAS A 1 + BNE RAMREAD ;NO IT WAS A ZERO + STA WRDADD+1+HI ;WRITE + BEQ RAMDO1 + +RAMREAD: STA RAMLOOP+1+HI ;READ + LDY RMDBNK ;THIS MUST BE GOTTEN FROM A SAFE PLACE + STA WRTBNK,Y ;SET TO READ TO RMDBNK +RAMDO1: LDY #00 +RAMLOOP: LDA $FF00,Y +WRDADD: STA $FF00,Y + INY + BNE RAMLOOP + + ; LEAVE WITH MAIN BANK1 ENABLED + ; AND MAIN 48K SELECTED FOR WRITE + + LDA BNK1SET + LDA BNK1SET + STA WRTBNK+MAIN + STA ALTZP+MAIN + RTS + + + ; FILL TO PAGE BOUNDRY WITH 00 + + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 0,0 + + +; INFOCOM'S VERSION OF APPLE RWTS (READ/WRITE TRACK/SECTOR) +; HACKED BY ANDREW KALUZNIACKI +; FROM THE DOS RWTS ON APPLE DOS 3.3 + + ORG $D000 + +; ------------------------------- +; MAIN ENTRY INTO INFO-DOS (IDOS) +; ------------------------------- +; [DCBSEC] SECTOR (0-15), SET BY CALLER +; [DCBTRK] TRACK (0-34), SET BY CALLER +; [DCBDRV] DRIVE (1 OR 2), SET BY CALLER [BOOT DEFAULT] +; [DCBSLT] SLOT*16, SET BY CALLER [BOOT DEFAULT] +; [DCBPSL] SLOT*16 OF LAST USED SLOT, SET BY BOOT +; [DCBPDR] LAST DRIVE USED (1 OR 2), SET BY BOOT +; [DCBCMD] STORAGE FOR COMMAND SENT IN HIGH ALOW AT CALL TO IDOS +; [DCBERR] IDOS ERROR CODE +; [DCBBFL] DISK BUFFER ADDRESS (LSB) [BOOT = IOBUFF] +; [DCBBFM] DISK BUFFER ADDRESS (MSB) [BOOT = IOBUFF] +; HIGH ALOW =1 WRITES DISK BUFFER +; HIGH ALOW =0 READS DISK BUFFER +; [IOBUFF] = 256-BYTE BUFFER FOR DISK I/O +; (OPTIONAL IF [DCBBFL/DCBBFM] ARE SET) +; [BUFFA] ONE PAGE BUFFER +; [BUFFB] $56 BYTE BUFFER +; CARRY CLEAR ON RETURN IF NO ERROR +; IF CARRY SET, ERROR CODE IS IN [DERR]: +; $10 = WRITE PROTECTED +; $40 = DRIVE ERROR +; $80 = READ ERROR +; *** WARNING *** +; IDOS MUST START ON A PAGE BOUNDARY. +; CHANGE ANY CODE BETWEEN [IDOS] AND [INIT] AT YOUR OWN RISK. +; YOU HAVE BEEN WARNED. + +DOS: NOP + NOP + NOP ; DON'T ASK, AND DON'T CHANGE + PHP ; SAVE STATUS OF [I] + SEI ; DISABLE INTERUPTS + JSR DOSENT ; DO IT (GO TO MAIN ROUTINE) + BCS DSERR ; ERROR OCCURED IF C=1 + PLP ; RESTORE [I] + CLC ; SET "NO ERROR" + RTS ; RETURN FROM CALL + +DSERR: PLP ; RESTORE [I] + SEC ; INDICATE ERROR + RTS ; EXIT + + ; PRE-NIBBLIZE [IOBUFF] BEFORE WRITING + +PRENIB: LDX #0 + LDY #2 +PRELP1: DEY + LDA (DCBBFL),Y + LSR A + ROL BUFFB,X + LSR A + ROL BUFFB,X + STA BUFFA,Y + INX + CPX #$56 + BCC PRELP1 + LDX #0 + TYA + BNE PRELP1 + LDX #$55 ; CLEAR BITS 7 AND 6 +PRELP2: LDA BUFFB,X ; OF TOP NIBBLE BUFFER + AND #%00111111 + STA BUFFB,X + DEX + BPL PRELP2 + RTS + + +; ------------ +; WRITE SECTOR +; ------------ +; WRITES PRENIBBLIZED DATA AT [BUFFA/BUFFB] TO DISK +; ENTRY: SLOT*16 IN [X] +; EXIT: CARRY SET IF ERROR + +WRTDTA: STX DTMP4 ; SAVE SLOT ID HERE + STX SLTMP2 + SEC ; SET CARRY FOR POSSIBLE ERROR + LDA Q6H,X ; CHECK FOR WRITE-PROTECT + LDA Q7L,X + BMI WRTEXI ; EXIT W/CARRY SET IF PROTECTED + LDA BUFFB ; SAVE 1ST BYTE OF 2NDARY BUFFER + STA DTMP3 ; FOR LATER + LDA #$FF ; ESTABLISH AUTOSYNC BYTE + STA Q7H,X ; SET DRIVE TO WRITE MODE + ORA Q6L,X ; WAIT FOR HARDWARE TO SETTLE + PHA + PLA + NOP + LDY #4 ; WRITE 5 AUTOSYNC BYTES +WRTLP1: PHA + PLA + JSR WRBYT2 ; USING 40 uS DELAY + DEY + BNE WRTLP1 + LDA #$D5 ; WRITE DATA FIELD PROLOGUE: + JSR WRBYT1 ; $D5-$AA-$AD + LDA #$AA + JSR WRBYT1 + LDA #$AD + JSR WRBYT1 + TYA ; A BRIEF DELAY + LDY #$56 ; INIT LOOP INDEX + BNE WRTSK1 ; BRANCH ALWAYS + + ; WRITE [BUFFB] TO DISK + +WRTLP2: LDA BUFFB,Y ; GET A BYTE FROM [BUFFB] +WRTSK1: EOR BUFFB-1,Y + TAX ; USE IT AS AN INDEX + LDA WRTTBL,X ; INTO THE TRANSLATE TABLE + LDX DTMP4 ; RESTORE SLOT ID + STA Q6H,X ; AND WRITE THE TRANSLATED BYTE + LDA Q6L,X + DEY ; LOOP TILL + BNE WRTLP2 ; EMPTY + + ; WRITE [BUFFA] TO DISK + + LDA DTMP3 ; RESTORE "LOST" [BUFFB] BYTE + NOP ; WAIT JUST A MOMENT ... +WRTLP3: EOR BUFFA,Y ; GET A BYTE FROM [BUFFA] + TAX ; USE IT AS AN INDEX + LDA WRTTBL,X ; INTO THE TRANSLATE TABLE + LDX SLTMP2 ; RESTORE SLOT ID + STA Q6H,X ; AND WRITE THE TRANSLATED BYTE + LDA Q6L,X + LDA BUFFA,Y ; GET NEXT BYTE FROM BUFFER + INY ; AND LOOP TILL + BNE WRTLP3 ; ALL OF [BUFFA] IS WRITTEN + TAX + LDA WRTTBL,X + LDX DTMP4 ; RESTORE SLOT ID + JSR WRBYT3 ; AND WRITE THE LAST [BUFFA] BYTE + LDA #$DE ; WRITE DATA FIELD EPILOGUE: + JSR WRBYT1 ; $DE-$AA-$EB + LDA #$AA + JSR WRBYT1 + LDA #$EB + JSR WRBYT1 + LDA #$FF ; WRITE GAP 3 + JSR WRBYT1 + LDA Q7L,X ; SET DRIVE TO READ MODE +WRTEXI: LDA Q6L,X + RTS + + +; ---------------------------- +; WRITE A BYTE (TIME-CRITICAL) +; ---------------------------- +; ENTRY: BYTE TO WRITE IN [A] +; SLOT*16 IN [X] + +WRBYT1: CLC ; PROLOGUE, EPILOGUE AND GAP 3 TIMING +WRBYT2: PHA ; ENTRY FOR GAP 2 TIMING + PLA +WRBYT3: STA Q6H,X + ORA Q6L,X + RTS + + ; CONVERT RAW DATA TO BINARY IN [IOBUFF] + +POSTNB: LDY #0 +PSTSK1: LDX #$56 +PSTLP1: DEX + BMI PSTSK1 + LDA BUFFA,Y + LSR BUFFB,X + ROL A + LSR BUFFB,X + ROL A + STA (DCBBFL),Y + INY + CPY DTMP3 + BNE PSTLP1 + RTS + + +; ----------- +; READ SECTOR +; ----------- +; READ RAW SECTOR DATA TO [BUFFA/BUFFB] +; ENTRY: SLOT*16 IN [X] +; EXIT: CARRY SET IF ERROR, ELSE 342 RAW BYTES IN [BUFFA/BUFFB] + +RDSECT: LDY #$20 +RDLP1: DEY ; RETURN AN ERROR IF + BEQ RDBAD ; NO $D5 FOUND AFTER 32 TRIES + + ; FETCH & VALIDATE PROLOGUE ($D5-$AA-$AD) + +RD1: LDA Q6L,X ; GET A BYTE + BPL RD1 +RDSK1: EOR #$D5 ; WAS IT $D5? + BNE RDLP1 ; NO, KEEP LOOKING + NOP ; ELSE WAIT A MOMENT ... +RD2: LDA Q6L,X ; GET ANOTHER BYTE + BPL RD2 + CMP #$AA ; WAS IT $AA? + BNE RDSK1 ; CHECK FOR $D5 AGAIN IF NOT + LDY #$56 ; ELSE INIT DATA-READ INDEX +RD3: LDA Q6L,X ; GET A BYTE + BPL RD3 + CMP #$AD ; WAS IT $AD? + BNE RDSK1 ; CHECK FOR $D5 IF NOT + + ; READ RAW DATA INTO [BUFFB] + + LDA #0 ; CLEAR [A], DELAY ... +RDLP2: DEY + STY DTMP3 ; SAVE INDEX HERE +RD4: LDY Q6L,X ; GET A DATA BYTE + BPL RD4 + EOR RDTBL-$96,Y ; TRANSLATE IT + LDY DTMP3 ; RESTORE INDEX + STA BUFFB,Y ; STORE BYTE IN [BUFFB] + BNE RDLP2 ; CONTINUE TILL [BUFFB] FULL + + ; READ RAW DATA INTO [BUFFA] + +RDLP3: STY DTMP3 ; RE-INIT INDEX TO ZERO +RD5: LDY Q6L,X ; GET A DATA BYTE + BPL RD5 + EOR RDTBL-$96,Y ; TRANSLATE IT + LDY DTMP3 ; RESTORE INDEX + STA BUFFA,Y ; SAVE BYTE IN [BUFFA] + INY + BNE RDLP3 ; LOOP TILL [BUFFA] IS FULL + + ; FETCH & VALIDATE CHECKSUM + +RD6: LDY Q6L,X ; GET THE NEXT BYTE + BPL RD6 + CMP RDTBL-$96,Y ; TRANSLATE IT + BNE RDBAD ; ERROR IF CHECKSUM BAD + + ; FETCH & VALIDATE EPILOGUE ($DE-$AA-$EB) + +RD7: LDA Q6L,X ; GET A BYTE + BPL RD7 + CMP #$DE ; IS IT $DE? + BNE RDBAD ; ERROR IF NOT + NOP ; WAIT ... +RD8: LDA Q6L,X ; GET ANOTHER BYTE + BPL RD8 + CMP #$AA ; IS IT $AA? + BEQ RDOK ; DATA OKAY IF SO +RDBAD: SEC ; ELSE SET CARRY FOR ERROR + RTS ; AND SCRAM + + +; --------------------- +; READ AN ADDRESS FIELD +; --------------------- +; ENTRY: SLOT*16 IN [X] +; EXIT: CARRY SET IF ERROR + +RDADDR: LDY #$FC ; INIT TIMEOUT COUNTER + STY DTMP3 +ADDLP1: INY + BNE ADD1 + INC DTMP3 ; ERROR IF + BEQ RDBAD ; CAN'T FIND ADDRESS HEADER + + ; FETCH THE ADDRESS FIELD PROLOGUE ($D5-$AA-$96) + +ADD1: LDA Q6L,X ; GRAB A BYTE + BPL ADD1 +ADDLP2: CMP #$D5 ; WAS IT $D5? + BNE ADDLP1 ; NO, KEEP SEARCHING + NOP ; ELSE WAIT A FEW MICROSECONDS ... +ADD2: LDA Q6L,X ; GET ANOTHER BYTE + BPL ADD2 + CMP #$AA ; WAS IT $AA? + BNE ADDLP2 ; NO, CHECK IF $D5 + LDY #3 ; ELSE INIT DATA-FETCH INDEX +ADD3: LDA Q6L,X ; GET A BYTE + BPL ADD3 + CMP #$96 ; WAS IT $96? + BNE ADDLP2 ; NO, CHECK FOR $D5 + + ; FETCH THE 4 BYTES OF ADDRESS DATA + + LDA #0 ; INIT CHECKSUM BYTE +ADDLP3: STA DTMP4 ; UPDATE CHECKSUM +ADD4: LDA Q6L,X ; GET A BYTE + BPL ADD4 + ROL A ; SHIFT IT + STA DTMP3 ; AND SAVE 1ST PART HERE +ADD5: LDA Q6L,X ; GET ANOTHER BYTE + BPL ADD5 + AND DTMP3 ; SUPER 1ST PART OF BYTE + STA HDRCHK,Y ; STORE IN RESULT TABLE + EOR DTMP4 ; COMPUTE CHECKSUM + DEY ; GOT 4 BYTES YET? + BPL ADDLP3 ; NO, LOOP BACK + TAY ; LOOK AT CHECKSUM BYTE + BNE RDBAD ; ERROR IF NON-ZERO + + ; FETCH & VALIDATE EPILOGUE ($DE-$AA, IGNORE $EB) + +ADD6: LDA Q6L,X ; GET A BYTE + BPL ADD6 + CMP #$DE ; WAS IT $DE? + BNE RDBAD ; ERROR IF NOT + NOP ; ELSE WAIT A MOMENT ... +ADD7: LDA Q6L,X ; GET ONE MORE BYTE + BPL ADD7 + CMP #$AA ; WAS IT $AA + BNE RDBAD ; ERROR IF NOT +RDOK: CLC ; ELSE CLEAR CARRY FOR SUCCESS + RTS ; AND RETURN + + +; --------------------- +; MOVE ARM TO TRACK [A] +; --------------------- +; ENTRY: SLOT*16 IN [X] +; TARGET TRACK IN [A] +; CURRENT TRACK IN [CTRACK] + +SEEK: STX SLTMP3 ; SAVE SLOT ID + STA TTRK ; AND TARGET TRACK + CMP CTRACK ; TARGET SAME AS CURRENT? + BEQ SEEEXI ; EXIT NOW IF SO + LDA #0 ; INIT + STA DTMP3 ; INDEX +SEESK1: LDA CTRACK ; GET CURRENT TRACK + STA DTMP4 ; SAVE IT HERE + SEC + SBC TTRK ; GET TRACK DIFFERENCE + BEQ SEESK6 + BCS SEESK2 + EOR #%11111111 + INC CTRACK + BCC SEESK3 +SEESK2: ADC #$FE + DEC CTRACK +SEESK3: CMP DTMP3 + BCC SEESK4 + LDA DTMP3 +SEESK4: CMP #$0C + BCS SEESK5 + TAY +SEESK5: SEC + JSR SEEK0 + LDA DELTB1,Y + JSR ARMDEL + LDA DTMP4 + CLC + JSR SEEK1 + LDA DELTB2,Y + JSR ARMDEL + INC DTMP3 + BNE SEESK1 +SEESK6: JSR ARMDEL + CLC +SEEK0: LDA CTRACK +SEEK1: AND #%00000011 + ROL A + ORA SLTMP3 + TAX + LDA PH0OFF,X ; MOVE THE ARM + LDX SLTMP3 +SEEEXI: RTS + + +; ------------------ +; ARM MOVEMENT DELAY +; ------------------ +; NOTE: THIS ROUTINE MUST BEGIN ON A PAGE BOUNDARY! +; ENTRY: 100uS DELAY INTERVAL IN [A] +; MOTOR TIME COUNT IN [MTIME] + +ARMDEL: LDX #$11 +ARMLP1: DEX + BNE ARMLP1 + INC DCNT + BNE ARMLP2 + INC DTMP2 +ARMLP2: SEC + SBC #1 + BNE ARMDEL + RTS + + +; ------------------------- +; ARM MOVEMENT DELAY TABLES +; ------------------------- + +DELTB1: DB $01,$30,$28,$24,$20,$1E,$1D,$1C + DB $1C,$1C,$1C,$1C +DELTB2: DB $70,$2C,$26,$22,$1F,$1E,$1D,$1C + DB $1C,$1C,$1C,$1C + + +; --------------------- +; WRITE TRANSLATE TABLE +; --------------------- + +WRTTBL: DB $96,$97,$9A,$9B,$9D,$9E,$9F,$A6 + DB $A7,$AB,$AC,$AD,$AE,$AF,$B2,$B3 + DB $B4,$B5,$B6,$B7,$B9,$BA,$BB,$BC + DB $BD,$BE,$BF,$CB,$CD,$CE,$CF,$D3 + DB $D6,$D7,$D9,$DA,$DB,$DC,$DD,$DE + DB $DF,$E5,$E6,$E7,$E9,$EA,$EB,$EC + DB $ED,$EE,$EF,$F2,$F3,$F4,$F5,$F6 + DB $F7,$F9,$FA,$FB,$FC,$FD,$FE,$FF + + +; -------------------- +; READ TRANSLATE TABLE +; -------------------- + +RDTBL: DB $00,$01,$98,$99,$02,$03,$9C,$04 + DB $05,$06,$A0,$A1,$A2,$A3,$A4,$A5 + DB $07,$08,$A8,$A9,$AA,$09,$0A,$0B + DB $0C,$0D,$B0,$B1,$0E,$0F,$10,$11 + DB $12,$13,$B8,$14,$15,$16,$17,$18 + DB $19,$1A,$C0,$C1,$C2,$C3,$C4,$C5 + DB $C6,$C7,$C8,$C9,$CA,$1B,$CC,$1C + DB $1D,$1E,$D0,$D1,$D2,$1F,$D4,$D5 + DB $20,$21,$D8,$22,$23,$24,$25,$26 + DB $27,$28,$E0,$E1,$E2,$E3,$E4,$29 + DB $2A,$2B,$E8,$2C,$2D,$2E,$2F,$30 + DB $31,$32,$F0,$F1,$33,$34,$35,$36 + DB $37,$38,$F8,$39,$3A,$3B,$3C,$3D + DB $3E,$3F + + +; --------------- +; MAIN RWTS ENTRY +; --------------- +; ENTRY: [A]=0 FOR READ, [A]=1 FOR WRITE +; [SLOT] = TARGET SLOT +; [DRIVE] = TARGET DRIVE +; [TRACK] = TARGET TRACK +; [SECTOR] = TARGET SECTOR +; EXIT: CARRY CLEAR IF OKAY +; COMMENTS - LINDE +; ACTUAL VARIABLES ARE: +; [DCBSLT] = SLOT +; [DCBTRK] = TRACK +; [DCBSEC] = SECTOR +; [[DCBDRV] = DRIVE +; FOR TRK, SEC, DRV 1 = 1 (DRIVE 1, SET DCBDRV TO 1) +; FOR SLT - MULTIPLY SLOT BY 16 (SLOT 6, SET DCBSLT TO $60) + +DOSENT: STA DCBCMD ; SAVE COMMAND + LDA #2 ; ALLOW 2 + STA NRECAL ; RECALS + ASL A ; AND 4 + STA NSEEK ; SEEKS + LDX DCBSLT ; GET REQUESTED SLOT ID + CPX DCBPSL ; SAME AS LAST SLOT? + BEQ DOSS1 ; YES, CONTINUE + LDX DCBPSL + + ; WAIT FOR OLD DRIVE TO TURN OFF, UPDATE SLOT ID + + LDA Q7L,X ; SET OLD SLOT TO READ MODE +DOSL1: LDY #8 ; INIT COUNTER + LDA Q6L,X +DOSL2: CMP Q6L,X + BNE DOSL1 + DEY + BNE DOSL2 + LDX DCBSLT ; GET NEW SLOT ID INTO [X] + STX DCBPSL ; MAKE IT THE "OLD" SLOT + + ; CURRENT SLOT ID IN [X] + +DOSS1: LDA Q7L,X ; GET DRIVE INTO READ MODE + LDA Q6L,X ; READ WITH DELAYS + LDY #8 ; TO SEE IF DRIVE IS SPINNING +DOSL3: LDA Q6L,X + PHA + PLA + PHA + PLA + STX SLTMP1 ; SAVE SLOT HERE + CMP Q6L,X + BNE DOSS2 + DEY + BNE DOSL3 +DOSS2: PHP ; SAVE TEST RESULT ON STACK + LDA DRVON,X ; TURN ON MOTOR + LDA #$D8 ; REFRESH + STA DTMP2 ; MOTOR TIME CONSTANT + + ; CHECK DRIVE ID + + LDA DCBDRV + CMP DCBPDR ; HAS DRIVE CHANGED? + BEQ DOSS3 ; NO, CONTINUE + STA DCBPDR ; ELSE MAKE NEW DRIVE "OLD" + PLP ; SET ZERO FLAG + LDY #0 ; OF TEST RESULT + PHP ; AND PUSH IT BACK ON STACK +DOSS3: ROR A ; CHECK DRIVE ID + BCC DOSS4 ; CARRY WILL BE CLEAR IF DRIVE = 2 + LDA DRV0EN,X ; ELSE SELECT DRIVE #1 + BCS DOSS5 ; BRANCH ALWAYS +DOSS4: LDA DRV1EN,X ; SELECT DRIVE #2 +DOSS5: ROR DRVFLG ; HIGH BIT = 1 FOR DRIVE 1, 0 FOR 2 + PLP ; CHECK TEST RESULTS + PHP + BNE DOSS6 ; BRANCH IF DRIVE WAS ON + LDY #7 ; WAIT FOR CAP DISCHARGE +DOSL4: JSR ARMDEL + DEY + BNE DOSL4 + LDX SLTMP1 ; RESTORE SLOT ID + + ; SEEK THE TARGET TRACK + +DOSS6: LDA DCBTRK ; GET TARGET TRACK + JSR MYSEEK + PLP ; WAS DRIVE ON? + BNE DOSS7 ; YES, CONTINUE + + ; WAIT FOR DRIVE TO COME UP TO SPEED + + LDY DTMP2 + BPL DOSS7 +DOSL5: LDY #$12 ; WAIT FOR DRIVE TO +DOSL6: DEY ; COME UP TO SPEED + BNE DOSL6 + INC DCNT + BNE DOSL5 + INC DTMP2 + BNE DOSL5 + + ; DECODE DISK COMMAND + +DOSS7: LDA DCBCMD ; GET COMMAND + ROR A ; CARRY = 0 IF "READ" + PHP ; SAVE READ/WRITE STATUS + + ; AND MAINTAIN STACK + + BCC GETADR ; BRANCH IF "READ" + JSR PRENIB + + ; FETCH AN ADDRESS FIELD + +GETADR: LDA #48 + STA DTMP1 ; INIT RETRY COUNT +GTA0: LDX SLTMP1 ; RESTORE SLOT ID + LDA DCBCMD + BPL DOSS8 + STA DTMP6 ; TELL RDFADD TO GET HEADER ONLY + JSR RDFSEC ; #$84 = READ FUNNY FORMAT + BCC RRGHT ; READ IT + BCS GTA1 ; OOPS +DOSS8: JSR RDADDR ; GET AN ADDRESS FIELD + BCC RRGHT ; CONTINUE IF SUCCESSFUL +GTA1: DEC DTMP1 ; ELSE UPDATE RETRY COUNT + BPL GTA0 ; AND TRY AGAIN + + ; RECALIBRATE THE ARM + +GTA2: LDA CTRACK ; SAVE THE + PHA ; CURRENT TRACK ID + LDA #$60 + JSR SETTRK + DEC NRECAL ; UPDATE RECAL COUNT + BEQ DOSERR ; ERROR IF EMPTY + LDA #4 ; RESET + STA NSEEK ; SEEK COUNT + LDA #0 ; CALIBRATE THE ARM + JSR MYSEEK ; TO TRACK #0 + PLA ; RESTORE CURRENT TRACK +GTA3: JSR MYSEEK ; GO TO IT + JMP GETADR ; AND TRY AGAIN + + ; ADDRESS FIELD FOUND + +RRGHT: LDY HDRTRK + CPY CTRACK ; ON THE RIGHT TRACK? + BEQ RTTRAK ; YES, CONTINUE + LDA CTRACK + PHA + TYA + JSR SETTRK + PLA + DEC NSEEK + BNE GTA3 + BEQ GTA2 ; ELSE RECALIBRATE + + ; HANDLE A DRIVE ERROR + +DOSERR PLA ; CLEAN UP STACK + LDA #$40 ; $40 = DRIVE ERROR + PLP ; CLEAN UP STATUS REGISTER + JMP DOSERR2 + + ; CHECK FOR PROPER SECTOR (VOLUME CHECK OMITTED) + +RTTRAK: LDA DCBCMD + BMI DOSS9 ; NO INTERLEAVE + LDY DCBSEC + LDA INTLVE,Y ; GET INTERLEAVE BYTE + CMP HDRSEC ; MATCHED FOUND SECTOR? + BNE GTA1 ; NO, TRY AGAIN + + ; SECTOR FOUND! + +DOSS9: PLP ; WILL THIS BE READ OR WRITE? + BCS DOSWRT ; DO "WRITE" IF CARRY SET + + ; READ A SECTOR + + LDA DCBCMD + BPL DOSS10 + LDY DCBSEC ; FUNNY FORMAT + STY DTMP6 + JSR RDFSEC + BCC DOSS11 + SEC + BCS DOSS11 +DOSS10: JSR RDSECT ; DO THE READ +DOSS11: BCC GTA3A ; OK + CLC ; RESET FOR NEXT TIME THRU + PHP ; PUSH FOR NEXT TIME THRU + BCC GTA1 ; JMP, ERROR OCCURRED +GTA3A: LDX #$00 + STX DTMP3 + JSR POSTNB + LDX SLTMP1 ; RESTORE SLOT ID +DOSFIN: LDA #0 ; 0 = NO ERRORS + CLC ; CARRY CLEAR FOR SUCCESS + BCC DOSEXI + + ; ERROR EXIT + +DOSERR2: SEC ; CARRY SET FOR ERROR + + ; GENERAL EXIT + +DOSEXI: STA DCBERR ; SAVE ERROR CODE HERE + LDA DRVOFF,X ; STOP THE DRIVE + RTS ; BYE! + + ; WRITE A SECTOR + +DOSWRT: JSR WRTDTA + BCC DOSFIN ; ALL'S WELL IF CARRY CLEAR + LDA #$10 ; ELSE GET ERROR CODE INTO [A] + BNE DOSERR2 ; AND DO AN ERROR EXIT + + +; --------------------- +; SET UP FOR TRACK SEEK +; --------------------- + +MYSEEK: ASL A ; TRACK*2 (PHASE OF DISK CARE) + JSR DOSEEK + LSR CTRACK ; CURRENT TRACK/2 + RTS + + +; -------------- +; EXECUTE A SEEK +; -------------- +; PAGE BOUNDARY SHOULD BEGIN HERE! + +DOSEEK: STA TTRK + JSR XTOY + LDA DR1TBL,Y + BIT DRVFLG + BMI EEK1 + LDA DR2TBL,Y +EEK1: STA CTRACK + LDA TTRK + BIT DRVFLG + BMI EEK2 + STA DR2TBL,Y + BPL EEK3 +EEK2: STA DR1TBL,Y +EEK3: JMP SEEK + + +; -------------------- +; GET SLOT ID INTO [Y] +; -------------------- + +XTOY: TXA + LSR A + LSR A + LSR A + LSR A + TAY + RTS + + +; ------------ +; SET TRACK ID +; ------------ + +SETTRK: PHA + LDA DCBDRV + ROR A + ROR DRVFLG + JSR XTOY + PLA + ASL A + BIT DRVFLG + BMI SETT1 + STA DR2TBL,Y + BPL SETT2 +SETT1: STA DR1TBL,Y +SETT2: RTS + + +; ----------- +; IDOS TABLES +; ----------- + +DR1TBL: DB 00,00,00,00 ; (8 BYTES) + DB 00,00,00,00 +CTRACK EQU DR1TBL ; CURRENT TRACK +DR2TBL: DB 00,00,00,00 ; (8 BYTES) + DB 00,00,00,00 +NSEEK: DB 00 ; SEEK COUNT +DTMP1: DB 00 ; RETRY COUNT +SLTMP1: DB 00 ; SLOT ID +SLTMP2: DB 00 +NRECAL: DB 00 ; RECALIBRATE COUNT + + ;DUPLICATE INTERLEAVE TBL FOR USE AFTER BOOT + +INTLVE: DB $00,$04,$08,$0C,$01,$05,$09,$0D + DB $02,$06,$0A,$0E,$03,$07,$0B,$0F + + +; ------------------ +; READ SECTOR FROM BIG TRACK +; ------------------ +; READ ADDRESS FIELD TO CHECK TRACK +; FIND HEADER $D5:$AA:$AD + +RDFSEC: LDA #$20 + STA HTEMP + TAY +RDFL1: LDA #$84 ; IN CASE ERROR OCCURS + DEC HTEMP + BEQ RDFBAD2 +RDFL2: DEY + BEQ RDFL2 + NOP + NOP + LDA Q6L,X + BPL RDFL2 + CMP #$D5 + BNE RDFL2 +RDF1: LDA Q6L,X + BPL RDF1 + CMP #$AA + BNE RDFL1 +RDF2: LDA Q6L,X + BPL RDF2 + CMP #$AD + BNE RDFL1 + + ; HEADER FOUND - GET TRACK ID 4+4 + + SEC +RDF3: LDA Q6L,X + BPL RDF3 + ROL A + STA TEMP +RDF4: LDA Q6L,X + BPL RDF4 + AND TEMP + STA HDRTRK + LDA DTMP6 + BMI RDFOK ; ONLY LOOKING FOR TRACK NUMBER AND ? +RDFNEXT: LDY #$56 ; SET INDEX (AND TIMING) + + ; SKIP UNUSED SECTORS + + LDA #$00 ; ZERO HIGH ALOW +RDFL3: DEY ; NEXT + STY DTMP3 ; SAVE INDEX +RDF5: LDY Q6L,X ; GET A BYTE + BPL RDF5 ; WAIT VALID + EOR RDTBL-$96,Y ; CHECK SUM AND DECODE + LDY DTMP3 ; GET INDEX + STA BUFFB,Y ; SAVE DATRA + BNE RDFL3 ; LOOP TILL DONE +RDFL4: STY DTMP3 ; SAVE INDEX +RDF6: LDY Q6L,X ; GET A BYTE + BPL RDF6 ; WAIT VALID + EOR RDTBL-$96,Y ; DECODE AND CHECK SUM + LDY DTMP3 ; GET INDEX + STA BUFFA,Y ; SAVE DATA + INY ; NEXT + BNE RDFL4 ; LOOP TIL DONE +RDF7: LDY Q6L,X ; GET A BYTE + BPL RDF7 ; WAIT VALID + DEC DTMP6 + BPL RDFNEXT + CMP RDTBL-$96,Y ; CHECK SUM VALID? + BNE RDFBAD ; NO, EXIT ERROR +RDFOK: CLC + RTS + +RDFBAD: LDA #$85 +RDFBAD2: STA DCBERR + SEC + RTS + + +; ---------------------- +; MACHINE INITIALIZATION +; ---------------------- + +INIT: LDA TXTSET ; SET TEXT MODE + LDA MIXCLR ; SET NO MIX + LDA LOWSCR ; SET PAGE 1 + LDA #>IOBUFF ; POINT [DCBBFL/H] TO [IOBUFF] + STA DCBBFM + LDA #STRYM ;DISP. "THE STORY IS LOADING..." + LDX #ZBEGIN ; MSB OF PRELOAD START ADDRESS + STA ZCODE ; FREEZE IT HERE + STA DBUFF+HI ; LSB IS ALWAYS ZERO + LDA #MAIN + STA DSKBNK ;SET TO MAIN BANK + JSR GETDSK ; [DBLOCK] SET TO Z-BLOCK 0 + + ; EXTRACT GAME DATA FROM Z-CODE HEADER + + LDA ZBEGIN+ZVERS ; (EZIP) IS GAME AN EZIP? + CMP #4 + BEQ YESEZ ; YES, CONTINUE + +; *** ERROR #15 -- NOT AN EZIP GAME *** + LDA #15 + JMP ZERROR + +; *** ERROR #0 -- INSUFFICIENT RAM *** +NORAM: LDA #5 + STA CV + JSR BASCAL + LDA #0 + JMP ZERROR + +YESEZ: LDA ZBEGIN+ZPURBT ; CHECK PURBOT POINTER + CMP #$AD ; MAXIMUM IMPURE IS $AD00 (43K) + BCC YZ1 ; OKAY, CONTINUE + + LDA #13 + JMP ZERROR ; ELSE ERROR #13 (IMPURE TOO BIG) + +YZ1: CMP #$80 ; IMPURE > 32K? + BCC YZ2 ; NO, USE 4 SAVES PER DISK + + LDA #3 ; ELSE USE ONLY 3 + BNE YZ3 + +YZ2: LDA #4 +YZ3: STA NUMSAV ; REMEMBER MAXIMUM # SAVES PER DISK + CLC + ADC #'0' ; CONVERT TO ASCII + STA SAVASC ; SAVE IN STRING + + LDX ZBEGIN+ZENDLD ; MSB OF ENDLOAD POINTER + INX ; ADD 1 TO GET + STX ZPURE ; 1ST "PURE" PAGE OF Z-CODE + LDA ZBEGIN+ZMODE ; ENABLE SPLIT-SCREEN, + ORA #%00110011 ; INVERSE, CURSOR CONTROL, + STA ZBEGIN+ZMODE ; SOUND (EZIP) + LDA #EZIPID ; SET INTERPRETER ID + STA ZBEGIN+ZINTWD + LDA #VERSID + STA ZBEGIN+ZINTWD+1 + LDA #$18 ; AND SCREEN PARAMETERS + STA ZBEGIN+ZSCRWD + LDA #80 + STA ZBEGIN+ZSCRWD+1 + 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+ZOBJEC ; NOT TO MENTION + CLC ; THE OBJECT TABLE + ADC ZCODE + STA OBJTAB+HI + LDA ZBEGIN+ZOBJEC+1 ; LSB SAME + STA OBJTAB+LO + JSR INITPAG + JSR CLS ; GET RID OF "LOADING" MSG + LDA ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + STA ZPCM ; MSB + LDA ZBEGIN+ZGO+1 ; AND LSB + STA ZPCL ; HIGH BIT ALREADY ZEROED + JSR VLDZPC ;MACKE ZPC VALID + LDX WWIDTH ; SET XSIZE TO 1 LESS + DEX + STX XSIZE + LDA PSTAT ; CHECK IF RESTART & WERE PRINTING + BPL EX2 ; NO + LDA #1 ; YES + STA PSTAT ; RESET PSTAT FOR NEXT TIME + STA SCRIPTF ; TURN SCRIPT FLAG ON + ORA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO + STA ZBEGIN+ZSCRIP+1 +EX2: JSR CLS ; CLEAR SCREEN ... + + + ; ... AND FALL INTO MAIN LOOP + + END diff --git a/apple/ezip/xpaging.asm b/apple/ezip/xpaging.asm new file mode 100644 index 0000000..b78d3a4 --- /dev/null +++ b/apple/ezip/xpaging.asm @@ -0,0 +1,466 @@ + PAGE + SBTTL "--- TIME-STAMP PAGENG ROUTINE ---" + + +; ------------------------- +; POINT [MPC] TO V-ADDR [I] +; ------------------------- + +SETWRD: LDA I+LO + STA MPCL + LDA I+HI + STA MPCM + LDA #0 + STA MPCH ; ZERO TOP BIT + JMP VLDMPC + + +; THE FIRST 98.5K (SIDE1) MUST +; BE RAM RESIDENT (394=$18A PAGES) +; 98.5K = $18A PAGES (V$0 TO V$189) +; +; PAGES V$13A TO V$189 ARE IN RAMDISK +; PAGES V$0 TO ($BF-VBEGIN) ARE IN MAIN +; PAGES ($C0-VBEGIN) TO V$139 ARE IN AUX +; PAGENG BUFFERS ARE IN AUX FROM +; V$13A-($C0-VBEGIN)+$08 TO $BF +; +DSKBNK: DB 00 +RAMSEC: DB 00 +; +WANTED: DB 00,00 +; +CURRENT: DB 00 +NEXT: DB 00 +NSUBA: DB 00 +PSUBA: DB 00 +NSUBCUR: DB 00 +; +YTEMP: DB 00 +ATEMP: DB 00 +NSUBY: DB 00 +; +; +; GET SIDE 1 LOADS ALL CODE FROM +; DISK SIDE 1 INTO ITS CORRECT +; PLACE + +; THE FIRST VPAGE MUST ALREADY BE +; RESIDENT AT [ZBEGIN] + +GETSIDE1: + LDA ZBEGIN+ZLENTH+1 ;GET LENGTH OF GAME (QUADS) + STA J+LO + LDA ZBEGIN+ZLENTH+0 + LDY #5 +SLP: + LSR A ;CONVERT QUADS TO PAGES WITH /64 + ROR J+LO + DEY + BPL SLP + STA J+HI + +; [J] HAS # PAGES IN GAME ROUNDED +; DOWN, BUT PAGE 0 IS IN ALREADY +; SO WE NEED ONLY LOAD [J] MORE +; PAGES OR FILL MEM WITH SIDE 1 +; IF THE GAME IS LARGER THAN SIDE 1 + +; FILL MAIN AND AUX (NOT RAMDSK) +; # GETDSK ASSUMED TO BE POINTING +; # AT V-PAGE 1 AND RAM PAGE ZBEGIN+1 +; # ALSO, GETDSK SHOULD ROLL INTO +; # AUX RAM WHEN INCMNTING DBUFF + +FLP: JSR DECJ ;C=0 IF [J] GOES HIGH 0 + BCC FIN + JSR GETDSK + LDA DSKBNK ;IS IT FILLING AUX ? + CMP #AUX + BNE FLP ;NO + LDA DBUFF+HI + CMP #PBEGIN ;FILLED TO PAGING BUFFERS YET? + BNE FLP ;NO, NOT YET + + ; NOW PUT STUFF IN RAMDSK + + LDA #MAIN + STA DSKBNK ;POINT BACK TO MAIN MEM + LDA #0 + STA RAMSEC ;POINT TO FIRST SECTOR +LP2: + LDA #>IOBUFF + STA DBUFF+HI ;MAKE GETDSK LEAVE CODE AT [IOBUFF] + JSR DECJ + BCC FIN + JSR GETDSK + LDY #>IOBUFF ;SET UP RAMDSK PARMS + LDA RAMSEC + LDX #WRITE + STA RDBNK+MAIN ;SO WE REALLY JSR RAMDSK + JSR RAMDSK ;CALL RAMDSK + INC RAMSEC + LDA RAMSEC + CMP #RMDSIZE + BCC LP2 + JSR CLS ; CLEAR THE SCREEN FOR NEATNESS + LDA #2 + STA CV + JMP SIDE2 ;CODE EXISTS ON SIDE2 AND WE HAVE SIDE 1 +FIN: + RTS + +;DECJ RETURNS C=0 WHEN J=$FFFF + +DECJ: LDA J+LO + SEC + SBC #1 + STA J+LO + LDA J+HI + SBC #0 + STA J+HI + RTS + + +; MAKE [MPCPNT],[MPCBNK] POINT TO +; THE RAM PAGE AND BANK THAT HOLDS +; THE V-PAGE MPCH,M +; +VLDMPC: + LDA MPCH + BNE VLD1 ;NOT IN FIRST V-64K + LDA MPCM + CMP #VAUX ;IS IT A PAGE IN MAIN + BCS VLD2 ;NO, IT IS IN AUX + ADC #>ZBEGIN ;ADD OFFSET TO GET RAM PAGE + LDY #MAIN + BEQ VLDEXI ;BRA +VLD2: SBC #VAUX-AUXSTART ;FIX TO OFFST INTO AUX RAM + LDY #AUX + BNE VLDEXI +VLD1: CMP #1 ;BETWEEN 64K AND 128K ? + BNE VLD3 ;NO, ABOVE 128K + + LDA MPCM + CMP #ZBEGIN ;ADD OFFSET TO GET RAM PAGE + LDY #MAIN + BEQ VLDZEXI ;BRA +VLDZ2: SBC #VAUX-AUXSTART ;FIX TO OFFST INTO AUX RAM + LDY #AUX + BNE VLDZEXI +VLDZ1: CMP #1 ;BETWEEN 64K AND 128K ? + BNE VLDZ3 ;NO, ABOVE 128K + LDA ZPCM + CMP #PSIDE1 ;CHECK IF IN RAMDSK + BCC GETYES + BNE GETNO + CPY #PSIDE1 ;IS THE BLOCK ON SIDE 1 OR 2 + BCC GETSD1 + BNE GETSD2 + CPY #PSIDE1 + TAX + TYA + SEC +SDL1: SBC #18 ; DIVIDE BY SECTORS PER TRACK + BCS S1 + DEX ; BORROW + BMI S2 ; ALL GONE + SEC +S1: INC DCBTRK ; INCREMENT TRACK + BCS SDL1 ; CONTINUE +S2: CLC + ADC #18 ; ADD BACK INTO GET SECTOR # + STA DCBSEC + LDA DCBTRK ; CHECK TRACK SIZE + CMP #ZTRKL ; ANYTHING ABOVE TRK 34 + BCC OKA + JMP TRKERR +OKA: + LDA #FREAD ; READ SIDE 2 INDICATOR + BNE GETSDGO ; GO VALIDATE TRACK + + ; CONVERT FOR SIDE 1 + +GETSD1: LDA SIDEFLG ; ARE WE ON SIDE 1 + CMP #1 + BEQ OK3 + JSR SIDE1 + LDX DBLOCK+HI + LDY DBLOCK+LO +OK3: TYA ; GET LSB OF BLOCK ID + AND #%00001111 ; MASK OFF TOP NIBBLE + STA DCBSEC ; TO FORM DCBSEC ID (0-15) + TXA ; GET MSB OF BLOCK ID + ASL A ; SHIFT BOTTOM NIB INTO TOP NIB + ASL A + ASL A + ASL A + STA DCBTRK ; SAVE HERE FOR A MOMENT + TYA ; GET LSB + LSR A ; MOVE TOP TO BOTTOM + LSR A + LSR A + LSR A + ORA DCBTRK ; SUPERIMPOSE TOP OF MSB + CLC ; PRE-LOAD Z-BLOCKS START ON + ADC #ZTRKF ; TRACK 3 (EZIP) + CMP #ZTRKL ; ANYTHING ABOVE TRACK 34 + BCS TRKERR + STA DCBTRK ; THIS IS THE TRACK ID +SDL2: LDA #READ +GETSDGO: + STA RDBNK+MAIN ;SET TO READ FROM MAIN BANK + + ;WHERE BUFFA AND BUFFB ARE + + JSR DOS + BCS DISKERR ;BAD READ + + ; SOMEDAY DOS SHOULD TAKE CARE OF + ; READING/WRITING FROM EITHER BANK + ; IN THE 48K + ; JUST MAKE SHURE THERE ARE NO BUFFA + ; BUFFB CONFLICTS + ; DOS EVENTUALLY + + LDY DSKBNK + STA WRTBNK,Y ;SET TO WRITE TO DSKBNK + LDY #0 ; MOVE DATA +SDLP3: LDA IOBUFF,Y ; IN [IOBUFF] + STA (DBUFF),Y ; TO [DBUFF] + INY + BNE SDLP3 + + ; RESET TO WRITE TO MAIN BANK + + STA WRTBNK+MAIN + + INC DBLOCK+LO ; POINT TO NEXT + BNE S5 ; VIRTUAL BLOCK + INC DBLOCK+HI +S5: INC DBUFF+HI + LDA DBUFF+HI + CMP #MAINEND+1 ;PAST LAST MAIN RAM PAGE ? + BCC S6 ;NO + LDA #AUXSTART ;RESET DBUFF TO FIRST AUX PAGE + STA DBUFF+HI + LDA #AUX ;SET DSKBNK TO AUX + STA DSKBNK +S6: RTS + + ; DISKERR SHOULD FIRST ASK IF + ; SIDE [SIDEFLG] IS IN, THEN + ; IT SHOULD RETRY AND IF + ; IT FAILS AGAIN, THEN IT SHOULD + ; ERROR 14 OUT + ; BUT FOR RIGHT NOW STUPIDITY + ; SHALL REMAIN A FATAL FLAW + +DISKERR: LDA #14 + JMP ZERROR ; DRIVE ACCESS ERROR + + ; POINT TO NEXT SECTOR + +NXTSEC: INC DCBSEC ; UPDATE SECTOR + LDA DCBSEC ; CHECK IT + AND #%00001111 ; DID IT OVERFLOW? + BNE SECTOK ; NO, ALL'S WELL + LDX DCBTRK ; ELSE UPDATE + INX ; TRACK ID + CPX #ZTRKL ; IF LOW 35, + BCS WRTERR ; SCRAM W/CARRY SET + STX DCBTRK ; ELSE SAVE NEW TRACK +SECTOK: STA DCBSEC ; AND SECTOR + INC DBUFF+HI ; POINT TO NEXT RAM PAGE + CLC ; CLEAR CARRY FOR SUCCESS (WRITE ONLY) + RTS + + +; ---------------------- +; WRITE [DBLOCK] TO DISK +; ---------------------- +; ENTRY: TRACK,SECTOR,DRIVE,SLOT ALL SET ALREADY +; PAGE TO WRITE IN (DBUFF) +; EXIT: CARRY CLEAR IF OKAY, SET IF FAILED + +PUTDSK: LDY #0 ; MOVE DATA AT [DBUFF] + STA RDBNK+MAIN ;SELECT MAIN BANK +PDSK0: LDA (DBUFF),Y ; TO [IOBUFF] + STA IOBUFF,Y ; FOR WRITING + INY + BNE PDSK0 + LDA #WRITE + JSR DOS ; DO IT! + BCC NXTSEC ; OKAY IF CARRY CLEAR +WRTERR: RTS ; ELSE EXIT WITH CARRY SET + + ; *** ERROR #12: DISK ADDRESS RANGE *** + +TRKERR: LDA #12 + JMP ZERROR + + ; *** ERROR #14: DRIVE ACCESS *** + +DSKER: LDA #14 + JMP ZERROR + + +; --------------------- +; READ DBLOCK FROM DISK +; --------------------- +; CALLED BY RESTORE +; ENTER: (W/[DCBSEC/TRK] PRESET) + +GETRES: LDA #READ + JSR DOS + BCS DSKER ; FATAL ERROR IF CARRY SET + LDY #0 ; MOVE DATA + STA RDBNK+MAIN +RES1: LDA IOBUFF,Y ; IN [IOBUFF] + STA (DBUFF),Y ; TO [DBUFF] + INY + BNE RES1 + INC DBLOCK+LO ; POINT TO NEXT + BNE RES2 ; VIRTUAL BLOCK + INC DBLOCK+HI + + ; POINT TO NEXT SECTOR + +RES2: INC DCBSEC ; UPDATE SECTOR + LDA DCBSEC ; CHECK IT + AND #%00001111 ; DID IT OVERFLOW? + BNE RES3 ; NO, ALL'S WELL + LDX DCBTRK ; ELSE UPDATE + INX ; TRACK ID + CPX #ZTRKL ; IF LOW 35, + BCS WRTERR ; SCRAM W/CARRY SET + STX DCBTRK ; ELSE SAVE NEW TRACK +RES3: STA DCBSEC ; AND SECTOR + INC DBUFF+HI ; POINT TO NEXT RAM PAGE + CLC ; CLEAR CARRY FOR SUCCESS (WRITE ONLY) + RTS + + +; ----------------------------- +; SET UP SAVE & RESTORE SCREENS +; ----------------------------- + +SAVRES: JSR ZCRLF ; CLEAR THE LINE BUFFER + LDA #0 + STA SCRIPT ; DISABLE SCRIPTING + RTS + +; JMP HOME ; CLEAR THE SCREEN (LEAVE STATUS AS IS - EZIP) + + +; ----------------- +; DISPLAY A DEFAULT +; ----------------- +; ENTRY: DEFAULT (1-8) IN [A] + +DEFAL: DB " (Default is " +DEFNUM: DB "*) >" +DEFALL EQU $-DEFAL + +DODEF: CLC + ADC #'1' ; CONVERT TO DB II 0-7 + STA DEFNUM ; INSERT IN STRING + LDX #DEFAL + LDY #DEFALL + JMP DLINE ; PRINT THE STRING + + +; ----------------------------- +; GET SAVE & RESTORE PARAMETERS +; ----------------------------- + +NUMSAV DB 0 ; HOLDS # SAVES AVAILABLE + +POSIT: DB EOL + DB "Position 1-" +SAVASC: DB "*" +POSITL: EQU $-POSIT +WDRIV: DB EOL + DB "Drive 1 or 2" +WDRIVL EQU $-WDRIV +SLOT: DB EOL + DB "Slot 1-7" +SLOTL EQU $-SLOT +GSLOT: DB 5 ;START W/ DEFAULT SLOT 6 (YES 5 IS 6) +MIND: DB EOL + DB EOL + DB "Position " +MPOS: DB "*; Drive #" +MDRI: DB "*; Slot " +MSLT: DB "*." + DB EOL + DB "Are you sure? (Y/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 #POSIT + LDY #POSITL + JSR DLINE ; "POSITION (1-X)" + + ; 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 DB II TO BINARY + CMP NUMSAV ; IF BELOW [NUMSAV] + BCC SETPOS ; MAKE IT THE NEW DEFAULT + JSR BEEP ; ELSE RAZZ + JMP GETPOS ; AND TRY AGAIN +POSSET: LDA GPOSIT ; USE DEFAULT +SETPOS: STA TPOSIT ; USE KEYPRESS + CLC + ADC #'1' ; CONVERT TO DB II "1"-"5" + STA MPOS ; STORE IN TEMP STRING + STA SVPOS + STA RSPOS + ORA #%10000000 + JSR CHAR ; AND DISPLAY IT + + ; GET DRIVE ID + + LDX #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 BEEP + JMP GETDRV ; ELSE TRY AGAIN +DRVSET: LDA GDRIVE ; USE DEFAULT +SETDRV: STA TDRIVE ; USE [A] + CLC + ADC #'1' ; CONVERT TO DB II 1 OR 2 + STA SAVDRI ; STORE IN DRIVE STRING + STA MDRI ; AND IN TEMP STRING + ORA #%10000000 + JSR CHAR ; AND SHOW NEW SETTING + + ;IF IIC SLOT IS 6 OTHERWISE ASK + + LDA SIG ; CHECK IF IIc + BNE PREIIC ; IS NOT A IIC SO ASK WHICH SLOT + LDA #5 ; SLOT 6 + BNE SETSLT ; JMP +PREIIC: LDX #SLOT + LDY #SLOTL + JSR DLINE ; "SLOT 1-7" + + ; GET DRIVE SLOT + + LDA GSLOT ; SHOW THE CURRENT + JSR DODEF ; DEFAULT SLOT +GETSLT: JSR GETKEY ; WAIT FOR A KEY + CMP #EOL ; IF [RETURN], + BEQ SLTSET ; USE DEFAULT + SEC + SBC #'1' ; ELSE CONVERT DB II TO BINARY + CMP #7 ; IF "7" OR BELOW + BCC SETSLT ; MAKE IT THE NEW DEFAULT +BADSLT: JSR BEEP ; ELSE RAZZ + JMP GETSLT ; AND TRY AGAIN +SLTSET: LDA GSLOT ; USE DEFAULT +SETSLT: STA TSLOT ; USE KEYPRESS + CLC + ADC #'1' ; CONVERT TO DB II "1"-"7" + STA MSLT ; STORE IN TEMP STRING + LDX SIG ; AND IF NOT IIC + BEQ DBLCHK + ORA #%10000000 + JSR CHAR ; DISPLAY IT + +DBLCHK: LDX #MIND + LDY #MINDL + JSR DLINE + + ; VALIDATE RESPONSES + +GETYN: 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 BEEP ; ELSE BEEP + JMP GETYN ; INSIST ON Y OR N + +NOTSAT: LDX #NO + LDY #NOL + JSR DLINE ; PRINT "NO"/EOL + JMP PARAMS ; AND TRY AGAIN + +ALLSET: LDX #YES + LDY #YESL + JSR DLINE ; PRINT "YES"/EOL + LDA TDRIVE ; MAKE THE TEMPORARY DRIVE + STA DCBDRV ; AND SET [DRIVE] ACCORDINGLY + INC DCBDRV ; 1-ALIGN THE DRIVE ID + LDX TSLOT ; MAKE TEMP DRIVE SLOT + INX ; 1-ALIGN + TXA + ASL A ; * 16 FOR # RWTS NEEDS + ASL A + ASL A + ASL A + STA DCBSLT ; AND SET SLOT ACCORDINGLY + +; CALC STARTING SECTOR & TRACK (BM 1/20/86) + + LDA TPOSIT ; GET THE SAVE POSITION + LDX NUMSAV ; AND # SAVES AVAILABLE + CPX #3 ; IF 3 SAVES, + BEQ GOOX ; NO OFFSET NECESSARY + + CLC ; ELSE JUMP INDEX + ADC #3 ; OVER 1ST 3 ENTRIES + +GOOX: TAX ; USE MUNGED [TPOSIT] AS AN INDEX + LDA TRAX,X ; INTO TABLES + STA DCBTRK ; FOR 1ST TRACK + LDA SEX,X ; AND SECTOR + STA DCBSEC + + LDX #INSM + LDY #INSML + JSR DLINE ; "INSERT SAVE DISK IN DRIVE X." + +; --------------------- +; "PRESS RETURN" PROMPT +; --------------------- + +RETURN: LDX #RTN + LDY #RTNL + JSR DLINE ; SHOW PROMPT + + ; ENTRY FOR QUIT/RESTART + +GETRET: JSR GETKEY ; WAIT FOR [RETURN] + CMP #EOL + BEQ GRRTS + JSR BEEP ; ACCEPT NO + JMP GETRET ; SUBSTITUTES! +GRRTS: RTS + +RTN: DB EOL + DB "Press [RETURN] to continue." + DB EOL + DB EOL + DB EOL +RTNL EQU $-RTN + +TRAX: DB 0,11,23 ; 1ST TRACK FOR 3-SAVE DISKS + DB 0,8,17,25 ; 1ST TRACK FOR 4-SAVE DISKS +SEX: DB 0,8,0 ; 1ST SECTOR FOR 3-SAVE DISKS + DB 0,8,0,8 ; 1ST SECTOR FOR 4-SAVE DISKS + +; -------------------- +; PROMPT FOR GAME DISK +; -------------------- +; EZIP USES BOTH SIDES OF DISK + +GAME: DB EOL + DB "Insert Side " +DSIDE: DB "* of the STORY disk into Drive #1." + DB EOL + DB EOL + DB EOL +GAMEL EQU $-GAME + +SIDE1: LDA #'1' ; ASK FOR SIDE 1 + STA DSIDE + LDA #1 ;SET FOR SUCCESS + STA SIDEFLG +SL1: LDX #GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + LDA #0 ; GO READ TRK 0, SEC 0, & SEE + STA DCBSEC ; IF THEY DID SWAP + STA DCBTRK + LDA #1 ; MAKE SURE WE'RE ON + STA DCBDRV ; THE BOOT DRIVE + LDA #READ + JSR DOS + BCS SL1 ; DISK READ ERROR, WRONG FORMAT, SO: WRONG SIDE + BCC ASK2 ; JUMP, GOOD +SIDE2: LDA #'2' ; ASK FOR SIDE 2 + STA DSIDE + LDA #2 + STA SIDEFLG ;SET FOR SUCCESS + LDA DCBDRV ; GET LAST DRIVE USED + PHA ; HOLD IT A SEC + LDA #1 ; MAKE SURE WE'RE ON + STA DCBDRV ; THE BOOT DRIVE + PLA ; IF SAVED/RESTORED + CMP #2 ; TO DRIVE 2, DON'T ASK + BEQ ASK2 ; NOTE: THIS IS OK W/ VERIFY CAUSE + + ; ASKS FOR SIDE 1 FIRST, RESETTING + ; DRIVE TO 1 + +SL2: LDX #GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + LDA #0 ; GO READ TRK 0, SEC 0, & SEE + STA DCBSEC ; IF THEY DID SWAP + STA DCBTRK + LDA #FREAD + JSR DOS + BCS SL2 ; DISK READ ERROR, WRONG FORMAT, SO: WRONG SIDE +ASK2: LDA #$FF ; RE-ENABLE + STA SCRIPT ; SCRIPTING + RTS + +; --------- +; SAVE GAME +; --------- + +SAV: DB "Save Position" + DB EOL +SAVL EQU $-SAV +SVING: DB EOL + DB EOL + DB "Saving position " +SVPOS: DB "* ..." + DB EOL + DB EOL + DB EOL +SVINGL EQU $-SVING + +ZSAVE: JSR SAVRES ; SET UP SCREEN + LDX #SAV + LDY #SAVL + JSR DLINE ; "SAVE POSITION" + JSR PARAMS ; GET PARAMETERS + LDX #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+LO ; MOVE [ZSP] + STA BUFSAV+2 + LDA ZSP+HI + STA BUFSAV+3 + LDA OLDZSP+LO + STA BUFSAV+4 + LDA OLDZSP+HI ; MOVE [OLDZSP] + STA BUFSAV+5 + LDX #2 ; MOVE CONTENTS OF [ZPC] +ZSL1: LDA ZPC,X ; TO BYTES 7-9 + STA BUFSAV+6,X ; OF [BUFSAV] + DEX + BPL ZSL1 + + ; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK + + LDA #>LOCALS + STA DBUFF+HI ; POINT TO THE PAGE + JSR PUTDSK ; AND WRITE IT OUT + BCC ZSOK ; IF SUCCEEDED, WRITE STACK + +ZSBAD: JSR SIDE2 ; ELSE REQUEST STORY DISK +; JSR CLS + LDA #22 ; SET CURSOR AT BOTTOM OF SCREEN + STA CV + JSR BASCAL + JMP RET0 ; AND FAIL + + ; WRITE CONTENTS OF Z-STACK TO DISK + +ZSOK: LDA #>ZSTKBL ; POINT TO 1ST PAGE + STA DBUFF+HI + LDA #4 ; DO ALL 4 PAGES + STA L ; SET COUNTER +ZSOKLP: JSR PUTDSK ; WRITE THEM + BCS ZSBAD + DEC L + BNE ZSOKLP + + ; 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 +ZSL2: JSR PUTDSK + BCS ZSBAD + DEC I+LO + BNE ZSL2 + JSR SIDE2 ; PROMPT FOR GAME DISK +; JSR CLS + LDA #22 + STA CV + JSR BASCAL + LDA TDRIVE ; IF SAVE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TSLOT ; NEXT TIME + STA GSLOT + LDA TPOSIT + STA GPOSIT + LDA #1 ; SET TO MARK + LDX #0 + JMP PUTBYT ; SUCCESS + + +; ------------ +; RESTORE GAME +; ------------ + +RES: DB "Restore Position" + DB EOL +RESL EQU $-RES +RSING: DB EOL + DB EOL + DB "Restoring position " +RSPOS: DB "* ..." + DB EOL + DB EOL + DB EOL +RSINGL EQU $-RSING + +ZREST: JSR SAVRES + LDX #RES + LDY #RESL + JSR DLINE ; "RESTORE POSITION" + JSR PARAMS ; GET PARAMETERS + LDX #RSING + LDY #RSINGL + JSR DLINE ; "RESTORING POSITION X ..." + + ; SAVE LOCALS IN CASE OF ERROR + + LDX #31 +ZRL1: LDA LOCALS,X ; COPY ALL LOCALS + STA $0100,X ; TO BOTTOM OF MACHINE STACK + DEX + BPL ZRL1 + LDA #>LOCALS + STA DBUFF+HI + JSR GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + BCS ZRBAD ; BAD DISK READ IF CARRY CLEAR + LDA BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID + CMP ZBEGIN+ZID ; MATCH THE CURRENT ID? + BNE ZRBAD ; WRONG DISK IF NOT + LDA BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE? + CMP ZBEGIN+ZID+1 + BEQ ZROK ; CONTINUE IF BOTH BYTES MATCH + + ; HANDLE RESTORE ERROR + +ZRBAD: LDX #31 ; RESTORE ALL SAVED LOCALS +ZRL2: LDA $0100,X + STA LOCALS,X + DEX + BPL ZRL2 + JSR SIDE2 ; PROMPT FOR GAME DISK +; JSR CLS + LDA #22 ; SET CURSOR AT BOTTOM OF SCREEN + STA CV + JSR BASCAL + JMP RET0 ; PREDICATE FAILS + + ; CONTINUE RESTORE + +ZROK: LDA ZBEGIN+ZSCRIP ; SAVE BOTH FLAG BYTES + STA I+LO + LDA ZBEGIN+ZSCRIP+1 + STA I+HI + LDA #>ZSTKBL ; RETRIEVE OLD CONTENTS OF + STA DBUFF+HI ; Z-STACK + LDA #4 ; DO 4 PAGES + STA L ; SET COUNTER +ZROKLP: JSR GETRES ; GET 4 PAGES OF Z-STACK + BCS ZRBAD + DEC L + BNE ZROKLP + + LDA ZCODE + STA DBUFF+HI + JSR GETRES ; GET 1ST BLOCK OF PRELOAD + BCS ZRBAD + 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 +ZRL3: JSR GETRES ; FETCH THE REMAINDER + BCS ZRBAD + DEC I+LO ; OF THE PRELOAD + BNE ZRL3 + + ; RESTORE THE STATE OF THE SAVED GAME + + LDA BUFSAV+2 ; RESTORE THE [ZSP] + STA ZSP+LO + LDA BUFSAV+3 + STA ZSP+HI + LDA BUFSAV+4 + STA OLDZSP+LO + LDA BUFSAV+5 ; AND THE [OLDZSP] + STA OLDZSP+HI + LDX #2 ; RESTORE THE [ZPC] +ZRL4: LDA BUFSAV+6,X + STA ZPC,X + DEX + BPL ZRL4 + JSR VLDZPC ;MAKE VALID + JSR SIDE2 ; PROMPT FOR GAME DISK +; JSR CLS + + LDA #22 + STA CV + JSR BASCAL + + LDA TDRIVE ; IF RESTORE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TSLOT ; NEXT TIME + STA GSLOT + LDA TPOSIT + STA GPOSIT + LDA #2 ; SET TO + LDX #0 + JMP PUTBYT ; SUCCESS + + END diff --git a/apple/ezip/zstring.asm b/apple/ezip/zstring.asm new file mode 100644 index 0000000..c911aad --- /dev/null +++ b/apple/ezip/zstring.asm @@ -0,0 +1,435 @@ + 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 + ROL A + STA MPCH + ASL MPCL ; QUAD-ALIGN ADDRESS!(EZIP) + ROL MPCM + ROL MPCH + JMP VLDMPC +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 ; DB II "a" MINUS Z-OFFSET +TODB: 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 ; DB II "A" MINUS Z-OFFSET + BNE TODB ; 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" DB II + TAX ; OTHERWISE USE CODE AS AN INDEX + LDA CHRTBL,X ; INTO THE CHARSET TABLE + JMP SHOVE ; AND PRINT THE CHAR + + ; DECODE A "DIRECT" DB II 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 ; DB II 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 SETFWD ; 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 + JSR VLDMPC + JMP PZTOP ; CONTINUE INNOCENTLY + + +; ---------------------- +; RETURN CURRENT CHARSET +; ---------------------- + +GETSET: LDA TSET + BPL GS + LDA PSET + RTS +GS: LDY #$FF + STY TSET + RTS + + +; ------------------------- +; POINT [I] AT FWORD STRING +; ------------------------- + +SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS + ASL A + STA MPCL + LDA I+HI + ROL A + STA MPCM + LDA #0 + ROL A + STA MPCH + JMP VLDMPC + + +; ----------------- +; 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 + LDX #$08 ; WITH PAD CHARS ($05) +CZSL: STA OUT,X + DEX + BPL CZSL + LDA #9 ; 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 DB II 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 9 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" DB II CHAR + + LDA #6 ; DB II 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 + STA OUT+2 ; MOVE CRUSHED Z-WORD + STX OUT+3 ; INTO PLACE + LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) + ASL A ; SHIFT BITS + ASL A + ASL A + ASL A + ROL OUT+6 ; ALONG WITH 7TH Z-CHAR + ASL A + ROL OUT+6 + ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR + STA OUT+5 ; SAVE HERE + LDA OUT+6 ; GRAB 7TH Z-CHAR + ORA #%10000000 ; SET HIGH BIT + STA OUT+4 ; MOVE CRUSHED Z-WORD 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 + diff --git a/apple/interp/infocom b/apple/interp/infocom new file mode 100644 index 0000000..ee09812 Binary files /dev/null and b/apple/interp/infocom differ diff --git a/apple/interp/journey.sys b/apple/interp/journey.sys new file mode 100644 index 0000000..4f5cc61 Binary files /dev/null and b/apple/interp/journey.sys differ diff --git a/apple/interp/shogun.bin b/apple/interp/shogun.bin new file mode 100644 index 0000000..33ec7bd Binary files /dev/null and b/apple/interp/shogun.bin differ diff --git a/apple/interp/shogun.sys b/apple/interp/shogun.sys new file mode 100644 index 0000000..33ec7bd Binary files /dev/null and b/apple/interp/shogun.sys differ diff --git a/apple/interp/yzip.bin b/apple/interp/yzip.bin new file mode 100644 index 0000000..0ad2c3b Binary files /dev/null and b/apple/interp/yzip.bin differ diff --git a/apple/interp/zork0.sys b/apple/interp/zork0.sys new file mode 100644 index 0000000..a1576a9 Binary files /dev/null and b/apple/interp/zork0.sys differ diff --git a/apple/oldzip/0ops.z b/apple/oldzip/0ops.z new file mode 100644 index 0000000..d226690 --- /dev/null +++ b/apple/oldzip/0ops.z @@ -0,0 +1,118 @@ +O^u L' .TITLE "ZORK - 0 OPS" + .PAGE + + RTRUE LDA #1 ;SIMULATE RETURN 1 + RTRUE1 STA ARG1 + LDA #0 + STA ARG1+1 + JMP RETURN + + RFALSE LDA #0 ;SIMULATE RETURN OF 0 + JMP RTRUE1 + + PRINTI MOVE ZPCL,MPCL ;SETUP MPC TO EQUAL ZPC + MOVEW ZPCH,MPCH + MOVE #0,MPCFLG + JSR PZSTR ;PRINT THE STRING + MOVE MPCL,ZPCL ;NOW CHANGE BACK ZPC TO END OF STRING + MOVEW MPCH,ZPCH + MOVE MPCFLG,ZPCFLG + MOVEW MPCPNT,ZPCPNT + ZNOP: RTS + + PRINTR JSR PRINTI + LDA #0D + JSR COUT + LDA #0A + JSR COUT + JMP RTRUE + + RSTACK JSR POPSTK + MOVEW TEMP,ARG1 + JMP RETURN + + CRLF LDA #0D + JSR COUT + LDA #0A + JMP COUT + + ;VERIFY INTEGRITY OF Z-PROGRAM + + INTMS .ASCII "INTERPRETER VERSION : " + .ASCII "B" + .BYTE 0D ;RETURN + .BYTE 255. + + VERIFY: MOVEI #INTMS,TEMP + LDY #0 + QP LDA (TEMP),Y + CMP #255. + BEQ QPO + EOR #80 + JSR 0FDED + INY + JMP QP + + QPO LDY #ZLENTH+ ;GET PROGRAM LENGTH (IN WORDS) + LDA @ZCODEP,Y + STA ARG2+LO + NEXT + LDA @ZCODEP,Y + STA ARG2+HI + LDA #0 + STA ARG3 ;INITIALIZE OTHER VARIABLES + STA ARG1+LO + STA ARG1+HI + STA TEMP+HI + STA ARG4 + LDA #ARG4 ;CHANGE GETBYT ZMEMT COMPAR. TO FORCE PAGE LOADS + STA GTBCMP + ASL ARG2+LO ;CONVERT LENGTH TO BYTES + ROL ARG2+HI + ROL ARG3 ;17TH BIT OF LENGTH + LDA #40 ;FIRST 64 BYTES AREN'T CHECKSUMMED + STA TEMP+LO + JSR SETWRD ;POINT TO FIRST BYTE TO USE + .IF SMALLD ;SMALL DISK? + LDA TWODFL ;IF SO, CHECK TWO-DISK FLAG + BEQ $3 ;NOT USING TWO DISKS + JSR DISK1 ;YES, SWITCH TO DISK #1 + $1 JSR GETBYT ;ADD BYTES TO CHECKSUM + CLC + ADC ARG1+LO + STA ARG1+LO + BCC $2 + INC ARG1+HI + $2 LDA MPCH+LO ;CHECK FOR END OF PRELOAD + CMP ZMEMT + BNE $1 ;NO + JSR DISK2 ;NOW SWITCH TO DISK #2 FOR THE REST + .ENDC + $3 JSR GETBYT ;ADD BYTES TO CHECKSUM + CLC + ADC ARG1+LO + STA ARG1+LO + BCC $4 + INC ARG1+HI + $4 LDA MPCL ;CHECK FOR END OF PROGRAM + CMP ARG2+LO + BNE $3 ;NO + LDA MPCH+LO + CMP ARG2+HI + BNE $3 ;NO + LDA MPCH+HI + CMP ARG3 + BNE $3 ;NO + LDA #ZMEMT ;YES, UNPATCH GETBYT ZMEMT COMPARISON + STA GTBCMP + LDY #ZCHKSM+ ;COMPARE CHECKSUMS + LDA @ZCODEP,Y + CMP ARG1+LO + BNE $5 ;DIFFERENT + NEXT + LDA @ZCODEP,Y + CMP ARG1+HI + BNE $5 ;DIFFERENT + JMP PREDS ;THE SAME, SUCCESS + $5 JMP PREDF ;FAILURE + \ No newline at end of file diff --git a/apple/oldzip/1ops.z b/apple/oldzip/1ops.z new file mode 100644 index 0000000..40444bf --- /dev/null +++ b/apple/oldzip/1ops.z @@ -0,0 +1,178 @@ +O^u " .TITLE "ZORK - 1 OPS" + .PAGE + + ZEROP LDA ARG1+HI + ORA ARG1+LO + BEQ PREDSL + JMP PREDF + PREDSL JMP PREDS + + NEXTP LDA ARG1+LO + JSR OBJLOC + LDY #5 + JMP FIRST1 ;SAME AS FIRST? + + FIRSTP LDA ARG1+LO + JSR OBJLOC + LDY #6 + FIRST1 LDA @TEMP,Y + PHA + STA TEMP+LO + LDA #0 + STA TEMP+HI + JSR PUTVLC ;STORE VALUE + PLA + ORA #0 + BNE PREDSL ;FOUND FIRST + JMP PREDF ;FIRST NOT FOUND + + LOC LDA ARG1+LO + JSR OBJLOC + LDY #4 + LDA @TEMP,Y + STA TEMP+LO + LDA #0 + STA TEMP+HI + JMP PUTVAL + + PTSIZE CLC + LDA ARG1+LO + ADC ZCODEP+LO + STA TEMP+LO + LDA ARG1+HI + ADC ZCODEP+HI + STA TEMP+HI + SUBB TEMP,#1 + LDY #0 + JSR PROPL + CLC + ADC #1 + JMP PUTBYT + + INC1 LDA ARG1+LO + JSR VARGET + INCW TEMP + INC2 PUSHW TEMP + LDA ARG1+LO + JSR VARPUT + PULLW TEMP + RTS + + DEC1 LDA ARG1+LO + JSR VARGET + SUBB TEMP,#1 + JMP INC2 + + PRINTB MOVEW ARG1,TEMP + PRINT2 JSR SETWRD + JMP PRINT1 + + REMOVC LDA ARG1+LO + JSR OBJLOC + LDY #4 + LDA @TEMP,Y + BNE $1 + RTS ;NO OBJECT + $1 TAX + PUSHW TEMP ;SAVE VALUE + TXA + JSR OBJLOC ;PARENT OBJECT, LP + LDY #6 + LDA @TEMP,Y ;SIBL + CMP ARG1+LO + BNE REMVC1 ;NOT SAME + PULLW VAL + PUSHW VAL ;L1 + LDY #5 + LDA @VAL,Y + LDY #6 ;PARENT'S FIRST SLOT GETS LOC SLOT + STA @TEMP,Y + JMP REMVC2 + + REMVC1 JSR OBJLOC ;GET SIBL + LDY #5 + LDA @TEMP,Y ;NEW SIBL + CMP ARG1+LO + BNE REMVC1 ;NOT END OF CHAIN + PULLW VAL + PUSHW VAL + LDA @VAL,Y ;OLD NEXT + STA @TEMP,Y + REMVC2 PULLW TEMP + LDY #4 + LDA #0 + STA @TEMP,Y + INY + STA @TEMP,Y + RTS + + PRINTD LDA ARG1+LO + PRNTDC JSR OBJLOC + LDY #7 + LDA @TEMP,Y + STA VAL+ + INY + LDA @TEMP,Y + STA VAL+ + MOVEW VAL,TEMP + INCW TEMP + JSR SETWRD + JMP PZSTR + + + RETURN MOVEW OZSTKP,ZSTAKP ;RESET STACK FROM CALL + MOVE OZSTKC,ZSTAKC + JSR POPSTK ;RESET Z-STACK + LDA TEMP ;HAS NUMBER OF LOCALS + BEQ RET2 ;NO LOCALS + MOVEI #LOCALS-2,VAL + LDA TEMP + STA MASK + ASL A + CLC + ADC VAL+LO ;POSITION VAL TO RESTORE LOCALS + STA VAL+LO + BCC RET1 + INC VAL+HI + RET1 JSR POPSTK ;GET THE LOCAL, REVERSE ORDER FIRST + LDY # + LDA TEMP+LO + STA @VAL,Y + NEXT + LDA TEMP+HI + STA @VAL,Y + SUBB VAL,#2 ;NOW BACK UP ONE ELEMENT + DEC MASK + BNE RET1 ;LOOP + RET2 JSR POPSTK ;RESTORE UPPER PC + MOVEW TEMP,ZPCH + JSR POPSTK ;RESET Z-STACK + MOVEW TEMP,OZSTKP + JSR POPSTK + MOVE TEMP+HI,ZPCL ;REST OF PC + MOVE TEMP+LO,OZSTKC ;RESTORE OLD VALUES + LDA #0 + STA ZPCFLG ;PC CHANGED + MOVEW ARG1,TEMP ;ARGUMENT TO BE RETURNED + JMP PUTVAL ;STORE AND RETURN + + JUMP MOVEW ARG1,TEMP + SUBB TEMP,#1 + JMP PREDB3 ;TREAT AS A SUCCESSFUL JUMP + + PRINT MOVEW ARG1,TEMP + JSR SETSTR + PRINT1 JMP PZSTR ;PRINT THE STRING + + VALUE LDA ARG1+LO + JSR VARGET + JMP PUTVAL + + BCOM LDA ARG1+LO + EOR #0FF + STA TEMP+LO + LDA ARG1+HI + EOR #0FF + STA TEMP+HI + JMP PUTVAL + \ No newline at end of file diff --git a/apple/oldzip/2ops.z b/apple/oldzip/2ops.z new file mode 100644 index 0000000..b8eb65b --- /dev/null +++ b/apple/oldzip/2ops.z @@ -0,0 +1,303 @@ +O^( |".TITLE "ZORK - 2 OPS" + .PAGE + + LESSP MOVEW ARG1,TEMP + MOVEW ARG2,VAL + JSR SHLGED + BCC PREDSM + JMP PREDF + + GRTRP MOVEW ARG1,VAL + MOVEW ARG2,TEMP + JSR SHLGED + BCC PREDSM + JMP PREDF + + DLESSP JSR DEC1 + MOVEW ARG2,VAL + JMP IGRTP1 + + IGRTRP JSR INC1 + MOVEW TEMP,VAL + MOVEW ARG2,TEMP + IGRTP1 JSR SHLGED + BCC PREDSM + JMP PREDF + PREDSM JMP PREDS + + INP LDA ARG1+LO + JSR OBJLOC + LDY #4 + LDA ARG2+LO + CMP @TEMP,Y + BEQ PREDSM ;SUCCESS IF OBJ 2 IN 1 + JMP PREDF + + BTST LDA ARG2+HI + STA TEMP+HI + AND ARG1+HI + STA VAL+HI + LDA ARG2+LO + STA TEMP+LO + AND ARG1+LO + STA VAL+LO + JSR HLGEDE + BEQ PREDSM + JMP PREDF + + BOR LDA ARG2+HI + ORA ARG1+HI + STA TEMP+HI + LDA ARG2+LO + ORA ARG1+LO + STA TEMP+LO + JMP PUTVAL + + BAND LDA ARG2+HI + AND ARG1+HI + STA TEMP+HI + LDA ARG2+LO + AND ARG1+LO + STA TEMP+LO + JMP PUTVAL + + FSETP JSR FLAGSU ;GET BIT + LDA VAL+HI + AND MASK+HI + STA VAL+HI + LDA VAL+LO + AND MASK+LO + ORA VAL+HI ;CHECK FOR ON + BNE PREDSM ;BIT ON + JMP PREDF ;BIT OFF + + FSET JSR FLAGSU + LDY # + LDA VAL+LO + ORA MASK+LO + STA @TEMP,Y + NEXT + LDA VAL+HI + ORA MASK+HI + STA @TEMP,Y + RTS + + FCLEAR JSR FLAGSU + LDY # + LDA MASK+LO + EOR #0FF + AND VAL+LO + STA @TEMP,Y + NEXT + LDA MASK+HI + EOR #0FF + AND VAL+HI + STA @TEMP,Y + RTS + + ZSET MOVEW ARG2,TEMP + LDA ARG1+LO + VARPTR JMP VARPUT + + ZMOVE JSR REMOVC ;REMOVE OBJECT FIRST + LDA ARG1+LO + JSR OBJLOC + PUSHW TEMP ;SAVE LOC OF FIRST ARG + LDY #4 + LDA ARG2+LO + STA @TEMP,Y + JSR OBJLOC + LDY #6 ;FIRST SLOT + LDA @TEMP,Y + TAX + LDA ARG1+LO + STA @TEMP,Y + PULLW TEMP + TXA + BEQ $1 + LDY #5 + STA @TEMP,Y ;NEXT SLOT + $1 RTS + + GET ASL ARG2+LO + ROL ARG2+HI ;ITEM NUMBER * 2 + CLC + LDA ARG2+LO + ADC ARG1+LO + STA TEMP+LO + LDA ARG2+HI + ADC ARG1+HI + STA TEMP+HI + JSR SETWRD + JSR GETWRD + JMP PUTVAL + + GETB CLC + LDA ARG2+LO + ADC ARG1+LO + STA TEMP+LO + LDA ARG2+HI + ADC ARG1+HI + STA TEMP+HI + JSR SETWRD + JSR GETBYT + STA TEMP+LO + LDA #0 + STA TEMP+HI + JMP PUTVAL + + GETP JSR PROPB ;GET POINTER TO PROPS IN PROP TABLE + GETP1 JSR PROPN + CMP ARG2+LO + BEQ GETP2 ;FOUND PROP + BCC GETP3 ;GET PROP FROM DEFAULT TABLE + JSR PROPNX ;NEXT ENTRY + JMP GETP1 + + GETP3 LDY #ZOBJEC+ + CLC + LDA @ZCODEP,Y + ADC ZCODEP+LO + STA VAL+LO + NEXT + LDA @ZCODEP,Y + ADC ZCODEP+HI + STA VAL+HI ;BEG OF OBJECT TABLE + LDA ARG2+LO + ASL A + TAY + DEY + LDA @VAL,Y + STA TEMP+ + DEY + LDA @VAL,Y + STA TEMP+ + JMP PUTVAL ;RETURN DEFAULT VALUE + + GETP2 JSR PROPL ;GET LENGTH + INY + CMP #0 + BEQ GETP2A ;1 BYTE + CMP #1 + BEQ $1 + JSR ZER ;BAD PROP LENGTH + $1 LDA @TEMP,Y + STA VAL+ + INY + LDA @TEMP,Y + STA VAL+ + MOVEW VAL,TEMP + JMP PUTVAL ;RETURN TWO BYTE PROP + + GETP2A LDA @TEMP,Y + STA TEMP+LO + LDA #0 + STA TEMP+HI + JMP PUTVAL + + GETPT JSR PROPB + GETPT1 JSR PROPN + CMP ARG2+LO + BEQ GETPT2 ;FOUND PROP + BCS $1 + JMP RET0 + $1 JSR PROPNX + JMP GETPT1 + + GETPT2 INCW TEMP + CLC ;ADD IN OFFSET + TYA + ADC TEMP+LO + STA TEMP+LO + BCC $1 + INC TEMP+HI + $1 SEC + LDA TEMP+LO + SBC ZCODEP+LO ;SUBTRACT OFF RELATIVE POINTER + STA TEMP+LO + LDA TEMP+HI + SBC ZCODEP+HI + STA TEMP+HI + JMP PUTVAL + + NXTP JSR PROPB ;POINT TO PROP VALUE + LDA ARG2+LO + BEQ NXTP2 ;PROP0 + NXTP1 JSR PROPN + CMP ARG2+LO + BEQ NXTP3 ;FOUND PROP + BCS $1 + JMP RET0 ;RETURN 0 + $1 JSR PROPNX + JMP NXTP1 + + NXTP2 JSR PROPN + JMP PUTBYT + + NXTP3 JSR PROPNX + JMP NXTP2 ;PROPN OF NEXT + + ZADD CLC + LDA ARG1+LO + ADC ARG2+LO + STA TEMP+LO + LDA ARG1+HI + ADC ARG2+HI + STA TEMP+HI + JMP PUTVAL + + ZSUB SEC + LDA ARG1+LO + SBC ARG2+LO + STA TEMP+LO + LDA ARG1+HI + SBC ARG2+HI + STA TEMP+HI + JMP PUTVAL + + MUL MOVEW ARG1,TEMP + MOVEW ARG2,VAL + JSR SIGNC ;CHECK SIGN + LDA VAL+HI + BNE MUL0 + LDA VAL+LO + CMP #2 + BEQ MUL2 + CMP #4 + BEQ MUL4 + MUL0 JSR MULT ;DO THE MULTIPLY + MUL1 JSR SIGNS ;SET THE SIGN + JMP PUTVAL + + MUL4 ASL TEMP+LO + ROL TEMP+HI + MUL2 ASL TEMP+LO + ROL TEMP+HI + JMP MUL1 + + DIV MOVEW ARG1,TEMP + MOVEW ARG2,VAL + JSR SIGNC ;CHECK SIGNS + LDA VAL+HI + BNE DIV0 + LDA VAL+LO + CMP #2 + BEQ DIV2 + CMP #4 + BEQ DIV4 + DIV0 JSR DIVIDE ;DO THE DIVIDE + JMP MUL1 ;SET SIGN AND RETURN + + DIV4 LSR TEMP+HI + ROR TEMP+LO + DIV2 LSR TEMP+HI + ROR TEMP+LO + JMP MUL1 + + ZMOD MOVEW ARG1,TEMP + MOVEW ARG2,VAL + JSR SIGNC ;MAKE THEM POSITIVE + JSR DIVIDE ;DO THE DIVIDE + MOVEW VAL,TEMP ;GET THE REMAINDER + JMP PUTVAL + \ No newline at end of file diff --git a/apple/oldzip/create.z b/apple/oldzip/create.z new file mode 100644 index 0000000..f5096fd --- /dev/null +++ b/apple/oldzip/create.z @@ -0,0 +1,101 @@ +O^{ c' PROGRAM Create; {Create a 16 ZORK Diskette from constituent parts} + + CONST K = 1024; + PG = 256; + + Type Byte = 0..255; + Buffer = Packed Array [0..8191] of Byte; {32 sectors} + + VAR Count, I: Integer; + GameFile: File; + Bufptr, Bufptr2: Buffer; + Ch: Char; + + FUNCTION FCallRWTS (Cmd: Integer; Bufptr: Buffer; Length: Integer; +0Slot, Drive, Track, Sector: Integer):Boolean; + External; + + PROCEDURE Create1; FORWARD; + + PROCEDURE Error (ErrMsg1, ErrMsg2: String); +#BEGIN +&Close (GameFile); +&Writeln; Writeln (ErrMsg1, ErrMsg2); +&Writeln; Writeln ('*** Create failed! ***'); Writeln; +&Exit (Create1); +#END; + + PROCEDURE Load (Fname: String; Offset, LoadPt: Integer); +#TYPE Kludge = RECORD CASE BOOLEAN OF +3TRUE: (Int: INTEGER); +3FALSE: (Ptr: ^CHAR); +1END; +#VAR T: Kludge; +#BEGIN +#Reset (GameFile, Fname); +#T.Int := LoadPt; {Start of code space} +#IF BlockRead (GameFile, T.Ptr^, 99, Offset) = 0 +&THEN Error ('ERROR on reading ', Fname); +#Close (GameFile); +#END; {of Load} + + + PROCEDURE Copy (Fname: String; Offset: Integer; {Source} +0Track, Sector: Integer; {Destination} +0PageSize: Integer {in pages}); +#VAR BlockSize: Integer; {in blocks} +#BEGIN +#Reset (GameFile, Fname); BlockSize := (PageSize+1) div 2; +#IF BlockRead (GameFile, BufPtr, BlockSize, Offset) <> BlockSize +&THEN Error ('ERROR on reading ', Fname); +#IF NOT FCallRWTS (2 {Write}, BufPtr, BlockSize*2, 6*16, 1, Track, Sector) +&THEN Error ('ERROR on writing ', Fname); +#IF NOT FCallRWTS (1 {Read}, BufPtr2, BlockSize*2, 6*16, 1, Track, Sector) +&THEN Error ('ERROR on writing (rereading) ', Fname); +#IF NOT (BufPtr=BufPtr2) +&THEN Error ('ERROR on writing (verifying) ', Fname); +#CLOSE (GameFile); +#WRITELN ('File "', Fname, '" copied.'); +#END; {of Copy} + + + PROCEDURE Create1; + BEGIN +#Load ('#5:RWTS', 0, 36*PG); {Load into DISK space} +#Writeln; Writeln ('Place Next Destination Diskette in #4'); +#Write ('Type RETURN when ready '); Readln; +#IF NOT FCallRWTS (4 {Format}, BufPtr, 1, 6*16, 1, 1, 0) + THEN Error ('ERROR on formatting ', 'game disk'); +#Writeln ('Game disk formatted.'); +#BufPtr2 := BufPtr; {must start out identical} +#Copy ('#5:BOOT', 0, {To} 0, 0, {Size} 1); +#Copy ('#5:BOOT2.CODE', 1, {To} 0, 1, {Size} 1); +#Copy ('#5:PRWTS', 0, {To} 0, 2, {Size} 8); +#Load ('#5:PRWTS', 0, 36*PG); {ReLoad into DISK space} +#Copy ('#5:Z.CODE', 1, {To} 1, 0, {Size} 28); +#Reset (GameFile, '#5:GAME'); +#Count := 3; +#WRITE ('Copying game'); +#WHILE NOT EOF (GameFile) DO +&BEGIN +&IF BlockRead (GameFile, BufPtr, 16) = 0 +& THEN Error ('ERROR on reading ', '#5:GAME'); +&IF NOT FCallRWTS (2 {Write}, BufPtr, 32, 6*16, 1, Count, 0) ++THEN Error ('ERROR on writing ', 'game'); +&IF NOT FCallRWTS (1 {Read}, BufPtr2, 32, 6*16, 1, Count, 0) ++THEN Error ('ERROR on writing (rereading) ', 'game'); +&IF NOT (BufPtr=BufPtr2) ++THEN Error ('ERROR on writing (verifying) ', 'game'); +&Write ('..'); +&FOR I := 1 TO 1000 DO BEGIN END; +&Count := Count+2; +&END; +#Close (GameFile); +#Writeln; Writeln ('Game copied successfully.'); + END; {of Create1} + + + BEGIN {Main Program} +#WHILE 1>0 {i.e., forever} DO Create1; + END. + \ No newline at end of file diff --git a/apple/oldzip/extops.z b/apple/oldzip/extops.z new file mode 100644 index 0000000..c877c5e --- /dev/null +++ b/apple/oldzip/extops.z @@ -0,0 +1,536 @@ +O^( L'.TITLE "ZORK - EXT OPS" + .PAGE + + SCREN JMP SCRENN ; SELECTION OF WHICH SPLIT SCREEN TO USE + + SPLIT JMP SPLITT ; SPLIT THE SCREEN IN TWO + + EQUALP LDX ARGCNT + DEX + BNE $2 + JSR ZER + $2 LDA ARG1+LO ;COMPARE AGAINST ARG2 + CMP ARG2+LO + BNE $3 + LDA ARG1+HI + CMP ARG2+HI + BEQ PREDSQ ;WIN + $3 DEX + BEQ PREDFQ + LDA ARG1+LO ;COMPARE AGAINST ARG3 + CMP ARG3+LO + BNE $4 + LDA ARG1+HI + CMP ARG3+HI + BEQ PREDSQ ;WIN + $4 DEX + BEQ PREDFQ + LDA ARG1+LO ;COMPARE AGAINST ARG4 + CMP ARG4+LO + BNE $2 + LDA ARG1+HI + CMP ARG4+HI + BEQ PREDSQ ;WIN + PREDFQ JMP PREDF + PREDSQ JMP PREDS + + ZCALL LDA ARG1+LO + ORA ARG1+HI + BNE $1 + MOVEI 0,TEMP + JMP PUTVAL + $1 LDA OZSTKC + STA TEMP+LO + LDA ZPCL + STA TEMP+HI + JSR PSHSTK + MOVEW OZSTKP,TEMP + JSR PSHSTK + MOVEW ZPCH,TEMP + JSR PSHSTK + LDA #0 + STA ZPCFLG ;PC HAS CHANGED + LDA ARG1+LO + ASL A + STA ZPCL ;NEW ZPCL + LDA ARG1+HI + ROL A + STA ZPCH+LO ;NEW ZPCH + LDA #0 + ROL A + STA ZPCH+HI ;SAVE CARRY BIT + JSR NEXTPC ;GET NUMBER OF LOCALS + PHA ;SAVE # OF LOCALS + ORA #0 + BEQ ZCALL2 ;NO LOCALS + LDX #0 ;STORE OLD LOCALS + ZCALL1 PHA + LDA LOCALS,X + STA TEMP+ + INX + LDA LOCALS,X + STA TEMP+ + DEX + TXA + PHA + JSR PSHSTK + JSR NEXTPC ;GET NEW DEFAULT VALUE FOR LOCAL + PHA + JSR NEXTPC ;WORD VALUE + STA TEMP+ + PLA + STA TEMP+ + PLA + TAX + LDA TEMP+ + STA LOCALS,X + INX + LDA TEMP+ + STA LOCALS,X + INX + PLA + SEC + SBC #1 + BNE ZCALL1 ;LOOP THROUGH ALL LOCALS + ZCALL2 LDA ARGCNT + STA MASK + DEC MASK + BEQ ZCALL4 ;NO ARGS TO PASS + LDA #0 ;POINTER TO FIRST ARG + STA VAL + LDA #0 ;POINTER TO FIRST LOCAL + STA TEMP + ZCALL3 LDX VAL + LDA ARG2+,X + LDX TEMP + STA LOCALS,X + INC TEMP + LDX VAL + LDA ARG2+,X + LDX TEMP + STA LOCALS,X + INC TEMP + INC VAL + INC VAL + DEC MASK + BNE ZCALL3 + ZCALL4 PLA ;GET BACK NUMBER OF LOCALS + STA TEMP + JSR PSHSTK + LDA ZSTAKC + STA OZSTKC + MOVEW ZSTAKP,OZSTKP ;FOR KNOWING WHERE TO RETURN + RTS + + PUT LDA ARG2+LO + ASL A + ROL ARG2+HI + CLC + ADC ARG1+LO + STA TEMP+LO + LDA ARG2+HI + ADC ARG1+HI + STA TEMP+HI + CLC + LDA TEMP+LO + ADC ZCODEP+LO + STA TEMP+LO + LDA TEMP+HI + ADC ZCODEP+HI + STA TEMP+HI + LDY #0 + LDA ARG3+ + STA @TEMP,Y + INY + LDA ARG3+ + STA @TEMP,Y + RTS + + + PUTB LDA ARG2+LO + CLC + ADC ARG1+LO + STA TEMP+LO + LDA ARG2+HI + ADC ARG1+HI + STA TEMP+HI + CLC + LDA TEMP+LO + ADC ZCODEP+LO + STA TEMP+LO + LDA TEMP+HI + ADC ZCODEP+HI + STA TEMP+HI + LDY #0 + LDA ARG3+LO + STA @TEMP,Y ;STORE ONE BYTE IN RANDOM TABLE + RTS + + PUTP JSR PROPB ;SET PROP + PUTP1 JSR PROPN ;GET PROP NUMBER + CMP ARG2+LO + BEQ PUTP2 ;FOUND PROPERTY + BCS $1 + JSR ZER ;BAD PROP NUMBER $1 JSR PROPNX ;TRY NEXT + JMP PUTP1 + + PUTP2 JSR PROPL ;GET LENGTH + INY + CMP #0 + BEQ PUTP2A ;STORE 1 BYTE + CMP #1 + BEQ $1 + JSR ZER ;TOO LONG + $1 LDA ARG3+ + STA @TEMP,Y + INY + LDA ARG3+ + STA @TEMP,Y + RTS + + PUTP2A LDA ARG3+LO + STA @TEMP,Y + RTS ;SET AND RETURN + + ZREAD JSR WHOLIN + CLC ;GET REAL POINTERS TO TABLES + LDA ARG1+LO ;BUFFER TABLE + ADC ZCODEP+LO + STA ARG1+LO + LDA ARG1+HI + ADC ZCODEP+HI + STA ARG1+HI + CLC + LDA ARG2+LO ;RESULT TABLE + ADC ZCODEP+LO + STA ARG2+LO + LDA ARG2+HI + ADC ZCODEP+HI + STA ARG2+HI + JSR READBF ;READ THE BUFFER + STA MASK+HI ;CHARACTER COUNT + LDA #0 + STA MASK+LO ;HAS CHARACTERS IN WORD + LDY #1 + LDA #0 + STA @ARG2,Y ;SET WORDS READ TO 0 + LDA #2 + STA RTABP ;INITIALIZE RESULT TABLE POINTER + LDA #1 + STA STABP ;HAS POINTER TO INPUT CHARACTERS + READL LDY #0 + LDA @ARG2,Y + INY + CMP @ARG2,Y + BNE $1 + RTS ;TOO MANY WORDS + ;ERROR HERE IF DESIRED INSTEAD OF BNE + $1 LDA MASK+HI + ORA MASK+LO + BNE $2 + RTS ;OUT OF CHARACTERS AND WORDS + $2 LDA MASK+LO + CMP #6 + BNE $3 + JSR FLUSHW ;FLUSH CHARS IN A WORD OVER 6 CHARACTERS + $3 LDA MASK+LO + BNE READL2 ;NOT FIRST CHARACTER IN WORD + LDY #6 + LDX #0 ;INITIALIZE WORD BUFFER + RDOPL LDA #0 + STA ZSTBUI,X + INX + DEY + BNE RDOPL + LDA STABP ;POSITION OF START OF WORD + LDY RTABP + INY + INY + INY + STA @ARG2,Y ;STORE IN RESULT TABLE + LDY STABP + LDA @ARG1,Y + JSR SIBRKP ;SELF INSERTING BREAK? + BCS RSIBRK + LDY STABP + LDA @ARG1,Y + JSR NBRKP ;NORMAL BREAK? + BCC READL2 ;NO + INC STABP ;YES, FLUSH STRANDED BREAKS + DEC MASK+HI + JMP READL ;LOOP BACK + + READL2 LDA MASK+HI + BEQ READL3 ;OUT OF CHARACTERS, SIMULATE WORD ENDING + LDY STABP + LDA @ARG1,Y + JSR RBRKP ;WORD BREAK? + BCS READL3 ;FOUND A BREAK + LDY STABP + LDA @ARG1,Y + LDX MASK+LO + STA ZSTBUI,X ;STORE CHARACTER IN BUFFER + DEC MASK+HI ;ONE LESS CHARACTER + INC MASK+LO ;ONE MORE CHARACTER IN WORD + INC STABP ;POINT TO NEXT CHARACTER + JMP READL + + RSIBRK STA ZSTBUI ;STORE SELF INSERTING BREAK + INC MASK+LO ;1 CHAR + DEC MASK+HI ;1 LESS CHAR + INC STABP + READL3 LDA MASK+LO ;INSERT WORD IF ANY CHARACTERS IN WORD + BEQ READL ;NO CHARACTERS IN WORD + LDA MASK+HI + PHA + LDY RTABP ;STORE PARAMS IN TABLE + INY + INY + LDA MASK+LO ;REAL LENGTH OF WORD + STA @ARG2,Y + JSR CONZST ;CONVERT TO ZSTRING + JSR FINDW ;LOOKUP WORD IN VOCAB TABLE + LDY RTABP ;STORE RESULT + LDA VAL+ + STA @ARG2,Y + INY + LDA VAL+ + STA @ARG2,Y + INY + INY + INY + STY RTABP ;POINTER TO NEXT WORD + LDY #1 + LDA @ARG2,Y + CLC + ADC #1 ;ONE MORE WORD + STA @ARG2,Y + PLA + STA MASK+HI + LDA #0 + STA MASK+LO ;ZERO CHARACTERS IN NEXT WORD + JMP READL + + FLUSHW LDA MASK+HI ;FLUSH CHARACTERS TILL BREAK OR END OF BUFFER + BNE $1 + RTS + $1 LDY STABP + LDA @ARG1,Y + JSR RBRKP + BCC $2 + RTS ;FOUND A BREAK + $2 INC STABP + DEC MASK+HI + INC MASK+LO + JMP FLUSHW + + BRKTBL .ASCII " .,?" + .BYTE 0D, 0A, 9, 0C + NBRKS .EQU *-BRKTBL + + RBRKP JSR SIBRKP ;FIRST CHECK SELF INSERTING BREAKS + BCC NBRKP + RTS + NBRKP LDY #0 ;CHECK FOR NORMAL BREAKS + LDX #NBRKS + RBRK1 CMP BRKTBL,Y + BEQ FBRK ;MATCH + INY + DEX + BNE RBRK1 + RBRK2 CLC ;NOT FOUND, CLEAR CARRY + RTS + + FBRK SEC + RTS ;FOUND A BREAK, SET CARRY AND RETURN + + SIBRKP PHA + JSR GETVOC + LDY #0 + LDA @TEMP,Y ;NUMBER OF SELF INSERTING BREAKS + TAX + PLA + SIBRKL BEQ RBRK2 ;FAIL + INY + CMP @TEMP,Y + BEQ FBRK ;MATCH + DEX + JMP SIBRKL + + GETVOC LDY #ZVOCAB + LDA @ZCODEP,Y + STA TEMP+ + INY + LDA @ZCODEP,Y + STA TEMP+ + CLC + LDA TEMP+LO + ADC ZCODEP+LO + STA TEMP+LO + LDA TEMP+HI + ADC ZCODEP+HI + STA TEMP+HI + RTS + + FINDW JSR GETVOC ;FIND WORD IN VOCAB TABLE + LDY #0 + LDA @TEMP,Y + TAY ;SKIP OVER SELF INSERTING BREAKS + INY + LDA @TEMP,Y + ASL A + ASL A + ASL A + ASL A + STA MASK+LO ;HAS 16 TIMES VOCAB ENTRY SIZE + INY + LDA @TEMP,Y + STA VAL+ + INY + LDA @TEMP,Y + STA VAL+ ;VAL HAS VOCAB SIZE + INY ;POINTS TO VOCAB SIZE + TYA + CLC + ADC TEMP+LO + STA TEMP+LO + BCC $1 + INC TEMP+HI + $1 LDY # ;MAKE IT POINT TO HIGH ORDER BYTE + JMP FWL2 ;WE CAN'T START AT THE BEGINNING + + FWL1 LDA @TEMP,Y + CMP ZSTBUO+HI ;CHECK ONLY FIRST BYTE + BCS FWL3 ;FOUND PROPER AREA FOR FINE SEARCH + FWL2 CLC ;INCREMENT TEMP BY MASK+LO + LDA TEMP+LO + ADC MASK+LO + STA TEMP+LO + BCC $1 + INC TEMP+HI ;POINTER TO NEXT BLOCK + $1 SEC ;DECREMENT COUNT IN VAL BY 16 + LDA VAL+LO + SBC #16. + STA VAL+LO + BCS $2 + DEC VAL+HI + $2 LDA VAL+HI ;OUT OF WORDS? + BMI FWL3 ;YES + BNE FWL1 ;NO + LDA VAL+LO ;MAYBE, CHECK FOR ZERO + BNE FWL1 ;NO, KEEP GOING + FWL3 SEC ;NOW DO FINE CHECK + LDA TEMP+LO ;BACKUP 16 WORDS + SBC MASK+LO + STA TEMP+LO + BCS $1 + DEC TEMP+HI + $1 CLC ;BACKUP COUNT + LDA VAL+LO + ADC #16. + STA VAL+LO + BCC $2 + INC VAL+HI + $2 LDA MASK+LO + LSR A + LSR A + LSR A + LSR A + STA MASK+LO ;REAL ENTRY SIZE + FWL4 LDY # + LDA ZSTBUO+HI + CMP @TEMP,Y + BCC FWFAIL + BNE FWLNXT ;CHECK ALL 4 BYTES + NEXT + LDA ZSTBUO+LO + CMP @TEMP,Y + BCC FWFAIL + BNE FWLNXT + LDY #2+ + LDA ZSTBUO+2+HI + CMP @TEMP,Y + BCC FWFAIL + BNE FWLNXT + NEXT + LDA ZSTBUO+2+LO + CMP @TEMP,Y + BCC FWFAIL + BEQ FWSUCC ;FOUND A MATCH + FWLNXT CLC + LDA TEMP+LO + ADC MASK+LO + STA TEMP+LO + BCC $1 + INC TEMP+HI + $1 SUBB VAL,#1 + LDA VAL+LO + ORA VAL+HI + BNE FWL4 ;NOT OUT OF WORDS YET + FWFAIL LDA #0 + STA VAL+HI + STA VAL+LO + RTS + + FWSUCC SEC + LDA TEMP+LO + SBC ZCODEP+LO + STA VAL+LO + LDA TEMP+HI + SBC ZCODEP+HI + STA VAL+HI + RTS + + + PRINTC LDA ARG1+LO + JMP COUT + + PRINTN MOVEW ARG1,TEMP + JMP PRNTNC + + PRNTNC LDA TEMP+HI + BPL $1 + JSR PRNTNG ;NEGATIVE NUMBER + $1 LDA #0 ;DIGIT COUNT + STA MASK + PRNTN1 LDA TEMP+HI + ORA TEMP+LO + BEQ PRNTN3 + MOVEI 10.,VAL + JSR DIVIDE + LDA VAL+LO + PHA + INC MASK + JMP PRNTN1 + + PRNTN3 LDA MASK + BEQ PRNTN6 ;PRINT AT LEAST 0 + PRNTN4 PLA + CLC + ADC #30 ;ASCII "0" + JSR COUT + DEC MASK + BNE PRNTN4 + RTS + + PRNTN6 LDA #30 ;ASCII "0" + JMP COUT + + PRNTNG LDA #2D ;ASCII "-" + JSR COUT + JMP SIGNCN ;CHANGE SIGN + + RANDOM MOVEW ARG1,VAL ;RANDOM GENERATOR + JSR RND ;GET THE BASE NUMBER + JSR DIVIDE + MOVEW VAL,TEMP ;GET REMAINDER + INCW TEMP ;MAKE NOT EQUAL TO 0 + JMP PUTVAL + + ZPUSH MOVEW ARG1,TEMP + JMP PSHSTK + + ZPOP JSR POPSTK + LDA ARG1+LO + JMP VARPTR + \ No newline at end of file diff --git a/apple/oldzip/init.z b/apple/oldzip/init.z new file mode 100644 index 0000000..097da10 --- /dev/null +++ b/apple/oldzip/init.z @@ -0,0 +1,144 @@ + .TITLE "ZORK - INITIALIZATION" + .PAGE + + START CLD ;Clear Decimal Mode + LDA #0 + LDX #ZPGOFF + $1 STA 0,X ;Clear Zero Page + INX + BNE $1 + + LDX #0FF ;INIT CONTROL STACK + TXS + JSR SINIT ;DO SYSTEM-DEPENDENT INITIALIZATION + + LDA #FALSE + STA ZPCFLG + STA MPCFLG ;NO VALID MEMORY IN FROM DISK + MOVE #1,ZSTAKC ;INIT STACK + MOVEI ZSTACK+<2*ZSTAKL>,ZSTAKP + MOVE #0FF,ZSTBUI+6 + + MOVEI PGTOFF,PGTBL ;INIT PAGE TABLES + MOVEI PGTOFF+MAXPGS,PGTBH + MOVEI PGTOFF+<2*MAXPGS>,PGTBLF + MOVEI PGTOFF+<3*MAXPGS>,PGTBLB + LDY #0 + LDX #MAXPGS + START1 LDA #0FF + STA @PGTBL,Y ;NO PAGE IN MEMORY + STA @PGTBH,Y + TYA + CLC + ADC #1 ;POINT ONE DOWN + STA @PGTBLF,Y ;FORWARD POINTER + TYA + SEC + SBC #1 + STA @PGTBLB,Y ;BACK POINTER + INY ;CONTINUE LOOP + DEX + BNE START1 + DEY ;CORRECT FOR NO FORWARD POINTER FOR LAST PAGE + LDA #0FF + STA @PGTBLF,Y + MOVE #0,PGTOP ;TOP PAGE + MOVE #MAXPGS-1,PGBOT ;BOTTOM PAGE + + MOVEI THEEND,ZCODEP ;FIRST Z LOCATION + MOVEW ZCODEP,TEMP + MOVEI 0,VAL + JSR GETDSK ;READ IN FIRST SECTION + LDY #ZENDLD+ + LDA #0FF + STA @ZCODEP,Y + NEXT + LDA @ZCODEP,Y ;ALL THIS TO GET TO BLOCK BOUNDARY + STA ZMEMT ;NUMBER OF PAGES + INC ZMEMT ;PAGE NUMBER + LDA #0 + START2 CLC ;LOAD PRE-LOAD + ADC #1 + TAX + ADC ZCODEP+HI + STA TEMP+HI + LDA ZCODEP+LO + STA TEMP+LO + TXA + CMP ZMEMT + BEQ START3 ;DONE + PHA + STA VAL+LO + LDA #0 + STA VAL+HI + JSR GETDSK + PLA + JMP START2 + + START3 LDY #ZSWAP + LDA @ZCODEP,Y + + ORA #20 ;SET SPLIT SCREEN BIT IN MODE BYTE + STA @ZCODEP,Y + + .IF SMALLD ;SMALL-DISK CODE? + PHA + .ENDC + AND #2 + STA TIMEFL ;NON-ZERO IF TIME-MODE BIT SET + .IF SMALLD + PLA + AND #4 + STA TWODFL ;NON-ZERO IF 2-DISK BIT SET + BEQ $1 + JSR DISK2 ;SWITCH TO DISK #2 + .ENDC + $1 LDY #ZSTART+ + LDA @ZCODEP,Y + STA ZPCL ;GET STARTING ADDRESS + NEXT + LDA @ZCODEP,Y + STA ZPCH+LO + LDA #0 + STA ZPCH+HI + + LDY #ZGLOBA+ + LDA @ZCODEP,Y + STA GLOBAL+LO + NEXT + LDA @ZCODEP,Y + CLC + ADC ZCODEP+HI ;GET REAL ADDRESS OF GLOBAL TABLE + STA GLOBAL+HI + + LDY #ZFWORD+ + LDA @ZCODEP,Y + STA FWORDS+LO + NEXT + LDA @ZCODEP,Y + CLC + ADC ZCODEP+HI ;GET REAL ADDRESS OF FWORDS TABLE + STA FWORDS+HI + + LDA #0 + STA PGBUFP+LO + LDA ZMEMT + CLC + ADC ZCODEP+HI + STA PGBUFP+HI ;TOP LOCATION + + JSR MEMTOP + SEC + SBC PGBUFP+HI ;SWAPPING SPACE + BCC ZERL ;NOT ENOUGH SPACE + TAY + INY + STY NPGS + TAY + STY PGBOT + LDA #0FF ;SET LAST PAGE + STA @PGTBLF,Y + JMP MLOOP + + ZERL JSR ZER + \ No newline at end of file diff --git a/apple/oldzip/mach1dep.z b/apple/oldzip/mach1dep.z new file mode 100644 index 0000000..8cf3927 --- /dev/null +++ b/apple/oldzip/mach1dep.z @@ -0,0 +1,482 @@ + C&O^u "( +  .TITLE "ZORK - MACHINE DEPENDENT - SECTION #1" + .PAGE + + ;MACHINE-RELATED CONSTANTS MODIFIED 2-01-84 + WLEFT .EQU 20 + WWIDTH .EQU 21 + WTOP .EQU 22 + WBOTM .EQU 23 + CH .EQU 24 + EH .EQU 057B ;II E CURSOR HORIZONTAL + CV .EQU 25 + INVFLG .EQU 32 + PROMPT .EQU 33 + CSW .EQU 36 + MBASCAL .EQU 0FC22 ;MONITOR'S CALC BASE ADR FOR LINE ROUTINE + MCLEOL .EQU 0FC9C ;MONITOR'S CLEAR TO END OF LINE + MCLEOS .EQU 0FC42 ;MONITOR'S CLEAR TO END OF SCREEN + MHOME .EQU 0FC58 ;MONITOR'S HOME AND CLEAR SCREEN + MCOUT .EQU 0FDED ;MONITOR'S CHAR OUTPUT + MCOUT1 .EQU 0FDF0 ;MONITOR'S CHAR OUTPUT TO SCREEN + MRDKEY .EQU 0FD0C ;MONITOR'S GET AN INPUT CHAR ROUTINE + MGETLN1 .EQU 0FD6F ;MONITOR'S GET AN INPUT LINE ROUTINE + BUFFER .EQU 200 ;PAGE TWO FOR COUT/READBF STORAGE + + ;SYSTEM-DEPENDENT INITIALIZATION + + TOPPER STA WTOP + STA WTOP + RTS ;ROUTINE TO STORE WTOP WITH IIE + + SINIT: LDA #0C1 + STA ALTCSW+1 + + LDA #0 ;FIRST INITIALIZE SCREEN PARAMETERS + JSR TOPPER ;SET FULL HEIGHT OF SCREEN FOR NOW... +0 + LDA IIE + BEQ SCREW ;DON'T DO #21 IF NOT IIE + LDA #21. ;CNTL "Q" + JSR MCOUT ;TURN OFF 80 COLUMN + + SCREW LDA #0 + STA IIE + STA WLEFT + STA SCRINI ;PRINTER WILL BE UNINITIALIZED + + LDA #18 ;23 ACTIVE LINES ON SCREEN + STA WBOTM + LDA #0BE ;ASCII > + STA PROMPT + LDA #0FF + STA INVFLG + + JSR MODCDE + + LDA #03 + STA LINCNT ;LESSEN # OF LINES FOR LONG SCREENS + + LDA #01 + JSR TOPPER + RTS + + SPLITF .BYTE 0 ;WHICH WINDOW FLAG + ISPLIT .BYTE 0 ;IS IT SPLIT FLAG + + PISSER LDA IIE ;TALK TO DAN OR MIKE + BEQ PISS + LDA #0D + JMP PIS + PISS LDA #8D + PIS JSR MCOUT + RTS + + SPLITT LDA ARG1+LO ;GET NUMBER OF LINES FOR SCREEN + BEQ NORL ;IF ZERO THEN RESTORE SCREEN + PHA + CLC + ADC #01 ;ONE LINES ADDITIONAL + STA WBOTM + STA ISPLIT ;NON ZERO = SCREEN IS SPLIT + JSR MHOME ;CLEAR FROM TOP TO BOTTOM + JSR PISSER ;OUTPUT + LDA #18 ;RESTORE BOTTOM FOR SCROLL + STA WBOTM + PLA ;GET NUMBER OF LINES AGAIN + CLC + ADC #01 ;ADD ONE + JSR TOPPER ;MAKE THAT THE TOP OF THE SECOND SCREEN + LDA #01 + STA CH + STA EH + LDA #16 + STA CV ;RESTORE CURSOR AFTER MHOME CALL + JSR PISSER ; TO MAKE CV WORK + RTS ;BY GONE FOOL + + NORL LDA #01 ;PUT CURSOR AT TOP OF SCREEN + JSR TOPPER + LDA #0 ;MAKE MORE COUNT ZERO + STA LINCNT + STA ISPLIT ;ZERO = SCREEN IS NOT SPLIT + BYEBYE RTS + + SCRENN LDA ARG1+LO ;GET WHICH SCREEN TO WORK IN + PHA + BNE SSPL ;SPLIT SCREEN + LDA #0 ;FLAG NOT SPLIT + STA SPLITF + LDA #01 + STA CH + STA EH ;PUT CURSOR AT BOTTOM OF SCREEN + LDA #16 + STA CV + PLA ;CLEAN UP STACK + JMP GONE1 + + SSPL PLA ;GET IT AGAIN IN CASE + CMP #01 + BNE BYEBYE + LDA #01 + STA SPLITF ;THIS SCREEN IS SPLIT + LDA #0 ;TRY IT WITH ZERO*** + STA CH + STA EH + STA CV ;PUT IT IN SPLIT SCREEN AT TOP + + GONE1 JSR PISSER ;PUT OUT + RTS + + CLEARS: JSR MHOME ;HOME AND CLEAR + LDA ISPLIT ;IS IT SPLIT + BNE EARS ;YES THEN JUMP AROUND + LDA #01 + JSR TOPPER ;SET TOP STATUS LINE + EARS LDA #01 + STA LINCNT + RTS + + + RESTAR .EQU START ;NOTHING FANCY FOR RESTART + + MEMTOP: MOVE #0C0,TEMP+HI ;CALCULATE PAGE # OF TOP OF FREE MEMORY + MOVE #0FF,TEMP+LO + LDY #0 + MEMLOOP DEC TEMP+HI + LDA @TEMP,Y ;FETCH CONTENTS + CMP @TEMP,Y ;TRY TO READ + BNE MEMLOOP ;FAILED + EOR #0FF + STA @TEMP,Y ;TRY TO WRITE + CMP @TEMP,Y + BNE MEMLOOP ;FAILED + EOR #0FF ;HOORAY, WE FOUND RAM + STA @TEMP,Y + LDA TEMP+HI ;PAGE # RETURNED IN A + RTS + + COUT: LDX CHRPNT + LDY IIE ;IIe FLAG IN Y-REG FOR U/L CASE TESTS + CMP #0D ;CONTROL-M + BNE $3 + JMP CR + $3 CMP #20 + BCC COUT1 ;IGNORE OTHER CONTROLS + CMP #60 ;LOWER CASE? + BCC $1 + CMP #80 + BCS $1 + CPY #01 ;CHECK TO SEE IF IIE FLAG IS SET + BEQ $1 ;YES, SO SKIP CONVERSION + SEC + SBC #20 ;THEN CONVERT TO UPPER CASE + $1 ORA #80 + STA BUFFER,X ;OUTPUT CHARACTER (TO INTERMEDIATE BUFFER) + COUTSP CPX WWIDTH + BCS FLUSH + INX + COUT1 STX CHRPNT + RTS + + FLUSH LDA #0A0 ;SCAN BACKWARDS FOR SPACE + FLUSH1 CMP BUFFER,X + BEQ FLUSH2 + DEX + BNE FLUSH1 + LDX WWIDTH + FLUSH2 STX CPSAV ;OUTPUT FIRST PORTION OF BUFFER + STX CHRPNT + JSR CR + FLUSH3 INC CPSAV ;SHIFT REST TO BEGINNING OF BUFFER + LDX CPSAV + CPX WWIDTH ;FROM OLD CPSAV+1 TO WWIDTH + BCC $1 + BEQ $1 + RTS + $1 LDA BUFFER,X + LDX CHRPNT + STA BUFFER,X + INC CHRPNT + LDX CPSAV + JMP FLUSH3 + + LINOUT LDY #ZSCRIP+ ;TEST IF SCRIPTING ON + LDA @ZCODEP,Y + AND #1 + BEQ $1 + + JSR SCRIPT + + $1 JSR SCREEN + RTS + + SCRINI .BYTE 0 ;SCRIPTING INITIALIZED? + + SCRIPT PUSHW CSW ;SAVE OUTPUT HOOK + LDA CH ;AND CURRENT CURSOR POSITION + PHA + MOVEW ALTCSW,CSW ;LOAD SCRIPTING HOOK + LDX #0 + LDA SCRINI ;MUST INITIALIZE INTERFACE? + BNE SCRIP1 ;NO, ALREADY DONE + INC SCRINI ;YES, BUT DON'T COME HERE AGAIN + LDA #89 ;OUTPUT PRINTER SETUP SEQUENCE + JSR MCOUT + TXA ;SAVE X FOR LATER + TAY + + LDA ALTCSW+1 + SEC + SBC #0C1 + TAX + + LDA #91 ;SET FLAGS FOR COM CARD + STA 779,X ;IN SLOT 1 + LDA #0B8 + JSR MCOUT + LDA #0B0 + JSR MCOUT + LDA #0CE + JSR MCOUT + TYA ;GET X BACK FOR SCRIP1 + TAX + + SCRIP1 CPX CHRPNT + BEQ SCRIP2 + LDA BUFFER,X + JSR MCOUT ;OUTPUT CHAR IN A + INX + JMP SCRIP1 + + SCRIP2 MOVEW CSW,ALTCSW + PLA + STA CH + STA EH + PULLW CSW + RTS + + SCREEN LDX #0 + + SCREE1 CPX CHRPNT + BEQ SCREE2 + LDA BUFFER,X + JSR MCOUT ;OUTPUT CHAR IN A + INX + JMP SCREE1 + SCREE2 LDX #0 + STX CHRPNT + RTS + + MORES .ASCII "[MORE]" + MOREL .EQU *-MORES + + CR LDA SPLITF ;ARE WE SPLIT?? + BNE CRUD + + INC LINCNT + + CRUD LDA LINCNT + CMP WBOTM + BCC CR1 + MOVEI MORES,TEMP ;PRINT MORE PROMPT + LDX #MOREL + LDA #3F ;USE INVERSE VIDEO + STA INVFLG + JSR PMSG + LDA #0FF ;REVERT TO NORMAL VIDEO + STA INVFLG + JSR MRDKEY + LDA #0 + STA CH + STA EH ;IIE'S CH + JSR MCLEOL + LDA WTOP + STA LINCNT + INC LINCNT + CR1 LDA CHRPNT + PHA + JSR LINOUT + PLA + CMP WWIDTH + BEQ $1 + LDA #8D + JSR MCOUT ;OUTPUT TO SCREEN + + $1 LDY #ZSCRIP+ ;TEST IF SCRIPTING ON + LDA @ZCODEP,Y + AND #1 + BEQ $2 + PUSHW CSW ;SAVE OUTPUT HOOK + MOVEW ALTCSW,CSW ;LOAD SCRIPTING HOOK + LDA #8D + JSR MCOUT ;OUTPUT + MOVEW CSW,ALTCSW + PULLW CSW + $2 LDX #0 + JMP COUT1 + + + WSCOR .ASCII "SCORE: " + WSCORL .EQU *-WSCOR + WTIME .ASCII "TIME: " + WTIMEL .EQU *-WTIME + OLDRM .BYTE 0 + + + WHOLIN JSR LINOUT + LDY IIE ;*** + CPY #00 + BEQ FFF + + LDA EH ;*** + PHA + JMP FFE + + FFF LDA CH ;*** + PHA + + FFE LDA CV + PHA + LDA #0 + STA CH + STA EH + STA CV + JSR MBASCAL + LDA #3F ;USE INVERSE VIDEO + STA INVFLG + LDA #ROOMG ;GET ROOM + JSR VARGET + LDA TEMP+LO + STA OLDRM ;YES, SAVE NEW ROOM +@;*** ALWAYS REDISPLAY STATUS LINE +@;IT DON'T MATTER TO ME! + JSR PRNTDC + JSR SCREEN + JSR MCLEOL + $10 LDA IIE ;GET THE 80 COL FLAG + BEQ $11 ;NOT 80 COLS, SO NYET SWEAT + LDA #60. ;THIS IS WHERE TO PRINT THE SCORE/TIME + STA CH + + STA EH ;IIE'S CH + + JMP $12 ;DONE WITH IIE FROBBIES + $11 LDA #25. ;OLD MIDDLE OF SCREEN + STA CH + $12 LDA TIMEFL ;TIME MODE? + BNE $1 ;YES + MOVEI WSCOR,TEMP ;NO, PRINT SCORE HEADER + LDX #WSCORL + JSR PMSG + LDA #SCOREG ;PRINT SCORE + JSR VARGET + JSR PRNTNC + LDA #02F ;ASCII + BNE $2 ;BRANCH ALWAYS + $1 MOVEI WTIME,TEMP ;PRINT TIME HEADER + LDX #WTIMEL + JSR PMSG + LDA #SCOREG ;PRINT HOUR + JSR VARGET + LDA TEMP+LO + BNE $8 ;00 IS REALLY 24 + LDA #24. + $8 CMP #12. ;NOW CONVERT TO 12-HOUR TIME + BMI $3 ;BLE + BEQ $3 + SEC + SBC #12. + STA TEMP+LO + $3 JSR PRNTNC + LDA #03A ;ASCII + $2 JSR COUT + LDA #MOVESG ;PRINT MOVES + JSR VARGET + LDA TIMEFL ;TIME MODE? + BEQ $9 ;NO + LDA TEMP+LO ;YES, CHECK FOR SINGLE-DIGIT NUMBER + CMP #10. + BCS $4 ;NO + LDA #0B0 ;YES, PAD WITH LEADING ZERO + JSR COUT + $4 JSR PRNTNC + LDA #0A0 ;SPACE + JSR COUT + LDA #SCOREG ;HOUR AGAIN + JSR VARGET + LDA TEMP+LO + CMP #12. ;PM? + BPL $6 ;YES + LDA #0C1 ;NO, USE A + BNE $7 + $6 LDA #0D0 ;P FOR PM + $7 JSR COUT + LDA #0CD ;M + JSR COUT + JMP $5 + $9 JSR PRNTNC + + $5 JSR SCREEN + JSR MCLEOL + LDA #0FF + STA INVFLG + PLA ;RESTORE H&V + STA CV + PLA + STA CH + STA EH ;*** IIE'S CH + JSR MBASCAL + RTS + + PMSG LDY #0 + PMSGL LDA @TEMP,Y + ORA #80 + JSR MCOUT + INY + DEX + BNE PMSGL + RTS + + READBF JSR LINOUT + LDA WTOP + STA LINCNT + JSR MGETLN1 ;GET INPUT LINE + INC LINCNT + LDA #8D ;TERMINATE WITH CR + STA 200,X + INX + TXA + PHA + LDY #ZSCRIP+ ;TEST IF SCRIPTING ON + LDA @ZCODEP,Y + AND #1 + BEQ $1 + TXA + STA CHRPNT ;ECHO INPUT TO SCRIPT + JSR SCRIPT + LDA #0 + STA CHRPNT + $1 PLA + LDY #0 + CMP @ARG1,Y + BCC $2 + LDA @ARG1,Y + $2 PHA + BEQ READBD + TAX READBL LDA 200,Y + AND #7F + CMP #41 ;CONVERT FROM UPPER CASE TO LOWER + BCC $1 + CMP #5B + BCS $1 + ORA #20 + $1 INY + STA @ARG1,Y + CMP #0D ;JUST STASHED ? + BEQ READBD + DEX + BNE READBL + READBD PLA + RTS + \ No newline at end of file diff --git a/apple/oldzip/mach2dep.z b/apple/oldzip/mach2dep.z new file mode 100644 index 0000000..a4c30d6 --- /dev/null +++ b/apple/oldzip/mach2dep.z @@ -0,0 +1,509 @@ + .TITLE "ZORK - MACHINE DEPENDENT - SECTION #2" + .PAGE + + ;LAST MODIFICATION - 2-01-84 + + ;**************************** DISK INTERFACE CODE ********************* + + RWTS .EQU 02900 ;READ/WRITE ROUTINE + + GAMETRK .EQU 3 ;TRACK ON WHICH GAME STARTS *** + + SECTDIV .EQU 07F ;SECTORS PER TRACK (EITHER 13. OR 16.) + + SAVSIZ .EQU 64. ;# SECTORS ALLOWED FOR SAVE + + ;I/O BLOCK (FOR RWTS) + IOB: .BYTE 1 ;TYPE (ALWAYS 1) + SLOT: .BYTE 6*10 ;SLOT # TIMES 10 + DRIVE: .BYTE 1 ;DRIVE (EITHER 1 OR 2) + VOLUME .BYTE 0 + TRACK .BYTE ;FROM 0 TO 34. + SECTOR .BYTE ;FROM 0 TO 12. FOR 13 SECTORS DISKS + .WORD DEVCHR ;POINTER TO DEVICE CHARACTERISTICS TABLE + IOBUFR .WORD 0 ;SOURCE/DESTINATION DATA BUFFER + .WORD 0 + IOCMD .BYTE ;1 IS READ, 2 IS WRITE + STATUS .BYTE + VOLFND .BYTE + PSLOT .BYTE 6*10 ;PREVIOUS SLOT # + PDRIVE .BYTE 1 ;PREVIOUS DRIVE # + + DEVCHR .BYTE 0 ;DEVICE CODE (ALWAYS 0) + .BYTE 1 + MOTORON .WORD 0D8EF ;MOTOR ON TIME (IN 100 USECS) COMPLEMENTED +@;0D8EF = 1.0 SECS, 0F82F = 0.2 SECS + + GETPUT STA IOCMD ;TELL READ/WRITE COMMAND + MOVEW TEMP,IOBUFR ;TELL WHERE + + MOVE #GAMETRK,TRACK ;COMPUTE TRACK & SECTOR FROM PAGE # + LDA VAL+LO ;LOW ORDER BYTE OF DIVIDEND + LDX VAL+HI + SEC + GPLOOP SBC SECTDIV ;DIVISOR + BCS $1 + DEX ;BORROW + BMI GPEND + SEC + $1 INC TRACK + JMP GPLOOP + GPEND CLC + ADC SECTDIV + STA SECTOR + + LDA #1*IOB/100 ;SETUP POINTER TO I/O BLOCK + LDY #1*IOB&0FF + JMP RWTS ;DO IT, RETURNS WITH CARRY CLEAR IF NO ERROR + + ;GET a disk block, destination memory address in TEMP & page # in VAL + + GET200 MOVEI 200,TEMP + GETNXT INCW VAL + IGETDK LDA #1 ;FOR READ + JMP GETPUT ;RETURNS WITH CARRY CLEAR IF NO ERROR + + GETDSK JSR IGETDK + BCC $1 + JSR ZER ;ERROR + $1 RTS + + PUT200 MOVEI 200,TEMP + PUTNXT INCW VAL + PUTDSK + ;; PUSHW MOTORON + ;; MOVE #0D8,MOTORON+HI + ;; MOVE #0EF,MOTORON+LO + LDA #2 ;FOR WRITE + JMP GETPUT + ;; PULLW MOTORON + ;; RTS ;RETURNS WITH CARRY CLEAR IF NO ERROR + + ;************************** SAVE/RESTORE CODE ************************* + + COUTM STX MASK + LDY #0 + STY MASK+1 + COUTML LDY MASK+1 + LDA @TEMP,Y + JSR COUT + INC MASK+1 + DEC MASK + BNE COUTML + RTS + INSERM .ASCII "INSERT SAVE DISKETTE," + INSERL .EQU *-INSERM + + SNMOFF .BYTE 0 + SNMSG .EQU * + SLOTM .EQU *-SNMSG + .ASCII "SLOT (1-7):" + SNMSGL .EQU *-SNMSG + SNMDF .EQU * + SLOTDF .BYTE 36 ;ASCII 6 + .BYTE 31,38 ;MUST BE BETWEEN 1 AND 7 + + DRIVM .EQU *-SNMSG + .ASCII "DRIVE (1-2):" + DRIVDF .BYTE 32 ;ASCII 2 + .BYTE 31,33 ;MUST BE 1 OR 2 + + POSM .EQU *-SNMSG + .ASCII "POSITION (0-7):" + POSDF .BYTE 30 ;ASCII 0 + .BYTE 30,38 ;MUST BE BETWEEN 0 AND 7 + + COLM80 .ASCII "80 COLUMNS? (Y/N):" + .BYTE 0D + .BYTE 255. + + DEFM .ASCII "DEFAULT = " + DEFL .EQU *-DEFM + + BEGM .ASCII "--- PRESS 'RETURN' TO BEGIN ---" + BEGL .EQU *-BEGM + + PRLM .ASCII "PRINTER SLOT (0-7):" + .BYTE 0D + .BYTE 255. + + PRFLG .BYTE 0 ;SLOT TEST FLAG + + IIE .BYTE 0 ;FLAG FOR IIe SET IN MODCDE, LATER USED +@;TO CHECK U/L CASE, ETC. + + MODCDE LDA 0FBB3 + CMP #06 ;IF 6 THEN IIE + BNE OUT + LDA 0C017 + AND #080 ;TEST FOR 0D OR 8D + BNE OUT ;HIGH BIT SET = IIE WITH NO CARD + + LDA #0 + STA IIE ;INIT IIE AGAIN FOR RESTART + + ASK80 MOVEI #COLM80,TEMP ;PROMPT + + JSR MHOME + LDY #0 + ILF LDA (TEMP),Y + CMP #255. + BEQ DIP + EOR #80 ;MASK FOR NO FLASHING + JSR MCOUT + INY + JMP ILF + DIP JSR MRDKEY ;MONITOR RDKEY + + TAX + CPX #0EE ;ASCII "n" + BEQ OUT ;yes + + CPX #0CE ;ASCII "N" + BEQ OUT ;YES + + CPX #0F9 ;ASCII "y" + BEQ ISY ;YES + + CPX #0D9 ;ASCII "Y" + BEQ ISY ;YES + + CPX #08D ;IS IT "CR" + BNE ASK80 ;NO THEN GO BACK + + ISY JSR MHOME ;CLEAR SCREEN AFTER PROMPT + + LDA #00 + STA 36 + LDA #0C3 ;PR#3 + STA 37 + JSR PISSER ;JSR CR + LDA #01 + STA IIE ;SET THE FLAG -- IT'S A IIE W 80 COLUMNS + RTS + + OUT LDA #0 + STA IIE ;ZERO OUT THE IIE FLAG + RTS + + PCHK LDA PRFLG + BNE DD ;DO ONLY ONCE + + PRLP MOVEI #PRLM,TEMP + + LDY #0 + ILF1 LDA (TEMP),Y + CMP #255. + BEQ DIP1 + EOR #80 ;MASK FOR NO FLASHING + JSR MCOUT + INY + JMP ILF1 + + DIP1 JSR MRDKEY + + SEC + SBC #0B0 + BCC PRLP + CLC + CMP #08 + BCS PRLP + CLC + ADC #0C0 + STA ALTCSW+1 + + INC PRFLG + + DD RTS + + LOADSV JSR CLEARS + JSR CR + JSR CR + MOVEI INSERM,TEMP + LDX #INSERL + JSR COUTM + JSR CR + POSR MOVE #POSM,SNMOFF + JSR GETSNM + POSGO STA POSDF + JSR COUT + SLOTR MOVE #SLOTM,SNMOFF + JSR GETSNM + SLOTGO TAX + AND #7 + ASL A ;TIMES 10 + ASL A + ASL A + ASL A + STA SLOT + TXA + STA SLOTDF + JSR COUT + DRIVR MOVE #DRIVM,SNMOFF + JSR GETSNM + DRIVGO TAX + AND #3 + STA DRIVE + TXA + STA DRIVDF + JSR COUT + BEGASK JSR CR + MOVEI BEGM,TEMP + LDX #BEGL + JSR COUTM + JSR LINOUT + JSR MRDKEY + CMP #8D ;ASCII RETURN + BNE BEGASK + LDA #0FF ;INITIAL DISK BLOCK # FOR POSITION 0 + STA VAL + STA VAL+1 + LDA POSDF ;RETRIEVE POSITION + AND #7 + BEQ $2 + TAY + $1 ADDB VAL,#SAVSIZ + DEY + BNE $1 + $2 JSR CR + RTS + + GETSNM JSR CR + MOVEI SNMSG,TEMP + ADDB TEMP,SNMOFF + LDX #SNMSGL + JSR COUTM + JSR LINOUT + LDA #25. + STA CH + + STA EH ;IIE'S CH + + LDA #3F ;USE INVERSE VIDEO + STA INVFLG + MOVEI DEFM,TEMP + LDX #DEFL + JSR PMSG + MOVEI SNMDF,TEMP + ADDB TEMP,SNMOFF + LDX #1 + JSR PMSG + LDA #0FF + STA INVFLG + JSR MRDKEY + PHA + LDA #25. + STA CH + + STA EH ;IIE'S CH + + JSR MCLEOL + PLA + LDY SNMOFF + CMP #8D ;ASCII RETURN + BNE $1 + LDA SNMDF,Y ;USE DEFAULT + $1 AND #7F + CMP SNMDF+1,Y ;NOW CHECK RANGE + BCC GETSNM + CMP SNMDF+2,Y + BCS GETSNM + RTS + + REINSM .ASCII "RE-INSERT GAME DISKETTE," + REINSL .EQU *-REINSM + CONM .ASCII "--- PRESS 'RETURN' TO CONTINUE ---" + CONL .EQU *-CONM + + + LOADGM LDA SLOT ;BOOT SLOT? + CMP #6*10 + BNE LOADG1 + LDA DRIVE ;BOOT DRIVE? + CMP #1 + BNE LOADG1 + JSR CR + MOVEI REINSM,TEMP + LDX #REINSL + JSR COUTM + CONASK JSR CR + MOVEI CONM,TEMP + LDX #CONL + JSR COUTM + JSR LINOUT + JSR MRDKEY + CMP #8D ;ASCII RETURN + BNE CONASK + JSR CR + LOADG1 LDA #6*10 ;BOOT SLOT + STA SLOT + LDA #1 ;BOOT DRIVE + STA DRIVE + RTS + + SAVE JSR LOADSV + LDX #0 ;INDEX TO SAVE BUFFER + LDY #ZID + LDA @ZCODEP,Y ;SAVE ZORKID + STA 200,X + INX + INY + LDA @ZCODEP,Y + STA 200,X + INX + MOVEI ZPCOFF,TEMP ;SAVE ZPCH & ZPCL + LDY #3 + JSR SAVE1 + MOVEI LOCALS,TEMP ;SAVE LOCALS + LDY #30. + JSR SAVE1 + MOVEI STKOFF,TEMP ;SAVE STACK POINTERS & COUNTS + LDY #6 + JSR SAVE1 + JSR PUT200 ;WRITE SAVE BUFFER + BCS SAVEF + LDX #0 ;INDEX TO SAVE BUFFER + MOVEI ZSTACK,TEMP ;SAVE STACK + LDY #0 ;SAVE FIRST 256 BYTES + JSR SAVE1 + JSR PUT200 ;WRITE + BCS SAVEF + LDX #0 ;INDEX TO SAVE BUFFER + MOVEI ZSTACK+100,TEMP + LDY #<2*ZSTAKL>-100 ;SAVE REST + JSR SAVE1 + JSR PUT200 + BCS SAVEF + MOVEW ZCODEP,TEMP ;START OF PURE SPACE + LDY #ZPURBT+ ;GET SIZE OF PURE SPACE + LDA @ZCODEP,Y + STA MASK + INC MASK ;ROUND UP + SAVEL JSR PUTNXT + BCS SAVEF + INC TEMP+HI + DEC MASK + BNE SAVEL + JSR PUTNXT ;FLUSH BUFFER + BCS SAVEF + JSR LOADGM + JMP PREDS + SAVEF JSR LOADGM + JMP PREDF + + SAVE1 DEY + LDA @TEMP,Y + STA 200,X + INX + CPY #0 + BNE SAVE1 + RTS + + + RESTOR JSR LOADSV + JSR GET200 ;READ INTO RESTORE BUFFER + BCC $1 + JMP RESTF + $1 LDX #0 ;INDEX TO RESTORE BUFFER + LDY #ZID + LDA @ZCODEP,Y ;COMPARE ZORKIDS + CMP 200,X + BNE $2 + INX + INY + LDA @ZCODEP,Y + CMP 200,X + BEQ $3 + $2 JMP RESTF + $3 LDY #ZSCRIP+ ;SAVE SCRIPTING FLAG + LDA @ZCODEP,Y + STA SIGNF + INX + MOVEI ZPCOFF,TEMP ;RESTORE ZPCH & ZPCL + LDY #3 + JSR REST1 + LDA #FALSE + STA ZPCFLG + MOVEI LOCALS,TEMP ;RESTORE LOCALS + LDY #30. + JSR REST1 + MOVEI STKOFF,TEMP ;RESTORE STACK POINTERS & COUNTS + LDY #6 + JSR REST1 + JSR GET200 ;READ NEXT BLOCK INTO RESTORE BUFFER + BCS RESTF + LDX #0 ;INDEX TO RESTORE BUFFER + MOVEI ZSTACK,TEMP ;RESTORE STACK + LDY #0 ;RESTORE FIRST 256 BYTES + JSR REST1 + JSR GET200 ;READ NEXT BLOCK + BCS RESTF + LDX #0 ;INDEX TO RESTORE BUFFER + MOVEI ZSTACK+100,TEMP + LDY #<2*ZSTAKL>-100 ;RESTORE REST + JSR REST1 + MOVEW ZCODEP,TEMP ;START OF PURE SPACE + LDY #ZPURBT+ ;GET SIZE OF PURE SPACE + LDA @ZCODEP,Y + STA MASK + INC MASK ;ROUND UP + RESTL JSR GETNXT + BCS RESTF + INC TEMP+HI + DEC MASK + BNE RESTL + LDA SIGNF ;RESTORE SCRIPTING FLAG + LDY #ZSCRIP+ + STA @ZCODEP,Y + JSR LOADGM + JMP PREDS + RESTF JSR LOADGM + JMP PREDF + + REST1 DEY + LDA 200,X + STA @TEMP,Y + INX + CPY #0 + BNE REST1 + RTS + + RND INC 04E ;MODIFY NUMBER IN CASE NO READKEYS + INC 04F + MOVEW 04E,TEMP ;SNARF RANDOM NUMBER FROM MONITOR + RTS + + QTMSG .ASCII "-- END OF SESSION --" + QTLNG .EQU *-QTMSG + ZERMSG .ASCII "INTERNAL ERROR #" + ZERLNG .EQU *-ZERMSG +0;ZIP INTERNAL ERROR +0 + ZER JSR CR + MOVEI ZERMSG,TEMP ;HEADER MESSAGE + LDX #ZERLNG + JSR COUTM + PLA + STA TEMP+LO + PLA + STA TEMP+HI + JSR PRNTNC + JMP QUIT + ; WARNING **** PUT NOTHING BETWEEN HERE +@; AND THE QUIT OPCODE THERE IS VARIABLE +@; FUNKINESS WITH BOOT2 DISK CONTROL +@; BLOCK AND IT CHANGES VARIABLES +@; WARNING ********************* +@ +@ + .ORG 023D0 ;BELOW CONTROL BLOCK USED BY BOOT2.CODE + + .LIST + + QUIT JSR CR + MOVEI QTMSG,TEMP + LDX #QTLNG + JSR COUTM + JSR CR + JMP * + \ No newline at end of file diff --git a/apple/oldzip/main.z b/apple/oldzip/main.z new file mode 100644 index 0000000..5d057f6 --- /dev/null +++ b/apple/oldzip/main.z @@ -0,0 +1,333 @@ +O^u & .TITLE "ZORK - MAIN LOOP" + .PAGE + ;MAIN LOOP, READ AN INSTRUCTION AND ITS ARGS, THEN DISPATCH + + MLOOP: + LDA PRFLG ;TEST PRINTER SLOT QUESTION + BNE DLOOP ;YES, FORGET IT + + LDY #ZSCRIP+ ;SCRIPT ON TEST + LDA @ZCODEP,Y + AND #1 + BEQ DLOOP ;*** MODF. 12-01-83 D.H. + + JSR PCHK ;NONE DONE SO DO THEM + + DLOOP: + ;; MOVE ZPCL,PCSAV ;SAVE CURRENT PC FOR DEBUGGING + ;; MOVEW ZPCH,PCSAV+1 + LDA #0 + STA ARGCNT ;ZERO ARG COUNT + JSR NEXTPC ;GET NEXT OPCODE + STA OPCODE ;SAVE IT + CMP #128. + BCS $1 + JMP OP2 ;TWO OP + $1 CMP #176. + BCS $2 + JMP OP1 ;ONE OP + $2 CMP #192. + BCC OP0 ;ZERO OP + OPEXT: JSR NEXTPC ;GET VAR TYPES, THIS IS AN EXT OP + LDX #0 + OPEXTL: PHA ;SAVE VAR TYPES + TAY + TXA ;SAVE ARG PTR + PHA + TYA + AND #0C0 ;ISOLATE ARG TYPE + BNE $1 + JSR GETLNG ;LONG IMMED + JMP $4 + $1 CMP #80 + BNE $2 + JSR GETVAR ;VARIABLE + JMP $4 + $2 CMP #40 + BNE $3 + JSR GETSHT ;SHORT IMMED + JMP $4 + $3 PLA + PLA + JMP OPEXTF ;ALL DONE + $4 PLA ;RESTORE ARG PTR + TAX + LDA TEMP+LO ;SAVE ARG + STA ARG1+LO,X + LDA TEMP+HI + STA ARG1+HI,X + INX + INX + INC ARGCNT + PLA ;RESTORE VAR TYPES + SEC ;GET TO NEXT ARG TYPE + ROL A + SEC + ROL A + JMP OPEXTL + + OPEXTF: MOVEI OPXT,TEMP ;COMPUTE DISPATCH POINTER + LDA OPCODE + CMP #224. + BCS $1 + JMP OP2EX ;2EX TYPE + $1 SBC #224. ;WHICH ONE + CMP #OPXM ;MAX VAL + BCS BADOP + OPDSPH: ASL A ;GENERALIZED DISPATCH + TAY ;2*OFFSET + LDA @TEMP,Y + STA JSROP+LO + INY + LDA @TEMP,Y + STA JSROP+HI ;LOCATION TO DISPATCH TO + ;;; JSR 07C ;PATCH AREA + JSROP .EQU *+1 ;PATCH LOCATION TO INSERT JSR ADDRESS + JSR * ;GO TO IT + JMP MLOOP ;NEXT OPERATION + + OP0: SEC + SBC #176. ;CHECK RANGE + CMP #OP0M + BCS BADOP + PHA + MOVEI OP0T,TEMP + PLA + JMP OPDSPH ;DISPATCH + + BADOP: JSR ZER + + OP1: AND #30 ;1 OP, GET ARG TYPE + BNE $10 + JSR GETLNG + JMP $99 + $10 CMP #10 + BNE $20 + JSR GETSHT + JMP $99 + $20 JSR GETVAR + $99 LDA #1 + STA ARGCNT ;1 ARG + MOVEW TEMP,ARG1 ;STORE IT + LDA OPCODE + AND #0F ;TURN OFF MODE BITS + CMP #OP1M ;CHECK IN RANGE + BCS BADOP + PHA + MOVEI OP1T,TEMP + PLA + JMP OPDSPH ;DISPATCH + + OP2: AND #40 ;2 OP, GET OPERAND TYPES + BNE $11 + JSR GETSHT + JMP $1 + $11 JSR GETVAR + $1 MOVEW TEMP,ARG1 ;STORE ARG1 + LDA OPCODE + AND #20 ;CHECK ARG2 + BNE $21 + JSR GETSHT + JMP $2 + $21 JSR GETVAR + $2 MOVEW TEMP,ARG2 ;STORE ARG 2 + LDA #2 + STA ARGCNT ;TWO ARGS + LDA OPCODE + OP2EX: AND #01F ;TURN OFF MODE BITS + CMP #OP2M + BCS BADOP + PHA + MOVEI OP2T,TEMP + PLA + JMP OPDSPH + + GETSHT: JSR NEXTPC ;GET SHORT IMMEDIATE + STA TEMP+LO + LDA #0 ;FILL IN MSB + STA TEMP+HI + RTS + + GETLNG: JSR NEXTPC + PHA + JSR NEXTPC + STA TEMP+ + PLA + STA TEMP+ + RTS + + VARGET: ORA #0 + BEQ VARGTS ;GET VAR FROM STACK + JMP GETVR1 + + VARPUT: ORA #0 + BEQ VARPTS + JMP PUTVR1 + + VARGTS: JSR POPSTK + JMP PSHSTK ;GET FROM STACK AND REPLACE + + VARPTS: PUSHW TEMP + JSR POPSTK ;TAKE OFF OLD TOP OF STACK + PULLW TEMP ;GET BACK NEW VALUE + JMP PSHSTK ;AND PUT IT ON TOP OF ZSTACK + + GETVAR: JSR NEXTPC ;GET VAR, FIND FIRST TYPE + ORA #0 + BEQ GETVRS ;FROM STACK + GETVR1: CMP #16. + BCS GETVRG ;GLOBAL + GETVRL: SEC ;LOCAL + SBC #1 + ASL A + TAX + LDA LOCALS,X + STA TEMP+ + INX + LDA LOCALS,X + STA TEMP+ + RTS + + GETVRG: SEC + SBC #16. ;SUBTRACT OFFSET OF 16. + ASL A ;DOUBLE GLOBAL # TO VAL + STA VAL+LO + LDA #0 + ROL A + STA VAL+HI + CLC ;ADD IN PTR TO GLOBAL TABLE + LDA GLOBAL+LO + ADC VAL+LO + STA VAL+LO + LDA GLOBAL+HI + ADC VAL+HI + STA VAL+HI + LDY #0 + LDA @VAL,Y + STA TEMP+ + INY + LDA @VAL,Y + STA TEMP+ + RTS ;RETURN VALUE IN TEMP + + GETVRS: JSR POPSTK ;VAR FROM STACK + RTS + + RET0: LDA #0 ;RETURN 0 + PUTBYT: STA TEMP+LO + LDA #0 + STA TEMP+HI + PUTVAL: JMP PUTVLC + + PUTVLC: PUSHW TEMP ;SAVE VALUE + JSR NEXTPC ;GET TYPE + TAX + PULLW TEMP + TXA + PUTVR1: ORA #0 + BNE $1 + JMP PSHSTK ;SAVE ON STACK AND RETURN + $1 CMP #16. + BCS PUTVLG ;GLOBAL + PUTVLL: SEC ;LOCAL + SBC #1 + ASL A + TAX + LDA TEMP+ + STA LOCALS,X + INX + LDA TEMP+ + STA LOCALS,X + RTS + + PUTVLG: SEC + SBC #16. ;SUBTRACT OFFSET OF 16. + ASL A ;DOUBLE GLOBAL # TO VAL + STA VAL+LO + LDA #0 + ROL A + STA VAL+HI + CLC ;ADD IN PTR TO GLOBAL TABLE + LDA GLOBAL+LO + ADC VAL+LO + STA VAL+LO + LDA GLOBAL+HI + ADC VAL+HI + STA VAL+HI + LDY #0 + LDA TEMP+ + STA @VAL,Y + INY + LDA TEMP+ + STA @VAL,Y + RTS + + PREDS: JSR NEXTPC ;PREDICATE HACKS, THIS ONE FOR SUCCEED + ORA #0 + BMI PREDB ;BRANCH + BPL PREDNB ;DON'T BRANCH + + PREDF: JSR NEXTPC ;PREDICATE FAIL + ORA #0 + BPL PREDB ;BRANCH + PREDNB: AND #40 ;CHECK FOR MULTI BYTE HACK + BNE $1 + JSR NEXTPC ;GET NEXT BYTE IF SO + $1 RTS ;CONTINUE IN SEQUENCE + + PREDB: TAX + AND #40 + BEQ PREDLB ;LONG (2 BYTE) BRANCH + TXA + AND #3F + STA TEMP+LO + LDA #0 + STA TEMP+HI + JMP PREDB1 ;SIMULATE LONG BRANCH TO A CLOSE PLACE + + PREDLB: TXA ;STRIP OFF EXTRANEOUS JUNK + AND #3F + PHA + JSR NEXTPC ;GET SECOND BYTE + STA TEMP+LO + PLA + STA TEMP+HI + AND #20 ;CHECK SIGN + BEQ PREDB1 ;POSITIVE + LDA TEMP+HI + ORA #0C0 ;MAKE A FULL WORD NEG + STA TEMP+HI + PREDB1: LDA TEMP+HI + ORA TEMP+LO + BEQ RFALSE ;RETURN FALSE + SUBB TEMP,#1 + LDA TEMP+HI + ORA TEMP+LO + BEQ RTRUE + PREDB3: SUBB TEMP,#1 ;2 NOW SUBTRACTED FROM JUMP ADDRESS + LDA TEMP+HI ;COMPUTE A 17 BIT ADDRESS + STA VAL+LO ;HIGH ORDER 9 BITS IN VAL + ASL A ;EXTEND SIGN BIT + LDA #0 + ROL A + STA VAL+HI + LDA ZPCL ;ADD IN LOW ORDER 8 BITS (FROM TEMP+LO) + CLC + ADC TEMP+LO + BCC PREDB2 ;NO OVERFLOW + INCW VAL + PREDB2: STA ZPCL ;STORE LOW BYTE + LDA VAL+HI + ORA VAL+LO + BEQ PREDB4 ;NO CHANGE IN PAGE, DO FASTER JUMP + CLC + LDA VAL+LO + ADC ZPCH+LO ;MODIFY UPPER + STA ZPCH+LO + LDA VAL+HI + ADC ZPCH+HI + AND #1 + STA ZPCH+HI + LDA #0 + STA ZPCFLG ;CHANGED PAGES + PREDB4: RTS ;FINISHED \ No newline at end of file diff --git a/apple/oldzip/paging.z b/apple/oldzip/paging.z new file mode 100644 index 0000000..182f99c --- /dev/null +++ b/apple/oldzip/paging.z @@ -0,0 +1,205 @@ +O^u g% .TITLE "ZORK - PAGING ROUTINES" + .PAGE + + NEXTPC: LDA ZPCFLG ;HAS PAGE MOVED? + BEQ NXTPC1 ;PAGE HAS MOVED + LDY ZPCL + LDA @ZPCPNT,Y ;GET VALUE + INY ;UPDATE POINTER + STY ZPCL + BEQ $1 ;OK IF Y NOT ZERO + RTS + + $1 LDY #FALSE ;CROSSED 256 BYTE BOUNDARY + STY ZPCFLG ;BAD DATA IN PCPNT, +@; WILL HAVE TO FETCH NEW BLOCK + INCW ZPCH ;INCREMENT ZPC HIGH + RTS ;RETURN, TROUBLE NEXT TIME + + NXTPC1: LDA ZPCH+HI ;GET ZPAGE NUMBER + BNE NXTPCH + LDA ZPCH+LO + CMP ZMEMT ;TOP OF LOW MEM + BCC NXTPCL + NXTPCH MOVEW ZPCH,TEMP + JSR FNDPGE + STA ZPCPG ;STORE PAGE + BCS NXTPC2 ;COULD NOT FIND PAGE, SWAP IT IN + + NXTPC3: JSR SPLICE ;PUT AT TOP OF LIST + CLC + LDA ZPCPG ;SET UP POINTER TO PAGE + ADC ZMEMT ;POINTER TO BEGINNING OF PAGE BUFFERS + + NXTPCL: CLC + ADC ZCODEP+HI ;ADD IN OFFSET + STA ZPCPNT+HI + LDA #0 + STA ZPCPNT+LO ;ZPCPNT NOW HAS POINTER TO BEG OF BUFFER + LDA #TRUE + STA ZPCFLG + JMP NEXTPC ;TRY AGAIN, THIS TIME IT WILL NOT FAIL + + NXTPC2: CMP MPCPG ;CHECK IF DESTROYING MPC + BNE NXTPC4 ;NOT DESTROYING PAGE + LDA #FALSE + STA MPCFLG + + NXTPC4: MOVEW PGBUFP,TEMP + LDA ZPCPG + CLC + ADC TEMP+HI + STA TEMP+HI ;POINTER TO BEGINNING OF BUFFER + MOVEW ZPCH,VAL + JSR GETDSK + LDY ZPCPG + LDA ZPCH+LO + STA @PGTBL,Y ;SET PAGE TABLE ENTRY + LDA ZPCH+HI + STA @PGTBH,Y + TYA + JMP NXTPC3 ;PAGE NOW IN MEMORY + + SETWRD: LDA TEMP+LO + STA MPCL + LDA TEMP+HI + STA MPCH+LO + LDA #0 + STA MPCH+HI + SETWR1: LDA #FALSE + STA MPCFLG + RTS + + SETSTR: LDA TEMP+LO + ASL A + STA MPCL + LDA TEMP+HI + ROL A + STA MPCH+LO + LDA #0 + ROL A + STA MPCH+HI + JMP SETWR1 + + GETWRD JSR GETBYT + PHA + JSR GETBYT ;GET A FULL WORD + STA TEMP+ + PLA + STA TEMP+ + RTS + + GETBYT LDA MPCFLG ;HAS PAGE MOVED? + BEQ GETBT1 ;PAGE HAS MOVED + LDY MPCL + LDA @MPCPNT,Y ;GET VALUE + INY + STY MPCL ;STORE BACK POINTER + BEQ $1 ;OK IF Y NOT ZERO + RTS + + $1 LDY #FALSE ;CROSSED 256 BYTE BOUNDARY + STY MPCFLG ;BAD DATA IN PCPNT, +@; WILL HAVE TO FETCH NEW BLOCK + INCW MPCH ;INCREMENT MPC HIGH + RTS ;RETURN, TROUBLE NEXT TIME + + GETBT1 LDA MPCH+HI ;GET MPAGE NUMBER + BNE GETBTH + LDA MPCH+LO + GTBCMP .EQU *+1 ;PATCH LOCATION FOR VERIFY + CMP ZMEMT ;TOP OF LOW MEM + BCC GETBTL + GETBTH MOVEW MPCH,TEMP + JSR FNDPGE + STA MPCPG ;STORE PAGE + BCS GETBT2 ;COULD NOT FIND PAGE, SWAP IT IN + + GETBT3: JSR SPLICE ;PUT AT TOP OF LIST + CLC + LDA MPCPG ;SET UP POINTER TO PAGE + ADC ZMEMT ;POINTER TO BEGINNING OF PAGE BUFFERS + + GETBTL: CLC + ADC ZCODEP+HI ;ADD IN OFFSET + STA MPCPNT+HI + LDA #0 + STA MPCPNT+LO ;ZPCPNT NOW HAS POINTER TO BEG OF BUFFER + LDA #TRUE + STA MPCFLG + JMP GETBYT ;TRY AGAIN, THIS TIME IT WILL NOT FAIL + + GETBT2 CMP ZPCPG ;CHECK IF DESTROYING ZPC + BNE $1 + LDA #FALSE + STA ZPCFLG + $1 MOVEW PGBUFP,TEMP + LDA MPCPG + CLC + ADC TEMP+HI + STA TEMP+HI ;POINTER TO BEGINNING OF BUFFER + MOVEW MPCH,VAL + JSR GETDSK + LDY MPCPG + LDA MPCH+LO + STA @PGTBL,Y ;SET PAGE TABLE ENTRY + LDA MPCH+HI + STA @PGTBH,Y + TYA + JMP GETBT3 ;PAGE NOW IN MEMORY + + SPLICE CMP PGTOP ;SPLICE PAGE IN A TO TOP OF LIST + BEQ $1 + LDX PGTOP ;OLD TOP IN X + STA PGTOP ;NEW TOP + TAY + LDA @PGTBLF,Y ;OLD FORWARD POINTER + STA TEMP + TXA ;NEW FORWARD TO OLD TOP + STA @PGTBLF,Y + LDA @PGTBLB,Y ;GETS OLD BACK POINTER + STA TEMP+1 + LDA #0FF ;TOP HAS NO BACK + STA @PGTBLB,Y + LDY TEMP+1 + LDA TEMP + STA @PGTBLF,Y ;PATCH FORWARD POINTER + TXA + TAY + LDA PGTOP + STA @PGTBLB,Y + LDA TEMP + CMP #0FF + BEQ SPLIC1 ;WAS LAST BLOCK WITHOUT FORWARD POINTER + TAY + LDA TEMP+1 + STA @PGTBLB,Y ;SPLICE BACK POINTER + $1 RTS + + SPLIC1 LDA TEMP+1 + STA PGBOT ;NEW BOTTOM OF LIST + RTS + + FNDPGE LDX NPGS ;FIND PAGE IN TEMP, +@;RETURN WITH CARRY SET IF NOT FOUND. +@;A WILL HAVE FOUND PAGE +@;OR BOTTOM OF PAGE LIST + LDY #0 + LDA TEMP+LO + FNDPGL CMP @PGTBL,Y + BNE FNDPG2 ;NO MATCH + LDA TEMP+HI + CMP @PGTBH,Y + BEQ FNDPG1 ;SUCCESS + LDA TEMP+LO + FNDPG2 INY + DEX + BNE FNDPGL + LDA PGBOT ;NOT FOUND + SEC ;SET CARRY AND RETURN BOTTOM + RTS + + FNDPG1 TYA + CLC + RTS ;CLEAR CARRY AND RETURN + \ No newline at end of file diff --git a/apple/oldzip/random.z b/apple/oldzip/random.z new file mode 100644 index 0000000..b96327a --- /dev/null +++ b/apple/oldzip/random.z @@ -0,0 +1,229 @@ +O^u w# .TITLE "ZORK - RANDOM ROUTINES" + .PAGE + + MULT PUSHW MASK ;VAL.TEMP <= VAL * TEMP + MOVEI 0,MASK + LDX #16. ;LOOP COUNTER + MULT1 LDA VAL+LO + CLC + AND #1 ;CHECK BIT FOR ADD + BEQ MULT2 ;SKIP ADD PART IF 0 + LDA TEMP+LO ;ADD PART + ADC MASK+LO + STA MASK+LO + LDA TEMP+HI + ADC MASK+HI + STA MASK+HI + MULT2 ROR MASK+HI ;32 BIT SHIFT REMEMBERING CARRY + ROR MASK+LO + ROR VAL+HI + ROR VAL+LO + DEX + BNE MULT1 + MOVEW VAL,TEMP ;PUT LOW ORDER ANSWER IN TEMP + MOVEW MASK,VAL ;HIGH PART IN VAL + PULLW MASK + RTS + + DIVIDE PUSHW MASK ;TEMP<= TEMP/VAL, REMAINDER IN VAL + MOVEW TEMP,MASK + MOVEI 0,TEMP ;INITIAL VALUE FOR REMAINDER + LDX #17. ;INIT LOOP COUNTER + DDIV0 SEC ;SUB DIVIS + LDA TEMP+LO + SBC VAL+LO + TAY + LDA TEMP+HI + SBC VAL+HI + BCC DDIV1 ;UNDERFLOW, RETAIN TEMP + STA TEMP+HI + TYA + STA TEMP+LO + DDIV1 ROL MASK+LO ;4 REG SHIFT LEFT + ROL MASK+HI ;WITH CARRY + ROL TEMP+LO ;CARRY -> MASK -> TEMP + ROL TEMP+HI + DEX + BNE DDIV0 ;KEEP LOOKING + ;CLEANUP, SHIFT REMAINDER RIGHT AND RETURN IN VAL + CLC + LDA TEMP+HI + ROR A + STA VAL+HI + LDA TEMP+LO + ROR A + STA VAL+LO + MOVEW MASK,TEMP + PULLW MASK + RTS + + SIGNC LDA #0 + STA SIGNF ;SET SIGNF + LDA TEMP+HI + JSR SIGNPC ;POS CHECK + LDA VAL+HI + JSR SIGNPC + RTS + + SIGNS LDA SIGNF ;CHECK FOR SIGN + AND #1 ;EVEN OR ODD + BNE SIGNCN + RTS ;EVEN NUMBER OF NEGATIVES, ANSWER OK + + SIGNCN SEC ;CHANGE SIGN + LDA #0 + SBC TEMP+LO + STA TEMP+LO + LDA #0 + SBC TEMP+HI + STA TEMP+HI ;INVERTED TEMP + RTS + + SIGNPC ORA #0 + BMI $1 + RTS ;POSITIVE + $1 INC SIGNF + JMP SIGNCN ;CHANGE SIGN + + FLAGSU LDA ARG1 ;SETUP FOR FLAG ROUTINES + JSR OBJLOC ;MASK WILL HAVE BIT POSITION, VAL FLAG VALUE + LDA ARG2 ;TEMP WILL GET OBJ POINTER + CMP #16. + BCC FLGSU1 ;NEXT WORD + SEC ;SECOND SET OF FLAGS + SBC #16. + INCW TEMP + INCW TEMP + FLGSU1 STA VAL + MOVEI 1,MASK + LDA #15. + SEC + SBC VAL + TAX + FLGSU2 BEQ FLGSU3 ;BIT IN POSITION + ASL MASK+LO + ROL MASK+HI + DEX + JMP FLGSU2 + + FLGSU3 LDY #0 + LDA @TEMP,Y + STA VAL+ + INY + LDA @TEMP,Y + STA VAL+ + RTS + + PROPB LDA ARG1 ;BEG OF PROPERTY PART OF OBJECT + JSR OBJLOC + LDY #7 + LDA @TEMP,Y + STA VAL+ + INY + LDA @TEMP,Y + STA VAL+ + CLC + LDA VAL+LO + ADC ZCODEP+LO + STA TEMP+LO + LDA VAL+HI + ADC ZCODEP+HI + STA TEMP+HI + LDY #0 + LDA @TEMP,Y ;LENGTH OF DESCRIPTION + ASL A + TAY + INY + RTS ;RETURN WITH INDEX + + PROPN LDA @TEMP,Y ;TEMP(Y) HAS REAL PROP POINTER + AND #1F + RTS + + PROPL LDA @TEMP,Y ;PROP LENGTH, TEMP(Y) HAS REAL PROP POINTER + ROR A ROR A + ROR A + ROR A + ROR A + AND #7 + RTS + + PROPNX JSR PROPL + TAX + $1 INY + DEX + BPL $1 + INY + RTS + + OBJLOC STA TEMP+LO + LDA #0 + STA TEMP+HI + LDA TEMP+LO + ASL TEMP+LO + ROL TEMP+HI + ASL TEMP+LO + ROL TEMP+HI + ASL TEMP+LO + ROL TEMP+HI + CLC + ADC TEMP+LO + BCC $1 + INC TEMP+HI + CLC + $1 ADC #53. ;9*NUMBER + 53. + STA TEMP+LO + BCC $2 + INC TEMP+HI + $2 LDY #ZOBJEC+ + LDA @ZCODEP,Y + CLC + ADC TEMP+LO + STA TEMP+LO + NEXT + LDA @ZCODEP,Y + ADC TEMP+HI + ADC ZCODEP+HI + STA TEMP+HI ;REAL ADDRESS + RTS + + SHLGED LDA VAL+HI + EOR TEMP+HI + BPL HLGEDE ;BOTH OF SAME SIGN + LDA VAL+HI + CMP TEMP+HI ;CARRY WILL BE SET IF VAL NEG AND THUS < TEMP + RTS + + HLGEDE LDA TEMP+HI ;RETURN WITH CARRY SET IF TEMP >= VAL + CMP VAL+HI + BNE $1 + LDA TEMP+LO + CMP VAL+LO + $1 RTS + + PSHSTK SUBB ZSTAKP,#1 ;PUSH STACK + LDY #0 + LDA TEMP+ + STA @ZSTAKP,Y + SUBB ZSTAKP,#1 + LDA TEMP+ + STA @ZSTAKP,Y + INC ZSTAKC ;COUNT + LDA ZSTAKC + CMP #ZSTAKL + BCC $1 + JSR ZER + $1 RTS + + POPSTK LDY #0 + LDA @ZSTAKP,Y + STA TEMP+ + INCW ZSTAKP + LDA @ZSTAKP,Y + STA TEMP+ + INCW ZSTAKP + DEC ZSTAKC ;CHECK COUNT + BNE $1 + JSR ZER ;OVER POP ERROR + $1 RTS ;VALUE IN TEMP + \ No newline at end of file diff --git a/apple/oldzip/string.z b/apple/oldzip/string.z new file mode 100644 index 0000000..a21ddab --- /dev/null +++ b/apple/oldzip/string.z @@ -0,0 +1,324 @@ +O^ q$.TITLE "ZORK - STRING ROUTINES" + .PAGE + + PZSTR LDA #0 ;PRINT STRING POINTED TO BY MPC + STA CSPERM ;PERMANENT MODE + STA STBYTF ;STRING BYTE FLAG + LDA #0FF + STA CSTEMP ;NO TEMP IN EFFECT + PZSTRL JSR GETZCH + BCC $1 + RTS ;END OF STRING + $1 STA MASK + BEQ PZSTRS ;SPACE + CMP #4 + BCC PZSTRF ;FWORD + CMP #6 + BCC PZSTRT ;SET NEW MODE + JSR GETMOD + ORA #0 + BNE PZSTR1 ;NOT SET 0 + LDA #61-6 ;LOWER CASE "a" - 6 + PZSTP0 CLC + ADC MASK + PZSTP1 JSR COUT + JMP PZSTRL + + PZSTR1 CMP #1 ;CHECK FOR SET 1 OR 2 + BNE PZSTR2 ;SET 2 + LDA #41-6 ;UPPER CASE "A" - 6 + JMP PZSTP0 + + PZSTR2 LDA MASK ;MODE 2 + SEC + SBC #7 ;CHECK FOR ASCII CHARACTER + BCC PZSTRA + BEQ PZSTRC ;OR CR-LF + TAY + DEY + LDA CHRTBL,Y ;GET CHARACTER FROM TABLE + JMP PZSTP1 + + PZSTRA JSR GETZCH ;FORM CHARACTER FROM TWO BYTES + ASL A + ASL A + ASL A + ASL A + ASL A + PHA + JSR GETZCH + STA MASK + PLA + ORA MASK + JMP PZSTP1 ;PRINT IT + + PZSTRS LDA #20 + JMP PZSTP1 ;PRINT SPACE + + PZSTRC LDA #0D ;CR-LF + JSR COUT + LDA #0A + JMP PZSTP1 + + PZSTRT SEC + SBC #3 ;CALCULATE NEW MODE + TAY + JSR GETMOD ;CURRENT MODE IS 0? + BNE PZSTRP ;NO, DO PERM SHIFT + STY CSTEMP ;YES, JUST DO TEMP SHIFT + JMP PZSTRL + + PZSTRP STY CSPERM ;DO A PERMANENT SHIFT + CMP CSPERM ;NEW MODE SAME AS CURRENT ONE? + BEQ $1 ;YES + LDY #0 ;NO, SHIFT TO MODE 0 + STY CSPERM + $1 JMP PZSTRL + + PZSTFO .BYTE 0 ;FWORD TABLE BLOCK OFFSET + + PZSTRF SEC ;CALCULATE BLOCK OFFSET + SBC #1 + ASL A + ASL A + ASL A + ASL A + ASL A + ASL A + STA PZSTFO ;SAVE FOR LATER + JSR GETZCH ;PRINT FREQUENCY WORD + ASL A + ADC # + ADC PZSTFO ;USE PROPER WORD BLOCK + TAY + LDA @FWORDS,Y + STA TEMP+LO + NEXT + LDA @FWORDS,Y + STA TEMP+HI + LDA CSPERM + PHA + LDA STBYTF + PHA + PUSHW ZSTWRD + LDA MPCL + PHA + PUSHW MPCH + JSR SETSTR + JSR PZSTR + PULLW MPCH + PLA + STA MPCL + MOVE #0,MPCFLG + PULLW ZSTWRD + PLA + STA STBYTF + PLA + STA CSPERM + LDA #0FF + STA CSTEMP + JMP PZSTRL + + CHRTBL .ASCII "0123456789.,!?_#'" + .BYTE 22 ;ASCII " + .ASCII "/\-:()" + + GETMOD LDA CSTEMP + BPL $1 + LDA CSPERM + RTS ;RETURN WITH PERM MODE IF NO TEMP MODE + $1 LDY #0FF + STY CSTEMP ;CLEAR MODE AFTER GETTING IT + RTS + + GETZCH LDA STBYTF ;FIND OUT WHICH BYTE + BPL $1 + SEC + RTS ;OUT OF CHARACTERS + $1 BNE GETZH1 ;NOT FIRST BYTE + INC STBYTF + JSR GETWRD + MOVEW TEMP,ZSTWRD ;SAVE WORD + LDA ZSTWRD+HI + LSR A + LSR A + AND #1F + CLC + RTS + + GETZH1 SEC + SBC #1 + BNE GETZH2 ;LAST CHAR IN WORD + LDA #2 + STA STBYTF + LDA ZSTWRD+HI ;SHIFT OVER RIGHTMOST BIT + LSR A + LDA ZSTWRD+LO + ROR A + TAY + LDA ZSTWRD+HI ;SHIFT OVER NEXT TO RIGHTMOST + LSR A + LSR A + TYA + ROR A + LSR A ;SHIFT FIVE BIT FIELD OVER 3 PLACES + LSR A + LSR A + AND #1F + CLC + RTS + + GETZH2 LDA #0 + STA STBYTF + LDA ZSTWRD+HI + BPL GETZH3 ;NOT LAST CHAR IN STRING + LDA #0FF + STA STBYTF ;INDICATE END OF STRING + GETZH3 LDA ZSTWRD+LO + AND #1F + CLC + RTS + + ;CONVERT TO ZSTRING + CONZST LDX #0 ;POINTER TO OUTPUT BUFFER (ZSTBUO) + LDY #6 ;OUTPUT 6 CHARACTERS TO CONVERT + CONZSL LDA #5 + STA ZSTBUO,X + INX + DEY + BNE CONZSL ;FILL BUFFER WITH PAD CHARACTERS + LDA #6 + STA MASK+HI + LDA #0 + STA VAL ;OUTPUT + STA TEMP ;INPUT + CNZSL1 LDX TEMP + INC TEMP + LDA ZSTBUI,X + STA MASK+LO + BNE CNZSL2 + LDA #5 + JMP CNZSLO ;BLANKS + + CNZSL2 LDA MASK+LO + JSR ZCHRCS ;WHICH CHARACTER SET + ORA #0 ;HAS CHARACTER SET OF CURRENT CHAR + BEQ CNZSLC ;IF CS 0, JUST CONVERT THEN OUTPUT + CLC ;ELSE, DO A TEMP SHIFT + ADC #3 + LDX VAL + STA ZSTBUO,X ;OUTPUT TEMP SHIFT + INC VAL + DEC MASK+HI + BNE CNZSLC + JMP CNZSLE + + CNZSLC LDA MASK+LO + JSR ZCHRCS + SEC + SBC #1 + BPL CNZSC1 ;NOT LOWER CASE + LDA MASK+LO + SEC + SBC #5B ;(ASCII A) - 6 + CNZSLO LDX VAL + STA ZSTBUO,X + INC VAL + DEC MASK+HI + BEQ $1 + JMP CNZSL1 ;NEXT + $1 JMP CNZSLE ;END + + CNZSC1 BNE CNZSC3 ;NOT UPPER CASE + LDA MASK+LO + SEC + SBC #3B ;(ASCII A) - 6 + JMP CNZSLO + + CNZSC3 LDA MASK+LO + JSR CNZS2M + BNE CNZSLO ;FOUND IN TABLE + LDA #6 + LDX VAL + STA ZSTBUO,X + INC VAL + DEC MASK+HI + BEQ CNZSLE ;STORE ASCII VERSION + LDA MASK+LO + LSR A + LSR A + LSR A + LSR A + LSR A + AND #3 + LDX VAL + STA ZSTBUO,X + INC VAL + DEC MASK+HI + BEQ CNZSLE + LDA MASK+LO + AND #1F + JMP CNZSLO + + CNZS2M LDX #24 ;SEARCH TABLE CNZS2L CMP CHRTBL,X + BEQ CNZS2P ;FOUND + DEX + BPL CNZS2L + LDY #0 ;NOT FOUND + RTS ;FAIL, ZERO SET + + CNZS2P TXA + CLC + ADC #8 + RTS ;PASSED, ZERO CLEARED + + ZCHRCS CMP #61 ;ASCII LOWER a + BCC ZCHRC1 + CMP #7B ;(ASCII LOWER z) + 1 + BCS ZCHRC1 + LDA #0 + RTS ;SET 0 + + ZCHRC1 CMP #41 ;ASCII UPPER A + BCC ZCHRC2 + CMP #5B ;(ASCII UPPER Z) + 1 + BCS ZCHRC2 + LDA #1 + RTS + + ZCHRC2 ORA #0 + BEQ $1 + BMI $1 ;END + LDA #2 ;ELSE SET 2 + $1 RTS + + CNZSLE LDA ZSTBUO+1 ;CONVERT OUTPUT STRING + ASL A ;LEFT JUSTIFY SECOND BYTE + ASL A + ASL A + ASL A ;SHIFT TWO BITS ONTO RIGHT END OF FIRST BYTE + ROL ZSTBUO + ASL A + ROL ZSTBUO + LDX ZSTBUO ;PLACE FIRST/SECOND BYTE INTO FINAL HOME + STX ZSTBUO+HI + ORA ZSTBUO+2 ;COMBINE REST OF SECOND BYTE WITH THIRD + STA ZSTBUO+LO + LDA ZSTBUO+4 ;DO SECOND TRIPLET OF BYTES + ASL A ;LEFT JUSTIFY SECOND BYTE + ASL A + ASL A + ASL A ;SHIFT TWO BITS ONTO RIGHT END OF FIRST BYTE + ROL ZSTBUO+3 + ASL A + ROL ZSTBUO+3 + LDX ZSTBUO+3 ;PLACE FIRST/SECOND BYTE INTO FINAL HOME + STX ZSTBUO+2+HI + ORA ZSTBUO+5 ;COMBINE REST OF SECOND BYTE WITH THIRD + STA ZSTBUO+2+LO + LDA ZSTBUO+2+HI ;SET SIGN BIT OF SECOND TRIPLET + ORA #80 + STA ZSTBUO+2+HI + RTS + + \ No newline at end of file diff --git a/apple/oldzip/z.z b/apple/oldzip/z.z new file mode 100644 index 0000000..74bd4c3 --- /dev/null +++ b/apple/oldzip/z.z @@ -0,0 +1,334 @@ + .NOLIST + .TITLE "ZORK FOR THE APPLE II" + + ;Split screen mod finished and transfered to 20 on Feb. 14th 1984 + ;NOTE: Apple Zip can extend to + ;23FF if necessary without any + ;changes to CREATE, etc. + .ABSOLUTE + + .PROC ZORK + + THEEND .EQU 2E00 ;Should be just past end of code + RWTS + ;*** NOTE: Modified FROM 2C00 to 2E00 on + ;10/27/83 See Apple IIe Zip Notebook + + TRUE .EQU 0FF + FALSE .EQU 0 + + LO .EQU 0 ;MACHINE HAS LOW-BYTE|HIGH-BYTE + HI .EQU 1 + INVERT .EQU 1 ;INVERT LSB & MSB (FROM SENSE OF 6502)? + + SMALLD .EQU FALSE ;NO SMALL DISKS ON AN APPLE + + .MACRO NEXT + .IF %1 +0INY + .ELSE +0DEY + .ENDC + .ENDM + + ;INIT VALUES + ZVERS .EQU 0 + ZSWAP .EQU 1 + ZID .EQU 2 + ZENDLD .EQU 4 + ZSTART .EQU 6 + ZVOCAB .EQU 8 + ZOBJEC .EQU 10. + ZGLOBA .EQU 12. + ZPURBT .EQU 14. + ZSCRIP .EQU 16. + ZFWORD .EQU 24. + ZLENTH .EQU 26. + ZCHKSM .EQU 28. + + ;GLOBALS FOR WHOLIN + ROOMG .EQU 10 + MOVESG .EQU 12 + SCOREG .EQU 11 + + ;********** Definition of Zero Page data locations ********** + + ZPGOFF .EQU 80 ;placed here away from APPLE II Monitor + + INSOFF .EQU ZPGOFF + OPCODE .EQU INSOFF ;Byte = CURRENT OPCODE + ARGCNT .EQU INSOFF+1 ;Byte = ARG COUNT + ARG1 .EQU INSOFF+2 ;Word = OPERAND 1 + ARG2 .EQU INSOFF+4 ;Word = " 2 + ARG3 .EQU INSOFF+6 ;Word = " 3 + ARG4 .EQU INSOFF+8 ;Word = " 4 + + ZPCOFF .EQU INSOFF+0A + ZPCL .EQU ZPCOFF ;Byte = LOW ORDER 8 BITS OF ZPC + ZPCH .EQU ZPCOFF+1 ;Word = HIGH ORDER 9 BITS OF ZPC + ZPCPNT .EQU ZPCOFF+3 ;Word = REAL POINTER TO PC page + ZPCFLG .EQU ZPCOFF+5 ;Byte = TRUE IF VALID PC POINTER + ZPCPG .EQU ZPCOFF+6 ;Byte = PAGE OF ZPC + + MPCOFF .EQU ZPCOFF+7 + MPCH .EQU MPCOFF ;Word = HIGH ORDER 8 BITS OF MEMORY POINTER + MPCL .EQU MPCOFF+2 ;Byte = LOW ORDER 8 BITS OF MEMORY POINTER + MPCPNT .EQU MPCOFF+3 ;Word = REAL POINTER TO MEMORY LOCATION + MPCFLG .EQU MPCOFF+5 ;Byte = TRUE IF VALID MPCPNT + MPCPG .EQU MPCOFF+6 ;Byte = PAGE NUMBER OF PC PAGE + + VAROFF .EQU MPCOFF+7 + GLOBAL .EQU VAROFF ;Word = POINTER TO GLOBALS + LOCALS .EQU VAROFF+2 ;15 Words = STORAGE FOR LOCALS + + PTVOFF .EQU VAROFF+32. ;page tables variables + PGBUFP .EQU PTVOFF ;Word = BUFFER POINTER + ZCODEP .EQU PTVOFF+2 ;Word = LOW MEM STARTING POINTER + ZMEMT .EQU PTVOFF+4 ;Byte = FIRST PAGE IN SWAPPING SPACE + NPGS .EQU PTVOFF+5 ;Byte = NUMBER OF PAGES + PGTOP .EQU PTVOFF+6 ;Byte = TOP OF LIST PAGE + PGBOT .EQU PTVOFF+7 ;Byte = BOTTOM OF LIST + PGTBL .EQU PTVOFF+8 ;Word = ptr to PAGE NUMBERS, -1 IMPLIES FREE + PGTBH .EQU PTVOFF+10. ;Word = ptr to PAGE HIGH BIT + PGTBLF .EQU PTVOFF+12. ;Word = ptr to NEXT LINKS, -1 IMPLIES END + PGTBLB .EQU PTVOFF+14. ;Word = ptr to PREVIOUS LINKS + MAXPGS .EQU 80 + PGTOFF .EQU 2C00 ;Where the page tables are placed, pgs 8 & 9 +@;*** NOTE: Page tables relocated 10/27/83 +@;to make more room for interp + + STKOFF .EQU PTVOFF+16. + ZSTAKL .EQU 224. ;LENGTH OF ZSTACK (in words) + ZSTACK .EQU 0228 ;ZSTACK, most of pg 2 and most of pg 3 + ZSTAKC .EQU STKOFF ;Byte = STACK COUNT, 1=>O IMPLIES OVERPOP, + ZSTAKP .EQU STKOFF+1 ;Word = POINTER TO CURRENT STACK + OZSTKP .EQU STKOFF+3 ;Word = OLD ZSTACK POINTER + OZSTKC .EQU STKOFF+5 ;Byte = OLD ZSTACK COUNT + + STROFF .EQU STKOFF+6 + CSTEMP .EQU STROFF ;Byte = 0FF IF NOT TEMP CHAR SET, ELSE SET + CSPERM .EQU STROFF+1 ;Byte = PERM CHARACTER SET + STBYTF .EQU STROFF+2 ;Byte = 0 FOR FIRST BYTE, 1 FOR 2, +@;2 FOR 3, 0FF FOR END. + ZSTWRD .EQU STROFF+3 ;Word = WORD STORAGE + ZSTBUI .EQU STROFF+5 ;6 Bytes = ZSTR INPUT BUFFER +@;Byte = End Marker (0FF) + ZSTBUO .EQU STROFF+12. ;6 Bytes = OUTPUT BUFFER + RTABP .EQU STROFF+18. ;Byte = TEMP FOR ZREAD, RESULT TABLE POINTER + STABP .EQU STROFF+19. ;Byte = TEMP FOR ZREAD, SOURCE TABLE POINTER + FWORDS .EQU STROFF+20. ;Word = Pointer to FWORDS table + + XTROFF .EQU STROFF+22. + VAL .EQU XTROFF ;Word = Value Return location (DE) + TEMP .EQU XTROFF+2 ;Word = Temp storage location (HL) + MASK .EQU XTROFF+4 ;Word = bit mask location (BC) + SIGNF .EQU XTROFF+6 ;Byte = STORAGE FOR SIGN IN MULT AND DIVIDE + + MACOFF .EQU XTROFF+7 + CHRPNT .EQU MACOFF ;Byte = POINTER INTO COUT BUFFER + CPSAV .EQU MACOFF+1 ;Byte = SAVED VERSION OF CHRPNT + LINCNT .EQU MACOFF+2 ;Byte = COUNT OF LINES OUTPUT + ALTCSW .EQU MACOFF+3 ;Word = SCRIPT OUTPUT SWITCH + PCSAV .EQU MACOFF+5 ;3Bytes = saved ZPC from MLOOP + TIMEFL .EQU MACOFF+8. ;BYTE = TRUE IF TIME MODE FOR WHOLINE + + .IF &0FF00 ;OVERFLOWED ZERO PAGE? + ERROR! ;ZERO PAGE OVERFLOW + .ENDC + + .PAGE + ;******************** MACRO DEFINITIONS ******************** + + + ; - - - - - - - - - - - - - - - - - + ; move byte from location or immediate %1 to location %2 + + .MACRO MOVE + LDA %1 + STA %2 + .ENDM + + ; - - - - - - - - - - - - - - - - - + ; move word from location %1 to location %2 + + .MACRO MOVEW + LDA %1 + STA %2 + LDA %1+1 + STA %2+1 + .ENDM + + ; - - - - - - - - - - - - - - - - - + ; move word from immediate %1 to location %2 + + .MACRO MOVEI + LDA #1*%1&0FF + STA %2 + LDA #1*%1/100 + STA %2+1 + .ENDM + + + ; - - - - - - - - - - - - - - - - - + ; pushes word from location %1 onto stack + + .MACRO PUSHW + LDA %1 + PHA + LDA %1+1 + PHA + .ENDM + + ; - - - - - - - - - - - - - - - - - + ; pop word from stack into location %1 + + .MACRO PULLW + PLA + STA %1+1 + PLA + STA %1 + .ENDM + + ; - - - - - - - - - - - - - - - - - + ; increments word at location %1 + + .MACRO INCW + INC %1 + BNE *+4 + INC %1+1 + .ENDM + + ; - - - - - - - - - - - - - - - - - + ; adds to the word at location %1 the byte or immediate %2 + + .MACRO ADDB + LDA %1 + CLC + ADC %2 + STA %1 + BCC *+4 + INC %1+1 + .ENDM + + ; - - - - - - - - - - - - - - - - - + ; subtracts from the word at location %1 the byte or immediate %2 + + .MACRO SUBB + LDA %1 + SEC + SBC %2 + STA %1 + BCS *+4 + DEC %1+1 + .ENDM + + + .ORG 0800 ;Starting Address of Zork Interpreter Code + + + .INCLUDE INIT.TEXT + + + .TITLE "ZORK - OPCODE DISPATCH TABLES" + .PAGE + + OP0T: .WORD RTRUE + .WORD RFALSE + .WORD PRINTI + .WORD PRINTR + .WORD ZNOP + .WORD SAVE + .WORD RESTOR + .WORD RESTAR + .WORD RSTACK + .WORD POPSTK + .WORD QUIT + .WORD CRLF + .WORD WHOLIN + .WORD VERIFY + OP0M .EQU *-OP0T/2 + + OP1T: .WORD ZEROP + .WORD NEXTP + .WORD FIRSTP + .WORD LOC + .WORD PTSIZE + .WORD INC1 + .WORD DEC1 + .WORD PRINTB + .WORD ZER + .WORD REMOVC + .WORD PRINTD + .WORD RETURN + .WORD JUMP + .WORD PRINT + .WORD VALUE + .WORD BCOM + OP1M .EQU *-OP1T/2 + + OP2T: .WORD ZER + .WORD EQUALP + .WORD LESSP + .WORD GRTRP + .WORD DLESSP + .WORD IGRTRP + .WORD INP + .WORD BTST + .WORD BOR + .WORD BAND + .WORD FSETP + .WORD FSET + .WORD FCLEAR + .WORD ZSET + .WORD ZMOVE + .WORD GET + .WORD GETB + .WORD GETP + .WORD GETPT + .WORD NXTP + .WORD ZADD + .WORD ZSUB + .WORD MUL + .WORD DIV + .WORD ZMOD + OP2M .EQU *-OP2T/2 + + OPXT: .WORD ZCALL + .WORD PUT + .WORD PUTB + .WORD PUTP + .WORD ZREAD + .WORD PRINTC + .WORD PRINTN + .WORD RANDOM + .WORD ZPUSH + .WORD ZPOP + .WORD SPLIT + .WORD SCREN + + OPXM .EQU *-OPXT/2 + + ;********************************************************************** + ;******************** MAIN BODY OF ZORK CODE ******************** + + .INCLUDE MAIN.TEXT + + .INCLUDE 0.OPS.TEXT + + .INCLUDE 1.OPS.TEXT + + .INCLUDE 2.OPS.TEXT + + .INCLUDE EXT.OPS.TEXT + + .INCLUDE RANDOM.TEXT + + .INCLUDE PAGING.TEXT + + .INCLUDE STRING.TEXT + + .INCLUDE MACH1.DEP.TEXT + + .INCLUDE MACH2.DEP.TEXT + + .END + \ No newline at end of file diff --git a/apple/read.me b/apple/read.me new file mode 100644 index 0000000..414baa1 --- /dev/null +++ b/apple/read.me @@ -0,0 +1,20 @@ +******* Directory Update and Source File Archive Record ****** + +NOTE: THIS DIRECTORY CONTAINS OLD! APPLE ZIP SOURCE FILES (.Z), NEW + APPLE ZIP FILES (.ASM), APPLE EZIP FILES (.EZIP-n), AND + APPLE DIP FILES (.DIP-Bn) + + Date of Last Change Version Letter Who Made the Change + ___________________ _____________ ____________________ + +1) 3/12/85 E (.ASM FILES) Le +2) 4/9/85 C (NEW NUMBERING) Le +3) 5/8/85 E " Le +4) 5/16/85 F Le +5) 7/26/85 G Le +6) 9/19/85 H, F WITH G FIXES (SPELLBREAKER)(48K) Le +7) EZIP-DEC SRCS, A Le +8) 3/24/86 EZIP B Le +9) 5/19/86 NEW & IMPROVED EZIP B Le + +10) 11/13/87 New XZIP & EZIP JDA diff --git a/apple/xzip/_read.me b/apple/xzip/_read.me new file mode 100644 index 0000000..acde851 --- /dev/null +++ b/apple/xzip/_read.me @@ -0,0 +1,7 @@ + Xzip on the Apple is the first 6502 machine to have its sources +on the IBM running under the 2500AD cross assembler. + + Version Date By + +1) A 3/13/87 LSD +2) A 11/11/87 JDA diff --git a/apple/xzip/bas.cmd b/apple/xzip/bas.cmd new file mode 100644 index 0000000..2d0d717 --- /dev/null +++ b/apple/xzip/bas.cmd @@ -0,0 +1,5 @@ +load"send" +run +g + + \ No newline at end of file diff --git a/apple/xzip/bugger.asm b/apple/xzip/bugger.asm new file mode 100644 index 0000000..bde7b6e --- /dev/null +++ b/apple/xzip/bugger.asm @@ -0,0 +1,257 @@ + PAGE + SBTTL "--- DEBUGGER: APPLE ---" + + ; -------------- + ; APPLE DEBUGGER + ; -------------- + + ; ENTRY: BREAKPOINT ID IN [A] + + ; SMALL DEBUGGER DBG1 (CONVERTS) DBG2 (JUST DISPLAYS) [A] + +DLCNT: DB 0 + +DBG1: + INC DLCNT + BNE DBG1m + PHA + JSR GETKEY + PLA +DBG1m: + PHA + LSR A + LSR A + LSR A + LSR A + JSR NIB1 + PLA + +NIB1: AND #%00001111 + TAY + LDA HCHARS,Y + JSR MCOUT + RTS + +DBG2: +; CMP #' ' +; BEQ DBG3 +; JSR MCOUT +; LDA #' ' +DBG3: JSR MCOUT + RTS + +HCHARS: DB "0123456789ABCDEF" + + END + +BLINE: DB "B: OP: PC: S: V: 1: 2: 3: 4: 5: 6: 7: 8: 9: " + DB EOL +BLINL EQU $-BLINE + +BUGLIN EQU LSTLNE + +DOBUG: LDX KBD ; WAS CTRL-S PRESSED? + CPX #$13 + BNE DO1 + RTS ; YES, SO LEAVE + +DO1: CMP #0 + BEQ BUGIT + RTS + + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + +BUGIT: LDX #2 ; INIT "CURSOR" + 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 BLINE,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 [ZSP] + LDA ZSP + JSR HEX + + LDX #29 ; CURSOR FOR [MPC] + LDA MPCH + JSR HEX + LDA MPCM + JSR HEX + LDA MPCL + JSR HEX + + LDX #38 + LDA BONE + JSR HEX + + LDX #43 + LDA BTWO + JSR HEX + + LDX #48 + LDA BTHREE + JSR HEX + + LDX #53 + LDA BFOUR + JSR HEX + + LDX #58 + LDA BFIVE + JSR HEX + + LDX #63 + LDA BSIX + JSR HEX + + LDX #68 + LDA BSEVEN + JSR HEX + + LDX #73 + LDA BEIGHT + JSR HEX + + LDX #78 + LDA BNINE + JSR HEX + +; TO SEND TO PRINTER IF WANTED +; LDA CSW+LO +; PHA +; LDA CSW+HI +; PHA +; LDA EH +; PHA +; LDA ALTCSW+LO +; STA CSW+LO +; LDA ALTCSW+HI +; STA CSW+HI +; +; LDA PSTAT +; BNE PPP +; +; LDA #$C1 +; STA CSW+HI +; LDA #$00 +; STA CSW+LO +; +; LDA #$89 +; JSR MCOUT +; LDA CSW+HI +; STA ALTCSW+HI +; LDA CSW+LO +; STA ALTCSW+LO +; LDA #$B8 +; JSR MCOUT +; LDA #$B0 +; JSR MCOUT +; LDA #$CE +; JSR MCOUT +; LDA #$8D +; JSR MCOUT + +PPP: LDX #2 +DBUG1: LDA BLINE,X ; PRINT DEBUGGER TEXT +; JSR MCOUT + JSR CHAR + INX + CPX #BLINL + BCC DBUG1 + +; PLA +; STA EH +; PLA +; STA CSW+HI +; PLA +; STA CSW+LO + +; BIT KBD +; BPL LETEX ; NO KEY PRESSED + + BIT ANYKEY ; CLEAR IT +BUGWAT: BIT KBD ; WAIT FOR A KEY + BPL BUGWAT + + LDA KBD + CMP #$8D + BNE LETEX + BRK + +LETEX: BIT ANYKEY ; CLEAR FOR NEXT ONE + 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 + ORA #%10000000 + STA BLINE,X + INX + RTS + +HCHARS: DB "0123456789ABCDEF" + +BONE: DB 0 +BTWO: DB 0 +BTHREE: DB 0 +BFOUR: DB 0 +BFIVE: DB 0 +BSIX: DB 0 +BSEVEN: DB 0 +BEIGHT: DB 0 +BNINE: DB 0 + + END + + \ No newline at end of file diff --git a/apple/xzip/cold.asm b/apple/xzip/cold.asm new file mode 100644 index 0000000..0a45439 --- /dev/null +++ b/apple/xzip/cold.asm @@ -0,0 +1,56 @@ + PAGE + STTL "--- MACHINE COLDSTART: APPLE II ---" + + ; --------- + ; COLDSTART + ; --------- + + +SIG: DB 0 ; IIc FLAG +STRYSL: DB 0 ; BOOT SLOT +STRYDR: DB 0 ; BOOT DRIVE + + ; FINISH LOADING THE ZIP + +COLD: + LDA BSLOT ; SET UP + STA DCBSLT ; CURRENT AND + STA DCBPSL ; PREVIOUS SLOT IDS + + LDA #>MCOUT1 ; SET SCREEN OUTPUT (X) + STA CSW+HI ; IN CASE OF PR#6 + LDA #ZRTRUE ;B0 + DB >ZRFALS ;B1 + DB >ZPRI ;B2 + DB >ZPRR ;B3 + DB >ZNOOP ;B4 + DB >OSAVE ;B5 + DB >OREST ;B6 + DB >ZSTART ;B7 + DB >ZRSTAK ;B8 + DB >ZCATCH ;B9 + DB >ZQUIT ;BA + DB >ZZCRLF ;BB + DB >ZUSL ;BC + DB >ZVER ;BD + DB >ZEXTOP ;BE + DB >ZORIG ;BF + +OPT0L: DB ZZERO ;80,90,A0 + DB >ZNEXT ;81 + DB >ZFIRST ;82 + DB >ZLOC ;83 + DB >ZPTSIZ ;84 + DB >ZINC ;85 + DB >ZDEC ;86 + DB >ZPRB ;87 + DB >ZCALL1 ;88 (EZIP) + DB >ZREMOV ;89 + DB >ZPRD ;8A + DB >ZRET ;8B + DB >ZJUMP ;8C + DB >ZPRINT ;8D + DB >ZVALUE ;8E + DB >ZICLL1 ;8F + +OPT1L: DB BADOP2 ;00 (UNDEFINED) + DB >ZEQUAL ;01 + DB >ZLESS ;02 + DB >ZGRTR ;03 + DB >ZDLESS ;04 + DB >ZIGRTR ;05 + DB >ZIN ;06 + DB >ZBTST ;07 + DB >ZBOR ;08 + DB >ZBAND ;09 + DB >ZFSETP ;0A + DB >ZFSET ;0B + DB >ZFCLR ;0C + DB >ZSET ;0D + DB >ZMOVE ;0E + DB >ZGET ;0F + DB >ZGETB ;10 + DB >ZGETP ;11 + DB >ZGETPT ;12 + DB >ZNEXTP ;13 + DB >ZADD ;14 + DB >ZSUB ;15 + DB >ZMUL ;16 + DB >ZDIV ;17 + DB >ZMOD ;18 + DB >ZCALL2 ;19 (EZIP) + DB >ZICLL2 ;1A + DB >ZCOLOR ;1B + DB >ZTHROW ;1C + DB >BADOP2 ;1D + DB >BADOP2 ;1E + DB >BADOP2 ;1F + +OPT2L: DB ZCALL ;E0 + DB >ZPUT ;E1 + DB >ZPUTB ;E2 + DB >ZPUTP ;E3 + DB >ZREAD ;E4 + DB >ZPRC ;E5 + DB >ZPRN ;E6 + DB >ZRAND ;E7 + DB >ZPUSH ;E8 + DB >ZPOP ;E9 + DB >ZSPLIT ;EA + DB >ZSCRN ;EB + + ; (EZIPS FROM HERE ON) + DB >ZXCALL ;EC + DB >ZCLR ;ED + DB >ZERASE ;EE + DB >ZCURST ;EF + DB >ZCURGT ;F0 (NOT IMPLEMENTED) + DB >ZLIGHT ;F1 + DB >ZBUFOUT ;F2 + DB >ZDIRT ;F3 + DB >ZDIRIN ;F4 (NOT IMPLEMENTED) + DB >ZSOUND ;F5 + DB >ZINPUT ;F6 + DB >ZINTBL ;F7 + DB >ZBCOM ;F8 + DB >ZICALL ;F9 + DB >ZIXCLL ;FA + DB >ZLEX ;FB + DB >ZWSTR ;FC + DB >ZCOPYT ;FD + DB >ZPRNTT ;FE + DB >ZASSND ;FF + +OPTXL: DB ZSAVE ;100 + DB >ZREST ;101 + DB >ZSHIFT ;102 + DB >ZASHFT ;103 + DB >ZFONT ;104 + DB >ZDISPL ;105 + DB >ZPICNF ;106 + DB >ZDCLR ;107 + DB >ZMARG ;108 + DB >ZISAVE ;109 + DB >ZIREST ;10A + +EXTLEN EQU $-EXTOPH + +EXTOPL: DB BIT OF [ZPC] +ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE +ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +ZPNTH EQU ZPCPNT+1 ; (BYTE) +ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +MPC EQU ZPCPNT+3 ; (3 BYTES) MEMORY PROGRAM COUNTER +MPCL EQU MPC ; (BYTE) <8 BITS OF [MPC] +MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] +MPCH EQU MPC+2 ; (BYTE) >BIT OF [MPC] +MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE +MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +MPNTH EQU MPCPNT+1 ; (BYTE) +MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +ZCODE EQU MPCPNT+3 ; (BYTE) 1ST ABSOLUTE PAGE OF PRELOAD +ZPURE EQU ZCODE+1 ; (WORD) 1ST VIRTUAL PAGE OF "PURE" Z-CODE +GLOBAL EQU ZCODE+3 ; (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 +TCHARS EQU GLOBAL+8 ; (WORD) TERMINATOR CHARS TABLE POINTER + +; Z-STRING MANIPULATION VARIABLES + +IN EQU GLOBAL+10 ; (9 BYTES) INPUT BUFFER +OUT EQU IN+9 ; (9 BYTES) OUTPUT BUFFER +SOURCE EQU OUT+9 ; (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 +PSVFLG EQU SOURCE+19 ; (BYTE) PRESERVE FLAG FOR LEX 0=DON'T 1=DO +VOCFLG EQU SOURCE+20 ; (BYTE) WHICH VOC TBL, 0=NORMAL 1= ARG3 +ALLFLG EQU SOURCE+21 ; (BYTE) IF =1 ALL FCN KEYS (>127) ARE TCHARS +DBLOCK EQU SOURCE+22 ; (WORD) Z-BLOCK TO READ +DBUFF EQU DBLOCK+2 ; (WORD) RAM PG TO ACCESS (LSB = 0) +PAGEOT EQU DBLOCK+4 ; (WORD) ZPCH,M OF 1ST VIRTUAL PAGE + +; THAT WILL HAVE TO GO IN PAGENG + +DIRFLG EQU PAGEOT+2 ; (BYTE) OUTPUT TO SCREEN (0) TABLE (1) FLAG +DIRTBL EQU PAGEOT+3 ; (WORD) CONTAINS TBLE TO STORE CHARS TO +DIRITM EQU PAGEOT+5 ; (WORD) OFFSET IN OUTPUT TBL (DIRTBL) +DIRCNT EQU PAGEOT+7 ; (WORD) COUNT OF CHARS IN TBL (DIRTBL) +BUFFLG EQU PAGEOT+9 ; (BYTE) DISPLAY BUFFERED (0) UNBUFFERED (1) +CHRMAX EQU PAGEOT+10 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD +XSIZE EQU PAGEOT+11 ; (BYTE) SCREEN WIDTH FOR TESTS +RAND1 EQU XSIZE+1 ; (BYTE) +RAND2 EQU XSIZE+2 ; (BYTE) RANDOM # +SPLITF EQU XSIZE+3 ; (BYTE) WHICH WINDOW TO WRITE IN +RDTBL1 EQU XSIZE+4 ; (WORD) READ TABLE 1 (ABSOLUTE- EZIP) +RDTBL2 EQU RDTBL1+2 ; (WORD) READ TABLE 2 +QUOT EQU RDTBL1+4 ; (WORD) QUOTIENT FOR DIVISION +REMAIN EQU QUOT+2 ; (WORD) REMAINDER FOR DIVISION +QSIGN EQU REMAIN+2 ;(BYTE) SIGN OF QUOTIENT +RSIGN EQU QSIGN+1 ; (BYTE) SIGN OF REMAINDER +DIGITS EQU RSIGN+1 ; (BYTE) DIGIT COUNT FOR "PRINTN" +LENGTH EQU DIGITS+1 ; (BYTE) CHAR POSITION ON THE SCREEN +CHRCNT EQU LENGTH+1 ; (BYTE) CHAR POSITION IN [LBUFF] +OLDLEN EQU CHRCNT+1 ; (BYTE) OLD LINE LENGTH +OLDEND EQU OLDLEN+1 ; (BYTE) OLD LAST CHAR IN [LBUFF] +SCRIPT EQU OLDEND+1 ; (BYTE) SCRIPT ENABLE FLAG +LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER +LMAX EQU LINCNT+1 ; (BYTE) MAX # LINES/SCREEN +IOCHAR EQU LMAX+1 ; (BYTE) CHARACTER BUFFER +SLINE EQU IOCHAR+1 ; (BYTE) BORDERLINE FOR SPLIT +SPSTAT EQU SLINE+1 ; (BYTE) SPLIT SCREEN STATUS FLAG +LFROM EQU SPSTAT+1 ; (WORD) "FROM" LINE ADDRESS +LTO EQU LFROM+2 ; (WORD) "TO" LINE ADDRESS +PRLEN EQU LTO+2 ; (BYTE) SCRIPT LINE LENGTH +SECTOR EQU PRLEN+1 ; (WORD) TARGET SECTOR +GPOSIT EQU SECTOR+2 ; (BYTE) DEFAULT SAVE POSITION +GDRIVE EQU GPOSIT+1 ; (BYTE) DEFAULT SAVE DRIVE +TPOSIT EQU GDRIVE+1 ; (BYTE) TEMP SAVE POSITION +TDRIVE EQU TPOSIT+1 ; (BYTE) TEMP SAVE DRIVE +TSLOT EQU TDRIVE+1 ; (BYTE) TEMP SAVE SLOT +DRIVE EQU TSLOT+1 ; (BYTE) CURRENT DRIVE +SIDEFLG EQU DRIVE+1 ; (BYTE) =1 IF WE ARE ON SIDE 1 2 IF SIDE 2 +SRHOLD EQU SIDEFLG+1 ; (BYTE) +TIMER EQU SRHOLD+1 ; (WORD) TIMED INPUT COUNTER +ZSP EQU TIMER+2 ; (WORD) +OLDZSP EQU ZSP+2 ; (WORD) +DBLK EQU OLDZSP+2 ; (WORD) +SCREENF EQU DBLK+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT +SCRIPTF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR PRINTER OUTPUT +TABLEF EQU SCRIPTF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT +VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH +TSTVAL EQU TABLEF+4 ; (BYTE) FOR MEMCHECK DONE AT START +LASTZP EQU TABLEF+5 ; CHECK FOR OVER ZERO PAGE + + END + \ No newline at end of file diff --git a/apple/xzip/hardeq.asm b/apple/xzip/hardeq.asm new file mode 100644 index 0000000..066d84d --- /dev/null +++ b/apple/xzip/hardeq.asm @@ -0,0 +1,209 @@ + STTL "--- HARDWARE EQUATES: APPLE II ---" + PAGE +; ------------------- +; APPLE II MEMORY MAP +; ------------------- + + +LBUFF EQU $0200 ; LINE INPUT BUFFER (80 BYTES) +SCREEN EQU $0400 ; START OF SCREEN RAM +LSTLNE EQU $07D0 ; LAST LINE OF SCREEN RAM +BORG EQU $0800 ; ORIGIN OF BOOT CODE (EZIP) +IOBUFF EQU BORG+$200 ; PAGENG BUFFER (EZIP) +BUFFA EQU IOBUFF+$100 ;($100 BYTES) DECODE BUFFER, LOWER HALF +BUFFB EQU BUFFA+$100 ;($56 BYTES) SECTOR DECODE BUFFER, UPPER HALF +LOCALS EQU BUFFB+$80 ; LOCAL VARIABLE STORAGE (30 BYTES) +BUFSAV EQU LOCALS+$20 ; TEMP SPACE FOR SAVE/RESTORE (80 BYTES) + +NEXTPNT EQU BUFFB+$100 +PREVPNT EQU NEXTPNT+$80 +VPAGEH EQU PREVPNT+$80 +VPAGEL EQU VPAGEH+$80 + +ZSTKBL EQU VPAGEL+$80 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) +ZSTKTL EQU ZSTKBL+$100 ; TOP, LO +ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI +ZSTKTH EQU ZSTKBL+$300 ; TOP, HI + +ZBEGIN EQU ZSTKBL+$400 ; START OF GAME CODE + + + + +; --------- +; CONSTANTS +; --------- + +XZIPID EQU 2 ; ID BYTE STATING THIS IS AN APPLE XZIP +IIcID EQU 9 ; IIc AND IIe DIFFERENT + +AUX EQU 1 +MAIN EQU 0 + + + +; THE FIRST 98.5K (SIDE1) MUST +; BE RAM RESIDENT (394=$18A PAGES) +; 98.5K = $18A PAGES (V$0 TO V$189) +; +; PAGES V$13A TO V$189 ARE IN RAMDISK +; PAGES V$0 TO ($BF-VBEGIN) ARE IN MAIN +; PAGES ($C0-VBEGIN) TO V$139 ARE IN AUX +; PAGENG BUFFERS ARE IN AUX FROM +; V$13A-($C0-VBEGIN)+$08 TO $BF + + + +VTOTAL EQU 256*4 ;TOTAL # PAGES IN EZIP +PSIDE2 EQU 35*18 ;# PAGES ON SIDE 2 OF DISK +PSIDE1 EQU VTOTAL-PSIDE2 ;# PAGES ON DISK SIDE 1 +RMDSIZE EQU $4F ; # PAGES RAMDSK CAN HOLD + ; (SECTORS 0-$4E) + +AUXSTART EQU $08 ;FIRST RAM PAGE IN AUX MEM +AUXEND EQU $BF ;LAST PAGE USABLE IN AUXMEM +MAINSTRT EQU ZBEGIN/$100 ;FIRST FREE PAGE IN MAIN +MAINEND EQU $BF ;LAST USABLE PAGE IN MAIN +VAUX EQU MAINEND-MAINSTRT+1 ;FIRST V-PAGE IN AUXMEM +VRAMDSK EQU PSIDE1-RMDSIZE ;FIRST V-PAGE IN RAMDSK + + +; PBEGIN IS FIRST RAM PAGING BUFFER IN AUX MEM +; PBEGIN IS FIRST PAGING BUFFER (RAM PAGE IN AUX MEM) + +PBEGIN EQU VRAMDSK-VAUX+AUXSTART +NUMBUFS EQU AUXEND-PBEGIN+1 ;# PAGENG BUFFER (RAM PAGES IN AUX) +;TEMP1 EQU (VRAMDSK*$100)/$100 +V64PG EQU PBEGIN- 35 IS ILLEGAL + + +; ---------------------- +; BOOT ZERO PAGE EQUATES +; ---------------------- + +BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS +BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT +BSECT EQU $3D ; (BYTE) BOOT SECTOR TO READ + + +; ---------------- +; HARDWARE EQUATES +; ---------------- + +KBD EQU $C000 ; KEY STROBE +ANYKEY EQU $C010 ; ANY KEY DOWN FLAG +SPKR EQU $C030 ; SPEAKER FLAG (MAKE A NOISE) +TXTSET EQU $C051 ; SWITCH FOR TEXT MODE +MIXCLR EQU $C052 ; SWITCH FOR MIX MODE CLEAR +LOWSCR EQU $C054 ; SWITCH FOR PAGE 1 SELECT + +ALTZP EQU $C008 ;WRITE R/W MAIN (C009 = AUX) >MEM +WRTBNK EQU $C004 ;WRITE WRITE MAIN 48K OF MEMORY (+MAIN, +AUX) +RDBNK EQU $C002 ;WRITE READ MAIN MEMORY (+MAIN, +AUX) +BNK2SET EQU $C083 ;READ/READ READ RAM WRITE RAM BANK 2 +BNK1SET EQU $C08B ;READ/READ READ RAM WRITE RAM BANK 1 +RDROM EQU $C08D ;READ/READ (X) READ ROM WRITE RAM (>MEM) + + +; ------------------------ +; IDOS INTERFACE VARIABLES +; ------------------------ + +DCBSLT EQU $00 ; (BYTE) TARGET SLOT ID +DCBPSL EQU DCBSLT+1 ; (BYTE) PREVIOUSLY ACCESSED SLOT +DCBDRV EQU DCBSLT+2 ; (BYTE) TARGET DRIVE ID +DCBPDR EQU DCBSLT+3 ; (BYTE) PREVIOUSLY ACCESSED DRIVE +DCBSEC EQU DCBSLT+4 ; (BYTE) TARGET SECTOR +DCBTRK EQU DCBSLT+5 ; (BYTE) TARGET TRACK +DCBERR EQU DCBSLT+6 ; (BYTE) DRIVE ERROR CODE +DCBCMD EQU DCBSLT+7 ; (BYTE) DISK COMMAND ID +DCBBFL EQU DCBSLT+8 ; (BYTE) LO POINTER TO DATA BUFFER +DCBBFM EQU DCBSLT+9 ; (BYTE) HI POINTER TO DATA BUFFER +DRVFLG EQU DCBSLT+10 ; (BYTE) CURRENT DRIVE +SLTMP3 EQU DCBSLT+11 ; (BYTE) TRACK-SEEK SLOT +TTRK EQU DCBSLT+12 ; (BYTE) TARGET TRACK +DTMP3 EQU DCBSLT+13 ; (BYTE) WORK BYTE +DTMP4 EQU DCBSLT+14 ; (BYTE) SLOT ID * 16 +HDRCHK EQU DCBSLT+15 ; (BYTE) CHECKSUM FOUND +HDRSEC EQU DCBSLT+16 ; (BYTE) SECTOR FOUND +HDRTRK EQU DCBSLT+17 ; (BYTE) TRACK FOUND +HDRVOL EQU DCBSLT+18 ; (BYTE) VOLUME FOUND +DCNT EQU DCBSLT+19 ; (BYTE) MOTOR TIME COUNT +DTMP2 EQU DCBSLT+20 ; (BYTE) TEMP + +; NEXT 4 FOR 18 SECTORS/TRK CODE IN RWTS + +HTEMP EQU DCBSLT+21 ; (BYTE) +TRYS EQU DCBSLT+22 ; (BYTE) +TEMP EQU DCBSLT+23 ; (BYTE) +WORD1 EQU DCBSLT+24 ; (WORD) +DTMP6 EQU DCBSLT+26 ; (BYTE) + + +; --------------------- +; DISK HARDWARE EQUATES +; --------------------- + +PH0OFF EQU $C080 ; STEP MOTOR POSITION #0 +DRVOFF EQU $C088 ; DRIVE MOTOR OFF +DRVON EQU $C089 ; DRIVE MOTOR ON +DRV0EN EQU $C08A ; ENGAGE DRIVE #1 +DRV1EN EQU $C08B ; ENGAGE DRIVE #2 +Q6L EQU $C08C ; READ DATA LATCH +Q6H EQU $C08D ; WRITE DATA LATCH +Q7L EQU $C08E ; SET READ MODE +Q7H EQU $C08F ; SET WRITE MODE + + +; ----------------- +; MONITOR VARIABLES +; ----------------- + +WLEFT EQU $20 ; LEFT MARGIN (0) +WWDTH EQU $21 ; RIGHT MARGIN (40 OR 80) +WTOP EQU $22 ; TOP LINE (0-23) +WBOTM EQU $23 ; BOTTOM LINE (1-24) +CHZ EQU $24 ; CURSOR HORIZONTAL +CVT EQU $25 ; CURSOR VERTICAL +BASL EQU $28 ; SCREEN LINE +INVFLG EQU $32 ; CHAR OUTPUT MASK ($FF=NORM, $3F=INVERSE) +PROMPT EQU $33 ; PROMPT CHARACTER (SET TO <) +CSW EQU $36 ; CHARACTER OUTPUT VECTOR +RNUM1 EQU $4E ; RANDOM #'S GENERATED BY +RNUM2 EQU $4F ; MONITOR GETKEY +EHZ EQU $057B ; CURSOR HORIZONTAL (IIE/C) +APKEY1 EQU $C061 ; open apple key flag +APKEY2 EQU $C062 ; closed apple key flag + +; ---------------- +; MONITOR ROUTINES +; ---------------- + +MBASCAL EQU $FC22 ; CALC LINE BASE ADDRESS +MBELL EQU $FF3A ; MAKE A NOISE +MCLEOL EQU $FC9C ; CLEAR TO END OF LINE +MCLEOS EQU $FC42 ; CLEAR TO END OF SCREEN +MHOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR +MMCOUT EQU $FDED ; CHAR OUTPUT +MCOUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN +MRDKEY EQU $FD0C ; READ KEY +MGETLN1 EQU $FD6F ; GET LINE +MMWAIT EQU $FCA8 ; WASTE SO MUCH TIME + + END + + \ No newline at end of file diff --git a/apple/xzip/io.asm b/apple/xzip/io.asm new file mode 100644 index 0000000..d018d4d --- /dev/null +++ b/apple/xzip/io.asm @@ -0,0 +1,1485 @@ + + STTL "--- GAME I/O: APPLE II ---" + PAGE + + ; -------------- + ; INTERNAL ERROR + ; -------------- + ; ENTRY: ERROR CODE IN [A] + ; EXIT: HA! + +ERRM: DB "Internal error " +ENUMB: DB "00. " +ERRML EQU $-ERRM + +ZERROR: LDY #1 ; CONVERT ERROR BYTE IN [A] +ZERR0: LDX #0 ; TO ASCII AT "ENUMB" +ZERR1: CMP #10 + BCC ZERR2 + SBC #10 + INX + BNE ZERR1 +ZERR2: ORA #'0' + STA ENUMB,Y + TXA + DEY + BPL ZERR0 + LDX #ERRM + LDY #ERRML + JSR DLINE ; PRINT ERROR MESSAGE + JMP ZQUIT1 + + + ; ---- + ; QUIT + ; ---- + +ZQUIT: JSR ZCRLF ; FLUSH BUFFER +ZQUIT1: LDX #ENDM + LDY #ENDML + JSR DLINE ; "END OF STORY" +FREEZE: JMP FREEZE ; AND STOP + +ENDM: DB "End of session." + DB EOL +ENDML EQU $-ENDM + + + ; ------- + ; RESTART + ; ------- + +ZSTART: LDX #0 + STX WTOP ; RESET FULL SCREEN FOR CLEAR + LDA SCRIPTF ; PRINTING? + BEQ REX ; NO + DEX ; = $FF + STX PSTAT ; MAKE TO CONTINUE PRINTING AFTER RESTART +REX: JSR SIDE1 ; NEED SIDE 1 AGAIN + JMP WARM ; AND DO WARMSTART + + + ; -------------------------- + ; RETURN TOP RAM PAGE IN [A] + ; -------------------------- + +MEMTOP: LDA #$FB ; FOR NOW, ASSUME LAST "BUFFER" + RTS ; OF AUX MEMORY + + + ; -------------------------------- + ; RETURN RANDOM BYTES IN [A] & [X] + ; -------------------------------- + +RANDOM: INC RNUM1 + DEC RNUM2 + LDA RNUM1 ; GENERATED BY MONITOR GETBYT + ADC RAND1 + TAX + LDA RNUM2 + SBC RAND2 + STA RAND1 + STX RAND2 + RTS + + + ; ------------------- + ; Z-PRINT A CHARACTER + ; ------------------- + ; ENTRY: ASCII CHAR IN [A] + ; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, + ; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN + ; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME + ; (DIROUT CHANGES 6/24/85) + +COUT: STA IOCHAR ; HOLD IT A SEC + LDX TABLEF ; OUTPUT TO TABLE? + BEQ COUT4 ; NO + JMP TBLRTN ; YES, DO IT (TBL ONLY) +COUT4: + LDX SCREENF ; OUTPUT TO SCREEN? + BNE COUT5 ; YES + LDX SCRIPTF ; OUTPUT TO PRINTER? + BNE COUT5 ; YES + RTS ; NO, SO DONE +COUT5: + LDA IOCHAR ; RETRIEVE CHAR + LDX BUFFLG ; UNBUFFERED OUTPUT? + BNE UNBUFR ; YES, PLACE ON SCREEN IMMED. + + CMP #$0D ; IF ASCII EOL, + BNE COUT0 + + JMP ZCRLF ; DO IT +COUT0: + CMP #SPACE ; IGNORE ALL OTHER + BCC CEX ; CONTROLS + +; LDX INVFLG ; CHECK IF NORMAL +; BPL COUT3 ; OR INVERSE + + ORA #%10000000 ; SET HIGH BIT FOR NORMAL +COUT3: + LDX CHRCNT ; GET LINE POINTER + STA LBUFF,X ; ADD CHAR TO BUFFER + + LDA SPLITF ; are we in screen 1 + BNE COUT2 ; yes + + LDY LENGTH ; GET LINE LENGTH COUNTER + INC LENGTH ; ELSE UPDATE + CPY XSIZE ; END OF SCREEN LINE? + BCC COUT2 + JMP FLUSH ; YES, FLUSH THE LINE +COUT2: + INC CHRCNT +CEX: RTS + + + ; -------------------------- + ; DIRECT, UNBUFFERED DISPLAY + ; -------------------------- + +UNBUFR: STA IOCHAR ; HOLD IN CASE NEED TO PRINT + LDA EHZ ; CHECK IF BEYOND SCREEN + CMP #80 + BCS UNBEX ; YES, LEAVE + + LDA SPLITF ; CHECK WHICH WINDOW + BEQ UNBBOT ; BOTTOM WINDOW + LDA CVT ; CHECK IF WITHIN WINDOW + CMP WTOP + BCS UNBEX ; NO, JUST LEAVE + BCC UNBDIS ; YES, GO DISPLAY + +UNBBOT: LDA CVT + CMP WTOP + BCC UNBEX ; NOT WITHIN WINDOW, LEAVE + +UNBDIS: LDA SCREENF ; DISPLAY TO SCREEN? + BEQ UNBPRN ; NO, CHECK IF PRINTING + + LDA IOCHAR + ORA #%10000000 ; SET BIT 7 FOR NORMAL DISPLAY IF WANTED + JSR CHAR + + ;SEND CHAR TO PRINTER +UNBPRN: + LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? + BEQ UNBEX ; NO + LDA SCRIPTF ; SCRIPTING ON ? + BEQ UNBEX ; NO + LDA CSW+LO ; SAVE NORMAL OUTPUT HOOK + PHA + LDA CSW+HI + PHA + LDA EHZ ; + CURRENT CURSOR POSITION + PHA + LDA ALTCSW+LO + STA CSW+LO + LDA ALTCSW+HI + STA CSW+HI + LDA IOCHAR ; GET CHAR + JSR MCOUT ; PRINT IT @ CURRENT EHZ + PLA + STA EHZ ; IIe USES CHZ ALSO + PLA + STA CSW+HI + PLA + STA CSW+LO +UNBEX: RTS + + + ; --------------- + ; OUTPUT TO TABLE + ; --------------- + +TBLRTN: TAX ; HOLD CHAR A SEC. + + ;PUT BYTE IN TABLE AT CURRENT OFFSET + + LDA DIRITM+LO ; ADD IN OFFSET + CLC + ADC DIRTBL+LO + STA I+LO + LDA DIRITM+HI + ADC DIRTBL+HI + STA I+HI + LDY #0 + TXA ; PICK UP ASCII CHAR + STA (I),Y ; STORE IT IN TBL @ BYTE ALIGNED @ + + ;SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER + + INC DIRITM+LO ; INC OFFSET TO NEXT BYTE + BNE TBLRTS + INC DIRITM+HI +TBLRTS: RTS + + + ; ------------------- + ; FLUSH OUTPUT BUFFER + ; ------------------- + ; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: LDA #$A0 ; SPACE + STX OLDEND ; SAVE CURRENT END OF LINE +FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR + BEQ FL1 ; IN THE LINE + DEX + BNE FL0 ; IF NONE FOUND, + LDX XSIZE ; FLUSH ENTIRE LINE +FL1: STX OLDLEN ; SAVE OLD LINE POS HERE + STX CHRCNT ; MAKE IT THE NEW LINE LENGTH + JSR ZCRLF ; PRINT LINE UP TO LAST SPACE + + ; START NEW LINE WITH REMAINDER OF OLD + + LDX OLDLEN ; GET OLD LINE POS + LDY #0 ; START NEW LINE AT BEGINNING +FL2: INX + CPX OLDEND ; CONTINUE IF + BCC FL3 ; INSIDE OR + BEQ FL3 ; AT END OF LINE + STY LENGTH ; ELSE SET NEW LINE LENGTH + STY CHRCNT + RTS +FL3: LDA LBUFF,X ; GET CHAR FROM OLD LINE + STA LBUFF,Y ; MOVE TO START OF NEW LINE + INY ; UPDATE LENGTH OF NEW LINE + BNE FL2 ; (ALWAYS) + + + ; --------------- + ; CARRIAGE RETURN + ; --------------- + +ZZCRLF: LDX TABLEF ; OUTPUT TO TABLE? + BEQ ZCRLF ; NO + LDA #$0D + JMP TBLRTN ; YES, DO IT (TBL ONLY) + +ZCRLF: LDX CHRCNT + LDA #$8D ; INSTALL EOL AT + STA LBUFF,X ; END OF CURRENT LINE + INC CHRCNT ; UPDATE LINE LENGTH + LDA SCREENF ; CHECK IF DISPLAYING TO SCREEN + BEQ ZCRLFX ; NO, GO HANDLE IF PRINTING + LDA SPLITF ; AT SPLIT SCREEN + BNE ZCRLFX ; YES, SKIP ALL THIS + INC LINCNT ; NEW LINE GOING OUT +ZCRLF0: LDX LINCNT ; IS IT TIME TO + CPX WBOTM ; PRINT "MORE" YET? + BNE ZCRLFX ; NO, CONTINUE + + LDA WTOP + STA LINCNT ; RESET LINE COUNTER + INC LINCNT ; to leave this line there + INC LINCNT ; to leave one line from previous screen + ; there + BIT ANYKEY ; CLEAN STROBE SO GET CLEAN READING + LDA ZBEGIN+ZLMRG+1 ; SET LEFT MARGIN + STA EHZ + LDA #>MORE + LDX #'S + +CHKFNC: LDA ZBEGIN+ZCRCNT+1 ; IF NULL IGNORE + ORA ZBEGIN+ZCRCNT+0 + BEQ CHKOUT + + LDA ZBEGIN+ZCRCNT+1 ; DECR COUNTER + SEC + SBC #1 + STA ZBEGIN+ZCRCNT+1 + LDA ZBEGIN+ZCRCNT+0 + SBC #0 + STA ZBEGIN+ZCRCNT+0 + LDA ZBEGIN+ZCRCNT+1 ; IF NULL NOW, CALL FCN + ORA ZBEGIN+ZCRCNT+0 + BNE CHKOUT + + LDA ZBEGIN+ZCRFUNC+1 ; SET UP FUNCTION + STA J+LO + LDA ZBEGIN+ZCRFUNC+0 + STA J+HI + JSR INTCLL ; DO FUNCTION CALL +CHKOUT: RTS + + + ; ---------------------- + ; UPDATE THE STATUS LINE + ; ---------------------- + ; NOT APPLICABLE IN EZIP. + +ZUSL: RTS + + + ; ------ + ; VERIFY + ; ------ + ; VERIFY GAME CODE ON DISK + +ZVER: JSR ZCRLF ; DISPLAY VERSION NUMBER, GET SIDE 1 + LDX #3 + LDA #0 + STA IOCHAR ; COFFEE FLAG +ZVR: STA K+LO,X ; CLEAR [K], [L] + 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 ZBEGIN+ZLENTH ; GET MSB + STA I+HI ; AND + LDA ZBEGIN+ZLENTH+1 ; LSB OF Z-CODE LENGTH IN BYTES + ASL A ; MULTIPLY BY + ROL I+HI ; FOUR + ROL K+LO + ASL A + STA I+LO + ROL I+HI ; TO GET # BYTES + ROL K+LO ; IN GAME + LDA #0 ; START AT BEGINNING + STA DBLOCK+LO + STA DBLOCK+HI + JMP READIN ; READ FIRST BLOCK IN +VSUM: LDA MPCL ; NEW PAGE? + BNE VSUM2 ; NO, CONTINUE +READIN: LDA #>IOBUFF ; FAKE READ OUT SO + STA DBUFF+HI ; IT DOESN'T MOVE BUFFER + LDA #MAIN + STA DSKBNK ; SET FOR MAIN BANK + JSR GETDSK ; GO READ A PAGE + + LDA IOCHAR ; CHECK COFFEE FLAG + BNE VSUM2 ; ALL DONE + LDA SIDEFLG + CMP #2 ; IF ON SIDE 2 + BNE VSUM2 + LDA #>COFMSG ; FIRST SECTOR, TELL THEM + LDX #BIT + CMP K+LO + BNE VSUM + LDA ZBEGIN+ZCHKSM+1 ; GET LSB OF CHECKSUM + CMP L+LO ; DOES IT MATCH? + BNE BADVER ; NO, PREDICATE FAILS + LDA ZBEGIN+ZCHKSM ; ELSE CHECK MSB + CMP L+HI ; LOOK GOOD? + BNE BADVER ; IF MATCHED, + JMP PREDS ; GAME IS OKAY +BADVER: JMP PREDF + +COFMSG: DB EOL + DB "Please be patient, this takes a while" + DB EOL +COFML EQU $-COFMSG + + + ; ------ + ; BUFOUT + ; ------ + ; ENTER: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE + ; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO + +ZBUFOUT: LDX ARG1+LO + BNE ZBUF1 ; SET TO BUFFERED OUTPUT + JSR CLRBUF ; CLEAR BUFFER + LDX #1 + STX BUFFLG ; SET FUTURE OUTPUT TO BE UNBUFFERED + RTS +ZBUF1: DEX + BNE ZBUFEX ; INVALID + STX BUFFLG ; SET TO BUFFERED +ZBUFEX: RTS + + + ; CLEAR OUTPUT BUFFER BEFORE DOING ANYTHING FANCY + +CLRBUF: JSR LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) + LDX #0 + STX CHRCNT + RTS + + ; ------ + ; DIROUT + ; ------ + ; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT + ; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT + ; MULTIPLE DEVICE USAGE IS POSSIBLE. + +ZDIRT: LDX ARG1+LO + BMI DIRRES ; NEGATIVE VALUE, DESELECTING + DEX + BEQ DIR1 ; 1 = SET OUTPUT TO SCREEN + DEX + BEQ DIR2 ; 2 = SCRIPTING + DEX + BEQ DIR3 ; 3 = TABLE + DEX + BEQ DIR4 ; 4 = RECORDING DEVICE + RTS ; INVALID VALUE +DIRRES: INX + BEQ DRES1 ; -1 = RESET TO SCREEN + INX + BEQ DRES2 + INX + BEQ DRES3 + INX + BEQ DRES4 + RTS ; INVALID VALUE, JUST LEAVE +DIR1: INX ; 1, TURN SCREEN OUTPUT ON + STX SCREENF + RTS +DRES1:; JSR CLRBUF + STX SCREENF ; 0, TURN SCREEN OFF + RTS +DIR2: INX + STX SCRIPTF ; SET SCRIPT FLAG ON + LDA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO + ORA #%00000001 + STA ZBEGIN+ZSCRIP+1 + LDA PSTAT ; CHECK IF PRINTER ALREADY INIT'D + BNE DIR2A + JSR PCHK ; NO, GO DO IT +DIR2A: RTS ; YES, READY TO LEAVE +DRES2: STX SCRIPTF ; TURN PRINTER OFF + LDA ZBEGIN+ZSCRIP+1 ; AND TURN OFF GAME FLAG TOO + AND #%11111110 + STA ZBEGIN+ZSCRIP+1 + RTS +DIR3: INX + STX TABLEF ; TURN TABLE OUTPUT FLAG ON + LDA ARG2+HI ; SET UP TBL + CLC + ADC ZCODE + LDX ARG2+LO ; TO STORE CHARS IN + STX DIRTBL+LO + STA DIRTBL+HI + LDA #2 + STA DIRITM+LO + LDA #0 + STA DIRITM+HI + RTS + +DRES3: LDA TABLEF ; IF OFF ALREADY + BEQ OUT3 ; LEAVE AS IS + + STX TABLEF ; TURN TBL OUTPUT OFF + LDA DIRITM+LO ; MARK END OF CHARS IN TBL + CLC ; WITH A NULL CHAR + ADC DIRTBL+LO + STA I+LO + LDA DIRITM+HI + ADC DIRTBL+HI + STA I+HI ; ALIGNED AT EOL + LDA #0 + TAY + STA (I),Y ; PLACE 0 IN TBL + LDY #1 ; GET CHAR COUNT + LDA DIRITM+LO ; (2 LESS THAN [DIRITM]) + SEC + SBC #2 + STA (DIRTBL),Y + BCS RESET0 + DEC DIRITM+HI +RESET0: LDA DIRITM+HI + DEY + STA (DIRTBL),Y ; STORE CHAR COUNT IN TBL + LDA #0 ; CLEAR COUNT FOR NEXT TIME + STA DIRFLG ; SET OUTPUT TO SCREEN +OUT3: RTS + +DIR4: +DRES4: RTS ; NOT YET IMPLEMENTED + + + ; ------ + ; CURSET + ; ------ + ; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW + ; AND AT COLUMN (ARG2) + +ZCURST: JSR CLRBUF ; CLEAR OUT ANY NON DISPLAYED TEXT 1ST + LDX ARG1+LO ; GET LINE + DEX ; ZERO ALIGN IT + STX CVT + LDX ARG2+LO ; GET COLUMN + DEX ; ZERO ALIGN IT + STX EHZ +; STX CHZ ; IIe SEEMS TO USE BOTH + JMP BASCAL ; MOVE THE CURSOR + + + ; ------ + ; CURGET + ; ------ + +ZCURGT: LDA ARG1+LO + STA I+LO + LDA ARG1+HI + CLC + ADC ZCODE ; ABSOLUTE + STA I+HI + LDY CVT ; GET CURSOR POSITION + LDX EHZ + INX ; 1 ALIGN IT + INY + TYA ; SLIP IT INTO PLACE + LDY #1 ; TO RETURN IT + STA (I),Y + DEY ; ZERO TOP BYTE + TYA + STA (I),Y + INY + INY + STA (I),Y + INY + TXA + STA (I),Y + RTS + + + ; ----- + ; DIRIN + ; ----- + ; NOT YET IMPLEMENTED, BUT RESERVED + +ZDIRIN: RTS + + + ; ------ + ; HLIGHT + ; ------ + +ZLIGHT: + JSR CLRBUF ; flush the ole buffer + + LDA ARG1+LO ; GET CHOICE OF MODE + BNE ZL1 + + LDA #$FF ; NORMAL DISPL + STA INVFLG +ZLIEX: + RTS ; MONO SPACE IS ONLY OPTION SO JUST IGNORE IT +ZL1: + CMP #1 ; INVERSE? + BNE ZLIEX ; NO OTHER OPTIONS ON APPLE + + LDA #$3F ; SET INVERSE DISPLAY + STA INVFLG + RTS + + + ; ----- + ; ERASE + ; ----- + +ZERASE: LDA ARG1+LO + CMP #1 + BNE ZEROUT ; INVALID + JSR CLRBUF + JMP CLEOL ; CLEAR TO END OF LINE +ZEROUT: RTS + + + ; ----- + ; CLEAR + ; ----- + +ZCLR: JSR CLRBUF +; LDA CHZ ; SAVE CURSOR JIC CLEARING OTHER WINDOW + STA OLDCHZ + LDA EHZ + STA OLDEHZ + LDA CVT + STA OLDCVT + + LDA ARG1+LO ; CHECK WHAT TO DO + BEQ CLR0 ; BOTTOM SCREEN + CMP #1 + BEQ CLR1 ; TOP SCREEN + CMP #$FF + BNE ZEROUT ; INVALID + + ; UNSPLIT SCREEN & CLEAR IT + + JSR NORL ; RESET TO FULL + JMP CLS ; & CLEAR IT + +CLR0: LDA WTOP ; SET COUNT + STA LINCNT ; FOR "MORE" + JSR CLS ; CLEAR & HOME + LDX #0 + JMP SETOLD + +CLR1: LDA WTOP ; SAVE SCROLLING TOP + PHA + LDX #0 ; TOP OF SCREEN + STX WTOP + STA WBOTM ; MAKE BOTTOM OF TOP SCREEN + JSR CLS + LDA #$18 ; RESET TOP & BOTTOM + STA WBOTM + PLA + STA WTOP + + LDX #1 ; SET SO NEXT TIME INTO WINDOW TOP LEFTS +SETOLD: LDA #0 + STA OLD0CVT,X + STA OLD0CHZ,X + STA OLD0EHZ,X + + CPX SPLITF + BEQ CLROUT ; LEAVE CURSOR TOP LEFT + + LDA OLDCHZ +; STA CHZ + LDA OLDEHZ + STA EHZ + LDA OLDCVT + STA CVT + JMP BASCAL +CLROUT: RTS + + +; ------ +; PRINTT +; ------ + + ; PRINT A TABLE TO SCREEN, ARG1 = # OF BYTES + ; ARG2 = WIDTH, ARG3 (DEF = 1) = HEIGHT + +OLDCHZ EQU I+LO ; EASIER TO READ +OLDEHZ EQU I+HI +OLDCVT EQU L+LO + +ZPRNTT: + LDA SPLITF ; check if in window 0 + BEQ PTTj ; don't clear buf in w0 (cuz we wrap) +; +; make sure the buffer is empty, thanks +; + JSR CLRBUF +PTTj: + LDA ARG1+LO ; USE GETBYT AS TBL COULD + STA MPCL ; BE ANYWHERE + LDA ARG1+HI + STA MPCM + LDA #0 + STA MPCH + JSR VLDMPC + LDA ARG2+LO ; ONLY A BYTE AS MAX + CMP #0 + BEQ PTTDUN ; QUIT NOW IF NULL + + STA J+HI ; SCREEN WIDTH IS 80 + STA J+LO + DEC NARGS + LDA NARGS + CMP #1 + BEQ NOHIGHT ; DEFAULT HEIGHT IS 1 + LDA ARG3+LO ; & SCREEN LENGTH MAX IS 25 +NOHIGHT: STA K+LO + + LDA EHZ + STA OLDEHZ + LDA CVT + STA OLDCVT + +PTTLP: JSR GETBYT ; GET A BYTE + JSR COUT + + DEC J+LO + BNE PTTLP + DEC K+LO ; IF DONE ALL LINES + BEQ PTTDUN ; LEAVE + + LDA OLDEHZ + STA EHZ + LDX OLDCVT + INX ; TO NEXT LINE + STX OLDCVT + STX CVT + JSR BASCAL ; PLACE CURSOR ON NEXT LINE + LDA J+HI ; RESET COUNT + STA J+LO + JMP PTTLP ; GO DO NEXT LINE +PTTDUN: RTS + + +; ------------ +; SET NEW FONT +; ------------ + +; FONT 1 (NORMAL) AND 3 (MOUSETEXT - ON IIC'S ONLY) ONLY +; FWRD (PIXEL HEIGHT & WIDTH) DOESN'T CHANGE + +ZFONT: + LDA ARG1+LO ; GET FONT CHOICE + LDX SPLITF ; get which window + CMP FONT,X ; see if it is a change + BEQ ZFDONE ; nope, so just return + + JSR CLRBUF ; got to clear the buffer! + LDA ARG1+LO ; GET FONT CHOICE, again + JSR CHFONT ; go change it + BCS ZFBAD ; bad choice +ZFDONE: + LDX SPLITF ; get old font for returning + LDA FONT,X + PHA + LDA ARG1+LO ; and save the new one + STA FONT,X ; REMEMBER NEW FONT FOR NEXT TIME + PLA + LDX #0 + JMP PUTVAL ; RETURN PREVIOUS FONT + +ZFBAD: JMP RET0 ; TELL IT DOESN'T WORK + +; +; entry point for local calls +; [A] has font # to change to +; +CHFONT: + LDX SIG + BNE CFBAD ; NOT A IIC + + CMP #1 + BEQ NORML + CMP #3 + BNE CFBAD + +FONT3: + LDA #$3F ; SET INVERSE ON + STA INVFLG + LDA #$1B ; AND MOUSETEXT ON + JSR MCOUT ; GO THRU THE CHANNELS FOR ANY OUTPUT TYPE + JMP CHFOUT + +NORML: + LDA #$18 ; TURN OFF MOUSE TEXT + JSR MCOUT + LDA #$FF + STA INVFLG +CHFOUT: + CLC ; clear carry to show goodness + RTS +CFBAD: + SEC ; set carry to show naughtiness + RTS + + ; ------------------------------ + ; FETCH A LINE OF INPUT FOR READ + ; ------------------------------ + ; ENTRY: ABS ADDR OF READ BUFFER IN [ARG1] + ; EXIT: # CHARS READ IN [A] + +INPUT: + JSR CLRBUF ; FLUSH [LBUFF] + LDA #0 ; RESET LINE COUNT + STA I+HI ; clear local variables + STA I+LO + STA J+HI + STA J+LO + STA BRKCHR ; init break char + + LDY WTOP + STY LINCNT ; RESET LINE COUNT + + TAY ; get length stuff + LDA (RDTBL1),Y ; get maximum size of buffer + CMP #79 ; IF OVER 78, CUT DOWN TO 78 + BCC MAX ; LEAVE IT AS IT IS, IT IS LESS + LDA #78 +MAX: + STA CHRMAX ; and save it + INY + LDA (RDTBL1),Y ; get current offset into buffer + TAX ; get so we can inc it + INX ; and not + INX ; count the 2 info-bytes + STX CHARCNT ; save how many chars out there + + JSR CHKTME ; START TIME LIMIT +INLOOP: + LDA I+HI ; is there a time? + BEQ INPL1 ; nope + JSR TIMIN ; do timed input + BCC INPL2 ; got a char, process it + JMP LEXBAD ; timed out with nothing there! +INPL1: + JSR GETKEY ; let apple do the walking +INPL2: + JSR ISTCHR ; CHECK IF IT'S AN ACCEPTABLE TERMINATOR KEY + BCS NOTYET + + STA BRKCHR + CMP #EOL ; IF EOL PUT TO SCREEN + BEQ ENDLIN + JMP ENDIN ; ELSE JUST END +NOTYET: + TAY ; check for functions keys that aren't + BMI CBAD ; terminators and feep if it is + CMP #EOL ; EOL? + BEQ ENDLIN ; LINE DONE IF SO + + CMP #BACKSP ; BACKSPACE? + BEQ BACKUP ; SPECIAL HANDLING + + LDY CHARCNT ; where do we put char? + CPY CHRMAX ; are we filled up? + BCS CBAD ; boy, am i full + CMP #$80 ; DON'T SHOW FCN KEYS + BCS LEX +SHOWIT: + STA SVCHAR ; save it + CMP #$80 ; don't display function keys + BCS NOSHOW ; okay, i won't +; LDX INVFLG +; BPL SHOW1 ; INVRSE + ORA #$80 ; ELSE MAKE IT NORMAL +SHOW1: JSR CHAR ; SEND TO SCREEN +; +; now save it for posterity +; +NOSHOW: + LDA SVCHAR ; get it to work on + CMP #'A' ; IF CHAR IS UPPERCASE ALPHA, + BCC LEX ; CONVERT TO LOWER CASE + CMP #'Z'+1 + BCS LEX + ADC #$20 ; converting away +LEX: + STA (RDTBL1),Y ; ADD CHAR TO INPUT BUFFER + INC CHARCNT ; NEXT POSITION IN LINE + JMP INLOOP ; NO, GET ANOTHER CHAR + + ; HANDLE BACKSPACE + +BACKUP: + LDA CHARCNT ; if == 2 then empty + CMP #2 ; and if not, then we still have room + BEQ CBAD ; JMP to beeping + DEC CHARCNT ; get rid of char + LDA #$08 ; BACKSP STRANGE SO DO 082008 + JSR CHAR + LDA #$A0 + JSR CHAR + LDA #$08 + JSR CHAR + JMP INLOOP + +CBAD: JSR BEEP ; ELSE SCREAM WITH PAIN + JMP INLOOP ; AND WAIT FOR SOMETHING BETTER + + ; HANDLE END OF LINE + +ENDLIN: STA BRKCHR + LDA #$8D + JSR CHAR ; SEND EOL TO SCREEN + INC LINCNT ; take into account the at EOL +; +; now, build lbuff so we can send it to the printer if necessary +; but only build it if it is necessary, really! +; + LDA SCRIPT ; find out if we are scripting + BEQ ENDIN ; i guess not + LDA ZBEGIN+ZSCRIP+1 ; check for printing + AND #$01 ; check bit flag + BEQ ENDIN ; no printing, continue on + + LDY CHARCNT ; start at end of buffer + LDA #0 ; to print (put in by clearp) + STA (RDTBL1),Y + + LDX CHARCNT ; fill in backwards + DEX + STX LINLEN ; say how many chars for printing + DEX ; we don't need to count info-bytes here +SLOOP: + LDA (RDTBL1),Y ; get char + STA LBUFF,X ; store char + DEY ; point to next get place + DEX ; point to next lbuff place + BPL SLOOP ; go to some more +SDONE: + JSR CLEARP ; CLEAR OFF FCN KEYS BEFORE PRINTING + JSR PPRINT ; SCRIPT [LBUFF] IF ENABLED +ENDIN: + LDY CHARCNT ; how many chars in buffer + LDA #00 ; to show end of line + STA (RDTBL1),Y ; and save it + DEY ; DON'T INCLUDE LENGTH BYTES + DEY ; IN COUNT + TYA ; SAVE INBUF LENGTH + LDY #1 + STA (RDTBL1),Y ; and tell the world about it! +LEXBAD: RTS ; INTO [A] + + ; CHKTME RTN - CALLED BY INPUT & ZINPUT + +CHKTME: + LDA NARGS ; CHECK IF TIME LIMIT + CMP #2 + BEQ CHKT1 ; NO + LDA ARG3+LO ; GET DELAY WANTED + STA I+HI + LDA NARGS ; IS THERE A FCN? + CMP #4 + BNE CHKT1 ; NO + LDA ARG4+LO ; YES, SET IT + STA J+LO + LDA ARG4+HI + STA J+HI +CHKT1: + RTS ; just set things up, please + + ; ZINPUT ENTRY (DIFFERENT ARG #'S SO SETUP AHEAD) + +TIMEK: + BIT ANYKEY ; CLEAR STROBE +TIMEST: + JSR STCUR ; start the cursor + LDA I+LO ; don't reset if not zero + BNE TIME0 ; so keep goin' then + LDA I+HI + STA I+LO + +TIME0: LDX #8 ; .09 SEC (time to do other stuff) +TIME1: LDA #$30 ; .O1 SEC + JSR MWAIT + DEX + BNE TIME1 + + BIT KBD ; CHECK FOR KEYSTROKE + BMI TIME2 ; OK, HE'S THERE, CONTINUE + + DEC I+LO ; 10TH'S OF SECONDS TO WAIT + BEQ TIMEOUT ; SOME TIME LEFT + + BNE TIME0 ; so gwon back and try again! (JMP) +; TIME OUT, CHECK FOR A FCN +TIMEOUT: + JSR ERCUR ; after erasing cursor + LDA J+HI ; IS THERE A FCN + BEQ TIMEBAD ; NO FCN, LEAVE WITH NOTHING +TIME3: + JSR INTCLL ; INTERNALLY CALL THE FCN + LDA VALUE+LO ; CHECK RESULTS + BNE TIMEBAD ; ELSE TRY AGAIN (END EZIP) + + LDA LINCNT + CMP WTOP ; check against start + BEQ TIMEST ; if anything printed out, reprint input + JSR FLUSHRD + JMP TIMEST +TIMEBAD: + SEC + RTS +TIME2: + CLC ; GOT A KEY + RTS +; +; send out the input chars type in so far +; +FLUSHRD: + ldy #1 ; start at 1 to skip junk in front +FRLOOP: + iny ; next char? + cpy CHARCNT ; see if we are full + beq FREND ; nope, still some more + lda (RDTBL1),Y ; get the char + CMP #$80 ; don't display function keys + BCS FRLOOP ; okay, i won't + ora #$80 ; make normal + jsr CHAR ; and send it out + jmp FRLOOP +FREND: + lda WTOP + sta LINCNT + rts + +; +; display the cursor in the current spot +; +STCUR: + LDX INVFLG ; save old invers + TXA ; and get it + EOR #$C0 ; set/clear inverse bits + STA INVFLG ; and save it + LDA #$A0 ; just an inverse space char + JSR CHAR ; display it + LDA #$08 ; gwon back + JSR CHAR ; and wait + STX INVFLG ; and reset it + RTS + +; just erase the cusor char, but leave cursor in its old place +; +ERCUR: + PHA ; save a + LDA #$A0 ; get space char + JSR CHAR ; and put it out there + LDA #$08 ; get backspace + JSR CHAR ; moving cursor back + PLA ; retrieve [A] + RTS +; +; timed key input loop +; +; carry set if timed out +; char in [A], if there is one! +TIMIN: + JSR TIMEK ; check for keystroke + BCC TM1 ; SOMEBODY'S THERE + BCS TMBAD ; ELSE ABORT +TM1: + JSR GOTKEY ; GET ASCII INTO [A] AND [IOCHAR] + BEQ TIMIN ; 0 means no good char + JSR ERCUR ; erase the cursor, please + CLC ; clear to show goody + BCC TMRET ; and go away +TMBAD: + SEC ; set carry to show timeout +TMRET: + RTS ; and away we go + + ; ------------------------ + ; IS IT A TERMINATOR CHAR? + ; ------------------------ + +ISTCHR: + PHA + LDA TCHARS+HI ; check if there is a tchars table + ORA TCHARS+LO ; == 0 if not + BEQ ISDUN ; nope + + PLA + LDX ALLFLG ; ARE ALL FCN KEYS (<127) TERMINATORS + BEQ ISCHK ; 0 = NO, GO CHECK LIST + CMP #$80 ; YES, SO CHECK IF PAST 127 + BCS ISFND ; YUP + BCC ISNOT + +ISCHK: + LDY #0 +ISLP: CMP (TCHARS),Y ; IS CHAR WE HAVE A TCHAR? + BEQ ISFND ; YES + PHA + LDA (TCHARS),Y ; NULL = END OF STRING + BEQ ISDUN + PLA + INY + BNE ISLP ; SHOULD ALWAYS LOOP +ISDUN: + PLA ; RETRIEVE CHAR +ISNOT: SEC + RTS ; NOT FOUND +ISFND: + CLC + RTS + + ; ------------------------ + ; CLEAR LBUFF FOR PRINTING + ; ------------------------ + +CLEARP: LDY #0 + LDX #0 +CLRLP: LDA LBUFF,Y + CMP #$80 + BCS CLSKIP ; DON'T PRINT FCN KEYS + CMP #00 ; (X) EOL BECOMES 00 IN XZIP + BNE CLRLP0 + LDA #$8D ; PRINTER NEEDS $8D +CLRLP0: STA LBUFF,X + INX +CLSKIP: INY + CPY LINLEN + BNE CLRLP ; CHECK ALL CHARS + STX PRLEN ; X = NEW LENGTH FOR PRINT + RTS + + + ; ----- + ; INPUT + ; ----- + +ZINPUT: LDA ARG1+LO + CMP #1 ; KEYBOARD? + BNE ZINPEX ; NO, INVALID + + JSR CLRBUF + + LDA WTOP ; RESET LINE COUNT + STA LINCNT + INC LINCNT ; save command line for later + + LDA #0 + STA CHRCNT + STA I+HI ; init locals too + STA I+LO + STA J+HI + STA J+LO + + DEC NARGS + BEQ ZINP3 ; NO TIME LIMIT + LDA ARG2+LO ; GET DELAY WANTED + STA I+HI + DEC NARGS + BEQ ZINP4 ; NO FCN + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI + +ZINP4: JSR TIMIN ; CALL timed input rotine + BCS ZINPEX ; NOBODY HOME + BCC ZINPRK ; send char on home +ZINP3: + JSR GETKEY ; OK, FIND WHICH CHAR WAS PRESSED +ZINPRK: + LDX #0 + JMP PUTBYT ; RETURN CHAR + +ZINPEX: JMP RET0 ; OOPS + + +INTCLL: +; +; can't do this in re-entrant code!!! +; +; LDA #>ZIRET ; SET ZRETURN TO RETURN HERE +; STA PATCHI+HI +; LDA #PUTVAL ; REPAIR ZRETURN +; STA PATCHI+HI +; LDA #)@%^&*( TO ,-.0256789 + +GK1: + LDX #ENDKEY ; GET LENGTH OF LIST +GK2: CMP HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + BEQ GK3 ; FOUND IT + DEX + BPL GK2 ; CHECK THEM ALL + BMI GK4 ; NOT FOUND, CONTINUE OTHER CHECKS +GK3: LDA WANT,X ; GET KEY TO USE INSTEAD + JMP OKj ; JMP + +GK4: CMP #SPACE ; NO CTRL CHARS ACCEPTABLE + BCC BADKEY ; IF < SPACE, BAD +; please allow '+' +; CMP #$2B ; + +; BEQ BADKEY + CMP #$3C ; + BCC OK + CMP #$7C ; | + BEQ OK + CMP #$3F ; ? + BEQ OK + +MASK0: CMP #'z'+1 ;PICK OUT LETTERS NOW + BCS BADKEY ;IF > BAD + CMP #'a' + BCS OK ;IF > OK + CMP #'A' + BCC BADKEY + CMP #'Z'+1 + BCC OK ;IF < OK +BADKEY: JSR BEEP ;BAD KEY, GIVE WARNING NOISE + LDA WTFLAG ; 1 - means don't wait + BNE BDj ; so don't + JMP GKEY0 ;TRY AGAIN +BDj: + LDA #0 ; make char a 0 +OK: + CMP #'0' ; check for number keys + BCC OKj ; nope, < 0 + CMP #'9'+1 ; more than a nine? + BCS OKj ; ayyup +; +; here we check for the apple keys being down too +; + LDX APKEY1 ; check for open apple + BMI OKj1 ; pressed, so pretend it is a function key + LDX APKEY2 ; how about the other one + BPL OKj ; not pressed, so use as number key +; +; transform number key into a function key +OKj1: + CLC ; get ready for add + ADC #84 ; transforms '1'-'9' to 133-141 + CMP #132 ; but '0' wants to be a 142! + BNE OKj ; but it's not it + CLC ; again, don't want carry + ADC #10 ; voila! +OKj: + STA IOCHAR ;HOLD ON TO IT + ADC RNUM1 ;FUTZ WITH RANDOM + STA RNUM1 + EOR RNUM2 + STA RNUM2 + PLA ; RESTORE + TAY ; EVERYTHING + PLA + TAX + LDA IOCHAR ; GET CHAR INTO [A] + RTS ; AND RETURN IT + +HAVE: DB $0B,$0A,$08,$15 +; turns ctrl-(left side of keyboard) to function keys +; DB $11,$01,$1A,$17,$13,$18,$05,$04,$03,$12,$06,$16,$14,$07,$02,$19 + DB $3C,$5F,$3E,$40,$25,$5E,$26 +WANT: DB 129,130,131,132 +; DB 133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148 + DB $2C,$2D,$2E,$32,$35,$36,$37 +ENDKEY EQU $-WANT-1 + +; INPUT: routine locals! +CHARCNT: DB 0 ; where into buffer goes char +SVCHAR: DB 0 ; where to save the char before printing + +IRET: DB 0 ; FLAG TELLS IF RETURNLESS CALL +OLD0CHZ: DB 0 ; HOLDS WHERE CURSOR WAS WHEN LEFT +OLD1CHZ: DB 0 ; A WINDOW SO CAN RETURN THERE +OLD0EHZ: DB 0 ; WHEN REENTER THE WINDOW +OLD1EHZ: DB 0 ; (MUST BE IN THIS ORDER!) +OLD0CVT: DB 0 +OLD1CVT: DB 0 + +OLDWL: DB 0 ; SAVE WLEFT & WWDTH WHILE IN SCREEN 1 +OLDWD: DB 0 + +MTEMP: DB 00,00 ; temp spot for math routines +TYPE: DB 0 ; PARTIAL OR NORMAL (WHOLE) SAVE/RESTORE +ASSVLU: DB 0 ; how many args to this subroutine +BRKCHR: DB 0 ; READ BREAK CHAR +RDFLAG: DB 0 ; 0 - only read 1 - do lex on it +FONT: DB 1,1 ; KEEP TRACK OF CURRENT FONT FOR CHANGES + ; remember for each window +MORE: DB "[MORE]" +MOREL EQU $-MORE +SLOTM: DB EOL + DB "Printer Slot 1-7: " +SLOTML EQU $-SLOTM + +STRYM: DB "The story is loading ..." +STRYML EQU $-STRYM + + END + + \ No newline at end of file diff --git a/apple/xzip/machine.asm b/apple/xzip/machine.asm new file mode 100644 index 0000000..49a30aa --- /dev/null +++ b/apple/xzip/machine.asm @@ -0,0 +1,386 @@ + PAGE + STTL "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + +; ----------------- +; PRINT CHAR IN [A] +; ----------------- + +CHAR: STA IOCHAR ; SAVE HERE + TXA ; SAVE [X] AND [Y] + PHA + TYA + PHA + LDA IOCHAR +CHAR1: JSR MCOUT + CMP #$8D ; check for + BNE CHj ; nope +; +; move cursor back to left margin +; + LDA ZBEGIN+ZLMRG+1 ; set left margin + STA EHZ ; positions +CHj: + PLA ; RESTORE [X] AND [Y] + TAY + PLA + TAX + RTS + +; ----------------------- +; 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 + STY J ; COUNTER + LDX #0 ; INIT CHAR-FETCH INDEX +DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE +STRING: DW $0000 ; DUMMY OPERAND BYTES +; LDY INVFLG ; INVERSE? +; BPL DOUT1 ; YES + ORA #%10000000 ; ELSE MAKE IT NORMAL +DOUT1: JSR CHAR + INX + DEC J ; LOOP TILL + BNE DOUT ; OUT OF CHARS + RTS + + +; ----------------------- +; SEND [LBUFF] TO PRINTER +; ----------------------- +; ENTRY: LENTH OF LINE IN [PRLEN] + +PLEAV: RTS + +PPRINT: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? + BEQ PLEAV ; NO, SCRAM IMMEDIATELY + LDA SCRIPTF ; SCRIPTING ON? + BEQ PLEAV ; NO, EXIT + LDA CSW+LO ;SAVE NORMAL OUTPUT HOOK + PHA + LDA CSW+HI + PHA + LDA EHZ ; IF 80 COL + PHA + LDA ALTCSW+LO ;LOAD SCRIPTING HOOK + STA CSW+LO + LDA ALTCSW+HI + STA CSW+HI + LDA #0 + STA EHZ + LDY #0 +PP5: LDA LBUFF,Y ;GET A CHAR TO SEND OUT + JSR MCOUT + INY + DEC PRLEN ;LINE COUNT + BNE PP5 ;PRINT WHOLE LINE + + ;ALL DONE, RESET TO NORMAL AND LEAVE + + PLA ;RETRIEVE CURRENT CURSOR POSITION + STA EHZ + PLA + STA CSW+HI + PLA + STA CSW+LO + RTS + +PSTAT: DB 0 ;SET TO CLEAR WHEN BOOT, + ;I PUT IT HERE SO RESTART WON'T ALTER +ALTCSW: DB 0,0 ;(WORD) PRINTER COUT + + ; FIRST TIME USING PRINTER, INITIALIZE IT + +PCHK: LDX #SLOTM + LDY #SLOTML + JSR DLINE + LDA #0 ;ACTUALLY SLOT 1 + JSR DODEF ;DISPLAY IT AS DEFAULT + JSR GETKEY + CMP #EOL + BEQ PC1 ;USE DEFAULT + SEC + SBC #'0' + CMP #8 ;1-7 + BCS PCHK ;OOPS + BCC PC2 ;SKIP AROUND DEFAULT +PC1: LDA #1 ;WHICH IS 1 +PC2: CLC + ADC #$C0 + STA ALTCSW+HI + JSR PISSER ;SEND >CR< TO SCREEN FOR NEATNESS + INC PSTAT ;SET TO ON + LDA CSW+LO ;SAVE NORMAL OUTPUT HOOK + PHA + LDA CSW+HI + PHA + LDA ALTCSW+LO ;LOAD SCRIPTING HOOK + STA CSW+LO + LDA ALTCSW+HI + STA CSW+HI +; jsr INIT_PR ; do initialization +; lda #$07 ; output @ Cs07 +; sta CSW+LO ; okay + LDA #$89 ; OUTPUT PRINTER SETUP SEQUENCE + JSR MCOUT ; START WITH COMMAND CHAR >CTRL-I< + LDA #$B8 ; 8 (80 COL WIDE) + JSR MCOUT + LDA #$B0 ; 0 + JSR MCOUT + LDA #$CE ; N (LF AFTER CR) + JSR MCOUT + LDA CSW+LO ; SAVE REAL PRINTER OUTPUT + STA ALTCSW+LO ; LOC. FOR NEXT TIME + LDA CSW+HI + STA ALTCSW+HI + PLA ; RESET NORMAL OUTPUT + STA CSW+HI + PLA + STA CSW+LO + +; PRINTER SETUP ON THE IIc COPIES THE ROM INTERRUPT VECTOR +; FROM $FFFE IN ROM TO BOTH MAIN & AUX. RAM PAGES @ $FFFE +; THAT PAGE IN MAIN RAM CONTAINS THE MONITOR STUFF SO IS OK +; BUT THAT PAGE IN AUX. RAM IS BEING USED TO CONTAIN A PAGE +; OF GAME CODE. THE FOLLOWING RTN CAUSES THE NEXT USE OF THAT +; PAGE TO READ IT IN NEW FROM THE DISK SO THAT THE VALUES +; WILL ALL BE CORRECT. (6/14/85 Le) +; +; THAT PAGE IS SECTOR $4F IN RAMDSK +; AND IT IS NOT USED +; ASK 85 + + RTS +;INIT_PR: +; jmp (CSW) ; jump to init routine + +; ------------ +; SPLIT SCREEN +; ------------ +; SPLIT SCREEN AT LINE [ARG1] +; DISABLE SPLIT IF [ARG1] = 0 +; IGNORE IF SPLIT ALREADY ENABLED OR [ARG1] >= 24 + +ZSPLIT: LDA ARG1+LO ; GET # OF LINES FOR SCREEN + BEQ NORL ; IF 0 THEN RESTORE SCREEN + CMP #24 ; IS SPLIT REALLY = WHOLE SCREEN + BCS ZSPOUT ; YES, IGNORE + + STA SPSTAT ; NON ZERO = SCREEN IS SPLIT + LDA #$18 ; RESTORE BOTTOM FOR SCROLL + STA WBOTM + LDA WTOP + STA I ; HOLD A SEC + LDA ARG1+LO ; GET BOTTOM OF SPLIT SCREEN (AGAIN) + STA WTOP ; MAKE THAT THE TOP OF THE SECOND SCREEN + CMP LINCNT ; IS SCROLLING SCREEN NOW LESS THAN LINCNT? + BCC ZSPL3 ; NO + STA LINCNT ; YES +ZSPL3: + LDA #0 ; ALIGN CURSOR PROPERLY + STA OLD1CHZ + STA OLD1EHZ + STA OLD1CVT + + LDA CVT + CMP I + BCC ZSPL5 ; FOR TOP SCREEN + CMP WTOP ; OR TO KEEP WITHIN BOTTOM SCREEN + BCS ZSPOUT ; OR IF OK WHERE IT IS, LEAVE IT + + LDA WTOP + STA CVT + LDA ZBEGIN+ZLMRG+1 ; XZIP +ZSPL4: + STA EHZ + JMP BASCAL ; TO MAKE CVT WORK + +ZSPL5: LDA #0 + STA CVT + BEQ ZSPL4 ; JMP + +NORL: ;RESTORE SCREEN TO FULL SCREEN MODE + + LDA #0 ; PUT CURSOR AT TOP OF SCREEN + STA WTOP ; RESTORE FULL SCREEN ALIGNMENT + STA LINCNT + STA SPSTAT ; FLAG NOT SPLIT +ZSPOUT: RTS + + +; ------ +; SCREEN +; ------ +; GO TO TOP WINDOW (TOP OF SCREEN) IF [ARG1] = 1 +; GO TO BOTTOM OF SCREEN IF [ARG1] = 0 +; IGNORE IF SPLIT NOT ENABLED OR [ARG1] <> 0 OR 1 +; FLAG SPLITF WILL BE SET FOR OUTPUT TO DETERMINE +; IF AND WHICH WINDOW TO DISPLAY TO +; (0=BOTTOM 1=TOP) + +ZSCRN: + LDA SPSTAT ; CHECK IF SCREEN IS SPLIT + BEQ ZSPOUT ; NO, SO JUST LEAVE + + JSR CLRBUF ; EMPTY OUTPUT BUFFER BEFORE MOVING + + LDX SPLITF ; SAVE CURSOR OF SCREEN NOW IN +SCRSAV: + LDA CVT + STA OLD0CVT,X + LDA EHZ + STA OLD0EHZ,X + LDA ARG1+LO ; CHECK WHICH WINDOW + BNE SCRN1 ; TOP SCREEN + +SCRN0: LDA #$FF ; SCROLLING SCREEN SO + STA SCRIPT ; AL RTN + +SCRN1: CMP #01 + BNE ZSPOUT ; INVALID SCREEN ID + + STA SPLITF ; SET FLAG TO UNSCROLLING SCREEN (1) + LDA XSIZE ; SAVE MARGINS + STA OLDWD + + LDA #0 + STA SCRIPT ; SET SCRIPTNG OFF, NOT ALLOWED THIS SCREEN + LDA #79 + STA XSIZE ; SET FOR TOP SCREEN USING WHOLE WIDTH +SCRNP: + LDX SPLITF ; WHICH SCREEN + LDA FONT,X ; get old font + JSR CHFONT ; now change font to this screen's last font + + LDX SPLITF ; WHICH SCREEN + LDA OLD0CVT,X ; SET CURSOR TO WHERE IT WAS IN THAT WINDOW + STA CVT + LDA OLD0EHZ,X + STA EHZ + JMP BASCAL ; SET CURSOR (+ LEAVE) + + +; ------ +; MARGIN +; ------ + +ZMARG: JSR CLRBUF ; CLEAR LBUFF BEFORE RESETTING LINE MARGINS + LDA ARG2+LO ; SET RIGHT MARGIN + STA ZBEGIN+ZRMRG+1 + LDA ARG1+LO ; GET LEFT MARGIN POSITION + STA ZBEGIN+ZLMRG+1 + STA EHZ + + LDA #79 ; FULL WIDTH + SEC + SBC ARG2+LO ; SUBTRACT BOTH MARGINS + SBC ARG1+LO ; TO GET NEW WIDTH + STA XSIZE + STA OLDWD ; JIC + RTS + + +; ------------ +; CLEAR SCREEN +; ------------ + +CLS: JSR HOME ; CLEAR & HOME CURSOR + LDA ZBEGIN+ZLMRG+1 ; GET LEFT MARGIN + STA EHZ + RTS + +PISSER: LDA #$8D + JMP MCOUT + + +; ----- +; SOUND +; ----- +; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID +; (EZIP) + +ZSOUND: LDA ZBEGIN+ZMODE + AND #%00100000 + BEQ ZSOEX ; NOT ENABLED + LDX ARG1+LO ; GET SOUND WANTED + DEX + BEQ BEEP + DEX + BNE ZSOEX ; INVALID + LDY #$FF ; DURATION ($C0 = .1 SEC) +BOOP: LDA #$10 ; TONE ($0C = 1 KHZ) + JSR MWAIT + LDA SPKR ; TOGGLE SPEAKER + DEY + BNE BOOP +ZSOEX: RTS + +BEEP: JMP BELL ; QUICK BEEP ( 1KHZ @ .1 SEC) + + + ; ------------------------ + ; CHECK IF 128 K OF MEMORY + ; ------------------------ + + ; EXIT: CARRY SET IF NOT 128K, CLEAR IF THERE IS + +MEMCHK: LDA #0 ; START @ 0 + STA TSTVAL +MLOOP1: LDY #0 +MLOOP2: STA $1000,Y ; WRITE [TSTVAL] TO + INY ; MAIN MEMORY + BNE MLOOP2 + INC TSTVAL + LDA TSTVAL + STA WRTBNK+AUX ; SET TO AUX MEMORY + +MLOOP3: STA $1000,Y ; WRITE NEXT VALUE + INY ; TO AUX MEMOYR + BNE MLOOP3 + STA WRTBNK+MAIN ; SET TO MAIN MEMORY + DEC TSTVAL ; RESET TO [TSTVAL] WRITTEN TO MAIN + +MLOOP4: LDA $1000,Y ; CHECK IF WHAT WRITTEN + CMP TSTVAL ; 1ST TO MAIN MEM PG $10 + BNE NO128 ; IS STILL THERE + INY + BNE MLOOP4 + INC TSTVAL + STA RDBNK+AUX ; & SET TO AUX MEMORY + +MLOOP5: LDA $1000,Y ; & SEE IF WHAT WROTE + CMP TSTVAL ; TO AUX MEM IS STILL THERE + BNE NO128 + INY + BNE MLOOP5 + STA RDBNK+MAIN ; RESET TO MAIN MEM + LDA TSTVAL ; LAST THING WAS INC'D + BNE MLOOP1 ; GO TRY W/ NEXT SET OF VALUES, DO 0,1 -> FF,O + CLC + RTS ; SIGNAL OK +NO128: STA RDBNK+MAIN ; RESET TO MAIN MEM + SEC + RTS ; OOPS, ONLY 64K + + + ; NOT IMPLEMENTED ON THE APPLE + +ZCOLOR: +ZDISPL: +ZDCLR: RTS +ZPICNF: JMP PREDF ; SET AS BAD + + END + + + \ No newline at end of file diff --git a/apple/xzip/main.asm b/apple/xzip/main.asm new file mode 100644 index 0000000..9c1afc1 --- /dev/null +++ b/apple/xzip/main.asm @@ -0,0 +1,375 @@ + STTL "--- MAIN LOOP ---" + PAGE + +MLOOP: LDA #0 + STA NARGS ; RESET # ARGUMENTS + + LDA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO + sta SCRIPTF ; SET SCRIPT FLAG ON + beq MLOOP0 ; check scripting flag + lda PSTAT ; CHECK IF PRINTER ALREADY INIT'D + bne MLOOP0 + jsr PCHK ; NO, GO DO IT + + + ; FASTPC - GET NEXT INSTRUCTION +MLOOP0: + LDY ZPCBNK ; THIS IS ANDREW'S CODE - AARRRGGGG! + STA RDBNK,Y + LDY ZPCL + LDA (ZPCPNT),Y + STA RDBNK+MAIN + INC ZPCL + BNE GOTIT1 + JSR CRSZPC +GOTIT1: TAY + + STA OPCODE ; SAVE IT HERE + + IF 0 + lda OPCODE + JSR DBG1 + LDA #' ' + JSR DBG2 + + LDA OPCODE + TAY + ENDIF + + IF 0 ;DEBUG + LDA #0 ; BREAKPOINT #0 + JSR DOBUG + LDA OPCODE + TAY + ENDIF + + + ; DECODE AN OPCODE + + 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: CMP #236 ; XCALL? + BNE OPX5 + JMP OPXCLL ; YES, PROCESS SEPARATELY +OPX5: CMP #250 ; IXCALL + BNE OPX6 + JMP OPXCLL +OPX6: 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 + CMP #$C0 ; IS IT NEW OPCODE RANGE? + BCC ZEXTOP ; YES + JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + +DOXOP: AND #%00011111 ; ISOLATE ID BITS + TAY + LDA OPTXL,Y + STA GOX+1+LO + LDA OPTXH,Y + STA GOX+1+HI +GOX: JSR $FFFF ;DUMMY + JMP MLOOP + + ; HANDLE EXTENDED OPCODE RANGE OPS + +ZEXTOP: CMP #EXTLEN ; OUT OF RANGE? + BCS BADEXT + TAY ; OFFSET ALREADY CORRECT + LDA EXTOPL,Y + STA GOE+1+LO + LDA EXTOPH,Y + STA GOE+1+HI +GOE: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #1 -- ILLEGAL X-OP *** + +BADOPX: LDA #1 + JMP ZERROR + + ; *** ERROR #16 -- ILLEGAL EXTENDED RANGE X-OP *** + +BADEXT: LDA #16 + JMP ZERROR + + ; HANDLE AN XCALL OPCODE + +OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + STA ABYTE + JSR NEXTPC + STA BBYTE + LDA ABYTE ; ONE TO START WITH + LDX #0 + STX ADEX ; INIT ARGUMENT INDEX + BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP +XCALL1: LDA ABYTE ; GET ARG BYTE + ASL A ; SHIFT NEXT 2 BITS + ASL A ; INTO BITS 7 & 6 + STA ABYTE ; HOLD FOR LATER +XCALL2: AND #%11000000 ; MASK OUT GARBAGE + BNE XCALL3 + JSR GETLNG ; 00 = LONG IMMEDIATE + JMP XCNXT +XCALL3: CMP #%01000000 ; SHORT IMMED? + BNE XCALL4 ; NO, TRY ANOTHER + JSR GETSHT ; 01 = SHORT IMMED. + JMP XCNXT +XCALL4: CMP #%10000000 ; LAST TEST + BNE OPX4 ; 11 = NO MORE ARGS + JSR GETVAR ; 10 = VARIABLE +XCNXT: LDX ADEX + LDA VALUE+LO + STA ARG1+LO,X + LDA VALUE+HI + STA ARG1+HI,X + INC NARGS + INX + INX + STX ADEX + CPX #16 + BNE XCALL5 + JMP OPX4 ; DONE, GO DO IT +XCALL5: CPX #8 ; DONE 1ST MODE BYTE? + BNE XCALL1 ; NOT QUITE YET + LDA BBYTE ; SET UP FOR NEXT + STA ABYTE ; MODE BYTE + JMP XCALL2 ; GO DO IT + + + +; ------------- +; HANDLE A 0-OP +; ------------- + +OP0: CMP #190 ; IS IT EXTOP OP + BEQ EXTOP ; YES + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT0L,Y + STA GO0+1+LO + LDA OPT0H,Y + STA GO0+1+HI +GO0: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #2 -- ILLEGAL 0-OP *** + +BADOP0: LDA #2 + JMP ZERROR + + ; THIS OPCODE TELLS THAT NEXT OP IS PART OF THE + ; EXTENDED RANGE OF OPCODES, GET IT AND PROCESS IT + ; (THEY ARE ALL XOPS) + +EXTOP: JSR NEXTPC ; GO GET EXTENDED RANGE OP + STA OPCODE ; SAVE IT + + IF 0 + JSR DBG1 + LDA #'!' + JSR DBG2 + LDA OPCODE + TAY + ENDIF + + JMP OPEXT ; AND HANDLE IT + + +; ------------- +; HANDLE A 1-OP +; ------------- + +OP1: AND #%00110000 ; ISOLATE ARGUMENT BITS + BNE OP1A + + ;JSR GETLNG ; 00 = LONG IMMEDIATE + + ; FASTPC - GET HI OF ARG1 + + LDY ZPCBNK + STA RDBNK,Y + LDY ZPCL + LDA (ZPCPNT),Y + STA RDBNK+MAIN + INC ZPCL + BNE GOTIT2 + JSR CRSZPC +GOTIT2: TAY + + JMP OP1A1 +OP1A: AND #%00100000 ; TEST AGAIN + BNE OP1B + + ;JSR GETSHT ; 01 = SHORT IMMEDIATE + +OP1A1: STA ARG1+HI + + ; FASTPC - GET ARG1+LO + + LDY ZPCBNK + STA RDBNK,Y + LDY ZPCL + LDA (ZPCPNT),Y + STA RDBNK+MAIN + INC ZPCL + BNE GOTIT3 + JSR CRSZPC +GOTIT3: TAY + + STA ARG1+LO + INC NARGS + JMP OP1EX1 +OP1B: JSR GETVAR ; 10 = VARIABLE +OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] +OP1EX1: LDA OPCODE + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT1L,Y + STA GO1+1+LO + LDA OPT1H,Y + STA GO1+1+HI +GO1: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 + + STA ARG1+HI + + ; FASTPC - + + LDY ZPCBNK + STA RDBNK,Y + LDY ZPCL + LDA (ZPCPNT),Y + STA RDBNK+MAIN + INC ZPCL + BNE GOTIT4 + JSR CRSZPC +GOTIT4: TAY + + STA ARG1+LO + INC NARGS + JMP OP2B1 +OP2A: JSR GETVAR ; 1 = VARIABLE +OP2B: JSR V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] +OP2B1: LDA OPCODE ; RESTORE OPCODE BYTE + AND #%00100000 ; ISOLATE 2ND ARG BIT + BNE OP2C + + ;JSR GETSHT ; 0 = SHORT IMMEDIATE + + STA ARG2+HI + + ; FASTPC - + + LDY ZPCBNK + STA RDBNK,Y + LDY ZPCL + LDA (ZPCPNT),Y + STA RDBNK+MAIN + INC ZPCL + BNE GOTIT5 + JSR CRSZPC +GOTIT5: TAY + + STA ARG2+LO + JMP OP2D1 +OP2C: JSR GETVAR ; 1 = VARIABLE +OP2D: LDA VALUE+LO ; MOVE 2ND [VALUE] + STA ARG2+LO ; INTO [ARG2] + LDA VALUE+HI + STA ARG2+HI +OP2D1: INC NARGS ; UPDATE ARGUMENT COUNT + + ; EXECUTE A 2-OP OR EXTENDED 2-OP + +OP2EX: LDA OPCODE + AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT2L,Y + STA GO2+1+LO + LDA OPT2H,Y + STA GO2+1+HI +GO2: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 + \ No newline at end of file diff --git a/apple/xzip/objects.asm b/apple/xzip/objects.asm new file mode 100644 index 0000000..1ffdd70 --- /dev/null +++ b/apple/xzip/objects.asm @@ -0,0 +1,200 @@ + PAGE + STTL "--- OBJECT & PROPERTY HANDLERS ---" + + +; ******************************************** +; AN ASSUMPTION HAS BEEN MADE WITH EZIP OBJECT +; HANDLING. THAT IS THAT ALL THIS STUFF IS +; BEFORE PURBOT AND IS IN MAIN MEMORY +; AND THEREFORE DIRECT ACCESSING IS JUST FINE +; LINDE +; ******************************************** +; ---------------------------------- +; GET ABSOLUTE ADDRESS OF OBJECT [A] +; ---------------------------------- +; ENTER: OBJECT IN A/X (LO/HI) +; EXIT: ADDRESS IN [I] +; (EZIP VERSION) + +OBJLOC: + STX I+HI ; SAVE MSB FOR SHIFTING + ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) + STA I+LO + ROL I+HI + LDX I+HI + ASL A + ROL I+HI ; *4 + ASL A + ROL I+HI ; *8 + ASL A + ROL I+HI ; *16 + SEC + SBC I+LO ; -(*2) + STA I+LO ; SO IS *14 TOTAL + LDA I+HI + STX I+HI + SBC I+HI + STA I+HI + LDA I+LO + CLC + ADC #112 ; ADD OBJECT TABLE OFFSET + BCC OBJ3 + INC I+HI +OBJ3: 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC + LDY #12 ; (EZIP) + 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 #%00111111 ; MASK OUT LENGTH BITS (EZIP) + RTS + + +; ------------------------------- +; FETCH # BYTES IN PROPERTY VALUE +; ------------------------------- +; ENTRY: LIKE "PROPB" EXIT +; (EZIP) + +PROPL: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + RTS + +SHORT: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE + LDA #2 ; BIT 6 = 1, LENGTH =2 + RTS +ONE: LDA #1 ; BIT 6 = 0, LENGTH =1 + RTS + + +; ---------------------- +; POINT TO NEXT PROPERTY +; ---------------------- +; ENTRY: LIKE "PROPB" EXIT + +PROPNX: JSR PROPL ; GET LENGTH OF CURRENT PROP + TAX ; SAVE HERE +PPX: INY ; LOOP UNTIL + BNE PPY + INC I+LO + BNE PPY + INC I+HI +PPY: DEX ; [Y] POINTS TO + BNE PPX ; START OF NEXT PROP + INY ; CORRECT ALIGNMENT + RTS + + +; ----------------------------------------- +; CALL PROPNX, THEN ALIGN [I] AT THAT ENTRY +; ----------------------------------------- +; EXIT: [I] IS ALIGNED AT CURRENT PROPERTY +; [Y] IS ZEROED +; (EZIP) + +NEXTPI: JSR PROPNX ; GET ALIGNMENT OF NEXT PROPERTY INTO [Y] + TYA ; ADD OFFSET TO NEXT PROP + CLC ; TO [I] SO I POINTS DIRECTLY + ADC I+LO ; AT IT + STA I+LO + BCC NXTPI1 + INC I+HI ; ADD IN CARRY +NXTPI1: LDY #0 ; CLEAR [Y] AS IT IS USED AS AN INDEX + 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 ; (EZIP) + LDX ARG1+HI + 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 + CMP #$10 ; CHECK IF IN 2ND WORD + BCC FLS ; YES, GO ALIGN FOR THAT + SBC #16 ; ELSE ALIGN TO 3RD WORD + TAX + LDA I+LO + CLC + ADC #4 ; 3RD FLAG WORD + STA I+LO + BCC FLS0 + INC I+HI + JMP FLS0 ; (END EZIP CHGS) +FLS: 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 + \ No newline at end of file diff --git a/apple/xzip/ops012.asm b/apple/xzip/ops012.asm new file mode 100644 index 0000000..2ab0234 --- /dev/null +++ b/apple/xzip/ops012.asm @@ -0,0 +1,1112 @@ + PAGE + STTL "--- 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: LDX #5 ;MOVE ZPC INTO MPC +ZPRI1: + LDA ZPC,X + STA MPC,X + DEX + BPL ZPRI1 ;NO NEED TO VALIDATE AS ZPC WAS VALID ANYWAY + JSR PZSTR ; PRINT THE Z-STRING AT [MPC] + LDX #5 ; COPY STATE OF [MPC] +ZPRI2: LDA MPC,X ; INTO [ZPC] + STA ZPC,X + DEX + BPL ZPRI2 + RTS + + +; ------ +; PRINTR +; ------ +; DO A "PRINTI," FOLLOWED BY "CRLF" AND "RTRUE" + +ZPRR: JSR ZPRI + JSR ZZCRLF + JMP ZRTRUE + + +; ------ +; RSTACK +; ------ +; "RETURN" WITH VALUE ON STACK + +ZRSTAK: JSR POPVAL ; GET VALUE INTO [X/A] + JMP ZRT1 ; AND GIVE IT TO "RETURN" + + +; ----- +; CATCH +; ----- + +ZCATCH: LDX OLDZSP+HI ; RETURN ZSTACK POINTER AS + LDA OLDZSP+LO ; ZRET WILL NEED IT + JMP PUTBYT + + +; --------- +; ORIGINAL? +; --------- + +; COPY PROTECTION DEVICE, RETURNS TRUE FOR NOW + +ZORIG: JMP PREDS + + + PAGE + STTL "--- 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC ; GET OBJECT ADDR INTO [I] + LDY #8 ; POINT TO "NEXT" SLOT (EZIP) + BNE FIRST1 ; JMP + + +; ------ +; FIRST? +; ------ +; RETURN "FIRST" POINTER IN OBJECT [ARG1] ; +; FAIL IF LAST AND RETURN ZERO +; (EZIP ALTERATIONS) + +ZFIRST: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET OBJECT ADDR INTO [I] + LDY #10 ; POINT TO "FIRST" SLOT +FIRST1: LDA (I),Y ; GET CONTENTS OF SLOT + TAX + INY + LDA (I),Y ; INTO A,X + JSR PUTBYT ; PASS IT TO VARIABLE + LDA VALUE+LO ; EXAMINE THE VALUE JUST "PUT" + BNE PFINE + LDA VALUE+HI + BEQ PYUCK ; FAIL IF IT WAS ZERO +PFINE: JMP PREDS ; ELSE REJOICE + + +; --- +; LOC +; --- +; RETURN THE OBJECT CONTAINING OBJECT [ARG1] ; +; RETURN ZERO IF NONE +; (EZIP ALTERED) + +ZLOC: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + LDY #6 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET THE WORD + TAX + INY + LDA (I),Y + 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 + LDA (I),Y ; OF PROPERTY AT [I] INTO [A] + BMI PTZ2 ; BIT 7 = 1, LENGTH > 2 BYTES + AND #%01000000 + BEQ PTZ1 ; BIT 6 = 0, LENGTH = 1 + LDA #2 ; BIT 6 = 1, LENGTH = 2 + BNE PTZ3 ; JMP +PTZ1: LDA #1 + BNE PTZ3 ; JMP +PTZ2: AND #%00111111 ; ELSE PICK UP SIZE > 2 +PTZ3: LDX #0 ; CLEAR FOR PUTBYT + JMP PUTBYT + + +; --- +; INC +; --- +; INCREMENT VARIABLE [ARG1] + +ZINC: LDA ARG1+LO + JSR VARGET ; FETCH VARIABLE INTO [VALUE] + INC VALUE+LO + BNE ZINC1 + INC VALUE+HI +ZINC1: JMP ZD0 + + +; --- +; DEC +; --- +; DECREMENT VARIABLE [ARG1] + +ZDEC: LDA ARG1+LO + JSR VARGET ; FETCH VAR INTO [VALUE] + LDA VALUE+LO + SEC + SBC #1 + STA VALUE+LO + LDA VALUE+HI + SBC #0 + STA VALUE+HI +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 +; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO +; 2) MOVES AND COMPARES 2 BYTES) + +ZREMOV: + LDA ARG1+LO ; GET SOURCE OBJECT ADDR + LDX ARG1+HI + 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 #7 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET THE DATA + STA K ; HOLD IT + DEY + LDA (I),Y + TAX ; X = HI + LDA K ; A = LO + ORA (I),Y ; COMPARE BYTES + BEQ REMVEX ; SCRAM IF NO OBJECT + LDA K ; PICK UP, DESTROYED BY ORA + JSR OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [I] + LDY #10 ; POINT TO "FIRST" SLOT + LDA (I),Y ; GRAB DATA + TAX + INY + LDA (I),Y ; A=LO, X=HI + CMP ARG1+LO ; IS THIS THE FIRST? + BNE REMVC1 ; NO, KEEP SEARCHING + CPX ARG1+HI ; HM? + BNE REMVC1 + LDY #8 ; ELSE COPY SOURCE'S "NEXT" SLOT + LDA (J),Y + INY ; INTO DEST'S "FIRST" SLOT ([Y] = 10) + INY + STA (I),Y + DEY ; BACK UP TO GET >BYTE + LDA (J),Y + INY + INY + STA (I),Y + BNE REMVC2 ; BRANCH ALWAYS +REMVC1: + JSR OBJLOC + LDY #8 ; GET "NEXT" + LDA (I),Y + TAX + INY + LDA (I),Y + CMP ARG1+LO ; FOUND IT? + BNE REMVC1 ; NO, KEEP TRYING + CPX ARG1+HI + BNE REMVC1 + LDY #8 ; WHEN FOUND + LDA (J),Y ; MOVE "NEXT" SLOT OF SOURCE (THIS OBJECT) + STA (I),Y ; TO "NEXT" SLOT OF DEST + ;(OBJECT THAT REFERENCED THIS ONE) + INY + LDA (J),Y + STA (I),Y +REMVC2: LDA #0 + LDY #6 ; CLEAR "LOC" + STA (J),Y + INY + STA (J),Y + INY ; AND "NEXT" SLOTS ([Y] = 5) + STA (J),Y ; OF SOURCE OBJECT (ARG1) + INY + STA (J),Y +REMVEX: + RTS + + +; ------ +; PRINTD +; ------ +; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + +ZPRD: LDA ARG1+LO + LDX ARG1+HI ; (EZIP) + + ; ENTRY POINT FOR "USL" + +PRNTDC: JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + LDY #12 ; GET PROP TABLE POINTER (EZIP) + 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+LO ; RE-SYNC THE + STA ZSP+LO ; Z-STACK POINTER + LDA OLDZSP+HI + STA ZSP+HI + JSR POPVAL ; POP # LOCALS INTO [X/A] + STX I+HI ; SAVE HERE + JSR POPVAL ; now we need number of args + STA ASSVLU ; for ASSIGNED? + + LDX I+HI ; see how many 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 IRET + STA ZPCL + JSR POPVAL + STX OLDZSP+LO + STA OLDZSP+HI + + LDA ZPCL ; check for zero zpc + BNE RETj ; which means we are returning to + LDA ZPCM ; an internal call + BNE RETj ; rather than just a normal + LDA ZPCH ; return + BNE RETj ; but so far it isn't + + JSR A12VAL ; MOVE [ARG1] TO [VALUE] + JMP ZIRET ; so then do internal return +RETj: + JSR VLDZPC ; MAKE VALID + LDA IRET ; CHECK IF SHOULD RETURN A VALUE + BEQ RETYES ; (0 = RET, 1 = NO RETURN) + RTS ; NO, SO JUST GET OUT OF HERE +RETYES: + 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 (QUAD) 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 + + + + PAGE + STTL "--- 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 + + +; ----------------- +; SIGNED COMPARISON +; ----------------- +; ENTRY: VALUES IN [VALUE] AND [I] +; +; IS [VALUE] > [I] +; +COMPAR: + LDA I+HI + EOR VALUE+HI + BPL SCMP + LDA I+HI + CMP VALUE+HI + BCC PGOOD + JMP PREDF + +SCMP: LDA VALUE+HI + CMP I+HI + BNE SCEX + LDA VALUE+LO + CMP I+LO +SCEX: BCC PGOOD + JMP PREDF + + +; --- +; IN? +; --- +; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? + +ZIN: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [I] + LDY #6 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET DATA + CMP ARG2+HI ; IS IT THERE? + BNE PBAD ; NO + INY + LDA (I),Y + CMP ARG2+LO + 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 + + ; FALL THROUGH ... + + +; --------------------- +; RETURN VALUE IN [X/A] +; --------------------- + +VEXIT: STX VALUE+LO + STA VALUE+HI + JMP PUTVAL + + +; ---- +; BAND +; ---- +; RETURN [ARG1] "AND" [ARG2] + +ZBAND: LDA ARG1+LO + AND ARG2+LO + TAX + LDA ARG1+HI + AND ARG2+HI + JMP VEXIT + + +; ----- +; FSET? +; ----- +; IS FLAG [ARG2] SET IN OBJECT [ARG1]? + +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] +; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + +ZMOVE: JSR ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS + + ; NOW, IF IT IS ANYWHERE + + LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET SOURCE OBJECT ADDR INTO [I] + LDA I+LO ; COPY SOURCE (ARG1) ADDRESS + STA J+LO ; INTO [J] + LDA I+HI + STA J+HI + LDA ARG2+HI ; GET DEST OBJECT ID + LDY #6 ; POINT TO "LOC" SLOT OF SOURCE + STA (I),Y ; AND MOVE IT IN + TAX ; (MOVE ARG2 INTO PARENT SLOT OF ARG1) + LDA ARG2+LO + INY + STA (I),Y ; X/A (HI/LO) SET FOR OBJLOC + JSR OBJLOC ; GET ADDR OF DEST OBJECT INTO [I] (GET PARENT) + + ; NOW SWAP IN NEW VALUE + + LDY #10 ; POINT TO "FIRST" SLOT + LDA (I),Y ; OF PARENT (ARG2) + STA K+HI ; SAVE HERE FOR A MOMENT + LDA ARG1+HI ; GET SOURCE OBJECT ID + STA (I),Y ; MAKE IT "FIRST" OF PARENT + INY + LDA (I),Y + TAX + LDA ARG1+LO + STA (I),Y + TXA + ORA K+HI ; CHECK OLD "FIRST" OF DEST/PARENT + BEQ ZMVEX ; SCRAM IF ZERO + TXA ; GET LO BYTE AGAIN + LDY #9 ; MAKE OLD "FIRST" OF PARENT + STA (J),Y ; THE "NEXT" (SIBLING) OF THIS OBJECT (ARG1) + DEY ; I.E. ADD THIS ONE AT THE TOP OF LIST + LDA K+HI ; & GET >BYTE + STA (J),Y +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 + LDA #0 + 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 + ADC #0 ; PICK UP CARRY FROM MPCM + STA MPCH ; TO GET TOP BIT + JMP VLDMPC + + +; ---- +; GETP +; ---- +; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 + +ZGETP: JSR PROPB +GETP1: JSR PROPN ; GET ADDR OF PROP TBL + CMP ARG2+LO ; GET PROP ID + BEQ GETP3 ; FOUND IT + BCC GETP2 ; NOT THERE + JSR NEXTPI ; GET NEXT PROP, ALIGN [I] TO IT (EZIP) + JMP GETP1 ; TRY AGAIN WITH NEXT PROP + + ; PROPERTY NOT THERE, GET DEFAULT + +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 ; GET LENGTH OF PROP INTO [A] + INY ; MAKE [Y] POINT TO 1ST BYTE OF PROP + CMP #1 ; IF LENGTH =1 + BEQ GETPB ; GET A BYTE PROPERTY + CMP #2 ; IF LENGTH = 2 + 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: LDA ARG1+LO + LDX ARG1+HI ; (EZIP) + JSR OBJLOC + LDY #12 ; (EZIP) + 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 + +GETPT1: LDA (I),Y + AND #%00111111 ; MASK OUT LENGTH BITS (EZIP) + + CMP ARG2+LO ; CHECK ID + BEQ GETPT2 + BCS DDD + JMP DORET ; BEYOND IT, SO NOT THERE + +DDD: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT0 ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + JMP AAA + +SHORT0: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE0 + LDA #2 ; BIT 6 = 1, LENGTH =2 + JMP AAA +ONE0: LDA #1 ; BIT 6 = 0, LENGTH =1 + +AAA: TAX ; SAVE HERE +PPPX: INY ; LOOP UNTIL + BNE PPPY + INC I+HI +PPPY: DEX ; [Y] POINTS TO + BNE PPPX ; START OF NEXT PROP + INY ; CORRECT ALIGNMENT + TYA ; ADD OFFSET TO NEXT PROP + CLC ; TO [I] SO I POINTS DIRECTLY + ADC I+LO ; AT IT + STA I+LO + BCC CCCC1 + INC I+HI ; ADD IN CARRY +CCCC1: LDY #0 ; CLEAR [Y] AS IT IS USED AS AN INDEX + + JMP GETPT1 + +GETPT2: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT1 ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + JMP BBB + +SHORT1: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE1 + LDA #2 ; BIT 6 = 1, LENGTH =2 + JMP BBB +ONE1: LDA #1 ; BIT 6 = 0, LENGTH =1 + +BBB: INY ; INC TO POINT AT PROPERTY VALUE (EZIP) + +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 [AR +; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO + +ZNEXTP: JSR PROPB ; ALIGN [I] AT PROPERTY TBL'S 1ST ENTRY + 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 NEXTPI ; ELSE TRY NEXT PROPERTY (EZIP) + JMP NXTP1 +NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +NXTP3: JSR PROPN ; GET THE PROPERTY # + LDX #0 ; FOR PUTBYT (EZIP) + 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 + + +; ----- +; THROW +; ----- + +ZTHROW: LDA ARG2+LO ; SET ZSTACK POINTER + STA OLDZSP+LO ; UP FOR ZRET + LDA ARG2+HI + STA OLDZSP+HI + JMP ZRET + + END + \ No newline at end of file diff --git a/apple/xzip/opsx.asm b/apple/xzip/opsx.asm new file mode 100644 index 0000000..cf3e492 --- /dev/null +++ b/apple/xzip/opsx.asm @@ -0,0 +1,740 @@ + PAGE + STTL "--- 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!) + + +; ---------------------------- +; ICALL,ICALL1, ICALL2, IXCALL +; ---------------------------- + +ZICALL: +ZICLL1: +ZICLL2: +ZIXCLL: LDA #1 ; SET FLAG FOR RETURNLESS CALL + STA IRET + BNE IENTR ; JMP OVER NORMAL SETTING + + +; ------------------- +; XCALL, CALL1, CALL2 +; ------------------- + +ZXCALL: ; DROP THROUGH +ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +ZCALL2: + + +; ---- +; CALL +; ---- +; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +; ([ARG5]-[ARG8] FOR XCALL (EZIP)) + +ZCALL: LDA #0 + STA IRET ; SET FLAG TO RETURN SOMETHING +IENTR: LDA ARG1+LO + ORA ARG1+HI ; IS CALL ADDRESS ZERO? + BNE DOCALL ; NO, CONTINUE + LDA IRET ; any ret value? + BEQ Ij ; yes, so return a zero + + RTS ; otherwise, just end +Ij: + LDX #0 + JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER + LDA OLDZSP+HI + JSR PUSHXA + LDA ZPCL ; AND LSB OF [ZPC] + LDX IRET ; AND RETURN FLAG + 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 + ASL ARG1+LO ; MULTIPLY [ARG1] + ROL ARG1+HI ; (BY 2) + ROL A ; >BIT INTO [A] + STA ZPCH ; NEW >BIT OF [ZPC] + ASL ARG1+LO ; BY 4 (EZIP) + ROL ARG1+HI + ROL ZPCH + LDA ARG1+HI ; GET NEW 0, just ignore! + ORA ARG3+LO + BEQ INTNF ; SAY NOT FOUND + + LDA NARGS ; IS THERE A RECORD SPEC? + CMP #4 + BEQ SET4 +SETDEF: LDA #130 ; NO, SET DEFAULT + STA ARG4+LO + +SET4: LDA ARG4+LO + BEQ SETDEF ; GO BACK AND GET VALUE + LDA #0 ; COMPARE BYTE OR WORD? + ASL ARG4+LO + ROL A ; PICK UP INDICATOR + LSR ARG4+LO ; CLEAR FROM RECORD LENGTH + STA TYPE ; BYTE (0) OR WORD (1) + LDA TYPE ; SET FLAG + BNE SETTBL + LDA ARG1+LO ; IF ONLY BYTE, MOVE IT + STA ARG1+HI ; TO FIRST BYTE CHECKED + +SETTBL: LDA ARG2+LO ; PICK UP TBL ADDR + STA MPCL + LDA ARG2+HI + STA MPCM + LDA #0 + STA MPCH ; ONLY A WORD ADDR, SO IN 1ST 64K + JSR VLDMPC + +INTLP: LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + JSR GETBYT ; GET 1ST BYTE + CMP ARG1+HI ; DOES IT = THE VALUE LOOKING FOR? + BNE INTNXT ; NO + LDA TYPE + BEQ INTFND ; ONLY COMPARING A BYTE SO FOUND! + JSR GETBYT + CMP ARG1+LO + BEQ INTFND ; YES, FOUND IT +INTNXT: + LDA VWCUR+0 ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC ARG4+LO ; ENTRY + STA MPCL + BCC INEXT0 + + LDA VWCUR+1 ; PICK UP CARRY + ADC #0 + STA MPCM + LDA VWCUR+2 + ADC #0 + STA MPCH + JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE + +INEXT0: DEC ARG3+LO ; CHECKED ALL ENTRIES? + BNE INTLP + LDA ARG3+HI + BEQ INTNF + DEC ARG3+HI + BNE INTLP + +INTNF: + LDA #0 ; 0 = NOT FOUND + STA VALUE+LO + STA VALUE+HI + JSR PUTVAL + JMP PREDF ; FAILED! + +INTFND: + LDA VWCUR+LO + STA VALUE+LO ; AND SET TO RETURN THE VALUE + LDA VWCUR+HI + STA VALUE+HI + JSR PUTVAL ; SEND IT BACK + JMP PREDS ; AND SCREEM SUCCESS + +; ---- +; BCOM +; ---- +; COMPLEMENT [ARG1] + +ZBCOM: LDA ARG1+LO + EOR #$FF + STA VALUE+LO + LDA ARG1+HI + EOR #$FF + STA VALUE+HI + JMP PUTVAL + + +; ----- +; COPYT +; ----- + +ZCOPYT: + LDA ARG2+LO ; CHECK OUT WHAT'S TO BE DONE + ORA ARG2+HI + BNE ZC0 + JMP CASE1 ; ZERO LENGTH BYTES OF SOURCE +ZC0: + LDA ARG3+HI + CMP #$7F + BCC CASE2 + JMP CASE3 ; FORWARD COPY + + ; CASE2 - CHECK IF FORWARD OR BACKWARD COPY + +CASE2: LDA ARG1+HI ; IF SRC < DEST + CMP ARG2+HI + BCC CHK2 + BEQ ZC1 + JMP FRWRD ; NO +ZC1: LDA ARG1+LO + CMP ARG2+LO + BEQ CHK2 + BCS FRWRD ; NO +CHK2: LDA ARG1+LO ; AND SRC + LENGTH > DEST + CLC + ADC ARG3+LO + STA I+LO + LDA ARG1+HI + ADC ARG3+HI + CMP ARG2+HI + BCC FRWRD ; NO + BNE BKWRD ; YES + LDA I+LO + CMP ARG2+LO + BEQ FRWRD ; DEBUG, IF EQUAL REALLY LESS + BCS BKWRD ; OVERLAPS SO DO BACKWARD COPY + + ; ELSE FALL THROUGH TO FORWARD COPY + +FRWRD: LDA #0 ; USE GETBYT CAUSE MAY BE + STA MPCH ; BEYOND MAIN MEMORY + LDA ARG1+HI + STA MPCM + LDA ARG1+LO + STA MPCL + JSR VLDMPC ; AND ALIGN TO CORRECT PAGE + LDA ARG2+LO + STA I+LO + LDA ARG2+HI + CLC + ADC ZCODE ; MAKE ABSOLUTE + STA I+HI + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI +FRLP: + JSR DECJ + BCC FRDUN ; CARRY CLEAR ON $FFFF + JSR GETBYT + LDY #0 + STA (I),Y + + INC I+LO + BNE FRLP + INC I+HI + JMP FRLP + +FRDUN: RTS + + +BKWRD: + LDA ARG3+LO ; DECR 1ST TO GET CORRECT OFFSET + STA J+LO + LDA ARG3+HI + STA J+HI + JSR DECJ + LDA ARG1+LO ; SET TO END OF SOURCE & DEST. + CLC + ADC J+LO + STA I+LO + LDA ARG1+HI + ADC J+HI + CLC + ADC ZCODE ; ABSOLUTE + STA I+HI + LDA ARG2+LO + CLC + ADC J+LO + STA K+LO + LDA ARG2+HI + ADC J+HI + CLC + ADC ZCODE + STA K+HI +BKLP: LDY #0 + LDA (I),Y + STA (K),Y + LDA I+LO ; DECR >BYTE AFTER X00 BYTE MOVED + BNE BKL0 + DEC I+HI +BKL0: DEC I+LO + LDA K+LO + BNE BKL1 + DEC K+HI +BKL1: DEC K+LO + JSR DECJ ; RETURNS CARRY CLEAR ON $FFFF + BCS BKLP +BKDUN: + RTS + + ; ZERO LENGTH # OF BYTES OF SOURCE + +CASE1: LDA ARG1+LO + STA I+LO + LDA ARG1+HI + CLC + ADC ZCODE ; ABSOLUTE + STA I+HI + LDA ARG3+LO ; SET UP COUNTER + STA J+LO + LDA ARG3+HI + STA J+HI + LDY #0 +C1LP: JSR DECJ ; CARRY CLEAR WHEN J = $FFFF + BCC C1DUN + LDA #0 + STA (I),Y + INY + BNE C1LP + INC I+HI ; NEXT PAGE + JMP C1LP +C1DUN: + RTS + + ; 2'S COMPLEMENT LENGTH (XOR + 1) THEN DO FORWARD COPY + +CASE3: + LDA ARG3+LO + EOR #$FF + STA ARG3+LO + LDA ARG3+HI + EOR #$FF + STA ARG3+HI + INC ARG3+LO + BNE GOFRWD + INC ARG3+HI +GOFRWD: JMP FRWRD + + +; --------- +; ASSIGNED? +; --------- + + +ZASSND: + LDA ARG1+LO ; COMPARE TO # OF OPTIONALS FROM LAST CALL + CMP ASSVLU + BCC DOYES ; IF LESS OR EQUAL, WAS ASSIGNED + BEQ DOYES + JMP PREDF +DOYES: + JMP PREDS + + +; ------------- +; LOGICAL SHIFT +; ------------- +; SHIFT ARG1, ARG2 BITS (LEFT IF ARG2 IS POS. RIGHT IF NEG.) + +ZSHIFT: LDA ARG1+LO ; SET UP FOR SHIFT + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCS SRIGHT + + ; SHIFT LEFT + + TAY ; COUNT +SLP1: ASL VALUE+LO + ROL VALUE+HI + DEY + BNE SLP1 + JMP PUTVAL ; AND RETURN THE VALUE + +SRIGHT: EOR #$FF ; COMPLEMENT + TAY +SLP2: LSR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL SLP2 + JMP PUTVAL + + +; ---------------- +; ARITHMETIC SHIFT +; ---------------- +; PROPAGATING SIGN BIT ON RIGHT SHIFT + +ZASHFT: LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCC ZSHIFT ; SAME AS LOGICAL SHIFT + LDX ARG1+LO ; SET UP FOR SHIFT + STX VALUE+LO + LDX ARG1+HI + STX VALUE+HI + + EOR #$FF ; COMPLEMENT COUNT + TAY +ASLP2: LDA ARG1+HI + ASL A ; GET SIGN BIT + ROR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL ASLP2 + JMP PUTVAL + + END + \ No newline at end of file diff --git a/apple/xzip/read.asm b/apple/xzip/read.asm new file mode 100644 index 0000000..1a50d6a --- /dev/null +++ b/apple/xzip/read.asm @@ -0,0 +1,651 @@ + STTL "--- READ HANDLER ---" + PAGE +; ---- +; READ +; ---- +; READ LINE INTO TABLE [ARG1] ; PARSE INTO TABLE [ARG2] (IF ARG2 IS THERE) + +ZREAD: + LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + CLC ; ABSOLUTE + ADC ZCODE + STA RDTBL1+HI ; AND PLACE IT HERE TO USE + LDA ARG1+LO + STA RDTBL1+LO ; LSBS NEED NOT CHANGE + + LDA #0 ; TURN OFF FLAGS + STA PSVFLG ; FOR ZLEX + STA VOCFLG + + LDX NARGS + DEX ; IF 2ND TBL ADDR 0 OR NOT THERE + BEQ ONLYRD ; JUST READ IN DON'T DO CONVERSION (X) + LDX #0 ; JIC + LDA ARG2+HI + ORA ARG2+LO + BEQ ONLYRD + + LDA ARG2+HI + CLC + ADC ZCODE + STA RDTBL2+HI + LDA ARG2+LO + STA RDTBL2+LO + + LDX #1 ; 1 = DO IT ALL (X) +ONLYRD: + STX RDFLAG ; CHECK AGAIN AFTER READ IN WHAT TO DO + + JSR INPUT ; READ LINE; RETURN LENGTH IN [RDTBL1],1 + + LDA RDFLAG ; FLAG (X) + BEQ RDEX ; IF INPUT ONLY, LEAVE NOW + JSR DOREST + + ; RETURN NOW ONLY WANTED READ PART +RDEX: + lda #$F0 + sta RDFLAG + + LDA BRKCHR ; GET BREAK CHAR + LDX #0 + + JMP PUTBYT ; RETURN IT + + ; IF TIMEOUT, [A]=0 SO WILL QUIT W/NO RESULTS + +DOREST: LDY #1 + LDA (RDTBL1),Y ; GET # OF CHARS IN INBUF + STA LINLEN ; SAVE # CHARS IN LINE + LDA #0 + STA WRDLEN ; INIT # CHARS IN WORD COUNTER + STA (RDTBL2),Y ; CLEAR "# WORDS READ" SLOT ([A] = 0) +NOCLR: INY ; = 2 + STY SOURCE ; INIT SOURCE TABLE PNTR + STY RESULT ; AND RESULT TABLE POINTER + + ; MAIN LOOP STARTS HERE + +READL: LDY #0 ; POINT TO "MAX # WORDS" SLOT + LDA (RDTBL2),Y ; AND READ IT + BEQ RDERR ; (5/14/85 - FORCE # WORDS TO + CMP #59 ; BE BETWEEN 1 AND 59) + BCC RD0 +RDERR: LDA #58 ; (5/16/86 - MAKE IT 58, 59 LOST) + STA (RDTBL2),Y ; Le) +RD0: INY ; (Y = 1) POINT TO "# WORDS READ" SLOT + CMP (RDTBL2),Y ; TOO MANY WORDS? + BCC RLEX ; YES, SO LEAVE, IGNORING THE REST + +; BCS RL1 ; CHANGED 5.2.85 IN ZIP & EZIP +; ; *** ERROR #13: PARSER OVERF<*** +; +; LDA #13 +; JMP ZERROR + +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 #9 ; 9 CHARS DONE? (EZIP) + 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 #8 ; 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 (RDTBL1),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 (RDTBL1),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 (RDTBL2),Y ; FETCH THE # WORDS READ + CLC + ADC #1 ; INCREMENT IT + STA (RDTBL2),Y ; AND UPDATE + LDY #0 + STY WRDLEN ; CLEAR # CHARS IN WORD + + LDA PSVFLG ; IF SHOULD PRESERVE WHAT'S IN + BEQ READL4 + LDA VALUE+HI ; RDTBL2 AND NOT FOUND (VALUE = 0) + ORA VALUE+LO + BEQ READL5 ; JUST SKIP OVER + +READL4: 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 + +READL5: LDA RESULT ; UPDATE THE + CLC ; RESULT TABLE POINTER + ADC #4 ; SO IT POINTS TO THE + STA RESULT ; NEXT ENTRY + JMP READL ; AND LOOP BACK + + +; --- +; LEX +; --- +; DO PARSE OF TBL1 INTO TBL2 (2ND HALF OF READ) + +ZLEX: LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + CLC ; ABSOLUTE + ADC ZCODE + STA RDTBL1+HI ; AND PLACE IT HERE TO USE + LDA ARG1+LO + STA RDTBL1+LO ; LSBS NEED NOT CHANGE + + LDA ARG2+HI + CLC + ADC ZCODE + STA RDTBL2+HI + LDA ARG2+LO + STA RDTBL2+LO + + DEC NARGS + DEC NARGS + BEQ NORMLEX ; USE NORMAL VOCAB TBL + + LDA #1 ; USE ARG3 VOCAB TBL + STA VOCFLG + LDA #0 + DEC NARGS + BEQ NOSAVE ; ZERO UNFOUND WORDS + LDA #1 ; PRESERVE UNFOUND WORD SLOT FLAG +NOSAVE: STA PSVFLG + JMP DOLEX + +NORMLEX: LDA #0 + STA VOCFLG ; USE NORMAL VOCAB TBL + STA PSVFLG ; AND WILL BE NO PRESERVING + +DOLEX: JMP DOREST ; GO DO LEXICAL CONVERSION AND JUST RETURN + + +; ----- +; ZWSTR +; ----- +; CONVERT A WORD TO A ZWORD, PLACE IN ARG4 TBL + +ZWSTR: LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + CLC ; ABSOLUTE + ADC ZCODE + STA RDTBL1+HI ; AND PLACE IT HERE TO USE + LDA ARG1+LO + STA RDTBL1+LO ; LSBS NEED NOT CHANGE + + ; (IGNORE WORD LENGTH CAUSE CHECK FOR BREAK CHAR (9 CHAR MAX)) + + LDA ARG3+LO ; ADD OFFSET INTO INBUF + CLC ; AS NOT SURE OF OFFSET SIZE + ADC RDTBL1+LO ; MAKE SO CAN BE ANY SIZE + STA RDTBL1+LO + LDA ARG3+HI + ADC RDTBL1+HI + STA RDTBL1+HI + + LDA ARG4+HI ; AND MAKE RECIPIENT ADDR ABSOLUTE + CLC + ADC ZCODE + STA RDTBL2+HI + LDA ARG4+LO + STA RDTBL2+LO + + ; START A NEW WORD + + LDA #9 + STA LINLEN ; 1 WORD'S WORTH + LDA #0 + STA WRDLEN + LDX #8 ; CLEAR Z-WORD INPUT BUFFER +WSTR1: STA IN,X ; [A] = 0 + DEX + BPL WSTR1 + + ; THIS LOOP READS FROM INBUF TIL BREAK OR 9 CHARS READ + +WSTR2: LDY WRDLEN ; SOURCE OFFSET SAME AS WRDLEN + LDA (RDTBL1),Y ; ELSE GRAB NEXT CHAR + JSR BREAK ; IS IT A BREAK? + BCS WSTR3 ; YES IF CARRY WAS SET + + LDY WRDLEN ; SOURCE OFFSET SAME AS WRDLEN + LDA (RDTBL1),Y ; ELSE GRAB NEXT CHAR + + LDX WRDLEN ; ELSE STORE THE CHAR + STA IN,X ; INTO THE INPUT BUFFER + INC WRDLEN ; ONE MORE CHAR IN WORD + DEC LINLEN ; ONE LESS IN LINE + BNE WSTR2 ; AND LOOP BACK TIL DONE + +WSTR3: LDA WRDLEN ; ANY CHARS IN WORD YET? + BEQ WOOPS ; APPARENTLY NOT, OOPS + JSR CONZST ; CONVERT ASCII IN [IN] TO Z-STRING + + LDY #5 ; MOVE FROM [OUT] TO RDTBL2 +WSTR4: LDA OUT,Y ; (RDTBL2 HAS DIFF USE HERE FROM IN ZREAD) + STA (RDTBL2),Y + DEY + BPL WSTR4 +WOOPS: RTS + + +; ----------------------------------- +; FIND BASE ADDR OF RESULT ENTRY SLOT +; ----------------------------------- + +EFIND: LDA RDTBL2+LO ; LSB OF RESULT TABLE BASE + CLC + ADC RESULT ; AND CURRENT POINTER + STA ENTRY+LO ; SAVE IN [ENTRY] + LDA RDTBL2+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 (RDTBL1),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? +; --------------------------------- +; ------------------ +; NORMAL BREAK CHARS +; ------------------ + +BRKTBL: DB '!?,.' ; IN ORDER OF + DB $0D ; ASCII ENDING FREQUENCY + DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED + DB 0 ; ZERO ADDED FOR ZWSTR (X) +NBRKS EQU $-BRKTBL ; # NORMAL BREAKS + +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 + + +; --------------------- +; IS CHAR IN [A] A SIB? +; --------------------- + +SIB: STA IOCHAR ; SAVE TEST CHAR + LDA ZBEGIN+ZVOCAB ; GET 1ST BYTE IN VOCAB TABLE + LDY ZBEGIN+ZVOCAB+1 + STA MPCM + STY MPCL + LDA #0 + STA MPCH + JSR VLDMPC ; GET CORRECT PAGE + JSR GETBYT ; HAS # SIBS + STA J ; USE AS AN INDEX +SBL: JSR GETBYT ; GET NEXT SIB + CMP IOCHAR ; MATCHED? + BEQ FBRK0 ; YES, REPORT IT + DEC J + BNE SBL ; ELSE KEEP LOOPING + LDA IOCHAR + CLC ; NO MATCH, SO + RTS ; EXIT WITH CARRY CLEAR +FBRK0: LDA IOCHAR +FBRK: SEC ; EXIT WITH CARRY SET + RTS ; IF MATCHED WITH A BREAK CHAR + + +; ----------------- +; VOCABULARY SEARCH +; ----------------- +; ENTRY: 6-BYTE TARGET Z-WORD IN [OUT] +; EXIT: VIRTUAL ENTRY ADDRESS IN [VALUE] IF FOUND ; +; OTHERWISE [VALUE] = 0 + +VWLEN EQU I ; ********** +VWCUR EQU J+HI + +FINDW: LDA VOCFLG ; USE WHAT VOCAB TBL? + BEQ FWL2 ; NORMAL + LDA ARG3+HI ; IF ALTERNATE VOCTBL + LDY ARG3+LO ; IT'S ADDR IS IN ARG3 + JMP FWL3 + +FWL2: LDA ZBEGIN+ZVOCAB ; GET VIRTUAL ADDR OF VOCAB TBL + LDY ZBEGIN+ZVOCAB+1 +FWL3: STA MPCM + STY MPCL + LDA #0 + STA MPCH + JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # SIBS + CLC + ADC MPCL ; GET ACTUAL BASE ADDR OF VOCAB ENTRIES + STA MPCL + BCC FWL0 + INC MPCM +FWL0: JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # BYTES PER ENTRY (AND MOVE TO NEXT BYTE) + STA ESIZE ; SAVE IT HERE + STA VWLEN+0 ; AND HERE + LDA #0 ; CLEAR REST OF COUNTER + STA VWLEN+1 + STA VWLEN+2 + + JSR GETBYT ; GET # OF ENTRIES IN TBL (MSB) + STA NENTS+HI ; AND STUFF IT IN [NENTS] + JSR GETBYT ; DON'T FORGET THE LSB! + STA NENTS+LO + LDA NENTS+HI + BPL SORTED + JMP UNSORTED ; VOCAB LIST IS UNSORTED, HANDLE DIFFERENTLY + +SORTED: LDA #0 ; FIND SIZE OF VAOCAB TBL + STA VOCEND ; TO LOCATE THE END OF IT + STA VOCEND+1 + STA VOCEND+2 + LDX ESIZE + +FWL1: CLC + LDA VOCEND ; (# OF ENTRIES) * (ENTRY SIZE) + ADC NENTS+LO + STA VOCEND + LDA VOCEND+1 + ADC NENTS+HI + STA VOCEND+1 + LDA VOCEND+2 + ADC #0 ; PICK UP CARRY + STA VOCEND+2 + DEX + BNE FWL1 + + CLC + LDA VOCEND ; AND ADD LENGTH TO START OF TBL + ADC MPCL ; TO GET END OF TBL + STA VOCEND + LDA VOCEND+1 + ADC MPCM + STA VOCEND+1 + LDA VOCEND+2 + ADC MPCH + STA VOCEND+2 ; TO SAVE FOR TESTING IF PAST END + + LDA VOCEND ; SUBTRACT [ESIZE] SO THAT + SEC ; [VOCEND] POINTS TO REAL LAST ENTRY + SBC ESIZE + STA VOCEND + LDA VOCEND+1 + SBC #0 + STA VOCEND+1 + + ; BEGIN THE SEARCH! [MPC] NOW POINTS TO 1ST ENTRY + + LSR NENTS+HI ; 2 ALIGN # OF ENTRIES + ROR NENTS+LO +FWCALC: ASL VWLEN+0 ; CALCULATE INITIAL OFFSET FOR SEARCH + ROL VWLEN+1 + ROL VWLEN+2 + LSR NENTS+HI + ROR NENTS+LO + BNE FWCALC + +; LDA NENTS+HI +; BNE FWCALC ; DOUBLE-CHECK + + CLC ; ADD 1ST OFFSET INTO START OF VOCABULARL + LDA MPCL ; WHICH IS CURRENTLY IN MPC + ADC VWLEN+0 + STA MPCL + LDA MPCM + ADC VWLEN+1 + STA MPCM + LDA MPCH + ADC VWLEN+2 + STA MPCH + + SEC ; AVOID FENCE-POST BUG FOR + LDA MPCL ; EXACT-POWER-OF-2 TBL (DUNCAN) + SBC ESIZE + STA MPCL + BCS FWLOOP + LDA MPCM + SEC + SBC #1 + STA MPCM + BCS FWLOOP + LDA MPCH + SBC #0 + STA MPCH + +FWLOOP: LSR VWLEN+2 ; SET FOR NEXT OFFSET, + ROR VWLEN+1 ; WHICH IS HALF THIS ONE + ROR VWLEN+0 + + LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + + JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET 1ST BYTE OF ENTRY + + CMP OUT ; MATCH 1ST BYTE OF TARGET? + BCC WNEXT ; LESS + BNE FWPREV ; GREATER + JSR GETBYT + CMP OUT+1 ; 2ND BYTE MATCHED? + BCC WNEXT + BNE FWPREV ; NOPE + JSR GETBYT + CMP OUT+2 ; 3RD BYTE? + BCC WNEXT + BNE FWPREV ; SORRY ... + JSR GETBYT + CMP OUT+3 ; 4TH BYTE + BCC WNEXT + BNE FWPREV + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BCC WNEXT + BNE FWPREV ; SORRY ... + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + BCS FWPREV ; ELSE BACK UP ... + +WNEXT: LDA VWCUR+0 ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + ADC VWLEN+1 + + BCS WNXT2 ; SAVES CODE (?) + + STA MPCM + + LDA #0 + STA MPCH + +WNXT0: LDA MPCM ; GONE PAST END? + CMP VOCEND+1 + BEQ WNXT1 ; MAYBE + BCS WNXT2 ; YES + BCC FWMORE ; NO +WNXT1: LDA MPCL + CMP VOCEND + BCC FWMORE ; NO + BEQ FWMORE ; NO, EQUAL +WNXT2: LDA VOCEND ; YES, SO POINT TO END OF TBL + STA MPCL + LDA VOCEND+1 + STA MPCM + LDA VOCEND+2 + STA MPCH + JMP FWMORE + +FWPREV: LDA VWCUR+0 ; TO MOVE DOWN, JUST SUBTRACT + SEC ; OFFSET FROM START OF THIS + SBC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + SBC VWLEN+1 + STA MPCM + LDA VWCUR+2 + SBC VWLEN+2 + STA MPCH + +FWMORE: LDA VWLEN+2 ; IF OFFSET >GE< 1 WORD, CONTINUE + BNE FWM1 + LDA VWLEN+1 + BNE FWM1 + LDA VWLEN+0 + CMP ESIZE + BCC FWFAIL +FWM1: JMP FWLOOP ; AND TRY AGAIN + +FWFAIL: LDA #0 ; NOT FOUND + STA VALUE+LO + STA VALUE+HI + RTS ; THEN RETURN WITH [VALUE] = 0 + +FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD + STA VALUE+LO + LDA VWCUR+1 + STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY + RTS ; WORD VALUE RETURNABLE + + +UNSORTED: ; DO UNSORTED SEARCH ON VOCAB TBL IN MPC + LDA #$FF ; 2'S COMPLEMENT LENGTH + EOR NENTS+HI ; TO GET REAL LENGTH + STA NENTS+HI ; WAS NEGATIVE TO SIGNIFY + LDA #$FF ; UNSORTED VOCAB TBL + EOR NENTS+LO + STA NENTS+LO + INC NENTS+LO ; 2'S CMPL + BNE UNSRT0 + INC NENTS+HI + +UNSRT0: LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + + JSR GETBYT ; GET 1ST BYTE OF ENTRY + CMP OUT ; MATCH 1ST BYTE OF TARGET? + BNE FNEXT ; LESS + JSR GETBYT + CMP OUT+1 ; 2ND BYTE MATCHED? + BNE FNEXT + JSR GETBYT + CMP OUT+2 ; 3RD BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+3 ; 4TH BYTE + BNE FNEXT + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + +FNEXT: LDA VWCUR+LO ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC ESIZE ; ENTRY + STA MPCL + BCC FNEXT0 + + LDA VWCUR+HI ; PICK UP CARRY + ADC #0 + STA MPCM + LDA #0 + STA MPCH + JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE + +FNEXT0: DEC NENTS+LO ; CHECKED ALL ENTRIES? + BNE UNSRT0 + LDA NENTS+HI + BEQ FWFAIL ; GO INDICATE NO FIND + DEC NENTS+HI ; OR DO NEXT 256 ENTRIES + JMP UNSRT0 + + END + \ No newline at end of file diff --git a/apple/xzip/rwts.asm b/apple/xzip/rwts.asm new file mode 100644 index 0000000..ad4cb57 --- /dev/null +++ b/apple/xzip/rwts.asm @@ -0,0 +1,1091 @@ + PAGE + STTL "--- BOOT CODE & RWTS: APPLE II ---" + + +; --------- +; BOOT CODE +; --------- +; LOADS ALL OF TRACK 0 INTO RAM AT $800 TO $1800, +; THEN JUMPS THROUGH [COLD] + + ORG BORG ; (EZIP) + DB 01 ; MAGICAL MYSTERY BYTE + + ; BOOT BEGINS HERE + +BOOT: ;THIS LABLE NEVER USED BUT MUST BE HERE + LDA BADDR+HI ; CHECK MSB OF BOOT ADDRESS + CMP #$09 ; 1ST ENTRY INTO BOOT? + BEQ BOOTS2 ; YES, DO STUFF (X) + CMP #$0A ; 3RD SECTOR GOES UP >(X) + BNE BOOTS0 ; NO, CONTINUE + + ; CALC ADDRESS OF ROM SECTOR READ ROUTINE + + LDA #$D0 + STA BADDR+HI + BNE BOOTS0 ; JMP (X) + +BOOTS2: LDA $C08B ; SET TO R/W RAM, BANK 1 + LDA $C08B ; MUST READ 2CE + LDA BSLOT ; GET SLOT ID * 16 + STA DCBSLT ; MAKE IT THE DEFAULT TARGET + STA DCBPSL ; AND THE "OLD" SLOT + LSR A ; DIVIDE BY 16 + LSR A + LSR A + LSR A + ORA #%11000000 ; MAKE IT $C0nn + STA I+HI ; USE AS MSB OF ADDRESS + LDA #$5C ; LSB IS ALWAYS $5C + STA I+LO + LDA #1 + STA DCBSEC + +BOOTS0: LDX DCBSEC + INC DCBSEC + CPX #$10 + BCS BOOTS1 + LDA ILEAVE,X + STA BSECT + LDX BSLOT + JMP (I) +BOOTS1: JSR INIT + JMP COLD ; LOAD REMAINDER OF ZIP + + +; --------------------- +; SECTOR INTERLEAVE MAP +; --------------------- +; USED BY "BOOT" (AND "RWTS" (NOT THIS W/ EZIP)) +; MUST BE IN 1ST PAGE! + +ILEAVE: DB $00,$04,$08,$0C,$01,$05,$09,$0D + DB $02,$06,$0A,$0E,$03,$07,$0B,$0F + + +; RAMDSK +; THIS CODE IS DESIGNED TO RESIDE +; IN MAIN 48K *ABOVE PAGE 2* +; +; ON ENTRY IT ASSUMES THAT MAIN +; BANK 1 IS ENABLED +; A = SECTOR - $00=<$4F +; Y = PAGE TO READ/WRITE +; TO/FROM +; X = ON ENTRY 1=WRITE +; 0=READ +; RMDBNK - 48K BANK TO READ TO +; AUX OR MAIN +; THE RAMDISK CAN ONLY WRITE FROM +; MAIN MEMORY (ACTUALLY FROM THE BANK THIS CODE IS IN) +; SECTOR MAP +; $00=<$0F IN MAIN BANK 2 +; $10=<$1F IN AUX BANK 2 +; $20=<$4F IN AUX BANK 1 + + +RMDBNK: DB 00 ;REMEMBER WHAT BANK THIS IS IN WHEN YOU SET IT + +RAMDSK: STY WRTBNK+MAIN ;WRITE TO MAIN 48K BANK (WHERE THIS CODE IS) + STY WRDADD+1+HI ;SAVE >ADDRESS FOR EITHER + STY RAMLOOP+1+HI ;READ OR WRITE + + CMP #$10 + BCS RAM1 + LDY BNK2SET ;IN MAIN BANK 2 + LDY BNK2SET ;ENABLE BANK 2 WITH TWO READS + ADC #$D0 ;C=0 , ALIGN SECTOR INTO RAM + BNE RAMDO +RAM1: + STA ALTZP+AUX ;IT IS IN AUX RAM + CMP #$20 ;BANK 1 OR 2 ??? + BCS RAM2 + LDY BNK2SET ;IN AUX BANK 2 + LDY BNK2SET ;ENABLE BANK 2 + ADC #$C0 ;ALIGN + BNE RAMDO + +RAM2: ADC #$AF ;C=1 ; IN AUX BANK 1 + +RAMDO: DEX ; SEE IF X WAS A 1 + BNE RAMREAD ;NO IT WAS A ZERO + STA WRDADD+1+HI ;WRITE + BEQ RAMDO1 + +RAMREAD: STA RAMLOOP+1+HI ;READ + LDY RMDBNK ;THIS MUST BE GOTTEN FROM A SAFE PLACE + STA WRTBNK,Y ;SET TO READ TO RMDBNK +RAMDO1: LDY #00 +RAMLOOP: LDA $FF00,Y +WRDADD: STA $FF00,Y + INY + BNE RAMLOOP + + ; LEAVE WITH MAIN BANK1 ENABLED + ; AND MAIN 48K SELECTED FOR WRITE + + LDA BNK1SET + LDA BNK1SET + STA WRTBNK+MAIN + STA ALTZP+MAIN + RTS + + + ; MONITOR CALLS ARE TO ROM SO MUST BE FROM MAIN 48K OF MEMORY + ; ALL CALLS IN XZIP ARE UNCHANGED FROM EZIP BUT ARE DIVERTED NOW + ; THROUGH THESE RTNS WHICH SWITCH IN ROM TO READ FROM, CALL THE + ; MONITOR ROUTINE THEN SWITCH BACK TO RAM FOR EVERYTHING AND RETURN + + ; EACH CALL SHOULD BE SEPARATE SO AS TO PRESERVE REGISTERS ON CALL + +BASCAL: PHA + LDA RDROM ; SET TO READ FROM ROM + LDA RDROM + PLA + JSR MBASCAL ; CALL MONITOR RTN + JMP MOUT + +BELL: PHA + LDA RDROM + LDA RDROM + PLA + JSR MBELL + JMP MOUT + +CLEOL: PHA + LDA RDROM + LDA RDROM + PLA + JSR MCLEOL + JMP MOUT + +CLEOS: PHA + LDA RDROM + LDA RDROM + PLA + JSR MCLEOS + JMP MOUT + +HOME: PHA + LDA RDROM + LDA RDROM + PLA + JSR MHOME + JMP MOUT + +MCOUT: PHA + LDA RDROM + LDA RDROM + PLA + JSR MMCOUT + JMP MOUT + +COUT1: PHA + LDA RDROM + LDA RDROM + PLA + JSR MCOUT1 + JMP MOUT + +RDKEY: PHA + LDA RDROM + LDA RDROM + PLA + JSR MRDKEY + JMP MOUT + +GETLN1: PHA + LDA RDROM + LDA RDROM + PLA + JSR MGETLN1 + JMP MOUT + +MWAIT: PHA + LDA RDROM + LDA RDROM + PLA + JSR MMWAIT + ; FALL THRU ON LAST ONE + + +MOUT: PHA ; SAVE [A] AS MAY HAVE INFORMATION + LDA BNK1SET ; RESET TO READ FROM RAM + LDA BNK1SET + PLA + RTS + + + ; TO CHECK IF HAVE ENOUGH MEMORY, MUST HAVE 128K OF MEMORY (X) + +CHKSIZ: LDA RDROM ; FLAGS IN ROM, MUST GET THEM + LDA RDROM + LDA $FBB3 ; CHECK ID BYTE + CMP #$06 ; IS IT A IIE OR IIC? + BEQ CHKS0 ; YES + + LDA BNK1SET ; RESET TO RAM + LDA BNK1SET + SEC ; NO, IT'S NOT 128K (EZIP) + RTS + +CHKS0: LDA $FBC0 ; IS IT A IIE OR! A IIC + LDX BNK1SET ; RESET TO RAM + LDX BNK1SET + STA SIG ; 0 = IIC + CLC ; SAY OK, + RTS ; FINISH UP IN COLD + +CALL80: LDA RDROM ; SET TO READ ROM + LDA RDROM ; SO CAN TURN 80 COL DISPLAY ON + JSR $C300 ; THIS NEEDS ROM + LDA BNK1SET ; RESET TO RAM + LDA BNK1SET + RTS + + ; MARK END OF SECTOR + + PAGE + +; INFOCOM'S VERSION OF APPLE RWTS (READ/WRITE TRACK/SECTOR) +; HACKED BY ANDREW KALUZNIACKI +; FROM THE DOS RWTS ON APPLE DOS 3.3 + + ORG $D000 + + +; ------------------------------- +; MAIN ENTRY INTO INFO-DOS (IDOS) +; ------------------------------- +; [DCBSEC] SECTOR (0-15), SET BY CALLER +; [DCBTRK] TRACK (0-34), SET BY CALLER +; [DCBDRV] DRIVE (1 OR 2), SET BY CALLER [BOOT DEFAULT] +; [DCBSLT] SLOT*16, SET BY CALLER [BOOT DEFAULT] +; [DCBPSL] SLOT*16 OF LAST USED SLOT, SET BY BOOT +; [DCBPDR] LAST DRIVE USED (1 OR 2), SET BY BOOT +; [DCBCMD] STORAGE FOR COMMAND SENT IN >A< AT CALL TO IDOS +; [DCBERR] IDOS ERROR CODE +; [DCBBFL] DISK BUFFER ADDRESS (LSB) [BOOT = IOBUFF] +; [DCBBFM] DISK BUFFER ADDRESS (MSB) [BOOT = IOBUFF] +; >A<=1 WRITES DISK BUFFER +; >A<=0 READS DISK BUFFER +; [IOBUFF] = 256-BYTE BUFFER FOR DISK I/O +; (OPTIONAL IF [DCBBFL/DCBBFM] ARE SET) +; [BUFFA] ONE PAGE BUFFER +; [BUFFB] $56 BYTE BUFFER +; CARRY CLEAR ON RETURN IF NO ERROR +; IF CARRY SET, ERROR CODE IS IN [DERR]: +; $10 = WRITE PROTECTED +; $40 = DRIVE ERROR +; $80 = READ ERROR +; *** WARNING *** +; IDOS MUST START ON A PAGE BOUNDARY. +; CHANGE ANY CODE BETWEEN [IDOS] AND [INIT] AT YOUR OWN RISK. +; YOU HAVE BEEN WARNED. + +DOS: NOP + NOP + NOP ; DON'T ASK, AND DON'T CHANGE + PHP ; SAVE STATUS OF [I] + SEI ; DISABLE INTERUPTS + JSR DOSENT ; DO IT (GO TO MAIN ROUTINE) + BCS DSERR ; ERROR OCCURED IF C=1 + PLP ; RESTORE [I] + CLC ; SET "NO ERROR" + RTS ; RETURN FROM CALL + +DSERR: PLP ; RESTORE [I] + SEC ; INDICATE ERROR + RTS ; EXIT + + ; PRE-NIBBLIZE [IOBUFF] BEFORE WRITING + +PRENIB: LDX #0 + LDY #2 +PRELP1: DEY + LDA (DCBBFL),Y + LSR A + ROL BUFFB,X + LSR A + ROL BUFFB,X + STA BUFFA,Y + INX + CPX #$56 + BCC PRELP1 + LDX #0 + TYA + BNE PRELP1 + LDX #$55 ; CLEAR BITS 7 AND 6 +PRELP2: LDA BUFFB,X ; OF TOP NIBBLE BUFFER + AND #%00111111 + STA BUFFB,X + DEX + BPL PRELP2 + RTS + + +; ------------ +; WRITE SECTOR +; ------------ +; WRITES PRENIBBLIZED DATA AT [BUFFA/BUFFB] TO DISK +; ENTRY: SLOT*16 IN [X] +; EXIT: CARRY SET IF ERROR + +WRTDTA: STX DTMP4 ; SAVE SLOT ID HERE + STX SLTMP2 + SEC ; SET CARRY FOR POSSIBLE ERROR + LDA Q6H,X ; CHECK FOR WRITE-PROTECT + LDA Q7L,X + BMI WRTEXI ; EXIT W/CARRY SET IF PROTECTED + LDA BUFFB ; SAVE 1ST BYTE OF 2NDARY BUFFER + STA DTMP3 ; FOR LATER + LDA #$FF ; ESTABLISH AUTOSYNC BYTE + STA Q7H,X ; SET DRIVE TO WRITE MODE + ORA Q6L,X ; WAIT FOR HARDWARE TO SETTLE + PHA + PLA + NOP + LDY #4 ; WRITE 5 AUTOSYNC BYTES +WRTLP1: PHA + PLA + JSR WRBYT2 ; USING 40 uS DELAY + DEY + BNE WRTLP1 + LDA #$D5 ; WRITE DATA FIELD PROLOGUE: + JSR WRBYT1 ; $D5-$AA-$AD + LDA #$AA + JSR WRBYT1 + LDA #$AD + JSR WRBYT1 + TYA ; A BRIEF DELAY + LDY #$56 ; INIT LOOP INDEX + BNE WRTSK1 ; BRANCH ALWAYS + + ; WRITE [BUFFB] TO DISK + +WRTLP2: LDA BUFFB,Y ; GET A BYTE FROM [BUFFB] +WRTSK1: EOR BUFFB-1,Y + TAX ; USE IT AS AN INDEX + LDA WRTTBL,X ; INTO THE TRANSLATE TABLE + LDX DTMP4 ; RESTORE SLOT ID + STA Q6H,X ; AND WRITE THE TRANSLATED BYTE + LDA Q6L,X + DEY ; LOOP TILL + BNE WRTLP2 ; EMPTY + + ; WRITE [BUFFA] TO DISK + + LDA DTMP3 ; RESTORE "LOST" [BUFFB] BYTE + NOP ; WAIT JUST A MOMENT ... +WRTLP3: EOR BUFFA,Y ; GET A BYTE FROM [BUFFA] + TAX ; USE IT AS AN INDEX + LDA WRTTBL,X ; INTO THE TRANSLATE TABLE + LDX SLTMP2 ; RESTORE SLOT ID + STA Q6H,X ; AND WRITE THE TRANSLATED BYTE + LDA Q6L,X + LDA BUFFA,Y ; GET NEXT BYTE FROM BUFFER + INY ; AND LOOP TILL + BNE WRTLP3 ; ALL OF [BUFFA] IS WRITTEN + TAX + LDA WRTTBL,X + LDX DTMP4 ; RESTORE SLOT ID + JSR WRBYT3 ; AND WRITE THE LAST [BUFFA] BYTE + LDA #$DE ; WRITE DATA FIELD EPILOGUE: + JSR WRBYT1 ; $DE-$AA-$EB + LDA #$AA + JSR WRBYT1 + LDA #$EB + JSR WRBYT1 + LDA #$FF ; WRITE GAP 3 + JSR WRBYT1 + LDA Q7L,X ; SET DRIVE TO READ MODE +WRTEXI: LDA Q6L,X + RTS + + +; ---------------------------- +; WRITE A BYTE (TIME-CRITICAL) +; ---------------------------- +; ENTRY: BYTE TO WRITE IN [A] +; SLOT*16 IN [X] + +WRBYT1: CLC ; PROLOGUE, EPILOGUE AND GAP 3 TIMING +WRBYT2: PHA ; ENTRY FOR GAP 2 TIMING + PLA +WRBYT3: STA Q6H,X + ORA Q6L,X + RTS + + ; CONVERT RAW DATA TO BINARY IN [IOBUFF] + +POSTNB: LDY #0 +PSTSK1: LDX #$56 +PSTLP1: DEX + BMI PSTSK1 + LDA BUFFA,Y + LSR BUFFB,X + ROL A + LSR BUFFB,X + ROL A + STA (DCBBFL),Y + INY + CPY DTMP3 + BNE PSTLP1 + RTS + + +; ----------- +; READ SECTOR +; ----------- +; READ RAW SECTOR DATA TO [BUFFA/BUFFB] +; ENTRY: SLOT*16 IN [X] +; EXIT: CARRY SET IF ERROR, ELSE 342 RAW BYTES IN [BUFFA/BUFFB] + +RDSECT: LDY #$20 +RDLP1: DEY ; RETURN AN ERROR IF + BEQ RDBAD ; NO $D5 FOUND AFTER 32 TRIES + + ; FETCH & VALIDATE PROLOGUE ($D5-$AA-$AD) + +RD1: LDA Q6L,X ; GET A BYTE + BPL RD1 +RDSK1: EOR #$D5 ; WAS IT $D5? + BNE RDLP1 ; NO, KEEP LOOKING + NOP ; ELSE WAIT A MOMENT ... +RD2: LDA Q6L,X ; GET ANOTHER BYTE + BPL RD2 + CMP #$AA ; WAS IT $AA? + BNE RDSK1 ; CHECK FOR $D5 AGAIN IF NOT + LDY #$56 ; ELSE INIT DATA-READ INDEX +RD3: LDA Q6L,X ; GET A BYTE + BPL RD3 + CMP #$AD ; WAS IT $AD? + BNE RDSK1 ; CHECK FOR $D5 IF NOT + + ; READ RAW DATA INTO [BUFFB] + + LDA #0 ; CLEAR [A], DELAY ... +RDLP2: DEY + STY DTMP3 ; SAVE INDEX HERE +RD4: LDY Q6L,X ; GET A DATA BYTE + BPL RD4 + EOR RDTBL-$96,Y ; TRANSLATE IT + LDY DTMP3 ; RESTORE INDEX + STA BUFFB,Y ; STORE BYTE IN [BUFFB] + BNE RDLP2 ; CONTINUE TILL [BUFFB] FULL + + ; READ RAW DATA INTO [BUFFA] + +RDLP3: STY DTMP3 ; RE-INIT INDEX TO ZERO +RD5: LDY Q6L,X ; GET A DATA BYTE + BPL RD5 + EOR RDTBL-$96,Y ; TRANSLATE IT + LDY DTMP3 ; RESTORE INDEX + STA BUFFA,Y ; SAVE BYTE IN [BUFFA] + INY + BNE RDLP3 ; LOOP TILL [BUFFA] IS FULL + + ; FETCH & VALIDATE CHECKSUM + +RD6: LDY Q6L,X ; GET THE NEXT BYTE + BPL RD6 + CMP RDTBL-$96,Y ; TRANSLATE IT + BNE RDBAD ; ERROR IF CHECKSUM BAD + + ; FETCH & VALIDATE EPILOGUE ($DE-$AA-$EB) + +RD7: LDA Q6L,X ; GET A BYTE + BPL RD7 + CMP #$DE ; IS IT $DE? + BNE RDBAD ; ERROR IF NOT + NOP ; WAIT ... +RD8: LDA Q6L,X ; GET ANOTHER BYTE + BPL RD8 + CMP #$AA ; IS IT $AA? + BEQ RDOK ; DATA OKAY IF SO +RDBAD: SEC ; ELSE SET CARRY FOR ERROR + RTS ; AND SCRAM + + +; --------------------- +; READ AN ADDRESS FIELD +; --------------------- +; ENTRY: SLOT*16 IN [X] +; EXIT: CARRY SET IF ERROR + +RDADDR: LDY #$FC ; INIT TIMEOUT COUNTER + STY DTMP3 +ADDLP1: INY + BNE ADD1 + INC DTMP3 ; ERROR IF + BEQ RDBAD ; CAN'T FIND ADDRESS HEADER + + ; FETCH THE ADDRESS FIELD PROLOGUE ($D5-$AA-$96) + +ADD1: LDA Q6L,X ; GRAB A BYTE + BPL ADD1 +ADDLP2: CMP #$D5 ; WAS IT $D5? + BNE ADDLP1 ; NO, KEEP SEARCHING + NOP ; ELSE WAIT A FEW MICROSECONDS ... +ADD2: LDA Q6L,X ; GET ANOTHER BYTE + BPL ADD2 + CMP #$AA ; WAS IT $AA? + BNE ADDLP2 ; NO, CHECK IF $D5 + LDY #3 ; ELSE INIT DATA-FETCH INDEX +ADD3: LDA Q6L,X ; GET A BYTE + BPL ADD3 + CMP #$96 ; WAS IT $96? + BNE ADDLP2 ; NO, CHECK FOR $D5 + + ; FETCH THE 4 BYTES OF ADDRESS DATA + + LDA #0 ; INIT CHECKSUM BYTE +ADDLP3: STA DTMP4 ; UPDATE CHECKSUM +ADD4: LDA Q6L,X ; GET A BYTE + BPL ADD4 + ROL A ; SHIFT IT + STA DTMP3 ; AND SAVE 1ST PART HERE +ADD5: LDA Q6L,X ; GET ANOTHER BYTE + BPL ADD5 + AND DTMP3 ; SUPER 1ST PART OF BYTE + STA HDRCHK,Y ; STORE IN RESULT TABLE + EOR DTMP4 ; COMPUTE CHECKSUM + DEY ; GOT 4 BYTES YET? + BPL ADDLP3 ; NO, LOOP BACK + TAY ; LOOK AT CHECKSUM BYTE + BNE RDBAD ; ERROR IF NON-ZERO + + ; FETCH & VALIDATE EPILOGUE ($DE-$AA, IGNORE $EB) + +ADD6: LDA Q6L,X ; GET A BYTE + BPL ADD6 + CMP #$DE ; WAS IT $DE? + BNE RDBAD ; ERROR IF NOT + NOP ; ELSE WAIT A MOMENT ... +ADD7: LDA Q6L,X ; GET ONE MORE BYTE + BPL ADD7 + CMP #$AA ; WAS IT $AA + BNE RDBAD ; ERROR IF NOT +RDOK: CLC ; ELSE CLEAR CARRY FOR SUCCESS + RTS ; AND RETURN + + +; --------------------- +; MOVE ARM TO TRACK [A] +; --------------------- +; ENTRY: SLOT*16 IN [X] +; TARGET TRACK IN [A] +; CURRENT TRACK IN [CTRACK] + +SEEK: STX SLTMP3 ; SAVE SLOT ID + STA TTRK ; AND TARGET TRACK + CMP CTRACK ; TARGET SAME AS CURRENT? + BEQ SEEEXI ; EXIT NOW IF SO + LDA #0 ; INIT + STA DTMP3 ; INDEX +SEESK1: LDA CTRACK ; GET CURRENT TRACK + STA DTMP4 ; SAVE IT HERE + SEC + SBC TTRK ; GET TRACK DIFFERENCE + BEQ SEESK6 + BCS SEESK2 + EOR #%11111111 + INC CTRACK + BCC SEESK3 +SEESK2: ADC #$FE + DEC CTRACK +SEESK3: CMP DTMP3 + BCC SEESK4 + LDA DTMP3 +SEESK4: CMP #$0C + BCS SEESK5 + TAY +SEESK5: SEC + JSR SEEK0 + LDA DELTB1,Y + JSR ARMDEL + LDA DTMP4 + CLC + JSR SEEK1 + LDA DELTB2,Y + JSR ARMDEL + INC DTMP3 + BNE SEESK1 +SEESK6: JSR ARMDEL + CLC +SEEK0: LDA CTRACK +SEEK1: AND #%00000011 + ROL A + ORA SLTMP3 + TAX + LDA PH0OFF,X ; MOVE THE ARM + LDX SLTMP3 +SEEEXI: RTS + + +; ------------------ +; ARM MOVEMENT DELAY +; ------------------ +; NOTE: THIS ROUTINE MUST BEGIN ON A PAGE BOUNDARY! +; ENTRY: 100uS DELAY INTERVAL IN [A] +; MOTOR TIME COUNT IN [MTIME] + +ARMDEL: LDX #$11 +ARMLP1: DEX + BNE ARMLP1 + INC DCNT + BNE ARMLP2 + INC DTMP2 +ARMLP2: SEC + SBC #1 + BNE ARMDEL + RTS + + +; ------------------------- +; ARM MOVEMENT DELAY TABLES +; ------------------------- + +DELTB1: DB $01,$30,$28,$24,$20,$1E,$1D,$1C + DB $1C,$1C,$1C,$1C +DELTB2: DB $70,$2C,$26,$22,$1F,$1E,$1D,$1C + DB $1C,$1C,$1C,$1C + + +; --------------------- +; WRITE TRANSLATE TABLE +; --------------------- + +WRTTBL: DB $96,$97,$9A,$9B,$9D,$9E,$9F,$A6 + DB $A7,$AB,$AC,$AD,$AE,$AF,$B2,$B3 + DB $B4,$B5,$B6,$B7,$B9,$BA,$BB,$BC + DB $BD,$BE,$BF,$CB,$CD,$CE,$CF,$D3 + DB $D6,$D7,$D9,$DA,$DB,$DC,$DD,$DE + DB $DF,$E5,$E6,$E7,$E9,$EA,$EB,$EC + DB $ED,$EE,$EF,$F2,$F3,$F4,$F5,$F6 + DB $F7,$F9,$FA,$FB,$FC,$FD,$FE,$FF + + +; -------------------- +; READ TRANSLATE TABLE +; -------------------- + +RDTBL: DB $00,$01,$98,$99,$02,$03,$9C,$04 + DB $05,$06,$A0,$A1,$A2,$A3,$A4,$A5 + DB $07,$08,$A8,$A9,$AA,$09,$0A,$0B + DB $0C,$0D,$B0,$B1,$0E,$0F,$10,$11 + DB $12,$13,$B8,$14,$15,$16,$17,$18 + DB $19,$1A,$C0,$C1,$C2,$C3,$C4,$C5 + DB $C6,$C7,$C8,$C9,$CA,$1B,$CC,$1C + DB $1D,$1E,$D0,$D1,$D2,$1F,$D4,$D5 + DB $20,$21,$D8,$22,$23,$24,$25,$26 + DB $27,$28,$E0,$E1,$E2,$E3,$E4,$29 + DB $2A,$2B,$E8,$2C,$2D,$2E,$2F,$30 + DB $31,$32,$F0,$F1,$33,$34,$35,$36 + DB $37,$38,$F8,$39,$3A,$3B,$3C,$3D + DB $3E,$3F + + +; --------------- +; MAIN RWTS ENTRY +; --------------- +; ENTRY: [A]=0 FOR READ, [A]=1 FOR WRITE +; [SLOT] = TARGET SLOT +; [DRIVE] = TARGET DRIVE +; [TRACK] = TARGET TRACK +; [SECTOR] = TARGET SECTOR +; EXIT: CARRY CLEAR IF OKAY +; COMMENTS - LINDE +; ACTUAL VARIABLES ARE: +; [DCBSLT] = SLOT +; [DCBTRK] = TRACK +; [DCBSEC] = SECTOR +; [[DCBDRV] = DRIVE +; FOR TRK, SEC, DRV 1 = 1 (DRIVE 1, SET DCBDRV TO 1) +; FOR SLT - MULTIPLY SLOT BY 16 (SLOT 6, SET DCBSLT TO $60) + +DOSENT: STA DCBCMD ; SAVE COMMAND + LDA #2 ; AL<2 + STA NRECAL ; RECALS + ASL A ; AND 4 + STA NSEEK ; SEEKS + LDX DCBSLT ; GET REQUESTED SLOT ID + CPX DCBPSL ; SAME AS LAST SLOT? + BEQ DOSS1 ; YES, CONTINUE + LDX DCBPSL + + ; WAIT FOR OLD DRIVE TO TURN OFF, UPDATE SLOT ID + + LDA Q7L,X ; SET OLD SLOT TO READ MODE +DOSL1: LDY #8 ; INIT COUNTER + LDA Q6L,X +DOSL2: CMP Q6L,X + BNE DOSL1 + DEY + BNE DOSL2 + LDX DCBSLT ; GET NEW SLOT ID INTO [X] + STX DCBPSL ; MAKE IT THE "OLD" SLOT + + ; CURRENT SLOT ID IN [X] + +DOSS1: LDA Q7L,X ; GET DRIVE INTO READ MODE + LDA Q6L,X ; READ WITH DELAYS + LDY #8 ; TO SEE IF DRIVE IS SPINNING +DOSL3: LDA Q6L,X + PHA + PLA + PHA + PLA + STX SLTMP1 ; SAVE SLOT HERE + CMP Q6L,X + BNE DOSS2 + DEY + BNE DOSL3 +DOSS2: PHP ; SAVE TEST RESULT ON STACK + LDA DRVON,X ; TURN ON MOTOR + LDA #$D8 ; REFRESH + STA DTMP2 ; MOTOR TIME CONSTANT + + ; CHECK DRIVE ID + + LDA DCBDRV + CMP DCBPDR ; HAS DRIVE CHANGED? + BEQ DOSS3 ; NO, CONTINUE + STA DCBPDR ; ELSE MAKE NEW DRIVE "OLD" + PLP ; SET ZERO FLAG + LDY #0 ; OF TEST RESULT + PHP ; AND PUSH IT BACK ON STACK +DOSS3: ROR A ; CHECK DRIVE ID + BCC DOSS4 ; CARRY WILL BE CLEAR IF DRIVE = 2 + LDA DRV0EN,X ; ELSE SELECT DRIVE #1 + BCS DOSS5 ; BRANCH ALWAYS +DOSS4: LDA DRV1EN,X ; SELECT DRIVE #2 +DOSS5: ROR DRVFLG ; >BIT = 1 FOR DRIVE 1, 0 FOR 2 + PLP ; CHECK TEST RESULTS + PHP + BNE DOSS6 ; BRANCH IF DRIVE WAS ON + LDY #7 ; WAIT FOR CAP DISCHARGE +DOSL4: JSR ARMDEL + DEY + BNE DOSL4 + LDX SLTMP1 ; RESTORE SLOT ID + + ; SEEK THE TARGET TRACK + +DOSS6: LDA DCBTRK ; GET TARGET TRACK + JSR MYSEEK + PLP ; WAS DRIVE ON? + BNE DOSS7 ; YES, CONTINUE + + ; WAIT FOR DRIVE TO COME UP TO SPEED + + LDY DTMP2 + BPL DOSS7 +DOSL5: LDY #$12 ; WAIT FOR DRIVE TO +DOSL6: DEY ; COME UP TO SPEED + BNE DOSL6 + INC DCNT + BNE DOSL5 + INC DTMP2 + BNE DOSL5 + + ; DECODE DISK COMMAND + +DOSS7: LDA DCBCMD ; GET COMMAND + ROR A ; CARRY = 0 IF "READ" + PHP ; SAVE READ/WRITE STATUS + + ; AND MAINTAIN STACK + + BCC GETADR ; BRANCH IF "READ" + JSR PRENIB + + ; FETCH AN ADDRESS FIELD + +GETADR: LDA #48 + STA DTMP1 ; INIT RETRY COUNT +GTA0: LDX SLTMP1 ; RESTORE SLOT ID + LDA DCBCMD + BPL DOSS8 + STA DTMP6 ; TELL RDFADD TO GET HEADER ONLY + JSR RDFSEC ; #$84 = READ FUNNY FORMAT + BCC RRGHT ; READ IT + BCS GTA1 ; OOPS +DOSS8: JSR RDADDR ; GET AN ADDRESS FIELD + BCC RRGHT ; CONTINUE IF SUCCESSFUL +GTA1: DEC DTMP1 ; ELSE UPDATE RETRY COUNT + BPL GTA0 ; AND TRY AGAIN + + ; RECALIBRATE THE ARM + +GTA2: LDA CTRACK ; SAVE THE + PHA ; CURRENT TRACK ID + LDA #$60 + JSR SETTRK + DEC NRECAL ; UPDATE RECAL COUNT + BEQ DOSERR ; ERROR IF EMPTY + LDA #4 ; RESET + STA NSEEK ; SEEK COUNT + LDA #0 ; CALIBRATE THE ARM + JSR MYSEEK ; TO TRACK #0 + PLA ; RESTORE CURRENT TRACK +GTA3: JSR MYSEEK ; GO TO IT + JMP GETADR ; AND TRY AGAIN + + ; ADDRESS FIELD FOUND + +RRGHT: LDY HDRTRK + CPY CTRACK ; ON THE RIGHT TRACK? + BEQ RTTRAK ; YES, CONTINUE + LDA CTRACK + PHA + TYA + JSR SETTRK + PLA + DEC NSEEK + BNE GTA3 + BEQ GTA2 ; ELSE RECALIBRATE + + ; HANDLE A DRIVE ERROR + +DOSERR PLA ; CLEAN UP STACK + LDA #$40 ; $40 = DRIVE ERROR + PLP ; CLEAN UP STATUS REGISTER + JMP DOSERR2 + + ; CHECK FOR PROPER SECTOR (VOLUME CHECK OMITTED) + +RTTRAK: LDA DCBCMD + BMI DOSS9 ; NO INTERLEAVE + LDY DCBSEC + LDA INTLVE,Y ; GET INTERLEAVE BYTE + CMP HDRSEC ; MATCHED FOUND SECTOR? + BNE GTA1 ; NO, TRY AGAIN + + ; SECTOR FOUND! + +DOSS9: PLP ; WILL THIS BE READ OR WRITE? + BCS DOSWRT ; DO "WRITE" IF CARRY SET + + ; READ A SECTOR + + LDA DCBCMD + BPL DOSS10 + LDY DCBSEC ; FUNNY FORMAT + STY DTMP6 + JSR RDFSEC + BCC DOSS11 + SEC + BCS DOSS11 +DOSS10: JSR RDSECT ; DO THE READ +DOSS11: BCC GTA3A ; OK + CLC ; RESET FOR NEXT TIME THRU + PHP ; PUSH FOR NEXT TIME THRU + BCC GTA1 ; JMP, ERROR OCCURRED +GTA3A: LDX #$00 + STX DTMP3 + JSR POSTNB + LDX SLTMP1 ; RESTORE SLOT ID +DOSFIN: LDA #0 ; 0 = NO ERRORS + CLC ; CARRY CLEAR FOR SUCCESS + BCC DOSEXI + + ; ERROR EXIT + +DOSERR2: SEC ; CARRY SET FOR ERROR + + ; GENERAL EXIT + +DOSEXI: STA DCBERR ; SAVE ERROR CODE HERE + LDA DRVOFF,X ; STOP THE DRIVE + RTS ; BYE! + + ; WRITE A SECTOR + +DOSWRT: JSR WRTDTA + BCC DOSFIN ; ALL'S WELL IF CARRY CLEAR + LDA #$10 ; ELSE GET ERROR CODE INTO [A] + BNE DOSERR2 ; AND DO AN ERROR EXIT + + +; --------------------- +; SET UP FOR TRACK SEEK +; --------------------- + +MYSEEK: ASL A ; TRACK*2 (PHASE OF DISK CARE) + JSR DOSEEK + LSR CTRACK ; CURRENT TRACK/2 + RTS + + +; -------------- +; EXECUTE A SEEK +; -------------- +; PAGE BOUNDARY SHOULD BEGIN HERE! + +DOSEEK: STA TTRK + JSR XTOY + LDA DR1TBL,Y + BIT DRVFLG + BMI EEK1 + LDA DR2TBL,Y +EEK1: STA CTRACK + LDA TTRK + BIT DRVFLG + BMI EEK2 + STA DR2TBL,Y + BPL EEK3 +EEK2: STA DR1TBL,Y +EEK3: JMP SEEK + + +; -------------------- +; GET SLOT ID INTO [Y] +; -------------------- + +XTOY: TXA + LSR A + LSR A + LSR A + LSR A + TAY + RTS + + +; ------------ +; SET TRACK ID +; ------------ + +SETTRK: PHA + LDA DCBDRV + ROR A + ROR DRVFLG + JSR XTOY + PLA + ASL A + BIT DRVFLG + BMI SETT1 + STA DR2TBL,Y + BPL SETT2 +SETT1: STA DR1TBL,Y +SETT2: RTS + + +; ----------- +; IDOS TABLES +; ----------- + +DR1TBL: DB 00,00,00,00 ; (8 BYTES) + DB 00,00,00,00 +CTRACK EQU DR1TBL ; CURRENT TRACK +DR2TBL: DB 00,00,00,00 ; (8 BYTES) + DB 00,00,00,00 +NSEEK: DB 00 ; SEEK COUNT +DTMP1: DB 00 ; RETRY COUNT +SLTMP1: DB 00 ; SLOT ID +SLTMP2: DB 00 +NRECAL: DB 00 ; RECALIBRATE COUNT + + ;DUPLICATE INTERLEAVE TBL FOR USE AFTER BOOT + +INTLVE: DB $00,$04,$08,$0C,$01,$05,$09,$0D + DB $02,$06,$0A,$0E,$03,$07,$0B,$0F + + +; ------------------ +; READ SECTOR FROM BIG TRACK +; ------------------ +; READ ADDRESS FIELD TO CHECK TRACK +; FIND HEADER $D5:$AA:$AD + +RDFSEC: LDA #$20 + STA HTEMP + TAY +RDFL1: LDA #$84 ; IN CASE ERROR OCCURS + DEC HTEMP + BEQ RDFBAD2 +RDFL2: DEY + BEQ RDFL2 + NOP + NOP + LDA Q6L,X + BPL RDFL2 + CMP #$D5 + BNE RDFL2 +RDF1: LDA Q6L,X + BPL RDF1 + CMP #$AA + BNE RDFL1 +RDF2: LDA Q6L,X + BPL RDF2 + CMP #$AD + BNE RDFL1 + + ; HEADER FOUND - GET TRACK ID 4+4 + + SEC +RDF3: LDA Q6L,X + BPL RDF3 + ROL A + STA TEMP +RDF4: LDA Q6L,X + BPL RDF4 + AND TEMP + STA HDRTRK + LDA DTMP6 + BMI RDFOK ; ONLY LOOKING FOR TRACK NUMBER AND ? +RDFNEXT: LDY #$56 ; SET INDEX (AND TIMING) + + ; SKIP UNUSED SECTORS + + LDA #$00 ; ZERO >A< +RDFL3: DEY ; NEXT + STY DTMP3 ; SAVE INDEX +RDF5: LDY Q6L,X ; GET A BYTE + BPL RDF5 ; WAIT VALID + EOR RDTBL-$96,Y ; CHECK SUM AND DECODE + LDY DTMP3 ; GET INDEX + STA BUFFB,Y ; SAVE DATRA + BNE RDFL3 ; LOOP TILL DONE +RDFL4: STY DTMP3 ; SAVE INDEX +RDF6: LDY Q6L,X ; GET A BYTE + BPL RDF6 ; WAIT VALID + EOR RDTBL-$96,Y ; DECODE AND CHECK SUM + LDY DTMP3 ; GET INDEX + STA BUFFA,Y ; SAVE DATA + INY ; NEXT + BNE RDFL4 ; LOOP TIL DONE +RDF7: LDY Q6L,X ; GET A BYTE + BPL RDF7 ; WAIT VALID + DEC DTMP6 + BPL RDFNEXT + CMP RDTBL-$96,Y ; CHECK SUM VALID? + BNE RDFBAD ; NO, EXIT ERROR +RDFOK: CLC + RTS + +RDFBAD: LDA #$85 +RDFBAD2: STA DCBERR + SEC + RTS + + +; ---------------------- +; MACHINE INITIALIZATION +; ---------------------- + +INIT: LDA TXTSET ; SET TEXT MODE + LDA MIXCLR ; SET NO MIX + LDA LOWSCR ; SET PAGE 1 + LDA #>IOBUFF ; POINT [DCBBFL/M] TO [IOBUFF] + STA DCBBFM + LDA #STRYM ;DISP. "THE STORY IS LOADING..." + LDX #ZBEGIN ; MSB OF PRELOAD START ADDRESS + STA ZCODE ; FREEZE IT HERE + STA DBUFF+HI ; LSB IS ALWAYS ZERO + LDA #MAIN + STA DSKBNK ;SET TO MAIN BANK + LDA #1 ; Set ZPURE to 100 to fake + STA ZPURE+HI ; GETDSK out this first time through + JSR GETDSK ; [DBLOCK] SET TO Z-BLOCK 0 + + ; EXTRACT GAME DATA FROM Z-CODE HEADER + + LDA ZBEGIN+ZVERS ; (EZIP) IS GAME AN EZIP? + CMP #5 ; (X) + BEQ YESEZ ; YES, CONTINUE + +; *** ERROR #15 -- NOT AN EZIP GAME *** + LDA #15 + JMP ZERROR + +; *** ERROR #0 -- INSUFFICIENT RAM *** +NORAM: LDA #5 + STA CVT + JSR BASCAL + LDA #0 + JMP ZERROR + +YESEZ: LDA ZBEGIN+ZPURBT ; CHECK PURBOT POINTER + CMP #$AD ; MAXIMUM IMPURE IS $AD00 (43K) + BCC YZ3 ; OKAY, CONTINUE + + LDA #13 + JMP ZERROR ; ELSE ERROR #13 (IMPURE TOO BIG) +YZ3: + LDA #3 ; ELSE USE ONLY 3 + STA NUMSAV ; REMEMBER MAXIMUM # SAVES PER DISK + CLC + ADC #'0' ; CONVERT TO ASCII + STA SAVASC ; SAVE IN STRING + + LDA ZBEGIN+ZENDLD ; MSB OF ENDLOAD POINTER + STA ZPURE+HI ; GOT TO FIGURE OUT FIRST PAGE + LDA ZBEGIN+ZENDLD+1 ; of data on side 2 + STA ZPURE+LO ; ok? + + LSR ZPURE+HI ; SO WE NEED TO /64 TO GET IT + ROR ZPURE+LO ; SO DO 6 SHITS + LSR ZPURE+HI + ROR ZPURE+LO + LSR ZPURE+HI + ROR ZPURE+LO + LSR ZPURE+HI + ROR ZPURE+LO + LSR ZPURE+HI + ROR ZPURE+LO + LSR ZPURE+HI ; NOW IT CONTAINS FIRST PAGE ON + ROR ZPURE+LO ; SIDE 2 OF THE DISK + + LDA ZBEGIN+ZMODE ; ENABLE SOUND & MONOSPACING (X) + ORA #%00110000 ; (X) + STA ZBEGIN+ZMODE + + LDA #XZIPID ; SET INTERPRETER ID + LDX SIG ; SET WHETHER IIe OR IIc + BNE SETID + LDA #IIcID +SETID: + STA ZBEGIN+ZINTWD + LDA #VERSID + STA ZBEGIN+ZINTWD+1 + LDA #0 ; CLEAR HIGH BYTE + STA ZBEGIN+ZHWRD + STA ZBEGIN+ZVWRD + LDA #80 ; SET SCREEN PARAMETERS + STA ZBEGIN+ZHWRD+1 + LDA #$18 + STA ZBEGIN+ZVWRD+1 + LDA #1 ; EACH "PIXEL" IS 1X1 + STA ZBEGIN+ZFWRD + STA ZBEGIN+ZFWRD+1 + LDA #$18 ; AND SCREEN PARAMETERS + STA ZBEGIN+ZSCRWD + LDA #80 + STA ZBEGIN+ZSCRWD+1 + + 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+ZOBJEC ; NOT TO MENTION + CLC ; THE OBJECT TABLE + ADC ZCODE + STA OBJTAB+HI + LDA ZBEGIN+ZOBJEC+1 ; LSB SAME + STA OBJTAB+LO + + LDA ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + ORA ZBEGIN+ZTCHAR+1 ; is it zero though? + BEQ INICLL + + LDA ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + CLC + ADC ZCODE + STA TCHARS+HI + LDA ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + STA TCHARS+LO + +INICLL: + JSR INITPAG +; +; after loading everything check tchars table! +; + LDA TCHARS+HI + ORA TCHARS+LO + BEQ TCHj ; don't check of tchars==0 + + LDY #$FF ; CHECK IF $FF IS IN TCHARS TBL +TCHLP: INY + LDA (TCHARS),Y + BEQ TCHj ; NULL TERMINATED STRING + CMP #$FF + BNE TCHLP + LDA #1 + STA ALLFLG ; YES, SET ALL FCN KEYS (>127) TO TERMINATORS +TCHj: + JSR CLS ; GET RID OF "LOADING" MSG + LDA ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + STA ZPCM ; MSB + LDA ZBEGIN+ZGO+1 ; AND LSB + STA ZPCL ; >BIT ALREADY ZEROED + JSR VLDZPC ; MACKE ZPC VALID + LDX #80 ; SET XSIZE TO 1 LESS + DEX + STX XSIZE + STX OLDWD ; JIC + + LDA PSTAT ; CHECK IF RESTART & WERE PRINTING + BPL EX2 ; NO + LDA #1 ; YES + STA PSTAT ; RESET PSTAT FOR NEXT TIME + STA SCRIPTF ; TURN SCRIPT FLAG ON + ORA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO + STA ZBEGIN+ZSCRIP+1 +EX2: JSR CLS ; CLEAR SCREEN ... + + + ; ... AND FALL INTO MAIN LOOP + + END + \ No newline at end of file diff --git a/apple/xzip/x.bat b/apple/xzip/x.bat new file mode 100644 index 0000000..88e0836 --- /dev/null +++ b/apple/xzip/x.bat @@ -0,0 +1,13 @@ +ECHO OFF +ECHO THIS BATCH FILE ASSEMBLES XZIP.ASM +ECHO ERRORS ONLY WILL BE IN XZIP.LST +ECHO IF NO ERRORS, XZIP.BIN WILL BE CREATED + +\6502\2500AD_X\X6502 XZIP -ED +\6502\2500AD_X\LINK -Q -C XZIP -X +\6502\SPLIT\SPL XZIP.TSK 2048 2560 53248 + +gwbasic 0 + BCC FIN + JSR GETDSK + LDA DSKBNK ;IS IT FILLING AUX ? + CMP #AUX + BNE FLP ;NO + LDA DBUFF+HI + CMP #PBEGIN ;FILLED TO PAGING BUFFERS YET? + BNE FLP ;NO, NOT YET + + ; NOW PUT STUFF IN RAMDSK + + LDA #MAIN + STA DSKBNK ;POINT BACK TO MAIN MEM + LDA #0 + STA RAMSEC ;POINT TO FIRST SECTOR +LP2: + LDA #>IOBUFF + STA DBUFF+HI ;MAKE GETDSK LEAVE CODE AT [IOBUFF] + JSR DECJ + BCC FIN + JSR GETDSK + LDY #>IOBUFF ;SET UP RAMDSK PARMS + LDA RAMSEC + LDX #WRITE + STA RDBNK+MAIN ;SO WE REALLY JSR RAMDSK + JSR RAMDSK ;CALL RAMDSK + INC RAMSEC + LDA RAMSEC + CMP #RMDSIZE + BCC LP2 + JSR CLS ; CLEAR THE SCREEN FOR NEATNESS + LDA #2 + STA CVT + + LDA NOSIDE2 ; is there a side 2? + BNE FIN ; nope + JMP SIDE2 ; CODE EXISTS ON SIDE2 AND WE HAVE SIDE 1 +FIN: + RTS + +;DECJ RETURNS C=0 WHEN J=$FFFF + +DECJ: LDA J+LO + SEC + SBC #1 + STA J+LO + LDA J+HI + SBC #0 + STA J+HI + RTS + + +; MAKE [MPCPNT],[MPCBNK] POINT TO +; THE RAM PAGE AND BANK THAT HOLDS +; THE V-PAGE MPCH,M +; +VLDMPC: + LDA MPCH + BNE VLD1 ;NOT IN FIRST V-64K + LDA MPCM + CMP #VAUX ;IS IT A PAGE IN MAIN + BCS VLD2 ;NO, IT IS IN AUX + ADC #>ZBEGIN ;ADD OFFSET TO GET RAM PAGE + LDY #MAIN + BEQ VLDEXI ;BRA +VLD2: SBC #VAUX-AUXSTART ;FIX TO OFFST INTO AUX RAM + LDY #AUX + BNE VLDEXI +VLD1: CMP #1 ;BETWEEN 64K AND 128K ? + BNE VLD3 ;NO, ABOVE 128K + + LDA MPCM + CMP #ZBEGIN ;ADD OFFSET TO GET RAM PAGE + LDY #MAIN + BEQ VLDZEXI ;BRA +VLDZ2: SBC #VAUX-AUXSTART ;FIX TO OFFST INTO AUX RAM + LDY #AUX + BNE VLDZEXI +VLDZ1: CMP #1 ;BETWEEN 64K AND 128K ? + BNE VLDZ3 ;NO, ABOVE 128K + LDA ZPCM + CMP #PSIDE1 ;CHECK IF IN RAMDSK + BCC GETYES + BNE GETNO + CPY #A< +; NEXT(PREV(A))=NEXT(A) +; PREV(NEXT(A))=PREV(A) + +DETATCH: TAX + LDA NEXTPNT,X + STA NSUBA + LDA PREVPNT,X + STA PSUBA + TAX + LDA NSUBA + STA NEXTPNT,X + LDA PSUBA + LDX NSUBA + STA PREVPNT,X + RTS + + +; RETURN BUFFER OF PAGE [WANTED] +; IN >A< ELSE SEC (Y=WANTED+LO) + +WHERE: LDX #NUMBUFS-1 +WHLOOP: + LDA WANTED+HI + CMP VPAGEH,X ;>SAME + BEQ WHGOT +WHNOGOT: + DEX + BPL WHLOOP + SEC + RTS +WHGOT: + TYA + CMP VPAGEL,X + BNE WHNOGOT + TXA + CLC + RTS + + +INITPAG: LDX #NUMBUFS-1 + STX CURRENT + LDA #$FF +INILP: + STA VPAGEH,X + DEX + BPL INILP + LDX #0 + LDY #1 +INILP2: + TYA + STA PREVPNT,X + INX + INY + CPX #NUMBUFS + BCC INILP2 + LDA #00 + DEX + STA PREVPNT,X + LDX #0 + LDY #$FF + LDA #NUMBUFS-1 +INILP3: + STA NEXTPNT,X + INX + INY + TYA + CPX #NUMBUFS + BCC INILP3 + + JMP GETSIDE1 + +; TAKE CARE OF CROSSING A PAGE + +CRSMPC: + PHA + INC MPCM + BNE CRS1 + INC MPCH +CRS1: JSR VLDMPC + PLA + RTS + +;SAME AS CRSMPC + +CRSZPC: + PHA + INC ZPCM + BNE CRSZ1 + INC ZPCH +CRSZ1: JSR VLDZPC + PLA + RTS + +GETBYT: + LDY MPCBNK ;SELECT CURRENT BANK + STA RDBNK,Y ;ENABLE READ + LDY MPCL + LDA (MPCPNT),Y ;GET THE BYTE + STA RDBNK+MAIN ;KILL (FOR SAFTY) + INC MPCL ;POINT TO NEXT BYTE + BNE GETGOT ;IF NO CROSS WE ARE STILL VALID + JSR CRSMPC +GETGOT: TAY ;SET FLAGS + RTS ;RED SLIPPER TIME + + ; LIKE GETBYT + +NEXTPC: LDY ZPCBNK + STA RDBNK,Y + LDY ZPCL + LDA (ZPCPNT),Y + STA RDBNK+MAIN ;KILL + INC ZPCL + BNE NXTGOT + JSR CRSZPC +NXTGOT: + TAY + RTS + + PAGE + + END + \ No newline at end of file diff --git a/apple/xzip/xzip.asm b/apple/xzip/xzip.asm new file mode 100644 index 0000000..0668a3e --- /dev/null +++ b/apple/xzip/xzip.asm @@ -0,0 +1,109 @@ + + + TITLE "EZIP/6502 INFOCOM, INC. --- EQUATES" + + ; -------------------------- + ; EZIP/6502 2.0 + ; Z-CODE INTERPRETER PROGRAM + ; FOR APPLE IIE/IIC + ; -------------------------- + + ; INFOCOM, INC. + ; 125 CAMBRIDGEPARK DRIVE + ; CAMBRIDGE, MA 02140 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + PL 58 ; PAGE LENGTH OF PRINTER + +DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER (1 = YES) + +VERSID EQU 'I' ; VERSION OF INTERPRETER +; +; A - INITIAL RELEASE VERSION 9/15/87 +; +; B - jdarnold 10/5/87 +; Fix some scrolling bugs (inc LINCNT twice in CRLF) +; Move INC LINCNT in INPUT: to after the is hit, so +; the FLUSHRD routine had easier check +; +; C - jdarnold 10/8/87 +; Feep on non-terminating function key inputs +; +; D - jdarnold 11/19/87 +; Don't increment LENGTH when in Window 1 +; Get side 1 size from ZENDLOD +; Don't ask for side 2 if there is nothing more there +; +; E - jdarnold 12/1/87 +; Flush buffer before HIGHLIGHT change +; +; F - jdarnold 12/14/87 +; Wrap PRNTT in screen 0, please by using COUT +; +; G - jdarnold 2/3/88 +; Fix SCRIPTING of input line - let CLEARP put in +; +; +; I - jdarnold November 10, 1988 +; Kludge in check of lo-core SCRIPT flag in main loop +; + ; ----------- + ; 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 -- IMPURE CODE TOO LARGE (BM 1/20/86) + ; 14 -- DRIVE ACCESS + ; 15 -- NOT AN EZIP GAME + ; 16 -- ILLEGAL EXTENDED RANGE X-OP + + INCLUDE EQ.ASM + + + TITLE "ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT SHELL" + INCLUDE HARDEQ.ASM + INCLUDE RWTS.ASM + INCLUDE ZDOS.ASM + INCLUDE MACHINE.ASM + INCLUDE COLD.ASM + + TITLE "ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE" + INCLUDE WARM.ASM + INCLUDE MAIN.ASM + INCLUDE SUBS.ASM + INCLUDE DISPATCH.ASM + + TITLE "ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS" + INCLUDE OPS012.ASM + INCLUDE OPSX.ASM + INCLUDE READ.ASM + + TITLE "ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT" + + INCLUDE XPAGING.ASM + INCLUDE ZSTRING.ASM + INCLUDE OBJECTS.ASM + + TITLE "ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT SHELL" + + INCLUDE IO.ASM ; (EZIP SO COLD IS ON 1ST TRACK) + + IF DEBUG + INCLUDE BUGGER.ASM + ENDIF + + END + + \ No newline at end of file diff --git a/apple/xzip/zdos.asm b/apple/xzip/zdos.asm new file mode 100644 index 0000000..49e755e --- /dev/null +++ b/apple/xzip/zdos.asm @@ -0,0 +1,886 @@ + PAGE + STTL "--- Z-DOS: APPLE II ---" + +; -------------------- +; READ A VIRTUAL BLOCK +; -------------------- +; ENTRY: V-BLOCK TO READ IN [DBLOCK] +; BUFFER ADDRESS IN [DBUFF] +; DSKBNK SAYS WHERE TO PUT PAGE (AUX OR MAIN) +; EXIT: DATA AT [DBUFF] + +GETDSK: LDA #0 ; CLEAR TRACK + STA DCBTRK ; USE AS COUNTER + LDX DBLOCK+HI + LDY DBLOCK+LO + CPX ZPURE+HI ;IS THE BLOCK ON SIDE 1 OR 2 + BCC GETSD1 + BNE GETSD2 + CPY ZPURE+LO ;DONT KNOW YET + BCC GETSD1 + + ; SUBTRACT # PAGES ON SIDE 1 TO + ; GET OFFSET INTO SIDE 2 + +GETSD2: LDA SIDEFLG ;ON SIDE 2? + CMP #2 + BEQ GETSDOK ;YES + JSR SIDE2 ;NO, ASK FOR IT + LDX DBLOCK+HI + LDY DBLOCK+LO +GETSDOK:TYA + SEC + SBC ZPURE+LO ;C=1 + TAY + TXA + SBC ZPURE+HI + TAX + TYA + SEC +SDL1: SBC #18 ; DIVIDE BY SECTORS PER TRACK + BCS S1 + DEX ; BORROW + BMI S2 ; ALL GONE + SEC +S1: INC DCBTRK ; INCREMENT TRACK + BCS SDL1 ; CONTINUE +S2: CLC + ADC #18 ; ADD BACK INTO GET SECTOR # + STA DCBSEC + LDA DCBTRK ; CHECK TRACK SIZE + CMP #ZTRKL ; ANYTHING ABOVE TRK 34 + BCC OKA + JMP TRKERR +OKA: + LDA #FREAD ; READ SIDE 2 INDICATOR + BNE GETSDGO ; GO VALIDATE TRACK + + ; CONVERT FOR SIDE 1 + +GETSD1: LDA SIDEFLG ; ARE WE ON SIDE 1 + CMP #1 + BEQ OK3 + JSR SIDE1 + LDX DBLOCK+HI + LDY DBLOCK+LO +OK3: TYA ; GET LSB OF BLOCK ID + AND #%00001111 ; MASK OFF TOP NIBBLE + STA DCBSEC ; TO FORM DCBSEC ID (0-15) + TXA ; GET MSB OF BLOCK ID + ASL A ; SHIFT BOTTOM NIB INTO TOP NIB + ASL A + ASL A + ASL A + STA DCBTRK ; SAVE HERE FOR A MOMENT + TYA ; GET LSB + LSR A ; MOVE TOP TO BOTTOM + LSR A + LSR A + LSR A + ORA DCBTRK ; SUPERIMPOSE TOP OF MSB + CLC ; PRE-LOAD Z-BLOCKS START ON + ADC #ZTRKF ; TRACK 3 (EZIP) + CMP #ZTRKL ; ANYTHING ABOVE TRACK 34 + BCS TRKERR + STA DCBTRK ; THIS IS THE TRACK ID +SDL2: LDA #READ +GETSDGO: + STA RDBNK+MAIN ;SET TO READ FROM MAIN BANK + + ;WHERE BUFFA AND BUFFB ARE + + JSR DOS + BCS DISKERR ;BAD READ + + ; SOMEDAY DOS SHOULD TAKE CARE OF + ; READING/WRITING FROM EITHER BANK + ; IN THE 48K + ; JUST MAKE SURE THERE ARE NO BUFFA + ; BUFFB CONFLICTS + ; DOS EVENTUALLY + + LDY DSKBNK + STA WRTBNK,Y ;SET TO WRITE TO DSKBNK + LDY #0 ; MOVE DATA +SDLP3: LDA IOBUFF,Y ; IN [IOBUFF] + STA (DBUFF),Y ; TO [DBUFF] + INY + BNE SDLP3 + + ; RESET TO WRITE TO MAIN BANK + + STA WRTBNK+MAIN + + INC DBLOCK+LO ; POINT TO NEXT + BNE S5 ; VIRTUAL BLOCK + INC DBLOCK+HI +S5: INC DBUFF+HI + LDA DBUFF+HI + CMP #MAINEND+1 ;PAST LAST MAIN RAM PAGE ? + BCC S6 ;NO + LDA #AUXSTART ;RESET DBUFF TO FIRST AUX PAGE + STA DBUFF+HI + LDA #AUX ;SET DSKBNK TO AUX + STA DSKBNK +S6: RTS + + ; DISKERR SHOULD FIRST ASK IF + ; SIDE [SIDEFLG] IS IN, THEN + ; IT SHOULD RETRY AND IF + ; IT FAILS AGAIN, THEN IT SHOULD + ; ERROR 14 OUT + ; BUT FOR RIGHT NOW STUPIDITY + ; SHALL REMAIN A FATAL FLAW + +DISKERR: + LDA #14 + JMP ZERROR ; DRIVE ACCESS ERROR + + ; POINT TO NEXT SECTOR + +NXTSEC: INC DCBSEC ; UPDATE SECTOR + LDA DCBSEC ; CHECK IT + AND #%00001111 ; DID IT OVERFLOW? + BNE SECTOK ; NO, ALL'S WELL + LDX DCBTRK ; ELSE UPDATE + INX ; TRACK ID + CPX #ZTRKL ; IF < 35, + BCS WRTERR ; SCRAM W/CARRY SET + STX DCBTRK ; ELSE SAVE NEW TRACK +SECTOK: STA DCBSEC ; AND SECTOR + INC DBUFF+HI ; POINT TO NEXT RAM PAGE + CLC ; CLEAR CARRY FOR SUCCESS (WRITE ONLY) + RTS + + +; ---------------------- +; WRITE [DBLOCK] TO DISK +; ---------------------- +; ENTRY: TRACK,SECTOR,DRIVE,SLOT ALL SET ALREADY +; PAGE TO WRITE IN (DBUFF) +; EXIT: CARRY CLEAR IF OKAY, SET IF FAILED + +PUTDSK: LDY #0 ; MOVE DATA AT [DBUFF] + STA RDBNK+MAIN ;SELECT MAIN BANK +PDSK0: LDA (DBUFF),Y ; TO [IOBUFF] + STA IOBUFF,Y ; FOR WRITING + INY + BNE PDSK0 + LDA #WRITE + JSR DOS ; DO IT! + BCC NXTSEC ; OKAY IF CARRY CLEAR +WRTERR: RTS ; ELSE EXIT WITH CARRY SET + + ; *** ERROR #12: DISK ADDRESS RANGE *** + +TRKERR: LDA #12 + JMP ZERROR + + ; *** ERROR #14: DRIVE ACCESS *** + +DSKER: LDA #14 + JMP ZERROR + + +; --------------------- +; READ DBLOCK FROM DISK +; --------------------- +; CALLED BY RESTORE +; ENTER: (W/[DCBSEC/TRK] PRESET) + +GETRES: LDA #READ + JSR DOS + BCS DSKER ; FATAL ERROR IF CARRY SET + LDY #0 ; MOVE DATA + STA RDBNK+MAIN +RES1: LDA IOBUFF,Y ; IN [IOBUFF] + STA (DBUFF),Y ; TO [DBUFF] + INY + BNE RES1 + INC DBLOCK+LO ; POINT TO NEXT + BNE RES2 ; VIRTUAL BLOCK + INC DBLOCK+HI + + ; POINT TO NEXT SECTOR + +RES2: INC DCBSEC ; UPDATE SECTOR + LDA DCBSEC ; CHECK IT + AND #%00001111 ; DID IT OVERFLOW? + BNE RES3 ; NO, ALL'S WELL + LDX DCBTRK ; ELSE UPDATE + INX ; TRACK ID + CPX #ZTRKL ; IF < 35, + BCS WRTERR ; SCRAM W/CARRY SET + STX DCBTRK ; ELSE SAVE NEW TRACK +RES3: STA DCBSEC ; AND SECTOR + INC DBUFF+HI ; POINT TO NEXT RAM PAGE + CLC ; CLEAR CARRY FOR SUCCESS (WRITE ONLY) + RTS + + +; ----------------------------- +; SET UP SAVE & RESTORE SCREENS +; ----------------------------- + +SAVRES: JSR ZCRLF ; CLEAR THE LINE BUFFER + LDA #0 + STA SCRIPT ; DISABLE SCRIPTING + RTS +; JMP HOME ; CLEAR THE SCREEN (LEAVE STATUS AS IS - EZIP) + + +; ----------------- +; DISPLAY A DEFAULT +; ----------------- +; ENTRY: DEFAULT (1-8) IN [A] + +DEFAL: DB " (Default is " +DEFNUM: DB "*) >" +DEFALL EQU $-DEFAL + +DODEF: CLC + ADC #'1' ; CONVERT TO DB II 0-7 + STA DEFNUM ; INSERT IN STRING + LDX #DEFAL + LDY #DEFALL + JMP DLINE ; PRINT THE STRING + + +; ----------------------------- +; GET SAVE & RESTORE PARAMETERS +; ----------------------------- + +NUMSAV DB 0 ; HOLDS # SAVES AVAILABLE + +POSIT: DB EOL + DB "Position 1-" +SAVASC: DB "*" +POSITL: EQU $-POSIT +WDRIV: DB EOL + DB "Drive 1 or 2" +WDRIVL EQU $-WDRIV +SLOT: DB EOL + DB "Slot 1-7" +SLOTL EQU $-SLOT +GSLOT: DB 5 ;START W/ DEFAULT SLOT 6 (YES 5 IS 6) +MIND: DB EOL + DB EOL + DB "Position " +MPOS: DB "*; Drive #" +MDRI: DB "*; Slot " +MSLT: DB "*." + DB EOL + DB "Are you sure? (Y/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 #POSIT + LDY #POSITL + JSR DLINE ; "POSITION (1-X)" + + ; GET GAME SAVE POSITION + + LDA GPOSIT ; SHOW THE CURRENT + JSR DODEF ; DEFAULT POSITION + +GETPOS: + BIT ANYKEY ; CLEAR STROBE + JSR GETKEY ; WAIT FOR A KEY + CMP #EOL ; IF [RETURN], + BEQ POSSET ; USE DEFAULT + SEC + SBC #'1' ; ELSE CONVERT DB II TO BINARY + CMP NUMSAV ; IF BE<[NUMSAV] + BCC SETPOS ; MAKE IT THE NEW DEFAULT + JSR BEEP ; ELSE RAZZ + JMP GETPOS ; AND TRY AGAIN +POSSET: LDA GPOSIT ; USE DEFAULT +SETPOS: STA TPOSIT ; USE KEYPRESS + CLC + ADC #'1' ; CONVERT TO DB II "1"-"5" + STA MPOS ; STORE IN TEMP STRING + STA SVPOS + STA RSPOS + ORA #%10000000 + JSR CHAR ; AND DISPLAY IT + + ; GET DRIVE ID + + LDX #WDRIV + LDY #WDRIVL + JSR DLINE ; "DRIVE 1 OR 2" + LDA GDRIVE ; SHOW DEFAULT + JSR DODEF + +GETDRV: + BIT ANYKEY ; CLEAR STROBE + 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 BEEP + JMP GETDRV ; ELSE TRY AGAIN +DRVSET: LDA GDRIVE ; USE DEFAULT +SETDRV: STA TDRIVE ; USE [A] + CLC + ADC #'1' ; CONVERT TO DB II 1 OR 2 + STA SAVDRI ; STORE IN DRIVE STRING + STA MDRI ; AND IN TEMP STRING + ORA #%10000000 + JSR CHAR ; AND SHOW NEW SETTING + + ;IF IIC SLOT IS 6 OTHERWISE ASK + + LDA SIG ; CHECK IF IIc + BNE PREIIC ; IS NOT A IIC SO ASK WHICH SLOT + LDA #5 ; SLOT 6 + BNE SETSLT ; JMP +PREIIC: LDX #SLOT + LDY #SLOTL + JSR DLINE ; "SLOT 1-7" + + ; GET DRIVE SLOT + + LDA GSLOT ; SHOW THE CURRENT + JSR DODEF ; DEFAULT SLOT +GETSLT: + BIT ANYKEY ; CLEAR STROBE + JSR GETKEY ; WAIT FOR A KEY + CMP #EOL ; IF [RETURN], + BEQ SLTSET ; USE DEFAULT + SEC + SBC #'1' ; ELSE CONVERT DB II TO BINARY + CMP #7 ; IF "7" OR BELOW + BCC SETSLT ; MAKE IT THE NEW DEFAULT +BADSLT: JSR BEEP ; ELSE RAZZ + JMP GETSLT ; AND TRY AGAIN +SLTSET: LDA GSLOT ; USE DEFAULT +SETSLT: STA TSLOT ; USE KEYPRESS + CLC + ADC #'1' ; CONVERT TO DB II "1"-"7" + STA MSLT ; STORE IN TEMP STRING + LDX SIG ; AND IF NOT IIC + BEQ DBLCHK + ORA #%10000000 + JSR CHAR ; DISPLAY IT + +DBLCHK: LDX #MIND + LDY #MINDL + JSR DLINE + + ; VALIDATE RESPONSES + +GETYN: + BIT ANYKEY ; CLEAR STROBE + 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 BEEP ; ELSE BEEP + JMP GETYN ; INSIST ON Y OR N + +NOTSAT: LDX #NO + LDY #NOL + JSR DLINE ; PRINT "NO"/EOL + JMP PARAMS ; AND TRY AGAIN + +ALLSET: LDX #YES + LDY #YESL + JSR DLINE ; PRINT "YES"/EOL + LDA TDRIVE ; MAKE THE TEMPORARY DRIVE + STA DCBDRV ; AND SET [DRIVE] ACCORDINGLY + INC DCBDRV ; 1-ALIGN THE DRIVE ID + LDX TSLOT ; MAKE TEMP DRIVE SLOT + INX ; 1-ALIGN + TXA + ASL A ; * 16 FOR # RWTS NEEDS + ASL A + ASL A + ASL A + STA DCBSLT ; AND SET SLOT ACCORDINGLY + +; CALC STARTING SECTOR & TRACK (BM 1/20/86) + + LDA TPOSIT ; GET THE SAVE POSITION + LDX NUMSAV ; AND # SAVES AVAILABLE + CPX #3 ; IF 3 SAVES, + BEQ GOOX ; NO OFFSET NECESSARY + + CLC ; ELSE JUMP INDEX + ADC #3 ; OVER 1ST 3 ENTRIES + +GOOX: TAX ; USE MUNGED [TPOSIT] AS AN INDEX + LDA TRAX,X ; INTO TABLES + STA DCBTRK ; FOR 1ST TRACK + LDA SEX,X ; AND SECTOR + STA DCBSEC + + LDX #INSM + LDY #INSML + JSR DLINE ; "INSERT SAVE DISK IN DRIVE X." + +; --------------------- +; "PRESS RETURN" PROMPT +; --------------------- + +RETURN: LDX #RTN + LDY #RTNL + JSR DLINE ; SHOW PROMPT + + ; ENTRY FOR QUIT/RESTART + +GETRET: + BIT ANYKEY ; CLEAR STROBE + JSR GETKEY ; WAIT FOR [RETURN] (SHOW NO CURSOR) + CMP #EOL + BEQ GRRTS + JSR BEEP ; ACCEPT NO + JMP GETRET ; SUBSTITUTES! +GRRTS: RTS + +RTN: DB EOL + DB "Press [RETURN] to continue." + DB EOL +RTNL EQU $-RTN + +TRAX: DB 0,11,23 ; 1ST TRACK FOR 3-SAVE DISKS + DB 0,8,17,25 ; 1ST TRACK FOR 4-SAVE DISKS +SEX: DB 0,8,0 ; 1ST SECTOR FOR 3-SAVE DISKS + DB 0,8,0,8 ; 1ST SECTOR FOR 4-SAVE DISKS + +; -------------------- +; PROMPT FOR GAME DISK +; -------------------- +; EZIP USES BOTH SIDES OF DISK + +GAME: DB EOL + DB "Insert Side " +DSIDE: DB "* of the STORY disk into Drive #1." + DB EOL +GAMEL EQU $-GAME + +SIDE1: LDA #'1' ; ASK FOR SIDE 1 + STA DSIDE + LDA #1 ;SET FOR SUCCESS + STA SIDEFLG +SL1: LDX #GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + LDA #0 ; GO READ TRK 0, SEC 0, & SEE + STA DCBSEC ; IF THEY DID SWAP + STA DCBTRK + LDA #1 ; MAKE SURE WE'RE ON + STA DCBDRV ; THE BOOT DRIVE + LDA #READ + JSR DOS + BCS SL1 ; DISK READ ERROR, WRONG FORMAT, SO: WRONG SIDE + BCC ASK2 ; JUMP, GOOD + +SIDE2: + LDA NOSIDE2 ; is there a side 2? + BEQ SIDEY ; ayyup + JMP SIDE1 ; if not, just ask for side1? +SIDEY: + LDA #'2' ; ASK FOR SIDE 2 + STA DSIDE + LDA #2 + STA SIDEFLG ; SET FOR SUCCESS + LDA DCBDRV ; GET LAST DRIVE USED + PHA ; HOLD IT A SEC + LDA #1 ; MAKE SURE WE'RE ON + STA DCBDRV ; THE BOOT DRIVE + PLA ; IF SAVED/RESTORED + CMP #2 ; TO DRIVE 2, DON'T ASK + BEQ ASK2 ; NOTE: THIS IS OK W/ VERIFY CAUSE + + ; ASKS FOR SIDE 2 FIRST, RESETTING + ; DRIVE TO 1 + +SL2: LDX #GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + LDA #0 ; GO READ TRK 0, SEC 0, & SEE + STA DCBSEC ; IF THEY DID SWAP + STA DCBTRK + LDA #FREAD + JSR DOS + BCS SL2 ; DISK READ ERROR, WRONG FORMAT, SO: WRONG SIDE +ASK2: LDA #$FF ; RE-ENABLE + STA SCRIPT ; SCRIPTING + 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: LDA #'N' + LDX NARGS + BEQ OLDSAV ; NORMAL, COMPLETE SAVE + LDA #'P' +OLDSAV: STA TYPE + + JSR SAVRES ; SET UP SCREEN + LDX #SAV + LDY #SAVL + JSR DLINE ; "SAVE POSITION" + JSR PARAMS ; GET PARAMETERS + LDX #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+LO ; MOVE [ZSP] + STA BUFSAV+2 + LDA ZSP+HI + STA BUFSAV+3 + LDA OLDZSP+LO + STA BUFSAV+4 + LDA OLDZSP+HI ; MOVE [OLDZSP] + STA BUFSAV+5 + LDX #2 ; MOVE CONTENTS OF [ZPC] +ZSL1: LDA ZPC,X ; TO BYTES 7-9 + STA BUFSAV+6,X ; OF [BUFSAV] + DEX + BPL ZSL1 + LDA TYPE + STA BUFSAV+9 ; NORMAL OR PARTIAL + CMP #'P' + BNE ZSNONM ; NORMAL SAVE SO NO name TO SAVE + LDY #0 + LDA (ARG3),Y + TAY ; MOVE NAME TO BUFSAV +ZSL3: LDA (ARG3),Y + STA BUFSAV+10,Y + DEY + BPL ZSL3 ; INCLUDE LENGTH BYTE + + ; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK + +ZSNONM: LDA #>LOCALS ; LOCALS OK, WILL RD WHOLE OF PG EVEN THOUGH + ; LOCALS STARTS PART WAY THRU, WE WANT FRM 00 + STA DBUFF+HI ; POINT TO THE PAGE + JSR PUTDSK ; AND WRITE IT OUT + BCC ZSOK ; IF SUCCEEDED, WRITE STACK + +ZSBAD: JSR SIDE2 ; ELSE REQUEST STORY DISK + JMP RET0 ; AND FAIL + + ; IF A PARTIAL SAVE WRITE FROM ARG1 FOR ARG2 BYTES TO DISK + ; (ROUNED TO PGS) SKIPPING ZSTACK WRITE + +ZSOK: LDA TYPE + CMP #'P' + BNE ZSALL + LDA ARG1+HI ; FIND WHERE TO START & HOW FAR TO GO + CLC + ADC ZCODE ; MAKE IT ABSOLUTE + STA DBUFF+HI + LDX ARG2+HI + INX ; TO GET WHOLE OF LAST PG + STX I+LO + JMP ZSL2 + + ; WRITE CONTENTS OF Z-STACK TO DISK + +ZSALL: LDA #>ZSTKBL ; POINT TO 1ST PAGE + STA DBUFF+HI + LDA #4 ; DO ALL 4 PAGES + STA L ; SET COUNTER +ZSOKLP: JSR PUTDSK ; WRITE THEM + BCS ZSBAD + DEC L + BNE ZSOKLP + + ; 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 +ZSL2: JSR PUTDSK + BCS ZSBAD + DEC I+LO + BNE ZSL2 + JSR SIDE2 ; PROMPT FOR GAME DISK + + LDA TDRIVE ; IF SAVE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TSLOT ; NEXT TIME + STA GSLOT + LDA TPOSIT + STA GPOSIT + LDA #1 ; SET TO MARK + LDX #0 + JMP PUTBYT ; SUCCESS + + +; ------------ +; 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: LDA #'N' + LDX NARGS + BEQ OLDRES ; NORMAL, COMPLETE RESTORE + LDA #'P' +OLDRES: STA TYPE + + JSR SAVRES + LDX #RES + LDY #RESL + JSR DLINE ; "RESTORE POSITION" + JSR PARAMS ; GET PARAMETERS + LDX #RSING + LDY #RSINGL + JSR DLINE ; "RESTORING POSITION X ..." + + LDA TYPE ; PARTIAL SAVE DIFFERS STARTING HERE + CMP #'P' + BNE ZRNRML + JMP ZPARTR + + ; SAVE LOCALS IN CASE OF ERROR + +ZRNRML: LDX #31 +LOCSAV: LDA LOCALS,X ; COPY ALL LOCALS + STA $0100,X ; TO BOTTOM OF MACHINE STACK + DEX + BPL LOCSAV + + LDA #MAIN + STA DSKBNK ; SET TO WRITE TO MAIN BANK + LDA #>LOCALS + STA DBUFF+HI + JSR GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + BCS ZRBAD + + LDA BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID + CMP ZBEGIN+ZID ; MATCH THE CURRENT ID? + BNE ZRBAD ; WRONG DISK IF NOT + + LDA BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE? + CMP ZBEGIN+ZID+1 + BEQ ZROK ; CONTINUE IF BOTH BYTES MATCH + + ; HANDLE RESTORE ERROR + +ZRBAD: LDX #31 ; RESTORE ALL SAVED LOCALS +ZRL2: LDA $0100,X + STA LOCALS,X + DEX + BPL ZRL2 + +BADRES: JSR SIDE2 ; PROMPT FOR GAME DISK + JMP RET0 ; PREDICATE FAILS + + ; CONTINUE RESTORE + +ZROK: LDA ZBEGIN+ZSCRIP ; SAVE BOTH FLAG BYTES + STA I+LO + LDA ZBEGIN+ZSCRIP+1 + STA I+HI + + LDA #>ZSTKBL ; RETRIEVE OLD CONTENTS OF + STA DBUFF+HI ; Z-STACK + LDA #4 ; DO 4 PAGES + STA L ; SET COUNTER +ZROKLP: JSR GETRES ; GET 4 PAGES OF Z-STACK + BCC ZROKL1 + JMP DISKERR ; IF HERE, MIX OF GOOD & BAD SO DIE + +ZROKL1: DEC L + BNE ZROKLP + + LDA ZCODE + STA DBUFF+HI + JSR GETRES ; GET 1ST BLOCK OF PRELOAD + BCC ZROKL2 + JMP DISKERR + +ZROKL2: 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 GETRES ; FETCH THE REMAINDER + BCC LREST0 + JMP DISKERR +LREST0: DEC I+LO ; OF THE PRELOAD + BNE LREST + + ; RESTORE THE STATE OF THE SAVED GAME + + LDA BUFSAV+2 ; RESTORE THE [ZSP] + STA ZSP+LO + LDA BUFSAV+3 + STA ZSP+HI + LDA BUFSAV+4 + STA OLDZSP+LO + LDA BUFSAV+5 ; AND THE [OLDZSP] + STA OLDZSP+HI + + LDX #2 ; RESTORE THE [ZPC] +ZRL4: LDA BUFSAV+6,X + STA ZPC,X + DEX + BPL ZRL4 + +ZROUT: JSR SIDE2 ; PROMPT FOR GAME DISK + JSR VLDZPC ; MAKE VALID (MUST DO AFTER GET DISK) + + LDA TDRIVE ; IF RESTORE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TSLOT ; NEXT TIME + STA GSLOT + LDA TPOSIT + STA GPOSIT + LDA #2 ; SET TO + LDX #0 + JMP PUTBYT ; SUCCESS + + + ; DO PARTIAL RESTORE GETTING 1ST PAGE + ; AND LAST PAGE BYTE ALIGNMENT CORRECT + +ZPARTR: ; WRITE LOCALS TO IOBUFF JUST TO LOOK AT NAME + + LDA #MAIN + STA DSKBNK + LDA #>IOBUFF ; DON'T READ TO LOCALS YET (X) + STA DBUFF+HI + JSR GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + BCS ZPBAD ; BAD DISK READ IF CARRY CLEAR + + LDY #0 ; ADD ALL OFFSETS TOGETHER TO + LDA (ARG3),Y ; COMPARE PARTIAL NAME (LENGTH) + TAY ; COUNTER + CLC + ADC #IOBUFF ; GET 1ST PAGE + STA DBUFF+HI ; GETRES SHOULD KEEP IN IOBUFF + JSR GETRES + BCC POK + JMP DISKERR ; ALL MESSED UP, JUST QUIT + +POK: LDY ARG1+LO ; START BYTE FIRST PAGE +ZPART0: LDA IOBUFF,Y + STA (I),Y + JSR DECJ + BCC ZROUT ; CARRY CLEAR IF $FFFF RESULT + INY + BNE ZPART0 + + LDA #>IOBUFF ; GET SUBSEQUENT PAGES + STA DBUFF+HI ; GETRES SHOULD KEEP IN IOBUFF + JSR GETRES + BCC POK2 + JMP DISKERR +POK2: LDY #0 + JMP ZPART0 + +ZPBAD: JMP BADRES ; NAMES DON'T MATCH, DIE + + + ; THE OLD SAVE & RESTORE STILL HAVE OPCODES + ; SO JUST PUT IN A PLACE FOR THEM HERE FOR NOW + +OSAVE: +OREST: RTS + +ZISAVE: +ZIREST: JMP RET0 ; NOT IMPLEMENTED ON APPLE + + END + \ No newline at end of file diff --git a/apple/xzip/zstring.asm b/apple/xzip/zstring.asm new file mode 100644 index 0000000..28c3d52 --- /dev/null +++ b/apple/xzip/zstring.asm @@ -0,0 +1,436 @@ + PAGE + STTL "--- 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 + ROL A + STA MPCH + ASL MPCL ; QUAD-ALIGN ADDRESS!(EZIP) + ROL MPCM + ROL MPCH + JMP VLDMPC +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 SETFWD ; 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 + JSR VLDMPC + JMP PZTOP ; CONTINUE INNOCENTLY + + +; ---------------------- +; RETURN CURRENT CHARSET +; ---------------------- + +GETSET: LDA TSET + BPL GS + LDA PSET + RTS +GS: LDY #$FF + STY TSET + RTS + + +; ------------------------- +; POINT [I] AT FWORD STRING +; ------------------------- + +SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS + ASL A + STA MPCL + LDA I+HI + ROL A + STA MPCM + LDA #0 + ROL A + STA MPCH + JMP VLDMPC + + +; ----------------- +; 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 + LDX #$08 ; WITH PAD CHARS ($05) +CZSL: STA OUT,X + DEX + BPL CZSL + + LDA #9 ; 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 9 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 + STA OUT+2 ; MOVE CRUSHED Z-WORD + STX OUT+3 ; INTO PLACE + LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) + ASL A ; SHIFT BITS + ASL A + ASL A + ASL A + ROL OUT+6 ; ALONG WITH 7TH Z-CHAR + ASL A + ROL OUT+6 + ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR + STA OUT+5 ; SAVE HERE + LDA OUT+6 ; GRAB 7TH Z-CHAR + ORA #%10000000 ; SET HIGH BIT + STA OUT+4 ; MOVE CRUSHED Z-WORD 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 + + \ No newline at end of file diff --git a/apple/yzip/apl2iff/apl2iff.c b/apple/yzip/apl2iff/apl2iff.c new file mode 100644 index 0000000..e1b08d5 --- /dev/null +++ b/apple/yzip/apl2iff/apl2iff.c @@ -0,0 +1,236 @@ +#include "iff-ilbm.h" +#include "picfile.h" +#include +#include + +BitMapHeader header; + +palette pal; + +dump_apple_iff(newdat, fname, width, height) +unsigned char *newdat; +char *fname; +int width, height; +{ + int n, i, y, x, dbit, col, sbit; + long int sav_ptr, len, osav_ptr, olen; + FILE *out; + int rwidth; + char *newname; + unsigned char *planes[4]; + load_apple_palette(&pal, 0); /* Get the palette set up */ + rwidth = width * 2; + header.w = 320; + header.h = 200; + header.pageWidth = 320; + header.pageHeight = 200; + header.x = 0; + header.y = 0; + header.yAspect = 11; + header.xAspect = 10; + header.nPlanes = 4; + n = 4 + 8 + 20 + 8; + n += 3 * 16; + if (n & 1) n++; +/* n += 8 + ((header.w + 7) / 8) * header.h * header.nPlanes; */ + newname = make_pic_name(fname, ".iff"); + out = fopen(newname, "wb+"); + fwrite("FORM", 1, 4, out); + sav_ptr = ftell(out); /* Save location of file size */ + putLONG( 0L, out); + fwrite("ILBM", 1, 4, out); + fwrite("BMHD", 1, 4, out); + header.compression = 1; + header.masking = mskNone; + header.pad1 = 0; + header.transparentColour = 0; + putLONG( 20L, out); + putWORD(header.w, out); + putWORD(header.h, out); + putWORD(header.x, out); + putWORD(header.y, out); + putc(header.nPlanes, out); + putc(header.masking, out); + putc(header.compression, out); + putc(header.pad1, out); + putWORD(header.transparentColour, out); + putc(header.xAspect, out); + putc(header.yAspect, out); + putWORD(header.pageWidth, out); + putWORD(header.pageHeight, out); + fwrite("CMAP", 1, 4, out); + osav_ptr = ftell(out); + putLONG(0L, out); + for (i = 0; i < pal.size; i++) { + putc(pal.paldata[i].r*240/255, out); + putc(pal.paldata[i].g*240/255, out); + putc(pal.paldata[i].b*240/255, out); } + olen = ftell(out) - osav_ptr - 4L; + if (((3 * pal.size) & 1) != 0) + putc(0, out); + fseek(out, osav_ptr, 0); + putLONG(olen, out); + fseek(out, 0L, 2); + for (i = 0; i < header.nPlanes; i++) + planes[i] = (unsigned char *)malloc((header.w + 7) / 8); + fwrite("BODY", 1, 4, out); + osav_ptr = ftell(out); + putLONG(0L, out); /* For length of body */ + for (y = 0; y < height; y++) { + for (x = 0; x < ((header.w + 7) / 8); x++) { + for (i = 0; i < header.nPlanes; i++) { + planes[i][x] = 0; } } + for (x = 0, dbit = (128 | 64) ; x < rwidth; x += 2, dbit /= 4) { + if (dbit == 0) dbit = (128 | 64); + col = *newdat++; + /* Do each pixel twice, to double the width */ + for (i = 0, sbit = 1; i < header.nPlanes; i++, sbit *= 2) + if (col & sbit) + planes[i][x / 8] |= dbit; } + for (i = 0; i < header.nPlanes; i++) + write_line(planes[i], header.w, out); } + for (x = 0; x < ((header.w + 7) / 8); x++) { + for (i = 0; i < header.nPlanes; i++) { + planes[i][x] = 0; } } + for (; y < 200; y++) { + for (i = 0; i < header.nPlanes; i++) + write_line(planes[i], header.w, out); } + olen = ftell(out) - osav_ptr - 4L; + if ((olen & 1) != 0) /* Pad to even # bytes */ + putc(0, out); + len = ftell(out) - sav_ptr - 4L; + fseek(out, osav_ptr, 0); + putLONG(olen, out); + fseek(out, sav_ptr, 0); + putLONG(len, out); /* Write out file length */ + fclose(out); } + +write_line(plane, width, out) +unsigned char *plane; +int width; +FILE *out; +{ + int i = 0, max = ((width + 7) / 8) - 1, j; + int lastout = -1; + int run = 0; + int cval, lastval, beg_run = 0; + while (1) { + cval = plane[i]; /* Current byte */ + if (i == 0) { /* If first on line, just initialize stuff */ + lastval = cval; + run = 1; } + else { + if (cval == lastval) { /* Same as last one */ + run++; + if ((run > 2) && (lastout != (beg_run - 1))) { + /* Dump some literals if we now have a run longer than 2 and + the next byte to dump isn't the beginning of the run. */ + putc(beg_run - lastout - 2, out); /* Literal */ + for (j = lastout + 1; j < beg_run; j++) + putc(plane[j], out); + lastout = beg_run - 1; } } + else if (run > 2) { + /* We have a run that just ended, so dump it */ + putc(-(run - 1), out); + putc(lastval, out); + lastval = cval; /* And start a new one */ + run = 1; + lastout = i - 1; + beg_run = i; } + else { + run = 1; + lastval = cval; + beg_run = i; } } + if (i == max) { + /* We're looking at the last byte */ + if (lastout != i) { + /* And it hasn't been dumped yet */ + if (run > 2) { + /* If there's a run, dump it */ + putc(-(run - 1), out); + putc(lastval, out); } + else { + /* Otherwise, dump some literals */ + putc(i - lastout - 1, out); + for (j = lastout + 1; j <= i; j++) + putc(plane[j], out); } } + break; } + i++; } } + +unsigned char input_buf[16384]; + +unsigned char *do_apple_cvt(fname, section) +char *fname; +int section; +{ + int fp, ilen; + unsigned char *picdat; + int iwidth = 140; + int iheight = 192; + int width, height, xmin, xmax, ymin, ymax; + fp = open(fname, O_RDONLY); + if (fp < 0) { + perror(fname); + exit(1); } + ilen = read(fp, &input_buf[0], 16384); + close(fp); + if (section) { + iwidth = input_buf[0]; + iheight = input_buf[1]; } + xmin = 0; + ymin = 0; + xmax = iwidth - 1; + ymax = iheight - 1; + width = 1 + xmax - xmin; + height = 1 + ymax - ymin; + picdat = (unsigned char *)malloc(width * height); + if (section) + parse_apple_file(&input_buf[2], picdat, iwidth, iheight, xmin, ymin, xmax, ymax); + else + parse_apple_file(&input_buf[0], picdat, 0, 0, xmin, ymin, xmax, ymax); + dump_apple_iff(picdat, fname, width, height); + free( picdat ); + } + +main(argc, argv) +int argc; +char **argv; +{ + char *str; + int section = 1; + argv++; + _fmode = O_BINARY; /* set the default open mode to NOT TEXT */ + while ( --argc ) + { + str = *argv++; + if (str[0] == '-') + { + if ((str[1] == 'p') || (str[1] == 'P')) + { + section = 0; + printf("Picture.\n"); + } +} + else + { + printf("Making %s %s an IFF file.\n", (section?"SECTION":"PICTURE"), + str ); + do_apple_cvt(str, section); + } + } +} + +putWORD(n, out) +FILE *out; +{ + putc(n>>8, out); + putc(n, out); +} + +putLONG(n, out) +long int n; +FILE *out; +{ + int i, shft; + for (i = 0, shft = 24; i < 4; i++, shft -= 8) { + putc(n >> shft, out); } } diff --git a/apple/yzip/apl2iff/apple.pal b/apple/yzip/apl2iff/apple.pal new file mode 100644 index 0000000..e6c719d Binary files /dev/null and b/apple/yzip/apl2iff/apple.pal differ diff --git a/apple/yzip/apl2iff/applebit.c b/apple/yzip/apl2iff/applebit.c new file mode 100644 index 0000000..1272f65 --- /dev/null +++ b/apple/yzip/apl2iff/applebit.c @@ -0,0 +1,94 @@ +/* Read data from a Dazzle Draw file. The format's kind of strange, and there + are two different ones: + If section is true (width and height are supplied), + this is part of a screen image. There are two header bytes, + width and height, followed by data. The data is in 7-bit bytes (which ignore + 8-bit byte boundaries), stored in reverse order. Each pixel is four bits. + One thus gets a 7-bit byte, reverses it, and takes the high four bits. + The remaining three bits go into the next pixel, along with the high bit + of the next 7-bit byte after reversing it. Ain't this just more fun than + you can count? + Otherwise, this is interleaved in strange and wondrous ways. Line 0 starts + at 0; 1 at 0x400; 2 at 0x800; 3 at 0xc00; etc up through 7. Line 8 starts at + 0x80, with subsequent numbers up 0x400 from that; line 16 starts at 0x100; and so + on through line 63. Line 64 starts at 0x28, and 64-127 are otherwise like 0 + through 63. Line 128 starts at 0x50. + Further, there are two sections, of 8K each. Line 0 actually starts at + 0 and 8192. The first byte used (where bytes are as above) is from the first + section; the second from the second section. The input file will always be + 16384 bytes; a group of three lines uses 120 bytes in each section, leaving + 8 bytes of hole, since groups of three lines physically occupy 128 bytes. */ + +int reverse_byte(cb) +int cb; +{ + int i, nb = 0, imask = 1, omask = 64; + for (i = 0; i < 7; i++) { + if (cb & imask) nb |= omask; + imask <<= 1; + omask >>= 1; } + return(nb); } + +parse_apple_file(inbuf, outbuf, width, height, xmin, ymin, xmax, ymax) +unsigned char *inbuf, *outbuf; +int width, height, xmin, ymin, xmax, ymax; +{ + int cbits_left = 0; + int curbyte, i, j, outbyte, loffs, bank; + unsigned char *lb1, *lb2; + if (width > 0) { /* It's just a file section */ + for (i = 0; i < height; i++) { + cbits_left = 0; + for (j = 0; j < width; j++) { + outbyte = 0; + if (cbits_left < 4) { /* Not enough in curbyte for a whole pixel */ + if (cbits_left > 0) /* Use what's there */ + outbyte = curbyte << (4 - cbits_left); + curbyte = reverse_byte(*inbuf++); + /* Now have a 7-bit byte in curbyte. Need 4-cbits_left bits + from it, leaving 3+cbits_left for the next time. */ + outbyte = outbyte | (curbyte >> (3 + cbits_left)); + cbits_left += 3; } + else { + cbits_left -= 4; + outbyte = curbyte >> cbits_left; } + outbyte &= 0xf; + if ((i >= ymin) && (i <= ymax) && (j >= xmin) && (j <= xmax)) + *outbuf++ = outbyte; } } } + else { /* It's a whole file */ + for (i = 0; i < 192; i++) { + j = i / 64; + if (j == 0) + loffs = 0; + else if (j == 1) + loffs = 0x28; + else + loffs = 0x50; + j = i % 64; + loffs = loffs + ((j / 8) * 0x80); + loffs = loffs + ((j % 8) * 0x400); + lb1 = &inbuf[loffs]; + lb2 = &inbuf[loffs + 8192]; + bank = 0; + cbits_left = 0; + for (j = 0; j < 140; j++) { + outbyte = 0; + if (cbits_left < 4) { + if (cbits_left > 0) + outbyte = curbyte << (4 - cbits_left); + if (bank == 0) { + bank = 1; + curbyte = reverse_byte(*lb1++); } + else { + bank = 0; + curbyte = reverse_byte(*lb2++); } + outbyte = outbyte | (curbyte >> (3 + cbits_left)); + cbits_left += 3; } + else { + cbits_left -= 4; + outbyte = curbyte >> cbits_left; } + outbyte &= 0xf; + if ((i >= ymin) && (i <= ymax) && (j >= xmin) && (j <= xmax)) + *outbuf++ = outbyte; } } } } + + \ No newline at end of file diff --git a/apple/yzip/apl2iff/dd.exe b/apple/yzip/apl2iff/dd.exe new file mode 100644 index 0000000..f55ee8a Binary files /dev/null and b/apple/yzip/apl2iff/dd.exe differ diff --git a/apple/yzip/apl2iff/iff-ilbm.h b/apple/yzip/apl2iff/iff-ilbm.h new file mode 100644 index 0000000..7725e7a --- /dev/null +++ b/apple/yzip/apl2iff/iff-ilbm.h @@ -0,0 +1,67 @@ +/*************************************************************** +iff.ilbm.h +Mon Mar 7 15:37:32 WET 1988 + + (C) 1988 Magnetic Scrolls Ltd + +***************************************************************/ +/* IFF ILBM format graphics */ + +typedef short WORD; +typedef unsigned short UWORD; +typedef unsigned char UBYTE; + +#define ID(c1,c2,c3,c4) ((c3<<8) + c4 ) + +/* Bit Map HeaDer */ + +typedef UBYTE Masking; +#define mskNone 0 +#define mskHasMask 1 +#define mskHasTransparentColor 2 +#define mskLasso 3 + +typedef UBYTE Compression; +#define cmpNone 0 +#define cmpByteRun1 1 + +typedef struct { + UWORD w, h; /* width & height in pixels */ + WORD x, y; /* pixel position for image */ + UBYTE nPlanes; /* # source bitplanes */ + Masking masking; + Compression compression; + UBYTE pad1; + UWORD transparentColour; + UBYTE xAspect, yAspect; /* aspect ratio */ + WORD pageWidth, pageHeight; /* source page size in pixels */ +} BitMapHeader; + +/* Colour MAP */ + +typedef struct { + UBYTE red, green, blue, foo; +} ColourRegister; + +/* GRAB */ + +typedef struct { + WORD x, y; +} Point2D; + +/* DEST */ + +typedef struct { + UBYTE depth; + UBYTE pad1; + UBYTE planePick; + UBYTE planeOnOff; + UBYTE planeMask; +} DestMerge; + +/* SPRT */ + +typedef UWORD SpritePrecedence; + + + \ No newline at end of file diff --git a/apple/yzip/apl2iff/iff.exe b/apple/yzip/apl2iff/iff.exe new file mode 100644 index 0000000..6633b81 Binary files /dev/null and b/apple/yzip/apl2iff/iff.exe differ diff --git a/apple/yzip/apl2iff/makeappl.c b/apple/yzip/apl2iff/makeappl.c new file mode 100644 index 0000000..58f837b --- /dev/null +++ b/apple/yzip/apl2iff/makeappl.c @@ -0,0 +1,759 @@ +/* + piccvt.c + Copyright (c) 1988, Infocom, Inc. + + Convert a picture from Magnetic Scrolls format (as modified) to 8-bit + pixels, with 2-255 colors. The palette is extracted from the picture, + and it is then (possibly) adjusted to the specified number of colors, + defaultly 14. + + There are three methods to reduce the palette: + 1) The least-frequently-used color is replaced by the color closest to it. + 2) The two least-frequently-used colors are replaced by their weighted + average. + 3) If the palette size is currently n, and the desired size is m, the + least-frequently-used 2*(n-m) colors are identified. The least-frequently-used + color and the color closest to it in the set are replaced by their weighted + average. (Experimental). + + Pictures may be coerced into a supplied palette, from a Magnetic Scrolls-format + palette file, by using the -p switch, followed by the name of the palette file. + + The palette size may be set by using the -s switch, followed by a number; + the -g switch may also be followed by the palette size. + + -a causes conversion to an Apple II picture, which uses ~graphics/apple.pal. + If -t is supplied before -a, various stipples used to produce light and dark gray + are disabled. If -h is used instead of -a, it should be followed by a small + fix identifying an alternate method for determining the best match in the palette + for a given color. Currently defined are: + 0: sum of absolute values of differences + 1: sum of absolute values of differences, weighted by input values + 2: sum of squares of differences, weighted by input values + ... + The default if -h is not supplied is just the sum of the squares of the + differences. + -d followed by a number will cause the picture (Apple only) to be dithered + before conversion. This is a failed experiment. */ + +#include +#include + +#ifdef __MSDOS__ +#include +#include +#endif + +#include "picfile.h" +#include "iff-ilbm.h" + +typedef struct cv_pixel { + short r,g,b; +} cv_pixel; + +#ifdef __MSDOS__ +unsigned char huge *FileBuff=0L; /* pointer to file data */ +unsigned char huge *FileOffset=0L; /* dynamic pointer to file data */ +#define _fmalloc farmalloc +#define _free farfree +#else + +#define far +#define _fmalloc malloc +#define _free free +#define SEEK_END 2 + +unsigned char *FileBuff = 0; +unsigned char *FileOffset = 0; +#endif + +unsigned getWORD(); +unsigned long getLONG(); +unsigned char getBYTE(); + + +palette pal; +palette applepal; +int counts[maxpal]; /* Number of uses of this color */ +int ids[maxpal]; /* What to translate this color to */ + +int palsize = 14; +#define PALETTE_CLOSEST 0 +#define PALETTE_WEIGHTED 1 +#define PALETTE_FUNNY 2 +int palette_method = PALETTE_CLOSEST; + +int palette_trans_colors = 2; +int palette_trans_defined = 0; +pixel palette_base; +pixel palette_base_ext; +int outfile; +unsigned char far *picdat; +unsigned char far *cpd; +ColourRegister *palreg; + +int apple_use_all = 0; +int apple_trans_other = 0; +int reduce_x = 1; +int apple_hack = -1; + +init_palettes() +{ + int i; + pal.size = 0; + if (palette_trans_defined) { + pal.size = 2; + pal.paldata[0].r = palette_base.r; + pal.paldata[0].g = palette_base.g; + pal.paldata[0].b = palette_base.b; + if (palette_trans_defined == 2) { + pal.paldata[1].r = palette_base_ext.r; + pal.paldata[1].g = palette_base_ext.g; + pal.paldata[1].b = palette_base_ext.b; } + else { + pal.paldata[1].r = palette_base.r; + pal.paldata[1].g = palette_base.g; + pal.paldata[1].b = palette_base.b; } } + else if (palette_trans_colors) { + pal.size = 2; + pal.paldata[0].r = 0; + pal.paldata[0].g = 0; + pal.paldata[0].b = 0; + pal.paldata[1].r = 255; + pal.paldata[1].g = 255; + pal.paldata[1].b = 255; } + for (i = 0; i < maxpal; i++) { + counts[i] = 0; + ids[i] = i; } +} + +main(argc, argv) +int argc; +char **argv; +{ + char *str; + int temp, i1, i2, i3, i; + int extpars[4]; + extpars[0] = 0; + extpars[1] = 0; + extpars[2] = 0; + extpars[3] = 0; + _fmode = O_BINARY; /* set the default open mode to NOT TEXT */ + + if (argc >= 2) { + argv++; /* Skip the program name */ + argc--; + printf("Generic Apple conversion.\n"); + init_palettes(); + load_apple_palette(&applepal, 1); + while (argc > 0) { + str = *argv++; + if (str[0] == '-') { /* A switch */ + switch (str[1]) { + case 'K': + case 'k': + printf("Colors 0 and 1 are not transparent.\n"); + apple_trans_other = 1; + palette_trans_colors = 0; + break; + case 'W': + case 'w': + printf("Using whole apple palette.\n"); + apple_use_all = 1; + break; + case 'B': + case 'b': + reduce_x = 0; + printf("Not reducing width.\n"); + break; + case 'E': + case 'e': + for (i = 0; i < 4; i++) { + sscanf(*argv++, "%d", &extpars[i]); + argc--; } + printf("Extracting: %d, %d, %d, %d.\n", extpars[0], extpars[1], + extpars[2], extpars[3]); + break; } } + else { + do_iff_cvt(str, &pal, &extpars[0]); } + argc--; } } } + +int linebase, ap_bit, bank, ap_offset, section, apple_ct = 0; +char screen[2][0x2000]; /* main, aux */ +char section_screen[0x4000]; + +void writebit(b) +int b; +{ + if (section) { + if (b) + section_screen[apple_ct] |= ap_bit; + else + section_screen[apple_ct] &= ap_bit ^ -1; } + else { + if (b) + screen[bank][linebase+ap_offset] |= ap_bit; + else + screen[bank][linebase+ap_offset] &= ap_bit ^ -1; } + ap_bit <<= 1; + if (ap_bit == 128) { + ap_bit = 1; + if (bank || section) { + bank = 0; + apple_ct++; + ap_offset++; } + else + bank = 1; } } + +char stip_base[] = {0, 15, 11, 1, 5, 2, 12, 6, 3, 13, 7, 4, 14, 8, 9, 10}; + +write_short(outfile, num) +int outfile, num; +{ + char foo[2]; + foo[0] = (num >> 8) & 0377; + foo[1] = num & 0377; + write(outfile, foo, 2); } + +BitMapHeader header; +int *pal_counts; +char *scanline; + +do_iff_cvt(fname, rpal, extpars) +char *fname; +palette *rpal; +int *extpars; +{ + FILE *fp, *get_iff(); + cv_pixel *picpix, *cpp; + char *newname; + int original_palsize; + int n, w, pid; + int xmin, ymin, xmax, ymax, width, height; + register sbit, dbit, i, j, x, y, planes, k, cbit; + ColourRegister *pp; + + fp = get_iff( fname ); + if (fp < 0) + { + perror(fname); + endit(1); + } + n = getLONG(fp); + if (n != ID('F','O','R','M')) + { + printf("not an IFF file\n"); + endit(-1); + } + n = getLONG(fp); /* number of bytes */ + n = getLONG(fp); + if (n != ID('I','L','B','M')) + { + printf("not an Interleaved Bitmap file\n"); + endit(-1); + } + for (;;) + { + n = getLONG(fp); + switch(n) + { + case ID('B','M','H','D') : /* read in the bit map header */ + n = getLONG(fp); + header.w = getWORD(fp); + header.h = getWORD(fp); + header.x = getWORD(fp); + header.y = getWORD(fp); + header.nPlanes = getBYTE(fp); + header.masking = getBYTE(fp); + header.compression = getBYTE(fp); + header.pad1 = getBYTE(fp); + header.transparentColour = getWORD(fp); + header.xAspect = getBYTE(fp); + header.yAspect = getBYTE(fp); + header.pageWidth = getWORD(fp); + header.pageHeight = getWORD(fp); + break; + case ID('C','M','A','P'): /* palette */ + n = getLONG(fp); /* no of colours * 3 */ + original_palsize = n / 3; + n = original_palsize * sizeof(ColourRegister); + pal_counts = (int *)malloc((n / 3) * sizeof(int)); + for (i = 0; i < original_palsize; i++) + pal_counts[i] = 0; + palreg = (ColourRegister *)malloc(n); + for (i = 0, pp = palreg; i < n/sizeof(ColourRegister); i++, pp++) + { + pp->red = getBYTE(fp); + pp->green = getBYTE(fp); + pp->blue = getBYTE(fp); + } + if (n & 1) + getBYTE(fp); /* lose pad byte */ + break; + case ID('B','O','D','Y'): /* the bit maps */ + n = getLONG(fp); + scanline = (char *)malloc(header.w); + xmin = extpars[0]; + ymin = extpars[1]; + xmax = (extpars[2] > 0)?extpars[2]:header.w+extpars[2]-1; + ymax = (extpars[3] > 0)?extpars[3]:header.h+extpars[3]-1; + width = 1 + xmax - xmin; + if ( width%2 ) + { /* don't want odd width, thank you */ + error("Width is odd - adding one to make even.\n"); + width++; + } + height = 1 + ymax - ymin; + if (reduce_x) + picdat = (unsigned char far *)_fmalloc((width / 2) * height); + else + picdat = (unsigned char far *)_fmalloc(width * height); + cpd = picdat; + for (y = 0; y <= ymax; y++) + { /* For each line in picture */ + dbit = 1; /* destination scanline bit */ + for (x = 0; x < header.w; x++) + scanline[x] = 0; /* Zero the scanline array */ + for (planes=0; planes= ymin) && (y <= ymax)) + { + for (x = xmin; x <= xmax; x++) + { + pid = scanline[x]; + if (reduce_x) + { + if (x % 2) + { + *cpd++ = pid; + pal_counts[pid]++; + } + } + else + { + *cpd++ = pid; + pal_counts[pid]++; + } + } + } + } + /* pal_counts has the number of uses for each color in the palette. + picdat has the actual data. width and height are the dimensions + of the data in picdat. + */ + if (reduce_x) + width = width / 2; + if ((width > 140) || (height > 192)) + { + printf("Picture too big for apple.(%dx%d)\n",width,height); + endit(1); + } + for (i = 0; i < maxpal; i++) + counts[i] = 0; + if (!apple_trans_other) + palette_trans_colors = 2; + rpal->size = 2; + ids[0] = 0; + ids[1] = 0; + /* Make the actual palette. ids[] contains the translations of + the existing numbers to what will actually happen in the output. + */ + for (i = palette_trans_colors; i < original_palsize; i++) + { + if (pal_counts[i] > 0) + { + palette_base.r = palreg[i].red*255/240; + palette_base.g = palreg[i].green*255/240; + palette_base.b = palreg[i].blue*255/240; + j = cvt_addnew(rpal, &palette_base, palette_trans_colors); + counts[j] += pal_counts[i]; + ids[i] = j; + } + } + generate_apple_ids(); + + /* Now translate the picture data */ + for (i = 0; i < width * height; i++) + picdat[i] = ids[picdat[i]]; + + /* At this point, rpal contains the actual palette used. + counts contains the counts for each color. + picdat matches the palette used; color 1 is never used, color 0 + is background only. + */ + if (apple_use_all) + newname = make_pic_name(fname, ".whl"); + else + newname = make_pic_name(fname, ".apl"); + outfile = open(newname, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0666); + if (outfile < 0) + { + outfile = creat(newname, 0666); + if (outfile < 0) + { + error("Can't open output file %s", newname); + endit(1); + } + } + for (i = 0; i < 2; i++) + { + for (j = 0; j < 0x2000; j++) + { + screen[i][j] = 0; + } + } + fprintf( stderr, "Filename %s is a ", newname ); + if ( height < 140 ) + { + fprintf( stderr, "SECTION" ); + section = 1; + write_char(outfile, width); + write_char(outfile, height); + } + else + fprintf( stderr, "PICTURE" ); + + fprintf( stderr, ".\n"); + cpd = picdat; + apple_ct = 0; + ap_bit = 1; + for (i = 0; i < height; i++) + { + linebase = 1024 * (i & 7) + 128 * ((i / 8) & 7) + 40 * (i / 64); + if (ap_bit != 1) + apple_ct++; + ap_bit = 1; + bank = 0; + ap_offset = 0; + for (j = 0; j < width; j++) + { + k = *cpd++; + for (cbit = 8; cbit > 0; cbit >>= 1) + { + if (k & cbit) + writebit(1); + else + writebit(0); + } + } + } + if (section) + { + if (ap_bit != 1) + apple_ct++; + write(outfile, §ion_screen[0], apple_ct); + } + else + write(outfile, &screen[0][0], 0x4000); + + endit(0); + case ID('C','R','N','G') : + getLONG(fp); + getLONG(fp); + getLONG(fp); + break; + case ID('D','P','P','V'): + case ID('C','A','M','G'): + n = getLONG(fp); /* Number of bytes, not including these */ + myseek(fp, (long)n, 1); + break; + default: + printf("Weird section %c%c%c%c\n", n>>24,n>>16,n>>8,n); + endit(-1); + } + } +} + +#define NORMAL 1 +#define LITERAL 2 +#define REPLICATE 3 + +int state = NORMAL; +int n, byte; + +decom(fp) +int fp; +{ + register c; + switch (header.compression) { + case cmpNone : + return getBYTE(fp); + case cmpByteRun1 : + switch (state) { + case NORMAL : + c = getBYTE(fp); + if (c & 0x80) c |= 0xffffff00; /* sign extend */ + if (c >= 0 && c <= 127) { + n = c+1; + state = LITERAL; + return decom(fp); } + else if (c >= -127 && c <= -1) { + n = -c + 1; + state = REPLICATE; + byte = getBYTE(fp); /* byte to replicate */ + return decom(fp); } + else /* noop */ + return decom(fp); + case LITERAL : + byte = getBYTE(fp); + case REPLICATE : + n--; + if (!n) + state = NORMAL; + return byte; + default : + printf("Unknown state %d\n", state); } + /*NOTREACHED*/ + default : + printf("Weird decompression algorithm %d\n", header.compression); } +} + +unsigned getWORD(fp) +FILE *fp; +{ + unsigned char buf[2]; + unsigned int retval; + + if ( FileOffset ) + { + retval = (*FileOffset++) << 8; + return( retval | (*FileOffset++) ); + } + else + { + fread( buf, 1, 2, fp ); + return( ((buf[0] << 8) | buf[1] ) ); + } +} +unsigned long getLONG(fp) +FILE *fp; +{ + unsigned char buf[4]; + + if ( FileOffset ) + { + FileOffset += 2; + return( getWORD(NULL) ); + } + else + { + fread( buf, 1, 4, fp ); + return( ((buf[2] << 8) | buf[3] )); + } +} +unsigned char getBYTE(fp) +FILE *fp; +{ + char buf[1]; + if ( FileOffset ) + return( *FileOffset++ ); + else + { + fread( buf, 1, 1, fp ); + return( buf[0] ); + } +} + + +/* Generate ids[] to map colors in the input palette into the apple palette. + If apple_use_all is set, use as many colors from the apple palette as possible; + this preserves detail at the cost of color fidelity. */ +generate_apple_ids() +{ + int i, j, k; + int nids[32]; + int apids[16]; + int oids[16]; + int distance[16][16]; + int used_colors = 0; + int bestdist, bestcol, unassigned_colors, free_apple_colors; + for (i = 0; i < palette_trans_colors; i++) + nids[i] = 0; + if (!apple_use_all || ((pal.size - palette_trans_colors) > 16)) { + for (i = palette_trans_colors; i < pal.size; i++) { + if (apple_hack >= 0) + k = apple_bestcol(&applepal, &pal.paldata[i], apple_hack); + else + k = cvt_bestcol(&applepal, &pal.paldata[i], 0); + used_colors |= 1 << k; + nids[i] = k; } } + else { + for (i = palette_trans_colors; i < pal.size; i++) { + for (j = 0; j < 16; j++) { + distance[i][j] = df(&pal.paldata[i],&applepal.paldata[j]); } } + /* dist[i][j] is the distance between color i in the source and color j + in the apple palette. */ + for (i = 0; i < 16; i++) + nids[i] = -1; + /* First find any colors that are really close matches, and assign them. */ + for (j = 0; j < 16; j++) { + bestcol = -1; + bestdist = 999999999; + for (i = palette_trans_colors; i < pal.size; i++) { + if (nids[i] >= 0) continue; /* Color already assigned */ + if (distance[i][j] < bestdist) { + bestdist = distance[i][j]; + if (bestdist < 3000) + bestcol = i; } } /* Best color in source for apple color j */ + if (bestcol >= 0) { + nids[bestcol] = j; + used_colors |= 1 << j; } } + unassigned_colors = 0; + free_apple_colors = 0; + /* Now store in oids[] all the source colors that haven't been given mates + yet. unassigned_colors is the count. */ + for (i = palette_trans_colors; i < pal.size; i++) { + if (nids[i] < 0) { + oids[unassigned_colors++] = i; } } + if (unassigned_colors) { + /* Sort these colors in order of luminosity. */ + for (i = 0; i < (unassigned_colors - 1); i++) { + for (j = 0; j < (unassigned_colors - i - 1); j++) { + if (lum(pal.paldata[oids[j]]) > lum(pal.paldata[oids[j+1]])) { + k = oids[j+1]; + oids[j+1] = oids[j]; + oids[j] = k; } } } + /* Now do same for apple colors that haven't been assigned. */ + for (i = 0; i < 16; i++) { + if ((used_colors & (1 << i)) == 0) { + apids[free_apple_colors++] = i; } } + for (i = 0; i < free_apple_colors - 1; i++) { + for (j = 0; j < free_apple_colors - i - 1; j++) { + if (lum(pal.paldata[apids[j]])>lum(pal.paldata[apids[j+1]])) { + k = apids[j+1]; + apids[j+1] = apids[j]; + apids[j] = k; } } } + j = 0; + k = free_apple_colors - 1; + for (i = 0; i < unassigned_colors; i++) { + if ((i % 2) == 0) { + used_colors |= 1 << apids[j]; + nids[oids[i / 2]] = apids[j++]; } + else { + used_colors |= 1 << apids[k]; + nids[oids[unassigned_colors - 1 - (i / 2)]] = + apids[k--]; } } } } + /* nids contains the mapping between colors in the input palette and colors + in the apple palette; ids contains the mapping between the source palette + and the input palette. */ + for (i = 0; i < 16; i++) + oids[i] = nids[ids[i]]; + if (palette_trans_colors && ((pal_counts[0] + pal_counts[1]) > 0)) { + for (i = 0; i < 16; i++) { + if ((used_colors & (1 << i)) == 0) { + printf("Transparencies mapped to %d.\n", i); + for (j = 0; j < palette_trans_colors; j++) { + ids[j] = i; } + break; } } } + for (i = palette_trans_colors; i < 16; i++) + ids[i] = oids[i]; } +/* +* read in the file into a file buffer +*/ +FILE *get_iff( name ) + char *name; +{ + FILE *fp; + long size, count; + unsigned int handle, read_val; +#ifdef __MSDOS__ + union REGS regs, oregs; + struct SREGS sregs; + + fp = fopen( name, "rb" ); +#else + fp = fopen(name, "r"); +#endif + fseek( fp, 0L, SEEK_END ); + size = ftell( fp ); +#ifdef __MSDOS__ + + if ( (FileBuff = (char huge * ) farmalloc( size )) == NULL ) + { /* problems getting memory */ + fprintf( stderr, "Unable to allocate FileBuff . . .\n" ); + fprintf( stderr, "Using disk reads . . .\n" ); + return fp; + } +/*** +* Use DOS functions to open the file and read it all in, cuz we have +* a FAR pointer and fread don't like it. +***/ + if ( (handle = _open( name, O_RDONLY )) < 0 ) + { + perror( "Unable to open file." ); + endit(1); + } + regs.h.ah = 0x3f; /* READ */ + regs.x.bx = handle; + regs.x.cx = 0xffff; /* in 64kb */ + + for ( count = 0; count < size; count += 0xffff ) + { /* read in 64K chunks */ + regs.x.dx = FP_OFF( (FileBuff+count) ); + sregs.ds = FP_SEG( (FileBuff+count) ); + intdosx( ®s, &oregs, &sregs ); + if ( oregs.x.cflag ) + { /* oops, some problems */ + fprintf( stderr, "Problems reading file . . .\n"); + fprintf( stderr, "Using disk reads . . .\n" ); + farfree( (char far *)FileBuff ); + return fp; + } + } + /* close up the files */ + _close( handle ); +#else + /* On Mac, just open the file, read the stuff in */ + FileBuff = (char *)malloc(size); + if ((handle = open(name, O_RDONLY)) < 0) { + perror(name); + exit(1); } + read(handle, FileBuff, size); + close(handle); +#endif + fclose( fp ); + + FileOffset = FileBuff; + return fp; +} + +endit( code ) + int code; +{ + int test; + + close(outfile); + free(scanline); + free(pal_counts); + free(palreg); + _free(picdat); +#ifdef __MSDOS__ + _free( (char far *)FileBuff ); +#endif + exit( code ); +} +myseek( fp, offset, seekn ) + FILE *fp; + long offset; + int seekn; +{ + + if ( FileOffset ) + FileOffset += offset; + else + lseek( fp, offset, seekn ); +} + diff --git a/apple/yzip/apl2iff/makefile b/apple/yzip/apl2iff/makefile new file mode 100644 index 0000000..09ccd90 --- /dev/null +++ b/apple/yzip/apl2iff/makefile @@ -0,0 +1,49 @@ +!if $d(REL) +# for "released version" +CFLAGS= -c -d -f- -k- -G -v- -Z +!else +# for debugging +CFLAGS= -c -d -f- -v +!endif + +!if $d(REL) +LFLAGS= -lc +!else +LFLAGS= -lm -lv -lc +!endif + +CC= tcc $(CFLAGS) $(CCFLAGS) + +LINK= tcc $(LFLAGS) $(CLFLAGS) + +!if $d(NEW) +all: new iff.exe dd.exe + +new: + del *.obj + del *.exe +!else +all: iff.exe dd.exe +!endif + +iff.exe: apl2iff.obj palette.obj picfile.obj applebit.obj + $(LINK) -eiff apl2iff.obj palette.obj picfile.obj applebit.obj + +dd.exe: makeappl.obj picfile.obj palette.obj + $(LINK) -edd makeappl.obj palette.obj picfile.obj + +palette.obj: palette.c picfile.h + $(CC) palette.c + +picfile.obj: picfile.c picfile.h + $(CC) picfile.c + +applebit.obj: applebit.c + $(CC) applebit.c + +makeappl.obj: makeappl.c picfile.h + $(CC) makeappl.c + +apl2iff.obj: apl2iff.c + $(CC) apl2iff.c + diff --git a/apple/yzip/apl2iff/palette.c b/apple/yzip/apl2iff/palette.c new file mode 100644 index 0000000..68cda3c --- /dev/null +++ b/apple/yzip/apl2iff/palette.c @@ -0,0 +1,174 @@ +/*************************************************************** +palette.c +Mon Mar 7 15:35:16 WET 1988 + + (C) 1988 Magnetic Scrolls Ltd + +***************************************************************/ +#include + +#include "picfile.h" + +int apple_bestcol(pl,p,which) +register palette *pl; +register pixel *p; +int which; +{ + int best; + register int i; + unsigned long d,bestdist,tmp; + pixel *p2; + + best = 0; + bestdist = 9999999L; + p2 = pl->paldata; + for (i = 0; i < pl->size; i++, p2++) { + switch (which) { + case 0: + d = 0; + tmp = p->r - p2->r; + if (tmp < 0) + d -= tmp; + else + d += tmp; + tmp = p->g - p2->g; + if (tmp < 0) + d -= tmp; + else + d +=tmp; + tmp = p->b - p2->b; + if (tmp < 0) + d -= tmp; + else + d += tmp; + break; + case 1: + d = 0; + tmp = p->r - p2->r; + if (tmp < 0) + tmp = 0 - tmp; + d += p->r * tmp; + tmp = p->g - p2->g; + if (tmp < 0) + tmp = 0 - tmp; + d += p->g * tmp; + tmp = p->b - p2->b; + if (tmp < 0) + tmp = 0 - tmp; + d += p->b * tmp; + break; + case 2: + d = (sq(p->r - p2->r) * p->r) + (sq(p->g - p2->g) * p->g) + + (sq(p->b - p2->b) * p->b); + break; } + if (d < bestdist) { + best = i; + bestdist = d; } } + return(best); } + +int cvt_bestcol(pl,p,start) +register palette *pl; +register pixel *p; +int start; +{ + int best; + register int i; + unsigned long d,bestdist; + pixel *p2; + best = 0; + bestdist = 9999999L; + p2 = &pl->paldata[start]; + for(i = start; i < pl->size; i++, p2++) + { + d = df(p,p2); + if (d < bestdist) + { + best = i; + bestdist = d; + } + } + return(best); } + +int cvt_inpal(pal,col,start) +register palette *pal; +register pixel *col; +int start; +{ + register int i; + for (i = (pal->size - 1);(i >= start) && (!pixelcmp(col,&pal->paldata[i])); --i); + if (i < start) return(-1); else return(i); +} + +int cvt_addnew(pal,col,start) +palette *pal; +pixel *col; +int start; +{ + int i; + if ((i = cvt_inpal(pal,col,start)) >=0) return (i); + else + { + addcol(pal,col); + return(pal->size - 1); + } +} + +addcol(pal,col) +palette *pal; +pixel *col; +{ + if (pal->size > maxpal) + { + error("Palette too large!\n"); + exit(-1); + } + pal->paldata[pal->size].r = col->r; + pal->paldata[pal->size].g = col->g; + pal->paldata[pal->size++].b = col->b; +} + +loadpalette_preserve(name, pal, preserve) +char *name; +palette *pal; +{ + int i, sz; + picfile *pfp; + pixel *paldat; + paldat = pal->paldata; + sz = pal->size; + if ((pfp = picfopen(name, "r")) != NULL) { + i = pfp->x; + while (i--) { + getpixel(pfp, &paldat[sz]); + sz++; } + pal->size = sz; } } + +loadpalette(name,pal) +char name[]; +palette *pal; + +{ +picfile *pf; + + if ((pf = picfopen(name,"r")) !=NULL) + { + pal->size = pf->x; + getline(pf,pal->paldata); + picfclose(pf); + } else { + error("Can't load palette %s\n",name); + exit(-1); + } +} + +load_apple_palette(pal, preserve) +palette *pal; +int preserve; +{ + char *str; + char palnam[200]; + strcpy(palnam, "apple.pal"); + if (preserve) + return(loadpalette_preserve(palnam, pal)); + else + return(loadpalette(palnam, pal)); } diff --git a/apple/yzip/apl2iff/picfile.c b/apple/yzip/apl2iff/picfile.c new file mode 100644 index 0000000..67bf2b6 --- /dev/null +++ b/apple/yzip/apl2iff/picfile.c @@ -0,0 +1,293 @@ +/*************************************************************** +picfile.c +Mon Mar 7 15:35:22 WET 1988 + + (C) 1988 Magnetic Scrolls Ltd + +***************************************************************/ +#include +#include +#include +#include +#include "picfile.h" + +extern char *malloc(); + +char toolname[40]; + +write_char(fil, chr) +int fil; +char chr; +{ + char buf[1]; + buf[0] = chr; + write(fil, buf, 1); } + +int get_char(fil) +int fil; +{ + unsigned char buf[1]; + read(fil, buf, 1); + return(buf[0]); } + +int get_number(fil) +int fil; +{ + unsigned char buf[2]; + read(fil, buf, 2); + return((buf[0]<<8) + buf[1]); } + +/* Call after reading 'PI' at beginning; fill in pf from info in header. */ +void read_pf_header(pf) +picfile *pf; +{ + unsigned char buf[2]; + char *oname; + int fil; + int hsize; + fil = pf->fp; + read(fil, buf, 1); + oname = malloc(buf[0] + 1); + oname[buf[0]] = 0; + read(fil, oname, buf[0]); + pf->source = oname; + if ((buf[0] + 1) & 1) + read(fil, buf, 1); /* Move to even byte boundary */ + hsize = get_number(fil); /* Number of words left in the header */ + pf->x = 0; + pf->y = 0; + pf->origin_x = 0; + pf->origin_y = 0; + pf->origin_width = 0; + pf->origin_height = 0; + pf->origin_palette = 0; + pf->bordered = 0; + pf->dither_factor = 0; + pf->written = 1; + if (hsize--) { + pf->is_palette = get_number(fil); + if (hsize--) { + pf->x = get_number(fil); + if (hsize--) { + pf->y = get_number(fil); + if (hsize--) { + pf->palette_size = get_number(fil); + if (hsize--) { + pf->origin_x = get_number(fil); + if (hsize--) { + pf->origin_y = get_number(fil); + if (hsize--) { + pf->origin_width = get_number(fil); + if (hsize--) { + pf->origin_height = get_number(fil); + if (hsize--) { + pf->origin_palette = get_number(fil); + if (hsize--) { + pf->bordered = get_number(fil); + if (hsize--) { + pf->dither_factor = get_number(fil); + /* Maybe some extra crap to skip in header */ + if (hsize) { + lseek(fil, 2*hsize, 1); } } } } } } } } } } } } } + +/* TAA 3/5/88. Base argument is picfile structure for input file for + this transform; not used when opening for read. Origin_name is passed + when producing a picfile from some other format (neo comes to mind); + base must be zero for us to look for it, and we must be opening for + writing. + On open for read, the returned picfile is filled in from the file header; + on open for write, the header is written just before the first pixel is + written, to allow the caller to fill information in based on the transform + he's performing. */ +picfile *picfopen(name,mode,xsize,ysize,base,origin_name) +char *name,*mode,*origin_name; +picfile *base; +int xsize,ysize; +{ + picfile *pf; + int fil; + int rfile; + int idx = 0; + int ptr; + int fmode; + char chr; + char buf[7]; + char temp[14]; + char *newname; + if (mode[0] != 'r') { + error("Can't open %s in mode %s", name, mode); + return(NULL); } + if (mode[0] == 'r') + fmode = O_RDONLY; + pf = (picfile *)malloc(sizeof(picfile)); + pf->tbuf = malloc(default_buflen); + pf->buf = pf->tbuf; + pf->buflen = default_buflen; + pf->in_buf = 0; + pf->cur_palette = 0; + pf->cur_stipple = 0; + fil = open(name,fmode,0666); + if (fil >= 0) { + pf->fp=fil; + switch (mode[0]) { + case 'r': + read(fil, buf, 2); + if ((buf[0] != 'P') || (buf[1] != 'I')) { + error("Not a picture file: %s\n", name); + exit(1); } + pf->written = 0; + pf->pictype = 0; + read_pf_header(pf); + break; } } + return (pf); +} + +int picfclose(pf) +picfile *pf; +{ + int result; + if (pf->fp < 0) + result = 0; + else + result = (close(pf->fp)); + if (pf->buflen) + free((char *)pf->tbuf); + if (pf->cur_palette) + free((char *)pf->cur_palette); + if (pf->cur_stipple) + free((char *)pf->cur_stipple); + free((char *) pf); + return(result); +} + +set_picfile_buffer(pf, size) +picfile *pf; +int size; +{ + if (pf->buflen) { + if ((pf->fp < 0) || (pf->buflen == size)) + return; + free(pf->tbuf); } + pf->in_buf = 0; + pf->buf = 0; + pf->buflen = size; + if (size > 0) { + pf->tbuf = (char *)malloc(size); + pf->buf = pf->tbuf; } } + +getpixel(pf,p) +picfile* pf; +pixel* p; +{ + char *cbuf; + palette *pal; + pixel *p1; + int i, j, ib; + char obuf[3]; + char k; + if (pf->buflen) { + cbuf = pf->buf; + ib = pf->in_buf; + if (pal = pf->cur_palette) { + if (ib == 0) { + j = read(pf->fp, pf->tbuf, pf->buflen); + pf->in_buf = j; + ib = j; + cbuf = pf->tbuf; } + if (pf->apple_pic == 3) { + k = *cbuf; + i = pf->buflen - ib; + if ((i % 2) == 0) + k = (k >> 4) & 017; + else { + k = k & 017; + cbuf++; } } + else + k = *cbuf++; + ib--; + p1 = &(pal->paldata[k]); + p->r = p1->r; + p->g = p1->g; + p->b = p1->b; } + else { + for (i = 0; i < 3; i++) { + if (ib == 0) { + j = read(pf->fp, pf->tbuf, pf->buflen); + pf->in_buf = j; + ib = j; + cbuf = pf->tbuf; } + k = *cbuf++; + ib--; + switch (i) { + case 0: + p->r = k; + break; + case 1: + p->g = k; + break; + case 2: + p->b = k; } } } + pf->buf = cbuf; + pf->in_buf = ib; } + else { + if (pal = pf->cur_palette) { + read(pf->fp, obuf, 1); + p1 = &(pal->paldata[obuf[0]]); + p->r = p1->r; + p->g = p1->g; + p->b = p1->b; } + else { + read(pf->fp, obuf, 3); + p->r = obuf[0]; + p->g = obuf[1]; + p->b = obuf[2]; } } +} + +getline(pf,ln) +picfile *pf; +pixel *ln; +{ +int i; + for(i=0;ix;i++) + getpixel(pf,&ln[i]); +} + +error(s,a1,a2,a3,a4,a5,a6) +char s[]; +int a1,a2,a3,a4,a5,a6; +{ + fprintf(stderr,"%s : ",toolname); + fprintf(stderr,s,a1,a2,a3,a4,a5,a6); + fprintf(stderr,"\n"); +} + +char *make_pic_name(old, app) +char *old, *app; +{ + int foo; + char *new, *look; + foo = strcspn(old, ".") + 5; + + if ( isdigit( (int)*old ) ) + { /* ProDOS name can't start with number */ + foo++; + } + new = (char *)malloc( foo ); + + look = new; + if ( isdigit( (int)*old ) ) + { /* can't start with digit, add 'X' in front */ + *look++ = 'X'; + } + for ( ; *old && (*old != '.'); old++ ) + { /* look for bad ProDOS chars */ + if ( isalnum( (int)(*old) ) ) + { /* good char, so copy in */ + *look++ = *old; + } + } + *look = '\0'; + strcat( new, app ); + return(new); +} + \ No newline at end of file diff --git a/apple/yzip/apl2iff/picfile.h b/apple/yzip/apl2iff/picfile.h new file mode 100644 index 0000000..1c6bae3 --- /dev/null +++ b/apple/yzip/apl2iff/picfile.h @@ -0,0 +1,77 @@ +/*************************************************************** +picfile.h +Mon Mar 7 15:37:36 WET 1988 + + (C) 1988 Magnetic Scrolls Ltd + +***************************************************************/ +#ifndef default_buflen + +#define default_buflen 16*3 + +typedef struct pixel { + unsigned char r,g,b; + } pixel; + +#define maxpal 32 + +typedef struct palette { + int size; + pixel paldata[maxpal]; +} palette; + +typedef struct picfile { + int x; + int y; + char *source; + int is_palette; + int origin_x; + int origin_y; + int origin_width; + int origin_height; + int origin_palette; + int bordered; + int dither_factor; + int written; + int fp; + char *buf; + int buflen; + char *tbuf; + int in_buf; + palette *cur_palette; + int palette_size; + char *cur_stipple; + int apple_pic; + int pictype; +} picfile; + +picfile *picfopen(); + +#define pixelcmp(A,B) (((A)->r==(B)->r)&&((A)->g==(B)->g)&&((A)->b==(B)->b)) + +#if (0) + +#define rf 30 +#define bf 11 +#define gf 59 + +#endif + +#define rf 1 +#define gf 1 +#define bf 1 + +#define lum(A) (rf*(A.r)+gf*(A.g)+bf*(A.b)) + +#define sq(a) (((int)a)*((int)a)) + +#define df(x,y) (rf*sq((x)->r-(y)->r)+gf*sq((x)->g-(y)->g) \ + +bf*sq((x)->b-(y)->b)) + + +extern char toolname[]; + +char *make_pic_name(); + +#endif + \ No newline at end of file diff --git a/apple/yzip/apl2iff/tags.mnu b/apple/yzip/apl2iff/tags.mnu new file mode 100644 index 0000000..321e05f --- /dev/null +++ b/apple/yzip/apl2iff/tags.mnu @@ -0,0 +1,40 @@ +reverse_byte ; 22 APPLEBIT.C +parse_apple_file ; 32 APPLEBIT.C +write_char ; 18 PICFILE.C +get_char ; 26 PICFILE.C +get_number ; 33 PICFILE.C +read_pf_header ; 41 PICFILE.C +picfopen ; 102 PICFILE.C +picfclose ; 145 PICFILE.C +set_picfile_buffer ; 163 PICFILE.C +getpixel ; 178 PICFILE.C +getline ; 246 PICFILE.C +error ; 255 PICFILE.C +make_pic_name ; 264 PICFILE.C +dump_apple_iff ; 10 APL2IFF.C +write_line ; 108 APL2IFF.C +do_apple_cvt ; 162 APL2IFF.C +main ; 195 APL2IFF.C +putWORD ; 222 APL2IFF.C +putLONG ; 229 APL2IFF.C +init_palettes ; 100 MAKEAPPL.C +main ; 130 MAKEAPPL.C +writebit ; 184 MAKEAPPL.C +write_short ; 209 MAKEAPPL.C +do_iff_cvt ; 221 MAKEAPPL.C +decom ; 486 MAKEAPPL.C +getWORD ; 523 MAKEAPPL.C +getLONG ; 540 MAKEAPPL.C +getBYTE ; 556 MAKEAPPL.C +generate_apple_ids ; 573 MAKEAPPL.C +get_iff ; 665 MAKEAPPL.C +endit ; 736 MAKEAPPL.C +myseek ; 753 MAKEAPPL.C +apple_bestcol ; 12 PALETTE.C +cvt_bestcol ; 68 PALETTE.C +cvt_inpal ; 91 PALETTE.C +cvt_addnew ; 101 PALETTE.C +addcol ; 115 PALETTE.C +loadpalette_preserve ; 129 PALETTE.C +loadpalette ; 145 PALETTE.C +load_apple_palette ; 163 PALETTE.C diff --git a/apple/yzip/apl2iff/tdconfig.td b/apple/yzip/apl2iff/tdconfig.td new file mode 100644 index 0000000..1e7a16c Binary files /dev/null and b/apple/yzip/apl2iff/tdconfig.td differ diff --git a/apple/yzip/apl2iff/tdd.bat b/apple/yzip/apl2iff/tdd.bat new file mode 100644 index 0000000..027b2eb --- /dev/null +++ b/apple/yzip/apl2iff/tdd.bat @@ -0,0 +1,3 @@ +@rem To debug dd +td -do dd -e 153 35 266 163 lavos.dp2 + diff --git a/apple/yzip/ice/6502test.asm b/apple/yzip/ice/6502test.asm new file mode 100644 index 0000000..9a96b63 --- /dev/null +++ b/apple/yzip/ice/6502test.asm @@ -0,0 +1,313 @@ + xlist ; Turn off listing while setting up printing parameters + page ,80 ; Use default page length, set page width to 80 columns +; + title "HMA6502 test file",'Alphabetical listing of 65C02 mnemonics' + + ifndef pass2 ; Set up local pass counter +pass2 = 0 + else +pass2 = 1 ; pass2 is true on pass 2 + endif + + list +; +; +; Note: Instructions marked with a "[C]" are for CMOS devices only +; +; +n EQU 0020h +w EQU 0584h +z EQU 0005h +; + CSEG +; +first_label: + adc #%100000 ; Add memory to accumulator with carry + ADC z ; (Default to zero page addressing) + ADC w,X ; (Force extended addressing) + ADC w,y + ADC (z) ; [C] + ADC (z,X) + ADC (z),Y + + and #$20 ; "AND" memory with accumulator + AND z + AND z,X + AND w + AND w,X + AND w,Y + AND (z) ; [C] + AND (z,X) + AND (z),Y + + asl a ; Shift left one bit + ASL z + ASL z,X + ASL w + ASL w,X + + bbr 0,z,first_label ; Branch on bit reset [C] + BBR 1,z,first_label ; [C] + BBR 2,z,$ ; [C] + BBR 3,z,* ; [C] + BBR 4,z,$+3 ; [C] + BBR 5,z,*-3 ; [C] + BBR 6,z,destination ; [C] + BBR 7,z,destination ; [C] + + bbs 0,z,destination ; Branch on bit set [C] + BBS 1,z,destination ; [C] + BBS 2,z,* ; [C] + BBS 3,z,$ ; [C] + BBS 4,z,$-3 ; [C] + BBS 5,z,*+3 ; [C] + BBS 6,z,first_label ; [C] + BBS 7,z,first_label ; [C] + + bcc first_label ; Branch on carry clear + + bcs first_label ; Branch on carry set + + beq $ ; Branch on result zero + + bit #20h ; Test bits in memory with accumulator [C] + BIT z + BIT z,X ; [C] + BIT w + BIT w,X ; [C] + + bmi * ; Branch on result minus + + bne $+2 ; Branch on result not zero + + bpl *-2 ; Branch on result plus + + bra 2+* ; Branch always [C] + + brk ; Force break + + bvc destination ; Branch on overflow clear + + bvs destination ; Branch on overflow set + +destination: + + clc ; Clear carry flag + + cld ; Clear decimal mode + + cli ; Clear interrupt disable bit + + clv ; Clear overflow flag + + cmp #100000b ; Compare memory and accumulator + CMP z + CMP z,X + CMP w + CMP w,X + CMP w,Y + CMP (z) ; [C] + CMP (z,X) + CMP (z),Y + + cpx #n ; Compare memory and index X + CPX z + CPX w + + cpy #n ; Compare memory and index Y + CPY z + CPY w + + dec A ; Decrement memory by one [C] + DEC z + DEC z,X + DEC w + DEC w,X + + dex ; Decrement index X by one + + dey ; Decrement index Y by one + + eor #n ; "Exclusive-Or" memory with accumulator + EOR z + EOR z,X + EOR w + EOR w,X + EOR w,Y + EOR (z) ; [C] + EOR (z,X) + EOR (z),Y + + inc A ; Increment memory by one [C] + INC z + INC z,X + INC w + INC w,X + + inx ; Increment index X by one + + iny ; Increment index Y by one + + jmp w ; Jump to new location + JMP (w) + JMP (w,X) ; [C] + + jsr w ; Jump to new location saving return address + + lda #n ; Load accumulator with memory + LDA z + LDA z,X + LDA w + LDA w,X + LDA w,Y + LDA (z) ; [C] + LDA (z,X) + LDA (z),Y + xlist + printx 'Halfway through pass ',pass2 + 1 + list + + ldx #n ; Load index X with memory + LDX z + LDX z,Y + LDX w + LDX w,Y + + ldy #n ; Load index Y with memory + LDY z + LDY z,X + LDY w + LDY w,X + + lsr A ; Shift right one bit + LSR z + LSR z,X + LSR w + LSR w,X + + NOP ; No operation + + ora #n ; "OR" memory with accumulator + ORA z + ORA z,X + ORA w + ORA w,X + ORA w,Y + ORA (z) ; [C] + ORA (z,X) + ORA (z),Y + + pha ; Push accumulator on stack + + php ; Push processor status on stack + + phx ; Push index X on stack [C] + + phy ; Push index Y on stack [C] + + pla ; Pull accumulator from stack + + plp ; Pull processor status from stack + + plx ; Pull index X from stack [C] + + ply ; Pull index Y from stack [C] + + rmb 0,z ; Reset memory bit [C] + RMB 1,z ; [C] + RMB 2,z ; [C] + RMB 3,z ; [C] + RMB 4,z ; [C] + RMB 5,z ; [C] + RMB 6,z ; [C] + RMB 7,z ; [C] + + rol A ; Rotate one bit left + ROL z + ROL z,X + ROL w + ROL w,X + + ror A ; Rotate one bit right + ROR z + ROR z,X + ROR w + ROR w,X + + rti ; Return from interrupt + + rts ; Return from subroutine + + sbc #n ; Subtract memory from accumulator with borrow + SBC z + SBC z,X + SBC w + SBC w,X + SBC w,Y + SBC (z) ; [C] + SBC (z,X) + SBC (z),Y + + sec ; Set carry flag + + sed ; Set decimal mode + + sei ; Set interrupt disable status + + smb 0,z ; Set memory bit [C] + SMB 1,z ; [C] + SMB 2,z ; [C] + SMB 3,z ; [C] + SMB 4,z ; [C] + SMB 5,z ; [C] + SMB 6,z ; [C] + SMB 7,z ; [C] + + sta z ; Store accumulator in memory + STA z,X + STA w + STA w,X + STA w,Y + STA (z) ; [C] + STA (z,X) + STA (z),Y + + stx z ; Store index X in memory + STX z,Y + STX w + + sty z ; Store index Y in memory + STY z,X + STY w + + stz z ; Store zero [C] + STZ z,X ; [C] + STZ w ; [C] + STZ w,X ; [C] + + tax ; Transfer accumulator to index X + + tay ; Transfer accumulator to index Y + + trb z ; Test and reset bits [C] + TRB w ; [C] + + tsb z ; Test and set bits [C] + TSB w ; [C] + + tsx ; Transfer stack pointer to index X + + txa ; Transfer index X to accumulator + + txs ; Transfer index X to stack pointer + + tya ; Transfer index Y to accumulator + +last_label: + END first_label + + xlist + title ,"Symbol Table" + list \ No newline at end of file diff --git a/apple/yzip/ice/6502test.prn b/apple/yzip/ice/6502test.prn new file mode 100644 index 0000000..bb8b4ca --- /dev/null +++ b/apple/yzip/ice/6502test.prn @@ -0,0 +1,462 @@ +Huntsville Macro Assembler 65C02 cross assembler for PC-DOS 2.0 v1.82L Page 1 + +Title: HMA6502 test file Module: 6502TEST + Alphabetical listing of 65C02 mnemonics + + ; + ; + ; Note: Instructions marked with a "[C]" are for CMOS devices on +ly + ; + ; +0020 n EQU 0020h +0584 w EQU 0584h +0005 z EQU 0005h + ; +0000' CSEG + ; +0000' first_label: +0000'6920 adc #%100000 ; Add memory to accumulator with + carry +0002'6505 ADC z ; (Default to zero page +addressing) +0004'7505 ADC w,X ; (Force extended addres +sing) +000C'798405 ADC w,y +000F'7205 ADC (z) ; [C] +0011'6105 ADC (z,X) +0013'7105 ADC (z),Y + +0015'2920 and #$20 ; "AND" memory with accumulator +0017'2505 AND z +0019'3505 AND z,X +001B'2D8405 AND w +001E'3D8405 AND w,X +0021'398405 AND w,Y +0024'3205 AND (z) ; [C] +0026'2105 AND (z,X) +0028'3105 AND (z),Y + +002A'0A asl a ; Shift left one bit +002B'0605 ASL z +002D'1605 ASL z,X +002F'0E8405 ASL w +0032'1E8405 ASL w,X + +0035'0F05C8 bbr 0,z,first_label ; Branch on bit reset [C] +0038'1F05C5 BBR 1,z,first_label ; [C] +003B'2F05FD BBR 2,z,$ ; [C] +003E'3F05FD BBR 3,z,* ; [C] +0041'4F0500 BBR 4,z,$+3 ; [C] +0044'5F05FA BBR 5,z,*-3 ; [C] +0047'6F053A BBR 6,z,destination ; [C] +004A'7F0537 BBR 7,z,destination ; [C] + + + + + + + + + +Huntsville Macro Assembler 65C02 cross assembler for PC-DOS 2.0 v1.82L Page 2 + +Title: HMA6502 test file Module: 6502TEST + Alphabetical listing of 65C02 mnemonics + +004D'8F0534 bbs 0,z,destination ; Branch on bit set [C] +0050'9F0531 BBS 1,z,destination ; [C] +0053'AF05FD BBS 2,z,* ; [C] +0056'BF05FD BBS 3,z,$ ; [C] +0059'CF05FA BBS 4,z,$-3 ; [C] +005C'DF0500 BBS 5,z,*+3 ; [C] +005F'EF059E BBS 6,z,first_label ; [C] +0062'FF059B BBS 7,z,first_label ; [C] + +0065'9099 bcc first_label ; Branch on carry clear + +0067'B097 bcs first_label ; Branch on carry set + +0069'F0FE beq $ ; Branch on result zero + +006B'8920 bit #20h ; Test bits in memory with accum +ulator [C] +006D'2405 BIT z +006F'3405 BIT z,X ; [C] +0071'2C8405 BIT w +0074'3C8405 BIT w,X ; [C] + +0077'30FE bmi * ; Branch on result minus + +0079'D000 bne $+2 ; Branch on result not zero + +007B'10FC bpl *-2 ; Branch on result plus + +007D'8000 bra 2+* ; Branch always [C] + +007F'00 brk ; Force break + +0080'5002 bvc destination ; Branch on overflow clear + +0082'7000 bvs destination ; Branch on overflow set + +0084' destination: + +0084'18 clc ; Clear carry flag + +0085'D8 cld ; Clear decimal mode + +0086'58 cli ; Clear interrupt disable bit + +0087'B8 clv ; Clear overflow flag + +0088'C920 cmp #100000b ; Compare memory and accumulator + +008A'C505 CMP z +008C'D505 CMP z,X +008E'CD8405 CMP w +0091'DD8405 CMP w,X +0094'D98405 CMP w,Y + + + + + + + + +Huntsville Macro Assembler 65C02 cross assembler for PC-DOS 2.0 v1.82L Page 3 + +Title: HMA6502 test file Module: 6502TEST + Alphabetical listing of 65C02 mnemonics + +0097'D205 CMP (z) ; [C] +0099'C105 CMP (z,X) +009B'D105 CMP (z),Y + +009D'E020 cpx #n ; Compare memory and index X +009F'E405 CPX z +00A1'EC8405 CPX w + +00A4'C020 cpy #n ; Compare memory and index Y +00A6'C405 CPY z +00A8'CC8405 CPY w + +00AB'3A dec A ; Decrement memory by one [C] +00AC'C605 DEC z +00AE'D605 DEC z,X +00B0'CE8405 DEC w +00B3'DE8405 DEC w,X + +00B6'CA dex ; Decrement index X by one + +00B7'88 dey ; Decrement index Y by one + +00B8'4920 eor #n ; "Exclusive-Or" memory with acc +umulator +00BA'4505 EOR z +00BC'5505 EOR z,X +00BE'4D8405 EOR w +00C1'5D8405 EOR w,X +00C4'598405 EOR w,Y +00C7'5205 EOR (z) ; [C] +00C9'4105 EOR (z,X) +00CB'5105 EOR (z),Y + +00CD'1A inc A ; Increment memory by one [C] +00CE'E605 INC z +00D0'F605 INC z,X +00D2'EE8405 INC w +00D5'FE8405 INC w,X + +00D8'E8 inx ; Increment index X by one + +00D9'C8 iny ; Increment index Y by one + +00DA'4C8405 jmp w ; Jump to new location +00DD'6C8405 JMP (w) +00E0'7C8405 JMP (w,X) ; [C] + +00E3'208405 jsr w ; Jump to new location saving re +turn address + +00E6'A920 lda #n ; Load accumulator with memory +00E8'A505 LDA z +00EA'B505 LDA z,X + + + + + + + + +Huntsville Macro Assembler 65C02 cross assembler for PC-DOS 2.0 v1.82L Page 4 + +Title: HMA6502 test file Module: 6502TEST + Alphabetical listing of 65C02 mnemonics + +00EC'AD8405 LDA w +00EF'BD8405 LDA w,X +00F2'B98405 LDA w,Y +00F5'B205 LDA (z) ; [C] +00F7'A105 LDA (z,X) +00F9'B105 LDA (z),Y + +00FB'A220 ldx #n ; Load index X with memory +00FD'A605 LDX z +00FF'B605 LDX z,Y +0101'AE8405 LDX w +0104'BE8405 LDX w,Y + +0107'A020 ldy #n ; Load index Y with memory +0109'A405 LDY z +010B'B405 LDY z,X +010D'AC8405 LDY w +0110'BC8405 LDY w,X + +0113'4A lsr A ; Shift right one bit +0114'4605 LSR z +0116'5605 LSR z,X +0118'4E8405 LSR w +011B'5E8405 LSR w,X + +011E'EA NOP ; No operation + +011F'0920 ora #n ; "OR" memory with accumulator +0121'0505 ORA z +0123'1505 ORA z,X +0125'0D8405 ORA w +0128'1D8405 ORA w,X +012B'198405 ORA w,Y +012E'1205 ORA (z) ; [C] +0130'0105 ORA (z,X) +0132'1105 ORA (z),Y + +0134'48 pha ; Push accumulator on stack + +0135'08 php ; Push processor status on stack + + +0136'DA phx ; Push index X on stack [C] + +0137'5A phy ; Push index Y on stack [C] + +0138'68 pla ; Pull accumulator from stack + +0139'28 plp ; Pull processor status from sta +ck + +013A'FA plx ; Pull index X from stack [C] + + + + + + + + + +Huntsville Macro Assembler 65C02 cross assembler for PC-DOS 2.0 v1.82L Page 5 + +Title: HMA6502 test file Module: 6502TEST + Alphabetical listing of 65C02 mnemonics + +013B'7A ply ; Pull index Y from stack [C] + +013C'0705 rmb 0,z ; Reset memory bit [C] +013E'1705 RMB 1,z ; [C] +0140'2705 RMB 2,z ; [C] +0142'3705 RMB 3,z ; [C] +0144'4705 RMB 4,z ; [C] +0146'5705 RMB 5,z ; [C] +0148'6705 RMB 6,z ; [C] +014A'7705 RMB 7,z ; [C] + +014C'2A rol A ; Rotate one bit left +014D'2605 ROL z +014F'3605 ROL z,X +0151'2E8405 ROL w +0154'3E8405 ROL w,X + +0157'6A ror A ; Rotate one bit right +0158'6605 ROR z +015A'7605 ROR z,X +015C'6E8405 ROR w +015F'7E8405 ROR w,X + +0162'40 rti ; Return from interrupt + +0163'60 rts ; Return from subroutine + +0164'E920 sbc #n ; Subtract memory from accumulat +or with borrow +0166'E505 SBC z +0168'F505 SBC z,X +016A'ED8405 SBC w +016D'FD8405 SBC w,X +0170'F98405 SBC w,Y +0173'F205 SBC (z) ; [C] +0175'E105 SBC (z,X) +0177'F105 SBC (z),Y + +0179'38 sec ; Set carry flag + +017A'F8 sed ; Set decimal mode + +017B'78 sei ; Set interrupt disable status + +017C'8705 smb 0,z ; Set memory bit [C] +017E'9705 SMB 1,z ; [C] +0180'A705 SMB 2,z ; [C] +0182'B705 SMB 3,z ; [C] +0184'C705 SMB 4,z ; [C] +0186'D705 SMB 5,z ; [C] +0188'E705 SMB 6,z ; [C] +018A'F705 SMB 7,z ; [C] + + + + + + + + + +Huntsville Macro Assembler 65C02 cross assembler for PC-DOS 2.0 v1.82L Page 6 + +Title: HMA6502 test file Module: 6502TEST + Alphabetical listing of 65C02 mnemonics + +018C'8505 sta z ; Store accumulator in memory +018E'9505 STA z,X +0190'8D8405 STA w +0193'9D8405 STA w,X +0196'998405 STA w,Y +0199'9205 STA (z) ; [C] +019B'8105 STA (z,X) +019D'9105 STA (z),Y + +019F'8605 stx z ; Store index X in memory +01A1'9605 STX z,Y +01A3'8E8405 STX w + +01A6'8405 sty z ; Store index Y in memory +01A8'9405 STY z,X +01AA'8C8405 STY w + +01AD'6405 stz z ; Store zero [C] +01AF'7405 STZ z,X ; [C] +01B1'9C8405 STZ w ; [C] +01B4'9E8405 STZ w,X ; [C] + +01B7'AA tax ; Transfer accumulator to index +X + +01B8'A8 tay ; Transfer accumulator to index +Y + +01B9'1405 trb z ; Test and reset bits [C] +01BB'1C8405 TRB w ; [C] + +01BE'0405 tsb z ; Test and set bits [C] +01C0'0C8405 TSB w ; [C] + +01C3'BA tsx ; Transfer stack pointer to inde +x X + +01C4'8A txa ; Transfer index X to accumulato +r + +01C5'9A txs ; Transfer index X to stack poin +ter + +01C6'98 tya ; Transfer index Y to accumulato +r + +01C7' last_label: +01C7' END first_label + + + 0 errors + + + + + + + + + + +Huntsville Macro Assembler 65C02 cross assembler for PC-DOS 2.0 v1.82L Page 7 + +Title: HMA6502 test file Module: 6502TEST + Symbol Table + +C 0084 destination C 0000 first_label C 01C7 last_label + 0020 n 0001 pass2 0584 w + 0005 z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apple/yzip/ice/apple.equ b/apple/yzip/ice/apple.equ new file mode 100644 index 0000000..3fd5163 --- /dev/null +++ b/apple/yzip/ice/apple.equ @@ -0,0 +1,283 @@ + TITLE "Apple ][ YZIP (c)Infocom","APPLE ][ HARDWARE STUFF" + PAGE +; ------------------- +; APPLE II MEMORY MAP +; ------------------- + +; +; some hardware spots +; +SCREEN EQU $2000 ; START OF Double HiRes SCREEN RAM + +PRGLBL EQU $BF00 ; ProDOS Globals page in main mem +PR_BITMAP EQU $BF58 ; ProDOS system bitmap +KVERSION EQU $BFFF ; ProDOS version (== $FF if InfoDOS) +INFODOS_ID EQU $FF + +IOADDR EQU $C000 ; start of I/O registers +PROADR EQU $D000 ; start of ProDOS + +LBUFF EQU $0200 ; LINE INPUT BUFFER +PIC1BUF EQU LBUFF ; we can use line buffer for one picture buffer +SCRBUFF EQU LBUFF+$80 ; screen line buffer +BORG EQU $2000 ; ORIGIN OF .SYSTEM CODE +; +; some page 3 storage relocated stuff +; +PAGE3STUFF EQU $300 +MOUSER EQU PAGE3STUFF ; this is where mouse subroutine goes +COLORS EQU MOUSER+$12 +XPOSTBL EQU COLORS+$40 + +SV_PCL EQU $400 ; for scrolling data +SV_PCH EQU $600 + +IOBUFF EQU $0800 ; 1Kb DATA BUFFER BUFFER + +PAGING_MEM EQU IOBUFF+$400 ; Paging table stuff +NEXTPNT EQU PAGING_MEM +PREVPNT EQU NEXTPNT+$40 +VPAGEH EQU PREVPNT+$40 +VPAGEL EQU VPAGEH+$40 +PAGELEN EQU $200 ; length of paged read + +ZSTKBL EQU PAGING_MEM+$100 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) +ZSTKTL EQU ZSTKBL+$100 ; TOP, LO +ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI +ZSTKTH EQU ZSTKBL+$300 ; TOP, HI +; +; now define some file i/o buffers and such +; +GAME1FIO EQU ZSTKBL+$400 ; Game file I/O buffer +GAME2FIO EQU GAME1FIO+$400 ; Second game file i/o buffer +SEGTBL EQU GAME2FIO+$400 ; segment table for multi disks +PIC2BUF EQU SEGTBL+($400-140) ; picture buffer is 140 bytes long +TCHARTBL EQU SEGTBL+$400 ; 208 bytes for (possible) terminating +COPY_LINE EQU TCHARTBL+$60 ; copy line in screen memory +DSKSEG EQU TCHARTBL+$D0 ; spot to stash pointers for disk segments +D1SEG EQU DSKSEG ; where in SEGTBL for Disk 1 +D2SEG EQU D1SEG+2 +D3SEG EQU D2SEG+2 +D4SEG EQU D3SEG+2 +D5SEG EQU D4SEG+2 +D6SEG EQU D5SEG+2 +D7SEG EQU D6SEG+2 +D8SEG EQU D7SEG+2 +LOCAL_SV EQU TCHARTBL+$E0 ; to save locals before restore +LOCALS EQU TCHARTBL+$100 ; LOCAL VARIABLE STORAGE (30 BYTES) +BUFSAV EQU LOCALS+$20 ; TEMP SPACE FOR SAVE/RESTORE (80 BYTES) +SCR_LINE EQU LOCALS+$100 ; place to build displayed line +; +; now for some interpreter data +; +INTR_BEGIN EQU $4000 ; START OF Interpreter CODE in main +INTR_SIZE EQU (41*512) ; size of interpreter + +ZBEGIN EQU (INTR_BEGIN+INTR_SIZE) ; start of Z code +MMSIZE EQU PRGLBL-INTR_BEGIN ; free memory in main bank +Z1SIZE EQU HIGH(PRGLBL-ZBEGIN) ; size of preload, part 1 +; +; this is in Bank 2, Main mem +; +; +; Picture directory goes in Bank 2, Aux mem +; +PIC_DIR EQU $D000 ; picture local directory + +; +; some special markers if we are using InfoDOS +; +SP_START EQU $D000 ; start of special area +SP_SIZE EQU ((($FF-(SP_START>>8))*256)/512) ; how many pages + +PBEGIN EQU $0800 ; start of paging buffers, in aux mem +NUMBUFS EQU HIGH(SCREEN-PBEGIN) ; how many 256k paging buffers + +P2PAGE EQU HIGH(PRGLBL-ZBEGIN) ; first page of zcode in aux bank +Z2BEGIN EQU $4000 ; start of part 2 in aux mem + ; just after the dhires screen +Z2PAGE EQU HIGH Z2BEGIN ; get me just the page address +Z2SIZE EQU HIGH (PRGLBL-Z2BEGIN) ; size of preload, part 2 +P3PAGE EQU Z1SIZE+Z2SIZE ; first page in aux mem part 3 +Z3BEGIN EQU $D000 ; start of 3 part in aux mem +Z3PAGE EQU HIGH Z3BEGIN ; get me page number too +Z3SIZE EQU LOW ($100-Z3PAGE) ; size of part 3, in pages + +; +; other numba's +; +PGBEGIN EQU (P3PAGE+Z3SIZE) ; first paged page +PRESIZE EQU (Z1SIZE+Z2SIZE+Z3SIZE) ; size of preload, # pages +SCRSZE EQU INTR_BEGIN-SCREEN ; size of Double HiRes screen (8k, each bank) +RAMDSK EQU (119*512) ; size of RAM disk in aux mem +RAMSAVE EQU $B500 ; save this much to cover HiRes screen in + ; aux and the rest of the preload, up to + ; PRGLBL ($bf00) +FREERAM EQU RAMDSK-RAMSAVE ; size of Free RAM after 'saving' + ; special AUX memory +DSKSZE EQU (512*273) ; size of ProDOS data disk file + +; --------- +; CONSTANTS +; --------- + +IIeID EQU 2 ; Apple ][e Yzip +IIcID EQU 9 ; ][c Yzip +IIgsID EQU 10 ; ][gs Yzip + +P3BANK EQU $FF ; show upper aux mem +AUX EQU 1 ; offset to Auxillary mem switches +MAIN EQU 0 ; for main memory switches + +LO EQU 0 +HI EQU 1 +ABANK EQU 2 ; for address variables + +OFF EQU 0 ; for toggling soft-switches +ON EQU 1 + +EOL EQU $0D ; EOL CHAR +LF EQU $0A ; LINE FEED +SPACE EQU $20 ; SPACE CHAR +BACKSPACE EQU $08 ; BACKSPACE CHAR +ESCAPE EQU $1B ; ESCAPE Key +VOLCHAR EQU '?' ; Key to hit for ONLINE command +; +; Screen Defs +; +MAXWIDTH EQU 140 ; 560 / 4 = max "pixels" +REAL_MAXW EQU MAXWIDTH*4 +MAXHEIGHT EQU 192 ; 192 screen lines +FONT_W EQU 2 ; font width (for game, anyway) +FONT_H EQU 9 ; font height +MFONT_W EQU 3 ; mono spaced font width, to game +MONOFONT_W EQU MFONT_W*4 ; how wide the mono font really is + +SPACE_WIDTH EQU 8 ; default space width +BLINK_RATE EQU 3 ; tenths of seconds between blinks + +OUTER_DELAY EQU $1C ; outside delay loop counter +INNER_DELAY EQU 3 ; inner delay loop + +GS_OUTER_DELAY EQU $72 ; ][gs outside counter +GS_INNER_DELAY EQU 2 ; ][gs inside counter + +; ---------------------- +; BOOT ZERO PAGE EQUATES +; ---------------------- + +BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS +BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT + +; ---------------- +; HARDWARE EQUATES +; ---------------- + +KBD EQU $C000 ; KEY STROBE +STORE80 EQU $C000 ; video aux mem switch +RDBNK EQU $C002 ; READ MAIN MEMORY (+MAIN, +AUX) +WRTBNK EQU $C004 ; WRITE MAIN 48K OF MEMORY (+MAIN, +AUX) +ALTZP EQU $C008 ; R/W MAIN (C009 = AUX) >MEM +COL80SW EQU $C00C ; 80 Column switch +ANYKEY EQU $C010 ; ANY KEY DOWN FLAG +VERTBLNK EQU $C019 ; Vertical Blanking Flag +IIGSVID EQU $C029 ; GS MEGA ][ video register +SPKR EQU $C030 ; SPEAKER FLAG (MAKE A NOISE) +IIGSSHD EQU $C035 ; ][GS shadowing reg +TEXTSW EQU $C050 ; Graphics Switch +MIXEDSW EQU $C052 ; Mixed Text/Graphics +PAGE2SW EQU $C054 ; Page select +HIRESSW EQU $C056 ; Select HiRes +DHIRESW EQU $C05E ; Double HiRes switch (backwards: +0 on +1 off) +IOUDIS EQU $C07E ; Double HiRes Switch enabler (same backass way) +BNK2SET EQU $C083 ;READ/READ READ RAM WRITE RAM BANK 2 +BNK1SET EQU $C08B ;READ/READ READ RAM WRITE RAM BANK 1 +RDROM EQU $C082 ; READ READ ROM NO WRITE +RDBNK1 EQU $C088 ; READ ram, bank 1 +RDBNK2 EQU $C080 ; Read ram, bank 2 + +; ----------------- +; MONITOR VARIABLES +; ----------------- + +CSW EQU $36 ; CHARACTER OUTPUT VECTOR (for scripting) +RNUM1 EQU $4e ; random numbers to be used +RNUM2 EQU $4f +APKEY1 EQU $C061 ; open apple key flag +APKEY2 EQU $C062 ; closed apple key flag +; ----------- +; MOUSE STUFF +; ----------- +MTABLE EQU $C412 ; Mouse ROM table +MSVECTOR EQU MOUSER+16 ; where vector is stored +MSMOVEF EQU MSVECTOR+2 ; Mouse moved flag +MSBTNF EQU MSMOVEF+1 ; Mouse button flag +; +; MOUSE screen holes +; +CLMPMINL EQU $478 ; lo part of clamping min +CLMPMINH EQU $578 ; hi part of " " +CLMPMAXL EQU $4F8 ; lo part of clamping max +CLMPMAXH EQU $5F8 ; hi part of " " +MOUSEXL EQU $478 ; lo part of mouse X +MOUSEXH EQU $578 ; hi part of mouse X +MOUSEYL EQU $4F8 ; lo part of mouse Y +MOUSEYH EQU $5F8 ; hi part of mouse Y +MOUSEST EQU $778 ; status byte +; +; some mouse constants +; +SGL_CLK EQU $81 ; single click char +DBL_CLK EQU $82 ; double click char +CLK_CNT EQU -4 ; counts between single and double click +; Subroutine offsets +SETM EQU 0 +SERVEM EQU 1 +READM EQU 2 +CLEARM EQU 3 +POSM EQU 4 +CLAMPM EQU 5 +HOMEM EQU 6 +INITM EQU 7 + +; -------------- +; PRODOS GLOBALS +; -------------- +PRODATE EQU $BF90 ; date and +PROTIME EQU $BF92 ; time +MACHID EQU $BF98 ; machine id + +; ---------------- +; MONITOR ROUTINES +; ---------------- +MPREAD EQU $FB1E ; Read for joystick control +MBASCAL EQU $FC22 ; CALC LINE BASE ADDRESS +MBELL EQU $FF3A ; MAKE A NOISE +RESET_VECTOR EQU $FFFC ; force warm reboot +MCLEOL EQU $FC9C ; CLEAR TO END OF LINE +MCLEOS EQU $FC42 ; CLEAR TO END OF SCREEN +MHOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR +MCOUT EQU $FDED ; CHAR OUTPUT +MCOUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN +MRDKEY EQU $FD0C ; READ KEY +MGETLN1 EQU $FD6F ; GET LINE +MWAIT EQU $FCA8 ; WASTE SO MUCH TIME +; +; Some /RAM spots +; +RAMVEC EQU $BF26 ; /RAM drive vector +OLDVEC EQU $77E ; spot to save the drive vector +UNSVEC EQU $BF16 ; "Uninstalled Device" vector +DEVCNT EQU $BF31 ; Device count +DEVNUM EQU $BF32 ; Device list + +; +; machine info spots +; +MACHID1 EQU $FBB3 ; first part +MACHID2 EQU $FBC0 ; second part +MACHCHK EQU $FE1F ; differentiate between ][e and gs + ; do sec, then jsr, and if still set, = ][e + END + + diff --git a/apple/yzip/ice/boot.asm b/apple/yzip/ice/boot.asm new file mode 100644 index 0000000..199a6ba --- /dev/null +++ b/apple/yzip/ice/boot.asm @@ -0,0 +1,351 @@ + TITLE "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + + INCLUDE "ZIP.EQU" + INCLUDE "ZERO.EQU" + INCLUDE "PRODOS.EQU" + INCLUDE "APPLE.EQU" + INCLUDE "MACROS.ASM" + + TITLE "Apple ][ YZIP (c)Infocom","APPLE ProDOS BOOT CODE" + PAGE + +CHZ EQU $24 ; CURSOR HORIZONTAL +CVT EQU $25 ; CURSOR VERTICAL + +; +; my own little error checking macro +; +ERRVAL = 0 +; +; this macros checks for carry being set (ProDOS error) and if it is +; loads an error code in x and jumps to the error handler +ERRCHK MACRO +ERRVAL = ERRVAL+1 + bcc BOOT.ERRVAL. + ldy \#.ERRVAL. + jmp BOOT_ERROR +BOOT.ERRVAL.: + ENDM + + ORG BORG + jmp BOOT_BEGIN ; just jump to beginning +PROGNAME: + db 0,0,0,0,0,0,0,0,0 ; 8 bytes for name + 1 for ending zero +BOOT_BEGIN: + sta TEXTSW+ON ; turn on text + sta COL80SW+OFF ; turn on 80 column + lda IIGSVID ; get current video setting + and #$1F ; turn off upper 3 bits + sta IIGSVID ; make sure double hires works + lda IIGSSHD ; get shadowing reg + and #$A0 ; turn on shadowing everywhere + sta IIGSSHD ; okay +; +; make sure we are on a ][c, or ][e+ +; + jsr MACHINE ; check it out, returns if good + jsr FIXRAM ; check and clear RAM disk + + jsr MHOME ; clear and home + lda #10 ; CENTER DISPLAY + sta CVT + lda #8 + sta CHZ + jsr MBASCAL ; move cursor there! + DLINE STRYM +; +; move down to lower left and print out version number +; + lda #20 + sta CVT + lda #1 + sta CHZ ; move to 1,20 + jsr MBASCAL ; move cursor there! + lda #VERSID/10 ; get version + ora #$B0 ; make normal char for ][ + jsr MCOUT + lda #VERSID%10 + ora #$B0 ; make normal char for ][ + jsr MCOUT + + lda #$FF ; init invflg to normal + sta INVFLG ; okay + + lda #0 ; zero out bit map + ldx #$17 ; 17 bytes in ProDOS system bitmap +CLRPRD: + sta PR_BITMAP,X ; and zero out the memory + dex + bpl CLRPRD ; and zero entire bitmap + + lda #$C0 ; start out the bitmap with c0 at start + sta PR_BITMAP + lda #$01 ; and a 1 at the end + sta PR_BITMAP+$17 ; thankx +; +; now we need to load in the interpreter +; + OPEN INTR_OPEN ; open up interpreter file + ERRCHK + + lda INTR_OPEN+OP_REFNUM ; get refnum for intr file + sta RD_BLOCK+RD_REFNUM ; and save for read + sta CLOSE_BLOCK+CL_REFNUM ; close up interpreter file + + READ RD_BLOCK ; read in interpreter + ERRCHK + + CLOSE CLOSE_BLOCK ; done with interpreter +; +; now read in first part of preload +; + ldx #0 ; start at first letter +MVPRE: + lda PROGNAME,X ; get letter + beq MVPREX ; all done + sta PRE_NAME,X ; save letter + inx ; next letter + bne MVPRE ; do gen +MVPREX: +; +; now add on ".d0" suffix for the preload +; + lda #'.' ; get '.' + sta PRE_NAME,X ; save it + inx ; next char + lda #'D' ; 'D' char + sta PRE_NAME,X ; save it + inx ; next char + lda #'1' ; preload is .1 + sta PRE_NAME,X ; saved + inx ; count the .1 + stx PRELOAD_NAME ; save length of name + + OPEN PRELOAD_OPEN ; so now open preload file + ERRCHK + + lda PRELOAD_OPEN+OP_REFNUM ; get refnum + sta RD_BLOCK+RD_REFNUM ; save refnum for read + sta PSEEK+SM_REFNUM ; and for moving around +; +; first, get the segment table +; + lda #HIGH IOBUFF ; just read in size + sta RD_BLOCK+RD_BUFFER+HI ; and where to begin next read + lda #4 ; read in first 1 Kb + sta RD_BLOCK+RD_BUFFLEN+HI ; to show how much to read + lda #0 ; get size in words + sta RD_BLOCK+RD_BUFFLEN+LO ; to show how much to read + + READ RD_BLOCK ; and read first block + ERRCHK +; +; now copy segtable to low mem +; + lda #HIGH IOBUFF + sta J+HI + lda #LOW IOBUFF + sta J+LO + lda #HIGH (SEGTBL-2) + sta K+HI + lda #LOW (SEGTBL-2) + sta K+LO + + lda IOBUFF ; get how many words + asl A ; *2 for number of bytes + sta PSEEK+SM_FPOS+HI ; set page number + tax ; make it a counter + ldy #2 ; start at second byte, after length +CPSEGT: + lda (J),y ; get byte + sta (K),y ; save byte + iny ; next byte + bne CPSEGT ; go do it + inc J+HI + inc K+HI + ldy #0 ; restart at beginning of block + dex ; count page + bpl CPSEGT ; next page +; +; now, seek to page following seg table +; + inc PSEEK+SM_FPOS+HI ; next page + lda PSEEK+SM_FPOS+HI ; make sure it is an even 512 page + and #$01 ; is it odd? + beq BTSK0 ; nope, so we be okay + inc PSEEK+SM_FPOS+HI ; next page +BTSK0: + SET_MARK PSEEK ; and point to beginning of game data + + lda #HIGH ZBEGIN ; begining of game code + sta RD_BLOCK+RD_BUFFER+HI ; and where to begin next read + lda #(Z1SIZE&$FE) ; get size + sta RD_BLOCK+RD_BUFFLEN+HI ; to show how much to read + lda #0 ; get size in words + sta RD_BLOCK+RD_BUFFLEN+LO ; to show how much to read + READ RD_BLOCK ; and read in part 1 of preload + ERRCHK + + lda #4 ; 4 pages per read + sta RD_BLOCK+RD_BUFFLEN+HI ; and lots + lda #HIGH IOBUFF ; read into my io buffer + sta RD_BLOCK+RD_BUFFER+HI ; hi part of address + + IF Z1SIZE & 1 ; if odd, do something special + READ RD_BLOCK + ldy #0 ; copy second page +C2LOOP: + lda IOBUFF,y + sta ZBEGIN+(Z1SIZE*$100)-$100,y + iny + bne C2LOOP + lda #(Z2BEGIN>>8)-1 ; don't need first block + sta MODOP+2 + bne RD10 ; skip that first read + ENDIF + +AUXRDL: + READ RD_BLOCK ; and do the read + bcc RD10 + cmp #$4C ; this just means EOF already + beq BT12 ; otherwise, blech + ERRCHK +RD10: + lda #HIGH IOBUFF ; read into my io buffer + sta CLOOP+2 ; start at IOBUFF + lda #4 ; 4 copies + sta L ; okay +RD11: + ldy #0 ; start at zero, of course + lda MODOP+2 ; check where we are reading too + beq BT12 ; wrapped, so we had better be done + cmp #HIGH PRGLBL ; done with aux mem, part 1? + bcc LOOPST ; nope + bne RD12 ; no need to change + lda #Z3PAGE ; restart at top of memory + sta MODOP+2 ; and do some self modifying code +RD12: + sta ALTZP+AUX ; turn on alt ZP + lda BNK2SET ; write to upper mem + lda BNK2SET ; write to upper mem +LOOPST: + sta WRTBNK+AUX ; always aux mem +CLOOP: + lda IOBUFF,Y ; get char +MODOP: sta Z2BEGIN,Y ; save + iny ; point to next one + bne CLOOP ; get next one + + lda RDROM ; swap back rom, just in case + lda RDROM ; swap back rom, just in case + sta ALTZP+MAIN ; and back to main page + sta WRTBNK+MAIN ; read into main bank + + inc MODOP+2 ; point to next page + inc CLOOP+2 ; point to next page + dec L ; next page + bne RD11 ; and get it + + jmp AUXRDL ; get next 1k +BT12: + lda RD_BLOCK+RD_REFNUM ; get refnum for + sta CLOSE_BLOCK+CL_REFNUM ; closing the file + CLOSE CLOSE_BLOCK ; okay, closed +; +; relocate the Zero Page routines +; + ldx #RLCLEN ; length of routine +RLOC: + lda FETCHBx,X ; get byte + sta ZERO_FB,X ; save byte + dex ; get next one + bpl RLOC ; thank you +; +; and now for the copying screen line sub +; + ldx #CPYLEN +CPYCPLP: + lda CPYx,X + sta COPY_LINE,X + dex + bpl CPYCPLP +; +; now relocate page 3 stuff +; + ldx #PAGE3RELL+1 ; get length of page 3 stuff +MSRCL: + lda PAGE3REL-1,X ; get byte + sta PAGE3STUFF-1,X ; save byte + dex ; count byte + bne MSRCL ; get next? + + jsr ZBOOT ; set up ZIP stuff + + JMP INTR_BEGIN ; jump to the interpreter + + INCLUDE "ZBOOT.ASM" ; ZBOOT subroutine + INCLUDE "BREL.ASM" ; relocated subroutines + INCLUDE "BSUBS.ASM" ; subs for me to use + + PAGE + TITLE "Apple ][ YZIP (c)Infocom","--- BOOT DATA STRUCTURES ---" +INTR_OPEN: + DB 3 ; 3 parameters + DW INTR_NAME ; name of file + DW GAME1FIO ; file data buffer + DS 1 ; refnum goes here +CLOSE_BLOCK: + DB 1 ; 1 parameter + DS 2 ; room for ref num +PSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +PRELOAD_OPEN: + DB 3 + DW PRELOAD_NAME + DW GAME1FIO ; close interpreter first! + DS 1 ; refnum here +; +; start with interpreter data +; +RD_BLOCK: + DB 4 ; 4 parms + DB 0 ; refnum + DW INTR_BEGIN ; where to start the interpreter + DW INTR_SIZE ; and how big could it be + DW 0 ; actual length of interpreter +INTR_NAME: + DB INAME_LEN ; length of name +I_NAME: + DB "INFOCOM" ; interpreter name +INAME_LEN EQU $-I_NAME + +PRELOAD_NAME: + DB 0 ; length of name +PRE_NAME: + DS 20 ; spot for preload name +PRELEN EQU $-PRE_NAME + +DH_SAVE: ; to actual 'write' the data + DB 4 ; 4 parms for write + DB 0 ; refnum goes here + DW 0 ; just 'copy' junk + DW RAMSAVE ; to preserve this much mem in AUX + DW 0 ; how much is done + +STRYM: DB "The story is loading ..." +STRYML EQU $-STRYM +MMSG: DB EOL,"Enter the letter of the pointing",EOL + DB "device you will be using:",EOL + DB "J)oystick M)ouse N)either",EOL,EOL +MMSGL EQU $-MMSG +MSLT: DB EOL,"Enter the slot number in which the",EOL + db "mouse card is installed >" +MSLTL EQU $-MSLT +MSLTBAD: DB EOL,"Slot number must be between",EOL + db "ONE and SEVEN! Try again!",EOL +MSLTBADL EQU $-MSLTBAD + + END + diff --git a/apple/yzip/ice/brel.asm b/apple/yzip/ice/brel.asm new file mode 100644 index 0000000..10a0f7e --- /dev/null +++ b/apple/yzip/ice/brel.asm @@ -0,0 +1,188 @@ + TITLE "Apple ][ YZIP (c)Infocom","RELOCATED SUBROUTINES" +; +; FETCHB - use FPC to get a byte in either aux or main mem +; +FETCHBx: + sta RDBNK,Y ; set bank, lower + ldy #0 ; gotta use Y + lda (FPC),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; and return +; +; ZFETCH - fetch byte at (ZPCPNT),Y - offset from (ZPCPNT) +; +ZFETCHx: + sta RDBNK,X ; set lower bank + lda (ZPCPNT),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; bye +; +; MFETCH - fetch byte at (MPCPNT),Y - offset from (MPCPNT) +; +MFETCHx: + sta RDBNK,X ; set bank + lda (MPCPNT),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; bye +; +; SAVE_DATA - copy data from [DBUFF] to IOBUFF +; [Y] must == 0; [X] == DSKBNK; [A] == IOBUFF ($8 or $9) +; + sta RDBNK,X ; and select that bank for reading + sta SAVE_DATA+9 ; show which part of iobuff +SDAT1: + lda (DBUFF),Y ; get me that byte +SDAT2: + sta IOBUFF,Y ; MODIFIED ABOVE + iny + bne SDAT1 + sta RDBNK+MAIN ; and back to main + rts +RLCLEN EQU $-FETCHBx-1 ; mark length +; +; Copy Line +; SPC - source pointer +; FPC - destination pointer +; SPCBNK - bank the above two are talking about +; LASTL - byte number of ending byte +; LASTBNK - bank of ending byte +; STMASK - mask to use on first byte (0 if none) +; ENDMASK - mask to use for end byte (0 if none) +CPYx EQU * + + ldx SPCBNK ; set up banks for first byte + sta PAGE2SW,X ; r/w which bank in display mem + + ldy #0 ; use Y reg + lda STMASK ; get start mask + beq CPLOOP ; no start mask, start in middle of loop + and (FPC),Y ; turn off changing bits, keep good bits + sta (FPC),Y ; save it + lda STMASK ; get changing bits + eor #$FF ; turn on changing bits + and (SPC),Y ; get SPC byte + ora (FPC),Y ; turn them on in destination too + sta (FPC),Y ; and destiny +CPLOOP: + lda CPY_COUNT ; get count + lsr A ; /2 for number in this bank +; adc #0 ; pick up carry if there + tax ; put in X for indexing + beq CPLP2 ; then done! + lda STMASK ; special start? + beq CPL1 ; nope + iny ; first one already done +; dex ; okay, fine +CPL1: + lda (SPC),Y ; get byte + sta (FPC),Y ; store byte + iny ; next byte + dex ; count down + bne CPL1 ; and do it all again +CPLP2: + ldy #0 ; reset y + lda SPCBNK ; get current bank + eor #1 ; toggle to point to the other one + tax + sta PAGE2SW,X + beq CPLP21 ; we are now in main, things are fine + iny ; start one more if now in AUX +CPLP21: + lda CPY_COUNT ; get count again + lsr A ; /2 for bytes in this bank + tax ; put in X for counter + beq CPDONE ; nothing here +CPLP2L: + lda (SPC),Y ; get byte + sta (FPC),Y ; store byte + iny ; next byte + dex ; count byte + bne CPLP2L ; and swing by again +CPDONE: + lda ENDMASK ; do same mucking as when starting + beq CPEXIT ; no mucking + pha ; save endmask + lda CPY_COUNT ; get how many bytes being copied + and #1 ; odd or even? + bne CPDONE1 ; if odd, then we are pointing to correct + ldx SPCBNK ; get original bank + sta PAGE2SW,X ; and point to it +CPDONE1: + pla ; get end mask back + eor #$FF ; turn on all off bits + and (FPC),Y ; turn off changing bits + sta (FPC),Y ; save it + lda (SPC),Y ; get SPC byte + and ENDMASK ; turn on changing bits + ora (FPC),Y ; turn them on in destination too + sta (FPC),Y ; and destiny +CPEXIT: + sta PAGE2SW ; set back to main mem + rts +CPYLEN EQU $-CPYx-1 +PAGE3REL: +; +; MOUSER - this vectors the call to the correct place +; +MOUSERx: + pha ; save A for a sec +MSX1: lda MTABLE,X ; get lo part of address + sta MSVECTOR+LO ; save lo part of address + pla ; get A back + nop +MSX2: ldx #$C4 ; might be changed, depending on slot +MSX3: ldy #$40 ; hopefully, this doesn't + jmp (MSVECTOR) ; and away we go +MSRxLEN EQU $-MOUSERx-1 ; show how long this is +MSVECTORx: + ds 1 ; where lo part of vector goes +MSX4: db $C4 ; slot where mouse is +MSRLEN EQU $-MOUSERx-1 ; length or routine +; +; colors for screen lines +; + RADIX 16d +COLORSx: + db $00,$00,$00,$00 ; black + db $08,$11,$22,$44 ; magenta + db $44,$08,$11,$22 ; brown + db $4C,$19,$33,$66 ; orange + db $22,$44,$08,$11 ; dark green + db $2A,$55,$2A,$55 ; gray 1 + db $66,$4C,$19,$33 ; green + db $6E,$5D,$3B,$77 ; yellow + db $11,$22,$44,$08 ; dark blue + db $19,$33,$66,$4C ; purple + db $55,$2A,$55,$2A ; gray 2 + db $5D,$3B,$77,$6E ; pink + db $33,$66,$4C,$19 ; medium blue + db $3B,$77,$6E,$5D ; light blue + db $77,$6E,$5D,$3B ; aqua + db $7F,$7F,$7F,$7F ; white +XPOSTBLx: + DB 0 + DB 0,1,1,2,2,3,4 + DB 4,5,5,6,6,7,8 + DB 8,9,9,$0a,$0a,$0b,$0c + DB $0c,$0d,$0d,$0e,$0e,$0f,$10 + DB $10,$11,$11,$12,$12,$13,$14 + DB $14,$15,$15,$16,$16,$17,$18 + DB $18,$19,$19,$1a,$1a,$1b,$1c + DB $1c,$1d,$1d,$1e,$1e,$1f,$20 + DB $20,$21,$21,$22,$22,$23,$24 + DB $24,$25,$25,$26,$26,$27,$28 + DB $28,$29,$29,$2a,$2a,$2b,$2c + DB $2c,$2d,$2d,$2e,$2e,$2f,$30 + DB $30,$31,$31,$32,$32,$33,$34 + DB $34,$35,$35,$36,$36,$37,$38 + DB $38,$39,$39,$3a,$3a,$3b,$3c + DB $3c,$3d,$3d,$3e,$3e,$3f,$40 + DB $40,$41,$41,$42,$42,$43,$44 + DB $44,$45,$45,$46,$46,$47,$48 + DB $48,$49,$49,$4a,$4a,$4b,$4c + DB $4c,$4d,$4d,$4e,$4e,$4f,$50 + RADIX 10d +PAGE3RELL EQU $-PAGE3REL-1 + END + + diff --git a/apple/yzip/ice/bsubs.asm b/apple/yzip/ice/bsubs.asm new file mode 100644 index 0000000..abba11d --- /dev/null +++ b/apple/yzip/ice/bsubs.asm @@ -0,0 +1,501 @@ + TITLE "Apple ][ YZIP (c)Infocom","BOOT CODE SUBROUTINES" + +ERRM: DB EOL,EOL + DB "Internal error " +ENUMB: DB "00" + DB "00. " +ERRML EQU $-ERRM +HCHARS: DB "0123456789ABCDEF" +; +; ZERROR: print out error code in HexWord: [A][Y]. +; +ZERROR: + pha ; save [A] + tya ; and put y to a for figgering + ldy #3 ; CONVERT ERROR BYTE IN [A] +ZERR0: + pha + and #%00001111 + tax + lda HCHARS,X + sta ENUMB,Y + pla + LSR A + LSR A + lsr A + lsr A + tax + lda HCHARS,X + dey + sta ENUMB,Y + beq ZR1 ; done + + pla ; done with first number + dey ; and point one more down + jmp ZERR0 ; so work on second number +ZR1: + ldx # LOW ERRM + lda # HIGH ERRM + ldy #ERRML + jsr DISPLAY_LINE ; PRINT ERROR MESSAGE + jsr GETRET ; wait for + jmp ZQUIT + +RETQ: db EOL,"Please insert new disk to boot." + db EOL, "And hit RETURN when ready.",EOL +RETQL EQU $-RETQ +GETRET: + DLINE RETQ, ; ask for return +GETRETL: + lda KBD ; get a key + bpl GETRETL ; no key + and #$7f ; make a good key + cmp #EOL ; return key? + bne GETRETL ; nope + jsr MCOUT ; show the + rts + + + ; ---- + ; QUIT + ; ---- + +ZQUIT: +; +; re-enable /RAM +; + ldx DEVCNT ; put device in at end + inx ; point to one past end + stx DEVCNT ; show new count + lda #$BF ; /RAM ID + sta DEVNUM,X ; save it + lda OLDVEC+HI ; restore old vector + sta RAMVEC+HI + lda OLDVEC+LO + sta RAMVEC+LO +; +; now format /RAM +; + lda #3 ; stash into FORMAT parm block + sta $42 ; it goes here, oddly enough + lda #$B0 ; device id for /RAM + sta $43 ; and here it goes + lda # HIGH GAME1FIO ; IO buffer + sta $45 ; this is where it goes + lda # LOW GAME1FIO ; lsb + sta $44 + sta RDBNK2 ; set up card for driver + jsr RAMDRV ; format /RAM + sta RDROM ; get ROM back + sta RDROM ; get ROM back + + sta TEXTSW+ON ; turn on text + QUIT QUIT_PB +QUIT_PB: + db 4 ; 4 parms + db 0,0,0,0,0,0 ; just zeros +RAMDRV: + jmp (RAMVEC) ; goto RAM driver + +; +; Jump here when ProDOS has a problem +; +; [A] - ProDOS error +; [Y] - my error code +; +BOOT_ERROR: + JMP ZERROR ; just use error routine +; +; Make sure we are on a good machine, like a ][c or ][e+/][gs +; +MACHINE: + lda MACHID1 ; Machine ID part 1 + cmp #6 ; must be a 6 for me to be interested + bne BADMACH ; nope + lda MACHID2 ; Machine ID part 2 + bne MACH1 ; must be a ][e or ][gs + lda #IIcID ; Apple ][c thank you + jmp MACH2 ; and save it +MACH1: + sec ; get ready to check machine + jsr MACHCHK ; check for 'new' machine + bcs OLDMACH ; must just be a ][e + lda #IIgsID ; this is a ][gs + bne MACH2 ; done +OLDMACH: + lda #IIeID ; this is IIe +MACH2: + sta MID ; save machine id + rts +BADMACH: + lda #30 ; bad machine error + ldy #$FF ; nothing here + jmp ZERROR ; and end it all + +; ----------------------- +; DIRECT PRINT LINE [X/A] +; ----------------------- +; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB) +; STRING LENGTH IN [Y] + +DISPLAY_LINE: STX STRING+LO ; DROP STRING ADDRESS + STA STRING+HI ; INTO DUMMY BYTES + STY J ; COUNTER + LDX #0 ; INIT CHAR-FETCH INDEX +DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE +STRING: DW $0000 ; DUMMY OPERAND BYTES + ORA #%10000000 ; ELSE MAKE IT NORMAL +DOUT1: JSR MCOUT + INX + DEC J ; LOOP TILL + BNE DOUT ; OUT OF CHARS + RTS +; +; set [A](page), [Y](bank) to point to memory page where page in [A] is +; +SETPC: + sta MEMPAGE ; save it for later addition + cmp #P2PAGE ; IS IT A PAGE IN MAIN + bcs VF2 ; No, it might be in aux mem + + lda # HIGH ZBEGIN ; ADD OFFSET TO GET RAM PAGE + ldy #MAIN ; in the main bank + beq VFEXI ; BRA to fetch +VF2: + cmp #PGBEGIN ; is it paged? + bcs VFERR ; yes it be paged, so can't deal with it + cmp #P3PAGE ; is it in Aux Mem, Part 2? + bcs VF3 ; yes, so subtract different amount +; +; this is in lower aux +; + lda #(Z2PAGE-Z1SIZE) ; subtract size from offset + ldy #AUX ; show aux mem + bne VFEXI ; jump to end +VF3: + lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides + ldy #P3BANK ; show page 3 bank +VFEXI: + clc ; get ready for addition + adc MEMPAGE ; now get actual offset + rts +VFERR: +; +; out of range +; + lda #$22 + jmp ZERROR + +; +; FETCHB - fetch a byte from either main memory, aux memory, or upper +; Aux memory +; +FETCHB: + ldy FPCBNK ; get the bank + bmi FB1 ; must be in upper RAM + jmp ZERO_FB ; go to low end fetch +; +; this is in aux mem, >$E000 +; +FB1: + lda FPCH ; get which page + sta FBMOD+2 ; and show in operand + ldy FPCL ; get which byte + sta ALTZP+AUX ; talk about aux mem + lda BNK1SET ; set up read/write ram in upper mem + lda BNK1SET ; set up read/write ram in upper mem +FBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + ldx RDROM ; now use ROM please + ldx RDROM ; now use ROM please + rts +; +; NEXTFPC - inc DPCL and check for wrapping round to next bank +; +NEXTFPC: + inc FPCL ; next lo byte + bne NXFP_EXIT ; no change then + inc FPCH ; next page + lda FPCH ; and get it for checking + cmp # HIGH PRGLBL ; have we reached end of line? + bne NXFP_EXIT ; we be okay + lda FPCBNK ; get bank + bne NXFP1 ; must skip over stuff in middle + inc FPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta FPCH ; and point to it + rts ; toots finis +NXFP1: + lda #Z3PAGE ; start of part 3 + sta FPCH ; so show me + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey +NXFP_EXIT: + rts +; +; INST_MOUSE - install mouse handler IRQ +; +MFIX1 EQU (MSX1-MOUSERx)+PAGE3STUFF+2 +MFIX2 EQU (MSX2-MOUSERx)+PAGE3STUFF+1 +MFIX3 EQU (MSX4-MOUSERx)+PAGE3STUFF +MFIX4 EQU (MSX3-MOUSERx)+PAGE3STUFF+1 +INST_MOUSE: + jsr FINDMOUSE ; find which slot the mouse is in + bcc INMS1 ; everything is fine + rts ; can't find the mouse +INMS1: + sta MFIX1 + sta MFIX2 + sta MFIX3 ; okay, everyone knows now + and #$0f ; pick up low byte + sta ARG1+LO ; save for program to pick up + asl A ; shift slot number to upper nybble + asl A + asl A + asl A + sta MFIX4 ; and save here +; +; now init mouse, please +; + ldx #INITM ; init first + jsr MOUSER ; so do it + ldx #SETM ; setup mouse + lda #$01 ; transparent mode + jsr MOUSER ; we do that + ldx #CLEARM ; and clear mouse pos + jsr MOUSER ; we did +; +; now set min and max for clamping. +; 0 <= xpos <= 139 +; 0 <= ypos <= 191 +; + lda #0 ; zero out a few of the things + sta CLMPMINH ; hi part of min clamp + sta CLMPMINL ; lo part of min clamp + lda # LOW 137 ; max X + sta CLMPMAXL ; stash in lo part + lda # HIGH 137 ; max X + sta CLMPMAXH ; hi part of clamp + lda #0 ; show setting X clamp + ldx #CLAMPM ; do clamping + jsr MOUSER ; okay, we did + lda # LOW 189 ; now for Y + sta CLMPMAXL ; saved in lo part + lda # HIGH 189 ; now for Y + sta CLMPMAXH ; saved in lo part + lda #1 ; set y boundries + ldx #CLAMPM ; okay, show which routine + jsr MOUSER ; and do it + +; +; initialize the mouse position +; + lda #0 ; clear MSB + sta MOUSEXH + sta MOUSEYH + lda #MAXHEIGHT + sta MOUSEYL + lda #MAXWIDTH + sta MOUSEXL + + ldx #POSM + jsr MOUSER ; and move it + +; cli ; enable interrupts now + lda #$FF ; < 0 show mouse + sta MOUSEF ; so show it + clc ; show everything is fine + rts ; done +; +; FINDMOUSE - scan the slots for a mouse +; +FINDMOUSE: + lda $C1FB ; check for mouse ID == D6 + cmp #$D6 ; mouse ID + bne FNDM1 ; not it + lda FINDMOUSE+2 ; get slot + clc ; show okay-ness + rts ; and return +FNDM1: + inc FINDMOUSE+2 ; point to next slot + lda FINDMOUSE+2 ; reached last one yet? + cmp #$C8 ; no slot eight + bcc FINDMOUSE ; go look again + sec ; show no mouse + rts +; +; INST_STICK - install the joystick handler +INST_STICK: + lda #$1 ; > 0 show joystick + sta MOUSEF ; okay, we do + clc ; show it worked + rts +RAMINFO: + db 10 ; 10 parms + dw RAMNAME ; name + ds 15 ; room for stuff +RAMNAME: + db 5 ; length of name + db "/RAM/" ; name +RAMQ: db EOL,"This program disables /RAM and it",EOL + db "is not empty. Do you want to" + db EOL,"continue (Y destroys /RAM)?" +RAMQL EQU $-RAMQ +FIXRAM: + GET_FILE_INFO RAMINFO ; get the volumn size + bcs FIXR1 ; problem, so we'll just disable it + + lda RAMINFO+9 ; get amount used + bne ASKUSER ; some files there complain + lda RAMINFO+8 ; get LSB of used + cmp #9 ; if >= 9, must be being used + bcc FIXR1 ; no problem, disable /RAM +ASKUSER: + jsr MHOME ; clear and home + DLINE RAMQ, ; ask about continuing + jsr MRDKEY ; get answer + and #$7F ; turn off hi bit + cmp #'y' ; check for yes + beq FIXR1 ; then continue + cmp #'Y' ; also, captital Y + beq FIXR1 ; okay again + jmp ZQUIT ; so die +FIXR1: + lda RAMVEC+LO ; get current /RAM vector + sta OLDVEC+LO ; save it for reinstalling + lda RAMVEC+HI + sta OLDVEC+HI + lda UNSVEC+LO ; point /RAM vector to uninstalled device + sta RAMVEC+LO + lda UNSVEC+HI + sta RAMVEC+HI + ldx DEVCNT ; get how many devices +DEVLP: + lda DEVNUM,X ; try to find /RAM device + and #$70 ; isolate slot + cmp #$30 ; look for slot 3 + beq GOTSLT ; got it + dex ; missed it + bpl DEVLP ; try again + rts ; didn't find it (?) +GOTSLT: + lda DEVNUM+1,X ; now move all down one + sta DEVNUM,X ; down one + cpx DEVCNT ; done yet + beq FIXREX ; ayyup + inx ; point to next slot + bne GOTSLT ; continue on +FIXREX: + dec DEVCNT ; one less device, thank you + rts ; all done +; +; DO_DSEGS - scan through the disk segment table and point to the +; beginning of the segment list for each of the disks in the +; file. +DO_DSEGS: + lda SEGTBL+SGTDISKS+1 ; get # number disks + sta J ; save in counter + dec J ; we hand hold #1 + lda # HIGH (SEGTBL+SGTCHKS1) ; start off at beginning + sta D1SEG+HI ; here is first one + lda # LOW (SEGTBL+SGTCHKS1); and here is LSB + sta D1SEG+LO ; save it + ldy SEGTBL+SGTSEG1+1 ; get number of segs in first disk + ldx #2 ; start at second one +DODSL: + lda DSKSEG-2+LO,X ; get LSB of previous start + clc ; doing some adding + adc #SGTSEG ; point to start of segment list + sta DSKSEG+LO,X ; save in working segment pointer + lda DSKSEG-2+HI,X ; now work on MSB + adc #0 ; pick up possible carry + sta DSKSEG+HI,X ; and save in new pointer +ADDLOOP: + clc ; doing add + lda #6 ; size of segment entry + adc DSKSEG+LO,X ; counting + sta DSKSEG+LO,X ; counting + bcc ADDL1 ; no wrap + inc DSKSEG+HI,X ; add one to hi +ADDL1: + dey ; count segment + bne ADDLOOP ; okay, not done yet + lda DSKSEG+LO,X ; get pointer to #segs in this one + sta DSEGS+LO ; save ptr + lda DSKSEG+HI,X ; get MSB + sta DSEGS+HI ; save ptr + ldy #SGTNSEG+1 ; just need LSB + lda (DSEGS),Y ; get #segs in this segment + tay ; save in counter Y + inx + inx ; point to new pointer loc + dec J ; count this disk + bne DODSL ; and do it again +; +; now, init DSEGS to point to beginnning again +; + lda D1SEG+HI ; here is first one + sta DSEGS+HI + lda D1SEG+LO ; save it + sta DSEGS+LO +; +; check to see if we are using infoDOS, and set pointer to second +; disk segment table if we are. +; + lda KVERSION ; get "version" number + cmp #INFODOS_ID ; is in our DOS? + bne DODX ; nope, it ain't + lda D2SEG+HI ; then have infoDOS flag to point + sta INFODOS+HI ; to the D2SEG, cuz that's what + lda D2SEG+LO ; we use to check all the ZPC's + sta INFODOS+LO + rts +DODX: + lda #0 ; regular ProDOS + sta INFODOS ; show nothing there! + rts + +; +; INITPAG - init the paging buffers, thank you +; +INITPAG: + LDX #NUMBUFS-1 ;*** + STX CURRENT ; make last one first one to be used + dec CURRENT ; using only even pages + LDA #$FF +INILP: + STA VPAGEH,X + DEX + BPL INILP + LDX #0 + LDY #2 ;*** +INILP2: + TYA + STA PREVPNT,X + INX + inx ;*** + INY + iny ;*** + CPX #NUMBUFS + BCC INILP2 + LDA #00 + DEX + dex ;*** + STA PREVPNT,X + LDX #0 ;*** + LDY #$FE ;*** + LDA #NUMBUFS-2 ;*** +INILP3: + STA NEXTPNT,X + INX + inx ;*** + iny ;*** + INY + TYA + CPX #NUMBUFS + BCC INILP3 + rts + + END + + diff --git a/apple/yzip/ice/bt.bat b/apple/yzip/ice/bt.bat new file mode 100644 index 0000000..c68c61c --- /dev/null +++ b/apple/yzip/ice/bt.bat @@ -0,0 +1,10 @@ +@echo off +hm\hma6502 boot.asm -e -s -x -p -r +ask "Want to fix boot.bin?",yn +if errorlevel 2 goto no +hm\itob boot +nu boot.bin +:no + + + diff --git a/apple/yzip/ice/bugger.asm b/apple/yzip/ice/bugger.asm new file mode 100644 index 0000000..5e7a837 --- /dev/null +++ b/apple/yzip/ice/bugger.asm @@ -0,0 +1,255 @@ + TITLE "Apple ][ YZIP (c)Infocom","DEBUGGER: APPLE" + + ; -------------- + ; APPLE DEBUGGER + ; -------------- + + ; ENTRY: BREAKPOINT ID IN [A] + + ; SMALL DEBUGGER DBG1 (CONVERTS) DBG2 (JUST DISPLAYS) [A] + +DLCNT: DB 0 + +DBG1: + INC DLCNT + BNE DBG1m + PHA + JSR GETKEY + PLA +DBG1m: + PHA + LSR A + LSR A + LSR A + LSR A + JSR NIB1 + PLA + +NIB1: AND #%00001111 + TAY + LDA HCHARS,Y + JSR MCOUT + RTS + +DBG2: +; CMP #' ' +; BEQ DBG3 +; JSR MCOUT +; LDA #' ' +DBG3: JSR MCOUT + RTS + +HCHARS: DB "0123456789ABCDEF" + + END + +BLINE: DB "B: OP: PC: S: V: 1: 2: 3: 4: 5: 6: 7: 8: 9: " + DB EOL +BLINL EQU $-BLINE + +BUGLIN EQU LSTLNE + +DOBUG: LDX KBD ; WAS CTRL-S PRESSED? + CPX #$13 + BNE DO1 + RTS ; YES, SO LEAVE + +DO1: CMP #0 + BEQ BUGIT + RTS + + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + +BUGIT: LDX #2 ; INIT "CURSOR" + 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 BLINE,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 [ZSP] + LDA ZSP + JSR HEX + + LDX #29 ; CURSOR FOR [MPC] + LDA MPCH + JSR HEX + LDA MPCM + JSR HEX + LDA MPCL + JSR HEX + + LDX #38 + LDA BONE + JSR HEX + + LDX #43 + LDA BTWO + JSR HEX + + LDX #48 + LDA BTHREE + JSR HEX + + LDX #53 + LDA BFOUR + JSR HEX + + LDX #58 + LDA BFIVE + JSR HEX + + LDX #63 + LDA BSIX + JSR HEX + + LDX #68 + LDA BSEVEN + JSR HEX + + LDX #73 + LDA BEIGHT + JSR HEX + + LDX #78 + LDA BNINE + JSR HEX + +; TO SEND TO PRINTER IF WANTED +; LDA CSW+LO +; PHA +; LDA CSW+HI +; PHA +; LDA EH +; PHA +; LDA ALTCSW+LO +; STA CSW+LO +; LDA ALTCSW+HI +; STA CSW+HI +; +; LDA PSTAT +; BNE PPP +; +; LDA #$C1 +; STA CSW+HI +; LDA #$00 +; STA CSW+LO +; +; LDA #$89 +; JSR MCOUT +; LDA CSW+HI +; STA ALTCSW+HI +; LDA CSW+LO +; STA ALTCSW+LO +; LDA #$B8 +; JSR MCOUT +; LDA #$B0 +; JSR MCOUT +; LDA #$CE +; JSR MCOUT +; LDA #$8D +; JSR MCOUT + +PPP: LDX #2 +DBUG1: LDA BLINE,X ; PRINT DEBUGGER TEXT +; JSR MCOUT + JSR CHAR + INX + CPX #BLINL + BCC DBUG1 + +; PLA +; STA EH +; PLA +; STA CSW+HI +; PLA +; STA CSW+LO + +; BIT KBD +; BPL LETEX ; NO KEY PRESSED + + BIT ANYKEY ; CLEAR IT +BUGWAT: BIT KBD ; WAIT FOR A KEY + BPL BUGWAT + + LDA KBD + CMP #$8D + BNE LETEX + BRK + +LETEX: BIT ANYKEY ; CLEAR FOR NEXT ONE + 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 + ORA #%10000000 + STA BLINE,X + INX + RTS + +HCHARS: DB "0123456789ABCDEF" + +BONE: DB 0 +BTWO: DB 0 +BTHREE: DB 0 +BFOUR: DB 0 +BFIVE: DB 0 +BSIX: DB 0 +BSEVEN: DB 0 +BEIGHT: DB 0 +BNINE: DB 0 + + END + diff --git a/apple/yzip/ice/dispatch.asm b/apple/yzip/ice/dispatch.asm new file mode 100644 index 0000000..395d425 --- /dev/null +++ b/apple/yzip/ice/dispatch.asm @@ -0,0 +1,279 @@ + TITLE "Apple ][ YZIP (c)Infocom","OPCODE DISPATCH TABLES" + + + ; 0-OPS + +OPT0H: DB HIGH ZRTRUE ;B0 + DB HIGH ZRFALS ;B1 + DB HIGH ZPRI ;B2 + DB HIGH ZPRR ;B3 + DB HIGH ZNOOP ;B4 + DB HIGH OSAVE ;B5 + DB HIGH OREST ;B6 + DB HIGH ZSTART ;B7 + DB HIGH ZRSTAK ;B8 + DB HIGH ZCATCH ;B9 + DB HIGH ZQUIT ;BA + DB HIGH ZZCRLF ;BB + DB HIGH ZUSL ;BC + DB HIGH ZVER ;BD + DB HIGH ZEXTOP ;BE + DB HIGH ZORIG ;BF + +OPT0L: DB LOW ZRTRUE ;B0 + DB LOW ZRFALS ;B1 + DB LOW ZPRI ;B2 + DB LOW ZPRR ;B3 + DB LOW ZNOOP ;B4 + DB LOW OSAVE ;B5 + DB LOW OREST ;B6 + DB LOW ZSTART ;B7 + DB LOW ZRSTAK ;B8 + DB LOW ZCATCH ;B9 + DB LOW ZQUIT ;BA + DB LOW ZZCRLF ;BB + DB LOW ZUSL ;BC + DB LOW ZVER ;BD + DB LOW ZEXTOP ;BE + DB LOW ZORIG ;BF + + ; 1-OPS + +OPT1H: DB HIGH ZZERO ;80,90,A0 + DB HIGH ZNEXT ;81 + DB HIGH ZFIRST ;82 + DB HIGH ZLOC ;83 + DB HIGH ZPTSIZ ;84 + DB HIGH ZINC ;85 + DB HIGH ZDEC ;86 + DB HIGH ZPRB ;87 + DB HIGH ZCALL1 ;88 (EZIP) + DB HIGH ZREMOV ;89 + DB HIGH ZPRD ;8A + DB HIGH ZRET ;8B + DB HIGH ZJUMP ;8C + DB HIGH ZPRINT ;8D + DB HIGH ZVALUE ;8E + DB HIGH ZICLL1 ;8F + +OPT1L: DB LOW ZZERO ;80 + DB LOW ZNEXT ;81 + DB LOW ZFIRST ;82 + DB LOW ZLOC ;83 + DB LOW ZPTSIZ ;84 + DB LOW ZINC ;85 + DB LOW ZDEC ;86 + DB LOW ZPRB ;87 + DB LOW ZCALL1 ;88 (EZIP) + DB LOW ZREMOV ;89 + DB LOW ZPRD ;8A + DB LOW ZRET ;8B + DB LOW ZJUMP ;8C + DB LOW ZPRINT ;8D + DB LOW ZVALUE ;8E + DB LOW ZICLL1 ;8F + + ; 2-OPS + +OPT2H: DB HIGH BADOP2 ;00 (UNDEFINED) + DB HIGH ZEQUAL ;01 + DB HIGH ZLESS ;02 + DB HIGH ZGRTR ;03 + DB HIGH ZDLESS ;04 + DB HIGH ZIGRTR ;05 + DB HIGH ZIN ;06 + DB HIGH ZBTST ;07 + DB HIGH ZBOR ;08 + DB HIGH ZBAND ;09 + DB HIGH ZFSETP ;0A + DB HIGH ZFSET ;0B + DB HIGH ZFCLR ;0C + DB HIGH ZSET ;0D + DB HIGH ZMOVE ;0E + DB HIGH ZGET ;0F + DB HIGH ZGETB ;10 + DB HIGH ZGETP ;11 + DB HIGH ZGETPT ;12 + DB HIGH ZNEXTP ;13 + DB HIGH ZADD ;14 + DB HIGH ZSUB ;15 + DB HIGH ZMUL ;16 + DB HIGH ZDIV ;17 + DB HIGH ZMOD ;18 + DB HIGH ZCALL2 ;19 (EZIP) + DB HIGH ZICLL2 ;1A + DB HIGH ZCOLOR ;1B + DB HIGH ZTHROW ;1C + DB HIGH BADOP2 ;1D + DB HIGH BADOP2 ;1E + DB HIGH BADOP2 ;1F + +OPT2L: DB LOW BADOP2 ;00 (UNDEFINED) + DB LOW ZEQUAL ;01 + DB LOW ZLESS ;02 + DB LOW ZGRTR ;03 + DB LOW ZDLESS ;04 + DB LOW ZIGRTR ;05 + DB LOW ZIN ;06 + DB LOW ZBTST ;07 + DB LOW ZBOR ;08 + DB LOW ZBAND ;09 + DB LOW ZFSETP ;0A + DB LOW ZFSET ;0B + DB LOW ZFCLR ;0C + DB LOW ZSET ;0D + DB LOW ZMOVE ;0E + DB LOW ZGET ;0F + DB LOW ZGETB ;10 + DB LOW ZGETP ;11 + DB LOW ZGETPT ;12 + DB LOW ZNEXTP ;13 + DB LOW ZADD ;14 + DB LOW ZSUB ;15 + DB LOW ZMUL ;16 + DB LOW ZDIV ;17 + DB LOW ZMOD ;18 + DB LOW ZCALL2 ;19 (EZIP) + DB LOW ZICLL2 ;1A + DB LOW ZCOLOR ;1B + DB LOW ZTHROW ;1C + DB LOW BADOP2 ;1D + DB LOW BADOP2 ;1E + DB LOW BADOP2 ;1F + + ; X-OPS + +OPTXH: DB HIGH ZCALL ;E0 + DB HIGH ZPUT ;E1 + DB HIGH ZPUTB ;E2 + DB HIGH ZPUTP ;E3 + DB HIGH ZREAD ;E4 + DB HIGH ZPRC ;E5 + DB HIGH ZPRN ;E6 + DB HIGH ZRAND ;E7 + DB HIGH ZPUSH ;E8 + DB HIGH ZPOP ;E9 + DB HIGH ZSPLIT ;EA + DB HIGH ZSCRN ;EB + + ; (EZIPS FROM HERE ON) + DB HIGH ZXCALL ;EC + DB HIGH ZCLR ;ED + DB HIGH ZERASE ;EE + DB HIGH ZCURST ;EF + DB HIGH ZCURGT ;F0 + DB HIGH ZLIGHT ;F1 + DB HIGH ZBUFOUT ;F2 + DB HIGH ZDIRT ;F3 + DB HIGH ZDIRIN ;F4 (NOT IMPLEMENTED) + DB HIGH ZSOUND ;F5 + DB HIGH ZINPUT ;F6 + DB HIGH ZINTBL ;F7 + DB HIGH ZBCOM ;F8 + DB HIGH ZICALL ;F9 + DB HIGH ZIXCLL ;FA + DB HIGH ZLEX ;FB + DB HIGH ZWSTR ;FC + DB HIGH ZCOPYT ;FD + DB HIGH ZPRNTT ;FE + DB HIGH ZASSND ;FF + +OPTXL: DB LOW ZCALL ;E0 + DB LOW ZPUT ;E1 + DB LOW ZPUTB ;E2 + DB LOW ZPUTP ;E3 + DB LOW ZREAD ;E4 + DB LOW ZPRC ;E5 + DB LOW ZPRN ;E6 + DB LOW ZRAND ;E7 + DB LOW ZPUSH ;E8 + DB LOW ZPOP ;E9 + DB LOW ZSPLIT ;EA + DB LOW ZSCRN ;EB + + ; (EZIPS FROM HERE ON) + DB LOW ZXCALL ;EC + DB LOW ZCLR ;ED + DB LOW ZERASE ;EE + DB LOW ZCURST ;EF + DB LOW ZCURGT ;F0 + DB LOW ZLIGHT ;F1 + DB LOW ZBUFOUT ;F2 + DB LOW ZDIRT ;F3 + DB LOW ZDIRIN ;F4 (NOT IMPLEMENTED) + DB LOW ZSOUND ;F5 + DB LOW ZINPUT ;F6 + DB LOW ZINTBL ;F7 + DB LOW ZBCOM ;F8 + DB LOW ZICALL ;F9 + DB LOW ZIXCLL ;FA + DB LOW ZLEX ;FB + DB LOW ZWSTR ;FC + DB LOW ZCOPYT ;FD + DB LOW ZPRNTT ;FE + DB LOW ZASSND ;FF + + +EXTOPH: DB HIGH ZSAVE ;100 + DB HIGH ZREST ;101 + DB HIGH ZSHIFT ;102 + DB HIGH ZASHFT ;103 + DB HIGH ZFONT ;104 + DB HIGH ZDISPL ;105 + DB HIGH ZPICNF ;106 + DB HIGH ZDCLR ;107 + DB HIGH ZMARG ;108 + DB HIGH ZISAVE ;109 + DB HIGH ZIREST ;10A + DB HIGH BADEXT ;10B - NOT USED + DB HIGH BADEXT ;10C - NOT USED + DB HIGH BADEXT ;10D - NOT USED + DB HIGH BADEXT ;10E - NOT USED + DB HIGH BADEXT ;10F - NOT USED + DB HIGH ZWINPOS ;110 + DB HIGH ZWINSIZE ;111 + DB HIGH ZWINATTR ;112 + DB HIGH ZWINGET ;113 + DB HIGH ZSCROLL ;114 + DB HIGH ZFSTACK ;115 + DB HIGH ZMINFO ;116 + DB HIGH ZMLIMIT ;117 + DB HIGH ZXPUSH ;118 + DB HIGH ZWINPUT ;119 + DB HIGH ZPRINTF ;11A + DB HIGH ZMENU ;11B + DB HIGH ZPICSET ;11c + +EXTLEN EQU $-EXTOPH + +EXTOPL: DB LOW ZSAVE ;100 + DB LOW ZREST ;101 + DB LOW ZSHIFT ;102 + DB LOW ZASHFT ;103 + DB LOW ZFONT ;104 + DB LOW ZDISPL ;105 + DB LOW ZPICNF ;106 + DB LOW ZDCLR ;107 + DB LOW ZMARG ;108 + DB LOW ZISAVE ;109 + DB LOW ZIREST ;10A + DB LOW BADEXT ;10B - NOT USED + DB LOW BADEXT ;10C - NOT USED + DB LOW BADEXT ;10D - NOT USED + DB LOW BADEXT ;10E - NOT USED + DB LOW BADEXT ;10F - NOT USED + DB LOW ZWINPOS ;110 + DB LOW ZWINSIZE ;111 + DB LOW ZWINATTR ;112 + DB LOW ZWINGET ;113 + DB LOW ZSCROLL ;114 + DB LOW ZFSTACK ;115 + DB LOW ZMINFO ;116 + DB LOW ZMLIMIT ;117 + DB LOW ZXPUSH ;118 + DB LOW ZWINPUT ;119 + DB LOW ZPRINTF ;11A + DB LOW ZMENU ;11B + DB LOW ZPICSET ;11C + + END diff --git a/apple/yzip/ice/dline.asm b/apple/yzip/ice/dline.asm new file mode 100644 index 0000000..949b5f5 --- /dev/null +++ b/apple/yzip/ice/dline.asm @@ -0,0 +1,304 @@ + TITLE "Apple ][ YZIP (c)Infocom","Display line Routine" +; +; some aux mem zero page stuff +; +DLVARS: +CHR_X EQU DLVARS ; (WORD) X pos for char (0-559) +LINEOFF EQU CHR_X+2 ; (BYTE) offset into SCRBUFF +ENDBIT EQU LINEOFF+1 ; (BYTE) ending bit offset +SAVEX EQU ENDBIT+1 ; (BYTE) save original X +CHR_Y EQU SAVEX+1 ; (BYTE) Working cursor Y pos +LINECHAR EQU CHR_Y+1 ; (BYTE) working char counter +BITTER EQU LINECHAR+1 ; (BYTE) bit twiddler counter +INCFLG EQU BITTER+1 ; (BYTE) ==1 if NEXT_SCR needed after setpos +SHOW_CURSOR EQU INCFLG+1 ; (BYTE) flag as to whether we are doing cursor +SCRCNT EQU SHOW_CURSOR+1 ; (BYTE) screen buffer offset +SV_UND EQU SCRCNT+1 ; (BYTE) spot to save underline flag +SV_INV EQU SV_UND+1 ; (BYTE) save starting INVFLG +LINE_HEIGHT EQU SV_INV+1 ; (BYTE) counter for height +LINE_X EQU LINE_HEIGHT+1 ; (WORD) width of line counter +CH_BYTE EQU LINE_X+2 ; (BYTE) small offset +DLVARSL EQU CH_BYTE-CHR_X+1 + + ds DLVARSL + +BIT_BITS: DB 7,6,5,4,3,2,1,0 ; number significant bits in last byte + +DISP_LINE: + lda SCRCNT ; make sure there are characters + bne DPL1 ; ayyup + rts ; no chars, don't do anything +DPL1: + lda #0 ; start at zero + sta CH_BYTE ; which byte to use + sta INCFLG ; and clear out inc'er flag + + lda #FONT_H-1 ; do for height of char + sta LINE_HEIGHT ; height counter + + ldy SCRCY ; and starting y + sty CHR_Y ; saved + ldy SCRCX ; save x to + sty SAVEX ; save it + lda INVFLG ; get current state + sta SV_INV ; and save it + + ldx CURSFLG ; changed x pos? + beq DPL2 ; no new figgering + + lda SCRCX ; get new cursor x pos + sta CHR_X+LO ; okay + + ldx #0 + stx CHR_X+HI ; clear out msb + + asl A ; *2 + rol CHR_X+HI + asl A ; *4 + sta CHR_X+LO + rol CHR_X+HI +DPL2: + lda CHR_X+LO + sta SCRCX + and #3 ; pick up 2 bits rolling out + sta BITTER ; what to add + lda CHR_X+HI + lsr A ; /2 + ror SCRCX + lsr A ; /4 + ror SCRCX + jsr SETPOS ; set up pointers + + lda BITTER ; get extra + clc ; add in + adc BITOFF ; normal bit offset + sta BITTER ; and make it new one + cmp #7 ; but can't be greater than 6 + bcc DO_LINE ; okay, it's not + sta INCFLG ; show needing NEXT_SCR call + sbc #7 ; so shrink it + sta BITTER ; save it +DO_LINE: + jsr SETPOS ; set up pointers + lda INCFLG ; do we need to go one more? + beq DOL1 ; nope + jsr NEXT_SCR ; and point to next screen byte +DOL1: + ldx BITTER ; get bit off set + stx BITOFF ; and save here + lda #0 ; init a few things + sta SCR_DATA ; init screen data byte + sta LINECHAR ; which character on the line + sta LINEOFF ; which byte in line on screen + sta LINE_X+LO ; X pos of line + sta LINE_X+HI ; part 2 + sta SV_UND ; start underlining bit at zero + + lda SV_INV ; get starting INV state + sta INVFLG ; okay! + + dec LINEOFF ; inclusive count + ldx BITOFF ; make bitoff be a count + lda BIT_BITS,X ; get count + tax ; x is bit counter +CHARL: + ldy LINECHAR ; get the char + cpy SCRCNT ; done with line? + bne CHARL1 ; nope + jmp COPYL ; okay, move onto screen +CHARL1: + inc LINECHAR ; point to next one + lda SCRBUFF,Y ; got it + bpl CHARL3 ; not a highlight char + + jsr HLIGHT ; so check it out + jmp CHARL ; done +CHARL3: + cmp #SPACE ; is it a highlight char? + bcc CHARL ; ignore this one then +CHARL2: + tay ; use as index + lda CHADR_H,Y ; get high part of address + sta CHPTR+HI ; point to it + lda CHADR_L,Y ; get lo part + sta CHPTR+LO ; save it + lda CHWID,Y ; get how wide the char is + sta CW ; save it + lda CH_BYTE ; to get data + ldy CW ; see how wide the char is + cpy #10 ; if <= 8, only one byte of info + bcc CHRLCW ; it is, so skip shift + asl A ; *2 for bigger chars +CHRLCW: + tay ; get the index + lda (CHPTR),Y ; get first byte + sta CHAR_D1 ; part one + iny ; point to next part + lda (CHPTR),Y ; get second byte + sta CHAR_D2 ; and save it + lda CW ; get width back + cmp #10 ; if <= 8 zero byte 2 of char data + bcs CHRLCW1 ; nope + lda #0 ; clear out byte 2 + sta CHAR_D2 ; okay +CHRLCW1: + lda FONTFLG ; is this monospacing? + beq CHRLFX ; nope +; +; if monospacing, see if it char is < mono width, and try to split +; the difference if so +; + cmp CW ; check against current width + bcs CHRLF0 ; CW < monowidth, so center +; +; too big, so take a little off front end too +; + lda CW ; get current width + sec ; get ready for subbing + sbc #MONOFONT_W ; take away mono width + lsr A ; /2 to get front half + tay ; use as counter + beq CHRLF1 ; nothing to do +CHRLFX1: + asl CHAR_D2 ; step to the left + rol CHAR_D1 ; pick up char + dey ; count one + bne CHRLFX1 ; do next one + beq CHRLF1 ; all done +CHRLF0: + sec ; do sub + sbc CW ; subtract CW + lsr A ; /2 to get front part + tay ; put in counter + beq CHRLF1 ; no need to do anything +CHRLFL: + lsr CHAR_D1 ; shift to right + ror CHAR_D2 ; this part too + dey ; count shift + bne CHRLFL ; not done shifting yet +CHRLF1: + lda #MONOFONT_W ; get mono font width + sta CW ; chop at mono width +CHRLFX: + lda LINE_HEIGHT ; if == 0, then pick up underlining + bne CHRL3 ; nope + lda UNDFLG ; get underlining flag + sta SV_UND ; and mark for later +CHRL3: + lda SCR_DATA ; get starting data +DATAL: + rol CHAR_D2 ; it's a step to the left + rol CHAR_D1 ; nother one + ror A ; and put into screen byte + eor INVFLG ; pick up inversing + ora SV_UND ; pick up underline flag + inc LINE_X+LO ; next X pos too + bne DATAL0 ; no wrap + inc LINE_X+HI ; wrapped +DATAL0: + dex ; next bit pos + bne DATAL1 ; nope +; +; save the byte and point to next byte +; +STCH: + lsr A ; put in lower 7 bits + inc LINEOFF ; point to next one + ldy LINEOFF ; get current offset + sta SCR_LINE,Y ; save in line + ldx #7 ; and start bitoff at 7 + lda #0 ; clear a few locals +DATAL1: + dec CW ; well? + bmi COPYL1 ; all done, start copying + bne DATAL ; nope + sta SCR_DATA ; save current screen byte stuff here + jmp CHARL ; do next char +COPYL: + lda LINE_X+LO ; see if we have any at all + ora LINE_X+HI ; well, did we go anywhere? + beq LINE_EXIT ; then quit + lda BIT_BITS,X ; get number of significant bits + sta ENDBIT ; save this one + cpx #7 ; has it been renewed? + beq COPYL1 ; no last byte + lda SCR_DATA ; get screen data +COPYSH: + lsr A ; put down low, please + dex ; one more + bne COPYSH ; and do it again + beq STCH ; now save this char +COPYL1: + jsr COPY_SCRL ; copy SCR_LINE to screen +LED2: + inc SCRCY ; point to next line + dec LINE_HEIGHT ; count this line + bmi LINE_EXIT ; all done! + + inc CH_BYTE ; point to next byte + jmp DO_LINE ; and do next line +LINE_EXIT: + lda SHOW_CURSOR ; are we just doing cursor? + bne LIX1 ; yes, don't change char pos + + clc ; add in length of this line + lda LINE_X+LO ; get length of line + adc CHR_X+LO ; add to start pos + sta CHR_X+LO ; save it + lda LINE_X+HI ; and the MSB + adc CHR_X+HI ; okay + sta CHR_X+HI ; save for a rainy day +LIX1: + ldx SAVEX ; get x back + stx SCRCX ; restore it + + ldx CURSFLG ; did we change it? + beq DLXX ; nope + + jsr GET_SCRCX ; set SCRCX back up +DLXX: + lda CHR_Y ; restore the + sta SCRCY ; y pos + lda #0 ; clear out counter + sta SCRCNT ; okay + sta CURSFLG ; reset this flag too + rts + +GET_SCRCX: + ldx CHR_X+LO ; pick this back up + stx LINE_X ; just use this + lsr A ; /2 + ror LINE_X ; pick up remainder + lsr A ; /4 + ror LINE_X ; pick up remainder + lda LINE_X ; restore X pos + sta SCRCX ; got it + lda CHR_X+LO ; any remainder? + and #3 ; well? + beq DLXX ; nope + inc SCRCX ; point to next pos + rts + +; +; DO_CURSOR - read in the screen byte, XOR cursor data, store it +; +DO_CURSOR: + ldy #0 ; and zero y + sty DATALOOP ; init this counter +DOCLOOP: + ldy #0 ; must use Y + ldx FPCBNK ; what bank + sta PAGE2SW,X ; select it + lda (FPC),Y ; okay, get byte + ldx DATALOOP ; get offset + eor SCR_LINE,X ; get data + sta (FPC),Y ; save data + jsr NEXT_SCR ; point to next screen byte + inc DATALOOP ; point to next char + dec LINEOFF ; count one char + bpl DOCLOOP ; all done with this line? + + rts + + END + diff --git a/apple/yzip/ice/dt.asm b/apple/yzip/ice/dt.asm new file mode 100644 index 0000000..2f431ad --- /dev/null +++ b/apple/yzip/ice/dt.asm @@ -0,0 +1,22 @@ +DLINE: MACRO STRING,SLEN + ldx \#LOW #STRING# ; get part of STRING + lda \#HIGH #STRING# ; get other part of string + IF (#SLEN#+"L") == "L" ; is there a length defined? + ldy \##STRING#L ; get length of string + printx "IF" + ELSE + ldy #SLEN# ; then just fetch it + printx "ELSE" + ENDIF + jsr DISPLAY_LINE ; print the string + ENDM + + DLINE TEST,TEX + rts +DISPLAY_LINE: + rts +TEST: db "This is a test" +TEX EQU $-TEST + + + END diff --git a/apple/yzip/ice/dt.bat b/apple/yzip/ice/dt.bat new file mode 100644 index 0000000..632ffbb --- /dev/null +++ b/apple/yzip/ice/dt.bat @@ -0,0 +1,3 @@ +hm\hma6502 dt.asm -ns -nh -pdt.lst + + diff --git a/apple/yzip/ice/dt.lst b/apple/yzip/ice/dt.lst new file mode 100644 index 0000000..cea9520 --- /dev/null +++ b/apple/yzip/ice/dt.lst @@ -0,0 +1,132 @@ +Huntsville Macro Assembler 65C02 cross assembler for PC-DOS 2.0 v1.85L Page 1 + Module: dt + +0000 DLINE: MACRO STRING,SLEN +0000 ldx \#LOW #STRING# ; get part of STRING +0000 lda \#HIGH #STRING# ; get other part of string +0000 IF (#SLEN#+"L") == "L" ; is there a length defined? +0000 ldy \##STRING#L ; get length of string +0000 printx "IF" +0000 ELSE +0000 ldy #SLEN# ; then just fetch it +0000 printx "ELSE" +0000 ENDIF +0000 jsr DISPLAY_LINE ; print the string +0000 ENDM + +0000 DLINE TEST,TEX +0000+A20B ldx #LOW TEST ; get part of STRING +0002+A900 lda #HIGH TEST ; get other part of string +0004+ IF (TEX+"L") == "L" ; is there a length defined? +0004+ ldy #TESTL ; get length of string +0004+ printx "IF" +0004+ ELSE +0004+AC0E00 ldy TEX ; then just fetch it +0007+ printx "ELSE" +0007+ ENDIF +0007+200A00 jsr DISPLAY_LINE ; print the string +000A 60 rts +000B DISPLAY_LINE: + ^ +dt.asm: Line 16: Error 14: Label value differs on Pass 2 + +000B 60 rts +000C 5468697320 TEST: db "This is a test" + 6973206120 + 74657374 + ^ +dt.asm: Line 18: Error 14: Label value differs on Pass 2 + +000F TEX EQU $-TEST + ^ +dt.asm: Line 19: Error 14: Label value differs on Pass 2 + + + +001A END + + 3 errors + + + + + + + + + + + + + + + + + + +Huntsville Macro Assembler 65C02 cross assembler for PC-DOS 2.0 v1.85L Page 2 + Module: dt + + Macros: + + DLINE + + + + Symbols: + + 000A DISPLAY_LINE 000B TEST U 0000 TESTL + 000E TEX + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apple/yzip/ice/dt.rel b/apple/yzip/ice/dt.rel new file mode 100644 index 0000000..2e80cc8 Binary files /dev/null and b/apple/yzip/ice/dt.rel differ diff --git a/apple/yzip/ice/elinks.doc b/apple/yzip/ice/elinks.doc new file mode 100644 index 0000000..d69971f --- /dev/null +++ b/apple/yzip/ice/elinks.doc @@ -0,0 +1,324 @@ + IBM PC/XT/AT SYMBOLIC DEBUG COMMUNICATIONS SOFTWARE + FOR PC-DOS v2.x AND v3.x + + +Supplied on the IBM compatible disk are two files: + +ELINKS.EXE - Executable Communications Software program which + uses the IBM-PC/XT/AT COM1 or COM2 port. + +ELINKS.DOC - This document. + + + If it is required that an I/O port other than a standard IBM +COM1 or COM2 port be used, contact Huntsville Microsystems, Inc. + + + +Starting ELINKS: + + The standard ELINKS command line is formatted as follows: + + ELINKS [-baud] [-port] [ [] ] + + All command line arguments are optional. + + + -baud Select communications port baud rate (9600 + default). Allowable selections are: N (No change + from current baud rate), 110, 150, 300, 600, 1200, + 2400, 4800, 9600. + + -port Select communications port. (COM1 or COM2 + default). ELINKS will automatically select COM1 + as its default, unless COM1 is not available, in + which case it will use COM2. The -port option + will override this port search and cause ELINKS to + use only the port named. Allowable options are: + AUX (Default -- may be COM1 or COM2), COM1, COM2. + + Set up the name of a .HEX file to load with the + emulator 'R' command, or write with the emulator + 'W' command. The hex file name is of the form: + [d:][path]filename[.ext] . The file's drive, + path, and extent are all optional. Drive and path + default to the currently logged-in drive and + directory. A hexfile's extent defaults to .HEX . + + Read the named symbol file into the ELINKS symbol + table. The symbol file must be in standard symbol + file format, such as that produced by the + Huntsville Microsystem's HMA series of cross- + assemblers. The symbol file name is of the same + form as a hex file name: [d:][path]filename[.ext] + Drive and path default as before. Extent defaults + to .SYM for a symbol file. + +Notes: + + To use ELINKS, the HMI emulator should be set up for +autobaud mode with 8 data bits and no parity (this is how ELINKS +sets up the COMx port). The CTS and RTS control lines are +ignored by ELINKS, and should be jumpered together inside the +emulator. + + When ELINKS is started, it will sign-on and ask: "Has the +emulator been reset (Y or N) ? ". If the emulator has just been +turned on, or if the emulator's reset button has been pressed +since last using ELINKS, this question should be answered 'Y'. +Otherwise, it should be answered 'N'. A 'Y' answer to this +question causes ELINKS to initialize the emulator's baud rate and +communications software handshake mode. + + To exit ELINKS, use the 'Ctrl-Break' key. + + +Examples: + ELINKS ; Run ELINKS + ELINKS -4800 ; Set baud rate to 4800 + ELINKS -COM2 ; Use COM2 + ELINKS TEST ; Set up "TEST.HEX" + ELINKS TEST.HXE ; Set up "TEST.HXE" + ELINKS TEST TEST ; Read "TEST.SYM" + ELINKS TEST TEST. ; Read "TEST." + ELINKS -1200 -COM1 TEST TEST ; All options used + + + +ELINKS commands: + + Using ELINKS in conjunction with an HMI emulator adds the +following commands to the emulator's command set: + + I hexfile ; Set up a hex file name for + ; reading/writing + R ; Read a hex file set up with 'I' + R bias ; Read a hex file with offset 'bias' + W saddr,faddr ; Write a hex file from 'saddr' to + ; 'faddr' into the 'I' file + DIR ; Show disk directory + < batfile ; Read emulator commands from the file + ; 'batfile' + + outfile ; Send all screen output to the file + ; 'outfile' + I. symfile ; Read the given symbol file + I.. symfile ; Append the given symbol file + W. symfile ; Write the ELINKS symbol table to the + ; named file + . ; Display the ELINKS symbol table + .symbol ; Display the ELINKS symbol table, + ; starting at 'symbol' + .symbol= ; Delete the named symbol from the + ; ELINKS symbol table + .symbol=value ; Create or revalue the named symbol + + + In addition to adding the commands listed, ELINKS will +insert symbols into the output of all 'L' commands and CPU +register displays. + + When ELINKS is in use, all emulator commands which require +addresses may have symbols used in place of the address(es). To +use a symbol in a command in place of an address, use ".symbol" +where the address is required. + +Examples: + L100 ; List from 0100 + L.START ; List from START + W.START,.END ; Write from START to END + + + +Details on ELINKS commands: + + + I hexfile + + The 'I' command is used to name a hex file for ELINKS +to use on subsequent 'R' and 'W' commands. + + The hex file name is given using standard file name +format. ".HEX" is the default file name extension. + + The initial 'I' filename can be given on the ELINKS +command line. + + + R + R bias + + The 'R' command is used for reading the last named 'I' +file into the emulator or target system memory. If a read bias +is given, this bias will be added to the addresses of all bytes +read from the hex file, before these bytes are stored in memory. + + 'bias' is a hexadecimal number (or symbol). + + + W saddr,faddr + + The 'W' command is used to write a hex file from saddr +to faddr into the last named 'I' file. + + 'saddr' and 'faddr' are hexadecimal numbers (or +symbols). + + + DIR + + The 'DIR' command causes ELINKS to run the operating +system DIR function. + + + < batfile + + The '<' command is used to temporarily re-direct ELINKS +input to the named batch file. Any emulator command may be given +in this batch file, except for the '<' command. + + A '<' command in a batch file causes ELINKS to pause +until a carriage-return is typed on the keyboard. + + Typing carriage-return while a pause is not in effect +will abort batch file processing. + + The batch file name is a standard file name. The +default extent for a batch file is ".BAT". + + + + outfile + + The '+' command causes all emulator output to be +written to the named file, in addition to appearing on the +screen. + + Output to the '+' file continues until a new '+' file +is opened, or a '+' is entered by itself on a line (this closes +the current '+' file without opening a new one). + + It is recommended that any '+' files be closed before +exiting ELINKS with 'Ctrl-Break'. + + The outfile name is a standard file name. No default +extent is assumed. + + + I. symfile + + The 'I.' command causes ELINKS to read the named symbol +file into its internal symbol table. + + The symbol file name is a standard file name. The +default extent is ".SYM". + + This command can be given by default on the ELINKS +command line. + + 'I.' given without a symbol file name causes an "ERROR +IN OPEN" message, and erases the current contents of the ELINKS +internal symbol table. + + + I.. symfile + + The 'I..' command causes ELINKS to read the named +symbol file and append its contents to the current contents of +its internal symbol table. + + + W. symfile + + The 'W.' command causes ELINKS to write the edited +contents of its internal symbol table to the named symbol file. + + + . + + '.' commands are used for editing and displaying the +contents of the ELINKS internal symbol table. + + A '.' given on the command line causes ELINKS to +display the contents of its internal symbol table. + + + .symbol + + A '.' command followed by a symbol causes ELINKS to +display the contents of its internal symbol table, starting at +'symbol'. + + + .symbol= + + A '.' command, followed by a symbol, followed by an '=' +causes ELINKS to erase the named symbol from its internal symbol +table. + + + .symbol=value + + This command causes ELINKS to assign 'value' to +'symbol'. + + If 'symbol' already exists, it is revalued. + + If symbol does not exist, it is appended to the symbol +table, and assigned the value 'value'. + + 'value' is an hexadecimal number. + + + +Notes on symbols: + + ELINKS defines a symbol as either a label, or a module path +followed by a label. + + The ELINKS iternal symbol table contains two types of +entries: labels and modules. + + To use an ordinary label in a command, use ".label". + + To use a module path to reach a certain label, use +".module/label" (i.e. L.STARTMOD/START). + + Using a module path will move the named module to the top of +the symbol table, and then search the symbol table for the named +label. This places the last pathed module first in the search +order for subsequent symbol manipulation operations. + + Modules cannot be editing with the ELINKS '.' commands. + + If a label is added to the internal symbol table with the +".symbol=value" command, and that symbol contains a path; the +label will be added after the module named in the path, rather +than at the end of the symbol table. + + +Notes for 8088/8086 users: + + Labels on the 8088/8086 emulator may have values beyond +those associated with normal 8-bit processors. + + For the 8088/8086, label values may take on the forms: + + ssss:oooo ; Segment:Offset (20-bit value) + CS:oooo ; Segment_Register:Offset (20-bit value) + DS:oooo + ES:oooo + SS:oooo + oooo ; Offset only (Ordinary 16-bit value) + + Label forms "ssss:oooo" and "oooo" are fixed values. Labels +defined with a segment register have values which vary according +to the current contents of the 8088/8086 segment registers. + + + The following labels have special meaning to ELINKS when +used with the 8088/8086, and should not be used in ANY assembly +language program: + + _Aorg_ _Corg_ _Dorg_ _Eorg_ _Sorg_ _Uorg_ + _Aend_ _Cend_ _Dend_ _Eend_ _Send_ _Uend_ + + \ No newline at end of file diff --git a/apple/yzip/ice/elinks.exe b/apple/yzip/ice/elinks.exe new file mode 100644 index 0000000..0b35c20 Binary files /dev/null and b/apple/yzip/ice/elinks.exe differ diff --git a/apple/yzip/ice/fix.cm b/apple/yzip/ice/fix.cm new file mode 100644 index 0000000..d9868db Binary files /dev/null and b/apple/yzip/ice/fix.cm differ diff --git a/apple/yzip/ice/fix.m b/apple/yzip/ice/fix.m new file mode 100644 index 0000000..682356d --- /dev/null +++ b/apple/yzip/ice/fix.m @@ -0,0 +1,6 @@ +(macro fix +( + (top_of_buffer) + (translate "DLINE\t{*}\t" "DLINE\0 " 1 ) +)) + diff --git a/apple/yzip/ice/hide.arc b/apple/yzip/ice/hide.arc new file mode 100644 index 0000000..5faaf5e Binary files /dev/null and b/apple/yzip/ice/hide.arc differ diff --git a/apple/yzip/ice/hlm.exe b/apple/yzip/ice/hlm.exe new file mode 100644 index 0000000..b69ba44 Binary files /dev/null and b/apple/yzip/ice/hlm.exe differ diff --git a/apple/yzip/ice/hma6502.add b/apple/yzip/ice/hma6502.add new file mode 100644 index 0000000..1afe33f --- /dev/null +++ b/apple/yzip/ice/hma6502.add @@ -0,0 +1,77 @@ + + HMA-02R 65C02 Cross Assembler Addendum + + +The following features have been added to HMA-02R for v1.82: + + 1) NUL (Empty) Macro Argument testing. + + 2) HIGH and LOW byte isolation operators. + + 3) Large Data Memory Model. + + +Added Feature #1: NUL (Empty) Macro Argument testing. + + The standard HMA conditional test, IF, has been extended to +allow for the testing of empty macro arguments. + + To test for an empty macro parameter, use the conditional IF +test, followed by the keyword NUL, followed by a #, the parameter +being tested, and another #. + + For example, to test for the occurrance of macro parameter +P1, which may be empty, use the following: + + IF NUL #P1# + (Stuff to do if P1 is empty) + ELSE + (Stuff to do if P1 is not empty) + ENDIF + + The NUL test checks the input line from the end of the NUL +keyword to the end of the line. If a character is encountered +before the end of the line which is not a space character, nor a +semicolon character, the NUL test is considered to be false, +otherwise, the NUL test is true. Note that a macro parameter +which starts with a ';' character will fool the NUL test into +being true when it should be false. + + +Added Feature #2: HIGH and LOW byte isolation operators. + + Two new mathematical operators, HIGH and LOW, have been +added. These operators have been assigned the highest precedence +in the HMA mathematical hierarchy. Only one HIGH or LOW operator +may be used in a mathematical expression, and must be the first +operator on the line. + + The HIGH operator takes the result of the mathematical +expression to its immediate left, isolates the high byte of this +value, and places it in the low byte position of a 16 bit word. +The high byte of this word is zeroed. + + The LOW operator takes the result of the mathematical +expression to its immediate left, and places a zero in the high +byte position of this 16 bit value. The low byte of this value is +unchanged. + + HIGH and LOW may be used with any operator or pseudo-op +which generates code or data. + + Examples: + DB HIGH 1234h ; generates 12h + DW LOW 1234h ; generates 0034h + + +Added Feature #3: Large Data Memory Model. + + All Huntsville Microsystems software products which have the +suffix 'L' on their version number (see the signon message issued +by the product in question when it is first started) use the +Large Data memory model. Use of a Large Data model in these +programs means that, when running, all available free memory will +be used for data storage, rather than the previous Small Data +model limit of 64K. + + \ No newline at end of file diff --git a/apple/yzip/ice/hma6502.exe b/apple/yzip/ice/hma6502.exe new file mode 100644 index 0000000..a62c522 Binary files /dev/null and b/apple/yzip/ice/hma6502.exe differ diff --git a/apple/yzip/ice/hmc.exe b/apple/yzip/ice/hmc.exe new file mode 100644 index 0000000..701f185 Binary files /dev/null and b/apple/yzip/ice/hmc.exe differ diff --git a/apple/yzip/ice/hml.add b/apple/yzip/ice/hml.add new file mode 100644 index 0000000..98194a1 --- /dev/null +++ b/apple/yzip/ice/hml.add @@ -0,0 +1,447 @@ + ADDENDUM + + Huntsville Microsystems' Linker v2.00 + + + The following changes and/or additions have been made to the +Huntsville Microsystems' Linker for version 2.00: + + * New switch: "-I". Allows multi-pass library searches. + + * New switch: "-A". Allows control over ASEG writing into + the .HEX file. + + * New switch: "-O". Allows control over writing COMMON + blocks into the .HEX file, and control over the COMMON block + base address. + + * New switch: "-V". Allows overlap of relocatable segments, + and provides better support of the 8051 and 8048 micro- + processors. + + * New switch: "-Y". Allows control over internal .REL file + library requests. + + * New switch: "-U". Allows conversion of all External and + Public labels into upper-case. + + * Deleted: "-B" switch. + + * Support for 8051 BIT space added. + + * Support for 8051/8048 DATA and IDATA spaces added. + + + + HML version 2.00 is a completely restructured successor to +HML v1.0, and provides better support for microprocessors with +overlapping addresses spaces. + + +Using HML v2.00: + + HML v2.00 has a new "Usage" message: + +----------------------------------------------------------------- + +Usage: HML [option(s)] + + options: default: + [d:]filename[.ext] + -l [d:]filename[.ext] + -i [d:]filename[.ext] + + -[n]h [d:][filename][.ext] -h .hex + -[n]m [d:][filename][.ext] -nm + -[n]s [d:][filename][.ext] -s .sym + -[n]x [d:][filename][.ext] -nx + + -[n]a -a + -[n]c [hex address] -c + -[n]d [hex address] -d + -[n]o [hex address] -o + + -[n]v [hex address][:hex address] -nv + -[n]y -y + -[n]u -nu + -f [d:]filename[.ext] + +----------------------------------------------------------------- + +The command line options are as follows: + + [d:]filename[.ext] + + Same as before. + + + -l [d:]filename[.ext] + + Same as before. + + + -i [d:]filename[.ext] + + The '-i' switch names a library file to the + linker, similar the to '-l' switch, but the + library is marked for multi-pass searching. + + A multi-pass library is searched until no more + modules are found in it which satisfy unlinked + external references in modules already pulled into + the linkage. This allows a library with forward + references to be specified on the HML command line + once, and still be linked properly. + + The '-i' switch must be followed by a filename. + + The default extent for a '-i' file is ".REL" . + + + -[n]h [d:][filename][.ext] + + Same as before. + + + -[n]m [d:][filename][.ext] + + Same as before. + + + -[n]s [d:][filename][.ext] + + Same as before. + + + -[n]x [d:][filename][.ext] + + Same as before. + + + -[n]a + + The '-a' option tells the HML whether or not to + write the ASEG into its output .HEX file. ('-a' + write ASEG, '-na' do not write ASEG.) + + + -[n]c [hex address] + + The '-c' option tells HML whether or not to write + the CSEG into its output .HEX file. [hex address] + is used to override the default value for the CSEG + start address. + + + -[n]d [hex address] + + The '-d' option is similar to the '-c' option, but + controls the output of the DSEG. + + + -[n]o [hex address] + + The '-o' option controls the output and start + address of any COMMON blocks which may be present + in the program. Current HMAs do not support the + output of COMMON blocks, so this option is only + useful when linking .REL files produced by + "foreign" cross-assemblers. + + + -[n]v [hex address][:hex address] + + The '-v' option controls overlap (8051) mode. + + When linking 8051 or 8048 .REL files, overlap mode + is automatically enabled. When linking other .REL + files, overlap mode is automatically disabled. + '-v' will enable overlap mode for non-8051 .REL + files, but '-nv' will not disable overlap mode for + 8051 and 8048 .REL files. + + Overlap mode disables the checks for overlapping + CSEG and DSEG addresses, and enables support for + the extra 8051 relocatable segments BIT, DATA, and + IDATA. + + The two hex addresses which can follow the '-v' + option allow control over the start addresses of + the DATA segment, and BIT segment respectively. A + colon (:) is used to seperate the two addresses. + + IDATA space always follows DATA space, and its + start address cannot be overridden. + + Examples: + -v ; Enable overlap mode. + -v 0 ; Start DATA space at 0. + -v :12 ; Start BIT space at 12H. + -v 40:16 ; Start DATA space at 40H, BIT + ; space at 16H + + + -[n]y + + The '-y' option enables/disables HML's honoring of + internal .REL file library requests. Current HMAs + do not support the generation of these internal + library requests, so this option would only be + useful when linking "foreign" .REL files. + + + -[n]u + + The '-u' option controls the 'upperization' of + External and Public label names. When the '-u' + option is enabled, all public and external labels + are converted to upper case before linking. When + '-u' is disabled ('-nu', the default setting), no + labels are converted, and linking proceeds with + all labels used as they naturally occur. + + This option may be useful with some "foreign" .REL + file libraries. + + + -f [d:]filename[.ext] + + Same as before. + + + +File Formats: + + .REL files: + + Unchanged. + + + .HEX files: + + Unchanged. + + + .SYM files: + + Unchanged. + + + .BIN files: + + Deleted. + + + .MAP files: + + The .MAP file format has been altered. + + HML now recognizes seven segments: ASEG, CSEG, DSEG, +COMMON, DATA, IDATA, and BIT. Of these seven, six are +relocatable, with ASEG being the only absolutely addressed +segment. + + The first four segments; ASEG, CSEG, DSEG, and COMMON; +can occur in any Microsoft-formatted .REL file. The last three +segments occur only in HMA8051-produced .REL files. (HMA8048 can +produce DATA and IDATA segments as well.) + + The following format is now used for HML MAP files: + +----------------------------------------------------------------- + + base: 0xnnnn size: 0xnnnn + . + . + . + +Modules: + + Module: cccccc base: 0xnnnn size: 0xnnnn + . + . + . + + Module: cccccc base: 0xnnnn size: 0xnnnn + . + . + . + +Labels: + + cccccc 0xnnnn cccccc 0xnnnn cccccc 0xnnnn + . + . + . + +----------------------------------------------------------------- + + The first lines show the segments actually used during the +linkage, their assigned absolute base addresses, and their +aggregate sizes. + + After the initial status lines comes a report on each module +pulled into the linkage. Each module name is shown, along with a +list of the segments actually used within that module, their +assigned absolute base addresses, and sizes. + + After the module report comes a report on the public labels +used. Three labels are reported on a line. The label name, and +its assigned absolute value are shown. + + 'nnnn' stands for a four-digit hexadecimal number. 'cccccc' +stands for a string of 1-6 ASCII characters. + + + +DATA, IDATA and BIT segments, and the 8051 (and 8048): + + HML v2.00 supports the special relocatable segments DATA, +IDATA and BIT. These three segments are provided to support the +allocation of internal data memory on 8051-family +microprocessors. + + The DATA and IDATA segments are used by 8048-family +microprocessors. + + When linking programs for the 8051 (and 8048), overlap mode +is automatically enabled for HML. When overlap mode goes into +effect, CSEG space is assigned to internal program memory, DSEG +space is assigned to external data memory, BIT space is assigned +to internal bit addressable memory, DATA space is assigned to +internal directly-addressable data memory, and IDATA space is +assigned to internal indirectly-addressable memory. See the 8051 +microprocessor manual for further details on these memory spaces. +ASEG space is generally treated as CSEG, but can be used for +assigning absolute addresses when necessary. + + In overlap mode, HML only allows the ASEG and CSEG spaces to +be written to the output .HEX file. + + BIT space is 128 bits in size, and occupies the bytes +physically located at addresses 20H-2FH in internal 8051 data +memory. DATA space occupies addresses 0-7FH, and must share with +BIT space. IDATA space occupies addresses 0-0FFH and must share +with DATA and BIT space. Note that not all microprocessors in +the 8051 family have the full IDATA space allotment. + + HML assignes addresses in BIT, DATA, and IDATA space as +follows: + + BIT space comes first, and is assigned addresses starting at +20H. When the last bit is allocated, HML adds enough padding +bits to fill out the byte, and then begins assigning DATA space +at the first following unused byte. When all DATA space is +allocated, IDATA bytes are then allocated on top of the DATA +space. + + If BIT, DATA, and/or IDATA spaces overlap, or exceed their +legal physical address space, a warning message is displayed. + + The '-v' option can be used to override the default +assignment of start addresses for BIT and DATA space. IDATA +space always follows DATA space immediately, and its start +address cannot be overridden. + + BIT space can be started on any address from 00-7F. + + DATA space can be started on any address from 00-7F. + + Be wary of setting the DATA start address below 20H. +Addresses below 20H are assigned to the internal register banks +on the 8051 (and to both registers and the stack on the 8048), +and could easily cause problems if proper care is not taken. + + + +Error messages: + + The following error messages are used by HML v2.00. +Changes, if any, from the previous version are noted: + + Error 1 -- ** Out of Memory ** + + Error 2 -- Cannot open: + + Error 3 -- Close error on: + + Error 4 -- No file(s) to link + + Error 5 -- is not a proper .REL file + + Error 6 -- Unimplemented link item in + + Error 7 -- Multiple start addresses + + Warning 8 -- and areas overlap + + This error message has been transformed into a warning. +The named segments have overlapping address spaces, and both are +to be written into the .HEX file. Make sure this is what you +want. HML does not stop. + + Error 9 -- Undefined or Multi-defined lables + + The text of this error message has changed slightly. +Its meaning is the same. + + Error 10 -- Nothing linked + + Error 11 -- Invalid link item (RPN) + + Error 12 -- HML is confused + + +New error messages: + + Error 13 -- Unwritable segment () accessed in File: + + + The named segment is a considered to be a segment which +holds data, and which cannot be initialized by the linker +properly (for example, the DATA segment on the 8051). The .REL +file attempted to initialize data in this segment. + + Error 14 -- Broken chain in File: + + EXTRN references in .REL files are resolved by means of +EXTRN chains. The linkage of one of these chains in the named +file has been broken, probably by overlapping addresses in the +same segment. + + Error 15 -- File: different on pass 2 + + A disk read error has probably occurred. + + Warning 16 -- space overflow + + The named segment has overflowed its physical address +boundaries. HML does not stop. + + + +Notes: + + 1. .REL file labels are still restriced to a maximum of + six characters in length, and are not converted to all + upper case (unless the '-u' option is used). + + 2. HML version 2.00 still supports the special meaning of + the label "$MEMRY". The bytes at $MEMRY and $MEMRY+1 + will be filled in with the value COMMON_base + + COMMON_size at link time, written low-byte-first. + + 3. Uninitialized bytes are no longer written to the .HEX + file. + + 4. HML version 2.00 performs an "incremental link", to + increase efficiency in memory usage. HML completely + links each individual module, and writes its results to + the .HEX file, before going on to the next module. + This allows HML v2.00 to allocate memory on a per- + module basis, rather than a per-segment bases, + resulting in the ability to link larger programs with + less memory. The maximum amount of memory needed by + HML now equals the amount of memory used by the largest + module in the link. + \ No newline at end of file diff --git a/apple/yzip/ice/hml.exe b/apple/yzip/ice/hml.exe new file mode 100644 index 0000000..98f32fe Binary files /dev/null and b/apple/yzip/ice/hml.exe differ diff --git a/apple/yzip/ice/infocom_.dat b/apple/yzip/ice/infocom_.dat new file mode 100644 index 0000000..35deb36 --- /dev/null +++ b/apple/yzip/ice/infocom_.dat @@ -0,0 +1,16 @@ + + +C-IA1-96 SUB-DISK INFIDEL HC-ATARI RM-INFOB 000000 00000000.00 +C-IA2-96 DISK SEASTALKER HC-ATARI INFOCOM RM-INFOB 000000 00000000.00 +C-IA3-96 SUB-DISK FY CUTTHROATS HC-ATARI RM-INFO 000000 00000000.00 +C-IA4-96 SUB-DISK S/S HOLLYWOOD HIJINKS HC-A RM-INFO 000000 00000000.00 +C-IC1-96 SUB-DISK FY LEATHER GODDESS HC-AT RM-INFO 000000 00000000.00 +C-IH1-96 SUB-DISK S/S LURKING HORROR HC-ATAR RM-INFO 000000 00000000.00 +C-IM2-96 SUB-DISK FY WITNESS HC-ATARI RM-INFO 000000 00000000.00 +C-IM3-96 SUB-DISK FY SUSPECT HC-ATARI RM-INFO 000000 00000000.00 +C-IM4-96 SUB-DISK FY BALLYHOO HC-ATARI RM-INFO 000000 00000000.00 +C-IM4-96 SUB-DISK FY BALLYHOO HC-ATARI RM-INFOB 000000 00000000.00 +C-IM5-96 SUB-DISK FY MOONMIST HC-ATARI RM-INFO 000000 00000000.00 +C-IR1-96 SUB-DISK PLUNDERED HEARTS HC-ATARI RM-INFO 000000 00000000.00 +C-IS1-96 SUB-DISK FY STARCROSS HC-ATARI RM-INFO 000000 00000000.00 +C-IS2-96 SUB-DISK FY SUSPENDED ATARI-HC RM-I \ No newline at end of file diff --git a/apple/yzip/ice/io.asm b/apple/yzip/ice/io.asm new file mode 100644 index 0000000..88db27d --- /dev/null +++ b/apple/yzip/ice/io.asm @@ -0,0 +1,1516 @@ + TITLE "Apple ][ YZIP (c)Infocom","--- GAME I/O: APPLE II ---" + + ; -------------- + ; INTERNAL ERROR + ; -------------- + ; ENTRY: ERROR CODE IN [A] + ; EXIT: HA! + +ERRM: DB EOL,"Internal error " +ERRML EQU $-ERRM + +ZERROR: + pha ; save err number + DLINE ERRM, + pla ; get error number + jsr HEXNUM ; print error number + jmp ZQUIT1 ; and hang + + + ; ---- + ; QUIT + ; ---- + +ZQUIT: JSR ZCRLF ; FLUSH BUFFER +ZQUIT1: + DLINE ENDMSG, + lda INFODOS ; in dinky-dos? + beq ZQUIT2 ; nope + jmp (RESET_VECTOR) ; just reset things +; +; re-enable /RAM +; +ZQUIT2: + jsr GETRET ; wait for LOW CRHIGH + ldx DEVCNT ; put device in at end + inx ; point to one past end + stx DEVCNT ; show new count + lda #$BF ; /RAM ID + sta DEVNUM,X ; save it + lda OLDVEC+HI ; restore old vector + sta RAMVEC+HI + lda OLDVEC+LO + sta RAMVEC+LO +; +; now format /RAM +; + lda #3 ; stash into FORMAT parm block + sta $42 ; it goes here, oddly enough + lda #$B0 ; device id for /RAM + sta $43 ; and here it goes + lda #HIGH GAME1FIO ; IO buffer + sta $45 ; this is where it goes + lda #LOW GAME1FIO ; lsb + sta $44 + lda RDBNK2 ; set up card for driver + jsr RAMDRV ; format /RAM + lda RDROM ; get ROM back + + sta TEXTSW+ON ; turn on text + QUIT QUIT_PB +QUIT_PB: + db 4 ; 4 parms + db 0,0,0,0,0,0 ; just zeros +RAMDRV: + jmp (RAMVEC) ; goto RAM driver + +ENDMSG: DB EOL,"End of session." +ENDMSGL EQU $-ENDMSG + +; ------- +; RESTART +; ------- +BOOT_RD: + db 4 + db 0 + dw BORG ; put into where it wants + dw $FFFF ; read lots +BOOTNAMEL: + db 0 ; length will go here +BOOTNAME: ds 15 ; name must be LOW = 15 chars +STMSG: db EOL,"Please insert " +STMSGL equ $-STMSG +SYSTEMNAME: + db ".SYSTEM" ; turn name into .SYSTEM using this +ZSTART: + jsr CLOSE_GAME ; make sure everything is closed + + lda #$FF ; just do a clear -1 + sta ARG1+LO ; done + jsr ZCLR ; to clear screen and set up window 0 +STRTL: + ldy #0 ; fill in the name of .SYSTEM file + ldx GAMEL ; get name of the game length +STRTCL: + lda GAMEL,X ; get the character + sta BOOTNAMEL,X ; save it + iny ; count it + dex ; point to next char + bne STRTCL ; next, please + ldx #0 ; this is the fetch system name counter +STRTSL: + lda SYSTEMNAME,X ; get system char + sta BOOTNAME,Y ; save in my boot name + iny ; next + inx + cmp #'M' ; this is last char in .SYSTEM + bne STRTSL ; so go get next one + sty BOOTNAMEL ; save length + lda #LOW BOOTNAMEL ; now, set open file name + sta OPEN_FILE+OP_PATHNAME+LO + lda #HIGH BOOTNAMEL + sta OPEN_FILE+OP_PATHNAME+HI + lda #'1' ; set disk name to disk #1 + sta SAVENUM ; and this is where it goes + jsr OPEN_GAMEF ; and try and open it + + lda OPEN_FILE+OP_REFNUM ; get ref num + sta BOOT_RD+RD_REFNUM ; save ref num + sta CLOSE_PB+CL_REFNUM + READ BOOT_RD ; read in boot system + bcc ZSTRTX ; okay, everything is fine + jmp DISK_FATAL ; die otherwise +ZSTRTX: + CLOSE CLOSE_PB ; and close it up + jmp BORG ; and go to it + + ; -------------------------------- + ; RETURN RANDOM BYTES IN [A] & [X] + ; -------------------------------- + +RANDOM: inc RNUM1 + dec RNUM2 + LDA RNUM1 ; GENERATED BY MONITOR GETBYT + ADC RAND1 + TAX + LDA RNUM2 + SBC RAND2 + STA RAND1 + STX RAND2 + RTS + + + ; ------------------- + ; Z-PRINT A CHARACTER + ; ------------------- + ; ENTRY: ASCII CHAR IN [A] + ; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, + ; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN + ; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME + ; (DIROUT CHANGES 6/24/85) + +COUT: + sta IOCHAR ; HOLD IT A SEC + ldx TABLEF ; OUTPUT TO TABLE? + beq COUT1 ; NO + ldx FMTTBL ; formatted table? + bne COUT5 ; yes, so just do it normal + jmp TBLOUT ; just put into table +COUT1: + ldx SCREENF ; OUTPUT TO SCREEN? + bne COUT5 ; YES + ldx SCRIPTF ; OUTPUT TO PRINTER? + bne COUT5 ; YES + rts ; NO, SO DONE +COUT5: + lda IOCHAR ; RETRIEVE CHAR + bmi COUT2 ; highlight chars have no width + cmp #EOL ; IF ASCII EOL, + bne COUT0 + + jmp ZCRLF ; DO IT +COUT0: + bcc CEX ; don't count control chars + + tax ; use char as index + lda FONTFLG ; get which font we be using + beq COUTF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne COUTF2 ; okay, now do add +COUTF1: + lda CHWID,X ; get width of char +COUTF2: + clc ; get ready for add + adc LENGTH+LO ; ADD LINE LENGTH COUNTER + sta LENGTH+LO ; update length + bcc COUT0C ; no wrap + inc LENGTH+HI ; okay, wrap then +COUT0C: + lda LENGTH+HI ; get MSB + cmp XSIZE+HI ; check MSB first + bcc COUT2 ; no need to check lsb + bne COUT00 ; XSIZE LOW LENGTH? + + lda LENGTH+LO ; check LSB + cmp XSIZE+LO ; END OF SCREEN LINE? + bcc COUT2 ; haven't reached the end if XSIZE HIGH LENGTH +COUT00: + ldy WRPFLG ; are we wrapping + beq CEX ; no, so truncate + ldx CHRCNT ; get character count + lda IOCHAR ; get the character + sta LBUFF,X ; save current char in buffer + jsr FLUSH ; YES, FLUSH THE LINE + rts ; done then +COUT2: + ldx CHRCNT ; GET LINE POINTER + lda IOCHAR ; get char back + sta LBUFF,X ; ADD CHAR TO BUFFER + inc CHRCNT ; and point to next CHRCNT +CEX: + rts + + ; --------------- + ; OUTPUT TO TABLE + ; --------------- +; +; this one just puts a char into the table +; +TBLOUT: + tax ; HOLD CHAR A SEC. +; +; figger out length of line in there +; + lda FONTFLG ; get which font we be using + beq TBLOUT1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne TBLOUT2 ; okay, now do add +TBLOUT1: + lda CHWID,X ; get width of char +TBLOUT2: + clc ; add width + adc ZBEGIN+ZTWIDTH+1 ; to current line width + sta ZBEGIN+ZTWIDTH+1 ; save current width + bcc TBLOUT3 ; no wrap + inc ZBEGIN+ZTWIDTH+0 ; wrap, then dammit +TBLOUT3: +; +; PUT BYTE IN TABLE AT CURRENT OFFSET +; + lda DIRITM+LO ; ADD IN OFFSET + clc + adc DIRTBL+LO + sta SPCL ; and make it lo part + lda DIRITM+HI + adc DIRTBL+HI + jsr SETPC ; set the PC + sta SPCH ; and this is high part + sty SPCBNK ; and the bank + txa ; PICK UP ASCII CHAR + jsr STASHB ; and save it +; +; SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER +; + inc DIRITM+LO ; INC OFFSET TO NEXT BYTE + bne TBLRTS + inc DIRITM+HI +TBLRTS: + rts +; +; PUT LBUFF IN TABLE AT CURRENT OFFSET +; +TBLRTN: + lda DIRITM+LO ; get where we are + clc + adc DIRTBL+LO ; ADD IN OFFSET + sta SPCL ; and make it lo part + sta FPCL ; save for later usage + lda DIRITM+HI ; get hi part + adc DIRTBL+HI + jsr SETPC ; set the PC + sta SPCH ; and this is high part + sta FPCH ; saving + sty SPCBNK ; and the bank + sty FPCBNK ; and here too + lda #0 ; start counter off at zero + sta J ; use J + sta K+HI ; this will be line length + sta K+LO ; both parts, please + jsr NEXTSPC ; point past the counter +TBLOOP: + ldy J ; get offset + lda LBUFF,Y ; get char + tax ; save char + bmi TBLP1 ; don't count hi light chars + cmp #SPACE ; see if less than a space + bcc TBLP1 ; no width if LOW $20 + tax ; use char as index + + lda FONTFLG ; get which font we be using + beq TBLF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne TBLF2 ; okay, now do add +TBLF1: + lda CHWID,X ; get width of char +TBLF2: + clc ; add width + adc K+LO ; to current line width + sta K+LO ; save current width + bcc TBLP1 ; no wrap + inc K+HI ; wrap, then dammit +TBLP1: + txa ; get char back + jsr STASHB ; and save it + jsr NEXTSPC ; next table entry + inc J ; point to next char + dec CHRCNT ; decrement counter + bne TBLOOP ; get next one +; +; now fill with necessary spaces +; + lda FONTFLG ; first, set up width to be added + beq TBLSPF1 ; must be variable width font + lda #MONOFONT_W ; get mono width + bne TBLSPF2 ; okay +TBLSPF1: + ldx #SPACE ; get space index + lda CHWID,X ; okay +TBLSPF2: + sta ARG8 ; use temporarily +TBLSP: + lda K+LO ; get how big line is + clc ; add in space + adc ARG8 ; pick up space width + sta K+LO ; saved + bcc TBLSP1 ; no wrap? + inc K+HI ; yes, wrapping +TBLSP1: + lda XSIZE+HI ; check against end + cmp K+HI ; compare against max width + bcc TBLSPX ; all done then + bne TBLSP2 ; no need to check if LOW HIGH + lda XSIZE+LO ; check LSB + cmp K+LO ; well? + bcc TBLSPX ; all done then +TBLSP2: + lda #SPACE ; get it + jsr STASHB ; save it + jsr NEXTSPC ; point to next one + inc J ; count it + bne TBLSP ; and continue +TBLSPX: + lda #0 ; show end of table + sta LENGTH+LO ; clear out line length too + sta LENGTH+HI ; and hi part too + jsr STASHB ; marked with a zero + jsr FP2SP ; have SPC point to beginning + lda J ; get how many chars are there + jsr STASHB ; save at beginning of line + inc J ; count counter in offset + lda J ; get J back + clc ; add in where we were + adc DIRITM+LO ; okay with lo part + sta DIRITM+LO ; save it + lda DIRITM+HI ; and now the hi part + adc #0 ; pick up carry, maybe + sta DIRITM+HI ; and save it + rts + + ; ------------------- + ; FLUSH OUTPUT BUFFER + ; ------------------- + ; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: + lda #SPACE ; SPACE CHAR + stx OLDEND ; SAVE CURRENT END OF LINE +FL0: + cmp LBUFF,X ; FIND LAST SPACE CHAR + beq FL1 ; IN THE LINE + dex + bne FL0 ; IF NONE FOUND, + ldx CHRCNT ; FLUSH ENTIRE LINE + dex ; minus last one +FL1: + stx OLDLEN ; SAVE OLD LINE POS HERE + stx CHRCNT ; MAKE IT THE NEW LINE LENGTH + + lda TABLEF ; are we doing table I/O? + beq FL11 ; nope + lda FMTTBL ; formatted table + bne FL11 ; yup, so handle normally + jsr TBLRTN ; YES, DO IT + jmp FL12 ; so refill line +FL11: + jsr ZCRLF ; PRINT LINE UP TO LAST SPACE +; +; START NEW LINE WITH REMAINDER OF OLD +; +FL12: + ldx OLDLEN ; GET OLD LINE POS + ldy #0 ; START NEW LINE AT BEGINNING +FL2: + inx + cpx OLDEND ; CONTINUE IF + bcc FL3 ; INSIDE of end of line + beq FL3 ; or at end of line + sty CHRCNT + rts +FL3: + lda LBUFF,X ; GET CHAR FROM OLD LINE + sta LBUFF,Y ; MOVE TO START OF NEW LINE + bmi FL4 ; don't count hi light chars + cmp #SPACE ; don't count control chars + bcc FL4 ; okay + txa ; save current x + pha ; saved + lda FONTFLG ; get which font we be using + beq FLSF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne FLSF2 ; okay, now do add +FLSF1: + lda LBUFF,X ; get char back + tax ; make index + lda CHWID,X ; get width of char +FLSF2: + clc ; get ready for add + adc LENGTH+LO ; okay, now add char width + sta LENGTH+LO ; save new length + pla ; get old X back + tax ; okay + bcc FL4 ; no wrap + inc LENGTH+HI +FL4: + iny ; UPDATE # OF chars in NEW LINE + bne FL2 ; (ALWAYS) + + + ; --------------- + ; CARRIAGE RETURN + ; --------------- + +ZZCRLF: + ldx TABLEF ; OUTPUT TO TABLE? + beq ZCRLF ; NO +; +; if putting a LOW CRHIGH into table, just add to line buffer and flush +; + lda #EOL ; get carriage return char + ldy CHRCNT ; add to lbuff + sta LBUFF,Y ; got it + inc CHRCNT ; now flush it + jsr TBLRTN ; YES, DO IT (TBL ONLY) + jmp ZCRLFX ; git out +ZCRLF: + ldx CHRCNT ; how far have we gone + lda #EOL ; get carriage return char + sta LBUFF,X ; END OF CURRENT LINE + inc CHRCNT ; UPDATE LINE LENGTH + jsr LINOUT ; DISPLAY LINE + +; +; now check about line count +; + lda #0 + sta CHRCNT ; AND RESET LINE COUNT + sta LENGTH+LO ; okay + sta LENGTH+HI ; okay + + jsr CHKFNC ; CHECK FOR CR FUNCTION (XZIP) + + lda SCREENF ; CHECK IF DISPLAYING TO SCREEN + beq ZCRLFX ; NO, GO HANDLE IF PRINTING + lda SCRLFLG ; is it a scrolling window? + beq ZCRLFX ; nope, so no more + inc LINCNT ; NEW LINE GOING OUT + + ldx LINCNT ; IS IT TIME TO + cpx MAXLINES ; PRINT "MORE" YET? + bne ZCRLFX ; NO, CONTINUE + + lda #1 ; leave one line from last screen, and input line + sta LINCNT ; RESET LINE COUNTER + lda LEFTMRG ; SET LEFT MARGIN + sta SCRCX + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay + DLINE MORE, +WAIT: + jsr GETKEY ; wait for key please + lda LEFTMRG ; move back to left margin + sta SCRCX ; okay + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay + jsr CLREOL ; and clear to end of line +ZCRLFX: + lda #0 + sta CHRCNT ; AND RESET LINE COUNT + sta LENGTH+LO ; okay + sta LENGTH+HI + rts +LINOUT: + ldy CHRCNT ; IF BUFFER EMPTY, + beq LINEX ; DON'T PRINT ANYTHING + sty PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + lda SCREENF ; DISPLAY TO SCREEN? + beq LOUT1 ; NO, GO CHECK IF PRINT + ldx #0 ; SEND CONTENTS OF [LBUFF] +LOUT: + lda LBUFF,X ; TO SCREEN + jsr CHAR + inx + dey + bne LOUT + jsr DISP_LINE ; make sure line gets printed +LOUT1: JSR PPRINT ; PRINT [LBUFF] IF ENABLED +LINEX: + rts ; AND RETURN +; +; CHECK IF THERE IS A PENDING FUNCTION CALL ASSOCIATED WITH LOW CRHIGH 'S +; +CHKFNC: + ldy #WINCRC+HI ; get function offset + lda (WINDOW),Y ; IF NULL IGNORE + dey ; point to lo part + ora (WINDOW),Y + beq CHKOUT + + lda (WINDOW),Y ; DECR COUNTER + sec + sbc #1 + sta (WINDOW),Y + iny + lda (WINDOW),Y ; work on hi part + sbc #0 ; pick up carry + sta (WINDOW),Y ; save it + dey + ora (WINDOW),Y ; if NULL NOW, CALL FCN + bne CHKOUT + + ldy #WINCRF+LO ; pointing to routine + lda (WINDOW),Y ; get lo part + sta J+LO ; and save in J + iny ; point to hi part + lda (WINDOW),Y ; got it + sta J+HI + jsr INTCLL ; DO FUNCTION CALL +CHKOUT: + rts + + + ; ---------------------- + ; UPDATE THE STATUS LINE + ; ---------------------- + ; NOT APPLICABLE IN EZIP. + +ZUSL: RTS + +; ------ +; BUFOUT +; ------ +; ENTER: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE +; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO +; +; shouldn't need this in YZIP ?! +; +ZBUFOUT: + rts +; +; CLEAR OUTPUT BUFFER BEFORE DOING ANYTHING FANCY +; +CLRBUF: + jsr LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) + ldx #0 + stx CHRCNT + rts + + ; ------ + ; DIROUT + ; ------ + ; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT + ; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT + ; MULTIPLE DEVICE USAGE IS POSSIBLE. + +SAVEXSIZE: db 0,0 ; for formatted table saving + +ZDIRT: + ldx ARG1+LO + bmi DIRRES ; NEGATIVE VALUE, DESELECTING + dex + beq DIR1 ; 1 = SET OUTPUT TO SCREEN + dex + beq DIR2 ; 2 = SCRIPTING + dex + beq DIR3 ; 3 = TABLE + rts ; INVALID VALUE +DIRRES: + inx + beq DRES1 ; -1 = RESET TO SCREEN + inx + beq DRES2 + inx + beq DRES3 + rts ; INVALID VALUE, JUST LEAVE +DIR1: + jsr CLRBUF + lda #1 ; turn screen on + sta SCREENF + rts +DRES1: + jsr CLRBUF + lda #0 + sta SCREENF ; 0, TURN SCREEN OFF + rts +DIR2: + inx + stx SCRIPTF ; SET SCRIPT FLAG ON + lda ZBEGIN+ZFLAGS+1 ; SET GAME FLAG ALSO + ora #%00000001 + sta ZBEGIN+ZFLAGS+1 + lda PSTAT ; CHECK IF PRINTER ALREADY INIT'D + bne DIR2A + jsr PCHK ; NO, GO DO IT +DIR2A: + rts ; YES, READY TO LEAVE +DRES2: + stx SCRIPTF ; TURN PRINTER OFF + lda ZBEGIN+ZFLAGS+1 ; AND TURN OFF GAME FLAG TOO + and #%11111110 + sta ZBEGIN+ZFLAGS+1 + rts +DIR3: + inx + stx TABLEF ; TURN TABLE OUTPUT FLAG ON + jmp START_TABLE ; and set things up +DRES3: + lda TABLEF ; IF OFF ALREADY + beq OUT3 ; LEAVE AS IS + + stx TABLEF ; TURN TBL OUTPUT OFF + + lsr ZBEGIN+ZTWIDTH+0 ; /4 to get # of pixels + ror ZBEGIN+ZTWIDTH+1 + lsr ZBEGIN+ZTWIDTH+0 + ror ZBEGIN+ZTWIDTH+1 + + lda FMTTBL ; did we do a formatted table? + bne DRESFT ; yes, so fix things +; +; now put count into table +; + lda DIRTBL+LO ; and put count into second byte of table + sta SPCL ; points to low par + lda DIRTBL+HI ; get page + jsr SETPC ; okay, page and bank + sta SPCH + sty SPCBNK + lda DIRITM+LO ; (2 LESS THAN [DIRITM]) + sec + sbc #2 + sta DIRITM+LO ; save this new count + bcs RESET0 + dec DIRITM+HI ; wrapped downwards +RESET0: + lda DIRITM+HI ; get hi part + jsr STASHB ; saved that count + jsr NEXTSPC ; and point to lo part + lda DIRITM+LO ; and get lo part + jsr STASHB ; and save it + rts ; done +DRESFT: + lda CHRCNT ; anything in buffer? + beq DRES31 ; nope + jsr TBLRTN ; then fill out last line +DRES31: + lda SAVEXSIZE+LO ; get old xsize back + sta XSIZE+LO ; restored + lda SAVEXSIZE+HI + sta XSIZE+HI + lda #0 ; reset this flag too + sta FMTTBL ; cleared +OUT3: + rts +; +; set things up for doing table output +; +START_TABLE: + + lda ARG2+HI ; SET UP TBL + sta DIRTBL+HI + lda ARG2+LO ; TO STORE CHARS IN + sta DIRTBL+LO + lda #2 + sta DIRITM+LO + lda #0 + sta DIRITM+HI + sta ZBEGIN+ZTWIDTH+1 ; clear width count + sta ZBEGIN+ZTWIDTH+0 +; +; check to see if we have formatted table +; + lda NARGS ; get # of arguments + cmp #3 ; if == 3, then we wrap it + beq DIR30 ; nope + rts ; all done other wise +DIR30: + stx FMTTBL ; set formatted table flag + lda XSIZE+LO ; save the current XSIZE + sta SAVEXSIZE+LO ; okay, did it + lda XSIZE+HI ; and MSB + sta SAVEXSIZE+HI ; okay + lda ARG3+LO ; this is the actual amount + ldx ARG3+HI ; get interesting arg + bmi DIRFT1 ; check for negative width + jsr SETWJ ; get the window offset + ldy #WINXSZ ; get its XSIZE + lda (J),Y ; got it + sta XSIZE+LO ; aren't we nice + bne DIR31 ; jump to end +DIRFT1: + eor #$FF ; turn to a positive number + sta XSIZE+LO ; save it + inc XSIZE+LO ; to make it right +DIR31: + lda #0 ; items starts at zero + sta DIRITM+LO ; okay + sta XSIZE+HI ; clear out highness + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + rts + + ; ------ + ; CURSET + ; ------ + ; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW + ; AND AT COLUMN (ARG2) in (optional) window ARG3 + +ZCURST: + jsr CLRBUF ; CLEAR OUT ANY NON DISPLAYED TEXT 1ST + + dec ARG1+LO ; zero base both args + dec ARG2+LO ; thanx + + lda NARGS ; check for id + cmp #3 ; if 3 args, then window ID specified + beq ZCURS1 ; not 3, so use current window + + lda CURWIN ; show current window being done + sta ARG3+LO ; thanx +ZCURS1: + lda ARG3+LO ; get window ID + jsr SETWJ ; put address into J + lda ARG1+LO ; GET LINE + ldy #WINHGHT ; check against height + cmp (J),Y ; too far? + bcc ZCURS3 ; no, so use it + lda (J),Y ; got max out + tay ; but one too far + dey ; all better now + tya ; back to A +ZCURS3: + clc ; get ready for add + ldy #WINTOP ; do y pos first + adc (J),Y ; add in top to get absolute value + ldy #WINY ; get y pos offset + sta (J),Y ; save here + lda ARG2+LO ; GET COLUMN + ldy #WINWID ; check against width + cmp (J),Y ; is it to for right (like Reagan?) + bcc ZCURS4 ; nope, must be dukakis + lda (J),Y ; get max + tay ; for going down one + dey ; done it + tya ; back to A for usefullness +ZCURS4: + ldy #WINLEFT ; get left edge to absolute it + adc (J),Y ; carry clear from above + ldy #WINX ; this is the x pos + sta (J),Y ; into the structure +; +; now check for current window again, move cursor anyway +; + jmp GET_CURSOR ; get cursor pos from WINDOW + + ; ------ + ; CURGET + ; ------ + +ZCURGT: + jsr CLRBUF ; flush the buffer + + jsr SAVE_CURSOR ; save the current position + + dec NARGS ; see how many arguments + beq ZCURG1 ; use main window + lda ARG2+LO ; get window id + bpl ZCURG2 ; and figger it out +ZCURG1: + lda CURWIN ; use current window +ZCURG2: + jsr SETWJ ; make J point to right place + + lda ARG1+HI ; get table address + jsr SETPC ; get real address in memory + sty SPCBNK ; set bank + sta SPCH ; and page + lda ARG1+LO ; get table offset + sta SPCL ; and save it + + lda #0 ; zero hi part of Y pos + jsr STASHB ; and save it + jsr NEXTSPC ; and point to next one + jsr FETCHCY ; Fetch Y pos + jsr STASHB ; and save it + jsr NEXTSPC +; +; now for the X pos + lda #0 ; zero top byte of x pos + jsr STASHB + jsr NEXTSPC + jsr FETCHCX ; and now the X pos, and return + jmp STASHB ; and stash it away + +; +; FETCHCY - get the relativized Y pos into [A] +; J points to window structure +FETCHCY: + ldy #WINY ; get Y pos of window's cursor + lda (J),Y ; got it + ldy #WINTOP ; need to de-absolute it + sec ; get ready for sub + sbc (J),Y ; get relative pos + tax ; for 1 basing it + inx ; 1 align it + txa ; and put for save + rts +; +; FETCHCX - get relativized X pos into [A] +; J points to window structure +FETCHCX: + ldy #WINX ; get X pos of cursor + lda (J),Y ; got it + ldy #WINLEFT ; relativize it + sec ; get ready for sub + sbc (J),Y ; subtract left edge + tax ; for incing + inx ; 1 ALIGN IT + txa + rts + + ; ----- + ; DIRIN + ; ----- + ; NOT YET IMPLEMENTED, BUT RESERVED + +ZDIRIN: RTS + +; +; SETWJ - set up J to point to window structure for window ID in [A] +; +SETWJ: + tay ; check for -3 (current window) + bpl SWJ1 ; nope, window ID here + lda CURWIN ; -3 means current window +SWJ1: + asl A ; shift to make word index + tay ; and now make index + lda WINTABLE,Y ; get lo part of window struct address + sta J+LO ; and save it + lda WINTABLE+1,Y ; here's the hi part + sta J+HI ; prove it + rts + + ; ----- + ; ERASE + ; ----- + +ZERASE: + lda ARG1+LO + cmp #1 + bne ZEROUT ; INVALID + + jsr CLRBUF + jmp CLREOL ; CLEAR TO END OF LINE +ZEROUT: + rts + +; ----- +; CLEAR the current window +; ----- +SAVEXY: dw 0 + +ZCLR: + jsr CLRBUF ; flush the current buffer + jsr SAVE_CURSOR ; save the cursor pos + + lda ARG1+LO ; CHECK WHAT TO DO + bpl CLRW ; a particular window + cmp #$FD ; -3 means current window + beq CLRW ; so just handle it regular + cmp #$FE ; clear with nothing social + beq CLRCLS ; just clear the screen +; +; UNSPLIT SCREEN & CLEAR IT +; + lda #0 ; just use SPLIT 0 + sta ARG1+LO ; as if called normally + jsr ZSPLIT ; do the split +; +; just clear the entire screen +; +CLRCLS: + lda #0 ; clear the entire screen + sta CLSLEFT ; from top left + sta CLSTOP + lda #MAXWIDTH ; to bottom right + sta CLSWIDTH + lda #MAXHEIGHT + sta CLSHEIGHT + + jsr CLS ; do the clear screen (no cursor movement) + lda ARG1+LO ; check for -2 + bmi ZCLRX ; it is, don't move cursor + bpl ZCLEARX ; move cursor +CLRW: + jsr SETWJ ; get me the window pointer + ldy #WINTOP ; step thro to get data + lda (J),Y ; TOP + sta CLSTOP ; save for clear + iny ; point to left + lda (J),Y ; get it + sta CLSLEFT ; tell CLS + iny ; now at WINHGHT + lda (J),Y ; got it + sta CLSHEIGHT ; save for clear + iny ; now at WINWID + lda (J),Y ; get height + sta CLSWIDTH ; saved + jsr CLS ; screen cleared +; +; now move the cursor to 1,1, if not == -2 +; +ZCLEARX: + lda ARG1+LO ; check arg + jsr SETWJ ; make sure J still points to window + ldy #WINTOP ; put at top left of window + lda (J),Y ; get top + ldy #WINY ; and make it the y pos + sta (J),Y ; of the cursor + ldy #WINLEFT ; and the left is + lda (J),Y ; the + clc ; add in the left margin + ldy #WINLM ; here's the left margin + adc (J),Y ; added it + ldy #WINX ; x pos of the + sta (J),Y ; cursor + lda #0 ; and clear out line count + ldy #WINLCNT ; line count + sta (J),Y ; okay + ldy #WINLLEN ; and length of current line + sta (J),Y ; okay + iny ; do hi + sta (J),Y ; okay +ZCLRX: + jmp GET_CURSOR ; restore the cursor pos for the current window + +; ------ +; PRINTT +; ------ +; PRINT A TABLE TO SCREEN, ARG1 = # OF BYTES +; ARG2 = WIDTH, ARG3 (DEF = 1) = HEIGHT + +OLDCHZ EQU I+LO ; EASIER TO READ +OLDEHZ EQU I+HI +OLDCVT EQU L+LO + +TBL_LEN DW 0 ; save for length + +ZPRNTT: +; +; make sure the buffer is empty, thanks +; + jsr CLRBUF + + lda ARG1+LO ; USE GETBYT AS TBL COULD + sta MPCL ; BE ANYWHERE + lda ARG1+HI + sta MPCM + lda #0 + sta MPCH + jsr VLDMPC + + lda ARG2+LO ; ONLY A BYTE AS MAX + beq PTTDUN ; QUIT NOW IF NULL + + sta TBLWIDTH ; width of the table + sta TBLCNT ; start counter off at width + dec NARGS ; count down to 1 (maybe) + lda NARGS + cmp #1 + beq NOHIGHT ; DEFAULT HEIGHT IS 1 + lda ARG3+LO ; get passed height +NOHIGHT: + sta TBLHEIGHT ; height of the table (at least 1) + lda SCRCX + sta OLDEHZ + sec ; subtract left margin to get how long line is + sbc LEFTMRG ; okay we did that + sta TBL_LEN+LO ; this is how big line is too + lda #0 ; clear MSB + asl TBL_LEN+LO ; *2 + rol A + asl TBL_LEN+LO ; *4 + rol A + sta TBL_LEN+HI ; save +PTTLP: + jsr GETBYT ; GET A BYTE + jsr COUT ; and send it out + + dec TBLCNT ; one more byte done + bne PTTLP + dec TBLHEIGHT ; IF DONE ALL LINES + beq PTTDUN ; LEAVE + + jsr CLRBUF ; so send out stuff that's there + + lda OLDEHZ ; get old x pos + sta SCRCX ; and restore it + lda #1 ; show cursor changed + sta CURSFLG ; okay + lda SCRCY ; point to next line + clc ; by adding in the font height + adc #FONT_H ; okay, goody + sta SCRCY ; and here we are + + lda TBL_LEN+HI ; reset length + sta LENGTH+HI ; hi part + lda TBL_LEN+LO ; lo part + sta LENGTH+LO ; just a lo + + lda TBLWIDTH ; RESET COUNT + sta TBLCNT ; thanx + bne PTTLP ; GO DO NEXT LINE +PTTDUN: + jsr CLRBUF ; send out last bit + rts +;-------------- +; ZPRINTF +;-------------- +; ZPRINTF - print a formatted table +; +ZPRINTF: + lda ARG1+LO ; USE GETBYT AS TBL COULD + sta MPCL ; BE ANYWHERE + lda ARG1+HI + sta MPCM + lda #0 + sta MPCH + jsr VLDMPC + + lda SCRCX ; save the X pos + sta OLDEHZ ; saved here +ZPFL1: + jsr GETBYT ; get the length byte + beq ZPFX ; no more if == 0 + sta TBLWIDTH ; keep track of it +ZPFL2: + jsr GETBYT ; now get the char byte + jsr CHAR ; and send it yt + dec TBLWIDTH ; any more? + bne ZPFL2 ; ayyup + + jsr DISP_LINE ; make sure line goes out + lda OLDEHZ ; reset a few things + sta SCRCX ; including x pos + lda #1 ; show cursor changed + sta CURSFLG ; okay + lda SCRCY ; point to next line + clc ; by adding in the font height + adc #FONT_H ; okay, goody + sta SCRCY ; and here we are + bne ZPFL1 ; and do it again +ZPFX: + rts +; ------------ +; SET NEW FONT +; ------------ + +; Font 4 is mono-spaced font. + +ZFONT: + dec NARGS ; did we get passed a window id? + bne ZFNTWID ; yup + lda #$FD ; -3 means current window + sta ARG2+LO ; make it the arg2 then +ZFNTWID: + lda ARG2+LO ; get window we are interested in + jsr SETWJ ; make [J] point to window struct + + lda ARG1+LO ; check for + cmp #1 ; font 1 + beq ZFNT1 ; or + cmp #4 ; font 4 (monospace) + bne ZFBAD ; nope, so die +; +; font 4 is the monospaced font +; + ldy #WINFSIZE ; point to width + lda #MFONT_W ; get game width + sta (J),Y ; store the width + lda #3 ; set font ID + bne ZFNTEX ; all done +ZFNT1: + ldy #WINFSIZE ; point to width + lda #FONT_W ; get game width + sta (J),Y ; store the width + lda #0 ; set font ID +ZFNTEX: + ldy #WINFONT ; set font + pha ; save font id + lda (J),Y ; get old font id + tax ; save old font id + pla ; get new one back + sta (J),Y ; save in structure + lda (WINDOW),Y ; get current window font + beq ZFNT0X ; set flag with zero + lda #MONOFONT_W ; get width of mono spaced font +ZFNT0X: + sta FONTFLG ; and set flag too + inx ; make it say correct font ID for game + txa ; put in A for put val + ldx #0 ; clear X + jmp PUTVAL ; and return it +ZFBAD: + jmp RET0 ; TELL IT DOESN'T WORK +; ------------------------------ +; FETCH A LINE OF INPUT FOR READ +; ------------------------------ +; ENTRY: Relative READ table address in RDTBL1 +; EXIT: # CHARS READ IN [A] +SV_SPC: ds 3 ; save SPC here for later usage + +INPUT: + jsr CLRBUF ; FLUSH [LBUFF] + ldy #0 ; RESET LINE COUNT + sty I+HI ; clear local variables + sty I+LO + sty J+HI + sty J+LO + sty BRKCHR ; init break char + sty LINCNT ; RESET LINE COUNT +; +; check for new TCHARS table +; + lda ZBEGIN+ZTCHAR+1 ; so check lower byte for different tchars + cmp SVTCHAR+LO ; is it different? + bne IO_DOT ; ayyup, get new one + lda ZBEGIN+ZTCHAR ; get current TCHARS hi part + cmp SVTCHAR+HI ; is it the same as saved one? + + beq IOj ; yes, so don't muck with it +IO_DOT: + jsr DO_TCHARS ; new table, so copy it over +; +; now set up FPC +; +IOj: + lda RDTBL1+HI ; get page of table + jsr SETPC ; and get me the memory page and bank + sta FPCH ; save page + sty FPCBNK ; and bank + lda RDTBL1+LO ; and get offset + sta FPCL ; set up FPC/SPC + jsr FETCHB ; get length of line + tay ; for dec'ing + dey ; don't count the offset byte + dey ; and leave room for terminator + sty CHRMAX ; and save it + jsr NEXTFPC ; point to next byte + jsr FETCHB ; get current offset into buffer + sta CHARCNT ; save how many chars out there + jsr NEXTFPC ; point to beginning of data buffer +; +; now finish setting up saved SPC +; + ldx #2 +INSVCL: + lda FPC,X ; get byte to saved for use later on + sta SV_SPC,X ; it is saved here + dex + bpl INSVCL ; next! +; +; now copy current buffer into local buffer +; + lda CHARCNT ; make sure we have some + beq CPIOLX ; nope, none in there now + ldx #0 ; start at first char +CPIOL: + jsr FETCHB ; get a char + sta LBUFF,X ; save char + jsr NEXTFPC ; point to next one + inx ; next char + cpx CHARCNT ; got them all yet? + bne CPIOL ; nope +CPIOLX: + jsr CHKTME ; START TIME LIMIT +; +; this is the get-a-key-and-whack-on-it loop +; +INLOOP: + lda I+HI ; is there a time? + beq INPL1 ; nope + jsr TIMIN ; do timed input + bcc INPL2 ; got a char, process it + jmp LEXBAD ; timed out with nothing there! +INPL1: + jsr GETKEY ; let apple do the walking +INPL2: + jsr ISTCHR ; CHECK IF IT'S AN ACCEPTABLE TERMINATOR KEY + bcs NOTYET + + sta BRKCHR + cmp #EOL ; IF EOL PUT TO SCREEN + beq ENDLIN + jmp ENDIN ; ELSE JUST END +NOTYET: + tay ; check for functions keys that aren't + bmi CBAD ; terminators and feep if it is + cmp #EOL ; EOL? + beq ENDLIN ; LINE DONE IF SO + cmp ESCAPE ; don't allow escape char's thru + beq CBAD ; okay, I won't + + cmp #BACKSPACE ; BACKSPACE? + beq BACKUP ; SPECIAL HANDLING + + ldy CHARCNT ; where do we put char? + cpy CHRMAX ; are we filled up? + bcs CBAD ; boy, am i full + + pha ; save it + tax ; use as index + lda LENGTH+LO ; GET LINE LENGTH COUNTER + clc ; get ready for add + adc CHWID,X ; add width + sta LENGTH+LO ; update length + bcc INP0C ; no wrap + inc LENGTH+HI ; okay, wrap then +INP0C: + lda LENGTH+HI ; get MSB + cmp XSIZE+HI ; check MSB first + bcc NOIOWRAP ; no need to check lsb + lda LENGTH+LO ; check LSB + cmp XSIZE+LO ; END OF SCREEN LINE? + bcc NOIOWRAP ; haven't reached the end if XSIZE HIGH LENGTH +INP1C: + jsr ZCRLF ; go back to beginning of next line + pla ; get char back + pha ; save again + tax ; use as index + lda LENGTH+LO ; GET LINE LENGTH COUNTER + clc ; get ready for add + adc CHWID,X ; add width + sta LENGTH+LO ; update length + bcc NOIOWRAP ; no wrap + inc LENGTH+HI ; okay, wrap then +NOIOWRAP: + pla ; get char back + ldx CHARCNT ; for putting in line buffer + sta LBUFF,X ; and save it in case we goto printer + jsr CHAR ; SEND TO SCREEN + jsr DISP_LINE ; show char + inc CHARCNT ; NEXT POSITION IN LINE + jmp INLOOP ; NO, GET ANOTHER CHAR +; +; HANDLE BACKSPACE +; +BACKUP: + ldx CHARCNT ; if == 2 then empty + beq CBAD ; JMP to beeping + dex ; get rid of char + stx CHARCNT ; saved + lda LBUFF,X ; get char we are interested in + tax ; put in x + + lda LENGTH+LO ; GET LINE LENGTH COUNTER + sec ; get ready for sub + sbc CHWID,X ; sub width + sta LENGTH+LO ; update length + bcs BCKP1 ; no wrap + dec LENGTH+HI ; okay, wrap then +BCKP1: + lda #BACKSPACE ; so do erasing backspace + jsr CHAR + jmp INLOOP +CBAD: + jsr BEEP ; ELSE SCREAM WITH PAIN + jmp INLOOP ; AND WAIT FOR SOMETHING BETTER +; +; HANDLE END OF LINE KEY +; +ENDLIN: + sta BRKCHR + lda #EOL ; get EOL char + jsr CHAR ; SEND EOL TO SCREEN + lda #0 ; and show 0 length of line out there + sta LENGTH+LO ; thanx + sta LENGTH+HI ; and msb + inc LINCNT ; take into account the LOW CRHIGH at EOL +ENDIN: +; +; now save lbuff in table for posterity +; + lda SV_SPC+ABANK ; get bank first + sta SPCBNK ; saved + lda SV_SPC+HI + sta SPCH + lda SV_SPC+LO + sta SPCL + ldx #0 ; start with first char in buffer +ENDLOOP: + cpx CHARCNT ; done yet? + beq INP111 + lda LBUFF,X ; get char + cmp #'A' ; IF CHAR IS UPPERCASE ALPHA, + bcc LEX ; CONVERT TO LOWER CASE + cmp #'Z'+1 + bcs LEX + adc #$20 ; converting away +LEX: + jsr STASHB ; okay, stashing away + jsr NEXTSPC ; and point to next char in table + inx ; point to next char + bne ENDLOOP ; so get next one +INP111: + lda #00 ; to show end of line + jsr STASHB ; so put it in buffer +; +; now put in new line length +; + lda RDTBL1+HI ; get page of table + jsr SETPC ; and get me the memory page and bank + sta SPCH ; save page + sty SPCBNK ; and bank + lda RDTBL1+LO ; and get offset + sta SPCL + jsr NEXTSPC ; and point to char count + lda CHARCNT ; get character count + jsr STASHB ; and shove it away +LEXBAD: + rts ; Length is in [A] +; +; Copy over a new TCHARS table +; +DO_TCHARS: +; +; now do somethin' with the TCHAR table (maybe, if LOW HIGH 0) +; + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + sta SVTCHAR+HI ; save it for checking + jsr SETPC ; and now make absolute + sta FPCH ; Save in FPC + sty FPCBNK + lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + sta SVTCHAR+LO ; and save for later check + sta FPCL ; now move pointer to fetch spot + + lda #0 ; and set index + sta I ; thank you + sta ALLFLG ; turn it off +TCHLP: + jsr FETCHB ; get the byte in [a] + jsr NEXTFPC ; point to next one + ldx I ; get offset + inc I ; and point to next one + sta TCHARTBL,X ; save in lower memory, thank you + cmp #0 ; are we done yet? + beq TCHj ; NULL TERMINATED STRING + cmp #$FF ; $ff means all HIGH 128 chars are terminators + bne TCHLNEXT ; nope + lda #1 ; yes, + sta ALLFLG ; so set flag to say so +TCHLNEXT: + bne TCHLP ; and go get it +TCHj: + rts + + ; ------------------------ + ; IS IT A TERMINATOR CHAR? + ; ------------------------ + +ISTCHR: + ldx TCHARTBL ; check for chars in TCHAR table + beq ISNOT ; nope + + LDX ALLFLG ; ARE ALL FCN KEYS (LOW 127) TERMINATORS + BEQ ISCHK ; 0 = NO, GO CHECK LIST + CMP #$80 ; YES, SO CHECK IF PAST 127 + BCS ISFND ; YUP + BCC ISNOT +ISCHK: + LDY #0 +ISLP: CMP TCHARTBL,Y ; IS CHAR WE HAVE A TCHAR? + BEQ ISFND ; YES + ldx TCHARTBL,Y ; NULL = END OF STRING + BEQ ISNOT + INY + BNE ISLP ; SHOULD ALWAYS LOOP +ISNOT: + SEC + RTS ; NOT FOUND +ISFND: + CLC + RTS + + ; ----- + ; INPUT 1 char, no printing + ; ----- + +ZINPUT: + JSR CLRBUF + + LDA #0 + STA LINCNT + STA CHRCNT + STA I+HI ; init locals too + STA I+LO + STA J+HI + STA J+LO + + DEC NARGS + BEQ ZINP3 ; NO TIME LIMIT + LDA ARG2+LO ; GET DELAY WANTED + STA I+HI + DEC NARGS + BEQ ZINP4 ; NO FCN + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI +ZINP4: + JSR TIMIN ; CALL timed input rotine + BCC ZINPRK ; send char on home + JMP RET0 ; time out without character +ZINP3: + JSR GETKEY ; OK, FIND WHICH CHAR WAS PRESSED +ZINPRK: + LDX #0 + JMP PUTBYT ; RETURN CHAR + + +INTCLL: + LDA I+HI ; SAVE VALUES FOR CALLING RTN + PHA + LDA I+LO + PHA + LDA J+HI + STA ARG1+HI ; pretend it's arg1 + PHA + LDA J+LO + STA ARG1+LO ; and this is the other half + PHA + + LDX #1 + STX NARGS ; 0 args for internal call + DEX + STX IRET ; make sure it returns here! + + LDA ZPCL ; a fake one to say we + PHA ; are an internal call + LDA ZPCM ; so save real one + PHA + LDA ZPCH + PHA + + LDA #0 ; return addr of zero is + STA ZPCH ; internal call! + STA ZPCM + STA ZPCL + + JSR DOCALL + + JMP MLOOP ; GO DO FCN +; +; RETURN FROM FCN WILL COME HERE +; +ZIRET: + PLA ; GET RID OF RTS FROM ZRET + PLA + + PLA ; get old zpc back + STA ZPCH + PLA + STA ZPCM + PLA + STA ZPCL + JSR VLDZPC ; and validate it + + PLA ; RESTORE FOR CALLING RTN + STA J+LO + PLA + STA J+HI + PLA + STA I+LO + PLA + STA I+HI + RTS ; GO BACK TO CALLER + +; INPUT: routine locals! +CHARCNT: DB 0 ; where into buffer goes char +SVCHAR: DB 0 ; where to save the char before printing + +IRET: DB 0 ; FLAG TELLS IF RETURNLESS CALL + +MTEMP: DB 00,00 ; temp spot for math routines +TYPE: DB 0 ; PARTIAL OR NORMAL (WHOLE) SAVE/RESTORE +ASSVLU: DB 0 ; how many args to this subroutine +BRKCHR: DB 0 ; READ BREAK CHAR +RDFLAG: DB 0 ; 0 - only read 1 - do lex on it +MORE: DB "[MORE]" +MOREL EQU $-MORE + + END + + diff --git a/apple/yzip/ice/itob.com b/apple/yzip/ice/itob.com new file mode 100644 index 0000000..766b076 Binary files /dev/null and b/apple/yzip/ice/itob.com differ diff --git a/apple/yzip/ice/itob.doc b/apple/yzip/ice/itob.doc new file mode 100644 index 0000000..00d26bd --- /dev/null +++ b/apple/yzip/ice/itob.doc @@ -0,0 +1,71 @@ + + INTEL HEX FILE TO BINARY FILE CONVERSION PROGRAM + + +Supplied on your master disk are the following two files: + + ITOB.COM Intel HEX file to Binary file conversion program. + + ITOB.DOC This file. + + +ITOB: + + The ITOB command line is formatted as follows: + + ITOB Hex_filename [Binary_filename] [-Base_address_override] + + + ITOB Name of the conversion program. + Hex_filename Name of the Intel Hex file to + convert. + Binary_filename Optional. Name of the binary + output file. + -Base_address_override Optional. Value to assume as the + base address of the input hex file. + + + The extent of the Hex_filename defaults to ".HEX" if it is +not given on the command line. + + The extent of the Binary_filename defaults to ".BIN" if it +is not given on the command line. + + If a Binary_filename is not given on the command line, the +name of the binary output file defaults to the Hex_filename, with +the extent ".BIN". + + If the -Base_address_override is not given, ITOB will take +the lowest-addressed byte in the Intel hex file and write this +byte as the first byte of the binary output file. + + If the -Base_address_override is given, ITOB will assume the +lowest-addressed byte in the Intel hex file is at the +Base_address_override value. + + If the -Base_address_override specifies a value which is +greater than the actual lowest-addressed byte in the Intel hex +file, a warning message will be issued. The bytes in the hex +file below the Base_address_override value will be discarded. + + If the Intel hex file contains "holes" in the hex records, +these holes will be filled in with 0FFH bytes in the binary +output file. + + +Examples: + ITOB HEXFILE ; Convert HEXFILE.HEX + ; into HEXFILE.BIN + ITOB HEXFILE.HXE ; Convert HEXFILE.HXE + ; into HEXFILE.BIN + ITOB HEXFILE BINFILE ; Convert HEXFILE.HEX + ; into BINFILE.BIN + ITOB HEXFILE BINFILE.COM ; Convert HEXFILE.HEX + ; into BINFILE.COM + ITOB HEXFILE -0 ; Convert HEXFILE.HEX + ; into HEXFILE.BIN with + ; the binary base + ; address set to 0 + ITOB HEXFILE BINFILE -F000 ; All options used + + \ No newline at end of file diff --git a/apple/yzip/ice/machine.asm b/apple/yzip/ice/machine.asm new file mode 100644 index 0000000..7a92bd2 --- /dev/null +++ b/apple/yzip/ice/machine.asm @@ -0,0 +1,902 @@ + TITLE "Apple ][ YZIP (c)Infocom","MACHINE-DEPENDENT I/O: APPLE II" +; ----------------------- +; DIRECT PRINT LINE [X/A] +; ----------------------- +; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB) +; STRING LENGTH IN [Y] +DLCNT: db 0 +DLOFF: db 0 +DISPLAY_LINE: + stx STRING+LO ; DROP STRING ADDRESS + sta STRING+HI ; INTO DUMMY BYTES + sty DLCNT ; COUNTER + ldx #0 ; INIT CHAR-FETCH INDEX + stx SCRIPT ; don't script any of my internal +DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE +STRING: DW $0000 ; DUMMY OPERAND BYTES + stx DLOFF ; save X +DOUT1: jsr COUT + ldx DLOFF ; get x back + inx + dec DLCNT ; LOOP TILL + bne DOUT ; OUT OF CHARS + jsr CLRBUF ; and force the chars out + lda #1 ; allow scripting again + sta SCRIPT ; okay, we did + rts ; done + +; SWAP2INFOW - save current state and swap to the information window, +; which is currently window zero +SWAPA1: ds 1 ; save for current ARG1 +SWAPCW: ds 1 ; save for current window +SWAPFLG: db 0 ; flag == 1 if we have already swapped +SWAP2INFOW: + lda SWAPFLG ; already swapped? + bne SWP2 ; ayyup + jsr CLRBUF ; clear out the buffer + jsr SAVE_CURSOR ; save current postion of cursor + lda ARG1+LO ; get current arg1 + sta SWAPA1 ; save it + lda CURWIN ; get current window + sta SWAPCW ; save it + lda #0 ; swap to window zero for messages + sta ARG1+LO ; okay + jsr ZSCRN ; and swap to it +SWP2: + inc SWAPFLG ; show we are in swap window +SWAPEX: + rts ; all done +; +; SWAPBACK - swap out of info window, and back to old window +; +SWAPBACK: + dec SWAPFLG ; are we finally leaving for good? + bne SWAPEX ; nope + lda SWAPCW ; and now for current window + sta ARG1+LO ; swap to it + jsr ZSCRN ; we did + lda SWAPA1 ; and get arg1 back + sta ARG1+LO ; we did + jmp GET_CURSOR ; and get cursor back + +; ----------------------- +; SEND [LBUFF] TO PRINTER +; ----------------------- +; ENTRY: LENTH OF LINE IN [PRLEN] + +PLEAV: RTS + +PPRINT: + lda SCRIPT ; SCRIPTING INTERNALLY ENABLED? + and SCRIPTF ; SCRIPTING ON? + and SCRIPTFLG ; Window allow scripting? + beq PLEAV ; NO, EXIT + lda CSW+LO ; SAVE NORMAL OUTPUT HOOK + pha + lda CSW+HI + pha + lda ALTCSW+LO ; LOAD SCRIPTING HOOK + sta CSW+LO + lda ALTCSW+HI + sta CSW+HI + lda RDROM ; put system ROM in for printer out + ldy #0 +PP5: + lda LBUFF,Y ;GET A CHAR TO SEND OUT + jsr MCOUT + iny + dec PRLEN ;LINE COUNT + bne PP5 ;PRINT WHOLE LINE +; +; ALL DONE, RESET TO NORMAL AND LEAVE +; + lda BNK2SET ; write RAM, bank 1 + lda BNK2SET + pla + sta CSW+HI + pla + sta CSW+LO + rts + +PSTAT: DB 0 ;SET TO CLEAR WHEN BOOT, + ;I PUT IT HERE SO RESTART WON'T ALTER +ALTCSW: DB 0,0 ;(WORD) PRINTER COUT + + ; FIRST TIME USING PRINTER, INITIALIZE IT +SLOTM: DB EOL + DB "Printer Slot 1-7: " +SLOTML EQU $-SLOTM + +PCHK: + jsr SWAP2INFOW ; point to info window +PCHK1: + DLINE SLOTM + jsr GETKEY + cmp #'8' ;1-7 + bcs PCHK1 ;OOPS + cmp #'1' ; less than '1'? + bcc PCHK1 ; ayyup +PC2: + eor #$F0 ; make it a slot address + sta ALTCSW+HI + lda #EOL + jsr CHAR ;SEND >CR< TO SCREEN FOR NEATNESS + inc PSTAT ;SET TO ON + lda CSW+LO ;SAVE NORMAL OUTPUT HOOK + pha + lda CSW+HI + pha + lda ALTCSW+LO ;LOAD SCRIPTING HOOK + sta CSW+LO + lda ALTCSW+HI + sta CSW+HI + jsr INITPRT ; now, init it + + lda RDROM ; bring in system ROM + lda #$89 ; OUTPUT PRINTER SETUP SEQUENCE + jsr MCOUT ; START WITH COMMAND CHAR >CTRL-I< + lda #$B8 ; 8 (80 COL WIDE) + jsr MCOUT + lda #$B0 ; 0 + jsr MCOUT + lda #$CE ; N (LF AFTER CR) + jsr MCOUT + lda CSW+LO ; SAVE REAL PRINTER OUTPUT + sta ALTCSW+LO ; LOC. FOR NEXT TIME + lda CSW+HI + sta ALTCSW+HI + pla ; RESET NORMAL OUTPUT + sta CSW+HI + pla + sta CSW+LO + lda BNK2SET ; and bring back top RAM + lda BNK2SET ; okay + jmp SWAPBACK ; and back to the old window +INITPRT: + lda #0 ; jump to $Cn00 + sta CSW+LO ; make LSB == 0 + jmp (CSW) ; and goto it + + +SAVE_CURSOR: + lda SCRCY ; save the cursor pos + ldy #WINY ; get offset + sta (WINDOW),Y ; first y pos + iny ; now x pos + lda SCRCX ; got it + sta (WINDOW),Y ; saved it + ldy #WINLCNT ; reset line count too + lda LINCNT ; okay + sta (WINDOW),Y ; get it + rts + +GET_CURSOR: + ldy #WINY ; get cursor pos back + lda (WINDOW),Y ; got y pos + sta SCRCY ; saved + iny ; point to x pos + lda (WINDOW),Y ; got it + sta SCRCX ; make it better + sec ; subtract left margin to get how long line is + sbc LEFTMRG ; okay we did that + sta LENGTH+LO ; this is how big line is too + lda #0 ; clear MSB + sta LENGTH+HI + asl LENGTH+LO ; *2 + rol LENGTH+HI + asl LENGTH+LO ; *4 + rol LENGTH+HI + + ldy #WINLCNT ; reset line count too + lda (WINDOW),Y ; get it + sta LINCNT ; okay + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay + rts + +; ------------ +; SPLIT SCREEN +; ------------ +; +; SPLIT SCREEN AT LINE [ARG1] putting screen 1 at top and screen +; 0 at bottom. +; DISABLE SPLIT IF [ARG1] = 0 +; +ZSPLIT: + jsr SAVE_CURSOR ; save the cursor pos +; +; first muck with window 1 +; + lda ARG1+LO ; get split arg back + sta WINDOW1+WINHGHT ; this becomes the height of window 1 + lda #0 ; put top of 1 to top of screen + sta WINDOW1+WINTOP ; okay, we did it + lda ARG1+LO ; get new height + ldx #$FF ; this is the counter + sec ; get ready for subs +ZSPLIT0: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZSPLIT0 ; still some lines + dex ; save input line + stx WINDOW1+WINLINES ; saved + + lda WINDOW1+WINY ; check cursor pos + cmp ARG1+LO ; against height + bcc ZSPL1 ; inside window, so save it +ZSPL0: + lda #0 ; reset to top left + sta WINDOW1+WINY ; y pos at top + sta WINDOW1+WINX ; x pos at left + sta WINDOW1+WINLLEN+LO ; line length + sta WINDOW1+WINLLEN+HI ; line length + sta WINDOW1+WINLCNT ; line counter +; +; now muck with window 0 +; +ZSPL1: + lda WINDOW0+WINTOP ; top of window 0 + sec ; doing sub + sbc ARG1+LO ; subtract out the new top + clc ; adding + adc WINDOW0+WINHGHT ; to get the new height +; bcc ZSPLIT1 ; okay, positive height +; lda #0 ; make height 0 +ZSPLIT1: + sta WINDOW0+WINHGHT ; and save new height + + ldx #$FF ; this is the counter + sec ; get ready for subs +ZSPLIT2: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZSPLIT2 ; still some lines + dex ; to save input line + stx WINDOW0+WINLINES ; saved + + lda ARG1+LO ; this is the new top + sta WINDOW0+WINTOP ; set in structure + cmp WINDOW0+WINY ; make sure cursor is still in window + beq ZSPL5 ; nope, at the top + bcc ZSPL5 ; or under it + sta WINDOW0+WINY ; put cursor at top + lda #0 ; left of new + sta WINDOW0+WINX ; window 0 + sta WINDOW0+WINLLEN+LO ; linelength + sta WINDOW0+WINLLEN+HI ; linelength + sta WINDOW0+WINLCNT ; line counter +ZSPL5: + jsr GET_CURSOR ; get the cursor pos back + + lda #0 ; now switch to window zero + sta ARG1+LO ; good bye + jmp ZSCRN ; making window 0 be current + +; ------ +; MARGIN +; ------ +; +; Set the margins for the window +; +; ARG1 - left margin +; ARG2 - right margin +; ARG3 - window ID (optional) +; +ZMARG: + jsr CLRBUF ; CLEAR LBUFF BEFORE RESETTING LINE MARGINS + jsr SAVE_CURSOR ; save current cursor pos + + lda NARGS ; see if window ID was passed + cmp #3 ; if ==3, then it's there + beq ZMRG1 ; okay, so use it + lda CURWIN ; get the current window + sta ARG3+LO ; and use as the default +ZMRG1: + lda ARG3+LO ; check what window + jsr SETWJ ; get window offset into J + lda ARG1+LO ; do left margin first + ldy #WINLM ; get offset + sta (J),Y ; save for window + iny ; point to right margin + lda ARG2+LO ; get right margin + sta (J),Y ; save right margin + ldy #WINWID ; get full width of window + lda (J),Y ; got it + sec ; subtract off the 2 margins + ldy #WINLM ; first the left margin + sbc (J),Y ; okay, gone + iny ; point to right margin + sbc (J),Y ; and take it off + ldy #WINXSZ ; set width of usable window + sta (J),Y ; see, here it is +; +; move cursor to left margin +; + ldy #WINLEFT ; get left edge + lda (J),Y ; got it + ldy #WINLM ; and add left margin + clc ; adding + adc (J),Y ; to get minimum X + ldy #WINX ; check to make sure X pos is okay + sta (J),Y ; then reset it +; +; now see if we changed the current window +; +ZMRGXP: + ldx ARG3+LO ; get the window + bmi ZMRG3 ; -3 means current window + cpx CURWIN ; check against the current window + bne ZMRGX ; nope, so we be done +ZMRG3: + sta LEFTMRG ; [A] already has left margin + ldy #WINXSZ ; get xsize to set + lda (WINDOW),Y ; got it + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + jsr GET_CURSOR ; restore the cursor pos +ZMRGX: + rts +; +; SOUND +; ----- +; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID +; (EZIP) + +ZSOUND: + ldx ARG1+LO ; GET SOUND WANTED + dex + beq BEEP + dex + bne ZSOEX ; INVALID + ldy #$FF ; DURATION ($C0 = .1 SEC) +BOOP: + lda #$10 ; TONE ($0C = 1 KHZ) + jsr WAIT10 + lda SPKR ; TOGGLE SPEAKER + dey + bne BOOP +ZSOEX: + rts + +BEEP: + lda RDROM + jsr MBELL ; just use system beep + lda BNK2SET ; back to bank 2 + lda BNK2SET ; back to bank 2 + rts +; +; just do the background color - foreground is always white/black +; +; +; ZIPCOLOR - maps ZIP colors to screen colors +; +ZIPCOLOR: db 0,$B,6,7,$C,1,$E,$F +ZCOLOR: + jsr CLRBUF ; print out what we have + + lda NARGS ; check if window was passed + cmp #3 ; was it? + beq ZCLR0 ; ayyup + lda CURWIN ; make it current window + sta ARG3+LO ; it is now +ZCLR0: + lda ARG3+LO ; get window ID + jsr SETWJ ; and put pointer into J + + ldx ARG2+LO ; get background color + beq ZCLR3 ; check fore ground color + bpl ZCLR01 ; not -1 + jsr GET_NYBBLE ; get me the color nybble here + jmp ZCLR11 ; and use as background color +ZCLR01: + dex ; check for default + bne ZCLR1 ; nope, find the color + ldx #1 ; use black as default back color +ZCLR1: + dex ; zero base the color + lda ZIPCOLOR,X ; get my color from the zip color +ZCLR11: + ldy #WINBGND ; get background offset + sta (J),Y ; saved color + ldx ARG1+LO ; get foreground color + beq ZCLREX ; no change + dex ; check for default + bne ZCLR3 ; nope, find the color + ldx #8 ; use white as default fore color +ZCLR3: + dex ; zero base the color + ldy #WINFORE ; foreground color offset + txa ; get into A for fun + sta (J),Y ; save in structure +ZCLREX: + rts + +; +; CHKTME RTN - CALLED BY INPUT & ZINPUT +; +CHKTME: + LDA NARGS ; CHECK IF TIME LIMIT + CMP #2 + BEQ CHKT1 ; NO + LDA ARG3+LO ; GET DELAY WANTED + STA I+HI + LDA NARGS ; IS THERE A FCN? + CMP #4 + BNE CHKT1 ; NO + LDA ARG4+LO ; YES, SET IT + STA J+LO + LDA ARG4+HI + STA J+HI +CHKT1: + RTS ; just set things up, please + +WAIT10: + ldy #OUTER_DELAY ; make a delay loop + lda #INNER_DELAY + ldx MID ; on a GS? + cpx #IIgsID ; well? + bne WAIT0 ; no changes + ldy #GS_OUTER_DELAY ; this is special GS loops + lda #GS_INNER_DELAY ; inner loop delay for GS +WAIT0: + sty DELAY_COUNTER ; show outer delay loop +WAIT11: + tay ; pick up inner delay loop +WAIT2: + ldx #0 ; inner loop +WAIT3: + dex + bne WAIT3 + dey + bne WAIT2 + pha ; save inner delay loop + lda MOUSEF ; move mouse cursor? + beq WAIT1 ; nope + jsr MOVE_MC ; move cursor, if necessary + dec DELAY_COUNTER ; for all the overhead +WAIT1: + pla ; get inner delay + dec DELAY_COUNTER + bpl WAIT11 + rts +; +; tick the ol timer +; +TIMEK: + lda #BLINK_RATE ; how often to blink + sta CURCOUNT ; okay! +TIMEST: + lda I+LO ; don't reset if not zero + bne TIMELOOP ; so keep goin' then + lda I+HI + sta I+LO + jsr STCUR ; start the cursor +TIMELOOP: + jsr WAIT10 ; wait .10 secs + + jsr FKEYX ; Check for Keystroke + bmi TIME2 ; OK, HE'S THERE, CONTINUE + + dec CURCOUNT ; count down to toggle + bne TMCNT ; okay, no blink + jsr STCUR ; blink cursor + lda #BLINK_RATE ; once per second + sta CURCOUNT ; okay! +TMCNT: + dec I+LO ; 10TH'S OF SECONDS TO WAIT + beq TIMEOUT ; SOME TIME LEFT + + bne TIMELOOP ; so gwon back and try again! (JMP) +; +; THERE IS A TIME OUT, CHECK FOR A FCN +; +TIMEOUT: + jsr ERCUR ; after erasing cursor + lda J+HI ; IS THERE A FCN + beq TIMEBAD ; NO FCN, LEAVE WITH NOTHING +TIME3: + jsr INTCLL ; INTERNALLY CALL THE FCN + lda VALUE+LO ; CHECK RESULTS + beq TIMEST ; ELSE TRY AGAIN + bne TIMEBAD ; else die a horrible death! +TIME2: + jsr ERCUR ; after erasing cursor + clc ; GOT A KEY + rts +TIMEBAD: + sec + rts +; +; display the cursor in the current spot +; +CURSTATE: db $80 ; blinking cursor state +CURCOUNT: db 0 ; toggle counter + +STCUR: + pha ; save a + lda INVFLG ; get current INVFLG + pha ; save it + lda #$80 ; make it all be ones + sta INVFLG ; and blink + + lda #SPACE ; space for cursor + sta SHOW_CURSOR ; show that we are doing cursor + jsr CHAR ; and print it out + jsr DISP_LINE ; send it out + + lda CURSTATE ; get current state + eor #$80 ; toggle it + sta CURSTATE ; save it + pla ; get invflg + sta INVFLG ; restored + lda #0 ; clear cursor flag + sta SHOW_CURSOR ; okay + + pla + rts +; +; just erase the cusor char, but leave cursor in its old place +; +ERCUR: + pha ; save a + lda CURSTATE ; get current state + bne ERCURX ; not on, leave alone + jsr STCUR ; 'start' it out +ERCURX: + pla ; retrieve [A] + rts +; +; timed key input loop +; +; carry set if timed out +; char in [A], if there is one! +TIMIN: + lda MOUSEF ; is there a mouse/joystick? + beq TIMIN1 ; nope + jsr MSCON ; turn on mouse cursor +TIMIN1: + jsr TIMEK ; check for keystroke + bcs TMBAD ; ELSE ABORT +TM1: + jsr PARSEKEY ; GET ASCII INTO [A] AND [IOCHAR] + bcs TIMIN1 ; c==1 means no good char +TMBAD: + ldx MOUSEF ; is there a mouse/joystick? + beq TIMIN2 ; nope + php ; save status + pha ; save (possible) char + jsr MSCOFF ; turn off mouse cursor + pla ; get char back + plp ; get return status +TIMIN2: + rts ; and away we go +; +; FKEYX - move the mouse cursor if any, then check for keystroke +; +FKEYX: + lda MOUSEF ; is there a mouse cursor? + beq KEYX ; nope + bmi KEYMOUSE ; handle mouse + jsr DO_STICK ; handle joystick + bpl KEYX ; go look for key still + bmi KEYBTN ; do button handling +KEYMOUSE: + jsr DO_MOUSE ; handle mouse stuff + bpl KEYX ; go look for key still +; +; button hit, so show pos in MSTBL +; +KEYBTN: + pha ; save status + lda MSTBL+LO + sta SPCL + lda MSTBL+HI + sta SPCH + lda MSTBL+ABANK + sta SPCBNK + lda #ZMSLOCX+1 ; point to LSB of mouse x + jsr ADDSPC ; add to point + lda MSX ; get X + jsr STASHB ; and stuff it away + lda #2 ; 2 more to get to mouse y + jsr ADDSPC ; okay + lda MSY ; now show the world the y pos + jsr STASHB ; and it is away + pla ; get status back + tay ; and set it again + rts ; otherwise, done +KEYX: + lda KBD ; check keyboard strobe + bpl KEYXX ; nothing + sta ANYKEY ; reset strobe +KEYXX: + rts +; +; MOVE_MC - move the mouse/joystick cursor, if necessary +; +MOVE_MC: + lda MOUSEF ; check which kind to move + bpl MOVE_MC1 ; move joystick cursor + jsr CHK_MOUSE ; move the mouse cursor + jmp MOVE_MC2 ; and print it +MOVE_MC1: + jsr MOVE_STICK ; okay, checked it out +MOVE_MC2 + lda MSMOVEF ; did it move? + beq MOVE_MCX ; nope + jmp MSCURS ; print it +MOVE_MCX: + rts ; done +; +; CHK_MOUSE - check the mouse position and button state, and flag any change +; +CHK_MOUSE: + sta PAGE2SW ; make sure we are pointing to main bank + ldx #READM ; get me current cursor pos + jsr MOUSER ; turn off interrupts and set current pos +MSFIX0 lda MOUSEST ; get status byte + tay ; save for a sec + and #$20 ; moved since last time? + beq CHKM1 ; nope + sta MSMOVEF ; show movement +MSFIX1 lda MOUSEXL ; get mouse X pos + sta MSX ; save new one +MSFIX2 lda MOUSEYL ; and the y pos + sta MSY ; save for me +CHKM1: + tya ; get status back + and #$40 ; button still down? + bne CHKMX ; yes + tya ; get status again + and #$80 ; is the button now down? + ora MSBTNF ; so say so + sta MSBTNF ; turn it on if necessary +CHKMX: +; cli ; reenable interrupts now + rts ; done +; +; there is a mouse, so check it +; +DO_MOUSE: + jsr CHK_MOUSE ; check the mouse please +; FALL THROUGH TO BUTTON CLICKING HANDLER +; jmp DO_BUTTON ; handle button clicking +; +; DO_BUTTON - handle button clicking, working with the timer to +; check for double clicking or not +; +DO_BUTTON: + lda MSMOVEF ; check moved flag + beq DOM01 ; nope + jsr MSCURS ; move mouse cursor +DOM01: + lda #0 ; show no char + ldy MSBTNF ; check button flag + beq DOBX ; none +; +; button strike, check for double click +; + ldy CLKCTR ; have we started click counter? + bpl DOB02 ; nope + ldy #1 ; this resets counter + sty CLKCTR ; reset it + lda #DBL_CLK ; show double click char + bne DOBEXIT ; and finis +DOB02: + ldy #CLK_CNT ; set to double click timeout + sty CLKCTR ; okay + bmi DOBEXIT ;done +DOBX: + ldy CLKCTR ; click counter counting? + bpl DOBEXIT ; nope + inc CLKCTR ; count it then + bne DOBEXIT ; all done + ldy #1 ; reset counter + sty CLKCTR ; okay + lda #SGL_CLK ; set as char +DOBEXIT: + ldy #0 ; clear out flags + sty MSBTNF ; button flag + sty MSMOVEF ; moved flag + tay ; set flag to show any char + rts ; return char +; +; DO_STICK - handle the joystick 'interrupt' +; +DO_STICK: + jsr MOVE_STICK ; first move it + lda APKEY1 ; get apple/button flag + bmi DOST5 ; button click + lda #0 ; show no button click +DOST5: + sta MSBTNF ; show the click + jmp DO_BUTTON ; now handle it +MOVE_STICK: + ldx #0 ; get horizontal change + jsr READ_STICK ; puts value in Y + cpy #80 ; if < 80, then jump to the left + bcs DOST1 ; it is not + lda MSX ; make sure X is > 0 + beq DOST2 ; it is == 0, can't get smaller + sta MSMOVEF ; show movement + dec MSX ; move one to the left + dec MSX ; move two to the left + bne DOST2 ; now check vertical +DOST1: + cpy #180 ; if > 160, then move right + bcc DOST2 ; nope + lda MSX ; make sure X is in bounds + cmp #MAXWIDTH-4 ; don't go too far + bcs DOST2 ; already maxxed out + sty MSMOVEF ; show movement + inc MSX ; one step to the left + inc MSX ; and another one +DOST2: + ldx #1 ; now check vertical + jsr READ_STICK ; ask the monitor + cpy #80 ; if < 80, move up + bcs DOST3 ; nope + lda MSY ; don't go negative + beq DOST4 ; already minned out + sta MSMOVEF ; show movement + dec MSY ; count down + dec MSY ; twice + bne DOST4 ; all done +DOST3: + cpy #180 ; check for downward motion + bcc DOST4 ; none + lda MSY ; check for maximum + cmp #MAXHEIGHT-3 ; don't go below water + bcs DOST4 ; gone, thanx + sty MSMOVEF ; show movement + inc MSY ; go further down + inc MSY ; twice as far for joystick +DOST4: + rts ; done +READ_STICK: + txa ; save which stick we want + ldy #6 ; another delay loop +READST1: + ldx #0 +READST2: + dex + bne READST2 + dey + bne READST1 + dec DELAY_COUNTER ; show outside loop what we be doing + dec DELAY_COUNTER ; show outside loop what we be doing + tax ; get x back + jmp MPREAD ; NOW do the read +; ---------------------------- +; FETCH ASCII KEYCODE INTO [A] +; ---------------------------- +; EXIT: ASCII IN [A] & [IOCHAR] + +GETKEY: + lda #BLINK_RATE ; flag as wait for good key + sta CURCOUNT ; clear blinker + lda MOUSEF ; is there a mouse/joystick? + beq GTK0 ; nope + jsr MSCON ; turn on mouse cursor +GTK0: + lda #0 ; clear line counter + sta LINCNT ; okay, we did + txa ; SAVE [X] & [Y] + pha + tya + pha +GKEY0: + inc RNUM1 ; just whack on random number + dec RNUM2 ; and more + jsr FKEYX ; is there a key? + bmi GKEY01 ; got the key + + jsr WAIT10 ; wait .1 seconds, moving mouse cursor + + dec CURCOUNT ; down one + bne GKEY0 ; no toggle + jsr STCUR ; okay, toggle + lda #BLINK_RATE ; 1 per second + sta CURCOUNT ; okay + bne GKEY0 ; check for key +GKEY01: + pha ; save char + lda MOUSEF ; any mouse cursor? + beq GTK1 ; nope + jsr MSCOFF ; turn mouse cursor off +GTK1: + pla ; get char back + jsr ERCUR ; so erase cursor +CHKKEY: + jsr PARSEKEY ; how was the key? + bcs GKEY0 ;TRY AGAIN + sta IOCHAR ;HOLD ON TO IT + adc RNUM1 ;FUTZ WITH RANDOM + sta RNUM1 + eor RNUM2 + sta RNUM2 + pla ; RESTORE + tay ; EVERYTHING + pla + tax + lda IOCHAR ; GET CHAR INTO [A] + rts ; AND RETURN IT + +; +; CHECK TO MAKE SURE KEY IS VALID, ONLY ACCEPT IT IF IT IS +; +PARSEKEY: + and #$7F ;SCREEN OUT SHIFTS +; +;CHECK FOR "ARROWS" & FUNCTION KEYS (X), CONVERT FOR USE (EZIP) +;ALSO : CHANGE <_>)@%^&*( TO ,-.0256789 - and 'mouse' clicks +; and other kinds of special chars +; +GK0: + ldx #ENDKEY ; GET LENGTH OF LIST +GK2: + cmp HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + beq GK3 ; FOUND IT + dex + bpl GK2 ; CHECK THEM ALL + bmi GK4 ; NOT FOUND, CONTINUE OTHER CHECKS +GK3: + lda WANT,X ; GET KEY TO USE INSTEAD + clc ; show niceness + rts ; done +GK4: + cmp #SPACE ; NO CTRL CHARS ACCEPTABLE + bcc BADKEY ; IF < SPACE, BAD + + cmp #'<' ; pick up numbers and most punctuation + bcc OK ; we did + + cmp #'z'+1 ;PICK OUT LETTERS NOW + bcs BADKEY ;IF > BAD + cmp #'a' + bcs OK ;IF > OK + cmp #'A' + bcc BADKEY + CMP #'Z'+1 + BCC OK ;IF < OK +BADKEY: + jsr BEEP ;BAD KEY, GIVE WARNING NOISE, gwon back + sec ; show badness + rts ; and done +OK: + cmp #'0' ; check for number keys + bcc OKj ; nope, < 0 + cmp #'9'+1 ; more than a nine? + bcs OKj ; ayyup +; +; here we check for the closed apple key being down too +; + ldx APKEY2 ; how about the closed apple key + bpl OKj ; not pressed, so use as number key +; +; transform number key into a function key +; + CLC ; get ready for add + ADC #84 ; transforms '1'-'9' to 133-141 + CMP #132 ; but '0' wants to be a 142! + BNE OKj ; but it's not it + CLC ; again, don't want carry + ADC #10 ; voila! +OKj: + clc ; show a wicked good character is about to arrive + rts ; toots finis + +HAVE: DB $0B,$0A,$08,$15,$7f,ESCAPE,$3C,$7C,$3F + DB $3C,$5F,$3E,$40,$25,$5E,$26,$01,$02, EOL +WANT: DB 129,130,131,132,08,ESCAPE,$3C,$7C,$3F + DB $2C,$2D,$2E,$32,$35,$36,$37,254,253, EOL +ENDKEY EQU $-WANT-1 + + END + + diff --git a/apple/yzip/ice/macros.asm b/apple/yzip/ice/macros.asm new file mode 100644 index 0000000..7444d26 --- /dev/null +++ b/apple/yzip/ice/macros.asm @@ -0,0 +1,114 @@ + TITLE "Apple ][ YZIP (c)Infocom","MACROS" + +; +; MACROS for Apple ][ Yzip +; +DLINE: MACRO STRING,SLEN + ldx \#LOW #STRING# ; get part of STRING + lda \#HIGH #STRING# ; get other part of string + IF NUL #SLEN# ; is there a length defined? + ldy \##STRING#L ; get length of string + ELSE + ldy #SLEN# ; then just fetch it + ENDIF + jsr DISPLAY_LINE ; print the string + ENDM +; +; ProDOS macros +; +PRODOS: MACRO CODE, PADDR + jsr $BF00 ; ProDOS handler + DB #CODE# ; ProDOS function code + DW #PADDR# ; Function Parameter Block address + ENDM + +QUIT: MACRO PBLOCK + PRODOS $65, #PBLOCK# + ENDM + +READ_BLOCK: MACRO PBLOCK + PRODOS $80, #PBLOCK# + ENDM + +WRITE_BLOCK: MACRO PBLOCK + PRODOS $81, #PBLOCK# + ENDM + +GET_TIME: MACRO PBLOCK + PRODOS $82, #PBLOCK# + ENDM + +CREATE: MACRO PBLOCK + PRODOS $C0, #PBLOCK# + ENDM + +DESTROY: MACRO PBLOCK + PRODOS $C1, #PBLOCK# + ENDM + +RENAME: MACRO PBLOCK + PRODOS $C2, #PBLOCK# + ENDM + +SET_FILE_INFO: MACRO PBLOCK + PRODOS $C3, #PBLOCK# + ENDM + +GET_FILE_INFO: MACRO PBLOCK + PRODOS $C4, #PBLOCK# + ENDM + +ONLINE: MACRO PBLOCK + PRODOS $C5, #PBLOCK# + ENDM + +SET_PREFIX: MACRO PBLOCK + PRODOS $C6, #PBLOCK# + ENDM + +GET_PREFIX: MACRO PBLOCK + PRODOS $C7, #PBLOCK# + ENDM + +OPEN: MACRO PBLOCK + PRODOS $C8, #PBLOCK# + ENDM + +NEWLINE: MACRO PBLOCK + PRODOS $C9, #PBLOCK# + ENDM + +READ: MACRO PBLOCK + PRODOS $CA, #PBLOCK# + ENDM + +WRITE: MACRO PBLOCK + PRODOS $CB, #PBLOCK# + ENDM + +CLOSE: MACRO PBLOCK + PRODOS $CC, #PBLOCK# + ENDM + +SET_MARK: MACRO PBLOCK + PRODOS $CE, #PBLOCK# + ENDM + +GET_MARK: MACRO PBLOCK + PRODOS $CF, #PBLOCK# + ENDM + +SET_EOF: MACRO PBLOCK + PRODOS $D0, #PBLOCK# + ENDM + +SET_BUF: MACRO PBLOCK + PRODOS $D1, #PBLOCK# + ENDM + +GET_BUF: MACRO PBLOCK + PRODOS $D2, #PBLOCK# + ENDM + + END + diff --git a/apple/yzip/ice/main.asm b/apple/yzip/ice/main.asm new file mode 100644 index 0000000..b19de34 --- /dev/null +++ b/apple/yzip/ice/main.asm @@ -0,0 +1,290 @@ + TITLE "Apple ][ YZIP (c)Infocom","MAIN LOOP" + +MLOOP: + lda #0 + sta NARGS ; reset number of args + sta PAGE2SW ; just do this for the heck of it + lda BNK2SET + lda BNK2SET + + jsr NEXTPC ; get op code + sta OPCODE ; SAVE IT HERE + + IF 0 +; +; special debugging code +; + lda OPCODE + JSR DBG1 + LDA #' ' + JSR DBG2 + LDA OPCODE + ENDIF +; +; DECODE AN OPCODE +; + tay ; 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: CMP #236 ; XCALL? + BNE OPX5 + JMP OPXCLL ; YES, PROCESS SEPARATELY +OPX5: CMP #250 ; IXCALL + BNE OPX6 + JMP OPXCLL +OPX6: 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 + CMP #$C0 ; IS IT NEW OPCODE RANGE? + BCC ZEXTOP ; YES + JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + +DOXOP: AND #%00011111 ; ISOLATE ID BITS + TAY + LDA OPTXL,Y + STA GOX+1+LO + LDA OPTXH,Y + STA GOX+1+HI +GOX: JSR $FFFF ;DUMMY + JMP MLOOP + + ; HANDLE EXTENDED OPCODE RANGE OPS + +ZEXTOP: CMP #EXTLEN ; OUT OF RANGE? + BCS BADEXT + TAY ; OFFSET ALREADY CORRECT + LDA EXTOPL,Y + STA GOE+1+LO + LDA EXTOPH,Y + STA GOE+1+HI +GOE: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #1 -- ILLEGAL X-OP *** + +BADOPX: LDA #1 + JMP ZERROR + + ; *** ERROR #16 -- ILLEGAL EXTENDED RANGE X-OP *** + +BADEXT: LDA #16 + JMP ZERROR + + ; HANDLE AN XCALL OPCODE + +OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + STA ABYTE + JSR NEXTPC + STA BBYTE + LDA ABYTE ; ONE TO START WITH + LDX #0 + STX ADEX ; INIT ARGUMENT INDEX + BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP +XCALL1: LDA ABYTE ; GET ARG BYTE + ASL A ; SHIFT NEXT 2 BITS + ASL A ; INTO BITS 7 & 6 + STA ABYTE ; HOLD FOR LATER +XCALL2: AND #%11000000 ; MASK OUT GARBAGE + BNE XCALL3 + JSR GETLNG ; 00 = LONG IMMEDIATE + JMP XCNXT +XCALL3: CMP #%01000000 ; SHORT IMMED? + BNE XCALL4 ; NO, TRY ANOTHER + JSR GETSHT ; 01 = SHORT IMMED. + JMP XCNXT +XCALL4: CMP #%10000000 ; LAST TEST + BNE OPX4 ; 11 = NO MORE ARGS + JSR GETVAR ; 10 = VARIABLE +XCNXT: LDX ADEX + LDA VALUE+LO + STA ARG1+LO,X + LDA VALUE+HI + STA ARG1+HI,X + INC NARGS + INX + INX + STX ADEX + CPX #16 + BNE XCALL5 + JMP OPX4 ; DONE, GO DO IT +XCALL5: CPX #8 ; DONE 1ST MODE BYTE? + BNE XCALL1 ; NOT QUITE YET + LDA BBYTE ; SET UP FOR NEXT + STA ABYTE ; MODE BYTE + JMP XCALL2 ; GO DO IT + +; ------------- +; HANDLE A 0-OP +; ------------- + +OP0: CMP #190 ; IS IT EXTOP OP + BEQ EXTOP ; YES + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT0L,Y + STA GO0+1+LO + LDA OPT0H,Y + STA GO0+1+HI +GO0: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #2 -- ILLEGAL 0-OP *** + +BADOP0: LDA #2 + JMP ZERROR + + ; THIS OPCODE TELLS THAT NEXT OP IS PART OF THE + ; EXTENDED RANGE OF OPCODES, GET IT AND PROCESS IT + ; (THEY ARE ALL XOPS) + +EXTOP: JSR NEXTPC ; GO GET EXTENDED RANGE OP + STA OPCODE ; SAVE IT + JMP OPEXT ; AND HANDLE IT + + +; ------------- +; HANDLE A 1-OP +; ------------- + +OP1: + and #%00110000 ; ISOLATE ARGUMENT BITS + bne OP1A + jsr NEXTPC ; get next byte + tay + jmp OP1A1 +OP1A: and #%00100000 ; TEST AGAIN + bne OP1B +; +; 01 = SHORT IMMEDIATE +; +OP1A1: sta ARG1+HI + jsr NEXTPC + sta ARG1+LO + inc NARGS + jmp OP1EX1 +OP1B: JSR GETVAR ; 10 = VARIABLE +OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] +OP1EX1: LDA OPCODE + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT1L,Y + STA GO1+1+LO + LDA OPT1H,Y + STA GO1+1+HI +GO1: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** ERROR #3 -- ILLEGAL 1-OP *** + +BADOP1: LDA #3 + JMP ZERROR + + + +; ------------- +; HANDLE A 2-OP +; ------------- + +OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT + BNE OP2A +; +; 0 = SHORT IMMEDIATE +; + sta ARG1+HI + jsr NEXTPC + sta ARG1+LO + inc NARGS + jmp OP2B1 +OP2A: jsr GETVAR ; 1 = VARIABLE +OP2B: jsr V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] +OP2B1: lda OPCODE ; RESTORE OPCODE BYTE + and #%00100000 ; ISOLATE 2ND ARG BIT + bne OP2C + sta ARG2+HI + jsr NEXTPC + sta ARG2+LO + jmp OP2D1 +OP2C: jsr GETVAR ; 1 = VARIABLE +OP2D: lda VALUE+LO ; MOVE 2ND [VALUE] + sta ARG2+LO ; INTO [ARG2] + lda VALUE+HI + sta ARG2+HI +OP2D1: inc NARGS ; UPDATE ARGUMENT COUNT + + ; EXECUTE A 2-OP OR EXTENDED 2-OP + +OP2EX: LDA OPCODE + AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT2L,Y + STA GO2+1+LO + LDA OPT2H,Y + STA GO2+1+HI +GO2: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 + diff --git a/apple/yzip/ice/objects.asm b/apple/yzip/ice/objects.asm new file mode 100644 index 0000000..5ffd6ae --- /dev/null +++ b/apple/yzip/ice/objects.asm @@ -0,0 +1,165 @@ + TITLE "Apple ][ YZIP (c)Infocom","OBJECT & PROPERTY HANDLERS" + +; ---------------------------------- +; GET ABSOLUTE ADDRESS OF OBJECT [A] +; ---------------------------------- +; ENTER: OBJECT IN A/X (LO/HI) +; EXIT: ADDRESS IN [FPC] +OBJLOC: + STX I+HI ; SAVE MSB FOR SHIFTING + ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) + STA I+LO + ROL I+HI + LDX I+HI + ASL A + ROL I+HI ; *4 + ASL A + ROL I+HI ; *8 + ASL A + ROL I+HI ; *16 + SEC + SBC I+LO ; -(*2) + STA I+LO ; SO IS *14 TOTAL + LDA I+HI + STX I+HI + SBC I+HI + STA I+HI + LDA I+LO + CLC + ADC #112 ; ADD OBJECT TABLE OFFSET + BCC OBJ3 + INC I+HI +OBJ3: + clc ; NEXT ADD THE relative ADDR + adc ZBEGIN+ZOBJEC+1 ; OF THE OBJECT TABLE + sta FPCL ; save lo byte + lda I+HI + adc ZBEGIN+ZOBJEC ; now work on page + jsr SETPC ; now get page/bank + sta FPCH ; this is hi part + sty FPCBNK ; and this is the bank + rts +; ----------------------------- +; GET ADDRESS OF PROPERTY TABLE +; ----------------------------- +; EXIT: [FPC] HAS ABSOLUTE ADDR OF PROPERTY TABLE +; including OFFSET TO START OF PROP IDS +PROPB: + lda ARG1+LO + ldx ARG1+HI ; get address + jsr OBJLOC ; put table location into FPC + lda #12 ; add 12 to get to beginning + jsr ADDFPC ; and add it to FPC + jsr FETCHB ; get MSB of P-TABLE Address + pha ; and save it for a moment + jsr NEXTFPC ; to get LSB + jsr FETCHB ; get LSB of P-TABLE Address + sta FPCL ; and save lo part + pla ; get page back + jsr SETPC ; and set up memory bank/page + sta FPCH ; save page + sty FPCBNK ; and bank + jsr FETCHB ; get length of short description + asl A ; WORD-ALIGN IT + jsr ADDFPC ; and add it to FPC + jsr NEXTFPC ; POINT JUST PAST THE DESCRIPTION + rts + + +; ------------------- +; FETCH A PROPERTY ID +; ------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +; +PROPN: + jsr FETCHB ; get the byte + and #%00111111 ; MASK OUT LENGTH BITS (EZIP) + rts + +; ------------------------------- +; FETCH # BYTES IN PROPERTY VALUE +; ------------------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +; +PROPL: + jsr FETCHB ; CHECK LENGTH FLAGS + tax ; save it + bpl SHORT ; OFF, SO 1 OR 2 BYTES + jsr NEXTFPC + jsr FETCHB ; NEXT BYTE HAS LENGTH + and #%00111111 ; MASK OFF EXTRA BITS + rts +SHORT: + and #%01000000 ; BIT 6 + beq ONE + lda #2 ; BIT 6 = 1, LENGTH =2 + rts +ONE: + lda #1 ; BIT 6 = 0, LENGTH =1 + rts + +; ---------------------- +; POINT TO NEXT PROPERTY +; ---------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - in [FPC]) +; +PROPNX: + jsr PROPL ; GET LENGTH OF CURRENT PROP + tay ; move one more for correct alignment + iny ; okay, done it + tya ; thanks + jsr ADDFPC ; add to [FPC] + rts +; +; ---------------- +; GET OBJECT FLAGS +; ---------------- +; ENTRY: OBJECT # IN [ARG1], FLAG # IN [ARG2] +; EXIT: FLAG WORD IN [K], BIT ID IN [J], +; FLAG WORD ADDRESS IN [FPC] +; +FLAGSU: + LDA ARG1+LO ; get table offset + LDX ARG1+HI + JSR OBJLOC ; GET OBJECT ADDR IN [FPC] + LDA ARG2+LO ; LOOK AT FLAG ID + CMP #$10 ; FIRST SET OF FLAGS? + BCC FLS1 ; YES, ADDR IN [FPC] IS CORRECT + SBC #16 ; ELSE ZERO-ALIGN FLAG INDEX + TAX ; SAVE IT HERE + CMP #$10 ; CHECK IF IN 2ND WORD + BCC FLS ; YES, GO ALIGN FOR THAT + SBC #16 ; ELSE ALIGN TO 3RD WORD + TAX + lda #4 ; 3rd Flag word + bne FLSx ; and add it in +FLS: + lda #2 ; 2nd Flag word +FLSx: + jsr ADDFPC +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: + jsr FETCHB ; MOVE THE FLAG WORD + sta K+HI ; INTO [K] - FIRST THE MSB + jsr NEXTFPC ; and then get get LSB + jsr FETCHB + sta K+LO ; THEN THE LSB + jmp PREVFPC ; point back to flag word + + END diff --git a/apple/yzip/ice/ops012.asm b/apple/yzip/ice/ops012.asm new file mode 100644 index 0000000..0af75d9 --- /dev/null +++ b/apple/yzip/ice/ops012.asm @@ -0,0 +1,1187 @@ + TITLE "Apple ][ YZIP (c)Infocom","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: LDX #5 ;MOVE ZPC INTO MPC +ZPRI1: + LDA ZPC,X + STA MPC,X + DEX + BPL ZPRI1 ;NO NEED TO VALIDATE AS ZPC WAS VALID ANYWAY + JSR PZSTR ; PRINT THE Z-STRING AT [MPC] + LDX #5 ; COPY STATE OF [MPC] +ZPRI2: LDA MPC,X ; INTO [ZPC] + STA ZPC,X + DEX + BPL ZPRI2 + RTS + + +; ------ +; PRINTR +; ------ +; DO A "PRINTI," FOLLOWED BY "CRLF" AND "RTRUE" + +ZPRR: JSR ZPRI + JSR ZZCRLF + JMP ZRTRUE + + +; ------ +; RSTACK +; ------ +; "RETURN" WITH VALUE ON STACK + +ZRSTAK: JSR POPVAL ; GET VALUE INTO [X/A] + JMP ZRT1 ; AND GIVE IT TO "RETURN" + + +; ----- +; CATCH +; ----- + +ZCATCH: LDX OLDZSP+HI ; RETURN ZSTACK POINTER AS + LDA OLDZSP+LO ; ZRET WILL NEED IT + JMP PUTBYT + + +; --------- +; ORIGINAL? +; --------- + +; COPY PROTECTION DEVICE, RETURNS TRUE FOR NOW + +ZORIG: JMP PREDS + + + TITLE "Apple ][ YZIP (c)Infocom","--- 1-OPS ---" + PAGE + + +; ----- +; 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC ; GET OBJECT ADDR INTO [FPC] + lda #8 ; POINT TO "NEXT" SLOT (EZIP) + jsr ADDFPC ; and point to it + jmp FIRST1 ; JMP to get it + +; ------ +; FIRST? +; ------ +; RETURN "FIRST" POINTER IN OBJECT [ARG1] ; +; FAIL IF LAST AND RETURN ZERO +; (EZIP ALTERATIONS) + +ZFIRST: + lda ARG1+LO + ldx ARG1+HI + jsr OBJLOC ; GET OBJECT ADDR INTO [FPC] + lda #10 ; point to "First" slot + jsr ADDFPC ; and add it +FIRST1: + jsr FETCHB ; and get it + pha ; save it + jsr NEXTFPC + jsr FETCHB ; and next one + tay ; now dance around a little; save LSB + pla ; get MSB back + tax ; and put to x + tya ; and put LSB back into [A] + jsr PUTBYT ; PASS IT TO VARIABLE + lda VALUE+LO ; EXAMINE THE VALUE JUST "PUT" + bne PFINE + lda VALUE+HI + beq PYUCK ; FAIL IF IT WAS ZERO +PFINE: + jmp PREDS ; ELSE REJOICE + +; --- +; LOC +; --- +; RETURN THE OBJECT CONTAINING OBJECT [ARG1] ; +; RETURN ZERO IF NONE +; (EZIP ALTERED) + +ZLOC: + lda ARG1+LO + ldx ARG1+HI + jsr OBJLOC ; GET ADDR OF OBJECT INTO [FPC] + lda #6 ; POINT TO "LOC" SLOT + jsr ADDFPC ; and make FPC point there + jsr FETCHB ; go get byte + pha ; save this please + jsr NEXTFPC ; and point to next one + jsr FETCHB ; and get it in [A] + tay ; save LSB + pla ; get MSB back + tax ; and put to [X] + tya ; and put LSB into a + jmp PUTBYT ; AND SHIP IT OUT + +; ------ +; PTSIZE +; ------ +; RETURN LENGTH OF PROP TABLE [ARG1] IN BYTES + +ZPTSIZ: + lda ARG1+HI ; MOVE ABS ADDR OF + jsr SETPC ; get bank/page + sta FPCH ; save page + sty FPCBNK ; and bank + lda ARG1+LO + sta FPCL ; and save lo part + jsr PREVFPC ; Decrement address while moving LSB +PTZ0: + jsr FETCHB ; get length of property + bmi PTZ2 ; BIT 7 = 1, LENGTH > 2 BYTES + and #%01000000 + beq PTZ1 ; BIT 6 = 0, LENGTH = 1 + lda #2 ; BIT 6 = 1, LENGTH = 2 + bne PTZ3 ; JMP +PTZ1: + lda #1 + bne PTZ3 ; JMP +PTZ2: + jsr FETCHB ; and get it + and #%00111111 ; ELSE PICK UP SIZE > 2 +PTZ3: + ldx #0 ; CLEAR FOR PUTBYT + jmp PUTBYT +; --- +; INC +; --- +; INCREMENT VARIABLE [ARG1] + +ZINC: LDA ARG1+LO + JSR VARGET ; FETCH VARIABLE INTO [VALUE] + INC VALUE+LO + BNE ZINC1 + INC VALUE+HI +ZINC1: JMP ZD0 + + +; --- +; DEC +; --- +; DECREMENT VARIABLE [ARG1] + +ZDEC: LDA ARG1+LO + JSR VARGET ; FETCH VAR INTO [VALUE] + LDA VALUE+LO + SEC + SBC #1 + STA VALUE+LO + LDA VALUE+HI + SBC #0 + STA VALUE+HI +ZD0: LDA ARG1+LO ; PUT RESULT BACK + JMP VARPUT ; INTO THE SAME VARIABLE + + +; ------ +; PRINTB +; ------ +; PRINT Z-STRING AT [ARG1] + +ZPRB: + lda ARG1+LO ; move arg1 to I + sta I+LO ; lo part + lda ARG1+HI ; and now for arg1 hi + sta I+HI ; okay + jsr SETWRD ; make [MPC] point to it + jmp PZSTR ; and print it + +; ------ +; REMOVE +; ------ +; MOVE OBJECT [ARG1] INTO PSEUDO-OBJECT #0 +; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO +; 2) MOVES AND COMPARES 2 BYTES) + +SAVEFPC: ds 3 ; spot to save the FPC + +ZREMOV: + lda ARG1+LO ; GET SOURCE OBJECT ADDR + ldx ARG1+HI + jsr OBJLOC ; INTO [FPC] +; +; now save this objects address in I,J +; + lda #6 ; point to the LOC slot + jsr ADDFPC ; thank you + lda FPCL ; COPY THE SOURCE ADDR + sta SAVEFPC+LO ; INTO [J] + lda FPCH ; FOR LATER REFERENCE + sta SAVEFPC+HI + lda FPCBNK + sta SAVEFPC+ABANK +; +; now go get object this one is in +; + jsr FETCHB ; get the data + sta K ; HOLD IT + jsr NEXTFPC ; get lo part + jsr FETCHB ; now get part + tay ; save it + ora K ; COMPARE BYTES + bne REMVj ; check for object + jmp REMVEX ; SCRAM IF NO OBJECT +REMVj: + tya ; get lo part + ldx K ; and hi part + jsr OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [FPC] + lda #11 ; POINT TO "FIRST" SLOT, LSB + jsr ADDFPC ; and point to it + jsr FETCHB ; and get it + pha ; save LSB + jsr PREVFPC ; point to MSB + jsr FETCHB ; A=LO, X=HI + tax ; put into x + pla ; get LSB back + cmp ARG1+LO ; IS THIS THE FIRST? + bne REMVC1 ; NO, KEEP SEARCHING + cpx ARG1+HI ; HM? + beq DO_REMOVE +REMVC1: + jsr OBJLOC ; get object + lda #9 ; GET "NEXT" slot address + jsr ADDFPC ; into FPC + jsr FETCHB ; get the byte + pha ; save LSB for later + jsr PREVFPC ; and this is the hi part + jsr FETCHB + tax ; and put into x for (possible) check + pla ; get lo part back + cmp ARG1+LO ; FOUND IT? + bne REMVC1 ; NO, KEEP TRYING + cpx ARG1+HI + bne REMVC1 +DO_REMOVE: +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; copied +; +; now get removed one's address for fetching +; + lda SAVEFPC+ABANK ; this is where bank is + sta FPCBNK ; so show it + lda SAVEFPC+HI ; and here's the hi/lo part + sta FPCH + lda SAVEFPC+LO + sta FPCL + lda #2 ; so get to source's "NEXT" slot + jsr ADDFPC ; point to next slot + jsr FETCHB ; get the hi byte + jsr STASHB ; and save it + jsr NEXTSPC ; point to next one + jsr NEXTFPC ; and from the source too + jsr FETCHB ; get lo byte + jsr STASHB ; and save it away +; +; now zero out SOURCE's loc and next spots +; + lda SAVEFPC+ABANK ; bank of source + sta SPCBNK + lda SAVEFPC+HI ; and addr of source LOC slot + sta SPCH + lda SAVEFPC+LO + sta SPCL +; +; zero out NEXT and LOC of source +; + lda #0 ; zero out 4 locations (LOC MSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (LOC LSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (NEXT MSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (NEXT LSB) + jsr STASHB + jsr NEXTSPC +REMVEX: + RTS + + +; ------ +; PRINTD +; ------ +; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + +ZPRD: + lda ARG1+LO + ldx ARG1+HI ; (EZIP) + jsr OBJLOC ; GET ADDR OF OBJECT INTO [FPC] + lda #13 ; GET PROP TABLE POINTER (EZIP) + jsr ADDFPC ; and point to LSB + jsr FETCHB ; fetch LSB + pha ; SAVE IT HERE + jsr PREVFPC ; and now fetch MSB + jsr FETCHB ; thank you + sta I+HI ; AND MSB + pla ; get LSB back + sta I+LO ; STORE LSB + 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+LO ; RE-SYNC THE + STA ZSP+LO ; Z-STACK POINTER + LDA OLDZSP+HI + STA ZSP+HI + JSR POPVAL ; POP # LOCALS INTO [X/A] + STX I+HI ; SAVE HERE + JSR POPVAL ; now we need number of args + STA ASSVLU ; for ASSIGNED? + + LDX I+HI ; see how many 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 IRET + STA ZPCL + JSR POPVAL + STX OLDZSP+LO + STA OLDZSP+HI + + LDA ZPCL ; check for zero zpc + BNE RETj ; which means we are returning to + LDA ZPCM ; an internal call + BNE RETj ; rather than just a normal + LDA ZPCH ; return + BNE RETj ; but so far it isn't + + JSR A12VAL ; MOVE [ARG1] TO [VALUE] + JMP ZIRET ; so then do internal return +RETj: + JSR VLDZPC ; MAKE VALID + LDA IRET ; CHECK IF SHOULD RETURN A VALUE + BEQ RETYES ; (0 = RET, 1 = NO RETURN) + RTS ; NO, SO JUST GET OUT OF HERE +RETYES: + 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 (QUAD) 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 + + + + TITLE "Apple ][ YZIP (c)Infocom","--- 2-OPS ---" + PAGE + + +; ----- +; 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 + + +; ----------------- +; SIGNED COMPARISON +; ----------------- +; ENTRY: VALUES IN [VALUE] AND [I] +; +; IS [VALUE] > [I] +; +COMPAR: + LDA I+HI + EOR VALUE+HI + BPL SCMP + LDA I+HI + CMP VALUE+HI + BCC PGOOD + JMP PREDF + +SCMP: LDA VALUE+HI + CMP I+HI + BNE SCEX + LDA VALUE+LO + CMP I+LO +SCEX: BCC PGOOD + JMP PREDF + + +; --- +; IN? +; --- +; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? +ZIN: + LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [FPC] + LDA #6 ; POINT TO "LOC" SLOT + jsr ADDFPC ; and point to it + jsr FETCHB ; well? + CMP ARG2+HI ; IS IT THERE? + BNE PBAD ; NO + jsr NEXTFPC ; point to lo part + jsr FETCHB ; and get it + CMP ARG2+LO + 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 + + ; FALL THROUGH ... + + +; --------------------- +; RETURN VALUE IN [X/A] +; --------------------- + +VEXIT: STX VALUE+LO + STA VALUE+HI + JMP PUTVAL + + +; ---- +; BAND +; ---- +; RETURN [ARG1] "AND" [ARG2] + +ZBAND: LDA ARG1+LO + AND ARG2+LO + TAX + LDA ARG1+HI + AND ARG2+HI + JMP VEXIT + + +; ----- +; FSET? +; ----- +; IS FLAG [ARG2] SET IN OBJECT [ARG1]? + +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 [FPC] +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; okay, done it + lda K+HI ; FIRST DO MSBS + ora J+HI + jsr STASHB + jsr NEXTSPC + lda K+LO ; THEN LSBS + ora J+LO + jsr STASHB + rts + + +; ------ +; FCLEAR +; ------ +; CLEAR FLAG [ARG2] IN OBJECT [ARG1] + +ZFCLR: + jsr FLAGSU ; GETS BITS INTO [J] & [K], ADDR IN [FPC] +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; okey dokey + + lda J+HI ; FETCH MSB + eor #$FF ; COMPLEMENT IT + and K+HI ; RUB OUT FLAG + jsr STASHB ; and save it + jsr NEXTSPC ; point to lo part + lda J+LO ; SAME FOR LSB + eor #$FF + and K+LO + jsr STASHB ; and show it to the world + 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] +; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + +ZMOVE: + jsr ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS +; +; Make [ARG1] be first in [ARG2]'s chain. +; + lda ARG2+LO + ldx ARG2+HI ; Get parent's address + jsr OBJLOC ; into [FPC] + lda #10 ; point to FIRST slot + jsr ADDFPC ; okay + jsr FETCHB ; get old first one (MSB) + sta K+HI ; save it + jsr NEXTFPC ; point to next part + jsr FETCHB ; and get it + sta K+LO ; okay, saved + jsr FP2SP ; make FPC == SPC +; +; now make object [ARG1] be first in object [ARG2] +; SPC is currently pointing to LSB of [ARG2]'s FIRST slot +; + lda ARG1+LO ; stash away low part first + jsr STASHB ; stashed + jsr PREVSPC ; point to high part + lda ARG1+HI ; get hi part of source + jsr STASHB ; save it +; +; now point to object [ARG1] to update its slots +; + ldx ARG1+HI ; put hi part here + lda ARG1+LO ; and lo part here for OBJLOC + jsr OBJLOC ; get me the SOURCE of all confusion + lda #6 ; point to LOC slot + jsr ADDFPC ; and now FPC points there + jsr FP2SP ; now make it the STASH pointer +; +; update [ARG1]s LOC pointer to be [ARG2] +; SPC points to LOC slot +; + lda ARG2+HI ; get PARENT number + jsr STASHB ; and save it in LOC + jsr NEXTSPC ; and point to LSB of LOC + lda ARG2+LO ; got parent's lowness + jsr STASHB ; and saved it in ARG1 +; +; Move old FIRST object and make it [ARG1]s NEXT +; now SPC points to [ARG1]s NEXT slot +; + jsr NEXTSPC ; point to MSB of NEXT + lda K+HI ; get old FIRST one + jsr STASHB ; and save it + jsr NEXTSPC ; and point to LSB now + lda K+LO ; get LSB of this + jsr STASHB ; saved + 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 + LDA #0 + 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 + ADC #0 ; PICK UP CARRY FROM MPCM + STA MPCH ; TO GET TOP BIT + JMP VLDMPC + + +; ---- +; GETP +; ---- +; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 + +ZGETP: + jsr PROPB ; set up FPC +GETP1: + jsr PROPN ; GET ID OF PROP TBL + cmp ARG2+LO ; Compare PROP ID + beq GETP3 ; FOUND IT + bcc GETP2 ; NOT THERE + jsr PROPNX ; GET NEXT PROP, ALIGN [FPC] TO IT + jmp GETP1 ; TRY AGAIN WITH NEXT PROP +; +; PROPERTY NOT THERE, GET DEFAULT +; +GETP2: + lda ARG2+LO ; GET PROPERTY # + sec ; ZERO-ALIGN IT + sbc #1 + asl A ; WORD-ALIGN IT + clc ; add in table start + adc ZBEGIN+ZOBJEC+1 ; add lo part + sta FPCL ; save for fetch + lda ZBEGIN+ZOBJEC ; now get hi part + adc #0 ; pick up carry, if any + jsr SETPC ; get memory spot for this page + sta FPCH ; page and + sty FPCBNK ; bank + jsr FETCHB ; GET MSB OF PROPERTY + sta VALUE+HI + jsr NEXTFPC + jsr FETCHB ; DO SAME WITH LSB + sta VALUE+LO + jmp PUTVAL ; RETURN DEFAULT IN [VALUE] +GETP3: + jsr PROPL ; GET LENGTH OF PROP INTO [A] + tax ; save [A] + jsr NEXTFPC ; MAKE [FPC] POINT TO 1ST BYTE OF PROP + cpx #1 ; IF LENGTH =1 + beq GETPB ; GET A BYTE PROPERTY + cpx #2 ; IF LENGTH = 2 + beq GETPW ; GET A WORD PROPERTY + + ; *** ERROR #7: PROPERTY LENGTH *** + + LDA #7 + JMP ZERROR +; +; GET A 1-BYTE PROPERTY +; +GETPB: + jsr FETCHB ; GET LSB INTO [A] + sta VALUE+LO ; STORE LSB + lda #0 ; CLEAR MSB + sta VALUE+HI ; and zero it + beq ETPEX +; +; GET A 2-BYTE PROPERTY +; +GETPW: + jsr FETCHB ; GET MSB + sta VALUE+HI ; store MSB + jsr NEXTFPC ; POINT TO LSB + jsr FETCHB ; GET IT INTO [A] + sta VALUE+LO ; AND MSB +ETPEX: + jmp PUTVAL + +; ----- +; GETPT +; ----- +; RETURN POINTER TO PROP TABLE [ARG2] +; IN OBJECT [ARG1] + +ZGETPT: + lda ARG1+LO + ldx ARG1+HI ; (EZIP) + jsr OBJLOC ; put location into [FPC] + lda #12 ; get offset table pointer + jsr ADDFPC ; and point to it + jsr FETCHB ; get MSB of table pointer + pha ; save page + jsr NEXTFPC ; point to LSB + jsr FETCHB ; and get it + sta FPCL ; and save it + pla ; get page address back + jsr SETPC ; and absolutize it + sta FPCH ; and save page + sty FPCBNK ; and bank + jsr FETCHB ; GET LENGTH OF SHORT DESC + asl A ; WORD-ALIGN IT + tay ; now point to just past it + iny ; thank you + tya ; for adding + jsr ADDFPC ; and POINT JUST PAST THE DESCRIPTION +GETPT1: + jsr PROPN ; get prop ID + cmp ARG2+LO ; CHECK ID + beq GETPT2 + bcs DDD ; .GE. so check some more + jmp DORET ; BEYOND IT, SO NOT THERE +DDD: + jsr PROPNX ; point to next one + jmp GETPT1 ; next please +GETPT2: + jsr PROPL ; get the length of this property + jsr NEXTFPC ; INC TO POINT AT PROPERTY VALUE (EZIP) +; +; now subtract absolute address to get relative address for returning +; what a pain in the neck +; + lda FPCBNK ; check which bank we are in + beq GETPB0 ; in main bank, it's easier +; +; if in AUX bank, then we must subtract beginning of AUX mem, then +; add in size of MAIN bank +; + lda FPCH ; get page + cmp # HIGH Z3BEGIN ; in part 2 of aux? + bcs GETPB3 ; ayyup + sec ; and subtract + sbc # HIGH Z2BEGIN ; first page in aux + clc ; now add in how many pages in main + adc #P2PAGE ; now we have relative start + bne GETP15 ; JUMP to putval +GETPB3: + sec ; and subtract + sbc # HIGH Z3BEGIN ; first page in aux, part 2 + clc ; now add in how many pages in main + adc #P3PAGE ; now we have relative start + bne GETP15 ; jump to putval +GETPB0: + lda FPCH ; get page in main mem + sec ; and then subtract + sbc # HIGH ZBEGIN ; start of main mem +GETP15: + sta VALUE+HI ; save hi part for returning + lda FPCL ; and just save lo part + sta VALUE+LO ; okay? + jmp PUTVAL ; AND RETURN +DORET: + jmp RET0 ; ELSE RETURN A ZERO + + +; ----- +; NEXTP +; ----- +; RETURN INDEX # OF PROP FOLLOWING PROP [ARG2] IN OBJECT [AR +; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO + +ZNEXTP: + JSR PROPB ; ALIGN [FPC] AT PROPERTY TBL'S 1ST ENTRY + 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 (EZIP) + JMP NXTP1 +NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +NXTP3: JSR PROPN ; GET THE PROPERTY # + LDX #0 ; FOR PUTBYT (EZIP) + 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 + + +; ----- +; THROW +; ----- + +ZTHROW: LDA ARG2+LO ; SET ZSTACK POINTER + STA OLDZSP+LO ; UP FOR ZRET + LDA ARG2+HI + STA OLDZSP+HI + JMP ZRET + + END diff --git a/apple/yzip/ice/opsx.asm b/apple/yzip/ice/opsx.asm new file mode 100644 index 0000000..b0f4210 --- /dev/null +++ b/apple/yzip/ice/opsx.asm @@ -0,0 +1,901 @@ + TITLE "Apple ][ YZIP (c)Infocom","X-OPS" + + ; ------ + ; EQUAL? + ; ------ + ; IS [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? + +ZEQUAL: + DEC NARGS ; DOUBLE-CHECK # ARGS + 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!) + + +; ---------------------------- +; ICALL,ICALL1, ICALL2, IXCALL +; ---------------------------- + +ZICALL: +ZICLL1: +ZICLL2: +ZIXCLL: LDA #1 ; SET FLAG FOR RETURNLESS CALL + STA IRET + BNE IENTR ; JMP OVER NORMAL SETTING + + +; ------------------- +; XCALL, CALL1, CALL2 +; ------------------- + +ZXCALL: ; DROP THROUGH +ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +ZCALL2: + +; ---- +; CALL +; ---- +; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +; ([ARG5]-[ARG8] FOR XCALL (EZIP)) + +ZCALL: LDA #0 + STA IRET ; SET FLAG TO RETURN SOMETHING +IENTR: LDA ARG1+LO + ORA ARG1+HI ; IS CALL ADDRESS ZERO? + BNE DOCALL ; NO, CONTINUE + LDA IRET ; any ret value? + BEQ Ij ; yes, so return a zero + + RTS ; otherwise, just end +Ij: + LDX #0 + JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER + LDA OLDZSP+HI + JSR PUSHXA + LDA ZPCL ; AND LSB OF [ZPC] + LDX IRET ; AND RETURN FLAG + 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 + ASL ARG1+LO ; MULTIPLY [ARG1] + ROL ARG1+HI ; (BY 2) + ROL A ; >BIT INTO [A] + ASL ARG1+LO ; BY 4 (EZIP) + ROL ARG1+HI + ROL A + STA ZPCH ; NEW >BIT OF [ZPC] + LDA ARG1+HI ; GET NEW 0, just ignore! + ORA ARG3+LO + BEQ INTNF ; SAY NOT FOUND + + LDA NARGS ; IS THERE A RECORD SPEC? + CMP #4 + BEQ SET4 +SETDEF: LDA #130 ; NO, SET DEFAULT + STA ARG4+LO + +SET4: LDA ARG4+LO + BEQ SETDEF ; GO BACK AND GET VALUE + LDA #0 ; COMPARE BYTE OR WORD? + ASL ARG4+LO + ROL A ; PICK UP INDICATOR + LSR ARG4+LO ; CLEAR FROM RECORD LENGTH + STA TYPE ; BYTE (0) OR WORD (1) + LDA TYPE ; SET FLAG + BNE SETTBL + LDA ARG1+LO ; IF ONLY BYTE, MOVE IT + STA ARG1+HI ; TO FIRST BYTE CHECKED +SETTBL: + LDA ARG2+LO ; PICK UP TBL ADDR + STA MPCL + LDA ARG2+HI + STA MPCM + LDA #0 + STA MPCH ; ONLY A WORD ADDR, SO IN 1ST 64K + JSR VLDMPC + +INTLP: LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + JSR GETBYT ; GET 1ST BYTE + CMP ARG1+HI ; DOES IT = THE VALUE LOOKING FOR? + BNE INTNXT ; NO + LDA TYPE + BEQ INTFND ; ONLY COMPARING A BYTE SO FOUND! + JSR GETBYT + CMP ARG1+LO + BEQ INTFND ; YES, FOUND IT +INTNXT: + LDA VWCUR+0 ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC ARG4+LO ; ENTRY + STA MPCL + BCC INEXT0 + + LDA VWCUR+1 ; PICK UP CARRY + ADC #0 + STA MPCM + LDA VWCUR+2 + ADC #0 + STA MPCH + JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE + +INEXT0: DEC ARG3+LO ; CHECKED ALL ENTRIES? + BNE INTLP + LDA ARG3+HI + BEQ INTNF + DEC ARG3+HI + BNE INTLP + +INTNF: + LDA #0 ; 0 = NOT FOUND + STA VALUE+LO + STA VALUE+HI + JSR PUTVAL + JMP PREDF ; FAILED! + +INTFND: + LDA VWCUR+LO + STA VALUE+LO ; AND SET TO RETURN THE VALUE + LDA VWCUR+HI + STA VALUE+HI + JSR PUTVAL ; SEND IT BACK + JMP PREDS ; AND SCREEM SUCCESS + +; ---- +; BCOM +; ---- +; COMPLEMENT [ARG1] + +ZBCOM: LDA ARG1+LO + EOR #$FF + STA VALUE+LO + LDA ARG1+HI + EOR #$FF + STA VALUE+HI + JMP PUTVAL + + +; ----- +; COPYT +; ----- + +ZCOPYT: + LDA ARG2+LO ; CHECK OUT WHAT'S TO BE DONE + ORA ARG2+HI + BNE ZC0 + JMP CASE1 ; ZERO LENGTH BYTES OF SOURCE +ZC0: + LDA ARG3+HI + CMP #$7F + BCC CASE2 + JMP CASE3 ; FORWARD COPY + + ; CASE2 - CHECK IF FORWARD OR BACKWARD COPY + +CASE2: LDA ARG1+HI ; IF SRC < DEST + CMP ARG2+HI + BCC CHK2 + BEQ ZC1 + JMP FRWRD ; NO +ZC1: LDA ARG1+LO + CMP ARG2+LO + BEQ CHK2 + BCS FRWRD ; NO +CHK2: LDA ARG1+LO ; AND SRC + LENGTH > DEST + CLC + ADC ARG3+LO + STA I+LO + LDA ARG1+HI + ADC ARG3+HI + CMP ARG2+HI + BCC FRWRD ; NO + BNE BKWRD ; YES + LDA I+LO + CMP ARG2+LO + BEQ FRWRD ; DEBUG, IF EQUAL REALLY LESS + BCS BKWRD ; OVERLAPS SO DO BACKWARD COPY + + ; ELSE FALL THROUGH TO FORWARD COPY + +FRWRD: LDA #0 ; USE GETBYT CAUSE MAY BE + STA MPCH ; BEYOND MAIN MEMORY + LDA ARG1+HI + STA MPCM + LDA ARG1+LO + STA MPCL + JSR VLDMPC ; AND ALIGN TO CORRECT PAGE + LDA ARG2+LO + STA SPCL + LDA ARG2+HI + jsr SETPC ; get memory spot + sta SPCH ; high part + sty SPCBNK ; and the bank part + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI +FRLP: + jsr DECJ + bcc FRDUN ; CARRY CLEAR ON $FFFF + jsr GETBYT + jsr STASHB ; and save it + jsr NEXTSPC ; and point to next one + jmp FRLP +FRDUN: + rts + + +BKWRD: + LDA ARG3+LO ; DECR 1ST TO GET CORRECT OFFSET + STA J+LO + LDA ARG3+HI + STA J+HI + JSR DECJ + LDA ARG1+LO ; SET TO END OF SOURCE & DEST. + CLC + ADC J+LO + sta FPCL ; set up fetch pointer + LDA ARG1+HI + ADC J+HI + jsr SETPC ; and get mem locations + sta FPCH + sty FPCBNK + LDA ARG2+LO + CLC + ADC J+LO + sta SPCL ; and now set up stash pointer + LDA ARG2+HI + ADC J+HI + jsr SETPC ; and get me page/bank + sta SPCH + sty SPCBNK +BKLP: + jsr FETCHB ; get byte + jsr STASHB ; and save it + jsr PREVFPC ; going backwards + jsr PREVSPC ; and here too + jsr DECJ ; RETURNS CARRY CLEAR ON $FFFF + bcs BKLP +BKDUN: + RTS + + ; ZERO LENGTH # OF BYTES OF SOURCE + +CASE1: LDA ARG1+LO + STA SPCL ; set stash pointer + LDA ARG1+HI + jsr SETPC ; get page/bank + sta SPCH + sty SPCBNK + LDA ARG3+LO ; SET UP COUNTER + STA J+LO + LDA ARG3+HI + STA J+HI +C1LP: + jsr DECJ ; CARRY CLEAR WHEN J = $FFFF + bcc C1DUN + lda #0 + jsr STASHB ; and zero it + jsr NEXTSPC ; and point to next one + jmp C1LP +C1DUN: + rts + + ; 2'S COMPLEMENT LENGTH (XOR + 1) THEN DO FORWARD COPY + +CASE3: + LDA ARG3+LO + EOR #$FF + STA ARG3+LO + LDA ARG3+HI + EOR #$FF + STA ARG3+HI + INC ARG3+LO + BNE GOFRWD + INC ARG3+HI +GOFRWD: JMP FRWRD + + +; --------- +; ASSIGNED? +; --------- + + +ZASSND: + LDA ARG1+LO ; COMPARE TO # OF OPTIONALS FROM LAST CALL + CMP ASSVLU + BCC DOYES ; IF LESS OR EQUAL, WAS ASSIGNED + BEQ DOYES + JMP PREDF +DOYES: + JMP PREDS + + +; ------------- +; LOGICAL SHIFT +; ------------- +; SHIFT ARG1, ARG2 BITS (LEFT IF ARG2 IS POS. RIGHT IF NEG.) + +ZSHIFT: LDA ARG1+LO ; SET UP FOR SHIFT + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCS SRIGHT + + ; SHIFT LEFT + + TAY ; COUNT +SLP1: ASL VALUE+LO + ROL VALUE+HI + DEY + BNE SLP1 + JMP PUTVAL ; AND RETURN THE VALUE + +SRIGHT: EOR #$FF ; COMPLEMENT + TAY +SLP2: LSR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL SLP2 + JMP PUTVAL + + +; ---------------- +; ARITHMETIC SHIFT +; ---------------- +; PROPAGATING SIGN BIT ON RIGHT SHIFT + +ZASHFT: LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCC ZSHIFT ; SAME AS LOGICAL SHIFT + LDX ARG1+LO ; SET UP FOR SHIFT + STX VALUE+LO + LDX ARG1+HI + STX VALUE+HI + + EOR #$FF ; COMPLEMENT COUNT + TAY +ASLP2: LDA ARG1+HI + ASL A ; GET SIGN BIT + ROR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL ASLP2 + JMP PUTVAL + +; -------- +; XPUSH +; -------- +ZXPUSH: + lda ARG2+LO ; get me the address of the LTABLE + sta FPCL ; for munging with + lda ARG2+HI ; this is page + jsr SETPC ; get me actual page/bank + sta FPCH ; set page + sty FPCBNK ; and bank + + jsr FETCHB ; this is hi part of counter + sta J+HI ; save it + jsr NEXTFPC ; point to lo part + jsr FETCHB ; get it + sta J+LO ; thanx + ora J+HI ; check for zero elements left + bne ZXP0 ; yes, there is room at the inn + + jmp PREDF ; no room here! +ZXP0: + jsr FP2SP ; set up to stash back in beginning of LTABLE + lda J+HI ; now the MSB + sta K+HI ; and saved it + lda J+LO ; save this + sta K+LO ; save it +; +; now count this one and stash it into the table +; + bne ZXP1 ; nope, dec okay + dec J+HI ; decrement MSB +ZXP1: + dec J+LO ; and the LSB + lda J+LO ; LSB first + jsr STASHB ; saved it + jsr PREVSPC ; point to MSB + lda J+HI ; get it + jsr STASHB ; saved it +; +; finally, we can save the arg into the stack +; + asl K+LO ; make a word offset (*2) + rol K+HI ; pick up carry maybe + lda K+LO ; add in arg offset + clc ; adding + adc ARG2+LO ; figger offset + sta SPCL ; this goes here for stashing + lda K+HI ; now page + adc ARG2+HI ; add in start of table + jsr SETPC ; get me memory page + sta SPCH ; page + sty SPCBNK ; and bank + + lda ARG1+HI ; push MSB + jsr STASHB ; saved + jsr NEXTSPC ; point to next one + lda ARG1+LO ; and now LSB + jsr STASHB ; into the stack + jmp PREDS ; show we worked good +;--------- +; ZFSTACK +;--------- +ZFSTACK: + dec NARGS ; how many args there? + bne ZFS1 ; flush ARG2 stack +; +; pop from system stack +; + lda ARG1+LO ; just add number to system counter + clc ; adding + adc ZSP+LO ; added + sta ZSP+LO ; and saved + lda ARG1+HI ; get hi part + adc ZSP+HI ; add in hi part + sta ZSP+HI ; save hi part + rts +ZFS1: + lda ARG2+LO ; get LTABLE we are interested in + sta FPCL ; set up FPC first + lda ARG2+HI ; and page + jsr SETPC ; tell me where + sta FPCH ; save me where + sty FPCBNK ; FPC all set + jsr FP2SP ; have SPC point to stack too + + jsr FETCHB ; get MSB of counter + sta J+HI ; save MSB + jsr NEXTFPC ; point to LSB + jsr FETCHB ; get LSB + sta J+LO ; save LSB + + lda J+LO ; get LSB back + clc ; get ready for add + adc ARG1+LO ; add how many to get rid off + sta J+LO ; save new counter + lda J+HI ; get MSB + adc ARG1+HI ; add MSB + + jsr STASHB ; save Msb of new counter + jsr NEXTSPC ; point to LSB + lda J+LO ; get lsb + jsr STASHB ; okay, reset the counter + rts + +; +; no mouse stuff yet +; +ZMINFO: +ZMLIMIT: + rts +ZMENU: + jmp PREDF ; no menu stuff either + + END diff --git a/apple/yzip/ice/pcp.bat b/apple/yzip/ice/pcp.bat new file mode 100644 index 0000000..794beba --- /dev/null +++ b/apple/yzip/ice/pcp.bat @@ -0,0 +1,10 @@ +@echo off +pcplus /faplyzip +ask "Load yzip.lst?", yn +if errorlevel 2 goto quit +if errorlevel 1 goto loady +:loady +b yzip.prn +:quit +cls +echo on diff --git a/apple/yzip/ice/pic.asm b/apple/yzip/ice/pic.asm new file mode 100644 index 0000000..a549d73 --- /dev/null +++ b/apple/yzip/ice/pic.asm @@ -0,0 +1,577 @@ + TITLE "Apple ][ YZIP (c)Infocom","Picture Op Codes" +PFILE_RD: ; for READING files + db 4 ; 4 parameters + db 0 ; refnum + dw IOBUFF ; read into io buffer + dw $400 ; 1Kb buffer + dw 0 ; length actually read +PFSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +NUMPIC: dw 0 ; how many entries +PICCNT: dw 0 ; counter of the entries +P_IDX: db 0 +P_BCNT: db 0 +P_LOFF: db 0 +PICINFO: + ds PLDSIZE ; get room for picture data + +TRANSCLR: DB 0 ; transparent color +UNKPIC: + db EOL,"Unkown Picture #" +UNKPICL EQU $-UNKPIC +ZDISPL: + jsr CLRBUF ; put out any and all text + jsr SAVE_CURSOR ; save the cursor pos + + jsr GET_PICINF ; get the necessary data + bcc ZDSP1 ; everything just fine + jmp GET_CURSOR ; not able to, restore cursor and die +ZDSP1: + lda #0 ; show no cursor change + sta CURSFLG ; start with none, anyway + + dec NARGS ; x,y pos passed? + beq ZDSP10 ; nope, just use as is + + lda ARG2+LO ; get passed y pos + beq ZDSP01 ; don't change + sta SCRCY ; change, then + dec SCRCY ; zero base it + ldy #WINTOP ; get top edge of window + lda (WINDOW),Y ; got it + clc ; get ready for add + adc SCRCY ; add the offset + sta SCRCY ; and make it Y pos + lda #1 ; show cursor change anyway + sta CURSFLG ; okay, we did +ZDSP01: + dec NARGS ; y pos passed? + beq ZDSP10 ; nope + + lda ARG3+LO ; get x pos + beq ZDSP10 ; if == 0, don't change + sta SCRCX ; set as passed + dec SCRCX ; zero base it + ldy #WINLEFT ; get left hand edge of window + lda (WINDOW),Y ; got it + clc ; get ready for add + adc SCRCX ; add the offset + sta SCRCX ; and make it X pos + lda #1 ; show cursor change anyway + sta CURSFLG ; okay, we did +ZDSP10: + lda CURSFLG ; see if cursor changed? + bne ZDSP101 ; it did, so restore back to here + lda SCRCX ; get current X + pha ; save it + clc ; adding + adc PICINFO+PLDWID ; add in pic width + sta SCRCX ; save here + jsr SAVE_CURSOR ; resave the cursor + pla ; get start X pos back + sta SCRCX ; restored +ZDSP101: + lda PICINFO+PLDFLG ; get flag byte + and #1 ; is there a transparent color? + bne ZDSP11 ; ayyup + lda #$FF ; make TRANSCLR be $FF + bne ZDSP12 ; okay +ZDSP11: + lda PICINFO+PLDFLG ; get hi byte of flag word + lsr A ; put in lower byte + lsr A ; put in lower byte + lsr A ; put in lower byte + lsr A ; put in lower byte +ZDSP12: + sta TRANSCLR ; save transparent color + + lda PICINFO+PLDPTR ; MSB of offset + sta PFSEEK+SM_FPOS+2 ; MSB of seek + lda PICINFO+PLDPTR+1 ; Middle + and #$FE ; seek only to 512byte boundary + sta PFSEEK+SM_FPOS+1 +; lda PICINFO+PLDPTR+2 ; LSB +; sta PFSEEK+SM_FPOS + + SET_MARK PFSEEK ; go to pic data + lda # HIGH PIC1BUF ; set up pointers to decode buffers + sta J+HI + lda # LOW PIC1BUF + sta J+LO + lda # HIGH PIC2BUF + sta K+HI + lda # LOW PIC2BUF + sta K+LO + lda #0 ; start line at zero + sta P_LOFF ; done + ldy #MAXWIDTH-1 ; clear out width buffer +ZDLI: + sta (J),Y ; init 'previous line' buffer to zero + dey ; down one + bne ZDLI + sta (J),Y ; get last one + + lda #3 ; 3 bytes of width data start it + clc ; doing add + adc PICINFO+PLDPTR+2 ; pick up LSB pointer + sta P_IDX ; start index + lda # HIGH IOBUFF ; now get data buffer address + sta L+HI + lda #4 ; 4 pages read in at once + sta P_BCNT ; okay + lda PICINFO+PLDPTR+1 ; tells which block it is in + and #$01 ; pick up which 512 block + beq ZDLP0 ; start at first one + inc L+HI ; start at second one + dec P_BCNT ; one less block +ZDLP0: + lda # LOW IOBUFF + sta L+LO + READ PFILE_RD ; read in 1kb worth of data + bcc ZDECLP ; everything went just fine + jsr DISK_ERR ; print out an error + rts ; and die +ZDECLP: + ldy P_IDX ; get data index + lda (L),Y ; get data byte + sta ARG8 ; save here + iny ; point to next one + bne ZDCLP0 ; okay, use offset + jsr NEXT_PICB ; read in next block + bcc ZDCLP0 ; everything went fine + rts ; return if not +ZDCLP0: + lda (L),Y ; is this count or data? + cmp #16 ; if <= 15, previous one was data + bcs ZDCL2 ; nope, must be compressed + lda #15 ; show 1 bytes + bne ZDCL3 ; and count this one +ZDCL2: + iny ; point to next byte + bne ZDCL3 ; okay, no wrap + pha ; save A + jsr NEXT_PICB ; check about nother block + pla ; get A back + bcc ZDCL3 ; everything came out okay + rts ; problems, return +ZDCL3: + sty P_IDX ; save index + sec ; get ready for sub + sbc #14 ; make good counter + tax ; put count into x +ZDCLPC: + ldy P_LOFF ; get line offset + lda ARG8 ; get data byte + eor (J),Y ; XOR with previous line + sta (K),Y ; and save away + iny ; next offset + sty P_LOFF ; save Y + cpy PICINFO+PLDWID ; end of line? + bne ZDCLPC1 ; nope + jsr COPY_PIC ; copy line into screen + lda SCRCY ; past bottom? + cmp #MAXHEIGHT-1 ; well? + beq ZDCLPX ; truncate at bottom then + inc SCRCY ; down one line + dec PICINFO+PLDHGHT ; count line + beq ZDCLPX ; all done then +ZDCLPC1: + dex ; count down counter + bne ZDCLPC ; do this byte again + beq ZDECLP ; check next byte +ZDCLPX: + jmp GET_CURSOR ; restore the cursor + +COPY_PIC: + txa ; save x + pha + lda SCRCX ; get start X pos + pha ; okay, saved + lda #0 ; start offset at zero + sta CH_OFFSET ; and into data buffer +CPICLOOP: + jsr SETPOS ; point to correct line + ldx BITOFF ; get starting offset + stx BITTER ; bit offset for COPY_SCRL to use + lda BIT_BITS,X ; get starting bit counter + tax ; okay, we did + lda #MAXWIDTH ; don't let screen wrap + sec ; doing sub + sbc SCRCX ; get current X pos + sta DATALOOP ; only use this many pixels + ldy #0 ; start with first byte + sty SCR_DATA ; data starts with zero + dey ; inclusive count + sty LINEOFF ; reset line offset + ldy CH_OFFSET ; start Y out + jsr PIC2SCR ; move line to screen + + lda CH_OFFSET ; current offset + cmp PICINFO+PLDWID ; did we finish whole line? + bcs COPYPIC1 ; yup, so wrap things up + adc SCRCX ; point to next start + sta SCRCX ; save it + bne CPICLOOP ; and continue with line +COPYPIC1: + lda J+HI ; get previous line + pha ; save addr + lda K+HI ; make current line be previous + sta J+HI + pla ; get old previous line back + sta K+HI ; make it be new current line + lda J+LO ; get previous line + pha ; and save it + lda K+LO + sta J+LO ; okay, it is + pla + sta K+LO ; and save new one + lda #0 ; pic offset is zero + sta P_LOFF ; done + pla ; get start X back + sta SCRCX ; restored + pla ; get X reg back + tax + rts + +PIC2SCR: + lda #4 ; 4 bits per pixel + sta ARG7 ; use zero page + lda (K),Y ; get data byte + cmp TRANSCLR ; is it transparent? + bne CPYPL1 ; nope +P2LOOP: + iny ; next pixel + cpy PICINFO+PLDWID ; done with line? + bcs P2LP1 ; yup + lda (K),Y ; get it + cmp TRANSCLR ; still transparent? + beq P2LOOP ; ayyup +P2LP1: + sty CH_OFFSET ; show where we ended up + rts +P2SLOOP: + lda (K),Y ; get data byte + cmp TRANSCLR ; is it transparent? + beq CPYSL1X ; yes, so done with this + ldy #4 ; 4 bits per pixel + sty ARG7 ; use zero page +CPYPL1: + asl A ; shift to upper nybble + asl A ; shift to upper nybble + asl A ; shift to upper nybble + asl A ; shift to upper nybble +CPYSL: + asl A ; shift into carry + ror SCR_DATA ; pick up carry + dex ; count it + bne CPYSL1 ; shift again, please +CPYSLST: + pha ; save byte + lda SCR_DATA ; get screen byte + lsr A ; move down to last 7 bits + inc LINEOFF ; point to interesting byte + ldy LINEOFF ; get offset + sta SCR_LINE,Y ; save into mem + ldx #7 ; and start bitoff at 7 + lda #0 ; clear a few locals + sta SCR_DATA ; screen data + pla ; get byte back +CPYSL1: + dec ARG7 ; count this bit + bmi CPYSLX ; all done + bne CPYSL ; not done with 'pixel' yet + inc CH_OFFSET ; point to next one + ldy CH_OFFSET ; next pixel + cpy PICINFO+PLDWID ; finished with line yet? + beq CPYSL1X ; yes, so move to screen + dec DATALOOP ; reached right edge of screen? + bne P2SLOOP ; do next pixel +CPYSL1X: + lda BIT_BITS,X ; get me number of significant bits in this byte + sta ENDBIT ; show end bit + cpx #7 ; is there a last byte to use? + beq CPYSLX ; no last byte + lda SCR_DATA ; get screen data +CPYLSH: + lsr A ; put down low, please + dex ; one more + bne CPYLSH ; and do it again + sta SCR_DATA ; save for later use + beq CPYSLST ; now save this char +CPYSLX: + jmp COPY_SCRL1 ; copy to screen + +NEXT_PICB: + pha ; save a please + + dec P_BCNT ; done all four pages? + bne NXTPX1 ; nope + + lda # HIGH IOBUFF ; reset data buffer address + sta L+HI + lda # LOW IOBUFF + sta L+LO + lda #4 ; 4 pages read in at once + sta P_BCNT ; okay + READ PFILE_RD ; read in 1kb worth of data + bcc NXTPX ; everything went just fine + jsr DISK_ERR ; print out an error + bcs NXTPXR ; and die +NXTPX1: + inc L+HI ; point to next page +NXTPX: + clc ; make sure carry is clear +NXTPXR: + ldy #0 ; start reading at beginnig of block + pla ; get [A] back + rts ; done + +GET_PDATA: + ldy #SGTPICOF ; point to picture offset + lda (DSEGS),Y ; get MSB + sta PFSEEK+SM_FPOS+2 ; Byte 2 + iny ; point to LSB + ora (DSEGS),Y ; is there any pic data? + bne GTPD00 ; yes + rts +GTPD00: + lda (DSEGS),Y ; get it for shifting + asl A ; *2 + sta PFSEEK+SM_FPOS+1 ; stash away + rol PFSEEK+SM_FPOS+2 ; pick up carry + lda #0 ; clear out MSB + sta PFILE_RD+RD_BUFFLEN+HI + sta PFSEEK+SM_FPOS ; and LSB of seeking + + SET_MARK PFSEEK ; and go to beginning + + lda #4 ; read in 4 256 blocks + sta PFILE_RD+RD_BUFFLEN+HI + READ PFILE_RD ; read in first block + bcc GTPD1 ; everything is okey + jmp DISK_ERR ; print out problem if not +GTPD1: + lda IOBUFF+PHNLD ; get number of pictures + sta NUMPIC+HI ; save MSB + sta PICCNT+HI ; save for count down too + lda IOBUFF+PHNLD+1 ; and here is LSB + sta NUMPIC+LO ; okay, we got it + sta PICCNT+LO ; saving for counting + + sta ALTZP+AUX ; use aux mem for most of this + lda #0 ; clear a few things + sta J+LO ; J = source + sta K+LO ; K = destination + lda # HIGH PIC_DIR ; start destination off here + sta K+HI ; MSB of destination + lda #4 ; 4 * (4*256) bytes max + sta PFILE_RD+RD_BUFFLEN+HI ; show the read too + sta P_IDX ; save here for counting +GTPDL: + ldy #0 ; start y + lda # HIGH IOBUFF ; get where source is + sta J+HI ; MSB of source + lda #4 ; 4 blocks worth of 256 + sta P_BCNT ; used as counter + lda BNK1SET ; we be using bank 1 @$D000 + lda BNK1SET ; we be using bank 1 @$D000 +GTPDL1: + lda (J),Y ; get the data byte + sta (K),Y ; store in upper aux + iny ; point to the next one + bne GTPDL1 ; and go get it + + inc J+HI ; next block please + inc K+HI ; for destination too + lda PICCNT+LO ; how many entries? + sec ; doing sbc + sbc #(256/PLDSIZE) ; how many entries in 256 bytes? + sta PICCNT+LO ; save result + bcs GTPDL2 ; no wrapping + dec PICCNT+HI ; wrap + bmi GTPDLX ; all done if we go negative +GTPDL2: + ora PICCNT+HI ; make sure both are not zero + beq GTPDLX ; if they are, then we are done + dec P_BCNT ; count this block + bne GTPDL1 ; go fetch next 256 bytes + sta ALTZP+MAIN ; swap back to main for read + READ PFILE_RD ; go get the next 4Kb worth + sta ALTZP+AUX ; and back to aux for working + dec P_IDX ; max 4Kb worth of reading + bne GTPDL ; and read in more +GTPDLX: + sta ALTZP+MAIN ; back to main bank of mem + lda BNK2SET ; back to bank 2 + lda BNK2SET ; yes please + rts ; all done +GTPFLAG: db 0 ; if 1 when opening next file, then + ; this is the next file, so unable to + ; find picture number +GET_PICINF: + lda #0 ; set flag for double check + sta GTPFLAG ; start at zero +GTPLOOP: + lda NUMPIC+HI ; get # of entries + sta PICCNT+HI ; MSB + lda NUMPIC+LO ; and the + sta PICCNT+LO ; LSB + lda ARG1+LO ; check argument for zero + ora ARG1+HI ; is it zero? + bne GTPINDX ; jump to look at first block + clc ; found some pictures + rts ; if zero, just give count +GTPINDX: + ldy ARG1+LO ; get arg, as we are swapping + ldx ARG1+HI ; to aux mem + sta ALTZP+AUX ; look at AUX mem + lda BNK1SET ; bank 1 + lda BNK1SET ; bank 1 + sty ARG1+LO ; use aux mem zero page + stx ARG1+HI ; for new arg1 + lda # HIGH PIC_DIR ; start at beginning of block + sta MPNTH ; hi part + lda # LOW PIC_DIR ; don't forget to start at beginning + sta MPNTL ; we are + lda #PHSIZE ; skip over header + sta P_IDX ; this is the counter +GTP3: + ldy P_IDX ; get offset + lda ARG1+HI ; check against desired one + cmp (MPCPNT),Y ; get ID hi byte + bcc GTPNOT ; arg1 < than entry, can't be here + bne GTP4 ; not it, so check next one + iny ; now to LSB + lda (MPCPNT),Y ; get it + cmp ARG1+LO ; is it what we want? + beq GTPFOUND ; found the picture + bcs GTPNOT ; arg1 < entry, cannot be here +GTP4: + lda PICCNT+LO ; get LSB + bne GTP4D ; no wrap down + dec PICCNT+HI ; count down MSB + bpl GTP4D ; everything still okay +GTPNOT: + sta ALTZP+MAIN ; back to main mem + lda BNK2SET ; back to bank 1 + lda BNK2SET ; yes please + lda GTPFLAG ; have we already tried to open another file? + beq GTPNOT1 ; nope + DLINE UNKPIC, ; unknown picture number error + lda ARG1+HI ; get MSB + jsr HEXNUM ; print it + lda ARG1+LO ; and LSB + jsr HEXNUM + lda #$14 ; bad picture number error + jmp ZERROR ; and croak +GTPNOT1: + inc GTPFLAG ; show trying next file + jsr NEXTPICF ; open other picture file + jmp GTPLOOP ; and try again +GTP4D: + dec PICCNT+LO ; count this entry + lda P_IDX ; get index + clc ; ready to add + adc #PLDSIZE ; point to next entry + sta P_IDX ; save lo part + bcc GTP3 ; no wrap + inc MPNTH ; next block + bne GTP3 ; do next block +GTPFOUND: + ldx #0 ; for copying data + dey ; point to beginning of data +GTPFL: + lda (MPCPNT),Y ; get data + sta PICINFO,X ; save data + iny ; point to new entry stuff + inx ; next x + cpx #PLDSIZE ; got it all yet (not ID, tho)? + bne GTPFL ; get data + sta ALTZP+MAIN ; back to main mem + lda BNK2SET ; back to bank 1 + lda BNK2SET ; yes please + clc ; show got data + rts + +ZPICNF: + jsr GET_PICINF ; find the info + bcs ZPICNFX ; not found +; +; being here means we found the picture +; + lda ARG2+LO ; lsb is okay + sta SPCL ; right + lda ARG2+HI ; get page + jsr SETPC ; get where it is + sta SPCH ; hi + sty SPCBNK ; bnak + lda ARG1+HI ; get argumnet + ora ARG1+LO ; check for zero arg + bne ZPIC1 ; okay, get picture data +; +; arg1 == 0, just return number of entries +; + lda PICCNT+HI ; get MSB + jsr STASHB ; and save it + jsr NEXTSPC ; point to LSB in table + lda PICCNT+LO ; get LSB + jsr STASHB ; and save it + jmp PREDS ; and show success +ZPIC1: + lda #0 ; hieght MSB + jsr STASHB ; save it too + jsr NEXTSPC ; next byte + lda PICINFO+PLDHGHT ; height LSB + jsr STASHB ; save it too + jsr NEXTSPC ; next byte + lda #0 ; width first + jsr STASHB ; put it there + jsr NEXTSPC ; continue + lda PICINFO+PLDWID ; LSB of width + jsr STASHB ; save it too + jmp PREDS +ZPICNFX: + JMP PREDF ; SET AS BAD +ZDCLR: +ZPICSET: + rts ; NOT IMPLEMENTED YET +; +; NEXTPICF - open other picture file +; +NEXTPICF: + lda DSEGS+HI ; save current DSEG + pha + lda DSEGS+LO + pha + lda GMREF ; to go back to this one + pha + ldx GAME2NML ; get length of name + lda GAME2NM,X ; get last number + cmp #'3' ; if 3, then open #4 + bne NXTPF1 ; nope + lda D4SEG+LO ; point to segment for part 4 + sta DSEGS+LO + lda D4SEG+HI + sta DSEGS+HI + lda #3 ; this opens file #4 + bne NXTPF2 ; and continue on +NXTPF1: + lda D3SEG+LO ; point to segment for part 3 + sta DSEGS+LO + lda D3SEG+HI + sta DSEGS+HI + lda #2 ; and this if for #3 +NXTPF2: + jsr FETCH_FILE ; and do it + pla ; get old ref num back + sta GMREF ; and for reading + sta PSEEK+SM_REFNUM ; this sets it up for set marking + pla ; get old DSEG back + sta DSEGS+LO + pla + sta DSEGS+HI + rts + + END diff --git a/apple/yzip/ice/prodos.equ b/apple/yzip/ice/prodos.equ new file mode 100644 index 0000000..0632f62 --- /dev/null +++ b/apple/yzip/ice/prodos.equ @@ -0,0 +1,53 @@ + TITLE "Apple ][ YZIP (c)Infocom","ProDOS EQUATES" + PAGE + +; +; some parameter structures +; +OPEN_PARM EQU 0 +OP_PCOUNT EQU OPEN_PARM ; must be 3 for open +OP_PATHNAME EQU OP_PCOUNT+1 ; address of pathname +OP_FILEBUFF EQU OP_PATHNAME+2 ; address of file data buffer +OP_REFNUM EQU OP_FILEBUFF+2 ; file reference number +OPEN_PSIZE EQU OP_REFNUM+1 ; size of parameter buffer + +READ_PARM EQU 0 ; to read things +RD_PCOUNT EQU READ_PARM ; param count (=4) +RD_REFNUM EQU RD_PCOUNT+1 ; ref num of file +RD_BUFFER EQU RD_REFNUM+1 ; where to +RD_BUFFLEN EQU RD_BUFFER+2 ; length of buffer +RD_LENGTH EQU RD_BUFFLEN+2 ; actual length of read +READ_PSIZE EQU RD_LENGTH+2 ; length of parm block + +CLOSE_PARM EQU 0 ; for closing file +CL_PCOUNT EQU CLOSE_PARM ; paramter count (=1) +CL_REFNUM EQU CL_PCOUNT+1 ; refnum of file to be closed +CLOSE_PSIZE EQU CL_REFNUM+1 ; this is the size, thank you + +WRITE_PARM EQU 0 ; to write things +WR_PCOUNT EQU WRITE_PARM ; parm count (= 4) +WR_REFNUM EQU WR_PCOUNT+1 ; file refnum +WR_BUFFER EQU WR_REFNUM+1 ; data buffer address +WR_BUFFLEN EQU WR_BUFFER+2 ; data buffer length +WR_LENGTH EQU WR_BUFFLEN+2 ; actual length written +WRITE_PSIZE EQU WR_LENGTH+2 ; length of parm block + +SETMARK_PARM EQU 0 +SM_PCOUNT EQU SETMARK_PARM ; parm count (=2) +SM_REFNUM EQU SM_PCOUNT+1 ; file refnum +SM_FPOS EQU SM_REFNUM+1 ; 3 byte file pos +SETMARK_PSIZE EQU SM_FPOS+3 ; length of parm block + +SETPREFIX_PARM EQU 0 +SP_PCOUNT EQU SETPREFIX_PARM ; parm count (=1) +SP_PATHNAME EQU SP_PCOUNT+1 ; pointer to path name +SETPREFIX_PSIZE EQU SP_PATHNAME+2 ; length of block + +SETEOF_PARM EQU 0 +SE_PCOUNT EQU SETEOF_PARM ; parm count (=2) +SE_REFNUM EQU SE_PCOUNT+1 ; reference number +SE_NEWEOF EQU SE_REFNUM+1 ; new EOF position +SETEOF_PSIZE EQU SE_NEWEOF+3 ; length of parm block + + END + diff --git a/apple/yzip/ice/read.asm b/apple/yzip/ice/read.asm new file mode 100644 index 0000000..a525115 --- /dev/null +++ b/apple/yzip/ice/read.asm @@ -0,0 +1,696 @@ + TITLE "Apple ][ YZIP (c)Infocom","READ HANDLER" +; ---- +; READ +; ---- +; READ LINE INTO TABLE [ARG1] ; PARSE INTO TABLE [ARG2] (IF ARG2 IS THERE) + +MAXWORDS DB 0 ; maximum number of words in table +WORDCNT DB 0 ; how many words read so far +WORDSTART DB 0 ; table offset of word +SAVESPC DS 3 ; SPC that points to Word Count + +ZREAD: + lda ARG1+HI ; MAKE THE TABLE ADDRESSES + sta RDTBL1+HI ; AND PLACE IT HERE TO USE + lda ARG1+LO + sta RDTBL1+LO ; LSBS NEED NOT CHANGE + + lda #0 ; TURN OFF FLAGS + sta PSVFLG ; FOR ZLEX + sta VOCFLG + + ldx NARGS + dex ; IF 2ND TBL ADDR 0 OR NOT THERE + beq ONLYRD ; JUST READ IN DON'T DO CONVERSION (X) + ldx #0 ; JIC + lda ARG2+HI + ora ARG2+LO + beq ONLYRD + + lda ARG2+HI + sta RDTBL2+HI + lda ARG2+LO + sta RDTBL2+LO + + ldx #1 ; 1 = DO IT ALL (X) +ONLYRD: + stx RDFLAG ; CHECK AGAIN AFTER READ IN WHAT TO DO + jsr INPUT ; READ LINE; RETURN LENGTH IN [RDTBL1],1 + + lda RDFLAG ; FLAG (X) + beq RDEX ; IF INPUT ONLY, LEAVE NOW + jsr DOREST +RDEX: + lda #$F0 ; RETURN NOW ONLY WANTED READ PART + sta RDFLAG + lda BRKCHR ; GET BREAK CHAR + ldx #0 + jmp PUTBYT ; RETURN IT +; +; IF TIMEOUT, [A]=0 SO WILL QUIT W/NO RESULTS +; +DOREST: + lda RDTBL2+HI ; get max number of words + jsr SETPC ; tell me memory and bank + sta FPCH ; save page + sty FPCBNK ; and bank + lda RDTBL2+LO ; and for LSB + sta FPCL ; it is same + jsr FETCHB ; get max # of words in table + beq RDERR ; (5/14/85 - FORCE # WORDS TO + cmp #59 ; BE BETWEEN 1 AND 59) + bcc RD0 +RDERR: + lda #58 ; (5/16/86 - MAKE IT 58, 59 LOST) +RD0: + sta MAXWORDS ; save max words + lda #0 ; start at 0 words + sta WORDCNT ; save it + sta WRDLEN ; INIT # CHARS IN WORD COUNTER + lda #2 + sta SOURCE ; INIT SOURCE TABLE PNTR +; +; now futz with destination table a little +; + jsr NEXTFPC ; now we point to # words read + lda FPCBNK ; and save this pointer + sta SAVESPC ; for stashing at the end + lda FPCH + sta SAVESPC+1 + lda FPCL + sta SAVESPC+2 + + lda #4 ; offset to end of first entry + jsr ADDFPC ; and point to end of first entry + jsr FP2SP ; now put RDTBL2 into stash pointer +; +; now get source table +; + lda RDTBL1+HI ; get page + jsr SETPC ; and tell me what mem page and bank + sta FPCH ; set up fetch counter + sty FPCBNK ; and bank + lda RDTBL1+LO ; and lo stays the same + sta FPCL ; and save it + jsr NEXTFPC ; get # of chars in buffer + jsr FETCHB ; and tell me about it + sta LINLEN ; SAVE # CHARS IN LINE + jsr NEXTFPC ; now point to first char in line +; +; MAIN LOOP STARTS HERE +; +READL: + lda MAXWORDS ; how we doin'? + cmp WORDCNT ; see if we have maxxed out + bcc RLEX ; all done, thank you + + lda LINLEN + ora WRDLEN ; OUT OF CHARS AND WORDS? + bne RL2 ; NOT YET +RLEX: + lda SAVESPC ; now set SPC to point to # words + sta SPCBNK ; read byte, as saved at the beginning + lda SAVESPC+1 + sta SPCH + lda SAVESPC+2 + sta SPCL + lda WORDCNT ; get word count + jsr STASHB ; and save it + rts +RL2: + lda WRDLEN ; GET WORD LENGTH + cmp #9 ; 9 CHARS DONE? (EZIP) + 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 #8 ; CLEAR Z-WORD INPUT BUFFER +RLL: sta IN,X ; [A] = 0 + dex + bpl RLL + + lda SOURCE ; STORE THE START POS OF THE WORD + sta WORDSTART ; and save it for later + jsr FETCHB ; 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 + jsr NEXTFPC ; and point to next char + dec LINLEN ; UPDATE # CHARS LEFT IN LINE + jmp READL ; AND LOOP +READL2: + lda LINLEN ; OUT OF CHARS YET? + beq READL3 ; LOOKS THAT WAY + jsr FETCHB ; Grab the 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 ; and update next source + jsr NEXTFPC ; POINT TO NEXT CHAR IN SOURCE + jmp READL ; AND LOOP BACK +; +; handle self-inserting breaks +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 ; and update next source + jsr NEXTFPC ; point to next source char +READL3: + lda WRDLEN ; ANY CHARS IN WORD YET? + bne READL31 ; yup, so deal with word + jmp READL ; then go get next word +READL31: + jsr CONZST ; CONVERT ASCII IN [IN] TO Z-STRING + jsr FINDW ; AND LOOK IT UP IN VOCABULARY + + lda WORDSTART ; get where it starts + jsr STASHB ; and save it + jsr PREVSPC ; step backwards to point to length + lda WRDLEN ; and get length + jsr STASHB ; and save it away + jsr PREVSPC ; and backwards to LSB of offset + ldx #6 ; offset to point to end of next entry + + inc WORDCNT ; increment # words read + + lda PSVFLG ; IF SHOULD PRESERVE WHAT'S IN + beq READL4 + lda VALUE+HI ; RDTBL2 AND NOT FOUND (VALUE = 0) + ora VALUE+LO + beq READL5 ; JUST SKIP OVER +READL4: + lda VALUE+LO ; GET LSB OF VOCAB ENTRY ADDRESS + jsr STASHB ; and stash it away + jsr PREVSPC ; point to MSB part + lda VALUE+HI ; ALSO STORE MSB IN 2ND SLOT + jsr STASHB ; and send it out + ldx #7 ; offset to point to end of next entry +READL5: + lda #0 + sta WRDLEN ; CLEAR # CHARS IN WORD + txa ; get offset + jsr ADDSPC ; and point to end of next entry + jmp READL ; AND LOOP BACK + +; --- +; LEX +; --- +; DO PARSE OF TBL1 INTO TBL2 (2ND HALF OF READ) + +ZLEX: + LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + STA RDTBL1+HI ; AND PLACE IT HERE TO USE + LDA ARG1+LO + STA RDTBL1+LO ; LSBS NEED NOT CHANGE + + LDA ARG2+HI + STA RDTBL2+HI + LDA ARG2+LO + STA RDTBL2+LO + + DEC NARGS + DEC NARGS + BEQ NORMLEX ; USE NORMAL VOCAB TBL + + LDA #1 ; USE ARG3 VOCAB TBL + STA VOCFLG + LDA #0 + DEC NARGS + BEQ NOSAVE ; ZERO UNFOUND WORDS + LDA #1 ; PRESERVE UNFOUND WORD SLOT FLAG +NOSAVE: STA PSVFLG + JMP DOLEX + +NORMLEX: LDA #0 + STA VOCFLG ; USE NORMAL VOCAB TBL + STA PSVFLG ; AND WILL BE NO PRESERVING + +DOLEX: JMP DOREST ; GO DO LEXICAL CONVERSION AND JUST RETURN + + +; ----- +; ZWSTR +; ----- +; CONVERT A WORD TO A ZWORD, PLACE IN ARG4 TBL +ZWSTR: + lda ARG1+HI ; Make ARG1 be the FPC + jsr SETPC ; so get absolute mem bank/page + sty FPCBNK ; save bank and + sta FPCH ; page + lda ARG1+LO + sta FPCL ; LSBS NEED NOT CHANGE +; +; (IGNORE WORD LENGTH CAUSE CHECK FOR BREAK CHAR (9 CHAR MAX)) +; + lda ARG3+LO ; ADD OFFSET INTO INBUF + jsr ADDFPC ; add it to the FPC + + lda ARG4+HI ; now fix the SPC too + jsr SETPC ; get me bank and page + sty SPCBNK ; save bank + sta SPCH ; save page + lda ARG4+LO + sta SPCL ; LSB doesn't change +; +; START A NEW WORD +; + lda #9 + sta LINLEN ; 1 WORD'S WORTH + lda #0 + sta WRDLEN + + ldx #8 ; CLEAR Z-WORD INPUT BUFFER +WSTR1: sta IN,X ; [A] = 0 + dex + bpl WSTR1 +; +; THIS LOOP READS FROM INBUF TIL BREAK OR 9 CHARS READ +; +WSTR2: + jsr FETCHB ; grab the next char + jsr BREAK ; IS IT A BREAK? + bcs WSTR3 ; YES IF CARRY WAS SET + ldx WRDLEN ; ELSE STORE THE CHAR + sta IN,X ; INTO THE INPUT BUFFER + inc WRDLEN ; ONE MORE CHAR IN WORD + dec LINLEN ; ONE LESS IN LINE + jsr NEXTFPC ; point to next char + bne WSTR2 ; AND LOOP BACK TIL DONE +WSTR3: + lda WRDLEN ; ANY CHARS IN WORD YET? + beq WOOPS ; APPARENTLY NOT, OOPS + jsr CONZST ; CONVERT ASCII IN [IN] TO Z-STRING + + ldx #0 ; MOVE FROM [OUT] TO RDTBL2 +WSTR4: lda OUT,X + jsr STASHB ; and stash it into ZWORD table + jsr NEXTSPC ; and point to next byte + inx + cpx #6 ; max 6 word table + bne WSTR4 ; not done yet +WOOPS: + rts + +; ---------- +; FLUSH WORD +; ---------- + +FLUSHW: + lda LINLEN ; ANY CHARS LEFT IN LINE? + beq FLEX ; NO, SCRAM + jsr FETCHB ; 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 + jsr NEXTFPC ; and FPC pointer too + jmp FLUSHW ; AND LOOP BACK (ALWAYS) +FLEX: + rts + + +; --------------------------------- +; IS CHAR IN [A] ANY TYPE OF BREAK? +; --------------------------------- +; ------------------ +; NORMAL BREAK CHARS +; ------------------ + +BRKTBL: DB '!?,.' ; IN ORDER OF + DB $0D ; ASCII ENDING FREQUENCY + DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED + DB 0 ; ZERO ADDED FOR ZWSTR (X) +NBRKS EQU $-BRKTBL ; # NORMAL BREAKS + +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 + + +; --------------------- +; IS CHAR IN [A] A SIB? +; --------------------- + +SIB: STA IOCHAR ; SAVE TEST CHAR + lda VOCAB+ABANK ; get bank + sta MPCBNK ; and save it + lda VOCAB+HI ; and hi part + sta MPCPNT+HI ; and save it + lda ZBEGIN+ZVOCAB+0 ; GET 1ST BYTE IN VOCAB TABLE + LDY ZBEGIN+ZVOCAB+1 + STA MPCM + STY MPCL + LDA #0 + STA MPCH ; now everything is set up + JSR GETBYT ; HAS # SIBS + STA J ; USE AS AN INDEX +SBL: JSR GETBYT ; GET NEXT SIB + CMP IOCHAR ; MATCHED? + BEQ FBRK0 ; YES, REPORT IT + DEC J + BNE SBL ; ELSE KEEP LOOPING + LDA IOCHAR + CLC ; NO MATCH, SO + RTS ; EXIT WITH CARRY CLEAR +FBRK0: LDA IOCHAR +FBRK: SEC ; EXIT WITH CARRY SET + RTS ; IF MATCHED WITH A BREAK CHAR + + +; ----------------- +; VOCABULARY SEARCH +; ----------------- +; ENTRY: 6-BYTE TARGET Z-WORD IN [OUT] +; EXIT: VIRTUAL ENTRY ADDRESS IN [VALUE] IF FOUND ; +; OTHERWISE [VALUE] = 0 + +VWLEN EQU I ; ********** +VWCUR EQU J+HI + +FINDW: + lda VOCFLG ; USE WHAT VOCAB TBL? + beq FWL2 ; NORMAL + lda ARG3+HI ; IF ALTERNATE VOCTBL + ldy ARG3+LO ; IT'S ADDR IS IN ARG3 + jmp FWL3 +FWL2: + lda DIDVTBL ; have we done default vocab table? + beq FWLNEW ; nope, so do it the first time + ldx #2 ; restore pointers +FWRSTL: + lda VOCMPC,X ; get it + sta MPC,X ; save it + lda VCESVE,X ; save VOCEND too + sta VOCEND,X ; okay, we have + lda VWLSVE,X ; and starting length + sta VWLEN,X ; we have + dex ; count + bpl FWRSTL ; okay, next one + jmp FWLOOP ; and go do it +FWLNEW: + lda #$FF ; show we are doing default table + sta DIDVTBL ; we shall + + lda ZBEGIN+ZVOCAB ; GET VIRTUAL ADDR OF VOCAB TBL + ldy ZBEGIN+ZVOCAB+1 +FWL3: + STA MPCM + STY MPCL + LDA #0 + STA MPCH + JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # SIBS + CLC + ADC MPCL ; GET ACTUAL BASE ADDR OF VOCAB ENTRIES + STA MPCL + BCC FWL0 + INC MPCM +FWL0: JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # BYTES PER ENTRY (AND MOVE TO NEXT BYTE) + STA ESIZE ; SAVE IT HERE + STA VWLEN+0 ; AND HERE + LDA #0 ; CLEAR REST OF COUNTER + STA VWLEN+1 + STA VWLEN+2 + + JSR GETBYT ; GET # OF ENTRIES IN TBL (MSB) + STA NENTS+HI ; AND STUFF IT IN [NENTS] + JSR GETBYT ; DON'T FORGET THE LSB! + STA NENTS+LO + LDA NENTS+HI + BPL SORTED + JMP UNSORTED ; VOCAB LIST IS UNSORTED, HANDLE DIFFERENTLY +SORTED: + LDA #0 ; FIND SIZE OF VAOCAB TBL + STA VOCEND ; TO LOCATE THE END OF IT + STA VOCEND+1 + STA VOCEND+2 + LDX ESIZE +FWL1: + CLC + LDA VOCEND ; (# OF ENTRIES) * (ENTRY SIZE) + ADC NENTS+LO + STA VOCEND + LDA VOCEND+1 + ADC NENTS+HI + STA VOCEND+1 + bcc FWL11 + inc VOCEND+2 +FWL11: + DEX + BNE FWL1 + + CLC + LDA VOCEND ; AND ADD LENGTH TO START OF TBL + ADC MPCL ; TO GET END OF TBL + STA VOCEND + LDA VOCEND+1 + ADC MPCM + STA VOCEND+1 + LDA VOCEND+2 + ADC MPCH + STA VOCEND+2 ; TO SAVE FOR TESTING IF PAST END + + LDA VOCEND ; SUBTRACT [ESIZE] SO THAT + SEC ; [VOCEND] POINTS TO REAL LAST ENTRY + SBC ESIZE + STA VOCEND + LDA VOCEND+1 + SBC #0 + STA VOCEND+1 +; +; BEGIN THE SEARCH! [MPC] NOW POINTS TO 1ST ENTRY +; + LSR NENTS+HI ; 2 ALIGN # OF ENTRIES + ROR NENTS+LO ; 2 point to middle of table +FWCALC: ASL VWLEN+0 ; CALCULATE INITIAL OFFSET FOR SEARCH + ROL VWLEN+1 + ROL VWLEN+2 + LSR NENTS+HI + ROR NENTS+LO + BNE FWCALC + + CLC ; ADD 1ST OFFSET INTO START OF VOCABULARL + LDA MPCL ; WHICH IS CURRENTLY IN MPC + ADC VWLEN+0 + STA MPCL + LDA MPCM + ADC VWLEN+1 + STA MPCM + LDA MPCH + ADC VWLEN+2 + STA MPCH + + SEC ; AVOID FENCE-POST BUG FOR + LDA MPCL ; EXACT-POWER-OF-2 TBL (DUNCAN) + SBC ESIZE + STA MPCL + BCS FWSAVE + LDA MPCM + SEC + SBC #1 + STA MPCM + BCS FWSAVE + LDA MPCH + SBC #0 + STA MPCH +FWSAVE: + lda DIDVTBL ; are we installing default table? + bpl FWLOOP ; already have? + ldx #2 ; save MPC + stx DIDVTBL ; show we have saved it +FWSVL: + lda MPC,X ; get it + sta VOCMPC,X ; save it + lda VOCEND,X ; save VOCEND too + sta VCESVE,X ; okay, we have + lda VWLEN,X ; and starting length + sta VWLSVE,X ; we have + dex ; count + bpl FWSVL ; okay, next one +FWLOOP: + lsr VWLEN+2 ; SET FOR NEXT OFFSET, + ror VWLEN+1 ; WHICH IS HALF THIS ONE + ror VWLEN+0 + + lda MPCL ; HOLD START ADDR, MPC WILL BE A MESS + sta VWCUR+0 + lda MPCM + sta VWCUR+1 + lda MPCH + sta VWCUR+2 + + jsr VLDMPC ; SET TO NEW PAGE + jsr GETBYT ; GET 1ST BYTE OF ENTRY + cmp OUT ; MATCH 1ST BYTE OF TARGET? + bcc WNEXT ; LESS + bne FWPREV ; GREATER + jsr GETBYT + cmp OUT+1 ; 2ND BYTE MATCHED? + bcc WNEXT + bne FWPREV ; NOPE + jsr GETBYT + cmp OUT+2 ; 3RD BYTE? + bcc WNEXT + bne FWPREV ; SORRY ... + jsr GETBYT + cmp OUT+3 ; 4TH BYTE + bcc WNEXT + BNE FWPREV + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BCC WNEXT + BNE FWPREV ; SORRY ... + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + BCS FWPREV ; ELSE BACK UP ... +WNEXT: + LDA VWCUR+0 ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + ADC VWLEN+1 + BCS WNXT2 ; SAVES CODE (?) + + STA MPCM + LDA #0 + STA MPCH +WNXT0: + LDA MPCM ; GONE PAST END? + CMP VOCEND+1 + BEQ WNXT1 ; MAYBE + BCS WNXT2 ; YES + BCC FWMORE ; NO +WNXT1: + LDA MPCL + CMP VOCEND + BCC FWMORE ; NO + BEQ FWMORE ; NO, EQUAL +WNXT2: + LDA VOCEND ; YES, SO POINT TO END OF TBL + STA MPCL + LDA VOCEND+1 + STA MPCM + LDA VOCEND+2 + STA MPCH + JMP FWMORE +FWPREV: + LDA VWCUR+0 ; TO MOVE DOWN, JUST SUBTRACT + SEC ; OFFSET FROM START OF THIS + SBC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + SBC VWLEN+1 + STA MPCM + LDA VWCUR+2 + SBC VWLEN+2 + STA MPCH +FWMORE: + LDA VWLEN+2 ; IF OFFSET >GE< 1 WORD, CONTINUE + BNE FWM1 + LDA VWLEN+1 + BNE FWM1 + LDA VWLEN+0 + CMP ESIZE + BCC FWFAIL +FWM1: + JMP FWLOOP ; AND TRY AGAIN + +FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD + STA VALUE+LO + LDA VWCUR+1 + STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY + RTS ; WORD VALUE RETURNABLE +FWFAIL: + LDA #0 ; NOT FOUND + STA VALUE+LO + STA VALUE+HI + RTS ; THEN RETURN WITH [VALUE] = 0 +; +; DO UNSORTED SEARCH ON VOCAB TBL IN MPC +; +UNSORTED: + LDA #$FF ; 2'S COMPLEMENT LENGTH + EOR NENTS+HI ; TO GET REAL LENGTH + STA NENTS+HI ; WAS NEGATIVE TO SIGNIFY + LDA #$FF ; UNSORTED VOCAB TBL + EOR NENTS+LO + STA NENTS+LO + INC NENTS+LO ; 2'S CMPL + BNE UNSRT0 + INC NENTS+HI +UNSRT0: + LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + + JSR GETBYT ; GET 1ST BYTE OF ENTRY + CMP OUT ; MATCH 1ST BYTE OF TARGET? + BNE FNEXT ; LESS + JSR GETBYT + CMP OUT+1 ; 2ND BYTE MATCHED? + BNE FNEXT + JSR GETBYT + CMP OUT+2 ; 3RD BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+3 ; 4TH BYTE + BNE FNEXT + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + +FNEXT: LDA VWCUR+LO ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC ESIZE ; ENTRY + STA MPCL + BCC FNEXT0 + + LDA VWCUR+HI ; PICK UP CARRY + ADC #0 + STA MPCM + LDA #0 + STA MPCH + JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE + +FNEXT0: DEC NENTS+LO ; CHECKED ALL ENTRIES? + BNE UNSRT0 + LDA NENTS+HI + BEQ FWFAIL ; GO INDICATE NO FIND + DEC NENTS+HI ; OR DO NEXT 256 ENTRIES + JMP UNSRT0 + + END diff --git a/apple/yzip/ice/rec.log b/apple/yzip/ice/rec.log new file mode 100644 index 0000000..a7864cd --- /dev/null +++ b/apple/yzip/ice/rec.log @@ -0,0 +1,20 @@ +N3 +%DCL-W-NOCOMD, no command on line - reenter with alphabetic first character +$ A ETransfer aborted by otherside._ +%DCL-W-ABVERB, ambiguous command verb - supply more characters + \A\ +$ + +Reply received from user EZAZ at _LTA1585: 18:59:36 +The system backup is starting in 1 minute...Please log off...Thank you...MIS + +$ + +Reply received from user EZAZ at _LTA1585: 18:59:43 +The system backup is starting in 1 minute...Please log off...Thank you...MIS + +$ log + INFO logged out at 9-FEB-1989 19:00:27.40 +Local -011- Session 1 disconnected from BAYVAX + +Local> \ No newline at end of file diff --git a/apple/yzip/ice/screen.asm b/apple/yzip/ice/screen.asm new file mode 100644 index 0000000..e6b7cb8 --- /dev/null +++ b/apple/yzip/ice/screen.asm @@ -0,0 +1,869 @@ + TITLE "Apple ][ YZIP (c)Infocom","APPLE ][ SCREEN STUFF" + +; ----------------- +; PRINT CHAR IN [A] AT CV,CH +; ----------------- +; +; uses memory register [L] +; +SAVECY DB 0 ; spot to save current screen y pos +SAVECX DB 0 ; spot for x pos + +CHAR: + sta IOCHAR ; SAVE HERE + txa ; SAVE [X] AND [Y] + pha + tya + pha + + lda IOCHAR ; get it back + cmp #BACKSPACE ; is it backspace with erase? + bne CHCX ; nope + + jmp DO_BSPC ; so handle backspace +CHCX: + cmp #EOL ; is it ? + bne CHCONT ; just let dline handle it + + jmp DO_EOL ; handle +; +; so save some stuff and do all the necessary figgering +; +CHCONT: + ldx SCRCNT ; just stash character + sta SCRBUFF,X ; save it + inc SCRCNT ; and count it +CH_EXIT: + pla ; RESTORE [X] AND [Y] + tay + pla + tax + rts +; +; PUT_NYBBLE - put 4 bits to the screen at SCRCX, SCRCY (the lower 4 bits +; in [A]). +; +PUT_NYBBLE: + sta NY_DATA ; save [A] for mucking with + jsr SETPOS ; set up offsets using SCRCX + + lda #$8 ; start at first bit, left to right + sta DATALOOP ; and init the counter with it +PNY0: + ldx FPCBNK ; which bank + sta PAGE2SW,X ; select it + ldy #0 ; start with zero + lda (FPC),Y ; get it + sta SCR_DATA ; and save it +PNY1: + ldx BITOFF ; get which interesting bit we want + lda GT_BITS,X ; get bit + pha ; save bit pictures + lda DATALOOP ; see if we have done all 4 bits in this 'pixel' + beq PNY_EXIT ; toots finis + lsr DATALOOP ; point to next bit + bit NY_DATA ; is this bit set? + bne PNY_SET ; yes it is, so we will handle different +; +; Bit is clear, so clear appropriate one in the SCR_DATA byte +; + pla ; get bit picture back + eor #$FF ; turn bits all around + and SCR_DATA ; turn off bit in screen data + jmp PNY_NEXT ; and continue +PNY_SET: + pla ; get bit mask back + ora SCR_DATA ; turn on bit +PNY_NEXT: + sta SCR_DATA ; save result + inc BITOFF ; we're looking at next bit + lda BITOFF ; now check how we're doing + cmp #7 ; only doing bits 0-6 + bne PNY1 ; check next bit +; +; we've finished this byte in screen memory, point to next one +; + lda #0 ; start at zero'th bit + sta BITOFF ; thank you + lda SCR_DATA ; now stash this one in the screen + sta (FPC),Y ; y is still zero; still pointing to bank + jsr NEXT_SCR ; make SPC/FPC point to next spot + jmp PNY0 ; and continue on please +; +; all done, so make sure we stash anything out there +; +PNY_EXIT: + pla ; get bit mask back to fix stack + lda SCR_DATA ; put away the current data byte + sta (FPC),Y ; y is still zero; still pointing to bank + rts +; +; NEXT_SCR - make FPC/SPC point to next screen byte +; +NEXT_SCR: +; +; if in main bank, when we go to aux bank, we need to look at the next +; byte in memory +; + lda FPCBNK ; get what bank we're talking to currently + bne NXS0 ; 0 = main bank, 1 = aux bank + inc SPCL ; point to next byte + inc FPCL ; and for fetching + lda #AUX ; and point to aux bank + bne NXS1 ; (BRANCH) and continue on +; +; if in aux bank, all we need to do is switch banks +; +NXS0: + lda #MAIN ; just make it main bank +NXS1: + sta SPCBNK ; for stashing and + sta FPCBNK ; fetching + rts +; +; GET_NYBBLE - get the 4 bits which represent the screen at position +; SCRCX, SCRCY; return nybble in low 4 bits of [A] +; +GT_BITS: db 1,2,4,8,$10,$20,$40 +GET_NYBBLE: + jsr SETPOS ; set up offsets using SCRCX + + lda #0 ; clear out my data spot + sta NY_DATA ; for mucking with + + lda #$10 ; setting bits 0-3, starting with shift + sta DATALOOP ; so init the setter +GNY0: + ldx FPCBNK ; which bank + sta PAGE2SW,X ; save which bank + ldy #0 ; zero y + lda (FPC),Y ; get byte + sta SCR_DATA ; and save it +GNY1: + lsr DATALOOP ; see if we have done all 4 bits in this 'pixel' + beq GNY_EXIT ; all done! + + ldx BITOFF ; get bit offset + lda GT_BITS,X ; get bit pattern +; +; now check appropriate bit in Screen Data +; + and SCR_DATA ; see if it is set + beq GNY3 ; no bit set here +; +; bit is set, so set it in my data nybble +; + lda DATALOOP ; get bit setter + ora NY_DATA ; and put it into my data byte + sta NY_DATA ; and save it +GNY3: + inc BITOFF ; we're looking at next bit + lda BITOFF ; now check how we're doing + cmp #7 ; only doing bits 0-6 + bne GNY1 ; check next bit +; +; we've finished this byte in screen memory, point to next one +; + lda #0 ; start at zero'th bit + sta BITOFF ; thank you + jsr NEXT_SCR ; point to next byte + jmp GNY0 ; and continue on please +GNY_EXIT: + lda NY_DATA ; get the nybble desired + rts +; +; SETPOS - get the byte offset and the bit offset from the table using +; SCRCX +; +; USES: SCRCX, SCRCY +; SETS: FPC - pointer to correct screen memory location +; BITOFF - bit offset to get to start of byte (N.B. this is left to +; right count, while in memory it is right to left!) +SETPOS: + lda SCRCX ; get the x pos + tax ; put where we can use it + lda XPOSTBL,X ; get byte # + sta FPCL ; okay, saved + lda XBITTBL,X ; get bitoffset + sta BITOFF ; where it wants it + + lda FPCL ; check for correct bank + and #$01 ; if odd, then must be main bank + bne STP11 ; okay, it be odd + lda #AUX ; aux bank + bne STP22 ; jump +STP11: + lda #MAIN ; main bank +STP22: + sta FPCBNK ; save it + lda FPCL ; get for fetch + lsr A ; /2 to get correct byte offset + ldx SCRCY ; get vertical pos + clc ; get ready for adding + adc BASEL,X ; add low part + sta FPCL ; save low part + lda BASEH,X ; get high part + sta FPCH ; save high part + rts ; done !? +; +; DO_EOL - if this is end of line, check if we are at end of window +; and if we are, and it is a scrollable window, scroll. Then move +; the cursor to the left margin of said window +; +DO_EOL: + jsr DISP_LINE ; make sure line gets out there + lda SCRCY ; get current vertical pos + clc ; add font height + adc #FONT_H ; thank you + pha ; save this position + adc #FONT_H ; make sure we have room for characters here + cmp SCRBTM ; so check against the bottom + beq SAVECV ; no scroll yet + bcs SCROLLCITY ; nope, can't use it +SAVECV: + pla ; get new CV + sta SCRCY ; and save it + bne DEL1 ; JUMP +SCROLLCITY: + pla ; get bad y pos + lda SCRLFLG ; is this a scrolling window? + beq DEL1 ; nope, just move to left edge + jsr SCROLL_UP ; and scroll window +DEL1: +; +; move cursor back to left margin +; + lda LEFTMRG ; get left margin + sta SCRCX ; and set itpositions + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay + lda #0 ; clear length too + sta LENGTH+LO ; no more on line + sta LENGTH+HI ; no more on line + jmp CH_EXIT ; now finish it up +; +; DO_BSPC - do a backspace, by erasing char just before cursor to +; background color, and moving cursor back one space +; X == character to delete +; +SAVECHX: DW 0 + +DO_BSPC: + lda CHR_X+LO ; figger new CHR_X + sec ; subtract width + sbc CHWID,X ; get width of char to be erased + sta CHR_X+LO ; show new one + sta SAVECHX+LO ; save to restore later + lda CHR_X+HI ; and pick up carry + sbc #0 ; okay, did it + sta CHR_X+HI ; save it + sta SAVECHX+HI ; okay + ldy #SPACE ; get SPACE offset + lda CHWID,X ; get width of char + sta CHWID,Y ; set space to be this wide + sty SCRBUFF ; make space for erasing + lda #1 ; show one char + sta SCRCNT ; assume it used to be zero + jsr DISP_LINE ; put that space out + lda SAVECHX+LO ; restore old/new x pos + sta CHR_X+LO + lda SAVECHX+HI + sta CHR_X+HI + jsr GET_SCRCX ; update SCRCX please + + lda #SPACE_WIDTH ; restore width of space char + ldy #SPACE ; get offset + sta CHWID,Y ; okay + + jmp CH_EXIT ; done +; +; CLS - clear the window, using CLS parameters +; +CLS: + lda SCRCX ; save the current X,Y + sta SAVECX ; x + lda SCRCY + sta SAVECY ; saved + lda CLSTOP ; get top line + sta SCRCY ; and set up a y pos + + jsr SETMASK ; set up masks and ending point + + lda CPY_COUNT ; get count + sta SH_LOOP ; save count + lda CLSLEFT ; get left edge + sta SCRCX ; set up as X pos + ldy #WINBGND ; get background offset + lda (WINDOW),Y ; get background color + sta ARG8 ; save it here + lda CLSWIDTH ; how wide we be? + cmp #3 ; if skinny, handle special + bcs L1L0 ; nope + sta ARG7 ; make this be the counter + lda CLSHEIGHT ; just use PUT/GET NYBBLE if only one wide + sta J ; save here +CLS1W: + lda ARG8 ; get color + jsr PUT_NYBBLE ; put it + inc SCRCX ; next x + dec ARG7 ; counter + bne CLS1W ; do next X + lda CLSLEFT ; get left edge again + sta SCRCX ; point to it + inc SCRCY ; next line + lda CLSWIDTH ; restore width count + sta ARG7 ; thanks + dec J ; count + bne CLS1W ; do it + beq CLSEXIT ; all done then +L1L0: + sta J ; use j as counter +L1L: + lda ARG8 ; a color please + jsr PUT_NYBBLE ; do first line easy + inc SCRCX ; next nybble + dec J ; done yet? + bne L1L ; nope + + lda CLSLEFT ; where is left column + sta SCRCX ; here! + jsr SETPOS ; get the address + jsr FP2SP ; SPC is source PC, now! + lda CLSHEIGHT ; how many lines are we clearing + sta J ; j is counter again + dec J ; already cleared one line + beq CLSEXIT ; only one line to do! + lda CLSLEFT ; where is left edge again? + sta SCRCX ; here! +CLSLOOP: + inc SCRCY ; clear this line + jsr SETPOS ; where am i? + lda SH_LOOP ; get count + sta CPY_COUNT ; and save it + jsr COPY_LINE ; did the copy (i hope) + dec J ; count it + bne CLSLOOP ; next one please +CLSEXIT: + lda SAVECX ; get X,Y back + sta SCRCX ; got it + lda SAVECY ; now for y + sta SCRCY ; restored! + + rts +; +; SETMASK - figger out the start and end masks, as well as setting +; stuff to point to stopping address. Use CLSLEFT and CLSWIDTH +; +ST_BITS: db 0,1,3,7,$f,$1f,$3f +SETMASK: + lda CLSLEFT ; munge with SCRX + sta SCRCX ; okay + jsr SETPOS ; get me the bit offset of start + + ldx BITOFF ; now set up mask + lda ST_BITS,X ; get the bit pattern + sta STMASK ; save it + + lda CLSLEFT ; get left edge again + clc ; add width + adc CLSWIDTH ; to get where to stop + tax ; make index + stx SCRCX ; set cur pos + lda XPOSTBL,X ; get how many bytes + ldx CLSLEFT ; subtract from byte offset of start + sec ; subbing + sbc XPOSTBL,X + sta CPY_COUNT ; and save it + + jsr SETPOS ; so get its address + + ldx BITOFF ; get bit offset + lda ST_BITS,X ; get pattern + sta ENDMASK ; okay! + rts +; +; SCROLL_UP - roll the current window by FONT_H lines +; +SCROLL_UP: + lda #FONT_H ; show one line + sta SCLLINES ; done + ldy #WINTOP ; get top of screen + lda (WINDOW),Y ; got it + sta CLSTOP ; saved it + iny ; point to left edge + lda (WINDOW),Y ; get left edge + sta CLSLEFT ; save + iny ; this is now the height + lda (WINDOW),Y ; get window height + sta CLSHEIGHT ; show me + iny ; and now for the width + lda (WINDOW),Y ; get width + sta CLSWIDTH ; saved it + ; so fall thru + ; and do the scrolling +; FALLING THRU +; | +; \ / +; +; +; DO_SCROLL - scroll SCLLINES withing the window as defined by +; CLSLEFT,TOP,WIDTH, and HEIGHT +; +DO_SCROLL: + lda SCRCX ; save the current X,Y + sta SAVECX ; x + lda SCRCY + sta SAVECY ; saved + + ldx SCLLINES ; get line count + bpl SC1 ; >0 means scroll up +; +; scroll down, so we are going to start at the bottom and copy downwards +; until we reach the top +; + txa ; first, make number of lines positive + eor #$FF ; make pos + tax ; put in X for inc + inx ; and make right +; +; now modify code so we do adds to get destination line and subtracts +; to get new src line +; + ldy #$C6 ; 'dec' opcode + bne SC2 ; jump to modify +SC1: +; +; scroll up - start at top and copy upwards until we reach the bottom +; + ldy #$E6 ; 'inc' opcode + ldx SCLLINES ; get # of scrolling lines +SC2: + sty SCMOD1 ; make inc/dec + sty SCMOD2 ; either inc or dec + stx SCOFF ; save the offset between SRC and DST + + lda SCLLINES ; get this again + bpl SC3 ; must be normal scroll +; +; if scrolling downwards, we need to start source at bottom-offset and +; end when the destination is at top+offset +; + lda CLSHEIGHT ; get # of lines in window + sec ; subbing + sbc SCOFF ; subtract offset to get source + clc ; adding + adc CLSTOP ; and get absolute position + tax ; put in X + dex ; for 0 offset it + lda CLSTOP ; now figger last line to copy + clc ; adding + adc CLSHEIGHT ; get me last line + tay ; for later storage + dey ; make 0 based + bne SC4 ; always jumps +SC3: +; +; if scrolling upwards, start src at top+offset and end when destination +; is at bottom-offset +; + lda CLSTOP ; get top + clc ; adding + adc SCOFF ; add in offset + tax ; for later on + ldy CLSTOP ; first destination is top of window +SC4: + stx SCRCY ; Starting Source + sty SCROLLY ; Starting Destination + + jsr SETMASK ; set the masks and horizontal endpoint + lda CPY_COUNT ; save for future generations + sta SH_LOOP ; save it + lda CLSHEIGHT ; how high + sta DATALOOP ; save as counter + sec ; for subbing + sbc SCOFF ; subtract scrolling amount + sta CLSHEIGHT ; this is how many lines to copy + lda SCRCY ; save Start Source + pha + lda CLSTOP ; start at Y pos + sta SCRCY + lda CLSLEFT ; and x pos + sta SCRCX ; thank you +SCRL1: + jsr SETPOS ; set up line pointer + ldy SCRCY ; get top + cpy #120 ; 120 bytes per list + bcc SCRLY ; all set + tya ; for adding + clc + adc #8 + tay +SCRLY: + lda FPCH + sta SV_PCH,Y + lda FPCL + sta SV_PCL,Y + inc SCRCY ; next line please + dec DATALOOP + bne SCRL1 + + pla ; get StartSource back + sta SCRCY + lda FPCBNK ; init SPC bank too + sta SPCBNK ; fine, we did +SCROLLING: + ldy SCRCY ; get source Y for index + cpy #120 ; jump over junk + bcc SCLYY + tya + clc + adc #8 + tay +SCLYY: + lda SV_PCH,Y + sta SPCH + lda SV_PCL,Y + sta SPCL + + ldy SCROLLY ; get destination Y pos + cpy #120 ; jump over junk + bcc SCLYY1 + tya + clc + adc #8 + tay +SCLYY1: + lda SV_PCH,Y + sta FPCH + lda SV_PCL,Y + sta FPCL + lda SH_LOOP ; get byte counter + sta CPY_COUNT ; show copy line + jsr COPY_LINE ; and do the copy +SCMOD1: inc SCRCY ; inc or dec to get next one +SCMOD2: inc SCROLLY ; inc/dec for next destination Y + dec CLSHEIGHT ; count down + bne SCROLLING ; nope + + ldx SCLLINES ; scroll up or down? + bpl SCLCLR1 ; clear a little different +; +; if scrolling down, clear from current Y+1 +; + lda SCRCY ; get current source + sta CLSTOP ; save in top spot + inc CLSTOP ; get inside window + jmp SCLCLR2 +SCLCLR1: + lda SCROLLY ; get last destination + sta CLSTOP ; and save it +SCLCLR2: + lda SCOFF ; and both clear this many lines + sta CLSHEIGHT ; okay? + + lda SAVECX ; now restore X and Y + sta SCRCX ; x + lda SAVECY ; and + sta SCRCY ; y + + jsr CLS ; WIDTH and LEFT should be okay still + + rts +; +; CLREOL - clear from current cursor position to end of line by +; using CLS after changing the window size +; +CLREOL: + lda SCRCX ; and make left be where cursor is + sta CLSLEFT + lda SCRCY ; and top be where Y is + sta CLSTOP + lda #FONT_H ; and bottom be bottom of char + sta CLSHEIGHT + ldy #WINWID ; get width + lda (WINDOW),Y ; got it + clc ; now adding + ldy #WINLEFT ; the left edge + adc (WINDOW),Y ; to get the right edge + sec ; subbing + sbc CLSLEFT ; and subtract left to get width + sta CLSWIDTH ; okay? + jmp CLS ; now clear the screen +; +; COPY_SCRL - copy from SCR_LINE onto the screen. LINEOFF says how +; many bytes in SCR_LINE to copy. FPC are assumed to be pointing +; to start of screen bytes. BITTER has the original BITOFF from +; SETPOS. ENDBIT shows how many significant bits in last byte. +; +COPY_SCRL: + ldx SHOW_CURSOR ; are we showing the cursor (ugh) + beq COPYL2 ; nope + jmp DO_CURSOR ; then XOR cursor in +COPYL2: + ldy #WINBGND ; get background offset + lda (WINDOW),Y ; get current background color + beq COPY_SCRL1 ; if black, ignore this + jsr FIX_COLOR ; or in the color, please +; +; Alternate entry point for COPY_SCRL, used by picture drawing routine +; to avoid using background color and checking for cursor +; +COPY_SCRL1: + ldx FPCBNK ; set up bank + sta PAGE2SW,X ; set first bank + lda ENDBIT ; did we end evenly? + bne COPYL22 ; nope + inc LINEOFF ; make LINEOFF be a counter +COPYL22: + ldy #0 ; zero y + + lda LINEOFF ; if only one, then handle real special + bne COPYL21 ; nope + + ldx BITTER ; get starting bit offset + lda ST_BITS,X ; get starting bit mask + sta IOCHAR ; save it + ldx ENDBIT ; get ending bit offset + lda ST_BITS,X ; combine with ending mask bits + eor #$FF ; set for good ones + ora IOCHAR ; set up mask for bits + and (FPC),Y ; get me interesting bits + sta (FPC),Y ; save + lda IOCHAR ; get flag for data + eor #$FF ; flip to get good data + and SCR_LINE ; pick up my bits + ora (FPC),Y ; and or in screen data + sta (FPC),Y ; and save it + jmp COPYLEX ; go away now +COPYL21: + lda LINEOFF ; get # of chars + lsr A ; /2 get number in this bank + adc #0 ; pick up carry for first one + sta DATALOOP ; and save it to work on + + ldx BITTER ; do we have a weird start? + beq DLL2 ; nope +; +; need to do the first one special +; + lda (FPC),Y ; get byte + and ST_BITS,X ; get masking bits + sta IOCHAR ; save for later + lda ST_BITS,X ; get masking bits again + eor #$FF ; get good bits + and SCR_LINE ; get first data byte + ora IOCHAR ; pick up screen bits + sta (FPC),Y ; pointing + iny ; next byte + ldx #2 ; start at next one for this bank + dec DATALOOP ; kount as done +COPYLOOP: + beq CPYLP2 ; all done with this part of line +DLL2: + lda SCR_LINE,X ; get data + sta (FPC),Y ; pointing + iny ; next byte + inx ; next one + inx ; next one + dec DATALOOP ; count as used + bpl COPYLOOP ; start loop again +CPYLP2: + ldy #0 ; reset Y + lda FPCBNK ; which bank were we at + eor #1 ; swap to other one + tax ; make it in x + sta PAGE2SW,X ; swap to write bank + beq CPYLP23 ; correct offset + iny ; fix offset if going from main to aux +CPYLP23: + ldx #1 ; start at second byte in screen line + lda LINEOFF ; get starting number + lsr A ; /2 to get how many for this bank + sta DATALOOP ; and show it +COPYLOOP2: + beq LINE_DONE ; all done with this part of line + + lda SCR_LINE,X ; get data + sta (FPC),Y ; pointing + iny ; next byte + inx ; next one + inx ; next one + dec DATALOOP ; count as used + bpl COPYLOOP2 ; start loop again +LINE_DONE: +; +; do the last byte special +; + stx DATALOOP ; save pointer + lda ENDBIT ; get ending bit offset + beq COPYLEX ; all done if nothing funky + lsr LINEOFF ; get line offset + bcs LINED1 ; if odd, point at right things + dec DATALOOP ; one less then + ldx FPCBNK ; get original bank + sta PAGE2SW,X ; switch to it + bne LINED1 ; no need to step back one + dey ; point one less here too +LINED1: + tax ; make end bits be index + lda ST_BITS,X ; get end mask + sta IOCHAR ; save mask bits + eor #$FF ; toggle every bit + and (FPC),Y ; get the interesting bits in byte + sta (FPC),Y ; save it + ldx DATALOOP ; get data pointer + lda SCR_LINE,X ; turn on my bits + and IOCHAR ; pick up my good bits + ora (FPC),Y ; bring everything together + sta (FPC),Y ; save the byte +COPYLEX: + sta PAGE2SW+MAIN ; back to main, thanks + rts + +FIX_COLOR: + asl A ; *2 + asl A ; *4 to get correct offset + adc # LOW COLORS ; add start of table + sta COLORP+LO ; save for pointer + lda # HIGH COLORS ; get hi part + adc #0 ; pick up maybe carry + sta COLORP+HI ; save pointer + lda BITTER ; get starting offset + and #3 ; pick up wrap + tay ; make index + ldx #0 ; start at zero line +FIXLOOP: + lda SCR_LINE,X ; get screen byte + ora (COLORP),Y ; or with color byte + sta SCR_LINE,X ; save it + iny ; next color byte + cpy #4 ; wrapped? + bne FIXLP1 ; nope + ldy #0 ; restart +FIXLP1: + inx ; next screen byte + cpx LINEOFF ; done yet? + bcc FIXLOOP ; nope + beq FIXLOOP ; still nope + rts ; now we are done +; +; MSCURS - Erase the cursor from the old spot and write it in the +; new spot +; +MOLDX: db MAXWIDTH ; spot to save x,y of mouse +MOLDY: db MAXHEIGHT +CURSW EQU 2 ; width of cursor +CURSH EQU 4 ; height of cursor +MSCCNT: ds 1 +SVCURS: ds CURSW*CURSH ; save room +MSWCNT: db 1 +MSSTATE: db 2 ; 1 = turn off, 2= move +MSCOLOR: db $f,7,7,7,7,7,7,7 +; +MSCURS: + lda #0 ; clear moved flag + sta MSMOVEF ; we did + jsr MSCOFF ; turn cursor off at current pos + jmp MSCON ; and turn it on in new spot + +; +; MSCOFF - mouse cursor off +; Copy info from saved spot back onto screen @ MOLDX, MOLDY +MSCOFF: + lda SCRCY ; save X,Y + sta SAVECY + lda SCRCX + sta SAVECX + lda MOLDX ; point to old X,Y + sta SCRCX + lda MOLDY + sta SCRCY + lda #0 ; start at beginning of saved area + sta MSCCNT ; save counter + lda #CURSW ; restore width + sta MSWCNT ; and counter +RENEWL: + lda SCRCY ; check bounds + cmp #MAXHEIGHT + bcs MSC1 ; all done +RENEWL0: + lda SCRCX + cmp #MAXWIDTH + bcs RENEWL1 ; might not be done + ldx MSCCNT ; get counter + lda SVCURS,X ; get saved data + jsr PUT_NYBBLE ; save nybble + inc MSCCNT ; point to next one + lda MSCCNT ; get counter + cmp #(CURSW*CURSH) ; done yet? + beq MSC1 ; yup + dec MSWCNT ; count down one width + beq RENEWL1 ; it is + inc SCRCX ; next x + bne RENEWL0 ; try again +RENEWL1: + lda MOLDX ; reset X + sta SCRCX + lda #CURSW ; restore width + sta MSWCNT ; and counter + inc SCRCY ; next y + bne RENEWL ; okay try some more +MSC1: + jmp MSCON4 ; done turning it off +; +; MSCON - turn mouse cursor on +; Copy white pixels into area specified by MSX, MSY +; +MSCON: + lda SCRCY ; save X,Y + sta SAVECY + lda SCRCX + sta SAVECX + + lda MSX ; get mouse x + sta SCRCX ; set mouse X + sta MOLDX ; save mouse x + lda MSY ; get mouse y + sta SCRCY ; set mouse Y + sta MOLDY ; and mouse Y + lda #0 ; start at beginning of saved area + sta MSCCNT ; save counter + lda #CURSW ; restore width + sta MSWCNT ; and counter +MSCON1: + lda SCRCY ; check bounds + cmp #MAXHEIGHT + bcs MSCON4 ; all done +MSCON2: + lda SCRCX + cmp #MAXWIDTH + bcs MSCON3 ; might not be done + jsr GET_NYBBLE ; save nybble + ldx MSCCNT ; get counter + sta SVCURS,X ; get saved data + lda MSCOLOR,X ; get cursor color + jsr PUT_NYBBLE ; put nybble + inc MSCCNT ; point to next one + lda MSCCNT ; check ending + cmp #(CURSW*CURSH) ; done yet? + beq MSCON4 ; yup + dec MSWCNT ; count down one width + beq MSCON3 ; finished for line + inc SCRCX ; next x + bne MSCON2 ; try again +MSCON3: + lda MSX ; reset X + sta SCRCX + lda #CURSW ; restore width + sta MSWCNT ; and counter + inc SCRCY ; next y + bne MSCON1 ; okay try some more +MSCON4: + lda SAVECX ; restore X,Y + sta SCRCX + lda SAVECY + sta SCRCY + rts + + + END diff --git a/apple/yzip/ice/subs.asm b/apple/yzip/ice/subs.asm new file mode 100644 index 0000000..9f74afd --- /dev/null +++ b/apple/yzip/ice/subs.asm @@ -0,0 +1,373 @@ + TITLE "Apple ][ YZIP (c)Infocom","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 LOW = 16, + BCS GETVRG ; IT'S GLOBAL + +; HANDLE A LOCAL VARIABLE + +GETVRL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA LOCALS-2+LO,X ; GRAB LSB + STA VALUE+LO + LDA LOCALS-2+HI,X ; AND MSB + STA VALUE+HI + RTS +; +; HANDLE A GLOBAL VARIABLE +; +GETVRG: + jsr GVCALC ; GET ADDRESS OF GLOBAL INTO [FPC] + jsr FETCHB ; and get hi part + sta VALUE+HI + jsr NEXTFPC ; and point to next part + jsr FETCHB ; and go get it + sta VALUE+LO ; SAVE IT + rts ; AND WE'RE DONE + +; ---------------------------------- +; POP Z-STACK INTO [VALUE] AND [X/A] +; ---------------------------------- +; ZSTACK DOUBLED IN SIZE FOR EZIP +; SO THIS RTN ALL NEW + +POPVAL: LDA ZSP+LO ; IF ZSP+LO IS 0 + BNE POP1 + STA ZSP+HI ; MUST DEC. HI (HI = 0 OR 1 ONLY) +POP1: DEC ZSP+LO ; THEN DEC ZSP LO + BNE POP2 + ORA ZSP+HI ; LO + HI BOTH 0? + BEQ UNDER ; UNDERFLOW IF ZERO! +POP2: LDY ZSP+LO + LDA ZSP+HI + BEQ POP3 ; BOTTOM HALF OF ZSTACK + LDA ZSTKTL,Y ; GET VALUE FROM TOP HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKTH,Y + STA VALUE+HI + RTS + +POP3: LDA ZSTKBL,Y ; GET VALUE FROM BOTTOM HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKBH,Y + STA VALUE+HI + 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: PHA ; HOLD VALUE IN [A] A SEC. + LDY ZSP+LO + LDA ZSP+HI + BEQ PSHBOT ; ON BOTTOM HALF OF STACK + TXA + STA ZSTKTL,Y ; PUSH VALUE ONTO TOP HALF OF STACK + PLA + STA ZSTKTH,Y + JMP PSHUPD ; NOW UPDATE POINTER + +PSHBOT: TXA ; PLACE VALUE ON ZSTACK + STA ZSTKBL,Y + PLA + STA ZSTKBH,Y +PSHUPD: INC ZSP+LO ; UPDATE ZSTACK POINTER + BNE PSHEX + LDA ZSP+LO + ORA ZSP+HI + BNE OVER ; OVERFLOW IF $200 + INC ZSP+HI ; TO 1 +PSHEX: 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 + +; FLUSH TOP WORD OFF STACK +; AND REPLACE WITH [VALUE] + + LDA ZSP+LO ; IF ZSP+LO =0 + BNE VAR1 ; THEN HI =1 (GUARDED ELSEWHERE) + STA ZSP+HI ; DECREMENT HI (ONLY 0 OR 1) +VAR1: DEC ZSP+LO ; NOW DEC LOW BYTE + BNE PSHVAL + ORA ZSP+HI + BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + BNE PSHVAL + + ; RETURN A ZERO +RET0: + lda #0 + tax ; zero's all +; +; RETURN WORD IN [A], [X] (LO,HI) (EZIP EXPANDED TO A WORD) +; +PUTBYT: + STA VALUE+LO + STX 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 LOW = 16, + BCS PUTVLG ; IT'S GLOBAL +; +; PUT A LOCAL VARIABLE +; +PUTVLL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA VALUE+LO ; GRAB LSB + STA LOCALS-2+LO,X ; SAVE IN LOCAL TABLE + LDA VALUE+HI ; DO SAME TO + STA LOCALS-2+HI,X ; MSB + RTS +; +; RETURN A GLOBAL VARIABLE +; +PUTVLG: + JSR GVCALC ; put address in [FPC] + lda FPCBNK ; and move it to stash spot + sta SPCBNK + lda FPCH + sta SPCH + lda FPCL + sta SPCL + lda VALUE+HI ; GET MSB + jsr STASHB ; and save it + jsr NEXTSPC ; point to next byte + lda VALUE+LO ; NOW GET LSB + jsr STASHB ; and send it out + rts + +; ----------------------- +; CALC GLOBAL WORD OFFSET +; ----------------------- +; ENTRY: VAR-I BYTE (16-255) IN [A] +; EXIT: ABSOLUTE ADDRESS OF GLOBAL VAR IN [FPC] +GVCALC: + sec ; time for a subtract + 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 FPCL ; ADDRESS OF THE + lda I+HI ; DESIRED GLOBAL VARIABLE + adc GLOBAL+HI ; STORE ADDRESS BACK IN [FPC] + jsr SETPC ; now get memory page and bank + sta FPCH ; hi part + sty FPCBNK ; and bank +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 PREDB7 ; 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 +PREDB7: 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: LDA VALUE+LO ; SUBTRACT 2 FROM OFFSET + SEC ; IN [VALUE] + SBC #2 + TAX ;SAVE LO BYTE + LDA VALUE+HI + SBC #0 + STA I+LO ;MSB OF OFFSET = LSB OF [I] + LDY #0 ; CLEAR THE MSB + STY I+HI ; OF [I] + ASL A ; EXTEND THE SIGN OF OFFSET + ROL I+HI ; INTO MSB OF [I] + ASL A + ROL I+HI ; (EZIP) + TXA ; GET LSB OF OFFSET + 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 PREDB6 + LDA I+LO ; ELSE CALC NEW UPPER BITS + CLC + ADC ZPCM + STA ZPCM + LDA I+HI + ADC ZPCH + AND #%00000011 ; USE ONLY BIT 0 (& 1 - EZIP) + STA ZPCH + JMP VLDZPC ;MAKE VALID +PREDB6: + + ; FALL THROUGH ... + +; ---- +; NOOP +; ---- + +ZNOOP: RTS + + +; ---------------------- +; MOVE [ARG1] TO [VALUE] +; ---------------------- + +A12VAL: LDA ARG1+LO + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + RTS + + +; ----------------------------------- +; INDICATE STATUS LINE REFRESH NEEDED +; ----------------------------------- + +REFRSH: LDA ZBEGIN+ZFLAGS+1 ; PICK UP LOW BYTE OF FLAG WORD + ORA #%00000100 ; SET BIT 2 + STA ZBEGIN+ZFLAGS+1 ; AND PUT IT BACK + RTS + + +;DECJ RETURNS C=0 WHEN J=$FFFF + +DECJ: LDA J+LO + SEC + SBC #1 + STA J+LO + LDA J+HI + SBC #0 + STA J+HI + RTS + + END diff --git a/apple/yzip/ice/tables.asm b/apple/yzip/ice/tables.asm new file mode 100644 index 0000000..c93d7c6 --- /dev/null +++ b/apple/yzip/ice/tables.asm @@ -0,0 +1,320 @@ + TITLE "Apple ][ YZIP (c)Infocom","--- ZIP DATA TABLES ---" +CHADR_H: + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db HIGH C20,HIGH C21,HIGH C22,HIGH C23,HIGH C24,HIGH C25,HIGH C26,HIGH C27 + DB HIGH C28,HIGH C29,HIGH C2A,HIGH C2B,HIGH C2C,HIGH C2D,HIGH C2E,HIGH C2F + db HIGH C30,HIGH C31,HIGH C32,HIGH C33,HIGH C34,HIGH C35,HIGH C36,HIGH C37 + DB HIGH C38,HIGH C39,HIGH C3A,HIGH C3B,HIGH C3C,HIGH C3D,HIGH C3E,HIGH C3F + db HIGH C40,HIGH C41,HIGH C42,HIGH C43,HIGH C44,HIGH C45,HIGH C46,HIGH C47 + DB HIGH C48,HIGH C49,HIGH C4A,HIGH C4B,HIGH C4C,HIGH C4D,HIGH C4E,HIGH C4F + db HIGH C50,HIGH C51,HIGH C52,HIGH C53,HIGH C54,HIGH C55,HIGH C56,HIGH C57 + DB HIGH C58,HIGH C59,HIGH C5A,HIGH C5B,HIGH C5C,HIGH C5D,HIGH C5E,HIGH C5F + db HIGH C60,HIGH C61,HIGH C62,HIGH C63,HIGH C64,HIGH C65,HIGH C66,HIGH C67 + DB HIGH C68,HIGH C69,HIGH C6A,HIGH C6B,HIGH C6C,HIGH C6D,HIGH C6E,HIGH C6F + db HIGH C70,HIGH C71,HIGH C72,HIGH C73,HIGH C74,HIGH C75,HIGH C76,HIGH C77 + DB HIGH C78,HIGH C79,HIGH C7A,HIGH C7B,HIGH C7C,HIGH C7D,HIGH C7E +CHADR_L: + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db LOW C20,LOW C21,LOW C22,LOW C23,LOW C24,LOW C25,LOW C26,LOW C27 + DB LOW C28,LOW C29,LOW C2A,LOW C2B,LOW C2C,LOW C2D,LOW C2E,LOW C2F + db LOW C30,LOW C31,LOW C32,LOW C33,LOW C34,LOW C35,LOW C36,LOW C37 + DB LOW C38,LOW C39,LOW C3A,LOW C3B,LOW C3C,LOW C3D,LOW C3E,LOW C3F + db LOW C40,LOW C41,LOW C42,LOW C43,LOW C44,LOW C45,LOW C46,LOW C47 + DB LOW C48,LOW C49,LOW C4A,LOW C4B,LOW C4C,LOW C4D,LOW C4E,LOW C4F + db LOW C50,LOW C51,LOW C52,LOW C53,LOW C54,LOW C55,LOW C56,LOW C57 + DB LOW C58,LOW C59,LOW C5A,LOW C5B,LOW C5C,LOW C5D,LOW C5E,LOW C5F + db LOW C60,LOW C61,LOW C62,LOW C63,LOW C64,LOW C65,LOW C66,LOW C67 + DB LOW C68,LOW C69,LOW C6A,LOW C6B,LOW C6C,LOW C6D,LOW C6E,LOW C6F + db LOW C70,LOW C71,LOW C72,LOW C73,LOW C74,LOW C75,LOW C76,LOW C77 + DB LOW C78,LOW C79,LOW C7A,LOW C7B,LOW C7C,LOW C7D,LOW C7E + +CHWID: + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 8,6,10,13,13,14,12,5,7,7,9,10,6,9,5,10 + db 11,7,10,10,13,10,11,9,11,11,5,6,9,9,9,11,16,11,11,11,11 + db 9,9,11,11,5,11,12,9,15,13,11,11,11,11,11,11,11,11 + db 16,11,11,11,9,11,9,11,9,7,11,11,11,11,11,9,11,11,6,9,11,6 + db 15,11,11,11,11,9,10,9,11,11,15,11,11,11,9,6,9,12 + +CHAR_TABLE EQU * +C20 DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;(SPACE) +C21 DB $78,$78,$78,$78,$78,$00,$78,$00,$00 ;! 5 +C22 DB $73,$80,$73,$80,$73,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;" 9 +C23 DB $39,$c0,$ff,$f0,$39,$c0,$39,$c0,$ff,$f0,$39,$c0,$00,$00,$00,$00,$00,$00 ;# 12 +C24 DB $06,$00,$7f,$e0,$e6,$00,$7f,$e0,$06,$70,$7f,$e0,$06,$00,$00,$00,$00,$00 ;$ 12 +C25 DB $78,$e0,$cd,$c0,$7b,$80,$07,$00,$0e,$f0,$1d,$98,$38,$f0,$00,$00,$00,$00 ;% 13 +C26 DB $7f,$00,$e3,$80,$e0,$00,$78,$00,$e0,$e0,$e1,$c0,$7f,$80,$00,$00,$00,$00 ;& 11 +C27 DB $70,$70,$70,$00,$00,$00,$00,$00,$00 ;' 4 +C28 DB $1c,$38,$70,$70,$70,$38,$1c,$00,$00 ;( 6 +C29 DB $70,$38,$1c,$1c,$1c,$38,$70,$00,$00 ;) 6 +C2A DB $db,$3c,$ff,$3c,$db,$00,$00,$00,$00 ;* 8 +C2B DB $1c,$00,$1c,$00,$ff,$80,$1c,$00,$1c,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;+ 9 +C2C DB $00,$00,$00,$00,$00,$38,$38,$18,$70 ;, 5 +C2D DB $00,$00,$00,$ff,$00,$00,$00,$00,$00 ;- 8 +C2E DB $00,$00,$00,$00,$00,$70,$70,$00,$00 ;. 4 +C2F DB $03,$80,$07,$00,$0e,$00,$1c,$00,$38,$00,$70,$00,$e0,$00,$00,$00,$00,$00 ;/ 9 +C30 DB $1f,$00,$3b,$80,$71,$c0,$71,$c0,$71,$c0,$3b,$80,$1f,$00,$00,$00,$00,$00 ;0 10 +C31 DB $1c,$7c,$1c,$1c,$1c,$1c,$1c,$00,$00 ;1 6 +C32 DB $3f,$00,$63,$80,$06,$80,$0e,$00,$1c,$00,$70,$00,$7f,$80,$00,$00,$00,$00 ;2 9 +C33 DB $7f,$80,$03,$00,$06,$00,$1f,$00,$03,$80,$63,$80,$3f,$00,$00,$00,$00,$00 ;3 9 +C34 DB $07,$c0,$0f,$c0,$1d,$c0,$39,$c0,$71,$c0,$7f,$f0,$01,$c0,$00,$00,$00,$00 ;4 12 +C35 DB $7f,$80,$78,$00,$78,$00,$7f,$00,$03,$80,$63,$80,$3f,$00,$00,$00,$00,$00 ;5 9 +C36 DB $1f,$80,$38,$00,$70,$00,$7f,$80,$71,$c0,$71,$c0,$3f,$80,$00,$00,$00,$00 ;6 10 +C37 DB $7f,$07,$07,$0e,$1c,$1c,$1c,$00,$00 ;7 8 +C38 DB $3f,$80,$71,$c0,$71,$c0,$3f,$80,$71,$c0,$71,$c0,$3f,$80,$00,$00,$00,$00 ;8 10 +C39 DB $3f,$80,$71,$c0,$71,$c0,$3f,$c0,$01,$c0,$03,$80,$3f,$00,$00,$00,$00,$00 ;9 10 +C3A DB $00,$00,$70,$70,$00,$70,$70,$00,$00 ;: 4 +C3B DB $00,$00,$38,$38,$00,$38,$38,$18,$70 ;; 5 +C3C DB $00,$0e,$38,$e0,$38,$0e,$00,$00,$00 ;LOW 8 +C3D DB $00,$00,$7f,$00,$7f,$00,$00,$00,$00 ;= 8 +C3E DB $00,$70,$1c,$07,$1c,$70,$00,$00,$00 ;HIGH 8 +C3F DB $3f,$80,$71,$c0,$03,$80,$0e,$00,$0e,$00,$00,$00,$0e,$00,$00,$00,$00,$00 ;? 10 +C40 DB $1f,$f8,$e0,$0e,$e3,$e7,$e6,$77,$e6,$77,$e3,$bc,$e0,$00,$1f,$f8,$00,$00 ;@ 16 +C41 DB $3f,$80,$71,$c0,$71,$c0,$7f,$c0,$71,$c0,$71,$c0,$71,$c0,$00,$00,$00,$00 ;A 10 +C42 DB $7f,$80,$71,$c0,$71,$c0,$7f,$00,$71,$c0,$71,$c0,$7f,$80,$00,$00,$00,$00 ;B 10 +C43 DB $3f,$80,$71,$c0,$70,$00,$70,$00,$70,$00,$71,$c0,$3f,$80,$00,$00,$00,$00 ;C 10 +C44 DB $7f,$80,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$7f,$80,$00,$00,$00,$00 ;D 10 +C45 DB $7f,$70,$70,$7f,$70,$70,$7f,$00,$00 ;E 8 +C46 DB $7f,$70,$70,$7e,$70,$70,$70,$00,$00 ;F 8 +C47 DB $3f,$80,$71,$c0,$70,$00,$73,$c0,$71,$c0,$71,$c0,$3f,$80,$00,$00,$00,$00 ;G 10 +C48 DB $71,$c0,$71,$c0,$71,$c0,$7f,$c0,$71,$c0,$71,$c0,$71,$c0,$00,$00,$00,$00 ;H 10 +C49 DB $70,$70,$70,$70,$70,$70,$70,$00,$00 ;I 4 +C4A DB $01,$c0,$01,$c0,$01,$c0,$01,$c0,$71,$c0,$71,$c0,$3f,$80,$00,$00,$00,$00 ;J 10 +C4B DB $70,$e0,$71,$c0,$73,$80,$7f,$00,$73,$80,$71,$c0,$70,$e0,$00,$00,$00,$00 ;K 11 +C4C DB $70,$70,$70,$70,$70,$70,$7f,$00,$00 ;L 8 +C4D DB $78,$3c,$7c,$7c,$7e,$fc,$77,$dc,$73,$9c,$70,$1c,$70,$1c,$00,$00,$00,$00 ;M 14 +C4E DB $78,$70,$7c,$70,$7e,$70,$77,$70,$73,$f0,$71,$f0,$70,$f0,$00,$00,$00,$00 ;N 12 +C4F DB $3f,$80,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$3f,$80,$00,$00,$00,$00 ;O 10 +C50 DB $7f,$80,$71,$c0,$71,$c0,$7f,$80,$70,$00,$70,$00,$70,$00,$00,$00,$00,$00 ;P 10 +C51 DB $3f,$80,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$3f,$00,$03,$c0,$00,$00 ;Q 10 +C52 DB $7f,$80,$71,$c0,$71,$c0,$7f,$00,$71,$c0,$71,$c0,$71,$c0,$00,$00,$00,$00 ;R 10 +C53 DB $3f,$80,$71,$c0,$78,$00,$1f,$00,$03,$c0,$71,$c0,$3f,$80,$00,$00,$00,$00 ;S 10 +C54 DB $7f,$c0,$0e,$00,$0e,$00,$0e,$00,$0e,$00,$0e,$00,$0e,$00,$00,$00,$00,$00 ;T 10 +C55 DB $71,$c0,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$1f,$00,$00,$00,$00,$00 ;U 10 +C56 DB $71,$c0,$71,$c0,$71,$c0,$71,$c0,$73,$80,$77,$00,$7e,$00,$00,$00,$00,$00 ;V 10 +C57 DB $71,$c7,$71,$c7,$71,$c7,$71,$c7,$71,$c7,$71,$dc,$7f,$f8,$00,$00,$00,$00 ;W 16 +C58 DB $71,$c0,$71,$c0,$71,$c0,$1f,$00,$71,$c0,$71,$c0,$71,$c0,$00,$00,$00,$00 ;X 10 +C59 DB $71,$c0,$71,$c0,$71,$c0,$3f,$80,$0e,$00,$0e,$00,$0e,$00,$00,$00,$00,$00 ;Y 10 +C5A DB $7f,$c0,$01,$c0,$03,$80,$0e,$00,$38,$00,$70,$00,$7f,$c0,$00,$00,$00,$00 ;Z 10 +C5B DB $7f,$70,$70,$70,$70,$70,$7f,$00,$00 ;[ 8 +C5C DB $70,$00,$38,$00,$1c,$00,$0e,$00,$07,$00,$03,$80,$01,$c0,$00,$00,$00,$00 ;\ 10 +C5D DB $7f,$07,$07,$07,$07,$07,$7f,$00,$00 ;] 8 +C5E DB $00,$00,$0c,$00,$3f,$00,$e1,$c0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;^ 10 +C5F DB $00,$00,$00,$00,$00,$00,$00,$ff,$00 ;_ 8 +C60 DB $70,$38,$1c,$00,$00,$00,$00,$00,$00 ;` 6 +C61 DB $00,$00,$00,$00,$3f,$80,$01,$c0,$3f,$c0,$71,$c0,$3f,$c0,$00,$00,$00,$00 ;a 10 +C62 DB $70,$00,$70,$00,$7f,$80,$71,$c0,$71,$c0,$71,$c0,$7f,$80,$00,$00,$00,$00 ;b 10 +C63 DB $00,$00,$00,$00,$3f,$80,$71,$c0,$70,$00,$71,$c0,$3f,$80,$00,$00,$00,$00 ;c 10 +C64 DB $01,$c0,$01,$c0,$3f,$c0,$71,$c0,$71,$c0,$71,$c0,$3f,$c0,$00,$00,$00,$00 ;d 10 +C65 DB $00,$00,$00,$00,$3f,$80,$79,$c0,$7f,$c0,$70,$00,$3f,$80,$00,$00,$00,$00 ;e 10 +C66 DB $0f,$1c,$7f,$1c,$1c,$1c,$1c,$00,$00 ;f 8 +C67 DB $00,$00,$00,$00,$3f,$c0,$71,$c0,$71,$c0,$71,$c0,$3f,$c0,$01,$c0,$3f,$80 ;g 10 +C68 DB $70,$00,$70,$00,$7f,$80,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$00,$00,$00,$00 ;h 10 +C69 DB $70,$00,$70,$70,$70,$70,$70,$00,$00 ;i 5 +C6A DB $0e,$00,$0e,$0e,$0e,$0e,$0e,$0e,$7c ;j 8 +C6B DB $70,$00,$70,$00,$71,$c0,$73,$80,$7f,$00,$73,$80,$71,$c0,$00,$00,$00,$00 ;k 10 +C6C DB $70,$70,$70,$70,$70,$70,$70,$00,$00 ;l 5 +C6D DB $00,$00,$00,$00,$7f,$fc,$73,$9c,$73,$9c,$73,$9c,$73,$9c,$00,$00,$00,$00 ;m 14 +C6E DB $00,$00,$00,$00,$7f,$80,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$00,$00,$00,$00 ;n 10 +C6F DB $00,$00,$00,$00,$3f,$80,$71,$c0,$71,$c0,$71,$c0,$3f,$80,$00,$00,$00,$00 ;o 10 +C70 DB $00,$00,$00,$00,$7f,$80,$71,$c0,$71,$c0,$71,$c0,$7f,$80,$70,$00,$70,$00 ;p 10 +C71 DB $00,$00,$00,$00,$3f,$80,$71,$c0,$71,$c0,$71,$c0,$3f,$c0,$01,$c0,$01,$c0 ;q 10 +C72 DB $00,$00,$77,$7c,$70,$70,$70,$00,$00 ;r 8 +C73 DB $00,$00,$00,$00,$3f,$00,$70,$00,$1e,$00,$03,$80,$3f,$00,$00,$00,$00,$00 ;s 9 +C74 DB $1c,$1c,$7f,$1c,$1c,$1c,$0f,$00,$00 ;t 8 +C75 DB $00,$00,$00,$00,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$3f,$c0,$00,$00,$00,$00 ;u 10 +C76 DB $00,$00,$00,$00,$71,$c0,$71,$c0,$73,$80,$77,$00,$7e,$00,$00,$00,$00,$00 ;v 10 +C77 DB $00,$00,$00,$00,$73,$9c,$73,$9c,$73,$9c,$73,$9c,$7f,$f8,$00,$00,$00,$00 ;w 14 +C78 DB $00,$00,$00,$00,$71,$c0,$71,$c0,$1f,$00,$71,$c0,$71,$c0,$00,$00,$00,$00 ;x 10 +C79 DB $00,$00,$00,$00,$71,$c0,$71,$c0,$71,$c0,$71,$c0,$3f,$c0,$01,$c0,$3f,$80 ;y 10 +C7A DB $00,$00,$00,$00,$7f,$c0,$03,$80,$0e,$00,$38,$00,$7f,$c0,$00,$00,$00,$00 ;z 10 +C7B DB $1f,$38,$38,$f0,$38,$38,$1f,$00,$00 ;} 8 +C7C DB $70,$70,$70,$70,$70,$70,$70,$70,$70 ;| 5 +C7D DB $f8,$1c,$1c,$0f,$1c,$1c,$f8,$00,$00 ;} 8 +C7E DB $00,$00,$00,$00,$3c,$e0,$e7,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ;~ 11 +; +; base addresses for the screen lines +; +BASEL: + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $80,$80,$80,$80,$80,$80,$80,$80 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $80,$80,$80,$80,$80,$80,$80,$80 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $80,$80,$80,$80,$80,$80,$80,$80 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $80,$80,$80,$80,$80,$80,$80,$80 + DB $28,$28,$28,$28,$28,$28,$28,$28 + DB $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 + DB $28,$28,$28,$28,$28,$28,$28,$28 + DB $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 + DB $28,$28,$28,$28,$28,$28,$28,$28 + DB $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 + DB $28,$28,$28,$28,$28,$28,$28,$28 + DB $A8,$A8,$A8,$A8,$A8,$A8,$A8,$A8 + DB $50,$50,$50,$50,$50,$50,$50,$50 + DB $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 + DB $50,$50,$50,$50,$50,$50,$50,$50 + DB $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 + DB $50,$50,$50,$50,$50,$50,$50,$50 + DB $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 + DB $50,$50,$50,$50,$50,$50,$50,$50 + DB $D0,$D0,$D0,$D0,$D0,$D0,$D0,$D0 +BASEH: + DB $20,$24,$28,$2C,$30,$34,$38,$3C + DB $20,$24,$28,$2C,$30,$34,$38,$3C + DB $21,$25,$29,$2D,$31,$35,$39,$3D + DB $21,$25,$29,$2D,$31,$35,$39,$3D + DB $22,$26,$2A,$2E,$32,$36,$3A,$3E + DB $22,$26,$2A,$2E,$32,$36,$3A,$3E + DB $23,$27,$2B,$2F,$33,$37,$3B,$3F + DB $23,$27,$2B,$2F,$33,$37,$3B,$3F + DB $20,$24,$28,$2C,$30,$34,$38,$3C + DB $20,$24,$28,$2C,$30,$34,$38,$3C + DB $21,$25,$29,$2D,$31,$35,$39,$3D + DB $21,$25,$29,$2D,$31,$35,$39,$3D + DB $22,$26,$2A,$2E,$32,$36,$3A,$3E + DB $22,$26,$2A,$2E,$32,$36,$3A,$3E + DB $23,$27,$2B,$2F,$33,$37,$3B,$3F + DB $23,$27,$2B,$2F,$33,$37,$3B,$3F + DB $20,$24,$28,$2C,$30,$34,$38,$3C + DB $20,$24,$28,$2C,$30,$34,$38,$3C + DB $21,$25,$29,$2D,$31,$35,$39,$3D + DB $21,$25,$29,$2D,$31,$35,$39,$3D + DB $22,$26,$2A,$2E,$32,$36,$3A,$3E + DB $22,$26,$2A,$2E,$32,$36,$3A,$3E + DB $23,$27,$2B,$2F,$33,$37,$3B,$3F + DB $23,$27,$2B,$2F,$33,$37,$3B,$3F +; +; this gives the bit offset for each one +; +XBITTBL: + DB 0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 +OLDZV: +; +; Variables that used to be in the zero page but got moved out +; +PSVFLG EQU OLDZV ; (BYTE) PRESERVE FLAG FOR LEX 0=DON'T 1=DO +VOCFLG EQU PSVFLG+1 ; (BYTE) WHICH VOC TBL, 0=NORMAL 1= ARG3 +DBLOCK EQU VOCFLG+1 ; (WORD) Z-BLOCK TO READ +QUOT EQU DBLOCK+2 ; (WORD) QUOTIENT FOR DIVISION +REMAIN EQU QUOT+2 ; (WORD) REMAINDER FOR DIVISION +QSIGN EQU REMAIN+2 ; (BYTE) SIGN OF QUOTIENT +RSIGN EQU QSIGN+1 ; (BYTE) SIGN OF REMAINDER +DIGITS EQU RSIGN+1 ; (BYTE) DIGIT COUNT FOR "PRINTN" +OLDLEN EQU DIGITS+1 ; (BYTE) OLD LINE LENGTH +OLDEND EQU OLDLEN+1 ; (BYTE) OLD LAST CHAR IN [LBUFF] +SPSTAT EQU OLDEND+1 ; (BYTE) SPLIT SCREEN STATUS FLAG +LFROM EQU SPSTAT+1 ; (WORD) "FROM" LINE ADDRESS +LTO EQU LFROM+2 ; (WORD) "TO" LINE ADDRESS +PRLEN EQU LTO+2 ; (BYTE) SCRIPT LINE LENGTH +GPOSIT EQU PRLEN+1 ; (BYTE) DEFAULT SAVE POSITION +GDRIVE EQU GPOSIT+1 ; (BYTE) DEFAULT SAVE DRIVE +TPOSIT EQU GDRIVE+1 ; (BYTE) TEMP SAVE POSITION +TDRIVE EQU TPOSIT+1 ; (BYTE) TEMP SAVE DRIVE +TSLOT EQU TDRIVE+1 ; (BYTE) TEMP SAVE SLOT +DRIVE EQU TSLOT+1 ; (BYTE) CURRENT DRIVE +SIDEFLG EQU DRIVE+1 ; (BYTE) which disk side are we on +SRHOLD EQU SIDEFLG+1 ; (WORD) LOW HIGH 0 if doing sequential random +SCRIPTF EQU SRHOLD+2 ; (BYTE) DIROUT FLAG FOR PRINTER OUTPUT +SCRIPTFLG EQU SCRIPTF+1 ; (BYTE) Does window allow scripting? +OLDZSP EQU SCRIPTFLG+1 ; (WORD) +CURSFLG EQU OLDZSP+2 ; (BYTE) 1==New cursor X for DLINE +DBLK EQU CURSFLG+1 ; (WORD) +RDTBL1 EQU DBLK+2 ; (WORD) READ TABLE 1 (Game Relative) +RDTBL2 EQU RDTBL1+2 ; (WORD) READ TABLE 2 +NENTS EQU RDTBL2+2 ; (WORD) # ENTRIES IN VOCAB TABLE +DIRITM EQU NENTS+2 ; (WORD) OFFSET IN OUTPUT TBL (DIRTBL) +DIRCNT EQU DIRITM+2 ; (WORD) COUNT OF CHARS IN TBL (DIRTBL) +SVTCHAR EQU DIRCNT+2 ; (WORD) Old TCHARS table address +VOCMPC EQU SVTCHAR+2 ; (3 BYTES) Save for vocabulary MPC +VCESVE EQU VOCMPC+3 ; (3 BYTES) Save for VOCEND +VWLSVE EQU VCESVE+3 ; (3 BYTES) Save for VOCLEN +DIDVTBL EQU VWLSVE+3 ; (BYTE) LOW HIGH 0 if we have done default table +IN EQU DIDVTBL+1 ; (9 BYTES) INPUT BUFFER +OUT EQU IN+9 ; (9 BYTES) OUTPUT BUFFER +OLDZVLEN EQU OUT-PSVFLG+9 ; this is how much to reserve + + ds OLDZVLEN ; and zero it out + +; ------------------ +; ERROR MESSAGE STRINGS +; ------------------ +E27: db E27L + db "Disk I/O Error" +E27L EQU $-E27-1 +E2B: db E2BL + db "Disk write protected" +E2BL EQU $-E2B-1 +E40: db E40L + db "Bad Filename" +E40L EQU $-E40-1 +E44: db E44L + db "Path not found" +E44L: EQU $-E44-1 +E45: db E45L + db "Volume not found" +E45L EQU $-E45-1 +E46: db E46L + db "File Not Found" +E46L EQU $-E46-1 +E48: db E48L + db "Disk Full" +E48L EQU $-E48-1 +E49: db E49L + db "LaneDOS limit: 12 files/directory" +E49L EQU $-E49-1 +E4E: db E4EL + db "LaneDOS limit: No writes to TREE files" +E4EL EQU $-E4E-1 +E4C: db E4CL + db "Unexpected EOF" +E4CL EQU $-E4C-1 + +ELIST: db $27 + dw E27 + db $2B + dw E2B + db $40 + dw E40 + db $44 + dw E44 + db $45 + dw E45 + db $46 + dw E46 + db $48 + dw E48 + db $49 + dw E49 + db $4C + dw E4C + db $4E + dw E4E +ELISTL EQU $-ELIST-3 ; mark last error code + + END + diff --git a/apple/yzip/ice/verify.asm b/apple/yzip/ice/verify.asm new file mode 100644 index 0000000..ad0db75 --- /dev/null +++ b/apple/yzip/ice/verify.asm @@ -0,0 +1,252 @@ + TITLE "Apple ][ YZIP (c)Infocom","VERIFY CODE" + + ; ------ + ; VERIFY + ; ------ + ; VERIFY GAME CODE ON DISK +VERBAD: DB EOL,"The data segment of file is BAD!",EOL +VERBADL EQU $-VERBAD +VERPBAD: DB EOL,"The picture data of file is BAD!",EOL +VERPBADL EQU $-VERPBAD +ZVFLAG: db 0 ; set to indicate ugliness +STARTPOS EQU I+LO ; this is where to start block +ZVER: + lda DSEGS+HI ; save current DSEG + pha + lda DSEGS+LO + pha + lda GMREF ; to go back to this one + pha + jsr CLOSE_GAME ; make sure the game files are closed + ldy GAME2NML ; get length of name + lda GAME2NM,Y ; get last char + eor #$30 ; make normal number + tay ; -1 to make ready for FETCH_FILE + dey ; F_F incs first + tya ; to push onto stack + pha ; and save for restoring later + lda #0 ; clear a few counters + sta ZVFLAG ; ==0 - verify worked; !=0 - verify broke + lda SEGTBL+SGTDISKS+1 ; get how many disks are here + sta DISKCNTR ; this shows which disk we are working on + dec DISKCNTR ; start down by one +VERIFY_LOOP: + jsr VERIFY_DATA ; check data in this file + jsr VERIFY_PICD ; check (possible) picture data in this file + lda GMREF ; get reference number + sta CLOSE_PB+CL_REFNUM ; and show CLOSE + CLOSE CLOSE_PB ; and shut it up + dec DISKCNTR ; next please + bpl VERIFY_LOOP ; and check the next file +ZVERX: + lda # HIGH PAGELEN ; reset read buffer length + sta READ_PB+RD_BUFFLEN+HI ; to be $100 + lda # LOW PAGELEN ; this is for LSB + sta READ_PB+RD_BUFFLEN+LO ; to be $100 + jsr CLOSE_GAME ; close up the 2 files, thank you + lda #1 ; open game file #1 (*.D2) + jsr FETCH_FILE ; this opens it up + pla ; get file number back (*.D3/4) + jsr FETCH_FILE ; and open it back up +; +; now point to the one we used to pointing to +; + pla ; get old ref num back + sta GMREF ; and for reading + sta PSEEK+SM_REFNUM ; this sets it up for set marking + pla ; get old DSEG back + sta DSEGS+LO + pla + sta DSEGS+HI + + lda ZVFLAG ; see if we were successful + beq ZVERGOOD ; it worked fine + jmp PREDF ; no it didn't +ZVERGOOD: + jmp PREDS ; all done +; +; VERIFY_DATA - check the data part of the picture. This routine sets +; up DSEGS and open the file. It will move to the data section if this +; is the preload file, set up J to be the number of 256 byte blocks, and +; print out the verdict. The disk we are working on (0-3) is in DISKCNTR. +; +VERIFY_DATA: + lda DISKCNTR ; get disk we are interested in + asl A ; make word pointer + tax ; create index + lda DSKSEG+HI,X ; get MSB of seg table address + sta DSEGS+HI ; save in pointer + lda DSKSEG+LO,X ; get LSB of seg table address + sta DSEGS+LO ; now pointer is all set + lda DISKCNTR ; get disk again + jsr FETCH_FILE ; so we can open up correct file + lda #0 ; make sure we start at beginning + sta PSEEK+SM_FPOS + sta PSEEK+SM_FPOS+1 + sta PSEEK+SM_FPOS+2 + sta STARTPOS ; start at first byte, prob'ly + lda DISKCNTR ; now check if this is preload + bne VERD1 ; if <> 0, then it isn't + jsr SETUP_DISK0 ; move around to point to start of data +VERD1: + SET_MARK PSEEK ; and move + ldy #SGTPICOF ; find where picture data starts + lda (DSEGS),Y ; MSB + sta J+HI ; J is the page counter + iny ; point to LSB + ora (DSEGS),Y ; any picture file? + bne VERD01 ; yes, so mark end of data + lda #$FF ; set J to be a real big number + sta J+LO ; okay + sta J+HI ; and this one + bne VERD11 ; all done +VERD01: + lda (DSEGS),Y ; and here it is + asl A ; *2 to make 512 pages be 256 pages + sta J+LO ; this is where it ends up + rol J+HI ; move in carry to MSB +VERD11: + jsr VERIFY_FILE ; now, actually do the work + bcc VERDX ; worked just fine + DLINE VERBAD, ; puke, gag, argh +; +; This prints out which file is garfed +; +VER_FMSG: + DLINE GAMEP,GAMEPL + lda DISKCNTR ; which file did we do? + cmp #2 ; 0,1 are in one place + bcs VERDB1 ; nope it isn't it + DLINE GAME1NAME,GAME1NML + jmp VERDB2 +VERDB1: + DLINE GAME2NAME,GAME2NML ; 2,3 are in another +VERDB2: + inc ZVFLAG ; show bad file + jsr GETRET ; just wait for +VERDX: + rts ; all done +; +; VERIFY_PICD - verify the picture data in a file. First check to see if +; there is any. If so, seek to it, set J==0 to show VERIFY_FILE to read +; til EOF, and print out bad picture data message if necessary. +; +VERIFY_PICD: + lda #$FF ; gonna zero bunch of stuff + sta J+HI ; and the counter + sta J+LO ; which means now goto EOF + ldy #SGTPICOF ; fetch the picture data offset + lda (DSEGS),Y ; get MSB + sta PSEEK+SM_FPOS+2 ; we are doing pages + iny ; pointing to LSB + ora (DSEGS),Y ; first, check for all zeros + bne VERP1 ; nope, some picture data is there + rts ; just gwon back if nothing here +VERP1: + lda (DSEGS),Y ; go get LSB + asl A ; *2 to get 256 byte pages + sta PSEEK+SM_FPOS+1 ; put away here + rol PSEEK+SM_FPOS+2 ; pick up carry + lda #PHSIZE ; skip over header of file + sta STARTPOS ; show offset in first block +VERP11: + SET_MARK PSEEK ; and move to picture data spot + jsr VERIFY_FILE ; read in the data + SET_MARK PSEEK ; get back to beginning of pic data + READ READ_PB ; read in a block worth + lda IOBUFF+PHCHKS ; get MSB of picture checksum + cmp L+HI ; same as what we got? + bne VERPB ; nope + lda IOBUFF+PHCHKS+1 ; get LSB of picture checksum + cmp L+LO ; same as mine? + beq VERPX ; yup, checked out fine +VERPB: + DLINE VERPBAD, ; picture data bad + jmp VER_FMSG ; print out file name +VERPX: + rts ; tootis finis +; +; VERIFY_FILE - Files is already open and pointing to start of checksummed +; data. Works along til J == 0 or EOF, which ever comes first. Starts by +; dec'ing J, so if J starts as 0, effectively means goto EOF. +; +VERIFY_FILE: + lda #0 ; clear out checksum counter + sta L+HI ; MSB + sta L+LO ; LSB + sta READ_PB+RD_BUFFLEN+LO + lda #4 ; make read read $400 (1Kb) + sta READ_PB+RD_BUFFLEN+HI +VFLOOP: + lda # LOW IOBUFF ; reset K to point to beginning of + sta K+LO ; IOBUFF we are + lda # HIGH IOBUFF ; reading all the data + sta K+HI ; into, using as pointer + READ READ_PB ; read in 1Kb of data + bcc VERF0 ; just fine read + cmp #$4C ; EOF error? + beq VFCHECK ; yes, so wee bee done + jmp DISK_ERR ; complain about read +VERF0: + ldy STARTPOS ; and begin +VERF1: + lda (K),Y ; get byte + clc ; doing add + adc L+LO ; add it in + sta L+LO ; save it + bcc VERF2 ; no wrap + inc L+HI ; yes ther is +VERF2: + iny ; next byte + bne VERF1 ; back to start of inner tloop + dec J+LO ; count block + bne VERF3 ; no wrap + lda J+LO ; get LSB + ora J+HI ; or with MSB to check for zero + beq VFCHECK ; all done then + dec J+HI ; then wrap +VERF3: + lda #0 ; start at first byte + sta STARTPOS ; okay + inc K+HI ; point to next block + dec READ_PB+RD_LENGTH+HI ; count this one + beq VFLOOP ; go read some more + bne VERF1 ; go do next 256 byte block +VFCHECK: + ldy #SGTCHKS ; get check sum + lda L+HI ; start with MSB + cmp (DSEGS),Y ; well . . . ? + bne VFBAD ; nope, it is wrong + iny ; first byte is okay + lda L+LO ; so check LSB + cmp (DSEGS),Y ; well . . . ? + bne VFBAD ; die a slow ugly death + clc ; clear carry to show niceness + rts +VFBAD: + sec ; carry is set if bad + rts ; and return to your fate +; +; SETUP_DISK0 - this routine does some special processing to get the file +; pointer to the beginning of data for the preload file. It skips over +; segment table and first 64 bytes of lo core. +SETUP_DISK0: + READ READ_PB ; read in first block + lda IOBUFF ; MSB of segment table size (in words) + sta PSEEK+SM_FPOS+1 ; middle part of offset + lda IOBUFF+1 ; LSB of size + asl A ; *2 to get # bytes + sta STARTPOS ; LSB of offset + rol PSEEK+SM_FPOS+1 ; rotate in carry + rol PSEEK+SM_FPOS+2 ; and once more + lda #66 ; add 2 to skip word count and 64 to + adc STARTPOS ; skip lo core in preload + sta STARTPOS ; save it + bcc STD0X ; all done, no wrapping + inc PSEEK+SM_FPOS+1 ; count wrap + bne STD0X ; again, no wrapping + inc PSEEK+SM_FPOS+2 ; gipper +STD0X: + rts ; all done + + END diff --git a/apple/yzip/ice/versions b/apple/yzip/ice/versions new file mode 100644 index 0000000..266ddaa --- /dev/null +++ b/apple/yzip/ice/versions @@ -0,0 +1,297 @@ +This is just a list of all the version changes for the Apple ][ YZIP + +; +; 1 - 7/29/88 New numbering scheme +; Faster text handling +; +; 2 - 8/17/88 Gargantu-Games handling +; Fixed Restart +; Handle COLOR -1 +; Handle transparent colors in pictures +; +; 3 - 8/24/88 Joystick/Mouse handling +; +; 4 - 8/30/88 Heavily debugged with/for ZORK0 +; +; 5 - 9/1/88 Fix cursor x,y in WINGET +; Make CLS work on REAL skinny windows +; +; 6 - 9/2/88 No status check on CLOSEs +; Only allow alphanumerics for save names +; +; 7 - 9/2/88 Don't clear strobe first, do it after getting key +; Add /RAM check to boot code - restore /RAM after QUIT +; +; 8 - 9/7/88 Flag day +; Changed WINGET/WINPUT to like GET/PUT +; Add in multi disk stuff +; +; 9 - 9/15/88 Preload is in SEGMENT table now +; Program name in BOOT.ASM +; Copy name to correct place in boot and interpreter +; New name of interpreter is now "INFOCOM" +; Add verify code too +; +;10 - 9/16/88 Keep running count of dirout char width in lo core +; Set up pure and pre pointers for tables and functions +; +;11 - 9/20/88 Don't forget to add one to x,y pos of window and cursor +; in WINGET +; Init vocab pointers for default vocab table and use them +; +;12 - 9/28/88 Zero zero page stuff in two passes - used to wipe out ProDOS zero page +; Data length in pic files is now 3 bytes + +; +;13 - 10/11/88 Picture files and Data files are one and the same now +; +;14 - October 24, 1988 +; Add volumn command to save/restore get name routine +; +;15 - November 8, 1988 +; Search on disk 1 in last resort (hints are probably there) +; Use mouse in passive mode +; +;16 - November 14, 1988 +; Make mouse stuff be passive, rather than interrupt driven +; +;17- November 15, 1988 +; Few more fixes 'n' stuff +; +;18-November 15, 1988 +; Clear ZTWIDTH when starting table output +; +;19-November 28, 1988 +; Fix up PUT_NYBBLE and GET_NYBBLE +; Reset DSEGS after closing save file +; Make FONTSIZE word be Width/Height +; Make Chars/line reflect mono spaced char width of 3 in lo core +; Change ZTWIDTH to be MSB/LSB, rather than LSB/MSB word +; Point to main bank in CHK_MOUSE +; Clamp mouse to 136,189, and don't do shift when getting pos +; Make CLK_CNT be negative, and set flag to show button state +; Set up point to MSTBL (extension table for mouse clicks) +; Put X,Y coordinates in MSTBL after click +; +;20-December 1, 1988 +; Don't use [A] in DO_MOUSE unless it is a character +; Clear LSB in seek pblock before doing seek +; No, really, DON'T use [A] in DO_MOUSE +; Make CLK_CNT be 8 +; Exit normally if double click +; Split mouse cursor routine into 2 pieces - off and on +; If can't find picture, try opening other file. If it isn't there +; then die with error #$14 +; Move XPOSTBL and COLORS to page 3 for some elbow room +; Save/restore refnum when opening new picture file +; +;21-December 2, 1988 +; Swap back to Bank 1 in pic.asm +; +;22-December 5, 1988 +; Save/restore DSEG in verify +; Dec saved filename for passing to Fetch_file in Verify +; Fix addition for getting to Picture data in Verify +; Check for files 0 & 1 names in different place than 2 & 3 (Verify) +; Add STARTPOS to verify +; Copy BITOFF to BITTER in picture stuff +; +;23-December 6, 1988 +; Get picture data checksum from the right place +; Init counter for picture data checksum to be $FF, not 0 +; Move "mouse" cursor for joystick too +; Do "mouse" cursor pos for button for joystick too +; Change movement thresholds for joystick to 120/135 +; Double movement rate for joystick +; Change boundaries check in stick movement to bcs, not beq +; Save/restore cursor position in DLINE +; Create SWAP2INFOW/SWAPBACK to go to/from info window +; and have DLINE & GETSNAME use them +; Have only one exit point in GETSNAME +; Make DLINE do a CLRBUF upon exitting +; Add EOL to end of DELQ +; Muck with a few messages in ZSAVRES +; Change GAMEPL to maximum (64-15) as can only be a list of directories +; Add "Unexpected EOF" error string +; +;24-December 8, 1988 +; Game data starts out on even (512 byte) page boundary +; +;25-December 13, 1988 +; Make pop's FETCHB store afterwards +; Make WINGET handle 0-15 words to get +; Change order of window parameters, to make user ones the first +; 16 available +; Don't SWAP to infowindow in DLINE, rather do it in routines that +; call DLINE +; Fix color green in COLORS table +; +;26-December 14, 1988 +; Change PBEGIN to $0200 +; Scan for mouse slot, rather than asking or assuming +; After finding it, save lo byte in arg1+lo to change interpreter +; screen holes for interesting stuff +; Save/restore printer slot before/after SWAPBACK call +; +;27-December 15, 1988 +; Put paging buffer start back to $0800, cuz screen holes in aux +; mem really screw things up +; Make only closed-apple key work as function key faker +; +;28-December 16, 1988 +; Need only 8 chars for name, as .SYSTEM adds 7 more, to max 15 +; Make ZQUIT read RDBNK2, not write +; +;29-December 19, 1988 +; Save disk number when saving refnum, so that we can scan the two +; disks currently inserted, then look at all the rest +; Pass starting offset for segment list, cuz segments for side 1 +; start a little weird, cuz preload is the first set of +; segments, then the list starts normally +; Don't forget to save refnum in all the right places +; +;30-December 20, 1988 +; Use BIT_BITS in both CHAR_LINE and picture stuff +; Take out retries - it just doesn't work +; Add check for save disk when asking about swapping disk +; Copy read buffer to local buffer before doing read +; +;31-December 22, 1988 +; Play with bounds for joystick movement a little further out +; Don't script input line +; Fix input with timeout, so that the key gets parsed correctly +; Only look at button zero for joystick +; Call FKEYX instead of KEYX in TIMEK +; Check all online volumes before asking for disk by name +; Fix length byte before you do +; Use CHPTR in volume checking routine +; Copy path name to SCRBUFF so we can prepend a '/' in checking volumes +; And don't forget to count it in the length byte +; Quit if no more volumes to check +; More changes to avoid errors in set_prefix, which really seem to gum +; up the works +; +;32-December 23, 1988 +; Don't clear interrupts before reading paddles +; +;33-January 3, 1989 +; Spell volume right in error message +; Save cursor a little earlier in zdispl +; Set/clear savedisk only in close_save +; +;34-January 4, 1989 +; Make sure carry is set before returning from DISK_ERR +; Have SET_GAMEPRE use SAVENUM +; Push current INVFLG instead of saving in variable in ST_CUR +; Check for mouse cursor in timed input please too +; Took GOTKEY out, cuz no-one used it any more +; Changed order in TIMIN for goodness sake +; +;35-January 5, 1989 +; Try for 512 byte paging buffers +; +;36-January 6, 1989 +; Fix up some more for 512 byte buffers +; Muck with paging scheme (oh oh) +; Make GETRES take from one to four blocks +; Make restore use 4 blocks when doing full restore +; +;37-January 9, 1989 +; Fix multiple block restore problems +; Don't destroy DOS return code in GETRES +; Clear CLOSE_PB refnum +; Make DOS routine be READ_DOS and WRITE_DOS +; Fix read so SIB's increment word start +; Make WAIT10 check for mouse/joystick cursor movement +; Use FKEYX for [MORE] so buttons can be used +; +;38-January 10, 1989 +; Mess with PCHK and other scripting stuff +; Use GETKEY for [MORE] +; Put in delay before calling PREAD to get joystick status +; +;39-January 11, 1989 +; Make mouse cursor be two colors +; Change WAIT10 to be a loop, not an MWAIT call +; Clear MSMOVEF flag in MSCURS +; Don't check GETKEY's return in MORE +; Joystick is > 0, mouse is < 0 +; Leave mouse status in [A] for CHK_MOUSE +; Add DELAY_COUNTER for WAIT10 +; +;40-January 12, 1989 +; Fix shift (asl -> rol) when getting position of picture T.O.C. +; Don't split Mouse moving/button +; Play with Delay counter, doubling it if on a GS +; Make sure interupts are turned back on in CHK mouse +; Only turn on button flag in CHK mouse, never turn it off +; Add another delay loop inside WAIT10 +; Make INNER & OUTER constant counters, with special ones for GS +; +;41-January 13, 1989 +; Add printer init call to pchk +; Play with SCRIPT flag (which allows scripting) +; Turn on initially +; Turn off at start of save/restore +; Turn on at end of save/restore +; Add SCRIPTFLG, which says whether window allows scripting +; +;42-January 19, 1989 +; Change to always seek to 512byte block boundary for new DOS +; pic.asm +; +;43-January 20, 1989 +; Move copy line for $D000 down to lower memory +; Add INFODOS flag for conditional assembly for special dos +; Play with boot to get it to work with 512byte blocks +; Take out all ROM calls, cept printer stuff; default is now +; BNK1SET +; +;44-January 26, 1989 +; Change DESTROY to SETEOF for new InfoDOS. +; +;45-January 31, 1989 +; Make paging stuff goto Bank 2, not bank 1 +; Make picture stuff goto Bank 1 +; Add INFODOS flag +; Non-sequential page map +; If INFODOS==1, then 12Kb preload in $D0-$FF, main bank, bank 2 +; and check for it in xpaging +; Just loop if using InfoDOS upon quit +; +;46-February 1, 1989 +; Don't muck with interrupts cuz InfoDOS don't like it +; +;47-February 4, 1989 +; Fixed set_eof to delete file. +; Ignore error returns for set_eof, cuz InfoDOS doesn't like to +; SET_EOF on an empty file. +; Make boot.asm print out version too +; Change special load from Kb's to pages +; Do special load 1 page at a time, rather than 2 +; +;48-February 6, 1989 +; Change get_special counter to count 2 blocks, not 4 +; Fix SAVE/RESTORE to do 512 byte pages for InfoDOS +; All reads in restore must be 512 bytes minimum +; +;49-February 7, 1989 +; Make SAVE_DATA self-modification be absolute, not relative +; Put version number into lower left corner of boot screen +; Fix scroll to move cursor to last line before doing any work +; and have it count the lines in lincnt, but not +; against the scrolling lines +; +;50-February 10, 1989 +; Add no write to TREE files error +; Add set_prefix call to OPEN_GAMEF, before opening file the +; first time +; Start Set-PB off pointing to game boot prefix +; Init a few GS registers in boot +; Put SET_EOF error check back +; Jump to reset vector if in InfoDOS +; +;51-February 10, 1989 +; Huntsville Micro Systems version +; + diff --git a/apple/yzip/ice/windows.asm b/apple/yzip/ice/windows.asm new file mode 100644 index 0000000..13243f3 --- /dev/null +++ b/apple/yzip/ice/windows.asm @@ -0,0 +1,777 @@ + TITLE "Apple ][ YZIP (c)Infocom","WINDOW OPERATIONS" +; +; these are the data structures for all 8 WINDOW. They are identical and +; are just seperated cuz I use the addresses in the table that follows. +; All numbers are inclusive, absolute, and zero-based. +; +WINDSTRUCT EQU 0 +WINTOP EQU WINDSTRUCT ; first line of the window +WINLEFT EQU WINTOP+1 ; left edge of the window +WINHGHT EQU WINLEFT+1 ; height of the window +WINWID EQU WINHGHT+1 ; width of the window, in pixels +WINY EQU WINWID+1 ; y pos of cursor (pos, not relative) +WINX EQU WINY+1 ; x pos of cursor (remember, ABSOLUTE) +WINLM EQU WINX+1 ; left margin +WINRM EQU WINLM+1 ; right margin +WINCRF EQU WINRM+1 ; (WORD) function +WINCRC EQU WINCRF+2 ; (WORD) counter +WINHIGHL EQU WINCRC+2 ; highlight mode +WINFORE EQU WINHIGHL+1 ; foreground color (0=black-7=white) +WINBGND EQU WINFORE+1 ; background color (0=black-7=white) +WINFONT EQU WINBGND+1 ; window font (0=normal/4=monospaced) +WINFSIZE EQU WINFONT+1 ; (WORD) font Height/Width +WINATR EQU WINFSIZE+2 ; Window Attributes +WINLCNT EQU WINATR+1 ; current number of lines +; +; these are my interesting things +; +WINXSZ EQU WINLCNT+1 ; width of window, in pixels, using margin +WINLLEN EQU WINXSZ+1 ; length of current line +WINLINES EQU WINLLEN+2 ; max # of lines for window + +WINDOW0: + DB 0 ; WINTOP - first line of the window + DB 0 ; WINLEFT - left edge of the window + DB MAXHEIGHT ; WINHGHT - height of window + DB MAXWIDTH ; WINWID - width of window + DB 0 ; WINY - y pos of cursor (pos, not relative) + DB 0 ; WINX - x pos of cursor (remember, ABSOLUTE) + DB 0 ; WINLM - left margin + DB 0 ; WINRM - right margin + DW 0 ; WINCRF - function + DW 0 ; WINCRC - counter + DB 0 ; WINHIGHL - Highlights + DB 7 ; WINFORE - foreground color default of white + DB 0 ; WINBGND - background color (0=black-7=white) + DB 0 ; WINFONT - window font (0=normal/1=alternate) + DB 2,FONT_H ; WINFSIZE - Width/Height + DB $0f ; WINATR - all attributes on for window 0 + DB 0 ; WINLCNT - current number of lines + DB MAXWIDTH ; WINXSZ - width of window, in pixels, using margin + DB 0,0 ; WINLLEN - length of current line + DB (MAXHEIGHT/FONT_H)-1 ; WINLINES - max # of lines for window +; +; same start as window 0, but with 0 length +; +WINDOW1: + DB 0,0,0,MAXWIDTH,0,0,0,0,0,0,0,0,0 + DB 7,0,0,2,FONT_H,$08,0,MAXWIDTH,0,0,0 +; +; the rest have no width/height/attributes (except buffering) +; +WINDOW2: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 7,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW3: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 7,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW4: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 7,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW5: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 7,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW6: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 7,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW7: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 7,0,0,2,FONT_H,$08,0,0,0,0,0 + +WINTABLE: + DW WINDOW0,WINDOW1,WINDOW2,WINDOW3 + DW WINDOW4,WINDOW5,WINDOW6,WINDOW7 + PAGE + +; ------ +; SCREEN +; ------ +; Move to the screen specified, by updating CURWIN and the cursor +; X,Y pos (SCRX,SCRY). Also put address of that window's structure +; in WINDOW. Save a bunch of the old stuff in old window's structure then +; update the same bunch with the new window's stuff. +; +; ARG1 - new screen id: 0-7 +; +ZSCRN: + jsr CLRBUF ; EMPTY OUTPUT BUFFER BEFORE MOVING +; +; now, save a few things from the common variables +; + ldy #WINLLEN ; current line length + lda LENGTH+LO ; get current line length + sta (WINDOW),Y ; save for later referencing + iny ; point to msb + lda LENGTH+HI ; get MSB + sta (WINDOW),Y ; saved + ldy #WINLCNT ; where the current line count goes + lda LINCNT ; get current line count + sta (WINDOW),Y ; save for later + jsr SAVE_CURSOR ; save the x,y pos of cursor + lda INVFLG ; get inverse flag + beq ZSCA1 ; not set + lda #1 ; set 1 bit + bne ZSCA2 ; set in window +ZSCA1: + lda UNDFLG ; how about underlining + beq ZSCA2 ; nope + lda #4 ; 4 == underlining +ZSCA2: + ldy #WINHIGHL ; set new highlight + sta (WINDOW),Y ; save current attributes +; +; now it is time to update for new screen +; + lda ARG1+LO ; get which window + sta CURWIN ; save window number + asl A ; shift to make word indes + tax ; swap to indexing reg + lda WINTABLE,X ; get the address of the new WINDOW + sta WINDOW+LO ; lo part comes first + lda WINTABLE+1,X ; so go get hi part + sta WINDOW+HI ; save the hi part of the address + + jsr GET_CURSOR ; restore the cursor pos + + ldy #WINXSZ ; get line length + lda (WINDOW),Y ; update zero page variable + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + ldy #WINLLEN ; get current line length + lda (WINDOW),Y ; from before + sta LENGTH+LO ; save for later checking + iny + lda (WINDOW),Y + sta LENGTH+HI + ldy #WINLCNT ; how many lines already out there + lda (WINDOW),Y ; has been already saved + sta LINCNT ; and save 'ere too + ldy #WINLINES ; how many lines in this + lda (WINDOW),Y ; window, anyway? + sta MAXLINES ; show for everyone to see + ldy #WINLEFT ; show left margin + lda (WINDOW),Y ; get left edge + ldy #WINLM ; left margin + clc ; adding + adc (WINDOW),Y ; to find new left margin + sta LEFTMRG ; set up left margin for ease of use + ldy #WINTOP ; get top of window + lda (WINDOW),Y ; got it + clc ; adding + ldy #WINHGHT ; add height + adc (WINDOW),Y ; did it + sta SCRBTM ; this is first line outside window + ldy #WINHIGHL ; get highlighting modes + lda (WINDOW),Y ; first for inverse video + and #1 ; check for inverse video + beq SCRINV ; nope + lda #$80 ; means inverse video +SCRINV: + sta INVFLG ; there it be + lda (WINDOW),Y ; point to underline flag + and #4 ; check for underlining + beq SCRUND ; nope + lda #$80 ; means underlining +SCRUND: + sta UNDFLG ; save for everyone + + ldy #WINATR ; get the current attributes + lda (WINDOW),Y ; gottem + jsr SET_ATTRIBUTES ; set the flags, thank you + ldy #WINFONT ; get the font + lda (WINDOW),Y ; thank you + beq SCRFNT0 ; is it font zero? + lda #MONOFONT_W ; must be mono font, set width + sta FONTFLG ; save as font flag + bne ZSCREX ; all done then +SCRFNT0: + sta FONTFLG ; mark normal font +ZSCREX: + rts +;-------------- +; ZWINPOS +;-------------- +; +; change the window ARG1's top left corner to the new position +; +; ARG1 - window id from 0-7 +; ARG2 - new top y pos +; ARG3 - new top x pos +; +ZWINPOS: + dec ARG2+LO ; make pos be zero based + dec ARG3+LO ; now they are! +; +; if moving current window, save current cursor pos +; +ZWPOS0: + jsr SAVE_CURSOR ; saving +; +; let's set up [J] to point to window we are talking about +; +ZWPOS1: + lda ARG1+LO ; get window ID + jsr SETWJ ; get J to point to it +; +; make the cursor pos be relative, so we can change back to +; absolute using new window pos +; + ldy #WINY ; let's do y pos first + lda (J),Y ; get the old y pos + ldy #WINTOP ; and subtract the top to make + sec ; (getting ready) + sbc (J),Y ; the pos relative + clc ; now add in new top + adc ARG2+LO ; this will be new top + ldy #WINY ; get y offset again + sta (J),Y ; and save new absolute y pos + ldy #WINX ; now we be talking about x pos + lda (J),Y ; get old x pos + sec ; getting ready for sub + ldy #WINLEFT ; get rid of left ness + sbc (J),Y ; now it's relative + clc ; get ready to add in new left ness + adc ARG3+LO ; done + ldy #WINX ; get x offset again + sta (J),Y ; save in structure +; +; now we can change the top and left of the window +; + lda ARG2+LO ; this is top of window + ldy #WINTOP ; TOP offset + sta (J),Y ; save the new top + lda ARG3+LO ; here is the left edge + ldy #WINLEFT ; offset into struct + sta (J),Y ; saved ! +; +; now, make sure height and width are okay +; + lda #MAXWIDTH ; this is max + sec ; subtract current left + sbc (J),Y ; gives me maximum width allowed + ldy #WINWID ; check against width + cmp (J),Y ; okay + bcs ZWSZCHK ; fits just fine + sta (J),Y ; then make it max + sec ; and subtract + ldy #WINLM ; left margin + sbc (J),Y ; to get the new + ldy #WINXSZ ; xsize + sta (J),Y ; okay +ZWSZCHK: + lda #MAXHEIGHT ; longest window + sec ; subtracting + ldy #WINTOP ; current top + sbc (J),Y ; take away current top + ldy #WINHGHT ; check against current height + cmp (J),Y ; okay + bcc ZWSZCHK1 ; done + sta (J),Y ; make it max +; +; we might have moved current window so update screen cursor and left margin +; +ZWSZCHK1: + jsr GET_CURSOR ; restore cursor + ldy #WINLEFT ; get left edge + lda (WINDOW),Y ; okay + ldy #WINLM ; add in left margin + clc ; adding + adc (WINDOW),Y ; to find new left edge + sta LEFTMRG ; store for ease of use + ldy #WINXSZ ; get xsize + lda (J),Y ; okay + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI +ZWPOSX: + rts +;------------ +; ZWINSIZE +;------------ +; +; Change the size of window ARG1. If cursor is outside of window, +; move to it. +; +; ARG1 - window ID +; ARG2 - height +; ARG3 - width +; +; Uses [J]. +; +ZWINSIZE: +; +; first put SCRCX,CY into window structure, just in case +; + jsr SAVE_CURSOR ; saved +; +; now do everything +; + lda ARG1+LO ; get the window ID + jsr SETWJ ; and get window pointer + + lda ARG2+LO ; get new height + ldy #WINHGHT ; offset + sta (J),Y ; save new height + lda ARG3+LO ; get width + ldy #WINWID ; store width + sta (J),Y ; okay + clc ; now check against maximum + ldy #WINLEFT ; width + adc (J),Y ; add left edge + cmp #MAXWIDTH+1 ; make sure it is within range + bcc ZWSZW ; if <= MAXWIDTH, it's okay + lda #MAXWIDTH ; so figger out how big it can be + sec ; by subtracting left edge from MAXWIDTH + sbc (J),Y ; okay, did it + ldy #WINWID ; offset + sta (J),Y ; save new width +ZWSZW: +; +; now we need to figger out new XSIZE, MAXLINES +; + ldy #WINWID ; store width + lda (J),Y ; get width + sec ; have width, subtract margins + ldy #WINRM ; first right margin + sbc (J),Y ; subtracted right margin + ldy #WINLM ; and now for the left margin + sbc (J),Y ; now we have new XSIZE + ldy #WINXSZ ; get offset + sta (J),Y ; save for later ref + lda ARG2+LO ; get new height + ldx #$FF ; this is the counter + sec ; get ready for subs +ZWSZ1: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZWSZ1 ; still some lines + dex ; to keep the input line on screen + txa ; get line count for storage + ldy #WINLINES ; this is how many lines are allowed + sta (J),Y ; saved +; +; check to make sure the cursor is still in the window +; + ldy #WINLM ; get left margin + clc ; for adding + adc (J),Y ; for figgering out right edge + ldy #WINLEFT ; add in left edge + adc (J),Y ; get right column by adding in left one + ldy #WINX ; check X pos + cmp (J),Y ; see if X is still inside? + beq ZWSZ2 ; must move to top left + bcc ZWSZ2 ; ditto if X >= margin + ldy #WINTOP ; get top to figger last line + lda (J),Y ; from the structure + ldy #WINHGHT ; and add in the height + clc ; getting ready for add + adc (J),Y ; to find first line outside of range + ldy #WINY ; now check y + cmp (J),Y ; now check y then + beq ZWSZ2 ; outside, move to top left + bcs ZWSZ3 ; inside so quit +; +; move the cursor to top left if outside of resized window +; +ZWSZ2: + ldy #WINTOP ; top line is here + lda (J),Y ; so get me it + ldy #WINY ; now we be doing y + sta (J),Y ; change Y + ldy #WINLEFT ; move X to left margin + lda (J),Y ; first get left edge + ldy #WINLM ; and add in left margin + clc ; (adding) + adc (J),Y ; to get left spot of cursor + ldy #WINX ; this is x offset + sta (J),Y ; so move X there +; +; now check to see if we mucked with current window +; +ZWSZ3: + lda ARG1+HI ; this is the id + bmi ZWSZ4 ; must be current window + cmp CURWIN ; is it current window? + bne ZWSZX ; nope, so done +ZWSZ4: + ldy #WINLINES ; get how many lines + lda (J),Y ; get number of lines + sta MAXLINES ; set global + ldy #WINXSZ ; get new XSIZE too + lda (J),Y ; get it + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + jsr GET_CURSOR ; fix the cursor pos +ZWSZX: + rts + + + ; ------ + ; HLIGHT + ; ------ + +ZLIGHT: + lda ARG1+LO ; get argument + cmp #$10 ; must be <= 8 + bcs ZLIEX ; nope it aint + ora #$80 ; turn on hi bit + jsr COUT ; send it out then +ZLIEX: + rts ; done +; +; actually set the highlight flags according to [A] +; +HLIGHT: +; +; TURN OFF ALL HIGHLIGHTS +; + and #$7F ; turn off high bit + bne ZL1 ; nope, must be something + sta UNDFLG ; and turn of underlining flag + sta INVFLG ; and inverse + rts ; all done +ZL1: + cmp #4 ; underlining + bne ZL_REV ; maybe its INVERSE? + + lda #$80 ; turn on UNDFLG + sta UNDFLG ; with an FF + rts ; done +ZL_REV: + cmp #1 ; INVERSE? + bne ZL_MONO ; maybe monospaced then + lda #$80 ; must be inverse video + sta INVFLG ; and put it in invflg + rts +ZL_MONO: + rts ; fuck it for now! +; +; ZWINATTER - change the scrolling/buffering/scripting/wrapping attributes +; of the window. +; +; ARG1 - window id +; ARG2 - interesting bits +; | buffering | scripting | scrolling | wrapping | +; ARG3 - operation - 0 MOVE +; 1 SET +; 2 CLEAR +; 3 COMPLEMENT +; +ZWINATTR: + lda NARGS ; see how many args + cmp #3 ; check for operation args + beq ZWAT1 ; yes, already there + lda #0 ; zero means MOVE + sta ARG3+LO ; so show it as default +ZWAT1: + lda ARG1+LO ; get window ID + jsr SETWJ ; put window address into [J] + + ldy #WINATR ; get attribute offset + lda (J),Y ; get current attribute + clc ; so we can just branch + + dec ARG3+LO ; decrement to find out what to do + bmi ZWMOVE ; do a move + beq ZWSET ; do a set + dec ARG3+LO ; check once more + beq ZWCLEAR ; clear set ones +; +; this is for the COMPLEMENT operations +; + eor ARG2+LO ; complement bits + bcc ZWAT2 ; done +ZWMOVE: +; +; move into the flag word +; + lda ARG2+LO ; get new flags + bcc ZWAT2 ; done +ZWSET: +; +; set turned on ones +; + ora ARG2+LO ; set'em up + bcc ZWAT2 ; done +ZWCLEAR: +; +; tough one - clear just the ones that are on +; + eor ARG2+LO ; turn off ones that are on + ora (J),Y ; turn off ones that weren't on before +ZWAT2: + sta (J),Y ; and save it back +; +; now, if current window, set necessary flags +; + ldx ARG1+LO ; get window ID + cpx CURWIN ; is this the current one? + bne ZWATX ; nope, so leave +SET_ATTRIBUTES: +; +; current window, so set flags accordingly +; + ldx #0 ; to turn off flag + ldy #1 ; to turn on flag + ror A ; get wrapping flag into carry + bcc ZWAT3 ; clear it + sty WRPFLG ; set wrapping on + bcs ZWAT33 ; okay +ZWAT3: + stx WRPFLG ; clear wrapping flag +ZWAT33: + ror A ; now check thes crolling flag + bcc ZWAT4 ; not set + sty SCRLFLG ; turn on scrolling flag + bcs ZWAT44 ; okay, next please +ZWAT4: + stx SCRLFLG ; turn off scrolling +ZWAT44: + ror A ; checking the scripting flag + bcc ZWAT5 ; not set + sty SCRIPTFLG ; allow scripting? yes + bcs ZWAT55 ; next flag +ZWAT5: + stx SCRIPTFLG ; allow scripting? no +ZWAT55: + ror A ; this checks the buffering flag + bcc ZWAT6 ; not set + sty BUFFLG ; turn on buffering + bcs ZWATX ; scram +ZWAT6: + stx BUFFLG ; turn off buffering +ZWATX: + rts +; +; ZWINGET - put the window stuff into a table +; +; ARG1 - Window id +; ARG2 - offset +; +ZWINGET: + jsr SAVE_CURSOR ; save x,y into structure + + lda ARG1+LO ; get window ID + jsr SETWJ ; set up window address + + lda ARG2+LO ; get where to start getting + asl A ; make word index + tax ; make index + lda ZWGTBL+LO,X ; get lo part of address + sta K+LO ; save for jumping + lda ZWGTBL+HI,X ; get hi part + sta K+HI ; saved + jsr ZWGVEC ; do the vectoring + stx VALUE+HI ; save hi part + sta VALUE+LO ; and the lo part + jmp PUTVAL ; and return it +ZWGVEC: + jmp (K) ; and goto it boys +ZWG0: + ldx #0 ; zero out high part + ldy #WINTOP ; get window y pos + lda (J),Y ; got it + tay ; need to inc it + iny ; to make it a one-based number + tya ; back to a + rts +ZWG1: + ldx #0 ; zero out high part + ldy #WINLEFT ; get window x pos + lda (J),Y ; got it + tay ; need to inc it + iny ; to make it a one-based number + tya ; back to a + rts +ZWG2: + ldx #0 ; zero out high part + ldy #WINHGHT ; get window height + lda (J),Y ; got it + rts +ZWG3: + ldx #0 ; zero out high part + ldy #WINWID ; window width + lda (J),Y ; got it + rts +ZWG4: + jsr FETCHCY ; get the current Y pos + ldx #0 ; zero out high part + rts +ZWG5: + jsr FETCHCX ; fetch the current X pos + ldx #0 ; zero out high part + rts +ZWG6: + ldx #0 ; zero out high part + ldy #WINLM ; left margin + lda (J),Y ; got it + rts +ZWG7: + ldx #0 ; zero out high part + ldy #WINRM ; right margin + lda (J),Y ; got it + rts +ZWG8: + ldy #WINCRF+HI ; function + lda (J),Y ; got it, lo part + tax ; save hi part + dey ; point to lo part + lda (J),Y ; got lo part + rts +ZWG9: + ldy #WINCRC+HI ; count + lda (J),Y ; got it, hi part + tax ; save it + dey ; now to lo part + lda (J),Y ; got it + rts +ZWG10: + ldy #WINHIGHL ; get high light mode + lda (J),Y ; got it + ldx #0 ; zero out high part + rts +ZWG11: + ldy #WINFORE ; get foreground + lda (J),Y ; got it + tax ; save it + ldy #WINBGND ; and background + lda (J),Y ; got it + rts +ZWG12: + ldy #WINFONT ; now for font id + lda (J),Y ; got it + ldx #0 ; zero out high part + rts +ZWG13: + ldy #WINFSIZE+1 ; font size (height) + lda (J),Y ; got it + tax ; save it + dey ; font size (width) + lda (J),Y ; got it + rts +ZWG14: + ldx #0 ; zero out high part + ldy #WINATR ; attributes + lda (J),Y ; got it + rts ; got them! +ZWG15: + ldx #0 ; only 1 byte worth + ldy #WINLCNT ; offset + lda (J),Y ; get more counter + rts +; +; jump table for figgering out where to start filling +; +ZWGTBL: + DW ZWG0,ZWG1,ZWG2,ZWG3,ZWG4,ZWG5,ZWG6,ZWG7 + DW ZWG8,ZWG9,ZWG10,ZWG11,ZWG12,ZWG13,ZWG14,ZWG15 +; +; ZSCROLL - scroll the specified window up or down +; +; ARG1 - window ID +; ARG2 - lines to scroll: <0 scrolls down +; +SCLCNTR: db 0 ; counter for scrolling + +ZSCROLL: + jsr SAVE_CURSOR ; save where cursor is + + lda ARG1+LO ; get which window + jsr SETWJ ; set up pointer + dec NARGS ; see what we have for lines + bne ZSCR1 ; a passed arg + lda #1 ; 1 line is default + sta ARG2+LO ; so say so +ZSCR1: + ldy #WINTOP ; get me window limits + lda (J),Y ; first top + sta CLSTOP ; save for usage + iny ; now left + lda (J),Y ; okay, get for this window + sta CLSLEFT ; save left + iny ; now it's width + lda (J),Y ; got the window height + sta CLSHEIGHT ; this is it + iny ; this is height + lda (J),Y ; get window's height + sta CLSWIDTH ; save + lda ARG2+LO ; get how many lines + sta SCLCNTR ; save for routine + + lda SCRBTM ; get bottom of screen + sec ; doing sub + sbc SCRCY ; subtract current vertical pos +ZSCRLLP: + sec ; doing subs + sbc #FONT_H ; count one line + bcc ZSCRLLP1 ; got all the line + beq ZSCRLLP1 ; ubetcha + pha ; save it + jsr ZCRLF ; so move down one line + pla ; get line count back + jmp ZSCRLLP ; check next one +ZSCRLLP1: + lda SCLCNTR ; get lines + sec ; doing sub + sbc #FONT_H ; - FONT height + bcc ZSCRLEX ; okay, then scroll the rest + sta SCLCNTR ; save amount left + jsr ZCRLF ; do + jmp ZSCRLLP1 ; and try again +ZSCRLEX: + lda SCLCNTR ; get how many left over lines + beq ZSCRLEX1 ; none left + sta SCLLINES ; save for scroller + jsr DO_SCROLL ; and do the scroll +ZSCRLEX1: + jmp GET_CURSOR ; restore the cursor, thank you +; +; ZWINPUT - put some information into window structure. Just CRF/CRC +; is legit now. +; +; ARG1 - window ID +; ARG2 - Word to be saved +; ARG3 - offset of value +; +ZWINPUT: + lda ARG1+LO ; get window ID + jsr SETWJ ; have J point to structure + + lda ARG2+LO ; get first value in table + cmp #8 ; 8 = function + beq ZWIPCRF ; so save that + cmp #9 ; this is counter + beq ZWIPCRC ; so set counter + rts ; just die then +ZWIPCRF: + lda ARG3+LO ; get LSB of address + ldy #WINCRF ; point to window's CR function + sta (J),Y ; save lo part + iny ; now to hi part + lda ARG3+HI ; and the hi part + sta (J),Y ; saved! + rts ; all done +ZWIPCRC: + lda ARG3+LO ; start with lo part + ldy #WINCRC ; point to window's CR counter + sta (J),Y ; save lo part + iny ; now to hi part + lda ARG3+HI ; now get hi part + sta (J),Y ; saved! + rts + + END diff --git a/apple/yzip/ice/xpaging.asm b/apple/yzip/ice/xpaging.asm new file mode 100644 index 0000000..3adeab3 --- /dev/null +++ b/apple/yzip/ice/xpaging.asm @@ -0,0 +1,690 @@ + TITLE "Apple ][ YZIP (c)Infocom","MEMORY PAGING ROUTINES" + +; ------------------------- +; POINT [MPC] TO V-ADDR [I] +; ------------------------- + +SETWRD: LDA I+LO + STA MPCL + LDA I+HI + STA MPCM + LDA #0 + STA MPCH ; ZERO TOP BIT + JMP VLDMPC + +; +WANTED: DB 00,00 +; +NEXT: DB 00 +NSUBA: DB 00 +PSUBA: DB 00 +; +YTEMP: DB 00 +ATEMP: DB 00 +NSUBY: DB 00 +; +; set [A](page), [Y](bank) to point to memory page where page in [A] is +; +SETPC: + sta MEMPAGE ; save it for later addition + cmp #P2PAGE ; IS IT A PAGE IN MAIN + bcs VF2 ; No, it might be in aux mem + + lda # HIGH ZBEGIN ; ADD OFFSET TO GET RAM PAGE + ldy #MAIN ; in the main bank + beq VFEXI ; BRA to fetch +VF2: + cmp #PGBEGIN ; is it paged? + bcs VFERR ; yes it be paged, so can't deal with it + cmp #P3PAGE ; is it in Aux Mem, Part 2? + bcs VF3 ; yes, so subtract different amount +; +; this is in lower aux +; + lda #(Z2PAGE-Z1SIZE) ; subtract size from offset + ldy #AUX ; show aux mem + bne VFEXI ; jump to end +VF3: + lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides + ldy #P3BANK ; show page 3 bank +VFEXI: + clc ; get ready for addition + adc MEMPAGE ; now get actual offset + rts +VFERR: +; +; out of range +; + lda #18 + jmp ZERROR +; +; NEXTSPC - inc SPCL and check for wrapping round to next bank +; +NEXTSPC: + inc SPCL ; next lo byte + bne NXSP_EXIT ; no change then + inc SPCH ; next page + lda SPCH ; so get page + cmp # HIGH PRGLBL ; have we reached end of line? + bne NXSP_EXIT ; we be okay + lda SPCBNK ; get bank + bne NXSP1 ; must go to Part 3 + inc SPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta SPCH ; and point to it + rts ; and all done +NXSP1: + lda #Z3PAGE ; get start of page 3 + sta SPCH ; and point there + lda #P3BANK ; and point to this bank + sta SPCBNK ; okey +NXSP_EXIT: + rts +; +; NEXTFPC - inc DPCL and check for wrapping round to next bank +; +NEXTFPC: + inc FPCL ; next lo byte + bne NXFP_EXIT ; no change then + inc FPCH ; next page + lda FPCH ; and get it for checking + cmp # HIGH PRGLBL ; have we reached end of line? + bne NXFP_EXIT ; we be okay + lda FPCBNK ; get bank + bne NXFP1 ; must skip over stuff in middle + inc FPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta FPCH ; and point to it + rts ; toots finis +NXFP1: + lda #Z3PAGE ; start of part 3 + sta FPCH ; so show me + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey +NXFP_EXIT: + rts +; +; ADDFPC - add amount in [A] to current FPC and check for bank wrap +; +ADDFPC: + clc ; get ready for add + adc FPCL ; add lo part + sta FPCL ; and save it + bcc AFPX ; all done if no page wrap + inc FPCH ; point to next page + lda FPCH ; get it for compare + cmp # HIGH PRGLBL ; at end of line in main bank? + bne AFPX ; nope, all done then + lda FPCBNK ; get bank + beq AFP1 ; it is main, so we be ok + lda #Z3PAGE ; must go to part 3 if in aux mem + sta FPCH ; thanx + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey + rts ; done +AFP1: + inc FPCBNK ; point to aux + lda #Z2PAGE ; get start in aux + sta FPCH ; and save it +AFPX: + rts +; +; ADDSPC - add amount in [A] to current SPC and check for bank wrap +; +ADDSPC: + clc ; get ready for add + adc SPCL ; add lo part + sta SPCL ; and save it + bcc ASPX ; all done if no page wrap + inc SPCH ; point to next page + lda SPCH ; get it for compare + cmp # HIGH PRGLBL ; at end of line in main bank? + bne ASPX ; nope, all done then + lda SPCBNK ; get bank + beq ASP1 ; it is main, so we be ok + lda #Z3PAGE ; must go to part 3 if in aux mem + sta SPCH ; thanx + lda #P3BANK ; and point to this bank + sta SPCBNK ; okey + rts ; done +ASP1: + inc SPCBNK ; point to aux + lda #Z2PAGE ; get start in aux + sta SPCH ; and save it +ASPX: + rts +; +; PREVFPC - DEC FPCL and check for wrapping round to next bank +; +PREVFPC: + lda FPCL ; get lo part + bne PFPC2 ; it's not zero, so no wrapping + lda FPCH ; get current page + cmp #Z2PAGE ; have we reached beginning of page 2? + beq PFPC1 ; wrap to first bank + cmp #Z3PAGE ; beginning of part 3? + beq PFPC3 ; ayyup + dec FPCH ; point to previous page + bne PFPC2 ; okay +PFPC1: + lda FPCBNK ; get bank + beq VF1ERR ; oops, can't go backwards from main bank + lda #MAIN ; so point to main bank + beq PFPC4 ; and store it away +PFPC3: + lda #AUX ; and point to this bank +PFPC4: + sta FPCBNK ; okey + lda #(PRGLBL>>8)-1 ; get me last page in part 2 + sta FPCH ; and show me +PFPC2: + dec FPCL ; and point to previous byte + rts +VF1ERR: +; +; out of range +; + lda #19 + jmp ZERROR +; +; PREVSPC - DEC SPCL and check for wrapping round to main bank +; +PREVSPC: + lda SPCL ; get lo part + bne PSPC2 ; it's not zero, so no wrapping + lda SPCH ; get current page + cmp #Z2PAGE ; have we reached beginning of page 2? + beq PSPC1 ; wrap to first bank + cmp #Z3PAGE ; down past page 3? + beq PSPC3 ; sure is + dec SPCH ; point to previous page + bne PSPC2 ; okay +PSPC1: + lda SPCBNK ; get bank + beq VF1ERR ; oops, can't go backwards from main bank + lda #MAIN ; so point to main bank + beq PSPC4 ; so save it +PSPC3: + lda #AUX ; and point to this bank +PSPC4: + sta FPCBNK ; okey + lda # HIGH PRGLBL-1 ; get me last page in low part + sta SPCH ; and show me +PSPC2: + dec SPCL ; and point to previous byte + rts +; +; FP2SP - copy the 3 parts of FPC to SPC +; +FP2SP: + lda FPCBNK + sta SPCBNK + lda FPCH + sta SPCH + lda FPCL + sta SPCL + rts + +; MAKE [MPCPNT],[MPCBNK] POINT TO +; THE RAM PAGE AND BANK THAT HOLDS +; THE V-PAGE MPCH,M +; +VLDMPC: + lda MPCH ; check hi part + bne VLD3 ; NOT IN FIRST V-64K, so must be paged + lda MPCM ; check to see if it is paged + jsr CHECKPRE ; is it preloaded? + bcs VLD3 ; no, so it be paged + jsr SETPC ; so put page/bank into A/Y + sty MPCBNK + sta MPCPNT+HI +NOMUCK: + rts +; +; must be paged, so check for it or read it in +; +VLD3: + lda MPCH + ldy MPCM + jsr FIND_PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + clc + adc # HIGH PBEGIN + sta MPCPNT+HI + ldy #AUX ; paging buffers are in aux mem + sty MPCBNK +; +; TEST FOR MUCK +; + lda MUCKFLG + beq NOMUCK + bne VLDZPC ;MAY HAVE MUCKED ZPC SO GO FIX +; +; SAME IDEA AS VLDMPC +; +VLDZPC: + lda INFODOS ; check first for InfoDOS page + beq VLDZ1 ; none + jsr INFO_PAGE ; well, is it? + bcc VLDZ1 ; nope + rts ; all set otherwise +VLDZ1: + lda ZPCH + bne VLDZ3 ;NOT IN FIRST V-64K, so must be paged + lda ZPCM ; check to see if it is paged + jsr CHECKPRE ; is it preloaded? + bcs VLDZ3 ; no, so it must be paged + jsr SETPC ; point to correct bank and page + sty ZPCBNK ; set bank + sta ZPCPNT+HI ; and MSB of pointer +NOZMUCK: + rts +VLDZ3: ;MUST BE PAGED + lda ZPCH + ldy ZPCM + jsr FIND_PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + clc + adc # HIGH PBEGIN + sta ZPCPNT+HI + ldy #AUX + sty ZPCBNK +; +; TEST MUCKING +; + lda MUCKFLG + beq NOZMUCK + jmp VLDMPC ;MAY HAVE MUCKED MPC SO GO FIX + + +; FIND V-PAGE A,Y IF IT IS IN MEM +; AND RETURN WITH LINKED LIST +; PROPERLY MAINTAINED +; IF V-PAGE A,Y NOT IN MEM +; GET FROM DISK AND PUT IN RIGHT +; PLACE + +MUCKFLG: DB 00 ;00 IF PAGING BUFFERS NOT MUCKED + +FIND_PAGE: + sta WANTED+HI + sty WANTED+LO + ldx #0 + stx MUCKFLG ; CLEAR MUCK FLAG + jsr WHERE + bcc TOUGH ; PAGE IS RESIDENT IN PAGING SPACE +; +; PAGE MUST BE BROUGHT IN FROM DISK +; + ldx CURRENT ;GET BUFFER TO PUT PAGE INTO + lda NEXTPNT,X ;BY LOOKING AT NEXT POINTER + sta CURRENT ;MAKE IT THE CURRENT BUFFER + tax + lda WANTED+HI ;LET BUFFER MAP KNOW + sta VPAGEH,X ;WHICH PAGE + lda WANTED+LO ;IS GOING TO + and #$FE ; make address be even + sta VPAGEL,X ;BE THERE +;*** +; point to the next page too +; + ora #1 ; add one to point to next 256 byte page + pha ; save it + txa ; get pointer + tay ; into y + iny ; point to next buffer + pla ; get second buffer back + sta VPAGEL,Y ; so point to it + lda VPAGEH,X ; get MSB + sta VPAGEH,Y ; and save it +; +; A = WANTED+HI +; Y = WANTED+LO +; X = BUFFER +; + lda WANTED+LO + and #$FE ; clear low bit to make it even + tay ; want it in y +;*** + lda WANTED+HI + ldx CURRENT + jsr GETVPAGE ; PUT V-PAGE A,Y INTO PAGING BUFFER X +;*** + dec MUCKFLG ; INDICATE A MUCKING + bne PAGEXIT ; and return current buffer +TOUGH: + and #$FE ; make even page, please + sta NEXT + cmp CURRENT ; GETS REALY SCREWED IF CURRENT==NEXT + beq PAGEXIT ; DO NOT CHANGE POINTERS IF IT DOES +; +; Y=NEXT(CURRENT) +; DO THE RIGHT THING TO THE POINTERS +; +; ldy CURRENT +; lda NEXTPNT,Y +; sta NSUBCUR + lda NEXT + jsr DETATCH + ldy CURRENT + lda NEXT + jsr INSERT + lda NEXT + sta CURRENT +PAGEXIT: +;*** perhaps add one to point to correct buffer + lda WANTED+LO ; get LSB + and #$01 ; pick up even/odd bit + clc ; doing add + adc CURRENT ; point to correct buffer + rts + +GETVPAGE: + sta DBLOCK+HI + sty DBLOCK+LO + txa ; get which paging buffer + clc + adc # HIGH PBEGIN ; and set up abs addr + sta DBUFF+HI ; thank you, that's much better + ldx #AUX + stx DSKBNK + jmp GETDSK + +; INSERT A AFTER Y +; A.next = Y.next +; Y.next = A +; A.previous = Y +; [Y.next].previous = A +INSERT: + tax + lda NEXTPNT,Y ; Y.next + sta NEXTPNT,X ; A.next = Y.next + pha ; save Y.next for later + txa + sta NEXTPNT,Y ; Y.next = A + tya + sta PREVPNT,X ; A.prev = Y + pla ; get Y.next back + tay ; [Y.next].previous + txa + sta PREVPNT,Y ; [Y.next].previous = A + rts + + IF 0 +; +; old one, which puts A AFTER! Y +; +; PREV(A)=Y +; PREV(NEXT(Y))=A +; NEXT(A)=NEXT(Y) +; NEXT(Y)=A + + sta ATEMP + sty YTEMP + tax + tya + sta PREVPNT,X + + lda NEXTPNT,Y + sta NSUBY + txa + ldx NSUBY + sta PREVPNT,X + + txa + ldx ATEMP + sta NEXTPNT,X + + lda ATEMP + sta NEXTPNT,Y + rts + ENDIF + +; DETATCH BUFFER >A< +; NEXT(PREV(A))=NEXT(A) +; PREV(NEXT(A))=PREV(A) + +DETATCH: + tax + lda NEXTPNT,X + tay ; Y == A.next +; STA NSUBA + lda PREVPNT,X ; get A.previous +; STA PSUBA + tax ; X == A.previous + tya ; get A.next +; LDA NSUBA + STA NEXTPNT,X ; [A.previous].next = A.next +; LDA PSUBA + txa ; get A.previous +; LDX NSUBA + STA PREVPNT,Y ; [A.next].previous = A.previous + RTS + + +; RETURN BUFFER OF PAGE [WANTED] +; IN >A< ELSE SEC (Y=WANTED+LO) + +WHERE: LDX #NUMBUFS-1 +WHLOOP: + LDA WANTED+HI + CMP VPAGEH,X ;>SAME + BEQ WHGOT +WHNOGOT: + DEX + BPL WHLOOP + SEC + RTS +WHGOT: + TYA + CMP VPAGEL,X + BNE WHNOGOT + TXA + CLC + RTS +; +; CHECKPRE - check to see if page in [A] is in preloaded +; +CHECKPRE: + cmp TBLPUR ; check against PURE tables + bcc CHKPEXY ; must be preloaded then +CHKP1: + cmp FUNPRE ; is it in function preload? + bcc CHKPEXN ; preloaded function > desired, not preloaded + cmp FUNPUR ; how bout at end? + bcs CHKPEXN ; it is not preloaded +CHKP3: + clc ; doing add + adc FUNPGE ; get me memory page for function +CHKPEXY: + clc ; show it is preloaded + rts ; then we got it +CHKPEXN: + sec ; show it ain't here + rts +; +; INFO_PAGE - is it one of the special preloaded pages for infoDOS? If it +; is, then set up ZPCPNTR to point to it, and set carry. Otherwise, +; clear carry to show it ain't. +INFO_PAGE: + lda ZPCH ; get 2 parts + sta BIGPAGE+HI + lda ZPCM + sta BIGPAGE+LO + lsr BIGPAGE+HI ; /2 to get 512 block + ror BIGPAGE+LO + ldy #SGTSEG ; point to first segment, MSB + lda (INFODOS),Y ; howzit look? + iny ; point to LSB + cmp BIGPAGE+HI + bcc INFP1 ; might be interesting + bne INFPNX ; not here, < than minimum + lda (INFODOS),Y ; how bout LSB + cmp BIGPAGE+LO + beq INFPYX ; found it + bcs INFPNX ; nope, < than minimum again +; +; here, it's at least > than minimum +; +INFP1: + iny ; point at end block, MSB + lda (INFODOS),Y ; howz end segment look + cmp BIGPAGE+HI + bcc INFPNX ; nope, > than maximum of special + bne INFPYX ; yup, < than maximum of special + iny ; LSB of last one + lda (INFODOS),Y ; is LSB < special? + cmp BIGPAGE+LO ; MSB of current one == MSB of special + bcc INFPNX ; nope, not here +INFPYX: + ldy #SGTSEG+1 ; point back to start block, LSB + lda (INFODOS),Y ; get start block + asl A ; *2 to get start page + sta BIGPAGE+LO ; save it + lda ZPCM + sec ; doing sub + sbc BIGPAGE+LO ; get offset into special block + clc ; now add in offset + adc # HIGH SP_START ; get the start of special area + sta ZPCPNT+HI ; show ZPCPNTR + lda #MAIN ; main bank + sta ZPCBNK ; okey + sec ; show it was here + rts +INFPNX: + clc ; show not here + rts ; g'day + + + +CHKPEXN0: + +GETBYT: + ldy MPCL + jsr MFETCH ; go and get it + inc MPCL ;POINT TO NEXT BYTE + bne GETGOT ;IF NO CROSS WE ARE STILL VALID + inc MPCM + bne GET1 + inc MPCH +GET1: + pha ; save byte + jsr VLDMPC + pla ; and get it back +GETGOT: + tay ;SET FLAGS + rts ;RED SLIPPER TIME +; +; NEXTPC - Fetch the byte at the current ZPC, point to next byte and +; validate pointer +; +NEXTPC: + ldy ZPCL ; get low pointer + jsr ZFETCH ; fetch @ZPCPNT + inc ZPCL + bne NXTGOT + inc ZPCM + bne CRSZ1 + inc ZPCH +CRSZ1: + pha ; save opcode + jsr VLDZPC + pla ; and get it back +NXTGOT: + tay + rts + +; +; STASHB - use SPC to save a byte in either aux or main mem +; +STASHB: + ldy SPCBNK ; get the bank + bmi SB1 ; must be in upper RAM + sta WRTBNK,Y ; set bank + ldy #0 ; can only do this with Y + sta (SPC),Y ; get the sucker + beq SBEXI ; jump to end it +; +; this is in aux mem, >$E000 +; +SB1: + ldy SPCH ; get high part + sty SBMOD+2 ; and self mod my code + ldy SPCL ; and get the low part + sta ALTZP+AUX ; talk about aux mem +SBMOD: + sta Z3BEGIN,Y ; store the little byte + sta ALTZP+MAIN ; go back to main mem +SBEXI: + sta WRTBNK+MAIN ; and write to main + rts +; +; FETCHB - fetch a byte from either main memory, aux memory, or upper +; Aux memory +; +FETCHB: + ldy FPCBNK ; get the bank + bmi FB1 ; must be in upper RAM + sta STORE80+OFF ; turn off this switch + jsr ZERO_FB ; go to low end fetch + sta STORE80+ON ; turn it back on + rts +; +; this is in aux mem, >$E000 +; +FB1: + lda FPCH ; get which page + sta FBMOD+2 ; and show in operand + ldy FPCL ; get which byte + sta ALTZP+AUX ; talk about aux mem +FBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + tay ; set condition code + rts +; +; ZFETCH - after checking for which bank (main, aux 1 or aux 2), go get +; the byte @ ZPCPNT, with the offset being in [Y] +; +ZFETCH: + ldx ZPCBNK ; get the bank + bmi ZFB1 ; must be in upper RAM + sta STORE80+OFF + jsr ZERO_ZF ; go to low end fetch + sta STORE80+ON + rts +; +; this is in aux mem, >$E000 +; +ZFB1: + lda ZPNTH ; which page are we talking about + sta ZBMOD+2 ; show in the operand + sta ALTZP+AUX ; talk about aux mem +ZBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + tax ; set condition code + rts +; +; MFETCH - after checking for which bank (main, aux 1 or aux 2), go get +; the byte @MPCPNT, with the offset being in [Y] +; +MFETCH: + ldx MPCBNK ; get the bank + bmi MB1 ; must be in upper RAM + sta STORE80+OFF + jsr ZERO_MF ; go to low end fetch + sta STORE80+ON + rts +; +; this is in aux mem, >$E000 +; +MB1: + lda MPNTH ; which page are we talking about + sta MBMOD+2 ; show in the operand + sta ALTZP+AUX ; talk about aux mem + +MBMOD: lda Z3BEGIN,Y ; get the sucker + + sta ALTZP+MAIN ; go back to main mem + tax ; set condition code + rts + + + END diff --git a/apple/yzip/ice/y.bat b/apple/yzip/ice/y.bat new file mode 100644 index 0000000..ffd35f8 --- /dev/null +++ b/apple/yzip/ice/y.bat @@ -0,0 +1,5 @@ +hm\hma6502 yzip.asm -e -s -x -p +hm\itob yzip + + + diff --git a/apple/yzip/ice/yt.bat b/apple/yzip/ice/yt.bat new file mode 100644 index 0000000..d2e0186 --- /dev/null +++ b/apple/yzip/ice/yt.bat @@ -0,0 +1,2 @@ +hm\elinks -com2 yzip yzip + diff --git a/apple/yzip/ice/yzip.asm b/apple/yzip/ice/yzip.asm new file mode 100644 index 0000000..b25b5ae --- /dev/null +++ b/apple/yzip/ice/yzip.asm @@ -0,0 +1,73 @@ + ; -------------------------- + ; YZIP + ; Z-CODE INTERPRETER PROGRAM + ; FOR APPLE ][e/][c/][gs + ; -------------------------- + + ; INFOCOM, INC. + ; 125 CAMBRIDGEPARK DRIVE + ; CAMBRIDGE, MA 02140 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + + PAGE 200 +DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER (1 = YES) + + ; ----------- + ; 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 -- IMPURE CODE TOO LARGE (BM 1/20/86) + ; 14 -- DRIVE ACCESS + ; 15 -- NOT AN EZIP GAME + ; 16 -- ILLEGAL EXTENDED RANGE X-OP + ; 17 -- BAD VIRTUAL PAGE + ; 18 -- SETPC NOT PRELOADED + ; 19 -- PREVIOUS (SPC/FPC) NOT POSSIBLE + ; 20 -- PICTURE NOT FOUND + + INCLUDE "ZIP.EQU" + INCLUDE "ZERO.EQU" + INCLUDE "PRODOS.EQU" + INCLUDE "APPLE.EQU" + INCLUDE "MACROS.ASM" + + INCLUDE "ZBEGIN.ASM" + INCLUDE "MAIN.ASM" + INCLUDE "SUBS.ASM" + INCLUDE "DISPATCH.ASM" + + INCLUDE "ZDOS.ASM" + INCLUDE "MACHINE.ASM" + INCLUDE "IO.ASM" + INCLUDE "VERIFY.ASM" + INCLUDE "SCREEN.ASM" + INCLUDE "TABLES.ASM" + INCLUDE "WINDOWS.ASM" + INCLUDE "DLINE.ASM" + INCLUDE "PIC.ASM" + + INCLUDE "OPS012.ASM" + INCLUDE "OPSX.ASM" + INCLUDE "READ.ASM" + INCLUDE "ZSAVRES.ASM" + + INCLUDE "XPAGING.ASM" + INCLUDE "ZSTRING.ASM" + INCLUDE "OBJECTS.ASM" + + END + diff --git a/apple/yzip/ice/zbegin.asm b/apple/yzip/ice/zbegin.asm new file mode 100644 index 0000000..a6294df --- /dev/null +++ b/apple/yzip/ice/zbegin.asm @@ -0,0 +1,94 @@ + TITLE "Apple ][ YZIP (c)Infocom","--- START OF APPLE ][ INTERPRETER ---" + + ORG INTR_BEGIN +; +; Set up for Double HiRes full screen graphics +; + sta PAGE2SW+OFF ; turn off page 2 + sta TEXTSW+OFF ; turn off text - turn on graphics + sta HIRESSW+ON ; turn on high resolution + sta MIXEDSW+OFF ; full screen graphics + sta COL80SW+ON ; turn on 80 column + sta IOUDIS+OFF ; turn ON (it too is backwards) Dhires switch + sta DHIRESW+OFF ; turn ON (it's backwards!) Dhires + + sta STORE80+ON ; turn on aux page display ability + lda BNK2SET ; read/write RAM, bank 2 + lda BNK2SET +; +; copy in progame from boot code +; + ldx #0 ; start at first letter +MVPRE: + lda BORG+3,X ; get letter + beq MVPREX ; all done + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + sta GAME,X ; save for asking about later + inx ; next letter + bne MVPRE ; do gen +MVPREX: + stx GAMEL ; save length of game name + lda #'.' ; get extension for names + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + inx ; next letter + lda #'D' ; for data segments + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + inx ; points to number + inx ; inclusive count for length + stx GAME1NML ; save length of name + stx GAME2NML ; save length of name + + lda #VERSID ; put in version number + sta ZBEGIN+ZINTWD+1 + + inc ZSP+LO ; INIT Z-STACK POINTERS + inc OLDZSP+LO ; TO "1" + inc SCREENF ; TURN DISPLAY ON + inc SCRIPT ; enable scripting + + lda WINTABLE+LO ; set WINDOW to point to window 0 + sta WINDOW+LO + lda WINTABLE+HI + sta WINDOW+HI ; okay, it does + + lda ARG1+LO ; using mouse? + beq ZBEGIN1 ; nope + ora #$78 ; point to correct screen holes + sta MSFIX0+1 + sta MSFIX1+1 ; and modify code to point to correct spot + sta MSFIX2+1 + lda ARG1+LO + ora #$F8 ; and one more + sta MSFIX2+1 +ZBEGIN1: + lda #$FF ; do a clear -1 to start off + sta ARG1+LO ; so arg 1 is this + jsr ZCLR ; doing it + + GET_PREFIX GPRE_PB ; get where we are to start + + lda D3SEG+HI ; start DSEGS at .D2 + sta DSEGS+HI + lda D3SEG+LO + sta DSEGS+LO + + lda #1 ; open game file .D2 please + jsr FETCH_FILE ; we did that + lda INFODOS ; are we on little dos? + beq ZBEGIN2 ; nope + jsr GET_SPECIAL ; do special preloading if so +ZBEGIN2: + lda #2 ; and just for giggles, do the + jsr FETCH_FILE ; same for game file .D3 + + jsr VLDZPC ; MAKE ZPC VALID + jsr NEXTPC ; skip over # of locals + + ; ... AND FALL INTO MAIN LOOP + + END + + diff --git a/apple/yzip/ice/zboot.asm b/apple/yzip/ice/zboot.asm new file mode 100644 index 0000000..569acc3 --- /dev/null +++ b/apple/yzip/ice/zboot.asm @@ -0,0 +1,242 @@ + TITLE "Apple ][ YZIP (c)Infocom","ZIP CODE BOOT PART" +ZBOOT: +; +; clear out ZERO page stuff +; + ldy MID ; save machine id! + ldx #LASTWV-1 ; start at end of first part + lda #0 ; and clear to zero +ZEROL: + sta 0,X ; clear out zero page loc + dex ; next loc + bpl ZEROL ; and do next one + ldx #ZEROPG ; now do other part +ZEROL1: + sta 0,X ; zero this one + inx ; point to next one + cpx #LASTZP ; find the last + bne ZEROL1 ; okay, so do it + + sty MID ; restore machine ID +; +; get game code from data and set up absolute pointers +; + lda ZBEGIN+ZVERS ; IS GAME A YZIP? + cmp #6 ; (X) + beq YESEZ ; YES, CONTINUE + +; *** ERROR #15 -- NOT AN EZIP GAME *** + lda #15 + ldy #0 + jmp ZERROR +YESEZ: + lda #%00111011 ; ENABLE SOUND, underline, MONOSPACING (X) + sta ZBEGIN+ZMODE + + lda MID ; get machine id! + sta ZBEGIN+ZINTWD + lda #0 ; CLEAR HIGH BYTE + sta MOUSEF ; init mouse flag to no mouse + sta ZBEGIN+ZHWRD + sta ZBEGIN+ZVWRD + lda #MAXWIDTH ; SET SCREEN PARAMETERS + sta ZBEGIN+ZHWRD+1 + lda #MAXWIDTH/3 ; number of mono spaces on a line + sta ZBEGIN+ZSCRWD+1 + lda #MAXHEIGHT + sta ZBEGIN+ZVWRD+1 + lda #MAXHEIGHT/FONT_H + sta ZBEGIN+ZSCRWD ; number of lines of chars + lda #FONT_H ; height of font + sta ZBEGIN+ZFWRD + lda #3 ; width of font (2 spaces == 8 pixels) + sta ZBEGIN+ZFWRD+1 + lda #9 ; the color white is the foreground color + sta ZBEGIN+ZCLRWD+1 ; show Z game too + lda #2 ; black is the background color + sta ZBEGIN+ZCLRWD ; tell game about it +; +; just move global address to zero page for quick working +; + lda ZBEGIN+ZGLOBAL ; get page + sta GLOBAL+HI ; save which page + lda ZBEGIN+ZGLOBAL+1 ; LSB NEEDN'T CHANGE + sta GLOBAL+LO ; so just store it away +; +; figger absolute address for the fword table +; + lda ZBEGIN+ZFWORD ; get fword page number + jsr SETPC ; and get absolute address + sta FWORDS+HI ; show high addr of table + sty FWORDS+ABANK ; show which bank + lda ZBEGIN+ZFWORD+1 ; LSB NEEDN'T CHANGE + sta FWORDS+LO ; so just save it +; +; figger absolute address for the vocab table +; + lda ZBEGIN+ZVOCAB ; get fword page number + jsr SETPC ; and get absolute address + sta VOCAB+HI ; show high addr of table + sty VOCAB+ABANK ; show which bank + lda #0 ; this is always zero (get lo part from MPCL) + sta VOCAB+LO ; so just save it +; +; now do somethin' with the TCHAR table (maybe, if <> 0) +; + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + ora ZBEGIN+ZTCHAR+1 ; is it zero though? + bne TCH1 ; no, so copy it to somewhere useful + sta TCHARTBL ; not there, so zero first byte in table + beq TCHj ; jmp +TCH1: + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + jsr SETPC ; and now make absolute + sta FPCH ; Save in FPC + sty FPCBNK + lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + sta FPCL ; now move pointer to fetch spot + + lda #0 ; and set index + sta I ; thank you +TCHLP: + jsr FETCHB ; get the byte in [a] + ldx I ; get offset + inc I ; and point to next one + sta TCHARTBL,X ; save in lower memory, thank you + cmp #0 ; are we done yet? + beq TCHj ; NULL TERMINATED STRING + cmp #$FF ; $ff means all >128 chars are terminators + bne TCHLNEXT ; nope + lda #1 ; yes, + sta ALLFLG ; so set flag to say so +TCHLNEXT: + jsr NEXTFPC ; point to next one + jmp TCHLP ; and go get it +TCHj: + jsr DO_DSEGS ; set up disk segment pointers +; +; use mouse/joystick, see if either is connected +; + lda ZBEGIN+ZFLAGS+1 ; get game flags + and #FMOUS ; uses a mouse? + beq ZBEND ; nope, so don't ask + jsr MHOME ; clear & home +MSLOOP: + DLINE MMSG, ; ask about Mouse/Joystick/Keyboard + jsr MRDKEY ; get a key please + jsr MCOUT ; put key out there + and #$7F ; turn off hi bit + cmp #'M' ; mouse? + beq DO_MOUSE ; yup + cmp #'m' + beq DO_MOUSE + cmp #'J' ; Joystick? + beq DO_STICK ; yup + cmp #'j' + beq DO_STICK + cmp #'N' ; neither + beq DO_NEITHER ; yup + cmp #'n' + beq DO_NEITHER +MSLOOP1: + jsr MBELL ; complain + jmp MSLOOP ; and do again +DO_MOUSE: + jsr INST_MOUSE ; install mouse handlers + bcs MSLOOP1 ; problems, try again + bcc ZBEND ; continue +DO_STICK: + jsr INST_STICK ; install joystick handler + bcs MSLOOP1 ; try again + bcc ZBEND ; continue, please +DO_NEITHER: +ZBEND: +; +; +; Multiply ZFOFF & ZSOFF * 8 to get actual offset +; + lda ZBEGIN+ZFOFF ; hi part + sta FOFFM ; this'll be the middle part + lda ZBEGIN+ZFOFF+1 ; lo part + asl A ; *2 + rol FOFFM + rol FOFFH + asl A ; *4 + rol FOFFM + rol FOFFH + asl A ; *8 + rol FOFFM + rol FOFFH + sta FOFFL ; lo part here too +; +; now do string offset +; + lda ZBEGIN+ZSOFF ; hi part + sta SOFFM ; this'll be the middle part + lda ZBEGIN+ZSOFF+1 ; lo part + asl A ; *2 + rol SOFFM + rol SOFFH + asl A ; *4 + rol SOFFM + rol SOFFH + asl A ; *8 + rol SOFFM + rol SOFFH + sta SOFFL ; lo part here too + + lda ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + sta ZPCM ; MSB + lda ZBEGIN+ZGO+1 ; AND LSB + asl A ; *2 + rol ZPCM + rol ZPCH + asl A ; *4 + rol ZPCM + rol ZPCH +; +; now add offset +; + clc ; doing adding + adc FOFFL ; add in lo part + sta ZPCL + lda ZPCM + adc FOFFM + sta ZPCM + lda ZPCH + adc FOFFH + sta ZPCH +; +; now, set up TBLPUR, FUNPRE, and FUNPUR +; + lda SEGTBL+SGTTBLE+1 ; get last page of table preload + asl A ; make 256K page + sta TBLPUR ; show last pre table + inc TBLPUR ; but we want first pure table address + inc TBLPUR ; so point to it + lda SEGTBL+SGTFUNS+1 ; get first page of function preload + asl A ; make 256K page + sta FUNPRE ; show me + lda SEGTBL+SGTFUNE+1 ; last page of function preload + asl A ; make 256K page + sta FUNPUR ; show last pre function + inc FUNPUR ; but we want first pure function + inc FUNPUR ; now we point to it + + lda TBLPUR ; now figger out negative number to + sec ; add to function preload addres to + sbc FUNPRE ; get page offset in memory + sta FUNPGE ; set up offset +; +; and now to set up extension table pointer +; + lda ZBEGIN+ZEXTAB+1 ; LSB of table + sta MSTBL+LO ; stays the same + lda ZBEGIN+ZEXTAB ; MSB of table + jsr SETPC ; get me the memory addres + sty MSTBL+ABANK ; save bank + sta MSTBL+HI ; and page + + jmp INITPAG ; set up paging system + + END diff --git a/apple/yzip/ice/zdos.asm b/apple/yzip/ice/zdos.asm new file mode 100644 index 0000000..8447c1a --- /dev/null +++ b/apple/yzip/ice/zdos.asm @@ -0,0 +1,736 @@ + TITLE "Apple ][ YZIP (c)Infocom","--- ZDOS (SEEKING, READING, WRITING) ---" +; +; some ProDOS parameter blocks here +; +READ_PB: ; for READING files + db 4 ; 4 parameters +GMREF: db 0 ; refnum + dw IOBUFF ; read into io buffer + dw PAGELEN ; 512 byte buffer + dw 0 ; length actually read +OPEN_FILE: ; opening up the pure file + db 3 ; 3 parameters + dw GAME1NM ; name of pure file + dw GAME1FIO ; game file buffer + db 0 ; where refnum goes +PSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +SET_PB: + db 1 ; just one parameter + dw GAMEPL ; where to go to +SWAP1: db EOL, "Take out " +SWAP1L equ $-SWAP1 +SWAP2: db ", Side " +SWAP2L EQU $-SWAP2 +INSG: db EOL,"Insert " +INSGL EQU $-INSG +INSG2: db ", Side " +INSG2L EQU $-INSG2 +SWAPSAVE: db EOL,"Take out save disk.",EOL +SWAPSAVEL EQU $-SWAPSAVE +; +; which disk to swap out +; +SWAPDISK: db 0,'2','1','4','3' +; place to stash prefixes and names +GPRE_PB: ; game prefix spot + db 1 ; 1 parm + dw GAMEPL ; where to put prefix +GAMEL: db 0 +GAME: ds 15 ; longest name + +GAME1NM: +GAME1NML: + db 0 ; not sure how long +GAME1NAME: + ds 15 ; room for name +GAME1REF: db 0 ; save refnum here +GAME1NUM: db 0 ; number (0-3) of side + +GAME2NM: +GAME2NML: + db 0 ; not sure how long +GAME2NAME: + ds 15 ; room for name +GAME2REF: db 0 ; refnum for game file 2 +GAME2NUM: db 0 ; number (0-3) of side +GAMEPL: db 0 ; name of prefix for game file +GAMEP: ds 64-15 ; max len +; -------------------- +; READ A VIRTUAL PAGE +; -------------------- +; ENTRY: V-BLOCK TO READ IN [DBLOCK] +; BUFFER ADDRESS IN [DBUFF] +; DSKBNK SAYS WHERE TO PUT PAGE (AUX OR MAIN) +; EXIT: DATA AT [DBUFF] + +GETDSK: + jsr FINDSEG ; find the segment and point to it + SET_MARK PSEEK ; move to the block + bcs GDBAD ; just die then + jsr READ_DOS ; do the read, thank you + bcs GDBAD ; it broke, die +GDEX: + lda #HIGH IOBUFF ; first 256 byte page + jsr COPY_DATA ; and copy from IOBUFF to DBUFF + inc DBUFF+HI ; point to next one + lda #HIGH IOBUFF+1 ; next 256 byte page + jmp COPY_DATA ; and copy it over +GDBAD: + jmp DISK_FATAL ; just die then +; +; this is the fatal error spot +; +DISK_FATAL: + jsr DISK_ERR ; print out problem +DRIVE_ERR: + lda #14 + jmp ZERROR ; DRIVE ACCESS ERROR +; +; this routine prints out the string associated with the error and +; returns with the carry set, like most routines do when there is +; an error. The error should be in [A]. +; +UNK_DISK: db "ProDOS error $" +UNK_DISKL EQU $-UNK_DISK + +DISK_ERR: + pha ; save [A] + jsr SWAP2INFOW ; point to information window + pla ; get it back + + ldx #ELISTL ; scan the error table +DSKE: + cmp ELIST,X ; is it this one + beq DSKE1 ; ayyup + dex ; now skip the address + dex ; of the description + dex ; point to next error number + bpl DSKE ; jump to start +; +; if we are here print out unknown error and it's value +; + pha ; save [A] + DLINE UNK_DISK, + pla ; get [A] + jsr HEXNUM ; print [A] + jmp DSK_EXIT ; done +DSKE1: + inx ; point to string address + lda ELIST,X ; get lo part + sta L+LO ; save it + inx ; point to hi part + lda ELIST,X ; get hi part + tax ; save here + sta L+HI ; and here + ldy #0 ; for offset + lda (L),Y ; get length of string + tay ; save in y + inc L+LO ; point past length + lda L+LO ; get it + bne DSKPR ; for printing + inx ; wrapped +DSKPR: + txa ; hi part in a + ldx L+LO ; lo part in X + jsr DISPLAY_LINE ; print out message +DSK_EXIT: + jsr GETRET ; wait for RETURN + jsr SWAPBACK ; all done + sec ; show badness again + rts ; and be done with it +; +; HEXNUM - print out the HEX value of [A] at the current cursor +; location +; +HEXNUM: + pha + lsr A + lsr A + lsr A + lsr A + jsr NIB1 + pla +NIB1: + and #%00001111 + tay + lda HCHARS,Y + jsr CHAR ; print it out + rts +HCHARS: DB "0123456789ABCDEF" + +; ---------------------- +; WRITE [DBUFF] TO DISK +; ---------------------- +; ENTRY: File already open and positioned, ready to be written to +; from page in (DBUFF). Writes out 512bytes, starting @ DBUFF. +; EXIT: CARRY CLEAR IF OKAY, SET IF FAILED + +PUTDSK: + ldx DSKBNK ; get bank + ldy #0 ; clear Y + lda #HIGH IOBUFF ; first buffer + jsr SAVE_DATA ; and copy from DBUFF to IOBUFF + jsr NEXT_DBUFF ; point to next buffer + ldy #0 ; clear Y again + lda #HIGH IOBUFF+1 ; top part + jsr SAVE_DATA ; copy to IOBUFF + jsr NEXT_DBUFF ; count buffer + jmp WRITE_DOS ; and now write it +; --------------------- +; READ DBLOCK FROM DISK +; --------------------- +; CALLED BY RESTORE +; ENTER: with file already set up as it DBUFF +; L+LO == # of 256k blocks to read +; +GETRES: + lda L+LO ; get # of blocks + sta READ_PB+RD_BUFFLEN+HI + jsr READ_DOS + ldx #HIGH PAGELEN ; get starting number of pages + stx READ_PB+RD_BUFFLEN+HI + bcc GTROK ; everything is fine + rts ; error if c == set +GTROK: + lda #HIGH IOBUFF ; start at first block + sta L+HI ; we can use L+HI +GTRLOOP: + lda L+HI ; doing this block + jsr COPY_DATA ; and copy from IOBUFF to DBUFF + jsr NEXT_DBUFF ; check for wrap + inc L+HI ; count this block + dec L+LO ; count this block + bne GTRLOOP ; do next one + rts ; all finished +; +; NEXT_DBUFF +; increment DBUFF to count the 2 pages done +; +NEXT_DBUFF: + inc DBUFF+HI ; point to next page + lda DBUFF+HI ; see where we are + cmp #HIGH PRGLBL ; wrapping? + bne GTREX ; okay then + lda DSKBNK ; which bank we be in + bne GTR1 ; aux, so go to page 3 + inc DSKBNK ; point to aux + lda #Z2PAGE ; start of page 2 + bne GTREX ; so tell me which page +GTR1: + lda #P3BANK ; show page 3 bank + sta DSKBNK ; okay + lda #Z3PAGE ; page 3 of things +GTREX: + sta DBUFF+HI ; saved + rts ; all done +; +WRITE_DOS: + WRITE WRITE_SV ; write out save buffer + rts ; done +READ_DOS: + READ READ_PB ; read it + rts ; go home +; +; COPY_DATA - +; now move the data from iobuff to dbuff (in some bank) +; which part of IOBUFF is in [a] ($08 - $0B) +; +COPY_DATA: + sta SDLP3+2 ; self-modify code to get from IOBUFF + sta RDBNK+MAIN ; read from main + ldx DSKBNK ; get which bank it's going to + bmi CPD1 ; oh oh, third bank + sta STORE80+OFF + sta WRTBNK,X ; and select that bank for writing + bpl CPD2 ; okay, bank selected +CPD1: + lda DBUFF+HI ; get from this zero page + sta ALTZP+AUX ; talk about aux mem + sta DBUFF+HI ; and save this in aux mem ZP +CPD2: + ldy #0 ; start at beginning + sty DBUFF+LO ; just to be sure +SDLP3: + lda IOBUFF,Y ; this becomes modified! + sta (DBUFF),Y ; to [DBUFF] + iny + bne SDLP3 + sta ALTZP+MAIN ; talk about main page again + sta WRTBNK+MAIN ; end up back at main + sta STORE80+ON + rts +; +; Segment table handling routines +; + +; +; FINDSEG - find the Virtual page in DBLOCK by searching through +; the SEGTBL. +; +DISKPAGE: ds 2 ; spot to put starting disk page +BIGPAGE: ds 2 ; DBLOCK/2 for 512 pages +FINDSEG: + lda DBLOCK+HI ; work with MSB first + lsr A ; /2 + sta BIGPAGE+HI + lda DBLOCK+LO ; now LSB + ror A ; /2 + sta BIGPAGE+LO + lda GAME1NUM ; get number for disk 1 + jsr SCANSEG ; scan through the current disk table + lda GAME1REF ; save refnum + bcc FNDSG1 ; found it, figger it out + lda GAME2NUM ; get number for disk 1 + jsr SCANSEG ; see if it is here + lda GAME2REF ; save refnum + bcc FNDSG1 ; ayyup + jsr SEGQUEST ; get correct disk/file with segment +FNDSG1: + sta PSEEK+SM_REFNUM ; for seeking + sta GMREF ; and for reading + lda (DSEGS),Y ; pick up MSB of disk page + sta DISKPAGE+HI ; save it + iny ; point to LSB + lda (DSEGS),Y ; get it + sta DISKPAGE+LO ; save it +; now point to Starting page again + dey + dey + dey + dey + lda BIGPAGE+LO ; LSB of desired page + sec ; doing subtract + sbc (DSEGS),Y ; get rid of LSB of starting page + sta PSEEK+SM_FPOS+1 ; save here for now + dey ; point to MSB of starting page + lda BIGPAGE+HI ; get DBLOCK MSB + sbc (DSEGS),Y ; get offset + sta PSEEK+SM_FPOS+2 ; save here temporarily + clc ; now add offset to starting disk page + lda DISKPAGE+LO ; get starting disk page + adc PSEEK+SM_FPOS+1 ; add inter-segment offset + sta PSEEK+SM_FPOS+1 ; save LSB + lda DISKPAGE+HI ; get MSB of segment disk page + adc PSEEK+SM_FPOS+2 ; add inter-segment offset + sta PSEEK+SM_FPOS+2 ; save MSB of disk page + asl PSEEK+SM_FPOS+1 ; *2 for 256Kb pages + rol PSEEK+SM_FPOS+2 ; okay, we did + lda DBLOCK+LO ; check to see which page in 512 we are + and #$01 ; if odd, then add one more + beq FNDEX ; all done then + inc PSEEK+SM_FPOS+1 ; one more page + bne FNDEX ; all done if no wrap + inc PSEEK+SM_FPOS+2 ; nother page +FNDEX: + rts ; done +; +; SCANSEG - look through the current segment table for the desired +; address found in BIGPAGE. Return with Y pointing to disk page +; and carry cleared if found. Otherwise, return carry set. +; [A] = which side number we are checking (0-3) +; +SCANSEG: + pha ; save which disk + asl A ; make word index + tax ; make it an index + lda DSKSEG+LO,X ; get LSB + sta DSEGS+LO + lda DSKSEG+HI,X + sta DSEGS+HI + ldy #SGTNSEG+1 ; point to segment count + lda (DSEGS),Y ; get it + tax ; use x as counter + pla ; get which side + tay ; is it side zero + bne SCANSG1 ; nope + ldy #SGTSEG+12 ; skip first two, cuz they're preload + bne SCANNING ; okay ready to go +SCANSG1: + ldy #SGTSEG ; begin at beginning +SCANNING: + lda (DSEGS),Y ; get MSB of start + cmp BIGPAGE+HI ; check against block we want + beq SCAN1 ; might be okay + bcc SCAN2 ; PAGE HIGH start seg, check end seg + iny ; LSB of start +SCAN0: + iny ; MSB of end + bcs NEXTSEG ; not this one +SCAN1: + iny ; point to LSB of start + lda (DSEGS),Y ; get LSB + cmp BIGPAGE+LO ; check against desired LSB + beq GOTSEG ; we found it + bcs SCAN0 ; DBLOCK LSB LOW then start LSB, not found + dey ; point back to MSB of start +SCAN2: + iny ; LSB of start + iny ; MSB of end + lda (DSEGS),Y ; get MSB of end + cmp BIGPAGE+HI ; check against DBLOCK MSB + bcc NEXTSEG ; end LOW DBLOCK, check next segment + bne GOTSEG1 ; end HIGH DBLOCK, must be in this segment + iny ; point to end LSB + lda (DSEGS),Y ; get LSB + cmp BIGPAGE+LO ; how does it compare to desired LSB + bcs GOTSEG2 ; it's LOW = end, so it is here + dey ; point back to MSB +NEXTSEG: + iny ; point to LSB of end + iny ; MSB of disk page + iny ; LSB of disk page + iny ; MSB of next start page + dex ; count this segment + bne SCANNING ; check this segment + + sec ; show not on this disk + rts ; and done +GOTSEG: + iny ; MSB of end page +GOTSEG1: + iny ; LSB of end page +GOTSEG2: + iny ; MSB of disk offset + clc ; show we found it + rts ; all done +; +; SEGQUEST - find the correct disk/file with the desired page on +; it. Returns SCANSEG's stuff. +; +DISKCNTR: ds 1 ; disk count down +PAGENF: + db "Page not found in segment table: " +PAGENFL EQU $-PAGENF +SEGQUEST: + lda #1 ; start at first disk + sta DISKCNTR ; init counter +SEGQL: + lda DISKCNTR ; get disk + cmp SEGTBL+SGTDISKS+1 ; looked at all the disks? + bne SEGQL1 ; nope +; +; as a last resort, check disk 1, the boot disk +; + lda #0 ; set up DISKCNTR + sta DISKCNTR ; we did + jsr SCANSEG ; see if it is there + bcc SEGQ1 ; we found it + + DLINE PAGENF, + lda BIGPAGE+HI ; show MSB + jsr HEXNUM ; printed + lda BIGPAGE+LO ; and LSB + jsr HEXNUM ; we did + + lda #17 ; bad page + jmp ZERROR ; die a horrible death +SEGQL1: + lda DISKCNTR ; get which disk we be working on + jsr SCANSEG ; find out if it is here + bcc SEGQ1 ; it is, so open up file + inc DISKCNTR ; not in this disk + bne SEGQL ; and try again +; +; we have found the disk it is in, so ask for it if necessary +; +SEGQ1: + tya ; save the y pointer + pha ; it is saved + lda DISKCNTR ; get which disk we found it under + jsr FETCH_FILE ; go get the disk desired + pla ; get the Y reg back + tay ; and show it + lda GMREF ; get reference number again + rts ; all done +; +; FETCH_FILE: check to see if we can open GAMEFILE# (where # is in [A]) +; if not, ask for DISK#. +; +SAVENUM: db 0 ; spot to save ascii number +FETCH_FILE: + clc ; adding to make + adc #$30 ; it an ascii number + sta SAVENUM ; just save a minute + inc SAVENUM ; make name be one based + ldx GAME1NML ; get length of name + lda SAVENUM ; get name back + cmp #'3' ; are we looking for disk 1 or 2? + bcs FEFI1 ; disks 3 and 4 handled otherwise +FEFI00: + cmp GAME1NM,X ; is it the current open one? + bne FEFI0 ; nope, so we need to open it + ldy GAME1REF ; get game 1 refnum + bne FEFIX ; all set, so point to it +FEFI0: + jsr DO_GAME1 ; handle it special + bne FEFIX ; so all done +FEFI1: + cmp GAME2NM,X ; how bout second open file? + bne FEFI2 ; nope, so we need to open it + ldy GAME2REF ; it is second one, so show me + bne FEFIX ; it is open too +FEFI2: + sta GAME2NM,X ; using second file + lda GAME2REF ; get its refnum + beq FEFI20 ; nothing to close, thank you + sta CLOSE_PB+CL_REFNUM ; show close who to close + CLOSE CLOSE_PB ; close it up tight +FEFI20: + jsr OPEN_GAME2 ; open up GAME2 file + jsr GET_PDATA ; now get the picture data + ldy GAME2REF ; get ref back, please +FEFIX: + sty PSEEK+SM_REFNUM ; for seeking + sty GMREF ; and for reading + rts ; did it +; +; OPEN_GAME2 - open up the file that GAME2NM is pointing to, +; returning the REFNUM in [A], after storing in GAME2REF, +; and the 2 picture structures +; +OPEN_GAME2: + lda #HIGH GAME2NM ; get lo byte + sta OPEN_FILE+OP_PATHNAME+HI + lda #LOW GAME2NM ; set address in open block + sta OPEN_FILE+OP_PATHNAME+LO + lda #HIGH GAME2FIO ; now set up file i/o buffer + sta OPEN_FILE+OP_FILEBUFF+HI + lda #LOW GAME2FIO ; now set up file i/o buffer + sta OPEN_FILE+OP_FILEBUFF+LO + jsr OPEN_GAMEF ; find and open game file + lda OPEN_FILE+OP_REFNUM ; get refnum + sta GAME2REF ; save refnum here + sta PFILE_RD+RD_REFNUM + sta PFSEEK+SM_REFNUM ; for seeking + ldx GAME2NML ; get me number of this side + lda GAME2NM,X ; get ascii number + eor #'0' ; make it binary + sta GAME2NUM ; save num + dec GAME2NUM ; make it zero based + rts ; finis +; +; SET_GAMEPRE: check if game prefix is in, and if not go ask for it +; +SAVEDISK: db 0 ; == 1 if it is save disk to be swapped +SET_GAMEPRE: + jsr SWAP2INFOW ; point to info window + lda #HIGH GAMEPL ; set up parm block + sta SET_PB+SP_PATHNAME+HI + lda #LOW GAMEPL + sta SET_PB+SP_PATHNAME+LO +SETGP0: + SET_PREFIX SET_PB ; set to game 1 prefix + bcc SETGP1 ; okay, it is + lda SAVEDISK ; is it a save disk in there? + beq SEGTP00 ; nope + DLINE SWAPSAVE, + jmp SEGTP01 ; and continue +SEGTP00: + DLINE SWAP1, + DLINE GAME, GAMEL ; name of game + DLINE SWAP2, + lda SAVENUM ; get disk I want + eor #'0' ; get binary number + tax ; make index + lda SWAPDISK,X ; get which disk to swap + jsr CHAR ; and send it out +SEGTP01: + DLINE INSG, + DLINE GAME, GAMEL ; this is the name of the game + DLINE INSG2, + lda SAVENUM ; get which disk to put it + jsr CHAR ; print it out + jsr GETRET ; wait for LOW CRHIGH + beq SETGP0 ; try again +SETGP1: + jmp SWAPBACK ; pointing to disk +; +; DO_GAME1 - open up the special game 1 file and point to it +; [A] = Ascii, 1-based side name +DO_GAME1: + ldy GAME1REF ; get the current game 1 ref num + beq DOG1 ; not currently open + pha ; save Name + sty CLOSE_PB+CL_REFNUM ; show close + CLOSE CLOSE_PB ; and close it + pla ; get name back +DOG1: + sta GAME1NM,X ; save name + pha ; save it for later use + lda #HIGH GAME1NM ; get lo byte + sta OPEN_FILE+OP_PATHNAME+HI + lda #LOW GAME1NM ; set address in open block + sta OPEN_FILE+OP_PATHNAME+LO + lda #HIGH GAME1FIO ; now set up file i/o buffer + sta OPEN_FILE+OP_FILEBUFF+HI + lda #LOW GAME1FIO ; now set up file i/o buffer + sta OPEN_FILE+OP_FILEBUFF+LO + jsr OPEN_GAMEF ; so find and open game file + pla ; get number back + eor #'0' ; make binary + sta GAME1NUM ; save number + dec GAME1NUM ; decrement for usage + ldy OPEN_FILE+OP_REFNUM ; get refnum + sty GAME1REF ; save refnum here + rts ; did it +; +;OPEN_GAMEF: open the currently pointed to game file, getting the +; disk if necessary (ascii number of disk/file found in SAVENUM) +; +OPEN_GAMEF: + lda #0 ; reset volume flag + sta CHPTR+HI ;okay, we be ready +OPGM1: + SET_PREFIX SET_PB ; go to a prefix + + OPEN OPEN_FILE ; open the file file + bcc OPGMX ; okay + cmp #$46 ; file not found error? + beq OPGMV ; get the volume + cmp #$45 ; volume not found error? + beq OPGMV ; then ask for it + jmp DISK_ERR ; die with ZERROR +OPGMV: + jsr CHECKVOLS ; try another volume + bcc OPGM1 ; ==0 if no more volumes to try + lda SAVENUM ; get alpha numeric + ldy GAMEPL ; get length of prefix + dey ; point to last char ('/') + dey ; point to next to last char (0-9) + sta GAMEP,Y ; set number for prefix + jsr SET_GAMEPRE ; okay, set up prefix + bcc OPEN_GAMEF ; try again +OPGMX: + rts +; +; LISTVOLS - list all the online volumes for saving to +; +ONLINE_PB: + db 2 ; 2 parms for ONLINE call + db 0 ; unit == 0 to get all current ones + dw IOBUFF ; use IOBUFFER to store names +LSTVM: db EOL,"Volumes: ",EOL +LSTVML EQU $-LSTVM + +LISTVOLS: + DLINE LSTVM, + + ONLINE ONLINE_PB + bcc LSTV1 ; worked fine + jsr DISK_ERR ; complain if we had an error + bcs LSTVEX ; all done +LSTV1: + lda #0 ; start at byte zero + pha ; saved on stack +LSTVL: + pla ; get index + tax ; make it an index + lda IOBUFF,X ; get drive/length byte + beq LSTVEX ; all done if == 0 + and #$0F ; just care about length + tay ; save in [Y] for now + txa ; into [A] for addition + clc ; doing add + adc #16 ; point to next entry + pha ; save for later reference + tya ; check for zero length + beq LSTVL ; nothing here but an error + lda #'/' ; start with / to be better + jsr CHAR ; and it is out there +LSTVCL: + inx ; point to next char + lda IOBUFF,X ; get char + jsr CHAR ; print it out + dey ; count char + bne LSTVCL ; go get next char + lda #'/' ; end with '/' to show volume status + jsr CHAR ; and awaaaaay we go + lda #EOL ; do a LOW CRHIGH + jsr CHAR ; printed + dex ; count back one, as loop starts with inx + bne LSTVL ; go do next one +LSTVEX: + rts ; toots finis +; +; CHECKVOLS - set prefix to particular volume that is currently online +; +CHECKVOLS: + lda CHPTR+HI ; is it zero? + bne CHV1 ; if not, then get next volume + ONLINE ONLINE_PB ; get online volumes + bcc CHV0 ; okey dokey +CHVBX: + sec ; show badness + rts ; all done +CHV0: + lda #LOW (IOBUFF-16) ; get LSB (-16 cuz we start with add) + sta CHPTR+LO + lda #HIGH IOBUFF ; and mSB + sta CHPTR+HI + lda #HIGH SCRBUFF ; this is where we will work on it + sta SET_PB+SP_PATHNAME+HI + lda #LOW SCRBUFF + sta SET_PB+SP_PATHNAME+LO +CHV1: + lda CHPTR+LO ; point to next entry + clc ; getting ready for add + adc #16 ; this points to next one + sta CHPTR+LO ; can't be any wrapping + ldy #0 ; to use indirect addressing + lda (CHPTR),Y ; get length byte + beq CHVBX ; all done if == 0 + and #$0F ; get rid of upper junk + beq CHV1 ; nothing in this one, do it again + sta SCRBUFF ; save length + inc SCRBUFF ; count the add '/' + tay ; get for countdown + lda #'/' ; need to start with a slash + sta SCRBUFF+1 ; okay, we are +CHVL: + lda (CHPTR),Y ; get char in path name + sta SCRBUFF+1,Y ; save name + dey ; count char + bne CHVL ; go get next one + + SET_PREFIX SET_PB ; so point to it +CHVX: + rts ; carry==0, we worked okay +; +; GET_SPECIAL - if we are in infodos, then we preload the first 12Kb of +; stuff into the area in the main bank, pages $D0-$FF, Language Card 2. +; Assume .D2 file has just been opened and go get it. +GET_SPECIAL: + lda #2 ; one page at a time + sta READ_PB+RD_BUFFLEN+HI ; show how much is special + lda #SP_SIZE ; how many pages in special part? + sta J+LO ; use as counter + lda #HIGH SP_START ; where does it go? + sta L+HI ; L is pointer to there +GTS_RD: + READ READ_PB ; go get 1Kb + bcc GTS_RD1 ; just fine + jmp DISK_FATAL ; croak otherwise +GTS_RD1: + lda #HIGH IOBUFF ; get MSB of start + sta K+HI ; K is source + ldx #2 ; 2 blocks of 256 bytes each +GTS_CPL0: + ldy #0 ; indexer +GTS_CPL: + lda (K),y ; get it + sta (L),y ; store it + iny ; next + bne GTS_CPL ; gwon then + inc K+HI ; point to next block + inc L+HI ; for destination too + dex ; count block + bne GTS_CPL0 ; next block + dec J+LO ; count this 1Kb + bne GTS_RD ; go get next one + rts ; done + + + END diff --git a/apple/yzip/ice/zero.bat b/apple/yzip/ice/zero.bat new file mode 100644 index 0000000..faae5ca --- /dev/null +++ b/apple/yzip/ice/zero.bat @@ -0,0 +1,3 @@ +f.dlvars,.ch_byte,0 +f.oldzv,6947,0 + diff --git a/apple/yzip/ice/zero.equ b/apple/yzip/ice/zero.equ new file mode 100644 index 0000000..c158778 --- /dev/null +++ b/apple/yzip/ice/zero.equ @@ -0,0 +1,173 @@ + TITLE "Apple ][ YZIP (c)Infocom","ZERO PAGE VARIABLES" + PAGE + +SCRCX EQU 0 ; CURSOR HORIZONTAL +SCRCY EQU SCRCX+1 ; CURSOR VERTICAL +SCRBTM EQU SCRCY+1 ; first line outside current window +MAXLINES EQU SCRBTM+1 ; maximum number of lines in window +LEFTMRG EQU MAXLINES+1 ; left edge + left margin in current window +WINDOW EQU LEFTMRG+1 ; (WORD) address of current window structure +WRPFLG EQU WINDOW+2 ; wrapping flag +SCRLFLG EQU WRPFLG+1 ; scrolling flag +BUFFLG EQU SCRLFLG+1 ; buffering flag +CLSLEFT EQU BUFFLG+1 ; screen limits for CLS code +CLSTOP EQU CLSLEFT+1 ; top of screen +CLSWIDTH EQU CLSTOP+1 ; # of columns +CLSHEIGHT EQU CLSWIDTH+1 ; # of lines +; +; some variables for all the screen positioning code +; +NY_DATA EQU CLSHEIGHT+1 ; place for GET/PUT_NYBBLE to use +CH_OFFSET EQU NY_DATA+1 ; offset into char data table +DATALOOP EQU CH_OFFSET+1 ; loop counter for byte works +BITOFF EQU DATALOOP+1 ; bit offset into screen byte +CH_DATA EQU BITOFF+1 ; actual char data being worked on +SCR_DATA EQU CH_DATA+1 ; screen byte being worked on +SH_LOOP EQU SCR_DATA+1 ; loop counter for bit shifting +SCROLLY EQU SH_LOOP+1 ; save spot for y pos when scrolling +MID EQU SCROLLY+1 ; (BYTE) Machine ID +CHRMAX EQU MID+1 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD +SCLLINES EQU CHRMAX+1 ; (BYTE) how many lines to scroll +FMTTBL EQU SCLLINES+1 ; (BYTE) flag to show formatted table output +STMASK EQU FMTTBL+1 ; (BYTE) Mask to use on first byte of CLS +ENDMASK EQU STMASK+1 ; (BYTE) Mask to use on last byte of CLS +CHPTR EQU ENDMASK+1 ; (WORD) pointer to char data +SCOFF EQU CHPTR+1 ;(BYTE) Offset used by scroll +DSEGS EQU SCOFF+1 ; (WORD) Pointer to current disk's segments +LASTWV EQU DSEGS+2 ; last of the WINDOW variables + +ZEROPG EQU $50 ; FIRST FREE Z-PAGE LOCATION +; +; these are first, cuz ZBOOT inits them so we don't want to clear them +; at ZBEGIN warm start +; +GLOBAL EQU ZEROPG ; (Relative Addr.) GLOBAL VARIABLE POINTER +VOCAB EQU GLOBAL+2 ; (ADDRESS) Vocab table pointer +FWORDS EQU VOCAB+3 ; (ADDRESS) F-WORDS TABLE POINTER +MOUSEF EQU FWORDS+3 ; (BYTE) ==-1/1 if we have mouse/joystick +INFODOS EQU MOUSEF+1 ; (WORD) if <>0, then pointer to D2SEG +FUNOFF EQU INFODOS+2 ; (ADDRESS) Function Offset (ZFOFF*8) +FOFFH EQU FUNOFF ; (BYTE) Hi part +FOFFM EQU FUNOFF+1 ; (BYTE) Middle part +FOFFL EQU FUNOFF+2 ; (BYTE) Lo part +STROFF EQU FUNOFF+3 ; (ADDRESS) String Offset (ZSOFF*8) +SOFFH EQU STROFF ; (BYTE) Hi part +SOFFM EQU STROFF+1 ; (BYTE) Middle part +SOFFL EQU STROFF+2 ; (BYTE) Lo part +; +; Beginning of warm start zeroing +; +OPCODE EQU STROFF+3 ; (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 +ARG5 EQU OPCODE+10 ; (WORD) +ARG6 EQU OPCODE+12 ; (WORD) +ARG7 EQU OPCODE+14 ; (WORD) +ARG8 EQU OPCODE+16 ; (WORD) +ABYTE EQU OPCODE+18 ; (BYTE) X-OP ARGUMENT BYTE +BBYTE EQU OPCODE+19 ; (BYTE) XCALL ARG BYTE (EZIP) +ADEX EQU OPCODE+20 ; (BYTE) X-OP ARGUMENT INDEX +VALUE EQU OPCODE+21 ; (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 +L EQU VALUE+8 ; (WORD) GEN-PURPOSE REGISTER #4 +ZPC EQU VALUE+10 ; (3 BYTES) ZIP PROGRAM COUNTER +ZPCL EQU ZPC ; (BYTE) <8 BITS OF [ZPC] +ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] +ZPCH EQU ZPC+2 ; (BYTE) >BIT OF [ZPC] +ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE +ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +ZPNTH EQU ZPCPNT+1 ; (BYTE) +ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +MPC EQU ZPCPNT+3 ; (3 BYTES) MEMORY PROGRAM COUNTER +MPCL EQU MPC ; (BYTE) <8 BITS OF [MPC] +MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] +MPCH EQU MPC+2 ; (BYTE) >BIT OF [MPC] +MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE +MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +MPNTH EQU MPCPNT+1 ; (BYTE) +MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +FPC EQU MPCBNK+1 ; (3 Bytes) Fetch pointer +FPCL EQU FPC ; (BYTE) Low part +FPCH EQU FPCL+1 ; (BYTE) High Part +FPCBNK EQU FPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) +SPC EQU FPCBNK+1 ; (3 Bytes) Fetch pointer +SPCL EQU SPC ; (BYTE) Low part +SPCH EQU SPCL+1 ; (BYTE) High Part +SPCBNK EQU SPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + +; Z-STRING MANIPULATION VARIABLES + +LINLEN EQU SPCBNK+1 ; (BYTE) LENGTH OF CURRENT LINE +SOURCE EQU LINLEN+1 ; (BYTE) counter for read +WRDLEN EQU SOURCE+1 ; (BYTE) LENGTH OF CURRENT WORD +ESIZE EQU WRDLEN+1 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES +PSET EQU ESIZE+1 ; (BYTE) PERMANENT CHARSET +TSET EQU PSET+1 ; (BYTE) TEMPORARY CHARSET +ZCHAR EQU TSET+1 ; (BYTE) CURRENT Z-CHAR +OFFSET EQU ZCHAR+1 ; (BYTE) F-WORD TABLE OFFSET +ZFLAG EQU OFFSET+1 ; (BYTE) Z-WORD ACCESS FLAG +ZWORD EQU ZFLAG+1 ; (WORD) CURRENT Z-WORD +CONCNT EQU ZWORD+2 ; (BYTE) Z-STRING SOURCE COUNTER +CONIN EQU CONCNT+1 ; (BYTE) CONVERSION SOURCE INDEX +CONOUT EQU CONIN+1 ; (BYTE) CONVERSION DEST INDEX +DIRTBL EQU CONOUT+1 ; (WORD) CONTAINS TBLE TO STORE CHARS TO +XSIZE EQU DIRTBL+2 ; (WORD) SCREEN WIDTH FOR TESTS +RAND1 EQU XSIZE+2 ; (BYTE) +RAND2 EQU XSIZE+3 ; (BYTE) RANDOM # +CURWIN EQU XSIZE+4 ; (BYTE) WHICH WINDOW TO WRITE IN +LENGTH EQU CURWIN+1 ; (WORD) CHAR POSITION ON THE SCREEN +CHRCNT EQU LENGTH+2 ; (BYTE) CHAR POSITION IN [LBUFF] +SCRIPT EQU CHRCNT+1 ; (BYTE) SCRIPT ENABLE FLAG +LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER +IOCHAR EQU LINCNT+1 ; (BYTE) CHARACTER BUFFER +COLORP EQU IOCHAR+1 ; (WORD) Pointer to current background color +ZSP EQU COLORP+2 ; (WORD) Z Stack +SCREENF EQU ZSP+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT +TABLEF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT +VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH +DBUFF EQU VOCEND+3 ; (WORD) RAM PG TO ACCESS (LSB = 0) +DSKBNK EQU DBUFF+2 ; (BYTE) MAIN/AUX bank +ALLFLG EQU DSKBNK+1 ; (BYTE) IF =1 ALL FCN KEYS (>127) ARE TCHARS +UNDFLG EQU ALLFLG+1 ; (BYTE) Underlining flag +INVFLG EQU UNDFLG+1 ; (BYTE) Inverse flag +MEMPAGE EQU INVFLG+1 ; (BYTE) Save spot for XPAGING stuff +CPY_COUNT EQU MEMPAGE+1 ; (BYTE) Number of bytes for copy line +TBLHEIGHT EQU CPY_COUNT+1 ;(BYTE) Number of lines in printing table +TBLWIDTH EQU TBLHEIGHT+1 ;(BYTE) Number of bytes per line +TBLCNT EQU TBLWIDTH+1 ;(BYTE) Counter for table printing +FONTFLG EQU TBLCNT+1 ;(BYTE) Which font (!=0 is width) +TBLPUR EQU FONTFLG+1 ;(BYTE) first pure table page +FUNPRE EQU TBLPUR+1 ;(BYTE) first preloaded function page +FUNPUR EQU FUNPRE+1 ;(BYTE) first pure function page +FUNPGE EQU FUNPUR+1 ;(BYTE) -number to get function preload page +DELAY_COUNTER EQU FUNPGE+1 ;(BYTE) counter for delay loop +; +; some char-to-screen variables +; +CHAR_D1 EQU DELAY_COUNTER+1 ; (BYTE) character data, part 1 +CHAR_D2 EQU CHAR_D1+1 ; (BYTE) char data, part 2 +CW EQU CHAR_D2+1 ; (BYTE) width of the character +CLKCTR EQU CW+1 ; (BYTE) counter for mouse clicking +MSX EQU CLKCTR+1 ; (BYTE) mouse cursor X +MSY EQU MSX+1 ; (BYTE) mouse cursor Y +CURRENT EQU MSY+1 ; (BYTE) current paging bufer +MSTBL EQU CURRENT+1 ; (ADDRESS) pointer to extension table +LASTZP EQU MSTBL+3 ; just checking +; +; these routines are in non-swapped memory +; +ZERO_FB EQU LASTZP ; put fetch byte routine in at end of ZP +ZERO_ZF EQU ZERO_FB+11 ; and ZPCPNT fetch after that +ZERO_MF EQU ZERO_ZF+9 ; and MPCPNT fetch after that +SAVE_DATA EQU ZERO_MF+9 ; copy data from DBUFF to IOBUFF routine +; +; and just to check the end +; +ZEE_END EQU SAVE_DATA+17 ; should be == 100 + + END diff --git a/apple/yzip/ice/zip.equ b/apple/yzip/ice/zip.equ new file mode 100644 index 0000000..035cff5 --- /dev/null +++ b/apple/yzip/ice/zip.equ @@ -0,0 +1,114 @@ + TITLE "Apple ][ YZIP (c)Infocom","YZIP EQUATES" + PAGE + +VERSID EQU 51 ; VERSION OF INTERPRETER + ; See file "versions" for complete descriptions + +TRUE EQU $FF +FALSE EQU 0 + +; --------------------- +; Segment table equates +; --------------------- +SGTDISKS EQU 0 ; number of disks +SGTPAD EQU SGTDISKS+2 ; just some extra room +SGTCHKS1 EQU SGTPAD+16 ; Checksum for disk 1 (PRELOAD) +SGTPICOF1 EQU SGTCHKS1+2 ; N/A +SGTSEG1 EQU SGTPICOF1+2 ; # of segments for preload (should be 2) +SGTTBLS EQU SGTSEG1+2 ; Start of table preload (should be 0) +SGTTBLE EQU SGTTBLS+2 ; Last page of table preload +SGTTBLX EQU SGTTBLE+2 ; N/A +SGTFUNS EQU SGTTBLX+2 ; First page of function preload +SGTFUNE EQU SGTFUNS+2 ; End page of function preload +SGTFUNX EQU SGTFUNE+2 ; N/A +SGTDSK EQU SGTFUNX+2 ; Actual start of disk segment tables + +SGTCHKS EQU 0 ; check sum for file +SGTPICOF EQU 2 ; picture data offset +SGTNSEG EQU 4 ; # of segments in this list +SGTSEG EQU 6 ; start of segments +; --------------------- +; Z-CODE HEADER OFFSETS +; --------------------- + +ZVERS EQU 0 ; VERSION BYTE +ZMODE EQU 1 ; MODE SELECT BYTE +ZID EQU 2 ; GAME ID WORD +ZENDLD EQU 4 ; # OF QUADWORDS ON SIDE 1 OF DISK +ZGO EQU 6 ; EXECUTION ADDRESS +ZVOCAB EQU 8 ; START OF VOCABULARY TABLE +ZOBJEC EQU 10 ; START OF OBJECT TABLE +ZGLOBAL EQU 12 ; START OF GLOBAL VARIABLE TABLE +ZPURBT EQU 14 ; START OF "PURE" Z-CODE +ZFLAGS EQU 16 ; FLAG WORD +ZSERIA EQU 18 ; 3-WORD 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 +ZINTWD EQU 30 ; INTERPRETER ID WORD (SUPPLIED BY EZIP) +ZSCRWD EQU 32 ; SCREEN PARAMETER WORD ( " " " ) +ZHWRD EQU 34 ; DISPLAY WIDTH IN PIXELS +ZVWRD EQU 36 ; DISPLAY HEIGHT IN PIXELS +ZFWRD EQU 38 ; FONT HEIGHT, FONT WIDTH +ZFOFF EQU 40 ; FUNCTION OFFSET +ZSOFF EQU 42 ; STRING OFFSET +ZCLRWD EQU 44 ; FORGROUND COLOR, BACKGROUND COLOR +ZTCHAR EQU 46 ; POINTER TO TBL OF TERMINATING CHARS +ZTWIDTH EQU 48 ; Running counter for table output char width +ZCRFUNC EQU 50 ; FUNCTION FOR CARRIAGE RETURNS +ZCHRSET EQU 52 ; POINTER TO CHAR SET TBL +ZEXTAB EQU 54 ; Points to extension table, if needed +; +; Extension table offsets +; +ZEXTLEN EQU 0 ; Length of extension table +ZMSLOCX EQU 2 ; x location of mouse +ZMSLOCY EQU 4 ; y location of mouse +ZMSETBL EQU 6 ; MOUSE TBL CHANGE WORD +ZMSEDIR EQU 8 ; DIRECTION MENU +ZMSEINV EQU 10 ; INVENTORY MENU +ZMSEVRB EQU 12 ; FREQUENT VERB MENU +ZMSEWRD EQU 14 ; FREQUENT WORD MENU +ZBUTTN EQU 16 ; BUTTON HANDLER +ZJOYST EQU 18 ; JOYSTICK HANDLER +ZBSTAT EQU 20 ; BUTTON STATUS +ZJSTAT EQU 22 ; JOYSTICK STATUS +; +; ZFLAGS values +; +FSCRI EQU $01 ; scripting? +FMONO EQU $02 ; mono spaced font? +FSTAT EQU $04 ; status line refresh? +FDISP EQU $08 ; uses DISPLAY operations? +FUNDO EQU $10 ; uses UNDO? +FMOUS EQU $20 ; uses mouse? +FCOLO EQU $40 ; uses color? +FMENU EQU $80 ; uses menus? +;--------------- +; Picture data +;--------------- +;=== DATA HEADER === +PHFID EQU 0 ; File ID +PHFLG EQU PHFID+1 ; Flags +PHHUFF EQU PHFLG+1 ; Pointer to Huffman data +PHNLD EQU PHHUFF+2 ; # entries in local directory +PHNGD EQU PHNLD+2 ; # entries in global directory +PHDSIZE EQU PHNGD+2 ; Local directory entry size +PHCHKS EQU PHDSIZE+2 ; File Checksum +PHFVERS EQU PHCHKS+2 ; File Version (N/A) +PHEXTRA EQU PHFVERS+2 ; Extra room for getting fatter +PHSIZE EQU 16 ; 16 bytes is header size +;=== DATA HEADER FLAGS === +PHFGD EQU $1 ; data has global directory +PHFHUFF EQU $2 ; Huffman encoded pictures +PHFHUFF1 EQU $4 ; All pictures use same Huff tree +PHFPAL EQU $8 ; No pallette information +;=== LOCAL DIRECTORY === +PLDID EQU 0 ; Picture ID +PLDWID EQU PLDID+2 ; Picture Width +PLDHGHT EQU PLDWID+1 ; Picture Height +PLDFLG EQU PLDHGHT+1 ; Flags +PLDPTR EQU PLDFLG+1 ; Pointer to picture data +PLDSIZE EQU PLDPTR+3 ; size of local directory entry + + END diff --git a/apple/yzip/ice/zsavres.asm b/apple/yzip/ice/zsavres.asm new file mode 100644 index 0000000..4dc3e4b --- /dev/null +++ b/apple/yzip/ice/zsavres.asm @@ -0,0 +1,630 @@ + TITLE "Apple ][ YZIP (c)Infocom","--- ZIP SAVE AND RESTORE ROUTINES ---" +; ----------------------------- +; SET UP SAVE & RESTORE SCREENS +; ----------------------------- +SAVRES: + jsr ZCRLF ; CLEAR THE LINE BUFFER + lda #0 + sta SCRIPT ; DISABLE SCRIPTING + rts + +; ----------------------------- +; SAVE & RESTORE STRINGS +; ----------------------------- +YES: DB "YES" + DB EOL +YESL EQU $-YES +NO: DB "NO" + DB EOL +NOL EQU $-NO + +NAMEQ: db EOL + db "Insert save disk and enter " + db "full pathame of save file: " + db EOL + db "Hit '?' key to get a list of online volumes." + db EOL + db "Current pathname is:" + db EOL +NAMEQL EQU $-NAMEQ +SNDATA: ; show start of name and length +SNAMEL: db 0 ; place to save length of name +SAVENAME: ds 64 ; save plenty of room for max name + +DELQ: db EOL,"File exists, delete it (Yes/No)? " +DELQL EQU $-DELQ+1 ; include this following EOL +RETQ: db EOL,"Please hit [RETURN]",EOL +RETQL EQU $-RETQ +; ----------------------------- +; SAVE/RESTORE Parameter Blocks +; ----------------------------- +CREATE_PB: + db 7 ; 7 parameters + dw SNDATA ; pointer to name + db $C3 ; full access to file + db $06 ; BIN file type + dw 0 ; no aux data + db $01 ; standard file + dw 0 ; create date + dw 0 + ; creation time +SETEOF_PB: + db 2 ; 1 parameter + db 0 ; refnum + db 0,0,0 ; set to zero spot to clear it out +OPEN_SV: + db 3 ; 3 parameters + dw SNDATA ; name + dw GAME1FIO ; file buffer + db 0 ; ref num +CLOSE_PB: + db 1 ; only one parm + db 0 ; the refnum +WRITE_SV: + db 4 ; parm count + db 0 ; refnum + dw IOBUFF ; data is always here + dw 512 ; 1 page worth + dw 0 ; how many actually went + +; get the save file name. If user hits the ESC key, then abort the +; save by return with the carry set. +; +GET_SNAME: + jsr CLOSE_GAME ; close the game files + jsr SWAP2INFOW ; goto information window +GTSN0: + DLINE NAMEQ, + lda SNAMEL ; is there a name yet? + beq GTSN00 ; nope + DLINE SAVENAME,SNAMEL ; show current name of file +GTSN00: + lda #0 ; clear line count + sta CLOSE_PB+CL_REFNUM ; clear this too + ldx SNAMEL ; get length + stx CHRCNT ; okay + ldy SNAMEL ; point to copy + dey ; one less +GCOPY: + lda SNAMEL,X ; get char + sta LBUFF,Y ; save it + dex ; point to previous one + dey ; previous pointer + bpl GCOPY ; copy until length byte +GNAME: + jsr GETKEY ; WAIT FOR A KEY + cmp #EOL ; IF [RETURN], + beq GOTNAME ; got the name + cmp #ESCAPE ; hit escape key? + sec ; just in case it does exit + beq GNX ; so then die + cmp #BACKSPACE ; erasing things? + bne GNM1 ; nope + + ldx CHRCNT ; make sure there are chars there + bne GNMBP ; ayyup, do delete +GNMBAD: + jsr BEEP ; no room for delete + jmp GNAME ; okay +GNMBP: + dex ; point down one + stx CHRCNT ; count one down + lda LBUFF,X ; get char to delete + tax ; show in [X] + lda #BACKSPACE ; and doing a backspace + bne GNMSHOW ; okay, delete char on screen +GNM1: + cmp #'/' ; slash is the only good non-numeric char + beq GNMGOOD ; fine, use it + cmp #'.' ; well, maybe a . too + beq GNMGOOD ; fine, here it is + cmp #VOLCHAR ; does user want list of volumes? + bne GNM1x ; nope + + lda #0 ; clear out current name + sta CHRCNT ; okay, we did + jsr LISTVOLS ; show them + jmp GTSN0 ; start over, kind of +GNM1x: + cmp #'0' ; is it a number + bcc GNMBAD ; nope + cmp #'9'+1 ; well? + bcc GNMGOOD ; yup + cmp #'z'+1 ; make sure it is alpha numeric + bcs GNMBAD ; nope + cmp #'A' ; well? + bcc GNMBAD ; nope + cmp #'a' ; little char? + bcs GNMGOOD ; yup + cmp #'Z'+1 ; big char + bcs GNMBAD ; nope +GNMGOOD: + ldx CHRCNT ; get name index + inc CHRCNT ; point to next char + sta LBUFF,X ; save name char +GNMSHOW: + jsr CHAR ; show character + jsr DISP_LINE ; make sure it is there + jmp GNAME ; go get next char +; +; got the name, so copy it to the SAVENAME buffer +; +GOTNAME: + ldx CHRCNT ; get how many characters + stx SNAMEL ; save in length byte + dex ; points one too far +GNL: + lda LBUFF,X ; get the char + sta SAVENAME,X ; save the char + dex ; point to previous one + bpl GNL ; and go get it + clc ; show did just fine +GNX: + php ; save status + lda #EOL ; print EOL + jsr CHAR ; okay + lda #0 ; and clear CHRCNT + sta CHRCNT ; okay + jsr SWAPBACK ; change back to old window + plp ; get status back + rts ; all done +; +; open up a save file, by first trying to create it. If it already exists +; then make sure the player wants to delete the file, then get rid of it. +; Finally open the file. Return with carry set if user aborts the save. +; Store the ref number into the write parm block. +; +OPEN_SAVE: + CREATE CREATE_PB ; first try to create the file + bcc OPSV_OPEN ; created just fine, so open it +; +; can't create the file, check out why +; + cmp #$47 ; this means file already there + beq OPSV1 ; nope, not that + jmp DISK_ERR ; show badness +OPSV1: + DLINE DELQ, + jsr GETYN ; get me the yes or no + bcc OPSV_OPEN ; so then delete it if yes + rts ; nope, so just quit +OPSV_OPEN: + OPEN OPEN_SV ; open the save file + bcc OPSV_OP1 ; okey, things worked just fine + jmp DISK_ERR ; complain about error +OPSV_OP1: + lda OPEN_SV+OP_REFNUM ; get the ref number + sta WRITE_SV+WR_REFNUM ; save the ref number + sta CLOSE_PB+CL_REFNUM ; to close parm too + sta SETEOF_PB+SE_REFNUM ; for cleansing file + SET_EOF SETEOF_PB ; clear out file + bcc OPSVEX ; no problems + jsr DISK_ERR ; complain +OPSVEX: + rts ; file has been opened, return +; +; OPEN_RES - open the save file +; +OPEN_RES: + OPEN OPEN_SV ; open it up + bcc OPR1 ; okay, it worked + rts ; okay, it didn't +OPR1: + lda OPEN_SV+OP_REFNUM ; get reference number + sta READ_PB+RD_REFNUM ; save for read + sta CLOSE_PB+CL_REFNUM ; and for close + rts +; +; CLOSE_SAVE: close up the save file if it is open +; +CLOSE_SAVE: + lda CLOSE_PB+CL_REFNUM ; check if it opened + beq CLSVX ; okay, nothing + CLOSE CLOSE_PB ; close the save file +CLSVX: + lda #1 ; open up GAME2 file, just for kicks + sta SAVEDISK ; show we have a save disk in there + jsr FETCH_FILE ; this does it + lda D2SEG+HI ; set DSEGS to point to #2 + sta DSEGS+HI + lda D2SEG+LO + sta DSEGS+LO + ldx GAME2NML ; get length of current name + lda GAME2NM,X ; get the number of the file + sta SAVENUM ; we need this to look for prefix + jsr OPEN_GAME2 ; open up GAME2 file + inc SCRIPT ; allow scripting again + lda #0 ; open up GAME2 file, just for kicks + sta SAVEDISK ; show we have a save disk in there + sta CLOSE_PB+CL_REFNUM ; clear close + rts ; DONE +; +; CLOSE_GAME - close the current game file(s) +; and set DSEGS to point to preload so it will reopen them +; +CLOSE_GAME: + lda #0 ; show no files are open + sta CLOSE_PB+CL_REFNUM ; 0 closes all files + sta GAME1REF ; zero out two game files too + sta GAME2REF ; and here is number 2 + CLOSE CLOSE_PB ; now all are closed + rts +; +; Get answer to Yes/No question. Return with C==0 for yes, and C==1 +; for a no. RETURN == Yes, ESCAPE == NO +; +GETYN: + jsr GETKEY ; get the key strok + cmp #'y' ; IF REPLY IS "Y" + beq ALLSET ; ACCEPT RESPONSES + cmp #'Y' ; get both y's + beq ALLSET + cmp #EOL ; EOL IS ALSO ACCEPTABLE + beq ALLSET + cmp #'n' ; IF REPLY IS "N" + beq NOTSAT ; return with carry set + cmp #'N' ; check both n's + beq NOTSAT + cmp #ESCAPE ; check for ESC key too + beq NOTSAT ; which means no + jsr BEEP ; ELSE BEEP + jmp GETYN ; INSIST ON Y OR N +NOTSAT: + DLINE NO, + sec ; set the carry + rts ; and show it +ALLSET: + DLINE YES, + clc ; clear the carry + rts +GETRET: + DLINE RETQ, +GETRETL: + jsr GETKEY ; get a key + cmp #EOL ; return key? + bne GETRETL ; nope + jsr CHAR ; show the LOW CRHIGH + rts + +; --------- +; SAVE GAME +; --------- +ZSAVE: + lda #'N' + ldx NARGS + beq OLDSAV ; NORMAL, COMPLETE SAVE + lda #'P' +OLDSAV: + sta TYPE + jsr SAVRES ; set up screen + jsr GET_SNAME ; get the name of the save file + bcs ZSEXIT ; don't wanna after all + jsr OPEN_SAVE ; open the file + bcs ZSEXIT ; don't really care to +; +; SAVE GAME PARAMETERS IN [BUFSAV] +; + lda ZBEGIN+ZID ; MOVE GAME ID + sta BUFSAV+0 ; INTO 1ST 2 BYTES + lda ZBEGIN+ZID+1 ; OF THE A + sta BUFSAV+1 + lda ZSP+LO ; MOVE [ZSP] + sta BUFSAV+2 + lda ZSP+HI + sta BUFSAV+3 + lda OLDZSP+LO + sta BUFSAV+4 + lda OLDZSP+HI ; MOVE [OLDZSP] + sta BUFSAV+5 + ldx #2 ; MOVE CONTENTS OF [ZPC] +ZSL1: lda ZPC,X ; TO BYTES 7-9 + sta BUFSAV+6,X ; OF [BUFSAV] + dex + bpl ZSL1 + lda TYPE + sta BUFSAV+9 ; NORMAL OR PARTIAL + cmp #'P' + bne ZSNONM ; NORMAL SAVE SO NO name TO SAVE + + lda ARG3+LO ; set up FPC to get save name + sta FPCL ; lo part is okay + lda ARG3+HI ; get page + jsr SETPC ; get memory addr + sta FPCH ; page number + sty FPCBNK ; and bank + jsr FETCHB ; get count + sta I ; and save it + jsr NEXTFPC ; point to next byte + lda #0 ; set up data offset + sta J ; did it +ZSL3: + jsr FETCHB ; get data byte + ldy J ; get offset + sta BUFSAV+10,Y ; save into buffer + jsr NEXTFPC ; point to next byte + inc J ; next byte + dec I ; count it + bne ZSL3 ; loop again +ZSNONM: +; +; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK +; + lda #MAIN ; in the main bank + sta DSKBNK ; thank you + lda #HIGH LOCALS ; start at locals + sta DBUFF+HI ; POINT TO THE PAGE + jsr PUTDSK ; AND WRITE IT OUT + bcc ZSOK ; IF SUCCEEDED, WRITE STACK +ZSBAD: + jsr DISK_ERR ; print error message +ZSEXIT: + jsr CLOSE_SAVE ; else get game file back + jmp RET0 ; AND FAIL +; +; IF A PARTIAL SAVE WRITE FROM ARG1 FOR ARG2 BYTES TO DISK +; (ROUNDED TO PGS) SKIPPING ZSTACK WRITE +; +ZSOK: + lda TYPE + cmp #'P' + bne ZSALL + lda ARG1+HI ; find where to start & how far to go + jsr SETPC ; get page in memory + sta DBUFF+HI ; this is page + sty DSKBNK ; which bank + ldx ARG2+HI ; get MSB of count + lda ARG1+LO ; get lo offset + clc ; add + adc ARG2+LO ; lo count + bcc ZSPINC ; no extra page + inx ; wrapped extra page +ZSPINC: + bne SAVE2DISK ; go copy it now +; +; WRITE CONTENTS OF Z-STACK TO DISK +; +ZSALL: + lda #HIGH ZSTKBL ; point to 1st page + sta DBUFF+HI + jsr PUTDSK ; write them, first one + bcs ZSBAD + jsr PUTDSK ; write them, second one + bcs ZSBAD +; +; WRITE ENTIRE GAME PRELOAD TO DISK +; + lda #HIGH ZBEGIN ; POINT TO 1ST PAGE + sta DBUFF+HI ; OF PRELOAD + ldx ZBEGIN+ZPURBT ; GET # IMPURE PAGES +SAVE2DISK: + inx ; use for counting + stx I+LO + lsr I+LO ; /2 for 512byte pages + bcc ZSL2 ; no wrapping + inc I+LO ; wrapped once +ZSL2: + jsr PUTDSK ; this does the write + bcs ZSBAD + dec I+LO ; count one page + bne ZSL2 ; not done yet + + jsr CLOSE_SAVE ; PROMPT FOR GAME FILE + lda #1 ; SET TO MARK + ldx #0 + jmp PUTBYT ; SUCCESS + +; ------------ +; RESTORE GAME +; ------------ + +ZREST: + lda #'N' + ldx NARGS + beq OLDRES ; NORMAL, COMPLETE RESTORE + lda #'P' ; partial restore +OLDRES: + sta TYPE ; save which kind of restore + + jsr GET_SNAME ; get the name of the file + bcs ZRBAD ; okay, don't do it + jsr OPEN_RES ; open the restore file + bcs ZRBAD ; can't do it + + lda TYPE ; PARTIAL SAVE DIFFERS STARTING HERE + cmp #'P' + bne ZRNRML + jmp ZPARTR ; just a partial restore + + ; SAVE LOCALS IN CASE OF ERROR + +ZRNRML: + ldx #31 +LOCSAV: lda LOCALS,X ; COPY ALL LOCALS + sta LOCAL_SV,X ; to a save spot + dex + bpl LOCSAV + + lda #MAIN + sta DSKBNK ; SET TO WRITE TO MAIN BANK + lda #HIGH LOCALS + sta DBUFF+HI + lda #2 ; must read in two pages + sta L+LO + jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + bcs ZRBAD + + lda BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID + cmp ZBEGIN+ZID ; MATCH THE CURRENT ID? + bne ZRQUIT ; WRONG DISK IF NOT + + lda BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE? + cmp ZBEGIN+ZID+1 + beq ZROK ; CONTINUE IF BOTH BYTES MATCH + bne ZRQUIT ; skip disk error message +; +; HANDLE RESTORE ERROR +; +ZRBAD: + jsr DISK_ERR ; print error message +ZRQUIT: + ldx #31 ; RESTORE ALL SAVED LOCALS +ZRL2: lda LOCAL_SV,X + sta LOCALS,X + dex + bpl ZRL2 +BADRES: + jsr CLOSE_SAVE ; PROMPT FOR GAME DISK + jmp RET0 ; PREDICATE FAILS +; +; CONTINUE RESTORE +; +ZROK: + lda ZBEGIN+ZFLAGS ; SAVE BOTH FLAG BYTES + sta I+LO + lda ZBEGIN+ZFLAGS+1 + sta I+HI + + lda #HIGH ZSTKBL ; RETRIEVE OLD CONTENTS OF + sta DBUFF+HI ; z-stack + lda #4 ; do 4 pages + sta L+LO ; tell GETRES how many pages + jsr GETRES ; get 4 pages of z-stack + bcc ZROKL1 + jmp DISK_FATAL ; if here, mix of good & bad so die +ZROKL1: + lda #HIGH ZBEGIN ; get where we are + sta DBUFF+HI + lda ZBEGIN+ZPURBT ; GET # PAGES TO LOAD + sta I+LO +LREST0: + lda I+LO ; how many pages left + sec ; doing subtract + sbc #4 ; doing it 4 blocks at a time + beq LRESTj ; all done + bcc LREST1 ; LOW 4 blocks left so deal with it special + sta I+LO ; save remenants +LREST: + lda #4 ; assume at least 4 pages + sta L+LO ; this tells GETRES how many to read in + jsr GETRES ; fetch the remainder + bcc LREST0 + jmp DISK_FATAL +LREST1: + lda I+LO ; get how many left + sta L+LO ; and show it to GETRES + jsr GETRES ; and finish it up +; +; RESTORE THE STATE OF THE SAVED GAME +; +LRESTj: + lda I+LO ; RESTORE THE STATE + sta ZBEGIN+ZFLAGS ; OF THE FLAG WORD + lda I+HI + sta ZBEGIN+ZFLAGS+1 + + lda BUFSAV+2 ; RESTORE THE [ZSP] + sta ZSP+LO + lda BUFSAV+3 + sta ZSP+HI + lda BUFSAV+4 + sta OLDZSP+LO + lda BUFSAV+5 ; AND THE [OLDZSP] + sta OLDZSP+HI + + ldx #2 ; RESTORE THE [ZPC] +ZRL4: lda BUFSAV+6,X + sta ZPC,X + dex + bpl ZRL4 + +ZROUT: jsr CLOSE_SAVE ; PROMPT FOR GAME DISK + jsr VLDZPC ; MAKE VALID (MUST DO AFTER GET DISK) + + lda #2 ; SET TO + ldx #0 + jmp PUTBYT ; SUCCESS + + + ; DO PARTIAL RESTORE GETTING 1ST PAGE + ; AND LAST PAGE BYTE ALIGNMENT CORRECT + +ZPARTR: ; WRITE LOCALS TO IOBUFF JUST TO LOOK AT NAME + + lda #MAIN + sta DSKBNK + lda #HIGH IOBUFF ; DON'T READ TO LOCALS YET (X) + sta DBUFF+HI + lda #1 ; just one block please + sta L+LO + jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + bcs ZPBAD ; BAD DISK READ IF CARRY CLEAR + + lda ARG3+LO ; set up FPC to get save name + sta FPCL ; lo part is okay + lda ARG3+HI ; get page + jsr SETPC ; get memory addr + sta FPCH ; page number + sty FPCBNK ; and bank + jsr FETCHB ; get count + sta I ; and save it + jsr NEXTFPC ; point to next byte + lda #LOW BUFSAV ; get bufsav offset + clc ; and add + adc #10 ; name offset + sta J ; did it +ZRN3: + jsr FETCHB ; get data byte + ldy J ; get offset + cmp IOBUFF,Y ; save into buffer + bne ZPBAD ; okay, then it's not it + jsr NEXTFPC ; point to next byte + inc J ; next byte + dec I ; count it + bne ZRN3 ; loop again + + lda ARG1+HI ; FIND WHERE TO START & HOW FAR TO GO + jsr SETPC ; get page in memory + sta SPCH ; this is page + sty SPCBNK ; which bank + lda ARG1+LO ; START BYTE FIRST PAGE + sta SPCL + + ldx ARG2+HI + stx J+HI + ldx ARG2+LO + stx J+LO + + jsr DECJ ; CORRECT ALIGNMENT FOR THIS USAGE +POK: + lda #HIGH IOBUFF ; GET 1ST PAGE + sta DBUFF+HI ; GETRES SHOULD KEEP IN IOBUFF + lda #1 ; just do one block + sta L+LO + jsr GETRES + bcc ZPART0 + jmp DISK_FATAL ; ALL MESSED UP, JUST QUIT +ZPART0: + ldy ARG1+LO ; START BYTE FIRST PAGE + lda IOBUFF,Y + jsr STASHB + jsr NEXTSPC + jsr DECJ + bcs ZPART1 ; CARRY CLEAR IF $FFFF RESULT + jmp ZROUT +ZPART1: + inc ARG1+LO + bne ZPART0 + beq POK ; read in a new block + +ZPBAD: JMP BADRES ; NAMES DON'T MATCH, DIE +; +; THE OLD SAVE & RESTORE STILL HAVE OPCODES +; SO JUST PUT IN A PLACE FOR THEM HERE FOR NOW +; +OSAVE: +OREST: RTS + +ZISAVE: +ZIREST: JMP RET0 ; NOT IMPLEMENTED ON APPLE + END + diff --git a/apple/yzip/ice/zstring.asm b/apple/yzip/ice/zstring.asm new file mode 100644 index 0000000..aaa27a8 --- /dev/null +++ b/apple/yzip/ice/zstring.asm @@ -0,0 +1,457 @@ + TITLE "Apple ][ YZIP (c)Infocom","Z-STRING HANDLERS" + +; ----------------------- +; POINT MPC TO ZSTRING IN [I], using SOFF +; ----------------------- + +SETSTR: + lda I+LO + sta MPCL ; save in lo part + lda I+HI + sta MPCM ; middle part + lda #0 ; clear hi part + sta MPCH ; okay, we did + asl MPCL ; *2 + rol MPCM + rol MPCH + asl MPCL ; *4 + rol MPCM + rol MPCH +; +; now add the offset +; + lda MPCL ; carry clear from above + adc SOFFL ; add lo part of offset + sta MPCL ; save + lda MPCM + adc SOFFM + sta MPCM + lda MPCH + adc SOFFH + sta MPCH + jmp VLDMPC ; make MPCPNT to it + + +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 +; +; set up FPC to point to FWORDS table +; + ldx FWORDS+ABANK + stx FPCBNK + ldx FWORDS+HI + stx FPCH + ldx FWORDS+LO + stx FPCL + jsr ADDFPC ; add offset of the F-word + jsr FETCHB ; and get MSB of F-word + sta I+HI ; and save it + jsr NEXTFPC ; and point to LSB + jsr FETCHB ; and get it + sta I+LO ; and save it +; +; 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 SETFWD ; 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 + JSR VLDMPC + JMP PZTOP ; CONTINUE INNOCENTLY + + +; ---------------------- +; RETURN CURRENT CHARSET +; ---------------------- + +GETSET: LDA TSET + BPL GS + LDA PSET + RTS +GS: LDY #$FF + STY TSET + RTS + + +; ------------------------- +; POINT [I] AT FWORD STRING +; ------------------------- + +SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS + ASL A + STA MPCL + LDA I+HI + ROL A + STA MPCM + LDA #0 + ROL A + STA MPCH + JMP VLDMPC + + +; ----------------- +; 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 #5 ; FILL OUTPUT BUFFER + LDX #8 ; WITH PAD CHARS ($05) +CZSL: STA OUT,X + DEX + BPL CZSL + + LDA #9 ; 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 9 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 + STA OUT+2 ; MOVE CRUSHED Z-WORD + STX OUT+3 ; INTO PLACE + LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) + ASL A ; SHIFT BITS + ASL A + ASL A + ASL A + ROL OUT+6 ; ALONG WITH 7TH Z-CHAR + ASL A + ROL OUT+6 + ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR + STA OUT+5 ; SAVE HERE + LDA OUT+6 ; GRAB 7TH Z-CHAR + ORA #%10000000 ; SET HIGH BIT + STA OUT+4 ; MOVE CRUSHED Z-WORD 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 + diff --git a/apple/yzip/rel.13/apple.equ b/apple/yzip/rel.13/apple.equ new file mode 100644 index 0000000..fb84363 --- /dev/null +++ b/apple/yzip/rel.13/apple.equ @@ -0,0 +1,298 @@ + STTL "--- APPLE ][ HARDWARE STUFF ---" + PAGE +; ------------------- +; APPLE II MEMORY MAP +; ------------------- +AUX EQU 1 ; offset to Auxillary mem switches +MAIN EQU 0 ; for main memory switches + +; +; some hardware spots +; +SCREEN EQU $2000 ; START OF Double HiRes SCREEN RAM + +PRGLBL EQU $BF00 ; ProDOS Globals page in main mem +PR_BITMAP EQU $BF58 ; ProDOS system bitmap +KVERSION EQU $BFFF ; ProDOS version (== $FF if InfoDOS) +INFODOS_ID EQU $FF + +IOADDR EQU $C000 ; start of I/O registers +PROADR EQU $D000 ; start of ProDOS + +LBUFF EQU $0200 ; LINE INPUT BUFFER +PIC1BUF EQU $0300-141 ; we can use line buffer for one picture buffer +SCRBUFF EQU LBUFF+$80 ; screen line buffer +BORG EQU $2000 ; ORIGIN OF .SYSTEM CODE +; +; some page 3 storage relocated stuff +; +PAGE3STUFF EQU $300 +MOUSER EQU PAGE3STUFF ; this is where mouse subroutine goes +COLORS EQU MOUSER+$12 +XPOSTBL EQU COLORS+$40 + +SV_PCL EQU $400 ; for scrolling data +SV_PCH EQU $600 + +IOBUFF EQU $0800 ; 1Kb DATA BUFFER BUFFER + +PAGING_MEM EQU IOBUFF+$400 ; Paging table stuff +NEXTPNT EQU PAGING_MEM +PREVPNT EQU NEXTPNT+$40 +VPAGEH EQU PREVPNT+$40 +VPAGEL EQU VPAGEH+$40 +PAGELEN EQU $200 ; length of paged read + +ZSTKBL EQU PAGING_MEM+$100 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) +ZSTKTL EQU ZSTKBL+$100 ; TOP, LO +ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI +ZSTKTH EQU ZSTKBL+$300 ; TOP, HI +; +; now define some file i/o buffers and such +; +GAME1FIO EQU ZSTKBL+$400 ; Game file I/O buffer +GAME2FIO EQU GAME1FIO+$400 ; Second game file i/o buffer +SEGTBL EQU GAME2FIO+$400 ; segment table for multi disks +PIC2BUF EQU SEGTBL+($400-140) ; picture buffer is 140 bytes long +TCHARTBL EQU SEGTBL+$400 ; 208 bytes for (possible) terminating +COPY_LINE EQU TCHARTBL+$50 ; copy line in screen memory +CPY_MOD1_SRC equ COPY_LINE+$2C ; special self-modifying places +CPY_MOD1_DST equ CPY_MOD1_SRC+3 +CPY_MOD2_SRC equ COPY_LINE+$50 +CPY_MOD2_DST equ CPY_MOD2_SRC+3 + +DSKSEG EQU TCHARTBL+$D0 ; spot to stash pointers for disk segments +D1SEG EQU DSKSEG ; where in SEGTBL for Disk 1 +D2SEG EQU D1SEG+2 +D3SEG EQU D2SEG+2 +D4SEG EQU D3SEG+2 +D5SEG EQU D4SEG+2 +D6SEG EQU D5SEG+2 +D7SEG EQU D6SEG+2 +D8SEG EQU D7SEG+2 +LOCAL_SV EQU TCHARTBL+$E0 ; to save locals before restore +LOCALS EQU TCHARTBL+$100 ; LOCAL VARIABLE STORAGE (30 BYTES) +BUFSAV EQU LOCALS+$20 ; TEMP SPACE FOR SAVE/RESTORE (80 BYTES) +SCR_LINE EQU LOCALS+$100 ; place to build displayed line +CHARSET EQU SCR_LINE+140 ; spot for charset to go +; +; now for some interpreter data +; +INTR_BEGIN EQU $4000 ; START OF Interpreter CODE in main +INTR_SIZE EQU (43*512) ; size of interpreter + +ZBEGIN EQU (INTR_BEGIN+INTR_SIZE) ; start of Z code +MMSIZE EQU PRGLBL-INTR_BEGIN ; free memory in main bank +Z1SIZE EQU >(PRGLBL-ZBEGIN) ; size of preload, part 1 +; +; this is in Bank 2, Main mem +; +; +; Picture directory goes in Bank 2, Aux mem +; +PIC_DIR EQU $D000 ; picture local directory +GBL_DIR EQU $DC00 ; global directory +; +; some special markers if we are using InfoDOS +; +SP_BANK EQU MAIN +SP_START EQU $D000 ; start of special area +SP_SIZE EQU ((($FE->SP_START)*256)/512) ; how many pages +;SP_SIZE EQU (((>SCREEN->SP_START)*256)/512) ; how many pages + +PB_BANK EQU AUX ; paging buffers in which bank +PBEGIN EQU $0800 ; start of paging buffers +NUMBUFS EQU >(SCREEN-PBEGIN) ; how many 256k paging buffers +;NUMBUFS EQU >($100-PBEGIN) ; how many 256k paging buffers + +P2PAGE EQU >(PRGLBL-ZBEGIN) ; first page of zcode in aux bank +Z2BEGIN EQU $4000 ; start of part 2 in aux mem + ; just after the dhires screen +Z2PAGE EQU >Z2BEGIN ; get me just the page address +Z2SIZE EQU >(PRGLBL-Z2BEGIN) ; size of preload, part 2 +P3PAGE EQU Z1SIZE+Z2SIZE ; first page in aux mem part 3 +Z3BEGIN EQU $D000 ; start of 3 part in aux mem +Z3PAGE EQU >Z3BEGIN ; get me page number too +Z3SIZE EQU <($FE-Z3PAGE) ; size of part 3, in pages + +; +; other numba's +; +PGBEGIN EQU (P3PAGE+Z3SIZE) ; first paged page +PRESIZE EQU (Z1SIZE+Z2SIZE+Z3SIZE) ; size of preload, # pages +SCRSZE EQU INTR_BEGIN-SCREEN ; size of Double HiRes screen (8k, each bank) +RAMDSK EQU (119*512) ; size of RAM disk in aux mem +RAMSAVE EQU $B500 ; save this much to cover HiRes screen in + ; aux and the rest of the preload, up to + ; PRGLBL ($bf00) +FREERAM EQU RAMDSK-RAMSAVE ; size of Free RAM after 'saving' + ; special AUX memory +DSKSZE EQU (512*273) ; size of ProDOS data disk file + +; --------- +; CONSTANTS +; --------- + +IIeID EQU 2 ; Apple ][e Yzip +IIcID EQU 9 ; ][c Yzip +IIgsID EQU 10 ; ][gs Yzip + +P3BANK EQU $FF ; show upper aux mem +LO EQU 0 +HI EQU 1 +ABANK EQU 2 ; for address variables + +OFF EQU 0 ; for toggling soft-switches +ON EQU 1 + +RETRY_COUNT EQU 3 ; how many retries before message + +TAB EQU $09 ; Tab char +EOS EQU $0B ; End of Sentence +EOL EQU $0D ; EOL CHAR +LF EQU $0A ; LINE FEED +SPACE EQU $20 ; SPACE CHAR +BACKSPACE EQU $08 ; BACKSPACE CHAR +ESCAPE EQU $1B ; ESCAPE Key +VOLCHAR EQU '?' ; Key to hit for ONLINE command +; +; Screen Defs +; +MAXWIDTH EQU 140 ; 560 / 4 = max "pixels" +REAL_MAXW EQU MAXWIDTH*4 +MAXHEIGHT EQU 192 ; 192 screen lines +FONT_W EQU 2 ; font width (for game, anyway) +FONT_H EQU 9 ; font height +MFONT_W EQU 3 ; mono spaced font width, to game +MONOFONT_W EQU MFONT_W*4 ; how wide the mono font really is + +SPACE_WIDTH EQU 8 ; default space width +BLINK_RATE EQU 3 ; tenths of seconds between blinks + +OUTER_DELAY EQU $1C ; outside delay loop counter +INNER_DELAY EQU 3 ; inner delay loop + +GS_OUTER_DELAY EQU $72 ; ][gs outside counter +GS_INNER_DELAY EQU 2 ; ][gs inside counter + +; ---------------------- +; BOOT ZERO PAGE EQUATES +; ---------------------- + +BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS +BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT + +START_NAME EQU $280 ; name upon boot is stored here +; ---------------- +; HARDWARE EQUATES +; ---------------- + +KBD EQU $C000 ; KEY STROBE +STORE80 EQU $C000 ; video aux mem switch +RDBNK EQU $C002 ; READ MAIN MEMORY (+MAIN, +AUX) +WRTBNK EQU $C004 ; WRITE MAIN 48K OF MEMORY (+MAIN, +AUX) +ALTZP EQU $C008 ; R/W MAIN (C009 = AUX) >MEM +COL80SW EQU $C00C ; 80 Column switch +ANYKEY EQU $C010 ; ANY KEY DOWN FLAG +VERTBLNK EQU $C019 ; Vertical Blanking Flag +IIGSVID EQU $C029 ; GS MEGA ][ video register +SPKR EQU $C030 ; SPEAKER FLAG (MAKE A NOISE) +IIGSSHD EQU $C035 ; ][GS shadowing reg +TEXTSW EQU $C050 ; Graphics Switch +MIXEDSW EQU $C052 ; Mixed Text/Graphics +PAGE2SW EQU $C054 ; Page select +HIRESSW EQU $C056 ; Select HiRes +DHIRESW EQU $C05E ; Double HiRes switch (backwards: +0 on +1 off) +IOUDIS EQU $C07E ; Double HiRes Switch enabler (same backass way) +BNK2SET EQU $C083 ;READ/READ READ RAM WRITE RAM BANK 2 +BNK1SET EQU $C08B ;READ/READ READ RAM WRITE RAM BANK 1 +RDROM EQU $C082 ; READ READ ROM NO WRITE +RDBNK1 EQU $C088 ; READ ram, bank 1 +RDBNK2 EQU $C080 ; Read ram, bank 2 + +; ----------------- +; MONITOR VARIABLES +; ----------------- + +CSW EQU $36 ; CHARACTER OUTPUT VECTOR (for scripting) +APKEY1 EQU $C061 ; open apple key flag +APKEY2 EQU $C062 ; closed apple key flag + +CURSW EQU 2 ; width of cursor +CURSH EQU 4 ; height of cursor +; ----------- +; MOUSE STUFF +; ----------- +MTABLE EQU $C412 ; Mouse ROM table +MSVECTOR EQU MOUSER+16 ; where vector is stored +MSMOVEF EQU MSVECTOR+2 ; Mouse moved flag +MSBTNF EQU MSMOVEF+1 ; Mouse button flag +; +; MOUSE screen holes +; +CLMPMINL EQU $478 ; lo part of clamping min +CLMPMINH EQU $578 ; hi part of " " +CLMPMAXL EQU $4F8 ; lo part of clamping max +CLMPMAXH EQU $5F8 ; hi part of " " +MOUSEXL EQU $478 ; lo part of mouse X +MOUSEXH EQU $578 ; hi part of mouse X +MOUSEYL EQU $4F8 ; lo part of mouse Y +MOUSEYH EQU $5F8 ; hi part of mouse Y +MOUSEST EQU $778 ; status byte +; +; some mouse constants +; +SGL_CLK EQU $81 ; single click char +DBL_CLK EQU $82 ; double click char +CLK_CNT EQU 6 ; counts between single and double click +; Subroutine offsets +SETM EQU 0 +SERVEM EQU 1 +READM EQU 2 +CLEARM EQU 3 +POSM EQU 4 +CLAMPM EQU 5 +HOMEM EQU 6 +INITM EQU 7 + +; -------------- +; PRODOS GLOBALS +; -------------- +PRODATE EQU $BF90 ; date and +PROTIME EQU $BF92 ; time +MACHID EQU $BF98 ; machine id + +; ---------------- +; MONITOR ROUTINES +; ---------------- +MPREAD EQU $FB1E ; Read for joystick control +MBASCAL EQU $FC22 ; CALC LINE BASE ADDRESS +MBELL EQU $FF3A ; MAKE A NOISE +RESET_VECTOR EQU $FFFC ; force warm reboot +MCLEOL EQU $FC9C ; CLEAR TO END OF LINE +MCLEOS EQU $FC42 ; CLEAR TO END OF SCREEN +MHOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR +MCOUT EQU $FDED ; CHAR OUTPUT +MCOUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN +MRDKEY EQU $FD0C ; READ KEY +MGETLN1 EQU $FD6F ; GET LINE +MWAIT EQU $FCA8 ; WASTE SO MUCH TIME +; +; Some /RAM spots +; +RAMVEC EQU $BF26 ; /RAM drive vector +OLDVEC EQU $77E ; spot to save the drive vector +UNSVEC EQU $BF16 ; "Uninstalled Device" vector +DEVCNT EQU $BF31 ; Device count +DEVNUM EQU $BF32 ; Device list + +; +; machine info spots +; +MACHID1 EQU $FBB3 ; first part +MACHID2 EQU $FBC0 ; second part +MACHCHK EQU $FE1F ; differentiate between ][e and gs + ; do sec, then jsr, and if still set, = ][e + END + + diff --git a/apple/yzip/rel.13/boot.asm b/apple/yzip/rel.13/boot.asm new file mode 100644 index 0000000..f105000 --- /dev/null +++ b/apple/yzip/rel.13/boot.asm @@ -0,0 +1,380 @@ + TITLE "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + + INCLUDE ZIP.EQU + INCLUDE ZERO.EQU + INCLUDE PRODOS.EQU + INCLUDE APPLE.EQU + INCLUDE MACROS.ASM + + STTL "--- APPLE ProDOS BOOT CODE ---" + PAGE + +CHZ EQU $24 ; CURSOR HORIZONTAL +EHZ EQU $57B ; CURSOR HORIZONTAL +CVT EQU $25 ; CURSOR VERTICAL + +; +; my own little error checking macro +; +ERRVAL .VAR 0 +; +; this macros checks for carry being set (ProDOS error) and if it is +; loads an error code in x and jumps to the error handler +ERRCHK .MACRO +ERRVAL .VAR ERRVAL+1 + bcc BOOT| + ldy #ERRVAL + jmp BOOT_ERROR +BOOT|: + .MACEND + + ORG BORG + jmp BOOT_BEGIN ; just jump to beginning +PROGNAME: + BLKB 9,0 ; 8 bytes for name + 1 for ending zero +BOOT_BEGIN: + lda RDROM ; swap in rom + sta TEXTSW+ON ; turn on text + sta COL80SW+OFF ; turn on 80 column + +; +; make sure we are on a ][c, or ][e+ +; + jsr MACHINE ; check it out, returns if good + lda ARG2+LO ; check machine + cmp #IIgsID ; 2gs? + bne ZBOOTGS ; nope + lda IIGSVID ; get current video setting + and #$1F ; turn off upper 3 bits + sta IIGSVID ; make sure double hires works + lda IIGSSHD ; get shadowing reg + and #$A0 ; turn on shadowing everywhere + sta IIGSSHD ; okay +ZBOOTGS: + jsr FIXRAM ; check and clear RAM disk + jsr DO_PREFIX ; go set my current prefix + + jsr MHOME ; clear and home + lda #9 ; CENTER DISPLAY + sta CVT + lda #8 + sta CHZ + sta EHZ + jsr MBASCAL ; move cursor there! + DLINE STRYM +; +; move down to lower left and print out version number +; + lda #21 + sta CVT + lda #1 + sta CHZ ; move to 1,20 + sta EHZ + jsr MBASCAL ; move cursor there! + DLINE VERMSG ; show me the version + lda #VERSID/10 ; get version + ora #$B0 ; make normal char for ][ + jsr MCOUT + lda #VERSID.MOD.10 + ora #$B0 ; make normal char for ][ + jsr MCOUT + + lda #$FF ; init invflg to normal + sta INVFLG ; okay + + lda #0 ; zero out bit map + ldx #$17 ; 17 bytes in ProDOS system bitmap +CLRPRD: + sta PR_BITMAP,X ; and zero out the memory + dex + bpl CLRPRD ; and zero entire bitmap + + lda #$C0 ; start out the bitmap with c0 at start + sta PR_BITMAP + lda #$01 ; and a 1 at the end + sta PR_BITMAP+$17 ; thankx +; +; now we need to load in the interpreter +; + OPEN INTR_OPEN ; open up interpreter file + ERRCHK + + lda INTR_OPEN+OP_REFNUM ; get refnum for intr file + sta READ_BLOCK+RD_REFNUM ; and save for read + sta CLOSE_BLOCK+CL_REFNUM ; close up interpreter file + + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now +RDINTR: + READ READ_BLOCK ; read in interpreter + bcc RDINTR1 ; it worked fine + dec RETRIES ; try again + bpl RDINTR ; fine + ERRCHK ; then just die +RDINTR1: + CLOSE CLOSE_BLOCK ; done with interpreter +; +; now read in first part of preload +; + ldx #0 ; start at first letter +MVPRE: + lda PROGNAME,X ; get letter + beq MVPREX ; all done + sta PRE_NAME,X ; save letter + inx ; next letter + bne MVPRE ; do gen +MVPREX: +; +; now add on ".d1" suffix for the preload +; + lda #'.' ; get '.' + sta PRE_NAME,X ; save it + inx ; next char + lda #'D' ; 'D' char + sta PRE_NAME,X ; save it + inx ; next char + lda #'1' ; preload is .1 + sta PRE_NAME,X ; saved + inx ; count the .1 + stx PRELOAD_NAME ; save length of name + + OPEN PRELOAD_OPEN ; so now open preload file + ERRCHK + + lda PRELOAD_OPEN+OP_REFNUM ; get refnum + sta READ_BLOCK+RD_REFNUM ; save refnum for read + sta PSEEK+SM_REFNUM ; and for moving around +; +; first, get the segment table +; + lda #>IOBUFF ; just read in size + sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + lda #4 ; read in first 1 Kb + sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + lda #0 ; get size in words + sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + + READ READ_BLOCK ; and read first block + ERRCHK +; +; now copy segtable to low mem +; + lda #>IOBUFF + sta J+HI + lda #(SEGTBL-2) + sta K+HI + lda #<(SEGTBL-2) + sta K+LO + + lda IOBUFF+1 ; get LSB + asl A ; *2, to pick up the carry + lda IOBUFF ; get how many words + rol A ; *2 for number of bytes + sta PSEEK+SM_FPOS+HI ; set page number + tax ; make it a counter + ldy #2 ; start at second byte, after length +CPSEGT: + lda (J),y ; get byte + sta (K),y ; save byte + iny ; next byte + bne CPSEGT ; go do it + inc J+HI + inc K+HI + ldy #0 ; restart at beginning of block + dex ; count page + bpl CPSEGT ; next page +; +; now, seek to page following seg table +; + inc PSEEK+SM_FPOS+HI ; next page + lda PSEEK+SM_FPOS+HI ; make sure it is an even 512 page + and #$01 ; is it odd? + beq BTSK0 ; nope, so we be okay + inc PSEEK+SM_FPOS+HI ; next page + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now +BTSK0: + SET_MARK PSEEK ; and point to beginning of game data + + lda #>ZBEGIN ; begining of game code + sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + lda #(Z1SIZE&$FE) ; get size + sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + lda #0 ; get size in words + sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + READ READ_BLOCK ; and read in part 1 of preload + bcc BTSK00 ; just fine + dec RETRIES ; try again + bpl BTSK0 ; fine + ERRCHK ; then just die +BTSK00: + lda #4 ; 4 pages per read + sta READ_BLOCK+RD_BUFFLEN+HI ; and lots + lda #>IOBUFF ; read into my io buffer + sta READ_BLOCK+RD_BUFFER+HI ; hi part of address + + IF Z1SIZE & 1 ; if odd, do something special + READ READ_BLOCK + ldy #0 ; copy second page +C2LOOP: + lda IOBUFF,Y + sta ZBEGIN+(Z1SIZE*$100)-$100,Y + iny + bne C2LOOP + lda #(>Z2BEGIN-1) ; don't need first block + sta MODOP+2 + bne RD10 ; skip that first read + ENDIF +AUXRDL: + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now +AUXRDL0: + READ READ_BLOCK ; and do the read + bcc RD10 + cmp #$4C ; this just means EOF already + beq BT12 ; otherwise, blech + dec RETRIES ; try again + bpl AUXRDL0 ; fine + ERRCHK ; then just die +RD10: + lda #>IOBUFF ; read into my io buffer + sta CLOOP+2 ; start at IOBUFF + lda #4 ; 4 copies + sta L ; okay +RD11: + ldy #0 ; start at zero, of course + lda MODOP+2 ; check where we are reading too + beq BT12 ; wrapped, so we had better be done + cmp #>PRGLBL ; done with aux mem, part 1? + bcc LOOPST ; nope + bne RD12 ; no need to change + lda #Z3PAGE ; restart at top of memory + sta MODOP+2 ; and do some self modifying code +RD12: + sta ALTZP+AUX ; turn on alt ZP + lda BNK2SET ; write to upper mem + lda BNK2SET ; write to upper mem +LOOPST: + sta WRTBNK+AUX ; always aux mem +CLOOP: + lda IOBUFF,Y ; get char +MODOP: sta Z2BEGIN,Y ; save + iny ; point to next one + bne CLOOP ; get next one + + lda RDROM ; swap back rom, just in case + lda RDROM ; swap back rom, just in case + sta ALTZP+MAIN ; and back to main page + sta WRTBNK+MAIN ; read into main bank + + inc MODOP+2 ; point to next page + inc CLOOP+2 ; point to next page + dec L ; next page + bne RD11 ; and get it + + jmp AUXRDL ; get next 1k +BT12: + lda READ_BLOCK+RD_REFNUM ; get refnum for + sta CLOSE_BLOCK+CL_REFNUM ; closing the file + CLOSE CLOSE_BLOCK ; okay, closed +; +; relocate the Zero Page routines +; + ldx #RLCLEN ; length of routine +RLOC: + lda FETCHBx,X ; get byte + sta ZERO_FB,X ; save byte + dex ; get next one + bpl RLOC ; thank you +; +; and now for the copying screen line sub +; + ldx #CPYLEN +CPYCPLP: + lda CPYx,X + sta COPY_LINE,X + dex + bpl CPYCPLP +; +; now relocate page 3 stuff +; + ldx #PAGE3RELL+1 ; get length of page 3 stuff +MSRCL: + lda PAGE3REL-1,X ; get byte + sta PAGE3STUFF-1,X ; save byte + dex ; count byte + bne MSRCL ; get next? + + jsr ZBOOT ; set up ZIP stuff + + JMP INTR_BEGIN ; jump to the interpreter + + INCLUDE ZBOOT.ASM ; ZBOOT subroutine + INCLUDE BREL.ASM ; relocated subroutines + INCLUDE BSUBS.ASM ; subs for e to use + + PAGE + STTL "--- BOOT DATA STRUCTURES ---" +INTR_OPEN: + DB 3 ; 3 parameters + DW INTR_NAME ; name of file + DW GAME1FIO ; file data buffer + DS 1 ; refnum goes here +CLOSE_BLOCK: + DB 1 ; 1 parameter + DS 2 ; room for ref num +PSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +PRELOAD_OPEN: + DB 3 + DW PRELOAD_NAME + DW GAME1FIO ; close interpreter first! + DS 1 ; refnum here +; +; start with interpreter data +; +READ_BLOCK: + DB 4 ; 4 parms + DB 0 ; refnum + DW INTR_BEGIN ; where to start the interpreter + DW INTR_SIZE ; and how big could it be + DW 0 ; actual length of interpreter +INTR_NAME: + DB INAME_LEN ; length of name +I_NAME: + DB "INFOCOM" ; interpreter name +INAME_LEN EQU $-I_NAME + +PRELOAD_NAME: + DB 0 ; length of name +PRE_NAME: + DS 20 ; spot for preload name +PRELEN EQU $-PRE_NAME + +DH_SAVE: ; to actual 'write' the data + DB 4 ; 4 parms for write + DB 0 ; refnum goes here + DW 0 ; just 'copy' junk + DW RAMSAVE ; to preserve this much mem in AUX + DW 0 ; how much is done + +STRYM: DB "The story is loading ..." +STRYML EQU $-STRYM +MMSG: DB EOL,"Enter the letter of the pointing",EOL + DB "device you will be using:",EOL + DB "J)oystick M)ouse N)either",EOL,EOL +MMSGL EQU $-MMSG +MSLT: DB EOL,"Enter the slot number in which the",EOL + db "mouse card is installed >" +MSLTL EQU $-MSLT +MSLTBAD: DB EOL,"Slot number must be between",EOL + db "ONE and SEVEN! Try again!",EOL +MSLTBADL EQU $-MSLTBAD +VERMSG: db EOL,"Version: " +VERMSGL equ $-VERMSG + END + diff --git a/apple/yzip/rel.13/boot.bin b/apple/yzip/rel.13/boot.bin new file mode 100644 index 0000000..ccd3c4e Binary files /dev/null and b/apple/yzip/rel.13/boot.bin differ diff --git a/apple/yzip/rel.13/boot.lst b/apple/yzip/rel.13/boot.lst new file mode 100644 index 0000000..b2b2e78 --- /dev/null +++ b/apple/yzip/rel.13/boot.lst @@ -0,0 +1,2730 @@ + Wed Jun 7 1989 12:04 Page 1 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT DATA STRUCTURES ---" + + + + + 2500 A.D. 6502 Macro Assembler - Version 4.01a + ------------------------------------------------ + + Input Filename : BOOT.asm + Output Filename : BOOT.obj + + + 1 0000 TITLE "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + 2 + 3 0000 INCLUDE ZIP.EQU + 4 0000 STTL "--- YZIP EQUATES ---" + 5 PAGE + Wed Jun 7 1989 12:04 Page 2 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- YZIP EQUATES ---" + + 6 + 7 000D VERSID EQU 13 ; VERSION OF INTERPRETER + 8 ; See file "versions" for complete descriptions + 9 + 10 00FF TRUE EQU $FF + 11 0000 FALSE EQU 0 + 12 + 13 ; --------------------- + 14 ; Segment table equates + 15 ; --------------------- + 16 0000 SGTDISKS EQU 0 ; number of disks + 17 0002 SGTPAD EQU SGTDISKS+2 ; just some extra room + 18 0012 SGTCHKS1 EQU SGTPAD+16 ; Checksum for disk 1 (PRELOAD) + 19 0014 SGTPICOF1 EQU SGTCHKS1+2 ; N/A + 20 0016 SGTSEG1 EQU SGTPICOF1+2 ; # of segments + 21 0018 SGTGPOF1 EQU SGTSEG1+2 ; Global Picture Directory + 22 001A SGTTBLS EQU SGTGPOF1+2 ; Start of table preload (should be 0) + 23 001C SGTTBLE EQU SGTTBLS+2 ; Last page of table preload + 24 001E SGTTBLX EQU SGTTBLE+2 ; N/A + 25 0020 SGTFUNS EQU SGTTBLX+2 ; First page of function preload + 26 0022 SGTFUNE EQU SGTFUNS+2 ; End page of function preload + 27 0024 SGTFUNX EQU SGTFUNE+2 ; N/A + 28 0026 SGTDSK EQU SGTFUNX+2 ; Actual start of disk segment tables + 29 + 30 0000 SGTCHKS EQU 0 ; check sum for file + 31 0002 SGTPICOF EQU 2 ; picture data offset + 32 0004 SGTNSEG EQU 4 ; # of segments in this list + 33 0006 SGTGPOF EQU 6 ; Global Directory Offset + 34 0008 SGTSEG EQU 8 ; start of segments + 35 ; --------------------- + 36 ; Z-CODE HEADER OFFSETS + 37 ; --------------------- + 38 + 39 0000 ZVERS EQU 0 ; VERSION BYTE + 40 0001 ZMODE EQU 1 ; MODE SELECT BYTE + 41 0002 ZID EQU 2 ; GAME ID WORD + 42 0004 ZENDLD EQU 4 ; # OF QUADWORDS ON SIDE 1 OF DISK + 43 0006 ZGO EQU 6 ; EXECUTION ADDRESS + 44 0008 ZVOCAB EQU 8 ; START OF VOCABULARY TABLE + 45 000A ZOBJEC EQU 10 ; START OF OBJECT TABLE + 46 000C ZGLOBAL EQU 12 ; START OF GLOBAL VARIABLE TABLE + 47 000E ZPURBT EQU 14 ; START OF "PURE" Z-CODE + 48 0010 ZFLAGS EQU 16 ; FLAG WORD + 49 0012 ZSERIA EQU 18 ; 3-WORD SERIAL NUMBER + 50 0018 ZFWORD EQU 24 ; START OF FWORDS TABLE + 51 001A ZLENTH EQU 26 ; LENGTH OF Z-PROGRAM IN WORDS + 52 001C ZCHKSM EQU 28 ; Z-CODE CHECKSUM WORD + 53 001E ZINTWD EQU 30 ; INTERPRETER ID WORD (SUPPLIED BY EZIP) + 54 0020 ZSCRWD EQU 32 ; SCREEN PARAMETER WORD ( " " " ) + 55 0022 ZHWRD EQU 34 ; DISPLAY WIDTH IN PIXELS + 56 0024 ZVWRD EQU 36 ; DISPLAY HEIGHT IN PIXELS + 57 0026 ZFWRD EQU 38 ; FONT HEIGHT, FONT WIDTH + 58 0028 ZFOFF EQU 40 ; FUNCTION OFFSET + 59 002A ZSOFF EQU 42 ; STRING OFFSET + 60 002C ZCLRWD EQU 44 ; FORGROUND COLOR, BACKGROUND COLOR + 61 002E ZTCHAR EQU 46 ; POINTER TO TBL OF TERMINATING CHARS + 62 0030 ZTWIDTH EQU 48 ; Running counter for table output char width + Wed Jun 7 1989 12:04 Page 3 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- YZIP EQUATES ---" + + 63 0032 ZCRFUNC EQU 50 ; FUNCTION FOR CARRIAGE RETURNS + 64 0034 ZCHRSET EQU 52 ; POINTER TO CHAR SET TBL + 65 0036 ZEXTAB EQU 54 ; Points to extension table, if needed + 66 ; + 67 ; Extension table offsets + 68 ; + 69 0000 ZEXTLEN EQU 0 ; Length of extension table + 70 0002 ZMSLOCX EQU 2 ; x location of mouse + 71 0004 ZMSLOCY EQU 4 ; y location of mouse + 72 0006 ZMSETBL EQU 6 ; MOUSE TBL CHANGE WORD + 73 0008 ZMSEDIR EQU 8 ; DIRECTION MENU + 74 000A ZMSEINV EQU 10 ; INVENTORY MENU + 75 000C ZMSEVRB EQU 12 ; FREQUENT VERB MENU + 76 000E ZMSEWRD EQU 14 ; FREQUENT WORD MENU + 77 0010 ZBUTTN EQU 16 ; BUTTON HANDLER + 78 0012 ZJOYST EQU 18 ; JOYSTICK HANDLER + 79 0014 ZBSTAT EQU 20 ; BUTTON STATUS + 80 0016 ZJSTAT EQU 22 ; JOYSTICK STATUS + 81 ; + 82 ; ZFLAGS values + 83 ; + 84 0001 FSCRI EQU $01 ; scripting? + 85 0002 FMONO EQU $02 ; mono spaced font? + 86 0004 FSTAT EQU $04 ; status line refresh? + 87 0008 FDISP EQU $08 ; uses DISPLAY operations? + 88 0010 FUNDO EQU $10 ; uses UNDO? + 89 0020 FMOUS EQU $20 ; uses mouse? + 90 0040 FCOLO EQU $40 ; uses color? + 91 0080 FMENU EQU $80 ; uses menus? + 92 ;--------------- + 93 ; Picture data + 94 ;--------------- + 95 ;=== DATA HEADER === + 96 0000 PHFID EQU 0 ; File ID + 97 0001 PHFLG EQU PHFID+1 ; Flags + 98 0002 PHHUFF EQU PHFLG+1 ; Pointer to Huffman data + 99 0004 PHNLD EQU PHHUFF+2 ; # entries in local directory + 100 0006 PHNGD EQU PHNLD+2 ; # entries in global directory + 101 0008 PHDSIZE EQU PHNGD+2 ; Local directory entry size + 102 000A PHCHKS EQU PHDSIZE+2 ; File Checksum + 103 000C PHFVERS EQU PHCHKS+2 ; File Version (N/A) + 104 000E PHEXTRA EQU PHFVERS+2 ; Extra room for getting fatter + 105 0010 PHSIZE EQU 16 ; 16 bytes is header size + 106 ;=== DATA HEADER FLAGS === + 107 0001 PHFGD EQU $1 ; data has global directory + 108 0002 PHFHUFF EQU $2 ; Huffman encoded pictures + 109 0004 PHFHUFF1 EQU $4 ; All pictures use same Huff tree + 110 0008 PHFPAL EQU $8 ; No pallette information + 111 ;=== LOCAL DIRECTORY === + 112 0000 PLDID EQU 0 ; Picture ID + 113 0002 PLDWID EQU PLDID+2 ; Picture Width + 114 0003 PLDHGHT EQU PLDWID+1 ; Picture Height + 115 0004 PLDFLG EQU PLDHGHT+1 ; Flags + 116 0005 PLDPTR EQU PLDFLG+1 ; Pointer to picture data + 117 0008 PLDSIZE EQU PLDPTR+3 ; size of local directory entry + 118 + 119 0000 END + Wed Jun 7 1989 12:04 Page 4 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- YZIP EQUATES ---" + + 120 + 121 0000 INCLUDE ZERO.EQU + 122 0000 STTL "--- ZERO PAGE VARIABLES ---" + 123 PAGE + Wed Jun 7 1989 12:04 Page 5 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 124 + 125 0000 SCRCX EQU 0 ; CURSOR HORIZONTAL + 126 0001 SCRCY EQU SCRCX+1 ; CURSOR VERTICAL + 127 0002 SCRBTM EQU SCRCY+1 ; first line outside current window + 128 0003 MAXLINES EQU SCRBTM+1 ; maximum number of lines in window + 129 0004 LEFTMRG EQU MAXLINES+1 ; left edge + left margin in current window + 130 0005 WINDOW EQU LEFTMRG+1 ; (WORD) address of current window structure + 131 0007 LINE_X EQU WINDOW+2 ; (WORD) width of line counter + 132 0009 CC_OFF EQU LINE_X+2 ; save offset for char drawing + 133 000A CLSLEFT EQU CC_OFF+1 ; screen limits for CLS code + 134 000B CLSTOP EQU CLSLEFT+1 ; top of screen + 135 000C CLSWIDTH EQU CLSTOP+1 ; # of columns + 136 000D CLSHEIGHT EQU CLSWIDTH+1 ; # of lines + 137 ; + 138 ; some variables for all the screen positioning code + 139 ; + 140 000E NY_DATA EQU CLSHEIGHT+1 ; place for GET/PUT_NYBBLE to use + 141 000F CH_OFFSET EQU NY_DATA+1 ; offset into char data table + 142 0010 DATALOOP EQU CH_OFFSET+1 ; loop counter for byte works + 143 0011 BITOFF EQU DATALOOP+1 ; bit offset into screen byte + 144 0012 CH_DATA EQU BITOFF+1 ; actual char data being worked on + 145 0013 SCR_DATA EQU CH_DATA+1 ; screen byte being worked on + 146 0014 SH_LOOP EQU SCR_DATA+1 ; loop counter for bit shifting + 147 0015 SCROLLY EQU SH_LOOP+1 ; save spot for y pos when scrolling + 148 0016 RETRIES EQU SCROLLY+1 ; (BYTE) Machine ID + 149 0017 CHRMAX EQU RETRIES+1 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD + 150 0018 SCLLINES EQU CHRMAX+1 ; (BYTE) how many lines to scroll + 151 0019 FMTTBL EQU SCLLINES+1 ; (BYTE) flag to show formatted table output + 152 001A STMASK EQU FMTTBL+1 ; (BYTE) Mask to use on first byte of CLS + 153 001B ENDMASK EQU STMASK+1 ; (BYTE) Mask to use on last byte of CLS + 154 001C CHPTR EQU ENDMASK+1 ; (WORD) pointer to char data + 155 001C SCOFF EQU CHPTR ;(BYTE) Offset used by scroll + 156 001D SCLDIR EQU CHPTR+1 ;(BYTE) Direction of scroll - >0 up, <0 down + 157 001E DSEGS EQU CHPTR+2 ; (WORD) Pointer to current disk's segments + 158 ;WIDE_FLAG EQU SCOFF+1 ; (BYTE) <> 0 if 16 bytes in char data + 159 ;DSEGS EQU WIDE_FLAG+1 ; (WORD) Pointer to current disk's segments + 160 0020 LASTWV EQU DSEGS+2 ; last of the WINDOW variables + 161 + 162 0050 ZEROPG EQU $50 ; FIRST FREE Z-PAGE LOCATION + 163 ; + 164 ; these are first, cuz ZBOOT inits them so we don't want to clear them + 165 ; at ZBEGIN warm start + 166 ; + 167 0050 GLOBAL EQU ZEROPG ; (Relative Addr.) GLOBAL VARIABLE POINTER + 168 0052 VOCAB EQU GLOBAL+2 ; (ADDRESS) Vocab table pointer + 169 0055 FWORDS EQU VOCAB+3 ; (ADDRESS) F-WORDS TABLE POINTER + 170 0058 MOUSEF EQU FWORDS+3 ; (BYTE) ==-1/1 if we have mouse/joystick + 171 0059 INFODOS EQU MOUSEF+1 ; (WORD) if <>0, then pointer to D2SEG + 172 005B FUNOFF EQU INFODOS+2 ; (ADDRESS) Function Offset (ZFOFF*8) + 173 005B FOFFH EQU FUNOFF ; (BYTE) Hi part + 174 005C FOFFM EQU FUNOFF+1 ; (BYTE) Middle part + 175 005D FOFFL EQU FUNOFF+2 ; (BYTE) Lo part + 176 005E STROFF EQU FUNOFF+3 ; (ADDRESS) String Offset (ZSOFF*8) + 177 005E SOFFH EQU STROFF ; (BYTE) Hi part + 178 005F SOFFM EQU STROFF+1 ; (BYTE) Middle part + 179 0060 SOFFL EQU STROFF+2 ; (BYTE) Lo part + 180 ; + Wed Jun 7 1989 12:04 Page 6 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 181 ; Beginning of warm start zeroing + 182 ; + 183 0061 OPCODE EQU STROFF+3 ; (BYTE) CURRENT OPCODE + 184 0062 NARGS EQU OPCODE+1 ; (BYTE) # ARGUMENTS + 185 0063 ARG1 EQU OPCODE+2 ; (WORD) ARGUMENT #1 + 186 0065 ARG2 EQU OPCODE+4 ; (WORD) ARGUMENT #2 + 187 0067 ARG3 EQU OPCODE+6 ; (WORD) ARGUMENT #3 + 188 0069 ARG4 EQU OPCODE+8 ; (WORD) ARGUMENT #4 + 189 006B ARG5 EQU OPCODE+10 ; (WORD) + 190 006D ARG6 EQU OPCODE+12 ; (WORD) + 191 006F ARG7 EQU OPCODE+14 ; (WORD) + 192 0071 ARG8 EQU OPCODE+16 ; (WORD) + 193 0073 ABYTE EQU OPCODE+18 ; (BYTE) X-OP ARGUMENT BYTE + 194 0074 BBYTE EQU OPCODE+19 ; (BYTE) XCALL ARG BYTE (EZIP) + 195 0075 ADEX EQU OPCODE+20 ; (BYTE) X-OP ARGUMENT INDEX + 196 0076 VALUE EQU OPCODE+21 ; (WORD) VALUE RETURN REGISTER + 197 0078 I EQU VALUE+2 ; (WORD) GEN-PURPOSE REGISTER #1 + 198 007A J EQU VALUE+4 ; (WORD) GEN-PURPOSE REGISTER #2 + 199 007C K EQU VALUE+6 ; (WORD) GEN-PURPOSE REGISTER #3 + 200 007E L EQU VALUE+8 ; (WORD) GEN-PURPOSE REGISTER #4 + 201 0080 ZPC EQU VALUE+10 ; (3 BYTES) ZIP PROGRAM COUNTER + 202 0080 ZPCL EQU ZPC ; (BYTE) <8 BITS OF [ZPC] + 203 0081 ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] + 204 0082 ZPCH EQU ZPC+2 ; (BYTE) >BIT OF [ZPC] + 205 0083 ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE + 206 0083 ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 207 0084 ZPNTH EQU ZPCPNT+1 ; (BYTE) + 208 0085 ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 209 0086 MPC EQU ZPCPNT+3 ; (3 BYTES) MEMORY PROGRAM COUNTER + 210 0086 MPCL EQU MPC ; (BYTE) <8 BITS OF [MPC] + 211 0087 MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] + 212 0088 MPCH EQU MPC+2 ; (BYTE) >BIT OF [MPC] + 213 0089 MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE + 214 0089 MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 215 008A MPNTH EQU MPCPNT+1 ; (BYTE) + 216 008B MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 217 008C FPC EQU MPCBNK+1 ; (3 Bytes) Fetch pointer + 218 008C FPCL EQU FPC ; (BYTE) Low part + 219 008D FPCH EQU FPCL+1 ; (BYTE) High Part + 220 008E FPCBNK EQU FPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 221 008F SPC EQU FPCBNK+1 ; (3 Bytes) Fetch pointer + 222 008F SPCL EQU SPC ; (BYTE) Low part + 223 0090 SPCH EQU SPCL+1 ; (BYTE) High Part + 224 0091 SPCBNK EQU SPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 225 + 226 ; Z-STRING MANIPULATION VARIABLES + 227 + 228 0092 LINLEN EQU SPCBNK+1 ; (BYTE) LENGTH OF CURRENT LINE + 229 0093 SOURCE EQU LINLEN+1 ; (BYTE) counter for read + 230 0094 WRDLEN EQU SOURCE+1 ; (BYTE) LENGTH OF CURRENT WORD + 231 0095 ESIZE EQU WRDLEN+1 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES + 232 0096 PSET EQU ESIZE+1 ; (BYTE) PERMANENT CHARSET + 233 0097 TSET EQU PSET+1 ; (BYTE) TEMPORARY CHARSET + 234 0098 ZCHAR EQU TSET+1 ; (BYTE) CURRENT Z-CHAR + 235 0099 OFFSET EQU ZCHAR+1 ; (BYTE) F-WORD TABLE OFFSET + 236 009A ZFLAG EQU OFFSET+1 ; (BYTE) Z-WORD ACCESS FLAG + 237 009B ZWORD EQU ZFLAG+1 ; (WORD) CURRENT Z-WORD + Wed Jun 7 1989 12:04 Page 7 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 238 009D CONCNT EQU ZWORD+2 ; (BYTE) Z-STRING SOURCE COUNTER + 239 009E CONIN EQU CONCNT+1 ; (BYTE) CONVERSION SOURCE INDEX + 240 009F CONOUT EQU CONIN+1 ; (BYTE) CONVERSION DEST INDEX + 241 00A0 DIRTBL EQU CONOUT+1 ; (WORD) CONTAINS TBLE TO STORE CHARS TO + 242 00A2 XSIZE EQU DIRTBL+2 ; (WORD) SCREEN WIDTH FOR TESTS + 243 00A4 RAND EQU XSIZE+2 ; (WORD) Random number offset + 244 00A6 CURWIN EQU RAND+2 ; (BYTE) WHICH WINDOW TO WRITE IN + 245 00A7 LENGTH EQU CURWIN+1 ; (WORD) CHAR POSITION ON THE SCREEN + 246 00A9 CHRCNT EQU LENGTH+2 ; (BYTE) CHAR POSITION IN [LBUFF] + 247 00AA SCRIPT EQU CHRCNT+1 ; (BYTE) SCRIPT ENABLE FLAG + 248 00AB LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER + 249 00AC IOCHAR EQU LINCNT+1 ; (BYTE) CHARACTER BUFFER + 250 00AD COLORP EQU IOCHAR+1 ; (WORD) Pointer to current background color + 251 00AF ZSP EQU COLORP+2 ; (WORD) Z Stack + 252 00B1 SCREENF EQU ZSP+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT + 253 00B2 TABLEF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT + 254 00B3 VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH + 255 00B6 DBUFF EQU VOCEND+3 ; (WORD) RAM PG TO ACCESS (LSB = 0) + 256 00B8 DSKBNK EQU DBUFF+2 ; (BYTE) MAIN/AUX bank + 257 00B9 ALLFLG EQU DSKBNK+1 ; (BYTE) IF =1 ALL FCN KEYS (>127) ARE TCHARS + 258 00BA UNDFLG EQU ALLFLG+1 ; (BYTE) Underlining flag + 259 00BB INVFLG EQU UNDFLG+1 ; (BYTE) Inverse flag + 260 00BC MEMPAGE EQU INVFLG+1 ; (BYTE) Save spot for XPAGING stuff + 261 00BD CPY_COUNT EQU MEMPAGE+1 ; (BYTE) Number of bytes for copy line + 262 00BE TBLHEIGHT EQU CPY_COUNT+1 ;(BYTE) Number of lines in printing table + 263 00BF TBLWIDTH EQU TBLHEIGHT+1 ;(BYTE) Number of bytes per line + 264 00C0 TBLCNT EQU TBLWIDTH+1 ;(BYTE) Counter for table printing + 265 00C1 FONTFLG EQU TBLCNT+1 ;(BYTE) Which font (!=0 is width) + 266 00C2 TBLPUR EQU FONTFLG+1 ;(BYTE) first pure table page + 267 00C3 FUNPRE EQU TBLPUR+1 ;(BYTE) first preloaded function page + 268 00C4 FUNPUR EQU FUNPRE+1 ;(BYTE) first pure function page + 269 00C5 FUNPGE EQU FUNPUR+1 ;(BYTE) -number to get function preload page + 270 00C6 DELAY_COUNTER EQU FUNPGE+1 ;(BYTE) counter for delay loop + 271 ; + 272 ; some char-to-screen variables + 273 ; + 274 00C7 CHAR_D1 EQU DELAY_COUNTER+1 ; (BYTE) character data, part 1 + 275 00C8 CHAR_D2 EQU CHAR_D1+1 ; (BYTE) char data, part 2 + 276 00C9 CW EQU CHAR_D2+1 ; (BYTE) width of the character + 277 00CA CLKCTR EQU CW+1 ; (BYTE) counter for mouse clicking + 278 00CB MSX EQU CLKCTR+1 ; (BYTE) mouse cursor X + 279 00CC MSY EQU MSX+1 ; (BYTE) mouse cursor Y + 280 00CD CURRENT EQU MSY+1 ; (BYTE) current paging bufer + 281 ;CURSOR_OFF EQU CURRENT+1 ; (BYTE) ==1 if "don't show the blinking cursor" + 282 00CE MSTBL EQU CURRENT+1 ; (ADDRESS) pointer to extension table + 283 00D1 LASTZP EQU MSTBL+3 ; just checking + 284 ; + 285 ; these routines are in non-swapped memory + 286 ; + 287 00D1 ZERO_FB EQU LASTZP ; put fetch byte routine in at end of ZP + 288 00DC ZERO_ZF EQU ZERO_FB+11 ; and ZPCPNT fetch after that + 289 00E5 ZERO_MF EQU ZERO_ZF+9 ; and MPCPNT fetch after that + 290 00EE SAVE_DATA EQU ZERO_MF+9 ; copy data from DBUFF to IOBUFF routine + 291 ; + 292 ; and just to check the end + 293 ; + 294 00FF ZEE_END EQU SAVE_DATA+17 ; should be == 100 + Wed Jun 7 1989 12:04 Page 8 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 295 + 296 0000 END + 297 + 298 0000 INCLUDE PRODOS.EQU + 299 0000 STTL "--- ProDOS EQUATES ---" + 300 PAGE + Wed Jun 7 1989 12:04 Page 9 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ProDOS EQUATES ---" + + 301 + 302 ; + 303 ; some parameter structures + 304 ; + 305 0000 OPEN_PARM EQU 0 + 306 0000 OP_PCOUNT EQU OPEN_PARM ; must be 3 for open + 307 0001 OP_PATHNAME EQU OP_PCOUNT+1 ; address of pathname + 308 0003 OP_FILEBUFF EQU OP_PATHNAME+2 ; address of file data buffer + 309 0005 OP_REFNUM EQU OP_FILEBUFF+2 ; file reference number + 310 0006 OPEN_PSIZE EQU OP_REFNUM+1 ; size of parameter buffer + 311 + 312 0000 READ_PARM EQU 0 ; to read things + 313 0000 RD_PCOUNT EQU READ_PARM ; param count (=4) + 314 0001 RD_REFNUM EQU RD_PCOUNT+1 ; ref num of file + 315 0002 RD_BUFFER EQU RD_REFNUM+1 ; where to + 316 0004 RD_BUFFLEN EQU RD_BUFFER+2 ; length of buffer + 317 0006 RD_LENGTH EQU RD_BUFFLEN+2 ; actual length of read + 318 0008 READ_PSIZE EQU RD_LENGTH+2 ; length of parm block + 319 + 320 0000 CLOSE_PARM EQU 0 ; for closing file + 321 0000 CL_PCOUNT EQU CLOSE_PARM ; paramter count (=1) + 322 0001 CL_REFNUM EQU CL_PCOUNT+1 ; refnum of file to be closed + 323 0002 CLOSE_PSIZE EQU CL_REFNUM+1 ; this is the size, thank you + 324 + 325 0000 WRITE_PARM EQU 0 ; to write things + 326 0000 WR_PCOUNT EQU WRITE_PARM ; parm count (= 4) + 327 0001 WR_REFNUM EQU WR_PCOUNT+1 ; file refnum + 328 0002 WR_BUFFER EQU WR_REFNUM+1 ; data buffer address + 329 0004 WR_BUFFLEN EQU WR_BUFFER+2 ; data buffer length + 330 0006 WR_LENGTH EQU WR_BUFFLEN+2 ; actual length written + 331 0008 WRITE_PSIZE EQU WR_LENGTH+2 ; length of parm block + 332 + 333 0000 SETMARK_PARM EQU 0 + 334 0000 SM_PCOUNT EQU SETMARK_PARM ; parm count (=2) + 335 0001 SM_REFNUM EQU SM_PCOUNT+1 ; file refnum + 336 0002 SM_FPOS EQU SM_REFNUM+1 ; 3 byte file pos + 337 0005 SETMARK_PSIZE EQU SM_FPOS+3 ; length of parm block + 338 + 339 0000 SETPREFIX_PARM EQU 0 + 340 0000 SP_PCOUNT EQU SETPREFIX_PARM ; parm count (=1) + 341 0001 SP_PATHNAME EQU SP_PCOUNT+1 ; pointer to path name + 342 0003 SETPREFIX_PSIZE EQU SP_PATHNAME+2 ; length of block + 343 + 344 0000 SETEOF_PARM EQU 0 + 345 0000 SE_PCOUNT EQU SETEOF_PARM ; parm count (=2) + 346 0001 SE_REFNUM EQU SE_PCOUNT+1 ; reference number + 347 0002 SE_NEWEOF EQU SE_REFNUM+1 ; new EOF position + 348 0005 SETEOF_PSIZE EQU SE_NEWEOF+3 ; length of parm block + 349 + 350 0000 END + 351 + 352 0000 INCLUDE APPLE.EQU + 353 0000 STTL "--- APPLE ][ HARDWARE STUFF ---" + 354 PAGE + Wed Jun 7 1989 12:04 Page 10 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 355 ; ------------------- + 356 ; APPLE II MEMORY MAP + 357 ; ------------------- + 358 0001 AUX EQU 1 ; offset to Auxillary mem switches + 359 0000 MAIN EQU 0 ; for main memory switches + 360 + 361 ; + 362 ; some hardware spots + 363 ; + 364 2000 SCREEN EQU $2000 ; START OF Double HiRes SCREEN RAM + 365 + 366 BF00 PRGLBL EQU $BF00 ; ProDOS Globals page in main mem + 367 BF58 PR_BITMAP EQU $BF58 ; ProDOS system bitmap + 368 BFFF KVERSION EQU $BFFF ; ProDOS version (== $FF if InfoDOS) + 369 00FF INFODOS_ID EQU $FF + 370 + 371 C000 IOADDR EQU $C000 ; start of I/O registers + 372 D000 PROADR EQU $D000 ; start of ProDOS + 373 + 374 0200 LBUFF EQU $0200 ; LINE INPUT BUFFER + 375 0273 PIC1BUF EQU $0300-141 ; we can use line buffer for one picture buffer + 376 0280 SCRBUFF EQU LBUFF+$80 ; screen line buffer + 377 2000 BORG EQU $2000 ; ORIGIN OF .SYSTEM CODE + 378 ; + 379 ; some page 3 storage relocated stuff + 380 ; + 381 0300 PAGE3STUFF EQU $300 + 382 0300 MOUSER EQU PAGE3STUFF ; this is where mouse subroutine goes + 383 0312 COLORS EQU MOUSER+$12 + 384 0352 XPOSTBL EQU COLORS+$40 + 385 + 386 0400 SV_PCL EQU $400 ; for scrolling data + 387 0600 SV_PCH EQU $600 + 388 + 389 0800 IOBUFF EQU $0800 ; 1Kb DATA BUFFER BUFFER + 390 + 391 0C00 PAGING_MEM EQU IOBUFF+$400 ; Paging table stuff + 392 0C00 NEXTPNT EQU PAGING_MEM + 393 0C40 PREVPNT EQU NEXTPNT+$40 + 394 0C80 VPAGEH EQU PREVPNT+$40 + 395 0CC0 VPAGEL EQU VPAGEH+$40 + 396 0200 PAGELEN EQU $200 ; length of paged read + 397 + 398 0D00 ZSTKBL EQU PAGING_MEM+$100 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) + 399 0E00 ZSTKTL EQU ZSTKBL+$100 ; TOP, LO + 400 0F00 ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI + 401 1000 ZSTKTH EQU ZSTKBL+$300 ; TOP, HI + 402 ; + 403 ; now define some file i/o buffers and such + 404 ; + 405 1100 GAME1FIO EQU ZSTKBL+$400 ; Game file I/O buffer + 406 1500 GAME2FIO EQU GAME1FIO+$400 ; Second game file i/o buffer + 407 1900 SEGTBL EQU GAME2FIO+$400 ; segment table for multi disks + 408 1C74 PIC2BUF EQU SEGTBL+($400-140) ; picture buffer is 140 bytes long + 409 1D00 TCHARTBL EQU SEGTBL+$400 ; 208 bytes for (possible) terminating + 410 1D50 COPY_LINE EQU TCHARTBL+$50 ; copy line in screen memory + 411 1D7C CPY_MOD1_SRC equ COPY_LINE+$2C ; special self-modifying places + Wed Jun 7 1989 12:04 Page 11 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 412 1D7F CPY_MOD1_DST equ CPY_MOD1_SRC+3 + 413 1DA0 CPY_MOD2_SRC equ COPY_LINE+$50 + 414 1DA3 CPY_MOD2_DST equ CPY_MOD2_SRC+3 + 415 + 416 1DD0 DSKSEG EQU TCHARTBL+$D0 ; spot to stash pointers for disk segments + 417 1DD0 D1SEG EQU DSKSEG ; where in SEGTBL for Disk 1 + 418 1DD2 D2SEG EQU D1SEG+2 + 419 1DD4 D3SEG EQU D2SEG+2 + 420 1DD6 D4SEG EQU D3SEG+2 + 421 1DD8 D5SEG EQU D4SEG+2 + 422 1DDA D6SEG EQU D5SEG+2 + 423 1DDC D7SEG EQU D6SEG+2 + 424 1DDE D8SEG EQU D7SEG+2 + 425 1DE0 LOCAL_SV EQU TCHARTBL+$E0 ; to save locals before restore + 426 1E00 LOCALS EQU TCHARTBL+$100 ; LOCAL VARIABLE STORAGE (30 BYTES) + 427 1E20 BUFSAV EQU LOCALS+$20 ; TEMP SPACE FOR SAVE/RESTORE (80 BYTES) + 428 1F00 SCR_LINE EQU LOCALS+$100 ; place to build displayed line + 429 1F8C CHARSET EQU SCR_LINE+140 ; spot for charset to go + 430 ; + 431 ; now for some interpreter data + 432 ; + 433 4000 INTR_BEGIN EQU $4000 ; START OF Interpreter CODE in main + 434 5600 INTR_SIZE EQU (43*512) ; size of interpreter + 435 + 436 9600 ZBEGIN EQU (INTR_BEGIN+INTR_SIZE) ; start of Z code + 437 7F00 MMSIZE EQU PRGLBL-INTR_BEGIN ; free memory in main bank + 438 0029 Z1SIZE EQU >(PRGLBL-ZBEGIN) ; size of preload, part 1 + 439 ; + 440 ; this is in Bank 2, Main mem + 441 ; + 442 ; + 443 ; Picture directory goes in Bank 2, Aux mem + 444 ; + 445 D000 PIC_DIR EQU $D000 ; picture local directory + 446 DC00 GBL_DIR EQU $DC00 ; global directory + 447 ; + 448 ; some special markers if we are using InfoDOS + 449 ; + 450 0000 SP_BANK EQU MAIN + 451 D000 SP_START EQU $D000 ; start of special area + 452 0017 SP_SIZE EQU ((($FE->SP_START)*256)/512) ; how many pages + 453 ;SP_SIZE EQU (((>SCREEN->SP_START)*256)/512) ; how many pages + 454 + 455 0001 PB_BANK EQU AUX ; paging buffers in which bank + 456 0800 PBEGIN EQU $0800 ; start of paging buffers + 457 0018 NUMBUFS EQU >(SCREEN-PBEGIN) ; how many 256k paging buffers + 458 ;NUMBUFS EQU >($100-PBEGIN) ; how many 256k paging buffers + 459 + 460 0029 P2PAGE EQU >(PRGLBL-ZBEGIN) ; first page of zcode in aux bank + 461 4000 Z2BEGIN EQU $4000 ; start of part 2 in aux mem + 462 ; just after the dhires screen + 463 0040 Z2PAGE EQU >Z2BEGIN ; get me just the page address + 464 007F Z2SIZE EQU >(PRGLBL-Z2BEGIN) ; size of preload, part 2 + 465 00A8 P3PAGE EQU Z1SIZE+Z2SIZE ; first page in aux mem part 3 + 466 D000 Z3BEGIN EQU $D000 ; start of 3 part in aux mem + 467 00D0 Z3PAGE EQU >Z3BEGIN ; get me page number too + 468 002E Z3SIZE EQU <($FE-Z3PAGE) ; size of part 3, in pages + Wed Jun 7 1989 12:04 Page 12 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 469 + 470 ; + 471 ; other numba's + 472 ; + 473 00D6 PGBEGIN EQU (P3PAGE+Z3SIZE) ; first paged page + 474 00D6 PRESIZE EQU (Z1SIZE+Z2SIZE+Z3SIZE) ; size of preload, # pages + 475 2000 SCRSZE EQU INTR_BEGIN-SCREEN ; size of Double HiRes screen (8k, each bank) + 476 EE00 RAMDSK EQU (119*512) ; size of RAM disk in aux mem + 477 B500 RAMSAVE EQU $B500 ; save this much to cover HiRes screen in + 478 ; aux and the rest of the preload, up to + 479 ; PRGLBL ($bf00) + 480 3900 FREERAM EQU RAMDSK-RAMSAVE ; size of Free RAM after 'saving' + 481 ; special AUX memory + 482 2200 DSKSZE EQU (512*273) ; size of ProDOS data disk file + 483 + 484 ; --------- + 485 ; CONSTANTS + 486 ; --------- + 487 + 488 0002 IIeID EQU 2 ; Apple ][e Yzip + 489 0009 IIcID EQU 9 ; ][c Yzip + 490 000A IIgsID EQU 10 ; ][gs Yzip + 491 + 492 00FF P3BANK EQU $FF ; show upper aux mem + 493 0000 LO EQU 0 + 494 0001 HI EQU 1 + 495 0002 ABANK EQU 2 ; for address variables + 496 + 497 0000 OFF EQU 0 ; for toggling soft-switches + 498 0001 ON EQU 1 + 499 + 500 0003 RETRY_COUNT EQU 3 ; how many retries before message + 501 + 502 0009 TAB EQU $09 ; Tab char + 503 000B EOS EQU $0B ; End of Sentence + 504 000D EOL EQU $0D ; EOL CHAR + 505 000A LF EQU $0A ; LINE FEED + 506 0020 SPACE EQU $20 ; SPACE CHAR + 507 0008 BACKSPACE EQU $08 ; BACKSPACE CHAR + 508 001B ESCAPE EQU $1B ; ESCAPE Key + 509 003F VOLCHAR EQU '?' ; Key to hit for ONLINE command + 510 ; + 511 ; Screen Defs + 512 ; + 513 008C MAXWIDTH EQU 140 ; 560 / 4 = max "pixels" + 514 0230 REAL_MAXW EQU MAXWIDTH*4 + 515 00C0 MAXHEIGHT EQU 192 ; 192 screen lines + 516 0002 FONT_W EQU 2 ; font width (for game, anyway) + 517 0009 FONT_H EQU 9 ; font height + 518 0003 MFONT_W EQU 3 ; mono spaced font width, to game + 519 000C MONOFONT_W EQU MFONT_W*4 ; how wide the mono font really is + 520 + 521 0008 SPACE_WIDTH EQU 8 ; default space width + 522 0003 BLINK_RATE EQU 3 ; tenths of seconds between blinks + 523 + 524 001C OUTER_DELAY EQU $1C ; outside delay loop counter + 525 0003 INNER_DELAY EQU 3 ; inner delay loop + Wed Jun 7 1989 12:04 Page 13 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 526 + 527 0072 GS_OUTER_DELAY EQU $72 ; ][gs outside counter + 528 0002 GS_INNER_DELAY EQU 2 ; ][gs inside counter + 529 + 530 ; ---------------------- + 531 ; BOOT ZERO PAGE EQUATES + 532 ; ---------------------- + 533 + 534 0026 BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS + 535 002B BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT + 536 + 537 0280 START_NAME EQU $280 ; name upon boot is stored here + 538 ; ---------------- + 539 ; HARDWARE EQUATES + 540 ; ---------------- + 541 + 542 C000 KBD EQU $C000 ; KEY STROBE + 543 C000 STORE80 EQU $C000 ; video aux mem switch + 544 C002 RDBNK EQU $C002 ; READ MAIN MEMORY (+MAIN, +AUX) + 545 C004 WRTBNK EQU $C004 ; WRITE MAIN 48K OF MEMORY (+MAIN, +AUX) + 546 C008 ALTZP EQU $C008 ; R/W MAIN (C009 = AUX) >MEM + 547 C00C COL80SW EQU $C00C ; 80 Column switch + 548 C010 ANYKEY EQU $C010 ; ANY KEY DOWN FLAG + 549 C019 VERTBLNK EQU $C019 ; Vertical Blanking Flag + 550 C029 IIGSVID EQU $C029 ; GS MEGA ][ video register + 551 C030 SPKR EQU $C030 ; SPEAKER FLAG (MAKE A NOISE) + 552 C035 IIGSSHD EQU $C035 ; ][GS shadowing reg + 553 C050 TEXTSW EQU $C050 ; Graphics Switch + 554 C052 MIXEDSW EQU $C052 ; Mixed Text/Graphics + 555 C054 PAGE2SW EQU $C054 ; Page select + 556 C056 HIRESSW EQU $C056 ; Select HiRes + 557 C05E DHIRESW EQU $C05E ; Double HiRes switch (backwards: +0 on +1 off) + 558 C07E IOUDIS EQU $C07E ; Double HiRes Switch enabler (same backass way) + 559 C083 BNK2SET EQU $C083 ;READ/READ READ RAM WRITE RAM BANK 2 + 560 C08B BNK1SET EQU $C08B ;READ/READ READ RAM WRITE RAM BANK 1 + 561 C082 RDROM EQU $C082 ; READ READ ROM NO WRITE + 562 C088 RDBNK1 EQU $C088 ; READ ram, bank 1 + 563 C080 RDBNK2 EQU $C080 ; Read ram, bank 2 + 564 + 565 ; ----------------- + 566 ; MONITOR VARIABLES + 567 ; ----------------- + 568 + 569 0036 CSW EQU $36 ; CHARACTER OUTPUT VECTOR (for scripting) + 570 C061 APKEY1 EQU $C061 ; open apple key flag + 571 C062 APKEY2 EQU $C062 ; closed apple key flag + 572 + 573 0002 CURSW EQU 2 ; width of cursor + 574 0004 CURSH EQU 4 ; height of cursor + 575 ; ----------- + 576 ; MOUSE STUFF + 577 ; ----------- + 578 C412 MTABLE EQU $C412 ; Mouse ROM table + 579 0310 MSVECTOR EQU MOUSER+16 ; where vector is stored + 580 0312 MSMOVEF EQU MSVECTOR+2 ; Mouse moved flag + 581 0313 MSBTNF EQU MSMOVEF+1 ; Mouse button flag + 582 ; + Wed Jun 7 1989 12:04 Page 14 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 583 ; MOUSE screen holes + 584 ; + 585 0478 CLMPMINL EQU $478 ; lo part of clamping min + 586 0578 CLMPMINH EQU $578 ; hi part of " " + 587 04F8 CLMPMAXL EQU $4F8 ; lo part of clamping max + 588 05F8 CLMPMAXH EQU $5F8 ; hi part of " " + 589 0478 MOUSEXL EQU $478 ; lo part of mouse X + 590 0578 MOUSEXH EQU $578 ; hi part of mouse X + 591 04F8 MOUSEYL EQU $4F8 ; lo part of mouse Y + 592 05F8 MOUSEYH EQU $5F8 ; hi part of mouse Y + 593 0778 MOUSEST EQU $778 ; status byte + 594 ; + 595 ; some mouse constants + 596 ; + 597 0081 SGL_CLK EQU $81 ; single click char + 598 0082 DBL_CLK EQU $82 ; double click char + 599 0006 CLK_CNT EQU 6 ; counts between single and double click + 600 ; Subroutine offsets + 601 0000 SETM EQU 0 + 602 0001 SERVEM EQU 1 + 603 0002 READM EQU 2 + 604 0003 CLEARM EQU 3 + 605 0004 POSM EQU 4 + 606 0005 CLAMPM EQU 5 + 607 0006 HOMEM EQU 6 + 608 0007 INITM EQU 7 + 609 + 610 ; -------------- + 611 ; PRODOS GLOBALS + 612 ; -------------- + 613 BF90 PRODATE EQU $BF90 ; date and + 614 BF92 PROTIME EQU $BF92 ; time + 615 BF98 MACHID EQU $BF98 ; machine id + 616 + 617 ; ---------------- + 618 ; MONITOR ROUTINES + 619 ; ---------------- + 620 FB1E MPREAD EQU $FB1E ; Read for joystick control + 621 FC22 MBASCAL EQU $FC22 ; CALC LINE BASE ADDRESS + 622 FF3A MBELL EQU $FF3A ; MAKE A NOISE + 623 FFFC RESET_VECTOR EQU $FFFC ; force warm reboot + 624 FC9C MCLEOL EQU $FC9C ; CLEAR TO END OF LINE + 625 FC42 MCLEOS EQU $FC42 ; CLEAR TO END OF SCREEN + 626 FC58 MHOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR + 627 FDED MCOUT EQU $FDED ; CHAR OUTPUT + 628 FDF0 MCOUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN + 629 FD0C MRDKEY EQU $FD0C ; READ KEY + 630 FD6F MGETLN1 EQU $FD6F ; GET LINE + 631 FCA8 MWAIT EQU $FCA8 ; WASTE SO MUCH TIME + 632 ; + 633 ; Some /RAM spots + 634 ; + 635 BF26 RAMVEC EQU $BF26 ; /RAM drive vector + 636 077E OLDVEC EQU $77E ; spot to save the drive vector + 637 BF16 UNSVEC EQU $BF16 ; "Uninstalled Device" vector + 638 BF31 DEVCNT EQU $BF31 ; Device count + 639 BF32 DEVNUM EQU $BF32 ; Device list + Wed Jun 7 1989 12:04 Page 15 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 640 + 641 ; + 642 ; machine info spots + 643 ; + 644 FBB3 MACHID1 EQU $FBB3 ; first part + 645 FBC0 MACHID2 EQU $FBC0 ; second part + 646 FE1F MACHCHK EQU $FE1F ; differentiate between ][e and gs + 647 ; do sec, then jsr, and if still set, = ][e + 648 0000 END + 649 + 650 0000 INCLUDE MACROS.ASM + 651 0000 STTL "--- MACROS ---" + 652 PAGE + Wed Jun 7 1989 12:04 Page 16 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- MACROS ---" + + 653 + 654 ; + 655 ; MACROS for Apple ][ Yzip + 656 ; + 657 DLINE: .MACRO STRING,SLEN + 658 ldx #STRING ; get other part of string + 660 IFMA 2 ; check to see if length passed in + 661 ldy SLEN ; then just fetch it + 662 ELSE + 663 ldy #STRING|L ; get length of string + 664 ENDIF + 665 jsr DLINE ; print the string + 666 .MACEND + 667 ; + 668 ; ProDOS macros + 669 ; + 670 PRODOS: .MACRO CODE, PADDR + 671 jsr $BF00 ; ProDOS handler + 672 DB CODE ; ProDOS function code + 673 DW PADDR ; Function Parameter Block address + 674 .MACEND + 675 + 676 QUIT: .MACRO PBLOCK + 677 PRODOS $65, PBLOCK + 678 .MACEND + 679 + 680 READ_BLOCK: .MACRO PBLOCK + 681 PRODOS $80, PBLOCK + 682 .MACEND + 683 + 684 WRITE_BLOCK: .MACRO PBLOCK + 685 PRODOS $81, PBLOCK + 686 .MACEND + 687 + 688 GET_TIME: .MACRO PBLOCK + 689 PRODOS $82, PBLOCK + 690 .MACEND + 691 + 692 CREATE: .MACRO PBLOCK + 693 PRODOS $C0, PBLOCK + 694 .MACEND + 695 + 696 DESTROY: .MACRO PBLOCK + 697 PRODOS $C1, PBLOCK + 698 .MACEND + 699 + 700 RENAME: .MACRO PBLOCK + 701 PRODOS $C2, PBLOCK + 702 .MACEND + 703 + 704 SET_FILE_INFO: .MACRO PBLOCK + 705 PRODOS $C3, PBLOCK + 706 .MACEND + 707 + 708 GET_FILE_INFO: .MACRO PBLOCK + 709 PRODOS $C4, PBLOCK + Wed Jun 7 1989 12:04 Page 17 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- MACROS ---" + + 710 .MACEND + 711 + 712 ONLINE: .MACRO PBLOCK + 713 PRODOS $C5, PBLOCK + 714 .MACEND + 715 + 716 SET_PREFIX: .MACRO PBLOCK + 717 PRODOS $C6, PBLOCK + 718 .MACEND + 719 + 720 GET_PREFIX: .MACRO PBLOCK + 721 PRODOS $C7, PBLOCK + 722 .MACEND + 723 + 724 OPEN: .MACRO PBLOCK + 725 PRODOS $C8, PBLOCK + 726 .MACEND + 727 + 728 NEWLINE: .MACRO PBLOCK + 729 PRODOS $C9, PBLOCK + 730 .MACEND + 731 + 732 READ: .MACRO PBLOCK + 733 PRODOS $CA, PBLOCK + 734 .MACEND + 735 + 736 WRITE: .MACRO PBLOCK + 737 PRODOS $CB, PBLOCK + 738 .MACEND + 739 + 740 CLOSE: .MACRO PBLOCK + 741 PRODOS $CC, PBLOCK + 742 .MACEND + 743 + 744 FLUSH: .MACRO PBLOCK + 745 PRODOS $CD, PBLOCK + 746 .MACEND + 747 + 748 SET_MARK: .MACRO PBLOCK + 749 PRODOS $CE, PBLOCK + 750 .MACEND + 751 + 752 GET_MARK: .MACRO PBLOCK + 753 PRODOS $CF, PBLOCK + 754 .MACEND + 755 + 756 SET_EOF: .MACRO PBLOCK + 757 PRODOS $D0, PBLOCK + 758 .MACEND + 759 + 760 SET_BUF: .MACRO PBLOCK + 761 PRODOS $D1, PBLOCK + 762 .MACEND + 763 + 764 GET_BUF: .MACRO PBLOCK + 765 PRODOS $D2, PBLOCK + 766 .MACEND + Wed Jun 7 1989 12:04 Page 18 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- MACROS ---" + + 767 + 768 0000 END + 769 + 770 + 771 0000 STTL "--- APPLE ProDOS BOOT CODE ---" + 772 PAGE + Wed Jun 7 1989 12:04 Page 19 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 773 + 774 0024 CHZ EQU $24 ; CURSOR HORIZONTAL + 775 057B EHZ EQU $57B ; CURSOR HORIZONTAL + 776 0025 CVT EQU $25 ; CURSOR VERTICAL + 777 + 778 ; + 779 ; my own little error checking macro + 780 ; + 781 0000 ERRVAL .VAR 0 + 782 ; + 783 ; this macros checks for carry being set (ProDOS error) and if it is + 784 ; loads an error code in x and jumps to the error handler + 785 ERRCHK .MACRO + 786 ERRVAL .VAR ERRVAL+1 + 787 bcc BOOT| + 788 ldy #ERRVAL + 789 jmp BOOT_ERROR + 790 BOOT|: + 791 .MACEND + 792 + 793 2000 ORG BORG + 794 2000 4C 0C 20 jmp BOOT_BEGIN ; just jump to beginning + 795 2003 PROGNAME: + 796 2003 BLKB 9,0 ; 8 bytes for name + 1 for ending zero + 797 200C BOOT_BEGIN: + 798 200C AD 82 C0 lda RDROM ; swap in rom + 799 200F 8D 51 C0 sta TEXTSW+ON ; turn on text + 800 2012 8D 0C C0 sta COL80SW+OFF ; turn on 80 column + 801 + 802 ; + 803 ; make sure we are on a ][c, or ][e+ + 804 ; + 805 2015 20 AE 26 jsr MACHINE ; check it out, returns if good + 806 2018 A5 65 lda ARG2+LO ; check machine + 807 201A C9 0A cmp #IIgsID ; 2gs? + 808 201C D0 10 bne ZBOOTGS ; nope + 809 201E AD 29 C0 lda IIGSVID ; get current video setting + 810 2021 29 1F and #$1F ; turn off upper 3 bits + 811 2023 8D 29 C0 sta IIGSVID ; make sure double hires works + 812 2026 AD 35 C0 lda IIGSSHD ; get shadowing reg + 813 2029 29 A0 and #$A0 ; turn on shadowing everywhere + 814 202B 8D 35 C0 sta IIGSSHD ; okay + 815 202E ZBOOTGS: + 816 202E 20 5C 28 jsr FIXRAM ; check and clear RAM disk + 817 2031 20 6C 29 jsr DO_PREFIX ; go set my current prefix + 818 + 819 2034 20 58 FC jsr MHOME ; clear and home + 820 2037 A9 09 lda #9 ; CENTER DISPLAY + 821 2039 85 25 sta CVT + 822 203B A9 08 lda #8 + 823 203D 85 24 sta CHZ + 824 203F 8D 7B 05 sta EHZ + 825 2042 20 22 FC jsr MBASCAL ; move cursor there! + 826 2045 DLINE STRYM + 827 2045 A2 5C ldx #STRYM ; get other part of string + 829 [01] IFMA 2 ; check to see if length passed in + Wed Jun 7 1989 12:04 Page 20 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 830 ldy M ; then just fetch it + 831 [01] ELSE + 832 2049 A0 18 ldy #STRYML ; get length of string + 833 [00] ENDIF + 834 204B 20 D5 26 jsr DLINE ; print the string + 835 204E .MACEND + 836 ; + 837 ; move down to lower left and print out version number + 838 ; + 839 204E A9 15 lda #21 + 840 2050 85 25 sta CVT + 841 2052 A9 01 lda #1 + 842 2054 85 24 sta CHZ ; move to 1,20 + 843 2056 8D 7B 05 sta EHZ + 844 2059 20 22 FC jsr MBASCAL ; move cursor there! + 845 205C DLINE VERMSG ; show me the version + 846 205C A2 42 ldx #VERMSG ; get other part of string + 848 [01] IFMA 2 ; check to see if length passed in + 849 ldy ; then just fetch it + 850 [01] ELSE + 851 2060 A0 0A ldy #VERMSGL ; get length of string + 852 [00] ENDIF + 853 2062 20 D5 26 jsr DLINE ; print the string + 854 2065 .MACEND + 855 2065 A9 01 lda #VERSID/10 ; get version + 856 2067 09 B0 ora #$B0 ; make normal char for ][ + 857 2069 20 ED FD jsr MCOUT + 858 206C A9 03 lda #VERSID.MOD.10 + 859 206E 09 B0 ora #$B0 ; make normal char for ][ + 860 2070 20 ED FD jsr MCOUT + 861 + 862 2073 A9 FF lda #$FF ; init invflg to normal + 863 2075 85 BB sta INVFLG ; okay + 864 + 865 2077 A9 00 lda #0 ; zero out bit map + 866 2079 A2 17 ldx #$17 ; 17 bytes in ProDOS system bitmap + 867 207B CLRPRD: + 868 207B 9D 58 BF sta PR_BITMAP,X ; and zero out the memory + 869 207E CA dex + 870 207F 10 FA bpl CLRPRD ; and zero entire bitmap + 871 + 872 2081 A9 C0 lda #$C0 ; start out the bitmap with c0 at start + 873 2083 8D 58 BF sta PR_BITMAP + 874 2086 A9 01 lda #$01 ; and a 1 at the end + 875 2088 8D 6F BF sta PR_BITMAP+$17 ; thankx + 876 ; + 877 ; now we need to load in the interpreter + 878 ; + 879 208B OPEN INTR_OPEN ; open up interpreter file + 880 208B PRODOS $C8, INTR_OPEN + 881 208B 20 00 BF jsr $BF00 ; ProDOS handler + 882 208E C8 DB $C8 ; ProDOS function code + 883 208F 1B2A DW INTR_OPEN ; Function Parameter Block address + 884 2091 .MACEND + 885 2091 .MACEND + 886 2091 ERRCHK + Wed Jun 7 1989 12:04 Page 21 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 887 0001 ERRVAL .VAR ERRVAL+1 + 888 2091 90 05 bcc BOOT1 + 889 2093 A0 01 ldy #ERRVAL + 890 2095 4C AB 26 jmp BOOT_ERROR + 891 2098 BOOT1: + 892 2098 .MACEND + 893 + 894 2098 AD 20 2A lda INTR_OPEN+OP_REFNUM ; get refnum for intr file + 895 209B 8D 30 2A sta READ_BLOCK+RD_REFNUM ; and save for read + 896 209E 8D 22 2A sta CLOSE_BLOCK+CL_REFNUM ; close up interpreter file + 897 + 898 20A1 A9 03 lda #RETRY_COUNT ; set retry + 899 20A3 85 16 sta RETRIES ; just use this for now + 900 20A5 RDINTR: + 901 20A5 READ READ_BLOCK ; read in interpreter + 902 20A5 PRODOS $CA, READ_BLOCK + 903 20A5 20 00 BF jsr $BF00 ; ProDOS handler + 904 20A8 CA DB $CA ; ProDOS function code + 905 20A9 2F2A DW READ_BLOCK ; Function Parameter Block address + 906 20AB .MACEND + 907 20AB .MACEND + 908 20AB 90 0B bcc RDINTR1 ; it worked fine + 909 20AD C6 16 dec RETRIES ; try again + 910 20AF 10 F4 bpl RDINTR ; fine + 911 20B1 ERRCHK ; then just die + 912 0002 ERRVAL .VAR ERRVAL+1 + 913 20B1 90 05 bcc BOOT2 + 914 20B3 A0 02 ldy #ERRVAL + 915 20B5 4C AB 26 jmp BOOT_ERROR + 916 20B8 BOOT2: + 917 20B8 .MACEND + 918 20B8 RDINTR1: + 919 20B8 CLOSE CLOSE_BLOCK ; done with interpreter + 920 20B8 PRODOS $CC, CLOSE_BLOCK + 921 20B8 20 00 BF jsr $BF00 ; ProDOS handler + 922 20BB CC DB $CC ; ProDOS function code + 923 20BC 212A DW CLOSE_BLOCK ; Function Parameter Block address + 924 20BE .MACEND + 925 20BE .MACEND + 926 ; + 927 ; now read in first part of preload + 928 ; + 929 20BE A2 00 ldx #0 ; start at first letter + 930 20C0 MVPRE: + 931 20C0 BD 03 20 lda PROGNAME,X ; get letter + 932 20C3 F0 06 beq MVPREX ; all done + 933 20C5 9D 40 2A sta PRE_NAME,X ; save letter + 934 20C8 E8 inx ; next letter + 935 20C9 D0 F5 bne MVPRE ; do gen + 936 20CB MVPREX: + 937 ; + 938 ; now add on ".d1" suffix for the preload + 939 ; + 940 20CB A9 2E lda #'.' ; get '.' + 941 20CD 9D 40 2A sta PRE_NAME,X ; save it + 942 20D0 E8 inx ; next char + 943 20D1 A9 44 lda #'D' ; 'D' char + Wed Jun 7 1989 12:04 Page 22 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 944 20D3 9D 40 2A sta PRE_NAME,X ; save it + 945 20D6 E8 inx ; next char + 946 20D7 A9 31 lda #'1' ; preload is .1 + 947 20D9 9D 40 2A sta PRE_NAME,X ; saved + 948 20DC E8 inx ; count the .1 + 949 20DD 8E 3F 2A stx PRELOAD_NAME ; save length of name + 950 + 951 20E0 OPEN PRELOAD_OPEN ; so now open preload file + 952 20E0 PRODOS $C8, PRELOAD_OPEN + 953 20E0 20 00 BF jsr $BF00 ; ProDOS handler + 954 20E3 C8 DB $C8 ; ProDOS function code + 955 20E4 292A DW PRELOAD_OPEN ; Function Parameter Block address + 956 20E6 .MACEND + 957 20E6 .MACEND + 958 20E6 ERRCHK + 959 0003 ERRVAL .VAR ERRVAL+1 + 960 20E6 90 05 bcc BOOT3 + 961 20E8 A0 03 ldy #ERRVAL + 962 20EA 4C AB 26 jmp BOOT_ERROR + 963 20ED BOOT3: + 964 20ED .MACEND + 965 + 966 20ED AD 2E 2A lda PRELOAD_OPEN+OP_REFNUM ; get refnum + 967 20F0 8D 30 2A sta READ_BLOCK+RD_REFNUM ; save refnum for read + 968 20F3 8D 25 2A sta PSEEK+SM_REFNUM ; and for moving around + 969 ; + 970 ; first, get the segment table + 971 ; + 972 20F6 A9 08 lda #>IOBUFF ; just read in size + 973 20F8 8D 32 2A sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + 974 20FB A9 04 lda #4 ; read in first 1 Kb + 975 20FD 8D 34 2A sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + 976 2100 A9 00 lda #0 ; get size in words + 977 2102 8D 33 2A sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + 978 2105 + 979 2105 READ READ_BLOCK ; and read first block + 980 2105 PRODOS $CA, READ_BLOCK + 981 2105 20 00 BF jsr $BF00 ; ProDOS handler + 982 2108 CA DB $CA ; ProDOS function code + 983 2109 2F2A DW READ_BLOCK ; Function Parameter Block address + 984 210B .MACEND + 985 210B .MACEND + 986 210B ERRCHK + 987 0004 ERRVAL .VAR ERRVAL+1 + 988 210B 90 05 bcc BOOT4 + 989 210D A0 04 ldy #ERRVAL + 990 210F 4C AB 26 jmp BOOT_ERROR + 991 2112 BOOT4: + 992 2112 .MACEND + 993 ; + 994 ; now copy segtable to low mem + 995 ; + 996 2112 A9 08 lda #>IOBUFF + 997 2114 85 7B sta J+HI + 998 2116 A9 00 lda #(SEGTBL-2) + Wed Jun 7 1989 12:04 Page 23 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1001 211C 85 7D sta K+HI + 1002 211E A9 FE lda #<(SEGTBL-2) + 1003 2120 85 7C sta K+LO + 1004 + 1005 2122 AD 01 08 lda IOBUFF+1 ; get LSB + 1006 2125 0A asl A ; *2, to pick up the carry + 1007 2126 AD 00 08 lda IOBUFF ; get how many words + 1008 2129 2A rol A ; *2 for number of bytes + 1009 212A 8D 27 2A sta PSEEK+SM_FPOS+HI ; set page number + 1010 212D AA tax ; make it a counter + 1011 212E A0 02 ldy #2 ; start at second byte, after length + 1012 2130 CPSEGT: + 1013 2130 B1 7A lda (J),y ; get byte + 1014 2132 91 7C sta (K),y ; save byte + 1015 2134 C8 iny ; next byte + 1016 2135 D0 F9 bne CPSEGT ; go do it + 1017 2137 E6 7B inc J+HI + 1018 2139 E6 7D inc K+HI + 1019 213B A0 00 ldy #0 ; restart at beginning of block + 1020 213D CA dex ; count page + 1021 213E 10 F0 bpl CPSEGT ; next page + 1022 ; + 1023 ; now, seek to page following seg table + 1024 ; + 1025 2140 EE 27 2A inc PSEEK+SM_FPOS+HI ; next page + 1026 2143 AD 27 2A lda PSEEK+SM_FPOS+HI ; make sure it is an even 512 page + 1027 2146 29 01 and #$01 ; is it odd? + 1028 2148 F0 07 beq BTSK0 ; nope, so we be okay + 1029 214A EE 27 2A inc PSEEK+SM_FPOS+HI ; next page + 1030 214D A9 03 lda #RETRY_COUNT ; set retry + 1031 214F 85 16 sta RETRIES ; just use this for now + 1032 2151 BTSK0: + 1033 2151 SET_MARK PSEEK ; and point to beginning of game data + 1034 2151 PRODOS $CE, PSEEK + 1035 2151 20 00 BF jsr $BF00 ; ProDOS handler + 1036 2154 CE DB $CE ; ProDOS function code + 1037 2155 242A DW PSEEK ; Function Parameter Block address + 1038 2157 .MACEND + 1039 2157 .MACEND + 1040 + 1041 2157 A9 96 lda #>ZBEGIN ; begining of game code + 1042 2159 8D 32 2A sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + 1043 215C A9 28 lda #(Z1SIZE&$FE) ; get size + 1044 215E 8D 34 2A sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + 1045 2161 A9 00 lda #0 ; get size in words + 1046 2163 8D 33 2A sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + 1047 2166 READ READ_BLOCK ; and read in part 1 of preload + 1048 2166 PRODOS $CA, READ_BLOCK + 1049 2166 20 00 BF jsr $BF00 ; ProDOS handler + 1050 2169 CA DB $CA ; ProDOS function code + 1051 216A 2F2A DW READ_BLOCK ; Function Parameter Block address + 1052 216C .MACEND + 1053 216C .MACEND + 1054 216C 90 0B bcc BTSK00 ; just fine + 1055 216E C6 16 dec RETRIES ; try again + 1056 2170 10 DF bpl BTSK0 ; fine + 1057 2172 ERRCHK ; then just die + Wed Jun 7 1989 12:04 Page 24 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1058 0005 ERRVAL .VAR ERRVAL+1 + 1059 2172 90 05 bcc BOOT5 + 1060 2174 A0 05 ldy #ERRVAL + 1061 2176 4C AB 26 jmp BOOT_ERROR + 1062 2179 BOOT5: + 1063 2179 .MACEND + 1064 2179 BTSK00: + 1065 2179 A9 04 lda #4 ; 4 pages per read + 1066 217B 8D 34 2A sta READ_BLOCK+RD_BUFFLEN+HI ; and lots + 1067 217E A9 08 lda #>IOBUFF ; read into my io buffer + 1068 2180 8D 32 2A sta READ_BLOCK+RD_BUFFER+HI ; hi part of address + 1069 + 1070 [01] IF Z1SIZE & 1 ; if odd, do something special + 1071 2183 READ READ_BLOCK + 1072 2183 PRODOS $CA, READ_BLOCK + 1073 2183 20 00 BF jsr $BF00 ; ProDOS handler + 1074 2186 CA DB $CA ; ProDOS function code + 1075 2187 2F2A DW READ_BLOCK ; Function Parameter Block address + 1076 2189 .MACEND + 1077 2189 .MACEND + 1078 2189 A0 00 ldy #0 ; copy second page + 1079 218B C2LOOP: + 1080 218B B9 00 08 lda IOBUFF,Y + 1081 218E 99 00 BE sta ZBEGIN+(Z1SIZE*$100)-$100,Y + 1082 2191 C8 iny + 1083 2192 D0 F7 bne C2LOOP + 1084 2194 A9 3F lda #(>Z2BEGIN-1) ; don't need first block + 1085 2196 8D E2 21 sta MODOP+2 + 1086 2199 D0 1B bne RD10 ; skip that first read + 1087 [00] ENDIF + 1088 219B AUXRDL: + 1089 219B A9 03 lda #RETRY_COUNT ; set retry + 1090 219D 85 16 sta RETRIES ; just use this for now + 1091 219F AUXRDL0: + 1092 219F READ READ_BLOCK ; and do the read + 1093 219F PRODOS $CA, READ_BLOCK + 1094 219F 20 00 BF jsr $BF00 ; ProDOS handler + 1095 21A2 CA DB $CA ; ProDOS function code + 1096 21A3 2F2A DW READ_BLOCK ; Function Parameter Block address + 1097 21A5 .MACEND + 1098 21A5 .MACEND + 1099 21A5 90 0F bcc RD10 + 1100 21A7 C9 4C cmp #$4C ; this just means EOF already + 1101 21A9 F0 54 beq BT12 ; otherwise, blech + 1102 21AB C6 16 dec RETRIES ; try again + 1103 21AD 10 F0 bpl AUXRDL0 ; fine + 1104 21AF ERRCHK ; then just die + 1105 0006 ERRVAL .VAR ERRVAL+1 + 1106 21AF 90 05 bcc BOOT6 + 1107 21B1 A0 06 ldy #ERRVAL + 1108 21B3 4C AB 26 jmp BOOT_ERROR + 1109 21B6 BOOT6: + 1110 21B6 .MACEND + 1111 21B6 RD10: + 1112 21B6 A9 08 lda #>IOBUFF ; read into my io buffer + 1113 21B8 8D DF 21 sta CLOOP+2 ; start at IOBUFF + 1114 21BB A9 04 lda #4 ; 4 copies + Wed Jun 7 1989 12:04 Page 25 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1115 21BD 85 7E sta L ; okay + 1116 21BF RD11: + 1117 21BF A0 00 ldy #0 ; start at zero, of course + 1118 21C1 AD E2 21 lda MODOP+2 ; check where we are reading too + 1119 21C4 F0 39 beq BT12 ; wrapped, so we had better be done + 1120 21C6 C9 BF cmp #>PRGLBL ; done with aux mem, part 1? + 1121 21C8 90 10 bcc LOOPST ; nope + 1122 21CA D0 05 bne RD12 ; no need to change + 1123 21CC A9 D0 lda #Z3PAGE ; restart at top of memory + 1124 21CE 8D E2 21 sta MODOP+2 ; and do some self modifying code + 1125 21D1 RD12: + 1126 21D1 8D 09 C0 sta ALTZP+AUX ; turn on alt ZP + 1127 21D4 AD 83 C0 lda BNK2SET ; write to upper mem + 1128 21D7 AD 83 C0 lda BNK2SET ; write to upper mem + 1129 21DA LOOPST: + 1130 21DA 8D 05 C0 sta WRTBNK+AUX ; always aux mem + 1131 21DD CLOOP: + 1132 21DD B9 00 08 lda IOBUFF,Y ; get char + 1133 21E0 99 00 40 MODOP: sta Z2BEGIN,Y ; save + 1134 21E3 C8 iny ; point to next one + 1135 21E4 D0 F7 bne CLOOP ; get next one + 1136 + 1137 21E6 AD 82 C0 lda RDROM ; swap back rom, just in case + 1138 21E9 AD 82 C0 lda RDROM ; swap back rom, just in case + 1139 21EC 8D 08 C0 sta ALTZP+MAIN ; and back to main page + 1140 21EF 8D 04 C0 sta WRTBNK+MAIN ; read into main bank + 1141 + 1142 21F2 EE E2 21 inc MODOP+2 ; point to next page + 1143 21F5 EE DF 21 inc CLOOP+2 ; point to next page + 1144 21F8 C6 7E dec L ; next page + 1145 21FA D0 C3 bne RD11 ; and get it + 1146 + 1147 21FC 4C 9B 21 jmp AUXRDL ; get next 1k + 1148 21FF BT12: + 1149 21FF AD 30 2A lda READ_BLOCK+RD_REFNUM ; get refnum for + 1150 2202 8D 22 2A sta CLOSE_BLOCK+CL_REFNUM ; closing the file + 1151 2205 CLOSE CLOSE_BLOCK ; okay, closed + 1152 2205 PRODOS $CC, CLOSE_BLOCK + 1153 2205 20 00 BF jsr $BF00 ; ProDOS handler + 1154 2208 CC DB $CC ; ProDOS function code + 1155 2209 212A DW CLOSE_BLOCK ; Function Parameter Block address + 1156 220B .MACEND + 1157 220B .MACEND + 1158 ; + 1159 ; relocate the Zero Page routines + 1160 ; + 1161 220B A2 2D ldx #RLCLEN ; length of routine + 1162 220D RLOC: + 1163 220D BD E2 23 lda FETCHBx,X ; get byte + 1164 2210 95 D1 sta ZERO_FB,X ; save byte + 1165 2212 CA dex ; get next one + 1166 2213 10 F8 bpl RLOC ; thank you + 1167 ; + 1168 ; and now for the copying screen line sub + 1169 ; + 1170 2215 A2 7C ldx #CPYLEN + 1171 2217 CPYCPLP: + Wed Jun 7 1989 12:04 Page 26 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1172 2217 BD 10 24 lda CPYx,X + 1173 221A 9D 50 1D sta COPY_LINE,X + 1174 221D CA dex + 1175 221E 10 F7 bpl CPYCPLP + 1176 ; + 1177 ; now relocate page 3 stuff + 1178 ; + 1179 2220 A2 DF ldx #PAGE3RELL+1 ; get length of page 3 stuff + 1180 2222 MSRCL: + 1181 2222 BD 8C 24 lda PAGE3REL-1,X ; get byte + 1182 2225 9D FF 02 sta PAGE3STUFF-1,X ; save byte + 1183 2228 CA dex ; count byte + 1184 2229 D0 F7 bne MSRCL ; get next? + 1185 + 1186 222B 20 31 22 jsr ZBOOT ; set up ZIP stuff + 1187 + 1188 222E 4C 00 40 JMP INTR_BEGIN ; jump to the interpreter + 1189 + 1190 2231 INCLUDE ZBOOT.ASM ; ZBOOT subroutine + 1191 PAGE + Wed Jun 7 1989 12:04 Page 27 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1192 2231 STTL "--- ZIP CODE BOOT PART ---" + 1193 2231 ZBOOT: + 1194 ; + 1195 ; clear out ZERO page stuff + 1196 ; + 1197 2231 A5 65 lda ARG2+LO ; get machine id! + 1198 2233 8D 1E 96 sta ZBEGIN+ZINTWD ; save before it gets zeroed + 1199 + 1200 2236 A2 1F ldx #LASTWV-1 ; start at end of first part + 1201 2238 A9 00 lda #0 ; and clear to zero + 1202 223A ZEROL: + 1203 223A 95 00 sta 0,X ; clear out zero page loc + 1204 223C CA dex ; next loc + 1205 223D 10 FB bpl ZEROL ; and do next one + 1206 + 1207 223F A2 50 ldx #ZEROPG ; now do other part + 1208 2241 ZEROL1: + 1209 2241 95 00 sta 0,X ; zero this one + 1210 2243 E8 inx ; point to next one + 1211 2244 E0 D1 cpx #LASTZP ; find the last + 1212 2246 D0 F9 bne ZEROL1 ; okay, so do it + 1213 ; + 1214 ; get game code from data and set up absolute pointers + 1215 ; + 1216 2248 AD 00 96 lda ZBEGIN+ZVERS ; IS GAME A YZIP? + 1217 224B C9 06 cmp #6 ; (X) + 1218 224D F0 07 beq YESEZ ; YES, CONTINUE + 1219 + 1220 ; *** ERROR #15 -- NOT AN EZIP GAME *** + 1221 224F A9 0F lda #15 + 1222 2251 A0 00 ldy #0 + 1223 2253 4C 94 25 jmp ZERROR + 1224 2256 YESEZ: + 1225 2256 A9 3B lda #%00111011 ; ENABLE SOUND, underline, MONOSPACING (X) + 1226 2258 8D 01 96 sta ZBEGIN+ZMODE + 1227 + 1228 225B A9 00 lda #0 ; CLEAR HIGH BYTE + 1229 225D 85 58 sta MOUSEF ; init mouse flag to no mouse + 1230 225F 8D 22 96 sta ZBEGIN+ZHWRD + 1231 2262 8D 24 96 sta ZBEGIN+ZVWRD + 1232 2265 A9 8C lda #MAXWIDTH ; SET SCREEN PARAMETERS + 1233 2267 8D 23 96 sta ZBEGIN+ZHWRD+1 + 1234 226A A9 2E lda #MAXWIDTH/3 ; number of mono spaces on a line + 1235 226C 8D 21 96 sta ZBEGIN+ZSCRWD+1 + 1236 226F A9 C0 lda #MAXHEIGHT + 1237 2271 8D 25 96 sta ZBEGIN+ZVWRD+1 + 1238 2274 A9 15 lda #MAXHEIGHT/FONT_H + 1239 2276 8D 20 96 sta ZBEGIN+ZSCRWD ; number of lines of chars + 1240 2279 A9 09 lda #FONT_H ; height of font + 1241 227B 8D 26 96 sta ZBEGIN+ZFWRD + 1242 227E A9 03 lda #3 ; width of font (2 spaces == 8 pixels) + 1243 2280 8D 27 96 sta ZBEGIN+ZFWRD+1 + 1244 2283 A9 09 lda #9 ; the color white is the foreground color + 1245 2285 8D 2D 96 sta ZBEGIN+ZCLRWD+1 ; show Z game too + 1246 2288 A9 02 lda #2 ; black is the background color + 1247 228A 8D 2C 96 sta ZBEGIN+ZCLRWD ; tell game about it + 1248 ; + Wed Jun 7 1989 12:04 Page 28 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1249 ; just move global address to zero page for quick working + 1250 ; + 1251 228D AD 0C 96 lda ZBEGIN+ZGLOBAL ; get page + 1252 2290 85 51 sta GLOBAL+HI ; save which page + 1253 2292 AD 0D 96 lda ZBEGIN+ZGLOBAL+1 ; LSB NEEDN'T CHANGE + 1254 2295 85 50 sta GLOBAL+LO ; so just store it away + 1255 ; + 1256 ; figger absolute address for the fword table + 1257 ; + 1258 2297 AD 18 96 lda ZBEGIN+ZFWORD ; get fword page number + 1259 229A 20 ED 26 jsr SETPC ; and get absolute address + 1260 229D 85 56 sta FWORDS+HI ; show high addr of table + 1261 229F 84 57 sty FWORDS+ABANK ; show which bank + 1262 22A1 AD 19 96 lda ZBEGIN+ZFWORD+1 ; LSB NEEDN'T CHANGE + 1263 22A4 85 55 sta FWORDS+LO ; so just save it + 1264 ; + 1265 ; figger absolute address for the vocab table + 1266 ; + 1267 22A6 AD 08 96 lda ZBEGIN+ZVOCAB ; get fword page number + 1268 22A9 20 ED 26 jsr SETPC ; and get absolute address + 1269 22AC 85 53 sta VOCAB+HI ; show high addr of table + 1270 22AE 84 54 sty VOCAB+ABANK ; show which bank + 1271 22B0 A9 00 lda #0 ; this is always zero (get lo part from MPCL) + 1272 22B2 85 52 sta VOCAB+LO ; so just save it + 1273 ; + 1274 ; now do somethin' with the TCHAR table (maybe, if <> 0) + 1275 ; + 1276 22B4 AD 2E 96 lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + 1277 22B7 0D 2F 96 ora ZBEGIN+ZTCHAR+1 ; is it zero though? + 1278 22BA D0 05 bne TCH1 ; no, so copy it to somewhere useful + 1279 22BC 8D 00 1D sta TCHARTBL ; not there, so zero first byte in table + 1280 22BF F0 2F beq TCHj ; jmp + 1281 22C1 TCH1: + 1282 22C1 AD 2E 96 lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + 1283 22C4 20 ED 26 jsr SETPC ; and now make absolute + 1284 22C7 85 8D sta FPCH ; Save in FPC + 1285 22C9 84 8E sty FPCBNK + 1286 22CB AD 2F 96 lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + 1287 22CE 85 8C sta FPCL ; now move pointer to fetch spot + 1288 + 1289 22D0 A9 00 lda #0 ; and set index + 1290 22D2 85 78 sta I ; thank you + 1291 22D4 TCHLP: + 1292 22D4 20 14 27 jsr FETCHB ; get the byte in [a] + 1293 22D7 A6 78 ldx I ; get offset + 1294 22D9 E6 78 inc I ; and point to next one + 1295 22DB 9D 00 1D sta TCHARTBL,X ; save in lower memory, thank you + 1296 22DE C9 00 cmp #0 ; are we done yet? + 1297 22E0 F0 0E beq TCHj ; NULL TERMINATED STRING + 1298 22E2 C9 FF cmp #$FF ; $ff means all >128 chars are terminators + 1299 22E4 D0 04 bne TCHLNEXT ; nope + 1300 22E6 A9 01 lda #1 ; yes, + 1301 22E8 85 B9 sta ALLFLG ; so set flag to say so + 1302 22EA TCHLNEXT: + 1303 22EA 20 38 27 jsr NEXTFPC ; point to next one + 1304 22ED 4C D4 22 jmp TCHLP ; and go get it + 1305 22F0 TCHj: + Wed Jun 7 1989 12:04 Page 29 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1306 22F0 20 C6 28 jsr DO_DSEGS ; set up disk segment pointers + 1307 ; + 1308 ; use mouse/joystick, see if either is connected + 1309 ; + 1310 22F3 AD 11 96 lda ZBEGIN+ZFLAGS+1 ; get game flags + 1311 22F6 29 20 and #FMOUS ; uses a mouse? + 1312 22F8 F0 4C beq ZBEND ; nope, so don't ask + 1313 22FA 20 58 FC jsr MHOME ; clear & home + 1314 22FD MSLOOP: + 1315 22FD DLINE MMSG ; ask about Mouse/Joystick/Keyboard + 1316 22FD A2 74 ldx #MMSG ; get other part of string + 1318 [01] IFMA 2 ; check to see if length passed in + 1319 ldy ; then just fetch it + 1320 [01] ELSE + 1321 2301 A0 59 ldy #MMSGL ; get length of string + 1322 [00] ENDIF + 1323 2303 20 D5 26 jsr DLINE ; print the string + 1324 2306 .MACEND + 1325 2306 A9 01 lda #1 ; move to left + 1326 2308 85 24 sta CHZ ; move to column 1 + 1327 230A 20 22 FC jsr MBASCAL ; move cursor there! + 1328 230D A9 8D lda #EOL.OR.$80 ; send out eol + 1329 230F 20 ED FD jsr MCOUT ; bye + 1330 2312 20 0C FD jsr MRDKEY ; get a key please + 1331 2315 20 ED FD jsr MCOUT ; put key out there + 1332 2318 29 7F and #$7F ; turn off hi bit + 1333 231A C9 4D cmp #'M' ; mouse? + 1334 231C F0 1A beq DO_MOUSE ; yup + 1335 231E C9 6D cmp #'m' + 1336 2320 F0 16 beq DO_MOUSE + 1337 2322 C9 4A cmp #'J' ; Joystick? + 1338 2324 F0 19 beq DO_STICK ; yup + 1339 2326 C9 6A cmp #'j' + 1340 2328 F0 15 beq DO_STICK + 1341 232A C9 4E cmp #'N' ; neither + 1342 232C F0 18 beq DO_NEITHER ; yup + 1343 232E C9 6E cmp #'n' + 1344 2330 F0 14 beq DO_NEITHER + 1345 2332 MSLOOP1: + 1346 2332 20 3A FF jsr MBELL ; complain + 1347 2335 4C FD 22 jmp MSLOOP ; and do again + 1348 2338 DO_MOUSE: + 1349 2338 20 58 27 jsr INST_MOUSE ; install mouse handlers + 1350 233B B0 F5 bcs MSLOOP1 ; problems, try again + 1351 233D 90 07 bcc ZBEND ; continue + 1352 233F DO_STICK: + 1353 233F 20 E2 27 jsr INST_STICK ; install joystick handler + 1354 2342 B0 EE bcs MSLOOP1 ; try again + 1355 2344 90 00 bcc ZBEND ; continue, please + 1356 2346 DO_NEITHER: + 1357 2346 ZBEND: + 1358 ; + 1359 ; now, set flags like I want them + 1360 2346 A9 4A lda #FMONO^FDISP^FCOLO + 1361 2348 A6 58 ldx MOUSEF ; doing mousey stuff? + 1362 234A F0 02 beq ZBEND0 ; nope + Wed Jun 7 1989 12:04 Page 30 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1363 234C 09 20 ora #FMOUS ; then turn on that bit too + 1364 234E ZBEND0: + 1365 234E 8D 11 96 sta ZBEGIN+ZFLAGS+1 ; set game flags + 1366 ; + 1367 ; + 1368 ; Multiply ZFOFF & ZSOFF * 8 to get actual offset + 1369 ; + 1370 2351 AD 28 96 lda ZBEGIN+ZFOFF ; hi part + 1371 2354 85 5C sta FOFFM ; this'll be the middle part + 1372 2356 AD 29 96 lda ZBEGIN+ZFOFF+1 ; lo part + 1373 2359 0A asl A ; *2 + 1374 235A 26 5C rol FOFFM + 1375 235C 26 5B rol FOFFH + 1376 235E 0A asl A ; *4 + 1377 235F 26 5C rol FOFFM + 1378 2361 26 5B rol FOFFH + 1379 2363 0A asl A ; *8 + 1380 2364 26 5C rol FOFFM + 1381 2366 26 5B rol FOFFH + 1382 2368 85 5D sta FOFFL ; lo part here too + 1383 ; + 1384 ; now do string offset + 1385 ; + 1386 236A AD 2A 96 lda ZBEGIN+ZSOFF ; hi part + 1387 236D 85 5F sta SOFFM ; this'll be the middle part + 1388 236F AD 2B 96 lda ZBEGIN+ZSOFF+1 ; lo part + 1389 2372 0A asl A ; *2 + 1390 2373 26 5F rol SOFFM + 1391 2375 26 5E rol SOFFH + 1392 2377 0A asl A ; *4 + 1393 2378 26 5F rol SOFFM + 1394 237A 26 5E rol SOFFH + 1395 237C 0A asl A ; *8 + 1396 237D 26 5F rol SOFFM + 1397 237F 26 5E rol SOFFH + 1398 2381 85 60 sta SOFFL ; lo part here too + 1399 + 1400 2383 AD 06 96 lda ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + 1401 2386 85 81 sta ZPCM ; MSB + 1402 2388 AD 07 96 lda ZBEGIN+ZGO+1 ; AND LSB + 1403 238B 0A asl A ; *2 + 1404 238C 26 81 rol ZPCM + 1405 238E 26 82 rol ZPCH + 1406 2390 0A asl A ; *4 + 1407 2391 26 81 rol ZPCM + 1408 2393 26 82 rol ZPCH + 1409 ; + 1410 ; now add offset + 1411 ; + 1412 2395 18 clc ; doing adding + 1413 2396 65 5D adc FOFFL ; add in lo part + 1414 2398 85 80 sta ZPCL + 1415 239A A5 81 lda ZPCM + 1416 239C 65 5C adc FOFFM + 1417 239E 85 81 sta ZPCM + 1418 23A0 A5 82 lda ZPCH + 1419 23A2 65 5B adc FOFFH + Wed Jun 7 1989 12:04 Page 31 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1420 23A4 85 82 sta ZPCH + 1421 ; + 1422 ; now, set up TBLPUR, FUNPRE, and FUNPUR + 1423 ; + 1424 23A6 AD 1D 19 lda SEGTBL+SGTTBLE+1 ; get last page of table preload + 1425 23A9 0A asl A ; make 256K page + 1426 23AA 85 C2 sta TBLPUR ; show last pre table + 1427 23AC E6 C2 inc TBLPUR ; but we want first pure table address + 1428 23AE E6 C2 inc TBLPUR ; so point to it + 1429 23B0 A5 C2 lda TBLPUR ; does table preload take up all preload? + 1430 23B2 C9 D6 cmp #PGBEGIN ; reach 1st paged page? + 1431 23B4 B0 17 bcs ZBEND1 ; ayyup, no function preload + 1432 + 1433 23B6 AD 21 19 lda SEGTBL+SGTFUNS+1 ; get first page of function preload + 1434 23B9 0A asl A ; make 256K page + 1435 23BA 85 C3 sta FUNPRE ; show me + 1436 23BC AD 23 19 lda SEGTBL+SGTFUNE+1 ; last page of function preload + 1437 23BF 0A asl A ; make 256K page + 1438 23C0 85 C4 sta FUNPUR ; show last pre function + 1439 23C2 E6 C4 inc FUNPUR ; but we want first pure function + 1440 23C4 E6 C4 inc FUNPUR ; now we point to it + 1441 23C6 + 1442 23C6 A5 C2 lda TBLPUR ; now figger out negative number to + 1443 23C8 38 sec ; add to function preload addres to + 1444 23C9 E5 C3 sbc FUNPRE ; get page offset in memory + 1445 23CB 85 C5 sta FUNPGE ; set up offset + 1446 ; + 1447 ; and now to set up extension table pointer + 1448 ; + 1449 23CD ZBEND1: + 1450 23CD AD 37 96 lda ZBEGIN+ZEXTAB+1 ; LSB of table + 1451 23D0 85 CE sta MSTBL+LO ; stays the same + 1452 23D2 AD 36 96 lda ZBEGIN+ZEXTAB ; MSB of table + 1453 23D5 20 ED 26 jsr SETPC ; get me the memory addres + 1454 23D8 84 D0 sty MSTBL+ABANK ; save bank + 1455 23DA 85 CF sta MSTBL+HI ; and page + 1456 23DC + 1457 23DC 20 D7 29 jsr INIT_CHARSET ; initialize the charset + 1458 23DF 4C 34 29 jmp INITPAG ; set up paging system + 1459 + 1460 23E2 END + 1461 + 1462 23E2 INCLUDE BREL.ASM ; relocated subroutines + 1463 23E2 STTL "--- RELOCATED SUBROUTINES ---" + 1464 PAGE + Wed Jun 7 1989 12:04 Page 32 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1465 + 1466 ; + 1467 ; FETCHB - use FPC to get a byte in either aux or main mem + 1468 ; + 1469 23E2 FETCHBx: + 1470 23E2 99 02 C0 sta RDBNK,Y ; set bank, lower + 1471 23E5 A0 00 ldy #0 ; gotta use Y + 1472 23E7 B1 8C lda (FPC),Y ; so go get it + 1473 23E9 8D 02 C0 sta RDBNK ; go back to main bank + 1474 23EC 60 rts ; and return + 1475 ; + 1476 ; ZFETCH - fetch byte at (ZPCPNT),Y - offset from (ZPCPNT) + 1477 ; + 1478 23ED ZFETCHx: + 1479 23ED 9D 02 C0 sta RDBNK,X ; set lower bank + 1480 23F0 B1 83 lda (ZPCPNT),Y ; so go get it + 1481 23F2 8D 02 C0 sta RDBNK ; go back to main bank + 1482 23F5 60 rts ; bye + 1483 ; + 1484 ; MFETCH - fetch byte at (MPCPNT),Y - offset from (MPCPNT) + 1485 ; + 1486 23F6 MFETCHx: + 1487 23F6 9D 02 C0 sta RDBNK,X ; set bank + 1488 23F9 B1 89 lda (MPCPNT),Y ; so go get it + 1489 23FB 8D 02 C0 sta RDBNK ; go back to main bank + 1490 23FE 60 rts ; bye + 1491 ; + 1492 ; SAVE_DATA - copy data from [DBUFF] to IOBUFF + 1493 ; [Y] must == 0; [X] == DSKBNK; [A] == IOBUFF ($8 or $9) + 1494 ; + 1495 23FF 9D 02 C0 sta RDBNK,X ; and select that bank for reading + 1496 2402 85 F7 sta SAVE_DATA+9 ; show which part of iobuff + 1497 2404 SDAT1: + 1498 2404 B1 B6 lda (DBUFF),Y ; get me that byte + 1499 2406 SDAT2: + 1500 2406 99 00 08 sta IOBUFF,Y ; MODIFIED ABOVE + 1501 2409 C8 iny + 1502 240A D0 F8 bne SDAT1 + 1503 240C 8D 02 C0 sta RDBNK+MAIN ; and back to main + 1504 240F 60 rts + 1505 002D RLCLEN EQU $-FETCHBx-1 ; mark length + 1506 ; + 1507 ; COPY_LINE: + 1508 ; SPC - source pointer + 1509 ; FPC - destination pointer + 1510 ; SPCBNK - bank the above two are talking about + 1511 ; CPY_COUNT - end-start bytes to move + 1512 ; STMASK - mask to use on first byte (0 if none) + 1513 ; ENDMASK - mask to use for end byte (0 if none) + 1514 ; + 1515 ; MODIFIED CODE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + 1516 ; The definitions for CPY_MODs are HARD CODED in apple.equ - they MUST + 1517 ; match the definitions below for similar xCPY_MODs!!!!!!!! + 1518 ; DON'T CHANGE WITHOUT FIXING THOSE OFFSETS IN APPLE.EQU!!!!! + 1519 ; + 1520 2410 CPYx EQU * + 1521 2410 A6 91 ldx SPCBNK ; set up banks for first byte + Wed Jun 7 1989 12:04 Page 33 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1522 2412 BD 54 C0 lda PAGE2SW,X ; r/w which bank in display mem + 1523 2415 A0 00 ldy #0 ; use Y reg + 1524 2417 A5 1A lda STMASK ; get start mask + 1525 2419 F0 0E beq CPLOOP ; no start mask, start in middle of loop + 1526 241B 31 8C and (FPC),Y ; turn off changing bits, keep good bits + 1527 241D 91 8C sta (FPC),Y ; save it + 1528 241F A5 1A lda STMASK ; get changing bits + 1529 2421 49 FF eor #$FF ; turn on changing bits + 1530 2423 31 8F and (SPC),Y ; get SPC byte + 1531 2425 11 8C ora (FPC),Y ; turn them on in destination too + 1532 2427 91 8C sta (FPC),Y ; and destiny + 1533 2429 CPLOOP: + 1534 2429 A5 BD lda CPY_COUNT ; get count + 1535 242B 4A lsr A ; /2 for number in this bank + 1536 242C AA tax ; put in X for indexing + 1537 242D F0 15 beq CPLP2 ; then done! + 1538 242F CA dex ; zero base the number + 1539 2430 A5 1A lda STMASK ; special start? + 1540 2432 F0 07 beq CPL1 ; nope + 1541 2434 EE 7C 1D inc CPY_MOD1_SRC ; first one already done + 1542 2437 EE 7F 1D inc CPY_MOD1_DST ; point to next one + 1543 243A CA dex ; and count first one as done + 1544 243B CPL1: + 1545 243B BD 00 20 lda SCREEN,X ; get byte + 1546 243E 9D 00 20 sta SCREEN,X ; store byte + 1547 2441 CA dex ; count down + 1548 2442 10 F7 bpl CPL1 ; and do it all again + 1549 2444 CPLP2: + 1550 2444 A0 00 ldy #0 ; reset y + 1551 2446 A5 91 lda SPCBNK ; get current bank + 1552 2448 49 01 eor #1 ; toggle to point to the other one + 1553 244A AA tax + 1554 244B BD 54 C0 lda PAGE2SW,X + 1555 244E 8A txa ; which bank? + 1556 244F F0 07 beq CPLP21 ; we are now in main, things are fine + 1557 2451 EE A0 1D inc CPY_MOD2_SRC ; start one more if now in AUX + 1558 2454 EE A3 1D inc CPY_MOD2_DST + 1559 2457 CA dex ; and count as done + 1560 2458 CPLP21: + 1561 2458 A5 BD lda CPY_COUNT ; get count again + 1562 245A 4A lsr A ; /2 for bytes in this bank + 1563 245B AA tax ; put in X for counter + 1564 245C F0 0A beq CPDONE ; nothing here + 1565 245E CA dex ; zero base the number + 1566 245F CPL2: + 1567 245F BD 00 20 lda SCREEN,X ; get byte + 1568 2462 9D 00 20 sta SCREEN,X ; store byte + 1569 2465 CA dex ; count byte + 1570 2466 10 F7 bpl CPL2 ; and swing by again + 1571 2468 CPDONE: + 1572 2468 A5 1B lda ENDMASK ; do same mucking as when starting + 1573 246A F0 1D beq CPEXIT ; no mucking + 1574 246C 48 pha ; save endmask + 1575 246D A5 BD lda CPY_COUNT ; get how many bytes being copied + 1576 246F 4A lsr A ; /2 + 1577 2470 B0 07 bcs CPDONE1 ; if odd, then we are pointing to correct + 1578 2472 48 pha ; save a + Wed Jun 7 1989 12:04 Page 34 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1579 2473 A6 91 ldx SPCBNK ; get original bank + 1580 2475 BD 54 C0 lda PAGE2SW,X ; and point to it + 1581 2478 68 pla ; get it back + 1582 2479 CPDONE1: + 1583 2479 A8 tay ; get offset + 1584 247A 68 pla ; get end mask back + 1585 247B 49 FF eor #$FF ; turn on all off bits + 1586 247D 31 8C and (FPC),Y ; turn off changing bits + 1587 247F 91 8C sta (FPC),Y ; save it + 1588 2481 B1 8F lda (SPC),Y ; get source byte + 1589 2483 25 1B and ENDMASK ; turn on changing bits + 1590 2485 11 8C ora (FPC),Y ; turn them on in destination too + 1591 2487 91 8C sta (FPC),Y ; and destiny + 1592 2489 CPEXIT: + 1593 2489 AD 54 C0 lda PAGE2SW ; set back to main mem + 1594 248C 60 rts + 1595 007C CPYLEN EQU $-CPYx-1 + 1596 002C xCPY_MOD1 equ (CPL1-CPYx+1) + 1597 002F xCPY_MOD1_DST equ xCPY_MOD1+3 + 1598 0050 xCPY_MOD2 equ (CPL2-CPYx+1) + 1599 0053 xCPY_MOD2_DST equ xCPY_MOD2+3 + 1600 248D PAGE3REL: + 1601 ; + 1602 ; MOUSER - this vectors the call to the correct place + 1603 ; + 1604 248D MOUSERx: + 1605 248D 48 pha ; save A for a sec + 1606 248E BD 12 C4 MSX1: lda MTABLE,X ; get lo part of address + 1607 2491 8D 10 03 sta MSVECTOR+LO ; save lo part of address + 1608 2494 68 pla ; get A back + 1609 2495 EA nop + 1610 2496 A2 C4 MSX2: ldx #$C4 ; might be changed, depending on slot + 1611 2498 A0 40 MSX3: ldy #$40 ; hopefully, this doesn't + 1612 249A 6C 10 03 jmp (MSVECTOR) ; and away we go + 1613 000F MSRxLEN EQU $-MOUSERx-1 ; show how long this is + 1614 249D MSVECTORx: + 1615 249D ds 1 ; where lo part of vector goes + 1616 249E C4 MSX4: db $C4 ; slot where mouse is + 1617 0011 MSRLEN EQU $-MOUSERx-1 ; length or routine + 1618 ; + 1619 ; colors for screen lines + 1620 ; + 1621 RADIX H + 1622 249F COLORSx: + 1623 249F 00 00 00 00 db 00,00,00,00 ; black + 1624 24A3 08 11 22 44 db 08,11,22,44 ; magenta + 1625 24A7 44 08 11 22 db 44,08,11,22 ; brown + 1626 24AB 4C 19 33 66 db 4C,19,33,66 ; orange + 1627 24AF 22 44 08 11 db 22,44,08,11 ; dark green + 1628 24B3 2A 55 2A 55 db 2A,55,2A,55 ; gray 1 + 1629 24B7 66 4C 19 33 db 66,4C,19,33 ; green + 1630 24BB 6E 5D 3B 77 db 6E,5D,3B,77 ; yellow + 1631 24BF 11 22 44 08 db 11,22,44,08 ; dark blue + 1632 24C3 19 33 66 4C db 19,33,66,4C ; purple + 1633 24C7 55 2A 55 2A db 55,2A,55,2A ; gray 2 + 1634 24CB 5D 3B 77 6E db 5D,3B,77,6E ; pink + 1635 24CF 33 66 4C 19 db 33,66,4C,19 ; medium blue + Wed Jun 7 1989 12:04 Page 35 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1636 24D3 3B 77 6E 5D db 3B,77,6E,5D ; light blue + 1637 24D7 77 6E 5D 3B db 77,6E,5D,3B ; aqua + 1638 24DB 7F 7F 7F 7F db 7F,7F,7F,7F ; white + 1639 24DF XPOSTBLx: + 1640 24DF 00 DB 0 + 1641 24E0 00 01 01 02 02 DB 0,1,1,2,2,3,4 + 24E5 03 04 + 1642 24E7 04 05 05 06 06 DB 4,5,5,6,6,7,8 + 24EC 07 08 + 1643 24EE 08 09 09 0A 0A DB 8,9,9,0a,0a,0b,0c + 24F3 0B 0C + 1644 24F5 0C 0D 0D 0E 0E DB 0c,0d,0d,0e,0e,0f,10 + 24FA 0F 10 + 1645 24FC 10 11 11 12 12 DB 10,11,11,12,12,13,14 + 2501 13 14 + 1646 2503 14 15 15 16 16 DB 14,15,15,16,16,17,18 + 2508 17 18 + 1647 250A 18 19 19 1A 1A DB 18,19,19,1a,1a,1b,1c + 250F 1B 1C + 1648 2511 1C 1D 1D 1E 1E DB 1c,1d,1d,1e,1e,1f,20 + 2516 1F 20 + 1649 2518 20 21 21 22 22 DB 20,21,21,22,22,23,24 + 251D 23 24 + 1650 251F 24 25 25 26 26 DB 24,25,25,26,26,27,28 + 2524 27 28 + 1651 2526 28 29 29 2A 2A DB 28,29,29,2a,2a,2b,2c + 252B 2B 2C + 1652 252D 2C 2D 2D 2E 2E DB 2c,2d,2d,2e,2e,2f,30 + 2532 2F 30 + 1653 2534 30 31 31 32 32 DB 30,31,31,32,32,33,34 + 2539 33 34 + 1654 253B 34 35 35 36 36 DB 34,35,35,36,36,37,38 + 2540 37 38 + 1655 2542 38 39 39 3A 3A DB 38,39,39,3a,3a,3b,3c + 2547 3B 3C + 1656 2549 3C 3D 3D 3E 3E DB 3c,3d,3d,3e,3e,3f,40 + 254E 3F 40 + 1657 2550 40 41 41 42 42 DB 40,41,41,42,42,43,44 + 2555 43 44 + 1658 2557 44 45 45 46 46 DB 44,45,45,46,46,47,48 + 255C 47 48 + 1659 255E 48 49 49 4A 4A DB 48,49,49,4a,4a,4b,4c + 2563 4B 4C + 1660 2565 4C 4D 4D 4E 4E DB 4c,4d,4d,4e,4e,4f,50 + 256A 4F 50 + 1661 RADIX D + 1662 00DE PAGE3RELL EQU $-PAGE3REL-1 + 1663 256C END + 1664 + 1665 256C INCLUDE BSUBS.ASM ; subs for e to use + 1666 PAGE + Wed Jun 7 1989 12:04 Page 36 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1667 256C STTL "--- BOOT CODE SUBROUTINES ---" + 1668 + 1669 256C 0D 0D ERRM: DB EOL,EOL + 1670 256E 49 6E 74 65 72 DB "Internal error " + 2573 6E 61 6C 20 65 + 2578 72 72 6F 72 20 + 1671 257D 30 30 ENUMB: DB "00" + 1672 257F 30 30 2E 20 20 DB "00. " + 1673 0018 ERRML EQU $-ERRM + 1674 2584 30 31 32 33 34 HCHARS: DB "0123456789ABCDEF" + 2589 35 36 37 38 39 + 258E 41 42 43 44 45 + 2593 46 + 1675 ; + 1676 ; ZERROR: print out error code in HexWord: [A][Y]. + 1677 ; + 1678 2594 ZERROR: + 1679 2594 48 pha ; save [A] + 1680 2595 98 tya ; and put y to a for figgering + 1681 2596 A0 03 ldy #3 ; CONVERT ERROR BYTE IN [A] + 1682 2598 ZERR0: + 1683 2598 48 pha + 1684 2599 29 0F and #%00001111 + 1685 259B AA tax + 1686 259C BD 84 25 lda HCHARS,X + 1687 259F 99 7D 25 sta ENUMB,Y + 1688 25A2 68 pla + 1689 25A3 4A LSR A + 1690 25A4 4A LSR A + 1691 25A5 4A lsr A + 1692 25A6 4A lsr A + 1693 25A7 AA tax + 1694 25A8 BD 84 25 lda HCHARS,X + 1695 25AB 88 dey + 1696 25AC 99 7D 25 sta ENUMB,Y + 1697 25AF F0 05 beq ZR1 ; done + 1698 25B1 + 1699 25B1 68 pla ; done with first number + 1700 25B2 88 dey ; and point one more down + 1701 25B3 4C 98 25 jmp ZERR0 ; so work on second number + 1702 25B6 ZR1: + 1703 25B6 A2 6C ldx #ERRM + 1705 25BA A0 18 ldy #ERRML + 1706 25BC 20 D5 26 jsr DLINE ; PRINT ERROR MESSAGE + 1707 25BF 20 01 26 jsr GETRET ; wait for + 1708 25C2 4C 19 26 jmp ZQUIT + 1709 + 1710 25C5 0D 50 6C 65 61 RETQ: db EOL,"Please insert new disk to boot." + 25CA 73 65 20 69 6E + 25CF 73 65 72 74 20 + 25D4 6E 65 77 20 64 + 25D9 69 73 6B 20 74 + 25DE 6F 20 62 6F 6F + 25E3 74 2E + 1711 25E5 0D 41 6E 64 20 db EOL, "And hit RETURN when ready.",EOL + 25EA 68 69 74 20 52 + Wed Jun 7 1989 12:04 Page 37 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 25EF 45 54 55 52 4E + 25F4 20 77 68 65 6E + 25F9 20 72 65 61 64 + 25FE 79 2E 0D + 1712 003C RETQL EQU $-RETQ + 1713 2601 GETRET: + 1714 2601 DLINE RETQ ; ask for return + 1715 2601 A2 C5 ldx #RETQ ; get other part of string + 1717 [01] IFMA 2 ; check to see if length passed in + 1718 ldy ; then just fetch it + 1719 [01] ELSE + 1720 2605 A0 3C ldy #RETQL ; get length of string + 1721 [00] ENDIF + 1722 2607 20 D5 26 jsr DLINE ; print the string + 1723 260A .MACEND + 1724 260A GETRETL: + 1725 260A AD 00 C0 lda KBD ; get a key + 1726 260D 10 FB bpl GETRETL ; no key + 1727 260F 29 7F and #$7f ; make a good key + 1728 2611 C9 0D cmp #EOL ; return key? + 1729 2613 D0 F5 bne GETRETL ; nope + 1730 2615 20 ED FD jsr MCOUT ; show the + 1731 2618 60 rts + 1732 2619 + 1733 + 1734 ; ---- + 1735 ; QUIT + 1736 ; ---- + 1737 + 1738 2619 ZQUIT: + 1739 2619 A5 59 lda INFODOS ; in dinky-dos? + 1740 261B F0 17 beq ZQUIT2 ; nope + 1741 261D A9 00 lda #0 ; clear power up byte + 1742 261F 8D F4 03 sta $3F4 ; make it do cold boot + 1743 2622 AD FD FF lda RESET_VECTOR+HI ; now, set up where to die to + 1744 2625 8D 33 26 sta ZQUITR1+2 + 1745 2628 AD FC FF lda RESET_VECTOR+LO + 1746 262B 8D 32 26 sta ZQUITR1+1 + 1747 262E AD 82 C0 lda RDROM ; get ROM back + 1748 2631 ZQUITR1: + 1749 2631 4C FC FF jmp RESET_VECTOR ; just reset things + 1750 ; + 1751 ; re-enable /RAM + 1752 ; + 1753 2634 ZQUIT2: + 1754 2634 AE 31 BF ldx DEVCNT ; put device in at end + 1755 2637 E8 inx ; point to one past end + 1756 2638 8E 31 BF stx DEVCNT ; show new count + 1757 263B A9 BF lda #$BF ; /RAM ID + 1758 263D 9D 32 BF sta DEVNUM,X ; save it + 1759 2640 AD 7F 07 lda OLDVEC+HI ; restore old vector + 1760 2643 8D 27 BF sta RAMVEC+HI + 1761 2646 AD 7E 07 lda OLDVEC+LO + 1762 2649 8D 26 BF sta RAMVEC+LO + 1763 ; + 1764 ; now format /RAM + Wed Jun 7 1989 12:04 Page 38 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1765 ; + 1766 264C A9 03 lda #3 ; stash into FORMAT parm block + 1767 264E 85 42 sta $42 ; it goes here, oddly enough + 1768 2650 A9 B0 lda #$B0 ; device id for /RAM + 1769 2652 85 43 sta $43 ; and here it goes + 1770 2654 A9 11 lda #>GAME1FIO ; IO buffer + 1771 2656 85 45 sta $45 ; this is where it goes + 1772 2658 A9 00 lda #ZBEGIN ; ADD OFFSET TO GET RAM PAGE + 1859 26F5 A0 00 ldy #MAIN ; in the main bank + 1860 26F7 F0 12 beq VFEXI ; BRA to fetch + 1861 26F9 VF2: + 1862 26F9 C9 D6 cmp #PGBEGIN ; is it paged? + 1863 26FB B0 12 bcs VFERR ; yes it be paged, so can't deal with it + 1864 26FD C9 A8 cmp #P3PAGE ; is it in Aux Mem, Part 2? + 1865 26FF B0 06 bcs VF3 ; yes, so subtract different amount + 1866 ; + 1867 ; this is in lower aux + 1868 ; + Wed Jun 7 1989 12:04 Page 40 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1869 2701 A9 17 lda #(Z2PAGE-Z1SIZE) ; subtract size from offset + 1870 2703 A0 01 ldy #AUX ; show aux mem + 1871 2705 D0 04 bne VFEXI ; jump to end + 1872 2707 VF3: + 1873 2707 A9 28 lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides + 1874 2709 A0 FF ldy #P3BANK ; show page 3 bank + 1875 270B VFEXI: + 1876 270B 18 clc ; get ready for addition + 1877 270C 65 BC adc MEMPAGE ; now get actual offset + 1878 270E 60 rts + 1879 270F VFERR: + 1880 ; + 1881 ; out of range + 1882 ; + 1883 270F A9 22 lda #$22 + 1884 2711 4C 94 25 jmp ZERROR + 1885 + 1886 ; + 1887 ; FETCHB - fetch a byte from either main memory, aux memory, or upper + 1888 ; Aux memory + 1889 ; + 1890 2714 FETCHB: + 1891 2714 A4 8E ldy FPCBNK ; get the bank + 1892 2716 30 03 bmi FB1 ; must be in upper RAM + 1893 2718 4C D1 00 jmp ZERO_FB ; go to low end fetch + 1894 ; + 1895 ; this is in aux mem, >$E000 + 1896 ; + 1897 271B FB1: + 1898 271B A5 8D lda FPCH ; get which page + 1899 271D 8D 2D 27 sta FBMOD+2 ; and show in operand + 1900 2720 A4 8C ldy FPCL ; get which byte + 1901 2722 8D 09 C0 sta ALTZP+AUX ; talk about aux mem + 1902 2725 AD 8B C0 lda BNK1SET ; set up read/write ram in upper mem + 1903 2728 AD 8B C0 lda BNK1SET ; set up read/write ram in upper mem + 1904 272B B9 00 D0 FBMOD: lda Z3BEGIN,Y ; get the sucker + 1905 272E 8D 08 C0 sta ALTZP+MAIN ; go back to main mem + 1906 2731 AE 82 C0 ldx RDROM ; now use ROM please + 1907 2734 AE 82 C0 ldx RDROM ; now use ROM please + 1908 2737 60 rts + 1909 ; + 1910 ; NEXTFPC - inc DPCL and check for wrapping round to next bank + 1911 ; + 1912 2738 NEXTFPC: + 1913 2738 E6 8C inc FPCL ; next lo byte + 1914 273A D0 1B bne NXFP_EXIT ; no change then + 1915 273C E6 8D inc FPCH ; next page + 1916 273E A5 8D lda FPCH ; and get it for checking + 1917 2740 C9 BF cmp #>PRGLBL ; have we reached end of line? + 1918 2742 D0 13 bne NXFP_EXIT ; we be okay + 1919 2744 A5 8E lda FPCBNK ; get bank + 1920 2746 D0 07 bne NXFP1 ; must skip over stuff in middle + 1921 2748 E6 8E inc FPCBNK ; so point to aux bank + 1922 274A A9 40 lda #Z2PAGE ; first page in aux + 1923 274C 85 8D sta FPCH ; and point to it + 1924 274E 60 rts ; toots finis + 1925 274F NXFP1: + Wed Jun 7 1989 12:04 Page 41 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1926 274F A9 D0 lda #Z3PAGE ; start of part 3 + 1927 2751 85 8D sta FPCH ; so show me + 1928 2753 A9 FF lda #P3BANK ; and point to this bank + 1929 2755 85 8E sta FPCBNK ; okey + 1930 2757 NXFP_EXIT: + 1931 2757 60 rts + 1932 ; + 1933 ; INST_MOUSE - install mouse handler IRQ + 1934 ; + 1935 0303 MFIX1 EQU (MSX1-MOUSERx)+PAGE3STUFF+2 + 1936 030A MFIX2 EQU (MSX2-MOUSERx)+PAGE3STUFF+1 + 1937 0311 MFIX3 EQU (MSX4-MOUSERx)+PAGE3STUFF + 1938 030C MFIX4 EQU (MSX3-MOUSERx)+PAGE3STUFF+1 + 1939 2758 INST_MOUSE: + 1940 2758 20 CA 27 jsr FINDMOUSE ; find which slot the mouse is in + 1941 275B 90 01 bcc INMS1 ; everything is fine + 1942 275D 60 rts ; can't find the mouse + 1943 275E INMS1: + 1944 275E 8D 03 03 sta MFIX1 + 1945 2761 8D 0A 03 sta MFIX2 + 1946 2764 8D 11 03 sta MFIX3 ; okay, everyone knows now + 1947 2767 29 0F and #$0f ; pick up low byte + 1948 2769 85 63 sta ARG1+LO ; save for program to pick up + 1949 276B 0A asl A ; shift slot number to upper nybble + 1950 276C 0A asl A + 1951 276D 0A asl A + 1952 276E 0A asl A + 1953 276F 8D 0C 03 sta MFIX4 ; and save here + 1954 ; + 1955 ; now init mouse, please + 1956 ; + 1957 2772 A2 07 ldx #INITM ; init first + 1958 2774 20 00 03 jsr MOUSER ; so do it + 1959 2777 A2 00 ldx #SETM ; setup mouse + 1960 2779 A9 01 lda #$01 ; transparent mode + 1961 277B 20 00 03 jsr MOUSER ; we do that + 1962 277E A2 03 ldx #CLEARM ; and clear mouse pos + 1963 2780 20 00 03 jsr MOUSER ; we did + 1964 ; + 1965 ; now set min and max for clamping. + 1966 ; 0 <= xpos <= 139 + 1967 ; 0 <= ypos <= 191 + 1968 ; + 1969 2783 A9 00 lda #0 ; zero out a few of the things + 1970 2785 8D 78 05 sta CLMPMINH ; hi part of min clamp + 1971 2788 8D 78 04 sta CLMPMINL ; lo part of min clamp + 1972 278B A9 89 lda #<137 ; max X + 1973 278D 8D F8 04 sta CLMPMAXL ; stash in lo part + 1974 2790 A9 00 lda #>137 ; max X + 1975 2792 8D F8 05 sta CLMPMAXH ; hi part of clamp + 1976 2795 A9 00 lda #0 ; show setting X clamp + 1977 2797 A2 05 ldx #CLAMPM ; do clamping + 1978 2799 20 00 03 jsr MOUSER ; okay, we did + 1979 279C A9 BD lda #<189 ; now for Y + 1980 279E 8D F8 04 sta CLMPMAXL ; saved in lo part + 1981 27A1 A9 00 lda #>189 ; now for Y + 1982 27A3 8D F8 05 sta CLMPMAXH ; saved in lo part + Wed Jun 7 1989 12:04 Page 42 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1983 27A6 A9 01 lda #1 ; set y boundries + 1984 27A8 A2 05 ldx #CLAMPM ; okay, show which routine + 1985 27AA 20 00 03 jsr MOUSER ; and do it + 1986 + 1987 ; + 1988 ; initialize the mouse position + 1989 ; + 1990 27AD A9 00 lda #0 ; clear MSB + 1991 27AF 8D 78 05 sta MOUSEXH + 1992 27B2 8D F8 05 sta MOUSEYH + 1993 27B5 A9 C0 lda #MAXHEIGHT + 1994 27B7 8D F8 04 sta MOUSEYL + 1995 27BA A9 8C lda #MAXWIDTH + 1996 27BC 8D 78 04 sta MOUSEXL + 1997 + 1998 27BF A2 04 ldx #POSM + 1999 27C1 20 00 03 jsr MOUSER ; and move it + 2000 + 2001 ; cli ; enable interrupts now + 2002 27C4 A9 FF lda #$FF ; < 0 show mouse + 2003 27C6 85 58 sta MOUSEF ; so show it + 2004 27C8 18 clc ; show everything is fine + 2005 27C9 60 rts ; done + 2006 ; + 2007 ; FINDMOUSE - scan the slots for a mouse + 2008 ; + 2009 27CA FINDMOUSE: + 2010 27CA AD FB C1 lda $C1FB ; check for mouse ID == D6 + 2011 27CD C9 D6 cmp #$D6 ; mouse ID + 2012 27CF D0 05 bne FNDM1 ; not it + 2013 27D1 AD CC 27 lda FINDMOUSE+2 ; get slot + 2014 27D4 18 clc ; show okay-ness + 2015 27D5 60 rts ; and return + 2016 27D6 FNDM1: + 2017 27D6 EE CC 27 inc FINDMOUSE+2 ; point to next slot + 2018 27D9 AD CC 27 lda FINDMOUSE+2 ; reached last one yet? + 2019 27DC C9 C8 cmp #$C8 ; no slot eight + 2020 27DE 90 EA bcc FINDMOUSE ; go look again + 2021 27E0 38 sec ; show no mouse + 2022 27E1 60 rts + 2023 ; + 2024 ; INST_STICK - install the joystick handler + 2025 27E2 INST_STICK: + 2026 27E2 A9 01 lda #$1 ; > 0 show joystick + 2027 27E4 85 58 sta MOUSEF ; okay, we do + 2028 27E6 18 clc ; show it worked + 2029 27E7 60 rts + 2030 27E8 RAMINFO: + 2031 27E8 0A db 10 ; 10 parms + 2032 27E9 FA27 dw RAMNAME ; name + 2033 27EB ds 15 ; room for stuff + 2034 27FA RAMNAME: + 2035 27FA 05 db 5 ; length of name + 2036 27FB 2F 52 41 4D 2F db "/RAM/" ; name + 2037 2800 0D 54 68 69 73 RAMQ: db EOL,"This program disables /RAM and it",EOL + 2805 20 70 72 6F 67 + 280A 72 61 6D 20 64 + Wed Jun 7 1989 12:04 Page 43 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 280F 69 73 61 62 6C + 2814 65 73 20 2F 52 + 2819 41 4D 20 61 6E + 281E 64 20 69 74 0D + 2038 2823 69 73 20 6E 6F db "is not empty. Do you want to" + 2828 74 20 65 6D 70 + 282D 74 79 2E 20 20 + 2832 44 6F 20 79 6F + 2837 75 20 77 61 6E + 283C 74 20 74 6F + 2039 2840 0D 63 6F 6E 74 db EOL,"continue (Y destroys /RAM)?" + 2845 69 6E 75 65 20 + 284A 28 59 20 64 65 + 284F 73 74 72 6F 79 + 2854 73 20 2F 52 41 + 2859 4D 29 3F + 2040 005C RAMQL EQU $-RAMQ + 2041 285C FIXRAM: + 2042 285C GET_FILE_INFO RAMINFO ; get the volumn size + 2043 285C PRODOS $C4, RAMINFO + 2044 285C 20 00 BF jsr $BF00 ; ProDOS handler + 2045 285F C4 DB $C4 ; ProDOS function code + 2046 2860 E827 DW RAMINFO ; Function Parameter Block address + 2047 2862 .MACEND + 2048 2862 .MACEND + 2049 2862 B0 28 bcs FIXR1 ; problem, so we'll just disable it + 2050 + 2051 2864 AD F1 27 lda RAMINFO+9 ; get amount used + 2052 2867 D0 07 bne ASKUSER ; some files there complain + 2053 2869 AD F0 27 lda RAMINFO+8 ; get LSB of used + 2054 286C C9 09 cmp #9 ; if >= 9, must be being used + 2055 286E 90 1C bcc FIXR1 ; no problem, disable /RAM + 2056 2870 ASKUSER: + 2057 2870 20 58 FC jsr MHOME ; clear and home + 2058 2873 DLINE RAMQ ; ask about continuing + 2059 2873 A2 00 ldx #RAMQ ; get other part of string + 2061 [01] IFMA 2 ; check to see if length passed in + 2062 ldy ; then just fetch it + 2063 [01] ELSE + 2064 2877 A0 5C ldy #RAMQL ; get length of string + 2065 [00] ENDIF + 2066 2879 20 D5 26 jsr DLINE ; print the string + 2067 287C .MACEND + 2068 287C 20 0C FD jsr MRDKEY ; get answer + 2069 287F 29 7F and #$7F ; turn off hi bit + 2070 2881 C9 79 cmp #'y' ; check for yes + 2071 2883 F0 07 beq FIXR1 ; then continue + 2072 2885 C9 59 cmp #'Y' ; also, captital Y + 2073 2887 F0 03 beq FIXR1 ; okay again + 2074 2889 4C 19 26 jmp ZQUIT ; so die + 2075 288C FIXR1: + 2076 288C AD 26 BF lda RAMVEC+LO ; get current /RAM vector + 2077 288F 8D 7E 07 sta OLDVEC+LO ; save it for reinstalling + 2078 2892 AD 27 BF lda RAMVEC+HI + 2079 2895 8D 7F 07 sta OLDVEC+HI + 2080 2898 AD 16 BF lda UNSVEC+LO ; point /RAM vector to uninstalled device + Wed Jun 7 1989 12:04 Page 44 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2081 289B 8D 26 BF sta RAMVEC+LO + 2082 289E AD 17 BF lda UNSVEC+HI + 2083 28A1 8D 27 BF sta RAMVEC+HI + 2084 28A4 AE 31 BF ldx DEVCNT ; get how many devices + 2085 28A7 DEVLP: + 2086 28A7 BD 32 BF lda DEVNUM,X ; try to find /RAM device + 2087 28AA 29 70 and #$70 ; isolate slot + 2088 28AC C9 30 cmp #$30 ; look for slot 3 + 2089 28AE F0 04 beq GOTSLT ; got it + 2090 28B0 CA dex ; missed it + 2091 28B1 10 F4 bpl DEVLP ; try again + 2092 28B3 60 rts ; didn't find it (?) + 2093 28B4 GOTSLT: + 2094 28B4 BD 33 BF lda DEVNUM+1,X ; now move all down one + 2095 28B7 9D 32 BF sta DEVNUM,X ; down one + 2096 28BA EC 31 BF cpx DEVCNT ; done yet + 2097 28BD F0 03 beq FIXREX ; ayyup + 2098 28BF E8 inx ; point to next slot + 2099 28C0 D0 F2 bne GOTSLT ; continue on + 2100 28C2 FIXREX: + 2101 28C2 CE 31 BF dec DEVCNT ; one less device, thank you + 2102 28C5 60 rts ; all done + 2103 ; + 2104 ; DO_DSEGS - scan through the disk segment table and point to the + 2105 ; beginning of the segment list for each of the disks in the + 2106 ; file. + 2107 28C6 DO_DSEGS: + 2108 28C6 AD 01 19 lda SEGTBL+SGTDISKS+1 ; get # number disks + 2109 28C9 85 7A sta J ; save in counter + 2110 28CB C6 7A dec J ; we hand hold #1 + 2111 28CD A9 19 lda #>(SEGTBL+SGTCHKS1) ; start off at beginning + 2112 28CF 8D D1 1D sta D1SEG+HI ; here is first one + 2113 28D2 A9 12 lda #<(SEGTBL+SGTCHKS1); and here is LSB + 2114 28D4 8D D0 1D sta D1SEG+LO ; save it + 2115 28D7 AC 17 19 ldy SEGTBL+SGTSEG1+1 ; get number of segs in first disk + 2116 28DA A2 02 ldx #2 ; start at second one + 2117 28DC DODSL: + 2118 28DC BD CE 1D lda DSKSEG-2+LO,X ; get LSB of previous start + 2119 28DF 18 clc ; doing some adding + 2120 28E0 69 08 adc #SGTSEG ; point to start of segment list + 2121 28E2 9D D0 1D sta DSKSEG+LO,X ; save in working segment pointer + 2122 28E5 BD CF 1D lda DSKSEG-2+HI,X ; now work on MSB + 2123 28E8 69 00 adc #0 ; pick up possible carry + 2124 28EA 9D D1 1D sta DSKSEG+HI,X ; and save in new pointer + 2125 28ED ADDLOOP: + 2126 28ED 18 clc ; doing add + 2127 28EE A9 06 lda #6 ; size of segment entry + 2128 28F0 7D D0 1D adc DSKSEG+LO,X ; counting + 2129 28F3 9D D0 1D sta DSKSEG+LO,X ; counting + 2130 28F6 90 03 bcc ADDL1 ; no wrap + 2131 28F8 FE D1 1D inc DSKSEG+HI,X ; add one to hi + 2132 28FB ADDL1: + 2133 28FB 88 dey ; count segment + 2134 28FC D0 EF bne ADDLOOP ; okay, not done yet + 2135 28FE BD D0 1D lda DSKSEG+LO,X ; get pointer to #segs in this one + 2136 2901 85 1E sta DSEGS+LO ; save ptr + 2137 2903 BD D1 1D lda DSKSEG+HI,X ; get MSB + Wed Jun 7 1989 12:04 Page 45 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2138 2906 85 1F sta DSEGS+HI ; save ptr + 2139 2908 A0 05 ldy #SGTNSEG+1 ; just need LSB + 2140 290A B1 1E lda (DSEGS),Y ; get #segs in this segment + 2141 290C A8 tay ; save in counter Y + 2142 290D E8 inx + 2143 290E E8 inx ; point to new pointer loc + 2144 290F C6 7A dec J ; count this disk + 2145 2911 D0 C9 bne DODSL ; and do it again + 2146 ; + 2147 ; now, init DSEGS to point to beginnning again + 2148 ; + 2149 2913 AD D1 1D lda D1SEG+HI ; here is first one + 2150 2916 85 1F sta DSEGS+HI + 2151 2918 AD D0 1D lda D1SEG+LO ; save it + 2152 291B 85 1E sta DSEGS+LO + 2153 ; + 2154 ; check to see if we are using infoDOS, and set pointer to second + 2155 ; disk segment table if we are. + 2156 ; + 2157 291D AD FF BF lda KVERSION ; get "version" number + 2158 2920 C9 FF cmp #INFODOS_ID ; is in our DOS? + 2159 2922 D0 0B bne DODX ; nope, it ain't + 2160 2924 AD D3 1D lda D2SEG+HI ; then have infoDOS flag to point + 2161 2927 85 5A sta INFODOS+HI ; to the D2SEG, cuz that's what + 2162 2929 AD D2 1D lda D2SEG+LO ; we use to check all the ZPC's + 2163 292C 85 59 sta INFODOS+LO + 2164 292E 60 rts + 2165 292F DODX: + 2166 292F A9 00 lda #0 ; regular ProDOS + 2167 2931 85 59 sta INFODOS ; show nothing there! + 2168 2933 60 rts + 2169 + 2170 ; + 2171 ; INITPAG - init the paging buffers, thank you + 2172 ; + 2173 2934 INITPAG: + 2174 2934 A2 17 LDX #NUMBUFS-1 ;*** + 2175 2936 86 CD STX CURRENT ; make last one first one to be used + 2176 2938 C6 CD dec CURRENT ; using only even pages + 2177 293A A9 FF LDA #$FF + 2178 293C INILP: + 2179 293C 9D 80 0C STA VPAGEH,X + 2180 293F CA DEX + 2181 2940 10 FA BPL INILP + 2182 2942 A2 00 LDX #0 + 2183 2944 A0 02 LDY #2 ;*** + 2184 2946 INILP2: + 2185 2946 98 TYA + 2186 2947 9D 40 0C STA PREVPNT,X + 2187 294A E8 INX + 2188 294B E8 inx ;*** + 2189 294C C8 INY + 2190 294D C8 iny ;*** + 2191 294E E0 18 CPX #NUMBUFS + 2192 2950 90 F4 BCC INILP2 + 2193 2952 A9 00 LDA #00 + 2194 2954 CA DEX + Wed Jun 7 1989 12:04 Page 46 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2195 2955 CA dex ;*** + 2196 2956 9D 40 0C STA PREVPNT,X + 2197 2959 A2 00 LDX #0 ;*** + 2198 295B A0 FE LDY #$FE ;*** + 2199 295D A9 16 LDA #NUMBUFS-2 ;*** + 2200 295F INILP3: + 2201 295F 9D 00 0C STA NEXTPNT,X + 2202 2962 E8 INX + 2203 2963 E8 inx ;*** + 2204 2964 C8 iny ;*** + 2205 2965 C8 INY + 2206 2966 98 TYA + 2207 2967 E0 18 CPX #NUMBUFS + 2208 2969 90 F4 BCC INILP3 + 2209 296B 60 rts + 2210 + 2211 ; + 2212 ; DO_PREFIX - check out the program name at $280. If there is a prefix + 2213 ; in there, just set prefix to it, so my default prefix is just fine. + 2214 ; + 2215 296C DO_PREFIX: + 2216 296C AE 80 02 ldx START_NAME ; get length of name + 2217 296F DOPLOOP: + 2218 296F BD 80 02 lda START_NAME,x ; get char + 2219 2972 29 7F and #$7F ; make it real ASCII + 2220 2974 C9 2F cmp #'/' ; directory seperator? + 2221 2976 F0 04 beq DOPLX ; yup, found the prefix + 2222 2978 CA dex ; previous char + 2223 2979 D0 F4 bne DOPLOOP ; go do it + 2224 297B 60 rts ; prefix is just fine as it is + 2225 297C DOPLX: + 2226 297C 8E 80 02 stx START_NAME ; just reuse the name + 2227 297F SET_PREFIX START_PREFIX ; and go set it to this one + 2228 297F PRODOS $C6, START_PREFIX + 2229 297F 20 00 BF jsr $BF00 ; ProDOS handler + 2230 2982 C6 DB $C6 ; ProDOS function code + 2231 2983 8629 DW START_PREFIX ; Function Parameter Block address + 2232 2985 .MACEND + 2233 2985 .MACEND + 2234 2985 60 rts + 2235 2986 START_PREFIX: + 2236 2986 01 DB 1 ; just one parm + 2237 2987 8002 DW START_NAME ; use my start up name + 2238 ; + 2239 ; INIT_CHARSET - move the default charset into lower memory + 2240 ; + 2241 2989 ICHARS: + 2242 2989 61 62 63 64 65 db "abcdefghijklmnopqrstuvwxyz" ; CHARSET 1 + 298E 66 67 68 69 6A + 2993 6B 6C 6D 6E 6F + 2998 70 71 72 73 74 + 299D 75 76 77 78 79 + 29A2 7A + 2243 29A3 41 42 43 44 45 db "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; CHARSET 2 + 29A8 46 47 48 49 4A + 29AD 4B 4C 4D 4E 4F + 29B2 50 51 52 53 54 + Wed Jun 7 1989 12:04 Page 47 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 29B7 55 56 57 58 59 + 29BC 5A + 2244 29BD 00 0D 30 31 32 db 0,EOL,"0123456789.,!?_#'""/\-:()" ; CHARSET 3 + 29C2 33 34 35 36 37 + 29C7 38 39 2E 2C 21 + 29CC 3F 5F 23 27 22 + 29D1 2F 5C 2D 3A 28 + 29D6 29 + 2245 004D ICHARSL EQU $-ICHARS-1 + 2246 + 2247 29D7 INIT_CHARSET: + 2248 29D7 AD 34 96 lda ZBEGIN+ZCHRSET ; see if game has passed one + 2249 29DA 0D 35 96 ora ZBEGIN+ZCHRSET+1 ; well? + 2250 29DD D0 0C bne INITCHG ; yes, so use that one + 2251 29DF A2 4D ldx #ICHARSL + 2252 29E1 INITCL: + 2253 29E1 BD 89 29 lda ICHARS,X ; get char + 2254 29E4 9D 8C 1F sta CHARSET,X ; save char + 2255 29E7 CA dex ; next char + 2256 29E8 10 F7 bpl INITCL ; go get it + 2257 29EA 60 rts + 2258 29EB INITCHG: + 2259 29EB AD 34 96 lda ZBEGIN+ZCHRSET ; get game page + 2260 29EE 20 ED 26 jsr SETPC ; find out where in memory it be + 2261 29F1 85 8D sta FPCH ; save page + 2262 29F3 84 8E sty FPCBNK ; and save the bank + 2263 29F5 AD 35 96 lda ZBEGIN+ZCHRSET+1 ; get the LSB + 2264 29F8 85 8C sta FPCL ; just save it + 2265 29FA A9 4E lda #78 ; 78 characters are in it + 2266 29FC 85 7A sta J ; use J as counter + 2267 29FE A9 00 lda #0 ; set up index + 2268 2A00 85 7C sta K ; in K + 2269 2A02 INCGL: + 2270 2A02 20 14 27 jsr FETCHB ; go get the character + 2271 2A05 A6 7C ldx K ; this is index + 2272 2A07 9D 8C 1F sta CHARSET,X ; save game character + 2273 2A0A 20 38 27 jsr NEXTFPC ; point to next character + 2274 2A0D E6 7C inc K ; point to next storage byte + 2275 2A0F C6 7A dec J ; count character + 2276 2A11 D0 EF bne INCGL ; go get next char + 2277 + 2278 2A13 A9 0D lda #EOL ; make sure EOL is in list + 2279 2A15 A2 35 ldx #53 ; offset of 53 + 2280 2A17 9D 8C 1F sta CHARSET,X ; and away it goes + 2281 + 2282 2A1A 60 rts ; done + 2283 2A1B + 2284 2A1B END + 2285 + 2286 + 2287 PAGE + Wed Jun 7 1989 12:04 Page 48 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2288 2A1B STTL "--- BOOT DATA STRUCTURES ---" + 2289 2A1B INTR_OPEN: + 2290 2A1B 03 DB 3 ; 3 parameters + 2291 2A1C 372A DW INTR_NAME ; name of file + 2292 2A1E 0011 DW GAME1FIO ; file data buffer + 2293 2A20 DS 1 ; refnum goes here + 2294 2A21 CLOSE_BLOCK: + 2295 2A21 01 DB 1 ; 1 parameter + 2296 2A22 DS 2 ; room for ref num + 2297 2A24 PSEEK: + 2298 2A24 02 db 2 ; 2 pararmeters + 2299 2A25 00 db 0 ; refnum + 2300 2A26 00 00 00 db 0,0,0 ; 3 byte new file pos + 2301 2A29 PRELOAD_OPEN: + 2302 2A29 03 DB 3 + 2303 2A2A 3F2A DW PRELOAD_NAME + 2304 2A2C 0011 DW GAME1FIO ; close interpreter first! + 2305 2A2E DS 1 ; refnum here + 2306 ; + 2307 ; start with interpreter data + 2308 ; + 2309 2A2F READ_BLOCK: + 2310 2A2F 04 DB 4 ; 4 parms + 2311 2A30 00 DB 0 ; refnum + 2312 2A31 0040 DW INTR_BEGIN ; where to start the interpreter + 2313 2A33 0056 DW INTR_SIZE ; and how big could it be + 2314 2A35 0000 DW 0 ; actual length of interpreter + 2315 2A37 INTR_NAME: + 2316 2A37 07 DB INAME_LEN ; length of name + 2317 2A38 I_NAME: + 2318 2A38 49 4E 46 4F 43 DB "INFOCOM" ; interpreter name + 2A3D 4F 4D + 2319 0007 INAME_LEN EQU $-I_NAME + 2320 + 2321 2A3F PRELOAD_NAME: + 2322 2A3F 00 DB 0 ; length of name + 2323 2A40 PRE_NAME: + 2324 2A40 DS 20 ; spot for preload name + 2325 0014 PRELEN EQU $-PRE_NAME + 2326 2A54 + 2327 DH_SAVE: ; to actual 'write' the data + 2328 2A54 04 DB 4 ; 4 parms for write + 2329 2A55 00 DB 0 ; refnum goes here + 2330 2A56 0000 DW 0 ; just 'copy' junk + 2331 2A58 00B5 DW RAMSAVE ; to preserve this much mem in AUX + 2332 2A5A 0000 DW 0 ; how much is done + 2333 2A5C + 2334 2A5C 54 68 65 20 73 STRYM: DB "The story is loading ..." + 2A61 74 6F 72 79 20 + 2A66 69 73 20 6C 6F + 2A6B 61 64 69 6E 67 + 2A70 20 2E 2E 2E + 2335 0018 STRYML EQU $-STRYM + 2336 2A74 0D 45 6E 74 65 MMSG: DB EOL,"Enter the letter of the pointing",EOL + 2A79 72 20 74 68 65 + 2A7E 20 6C 65 74 74 + 2A83 65 72 20 6F 66 + Wed Jun 7 1989 12:04 Page 49 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT DATA STRUCTURES ---" + + 2A88 20 74 68 65 20 + 2A8D 70 6F 69 6E 74 + 2A92 69 6E 67 0D + 2337 2A96 64 65 76 69 63 DB "device you will be using:",EOL + 2A9B 65 20 79 6F 75 + 2AA0 20 77 69 6C 6C + 2AA5 20 62 65 20 75 + 2AAA 73 69 6E 67 3A + 2AAF 0D + 2338 2AB0 4A 29 6F 79 73 DB "J)oystick M)ouse N)either",EOL,EOL + 2AB5 74 69 63 6B 20 + 2ABA 20 4D 29 6F 75 + 2ABF 73 65 20 20 4E + 2AC4 29 65 69 74 68 + 2AC9 65 72 0D 0D + 2339 0059 MMSGL EQU $-MMSG + 2340 2ACD 0D 45 6E 74 65 MSLT: DB EOL,"Enter the slot number in which the",EOL + 2AD2 72 20 74 68 65 + 2AD7 20 73 6C 6F 74 + 2ADC 20 6E 75 6D 62 + 2AE1 65 72 20 69 6E + 2AE6 20 77 68 69 63 + 2AEB 68 20 74 68 65 + 2AF0 0D + 2341 2AF1 6D 6F 75 73 65 db "mouse card is installed >" + 2AF6 20 63 61 72 64 + 2AFB 20 69 73 20 69 + 2B00 6E 73 74 61 6C + 2B05 6C 65 64 20 3E + 2342 003D MSLTL EQU $-MSLT + 2343 2B0A 0D 53 6C 6F 74 MSLTBAD: DB EOL,"Slot number must be between",EOL + 2B0F 20 6E 75 6D 62 + 2B14 65 72 20 6D 75 + 2B19 73 74 20 62 65 + 2B1E 20 62 65 74 77 + 2B23 65 65 6E 0D + 2344 2B27 4F 4E 45 20 61 db "ONE and SEVEN! Try again!",EOL + 2B2C 6E 64 20 53 45 + 2B31 56 45 4E 21 20 + 2B36 20 54 72 79 20 + 2B3B 61 67 61 69 6E + 2B40 21 0D + 2345 0038 MSLTBADL EQU $-MSLTBAD + 2346 2B42 0D 56 65 72 73 VERMSG: db EOL,"Version: " + 2B47 69 6F 6E 3A 20 + 2347 000A VERMSGL equ $-VERMSG + 2348 2B4C END + + + + Lines Assembled : 2348 Assembly Errors : 0 + + + \ No newline at end of file diff --git a/apple/yzip/rel.13/brel.asm b/apple/yzip/rel.13/brel.asm new file mode 100644 index 0000000..37052c2 --- /dev/null +++ b/apple/yzip/rel.13/brel.asm @@ -0,0 +1,203 @@ + STTL "--- RELOCATED SUBROUTINES ---" + PAGE + +; +; FETCHB - use FPC to get a byte in either aux or main mem +; +FETCHBx: + sta RDBNK,Y ; set bank, lower + ldy #0 ; gotta use Y + lda (FPC),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; and return +; +; ZFETCH - fetch byte at (ZPCPNT),Y - offset from (ZPCPNT) +; +ZFETCHx: + sta RDBNK,X ; set lower bank + lda (ZPCPNT),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; bye +; +; MFETCH - fetch byte at (MPCPNT),Y - offset from (MPCPNT) +; +MFETCHx: + sta RDBNK,X ; set bank + lda (MPCPNT),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; bye +; +; SAVE_DATA - copy data from [DBUFF] to IOBUFF +; [Y] must == 0; [X] == DSKBNK; [A] == IOBUFF ($8 or $9) +; + sta RDBNK,X ; and select that bank for reading + sta SAVE_DATA+9 ; show which part of iobuff +SDAT1: + lda (DBUFF),Y ; get me that byte +SDAT2: + sta IOBUFF,Y ; MODIFIED ABOVE + iny + bne SDAT1 + sta RDBNK+MAIN ; and back to main + rts +RLCLEN EQU $-FETCHBx-1 ; mark length +; +; COPY_LINE: +; SPC - source pointer +; FPC - destination pointer +; SPCBNK - bank the above two are talking about +; CPY_COUNT - end-start bytes to move +; STMASK - mask to use on first byte (0 if none) +; ENDMASK - mask to use for end byte (0 if none) +; +; MODIFIED CODE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +; The definitions for CPY_MODs are HARD CODED in apple.equ - they MUST +; match the definitions below for similar xCPY_MODs!!!!!!!! +; DON'T CHANGE WITHOUT FIXING THOSE OFFSETS IN APPLE.EQU!!!!! +; +CPYx EQU * + ldx SPCBNK ; set up banks for first byte + lda PAGE2SW,X ; r/w which bank in display mem + ldy #0 ; use Y reg + lda STMASK ; get start mask + beq CPLOOP ; no start mask, start in middle of loop + and (FPC),Y ; turn off changing bits, keep good bits + sta (FPC),Y ; save it + lda STMASK ; get changing bits + eor #$FF ; turn on changing bits + and (SPC),Y ; get SPC byte + ora (FPC),Y ; turn them on in destination too + sta (FPC),Y ; and destiny +CPLOOP: + lda CPY_COUNT ; get count + lsr A ; /2 for number in this bank + tax ; put in X for indexing + beq CPLP2 ; then done! + dex ; zero base the number + lda STMASK ; special start? + beq CPL1 ; nope + inc CPY_MOD1_SRC ; first one already done + inc CPY_MOD1_DST ; point to next one + dex ; and count first one as done +CPL1: + lda SCREEN,X ; get byte + sta SCREEN,X ; store byte + dex ; count down + bpl CPL1 ; and do it all again +CPLP2: + ldy #0 ; reset y + lda SPCBNK ; get current bank + eor #1 ; toggle to point to the other one + tax + lda PAGE2SW,X + txa ; which bank? + beq CPLP21 ; we are now in main, things are fine + inc CPY_MOD2_SRC ; start one more if now in AUX + inc CPY_MOD2_DST + dex ; and count as done +CPLP21: + lda CPY_COUNT ; get count again + lsr A ; /2 for bytes in this bank + tax ; put in X for counter + beq CPDONE ; nothing here + dex ; zero base the number +CPL2: + lda SCREEN,X ; get byte + sta SCREEN,X ; store byte + dex ; count byte + bpl CPL2 ; and swing by again +CPDONE: + lda ENDMASK ; do same mucking as when starting + beq CPEXIT ; no mucking + pha ; save endmask + lda CPY_COUNT ; get how many bytes being copied + lsr A ; /2 + bcs CPDONE1 ; if odd, then we are pointing to correct + pha ; save a + ldx SPCBNK ; get original bank + lda PAGE2SW,X ; and point to it + pla ; get it back +CPDONE1: + tay ; get offset + pla ; get end mask back + eor #$FF ; turn on all off bits + and (FPC),Y ; turn off changing bits + sta (FPC),Y ; save it + lda (SPC),Y ; get source byte + and ENDMASK ; turn on changing bits + ora (FPC),Y ; turn them on in destination too + sta (FPC),Y ; and destiny +CPEXIT: + lda PAGE2SW ; set back to main mem + rts +CPYLEN EQU $-CPYx-1 +xCPY_MOD1 equ (CPL1-CPYx+1) +xCPY_MOD1_DST equ xCPY_MOD1+3 +xCPY_MOD2 equ (CPL2-CPYx+1) +xCPY_MOD2_DST equ xCPY_MOD2+3 +PAGE3REL: +; +; MOUSER - this vectors the call to the correct place +; +MOUSERx: + pha ; save A for a sec +MSX1: lda MTABLE,X ; get lo part of address + sta MSVECTOR+LO ; save lo part of address + pla ; get A back + nop +MSX2: ldx #$C4 ; might be changed, depending on slot +MSX3: ldy #$40 ; hopefully, this doesn't + jmp (MSVECTOR) ; and away we go +MSRxLEN EQU $-MOUSERx-1 ; show how long this is +MSVECTORx: + ds 1 ; where lo part of vector goes +MSX4: db $C4 ; slot where mouse is +MSRLEN EQU $-MOUSERx-1 ; length or routine +; +; colors for screen lines +; + RADIX H +COLORSx: + db 00,00,00,00 ; black + db 08,11,22,44 ; magenta + db 44,08,11,22 ; brown + db 4C,19,33,66 ; orange + db 22,44,08,11 ; dark green + db 2A,55,2A,55 ; gray 1 + db 66,4C,19,33 ; green + db 6E,5D,3B,77 ; yellow + db 11,22,44,08 ; dark blue + db 19,33,66,4C ; purple + db 55,2A,55,2A ; gray 2 + db 5D,3B,77,6E ; pink + db 33,66,4C,19 ; medium blue + db 3B,77,6E,5D ; light blue + db 77,6E,5D,3B ; aqua + db 7F,7F,7F,7F ; white +XPOSTBLx: + DB 0 + DB 0,1,1,2,2,3,4 + DB 4,5,5,6,6,7,8 + DB 8,9,9,0a,0a,0b,0c + DB 0c,0d,0d,0e,0e,0f,10 + DB 10,11,11,12,12,13,14 + DB 14,15,15,16,16,17,18 + DB 18,19,19,1a,1a,1b,1c + DB 1c,1d,1d,1e,1e,1f,20 + DB 20,21,21,22,22,23,24 + DB 24,25,25,26,26,27,28 + DB 28,29,29,2a,2a,2b,2c + DB 2c,2d,2d,2e,2e,2f,30 + DB 30,31,31,32,32,33,34 + DB 34,35,35,36,36,37,38 + DB 38,39,39,3a,3a,3b,3c + DB 3c,3d,3d,3e,3e,3f,40 + DB 40,41,41,42,42,43,44 + DB 44,45,45,46,46,47,48 + DB 48,49,49,4a,4a,4b,4c + DB 4c,4d,4d,4e,4e,4f,50 + RADIX D +PAGE3RELL EQU $-PAGE3REL-1 + END + + diff --git a/apple/yzip/rel.13/bsubs.asm b/apple/yzip/rel.13/bsubs.asm new file mode 100644 index 0000000..8dd9d7e --- /dev/null +++ b/apple/yzip/rel.13/bsubs.asm @@ -0,0 +1,584 @@ + PAGE + STTL "--- BOOT CODE SUBROUTINES ---" + +ERRM: DB EOL,EOL + DB "Internal error " +ENUMB: DB "00" + DB "00. " +ERRML EQU $-ERRM +HCHARS: DB "0123456789ABCDEF" +; +; ZERROR: print out error code in HexWord: [A][Y]. +; +ZERROR: + pha ; save [A] + tya ; and put y to a for figgering + ldy #3 ; CONVERT ERROR BYTE IN [A] +ZERR0: + pha + and #%00001111 + tax + lda HCHARS,X + sta ENUMB,Y + pla + LSR A + LSR A + lsr A + lsr A + tax + lda HCHARS,X + dey + sta ENUMB,Y + beq ZR1 ; done + + pla ; done with first number + dey ; and point one more down + jmp ZERR0 ; so work on second number +ZR1: + ldx #ERRM + ldy #ERRML + jsr DLINE ; PRINT ERROR MESSAGE + jsr GETRET ; wait for + jmp ZQUIT + +RETQ: db EOL,"Please insert new disk to boot." + db EOL, "And hit RETURN when ready.",EOL +RETQL EQU $-RETQ +GETRET: + DLINE RETQ ; ask for return +GETRETL: + lda KBD ; get a key + bpl GETRETL ; no key + and #$7f ; make a good key + cmp #EOL ; return key? + bne GETRETL ; nope + jsr MCOUT ; show the + rts + + + ; ---- + ; QUIT + ; ---- + +ZQUIT: + lda INFODOS ; in dinky-dos? + beq ZQUIT2 ; nope + lda #0 ; clear power up byte + sta $3F4 ; make it do cold boot + lda RESET_VECTOR+HI ; now, set up where to die to + sta ZQUITR1+2 + lda RESET_VECTOR+LO + sta ZQUITR1+1 + lda RDROM ; get ROM back +ZQUITR1: + jmp RESET_VECTOR ; just reset things +; +; re-enable /RAM +; +ZQUIT2: + ldx DEVCNT ; put device in at end + inx ; point to one past end + stx DEVCNT ; show new count + lda #$BF ; /RAM ID + sta DEVNUM,X ; save it + lda OLDVEC+HI ; restore old vector + sta RAMVEC+HI + lda OLDVEC+LO + sta RAMVEC+LO +; +; now format /RAM +; + lda #3 ; stash into FORMAT parm block + sta $42 ; it goes here, oddly enough + lda #$B0 ; device id for /RAM + sta $43 ; and here it goes + lda #>GAME1FIO ; IO buffer + sta $45 ; this is where it goes + lda #ZBEGIN ; ADD OFFSET TO GET RAM PAGE + ldy #MAIN ; in the main bank + beq VFEXI ; BRA to fetch +VF2: + cmp #PGBEGIN ; is it paged? + bcs VFERR ; yes it be paged, so can't deal with it + cmp #P3PAGE ; is it in Aux Mem, Part 2? + bcs VF3 ; yes, so subtract different amount +; +; this is in lower aux +; + lda #(Z2PAGE-Z1SIZE) ; subtract size from offset + ldy #AUX ; show aux mem + bne VFEXI ; jump to end +VF3: + lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides + ldy #P3BANK ; show page 3 bank +VFEXI: + clc ; get ready for addition + adc MEMPAGE ; now get actual offset + rts +VFERR: +; +; out of range +; + lda #$22 + jmp ZERROR + +; +; FETCHB - fetch a byte from either main memory, aux memory, or upper +; Aux memory +; +FETCHB: + ldy FPCBNK ; get the bank + bmi FB1 ; must be in upper RAM + jmp ZERO_FB ; go to low end fetch +; +; this is in aux mem, >$E000 +; +FB1: + lda FPCH ; get which page + sta FBMOD+2 ; and show in operand + ldy FPCL ; get which byte + sta ALTZP+AUX ; talk about aux mem + lda BNK1SET ; set up read/write ram in upper mem + lda BNK1SET ; set up read/write ram in upper mem +FBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + ldx RDROM ; now use ROM please + ldx RDROM ; now use ROM please + rts +; +; NEXTFPC - inc DPCL and check for wrapping round to next bank +; +NEXTFPC: + inc FPCL ; next lo byte + bne NXFP_EXIT ; no change then + inc FPCH ; next page + lda FPCH ; and get it for checking + cmp #>PRGLBL ; have we reached end of line? + bne NXFP_EXIT ; we be okay + lda FPCBNK ; get bank + bne NXFP1 ; must skip over stuff in middle + inc FPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta FPCH ; and point to it + rts ; toots finis +NXFP1: + lda #Z3PAGE ; start of part 3 + sta FPCH ; so show me + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey +NXFP_EXIT: + rts +; +; INST_MOUSE - install mouse handler IRQ +; +MFIX1 EQU (MSX1-MOUSERx)+PAGE3STUFF+2 +MFIX2 EQU (MSX2-MOUSERx)+PAGE3STUFF+1 +MFIX3 EQU (MSX4-MOUSERx)+PAGE3STUFF +MFIX4 EQU (MSX3-MOUSERx)+PAGE3STUFF+1 +INST_MOUSE: + jsr FINDMOUSE ; find which slot the mouse is in + bcc INMS1 ; everything is fine + rts ; can't find the mouse +INMS1: + sta MFIX1 + sta MFIX2 + sta MFIX3 ; okay, everyone knows now + and #$0f ; pick up low byte + sta ARG1+LO ; save for program to pick up + asl A ; shift slot number to upper nybble + asl A + asl A + asl A + sta MFIX4 ; and save here +; +; now init mouse, please +; + ldx #INITM ; init first + jsr MOUSER ; so do it + ldx #SETM ; setup mouse + lda #$01 ; transparent mode + jsr MOUSER ; we do that + ldx #CLEARM ; and clear mouse pos + jsr MOUSER ; we did +; +; now set min and max for clamping. +; 0 <= xpos <= 139 +; 0 <= ypos <= 191 +; + lda #0 ; zero out a few of the things + sta CLMPMINH ; hi part of min clamp + sta CLMPMINL ; lo part of min clamp + lda #<137 ; max X + sta CLMPMAXL ; stash in lo part + lda #>137 ; max X + sta CLMPMAXH ; hi part of clamp + lda #0 ; show setting X clamp + ldx #CLAMPM ; do clamping + jsr MOUSER ; okay, we did + lda #<189 ; now for Y + sta CLMPMAXL ; saved in lo part + lda #>189 ; now for Y + sta CLMPMAXH ; saved in lo part + lda #1 ; set y boundries + ldx #CLAMPM ; okay, show which routine + jsr MOUSER ; and do it + +; +; initialize the mouse position +; + lda #0 ; clear MSB + sta MOUSEXH + sta MOUSEYH + lda #MAXHEIGHT + sta MOUSEYL + lda #MAXWIDTH + sta MOUSEXL + + ldx #POSM + jsr MOUSER ; and move it + +; cli ; enable interrupts now + lda #$FF ; < 0 show mouse + sta MOUSEF ; so show it + clc ; show everything is fine + rts ; done +; +; FINDMOUSE - scan the slots for a mouse +; +FINDMOUSE: + lda $C1FB ; check for mouse ID == D6 + cmp #$D6 ; mouse ID + bne FNDM1 ; not it + lda FINDMOUSE+2 ; get slot + clc ; show okay-ness + rts ; and return +FNDM1: + inc FINDMOUSE+2 ; point to next slot + lda FINDMOUSE+2 ; reached last one yet? + cmp #$C8 ; no slot eight + bcc FINDMOUSE ; go look again + sec ; show no mouse + rts +; +; INST_STICK - install the joystick handler +INST_STICK: + lda #$1 ; > 0 show joystick + sta MOUSEF ; okay, we do + clc ; show it worked + rts +RAMINFO: + db 10 ; 10 parms + dw RAMNAME ; name + ds 15 ; room for stuff +RAMNAME: + db 5 ; length of name + db "/RAM/" ; name +RAMQ: db EOL,"This program disables /RAM and it",EOL + db "is not empty. Do you want to" + db EOL,"continue (Y destroys /RAM)?" +RAMQL EQU $-RAMQ +FIXRAM: + GET_FILE_INFO RAMINFO ; get the volumn size + bcs FIXR1 ; problem, so we'll just disable it + + lda RAMINFO+9 ; get amount used + bne ASKUSER ; some files there complain + lda RAMINFO+8 ; get LSB of used + cmp #9 ; if >= 9, must be being used + bcc FIXR1 ; no problem, disable /RAM +ASKUSER: + jsr MHOME ; clear and home + DLINE RAMQ ; ask about continuing + jsr MRDKEY ; get answer + and #$7F ; turn off hi bit + cmp #'y' ; check for yes + beq FIXR1 ; then continue + cmp #'Y' ; also, captital Y + beq FIXR1 ; okay again + jmp ZQUIT ; so die +FIXR1: + lda RAMVEC+LO ; get current /RAM vector + sta OLDVEC+LO ; save it for reinstalling + lda RAMVEC+HI + sta OLDVEC+HI + lda UNSVEC+LO ; point /RAM vector to uninstalled device + sta RAMVEC+LO + lda UNSVEC+HI + sta RAMVEC+HI + ldx DEVCNT ; get how many devices +DEVLP: + lda DEVNUM,X ; try to find /RAM device + and #$70 ; isolate slot + cmp #$30 ; look for slot 3 + beq GOTSLT ; got it + dex ; missed it + bpl DEVLP ; try again + rts ; didn't find it (?) +GOTSLT: + lda DEVNUM+1,X ; now move all down one + sta DEVNUM,X ; down one + cpx DEVCNT ; done yet + beq FIXREX ; ayyup + inx ; point to next slot + bne GOTSLT ; continue on +FIXREX: + dec DEVCNT ; one less device, thank you + rts ; all done +; +; DO_DSEGS - scan through the disk segment table and point to the +; beginning of the segment list for each of the disks in the +; file. +DO_DSEGS: + lda SEGTBL+SGTDISKS+1 ; get # number disks + sta J ; save in counter + dec J ; we hand hold #1 + lda #>(SEGTBL+SGTCHKS1) ; start off at beginning + sta D1SEG+HI ; here is first one + lda #<(SEGTBL+SGTCHKS1); and here is LSB + sta D1SEG+LO ; save it + ldy SEGTBL+SGTSEG1+1 ; get number of segs in first disk + ldx #2 ; start at second one +DODSL: + lda DSKSEG-2+LO,X ; get LSB of previous start + clc ; doing some adding + adc #SGTSEG ; point to start of segment list + sta DSKSEG+LO,X ; save in working segment pointer + lda DSKSEG-2+HI,X ; now work on MSB + adc #0 ; pick up possible carry + sta DSKSEG+HI,X ; and save in new pointer +ADDLOOP: + clc ; doing add + lda #6 ; size of segment entry + adc DSKSEG+LO,X ; counting + sta DSKSEG+LO,X ; counting + bcc ADDL1 ; no wrap + inc DSKSEG+HI,X ; add one to hi +ADDL1: + dey ; count segment + bne ADDLOOP ; okay, not done yet + lda DSKSEG+LO,X ; get pointer to #segs in this one + sta DSEGS+LO ; save ptr + lda DSKSEG+HI,X ; get MSB + sta DSEGS+HI ; save ptr + ldy #SGTNSEG+1 ; just need LSB + lda (DSEGS),Y ; get #segs in this segment + tay ; save in counter Y + inx + inx ; point to new pointer loc + dec J ; count this disk + bne DODSL ; and do it again +; +; now, init DSEGS to point to beginnning again +; + lda D1SEG+HI ; here is first one + sta DSEGS+HI + lda D1SEG+LO ; save it + sta DSEGS+LO +; +; check to see if we are using infoDOS, and set pointer to second +; disk segment table if we are. +; + lda KVERSION ; get "version" number + cmp #INFODOS_ID ; is in our DOS? + bne DODX ; nope, it ain't + lda D2SEG+HI ; then have infoDOS flag to point + sta INFODOS+HI ; to the D2SEG, cuz that's what + lda D2SEG+LO ; we use to check all the ZPC's + sta INFODOS+LO + rts +DODX: + lda #0 ; regular ProDOS + sta INFODOS ; show nothing there! + rts + +; +; INITPAG - init the paging buffers, thank you +; +INITPAG: + LDX #NUMBUFS-1 ;*** + STX CURRENT ; make last one first one to be used + dec CURRENT ; using only even pages + LDA #$FF +INILP: + STA VPAGEH,X + DEX + BPL INILP + LDX #0 + LDY #2 ;*** +INILP2: + TYA + STA PREVPNT,X + INX + inx ;*** + INY + iny ;*** + CPX #NUMBUFS + BCC INILP2 + LDA #00 + DEX + dex ;*** + STA PREVPNT,X + LDX #0 ;*** + LDY #$FE ;*** + LDA #NUMBUFS-2 ;*** +INILP3: + STA NEXTPNT,X + INX + inx ;*** + iny ;*** + INY + TYA + CPX #NUMBUFS + BCC INILP3 + rts + +; +; DO_PREFIX - check out the program name at $280. If there is a prefix +; in there, just set prefix to it, so my default prefix is just fine. +; +DO_PREFIX: + ldx START_NAME ; get length of name +DOPLOOP: + lda START_NAME,x ; get char + and #$7F ; make it real ASCII + cmp #'/' ; directory seperator? + beq DOPLX ; yup, found the prefix + dex ; previous char + bne DOPLOOP ; go do it + rts ; prefix is just fine as it is +DOPLX: + stx START_NAME ; just reuse the name + SET_PREFIX START_PREFIX ; and go set it to this one + rts +START_PREFIX: + DB 1 ; just one parm + DW START_NAME ; use my start up name +; +; INIT_CHARSET - move the default charset into lower memory +; +ICHARS: + db "abcdefghijklmnopqrstuvwxyz" ; CHARSET 1 + db "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; CHARSET 2 + db 0,EOL,"0123456789.,!?_#'""/\-:()" ; CHARSET 3 +ICHARSL EQU $-ICHARS-1 + +INIT_CHARSET: + lda ZBEGIN+ZCHRSET ; see if game has passed one + ora ZBEGIN+ZCHRSET+1 ; well? + bne INITCHG ; yes, so use that one + ldx #ICHARSL +INITCL: + lda ICHARS,X ; get char + sta CHARSET,X ; save char + dex ; next char + bpl INITCL ; go get it + rts +INITCHG: + lda ZBEGIN+ZCHRSET ; get game page + jsr SETPC ; find out where in memory it be + sta FPCH ; save page + sty FPCBNK ; and save the bank + lda ZBEGIN+ZCHRSET+1 ; get the LSB + sta FPCL ; just save it + lda #78 ; 78 characters are in it + sta J ; use J as counter + lda #0 ; set up index + sta K ; in K +INCGL: + jsr FETCHB ; go get the character + ldx K ; this is index + sta CHARSET,X ; save game character + jsr NEXTFPC ; point to next character + inc K ; point to next storage byte + dec J ; count character + bne INCGL ; go get next char + + lda #EOL ; make sure EOL is in list + ldx #53 ; offset of 53 + sta CHARSET,X ; and away it goes + + rts ; done + + END + diff --git a/apple/yzip/rel.13/bugger.asm b/apple/yzip/rel.13/bugger.asm new file mode 100644 index 0000000..bde7b6e --- /dev/null +++ b/apple/yzip/rel.13/bugger.asm @@ -0,0 +1,257 @@ + PAGE + SBTTL "--- DEBUGGER: APPLE ---" + + ; -------------- + ; APPLE DEBUGGER + ; -------------- + + ; ENTRY: BREAKPOINT ID IN [A] + + ; SMALL DEBUGGER DBG1 (CONVERTS) DBG2 (JUST DISPLAYS) [A] + +DLCNT: DB 0 + +DBG1: + INC DLCNT + BNE DBG1m + PHA + JSR GETKEY + PLA +DBG1m: + PHA + LSR A + LSR A + LSR A + LSR A + JSR NIB1 + PLA + +NIB1: AND #%00001111 + TAY + LDA HCHARS,Y + JSR MCOUT + RTS + +DBG2: +; CMP #' ' +; BEQ DBG3 +; JSR MCOUT +; LDA #' ' +DBG3: JSR MCOUT + RTS + +HCHARS: DB "0123456789ABCDEF" + + END + +BLINE: DB "B: OP: PC: S: V: 1: 2: 3: 4: 5: 6: 7: 8: 9: " + DB EOL +BLINL EQU $-BLINE + +BUGLIN EQU LSTLNE + +DOBUG: LDX KBD ; WAS CTRL-S PRESSED? + CPX #$13 + BNE DO1 + RTS ; YES, SO LEAVE + +DO1: CMP #0 + BEQ BUGIT + RTS + + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + +BUGIT: LDX #2 ; INIT "CURSOR" + 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 BLINE,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 [ZSP] + LDA ZSP + JSR HEX + + LDX #29 ; CURSOR FOR [MPC] + LDA MPCH + JSR HEX + LDA MPCM + JSR HEX + LDA MPCL + JSR HEX + + LDX #38 + LDA BONE + JSR HEX + + LDX #43 + LDA BTWO + JSR HEX + + LDX #48 + LDA BTHREE + JSR HEX + + LDX #53 + LDA BFOUR + JSR HEX + + LDX #58 + LDA BFIVE + JSR HEX + + LDX #63 + LDA BSIX + JSR HEX + + LDX #68 + LDA BSEVEN + JSR HEX + + LDX #73 + LDA BEIGHT + JSR HEX + + LDX #78 + LDA BNINE + JSR HEX + +; TO SEND TO PRINTER IF WANTED +; LDA CSW+LO +; PHA +; LDA CSW+HI +; PHA +; LDA EH +; PHA +; LDA ALTCSW+LO +; STA CSW+LO +; LDA ALTCSW+HI +; STA CSW+HI +; +; LDA PSTAT +; BNE PPP +; +; LDA #$C1 +; STA CSW+HI +; LDA #$00 +; STA CSW+LO +; +; LDA #$89 +; JSR MCOUT +; LDA CSW+HI +; STA ALTCSW+HI +; LDA CSW+LO +; STA ALTCSW+LO +; LDA #$B8 +; JSR MCOUT +; LDA #$B0 +; JSR MCOUT +; LDA #$CE +; JSR MCOUT +; LDA #$8D +; JSR MCOUT + +PPP: LDX #2 +DBUG1: LDA BLINE,X ; PRINT DEBUGGER TEXT +; JSR MCOUT + JSR CHAR + INX + CPX #BLINL + BCC DBUG1 + +; PLA +; STA EH +; PLA +; STA CSW+HI +; PLA +; STA CSW+LO + +; BIT KBD +; BPL LETEX ; NO KEY PRESSED + + BIT ANYKEY ; CLEAR IT +BUGWAT: BIT KBD ; WAIT FOR A KEY + BPL BUGWAT + + LDA KBD + CMP #$8D + BNE LETEX + BRK + +LETEX: BIT ANYKEY ; CLEAR FOR NEXT ONE + 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 + ORA #%10000000 + STA BLINE,X + INX + RTS + +HCHARS: DB "0123456789ABCDEF" + +BONE: DB 0 +BTWO: DB 0 +BTHREE: DB 0 +BFOUR: DB 0 +BFIVE: DB 0 +BSIX: DB 0 +BSEVEN: DB 0 +BEIGHT: DB 0 +BNINE: DB 0 + + END + + \ No newline at end of file diff --git a/apple/yzip/rel.13/dispatch.asm b/apple/yzip/rel.13/dispatch.asm new file mode 100644 index 0000000..17f2bcc --- /dev/null +++ b/apple/yzip/rel.13/dispatch.asm @@ -0,0 +1,281 @@ + PAGE + STTL "--- OPCODE DISPATCH TABLES ---" + + + ; 0-OPS + +OPT0H: DB >ZRTRUE ;B0 + DB >ZRFALS ;B1 + DB >ZPRI ;B2 + DB >ZPRR ;B3 + DB >ZNOOP ;B4 + DB >OSAVE ;B5 + DB >OREST ;B6 + DB >ZSTART ;B7 + DB >ZRSTAK ;B8 + DB >ZCATCH ;B9 + DB >ZQUIT ;BA + DB >ZZCRLF ;BB + DB >ZUSL ;BC + DB >ZVER ;BD + DB >ZEXTOP ;BE + DB >ZORIG ;BF + +OPT0L: DB ZZERO ;80,90,A0 + DB >ZNEXT ;81 + DB >ZFIRST ;82 + DB >ZLOC ;83 + DB >ZPTSIZ ;84 + DB >ZINC ;85 + DB >ZDEC ;86 + DB >ZPRB ;87 + DB >ZCALL1 ;88 (EZIP) + DB >ZREMOV ;89 + DB >ZPRD ;8A + DB >ZRET ;8B + DB >ZJUMP ;8C + DB >ZPRINT ;8D + DB >ZVALUE ;8E + DB >ZICLL1 ;8F + +OPT1L: DB BADOP2 ;00 (UNDEFINED) + DB >ZEQUAL ;01 + DB >ZLESS ;02 + DB >ZGRTR ;03 + DB >ZDLESS ;04 + DB >ZIGRTR ;05 + DB >ZIN ;06 + DB >ZBTST ;07 + DB >ZBOR ;08 + DB >ZBAND ;09 + DB >ZFSETP ;0A + DB >ZFSET ;0B + DB >ZFCLR ;0C + DB >ZSET ;0D + DB >ZMOVE ;0E + DB >ZGET ;0F + DB >ZGETB ;10 + DB >ZGETP ;11 + DB >ZGETPT ;12 + DB >ZNEXTP ;13 + DB >ZADD ;14 + DB >ZSUB ;15 + DB >ZMUL ;16 + DB >ZDIV ;17 + DB >ZMOD ;18 + DB >ZCALL2 ;19 (EZIP) + DB >ZICLL2 ;1A + DB >ZCOLOR ;1B + DB >ZTHROW ;1C + DB >BADOP2 ;1D + DB >BADOP2 ;1E + DB >BADOP2 ;1F + +OPT2L: DB ZCALL ;E0 + DB >ZPUT ;E1 + DB >ZPUTB ;E2 + DB >ZPUTP ;E3 + DB >ZREAD ;E4 + DB >ZPRC ;E5 + DB >ZPRN ;E6 + DB >ZRAND ;E7 + DB >ZPUSH ;E8 + DB >ZPOP ;E9 + DB >ZSPLIT ;EA + DB >ZSCRN ;EB + + ; (EZIPS FROM HERE ON) + DB >ZXCALL ;EC + DB >ZCLR ;ED + DB >ZERASE ;EE + DB >ZCURST ;EF + DB >ZCURGT ;F0 + DB >ZLIGHT ;F1 + DB >ZBUFOUT ;F2 + DB >ZDIRT ;F3 + DB >ZDIRIN ;F4 (NOT IMPLEMENTED) + DB >ZSOUND ;F5 + DB >ZINPUT ;F6 + DB >ZINTBL ;F7 + DB >ZBCOM ;F8 + DB >ZICALL ;F9 + DB >ZIXCLL ;FA + DB >ZLEX ;FB + DB >ZWSTR ;FC + DB >ZCOPYT ;FD + DB >ZPRNTT ;FE + DB >ZASSND ;FF + +OPTXL: DB ZSAVE ;100 + DB >ZREST ;101 + DB >ZSHIFT ;102 + DB >ZASHFT ;103 + DB >ZFONT ;104 + DB >ZDISPL ;105 + DB >ZPICNF ;106 + DB >ZDCLR ;107 + DB >ZMARG ;108 + DB >ZISAVE ;109 + DB >ZIREST ;10A + DB >BADEXT ;10B - NOT USED + DB >BADEXT ;10C - NOT USED + DB >BADEXT ;10D - NOT USED + DB >BADEXT ;10E - NOT USED + DB >BADEXT ;10F - NOT USED + DB >ZWINPOS ;110 + DB >ZWINSIZE ;111 + DB >ZWINATTR ;112 + DB >ZWINGET ;113 + DB >ZSCROLL ;114 + DB >ZFSTACK ;115 + DB >ZMINFO ;116 + DB >ZMLIMIT ;117 + DB >ZXPUSH ;118 + DB >ZWINPUT ;119 + DB >ZPRINTF ;11A + DB >ZMENU ;11B + DB >ZPICSET ;11c + +EXTLEN EQU $-EXTOPH + +EXTOPL: DB + lda INFODOS ; in dinky-dos? + beq ZQUIT2 ; nope + lda #0 ; clear power up byte + sta $3F4 ; make it do cold boot + lda RESET_VECTOR+HI ; now, set up where to die to + sta ZQUITR1+2 + lda RESET_VECTOR+LO + sta ZQUITR1+1 + lda RDROM ; get ROM back +ZQUITR1: + jmp RESET_VECTOR ; just reset things +; +; re-enable /RAM +; +ZQUIT2: + ldx DEVCNT ; put device in at end + inx ; point to one past end + stx DEVCNT ; show new count + lda #$BF ; /RAM ID + sta DEVNUM,X ; save it + lda OLDVEC+HI ; restore old vector + sta RAMVEC+HI + lda OLDVEC+LO + sta RAMVEC+LO +; +; now format /RAM +; + lda #3 ; stash into FORMAT parm block + sta $42 ; it goes here, oddly enough + lda #$B0 ; device id for /RAM + sta $43 ; and here it goes + lda #>GAME1FIO ; IO buffer + sta $45 ; this is where it goes + lda #BOOTNAME + sta OPEN_FILE+OP_PATHNAME+HI + lda #'1' ; set disk name to disk #1 + sta SAVENUM ; show open_gamef + jsr OPEN_GAMEF ; okay + + lda OPEN_FILE+OP_REFNUM ; get ref num + sta BOOT_RD+RD_REFNUM ; save ref num + sta CLOSE_PB+CL_REFNUM + READ BOOT_RD ; read in boot system + bcc ZSTRTX ; okay, everything is fine + jmp DISK_FATAL ; die otherwise +ZSTRTX: + CLOSE CLOSE_PB ; and close it up + jmp BORG ; and go to it + + ; -------------------------------- + ; RETURN RANDOM BYTES IN [A] & [X] + ; -------------------------------- +RANDOM: + inc RAND+HI + dec RAND+LO + lda RAND+LO ; get LSB + adc RAND+HI ; add MSB + and #$7F ; don't let it go into $C0 page + sta RAND+HI ; new MSB + tay ; get random offset + lda (RAND),Y ; get random number + tax ; save in X + adc RAND+LO ; and go to another spot + and #$7F ; don't go above $80 + sta RAND+HI ; okay + tay ; more randomness + lda (RAND),Y ; and get it again + ora RAND+HI ; set more bits + rts + + + ; ------------------- + ; Z-PRINT A CHARACTER + ; ------------------- + ; ENTRY: ASCII CHAR IN [A] + ; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, + ; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN + ; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME + ; (DIROUT CHANGES 6/24/85) + +COUT: + sta IOCHAR ; HOLD IT A SEC + ldx TABLEF ; OUTPUT TO TABLE? + beq COUT1 ; NO + ldx FMTTBL ; formatted table? + bne COUT5 ; yes, so just do it normal + jmp TBLOUT ; just put into table +COUT1: + ldx SCREENF ; OUTPUT TO SCREEN? + bne COUT5 ; YES + ldx SCRIPTF ; OUTPUT TO PRINTER? + bne COUT5 ; YES + rts ; NO, SO DONE +COUT5: + lda IOCHAR ; RETRIEVE CHAR + bmi COUT2 ; highlight chars have no width +; +; this is an entry point for DLINE, so it doesn't check any of the above +; things. Enter with character in [A] +; +DIRECT_OUT: + cmp #EOL ; IF ASCII EOL, just handle it special + bne COUT0 + + jmp ZCRLF ; DO IT +COUT0: + bcs COUT02 ; not control character + cmp #EOS ; control-k (end of sentence)? + beq COUT01 ; yes, so put out 2 spaces + cmp #TAB ; tab char? + bne CEX ; ignore all other control chars +; +; this means do a couple of spaces +; + lda #SPACE ; do 3 spaces for start of line + jsr COUT ; a little recursion never hurt! + ldx CHRCNT ; back to beginning of line? + bne COUT01 ; nope +COUT010: + rts ; don't do any to start line +COUT01: + lda #SPACE ; 2 more spaces + jsr COUT + ldx CHRCNT ; back to zero? + beq COUT010 ; yes, so don't add to start of line + + lda #SPACE ; last one + jmp COUT ; finally +COUT02: + tax ; use char as index + lda FONTFLG ; get which font we be using + beq COUTF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne COUTF2 ; okay, now do add +COUTF1: + lda CHWID,X ; get width of char +COUTF2: + clc ; get ready for add + adc LENGTH+LO ; ADD LINE LENGTH COUNTER + sta LENGTH+LO ; update length + bcc COUT0C ; no wrap + inc LENGTH+HI ; okay, wrap then +COUT0C: + lda LENGTH+HI ; get MSB + cmp XSIZE+HI ; check MSB first + bcc COUT2 ; no need to check lsb + bne COUT00 ; XSIZE < LENGTH? + + lda LENGTH+LO ; check LSB + cmp XSIZE+LO ; END OF SCREEN LINE? + bcc COUT2 ; haven't reached the end if XSIZE > LENGTH +COUT00: + ldy WRPFLG ; are we wrapping + beq CEX ; no, so truncate + ldx CHRCNT ; get character count + lda IOCHAR ; get the character + sta LBUFF,X ; save current char in buffer + jmp FLUSH ; YES, FLUSH THE LINE +COUT2: + ldx CHRCNT ; GET LINE POINTER + lda IOCHAR ; get char back + sta LBUFF,X ; ADD CHAR TO BUFFER + inc CHRCNT ; and point to next CHRCNT +CEX: + rts + + ; --------------- + ; OUTPUT TO TABLE + ; --------------- +; +; this one just puts a char into the table +; +TBLOUT: + tax ; HOLD CHAR A SEC. +; +; figger out length of line in there +; + lda FONTFLG ; get which font we be using + beq TBLOUT1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne TBLOUT2 ; okay, now do add +TBLOUT1: + lda CHWID,X ; get width of char +TBLOUT2: + clc ; add width + adc ZBEGIN+ZTWIDTH+1 ; to current line width + sta ZBEGIN+ZTWIDTH+1 ; save current width + bcc TBLOUT3 ; no wrap + inc ZBEGIN+ZTWIDTH+0 ; wrap, then dammit +TBLOUT3: +; +; PUT BYTE IN TABLE AT CURRENT OFFSET +; + lda DIRITM+LO ; ADD IN OFFSET + clc + adc DIRTBL+LO + sta SPCL ; and make it lo part + lda DIRITM+HI + adc DIRTBL+HI + jsr SETPC ; set the PC + sta SPCH ; and this is high part + sty SPCBNK ; and the bank + txa ; PICK UP ASCII CHAR + jsr STASHB ; and save it +; +; SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER +; + inc DIRITM+LO ; INC OFFSET TO NEXT BYTE + bne TBLRTS + inc DIRITM+HI +TBLRTS: + rts +; +; PUT LBUFF IN TABLE AT CURRENT OFFSET +; +TBLRTN: + lda DIRITM+LO ; get where we are + clc + adc DIRTBL+LO ; ADD IN OFFSET + sta SPCL ; and make it lo part + sta FPCL ; save for later usage + lda DIRITM+HI ; get hi part + adc DIRTBL+HI + jsr SETPC ; set the PC + sta SPCH ; and this is high part + sta FPCH ; saving + sty SPCBNK ; and the bank + sty FPCBNK ; and here too + lda #0 ; start counter off at zero + sta J ; use J + sta K+HI ; this will be line length + sta K+LO ; both parts, please + jsr NEXTSPC ; point past the counter +TBLOOP: + ldy J ; get offset + lda LBUFF,Y ; get char + tax ; save char + bmi TBLP1 ; don't count hi light chars + cmp #SPACE ; see if less than a space + bcc TBLP1 ; no width if <$20 + tax ; use char as index + + lda FONTFLG ; get which font we be using + beq TBLF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne TBLF2 ; okay, now do add +TBLF1: + lda CHWID,X ; get width of char +TBLF2: + clc ; add width + adc K+LO ; to current line width + sta K+LO ; save current width + bcc TBLP1 ; no wrap + inc K+HI ; wrap, then dammit +TBLP1: + txa ; get char back + jsr STASHB ; and save it + jsr NEXTSPC ; next table entry + inc J ; point to next char + dec CHRCNT ; decrement counter + bne TBLOOP ; get next one +; +; now fill with necessary spaces +; + lda FONTFLG ; first, set up width to be added + beq TBLSPF1 ; must be variable width font + lda #MONOFONT_W ; get mono width + bne TBLSPF2 ; okay +TBLSPF1: + ldx #SPACE ; get space index + lda CHWID,X ; okay +TBLSPF2: + sta ARG8 ; use temporarily +TBLSP: + lda K+LO ; get how big line is + clc ; add in space + adc ARG8 ; pick up space width + sta K+LO ; saved + bcc TBLSP1 ; no wrap? + inc K+HI ; yes, wrapping +TBLSP1: + lda XSIZE+HI ; check against end + cmp K+HI ; compare against max width + bcc TBLSPX ; all done then + bne TBLSP2 ; no need to check if <> + lda XSIZE+LO ; check LSB + cmp K+LO ; well? + bcc TBLSPX ; all done then +TBLSP2: + lda #SPACE ; get it + jsr STASHB ; save it + jsr NEXTSPC ; point to next one + inc J ; count it + bne TBLSP ; and continue +TBLSPX: + lda #0 ; show end of table + sta LENGTH+LO ; clear out line length too + sta LENGTH+HI ; and hi part too + jsr STASHB ; marked with a zero + jsr FP2SP ; have SPC point to beginning + lda #0 ; upper byte of count is zero + jsr STASHB ; show it + jsr NEXTSPC ; point to LSB + lda J ; get how many chars are there + jsr STASHB ; save at beginning of line + inc J ; count counter in offset + lda J ; get J back + clc ; add in where we were + adc DIRITM+LO ; okay with lo part + sta DIRITM+LO ; save it + lda DIRITM+HI ; and now the hi part + adc #0 ; pick up carry, maybe + sta DIRITM+HI ; and save it + rts + + ; ------------------- + ; FLUSH OUTPUT BUFFER + ; ------------------- + ; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: + lda #SPACE ; SPACE CHAR + stx OLDEND ; SAVE CURRENT END OF LINE +FL0: + cmp LBUFF,X ; FIND LAST SPACE CHAR + beq FL1 ; IN THE LINE + dex + bne FL0 ; IF NONE FOUND, + ldx CHRCNT ; FLUSH ENTIRE LINE + dex ; minus last one +FL1: + stx OLDLEN ; SAVE OLD LINE POS HERE + stx CHRCNT ; MAKE IT THE NEW LINE LENGTH + + lda TABLEF ; are we doing table I/O? + beq FL11 ; nope + jsr TBLRTN ; YES, DO IT + jmp FL12 ; so refill line +FL11: + jsr ZCRLF ; PRINT LINE UP TO LAST SPACE +; +; START NEW LINE WITH REMAINDER OF OLD +; +FL12: + ldx OLDLEN ; GET OLD LINE POS + ldy #0 ; START NEW LINE AT BEGINNING +FL2: + inx + cpx OLDEND ; CONTINUE IF + bcc FL3 ; INSIDE of end of line + beq FL3 ; or at end of line + sty CHRCNT + rts +FL3: + lda LBUFF,X ; GET CHAR FROM OLD LINE + cmp #SPACE ; don't move start spaces in either + beq FL4 ; fine, I won't + sta LBUFF,Y ; MOVE TO START OF NEW LINE + bmi FL4 ; don't count hi light chars + cmp #SPACE ; don't count control chars + bcc FL4 ; okay + txa ; save current x + pha ; saved + lda FONTFLG ; get which font we be using + beq FLSF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne FLSF2 ; okay, now do add +FLSF1: + lda LBUFF,X ; get char back + tax ; make index + lda CHWID,X ; get width of char +FLSF2: + clc ; get ready for add + adc LENGTH+LO ; okay, now add char width + sta LENGTH+LO ; save new length + pla ; get old X back + tax ; okay + bcc FL4 ; no wrap + inc LENGTH+HI +FL4: + iny ; UPDATE # OF chars in NEW LINE + bne FL2 ; (ALWAYS) + + + ; --------------- + ; CARRIAGE RETURN + ; --------------- + +ZZCRLF: + ldx TABLEF ; OUTPUT TO TABLE? + beq ZCRLF ; NO +; +; if putting a into table, just add to line buffer and flush +; + lda #EOL ; get carriage return char + ldy CHRCNT ; add to lbuff + sta LBUFF,Y ; got it + inc CHRCNT ; now flush it + jsr TBLRTN ; YES, DO IT (TBL ONLY) + jmp ZCRLFX ; git out +ZCRLF: + ldx CHRCNT ; how far have we gone + lda #EOL ; get carriage return char + sta LBUFF,X ; END OF CURRENT LINE + inc CHRCNT ; UPDATE LINE LENGTH + jsr LINOUT ; DISPLAY LINE + +; +; now check about line count +; + lda #0 + sta CHRCNT ; AND RESET LINE COUNT + sta LENGTH+LO ; okay + sta LENGTH+HI ; okay + + jsr CHKFNC ; CHECK FOR CR FUNCTION (XZIP) + + lda SCREENF ; CHECK IF DISPLAYING TO SCREEN + beq ZCRLFX ; NO, GO HANDLE IF PRINTING + lda SCRLFLG ; is it a scrolling window? + beq ZCRLFX ; nope, so no more + inc LINCNT ; NEW LINE GOING OUT + + ldx LINCNT ; IS IT TIME TO + cpx MAXLINES ; PRINT "MORE" YET? + bcc ZCRLFX ; NO, CONTINUE + + lda #1 ; leave one line from last screen, and input line + sta LINCNT ; RESET LINE COUNTER + lda LEFTMRG ; SET LEFT MARGIN + sta SCRCX + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay +; +; print [MORE] out myself, to avoid re-entrancy problems +; + lda SCRIPTF ; make sure we don't script + pha + ldx #0 ; start with first char + stx SCRIPTF ; clear script flag + stx SCLLINES ; use this as a counter +MORELOOP: + lda MORE,X ; get char + sta IOCHAR ; save it + jsr DIRECT_OUT ; pump it out there + inc SCLLINES ; count char + ldx SCLLINES ; how many have we done + cpx #MOREL ; done? + bne MORELOOP ; nope + + jsr CLRBUF ; make sure it shows +WAIT: + jsr GETKEY ; wait for key please + lda #MOREL-1 ; how many backspaces + sta LENGTH ; just use this as counter +WM11: + ldx LENGTH ; which char? + lda MORE,X ; get char + tax ; put here for erase + lda #BACKSPACE ; erase char + jsr CHAR + dec LENGTH ; count it + bpl WM11 + pla ; get script flag back + sta SCRIPTF ; fine + lda LEFTMRG ; move back to left margin + sta SCRCX ; okay + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay +ZCRLFX: + lda #0 + sta CHRCNT ; AND RESET LINE COUNT + sta LENGTH+LO ; okay + sta LENGTH+HI + rts +LINOUT: + ldy CHRCNT ; IF BUFFER EMPTY, + beq LINEX ; DON'T PRINT ANYTHING + sty PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + lda SCREENF ; DISPLAY TO SCREEN? + beq LOUT1 ; NO, GO CHECK IF PRINT + ldx #0 ; SEND CONTENTS OF [LBUFF] +LOUT: + lda LBUFF,X ; TO SCREEN + jsr CHAR + inx + dey + bne LOUT + jsr DISP_LINE ; make sure line gets printed +LOUT1: JSR PPRINT ; PRINT [LBUFF] IF ENABLED +LINEX: + rts ; AND RETURN +; +; CHECK IF THERE IS A PENDING FUNCTION CALL ASSOCIATED WITH 'S +; +CHKFNC: + ldy #WINCRC+HI ; get function offset + lda (WINDOW),Y ; IF NULL IGNORE + dey ; point to lo part + ora (WINDOW),Y + beq CHKOUT + + lda CRLF_CHECK ; do we really want to do this? + beq CHKOUT ; nope + + lda (WINDOW),Y ; DECR COUNTER + sec + sbc #1 + sta (WINDOW),Y + iny + lda (WINDOW),Y ; work on hi part + sbc #0 ; pick up carry + sta (WINDOW),Y ; save it + dey + ora (WINDOW),Y ; if NULL NOW, CALL FCN + bne CHKOUT + + ldy #WINCRF+LO ; pointing to routine + lda (WINDOW),Y ; get lo part + sta J+LO ; and save in J + iny ; point to hi part + lda (WINDOW),Y ; got it + sta J+HI + jsr INTCLL ; DO FUNCTION CALL +CHKOUT: + rts + + + ; ---------------------- + ; UPDATE THE STATUS LINE + ; ---------------------- + ; NOT APPLICABLE IN EZIP. + +ZUSL: RTS + +; ------ +; BUFOUT +; ------ +; ENTER: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE +; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO +; +; shouldn't need this in YZIP ?! +; +ZBUFOUT: +; +; CLEAR OUTPUT BUFFER BEFORE DOING ANYTHING FANCY +; +CLRBUF: + jsr LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) + ldx #0 + stx CHRCNT + rts + + ; ------ + ; DIROUT + ; ------ + ; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT + ; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT + ; MULTIPLE DEVICE USAGE IS POSSIBLE. + +SAVEXSIZE: db 0,0 ; for formatted table saving + +ZDIRT: + jsr CLRBUF ; send out anything there now! + + ldx ARG1+LO + bmi DIRRES ; NEGATIVE VALUE, DESELECTING + dex + beq DIR1 ; 1 = SET OUTPUT TO SCREEN + dex + beq DIR2 ; 2 = SCRIPTING + dex + beq DIR3 ; 3 = TABLE + rts ; INVALID VALUE +DIRRES: + inx + beq DRES1 ; -1 = RESET TO SCREEN + inx + beq DRES2 + inx + beq DRES3 + rts ; INVALID VALUE, JUST LEAVE +DIR1: + jsr CLRBUF + lda #1 ; turn screen on + sta SCREENF + rts +DRES1: + jsr CLRBUF + lda #0 + sta SCREENF ; 0, TURN SCREEN OFF + rts +DIR2: + inx + stx SCRIPTF ; SET SCRIPT FLAG ON + lda ZBEGIN+ZFLAGS+1 ; SET GAME FLAG ALSO + ora #%00000001 + sta ZBEGIN+ZFLAGS+1 + lda PSTAT ; CHECK IF PRINTER ALREADY INIT'D + bne DIR2A + jsr PCHK ; NO, GO DO IT +DIR2A: + rts ; YES, READY TO LEAVE +DRES2: + stx SCRIPTF ; TURN PRINTER OFF + lda ZBEGIN+ZFLAGS+1 ; AND TURN OFF GAME FLAG TOO + and #%11111110 + sta ZBEGIN+ZFLAGS+1 + rts +DIR3: + stx SCREENF ; turn off screen + inx + stx TABLEF ; TURN TABLE OUTPUT FLAG ON + jmp START_TABLE ; and set things up +DRES3: + lda TABLEF ; IF OFF ALREADY + beq OUT3 ; LEAVE AS IS + + stx TABLEF ; TURN TBL OUTPUT OFF + inx ; turn screen back on + stx SCREENF ; screen back on + + lda #3 ; add three to make it wrap + clc ; ready for add + adc ZBEGIN+ZTWIDTH+1 ; do it + sta ZBEGIN+ZTWIDTH+1 + bcc DRESCC ; no wrap into MSB + inc ZBEGIN+ZTWIDTH +DRESCC: + lsr ZBEGIN+ZTWIDTH+0 ; /4 to get # of pixels + ror ZBEGIN+ZTWIDTH+1 + lsr ZBEGIN+ZTWIDTH+0 + ror ZBEGIN+ZTWIDTH+1 + + + lda FMTTBL ; did we do a formatted table? + bne DRESFT ; yes, so fix things +; +; now put count into table +; + lda DIRTBL+LO ; and put count into second byte of table + sta SPCL ; points to low par + lda DIRTBL+HI ; get page + jsr SETPC ; okay, page and bank + sta SPCH + sty SPCBNK + lda DIRITM+LO ; (2 LESS THAN [DIRITM]) + sec + sbc #2 + sta DIRITM+LO ; save this new count + bcs RESET0 + dec DIRITM+HI ; wrapped downwards +RESET0: + lda DIRITM+HI ; get hi part + jsr STASHB ; saved that count + jsr NEXTSPC ; and point to lo part + lda DIRITM+LO ; and get lo part + jsr STASHB ; and save it + rts ; done +DRESFT: + lda CHRCNT ; anything in buffer? + beq DRES31 ; nope + jsr TBLRTN ; then fill out last line +DRES31: + lda SAVEXSIZE+LO ; get old xsize back + sta XSIZE+LO ; restored + lda SAVEXSIZE+HI + sta XSIZE+HI + lda #0 ; reset this flag too + sta FMTTBL ; cleared +OUT3: + rts +; +; set things up for doing table output +; +START_TABLE: + + lda ARG2+HI ; SET UP TBL + sta DIRTBL+HI + lda ARG2+LO ; TO STORE CHARS IN + sta DIRTBL+LO + lda #2 + sta DIRITM+LO + lda #0 + sta DIRITM+HI + sta ZBEGIN+ZTWIDTH+1 ; clear width count + sta ZBEGIN+ZTWIDTH+0 +; +; check to see if we have formatted table +; + lda NARGS ; get # of arguments + cmp #3 ; if == 3, then we wrap it + beq DIR30 ; nope + rts ; all done other wise +DIR30: + stx FMTTBL ; set formatted table flag + lda XSIZE+LO ; save the current XSIZE + sta SAVEXSIZE+LO ; okay, did it + lda XSIZE+HI ; and MSB + sta SAVEXSIZE+HI ; okay + lda ARG3+LO ; this is the actual amount + ldx ARG3+HI ; get interesting arg + bmi DIRFT1 ; check for negative width + jsr SETWJ ; get the window offset + ldy #WINXSZ ; get its XSIZE + lda (J),Y ; got it + sta XSIZE+LO ; aren't we nice + bne DIR31 ; jump to end +DIRFT1: + eor #$FF ; turn to a positive number + sta XSIZE+LO ; save it + inc XSIZE+LO ; to make it right +DIR31: + lda #0 ; items starts at zero + sta DIRITM+LO ; okay + sta XSIZE+HI ; clear out highness + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + rts + + ; ------ + ; CURSET + ; ------ + ; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW + ; AND AT COLUMN (ARG2) in (optional) window ARG3 + +ZCURST: + jsr CLRBUF ; CLEAR OUT ANY NON DISPLAYED TEXT 1ST + lda ARG1+LO ; see if < 0 + cmp #$FF ; -1 == turn off cursor + bne ZCURS00 ; nope + lda #1 ; show cursor off + bne ZCURSTXX ; go do it and return +ZCURS00: + cmp #$FE ; -2 == turn cursor on + bne ZCURS0 ; nope, just deal with normally + lda #0 ; show cursor not off +ZCURSTXX: + sta CURSOR_OFF ; show current cursor state + rts +ZCURS0: + dec ARG1+LO ; zero base both args + dec ARG2+LO ; thanx + + lda NARGS ; check for id + cmp #3 ; if 3 args, then window ID specified + beq ZCURS1 ; not 3, so use current window + + lda CURWIN ; show current window being done + sta ARG3+LO ; thanx +ZCURS1: + lda ARG3+LO ; get window ID + jsr SETWJ ; put address into J + lda ARG1+LO ; GET LINE + ldy #WINHGHT ; check against height + cmp (J),Y ; too far? + bcc ZCURS3 ; no, so use it + lda (J),Y ; got max out + tay ; but one too far + dey ; all better now + tya ; back to A +ZCURS3: + clc ; get ready for add + ldy #WINTOP ; do y pos first + adc (J),Y ; add in top to get absolute value + ldy #WINY ; get y pos offset + sta (J),Y ; save here + lda ARG2+LO ; GET COLUMN + ldy #WINWID ; check against width + cmp (J),Y ; is it to for right (like Reagan?) + bcc ZCURS4 ; nope, must be dukakis + lda (J),Y ; get max + tay ; for going down one + dey ; done it + tya ; back to A for usefullness +ZCURS4: + ldy #WINLEFT ; get left edge to absolute it + adc (J),Y ; carry clear from above + ldy #WINX ; this is the x pos + sta (J),Y ; into the structure +; +; now check for current window again, move cursor anyway +; + jmp GET_CURSOR ; get cursor pos from WINDOW + + ; ------ + ; CURGET + ; ------ + +ZCURGT: + jsr CLRBUF ; flush the buffer + + jsr SAVE_CURSOR ; save the current position + + dec NARGS ; see how many arguments + beq ZCURG1 ; use main window + lda ARG2+LO ; get window id + bpl ZCURG2 ; and figger it out +ZCURG1: + lda CURWIN ; use current window +ZCURG2: + jsr SETWJ ; make J point to right place + + lda ARG1+HI ; get table address + jsr SETPC ; get real address in memory + sty SPCBNK ; set bank + sta SPCH ; and page + lda ARG1+LO ; get table offset + sta SPCL ; and save it + + lda #0 ; zero hi part of Y pos + jsr STASHB ; and save it + jsr NEXTSPC ; and point to next one + jsr FETCHCY ; Fetch Y pos + jsr STASHB ; and save it + jsr NEXTSPC +; +; now for the X pos + lda #0 ; zero top byte of x pos + jsr STASHB + jsr NEXTSPC + jsr FETCHCX ; and now the X pos, and return + jmp STASHB ; and stash it away + +; +; FETCHCY - get the relativized Y pos into [A] +; J points to window structure +FETCHCY: + ldy #WINY ; get Y pos of window's cursor + lda (J),Y ; got it + ldy #WINTOP ; need to de-absolute it + sec ; get ready for sub + sbc (J),Y ; get relative pos + tax ; for 1 basing it + inx ; 1 align it + txa ; and put for save + rts +; +; FETCHCX - get relativized X pos into [A] +; J points to window structure +FETCHCX: + ldy #WINX ; get X pos of cursor + lda (J),Y ; got it + ldy #WINLEFT ; relativize it + sec ; get ready for sub + sbc (J),Y ; subtract left edge + tax ; for incing + inx ; 1 ALIGN IT + txa + rts + + ; ----- + ; DIRIN + ; ----- + ; NOT YET IMPLEMENTED, BUT RESERVED + +ZDIRIN: RTS + +; +; SETWJ - set up J to point to window structure for window ID in [A] +; +SETWJ: + tay ; check for -3 (current window) + bpl SWJ1 ; nope, window ID here + lda CURWIN ; -3 means current window +SWJ1: + asl A ; shift to make word index + tay ; and now make index + lda WINTABLE,Y ; get lo part of window struct address + sta J+LO ; and save it + lda WINTABLE+1,Y ; here's the hi part + sta J+HI ; prove it + rts + + ; ----- + ; ERASE + ; ----- + +ZERASE: + lda ARG1+LO + cmp #1 + bne ZEROUT ; not clreol + + jsr CLRBUF + jmp CLREOL ; CLEAR TO END OF LINE +ZEROUT: + sta CLSWIDTH ; this many pixels wide + lda #FONT_H ; pixels of font_height + sta CLSHEIGHT + lda SCRCX ; start at current cursor pos + sta CLSLEFT + lda SCRCY + sta CLSTOP + jmp CLS ; and do it + +; ----- +; CLEAR the current window +; ----- +SAVEXY: dw 0 + +ZCLR: + jsr CLRBUF ; flush the current buffer + jsr SAVE_CURSOR ; save the cursor pos + + lda ARG1+LO ; CHECK WHAT TO DO + bpl CLRW ; a particular window + cmp #$FD ; -3 means current window + beq CLRW ; so just handle it regular + cmp #$FE ; clear with nothing social + beq CLRCLS ; just clear the screen +; +; UNSPLIT SCREEN & CLEAR IT +; + lda #0 ; just use SPLIT 0 + sta ARG1+LO ; as if called normally + jsr ZSPLIT ; do the split +; +; just clear the entire screen +; +CLRCLS: + lda #0 ; clear the entire screen + sta CLSLEFT ; from top left + sta CLSTOP + lda #MAXWIDTH ; to bottom right + sta CLSWIDTH + lda #MAXHEIGHT + sta CLSHEIGHT + + jsr CLS ; do the clear screen (no cursor movement) + lda ARG1+LO ; check for -2 + bmi ZCLRX ; it is, don't move cursor + bpl ZCLEARX ; move cursor +CLRW: + jsr SETWJ ; get me the window pointer + ldy #WINTOP ; step thro to get data + lda (J),Y ; TOP + sta CLSTOP ; save for clear + iny ; point to left + lda (J),Y ; get it + sta CLSLEFT ; tell CLS + iny ; now at WINHGHT + lda (J),Y ; got it + sta CLSHEIGHT ; save for clear + iny ; now at WINWID + lda (J),Y ; get height + sta CLSWIDTH ; saved + jsr CLS ; screen cleared +; +; now move the cursor to 1,1, if not == -2 +; +ZCLEARX: + lda ARG1+LO ; check arg + jsr SETWJ ; make sure J still points to window + ldy #WINTOP ; put at top left of window + lda (J),Y ; get top + ldy #WINY ; and make it the y pos + sta (J),Y ; of the cursor + ldy #WINLEFT ; and the left is + lda (J),Y ; the + clc ; add in the left margin + ldy #WINLM ; here's the left margin + adc (J),Y ; added it + ldy #WINX ; x pos of the + sta (J),Y ; cursor + lda #0 ; and clear out line count + ldy #WINLCNT ; line count + sta (J),Y ; okay + ldy #WINLLEN ; and length of current line + sta (J),Y ; okay + iny ; do hi + sta (J),Y ; okay +ZCLRX: + jmp GET_CURSOR ; restore the cursor pos for the current window + +; ------ +; PRINTT +; ------ +; PRINT A TABLE TO SCREEN, ARG1 = # OF BYTES +; ARG2 = WIDTH, ARG3 (DEF = 1) = HEIGHT + +OLDCHZ EQU I+LO ; EASIER TO READ +OLDEHZ EQU I+HI +OLDCVT EQU L+LO + +TBL_LEN DW 0 ; save for length + +ZPRNTT: + lda ARG1+LO ; USE GETBYT AS TBL COULD + sta MPCL ; BE ANYWHERE + lda ARG1+HI + sta MPCM + lda #0 + sta MPCH + jsr VLDMPC + + lda ARG2+LO ; ONLY A BYTE AS MAX + beq PTTDUN ; QUIT NOW IF NULL + + sta TBLWIDTH ; width of the table + sta TBLCNT ; start counter off at width + dec NARGS ; count down to 1 (maybe) + lda NARGS + cmp #1 + beq NOHIGHT ; DEFAULT HEIGHT IS 1 + lda ARG3+LO ; get passed height +NOHIGHT: + sta TBLHEIGHT ; height of the table (at least 1) + lda SCRCX + sta OLDEHZ + sec ; subtract left margin to get how long line is + sbc LEFTMRG ; okay we did that + sta TBL_LEN+LO ; this is how big line is too + lda #0 ; clear MSB + asl TBL_LEN+LO ; *2 + rol A + asl TBL_LEN+LO ; *4 + rol A + sta TBL_LEN+HI ; save +PTTLP: + jsr GETBYT ; GET A BYTE + jsr COUT ; and send it out + + dec TBLCNT ; one more byte done + bne PTTLP + dec TBLHEIGHT ; IF DONE ALL LINES + beq PTTDUN ; LEAVE + + jsr CLRBUF ; so send out stuff that's there + + lda OLDEHZ ; get old x pos + sta SCRCX ; and restore it + lda #1 ; show cursor changed + sta CURSFLG ; okay + lda SCRCY ; point to next line + clc ; by adding in the font height + adc #FONT_H ; okay, goody + sta SCRCY ; and here we are + + lda TBL_LEN+HI ; reset length + sta LENGTH+HI ; hi part + lda TBL_LEN+LO ; lo part + sta LENGTH+LO ; just a lo + + lda TBLWIDTH ; RESET COUNT + sta TBLCNT ; thanx + bne PTTLP ; GO DO NEXT LINE +PTTDUN: + rts +;-------------- +; ZPRINTF +;-------------- +; ZPRINTF - print a formatted table +; +ZPRINTF: + lda ARG1+LO ; USE GETBYT AS TBL COULD + sta MPCL ; BE ANYWHERE + lda ARG1+HI + sta MPCM + lda #0 + sta MPCH + jsr VLDMPC + + lda SCRCX ; save the X pos + sta OLDEHZ ; saved here +ZPFL1: + jsr GETBYT ; get the length byte, MSB, & ignore + jsr GETBYT ; get the length byte + beq ZPFX ; no more if == 0 + sta TBLWIDTH ; keep track of it +ZPFL2: + jsr GETBYT ; now get the char byte + jsr CHAR ; and send it yt + dec TBLWIDTH ; any more? + bne ZPFL2 ; ayyup + + jsr DISP_LINE ; make sure line goes out + lda OLDEHZ ; reset a few things + sta SCRCX ; including x pos + lda #1 ; show cursor changed + sta CURSFLG ; okay + lda SCRCY ; point to next line + clc ; by adding in the font height + adc #FONT_H ; okay, goody + sta SCRCY ; and here we are + bne ZPFL1 ; and do it again +ZPFX: + rts +; ------------ +; SET NEW FONT +; ------------ + +; Font 4 is mono-spaced font. + +ZFONT: + jsr CLRBUF ; clear the buffer first + + dec NARGS ; did we get passed a window id? + bne ZFNTWID ; yup + lda #$FD ; -3 means current window + sta ARG2+LO ; make it the arg2 then +ZFNTWID: + lda ARG2+LO ; get window we are interested in + jsr SETWJ ; make [J] point to window struct + + lda ARG1+LO ; check for + cmp #1 ; font 1 + beq ZFNT1 ; or + cmp #4 ; font 4 (monospace) + bne ZFBAD ; nope, so die +; +; font 4 is the monospaced font +; + ldy #WINFSIZE ; point to width + lda #MFONT_W ; get game width + sta (J),Y ; store the width + lda #3 ; set font ID + bne ZFNTEX ; all done +ZFNT1: + ldy #WINFSIZE ; point to width + lda #FONT_W ; get game width + sta (J),Y ; store the width + lda #0 ; set font ID +ZFNTEX: + ldy #WINFONT ; set font + pha ; save font id + lda (J),Y ; get old font id + tax ; save old font id + pla ; get new one back + sta (J),Y ; save in structure + lda (WINDOW),Y ; get current window font + beq ZFNT0X ; set flag with zero + lda #MONOFONT_W ; get width of mono spaced font +ZFNT0X: + sta FONTFLG ; and set flag too + inx ; make it say correct font ID for game + txa ; put in A for put val + ldx #0 ; clear X + jmp PUTVAL ; and return it +ZFBAD: + jmp RET0 ; TELL IT DOESN'T WORK +; ------------------------------ +; FETCH A LINE OF INPUT FOR READ +; ------------------------------ +; ENTRY: Relative READ table address in RDTBL1 +; EXIT: # CHARS READ IN [A] +SV_SPC: ds 3 ; save SPC here for later usage + +INPUT: + jsr CLRBUF ; FLUSH [LBUFF] + ldy #0 ; RESET LINE COUNT + sty I+HI ; clear local variables + sty I+LO + sty J+HI + sty J+LO + sty BRKCHR ; init break char + sty LINCNT ; RESET LINE COUNT + sty PTR_COUNT ; we start by looking at pointer + sty CURSFLG ; make sure we don't change cursor +; +; check for new TCHARS table +; + lda ZBEGIN+ZTCHAR+1 ; so check lower byte for different tchars + cmp SVTCHAR+LO ; is it different? + bne IO_DOT ; ayyup, get new one + lda ZBEGIN+ZTCHAR ; get current TCHARS hi part + cmp SVTCHAR+HI ; is it the same as saved one? + + beq IOj ; yes, so don't muck with it +IO_DOT: + jsr DO_TCHARS ; new table, so copy it over +; +; now set up FPC +; +IOj: + lda RDTBL1+HI ; get page of table + jsr SETPC ; and get me the memory page and bank + sta FPCH ; save page + sty FPCBNK ; and bank + lda RDTBL1+LO ; and get offset + sta FPCL ; set up FPC/SPC + jsr FETCHB ; get length of line + tay ; for dec'ing + dey ; don't count the offset byte + dey ; and leave room for terminator + sty CHRMAX ; and save it + jsr NEXTFPC ; point to next byte + jsr FETCHB ; get current offset into buffer + sta CHARCNT ; save how many chars out there + jsr NEXTFPC ; point to beginning of data buffer +; +; now finish setting up saved SPC +; + ldx #2 +INSVCL: + lda FPC,X ; get byte to saved for use later on + sta SV_SPC,X ; it is saved here + dex + bpl INSVCL ; next! +; +; now copy current buffer into local buffer +; + lda CHARCNT ; make sure we have some + beq CPIOLX ; nope, none in there now + ldx #0 ; start at first char +CPIOL: + jsr FETCHB ; get a char + sta LBUFF,X ; save char + jsr NEXTFPC ; point to next one + inx ; next char + cpx CHARCNT ; got them all yet? + bne CPIOL ; nope +CPIOLX: + jsr CHKTME ; START TIME LIMIT +; +; this is the get-a-key-and-whack-on-it loop +; +INLOOP: + lda I+HI ; is there a time? + beq INPL1 ; nope + jsr TIMIN ; do timed input + bcc INPL2 ; got a char, process it + jmp LEXBAD ; timed out with nothing there! +INPL1: + jsr GETKEY ; let apple do the walking +INPL2: + jsr ISTCHR ; CHECK IF IT'S AN ACCEPTABLE TERMINATOR KEY + bcs NOTYET + + sta BRKCHR + cmp #EOL ; IF EOL PUT TO SCREEN + beq ENDLINx + jmp ENDIN ; ELSE JUST END +ENDLINx: + jmp ENDLIN ; can't reach with a branch +NOTYET: + ldy #$FF ; restart pointer device counter + sty PTR_COUNT ; and start again + tay ; check for functions keys that aren't + bmi CBAD ; terminators and feep if it is + cmp #EOL ; EOL? + beq ENDLIN ; LINE DONE IF SO + cmp ESCAPE ; don't allow escape char's thru + beq CBAD ; okay, I won't + + cmp #BACKSPACE ; BACKSPACE? + beq BACKUP ; SPECIAL HANDLING + cmp #ESCAPE ; ESCAPE char? + beq CBAD ; don't like it + + ldy CHARCNT ; where do we put char? + cpy CHRMAX ; are we filled up? + bcs CBAD ; boy, am i full + + pha ; save it + tax ; use as index + lda LENGTH+LO ; GET LINE LENGTH COUNTER + clc ; get ready for add + adc CHWID,X ; add width + tay ; save LSB in Y + ldx LENGTH+HI ; get high byte + bcc INP0C ; no wrap + inx ; okay, wrap then +INP0C: + pla ; get char back + cpx XSIZE+HI ; check MSB first + bcc NOIOWRAP ; no need to check lsb + cpy XSIZE+LO ; end of screen line? + bcs CBAD ; reached end, so just beep +NOIOWRAP: + stx LENGTH+HI ; save MSB + sty LENGTH+LO ; and LSB + ldx CHARCNT ; for putting in line buffer + sta LBUFF,X ; and save it in case we goto printer + jsr CHAR ; SEND TO SCREEN + jsr DISP_LINE ; show char + inc CHARCNT ; NEXT POSITION IN LINE + jmp INLOOP ; NO, GET ANOTHER CHAR +; +; HANDLE BACKSPACE +; +BACKUP: + ldx CHARCNT ; if == 2 then empty + beq CBAD ; JMP to beeping + dex ; get rid of char + stx CHARCNT ; saved + lda LBUFF,X ; get char we are interested in + tax ; put in x + + lda LENGTH+LO ; GET LINE LENGTH COUNTER + sec ; get ready for sub + sbc CHWID,X ; sub width + sta LENGTH+LO ; update length + bcs BCKP1 ; no wrap + dec LENGTH+HI ; okay, wrap then +BCKP1: + lda #BACKSPACE ; so do erasing backspace + jsr CHAR + jmp INLOOP +CBAD: + jsr BEEP ; ELSE SCREAM WITH PAIN + jmp INLOOP ; AND WAIT FOR SOMETHING BETTER +; +; HANDLE END OF LINE KEY +; +ENDLIN: + sta BRKCHR + lda #EOL ; get EOL char + jsr CHAR ; SEND EOL TO SCREEN + lda #0 ; and show 0 length of line out there + sta LENGTH+LO ; thanx + sta LENGTH+HI ; and msb + inc LINCNT ; take into account the at EOL +ENDIN: +; +; now save lbuff in table for posterity +; + lda SV_SPC+ABANK ; get bank first + sta SPCBNK ; saved + lda SV_SPC+HI + sta SPCH + lda SV_SPC+LO + sta SPCL + ldx #0 ; start with first char in buffer +ENDLOOP: + cpx CHARCNT ; done yet? + beq INP111 + lda LBUFF,X ; get char + cmp #'A' ; IF CHAR IS UPPERCASE ALPHA, + bcc LEX ; CONVERT TO LOWER CASE + cmp #'Z'+1 + bcs LEX + adc #$20 ; converting away +LEX: + jsr STASHB ; okay, stashing away + jsr NEXTSPC ; and point to next char in table + inx ; point to next char + bne ENDLOOP ; so get next one +INP111: + lda #00 ; to show end of line + jsr STASHB ; so put it in buffer +; +; now put in new line length +; + lda RDTBL1+HI ; get page of table + jsr SETPC ; and get me the memory page and bank + sta SPCH ; save page + sty SPCBNK ; and bank + lda RDTBL1+LO ; and get offset + sta SPCL + jsr NEXTSPC ; and point to char count + lda CHARCNT ; get character count + jsr STASHB ; and shove it away +LEXBAD: + ldy #0 ; clear out + sty PTR_COUNT ; pointer flag + rts ; Length is in [A] +; +; Copy over a new TCHARS table +; +DO_TCHARS: +; +; now do somethin' with the TCHAR table (maybe, if <> 0) +; + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + sta SVTCHAR+HI ; save it for checking + jsr SETPC ; and now make absolute + sta FPCH ; Save in FPC + sty FPCBNK + lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + sta SVTCHAR+LO ; and save for later check + sta FPCL ; now move pointer to fetch spot + + lda #0 ; and set index + sta I ; thank you + sta ALLFLG ; turn it off +TCHLP: + jsr FETCHB ; get the byte in [a] + jsr NEXTFPC ; point to next one + ldx I ; get offset + inc I ; and point to next one + sta TCHARTBL,X ; save in lower memory, thank you + cmp #0 ; are we done yet? + beq TCHj ; NULL TERMINATED STRING + cmp #$FF ; $ff means all >128 chars are terminators + bne TCHLNEXT ; nope + lda #1 ; yes, + sta ALLFLG ; so set flag to say so +TCHLNEXT: + bne TCHLP ; and go get it +TCHj: + rts + + ; ------------------------ + ; IS IT A TERMINATOR CHAR? + ; ------------------------ + +ISTCHR: + ldx TCHARTBL ; check for chars in TCHAR table + beq ISNOT ; nope + + ldx ALLFLG ; ARE ALL FCN KEYS (<127) TERMINATORS + beq ISCHK ; 0 = NO, GO CHECK LIST + tax ; check for minus + bmi ISFND ; YUP + bpl ISNOT +ISCHK: + ldy #0 +ISLP: + cmp TCHARTBL,Y ; IS CHAR WE HAVE A TCHAR? + beq ISFND ; YES + ldx TCHARTBL,Y ; NULL = END OF STRING + beq ISNOT + iny + bne ISLP ; SHOULD ALWAYS LOOP +ISNOT: + sec + rts ; NOT FOUND +ISFND: + clc + rts + + ; ----- + ; INPUT 1 char, no printing + ; ----- + +ZINPUT: + JSR CLRBUF + + ldy #0 + sty LINCNT + sty CHRCNT + sty I+HI ; init locals too + sty I+LO + sty J+HI + sty J+LO + sty PTR_COUNT ; always check the pointer + + DEC NARGS + BEQ ZINP3 ; NO TIME LIMIT + LDA ARG2+LO ; GET DELAY WANTED + STA I+HI + DEC NARGS + BEQ ZINP4 ; NO FCN + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI +ZINP4: + JSR TIMIN ; CALL timed input rotine + BCC ZINPRK ; send char on home + JMP RET0 ; time out without character +ZINP3: + jsr GETKEY ; ok, find which char was pressed + cmp #ESCAPE ; don't use escape char + bne ZINPRK ; fine + jsr BEEP ; complain + jmp ZINP3 ; do again +ZINPRK: + LDX #0 + JMP PUTBYT ; RETURN CHAR + + +INTCLL: + LDA I+HI ; SAVE VALUES FOR CALLING RTN + PHA + LDA I+LO + PHA + LDA J+HI + STA ARG1+HI ; pretend it's arg1 + PHA + LDA J+LO + STA ARG1+LO ; and this is the other half + PHA + + LDX #1 + STX NARGS ; 0 args for internal call + DEX + STX IRET ; make sure it returns here! + + LDA ZPCL ; a fake one to say we + PHA ; are an internal call + LDA ZPCM ; so save real one + PHA + LDA ZPCH + PHA + + LDA #0 ; return addr of zero is + STA ZPCH ; internal call! + STA ZPCM + STA ZPCL + + JSR DOCALL + + JMP MLOOP ; GO DO FCN +; +; RETURN FROM FCN WILL COME HERE +; +ZIRET: + PLA ; GET RID OF RTS FROM ZRET + PLA + + PLA ; get old zpc back + STA ZPCH + PLA + STA ZPCM + PLA + STA ZPCL + JSR VLDZPC ; and validate it + + PLA ; RESTORE FOR CALLING RTN + STA J+LO + PLA + STA J+HI + PLA + STA I+LO + PLA + STA I+HI + RTS ; GO BACK TO CALLER + +; INPUT: routine locals! +CHARCNT: DB 0 ; where into buffer goes char +SVCHAR: DB 0 ; where to save the char before printing + +IRET: DB 0 ; FLAG TELLS IF RETURNLESS CALL + +MTEMP: DB 00,00 ; temp spot for math routines +TYPE: DB 0 ; PARTIAL OR NORMAL (WHOLE) SAVE/RESTORE +ASSVLU: DB 0 ; how many args to this subroutine +BRKCHR: DB 0 ; READ BREAK CHAR +RDFLAG: DB 0 ; 0 - only read 1 - do lex on it +MORE: DB "[MORE]" +MOREL EQU $-MORE + END + + diff --git a/apple/yzip/rel.13/machine.asm b/apple/yzip/rel.13/machine.asm new file mode 100644 index 0000000..baa45fd --- /dev/null +++ b/apple/yzip/rel.13/machine.asm @@ -0,0 +1,946 @@ + STTL "--- MACHINE-DEPENDENT I/O: APPLE II ---" + PAGE +; ----------------------- +; DIRECT PRINT LINE [X/A] +; ----------------------- +; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB) +; STRING LENGTH IN [Y] +DLCNT: db 0 +DLOFF: db 0 +DLINE: + stx STRING+LO ; DROP STRING ADDRESS + sta STRING+HI ; INTO DUMMY BYTES + sty DLCNT ; COUNTER + jsr CLRBUF ; send out what's out + lda SCREENF ; save output flag + pha + ldx #1 ; INIT CHAR-FETCH INDEX + stx SCREENF ; make sure screen output is on + dex + stx CRLF_CHECK ; don't let swap happen + stx SCRIPT ; don't script any of my internal +DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE +STRING: DW $0000 ; DUMMY OPERAND BYTES + stx DLOFF ; save X + sta IOCHAR ; save here for DIRECT_OUT +DOUT1: jsr DIRECT_OUT ; send directly out there + ldx DLOFF ; get x back + inx + dec DLCNT ; LOOP TILL + bne DOUT ; OUT OF CHARS + jsr CLRBUF ; and force the chars out + ldx #1 ; allow scripting again + stx SCRIPT ; okay, we did + stx CRLF_CHECK ; and turn on check + pla ; get screen flag back + sta SCREENF ; bingo + rts ; done + +; SWAP2INFOW - save current state and swap to the information window, +; which is currently window zero +SWAPA1: ds 1 ; save for current ARG1 +SWAPCW: ds 1 ; save for current window +SWAPFLG: db 0 ; flag == 1 if we have already swapped +SWAP2INFOW: + lda SWAPFLG ; already swapped? + bne SWP2 ; ayyup + jsr CLRBUF ; clear out the buffer + jsr SAVE_CURSOR ; save current postion of cursor + lda ARG1+LO ; get current arg1 + sta SWAPA1 ; save it + lda CURWIN ; get current window + sta SWAPCW ; save it + lda #0 ; swap to window zero for messages + sta ARG1+LO ; okay + jsr ZSCRN ; and swap to it +SWP2: + inc SWAPFLG ; show we are in swap window +SWAPEX: + rts ; all done +; +; SWAPBACK - swap out of info window, and back to old window +; +SWAPBACK: + dec SWAPFLG ; are we finally leaving for good? + bne SWAPEX ; nope + lda SWAPCW ; and now for current window + sta ARG1+LO ; swap to it + jsr ZSCRN ; we did + lda SWAPA1 ; and get arg1 back + sta ARG1+LO ; we did + jmp GET_CURSOR ; and get cursor back + +; ----------------------- +; SEND [LBUFF] TO PRINTER +; ----------------------- +; ENTRY: LENTH OF LINE IN [PRLEN] + +PLEAV: RTS + +PPRINT: + lda SCRIPT ; SCRIPTING INTERNALLY ENABLED? + and SCRIPTF ; SCRIPTING ON? + and SCRIPTFLG ; Window allow scripting? + beq PLEAV ; NO, EXIT + lda CSW+LO ; SAVE NORMAL OUTPUT HOOK + pha + lda CSW+HI + pha + lda ALTCSW+LO ; LOAD SCRIPTING HOOK + sta CSW+LO + lda ALTCSW+HI + sta CSW+HI + lda RDROM ; put system ROM in for printer out + ldy #0 +PP5: + lda LBUFF,Y ;GET A CHAR TO SEND OUT + bmi PP6 ; don't do highlighting + ora #$80 ; make it apple happy + jsr MCOUT +PP6: + iny + dec PRLEN ;LINE COUNT + bne PP5 ;PRINT WHOLE LINE +; +; ALL DONE, RESET TO NORMAL AND LEAVE +; + lda BNK2SET ; write RAM, bank 1 + lda BNK2SET + pla + sta CSW+HI + pla + sta CSW+LO + rts + +PSTAT: DB 0 ;SET TO CLEAR WHEN BOOT, + ;I PUT IT HERE SO RESTART WON'T ALTER +ALTCSW: DB 0,0 ;(WORD) PRINTER COUT + + ; FIRST TIME USING PRINTER, INITIALIZE IT +SLOTM: DB EOL + DB "Printer Slot 1-7: " +SLOTML EQU $-SLOTM + +PCHK: + jsr SWAP2INFOW ; point to info window +PCHK1: + DLINE SLOTM + jsr GETKEY + cmp #'8' ;1-7 + bcs PCHK1 ;OOPS + cmp #'1' ; less than '1'? + bcc PCHK1 ; ayyup +PC2: + eor #$F0 ; make it a slot address + sta ALTCSW+HI + lda #EOL + jsr CHAR ;SEND >CR< TO SCREEN FOR NEATNESS + inc PSTAT ;SET TO ON + lda CSW+LO ;SAVE NORMAL OUTPUT HOOK + pha + lda CSW+HI + pha + lda ALTCSW+LO ;LOAD SCRIPTING HOOK + sta CSW+LO + lda ALTCSW+HI + sta CSW+HI + jsr INITPRT ; now, init it + + lda RDROM ; bring in system ROM + lda #$89 ; OUTPUT PRINTER SETUP SEQUENCE + jsr MCOUT ; START WITH COMMAND CHAR >CTRL-I< + lda #$B8 ; 8 (80 COL WIDE) + jsr MCOUT + lda #$B0 ; 0 + jsr MCOUT + lda #$CE ; N (LF AFTER CR) + jsr MCOUT + lda CSW+LO ; SAVE REAL PRINTER OUTPUT + sta ALTCSW+LO ; LOC. FOR NEXT TIME + lda CSW+HI + sta ALTCSW+HI + pla ; RESET NORMAL OUTPUT + sta CSW+HI + pla + sta CSW+LO + lda BNK2SET ; and bring back top RAM + lda BNK2SET ; okay + jmp SWAPBACK ; and back to the old window +INITPRT: + lda #0 ; jump to $Cn00 + sta CSW+LO ; make LSB == 0 + jmp (CSW) ; and goto it + + +SAVE_CURSOR: + lda SCRCY ; save the cursor pos + ldy #WINY ; get offset + sta (WINDOW),Y ; first y pos + iny ; now x pos + lda SCRCX ; got it + sta (WINDOW),Y ; saved it + ldy #WINLCNT ; reset line count too + lda LINCNT ; okay + sta (WINDOW),Y ; get it + rts + +GET_CURSOR: + ldy #WINY ; get cursor pos back + lda (WINDOW),Y ; got y pos + sta SCRCY ; saved + iny ; point to x pos + lda (WINDOW),Y ; got it + sta SCRCX ; make it better + sec ; subtract left margin to get how long line is + sbc LEFTMRG ; okay we did that + bcs GETCR1 ; make sure left margin is not > cur x pos + lda #0 ; otherwise, pretend length is zero +GETCR1: + sta LENGTH+LO ; this is how big line is too + lda #0 ; clear MSB + sta LENGTH+HI + asl LENGTH+LO ; *2 + rol LENGTH+HI + asl LENGTH+LO ; *4 + rol LENGTH+HI + + ldy #WINLCNT ; reset line count too + lda (WINDOW),Y ; get it + sta LINCNT ; okay + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay + rts + +; ------------ +; SPLIT SCREEN +; ------------ +; +; SPLIT SCREEN AT LINE [ARG1] putting screen 1 at top and screen +; 0 at bottom. +; DISABLE SPLIT IF [ARG1] = 0 +; +ZSPLIT: + jsr SAVE_CURSOR ; save the cursor pos +; +; first muck with window 1 +; + lda ARG1+LO ; get split arg back + sta WINDOW1+WINHGHT ; this becomes the height of window 1 + lda #0 ; put top of 1 to top of screen + sta WINDOW1+WINTOP ; okay, we did it + lda ARG1+LO ; get new height + ldx #$FF ; this is the counter + sec ; get ready for subs +ZSPLIT0: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZSPLIT0 ; still some lines + dex ; save input line + stx WINDOW1+WINLINES ; saved + + lda WINDOW1+WINY ; check cursor pos + cmp ARG1+LO ; against height + bcc ZSPL1 ; inside window, so save it +ZSPL0: + lda #0 ; reset to top left + sta WINDOW1+WINY ; y pos at top + sta WINDOW1+WINX ; x pos at left + sta WINDOW1+WINLLEN+LO ; line length + sta WINDOW1+WINLLEN+HI ; line length + sta WINDOW1+WINLCNT ; line counter +; +; now muck with window 0 +; +ZSPL1: + lda WINDOW0+WINTOP ; top of window 0 + sec ; doing sub + sbc ARG1+LO ; subtract out the new top + clc ; adding + adc WINDOW0+WINHGHT ; to get the new height +; bcc ZSPLIT1 ; okay, positive height +; lda #0 ; make height 0 +ZSPLIT1: + sta WINDOW0+WINHGHT ; and save new height + + ldx #$FF ; this is the counter + sec ; get ready for subs +ZSPLIT2: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZSPLIT2 ; still some lines + dex ; to save input line + stx WINDOW0+WINLINES ; saved + + lda ARG1+LO ; this is the new top + sta WINDOW0+WINTOP ; set in structure + cmp WINDOW0+WINY ; make sure cursor is still in window + beq ZSPL5 ; nope, at the top + bcc ZSPL5 ; or under it + sta WINDOW0+WINY ; put cursor at top + lda #0 ; left of new + sta WINDOW0+WINX ; window 0 + sta WINDOW0+WINLLEN+LO ; linelength + sta WINDOW0+WINLLEN+HI ; linelength + sta WINDOW0+WINLCNT ; line counter +ZSPL5: + jsr GET_CURSOR ; get the cursor pos back + + lda #0 ; now switch to window zero + sta ARG1+LO ; good bye + jmp ZSCRN ; making window 0 be current + +; ------ +; MARGIN +; ------ +; +; Set the margins for the window +; +; ARG1 - left margin +; ARG2 - right margin +; ARG3 - window ID (optional) +; +ZMARG: + jsr CLRBUF ; CLEAR LBUFF BEFORE RESETTING LINE MARGINS + jsr SAVE_CURSOR ; save current cursor pos + + lda NARGS ; see if window ID was passed + cmp #3 ; if ==3, then it's there + beq ZMRG1 ; okay, so use it + lda CURWIN ; get the current window + sta ARG3+LO ; and use as the default +ZMRG1: + lda ARG3+LO ; check what window + jsr SETWJ ; get window offset into J + lda ARG1+LO ; do left margin first + ldy #WINLM ; get offset + sta (J),Y ; save for window + iny ; point to right margin + lda ARG2+LO ; get right margin + sta (J),Y ; save right margin + ldy #WINWID ; get full width of window + lda (J),Y ; got it + sec ; subtract off the 2 margins + ldy #WINLM ; first the left margin + sbc (J),Y ; okay, gone + iny ; point to right margin + sbc (J),Y ; and take it off + ldy #WINXSZ ; set width of usable window + sta (J),Y ; see, here it is +; +; move cursor to left margin +; + ldy #WINLEFT ; get left edge + lda (J),Y ; got it + ldy #WINLM ; and add left margin + clc ; adding + adc (J),Y ; to get minimum X + ldy #WINX ; check to make sure X pos is okay + sta (J),Y ; then reset it +; +; now see if we changed the current window +; +ZMRGXP: + ldx ARG3+LO ; get the window + bmi ZMRG3 ; -3 means current window + cpx CURWIN ; check against the current window + bne ZMRGX ; nope, so we be done +ZMRG3: + sta LEFTMRG ; [A] already has left margin + ldy #WINXSZ ; get xsize to set + lda (WINDOW),Y ; got it + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + jsr GET_CURSOR ; restore the cursor pos +ZMRGX: + rts +; +; SOUND +; ----- +; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID +; (EZIP) + +ZSOUND: + ldx ARG1+LO ; GET SOUND WANTED + dex + beq BEEP + dex + bne ZSOEX ; INVALID + ldy #$FF ; DURATION ($C0 = .1 SEC) +BOOP: + lda #$10 ; TONE ($0C = 1 KHZ) + jsr WAIT10 + lda SPKR ; TOGGLE SPEAKER + dey + bne BOOP +ZSOEX: + rts + +BEEP: + lda RDROM + jsr MBELL ; just use system beep + lda BNK2SET ; back to bank 2 + lda BNK2SET ; back to bank 2 + rts +; +; just do the background color - foreground is always white/black +; +; +; ZIPCOLOR - maps ZIP colors to screen colors +; +ZCOLOR: + jsr CLRBUF ; print out what we have + + lda NARGS ; check if window was passed + cmp #3 ; was it? + beq ZCLR0 ; ayyup + lda CURWIN ; make it current window + sta ARG3+LO ; it is now +ZCLR0: + lda ARG3+LO ; get window ID + jsr SETWJ ; and put pointer into J + + ldx ARG2+LO ; get background color + beq ZCLR2 ; check fore ground color + bpl ZCLR01 ; not -1 + jsr GET_NYBBLE ; get me the color nybble here + jmp ZCLR11 ; and use as background color +ZCLR01: + dex ; check for default + bne ZCLR1 ; nope, find the color + ldx #1 ; use black as default back color +ZCLR1: + dex ; zero base the color + lda ZIPCOLOR,X ; get my color from the zip color +ZCLR11: + ldy #WINBGND ; get background offset + sta (J),Y ; saved color +; +; now do foreground color +; +ZCLR2: + ldx ARG1+LO ; get foreground color + beq ZCLREX ; no change + dex ; check for default + bne ZCLR3 ; nope, find the color + ldx #8 ; use white as default fore color +ZCLR3: + dex ; zero base the color + lda ZIPCOLOR,X ; get my color from the zip color + ldy #WINFORE ; foreground color offset + txa ; get into A for fun + sta (J),Y ; save in structure +ZCLREX: + rts + +; +; CHKTME RTN - CALLED BY INPUT & ZINPUT +; +CHKTME: + lda NARGS ; CHECK IF TIME LIMIT + cmp #2 + beq CHKT1 ; NO + lda ARG3+LO ; GET DELAY WANTED + sta I+HI + lda NARGS ; IS THERE A FCN? + cmp #4 + bne CHKT1 ; NO + lda ARG4+LO ; YES, SET IT + sta J+LO + lda ARG4+HI + sta J+HI +CHKT1: + rts ; just set things up, please + +WAIT10: + lda #2 ; do this twice (maybe) + sta DELAY_COUNTER ; put in counter +WAIT0: + lda RDROM ; get roms in + ldx #4 ; .04 SEC (time to do other stuff) +TIME1: lda #$30 ; .01 SEC + jsr MWAIT + dex + bne TIME1 + + lda BNK2SET ; get roms out + lda BNK2SET + + lda MOUSEF ; move mouse cursor? + beq WAIT1 ; nope + lda PTR_COUNT ; but do we really want to check it + bne WAIT1 ; nope + jmp MOVE_MC ; move cursor, if necessary +WAIT1: + dec DELAY_COUNTER ; count loop + bne WAIT0 ; go do again + rts +; +; tick the ol timer +; +TIMEK: + lda #BLINK_RATE ; how often to blink + sta CURCOUNT ; okay! +TIMEST: + lda I+LO ; don't reset if not zero + bne TIMELOOP ; so keep goin' then + lda I+HI + sta I+LO + jsr STCUR ; start the cursor +TIMELOOP: + jsr WAIT10 ; wait .10 secs + + jsr FKEYX ; Check for Keystroke + bmi TIME2 ; OK, HE'S THERE, CONTINUE + + dec CURCOUNT ; count down to toggle + bne TMCNT ; okay, no blink + jsr STCUR ; blink cursor + lda #BLINK_RATE ; once per second + sta CURCOUNT ; okay! +TMCNT: + dec I+LO ; 10TH'S OF SECONDS TO WAIT + beq TIMEOUT ; SOME TIME LEFT + + bne TIMELOOP ; so gwon back and try again! (JMP) +; +; THERE IS A TIME OUT, CHECK FOR A FCN +; +TIMEOUT: + jsr ERCUR ; after erasing cursor + lda J+HI ; IS THERE A FCN + beq TIMEBAD ; NO FCN, LEAVE WITH NOTHING +TIME3: + jsr INTCLL ; INTERNALLY CALL THE FCN + lda VALUE+LO ; CHECK RESULTS + beq TIMEST ; ELSE TRY AGAIN + bne TIMEBAD ; else die a horrible death! +TIME2: + jsr ERCUR ; after erasing cursor + clc ; GOT A KEY + rts +TIMEBAD: + sec + rts +; +; display the cursor in the current spot +; +CURSTATE: db $80 ; blinking cursor state +CURCOUNT: db 0 ; toggle counter + +STCUR: + lda CURSOR_OFF ; is the cursor off? + beq STCUR1 ; no + rts ; yes, so don't do nuthin' +STCUR1: + pha ; save a + lda INVFLG ; get current INVFLG + pha ; save it + lda #$80 ; make it all be ones + sta INVFLG ; and blink + + lda #SPACE ; space for cursor + sta SHOW_CURSOR ; show that we are doing cursor + jsr CHAR ; and print it out + jsr DISP_LINE ; send it out + + lda CURSTATE ; get current state + eor #$80 ; toggle it + sta CURSTATE ; save it + pla ; get invflg + sta INVFLG ; restored + lda #0 ; clear cursor flag + sta SHOW_CURSOR ; okay + + pla + rts +; +; just erase the cusor char, but leave cursor in its old place +; +ERCUR: + pha ; save a + lda CURSTATE ; get current state + bne ERCURX ; not on, leave alone + jsr STCUR ; 'start' it out +ERCURX: + pla ; retrieve [A] + rts +; +; timed key input loop +; +; carry set if timed out +; char in [A], if there is one! +TIMIN: + lda MOUSEF ; is there a mouse/joystick? + beq TIMIN1 ; nope + jsr MSCON ; turn on mouse cursor +TIMIN1: + jsr TIMEK ; check for keystroke + bcs TMBAD ; ELSE ABORT +TM1: + jsr PARSEKEY ; GET ASCII INTO [A] AND [IOCHAR] + bcs TIMIN1 ; c==1 means no good char +TMBAD: + ldx MOUSEF ; is there a mouse/joystick? + beq TIMIN2 ; nope + php ; save status + pha ; save (possible) char + jsr MSCOFF ; turn off mouse cursor + pla ; get char back + plp ; get return status +TIMIN2: + rts ; and away we go +; +; FKEYX - move the mouse cursor if any, then check for keystroke +; +FKEYX: + lda MOUSEF ; is there a mouse cursor? + beq KEYX ; nope + bmi KEYMOUSE ; handle mouse + jsr DO_STICK ; handle joystick + bpl KEYX ; go look for key still + bmi KEYBTN ; do button handling +KEYMOUSE: + jsr DO_MOUSE ; handle mouse stuff + bpl KEYX ; go look for key still +; +; button hit, so show pos in MSTBL +; +KEYBTN: + pha ; save status + lda MSTBL+LO + sta SPCL + lda MSTBL+HI + sta SPCH + lda MSTBL+ABANK + sta SPCBNK + lda #ZMSLOCX+1 ; point to LSB of mouse x + jsr ADDSPC ; add to point + lda MSX ; get X + clc ; center the hot spot + adc #CURSW/2 ; add 1/2 width + jsr STASHB ; and stuff it away + lda #2 ; 2 more to get to mouse y + jsr ADDSPC ; okay + lda MSY ; now show the world the y pos + clc ; and center vertically too + adc #CURSH/2 ; add 1/2 height + jsr STASHB ; and it is away + pla ; get status back + tay ; and set it again + rts ; otherwise, done +KEYX: + lda KBD ; check keyboard strobe + bpl KEYXX ; nothing + sta ANYKEY ; reset strobe +KEYXX: + rts +; +; MOVE_MC - move the mouse/joystick cursor, if necessary +; +MOVE_MC: + lda MOUSEF ; check which kind to move + bpl MOVE_MC1 ; move joystick cursor + jsr CHK_MOUSE ; move the mouse cursor + jmp MOVE_MC2 ; and print it +MOVE_MC1: + jsr MOVE_STICK ; okay, checked it out +MOVE_MC2 + lda MSMOVEF ; did it move? + beq MOVE_MCX ; nope + jmp MSCURS ; print it +MOVE_MCX: + rts ; done +; +; CHK_MOUSE - check the mouse position and button state, and flag any change +; +CHK_MOUSE: + lda PAGE2SW ; make sure we are pointing to main bank + + ldx #READM ; get me current cursor pos + jsr MOUSER ; turn off interrupts and set current pos + + lda BNK2SET ; make sure we are pointing to second bank + lda BNK2SET ; okay + +MSFIX0 lda MOUSEST ; get status byte + tay ; save for a sec + and #$20 ; moved since last time? + beq CHKM1 ; nope + sta MSMOVEF ; show movement +MSFIX1 lda MOUSEXL ; get mouse X pos + sta MSX ; save new one +MSFIX2 lda MOUSEYL ; and the y pos + sta MSY ; save for me +CHKM1: + tya ; get status back + and #$C0 ; is button down? + beq CHKMX ; nope + lda #$80 ; show down state +CHKMX: + jmp CHK_BTN ; check button state +; +; there is a mouse, so check it +; +DO_MOUSE: + jsr CHK_MOUSE ; check the mouse please +; FALL THROUGH TO BUTTON CLICKING HANDLER +; jmp DO_BUTTON ; handle button clicking +; +; DO_BUTTON - handle button clicking, working with the timer to +; check for double clicking or not +; +DO_BUTTON: + lda MSMOVEF ; check moved flag + beq DOM01 ; nope + jsr MSCURS ; move mouse cursor +DOM01: + lda #0 ; show no char + ldy MSBTNF ; check button flag + bpl DOBX ; none +; +; button strike, check for double click +; + sty JB_STATE ; show new state + ldy CLKCTR ; have we started click counter? + bpl DOB02 ; nope + ldy #1 ; this resets counter + sty CLKCTR ; reset it + lda #DBL_CLK ; show double click char + bne DOBEXIT ; and finis +DOB02: + ldy #-CLK_CNT ; set to double click timeout + sty CLKCTR ; okay + bmi DOBEXIT ;done +DOBX: + ldy CLKCTR ; click counter counting? + bpl DOBEXIT ; nope + inc CLKCTR ; count it then + bne DOBEXIT ; all done + ldy #1 ; reset counter + sty CLKCTR ; okay + lda #SGL_CLK ; set as char +DOBEXIT: + ldy #0 ; clear out flags + sty MSBTNF ; button flag + sty MSMOVEF ; moved flag + tay ; set flag to show any char + rts ; return char +; +; DO_STICK - handle the joystick 'interrupt' +; +DO_STICK: + jsr MOVE_STICK ; first move it + jmp DO_BUTTON ; now handle it +MOVE_STICK: + lda #0 ; get horizontal change + jsr READ_STICK ; puts value in Y + cpy #80 ; if < 80, then jump to the left + bcs DOST1 ; it is not + lda MSX ; make sure X is > 0 + beq DOST2 ; it is == 0, can't get smaller + sta MSMOVEF ; show movement + dec MSX ; move one to the left + dec MSX ; move two to the left + bne DOST2 ; now check vertical +DOST1: + cpy #180 ; if > 160, then move right + bcc DOST2 ; nope + lda MSX ; make sure X is in bounds + cmp #MAXWIDTH-4 ; don't go too far + bcs DOST2 ; already maxxed out + sty MSMOVEF ; show movement + inc MSX ; one step to the left + inc MSX ; and another one +DOST2: + lda #1 ; now check vertical + jsr READ_STICK ; ask the monitor + cpy #80 ; if < 80, move up + bcs DOST3 ; nope + lda MSY ; don't go negative + beq DOST4 ; already minned out + sta MSMOVEF ; show movement + dec MSY ; count down + dec MSY ; twice + bne DOST4 ; all done +DOST3: + cpy #180 ; check for downward motion + bcc DOST4 ; none + lda MSY ; check for maximum + cmp #MAXHEIGHT-3 ; don't go below water + bcs DOST4 ; gone, thanx + sty MSMOVEF ; show movement + inc MSY ; go further down + inc MSY ; twice as far for joystick +DOST4: + rts ; done +; +; READ_STICK - read the x or y value of the stick in mind. +; [A] == 0 or 1 - the "stick" you are interested in +; Also, check the button status. +; +JB_STATE db 0 ; last state of joystick button +READ_STICK: + pha ; save which stick we want + ldx #$E0 ; oh, pick something random +READST2: + jsr CHECK_JOYBTN ; check the joystick button + dex + bne READST2 + pla ; get x back + tax ; got it + lda RDROM ; bring ROM back + jsr MPREAD ; NOW do the read + lda BNK2SET ; back to RAM + lda BNK2SET ; back to RAM + rts +CHECK_JOYBTN: + lda MOUSEF ; check which kind to move + bpl DO_JBTN ; no joystick, check mouse + jmp CHK_MOUSE ; then do the mouse +DO_JBTN: + lda APKEY1 ; get joystick button +CHK_BTN: + bmi READST3 ; button down + sta JB_STATE ; show button went up +READST3: + eor JB_STATE ; toggle previous state + sta MSBTNF ; set button flag + rts +; ---------------------------- +; FETCH ASCII KEYCODE INTO [A] +; ---------------------------- +; EXIT: ASCII IN [A] & [IOCHAR] + +GETKEY: + lda #BLINK_RATE ; flag as wait for good key + sta CURCOUNT ; clear blinker + lda MOUSEF ; is there a mouse/joystick? + beq GTK0 ; nope + jsr MSCON ; turn on mouse cursor +GTK0: + lda #0 ; clear line counter + sta LINCNT ; okay, we did + txa ; SAVE [X] & [Y] + pha + tya + pha +GKEY0: + inc RAND+HI ; just whack on random number + dec RAND+LO ; and more + jsr FKEYX ; is there a key? + bmi GKEY01 ; got the key + + jsr WAIT10 ; wait .1 seconds, moving mouse cursor + + lda MOUSEF ; do we have a joystick/mouse? + beq GKEY02 ; nope + lda PTR_COUNT ; count down counter? + beq GKEY00 ; nope + dec PTR_COUNT ; count one wait cycle + bne GKEY02 ; don't check yet +GKEY00: + jsr CHECK_JOYBTN ; check the joystick button, just fur the heckuvit +GKEY02: + dec CURCOUNT ; down one + bne GKEY0 ; no toggle + jsr STCUR ; okay, toggle + lda #BLINK_RATE ; 1 per second + sta CURCOUNT ; okay + bne GKEY0 ; check for key +GKEY01: + pha ; save char + lda MOUSEF ; any mouse cursor? + beq GTK1 ; nope + jsr MSCOFF ; turn mouse cursor off +GTK1: + pla ; get char back + jsr ERCUR ; so erase cursor +CHKKEY: + jsr PARSEKEY ; how was the key? + bcs GKEY0 ;TRY AGAIN + sta IOCHAR ;HOLD ON TO IT + pla ; RESTORE + tay ; EVERYTHING + pla + tax + lda IOCHAR ; GET CHAR INTO [A] + rts ; AND RETURN IT + +; +; CHECK TO MAKE SURE KEY IS VALID, ONLY ACCEPT IT IF IT IS +; +PARSEKEY: + and #$7F ;SCREEN OUT SHIFTS +; +;CHECK FOR "ARROWS" & FUNCTION KEYS (X), CONVERT FOR USE (EZIP) +;ALSO : CHANGE <_>)@%^&*( TO ,-.0256789 - and 'mouse' clicks +; and other kinds of special chars +; +GK0: + ldx #ENDKEY ; GET LENGTH OF LIST +GK2: + cmp HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + beq GK3 ; FOUND IT + dex + bpl GK2 ; CHECK THEM ALL + bmi GK4 ; NOT FOUND, CONTINUE OTHER CHECKS +GK3: + lda WANT,X ; GET KEY TO USE INSTEAD + clc ; show niceness + rts ; done +GK4: + cmp #SPACE ; NO CTRL CHARS ACCEPTABLE + bcc BADKEY ; IF < SPACE, BAD + + cmp #'<' ; pick up numbers and most punctuation + bcc OK ; we did + + cmp #'z'+1 ;PICK OUT LETTERS NOW + bcs BADKEY ;IF > BAD + cmp #'a' + bcs OK ;IF > OK + cmp #'A' + bcc BADKEY + CMP #'Z'+1 + BCC OK ;IF < OK +BADKEY: + jsr BEEP ;BAD KEY, GIVE WARNING NOISE, gwon back + sec ; show badness + rts ; and done +OK: + cmp #'0' ; check for number keys + bcc OKj ; nope, < 0 + cmp #'9'+1 ; more than a nine? + bcs OKj ; ayyup +; +; here we check for the closed apple key being down too +; + ldx APKEY2 ; how about the closed apple key + bpl OKj ; not pressed, so use as number key +; +; transform number key into a function key +; + CLC ; get ready for add + ADC #84 ; transforms '1'-'9' to 133-141 + CMP #132 ; but '0' wants to be a 142! + BNE OKj ; but it's not it + CLC ; again, don't want carry + ADC #10 ; voila! +OKj: + clc ; show a wicked good character is about to arrive + rts ; toots finis + +HAVE: DB $0B,$0A,$08,$15,$7f,ESCAPE,$3C,$7C,$3F + DB $3C,$5F,$3E,$40,$25,$5E,$26,$01,$02, EOL +WANT: DB 129,130,131,132,08,ESCAPE,$3C,$7C,$3F + DB $2C,$2D,$2E,$32,$35,$36,$37,254,253, EOL +ENDKEY EQU $-WANT-1 + + END + + diff --git a/apple/yzip/rel.13/macros.asm b/apple/yzip/rel.13/macros.asm new file mode 100644 index 0000000..645c8b0 --- /dev/null +++ b/apple/yzip/rel.13/macros.asm @@ -0,0 +1,120 @@ + STTL "--- MACROS ---" + PAGE + +; +; MACROS for Apple ][ Yzip +; +DLINE: .MACRO STRING,SLEN + ldx #STRING ; get other part of string + IFMA 2 ; check to see if length passed in + ldy SLEN ; then just fetch it + ELSE + ldy #STRING|L ; get length of string + ENDIF + jsr DLINE ; print the string + .MACEND +; +; ProDOS macros +; +PRODOS: .MACRO CODE, PADDR + jsr $BF00 ; ProDOS handler + DB CODE ; ProDOS function code + DW PADDR ; Function Parameter Block address + .MACEND + +QUIT: .MACRO PBLOCK + PRODOS $65, PBLOCK + .MACEND + +READ_BLOCK: .MACRO PBLOCK + PRODOS $80, PBLOCK + .MACEND + +WRITE_BLOCK: .MACRO PBLOCK + PRODOS $81, PBLOCK + .MACEND + +GET_TIME: .MACRO PBLOCK + PRODOS $82, PBLOCK + .MACEND + +CREATE: .MACRO PBLOCK + PRODOS $C0, PBLOCK + .MACEND + +DESTROY: .MACRO PBLOCK + PRODOS $C1, PBLOCK + .MACEND + +RENAME: .MACRO PBLOCK + PRODOS $C2, PBLOCK + .MACEND + +SET_FILE_INFO: .MACRO PBLOCK + PRODOS $C3, PBLOCK + .MACEND + +GET_FILE_INFO: .MACRO PBLOCK + PRODOS $C4, PBLOCK + .MACEND + +ONLINE: .MACRO PBLOCK + PRODOS $C5, PBLOCK + .MACEND + +SET_PREFIX: .MACRO PBLOCK + PRODOS $C6, PBLOCK + .MACEND + +GET_PREFIX: .MACRO PBLOCK + PRODOS $C7, PBLOCK + .MACEND + +OPEN: .MACRO PBLOCK + PRODOS $C8, PBLOCK + .MACEND + +NEWLINE: .MACRO PBLOCK + PRODOS $C9, PBLOCK + .MACEND + +READ: .MACRO PBLOCK + PRODOS $CA, PBLOCK + .MACEND + +WRITE: .MACRO PBLOCK + PRODOS $CB, PBLOCK + .MACEND + +CLOSE: .MACRO PBLOCK + PRODOS $CC, PBLOCK + .MACEND + +FLUSH: .MACRO PBLOCK + PRODOS $CD, PBLOCK + .MACEND + +SET_MARK: .MACRO PBLOCK + PRODOS $CE, PBLOCK + .MACEND + +GET_MARK: .MACRO PBLOCK + PRODOS $CF, PBLOCK + .MACEND + +SET_EOF: .MACRO PBLOCK + PRODOS $D0, PBLOCK + .MACEND + +SET_BUF: .MACRO PBLOCK + PRODOS $D1, PBLOCK + .MACEND + +GET_BUF: .MACRO PBLOCK + PRODOS $D2, PBLOCK + .MACEND + + END + + \ No newline at end of file diff --git a/apple/yzip/rel.13/main.asm b/apple/yzip/rel.13/main.asm new file mode 100644 index 0000000..5d965d2 --- /dev/null +++ b/apple/yzip/rel.13/main.asm @@ -0,0 +1,328 @@ + STTL "--- MAIN LOOP ---" + PAGE + +MD_ADDR EQU ZBEGIN +MDEBUG EQU 1 + +MLOOP: + IF MDEBUG + lda MD_ADDR ; get interesting address + bne MLOOPx ; just fine, thank you + brk ; then die +MLOOPx: + ENDIF + + lda #0 + sta NARGS ; reset number of args + lda PAGE2SW+OFF ; just do this for the heck of it + lda BNK2SET + lda BNK2SET + sta STORE80+ON ; must always be on + + jsr NEXTPC ; get op code + sta OPCODE ; SAVE IT HERE + + IF MDEBUG +; +; special debugging code +; + ldy SPCSV + lda OPCODE + sta SAVEOP,Y + lda ZPCH + sta SAVEZH,Y + lda ZPCM + sta SAVEZM,Y + lda ZPCL + sta SAVEZL,Y + lda ZPCBNK + sta SAVEZB,Y + lda ZPCPNT+HI + sta SAVEZP,Y + ldy SPCSV + iny + tya + and #$0F + sta SPCSV + lda OPCODE + jmp MAINDB +SPCSV: db 0 + ORG $+15 + ORG $.SHR.4 + ORG $.SHL.4 +SAVEOP: ds 16 +SAVEZH: ds 16 +SAVEZM: ds 16 +SAVEZL: ds 16 +SAVEZB: ds 16 +SAVEZP: ds 16 +MAINDB: + ENDIF +; +; DECODE AN OPCODE +; + tay ; 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: CMP #236 ; XCALL? + BNE OPX5 + JMP OPXCLL ; YES, PROCESS SEPARATELY +OPX5: CMP #250 ; IXCALL + BNE OPX6 + JMP OPXCLL +OPX6: 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 + CMP #$C0 ; IS IT NEW OPCODE RANGE? + BCC ZEXTOP ; YES + JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + +DOXOP: AND #%00011111 ; ISOLATE ID BITS + TAY + LDA OPTXL,Y + STA GOX+1+LO + LDA OPTXH,Y + STA GOX+1+HI +GOX: JSR $FFFF ;DUMMY + JMP MLOOP + + ; HANDLE EXTENDED OPCODE RANGE OPS + +ZEXTOP: CMP #EXTLEN ; OUT OF RANGE? + BCS BADEXT + TAY ; OFFSET ALREADY CORRECT + LDA EXTOPL,Y + STA GOE+1+LO + LDA EXTOPH,Y + STA GOE+1+HI +GOE: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #1 -- ILLEGAL X-OP *** + +BADOPX: LDA #1 + JMP ZERROR + + ; *** ERROR #16 -- ILLEGAL EXTENDED RANGE X-OP *** + +BADEXT: LDA #16 + JMP ZERROR + + ; HANDLE AN XCALL OPCODE + +OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + STA ABYTE + JSR NEXTPC + STA BBYTE + LDA ABYTE ; ONE TO START WITH + LDX #0 + STX ADEX ; INIT ARGUMENT INDEX + BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP +XCALL1: LDA ABYTE ; GET ARG BYTE + ASL A ; SHIFT NEXT 2 BITS + ASL A ; INTO BITS 7 & 6 + STA ABYTE ; HOLD FOR LATER +XCALL2: AND #%11000000 ; MASK OUT GARBAGE + BNE XCALL3 + JSR GETLNG ; 00 = LONG IMMEDIATE + JMP XCNXT +XCALL3: CMP #%01000000 ; SHORT IMMED? + BNE XCALL4 ; NO, TRY ANOTHER + JSR GETSHT ; 01 = SHORT IMMED. + JMP XCNXT +XCALL4: CMP #%10000000 ; LAST TEST + BNE OPX4 ; 11 = NO MORE ARGS + JSR GETVAR ; 10 = VARIABLE +XCNXT: LDX ADEX + LDA VALUE+LO + STA ARG1+LO,X + LDA VALUE+HI + STA ARG1+HI,X + INC NARGS + INX + INX + STX ADEX + CPX #16 + BNE XCALL5 + JMP OPX4 ; DONE, GO DO IT +XCALL5: CPX #8 ; DONE 1ST MODE BYTE? + BNE XCALL1 ; NOT QUITE YET + LDA BBYTE ; SET UP FOR NEXT + STA ABYTE ; MODE BYTE + JMP XCALL2 ; GO DO IT + +; ------------- +; HANDLE A 0-OP +; ------------- + +OP0: CMP #190 ; IS IT EXTOP OP + BEQ EXTOP ; YES + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT0L,Y + STA GO0+1+LO + LDA OPT0H,Y + STA GO0+1+HI +GO0: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #2 -- ILLEGAL 0-OP *** + +BADOP0: LDA #2 + JMP ZERROR + + ; THIS OPCODE TELLS THAT NEXT OP IS PART OF THE + ; EXTENDED RANGE OF OPCODES, GET IT AND PROCESS IT + ; (THEY ARE ALL XOPS) + +EXTOP: JSR NEXTPC ; GO GET EXTENDED RANGE OP + STA OPCODE ; SAVE IT + JMP OPEXT ; AND HANDLE IT + + +; ------------- +; HANDLE A 1-OP +; ------------- + +OP1: + and #%00110000 ; ISOLATE ARGUMENT BITS + bne OP1A + jsr NEXTPC ; get next byte + tay + jmp OP1A1 +OP1A: and #%00100000 ; TEST AGAIN + bne OP1B +; +; 01 = SHORT IMMEDIATE +; +OP1A1: sta ARG1+HI + jsr NEXTPC + sta ARG1+LO + inc NARGS + jmp OP1EX1 +OP1B: JSR GETVAR ; 10 = VARIABLE +OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] +OP1EX1: LDA OPCODE + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT1L,Y + STA GO1+1+LO + LDA OPT1H,Y + STA GO1+1+HI +GO1: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** ERROR #3 -- ILLEGAL 1-OP *** + +BADOP1: LDA #3 + JMP ZERROR + + + +; ------------- +; HANDLE A 2-OP +; ------------- + +OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT + BNE OP2A +; +; 0 = SHORT IMMEDIATE +; + sta ARG1+HI + jsr NEXTPC + sta ARG1+LO + inc NARGS + jmp OP2B1 +OP2A: jsr GETVAR ; 1 = VARIABLE +OP2B: jsr V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] +OP2B1: lda OPCODE ; RESTORE OPCODE BYTE + and #%00100000 ; ISOLATE 2ND ARG BIT + bne OP2C + sta ARG2+HI + jsr NEXTPC + sta ARG2+LO + jmp OP2D1 +OP2C: jsr GETVAR ; 1 = VARIABLE +OP2D: lda VALUE+LO ; MOVE 2ND [VALUE] + sta ARG2+LO ; INTO [ARG2] + lda VALUE+HI + sta ARG2+HI +OP2D1: inc NARGS ; UPDATE ARGUMENT COUNT + + ; EXECUTE A 2-OP OR EXTENDED 2-OP + +OP2EX: LDA OPCODE + AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT2L,Y + STA GO2+1+LO + LDA OPT2H,Y + STA GO2+1+HI +GO2: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 + diff --git a/apple/yzip/rel.13/objects.asm b/apple/yzip/rel.13/objects.asm new file mode 100644 index 0000000..a7f6f78 --- /dev/null +++ b/apple/yzip/rel.13/objects.asm @@ -0,0 +1,167 @@ + STTL "--- OBJECT & PROPERTY HANDLERS ---" + PAGE + +; ---------------------------------- +; GET ABSOLUTE ADDRESS OF OBJECT [A] +; ---------------------------------- +; ENTER: OBJECT IN A/X (LO/HI) +; EXIT: ADDRESS IN [FPC] +OBJLOC: + STX I+HI ; SAVE MSB FOR SHIFTING + ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) + STA I+LO + ROL I+HI + LDX I+HI + ASL A + ROL I+HI ; *4 + ASL A + ROL I+HI ; *8 + ASL A + ROL I+HI ; *16 + SEC + SBC I+LO ; -(*2) + STA I+LO ; SO IS *14 TOTAL + LDA I+HI + STX I+HI + SBC I+HI + STA I+HI + LDA I+LO + CLC + ADC #112 ; ADD OBJECT TABLE OFFSET + BCC OBJ3 + INC I+HI +OBJ3: + clc ; NEXT ADD THE relative ADDR + adc ZBEGIN+ZOBJEC+1 ; OF THE OBJECT TABLE + sta FPCL ; save lo byte + lda I+HI + adc ZBEGIN+ZOBJEC ; now work on page + jsr SETPC ; now get page/bank + sta FPCH ; this is hi part + sty FPCBNK ; and this is the bank + rts +; ----------------------------- +; GET ADDRESS OF PROPERTY TABLE +; ----------------------------- +; EXIT: [FPC] HAS ABSOLUTE ADDR OF PROPERTY TABLE +; including OFFSET TO START OF PROP IDS +PROPB: + lda ARG1+LO + ldx ARG1+HI ; get address + jsr OBJLOC ; put table location into FPC + lda #12 ; add 12 to get to beginning + jsr ADDFPC ; and add it to FPC + jsr FETCHB ; get MSB of P-TABLE Address + pha ; and save it for a moment + jsr NEXTFPC ; to get LSB + jsr FETCHB ; get LSB of P-TABLE Address + sta FPCL ; and save lo part + pla ; get page back + jsr SETPC ; and set up memory bank/page + sta FPCH ; save page + sty FPCBNK ; and bank + jsr FETCHB ; get length of short description + asl A ; WORD-ALIGN IT + jsr ADDFPC ; and add it to FPC + jsr NEXTFPC ; POINT JUST PAST THE DESCRIPTION + rts + + +; ------------------- +; FETCH A PROPERTY ID +; ------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +; +PROPN: + jsr FETCHB ; get the byte + and #%00111111 ; MASK OUT LENGTH BITS (EZIP) + rts + +; ------------------------------- +; FETCH # BYTES IN PROPERTY VALUE +; ------------------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +; +PROPL: + jsr FETCHB ; CHECK LENGTH FLAGS + tax ; save it + bpl SHORT ; OFF, SO 1 OR 2 BYTES + jsr NEXTFPC + jsr FETCHB ; NEXT BYTE HAS LENGTH + and #%00111111 ; MASK OFF EXTRA BITS + rts +SHORT: + and #%01000000 ; BIT 6 + beq ONE + lda #2 ; BIT 6 = 1, LENGTH =2 + rts +ONE: + lda #1 ; BIT 6 = 0, LENGTH =1 + rts + +; ---------------------- +; POINT TO NEXT PROPERTY +; ---------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - in [FPC]) +; +PROPNX: + jsr PROPL ; GET LENGTH OF CURRENT PROP + tay ; move one more for correct alignment + iny ; okay, done it + tya ; thanks + jsr ADDFPC ; add to [FPC] + rts +; +; ---------------- +; GET OBJECT FLAGS +; ---------------- +; ENTRY: OBJECT # IN [ARG1], FLAG # IN [ARG2] +; EXIT: FLAG WORD IN [K], BIT ID IN [J], +; FLAG WORD ADDRESS IN [FPC] +; +FLAGSU: + LDA ARG1+LO ; get table offset + LDX ARG1+HI + JSR OBJLOC ; GET OBJECT ADDR IN [FPC] + LDA ARG2+LO ; LOOK AT FLAG ID + CMP #$10 ; FIRST SET OF FLAGS? + BCC FLS1 ; YES, ADDR IN [FPC] IS CORRECT + SBC #16 ; ELSE ZERO-ALIGN FLAG INDEX + TAX ; SAVE IT HERE + CMP #$10 ; CHECK IF IN 2ND WORD + BCC FLS ; YES, GO ALIGN FOR THAT + SBC #16 ; ELSE ALIGN TO 3RD WORD + TAX + lda #4 ; 3rd Flag word + bne FLSx ; and add it in +FLS: + lda #2 ; 2nd Flag word +FLSx: + jsr ADDFPC +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: + jsr FETCHB ; MOVE THE FLAG WORD + sta K+HI ; INTO [K] - FIRST THE MSB + jsr NEXTFPC ; and then get get LSB + jsr FETCHB + sta K+LO ; THEN THE LSB + jmp PREVFPC ; point back to flag word + + END + \ No newline at end of file diff --git a/apple/yzip/rel.13/ops012.asm b/apple/yzip/rel.13/ops012.asm new file mode 100644 index 0000000..329d754 --- /dev/null +++ b/apple/yzip/rel.13/ops012.asm @@ -0,0 +1,1215 @@ + STTL "--- 0-OPS ---" + PAGE + + +; ----- +; 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: LDX #5 ;MOVE ZPC INTO MPC +ZPRI1: + LDA ZPC,X + STA MPC,X + DEX + BPL ZPRI1 ;NO NEED TO VALIDATE AS ZPC WAS VALID ANYWAY + JSR PZSTR ; PRINT THE Z-STRING AT [MPC] + LDX #5 ; COPY STATE OF [MPC] +ZPRI2: LDA MPC,X ; INTO [ZPC] + STA ZPC,X + DEX + BPL ZPRI2 + RTS + + +; ------ +; PRINTR +; ------ +; DO A "PRINTI," FOLLOWED BY "CRLF" AND "RTRUE" + +ZPRR: JSR ZPRI + JSR ZZCRLF + JMP ZRTRUE + + +; ------ +; RSTACK +; ------ +; "RETURN" WITH VALUE ON STACK + +ZRSTAK: JSR POPVAL ; GET VALUE INTO [X/A] + JMP ZRT1 ; AND GIVE IT TO "RETURN" + + +; ----- +; CATCH +; ----- + +ZCATCH: LDX OLDZSP+HI ; RETURN ZSTACK POINTER AS + LDA OLDZSP+LO ; ZRET WILL NEED IT + JMP PUTBYT + + +; --------- +; ORIGINAL? +; --------- + +; COPY PROTECTION DEVICE, RETURNS TRUE FOR NOW + +ZORIG: JMP PREDS + + + STTL "--- 1-OPS ---" + PAGE + + +; ----- +; 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC ; GET OBJECT ADDR INTO [FPC] + lda #8 ; POINT TO "NEXT" SLOT (EZIP) + jsr ADDFPC ; and point to it + jmp FIRST1 ; JMP to get it + +; ------ +; FIRST? +; ------ +; RETURN "FIRST" POINTER IN OBJECT [ARG1] ; +; FAIL IF LAST AND RETURN ZERO +; (EZIP ALTERATIONS) + +ZFIRST: + lda ARG1+LO + ldx ARG1+HI + jsr OBJLOC ; GET OBJECT ADDR INTO [FPC] + lda #10 ; point to "First" slot + jsr ADDFPC ; and add it +FIRST1: + jsr FETCHB ; and get it + pha ; save it + jsr NEXTFPC + jsr FETCHB ; and next one + tay ; now dance around a little; save LSB + pla ; get MSB back + tax ; and put to x + tya ; and put LSB back into [A] + jsr PUTBYT ; PASS IT TO VARIABLE + lda VALUE+LO ; EXAMINE THE VALUE JUST "PUT" + bne PFINE + lda VALUE+HI + beq PYUCK ; FAIL IF IT WAS ZERO +PFINE: + jmp PREDS ; ELSE REJOICE + +; --- +; LOC +; --- +; RETURN THE OBJECT CONTAINING OBJECT [ARG1] ; +; RETURN ZERO IF NONE +; (EZIP ALTERED) + +ZLOC: + lda ARG1+LO + ldx ARG1+HI + cpx #$20 ; don't let it get too high + bcc ZLOC1 ; fine + lda #22 ; too big object + jmp ZERROR ; and die +ZLOC1: + jsr OBJLOC ; GET ADDR OF OBJECT INTO [FPC] + lda #6 ; POINT TO "LOC" SLOT + jsr ADDFPC ; and make FPC point there + jsr FETCHB ; go get byte + pha ; save this please + jsr NEXTFPC ; and point to next one + jsr FETCHB ; and get it in [A] + tay ; save LSB + pla ; get MSB back + tax ; and put to [X] + tya ; and put LSB into a + jmp PUTBYT ; AND SHIP IT OUT + +; ------ +; PTSIZE +; ------ +; RETURN LENGTH OF PROP TABLE [ARG1] IN BYTES + +ZPTSIZ: + lda ARG1+HI ; MOVE ABS ADDR OF + jsr SETPC ; get bank/page + sta FPCH ; save page + sty FPCBNK ; and bank + lda ARG1+LO + sta FPCL ; and save lo part + jsr PREVFPC ; Decrement address while moving LSB +PTZ0: + jsr FETCHB ; get length of property + bmi PTZ2 ; BIT 7 = 1, LENGTH > 2 BYTES + and #%01000000 + beq PTZ1 ; BIT 6 = 0, LENGTH = 1 + lda #2 ; BIT 6 = 1, LENGTH = 2 + bne PTZ3 ; JMP +PTZ1: + lda #1 + bne PTZ3 ; JMP +PTZ2: + jsr FETCHB ; and get it + and #%00111111 ; ELSE PICK UP SIZE > 2 +PTZ3: + ldx #0 ; CLEAR FOR PUTBYT + jmp PUTBYT +; --- +; INC +; --- +; INCREMENT VARIABLE [ARG1] + +ZINC: LDA ARG1+LO + JSR VARGET ; FETCH VARIABLE INTO [VALUE] + INC VALUE+LO + BNE ZINC1 + INC VALUE+HI +ZINC1: JMP ZD0 + + +; --- +; DEC +; --- +; DECREMENT VARIABLE [ARG1] + +ZDEC: LDA ARG1+LO + JSR VARGET ; FETCH VAR INTO [VALUE] + LDA VALUE+LO + SEC + SBC #1 + STA VALUE+LO + LDA VALUE+HI + SBC #0 + STA VALUE+HI +ZD0: LDA ARG1+LO ; PUT RESULT BACK + JMP VARPUT ; INTO THE SAME VARIABLE + + +; ------ +; PRINTB +; ------ +; PRINT Z-STRING AT [ARG1] + +ZPRB: + lda ARG1+LO ; move arg1 to I + sta I+LO ; lo part + lda ARG1+HI ; and now for arg1 hi + sta I+HI ; okay + jsr SETWRD ; make [MPC] point to it + jmp PZSTR ; and print it + +; ------ +; REMOVE +; ------ +; MOVE OBJECT [ARG1] INTO PSEUDO-OBJECT #0 +; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO +; 2) MOVES AND COMPARES 2 BYTES) + +SAVEFPC: ds 3 ; spot to save the FPC +SAVEOBJ: ds 1 ; check for zero object + +ZREMOV: + lda ARG1+LO ; GET SOURCE OBJECT ADDR + ldx ARG1+HI + jsr OBJLOC ; INTO [FPC] +; +; now save this objects address in I,J +; + lda #6 ; point to the LOC slot + jsr ADDFPC ; thank you + lda FPCL ; COPY THE SOURCE ADDR + sta SAVEFPC+LO ; INTO [J] + lda FPCH ; FOR LATER REFERENCE + sta SAVEFPC+HI + lda FPCBNK + sta SAVEFPC+ABANK +; +; now go get object this one is in +; + jsr FETCHB ; get the data + sta K ; HOLD IT + jsr NEXTFPC ; get lo part + jsr FETCHB ; now get part + tay ; save it + ora K ; COMPARE BYTES + bne REMVj ; check for object + jmp REMVEX ; SCRAM IF NO OBJECT +REMVj: + tya ; get lo part + ldx K ; and hi part + jsr OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [FPC] + lda #11 ; POINT TO "FIRST" SLOT, LSB + jsr ADDFPC ; and point to it + jsr FETCHB ; and get it + pha ; save LSB + jsr PREVFPC ; point to MSB + jsr FETCHB ; A=LO, X=HI + tax ; put into x + pla ; get LSB back + cmp ARG1+LO ; IS THIS THE FIRST? + bne REMVC1 ; NO, KEEP SEARCHING + cpx ARG1+HI ; HM? + beq DO_REMOVE ; yes, so use it +REMVC1: + jsr OBJLOC ; get object + lda #9 ; GET "NEXT" slot address + jsr ADDFPC ; into FPC + jsr FETCHB ; get the byte + pha ; save LSB for later + jsr PREVFPC ; and this is the hi part + jsr FETCHB + sta SAVEOBJ ; save for later check + tax ; and put into x for (possible) check + pla ; get lo part back + tay ; save a minute + ora SAVEOBJ ; well, is it zero? + bne REMVC2 ; no, so check it + lda #21 ; so die + jmp ZERROR ; and croak +REMVC2: + tya ; put back into [A] + cmp ARG1+LO ; FOUND IT? + bne REMVC1 ; NO, KEEP TRYING + cpx ARG1+HI + bne REMVC1 +DO_REMOVE: +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; copied +; +; now get removed one's address for fetching +; + lda SAVEFPC+ABANK ; this is where bank is + sta FPCBNK ; so show it + lda SAVEFPC+HI ; and here's the hi/lo part + sta FPCH + lda SAVEFPC+LO + sta FPCL + lda #2 ; so get to source's "NEXT" slot + jsr ADDFPC ; point to next slot + jsr FETCHB ; get the hi byte + jsr STASHB ; and save it + jsr NEXTSPC ; point to next one + jsr NEXTFPC ; and from the source too + jsr FETCHB ; get lo byte + jsr STASHB ; and save it away +; +; now zero out SOURCE's loc and next spots +; + lda SAVEFPC+ABANK ; bank of source + sta SPCBNK + lda SAVEFPC+HI ; and addr of source LOC slot + sta SPCH + lda SAVEFPC+LO + sta SPCL +; +; zero out NEXT and LOC of source +; + lda #0 ; zero out 4 locations (LOC MSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (LOC LSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (NEXT MSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (NEXT LSB) + jsr STASHB + jsr NEXTSPC +REMVEX: + RTS + + +; ------ +; PRINTD +; ------ +; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + +ZPRD: + lda ARG1+LO + ldx ARG1+HI ; (EZIP) + jsr OBJLOC ; GET ADDR OF OBJECT INTO [FPC] + lda #13 ; GET PROP TABLE POINTER (EZIP) + jsr ADDFPC ; and point to LSB + jsr FETCHB ; fetch LSB + pha ; SAVE IT HERE + jsr PREVFPC ; and now fetch MSB + jsr FETCHB ; thank you + sta I+HI ; AND MSB + pla ; get LSB back + sta I+LO ; STORE LSB + 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+LO ; RE-SYNC THE + STA ZSP+LO ; Z-STACK POINTER + LDA OLDZSP+HI + STA ZSP+HI + JSR POPVAL ; POP # LOCALS INTO [X/A] + STX I+HI ; SAVE HERE + JSR POPVAL ; now we need number of args + STA ASSVLU ; for ASSIGNED? + + LDX I+HI ; see how many 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 IRET + STA ZPCL + JSR POPVAL + STX OLDZSP+LO + STA OLDZSP+HI + + LDA ZPCL ; check for zero zpc + BNE RETj ; which means we are returning to + LDA ZPCM ; an internal call + BNE RETj ; rather than just a normal + LDA ZPCH ; return + BNE RETj ; but so far it isn't + + JSR A12VAL ; MOVE [ARG1] TO [VALUE] + JMP ZIRET ; so then do internal return +RETj: + JSR VLDZPC ; MAKE VALID + LDA IRET ; CHECK IF SHOULD RETURN A VALUE + BEQ RETYES ; (0 = RET, 1 = NO RETURN) + RTS ; NO, SO JUST GET OUT OF HERE +RETYES: + 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 (QUAD) 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 + + + + STTL "--- 2-OPS ---" + PAGE + + +; ----- +; 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 + + +; ----------------- +; SIGNED COMPARISON +; ----------------- +; ENTRY: VALUES IN [VALUE] AND [I] +; +; IS [VALUE] > [I] +; +COMPAR: + LDA I+HI + EOR VALUE+HI + BPL SCMP + LDA I+HI + CMP VALUE+HI + BCC PGOOD + JMP PREDF + +SCMP: LDA VALUE+HI + CMP I+HI + BNE SCEX + LDA VALUE+LO + CMP I+LO +SCEX: BCC PGOOD + JMP PREDF + + +; --- +; IN? +; --- +; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? +ZIN: + LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [FPC] + LDA #6 ; POINT TO "LOC" SLOT + jsr ADDFPC ; and point to it + jsr FETCHB ; well? + CMP ARG2+HI ; IS IT THERE? + BNE PBAD ; NO + jsr NEXTFPC ; point to lo part + jsr FETCHB ; and get it + CMP ARG2+LO + 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 + + ; FALL THROUGH ... + + +; --------------------- +; RETURN VALUE IN [X/A] +; --------------------- + +VEXIT: STX VALUE+LO + STA VALUE+HI + JMP PUTVAL + + +; ---- +; BAND +; ---- +; RETURN [ARG1] "AND" [ARG2] + +ZBAND: LDA ARG1+LO + AND ARG2+LO + TAX + LDA ARG1+HI + AND ARG2+HI + JMP VEXIT + + +; ----- +; FSET? +; ----- +; IS FLAG [ARG2] SET IN OBJECT [ARG1]? + +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 [FPC] +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; okay, done it + lda K+HI ; FIRST DO MSBS + ora J+HI + jsr STASHB + jsr NEXTSPC + lda K+LO ; THEN LSBS + ora J+LO + jsr STASHB + rts + + +; ------ +; FCLEAR +; ------ +; CLEAR FLAG [ARG2] IN OBJECT [ARG1] + +ZFCLR: + jsr FLAGSU ; GETS BITS INTO [J] & [K], ADDR IN [FPC] +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; okey dokey + + lda J+HI ; FETCH MSB + eor #$FF ; COMPLEMENT IT + and K+HI ; RUB OUT FLAG + jsr STASHB ; and save it + jsr NEXTSPC ; point to lo part + lda J+LO ; SAME FOR LSB + eor #$FF + and K+LO + jsr STASHB ; and show it to the world + 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] +; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + +ZMOVE: + jsr ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS +; +; Make [ARG1] be first in [ARG2]'s chain. +; + lda ARG2+LO + ldx ARG2+HI ; Get parent's address + jsr OBJLOC ; into [FPC] + lda #10 ; point to FIRST slot + jsr ADDFPC ; okay + jsr FETCHB ; get old first one (MSB) + sta K+HI ; save it + jsr NEXTFPC ; point to next part + jsr FETCHB ; and get it + sta K+LO ; okay, saved + jsr FP2SP ; make FPC == SPC +; +; now make object [ARG1] be first in object [ARG2] +; SPC is currently pointing to LSB of [ARG2]'s FIRST slot +; + lda ARG1+LO ; stash away low part first + jsr STASHB ; stashed + jsr PREVSPC ; point to high part + lda ARG1+HI ; get hi part of source + jsr STASHB ; save it +; +; now point to object [ARG1] to update its slots +; + ldx ARG1+HI ; put hi part here + lda ARG1+LO ; and lo part here for OBJLOC + jsr OBJLOC ; get me the SOURCE of all confusion + lda #6 ; point to LOC slot + jsr ADDFPC ; and now FPC points there + jsr FP2SP ; now make it the STASH pointer +; +; update [ARG1]s LOC pointer to be [ARG2] +; SPC points to LOC slot +; + lda ARG2+HI ; get PARENT number + jsr STASHB ; and save it in LOC + jsr NEXTSPC ; and point to LSB of LOC + lda ARG2+LO ; got parent's lowness + jsr STASHB ; and saved it in ARG1 +; +; Move old FIRST object and make it [ARG1]s NEXT +; now SPC points to [ARG1]s NEXT slot +; + jsr NEXTSPC ; point to MSB of NEXT + lda K+HI ; get old FIRST one + jsr STASHB ; and save it + jsr NEXTSPC ; and point to LSB now + lda K+LO ; get LSB of this + jsr STASHB ; saved + 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 + LDA #0 + 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 + ADC #0 ; PICK UP CARRY FROM MPCM + STA MPCH ; TO GET TOP BIT + JMP VLDMPC + + +; ---- +; GETP +; ---- +; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 + +ZGETP: + jsr PROPB ; set up FPC +GETP1: + jsr PROPN ; GET ID OF PROP TBL + cmp ARG2+LO ; Compare PROP ID + beq GETP3 ; FOUND IT + bcc GETP2 ; NOT THERE + jsr PROPNX ; GET NEXT PROP, ALIGN [FPC] TO IT + jmp GETP1 ; TRY AGAIN WITH NEXT PROP +; +; PROPERTY NOT THERE, GET DEFAULT +; +GETP2: + lda ARG2+LO ; GET PROPERTY # + sec ; ZERO-ALIGN IT + sbc #1 + asl A ; WORD-ALIGN IT + clc ; add in table start + adc ZBEGIN+ZOBJEC+1 ; add lo part + sta FPCL ; save for fetch + lda ZBEGIN+ZOBJEC ; now get hi part + adc #0 ; pick up carry, if any + jsr SETPC ; get memory spot for this page + sta FPCH ; page and + sty FPCBNK ; bank + jsr FETCHB ; GET MSB OF PROPERTY + sta VALUE+HI + jsr NEXTFPC + jsr FETCHB ; DO SAME WITH LSB + sta VALUE+LO + jmp PUTVAL ; RETURN DEFAULT IN [VALUE] +GETP3: + jsr PROPL ; GET LENGTH OF PROP INTO [A] + tax ; save [A] + jsr NEXTFPC ; MAKE [FPC] POINT TO 1ST BYTE OF PROP + cpx #1 ; IF LENGTH =1 + beq GETPB ; GET A BYTE PROPERTY + cpx #2 ; IF LENGTH = 2 + beq GETPW ; GET A WORD PROPERTY + + ; *** ERROR #7: PROPERTY LENGTH *** + + LDA #7 + JMP ZERROR +; +; GET A 1-BYTE PROPERTY +; +GETPB: + jsr FETCHB ; GET LSB INTO [A] + sta VALUE+LO ; STORE LSB + lda #0 ; CLEAR MSB + sta VALUE+HI ; and zero it + beq ETPEX +; +; GET A 2-BYTE PROPERTY +; +GETPW: + jsr FETCHB ; GET MSB + sta VALUE+HI ; store MSB + jsr NEXTFPC ; POINT TO LSB + jsr FETCHB ; GET IT INTO [A] + sta VALUE+LO ; AND MSB +ETPEX: + jmp PUTVAL + +; ----- +; GETPT +; ----- +; RETURN POINTER TO PROP TABLE [ARG2] +; IN OBJECT [ARG1] + +ZGETPT: + lda ARG1+LO + ldx ARG1+HI ; (EZIP) + jsr OBJLOC ; put location into [FPC] + lda #12 ; get offset table pointer + jsr ADDFPC ; and point to it + jsr FETCHB ; get MSB of table pointer + pha ; save page + jsr NEXTFPC ; point to LSB + jsr FETCHB ; and get it + sta FPCL ; and save it + pla ; get page address back + jsr SETPC ; and absolutize it + sta FPCH ; and save page + sty FPCBNK ; and bank + jsr FETCHB ; GET LENGTH OF SHORT DESC + asl A ; WORD-ALIGN IT + tay ; now point to just past it + iny ; thank you + tya ; for adding + jsr ADDFPC ; and POINT JUST PAST THE DESCRIPTION +GETPT1: + jsr PROPN ; get prop ID + cmp ARG2+LO ; CHECK ID + beq GETPT2 + bcs DDD ; .GE. so check some more + jmp DORET ; BEYOND IT, SO NOT THERE +DDD: + jsr PROPNX ; point to next one + jmp GETPT1 ; next please +GETPT2: + jsr PROPL ; get the length of this property + jsr NEXTFPC ; INC TO POINT AT PROPERTY VALUE (EZIP) +; +; now subtract absolute address to get relative address for returning +; what a pain in the neck +; + lda FPCBNK ; check which bank we are in + beq GETPB0 ; in main bank, it's easier +; +; if in AUX bank, then we must subtract beginning of AUX mem, then +; add in size of MAIN bank +; + lda FPCH ; get page + cmp #>Z3BEGIN ; in part 2 of aux? + bcs GETPB3 ; ayyup + sec ; and subtract + sbc #>Z2BEGIN ; first page in aux + clc ; now add in how many pages in main + adc #P2PAGE ; now we have relative start + bne GETP15 ; JUMP to putval +GETPB3: + sec ; and subtract + sbc #>Z3BEGIN ; first page in aux, part 2 + clc ; now add in how many pages in main + adc #P3PAGE ; now we have relative start + bne GETP15 ; jump to putval +GETPB0: + lda FPCH ; get page in main mem + sec ; and then subtract + sbc #>ZBEGIN ; start of main mem +GETP15: + sta VALUE+HI ; save hi part for returning + lda FPCL ; and just save lo part + sta VALUE+LO ; okay? + jmp PUTVAL ; AND RETURN +DORET: + jmp RET0 ; ELSE RETURN A ZERO + + +; ----- +; NEXTP +; ----- +; RETURN INDEX # OF PROP FOLLOWING PROP [ARG2] IN OBJECT [AR +; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO + +ZNEXTP: + JSR PROPB ; ALIGN [FPC] AT PROPERTY TBL'S 1ST ENTRY + 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 (EZIP) + JMP NXTP1 +NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +NXTP3: JSR PROPN ; GET THE PROPERTY # + LDX #0 ; FOR PUTBYT (EZIP) + 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 + + +; ----- +; THROW +; ----- + +ZTHROW: + lda ARG2+LO ; check to see if we are ready to do return + cmp OLDZSP+LO + bne ZTHLOOP ; nope, keep unwinding the stack + lda ARG2+HI + cmp OLDZSP+HI ; have we found the right frame yet? + beq ZTHDO ; yes +ZTHLOOP: + jsr ZRET ; do another return + jmp ZTHROW ; and try again +ZTHDO: + lda ARG2+LO ; SET ZSTACK POINTER + sta OLDZSP+LO ; UP FOR ZRET + lda ARG2+HI + sta OLDZSP+HI + jmp ZRET + + END diff --git a/apple/yzip/rel.13/opsx.asm b/apple/yzip/rel.13/opsx.asm new file mode 100644 index 0000000..774df57 --- /dev/null +++ b/apple/yzip/rel.13/opsx.asm @@ -0,0 +1,903 @@ + PAGE + STTL "--- X-OPS ---" + + + ; ------ + ; EQUAL? + ; ------ + ; IS [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? + +ZEQUAL: + DEC NARGS ; DOUBLE-CHECK # ARGS + 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!) + + +; ---------------------------- +; ICALL,ICALL1, ICALL2, IXCALL +; ---------------------------- + +ZICALL: +ZICLL1: +ZICLL2: +ZIXCLL: LDA #1 ; SET FLAG FOR RETURNLESS CALL + STA IRET + BNE IENTR ; JMP OVER NORMAL SETTING + + +; ------------------- +; XCALL, CALL1, CALL2 +; ------------------- + +ZXCALL: ; DROP THROUGH +ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +ZCALL2: + +; ---- +; CALL +; ---- +; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +; ([ARG5]-[ARG8] FOR XCALL (EZIP)) + +ZCALL: LDA #0 + STA IRET ; SET FLAG TO RETURN SOMETHING +IENTR: LDA ARG1+LO + ORA ARG1+HI ; IS CALL ADDRESS ZERO? + BNE DOCALL ; NO, CONTINUE + LDA IRET ; any ret value? + BEQ Ij ; yes, so return a zero + + RTS ; otherwise, just end +Ij: + LDX #0 + JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER + LDA OLDZSP+HI + JSR PUSHXA + LDA ZPCL ; AND LSB OF [ZPC] + LDX IRET ; AND RETURN FLAG + 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 + ASL ARG1+LO ; MULTIPLY [ARG1] + ROL ARG1+HI ; (BY 2) + ROL A ; >BIT INTO [A] + ASL ARG1+LO ; BY 4 (EZIP) + ROL ARG1+HI + ROL A + STA ZPCH ; NEW >BIT OF [ZPC] + LDA ARG1+HI ; GET NEW 0, just ignore! + ORA ARG3+LO + BEQ INTNF ; SAY NOT FOUND + + LDA NARGS ; IS THERE A RECORD SPEC? + CMP #4 + BEQ SET4 +SETDEF: LDA #130 ; NO, SET DEFAULT + STA ARG4+LO + +SET4: LDA ARG4+LO + BEQ SETDEF ; GO BACK AND GET VALUE + LDA #0 ; COMPARE BYTE OR WORD? + ASL ARG4+LO + ROL A ; PICK UP INDICATOR + LSR ARG4+LO ; CLEAR FROM RECORD LENGTH + STA TYPE ; BYTE (0) OR WORD (1) + LDA TYPE ; SET FLAG + BNE SETTBL + LDA ARG1+LO ; IF ONLY BYTE, MOVE IT + STA ARG1+HI ; TO FIRST BYTE CHECKED +SETTBL: + LDA ARG2+LO ; PICK UP TBL ADDR + STA MPCL + LDA ARG2+HI + STA MPCM + LDA #0 + STA MPCH ; ONLY A WORD ADDR, SO IN 1ST 64K + JSR VLDMPC + +INTLP: LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + JSR GETBYT ; GET 1ST BYTE + CMP ARG1+HI ; DOES IT = THE VALUE LOOKING FOR? + BNE INTNXT ; NO + LDA TYPE + BEQ INTFND ; ONLY COMPARING A BYTE SO FOUND! + JSR GETBYT + CMP ARG1+LO + BEQ INTFND ; YES, FOUND IT +INTNXT: + LDA VWCUR+0 ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC ARG4+LO ; ENTRY + STA MPCL + BCC INEXT0 + + LDA VWCUR+1 ; PICK UP CARRY + ADC #0 + STA MPCM + LDA VWCUR+2 + ADC #0 + STA MPCH + JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE + +INEXT0: DEC ARG3+LO ; CHECKED ALL ENTRIES? + BNE INTLP + LDA ARG3+HI + BEQ INTNF + DEC ARG3+HI + BNE INTLP + +INTNF: + LDA #0 ; 0 = NOT FOUND + STA VALUE+LO + STA VALUE+HI + JSR PUTVAL + JMP PREDF ; FAILED! + +INTFND: + LDA VWCUR+LO + STA VALUE+LO ; AND SET TO RETURN THE VALUE + LDA VWCUR+HI + STA VALUE+HI + JSR PUTVAL ; SEND IT BACK + JMP PREDS ; AND SCREEM SUCCESS + +; ---- +; BCOM +; ---- +; COMPLEMENT [ARG1] + +ZBCOM: LDA ARG1+LO + EOR #$FF + STA VALUE+LO + LDA ARG1+HI + EOR #$FF + STA VALUE+HI + JMP PUTVAL + + +; ----- +; COPYT +; ----- + +ZCOPYT: + LDA ARG2+LO ; CHECK OUT WHAT'S TO BE DONE + ORA ARG2+HI + BNE ZC0 + JMP CASE1 ; ZERO LENGTH BYTES OF SOURCE +ZC0: + LDA ARG3+HI + CMP #$7F + BCC CASE2 + JMP CASE3 ; FORWARD COPY + + ; CASE2 - CHECK IF FORWARD OR BACKWARD COPY + +CASE2: LDA ARG1+HI ; IF SRC < DEST + CMP ARG2+HI + BCC CHK2 + BEQ ZC1 + JMP FRWRD ; NO +ZC1: LDA ARG1+LO + CMP ARG2+LO + BEQ CHK2 + BCS FRWRD ; NO +CHK2: LDA ARG1+LO ; AND SRC + LENGTH > DEST + CLC + ADC ARG3+LO + STA I+LO + LDA ARG1+HI + ADC ARG3+HI + CMP ARG2+HI + BCC FRWRD ; NO + BNE BKWRD ; YES + LDA I+LO + CMP ARG2+LO + BEQ FRWRD ; DEBUG, IF EQUAL REALLY LESS + BCS BKWRD ; OVERLAPS SO DO BACKWARD COPY + + ; ELSE FALL THROUGH TO FORWARD COPY + +FRWRD: LDA #0 ; USE GETBYT CAUSE MAY BE + STA MPCH ; BEYOND MAIN MEMORY + LDA ARG1+HI + STA MPCM + LDA ARG1+LO + STA MPCL + JSR VLDMPC ; AND ALIGN TO CORRECT PAGE + LDA ARG2+LO + STA SPCL + LDA ARG2+HI + jsr SETPC ; get memory spot + sta SPCH ; high part + sty SPCBNK ; and the bank part + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI +FRLP: + jsr DECJ + bcc FRDUN ; CARRY CLEAR ON $FFFF + jsr GETBYT + jsr STASHB ; and save it + jsr NEXTSPC ; and point to next one + jmp FRLP +FRDUN: + rts + + +BKWRD: + LDA ARG3+LO ; DECR 1ST TO GET CORRECT OFFSET + STA J+LO + LDA ARG3+HI + STA J+HI + JSR DECJ + LDA ARG1+LO ; SET TO END OF SOURCE & DEST. + CLC + ADC J+LO + sta FPCL ; set up fetch pointer + LDA ARG1+HI + ADC J+HI + jsr SETPC ; and get mem locations + sta FPCH + sty FPCBNK + LDA ARG2+LO + CLC + ADC J+LO + sta SPCL ; and now set up stash pointer + LDA ARG2+HI + ADC J+HI + jsr SETPC ; and get me page/bank + sta SPCH + sty SPCBNK +BKLP: + jsr FETCHB ; get byte + jsr STASHB ; and save it + jsr PREVFPC ; going backwards + jsr PREVSPC ; and here too + jsr DECJ ; RETURNS CARRY CLEAR ON $FFFF + bcs BKLP +BKDUN: + RTS + + ; ZERO LENGTH # OF BYTES OF SOURCE + +CASE1: LDA ARG1+LO + STA SPCL ; set stash pointer + LDA ARG1+HI + jsr SETPC ; get page/bank + sta SPCH + sty SPCBNK + LDA ARG3+LO ; SET UP COUNTER + STA J+LO + LDA ARG3+HI + STA J+HI +C1LP: + jsr DECJ ; CARRY CLEAR WHEN J = $FFFF + bcc C1DUN + lda #0 + jsr STASHB ; and zero it + jsr NEXTSPC ; and point to next one + jmp C1LP +C1DUN: + rts + + ; 2'S COMPLEMENT LENGTH (XOR + 1) THEN DO FORWARD COPY + +CASE3: + LDA ARG3+LO + EOR #$FF + STA ARG3+LO + LDA ARG3+HI + EOR #$FF + STA ARG3+HI + INC ARG3+LO + BNE GOFRWD + INC ARG3+HI +GOFRWD: JMP FRWRD + + +; --------- +; ASSIGNED? +; --------- + + +ZASSND: + LDA ARG1+LO ; COMPARE TO # OF OPTIONALS FROM LAST CALL + CMP ASSVLU + BCC DOYES ; IF LESS OR EQUAL, WAS ASSIGNED + BEQ DOYES + JMP PREDF +DOYES: + JMP PREDS + + +; ------------- +; LOGICAL SHIFT +; ------------- +; SHIFT ARG1, ARG2 BITS (LEFT IF ARG2 IS POS. RIGHT IF NEG.) + +ZSHIFT: LDA ARG1+LO ; SET UP FOR SHIFT + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCS SRIGHT + + ; SHIFT LEFT + + TAY ; COUNT +SLP1: ASL VALUE+LO + ROL VALUE+HI + DEY + BNE SLP1 + JMP PUTVAL ; AND RETURN THE VALUE + +SRIGHT: EOR #$FF ; COMPLEMENT + TAY +SLP2: LSR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL SLP2 + JMP PUTVAL + + +; ---------------- +; ARITHMETIC SHIFT +; ---------------- +; PROPAGATING SIGN BIT ON RIGHT SHIFT + +ZASHFT: LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCC ZSHIFT ; SAME AS LOGICAL SHIFT + LDX ARG1+LO ; SET UP FOR SHIFT + STX VALUE+LO + LDX ARG1+HI + STX VALUE+HI + + EOR #$FF ; COMPLEMENT COUNT + TAY +ASLP2: LDA ARG1+HI + ASL A ; GET SIGN BIT + ROR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL ASLP2 + JMP PUTVAL + +; -------- +; XPUSH +; -------- +ZXPUSH: + lda ARG2+LO ; get me the address of the LTABLE + sta FPCL ; for munging with + lda ARG2+HI ; this is page + jsr SETPC ; get me actual page/bank + sta FPCH ; set page + sty FPCBNK ; and bank + + jsr FETCHB ; this is hi part of counter + sta J+HI ; save it + jsr NEXTFPC ; point to lo part + jsr FETCHB ; get it + sta J+LO ; thanx + ora J+HI ; check for zero elements left + bne ZXP0 ; yes, there is room at the inn + + jmp PREDF ; no room here! +ZXP0: + jsr FP2SP ; set up to stash back in beginning of LTABLE + lda J+HI ; now the MSB + sta K+HI ; and saved it + lda J+LO ; save this + sta K+LO ; save it +; +; now count this one and stash it into the table +; + bne ZXP1 ; nope, dec okay + dec J+HI ; decrement MSB +ZXP1: + dec J+LO ; and the LSB + lda J+LO ; LSB first + jsr STASHB ; saved it + jsr PREVSPC ; point to MSB + lda J+HI ; get it + jsr STASHB ; saved it +; +; finally, we can save the arg into the stack +; + asl K+LO ; make a word offset (*2) + rol K+HI ; pick up carry maybe + lda K+LO ; add in arg offset + clc ; adding + adc ARG2+LO ; figger offset + sta SPCL ; this goes here for stashing + lda K+HI ; now page + adc ARG2+HI ; add in start of table + jsr SETPC ; get me memory page + sta SPCH ; page + sty SPCBNK ; and bank + + lda ARG1+HI ; push MSB + jsr STASHB ; saved + jsr NEXTSPC ; point to next one + lda ARG1+LO ; and now LSB + jsr STASHB ; into the stack + jmp PREDS ; show we worked good +;--------- +; ZFSTACK +;--------- +ZFSTACK: + dec NARGS ; how many args there? + bne ZFS1 ; flush ARG2 stack +; +; pop from system stack +; + lda ARG1+LO ; just add number to system counter + clc ; adding + adc ZSP+LO ; added + sta ZSP+LO ; and saved + lda ARG1+HI ; get hi part + adc ZSP+HI ; add in hi part + sta ZSP+HI ; save hi part + rts +ZFS1: + lda ARG2+LO ; get LTABLE we are interested in + sta FPCL ; set up FPC first + lda ARG2+HI ; and page + jsr SETPC ; tell me where + sta FPCH ; save me where + sty FPCBNK ; FPC all set + jsr FP2SP ; have SPC point to stack too + + jsr FETCHB ; get MSB of counter + sta J+HI ; save MSB + jsr NEXTFPC ; point to LSB + jsr FETCHB ; get LSB + sta J+LO ; save LSB + + lda J+LO ; get LSB back + clc ; get ready for add + adc ARG1+LO ; add how many to get rid off + sta J+LO ; save new counter + lda J+HI ; get MSB + adc ARG1+HI ; add MSB + + jsr STASHB ; save Msb of new counter + jsr NEXTSPC ; point to LSB + lda J+LO ; get lsb + jsr STASHB ; okay, reset the counter + rts + +; +; no mouse stuff yet +; +ZMINFO: +ZMLIMIT: + rts +ZMENU: + jmp PREDF ; no menu stuff either + + END diff --git a/apple/yzip/rel.13/pic.asm b/apple/yzip/rel.13/pic.asm new file mode 100644 index 0000000..09d616f --- /dev/null +++ b/apple/yzip/rel.13/pic.asm @@ -0,0 +1,826 @@ + STTL "--- Picture Op Codes ---" + PAGE +PFILE_RD: ; for READING files + db 4 ; 4 parameters + db 0 ; refnum + dw IOBUFF ; read into io buffer + dw $400 ; 1Kb buffer + dw 0 ; length actually read +PFSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +PICCNT: dw 0 ; counter of the entries +PF_REFNUM: db 0 ; place to store refnum +PF_FID: db $FF ; File ID of local directory data +P_IDX: db 0 +P_BCNT: db 0 +P_LOFF: db 0 +GBL_FLAG: db 0 ; found global directory? +PIC_FLAG: db 0 ; found pictures? +PF_NAME: db 0 ; name we are looking at + db 0 ; name we found + +PICINFO: + ds PLDSIZE ; get room for picture data + +TRANSCLR: DB 0 ; transparent color +UNKPIC: + + db EOL,"Unknown Picture #" +UNKPICL EQU $-UNKPIC +ZDISPL: + jsr CLRBUF ; put out any and all text + + jsr GET_PICINF ; get the necessary data + bcc ZDSP1 ; everything just fine + + DLINE UNKPIC ; unknown picture number error + lda ARG1+HI ; get MSB + jsr HEXNUM ; print it + lda ARG1+LO ; and LSB + jsr HEXNUM + lda #$14 ; bad picture number error + jmp ZERROR ; and croak +ZDSP1: + jsr SAVE_CURSOR ; save the cursor + + lda #0 ; show no cursor change + sta CURSFLG ; start with none, anyway + + dec NARGS ; x,y pos passed? + beq ZDSP10 ; nope, just use as is + + lda ARG2+LO ; get passed y pos + beq ZDSP01 ; don't change + sta SCRCY ; change, then + dec SCRCY ; zero base it + ldy #WINTOP ; get top edge of window + lda (WINDOW),Y ; got it + clc ; get ready for add + adc SCRCY ; add the offset + sta SCRCY ; and make it Y pos + lda #1 ; show cursor change anyway + sta CURSFLG ; okay, we did +ZDSP01: + dec NARGS ; x pos passed? + beq ZDSP10 ; nope + + lda ARG3+LO ; get x pos + beq ZDSP10 ; if == 0, don't change + sta SCRCX ; set as passed + dec SCRCX ; zero base it + ldy #WINLEFT ; get left hand edge of window + lda (WINDOW),Y ; got it + clc ; get ready for add + adc SCRCX ; add the offset + sta SCRCX ; and make it X pos + lda #1 ; show cursor change anyway + sta CURSFLG ; okay, we did +ZDSP10: + lda SCRCX ; get current X + pha ; save it + clc ; adding + adc PICINFO+PLDWID ; add in pic width + sta SCRCX ; save here + pla ; get start X pos back + sta SCRCX ; restored +ZDSP101: + lda PICINFO+PLDFLG ; get flag byte + and #1 ; is there a transparent color? + bne ZDSP11 ; ayyup + lda #$FF ; make TRANSCLR be $FF + bne ZDSP12 ; okay +ZDSP11: + lda PICINFO+PLDFLG ; get hi byte of flag word + lsr A ; put in lower byte + lsr A ; put in lower byte + lsr A ; put in lower byte + lsr A ; put in lower byte +ZDSP12: + sta TRANSCLR ; save transparent color + + lda PICINFO+PLDPTR ; MSB of offset + sta PFSEEK+SM_FPOS+2 ; MSB of seek + lda PICINFO+PLDPTR+1 ; Middle + and #$FE ; seek only to 512byte boundary + sta PFSEEK+SM_FPOS+1 + + SET_MARK PFSEEK ; go to pic data + lda #>PIC1BUF ; set up pointers to decode buffers + sta J+HI + lda #PIC2BUF + sta K+HI + lda #IOBUFF ; now get data buffer address + sta L+HI + lda #4 ; 4 pages read in at once + sta P_BCNT ; okay + lda #3 ; 3 bytes of width data start it + clc ; doing add + adc PICINFO+PLDPTR+2 ; pick up LSB pointer + sta P_IDX ; start index + bcc ZDLPCC ; no wrap + inc L+HI ; start at second one + dec P_BCNT ; one less block +ZDLPCC: + lda PICINFO+PLDPTR+1 ; tells which block it is in + and #$01 ; pick up which 256 block + beq ZDLP0 ; start at first one + inc L+HI ; start at next one + dec P_BCNT ; one less block +ZDLP0: + lda #IOBUFF ; reset data buffer address + sta L+HI + lda #GBL_DIR ; start destination off here + jsr READ_IN_PDATA ; go get global directory, if any + sta GBL_FLAG ; indicate whether there is a global +GTPG1: + lda SAVENUM ; get which file is being opened + and #$0F ; just make it binary + cmp PF_FID ; same as the file we already have? + beq GETPGX ; yes, so don't bother + ldy #SGTPICOF ; point to picture offset + lda #>PIC_DIR ; start destination off here + jsr READ_IN_PDATA ; go get the data for local pictures + sta PIC_FLAG ; any picture data +GETPGX: + rts +; +; READ_IN_PDATA - check for desired data being in file, and skip to it if +; it is. Then, read it in in 1Kb chunks, stashing it away into the +; upper bank of the aux mem language card. +; Enter with: +; [A] = Destination page +; [Y] = Offset into Segment table +; +READ_IN_PDATA: + pha ; save destination page + lda (DSEGS),Y ; get MSB + sta PFSEEK+SM_FPOS+2 ; Byte 2 + iny ; point to LSB + ora (DSEGS),Y ; is there any pic data? + bne GTPD00 ; yes + pla ; get page back + lda #0 ; show not here + rts ; nope +GTPD00: + lda (DSEGS),Y ; get it for shifting + asl A ; *2 + sta PFSEEK+SM_FPOS+1 ; stash away + rol PFSEEK+SM_FPOS+2 ; pick up carry + lda #0 ; clear out MSB + sta PFILE_RD+RD_BUFFLEN+HI + sta PFSEEK+SM_FPOS ; and LSB of seeking + + lda PF_REFNUM ; get file ref number + sta PFILE_RD+RD_REFNUM ; and save it for reading and + sta PFSEEK+SM_REFNUM ; for seeking + + lda #RETRY_COUNT ; set retry + sta NY_DATA ; just use this for now +GTPDRD0: + SET_MARK PFSEEK ; and go to beginning + + lda #4 ; read in 4 256 blocks + sta PFILE_RD+RD_BUFFLEN+HI + READ PFILE_RD ; go get the next 4Kb worth + bcc GTPD1 ; fine + jsr RETRY ; well, do it again? + bcc GTPDRD0 ; yes +GTPD1: + pla ; get destination page back + cmp #>PIC_DIR ; if doing local directory, set up + bne GTPD2 ; picture count + ldx IOBUFF+PHNLD ; get number of pictures + stx PICCNT+HI ; save for count down too + ldx IOBUFF+PHNLD+1 ; and here is LSB + stx PICCNT+LO ; saving for counting + ldx IOBUFF+PHFID ; get file ID + stx PF_FID ; and save for later + ldx #(256/PLDSIZE) ; how many entries in 256 bytes + bne GTPD3 ; done +GTPD2: + ldx IOBUFF ; get MSB of how many + stx PICCNT+HI ; show me + ldx IOBUFF+1 ; get LSB of count + stx PICCNT+LO + ldx #(256/2) ; how many entries / 256 bytes +GTPD3: + stx GTPMOD+1 ; set up how big entry is + sta ALTZP+AUX ; use aux mem for most of this + sta K+HI ; MSB of destination + lda #0 ; clear a few things + sta J+LO ; J = source + sta K+LO ; K = destination + lda #4 ; 4 * (4*256) bytes max + sta PFILE_RD+RD_BUFFLEN+HI ; show the read too + sta P_IDX ; save here for counting +GTPDL: + ldy #0 ; start y + lda #>IOBUFF ; get where source is + sta J+HI ; MSB of source + lda #4 ; 4 blocks worth of 256 + sta P_BCNT ; used as counter + lda BNK1SET ; we be using bank 1 @$D000 + lda BNK1SET ; we be using bank 1 @$D000 +GTPDL1: + lda (J),Y ; get the data byte + sta (K),Y ; store in upper aux + iny ; point to the next one + bne GTPDL1 ; and go get it + + inc J+HI ; next block please + inc K+HI ; for destination too + lda PICCNT+LO ; how many entries? + sec ; doing sbc +GTPMOD: sbc #(256/PLDSIZE) ; how many entries in 256 bytes? + sta PICCNT+LO ; save result + bcs GTPDL2 ; no wrapping + dec PICCNT+HI ; wrap + bmi GTPDLX ; all done if we go negative +GTPDL2: + ora PICCNT+HI ; make sure both are not zero + beq GTPDLX ; if they are, then we are done + dec P_BCNT ; count this block + bne GTPDL1 ; go fetch next 256 bytes + sta ALTZP+MAIN ; swap back to main for read + + lda #RETRY_COUNT ; set retry + sta NY_DATA ; just use this for now +GTPDRD: + READ PFILE_RD ; go get the next 4Kb worth + bcc GTPDRDG ; fine + jsr RETRY ; well, do it again? + bcc GTPDRD ; yes +GTPDRDG: + sta ALTZP+AUX ; and back to aux for working + dec P_IDX ; max 4Kb worth of reading + bne GTPDL ; and read in more +GTPDLX: + sta ALTZP+MAIN ; back to main bank of mem + lda BNK2SET ; back to bank 2 + lda BNK2SET ; yes please + lda #1 ; show we found it + rts ; all done + +GTPFLAG: db 0 ; if 1 when opening next file, then + ; this is the next file, so unable to + ; find picture number +GET_PICINF: + lda #0 ; set flag for double check + sta GTPFLAG ; start at zero +GTPLOOP: + lda ARG1+LO ; check argument for zero + ora ARG1+HI ; is it zero? + bne GTPINDX ; jump to look at first block + clc ; found some pictures + rts ; if zero, just give count +GTPINDX: + ldy ARG1+LO ; get arg, as we are swapping + ldx ARG1+HI ; to aux mem + sta ALTZP+AUX ; look at AUX mem + lda BNK1SET ; bank 1 + lda BNK1SET ; bank 1 + lda PIC_DIR+PHNLD ; get # of entries + sta PICCNT+HI + lda PIC_DIR+PHNLD+1 ; it's in reverse order + sta PICCNT+LO + sty ARG1+LO ; use aux mem zero page + stx ARG1+HI ; for new arg1 + lda #>PIC_DIR ; start at beginning of block + sta MPNTH ; hi part + lda #GBL_DIR ; start at beginning of block + sta MPNTH ; hi part + lda #GE< 1 WORD, CONTINUE + BNE FWM1 + LDA VWLEN+1 + BNE FWM1 + LDA VWLEN+0 + CMP ESIZE + BCC FWFAIL +FWM1: + JMP FWLOOP ; AND TRY AGAIN + +FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD + STA VALUE+LO + LDA VWCUR+1 + STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY + RTS ; WORD VALUE RETURNABLE +FWFAIL: + LDA #0 ; NOT FOUND + STA VALUE+LO + STA VALUE+HI + RTS ; THEN RETURN WITH [VALUE] = 0 +; +; DO UNSORTED SEARCH ON VOCAB TBL IN MPC +; +UNSORTED: + LDA #$FF ; 2'S COMPLEMENT LENGTH + EOR NENTS+HI ; TO GET REAL LENGTH + STA NENTS+HI ; WAS NEGATIVE TO SIGNIFY + LDA #$FF ; UNSORTED VOCAB TBL + EOR NENTS+LO + STA NENTS+LO + INC NENTS+LO ; 2'S CMPL + BNE UNSRT0 + INC NENTS+HI +UNSRT0: + LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + + JSR GETBYT ; GET 1ST BYTE OF ENTRY + CMP OUT ; MATCH 1ST BYTE OF TARGET? + BNE FNEXT ; LESS + JSR GETBYT + CMP OUT+1 ; 2ND BYTE MATCHED? + BNE FNEXT + JSR GETBYT + CMP OUT+2 ; 3RD BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+3 ; 4TH BYTE + BNE FNEXT + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + +FNEXT: LDA VWCUR+LO ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC ESIZE ; ENTRY + STA MPCL + BCC FNEXT0 + + LDA VWCUR+HI ; PICK UP CARRY + ADC #0 + STA MPCM + LDA #0 + STA MPCH + JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE + +FNEXT0: DEC NENTS+LO ; CHECKED ALL ENTRIES? + BNE UNSRT0 + LDA NENTS+HI + BEQ FWFAIL ; GO INDICATE NO FIND + DEC NENTS+HI ; OR DO NEXT 256 ENTRIES + JMP UNSRT0 + + END + \ No newline at end of file diff --git a/apple/yzip/rel.13/screen.asm b/apple/yzip/rel.13/screen.asm new file mode 100644 index 0000000..3b6b22e --- /dev/null +++ b/apple/yzip/rel.13/screen.asm @@ -0,0 +1,948 @@ + STTL "--- APPLE ][ SCREEN STUFF ---" + PAGE + +; ----------------- +; PRINT CHAR IN [A] AT CV,CH +; ----------------- +; +; uses memory register [L] +; +SAVECY DB 0 ; spot to save current screen y pos +SAVECX DB 0 ; spot for x pos + +CHAR: + sta IOCHAR ; SAVE HERE + txa ; SAVE [X] AND [Y] + pha + tya + pha + + lda IOCHAR ; get it back + cmp #BACKSPACE ; is it backspace with erase? + bne CHCX ; nope + + jmp DO_BSPC ; so handle backspace +CHCX: + cmp #EOL ; is it ? + bne CHCONT ; just let dline handle it + + jmp DO_EOL ; handle +; +; so save some stuff and do all the necessary figgering +; +CHCONT: + ldx SCRCNT ; just stash character + sta SCRBUFF,X ; save it + inc SCRCNT ; and count it +CH_EXIT: + pla ; RESTORE [X] AND [Y] + tay + pla + tax + rts +; +; PUT_NYBBLE - put 4 bits to the screen at SCRCX, SCRCY (the lower 4 bits +; in [A]). +; +PUT_NYBBLE: + sta NY_DATA ; save [A] for mucking with + jsr SETPOS ; set up offsets using SCRCX + + lda #$8 ; start at first bit, left to right + sta DATALOOP ; and init the counter with it +PNY0: + ldx FPCBNK ; which bank + lda PAGE2SW,X ; select it + ldy #0 ; start with zero + lda (FPC),Y ; get it + sta SCR_DATA ; and save it +PNY1: + ldx BITOFF ; get which interesting bit we want + lda GT_BITS,X ; get bit + pha ; save bit pictures + lda DATALOOP ; see if we have done all 4 bits in this 'pixel' + beq PNY_EXIT ; toots finis + lsr DATALOOP ; point to next bit + bit NY_DATA ; is this bit set? + bne PNY_SET ; yes it is, so we will handle different +; +; Bit is clear, so clear appropriate one in the SCR_DATA byte +; + pla ; get bit picture back + eor #$FF ; turn bits all around + and SCR_DATA ; turn off bit in screen data + jmp PNY_NEXT ; and continue +PNY_SET: + pla ; get bit mask back + ora SCR_DATA ; turn on bit +PNY_NEXT: + sta SCR_DATA ; save result + inc BITOFF ; we're looking at next bit + lda BITOFF ; now check how we're doing + cmp #7 ; only doing bits 0-6 + bne PNY1 ; check next bit +; +; we've finished this byte in screen memory, point to next one +; + lda #0 ; start at zero'th bit + sta BITOFF ; thank you + lda SCR_DATA ; now stash this one in the screen + sta (FPC),Y ; y is still zero; still pointing to bank + jsr NEXT_SCR ; make SPC/FPC point to next spot + jmp PNY0 ; and continue on please +; +; all done, so make sure we stash anything out there +; +PNY_EXIT: + pla ; get bit mask back to fix stack + lda SCR_DATA ; put away the current data byte + sta (FPC),Y ; y is still zero; still pointing to bank + lda PAGE2SW+MAIN ; back to MAIN page 2 + rts +; +; NEXT_SCR - make FPC/SPC point to next screen byte +; +NEXT_SCR: +; +; if in main bank, when we go to aux bank, we need to look at the next +; byte in memory +; + lda FPCBNK ; get what bank we're talking to currently + bne NXS0 ; 0 = main bank, 1 = aux bank + inc SPCL ; point to next byte + inc FPCL ; and for fetching + lda #AUX ; and point to aux bank + bne NXS1 ; (BRANCH) and continue on +; +; if in aux bank, all we need to do is switch banks +; +NXS0: + lda #MAIN ; just make it main bank +NXS1: + sta SPCBNK ; for stashing and + sta FPCBNK ; fetching + rts +; +; GET_NYBBLE - get the 4 bits which represent the screen at position +; SCRCX, SCRCY; return nybble in low 4 bits of [A] +; +GT_BITS: db 1,2,4,8,$10,$20,$40 +GET_NYBBLE: + jsr SETPOS ; set up offsets using SCRCX + + lda #0 ; clear out my data spot + sta NY_DATA ; for mucking with + + lda #$10 ; setting bits 0-3, starting with shift + sta DATALOOP ; so init the setter +GNY0: + ldx FPCBNK ; which bank + lda PAGE2SW,X ; save which bank + ldy #0 ; zero y + lda (FPC),Y ; get byte + sta SCR_DATA ; and save it +GNY1: + lsr DATALOOP ; see if we have done all 4 bits in this 'pixel' + beq GNY_EXIT ; all done! + + ldx BITOFF ; get bit offset + lda GT_BITS,X ; get bit pattern +; +; now check appropriate bit in Screen Data +; + and SCR_DATA ; see if it is set + beq GNY3 ; no bit set here +; +; bit is set, so set it in my data nybble +; + lda DATALOOP ; get bit setter + ora NY_DATA ; and put it into my data byte + sta NY_DATA ; and save it +GNY3: + inc BITOFF ; we're looking at next bit + lda BITOFF ; now check how we're doing + cmp #7 ; only doing bits 0-6 + bne GNY1 ; check next bit +; +; we've finished this byte in screen memory, point to next one +; + lda #0 ; start at zero'th bit + sta BITOFF ; thank you + jsr NEXT_SCR ; point to next byte + jmp GNY0 ; and continue on please +GNY_EXIT: + lda PAGE2SW+MAIN ; back to main page 2 + lda NY_DATA ; get the nybble desired + rts +; +; SETPOS - get the byte offset and the bit offset from the table using +; SCRCX +; +; USES: SCRCX, SCRCY +; SETS: FPC - pointer to correct screen memory location +; BITOFF - bit offset to get to start of byte (N.B. this is left to +; right count, while in memory it is right to left!) +SETPOS: + lda SCRCX ; get the x pos + tax ; put where we can use it + lda XPOSTBL,X ; get byte # + sta FPCL ; okay, saved + lda XBITTBL,X ; get bitoffset + sta BITOFF ; where it wants it + + lda FPCL ; check for correct bank + and #$01 ; if odd, then must be main bank + bne STP11 ; okay, it be odd + lda #AUX ; aux bank + bne STP22 ; jump +STP11: + lda #MAIN ; main bank +STP22: + sta FPCBNK ; save it + lda FPCL ; get for fetch + lsr A ; /2 to get correct byte offset + ldx SCRCY ; get vertical pos + clc ; get ready for adding + adc BASEL,X ; add low part + sta FPCL ; save low part + lda BASEH,X ; get high part + sta FPCH ; save high part + rts ; done !? +; +; DO_EOL - if this is end of line, check if we are at end of window +; and if we are, and it is a scrollable window, scroll. Then move +; the cursor to the left margin of said window +; +DO_EOL: + jsr DISP_LINE ; make sure line gets out there + lda SCRCY ; get current vertical pos + clc ; add font height + adc #FONT_H ; thank you + pha ; save this position + adc #FONT_H ; make sure we have room for characters here + cmp SCRBTM ; so check against the bottom + beq SAVECV ; no scroll yet + bcs SCROLLCITY ; nope, can't use it +SAVECV: + pla ; get new CV + sta SCRCY ; and save it + bne DEL1 ; JUMP +SCROLLCITY: + pla ; get bad y pos + lda SCRLFLG ; is this a scrolling window? + beq DEL1 ; nope, just move to left edge + jsr SCROLL_UP ; and scroll window +DEL1: +; +; move cursor back to left margin +; + lda LEFTMRG ; get left margin + sta SCRCX ; and set itpositions + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay + lda #0 ; clear length too + sta LENGTH+LO ; no more on line + sta LENGTH+HI ; no more on line + jmp CH_EXIT ; now finish it up +; +; DO_BSPC - do a backspace, by erasing char just before cursor to +; background color, and moving cursor back one space +; [X] == character to delete +; +SAVECHX: DW 0 + +DO_BSPC: + lda CHR_X+LO ; figger new CHR_X + sec ; subtract width + ldy FONTFLG ; get which font we be using + beq DOBSP0 ; must be variable width + sbc #MONOFONT_W ; get width then of mono font + jmp DOBSP1 ; okay, now do add +DOBSP0: + sbc CHWID,X ; get width of char to be erased +DOBSP1: + sta CHR_X+LO ; show new one + sta SAVECHX+LO ; save to restore later + lda CHR_X+HI ; and pick up carry + sbc #0 ; okay, did it + sta CHR_X+HI ; save it + sta SAVECHX+HI ; okay + ldy #SPACE ; get SPACE offset + lda FONTFLG ; monospaced font? + beq DOBSP2 ; nope + lda #MONOFONT_W ; make monospaced wide + bne DOBSP3 ; fine +DOBSP2: + lda CHWID,X ; get width of char +DOBSP3: + sta CHWID,Y ; set space to be this wide + sty SCRBUFF ; make space for erasing + lda #1 ; show one char + sta SCRCNT ; assume it used to be zero + jsr DISP_LINE ; put that space out + lda SAVECHX+LO ; restore old/new x pos + sta CHR_X+LO + lda SAVECHX+HI + sta CHR_X+HI + jsr GET_SCRCX ; update SCRCX please + + lda #SPACE_WIDTH ; restore width of space char + ldy #SPACE ; get offset + sta CHWID,Y ; okay + + jmp CH_EXIT ; done +; +; CLS - clear the window, using CLS parameters +; +CLS: + lda SCRCX ; save the current X,Y + sta SAVECX ; x + lda SCRCY + sta SAVECY ; saved + lda CLSTOP ; get top line + sta SCRCY ; and set up a y pos + + jsr SETMASK ; set up masks and ending point + + lda CPY_COUNT ; get count + sta SH_LOOP ; save count + lda CLSLEFT ; get left edge + sta SCRCX ; set up as X pos + ldy #WINBGND ; get background offset + lda (WINDOW),Y ; get background color + sta ARG8 ; save it here + lda CLSWIDTH ; how wide we be? + bne CLSOKAY ; not a zero width + lda #25 ; zero can't do zero width + jmp ZERROR ; so die +CLSOKAY: + cmp #3 ; if skinny, handle special + bcs L1L0 ; nope + sta ARG7 ; make this be the counter + lda CLSHEIGHT ; just use PUT/GET NYBBLE if only one wide + bne CLSOKAY1 ; not a zero height either + lda #25 ; bad error + jmp ZERROR +CLSOKAY1: + sta J ; save here +CLS1W: + lda ARG8 ; get color + jsr PUT_NYBBLE ; put it + inc SCRCX ; next x + dec ARG7 ; counter + bne CLS1W ; do next X + lda CLSLEFT ; get left edge again + sta SCRCX ; point to it + inc SCRCY ; next line + lda CLSWIDTH ; restore width count + sta ARG7 ; thanks + dec J ; count + bne CLS1W ; do it + beq CLSEXIT ; all done then +L1L0: + sta J ; use j as counter +L1L: + lda ARG8 ; a color please + jsr PUT_NYBBLE ; do first line easy + inc SCRCX ; next nybble + dec J ; done yet? + bne L1L ; nope + + lda CLSLEFT ; where is left column + sta SCRCX ; here! + jsr SETPOS ; get the address + jsr FP2SP ; SPC is source PC, now! + lda CLSHEIGHT ; how many lines are we clearing + bne CLSOKAY2 ; not a zero height either + lda #25 ; bad error + jmp ZERROR +CLSOKAY2: + sta J ; j is counter again + dec J ; already cleared one line + beq CLSEXIT ; only one line to do! +CLSLOOP: + lda SPCH ; now, modify COPY_LINE + sta CPY_MOD1_SRC+HI + sta CPY_MOD2_SRC+HI + lda SPCL + sta CPY_MOD1_SRC+LO + sta CPY_MOD2_SRC+LO + inc SCRCY ; clear this line + jsr SETPOS ; where am i? + lda FPCH ; now, modify COPY_LINE + sta CPY_MOD1_DST+HI + sta CPY_MOD2_DST+HI + lda FPCL + sta CPY_MOD1_DST+LO + sta CPY_MOD2_DST+LO + lda SH_LOOP ; get count + sta CPY_COUNT ; and save it + jsr COPY_LINE ; did the copy (i hope) + dec J ; count it + bne CLSLOOP ; next one please +CLSEXIT: + lda SAVECX ; get X,Y back + sta SCRCX ; got it + lda SAVECY ; now for y + sta SCRCY ; restored! + + rts +; +; SETMASK - figger out the start and end masks, as well as setting +; stuff to point to stopping address. Use CLSLEFT and CLSWIDTH +; +ST_BITS: db 0,1,3,7,$f,$1f,$3f +SETMASK: + lda CLSLEFT ; munge with SCRX + sta SCRCX ; okay + jsr SETPOS ; get me the bit offset of start + + ldx BITOFF ; now set up mask + lda ST_BITS,X ; get the bit pattern + sta STMASK ; save it + + lda CLSLEFT ; get left edge again + clc ; add width + adc CLSWIDTH ; to get where to stop + tax ; make index + stx SCRCX ; set cur pos + lda XPOSTBL,X ; get how many bytes + ldx CLSLEFT ; subtract from byte offset of start + sec ; subbing + sbc XPOSTBL,X + sta CPY_COUNT ; and save it + + jsr SETPOS ; so get its address + + ldx BITOFF ; get bit offset + lda ST_BITS,X ; get pattern + sta ENDMASK ; okay! + rts +; +; SCROLL_UP - roll the current window by FONT_H lines +; +SCROLL_UP: + lda #FONT_H ; show one line + sta SCLLINES ; done + sta SCLDIR ; show scroll up with positive number + ldy #WINTOP ; get top of screen + lda (WINDOW),Y ; got it + sta CLSTOP ; saved it + iny ; point to left edge + lda (WINDOW),Y ; get left edge + sta CLSLEFT ; save + iny ; this is now the height + lda (WINDOW),Y ; get window height + sta CLSHEIGHT ; show me + iny ; and now for the width + lda (WINDOW),Y ; get width + sta CLSWIDTH ; saved it + ; so fall thru + ; and do the scrolling +; FALLING THRU +; | +; \ / +; +; +; DO_SCROLL - scroll SCLLINES withing the window as defined by +; CLSLEFT,TOP,WIDTH, and HEIGHT +; +DO_SCROLL: + lda SCRCX ; save the current X,Y + sta SAVECX ; x + lda SCRCY + sta SAVECY ; saved + lda SCLLINES ; how many lines? + + ldx SCLDIR ; which direction? + bpl SC1 ; >0 means scroll up +; +; scroll down, so we are going to start at the bottom and copy downwards +; until we reach the top +; +; now modify code so we do adds to get destination line and subtracts +; to get new src line +; + ldy #$C6 ; 'dec' opcode + bne SC2 ; jump to modify +SC1: +; +; scroll up - start at top and copy upwards until we reach the bottom +; + ldy #$E6 ; 'inc' opcode + ldx SCLLINES ; get # of scrolling lines +SC2: + sty SCMOD1 ; make inc/dec + sty SCMOD2 ; either inc or dec + stx SCOFF ; save the offset between SRC and DST + + lda SCLDIR ; which direction? + bpl SC3 ; must be normal scroll +; +; if scrolling downwards, we need to start source at bottom-offset and +; end when the destination is at top+offset +; + lda CLSHEIGHT ; get # of lines in window + sec ; subbing + sbc SCOFF ; subtract offset to get source + clc ; adding + adc CLSTOP ; and get absolute position + tax ; put in X + dex ; for 0 offset it + lda CLSTOP ; now figger last line to copy + clc ; adding + adc CLSHEIGHT ; get me last line + tay ; for later storage + dey ; make 0 based + bne SC4 ; always jumps +SC3: +; +; if scrolling upwards, start src at top+offset and end when destination +; is at bottom-offset +; + lda CLSTOP ; get top + clc ; adding + adc SCOFF ; add in offset + tax ; for later on + ldy CLSTOP ; first destination is top of window +SC4: + stx SCRCY ; Starting Source + sty SCROLLY ; Starting Destination + + jsr SETMASK ; set the masks and horizontal endpoint + lda CPY_COUNT ; save for future generations + sta SH_LOOP ; save it + lda CLSHEIGHT ; how high + sta DATALOOP ; save as counter + sec ; for subbing + sbc SCOFF ; subtract scrolling amount + sta CLSHEIGHT ; this is how many lines to copy + lda SCRCY ; save Start Source + pha + lda CLSTOP ; start at Y pos + sta SCRCY + lda CLSLEFT ; and x pos + sta SCRCX ; thank you + lda PAGE2SW+MAIN ; make sure main memory page is in there +SCRL1: + jsr SETPOS ; set up line pointer + ldy SCRCY ; get top + cpy #120 ; 120 bytes per list + bcc SCRLY ; all set + tya ; for adding + clc + adc #8 + tay +SCRLY: + lda FPCH + sta SV_PCH,Y + lda FPCL + sta SV_PCL,Y + inc SCRCY ; next line please + dec DATALOOP + bne SCRL1 + + pla ; get StartSource back + sta SCRCY + lda FPCBNK ; init SPC bank too + sta SPCBNK ; fine, we did +SCROLLING: + ldy SCRCY ; get source Y for index + cpy #120 ; jump over junk + bcc SCLYY + tya + clc + adc #8 + tay +SCLYY: + lda SV_PCH,Y + sta SPCH + sta CPY_MOD1_SRC+HI + sta CPY_MOD2_SRC+HI + lda SV_PCL,Y + sta CPY_MOD1_SRC+LO + sta CPY_MOD2_SRC+LO + sta SPCL + + ldy SCROLLY ; get destination Y pos + cpy #120 ; jump over junk + bcc SCLYY1 + tya + clc + adc #8 + tay +SCLYY1: + lda SV_PCH,Y + sta FPCH + sta CPY_MOD1_DST+HI + sta CPY_MOD2_DST+HI + lda SV_PCL,Y + sta CPY_MOD1_DST+LO + sta CPY_MOD2_DST+LO + sta FPCL + + lda SH_LOOP ; get byte counter + sta CPY_COUNT ; show copy line + jsr COPY_LINE ; and do the copy +SCMOD1: inc SCRCY ; inc or dec to get next one +SCMOD2: inc SCROLLY ; inc/dec for next destination Y + dec CLSHEIGHT ; count down + bne SCROLLING ; nope + + ldx SCLDIR ; scroll up or down? + bpl SCLCLR1 ; clear a little different +; +; if scrolling down, clear from current Y+1 +; + lda SCRCY ; get current source + sta CLSTOP ; save in top spot + inc CLSTOP ; get inside window + jmp SCLCLR2 +SCLCLR1: + lda SCROLLY ; get last destination + sta CLSTOP ; and save it +SCLCLR2: + lda SCOFF ; and both clear this many lines + sta CLSHEIGHT ; okay? + + lda SAVECX ; now restore X and Y + sta SCRCX ; x + lda SAVECY ; and + sta SCRCY ; y + + jsr CLS ; WIDTH and LEFT should be okay still + + rts +; +; CLREOL - clear from current cursor position to end of line by +; using CLS after changing the window size +; +CLREOL: + lda SCRCX ; and make left be where cursor is + sta CLSLEFT + lda SCRCY ; and top be where Y is + sta CLSTOP + lda #FONT_H ; and bottom be bottom of char + sta CLSHEIGHT + ldy #WINWID ; get width + lda (WINDOW),Y ; got it + clc ; now adding + ldy #WINLEFT ; the left edge + adc (WINDOW),Y ; to get the right edge + sec ; subbing + sbc CLSLEFT ; and subtract left to get width + ldy #WINRM ; remove the size of the right margin + sbc (WINDOW),Y ; that too + sta CLSWIDTH ; okay? + jmp CLS ; now clear the screen +; +; COPY_SCRL - copy from SCR_LINE onto the screen. CH_OFFSET says how +; many bytes in SCR_LINE to copy. FPC is assumed to be pointing +; to start of screen bytes. BITTER has the original BITOFF from +; SETPOS. ENDBIT shows how many significant bits in last byte. +; +COPY_SCRL: + ldx SHOW_CURSOR ; are we showing the cursor (ugh) + beq COPYL2 ; nope + jmp DO_CURSOR ; then XOR cursor in +COPYL2: + ldy #WINBGND ; get background offset + lda (WINDOW),Y ; get current background color + beq COPY_SCRL1 ; if black, ignore this + jsr FIX_COLOR ; or in the color, please +; +; Alternate entry point for COPY_SCRL, used by picture drawing routine +; to avoid using background color and checking for cursor +; +COPY_SCRL1: + ldx FPCBNK ; set up bank + lda PAGE2SW,X ; set first bank + lda ENDBIT ; did we end evenly? + bne COPYL22 ; nope + inc CH_OFFSET ; make CH_OFFSET be a counter +COPYL22: + ldy #0 ; zero y + + lda CH_OFFSET ; if only one, then handle real special + bne COPYL21 ; nope + + ldx BITTER ; get starting bit offset + lda ST_BITS,X ; get starting bit mask + sta IOCHAR ; save it + ldx ENDBIT ; get ending bit offset + lda ST_BITS,X ; combine with ending mask bits + eor #$FF ; set for good ones + ora IOCHAR ; set up mask for bits + and (FPC),Y ; get me interesting bits + sta (FPC),Y ; save + lda IOCHAR ; get flag for data + eor #$FF ; flip to get good data +CPYSM1: and SCR_LINE ; pick up my bits + ora (FPC),Y ; and or in screen data + sta (FPC),Y ; and save it + jmp COPYLEX ; go away now +COPYL21: + lda CH_OFFSET ; get # of chars + lsr A ; /2 get number in this bank + adc #0 ; pick up carry for first one + sta DATALOOP ; and save it to work on + + ldx BITTER ; do we have a weird start? + beq DLL2 ; nope +; +; need to do the first one special +; + lda (FPC),Y ; get byte + and ST_BITS,X ; get masking bits + sta IOCHAR ; save for later + lda ST_BITS,X ; get masking bits again + eor #$FF ; get good bits +CPYSM2: and SCR_LINE ; get first data byte + ora IOCHAR ; pick up screen bits + sta (FPC),Y ; pointing + iny ; next byte + ldx #2 ; start at next one for this bank + dec DATALOOP ; kount as done +COPYLOOP: + beq CPYLP2 ; all done with this part of line +DLL2: +CPYSM3: lda SCR_LINE,X ; get data + sta (FPC),Y ; pointing + iny ; next byte + inx ; next one + inx ; next one + dec DATALOOP ; count as used + bpl COPYLOOP ; start loop again +CPYLP2: + ldy #0 ; reset Y + lda FPCBNK ; which bank were we at + eor #1 ; swap to other one + tax ; make it in x + lda PAGE2SW,X ; swap to write bank + txa ; check which one + beq CPYLP23 ; correct offset + iny ; fix offset if going from main to aux +CPYLP23: + ldx #1 ; start at second byte in screen line + lda CH_OFFSET ; get starting number + lsr A ; /2 to get how many for this bank + sta DATALOOP ; and show it +COPYLOOP2: + beq LINE_DONE ; all done with this part of line + +CPYSM4: lda SCR_LINE,X ; get data + sta (FPC),Y ; pointing + iny ; next byte + inx ; next one + inx ; next one + dec DATALOOP ; count as used + bpl COPYLOOP2 ; start loop again +LINE_DONE: +; +; do the last byte special +; + stx DATALOOP ; save pointer + lda ENDBIT ; get ending bit offset + beq COPYLEX ; all done if nothing funky + lsr CH_OFFSET ; get line offset + pha ; save [A] + bcs LINED1 ; if odd, point at right things + dec DATALOOP ; one less then + ldx FPCBNK ; get original bank + lda PAGE2SW,X ; switch to it + txa ; which bank did we do? + bne LINED1 ; no need to step back one + dey ; point one less here too +LINED1: + pla ; get ENDBIT back + tax ; make end bits be index + lda ST_BITS,X ; get end mask + sta IOCHAR ; save mask bits + eor #$FF ; toggle every bit + and (FPC),Y ; get the interesting bits in byte + sta (FPC),Y ; save it + ldx DATALOOP ; get data pointer +CPYSM5: lda SCR_LINE,X ; turn on my bits + and IOCHAR ; pick up my good bits + ora (FPC),Y ; bring everything together + sta (FPC),Y ; save the byte +COPYLEX: + lda PAGE2SW+MAIN ; back to main, thanks + rts + +FIX_COLOR: + inc CH_OFFSET ; just to make checking easier for now + + asl A ; *2 + asl A ; *4 to get correct offset + adc #COLORS ; get hi part + adc #0 ; pick up maybe carry + sta COLORP+HI ; save pointer + ldx #$11 ; ORA (),Y opcode + ldy #WINFORE ; check foreground color + lda (WINDOW),Y ; check what color + bne FIXC1 ; just leave white if not black + ldx #0 ; start at beginning +FIXMUNGEL: + lda SCR_LINE,X ; get byte + eor #$FF ; swap all the bits + sta SCR_LINE,X ; store back + inx ; count it + cpx CH_OFFSET ; done? + bcc FIXMUNGEL ; nope + ldx #$31 ; AND (),Y opcode +FIXC1: + stx FCLM ; self mod my code (again . . . sigh) + lda BITTER ; get starting offset + and #3 ; pick up wrap + tay ; make index + ldx #0 ; start at zero line +FIXLOOP: +FCM1: lda SCR_LINE,X ; get screen byte +FCLM: ora (COLORP),Y ; or with color byte +FCM2: sta SCR_LINE,X ; save it + iny ; next color byte + cpy #4 ; wrapped? + bne FIXLP1 ; nope + ldy #0 ; restart +FIXLP1: + inx ; next screen byte + cpx CH_OFFSET ; done yet? + bcc FIXLOOP ; nope + + dec CH_OFFSET ; fix counter + rts ; now we are done +; +; MSCURS - Erase the cursor from the old spot and write it in the +; new spot +; +MOLDX: db MAXWIDTH ; spot to save x,y of mouse +MOLDY: db MAXHEIGHT +MSCCNT: ds 1 +SVCURS: ds CURSW*CURSH ; save room +MSWCNT: db 1 +MSSTATE: db 0 ; 0 == off, 1 == on +MSCOLOR: db $f,7,7,7,7,7,7,7 +; +MSCURS: + lda #0 ; clear moved flag + sta MSMOVEF ; we did + jsr MSCOFF ; turn cursor off at current pos + jmp MSCON ; and turn it on in new spot + +; +; MSCOFF - mouse cursor off +; Copy info from saved spot back onto screen @ MOLDX, MOLDY +MSCOFF: + lda MSSTATE ; already off? + bne MSCOFF1 ; no + rts ; done then +MSCOFF1: + lda SCRCY ; save X,Y + sta SAVECY + lda SCRCX + sta SAVECX + lda MOLDX ; point to old X,Y + sta SCRCX + lda MOLDY + sta SCRCY + lda #0 ; start at beginning of saved area + sta MSCCNT ; save counter + lda #CURSW ; restore width + sta MSWCNT ; and counter +RENEWL: + lda SCRCY ; check bounds + cmp #MAXHEIGHT + bcs MSC1 ; all done +RENEWL0: + lda SCRCX + cmp #MAXWIDTH + bcs RENEWL1 ; might not be done + jsr GET_NYBBLE ; get screen nybble + ldx MSCCNT ; get counter +; eor MSCOLOR,X ; xor to turn off + eor #$0F ; turn white/black + jsr PUT_NYBBLE ; save nybble + inc MSCCNT ; point to next one + lda MSCCNT ; get counter + cmp #(CURSW*CURSH) ; done yet? + beq MSC1 ; yup + dec MSWCNT ; count down one width + beq RENEWL1 ; it is + inc SCRCX ; next x + bne RENEWL0 ; try again +RENEWL1: + lda MOLDX ; reset X + sta SCRCX + lda #CURSW ; restore width + sta MSWCNT ; and counter + inc SCRCY ; next y + bne RENEWL ; okay try some more +MSC1: + jmp MSCON4 ; done turning it off +; +; MSCON - turn mouse cursor on +; Copy white pixels into area specified by MSX, MSY +; +MSCON: + lda MSSTATE ; already on? + beq MSCON0 ; no + rts ; don't bother +MSCON0: + lda SCRCY ; save X,Y + sta SAVECY + lda SCRCX + sta SAVECX + + lda MSX ; get mouse x + sta SCRCX ; set mouse X + sta MOLDX ; save mouse x + lda MSY ; get mouse y + sta SCRCY ; set mouse Y + sta MOLDY ; and mouse Y + lda #0 ; start at beginning of saved area + sta MSCCNT ; save counter + lda #CURSW ; restore width + sta MSWCNT ; and counter +MSCON1: + lda SCRCY ; check bounds + cmp #MAXHEIGHT + bcs MSCON4 ; all done +MSCON2: + lda SCRCX + cmp #MAXWIDTH + bcs MSCON3 ; might not be done + jsr GET_NYBBLE ; save nybble + ldx MSCCNT ; get counter +; eor MSCOLOR,X ; get cursor color + eor #$0F ; turn white/black + jsr PUT_NYBBLE ; put nybble + inc MSCCNT ; point to next one + lda MSCCNT ; check ending + cmp #(CURSW*CURSH) ; done yet? + beq MSCON4 ; yup + dec MSWCNT ; count down one width + beq MSCON3 ; finished for line + inc SCRCX ; next x + bne MSCON2 ; try again +MSCON3: + lda MSX ; reset X + sta SCRCX + lda #CURSW ; restore width + sta MSWCNT ; and counter + inc SCRCY ; next y + bne MSCON1 ; okay try some more +MSCON4: + lda MSSTATE ; get current state + eor #$01 ; toggle it + sta MSSTATE ; bang + lda SAVECX ; restore X,Y + sta SCRCX + lda SAVECY + sta SCRCY + rts + + + END diff --git a/apple/yzip/rel.13/subs.asm b/apple/yzip/rel.13/subs.asm new file mode 100644 index 0000000..63703e7 --- /dev/null +++ b/apple/yzip/rel.13/subs.asm @@ -0,0 +1,376 @@ + STTL "--- OPCODE SUPPORT SUBROUTINES ---" + PAGE + +; ----------------------- +; 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 LOW = 16, + BCS GETVRG ; IT'S GLOBAL + +; HANDLE A LOCAL VARIABLE + +GETVRL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA LOCALS-2+LO,X ; GRAB LSB + STA VALUE+LO + LDA LOCALS-2+HI,X ; AND MSB + STA VALUE+HI + RTS +; +; HANDLE A GLOBAL VARIABLE +; +GETVRG: + jsr GVCALC ; GET ADDRESS OF GLOBAL INTO [FPC] + jsr FETCHB ; and get hi part + sta VALUE+HI + jsr NEXTFPC ; and point to next part + jsr FETCHB ; and go get it + sta VALUE+LO ; SAVE IT + rts ; AND WE'RE DONE + +; ---------------------------------- +; POP Z-STACK INTO [VALUE] AND [X/A] +; ---------------------------------- +; ZSTACK DOUBLED IN SIZE FOR EZIP +; SO THIS RTN ALL NEW + +POPVAL: LDA ZSP+LO ; IF ZSP+LO IS 0 + BNE POP1 + STA ZSP+HI ; MUST DEC. HI (HI = 0 OR 1 ONLY) +POP1: DEC ZSP+LO ; THEN DEC ZSP LO + BNE POP2 + ORA ZSP+HI ; LO + HI BOTH 0? + BEQ UNDER ; UNDERFLOW IF ZERO! +POP2: LDY ZSP+LO + LDA ZSP+HI + BEQ POP3 ; BOTTOM HALF OF ZSTACK + LDA ZSTKTL,Y ; GET VALUE FROM TOP HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKTH,Y + STA VALUE+HI + RTS + +POP3: LDA ZSTKBL,Y ; GET VALUE FROM BOTTOM HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKBH,Y + STA VALUE+HI + 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: PHA ; HOLD VALUE IN [A] A SEC. + LDY ZSP+LO + LDA ZSP+HI + BEQ PSHBOT ; ON BOTTOM HALF OF STACK + TXA + STA ZSTKTL,Y ; PUSH VALUE ONTO TOP HALF OF STACK + PLA + STA ZSTKTH,Y + JMP PSHUPD ; NOW UPDATE POINTER + +PSHBOT: TXA ; PLACE VALUE ON ZSTACK + STA ZSTKBL,Y + PLA + STA ZSTKBH,Y +PSHUPD: INC ZSP+LO ; UPDATE ZSTACK POINTER + BNE PSHEX + LDA ZSP+LO + ORA ZSP+HI + BNE OVER ; OVERFLOW IF $200 + INC ZSP+HI ; TO 1 +PSHEX: 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 + +; FLUSH TOP WORD OFF STACK +; AND REPLACE WITH [VALUE] + + LDA ZSP+LO ; IF ZSP+LO =0 + BNE VAR1 ; THEN HI =1 (GUARDED ELSEWHERE) + STA ZSP+HI ; DECREMENT HI (ONLY 0 OR 1) +VAR1: DEC ZSP+LO ; NOW DEC LOW BYTE + BNE PSHVAL + ORA ZSP+HI + BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + BNE PSHVAL + + ; RETURN A ZERO +RET0: + lda #0 + tax ; zero's all +; +; RETURN WORD IN [A], [X] (LO,HI) (EZIP EXPANDED TO A WORD) +; +PUTBYT: + STA VALUE+LO + STX 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 LOW = 16, + BCS PUTVLG ; IT'S GLOBAL +; +; PUT A LOCAL VARIABLE +; +PUTVLL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA VALUE+LO ; GRAB LSB + STA LOCALS-2+LO,X ; SAVE IN LOCAL TABLE + LDA VALUE+HI ; DO SAME TO + STA LOCALS-2+HI,X ; MSB + RTS +; +; RETURN A GLOBAL VARIABLE +; +PUTVLG: + JSR GVCALC ; put address in [FPC] + lda FPCBNK ; and move it to stash spot + sta SPCBNK + lda FPCH + sta SPCH + lda FPCL + sta SPCL + lda VALUE+HI ; GET MSB + jsr STASHB ; and save it + jsr NEXTSPC ; point to next byte + lda VALUE+LO ; NOW GET LSB + jsr STASHB ; and send it out + rts + +; ----------------------- +; CALC GLOBAL WORD OFFSET +; ----------------------- +; ENTRY: VAR-I BYTE (16-255) IN [A] +; EXIT: ABSOLUTE ADDRESS OF GLOBAL VAR IN [FPC] +GVCALC: + sec ; time for a subtract + 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 FPCL ; ADDRESS OF THE + lda I+HI ; DESIRED GLOBAL VARIABLE + adc GLOBAL+HI ; STORE ADDRESS BACK IN [FPC] + jsr SETPC ; now get memory page and bank + sta FPCH ; hi part + sty FPCBNK ; and bank +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 PREDB7 ; 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 +PREDB7: 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: LDA VALUE+LO ; SUBTRACT 2 FROM OFFSET + SEC ; IN [VALUE] + SBC #2 + TAX ;SAVE LO BYTE + LDA VALUE+HI + SBC #0 + STA I+LO ;MSB OF OFFSET = LSB OF [I] + LDY #0 ; CLEAR THE MSB + STY I+HI ; OF [I] + ASL A ; EXTEND THE SIGN OF OFFSET + ROL I+HI ; INTO MSB OF [I] + ASL A + ROL I+HI ; (EZIP) + asl A + rol I+HI ; (YZIP) ??!! + TXA ; GET LSB OF OFFSET + 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 PREDB6 + LDA I+LO ; ELSE CALC NEW UPPER BITS + CLC + ADC ZPCM + STA ZPCM + LDA I+HI + ADC ZPCH + AND #%00000111 + STA ZPCH + JMP VLDZPC ;MAKE VALID +PREDB6: + + ; FALL THROUGH ... + +; ---- +; NOOP +; ---- + +ZNOOP: RTS + + +; ---------------------- +; MOVE [ARG1] TO [VALUE] +; ---------------------- + +A12VAL: LDA ARG1+LO + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + RTS + + +; ----------------------------------- +; INDICATE STATUS LINE REFRESH NEEDED +; ----------------------------------- + +REFRSH: LDA ZBEGIN+ZFLAGS+1 ; PICK UP LOW BYTE OF FLAG WORD + ORA #%00000100 ; SET BIT 2 + STA ZBEGIN+ZFLAGS+1 ; AND PUT IT BACK + RTS + + +;DECJ RETURNS C=0 WHEN J=$FFFF + +DECJ: LDA J+LO + SEC + SBC #1 + STA J+LO + LDA J+HI + SBC #0 + STA J+HI + RTS + + END diff --git a/apple/yzip/rel.13/tables.asm b/apple/yzip/rel.13/tables.asm new file mode 100644 index 0000000..80220e9 --- /dev/null +++ b/apple/yzip/rel.13/tables.asm @@ -0,0 +1,329 @@ + STTL "--- ZIP DATA TABLES ---" + PAGE +CHADR_H: + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db >C20,>C21,>C22,>C23,>C24,>C25,>C26,>C27 + DB >C28,>C29,>C2A,>C2B,>C2C,>C2D,>C2E,>C2F + db >C30,>C31,>C32,>C33,>C34,>C35,>C36,>C37 + DB >C38,>C39,>C3A,>C3B,>C3C,>C3D,>C3E,>C3F + db >C40,>C41,>C42,>C43,>C44,>C45,>C46,>C47 + DB >C48,>C49,>C4A,>C4B,>C4C,>C4D,>C4E,>C4F + db >C50,>C51,>C52,>C53,>C54,>C55,>C56,>C57 + DB >C58,>C59,>C5A,>C5B,>C5C,>C5D,>C5E,>C5F + db >C60,>C61,>C62,>C63,>C64,>C65,>C66,>C67 + DB >C68,>C69,>C6A,>C6B,>C6C,>C6D,>C6E,>C6F + db >C70,>C71,>C72,>C73,>C74,>C75,>C76,>C77 + DB >C78,>C79,>C7A,>C7B,>C7C,>C7D,>C7E +CHADR_L: + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 8 +C3F DB 3f,80,71,c0,03,80,0e,00,0e,00,00,00,0e,00,00,00,00,00 ;? 10 +C40 DB 1f,f8,e0,0e,e3,e7,e6,77,e6,77,e3,bc,e0,00,1f,f8,00,00 ;@ 16 +C41 DB 3f,80,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;A 10 +C42 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,7f,80,00,00,00,00 ;B 10 +C43 DB 3f,80,71,c0,70,00,70,00,70,00,71,c0,3f,80,00,00,00,00 ;C 10 +C44 DB 7f,80,71,c0,71,c0,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;D 10 +C45 DB 7f,70,70,7f,70,70,7f,00,00 ;E 8 +C46 DB 7f,70,70,7e,70,70,70,00,00 ;F 8 +C47 DB 3f,80,71,c0,70,00,73,c0,71,c0,71,c0,3f,80,00,00,00,00 ;G 10 +C48 DB 71,c0,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;H 10 +C49 DB 70,70,70,70,70,70,70,00,00 ;I 4 +C4A DB 01,c0,01,c0,01,c0,01,c0,71,c0,71,c0,3f,80,00,00,00,00 ;J 10 +C4B DB 70,e0,71,c0,73,80,7f,00,73,80,71,c0,70,e0,00,00,00,00 ;K 11 +C4C DB 70,70,70,70,70,70,7f,00,00 ;L 8 +C4D DB 78,3c,7c,7c,7e,fc,77,dc,73,9c,70,1c,70,1c,00,00,00,00 ;M 14 +C4E DB 78,70,7c,70,7e,70,77,70,73,f0,71,f0,70,f0,00,00,00,00 ;N 12 +C4F DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;O 10 +C50 DB 7f,80,71,c0,71,c0,7f,80,70,00,70,00,70,00,00,00,00,00 ;P 10 +C51 DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,00,03,c0,00,00 ;Q 10 +C52 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,71,c0,00,00,00,00 ;R 10 +C53 DB 3f,80,71,c0,78,00,1f,00,03,c0,71,c0,3f,80,00,00,00,00 ;S 10 +C54 DB 7f,c0,0e,00,0e,00,0e,00,0e,00,0e,00,0e,00,00,00,00,00 ;T 10 +C55 DB 71,c0,71,c0,71,c0,71,c0,71,c0,71,c0,1f,00,00,00,00,00 ;U 10 +C56 DB 71,c0,71,c0,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;V 10 +C57 DB 71,c7,71,c7,71,c7,71,c7,71,c7,71,dc,7f,f8,00,00,00,00 ;W 16 +C58 DB 71,c0,71,c0,71,c0,1f,00,71,c0,71,c0,71,c0,00,00,00,00 ;X 10 +C59 DB 71,c0,71,c0,71,c0,3f,80,0e,00,0e,00,0e,00,00,00,00,00 ;Y 10 +C5A DB 7f,c0,01,c0,03,80,0e,00,38,00,70,00,7f,c0,00,00,00,00 ;Z 10 +C5B DB 7f,70,70,70,70,70,7f,00,00 ;[ 8 +C5C DB 70,00,38,00,1c,00,0e,00,07,00,03,80,01,c0,00,00,00,00 ;\ 10 +C5D DB 7f,07,07,07,07,07,7f,00,00 ;] 8 +C5E DB 00,00,0c,00,3f,00,e1,c0,00,00,00,00,00,00,00,00,00,00 ;^ 10 +C5F DB 00,00,00,00,00,00,00,ff,00 ;_ 8 +C60 DB 70,38,1c,00,00,00,00,00,00 ;` 6 +C61 DB 00,00,00,00,3f,80,01,c0,3f,c0,71,c0,3f,c0,00,00,00,00 ;a 10 +C62 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;b 10 +C63 DB 00,00,00,00,3f,80,71,c0,70,00,71,c0,3f,80,00,00,00,00 ;c 10 +C64 DB 01,c0,01,c0,3f,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;d 10 +C65 DB 00,00,00,00,3f,80,79,c0,7f,c0,70,00,3f,80,00,00,00,00 ;e 10 +C66 DB 0f,1c,7f,1c,1c,1c,1c,00,00 ;f 8 +C67 DB 00,00,00,00,3f,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;g 10 +C68 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;h 10 +C69 DB 70,00,70,70,70,70,70,00,00 ;i 5 +C6A DB 0e,00,0e,0e,0e,0e,0e,0e,7c ;j 8 +C6B DB 70,00,70,00,71,c0,73,80,7f,00,73,80,71,c0,00,00,00,00 ;k 10 +C6C DB 70,70,70,70,70,70,70,00,00 ;l 5 +C6D DB 00,00,00,00,7f,fc,73,9c,73,9c,73,9c,73,9c,00,00,00,00 ;m 14 +C6E DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;n 10 +C6F DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;o 10 +C70 DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,7f,80,70,00,70,00 ;p 10 +C71 DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,c0,01,c0,01,c0 ;q 10 +C72 DB 00,00,77,7c,70,70,70,00,00 ;r 8 +C73 DB 00,00,00,00,3f,00,70,00,1e,00,03,80,3f,00,00,00,00,00 ;s 9 +C74 DB 1c,1c,7f,1c,1c,1c,0f,00,00 ;t 8 +C75 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;u 10 +C76 DB 00,00,00,00,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;v 10 +C77 DB 00,00,00,00,73,9c,73,9c,73,9c,73,9c,7f,f8,00,00,00,00 ;w 14 +C78 DB 00,00,00,00,71,c0,71,c0,1f,00,71,c0,71,c0,00,00,00,00 ;x 10 +C79 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;y 10 +C7A DB 00,00,00,00,7f,c0,03,80,0e,00,38,00,7f,c0,00,00,00,00 ;z 10 +C7B DB 1f,38,38,f0,38,38,1f,00,00 ;} 8 +C7C DB 70,70,70,70,70,70,70,70,70 ;| 5 +C7D DB f8,1c,1c,0f,1c,1c,f8,00,00 ;} 8 +C7E DB 00,00,00,00,3c,e0,e7,80,00,00,00,00,00,00,00,00,00,00 ;~ 11 +; +; base addresses for the screen lines +; +BASEL: + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 +BASEH: + DB 20,24,28,2C,30,34,38,3C + DB 20,24,28,2C,30,34,38,3C + DB 21,25,29,2D,31,35,39,3D + DB 21,25,29,2D,31,35,39,3D + DB 22,26,2A,2E,32,36,3A,3E + DB 22,26,2A,2E,32,36,3A,3E + DB 23,27,2B,2F,33,37,3B,3F + DB 23,27,2B,2F,33,37,3B,3F + DB 20,24,28,2C,30,34,38,3C + DB 20,24,28,2C,30,34,38,3C + DB 21,25,29,2D,31,35,39,3D + DB 21,25,29,2D,31,35,39,3D + DB 22,26,2A,2E,32,36,3A,3E + DB 22,26,2A,2E,32,36,3A,3E + DB 23,27,2B,2F,33,37,3B,3F + DB 23,27,2B,2F,33,37,3B,3F + DB 20,24,28,2C,30,34,38,3C + DB 20,24,28,2C,30,34,38,3C + DB 21,25,29,2D,31,35,39,3D + DB 21,25,29,2D,31,35,39,3D + DB 22,26,2A,2E,32,36,3A,3E + DB 22,26,2A,2E,32,36,3A,3E + DB 23,27,2B,2F,33,37,3B,3F + DB 23,27,2B,2F,33,37,3B,3F +; +; this gives the bit offset for each one +; +XBITTBL: + DB 0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + RADIX D +ZIPCOLOR: db 0,1,6,7,$C,$B,$E,$F +APLCOLOR: db 2,3,$FF,$FF,$FF,$FF,4,5,$FF,$FF,$FF,7,$FF,$FF,8,9 +OLDZV: +; +; Variables that used to be in the zero page but got moved out +; +PSVFLG EQU OLDZV ; (BYTE) PRESERVE FLAG FOR LEX 0=DON'T 1=DO +VOCFLG EQU PSVFLG+1 ; (BYTE) WHICH VOC TBL, 0=NORMAL 1= ARG3 +DBLOCK EQU VOCFLG+1 ; (WORD) Z-BLOCK TO READ +QUOT EQU DBLOCK+2 ; (WORD) QUOTIENT FOR DIVISION +REMAIN EQU QUOT+2 ; (WORD) REMAINDER FOR DIVISION +QSIGN EQU REMAIN+2 ; (BYTE) SIGN OF QUOTIENT +RSIGN EQU QSIGN+1 ; (BYTE) SIGN OF REMAINDER +DIGITS EQU RSIGN+1 ; (BYTE) DIGIT COUNT FOR "PRINTN" +OLDLEN EQU DIGITS+1 ; (BYTE) OLD LINE LENGTH +OLDEND EQU OLDLEN+1 ; (BYTE) OLD LAST CHAR IN [LBUFF] +SPSTAT EQU OLDEND+1 ; (BYTE) SPLIT SCREEN STATUS FLAG +LFROM EQU SPSTAT+1 ; (WORD) "FROM" LINE ADDRESS +LTO EQU LFROM+2 ; (WORD) "TO" LINE ADDRESS +PRLEN EQU LTO+2 ; (BYTE) SCRIPT LINE LENGTH +GPOSIT EQU PRLEN+1 ; (BYTE) DEFAULT SAVE POSITION +GDRIVE EQU GPOSIT+1 ; (BYTE) DEFAULT SAVE DRIVE +TPOSIT EQU GDRIVE+1 ; (BYTE) TEMP SAVE POSITION +TDRIVE EQU TPOSIT+1 ; (BYTE) TEMP SAVE DRIVE +TSLOT EQU TDRIVE+1 ; (BYTE) TEMP SAVE SLOT +DRIVE EQU TSLOT+1 ; (BYTE) CURRENT DRIVE +SIDEFLG EQU DRIVE+1 ; (BYTE) which disk side are we on +SRHOLD EQU SIDEFLG+1 ; (WORD) <>0 if doing sequential random +SCRIPTF EQU SRHOLD+2 ; (BYTE) DIROUT FLAG FOR PRINTER OUTPUT +SCRIPTFLG EQU SCRIPTF+1 ; (BYTE) Does window allow scripting? +OLDZSP EQU SCRIPTFLG+1 ; (WORD) +CURSFLG EQU OLDZSP+2 ; (BYTE) 1==New cursor X for DLINE +DBLK EQU CURSFLG+1 ; (WORD) +RDTBL1 EQU DBLK+2 ; (WORD) READ TABLE 1 (Game Relative) +RDTBL2 EQU RDTBL1+2 ; (WORD) READ TABLE 2 +NENTS EQU RDTBL2+2 ; (WORD) # ENTRIES IN VOCAB TABLE +DIRITM EQU NENTS+2 ; (WORD) OFFSET IN OUTPUT TBL (DIRTBL) +DIRCNT EQU DIRITM+2 ; (WORD) COUNT OF CHARS IN TBL (DIRTBL) +SVTCHAR EQU DIRCNT+2 ; (WORD) Old TCHARS table address +VOCMPC EQU SVTCHAR+2 ; (3 BYTES) Save for vocabulary MPC +VCESVE EQU VOCMPC+3 ; (3 BYTES) Save for VOCEND +VWLSVE EQU VCESVE+3 ; (3 BYTES) Save for VOCLEN +DIDVTBL EQU VWLSVE+3 ; (BYTE) <>0 if we have done default table +IN EQU DIDVTBL+1 ; (9 BYTES) INPUT BUFFER +OUT EQU IN+9 ; (9 BYTES) OUTPUT BUFFER +CURSOR_OFF EQU OUT+9 ; (BYTE) ==1 if char cursor not to be on +CRLF_CHECK EQU CURSOR_OFF+1 ; (BYTE) ==1 to do CRLF function check +PTR_COUNT EQU CRLF_CHECK+1 ; (BYTE) ==0 if checking pointer movement +INFODOS_END EQU PTR_COUNT+1 ; (WORD) last segment of infodos special +OLDZVLEN EQU INFODOS_END-PSVFLG+2 ; this is how much to reserve + + BLKB OLDZVLEN,0 ; and zero it out + +; ------------------ +; ERROR MESSAGE STRINGS +; ------------------ +E27: db E27L + db "Disk I/O Error" +E27L EQU $-E27-1 +E2B: db E2BL + db "Disk write protected" +E2BL EQU $-E2B-1 +E40: db E40L + db "Bad Filename" +E40L EQU $-E40-1 +E44: db E44L + db "Path not found" +E44L: EQU $-E44-1 +E45: db E45L + db "Volume not found" +E45L EQU $-E45-1 +E46: db E46L + db "File Not Found" +E46L EQU $-E46-1 +E48: db E48L + db "Disk Full" +E48L EQU $-E48-1 +E49: db E49L + db "LaneDOS limit: 12 files/directory" +E49L EQU $-E49-1 +E4E: db E4EL + db "LaneDOS limit: No writes to TREE files" +E4EL EQU $-E4E-1 +E4C: db E4CL + db "Unexpected EOF" +E4CL EQU $-E4C-1 + +ELIST: db $27 + dw E27 + db $2B + dw E2B + db $40 + dw E40 + db $44 + dw E44 + db $45 + dw E45 + db $46 + dw E46 + db $48 + dw E48 + db $49 + dw E49 + db $4C + dw E4C + db $4E + dw E4E +ELISTL EQU $-ELIST-3 ; mark last error code + + END + diff --git a/apple/yzip/rel.13/verify.asm b/apple/yzip/rel.13/verify.asm new file mode 100644 index 0000000..b2cd98a --- /dev/null +++ b/apple/yzip/rel.13/verify.asm @@ -0,0 +1,252 @@ + STTL "--- VERIFY CODE ---" + PAGE + + ; ------ + ; VERIFY + ; ------ + ; VERIFY GAME CODE ON DISK +VERBAD: DB EOL,"The data segment of file is BAD!",EOL +VERBADL EQU $-VERBAD +VERPBAD: DB EOL,"The picture data of file is BAD!",EOL +VERPBADL EQU $-VERPBAD +ZVFLAG: db 0 ; set to indicate ugliness +STARTPOS EQU I+LO ; this is where to start block +ZVER: + jsr CLOSE_GAME ; make sure the game files are closed + ldy GAME2NML ; get length of name + lda GAME2NM,Y ; get last char + eor #$30 ; make normal number + tay ; -1 to make ready for FETCH_FILE + dey ; F_F incs first + tya ; to push onto stack + pha ; and save for restoring later + lda #0 ; clear a few counters + sta ZVFLAG ; ==0 - verify worked; !=0 - verify broke + lda SEGTBL+SGTDISKS+1 ; get how many disks are here + sta DISKCNTR ; this shows which disk we are working on + dec DISKCNTR ; start down by one +VERIFY_LOOP: + jsr VERIFY_DATA ; check data in this file + jsr VERIFY_PICD ; check (possible) picture data in this file + lda GMREF ; get reference number + sta CLOSE_PB+CL_REFNUM ; and show CLOSE + CLOSE CLOSE_PB ; and shut it up + dec DISKCNTR ; next please + bpl VERIFY_LOOP ; and check the next file +ZVERX: + lda #>PAGELEN ; reset read buffer length + sta READ_PB+RD_BUFFLEN+HI ; to be $100 + lda # 0, then it isn't + jsr SETUP_DISK0 ; move around to point to start of data +VERD1: + ldy #SGTPICOF ; find where picture data starts + lda (DSEGS),Y ; MSB + sta J+HI ; J is the page counter + iny ; point to LSB + ora (DSEGS),Y ; any picture file? + bne VERD01 ; yes, so mark end of data + lda #$FF ; set J to be a real big number + sta J+LO ; okay + sta J+HI ; and this one + bne VERD11 ; all done +VERD01: + lda (DSEGS),Y ; and here it is + asl A ; *2 to make 512 pages be 256 pages + sta J+LO ; this is where it ends up + rol J+HI ; move in carry to MSB + lda J+LO ; now, subtract any skipping + sec ; doing sub + sbc PSEEK+SM_FPOS+1 ; take away any skipped amount + sta J+LO ; and save it + lda J+HI ; pick up carry + sbc #0 ; we will + sta J+HI ; we did +VERD11: + jsr VERIFY_FILE ; now, actually do the work + bcc VERDX ; worked just fine + DLINE VERBAD ; puke, gag, argh +; +; This prints out which file is garfed +; +VER_FMSG: + lda DISKCNTR ; which file did we do? + cmp #2 ; 0,1 are in one place + bcs VERDB1 ; nope it isn't it + DLINE GAME1NAME,GAME1NML + jmp VERDB2 +VERDB1: + DLINE GAME2NAME,GAME2NML ; 2,3 are in another +VERDB2: + inc ZVFLAG ; show bad file + jsr GETRET ; just wait for +VERDX: + rts ; all done +; +; VERIFY_PICD - verify the picture data in a file. First check to see if +; there is any. If so, seek to it, set J==0 to show VERIFY_FILE to read +; til EOF, and print out bad picture data message if necessary. +; +VERIFY_PICD: + lda #$FF ; gonna zero bunch of stuff + sta J+HI ; and the counter + sta J+LO ; which means now goto EOF + ldy #SGTPICOF ; fetch the picture data offset + lda (DSEGS),Y ; get MSB + sta PSEEK+SM_FPOS+2 ; we are doing pages + iny ; pointing to LSB + ora (DSEGS),Y ; first, check for all zeros + bne VERP1 ; nope, some picture data is there + rts ; just gwon back if nothing here +VERP1: + lda (DSEGS),Y ; go get LSB + asl A ; *2 to get 256 byte pages + sta PSEEK+SM_FPOS+1 ; put away here + rol PSEEK+SM_FPOS+2 ; pick up carry + lda #PHSIZE ; skip over header of file + sta STARTPOS ; show offset in first block +VERP11: + SET_MARK PSEEK ; and move to picture data spot + jsr VERIFY_FILE ; read in the data + SET_MARK PSEEK ; get back to beginning of pic data + READ READ_PB ; read in a block worth + lda IOBUFF+PHCHKS ; get MSB of picture checksum + cmp L+HI ; same as what we got? + bne VERPB ; nope + lda IOBUFF+PHCHKS+1 ; get LSB of picture checksum + cmp L+LO ; same as mine? + beq VERPX ; yup, checked out fine +VERPB: + DLINE VERPBAD ; picture data bad + jmp VER_FMSG ; print out file name +VERPX: + rts ; tootis finis +; +; VERIFY_FILE - Files is already open and pointing to start of checksummed +; data. Works along til J == 0 or EOF, which ever comes first. Starts by +; dec'ing J, so if J starts as 0, effectively means goto EOF. +; +VERIFY_FILE: + lda #0 ; clear out checksum counter + sta L+HI ; MSB + sta L+LO ; LSB + sta READ_PB+RD_BUFFLEN+LO + lda #4 ; make read read $400 (1Kb) + sta READ_PB+RD_BUFFLEN+HI +VFLOOP: + lda #RETRY_COUNT ; and set up retry count + sta RETRIES + lda #IOBUFF ; reading all the data + sta K+HI ; into, using as pointer +VFLRD: + READ READ_PB ; read in 1Kb of data + bcc VERF0 ; just fine read + cmp #$4C ; EOF error? + beq VFCHECK ; yes, so wee bee done + cmp #$4D ; InfoDOS EOF error? + beq VFCHECK ; ayyup + jsr RETRY ; check about retrying + bcc VFLRD ; and do again +VERF0: + lda J+LO ; count the block to be read + bne VERF1 ; no wrapping + lda J+HI ; anything left? + beq VFCHECK ; nope, all done then + dec J+HI ; count one block +VERF1: + dec J+LO ; count block + ldy STARTPOS ; and begin +VERF2: + lda (K),Y ; get byte + clc ; doing add + adc L+LO ; add it in + sta L+LO ; save it + bcc VERF3 ; no wrap + inc L+HI ; yes ther is +VERF3: + iny ; next byte + bne VERF2 ; back to start of inner tloop + + lda #0 ; start at first byte + sta STARTPOS ; okay + inc K+HI ; point to next block + dec READ_PB+RD_LENGTH+HI ; count this one + beq VFLOOP ; go read some more + bne VERF0 ; go do next 256 byte block +VFCHECK: + ldy #SGTCHKS ; get check sum + lda L+HI ; start with MSB + cmp (DSEGS),Y ; well . . . ? + bne VFBAD ; nope, it is wrong + iny ; first byte is okay + lda L+LO ; so check LSB + cmp (DSEGS),Y ; well . . . ? + bne VFBAD ; die a slow ugly death + clc ; clear carry to show niceness + rts +VFBAD: + sec ; carry is set if bad + rts ; and return to your fate +; +; SETUP_DISK0 - this routine does some special processing to get the file +; pointer to the beginning of data for the preload file. It skips over +; segment table. +SETUP_DISK0: + READ READ_PB ; read in first block + lda IOBUFF ; MSB of segment table size (in words) + sta PSEEK+SM_FPOS+1 ; middle part of offset + lda IOBUFF+1 ; LSB of size + asl A ; *2 to pick up carry + rol PSEEK+SM_FPOS+1 ; rotate in carry + rol PSEEK+SM_FPOS+2 ; and once more + tay ; check for wrapping upwards + beq STD01 ; no wrap up then +STD00: + inc PSEEK+SM_FPOS+1 ; wee did + bne STD01 ; no more wrapping + inc PSEEK+SM_FPOS+2 ; yes there is +STD01: + lda PSEEK+SM_FPOS+1 ; make sure it is a 512 byte page + and #$1 ; even page? + bne STD00 ; inc again, please +STD0X: + SET_MARK PSEEK ; skip the segment table stuff + rts ; all done + + END diff --git a/apple/yzip/rel.13/versions b/apple/yzip/rel.13/versions new file mode 100644 index 0000000..cd5d84c --- /dev/null +++ b/apple/yzip/rel.13/versions @@ -0,0 +1,670 @@ +This is just a list of all the version changes for the Apple ][ YZIP + +; +; 1 - 7/29/88 New numbering scheme +; Faster text handling +; +; 2 - 8/17/88 Gargantu-Games handling +; Fixed Restart +; Handle COLOR -1 +; Handle transparent colors in pictures +; +; 3 - 8/24/88 Joystick/Mouse handling +; +; 4 - 8/30/88 Heavily debugged with/for ZORK0 +; +; 5 - 9/1/88 Fix cursor x,y in WINGET +; Make CLS work on REAL skinny windows +; +; 6 - 9/2/88 No status check on CLOSEs +; Only allow alphanumerics for save names +; +; 7 - 9/2/88 Don't clear strobe first, do it after getting key +; Add /RAM check to boot code - restore /RAM after QUIT +; +; 8 - 9/7/88 Flag day +; Changed WINGET/WINPUT to like GET/PUT +; Add in multi disk stuff +; +; 9 - 9/15/88 Preload is in SEGMENT table now +; Program name in BOOT.ASM +; Copy name to correct place in boot and interpreter +; New name of interpreter is now "INFOCOM" +; Add verify code too +; +;10 - 9/16/88 Keep running count of dirout char width in lo core +; Set up pure and pre pointers for tables and functions +; +;11 - 9/20/88 Don't forget to add one to x,y pos of window and cursor +; in WINGET +; Init vocab pointers for default vocab table and use them +; +;12 - 9/28/88 Zero zero page stuff in two passes - used to wipe out ProDOS zero page +; Data length in pic files is now 3 bytes + +; +;13 - 10/11/88 Picture files and Data files are one and the same now +; +;14 - October 24, 1988 +; Add volumn command to save/restore get name routine +; +;15 - November 8, 1988 +; Search on disk 1 in last resort (hints are probably there) +; Use mouse in passive mode +; +;16 - November 14, 1988 +; Make mouse stuff be passive, rather than interrupt driven +; +;17- November 15, 1988 +; Few more fixes 'n' stuff +; +;18-November 15, 1988 +; Clear ZTWIDTH when starting table output +; +;19-November 28, 1988 +; Fix up PUT_NYBBLE and GET_NYBBLE +; Reset DSEGS after closing save file +; Make FONTSIZE word be Width/Height +; Make Chars/line reflect mono spaced char width of 3 in lo core +; Change ZTWIDTH to be MSB/LSB, rather than LSB/MSB word +; Point to main bank in CHK_MOUSE +; Clamp mouse to 136,189, and don't do shift when getting pos +; Make CLK_CNT be negative, and set flag to show button state +; Set up point to MSTBL (extension table for mouse clicks) +; Put X,Y coordinates in MSTBL after click +; +;20-December 1, 1988 +; Don't use [A] in DO_MOUSE unless it is a character +; Clear LSB in seek pblock before doing seek +; No, really, DON'T use [A] in DO_MOUSE +; Make CLK_CNT be 8 +; Exit normally if double click +; Split mouse cursor routine into 2 pieces - off and on +; If can't find picture, try opening other file. If it isn't there +; then die with error #$14 +; Move XPOSTBL and COLORS to page 3 for some elbow room +; Save/restore refnum when opening new picture file +; +;21-December 2, 1988 +; Swap back to Bank 1 in pic.asm +; +;22-December 5, 1988 +; Save/restore DSEG in verify +; Dec saved filename for passing to Fetch_file in Verify +; Fix addition for getting to Picture data in Verify +; Check for files 0 & 1 names in different place than 2 & 3 (Verify) +; Add STARTPOS to verify +; Copy BITOFF to BITTER in picture stuff +; +;23-December 6, 1988 +; Get picture data checksum from the right place +; Init counter for picture data checksum to be $FF, not 0 +; Move "mouse" cursor for joystick too +; Do "mouse" cursor pos for button for joystick too +; Change movement thresholds for joystick to 120/135 +; Double movement rate for joystick +; Change boundaries check in stick movement to bcs, not beq +; Save/restore cursor position in DLINE +; Create SWAP2INFOW/SWAPBACK to go to/from info window +; and have DLINE & GETSNAME use them +; Have only one exit point in GETSNAME +; Make DLINE do a CLRBUF upon exitting +; Add EOL to end of DELQ +; Muck with a few messages in ZSAVRES +; Change GAMEPL to maximum (64-15) as can only be a list of directories +; Add "Unexpected EOF" error string +; +;24-December 8, 1988 +; Game data starts out on even (512 byte) page boundary +; +;25-December 13, 1988 +; Make pop's FETCHB store afterwards +; Make WINGET handle 0-15 words to get +; Change order of window parameters, to make user ones the first +; 16 available +; Don't SWAP to infowindow in DLINE, rather do it in routines that +; call DLINE +; Fix color green in COLORS table +; +;26-December 14, 1988 +; Change PBEGIN to $0200 +; Scan for mouse slot, rather than asking or assuming +; After finding it, save lo byte in arg1+lo to change interpreter +; screen holes for interesting stuff +; Save/restore printer slot before/after SWAPBACK call +; +;27-December 15, 1988 +; Put paging buffer start back to $0800, cuz screen holes in aux +; mem really screw things up +; Make only closed-apple key work as function key faker +; +;28-December 16, 1988 +; Need only 8 chars for name, as .SYSTEM adds 7 more, to max 15 +; Make ZQUIT read RDBNK2, not write +; +;29-December 19, 1988 +; Save disk number when saving refnum, so that we can scan the two +; disks currently inserted, then look at all the rest +; Pass starting offset for segment list, cuz segments for side 1 +; start a little weird, cuz preload is the first set of +; segments, then the list starts normally +; Don't forget to save refnum in all the right places +; +;30-December 20, 1988 +; Use BIT_BITS in both CHAR_LINE and picture stuff +; Take out retries - it just doesn't work +; Add check for save disk when asking about swapping disk +; Copy read buffer to local buffer before doing read +; +;31-December 22, 1988 +; Play with bounds for joystick movement a little further out +; Don't script input line +; Fix input with timeout, so that the key gets parsed correctly +; Only look at button zero for joystick +; Call FKEYX instead of KEYX in TIMEK +; Check all online volumes before asking for disk by name +; Fix length byte before you do +; Use CHPTR in volume checking routine +; Copy path name to SCRBUFF so we can prepend a '/' in checking volumes +; And don't forget to count it in the length byte +; Quit if no more volumes to check +; More changes to avoid errors in set_prefix, which really seem to gum +; up the works +; +;32-December 23, 1988 +; Don't clear interrupts before reading paddles +; +;33-January 3, 1989 +; Spell volume right in error message +; Save cursor a little earlier in zdispl +; Set/clear savedisk only in close_save +; +;34-January 4, 1989 +; Make sure carry is set before returning from DISK_ERR +; Have SET_GAMEPRE use SAVENUM +; Push current INVFLG instead of saving in variable in ST_CUR +; Check for mouse cursor in timed input please too +; Took GOTKEY out, cuz no-one used it any more +; Changed order in TIMIN for goodness sake +; +;35-January 5, 1989 +; Try for 512 byte paging buffers +; +;36-January 6, 1989 +; Fix up some more for 512 byte buffers +; Muck with paging scheme (oh oh) +; Make GETRES take from one to four blocks +; Make restore use 4 blocks when doing full restore +; +;37-January 9, 1989 +; Fix multiple block restore problems +; Don't destroy DOS return code in GETRES +; Clear CLOSE_PB refnum +; Make DOS routine be READ_DOS and WRITE_DOS +; Fix read so SIB's increment word start +; Make WAIT10 check for mouse/joystick cursor movement +; Use FKEYX for [MORE] so buttons can be used +; +;38-January 10, 1989 +; Mess with PCHK and other scripting stuff +; Use GETKEY for [MORE] +; Put in delay before calling PREAD to get joystick status +; +;39-January 11, 1989 +; Make mouse cursor be two colors +; Change WAIT10 to be a loop, not an MWAIT call +; Clear MSMOVEF flag in MSCURS +; Don't check GETKEY's return in MORE +; Joystick is > 0, mouse is < 0 +; Leave mouse status in [A] for CHK_MOUSE +; Add DELAY_COUNTER for WAIT10 +; +;40-January 12, 1989 +; Fix shift (asl -> rol) when getting position of picture T.O.C. +; Don't split Mouse moving/button +; Play with Delay counter, doubling it if on a GS +; Make sure interrupts are turned back on in CHK mouse +; Only turn on button flag in CHK mouse, never turn it off +; Add another delay loop inside WAIT10 +; Make INNER & OUTER constant counters, with special ones for GS +; +;41-January 13, 1989 +; Add printer init call to pchk +; Play with SCRIPT flag (which allows scripting) +; Turn on initially +; Turn off at start of save/restore +; Turn on at end of save/restore +; Add SCRIPTFLG, which says whether window allows scripting +; +;42-January 19, 1989 +; Change to always seek to 512byte block boundary for new DOS +; pic.asm +; +;43-January 20, 1989 +; Move copy line for $D000 down to lower memory +; Add INFODOS flag for conditional assembly for special dos +; Play with boot to get it to work with 512byte blocks +; Take out all ROM calls, cept printer stuff; default is now +; BNK1SET +; +;44-January 26, 1989 +; Change DESTROY to SETEOF for new InfoDOS. +; +;45-January 31, 1989 +; Make paging stuff goto Bank 2, not bank 1 +; Make picture stuff goto Bank 1 +; Add INFODOS flag +; Non-sequential page map +; If INFODOS==1, then 12Kb preload in $D0-$FF, main bank, bank 2 +; and check for it in xpaging +; Just loop if using InfoDOS upon quit +; +;46-February 1, 1989 +; Don't muck with interrupts cuz InfoDOS don't like it +; +;47-February 4, 1989 +; Fixed set_eof to delete file. +; Ignore error returns for set_eof, cuz InfoDOS doesn't like to +; SET_EOF on an empty file. +; Make boot.asm print out version too +; Change special load from Kb's to pages +; Do special load 1 page at a time, rather than 2 +; +;48-February 6, 1989 +; Change get_special counter to count 2 blocks, not 4 +; Fix SAVE/RESTORE to do 512 byte pages for InfoDOS +; All reads in restore must be 512 bytes minimum +; +;49-February 7, 1989 +; Make SAVE_DATA self-modification be absolute, not relative +; Put version number into lower left corner of boot screen +; Fix scroll to move cursor to last line before doing any work +; and have it count the lines in lincnt, but not +; against the scrolling lines +; +;50-February 10, 1989 +; Add no write to TREE files error +; Add set_prefix call to OPEN_GAMEF, before opening file the +; first time +; Start Set-PB off pointing to game boot prefix +; Init a few GS registers in boot +; Put SET_EOF error check back +; Jump to reset vector if in InfoDOS +; +;51-February 13, 1989 +; Swap ROM back in if reading joystick +; Do a SET_EOF if bad save +; Check button click for joystick in delay loop +; Swap in ROM for jump to reset_vector +; Make restart load INFOCOM.SYSTEM +; Swap in ROM at start of boot task +; Try to get click/double click for joystick to work +; Add JB_STATE to show changing state +; Only check bit 7 +; Set CLK_CNT to 3 +; Only one loop in read_stick +; Fix restore of SCRCX in disp_line (nothing passed in [A]) +; In displaying cursor, always set up CHR_X, but don't change +; SCRCX +; +;52-February 14, 1989 +; Set CURSFLG at start of input and zinput +; Change display_line to not update for just show_cursor +; Don't let GET_SCRCX change chr_x +; Use my toggle for mouse button up&down +; Put in more check for joystick button +; Add Cursor off/on on curset of -1/-2 +; Go to prefix that was there on a save +; Take it out of zdos and put in close_save +; Just ask to put back game disk, not particular disk +; Fix set_gamepre - getret does not return == +; +;53-February 15, 1989 +; Wrap correctly if picture data starts near 256 byte boundary +; Add DIRECT_OUT call to DLINE/COUT to skip over checks like +; formatted table output and scripting +; Fix CHECK_JYBTN to check mouse if there is a mouse +; +;54-February 16, 1989 +; Fix check for -1/-2 in CURSET +; +;55-February 16, 1989 +; Major changes to COPY_LINE +; Change (zzz),Y to zzz,X +; Take out one of the counters +; +;56-February 17, 1989 +; Don't do CRLF check if doing interpreter printing +; +;57-February 21, 1989 +; Don't set function preload if tables take up all preload +; +;58-February 25, 1989 +; Ignore LINCNT during call to ZSCROLL +; Jump to ZRQUIT, not ZRBAD, when no restore name given +; Get updated DSKBNK in PUTDSK +; Make mouse hotspot be in middle of cursor +; +;59-February 28, 1989 +; Add Global Directory Offset to segment table structure +; Fix transparent color skipping to New X pos +; Add "Version:" to boot screen +; Move cursor to left most column for M/J/N question +; Ask for particular Game disk side after taking out save disk +; +;60-March 1, 1989 +; Change CHZ to good spot in boot.asm +; Add Global dir offset to segment 1 structure too +; Move Scrcx for good color in picture drawing too +; Send out eol too to position cursor in boot +; Don't ask for particular disk side after save, cuz I can't be sure +; whether it is a one disk or multi disk game (i.e. on a +; 3.5" disk, I don't want to ask for a particular side). If +; users puts in wrong disk, I will then ask for a particular +; side). +; Add SWAPPED flag to show a multi disk game, which requires special +; detailed question +; Check for $4D error in verify, cuz InfoDOS returns it instead of +; $4C on EOF +; +;61-March 2, 1989 +; Add SET_PREFIX to boot code startup +; Don't check for pointer movement if a key has been hit, at least +; not for a while (PTR_COUNT) +; +;62-March 4, 1989 +; Clear PTR_COUNT at start of ZINPUT and end of INPUT +; +;63-March 6, 1989 +; Don't set CURSFLG in ZINPUT/INPUT, cuz cursor doesn't want to +; move in an aborted one +; Make cursor always end up at top right of picture +; Move PIC1BUFF so it doesn't tromp input buffer +; Make RESTART use FETCH_FILE to get correct disk before rebooting +; Make CLOSE_SAVE use DO_GAME1 to get GAME1 file +; +;64-March 7, 1989 +; Make INPUT explicitly clear CURSFLG +; CLOSE_GAME should call DO_GAME1 first +; And don't forget to set SAVEDISK flag still +; Use OPEN_GAMEF, not FETCH_FILE in restart +; Make mouse x,y be one based +; Make sure there is a prefix in the save name +; Add check for zero length save file name +; Fix COPY_LINE to do ENDMASK correctly +; Update COPY_LINE's source address every loop in CLS +; Have call to buffout fall thru to CLRBUF +; +;65-March 7, 1989 +; Increased interpreter size to 42 pages +; Add clrbuf call to zfont +; Make random go fetch a word from memory +; Take out RNUM, just use RAND +; Add in Global directory handling +; +;66-March 8, 1989 +; Fix special case in SCANSEG for side 1 (skip 6, not 14) +; Add UNDERF to disp_line, so underline flag gets reset correctly +; Make partial save/restore work better, including by always readin +; in 2 pages worth +; +;67-March 9, 1989 +; Change some messages for inserting disks +; Fix get_save_name so it doesn't double print name on prefix error +; Modify some messages in save/restore +; Don't let user wrap input line +; +;68-March 9, 1989 +; Move Special to Aux bank, and paging to main bank +; +;69-March 10, 1989 +; Make CLREOL show inclusive width +; +;70-March 13, 1989 +; Don't make mouse x/y be one based (why?) +; When *2 for segment table size in boot, use both LSB & MSB +; +;71-March 14, 1989 +; Add in global dir handlers +; pic.asm - add OPEN_NEW_PF, FIND_PIC_DISK, and an expanded +; FIND_GBL +; zdos.asm - look for picture data in all files, including 1 & 2 +; Try to make keyboard read a little more responsive +; Set flags word to Apple ][ stuff in zbegin +; Add retry to GET_SPECIAL and GETDSK and VERIFY +; +;72-March 15, 1989 +; Don't forget to send side # out for RESEAT message +; Add CHARSET stuff +; Take into account the margins in CLREOL +; Modify how big entry is in getting picture/global directory +; Handle Ctrl-K (end of sentence) and Ctrl-I (start of paragraph) in +; COUT +; Go back to using MWAIT in WAIT10 +; Had NEXTPICF check backwards +; +;73-March 16, 1989 +; Make ISTCHARS function key check use tax/bmi sequence - no CMP +; Save LOCALS first in ZREST:, in case of early error +; Change where we display disk error (after RESEAT msg). +; Don't forget to save/restore the disk error # +; Fix check for double picture lookup +; Save cursor before drawing picture/restore it after +; Make FIX_COLOR handle either black or white foreground +; +;74-March 16, 1989 +; Make [MORE] get printed out without call to DLINE +; Set/restore DSEGS upon call to get picture data, just +; to make sure it's right. Also, don't bother going to +; get the data if it is the stuff already in memory +; Try to get more random +; Make sure GET_SPECIAL get's from the start of .D2 +; and all LSB's are zero'd +; +;75-March 17, 1989 +; Make sure disk error gets saved/restored while in RETRY +; Just tell user where to put disk, rather than what to take out +; and then tell what disk to put in +; Add APLCOLOR table for winget on color +; +;76-March 21, 1989 +; Reset find_gbl counter upon finding a picture +; Don't look for another global directory if we already have one +; Make findpicdisk stop trouncing on its data, and check both +; the disks that are in there +; Make the disk findpicdisk asks for be zero relative +; Change CLREOL width again - just make it # of pixels to clear +; User lower 4 bits in Long Jump ZPC MSB, and shift over once more? +; Allow game to set line count +; Go get picture data even if file is already open, if it isn't the +; one currently in memory +; Don't add extra spaces to start of line for tab/eos chars +; +;77-March 22, 1989 +; 'nother day, 'nother version +; Turn screen on/off with table output off/on +; Swap returned fore/back colors in winget +; Set length to zero if x pos < left margin +; Probably ought to be fixed better, perhaps by not taking +; left margin into account in XSIZE, and starting length off +; at left margin on CRLF/wrap +; Implement ERASE n, where n > 1 +; Make sure picture file directory gets read in, even if the file +; is already open, if it is not the data in memory +; Clear LINCNT on every ZCRLF in ZSCROLL +; Don't take into account the left margin in CLREOL +; Count byte if special start/end in COPY_LINE +; +;78-March 23, 1989 +; Try once more . . . +; Fix verify so it counts down correctly, and count the block at +; start of add, not end +; Make take out save disk message wrap better +; Make sure EOL is in CHARSET table, even if a table is passed to +; me +; Fix MSB/LSB of piccnt in FIND_GBL +; Save File ID of local directory, for later checking +; Don't move in starting spaces in FLUSH +; Make sure SCREENF is on while in DLINE +; +;79-March 24, 1989 +; This is so much fun, I just wanted to do it again . . . +; Wrap TWIDTH up before /4 +; Don't set undo bit in flag word +; Don't script [MORE] +; +;80-March 27, 1989 +; 'nother week, 'nother interpreter (are we having fun yet?) +; Change CLICK_CNT to 4 +; Swap to infowindow before zerror +; Just check passed arguments for fitness in WINSIZE/WINPOS, not +; the results +; +;81-March 28, 1989 +; Make sure the clear operand in the window attributes command works +; correctly +; Change LINCNT check in ZCRLF to be bcc, not bne +; Make sure first read in full restore has 2 blocks, to maybe catch +; a define save +; Make sure ROM is NOT in there when doing a reset +; Add some retries to boot disk +; +;82-March 29, 1989 +; Add one to PURBT size on restore and make sure last read is an +; 512 page +; Use TBLRTN on formatted table in flush +; +;83-March 30, 1989 +; Put in some retries in boot reads +; Make sure winput puts LINCNT +; Update attributes if -3 passed to WINATTR too +; Do CLRBUF in DIROUT +; Just set SCRIPT to true, not inc it, in CLOSE_SAVE +; +;84-March 31, 1989 +; Fix verify's handling of disk 1, and don't bother to skip 64 bytes +; of lo core +; +;85-April 3, 1989 +; Munge power up valid byte before jump to RESET_VECTOR +; Set ZFLAGS word correctly +; Try to turn on more bits in hi byte of random number +; +;86-April 5, 1989 +; Don't save/restore DSEG/GMREF in verify - just let fetch_file do +; the work +; Clear PF_FID in CLOSE_GAME +; Try to make RESET_VECTOR work, but getting/storing RESET_VECTOR, +; loading in ROM, then jumping to vector +; +;87-April 6, 1989 +; On error in GTS, restart whole process +; Load length of Game 2 name before checking in fetch file +; +;88-April 10, 1989 +; Don't script SCROLL call +; XOR mouse cursor onto screen +; Don't update LENGTH in INPUT til we've made sure it fits +; Handle monospaced font in BACKSPACE +; Don't script special chars +; Don't die on bad call to picinf, just on disp pic +; +;89-April 11, 1989 +; Check for zero object in REMOVE +; Make sure soft switches are good in ZSAVE +; Make sure restore gets correct number of blocks if even multiple +; of 4 is saved +; Don't allow escape key +; Swap to info window on reseat message +; Try doing online call before checking volume name again +; +;90-April 12, 1989 +; Make sample filename for save be in uppercase, cuz Hollywood's a +; turkey +; +;91-April 13, 1989 +; One more for the gipper +; Don't bother printing the prefix on bad file verify message +; Print spaces to delete MORE, not CLREOL +; +;92-April 18, 1989 +; Add IPAGE to INFO_PAGE +; Clear [MORE] with backspaces +; +;93-April 19, 1989 +; If no bit in global directory, assume picture is on disk 1 +; +;94-April 20, 1989 +; Add more debugging code (save ZPC, ZPCPNT, and OPCODE) +; +;95-April 21, 1989 +; Add fatal error on clear of zero width/height (#25) screen +; +;96-April 22, 1989 +; Unwind the stack on a THROW +; +;97-April 26, 1989 +; Take out unscripting of control chars, so we get EOL +; +;98-April 27, 1989 +; Give back version number of pic file +; Move file pointer to beginning of file in verify, before calling +; SETUP_DISK0 +; Don't count skipped data on side 1, verify +; +;99-April 28, 1989 +; 'Nother new version, just cuz it's so much fun messing with +; Hollywood's pea brain +; Make sure bank 2 is still in after mouse call +; +;1-May 1, 1989 +; Shipped version +; +;2-May 2, 1989 +; HA! +; Do 5 retries, reseeking to zero and back before asking for reseat +; +;3-May 8, 1989 +; Let's pretend this is the shipped version +; Let's first retry the set prefix a few times before asking again +; +;4-May 11, 1989 +; Put in more debugging stuff for SHOGUN problems +; +;5-May 18, 1989 +; Take out ONLINE call in SET_PREFIX +; Make all PAGE2SW be READS!! not WRITES!! +; Make sure we leave off pointing to MAIN PAGE 2 always! +; Don't ever mess with STORE80 switch - ALWAYS ON +; +;6-May 19, 1989 +; Take out debugging stuff +; Make version number for pic files be swapped +; +;7-May 22, 1989 +; Put debugging code back in +; Make sure main bank is in there before starting scroll stuff +; Just scroll up X lines, don't bother with ZCRLF stuff +; +;8-May 23, 1989 +; Let's ship this version +; Move the SWAPBACK call on retry +; ORA char with $80 before shipping to printer +; Don't do clrbuf's at the start/end of PRINTT +; +;9-May 24, 1989 +; SHOGUN version, without PRINTT change +; +;10-May 24, 1989 +; Continued version, with PRINTT change +; +;11-June 2, 1989 +; Make formatted table have char count at front of line be a full +; word, for some dumb ass reason +; +;12-June 6, 1989 +; Make erase width be zero-based +; +;13-June 7, 1989 +; Take above "fix" out, please +; diff --git a/apple/yzip/rel.13/windows.asm b/apple/yzip/rel.13/windows.asm new file mode 100644 index 0000000..67be2b6 --- /dev/null +++ b/apple/yzip/rel.13/windows.asm @@ -0,0 +1,769 @@ + + STTL "--- WINDOW OPERATIONS ---" + PAGE +; +; these are the data structures for all 8 WINDOW. They are identical and +; are just seperated cuz I use the addresses in the table that follows. +; All numbers are inclusive, absolute, and zero-based. +; +WINDSTRUCT EQU 0 +WINTOP EQU WINDSTRUCT ; first line of the window +WINLEFT EQU WINTOP+1 ; left edge of the window +WINHGHT EQU WINLEFT+1 ; height of the window +WINWID EQU WINHGHT+1 ; width of the window, in pixels +WINY EQU WINWID+1 ; y pos of cursor (pos, not relative) +WINX EQU WINY+1 ; x pos of cursor (remember, ABSOLUTE) +WINLM EQU WINX+1 ; left margin +WINRM EQU WINLM+1 ; right margin +WINCRF EQU WINRM+1 ; (WORD) function +WINCRC EQU WINCRF+2 ; (WORD) counter +WINHIGHL EQU WINCRC+2 ; highlight mode +WINFORE EQU WINHIGHL+1 ; foreground color (0=black-7=white) +WINBGND EQU WINFORE+1 ; background color (0=black-7=white) +WINFONT EQU WINBGND+1 ; window font (0=normal/4=monospaced) +WINFSIZE EQU WINFONT+1 ; (WORD) font Height/Width +WINATR EQU WINFSIZE+2 ; Window Attributes +WINLCNT EQU WINATR+1 ; current number of lines +; +; these are my interesting things +; +WINXSZ EQU WINLCNT+1 ; width of window, in pixels, using margin +WINLLEN EQU WINXSZ+1 ; length of current line +WINLINES EQU WINLLEN+2 ; max # of lines for window + +WINDOW0: + DB 0 ; WINTOP - first line of the window + DB 0 ; WINLEFT - left edge of the window + DB MAXHEIGHT ; WINHGHT - height of window + DB MAXWIDTH ; WINWID - width of window + DB 0 ; WINY - y pos of cursor (pos, not relative) + DB 0 ; WINX - x pos of cursor (remember, ABSOLUTE) + DB 0 ; WINLM - left margin + DB 0 ; WINRM - right margin + DW 0 ; WINCRF - function + DW 0 ; WINCRC - counter + DB 0 ; WINHIGHL - Highlights + DB $f ; WINFORE - foreground color default of white + DB 0 ; WINBGND - background color + DB 0 ; WINFONT - window font (0=normal/1=alternate) + DB 2,FONT_H ; WINFSIZE - Width/Height + DB $0f ; WINATR - all attributes on for window 0 + DB 0 ; WINLCNT - current number of lines + DB MAXWIDTH ; WINXSZ - width of window, in pixels, using margin + DB 0,0 ; WINLLEN - length of current line + DB (MAXHEIGHT/FONT_H)-1 ; WINLINES - max # of lines for window +; +; same start as window 0, but with 0 length +; +WINDOW1: + DB 0,0,0,MAXWIDTH,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,MAXWIDTH,0,0,0 +; +; the rest have no width/height/attributes (except buffering) +; +WINDOW2: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW3: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW4: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW5: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW6: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW7: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + +WINTABLE: + DW WINDOW0,WINDOW1,WINDOW2,WINDOW3 + DW WINDOW4,WINDOW5,WINDOW6,WINDOW7 + PAGE + +; ------ +; SCREEN +; ------ +; Move to the screen specified, by updating CURWIN and the cursor +; X,Y pos (SCRX,SCRY). Also put address of that window's structure +; in WINDOW. Save a bunch of the old stuff in old window's structure then +; update the same bunch with the new window's stuff. +; +; ARG1 - new screen id: 0-7 +; +ZSCRN: + jsr CLRBUF ; EMPTY OUTPUT BUFFER BEFORE MOVING +; +; now, save a few things from the common variables +; + ldy #WINLLEN ; current line length + lda LENGTH+LO ; get current line length + sta (WINDOW),Y ; save for later referencing + iny ; point to msb + lda LENGTH+HI ; get MSB + sta (WINDOW),Y ; saved + jsr SAVE_CURSOR ; save the x,y pos of cursor + lda INVFLG ; get inverse flag + beq ZSCA1 ; not set + lda #1 ; set 1 bit + bne ZSCA2 ; set in window +ZSCA1: + lda UNDFLG ; how about underlining + beq ZSCA2 ; nope + lda #4 ; 4 == underlining +ZSCA2: + ldy #WINHIGHL ; set new highlight + sta (WINDOW),Y ; save current attributes +; +; now it is time to update for new screen +; + lda ARG1+LO ; get which window + sta CURWIN ; save window number + asl A ; shift to make word indes + tax ; swap to indexing reg + lda WINTABLE,X ; get the address of the new WINDOW + sta WINDOW+LO ; lo part comes first + lda WINTABLE+1,X ; so go get hi part + sta WINDOW+HI ; save the hi part of the address + + jsr GET_CURSOR ; restore the cursor pos + + ldy #WINXSZ ; get line length + lda (WINDOW),Y ; update zero page variable + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + ldy #WINLLEN ; get current line length + lda (WINDOW),Y ; from before + sta LENGTH+LO ; save for later checking + iny + lda (WINDOW),Y + sta LENGTH+HI + ldy #WINLCNT ; how many lines already out there + lda (WINDOW),Y ; has been already saved + sta LINCNT ; and save 'ere too + ldy #WINLINES ; how many lines in this + lda (WINDOW),Y ; window, anyway? + sta MAXLINES ; show for everyone to see + ldy #WINLEFT ; show left margin + lda (WINDOW),Y ; get left edge + ldy #WINLM ; left margin + clc ; adding + adc (WINDOW),Y ; to find new left margin + sta LEFTMRG ; set up left margin for ease of use + ldy #WINTOP ; get top of window + lda (WINDOW),Y ; got it + clc ; adding + ldy #WINHGHT ; add height + adc (WINDOW),Y ; did it + sta SCRBTM ; this is first line outside window + ldy #WINHIGHL ; get highlighting modes + lda (WINDOW),Y ; first for inverse video + and #1 ; check for inverse video + beq SCRINV ; nope + lda #$80 ; means inverse video +SCRINV: + sta INVFLG ; there it be + lda (WINDOW),Y ; point to underline flag + and #4 ; check for underlining + beq SCRUND ; nope + lda #$80 ; means underlining +SCRUND: + sta UNDFLG ; save for everyone + + ldy #WINATR ; get the current attributes + lda (WINDOW),Y ; gottem + jsr SET_ATTRIBUTES ; set the flags, thank you + ldy #WINFONT ; get the font + lda (WINDOW),Y ; thank you + beq SCRFNT0 ; is it font zero? + lda #MONOFONT_W ; must be mono font, set width +SCRFNT0: + sta FONTFLG ; mark normal font +ZSCREX: + rts +;-------------- +; ZWINPOS +;-------------- +; +; change the window ARG1's top left corner to the new position +; +; ARG1 - window id from 0-7 +; ARG2 - new top y pos +; ARG3 - new top x pos +; +ZWINPOS: + dec ARG2+LO ; make pos be zero based + dec ARG3+LO ; now they are! +; +; if moving current window, save current cursor pos +; +ZWPOS0: + jsr SAVE_CURSOR ; saving +; +; let's set up [J] to point to window we are talking about +; +ZWPOS1: + lda ARG1+LO ; get window ID + jsr SETWJ ; get J to point to it + + lda ARG2+LO ; first, check the top + cmp #MAXHEIGHT ; < max height? + bcc CKWA1 ; fine + lda #0 ; make it zero then + sta ARG2+LO ; it is now +CKWA1: + lda ARG3+LO ; now check left edge + cmp #MAXWIDTH ; howzit compare + bcc CKWA2 ; just fine + lda #0 ; this too + sta ARG3+LO ; it is now +CKWA2: +; +; make the cursor pos be relative, so we can change back to +; absolute using new window pos +; + ldy #WINY ; let's do y pos first + lda (J),Y ; get the old y pos + ldy #WINTOP ; and subtract the top to make + sec ; (getting ready) + sbc (J),Y ; the pos relative + clc ; now add in new top + adc ARG2+LO ; this will be new top + ldy #WINY ; get y offset again + sta (J),Y ; and save new absolute y pos + ldy #WINX ; now we be talking about x pos + lda (J),Y ; get old x pos + sec ; getting ready for sub + ldy #WINLEFT ; get rid of left ness + sbc (J),Y ; now it's relative + clc ; get ready to add in new left ness + adc ARG3+LO ; done + ldy #WINX ; get x offset again + sta (J),Y ; save in structure +; +; now we can change the top and left of the window +; + lda ARG2+LO ; this is top of window + ldy #WINTOP ; TOP offset + sta (J),Y ; save the new top + lda ARG3+LO ; here is the left edge + ldy #WINLEFT ; offset into struct + sta (J),Y ; saved ! +; +; we might have moved current window so update screen cursor and left margin +; + jsr GET_CURSOR ; restore cursor + ldy #WINLEFT ; get left edge + lda (WINDOW),Y ; okay + ldy #WINLM ; add in left margin + clc ; adding + adc (WINDOW),Y ; to find new left edge + sta LEFTMRG ; store for ease of use + ldy #WINXSZ ; get xsize + lda (J),Y ; okay + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI +ZWPOSX: + rts +;------------ +; ZWINSIZE +;------------ +; +; Change the size of window ARG1. If cursor is outside of window, +; move to it. +; +; ARG1 - window ID +; ARG2 - height +; ARG3 - width +; +; Uses [J]. +; +ZWINSIZE: +; +; first put SCRCX,CY into window structure, just in case +; + jsr SAVE_CURSOR ; saved +; +; now do everything +; + lda ARG1+LO ; get the window ID + jsr SETWJ ; and get window pointer + + lda ARG2+LO ; first, check the top + cmp #MAXHEIGHT ; < max height? + bcc CKWA11 ; fine + lda #MAXHEIGHT ; make better + sta ARG2+LO ; it is now +CKWA11: + lda ARG3+LO ; now check left edge + cmp #MAXWIDTH ; howzit compare + bcc CKWA21 ; just fine + lda #MAXWIDTH ; make it the max + sta ARG3+LO ; it is now +CKWA21: + lda ARG2+LO ; get new height + ldy #WINHGHT ; offset + sta (J),Y ; save new height + lda ARG3+LO ; get width + ldy #WINWID ; store width + sta (J),Y ; okay +; +; now we need to figger out new XSIZE, MAXLINES +; + ldy #WINWID ; store width + lda (J),Y ; get width + sec ; have width, subtract margins + ldy #WINRM ; first right margin + sbc (J),Y ; subtracted right margin + ldy #WINLM ; and now for the left margin + sbc (J),Y ; now we have new XSIZE + ldy #WINXSZ ; get offset + sta (J),Y ; save for later ref + lda ARG2+LO ; get new height + ldx #$FF ; this is the counter + sec ; get ready for subs +ZWSZ1: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZWSZ1 ; still some lines + dex ; to keep the input line on screen + txa ; get line count for storage + ldy #WINLINES ; this is how many lines are allowed + sta (J),Y ; saved +; +; check to make sure the cursor is still in the window +; + ldy #WINLM ; get left margin + clc ; for adding + adc (J),Y ; for figgering out right edge + ldy #WINLEFT ; add in left edge + adc (J),Y ; get right column by adding in left one + ldy #WINX ; check X pos + cmp (J),Y ; see if X is still inside? + beq ZWSZ2 ; must move to top left + bcc ZWSZ2 ; ditto if X >= margin + ldy #WINTOP ; get top to figger last line + lda (J),Y ; from the structure + ldy #WINHGHT ; and add in the height + clc ; getting ready for add + adc (J),Y ; to find first line outside of range + ldy #WINY ; now check y + cmp (J),Y ; now check y then + beq ZWSZ2 ; outside, move to top left + bcs ZWSZ3 ; inside so quit +; +; move the cursor to top left if outside of resized window +; +ZWSZ2: + ldy #WINTOP ; top line is here + lda (J),Y ; so get me it + ldy #WINY ; now we be doing y + sta (J),Y ; change Y + ldy #WINLEFT ; move X to left margin + lda (J),Y ; first get left edge + ldy #WINLM ; and add in left margin + clc ; (adding) + adc (J),Y ; to get left spot of cursor + ldy #WINX ; this is x offset + sta (J),Y ; so move X there +; +; now check to see if we mucked with current window +; +ZWSZ3: + lda ARG1+HI ; this is the id + bmi ZWSZ4 ; must be current window + cmp CURWIN ; is it current window? + bne ZWSZX ; nope, so done +ZWSZ4: + ldy #WINLINES ; get how many lines + lda (J),Y ; get number of lines + sta MAXLINES ; set global + ldy #WINXSZ ; get new XSIZE too + lda (J),Y ; get it + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + jsr GET_CURSOR ; fix the cursor pos +ZWSZX: + rts +; +;CHECK_WIN_ARGS +; check args to make sure they be okay +; +; ARG2 = top/height +; ARG3 = right/width +; +CHECK_WIN_ARGS: + rts + + ; ------ + ; HLIGHT + ; ------ + +ZLIGHT: + lda ARG1+LO ; get argument + cmp #$10 ; must be <= 8 + bcs ZLIEX ; nope it aint + ora #$80 ; turn on hi bit + jsr COUT ; send it out then +ZLIEX: + rts ; done +; +; actually set the highlight flags according to [A] +; +HLIGHT: +; +; TURN OFF ALL HIGHLIGHTS +; + and #$7F ; turn off high bit + bne ZL1 ; nope, must be something + sta UNDFLG ; and turn of underlining flag + sta INVFLG ; and inverse + rts ; all done +ZL1: + cmp #4 ; underlining + bne ZL_REV ; maybe its INVERSE? + + lda #$80 ; turn on UNDFLG + sta UNDFLG ; with an FF + rts ; done +ZL_REV: + cmp #1 ; INVERSE? + bne ZL_MONO ; maybe monospaced then + lda #$80 ; must be inverse video + sta INVFLG ; and put it in invflg + rts +ZL_MONO: + rts ; fuck it for now! +; +; ZWINATTER - change the scrolling/buffering/scripting/wrapping attributes +; of the window. +; +; ARG1 - window id +; ARG2 - interesting bits +; | buffering | scripting | scrolling | wrapping | +; ARG3 - operation - 0 MOVE +; 1 SET +; 2 CLEAR +; 3 COMPLEMENT +; +ZWINATTR: + lda NARGS ; see how many args + cmp #3 ; check for operation args + beq ZWAT1 ; yes, already there + lda #0 ; zero means MOVE + sta ARG3+LO ; so show it as default +ZWAT1: + lda ARG1+LO ; get window ID + jsr SETWJ ; put window address into [J] + + ldy #WINATR ; get attribute offset + lda (J),Y ; get current attribute + clc ; so we can just branch + + dec ARG3+LO ; decrement to find out what to do + bmi ZWMOVE ; do a move + beq ZWSET ; do a set + dec ARG3+LO ; check once more + beq ZWCLEAR ; clear set ones +; +; this is for the COMPLEMENT operations +; + eor ARG2+LO ; complement bits + bcc ZWAT2 ; done +ZWMOVE: +; +; move into the flag word +; + lda ARG2+LO ; get new flags + bcc ZWAT2 ; done +ZWSET: +; +; set turned on ones +; + ora ARG2+LO ; set'em up + bcc ZWAT2 ; done +ZWCLEAR: +; +; clear just the ones that are on +; + lda ARG2+LO ; get argument + eor #$FF ; turn on all the off ones + and (J),Y ; keep all the other ones +ZWAT2: + sta (J),Y ; and save it back +; +; now, if current window, set necessary flags +; + ldx ARG1+LO ; get window ID + bmi SET_ATTRIBUTES ; assume negative is current window + cpx CURWIN ; is this the current one? + bne ZWATX ; nope, so leave +SET_ATTRIBUTES: +; +; current window, so set flags accordingly +; + ldx #0 ; to turn off flag + ldy #1 ; to turn on flag + ror A ; get wrapping flag into carry + bcc ZWAT3 ; clear it + sty WRPFLG ; set wrapping on + bcs ZWAT33 ; okay +ZWAT3: + stx WRPFLG ; clear wrapping flag +ZWAT33: + ror A ; now check thes crolling flag + bcc ZWAT4 ; not set + sty SCRLFLG ; turn on scrolling flag + bcs ZWAT44 ; okay, next please +ZWAT4: + stx SCRLFLG ; turn off scrolling +ZWAT44: + ror A ; checking the scripting flag + bcc ZWAT5 ; not set + sty SCRIPTFLG ; allow scripting? yes + bcs ZWAT55 ; next flag +ZWAT5: + stx SCRIPTFLG ; allow scripting? no +ZWAT55: + ror A ; this checks the buffering flag + bcc ZWAT6 ; not set + sty BUFFLG ; turn on buffering + bcs ZWATX ; scram +ZWAT6: + stx BUFFLG ; turn off buffering +ZWATX: + rts +; +; ZWINGET - put the window stuff into a table +; +; ARG1 - Window id +; ARG2 - offset +; +ZWINGET: + jsr SAVE_CURSOR ; save x,y into structure + + lda ARG1+LO ; get window ID + jsr SETWJ ; set up window address + + lda ARG2+LO ; get where to start getting + asl A ; make word index + tax ; make index + lda ZWGTBL+LO,X ; get lo part of address + sta K+LO ; save for jumping + lda ZWGTBL+HI,X ; get hi part + sta K+HI ; saved + jsr ZWGVEC ; do the vectoring + stx VALUE+HI ; save hi part + sta VALUE+LO ; and the lo part + jmp PUTVAL ; and return it +ZWGVEC: + jmp (K) ; and goto it boys +ZWG0: + ldx #0 ; zero out high part + ldy #WINTOP ; get window y pos + lda (J),Y ; got it + tay ; need to inc it + iny ; to make it a one-based number + tya ; back to a + rts +ZWG1: + ldx #0 ; zero out high part + ldy #WINLEFT ; get window x pos + lda (J),Y ; got it + tay ; need to inc it + iny ; to make it a one-based number + tya ; back to a + rts +ZWG2: + ldx #0 ; zero out high part + ldy #WINHGHT ; get window height + lda (J),Y ; got it + rts +ZWG3: + ldx #0 ; zero out high part + ldy #WINWID ; window width + lda (J),Y ; got it + rts +ZWG4: + jsr FETCHCY ; get the current Y pos + ldx #0 ; zero out high part + rts +ZWG5: + jsr FETCHCX ; fetch the current X pos + ldx #0 ; zero out high part + rts +ZWG6: + ldx #0 ; zero out high part + ldy #WINLM ; left margin + lda (J),Y ; got it + rts +ZWG7: + ldx #0 ; zero out high part + ldy #WINRM ; right margin + lda (J),Y ; got it + rts +ZWG8: + ldy #WINCRF+HI ; function + lda (J),Y ; got it, lo part + tax ; save hi part + dey ; point to lo part + lda (J),Y ; got lo part + rts +ZWG9: + ldy #WINCRC+HI ; count + lda (J),Y ; got it, hi part + tax ; save it + dey ; now to lo part + lda (J),Y ; got it + rts +ZWG10: + ldy #WINHIGHL ; get high light mode + lda (J),Y ; got it + ldx #0 ; zero out high part + rts +ZWG11: + ldy #WINBGND ; and background + lda (J),Y ; got it + tay ; make index + lda APLCOLOR,Y ; get apl->zip color + tax ; save for return + ldy #WINFORE ; get foreground + lda (J),Y ; got it + tay ; save it + lda APLCOLOR,Y ; get apl->zip color + rts +ZWG12: + ldy #WINFONT ; now for font id + lda (J),Y ; got it + ldx #0 ; zero out high part + rts +ZWG13: + ldy #WINFSIZE+1 ; font size (width) + lda (J),Y ; got it + tax ; save it + dey ; font size (height) + lda (J),Y ; got it + rts +ZWG14: + ldx #0 ; zero out high part + ldy #WINATR ; attributes + lda (J),Y ; got it + rts ; got them! +ZWG15: + ldx #0 ; only 1 byte worth + ldy #WINLCNT ; offset + lda (J),Y ; get more counter + rts +; +; jump table for figgering out where to start filling +; +ZWGTBL: + DW ZWG0,ZWG1,ZWG2,ZWG3,ZWG4,ZWG5,ZWG6,ZWG7 + DW ZWG8,ZWG9,ZWG10,ZWG11,ZWG12,ZWG13,ZWG14,ZWG15 +; +; ZSCROLL - scroll the specified window up or down +; +; ARG1 - window ID +; ARG2 - lines to scroll; <0 scrolls down +; +ZSCROLL: + jsr SAVE_CURSOR ; save where cursor is + + lda #0 ; don't script scroll + sta SCRIPT ; fine, we won't now + + lda ARG1+LO ; get which window + jsr SETWJ ; set up pointer + dec NARGS ; see what we have for lines + bne ZSCR1 ; a passed arg + lda #1 ; 1 line is default + sta ARG2+LO ; so say so +ZSCR1: + ldy #WINTOP ; get me window limits + lda (J),Y ; first top + sta CLSTOP ; save for usage + iny ; now left + lda (J),Y ; okay, get for this window + sta CLSLEFT ; save left + iny ; now it's width + lda (J),Y ; got the window height + sta CLSHEIGHT ; this is it + iny ; this is height + lda (J),Y ; get window's height + sta CLSWIDTH ; save + lda ARG2+HI ; is it negative? + sta SCLDIR ; show direction of scroll + bpl ZSCRL1 ; nope + ldx ARG2+LO ; get how many lines + eor #$FF ; make pos + tax ; put in X for inc + inx ; and make right + bne ZSCRLEX ; done +ZSCRL1: + ldx ARG2+LO ; get how many lines +ZSCRLEX: + stx SCLLINES ; save for routine + jsr DO_SCROLL ; and do the scroll +ZSCRLEX1: + lda #1 ; allow scripting + sta SCRIPT ; we do + jmp GET_CURSOR ; restore the cursor, thank you +; +; ZWINPUT - put some information into window structure. Just CRF/CRC +; is legit now. +; +; ARG1 - window ID +; ARG2 - Word to be saved +; ARG3 - offset of value +; +ZWINPUT: + jsr SAVE_CURSOR ; save the cursor pos + lda ARG1+LO ; get window ID + jsr SETWJ ; have J point to structure + + lda ARG2+LO ; get first value in table + cmp #8 ; 8 = function + beq ZWIPCRF ; so save that + cmp #9 ; this is counter + beq ZWIPCRC ; so set counter + cmp #15 ; LINCNT? + beq ZIPLCT ; then set it too + rts ; just die then +ZIPLCT: + ldy #WINLCNT ; point to line count + bne ZWINPUT2 ; and stash it away +ZWIPCRF: + ldy #WINCRF+1 ; point to window's CR function + bne ZWINPUT1 ; and put it +ZWIPCRC: + ldy #WINCRC+1 ; point to window's CR counter +ZWINPUT1: + lda ARG3+HI ; now get hi part + sta (J),Y ; saved! + dey ; point to lo part +ZWINPUT2: + lda ARG3+LO ; start with lo part + sta (J),Y ; save lo part +ZWIPLCT: + jmp GET_CURSOR ; restore cursor/lincnt + + END diff --git a/apple/yzip/rel.13/xpaging.asm b/apple/yzip/rel.13/xpaging.asm new file mode 100644 index 0000000..ebce363 --- /dev/null +++ b/apple/yzip/rel.13/xpaging.asm @@ -0,0 +1,681 @@ + STTL "--- MEMORY PAGING ROUTINES ---" + PAGE + +; ------------------------- +; POINT [MPC] TO V-ADDR [I] +; ------------------------- + +SETWRD: LDA I+LO + STA MPCL + LDA I+HI + STA MPCM + LDA #0 + STA MPCH ; ZERO TOP BIT + JMP VLDMPC + +; +WANTED: DB 00,00 +; +NEXT: DB 00 +NSUBA: DB 00 +PSUBA: DB 00 +; +YTEMP: DB 00 +ATEMP: DB 00 +NSUBY: DB 00 +; +; set [A](page), [Y](bank) to point to memory page where page in [A] is +; +SETPC: + sta MEMPAGE ; save it for later addition + cmp #P2PAGE ; IS IT A PAGE IN MAIN + bcs VF2 ; No, it might be in aux mem + + lda #>ZBEGIN ; ADD OFFSET TO GET RAM PAGE + ldy #MAIN ; in the main bank + beq VFEXI ; BRA to fetch +VF2: + cmp #PGBEGIN ; is it paged? + bcs VFERR ; yes it be paged, so can't deal with it + cmp #P3PAGE ; is it in Aux Mem, Part 2? + bcs VF3 ; yes, so subtract different amount +; +; this is in lower aux +; + lda #(Z2PAGE-Z1SIZE) ; subtract size from offset + ldy #AUX ; show aux mem + bne VFEXI ; jump to end +VF3: + lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides + ldy #P3BANK ; show page 3 bank +VFEXI: + clc ; get ready for addition + adc MEMPAGE ; now get actual offset + rts +VFERR: +; +; out of range +; + lda #18 + jmp ZERROR +; +; NEXTSPC - inc SPCL and check for wrapping round to next bank +; +NEXTSPC: + inc SPCL ; next lo byte + bne NXSP_EXIT ; no change then + inc SPCH ; next page + lda SPCH ; so get page + cmp #>PRGLBL ; have we reached end of line? + bne NXSP_EXIT ; we be okay + lda SPCBNK ; get bank + bne NXSP1 ; must go to Part 3 + inc SPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta SPCH ; and point to it + rts ; and all done +NXSP1: + lda #Z3PAGE ; get start of page 3 + sta SPCH ; and point there + lda #P3BANK ; and point to this bank + sta SPCBNK ; okey +NXSP_EXIT: + rts +; +; NEXTFPC - inc DPCL and check for wrapping round to next bank +; +NEXTFPC: + inc FPCL ; next lo byte + bne NXFP_EXIT ; no change then + inc FPCH ; next page + lda FPCH ; and get it for checking + cmp #>PRGLBL ; have we reached end of line? + bne NXFP_EXIT ; we be okay + lda FPCBNK ; get bank + bne NXFP1 ; must skip over stuff in middle + inc FPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta FPCH ; and point to it + rts ; toots finis +NXFP1: + lda #Z3PAGE ; start of part 3 + sta FPCH ; so show me + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey +NXFP_EXIT: + rts +; +; ADDFPC - add amount in [A] to current FPC and check for bank wrap +; +ADDFPC: + clc ; get ready for add + adc FPCL ; add lo part + sta FPCL ; and save it + bcc AFPX ; all done if no page wrap + inc FPCH ; point to next page + lda FPCH ; get it for compare + cmp #>PRGLBL ; at end of line in main bank? + bne AFPX ; nope, all done then + lda FPCBNK ; get bank + beq AFP1 ; it is main, so we be ok + lda #Z3PAGE ; must go to part 3 if in aux mem + sta FPCH ; thanx + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey + rts ; done +AFP1: + inc FPCBNK ; point to aux + lda #Z2PAGE ; get start in aux + sta FPCH ; and save it +AFPX: + rts +; +; ADDSPC - add amount in [A] to current SPC and check for bank wrap +; +ADDSPC: + clc ; get ready for add + adc SPCL ; add lo part + sta SPCL ; and save it + bcc ASPX ; all done if no page wrap + inc SPCH ; point to next page + lda SPCH ; get it for compare + cmp #>PRGLBL ; at end of line in main bank? + bne ASPX ; nope, all done then + lda SPCBNK ; get bank + beq ASP1 ; it is main, so we be ok + lda #Z3PAGE ; must go to part 3 if in aux mem + sta SPCH ; thanx + lda #P3BANK ; and point to this bank + sta SPCBNK ; okey + rts ; done +ASP1: + inc SPCBNK ; point to aux + lda #Z2PAGE ; get start in aux + sta SPCH ; and save it +ASPX: + rts +; +; PREVFPC - DEC FPCL and check for wrapping round to next bank +; +PREVFPC: + lda FPCL ; get lo part + bne PFPC2 ; it's not zero, so no wrapping + lda FPCH ; get current page + cmp #Z2PAGE ; have we reached beginning of page 2? + beq PFPC1 ; wrap to first bank + cmp #Z3PAGE ; beginning of part 3? + beq PFPC3 ; ayyup + dec FPCH ; point to previous page + bne PFPC2 ; okay +PFPC1: + lda FPCBNK ; get bank + beq VF1ERR ; oops, can't go backwards from main bank + lda #MAIN ; so point to main bank + beq PFPC4 ; and store it away +PFPC3: + lda #AUX ; and point to this bank +PFPC4: + sta FPCBNK ; okey + lda #(>PRGLBL)-1 ; get me last page in part 2 + sta FPCH ; and show me +PFPC2: + dec FPCL ; and point to previous byte + rts +VF1ERR: +; +; out of range +; + lda #19 + jmp ZERROR +; +; PREVSPC - DEC SPCL and check for wrapping round to main bank +; +PREVSPC: + lda SPCL ; get lo part + bne PSPC2 ; it's not zero, so no wrapping + lda SPCH ; get current page + cmp #Z2PAGE ; have we reached beginning of page 2? + beq PSPC1 ; wrap to first bank + cmp #Z3PAGE ; down past page 3? + beq PSPC3 ; sure is + dec SPCH ; point to previous page + bne PSPC2 ; okay +PSPC1: + lda SPCBNK ; get bank + beq VF1ERR ; oops, can't go backwards from main bank + lda #MAIN ; so point to main bank + beq PSPC4 ; so save it +PSPC3: + lda #AUX ; and point to this bank +PSPC4: + sta FPCBNK ; okey + lda #>PRGLBL-1 ; get me last page in low part + sta SPCH ; and show me +PSPC2: + dec SPCL ; and point to previous byte + rts +; +; FP2SP - copy the 3 parts of FPC to SPC +; +FP2SP: + lda FPCBNK + sta SPCBNK + lda FPCH + sta SPCH + lda FPCL + sta SPCL + rts + +; MAKE [MPCPNT],[MPCBNK] POINT TO +; THE RAM PAGE AND BANK THAT HOLDS +; THE V-PAGE MPCH,M +; +VLDMPC: + lda MPCH ; check hi part + bne VLD3 ; NOT IN FIRST V-64K, so must be paged + lda MPCM ; check to see if it is paged + jsr CHECKPRE ; is it preloaded? + bcs VLD3 ; no, so it be paged + jsr SETPC ; so put page/bank into A/Y + sty MPCBNK + sta MPCPNT+HI +NOMUCK: + rts +; +; must be paged, so check for it or read it in +; +VLD3: + lda MPCH + ldy MPCM + jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + clc + adc #>PBEGIN + sta MPCPNT+HI + ldy #PB_BANK ; paging buffers are in aux mem + sty MPCBNK +; +; TEST FOR MUCK +; + lda MUCKFLG + beq NOMUCK + bne VLDZPC ;MAY HAVE MUCKED ZPC SO GO FIX +; +; SAME IDEA AS VLDMPC +; +VLDZPC: + lda INFODOS ; check first for InfoDOS page + beq VLDZ1 ; none + jsr INFO_PAGE ; well, is it? + bcc VLDZ1 ; nope + rts ; all set otherwise +VLDZ1: + lda ZPCH + bne VLDZ3 ;NOT IN FIRST V-64K, so must be paged + lda ZPCM ; check to see if it is paged + jsr CHECKPRE ; is it preloaded? + bcs VLDZ3 ; no, so it must be paged + jsr SETPC ; point to correct bank and page + sty ZPCBNK ; set bank + sta ZPCPNT+HI ; and MSB of pointer +NOZMUCK: + rts +VLDZ3: ;MUST BE PAGED + lda ZPCH + ldy ZPCM + jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + clc + adc #>PBEGIN + sta ZPCPNT+HI + ldy #PB_BANK + sty ZPCBNK +; +; TEST MUCKING +; + lda MUCKFLG + beq NOZMUCK + jmp VLDMPC ;MAY HAVE MUCKED MPC SO GO FIX + + +; FIND V-PAGE A,Y IF IT IS IN MEM +; AND RETURN WITH LINKED LIST +; PROPERLY MAINTAINED +; IF V-PAGE A,Y NOT IN MEM +; GET FROM DISK AND PUT IN RIGHT +; PLACE + +MUCKFLG: DB 00 ;00 IF PAGING BUFFERS NOT MUCKED + +PAGE: + sta WANTED+HI + sty WANTED+LO + ldx #0 + stx MUCKFLG ; CLEAR MUCK FLAG + jsr WHERE + bcc TOUGH ; PAGE IS RESIDENT IN PAGING SPACE +; +; PAGE MUST BE BROUGHT IN FROM DISK +; + ldx CURRENT ;GET BUFFER TO PUT PAGE INTO + lda NEXTPNT,X ;BY LOOKING AT NEXT POINTER + sta CURRENT ;MAKE IT THE CURRENT BUFFER + tax + lda WANTED+HI ;LET BUFFER MAP KNOW + sta VPAGEH,X ;WHICH PAGE + lda WANTED+LO ;IS GOING TO + and #$FE ; make address be even + sta VPAGEL,X ;BE THERE +;*** +; point to the next page too +; + ora #1 ; add one to point to next 256 byte page + pha ; save it + txa ; get pointer + tay ; into y + iny ; point to next buffer + pla ; get second buffer back + sta VPAGEL,Y ; so point to it + lda VPAGEH,X ; get MSB + sta VPAGEH,Y ; and save it +; +; A = WANTED+HI +; Y = WANTED+LO +; X = BUFFER +; + lda WANTED+LO + and #$FE ; clear low bit to make it even + tay ; want it in y +;*** + lda WANTED+HI + ldx CURRENT + jsr GETVPAGE ; PUT V-PAGE A,Y INTO PAGING BUFFER X +;*** + dec MUCKFLG ; INDICATE A MUCKING + bne PAGEXIT ; and return current buffer +TOUGH: + and #$FE ; make even page, please + sta NEXT + cmp CURRENT ; GETS REALY SCREWED IF CURRENT==NEXT + beq PAGEXIT ; DO NOT CHANGE POINTERS IF IT DOES +; +; Y=NEXT(CURRENT) +; DO THE RIGHT THING TO THE POINTERS +; +; ldy CURRENT +; lda NEXTPNT,Y +; sta NSUBCUR + lda NEXT + jsr DETATCH + ldy CURRENT + lda NEXT + jsr INSERT + lda NEXT + sta CURRENT +PAGEXIT: +;*** perhaps add one to point to correct buffer + lda WANTED+LO ; get LSB + and #$01 ; pick up even/odd bit + clc ; doing add + adc CURRENT ; point to correct buffer + rts + +GETVPAGE: + sta DBLOCK+HI + sty DBLOCK+LO + txa ; get which paging buffer + clc + adc #>PBEGIN ; and set up abs addr + sta DBUFF+HI ; thank you, that's much better + ldx #PB_BANK + stx DSKBNK + jmp GETDSK + +; INSERT A AFTER Y +; A.next = Y.next +; Y.next = A +; A.previous = Y +; [Y.next].previous = A +INSERT: + tax + lda NEXTPNT,Y ; Y.next + sta NEXTPNT,X ; A.next = Y.next + pha ; save Y.next for later + txa + sta NEXTPNT,Y ; Y.next = A + tya + sta PREVPNT,X ; A.prev = Y + pla ; get Y.next back + tay ; [Y.next].previous + txa + sta PREVPNT,Y ; [Y.next].previous = A + rts + + IF 0 +; +; old one, which puts A AFTER! Y +; +; PREV(A)=Y +; PREV(NEXT(Y))=A +; NEXT(A)=NEXT(Y) +; NEXT(Y)=A + + sta ATEMP + sty YTEMP + tax + tya + sta PREVPNT,X + + lda NEXTPNT,Y + sta NSUBY + txa + ldx NSUBY + sta PREVPNT,X + + txa + ldx ATEMP + sta NEXTPNT,X + + lda ATEMP + sta NEXTPNT,Y + rts + ENDIF + +; DETATCH BUFFER >A< +; NEXT(PREV(A))=NEXT(A) +; PREV(NEXT(A))=PREV(A) + +DETATCH: + tax + lda NEXTPNT,X + tay ; Y == A.next + lda PREVPNT,X ; get A.previous + tax ; X == A.previous + tya ; get A.next + sta NEXTPNT,X ; [A.previous].next = A.next + txa ; get A.previous + sta PREVPNT,Y ; [A.next].previous = A.previous + rts + + +; RETURN BUFFER OF PAGE [WANTED] +; IN >A< ELSE SEC (Y=WANTED+LO) + +WHERE: LDX #NUMBUFS-1 +WHLOOP: + LDA WANTED+HI + CMP VPAGEH,X ;>SAME + BEQ WHGOT +WHNOGOT: + DEX + BPL WHLOOP + SEC + RTS +WHGOT: + TYA + CMP VPAGEL,X + BNE WHNOGOT + TXA + CLC + RTS +; +; CHECKPRE - check to see if page in [A] is in preloaded +; +CHECKPRE: + cmp TBLPUR ; check against PURE tables + bcc CHKPEXY ; must be preloaded then +CHKP1: + cmp FUNPRE ; is it in function preload? + bcc CHKPEXN ; preloaded function > desired, not preloaded + cmp FUNPUR ; how bout at end? + bcs CHKPEXN ; it is not preloaded +CHKP3: + clc ; doing add + adc FUNPGE ; get me memory page for function +CHKPEXY: + clc ; show it is preloaded + rts ; then we got it +CHKPEXN: + sec ; show it ain't here + rts +; +; INFO_PAGE - is it one of the special preloaded pages for infoDOS? If it +; is, then set up ZPCPNTR to point to it, and set carry. Otherwise, +; clear carry to show it ain't. +IPAGE: ds 2 +INFO_PAGE: + lda ZPCH ; get 2 parts + sta IPAGE+HI + lda ZPCM + sta IPAGE+LO + lsr IPAGE+HI ; /2 to get 512 block + ror IPAGE+LO + ldy #SGTSEG ; point to first segment, MSB + lda (INFODOS),Y ; howzit look? + iny ; point to LSB + cmp IPAGE+HI + bcc INFP1 ; might be interesting + bne INFPNX ; not here, < than minimum + lda (INFODOS),Y ; how bout LSB + cmp IPAGE+LO + beq INFPYX ; found it + bcs INFPNX ; nope, < than minimum again +; +; here, it's at least > than minimum +; +INFP1: +; iny ; point at end block, MSB + lda INFODOS_END+HI ; howz end segment look + cmp IPAGE+HI + bcc INFPNX ; nope, > than maximum of special + bne INFPYX ; yup, < than maximum of special +; iny ; LSB of last one + lda INFODOS_END+LO ; is LSB < special? + cmp IPAGE+LO ; MSB of current one == MSB of special + bcc INFPNX ; nope, not here +INFPYX: + ldy #SGTSEG+1 ; point back to start block, LSB + lda (INFODOS),Y ; get start block + asl A ; *2 to get start page + sta IPAGE+LO ; save it + lda ZPCM + sec ; doing sub + sbc IPAGE+LO ; get offset into special block + clc ; now add in offset + adc #>SP_START ; get the start of special area + sta ZPCPNT+HI ; show ZPCPNTR + lda #SP_BANK ; which bank + sta ZPCBNK ; okey + sec ; show it was here + rts +INFPNX: + clc ; show not here + rts ; g'day + + + +CHKPEXN0: + +GETBYT: + ldy MPCL + jsr MFETCH ; go and get it + inc MPCL ;POINT TO NEXT BYTE + bne GETGOT ;IF NO CROSS WE ARE STILL VALID + inc MPCM + bne GET1 + inc MPCH +GET1: + pha ; save byte + jsr VLDMPC + pla ; and get it back +GETGOT: + tay ;SET FLAGS + rts ;RED SLIPPER TIME +; +; NEXTPC - Fetch the byte at the current ZPC, point to next byte and +; validate pointer +; +NEXTPC: + ldy ZPCL ; get low pointer + jsr ZFETCH ; fetch @ZPCPNT + inc ZPCL + bne NXTGOT + inc ZPCM + bne CRSZ1 + inc ZPCH +CRSZ1: + pha ; save opcode + jsr VLDZPC + pla ; and get it back +NXTGOT: + tay + rts + +; +; STASHB - use SPC to save a byte in either aux or main mem +; +STASHB: + ldy SPCBNK ; get the bank + bmi SB1 ; must be in upper RAM + sta WRTBNK,Y ; set bank + ldy #0 ; can only do this with Y + sta (SPC),Y ; get the sucker + beq SBEXI ; jump to end it +; +; this is in aux mem, >$E000 +; +SB1: + ldy SPCH ; get high part + sty SBMOD+2 ; and self mod my code + ldy SPCL ; and get the low part + sta ALTZP+AUX ; talk about aux mem +SBMOD: + sta Z3BEGIN,Y ; store the little byte + sta ALTZP+MAIN ; go back to main mem +SBEXI: + sta WRTBNK+MAIN ; and write to main + rts +; +; FETCHB - fetch a byte from either main memory, aux memory, or upper +; Aux memory +; +FETCHB: + ldy FPCBNK ; get the bank + bmi FB1 ; must be in upper RAM + jsr ZERO_FB ; go to low end fetch + rts +; +; this is in aux mem, >$E000 +; +FB1: + lda FPCH ; get which page + sta FBMOD+2 ; and show in operand + ldy FPCL ; get which byte + sta ALTZP+AUX ; talk about aux mem +FBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + tay ; set condition code + rts +; +; ZFETCH - after checking for which bank (main, aux 1 or aux 2), go get +; the byte @ ZPCPNT, with the offset being in [Y] +; +ZFETCH: + ldx ZPCBNK ; get the bank + bmi ZFB1 ; must be in upper RAM + jsr ZERO_ZF ; go to low end fetch + rts +; +; this is in aux mem, >$D000 +; +ZFB1: + lda ZPNTH ; which page are we talking about + sta ZBMOD+2 ; show in the operand + sta ALTZP+AUX ; talk about aux mem +ZBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + tax ; set condition code + rts +; +; MFETCH - after checking for which bank (main, aux 1 or aux 2), go get +; the byte @MPCPNT, with the offset being in [Y] +; +MFETCH: + ldx MPCBNK ; get the bank + bmi MB1 ; must be in upper RAM + jsr ZERO_MF ; go to low end fetch + rts +; +; this is in aux mem, >$D000 +; +MB1: + lda MPNTH ; which page are we talking about + sta MBMOD+2 ; show in the operand + sta ALTZP+AUX ; talk about aux mem + +MBMOD: lda Z3BEGIN,Y ; get the sucker + + sta ALTZP+MAIN ; go back to main mem + tax ; set condition code + rts + + + END diff --git a/apple/yzip/rel.13/yzip.asm b/apple/yzip/rel.13/yzip.asm new file mode 100644 index 0000000..40cef6e --- /dev/null +++ b/apple/yzip/rel.13/yzip.asm @@ -0,0 +1,86 @@ + ; -------------------------- + ; YZIP + ; Z-CODE INTERPRETER PROGRAM + ; FOR APPLE ][e/][c/][gs + ; -------------------------- + + ; INFOCOM, INC. + ; 125 CAMBRIDGEPARK DRIVE + ; CAMBRIDGE, MA 02140 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + + PL 50000 ; PAGE LENGTH OF PRINTER + +DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER (1 = YES) +CHECKSUM EQU 0 ; == 1 for generating save/restore checksum + + ; ----------- + ; 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 -- IMPURE CODE TOO LARGE (BM 1/20/86) + ; 14 -- DRIVE ACCESS + ; 15 -- NOT AN EZIP GAME + ; 16 -- ILLEGAL EXTENDED RANGE X-OP + ; 17 -- BAD VIRTUAL PAGE + ; 18 -- SETPC NOT PRELOADED + ; 19 -- PREVIOUS (SPC/FPC) NOT POSSIBLE + ; 20 -- PICTURE NOT FOUND + ; 21 -- ZERO OBJECT TO BE REMOVED + ; 22 -- OBJECT TOO BIG (ZLOC) + ; 23 -- Bad read: Read != Asked for + ; 24 -- Bad read: Retry 1 != Retry 2 + ; 25 -- Clear of zero height/width window + + TITLE "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + INCLUDE ZIP.EQU + INCLUDE ZERO.EQU + INCLUDE PRODOS.EQU + INCLUDE APPLE.EQU + INCLUDE MACROS.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + INCLUDE ZBEGIN.ASM + INCLUDE MAIN.ASM + INCLUDE SUBS.ASM + INCLUDE DISPATCH.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + INCLUDE ZDOS.ASM + INCLUDE MACHINE.ASM + INCLUDE IO.ASM + INCLUDE VERIFY.ASM + INCLUDE SCREEN.ASM + INCLUDE TABLES.ASM + INCLUDE WINDOWS.ASM + INCLUDE DLINE.ASM + INCLUDE PIC.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + INCLUDE OPS012.ASM + INCLUDE OPSX.ASM + INCLUDE READ.ASM + INCLUDE ZSAVRES.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + INCLUDE XPAGING.ASM + INCLUDE ZSTRING.ASM + INCLUDE OBJECTS.ASM + + BLKB ZBEGIN-$,0 + END + diff --git a/apple/yzip/rel.13/yzip.bin b/apple/yzip/rel.13/yzip.bin new file mode 100644 index 0000000..5a24659 Binary files /dev/null and b/apple/yzip/rel.13/yzip.bin differ diff --git a/apple/yzip/rel.13/yzip.lst b/apple/yzip/rel.13/yzip.lst new file mode 100644 index 0000000..ecaeb8a --- /dev/null +++ b/apple/yzip/rel.13/yzip.lst @@ -0,0 +1,15767 @@ + Wed Jun 7 1989 12:04 Page 1 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + + + + + 2500 A.D. 6502 Macro Assembler - Version 4.01a + ------------------------------------------------ + + Input Filename : YZIP.asm + Output Filename : YZIP.obj + + + 1 ; -------------------------- + 2 ; YZIP + 3 ; Z-CODE INTERPRETER PROGRAM + 4 ; FOR APPLE ][e/][c/][gs + 5 ; -------------------------- + 6 + 7 ; INFOCOM, INC. + 8 ; 125 CAMBRIDGEPARK DRIVE + 9 ; CAMBRIDGE, MA 02140 + 10 + 11 ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + 12 + 13 PL 50000 ; PAGE LENGTH OF PRINTER + 14 + 15 0000 DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER (1 = YES) + 16 0000 CHECKSUM EQU 0 ; == 1 for generating save/restore checksum + 17 + 18 ; ----------- + 19 ; ERROR CODES + 20 ; ----------- + 21 + 22 ; 00 -- INSUFFICIENT RAM + 23 ; 01 -- ILLEGAL X-OP + 24 ; 02 -- ILLEGAL 0-OP + 25 ; 03 -- ILLEGAL 1-OP + 26 ; 04 -- ILLEGAL 2-OP + 27 ; 05 -- Z-STACK UNDERFLOW + 28 ; 06 -- Z-STACK OVERFLOW + 29 ; 07 -- ILLEGAL PROPERTY LENGTH (GETP) + 30 ; 08 -- DIVISION BY ZERO + 31 ; 09 -- ILLEGAL ARGUMENT COUNT (EQUAL?) + 32 ; 10 -- ILLEGAL PROPERTY ID (PUTP) + 33 ; 11 -- ILLEGAL PROPERTY LENGTH (PUTP) + 34 ; 12 -- DISK ADDRESS OUT OF RANGE + 35 ; 13 -- IMPURE CODE TOO LARGE (BM 1/20/86) + 36 ; 14 -- DRIVE ACCESS + 37 ; 15 -- NOT AN EZIP GAME + 38 ; 16 -- ILLEGAL EXTENDED RANGE X-OP + 39 ; 17 -- BAD VIRTUAL PAGE + 40 ; 18 -- SETPC NOT PRELOADED + 41 ; 19 -- PREVIOUS (SPC/FPC) NOT POSSIBLE + 42 ; 20 -- PICTURE NOT FOUND + 43 ; 21 -- ZERO OBJECT TO BE REMOVED + 44 ; 22 -- OBJECT TOO BIG (ZLOC) + 45 ; 23 -- Bad read: Read != Asked for + 46 ; 24 -- Bad read: Retry 1 != Retry 2 + 47 ; 25 -- Clear of zero height/width window + 48 0000 + 49 0000 TITLE "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + 50 0000 INCLUDE ZIP.EQU + 51 0000 STTL "--- YZIP EQUATES ---" + 52 PAGE + Wed Jun 7 1989 12:04 Page 2 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- YZIP EQUATES ---" + + 53 + 54 000D VERSID EQU 13 ; VERSION OF INTERPRETER + 55 ; See file "versions" for complete descriptions + 56 + 57 00FF TRUE EQU $FF + 58 0000 FALSE EQU 0 + 59 + 60 ; --------------------- + 61 ; Segment table equates + 62 ; --------------------- + 63 0000 SGTDISKS EQU 0 ; number of disks + 64 0002 SGTPAD EQU SGTDISKS+2 ; just some extra room + 65 0012 SGTCHKS1 EQU SGTPAD+16 ; Checksum for disk 1 (PRELOAD) + 66 0014 SGTPICOF1 EQU SGTCHKS1+2 ; N/A + 67 0016 SGTSEG1 EQU SGTPICOF1+2 ; # of segments + 68 0018 SGTGPOF1 EQU SGTSEG1+2 ; Global Picture Directory + 69 001A SGTTBLS EQU SGTGPOF1+2 ; Start of table preload (should be 0) + 70 001C SGTTBLE EQU SGTTBLS+2 ; Last page of table preload + 71 001E SGTTBLX EQU SGTTBLE+2 ; N/A + 72 0020 SGTFUNS EQU SGTTBLX+2 ; First page of function preload + 73 0022 SGTFUNE EQU SGTFUNS+2 ; End page of function preload + 74 0024 SGTFUNX EQU SGTFUNE+2 ; N/A + 75 0026 SGTDSK EQU SGTFUNX+2 ; Actual start of disk segment tables + 76 + 77 0000 SGTCHKS EQU 0 ; check sum for file + 78 0002 SGTPICOF EQU 2 ; picture data offset + 79 0004 SGTNSEG EQU 4 ; # of segments in this list + 80 0006 SGTGPOF EQU 6 ; Global Directory Offset + 81 0008 SGTSEG EQU 8 ; start of segments + 82 ; --------------------- + 83 ; Z-CODE HEADER OFFSETS + 84 ; --------------------- + 85 + 86 0000 ZVERS EQU 0 ; VERSION BYTE + 87 0001 ZMODE EQU 1 ; MODE SELECT BYTE + 88 0002 ZID EQU 2 ; GAME ID WORD + 89 0004 ZENDLD EQU 4 ; # OF QUADWORDS ON SIDE 1 OF DISK + 90 0006 ZGO EQU 6 ; EXECUTION ADDRESS + 91 0008 ZVOCAB EQU 8 ; START OF VOCABULARY TABLE + 92 000A ZOBJEC EQU 10 ; START OF OBJECT TABLE + 93 000C ZGLOBAL EQU 12 ; START OF GLOBAL VARIABLE TABLE + 94 000E ZPURBT EQU 14 ; START OF "PURE" Z-CODE + 95 0010 ZFLAGS EQU 16 ; FLAG WORD + 96 0012 ZSERIA EQU 18 ; 3-WORD SERIAL NUMBER + 97 0018 ZFWORD EQU 24 ; START OF FWORDS TABLE + 98 001A ZLENTH EQU 26 ; LENGTH OF Z-PROGRAM IN WORDS + 99 001C ZCHKSM EQU 28 ; Z-CODE CHECKSUM WORD + 100 001E ZINTWD EQU 30 ; INTERPRETER ID WORD (SUPPLIED BY EZIP) + 101 0020 ZSCRWD EQU 32 ; SCREEN PARAMETER WORD ( " " " ) + 102 0022 ZHWRD EQU 34 ; DISPLAY WIDTH IN PIXELS + 103 0024 ZVWRD EQU 36 ; DISPLAY HEIGHT IN PIXELS + 104 0026 ZFWRD EQU 38 ; FONT HEIGHT, FONT WIDTH + 105 0028 ZFOFF EQU 40 ; FUNCTION OFFSET + 106 002A ZSOFF EQU 42 ; STRING OFFSET + 107 002C ZCLRWD EQU 44 ; FORGROUND COLOR, BACKGROUND COLOR + 108 002E ZTCHAR EQU 46 ; POINTER TO TBL OF TERMINATING CHARS + 109 0030 ZTWIDTH EQU 48 ; Running counter for table output char width + 110 0032 ZCRFUNC EQU 50 ; FUNCTION FOR CARRIAGE RETURNS + 111 0034 ZCHRSET EQU 52 ; POINTER TO CHAR SET TBL + 112 0036 ZEXTAB EQU 54 ; Points to extension table, if needed + 113 ; + 114 ; Extension table offsets + 115 ; + 116 0000 ZEXTLEN EQU 0 ; Length of extension table + 117 0002 ZMSLOCX EQU 2 ; x location of mouse + 118 0004 ZMSLOCY EQU 4 ; y location of mouse + 119 0006 ZMSETBL EQU 6 ; MOUSE TBL CHANGE WORD + 120 0008 ZMSEDIR EQU 8 ; DIRECTION MENU + 121 000A ZMSEINV EQU 10 ; INVENTORY MENU + 122 000C ZMSEVRB EQU 12 ; FREQUENT VERB MENU + 123 000E ZMSEWRD EQU 14 ; FREQUENT WORD MENU + 124 0010 ZBUTTN EQU 16 ; BUTTON HANDLER + 125 0012 ZJOYST EQU 18 ; JOYSTICK HANDLER + 126 0014 ZBSTAT EQU 20 ; BUTTON STATUS + 127 0016 ZJSTAT EQU 22 ; JOYSTICK STATUS + Wed Jun 7 1989 12:04 Page 3 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- YZIP EQUATES ---" + + 128 ; + 129 ; ZFLAGS values + 130 ; + 131 0001 FSCRI EQU $01 ; scripting? + 132 0002 FMONO EQU $02 ; mono spaced font? + 133 0004 FSTAT EQU $04 ; status line refresh? + 134 0008 FDISP EQU $08 ; uses DISPLAY operations? + 135 0010 FUNDO EQU $10 ; uses UNDO? + 136 0020 FMOUS EQU $20 ; uses mouse? + 137 0040 FCOLO EQU $40 ; uses color? + 138 0080 FMENU EQU $80 ; uses menus? + 139 ;--------------- + 140 ; Picture data + 141 ;--------------- + 142 ;=== DATA HEADER === + 143 0000 PHFID EQU 0 ; File ID + 144 0001 PHFLG EQU PHFID+1 ; Flags + 145 0002 PHHUFF EQU PHFLG+1 ; Pointer to Huffman data + 146 0004 PHNLD EQU PHHUFF+2 ; # entries in local directory + 147 0006 PHNGD EQU PHNLD+2 ; # entries in global directory + 148 0008 PHDSIZE EQU PHNGD+2 ; Local directory entry size + 149 000A PHCHKS EQU PHDSIZE+2 ; File Checksum + 150 000C PHFVERS EQU PHCHKS+2 ; File Version (N/A) + 151 000E PHEXTRA EQU PHFVERS+2 ; Extra room for getting fatter + 152 0010 PHSIZE EQU 16 ; 16 bytes is header size + 153 ;=== DATA HEADER FLAGS === + 154 0001 PHFGD EQU $1 ; data has global directory + 155 0002 PHFHUFF EQU $2 ; Huffman encoded pictures + 156 0004 PHFHUFF1 EQU $4 ; All pictures use same Huff tree + 157 0008 PHFPAL EQU $8 ; No pallette information + 158 ;=== LOCAL DIRECTORY === + 159 0000 PLDID EQU 0 ; Picture ID + 160 0002 PLDWID EQU PLDID+2 ; Picture Width + 161 0003 PLDHGHT EQU PLDWID+1 ; Picture Height + 162 0004 PLDFLG EQU PLDHGHT+1 ; Flags + 163 0005 PLDPTR EQU PLDFLG+1 ; Pointer to picture data + 164 0008 PLDSIZE EQU PLDPTR+3 ; size of local directory entry + 165 + 166 0000 END + 167 + 168 0000 INCLUDE ZERO.EQU + 169 0000 STTL "--- ZERO PAGE VARIABLES ---" + 170 PAGE + Wed Jun 7 1989 12:04 Page 4 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ZERO PAGE VARIABLES ---" + + 171 + 172 0000 SCRCX EQU 0 ; CURSOR HORIZONTAL + 173 0001 SCRCY EQU SCRCX+1 ; CURSOR VERTICAL + 174 0002 SCRBTM EQU SCRCY+1 ; first line outside current window + 175 0003 MAXLINES EQU SCRBTM+1 ; maximum number of lines in window + 176 0004 LEFTMRG EQU MAXLINES+1 ; left edge + left margin in current window + 177 0005 WINDOW EQU LEFTMRG+1 ; (WORD) address of current window structure + 178 0007 LINE_X EQU WINDOW+2 ; (WORD) width of line counter + 179 0009 CC_OFF EQU LINE_X+2 ; save offset for char drawing + 180 000A CLSLEFT EQU CC_OFF+1 ; screen limits for CLS code + 181 000B CLSTOP EQU CLSLEFT+1 ; top of screen + 182 000C CLSWIDTH EQU CLSTOP+1 ; # of columns + 183 000D CLSHEIGHT EQU CLSWIDTH+1 ; # of lines + 184 ; + 185 ; some variables for all the screen positioning code + 186 ; + 187 000E NY_DATA EQU CLSHEIGHT+1 ; place for GET/PUT_NYBBLE to use + 188 000F CH_OFFSET EQU NY_DATA+1 ; offset into char data table + 189 0010 DATALOOP EQU CH_OFFSET+1 ; loop counter for byte works + 190 0011 BITOFF EQU DATALOOP+1 ; bit offset into screen byte + 191 0012 CH_DATA EQU BITOFF+1 ; actual char data being worked on + 192 0013 SCR_DATA EQU CH_DATA+1 ; screen byte being worked on + 193 0014 SH_LOOP EQU SCR_DATA+1 ; loop counter for bit shifting + 194 0015 SCROLLY EQU SH_LOOP+1 ; save spot for y pos when scrolling + 195 0016 RETRIES EQU SCROLLY+1 ; (BYTE) Machine ID + 196 0017 CHRMAX EQU RETRIES+1 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD + 197 0018 SCLLINES EQU CHRMAX+1 ; (BYTE) how many lines to scroll + 198 0019 FMTTBL EQU SCLLINES+1 ; (BYTE) flag to show formatted table output + 199 001A STMASK EQU FMTTBL+1 ; (BYTE) Mask to use on first byte of CLS + 200 001B ENDMASK EQU STMASK+1 ; (BYTE) Mask to use on last byte of CLS + 201 001C CHPTR EQU ENDMASK+1 ; (WORD) pointer to char data + 202 001C SCOFF EQU CHPTR ;(BYTE) Offset used by scroll + 203 001D SCLDIR EQU CHPTR+1 ;(BYTE) Direction of scroll - >0 up, <0 down + 204 001E DSEGS EQU CHPTR+2 ; (WORD) Pointer to current disk's segments + 205 ;WIDE_FLAG EQU SCOFF+1 ; (BYTE) <> 0 if 16 bytes in char data + 206 ;DSEGS EQU WIDE_FLAG+1 ; (WORD) Pointer to current disk's segments + 207 0020 LASTWV EQU DSEGS+2 ; last of the WINDOW variables + 208 + 209 0050 ZEROPG EQU $50 ; FIRST FREE Z-PAGE LOCATION + 210 ; + 211 ; these are first, cuz ZBOOT inits them so we don't want to clear them + 212 ; at ZBEGIN warm start + 213 ; + 214 0050 GLOBAL EQU ZEROPG ; (Relative Addr.) GLOBAL VARIABLE POINTER + 215 0052 VOCAB EQU GLOBAL+2 ; (ADDRESS) Vocab table pointer + 216 0055 FWORDS EQU VOCAB+3 ; (ADDRESS) F-WORDS TABLE POINTER + 217 0058 MOUSEF EQU FWORDS+3 ; (BYTE) ==-1/1 if we have mouse/joystick + 218 0059 INFODOS EQU MOUSEF+1 ; (WORD) if <>0, then pointer to D2SEG + 219 005B FUNOFF EQU INFODOS+2 ; (ADDRESS) Function Offset (ZFOFF*8) + 220 005B FOFFH EQU FUNOFF ; (BYTE) Hi part + 221 005C FOFFM EQU FUNOFF+1 ; (BYTE) Middle part + 222 005D FOFFL EQU FUNOFF+2 ; (BYTE) Lo part + 223 005E STROFF EQU FUNOFF+3 ; (ADDRESS) String Offset (ZSOFF*8) + 224 005E SOFFH EQU STROFF ; (BYTE) Hi part + 225 005F SOFFM EQU STROFF+1 ; (BYTE) Middle part + 226 0060 SOFFL EQU STROFF+2 ; (BYTE) Lo part + 227 ; + 228 ; Beginning of warm start zeroing + 229 ; + 230 0061 OPCODE EQU STROFF+3 ; (BYTE) CURRENT OPCODE + 231 0062 NARGS EQU OPCODE+1 ; (BYTE) # ARGUMENTS + 232 0063 ARG1 EQU OPCODE+2 ; (WORD) ARGUMENT #1 + 233 0065 ARG2 EQU OPCODE+4 ; (WORD) ARGUMENT #2 + 234 0067 ARG3 EQU OPCODE+6 ; (WORD) ARGUMENT #3 + 235 0069 ARG4 EQU OPCODE+8 ; (WORD) ARGUMENT #4 + 236 006B ARG5 EQU OPCODE+10 ; (WORD) + 237 006D ARG6 EQU OPCODE+12 ; (WORD) + 238 006F ARG7 EQU OPCODE+14 ; (WORD) + 239 0071 ARG8 EQU OPCODE+16 ; (WORD) + 240 0073 ABYTE EQU OPCODE+18 ; (BYTE) X-OP ARGUMENT BYTE + 241 0074 BBYTE EQU OPCODE+19 ; (BYTE) XCALL ARG BYTE (EZIP) + 242 0075 ADEX EQU OPCODE+20 ; (BYTE) X-OP ARGUMENT INDEX + 243 0076 VALUE EQU OPCODE+21 ; (WORD) VALUE RETURN REGISTER + 244 0078 I EQU VALUE+2 ; (WORD) GEN-PURPOSE REGISTER #1 + 245 007A J EQU VALUE+4 ; (WORD) GEN-PURPOSE REGISTER #2 + Wed Jun 7 1989 12:04 Page 5 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ZERO PAGE VARIABLES ---" + + 246 007C K EQU VALUE+6 ; (WORD) GEN-PURPOSE REGISTER #3 + 247 007E L EQU VALUE+8 ; (WORD) GEN-PURPOSE REGISTER #4 + 248 0080 ZPC EQU VALUE+10 ; (3 BYTES) ZIP PROGRAM COUNTER + 249 0080 ZPCL EQU ZPC ; (BYTE) <8 BITS OF [ZPC] + 250 0081 ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] + 251 0082 ZPCH EQU ZPC+2 ; (BYTE) >BIT OF [ZPC] + 252 0083 ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE + 253 0083 ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 254 0084 ZPNTH EQU ZPCPNT+1 ; (BYTE) + 255 0085 ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 256 0086 MPC EQU ZPCPNT+3 ; (3 BYTES) MEMORY PROGRAM COUNTER + 257 0086 MPCL EQU MPC ; (BYTE) <8 BITS OF [MPC] + 258 0087 MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] + 259 0088 MPCH EQU MPC+2 ; (BYTE) >BIT OF [MPC] + 260 0089 MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE + 261 0089 MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 262 008A MPNTH EQU MPCPNT+1 ; (BYTE) + 263 008B MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 264 008C FPC EQU MPCBNK+1 ; (3 Bytes) Fetch pointer + 265 008C FPCL EQU FPC ; (BYTE) Low part + 266 008D FPCH EQU FPCL+1 ; (BYTE) High Part + 267 008E FPCBNK EQU FPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 268 008F SPC EQU FPCBNK+1 ; (3 Bytes) Fetch pointer + 269 008F SPCL EQU SPC ; (BYTE) Low part + 270 0090 SPCH EQU SPCL+1 ; (BYTE) High Part + 271 0091 SPCBNK EQU SPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 272 + 273 ; Z-STRING MANIPULATION VARIABLES + 274 + 275 0092 LINLEN EQU SPCBNK+1 ; (BYTE) LENGTH OF CURRENT LINE + 276 0093 SOURCE EQU LINLEN+1 ; (BYTE) counter for read + 277 0094 WRDLEN EQU SOURCE+1 ; (BYTE) LENGTH OF CURRENT WORD + 278 0095 ESIZE EQU WRDLEN+1 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES + 279 0096 PSET EQU ESIZE+1 ; (BYTE) PERMANENT CHARSET + 280 0097 TSET EQU PSET+1 ; (BYTE) TEMPORARY CHARSET + 281 0098 ZCHAR EQU TSET+1 ; (BYTE) CURRENT Z-CHAR + 282 0099 OFFSET EQU ZCHAR+1 ; (BYTE) F-WORD TABLE OFFSET + 283 009A ZFLAG EQU OFFSET+1 ; (BYTE) Z-WORD ACCESS FLAG + 284 009B ZWORD EQU ZFLAG+1 ; (WORD) CURRENT Z-WORD + 285 009D CONCNT EQU ZWORD+2 ; (BYTE) Z-STRING SOURCE COUNTER + 286 009E CONIN EQU CONCNT+1 ; (BYTE) CONVERSION SOURCE INDEX + 287 009F CONOUT EQU CONIN+1 ; (BYTE) CONVERSION DEST INDEX + 288 00A0 DIRTBL EQU CONOUT+1 ; (WORD) CONTAINS TBLE TO STORE CHARS TO + 289 00A2 XSIZE EQU DIRTBL+2 ; (WORD) SCREEN WIDTH FOR TESTS + 290 00A4 RAND EQU XSIZE+2 ; (WORD) Random number offset + 291 00A6 CURWIN EQU RAND+2 ; (BYTE) WHICH WINDOW TO WRITE IN + 292 00A7 LENGTH EQU CURWIN+1 ; (WORD) CHAR POSITION ON THE SCREEN + 293 00A9 CHRCNT EQU LENGTH+2 ; (BYTE) CHAR POSITION IN [LBUFF] + 294 00AA SCRIPT EQU CHRCNT+1 ; (BYTE) SCRIPT ENABLE FLAG + 295 00AB LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER + 296 00AC IOCHAR EQU LINCNT+1 ; (BYTE) CHARACTER BUFFER + 297 00AD COLORP EQU IOCHAR+1 ; (WORD) Pointer to current background color + 298 00AF ZSP EQU COLORP+2 ; (WORD) Z Stack + 299 00B1 SCREENF EQU ZSP+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT + 300 00B2 TABLEF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT + 301 00B3 VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH + 302 00B6 DBUFF EQU VOCEND+3 ; (WORD) RAM PG TO ACCESS (LSB = 0) + 303 00B8 DSKBNK EQU DBUFF+2 ; (BYTE) MAIN/AUX bank + 304 00B9 ALLFLG EQU DSKBNK+1 ; (BYTE) IF =1 ALL FCN KEYS (>127) ARE TCHARS + 305 00BA UNDFLG EQU ALLFLG+1 ; (BYTE) Underlining flag + 306 00BB INVFLG EQU UNDFLG+1 ; (BYTE) Inverse flag + 307 00BC MEMPAGE EQU INVFLG+1 ; (BYTE) Save spot for XPAGING stuff + 308 00BD CPY_COUNT EQU MEMPAGE+1 ; (BYTE) Number of bytes for copy line + 309 00BE TBLHEIGHT EQU CPY_COUNT+1 ;(BYTE) Number of lines in printing table + 310 00BF TBLWIDTH EQU TBLHEIGHT+1 ;(BYTE) Number of bytes per line + 311 00C0 TBLCNT EQU TBLWIDTH+1 ;(BYTE) Counter for table printing + 312 00C1 FONTFLG EQU TBLCNT+1 ;(BYTE) Which font (!=0 is width) + 313 00C2 TBLPUR EQU FONTFLG+1 ;(BYTE) first pure table page + 314 00C3 FUNPRE EQU TBLPUR+1 ;(BYTE) first preloaded function page + 315 00C4 FUNPUR EQU FUNPRE+1 ;(BYTE) first pure function page + 316 00C5 FUNPGE EQU FUNPUR+1 ;(BYTE) -number to get function preload page + 317 00C6 DELAY_COUNTER EQU FUNPGE+1 ;(BYTE) counter for delay loop + 318 ; + 319 ; some char-to-screen variables + 320 ; + Wed Jun 7 1989 12:04 Page 6 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ZERO PAGE VARIABLES ---" + + 321 00C7 CHAR_D1 EQU DELAY_COUNTER+1 ; (BYTE) character data, part 1 + 322 00C8 CHAR_D2 EQU CHAR_D1+1 ; (BYTE) char data, part 2 + 323 00C9 CW EQU CHAR_D2+1 ; (BYTE) width of the character + 324 00CA CLKCTR EQU CW+1 ; (BYTE) counter for mouse clicking + 325 00CB MSX EQU CLKCTR+1 ; (BYTE) mouse cursor X + 326 00CC MSY EQU MSX+1 ; (BYTE) mouse cursor Y + 327 00CD CURRENT EQU MSY+1 ; (BYTE) current paging bufer + 328 ;CURSOR_OFF EQU CURRENT+1 ; (BYTE) ==1 if "don't show the blinking cursor" + 329 00CE MSTBL EQU CURRENT+1 ; (ADDRESS) pointer to extension table + 330 00D1 LASTZP EQU MSTBL+3 ; just checking + 331 ; + 332 ; these routines are in non-swapped memory + 333 ; + 334 00D1 ZERO_FB EQU LASTZP ; put fetch byte routine in at end of ZP + 335 00DC ZERO_ZF EQU ZERO_FB+11 ; and ZPCPNT fetch after that + 336 00E5 ZERO_MF EQU ZERO_ZF+9 ; and MPCPNT fetch after that + 337 00EE SAVE_DATA EQU ZERO_MF+9 ; copy data from DBUFF to IOBUFF routine + 338 ; + 339 ; and just to check the end + 340 ; + 341 00FF ZEE_END EQU SAVE_DATA+17 ; should be == 100 + 342 + 343 0000 END + 344 + 345 0000 INCLUDE PRODOS.EQU + 346 0000 STTL "--- ProDOS EQUATES ---" + 347 PAGE + Wed Jun 7 1989 12:04 Page 7 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ProDOS EQUATES ---" + + 348 + 349 ; + 350 ; some parameter structures + 351 ; + 352 0000 OPEN_PARM EQU 0 + 353 0000 OP_PCOUNT EQU OPEN_PARM ; must be 3 for open + 354 0001 OP_PATHNAME EQU OP_PCOUNT+1 ; address of pathname + 355 0003 OP_FILEBUFF EQU OP_PATHNAME+2 ; address of file data buffer + 356 0005 OP_REFNUM EQU OP_FILEBUFF+2 ; file reference number + 357 0006 OPEN_PSIZE EQU OP_REFNUM+1 ; size of parameter buffer + 358 + 359 0000 READ_PARM EQU 0 ; to read things + 360 0000 RD_PCOUNT EQU READ_PARM ; param count (=4) + 361 0001 RD_REFNUM EQU RD_PCOUNT+1 ; ref num of file + 362 0002 RD_BUFFER EQU RD_REFNUM+1 ; where to + 363 0004 RD_BUFFLEN EQU RD_BUFFER+2 ; length of buffer + 364 0006 RD_LENGTH EQU RD_BUFFLEN+2 ; actual length of read + 365 0008 READ_PSIZE EQU RD_LENGTH+2 ; length of parm block + 366 + 367 0000 CLOSE_PARM EQU 0 ; for closing file + 368 0000 CL_PCOUNT EQU CLOSE_PARM ; paramter count (=1) + 369 0001 CL_REFNUM EQU CL_PCOUNT+1 ; refnum of file to be closed + 370 0002 CLOSE_PSIZE EQU CL_REFNUM+1 ; this is the size, thank you + 371 + 372 0000 WRITE_PARM EQU 0 ; to write things + 373 0000 WR_PCOUNT EQU WRITE_PARM ; parm count (= 4) + 374 0001 WR_REFNUM EQU WR_PCOUNT+1 ; file refnum + 375 0002 WR_BUFFER EQU WR_REFNUM+1 ; data buffer address + 376 0004 WR_BUFFLEN EQU WR_BUFFER+2 ; data buffer length + 377 0006 WR_LENGTH EQU WR_BUFFLEN+2 ; actual length written + 378 0008 WRITE_PSIZE EQU WR_LENGTH+2 ; length of parm block + 379 + 380 0000 SETMARK_PARM EQU 0 + 381 0000 SM_PCOUNT EQU SETMARK_PARM ; parm count (=2) + 382 0001 SM_REFNUM EQU SM_PCOUNT+1 ; file refnum + 383 0002 SM_FPOS EQU SM_REFNUM+1 ; 3 byte file pos + 384 0005 SETMARK_PSIZE EQU SM_FPOS+3 ; length of parm block + 385 + 386 0000 SETPREFIX_PARM EQU 0 + 387 0000 SP_PCOUNT EQU SETPREFIX_PARM ; parm count (=1) + 388 0001 SP_PATHNAME EQU SP_PCOUNT+1 ; pointer to path name + 389 0003 SETPREFIX_PSIZE EQU SP_PATHNAME+2 ; length of block + 390 + 391 0000 SETEOF_PARM EQU 0 + 392 0000 SE_PCOUNT EQU SETEOF_PARM ; parm count (=2) + 393 0001 SE_REFNUM EQU SE_PCOUNT+1 ; reference number + 394 0002 SE_NEWEOF EQU SE_REFNUM+1 ; new EOF position + 395 0005 SETEOF_PSIZE EQU SE_NEWEOF+3 ; length of parm block + 396 + 397 0000 END + 398 + 399 0000 INCLUDE APPLE.EQU + 400 0000 STTL "--- APPLE ][ HARDWARE STUFF ---" + 401 PAGE + Wed Jun 7 1989 12:04 Page 8 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 402 ; ------------------- + 403 ; APPLE II MEMORY MAP + 404 ; ------------------- + 405 0001 AUX EQU 1 ; offset to Auxillary mem switches + 406 0000 MAIN EQU 0 ; for main memory switches + 407 + 408 ; + 409 ; some hardware spots + 410 ; + 411 2000 SCREEN EQU $2000 ; START OF Double HiRes SCREEN RAM + 412 + 413 BF00 PRGLBL EQU $BF00 ; ProDOS Globals page in main mem + 414 BF58 PR_BITMAP EQU $BF58 ; ProDOS system bitmap + 415 BFFF KVERSION EQU $BFFF ; ProDOS version (== $FF if InfoDOS) + 416 00FF INFODOS_ID EQU $FF + 417 + 418 C000 IOADDR EQU $C000 ; start of I/O registers + 419 D000 PROADR EQU $D000 ; start of ProDOS + 420 + 421 0200 LBUFF EQU $0200 ; LINE INPUT BUFFER + 422 0273 PIC1BUF EQU $0300-141 ; we can use line buffer for one picture buffer + 423 0280 SCRBUFF EQU LBUFF+$80 ; screen line buffer + 424 2000 BORG EQU $2000 ; ORIGIN OF .SYSTEM CODE + 425 ; + 426 ; some page 3 storage relocated stuff + 427 ; + 428 0300 PAGE3STUFF EQU $300 + 429 0300 MOUSER EQU PAGE3STUFF ; this is where mouse subroutine goes + 430 0312 COLORS EQU MOUSER+$12 + 431 0352 XPOSTBL EQU COLORS+$40 + 432 + 433 0400 SV_PCL EQU $400 ; for scrolling data + 434 0600 SV_PCH EQU $600 + 435 + 436 0800 IOBUFF EQU $0800 ; 1Kb DATA BUFFER BUFFER + 437 + 438 0C00 PAGING_MEM EQU IOBUFF+$400 ; Paging table stuff + 439 0C00 NEXTPNT EQU PAGING_MEM + 440 0C40 PREVPNT EQU NEXTPNT+$40 + 441 0C80 VPAGEH EQU PREVPNT+$40 + 442 0CC0 VPAGEL EQU VPAGEH+$40 + 443 0200 PAGELEN EQU $200 ; length of paged read + 444 + 445 0D00 ZSTKBL EQU PAGING_MEM+$100 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) + 446 0E00 ZSTKTL EQU ZSTKBL+$100 ; TOP, LO + 447 0F00 ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI + 448 1000 ZSTKTH EQU ZSTKBL+$300 ; TOP, HI + 449 ; + 450 ; now define some file i/o buffers and such + 451 ; + 452 1100 GAME1FIO EQU ZSTKBL+$400 ; Game file I/O buffer + 453 1500 GAME2FIO EQU GAME1FIO+$400 ; Second game file i/o buffer + 454 1900 SEGTBL EQU GAME2FIO+$400 ; segment table for multi disks + 455 1C74 PIC2BUF EQU SEGTBL+($400-140) ; picture buffer is 140 bytes long + 456 1D00 TCHARTBL EQU SEGTBL+$400 ; 208 bytes for (possible) terminating + 457 1D50 COPY_LINE EQU TCHARTBL+$50 ; copy line in screen memory + 458 1D7C CPY_MOD1_SRC equ COPY_LINE+$2C ; special self-modifying places + 459 1D7F CPY_MOD1_DST equ CPY_MOD1_SRC+3 + 460 1DA0 CPY_MOD2_SRC equ COPY_LINE+$50 + 461 1DA3 CPY_MOD2_DST equ CPY_MOD2_SRC+3 + 462 + 463 1DD0 DSKSEG EQU TCHARTBL+$D0 ; spot to stash pointers for disk segments + 464 1DD0 D1SEG EQU DSKSEG ; where in SEGTBL for Disk 1 + 465 1DD2 D2SEG EQU D1SEG+2 + 466 1DD4 D3SEG EQU D2SEG+2 + 467 1DD6 D4SEG EQU D3SEG+2 + 468 1DD8 D5SEG EQU D4SEG+2 + 469 1DDA D6SEG EQU D5SEG+2 + 470 1DDC D7SEG EQU D6SEG+2 + 471 1DDE D8SEG EQU D7SEG+2 + 472 1DE0 LOCAL_SV EQU TCHARTBL+$E0 ; to save locals before restore + 473 1E00 LOCALS EQU TCHARTBL+$100 ; LOCAL VARIABLE STORAGE (30 BYTES) + 474 1E20 BUFSAV EQU LOCALS+$20 ; TEMP SPACE FOR SAVE/RESTORE (80 BYTES) + 475 1F00 SCR_LINE EQU LOCALS+$100 ; place to build displayed line + 476 1F8C CHARSET EQU SCR_LINE+140 ; spot for charset to go + Wed Jun 7 1989 12:04 Page 9 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 477 ; + 478 ; now for some interpreter data + 479 ; + 480 4000 INTR_BEGIN EQU $4000 ; START OF Interpreter CODE in main + 481 5600 INTR_SIZE EQU (43*512) ; size of interpreter + 482 + 483 9600 ZBEGIN EQU (INTR_BEGIN+INTR_SIZE) ; start of Z code + 484 7F00 MMSIZE EQU PRGLBL-INTR_BEGIN ; free memory in main bank + 485 0029 Z1SIZE EQU >(PRGLBL-ZBEGIN) ; size of preload, part 1 + 486 ; + 487 ; this is in Bank 2, Main mem + 488 ; + 489 ; + 490 ; Picture directory goes in Bank 2, Aux mem + 491 ; + 492 D000 PIC_DIR EQU $D000 ; picture local directory + 493 DC00 GBL_DIR EQU $DC00 ; global directory + 494 ; + 495 ; some special markers if we are using InfoDOS + 496 ; + 497 0000 SP_BANK EQU MAIN + 498 D000 SP_START EQU $D000 ; start of special area + 499 0017 SP_SIZE EQU ((($FE->SP_START)*256)/512) ; how many pages + 500 ;SP_SIZE EQU (((>SCREEN->SP_START)*256)/512) ; how many pages + 501 + 502 0001 PB_BANK EQU AUX ; paging buffers in which bank + 503 0800 PBEGIN EQU $0800 ; start of paging buffers + 504 0018 NUMBUFS EQU >(SCREEN-PBEGIN) ; how many 256k paging buffers + 505 ;NUMBUFS EQU >($100-PBEGIN) ; how many 256k paging buffers + 506 + 507 0029 P2PAGE EQU >(PRGLBL-ZBEGIN) ; first page of zcode in aux bank + 508 4000 Z2BEGIN EQU $4000 ; start of part 2 in aux mem + 509 ; just after the dhires screen + 510 0040 Z2PAGE EQU >Z2BEGIN ; get me just the page address + 511 007F Z2SIZE EQU >(PRGLBL-Z2BEGIN) ; size of preload, part 2 + 512 00A8 P3PAGE EQU Z1SIZE+Z2SIZE ; first page in aux mem part 3 + 513 D000 Z3BEGIN EQU $D000 ; start of 3 part in aux mem + 514 00D0 Z3PAGE EQU >Z3BEGIN ; get me page number too + 515 002E Z3SIZE EQU <($FE-Z3PAGE) ; size of part 3, in pages + 516 + 517 ; + 518 ; other numba's + 519 ; + 520 00D6 PGBEGIN EQU (P3PAGE+Z3SIZE) ; first paged page + 521 00D6 PRESIZE EQU (Z1SIZE+Z2SIZE+Z3SIZE) ; size of preload, # pages + 522 2000 SCRSZE EQU INTR_BEGIN-SCREEN ; size of Double HiRes screen (8k, each bank) + 523 EE00 RAMDSK EQU (119*512) ; size of RAM disk in aux mem + 524 B500 RAMSAVE EQU $B500 ; save this much to cover HiRes screen in + 525 ; aux and the rest of the preload, up to + 526 ; PRGLBL ($bf00) + 527 3900 FREERAM EQU RAMDSK-RAMSAVE ; size of Free RAM after 'saving' + 528 ; special AUX memory + 529 2200 DSKSZE EQU (512*273) ; size of ProDOS data disk file + 530 + 531 ; --------- + 532 ; CONSTANTS + 533 ; --------- + 534 + 535 0002 IIeID EQU 2 ; Apple ][e Yzip + 536 0009 IIcID EQU 9 ; ][c Yzip + 537 000A IIgsID EQU 10 ; ][gs Yzip + 538 + 539 00FF P3BANK EQU $FF ; show upper aux mem + 540 0000 LO EQU 0 + 541 0001 HI EQU 1 + 542 0002 ABANK EQU 2 ; for address variables + 543 + 544 0000 OFF EQU 0 ; for toggling soft-switches + 545 0001 ON EQU 1 + 546 + 547 0003 RETRY_COUNT EQU 3 ; how many retries before message + 548 + 549 0009 TAB EQU $09 ; Tab char + 550 000B EOS EQU $0B ; End of Sentence + 551 000D EOL EQU $0D ; EOL CHAR + Wed Jun 7 1989 12:04 Page 10 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 552 000A LF EQU $0A ; LINE FEED + 553 0020 SPACE EQU $20 ; SPACE CHAR + 554 0008 BACKSPACE EQU $08 ; BACKSPACE CHAR + 555 001B ESCAPE EQU $1B ; ESCAPE Key + 556 003F VOLCHAR EQU '?' ; Key to hit for ONLINE command + 557 ; + 558 ; Screen Defs + 559 ; + 560 008C MAXWIDTH EQU 140 ; 560 / 4 = max "pixels" + 561 0230 REAL_MAXW EQU MAXWIDTH*4 + 562 00C0 MAXHEIGHT EQU 192 ; 192 screen lines + 563 0002 FONT_W EQU 2 ; font width (for game, anyway) + 564 0009 FONT_H EQU 9 ; font height + 565 0003 MFONT_W EQU 3 ; mono spaced font width, to game + 566 000C MONOFONT_W EQU MFONT_W*4 ; how wide the mono font really is + 567 + 568 0008 SPACE_WIDTH EQU 8 ; default space width + 569 0003 BLINK_RATE EQU 3 ; tenths of seconds between blinks + 570 + 571 001C OUTER_DELAY EQU $1C ; outside delay loop counter + 572 0003 INNER_DELAY EQU 3 ; inner delay loop + 573 + 574 0072 GS_OUTER_DELAY EQU $72 ; ][gs outside counter + 575 0002 GS_INNER_DELAY EQU 2 ; ][gs inside counter + 576 + 577 ; ---------------------- + 578 ; BOOT ZERO PAGE EQUATES + 579 ; ---------------------- + 580 + 581 0026 BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS + 582 002B BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT + 583 + 584 0280 START_NAME EQU $280 ; name upon boot is stored here + 585 ; ---------------- + 586 ; HARDWARE EQUATES + 587 ; ---------------- + 588 + 589 C000 KBD EQU $C000 ; KEY STROBE + 590 C000 STORE80 EQU $C000 ; video aux mem switch + 591 C002 RDBNK EQU $C002 ; READ MAIN MEMORY (+MAIN, +AUX) + 592 C004 WRTBNK EQU $C004 ; WRITE MAIN 48K OF MEMORY (+MAIN, +AUX) + 593 C008 ALTZP EQU $C008 ; R/W MAIN (C009 = AUX) >MEM + 594 C00C COL80SW EQU $C00C ; 80 Column switch + 595 C010 ANYKEY EQU $C010 ; ANY KEY DOWN FLAG + 596 C019 VERTBLNK EQU $C019 ; Vertical Blanking Flag + 597 C029 IIGSVID EQU $C029 ; GS MEGA ][ video register + 598 C030 SPKR EQU $C030 ; SPEAKER FLAG (MAKE A NOISE) + 599 C035 IIGSSHD EQU $C035 ; ][GS shadowing reg + 600 C050 TEXTSW EQU $C050 ; Graphics Switch + 601 C052 MIXEDSW EQU $C052 ; Mixed Text/Graphics + 602 C054 PAGE2SW EQU $C054 ; Page select + 603 C056 HIRESSW EQU $C056 ; Select HiRes + 604 C05E DHIRESW EQU $C05E ; Double HiRes switch (backwards: +0 on +1 off) + 605 C07E IOUDIS EQU $C07E ; Double HiRes Switch enabler (same backass way) + 606 C083 BNK2SET EQU $C083 ;READ/READ READ RAM WRITE RAM BANK 2 + 607 C08B BNK1SET EQU $C08B ;READ/READ READ RAM WRITE RAM BANK 1 + 608 C082 RDROM EQU $C082 ; READ READ ROM NO WRITE + 609 C088 RDBNK1 EQU $C088 ; READ ram, bank 1 + 610 C080 RDBNK2 EQU $C080 ; Read ram, bank 2 + 611 + 612 ; ----------------- + 613 ; MONITOR VARIABLES + 614 ; ----------------- + 615 + 616 0036 CSW EQU $36 ; CHARACTER OUTPUT VECTOR (for scripting) + 617 C061 APKEY1 EQU $C061 ; open apple key flag + 618 C062 APKEY2 EQU $C062 ; closed apple key flag + 619 + 620 0002 CURSW EQU 2 ; width of cursor + 621 0004 CURSH EQU 4 ; height of cursor + 622 ; ----------- + 623 ; MOUSE STUFF + 624 ; ----------- + 625 C412 MTABLE EQU $C412 ; Mouse ROM table + 626 0310 MSVECTOR EQU MOUSER+16 ; where vector is stored + Wed Jun 7 1989 12:04 Page 11 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 627 0312 MSMOVEF EQU MSVECTOR+2 ; Mouse moved flag + 628 0313 MSBTNF EQU MSMOVEF+1 ; Mouse button flag + 629 ; + 630 ; MOUSE screen holes + 631 ; + 632 0478 CLMPMINL EQU $478 ; lo part of clamping min + 633 0578 CLMPMINH EQU $578 ; hi part of " " + 634 04F8 CLMPMAXL EQU $4F8 ; lo part of clamping max + 635 05F8 CLMPMAXH EQU $5F8 ; hi part of " " + 636 0478 MOUSEXL EQU $478 ; lo part of mouse X + 637 0578 MOUSEXH EQU $578 ; hi part of mouse X + 638 04F8 MOUSEYL EQU $4F8 ; lo part of mouse Y + 639 05F8 MOUSEYH EQU $5F8 ; hi part of mouse Y + 640 0778 MOUSEST EQU $778 ; status byte + 641 ; + 642 ; some mouse constants + 643 ; + 644 0081 SGL_CLK EQU $81 ; single click char + 645 0082 DBL_CLK EQU $82 ; double click char + 646 0006 CLK_CNT EQU 6 ; counts between single and double click + 647 ; Subroutine offsets + 648 0000 SETM EQU 0 + 649 0001 SERVEM EQU 1 + 650 0002 READM EQU 2 + 651 0003 CLEARM EQU 3 + 652 0004 POSM EQU 4 + 653 0005 CLAMPM EQU 5 + 654 0006 HOMEM EQU 6 + 655 0007 INITM EQU 7 + 656 + 657 ; -------------- + 658 ; PRODOS GLOBALS + 659 ; -------------- + 660 BF90 PRODATE EQU $BF90 ; date and + 661 BF92 PROTIME EQU $BF92 ; time + 662 BF98 MACHID EQU $BF98 ; machine id + 663 + 664 ; ---------------- + 665 ; MONITOR ROUTINES + 666 ; ---------------- + 667 FB1E MPREAD EQU $FB1E ; Read for joystick control + 668 FC22 MBASCAL EQU $FC22 ; CALC LINE BASE ADDRESS + 669 FF3A MBELL EQU $FF3A ; MAKE A NOISE + 670 FFFC RESET_VECTOR EQU $FFFC ; force warm reboot + 671 FC9C MCLEOL EQU $FC9C ; CLEAR TO END OF LINE + 672 FC42 MCLEOS EQU $FC42 ; CLEAR TO END OF SCREEN + 673 FC58 MHOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR + 674 FDED MCOUT EQU $FDED ; CHAR OUTPUT + 675 FDF0 MCOUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN + 676 FD0C MRDKEY EQU $FD0C ; READ KEY + 677 FD6F MGETLN1 EQU $FD6F ; GET LINE + 678 FCA8 MWAIT EQU $FCA8 ; WASTE SO MUCH TIME + 679 ; + 680 ; Some /RAM spots + 681 ; + 682 BF26 RAMVEC EQU $BF26 ; /RAM drive vector + 683 077E OLDVEC EQU $77E ; spot to save the drive vector + 684 BF16 UNSVEC EQU $BF16 ; "Uninstalled Device" vector + 685 BF31 DEVCNT EQU $BF31 ; Device count + 686 BF32 DEVNUM EQU $BF32 ; Device list + 687 + 688 ; + 689 ; machine info spots + 690 ; + 691 FBB3 MACHID1 EQU $FBB3 ; first part + 692 FBC0 MACHID2 EQU $FBC0 ; second part + 693 FE1F MACHCHK EQU $FE1F ; differentiate between ][e and gs + 694 ; do sec, then jsr, and if still set, = ][e + 695 0000 END + 696 + 697 0000 INCLUDE MACROS.ASM + 698 0000 STTL "--- MACROS ---" + 699 PAGE + Wed Jun 7 1989 12:04 Page 12 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- MACROS ---" + + 700 + 701 ; + 702 ; MACROS for Apple ][ Yzip + 703 ; + 704 DLINE: .MACRO STRING,SLEN + 705 ldx #STRING ; get other part of string + 707 IFMA 2 ; check to see if length passed in + 708 ldy SLEN ; then just fetch it + 709 ELSE + 710 ldy #STRING|L ; get length of string + 711 ENDIF + 712 jsr DLINE ; print the string + 713 .MACEND + 714 ; + 715 ; ProDOS macros + 716 ; + 717 PRODOS: .MACRO CODE, PADDR + 718 jsr $BF00 ; ProDOS handler + 719 DB CODE ; ProDOS function code + 720 DW PADDR ; Function Parameter Block address + 721 .MACEND + 722 + 723 QUIT: .MACRO PBLOCK + 724 PRODOS $65, PBLOCK + 725 .MACEND + 726 + 727 READ_BLOCK: .MACRO PBLOCK + 728 PRODOS $80, PBLOCK + 729 .MACEND + 730 + 731 WRITE_BLOCK: .MACRO PBLOCK + 732 PRODOS $81, PBLOCK + 733 .MACEND + 734 + 735 GET_TIME: .MACRO PBLOCK + 736 PRODOS $82, PBLOCK + 737 .MACEND + 738 + 739 CREATE: .MACRO PBLOCK + 740 PRODOS $C0, PBLOCK + 741 .MACEND + 742 + 743 DESTROY: .MACRO PBLOCK + 744 PRODOS $C1, PBLOCK + 745 .MACEND + 746 + 747 RENAME: .MACRO PBLOCK + 748 PRODOS $C2, PBLOCK + 749 .MACEND + 750 + 751 SET_FILE_INFO: .MACRO PBLOCK + 752 PRODOS $C3, PBLOCK + 753 .MACEND + 754 + 755 GET_FILE_INFO: .MACRO PBLOCK + 756 PRODOS $C4, PBLOCK + 757 .MACEND + 758 + 759 ONLINE: .MACRO PBLOCK + 760 PRODOS $C5, PBLOCK + 761 .MACEND + 762 + 763 SET_PREFIX: .MACRO PBLOCK + 764 PRODOS $C6, PBLOCK + 765 .MACEND + 766 + 767 GET_PREFIX: .MACRO PBLOCK + 768 PRODOS $C7, PBLOCK + 769 .MACEND + 770 + 771 OPEN: .MACRO PBLOCK + 772 PRODOS $C8, PBLOCK + 773 .MACEND + 774 + Wed Jun 7 1989 12:04 Page 13 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- MACROS ---" + + 775 NEWLINE: .MACRO PBLOCK + 776 PRODOS $C9, PBLOCK + 777 .MACEND + 778 + 779 READ: .MACRO PBLOCK + 780 PRODOS $CA, PBLOCK + 781 .MACEND + 782 + 783 WRITE: .MACRO PBLOCK + 784 PRODOS $CB, PBLOCK + 785 .MACEND + 786 + 787 CLOSE: .MACRO PBLOCK + 788 PRODOS $CC, PBLOCK + 789 .MACEND + 790 + 791 FLUSH: .MACRO PBLOCK + 792 PRODOS $CD, PBLOCK + 793 .MACEND + 794 + 795 SET_MARK: .MACRO PBLOCK + 796 PRODOS $CE, PBLOCK + 797 .MACEND + 798 + 799 GET_MARK: .MACRO PBLOCK + 800 PRODOS $CF, PBLOCK + 801 .MACEND + 802 + 803 SET_EOF: .MACRO PBLOCK + 804 PRODOS $D0, PBLOCK + 805 .MACEND + 806 + 807 SET_BUF: .MACRO PBLOCK + 808 PRODOS $D1, PBLOCK + 809 .MACEND + 810 + 811 GET_BUF: .MACRO PBLOCK + 812 PRODOS $D2, PBLOCK + 813 .MACEND + 814 + 815 0000 END + 816 + 817 + 818 0000 TITLE "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + 819 0000 INCLUDE ZBEGIN.ASM + 820 0000 STTL "--- START OF APPLE ][ INTERPRETER ---" + 821 PAGE + Wed Jun 7 1989 12:04 Page 14 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- START OF APPLE ][ INTERPRETER ---" + + 822 + 823 4000 ORG INTR_BEGIN + 824 ; + 825 ; Set up for Double HiRes full screen graphics + 826 ; + 827 4000 AD 54 C0 lda PAGE2SW+OFF ; turn off page 2 + 828 4003 8D 50 C0 sta TEXTSW+OFF ; turn off text - turn on graphics + 829 4006 8D 57 C0 sta HIRESSW+ON ; turn on high resolution + 830 4009 8D 52 C0 sta MIXEDSW+OFF ; full screen graphics + 831 400C 8D 0D C0 sta COL80SW+ON ; turn on 80 column + 832 400F 8D 7E C0 sta IOUDIS+OFF ; turn ON (it too is backwards) Dhires switch + 833 4012 8D 5E C0 sta DHIRESW+OFF ; turn ON (it's backwards!) Dhires + 834 + 835 4015 8D 01 C0 sta STORE80+ON ; turn on aux page display ability + 836 4018 AD 83 C0 lda BNK2SET ; read/write RAM, bank 2 + 837 401B AD 83 C0 lda BNK2SET + 838 ; + 839 ; copy in progame from boot code + 840 ; + 841 401E A2 00 ldx #0 ; start at first letter + 842 4020 MVPRE: + 843 4020 BD 03 20 lda BORG+3,X ; get letter + 844 4023 F0 0C beq MVPREX ; all done + 845 4025 9D 78 46 sta GAME1NAME,X ; save letter + 846 4028 9D 8A 46 sta GAME2NAME,X ; save letter + 847 402B 9D 68 46 sta GAME,X ; save for asking about later + 848 402E E8 inx ; next letter + 849 402F D0 EF bne MVPRE ; do gen + 850 4031 MVPREX: + 851 4031 8E 67 46 stx GAMEL ; save length of game name + 852 4034 A9 2E lda #'.' ; get extension for names + 853 4036 9D 78 46 sta GAME1NAME,X ; save letter + 854 4039 9D 8A 46 sta GAME2NAME,X ; save letter + 855 403C E8 inx ; next letter + 856 403D A9 44 lda #'D' ; for data segments + 857 403F 9D 78 46 sta GAME1NAME,X ; save letter + 858 4042 9D 8A 46 sta GAME2NAME,X ; save letter + 859 4045 E8 inx ; points to number + 860 4046 E8 inx ; inclusive count for length + 861 4047 8E 77 46 stx GAME1NML ; save length of name + 862 404A 8E 89 46 stx GAME2NML ; save length of name + 863 + 864 404D A9 0D lda #VERSID ; put in version number + 865 404F 8D 1F 96 sta ZBEGIN+ZINTWD+1 + 866 + 867 4052 E6 AF inc ZSP+LO ; INIT Z-STACK POINTERS + 868 4054 EE 7A 6C inc OLDZSP+LO ; TO "1" + 869 4057 E6 B1 inc SCREENF ; TURN DISPLAY ON + 870 4059 E6 AA inc SCRIPT ; enable scripting + 871 405B EE A8 6C inc CRLF_CHECK ; do CR functino check + 872 + 873 405E AD 4C 6E lda WINTABLE+LO ; set WINDOW to point to window 0 + 874 4061 85 05 sta WINDOW+LO + 875 4063 AD 4D 6E lda WINTABLE+HI + 876 4066 85 06 sta WINDOW+HI ; okay, it does + 877 + 878 4068 A5 63 lda ARG1+LO ; using mouse? + 879 406A F0 12 beq ZBEGIN1 ; nope + 880 406C 09 78 ora #$78 ; point to correct screen holes + 881 406E 8D 50 50 sta MSFIX0+1 + 882 4071 8D 5B 50 sta MSFIX1+1 ; and modify code to point to correct spot + 883 4074 8D 60 50 sta MSFIX2+1 + 884 4077 A5 63 lda ARG1+LO + 885 4079 09 F8 ora #$F8 ; and one more + 886 407B 8D 60 50 sta MSFIX2+1 + 887 407E ZBEGIN1: + 888 407E A9 FF lda #$FF ; do a clear -1 to start off + 889 4080 85 63 sta ARG1+LO ; so arg 1 is this + 890 4082 20 B0 57 jsr ZCLR ; doing it + 891 + 892 4085 GET_PREFIX GPRE_PB ; get where we are to start + 893 4085 PRODOS $C7, GPRE_PB + 894 4085 20 00 BF jsr $BF00 ; ProDOS handler + 895 4088 C7 DB $C7 ; ProDOS function code + 896 4089 6446 DW GPRE_PB ; Function Parameter Block address + Wed Jun 7 1989 12:04 Page 15 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- START OF APPLE ][ INTERPRETER ---" + + 897 408B .MACEND + 898 408B .MACEND + 899 + 900 408B AD D3 1D lda D2SEG+HI ; start DSEGS at .D2 + 901 408E 85 1F sta DSEGS+HI + 902 4090 AD D2 1D lda D2SEG+LO + 903 4093 85 1E sta DSEGS+LO + 904 + 905 4095 A9 01 lda #1 ; open game file .D2 please + 906 4097 20 C6 49 jsr FETCH_FILE ; we did that + 907 409A A5 59 lda INFODOS ; are we on little dos? + 908 409C F0 03 beq ZBEGIN2 ; nope + 909 409E 20 F1 4B jsr GET_SPECIAL ; do special preloading if so + 910 40A1 ZBEGIN2: + 911 40A1 AD D5 1D lda D3SEG+HI ; this is cuz we be openin' .D3 + 912 40A4 85 1F sta DSEGS+HI + 913 40A6 AD D4 1D lda D3SEG+LO + 914 40A9 85 1E sta DSEGS+LO + 915 40AB A9 02 lda #2 ; and just for giggles, do the + 916 40AD 20 C6 49 jsr FETCH_FILE ; same for game file .D3 + 917 + 918 40B0 20 AF 90 jsr VLDZPC ; MAKE ZPC VALID + 919 40B3 20 24 92 jsr NEXTPC ; skip over # of locals + 920 + 921 ; ... AND FALL INTO MAIN LOOP + 922 + 923 40B6 END + 924 + 925 40B6 INCLUDE MAIN.ASM + 926 40B6 STTL "--- MAIN LOOP ---" + 927 PAGE + Wed Jun 7 1989 12:04 Page 16 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 928 + 929 9600 MD_ADDR EQU ZBEGIN + 930 0001 MDEBUG EQU 1 + 931 + 932 40B6 MLOOP: + 933 [01] IF MDEBUG + 934 40B6 AD 00 96 lda MD_ADDR ; get interesting address + 935 40B9 D0 01 bne MLOOPx ; just fine, thank you + 936 40BB 00 brk ; then die + 937 40BC MLOOPx: + 938 [00] ENDIF + 939 + 940 40BC A9 00 lda #0 + 941 40BE 85 62 sta NARGS ; reset number of args + 942 40C0 AD 54 C0 lda PAGE2SW+OFF ; just do this for the heck of it + 943 40C3 AD 83 C0 lda BNK2SET + 944 40C6 AD 83 C0 lda BNK2SET + 945 40C9 8D 01 C0 sta STORE80+ON ; must always be on + 946 + 947 40CC 20 24 92 jsr NEXTPC ; get op code + 948 40CF 85 61 sta OPCODE ; SAVE IT HERE + 949 + 950 [01] IF MDEBUG + 951 ; + 952 ; special debugging code + 953 ; + 954 40D1 AC 01 41 ldy SPCSV + 955 40D4 A5 61 lda OPCODE + 956 40D6 99 10 41 sta SAVEOP,Y + 957 40D9 A5 82 lda ZPCH + 958 40DB 99 20 41 sta SAVEZH,Y + 959 40DE A5 81 lda ZPCM + 960 40E0 99 30 41 sta SAVEZM,Y + 961 40E3 A5 80 lda ZPCL + 962 40E5 99 40 41 sta SAVEZL,Y + 963 40E8 A5 85 lda ZPCBNK + 964 40EA 99 50 41 sta SAVEZB,Y + 965 40ED A5 84 lda ZPCPNT+HI + 966 40EF 99 60 41 sta SAVEZP,Y + 967 40F2 AC 01 41 ldy SPCSV + 968 40F5 C8 iny + 969 40F6 98 tya + 970 40F7 29 0F and #$0F + 971 40F9 8D 01 41 sta SPCSV + 972 40FC A5 61 lda OPCODE + 973 40FE 4C 70 41 jmp MAINDB + 974 4101 00 SPCSV: db 0 + 975 4111 ORG $+15 + 976 0411 ORG $.SHR.4 + 977 4110 ORG $.SHL.4 + 978 4110 SAVEOP: ds 16 + 979 4120 SAVEZH: ds 16 + 980 4130 SAVEZM: ds 16 + 981 4140 SAVEZL: ds 16 + 982 4150 SAVEZB: ds 16 + 983 4160 SAVEZP: ds 16 + 984 4170 MAINDB: + 985 [00] ENDIF + 986 ; + 987 ; DECODE AN OPCODE + 988 ; + 989 4170 A8 tay ; set flags + 990 4171 30 03 bmi DC0 ; IF POSITIVE, + 991 4173 4C CD 42 jmp OP2 ; IT'S A 2-OP + 992 4176 C9 B0 DC0: cmp #$B0 + 993 4178 B0 03 bcs DC1 + 994 417A 4C 90 42 jmp OP1 ; OR MAYBE A 1-OP + 995 417D C9 C0 DC1: cmp #$C0 + 996 417F B0 03 bcs OPEXT + 997 4181 4C 6A 42 jmp OP0 ; PERHAPS A 0-OP + 998 + 999 ; -------------- + 1000 ; HANDLE AN X-OP + 1001 ; -------------- + 1002 + Wed Jun 7 1989 12:04 Page 17 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1003 4184 C9 EC OPEXT: CMP #236 ; XCALL? + 1004 4186 D0 03 BNE OPX5 + 1005 4188 4C 15 42 JMP OPXCLL ; YES, PROCESS SEPARATELY + 1006 418B C9 FA OPX5: CMP #250 ; IXCALL + 1007 418D D0 03 BNE OPX6 + 1008 418F 4C 15 42 JMP OPXCLL + 1009 4192 20 24 92 OPX6: JSR NEXTPC ; GRAB THE ARGUMENT ID BYTE + 1010 4195 85 73 STA ABYTE ; HOLD IT HERE + 1011 4197 A2 00 LDX #0 + 1012 4199 86 75 STX ADEX ; INIT ARGUMENT INDEX + 1013 419B F0 06 BEQ OPX1 ; JUMP TO TOP OF LOOP + 1014 419D A5 73 OPX0: LDA ABYTE ; GET ARG BYTE + 1015 419F 0A ASL A ; SHIFT NEXT 2 ARG BITS + 1016 41A0 0A ASL A ; INTO BITS 7 & 6 + 1017 41A1 85 73 STA ABYTE ; HOLD FOR LATER + 1018 41A3 29 C0 OPX1: AND #%11000000 ; MASK OUT GARBAGE BITS + 1019 41A5 D0 06 BNE OPX2 + 1020 41A7 20 2B 43 JSR GETLNG ; 00 = LONG IMMEDIATE + 1021 41AA 4C BE 41 JMP OPXNXT + 1022 41AD C9 40 OPX2: CMP #%01000000 ; IS IT A SHORT IMMEDIATE? + 1023 41AF D0 06 BNE OPX3 ; NO, KEEP GUESSING + 1024 41B1 20 27 43 JSR GETSHT ; 01 = SHORT IMMEDIATE + 1025 41B4 4C BE 41 JMP OPXNXT + 1026 41B7 C9 80 OPX3: CMP #%10000000 ; LAST TEST + 1027 41B9 D0 17 BNE OPX4 ; 11 = NO MORE ARGUMENTS + 1028 41BB 20 3F 43 JSR GETVAR ; 10 = VARIABLE + 1029 41BE A6 75 OPXNXT: LDX ADEX ; RETRIEVE ARGUMENT INDEX + 1030 41C0 A5 76 LDA VALUE+LO ; GRAB LSB OF VALUE + 1031 41C2 95 63 STA ARG1+LO,X ; STORE IN ARGUMENT TABLE + 1032 41C4 A5 77 LDA VALUE+HI ; GRAB MSB OF VALUE + 1033 41C6 95 64 STA ARG1+HI,X ; STORE THAT, TOO + 1034 41C8 E6 62 INC NARGS ; UPDATE ARGUMENT COUNTER + 1035 41CA E8 INX + 1036 41CB E8 INX + 1037 41CC 86 75 STX ADEX ; UPDATE INDEX + 1038 41CE E0 08 CPX #8 ; DONE 4 ARGUMENTS YET? + 1039 41D0 90 CB BCC OPX0 ; NO, GET SOME MORE + 1040 + 1041 ; ALL X-OP ARGUMENTS READY + 1042 + 1043 41D2 A5 61 OPX4: LDA OPCODE ; IS THIS + 1044 41D4 C9 E0 CMP #$E0 ; AN EXTENDED 2-OP? + 1045 41D6 B0 07 BCS DOXOP ; NO, IT'S A REAL X-OP + 1046 41D8 C9 C0 CMP #$C0 ; IS IT NEW OPCODE RANGE? + 1047 41DA 90 18 BCC ZEXTOP ; YES + 1048 41DC 4C 00 43 JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + 1049 + 1050 41DF 29 1F DOXOP: AND #%00011111 ; ISOLATE ID BITS + 1051 41E1 A8 TAY + 1052 41E2 B9 74 45 LDA OPTXL,Y + 1053 41E5 8D EF 41 STA GOX+1+LO + 1054 41E8 B9 54 45 LDA OPTXH,Y + 1055 41EB 8D F0 41 STA GOX+1+HI + 1056 41EE 20 FF FF GOX: JSR $FFFF ;DUMMY + 1057 41F1 4C B6 40 JMP MLOOP + 1058 + 1059 ; HANDLE EXTENDED OPCODE RANGE OPS + 1060 + 1061 41F4 C9 1D ZEXTOP: CMP #EXTLEN ; OUT OF RANGE? + 1062 41F6 B0 18 BCS BADEXT + 1063 41F8 A8 TAY ; OFFSET ALREADY CORRECT + 1064 41F9 B9 B1 45 LDA EXTOPL,Y + 1065 41FC 8D 06 42 STA GOE+1+LO + 1066 41FF B9 94 45 LDA EXTOPH,Y + 1067 4202 8D 07 42 STA GOE+1+HI + 1068 4205 20 FF FF GOE: JSR $FFFF ;DUMMY + 1069 4208 4C B6 40 JMP MLOOP + 1070 + 1071 ; *** ERROR #1 -- ILLEGAL X-OP *** + 1072 + 1073 420B A9 01 BADOPX: LDA #1 + 1074 420D 4C 0A 52 JMP ZERROR + 1075 + 1076 ; *** ERROR #16 -- ILLEGAL EXTENDED RANGE X-OP *** + 1077 + Wed Jun 7 1989 12:04 Page 18 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1078 4210 A9 10 BADEXT: LDA #16 + 1079 4212 4C 0A 52 JMP ZERROR + 1080 + 1081 ; HANDLE AN XCALL OPCODE + 1082 + 1083 4215 20 24 92 OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + 1084 4218 85 73 STA ABYTE + 1085 421A 20 24 92 JSR NEXTPC + 1086 421D 85 74 STA BBYTE + 1087 421F A5 73 LDA ABYTE ; ONE TO START WITH + 1088 4221 A2 00 LDX #0 + 1089 4223 86 75 STX ADEX ; INIT ARGUMENT INDEX + 1090 4225 F0 06 BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP + 1091 4227 A5 73 XCALL1: LDA ABYTE ; GET ARG BYTE + 1092 4229 0A ASL A ; SHIFT NEXT 2 BITS + 1093 422A 0A ASL A ; INTO BITS 7 & 6 + 1094 422B 85 73 STA ABYTE ; HOLD FOR LATER + 1095 422D 29 C0 XCALL2: AND #%11000000 ; MASK OUT GARBAGE + 1096 422F D0 06 BNE XCALL3 + 1097 4231 20 2B 43 JSR GETLNG ; 00 = LONG IMMEDIATE + 1098 4234 4C 48 42 JMP XCNXT + 1099 4237 C9 40 XCALL3: CMP #%01000000 ; SHORT IMMED? + 1100 4239 D0 06 BNE XCALL4 ; NO, TRY ANOTHER + 1101 423B 20 27 43 JSR GETSHT ; 01 = SHORT IMMED. + 1102 423E 4C 48 42 JMP XCNXT + 1103 4241 C9 80 XCALL4: CMP #%10000000 ; LAST TEST + 1104 4243 D0 8D BNE OPX4 ; 11 = NO MORE ARGS + 1105 4245 20 3F 43 JSR GETVAR ; 10 = VARIABLE + 1106 4248 A6 75 XCNXT: LDX ADEX + 1107 424A A5 76 LDA VALUE+LO + 1108 424C 95 63 STA ARG1+LO,X + 1109 424E A5 77 LDA VALUE+HI + 1110 4250 95 64 STA ARG1+HI,X + 1111 4252 E6 62 INC NARGS + 1112 4254 E8 INX + 1113 4255 E8 INX + 1114 4256 86 75 STX ADEX + 1115 4258 E0 10 CPX #16 + 1116 425A D0 03 BNE XCALL5 + 1117 425C 4C D2 41 JMP OPX4 ; DONE, GO DO IT + 1118 425F E0 08 XCALL5: CPX #8 ; DONE 1ST MODE BYTE? + 1119 4261 D0 C4 BNE XCALL1 ; NOT QUITE YET + 1120 4263 A5 74 LDA BBYTE ; SET UP FOR NEXT + 1121 4265 85 73 STA ABYTE ; MODE BYTE + 1122 4267 4C 2D 42 JMP XCALL2 ; GO DO IT + 1123 + 1124 ; ------------- + 1125 ; HANDLE A 0-OP + 1126 ; ------------- + 1127 + 1128 426A C9 BE OP0: CMP #190 ; IS IT EXTOP OP + 1129 426C F0 1A BEQ EXTOP ; YES + 1130 426E 29 0F AND #%00001111 ; ISOLATE 0-OP ID BITS + 1131 4270 A8 TAY + 1132 4271 B9 E4 44 LDA OPT0L,Y + 1133 4274 8D 7E 42 STA GO0+1+LO + 1134 4277 B9 D4 44 LDA OPT0H,Y + 1135 427A 8D 7F 42 STA GO0+1+HI + 1136 427D 20 FF FF GO0: JSR $FFFF ;DUMMY + 1137 4280 4C B6 40 JMP MLOOP + 1138 + 1139 ; *** ERROR #2 -- ILLEGAL 0-OP *** + 1140 + 1141 4283 A9 02 BADOP0: LDA #2 + 1142 4285 4C 0A 52 JMP ZERROR + 1143 + 1144 ; THIS OPCODE TELLS THAT NEXT OP IS PART OF THE + 1145 ; EXTENDED RANGE OF OPCODES, GET IT AND PROCESS IT + 1146 ; (THEY ARE ALL XOPS) + 1147 + 1148 4288 20 24 92 EXTOP: JSR NEXTPC ; GO GET EXTENDED RANGE OP + 1149 428B 85 61 STA OPCODE ; SAVE IT + 1150 428D 4C 84 41 JMP OPEXT ; AND HANDLE IT + 1151 + 1152 + Wed Jun 7 1989 12:04 Page 19 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1153 ; ------------- + 1154 ; HANDLE A 1-OP + 1155 ; ------------- + 1156 + 1157 4290 OP1: + 1158 4290 29 30 and #%00110000 ; ISOLATE ARGUMENT BITS + 1159 4292 D0 07 bne OP1A + 1160 4294 20 24 92 jsr NEXTPC ; get next byte + 1161 4297 A8 tay + 1162 4298 4C 9F 42 jmp OP1A1 + 1163 429B 29 20 OP1A: and #%00100000 ; TEST AGAIN + 1164 429D D0 0C bne OP1B + 1165 ; + 1166 ; 01 = SHORT IMMEDIATE + 1167 ; + 1168 429F 85 64 OP1A1: sta ARG1+HI + 1169 42A1 20 24 92 jsr NEXTPC + 1170 42A4 85 63 sta ARG1+LO + 1171 42A6 E6 62 inc NARGS + 1172 42A8 4C B1 42 jmp OP1EX1 + 1173 42AB 20 3F 43 OP1B: JSR GETVAR ; 10 = VARIABLE + 1174 42AE 20 1C 43 OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] + 1175 42B1 A5 61 OP1EX1: LDA OPCODE + 1176 42B3 29 0F AND #%00001111 ; ISOLATE 0-OP ID BITS + 1177 42B5 A8 TAY + 1178 42B6 B9 04 45 LDA OPT1L,Y + 1179 42B9 8D C3 42 STA GO1+1+LO + 1180 42BC B9 F4 44 LDA OPT1H,Y + 1181 42BF 8D C4 42 STA GO1+1+HI + 1182 42C2 20 FF FF GO1: JSR $FFFF ;DUMMY + 1183 42C5 4C B6 40 JMP MLOOP + 1184 + 1185 ; *** ERROR #3 -- ILLEGAL 1-OP *** + 1186 + 1187 42C8 A9 03 BADOP1: LDA #3 + 1188 42CA 4C 0A 52 JMP ZERROR + 1189 + 1190 + 1191 + 1192 ; ------------- + 1193 ; HANDLE A 2-OP + 1194 ; ------------- + 1195 + 1196 42CD 29 40 OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT + 1197 42CF D0 0C BNE OP2A + 1198 ; + 1199 ; 0 = SHORT IMMEDIATE + 1200 ; + 1201 42D1 85 64 sta ARG1+HI + 1202 42D3 20 24 92 jsr NEXTPC + 1203 42D6 85 63 sta ARG1+LO + 1204 42D8 E6 62 inc NARGS + 1205 42DA 4C E3 42 jmp OP2B1 + 1206 42DD 20 3F 43 OP2A: jsr GETVAR ; 1 = VARIABLE + 1207 42E0 20 1C 43 OP2B: jsr V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] + 1208 42E3 A5 61 OP2B1: lda OPCODE ; RESTORE OPCODE BYTE + 1209 42E5 29 20 and #%00100000 ; ISOLATE 2ND ARG BIT + 1210 42E7 D0 0A bne OP2C + 1211 42E9 85 66 sta ARG2+HI + 1212 42EB 20 24 92 jsr NEXTPC + 1213 42EE 85 65 sta ARG2+LO + 1214 42F0 4C FE 42 jmp OP2D1 + 1215 42F3 20 3F 43 OP2C: jsr GETVAR ; 1 = VARIABLE + 1216 42F6 A5 76 OP2D: lda VALUE+LO ; MOVE 2ND [VALUE] + 1217 42F8 85 65 sta ARG2+LO ; INTO [ARG2] + 1218 42FA A5 77 lda VALUE+HI + 1219 42FC 85 66 sta ARG2+HI + 1220 42FE E6 62 OP2D1: inc NARGS ; UPDATE ARGUMENT COUNT + 1221 + 1222 ; EXECUTE A 2-OP OR EXTENDED 2-OP + 1223 + 1224 4300 A5 61 OP2EX: LDA OPCODE + 1225 4302 29 1F AND #%00011111 ; ISOLATE 0-OP ID BITS + 1226 4304 A8 TAY + 1227 4305 B9 34 45 LDA OPT2L,Y + Wed Jun 7 1989 12:04 Page 20 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1228 4308 8D 12 43 STA GO2+1+LO + 1229 430B B9 14 45 LDA OPT2H,Y + 1230 430E 8D 13 43 STA GO2+1+HI + 1231 4311 20 FF FF GO2: JSR $FFFF ;DUMMY + 1232 4314 4C B6 40 JMP MLOOP + 1233 + 1234 ; *** ERROR #4 -- ILLEGAL 2-OP **** + 1235 + 1236 4317 A9 04 BADOP2: LDA #4 + 1237 4319 4C 0A 52 JMP ZERROR + 1238 + 1239 + 1240 + 1241 ; -------------------------------------- + 1242 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] + 1243 ; -------------------------------------- + 1244 + 1245 431C A5 76 V2A1: LDA VALUE+LO + 1246 431E 85 63 STA ARG1+LO + 1247 4320 A5 77 LDA VALUE+HI + 1248 4322 85 64 STA ARG1+HI + 1249 4324 E6 62 INC NARGS + 1250 4326 60 RTS + 1251 + 1252 4327 END + 1253 + 1254 4327 INCLUDE SUBS.ASM + 1255 4327 STTL "--- OPCODE SUPPORT SUBROUTINES ---" + 1256 PAGE + Wed Jun 7 1989 12:04 Page 21 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1257 + 1258 ; ----------------------- + 1259 ; FETCH A SHORT IMMEDIATE + 1260 ; ----------------------- + 1261 + 1262 4327 A9 00 GETSHT: LDA #0 ; MSB IS ZERO + 1263 4329 F0 03 BEQ GETV ; FETCH LSB FROM Z-CODE + 1264 + 1265 + 1266 ; ---------------------- + 1267 ; FETCH A LONG IMMEDIATE + 1268 ; ---------------------- + 1269 + 1270 432B 20 24 92 GETLNG: JSR NEXTPC ; GRAB MSB + 1271 432E 85 77 GETV: STA VALUE+HI + 1272 4330 20 24 92 JSR NEXTPC ; GRAB LSB + 1273 4333 85 76 STA VALUE+LO + 1274 4335 60 RTS + 1275 + 1276 + 1277 ; ---------------- + 1278 ; FETCH A VARIABLE + 1279 ; ---------------- + 1280 ; FROM INSIDE AN OPCODE (VARIABLE ID IN [A]) + 1281 + 1282 4336 AA VARGET: TAX ; IF NON-ZERO, + 1283 4337 D0 0B BNE GETVR1 ; ACCESS A VARIABLE + 1284 4339 20 66 43 JSR POPVAL ; ELSE PULL VAR OFF Z-STACK + 1285 433C 4C 97 43 JMP PSHVAL ; WITHOUT ALTERING STACK + 1286 + 1287 ; FROM THE MAIN LOOP (VARIABLE ID IN Z-CODE) + 1288 + 1289 433F 20 24 92 GETVAR: JSR NEXTPC ; GRAB VAR-TYPE BYTE + 1290 4342 F0 22 BEQ POPVAL ; VALUE IS ON Z-STACK + 1291 + 1292 ; IS VARIABLE LOCAL OR GLOBAL? + 1293 + 1294 4344 C9 10 GETVR1: CMP #$10 ; IF LOW = 16, + 1295 4346 B0 0D BCS GETVRG ; IT'S GLOBAL + 1296 + 1297 ; HANDLE A LOCAL VARIABLE + 1298 + 1299 4348 0A GETVRL: ASL A ; WORD INDEX + 1300 4349 AA TAX ; INTO THE [LOCALS] TABLE + 1301 434A BD FE 1D LDA LOCALS-2+LO,X ; GRAB LSB + 1302 434D 85 76 STA VALUE+LO + 1303 434F BD FF 1D LDA LOCALS-2+HI,X ; AND MSB + 1304 4352 85 77 STA VALUE+HI + 1305 4354 60 RTS + 1306 ; + 1307 ; HANDLE A GLOBAL VARIABLE + 1308 ; + 1309 4355 GETVRG: + 1310 4355 20 14 44 jsr GVCALC ; GET ADDRESS OF GLOBAL INTO [FPC] + 1311 4358 20 5B 92 jsr FETCHB ; and get hi part + 1312 435B 85 77 sta VALUE+HI + 1313 435D 20 C3 8F jsr NEXTFPC ; and point to next part + 1314 4360 20 5B 92 jsr FETCHB ; and go get it + 1315 4363 85 76 sta VALUE+LO ; SAVE IT + 1316 4365 60 rts ; AND WE'RE DONE + 1317 + 1318 ; ---------------------------------- + 1319 ; POP Z-STACK INTO [VALUE] AND [X/A] + 1320 ; ---------------------------------- + 1321 ; ZSTACK DOUBLED IN SIZE FOR EZIP + 1322 ; SO THIS RTN ALL NEW + 1323 + 1324 4366 A5 AF POPVAL: LDA ZSP+LO ; IF ZSP+LO IS 0 + 1325 4368 D0 02 BNE POP1 + 1326 436A 85 B0 STA ZSP+HI ; MUST DEC. HI (HI = 0 OR 1 ONLY) + 1327 436C C6 AF POP1: DEC ZSP+LO ; THEN DEC ZSP LO + 1328 436E D0 04 BNE POP2 + 1329 4370 05 B0 ORA ZSP+HI ; LO + HI BOTH 0? + 1330 4372 F0 1E BEQ UNDER ; UNDERFLOW IF ZERO! + 1331 4374 A4 AF POP2: LDY ZSP+LO + Wed Jun 7 1989 12:04 Page 22 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1332 4376 A5 B0 LDA ZSP+HI + 1333 4378 F0 0C BEQ POP3 ; BOTTOM HALF OF ZSTACK + 1334 437A B9 00 0E LDA ZSTKTL,Y ; GET VALUE FROM TOP HALF + 1335 437D 85 76 STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + 1336 437F AA TAX + 1337 4380 B9 00 10 LDA ZSTKTH,Y + 1338 4383 85 77 STA VALUE+HI + 1339 4385 60 RTS + 1340 + 1341 4386 B9 00 0D POP3: LDA ZSTKBL,Y ; GET VALUE FROM BOTTOM HALF + 1342 4389 85 76 STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + 1343 438B AA TAX + 1344 438C B9 00 0F LDA ZSTKBH,Y + 1345 438F 85 77 STA VALUE+HI + 1346 4391 60 RTS + 1347 + 1348 ; *** ERROR #5 -- Z-STACK UNDERFLOW *** + 1349 4392 A9 05 UNDER: LDA #5 + 1350 4394 4C 0A 52 JMP ZERROR + 1351 + 1352 ; ----------------------- + 1353 ; PUSH [VALUE] TO Z-STACK + 1354 ; ----------------------- + 1355 + 1356 4397 A6 76 PSHVAL: LDX VALUE+LO + 1357 4399 A5 77 LDA VALUE+HI + 1358 + 1359 ; --------------------- + 1360 ; PUSH [X/A] TO Z-STACK + 1361 ; --------------------- + 1362 + 1363 439B 48 PUSHXA: PHA ; HOLD VALUE IN [A] A SEC. + 1364 439C A4 AF LDY ZSP+LO + 1365 439E A5 B0 LDA ZSP+HI + 1366 43A0 F0 0B BEQ PSHBOT ; ON BOTTOM HALF OF STACK + 1367 43A2 8A TXA + 1368 43A3 99 00 0E STA ZSTKTL,Y ; PUSH VALUE ONTO TOP HALF OF STACK + 1369 43A6 68 PLA + 1370 43A7 99 00 10 STA ZSTKTH,Y + 1371 43AA 4C B5 43 JMP PSHUPD ; NOW UPDATE POINTER + 1372 + 1373 43AD 8A PSHBOT: TXA ; PLACE VALUE ON ZSTACK + 1374 43AE 99 00 0D STA ZSTKBL,Y + 1375 43B1 68 PLA + 1376 43B2 99 00 0F STA ZSTKBH,Y + 1377 43B5 E6 AF PSHUPD: INC ZSP+LO ; UPDATE ZSTACK POINTER + 1378 43B7 D0 08 BNE PSHEX + 1379 43B9 A5 AF LDA ZSP+LO + 1380 43BB 05 B0 ORA ZSP+HI + 1381 43BD D0 03 BNE OVER ; OVERFLOW IF $200 + 1382 43BF E6 B0 INC ZSP+HI ; TO 1 + 1383 43C1 60 PSHEX: RTS + 1384 + 1385 ; *** ERROR #6 -- Z-STACK OVERFLOW *** + 1386 43C2 A9 06 OVER: LDA #6 + 1387 43C4 4C 0A 52 JMP ZERROR + 1388 + 1389 + 1390 ; -------------- + 1391 ; RETURN A VALUE + 1392 ; -------------- + 1393 ; FROM WITHIN AN OPCODE (VARIABLE ID IN [A]) + 1394 + 1395 43C7 AA VARPUT: TAX ; IF ZERO, + 1396 43C8 D0 1C BNE PUTVR1 + 1397 + 1398 ; FLUSH TOP WORD OFF STACK + 1399 ; AND REPLACE WITH [VALUE] + 1400 + 1401 43CA A5 AF LDA ZSP+LO ; IF ZSP+LO =0 + 1402 43CC D0 02 BNE VAR1 ; THEN HI =1 (GUARDED ELSEWHERE) + 1403 43CE 85 B0 STA ZSP+HI ; DECREMENT HI (ONLY 0 OR 1) + 1404 43D0 C6 AF VAR1: DEC ZSP+LO ; NOW DEC LOW BYTE + 1405 43D2 D0 C3 BNE PSHVAL + 1406 43D4 05 B0 ORA ZSP+HI + Wed Jun 7 1989 12:04 Page 23 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1407 43D6 F0 BA BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + 1408 43D8 D0 BD BNE PSHVAL + 1409 + 1410 ; RETURN A ZERO + 1411 43DA RET0: + 1412 43DA A9 00 lda #0 + 1413 43DC AA tax ; zero's all + 1414 ; + 1415 ; RETURN WORD IN [A], [X] (LO,HI) (EZIP EXPANDED TO A WORD) + 1416 ; + 1417 43DD PUTBYT: + 1418 43DD 85 76 STA VALUE+LO + 1419 43DF 86 77 STX VALUE+HI ; CLEAR MSB + 1420 ; + 1421 ; RETURN [VALUE] + 1422 ; + 1423 43E1 20 24 92 PUTVAL: JSR NEXTPC ; GET VARIABLE ID BYTE + 1424 43E4 F0 B1 BEQ PSHVAL ; [VALUE] GOES TO Z-STACK + 1425 ; + 1426 ; LOCAL OR GLOBAL VARIABLE? + 1427 ; + 1428 43E6 C9 10 PUTVR1: CMP #$10 ; IF LOW = 16, + 1429 43E8 B0 0D BCS PUTVLG ; IT'S GLOBAL + 1430 ; + 1431 ; PUT A LOCAL VARIABLE + 1432 ; + 1433 43EA 0A PUTVLL: ASL A ; WORD INDEX + 1434 43EB AA TAX ; INTO THE [LOCALS] TABLE + 1435 43EC A5 76 LDA VALUE+LO ; GRAB LSB + 1436 43EE 9D FE 1D STA LOCALS-2+LO,X ; SAVE IN LOCAL TABLE + 1437 43F1 A5 77 LDA VALUE+HI ; DO SAME TO + 1438 43F3 9D FF 1D STA LOCALS-2+HI,X ; MSB + 1439 43F6 60 RTS + 1440 ; + 1441 ; RETURN A GLOBAL VARIABLE + 1442 ; + 1443 43F7 PUTVLG: + 1444 43F7 20 14 44 JSR GVCALC ; put address in [FPC] + 1445 43FA A5 8E lda FPCBNK ; and move it to stash spot + 1446 43FC 85 91 sta SPCBNK + 1447 43FE A5 8D lda FPCH + 1448 4400 85 90 sta SPCH + 1449 4402 A5 8C lda FPCL + 1450 4404 85 8F sta SPCL + 1451 4406 A5 77 lda VALUE+HI ; GET MSB + 1452 4408 20 3A 92 jsr STASHB ; and save it + 1453 440B 20 A3 8F jsr NEXTSPC ; point to next byte + 1454 440E A5 76 lda VALUE+LO ; NOW GET LSB + 1455 4410 20 3A 92 jsr STASHB ; and send it out + 1456 4413 60 rts + 1457 + 1458 ; ----------------------- + 1459 ; CALC GLOBAL WORD OFFSET + 1460 ; ----------------------- + 1461 ; ENTRY: VAR-I BYTE (16-255) IN [A] + 1462 ; EXIT: ABSOLUTE ADDRESS OF GLOBAL VAR IN [FPC] + 1463 4414 GVCALC: + 1464 4414 38 sec ; time for a subtract + 1465 4415 E9 10 sbc #$10 ; FORM A ZERO-ALIGNED INDEX + 1466 4417 A0 00 ldy #0 ; MAKE SURE MSB OF OFFSET AND [Y] + 1467 4419 84 79 sty I+HI ; ARE CLEARED + 1468 441B 0A asl A ; MULTIPLY OFFSET BY 2 + 1469 441C 26 79 rol I+HI ; TO WORD-ALIGN IT + 1470 441E 18 clc ; ADD OFFSET TO ADDR OF GLOBAL TABLE + 1471 441F 65 50 adc GLOBAL+LO ; TO FORM THE ABSOLUTE + 1472 4421 85 8C sta FPCL ; ADDRESS OF THE + 1473 4423 A5 79 lda I+HI ; DESIRED GLOBAL VARIABLE + 1474 4425 65 51 adc GLOBAL+HI ; STORE ADDRESS BACK IN [FPC] + 1475 4427 20 7C 8F jsr SETPC ; now get memory page and bank + 1476 442A 85 8D sta FPCH ; hi part + 1477 442C 84 8E sty FPCBNK ; and bank + 1478 442E WCEX: + 1479 442E 60 rts + 1480 + 1481 + Wed Jun 7 1989 12:04 Page 24 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1482 ; --------------- + 1483 ; PREDICATE FAILS + 1484 ; --------------- + 1485 + 1486 442F 20 24 92 PREDF: JSR NEXTPC ; GET 1ST BRANCH BYTE + 1487 4432 10 0C BPL PREDB ; DO BRANCH IF BIT 7 OFF + 1488 + 1489 + 1490 ; ----------------------- + 1491 ; IGNORE PREDICATE BRANCH + 1492 ; ----------------------- + 1493 ; ENTRY: 1ST BRANCH BYTE IN [A] + 1494 + 1495 4434 29 40 PREDNB: AND #%01000000 ; TEST BIT 6 + 1496 4436 D0 F6 BNE WCEX ; SHORT BRANCH IF SET + 1497 4438 4C 24 92 JMP NEXTPC ; ELSE SKIP OVER 2ND BRANCH BYTE + 1498 + 1499 + 1500 ; ------------------ + 1501 ; PREDICATE SUCCEEDS + 1502 ; ------------------ + 1503 + 1504 443B 20 24 92 PREDS: JSR NEXTPC ; GET 1ST BRANCH BYTE + 1505 443E 10 F4 BPL PREDNB ; DON'T BRANCH IF BIT 7 CLEAR + 1506 + 1507 + 1508 ; -------------------------- + 1509 ; PERFORM A PREDICATE BRANCH + 1510 ; -------------------------- + 1511 ; ENTRY: 1ST PRED BYTE IN [A] + 1512 + 1513 4440 AA PREDB: TAX ; SAVE HERE + 1514 4441 29 40 AND #%01000000 ; LONG OR SHORT BRANCH? + 1515 4443 F0 0B BEQ PREDLB ; LONG IF BIT 6 IS CLEAR + 1516 + 1517 ; HANDLE A SHORT BRANCH + 1518 + 1519 4445 8A TXA ; RESTORE PRED BYTE + 1520 4446 29 3F AND #%00111111 ; FORM SHORT OFFSET + 1521 4448 85 76 STA VALUE+LO ; USE AS LSB OF BRANCH OFFSET + 1522 444A A9 00 LDA #0 + 1523 444C 85 77 STA VALUE+HI ; MSB OF OFFSET IS ZERO + 1524 444E F0 17 BEQ PREDB7 ; DO THE BRANCH + 1525 + 1526 ; HANDLE A LONG BRANCH + 1527 + 1528 4450 8A PREDLB: TXA ; RESTORE 1ST PRED BYTE + 1529 4451 29 3F AND #%00111111 ; FORM MSB OF OFFSET + 1530 4453 AA TAX ; SAVE HERE FOR REFERENCE + 1531 4454 29 20 AND #%00100000 ; CHECK SIGN OF 14-BIT VALUE + 1532 4456 F0 04 BEQ DOB2 ; POSITIVE IF ZERO, SO USE [X] + 1533 4458 8A TXA ; ELSE RESTORE BYTE + 1534 4459 09 E0 ORA #%11100000 ; EXTEND THE SIGN BIT + 1535 445B AA TAX ; BACK HERE FOR STORAGE + 1536 445C 86 77 DOB2: STX VALUE+HI + 1537 445E 20 24 92 JSR NEXTPC ; FETCH LSB OF 14-BIT OFFSET + 1538 4461 85 76 STA VALUE+LO + 1539 + 1540 ; BRANCH TO Z-ADDRESS IN [VALUE] + 1541 + 1542 4463 A5 77 PREDB1: LDA VALUE+HI ; CHECK MSB OF OFFSET + 1543 4465 D0 0E BNE PREDB3 ; DO BRANCH IF NZ + 1544 4467 A5 76 PREDB7: LDA VALUE+LO ; IF LSB IS NON-ZERO, + 1545 4469 D0 03 BNE PREDB2 ; MAKE SURE IT ISN'T 1 + 1546 446B 4C 66 79 JMP ZRFALS ; ELSE DO AN "RFALSE" + 1547 446E C9 01 PREDB2: CMP #1 ; IF OFFSET = 1 + 1548 4470 D0 03 BNE PREDB3 + 1549 4472 4C 5B 79 JMP ZRTRUE ; DO AN "RTRUE" + 1550 + 1551 ; ENTRY POINT FOR "JUMP" + 1552 + 1553 4475 A5 76 PREDB3: LDA VALUE+LO ; SUBTRACT 2 FROM OFFSET + 1554 4477 38 SEC ; IN [VALUE] + 1555 4478 E9 02 SBC #2 + 1556 447A AA TAX ;SAVE LO BYTE + Wed Jun 7 1989 12:04 Page 25 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1557 447B A5 77 LDA VALUE+HI + 1558 447D E9 00 SBC #0 + 1559 447F 85 78 STA I+LO ;MSB OF OFFSET = LSB OF [I] + 1560 4481 A0 00 LDY #0 ; CLEAR THE MSB + 1561 4483 84 79 STY I+HI ; OF [I] + 1562 4485 0A ASL A ; EXTEND THE SIGN OF OFFSET + 1563 4486 26 79 ROL I+HI ; INTO MSB OF [I] + 1564 4488 0A ASL A + 1565 4489 26 79 ROL I+HI ; (EZIP) + 1566 448B 0A asl A + 1567 448C 26 79 rol I+HI ; (YZIP) ??!! + 1568 448E 8A TXA ; GET LSB OF OFFSET + 1569 448F 65 80 ADC ZPCL ; ADD LOW 8 BITS OF ZPC + 1570 4491 90 06 BCC PREDB5 ; IF OVERFLOWED, + 1571 4493 E6 78 INC I+LO ; UPDATE UPPER 9 BITS + 1572 4495 D0 02 BNE PREDB5 + 1573 4497 E6 79 INC I+HI + 1574 4499 85 80 PREDB5: STA ZPCL ; UPDATE ZPC + 1575 449B A5 78 LDA I+LO ; IF UPPER 9 BITS ARE ZERO, + 1576 449D 05 79 ORA I+HI ; NO NEED TO CHANGE PAGES + 1577 449F F0 12 BEQ PREDB6 + 1578 44A1 A5 78 LDA I+LO ; ELSE CALC NEW UPPER BITS + 1579 44A3 18 CLC + 1580 44A4 65 81 ADC ZPCM + 1581 44A6 85 81 STA ZPCM + 1582 44A8 A5 79 LDA I+HI + 1583 44AA 65 82 ADC ZPCH + 1584 44AC 29 07 AND #%00000111 + 1585 44AE 85 82 STA ZPCH + 1586 44B0 4C AF 90 JMP VLDZPC ;MAKE VALID + 1587 44B3 PREDB6: + 1588 + 1589 ; FALL THROUGH ... + 1590 + 1591 ; ---- + 1592 ; NOOP + 1593 ; ---- + 1594 + 1595 44B3 60 ZNOOP: RTS + 1596 + 1597 + 1598 ; ---------------------- + 1599 ; MOVE [ARG1] TO [VALUE] + 1600 ; ---------------------- + 1601 + 1602 44B4 A5 63 A12VAL: LDA ARG1+LO + 1603 44B6 85 76 STA VALUE+LO + 1604 44B8 A5 64 LDA ARG1+HI + 1605 44BA 85 77 STA VALUE+HI + 1606 44BC 60 RTS + 1607 + 1608 + 1609 ; ----------------------------------- + 1610 ; INDICATE STATUS LINE REFRESH NEEDED + 1611 ; ----------------------------------- + 1612 + 1613 44BD AD 11 96 REFRSH: LDA ZBEGIN+ZFLAGS+1 ; PICK UP LOW BYTE OF FLAG WORD + 1614 44C0 09 04 ORA #%00000100 ; SET BIT 2 + 1615 44C2 8D 11 96 STA ZBEGIN+ZFLAGS+1 ; AND PUT IT BACK + 1616 44C5 60 RTS + 1617 + 1618 + 1619 ;DECJ RETURNS C=0 WHEN J=$FFFF + 1620 + 1621 44C6 A5 7A DECJ: LDA J+LO + 1622 44C8 38 SEC + 1623 44C9 E9 01 SBC #1 + 1624 44CB 85 7A STA J+LO + 1625 44CD A5 7B LDA J+HI + 1626 44CF E9 00 SBC #0 + 1627 44D1 85 7B STA J+HI + 1628 44D3 60 RTS + 1629 + 1630 44D4 END + 1631 + Wed Jun 7 1989 12:04 Page 26 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1632 44D4 INCLUDE DISPATCH.ASM + 1633 PAGE + Wed Jun 7 1989 12:04 Page 27 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1634 44D4 STTL "--- OPCODE DISPATCH TABLES ---" + 1635 + 1636 + 1637 ; 0-OPS + 1638 + 1639 44D4 79 OPT0H: DB >ZRTRUE ;B0 + 1640 44D5 79 DB >ZRFALS ;B1 + 1641 44D6 79 DB >ZPRI ;B2 + 1642 44D7 79 DB >ZPRR ;B3 + 1643 44D8 44 DB >ZNOOP ;B4 + 1644 44D9 8F DB >OSAVE ;B5 + 1645 44DA 8F DB >OREST ;B6 + 1646 44DB 52 DB >ZSTART ;B7 + 1647 44DC 79 DB >ZRSTAK ;B8 + 1648 44DD 79 DB >ZCATCH ;B9 + 1649 44DE 52 DB >ZQUIT ;BA + 1650 44DF 54 DB >ZZCRLF ;BB + 1651 44E0 55 DB >ZUSL ;BC + 1652 44E1 5B DB >ZVER ;BD + 1653 44E2 41 DB >ZEXTOP ;BE + 1654 44E3 79 DB >ZORIG ;BF + 1655 + 1656 44E4 5B OPT0L: DB ZZERO ;80,90,A0 + 1676 44F5 79 DB >ZNEXT ;81 + 1677 44F6 79 DB >ZFIRST ;82 + 1678 44F7 79 DB >ZLOC ;83 + 1679 44F8 7A DB >ZPTSIZ ;84 + 1680 44F9 7A DB >ZINC ;85 + 1681 44FA 7A DB >ZDEC ;86 + 1682 44FB 7A DB >ZPRB ;87 + 1683 44FC 7F DB >ZCALL1 ;88 (EZIP) + 1684 44FD 7A DB >ZREMOV ;89 + 1685 44FE 7B DB >ZPRD ;8A + 1686 44FF 7B DB >ZRET ;8B + 1687 4500 7B DB >ZJUMP ;8C + 1688 4501 7B DB >ZPRINT ;8D + 1689 4502 7B DB >ZVALUE ;8E + 1690 4503 7F DB >ZICLL1 ;8F + 1691 + 1692 4504 9B OPT1L: DB BADOP2 ;00 (UNDEFINED) + 1712 4515 7F DB >ZEQUAL ;01 + 1713 4516 7B DB >ZLESS ;02 + 1714 4517 7B DB >ZGRTR ;03 + 1715 4518 7B DB >ZDLESS ;04 + 1716 4519 7C DB >ZIGRTR ;05 + 1717 451A 7C DB >ZIN ;06 + 1718 451B 7C DB >ZBTST ;07 + 1719 451C 7C DB >ZBOR ;08 + 1720 451D 7C DB >ZBAND ;09 + 1721 451E 7C DB >ZFSETP ;0A + 1722 451F 7C DB >ZFSET ;0B + 1723 4520 7C DB >ZFCLR ;0C + 1724 4521 7C DB >ZSET ;0D + 1725 4522 7C DB >ZMOVE ;0E + 1726 4523 7D DB >ZGET ;0F + 1727 4524 7D DB >ZGETB ;10 + 1728 4525 7D DB >ZGETP ;11 + 1729 4526 7D DB >ZGETPT ;12 + 1730 4527 7E DB >ZNEXTP ;13 + 1731 4528 7E DB >ZADD ;14 + 1732 4529 7E DB >ZSUB ;15 + 1733 452A 7E DB >ZMUL ;16 + 1734 452B 7E DB >ZDIV ;17 + 1735 452C 7E DB >ZMOD ;18 + 1736 452D 7F DB >ZCALL2 ;19 (EZIP) + 1737 452E 7F DB >ZICLL2 ;1A + 1738 452F 4E DB >ZCOLOR ;1B + 1739 4530 7F DB >ZTHROW ;1C + 1740 4531 43 DB >BADOP2 ;1D + 1741 4532 43 DB >BADOP2 ;1E + 1742 4533 43 DB >BADOP2 ;1F + 1743 + 1744 4534 17 OPT2L: DB ZCALL ;E0 + 1780 4555 80 DB >ZPUT ;E1 + 1781 4556 80 DB >ZPUTB ;E2 + 1782 4557 80 DB >ZPUTP ;E3 + 1783 4558 85 DB >ZREAD ;E4 + Wed Jun 7 1989 12:04 Page 29 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE DISPATCH TABLES ---" + + 1784 4559 81 DB >ZPRC ;E5 + 1785 455A 81 DB >ZPRN ;E6 + 1786 455B 81 DB >ZRAND ;E7 + 1787 455C 82 DB >ZPUSH ;E8 + 1788 455D 82 DB >ZPOP ;E9 + 1789 455E 4D DB >ZSPLIT ;EA + 1790 455F 6E DB >ZSCRN ;EB + 1791 + 1792 ; (EZIPS FROM HERE ON) + 1793 4560 7F DB >ZXCALL ;EC + 1794 4561 57 DB >ZCLR ;ED + 1795 4562 57 DB >ZERASE ;EE + 1796 4563 56 DB >ZCURST ;EF + 1797 4564 57 DB >ZCURGT ;F0 + 1798 4565 70 DB >ZLIGHT ;F1 + 1799 4566 55 DB >ZBUFOUT ;F2 + 1800 4567 55 DB >ZDIRT ;F3 + 1801 4568 57 DB >ZDIRIN ;F4 (NOT IMPLEMENTED) + 1802 4569 4E DB >ZSOUND ;F5 + 1803 456A 5A DB >ZINPUT ;F6 + 1804 456B 82 DB >ZINTBL ;F7 + 1805 456C 83 DB >ZBCOM ;F8 + 1806 456D 7F DB >ZICALL ;F9 + 1807 456E 7F DB >ZIXCLL ;FA + 1808 456F 86 DB >ZLEX ;FB + 1809 4570 86 DB >ZWSTR ;FC + 1810 4571 83 DB >ZCOPYT ;FD + 1811 4572 58 DB >ZPRNTT ;FE + 1812 4573 84 DB >ZASSND ;FF + 1813 + 1814 4574 B7 OPTXL: DB ZSAVE ;100 + 1851 4595 8D DB >ZREST ;101 + 1852 4596 84 DB >ZSHIFT ;102 + 1853 4597 84 DB >ZASHFT ;103 + 1854 4598 58 DB >ZFONT ;104 + 1855 4599 73 DB >ZDISPL ;105 + 1856 459A 78 DB >ZPICNF ;106 + 1857 459B 79 DB >ZDCLR ;107 + 1858 459C 4E DB >ZMARG ;108 + Wed Jun 7 1989 12:04 Page 30 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE DISPATCH TABLES ---" + + 1859 459D 8F DB >ZISAVE ;109 + 1860 459E 8F DB >ZIREST ;10A + 1861 459F 42 DB >BADEXT ;10B - NOT USED + 1862 45A0 42 DB >BADEXT ;10C - NOT USED + 1863 45A1 42 DB >BADEXT ;10D - NOT USED + 1864 45A2 42 DB >BADEXT ;10E - NOT USED + 1865 45A3 42 DB >BADEXT ;10F - NOT USED + 1866 45A4 6E DB >ZWINPOS ;110 + 1867 45A5 6F DB >ZWINSIZE ;111 + 1868 45A6 70 DB >ZWINATTR ;112 + 1869 45A7 70 DB >ZWINGET ;113 + 1870 45A8 71 DB >ZSCROLL ;114 + 1871 45A9 84 DB >ZFSTACK ;115 + 1872 45AA 85 DB >ZMINFO ;116 + 1873 45AB 85 DB >ZMLIMIT ;117 + 1874 45AC 84 DB >ZXPUSH ;118 + 1875 45AD 71 DB >ZWINPUT ;119 + 1876 45AE 58 DB >ZPRINTF ;11A + 1877 45AF 85 DB >ZMENU ;11B + 1878 45B0 79 DB >ZPICSET ;11c + 1879 + 1880 001D EXTLEN EQU $-EXTOPH + 1881 + 1882 45B1 F4 EXTOPL: DB IOBUFF ; first 256 byte page + 2065 46FA 20 5D 48 jsr COPY_DATA ; and copy from IOBUFF to DBUFF + 2066 46FD E6 B7 inc DBUFF+HI ; point to next one + 2067 46FF A9 09 lda #>IOBUFF+1 ; next 256 byte page + 2068 4701 4C 5D 48 jmp COPY_DATA ; and copy it over + 2069 4704 GDBAD: + 2070 4704 4C 74 47 jmp DISK_FATAL ; just die then + 2071 4707 RETRY: + 2072 [01] IF CHECKSUM + 2073 DLINE RETRYING ; show me the way to go home + 2074 [00] ENDIF + 2075 + 2076 4707 C6 16 dec RETRIES ; count this try + 2077 4709 30 F9 bmi GDBAD ; it's dead jim + 2078 470B F0 2F beq RETRY0 ; ask for reset + 2079 470D C9 01 cmp #1 ; down to last time? + 2080 470F D0 61 bne RETRYX ; just try again + 2081 4711 AD DE 45 lda PSEEK+SM_FPOS+0 + 2082 4714 48 pha + 2083 4715 AD DF 45 lda PSEEK+SM_FPOS+1 + 2084 4718 48 pha + 2085 4719 AD E0 45 lda PSEEK+SM_FPOS+2 + 2086 471C 48 pha + 2087 471D A9 00 lda #0 ; seek to zero + 2088 471F 8D DE 45 sta PSEEK+SM_FPOS+0 ; save here for now + 2089 4722 8D DF 45 sta PSEEK+SM_FPOS+1 ; save here for now + 2090 4725 8D E0 45 sta PSEEK+SM_FPOS+2 ; save here for now + 2091 4728 SET_MARK PSEEK ; move to the block + 2092 4728 PRODOS $CE, PSEEK + 2093 4728 20 00 BF jsr $BF00 ; ProDOS handler + 2094 472B CE DB $CE ; ProDOS function code + 2095 472C DC45 DW PSEEK ; Function Parameter Block address + 2096 472E .MACEND + 2097 472E .MACEND + 2098 472E 68 pla + 2099 472F 8D E0 45 sta PSEEK+SM_FPOS+2 + 2100 4732 68 pla + 2101 4733 8D DF 45 sta PSEEK+SM_FPOS+1 + 2102 4736 68 pla + 2103 4737 8D DE 45 sta PSEEK+SM_FPOS+0 + 2104 473A 90 36 bcc RETRYX ; all done + 2105 473C RETRY0: + 2106 473C 48 pha ; save disk error + 2107 473D 20 A9 4C jsr SWAP2INFOW ; go to window zero + 2108 4740 DLINE RESEAT_MSG1 ; ask to move the disk around + 2109 4740 A2 2D ldx #RESEAT_MSG1 ; get other part of string + 2111 [01] IFMA 2 ; check to see if length passed in + 2112 ldy ; then just fetch it + 2113 [01] ELSE + 2114 4744 A0 1F ldy #RESEAT_MSG1L ; get length of string + 2115 [00] ENDIF + 2116 4746 20 6B 4C jsr DLINE ; print the string + 2117 4749 .MACEND + 2118 4749 AD CF 45 lda GMREF ; get ref num + 2119 474C CD 99 46 cmp GAME2REF ; game2? + 2120 474F D0 08 bne RETRY1 ; nope + 2121 4751 AC 89 46 ldy GAME2NML ; get length + Wed Jun 7 1989 12:04 Page 34 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2122 4754 B9 89 46 lda GAME2NM,Y ; and side # + 2123 4757 D0 06 bne RETRY2 ; and continue + 2124 4759 RETRY1: + 2125 4759 AC 77 46 ldy GAME1NML ; get length + 2126 475C B9 77 46 lda GAME1NM,Y ; and side # + 2127 475F RETRY2: + 2128 475F 20 82 5D jsr CHAR ; send char out there + 2129 4762 DLINE RESEAT_MSG2 ; and finish statement + 2130 4762 A2 4C ldx #RESEAT_MSG2 ; get other part of string + 2132 [01] IFMA 2 ; check to see if length passed in + 2133 ldy ; then just fetch it + 2134 [01] ELSE + 2135 4766 A0 18 ldy #RESEAT_MSG2L ; get length of string + 2136 [00] ENDIF + 2137 4768 20 6B 4C jsr DLINE ; print the string + 2138 476B .MACEND + 2139 476B 68 pla ; get disk error back + 2140 476C 20 8A 47 jsr DISK_ERR ; tell the error + 2141 476F 20 C9 4C jsr SWAPBACK ; back to current window + 2142 4772 RETRYX: + 2143 4772 18 clc ; show goodness + 2144 4773 60 rts ; and done + 2145 ; + 2146 ; this is the fatal error spot + 2147 ; + 2148 4774 DISK_FATAL: + 2149 4774 20 8A 47 jsr DISK_ERR ; print out problem + 2150 4777 DRIVE_ERR: + 2151 4777 A9 0E lda #14 + 2152 4779 4C 0A 52 jmp ZERROR ; DRIVE ACCESS ERROR + 2153 ; + 2154 ; this routine prints out the string associated with the error and + 2155 ; returns with the carry set, like most routines do when there is + 2156 ; an error. The error should be in [A]. + 2157 ; + 2158 477C 50 72 6F 44 4F UNK_DISK: db "ProDOS error $" + 4781 53 20 65 72 72 + 4786 6F 72 20 24 + 2159 000E UNK_DISKL EQU $-UNK_DISK + 2160 + 2161 478A DISK_ERR: + 2162 478A 48 pha ; save [A] + 2163 478B 20 A9 4C jsr SWAP2INFOW ; point to information window + 2164 478E 68 pla ; get it back + 2165 + 2166 478F A2 1B ldx #ELISTL ; scan the error table + 2167 4791 DSKE: + 2168 4791 DD 6E 6D cmp ELIST,X ; is it this one + 2169 4794 F0 16 beq DSKE1 ; ayyup + 2170 4796 CA dex ; now skip the address + 2171 4797 CA dex ; of the description + 2172 4798 CA dex ; point to next error number + 2173 4799 10 F6 bpl DSKE ; jump to start + 2174 ; + 2175 ; if we are here print out unknown error and it's value + 2176 ; + 2177 479B 48 pha ; save [A] + 2178 479C DLINE UNK_DISK ; show error + 2179 479C A2 7C ldx #UNK_DISK ; get other part of string + 2181 [01] IFMA 2 ; check to see if length passed in + 2182 ldy ; then just fetch it + 2183 [01] ELSE + 2184 47A0 A0 0E ldy #UNK_DISKL ; get length of string + 2185 [00] ENDIF + 2186 47A2 20 6B 4C jsr DLINE ; print the string + 2187 47A5 .MACEND + 2188 47A5 68 pla ; get [A] + 2189 47A6 20 D3 47 jsr HEXNUM ; print [A] + 2190 47A9 4C CB 47 jmp DSK_EXIT ; done + 2191 47AC DSKE1: + 2192 47AC E8 inx ; point to string address + 2193 47AD BD 6E 6D lda ELIST,X ; get lo part + 2194 47B0 85 7E sta L+LO ; save it + Wed Jun 7 1989 12:04 Page 35 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2195 47B2 E8 inx ; point to hi part + 2196 47B3 BD 6E 6D lda ELIST,X ; get hi part + 2197 47B6 AA tax ; save here + 2198 47B7 85 7F sta L+HI ; and here + 2199 47B9 A0 00 ldy #0 ; for offset + 2200 47BB B1 7E lda (L),Y ; get length of string + 2201 47BD A8 tay ; save in y + 2202 47BE E6 7E inc L+LO ; point past length + 2203 47C0 A5 7E lda L+LO ; get it + 2204 47C2 D0 01 bne DSKPR ; for printing + 2205 47C4 E8 inx ; wrapped + 2206 47C5 DSKPR: + 2207 47C5 8A txa ; hi part in a + 2208 47C6 A6 7E ldx L+LO ; lo part in X + 2209 47C8 20 6B 4C jsr DLINE ; print out message + 2210 47CB DSK_EXIT: + 2211 47CB 20 E0 8C jsr GETRET ; wait for RETURN + 2212 47CE 20 C9 4C jsr SWAPBACK ; all done + 2213 47D1 38 sec ; show badness again + 2214 47D2 60 rts ; and be done with it + 2215 ; + 2216 ; HEXNUM - print out the HEX value of [A] at the current cursor + 2217 ; location + 2218 ; + 2219 47D3 HEXNUM: + 2220 47D3 48 pha + 2221 47D4 4A lsr A + 2222 47D5 4A lsr A + 2223 47D6 4A lsr A + 2224 47D7 4A lsr A + 2225 47D8 20 DC 47 jsr NIB1 + 2226 47DB 68 pla + 2227 47DC NIB1: + 2228 47DC 29 0F and #%00001111 + 2229 47DE A8 tay + 2230 47DF B9 E6 47 lda HCHARS,Y + 2231 47E2 20 82 5D jsr CHAR ; print it out + 2232 47E5 60 rts + 2233 47E6 30 31 32 33 34 HCHARS: DB "0123456789ABCDEF" + 47EB 35 36 37 38 39 + 47F0 41 42 43 44 45 + 47F5 46 + 2234 + 2235 ; ---------------------- + 2236 ; WRITE [DBUFF] TO DISK + 2237 ; ---------------------- + 2238 ; ENTRY: File already open and positioned, ready to be written to + 2239 ; from page in (DBUFF). Writes out 512bytes, starting @ DBUFF. + 2240 ; EXIT: CARRY CLEAR IF OKAY, SET IF FAILED + 2241 + 2242 47F6 PUTDSK: + 2243 47F6 A6 B8 ldx DSKBNK ; get bank + 2244 47F8 A0 00 ldy #0 ; clear Y + 2245 47FA A9 08 lda #>IOBUFF ; first buffer + 2246 47FC 20 EE 00 jsr SAVE_DATA ; and copy from DBUFF to IOBUFF + 2247 + 2248 [01] IF CHECKSUM == 1 + 2249 lda #>IOBUFF + 2250 jsr CKS_BLOCK + 2251 [00] ENDIF + 2252 + 2253 47FF 20 34 48 jsr NEXT_DBUFF ; point to next buffer + 2254 4802 A6 B8 ldx DSKBNK ; go get new DSKBNK + 2255 4804 A0 00 ldy #0 ; clear Y again + 2256 4806 A9 09 lda #>IOBUFF+1 ; top part + 2257 4808 20 EE 00 jsr SAVE_DATA ; copy to IOBUFF + 2258 + 2259 [01] IF CHECKSUM == 1 + 2260 lda #>IOBUFF+1 + 2261 jsr CKS_BLOCK + 2262 [00] ENDIF + 2263 + 2264 480B 20 34 48 jsr NEXT_DBUFF ; count buffer + 2265 480E 4C 4F 48 jmp WRITE_DOS ; and now write it + 2266 ; --------------------- + Wed Jun 7 1989 12:04 Page 36 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2267 ; READ DBLOCK FROM DISK + 2268 ; --------------------- + 2269 ; CALLED BY RESTORE + 2270 ; ENTER: with file already set up as it DBUFF + 2271 ; L+LO == # of 256k blocks to read + 2272 ; + 2273 4811 GETRES: + 2274 4811 A5 7E lda L+LO ; get # of blocks + 2275 4813 8D D3 45 sta READ_PB+RD_BUFFLEN+HI + 2276 4816 20 56 48 jsr READ_DOS + 2277 4819 A2 02 ldx #>PAGELEN ; get starting number of pages + 2278 481B 8E D3 45 stx READ_PB+RD_BUFFLEN+HI + 2279 481E 90 01 bcc GTROK ; everything is fine + 2280 4820 60 rts ; error if c == set + 2281 4821 GTROK: + 2282 4821 A9 08 lda #>IOBUFF ; start at first block + 2283 4823 85 7F sta L+HI ; we can use L+HI + 2284 4825 GTRLOOP: + 2285 4825 A5 7F lda L+HI ; doing this block + 2286 + 2287 [01] IF CHECKSUM == 1 + 2288 jsr CKS_BLOCK ; check check sum + 2289 [00] ENDIF + 2290 + 2291 4827 20 5D 48 jsr COPY_DATA ; and copy from IOBUFF to DBUFF + 2292 482A 20 34 48 jsr NEXT_DBUFF ; check for wrap + 2293 482D E6 7F inc L+HI ; count this block + 2294 482F C6 7E dec L+LO ; count this block + 2295 4831 D0 F2 bne GTRLOOP ; do next one + 2296 4833 60 rts ; all finished + 2297 ; + 2298 ; NEXT_DBUFF + 2299 ; increment DBUFF to count the 2 pages done + 2300 ; + 2301 4834 NEXT_DBUFF: + 2302 4834 E6 B7 inc DBUFF+HI ; point to next page + 2303 4836 A5 B7 lda DBUFF+HI ; see where we are + 2304 4838 C9 BF cmp #>PRGLBL ; wrapping? + 2305 483A D0 10 bne GTREX ; okay then + 2306 483C A5 B8 lda DSKBNK ; which bank we be in + 2307 483E D0 06 bne GTR1 ; aux, so go to page 3 + 2308 4840 E6 B8 inc DSKBNK ; point to aux + 2309 4842 A9 40 lda #Z2PAGE ; start of page 2 + 2310 4844 D0 06 bne GTREX ; so tell me which page + 2311 4846 GTR1: + 2312 4846 A9 FF lda #P3BANK ; show page 3 bank + 2313 4848 85 B8 sta DSKBNK ; okay + 2314 484A A9 D0 lda #Z3PAGE ; page 3 of things + 2315 484C GTREX: + 2316 484C 85 B7 sta DBUFF+HI ; saved + 2317 484E 60 rts ; all done + 2318 ; + 2319 484F WRITE_DOS: + 2320 484F WRITE WRITE_SV ; write out save buffer + 2321 484F PRODOS $CB, WRITE_SV + 2322 484F 20 00 BF jsr $BF00 ; ProDOS handler + 2323 4852 CB DB $CB ; ProDOS function code + 2324 4853 0D8B DW WRITE_SV ; Function Parameter Block address + 2325 4855 .MACEND + 2326 4855 .MACEND + 2327 4855 60 rts ; done + 2328 4856 READ_DOS: + 2329 4856 READ READ_PB ; read it + 2330 4856 PRODOS $CA, READ_PB + 2331 4856 20 00 BF jsr $BF00 ; ProDOS handler + 2332 4859 CA DB $CA ; ProDOS function code + 2333 485A CE45 DW READ_PB ; Function Parameter Block address + 2334 485C .MACEND + 2335 485C .MACEND + 2336 485C 60 rts ; go home + 2337 ; + 2338 ; COPY_DATA - + 2339 ; now move the data from iobuff to dbuff (in some bank) + 2340 ; which part of IOBUFF is in [a] ($08 - $0B) + 2341 ; + Wed Jun 7 1989 12:04 Page 37 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2342 485D COPY_DATA: + 2343 485D 8D 79 48 sta SDLP3+2 ; self-modify code to get from IOBUFF + 2344 4860 8D 02 C0 sta RDBNK+MAIN ; read from main + 2345 4863 A6 B8 ldx DSKBNK ; get which bank it's going to + 2346 4865 30 05 bmi CPD1 ; oh oh, third bank + 2347 4867 9D 04 C0 sta WRTBNK,X ; and select that bank for writing + 2348 486A 10 07 bpl CPD2 ; okay, bank selected + 2349 486C CPD1: + 2350 486C A5 B7 lda DBUFF+HI ; get from this zero page + 2351 486E 8D 09 C0 sta ALTZP+AUX ; talk about aux mem + 2352 4871 85 B7 sta DBUFF+HI ; and save this in aux mem ZP + 2353 4873 CPD2: + 2354 4873 A0 00 ldy #0 ; start at beginning + 2355 4875 84 B6 sty DBUFF+LO ; just to be sure + 2356 4877 SDLP3: + 2357 4877 B9 00 08 lda IOBUFF,Y ; this becomes modified! + 2358 487A 91 B6 sta (DBUFF),Y ; to [DBUFF] + 2359 487C C8 iny + 2360 487D D0 F8 bne SDLP3 + 2361 487F 8D 08 C0 sta ALTZP+MAIN ; talk about main page again + 2362 4882 8D 04 C0 sta WRTBNK+MAIN ; end up back at main + 2363 4885 60 rts + 2364 ; + 2365 ; Segment table handling routines + 2366 ; + 2367 + 2368 ; + 2369 ; FINDSEG - find the Virtual page in DBLOCK by searching through + 2370 ; the SEGTBL. + 2371 ; + 2372 4886 DISKPAGE: ds 2 ; spot to put starting disk page + 2373 4888 BIGPAGE: ds 2 ; DBLOCK/2 for 512 pages + 2374 488A FINDSEG: + 2375 488A AD 5F 6C lda DBLOCK+HI ; work with MSB first + 2376 488D 4A lsr A ; /2 + 2377 488E 8D 89 48 sta BIGPAGE+HI + 2378 4891 AD 5E 6C lda DBLOCK+LO ; now LSB + 2379 4894 6A ror A ; /2 + 2380 4895 8D 88 48 sta BIGPAGE+LO + 2381 4898 AD 88 46 lda GAME1NUM ; get number for disk 1 + 2382 489B 20 01 49 jsr SCANSEG ; scan through the current disk table + 2383 489E AD 87 46 lda GAME1REF ; save refnum + 2384 48A1 90 0E bcc FNDSG1 ; found it, figger it out + 2385 48A3 AD 9A 46 lda GAME2NUM ; get number for disk 2 + 2386 48A6 20 01 49 jsr SCANSEG ; see if it is here + 2387 48A9 AD 99 46 lda GAME2REF ; save refnum + 2388 48AC 90 03 bcc FNDSG1 ; ayyup + 2389 48AE 20 79 49 jsr SEGQUEST ; get correct disk/file with segment + 2390 48B1 FNDSG1: + 2391 48B1 8D DD 45 sta PSEEK+SM_REFNUM ; for seeking + 2392 48B4 8D CF 45 sta GMREF ; and for reading + 2393 48B7 B1 1E lda (DSEGS),Y ; pick up MSB of disk page + 2394 48B9 8D 87 48 sta DISKPAGE+HI ; save it + 2395 48BC C8 iny ; point to LSB + 2396 48BD B1 1E lda (DSEGS),Y ; get it + 2397 48BF 8D 86 48 sta DISKPAGE+LO ; save it + 2398 ; now point to Starting page again + 2399 48C2 88 dey + 2400 48C3 88 dey + 2401 48C4 88 dey + 2402 48C5 88 dey + 2403 48C6 AD 88 48 lda BIGPAGE+LO ; LSB of desired page + 2404 48C9 38 sec ; doing subtract + 2405 48CA F1 1E sbc (DSEGS),Y ; get rid of LSB of starting page + 2406 48CC 8D DF 45 sta PSEEK+SM_FPOS+1 ; save here for now + 2407 48CF 88 dey ; point to MSB of starting page + 2408 48D0 AD 89 48 lda BIGPAGE+HI ; get DBLOCK MSB + 2409 48D3 F1 1E sbc (DSEGS),Y ; get offset + 2410 48D5 8D E0 45 sta PSEEK+SM_FPOS+2 ; save here temporarily + 2411 48D8 18 clc ; now add offset to starting disk page + 2412 48D9 AD 86 48 lda DISKPAGE+LO ; get starting disk page + 2413 48DC 6D DF 45 adc PSEEK+SM_FPOS+1 ; add inter-segment offset + 2414 48DF 8D DF 45 sta PSEEK+SM_FPOS+1 ; save LSB + 2415 48E2 AD 87 48 lda DISKPAGE+HI ; get MSB of segment disk page + 2416 48E5 6D E0 45 adc PSEEK+SM_FPOS+2 ; add inter-segment offset + Wed Jun 7 1989 12:04 Page 38 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2417 48E8 8D E0 45 sta PSEEK+SM_FPOS+2 ; save MSB of disk page + 2418 48EB 0E DF 45 asl PSEEK+SM_FPOS+1 ; *2 for 256Kb pages + 2419 48EE 2E E0 45 rol PSEEK+SM_FPOS+2 ; okay, we did + 2420 48F1 AD 5E 6C lda DBLOCK+LO ; check to see which page in 512 we are + 2421 48F4 29 01 and #$01 ; if odd, then add one more + 2422 48F6 F0 08 beq FNDEX ; all done then + 2423 48F8 EE DF 45 inc PSEEK+SM_FPOS+1 ; one more page + 2424 48FB D0 03 bne FNDEX ; all done if no wrap + 2425 48FD EE E0 45 inc PSEEK+SM_FPOS+2 ; nother page + 2426 4900 FNDEX: + 2427 4900 60 rts ; done + 2428 ; + 2429 ; SCANSEG - look through the current segment table for the desired + 2430 ; address found in BIGPAGE. Return with Y pointing to disk page + 2431 ; and carry cleared if found. Otherwise, return carry set. + 2432 ; [A] = which side number we are checking (0-n) + 2433 ; + 2434 4901 SCANSEG: + 2435 4901 48 pha ; save which disk + 2436 4902 0A asl A ; make word index + 2437 4903 AA tax ; make it an index + 2438 4904 BD D0 1D lda DSKSEG+LO,X ; get LSB + 2439 4907 85 1E sta DSEGS+LO + 2440 4909 BD D1 1D lda DSKSEG+HI,X + 2441 490C 85 1F sta DSEGS+HI + 2442 490E A0 05 ldy #SGTNSEG+1 ; point to segment count + 2443 4910 B1 1E lda (DSEGS),Y ; get it + 2444 4912 AA tax ; use x as counter + 2445 4913 68 pla ; get which side + 2446 4914 A8 tay ; is it side zero + 2447 4915 D0 04 bne SCANSG1 ; nope + 2448 4917 A0 0E ldy #SGTSEG+6 ; skip first entry, cuz they're preload + 2449 4919 D0 02 bne SCANNING ; okay ready to go + 2450 491B SCANSG1: + 2451 491B A0 08 ldy #SGTSEG ; begin at beginning + 2452 491D SCANNING: + 2453 491D B1 1E lda (DSEGS),Y ; get MSB of start + 2454 491F CD 89 48 cmp BIGPAGE+HI ; check against block we want + 2455 4922 F0 06 beq SCAN1 ; might be okay + 2456 4924 90 0F bcc SCAN2 ; PAGE > start seg, check end seg + 2457 4926 C8 iny ; LSB of start + 2458 4927 SCAN0: + 2459 4927 C8 iny ; MSB of end + 2460 4928 B0 1F bcs NEXTSEG ; not this one + 2461 492A SCAN1: + 2462 492A C8 iny ; point to LSB of start + 2463 492B B1 1E lda (DSEGS),Y ; get LSB + 2464 492D CD 88 48 cmp BIGPAGE+LO ; check against desired LSB + 2465 4930 F0 20 beq GOTSEG ; we found it + 2466 4932 B0 F3 bcs SCAN0 ; DBLOCK LSB < then start LSB, not found + 2467 4934 88 dey ; point back to MSB of start + 2468 4935 SCAN2: + 2469 4935 C8 iny ; LSB of start + 2470 4936 C8 iny ; MSB of end + 2471 4937 B1 1E lda (DSEGS),Y ; get MSB of end + 2472 4939 CD 89 48 cmp BIGPAGE+HI ; check against DBLOCK MSB + 2473 493C 90 0B bcc NEXTSEG ; end < DBLOCK, check next segment + 2474 493E D0 13 bne GOTSEG1 ; end > DBLOCK, must be in this segment + 2475 4940 C8 iny ; point to end LSB + 2476 4941 B1 1E lda (DSEGS),Y ; get LSB + 2477 4943 CD 88 48 cmp BIGPAGE+LO ; how does it compare to desired LSB + 2478 4946 B0 0C bcs GOTSEG2 ; it's <= end, so it is here + 2479 4948 88 dey ; point back to MSB + 2480 4949 NEXTSEG: + 2481 4949 C8 iny ; point to LSB of end + 2482 494A C8 iny ; MSB of disk page + 2483 494B C8 iny ; LSB of disk page + 2484 494C C8 iny ; MSB of next start page + 2485 494D CA dex ; count this segment + 2486 494E D0 CD bne SCANNING ; check this segment + 2487 + 2488 4950 38 sec ; show not on this disk + 2489 4951 60 rts ; and done + 2490 4952 GOTSEG: + 2491 4952 C8 iny ; MSB of end page + Wed Jun 7 1989 12:04 Page 39 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2492 4953 GOTSEG1: + 2493 4953 C8 iny ; LSB of end page + 2494 4954 GOTSEG2: + 2495 4954 C8 iny ; MSB of disk offset + 2496 4955 18 clc ; show we found it + 2497 4956 60 rts ; all done + 2498 ; + 2499 ; SEGQUEST - find the correct disk/file with the desired page on + 2500 ; it. Returns SCANSEG's stuff. + 2501 ; + 2502 4957 DISKCNTR: ds 1 ; disk count down + 2503 4958 PAGENF: + 2504 4958 50 61 67 65 20 db "Page not found in segment table: " + 495D 6E 6F 74 20 66 + 4962 6F 75 6E 64 20 + 4967 69 6E 20 73 65 + 496C 67 6D 65 6E 74 + 4971 20 74 61 62 6C + 4976 65 3A 20 + 2505 0021 PAGENFL EQU $-PAGENF + 2506 4979 SEGQUEST: + 2507 4979 A9 01 lda #1 ; start at first disk + 2508 497B 8D 57 49 sta DISKCNTR ; init counter + 2509 497E SEGQL: + 2510 497E AD 57 49 lda DISKCNTR ; get disk + 2511 4981 CD 01 19 cmp SEGTBL+SGTDISKS+1 ; looked at all the disks? + 2512 4984 D0 24 bne SEGQL1 ; nope + 2513 ; + 2514 ; as a last resort, check disk 1, the boot disk + 2515 ; + 2516 4986 A9 00 lda #0 ; set up DISKCNTR + 2517 4988 8D 57 49 sta DISKCNTR ; we did + 2518 498B 20 01 49 jsr SCANSEG ; see if it is there + 2519 498E 90 27 bcc SEGQ1 ; we found it + 2520 + 2521 4990 DLINE PAGENF ; page not found + 2522 4990 A2 58 ldx #PAGENF ; get other part of string + 2524 [01] IFMA 2 ; check to see if length passed in + 2525 ldy ; then just fetch it + 2526 [01] ELSE + 2527 4994 A0 21 ldy #PAGENFL ; get length of string + 2528 [00] ENDIF + 2529 4996 20 6B 4C jsr DLINE ; print the string + 2530 4999 .MACEND + 2531 4999 AD 89 48 lda BIGPAGE+HI ; show MSB + 2532 499C 20 D3 47 jsr HEXNUM ; printed + 2533 499F AD 88 48 lda BIGPAGE+LO ; and LSB + 2534 49A2 20 D3 47 jsr HEXNUM ; we did + 2535 + 2536 49A5 A9 11 lda #17 ; bad page + 2537 49A7 4C 0A 52 jmp ZERROR ; die a horrible death + 2538 49AA SEGQL1: + 2539 49AA AD 57 49 lda DISKCNTR ; get which disk we be working on + 2540 49AD 20 01 49 jsr SCANSEG ; find out if it is here + 2541 49B0 90 05 bcc SEGQ1 ; it is, so open up file + 2542 49B2 EE 57 49 inc DISKCNTR ; not in this disk + 2543 49B5 D0 C7 bne SEGQL ; and try again + 2544 ; + 2545 ; we have found the disk it is in, so ask for it if necessary + 2546 ; + 2547 49B7 SEGQ1: + 2548 49B7 98 tya ; save the y pointer + 2549 49B8 48 pha ; it is saved + 2550 49B9 AD 57 49 lda DISKCNTR ; get which disk we found it under + 2551 49BC 20 C6 49 jsr FETCH_FILE ; go get the disk desired + 2552 49BF 68 pla ; get the Y reg back + 2553 49C0 A8 tay ; and show it + 2554 49C1 AD CF 45 lda GMREF ; get reference number again + 2555 49C4 60 rts ; all done + 2556 ; + 2557 ; FETCH_FILE: check to see if we can open GAMEFILE# (where # is in [A]) + 2558 ; if not, ask for DISK#. + 2559 ; + 2560 49C5 00 SAVENUM: db 0 ; spot to save ascii number + Wed Jun 7 1989 12:04 Page 40 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2561 49C6 FETCH_FILE: + 2562 49C6 18 clc ; adding to make + 2563 49C7 69 30 adc #$30 ; it an ascii number + 2564 49C9 8D C5 49 sta SAVENUM ; just save a minute + 2565 49CC EE C5 49 inc SAVENUM ; make name be one based + 2566 49CF AE 77 46 ldx GAME1NML ; get length of name + 2567 49D2 AD C5 49 lda SAVENUM ; get name back + 2568 49D5 C9 33 cmp #'3' ; are we looking for disk 1 or 2? + 2569 49D7 B0 18 bcs FEFI1 ; disks 3 and up handled special + 2570 49D9 FEFI00: + 2571 49D9 DD 77 46 cmp GAME1NM,X ; is it the current open one? + 2572 49DC D0 05 bne FEFI0 ; nope, so we need to open it + 2573 49DE AC 87 46 ldy GAME1REF ; get game 1 refnum + 2574 49E1 D0 35 bne FEFIX ; all set, so point to it + 2575 49E3 FEFI0: + 2576 49E3 20 E1 4A jsr DO_GAME1 ; handle it special + 2577 49E6 AD 87 46 lda GAME1REF ; fetch refnum + 2578 49E9 20 20 76 jsr GET_PDATA ; now get the picture data + 2579 49EC AC 87 46 ldy GAME1REF ; refetch refnum + 2580 49EF D0 27 bne FEFIX ; so all done + 2581 49F1 FEFI1: + 2582 49F1 AE 89 46 ldx GAME2NML ; get length of second name + 2583 49F4 DD 89 46 cmp GAME2NM,X ; how bout second open file? + 2584 49F7 D0 05 bne FEFI2 ; nope, so we need to open it + 2585 49F9 AC 99 46 ldy GAME2REF ; it is second one, so show me + 2586 49FC D0 1A bne FEFIX ; it is open too + 2587 49FE FEFI2: + 2588 49FE AD 99 46 lda GAME2REF ; get its refnum + 2589 4A01 F0 09 beq FEFI20 ; nothing to close, thank you + 2590 4A03 8D 0C 8B sta CLOSE_PB+CL_REFNUM ; show close who to close + 2591 4A06 CLOSE CLOSE_PB ; close it up tight + 2592 4A06 PRODOS $CC, CLOSE_PB + 2593 4A06 20 00 BF jsr $BF00 ; ProDOS handler + 2594 4A09 CC DB $CC ; ProDOS function code + 2595 4A0A 0B8B DW CLOSE_PB ; Function Parameter Block address + 2596 4A0C .MACEND + 2597 4A0C .MACEND + 2598 4A0C FEFI20: + 2599 4A0C 20 1F 4A jsr OPEN_GAME2 ; open up GAME2 file + 2600 4A0F AD 99 46 lda GAME2REF ; get refnum for this file + 2601 4A12 20 20 76 jsr GET_PDATA ; now get the picture data + 2602 4A15 AC 99 46 ldy GAME2REF ; get ref back, please + 2603 4A18 FEFIX: + 2604 4A18 8C DD 45 sty PSEEK+SM_REFNUM ; for seeking + 2605 4A1B 8C CF 45 sty GMREF ; and for reading + 2606 4A1E 60 rts ; did it + 2607 ; + 2608 ; OPEN_GAME2 - open up the file that GAME2NM is pointing to, + 2609 ; returning the REFNUM in [A], after storing in GAME2REF, + 2610 ; and the 2 picture structures + 2611 ; + 2612 4A1F OPEN_GAME2: + 2613 4A1F AE 89 46 ldx GAME2NML ; get end of name + 2614 4A22 AD C5 49 lda SAVENUM ; get new name + 2615 4A25 9D 89 46 sta GAME2NM,X ; using second file + 2616 4A28 A9 46 lda #>GAME2NM ; get lo byte + 2617 4A2A 8D D8 45 sta OPEN_FILE+OP_PATHNAME+HI + 2618 4A2D A9 89 lda #GAME2FIO ; now set up file i/o buffer + 2621 4A34 8D DA 45 sta OPEN_FILE+OP_FILEBUFF+HI + 2622 4A37 A9 00 lda #0 if multi disk game + 2638 + 2639 4A56 SET_GAMEPRE: + 2640 4A56 20 A9 4C jsr SWAP2INFOW ; point to info window + 2641 4A59 AD 55 4A lda SWAPPED ; are we swapping disks? + 2642 4A5C F0 0B beq SETGP ; nope, don't change game prefix + 2643 4A5E AD C5 49 lda SAVENUM ; get which disk to put it + 2644 4A61 AC 9B 46 ldy GAMEPL ; get length of prefix + 2645 4A64 88 dey ; subtract 2 to point to prefix + 2646 4A65 88 dey ; number + 2647 4A66 99 9C 46 sta GAMEP,Y ; set number for prefix + 2648 4A69 SETGP: + 2649 4A69 A9 46 lda #>GAMEPL ; set up parm block + 2650 4A6B 8D E3 45 sta SET_PB+SP_PATHNAME+HI + 2651 4A6E A9 9B lda #SWAPSAVE ; get other part of string + 2670 [01] IFMA 2 ; check to see if length passed in + 2671 ldy ; then just fetch it + 2672 [01] ELSE + 2673 4A84 A0 20 ldy #SWAPSAVEL ; get length of string + 2674 [00] ENDIF + 2675 4A86 20 6B 4C jsr DLINE ; print the string + 2676 4A89 .MACEND + 2677 4A89 AD 55 4A lda SWAPPED ; should we ask for specific disk? + 2678 4A8C D0 15 bne SEGTP01 ; yes, so ask for it + 2679 4A8E DLINE NOSWAP ; no, so just get game disk + 2680 4A8E A2 04 ldx #NOSWAP ; get other part of string + 2682 [01] IFMA 2 ; check to see if length passed in + 2683 ldy ; then just fetch it + 2684 [01] ELSE + 2685 4A92 A0 0A ldy #NOSWAPL ; get length of string + 2686 [00] ENDIF + 2687 4A94 20 6B 4C jsr DLINE ; print the string + 2688 4A97 .MACEND + 2689 4A97 4C D8 4A jmp SEGTP03 ; and continue + 2690 4A9A SEGTP00: + 2691 4A9A DLINE INS_MSG ; ask for game disk + 2692 4A9A A2 0E ldx #INS_MSG ; get other part of string + 2694 [01] IFMA 2 ; check to see if length passed in + 2695 ldy ; then just fetch it + 2696 [01] ELSE + 2697 4A9E A0 08 ldy #INS_MSGL ; get length of string + 2698 [00] ENDIF + 2699 4AA0 20 6B 4C jsr DLINE ; print the string + 2700 4AA3 .MACEND + 2701 4AA3 SEGTP01: + 2702 4AA3 DLINE GAME, GAMEL ; this is the name of the game + 2703 4AA3 A2 68 ldx #GAME ; get other part of string + 2705 [01] IFMA 2 ; check to see if length passed in + 2706 4AA7 AC 67 46 ldy GAMEL ; then just fetch it + 2707 [01] ELSE + 2708 ldy #GAMEL ; get length of string + 2709 [00] ENDIF + 2710 4AAA 20 6B 4C jsr DLINE ; print the string + Wed Jun 7 1989 12:04 Page 42 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2711 4AAD .MACEND + 2712 4AAD DLINE SIDEMSG ; part 2 of message + 2713 4AAD A2 16 ldx #SIDEMSG ; get other part of string + 2715 [01] IFMA 2 ; check to see if length passed in + 2716 ldy ; then just fetch it + 2717 [01] ELSE + 2718 4AB1 A0 07 ldy #SIDEMSGL ; get length of string + 2719 [00] ENDIF + 2720 4AB3 20 6B 4C jsr DLINE ; print the string + 2721 4AB6 .MACEND + 2722 4AB6 AD C5 49 lda SAVENUM ; get which disk to put it + 2723 4AB9 20 82 5D jsr CHAR ; print it out + 2724 4ABC DLINE DRIVE_MSG ; tell about drive + 2725 4ABC A2 1D ldx #DRIVE_MSG ; get other part of string + 2727 [01] IFMA 2 ; check to see if length passed in + 2728 ldy ; then just fetch it + 2729 [01] ELSE + 2730 4AC0 A0 10 ldy #DRIVE_MSGL ; get length of string + 2731 [00] ENDIF + 2732 4AC2 20 6B 4C jsr DLINE ; print the string + 2733 4AC5 .MACEND + 2734 4AC5 A9 32 lda #'2' ; assume it's drive 2 + 2735 4AC7 AE C5 49 ldx SAVENUM ; get which disk we want + 2736 4ACA E0 33 cpx #'3' ; >= side 3, must be disk drive 2 + 2737 4ACC B0 02 bcs SEGTP02 ; fine, send that message out + 2738 4ACE A9 31 lda #'1' ; ask for drive 1 then + 2739 4AD0 SEGTP02: + 2740 4AD0 20 82 5D jsr CHAR ; save which drive + 2741 4AD3 A9 2E lda #'.' ; finish sentence + 2742 4AD5 20 82 5D jsr CHAR ; okay + 2743 4AD8 SEGTP03: + 2744 4AD8 20 E0 8C jsr GETRET ; wait for + 2745 4ADB 4C 73 4A jmp SETGP0 ; try again + 2746 4ADE SETGP1: + 2747 4ADE 4C C9 4C jmp SWAPBACK ; pointing to disk + 2748 ; + 2749 ; DO_GAME1 - open up the special game 1 file and point to it + 2750 ; + 2751 4AE1 DO_GAME1: + 2752 4AE1 AC 87 46 ldy GAME1REF ; get the current game 1 ref num + 2753 4AE4 F0 0B beq DOG1 ; not currently open + 2754 4AE6 48 pha ; save Name + 2755 4AE7 8C 0C 8B sty CLOSE_PB+CL_REFNUM ; show close + 2756 4AEA CLOSE CLOSE_PB ; and close it + 2757 4AEA PRODOS $CC, CLOSE_PB + 2758 4AEA 20 00 BF jsr $BF00 ; ProDOS handler + 2759 4AED CC DB $CC ; ProDOS function code + 2760 4AEE 0B8B DW CLOSE_PB ; Function Parameter Block address + 2761 4AF0 .MACEND + 2762 4AF0 .MACEND + 2763 4AF0 68 pla ; get name back + 2764 4AF1 DOG1: + 2765 4AF1 AE 77 46 ldx GAME1NML ; get length of name + 2766 4AF4 AD C5 49 lda SAVENUM ; get new number + 2767 4AF7 9D 77 46 sta GAME1NM,X ; save name + 2768 4AFA 48 pha ; save it for later use + 2769 4AFB A9 46 lda #>GAME1NM ; get lo byte + 2770 4AFD 8D D8 45 sta OPEN_FILE+OP_PATHNAME+HI + 2771 4B00 A9 77 lda #GAME1FIO ; now set up file i/o buffer + 2774 4B07 8D DA 45 sta OPEN_FILE+OP_FILEBUFF+HI + 2775 4B0A A9 00 lda #LSTVM ; get other part of string + 2832 [01] IFMA 2 ; check to see if length passed in + 2833 ldy ; then just fetch it + 2834 [01] ELSE + 2835 4B61 A0 0B ldy #LSTVML ; get length of string + 2836 [00] ENDIF + 2837 4B63 20 6B 4C jsr DLINE ; print the string + 2838 4B66 .MACEND + 2839 + 2840 4B66 ONLINE ONLINE_PB + 2841 4B66 PRODOS $C5, ONLINE_PB + 2842 4B66 20 00 BF jsr $BF00 ; ProDOS handler + 2843 4B69 C5 DB $C5 ; ProDOS function code + 2844 4B6A 4E4B DW ONLINE_PB ; Function Parameter Block address + 2845 4B6C .MACEND + 2846 4B6C .MACEND + 2847 4B6C 90 05 bcc LSTV1 ; worked fine + 2848 4B6E 20 8A 47 jsr DISK_ERR ; complain if we had an error + 2849 4B71 B0 31 bcs LSTVEX ; all done + 2850 4B73 LSTV1: + 2851 4B73 A9 00 lda #0 ; start at byte zero + 2852 4B75 48 pha ; saved on stack + 2853 4B76 LSTVL: + 2854 4B76 68 pla ; get index + 2855 4B77 AA tax ; make it an index + 2856 4B78 BD 00 08 lda IOBUFF,X ; get drive/length byte + 2857 4B7B F0 27 beq LSTVEX ; all done if == 0 + 2858 4B7D 29 0F and #$0F ; just care about length + Wed Jun 7 1989 12:04 Page 44 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2859 4B7F A8 tay ; save in [Y] for now + 2860 4B80 8A txa ; into [A] for addition + 2861 4B81 18 clc ; doing add + 2862 4B82 69 10 adc #16 ; point to next entry + 2863 4B84 48 pha ; save for later reference + 2864 4B85 98 tya ; check for zero length + 2865 4B86 F0 EE beq LSTVL ; nothing here but an error + 2866 4B88 A9 2F lda #'/' ; start with / to be better + 2867 4B8A 20 82 5D jsr CHAR ; and it is out there + 2868 4B8D LSTVCL: + 2869 4B8D E8 inx ; point to next char + 2870 4B8E BD 00 08 lda IOBUFF,X ; get char + 2871 4B91 20 82 5D jsr CHAR ; print it out + 2872 4B94 88 dey ; count char + 2873 4B95 D0 F6 bne LSTVCL ; go get next char + 2874 4B97 A9 2F lda #'/' ; end with '/' to show volume status + 2875 4B99 20 82 5D jsr CHAR ; and awaaaaay we go + 2876 4B9C A9 0D lda #EOL ; do a + 2877 4B9E 20 82 5D jsr CHAR ; printed + 2878 4BA1 CA dex ; count back one, as loop starts with inx + 2879 4BA2 D0 D2 bne LSTVL ; go do next one + 2880 4BA4 LSTVEX: + 2881 4BA4 60 rts ; toots finis + 2882 ; + 2883 ; CHECKVOLS - set prefix to particular volume that is currently online + 2884 ; + 2885 4BA5 CHECKVOLS: + 2886 4BA5 A5 1D lda CHPTR+HI ; is it zero? + 2887 4BA7 D0 1C bne CHV1 ; if not, then get next volume + 2888 4BA9 ONLINE ONLINE_PB ; get online volumes + 2889 4BA9 PRODOS $C5, ONLINE_PB + 2890 4BA9 20 00 BF jsr $BF00 ; ProDOS handler + 2891 4BAC C5 DB $C5 ; ProDOS function code + 2892 4BAD 4E4B DW ONLINE_PB ; Function Parameter Block address + 2893 4BAF .MACEND + 2894 4BAF .MACEND + 2895 4BAF 90 02 bcc CHV0 ; okey dokey + 2896 4BB1 CHVBX: + 2897 4BB1 38 sec ; show badness + 2898 4BB2 60 rts ; all done + 2899 4BB3 CHV0: + 2900 4BB3 A9 F0 lda #<(IOBUFF-16) ; get LSB (-16 cuz we start with add) + 2901 4BB5 85 1C sta CHPTR+LO + 2902 4BB7 A9 08 lda #>IOBUFF ; and mSB + 2903 4BB9 85 1D sta CHPTR+HI + 2904 4BBB A9 02 lda #>SCRBUFF ; this is where we will work on it + 2905 4BBD 8D E3 45 sta SET_PB+SP_PATHNAME+HI + 2906 4BC0 A9 80 lda #SP_START ; where does it go? + 2965 4C15 85 7F sta L+HI ; L is pointer to there + 2966 4C17 GTS_RD: + 2967 4C17 A9 00 lda #MAIN ; make sure we are in main + 2968 4C19 8D 04 C0 sta WRTBNK+MAIN + 2969 4C1C READ READ_PB ; go get 1Kb + 2970 4C1C PRODOS $CA, READ_PB + 2971 4C1C 20 00 BF jsr $BF00 ; ProDOS handler + 2972 4C1F CA DB $CA ; ProDOS function code + 2973 4C20 CE45 DW READ_PB ; Function Parameter Block address + 2974 4C22 .MACEND + 2975 4C22 .MACEND + 2976 4C22 90 05 bcc GTS_RD1 ; just fine + 2977 4C24 20 07 47 jsr RETRY ; try again + 2978 4C27 90 CC bcc GTS_RDL ; and do it again + 2979 4C29 GTS_RD1: + 2980 4C29 A2 00 ldx #SP_BANK ; get bank that special is in + 2981 4C2B 9D 04 C0 sta WRTBNK,X + 2982 4C2E A9 08 lda #>IOBUFF ; get MSB of start + 2983 4C30 85 7D sta K+HI ; K is source + 2984 4C32 A2 02 ldx #2 ; 2 blocks of 256 bytes each + 2985 4C34 GTS_CPL0: + 2986 4C34 A0 00 ldy #0 ; indexer + 2987 4C36 GTS_CPL: + 2988 4C36 B1 7C lda (K),y ; get it + 2989 4C38 91 7E sta (L),y ; store it + 2990 4C3A C8 iny ; next + 2991 4C3B D0 F9 bne GTS_CPL ; gwon then + 2992 4C3D E6 7D inc K+HI ; point to next block + 2993 4C3F E6 7F inc L+HI ; for destination too + 2994 4C41 CA dex ; count block + 2995 4C42 D0 F0 bne GTS_CPL0 ; next block + 2996 4C44 C6 7A dec J+LO ; count this 1Kb + 2997 4C46 D0 CF bne GTS_RD ; go get next one + 2998 4C48 + 2999 4C48 8D 04 C0 sta WRTBNK+MAIN ; make sure we are in main + 3000 ; + 3001 ; now figger out last page + 3002 ; + 3003 4C4B A0 09 ldy #SGTSEG+1 ; get start segment LSB + 3004 4C4D B1 59 lda (INFODOS),Y ; got it + 3005 4C4F 18 clc ; doing add + 3006 4C50 69 17 adc #SP_SIZE ; add in size MSB + 3011 4C5A 8D AB 6C sta INFODOS_END+HI ; and save it + 3012 4C5D AD AA 6C lda INFODOS_END+LO ; now, subtract one to make + 3013 4C60 D0 03 bne GTS_END ; it inclusive + 3014 4C62 CE AB 6C dec INFODOS_END+HI ; wrapped, so dec MSB + 3015 4C65 GTS_END: + 3016 4C65 CE AA 6C dec INFODOS_END+LO ; make pointers inclusive + 3017 + 3018 4C68 60 rts ; done + 3019 + 3020 [01] IF CHECKSUM == 1 + 3021 CKS_COUNT: db 0 + 3022 CKSB: db 0 + 3023 CKS_BLOCK: + 3024 pha + 3025 sta CKSMOD+2 + 3026 ldy #0 + 3027 lda CKSB + 3028 CKSLP: + 3029 clc + 3030 CKSMOD: adc IOBUFF,Y + 3031 iny + 3032 bne CKSLP + 3033 + 3034 sta CKSB + 3035 inc CKS_COUNT + 3036 pla + 3037 rts + 3038 + 3039 [02] IF 0 + 3040 jsr HEXNUM + 3041 lda CKS_COUNT + 3042 cmp #$F + 3043 bne CKSCNT + 3044 lda #0 + 3045 sta CKS_COUNT + 3046 lda #EOL + 3047 bne CKSSEND + 3048 CKSCNT: + 3049 inc CKS_COUNT + 3050 lda #SPACE + 3051 CKSSEND: + 3052 jsr CHAR + 3053 jsr DISP_LINE + 3054 pla + 3055 rts + 3056 [01] ENDIF + 3057 + 3058 [00] ENDIF + 3059 + 3060 4C69 END + 3061 + 3062 4C69 INCLUDE MACHINE.ASM + 3063 4C69 STTL "--- MACHINE-DEPENDENT I/O: APPLE II ---" + 3064 PAGE + Wed Jun 7 1989 12:04 Page 47 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3065 ; ----------------------- + 3066 ; DIRECT PRINT LINE [X/A] + 3067 ; ----------------------- + 3068 ; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB) + 3069 ; STRING LENGTH IN [Y] + 3070 4C69 00 DLCNT: db 0 + 3071 4C6A 00 DLOFF: db 0 + 3072 4C6B DLINE: + 3073 4C6B 8E 85 4C stx STRING+LO ; DROP STRING ADDRESS + 3074 4C6E 8D 86 4C sta STRING+HI ; INTO DUMMY BYTES + 3075 4C71 8C 69 4C sty DLCNT ; COUNTER + 3076 4C74 20 B5 55 jsr CLRBUF ; send out what's out + 3077 4C77 A5 B1 lda SCREENF ; save output flag + 3078 4C79 48 pha + 3079 4C7A A2 01 ldx #1 ; INIT CHAR-FETCH INDEX + 3080 4C7C 86 B1 stx SCREENF ; make sure screen output is on + 3081 4C7E CA dex + 3082 4C7F 8E A8 6C stx CRLF_CHECK ; don't let swap happen + 3083 4C82 86 AA stx SCRIPT ; don't script any of my internal + 3084 4C84 BD DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE + 3085 4C85 0000 STRING: DW $0000 ; DUMMY OPERAND BYTES + 3086 4C87 8E 6A 4C stx DLOFF ; save X + 3087 4C8A 85 AC sta IOCHAR ; save here for DIRECT_OUT + 3088 4C8C 20 21 53 DOUT1: jsr DIRECT_OUT ; send directly out there + 3089 4C8F AE 6A 4C ldx DLOFF ; get x back + 3090 4C92 E8 inx + 3091 4C93 CE 69 4C dec DLCNT ; LOOP TILL + 3092 4C96 D0 EC bne DOUT ; OUT OF CHARS + 3093 4C98 20 B5 55 jsr CLRBUF ; and force the chars out + 3094 4C9B A2 01 ldx #1 ; allow scripting again + 3095 4C9D 86 AA stx SCRIPT ; okay, we did + 3096 4C9F 8E A8 6C stx CRLF_CHECK ; and turn on check + 3097 4CA2 68 pla ; get screen flag back + 3098 4CA3 85 B1 sta SCREENF ; bingo + 3099 4CA5 60 rts ; done + 3100 + 3101 ; SWAP2INFOW - save current state and swap to the information window, + 3102 ; which is currently window zero + 3103 4CA6 SWAPA1: ds 1 ; save for current ARG1 + 3104 4CA7 SWAPCW: ds 1 ; save for current window + 3105 4CA8 00 SWAPFLG: db 0 ; flag == 1 if we have already swapped + 3106 4CA9 SWAP2INFOW: + 3107 4CA9 AD A8 4C lda SWAPFLG ; already swapped? + 3108 4CAC D0 17 bne SWP2 ; ayyup + 3109 4CAE 20 B5 55 jsr CLRBUF ; clear out the buffer + 3110 4CB1 20 9F 4D jsr SAVE_CURSOR ; save current postion of cursor + 3111 4CB4 A5 63 lda ARG1+LO ; get current arg1 + 3112 4CB6 8D A6 4C sta SWAPA1 ; save it + 3113 4CB9 A5 A6 lda CURWIN ; get current window + 3114 4CBB 8D A7 4C sta SWAPCW ; save it + 3115 4CBE A9 00 lda #0 ; swap to window zero for messages + 3116 4CC0 85 63 sta ARG1+LO ; okay + 3117 4CC2 20 5C 6E jsr ZSCRN ; and swap to it + 3118 4CC5 SWP2: + 3119 4CC5 EE A8 4C inc SWAPFLG ; show we are in swap window + 3120 4CC8 SWAPEX: + 3121 4CC8 60 rts ; all done + 3122 ; + 3123 ; SWAPBACK - swap out of info window, and back to old window + 3124 ; + 3125 4CC9 SWAPBACK: + 3126 4CC9 CE A8 4C dec SWAPFLG ; are we finally leaving for good? + 3127 4CCC D0 FA bne SWAPEX ; nope + 3128 4CCE AD A7 4C lda SWAPCW ; and now for current window + 3129 4CD1 85 63 sta ARG1+LO ; swap to it + 3130 4CD3 20 5C 6E jsr ZSCRN ; we did + 3131 4CD6 AD A6 4C lda SWAPA1 ; and get arg1 back + 3132 4CD9 85 63 sta ARG1+LO ; we did + 3133 4CDB 4C B1 4D jmp GET_CURSOR ; and get cursor back + 3134 + 3135 ; ----------------------- + 3136 ; SEND [LBUFF] TO PRINTER + 3137 ; ----------------------- + 3138 ; ENTRY: LENTH OF LINE IN [PRLEN] + 3139 + Wed Jun 7 1989 12:04 Page 48 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3140 4CDE 60 PLEAV: RTS + 3141 + 3142 4CDF PPRINT: + 3143 4CDF A5 AA lda SCRIPT ; SCRIPTING INTERNALLY ENABLED? + 3144 4CE1 2D 78 6C and SCRIPTF ; SCRIPTING ON? + 3145 4CE4 2D 79 6C and SCRIPTFLG ; Window allow scripting? + 3146 4CE7 F0 F5 beq PLEAV ; NO, EXIT + 3147 4CE9 A5 36 lda CSW+LO ; SAVE NORMAL OUTPUT HOOK + 3148 4CEB 48 pha + 3149 4CEC A5 37 lda CSW+HI + 3150 4CEE 48 pha + 3151 4CEF AD 1C 4D lda ALTCSW+LO ; LOAD SCRIPTING HOOK + 3152 4CF2 85 36 sta CSW+LO + 3153 4CF4 AD 1D 4D lda ALTCSW+HI + 3154 4CF7 85 37 sta CSW+HI + 3155 4CF9 AD 82 C0 lda RDROM ; put system ROM in for printer out + 3156 4CFC A0 00 ldy #0 + 3157 4CFE PP5: + 3158 4CFE B9 00 02 lda LBUFF,Y ;GET A CHAR TO SEND OUT + 3159 4D01 30 05 bmi PP6 ; don't do highlighting + 3160 4D03 09 80 ora #$80 ; make it apple happy + 3161 4D05 20 ED FD jsr MCOUT + 3162 4D08 PP6: + 3163 4D08 C8 iny + 3164 4D09 CE 6E 6C dec PRLEN ;LINE COUNT + 3165 4D0C D0 F0 bne PP5 ;PRINT WHOLE LINE + 3166 ; + 3167 ; ALL DONE, RESET TO NORMAL AND LEAVE + 3168 ; + 3169 4D0E AD 83 C0 lda BNK2SET ; write RAM, bank 1 + 3170 4D11 AD 83 C0 lda BNK2SET + 3171 4D14 68 pla + 3172 4D15 85 37 sta CSW+HI + 3173 4D17 68 pla + 3174 4D18 85 36 sta CSW+LO + 3175 4D1A 60 rts + 3176 + 3177 4D1B 00 PSTAT: DB 0 ;SET TO CLEAR WHEN BOOT, + 3178 ;I PUT IT HERE SO RESTART WON'T ALTER + 3179 4D1C 00 00 ALTCSW: DB 0,0 ;(WORD) PRINTER COUT + 3180 + 3181 ; FIRST TIME USING PRINTER, INITIALIZE IT + 3182 4D1E 0D SLOTM: DB EOL + 3183 4D1F 50 72 69 6E 74 DB "Printer Slot 1-7: " + 4D24 65 72 20 53 6C + 4D29 6F 74 20 31 2D + 4D2E 37 3A 20 + 3184 0013 SLOTML EQU $-SLOTM + 3185 + 3186 4D31 PCHK: + 3187 4D31 20 A9 4C jsr SWAP2INFOW ; point to info window + 3188 4D34 PCHK1: + 3189 4D34 DLINE SLOTM + 3190 4D34 A2 1E ldx #SLOTM ; get other part of string + 3192 [01] IFMA 2 ; check to see if length passed in + 3193 ldy M ; then just fetch it + 3194 [01] ELSE + 3195 4D38 A0 13 ldy #SLOTML ; get length of string + 3196 [00] ENDIF + 3197 4D3A 20 6B 4C jsr DLINE ; print the string + 3198 4D3D .MACEND + 3199 4D3D 20 31 51 jsr GETKEY + 3200 4D40 C9 38 cmp #'8' ;1-7 + 3201 4D42 B0 F0 bcs PCHK1 ;OOPS + 3202 4D44 C9 31 cmp #'1' ; less than '1'? + 3203 4D46 90 EC bcc PCHK1 ; ayyup + 3204 4D48 PC2: + 3205 4D48 49 F0 eor #$F0 ; make it a slot address + 3206 4D4A 8D 1D 4D sta ALTCSW+HI + 3207 4D4D A9 0D lda #EOL + 3208 4D4F 20 82 5D jsr CHAR ;SEND >CR< TO SCREEN FOR NEATNESS + 3209 4D52 EE 1B 4D inc PSTAT ;SET TO ON + 3210 4D55 A5 36 lda CSW+LO ;SAVE NORMAL OUTPUT HOOK + 3211 4D57 48 pha + Wed Jun 7 1989 12:04 Page 49 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3212 4D58 A5 37 lda CSW+HI + 3213 4D5A 48 pha + 3214 4D5B AD 1C 4D lda ALTCSW+LO ;LOAD SCRIPTING HOOK + 3215 4D5E 85 36 sta CSW+LO + 3216 4D60 AD 1D 4D lda ALTCSW+HI + 3217 4D63 85 37 sta CSW+HI + 3218 4D65 20 98 4D jsr INITPRT ; now, init it + 3219 + 3220 4D68 AD 82 C0 lda RDROM ; bring in system ROM + 3221 4D6B A9 89 lda #$89 ; OUTPUT PRINTER SETUP SEQUENCE + 3222 4D6D 20 ED FD jsr MCOUT ; START WITH COMMAND CHAR >CTRL-I< + 3223 4D70 A9 B8 lda #$B8 ; 8 (80 COL WIDE) + 3224 4D72 20 ED FD jsr MCOUT + 3225 4D75 A9 B0 lda #$B0 ; 0 + 3226 4D77 20 ED FD jsr MCOUT + 3227 4D7A A9 CE lda #$CE ; N (LF AFTER CR) + 3228 4D7C 20 ED FD jsr MCOUT + 3229 4D7F A5 36 lda CSW+LO ; SAVE REAL PRINTER OUTPUT + 3230 4D81 8D 1C 4D sta ALTCSW+LO ; LOC. FOR NEXT TIME + 3231 4D84 A5 37 lda CSW+HI + 3232 4D86 8D 1D 4D sta ALTCSW+HI + 3233 4D89 68 pla ; RESET NORMAL OUTPUT + 3234 4D8A 85 37 sta CSW+HI + 3235 4D8C 68 pla + 3236 4D8D 85 36 sta CSW+LO + 3237 4D8F AD 83 C0 lda BNK2SET ; and bring back top RAM + 3238 4D92 AD 83 C0 lda BNK2SET ; okay + 3239 4D95 4C C9 4C jmp SWAPBACK ; and back to the old window + 3240 4D98 INITPRT: + 3241 4D98 A9 00 lda #0 ; jump to $Cn00 + 3242 4D9A 85 36 sta CSW+LO ; make LSB == 0 + 3243 4D9C 6C 36 00 jmp (CSW) ; and goto it + 3244 + 3245 + 3246 4D9F SAVE_CURSOR: + 3247 4D9F A5 01 lda SCRCY ; save the cursor pos + 3248 4DA1 A0 04 ldy #WINY ; get offset + 3249 4DA3 91 05 sta (WINDOW),Y ; first y pos + 3250 4DA5 C8 iny ; now x pos + 3251 4DA6 A5 00 lda SCRCX ; got it + 3252 4DA8 91 05 sta (WINDOW),Y ; saved it + 3253 4DAA A0 13 ldy #WINLCNT ; reset line count too + 3254 4DAC A5 AB lda LINCNT ; okay + 3255 4DAE 91 05 sta (WINDOW),Y ; get it + 3256 4DB0 60 rts + 3257 + 3258 4DB1 GET_CURSOR: + 3259 4DB1 A0 04 ldy #WINY ; get cursor pos back + 3260 4DB3 B1 05 lda (WINDOW),Y ; got y pos + 3261 4DB5 85 01 sta SCRCY ; saved + 3262 4DB7 C8 iny ; point to x pos + 3263 4DB8 B1 05 lda (WINDOW),Y ; got it + 3264 4DBA 85 00 sta SCRCX ; make it better + 3265 4DBC 38 sec ; subtract left margin to get how long line is + 3266 4DBD E5 04 sbc LEFTMRG ; okay we did that + 3267 4DBF B0 02 bcs GETCR1 ; make sure left margin is not > cur x pos + 3268 4DC1 A9 00 lda #0 ; otherwise, pretend length is zero + 3269 4DC3 GETCR1: + 3270 4DC3 85 A7 sta LENGTH+LO ; this is how big line is too + 3271 4DC5 A9 00 lda #0 ; clear MSB + 3272 4DC7 85 A8 sta LENGTH+HI + 3273 4DC9 06 A7 asl LENGTH+LO ; *2 + 3274 4DCB 26 A8 rol LENGTH+HI + 3275 4DCD 06 A7 asl LENGTH+LO ; *4 + 3276 4DCF 26 A8 rol LENGTH+HI + 3277 4DD1 + 3278 4DD1 A0 13 ldy #WINLCNT ; reset line count too + 3279 4DD3 B1 05 lda (WINDOW),Y ; get it + 3280 4DD5 85 AB sta LINCNT ; okay + 3281 4DD7 A9 01 lda #1 ; show cursor changed (maybe) + 3282 4DD9 8D 7C 6C sta CURSFLG ; okay + 3283 4DDC 60 rts + 3284 + 3285 ; ------------ + 3286 ; SPLIT SCREEN + Wed Jun 7 1989 12:04 Page 50 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3287 ; ------------ + 3288 ; + 3289 ; SPLIT SCREEN AT LINE [ARG1] putting screen 1 at top and screen + 3290 ; 0 at bottom. + 3291 ; DISABLE SPLIT IF [ARG1] = 0 + 3292 ; + 3293 4DDD ZSPLIT: + 3294 4DDD 20 9F 4D jsr SAVE_CURSOR ; save the cursor pos + 3295 ; + 3296 ; first muck with window 1 + 3297 ; + 3298 4DE0 A5 63 lda ARG1+LO ; get split arg back + 3299 4DE2 8D A6 6D sta WINDOW1+WINHGHT ; this becomes the height of window 1 + 3300 4DE5 A9 00 lda #0 ; put top of 1 to top of screen + 3301 4DE7 8D A4 6D sta WINDOW1+WINTOP ; okay, we did it + 3302 4DEA A5 63 lda ARG1+LO ; get new height + 3303 4DEC A2 FF ldx #$FF ; this is the counter + 3304 4DEE 38 sec ; get ready for subs + 3305 4DEF ZSPLIT0: + 3306 4DEF E8 inx ; count this line + 3307 4DF0 E9 09 sbc #FONT_H ; subtract off font height + 3308 4DF2 B0 FB bcs ZSPLIT0 ; still some lines + 3309 4DF4 CA dex ; save input line + 3310 4DF5 8E BB 6D stx WINDOW1+WINLINES ; saved + 3311 + 3312 4DF8 AD A8 6D lda WINDOW1+WINY ; check cursor pos + 3313 4DFB C5 63 cmp ARG1+LO ; against height + 3314 4DFD 90 11 bcc ZSPL1 ; inside window, so save it + 3315 4DFF ZSPL0: + 3316 4DFF A9 00 lda #0 ; reset to top left + 3317 4E01 8D A8 6D sta WINDOW1+WINY ; y pos at top + 3318 4E04 8D A9 6D sta WINDOW1+WINX ; x pos at left + 3319 4E07 8D B9 6D sta WINDOW1+WINLLEN+LO ; line length + 3320 4E0A 8D BA 6D sta WINDOW1+WINLLEN+HI ; line length + 3321 4E0D 8D B7 6D sta WINDOW1+WINLCNT ; line counter + 3322 ; + 3323 ; now muck with window 0 + 3324 ; + 3325 4E10 ZSPL1: + 3326 4E10 AD 8C 6D lda WINDOW0+WINTOP ; top of window 0 + 3327 4E13 38 sec ; doing sub + 3328 4E14 E5 63 sbc ARG1+LO ; subtract out the new top + 3329 4E16 18 clc ; adding + 3330 4E17 6D 8E 6D adc WINDOW0+WINHGHT ; to get the new height + 3331 ; bcc ZSPLIT1 ; okay, positive height + 3332 ; lda #0 ; make height 0 + 3333 4E1A ZSPLIT1: + 3334 4E1A 8D 8E 6D sta WINDOW0+WINHGHT ; and save new height + 3335 4E1D + 3336 4E1D A2 FF ldx #$FF ; this is the counter + 3337 4E1F 38 sec ; get ready for subs + 3338 4E20 ZSPLIT2: + 3339 4E20 E8 inx ; count this line + 3340 4E21 E9 09 sbc #FONT_H ; subtract off font height + 3341 4E23 B0 FB bcs ZSPLIT2 ; still some lines + 3342 4E25 CA dex ; to save input line + 3343 4E26 8E A3 6D stx WINDOW0+WINLINES ; saved + 3344 + 3345 4E29 A5 63 lda ARG1+LO ; this is the new top + 3346 4E2B 8D 8C 6D sta WINDOW0+WINTOP ; set in structure + 3347 4E2E CD 90 6D cmp WINDOW0+WINY ; make sure cursor is still in window + 3348 4E31 F0 13 beq ZSPL5 ; nope, at the top + 3349 4E33 90 11 bcc ZSPL5 ; or under it + 3350 4E35 8D 90 6D sta WINDOW0+WINY ; put cursor at top + 3351 4E38 A9 00 lda #0 ; left of new + 3352 4E3A 8D 91 6D sta WINDOW0+WINX ; window 0 + 3353 4E3D 8D A1 6D sta WINDOW0+WINLLEN+LO ; linelength + 3354 4E40 8D A2 6D sta WINDOW0+WINLLEN+HI ; linelength + 3355 4E43 8D 9F 6D sta WINDOW0+WINLCNT ; line counter + 3356 4E46 ZSPL5: + 3357 4E46 20 B1 4D jsr GET_CURSOR ; get the cursor pos back + 3358 + 3359 4E49 A9 00 lda #0 ; now switch to window zero + 3360 4E4B 85 63 sta ARG1+LO ; good bye + 3361 4E4D 4C 5C 6E jmp ZSCRN ; making window 0 be current + Wed Jun 7 1989 12:04 Page 51 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3362 + 3363 ; ------ + 3364 ; MARGIN + 3365 ; ------ + 3366 ; + 3367 ; Set the margins for the window + 3368 ; + 3369 ; ARG1 - left margin + 3370 ; ARG2 - right margin + 3371 ; ARG3 - window ID (optional) + 3372 ; + 3373 4E50 ZMARG: + 3374 4E50 20 B5 55 jsr CLRBUF ; CLEAR LBUFF BEFORE RESETTING LINE MARGINS + 3375 4E53 20 9F 4D jsr SAVE_CURSOR ; save current cursor pos + 3376 4E56 + 3377 4E56 A5 62 lda NARGS ; see if window ID was passed + 3378 4E58 C9 03 cmp #3 ; if ==3, then it's there + 3379 4E5A F0 04 beq ZMRG1 ; okay, so use it + 3380 4E5C A5 A6 lda CURWIN ; get the current window + 3381 4E5E 85 67 sta ARG3+LO ; and use as the default + 3382 4E60 ZMRG1: + 3383 4E60 A5 67 lda ARG3+LO ; check what window + 3384 4E62 20 7F 57 jsr SETWJ ; get window offset into J + 3385 4E65 A5 63 lda ARG1+LO ; do left margin first + 3386 4E67 A0 06 ldy #WINLM ; get offset + 3387 4E69 91 7A sta (J),Y ; save for window + 3388 4E6B C8 iny ; point to right margin + 3389 4E6C A5 65 lda ARG2+LO ; get right margin + 3390 4E6E 91 7A sta (J),Y ; save right margin + 3391 4E70 A0 03 ldy #WINWID ; get full width of window + 3392 4E72 B1 7A lda (J),Y ; got it + 3393 4E74 38 sec ; subtract off the 2 margins + 3394 4E75 A0 06 ldy #WINLM ; first the left margin + 3395 4E77 F1 7A sbc (J),Y ; okay, gone + 3396 4E79 C8 iny ; point to right margin + 3397 4E7A F1 7A sbc (J),Y ; and take it off + 3398 4E7C A0 14 ldy #WINXSZ ; set width of usable window + 3399 4E7E 91 7A sta (J),Y ; see, here it is + 3400 ; + 3401 ; move cursor to left margin + 3402 ; + 3403 4E80 A0 01 ldy #WINLEFT ; get left edge + 3404 4E82 B1 7A lda (J),Y ; got it + 3405 4E84 A0 06 ldy #WINLM ; and add left margin + 3406 4E86 18 clc ; adding + 3407 4E87 71 7A adc (J),Y ; to get minimum X + 3408 4E89 A0 05 ldy #WINX ; check to make sure X pos is okay + 3409 4E8B 91 7A sta (J),Y ; then reset it + 3410 ; + 3411 ; now see if we changed the current window + 3412 ; + 3413 4E8D ZMRGXP: + 3414 4E8D A6 67 ldx ARG3+LO ; get the window + 3415 4E8F 30 04 bmi ZMRG3 ; -3 means current window + 3416 4E91 E4 A6 cpx CURWIN ; check against the current window + 3417 4E93 D0 17 bne ZMRGX ; nope, so we be done + 3418 4E95 ZMRG3: + 3419 4E95 85 04 sta LEFTMRG ; [A] already has left margin + 3420 4E97 A0 14 ldy #WINXSZ ; get xsize to set + 3421 4E99 B1 05 lda (WINDOW),Y ; got it + 3422 4E9B 85 A2 sta XSIZE+LO ; this is for quicky comparing + 3423 4E9D A9 00 lda #0 ; clear MSB + 3424 4E9F 85 A3 sta XSIZE+HI + 3425 4EA1 06 A2 asl XSIZE+LO ; *2 + 3426 4EA3 26 A3 rol XSIZE+HI + 3427 4EA5 06 A2 asl XSIZE+LO ; *4 + 3428 4EA7 26 A3 rol XSIZE+HI + 3429 4EA9 20 B1 4D jsr GET_CURSOR ; restore the cursor pos + 3430 4EAC ZMRGX: + 3431 4EAC 60 rts + 3432 ; + 3433 ; SOUND + 3434 ; ----- + 3435 ; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID + 3436 ; (EZIP) + Wed Jun 7 1989 12:04 Page 52 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3437 + 3438 4EAD ZSOUND: + 3439 4EAD A6 63 ldx ARG1+LO ; GET SOUND WANTED + 3440 4EAF CA dex + 3441 4EB0 F0 11 beq BEEP + 3442 4EB2 CA dex + 3443 4EB3 D0 0D bne ZSOEX ; INVALID + 3444 4EB5 A0 FF ldy #$FF ; DURATION ($C0 = .1 SEC) + 3445 4EB7 BOOP: + 3446 4EB7 A9 10 lda #$10 ; TONE ($0C = 1 KHZ) + 3447 4EB9 20 27 4F jsr WAIT10 + 3448 4EBC AD 30 C0 lda SPKR ; TOGGLE SPEAKER + 3449 4EBF 88 dey + 3450 4EC0 D0 F5 bne BOOP + 3451 4EC2 ZSOEX: + 3452 4EC2 60 rts + 3453 + 3454 4EC3 BEEP: + 3455 4EC3 AD 82 C0 lda RDROM + 3456 4EC6 20 3A FF jsr MBELL ; just use system beep + 3457 4EC9 AD 83 C0 lda BNK2SET ; back to bank 2 + 3458 4ECC AD 83 C0 lda BNK2SET ; back to bank 2 + 3459 4ECF 60 rts + 3460 ; + 3461 ; just do the background color - foreground is always white/black + 3462 ; + 3463 ; + 3464 ; ZIPCOLOR - maps ZIP colors to screen colors + 3465 ; + 3466 4ED0 ZCOLOR: + 3467 4ED0 20 B5 55 jsr CLRBUF ; print out what we have + 3468 + 3469 4ED3 A5 62 lda NARGS ; check if window was passed + 3470 4ED5 C9 03 cmp #3 ; was it? + 3471 4ED7 F0 04 beq ZCLR0 ; ayyup + 3472 4ED9 A5 A6 lda CURWIN ; make it current window + 3473 4EDB 85 67 sta ARG3+LO ; it is now + 3474 4EDD ZCLR0: + 3475 4EDD A5 67 lda ARG3+LO ; get window ID + 3476 4EDF 20 7F 57 jsr SETWJ ; and put pointer into J + 3477 + 3478 4EE2 A6 65 ldx ARG2+LO ; get background color + 3479 4EE4 F0 15 beq ZCLR2 ; check fore ground color + 3480 4EE6 10 06 bpl ZCLR01 ; not -1 + 3481 4EE8 20 10 5E jsr GET_NYBBLE ; get me the color nybble here + 3482 4EEB 4C F7 4E jmp ZCLR11 ; and use as background color + 3483 4EEE ZCLR01: + 3484 4EEE CA dex ; check for default + 3485 4EEF D0 02 bne ZCLR1 ; nope, find the color + 3486 4EF1 A2 01 ldx #1 ; use black as default back color + 3487 4EF3 ZCLR1: + 3488 4EF3 CA dex ; zero base the color + 3489 4EF4 BD 44 6C lda ZIPCOLOR,X ; get my color from the zip color + 3490 4EF7 ZCLR11: + 3491 4EF7 A0 0E ldy #WINBGND ; get background offset + 3492 4EF9 91 7A sta (J),Y ; saved color + 3493 ; + 3494 ; now do foreground color + 3495 ; + 3496 4EFB ZCLR2: + 3497 4EFB A6 63 ldx ARG1+LO ; get foreground color + 3498 4EFD F0 0E beq ZCLREX ; no change + 3499 4EFF CA dex ; check for default + 3500 4F00 D0 02 bne ZCLR3 ; nope, find the color + 3501 4F02 A2 08 ldx #8 ; use white as default fore color + 3502 4F04 ZCLR3: + 3503 4F04 CA dex ; zero base the color + 3504 4F05 BD 44 6C lda ZIPCOLOR,X ; get my color from the zip color + 3505 4F08 A0 0D ldy #WINFORE ; foreground color offset + 3506 4F0A 8A txa ; get into A for fun + 3507 4F0B 91 7A sta (J),Y ; save in structure + 3508 4F0D ZCLREX: + 3509 4F0D 60 rts + 3510 + 3511 ; + Wed Jun 7 1989 12:04 Page 53 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3512 ; CHKTME RTN - CALLED BY INPUT & ZINPUT + 3513 ; + 3514 4F0E CHKTME: + 3515 4F0E A5 62 lda NARGS ; CHECK IF TIME LIMIT + 3516 4F10 C9 02 cmp #2 + 3517 4F12 F0 12 beq CHKT1 ; NO + 3518 4F14 A5 67 lda ARG3+LO ; GET DELAY WANTED + 3519 4F16 85 79 sta I+HI + 3520 4F18 A5 62 lda NARGS ; IS THERE A FCN? + 3521 4F1A C9 04 cmp #4 + 3522 4F1C D0 08 bne CHKT1 ; NO + 3523 4F1E A5 69 lda ARG4+LO ; YES, SET IT + 3524 4F20 85 7A sta J+LO + 3525 4F22 A5 6A lda ARG4+HI + 3526 4F24 85 7B sta J+HI + 3527 4F26 CHKT1: + 3528 4F26 60 rts ; just set things up, please + 3529 + 3530 4F27 WAIT10: + 3531 4F27 A9 02 lda #2 ; do this twice (maybe) + 3532 4F29 85 C6 sta DELAY_COUNTER ; put in counter + 3533 4F2B WAIT0: + 3534 4F2B AD 82 C0 lda RDROM ; get roms in + 3535 4F2E A2 04 ldx #4 ; .04 SEC (time to do other stuff) + 3536 4F30 A9 30 TIME1: lda #$30 ; .01 SEC + 3537 4F32 20 A8 FC jsr MWAIT + 3538 4F35 CA dex + 3539 4F36 D0 F8 bne TIME1 + 3540 + 3541 4F38 AD 83 C0 lda BNK2SET ; get roms out + 3542 4F3B AD 83 C0 lda BNK2SET + 3543 + 3544 4F3E A5 58 lda MOUSEF ; move mouse cursor? + 3545 4F40 F0 08 beq WAIT1 ; nope + 3546 4F42 AD A9 6C lda PTR_COUNT ; but do we really want to check it + 3547 4F45 D0 03 bne WAIT1 ; nope + 3548 4F47 4C 2B 50 jmp MOVE_MC ; move cursor, if necessary + 3549 4F4A WAIT1: + 3550 4F4A C6 C6 dec DELAY_COUNTER ; count loop + 3551 4F4C D0 DD bne WAIT0 ; go do again + 3552 4F4E 60 rts + 3553 ; + 3554 ; tick the ol timer + 3555 ; + 3556 4F4F TIMEK: + 3557 4F4F A9 03 lda #BLINK_RATE ; how often to blink + 3558 4F51 8D 92 4F sta CURCOUNT ; okay! + 3559 4F54 TIMEST: + 3560 4F54 A5 78 lda I+LO ; don't reset if not zero + 3561 4F56 D0 07 bne TIMELOOP ; so keep goin' then + 3562 4F58 A5 79 lda I+HI + 3563 4F5A 85 78 sta I+LO + 3564 4F5C 20 93 4F jsr STCUR ; start the cursor + 3565 4F5F TIMELOOP: + 3566 4F5F 20 27 4F jsr WAIT10 ; wait .10 secs + 3567 + 3568 4F62 20 E6 4F jsr FKEYX ; Check for Keystroke + 3569 4F65 30 23 bmi TIME2 ; OK, HE'S THERE, CONTINUE + 3570 + 3571 4F67 CE 92 4F dec CURCOUNT ; count down to toggle + 3572 4F6A D0 08 bne TMCNT ; okay, no blink + 3573 4F6C 20 93 4F jsr STCUR ; blink cursor + 3574 4F6F A9 03 lda #BLINK_RATE ; once per second + 3575 4F71 8D 92 4F sta CURCOUNT ; okay! + 3576 4F74 TMCNT: + 3577 4F74 C6 78 dec I+LO ; 10TH'S OF SECONDS TO WAIT + 3578 4F76 F0 02 beq TIMEOUT ; SOME TIME LEFT + 3579 + 3580 4F78 D0 E5 bne TIMELOOP ; so gwon back and try again! (JMP) + 3581 ; + 3582 ; THERE IS A TIME OUT, CHECK FOR A FCN + 3583 ; + 3584 4F7A TIMEOUT: + 3585 4F7A 20 BE 4F jsr ERCUR ; after erasing cursor + 3586 4F7D A5 7B lda J+HI ; IS THERE A FCN + Wed Jun 7 1989 12:04 Page 54 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3587 4F7F F0 0E beq TIMEBAD ; NO FCN, LEAVE WITH NOTHING + 3588 4F81 TIME3: + 3589 4F81 20 18 5B jsr INTCLL ; INTERNALLY CALL THE FCN + 3590 4F84 A5 76 lda VALUE+LO ; CHECK RESULTS + 3591 4F86 F0 CC beq TIMEST ; ELSE TRY AGAIN + 3592 4F88 D0 05 bne TIMEBAD ; else die a horrible death! + 3593 4F8A TIME2: + 3594 4F8A 20 BE 4F jsr ERCUR ; after erasing cursor + 3595 4F8D 18 clc ; GOT A KEY + 3596 4F8E 60 rts + 3597 4F8F TIMEBAD: + 3598 4F8F 38 sec + 3599 4F90 60 rts + 3600 ; + 3601 ; display the cursor in the current spot + 3602 ; + 3603 4F91 80 CURSTATE: db $80 ; blinking cursor state + 3604 4F92 00 CURCOUNT: db 0 ; toggle counter + 3605 + 3606 4F93 STCUR: + 3607 4F93 AD A7 6C lda CURSOR_OFF ; is the cursor off? + 3608 4F96 F0 01 beq STCUR1 ; no + 3609 4F98 60 rts ; yes, so don't do nuthin' + 3610 4F99 STCUR1: + 3611 4F99 48 pha ; save a + 3612 4F9A A5 BB lda INVFLG ; get current INVFLG + 3613 4F9C 48 pha ; save it + 3614 4F9D A9 80 lda #$80 ; make it all be ones + 3615 4F9F 85 BB sta INVFLG ; and blink + 3616 + 3617 4FA1 A9 20 lda #SPACE ; space for cursor + 3618 4FA3 8D E3 71 sta SHOW_CURSOR ; show that we are doing cursor + 3619 4FA6 20 82 5D jsr CHAR ; and print it out + 3620 4FA9 20 F1 71 jsr DISP_LINE ; send it out + 3621 + 3622 4FAC AD 91 4F lda CURSTATE ; get current state + 3623 4FAF 49 80 eor #$80 ; toggle it + 3624 4FB1 8D 91 4F sta CURSTATE ; save it + 3625 4FB4 68 pla ; get invflg + 3626 4FB5 85 BB sta INVFLG ; restored + 3627 4FB7 A9 00 lda #0 ; clear cursor flag + 3628 4FB9 8D E3 71 sta SHOW_CURSOR ; okay + 3629 4FBC + 3630 4FBC 68 pla + 3631 4FBD 60 rts + 3632 ; + 3633 ; just erase the cusor char, but leave cursor in its old place + 3634 ; + 3635 4FBE ERCUR: + 3636 4FBE 48 pha ; save a + 3637 4FBF AD 91 4F lda CURSTATE ; get current state + 3638 4FC2 D0 03 bne ERCURX ; not on, leave alone + 3639 4FC4 20 93 4F jsr STCUR ; 'start' it out + 3640 4FC7 ERCURX: + 3641 4FC7 68 pla ; retrieve [A] + 3642 4FC8 60 rts + 3643 ; + 3644 ; timed key input loop + 3645 ; + 3646 ; carry set if timed out + 3647 ; char in [A], if there is one! + 3648 4FC9 TIMIN: + 3649 4FC9 A5 58 lda MOUSEF ; is there a mouse/joystick? + 3650 4FCB F0 03 beq TIMIN1 ; nope + 3651 4FCD 20 BA 62 jsr MSCON ; turn on mouse cursor + 3652 4FD0 TIMIN1: + 3653 4FD0 20 4F 4F jsr TIMEK ; check for keystroke + 3654 4FD3 B0 05 bcs TMBAD ; ELSE ABORT + 3655 4FD5 TM1: + 3656 4FD5 20 8B 51 jsr PARSEKEY ; GET ASCII INTO [A] AND [IOCHAR] + 3657 4FD8 B0 F6 bcs TIMIN1 ; c==1 means no good char + 3658 4FDA TMBAD: + 3659 4FDA A6 58 ldx MOUSEF ; is there a mouse/joystick? + 3660 4FDC F0 07 beq TIMIN2 ; nope + 3661 4FDE 08 php ; save status + Wed Jun 7 1989 12:04 Page 55 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3662 4FDF 48 pha ; save (possible) char + 3663 4FE0 20 5B 62 jsr MSCOFF ; turn off mouse cursor + 3664 4FE3 68 pla ; get char back + 3665 4FE4 28 plp ; get return status + 3666 4FE5 TIMIN2: + 3667 4FE5 60 rts ; and away we go + 3668 ; + 3669 ; FKEYX - move the mouse cursor if any, then check for keystroke + 3670 ; + 3671 4FE6 FKEYX: + 3672 4FE6 A5 58 lda MOUSEF ; is there a mouse cursor? + 3673 4FE8 F0 38 beq KEYX ; nope + 3674 4FEA 30 07 bmi KEYMOUSE ; handle mouse + 3675 4FEC 20 AD 50 jsr DO_STICK ; handle joystick + 3676 4FEF 10 31 bpl KEYX ; go look for key still + 3677 4FF1 30 05 bmi KEYBTN ; do button handling + 3678 4FF3 KEYMOUSE: + 3679 4FF3 20 6E 50 jsr DO_MOUSE ; handle mouse stuff + 3680 4FF6 10 2A bpl KEYX ; go look for key still + 3681 ; + 3682 ; button hit, so show pos in MSTBL + 3683 ; + 3684 4FF8 KEYBTN: + 3685 4FF8 48 pha ; save status + 3686 4FF9 A5 CE lda MSTBL+LO + 3687 4FFB 85 8F sta SPCL + 3688 4FFD A5 CF lda MSTBL+HI + 3689 4FFF 85 90 sta SPCH + 3690 5001 A5 D0 lda MSTBL+ABANK + 3691 5003 85 91 sta SPCBNK + 3692 5005 A9 03 lda #ZMSLOCX+1 ; point to LSB of mouse x + 3693 5007 20 06 90 jsr ADDSPC ; add to point + 3694 500A A5 CB lda MSX ; get X + 3695 500C 18 clc ; center the hot spot + 3696 500D 69 01 adc #CURSW/2 ; add 1/2 width + 3697 500F 20 3A 92 jsr STASHB ; and stuff it away + 3698 5012 A9 02 lda #2 ; 2 more to get to mouse y + 3699 5014 20 06 90 jsr ADDSPC ; okay + 3700 5017 A5 CC lda MSY ; now show the world the y pos + 3701 5019 18 clc ; and center vertically too + 3702 501A 69 02 adc #CURSH/2 ; add 1/2 height + 3703 501C 20 3A 92 jsr STASHB ; and it is away + 3704 501F 68 pla ; get status back + 3705 5020 A8 tay ; and set it again + 3706 5021 60 rts ; otherwise, done + 3707 5022 KEYX: + 3708 5022 AD 00 C0 lda KBD ; check keyboard strobe + 3709 5025 10 03 bpl KEYXX ; nothing + 3710 5027 8D 10 C0 sta ANYKEY ; reset strobe + 3711 502A KEYXX: + 3712 502A 60 rts + 3713 ; + 3714 ; MOVE_MC - move the mouse/joystick cursor, if necessary + 3715 ; + 3716 502B MOVE_MC: + 3717 502B A5 58 lda MOUSEF ; check which kind to move + 3718 502D 10 06 bpl MOVE_MC1 ; move joystick cursor + 3719 502F 20 41 50 jsr CHK_MOUSE ; move the mouse cursor + 3720 5032 4C 38 50 jmp MOVE_MC2 ; and print it + 3721 5035 MOVE_MC1: + 3722 5035 20 B3 50 jsr MOVE_STICK ; okay, checked it out + 3723 5038 MOVE_MC2 + 3724 5038 AD 12 03 lda MSMOVEF ; did it move? + 3725 503B F0 03 beq MOVE_MCX ; nope + 3726 503D 4C 50 62 jmp MSCURS ; print it + 3727 5040 MOVE_MCX: + 3728 5040 60 rts ; done + 3729 ; + 3730 ; CHK_MOUSE - check the mouse position and button state, and flag any change + 3731 ; + 3732 5041 CHK_MOUSE: + 3733 5041 AD 54 C0 lda PAGE2SW ; make sure we are pointing to main bank + 3734 + 3735 5044 A2 02 ldx #READM ; get me current cursor pos + 3736 5046 20 00 03 jsr MOUSER ; turn off interrupts and set current pos + Wed Jun 7 1989 12:04 Page 56 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3737 + 3738 5049 AD 83 C0 lda BNK2SET ; make sure we are pointing to second bank + 3739 504C AD 83 C0 lda BNK2SET ; okay + 3740 + 3741 504F AD 78 07 MSFIX0 lda MOUSEST ; get status byte + 3742 5052 A8 tay ; save for a sec + 3743 5053 29 20 and #$20 ; moved since last time? + 3744 5055 F0 0D beq CHKM1 ; nope + 3745 5057 8D 12 03 sta MSMOVEF ; show movement + 3746 505A AD 78 04 MSFIX1 lda MOUSEXL ; get mouse X pos + 3747 505D 85 CB sta MSX ; save new one + 3748 505F AD F8 04 MSFIX2 lda MOUSEYL ; and the y pos + 3749 5062 85 CC sta MSY ; save for me + 3750 5064 CHKM1: + 3751 5064 98 tya ; get status back + 3752 5065 29 C0 and #$C0 ; is button down? + 3753 5067 F0 02 beq CHKMX ; nope + 3754 5069 A9 80 lda #$80 ; show down state + 3755 506B CHKMX: + 3756 506B 4C 25 51 jmp CHK_BTN ; check button state + 3757 ; + 3758 ; there is a mouse, so check it + 3759 ; + 3760 506E DO_MOUSE: + 3761 506E 20 41 50 jsr CHK_MOUSE ; check the mouse please + 3762 ; FALL THROUGH TO BUTTON CLICKING HANDLER + 3763 ; jmp DO_BUTTON ; handle button clicking + 3764 ; + 3765 ; DO_BUTTON - handle button clicking, working with the timer to + 3766 ; check for double clicking or not + 3767 ; + 3768 5071 DO_BUTTON: + 3769 5071 AD 12 03 lda MSMOVEF ; check moved flag + 3770 5074 F0 03 beq DOM01 ; nope + 3771 5076 20 50 62 jsr MSCURS ; move mouse cursor + 3772 5079 DOM01: + 3773 5079 A9 00 lda #0 ; show no char + 3774 507B AC 13 03 ldy MSBTNF ; check button flag + 3775 507E 10 15 bpl DOBX ; none + 3776 ; + 3777 ; button strike, check for double click + 3778 ; + 3779 5080 8C 02 51 sty JB_STATE ; show new state + 3780 5083 A4 CA ldy CLKCTR ; have we started click counter? + 3781 5085 10 08 bpl DOB02 ; nope + 3782 5087 A0 01 ldy #1 ; this resets counter + 3783 5089 84 CA sty CLKCTR ; reset it + 3784 508B A9 82 lda #DBL_CLK ; show double click char + 3785 508D D0 14 bne DOBEXIT ; and finis + 3786 508F DOB02: + 3787 508F A0 FA ldy #-CLK_CNT ; set to double click timeout + 3788 5091 84 CA sty CLKCTR ; okay + 3789 5093 30 0E bmi DOBEXIT ;done + 3790 5095 DOBX: + 3791 5095 A4 CA ldy CLKCTR ; click counter counting? + 3792 5097 10 0A bpl DOBEXIT ; nope + 3793 5099 E6 CA inc CLKCTR ; count it then + 3794 509B D0 06 bne DOBEXIT ; all done + 3795 509D A0 01 ldy #1 ; reset counter + 3796 509F 84 CA sty CLKCTR ; okay + 3797 50A1 A9 81 lda #SGL_CLK ; set as char + 3798 50A3 DOBEXIT: + 3799 50A3 A0 00 ldy #0 ; clear out flags + 3800 50A5 8C 13 03 sty MSBTNF ; button flag + 3801 50A8 8C 12 03 sty MSMOVEF ; moved flag + 3802 50AB A8 tay ; set flag to show any char + 3803 50AC 60 rts ; return char + 3804 ; + 3805 ; DO_STICK - handle the joystick 'interrupt' + 3806 ; + 3807 50AD DO_STICK: + 3808 50AD 20 B3 50 jsr MOVE_STICK ; first move it + 3809 50B0 4C 71 50 jmp DO_BUTTON ; now handle it + 3810 50B3 MOVE_STICK: + 3811 50B3 A9 00 lda #0 ; get horizontal change + Wed Jun 7 1989 12:04 Page 57 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3812 50B5 20 03 51 jsr READ_STICK ; puts value in Y + 3813 50B8 C0 50 cpy #80 ; if < 80, then jump to the left + 3814 50BA B0 0D bcs DOST1 ; it is not + 3815 50BC A5 CB lda MSX ; make sure X is > 0 + 3816 50BE F0 1A beq DOST2 ; it is == 0, can't get smaller + 3817 50C0 8D 12 03 sta MSMOVEF ; show movement + 3818 50C3 C6 CB dec MSX ; move one to the left + 3819 50C5 C6 CB dec MSX ; move two to the left + 3820 50C7 D0 11 bne DOST2 ; now check vertical + 3821 50C9 DOST1: + 3822 50C9 C0 B4 cpy #180 ; if > 160, then move right + 3823 50CB 90 0D bcc DOST2 ; nope + 3824 50CD A5 CB lda MSX ; make sure X is in bounds + 3825 50CF C9 88 cmp #MAXWIDTH-4 ; don't go too far + 3826 50D1 B0 07 bcs DOST2 ; already maxxed out + 3827 50D3 8C 12 03 sty MSMOVEF ; show movement + 3828 50D6 E6 CB inc MSX ; one step to the left + 3829 50D8 E6 CB inc MSX ; and another one + 3830 50DA DOST2: + 3831 50DA A9 01 lda #1 ; now check vertical + 3832 50DC 20 03 51 jsr READ_STICK ; ask the monitor + 3833 50DF C0 50 cpy #80 ; if < 80, move up + 3834 50E1 B0 0D bcs DOST3 ; nope + 3835 50E3 A5 CC lda MSY ; don't go negative + 3836 50E5 F0 1A beq DOST4 ; already minned out + 3837 50E7 8D 12 03 sta MSMOVEF ; show movement + 3838 50EA C6 CC dec MSY ; count down + 3839 50EC C6 CC dec MSY ; twice + 3840 50EE D0 11 bne DOST4 ; all done + 3841 50F0 DOST3: + 3842 50F0 C0 B4 cpy #180 ; check for downward motion + 3843 50F2 90 0D bcc DOST4 ; none + 3844 50F4 A5 CC lda MSY ; check for maximum + 3845 50F6 C9 BD cmp #MAXHEIGHT-3 ; don't go below water + 3846 50F8 B0 07 bcs DOST4 ; gone, thanx + 3847 50FA 8C 12 03 sty MSMOVEF ; show movement + 3848 50FD E6 CC inc MSY ; go further down + 3849 50FF E6 CC inc MSY ; twice as far for joystick + 3850 5101 DOST4: + 3851 5101 60 rts ; done + 3852 ; + 3853 ; READ_STICK - read the x or y value of the stick in mind. + 3854 ; [A] == 0 or 1 - the "stick" you are interested in + 3855 ; Also, check the button status. + 3856 ; + 3857 5102 00 JB_STATE db 0 ; last state of joystick button + 3858 5103 READ_STICK: + 3859 5103 48 pha ; save which stick we want + 3860 5104 A2 E0 ldx #$E0 ; oh, pick something random + 3861 5106 READST2: + 3862 5106 20 1B 51 jsr CHECK_JOYBTN ; check the joystick button + 3863 5109 CA dex + 3864 510A D0 FA bne READST2 + 3865 510C 68 pla ; get x back + 3866 510D AA tax ; got it + 3867 510E AD 82 C0 lda RDROM ; bring ROM back + 3868 5111 20 1E FB jsr MPREAD ; NOW do the read + 3869 5114 AD 83 C0 lda BNK2SET ; back to RAM + 3870 5117 AD 83 C0 lda BNK2SET ; back to RAM + 3871 511A 60 rts + 3872 511B CHECK_JOYBTN: + 3873 511B A5 58 lda MOUSEF ; check which kind to move + 3874 511D 10 03 bpl DO_JBTN ; no joystick, check mouse + 3875 511F 4C 41 50 jmp CHK_MOUSE ; then do the mouse + 3876 5122 DO_JBTN: + 3877 5122 AD 61 C0 lda APKEY1 ; get joystick button + 3878 5125 CHK_BTN: + 3879 5125 30 03 bmi READST3 ; button down + 3880 5127 8D 02 51 sta JB_STATE ; show button went up + 3881 512A READST3: + 3882 512A 4D 02 51 eor JB_STATE ; toggle previous state + 3883 512D 8D 13 03 sta MSBTNF ; set button flag + 3884 5130 60 rts + 3885 ; ---------------------------- + 3886 ; FETCH ASCII KEYCODE INTO [A] + Wed Jun 7 1989 12:04 Page 58 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3887 ; ---------------------------- + 3888 ; EXIT: ASCII IN [A] & [IOCHAR] + 3889 + 3890 5131 GETKEY: + 3891 5131 A9 03 lda #BLINK_RATE ; flag as wait for good key + 3892 5133 8D 92 4F sta CURCOUNT ; clear blinker + 3893 5136 A5 58 lda MOUSEF ; is there a mouse/joystick? + 3894 5138 F0 03 beq GTK0 ; nope + 3895 513A 20 BA 62 jsr MSCON ; turn on mouse cursor + 3896 513D GTK0: + 3897 513D A9 00 lda #0 ; clear line counter + 3898 513F 85 AB sta LINCNT ; okay, we did + 3899 5141 8A txa ; SAVE [X] & [Y] + 3900 5142 48 pha + 3901 5143 98 tya + 3902 5144 48 pha + 3903 5145 GKEY0: + 3904 5145 E6 A5 inc RAND+HI ; just whack on random number + 3905 5147 C6 A4 dec RAND+LO ; and more + 3906 5149 20 E6 4F jsr FKEYX ; is there a key? + 3907 514C 30 23 bmi GKEY01 ; got the key + 3908 + 3909 514E 20 27 4F jsr WAIT10 ; wait .1 seconds, moving mouse cursor + 3910 + 3911 5151 A5 58 lda MOUSEF ; do we have a joystick/mouse? + 3912 5153 F0 0D beq GKEY02 ; nope + 3913 5155 AD A9 6C lda PTR_COUNT ; count down counter? + 3914 5158 F0 05 beq GKEY00 ; nope + 3915 515A CE A9 6C dec PTR_COUNT ; count one wait cycle + 3916 515D D0 03 bne GKEY02 ; don't check yet + 3917 515F GKEY00: + 3918 515F 20 1B 51 jsr CHECK_JOYBTN ; check the joystick button, just fur the heckuvit + 3919 5162 GKEY02: + 3920 5162 CE 92 4F dec CURCOUNT ; down one + 3921 5165 D0 DE bne GKEY0 ; no toggle + 3922 5167 20 93 4F jsr STCUR ; okay, toggle + 3923 516A A9 03 lda #BLINK_RATE ; 1 per second + 3924 516C 8D 92 4F sta CURCOUNT ; okay + 3925 516F D0 D4 bne GKEY0 ; check for key + 3926 5171 GKEY01: + 3927 5171 48 pha ; save char + 3928 5172 A5 58 lda MOUSEF ; any mouse cursor? + 3929 5174 F0 03 beq GTK1 ; nope + 3930 5176 20 5B 62 jsr MSCOFF ; turn mouse cursor off + 3931 5179 GTK1: + 3932 5179 68 pla ; get char back + 3933 517A 20 BE 4F jsr ERCUR ; so erase cursor + 3934 517D CHKKEY: + 3935 517D 20 8B 51 jsr PARSEKEY ; how was the key? + 3936 5180 B0 C3 bcs GKEY0 ;TRY AGAIN + 3937 5182 85 AC sta IOCHAR ;HOLD ON TO IT + 3938 5184 68 pla ; RESTORE + 3939 5185 A8 tay ; EVERYTHING + 3940 5186 68 pla + 3941 5187 AA tax + 3942 5188 A5 AC lda IOCHAR ; GET CHAR INTO [A] + 3943 518A 60 rts ; AND RETURN IT + 3944 + 3945 ; + 3946 ; CHECK TO MAKE SURE KEY IS VALID, ONLY ACCEPT IT IF IT IS + 3947 ; + 3948 518B PARSEKEY: + 3949 518B 29 7F and #$7F ;SCREEN OUT SHIFTS + 3950 ; + 3951 ;CHECK FOR "ARROWS" & FUNCTION KEYS (X), CONVERT FOR USE (EZIP) + 3952 ;ALSO : CHANGE <_>)@%^&*( TO ,-.0256789 - and 'mouse' clicks + 3953 ; and other kinds of special chars + 3954 ; + 3955 518D GK0: + 3956 518D A2 12 ldx #ENDKEY ; GET LENGTH OF LIST + 3957 518F GK2: + 3958 518F DD D4 51 cmp HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + 3959 5192 F0 05 beq GK3 ; FOUND IT + 3960 5194 CA dex + 3961 5195 10 F8 bpl GK2 ; CHECK THEM ALL + Wed Jun 7 1989 12:04 Page 59 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3962 5197 30 05 bmi GK4 ; NOT FOUND, CONTINUE OTHER CHECKS + 3963 5199 GK3: + 3964 5199 BD E7 51 lda WANT,X ; GET KEY TO USE INSTEAD + 3965 519C 18 clc ; show niceness + 3966 519D 60 rts ; done + 3967 519E GK4: + 3968 519E C9 20 cmp #SPACE ; NO CTRL CHARS ACCEPTABLE + 3969 51A0 90 14 bcc BADKEY ; IF < SPACE, BAD + 3970 + 3971 51A2 C9 3C cmp #'<' ; pick up numbers and most punctuation + 3972 51A4 90 15 bcc OK ; we did + 3973 + 3974 51A6 C9 7B cmp #'z'+1 ;PICK OUT LETTERS NOW + 3975 51A8 B0 0C bcs BADKEY ;IF > BAD + 3976 51AA C9 61 cmp #'a' + 3977 51AC B0 0D bcs OK ;IF > OK + 3978 51AE C9 41 cmp #'A' + 3979 51B0 90 04 bcc BADKEY + 3980 51B2 C9 5B CMP #'Z'+1 + 3981 51B4 90 05 BCC OK ;IF < OK + 3982 51B6 BADKEY: + 3983 51B6 20 C3 4E jsr BEEP ;BAD KEY, GIVE WARNING NOISE, gwon back + 3984 51B9 38 sec ; show badness + 3985 51BA 60 rts ; and done + 3986 51BB OK: + 3987 51BB C9 30 cmp #'0' ; check for number keys + 3988 51BD 90 13 bcc OKj ; nope, < 0 + 3989 51BF C9 3A cmp #'9'+1 ; more than a nine? + 3990 51C1 B0 0F bcs OKj ; ayyup + 3991 ; + 3992 ; here we check for the closed apple key being down too + 3993 ; + 3994 51C3 AE 62 C0 ldx APKEY2 ; how about the closed apple key + 3995 51C6 10 0A bpl OKj ; not pressed, so use as number key + 3996 ; + 3997 ; transform number key into a function key + 3998 ; + 3999 51C8 18 CLC ; get ready for add + 4000 51C9 69 54 ADC #84 ; transforms '1'-'9' to 133-141 + 4001 51CB C9 84 CMP #132 ; but '0' wants to be a 142! + 4002 51CD D0 03 BNE OKj ; but it's not it + 4003 51CF 18 CLC ; again, don't want carry + 4004 51D0 69 0A ADC #10 ; voila! + 4005 51D2 OKj: + 4006 51D2 18 clc ; show a wicked good character is about to arrive + 4007 51D3 60 rts ; toots finis + 4008 + 4009 51D4 0B 0A 08 15 7F HAVE: DB $0B,$0A,$08,$15,$7f,ESCAPE,$3C,$7C,$3F + 51D9 1B 3C 7C 3F + 4010 51DD 3C 5F 3E 40 25 DB $3C,$5F,$3E,$40,$25,$5E,$26,$01,$02, EOL + 51E2 5E 26 01 02 0D + 4011 51E7 81 82 83 84 08 WANT: DB 129,130,131,132,08,ESCAPE,$3C,$7C,$3F + 51EC 1B 3C 7C 3F + 4012 51F0 2C 2D 2E 32 35 DB $2C,$2D,$2E,$32,$35,$36,$37,254,253, EOL + 51F5 36 37 FE FD 0D + 4013 0012 ENDKEY EQU $-WANT-1 + 4014 + 4015 51FA END + 4016 + 4017 51FA INCLUDE IO.ASM + 4018 51FA STTL "--- GAME I/O: APPLE II ---" + 4019 PAGE + Wed Jun 7 1989 12:04 Page 60 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4020 + 4021 ; -------------- + 4022 ; INTERNAL ERROR + 4023 ; -------------- + 4024 ; ENTRY: ERROR CODE IN [A] + 4025 ; EXIT: HA! + 4026 + 4027 51FA 0D 49 6E 74 65 ERRM: DB EOL,"Internal error " + 51FF 72 6E 61 6C 20 + 5204 65 72 72 6F 72 + 5209 20 + 4028 0010 ERRML EQU $-ERRM + 4029 + 4030 520A ZERROR: + 4031 520A 48 pha ; save err number + 4032 520B 20 A9 4C jsr SWAP2INFOW ; go to the info window (window 0)` + 4033 520E DLINE ERRM ; print message + 4034 520E A2 FA ldx #ERRM ; get other part of string + 4036 [01] IFMA 2 ; check to see if length passed in + 4037 ldy ; then just fetch it + 4038 [01] ELSE + 4039 5212 A0 10 ldy #ERRML ; get length of string + 4040 [00] ENDIF + 4041 5214 20 6B 4C jsr DLINE ; print the string + 4042 5217 .MACEND + 4043 5217 68 pla ; get error number + 4044 5218 20 D3 47 jsr HEXNUM ; print error number + 4045 521B 4C 21 52 jmp ZQUIT1 ; and die + 4046 + 4047 + 4048 ; ---- + 4049 ; QUIT + 4050 ; ---- + 4051 + 4052 521E 20 E7 54 ZQUIT: JSR ZCRLF ; FLUSH BUFFER + 4053 5221 ZQUIT1: + 4054 5221 DLINE ENDM ; print ending message + 4055 5221 A2 8C ldx #ENDM ; get other part of string + 4057 [01] IFMA 2 ; check to see if length passed in + 4058 ldy ; then just fetch it + 4059 [01] ELSE + 4060 5225 A0 10 ldy #ENDML ; get length of string + 4061 [00] ENDIF + 4062 5227 20 6B 4C jsr DLINE ; print the string + 4063 522A .MACEND + 4064 522A 20 E0 8C jsr GETRET ; wait for + 4065 522D A5 59 lda INFODOS ; in dinky-dos? + 4066 522F F0 17 beq ZQUIT2 ; nope + 4067 5231 A9 00 lda #0 ; clear power up byte + 4068 5233 8D F4 03 sta $3F4 ; make it do cold boot + 4069 5236 AD FD FF lda RESET_VECTOR+HI ; now, set up where to die to + 4070 5239 8D 47 52 sta ZQUITR1+2 + 4071 523C AD FC FF lda RESET_VECTOR+LO + 4072 523F 8D 46 52 sta ZQUITR1+1 + 4073 5242 AD 82 C0 lda RDROM ; get ROM back + 4074 5245 ZQUITR1: + 4075 5245 4C FC FF jmp RESET_VECTOR ; just reset things + 4076 ; + 4077 ; re-enable /RAM + 4078 ; + 4079 5248 ZQUIT2: + 4080 5248 AE 31 BF ldx DEVCNT ; put device in at end + 4081 524B E8 inx ; point to one past end + 4082 524C 8E 31 BF stx DEVCNT ; show new count + 4083 524F A9 BF lda #$BF ; /RAM ID + 4084 5251 9D 32 BF sta DEVNUM,X ; save it + 4085 5254 AD 7F 07 lda OLDVEC+HI ; restore old vector + 4086 5257 8D 27 BF sta RAMVEC+HI + 4087 525A AD 7E 07 lda OLDVEC+LO + 4088 525D 8D 26 BF sta RAMVEC+LO + 4089 ; + 4090 ; now format /RAM + 4091 ; + Wed Jun 7 1989 12:04 Page 61 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4092 5260 A9 03 lda #3 ; stash into FORMAT parm block + 4093 5262 85 42 sta $42 ; it goes here, oddly enough + 4094 5264 A9 B0 lda #$B0 ; device id for /RAM + 4095 5266 85 43 sta $43 ; and here it goes + 4096 5268 A9 11 lda #>GAME1FIO ; IO buffer + 4097 526A 85 45 sta $45 ; this is where it goes + 4098 526C A9 00 lda #BOOTNAME + 4142 52C2 8D D8 45 sta OPEN_FILE+OP_PATHNAME+HI + 4143 52C5 A9 31 lda #'1' ; set disk name to disk #1 + 4144 52C7 8D C5 49 sta SAVENUM ; show open_gamef + 4145 52CA 20 22 4B jsr OPEN_GAMEF ; okay + 4146 + 4147 52CD AD DB 45 lda OPEN_FILE+OP_REFNUM ; get ref num + 4148 52D0 8D 9D 52 sta BOOT_RD+RD_REFNUM ; save ref num + 4149 52D3 8D 0C 8B sta CLOSE_PB+CL_REFNUM + 4150 52D6 READ BOOT_RD ; read in boot system + 4151 52D6 PRODOS $CA, BOOT_RD + 4152 52D6 20 00 BF jsr $BF00 ; ProDOS handler + 4153 52D9 CA DB $CA ; ProDOS function code + 4154 52DA 9C52 DW BOOT_RD ; Function Parameter Block address + 4155 52DC .MACEND + 4156 52DC .MACEND + 4157 52DC 90 03 bcc ZSTRTX ; okay, everything is fine + 4158 52DE 4C 74 47 jmp DISK_FATAL ; die otherwise + 4159 52E1 ZSTRTX: + 4160 52E1 CLOSE CLOSE_PB ; and close it up + Wed Jun 7 1989 12:04 Page 62 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4161 52E1 PRODOS $CC, CLOSE_PB + 4162 52E1 20 00 BF jsr $BF00 ; ProDOS handler + 4163 52E4 CC DB $CC ; ProDOS function code + 4164 52E5 0B8B DW CLOSE_PB ; Function Parameter Block address + 4165 52E7 .MACEND + 4166 52E7 .MACEND + 4167 52E7 4C 00 20 jmp BORG ; and go to it + 4168 52EA + 4169 ; -------------------------------- + 4170 ; RETURN RANDOM BYTES IN [A] & [X] + 4171 ; -------------------------------- + 4172 52EA RANDOM: + 4173 52EA E6 A5 inc RAND+HI + 4174 52EC C6 A4 dec RAND+LO + 4175 52EE A5 A4 lda RAND+LO ; get LSB + 4176 52F0 65 A5 adc RAND+HI ; add MSB + 4177 52F2 29 7F and #$7F ; don't let it go into $C0 page + 4178 52F4 85 A5 sta RAND+HI ; new MSB + 4179 52F6 A8 tay ; get random offset + 4180 52F7 B1 A4 lda (RAND),Y ; get random number + 4181 52F9 AA tax ; save in X + 4182 52FA 65 A4 adc RAND+LO ; and go to another spot + 4183 52FC 29 7F and #$7F ; don't go above $80 + 4184 52FE 85 A5 sta RAND+HI ; okay + 4185 5300 A8 tay ; more randomness + 4186 5301 B1 A4 lda (RAND),Y ; and get it again + 4187 5303 05 A5 ora RAND+HI ; set more bits + 4188 5305 60 rts + 4189 + 4190 + 4191 ; ------------------- + 4192 ; Z-PRINT A CHARACTER + 4193 ; ------------------- + 4194 ; ENTRY: ASCII CHAR IN [A] + 4195 ; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, + 4196 ; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN + 4197 ; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME + 4198 ; (DIROUT CHANGES 6/24/85) + 4199 + 4200 5306 COUT: + 4201 5306 85 AC sta IOCHAR ; HOLD IT A SEC + 4202 5308 A6 B2 ldx TABLEF ; OUTPUT TO TABLE? + 4203 530A F0 07 beq COUT1 ; NO + 4204 530C A6 19 ldx FMTTBL ; formatted table? + 4205 530E D0 0D bne COUT5 ; yes, so just do it normal + 4206 5310 4C 86 53 jmp TBLOUT ; just put into table + 4207 5313 COUT1: + 4208 5313 A6 B1 ldx SCREENF ; OUTPUT TO SCREEN? + 4209 5315 D0 06 bne COUT5 ; YES + 4210 5317 AE 78 6C ldx SCRIPTF ; OUTPUT TO PRINTER? + 4211 531A D0 01 bne COUT5 ; YES + 4212 531C 60 rts ; NO, SO DONE + 4213 531D COUT5: + 4214 531D A5 AC lda IOCHAR ; RETRIEVE CHAR + 4215 531F 30 5B bmi COUT2 ; highlight chars have no width + 4216 ; + 4217 ; this is an entry point for DLINE, so it doesn't check any of the above + 4218 ; things. Enter with character in [A] + 4219 ; + 4220 5321 DIRECT_OUT: + 4221 5321 C9 0D cmp #EOL ; IF ASCII EOL, just handle it special + 4222 5323 D0 03 bne COUT0 + 4223 + 4224 5325 4C E7 54 jmp ZCRLF ; DO IT + 4225 5328 COUT0: + 4226 5328 B0 20 bcs COUT02 ; not control character + 4227 532A C9 0B cmp #EOS ; control-k (end of sentence)? + 4228 532C F0 0E beq COUT01 ; yes, so put out 2 spaces + 4229 532E C9 09 cmp #TAB ; tab char? + 4230 5330 D0 53 bne CEX ; ignore all other control chars + 4231 ; + 4232 ; this means do a couple of spaces + 4233 ; + 4234 5332 A9 20 lda #SPACE ; do 3 spaces for start of line + 4235 5334 20 06 53 jsr COUT ; a little recursion never hurt! + Wed Jun 7 1989 12:04 Page 63 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4236 5337 A6 A9 ldx CHRCNT ; back to beginning of line? + 4237 5339 D0 01 bne COUT01 ; nope + 4238 533B COUT010: + 4239 533B 60 rts ; don't do any to start line + 4240 533C COUT01: + 4241 533C A9 20 lda #SPACE ; 2 more spaces + 4242 533E 20 06 53 jsr COUT + 4243 5341 A6 A9 ldx CHRCNT ; back to zero? + 4244 5343 F0 F6 beq COUT010 ; yes, so don't add to start of line + 4245 + 4246 5345 A9 20 lda #SPACE ; last one + 4247 5347 4C 06 53 jmp COUT ; finally + 4248 534A COUT02: + 4249 534A AA tax ; use char as index + 4250 534B A5 C1 lda FONTFLG ; get which font we be using + 4251 534D F0 04 beq COUTF1 ; must be variable width + 4252 534F A9 0C lda #MONOFONT_W ; get width then of mono font + 4253 5351 D0 03 bne COUTF2 ; okay, now do add + 4254 5353 COUTF1: + 4255 5353 BD 2A 64 lda CHWID,X ; get width of char + 4256 5356 COUTF2: + 4257 5356 18 clc ; get ready for add + 4258 5357 65 A7 adc LENGTH+LO ; ADD LINE LENGTH COUNTER + 4259 5359 85 A7 sta LENGTH+LO ; update length + 4260 535B 90 02 bcc COUT0C ; no wrap + 4261 535D E6 A8 inc LENGTH+HI ; okay, wrap then + 4262 535F COUT0C: + 4263 535F A5 A8 lda LENGTH+HI ; get MSB + 4264 5361 C5 A3 cmp XSIZE+HI ; check MSB first + 4265 5363 90 17 bcc COUT2 ; no need to check lsb + 4266 5365 D0 06 bne COUT00 ; XSIZE < LENGTH? + 4267 5367 + 4268 5367 A5 A7 lda LENGTH+LO ; check LSB + 4269 5369 C5 A2 cmp XSIZE+LO ; END OF SCREEN LINE? + 4270 536B 90 0F bcc COUT2 ; haven't reached the end if XSIZE > LENGTH + 4271 536D COUT00: + 4272 536D AC DB 71 ldy WRPFLG ; are we wrapping + 4273 5370 F0 13 beq CEX ; no, so truncate + 4274 5372 A6 A9 ldx CHRCNT ; get character count + 4275 5374 A5 AC lda IOCHAR ; get the character + 4276 5376 9D 00 02 sta LBUFF,X ; save current char in buffer + 4277 5379 4C 73 54 jmp FLUSH ; YES, FLUSH THE LINE + 4278 537C COUT2: + 4279 537C A6 A9 ldx CHRCNT ; GET LINE POINTER + 4280 537E A5 AC lda IOCHAR ; get char back + 4281 5380 9D 00 02 sta LBUFF,X ; ADD CHAR TO BUFFER + 4282 5383 E6 A9 inc CHRCNT ; and point to next CHRCNT + 4283 5385 CEX: + 4284 5385 60 rts + 4285 5386 + 4286 ; --------------- + 4287 ; OUTPUT TO TABLE + 4288 ; --------------- + 4289 ; + 4290 ; this one just puts a char into the table + 4291 ; + 4292 5386 TBLOUT: + 4293 5386 AA tax ; HOLD CHAR A SEC. + 4294 ; + 4295 ; figger out length of line in there + 4296 ; + 4297 5387 A5 C1 lda FONTFLG ; get which font we be using + 4298 5389 F0 04 beq TBLOUT1 ; must be variable width + 4299 538B A9 0C lda #MONOFONT_W ; get width then of mono font + 4300 538D D0 03 bne TBLOUT2 ; okay, now do add + 4301 538F TBLOUT1: + 4302 538F BD 2A 64 lda CHWID,X ; get width of char + 4303 5392 TBLOUT2: + 4304 5392 18 clc ; add width + 4305 5393 6D 31 96 adc ZBEGIN+ZTWIDTH+1 ; to current line width + 4306 5396 8D 31 96 sta ZBEGIN+ZTWIDTH+1 ; save current width + 4307 5399 90 03 bcc TBLOUT3 ; no wrap + 4308 539B EE 30 96 inc ZBEGIN+ZTWIDTH+0 ; wrap, then dammit + 4309 539E TBLOUT3: + 4310 ; + Wed Jun 7 1989 12:04 Page 64 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4311 ; PUT BYTE IN TABLE AT CURRENT OFFSET + 4312 ; + 4313 539E AD 85 6C lda DIRITM+LO ; ADD IN OFFSET + 4314 53A1 18 clc + 4315 53A2 65 A0 adc DIRTBL+LO + 4316 53A4 85 8F sta SPCL ; and make it lo part + 4317 53A6 AD 86 6C lda DIRITM+HI + 4318 53A9 65 A1 adc DIRTBL+HI + 4319 53AB 20 7C 8F jsr SETPC ; set the PC + 4320 53AE 85 90 sta SPCH ; and this is high part + 4321 53B0 84 91 sty SPCBNK ; and the bank + 4322 53B2 8A txa ; PICK UP ASCII CHAR + 4323 53B3 20 3A 92 jsr STASHB ; and save it + 4324 ; + 4325 ; SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER + 4326 ; + 4327 53B6 EE 85 6C inc DIRITM+LO ; INC OFFSET TO NEXT BYTE + 4328 53B9 D0 03 bne TBLRTS + 4329 53BB EE 86 6C inc DIRITM+HI + 4330 53BE TBLRTS: + 4331 53BE 60 rts + 4332 ; + 4333 ; PUT LBUFF IN TABLE AT CURRENT OFFSET + 4334 ; + 4335 53BF TBLRTN: + 4336 53BF AD 85 6C lda DIRITM+LO ; get where we are + 4337 53C2 18 clc + 4338 53C3 65 A0 adc DIRTBL+LO ; ADD IN OFFSET + 4339 53C5 85 8F sta SPCL ; and make it lo part + 4340 53C7 85 8C sta FPCL ; save for later usage + 4341 53C9 AD 86 6C lda DIRITM+HI ; get hi part + 4342 53CC 65 A1 adc DIRTBL+HI + 4343 53CE 20 7C 8F jsr SETPC ; set the PC + 4344 53D1 85 90 sta SPCH ; and this is high part + 4345 53D3 85 8D sta FPCH ; saving + 4346 53D5 84 91 sty SPCBNK ; and the bank + 4347 53D7 84 8E sty FPCBNK ; and here too + 4348 53D9 A9 00 lda #0 ; start counter off at zero + 4349 53DB 85 7A sta J ; use J + 4350 53DD 85 7D sta K+HI ; this will be line length + 4351 53DF 85 7C sta K+LO ; both parts, please + 4352 53E1 20 A3 8F jsr NEXTSPC ; point past the counter + 4353 53E4 TBLOOP: + 4354 53E4 A4 7A ldy J ; get offset + 4355 53E6 B9 00 02 lda LBUFF,Y ; get char + 4356 53E9 AA tax ; save char + 4357 53EA 30 19 bmi TBLP1 ; don't count hi light chars + 4358 53EC C9 20 cmp #SPACE ; see if less than a space + 4359 53EE 90 15 bcc TBLP1 ; no width if <$20 + 4360 53F0 AA tax ; use char as index + 4361 + 4362 53F1 A5 C1 lda FONTFLG ; get which font we be using + 4363 53F3 F0 04 beq TBLF1 ; must be variable width + 4364 53F5 A9 0C lda #MONOFONT_W ; get width then of mono font + 4365 53F7 D0 03 bne TBLF2 ; okay, now do add + 4366 53F9 TBLF1: + 4367 53F9 BD 2A 64 lda CHWID,X ; get width of char + 4368 53FC TBLF2: + 4369 53FC 18 clc ; add width + 4370 53FD 65 7C adc K+LO ; to current line width + 4371 53FF 85 7C sta K+LO ; save current width + 4372 5401 90 02 bcc TBLP1 ; no wrap + 4373 5403 E6 7D inc K+HI ; wrap, then dammit + 4374 5405 TBLP1: + 4375 5405 8A txa ; get char back + 4376 5406 20 3A 92 jsr STASHB ; and save it + 4377 5409 20 A3 8F jsr NEXTSPC ; next table entry + 4378 540C E6 7A inc J ; point to next char + 4379 540E C6 A9 dec CHRCNT ; decrement counter + 4380 5410 D0 D2 bne TBLOOP ; get next one + 4381 ; + 4382 ; now fill with necessary spaces + 4383 ; + 4384 5412 A5 C1 lda FONTFLG ; first, set up width to be added + 4385 5414 F0 04 beq TBLSPF1 ; must be variable width font + Wed Jun 7 1989 12:04 Page 65 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4386 5416 A9 0C lda #MONOFONT_W ; get mono width + 4387 5418 D0 05 bne TBLSPF2 ; okay + 4388 541A TBLSPF1: + 4389 541A A2 20 ldx #SPACE ; get space index + 4390 541C BD 2A 64 lda CHWID,X ; okay + 4391 541F TBLSPF2: + 4392 541F 85 71 sta ARG8 ; use temporarily + 4393 5421 TBLSP: + 4394 5421 A5 7C lda K+LO ; get how big line is + 4395 5423 18 clc ; add in space + 4396 5424 65 71 adc ARG8 ; pick up space width + 4397 5426 85 7C sta K+LO ; saved + 4398 5428 90 02 bcc TBLSP1 ; no wrap? + 4399 542A E6 7D inc K+HI ; yes, wrapping + 4400 542C TBLSP1: + 4401 542C A5 A3 lda XSIZE+HI ; check against end + 4402 542E C5 7D cmp K+HI ; compare against max width + 4403 5430 90 14 bcc TBLSPX ; all done then + 4404 5432 D0 06 bne TBLSP2 ; no need to check if <> + 4405 5434 A5 A2 lda XSIZE+LO ; check LSB + 4406 5436 C5 7C cmp K+LO ; well? + 4407 5438 90 0C bcc TBLSPX ; all done then + 4408 543A TBLSP2: + 4409 543A A9 20 lda #SPACE ; get it + 4410 543C 20 3A 92 jsr STASHB ; save it + 4411 543F 20 A3 8F jsr NEXTSPC ; point to next one + 4412 5442 E6 7A inc J ; count it + 4413 5444 D0 DB bne TBLSP ; and continue + 4414 5446 TBLSPX: + 4415 5446 A9 00 lda #0 ; show end of table + 4416 5448 85 A7 sta LENGTH+LO ; clear out line length too + 4417 544A 85 A8 sta LENGTH+HI ; and hi part too + 4418 544C 20 3A 92 jsr STASHB ; marked with a zero + 4419 544F 20 78 90 jsr FP2SP ; have SPC point to beginning + 4420 5452 A9 00 lda #0 ; upper byte of count is zero + 4421 5454 20 3A 92 jsr STASHB ; show it + 4422 5457 20 A3 8F jsr NEXTSPC ; point to LSB + 4423 545A A5 7A lda J ; get how many chars are there + 4424 545C 20 3A 92 jsr STASHB ; save at beginning of line + 4425 545F E6 7A inc J ; count counter in offset + 4426 5461 A5 7A lda J ; get J back + 4427 5463 18 clc ; add in where we were + 4428 5464 6D 85 6C adc DIRITM+LO ; okay with lo part + 4429 5467 8D 85 6C sta DIRITM+LO ; save it + 4430 546A AD 86 6C lda DIRITM+HI ; and now the hi part + 4431 546D 69 00 adc #0 ; pick up carry, maybe + 4432 546F 8D 86 6C sta DIRITM+HI ; and save it + 4433 5472 60 rts + 4434 + 4435 ; ------------------- + 4436 ; FLUSH OUTPUT BUFFER + 4437 ; ------------------- + 4438 ; ENTRY: LENGTH OF BUFFER IN [X] + 4439 + 4440 5473 FLUSH: + 4441 5473 A9 20 lda #SPACE ; SPACE CHAR + 4442 5475 8E 68 6C stx OLDEND ; SAVE CURRENT END OF LINE + 4443 5478 FL0: + 4444 5478 DD 00 02 cmp LBUFF,X ; FIND LAST SPACE CHAR + 4445 547B F0 06 beq FL1 ; IN THE LINE + 4446 547D CA dex + 4447 547E D0 F8 bne FL0 ; IF NONE FOUND, + 4448 5480 A6 A9 ldx CHRCNT ; FLUSH ENTIRE LINE + 4449 5482 CA dex ; minus last one + 4450 5483 FL1: + 4451 5483 8E 67 6C stx OLDLEN ; SAVE OLD LINE POS HERE + 4452 5486 86 A9 stx CHRCNT ; MAKE IT THE NEW LINE LENGTH + 4453 5488 + 4454 5488 A5 B2 lda TABLEF ; are we doing table I/O? + 4455 548A F0 06 beq FL11 ; nope + 4456 548C 20 BF 53 jsr TBLRTN ; YES, DO IT + 4457 548F 4C 95 54 jmp FL12 ; so refill line + 4458 5492 FL11: + 4459 5492 20 E7 54 jsr ZCRLF ; PRINT LINE UP TO LAST SPACE + 4460 ; + Wed Jun 7 1989 12:04 Page 66 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4461 ; START NEW LINE WITH REMAINDER OF OLD + 4462 ; + 4463 5495 FL12: + 4464 5495 AE 67 6C ldx OLDLEN ; GET OLD LINE POS + 4465 5498 A0 00 ldy #0 ; START NEW LINE AT BEGINNING + 4466 549A FL2: + 4467 549A E8 inx + 4468 549B EC 68 6C cpx OLDEND ; CONTINUE IF + 4469 549E 90 05 bcc FL3 ; INSIDE of end of line + 4470 54A0 F0 03 beq FL3 ; or at end of line + 4471 54A2 84 A9 sty CHRCNT + 4472 54A4 60 rts + 4473 54A5 FL3: + 4474 54A5 BD 00 02 lda LBUFF,X ; GET CHAR FROM OLD LINE + 4475 54A8 C9 20 cmp #SPACE ; don't move start spaces in either + 4476 54AA F0 25 beq FL4 ; fine, I won't + 4477 54AC 99 00 02 sta LBUFF,Y ; MOVE TO START OF NEW LINE + 4478 54AF 30 20 bmi FL4 ; don't count hi light chars + 4479 54B1 C9 20 cmp #SPACE ; don't count control chars + 4480 54B3 90 1C bcc FL4 ; okay + 4481 54B5 8A txa ; save current x + 4482 54B6 48 pha ; saved + 4483 54B7 A5 C1 lda FONTFLG ; get which font we be using + 4484 54B9 F0 04 beq FLSF1 ; must be variable width + 4485 54BB A9 0C lda #MONOFONT_W ; get width then of mono font + 4486 54BD D0 07 bne FLSF2 ; okay, now do add + 4487 54BF FLSF1: + 4488 54BF BD 00 02 lda LBUFF,X ; get char back + 4489 54C2 AA tax ; make index + 4490 54C3 BD 2A 64 lda CHWID,X ; get width of char + 4491 54C6 FLSF2: + 4492 54C6 18 clc ; get ready for add + 4493 54C7 65 A7 adc LENGTH+LO ; okay, now add char width + 4494 54C9 85 A7 sta LENGTH+LO ; save new length + 4495 54CB 68 pla ; get old X back + 4496 54CC AA tax ; okay + 4497 54CD 90 02 bcc FL4 ; no wrap + 4498 54CF E6 A8 inc LENGTH+HI + 4499 54D1 FL4: + 4500 54D1 C8 iny ; UPDATE # OF chars in NEW LINE + 4501 54D2 D0 C6 bne FL2 ; (ALWAYS) + 4502 + 4503 + 4504 ; --------------- + 4505 ; CARRIAGE RETURN + 4506 ; --------------- + 4507 + 4508 54D4 ZZCRLF: + 4509 54D4 A6 B2 ldx TABLEF ; OUTPUT TO TABLE? + 4510 54D6 F0 0F beq ZCRLF ; NO + 4511 ; + 4512 ; if putting a into table, just add to line buffer and flush + 4513 ; + 4514 54D8 A9 0D lda #EOL ; get carriage return char + 4515 54DA A4 A9 ldy CHRCNT ; add to lbuff + 4516 54DC 99 00 02 sta LBUFF,Y ; got it + 4517 54DF E6 A9 inc CHRCNT ; now flush it + 4518 54E1 20 BF 53 jsr TBLRTN ; YES, DO IT (TBL ONLY) + 4519 54E4 4C 5D 55 jmp ZCRLFX ; git out + 4520 54E7 ZCRLF: + 4521 54E7 A6 A9 ldx CHRCNT ; how far have we gone + 4522 54E9 A9 0D lda #EOL ; get carriage return char + 4523 54EB 9D 00 02 sta LBUFF,X ; END OF CURRENT LINE + 4524 54EE E6 A9 inc CHRCNT ; UPDATE LINE LENGTH + 4525 54F0 20 66 55 jsr LINOUT ; DISPLAY LINE + 4526 + 4527 ; + 4528 ; now check about line count + 4529 ; + 4530 54F3 A9 00 lda #0 + 4531 54F5 85 A9 sta CHRCNT ; AND RESET LINE COUNT + 4532 54F7 85 A7 sta LENGTH+LO ; okay + 4533 54F9 85 A8 sta LENGTH+HI ; okay + 4534 + 4535 54FB 20 84 55 jsr CHKFNC ; CHECK FOR CR FUNCTION (XZIP) + Wed Jun 7 1989 12:04 Page 67 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4536 + 4537 54FE A5 B1 lda SCREENF ; CHECK IF DISPLAYING TO SCREEN + 4538 5500 F0 5B beq ZCRLFX ; NO, GO HANDLE IF PRINTING + 4539 5502 AD DC 71 lda SCRLFLG ; is it a scrolling window? + 4540 5505 F0 56 beq ZCRLFX ; nope, so no more + 4541 5507 E6 AB inc LINCNT ; NEW LINE GOING OUT + 4542 + 4543 5509 A6 AB ldx LINCNT ; IS IT TIME TO + 4544 550B E4 03 cpx MAXLINES ; PRINT "MORE" YET? + 4545 550D 90 4E bcc ZCRLFX ; NO, CONTINUE + 4546 + 4547 550F A9 01 lda #1 ; leave one line from last screen, and input line + 4548 5511 85 AB sta LINCNT ; RESET LINE COUNTER + 4549 5513 A5 04 lda LEFTMRG ; SET LEFT MARGIN + 4550 5515 85 00 sta SCRCX + 4551 5517 A9 01 lda #1 ; show cursor changed (maybe) + 4552 5519 8D 7C 6C sta CURSFLG ; okay + 4553 ; + 4554 ; print [MORE] out myself, to avoid re-entrancy problems + 4555 ; + 4556 551C AD 78 6C lda SCRIPTF ; make sure we don't script + 4557 551F 48 pha + 4558 5520 A2 00 ldx #0 ; start with first char + 4559 5522 8E 78 6C stx SCRIPTF ; clear script flag + 4560 5525 86 18 stx SCLLINES ; use this as a counter + 4561 5527 MORELOOP: + 4562 5527 BD 6B 5B lda MORE,X ; get char + 4563 552A 85 AC sta IOCHAR ; save it + 4564 552C 20 21 53 jsr DIRECT_OUT ; pump it out there + 4565 552F E6 18 inc SCLLINES ; count char + 4566 5531 A6 18 ldx SCLLINES ; how many have we done + 4567 5533 E0 06 cpx #MOREL ; done? + 4568 5535 D0 F0 bne MORELOOP ; nope + 4569 + 4570 5537 20 B5 55 jsr CLRBUF ; make sure it shows + 4571 553A WAIT: + 4572 553A 20 31 51 jsr GETKEY ; wait for key please + 4573 553D A9 05 lda #MOREL-1 ; how many backspaces + 4574 553F 85 A7 sta LENGTH ; just use this as counter + 4575 5541 WM11: + 4576 5541 A6 A7 ldx LENGTH ; which char? + 4577 5543 BD 6B 5B lda MORE,X ; get char + 4578 5546 AA tax ; put here for erase + 4579 5547 A9 08 lda #BACKSPACE ; erase char + 4580 5549 20 82 5D jsr CHAR + 4581 554C C6 A7 dec LENGTH ; count it + 4582 554E 10 F1 bpl WM11 + 4583 5550 68 pla ; get script flag back + 4584 5551 8D 78 6C sta SCRIPTF ; fine + 4585 5554 A5 04 lda LEFTMRG ; move back to left margin + 4586 5556 85 00 sta SCRCX ; okay + 4587 5558 A9 01 lda #1 ; show cursor changed (maybe) + 4588 555A 8D 7C 6C sta CURSFLG ; okay + 4589 555D ZCRLFX: + 4590 555D A9 00 lda #0 + 4591 555F 85 A9 sta CHRCNT ; AND RESET LINE COUNT + 4592 5561 85 A7 sta LENGTH+LO ; okay + 4593 5563 85 A8 sta LENGTH+HI + 4594 5565 60 rts + 4595 5566 LINOUT: + 4596 5566 A4 A9 ldy CHRCNT ; IF BUFFER EMPTY, + 4597 5568 F0 19 beq LINEX ; DON'T PRINT ANYTHING + 4598 556A 8C 6E 6C sty PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + 4599 556D A5 B1 lda SCREENF ; DISPLAY TO SCREEN? + 4600 556F F0 0F beq LOUT1 ; NO, GO CHECK IF PRINT + 4601 5571 A2 00 ldx #0 ; SEND CONTENTS OF [LBUFF] + 4602 5573 LOUT: + 4603 5573 BD 00 02 lda LBUFF,X ; TO SCREEN + 4604 5576 20 82 5D jsr CHAR + 4605 5579 E8 inx + 4606 557A 88 dey + 4607 557B D0 F6 bne LOUT + 4608 557D 20 F1 71 jsr DISP_LINE ; make sure line gets printed + 4609 5580 20 DF 4C LOUT1: JSR PPRINT ; PRINT [LBUFF] IF ENABLED + 4610 5583 LINEX: + Wed Jun 7 1989 12:04 Page 68 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4611 5583 60 rts ; AND RETURN + 4612 ; + 4613 ; CHECK IF THERE IS A PENDING FUNCTION CALL ASSOCIATED WITH 'S + 4614 ; + 4615 5584 CHKFNC: + 4616 5584 A0 0B ldy #WINCRC+HI ; get function offset + 4617 5586 B1 05 lda (WINDOW),Y ; IF NULL IGNORE + 4618 5588 88 dey ; point to lo part + 4619 5589 11 05 ora (WINDOW),Y + 4620 558B F0 26 beq CHKOUT + 4621 + 4622 558D AD A8 6C lda CRLF_CHECK ; do we really want to do this? + 4623 5590 F0 21 beq CHKOUT ; nope + 4624 + 4625 5592 B1 05 lda (WINDOW),Y ; DECR COUNTER + 4626 5594 38 sec + 4627 5595 E9 01 sbc #1 + 4628 5597 91 05 sta (WINDOW),Y + 4629 5599 C8 iny + 4630 559A B1 05 lda (WINDOW),Y ; work on hi part + 4631 559C E9 00 sbc #0 ; pick up carry + 4632 559E 91 05 sta (WINDOW),Y ; save it + 4633 55A0 88 dey + 4634 55A1 11 05 ora (WINDOW),Y ; if NULL NOW, CALL FCN + 4635 55A3 D0 0E bne CHKOUT + 4636 + 4637 55A5 A0 08 ldy #WINCRF+LO ; pointing to routine + 4638 55A7 B1 05 lda (WINDOW),Y ; get lo part + 4639 55A9 85 7A sta J+LO ; and save in J + 4640 55AB C8 iny ; point to hi part + 4641 55AC B1 05 lda (WINDOW),Y ; got it + 4642 55AE 85 7B sta J+HI + 4643 55B0 20 18 5B jsr INTCLL ; DO FUNCTION CALL + 4644 55B3 CHKOUT: + 4645 55B3 60 rts + 4646 + 4647 + 4648 ; ---------------------- + 4649 ; UPDATE THE STATUS LINE + 4650 ; ---------------------- + 4651 ; NOT APPLICABLE IN EZIP. + 4652 + 4653 55B4 60 ZUSL: RTS + 4654 + 4655 ; ------ + 4656 ; BUFOUT + 4657 ; ------ + 4658 ; ENTER: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE + 4659 ; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO + 4660 ; + 4661 ; shouldn't need this in YZIP ?! + 4662 ; + 4663 55B5 ZBUFOUT: + 4664 ; + 4665 ; CLEAR OUTPUT BUFFER BEFORE DOING ANYTHING FANCY + 4666 ; + 4667 55B5 CLRBUF: + 4668 55B5 20 66 55 jsr LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) + 4669 55B8 A2 00 ldx #0 + 4670 55BA 86 A9 stx CHRCNT + 4671 55BC 60 rts + 4672 + 4673 ; ------ + 4674 ; DIROUT + 4675 ; ------ + 4676 ; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT + 4677 ; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT + 4678 ; MULTIPLE DEVICE USAGE IS POSSIBLE. + 4679 + 4680 55BD 00 00 SAVEXSIZE: db 0,0 ; for formatted table saving + 4681 + 4682 55BF ZDIRT: + 4683 55BF 20 B5 55 jsr CLRBUF ; send out anything there now! + 4684 + 4685 55C2 A6 63 ldx ARG1+LO + Wed Jun 7 1989 12:04 Page 69 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4686 55C4 30 0A bmi DIRRES ; NEGATIVE VALUE, DESELECTING + 4687 55C6 CA dex + 4688 55C7 F0 11 beq DIR1 ; 1 = SET OUTPUT TO SCREEN + 4689 55C9 CA dex + 4690 55CA F0 1E beq DIR2 ; 2 = SCRIPTING + 4691 55CC CA dex + 4692 55CD F0 3C beq DIR3 ; 3 = TABLE + 4693 55CF 60 rts ; INVALID VALUE + 4694 55D0 DIRRES: + 4695 55D0 E8 inx + 4696 55D1 F0 0F beq DRES1 ; -1 = RESET TO SCREEN + 4697 55D3 E8 inx + 4698 55D4 F0 29 beq DRES2 + 4699 55D6 E8 inx + 4700 55D7 F0 3A beq DRES3 + 4701 55D9 60 rts ; INVALID VALUE, JUST LEAVE + 4702 55DA DIR1: + 4703 55DA 20 B5 55 jsr CLRBUF + 4704 55DD A9 01 lda #1 ; turn screen on + 4705 55DF 85 B1 sta SCREENF + 4706 55E1 60 rts + 4707 55E2 DRES1: + 4708 55E2 20 B5 55 jsr CLRBUF + 4709 55E5 A9 00 lda #0 + 4710 55E7 85 B1 sta SCREENF ; 0, TURN SCREEN OFF + 4711 55E9 60 rts + 4712 55EA DIR2: + 4713 55EA E8 inx + 4714 55EB 8E 78 6C stx SCRIPTF ; SET SCRIPT FLAG ON + 4715 55EE AD 11 96 lda ZBEGIN+ZFLAGS+1 ; SET GAME FLAG ALSO + 4716 55F1 09 01 ora #%00000001 + 4717 55F3 8D 11 96 sta ZBEGIN+ZFLAGS+1 + 4718 55F6 AD 1B 4D lda PSTAT ; CHECK IF PRINTER ALREADY INIT'D + 4719 55F9 D0 03 bne DIR2A + 4720 55FB 20 31 4D jsr PCHK ; NO, GO DO IT + 4721 55FE DIR2A: + 4722 55FE 60 rts ; YES, READY TO LEAVE + 4723 55FF DRES2: + 4724 55FF 8E 78 6C stx SCRIPTF ; TURN PRINTER OFF + 4725 5602 AD 11 96 lda ZBEGIN+ZFLAGS+1 ; AND TURN OFF GAME FLAG TOO + 4726 5605 29 FE and #%11111110 + 4727 5607 8D 11 96 sta ZBEGIN+ZFLAGS+1 + 4728 560A 60 rts + 4729 560B DIR3: + 4730 560B 86 B1 stx SCREENF ; turn off screen + 4731 560D E8 inx + 4732 560E 86 B2 stx TABLEF ; TURN TABLE OUTPUT FLAG ON + 4733 5610 4C 7B 56 jmp START_TABLE ; and set things up + 4734 5613 DRES3: + 4735 5613 A5 B2 lda TABLEF ; IF OFF ALREADY + 4736 5615 F0 63 beq OUT3 ; LEAVE AS IS + 4737 + 4738 5617 86 B2 stx TABLEF ; TURN TBL OUTPUT OFF + 4739 5619 E8 inx ; turn screen back on + 4740 561A 86 B1 stx SCREENF ; screen back on + 4741 + 4742 561C A9 03 lda #3 ; add three to make it wrap + 4743 561E 18 clc ; ready for add + 4744 561F 6D 31 96 adc ZBEGIN+ZTWIDTH+1 ; do it + 4745 5622 8D 31 96 sta ZBEGIN+ZTWIDTH+1 + 4746 5625 90 03 bcc DRESCC ; no wrap into MSB + 4747 5627 EE 30 96 inc ZBEGIN+ZTWIDTH + 4748 562A DRESCC: + 4749 562A 4E 30 96 lsr ZBEGIN+ZTWIDTH+0 ; /4 to get # of pixels + 4750 562D 6E 31 96 ror ZBEGIN+ZTWIDTH+1 + 4751 5630 4E 30 96 lsr ZBEGIN+ZTWIDTH+0 + 4752 5633 6E 31 96 ror ZBEGIN+ZTWIDTH+1 + 4753 + 4754 + 4755 5636 A5 19 lda FMTTBL ; did we do a formatted table? + 4756 5638 D0 2B bne DRESFT ; yes, so fix things + 4757 ; + 4758 ; now put count into table + 4759 ; + 4760 563A A5 A0 lda DIRTBL+LO ; and put count into second byte of table + Wed Jun 7 1989 12:04 Page 70 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4761 563C 85 8F sta SPCL ; points to low par + 4762 563E A5 A1 lda DIRTBL+HI ; get page + 4763 5640 20 7C 8F jsr SETPC ; okay, page and bank + 4764 5643 85 90 sta SPCH + 4765 5645 84 91 sty SPCBNK + 4766 5647 AD 85 6C lda DIRITM+LO ; (2 LESS THAN [DIRITM]) + 4767 564A 38 sec + 4768 564B E9 02 sbc #2 + 4769 564D 8D 85 6C sta DIRITM+LO ; save this new count + 4770 5650 B0 03 bcs RESET0 + 4771 5652 CE 86 6C dec DIRITM+HI ; wrapped downwards + 4772 5655 RESET0: + 4773 5655 AD 86 6C lda DIRITM+HI ; get hi part + 4774 5658 20 3A 92 jsr STASHB ; saved that count + 4775 565B 20 A3 8F jsr NEXTSPC ; and point to lo part + 4776 565E AD 85 6C lda DIRITM+LO ; and get lo part + 4777 5661 20 3A 92 jsr STASHB ; and save it + 4778 5664 60 rts ; done + 4779 5665 DRESFT: + 4780 5665 A5 A9 lda CHRCNT ; anything in buffer? + 4781 5667 F0 03 beq DRES31 ; nope + 4782 5669 20 BF 53 jsr TBLRTN ; then fill out last line + 4783 566C DRES31: + 4784 566C AD BD 55 lda SAVEXSIZE+LO ; get old xsize back + 4785 566F 85 A2 sta XSIZE+LO ; restored + 4786 5671 AD BE 55 lda SAVEXSIZE+HI + 4787 5674 85 A3 sta XSIZE+HI + 4788 5676 A9 00 lda #0 ; reset this flag too + 4789 5678 85 19 sta FMTTBL ; cleared + 4790 567A OUT3: + 4791 567A 60 rts + 4792 ; + 4793 ; set things up for doing table output + 4794 ; + 4795 567B START_TABLE: + 4796 + 4797 567B A5 66 lda ARG2+HI ; SET UP TBL + 4798 567D 85 A1 sta DIRTBL+HI + 4799 567F A5 65 lda ARG2+LO ; TO STORE CHARS IN + 4800 5681 85 A0 sta DIRTBL+LO + 4801 5683 A9 02 lda #2 + 4802 5685 8D 85 6C sta DIRITM+LO + 4803 5688 A9 00 lda #0 + 4804 568A 8D 86 6C sta DIRITM+HI + 4805 568D 8D 31 96 sta ZBEGIN+ZTWIDTH+1 ; clear width count + 4806 5690 8D 30 96 sta ZBEGIN+ZTWIDTH+0 + 4807 ; + 4808 ; check to see if we have formatted table + 4809 ; + 4810 5693 A5 62 lda NARGS ; get # of arguments + 4811 5695 C9 03 cmp #3 ; if == 3, then we wrap it + 4812 5697 F0 01 beq DIR30 ; nope + 4813 5699 60 rts ; all done other wise + 4814 569A DIR30: + 4815 569A 86 19 stx FMTTBL ; set formatted table flag + 4816 569C A5 A2 lda XSIZE+LO ; save the current XSIZE + 4817 569E 8D BD 55 sta SAVEXSIZE+LO ; okay, did it + 4818 56A1 A5 A3 lda XSIZE+HI ; and MSB + 4819 56A3 8D BE 55 sta SAVEXSIZE+HI ; okay + 4820 56A6 A5 67 lda ARG3+LO ; this is the actual amount + 4821 56A8 A6 68 ldx ARG3+HI ; get interesting arg + 4822 56AA 30 0B bmi DIRFT1 ; check for negative width + 4823 56AC 20 7F 57 jsr SETWJ ; get the window offset + 4824 56AF A0 14 ldy #WINXSZ ; get its XSIZE + 4825 56B1 B1 7A lda (J),Y ; got it + 4826 56B3 85 A2 sta XSIZE+LO ; aren't we nice + 4827 56B5 D0 06 bne DIR31 ; jump to end + 4828 56B7 DIRFT1: + 4829 56B7 49 FF eor #$FF ; turn to a positive number + 4830 56B9 85 A2 sta XSIZE+LO ; save it + 4831 56BB E6 A2 inc XSIZE+LO ; to make it right + 4832 56BD DIR31: + 4833 56BD A9 00 lda #0 ; items starts at zero + 4834 56BF 8D 85 6C sta DIRITM+LO ; okay + 4835 56C2 85 A3 sta XSIZE+HI ; clear out highness + Wed Jun 7 1989 12:04 Page 71 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4836 56C4 06 A2 asl XSIZE+LO ; *2 + 4837 56C6 26 A3 rol XSIZE+HI + 4838 56C8 06 A2 asl XSIZE+LO ; *4 + 4839 56CA 26 A3 rol XSIZE+HI + 4840 56CC 60 rts + 4841 + 4842 ; ------ + 4843 ; CURSET + 4844 ; ------ + 4845 ; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW + 4846 ; AND AT COLUMN (ARG2) in (optional) window ARG3 + 4847 + 4848 56CD ZCURST: + 4849 56CD 20 B5 55 jsr CLRBUF ; CLEAR OUT ANY NON DISPLAYED TEXT 1ST + 4850 56D0 A5 63 lda ARG1+LO ; see if < 0 + 4851 56D2 C9 FF cmp #$FF ; -1 == turn off cursor + 4852 56D4 D0 04 bne ZCURS00 ; nope + 4853 56D6 A9 01 lda #1 ; show cursor off + 4854 56D8 D0 06 bne ZCURSTXX ; go do it and return + 4855 56DA ZCURS00: + 4856 56DA C9 FE cmp #$FE ; -2 == turn cursor on + 4857 56DC D0 06 bne ZCURS0 ; nope, just deal with normally + 4858 56DE A9 00 lda #0 ; show cursor not off + 4859 56E0 ZCURSTXX: + 4860 56E0 8D A7 6C sta CURSOR_OFF ; show current cursor state + 4861 56E3 60 rts + 4862 56E4 ZCURS0: + 4863 56E4 C6 63 dec ARG1+LO ; zero base both args + 4864 56E6 C6 65 dec ARG2+LO ; thanx + 4865 56E8 + 4866 56E8 A5 62 lda NARGS ; check for id + 4867 56EA C9 03 cmp #3 ; if 3 args, then window ID specified + 4868 56EC F0 04 beq ZCURS1 ; not 3, so use current window + 4869 + 4870 56EE A5 A6 lda CURWIN ; show current window being done + 4871 56F0 85 67 sta ARG3+LO ; thanx + 4872 56F2 ZCURS1: + 4873 56F2 A5 67 lda ARG3+LO ; get window ID + 4874 56F4 20 7F 57 jsr SETWJ ; put address into J + 4875 56F7 A5 63 lda ARG1+LO ; GET LINE + 4876 56F9 A0 02 ldy #WINHGHT ; check against height + 4877 56FB D1 7A cmp (J),Y ; too far? + 4878 56FD 90 05 bcc ZCURS3 ; no, so use it + 4879 56FF B1 7A lda (J),Y ; got max out + 4880 5701 A8 tay ; but one too far + 4881 5702 88 dey ; all better now + 4882 5703 98 tya ; back to A + 4883 5704 ZCURS3: + 4884 5704 18 clc ; get ready for add + 4885 5705 A0 00 ldy #WINTOP ; do y pos first + 4886 5707 71 7A adc (J),Y ; add in top to get absolute value + 4887 5709 A0 04 ldy #WINY ; get y pos offset + 4888 570B 91 7A sta (J),Y ; save here + 4889 570D A5 65 lda ARG2+LO ; GET COLUMN + 4890 570F A0 03 ldy #WINWID ; check against width + 4891 5711 D1 7A cmp (J),Y ; is it to for right (like Reagan?) + 4892 5713 90 05 bcc ZCURS4 ; nope, must be dukakis + 4893 5715 B1 7A lda (J),Y ; get max + 4894 5717 A8 tay ; for going down one + 4895 5718 88 dey ; done it + 4896 5719 98 tya ; back to A for usefullness + 4897 571A ZCURS4: + 4898 571A A0 01 ldy #WINLEFT ; get left edge to absolute it + 4899 571C 71 7A adc (J),Y ; carry clear from above + 4900 571E A0 05 ldy #WINX ; this is the x pos + 4901 5720 91 7A sta (J),Y ; into the structure + 4902 ; + 4903 ; now check for current window again, move cursor anyway + 4904 ; + 4905 5722 4C B1 4D jmp GET_CURSOR ; get cursor pos from WINDOW + 4906 + 4907 ; ------ + 4908 ; CURGET + 4909 ; ------ + 4910 + Wed Jun 7 1989 12:04 Page 72 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4911 5725 ZCURGT: + 4912 5725 20 B5 55 jsr CLRBUF ; flush the buffer + 4913 + 4914 5728 20 9F 4D jsr SAVE_CURSOR ; save the current position + 4915 + 4916 572B C6 62 dec NARGS ; see how many arguments + 4917 572D F0 04 beq ZCURG1 ; use main window + 4918 572F A5 65 lda ARG2+LO ; get window id + 4919 5731 10 02 bpl ZCURG2 ; and figger it out + 4920 5733 ZCURG1: + 4921 5733 A5 A6 lda CURWIN ; use current window + 4922 5735 ZCURG2: + 4923 5735 20 7F 57 jsr SETWJ ; make J point to right place + 4924 + 4925 5738 A5 64 lda ARG1+HI ; get table address + 4926 573A 20 7C 8F jsr SETPC ; get real address in memory + 4927 573D 84 91 sty SPCBNK ; set bank + 4928 573F 85 90 sta SPCH ; and page + 4929 5741 A5 63 lda ARG1+LO ; get table offset + 4930 5743 85 8F sta SPCL ; and save it + 4931 + 4932 5745 A9 00 lda #0 ; zero hi part of Y pos + 4933 5747 20 3A 92 jsr STASHB ; and save it + 4934 574A 20 A3 8F jsr NEXTSPC ; and point to next one + 4935 574D 20 64 57 jsr FETCHCY ; Fetch Y pos + 4936 5750 20 3A 92 jsr STASHB ; and save it + 4937 5753 20 A3 8F jsr NEXTSPC + 4938 ; + 4939 ; now for the X pos + 4940 5756 A9 00 lda #0 ; zero top byte of x pos + 4941 5758 20 3A 92 jsr STASHB + 4942 575B 20 A3 8F jsr NEXTSPC + 4943 575E 20 71 57 jsr FETCHCX ; and now the X pos, and return + 4944 5761 4C 3A 92 jmp STASHB ; and stash it away + 4945 + 4946 ; + 4947 ; FETCHCY - get the relativized Y pos into [A] + 4948 ; J points to window structure + 4949 5764 FETCHCY: + 4950 5764 A0 04 ldy #WINY ; get Y pos of window's cursor + 4951 5766 B1 7A lda (J),Y ; got it + 4952 5768 A0 00 ldy #WINTOP ; need to de-absolute it + 4953 576A 38 sec ; get ready for sub + 4954 576B F1 7A sbc (J),Y ; get relative pos + 4955 576D AA tax ; for 1 basing it + 4956 576E E8 inx ; 1 align it + 4957 576F 8A txa ; and put for save + 4958 5770 60 rts + 4959 ; + 4960 ; FETCHCX - get relativized X pos into [A] + 4961 ; J points to window structure + 4962 5771 FETCHCX: + 4963 5771 A0 05 ldy #WINX ; get X pos of cursor + 4964 5773 B1 7A lda (J),Y ; got it + 4965 5775 A0 01 ldy #WINLEFT ; relativize it + 4966 5777 38 sec ; get ready for sub + 4967 5778 F1 7A sbc (J),Y ; subtract left edge + 4968 577A AA tax ; for incing + 4969 577B E8 inx ; 1 ALIGN IT + 4970 577C 8A txa + 4971 577D 60 rts + 4972 + 4973 ; ----- + 4974 ; DIRIN + 4975 ; ----- + 4976 ; NOT YET IMPLEMENTED, BUT RESERVED + 4977 + 4978 577E 60 ZDIRIN: RTS + 4979 + 4980 ; + 4981 ; SETWJ - set up J to point to window structure for window ID in [A] + 4982 ; + 4983 577F SETWJ: + 4984 577F A8 tay ; check for -3 (current window) + 4985 5780 10 02 bpl SWJ1 ; nope, window ID here + Wed Jun 7 1989 12:04 Page 73 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4986 5782 A5 A6 lda CURWIN ; -3 means current window + 4987 5784 SWJ1: + 4988 5784 0A asl A ; shift to make word index + 4989 5785 A8 tay ; and now make index + 4990 5786 B9 4C 6E lda WINTABLE,Y ; get lo part of window struct address + 4991 5789 85 7A sta J+LO ; and save it + 4992 578B B9 4D 6E lda WINTABLE+1,Y ; here's the hi part + 4993 578E 85 7B sta J+HI ; prove it + 4994 5790 60 rts + 4995 + 4996 ; ----- + 4997 ; ERASE + 4998 ; ----- + 4999 + 5000 5791 ZERASE: + 5001 5791 A5 63 lda ARG1+LO + 5002 5793 C9 01 cmp #1 + 5003 5795 D0 06 bne ZEROUT ; not clreol + 5004 + 5005 5797 20 B5 55 jsr CLRBUF + 5006 579A 4C 02 61 jmp CLREOL ; CLEAR TO END OF LINE + 5007 579D ZEROUT: + 5008 579D 85 0C sta CLSWIDTH ; this many pixels wide + 5009 579F A9 09 lda #FONT_H ; pixels of font_height + 5010 57A1 85 0D sta CLSHEIGHT + 5011 57A3 A5 00 lda SCRCX ; start at current cursor pos + 5012 57A5 85 0A sta CLSLEFT + 5013 57A7 A5 01 lda SCRCY + 5014 57A9 85 0B sta CLSTOP + 5015 57AB 4C 05 5F jmp CLS ; and do it + 5016 + 5017 ; ----- + 5018 ; CLEAR the current window + 5019 ; ----- + 5020 57AE 0000 SAVEXY: dw 0 + 5021 + 5022 57B0 ZCLR: + 5023 57B0 20 B5 55 jsr CLRBUF ; flush the current buffer + 5024 57B3 20 9F 4D jsr SAVE_CURSOR ; save the cursor pos + 5025 + 5026 57B6 A5 63 lda ARG1+LO ; CHECK WHAT TO DO + 5027 57B8 10 26 bpl CLRW ; a particular window + 5028 57BA C9 FD cmp #$FD ; -3 means current window + 5029 57BC F0 22 beq CLRW ; so just handle it regular + 5030 57BE C9 FE cmp #$FE ; clear with nothing social + 5031 57C0 F0 07 beq CLRCLS ; just clear the screen + 5032 ; + 5033 ; UNSPLIT SCREEN & CLEAR IT + 5034 ; + 5035 57C2 A9 00 lda #0 ; just use SPLIT 0 + 5036 57C4 85 63 sta ARG1+LO ; as if called normally + 5037 57C6 20 DD 4D jsr ZSPLIT ; do the split + 5038 ; + 5039 ; just clear the entire screen + 5040 ; + 5041 57C9 CLRCLS: + 5042 57C9 A9 00 lda #0 ; clear the entire screen + 5043 57CB 85 0A sta CLSLEFT ; from top left + 5044 57CD 85 0B sta CLSTOP + 5045 57CF A9 8C lda #MAXWIDTH ; to bottom right + 5046 57D1 85 0C sta CLSWIDTH + 5047 57D3 A9 C0 lda #MAXHEIGHT + 5048 57D5 85 0D sta CLSHEIGHT + 5049 + 5050 57D7 20 05 5F jsr CLS ; do the clear screen (no cursor movement) + 5051 57DA A5 63 lda ARG1+LO ; check for -2 + 5052 57DC 30 44 bmi ZCLRX ; it is, don't move cursor + 5053 57DE 10 1B bpl ZCLEARX ; move cursor + 5054 57E0 CLRW: + 5055 57E0 20 7F 57 jsr SETWJ ; get me the window pointer + 5056 57E3 A0 00 ldy #WINTOP ; step thro to get data + 5057 57E5 B1 7A lda (J),Y ; TOP + 5058 57E7 85 0B sta CLSTOP ; save for clear + 5059 57E9 C8 iny ; point to left + 5060 57EA B1 7A lda (J),Y ; get it + Wed Jun 7 1989 12:04 Page 74 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5061 57EC 85 0A sta CLSLEFT ; tell CLS + 5062 57EE C8 iny ; now at WINHGHT + 5063 57EF B1 7A lda (J),Y ; got it + 5064 57F1 85 0D sta CLSHEIGHT ; save for clear + 5065 57F3 C8 iny ; now at WINWID + 5066 57F4 B1 7A lda (J),Y ; get height + 5067 57F6 85 0C sta CLSWIDTH ; saved + 5068 57F8 20 05 5F jsr CLS ; screen cleared + 5069 ; + 5070 ; now move the cursor to 1,1, if not == -2 + 5071 ; + 5072 57FB ZCLEARX: + 5073 57FB A5 63 lda ARG1+LO ; check arg + 5074 57FD 20 7F 57 jsr SETWJ ; make sure J still points to window + 5075 5800 A0 00 ldy #WINTOP ; put at top left of window + 5076 5802 B1 7A lda (J),Y ; get top + 5077 5804 A0 04 ldy #WINY ; and make it the y pos + 5078 5806 91 7A sta (J),Y ; of the cursor + 5079 5808 A0 01 ldy #WINLEFT ; and the left is + 5080 580A B1 7A lda (J),Y ; the + 5081 580C 18 clc ; add in the left margin + 5082 580D A0 06 ldy #WINLM ; here's the left margin + 5083 580F 71 7A adc (J),Y ; added it + 5084 5811 A0 05 ldy #WINX ; x pos of the + 5085 5813 91 7A sta (J),Y ; cursor + 5086 5815 A9 00 lda #0 ; and clear out line count + 5087 5817 A0 13 ldy #WINLCNT ; line count + 5088 5819 91 7A sta (J),Y ; okay + 5089 581B A0 15 ldy #WINLLEN ; and length of current line + 5090 581D 91 7A sta (J),Y ; okay + 5091 581F C8 iny ; do hi + 5092 5820 91 7A sta (J),Y ; okay + 5093 5822 ZCLRX: + 5094 5822 4C B1 4D jmp GET_CURSOR ; restore the cursor pos for the current window + 5095 + 5096 ; ------ + 5097 ; PRINTT + 5098 ; ------ + 5099 ; PRINT A TABLE TO SCREEN, ARG1 = # OF BYTES + 5100 ; ARG2 = WIDTH, ARG3 (DEF = 1) = HEIGHT + 5101 + 5102 0078 OLDCHZ EQU I+LO ; EASIER TO READ + 5103 0079 OLDEHZ EQU I+HI + 5104 007E OLDCVT EQU L+LO + 5105 + 5106 5825 0000 TBL_LEN DW 0 ; save for length + 5107 + 5108 5827 ZPRNTT: + 5109 5827 A5 63 lda ARG1+LO ; USE GETBYT AS TBL COULD + 5110 5829 85 86 sta MPCL ; BE ANYWHERE + 5111 582B A5 64 lda ARG1+HI + 5112 582D 85 87 sta MPCM + 5113 582F A9 00 lda #0 + 5114 5831 85 88 sta MPCH + 5115 5833 20 85 90 jsr VLDMPC + 5116 + 5117 5836 A5 65 lda ARG2+LO ; ONLY A BYTE AS MAX + 5118 5838 F0 58 beq PTTDUN ; QUIT NOW IF NULL + 5119 + 5120 583A 85 BF sta TBLWIDTH ; width of the table + 5121 583C 85 C0 sta TBLCNT ; start counter off at width + 5122 583E C6 62 dec NARGS ; count down to 1 (maybe) + 5123 5840 A5 62 lda NARGS + 5124 5842 C9 01 cmp #1 + 5125 5844 F0 02 beq NOHIGHT ; DEFAULT HEIGHT IS 1 + 5126 5846 A5 67 lda ARG3+LO ; get passed height + 5127 5848 NOHIGHT: + 5128 5848 85 BE sta TBLHEIGHT ; height of the table (at least 1) + 5129 584A A5 00 lda SCRCX + 5130 584C 85 79 sta OLDEHZ + 5131 584E 38 sec ; subtract left margin to get how long line is + 5132 584F E5 04 sbc LEFTMRG ; okay we did that + 5133 5851 8D 25 58 sta TBL_LEN+LO ; this is how big line is too + 5134 5854 A9 00 lda #0 ; clear MSB + 5135 5856 0E 25 58 asl TBL_LEN+LO ; *2 + Wed Jun 7 1989 12:04 Page 75 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5136 5859 2A rol A + 5137 585A 0E 25 58 asl TBL_LEN+LO ; *4 + 5138 585D 2A rol A + 5139 585E 8D 26 58 sta TBL_LEN+HI ; save + 5140 5861 PTTLP: + 5141 5861 20 0E 92 jsr GETBYT ; GET A BYTE + 5142 5864 20 06 53 jsr COUT ; and send it out + 5143 + 5144 5867 C6 C0 dec TBLCNT ; one more byte done + 5145 5869 D0 F6 bne PTTLP + 5146 586B C6 BE dec TBLHEIGHT ; IF DONE ALL LINES + 5147 586D F0 23 beq PTTDUN ; LEAVE + 5148 + 5149 586F 20 B5 55 jsr CLRBUF ; so send out stuff that's there + 5150 + 5151 5872 A5 79 lda OLDEHZ ; get old x pos + 5152 5874 85 00 sta SCRCX ; and restore it + 5153 5876 A9 01 lda #1 ; show cursor changed + 5154 5878 8D 7C 6C sta CURSFLG ; okay + 5155 587B A5 01 lda SCRCY ; point to next line + 5156 587D 18 clc ; by adding in the font height + 5157 587E 69 09 adc #FONT_H ; okay, goody + 5158 5880 85 01 sta SCRCY ; and here we are + 5159 + 5160 5882 AD 26 58 lda TBL_LEN+HI ; reset length + 5161 5885 85 A8 sta LENGTH+HI ; hi part + 5162 5887 AD 25 58 lda TBL_LEN+LO ; lo part + 5163 588A 85 A7 sta LENGTH+LO ; just a lo + 5164 + 5165 588C A5 BF lda TBLWIDTH ; RESET COUNT + 5166 588E 85 C0 sta TBLCNT ; thanx + 5167 5890 D0 CF bne PTTLP ; GO DO NEXT LINE + 5168 5892 PTTDUN: + 5169 5892 60 rts + 5170 ;-------------- + 5171 ; ZPRINTF + 5172 ;-------------- + 5173 ; ZPRINTF - print a formatted table + 5174 ; + 5175 5893 ZPRINTF: + 5176 5893 A5 63 lda ARG1+LO ; USE GETBYT AS TBL COULD + 5177 5895 85 86 sta MPCL ; BE ANYWHERE + 5178 5897 A5 64 lda ARG1+HI + 5179 5899 85 87 sta MPCM + 5180 589B A9 00 lda #0 + 5181 589D 85 88 sta MPCH + 5182 589F 20 85 90 jsr VLDMPC + 5183 + 5184 58A2 A5 00 lda SCRCX ; save the X pos + 5185 58A4 85 79 sta OLDEHZ ; saved here + 5186 58A6 ZPFL1: + 5187 58A6 20 0E 92 jsr GETBYT ; get the length byte, MSB, & ignore + 5188 58A9 20 0E 92 jsr GETBYT ; get the length byte + 5189 58AC F0 21 beq ZPFX ; no more if == 0 + 5190 58AE 85 BF sta TBLWIDTH ; keep track of it + 5191 58B0 ZPFL2: + 5192 58B0 20 0E 92 jsr GETBYT ; now get the char byte + 5193 58B3 20 82 5D jsr CHAR ; and send it yt + 5194 58B6 C6 BF dec TBLWIDTH ; any more? + 5195 58B8 D0 F6 bne ZPFL2 ; ayyup + 5196 + 5197 58BA 20 F1 71 jsr DISP_LINE ; make sure line goes out + 5198 58BD A5 79 lda OLDEHZ ; reset a few things + 5199 58BF 85 00 sta SCRCX ; including x pos + 5200 58C1 A9 01 lda #1 ; show cursor changed + 5201 58C3 8D 7C 6C sta CURSFLG ; okay + 5202 58C6 A5 01 lda SCRCY ; point to next line + 5203 58C8 18 clc ; by adding in the font height + 5204 58C9 69 09 adc #FONT_H ; okay, goody + 5205 58CB 85 01 sta SCRCY ; and here we are + 5206 58CD D0 D7 bne ZPFL1 ; and do it again + 5207 58CF ZPFX: + 5208 58CF 60 rts + 5209 ; ------------ + 5210 ; SET NEW FONT + Wed Jun 7 1989 12:04 Page 76 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5211 ; ------------ + 5212 + 5213 ; Font 4 is mono-spaced font. + 5214 + 5215 58D0 ZFONT: + 5216 58D0 20 B5 55 jsr CLRBUF ; clear the buffer first + 5217 + 5218 58D3 C6 62 dec NARGS ; did we get passed a window id? + 5219 58D5 D0 04 bne ZFNTWID ; yup + 5220 58D7 A9 FD lda #$FD ; -3 means current window + 5221 58D9 85 65 sta ARG2+LO ; make it the arg2 then + 5222 58DB ZFNTWID: + 5223 58DB A5 65 lda ARG2+LO ; get window we are interested in + 5224 58DD 20 7F 57 jsr SETWJ ; make [J] point to window struct + 5225 + 5226 58E0 A5 63 lda ARG1+LO ; check for + 5227 58E2 C9 01 cmp #1 ; font 1 + 5228 58E4 F0 0E beq ZFNT1 ; or + 5229 58E6 C9 04 cmp #4 ; font 4 (monospace) + 5230 58E8 D0 2A bne ZFBAD ; nope, so die + 5231 ; + 5232 ; font 4 is the monospaced font + 5233 ; + 5234 58EA A0 10 ldy #WINFSIZE ; point to width + 5235 58EC A9 03 lda #MFONT_W ; get game width + 5236 58EE 91 7A sta (J),Y ; store the width + 5237 58F0 A9 03 lda #3 ; set font ID + 5238 58F2 D0 08 bne ZFNTEX ; all done + 5239 58F4 ZFNT1: + 5240 58F4 A0 10 ldy #WINFSIZE ; point to width + 5241 58F6 A9 02 lda #FONT_W ; get game width + 5242 58F8 91 7A sta (J),Y ; store the width + 5243 58FA A9 00 lda #0 ; set font ID + 5244 58FC ZFNTEX: + 5245 58FC A0 0F ldy #WINFONT ; set font + 5246 58FE 48 pha ; save font id + 5247 58FF B1 7A lda (J),Y ; get old font id + 5248 5901 AA tax ; save old font id + 5249 5902 68 pla ; get new one back + 5250 5903 91 7A sta (J),Y ; save in structure + 5251 5905 B1 05 lda (WINDOW),Y ; get current window font + 5252 5907 F0 02 beq ZFNT0X ; set flag with zero + 5253 5909 A9 0C lda #MONOFONT_W ; get width of mono spaced font + 5254 590B ZFNT0X: + 5255 590B 85 C1 sta FONTFLG ; and set flag too + 5256 590D E8 inx ; make it say correct font ID for game + 5257 590E 8A txa ; put in A for put val + 5258 590F A2 00 ldx #0 ; clear X + 5259 5911 4C E1 43 jmp PUTVAL ; and return it + 5260 5914 ZFBAD: + 5261 5914 4C DA 43 jmp RET0 ; TELL IT DOESN'T WORK + 5262 ; ------------------------------ + 5263 ; FETCH A LINE OF INPUT FOR READ + 5264 ; ------------------------------ + 5265 ; ENTRY: Relative READ table address in RDTBL1 + 5266 ; EXIT: # CHARS READ IN [A] + 5267 5917 SV_SPC: ds 3 ; save SPC here for later usage + 5268 + 5269 591A INPUT: + 5270 591A 20 B5 55 jsr CLRBUF ; FLUSH [LBUFF] + 5271 591D A0 00 ldy #0 ; RESET LINE COUNT + 5272 591F 84 79 sty I+HI ; clear local variables + 5273 5921 84 78 sty I+LO + 5274 5923 84 7B sty J+HI + 5275 5925 84 7A sty J+LO + 5276 5927 8C 69 5B sty BRKCHR ; init break char + 5277 592A 84 AB sty LINCNT ; RESET LINE COUNT + 5278 592C 8C A9 6C sty PTR_COUNT ; we start by looking at pointer + 5279 592F 8C 7C 6C sty CURSFLG ; make sure we don't change cursor + 5280 ; + 5281 ; check for new TCHARS table + 5282 ; + 5283 5932 AD 2F 96 lda ZBEGIN+ZTCHAR+1 ; so check lower byte for different tchars + 5284 5935 CD 89 6C cmp SVTCHAR+LO ; is it different? + 5285 5938 D0 08 bne IO_DOT ; ayyup, get new one + Wed Jun 7 1989 12:04 Page 77 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5286 593A AD 2E 96 lda ZBEGIN+ZTCHAR ; get current TCHARS hi part + 5287 593D CD 8A 6C cmp SVTCHAR+HI ; is it the same as saved one? + 5288 + 5289 5940 F0 03 beq IOj ; yes, so don't muck with it + 5290 5942 IO_DOT: + 5291 5942 20 7E 5A jsr DO_TCHARS ; new table, so copy it over + 5292 ; + 5293 ; now set up FPC + 5294 ; + 5295 5945 IOj: + 5296 5945 AD 80 6C lda RDTBL1+HI ; get page of table + 5297 5948 20 7C 8F jsr SETPC ; and get me the memory page and bank + 5298 594B 85 8D sta FPCH ; save page + 5299 594D 84 8E sty FPCBNK ; and bank + 5300 594F AD 7F 6C lda RDTBL1+LO ; and get offset + 5301 5952 85 8C sta FPCL ; set up FPC/SPC + 5302 5954 20 5B 92 jsr FETCHB ; get length of line + 5303 5957 A8 tay ; for dec'ing + 5304 5958 88 dey ; don't count the offset byte + 5305 5959 88 dey ; and leave room for terminator + 5306 595A 84 17 sty CHRMAX ; and save it + 5307 595C 20 C3 8F jsr NEXTFPC ; point to next byte + 5308 595F 20 5B 92 jsr FETCHB ; get current offset into buffer + 5309 5962 8D 62 5B sta CHARCNT ; save how many chars out there + 5310 5965 20 C3 8F jsr NEXTFPC ; point to beginning of data buffer + 5311 ; + 5312 ; now finish setting up saved SPC + 5313 ; + 5314 5968 A2 02 ldx #2 + 5315 596A INSVCL: + 5316 596A B5 8C lda FPC,X ; get byte to saved for use later on + 5317 596C 9D 17 59 sta SV_SPC,X ; it is saved here + 5318 596F CA dex + 5319 5970 10 F8 bpl INSVCL ; next! + 5320 ; + 5321 ; now copy current buffer into local buffer + 5322 ; + 5323 5972 AD 62 5B lda CHARCNT ; make sure we have some + 5324 5975 F0 11 beq CPIOLX ; nope, none in there now + 5325 5977 A2 00 ldx #0 ; start at first char + 5326 5979 CPIOL: + 5327 5979 20 5B 92 jsr FETCHB ; get a char + 5328 597C 9D 00 02 sta LBUFF,X ; save char + 5329 597F 20 C3 8F jsr NEXTFPC ; point to next one + 5330 5982 E8 inx ; next char + 5331 5983 EC 62 5B cpx CHARCNT ; got them all yet? + 5332 5986 D0 F1 bne CPIOL ; nope + 5333 5988 CPIOLX: + 5334 5988 20 0E 4F jsr CHKTME ; START TIME LIMIT + 5335 ; + 5336 ; this is the get-a-key-and-whack-on-it loop + 5337 ; + 5338 598B INLOOP: + 5339 598B A5 79 lda I+HI ; is there a time? + 5340 598D F0 08 beq INPL1 ; nope + 5341 598F 20 C9 4F jsr TIMIN ; do timed input + 5342 5992 90 06 bcc INPL2 ; got a char, process it + 5343 5994 4C 78 5A jmp LEXBAD ; timed out with nothing there! + 5344 5997 INPL1: + 5345 5997 20 31 51 jsr GETKEY ; let apple do the walking + 5346 599A INPL2: + 5347 599A 20 B5 5A jsr ISTCHR ; CHECK IF IT'S AN ACCEPTABLE TERMINATOR KEY + 5348 599D B0 0D bcs NOTYET + 5349 + 5350 599F 8D 69 5B sta BRKCHR + 5351 59A2 C9 0D cmp #EOL ; IF EOL PUT TO SCREEN + 5352 59A4 F0 03 beq ENDLINx + 5353 59A6 4C 2F 5A jmp ENDIN ; ELSE JUST END + 5354 59A9 ENDLINx: + 5355 59A9 4C 1F 5A jmp ENDLIN ; can't reach with a branch + 5356 59AC NOTYET: + 5357 59AC A0 FF ldy #$FF ; restart pointer device counter + 5358 59AE 8C A9 6C sty PTR_COUNT ; and start again + 5359 59B1 A8 tay ; check for functions keys that aren't + 5360 59B2 30 65 bmi CBAD ; terminators and feep if it is + Wed Jun 7 1989 12:04 Page 78 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5361 59B4 C9 0D cmp #EOL ; EOL? + 5362 59B6 F0 67 beq ENDLIN ; LINE DONE IF SO + 5363 59B8 C5 1B cmp ESCAPE ; don't allow escape char's thru + 5364 59BA F0 5D beq CBAD ; okay, I won't + 5365 + 5366 59BC C9 08 cmp #BACKSPACE ; BACKSPACE? + 5367 59BE F0 38 beq BACKUP ; SPECIAL HANDLING + 5368 59C0 C9 1B cmp #ESCAPE ; ESCAPE char? + 5369 59C2 F0 55 beq CBAD ; don't like it + 5370 + 5371 59C4 AC 62 5B ldy CHARCNT ; where do we put char? + 5372 59C7 C4 17 cpy CHRMAX ; are we filled up? + 5373 59C9 B0 4E bcs CBAD ; boy, am i full + 5374 + 5375 59CB 48 pha ; save it + 5376 59CC AA tax ; use as index + 5377 59CD A5 A7 lda LENGTH+LO ; GET LINE LENGTH COUNTER + 5378 59CF 18 clc ; get ready for add + 5379 59D0 7D 2A 64 adc CHWID,X ; add width + 5380 59D3 A8 tay ; save LSB in Y + 5381 59D4 A6 A8 ldx LENGTH+HI ; get high byte + 5382 59D6 90 01 bcc INP0C ; no wrap + 5383 59D8 E8 inx ; okay, wrap then + 5384 59D9 INP0C: + 5385 59D9 68 pla ; get char back + 5386 59DA E4 A3 cpx XSIZE+HI ; check MSB first + 5387 59DC 90 04 bcc NOIOWRAP ; no need to check lsb + 5388 59DE C4 A2 cpy XSIZE+LO ; end of screen line? + 5389 59E0 B0 37 bcs CBAD ; reached end, so just beep + 5390 59E2 NOIOWRAP: + 5391 59E2 86 A8 stx LENGTH+HI ; save MSB + 5392 59E4 84 A7 sty LENGTH+LO ; and LSB + 5393 59E6 AE 62 5B ldx CHARCNT ; for putting in line buffer + 5394 59E9 9D 00 02 sta LBUFF,X ; and save it in case we goto printer + 5395 59EC 20 82 5D jsr CHAR ; SEND TO SCREEN + 5396 59EF 20 F1 71 jsr DISP_LINE ; show char + 5397 59F2 EE 62 5B inc CHARCNT ; NEXT POSITION IN LINE + 5398 59F5 4C 8B 59 jmp INLOOP ; NO, GET ANOTHER CHAR + 5399 ; + 5400 ; HANDLE BACKSPACE + 5401 ; + 5402 59F8 BACKUP: + 5403 59F8 AE 62 5B ldx CHARCNT ; if == 2 then empty + 5404 59FB F0 1C beq CBAD ; JMP to beeping + 5405 59FD CA dex ; get rid of char + 5406 59FE 8E 62 5B stx CHARCNT ; saved + 5407 5A01 BD 00 02 lda LBUFF,X ; get char we are interested in + 5408 5A04 AA tax ; put in x + 5409 + 5410 5A05 A5 A7 lda LENGTH+LO ; GET LINE LENGTH COUNTER + 5411 5A07 38 sec ; get ready for sub + 5412 5A08 FD 2A 64 sbc CHWID,X ; sub width + 5413 5A0B 85 A7 sta LENGTH+LO ; update length + 5414 5A0D B0 02 bcs BCKP1 ; no wrap + 5415 5A0F C6 A8 dec LENGTH+HI ; okay, wrap then + 5416 5A11 BCKP1: + 5417 5A11 A9 08 lda #BACKSPACE ; so do erasing backspace + 5418 5A13 20 82 5D jsr CHAR + 5419 5A16 4C 8B 59 jmp INLOOP + 5420 5A19 CBAD: + 5421 5A19 20 C3 4E jsr BEEP ; ELSE SCREAM WITH PAIN + 5422 5A1C 4C 8B 59 jmp INLOOP ; AND WAIT FOR SOMETHING BETTER + 5423 ; + 5424 ; HANDLE END OF LINE KEY + 5425 ; + 5426 5A1F ENDLIN: + 5427 5A1F 8D 69 5B sta BRKCHR + 5428 5A22 A9 0D lda #EOL ; get EOL char + 5429 5A24 20 82 5D jsr CHAR ; SEND EOL TO SCREEN + 5430 5A27 A9 00 lda #0 ; and show 0 length of line out there + 5431 5A29 85 A7 sta LENGTH+LO ; thanx + 5432 5A2B 85 A8 sta LENGTH+HI ; and msb + 5433 5A2D E6 AB inc LINCNT ; take into account the at EOL + 5434 5A2F ENDIN: + 5435 ; + Wed Jun 7 1989 12:04 Page 79 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5436 ; now save lbuff in table for posterity + 5437 ; + 5438 5A2F AD 19 59 lda SV_SPC+ABANK ; get bank first + 5439 5A32 85 91 sta SPCBNK ; saved + 5440 5A34 AD 18 59 lda SV_SPC+HI + 5441 5A37 85 90 sta SPCH + 5442 5A39 AD 17 59 lda SV_SPC+LO + 5443 5A3C 85 8F sta SPCL + 5444 5A3E A2 00 ldx #0 ; start with first char in buffer + 5445 5A40 ENDLOOP: + 5446 5A40 EC 62 5B cpx CHARCNT ; done yet? + 5447 5A43 F0 16 beq INP111 + 5448 5A45 BD 00 02 lda LBUFF,X ; get char + 5449 5A48 C9 41 cmp #'A' ; IF CHAR IS UPPERCASE ALPHA, + 5450 5A4A 90 06 bcc LEX ; CONVERT TO LOWER CASE + 5451 5A4C C9 5B cmp #'Z'+1 + 5452 5A4E B0 02 bcs LEX + 5453 5A50 69 20 adc #$20 ; converting away + 5454 5A52 LEX: + 5455 5A52 20 3A 92 jsr STASHB ; okay, stashing away + 5456 5A55 20 A3 8F jsr NEXTSPC ; and point to next char in table + 5457 5A58 E8 inx ; point to next char + 5458 5A59 D0 E5 bne ENDLOOP ; so get next one + 5459 5A5B INP111: + 5460 5A5B A9 00 lda #00 ; to show end of line + 5461 5A5D 20 3A 92 jsr STASHB ; so put it in buffer + 5462 ; + 5463 ; now put in new line length + 5464 ; + 5465 5A60 AD 80 6C lda RDTBL1+HI ; get page of table + 5466 5A63 20 7C 8F jsr SETPC ; and get me the memory page and bank + 5467 5A66 85 90 sta SPCH ; save page + 5468 5A68 84 91 sty SPCBNK ; and bank + 5469 5A6A AD 7F 6C lda RDTBL1+LO ; and get offset + 5470 5A6D 85 8F sta SPCL + 5471 5A6F 20 A3 8F jsr NEXTSPC ; and point to char count + 5472 5A72 AD 62 5B lda CHARCNT ; get character count + 5473 5A75 20 3A 92 jsr STASHB ; and shove it away + 5474 5A78 LEXBAD: + 5475 5A78 A0 00 ldy #0 ; clear out + 5476 5A7A 8C A9 6C sty PTR_COUNT ; pointer flag + 5477 5A7D 60 rts ; Length is in [A] + 5478 ; + 5479 ; Copy over a new TCHARS table + 5480 ; + 5481 5A7E DO_TCHARS: + 5482 ; + 5483 ; now do somethin' with the TCHAR table (maybe, if <> 0) + 5484 ; + 5485 5A7E AD 2E 96 lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + 5486 5A81 8D 8A 6C sta SVTCHAR+HI ; save it for checking + 5487 5A84 20 7C 8F jsr SETPC ; and now make absolute + 5488 5A87 85 8D sta FPCH ; Save in FPC + 5489 5A89 84 8E sty FPCBNK + 5490 5A8B AD 2F 96 lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + 5491 5A8E 8D 89 6C sta SVTCHAR+LO ; and save for later check + 5492 5A91 85 8C sta FPCL ; now move pointer to fetch spot + 5493 + 5494 5A93 A9 00 lda #0 ; and set index + 5495 5A95 85 78 sta I ; thank you + 5496 5A97 85 B9 sta ALLFLG ; turn it off + 5497 5A99 TCHLP: + 5498 5A99 20 5B 92 jsr FETCHB ; get the byte in [a] + 5499 5A9C 20 C3 8F jsr NEXTFPC ; point to next one + 5500 5A9F A6 78 ldx I ; get offset + 5501 5AA1 E6 78 inc I ; and point to next one + 5502 5AA3 9D 00 1D sta TCHARTBL,X ; save in lower memory, thank you + 5503 5AA6 C9 00 cmp #0 ; are we done yet? + 5504 5AA8 F0 0A beq TCHj ; NULL TERMINATED STRING + 5505 5AAA C9 FF cmp #$FF ; $ff means all >128 chars are terminators + 5506 5AAC D0 04 bne TCHLNEXT ; nope + 5507 5AAE A9 01 lda #1 ; yes, + 5508 5AB0 85 B9 sta ALLFLG ; so set flag to say so + 5509 5AB2 TCHLNEXT: + 5510 5AB2 D0 E5 bne TCHLP ; and go get it + Wed Jun 7 1989 12:04 Page 80 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5511 5AB4 TCHj: + 5512 5AB4 60 rts + 5513 + 5514 ; ------------------------ + 5515 ; IS IT A TERMINATOR CHAR? + 5516 ; ------------------------ + 5517 + 5518 5AB5 ISTCHR: + 5519 5AB5 AE 00 1D ldx TCHARTBL ; check for chars in TCHAR table + 5520 5AB8 F0 18 beq ISNOT ; nope + 5521 + 5522 5ABA A6 B9 ldx ALLFLG ; ARE ALL FCN KEYS (<127) TERMINATORS + 5523 5ABC F0 05 beq ISCHK ; 0 = NO, GO CHECK LIST + 5524 5ABE AA tax ; check for minus + 5525 5ABF 30 13 bmi ISFND ; YUP + 5526 5AC1 10 0F bpl ISNOT + 5527 5AC3 ISCHK: + 5528 5AC3 A0 00 ldy #0 + 5529 5AC5 ISLP: + 5530 5AC5 D9 00 1D cmp TCHARTBL,Y ; IS CHAR WE HAVE A TCHAR? + 5531 5AC8 F0 0A beq ISFND ; YES + 5532 5ACA BE 00 1D ldx TCHARTBL,Y ; NULL = END OF STRING + 5533 5ACD F0 03 beq ISNOT + 5534 5ACF C8 iny + 5535 5AD0 D0 F3 bne ISLP ; SHOULD ALWAYS LOOP + 5536 5AD2 ISNOT: + 5537 5AD2 38 sec + 5538 5AD3 60 rts ; NOT FOUND + 5539 5AD4 ISFND: + 5540 5AD4 18 clc + 5541 5AD5 60 rts + 5542 + 5543 ; ----- + 5544 ; INPUT 1 char, no printing + 5545 ; ----- + 5546 + 5547 5AD6 ZINPUT: + 5548 5AD6 20 B5 55 JSR CLRBUF + 5549 + 5550 5AD9 A0 00 ldy #0 + 5551 5ADB 84 AB sty LINCNT + 5552 5ADD 84 A9 sty CHRCNT + 5553 5ADF 84 79 sty I+HI ; init locals too + 5554 5AE1 84 78 sty I+LO + 5555 5AE3 84 7B sty J+HI + 5556 5AE5 84 7A sty J+LO + 5557 5AE7 8C A9 6C sty PTR_COUNT ; always check the pointer + 5558 5AEA + 5559 5AEA C6 62 DEC NARGS + 5560 5AEC F0 18 BEQ ZINP3 ; NO TIME LIMIT + 5561 5AEE A5 65 LDA ARG2+LO ; GET DELAY WANTED + 5562 5AF0 85 79 STA I+HI + 5563 5AF2 C6 62 DEC NARGS + 5564 5AF4 F0 08 BEQ ZINP4 ; NO FCN + 5565 5AF6 A5 67 LDA ARG3+LO + 5566 5AF8 85 7A STA J+LO + 5567 5AFA A5 68 LDA ARG3+HI + 5568 5AFC 85 7B STA J+HI + 5569 5AFE ZINP4: + 5570 5AFE 20 C9 4F JSR TIMIN ; CALL timed input rotine + 5571 5B01 90 10 BCC ZINPRK ; send char on home + 5572 5B03 4C DA 43 JMP RET0 ; time out without character + 5573 5B06 ZINP3: + 5574 5B06 20 31 51 jsr GETKEY ; ok, find which char was pressed + 5575 5B09 C9 1B cmp #ESCAPE ; don't use escape char + 5576 5B0B D0 06 bne ZINPRK ; fine + 5577 5B0D 20 C3 4E jsr BEEP ; complain + 5578 5B10 4C 06 5B jmp ZINP3 ; do again + 5579 5B13 ZINPRK: + 5580 5B13 A2 00 LDX #0 + 5581 5B15 4C DD 43 JMP PUTBYT ; RETURN CHAR + 5582 + 5583 + 5584 5B18 INTCLL: + 5585 5B18 A5 79 LDA I+HI ; SAVE VALUES FOR CALLING RTN + Wed Jun 7 1989 12:04 Page 81 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5586 5B1A 48 PHA + 5587 5B1B A5 78 LDA I+LO + 5588 5B1D 48 PHA + 5589 5B1E A5 7B LDA J+HI + 5590 5B20 85 64 STA ARG1+HI ; pretend it's arg1 + 5591 5B22 48 PHA + 5592 5B23 A5 7A LDA J+LO + 5593 5B25 85 63 STA ARG1+LO ; and this is the other half + 5594 5B27 48 PHA + 5595 + 5596 5B28 A2 01 LDX #1 + 5597 5B2A 86 62 STX NARGS ; 0 args for internal call + 5598 5B2C CA DEX + 5599 5B2D 8E 64 5B STX IRET ; make sure it returns here! + 5600 5B30 + 5601 5B30 A5 80 LDA ZPCL ; a fake one to say we + 5602 5B32 48 PHA ; are an internal call + 5603 5B33 A5 81 LDA ZPCM ; so save real one + 5604 5B35 48 PHA + 5605 5B36 A5 82 LDA ZPCH + 5606 5B38 48 PHA + 5607 + 5608 5B39 A9 00 LDA #0 ; return addr of zero is + 5609 5B3B 85 82 STA ZPCH ; internal call! + 5610 5B3D 85 81 STA ZPCM + 5611 5B3F 85 80 STA ZPCL + 5612 + 5613 5B41 20 CD 7F JSR DOCALL + 5614 + 5615 5B44 4C B6 40 JMP MLOOP ; GO DO FCN + 5616 ; + 5617 ; RETURN FROM FCN WILL COME HERE + 5618 ; + 5619 5B47 ZIRET: + 5620 5B47 68 PLA ; GET RID OF RTS FROM ZRET + 5621 5B48 68 PLA + 5622 + 5623 5B49 68 PLA ; get old zpc back + 5624 5B4A 85 82 STA ZPCH + 5625 5B4C 68 PLA + 5626 5B4D 85 81 STA ZPCM + 5627 5B4F 68 PLA + 5628 5B50 85 80 STA ZPCL + 5629 5B52 20 AF 90 JSR VLDZPC ; and validate it + 5630 + 5631 5B55 68 PLA ; RESTORE FOR CALLING RTN + 5632 5B56 85 7A STA J+LO + 5633 5B58 68 PLA + 5634 5B59 85 7B STA J+HI + 5635 5B5B 68 PLA + 5636 5B5C 85 78 STA I+LO + 5637 5B5E 68 PLA + 5638 5B5F 85 79 STA I+HI + 5639 5B61 60 RTS ; GO BACK TO CALLER + 5640 + 5641 ; INPUT: routine locals! + 5642 5B62 00 CHARCNT: DB 0 ; where into buffer goes char + 5643 5B63 00 SVCHAR: DB 0 ; where to save the char before printing + 5644 + 5645 5B64 00 IRET: DB 0 ; FLAG TELLS IF RETURNLESS CALL + 5646 + 5647 5B65 00 00 MTEMP: DB 00,00 ; temp spot for math routines + 5648 5B67 00 TYPE: DB 0 ; PARTIAL OR NORMAL (WHOLE) SAVE/RESTORE + 5649 5B68 00 ASSVLU: DB 0 ; how many args to this subroutine + 5650 5B69 00 BRKCHR: DB 0 ; READ BREAK CHAR + 5651 5B6A 00 RDFLAG: DB 0 ; 0 - only read 1 - do lex on it + 5652 5B6B 5B 4D 4F 52 45 MORE: DB "[MORE]" + 5B70 5D + 5653 0006 MOREL EQU $-MORE + 5654 5B71 END + 5655 + 5656 5B71 INCLUDE VERIFY.ASM + 5657 5B71 STTL "--- VERIFY CODE ---" + 5658 PAGE + Wed Jun 7 1989 12:04 Page 82 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5659 + 5660 ; ------ + 5661 ; VERIFY + 5662 ; ------ + 5663 ; VERIFY GAME CODE ON DISK + 5664 5B71 0D 54 68 65 20 VERBAD: DB EOL,"The data segment of file is BAD!",EOL + 5B76 64 61 74 61 20 + 5B7B 73 65 67 6D 65 + 5B80 6E 74 20 6F 66 + 5B85 20 66 69 6C 65 + 5B8A 20 69 73 20 42 + 5B8F 41 44 21 0D + 5665 0022 VERBADL EQU $-VERBAD + 5666 5B93 0D 54 68 65 20 VERPBAD: DB EOL,"The picture data of file is BAD!",EOL + 5B98 70 69 63 74 75 + 5B9D 72 65 20 64 61 + 5BA2 74 61 20 6F 66 + 5BA7 20 66 69 6C 65 + 5BAC 20 69 73 20 42 + 5BB1 41 44 21 0D + 5667 0022 VERPBADL EQU $-VERPBAD + 5668 5BB5 00 ZVFLAG: db 0 ; set to indicate ugliness + 5669 0078 STARTPOS EQU I+LO ; this is where to start block + 5670 5BB6 ZVER: + 5671 5BB6 20 94 8C jsr CLOSE_GAME ; make sure the game files are closed + 5672 5BB9 AC 89 46 ldy GAME2NML ; get length of name + 5673 5BBC B9 89 46 lda GAME2NM,Y ; get last char + 5674 5BBF 49 30 eor #$30 ; make normal number + 5675 5BC1 A8 tay ; -1 to make ready for FETCH_FILE + 5676 5BC2 88 dey ; F_F incs first + 5677 5BC3 98 tya ; to push onto stack + 5678 5BC4 48 pha ; and save for restoring later + 5679 5BC5 A9 00 lda #0 ; clear a few counters + 5680 5BC7 8D B5 5B sta ZVFLAG ; ==0 - verify worked; !=0 - verify broke + 5681 5BCA AD 01 19 lda SEGTBL+SGTDISKS+1 ; get how many disks are here + 5682 5BCD 8D 57 49 sta DISKCNTR ; this shows which disk we are working on + 5683 5BD0 CE 57 49 dec DISKCNTR ; start down by one + 5684 5BD3 VERIFY_LOOP: + 5685 5BD3 20 0B 5C jsr VERIFY_DATA ; check data in this file + 5686 5BD6 20 96 5C jsr VERIFY_PICD ; check (possible) picture data in this file + 5687 5BD9 AD CF 45 lda GMREF ; get reference number + 5688 5BDC 8D 0C 8B sta CLOSE_PB+CL_REFNUM ; and show CLOSE + 5689 5BDF CLOSE CLOSE_PB ; and shut it up + 5690 5BDF PRODOS $CC, CLOSE_PB + 5691 5BDF 20 00 BF jsr $BF00 ; ProDOS handler + 5692 5BE2 CC DB $CC ; ProDOS function code + 5693 5BE3 0B8B DW CLOSE_PB ; Function Parameter Block address + 5694 5BE5 .MACEND + 5695 5BE5 .MACEND + 5696 5BE5 CE 57 49 dec DISKCNTR ; next please + 5697 5BE8 10 E9 bpl VERIFY_LOOP ; and check the next file + 5698 5BEA ZVERX: + 5699 5BEA A9 02 lda #>PAGELEN ; reset read buffer length + 5700 5BEC 8D D3 45 sta READ_PB+RD_BUFFLEN+HI ; to be $100 + 5701 5BEF A9 00 lda # 0, then it isn't + 5743 5C38 20 51 5D jsr SETUP_DISK0 ; move around to point to start of data + 5744 5C3B VERD1: + 5745 5C3B A0 02 ldy #SGTPICOF ; find where picture data starts + 5746 5C3D B1 1E lda (DSEGS),Y ; MSB + 5747 5C3F 85 7B sta J+HI ; J is the page counter + 5748 5C41 C8 iny ; point to LSB + 5749 5C42 11 1E ora (DSEGS),Y ; any picture file? + 5750 5C44 D0 08 bne VERD01 ; yes, so mark end of data + 5751 5C46 A9 FF lda #$FF ; set J to be a real big number + 5752 5C48 85 7A sta J+LO ; okay + 5753 5C4A 85 7B sta J+HI ; and this one + 5754 5C4C D0 15 bne VERD11 ; all done + 5755 5C4E VERD01: + 5756 5C4E B1 1E lda (DSEGS),Y ; and here it is + 5757 5C50 0A asl A ; *2 to make 512 pages be 256 pages + 5758 5C51 85 7A sta J+LO ; this is where it ends up + 5759 5C53 26 7B rol J+HI ; move in carry to MSB + 5760 5C55 A5 7A lda J+LO ; now, subtract any skipping + 5761 5C57 38 sec ; doing sub + 5762 5C58 ED DF 45 sbc PSEEK+SM_FPOS+1 ; take away any skipped amount + 5763 5C5B 85 7A sta J+LO ; and save it + 5764 5C5D A5 7B lda J+HI ; pick up carry + 5765 5C5F E9 00 sbc #0 ; we will + 5766 5C61 85 7B sta J+HI ; we did + 5767 5C63 VERD11: + 5768 5C63 20 E6 5C jsr VERIFY_FILE ; now, actually do the work + 5769 5C66 90 2D bcc VERDX ; worked just fine + 5770 5C68 DLINE VERBAD ; puke, gag, argh + 5771 5C68 A2 71 ldx #VERBAD ; get other part of string + 5773 [01] IFMA 2 ; check to see if length passed in + 5774 ldy ; then just fetch it + 5775 [01] ELSE + 5776 5C6C A0 22 ldy #VERBADL ; get length of string + 5777 [00] ENDIF + 5778 5C6E 20 6B 4C jsr DLINE ; print the string + 5779 5C71 .MACEND + 5780 ; + 5781 ; This prints out which file is garfed + 5782 ; + 5783 5C71 VER_FMSG: + 5784 5C71 AD 57 49 lda DISKCNTR ; which file did we do? + 5785 5C74 C9 02 cmp #2 ; 0,1 are in one place + 5786 5C76 B0 0D bcs VERDB1 ; nope it isn't it + 5787 5C78 DLINE GAME1NAME,GAME1NML + 5788 5C78 A2 78 ldx #GAME1NAME ; get other part of string + 5790 [01] IFMA 2 ; check to see if length passed in + 5791 5C7C AC 77 46 ldy GAME1NML ; then just fetch it + 5792 [01] ELSE + 5793 ldy #GAME1NAMEL ; get length of string + 5794 [00] ENDIF + 5795 5C7F 20 6B 4C jsr DLINE ; print the string + 5796 5C82 .MACEND + Wed Jun 7 1989 12:04 Page 84 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5797 5C82 4C 8F 5C jmp VERDB2 + 5798 5C85 VERDB1: + 5799 5C85 DLINE GAME2NAME,GAME2NML ; 2,3 are in another + 5800 5C85 A2 8A ldx #GAME2NAME ; get other part of string + 5802 [01] IFMA 2 ; check to see if length passed in + 5803 5C89 AC 89 46 ldy GAME2NML ; then just fetch it + 5804 [01] ELSE + 5805 ldy #GAME2NAMEL ; get length of string + 5806 [00] ENDIF + 5807 5C8C 20 6B 4C jsr DLINE ; print the string + 5808 5C8F .MACEND + 5809 5C8F VERDB2: + 5810 5C8F EE B5 5B inc ZVFLAG ; show bad file + 5811 5C92 20 E0 8C jsr GETRET ; just wait for + 5812 5C95 VERDX: + 5813 5C95 60 rts ; all done + 5814 ; + 5815 ; VERIFY_PICD - verify the picture data in a file. First check to see if + 5816 ; there is any. If so, seek to it, set J==0 to show VERIFY_FILE to read + 5817 ; til EOF, and print out bad picture data message if necessary. + 5818 ; + 5819 5C96 VERIFY_PICD: + 5820 5C96 A9 FF lda #$FF ; gonna zero bunch of stuff + 5821 5C98 85 7B sta J+HI ; and the counter + 5822 5C9A 85 7A sta J+LO ; which means now goto EOF + 5823 5C9C A0 02 ldy #SGTPICOF ; fetch the picture data offset + 5824 5C9E B1 1E lda (DSEGS),Y ; get MSB + 5825 5CA0 8D E0 45 sta PSEEK+SM_FPOS+2 ; we are doing pages + 5826 5CA3 C8 iny ; pointing to LSB + 5827 5CA4 11 1E ora (DSEGS),Y ; first, check for all zeros + 5828 5CA6 D0 01 bne VERP1 ; nope, some picture data is there + 5829 5CA8 60 rts ; just gwon back if nothing here + 5830 5CA9 VERP1: + 5831 5CA9 B1 1E lda (DSEGS),Y ; go get LSB + 5832 5CAB 0A asl A ; *2 to get 256 byte pages + 5833 5CAC 8D DF 45 sta PSEEK+SM_FPOS+1 ; put away here + 5834 5CAF 2E E0 45 rol PSEEK+SM_FPOS+2 ; pick up carry + 5835 5CB2 A9 10 lda #PHSIZE ; skip over header of file + 5836 5CB4 85 78 sta STARTPOS ; show offset in first block + 5837 5CB6 VERP11: + 5838 5CB6 SET_MARK PSEEK ; and move to picture data spot + 5839 5CB6 PRODOS $CE, PSEEK + 5840 5CB6 20 00 BF jsr $BF00 ; ProDOS handler + 5841 5CB9 CE DB $CE ; ProDOS function code + 5842 5CBA DC45 DW PSEEK ; Function Parameter Block address + 5843 5CBC .MACEND + 5844 5CBC .MACEND + 5845 5CBC 20 E6 5C jsr VERIFY_FILE ; read in the data + 5846 5CBF SET_MARK PSEEK ; get back to beginning of pic data + 5847 5CBF PRODOS $CE, PSEEK + 5848 5CBF 20 00 BF jsr $BF00 ; ProDOS handler + 5849 5CC2 CE DB $CE ; ProDOS function code + 5850 5CC3 DC45 DW PSEEK ; Function Parameter Block address + 5851 5CC5 .MACEND + 5852 5CC5 .MACEND + 5853 5CC5 READ READ_PB ; read in a block worth + 5854 5CC5 PRODOS $CA, READ_PB + 5855 5CC5 20 00 BF jsr $BF00 ; ProDOS handler + 5856 5CC8 CA DB $CA ; ProDOS function code + 5857 5CC9 CE45 DW READ_PB ; Function Parameter Block address + 5858 5CCB .MACEND + 5859 5CCB .MACEND + 5860 5CCB AD 0A 08 lda IOBUFF+PHCHKS ; get MSB of picture checksum + 5861 5CCE C5 7F cmp L+HI ; same as what we got? + 5862 5CD0 D0 07 bne VERPB ; nope + 5863 5CD2 AD 0B 08 lda IOBUFF+PHCHKS+1 ; get LSB of picture checksum + 5864 5CD5 C5 7E cmp L+LO ; same as mine? + 5865 5CD7 F0 0C beq VERPX ; yup, checked out fine + 5866 5CD9 VERPB: + 5867 5CD9 DLINE VERPBAD ; picture data bad + 5868 5CD9 A2 93 ldx #VERPBAD ; get other part of string + 5870 [01] IFMA 2 ; check to see if length passed in + 5871 ldy ; then just fetch it + Wed Jun 7 1989 12:04 Page 85 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5872 [01] ELSE + 5873 5CDD A0 22 ldy #VERPBADL ; get length of string + 5874 [00] ENDIF + 5875 5CDF 20 6B 4C jsr DLINE ; print the string + 5876 5CE2 .MACEND + 5877 5CE2 4C 71 5C jmp VER_FMSG ; print out file name + 5878 5CE5 VERPX: + 5879 5CE5 60 rts ; tootis finis + 5880 ; + 5881 ; VERIFY_FILE - Files is already open and pointing to start of checksummed + 5882 ; data. Works along til J == 0 or EOF, which ever comes first. Starts by + 5883 ; dec'ing J, so if J starts as 0, effectively means goto EOF. + 5884 ; + 5885 5CE6 VERIFY_FILE: + 5886 5CE6 A9 00 lda #0 ; clear out checksum counter + 5887 5CE8 85 7F sta L+HI ; MSB + 5888 5CEA 85 7E sta L+LO ; LSB + 5889 5CEC 8D D2 45 sta READ_PB+RD_BUFFLEN+LO + 5890 5CEF A9 04 lda #4 ; make read read $400 (1Kb) + 5891 5CF1 8D D3 45 sta READ_PB+RD_BUFFLEN+HI + 5892 5CF4 VFLOOP: + 5893 5CF4 A9 03 lda #RETRY_COUNT ; and set up retry count + 5894 5CF6 85 16 sta RETRIES + 5895 5CF8 A9 00 lda #IOBUFF ; reading all the data + 5898 5CFE 85 7D sta K+HI ; into, using as pointer + 5899 5D00 VFLRD: + 5900 5D00 READ READ_PB ; read in 1Kb of data + 5901 5D00 PRODOS $CA, READ_PB + 5902 5D00 20 00 BF jsr $BF00 ; ProDOS handler + 5903 5D03 CA DB $CA ; ProDOS function code + 5904 5D04 CE45 DW READ_PB ; Function Parameter Block address + 5905 5D06 .MACEND + 5906 5D06 .MACEND + 5907 5D06 90 0D bcc VERF0 ; just fine read + 5908 5D08 C9 4C cmp #$4C ; EOF error? + 5909 5D0A F0 32 beq VFCHECK ; yes, so wee bee done + 5910 5D0C C9 4D cmp #$4D ; InfoDOS EOF error? + 5911 5D0E F0 2E beq VFCHECK ; ayyup + 5912 5D10 20 07 47 jsr RETRY ; check about retrying + 5913 5D13 90 EB bcc VFLRD ; and do again + 5914 5D15 VERF0: + 5915 5D15 A5 7A lda J+LO ; count the block to be read + 5916 5D17 D0 06 bne VERF1 ; no wrapping + 5917 5D19 A5 7B lda J+HI ; anything left? + 5918 5D1B F0 21 beq VFCHECK ; nope, all done then + 5919 5D1D C6 7B dec J+HI ; count one block + 5920 5D1F VERF1: + 5921 5D1F C6 7A dec J+LO ; count block + 5922 5D21 A4 78 ldy STARTPOS ; and begin + 5923 5D23 VERF2: + 5924 5D23 B1 7C lda (K),Y ; get byte + 5925 5D25 18 clc ; doing add + 5926 5D26 65 7E adc L+LO ; add it in + 5927 5D28 85 7E sta L+LO ; save it + 5928 5D2A 90 02 bcc VERF3 ; no wrap + 5929 5D2C E6 7F inc L+HI ; yes ther is + 5930 5D2E VERF3: + 5931 5D2E C8 iny ; next byte + 5932 5D2F D0 F2 bne VERF2 ; back to start of inner tloop + 5933 + 5934 5D31 A9 00 lda #0 ; start at first byte + 5935 5D33 85 78 sta STARTPOS ; okay + 5936 5D35 E6 7D inc K+HI ; point to next block + 5937 5D37 CE D5 45 dec READ_PB+RD_LENGTH+HI ; count this one + 5938 5D3A F0 B8 beq VFLOOP ; go read some more + 5939 5D3C D0 D7 bne VERF0 ; go do next 256 byte block + 5940 5D3E VFCHECK: + 5941 5D3E A0 00 ldy #SGTCHKS ; get check sum + 5942 5D40 A5 7F lda L+HI ; start with MSB + 5943 5D42 D1 1E cmp (DSEGS),Y ; well . . . ? + 5944 5D44 D0 09 bne VFBAD ; nope, it is wrong + 5945 5D46 C8 iny ; first byte is okay + 5946 5D47 A5 7E lda L+LO ; so check LSB + Wed Jun 7 1989 12:04 Page 86 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5947 5D49 D1 1E cmp (DSEGS),Y ; well . . . ? + 5948 5D4B D0 02 bne VFBAD ; die a slow ugly death + 5949 5D4D 18 clc ; clear carry to show niceness + 5950 5D4E 60 rts + 5951 5D4F VFBAD: + 5952 5D4F 38 sec ; carry is set if bad + 5953 5D50 60 rts ; and return to your fate + 5954 ; + 5955 ; SETUP_DISK0 - this routine does some special processing to get the file + 5956 ; pointer to the beginning of data for the preload file. It skips over + 5957 ; segment table. + 5958 5D51 SETUP_DISK0: + 5959 5D51 READ READ_PB ; read in first block + 5960 5D51 PRODOS $CA, READ_PB + 5961 5D51 20 00 BF jsr $BF00 ; ProDOS handler + 5962 5D54 CA DB $CA ; ProDOS function code + 5963 5D55 CE45 DW READ_PB ; Function Parameter Block address + 5964 5D57 .MACEND + 5965 5D57 .MACEND + 5966 5D57 AD 00 08 lda IOBUFF ; MSB of segment table size (in words) + 5967 5D5A 8D DF 45 sta PSEEK+SM_FPOS+1 ; middle part of offset + 5968 5D5D AD 01 08 lda IOBUFF+1 ; LSB of size + 5969 5D60 0A asl A ; *2 to pick up carry + 5970 5D61 2E DF 45 rol PSEEK+SM_FPOS+1 ; rotate in carry + 5971 5D64 2E E0 45 rol PSEEK+SM_FPOS+2 ; and once more + 5972 5D67 A8 tay ; check for wrapping upwards + 5973 5D68 F0 08 beq STD01 ; no wrap up then + 5974 5D6A STD00: + 5975 5D6A EE DF 45 inc PSEEK+SM_FPOS+1 ; wee did + 5976 5D6D D0 03 bne STD01 ; no more wrapping + 5977 5D6F EE E0 45 inc PSEEK+SM_FPOS+2 ; yes there is + 5978 5D72 STD01: + 5979 5D72 AD DF 45 lda PSEEK+SM_FPOS+1 ; make sure it is a 512 byte page + 5980 5D75 29 01 and #$1 ; even page? + 5981 5D77 D0 F1 bne STD00 ; inc again, please + 5982 5D79 STD0X: + 5983 5D79 SET_MARK PSEEK ; skip the segment table stuff + 5984 5D79 PRODOS $CE, PSEEK + 5985 5D79 20 00 BF jsr $BF00 ; ProDOS handler + 5986 5D7C CE DB $CE ; ProDOS function code + 5987 5D7D DC45 DW PSEEK ; Function Parameter Block address + 5988 5D7F .MACEND + 5989 5D7F .MACEND + 5990 5D7F 60 rts ; all done + 5991 + 5992 5D80 END + 5993 + 5994 5D80 INCLUDE SCREEN.ASM + 5995 5D80 STTL "--- APPLE ][ SCREEN STUFF ---" + 5996 PAGE + Wed Jun 7 1989 12:04 Page 87 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 5997 + 5998 ; ----------------- + 5999 ; PRINT CHAR IN [A] AT CV,CH + 6000 ; ----------------- + 6001 ; + 6002 ; uses memory register [L] + 6003 ; + 6004 5D80 00 SAVECY DB 0 ; spot to save current screen y pos + 6005 5D81 00 SAVECX DB 0 ; spot for x pos + 6006 + 6007 5D82 CHAR: + 6008 5D82 85 AC sta IOCHAR ; SAVE HERE + 6009 5D84 8A txa ; SAVE [X] AND [Y] + 6010 5D85 48 pha + 6011 5D86 98 tya + 6012 5D87 48 pha + 6013 5D88 + 6014 5D88 A5 AC lda IOCHAR ; get it back + 6015 5D8A C9 08 cmp #BACKSPACE ; is it backspace with erase? + 6016 5D8C D0 03 bne CHCX ; nope + 6017 + 6018 5D8E 4C B0 5E jmp DO_BSPC ; so handle backspace + 6019 5D91 CHCX: + 6020 5D91 C9 0D cmp #EOL ; is it ? + 6021 5D93 D0 03 bne CHCONT ; just let dline handle it + 6022 5D95 + 6023 5D95 4C 7D 5E jmp DO_EOL ; handle + 6024 ; + 6025 ; so save some stuff and do all the necessary figgering + 6026 ; + 6027 5D98 CHCONT: + 6028 5D98 AE E4 71 ldx SCRCNT ; just stash character + 6029 5D9B 9D 80 02 sta SCRBUFF,X ; save it + 6030 5D9E EE E4 71 inc SCRCNT ; and count it + 6031 5DA1 CH_EXIT: + 6032 5DA1 68 pla ; RESTORE [X] AND [Y] + 6033 5DA2 A8 tay + 6034 5DA3 68 pla + 6035 5DA4 AA tax + 6036 5DA5 60 rts + 6037 ; + 6038 ; PUT_NYBBLE - put 4 bits to the screen at SCRCX, SCRCY (the lower 4 bits + 6039 ; in [A]). + 6040 ; + 6041 5DA6 PUT_NYBBLE: + 6042 5DA6 85 0E sta NY_DATA ; save [A] for mucking with + 6043 5DA8 20 51 5E jsr SETPOS ; set up offsets using SCRCX + 6044 + 6045 5DAB A9 08 lda #$8 ; start at first bit, left to right + 6046 5DAD 85 10 sta DATALOOP ; and init the counter with it + 6047 5DAF PNY0: + 6048 5DAF A6 8E ldx FPCBNK ; which bank + 6049 5DB1 BD 54 C0 lda PAGE2SW,X ; select it + 6050 5DB4 A0 00 ldy #0 ; start with zero + 6051 5DB6 B1 8C lda (FPC),Y ; get it + 6052 5DB8 85 13 sta SCR_DATA ; and save it + 6053 5DBA PNY1: + 6054 5DBA A6 11 ldx BITOFF ; get which interesting bit we want + 6055 5DBC BD 09 5E lda GT_BITS,X ; get bit + 6056 5DBF 48 pha ; save bit pictures + 6057 5DC0 A5 10 lda DATALOOP ; see if we have done all 4 bits in this 'pixel' + 6058 5DC2 F0 29 beq PNY_EXIT ; toots finis + 6059 5DC4 46 10 lsr DATALOOP ; point to next bit + 6060 5DC6 24 0E bit NY_DATA ; is this bit set? + 6061 5DC8 D0 08 bne PNY_SET ; yes it is, so we will handle different + 6062 ; + 6063 ; Bit is clear, so clear appropriate one in the SCR_DATA byte + 6064 ; + 6065 5DCA 68 pla ; get bit picture back + 6066 5DCB 49 FF eor #$FF ; turn bits all around + 6067 5DCD 25 13 and SCR_DATA ; turn off bit in screen data + 6068 5DCF 4C D5 5D jmp PNY_NEXT ; and continue + 6069 5DD2 PNY_SET: + 6070 5DD2 68 pla ; get bit mask back + 6071 5DD3 05 13 ora SCR_DATA ; turn on bit + Wed Jun 7 1989 12:04 Page 88 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6072 5DD5 PNY_NEXT: + 6073 5DD5 85 13 sta SCR_DATA ; save result + 6074 5DD7 E6 11 inc BITOFF ; we're looking at next bit + 6075 5DD9 A5 11 lda BITOFF ; now check how we're doing + 6076 5DDB C9 07 cmp #7 ; only doing bits 0-6 + 6077 5DDD D0 DB bne PNY1 ; check next bit + 6078 ; + 6079 ; we've finished this byte in screen memory, point to next one + 6080 ; + 6081 5DDF A9 00 lda #0 ; start at zero'th bit + 6082 5DE1 85 11 sta BITOFF ; thank you + 6083 5DE3 A5 13 lda SCR_DATA ; now stash this one in the screen + 6084 5DE5 91 8C sta (FPC),Y ; y is still zero; still pointing to bank + 6085 5DE7 20 F6 5D jsr NEXT_SCR ; make SPC/FPC point to next spot + 6086 5DEA 4C AF 5D jmp PNY0 ; and continue on please + 6087 ; + 6088 ; all done, so make sure we stash anything out there + 6089 ; + 6090 5DED PNY_EXIT: + 6091 5DED 68 pla ; get bit mask back to fix stack + 6092 5DEE A5 13 lda SCR_DATA ; put away the current data byte + 6093 5DF0 91 8C sta (FPC),Y ; y is still zero; still pointing to bank + 6094 5DF2 AD 54 C0 lda PAGE2SW+MAIN ; back to MAIN page 2 + 6095 5DF5 60 rts + 6096 ; + 6097 ; NEXT_SCR - make FPC/SPC point to next screen byte + 6098 ; + 6099 5DF6 NEXT_SCR: + 6100 ; + 6101 ; if in main bank, when we go to aux bank, we need to look at the next + 6102 ; byte in memory + 6103 ; + 6104 5DF6 A5 8E lda FPCBNK ; get what bank we're talking to currently + 6105 5DF8 D0 08 bne NXS0 ; 0 = main bank, 1 = aux bank + 6106 5DFA E6 8F inc SPCL ; point to next byte + 6107 5DFC E6 8C inc FPCL ; and for fetching + 6108 5DFE A9 01 lda #AUX ; and point to aux bank + 6109 5E00 D0 02 bne NXS1 ; (BRANCH) and continue on + 6110 ; + 6111 ; if in aux bank, all we need to do is switch banks + 6112 ; + 6113 5E02 NXS0: + 6114 5E02 A9 00 lda #MAIN ; just make it main bank + 6115 5E04 NXS1: + 6116 5E04 85 91 sta SPCBNK ; for stashing and + 6117 5E06 85 8E sta FPCBNK ; fetching + 6118 5E08 60 rts + 6119 ; + 6120 ; GET_NYBBLE - get the 4 bits which represent the screen at position + 6121 ; SCRCX, SCRCY; return nybble in low 4 bits of [A] + 6122 ; + 6123 5E09 01 02 04 08 10 GT_BITS: db 1,2,4,8,$10,$20,$40 + 5E0E 20 40 + 6124 5E10 GET_NYBBLE: + 6125 5E10 20 51 5E jsr SETPOS ; set up offsets using SCRCX + 6126 + 6127 5E13 A9 00 lda #0 ; clear out my data spot + 6128 5E15 85 0E sta NY_DATA ; for mucking with + 6129 + 6130 5E17 A9 10 lda #$10 ; setting bits 0-3, starting with shift + 6131 5E19 85 10 sta DATALOOP ; so init the setter + 6132 5E1B GNY0: + 6133 5E1B A6 8E ldx FPCBNK ; which bank + 6134 5E1D BD 54 C0 lda PAGE2SW,X ; save which bank + 6135 5E20 A0 00 ldy #0 ; zero y + 6136 5E22 B1 8C lda (FPC),Y ; get byte + 6137 5E24 85 13 sta SCR_DATA ; and save it + 6138 5E26 GNY1: + 6139 5E26 46 10 lsr DATALOOP ; see if we have done all 4 bits in this 'pixel' + 6140 5E28 F0 21 beq GNY_EXIT ; all done! + 6141 + 6142 5E2A A6 11 ldx BITOFF ; get bit offset + 6143 5E2C BD 09 5E lda GT_BITS,X ; get bit pattern + 6144 ; + 6145 ; now check appropriate bit in Screen Data + Wed Jun 7 1989 12:04 Page 89 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6146 ; + 6147 5E2F 25 13 and SCR_DATA ; see if it is set + 6148 5E31 F0 06 beq GNY3 ; no bit set here + 6149 ; + 6150 ; bit is set, so set it in my data nybble + 6151 ; + 6152 5E33 A5 10 lda DATALOOP ; get bit setter + 6153 5E35 05 0E ora NY_DATA ; and put it into my data byte + 6154 5E37 85 0E sta NY_DATA ; and save it + 6155 5E39 GNY3: + 6156 5E39 E6 11 inc BITOFF ; we're looking at next bit + 6157 5E3B A5 11 lda BITOFF ; now check how we're doing + 6158 5E3D C9 07 cmp #7 ; only doing bits 0-6 + 6159 5E3F D0 E5 bne GNY1 ; check next bit + 6160 ; + 6161 ; we've finished this byte in screen memory, point to next one + 6162 ; + 6163 5E41 A9 00 lda #0 ; start at zero'th bit + 6164 5E43 85 11 sta BITOFF ; thank you + 6165 5E45 20 F6 5D jsr NEXT_SCR ; point to next byte + 6166 5E48 4C 1B 5E jmp GNY0 ; and continue on please + 6167 5E4B GNY_EXIT: + 6168 5E4B AD 54 C0 lda PAGE2SW+MAIN ; back to main page 2 + 6169 5E4E A5 0E lda NY_DATA ; get the nybble desired + 6170 5E50 60 rts + 6171 ; + 6172 ; SETPOS - get the byte offset and the bit offset from the table using + 6173 ; SCRCX + 6174 ; + 6175 ; USES: SCRCX, SCRCY + 6176 ; SETS: FPC - pointer to correct screen memory location + 6177 ; BITOFF - bit offset to get to start of byte (N.B. this is left to + 6178 ; right count, while in memory it is right to left!) + 6179 5E51 SETPOS: + 6180 5E51 A5 00 lda SCRCX ; get the x pos + 6181 5E53 AA tax ; put where we can use it + 6182 5E54 BD 52 03 lda XPOSTBL,X ; get byte # + 6183 5E57 85 8C sta FPCL ; okay, saved + 6184 5E59 BD B7 6B lda XBITTBL,X ; get bitoffset + 6185 5E5C 85 11 sta BITOFF ; where it wants it + 6186 + 6187 5E5E A5 8C lda FPCL ; check for correct bank + 6188 5E60 29 01 and #$01 ; if odd, then must be main bank + 6189 5E62 D0 04 bne STP11 ; okay, it be odd + 6190 5E64 A9 01 lda #AUX ; aux bank + 6191 5E66 D0 02 bne STP22 ; jump + 6192 5E68 STP11: + 6193 5E68 A9 00 lda #MAIN ; main bank + 6194 5E6A STP22: + 6195 5E6A 85 8E sta FPCBNK ; save it + 6196 5E6C A5 8C lda FPCL ; get for fetch + 6197 5E6E 4A lsr A ; /2 to get correct byte offset + 6198 5E6F A6 01 ldx SCRCY ; get vertical pos + 6199 5E71 18 clc ; get ready for adding + 6200 5E72 7D 37 6A adc BASEL,X ; add low part + 6201 5E75 85 8C sta FPCL ; save low part + 6202 5E77 BD F7 6A lda BASEH,X ; get high part + 6203 5E7A 85 8D sta FPCH ; save high part + 6204 5E7C 60 rts ; done !? + 6205 ; + 6206 ; DO_EOL - if this is end of line, check if we are at end of window + 6207 ; and if we are, and it is a scrollable window, scroll. Then move + 6208 ; the cursor to the left margin of said window + 6209 ; + 6210 5E7D DO_EOL: + 6211 5E7D 20 F1 71 jsr DISP_LINE ; make sure line gets out there + 6212 5E80 A5 01 lda SCRCY ; get current vertical pos + 6213 5E82 18 clc ; add font height + 6214 5E83 69 09 adc #FONT_H ; thank you + 6215 5E85 48 pha ; save this position + 6216 5E86 69 09 adc #FONT_H ; make sure we have room for characters here + 6217 5E88 C5 02 cmp SCRBTM ; so check against the bottom + 6218 5E8A F0 02 beq SAVECV ; no scroll yet + 6219 5E8C B0 05 bcs SCROLLCITY ; nope, can't use it + 6220 5E8E SAVECV: + Wed Jun 7 1989 12:04 Page 90 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6221 5E8E 68 pla ; get new CV + 6222 5E8F 85 01 sta SCRCY ; and save it + 6223 5E91 D0 09 bne DEL1 ; JUMP + 6224 5E93 SCROLLCITY: + 6225 5E93 68 pla ; get bad y pos + 6226 5E94 AD DC 71 lda SCRLFLG ; is this a scrolling window? + 6227 5E97 F0 03 beq DEL1 ; nope, just move to left edge + 6228 5E99 20 ED 5F jsr SCROLL_UP ; and scroll window + 6229 5E9C DEL1: + 6230 ; + 6231 ; move cursor back to left margin + 6232 ; + 6233 5E9C A5 04 lda LEFTMRG ; get left margin + 6234 5E9E 85 00 sta SCRCX ; and set itpositions + 6235 5EA0 A9 01 lda #1 ; show cursor changed (maybe) + 6236 5EA2 8D 7C 6C sta CURSFLG ; okay + 6237 5EA5 A9 00 lda #0 ; clear length too + 6238 5EA7 85 A7 sta LENGTH+LO ; no more on line + 6239 5EA9 85 A8 sta LENGTH+HI ; no more on line + 6240 5EAB 4C A1 5D jmp CH_EXIT ; now finish it up + 6241 ; + 6242 ; DO_BSPC - do a backspace, by erasing char just before cursor to + 6243 ; background color, and moving cursor back one space + 6244 ; [X] == character to delete + 6245 ; + 6246 5EAE 0000 SAVECHX: DW 0 + 6247 + 6248 5EB0 DO_BSPC: + 6249 5EB0 AD D8 71 lda CHR_X+LO ; figger new CHR_X + 6250 5EB3 38 sec ; subtract width + 6251 5EB4 A4 C1 ldy FONTFLG ; get which font we be using + 6252 5EB6 F0 05 beq DOBSP0 ; must be variable width + 6253 5EB8 E9 0C sbc #MONOFONT_W ; get width then of mono font + 6254 5EBA 4C C0 5E jmp DOBSP1 ; okay, now do add + 6255 5EBD DOBSP0: + 6256 5EBD FD 2A 64 sbc CHWID,X ; get width of char to be erased + 6257 5EC0 DOBSP1: + 6258 5EC0 8D D8 71 sta CHR_X+LO ; show new one + 6259 5EC3 8D AE 5E sta SAVECHX+LO ; save to restore later + 6260 5EC6 AD D9 71 lda CHR_X+HI ; and pick up carry + 6261 5EC9 E9 00 sbc #0 ; okay, did it + 6262 5ECB 8D D9 71 sta CHR_X+HI ; save it + 6263 5ECE 8D AF 5E sta SAVECHX+HI ; okay + 6264 5ED1 A0 20 ldy #SPACE ; get SPACE offset + 6265 5ED3 A5 C1 lda FONTFLG ; monospaced font? + 6266 5ED5 F0 04 beq DOBSP2 ; nope + 6267 5ED7 A9 0C lda #MONOFONT_W ; make monospaced wide + 6268 5ED9 D0 03 bne DOBSP3 ; fine + 6269 5EDB DOBSP2: + 6270 5EDB BD 2A 64 lda CHWID,X ; get width of char + 6271 5EDE DOBSP3: + 6272 5EDE 99 2A 64 sta CHWID,Y ; set space to be this wide + 6273 5EE1 8C 80 02 sty SCRBUFF ; make space for erasing + 6274 5EE4 A9 01 lda #1 ; show one char + 6275 5EE6 8D E4 71 sta SCRCNT ; assume it used to be zero + 6276 5EE9 20 F1 71 jsr DISP_LINE ; put that space out + 6277 5EEC AD AE 5E lda SAVECHX+LO ; restore old/new x pos + 6278 5EEF 8D D8 71 sta CHR_X+LO + 6279 5EF2 AD AF 5E lda SAVECHX+HI + 6280 5EF5 8D D9 71 sta CHR_X+HI + 6281 5EF8 20 8A 73 jsr GET_SCRCX ; update SCRCX please + 6282 + 6283 5EFB A9 08 lda #SPACE_WIDTH ; restore width of space char + 6284 5EFD A0 20 ldy #SPACE ; get offset + 6285 5EFF 99 2A 64 sta CHWID,Y ; okay + 6286 + 6287 5F02 4C A1 5D jmp CH_EXIT ; done + 6288 ; + 6289 ; CLS - clear the window, using CLS parameters + 6290 ; + 6291 5F05 CLS: + 6292 5F05 A5 00 lda SCRCX ; save the current X,Y + 6293 5F07 8D 81 5D sta SAVECX ; x + 6294 5F0A A5 01 lda SCRCY + 6295 5F0C 8D 80 5D sta SAVECY ; saved + Wed Jun 7 1989 12:04 Page 91 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6296 5F0F A5 0B lda CLSTOP ; get top line + 6297 5F11 85 01 sta SCRCY ; and set up a y pos + 6298 + 6299 5F13 20 C1 5F jsr SETMASK ; set up masks and ending point + 6300 + 6301 5F16 A5 BD lda CPY_COUNT ; get count + 6302 5F18 85 14 sta SH_LOOP ; save count + 6303 5F1A A5 0A lda CLSLEFT ; get left edge + 6304 5F1C 85 00 sta SCRCX ; set up as X pos + 6305 5F1E A0 0E ldy #WINBGND ; get background offset + 6306 5F20 B1 05 lda (WINDOW),Y ; get background color + 6307 5F22 85 71 sta ARG8 ; save it here + 6308 5F24 A5 0C lda CLSWIDTH ; how wide we be? + 6309 5F26 D0 05 bne CLSOKAY ; not a zero width + 6310 5F28 A9 19 lda #25 ; zero can't do zero width + 6311 5F2A 4C 0A 52 jmp ZERROR ; so die + 6312 5F2D CLSOKAY: + 6313 5F2D C9 03 cmp #3 ; if skinny, handle special + 6314 5F2F B0 28 bcs L1L0 ; nope + 6315 5F31 85 6F sta ARG7 ; make this be the counter + 6316 5F33 A5 0D lda CLSHEIGHT ; just use PUT/GET NYBBLE if only one wide + 6317 5F35 D0 05 bne CLSOKAY1 ; not a zero height either + 6318 5F37 A9 19 lda #25 ; bad error + 6319 5F39 4C 0A 52 jmp ZERROR + 6320 5F3C CLSOKAY1: + 6321 5F3C 85 7A sta J ; save here + 6322 5F3E CLS1W: + 6323 5F3E A5 71 lda ARG8 ; get color + 6324 5F40 20 A6 5D jsr PUT_NYBBLE ; put it + 6325 5F43 E6 00 inc SCRCX ; next x + 6326 5F45 C6 6F dec ARG7 ; counter + 6327 5F47 D0 F5 bne CLS1W ; do next X + 6328 5F49 A5 0A lda CLSLEFT ; get left edge again + 6329 5F4B 85 00 sta SCRCX ; point to it + 6330 5F4D E6 01 inc SCRCY ; next line + 6331 5F4F A5 0C lda CLSWIDTH ; restore width count + 6332 5F51 85 6F sta ARG7 ; thanks + 6333 5F53 C6 7A dec J ; count + 6334 5F55 D0 E7 bne CLS1W ; do it + 6335 5F57 F0 56 beq CLSEXIT ; all done then + 6336 5F59 L1L0: + 6337 5F59 85 7A sta J ; use j as counter + 6338 5F5B L1L: + 6339 5F5B A5 71 lda ARG8 ; a color please + 6340 5F5D 20 A6 5D jsr PUT_NYBBLE ; do first line easy + 6341 5F60 E6 00 inc SCRCX ; next nybble + 6342 5F62 C6 7A dec J ; done yet? + 6343 5F64 D0 F5 bne L1L ; nope + 6344 + 6345 5F66 A5 0A lda CLSLEFT ; where is left column + 6346 5F68 85 00 sta SCRCX ; here! + 6347 5F6A 20 51 5E jsr SETPOS ; get the address + 6348 5F6D 20 78 90 jsr FP2SP ; SPC is source PC, now! + 6349 5F70 A5 0D lda CLSHEIGHT ; how many lines are we clearing + 6350 5F72 D0 05 bne CLSOKAY2 ; not a zero height either + 6351 5F74 A9 19 lda #25 ; bad error + 6352 5F76 4C 0A 52 jmp ZERROR + 6353 5F79 CLSOKAY2: + 6354 5F79 85 7A sta J ; j is counter again + 6355 5F7B C6 7A dec J ; already cleared one line + 6356 5F7D F0 30 beq CLSEXIT ; only one line to do! + 6357 5F7F CLSLOOP: + 6358 5F7F A5 90 lda SPCH ; now, modify COPY_LINE + 6359 5F81 8D 7D 1D sta CPY_MOD1_SRC+HI + 6360 5F84 8D A1 1D sta CPY_MOD2_SRC+HI + 6361 5F87 A5 8F lda SPCL + 6362 5F89 8D 7C 1D sta CPY_MOD1_SRC+LO + 6363 5F8C 8D A0 1D sta CPY_MOD2_SRC+LO + 6364 5F8F E6 01 inc SCRCY ; clear this line + 6365 5F91 20 51 5E jsr SETPOS ; where am i? + 6366 5F94 A5 8D lda FPCH ; now, modify COPY_LINE + 6367 5F96 8D 80 1D sta CPY_MOD1_DST+HI + 6368 5F99 8D A4 1D sta CPY_MOD2_DST+HI + 6369 5F9C A5 8C lda FPCL + 6370 5F9E 8D 7F 1D sta CPY_MOD1_DST+LO + Wed Jun 7 1989 12:04 Page 92 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6371 5FA1 8D A3 1D sta CPY_MOD2_DST+LO + 6372 5FA4 A5 14 lda SH_LOOP ; get count + 6373 5FA6 85 BD sta CPY_COUNT ; and save it + 6374 5FA8 20 50 1D jsr COPY_LINE ; did the copy (i hope) + 6375 5FAB C6 7A dec J ; count it + 6376 5FAD D0 D0 bne CLSLOOP ; next one please + 6377 5FAF CLSEXIT: + 6378 5FAF AD 81 5D lda SAVECX ; get X,Y back + 6379 5FB2 85 00 sta SCRCX ; got it + 6380 5FB4 AD 80 5D lda SAVECY ; now for y + 6381 5FB7 85 01 sta SCRCY ; restored! + 6382 + 6383 5FB9 60 rts + 6384 ; + 6385 ; SETMASK - figger out the start and end masks, as well as setting + 6386 ; stuff to point to stopping address. Use CLSLEFT and CLSWIDTH + 6387 ; + 6388 5FBA 00 01 03 07 0F ST_BITS: db 0,1,3,7,$f,$1f,$3f + 5FBF 1F 3F + 6389 5FC1 SETMASK: + 6390 5FC1 A5 0A lda CLSLEFT ; munge with SCRX + 6391 5FC3 85 00 sta SCRCX ; okay + 6392 5FC5 20 51 5E jsr SETPOS ; get me the bit offset of start + 6393 + 6394 5FC8 A6 11 ldx BITOFF ; now set up mask + 6395 5FCA BD BA 5F lda ST_BITS,X ; get the bit pattern + 6396 5FCD 85 1A sta STMASK ; save it + 6397 + 6398 5FCF A5 0A lda CLSLEFT ; get left edge again + 6399 5FD1 18 clc ; add width + 6400 5FD2 65 0C adc CLSWIDTH ; to get where to stop + 6401 5FD4 AA tax ; make index + 6402 5FD5 86 00 stx SCRCX ; set cur pos + 6403 5FD7 BD 52 03 lda XPOSTBL,X ; get how many bytes + 6404 5FDA A6 0A ldx CLSLEFT ; subtract from byte offset of start + 6405 5FDC 38 sec ; subbing + 6406 5FDD FD 52 03 sbc XPOSTBL,X + 6407 5FE0 85 BD sta CPY_COUNT ; and save it + 6408 + 6409 5FE2 20 51 5E jsr SETPOS ; so get its address + 6410 + 6411 5FE5 A6 11 ldx BITOFF ; get bit offset + 6412 5FE7 BD BA 5F lda ST_BITS,X ; get pattern + 6413 5FEA 85 1B sta ENDMASK ; okay! + 6414 5FEC 60 rts + 6415 ; + 6416 ; SCROLL_UP - roll the current window by FONT_H lines + 6417 ; + 6418 5FED SCROLL_UP: + 6419 5FED A9 09 lda #FONT_H ; show one line + 6420 5FEF 85 18 sta SCLLINES ; done + 6421 5FF1 85 1D sta SCLDIR ; show scroll up with positive number + 6422 5FF3 A0 00 ldy #WINTOP ; get top of screen + 6423 5FF5 B1 05 lda (WINDOW),Y ; got it + 6424 5FF7 85 0B sta CLSTOP ; saved it + 6425 5FF9 C8 iny ; point to left edge + 6426 5FFA B1 05 lda (WINDOW),Y ; get left edge + 6427 5FFC 85 0A sta CLSLEFT ; save + 6428 5FFE C8 iny ; this is now the height + 6429 5FFF B1 05 lda (WINDOW),Y ; get window height + 6430 6001 85 0D sta CLSHEIGHT ; show me + 6431 6003 C8 iny ; and now for the width + 6432 6004 B1 05 lda (WINDOW),Y ; get width + 6433 6006 85 0C sta CLSWIDTH ; saved it + 6434 ; so fall thru + 6435 ; and do the scrolling + 6436 ; FALLING THRU + 6437 ; | + 6438 ; \ / + 6439 ; + 6440 ; + 6441 ; DO_SCROLL - scroll SCLLINES withing the window as defined by + 6442 ; CLSLEFT,TOP,WIDTH, and HEIGHT + 6443 ; + 6444 6008 DO_SCROLL: + Wed Jun 7 1989 12:04 Page 93 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6445 6008 A5 00 lda SCRCX ; save the current X,Y + 6446 600A 8D 81 5D sta SAVECX ; x + 6447 600D A5 01 lda SCRCY + 6448 600F 8D 80 5D sta SAVECY ; saved + 6449 6012 A5 18 lda SCLLINES ; how many lines? + 6450 + 6451 6014 A6 1D ldx SCLDIR ; which direction? + 6452 6016 10 04 bpl SC1 ; >0 means scroll up + 6453 ; + 6454 ; scroll down, so we are going to start at the bottom and copy downwards + 6455 ; until we reach the top + 6456 ; + 6457 ; now modify code so we do adds to get destination line and subtracts + 6458 ; to get new src line + 6459 ; + 6460 6018 A0 C6 ldy #$C6 ; 'dec' opcode + 6461 601A D0 04 bne SC2 ; jump to modify + 6462 601C SC1: + 6463 ; + 6464 ; scroll up - start at top and copy upwards until we reach the bottom + 6465 ; + 6466 601C A0 E6 ldy #$E6 ; 'inc' opcode + 6467 601E A6 18 ldx SCLLINES ; get # of scrolling lines + 6468 6020 SC2: + 6469 6020 8C D7 60 sty SCMOD1 ; make inc/dec + 6470 6023 8C D9 60 sty SCMOD2 ; either inc or dec + 6471 6026 86 1C stx SCOFF ; save the offset between SRC and DST + 6472 + 6473 6028 A5 1D lda SCLDIR ; which direction? + 6474 602A 10 13 bpl SC3 ; must be normal scroll + 6475 ; + 6476 ; if scrolling downwards, we need to start source at bottom-offset and + 6477 ; end when the destination is at top+offset + 6478 ; + 6479 602C A5 0D lda CLSHEIGHT ; get # of lines in window + 6480 602E 38 sec ; subbing + 6481 602F E5 1C sbc SCOFF ; subtract offset to get source + 6482 6031 18 clc ; adding + 6483 6032 65 0B adc CLSTOP ; and get absolute position + 6484 6034 AA tax ; put in X + 6485 6035 CA dex ; for 0 offset it + 6486 6036 A5 0B lda CLSTOP ; now figger last line to copy + 6487 6038 18 clc ; adding + 6488 6039 65 0D adc CLSHEIGHT ; get me last line + 6489 603B A8 tay ; for later storage + 6490 603C 88 dey ; make 0 based + 6491 603D D0 08 bne SC4 ; always jumps + 6492 603F SC3: + 6493 ; + 6494 ; if scrolling upwards, start src at top+offset and end when destination + 6495 ; is at bottom-offset + 6496 ; + 6497 603F A5 0B lda CLSTOP ; get top + 6498 6041 18 clc ; adding + 6499 6042 65 1C adc SCOFF ; add in offset + 6500 6044 AA tax ; for later on + 6501 6045 A4 0B ldy CLSTOP ; first destination is top of window + 6502 6047 SC4: + 6503 6047 86 01 stx SCRCY ; Starting Source + 6504 6049 84 15 sty SCROLLY ; Starting Destination + 6505 + 6506 604B 20 C1 5F jsr SETMASK ; set the masks and horizontal endpoint + 6507 604E A5 BD lda CPY_COUNT ; save for future generations + 6508 6050 85 14 sta SH_LOOP ; save it + 6509 6052 A5 0D lda CLSHEIGHT ; how high + 6510 6054 85 10 sta DATALOOP ; save as counter + 6511 6056 38 sec ; for subbing + 6512 6057 E5 1C sbc SCOFF ; subtract scrolling amount + 6513 6059 85 0D sta CLSHEIGHT ; this is how many lines to copy + 6514 605B A5 01 lda SCRCY ; save Start Source + 6515 605D 48 pha + 6516 605E A5 0B lda CLSTOP ; start at Y pos + 6517 6060 85 01 sta SCRCY + 6518 6062 A5 0A lda CLSLEFT ; and x pos + 6519 6064 85 00 sta SCRCX ; thank you + Wed Jun 7 1989 12:04 Page 94 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6520 6066 AD 54 C0 lda PAGE2SW+MAIN ; make sure main memory page is in there + 6521 6069 SCRL1: + 6522 6069 20 51 5E jsr SETPOS ; set up line pointer + 6523 606C A4 01 ldy SCRCY ; get top + 6524 606E C0 78 cpy #120 ; 120 bytes per list + 6525 6070 90 05 bcc SCRLY ; all set + 6526 6072 98 tya ; for adding + 6527 6073 18 clc + 6528 6074 69 08 adc #8 + 6529 6076 A8 tay + 6530 6077 SCRLY: + 6531 6077 A5 8D lda FPCH + 6532 6079 99 00 06 sta SV_PCH,Y + 6533 607C A5 8C lda FPCL + 6534 607E 99 00 04 sta SV_PCL,Y + 6535 6081 E6 01 inc SCRCY ; next line please + 6536 6083 C6 10 dec DATALOOP + 6537 6085 D0 E2 bne SCRL1 + 6538 + 6539 6087 68 pla ; get StartSource back + 6540 6088 85 01 sta SCRCY + 6541 608A A5 8E lda FPCBNK ; init SPC bank too + 6542 608C 85 91 sta SPCBNK ; fine, we did + 6543 608E SCROLLING: + 6544 608E A4 01 ldy SCRCY ; get source Y for index + 6545 6090 C0 78 cpy #120 ; jump over junk + 6546 6092 90 05 bcc SCLYY + 6547 6094 98 tya + 6548 6095 18 clc + 6549 6096 69 08 adc #8 + 6550 6098 A8 tay + 6551 6099 SCLYY: + 6552 6099 B9 00 06 lda SV_PCH,Y + 6553 609C 85 90 sta SPCH + 6554 609E 8D 7D 1D sta CPY_MOD1_SRC+HI + 6555 60A1 8D A1 1D sta CPY_MOD2_SRC+HI + 6556 60A4 B9 00 04 lda SV_PCL,Y + 6557 60A7 8D 7C 1D sta CPY_MOD1_SRC+LO + 6558 60AA 8D A0 1D sta CPY_MOD2_SRC+LO + 6559 60AD 85 8F sta SPCL + 6560 + 6561 60AF A4 15 ldy SCROLLY ; get destination Y pos + 6562 60B1 C0 78 cpy #120 ; jump over junk + 6563 60B3 90 05 bcc SCLYY1 + 6564 60B5 98 tya + 6565 60B6 18 clc + 6566 60B7 69 08 adc #8 + 6567 60B9 A8 tay + 6568 60BA SCLYY1: + 6569 60BA B9 00 06 lda SV_PCH,Y + 6570 60BD 85 8D sta FPCH + 6571 60BF 8D 80 1D sta CPY_MOD1_DST+HI + 6572 60C2 8D A4 1D sta CPY_MOD2_DST+HI + 6573 60C5 B9 00 04 lda SV_PCL,Y + 6574 60C8 8D 7F 1D sta CPY_MOD1_DST+LO + 6575 60CB 8D A3 1D sta CPY_MOD2_DST+LO + 6576 60CE 85 8C sta FPCL + 6577 + 6578 60D0 A5 14 lda SH_LOOP ; get byte counter + 6579 60D2 85 BD sta CPY_COUNT ; show copy line + 6580 60D4 20 50 1D jsr COPY_LINE ; and do the copy + 6581 60D7 E6 01 SCMOD1: inc SCRCY ; inc or dec to get next one + 6582 60D9 E6 15 SCMOD2: inc SCROLLY ; inc/dec for next destination Y + 6583 60DB C6 0D dec CLSHEIGHT ; count down + 6584 60DD D0 AF bne SCROLLING ; nope + 6585 + 6586 60DF A6 1D ldx SCLDIR ; scroll up or down? + 6587 60E1 10 09 bpl SCLCLR1 ; clear a little different + 6588 ; + 6589 ; if scrolling down, clear from current Y+1 + 6590 ; + 6591 60E3 A5 01 lda SCRCY ; get current source + 6592 60E5 85 0B sta CLSTOP ; save in top spot + 6593 60E7 E6 0B inc CLSTOP ; get inside window + 6594 60E9 4C F0 60 jmp SCLCLR2 + Wed Jun 7 1989 12:04 Page 95 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6595 60EC SCLCLR1: + 6596 60EC A5 15 lda SCROLLY ; get last destination + 6597 60EE 85 0B sta CLSTOP ; and save it + 6598 60F0 SCLCLR2: + 6599 60F0 A5 1C lda SCOFF ; and both clear this many lines + 6600 60F2 85 0D sta CLSHEIGHT ; okay? + 6601 + 6602 60F4 AD 81 5D lda SAVECX ; now restore X and Y + 6603 60F7 85 00 sta SCRCX ; x + 6604 60F9 AD 80 5D lda SAVECY ; and + 6605 60FC 85 01 sta SCRCY ; y + 6606 + 6607 60FE 20 05 5F jsr CLS ; WIDTH and LEFT should be okay still + 6608 + 6609 6101 60 rts + 6610 ; + 6611 ; CLREOL - clear from current cursor position to end of line by + 6612 ; using CLS after changing the window size + 6613 ; + 6614 6102 CLREOL: + 6615 6102 A5 00 lda SCRCX ; and make left be where cursor is + 6616 6104 85 0A sta CLSLEFT + 6617 6106 A5 01 lda SCRCY ; and top be where Y is + 6618 6108 85 0B sta CLSTOP + 6619 610A A9 09 lda #FONT_H ; and bottom be bottom of char + 6620 610C 85 0D sta CLSHEIGHT + 6621 610E A0 03 ldy #WINWID ; get width + 6622 6110 B1 05 lda (WINDOW),Y ; got it + 6623 6112 18 clc ; now adding + 6624 6113 A0 01 ldy #WINLEFT ; the left edge + 6625 6115 71 05 adc (WINDOW),Y ; to get the right edge + 6626 6117 38 sec ; subbing + 6627 6118 E5 0A sbc CLSLEFT ; and subtract left to get width + 6628 611A A0 07 ldy #WINRM ; remove the size of the right margin + 6629 611C F1 05 sbc (WINDOW),Y ; that too + 6630 611E 85 0C sta CLSWIDTH ; okay? + 6631 6120 4C 05 5F jmp CLS ; now clear the screen + 6632 ; + 6633 ; COPY_SCRL - copy from SCR_LINE onto the screen. CH_OFFSET says how + 6634 ; many bytes in SCR_LINE to copy. FPC is assumed to be pointing + 6635 ; to start of screen bytes. BITTER has the original BITOFF from + 6636 ; SETPOS. ENDBIT shows how many significant bits in last byte. + 6637 ; + 6638 6123 COPY_SCRL: + 6639 6123 AE E3 71 ldx SHOW_CURSOR ; are we showing the cursor (ugh) + 6640 6126 F0 03 beq COPYL2 ; nope + 6641 6128 4C A2 73 jmp DO_CURSOR ; then XOR cursor in + 6642 612B COPYL2: + 6643 612B A0 0E ldy #WINBGND ; get background offset + 6644 612D B1 05 lda (WINDOW),Y ; get current background color + 6645 612F F0 03 beq COPY_SCRL1 ; if black, ignore this + 6646 6131 20 F2 61 jsr FIX_COLOR ; or in the color, please + 6647 ; + 6648 ; Alternate entry point for COPY_SCRL, used by picture drawing routine + 6649 ; to avoid using background color and checking for cursor + 6650 ; + 6651 6134 COPY_SCRL1: + 6652 6134 A6 8E ldx FPCBNK ; set up bank + 6653 6136 BD 54 C0 lda PAGE2SW,X ; set first bank + 6654 6139 AD DA 71 lda ENDBIT ; did we end evenly? + 6655 613C D0 02 bne COPYL22 ; nope + 6656 613E E6 0F inc CH_OFFSET ; make CH_OFFSET be a counter + 6657 6140 COPYL22: + 6658 6140 A0 00 ldy #0 ; zero y + 6659 + 6660 6142 A5 0F lda CH_OFFSET ; if only one, then handle real special + 6661 6144 D0 24 bne COPYL21 ; nope + 6662 + 6663 6146 AE E1 71 ldx BITTER ; get starting bit offset + 6664 6149 BD BA 5F lda ST_BITS,X ; get starting bit mask + 6665 614C 85 AC sta IOCHAR ; save it + 6666 614E AE DA 71 ldx ENDBIT ; get ending bit offset + 6667 6151 BD BA 5F lda ST_BITS,X ; combine with ending mask bits + 6668 6154 49 FF eor #$FF ; set for good ones + 6669 6156 05 AC ora IOCHAR ; set up mask for bits + Wed Jun 7 1989 12:04 Page 96 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6670 6158 31 8C and (FPC),Y ; get me interesting bits + 6671 615A 91 8C sta (FPC),Y ; save + 6672 615C A5 AC lda IOCHAR ; get flag for data + 6673 615E 49 FF eor #$FF ; flip to get good data + 6674 6160 2D 00 1F CPYSM1: and SCR_LINE ; pick up my bits + 6675 6163 11 8C ora (FPC),Y ; and or in screen data + 6676 6165 91 8C sta (FPC),Y ; and save it + 6677 6167 4C EE 61 jmp COPYLEX ; go away now + 6678 616A COPYL21: + 6679 616A A5 0F lda CH_OFFSET ; get # of chars + 6680 616C 4A lsr A ; /2 get number in this bank + 6681 616D 69 00 adc #0 ; pick up carry for first one + 6682 616F 85 10 sta DATALOOP ; and save it to work on + 6683 + 6684 6171 AE E1 71 ldx BITTER ; do we have a weird start? + 6685 6174 F0 1A beq DLL2 ; nope + 6686 ; + 6687 ; need to do the first one special + 6688 ; + 6689 6176 B1 8C lda (FPC),Y ; get byte + 6690 6178 3D BA 5F and ST_BITS,X ; get masking bits + 6691 617B 85 AC sta IOCHAR ; save for later + 6692 617D BD BA 5F lda ST_BITS,X ; get masking bits again + 6693 6180 49 FF eor #$FF ; get good bits + 6694 6182 2D 00 1F CPYSM2: and SCR_LINE ; get first data byte + 6695 6185 05 AC ora IOCHAR ; pick up screen bits + 6696 6187 91 8C sta (FPC),Y ; pointing + 6697 6189 C8 iny ; next byte + 6698 618A A2 02 ldx #2 ; start at next one for this bank + 6699 618C C6 10 dec DATALOOP ; kount as done + 6700 618E COPYLOOP: + 6701 618E F0 0C beq CPYLP2 ; all done with this part of line + 6702 6190 DLL2: + 6703 6190 BD 00 1F CPYSM3: lda SCR_LINE,X ; get data + 6704 6193 91 8C sta (FPC),Y ; pointing + 6705 6195 C8 iny ; next byte + 6706 6196 E8 inx ; next one + 6707 6197 E8 inx ; next one + 6708 6198 C6 10 dec DATALOOP ; count as used + 6709 619A 10 F2 bpl COPYLOOP ; start loop again + 6710 619C CPYLP2: + 6711 619C A0 00 ldy #0 ; reset Y + 6712 619E A5 8E lda FPCBNK ; which bank were we at + 6713 61A0 49 01 eor #1 ; swap to other one + 6714 61A2 AA tax ; make it in x + 6715 61A3 BD 54 C0 lda PAGE2SW,X ; swap to write bank + 6716 61A6 8A txa ; check which one + 6717 61A7 F0 01 beq CPYLP23 ; correct offset + 6718 61A9 C8 iny ; fix offset if going from main to aux + 6719 61AA CPYLP23: + 6720 61AA A2 01 ldx #1 ; start at second byte in screen line + 6721 61AC A5 0F lda CH_OFFSET ; get starting number + 6722 61AE 4A lsr A ; /2 to get how many for this bank + 6723 61AF 85 10 sta DATALOOP ; and show it + 6724 61B1 COPYLOOP2: + 6725 61B1 F0 0C beq LINE_DONE ; all done with this part of line + 6726 + 6727 61B3 BD 00 1F CPYSM4: lda SCR_LINE,X ; get data + 6728 61B6 91 8C sta (FPC),Y ; pointing + 6729 61B8 C8 iny ; next byte + 6730 61B9 E8 inx ; next one + 6731 61BA E8 inx ; next one + 6732 61BB C6 10 dec DATALOOP ; count as used + 6733 61BD 10 F2 bpl COPYLOOP2 ; start loop again + 6734 61BF LINE_DONE: + 6735 ; + 6736 ; do the last byte special + 6737 ; + 6738 61BF 86 10 stx DATALOOP ; save pointer + 6739 61C1 AD DA 71 lda ENDBIT ; get ending bit offset + 6740 61C4 F0 28 beq COPYLEX ; all done if nothing funky + 6741 61C6 46 0F lsr CH_OFFSET ; get line offset + 6742 61C8 48 pha ; save [A] + 6743 61C9 B0 0B bcs LINED1 ; if odd, point at right things + 6744 61CB C6 10 dec DATALOOP ; one less then + Wed Jun 7 1989 12:04 Page 97 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6745 61CD A6 8E ldx FPCBNK ; get original bank + 6746 61CF BD 54 C0 lda PAGE2SW,X ; switch to it + 6747 61D2 8A txa ; which bank did we do? + 6748 61D3 D0 01 bne LINED1 ; no need to step back one + 6749 61D5 88 dey ; point one less here too + 6750 61D6 LINED1: + 6751 61D6 68 pla ; get ENDBIT back + 6752 61D7 AA tax ; make end bits be index + 6753 61D8 BD BA 5F lda ST_BITS,X ; get end mask + 6754 61DB 85 AC sta IOCHAR ; save mask bits + 6755 61DD 49 FF eor #$FF ; toggle every bit + 6756 61DF 31 8C and (FPC),Y ; get the interesting bits in byte + 6757 61E1 91 8C sta (FPC),Y ; save it + 6758 61E3 A6 10 ldx DATALOOP ; get data pointer + 6759 61E5 BD 00 1F CPYSM5: lda SCR_LINE,X ; turn on my bits + 6760 61E8 25 AC and IOCHAR ; pick up my good bits + 6761 61EA 11 8C ora (FPC),Y ; bring everything together + 6762 61EC 91 8C sta (FPC),Y ; save the byte + 6763 61EE COPYLEX: + 6764 61EE AD 54 C0 lda PAGE2SW+MAIN ; back to main, thanks + 6765 61F1 60 rts + 6766 + 6767 61F2 FIX_COLOR: + 6768 61F2 E6 0F inc CH_OFFSET ; just to make checking easier for now + 6769 + 6770 61F4 0A asl A ; *2 + 6771 61F5 0A asl A ; *4 to get correct offset + 6772 61F6 69 12 adc #COLORS ; get hi part + 6775 61FC 69 00 adc #0 ; pick up maybe carry + 6776 61FE 85 AE sta COLORP+HI ; save pointer + 6777 6200 A2 11 ldx #$11 ; ORA (),Y opcode + 6778 6202 A0 0D ldy #WINFORE ; check foreground color + 6779 6204 B1 05 lda (WINDOW),Y ; check what color + 6780 6206 D0 11 bne FIXC1 ; just leave white if not black + 6781 6208 A2 00 ldx #0 ; start at beginning + 6782 620A FIXMUNGEL: + 6783 620A BD 00 1F lda SCR_LINE,X ; get byte + 6784 620D 49 FF eor #$FF ; swap all the bits + 6785 620F 9D 00 1F sta SCR_LINE,X ; store back + 6786 6212 E8 inx ; count it + 6787 6213 E4 0F cpx CH_OFFSET ; done? + 6788 6215 90 F3 bcc FIXMUNGEL ; nope + 6789 6217 A2 31 ldx #$31 ; AND (),Y opcode + 6790 6219 FIXC1: + 6791 6219 8E 27 62 stx FCLM ; self mod my code (again . . . sigh) + 6792 621C AD E1 71 lda BITTER ; get starting offset + 6793 621F 29 03 and #3 ; pick up wrap + 6794 6221 A8 tay ; make index + 6795 6222 A2 00 ldx #0 ; start at zero line + 6796 6224 FIXLOOP: + 6797 6224 BD 00 1F FCM1: lda SCR_LINE,X ; get screen byte + 6798 6227 11 AD FCLM: ora (COLORP),Y ; or with color byte + 6799 6229 9D 00 1F FCM2: sta SCR_LINE,X ; save it + 6800 622C C8 iny ; next color byte + 6801 622D C0 04 cpy #4 ; wrapped? + 6802 622F D0 02 bne FIXLP1 ; nope + 6803 6231 A0 00 ldy #0 ; restart + 6804 6233 FIXLP1: + 6805 6233 E8 inx ; next screen byte + 6806 6234 E4 0F cpx CH_OFFSET ; done yet? + 6807 6236 90 EC bcc FIXLOOP ; nope + 6808 6238 + 6809 6238 C6 0F dec CH_OFFSET ; fix counter + 6810 623A 60 rts ; now we are done + 6811 ; + 6812 ; MSCURS - Erase the cursor from the old spot and write it in the + 6813 ; new spot + 6814 ; + 6815 623B 8C MOLDX: db MAXWIDTH ; spot to save x,y of mouse + 6816 623C C0 MOLDY: db MAXHEIGHT + 6817 623D MSCCNT: ds 1 + 6818 623E SVCURS: ds CURSW*CURSH ; save room + 6819 6246 01 MSWCNT: db 1 + Wed Jun 7 1989 12:04 Page 98 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6820 6247 00 MSSTATE: db 0 ; 0 == off, 1 == on + 6821 6248 0F 07 07 07 07 MSCOLOR: db $f,7,7,7,7,7,7,7 + 624D 07 07 07 + 6822 ; + 6823 6250 MSCURS: + 6824 6250 A9 00 lda #0 ; clear moved flag + 6825 6252 8D 12 03 sta MSMOVEF ; we did + 6826 6255 20 5B 62 jsr MSCOFF ; turn cursor off at current pos + 6827 6258 4C BA 62 jmp MSCON ; and turn it on in new spot + 6828 + 6829 ; + 6830 ; MSCOFF - mouse cursor off + 6831 ; Copy info from saved spot back onto screen @ MOLDX, MOLDY + 6832 625B MSCOFF: + 6833 625B AD 47 62 lda MSSTATE ; already off? + 6834 625E D0 01 bne MSCOFF1 ; no + 6835 6260 60 rts ; done then + 6836 6261 MSCOFF1: + 6837 6261 A5 01 lda SCRCY ; save X,Y + 6838 6263 8D 80 5D sta SAVECY + 6839 6266 A5 00 lda SCRCX + 6840 6268 8D 81 5D sta SAVECX + 6841 626B AD 3B 62 lda MOLDX ; point to old X,Y + 6842 626E 85 00 sta SCRCX + 6843 6270 AD 3C 62 lda MOLDY + 6844 6273 85 01 sta SCRCY + 6845 6275 A9 00 lda #0 ; start at beginning of saved area + 6846 6277 8D 3D 62 sta MSCCNT ; save counter + 6847 627A A9 02 lda #CURSW ; restore width + 6848 627C 8D 46 62 sta MSWCNT ; and counter + 6849 627F RENEWL: + 6850 627F A5 01 lda SCRCY ; check bounds + 6851 6281 C9 C0 cmp #MAXHEIGHT + 6852 6283 B0 32 bcs MSC1 ; all done + 6853 6285 RENEWL0: + 6854 6285 A5 00 lda SCRCX + 6855 6287 C9 8C cmp #MAXWIDTH + 6856 6289 B0 1E bcs RENEWL1 ; might not be done + 6857 628B 20 10 5E jsr GET_NYBBLE ; get screen nybble + 6858 628E AE 3D 62 ldx MSCCNT ; get counter + 6859 ; eor MSCOLOR,X ; xor to turn off + 6860 6291 49 0F eor #$0F ; turn white/black + 6861 6293 20 A6 5D jsr PUT_NYBBLE ; save nybble + 6862 6296 EE 3D 62 inc MSCCNT ; point to next one + 6863 6299 AD 3D 62 lda MSCCNT ; get counter + 6864 629C C9 08 cmp #(CURSW*CURSH) ; done yet? + 6865 629E F0 17 beq MSC1 ; yup + 6866 62A0 CE 46 62 dec MSWCNT ; count down one width + 6867 62A3 F0 04 beq RENEWL1 ; it is + 6868 62A5 E6 00 inc SCRCX ; next x + 6869 62A7 D0 DC bne RENEWL0 ; try again + 6870 62A9 RENEWL1: + 6871 62A9 AD 3B 62 lda MOLDX ; reset X + 6872 62AC 85 00 sta SCRCX + 6873 62AE A9 02 lda #CURSW ; restore width + 6874 62B0 8D 46 62 sta MSWCNT ; and counter + 6875 62B3 E6 01 inc SCRCY ; next y + 6876 62B5 D0 C8 bne RENEWL ; okay try some more + 6877 62B7 MSC1: + 6878 62B7 4C 19 63 jmp MSCON4 ; done turning it off + 6879 ; + 6880 ; MSCON - turn mouse cursor on + 6881 ; Copy white pixels into area specified by MSX, MSY + 6882 ; + 6883 62BA MSCON: + 6884 62BA AD 47 62 lda MSSTATE ; already on? + 6885 62BD F0 01 beq MSCON0 ; no + 6886 62BF 60 rts ; don't bother + 6887 62C0 MSCON0: + 6888 62C0 A5 01 lda SCRCY ; save X,Y + 6889 62C2 8D 80 5D sta SAVECY + 6890 62C5 A5 00 lda SCRCX + 6891 62C7 8D 81 5D sta SAVECX + 6892 + 6893 62CA A5 CB lda MSX ; get mouse x + Wed Jun 7 1989 12:04 Page 99 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6894 62CC 85 00 sta SCRCX ; set mouse X + 6895 62CE 8D 3B 62 sta MOLDX ; save mouse x + 6896 62D1 A5 CC lda MSY ; get mouse y + 6897 62D3 85 01 sta SCRCY ; set mouse Y + 6898 62D5 8D 3C 62 sta MOLDY ; and mouse Y + 6899 62D8 A9 00 lda #0 ; start at beginning of saved area + 6900 62DA 8D 3D 62 sta MSCCNT ; save counter + 6901 62DD A9 02 lda #CURSW ; restore width + 6902 62DF 8D 46 62 sta MSWCNT ; and counter + 6903 62E2 MSCON1: + 6904 62E2 A5 01 lda SCRCY ; check bounds + 6905 62E4 C9 C0 cmp #MAXHEIGHT + 6906 62E6 B0 31 bcs MSCON4 ; all done + 6907 62E8 MSCON2: + 6908 62E8 A5 00 lda SCRCX + 6909 62EA C9 8C cmp #MAXWIDTH + 6910 62EC B0 1E bcs MSCON3 ; might not be done + 6911 62EE 20 10 5E jsr GET_NYBBLE ; save nybble + 6912 62F1 AE 3D 62 ldx MSCCNT ; get counter + 6913 ; eor MSCOLOR,X ; get cursor color + 6914 62F4 49 0F eor #$0F ; turn white/black + 6915 62F6 20 A6 5D jsr PUT_NYBBLE ; put nybble + 6916 62F9 EE 3D 62 inc MSCCNT ; point to next one + 6917 62FC AD 3D 62 lda MSCCNT ; check ending + 6918 62FF C9 08 cmp #(CURSW*CURSH) ; done yet? + 6919 6301 F0 16 beq MSCON4 ; yup + 6920 6303 CE 46 62 dec MSWCNT ; count down one width + 6921 6306 F0 04 beq MSCON3 ; finished for line + 6922 6308 E6 00 inc SCRCX ; next x + 6923 630A D0 DC bne MSCON2 ; try again + 6924 630C MSCON3: + 6925 630C A5 CB lda MSX ; reset X + 6926 630E 85 00 sta SCRCX + 6927 6310 A9 02 lda #CURSW ; restore width + 6928 6312 8D 46 62 sta MSWCNT ; and counter + 6929 6315 E6 01 inc SCRCY ; next y + 6930 6317 D0 C9 bne MSCON1 ; okay try some more + 6931 6319 MSCON4: + 6932 6319 AD 47 62 lda MSSTATE ; get current state + 6933 631C 49 01 eor #$01 ; toggle it + 6934 631E 8D 47 62 sta MSSTATE ; bang + 6935 6321 AD 81 5D lda SAVECX ; restore X,Y + 6936 6324 85 00 sta SCRCX + 6937 6326 AD 80 5D lda SAVECY + 6938 6329 85 01 sta SCRCY + 6939 632B 60 rts + 6940 632C + 6941 + 6942 632C END + 6943 + 6944 632C INCLUDE TABLES.ASM + 6945 632C STTL "--- ZIP DATA TABLES ---" + 6946 PAGE + Wed Jun 7 1989 12:04 Page 100 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6947 632C CHADR_H: + 6948 632C 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 6331 00 00 00 00 00 + 6336 00 00 00 00 00 + 633B 00 + 6949 633C 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 6341 00 00 00 00 00 + 6346 00 00 00 00 00 + 634B 00 + 6950 634C 64 64 64 64 64 db >C20,>C21,>C22,>C23,>C24,>C25,>C26,>C27 + 6351 64 65 65 + 6951 6354 65 65 65 65 65 DB >C28,>C29,>C2A,>C2B,>C2C,>C2D,>C2E,>C2F + 6359 65 65 65 + 6952 635C 65 65 65 65 65 db >C30,>C31,>C32,>C33,>C34,>C35,>C36,>C37 + 6361 65 65 65 + 6953 6364 65 66 66 66 66 DB >C38,>C39,>C3A,>C3B,>C3C,>C3D,>C3E,>C3F + 6369 66 66 66 + 6954 636C 66 66 66 66 66 db >C40,>C41,>C42,>C43,>C44,>C45,>C46,>C47 + 6371 66 66 66 + 6955 6374 66 66 66 67 67 DB >C48,>C49,>C4A,>C4B,>C4C,>C4D,>C4E,>C4F + 6379 67 67 67 + 6956 637C 67 67 67 67 67 db >C50,>C51,>C52,>C53,>C54,>C55,>C56,>C57 + 6381 67 67 67 + 6957 6384 67 68 68 68 68 DB >C58,>C59,>C5A,>C5B,>C5C,>C5D,>C5E,>C5F + 6389 68 68 68 + 6958 638C 68 68 68 68 68 db >C60,>C61,>C62,>C63,>C64,>C65,>C66,>C67 + 6391 68 68 68 + 6959 6394 68 68 68 69 69 DB >C68,>C69,>C6A,>C6B,>C6C,>C6D,>C6E,>C6F + 6399 69 69 69 + 6960 639C 69 69 69 69 69 db >C70,>C71,>C72,>C73,>C74,>C75,>C76,>C77 + 63A1 69 69 69 + 6961 63A4 69 69 69 6A 6A DB >C78,>C79,>C7A,>C7B,>C7C,>C7D,>C7E + 63A9 6A 6A + 6962 63AB CHADR_L: + 6963 63AB 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 63B0 00 00 00 00 00 + 63B5 00 00 00 00 00 + 63BA 00 + 6964 63BB 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 63C0 00 00 00 00 00 + 63C5 00 00 00 00 00 + 63CA 00 + 6965 63CB A9 BB C4 D6 E8 db 8 + 664C 70 00 00 00 + 7020 6650 3F 80 71 C0 03 C3F DB 3f,80,71,c0,03,80,0e,00,0e,00,00,00,0e,00,00,00,00,00 ;? 10 + 6655 80 0E 00 0E 00 + 665A 00 00 0E 00 00 + 665F 00 00 00 + 7021 6662 1F F8 E0 0E E3 C40 DB 1f,f8,e0,0e,e3,e7,e6,77,e6,77,e3,bc,e0,00,1f,f8,00,00 ;@ 16 + 6667 E7 E6 77 E6 77 + 666C E3 BC E0 00 1F + 6671 F8 00 00 + 7022 6674 3F 80 71 C0 71 C41 DB 3f,80,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;A 10 + 6679 C0 7F C0 71 C0 + 667E 71 C0 71 C0 00 + 6683 00 00 00 + 7023 6686 7F 80 71 C0 71 C42 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,7f,80,00,00,00,00 ;B 10 + 668B C0 7F 00 71 C0 + 6690 71 C0 7F 80 00 + 6695 00 00 00 + 7024 6698 3F 80 71 C0 70 C43 DB 3f,80,71,c0,70,00,70,00,70,00,71,c0,3f,80,00,00,00,00 ;C 10 + 669D 00 70 00 70 00 + 66A2 71 C0 3F 80 00 + 66A7 00 00 00 + 7025 66AA 7F 80 71 C0 71 C44 DB 7f,80,71,c0,71,c0,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;D 10 + 66AF C0 71 C0 71 C0 + 66B4 71 C0 7F 80 00 + 66B9 00 00 00 + 7026 66BC 7F 70 70 7F 70 C45 DB 7f,70,70,7f,70,70,7f,00,00 ;E 8 + 66C1 70 7F 00 00 + 7027 66C5 7F 70 70 7E 70 C46 DB 7f,70,70,7e,70,70,70,00,00 ;F 8 + 66CA 70 70 00 00 + 7028 66CE 3F 80 71 C0 70 C47 DB 3f,80,71,c0,70,00,73,c0,71,c0,71,c0,3f,80,00,00,00,00 ;G 10 + 66D3 00 73 C0 71 C0 + Wed Jun 7 1989 12:04 Page 103 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 66D8 71 C0 3F 80 00 + 66DD 00 00 00 + 7029 66E0 71 C0 71 C0 71 C48 DB 71,c0,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;H 10 + 66E5 C0 7F C0 71 C0 + 66EA 71 C0 71 C0 00 + 66EF 00 00 00 + 7030 66F2 70 70 70 70 70 C49 DB 70,70,70,70,70,70,70,00,00 ;I 4 + 66F7 70 70 00 00 + 7031 66FB 01 C0 01 C0 01 C4A DB 01,c0,01,c0,01,c0,01,c0,71,c0,71,c0,3f,80,00,00,00,00 ;J 10 + 6700 C0 01 C0 71 C0 + 6705 71 C0 3F 80 00 + 670A 00 00 00 + 7032 670D 70 E0 71 C0 73 C4B DB 70,e0,71,c0,73,80,7f,00,73,80,71,c0,70,e0,00,00,00,00 ;K 11 + 6712 80 7F 00 73 80 + 6717 71 C0 70 E0 00 + 671C 00 00 00 + 7033 671F 70 70 70 70 70 C4C DB 70,70,70,70,70,70,7f,00,00 ;L 8 + 6724 70 7F 00 00 + 7034 6728 78 3C 7C 7C 7E C4D DB 78,3c,7c,7c,7e,fc,77,dc,73,9c,70,1c,70,1c,00,00,00,00 ;M 14 + 672D FC 77 DC 73 9C + 6732 70 1C 70 1C 00 + 6737 00 00 00 + 7035 673A 78 70 7C 70 7E C4E DB 78,70,7c,70,7e,70,77,70,73,f0,71,f0,70,f0,00,00,00,00 ;N 12 + 673F 70 77 70 73 F0 + 6744 71 F0 70 F0 00 + 6749 00 00 00 + 7036 674C 3F 80 71 C0 71 C4F DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;O 10 + 6751 C0 71 C0 71 C0 + 6756 71 C0 3F 80 00 + 675B 00 00 00 + 7037 675E 7F 80 71 C0 71 C50 DB 7f,80,71,c0,71,c0,7f,80,70,00,70,00,70,00,00,00,00,00 ;P 10 + 6763 C0 7F 80 70 00 + 6768 70 00 70 00 00 + 676D 00 00 00 + 7038 6770 3F 80 71 C0 71 C51 DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,00,03,c0,00,00 ;Q 10 + 6775 C0 71 C0 71 C0 + 677A 71 C0 3F 00 03 + 677F C0 00 00 + 7039 6782 7F 80 71 C0 71 C52 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,71,c0,00,00,00,00 ;R 10 + 6787 C0 7F 00 71 C0 + 678C 71 C0 71 C0 00 + 6791 00 00 00 + 7040 6794 3F 80 71 C0 78 C53 DB 3f,80,71,c0,78,00,1f,00,03,c0,71,c0,3f,80,00,00,00,00 ;S 10 + 6799 00 1F 00 03 C0 + 679E 71 C0 3F 80 00 + 67A3 00 00 00 + 7041 67A6 7F C0 0E 00 0E C54 DB 7f,c0,0e,00,0e,00,0e,00,0e,00,0e,00,0e,00,00,00,00,00 ;T 10 + 67AB 00 0E 00 0E 00 + 67B0 0E 00 0E 00 00 + 67B5 00 00 00 + 7042 67B8 71 C0 71 C0 71 C55 DB 71,c0,71,c0,71,c0,71,c0,71,c0,71,c0,1f,00,00,00,00,00 ;U 10 + 67BD C0 71 C0 71 C0 + 67C2 71 C0 1F 00 00 + 67C7 00 00 00 + 7043 67CA 71 C0 71 C0 71 C56 DB 71,c0,71,c0,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;V 10 + 67CF C0 71 C0 73 80 + 67D4 77 00 7E 00 00 + 67D9 00 00 00 + 7044 67DC 71 C7 71 C7 71 C57 DB 71,c7,71,c7,71,c7,71,c7,71,c7,71,dc,7f,f8,00,00,00,00 ;W 16 + 67E1 C7 71 C7 71 C7 + 67E6 71 DC 7F F8 00 + 67EB 00 00 00 + 7045 67EE 71 C0 71 C0 71 C58 DB 71,c0,71,c0,71,c0,1f,00,71,c0,71,c0,71,c0,00,00,00,00 ;X 10 + 67F3 C0 1F 00 71 C0 + 67F8 71 C0 71 C0 00 + 67FD 00 00 00 + 7046 6800 71 C0 71 C0 71 C59 DB 71,c0,71,c0,71,c0,3f,80,0e,00,0e,00,0e,00,00,00,00,00 ;Y 10 + 6805 C0 3F 80 0E 00 + 680A 0E 00 0E 00 00 + 680F 00 00 00 + 7047 6812 7F C0 01 C0 03 C5A DB 7f,c0,01,c0,03,80,0e,00,38,00,70,00,7f,c0,00,00,00,00 ;Z 10 + 6817 80 0E 00 38 00 + 681C 70 00 7F C0 00 + 6821 00 00 00 + 7048 6824 7F 70 70 70 70 C5B DB 7f,70,70,70,70,70,7f,00,00 ;[ 8 + Wed Jun 7 1989 12:04 Page 104 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6829 70 7F 00 00 + 7049 682D 70 00 38 00 1C C5C DB 70,00,38,00,1c,00,0e,00,07,00,03,80,01,c0,00,00,00,00 ;\ 10 + 6832 00 0E 00 07 00 + 6837 03 80 01 C0 00 + 683C 00 00 00 + 7050 683F 7F 07 07 07 07 C5D DB 7f,07,07,07,07,07,7f,00,00 ;] 8 + 6844 07 7F 00 00 + 7051 6848 00 00 0C 00 3F C5E DB 00,00,0c,00,3f,00,e1,c0,00,00,00,00,00,00,00,00,00,00 ;^ 10 + 684D 00 E1 C0 00 00 + 6852 00 00 00 00 00 + 6857 00 00 00 + 7052 685A 00 00 00 00 00 C5F DB 00,00,00,00,00,00,00,ff,00 ;_ 8 + 685F 00 00 FF 00 + 7053 6863 70 38 1C 00 00 C60 DB 70,38,1c,00,00,00,00,00,00 ;` 6 + 6868 00 00 00 00 + 7054 686C 00 00 00 00 3F C61 DB 00,00,00,00,3f,80,01,c0,3f,c0,71,c0,3f,c0,00,00,00,00 ;a 10 + 6871 80 01 C0 3F C0 + 6876 71 C0 3F C0 00 + 687B 00 00 00 + 7055 687E 70 00 70 00 7F C62 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;b 10 + 6883 80 71 C0 71 C0 + 6888 71 C0 7F 80 00 + 688D 00 00 00 + 7056 6890 00 00 00 00 3F C63 DB 00,00,00,00,3f,80,71,c0,70,00,71,c0,3f,80,00,00,00,00 ;c 10 + 6895 80 71 C0 70 00 + 689A 71 C0 3F 80 00 + 689F 00 00 00 + 7057 68A2 01 C0 01 C0 3F C64 DB 01,c0,01,c0,3f,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;d 10 + 68A7 C0 71 C0 71 C0 + 68AC 71 C0 3F C0 00 + 68B1 00 00 00 + 7058 68B4 00 00 00 00 3F C65 DB 00,00,00,00,3f,80,79,c0,7f,c0,70,00,3f,80,00,00,00,00 ;e 10 + 68B9 80 79 C0 7F C0 + 68BE 70 00 3F 80 00 + 68C3 00 00 00 + 7059 68C6 0F 1C 7F 1C 1C C66 DB 0f,1c,7f,1c,1c,1c,1c,00,00 ;f 8 + 68CB 1C 1C 00 00 + 7060 68CF 00 00 00 00 3F C67 DB 00,00,00,00,3f,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;g 10 + 68D4 C0 71 C0 71 C0 + 68D9 71 C0 3F C0 01 + 68DE C0 3F 80 + 7061 68E1 70 00 70 00 7F C68 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;h 10 + 68E6 80 71 C0 71 C0 + 68EB 71 C0 71 C0 00 + 68F0 00 00 00 + 7062 68F3 70 00 70 70 70 C69 DB 70,00,70,70,70,70,70,00,00 ;i 5 + 68F8 70 70 00 00 + 7063 68FC 0E 00 0E 0E 0E C6A DB 0e,00,0e,0e,0e,0e,0e,0e,7c ;j 8 + 6901 0E 0E 0E 7C + 7064 6905 70 00 70 00 71 C6B DB 70,00,70,00,71,c0,73,80,7f,00,73,80,71,c0,00,00,00,00 ;k 10 + 690A C0 73 80 7F 00 + 690F 73 80 71 C0 00 + 6914 00 00 00 + 7065 6917 70 70 70 70 70 C6C DB 70,70,70,70,70,70,70,00,00 ;l 5 + 691C 70 70 00 00 + 7066 6920 00 00 00 00 7F C6D DB 00,00,00,00,7f,fc,73,9c,73,9c,73,9c,73,9c,00,00,00,00 ;m 14 + 6925 FC 73 9C 73 9C + 692A 73 9C 73 9C 00 + 692F 00 00 00 + 7067 6932 00 00 00 00 7F C6E DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;n 10 + 6937 80 71 C0 71 C0 + 693C 71 C0 71 C0 00 + 6941 00 00 00 + 7068 6944 00 00 00 00 3F C6F DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;o 10 + 6949 80 71 C0 71 C0 + 694E 71 C0 3F 80 00 + 6953 00 00 00 + 7069 6956 00 00 00 00 7F C70 DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,7f,80,70,00,70,00 ;p 10 + 695B 80 71 C0 71 C0 + 6960 71 C0 7F 80 70 + 6965 00 70 00 + 7070 6968 00 00 00 00 3F C71 DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,c0,01,c0,01,c0 ;q 10 + 696D 80 71 C0 71 C0 + 6972 71 C0 3F C0 01 + 6977 C0 01 C0 + Wed Jun 7 1989 12:04 Page 105 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 7071 697A 00 00 77 7C 70 C72 DB 00,00,77,7c,70,70,70,00,00 ;r 8 + 697F 70 70 00 00 + 7072 6983 00 00 00 00 3F C73 DB 00,00,00,00,3f,00,70,00,1e,00,03,80,3f,00,00,00,00,00 ;s 9 + 6988 00 70 00 1E 00 + 698D 03 80 3F 00 00 + 6992 00 00 00 + 7073 6995 1C 1C 7F 1C 1C C74 DB 1c,1c,7f,1c,1c,1c,0f,00,00 ;t 8 + 699A 1C 0F 00 00 + 7074 699E 00 00 00 00 71 C75 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;u 10 + 69A3 C0 71 C0 71 C0 + 69A8 71 C0 3F C0 00 + 69AD 00 00 00 + 7075 69B0 00 00 00 00 71 C76 DB 00,00,00,00,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;v 10 + 69B5 C0 71 C0 73 80 + 69BA 77 00 7E 00 00 + 69BF 00 00 00 + 7076 69C2 00 00 00 00 73 C77 DB 00,00,00,00,73,9c,73,9c,73,9c,73,9c,7f,f8,00,00,00,00 ;w 14 + 69C7 9C 73 9C 73 9C + 69CC 73 9C 7F F8 00 + 69D1 00 00 00 + 7077 69D4 00 00 00 00 71 C78 DB 00,00,00,00,71,c0,71,c0,1f,00,71,c0,71,c0,00,00,00,00 ;x 10 + 69D9 C0 71 C0 1F 00 + 69DE 71 C0 71 C0 00 + 69E3 00 00 00 + 7078 69E6 00 00 00 00 71 C79 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;y 10 + 69EB C0 71 C0 71 C0 + 69F0 71 C0 3F C0 01 + 69F5 C0 3F 80 + 7079 69F8 00 00 00 00 7F C7A DB 00,00,00,00,7f,c0,03,80,0e,00,38,00,7f,c0,00,00,00,00 ;z 10 + 69FD C0 03 80 0E 00 + 6A02 38 00 7F C0 00 + 6A07 00 00 00 + 7080 6A0A 1F 38 38 F0 38 C7B DB 1f,38,38,f0,38,38,1f,00,00 ;} 8 + 6A0F 38 1F 00 00 + 7081 6A13 70 70 70 70 70 C7C DB 70,70,70,70,70,70,70,70,70 ;| 5 + 6A18 70 70 70 70 + 7082 6A1C F8 1C 1C 0F 1C C7D DB f8,1c,1c,0f,1c,1c,f8,00,00 ;} 8 + 6A21 1C F8 00 00 + 7083 6A25 00 00 00 00 3C C7E DB 00,00,00,00,3c,e0,e7,80,00,00,00,00,00,00,00,00,00,00 ;~ 11 + 6A2A E0 E7 80 00 00 + 6A2F 00 00 00 00 00 + 6A34 00 00 00 + 7084 ; + 7085 ; base addresses for the screen lines + 7086 ; + 7087 6A37 BASEL: + 7088 6A37 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A3C 00 00 00 + 7089 6A3F 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A44 80 80 80 + 7090 6A47 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A4C 00 00 00 + 7091 6A4F 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A54 80 80 80 + 7092 6A57 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A5C 00 00 00 + 7093 6A5F 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A64 80 80 80 + 7094 6A67 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A6C 00 00 00 + 7095 6A6F 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A74 80 80 80 + 7096 6A77 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + 6A7C 28 28 28 + 7097 6A7F A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6A84 A8 A8 A8 + 7098 6A87 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + 6A8C 28 28 28 + 7099 6A8F A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6A94 A8 A8 A8 + 7100 6A97 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + 6A9C 28 28 28 + 7101 6A9F A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6AA4 A8 A8 A8 + 7102 6AA7 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + Wed Jun 7 1989 12:04 Page 106 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6AAC 28 28 28 + 7103 6AAF A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6AB4 A8 A8 A8 + 7104 6AB7 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6ABC 50 50 50 + 7105 6ABF D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6AC4 D0 D0 D0 + 7106 6AC7 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6ACC 50 50 50 + 7107 6ACF D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6AD4 D0 D0 D0 + 7108 6AD7 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6ADC 50 50 50 + 7109 6ADF D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6AE4 D0 D0 D0 + 7110 6AE7 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6AEC 50 50 50 + 7111 6AEF D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6AF4 D0 D0 D0 + 7112 6AF7 BASEH: + 7113 6AF7 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6AFC 34 38 3C + 7114 6AFF 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B04 34 38 3C + 7115 6B07 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B0C 35 39 3D + 7116 6B0F 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B14 35 39 3D + 7117 6B17 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B1C 36 3A 3E + 7118 6B1F 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B24 36 3A 3E + 7119 6B27 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B2C 37 3B 3F + 7120 6B2F 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B34 37 3B 3F + 7121 6B37 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B3C 34 38 3C + 7122 6B3F 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B44 34 38 3C + 7123 6B47 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B4C 35 39 3D + 7124 6B4F 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B54 35 39 3D + 7125 6B57 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B5C 36 3A 3E + 7126 6B5F 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B64 36 3A 3E + 7127 6B67 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B6C 37 3B 3F + 7128 6B6F 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B74 37 3B 3F + 7129 6B77 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B7C 34 38 3C + 7130 6B7F 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B84 34 38 3C + 7131 6B87 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B8C 35 39 3D + 7132 6B8F 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B94 35 39 3D + 7133 6B97 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B9C 36 3A 3E + 7134 6B9F 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6BA4 36 3A 3E + 7135 6BA7 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6BAC 37 3B 3F + 7136 6BAF 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6BB4 37 3B 3F + 7137 ; + 7138 ; this gives the bit offset for each one + 7139 ; + 7140 6BB7 XBITTBL: + 7141 6BB7 00 DB 0 + 7142 6BB8 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BBD 03 00 + Wed Jun 7 1989 12:04 Page 107 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 7143 6BBF 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BC4 03 00 + 7144 6BC6 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BCB 03 00 + 7145 6BCD 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BD2 03 00 + 7146 6BD4 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BD9 03 00 + 7147 6BDB 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BE0 03 00 + 7148 6BE2 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BE7 03 00 + 7149 6BE9 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BEE 03 00 + 7150 6BF0 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BF5 03 00 + 7151 6BF7 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BFC 03 00 + 7152 6BFE 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C03 03 00 + 7153 6C05 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C0A 03 00 + 7154 6C0C 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C11 03 00 + 7155 6C13 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C18 03 00 + 7156 6C1A 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C1F 03 00 + 7157 6C21 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C26 03 00 + 7158 6C28 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C2D 03 00 + 7159 6C2F 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C34 03 00 + 7160 6C36 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C3B 03 00 + 7161 6C3D 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C42 03 00 + 7162 RADIX D + 7163 6C44 00 01 06 07 0C ZIPCOLOR: db 0,1,6,7,$C,$B,$E,$F + 6C49 0B 0E 0F + 7164 6C4C 02 03 FF FF FF APLCOLOR: db 2,3,$FF,$FF,$FF,$FF,4,5,$FF,$FF,$FF,7,$FF,$FF,8,9 + 6C51 FF 04 05 FF FF + 6C56 FF 07 FF FF 08 + 6C5B 09 + 7165 6C5C OLDZV: + 7166 ; + 7167 ; Variables that used to be in the zero page but got moved out + 7168 ; + 7169 6C5C PSVFLG EQU OLDZV ; (BYTE) PRESERVE FLAG FOR LEX 0=DON'T 1=DO + 7170 6C5D VOCFLG EQU PSVFLG+1 ; (BYTE) WHICH VOC TBL, 0=NORMAL 1= ARG3 + 7171 6C5E DBLOCK EQU VOCFLG+1 ; (WORD) Z-BLOCK TO READ + 7172 6C60 QUOT EQU DBLOCK+2 ; (WORD) QUOTIENT FOR DIVISION + 7173 6C62 REMAIN EQU QUOT+2 ; (WORD) REMAINDER FOR DIVISION + 7174 6C64 QSIGN EQU REMAIN+2 ; (BYTE) SIGN OF QUOTIENT + 7175 6C65 RSIGN EQU QSIGN+1 ; (BYTE) SIGN OF REMAINDER + 7176 6C66 DIGITS EQU RSIGN+1 ; (BYTE) DIGIT COUNT FOR "PRINTN" + 7177 6C67 OLDLEN EQU DIGITS+1 ; (BYTE) OLD LINE LENGTH + 7178 6C68 OLDEND EQU OLDLEN+1 ; (BYTE) OLD LAST CHAR IN [LBUFF] + 7179 6C69 SPSTAT EQU OLDEND+1 ; (BYTE) SPLIT SCREEN STATUS FLAG + 7180 6C6A LFROM EQU SPSTAT+1 ; (WORD) "FROM" LINE ADDRESS + 7181 6C6C LTO EQU LFROM+2 ; (WORD) "TO" LINE ADDRESS + 7182 6C6E PRLEN EQU LTO+2 ; (BYTE) SCRIPT LINE LENGTH + 7183 6C6F GPOSIT EQU PRLEN+1 ; (BYTE) DEFAULT SAVE POSITION + 7184 6C70 GDRIVE EQU GPOSIT+1 ; (BYTE) DEFAULT SAVE DRIVE + 7185 6C71 TPOSIT EQU GDRIVE+1 ; (BYTE) TEMP SAVE POSITION + 7186 6C72 TDRIVE EQU TPOSIT+1 ; (BYTE) TEMP SAVE DRIVE + 7187 6C73 TSLOT EQU TDRIVE+1 ; (BYTE) TEMP SAVE SLOT + 7188 6C74 DRIVE EQU TSLOT+1 ; (BYTE) CURRENT DRIVE + 7189 6C75 SIDEFLG EQU DRIVE+1 ; (BYTE) which disk side are we on + 7190 6C76 SRHOLD EQU SIDEFLG+1 ; (WORD) <>0 if doing sequential random + 7191 6C78 SCRIPTF EQU SRHOLD+2 ; (BYTE) DIROUT FLAG FOR PRINTER OUTPUT + 7192 6C79 SCRIPTFLG EQU SCRIPTF+1 ; (BYTE) Does window allow scripting? + 7193 6C7A OLDZSP EQU SCRIPTFLG+1 ; (WORD) + 7194 6C7C CURSFLG EQU OLDZSP+2 ; (BYTE) 1==New cursor X for DLINE + Wed Jun 7 1989 12:04 Page 108 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 7195 6C7D DBLK EQU CURSFLG+1 ; (WORD) + 7196 6C7F RDTBL1 EQU DBLK+2 ; (WORD) READ TABLE 1 (Game Relative) + 7197 6C81 RDTBL2 EQU RDTBL1+2 ; (WORD) READ TABLE 2 + 7198 6C83 NENTS EQU RDTBL2+2 ; (WORD) # ENTRIES IN VOCAB TABLE + 7199 6C85 DIRITM EQU NENTS+2 ; (WORD) OFFSET IN OUTPUT TBL (DIRTBL) + 7200 6C87 DIRCNT EQU DIRITM+2 ; (WORD) COUNT OF CHARS IN TBL (DIRTBL) + 7201 6C89 SVTCHAR EQU DIRCNT+2 ; (WORD) Old TCHARS table address + 7202 6C8B VOCMPC EQU SVTCHAR+2 ; (3 BYTES) Save for vocabulary MPC + 7203 6C8E VCESVE EQU VOCMPC+3 ; (3 BYTES) Save for VOCEND + 7204 6C91 VWLSVE EQU VCESVE+3 ; (3 BYTES) Save for VOCLEN + 7205 6C94 DIDVTBL EQU VWLSVE+3 ; (BYTE) <>0 if we have done default table + 7206 6C95 IN EQU DIDVTBL+1 ; (9 BYTES) INPUT BUFFER + 7207 6C9E OUT EQU IN+9 ; (9 BYTES) OUTPUT BUFFER + 7208 6CA7 CURSOR_OFF EQU OUT+9 ; (BYTE) ==1 if char cursor not to be on + 7209 6CA8 CRLF_CHECK EQU CURSOR_OFF+1 ; (BYTE) ==1 to do CRLF function check + 7210 6CA9 PTR_COUNT EQU CRLF_CHECK+1 ; (BYTE) ==0 if checking pointer movement + 7211 6CAA INFODOS_END EQU PTR_COUNT+1 ; (WORD) last segment of infodos special + 7212 0050 OLDZVLEN EQU INFODOS_END-PSVFLG+2 ; this is how much to reserve + 7213 + 7214 6C5C BLKB OLDZVLEN,0 ; and zero it out + 7215 + 7216 ; ------------------ + 7217 ; ERROR MESSAGE STRINGS + 7218 ; ------------------ + 7219 6CAC 0E E27: db E27L + 7220 6CAD 44 69 73 6B 20 db "Disk I/O Error" + 6CB2 49 2F 4F 20 45 + 6CB7 72 72 6F 72 + 7221 000E E27L EQU $-E27-1 + 7222 6CBB 14 E2B: db E2BL + 7223 6CBC 44 69 73 6B 20 db "Disk write protected" + 6CC1 77 72 69 74 65 + 6CC6 20 70 72 6F 74 + 6CCB 65 63 74 65 64 + 7224 0014 E2BL EQU $-E2B-1 + 7225 6CD0 0C E40: db E40L + 7226 6CD1 42 61 64 20 46 db "Bad Filename" + 6CD6 69 6C 65 6E 61 + 6CDB 6D 65 + 7227 000C E40L EQU $-E40-1 + 7228 6CDD 0E E44: db E44L + 7229 6CDE 50 61 74 68 20 db "Path not found" + 6CE3 6E 6F 74 20 66 + 6CE8 6F 75 6E 64 + 7230 000E E44L: EQU $-E44-1 + 7231 6CEC 10 E45: db E45L + 7232 6CED 56 6F 6C 75 6D db "Volume not found" + 6CF2 65 20 6E 6F 74 + 6CF7 20 66 6F 75 6E + 6CFC 64 + 7233 0010 E45L EQU $-E45-1 + 7234 6CFD 0E E46: db E46L + 7235 6CFE 46 69 6C 65 20 db "File Not Found" + 6D03 4E 6F 74 20 46 + 6D08 6F 75 6E 64 + 7236 000E E46L EQU $-E46-1 + 7237 6D0C 09 E48: db E48L + 7238 6D0D 44 69 73 6B 20 db "Disk Full" + 6D12 46 75 6C 6C + 7239 0009 E48L EQU $-E48-1 + 7240 6D16 21 E49: db E49L + 7241 6D17 4C 61 6E 65 44 db "LaneDOS limit: 12 files/directory" + 6D1C 4F 53 20 6C 69 + 6D21 6D 69 74 3A 20 + 6D26 31 32 20 66 69 + 6D2B 6C 65 73 2F 64 + 6D30 69 72 65 63 74 + 6D35 6F 72 79 + 7242 0021 E49L EQU $-E49-1 + 7243 6D38 26 E4E: db E4EL + 7244 6D39 4C 61 6E 65 44 db "LaneDOS limit: No writes to TREE files" + 6D3E 4F 53 20 6C 69 + 6D43 6D 69 74 3A 20 + 6D48 4E 6F 20 77 72 + 6D4D 69 74 65 73 20 + Wed Jun 7 1989 12:04 Page 109 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6D52 74 6F 20 54 52 + 6D57 45 45 20 66 69 + 6D5C 6C 65 73 + 7245 0026 E4EL EQU $-E4E-1 + 7246 6D5F 0E E4C: db E4CL + 7247 6D60 55 6E 65 78 70 db "Unexpected EOF" + 6D65 65 63 74 65 64 + 6D6A 20 45 4F 46 + 7248 000E E4CL EQU $-E4C-1 + 7249 + 7250 6D6E 27 ELIST: db $27 + 7251 6D6F AC6C dw E27 + 7252 6D71 2B db $2B + 7253 6D72 BB6C dw E2B + 7254 6D74 40 db $40 + 7255 6D75 D06C dw E40 + 7256 6D77 44 db $44 + 7257 6D78 DD6C dw E44 + 7258 6D7A 45 db $45 + 7259 6D7B EC6C dw E45 + 7260 6D7D 46 db $46 + 7261 6D7E FD6C dw E46 + 7262 6D80 48 db $48 + 7263 6D81 0C6D dw E48 + 7264 6D83 49 db $49 + 7265 6D84 166D dw E49 + 7266 6D86 4C db $4C + 7267 6D87 5F6D dw E4C + 7268 6D89 4E db $4E + 7269 6D8A 386D dw E4E + 7270 001B ELISTL EQU $-ELIST-3 ; mark last error code + 7271 + 7272 6D8C END + 7273 + 7274 6D8C INCLUDE WINDOWS.ASM + 7275 + 7276 6D8C STTL "--- WINDOW OPERATIONS ---" + 7277 PAGE + Wed Jun 7 1989 12:04 Page 110 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7278 ; + 7279 ; these are the data structures for all 8 WINDOW. They are identical and + 7280 ; are just seperated cuz I use the addresses in the table that follows. + 7281 ; All numbers are inclusive, absolute, and zero-based. + 7282 ; + 7283 0000 WINDSTRUCT EQU 0 + 7284 0000 WINTOP EQU WINDSTRUCT ; first line of the window + 7285 0001 WINLEFT EQU WINTOP+1 ; left edge of the window + 7286 0002 WINHGHT EQU WINLEFT+1 ; height of the window + 7287 0003 WINWID EQU WINHGHT+1 ; width of the window, in pixels + 7288 0004 WINY EQU WINWID+1 ; y pos of cursor (pos, not relative) + 7289 0005 WINX EQU WINY+1 ; x pos of cursor (remember, ABSOLUTE) + 7290 0006 WINLM EQU WINX+1 ; left margin + 7291 0007 WINRM EQU WINLM+1 ; right margin + 7292 0008 WINCRF EQU WINRM+1 ; (WORD) function + 7293 000A WINCRC EQU WINCRF+2 ; (WORD) counter + 7294 000C WINHIGHL EQU WINCRC+2 ; highlight mode + 7295 000D WINFORE EQU WINHIGHL+1 ; foreground color (0=black-7=white) + 7296 000E WINBGND EQU WINFORE+1 ; background color (0=black-7=white) + 7297 000F WINFONT EQU WINBGND+1 ; window font (0=normal/4=monospaced) + 7298 0010 WINFSIZE EQU WINFONT+1 ; (WORD) font Height/Width + 7299 0012 WINATR EQU WINFSIZE+2 ; Window Attributes + 7300 0013 WINLCNT EQU WINATR+1 ; current number of lines + 7301 ; + 7302 ; these are my interesting things + 7303 ; + 7304 0014 WINXSZ EQU WINLCNT+1 ; width of window, in pixels, using margin + 7305 0015 WINLLEN EQU WINXSZ+1 ; length of current line + 7306 0017 WINLINES EQU WINLLEN+2 ; max # of lines for window + 7307 + 7308 6D8C WINDOW0: + 7309 6D8C 00 DB 0 ; WINTOP - first line of the window + 7310 6D8D 00 DB 0 ; WINLEFT - left edge of the window + 7311 6D8E C0 DB MAXHEIGHT ; WINHGHT - height of window + 7312 6D8F 8C DB MAXWIDTH ; WINWID - width of window + 7313 6D90 00 DB 0 ; WINY - y pos of cursor (pos, not relative) + 7314 6D91 00 DB 0 ; WINX - x pos of cursor (remember, ABSOLUTE) + 7315 6D92 00 DB 0 ; WINLM - left margin + 7316 6D93 00 DB 0 ; WINRM - right margin + 7317 6D94 0000 DW 0 ; WINCRF - function + 7318 6D96 0000 DW 0 ; WINCRC - counter + 7319 6D98 00 DB 0 ; WINHIGHL - Highlights + 7320 6D99 0F DB $f ; WINFORE - foreground color default of white + 7321 6D9A 00 DB 0 ; WINBGND - background color + 7322 6D9B 00 DB 0 ; WINFONT - window font (0=normal/1=alternate) + 7323 6D9C 02 09 DB 2,FONT_H ; WINFSIZE - Width/Height + 7324 6D9E 0F DB $0f ; WINATR - all attributes on for window 0 + 7325 6D9F 00 DB 0 ; WINLCNT - current number of lines + 7326 6DA0 8C DB MAXWIDTH ; WINXSZ - width of window, in pixels, using margin + 7327 6DA1 00 00 DB 0,0 ; WINLLEN - length of current line + 7328 6DA3 14 DB (MAXHEIGHT/FONT_H)-1 ; WINLINES - max # of lines for window + 7329 ; + 7330 ; same start as window 0, but with 0 length + 7331 ; + 7332 6DA4 WINDOW1: + 7333 6DA4 00 00 00 8C 00 DB 0,0,0,MAXWIDTH,0,0,0,0,0,0,0,0,0 + 6DA9 00 00 00 00 00 + 6DAE 00 00 00 + 7334 6DB1 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,MAXWIDTH,0,0,0 + 6DB6 08 00 8C 00 00 + 6DBB 00 + 7335 ; + 7336 ; the rest have no width/height/attributes (except buffering) + 7337 ; + 7338 6DBC WINDOW2: + 7339 6DBC 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6DC1 00 00 00 00 00 + 6DC6 00 00 00 + 7340 6DC9 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6DCE 08 00 00 00 00 + 6DD3 00 + 7341 6DD4 WINDOW3: + 7342 6DD4 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6DD9 00 00 00 00 00 + 6DDE 00 00 00 + Wed Jun 7 1989 12:04 Page 111 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7343 6DE1 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6DE6 08 00 00 00 00 + 6DEB 00 + 7344 6DEC WINDOW4: + 7345 6DEC 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6DF1 00 00 00 00 00 + 6DF6 00 00 00 + 7346 6DF9 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6DFE 08 00 00 00 00 + 6E03 00 + 7347 6E04 WINDOW5: + 7348 6E04 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6E09 00 00 00 00 00 + 6E0E 00 00 00 + 7349 6E11 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6E16 08 00 00 00 00 + 6E1B 00 + 7350 6E1C WINDOW6: + 7351 6E1C 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6E21 00 00 00 00 00 + 6E26 00 00 00 + 7352 6E29 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6E2E 08 00 00 00 00 + 6E33 00 + 7353 6E34 WINDOW7: + 7354 6E34 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6E39 00 00 00 00 00 + 6E3E 00 00 00 + 7355 6E41 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6E46 08 00 00 00 00 + 6E4B 00 + 7356 + 7357 6E4C WINTABLE: + 7358 6E4C 8C6D A46D BC6D DW WINDOW0,WINDOW1,WINDOW2,WINDOW3 + 6E52 D46D + 7359 6E54 EC6D 046E 1C6E DW WINDOW4,WINDOW5,WINDOW6,WINDOW7 + 6E5A 346E + 7360 PAGE + Wed Jun 7 1989 12:04 Page 112 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7361 + 7362 ; ------ + 7363 ; SCREEN + 7364 ; ------ + 7365 ; Move to the screen specified, by updating CURWIN and the cursor + 7366 ; X,Y pos (SCRX,SCRY). Also put address of that window's structure + 7367 ; in WINDOW. Save a bunch of the old stuff in old window's structure then + 7368 ; update the same bunch with the new window's stuff. + 7369 ; + 7370 ; ARG1 - new screen id: 0-7 + 7371 ; + 7372 6E5C ZSCRN: + 7373 6E5C 20 B5 55 jsr CLRBUF ; EMPTY OUTPUT BUFFER BEFORE MOVING + 7374 ; + 7375 ; now, save a few things from the common variables + 7376 ; + 7377 6E5F A0 15 ldy #WINLLEN ; current line length + 7378 6E61 A5 A7 lda LENGTH+LO ; get current line length + 7379 6E63 91 05 sta (WINDOW),Y ; save for later referencing + 7380 6E65 C8 iny ; point to msb + 7381 6E66 A5 A8 lda LENGTH+HI ; get MSB + 7382 6E68 91 05 sta (WINDOW),Y ; saved + 7383 6E6A 20 9F 4D jsr SAVE_CURSOR ; save the x,y pos of cursor + 7384 6E6D A5 BB lda INVFLG ; get inverse flag + 7385 6E6F F0 04 beq ZSCA1 ; not set + 7386 6E71 A9 01 lda #1 ; set 1 bit + 7387 6E73 D0 06 bne ZSCA2 ; set in window + 7388 6E75 ZSCA1: + 7389 6E75 A5 BA lda UNDFLG ; how about underlining + 7390 6E77 F0 02 beq ZSCA2 ; nope + 7391 6E79 A9 04 lda #4 ; 4 == underlining + 7392 6E7B ZSCA2: + 7393 6E7B A0 0C ldy #WINHIGHL ; set new highlight + 7394 6E7D 91 05 sta (WINDOW),Y ; save current attributes + 7395 ; + 7396 ; now it is time to update for new screen + 7397 ; + 7398 6E7F A5 63 lda ARG1+LO ; get which window + 7399 6E81 85 A6 sta CURWIN ; save window number + 7400 6E83 0A asl A ; shift to make word indes + 7401 6E84 AA tax ; swap to indexing reg + 7402 6E85 BD 4C 6E lda WINTABLE,X ; get the address of the new WINDOW + 7403 6E88 85 05 sta WINDOW+LO ; lo part comes first + 7404 6E8A BD 4D 6E lda WINTABLE+1,X ; so go get hi part + 7405 6E8D 85 06 sta WINDOW+HI ; save the hi part of the address + 7406 + 7407 6E8F 20 B1 4D jsr GET_CURSOR ; restore the cursor pos + 7408 + 7409 6E92 A0 14 ldy #WINXSZ ; get line length + 7410 6E94 B1 05 lda (WINDOW),Y ; update zero page variable + 7411 6E96 85 A2 sta XSIZE+LO ; this is for quicky comparing + 7412 6E98 A9 00 lda #0 ; clear MSB + 7413 6E9A 85 A3 sta XSIZE+HI + 7414 6E9C 06 A2 asl XSIZE+LO ; *2 + 7415 6E9E 26 A3 rol XSIZE+HI + 7416 6EA0 06 A2 asl XSIZE+LO ; *4 + 7417 6EA2 26 A3 rol XSIZE+HI + 7418 6EA4 A0 15 ldy #WINLLEN ; get current line length + 7419 6EA6 B1 05 lda (WINDOW),Y ; from before + 7420 6EA8 85 A7 sta LENGTH+LO ; save for later checking + 7421 6EAA C8 iny + 7422 6EAB B1 05 lda (WINDOW),Y + 7423 6EAD 85 A8 sta LENGTH+HI + 7424 6EAF A0 13 ldy #WINLCNT ; how many lines already out there + 7425 6EB1 B1 05 lda (WINDOW),Y ; has been already saved + 7426 6EB3 85 AB sta LINCNT ; and save 'ere too + 7427 6EB5 A0 17 ldy #WINLINES ; how many lines in this + 7428 6EB7 B1 05 lda (WINDOW),Y ; window, anyway? + 7429 6EB9 85 03 sta MAXLINES ; show for everyone to see + 7430 6EBB A0 01 ldy #WINLEFT ; show left margin + 7431 6EBD B1 05 lda (WINDOW),Y ; get left edge + 7432 6EBF A0 06 ldy #WINLM ; left margin + 7433 6EC1 18 clc ; adding + 7434 6EC2 71 05 adc (WINDOW),Y ; to find new left margin + 7435 6EC4 85 04 sta LEFTMRG ; set up left margin for ease of use + Wed Jun 7 1989 12:04 Page 113 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7436 6EC6 A0 00 ldy #WINTOP ; get top of window + 7437 6EC8 B1 05 lda (WINDOW),Y ; got it + 7438 6ECA 18 clc ; adding + 7439 6ECB A0 02 ldy #WINHGHT ; add height + 7440 6ECD 71 05 adc (WINDOW),Y ; did it + 7441 6ECF 85 02 sta SCRBTM ; this is first line outside window + 7442 6ED1 A0 0C ldy #WINHIGHL ; get highlighting modes + 7443 6ED3 B1 05 lda (WINDOW),Y ; first for inverse video + 7444 6ED5 29 01 and #1 ; check for inverse video + 7445 6ED7 F0 02 beq SCRINV ; nope + 7446 6ED9 A9 80 lda #$80 ; means inverse video + 7447 6EDB SCRINV: + 7448 6EDB 85 BB sta INVFLG ; there it be + 7449 6EDD B1 05 lda (WINDOW),Y ; point to underline flag + 7450 6EDF 29 04 and #4 ; check for underlining + 7451 6EE1 F0 02 beq SCRUND ; nope + 7452 6EE3 A9 80 lda #$80 ; means underlining + 7453 6EE5 SCRUND: + 7454 6EE5 85 BA sta UNDFLG ; save for everyone + 7455 + 7456 6EE7 A0 12 ldy #WINATR ; get the current attributes + 7457 6EE9 B1 05 lda (WINDOW),Y ; gottem + 7458 6EEB 20 6D 70 jsr SET_ATTRIBUTES ; set the flags, thank you + 7459 6EEE A0 0F ldy #WINFONT ; get the font + 7460 6EF0 B1 05 lda (WINDOW),Y ; thank you + 7461 6EF2 F0 02 beq SCRFNT0 ; is it font zero? + 7462 6EF4 A9 0C lda #MONOFONT_W ; must be mono font, set width + 7463 6EF6 SCRFNT0: + 7464 6EF6 85 C1 sta FONTFLG ; mark normal font + 7465 6EF8 ZSCREX: + 7466 6EF8 60 rts + 7467 ;-------------- + 7468 ; ZWINPOS + 7469 ;-------------- + 7470 ; + 7471 ; change the window ARG1's top left corner to the new position + 7472 ; + 7473 ; ARG1 - window id from 0-7 + 7474 ; ARG2 - new top y pos + 7475 ; ARG3 - new top x pos + 7476 ; + 7477 6EF9 ZWINPOS: + 7478 6EF9 C6 65 dec ARG2+LO ; make pos be zero based + 7479 6EFB C6 67 dec ARG3+LO ; now they are! + 7480 ; + 7481 ; if moving current window, save current cursor pos + 7482 ; + 7483 6EFD ZWPOS0: + 7484 6EFD 20 9F 4D jsr SAVE_CURSOR ; saving + 7485 ; + 7486 ; let's set up [J] to point to window we are talking about + 7487 ; + 7488 6F00 ZWPOS1: + 7489 6F00 A5 63 lda ARG1+LO ; get window ID + 7490 6F02 20 7F 57 jsr SETWJ ; get J to point to it + 7491 + 7492 6F05 A5 65 lda ARG2+LO ; first, check the top + 7493 6F07 C9 C0 cmp #MAXHEIGHT ; < max height? + 7494 6F09 90 04 bcc CKWA1 ; fine + 7495 6F0B A9 00 lda #0 ; make it zero then + 7496 6F0D 85 65 sta ARG2+LO ; it is now + 7497 6F0F CKWA1: + 7498 6F0F A5 67 lda ARG3+LO ; now check left edge + 7499 6F11 C9 8C cmp #MAXWIDTH ; howzit compare + 7500 6F13 90 04 bcc CKWA2 ; just fine + 7501 6F15 A9 00 lda #0 ; this too + 7502 6F17 85 67 sta ARG3+LO ; it is now + 7503 6F19 CKWA2: + 7504 ; + 7505 ; make the cursor pos be relative, so we can change back to + 7506 ; absolute using new window pos + 7507 ; + 7508 6F19 A0 04 ldy #WINY ; let's do y pos first + 7509 6F1B B1 7A lda (J),Y ; get the old y pos + 7510 6F1D A0 00 ldy #WINTOP ; and subtract the top to make + Wed Jun 7 1989 12:04 Page 114 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7511 6F1F 38 sec ; (getting ready) + 7512 6F20 F1 7A sbc (J),Y ; the pos relative + 7513 6F22 18 clc ; now add in new top + 7514 6F23 65 65 adc ARG2+LO ; this will be new top + 7515 6F25 A0 04 ldy #WINY ; get y offset again + 7516 6F27 91 7A sta (J),Y ; and save new absolute y pos + 7517 6F29 A0 05 ldy #WINX ; now we be talking about x pos + 7518 6F2B B1 7A lda (J),Y ; get old x pos + 7519 6F2D 38 sec ; getting ready for sub + 7520 6F2E A0 01 ldy #WINLEFT ; get rid of left ness + 7521 6F30 F1 7A sbc (J),Y ; now it's relative + 7522 6F32 18 clc ; get ready to add in new left ness + 7523 6F33 65 67 adc ARG3+LO ; done + 7524 6F35 A0 05 ldy #WINX ; get x offset again + 7525 6F37 91 7A sta (J),Y ; save in structure + 7526 ; + 7527 ; now we can change the top and left of the window + 7528 ; + 7529 6F39 A5 65 lda ARG2+LO ; this is top of window + 7530 6F3B A0 00 ldy #WINTOP ; TOP offset + 7531 6F3D 91 7A sta (J),Y ; save the new top + 7532 6F3F A5 67 lda ARG3+LO ; here is the left edge + 7533 6F41 A0 01 ldy #WINLEFT ; offset into struct + 7534 6F43 91 7A sta (J),Y ; saved ! + 7535 ; + 7536 ; we might have moved current window so update screen cursor and left margin + 7537 ; + 7538 6F45 20 B1 4D jsr GET_CURSOR ; restore cursor + 7539 6F48 A0 01 ldy #WINLEFT ; get left edge + 7540 6F4A B1 05 lda (WINDOW),Y ; okay + 7541 6F4C A0 06 ldy #WINLM ; add in left margin + 7542 6F4E 18 clc ; adding + 7543 6F4F 71 05 adc (WINDOW),Y ; to find new left edge + 7544 6F51 85 04 sta LEFTMRG ; store for ease of use + 7545 6F53 A0 14 ldy #WINXSZ ; get xsize + 7546 6F55 B1 7A lda (J),Y ; okay + 7547 6F57 85 A2 sta XSIZE+LO ; this is for quicky comparing + 7548 6F59 A9 00 lda #0 ; clear MSB + 7549 6F5B 85 A3 sta XSIZE+HI + 7550 6F5D 06 A2 asl XSIZE+LO ; *2 + 7551 6F5F 26 A3 rol XSIZE+HI + 7552 6F61 06 A2 asl XSIZE+LO ; *4 + 7553 6F63 26 A3 rol XSIZE+HI + 7554 6F65 ZWPOSX: + 7555 6F65 60 rts + 7556 ;------------ + 7557 ; ZWINSIZE + 7558 ;------------ + 7559 ; + 7560 ; Change the size of window ARG1. If cursor is outside of window, + 7561 ; move to it. + 7562 ; + 7563 ; ARG1 - window ID + 7564 ; ARG2 - height + 7565 ; ARG3 - width + 7566 ; + 7567 ; Uses [J]. + 7568 ; + 7569 6F66 ZWINSIZE: + 7570 ; + 7571 ; first put SCRCX,CY into window structure, just in case + 7572 ; + 7573 6F66 20 9F 4D jsr SAVE_CURSOR ; saved + 7574 ; + 7575 ; now do everything + 7576 ; + 7577 6F69 A5 63 lda ARG1+LO ; get the window ID + 7578 6F6B 20 7F 57 jsr SETWJ ; and get window pointer + 7579 + 7580 6F6E A5 65 lda ARG2+LO ; first, check the top + 7581 6F70 C9 C0 cmp #MAXHEIGHT ; < max height? + 7582 6F72 90 04 bcc CKWA11 ; fine + 7583 6F74 A9 C0 lda #MAXHEIGHT ; make better + 7584 6F76 85 65 sta ARG2+LO ; it is now + 7585 6F78 CKWA11: + Wed Jun 7 1989 12:04 Page 115 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7586 6F78 A5 67 lda ARG3+LO ; now check left edge + 7587 6F7A C9 8C cmp #MAXWIDTH ; howzit compare + 7588 6F7C 90 04 bcc CKWA21 ; just fine + 7589 6F7E A9 8C lda #MAXWIDTH ; make it the max + 7590 6F80 85 67 sta ARG3+LO ; it is now + 7591 6F82 CKWA21: + 7592 6F82 A5 65 lda ARG2+LO ; get new height + 7593 6F84 A0 02 ldy #WINHGHT ; offset + 7594 6F86 91 7A sta (J),Y ; save new height + 7595 6F88 A5 67 lda ARG3+LO ; get width + 7596 6F8A A0 03 ldy #WINWID ; store width + 7597 6F8C 91 7A sta (J),Y ; okay + 7598 ; + 7599 ; now we need to figger out new XSIZE, MAXLINES + 7600 ; + 7601 6F8E A0 03 ldy #WINWID ; store width + 7602 6F90 B1 7A lda (J),Y ; get width + 7603 6F92 38 sec ; have width, subtract margins + 7604 6F93 A0 07 ldy #WINRM ; first right margin + 7605 6F95 F1 7A sbc (J),Y ; subtracted right margin + 7606 6F97 A0 06 ldy #WINLM ; and now for the left margin + 7607 6F99 F1 7A sbc (J),Y ; now we have new XSIZE + 7608 6F9B A0 14 ldy #WINXSZ ; get offset + 7609 6F9D 91 7A sta (J),Y ; save for later ref + 7610 6F9F A5 65 lda ARG2+LO ; get new height + 7611 6FA1 A2 FF ldx #$FF ; this is the counter + 7612 6FA3 38 sec ; get ready for subs + 7613 6FA4 ZWSZ1: + 7614 6FA4 E8 inx ; count this line + 7615 6FA5 E9 09 sbc #FONT_H ; subtract off font height + 7616 6FA7 B0 FB bcs ZWSZ1 ; still some lines + 7617 6FA9 CA dex ; to keep the input line on screen + 7618 6FAA 8A txa ; get line count for storage + 7619 6FAB A0 17 ldy #WINLINES ; this is how many lines are allowed + 7620 6FAD 91 7A sta (J),Y ; saved + 7621 ; + 7622 ; check to make sure the cursor is still in the window + 7623 ; + 7624 6FAF A0 06 ldy #WINLM ; get left margin + 7625 6FB1 18 clc ; for adding + 7626 6FB2 71 7A adc (J),Y ; for figgering out right edge + 7627 6FB4 A0 01 ldy #WINLEFT ; add in left edge + 7628 6FB6 71 7A adc (J),Y ; get right column by adding in left one + 7629 6FB8 A0 05 ldy #WINX ; check X pos + 7630 6FBA D1 7A cmp (J),Y ; see if X is still inside? + 7631 6FBC F0 13 beq ZWSZ2 ; must move to top left + 7632 6FBE 90 11 bcc ZWSZ2 ; ditto if X >= margin + 7633 6FC0 A0 00 ldy #WINTOP ; get top to figger last line + 7634 6FC2 B1 7A lda (J),Y ; from the structure + 7635 6FC4 A0 02 ldy #WINHGHT ; and add in the height + 7636 6FC6 18 clc ; getting ready for add + 7637 6FC7 71 7A adc (J),Y ; to find first line outside of range + 7638 6FC9 A0 04 ldy #WINY ; now check y + 7639 6FCB D1 7A cmp (J),Y ; now check y then + 7640 6FCD F0 02 beq ZWSZ2 ; outside, move to top left + 7641 6FCF B0 15 bcs ZWSZ3 ; inside so quit + 7642 ; + 7643 ; move the cursor to top left if outside of resized window + 7644 ; + 7645 6FD1 ZWSZ2: + 7646 6FD1 A0 00 ldy #WINTOP ; top line is here + 7647 6FD3 B1 7A lda (J),Y ; so get me it + 7648 6FD5 A0 04 ldy #WINY ; now we be doing y + 7649 6FD7 91 7A sta (J),Y ; change Y + 7650 6FD9 A0 01 ldy #WINLEFT ; move X to left margin + 7651 6FDB B1 7A lda (J),Y ; first get left edge + 7652 6FDD A0 06 ldy #WINLM ; and add in left margin + 7653 6FDF 18 clc ; (adding) + 7654 6FE0 71 7A adc (J),Y ; to get left spot of cursor + 7655 6FE2 A0 05 ldy #WINX ; this is x offset + 7656 6FE4 91 7A sta (J),Y ; so move X there + 7657 ; + 7658 ; now check to see if we mucked with current window + 7659 ; + 7660 6FE6 ZWSZ3: + Wed Jun 7 1989 12:04 Page 116 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7661 6FE6 A5 64 lda ARG1+HI ; this is the id + 7662 6FE8 30 04 bmi ZWSZ4 ; must be current window + 7663 6FEA C5 A6 cmp CURWIN ; is it current window? + 7664 6FEC D0 1B bne ZWSZX ; nope, so done + 7665 6FEE ZWSZ4: + 7666 6FEE A0 17 ldy #WINLINES ; get how many lines + 7667 6FF0 B1 7A lda (J),Y ; get number of lines + 7668 6FF2 85 03 sta MAXLINES ; set global + 7669 6FF4 A0 14 ldy #WINXSZ ; get new XSIZE too + 7670 6FF6 B1 7A lda (J),Y ; get it + 7671 6FF8 85 A2 sta XSIZE+LO ; this is for quicky comparing + 7672 6FFA A9 00 lda #0 ; clear MSB + 7673 6FFC 85 A3 sta XSIZE+HI + 7674 6FFE 06 A2 asl XSIZE+LO ; *2 + 7675 7000 26 A3 rol XSIZE+HI + 7676 7002 06 A2 asl XSIZE+LO ; *4 + 7677 7004 26 A3 rol XSIZE+HI + 7678 7006 20 B1 4D jsr GET_CURSOR ; fix the cursor pos + 7679 7009 ZWSZX: + 7680 7009 60 rts + 7681 ; + 7682 ;CHECK_WIN_ARGS + 7683 ; check args to make sure they be okay + 7684 ; + 7685 ; ARG2 = top/height + 7686 ; ARG3 = right/width + 7687 ; + 7688 700A CHECK_WIN_ARGS: + 7689 700A 60 rts + 7690 + 7691 ; ------ + 7692 ; HLIGHT + 7693 ; ------ + 7694 + 7695 700B ZLIGHT: + 7696 700B A5 63 lda ARG1+LO ; get argument + 7697 700D C9 10 cmp #$10 ; must be <= 8 + 7698 700F B0 05 bcs ZLIEX ; nope it aint + 7699 7011 09 80 ora #$80 ; turn on hi bit + 7700 7013 20 06 53 jsr COUT ; send it out then + 7701 7016 ZLIEX: + 7702 7016 60 rts ; done + 7703 ; + 7704 ; actually set the highlight flags according to [A] + 7705 ; + 7706 7017 HLIGHT: + 7707 ; + 7708 ; TURN OFF ALL HIGHLIGHTS + 7709 ; + 7710 7017 29 7F and #$7F ; turn off high bit + 7711 7019 D0 05 bne ZL1 ; nope, must be something + 7712 701B 85 BA sta UNDFLG ; and turn of underlining flag + 7713 701D 85 BB sta INVFLG ; and inverse + 7714 701F 60 rts ; all done + 7715 7020 ZL1: + 7716 7020 C9 04 cmp #4 ; underlining + 7717 7022 D0 05 bne ZL_REV ; maybe its INVERSE? + 7718 + 7719 7024 A9 80 lda #$80 ; turn on UNDFLG + 7720 7026 85 BA sta UNDFLG ; with an FF + 7721 7028 60 rts ; done + 7722 7029 ZL_REV: + 7723 7029 C9 01 cmp #1 ; INVERSE? + 7724 702B D0 05 bne ZL_MONO ; maybe monospaced then + 7725 702D A9 80 lda #$80 ; must be inverse video + 7726 702F 85 BB sta INVFLG ; and put it in invflg + 7727 7031 60 rts + 7728 7032 ZL_MONO: + 7729 7032 60 rts ; fuck it for now! + 7730 ; + 7731 ; ZWINATTER - change the scrolling/buffering/scripting/wrapping attributes + 7732 ; of the window. + 7733 ; + 7734 ; ARG1 - window id + 7735 ; ARG2 - interesting bits + Wed Jun 7 1989 12:04 Page 117 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7736 ; | buffering | scripting | scrolling | wrapping | + 7737 ; ARG3 - operation - 0 MOVE + 7738 ; 1 SET + 7739 ; 2 CLEAR + 7740 ; 3 COMPLEMENT + 7741 ; + 7742 7033 ZWINATTR: + 7743 7033 A5 62 lda NARGS ; see how many args + 7744 7035 C9 03 cmp #3 ; check for operation args + 7745 7037 F0 04 beq ZWAT1 ; yes, already there + 7746 7039 A9 00 lda #0 ; zero means MOVE + 7747 703B 85 67 sta ARG3+LO ; so show it as default + 7748 703D ZWAT1: + 7749 703D A5 63 lda ARG1+LO ; get window ID + 7750 703F 20 7F 57 jsr SETWJ ; put window address into [J] + 7751 + 7752 7042 A0 12 ldy #WINATR ; get attribute offset + 7753 7044 B1 7A lda (J),Y ; get current attribute + 7754 7046 18 clc ; so we can just branch + 7755 + 7756 7047 C6 67 dec ARG3+LO ; decrement to find out what to do + 7757 7049 30 0A bmi ZWMOVE ; do a move + 7758 704B F0 0C beq ZWSET ; do a set + 7759 704D C6 67 dec ARG3+LO ; check once more + 7760 704F F0 0C beq ZWCLEAR ; clear set ones + 7761 ; + 7762 ; this is for the COMPLEMENT operations + 7763 ; + 7764 7051 45 65 eor ARG2+LO ; complement bits + 7765 7053 90 0E bcc ZWAT2 ; done + 7766 7055 ZWMOVE: + 7767 ; + 7768 ; move into the flag word + 7769 ; + 7770 7055 A5 65 lda ARG2+LO ; get new flags + 7771 7057 90 0A bcc ZWAT2 ; done + 7772 7059 ZWSET: + 7773 ; + 7774 ; set turned on ones + 7775 ; + 7776 7059 05 65 ora ARG2+LO ; set'em up + 7777 705B 90 06 bcc ZWAT2 ; done + 7778 705D ZWCLEAR: + 7779 ; + 7780 ; clear just the ones that are on + 7781 ; + 7782 705D A5 65 lda ARG2+LO ; get argument + 7783 705F 49 FF eor #$FF ; turn on all the off ones + 7784 7061 31 7A and (J),Y ; keep all the other ones + 7785 7063 ZWAT2: + 7786 7063 91 7A sta (J),Y ; and save it back + 7787 ; + 7788 ; now, if current window, set necessary flags + 7789 ; + 7790 7065 A6 63 ldx ARG1+LO ; get window ID + 7791 7067 30 04 bmi SET_ATTRIBUTES ; assume negative is current window + 7792 7069 E4 A6 cpx CURWIN ; is this the current one? + 7793 706B D0 30 bne ZWATX ; nope, so leave + 7794 706D SET_ATTRIBUTES: + 7795 ; + 7796 ; current window, so set flags accordingly + 7797 ; + 7798 706D A2 00 ldx #0 ; to turn off flag + 7799 706F A0 01 ldy #1 ; to turn on flag + 7800 7071 6A ror A ; get wrapping flag into carry + 7801 7072 90 05 bcc ZWAT3 ; clear it + 7802 7074 8C DB 71 sty WRPFLG ; set wrapping on + 7803 7077 B0 03 bcs ZWAT33 ; okay + 7804 7079 ZWAT3: + 7805 7079 8E DB 71 stx WRPFLG ; clear wrapping flag + 7806 707C ZWAT33: + 7807 707C 6A ror A ; now check thes crolling flag + 7808 707D 90 05 bcc ZWAT4 ; not set + 7809 707F 8C DC 71 sty SCRLFLG ; turn on scrolling flag + 7810 7082 B0 03 bcs ZWAT44 ; okay, next please + Wed Jun 7 1989 12:04 Page 118 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7811 7084 ZWAT4: + 7812 7084 8E DC 71 stx SCRLFLG ; turn off scrolling + 7813 7087 ZWAT44: + 7814 7087 6A ror A ; checking the scripting flag + 7815 7088 90 05 bcc ZWAT5 ; not set + 7816 708A 8C 79 6C sty SCRIPTFLG ; allow scripting? yes + 7817 708D B0 03 bcs ZWAT55 ; next flag + 7818 708F ZWAT5: + 7819 708F 8E 79 6C stx SCRIPTFLG ; allow scripting? no + 7820 7092 ZWAT55: + 7821 7092 6A ror A ; this checks the buffering flag + 7822 7093 90 05 bcc ZWAT6 ; not set + 7823 7095 8C DD 71 sty BUFFLG ; turn on buffering + 7824 7098 B0 03 bcs ZWATX ; scram + 7825 709A ZWAT6: + 7826 709A 8E DD 71 stx BUFFLG ; turn off buffering + 7827 709D ZWATX: + 7828 709D 60 rts + 7829 ; + 7830 ; ZWINGET - put the window stuff into a table + 7831 ; + 7832 ; ARG1 - Window id + 7833 ; ARG2 - offset + 7834 ; + 7835 709E ZWINGET: + 7836 709E 20 9F 4D jsr SAVE_CURSOR ; save x,y into structure + 7837 + 7838 70A1 A5 63 lda ARG1+LO ; get window ID + 7839 70A3 20 7F 57 jsr SETWJ ; set up window address + 7840 + 7841 70A6 A5 65 lda ARG2+LO ; get where to start getting + 7842 70A8 0A asl A ; make word index + 7843 70A9 AA tax ; make index + 7844 70AA BD 46 71 lda ZWGTBL+LO,X ; get lo part of address + 7845 70AD 85 7C sta K+LO ; save for jumping + 7846 70AF BD 47 71 lda ZWGTBL+HI,X ; get hi part + 7847 70B2 85 7D sta K+HI ; saved + 7848 70B4 20 BE 70 jsr ZWGVEC ; do the vectoring + 7849 70B7 86 77 stx VALUE+HI ; save hi part + 7850 70B9 85 76 sta VALUE+LO ; and the lo part + 7851 70BB 4C E1 43 jmp PUTVAL ; and return it + 7852 70BE ZWGVEC: + 7853 70BE 6C 7C 00 jmp (K) ; and goto it boys + 7854 70C1 ZWG0: + 7855 70C1 A2 00 ldx #0 ; zero out high part + 7856 70C3 A0 00 ldy #WINTOP ; get window y pos + 7857 70C5 B1 7A lda (J),Y ; got it + 7858 70C7 A8 tay ; need to inc it + 7859 70C8 C8 iny ; to make it a one-based number + 7860 70C9 98 tya ; back to a + 7861 70CA 60 rts + 7862 70CB ZWG1: + 7863 70CB A2 00 ldx #0 ; zero out high part + 7864 70CD A0 01 ldy #WINLEFT ; get window x pos + 7865 70CF B1 7A lda (J),Y ; got it + 7866 70D1 A8 tay ; need to inc it + 7867 70D2 C8 iny ; to make it a one-based number + 7868 70D3 98 tya ; back to a + 7869 70D4 60 rts + 7870 70D5 ZWG2: + 7871 70D5 A2 00 ldx #0 ; zero out high part + 7872 70D7 A0 02 ldy #WINHGHT ; get window height + 7873 70D9 B1 7A lda (J),Y ; got it + 7874 70DB 60 rts + 7875 70DC ZWG3: + 7876 70DC A2 00 ldx #0 ; zero out high part + 7877 70DE A0 03 ldy #WINWID ; window width + 7878 70E0 B1 7A lda (J),Y ; got it + 7879 70E2 60 rts + 7880 70E3 ZWG4: + 7881 70E3 20 64 57 jsr FETCHCY ; get the current Y pos + 7882 70E6 A2 00 ldx #0 ; zero out high part + 7883 70E8 60 rts + 7884 70E9 ZWG5: + 7885 70E9 20 71 57 jsr FETCHCX ; fetch the current X pos + Wed Jun 7 1989 12:04 Page 119 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7886 70EC A2 00 ldx #0 ; zero out high part + 7887 70EE 60 rts + 7888 70EF ZWG6: + 7889 70EF A2 00 ldx #0 ; zero out high part + 7890 70F1 A0 06 ldy #WINLM ; left margin + 7891 70F3 B1 7A lda (J),Y ; got it + 7892 70F5 60 rts + 7893 70F6 ZWG7: + 7894 70F6 A2 00 ldx #0 ; zero out high part + 7895 70F8 A0 07 ldy #WINRM ; right margin + 7896 70FA B1 7A lda (J),Y ; got it + 7897 70FC 60 rts + 7898 70FD ZWG8: + 7899 70FD A0 09 ldy #WINCRF+HI ; function + 7900 70FF B1 7A lda (J),Y ; got it, lo part + 7901 7101 AA tax ; save hi part + 7902 7102 88 dey ; point to lo part + 7903 7103 B1 7A lda (J),Y ; got lo part + 7904 7105 60 rts + 7905 7106 ZWG9: + 7906 7106 A0 0B ldy #WINCRC+HI ; count + 7907 7108 B1 7A lda (J),Y ; got it, hi part + 7908 710A AA tax ; save it + 7909 710B 88 dey ; now to lo part + 7910 710C B1 7A lda (J),Y ; got it + 7911 710E 60 rts + 7912 710F ZWG10: + 7913 710F A0 0C ldy #WINHIGHL ; get high light mode + 7914 7111 B1 7A lda (J),Y ; got it + 7915 7113 A2 00 ldx #0 ; zero out high part + 7916 7115 60 rts + 7917 7116 ZWG11: + 7918 7116 A0 0E ldy #WINBGND ; and background + 7919 7118 B1 7A lda (J),Y ; got it + 7920 711A A8 tay ; make index + 7921 711B B9 4C 6C lda APLCOLOR,Y ; get apl->zip color + 7922 711E AA tax ; save for return + 7923 711F A0 0D ldy #WINFORE ; get foreground + 7924 7121 B1 7A lda (J),Y ; got it + 7925 7123 A8 tay ; save it + 7926 7124 B9 4C 6C lda APLCOLOR,Y ; get apl->zip color + 7927 7127 60 rts + 7928 7128 ZWG12: + 7929 7128 A0 0F ldy #WINFONT ; now for font id + 7930 712A B1 7A lda (J),Y ; got it + 7931 712C A2 00 ldx #0 ; zero out high part + 7932 712E 60 rts + 7933 712F ZWG13: + 7934 712F A0 11 ldy #WINFSIZE+1 ; font size (width) + 7935 7131 B1 7A lda (J),Y ; got it + 7936 7133 AA tax ; save it + 7937 7134 88 dey ; font size (height) + 7938 7135 B1 7A lda (J),Y ; got it + 7939 7137 60 rts + 7940 7138 ZWG14: + 7941 7138 A2 00 ldx #0 ; zero out high part + 7942 713A A0 12 ldy #WINATR ; attributes + 7943 713C B1 7A lda (J),Y ; got it + 7944 713E 60 rts ; got them! + 7945 713F ZWG15: + 7946 713F A2 00 ldx #0 ; only 1 byte worth + 7947 7141 A0 13 ldy #WINLCNT ; offset + 7948 7143 B1 7A lda (J),Y ; get more counter + 7949 7145 60 rts + 7950 ; + 7951 ; jump table for figgering out where to start filling + 7952 ; + 7953 7146 ZWGTBL: + 7954 7146 C170 CB70 D570 DW ZWG0,ZWG1,ZWG2,ZWG3,ZWG4,ZWG5,ZWG6,ZWG7 + 714C DC70 E370 E970 + 7152 EF70 F670 + 7955 7156 FD70 0671 0F71 DW ZWG8,ZWG9,ZWG10,ZWG11,ZWG12,ZWG13,ZWG14,ZWG15 + 715C 1671 2871 2F71 + 7162 3871 3F71 + 7956 ; + Wed Jun 7 1989 12:04 Page 120 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7957 ; ZSCROLL - scroll the specified window up or down + 7958 ; + 7959 ; ARG1 - window ID + 7960 ; ARG2 - lines to scroll; <0 scrolls down + 7961 ; + 7962 7166 ZSCROLL: + 7963 7166 20 9F 4D jsr SAVE_CURSOR ; save where cursor is + 7964 + 7965 7169 A9 00 lda #0 ; don't script scroll + 7966 716B 85 AA sta SCRIPT ; fine, we won't now + 7967 + 7968 716D A5 63 lda ARG1+LO ; get which window + 7969 716F 20 7F 57 jsr SETWJ ; set up pointer + 7970 7172 C6 62 dec NARGS ; see what we have for lines + 7971 7174 D0 04 bne ZSCR1 ; a passed arg + 7972 7176 A9 01 lda #1 ; 1 line is default + 7973 7178 85 65 sta ARG2+LO ; so say so + 7974 717A ZSCR1: + 7975 717A A0 00 ldy #WINTOP ; get me window limits + 7976 717C B1 7A lda (J),Y ; first top + 7977 717E 85 0B sta CLSTOP ; save for usage + 7978 7180 C8 iny ; now left + 7979 7181 B1 7A lda (J),Y ; okay, get for this window + 7980 7183 85 0A sta CLSLEFT ; save left + 7981 7185 C8 iny ; now it's width + 7982 7186 B1 7A lda (J),Y ; got the window height + 7983 7188 85 0D sta CLSHEIGHT ; this is it + 7984 718A C8 iny ; this is height + 7985 718B B1 7A lda (J),Y ; get window's height + 7986 718D 85 0C sta CLSWIDTH ; save + 7987 718F A5 66 lda ARG2+HI ; is it negative? + 7988 7191 85 1D sta SCLDIR ; show direction of scroll + 7989 7193 10 08 bpl ZSCRL1 ; nope + 7990 7195 A6 65 ldx ARG2+LO ; get how many lines + 7991 7197 49 FF eor #$FF ; make pos + 7992 7199 AA tax ; put in X for inc + 7993 719A E8 inx ; and make right + 7994 719B D0 02 bne ZSCRLEX ; done + 7995 719D ZSCRL1: + 7996 719D A6 65 ldx ARG2+LO ; get how many lines + 7997 719F ZSCRLEX: + 7998 719F 86 18 stx SCLLINES ; save for routine + 7999 71A1 20 08 60 jsr DO_SCROLL ; and do the scroll + 8000 71A4 ZSCRLEX1: + 8001 71A4 A9 01 lda #1 ; allow scripting + 8002 71A6 85 AA sta SCRIPT ; we do + 8003 71A8 4C B1 4D jmp GET_CURSOR ; restore the cursor, thank you + 8004 ; + 8005 ; ZWINPUT - put some information into window structure. Just CRF/CRC + 8006 ; is legit now. + 8007 ; + 8008 ; ARG1 - window ID + 8009 ; ARG2 - Word to be saved + 8010 ; ARG3 - offset of value + 8011 ; + 8012 71AB ZWINPUT: + 8013 71AB 20 9F 4D jsr SAVE_CURSOR ; save the cursor pos + 8014 71AE A5 63 lda ARG1+LO ; get window ID + 8015 71B0 20 7F 57 jsr SETWJ ; have J point to structure + 8016 + 8017 71B3 A5 65 lda ARG2+LO ; get first value in table + 8018 71B5 C9 08 cmp #8 ; 8 = function + 8019 71B7 F0 0D beq ZWIPCRF ; so save that + 8020 71B9 C9 09 cmp #9 ; this is counter + 8021 71BB F0 0D beq ZWIPCRC ; so set counter + 8022 71BD C9 0F cmp #15 ; LINCNT? + 8023 71BF F0 01 beq ZIPLCT ; then set it too + 8024 71C1 60 rts ; just die then + 8025 71C2 ZIPLCT: + 8026 71C2 A0 13 ldy #WINLCNT ; point to line count + 8027 71C4 D0 0B bne ZWINPUT2 ; and stash it away + 8028 71C6 ZWIPCRF: + 8029 71C6 A0 09 ldy #WINCRF+1 ; point to window's CR function + 8030 71C8 D0 02 bne ZWINPUT1 ; and put it + 8031 71CA ZWIPCRC: + Wed Jun 7 1989 12:04 Page 121 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 8032 71CA A0 0B ldy #WINCRC+1 ; point to window's CR counter + 8033 71CC ZWINPUT1: + 8034 71CC A5 68 lda ARG3+HI ; now get hi part + 8035 71CE 91 7A sta (J),Y ; saved! + 8036 71D0 88 dey ; point to lo part + 8037 71D1 ZWINPUT2: + 8038 71D1 A5 67 lda ARG3+LO ; start with lo part + 8039 71D3 91 7A sta (J),Y ; save lo part + 8040 71D5 ZWIPLCT: + 8041 71D5 4C B1 4D jmp GET_CURSOR ; restore cursor/lincnt + 8042 71D8 + 8043 71D8 END + 8044 + 8045 71D8 INCLUDE DLINE.ASM + 8046 71D8 STTL "--- Display line Routine ---" + 8047 PAGE + Wed Jun 7 1989 12:04 Page 122 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8048 ; + 8049 ; some aux mem zero page stuff + 8050 ; + 8051 71D8 DLVARS: + 8052 71D8 CHR_X EQU DLVARS ; (WORD) X pos for char (0-559) + 8053 71DA ENDBIT EQU CHR_X+2 ; (BYTE) ending bit offset + 8054 71DB WRPFLG EQU ENDBIT+1 ; wrapping flag + 8055 71DC SCRLFLG EQU WRPFLG+1 ; scrolling flag + 8056 71DD BUFFLG EQU SCRLFLG+1 ; buffering flag + 8057 71DE SAVEX EQU BUFFLG+1 ; (BYTE) save original X + 8058 71DF CHR_Y EQU SAVEX+1 ; (BYTE) Working cursor Y pos + 8059 71E0 LINECHAR EQU CHR_Y+1 ; (BYTE) working char counter + 8060 71E1 BITTER EQU LINECHAR+1 ; (BYTE) bit twiddler counter + 8061 71E2 INCFLG EQU BITTER+1 ; (BYTE) ==1 if NEXT_SCR needed after setpos + 8062 71E3 SHOW_CURSOR EQU INCFLG+1 ; (BYTE) flag as to whether we are doing cursor + 8063 71E4 SCRCNT EQU SHOW_CURSOR+1 ; (BYTE) screen buffer offset + 8064 71E5 SV_UND EQU SCRCNT+1 ; (BYTE) spot to save underline flag + 8065 71E6 SV_INV EQU SV_UND+1 ; (BYTE) save starting INVFLG + 8066 71E7 UNDERF EQU SV_INV+1 ; (BYTE) underline flag used internally + 8067 71E8 LINE_HEIGHT EQU UNDERF+1 ; (BYTE) counter for height + 8068 0011 DLVARSL EQU LINE_HEIGHT-CHR_X+1 + 8069 + 8070 71D8 BLKB DLVARSL,0 + 8071 + 8072 71E9 07 06 05 04 03 BIT_BITS: DB 7,6,5,4,3,2,1,0 ; number significant bits in last byte + 71EE 02 01 00 + 8073 + 8074 71F1 DISP_LINE: + 8075 71F1 AD E4 71 lda SCRCNT ; make sure there are characters + 8076 71F4 D0 01 bne DPL1 ; ayyup + 8077 71F6 60 rts ; no chars, don't do anything + 8078 71F7 DPL1: + 8079 71F7 A9 00 lda #0 ; start at zero + 8080 71F9 85 09 sta CC_OFF ; which byte to use + 8081 71FB 8D E2 71 sta INCFLG ; and clear out inc'er flag + 8082 71FE + 8083 71FE A9 08 lda #FONT_H-1 ; do for height of char + 8084 7200 8D E8 71 sta LINE_HEIGHT ; height counter + 8085 + 8086 7203 A4 01 ldy SCRCY ; and starting y + 8087 7205 8C DF 71 sty CHR_Y ; saved + 8088 7208 A4 00 ldy SCRCX ; save x to + 8089 720A 8C DE 71 sty SAVEX ; save it + 8090 720D A5 BB lda INVFLG ; get current state + 8091 720F 8D E6 71 sta SV_INV ; and save it + 8092 7212 A5 BA lda UNDFLG ; get current underline state + 8093 7214 8D E5 71 sta SV_UND ; and save it too + 8094 + 8095 7217 AD 7C 6C lda CURSFLG ; changed x pos? + 8096 721A F0 12 beq DPL2 ; no new figgering + 8097 721C A2 00 ldx #0 + 8098 721E 8E D9 71 stx CHR_X+HI ; clear out msb + 8099 + 8100 7221 A5 00 lda SCRCX ; get new cursor x pos + 8101 7223 0A asl A ; *2 + 8102 7224 2E D9 71 rol CHR_X+HI + 8103 7227 0A asl A ; *4 + 8104 7228 8D D8 71 sta CHR_X+LO + 8105 722B 2E D9 71 rol CHR_X+HI + 8106 722E DPL2: + 8107 722E AD D8 71 lda CHR_X+LO + 8108 7231 85 00 sta SCRCX + 8109 7233 29 03 and #3 ; pick up 2 bits rolling out + 8110 7235 8D E1 71 sta BITTER ; what to add + 8111 7238 AD D9 71 lda CHR_X+HI + 8112 723B 4A lsr A ; /2 + 8113 723C 66 00 ror SCRCX + 8114 723E 4A lsr A ; /4 + 8115 723F 66 00 ror SCRCX + 8116 7241 20 51 5E jsr SETPOS ; set up pointers + 8117 + 8118 7244 AD E1 71 lda BITTER ; get extra + 8119 7247 18 clc ; add in + 8120 7248 65 11 adc BITOFF ; normal bit offset + 8121 724A 8D E1 71 sta BITTER ; and make it new one + Wed Jun 7 1989 12:04 Page 123 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8122 724D C9 07 cmp #7 ; but can't be greater than 6 + 8123 724F 90 08 bcc DO_LINE ; okay, it's not + 8124 7251 8D E2 71 sta INCFLG ; show needing NEXT_SCR call + 8125 7254 E9 07 sbc #7 ; so shrink it + 8126 7256 8D E1 71 sta BITTER ; save it + 8127 7259 DO_LINE: + 8128 7259 20 51 5E jsr SETPOS ; set up pointers + 8129 725C AD E2 71 lda INCFLG ; do we need to go one more? + 8130 725F F0 03 beq DOL1 ; nope + 8131 7261 20 F6 5D jsr NEXT_SCR ; and point to next screen byte + 8132 7264 DOL1: + 8133 7264 AE E1 71 ldx BITTER ; get bit off set + 8134 7267 86 11 stx BITOFF ; and save here + 8135 7269 A9 00 lda #0 ; init a few things + 8136 726B 85 13 sta SCR_DATA ; init screen data byte + 8137 726D 8D E0 71 sta LINECHAR ; which character on the line + 8138 7270 85 0F sta CH_OFFSET ; which byte in line on screen + 8139 7272 85 07 sta LINE_X+LO ; X pos of line + 8140 7274 85 08 sta LINE_X+HI ; part 2 + 8141 7276 8D E7 71 sta UNDERF ; make sure this be zero + 8142 + 8143 7279 AD E6 71 lda SV_INV ; get starting INV state + 8144 727C 85 BB sta INVFLG ; okay! + 8145 727E AD E5 71 lda SV_UND ; get starting UNDERLINE state + 8146 7281 85 BA sta UNDFLG ; and restart it + 8147 + 8148 7283 C6 0F dec CH_OFFSET ; inclusive count + 8149 7285 A6 11 ldx BITOFF ; make bitoff be a count + 8150 7287 BD E9 71 lda BIT_BITS,X ; get count + 8151 728A AA tax ; x is bit counter + 8152 728B CHARL: + 8153 728B AC E0 71 ldy LINECHAR ; get the char + 8154 728E CC E4 71 cpy SCRCNT ; done with line? + 8155 7291 D0 03 bne CHARL1 ; nope + 8156 7293 4C 37 73 jmp COPYL ; okay, move onto screen + 8157 7296 CHARL1: + 8158 7296 EE E0 71 inc LINECHAR ; point to next one + 8159 7299 B9 80 02 lda SCRBUFF,Y ; got it + 8160 729C 10 06 bpl CHARL3 ; not a highlight char + 8161 + 8162 729E 20 17 70 jsr HLIGHT ; so check it out + 8163 72A1 4C 8B 72 jmp CHARL ; done + 8164 72A4 CHARL3: + 8165 72A4 C9 20 cmp #SPACE ; is it a highlight char? + 8166 72A6 90 E3 bcc CHARL ; ignore this one then + 8167 72A8 CHARL2: + 8168 72A8 A8 tay ; use as index + 8169 72A9 B9 2C 63 lda CHADR_H,Y ; get high part of address + 8170 72AC 85 1D sta CHPTR+HI ; point to it + 8171 72AE B9 AB 63 lda CHADR_L,Y ; get lo part + 8172 72B1 85 1C sta CHPTR+LO ; save it + 8173 72B3 B9 2A 64 lda CHWID,Y ; get how wide the char is + 8174 72B6 85 C9 sta CW ; save it + 8175 72B8 A5 09 lda CC_OFF ; to get data + 8176 72BA A4 C9 ldy CW ; see how wide the char is + 8177 72BC C0 0A cpy #10 ; if <= 8, only one byte of info + 8178 72BE 90 01 bcc CHRLCW ; it is, so skip shift + 8179 72C0 0A asl A ; *2 for bigger chars + 8180 72C1 CHRLCW: + 8181 72C1 A8 tay ; get the index + 8182 72C2 B1 1C lda (CHPTR),Y ; get first byte + 8183 72C4 85 C7 sta CHAR_D1 ; part one + 8184 72C6 C8 iny ; point to next part + 8185 72C7 B1 1C lda (CHPTR),Y ; get second byte + 8186 72C9 85 C8 sta CHAR_D2 ; and save it + 8187 72CB A5 C9 lda CW ; get width back + 8188 72CD C9 0A cmp #10 ; if <= 8 zero byte 2 of char data + 8189 72CF B0 04 bcs CHRLCW1 ; nope + 8190 72D1 A9 00 lda #0 ; clear out byte 2 + 8191 72D3 85 C8 sta CHAR_D2 ; okay + 8192 72D5 CHRLCW1: + 8193 72D5 A5 C1 lda FONTFLG ; is this monospacing? + 8194 72D7 F0 28 beq CHRLFX ; nope + 8195 ; + 8196 ; if monospacing, see if it char is < mono width, and try to split + Wed Jun 7 1989 12:04 Page 124 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8197 ; the difference if so + 8198 ; + 8199 72D9 C5 C9 cmp CW ; check against current width + 8200 72DB B0 12 bcs CHRLF0 ; CW < monowidth, so center + 8201 ; + 8202 ; too big, so take a little off front end too + 8203 ; + 8204 72DD A5 C9 lda CW ; get current width + 8205 72DF 38 sec ; get ready for subbing + 8206 72E0 E9 0C sbc #MONOFONT_W ; take away mono width + 8207 72E2 4A lsr A ; /2 to get front half + 8208 72E3 A8 tay ; use as counter + 8209 72E4 F0 17 beq CHRLF1 ; nothing to do + 8210 72E6 CHRLFX1: + 8211 72E6 06 C8 asl CHAR_D2 ; step to the left + 8212 72E8 26 C7 rol CHAR_D1 ; pick up char + 8213 72EA 88 dey ; count one + 8214 72EB D0 F9 bne CHRLFX1 ; do next one + 8215 72ED F0 0E beq CHRLF1 ; all done + 8216 72EF CHRLF0: + 8217 72EF 38 sec ; do sub + 8218 72F0 E5 C9 sbc CW ; subtract CW + 8219 72F2 4A lsr A ; /2 to get front part + 8220 72F3 A8 tay ; put in counter + 8221 72F4 F0 07 beq CHRLF1 ; no need to do anything + 8222 72F6 CHRLFL: + 8223 72F6 46 C7 lsr CHAR_D1 ; shift to right + 8224 72F8 66 C8 ror CHAR_D2 ; this part too + 8225 72FA 88 dey ; count shift + 8226 72FB D0 F9 bne CHRLFL ; not done shifting yet + 8227 72FD CHRLF1: + 8228 72FD A9 0C lda #MONOFONT_W ; get mono font width + 8229 72FF 85 C9 sta CW ; chop at mono width + 8230 7301 CHRLFX: + 8231 7301 AD E8 71 lda LINE_HEIGHT ; if == 0, then pick up underlining + 8232 7304 D0 05 bne CHRL3 ; nope + 8233 + 8234 7306 A5 BA lda UNDFLG ; get underlining flag + 8235 7308 8D E7 71 sta UNDERF ; and mark for later + 8236 730B CHRL3: + 8237 730B A5 13 lda SCR_DATA ; get starting data + 8238 730D DATAL: + 8239 730D 26 C8 rol CHAR_D2 ; it's a step to the left + 8240 730F 26 C7 rol CHAR_D1 ; nother one + 8241 7311 6A ror A ; and put into screen byte + 8242 7312 45 BB eor INVFLG ; pick up inversing + 8243 7314 0D E7 71 ora UNDERF ; pick up underline flag + 8244 7317 E6 07 inc LINE_X+LO ; next X pos too + 8245 7319 D0 02 bne DATAL0 ; no wrap + 8246 731B E6 08 inc LINE_X+HI ; wrapped + 8247 731D DATAL0: + 8248 731D CA dex ; next bit pos + 8249 731E D0 0C bne DATAL1 ; nope + 8250 ; + 8251 ; save the byte and point to next byte + 8252 ; + 8253 7320 STCH: + 8254 7320 4A lsr A ; put in lower 7 bits + 8255 7321 E6 0F inc CH_OFFSET ; point to next one + 8256 7323 A4 0F ldy CH_OFFSET ; get current offset + 8257 7325 99 00 1F sta SCR_LINE,Y ; save in line + 8258 7328 A2 07 ldx #7 ; and start bitoff at 7 + 8259 732A A9 00 lda #0 ; clear a few locals + 8260 732C DATAL1: + 8261 732C C6 C9 dec CW ; well? + 8262 732E 30 1F bmi COPYL1 ; all done, start copying + 8263 7330 D0 DB bne DATAL ; nope + 8264 7332 85 13 sta SCR_DATA ; save current screen byte stuff here + 8265 7334 4C 8B 72 jmp CHARL ; do next char + 8266 7337 COPYL: + 8267 7337 A5 07 lda LINE_X+LO ; see if we have any at all + 8268 7339 05 08 ora LINE_X+HI ; well, did we go anywhere? + 8269 733B F0 21 beq LINE_EXIT ; then quit + 8270 733D BD E9 71 lda BIT_BITS,X ; get number of significant bits + 8271 7340 8D DA 71 sta ENDBIT ; save this one + Wed Jun 7 1989 12:04 Page 125 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8272 7343 E0 07 cpx #7 ; has it been renewed? + 8273 7345 F0 08 beq COPYL1 ; no last byte + 8274 7347 A5 13 lda SCR_DATA ; get screen data + 8275 7349 COPYSH: + 8276 7349 4A lsr A ; put down low, please + 8277 734A CA dex ; one more + 8278 734B D0 FC bne COPYSH ; and do it again + 8279 734D F0 D1 beq STCH ; now save this char + 8280 734F COPYL1: + 8281 734F 20 23 61 jsr COPY_SCRL ; copy SCR_LINE to screen + 8282 7352 LED2: + 8283 7352 E6 01 inc SCRCY ; point to next line + 8284 7354 CE E8 71 dec LINE_HEIGHT ; count this line + 8285 7357 30 05 bmi LINE_EXIT ; all done! + 8286 + 8287 7359 E6 09 inc CC_OFF ; point to next byte + 8288 735B 4C 59 72 jmp DO_LINE ; and do next line + 8289 735E LINE_EXIT: + 8290 735E AE DE 71 ldx SAVEX ; get x back + 8291 7361 86 00 stx SCRCX ; restore it + 8292 + 8293 7363 AD E3 71 lda SHOW_CURSOR ; are we just doing cursor? + 8294 7366 D0 14 bne DLXX ; yes, don't change char pos + 8295 + 8296 7368 18 clc ; add in length of this line + 8297 7369 A5 07 lda LINE_X+LO ; get length of line + 8298 736B 6D D8 71 adc CHR_X+LO ; add to start pos + 8299 736E 8D D8 71 sta CHR_X+LO ; save it + 8300 7371 A5 08 lda LINE_X+HI ; and the MSB + 8301 7373 6D D9 71 adc CHR_X+HI ; okay + 8302 7376 8D D9 71 sta CHR_X+HI ; save for a rainy day + 8303 7379 20 8A 73 jsr GET_SCRCX ; set SCRCX back up + 8304 737C DLXX: + 8305 737C AD DF 71 lda CHR_Y ; restore the + 8306 737F 85 01 sta SCRCY ; y pos + 8307 7381 A9 00 lda #0 ; clear out counter + 8308 7383 8D E4 71 sta SCRCNT ; okay + 8309 7386 8D 7C 6C sta CURSFLG ; reset this flag too + 8310 7389 60 rts + 8311 + 8312 738A GET_SCRCX: + 8313 738A AD D8 71 lda CHR_X+LO ; pick this back up + 8314 738D 85 00 sta SCRCX + 8315 738F AD D9 71 lda CHR_X+HI ; /2 + 8316 7392 4A lsr A ; pick up remainder + 8317 7393 66 00 ror SCRCX ; /4 + 8318 7395 4A lsr A ; pick up remainder + 8319 7396 66 00 ror SCRCX ; got it + 8320 7398 AD D8 71 lda CHR_X+LO ; any remainder? + 8321 739B 29 03 and #3 ; well? + 8322 739D F0 DD beq DLXX ; nope + 8323 739F E6 00 inc SCRCX ; point to next pos + 8324 73A1 60 rts + 8325 + 8326 ; + 8327 ; DO_CURSOR - read in the screen byte, XOR cursor data, store it + 8328 ; + 8329 73A2 DO_CURSOR: + 8330 73A2 A0 00 ldy #0 ; and zero y + 8331 73A4 84 10 sty DATALOOP ; init this counter + 8332 73A6 DOCLOOP: + 8333 + 8334 73A6 A0 00 ldy #0 ; must use Y + 8335 73A8 A6 8E ldx FPCBNK ; what bank + 8336 73AA BD 54 C0 lda PAGE2SW,X ; select it + 8337 73AD B1 8C lda (FPC),Y ; okay, get byte + 8338 73AF A6 10 ldx DATALOOP ; get offset + 8339 73B1 5D 00 1F eor SCR_LINE,X ; get data + 8340 73B4 91 8C sta (FPC),Y ; save data + 8341 73B6 20 F6 5D jsr NEXT_SCR ; point to next screen byte + 8342 73B9 E6 10 inc DATALOOP ; point to next char + 8343 73BB C6 0F dec CH_OFFSET ; count one char + 8344 73BD 10 E7 bpl DOCLOOP ; all done with this line? + 8345 73BF AD 54 C0 lda PAGE2SW+MAIN ; make sure we are point to MAIN + 8346 73C2 60 rts + Wed Jun 7 1989 12:04 Page 126 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8347 + 8348 73C3 END + 8349 + 8350 73C3 INCLUDE PIC.ASM + 8351 73C3 STTL "--- Picture Op Codes ---" + 8352 PAGE + Wed Jun 7 1989 12:04 Page 127 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8353 PFILE_RD: ; for READING files + 8354 73C3 04 db 4 ; 4 parameters + 8355 73C4 00 db 0 ; refnum + 8356 73C5 0008 dw IOBUFF ; read into io buffer + 8357 73C7 0004 dw $400 ; 1Kb buffer + 8358 73C9 0000 dw 0 ; length actually read + 8359 73CB PFSEEK: + 8360 73CB 02 db 2 ; 2 pararmeters + 8361 73CC 00 db 0 ; refnum + 8362 73CD 00 00 00 db 0,0,0 ; 3 byte new file pos + 8363 73D0 0000 PICCNT: dw 0 ; counter of the entries + 8364 73D2 00 PF_REFNUM: db 0 ; place to store refnum + 8365 73D3 FF PF_FID: db $FF ; File ID of local directory data + 8366 73D4 00 P_IDX: db 0 + 8367 73D5 00 P_BCNT: db 0 + 8368 73D6 00 P_LOFF: db 0 + 8369 73D7 00 GBL_FLAG: db 0 ; found global directory? + 8370 73D8 00 PIC_FLAG: db 0 ; found pictures? + 8371 73D9 00 PF_NAME: db 0 ; name we are looking at + 8372 73DA 00 db 0 ; name we found + 8373 + 8374 73DB PICINFO: + 8375 73DB ds PLDSIZE ; get room for picture data + 8376 + 8377 73E3 00 TRANSCLR: DB 0 ; transparent color + 8378 73E4 UNKPIC: + 8379 + 8380 73E4 0D 55 6E 6B 6E db EOL,"Unknown Picture #" + 73E9 6F 77 6E 20 50 + 73EE 69 63 74 75 72 + 73F3 65 20 23 + 8381 0012 UNKPICL EQU $-UNKPIC + 8382 73F6 ZDISPL: + 8383 73F6 20 B5 55 jsr CLRBUF ; put out any and all text + 8384 + 8385 73F9 20 4D 77 jsr GET_PICINF ; get the necessary data + 8386 73FC 90 18 bcc ZDSP1 ; everything just fine + 8387 + 8388 73FE DLINE UNKPIC ; unknown picture number error + 8389 73FE A2 E4 ldx #UNKPIC ; get other part of string + 8391 [01] IFMA 2 ; check to see if length passed in + 8392 ldy ; then just fetch it + 8393 [01] ELSE + 8394 7402 A0 12 ldy #UNKPICL ; get length of string + 8395 [00] ENDIF + 8396 7404 20 6B 4C jsr DLINE ; print the string + 8397 7407 .MACEND + 8398 7407 A5 64 lda ARG1+HI ; get MSB + 8399 7409 20 D3 47 jsr HEXNUM ; print it + 8400 740C A5 63 lda ARG1+LO ; and LSB + 8401 740E 20 D3 47 jsr HEXNUM + 8402 7411 A9 14 lda #$14 ; bad picture number error + 8403 7413 4C 0A 52 jmp ZERROR ; and croak + 8404 7416 ZDSP1: + 8405 7416 20 9F 4D jsr SAVE_CURSOR ; save the cursor + 8406 + 8407 7419 A9 00 lda #0 ; show no cursor change + 8408 741B 8D 7C 6C sta CURSFLG ; start with none, anyway + 8409 + 8410 741E C6 62 dec NARGS ; x,y pos passed? + 8411 7420 F0 30 beq ZDSP10 ; nope, just use as is + 8412 + 8413 7422 A5 65 lda ARG2+LO ; get passed y pos + 8414 7424 F0 12 beq ZDSP01 ; don't change + 8415 7426 85 01 sta SCRCY ; change, then + 8416 7428 C6 01 dec SCRCY ; zero base it + 8417 742A A0 00 ldy #WINTOP ; get top edge of window + 8418 742C B1 05 lda (WINDOW),Y ; got it + 8419 742E 18 clc ; get ready for add + 8420 742F 65 01 adc SCRCY ; add the offset + 8421 7431 85 01 sta SCRCY ; and make it Y pos + 8422 7433 A9 01 lda #1 ; show cursor change anyway + 8423 7435 8D 7C 6C sta CURSFLG ; okay, we did + 8424 7438 ZDSP01: + Wed Jun 7 1989 12:04 Page 128 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8425 7438 C6 62 dec NARGS ; x pos passed? + 8426 743A F0 16 beq ZDSP10 ; nope + 8427 + 8428 743C A5 67 lda ARG3+LO ; get x pos + 8429 743E F0 12 beq ZDSP10 ; if == 0, don't change + 8430 7440 85 00 sta SCRCX ; set as passed + 8431 7442 C6 00 dec SCRCX ; zero base it + 8432 7444 A0 01 ldy #WINLEFT ; get left hand edge of window + 8433 7446 B1 05 lda (WINDOW),Y ; got it + 8434 7448 18 clc ; get ready for add + 8435 7449 65 00 adc SCRCX ; add the offset + 8436 744B 85 00 sta SCRCX ; and make it X pos + 8437 744D A9 01 lda #1 ; show cursor change anyway + 8438 744F 8D 7C 6C sta CURSFLG ; okay, we did + 8439 7452 ZDSP10: + 8440 7452 A5 00 lda SCRCX ; get current X + 8441 7454 48 pha ; save it + 8442 7455 18 clc ; adding + 8443 7456 6D DD 73 adc PICINFO+PLDWID ; add in pic width + 8444 7459 85 00 sta SCRCX ; save here + 8445 745B 68 pla ; get start X pos back + 8446 745C 85 00 sta SCRCX ; restored + 8447 745E ZDSP101: + 8448 745E AD DF 73 lda PICINFO+PLDFLG ; get flag byte + 8449 7461 29 01 and #1 ; is there a transparent color? + 8450 7463 D0 04 bne ZDSP11 ; ayyup + 8451 7465 A9 FF lda #$FF ; make TRANSCLR be $FF + 8452 7467 D0 07 bne ZDSP12 ; okay + 8453 7469 ZDSP11: + 8454 7469 AD DF 73 lda PICINFO+PLDFLG ; get hi byte of flag word + 8455 746C 4A lsr A ; put in lower byte + 8456 746D 4A lsr A ; put in lower byte + 8457 746E 4A lsr A ; put in lower byte + 8458 746F 4A lsr A ; put in lower byte + 8459 7470 ZDSP12: + 8460 7470 8D E3 73 sta TRANSCLR ; save transparent color + 8461 + 8462 7473 AD E0 73 lda PICINFO+PLDPTR ; MSB of offset + 8463 7476 8D CF 73 sta PFSEEK+SM_FPOS+2 ; MSB of seek + 8464 7479 AD E1 73 lda PICINFO+PLDPTR+1 ; Middle + 8465 747C 29 FE and #$FE ; seek only to 512byte boundary + 8466 747E 8D CE 73 sta PFSEEK+SM_FPOS+1 + 8467 + 8468 7481 SET_MARK PFSEEK ; go to pic data + 8469 7481 PRODOS $CE, PFSEEK + 8470 7481 20 00 BF jsr $BF00 ; ProDOS handler + 8471 7484 CE DB $CE ; ProDOS function code + 8472 7485 CB73 DW PFSEEK ; Function Parameter Block address + 8473 7487 .MACEND + 8474 7487 .MACEND + 8475 7487 A9 02 lda #>PIC1BUF ; set up pointers to decode buffers + 8476 7489 85 7B sta J+HI + 8477 748B A9 73 lda #PIC2BUF + 8480 7491 85 7D sta K+HI + 8481 7493 A9 74 lda #IOBUFF ; now get data buffer address + 8493 74A7 85 7F sta L+HI + 8494 74A9 A9 04 lda #4 ; 4 pages read in at once + 8495 74AB 8D D5 73 sta P_BCNT ; okay + 8496 74AE A9 03 lda #3 ; 3 bytes of width data start it + 8497 74B0 18 clc ; doing add + 8498 74B1 6D E2 73 adc PICINFO+PLDPTR+2 ; pick up LSB pointer + 8499 74B4 8D D4 73 sta P_IDX ; start index + Wed Jun 7 1989 12:04 Page 129 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8500 74B7 90 05 bcc ZDLPCC ; no wrap + 8501 74B9 E6 7F inc L+HI ; start at second one + 8502 74BB CE D5 73 dec P_BCNT ; one less block + 8503 74BE ZDLPCC: + 8504 74BE AD E1 73 lda PICINFO+PLDPTR+1 ; tells which block it is in + 8505 74C1 29 01 and #$01 ; pick up which 256 block + 8506 74C3 F0 05 beq ZDLP0 ; start at first one + 8507 74C5 E6 7F inc L+HI ; start at next one + 8508 74C7 CE D5 73 dec P_BCNT ; one less block + 8509 74CA ZDLP0: + 8510 74CA A9 00 lda #IOBUFF ; reset data buffer address + 8705 7601 85 7F sta L+HI + 8706 7603 A9 00 lda #GBL_DIR ; start destination off here + 8763 764F 20 6A 76 jsr READ_IN_PDATA ; go get global directory, if any + 8764 7652 8D D7 73 sta GBL_FLAG ; indicate whether there is a global + 8765 7655 GTPG1: + 8766 7655 AD C5 49 lda SAVENUM ; get which file is being opened + 8767 7658 29 0F and #$0F ; just make it binary + 8768 765A CD D3 73 cmp PF_FID ; same as the file we already have? + 8769 765D F0 0A beq GETPGX ; yes, so don't bother + 8770 765F A0 02 ldy #SGTPICOF ; point to picture offset + 8771 7661 A9 D0 lda #>PIC_DIR ; start destination off here + 8772 7663 20 6A 76 jsr READ_IN_PDATA ; go get the data for local pictures + 8773 7666 8D D8 73 sta PIC_FLAG ; any picture data + 8774 7669 GETPGX: + 8775 7669 60 rts + 8776 ; + 8777 ; READ_IN_PDATA - check for desired data being in file, and skip to it if + 8778 ; it is. Then, read it in in 1Kb chunks, stashing it away into the + 8779 ; upper bank of the aux mem language card. + 8780 ; Enter with: + 8781 ; [A] = Destination page + 8782 ; [Y] = Offset into Segment table + 8783 ; + 8784 766A READ_IN_PDATA: + 8785 766A 48 pha ; save destination page + 8786 766B B1 1E lda (DSEGS),Y ; get MSB + 8787 766D 8D CF 73 sta PFSEEK+SM_FPOS+2 ; Byte 2 + 8788 7670 C8 iny ; point to LSB + 8789 7671 11 1E ora (DSEGS),Y ; is there any pic data? + 8790 7673 D0 04 bne GTPD00 ; yes + 8791 7675 68 pla ; get page back + 8792 7676 A9 00 lda #0 ; show not here + 8793 7678 60 rts ; nope + 8794 7679 GTPD00: + 8795 7679 B1 1E lda (DSEGS),Y ; get it for shifting + 8796 767B 0A asl A ; *2 + 8797 767C 8D CE 73 sta PFSEEK+SM_FPOS+1 ; stash away + 8798 767F 2E CF 73 rol PFSEEK+SM_FPOS+2 ; pick up carry + 8799 7682 A9 00 lda #0 ; clear out MSB + Wed Jun 7 1989 12:04 Page 133 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8800 7684 8D C8 73 sta PFILE_RD+RD_BUFFLEN+HI + 8801 7687 8D CD 73 sta PFSEEK+SM_FPOS ; and LSB of seeking + 8802 + 8803 768A AD D2 73 lda PF_REFNUM ; get file ref number + 8804 768D 8D C4 73 sta PFILE_RD+RD_REFNUM ; and save it for reading and + 8805 7690 8D CC 73 sta PFSEEK+SM_REFNUM ; for seeking + 8806 + 8807 7693 A9 03 lda #RETRY_COUNT ; set retry + 8808 7695 85 0E sta NY_DATA ; just use this for now + 8809 7697 GTPDRD0: + 8810 7697 SET_MARK PFSEEK ; and go to beginning + 8811 7697 PRODOS $CE, PFSEEK + 8812 7697 20 00 BF jsr $BF00 ; ProDOS handler + 8813 769A CE DB $CE ; ProDOS function code + 8814 769B CB73 DW PFSEEK ; Function Parameter Block address + 8815 769D .MACEND + 8816 769D .MACEND + 8817 + 8818 769D A9 04 lda #4 ; read in 4 256 blocks + 8819 769F 8D C8 73 sta PFILE_RD+RD_BUFFLEN+HI + 8820 76A2 READ PFILE_RD ; go get the next 4Kb worth + 8821 76A2 PRODOS $CA, PFILE_RD + 8822 76A2 20 00 BF jsr $BF00 ; ProDOS handler + 8823 76A5 CA DB $CA ; ProDOS function code + 8824 76A6 C373 DW PFILE_RD ; Function Parameter Block address + 8825 76A8 .MACEND + 8826 76A8 .MACEND + 8827 76A8 90 05 bcc GTPD1 ; fine + 8828 76AA 20 07 47 jsr RETRY ; well, do it again? + 8829 76AD 90 E8 bcc GTPDRD0 ; yes + 8830 76AF GTPD1: + 8831 76AF 68 pla ; get destination page back + 8832 76B0 C9 D0 cmp #>PIC_DIR ; if doing local directory, set up + 8833 76B2 D0 16 bne GTPD2 ; picture count + 8834 76B4 AE 04 08 ldx IOBUFF+PHNLD ; get number of pictures + 8835 76B7 8E D1 73 stx PICCNT+HI ; save for count down too + 8836 76BA AE 05 08 ldx IOBUFF+PHNLD+1 ; and here is LSB + 8837 76BD 8E D0 73 stx PICCNT+LO ; saving for counting + 8838 76C0 AE 00 08 ldx IOBUFF+PHFID ; get file ID + 8839 76C3 8E D3 73 stx PF_FID ; and save for later + 8840 76C6 A2 20 ldx #(256/PLDSIZE) ; how many entries in 256 bytes + 8841 76C8 D0 0E bne GTPD3 ; done + 8842 76CA GTPD2: + 8843 76CA AE 00 08 ldx IOBUFF ; get MSB of how many + 8844 76CD 8E D1 73 stx PICCNT+HI ; show me + 8845 76D0 AE 01 08 ldx IOBUFF+1 ; get LSB of count + 8846 76D3 8E D0 73 stx PICCNT+LO + 8847 76D6 A2 80 ldx #(256/2) ; how many entries / 256 bytes + 8848 76D8 GTPD3: + 8849 76D8 8E 0F 77 stx GTPMOD+1 ; set up how big entry is + 8850 76DB 8D 09 C0 sta ALTZP+AUX ; use aux mem for most of this + 8851 76DE 85 7D sta K+HI ; MSB of destination + 8852 76E0 A9 00 lda #0 ; clear a few things + 8853 76E2 85 7A sta J+LO ; J = source + 8854 76E4 85 7C sta K+LO ; K = destination + 8855 76E6 A9 04 lda #4 ; 4 * (4*256) bytes max + 8856 76E8 8D C8 73 sta PFILE_RD+RD_BUFFLEN+HI ; show the read too + 8857 76EB 8D D4 73 sta P_IDX ; save here for counting + 8858 76EE GTPDL: + 8859 76EE A0 00 ldy #0 ; start y + 8860 76F0 A9 08 lda #>IOBUFF ; get where source is + 8861 76F2 85 7B sta J+HI ; MSB of source + 8862 76F4 A9 04 lda #4 ; 4 blocks worth of 256 + 8863 76F6 8D D5 73 sta P_BCNT ; used as counter + 8864 76F9 AD 8B C0 lda BNK1SET ; we be using bank 1 @$D000 + 8865 76FC AD 8B C0 lda BNK1SET ; we be using bank 1 @$D000 + 8866 76FF GTPDL1: + 8867 76FF B1 7A lda (J),Y ; get the data byte + 8868 7701 91 7C sta (K),Y ; store in upper aux + 8869 7703 C8 iny ; point to the next one + 8870 7704 D0 F9 bne GTPDL1 ; and go get it + 8871 7706 + 8872 7706 E6 7B inc J+HI ; next block please + 8873 7708 E6 7D inc K+HI ; for destination too + 8874 770A AD D0 73 lda PICCNT+LO ; how many entries? + Wed Jun 7 1989 12:04 Page 134 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8875 770D 38 sec ; doing sbc + 8876 770E E9 20 GTPMOD: sbc #(256/PLDSIZE) ; how many entries in 256 bytes? + 8877 7710 8D D0 73 sta PICCNT+LO ; save result + 8878 7713 B0 05 bcs GTPDL2 ; no wrapping + 8879 7715 CE D1 73 dec PICCNT+HI ; wrap + 8880 7718 30 26 bmi GTPDLX ; all done if we go negative + 8881 771A GTPDL2: + 8882 771A 0D D1 73 ora PICCNT+HI ; make sure both are not zero + 8883 771D F0 21 beq GTPDLX ; if they are, then we are done + 8884 771F CE D5 73 dec P_BCNT ; count this block + 8885 7722 D0 DB bne GTPDL1 ; go fetch next 256 bytes + 8886 7724 8D 08 C0 sta ALTZP+MAIN ; swap back to main for read + 8887 + 8888 7727 A9 03 lda #RETRY_COUNT ; set retry + 8889 7729 85 0E sta NY_DATA ; just use this for now + 8890 772B GTPDRD: + 8891 772B READ PFILE_RD ; go get the next 4Kb worth + 8892 772B PRODOS $CA, PFILE_RD + 8893 772B 20 00 BF jsr $BF00 ; ProDOS handler + 8894 772E CA DB $CA ; ProDOS function code + 8895 772F C373 DW PFILE_RD ; Function Parameter Block address + 8896 7731 .MACEND + 8897 7731 .MACEND + 8898 7731 90 05 bcc GTPDRDG ; fine + 8899 7733 20 07 47 jsr RETRY ; well, do it again? + 8900 7736 90 F3 bcc GTPDRD ; yes + 8901 7738 GTPDRDG: + 8902 7738 8D 09 C0 sta ALTZP+AUX ; and back to aux for working + 8903 773B CE D4 73 dec P_IDX ; max 4Kb worth of reading + 8904 773E D0 AE bne GTPDL ; and read in more + 8905 7740 GTPDLX: + 8906 7740 8D 08 C0 sta ALTZP+MAIN ; back to main bank of mem + 8907 7743 AD 83 C0 lda BNK2SET ; back to bank 2 + 8908 7746 AD 83 C0 lda BNK2SET ; yes please + 8909 7749 A9 01 lda #1 ; show we found it + 8910 774B 60 rts ; all done + 8911 + 8912 774C 00 GTPFLAG: db 0 ; if 1 when opening next file, then + 8913 ; this is the next file, so unable to + 8914 ; find picture number + 8915 774D GET_PICINF: + 8916 774D A9 00 lda #0 ; set flag for double check + 8917 774F 8D 4C 77 sta GTPFLAG ; start at zero + 8918 7752 GTPLOOP: + 8919 7752 A5 63 lda ARG1+LO ; check argument for zero + 8920 7754 05 64 ora ARG1+HI ; is it zero? + 8921 7756 D0 02 bne GTPINDX ; jump to look at first block + 8922 7758 18 clc ; found some pictures + 8923 7759 60 rts ; if zero, just give count + 8924 775A GTPINDX: + 8925 775A A4 63 ldy ARG1+LO ; get arg, as we are swapping + 8926 775C A6 64 ldx ARG1+HI ; to aux mem + 8927 775E 8D 09 C0 sta ALTZP+AUX ; look at AUX mem + 8928 7761 AD 8B C0 lda BNK1SET ; bank 1 + 8929 7764 AD 8B C0 lda BNK1SET ; bank 1 + 8930 7767 AD 04 D0 lda PIC_DIR+PHNLD ; get # of entries + 8931 776A 8D D1 73 sta PICCNT+HI + 8932 776D AD 05 D0 lda PIC_DIR+PHNLD+1 ; it's in reverse order + 8933 7770 8D D0 73 sta PICCNT+LO + 8934 7773 84 63 sty ARG1+LO ; use aux mem zero page + 8935 7775 86 64 stx ARG1+HI ; for new arg1 + 8936 7777 A9 D0 lda #>PIC_DIR ; start at beginning of block + 8937 7779 85 8A sta MPNTH ; hi part + 8938 777B A9 00 lda #GBL_DIR ; start at beginning of block + 9027 7810 85 8A sta MPNTH ; hi part + 9028 7812 A9 00 lda # 2 BYTES + 9411 7A16 29 40 and #%01000000 + 9412 7A18 F0 04 beq PTZ1 ; BIT 6 = 0, LENGTH = 1 + 9413 7A1A A9 02 lda #2 ; BIT 6 = 1, LENGTH = 2 + 9414 7A1C D0 09 bne PTZ3 ; JMP + 9415 7A1E PTZ1: + 9416 7A1E A9 01 lda #1 + 9417 7A20 D0 05 bne PTZ3 ; JMP + 9418 7A22 PTZ2: + 9419 7A22 20 5B 92 jsr FETCHB ; and get it + 9420 7A25 29 3F and #%00111111 ; ELSE PICK UP SIZE > 2 + 9421 7A27 PTZ3: + 9422 7A27 A2 00 ldx #0 ; CLEAR FOR PUTBYT + 9423 7A29 4C DD 43 jmp PUTBYT + 9424 ; --- + 9425 ; INC + 9426 ; --- + 9427 ; INCREMENT VARIABLE [ARG1] + 9428 + 9429 7A2C A5 63 ZINC: LDA ARG1+LO + 9430 7A2E 20 36 43 JSR VARGET ; FETCH VARIABLE INTO [VALUE] + 9431 7A31 E6 76 INC VALUE+LO + 9432 7A33 D0 02 BNE ZINC1 + 9433 7A35 E6 77 INC VALUE+HI + 9434 7A37 4C 4C 7A ZINC1: JMP ZD0 + 9435 + 9436 + 9437 ; --- + 9438 ; DEC + 9439 ; --- + 9440 ; DECREMENT VARIABLE [ARG1] + 9441 + 9442 7A3A A5 63 ZDEC: LDA ARG1+LO + 9443 7A3C 20 36 43 JSR VARGET ; FETCH VAR INTO [VALUE] + 9444 7A3F A5 76 LDA VALUE+LO + 9445 7A41 38 SEC + 9446 7A42 E9 01 SBC #1 + 9447 7A44 85 76 STA VALUE+LO + 9448 7A46 A5 77 LDA VALUE+HI + 9449 7A48 E9 00 SBC #0 + 9450 7A4A 85 77 STA VALUE+HI + 9451 7A4C A5 63 ZD0: LDA ARG1+LO ; PUT RESULT BACK + 9452 7A4E 4C C7 43 JMP VARPUT ; INTO THE SAME VARIABLE + 9453 + 9454 + 9455 ; ------ + 9456 ; PRINTB + 9457 ; ------ + 9458 ; PRINT Z-STRING AT [ARG1] + 9459 + Wed Jun 7 1989 12:04 Page 143 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9460 7A51 ZPRB: + 9461 7A51 A5 63 lda ARG1+LO ; move arg1 to I + 9462 7A53 85 78 sta I+LO ; lo part + 9463 7A55 A5 64 lda ARG1+HI ; and now for arg1 hi + 9464 7A57 85 79 sta I+HI ; okay + 9465 7A59 20 65 8F jsr SETWRD ; make [MPC] point to it + 9466 7A5C 4C D3 92 jmp PZSTR ; and print it + 9467 + 9468 ; ------ + 9469 ; REMOVE + 9470 ; ------ + 9471 ; MOVE OBJECT [ARG1] INTO PSEUDO-OBJECT #0 + 9472 ; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO + 9473 ; 2) MOVES AND COMPARES 2 BYTES) + 9474 + 9475 7A5F SAVEFPC: ds 3 ; spot to save the FPC + 9476 7A62 SAVEOBJ: ds 1 ; check for zero object + 9477 + 9478 7A63 ZREMOV: + 9479 7A63 A5 63 lda ARG1+LO ; GET SOURCE OBJECT ADDR + 9480 7A65 A6 64 ldx ARG1+HI + 9481 7A67 20 F1 94 jsr OBJLOC ; INTO [FPC] + 9482 ; + 9483 ; now save this objects address in I,J + 9484 ; + 9485 7A6A A9 06 lda #6 ; point to the LOC slot + 9486 7A6C 20 E3 8F jsr ADDFPC ; thank you + 9487 7A6F A5 8C lda FPCL ; COPY THE SOURCE ADDR + 9488 7A71 8D 5F 7A sta SAVEFPC+LO ; INTO [J] + 9489 7A74 A5 8D lda FPCH ; FOR LATER REFERENCE + 9490 7A76 8D 60 7A sta SAVEFPC+HI + 9491 7A79 A5 8E lda FPCBNK + 9492 7A7B 8D 61 7A sta SAVEFPC+ABANK + 9493 ; + 9494 ; now go get object this one is in + 9495 ; + 9496 7A7E 20 5B 92 jsr FETCHB ; get the data + 9497 7A81 85 7C sta K ; HOLD IT + 9498 7A83 20 C3 8F jsr NEXTFPC ; get lo part + 9499 7A86 20 5B 92 jsr FETCHB ; now get part + 9500 7A89 A8 tay ; save it + 9501 7A8A 05 7C ora K ; COMPARE BYTES + 9502 7A8C D0 03 bne REMVj ; check for object + 9503 7A8E 4C 33 7B jmp REMVEX ; SCRAM IF NO OBJECT + 9504 7A91 REMVj: + 9505 7A91 98 tya ; get lo part + 9506 7A92 A6 7C ldx K ; and hi part + 9507 7A94 20 F1 94 jsr OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [FPC] + 9508 7A97 A9 0B lda #11 ; POINT TO "FIRST" SLOT, LSB + 9509 7A99 20 E3 8F jsr ADDFPC ; and point to it + 9510 7A9C 20 5B 92 jsr FETCHB ; and get it + 9511 7A9F 48 pha ; save LSB + 9512 7AA0 20 29 90 jsr PREVFPC ; point to MSB + 9513 7AA3 20 5B 92 jsr FETCHB ; A=LO, X=HI + 9514 7AA6 AA tax ; put into x + 9515 7AA7 68 pla ; get LSB back + 9516 7AA8 C5 63 cmp ARG1+LO ; IS THIS THE FIRST? + 9517 7AAA D0 04 bne REMVC1 ; NO, KEEP SEARCHING + 9518 7AAC E4 64 cpx ARG1+HI ; HM? + 9519 7AAE F0 2B beq DO_REMOVE ; yes, so use it + 9520 7AB0 REMVC1: + 9521 7AB0 20 F1 94 jsr OBJLOC ; get object + 9522 7AB3 A9 09 lda #9 ; GET "NEXT" slot address + 9523 7AB5 20 E3 8F jsr ADDFPC ; into FPC + 9524 7AB8 20 5B 92 jsr FETCHB ; get the byte + 9525 7ABB 48 pha ; save LSB for later + 9526 7ABC 20 29 90 jsr PREVFPC ; and this is the hi part + 9527 7ABF 20 5B 92 jsr FETCHB + 9528 7AC2 8D 62 7A sta SAVEOBJ ; save for later check + 9529 7AC5 AA tax ; and put into x for (possible) check + 9530 7AC6 68 pla ; get lo part back + 9531 7AC7 A8 tay ; save a minute + 9532 7AC8 0D 62 7A ora SAVEOBJ ; well, is it zero? + 9533 7ACB D0 05 bne REMVC2 ; no, so check it + 9534 7ACD A9 15 lda #21 ; so die + Wed Jun 7 1989 12:04 Page 144 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9535 7ACF 4C 0A 52 jmp ZERROR ; and croak + 9536 7AD2 REMVC2: + 9537 7AD2 98 tya ; put back into [A] + 9538 7AD3 C5 63 cmp ARG1+LO ; FOUND IT? + 9539 7AD5 D0 D9 bne REMVC1 ; NO, KEEP TRYING + 9540 7AD7 E4 64 cpx ARG1+HI + 9541 7AD9 D0 D5 bne REMVC1 + 9542 7ADB DO_REMOVE: + 9543 ; + 9544 ; now, copy from FPC to SPC for stashing away + 9545 ; + 9546 7ADB 20 78 90 jsr FP2SP ; copied + 9547 ; + 9548 ; now get removed one's address for fetching + 9549 ; + 9550 7ADE AD 61 7A lda SAVEFPC+ABANK ; this is where bank is + 9551 7AE1 85 8E sta FPCBNK ; so show it + 9552 7AE3 AD 60 7A lda SAVEFPC+HI ; and here's the hi/lo part + 9553 7AE6 85 8D sta FPCH + 9554 7AE8 AD 5F 7A lda SAVEFPC+LO + 9555 7AEB 85 8C sta FPCL + 9556 7AED A9 02 lda #2 ; so get to source's "NEXT" slot + 9557 7AEF 20 E3 8F jsr ADDFPC ; point to next slot + 9558 7AF2 20 5B 92 jsr FETCHB ; get the hi byte + 9559 7AF5 20 3A 92 jsr STASHB ; and save it + 9560 7AF8 20 A3 8F jsr NEXTSPC ; point to next one + 9561 7AFB 20 C3 8F jsr NEXTFPC ; and from the source too + 9562 7AFE 20 5B 92 jsr FETCHB ; get lo byte + 9563 7B01 20 3A 92 jsr STASHB ; and save it away + 9564 ; + 9565 ; now zero out SOURCE's loc and next spots + 9566 ; + 9567 7B04 AD 61 7A lda SAVEFPC+ABANK ; bank of source + 9568 7B07 85 91 sta SPCBNK + 9569 7B09 AD 60 7A lda SAVEFPC+HI ; and addr of source LOC slot + 9570 7B0C 85 90 sta SPCH + 9571 7B0E AD 5F 7A lda SAVEFPC+LO + 9572 7B11 85 8F sta SPCL + 9573 ; + 9574 ; zero out NEXT and LOC of source + 9575 ; + 9576 7B13 A9 00 lda #0 ; zero out 4 locations (LOC MSB) + 9577 7B15 20 3A 92 jsr STASHB + 9578 7B18 20 A3 8F jsr NEXTSPC + 9579 7B1B + 9580 7B1B A9 00 lda #0 ; zero out 4 locations (LOC LSB) + 9581 7B1D 20 3A 92 jsr STASHB + 9582 7B20 20 A3 8F jsr NEXTSPC + 9583 7B23 + 9584 7B23 A9 00 lda #0 ; zero out 4 locations (NEXT MSB) + 9585 7B25 20 3A 92 jsr STASHB + 9586 7B28 20 A3 8F jsr NEXTSPC + 9587 7B2B + 9588 7B2B A9 00 lda #0 ; zero out 4 locations (NEXT LSB) + 9589 7B2D 20 3A 92 jsr STASHB + 9590 7B30 20 A3 8F jsr NEXTSPC + 9591 7B33 REMVEX: + 9592 7B33 60 RTS + 9593 + 9594 + 9595 ; ------ + 9596 ; PRINTD + 9597 ; ------ + 9598 ; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + 9599 + 9600 7B34 ZPRD: + 9601 7B34 A5 63 lda ARG1+LO + 9602 7B36 A6 64 ldx ARG1+HI ; (EZIP) + 9603 7B38 20 F1 94 jsr OBJLOC ; GET ADDR OF OBJECT INTO [FPC] + 9604 7B3B A9 0D lda #13 ; GET PROP TABLE POINTER (EZIP) + 9605 7B3D 20 E3 8F jsr ADDFPC ; and point to LSB + 9606 7B40 20 5B 92 jsr FETCHB ; fetch LSB + 9607 7B43 48 pha ; SAVE IT HERE + 9608 7B44 20 29 90 jsr PREVFPC ; and now fetch MSB + 9609 7B47 20 5B 92 jsr FETCHB ; thank you + Wed Jun 7 1989 12:04 Page 145 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9610 7B4A 85 79 sta I+HI ; AND MSB + 9611 7B4C 68 pla ; get LSB back + 9612 7B4D 85 78 sta I+LO ; STORE LSB + 9613 7B4F E6 78 inc I+LO ; POINT PAST THE + 9614 7B51 D0 02 bne PDC0 ; LENGTH BYTE + 9615 7B53 E6 79 inc I+HI + 9616 7B55 20 65 8F PDC0: jsr SETWRD ; CALC Z-STRING ADDR + 9617 7B58 4C D3 92 jmp PZSTR ; AND PRINT IT + 9618 + 9619 + 9620 ; ------ + 9621 ; RETURN + 9622 ; ------ + 9623 ; RETURN FROM "CALL" WITH VALUE [ARG1] + 9624 + 9625 7B5B ZRET: + 9626 7B5B AD 7A 6C LDA OLDZSP+LO ; RE-SYNC THE + 9627 7B5E 85 AF STA ZSP+LO ; Z-STACK POINTER + 9628 7B60 AD 7B 6C LDA OLDZSP+HI + 9629 7B63 85 B0 STA ZSP+HI + 9630 7B65 20 66 43 JSR POPVAL ; POP # LOCALS INTO [X/A] + 9631 7B68 86 79 STX I+HI ; SAVE HERE + 9632 7B6A 20 66 43 JSR POPVAL ; now we need number of args + 9633 7B6D 8D 68 5B STA ASSVLU ; for ASSIGNED? + 9634 + 9635 7B70 A6 79 LDX I+HI ; see how many locals + 9636 7B72 F0 19 BEQ RET2 ; SKIP IF NOT + 9637 + 9638 ; RESTORE PUSHED LOCALS + 9639 + 9640 7B74 CA DEX ; ZERO-ALIGN + 9641 7B75 8A TXA ; AND + 9642 7B76 0A ASL A ; WORD-ALIGN # LOCALS + 9643 7B77 85 78 STA I+LO ; FOR USE AS A STORAGE INDEX + 9644 7B79 20 66 43 RET1: JSR POPVAL ; POP A LOCAL INTO [X/A] + 9645 7B7C A4 78 LDY I+LO ; RETRIEVE STORAGE INDEX + 9646 7B7E 99 01 1E STA LOCALS+HI,Y ; STORE MSB OF LOCAL + 9647 7B81 8A TXA ; MOVE LSB + 9648 7B82 99 00 1E STA LOCALS+LO,Y ; AND STORE THAT TOO + 9649 7B85 C6 78 DEC I+LO + 9650 7B87 C6 78 DEC I+LO ; UPDATE STORAGE INDEX + 9651 7B89 C6 79 DEC I+HI ; AND LOCALS COUNT + 9652 7B8B D0 EC BNE RET1 ; POP TILL NO MORE LOCALS + 9653 + 9654 ; RESTORE OTHER VARIABLES + 9655 + 9656 7B8D RET2: + 9657 7B8D 20 66 43 JSR POPVAL ; POP [ZPCH] AND [ZPCM] + 9658 7B90 86 81 STX ZPCM + 9659 7B92 85 82 STA ZPCH + 9660 7B94 20 66 43 JSR POPVAL ; POP AND RESTORE + 9661 7B97 8E 64 5B STX IRET + 9662 7B9A 85 80 STA ZPCL + 9663 7B9C 20 66 43 JSR POPVAL + 9664 7B9F 8E 7A 6C STX OLDZSP+LO + 9665 7BA2 8D 7B 6C STA OLDZSP+HI + 9666 + 9667 7BA5 A5 80 LDA ZPCL ; check for zero zpc + 9668 7BA7 D0 0E BNE RETj ; which means we are returning to + 9669 7BA9 A5 81 LDA ZPCM ; an internal call + 9670 7BAB D0 0A BNE RETj ; rather than just a normal + 9671 7BAD A5 82 LDA ZPCH ; return + 9672 7BAF D0 06 BNE RETj ; but so far it isn't + 9673 + 9674 7BB1 20 B4 44 JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9675 7BB4 4C 47 5B JMP ZIRET ; so then do internal return + 9676 7BB7 RETj: + 9677 7BB7 20 AF 90 JSR VLDZPC ; MAKE VALID + 9678 7BBA AD 64 5B LDA IRET ; CHECK IF SHOULD RETURN A VALUE + 9679 7BBD F0 01 BEQ RETYES ; (0 = RET, 1 = NO RETURN) + 9680 7BBF 60 RTS ; NO, SO JUST GET OUT OF HERE + 9681 7BC0 RETYES: + 9682 7BC0 20 B4 44 JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9683 7BC3 4C E1 43 JMP PUTVAL ; AND RETURN IT + 9684 + Wed Jun 7 1989 12:04 Page 146 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9685 + 9686 ; ---- + 9687 ; JUMP + 9688 ; ---- + 9689 ; JUMP TO Z-LOCATION IN [ARG1] + 9690 + 9691 7BC6 20 B4 44 ZJUMP: JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9692 7BC9 4C 75 44 JMP PREDB3 ; A BRANCH THAT ALWAYS SUCCEEDS + 9693 + 9694 + 9695 ; ----- + 9696 ; PRINT + 9697 ; ----- + 9698 ; PRINT Z-STRING AT WORD (QUAD) POINTER [ARG1] + 9699 + 9700 7BCC ZPRINT: + 9701 7BCC A5 63 LDA ARG1+LO + 9702 7BCE 85 78 STA I+LO + 9703 7BD0 A5 64 LDA ARG1+HI + 9704 7BD2 85 79 STA I+HI + 9705 7BD4 20 A5 92 JSR SETSTR ; CALC STRING ADDRESS + 9706 7BD7 4C D3 92 JMP PZSTR ; AND PRINT IT + 9707 + 9708 + 9709 ; ----- + 9710 ; VALUE + 9711 ; ----- + 9712 ; RETURN VALUE OF VARIABLE [ARG1] + 9713 + 9714 7BDA ZVALUE: + 9715 7BDA A5 63 LDA ARG1+LO + 9716 7BDC 20 36 43 JSR VARGET ; GET THE VALUE + 9717 7BDF 4C E1 43 JMP PUTVAL ; EASY ENOUGH + 9718 + 9719 + 9720 + 9721 7BE2 STTL "--- 2-OPS ---" + 9722 PAGE + Wed Jun 7 1989 12:04 Page 147 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9723 + 9724 + 9725 ; ----- + 9726 ; LESS? + 9727 ; ----- + 9728 ; [ARG1] < [ARG2]? + 9729 + 9730 7BE2 ZLESS: + 9731 7BE2 20 B4 44 JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9732 7BE5 4C EB 7B JMP DLS0 ; MOVE [ARG2] TO [I] & COMPARE + 9733 + 9734 + 9735 ; ------ + 9736 ; DLESS? + 9737 ; ------ + 9738 ; DECREMENT [ARG1] ; SUCCEED IF < [ARG2] + 9739 + 9740 7BE8 ZDLESS: + 9741 7BE8 20 3A 7A JSR ZDEC ; MOVES ([ARG1]-1) TO [VALUE] + 9742 7BEB A5 65 DLS0: LDA ARG2+LO ; MOVE [ARG2] TO [I] + 9743 7BED 85 78 STA I+LO + 9744 7BEF A5 66 LDA ARG2+HI + 9745 7BF1 85 79 STA I+HI + 9746 7BF3 4C 14 7C JMP COMPAR ; COMPARE & RETURN + 9747 + 9748 + 9749 ; ----- + 9750 ; GRTR? + 9751 ; ----- + 9752 ; [ARG1] < [ARG2]? + 9753 + 9754 7BF6 A5 63 ZGRTR: LDA ARG1+LO ; MOVE [ARG1] TO [I] + 9755 7BF8 85 78 STA I+LO + 9756 7BFA A5 64 LDA ARG1+HI + 9757 7BFC 85 79 STA I+HI + 9758 7BFE 4C 0C 7C JMP A2VAL ; MOVE [ARG2] TO [VALUE] & COMPARE + 9759 + 9760 + 9761 ; ------ + 9762 ; IGRTR? + 9763 ; ------ + 9764 ; INCREMENT [ARG1] ; SUCCEED IF GREATER THAN [ARG2] + 9765 + 9766 7C01 20 2C 7A ZIGRTR: JSR ZINC ; GET ([ARG1]+1) INTO [VALUE] + 9767 7C04 A5 76 LDA VALUE+LO ; MOVE [VALUE] TO [I] + 9768 7C06 85 78 STA I+LO + 9769 7C08 A5 77 LDA VALUE+HI + 9770 7C0A 85 79 STA I+HI + 9771 7C0C A5 65 A2VAL: LDA ARG2+LO ; MOVE [ARG2] TO [VALUE] + 9772 7C0E 85 76 STA VALUE+LO + 9773 7C10 A5 66 LDA ARG2+HI + 9774 7C12 85 77 STA VALUE+HI + 9775 + 9776 + 9777 ; ----------------- + 9778 ; SIGNED COMPARISON + 9779 ; ----------------- + 9780 ; ENTRY: VALUES IN [VALUE] AND [I] + 9781 ; + 9782 ; IS [VALUE] > [I] + 9783 ; + 9784 7C14 COMPAR: + 9785 7C14 A5 79 LDA I+HI + 9786 7C16 45 77 EOR VALUE+HI + 9787 7C18 10 09 BPL SCMP + 9788 7C1A A5 79 LDA I+HI + 9789 7C1C C5 77 CMP VALUE+HI + 9790 7C1E 90 42 BCC PGOOD + 9791 7C20 4C 2F 44 JMP PREDF + 9792 + 9793 7C23 A5 77 SCMP: LDA VALUE+HI + 9794 7C25 C5 79 CMP I+HI + 9795 7C27 D0 04 BNE SCEX + 9796 7C29 A5 76 LDA VALUE+LO + 9797 7C2B C5 78 CMP I+LO + Wed Jun 7 1989 12:04 Page 148 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9798 7C2D 90 33 SCEX: BCC PGOOD + 9799 7C2F 4C 2F 44 JMP PREDF + 9800 + 9801 + 9802 ; --- + 9803 ; IN? + 9804 ; --- + 9805 ; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? + 9806 7C32 ZIN: + 9807 7C32 A5 63 LDA ARG1+LO + 9808 7C34 A6 64 LDX ARG1+HI + 9809 7C36 20 F1 94 JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [FPC] + 9810 7C39 A9 06 LDA #6 ; POINT TO "LOC" SLOT + 9811 7C3B 20 E3 8F jsr ADDFPC ; and point to it + 9812 7C3E 20 5B 92 jsr FETCHB ; well? + 9813 7C41 C5 66 CMP ARG2+HI ; IS IT THERE? + 9814 7C43 D0 0A BNE PBAD ; NO + 9815 7C45 20 C3 8F jsr NEXTFPC ; point to lo part + 9816 7C48 20 5B 92 jsr FETCHB ; and get it + 9817 7C4B C5 65 CMP ARG2+LO + 9818 7C4D F0 13 BEQ PGOOD ; YES, SUCCEED + 9819 7C4F 4C 2F 44 PBAD: JMP PREDF ; TOO BAD, CHUM ... + 9820 + 9821 + 9822 ; ---- + 9823 ; BTST + 9824 ; ---- + 9825 ; IS EVERY "ON" BIT IN [ARG1] + 9826 ; ALSO "ON" IN [ARG2]? + 9827 + 9828 7C52 A5 65 ZBTST: LDA ARG2+LO ; FIRST CHECK LSBS + 9829 7C54 25 63 AND ARG1+LO + 9830 7C56 C5 65 CMP ARG2+LO ; LSBS MATCH? + 9831 7C58 D0 F5 BNE PBAD ; NO, EXIT NOW + 9832 7C5A A5 66 LDA ARG2+HI ; ELSE CHECK MSBS + 9833 7C5C 25 64 AND ARG1+HI + 9834 7C5E C5 66 CMP ARG2+HI ; MATCHED? + 9835 7C60 D0 ED BNE PBAD ; SORRY ... + 9836 7C62 PGOOD: + 9837 7C62 4C 3B 44 JMP PREDS + 9838 + 9839 + 9840 ; --- + 9841 ; BOR + 9842 ; --- + 9843 ; RETURN [ARG1] "OR" [ARG2] + 9844 + 9845 7C65 A5 63 ZBOR: LDA ARG1+LO + 9846 7C67 05 65 ORA ARG2+LO + 9847 7C69 AA TAX + 9848 7C6A A5 64 LDA ARG1+HI + 9849 7C6C 05 66 ORA ARG2+HI + 9850 + 9851 ; FALL THROUGH ... + 9852 + 9853 + 9854 ; --------------------- + 9855 ; RETURN VALUE IN [X/A] + 9856 ; --------------------- + 9857 + 9858 7C6E 86 76 VEXIT: STX VALUE+LO + 9859 7C70 85 77 STA VALUE+HI + 9860 7C72 4C E1 43 JMP PUTVAL + 9861 + 9862 + 9863 ; ---- + 9864 ; BAND + 9865 ; ---- + 9866 ; RETURN [ARG1] "AND" [ARG2] + 9867 + 9868 7C75 A5 63 ZBAND: LDA ARG1+LO + 9869 7C77 25 65 AND ARG2+LO + 9870 7C79 AA TAX + 9871 7C7A A5 64 LDA ARG1+HI + 9872 7C7C 25 66 AND ARG2+HI + Wed Jun 7 1989 12:04 Page 149 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9873 7C7E 4C 6E 7C JMP VEXIT + 9874 + 9875 + 9876 ; ----- + 9877 ; FSET? + 9878 ; ----- + 9879 ; IS FLAG [ARG2] SET IN OBJECT [ARG1]? + 9880 + 9881 7C81 20 80 95 ZFSETP: JSR FLAGSU ; GET BITS INTO [K] AND [J] + 9882 7C84 A5 7D LDA K+HI ; DO MSBS + 9883 7C86 25 7B AND J+HI + 9884 7C88 85 7D STA K+HI + 9885 7C8A A5 7C LDA K+LO ; DO LSBS + 9886 7C8C 25 7A AND J+LO + 9887 7C8E 05 7D ORA K+HI ; ANY BITS ON? + 9888 7C90 D0 D0 BNE PGOOD ; TARGET BIT MUST BE ON + 9889 7C92 4C 2F 44 JMP PREDF + 9890 + 9891 + 9892 ; ---- + 9893 ; FSET + 9894 ; ---- + 9895 ; SET FLAG [ARG2] IN OBJECT [ARG1] + 9896 + 9897 7C95 ZFSET: + 9898 7C95 20 80 95 JSR FLAGSU ; GET BITS INTO [K] & [J], ADDR IN [FPC] + 9899 ; + 9900 ; now, copy from FPC to SPC for stashing away + 9901 ; + 9902 7C98 20 78 90 jsr FP2SP ; okay, done it + 9903 7C9B A5 7D lda K+HI ; FIRST DO MSBS + 9904 7C9D 05 7B ora J+HI + 9905 7C9F 20 3A 92 jsr STASHB + 9906 7CA2 20 A3 8F jsr NEXTSPC + 9907 7CA5 A5 7C lda K+LO ; THEN LSBS + 9908 7CA7 05 7A ora J+LO + 9909 7CA9 20 3A 92 jsr STASHB + 9910 7CAC 60 rts + 9911 + 9912 + 9913 ; ------ + 9914 ; FCLEAR + 9915 ; ------ + 9916 ; CLEAR FLAG [ARG2] IN OBJECT [ARG1] + 9917 + 9918 7CAD ZFCLR: + 9919 7CAD 20 80 95 jsr FLAGSU ; GETS BITS INTO [J] & [K], ADDR IN [FPC] + 9920 ; + 9921 ; now, copy from FPC to SPC for stashing away + 9922 ; + 9923 7CB0 20 78 90 jsr FP2SP ; okey dokey + 9924 + 9925 7CB3 A5 7B lda J+HI ; FETCH MSB + 9926 7CB5 49 FF eor #$FF ; COMPLEMENT IT + 9927 7CB7 25 7D and K+HI ; RUB OUT FLAG + 9928 7CB9 20 3A 92 jsr STASHB ; and save it + 9929 7CBC 20 A3 8F jsr NEXTSPC ; point to lo part + 9930 7CBF A5 7A lda J+LO ; SAME FOR LSB + 9931 7CC1 49 FF eor #$FF + 9932 7CC3 25 7C and K+LO + 9933 7CC5 20 3A 92 jsr STASHB ; and show it to the world + 9934 7CC8 60 rts + 9935 + 9936 + 9937 ; --- + 9938 ; SET + 9939 ; --- + 9940 ; SET VARIABLE [ARG1] EQUAL TO [ARG2] + 9941 + 9942 7CC9 A5 65 ZSET: LDA ARG2+LO ; MOVE THE VALUE + 9943 7CCB 85 76 STA VALUE+LO ; INTO [VALUE] + 9944 7CCD A5 66 LDA ARG2+HI + 9945 7CCF 85 77 STA VALUE+HI + 9946 7CD1 A5 63 LDA ARG1+LO ; GET VARIABLE ID + 9947 7CD3 4C C7 43 JMP VARPUT ; AND CHANGE THE VARIABLE + Wed Jun 7 1989 12:04 Page 150 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9948 + 9949 + 9950 ; ---- + 9951 ; MOVE + 9952 ; ---- + 9953 ; MOVE OBJECT [ARG1] INTO OBJECT [ARG2] + 9954 ; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + 9955 + 9956 7CD6 ZMOVE: + 9957 7CD6 20 63 7A jsr ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS + 9958 ; + 9959 ; Make [ARG1] be first in [ARG2]'s chain. + 9960 ; + 9961 7CD9 A5 65 lda ARG2+LO + 9962 7CDB A6 66 ldx ARG2+HI ; Get parent's address + 9963 7CDD 20 F1 94 jsr OBJLOC ; into [FPC] + 9964 7CE0 A9 0A lda #10 ; point to FIRST slot + 9965 7CE2 20 E3 8F jsr ADDFPC ; okay + 9966 7CE5 20 5B 92 jsr FETCHB ; get old first one (MSB) + 9967 7CE8 85 7D sta K+HI ; save it + 9968 7CEA 20 C3 8F jsr NEXTFPC ; point to next part + 9969 7CED 20 5B 92 jsr FETCHB ; and get it + 9970 7CF0 85 7C sta K+LO ; okay, saved + 9971 7CF2 20 78 90 jsr FP2SP ; make FPC == SPC + 9972 ; + 9973 ; now make object [ARG1] be first in object [ARG2] + 9974 ; SPC is currently pointing to LSB of [ARG2]'s FIRST slot + 9975 ; + 9976 7CF5 A5 63 lda ARG1+LO ; stash away low part first + 9977 7CF7 20 3A 92 jsr STASHB ; stashed + 9978 7CFA 20 53 90 jsr PREVSPC ; point to high part + 9979 7CFD A5 64 lda ARG1+HI ; get hi part of source + 9980 7CFF 20 3A 92 jsr STASHB ; save it + 9981 ; + 9982 ; now point to object [ARG1] to update its slots + 9983 ; + 9984 7D02 A6 64 ldx ARG1+HI ; put hi part here + 9985 7D04 A5 63 lda ARG1+LO ; and lo part here for OBJLOC + 9986 7D06 20 F1 94 jsr OBJLOC ; get me the SOURCE of all confusion + 9987 7D09 A9 06 lda #6 ; point to LOC slot + 9988 7D0B 20 E3 8F jsr ADDFPC ; and now FPC points there + 9989 7D0E 20 78 90 jsr FP2SP ; now make it the STASH pointer + 9990 ; + 9991 ; update [ARG1]s LOC pointer to be [ARG2] + 9992 ; SPC points to LOC slot + 9993 ; + 9994 7D11 A5 66 lda ARG2+HI ; get PARENT number + 9995 7D13 20 3A 92 jsr STASHB ; and save it in LOC + 9996 7D16 20 A3 8F jsr NEXTSPC ; and point to LSB of LOC + 9997 7D19 A5 65 lda ARG2+LO ; got parent's lowness + 9998 7D1B 20 3A 92 jsr STASHB ; and saved it in ARG1 + 9999 ; +10000 ; Move old FIRST object and make it [ARG1]s NEXT +10001 ; now SPC points to [ARG1]s NEXT slot +10002 ; +10003 7D1E 20 A3 8F jsr NEXTSPC ; point to MSB of NEXT +10004 7D21 A5 7D lda K+HI ; get old FIRST one +10005 7D23 20 3A 92 jsr STASHB ; and save it +10006 7D26 20 A3 8F jsr NEXTSPC ; and point to LSB now +10007 7D29 A5 7C lda K+LO ; get LSB of this +10008 7D2B 20 3A 92 jsr STASHB ; saved +10009 7D2E 60 rts +10010 +10011 ; --- +10012 ; GET +10013 ; --- +10014 ; RETURN ITEM [ARG2] IN WORD-TABLE [ARG1] +10015 +10016 7D2F ZGET: +10017 7D2F 20 46 7D JSR WCALC ; CALC ADDRESS +10018 7D32 20 0E 92 JSR GETBYT ; GET 1ST BYTE (MSB) +10019 7D35 85 77 DOGET: STA VALUE+HI ; SAVE MSB +10020 7D37 20 0E 92 JSR GETBYT ; GET LSB +10021 7D3A 85 76 STA VALUE+LO ; SAVE AND +10022 7D3C 4C E1 43 jmp PUTVAL ; HAND IT OVER + Wed Jun 7 1989 12:04 Page 151 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10023 +10024 +10025 ; ---- +10026 ; GETB +10027 ; ---- +10028 ; RETURN ITEM [ARG2] IN BYTE-TABLE AT [ARG1] +10029 +10030 7D3F ZGETB: +10031 7D3F 20 4A 7D JSR BCALC +10032 7D42 A9 00 LDA #0 +10033 7D44 F0 EF BEQ DOGET ; [A] = 0, SO CLEAR MSB OF [VALUE] +10034 +10035 +10036 ; -------------------- +10037 ; CALC TABLE ADDRESSES +10038 ; -------------------- +10039 ; WORD-ALIGNED ENTRY +10040 +10041 7D46 WCALC: +10042 7D46 06 65 ASL ARG2+LO ; WORD-ALIGN FOR +10043 7D48 26 66 ROL ARG2+HI ; WORD ACCESS +10044 ; +10045 ; BYTE-ALIGNED ENTRY +10046 ; +10047 7D4A BCALC: +10048 7D4A A5 65 LDA ARG2+LO ; ADD BASE ADDR OF TABLE +10049 7D4C 18 CLC ; TO ITEM +10050 7D4D 65 63 ADC ARG1+LO ; INDEX +10051 7D4F 85 86 STA MPCL +10052 7D51 A5 66 LDA ARG2+HI ; SAME FOR MSBS +10053 7D53 65 64 ADC ARG1+HI +10054 7D55 85 87 STA MPCM +10055 7D57 A9 00 LDA #0 +10056 7D59 69 00 ADC #0 ; PICK UP CARRY FROM MPCM +10057 7D5B 85 88 STA MPCH ; TO GET TOP BIT +10058 7D5D 4C 85 90 JMP VLDMPC +10059 +10060 +10061 ; ---- +10062 ; GETP +10063 ; ---- +10064 ; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +10065 ; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 +10066 +10067 7D60 ZGETP: +10068 7D60 20 2C 95 jsr PROPB ; set up FPC +10069 7D63 GETP1: +10070 7D63 20 57 95 jsr PROPN ; GET ID OF PROP TBL +10071 7D66 C5 65 cmp ARG2+LO ; Compare PROP ID +10072 7D68 F0 30 beq GETP3 ; FOUND IT +10073 7D6A 90 06 bcc GETP2 ; NOT THERE +10074 7D6C 20 76 95 jsr PROPNX ; GET NEXT PROP, ALIGN [FPC] TO IT +10075 7D6F 4C 63 7D jmp GETP1 ; TRY AGAIN WITH NEXT PROP +10076 ; +10077 ; PROPERTY NOT THERE, GET DEFAULT +10078 ; +10079 7D72 GETP2: +10080 7D72 A5 65 lda ARG2+LO ; GET PROPERTY # +10081 7D74 38 sec ; ZERO-ALIGN IT +10082 7D75 E9 01 sbc #1 +10083 7D77 0A asl A ; WORD-ALIGN IT +10084 7D78 18 clc ; add in table start +10085 7D79 6D 0B 96 adc ZBEGIN+ZOBJEC+1 ; add lo part +10086 7D7C 85 8C sta FPCL ; save for fetch +10087 7D7E AD 0A 96 lda ZBEGIN+ZOBJEC ; now get hi part +10088 7D81 69 00 adc #0 ; pick up carry, if any +10089 7D83 20 7C 8F jsr SETPC ; get memory spot for this page +10090 7D86 85 8D sta FPCH ; page and +10091 7D88 84 8E sty FPCBNK ; bank +10092 7D8A 20 5B 92 jsr FETCHB ; GET MSB OF PROPERTY +10093 7D8D 85 77 sta VALUE+HI +10094 7D8F 20 C3 8F jsr NEXTFPC +10095 7D92 20 5B 92 jsr FETCHB ; DO SAME WITH LSB +10096 7D95 85 76 sta VALUE+LO +10097 7D97 4C E1 43 jmp PUTVAL ; RETURN DEFAULT IN [VALUE] + Wed Jun 7 1989 12:04 Page 152 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10098 7D9A GETP3: +10099 7D9A 20 5D 95 jsr PROPL ; GET LENGTH OF PROP INTO [A] +10100 7D9D AA tax ; save [A] +10101 7D9E 20 C3 8F jsr NEXTFPC ; MAKE [FPC] POINT TO 1ST BYTE OF PROP +10102 7DA1 E0 01 cpx #1 ; IF LENGTH =1 +10103 7DA3 F0 09 beq GETPB ; GET A BYTE PROPERTY +10104 7DA5 E0 02 cpx #2 ; IF LENGTH = 2 +10105 7DA7 F0 10 beq GETPW ; GET A WORD PROPERTY +10106 +10107 ; *** ERROR #7: PROPERTY LENGTH *** +10108 +10109 7DA9 A9 07 LDA #7 +10110 7DAB 4C 0A 52 JMP ZERROR +10111 ; +10112 ; GET A 1-BYTE PROPERTY +10113 ; +10114 7DAE GETPB: +10115 7DAE 20 5B 92 jsr FETCHB ; GET LSB INTO [A] +10116 7DB1 85 76 sta VALUE+LO ; STORE LSB +10117 7DB3 A9 00 lda #0 ; CLEAR MSB +10118 7DB5 85 77 sta VALUE+HI ; and zero it +10119 7DB7 F0 0D beq ETPEX +10120 ; +10121 ; GET A 2-BYTE PROPERTY +10122 ; +10123 7DB9 GETPW: +10124 7DB9 20 5B 92 jsr FETCHB ; GET MSB +10125 7DBC 85 77 sta VALUE+HI ; store MSB +10126 7DBE 20 C3 8F jsr NEXTFPC ; POINT TO LSB +10127 7DC1 20 5B 92 jsr FETCHB ; GET IT INTO [A] +10128 7DC4 85 76 sta VALUE+LO ; AND MSB +10129 7DC6 ETPEX: +10130 7DC6 4C E1 43 jmp PUTVAL +10131 +10132 ; ----- +10133 ; GETPT +10134 ; ----- +10135 ; RETURN POINTER TO PROP TABLE [ARG2] +10136 ; IN OBJECT [ARG1] +10137 +10138 7DC9 ZGETPT: +10139 7DC9 A5 63 lda ARG1+LO +10140 7DCB A6 64 ldx ARG1+HI ; (EZIP) +10141 7DCD 20 F1 94 jsr OBJLOC ; put location into [FPC] +10142 7DD0 A9 0C lda #12 ; get offset table pointer +10143 7DD2 20 E3 8F jsr ADDFPC ; and point to it +10144 7DD5 20 5B 92 jsr FETCHB ; get MSB of table pointer +10145 7DD8 48 pha ; save page +10146 7DD9 20 C3 8F jsr NEXTFPC ; point to LSB +10147 7DDC 20 5B 92 jsr FETCHB ; and get it +10148 7DDF 85 8C sta FPCL ; and save it +10149 7DE1 68 pla ; get page address back +10150 7DE2 20 7C 8F jsr SETPC ; and absolutize it +10151 7DE5 85 8D sta FPCH ; and save page +10152 7DE7 84 8E sty FPCBNK ; and bank +10153 7DE9 20 5B 92 jsr FETCHB ; GET LENGTH OF SHORT DESC +10154 7DEC 0A asl A ; WORD-ALIGN IT +10155 7DED A8 tay ; now point to just past it +10156 7DEE C8 iny ; thank you +10157 7DEF 98 tya ; for adding +10158 7DF0 20 E3 8F jsr ADDFPC ; and POINT JUST PAST THE DESCRIPTION +10159 7DF3 GETPT1: +10160 7DF3 20 57 95 jsr PROPN ; get prop ID +10161 7DF6 C5 65 cmp ARG2+LO ; CHECK ID +10162 7DF8 F0 0B beq GETPT2 +10163 7DFA B0 03 bcs DDD ; .GE. so check some more +10164 7DFC 4C 33 7E jmp DORET ; BEYOND IT, SO NOT THERE +10165 7DFF DDD: +10166 7DFF 20 76 95 jsr PROPNX ; point to next one +10167 7E02 4C F3 7D jmp GETPT1 ; next please +10168 7E05 GETPT2: +10169 7E05 20 5D 95 jsr PROPL ; get the length of this property +10170 7E08 20 C3 8F jsr NEXTFPC ; INC TO POINT AT PROPERTY VALUE (EZIP) +10171 ; +10172 ; now subtract absolute address to get relative address for returning + Wed Jun 7 1989 12:04 Page 153 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10173 ; what a pain in the neck +10174 ; +10175 7E0B A5 8E lda FPCBNK ; check which bank we are in +10176 7E0D F0 16 beq GETPB0 ; in main bank, it's easier +10177 ; +10178 ; if in AUX bank, then we must subtract beginning of AUX mem, then +10179 ; add in size of MAIN bank +10180 ; +10181 7E0F A5 8D lda FPCH ; get page +10182 7E11 C9 D0 cmp #>Z3BEGIN ; in part 2 of aux? +10183 7E13 B0 08 bcs GETPB3 ; ayyup +10184 7E15 38 sec ; and subtract +10185 7E16 E9 40 sbc #>Z2BEGIN ; first page in aux +10186 7E18 18 clc ; now add in how many pages in main +10187 7E19 69 29 adc #P2PAGE ; now we have relative start +10188 7E1B D0 0D bne GETP15 ; JUMP to putval +10189 7E1D GETPB3: +10190 7E1D 38 sec ; and subtract +10191 7E1E E9 D0 sbc #>Z3BEGIN ; first page in aux, part 2 +10192 7E20 18 clc ; now add in how many pages in main +10193 7E21 69 A8 adc #P3PAGE ; now we have relative start +10194 7E23 D0 05 bne GETP15 ; jump to putval +10195 7E25 GETPB0: +10196 7E25 A5 8D lda FPCH ; get page in main mem +10197 7E27 38 sec ; and then subtract +10198 7E28 E9 96 sbc #>ZBEGIN ; start of main mem +10199 7E2A GETP15: +10200 7E2A 85 77 sta VALUE+HI ; save hi part for returning +10201 7E2C A5 8C lda FPCL ; and just save lo part +10202 7E2E 85 76 sta VALUE+LO ; okay? +10203 7E30 4C E1 43 jmp PUTVAL ; AND RETURN +10204 7E33 DORET: +10205 7E33 4C DA 43 jmp RET0 ; ELSE RETURN A ZERO +10206 +10207 +10208 ; ----- +10209 ; NEXTP +10210 ; ----- +10211 ; RETURN INDEX # OF PROP FOLLOWING PROP [ARG2] IN OBJECT [AR +10212 ; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO +10213 +10214 7E36 ZNEXTP: +10215 7E36 20 2C 95 JSR PROPB ; ALIGN [FPC] AT PROPERTY TBL'S 1ST ENTRY +10216 7E39 A5 65 LDA ARG2+LO ; IF [ARG2]=0 +10217 7E3B F0 12 BEQ NXTP3 ; RETURN "FIRST" SLOT +10218 7E3D NXTP1: +10219 7E3D 20 57 95 JSR PROPN ; FETCH PROPERTY # +10220 7E40 C5 65 CMP ARG2+LO ; COMPARE TO TARGET # +10221 7E42 F0 08 BEQ NXTP2 ; FOUND IT! +10222 7E44 90 ED BCC DORET ; LAST PROP, SO RETURN ZERO +10223 7E46 20 76 95 JSR PROPNX ; ELSE TRY NEXT PROPERTY (EZIP) +10224 7E49 4C 3D 7E JMP NXTP1 +10225 7E4C 20 76 95 NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +10226 7E4F 20 57 95 NXTP3: JSR PROPN ; GET THE PROPERTY # +10227 7E52 A2 00 LDX #0 ; FOR PUTBYT (EZIP) +10228 7E54 4C DD 43 JMP PUTBYT ; AND RETURN IT +10229 +10230 +10231 ; --- +10232 ; ADD +10233 ; --- +10234 ; RETURN [ARG1] + [ARG2] +10235 +10236 7E57 A5 63 ZADD: LDA ARG1+LO ; ADD LSBS +10237 7E59 18 CLC +10238 7E5A 65 65 ADC ARG2+LO +10239 7E5C AA TAX ; SAVE LSB HERE +10240 7E5D A5 64 LDA ARG1+HI ; ADD MSBS +10241 7E5F 65 66 ADC ARG2+HI +10242 7E61 4C 6E 7C JMP VEXIT +10243 +10244 +10245 ; --- +10246 ; SUB +10247 ; --- + Wed Jun 7 1989 12:04 Page 154 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10248 ; RETURN [ARG1] - [ARG2] +10249 +10250 7E64 A5 63 ZSUB: LDA ARG1+LO ; SUBTRACT LSBS +10251 7E66 38 SEC +10252 7E67 E5 65 SBC ARG2+LO +10253 7E69 AA TAX ; SAVE LSB HERE +10254 7E6A A5 64 LDA ARG1+HI ; SUBTRACT MSBS +10255 7E6C E5 66 SBC ARG2+HI +10256 7E6E 4C 6E 7C JMP VEXIT ; EXIT WITH [X]=LSB, [A]=MSB +10257 +10258 +10259 ; --- +10260 ; MUL +10261 ; --- +10262 ; RETURN [ARG1] * [ARG2] +10263 +10264 7E71 20 57 7F ZMUL: JSR MINIT ; INIT THINGS +10265 7E74 6E 66 5B ZMLOOP: ROR MTEMP+HI +10266 7E77 6E 65 5B ROR MTEMP+LO +10267 7E7A 66 66 ROR ARG2+HI +10268 7E7C 66 65 ROR ARG2+LO +10269 7E7E 90 11 BCC ZMNEXT +10270 7E80 A5 63 LDA ARG1+LO +10271 7E82 18 CLC +10272 7E83 6D 65 5B ADC MTEMP+LO +10273 7E86 8D 65 5B STA MTEMP+LO +10274 7E89 A5 64 LDA ARG1+HI +10275 7E8B 6D 66 5B ADC MTEMP+HI +10276 7E8E 8D 66 5B STA MTEMP+HI +10277 7E91 CA ZMNEXT: DEX +10278 7E92 10 E0 BPL ZMLOOP +10279 7E94 A6 65 LDX ARG2+LO ; PUT LSB OF PRODUCT +10280 7E96 A5 66 LDA ARG2+HI ; AND MSB +10281 7E98 4C 6E 7C JMP VEXIT ; WHERE "VEXIT" EXPECTS THEM +10282 +10283 +10284 ; --- +10285 ; DIV +10286 ; --- +10287 ; RETURN QUOTIENT OF [ARG1] / [ARG2] +10288 +10289 7E9B 20 B3 7E ZDIV: JSR DIVIDE +10290 7E9E AE 60 6C LDX QUOT+LO +10291 7EA1 AD 61 6C LDA QUOT+HI +10292 7EA4 4C 6E 7C JMP VEXIT +10293 +10294 +10295 ; --- +10296 ; MOD +10297 ; --- +10298 ; RETURN REMAINDER OF [ARG1] / [ARG2] +10299 +10300 7EA7 20 B3 7E ZMOD: JSR DIVIDE +10301 7EAA AE 62 6C LDX REMAIN+LO ; FETCH THE REMAINDER +10302 7EAD AD 63 6C LDA REMAIN+HI ; IN [REMAIN] +10303 7EB0 4C 6E 7C JMP VEXIT ; AND RETURN IT +10304 +10305 +10306 ; --------------- +10307 ; SIGNED DIVISION +10308 ; --------------- +10309 ; ENTRY: DIVIDEND IN [ARG1], DIVISOR IN [ARG2] +10310 ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] +10311 +10312 7EB3 DIVIDE: +10313 7EB3 A5 64 LDA ARG1+HI ; SIGN OF REMAINDER +10314 7EB5 8D 65 6C STA RSIGN ; IS THE SIGN OF THE DIVIDEND +10315 7EB8 45 66 EOR ARG2+HI ; SIGN OF QUOTIENT IS POSITIVE +10316 7EBA 8D 64 6C STA QSIGN ; IF SIGNS OF TERMS ARE THE SAME +10317 7EBD A5 63 LDA ARG1+LO ; MOVE [ARG1] TO [QUOT] +10318 7EBF 8D 60 6C STA QUOT+LO +10319 7EC2 A5 64 LDA ARG1+HI +10320 7EC4 8D 61 6C STA QUOT+HI ; IF DIVIDEND IS POSITIVE +10321 7EC7 10 03 BPL ABSDIV ; MOVE DIVISOR +10322 7EC9 20 FD 7E JSR ABQUOT ; ELSE CALC ABS(DIVIDEND) FIRST + Wed Jun 7 1989 12:04 Page 155 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10323 7ECC A5 65 ABSDIV: LDA ARG2+LO +10324 7ECE 8D 62 6C STA REMAIN+LO +10325 7ED1 A5 66 LDA ARG2+HI +10326 7ED3 8D 63 6C STA REMAIN+HI ; IF REMAINDER IS POSITIVE +10327 7ED6 10 03 BPL GODIV ; WE'RE READY TO DIVIDE +10328 7ED8 20 EB 7E JSR ABREM ; ELSE CALC ABS(DIVISOR) +10329 7EDB 20 0F 7F GODIV: JSR UDIV ; DO UNSIGNED DIVIDE +10330 7EDE AD 64 6C LDA QSIGN ; SHOULD QUOTIENT BE FLIPPED? +10331 7EE1 10 03 BPL RFLIP ; NO, TEST REMAINDER +10332 7EE3 20 FD 7E JSR ABQUOT ; ELSE GET ABSOLUTE VALUE +10333 7EE6 AD 65 6C RFLIP: LDA RSIGN ; SHOULD EMAINDER BE FLIPPED? +10334 7EE9 10 11 BPL DIVEX ; NO, WE'RE DONE +10335 +10336 ; ELSE FALL THROUGH ... +10337 +10338 +10339 ; ---------------- +10340 ; CALC ABS(REMAIN) +10341 ; ---------------- +10342 +10343 7EEB A9 00 ABREM: LDA #0 +10344 7EED 38 SEC +10345 7EEE ED 62 6C SBC REMAIN+LO +10346 7EF1 8D 62 6C STA REMAIN+LO +10347 7EF4 A9 00 LDA #0 +10348 7EF6 ED 63 6C SBC REMAIN+HI +10349 7EF9 8D 63 6C STA REMAIN+HI +10350 7EFC 60 DIVEX: RTS +10351 +10352 +10353 ; -------------- +10354 ; CALC ABS(QUOT) +10355 ; -------------- +10356 +10357 7EFD A9 00 ABQUOT: LDA #0 +10358 7EFF 38 SEC +10359 7F00 ED 60 6C SBC QUOT+LO +10360 7F03 8D 60 6C STA QUOT+LO +10361 7F06 A9 00 LDA #0 +10362 7F08 ED 61 6C SBC QUOT+HI +10363 7F0B 8D 61 6C STA QUOT+HI +10364 7F0E 60 RTS +10365 +10366 +10367 ; ----------------- +10368 ; UNSIGNED DIVISION +10369 ; ----------------- +10370 ; ENTRY: DIVIDEND IN [QUOT], DIVISOR IN [REMAIN] +10371 ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] +10372 +10373 7F0F UDIV: +10374 7F0F AD 62 6C LDA REMAIN+LO ; CHECK [REMAIN] +10375 7F12 0D 63 6C ORA REMAIN+HI ; BEFORE PROCEEDING +10376 7F15 F0 3B BEQ DIVERR ; CAN'T DIVIDE BY ZERO! +10377 7F17 20 57 7F JSR MINIT ; SET IT ALL UP +10378 7F1A 2E 60 6C UDLOOP: ROL QUOT+LO +10379 7F1D 2E 61 6C ROL QUOT+HI +10380 7F20 2E 65 5B ROL MTEMP+LO +10381 7F23 2E 66 5B ROL MTEMP+HI +10382 7F26 AD 65 5B LDA MTEMP+LO +10383 7F29 38 SEC +10384 7F2A ED 62 6C SBC REMAIN+LO +10385 7F2D A8 TAY ; SAVE HERE +10386 7F2E AD 66 5B LDA MTEMP+HI +10387 7F31 ED 63 6C SBC REMAIN+HI +10388 7F34 90 06 BCC UDNEXT +10389 7F36 8C 65 5B STY MTEMP+LO +10390 7F39 8D 66 5B STA MTEMP+HI +10391 7F3C CA UDNEXT: DEX +10392 7F3D D0 DB BNE UDLOOP +10393 7F3F 2E 60 6C ROL QUOT+LO ; SHIFT LAST CARRY FOR QUOTIENT +10394 7F42 2E 61 6C ROL QUOT+HI +10395 7F45 AD 65 5B LDA MTEMP+LO ; MOVE REMAINDER +10396 7F48 8D 62 6C STA REMAIN+LO ; INTO [REMAIN] +10397 7F4B AD 66 5B LDA MTEMP+HI + Wed Jun 7 1989 12:04 Page 156 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10398 7F4E 8D 63 6C STA REMAIN+HI +10399 7F51 60 RTS +10400 +10401 ; *** ERROR #8: DIVISION BY ZERO *** +10402 +10403 7F52 A9 08 DIVERR: LDA #8 +10404 7F54 4C 0A 52 JMP ZERROR +10405 +10406 +10407 ; --------- +10408 ; MATH INIT +10409 ; --------- +10410 +10411 7F57 A2 10 MINIT: LDX #16 ; INIT LOOPING INDEX +10412 7F59 A9 00 LDA #0 +10413 7F5B 8D 65 5B STA MTEMP+LO ; CLEAR TEMP +10414 7F5E 8D 66 5B STA MTEMP+HI ; REGISTER +10415 7F61 18 CLC ; AND CARRY +10416 7F62 60 RTS +10417 +10418 +10419 ; ----- +10420 ; THROW +10421 ; ----- +10422 +10423 7F63 ZTHROW: +10424 7F63 A5 65 lda ARG2+LO ; check to see if we are ready to do return +10425 7F65 CD 7A 6C cmp OLDZSP+LO +10426 7F68 D0 07 bne ZTHLOOP ; nope, keep unwinding the stack +10427 7F6A A5 66 lda ARG2+HI +10428 7F6C CD 7B 6C cmp OLDZSP+HI ; have we found the right frame yet? +10429 7F6F F0 06 beq ZTHDO ; yes +10430 7F71 ZTHLOOP: +10431 7F71 20 5B 7B jsr ZRET ; do another return +10432 7F74 4C 63 7F jmp ZTHROW ; and try again +10433 7F77 ZTHDO: +10434 7F77 A5 65 lda ARG2+LO ; SET ZSTACK POINTER +10435 7F79 8D 7A 6C sta OLDZSP+LO ; UP FOR ZRET +10436 7F7C A5 66 lda ARG2+HI +10437 7F7E 8D 7B 6C sta OLDZSP+HI +10438 7F81 4C 5B 7B jmp ZRET +10439 +10440 7F84 END +10441 +10442 7F84 INCLUDE OPSX.ASM +10443 PAGE + Wed Jun 7 1989 12:04 Page 157 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10444 7F84 STTL "--- X-OPS ---" +10445 +10446 +10447 ; ------ +10448 ; EQUAL? +10449 ; ------ +10450 ; IS [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? +10451 +10452 7F84 ZEQUAL: +10453 7F84 C6 62 DEC NARGS ; DOUBLE-CHECK # ARGS +10454 7F86 A5 63 LDA ARG1+LO ; FETCH LSB +10455 7F88 A6 64 LDX ARG1+HI ; AND MSB OF [ARG1] +10456 7F8A C5 65 CMP ARG2+LO ; TEST LSB OF [ARG2] +10457 7F8C D0 04 BNE TRY2 ; NO GOOD, LOOK FOR ANOTHER ARG +10458 7F8E E4 66 CPX ARG2+HI ; ELSE TRY MSB OF [ARG2] +10459 7F90 F0 18 BEQ EQOK ; MATCHED! +10460 7F92 C6 62 TRY2: DEC NARGS ; OUT OF ARGS YET? +10461 7F94 F0 17 BEQ EQBAD ; YES, WE FAILED +10462 7F96 C5 67 CMP ARG3+LO ; TRY LSB OF [ARG3] +10463 7F98 D0 04 BNE TRY3 ; NO GOOD, LOOK FOR ANOTHER ARG +10464 7F9A E4 68 CPX ARG3+HI ; HOW ABOUT MSB OF [ARG3]? +10465 7F9C F0 0C BEQ EQOK ; YAY! +10466 7F9E C6 62 TRY3: DEC NARGS ; OUT OF ARGS YET? +10467 7FA0 F0 0B BEQ EQBAD ; IF NOT ... +10468 7FA2 C5 69 CMP ARG4+LO ; TRY [ARG4] +10469 7FA4 D0 07 BNE EQBAD ; SORRY, CHUM +10470 7FA6 E4 6A CPX ARG4+HI ; MSB MATCHED? +10471 7FA8 D0 03 BNE EQBAD ; TOO BAD +10472 +10473 7FAA 4C 3B 44 EQOK: JMP PREDS ; FINALLY MATCHED! +10474 +10475 7FAD 4C 2F 44 EQBAD: JMP PREDF ; FAILURE (SNIFF!) +10476 +10477 +10478 ; ---------------------------- +10479 ; ICALL,ICALL1, ICALL2, IXCALL +10480 ; ---------------------------- +10481 +10482 7FB0 ZICALL: +10483 7FB0 ZICLL1: +10484 7FB0 ZICLL2: +10485 7FB0 A9 01 ZIXCLL: LDA #1 ; SET FLAG FOR RETURNLESS CALL +10486 7FB2 8D 64 5B STA IRET +10487 7FB5 D0 05 BNE IENTR ; JMP OVER NORMAL SETTING +10488 +10489 +10490 ; ------------------- +10491 ; XCALL, CALL1, CALL2 +10492 ; ------------------- +10493 +10494 ZXCALL: ; DROP THROUGH +10495 ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +10496 7FB7 ZCALL2: +10497 +10498 ; ---- +10499 ; CALL +10500 ; ---- +10501 ; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +10502 ; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +10503 ; ([ARG5]-[ARG8] FOR XCALL (EZIP)) +10504 +10505 7FB7 A9 00 ZCALL: LDA #0 +10506 7FB9 8D 64 5B STA IRET ; SET FLAG TO RETURN SOMETHING +10507 7FBC A5 63 IENTR: LDA ARG1+LO +10508 7FBE 05 64 ORA ARG1+HI ; IS CALL ADDRESS ZERO? +10509 7FC0 D0 0B BNE DOCALL ; NO, CONTINUE +10510 7FC2 AD 64 5B LDA IRET ; any ret value? +10511 7FC5 F0 01 BEQ Ij ; yes, so return a zero +10512 +10513 7FC7 60 RTS ; otherwise, just end +10514 7FC8 Ij: +10515 7FC8 A2 00 LDX #0 +10516 7FCA 4C DD 43 JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +10517 7FCD AE 7A 6C DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER +10518 7FD0 AD 7B 6C LDA OLDZSP+HI + Wed Jun 7 1989 12:04 Page 158 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +10519 7FD3 20 9B 43 JSR PUSHXA +10520 7FD6 A5 80 LDA ZPCL ; AND LSB OF [ZPC] +10521 7FD8 AE 64 5B LDX IRET ; AND RETURN FLAG +10522 7FDB 20 9B 43 JSR PUSHXA ; ON THE Z-STACK +10523 7FDE A6 81 LDX ZPCM ; SAVE MIDDLE 8 BITS +10524 7FE0 A5 82 LDA ZPCH ; AND TOP BIT OF [ZPC] +10525 7FE2 20 9B 43 JSR PUSHXA ; AS WELL +10526 +10527 ; FORM 16-BIT ADDRESS FROM [ARG1] +10528 +10529 7FE5 A9 00 LDA #0 +10530 7FE7 06 63 ASL ARG1+LO ; MULTIPLY [ARG1] +10531 7FE9 26 64 ROL ARG1+HI ; (BY 2) +10532 7FEB 2A ROL A ; >BIT INTO [A] +10533 7FEC 06 63 ASL ARG1+LO ; BY 4 (EZIP) +10534 7FEE 26 64 ROL ARG1+HI +10535 7FF0 2A ROL A +10536 7FF1 85 82 STA ZPCH ; NEW >BIT OF [ZPC] +10537 7FF3 A5 64 LDA ARG1+HI ; GET NEW 0, just ignore! +10928 826E 05 67 ORA ARG3+LO +10929 8270 F0 79 BEQ INTNF ; SAY NOT FOUND +10930 +10931 8272 A5 62 LDA NARGS ; IS THERE A RECORD SPEC? +10932 8274 C9 04 CMP #4 +10933 8276 F0 04 BEQ SET4 +10934 8278 A9 82 SETDEF: LDA #130 ; NO, SET DEFAULT +10935 827A 85 69 STA ARG4+LO +10936 +10937 827C A5 69 SET4: LDA ARG4+LO +10938 827E F0 F8 BEQ SETDEF ; GO BACK AND GET VALUE +10939 8280 A9 00 LDA #0 ; COMPARE BYTE OR WORD? +10940 8282 06 69 ASL ARG4+LO +10941 8284 2A ROL A ; PICK UP INDICATOR +10942 8285 46 69 LSR ARG4+LO ; CLEAR FROM RECORD LENGTH +10943 8287 8D 67 5B STA TYPE ; BYTE (0) OR WORD (1) +10944 828A AD 67 5B LDA TYPE ; SET FLAG +10945 828D D0 04 BNE SETTBL +10946 828F A5 63 LDA ARG1+LO ; IF ONLY BYTE, MOVE IT +10947 8291 85 64 STA ARG1+HI ; TO FIRST BYTE CHECKED +10948 8293 SETTBL: +10949 8293 A5 65 LDA ARG2+LO ; PICK UP TBL ADDR +10950 8295 85 86 STA MPCL +10951 8297 A5 66 LDA ARG2+HI +10952 8299 85 87 STA MPCM +10953 829B A9 00 LDA #0 +10954 829D 85 88 STA MPCH ; ONLY A WORD ADDR, SO IN 1ST 64K +10955 829F 20 85 90 JSR VLDMPC +10956 +10957 82A2 A5 86 INTLP: LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS +10958 82A4 8D 7B 00 STA VWCUR+0 +10959 82A7 A5 87 LDA MPCM +10960 82A9 8D 7C 00 STA VWCUR+1 +10961 82AC A5 88 LDA MPCH +10962 82AE 8D 7D 00 STA VWCUR+2 +10963 82B1 20 0E 92 JSR GETBYT ; GET 1ST BYTE +10964 82B4 C5 64 CMP ARG1+HI ; DOES IT = THE VALUE LOOKING FOR? +10965 82B6 D0 0C BNE INTNXT ; NO +10966 82B8 AD 67 5B LDA TYPE +10967 82BB F0 3A BEQ INTFND ; ONLY COMPARING A BYTE SO FOUND! +10968 82BD 20 0E 92 JSR GETBYT + Wed Jun 7 1989 12:04 Page 164 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +10969 82C0 C5 63 CMP ARG1+LO +10970 82C2 F0 33 BEQ INTFND ; YES, FOUND IT +10971 82C4 INTNXT: +10972 82C4 AD 7B 00 LDA VWCUR+0 ; TO MOVE UP, JUST ADD +10973 82C7 18 CLC ; OFFSET FROM START OF THIS +10974 82C8 65 69 ADC ARG4+LO ; ENTRY +10975 82CA 85 86 STA MPCL +10976 82CC 90 11 BCC INEXT0 +10977 +10978 82CE AD 7C 00 LDA VWCUR+1 ; PICK UP CARRY +10979 82D1 69 00 ADC #0 +10980 82D3 85 87 STA MPCM +10981 82D5 AD 7D 00 LDA VWCUR+2 +10982 82D8 69 00 ADC #0 +10983 82DA 85 88 STA MPCH +10984 82DC 20 85 90 JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE +10985 +10986 82DF C6 67 INEXT0: DEC ARG3+LO ; CHECKED ALL ENTRIES? +10987 82E1 D0 BF BNE INTLP +10988 82E3 A5 68 LDA ARG3+HI +10989 82E5 F0 04 BEQ INTNF +10990 82E7 C6 68 DEC ARG3+HI +10991 82E9 D0 B7 BNE INTLP +10992 +10993 82EB INTNF: +10994 82EB A9 00 LDA #0 ; 0 = NOT FOUND +10995 82ED 85 76 STA VALUE+LO +10996 82EF 85 77 STA VALUE+HI +10997 82F1 20 E1 43 JSR PUTVAL +10998 82F4 4C 2F 44 JMP PREDF ; FAILED! +10999 +11000 82F7 INTFND: +11001 82F7 AD 7B 00 LDA VWCUR+LO +11002 82FA 85 76 STA VALUE+LO ; AND SET TO RETURN THE VALUE +11003 82FC AD 7C 00 LDA VWCUR+HI +11004 82FF 85 77 STA VALUE+HI +11005 8301 20 E1 43 JSR PUTVAL ; SEND IT BACK +11006 8304 4C 3B 44 JMP PREDS ; AND SCREEM SUCCESS +11007 +11008 ; ---- +11009 ; BCOM +11010 ; ---- +11011 ; COMPLEMENT [ARG1] +11012 +11013 8307 A5 63 ZBCOM: LDA ARG1+LO +11014 8309 49 FF EOR #$FF +11015 830B 85 76 STA VALUE+LO +11016 830D A5 64 LDA ARG1+HI +11017 830F 49 FF EOR #$FF +11018 8311 85 77 STA VALUE+HI +11019 8313 4C E1 43 JMP PUTVAL +11020 +11021 +11022 ; ----- +11023 ; COPYT +11024 ; ----- +11025 +11026 8316 ZCOPYT: +11027 8316 A5 65 LDA ARG2+LO ; CHECK OUT WHAT'S TO BE DONE +11028 8318 05 66 ORA ARG2+HI +11029 831A D0 03 BNE ZC0 +11030 831C 4C CB 83 JMP CASE1 ; ZERO LENGTH BYTES OF SOURCE +11031 831F ZC0: +11032 831F A5 68 LDA ARG3+HI +11033 8321 C9 7F CMP #$7F +11034 8323 90 03 BCC CASE2 +11035 8325 4C F1 83 JMP CASE3 ; FORWARD COPY +11036 +11037 ; CASE2 - CHECK IF FORWARD OR BACKWARD COPY +11038 +11039 8328 A5 64 CASE2: LDA ARG1+HI ; IF SRC < DEST +11040 832A C5 66 CMP ARG2+HI +11041 832C 90 0D BCC CHK2 +11042 832E F0 03 BEQ ZC1 +11043 8330 4C 54 83 JMP FRWRD ; NO + Wed Jun 7 1989 12:04 Page 165 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11044 8333 A5 63 ZC1: LDA ARG1+LO +11045 8335 C5 65 CMP ARG2+LO +11046 8337 F0 02 BEQ CHK2 +11047 8339 B0 19 BCS FRWRD ; NO +11048 833B A5 63 CHK2: LDA ARG1+LO ; AND SRC + LENGTH > DEST +11049 833D 18 CLC +11050 833E 65 67 ADC ARG3+LO +11051 8340 85 78 STA I+LO +11052 8342 A5 64 LDA ARG1+HI +11053 8344 65 68 ADC ARG3+HI +11054 8346 C5 66 CMP ARG2+HI +11055 8348 90 0A BCC FRWRD ; NO +11056 834A D0 3E BNE BKWRD ; YES +11057 834C A5 78 LDA I+LO +11058 834E C5 65 CMP ARG2+LO +11059 8350 F0 02 BEQ FRWRD ; DEBUG, IF EQUAL REALLY LESS +11060 8352 B0 36 BCS BKWRD ; OVERLAPS SO DO BACKWARD COPY +11061 +11062 ; ELSE FALL THROUGH TO FORWARD COPY +11063 +11064 8354 A9 00 FRWRD: LDA #0 ; USE GETBYT CAUSE MAY BE +11065 8356 85 88 STA MPCH ; BEYOND MAIN MEMORY +11066 8358 A5 64 LDA ARG1+HI +11067 835A 85 87 STA MPCM +11068 835C A5 63 LDA ARG1+LO +11069 835E 85 86 STA MPCL +11070 8360 20 85 90 JSR VLDMPC ; AND ALIGN TO CORRECT PAGE +11071 8363 A5 65 LDA ARG2+LO +11072 8365 85 8F STA SPCL +11073 8367 A5 66 LDA ARG2+HI +11074 8369 20 7C 8F jsr SETPC ; get memory spot +11075 836C 85 90 sta SPCH ; high part +11076 836E 84 91 sty SPCBNK ; and the bank part +11077 8370 A5 67 LDA ARG3+LO +11078 8372 85 7A STA J+LO +11079 8374 A5 68 LDA ARG3+HI +11080 8376 85 7B STA J+HI +11081 8378 FRLP: +11082 8378 20 C6 44 jsr DECJ +11083 837B 90 0C bcc FRDUN ; CARRY CLEAR ON $FFFF +11084 837D 20 0E 92 jsr GETBYT +11085 8380 20 3A 92 jsr STASHB ; and save it +11086 8383 20 A3 8F jsr NEXTSPC ; and point to next one +11087 8386 4C 78 83 jmp FRLP +11088 8389 FRDUN: +11089 8389 60 rts +11090 +11091 +11092 838A BKWRD: +11093 838A A5 67 LDA ARG3+LO ; DECR 1ST TO GET CORRECT OFFSET +11094 838C 85 7A STA J+LO +11095 838E A5 68 LDA ARG3+HI +11096 8390 85 7B STA J+HI +11097 8392 20 C6 44 JSR DECJ +11098 8395 A5 63 LDA ARG1+LO ; SET TO END OF SOURCE & DEST. +11099 8397 18 CLC +11100 8398 65 7A ADC J+LO +11101 839A 85 8C sta FPCL ; set up fetch pointer +11102 839C A5 64 LDA ARG1+HI +11103 839E 65 7B ADC J+HI +11104 83A0 20 7C 8F jsr SETPC ; and get mem locations +11105 83A3 85 8D sta FPCH +11106 83A5 84 8E sty FPCBNK +11107 83A7 A5 65 LDA ARG2+LO +11108 83A9 18 CLC +11109 83AA 65 7A ADC J+LO +11110 83AC 85 8F sta SPCL ; and now set up stash pointer +11111 83AE A5 66 LDA ARG2+HI +11112 83B0 65 7B ADC J+HI +11113 83B2 20 7C 8F jsr SETPC ; and get me page/bank +11114 83B5 85 90 sta SPCH +11115 83B7 84 91 sty SPCBNK +11116 83B9 BKLP: +11117 83B9 20 5B 92 jsr FETCHB ; get byte +11118 83BC 20 3A 92 jsr STASHB ; and save it + Wed Jun 7 1989 12:04 Page 166 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11119 83BF 20 29 90 jsr PREVFPC ; going backwards +11120 83C2 20 53 90 jsr PREVSPC ; and here too +11121 83C5 20 C6 44 jsr DECJ ; RETURNS CARRY CLEAR ON $FFFF +11122 83C8 B0 EF bcs BKLP +11123 83CA BKDUN: +11124 83CA 60 RTS +11125 +11126 ; ZERO LENGTH # OF BYTES OF SOURCE +11127 +11128 83CB A5 63 CASE1: LDA ARG1+LO +11129 83CD 85 8F STA SPCL ; set stash pointer +11130 83CF A5 64 LDA ARG1+HI +11131 83D1 20 7C 8F jsr SETPC ; get page/bank +11132 83D4 85 90 sta SPCH +11133 83D6 84 91 sty SPCBNK +11134 83D8 A5 67 LDA ARG3+LO ; SET UP COUNTER +11135 83DA 85 7A STA J+LO +11136 83DC A5 68 LDA ARG3+HI +11137 83DE 85 7B STA J+HI +11138 83E0 C1LP: +11139 83E0 20 C6 44 jsr DECJ ; CARRY CLEAR WHEN J = $FFFF +11140 83E3 90 0B bcc C1DUN +11141 83E5 A9 00 lda #0 +11142 83E7 20 3A 92 jsr STASHB ; and zero it +11143 83EA 20 A3 8F jsr NEXTSPC ; and point to next one +11144 83ED 4C E0 83 jmp C1LP +11145 83F0 C1DUN: +11146 83F0 60 rts +11147 +11148 ; 2'S COMPLEMENT LENGTH (XOR + 1) THEN DO FORWARD COPY +11149 +11150 83F1 CASE3: +11151 83F1 A5 67 LDA ARG3+LO +11152 83F3 49 FF EOR #$FF +11153 83F5 85 67 STA ARG3+LO +11154 83F7 A5 68 LDA ARG3+HI +11155 83F9 49 FF EOR #$FF +11156 83FB 85 68 STA ARG3+HI +11157 83FD E6 67 INC ARG3+LO +11158 83FF D0 02 BNE GOFRWD +11159 8401 E6 68 INC ARG3+HI +11160 8403 4C 54 83 GOFRWD: JMP FRWRD +11161 +11162 +11163 ; --------- +11164 ; ASSIGNED? +11165 ; --------- +11166 +11167 +11168 8406 ZASSND: +11169 8406 A5 63 LDA ARG1+LO ; COMPARE TO # OF OPTIONALS FROM LAST CALL +11170 8408 CD 68 5B CMP ASSVLU +11171 840B 90 05 BCC DOYES ; IF LESS OR EQUAL, WAS ASSIGNED +11172 840D F0 03 BEQ DOYES +11173 840F 4C 2F 44 JMP PREDF +11174 8412 DOYES: +11175 8412 4C 3B 44 JMP PREDS +11176 +11177 +11178 ; ------------- +11179 ; LOGICAL SHIFT +11180 ; ------------- +11181 ; SHIFT ARG1, ARG2 BITS (LEFT IF ARG2 IS POS. RIGHT IF NEG.) +11182 +11183 8415 A5 63 ZSHIFT: LDA ARG1+LO ; SET UP FOR SHIFT +11184 8417 85 76 STA VALUE+LO +11185 8419 A5 64 LDA ARG1+HI +11186 841B 85 77 STA VALUE+HI +11187 841D A5 65 LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT +11188 841F C9 80 CMP #$80 +11189 8421 B0 0B BCS SRIGHT +11190 +11191 ; SHIFT LEFT +11192 +11193 8423 A8 TAY ; COUNT + Wed Jun 7 1989 12:04 Page 167 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11194 8424 06 76 SLP1: ASL VALUE+LO +11195 8426 26 77 ROL VALUE+HI +11196 8428 88 DEY +11197 8429 D0 F9 BNE SLP1 +11198 842B 4C E1 43 JMP PUTVAL ; AND RETURN THE VALUE +11199 +11200 842E 49 FF SRIGHT: EOR #$FF ; COMPLEMENT +11201 8430 A8 TAY +11202 8431 46 77 SLP2: LSR VALUE+HI ; SHIFT +11203 8433 66 76 ROR VALUE+LO +11204 8435 88 DEY +11205 8436 10 F9 BPL SLP2 +11206 8438 4C E1 43 JMP PUTVAL +11207 +11208 +11209 ; ---------------- +11210 ; ARITHMETIC SHIFT +11211 ; ---------------- +11212 ; PROPAGATING SIGN BIT ON RIGHT SHIFT +11213 +11214 843B A5 65 ZASHFT: LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT +11215 843D C9 80 CMP #$80 +11216 843F 90 D4 BCC ZSHIFT ; SAME AS LOGICAL SHIFT +11217 8441 A6 63 LDX ARG1+LO ; SET UP FOR SHIFT +11218 8443 86 76 STX VALUE+LO +11219 8445 A6 64 LDX ARG1+HI +11220 8447 86 77 STX VALUE+HI +11221 +11222 8449 49 FF EOR #$FF ; COMPLEMENT COUNT +11223 844B A8 TAY +11224 844C A5 64 ASLP2: LDA ARG1+HI +11225 844E 0A ASL A ; GET SIGN BIT +11226 844F 66 77 ROR VALUE+HI ; SHIFT +11227 8451 66 76 ROR VALUE+LO +11228 8453 88 DEY +11229 8454 10 F6 BPL ASLP2 +11230 8456 4C E1 43 JMP PUTVAL +11231 8459 +11232 ; -------- +11233 ; XPUSH +11234 ; -------- +11235 8459 ZXPUSH: +11236 8459 A5 65 lda ARG2+LO ; get me the address of the LTABLE +11237 845B 85 8C sta FPCL ; for munging with +11238 845D A5 66 lda ARG2+HI ; this is page +11239 845F 20 7C 8F jsr SETPC ; get me actual page/bank +11240 8462 85 8D sta FPCH ; set page +11241 8464 84 8E sty FPCBNK ; and bank +11242 +11243 8466 20 5B 92 jsr FETCHB ; this is hi part of counter +11244 8469 85 7B sta J+HI ; save it +11245 846B 20 C3 8F jsr NEXTFPC ; point to lo part +11246 846E 20 5B 92 jsr FETCHB ; get it +11247 8471 85 7A sta J+LO ; thanx +11248 8473 05 7B ora J+HI ; check for zero elements left +11249 8475 D0 03 bne ZXP0 ; yes, there is room at the inn +11250 +11251 8477 4C 2F 44 jmp PREDF ; no room here! +11252 847A ZXP0: +11253 847A 20 78 90 jsr FP2SP ; set up to stash back in beginning of LTABLE +11254 847D A5 7B lda J+HI ; now the MSB +11255 847F 85 7D sta K+HI ; and saved it +11256 8481 A5 7A lda J+LO ; save this +11257 8483 85 7C sta K+LO ; save it +11258 ; +11259 ; now count this one and stash it into the table +11260 ; +11261 8485 D0 02 bne ZXP1 ; nope, dec okay +11262 8487 C6 7B dec J+HI ; decrement MSB +11263 8489 ZXP1: +11264 8489 C6 7A dec J+LO ; and the LSB +11265 848B A5 7A lda J+LO ; LSB first +11266 848D 20 3A 92 jsr STASHB ; saved it +11267 8490 20 53 90 jsr PREVSPC ; point to MSB +11268 8493 A5 7B lda J+HI ; get it + Wed Jun 7 1989 12:04 Page 168 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11269 8495 20 3A 92 jsr STASHB ; saved it +11270 ; +11271 ; finally, we can save the arg into the stack +11272 ; +11273 8498 06 7C asl K+LO ; make a word offset (*2) +11274 849A 26 7D rol K+HI ; pick up carry maybe +11275 849C A5 7C lda K+LO ; add in arg offset +11276 849E 18 clc ; adding +11277 849F 65 65 adc ARG2+LO ; figger offset +11278 84A1 85 8F sta SPCL ; this goes here for stashing +11279 84A3 A5 7D lda K+HI ; now page +11280 84A5 65 66 adc ARG2+HI ; add in start of table +11281 84A7 20 7C 8F jsr SETPC ; get me memory page +11282 84AA 85 90 sta SPCH ; page +11283 84AC 84 91 sty SPCBNK ; and bank +11284 +11285 84AE A5 64 lda ARG1+HI ; push MSB +11286 84B0 20 3A 92 jsr STASHB ; saved +11287 84B3 20 A3 8F jsr NEXTSPC ; point to next one +11288 84B6 A5 63 lda ARG1+LO ; and now LSB +11289 84B8 20 3A 92 jsr STASHB ; into the stack +11290 84BB 4C 3B 44 jmp PREDS ; show we worked good +11291 ;--------- +11292 ; ZFSTACK +11293 ;--------- +11294 84BE ZFSTACK: +11295 84BE C6 62 dec NARGS ; how many args there? +11296 84C0 D0 0E bne ZFS1 ; flush ARG2 stack +11297 ; +11298 ; pop from system stack +11299 ; +11300 84C2 A5 63 lda ARG1+LO ; just add number to system counter +11301 84C4 18 clc ; adding +11302 84C5 65 AF adc ZSP+LO ; added +11303 84C7 85 AF sta ZSP+LO ; and saved +11304 84C9 A5 64 lda ARG1+HI ; get hi part +11305 84CB 65 B0 adc ZSP+HI ; add in hi part +11306 84CD 85 B0 sta ZSP+HI ; save hi part +11307 84CF 60 rts +11308 84D0 ZFS1: +11309 84D0 A5 65 lda ARG2+LO ; get LTABLE we are interested in +11310 84D2 85 8C sta FPCL ; set up FPC first +11311 84D4 A5 66 lda ARG2+HI ; and page +11312 84D6 20 7C 8F jsr SETPC ; tell me where +11313 84D9 85 8D sta FPCH ; save me where +11314 84DB 84 8E sty FPCBNK ; FPC all set +11315 84DD 20 78 90 jsr FP2SP ; have SPC point to stack too +11316 +11317 84E0 20 5B 92 jsr FETCHB ; get MSB of counter +11318 84E3 85 7B sta J+HI ; save MSB +11319 84E5 20 C3 8F jsr NEXTFPC ; point to LSB +11320 84E8 20 5B 92 jsr FETCHB ; get LSB +11321 84EB 85 7A sta J+LO ; save LSB +11322 84ED +11323 84ED A5 7A lda J+LO ; get LSB back +11324 84EF 18 clc ; get ready for add +11325 84F0 65 63 adc ARG1+LO ; add how many to get rid off +11326 84F2 85 7A sta J+LO ; save new counter +11327 84F4 A5 7B lda J+HI ; get MSB +11328 84F6 65 64 adc ARG1+HI ; add MSB +11329 +11330 84F8 20 3A 92 jsr STASHB ; save Msb of new counter +11331 84FB 20 A3 8F jsr NEXTSPC ; point to LSB +11332 84FE A5 7A lda J+LO ; get lsb +11333 8500 20 3A 92 jsr STASHB ; okay, reset the counter +11334 8503 60 rts +11335 +11336 ; +11337 ; no mouse stuff yet +11338 ; +11339 8504 ZMINFO: +11340 8504 ZMLIMIT: +11341 8504 60 rts +11342 8505 ZMENU: +11343 8505 4C 2F 44 jmp PREDF ; no menu stuff either + Wed Jun 7 1989 12:04 Page 169 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11344 +11345 8508 END +11346 +11347 8508 INCLUDE READ.ASM +11348 8508 STTL "--- READ HANDLER ---" +11349 PAGE + Wed Jun 7 1989 12:04 Page 170 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11350 ; ---- +11351 ; READ +11352 ; ---- +11353 ; READ LINE INTO TABLE [ARG1] ; PARSE INTO TABLE [ARG2] (IF ARG2 IS THERE) +11354 +11355 8508 00 MAXWORDS DB 0 ; maximum number of words in table +11356 8509 00 WORDCNT DB 0 ; how many words read so far +11357 850A 00 WORDSTART DB 0 ; table offset of word +11358 850B SAVESPC DS 3 ; SPC that points to Word Count +11359 +11360 850E ZREAD: +11361 850E A5 64 lda ARG1+HI ; MAKE THE TABLE ADDRESSES +11362 8510 8D 80 6C sta RDTBL1+HI ; AND PLACE IT HERE TO USE +11363 8513 A5 63 lda ARG1+LO +11364 8515 8D 7F 6C sta RDTBL1+LO ; LSBS NEED NOT CHANGE +11365 +11366 8518 A9 00 lda #0 ; TURN OFF FLAGS +11367 851A 8D 5C 6C sta PSVFLG ; FOR ZLEX +11368 851D 8D 5D 6C sta VOCFLG +11369 +11370 8520 A6 62 ldx NARGS +11371 8522 CA dex ; IF 2ND TBL ADDR 0 OR NOT THERE +11372 8523 F0 14 beq ONLYRD ; JUST READ IN DON'T DO CONVERSION (X) +11373 8525 A2 00 ldx #0 ; JIC +11374 8527 A5 66 lda ARG2+HI +11375 8529 05 65 ora ARG2+LO +11376 852B F0 0C beq ONLYRD +11377 +11378 852D A5 66 lda ARG2+HI +11379 852F 8D 82 6C sta RDTBL2+HI +11380 8532 A5 65 lda ARG2+LO +11381 8534 8D 81 6C sta RDTBL2+LO +11382 +11383 8537 A2 01 ldx #1 ; 1 = DO IT ALL (X) +11384 8539 ONLYRD: +11385 8539 8E 6A 5B stx RDFLAG ; CHECK AGAIN AFTER READ IN WHAT TO DO +11386 853C 20 1A 59 jsr INPUT ; READ LINE; RETURN LENGTH IN [RDTBL1],1 +11387 +11388 853F AD 6A 5B lda RDFLAG ; FLAG (X) +11389 8542 F0 03 beq RDEX ; IF INPUT ONLY, LEAVE NOW +11390 8544 20 54 85 jsr DOREST +11391 8547 RDEX: +11392 8547 A9 F0 lda #$F0 ; RETURN NOW ONLY WANTED READ PART +11393 8549 8D 6A 5B sta RDFLAG +11394 854C AD 69 5B lda BRKCHR ; GET BREAK CHAR +11395 854F A2 00 ldx #0 +11396 8551 4C DD 43 jmp PUTBYT ; RETURN IT +11397 ; +11398 ; IF TIMEOUT, [A]=0 SO WILL QUIT W/NO RESULTS +11399 ; +11400 8554 DOREST: +11401 8554 AD 82 6C lda RDTBL2+HI ; get max number of words +11402 8557 20 7C 8F jsr SETPC ; tell me memory and bank +11403 855A 85 8D sta FPCH ; save page +11404 855C 84 8E sty FPCBNK ; and bank +11405 855E AD 81 6C lda RDTBL2+LO ; and for LSB +11406 8561 85 8C sta FPCL ; it is same +11407 8563 20 5B 92 jsr FETCHB ; get max # of words in table +11408 8566 F0 04 beq RDERR ; (5/14/85 - FORCE # WORDS TO +11409 8568 C9 3B cmp #59 ; BE BETWEEN 1 AND 59) +11410 856A 90 02 bcc RD0 +11411 856C RDERR: +11412 856C A9 3A lda #58 ; (5/16/86 - MAKE IT 58, 59 LOST) +11413 856E RD0: +11414 856E 8D 08 85 sta MAXWORDS ; save max words +11415 8571 A9 00 lda #0 ; start at 0 words +11416 8573 8D 09 85 sta WORDCNT ; save it +11417 8576 85 94 sta WRDLEN ; INIT # CHARS IN WORD COUNTER +11418 8578 A9 02 lda #2 +11419 857A 85 93 sta SOURCE ; INIT SOURCE TABLE PNTR +11420 ; +11421 ; now futz with destination table a little +11422 ; +11423 857C 20 C3 8F jsr NEXTFPC ; now we point to # words read +11424 857F A5 8E lda FPCBNK ; and save this pointer + Wed Jun 7 1989 12:04 Page 171 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11425 8581 8D 0B 85 sta SAVESPC ; for stashing at the end +11426 8584 A5 8D lda FPCH +11427 8586 8D 0C 85 sta SAVESPC+1 +11428 8589 A5 8C lda FPCL +11429 858B 8D 0D 85 sta SAVESPC+2 +11430 +11431 858E A9 04 lda #4 ; offset to end of first entry +11432 8590 20 E3 8F jsr ADDFPC ; and point to end of first entry +11433 8593 20 78 90 jsr FP2SP ; now put RDTBL2 into stash pointer +11434 ; +11435 ; now get source table +11436 ; +11437 8596 AD 80 6C lda RDTBL1+HI ; get page +11438 8599 20 7C 8F jsr SETPC ; and tell me what mem page and bank +11439 859C 85 8D sta FPCH ; set up fetch counter +11440 859E 84 8E sty FPCBNK ; and bank +11441 85A0 AD 7F 6C lda RDTBL1+LO ; and lo stays the same +11442 85A3 85 8C sta FPCL ; and save it +11443 85A5 20 C3 8F jsr NEXTFPC ; get # of chars in buffer +11444 85A8 20 5B 92 jsr FETCHB ; and tell me about it +11445 85AB 85 92 sta LINLEN ; SAVE # CHARS IN LINE +11446 85AD 20 C3 8F jsr NEXTFPC ; now point to first char in line +11447 ; +11448 ; MAIN LOOP STARTS HERE +11449 ; +11450 85B0 READL: +11451 85B0 AD 08 85 lda MAXWORDS ; how we doin'? +11452 85B3 CD 09 85 cmp WORDCNT ; see if we have maxxed out +11453 85B6 90 06 bcc RLEX ; all done, thank you +11454 +11455 85B8 A5 92 lda LINLEN +11456 85BA 05 94 ora WRDLEN ; OUT OF CHARS AND WORDS? +11457 85BC D0 16 bne RL2 ; NOT YET +11458 85BE RLEX: +11459 85BE AD 0B 85 lda SAVESPC ; now set SPC to point to # words +11460 85C1 85 91 sta SPCBNK ; read byte, as saved at the beginning +11461 85C3 AD 0C 85 lda SAVESPC+1 +11462 85C6 85 90 sta SPCH +11463 85C8 AD 0D 85 lda SAVESPC+2 +11464 85CB 85 8F sta SPCL +11465 85CD AD 09 85 lda WORDCNT ; get word count +11466 85D0 20 3A 92 jsr STASHB ; and save it +11467 85D3 60 rts +11468 85D4 RL2: +11469 85D4 A5 94 lda WRDLEN ; GET WORD LENGTH +11470 85D6 C9 09 cmp #9 ; 9 CHARS DONE? (EZIP) +11471 85D8 90 03 bcc RL3 ; NO, KEEP GOING +11472 85DA 20 0B 87 jsr FLUSHW ; ELSE FLUSH REMAINDER OF WORD +11473 85DD RL3: +11474 85DD A5 94 lda WRDLEN ; GET WORD LENGTH AGAIN +11475 85DF D0 24 bne READL2 ; CONTINUE IF NOT FIRST CHAR +11476 ; +11477 ; START A NEW WORD +11478 ; +11479 85E1 A2 08 ldx #8 ; CLEAR Z-WORD INPUT BUFFER +11480 85E3 9D 95 6C RLL: sta IN,X ; [A] = 0 +11481 85E6 CA dex +11482 85E7 10 FA bpl RLL +11483 +11484 85E9 A5 93 lda SOURCE ; STORE THE START POS OF THE WORD +11485 85EB 8D 0A 85 sta WORDSTART ; and save it for later +11486 85EE 20 5B 92 jsr FETCHB ; GET A CHAR FROM SOURCE BUFFER +11487 85F1 20 3C 87 jsr SIB ; IS IT A SELF-INSERTING BREAK? +11488 85F4 B0 2C bcs DOSIB ; YES IF CARRY WAS SET +11489 85F6 20 30 87 jsr NORM ; IS IT A "NORMAL" BREAK? +11490 85F9 90 0A bcc READL2 ; NO, CONTINUE +11491 85FB E6 93 inc SOURCE ; ELSE FLUSH THE STRANDED BREAK +11492 85FD 20 C3 8F jsr NEXTFPC ; and point to next char +11493 8600 C6 92 dec LINLEN ; UPDATE # CHARS LEFT IN LINE +11494 8602 4C B0 85 jmp READL ; AND LOOP +11495 8605 READL2: +11496 8605 A5 92 lda LINLEN ; OUT OF CHARS YET? +11497 8607 F0 25 beq READL3 ; LOOKS THAT WAY +11498 8609 20 5B 92 jsr FETCHB ; Grab the char +11499 860C 20 2B 87 jsr BREAK ; IS IT A BREAK? + Wed Jun 7 1989 12:04 Page 172 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11500 860F B0 1D bcs READL3 ; YES IF CARRY WAS SET +11501 8611 A6 94 ldx WRDLEN ; ELSE STORE THE CHAR +11502 8613 9D 95 6C sta IN,X ; INTO THE INPUT BUFFER +11503 8616 C6 92 dec LINLEN ; ONE LESS CHAR IN LINE +11504 8618 E6 94 inc WRDLEN ; ONE MORE IN WORD +11505 861A E6 93 inc SOURCE ; and update next source +11506 861C 20 C3 8F jsr NEXTFPC ; POINT TO NEXT CHAR IN SOURCE +11507 861F 4C B0 85 jmp READL ; AND LOOP BACK +11508 ; +11509 ; handle self-inserting breaks +11510 8622 DOSIB: +11511 8622 8D 95 6C sta IN ; put the break into 1st word slot +11512 8625 C6 92 dec LINLEN ; one less char in line +11513 8627 E6 94 inc WRDLEN ; one more in word buffer +11514 8629 E6 93 inc SOURCE ; and update next source +11515 862B 20 C3 8F jsr NEXTFPC ; point to next source char +11516 862E READL3: +11517 862E A5 94 lda WRDLEN ; ANY CHARS IN WORD YET? +11518 8630 D0 03 bne READL31 ; yup, so deal with word +11519 8632 4C B0 85 jmp READL ; then go get next word +11520 8635 READL31: +11521 8635 20 17 94 jsr CONZST ; CONVERT ASCII IN [IN] TO Z-STRING +11522 8638 20 6C 87 jsr FINDW ; AND LOOK IT UP IN VOCABULARY +11523 +11524 863B AD 0A 85 lda WORDSTART ; get where it starts +11525 863E 20 3A 92 jsr STASHB ; and save it +11526 8641 20 53 90 jsr PREVSPC ; step backwards to point to length +11527 8644 A5 94 lda WRDLEN ; and get length +11528 8646 20 3A 92 jsr STASHB ; and save it away +11529 8649 20 53 90 jsr PREVSPC ; and backwards to LSB of offset +11530 864C A2 06 ldx #6 ; offset to point to end of next entry +11531 +11532 864E EE 09 85 inc WORDCNT ; increment # words read +11533 +11534 8651 AD 5C 6C lda PSVFLG ; IF SHOULD PRESERVE WHAT'S IN +11535 8654 F0 06 beq READL4 +11536 8656 A5 77 lda VALUE+HI ; RDTBL2 AND NOT FOUND (VALUE = 0) +11537 8658 05 76 ora VALUE+LO +11538 865A F0 0F beq READL5 ; JUST SKIP OVER +11539 865C READL4: +11540 865C A5 76 lda VALUE+LO ; GET LSB OF VOCAB ENTRY ADDRESS +11541 865E 20 3A 92 jsr STASHB ; and stash it away +11542 8661 20 53 90 jsr PREVSPC ; point to MSB part +11543 8664 A5 77 lda VALUE+HI ; ALSO STORE MSB IN 2ND SLOT +11544 8666 20 3A 92 jsr STASHB ; and send it out +11545 8669 A2 07 ldx #7 ; offset to point to end of next entry +11546 866B READL5: +11547 866B A9 00 lda #0 +11548 866D 85 94 sta WRDLEN ; CLEAR # CHARS IN WORD +11549 866F 8A txa ; get offset +11550 8670 20 06 90 jsr ADDSPC ; and point to end of next entry +11551 8673 4C B0 85 jmp READL ; AND LOOP BACK +11552 +11553 ; --- +11554 ; LEX +11555 ; --- +11556 ; DO PARSE OF TBL1 INTO TBL2 (2ND HALF OF READ) +11557 +11558 8676 ZLEX: +11559 8676 A5 64 LDA ARG1+HI ; MAKE THE TABLE ADDRESSES +11560 8678 8D 80 6C STA RDTBL1+HI ; AND PLACE IT HERE TO USE +11561 867B A5 63 LDA ARG1+LO +11562 867D 8D 7F 6C STA RDTBL1+LO ; LSBS NEED NOT CHANGE +11563 +11564 8680 A5 66 LDA ARG2+HI +11565 8682 8D 82 6C STA RDTBL2+HI +11566 8685 A5 65 LDA ARG2+LO +11567 8687 8D 81 6C STA RDTBL2+LO +11568 +11569 868A C6 62 DEC NARGS +11570 868C C6 62 DEC NARGS +11571 868E F0 13 BEQ NORMLEX ; USE NORMAL VOCAB TBL +11572 +11573 8690 A9 01 LDA #1 ; USE ARG3 VOCAB TBL +11574 8692 8D 5D 6C STA VOCFLG + Wed Jun 7 1989 12:04 Page 173 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11575 8695 A9 00 LDA #0 +11576 8697 C6 62 DEC NARGS +11577 8699 F0 02 BEQ NOSAVE ; ZERO UNFOUND WORDS +11578 869B A9 01 LDA #1 ; PRESERVE UNFOUND WORD SLOT FLAG +11579 869D 8D 5C 6C NOSAVE: STA PSVFLG +11580 86A0 4C AB 86 JMP DOLEX +11581 +11582 86A3 A9 00 NORMLEX: LDA #0 +11583 86A5 8D 5D 6C STA VOCFLG ; USE NORMAL VOCAB TBL +11584 86A8 8D 5C 6C STA PSVFLG ; AND WILL BE NO PRESERVING +11585 +11586 86AB 4C 54 85 DOLEX: JMP DOREST ; GO DO LEXICAL CONVERSION AND JUST RETURN +11587 +11588 +11589 ; ----- +11590 ; ZWSTR +11591 ; ----- +11592 ; CONVERT A WORD TO A ZWORD, PLACE IN ARG4 TBL +11593 86AE ZWSTR: +11594 86AE A5 64 lda ARG1+HI ; Make ARG1 be the FPC +11595 86B0 20 7C 8F jsr SETPC ; so get absolute mem bank/page +11596 86B3 84 8E sty FPCBNK ; save bank and +11597 86B5 85 8D sta FPCH ; page +11598 86B7 A5 63 lda ARG1+LO +11599 86B9 85 8C sta FPCL ; LSBS NEED NOT CHANGE +11600 ; +11601 ; (IGNORE WORD LENGTH CAUSE CHECK FOR BREAK CHAR (9 CHAR MAX)) +11602 ; +11603 86BB A5 67 lda ARG3+LO ; ADD OFFSET INTO INBUF +11604 86BD 20 E3 8F jsr ADDFPC ; add it to the FPC +11605 +11606 86C0 A5 6A lda ARG4+HI ; now fix the SPC too +11607 86C2 20 7C 8F jsr SETPC ; get me bank and page +11608 86C5 84 91 sty SPCBNK ; save bank +11609 86C7 85 90 sta SPCH ; save page +11610 86C9 A5 69 lda ARG4+LO +11611 86CB 85 8F sta SPCL ; LSB doesn't change +11612 ; +11613 ; START A NEW WORD +11614 ; +11615 86CD A9 09 lda #9 +11616 86CF 85 92 sta LINLEN ; 1 WORD'S WORTH +11617 86D1 A9 00 lda #0 +11618 86D3 85 94 sta WRDLEN +11619 +11620 86D5 A2 08 ldx #8 ; CLEAR Z-WORD INPUT BUFFER +11621 86D7 9D 95 6C WSTR1: sta IN,X ; [A] = 0 +11622 86DA CA dex +11623 86DB 10 FA bpl WSTR1 +11624 ; +11625 ; THIS LOOP READS FROM INBUF TIL BREAK OR 9 CHARS READ +11626 ; +11627 86DD WSTR2: +11628 86DD 20 5B 92 jsr FETCHB ; grab the next char +11629 86E0 20 2B 87 jsr BREAK ; IS IT A BREAK? +11630 86E3 B0 0E bcs WSTR3 ; YES IF CARRY WAS SET +11631 86E5 A6 94 ldx WRDLEN ; ELSE STORE THE CHAR +11632 86E7 9D 95 6C sta IN,X ; INTO THE INPUT BUFFER +11633 86EA E6 94 inc WRDLEN ; ONE MORE CHAR IN WORD +11634 86EC C6 92 dec LINLEN ; ONE LESS IN LINE +11635 86EE 20 C3 8F jsr NEXTFPC ; point to next char +11636 86F1 D0 EA bne WSTR2 ; AND LOOP BACK TIL DONE +11637 86F3 WSTR3: +11638 86F3 A5 94 lda WRDLEN ; ANY CHARS IN WORD YET? +11639 86F5 F0 13 beq WOOPS ; APPARENTLY NOT, OOPS +11640 86F7 20 17 94 jsr CONZST ; CONVERT ASCII IN [IN] TO Z-STRING +11641 +11642 86FA A2 00 ldx #0 ; MOVE FROM [OUT] TO RDTBL2 +11643 86FC BD 9E 6C WSTR4: lda OUT,X +11644 86FF 20 3A 92 jsr STASHB ; and stash it into ZWORD table +11645 8702 20 A3 8F jsr NEXTSPC ; and point to next byte +11646 8705 E8 inx +11647 8706 E0 06 cpx #6 ; max 6 word table +11648 8708 D0 F2 bne WSTR4 ; not done yet +11649 870A WOOPS: + Wed Jun 7 1989 12:04 Page 174 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11650 870A 60 rts +11651 +11652 ; ---------- +11653 ; FLUSH WORD +11654 ; ---------- +11655 +11656 870B FLUSHW: +11657 870B A5 92 lda LINLEN ; ANY CHARS LEFT IN LINE? +11658 870D F0 14 beq FLEX ; NO, SCRAM +11659 870F 20 5B 92 jsr FETCHB ; GRAB A CHAR +11660 8712 20 2B 87 jsr BREAK ; IS IT A BREAK? +11661 8715 B0 0C bcs FLEX ; EXIT IF SO +11662 8717 C6 92 dec LINLEN ; ELSE UPDATE CHAR COUNT +11663 8719 E6 94 inc WRDLEN ; AND WORD-CHAR COUNT +11664 871B E6 93 inc SOURCE ; AND CHAR POINTER +11665 871D 20 C3 8F jsr NEXTFPC ; and FPC pointer too +11666 8720 4C 0B 87 jmp FLUSHW ; AND LOOP BACK (ALWAYS) +11667 8723 FLEX: +11668 8723 60 rts +11669 +11670 +11671 ; --------------------------------- +11672 ; IS CHAR IN [A] ANY TYPE OF BREAK? +11673 ; --------------------------------- +11674 ; ------------------ +11675 ; NORMAL BREAK CHARS +11676 ; ------------------ +11677 +11678 8724 21 3F 2C 2E BRKTBL: DB '!?,.' ; IN ORDER OF +11679 8728 0D DB $0D ; ASCII ENDING FREQUENCY +11680 8729 20 DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED +11681 872A 00 DB 0 ; ZERO ADDED FOR ZWSTR (X) +11682 0007 NBRKS EQU $-BRKTBL ; # NORMAL BREAKS +11683 +11684 872B 20 3C 87 BREAK: JSR SIB ; CHECK FOR A SIB FIRST +11685 872E B0 3A BCS FBRK ; EXIT NOW IF MATCHED +11686 +11687 ; ELSE FALL THROUGH ... +11688 +11689 +11690 ; -------------------------------- +11691 ; IS CHAR IN [A] A "NORMAL" BREAK? +11692 ; -------------------------------- +11693 +11694 8730 A2 06 NORM: LDX #NBRKS-1 ; NUMBER OF "NORMAL" BREAKS +11695 8732 DD 24 87 NBL: CMP BRKTBL,X ; MATCHED? +11696 8735 F0 33 BEQ FBRK ; YES, EXIT +11697 8737 CA DEX +11698 8738 10 F8 BPL NBL ; NO, KEEP LOOKING +11699 873A 18 CLC ; NO MATCH, CLEAR CARRY +11700 873B 60 RTS ; AND RETURN +11701 +11702 +11703 ; --------------------- +11704 ; IS CHAR IN [A] A SIB? +11705 ; --------------------- +11706 +11707 873C 85 AC SIB: STA IOCHAR ; SAVE TEST CHAR +11708 873E A5 54 lda VOCAB+ABANK ; get bank +11709 8740 85 8B sta MPCBNK ; and save it +11710 8742 A5 53 lda VOCAB+HI ; and hi part +11711 8744 85 8A sta MPCPNT+HI ; and save it +11712 8746 AD 08 96 lda ZBEGIN+ZVOCAB+0 ; GET 1ST BYTE IN VOCAB TABLE +11713 8749 AC 09 96 LDY ZBEGIN+ZVOCAB+1 +11714 874C 85 87 STA MPCM +11715 874E 84 86 STY MPCL +11716 8750 A9 00 LDA #0 +11717 8752 85 88 STA MPCH ; now everything is set up +11718 8754 20 0E 92 JSR GETBYT ; HAS # SIBS +11719 8757 85 7A STA J ; USE AS AN INDEX +11720 8759 20 0E 92 SBL: JSR GETBYT ; GET NEXT SIB +11721 875C C5 AC CMP IOCHAR ; MATCHED? +11722 875E F0 08 BEQ FBRK0 ; YES, REPORT IT +11723 8760 C6 7A DEC J +11724 8762 D0 F5 BNE SBL ; ELSE KEEP LOOPING + Wed Jun 7 1989 12:04 Page 175 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11725 8764 A5 AC LDA IOCHAR +11726 8766 18 CLC ; NO MATCH, SO +11727 8767 60 RTS ; EXIT WITH CARRY CLEAR +11728 8768 A5 AC FBRK0: LDA IOCHAR +11729 876A 38 FBRK: SEC ; EXIT WITH CARRY SET +11730 876B 60 RTS ; IF MATCHED WITH A BREAK CHAR +11731 +11732 +11733 ; ----------------- +11734 ; VOCABULARY SEARCH +11735 ; ----------------- +11736 ; ENTRY: 6-BYTE TARGET Z-WORD IN [OUT] +11737 ; EXIT: VIRTUAL ENTRY ADDRESS IN [VALUE] IF FOUND ; +11738 ; OTHERWISE [VALUE] = 0 +11739 +11740 0078 VWLEN EQU I ; ********** +11741 007B VWCUR EQU J+HI +11742 +11743 876C FINDW: +11744 876C AD 5D 6C lda VOCFLG ; USE WHAT VOCAB TBL? +11745 876F F0 07 beq FWL2 ; NORMAL +11746 8771 A5 68 lda ARG3+HI ; IF ALTERNATE VOCTBL +11747 8773 A4 67 ldy ARG3+LO ; IT'S ADDR IS IN ARG3 +11748 8775 4C 9F 87 jmp FWL3 +11749 8778 FWL2: +11750 8778 AD 94 6C lda DIDVTBL ; have we done default vocab table? +11751 877B F0 17 beq FWLNEW ; nope, so do it the first time +11752 877D A2 02 ldx #2 ; restore pointers +11753 877F FWRSTL: +11754 877F BD 8B 6C lda VOCMPC,X ; get it +11755 8782 95 86 sta MPC,X ; save it +11756 8784 BD 8E 6C lda VCESVE,X ; save VOCEND too +11757 8787 95 B3 sta VOCEND,X ; okay, we have +11758 8789 BD 91 6C lda VWLSVE,X ; and starting length +11759 878C 95 78 sta VWLEN,X ; we have +11760 878E CA dex ; count +11761 878F 10 EE bpl FWRSTL ; okay, next one +11762 8791 4C 75 88 jmp FWLOOP ; and go do it +11763 8794 FWLNEW: +11764 8794 A9 FF lda #$FF ; show we are doing default table +11765 8796 8D 94 6C sta DIDVTBL ; we shall +11766 +11767 8799 AD 08 96 lda ZBEGIN+ZVOCAB ; GET VIRTUAL ADDR OF VOCAB TBL +11768 879C AC 09 96 ldy ZBEGIN+ZVOCAB+1 +11769 879F FWL3: +11770 879F 85 87 STA MPCM +11771 87A1 84 86 STY MPCL +11772 87A3 A9 00 LDA #0 +11773 87A5 85 88 STA MPCH +11774 87A7 20 85 90 JSR VLDMPC ; SET TO NEW PAGE +11775 87AA 20 0E 92 JSR GETBYT ; GET # SIBS +11776 87AD 18 CLC +11777 87AE 65 86 ADC MPCL ; GET ACTUAL BASE ADDR OF VOCAB ENTRIES +11778 87B0 85 86 STA MPCL +11779 87B2 90 02 BCC FWL0 +11780 87B4 E6 87 INC MPCM +11781 87B6 20 85 90 FWL0: JSR VLDMPC ; SET TO NEW PAGE +11782 87B9 20 0E 92 JSR GETBYT ; GET # BYTES PER ENTRY (AND MOVE TO NEXT BYTE) +11783 87BC 85 95 STA ESIZE ; SAVE IT HERE +11784 87BE 85 78 STA VWLEN+0 ; AND HERE +11785 87C0 A9 00 LDA #0 ; CLEAR REST OF COUNTER +11786 87C2 85 79 STA VWLEN+1 +11787 87C4 85 7A STA VWLEN+2 +11788 +11789 87C6 20 0E 92 JSR GETBYT ; GET # OF ENTRIES IN TBL (MSB) +11790 87C9 8D 84 6C STA NENTS+HI ; AND STUFF IT IN [NENTS] +11791 87CC 20 0E 92 JSR GETBYT ; DON'T FORGET THE LSB! +11792 87CF 8D 83 6C STA NENTS+LO +11793 87D2 AD 84 6C LDA NENTS+HI +11794 87D5 10 03 BPL SORTED +11795 87D7 4C 2E 89 JMP UNSORTED ; VOCAB LIST IS UNSORTED, HANDLE DIFFERENTLY +11796 87DA SORTED: +11797 87DA A9 00 LDA #0 ; FIND SIZE OF VAOCAB TBL +11798 87DC 85 B3 STA VOCEND ; TO LOCATE THE END OF IT +11799 87DE 85 B4 STA VOCEND+1 + Wed Jun 7 1989 12:04 Page 176 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11800 87E0 85 B5 STA VOCEND+2 +11801 87E2 A6 95 LDX ESIZE +11802 87E4 FWL1: +11803 87E4 18 CLC +11804 87E5 A5 B3 LDA VOCEND ; (# OF ENTRIES) * (ENTRY SIZE) +11805 87E7 6D 83 6C ADC NENTS+LO +11806 87EA 85 B3 STA VOCEND +11807 87EC A5 B4 LDA VOCEND+1 +11808 87EE 6D 84 6C ADC NENTS+HI +11809 87F1 85 B4 STA VOCEND+1 +11810 87F3 90 02 bcc FWL11 +11811 87F5 E6 B5 inc VOCEND+2 +11812 87F7 FWL11: +11813 87F7 CA DEX +11814 87F8 D0 EA BNE FWL1 +11815 +11816 87FA 18 CLC +11817 87FB A5 B3 LDA VOCEND ; AND ADD LENGTH TO START OF TBL +11818 87FD 65 86 ADC MPCL ; TO GET END OF TBL +11819 87FF 85 B3 STA VOCEND +11820 8801 A5 B4 LDA VOCEND+1 +11821 8803 65 87 ADC MPCM +11822 8805 85 B4 STA VOCEND+1 +11823 8807 A5 B5 LDA VOCEND+2 +11824 8809 65 88 ADC MPCH +11825 880B 85 B5 STA VOCEND+2 ; TO SAVE FOR TESTING IF PAST END +11826 +11827 880D A5 B3 LDA VOCEND ; SUBTRACT [ESIZE] SO THAT +11828 880F 38 SEC ; [VOCEND] POINTS TO REAL LAST ENTRY +11829 8810 E5 95 SBC ESIZE +11830 8812 85 B3 STA VOCEND +11831 8814 A5 B4 LDA VOCEND+1 +11832 8816 E9 00 SBC #0 +11833 8818 85 B4 STA VOCEND+1 +11834 ; +11835 ; BEGIN THE SEARCH! [MPC] NOW POINTS TO 1ST ENTRY +11836 ; +11837 881A 4E 84 6C LSR NENTS+HI ; 2 ALIGN # OF ENTRIES +11838 881D 6E 83 6C ROR NENTS+LO ; 2 point to middle of table +11839 8820 06 78 FWCALC: ASL VWLEN+0 ; CALCULATE INITIAL OFFSET FOR SEARCH +11840 8822 26 79 ROL VWLEN+1 +11841 8824 26 7A ROL VWLEN+2 +11842 8826 4E 84 6C LSR NENTS+HI +11843 8829 6E 83 6C ROR NENTS+LO +11844 882C D0 F2 BNE FWCALC +11845 +11846 882E 18 CLC ; ADD 1ST OFFSET INTO START OF VOCABULARL +11847 882F A5 86 LDA MPCL ; WHICH IS CURRENTLY IN MPC +11848 8831 65 78 ADC VWLEN+0 +11849 8833 85 86 STA MPCL +11850 8835 A5 87 LDA MPCM +11851 8837 65 79 ADC VWLEN+1 +11852 8839 85 87 STA MPCM +11853 883B A5 88 LDA MPCH +11854 883D 65 7A ADC VWLEN+2 +11855 883F 85 88 STA MPCH +11856 +11857 8841 38 SEC ; AVOID FENCE-POST BUG FOR +11858 8842 A5 86 LDA MPCL ; EXACT-POWER-OF-2 TBL (DUNCAN) +11859 8844 E5 95 SBC ESIZE +11860 8846 85 86 STA MPCL +11861 8848 B0 0F BCS FWSAVE +11862 884A A5 87 LDA MPCM +11863 884C 38 SEC +11864 884D E9 01 SBC #1 +11865 884F 85 87 STA MPCM +11866 8851 B0 06 BCS FWSAVE +11867 8853 A5 88 LDA MPCH +11868 8855 E9 00 SBC #0 +11869 8857 85 88 STA MPCH +11870 8859 FWSAVE: +11871 8859 AD 94 6C lda DIDVTBL ; are we installing default table? +11872 885C 10 17 bpl FWLOOP ; already have? +11873 885E A2 02 ldx #2 ; save MPC +11874 8860 8E 94 6C stx DIDVTBL ; show we have saved it + Wed Jun 7 1989 12:04 Page 177 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11875 8863 FWSVL: +11876 8863 B5 86 lda MPC,X ; get it +11877 8865 9D 8B 6C sta VOCMPC,X ; save it +11878 8868 B5 B3 lda VOCEND,X ; save VOCEND too +11879 886A 9D 8E 6C sta VCESVE,X ; okay, we have +11880 886D B5 78 lda VWLEN,X ; and starting length +11881 886F 9D 91 6C sta VWLSVE,X ; we have +11882 8872 CA dex ; count +11883 8873 10 EE bpl FWSVL ; okay, next one +11884 8875 FWLOOP: +11885 8875 46 7A lsr VWLEN+2 ; SET FOR NEXT OFFSET, +11886 8877 66 79 ror VWLEN+1 ; WHICH IS HALF THIS ONE +11887 8879 66 78 ror VWLEN+0 +11888 +11889 887B A5 86 lda MPCL ; HOLD START ADDR, MPC WILL BE A MESS +11890 887D 85 7B sta VWCUR+0 +11891 887F A5 87 lda MPCM +11892 8881 85 7C sta VWCUR+1 +11893 8883 A5 88 lda MPCH +11894 8885 85 7D sta VWCUR+2 +11895 +11896 8887 20 85 90 jsr VLDMPC ; SET TO NEW PAGE +11897 888A 20 0E 92 jsr GETBYT ; GET 1ST BYTE OF ENTRY +11898 888D CD 9E 6C cmp OUT ; MATCH 1ST BYTE OF TARGET? +11899 8890 90 34 bcc WNEXT ; LESS +11900 8892 D0 66 bne FWPREV ; GREATER +11901 8894 20 0E 92 jsr GETBYT +11902 8897 CD 9F 6C cmp OUT+1 ; 2ND BYTE MATCHED? +11903 889A 90 2A bcc WNEXT +11904 889C D0 5C bne FWPREV ; NOPE +11905 889E 20 0E 92 jsr GETBYT +11906 88A1 CD A0 6C cmp OUT+2 ; 3RD BYTE? +11907 88A4 90 20 bcc WNEXT +11908 88A6 D0 52 bne FWPREV ; SORRY ... +11909 88A8 20 0E 92 jsr GETBYT +11910 88AB CD A1 6C cmp OUT+3 ; 4TH BYTE +11911 88AE 90 16 bcc WNEXT +11912 88B0 D0 48 BNE FWPREV +11913 88B2 20 0E 92 JSR GETBYT +11914 88B5 CD A2 6C CMP OUT+4 ; 5TH BYTE? +11915 88B8 90 0C BCC WNEXT +11916 88BA D0 3E BNE FWPREV ; SORRY ... +11917 88BC 20 0E 92 JSR GETBYT +11918 88BF CD A3 6C CMP OUT+5 ; LAST BYTE? +11919 88C2 F0 5A BEQ FWSUCC ; FOUND IT! +11920 88C4 B0 34 BCS FWPREV ; ELSE BACK UP ... +11921 88C6 WNEXT: +11922 88C6 A5 7B LDA VWCUR+0 ; TO MOVE UP, JUST ADD +11923 88C8 18 CLC ; OFFSET FROM START OF THIS +11924 88C9 65 78 ADC VWLEN+0 ; ENTRY +11925 88CB 85 86 STA MPCL +11926 88CD A5 7C LDA VWCUR+1 +11927 88CF 65 79 ADC VWLEN+1 +11928 88D1 B0 18 BCS WNXT2 ; SAVES CODE (?) +11929 +11930 88D3 85 87 STA MPCM +11931 88D5 A9 00 LDA #0 +11932 88D7 85 88 STA MPCH +11933 88D9 WNXT0: +11934 88D9 A5 87 LDA MPCM ; GONE PAST END? +11935 88DB C5 B4 CMP VOCEND+1 +11936 88DD F0 04 BEQ WNXT1 ; MAYBE +11937 88DF B0 0A BCS WNXT2 ; YES +11938 88E1 90 2A BCC FWMORE ; NO +11939 88E3 WNXT1: +11940 88E3 A5 86 LDA MPCL +11941 88E5 C5 B3 CMP VOCEND +11942 88E7 90 24 BCC FWMORE ; NO +11943 88E9 F0 22 BEQ FWMORE ; NO, EQUAL +11944 88EB WNXT2: +11945 88EB A5 B3 LDA VOCEND ; YES, SO POINT TO END OF TBL +11946 88ED 85 86 STA MPCL +11947 88EF A5 B4 LDA VOCEND+1 +11948 88F1 85 87 STA MPCM +11949 88F3 A5 B5 LDA VOCEND+2 + Wed Jun 7 1989 12:04 Page 178 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11950 88F5 85 88 STA MPCH +11951 88F7 4C 0D 89 JMP FWMORE +11952 88FA FWPREV: +11953 88FA A5 7B LDA VWCUR+0 ; TO MOVE DOWN, JUST SUBTRACT +11954 88FC 38 SEC ; OFFSET FROM START OF THIS +11955 88FD E5 78 SBC VWLEN+0 ; ENTRY +11956 88FF 85 86 STA MPCL +11957 8901 A5 7C LDA VWCUR+1 +11958 8903 E5 79 SBC VWLEN+1 +11959 8905 85 87 STA MPCM +11960 8907 A5 7D LDA VWCUR+2 +11961 8909 E5 7A SBC VWLEN+2 +11962 890B 85 88 STA MPCH +11963 890D FWMORE: +11964 890D A5 7A LDA VWLEN+2 ; IF OFFSET >GE< 1 WORD, CONTINUE +11965 890F D0 0A BNE FWM1 +11966 8911 A5 79 LDA VWLEN+1 +11967 8913 D0 06 BNE FWM1 +11968 8915 A5 78 LDA VWLEN+0 +11969 8917 C5 95 CMP ESIZE +11970 8919 90 0C BCC FWFAIL +11971 891B FWM1: +11972 891B 4C 75 88 JMP FWLOOP ; AND TRY AGAIN +11973 +11974 891E A5 7B FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD +11975 8920 85 76 STA VALUE+LO +11976 8922 A5 7C LDA VWCUR+1 +11977 8924 85 77 STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY +11978 8926 60 RTS ; WORD VALUE RETURNABLE +11979 8927 FWFAIL: +11980 8927 A9 00 LDA #0 ; NOT FOUND +11981 8929 85 76 STA VALUE+LO +11982 892B 85 77 STA VALUE+HI +11983 892D 60 RTS ; THEN RETURN WITH [VALUE] = 0 +11984 ; +11985 ; DO UNSORTED SEARCH ON VOCAB TBL IN MPC +11986 ; +11987 892E UNSORTED: +11988 892E A9 FF LDA #$FF ; 2'S COMPLEMENT LENGTH +11989 8930 4D 84 6C EOR NENTS+HI ; TO GET REAL LENGTH +11990 8933 8D 84 6C STA NENTS+HI ; WAS NEGATIVE TO SIGNIFY +11991 8936 A9 FF LDA #$FF ; UNSORTED VOCAB TBL +11992 8938 4D 83 6C EOR NENTS+LO +11993 893B 8D 83 6C STA NENTS+LO +11994 893E EE 83 6C INC NENTS+LO ; 2'S CMPL +11995 8941 D0 03 BNE UNSRT0 +11996 8943 EE 84 6C INC NENTS+HI +11997 8946 UNSRT0: +11998 8946 A5 86 LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS +11999 8948 85 7B STA VWCUR+0 +12000 894A A5 87 LDA MPCM +12001 894C 85 7C STA VWCUR+1 +12002 894E A5 88 LDA MPCH +12003 8950 85 7D STA VWCUR+2 +12004 +12005 8952 20 0E 92 JSR GETBYT ; GET 1ST BYTE OF ENTRY +12006 8955 CD 9E 6C CMP OUT ; MATCH 1ST BYTE OF TARGET? +12007 8958 D0 28 BNE FNEXT ; LESS +12008 895A 20 0E 92 JSR GETBYT +12009 895D CD 9F 6C CMP OUT+1 ; 2ND BYTE MATCHED? +12010 8960 D0 20 BNE FNEXT +12011 8962 20 0E 92 JSR GETBYT +12012 8965 CD A0 6C CMP OUT+2 ; 3RD BYTE? +12013 8968 D0 18 BNE FNEXT +12014 896A 20 0E 92 JSR GETBYT +12015 896D CD A1 6C CMP OUT+3 ; 4TH BYTE +12016 8970 D0 10 BNE FNEXT +12017 8972 20 0E 92 JSR GETBYT +12018 8975 CD A2 6C CMP OUT+4 ; 5TH BYTE? +12019 8978 D0 08 BNE FNEXT +12020 897A 20 0E 92 JSR GETBYT +12021 897D CD A3 6C CMP OUT+5 ; LAST BYTE? +12022 8980 F0 9C BEQ FWSUCC ; FOUND IT! +12023 +12024 8982 A5 7B FNEXT: LDA VWCUR+LO ; TO MOVE UP, JUST ADD + Wed Jun 7 1989 12:04 Page 179 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +12025 8984 18 CLC ; OFFSET FROM START OF THIS +12026 8985 65 95 ADC ESIZE ; ENTRY +12027 8987 85 86 STA MPCL +12028 8989 90 0D BCC FNEXT0 +12029 +12030 898B A5 7C LDA VWCUR+HI ; PICK UP CARRY +12031 898D 69 00 ADC #0 +12032 898F 85 87 STA MPCM +12033 8991 A9 00 LDA #0 +12034 8993 85 88 STA MPCH +12035 8995 20 85 90 JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE +12036 +12037 8998 CE 83 6C FNEXT0: DEC NENTS+LO ; CHECKED ALL ENTRIES? +12038 899B D0 A9 BNE UNSRT0 +12039 899D AD 84 6C LDA NENTS+HI +12040 89A0 F0 85 BEQ FWFAIL ; GO INDICATE NO FIND +12041 89A2 CE 84 6C DEC NENTS+HI ; OR DO NEXT 256 ENTRIES +12042 89A5 4C 46 89 JMP UNSRT0 +12043 +12044 89A8 END +12045 +12046 89A8 INCLUDE ZSAVRES.ASM +12047 +12048 89A8 STTL "--- ZIP SAVE AND RESTORE ROUTINES ---" +12049 PAGE + Wed Jun 7 1989 12:04 Page 180 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12050 ; ----------------------------- +12051 ; SET UP SAVE & RESTORE SCREENS +12052 ; ----------------------------- +12053 89A8 SAVRES: +12054 89A8 20 E7 54 jsr ZCRLF ; CLEAR THE LINE BUFFER +12055 89AB A9 00 lda #0 +12056 89AD 85 AA sta SCRIPT ; DISABLE SCRIPTING +12057 89AF AD 54 C0 lda PAGE2SW+MAIN ; just do this for the heck of it +12058 89B2 AD 83 C0 lda BNK2SET ; this stuff too +12059 89B5 AD 83 C0 lda BNK2SET +12060 +12061 89B8 60 rts +12062 +12063 ; ----------------------------- +12064 ; SAVE & RESTORE STRINGS +12065 ; ----------------------------- +12066 89B9 59 45 53 YES: DB "YES" +12067 89BC 0D DB EOL +12068 0004 YESL EQU $-YES +12069 89BD 4E 4F NO: DB "NO" +12070 89BF 0D DB EOL +12071 0003 NOL EQU $-NO +12072 +12073 89C0 0D NAMEQ: db EOL +12074 89C1 49 6E 73 65 72 db "Insert save disk and enter " + 89C6 74 20 73 61 76 + 89CB 65 20 64 69 73 + 89D0 6B 20 61 6E 64 + 89D5 20 65 6E 74 65 + 89DA 72 20 +12075 89DC 66 75 6C 6C 20 db "full pathname of save file: " + 89E1 70 61 74 68 6E + 89E6 61 6D 65 20 6F + 89EB 66 20 73 61 76 + 89F0 65 20 66 69 6C + 89F5 65 3A 20 +12076 89F8 0D db EOL +12077 89F9 48 69 74 20 27 db "Hit '?' key to get a list of online volumes." + 89FE 3F 27 20 6B 65 + 8A03 79 20 74 6F 20 + 8A08 67 65 74 20 61 + 8A0D 20 6C 69 73 74 + 8A12 20 6F 66 20 6F + 8A17 6E 6C 69 6E 65 + 8A1C 20 76 6F 6C 75 + 8A21 6D 65 73 2E +12078 8A25 0D db EOL +12079 8A26 43 75 72 72 65 db "Current pathname is:", + 8A2B 6E 74 20 70 61 + 8A30 74 68 6E 61 6D + 8A35 65 20 69 73 3A + 8A3A 00 +12080 8A3B 0D db EOL +12081 007C NAMEQL EQU $-NAMEQ +12082 SNDATA: ; show start of name and length +12083 8A3C 00 SNAMEL: db 0 ; place to save length of name +12084 8A3D SAVENAME: ds 64+15 ; save plenty of room for max name +12085 +12086 8A8C 0D 46 69 6C 65 DELQ: db EOL,"File exists, delete it (Yes/No)? " + 8A91 20 65 78 69 73 + 8A96 74 73 2C 20 64 + 8A9B 65 6C 65 74 65 + 8AA0 20 69 74 20 28 + 8AA5 59 65 73 2F 4E + 8AAA 6F 29 3F 20 +12087 0023 DELQL EQU $-DELQ+1 ; include this following EOL +12088 8AAE 0D 50 6C 65 61 RETQ: db EOL,"Please hit [RETURN]",EOL + 8AB3 73 65 20 68 69 + 8AB8 74 20 5B 52 45 + 8ABD 54 55 52 4E 5D + 8AC2 0D +12089 0015 RETQL EQU $-RETQ +12090 8AC3 0D 4E 61 6D 65 PREFIX_ERR: db EOL,"Name must have prefix, " + 8AC8 20 6D 75 73 74 + 8ACD 20 68 61 76 65 + Wed Jun 7 1989 12:04 Page 181 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + + 8AD2 20 70 72 65 66 + 8AD7 69 78 2C 20 +12091 8ADB 69 2E 65 2E 3A db "i.e.: /DISKNAME/FILENAME",EOL + 8AE0 20 2F 44 49 53 + 8AE5 4B 4E 41 4D 45 + 8AEA 2F 46 49 4C 45 + 8AEF 4E 41 4D 45 0D +12092 0031 PREFIX_ERRL EQU $-PREFIX_ERR +12093 ; ----------------------------- +12094 ; SAVE/RESTORE Parameter Blocks +12095 ; ----------------------------- +12096 8AF4 CREATE_PB: +12097 8AF4 07 db 7 ; 7 parameters +12098 8AF5 3C8A dw SNDATA ; pointer to name +12099 8AF7 C3 db $C3 ; full access to file +12100 8AF8 06 db $06 ; BIN file type +12101 8AF9 0000 dw 0 ; no aux data +12102 8AFB 01 db $01 ; standard file +12103 8AFC 0000 dw 0 ; create date +12104 8AFE 0000 dw 0 +12105 ; creation time +12106 8B00 SETEOF_PB: +12107 8B00 02 db 2 ; 1 parameter +12108 8B01 00 db 0 ; refnum +12109 8B02 00 00 00 db 0,0,0 ; set to zero spot to clear it out +12110 8B05 OPEN_SV: +12111 8B05 03 db 3 ; 3 parameters +12112 8B06 3C8A dw SNDATA ; name +12113 8B08 0011 dw GAME1FIO ; file buffer +12114 8B0A 00 db 0 ; ref num +12115 8B0B CLOSE_PB: +12116 8B0B 01 db 1 ; only one parm +12117 8B0C 00 db 0 ; the refnum +12118 8B0D WRITE_SV: +12119 8B0D 04 db 4 ; parm count +12120 8B0E 00 db 0 ; refnum +12121 8B0F 0008 dw IOBUFF ; data is always here +12122 8B11 0002 dw 512 ; 1 page worth +12123 8B13 0000 dw 0 ; how many actually went +12124 +12125 ; get the save file name. If user hits the ESC key, then abort the +12126 ; save by return with the carry set. +12127 ; +12128 8B15 GET_SNAME: +12129 8B15 20 94 8C jsr CLOSE_GAME ; close the game files +12130 8B18 20 A9 4C jsr SWAP2INFOW ; goto information window +12131 8B1B GTSN0: +12132 8B1B DLINE NAMEQ ; ask about name +12133 8B1B A2 C0 ldx #NAMEQ ; get other part of string +12135 [01] IFMA 2 ; check to see if length passed in +12136 ldy ; then just fetch it +12137 [01] ELSE +12138 8B1F A0 7C ldy #NAMEQL ; get length of string +12139 [00] ENDIF +12140 8B21 20 6B 4C jsr DLINE ; print the string +12141 8B24 .MACEND +12142 8B24 AD 3C 8A lda SNAMEL ; is there a name yet? +12143 8B27 F0 0A beq GTSN00 ; nope +12144 8B29 DLINE SAVENAME,SNAMEL ; show current name of file +12145 8B29 A2 3D ldx #SAVENAME ; get other part of string +12147 [01] IFMA 2 ; check to see if length passed in +12148 8B2D AC 3C 8A ldy SNAMEL ; then just fetch it +12149 [01] ELSE +12150 ldy #SAVENAMEL ; get length of string +12151 [00] ENDIF +12152 8B30 20 6B 4C jsr DLINE ; print the string +12153 8B33 .MACEND +12154 8B33 GTSN00: +12155 8B33 A9 00 lda #0 ; clear line count +12156 8B35 8D 0C 8B sta CLOSE_PB+CL_REFNUM ; clear this too +12157 8B38 AE 3C 8A ldx SNAMEL ; get length +12158 8B3B 86 A9 stx CHRCNT ; okay +12159 8B3D AC 3C 8A ldy SNAMEL ; point to copy + Wed Jun 7 1989 12:04 Page 182 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12160 8B40 88 dey ; one less +12161 8B41 GCOPY: +12162 8B41 BD 3C 8A lda SNAMEL,X ; get char +12163 8B44 99 00 02 sta LBUFF,Y ; save it +12164 8B47 CA dex ; point to previous one +12165 8B48 88 dey ; previous pointer +12166 8B49 10 F6 bpl GCOPY ; copy until length byte +12167 8B4B GNAME: +12168 8B4B 20 31 51 jsr GETKEY ; WAIT FOR A KEY +12169 8B4E C9 0D cmp #EOL ; IF [RETURN], +12170 8B50 F0 5F beq GOTNAME ; got the name +12171 8B52 C9 1B cmp #ESCAPE ; hit escape key? +12172 8B54 38 sec ; just in case it does exit +12173 8B55 D0 03 bne GNM2 +12174 8B57 4C F5 8B jmp GNX ; all done then +12175 8B5A GNM2: +12176 8B5A C9 08 cmp #BACKSPACE ; erasing things? +12177 8B5C D0 15 bne GNM1 ; nope +12178 +12179 8B5E A6 A9 ldx CHRCNT ; make sure there are chars there +12180 8B60 D0 06 bne GNMBP ; ayyup, do delete +12181 8B62 GNMBAD: +12182 8B62 20 C3 4E jsr BEEP ; no room for delete +12183 8B65 4C 4B 8B jmp GNAME ; okay +12184 8B68 GNMBP: +12185 8B68 CA dex ; point down one +12186 8B69 86 A9 stx CHRCNT ; count one down +12187 8B6B BD 00 02 lda LBUFF,X ; get char to delete +12188 8B6E AA tax ; show in [X] +12189 8B6F A9 08 lda #BACKSPACE ; and doing a backspace +12190 8B71 D0 35 bne GNMSHOW ; okay, delete char on screen +12191 8B73 GNM1: +12192 8B73 C9 2F cmp #'/' ; slash is the only good non-numeric char +12193 8B75 F0 2A beq GNMGOOD ; fine, use it +12194 8B77 C9 2E cmp #'.' ; well, maybe a . too +12195 8B79 F0 26 beq GNMGOOD ; fine, here it is +12196 8B7B C9 3F cmp #VOLCHAR ; does user want list of volumes? +12197 8B7D D0 0A bne GNM1x ; nope +12198 +12199 8B7F A9 00 lda #0 ; clear out current name +12200 8B81 85 A9 sta CHRCNT ; okay, we did +12201 8B83 20 5D 4B jsr LISTVOLS ; show them +12202 8B86 4C 1B 8B jmp GTSN0 ; start over, kind of +12203 8B89 GNM1x: +12204 8B89 C9 30 cmp #'0' ; is it a number +12205 8B8B 90 D5 bcc GNMBAD ; nope +12206 8B8D C9 3A cmp #'9'+1 ; well? +12207 8B8F 90 10 bcc GNMGOOD ; yup +12208 8B91 C9 7B cmp #'z'+1 ; make sure it is alpha numeric +12209 8B93 B0 CD bcs GNMBAD ; nope +12210 8B95 C9 41 cmp #'A' ; well? +12211 8B97 90 C9 bcc GNMBAD ; nope +12212 8B99 C9 61 cmp #'a' ; little char? +12213 8B9B B0 04 bcs GNMGOOD ; yup +12214 8B9D C9 5B cmp #'Z'+1 ; big char +12215 8B9F B0 C1 bcs GNMBAD ; nope +12216 8BA1 GNMGOOD: +12217 8BA1 A6 A9 ldx CHRCNT ; get name index +12218 8BA3 E6 A9 inc CHRCNT ; point to next char +12219 8BA5 9D 00 02 sta LBUFF,X ; save name char +12220 8BA8 GNMSHOW: +12221 8BA8 20 82 5D jsr CHAR ; show character +12222 8BAB 20 F1 71 jsr DISP_LINE ; make sure it is there +12223 8BAE 4C 4B 8B jmp GNAME ; go get next char +12224 ; +12225 ; got the name, so copy it to the SAVENAME buffer +12226 ; +12227 8BB1 GOTNAME: +12228 8BB1 A5 A9 lda CHRCNT ; did we get any? +12229 8BB3 F0 07 beq GTNMERR ; nope +12230 8BB5 AD 00 02 lda LBUFF ; make sure first name is a directory +12231 8BB8 C9 2F cmp #'/' ; is it? +12232 8BBA F0 10 beq GTNM1 ; yup, probly okay then +12233 8BBC GTNMERR: +12234 8BBC A9 00 lda #0 ; clear CHRCNT so name doesn't get + Wed Jun 7 1989 12:04 Page 183 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12235 8BBE 85 A9 sta CHRCNT ; output again +12236 8BC0 DLINE PREFIX_ERR ; complain and die +12237 8BC0 A2 C3 ldx #PREFIX_ERR ; get other part of string +12239 [01] IFMA 2 ; check to see if length passed in +12240 ldy ; then just fetch it +12241 [01] ELSE +12242 8BC4 A0 31 ldy #PREFIX_ERRL ; get length of string +12243 [00] ENDIF +12244 8BC6 20 6B 4C jsr DLINE ; print the string +12245 8BC9 .MACEND +12246 8BC9 38 sec ; show bad name +12247 8BCA B0 29 bcs GNX ; all done +12248 8BCC GTNM1: +12249 8BCC A2 00 ldx #0 ; now check to make sure there are 2 +12250 8BCE A0 FE ldy #$FE ; use this as counter +12251 8BD0 GTNMCHK: +12252 8BD0 BD 00 02 lda LBUFF,X ; get char +12253 8BD3 E8 inx ; next char +12254 8BD4 C9 2F cmp #'/' ; prefix deliminator? +12255 8BD6 D0 03 bne GTNMCHK1 ; nope +12256 8BD8 C8 iny ; count this one +12257 8BD9 F0 06 beq GTNM2 ; we have 2 of them +12258 8BDB GTNMCHK1: +12259 8BDB E4 A9 cpx CHRCNT ; at end? +12260 8BDD F0 DD beq GTNMERR ; yes, and no 2 '/'s +12261 8BDF D0 EF bne GTNMCHK ; go check next char +12262 8BE1 GTNM2: +12263 8BE1 E4 A9 cpx CHRCNT ; make sure there are chars after prefix +12264 8BE3 F0 D7 beq GTNMERR ; nope, still an error +12265 8BE5 A6 A9 ldx CHRCNT ; get how many characters +12266 8BE7 8E 3C 8A stx SNAMEL ; save in length byte +12267 8BEA CA dex ; points one too far +12268 8BEB GNL: +12269 8BEB BD 00 02 lda LBUFF,X ; get the char +12270 8BEE 9D 3D 8A sta SAVENAME,X ; save the char +12271 8BF1 CA dex ; point to previous one +12272 8BF2 10 F7 bpl GNL ; and go get it +12273 8BF4 18 clc ; show did just fine +12274 8BF5 GNX: +12275 8BF5 08 php ; save status +12276 8BF6 A9 00 lda #0 ; and clear CHRCNT +12277 8BF8 85 A9 sta CHRCNT ; okay +12278 8BFA A9 0D lda #EOL ; print EOL +12279 8BFC 20 82 5D jsr CHAR ; okay +12280 8BFF 20 C9 4C jsr SWAPBACK ; change back to old window +12281 8C02 28 plp ; get status back +12282 8C03 60 rts ; all done +12283 ; +12284 ; open up a save file, by first trying to create it. If it already exists +12285 ; then make sure the player wants to delete the file, then get rid of it. +12286 ; Finally open the file. Return with carry set if user aborts the save. +12287 ; Store the ref number into the write parm block. +12288 ; +12289 8C04 OPEN_SAVE: +12290 8C04 CREATE CREATE_PB ; first try to create the file +12291 8C04 PRODOS $C0, CREATE_PB +12292 8C04 20 00 BF jsr $BF00 ; ProDOS handler +12293 8C07 C0 DB $C0 ; ProDOS function code +12294 8C08 F48A DW CREATE_PB ; Function Parameter Block address +12295 8C0A .MACEND +12296 8C0A .MACEND +12297 8C0A 90 16 bcc OPSV_OPEN ; created just fine, so open it +12298 ; +12299 ; can't create the file, check out why +12300 ; +12301 8C0C C9 47 cmp #$47 ; this means file already there +12302 8C0E F0 03 beq OPSV1 ; nope, not that +12303 8C10 4C 8A 47 jmp DISK_ERR ; show badness +12304 8C13 OPSV1: +12305 8C13 DLINE DELQ ; ask about deleting this file +12306 8C13 A2 8C ldx #DELQ ; get other part of string +12308 [01] IFMA 2 ; check to see if length passed in +12309 ldy ; then just fetch it + Wed Jun 7 1989 12:04 Page 184 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12310 [01] ELSE +12311 8C17 A0 23 ldy #DELQL ; get length of string +12312 [00] ENDIF +12313 8C19 20 6B 4C jsr DLINE ; print the string +12314 8C1C .MACEND +12315 8C1C 20 A9 8C jsr GETYN ; get me the yes or no +12316 8C1F 90 01 bcc OPSV_OPEN ; so then delete it if yes +12317 8C21 60 rts ; nope, so just quit +12318 8C22 OPSV_OPEN: +12319 8C22 OPEN OPEN_SV ; open the save file +12320 8C22 PRODOS $C8, OPEN_SV +12321 8C22 20 00 BF jsr $BF00 ; ProDOS handler +12322 8C25 C8 DB $C8 ; ProDOS function code +12323 8C26 058B DW OPEN_SV ; Function Parameter Block address +12324 8C28 .MACEND +12325 8C28 .MACEND +12326 8C28 90 03 bcc OPSV_OP1 ; okey, things worked just fine +12327 8C2A 4C 8A 47 jmp DISK_ERR ; complain about error +12328 8C2D OPSV_OP1: +12329 8C2D AD 0A 8B lda OPEN_SV+OP_REFNUM ; get the ref number +12330 8C30 8D 0E 8B sta WRITE_SV+WR_REFNUM ; save the ref number +12331 8C33 8D 0C 8B sta CLOSE_PB+CL_REFNUM ; to close parm too +12332 8C36 8D 01 8B sta SETEOF_PB+SE_REFNUM ; for cleansing file +12333 8C39 SET_EOF SETEOF_PB ; clear out file +12334 8C39 PRODOS $D0, SETEOF_PB +12335 8C39 20 00 BF jsr $BF00 ; ProDOS handler +12336 8C3C D0 DB $D0 ; ProDOS function code +12337 8C3D 008B DW SETEOF_PB ; Function Parameter Block address +12338 8C3F .MACEND +12339 8C3F .MACEND +12340 8C3F 90 03 bcc OPSVEX ; no problems +12341 8C41 20 8A 47 jsr DISK_ERR ; complain +12342 8C44 OPSVEX: +12343 8C44 60 rts ; file has been opened, return +12344 ; +12345 ; OPEN_RES - open the save file +12346 ; +12347 8C45 OPEN_RES: +12348 8C45 OPEN OPEN_SV ; open it up +12349 8C45 PRODOS $C8, OPEN_SV +12350 8C45 20 00 BF jsr $BF00 ; ProDOS handler +12351 8C48 C8 DB $C8 ; ProDOS function code +12352 8C49 058B DW OPEN_SV ; Function Parameter Block address +12353 8C4B .MACEND +12354 8C4B .MACEND +12355 8C4B 90 01 bcc OPR1 ; okay, it worked +12356 8C4D 60 rts ; okay, it didn't +12357 8C4E OPR1: +12358 8C4E AD 0A 8B lda OPEN_SV+OP_REFNUM ; get reference number +12359 8C51 8D CF 45 sta READ_PB+RD_REFNUM ; save for read +12360 8C54 8D 0C 8B sta CLOSE_PB+CL_REFNUM ; and for close +12361 8C57 60 rts +12362 ; +12363 ; CLOSE_SAVE - close up the save file if it is open, and +12364 ; restore open game files +12365 ; +12366 8C58 CLOSE_SAVE: +12367 8C58 AD 0C 8B lda CLOSE_PB+CL_REFNUM ; check if it opened +12368 8C5B F0 06 beq CLSVX ; okay, nothing +12369 8C5D CLOSE CLOSE_PB ; close the save file +12370 8C5D PRODOS $CC, CLOSE_PB +12371 8C5D 20 00 BF jsr $BF00 ; ProDOS handler +12372 8C60 CC DB $CC ; ProDOS function code +12373 8C61 0B8B DW CLOSE_PB ; Function Parameter Block address +12374 8C63 .MACEND +12375 8C63 .MACEND +12376 8C63 CLSVX: +12377 ; lda #1 ; flag is true +12378 ; sta SAVEDISK ; show we have a save disk in there +12379 ; jsr SET_GAMEPRE ; go get the last one used +12380 ; jsr FETCH_FILE ; this does it +12381 8C63 AE 77 46 ldx GAME1NML ; get length of current name +12382 8C66 BD 77 46 lda GAME1NM,X ; get the number of the file +12383 8C69 8D C5 49 sta SAVENUM ; we need this to look for prefix +12384 8C6C 8D 54 4A sta SAVEDISK ; show taking out save disk, not game disk + Wed Jun 7 1989 12:04 Page 185 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12385 8C6F 20 E1 4A jsr DO_GAME1 ; open up GAME1 file +12386 8C72 AD D3 1D lda D2SEG+HI ; set DSEGS to point to #2 +12387 8C75 85 1F sta DSEGS+HI +12388 8C77 AD D2 1D lda D2SEG+LO +12389 8C7A 85 1E sta DSEGS+LO +12390 8C7C AE 89 46 ldx GAME2NML ; get length of current name +12391 8C7F BD 89 46 lda GAME2NM,X ; get the number of the file +12392 8C82 8D C5 49 sta SAVENUM ; we need this to look for prefix +12393 8C85 20 1F 4A jsr OPEN_GAME2 ; open up GAME2 file +12394 8C88 A0 00 ldy #0 ; open up GAME2 file, just for kicks +12395 8C8A 8C 54 4A sty SAVEDISK ; show we have a save disk in there +12396 8C8D 8C 0C 8B sty CLOSE_PB+CL_REFNUM ; clear close +12397 8C90 C8 iny ; set for true +12398 8C91 84 AA sty SCRIPT ; allow scripting again +12399 8C93 60 rts ; DONE +12400 ; +12401 ; CLOSE_GAME - close the current game file(s) +12402 ; and set DSEGS to point to preload so it will reopen them +12403 ; +12404 8C94 CLOSE_GAME: +12405 8C94 A9 00 lda #0 ; show no files are open +12406 8C96 8D 0C 8B sta CLOSE_PB+CL_REFNUM ; 0 closes all files +12407 8C99 8D 87 46 sta GAME1REF ; zero out two game files too +12408 8C9C 8D 99 46 sta GAME2REF ; and here is number 2 +12409 8C9F 8D D3 73 sta PF_FID ; clear this too +12410 8CA2 CLOSE CLOSE_PB ; now all are closed +12411 8CA2 PRODOS $CC, CLOSE_PB +12412 8CA2 20 00 BF jsr $BF00 ; ProDOS handler +12413 8CA5 CC DB $CC ; ProDOS function code +12414 8CA6 0B8B DW CLOSE_PB ; Function Parameter Block address +12415 8CA8 .MACEND +12416 8CA8 .MACEND +12417 8CA8 60 rts +12418 ; +12419 ; Get answer to Yes/No question. Return with C==0 for yes, and C==1 +12420 ; for a no. RETURN == Yes, ESCAPE == NO +12421 ; +12422 8CA9 GETYN: +12423 8CA9 20 31 51 jsr GETKEY ; get the key strok +12424 8CAC C9 79 cmp #'y' ; IF REPLY IS "Y" +12425 8CAE F0 25 beq ALLSET ; ACCEPT RESPONSES +12426 8CB0 C9 59 cmp #'Y' ; get both y's +12427 8CB2 F0 21 beq ALLSET +12428 8CB4 C9 0D cmp #EOL ; EOL IS ALSO ACCEPTABLE +12429 8CB6 F0 1D beq ALLSET +12430 8CB8 C9 6E cmp #'n' ; IF REPLY IS "N" +12431 8CBA F0 0E beq NOTSAT ; return with carry set +12432 8CBC C9 4E cmp #'N' ; check both n's +12433 8CBE F0 0A beq NOTSAT +12434 8CC0 C9 1B cmp #ESCAPE ; check for ESC key too +12435 8CC2 F0 06 beq NOTSAT ; which means no +12436 8CC4 20 C3 4E jsr BEEP ; ELSE BEEP +12437 8CC7 4C A9 8C jmp GETYN ; INSIST ON Y OR N +12438 8CCA NOTSAT: +12439 8CCA DLINE NO ; PRINT "NO"/EOL +12440 8CCA A2 BD ldx #NO ; get other part of string +12442 [01] IFMA 2 ; check to see if length passed in +12443 ldy ; then just fetch it +12444 [01] ELSE +12445 8CCE A0 03 ldy #NOL ; get length of string +12446 [00] ENDIF +12447 8CD0 20 6B 4C jsr DLINE ; print the string +12448 8CD3 .MACEND +12449 8CD3 38 sec ; set the carry +12450 8CD4 60 rts ; and show it +12451 8CD5 ALLSET: +12452 8CD5 DLINE YES ; Print "YES"/EOL +12453 8CD5 A2 B9 ldx #YES ; get other part of string +12455 [01] IFMA 2 ; check to see if length passed in +12456 ldy ; then just fetch it +12457 [01] ELSE +12458 8CD9 A0 04 ldy #YESL ; get length of string +12459 [00] ENDIF + Wed Jun 7 1989 12:04 Page 186 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12460 8CDB 20 6B 4C jsr DLINE ; print the string +12461 8CDE .MACEND +12462 8CDE 18 clc ; clear the carry +12463 8CDF 60 rts +12464 8CE0 GETRET: +12465 8CE0 DLINE RETQ ; ask for return +12466 8CE0 A2 AE ldx #RETQ ; get other part of string +12468 [01] IFMA 2 ; check to see if length passed in +12469 ldy ; then just fetch it +12470 [01] ELSE +12471 8CE4 A0 15 ldy #RETQL ; get length of string +12472 [00] ENDIF +12473 8CE6 20 6B 4C jsr DLINE ; print the string +12474 8CE9 .MACEND +12475 8CE9 GETRETL: +12476 8CE9 20 31 51 jsr GETKEY ; get a key +12477 8CEC C9 0D cmp #EOL ; return key? +12478 8CEE D0 F9 bne GETRETL ; nope +12479 8CF0 20 82 5D jsr CHAR ; show the +12480 8CF3 60 rts +12481 8CF4 +12482 ; --------- +12483 ; SAVE GAME +12484 ; --------- +12485 8CF4 ZSAVE: +12486 8CF4 A9 4E lda #'N' +12487 8CF6 A6 62 ldx NARGS +12488 8CF8 F0 02 beq OLDSAV ; NORMAL, COMPLETE SAVE +12489 8CFA A9 50 lda #'P' +12490 8CFC OLDSAV: +12491 8CFC 8D 67 5B sta TYPE +12492 8CFF 20 A8 89 jsr SAVRES ; set up screen +12493 8D02 20 15 8B jsr GET_SNAME ; get the name of the save file +12494 8D05 B0 7B bcs ZSEXIT ; don't wanna after all +12495 8D07 20 04 8C jsr OPEN_SAVE ; open the file +12496 8D0A B0 76 bcs ZSEXIT ; don't really care to +12497 ; +12498 ; SAVE GAME PARAMETERS IN [BUFSAV] +12499 ; +12500 8D0C AD 02 96 lda ZBEGIN+ZID ; MOVE GAME ID +12501 8D0F 8D 20 1E sta BUFSAV+0 ; INTO 1ST 2 BYTES +12502 8D12 AD 03 96 lda ZBEGIN+ZID+1 ; OF THE A +12503 8D15 8D 21 1E sta BUFSAV+1 +12504 8D18 A5 AF lda ZSP+LO ; MOVE [ZSP] +12505 8D1A 8D 22 1E sta BUFSAV+2 +12506 8D1D A5 B0 lda ZSP+HI +12507 8D1F 8D 23 1E sta BUFSAV+3 +12508 8D22 AD 7A 6C lda OLDZSP+LO +12509 8D25 8D 24 1E sta BUFSAV+4 +12510 8D28 AD 7B 6C lda OLDZSP+HI ; MOVE [OLDZSP] +12511 8D2B 8D 25 1E sta BUFSAV+5 +12512 8D2E A2 02 ldx #2 ; MOVE CONTENTS OF [ZPC] +12513 8D30 B5 80 ZSL1: lda ZPC,X ; TO BYTES 7-9 +12514 8D32 9D 26 1E sta BUFSAV+6,X ; OF [BUFSAV] +12515 8D35 CA dex +12516 8D36 10 F8 bpl ZSL1 +12517 8D38 AD 67 5B lda TYPE +12518 8D3B 8D 29 1E sta BUFSAV+9 ; NORMAL OR PARTIAL +12519 8D3E C9 50 cmp #'P' +12520 8D40 D0 2A bne ZSNONM ; NORMAL SAVE SO NO name TO SAVE +12521 +12522 8D42 A5 67 lda ARG3+LO ; set up FPC to get save name +12523 8D44 85 8C sta FPCL ; lo part is okay +12524 8D46 A5 68 lda ARG3+HI ; get page +12525 8D48 20 7C 8F jsr SETPC ; get memory addr +12526 8D4B 85 8D sta FPCH ; page number +12527 8D4D 84 8E sty FPCBNK ; and bank +12528 8D4F 20 5B 92 jsr FETCHB ; get count +12529 8D52 85 78 sta I ; and save it +12530 8D54 20 C3 8F jsr NEXTFPC ; point to next byte +12531 8D57 A9 00 lda #0 ; set up data offset +12532 8D59 85 7A sta J ; did it +12533 8D5B ZSL3: +12534 8D5B 20 5B 92 jsr FETCHB ; get data byte + Wed Jun 7 1989 12:04 Page 187 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12535 8D5E A4 7A ldy J ; get offset +12536 8D60 99 2A 1E sta BUFSAV+10,Y ; save into buffer +12537 8D63 20 C3 8F jsr NEXTFPC ; point to next byte +12538 8D66 E6 7A inc J ; next byte +12539 8D68 C6 78 dec I ; count it +12540 8D6A D0 EF bne ZSL3 ; loop again +12541 8D6C ZSNONM: +12542 ; +12543 ; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK +12544 ; +12545 8D6C A9 00 lda #MAIN ; in the main bank +12546 8D6E 85 B8 sta DSKBNK ; thank you +12547 8D70 A9 1E lda #>LOCALS ; start at locals +12548 8D72 85 B7 sta DBUFF+HI ; POINT TO THE PAGE +12549 8D74 20 F6 47 jsr PUTDSK ; AND WRITE IT OUT +12550 8D77 90 0F bcc ZSOK ; IF SUCCEEDED, WRITE STACK +12551 8D79 ZSBAD: +12552 8D79 20 8A 47 jsr DISK_ERR ; print error message +12553 8D7C SET_EOF SETEOF_PB ; clear out file, maybe +12554 8D7C PRODOS $D0, SETEOF_PB +12555 8D7C 20 00 BF jsr $BF00 ; ProDOS handler +12556 8D7F D0 DB $D0 ; ProDOS function code +12557 8D80 008B DW SETEOF_PB ; Function Parameter Block address +12558 8D82 .MACEND +12559 8D82 .MACEND +12560 8D82 ZSEXIT: +12561 8D82 20 58 8C jsr CLOSE_SAVE ; else get game file back +12562 8D85 4C DA 43 jmp RET0 ; AND FAIL +12563 ; +12564 ; IF A PARTIAL SAVE WRITE FROM ARG1 FOR ARG2 BYTES TO DISK +12565 ; (ROUNDED TO PGS) SKIPPING ZSTACK WRITE +12566 ; +12567 8D88 ZSOK: +12568 8D88 AD 67 5B lda TYPE +12569 8D8B C9 50 cmp #'P' +12570 8D8D D0 1F bne ZSALL +12571 8D8F A5 64 lda ARG1+HI ; find where to start & how far to go +12572 8D91 20 7C 8F jsr SETPC ; get page in memory +12573 8D94 48 pha ; save for minute +12574 8D95 29 01 and #$01 ; check for odd page +12575 8D97 F0 02 beq ZSP1 ; nope, don't make one more page +12576 8D99 E6 66 inc ARG2+HI ; go get one more page +12577 8D9B ZSP1: +12578 8D9B 68 pla ; get it back +12579 8D9C 29 FE and #$FE ; must be on block boundary +12580 8D9E 85 B7 sta DBUFF+HI ; this is page +12581 8DA0 84 B8 sty DSKBNK ; which bank +12582 8DA2 A6 66 ldx ARG2+HI ; get MSB of count +12583 8DA4 A5 63 lda ARG1+LO ; get lo offset +12584 8DA6 18 clc ; add +12585 8DA7 65 65 adc ARG2+LO ; lo count +12586 8DA9 90 01 bcc ZSPINC ; no extra page +12587 8DAB E8 inx ; wrapped extra page +12588 8DAC ZSPINC: +12589 8DAC D0 15 bne SAVE2DISK ; go copy it now +12590 ; +12591 ; WRITE CONTENTS OF Z-STACK TO DISK +12592 ; +12593 8DAE ZSALL: +12594 8DAE A9 0D lda #>ZSTKBL ; point to 1st page +12595 8DB0 85 B7 sta DBUFF+HI +12596 8DB2 20 F6 47 jsr PUTDSK ; write them, first one +12597 8DB5 B0 C2 bcs ZSBAD +12598 8DB7 20 F6 47 jsr PUTDSK ; write them, second one +12599 8DBA B0 BD bcs ZSBAD +12600 ; +12601 ; WRITE ENTIRE GAME PRELOAD TO DISK +12602 ; +12603 8DBC A9 96 lda #>ZBEGIN ; POINT TO 1ST PAGE +12604 8DBE 85 B7 sta DBUFF+HI ; OF PRELOAD +12605 8DC0 AE 0E 96 ldx ZBEGIN+ZPURBT ; GET # IMPURE PAGES +12606 8DC3 SAVE2DISK: +12607 8DC3 E8 inx ; use for counting +12608 8DC4 86 78 stx I+LO +12609 8DC6 46 78 lsr I+LO ; /2 for 512byte pages + Wed Jun 7 1989 12:04 Page 188 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12610 8DC8 90 02 bcc ZSL2 ; no wrapping +12611 8DCA E6 78 inc I+LO ; wrapped once +12612 8DCC ZSL2: +12613 8DCC 20 F6 47 jsr PUTDSK ; this does the write +12614 8DCF B0 A8 bcs ZSBAD +12615 8DD1 C6 78 dec I+LO ; count one page +12616 8DD3 D0 F7 bne ZSL2 ; not done yet +12617 +12618 8DD5 20 58 8C jsr CLOSE_SAVE ; prompt for game file +12619 +12620 [01] IF CHECKSUM == 1 +12621 lda CKS_COUNT +12622 jsr HEXNUM +12623 lda CKSB +12624 jsr HEXNUM +12625 lda #EOL +12626 jsr CHAR +12627 [00] ENDIF +12628 +12629 8DD8 A9 01 lda #1 ; set to mark +12630 8DDA A2 00 ldx #0 +12631 8DDC 4C DD 43 jmp PUTBYT ; SUCCESS +12632 +12633 ; ------------ +12634 ; RESTORE GAME +12635 ; ------------ +12636 +12637 8DDF ZREST: +12638 8DDF A9 4E lda #'N' +12639 8DE1 A6 62 ldx NARGS +12640 8DE3 F0 02 beq OLDRES ; NORMAL, COMPLETE RESTORE +12641 8DE5 A9 50 lda #'P' ; partial restore +12642 8DE7 OLDRES: +12643 8DE7 8D 67 5B sta TYPE ; save which kind of restore +12644 ; +12645 ; SAVE LOCALS IN CASE OF ERROR +12646 ; +12647 8DEA A2 1F ldx #31 +12648 8DEC BD 00 1E LOCSAV: lda LOCALS,X ; COPY ALL LOCALS +12649 8DEF 9D E0 1D sta LOCAL_SV,X ; to a save spot +12650 8DF2 CA dex +12651 8DF3 10 F7 bpl LOCSAV +12652 +12653 8DF5 20 15 8B jsr GET_SNAME ; get the name of the file +12654 8DF8 B0 3C bcs ZRQUIT ; okay, don't do it +12655 8DFA 20 45 8C jsr OPEN_RES ; open the restore file +12656 8DFD B0 34 bcs ZRBAD ; can't do it +12657 +12658 8DFF AD 67 5B lda TYPE ; PARTIAL SAVE DIFFERS STARTING HERE +12659 8E02 C9 50 cmp #'P' +12660 8E04 D0 03 bne ZRNRML +12661 8E06 4C C7 8E jmp ZPARTR ; just a partial restore +12662 8E09 ZRNRML: +12663 8E09 A9 00 lda #MAIN +12664 8E0B 85 B8 sta DSKBNK ; SET TO WRITE TO MAIN BANK +12665 8E0D A9 1E lda #>LOCALS +12666 8E0F 85 B7 sta DBUFF+HI +12667 8E11 A9 02 lda #2 ; must read in two pages +12668 8E13 85 7E sta L+LO +12669 8E15 20 11 48 jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD +12670 8E18 B0 19 bcs ZRBAD ; didn't work! +12671 8E1A AD D5 45 lda READ_PB+RD_LENGTH+HI ; see how much was read in +12672 8E1D C9 02 cmp #2 ; were 2 blocks read in? +12673 8E1F D0 15 bne ZRQUIT ; wrong kind of file for complete save +12674 +12675 8E21 AD 20 1E lda BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID +12676 8E24 CD 02 96 cmp ZBEGIN+ZID ; MATCH THE CURRENT ID? +12677 8E27 D0 0D bne ZRQUIT ; WRONG DISK IF NOT +12678 +12679 8E29 AD 21 1E lda BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE? +12680 8E2C CD 03 96 cmp ZBEGIN+ZID+1 +12681 8E2F F0 16 beq ZROK ; CONTINUE IF BOTH BYTES MATCH +12682 8E31 D0 03 bne ZRQUIT ; skip disk error message +12683 ; +12684 ; HANDLE RESTORE ERROR + Wed Jun 7 1989 12:04 Page 189 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12685 ; +12686 8E33 ZRBAD: +12687 8E33 20 8A 47 jsr DISK_ERR ; print error message +12688 8E36 ZRQUIT: +12689 8E36 A2 1F ldx #31 ; RESTORE ALL SAVED LOCALS +12690 8E38 BD E0 1D ZRL2: lda LOCAL_SV,X +12691 8E3B 9D 00 1E sta LOCALS,X +12692 8E3E CA dex +12693 8E3F 10 F7 bpl ZRL2 +12694 8E41 BADRES: +12695 8E41 20 58 8C jsr CLOSE_SAVE ; PROMPT FOR GAME DISK +12696 8E44 4C DA 43 jmp RET0 ; PREDICATE FAILS +12697 ; +12698 ; CONTINUE RESTORE +12699 ; +12700 8E47 ZROK: +12701 8E47 AD 10 96 lda ZBEGIN+ZFLAGS ; save both flag bytes +12702 8E4A 85 7A sta J+LO +12703 8E4C AD 11 96 lda ZBEGIN+ZFLAGS+1 +12704 8E4F 85 7B sta J+HI +12705 +12706 8E51 A9 0D lda #>ZSTKBL ; retrieve old contents of +12707 8E53 85 B7 sta DBUFF+HI ; z-stack +12708 8E55 A9 04 lda #4 ; do 4 pages +12709 8E57 85 7E sta L+LO ; tell GETRES how many pages +12710 8E59 20 11 48 jsr GETRES ; get 4 pages of z-stack +12711 8E5C 90 03 bcc ZROKL1 +12712 8E5E 4C 74 47 jmp DISK_FATAL ; if here, mix of good & bad so die +12713 8E61 ZROKL1: +12714 8E61 A9 96 lda #>ZBEGIN ; get where we are +12715 8E63 85 B7 sta DBUFF+HI +12716 8E65 AD 0E 96 lda ZBEGIN+ZPURBT ; get # pages to load +12717 8E68 85 78 sta I+LO +12718 8E6A E6 78 inc I+LO ; go get last page if possible +12719 8E6C LREST0: +12720 8E6C A5 78 lda I+LO ; how many pages left +12721 8E6E F0 20 beq LRESTj ; finis +12722 8E70 38 sec ; doing subtract +12723 8E71 E9 04 sbc #4 ; doing it 4 blocks at a time +12724 8E73 90 0E bcc LREST1 ; <4 blocks left so deal with it special +12725 8E75 85 78 sta I+LO ; save remenants +12726 8E77 LREST: +12727 8E77 A9 04 lda #4 ; assume at least 4 pages +12728 8E79 85 7E sta L+LO ; this tells GETRES how many to read in +12729 8E7B 20 11 48 jsr GETRES ; fetch the remainder +12730 8E7E 90 EC bcc LREST0 +12731 8E80 4C 74 47 jmp DISK_FATAL +12732 8E83 LREST1: +12733 8E83 A5 78 lda I+LO ; get how many left +12734 8E85 85 7E sta L+LO ; and show it to GETRES +12735 8E87 29 01 and #$1 ; is it odd? +12736 8E89 F0 02 beq LREST2 ; nope +12737 8E8B E6 7E inc L+LO ; read one more +12738 8E8D LREST2: +12739 8E8D 20 11 48 jsr GETRES ; and finish it up +12740 ; +12741 ; RESTORE THE STATE OF THE SAVED GAME +12742 ; +12743 8E90 LRESTj: +12744 8E90 A5 7A lda J+LO ; RESTORE THE STATE +12745 8E92 8D 10 96 sta ZBEGIN+ZFLAGS ; OF THE FLAG WORD +12746 8E95 A5 7B lda J+HI +12747 8E97 8D 11 96 sta ZBEGIN+ZFLAGS+1 +12748 +12749 8E9A AD 22 1E lda BUFSAV+2 ; RESTORE THE [ZSP] +12750 8E9D 85 AF sta ZSP+LO +12751 8E9F AD 23 1E lda BUFSAV+3 +12752 8EA2 85 B0 sta ZSP+HI +12753 8EA4 AD 24 1E lda BUFSAV+4 +12754 8EA7 8D 7A 6C sta OLDZSP+LO +12755 8EAA AD 25 1E lda BUFSAV+5 ; AND THE [OLDZSP] +12756 8EAD 8D 7B 6C sta OLDZSP+HI +12757 +12758 8EB0 A2 02 ldx #2 ; RESTORE THE [ZPC] +12759 8EB2 BD 26 1E ZRL4: lda BUFSAV+6,X + Wed Jun 7 1989 12:04 Page 190 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12760 8EB5 95 80 sta ZPC,X +12761 8EB7 CA dex +12762 8EB8 10 F8 bpl ZRL4 +12763 +12764 8EBA 20 58 8C ZROUT: jsr CLOSE_SAVE ; PROMPT FOR GAME DISK +12765 8EBD 20 AF 90 jsr VLDZPC ; MAKE VALID (MUST DO AFTER GET DISK) +12766 +12767 [01] IF CHECKSUM == 1 +12768 lda CKS_COUNT +12769 jsr HEXNUM +12770 lda CKSB +12771 jsr HEXNUM +12772 lda #EOL +12773 jsr CHAR +12774 [00] ENDIF +12775 +12776 8EC0 A9 02 lda #2 ; SET TO +12777 8EC2 A2 00 ldx #0 +12778 8EC4 4C DD 43 jmp PUTBYT ; SUCCESS +12779 +12780 +12781 ; DO PARTIAL RESTORE GETTING 1ST PAGE +12782 ; AND LAST PAGE BYTE ALIGNMENT CORRECT +12783 ; WRITE LOCALS TO IOBUFF JUST TO LOOK AT NAME +12784 8EC7 ZPARTR: +12785 8EC7 A9 00 lda #MAIN +12786 8EC9 85 B8 sta DSKBNK +12787 8ECB A9 08 lda #>IOBUFF ; DON'T READ TO LOCALS YET (X) +12788 8ECD 85 B7 sta DBUFF+HI +12789 8ECF A9 02 lda #2 ; just one block please +12790 8ED1 85 7E sta L+LO +12791 8ED3 20 11 48 jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD +12792 8ED6 90 03 bcc ZRN2 ; worked just fine +12793 8ED8 ZPBAD: +12794 8ED8 4C 41 8E jmp BADRES ; names don't match, die +12795 8EDB ZRN2: +12796 8EDB A5 67 lda ARG3+LO ; set up FPC to get save name +12797 8EDD 85 8C sta FPCL ; lo part is okay +12798 8EDF A5 68 lda ARG3+HI ; get page +12799 8EE1 20 7C 8F jsr SETPC ; get memory addr +12800 8EE4 85 8D sta FPCH ; page number +12801 8EE6 84 8E sty FPCBNK ; and bank +12802 8EE8 20 5B 92 jsr FETCHB ; get count +12803 8EEB 85 78 sta I ; and save it +12804 8EED 20 C3 8F jsr NEXTFPC ; point to next byte +12805 8EF0 A9 20 lda #IOBUFF ; get 1st page +12834 8F24 85 B7 sta DBUFF+HI ; getres should keep in iobuff + Wed Jun 7 1989 12:04 Page 191 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12835 8F26 8D 42 8F sta ZPARTMOD+2 ; and show where to get it from +12836 8F29 A9 01 lda #$01 ; is it odd +12837 8F2B 24 90 bit SPCH ; get page destination +12838 8F2D F0 03 beq ZPARTx ; nope +12839 8F2F EE 42 8F inc ZPARTMOD+2 ; then get second page worth +12840 8F32 ZPARTx: +12841 8F32 A9 02 lda #2 ; just do one block +12842 8F34 85 7E sta L+LO +12843 8F36 20 11 48 jsr GETRES +12844 8F39 90 03 bcc ZPART0 +12845 8F3B 4C 74 47 jmp DISK_FATAL ; ALL MESSED UP, JUST QUIT +12846 8F3E ZPART0: +12847 8F3E A4 63 ldy ARG1+LO ; START BYTE FIRST PAGE +12848 8F40 ZPARTMOD: +12849 8F40 B9 00 08 lda IOBUFF,Y ; this gets modified with good page # +12850 8F43 20 3A 92 jsr STASHB +12851 8F46 20 A3 8F jsr NEXTSPC +12852 8F49 20 C6 44 jsr DECJ +12853 8F4C B0 03 bcs ZPART1 ; CARRY CLEAR IF $FFFF RESULT +12854 8F4E 4C BA 8E jmp ZROUT +12855 8F51 ZPART1: +12856 8F51 E6 63 inc ARG1+LO +12857 8F53 D0 E9 bne ZPART0 +12858 8F55 A9 09 lda #>IOBUFF+1 ; this is second page address +12859 8F57 CD 42 8F cmp ZPARTMOD+2 ; is it second one already? +12860 8F5A F0 C6 beq POK ; yes, so read in a new block +12861 8F5C 8D 42 8F sta ZPARTMOD+2 ; then update it +12862 8F5F D0 DD bne ZPART0 ; and do it again +12863 ; +12864 ; THE OLD SAVE & RESTORE STILL HAVE OPCODES +12865 ; SO JUST PUT IN A PLACE FOR THEM HERE FOR NOW +12866 ; +12867 8F61 OSAVE: +12868 8F61 60 OREST: RTS +12869 +12870 8F62 ZISAVE: +12871 8F62 4C DA 43 ZIREST: JMP RET0 ; NOT IMPLEMENTED ON APPLE +12872 8F65 END +12873 +12874 +12875 8F65 TITLE "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" +12876 8F65 INCLUDE XPAGING.ASM +12877 8F65 STTL "--- MEMORY PAGING ROUTINES ---" +12878 PAGE + Wed Jun 7 1989 12:04 Page 192 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +12879 +12880 ; ------------------------- +12881 ; POINT [MPC] TO V-ADDR [I] +12882 ; ------------------------- +12883 +12884 8F65 A5 78 SETWRD: LDA I+LO +12885 8F67 85 86 STA MPCL +12886 8F69 A5 79 LDA I+HI +12887 8F6B 85 87 STA MPCM +12888 8F6D A9 00 LDA #0 +12889 8F6F 85 88 STA MPCH ; ZERO TOP BIT +12890 8F71 4C 85 90 JMP VLDMPC +12891 +12892 ; +12893 8F74 00 00 WANTED: DB 00,00 +12894 ; +12895 8F76 00 NEXT: DB 00 +12896 8F77 00 NSUBA: DB 00 +12897 8F78 00 PSUBA: DB 00 +12898 ; +12899 8F79 00 YTEMP: DB 00 +12900 8F7A 00 ATEMP: DB 00 +12901 8F7B 00 NSUBY: DB 00 +12902 ; +12903 ; set [A](page), [Y](bank) to point to memory page where page in [A] is +12904 ; +12905 8F7C SETPC: +12906 8F7C 85 BC sta MEMPAGE ; save it for later addition +12907 8F7E C9 29 cmp #P2PAGE ; IS IT A PAGE IN MAIN +12908 8F80 B0 06 bcs VF2 ; No, it might be in aux mem +12909 +12910 8F82 A9 96 lda #>ZBEGIN ; ADD OFFSET TO GET RAM PAGE +12911 8F84 A0 00 ldy #MAIN ; in the main bank +12912 8F86 F0 12 beq VFEXI ; BRA to fetch +12913 8F88 VF2: +12914 8F88 C9 D6 cmp #PGBEGIN ; is it paged? +12915 8F8A B0 12 bcs VFERR ; yes it be paged, so can't deal with it +12916 8F8C C9 A8 cmp #P3PAGE ; is it in Aux Mem, Part 2? +12917 8F8E B0 06 bcs VF3 ; yes, so subtract different amount +12918 ; +12919 ; this is in lower aux +12920 ; +12921 8F90 A9 17 lda #(Z2PAGE-Z1SIZE) ; subtract size from offset +12922 8F92 A0 01 ldy #AUX ; show aux mem +12923 8F94 D0 04 bne VFEXI ; jump to end +12924 8F96 VF3: +12925 8F96 A9 28 lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides +12926 8F98 A0 FF ldy #P3BANK ; show page 3 bank +12927 8F9A VFEXI: +12928 8F9A 18 clc ; get ready for addition +12929 8F9B 65 BC adc MEMPAGE ; now get actual offset +12930 8F9D 60 rts +12931 8F9E VFERR: +12932 ; +12933 ; out of range +12934 ; +12935 8F9E A9 12 lda #18 +12936 8FA0 4C 0A 52 jmp ZERROR +12937 ; +12938 ; NEXTSPC - inc SPCL and check for wrapping round to next bank +12939 ; +12940 8FA3 NEXTSPC: +12941 8FA3 E6 8F inc SPCL ; next lo byte +12942 8FA5 D0 1B bne NXSP_EXIT ; no change then +12943 8FA7 E6 90 inc SPCH ; next page +12944 8FA9 A5 90 lda SPCH ; so get page +12945 8FAB C9 BF cmp #>PRGLBL ; have we reached end of line? +12946 8FAD D0 13 bne NXSP_EXIT ; we be okay +12947 8FAF A5 91 lda SPCBNK ; get bank +12948 8FB1 D0 07 bne NXSP1 ; must go to Part 3 +12949 8FB3 E6 91 inc SPCBNK ; so point to aux bank +12950 8FB5 A9 40 lda #Z2PAGE ; first page in aux +12951 8FB7 85 90 sta SPCH ; and point to it +12952 8FB9 60 rts ; and all done +12953 8FBA NXSP1: + Wed Jun 7 1989 12:04 Page 193 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +12954 8FBA A9 D0 lda #Z3PAGE ; get start of page 3 +12955 8FBC 85 90 sta SPCH ; and point there +12956 8FBE A9 FF lda #P3BANK ; and point to this bank +12957 8FC0 85 91 sta SPCBNK ; okey +12958 8FC2 NXSP_EXIT: +12959 8FC2 60 rts +12960 ; +12961 ; NEXTFPC - inc DPCL and check for wrapping round to next bank +12962 ; +12963 8FC3 NEXTFPC: +12964 8FC3 E6 8C inc FPCL ; next lo byte +12965 8FC5 D0 1B bne NXFP_EXIT ; no change then +12966 8FC7 E6 8D inc FPCH ; next page +12967 8FC9 A5 8D lda FPCH ; and get it for checking +12968 8FCB C9 BF cmp #>PRGLBL ; have we reached end of line? +12969 8FCD D0 13 bne NXFP_EXIT ; we be okay +12970 8FCF A5 8E lda FPCBNK ; get bank +12971 8FD1 D0 07 bne NXFP1 ; must skip over stuff in middle +12972 8FD3 E6 8E inc FPCBNK ; so point to aux bank +12973 8FD5 A9 40 lda #Z2PAGE ; first page in aux +12974 8FD7 85 8D sta FPCH ; and point to it +12975 8FD9 60 rts ; toots finis +12976 8FDA NXFP1: +12977 8FDA A9 D0 lda #Z3PAGE ; start of part 3 +12978 8FDC 85 8D sta FPCH ; so show me +12979 8FDE A9 FF lda #P3BANK ; and point to this bank +12980 8FE0 85 8E sta FPCBNK ; okey +12981 8FE2 NXFP_EXIT: +12982 8FE2 60 rts +12983 ; +12984 ; ADDFPC - add amount in [A] to current FPC and check for bank wrap +12985 ; +12986 8FE3 ADDFPC: +12987 8FE3 18 clc ; get ready for add +12988 8FE4 65 8C adc FPCL ; add lo part +12989 8FE6 85 8C sta FPCL ; and save it +12990 8FE8 90 1B bcc AFPX ; all done if no page wrap +12991 8FEA E6 8D inc FPCH ; point to next page +12992 8FEC A5 8D lda FPCH ; get it for compare +12993 8FEE C9 BF cmp #>PRGLBL ; at end of line in main bank? +12994 8FF0 D0 13 bne AFPX ; nope, all done then +12995 8FF2 A5 8E lda FPCBNK ; get bank +12996 8FF4 F0 09 beq AFP1 ; it is main, so we be ok +12997 8FF6 A9 D0 lda #Z3PAGE ; must go to part 3 if in aux mem +12998 8FF8 85 8D sta FPCH ; thanx +12999 8FFA A9 FF lda #P3BANK ; and point to this bank +13000 8FFC 85 8E sta FPCBNK ; okey +13001 8FFE 60 rts ; done +13002 8FFF AFP1: +13003 8FFF E6 8E inc FPCBNK ; point to aux +13004 9001 A9 40 lda #Z2PAGE ; get start in aux +13005 9003 85 8D sta FPCH ; and save it +13006 9005 AFPX: +13007 9005 60 rts +13008 ; +13009 ; ADDSPC - add amount in [A] to current SPC and check for bank wrap +13010 ; +13011 9006 ADDSPC: +13012 9006 18 clc ; get ready for add +13013 9007 65 8F adc SPCL ; add lo part +13014 9009 85 8F sta SPCL ; and save it +13015 900B 90 1B bcc ASPX ; all done if no page wrap +13016 900D E6 90 inc SPCH ; point to next page +13017 900F A5 90 lda SPCH ; get it for compare +13018 9011 C9 BF cmp #>PRGLBL ; at end of line in main bank? +13019 9013 D0 13 bne ASPX ; nope, all done then +13020 9015 A5 91 lda SPCBNK ; get bank +13021 9017 F0 09 beq ASP1 ; it is main, so we be ok +13022 9019 A9 D0 lda #Z3PAGE ; must go to part 3 if in aux mem +13023 901B 85 90 sta SPCH ; thanx +13024 901D A9 FF lda #P3BANK ; and point to this bank +13025 901F 85 91 sta SPCBNK ; okey +13026 9021 60 rts ; done +13027 9022 ASP1: +13028 9022 E6 91 inc SPCBNK ; point to aux + Wed Jun 7 1989 12:04 Page 194 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13029 9024 A9 40 lda #Z2PAGE ; get start in aux +13030 9026 85 90 sta SPCH ; and save it +13031 9028 ASPX: +13032 9028 60 rts +13033 ; +13034 ; PREVFPC - DEC FPCL and check for wrapping round to next bank +13035 ; +13036 9029 PREVFPC: +13037 9029 A5 8C lda FPCL ; get lo part +13038 902B D0 1E bne PFPC2 ; it's not zero, so no wrapping +13039 902D A5 8D lda FPCH ; get current page +13040 902F C9 40 cmp #Z2PAGE ; have we reached beginning of page 2? +13041 9031 F0 08 beq PFPC1 ; wrap to first bank +13042 9033 C9 D0 cmp #Z3PAGE ; beginning of part 3? +13043 9035 F0 0C beq PFPC3 ; ayyup +13044 9037 C6 8D dec FPCH ; point to previous page +13045 9039 D0 10 bne PFPC2 ; okay +13046 903B PFPC1: +13047 903B A5 8E lda FPCBNK ; get bank +13048 903D F0 0F beq VF1ERR ; oops, can't go backwards from main bank +13049 903F A9 00 lda #MAIN ; so point to main bank +13050 9041 F0 02 beq PFPC4 ; and store it away +13051 9043 PFPC3: +13052 9043 A9 01 lda #AUX ; and point to this bank +13053 9045 PFPC4: +13054 9045 85 8E sta FPCBNK ; okey +13055 9047 A9 BE lda #(>PRGLBL)-1 ; get me last page in part 2 +13056 9049 85 8D sta FPCH ; and show me +13057 904B PFPC2: +13058 904B C6 8C dec FPCL ; and point to previous byte +13059 904D 60 rts +13060 904E VF1ERR: +13061 ; +13062 ; out of range +13063 ; +13064 904E A9 13 lda #19 +13065 9050 4C 0A 52 jmp ZERROR +13066 ; +13067 ; PREVSPC - DEC SPCL and check for wrapping round to main bank +13068 ; +13069 9053 PREVSPC: +13070 9053 A5 8F lda SPCL ; get lo part +13071 9055 D0 1E bne PSPC2 ; it's not zero, so no wrapping +13072 9057 A5 90 lda SPCH ; get current page +13073 9059 C9 40 cmp #Z2PAGE ; have we reached beginning of page 2? +13074 905B F0 08 beq PSPC1 ; wrap to first bank +13075 905D C9 D0 cmp #Z3PAGE ; down past page 3? +13076 905F F0 0C beq PSPC3 ; sure is +13077 9061 C6 90 dec SPCH ; point to previous page +13078 9063 D0 10 bne PSPC2 ; okay +13079 9065 PSPC1: +13080 9065 A5 91 lda SPCBNK ; get bank +13081 9067 F0 E5 beq VF1ERR ; oops, can't go backwards from main bank +13082 9069 A9 00 lda #MAIN ; so point to main bank +13083 906B F0 02 beq PSPC4 ; so save it +13084 906D PSPC3: +13085 906D A9 01 lda #AUX ; and point to this bank +13086 906F PSPC4: +13087 906F 85 8E sta FPCBNK ; okey +13088 9071 A9 BE lda #>PRGLBL-1 ; get me last page in low part +13089 9073 85 90 sta SPCH ; and show me +13090 9075 PSPC2: +13091 9075 C6 8F dec SPCL ; and point to previous byte +13092 9077 60 rts +13093 ; +13094 ; FP2SP - copy the 3 parts of FPC to SPC +13095 ; +13096 9078 FP2SP: +13097 9078 A5 8E lda FPCBNK +13098 907A 85 91 sta SPCBNK +13099 907C A5 8D lda FPCH +13100 907E 85 90 sta SPCH +13101 9080 A5 8C lda FPCL +13102 9082 85 8F sta SPCL +13103 9084 60 rts + Wed Jun 7 1989 12:04 Page 195 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13104 9085 +13105 ; MAKE [MPCPNT],[MPCBNK] POINT TO +13106 ; THE RAM PAGE AND BANK THAT HOLDS +13107 ; THE V-PAGE MPCH,M +13108 ; +13109 9085 VLDMPC: +13110 9085 A5 88 lda MPCH ; check hi part +13111 9087 D0 0F bne VLD3 ; NOT IN FIRST V-64K, so must be paged +13112 9089 A5 87 lda MPCM ; check to see if it is paged +13113 908B 20 A7 91 jsr CHECKPRE ; is it preloaded? +13114 908E B0 08 bcs VLD3 ; no, so it be paged +13115 9090 20 7C 8F jsr SETPC ; so put page/bank into A/Y +13116 9093 84 8B sty MPCBNK +13117 9095 85 8A sta MPCPNT+HI +13118 9097 NOMUCK: +13119 9097 60 rts +13120 ; +13121 ; must be paged, so check for it or read it in +13122 ; +13123 9098 VLD3: +13124 9098 A5 88 lda MPCH +13125 909A A4 87 ldy MPCM +13126 909C 20 E5 90 jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y +13127 909F 18 clc +13128 90A0 69 08 adc #>PBEGIN +13129 90A2 85 8A sta MPCPNT+HI +13130 90A4 A0 01 ldy #PB_BANK ; paging buffers are in aux mem +13131 90A6 84 8B sty MPCBNK +13132 ; +13133 ; TEST FOR MUCK +13134 ; +13135 90A8 AD E4 90 lda MUCKFLG +13136 90AB F0 EA beq NOMUCK +13137 90AD D0 00 bne VLDZPC ;MAY HAVE MUCKED ZPC SO GO FIX +13138 ; +13139 ; SAME IDEA AS VLDMPC +13140 ; +13141 90AF VLDZPC: +13142 90AF A5 59 lda INFODOS ; check first for InfoDOS page +13143 90B1 F0 06 beq VLDZ1 ; none +13144 90B3 20 BC 91 jsr INFO_PAGE ; well, is it? +13145 90B6 90 01 bcc VLDZ1 ; nope +13146 90B8 60 rts ; all set otherwise +13147 90B9 VLDZ1: +13148 90B9 A5 82 lda ZPCH +13149 90BB D0 0F bne VLDZ3 ;NOT IN FIRST V-64K, so must be paged +13150 90BD A5 81 lda ZPCM ; check to see if it is paged +13151 90BF 20 A7 91 jsr CHECKPRE ; is it preloaded? +13152 90C2 B0 08 bcs VLDZ3 ; no, so it must be paged +13153 90C4 20 7C 8F jsr SETPC ; point to correct bank and page +13154 90C7 84 85 sty ZPCBNK ; set bank +13155 90C9 85 84 sta ZPCPNT+HI ; and MSB of pointer +13156 90CB NOZMUCK: +13157 90CB 60 rts +13158 VLDZ3: ;MUST BE PAGED +13159 90CC A5 82 lda ZPCH +13160 90CE A4 81 ldy ZPCM +13161 90D0 20 E5 90 jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y +13162 90D3 18 clc +13163 90D4 69 08 adc #>PBEGIN +13164 90D6 85 84 sta ZPCPNT+HI +13165 90D8 A0 01 ldy #PB_BANK +13166 90DA 84 85 sty ZPCBNK +13167 ; +13168 ; TEST MUCKING +13169 ; +13170 90DC AD E4 90 lda MUCKFLG +13171 90DF F0 EA beq NOZMUCK +13172 90E1 4C 85 90 jmp VLDMPC ;MAY HAVE MUCKED MPC SO GO FIX +13173 +13174 +13175 ; FIND V-PAGE A,Y IF IT IS IN MEM +13176 ; AND RETURN WITH LINKED LIST +13177 ; PROPERLY MAINTAINED +13178 ; IF V-PAGE A,Y NOT IN MEM + Wed Jun 7 1989 12:04 Page 196 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13179 ; GET FROM DISK AND PUT IN RIGHT +13180 ; PLACE +13181 +13182 90E4 00 MUCKFLG: DB 00 ;00 IF PAGING BUFFERS NOT MUCKED +13183 +13184 90E5 PAGE: +13185 90E5 8D 75 8F sta WANTED+HI +13186 90E8 8C 74 8F sty WANTED+LO +13187 90EB A2 00 ldx #0 +13188 90ED 8E E4 90 stx MUCKFLG ; CLEAR MUCK FLAG +13189 90F0 20 8F 91 jsr WHERE +13190 90F3 90 39 bcc TOUGH ; PAGE IS RESIDENT IN PAGING SPACE +13191 ; +13192 ; PAGE MUST BE BROUGHT IN FROM DISK +13193 ; +13194 90F5 A6 CD ldx CURRENT ;GET BUFFER TO PUT PAGE INTO +13195 90F7 BD 00 0C lda NEXTPNT,X ;BY LOOKING AT NEXT POINTER +13196 90FA 85 CD sta CURRENT ;MAKE IT THE CURRENT BUFFER +13197 90FC AA tax +13198 90FD AD 75 8F lda WANTED+HI ;LET BUFFER MAP KNOW +13199 9100 9D 80 0C sta VPAGEH,X ;WHICH PAGE +13200 9103 AD 74 8F lda WANTED+LO ;IS GOING TO +13201 9106 29 FE and #$FE ; make address be even +13202 9108 9D C0 0C sta VPAGEL,X ;BE THERE +13203 ;*** +13204 ; point to the next page too +13205 ; +13206 910B 09 01 ora #1 ; add one to point to next 256 byte page +13207 910D 48 pha ; save it +13208 910E 8A txa ; get pointer +13209 910F A8 tay ; into y +13210 9110 C8 iny ; point to next buffer +13211 9111 68 pla ; get second buffer back +13212 9112 99 C0 0C sta VPAGEL,Y ; so point to it +13213 9115 BD 80 0C lda VPAGEH,X ; get MSB +13214 9118 99 80 0C sta VPAGEH,Y ; and save it +13215 ; +13216 ; A = WANTED+HI +13217 ; Y = WANTED+LO +13218 ; X = BUFFER +13219 ; +13220 911B AD 74 8F lda WANTED+LO +13221 911E 29 FE and #$FE ; clear low bit to make it even +13222 9120 A8 tay ; want it in y +13223 ;*** +13224 9121 AD 75 8F lda WANTED+HI +13225 9124 A6 CD ldx CURRENT +13226 9126 20 53 91 jsr GETVPAGE ; PUT V-PAGE A,Y INTO PAGING BUFFER X +13227 ;*** +13228 9129 CE E4 90 dec MUCKFLG ; INDICATE A MUCKING +13229 912C D0 1C bne PAGEXIT ; and return current buffer +13230 912E TOUGH: +13231 912E 29 FE and #$FE ; make even page, please +13232 9130 8D 76 8F sta NEXT +13233 9133 C5 CD cmp CURRENT ; GETS REALY SCREWED IF CURRENT==NEXT +13234 9135 F0 13 beq PAGEXIT ; DO NOT CHANGE POINTERS IF IT DOES +13235 ; +13236 ; Y=NEXT(CURRENT) +13237 ; DO THE RIGHT THING TO THE POINTERS +13238 ; +13239 ; ldy CURRENT +13240 ; lda NEXTPNT,Y +13241 ; sta NSUBCUR +13242 9137 AD 76 8F lda NEXT +13243 913A 20 7D 91 jsr DETATCH +13244 913D A4 CD ldy CURRENT +13245 913F AD 76 8F lda NEXT +13246 9142 20 66 91 jsr INSERT +13247 9145 AD 76 8F lda NEXT +13248 9148 85 CD sta CURRENT +13249 914A PAGEXIT: +13250 ;*** perhaps add one to point to correct buffer +13251 914A AD 74 8F lda WANTED+LO ; get LSB +13252 914D 29 01 and #$01 ; pick up even/odd bit +13253 914F 18 clc ; doing add + Wed Jun 7 1989 12:04 Page 197 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13254 9150 65 CD adc CURRENT ; point to correct buffer +13255 9152 60 rts +13256 +13257 9153 GETVPAGE: +13258 9153 8D 5F 6C sta DBLOCK+HI +13259 9156 8C 5E 6C sty DBLOCK+LO +13260 9159 8A txa ; get which paging buffer +13261 915A 18 clc +13262 915B 69 08 adc #>PBEGIN ; and set up abs addr +13263 915D 85 B7 sta DBUFF+HI ; thank you, that's much better +13264 915F A2 01 ldx #PB_BANK +13265 9161 86 B8 stx DSKBNK +13266 9163 4C CF 46 jmp GETDSK +13267 +13268 ; INSERT A AFTER Y +13269 ; A.next = Y.next +13270 ; Y.next = A +13271 ; A.previous = Y +13272 ; [Y.next].previous = A +13273 9166 INSERT: +13274 9166 AA tax +13275 9167 B9 00 0C lda NEXTPNT,Y ; Y.next +13276 916A 9D 00 0C sta NEXTPNT,X ; A.next = Y.next +13277 916D 48 pha ; save Y.next for later +13278 916E 8A txa +13279 916F 99 00 0C sta NEXTPNT,Y ; Y.next = A +13280 9172 98 tya +13281 9173 9D 40 0C sta PREVPNT,X ; A.prev = Y +13282 9176 68 pla ; get Y.next back +13283 9177 A8 tay ; [Y.next].previous +13284 9178 8A txa +13285 9179 99 40 0C sta PREVPNT,Y ; [Y.next].previous = A +13286 917C 60 rts +13287 +13288 [01] IF 0 +13289 ; +13290 ; old one, which puts A AFTER! Y +13291 ; +13292 ; PREV(A)=Y +13293 ; PREV(NEXT(Y))=A +13294 ; NEXT(A)=NEXT(Y) +13295 ; NEXT(Y)=A +13296 +13297 sta ATEMP +13298 sty YTEMP +13299 tax +13300 tya +13301 sta PREVPNT,X +13302 +13303 lda NEXTPNT,Y +13304 sta NSUBY +13305 txa +13306 ldx NSUBY +13307 sta PREVPNT,X +13308 +13309 txa +13310 ldx ATEMP +13311 sta NEXTPNT,X +13312 +13313 lda ATEMP +13314 sta NEXTPNT,Y +13315 rts +13316 [00] ENDIF +13317 +13318 ; DETATCH BUFFER >A< +13319 ; NEXT(PREV(A))=NEXT(A) +13320 ; PREV(NEXT(A))=PREV(A) +13321 +13322 917D DETATCH: +13323 917D AA tax +13324 917E BD 00 0C lda NEXTPNT,X +13325 9181 A8 tay ; Y == A.next +13326 9182 BD 40 0C lda PREVPNT,X ; get A.previous +13327 9185 AA tax ; X == A.previous +13328 9186 98 tya ; get A.next + Wed Jun 7 1989 12:04 Page 198 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13329 9187 9D 00 0C sta NEXTPNT,X ; [A.previous].next = A.next +13330 918A 8A txa ; get A.previous +13331 918B 99 40 0C sta PREVPNT,Y ; [A.next].previous = A.previous +13332 918E 60 rts +13333 +13334 +13335 ; RETURN BUFFER OF PAGE [WANTED] +13336 ; IN >A< ELSE SEC (Y=WANTED+LO) +13337 +13338 918F A2 17 WHERE: LDX #NUMBUFS-1 +13339 9191 WHLOOP: +13340 9191 AD 75 8F LDA WANTED+HI +13341 9194 DD 80 0C CMP VPAGEH,X ;>SAME +13342 9197 F0 05 BEQ WHGOT +13343 9199 WHNOGOT: +13344 9199 CA DEX +13345 919A 10 F5 BPL WHLOOP +13346 919C 38 SEC +13347 919D 60 RTS +13348 919E WHGOT: +13349 919E 98 TYA +13350 919F DD C0 0C CMP VPAGEL,X +13351 91A2 D0 F5 BNE WHNOGOT +13352 91A4 8A TXA +13353 91A5 18 CLC +13354 91A6 60 RTS +13355 ; +13356 ; CHECKPRE - check to see if page in [A] is in preloaded +13357 ; +13358 91A7 CHECKPRE: +13359 91A7 C5 C2 cmp TBLPUR ; check against PURE tables +13360 91A9 90 0B bcc CHKPEXY ; must be preloaded then +13361 91AB CHKP1: +13362 91AB C5 C3 cmp FUNPRE ; is it in function preload? +13363 91AD 90 09 bcc CHKPEXN ; preloaded function > desired, not preloaded +13364 91AF C5 C4 cmp FUNPUR ; how bout at end? +13365 91B1 B0 05 bcs CHKPEXN ; it is not preloaded +13366 91B3 CHKP3: +13367 91B3 18 clc ; doing add +13368 91B4 65 C5 adc FUNPGE ; get me memory page for function +13369 91B6 CHKPEXY: +13370 91B6 18 clc ; show it is preloaded +13371 91B7 60 rts ; then we got it +13372 91B8 CHKPEXN: +13373 91B8 38 sec ; show it ain't here +13374 91B9 60 rts +13375 ; +13376 ; INFO_PAGE - is it one of the special preloaded pages for infoDOS? If it +13377 ; is, then set up ZPCPNTR to point to it, and set carry. Otherwise, +13378 ; clear carry to show it ain't. +13379 91BA IPAGE: ds 2 +13380 91BC INFO_PAGE: +13381 91BC A5 82 lda ZPCH ; get 2 parts +13382 91BE 8D BB 91 sta IPAGE+HI +13383 91C1 A5 81 lda ZPCM +13384 91C3 8D BA 91 sta IPAGE+LO +13385 91C6 4E BB 91 lsr IPAGE+HI ; /2 to get 512 block +13386 91C9 6E BA 91 ror IPAGE+LO +13387 91CC A0 08 ldy #SGTSEG ; point to first segment, MSB +13388 91CE B1 59 lda (INFODOS),Y ; howzit look? +13389 91D0 C8 iny ; point to LSB +13390 91D1 CD BB 91 cmp IPAGE+HI +13391 91D4 90 0B bcc INFP1 ; might be interesting +13392 91D6 D0 34 bne INFPNX ; not here, < than minimum +13393 91D8 B1 59 lda (INFODOS),Y ; how bout LSB +13394 91DA CD BA 91 cmp IPAGE+LO +13395 91DD F0 14 beq INFPYX ; found it +13396 91DF B0 2B bcs INFPNX ; nope, < than minimum again +13397 ; +13398 ; here, it's at least > than minimum +13399 ; +13400 91E1 INFP1: +13401 ; iny ; point at end block, MSB +13402 91E1 AD AB 6C lda INFODOS_END+HI ; howz end segment look +13403 91E4 CD BB 91 cmp IPAGE+HI + Wed Jun 7 1989 12:04 Page 199 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13404 91E7 90 23 bcc INFPNX ; nope, > than maximum of special +13405 91E9 D0 08 bne INFPYX ; yup, < than maximum of special +13406 ; iny ; LSB of last one +13407 91EB AD AA 6C lda INFODOS_END+LO ; is LSB < special? +13408 91EE CD BA 91 cmp IPAGE+LO ; MSB of current one == MSB of special +13409 91F1 90 19 bcc INFPNX ; nope, not here +13410 91F3 INFPYX: +13411 91F3 A0 09 ldy #SGTSEG+1 ; point back to start block, LSB +13412 91F5 B1 59 lda (INFODOS),Y ; get start block +13413 91F7 0A asl A ; *2 to get start page +13414 91F8 8D BA 91 sta IPAGE+LO ; save it +13415 91FB A5 81 lda ZPCM +13416 91FD 38 sec ; doing sub +13417 91FE ED BA 91 sbc IPAGE+LO ; get offset into special block +13418 9201 18 clc ; now add in offset +13419 9202 69 D0 adc #>SP_START ; get the start of special area +13420 9204 85 84 sta ZPCPNT+HI ; show ZPCPNTR +13421 9206 A9 00 lda #SP_BANK ; which bank +13422 9208 85 85 sta ZPCBNK ; okey +13423 920A 38 sec ; show it was here +13424 920B 60 rts +13425 920C INFPNX: +13426 920C 18 clc ; show not here +13427 920D 60 rts ; g'day +13428 920E +13429 920E +13430 920E +13431 920E CHKPEXN0: +13432 +13433 920E GETBYT: +13434 920E A4 86 ldy MPCL +13435 9210 20 8D 92 jsr MFETCH ; go and get it +13436 9213 E6 86 inc MPCL ;POINT TO NEXT BYTE +13437 9215 D0 0B bne GETGOT ;IF NO CROSS WE ARE STILL VALID +13438 9217 E6 87 inc MPCM +13439 9219 D0 02 bne GET1 +13440 921B E6 88 inc MPCH +13441 921D GET1: +13442 921D 48 pha ; save byte +13443 921E 20 85 90 jsr VLDMPC +13444 9221 68 pla ; and get it back +13445 9222 GETGOT: +13446 9222 A8 tay ;SET FLAGS +13447 9223 60 rts ;RED SLIPPER TIME +13448 ; +13449 ; NEXTPC - Fetch the byte at the current ZPC, point to next byte and +13450 ; validate pointer +13451 ; +13452 9224 NEXTPC: +13453 9224 A4 80 ldy ZPCL ; get low pointer +13454 9226 20 75 92 jsr ZFETCH ; fetch @ZPCPNT +13455 9229 E6 80 inc ZPCL +13456 922B D0 0B bne NXTGOT +13457 922D E6 81 inc ZPCM +13458 922F D0 02 bne CRSZ1 +13459 9231 E6 82 inc ZPCH +13460 9233 CRSZ1: +13461 9233 48 pha ; save opcode +13462 9234 20 AF 90 jsr VLDZPC +13463 9237 68 pla ; and get it back +13464 9238 NXTGOT: +13465 9238 A8 tay +13466 9239 60 rts +13467 +13468 ; +13469 ; STASHB - use SPC to save a byte in either aux or main mem +13470 ; +13471 923A STASHB: +13472 923A A4 91 ldy SPCBNK ; get the bank +13473 923C 30 09 bmi SB1 ; must be in upper RAM +13474 923E 99 04 C0 sta WRTBNK,Y ; set bank +13475 9241 A0 00 ldy #0 ; can only do this with Y +13476 9243 91 8F sta (SPC),Y ; get the sucker +13477 9245 F0 10 beq SBEXI ; jump to end it +13478 ; + Wed Jun 7 1989 12:04 Page 200 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13479 ; this is in aux mem, >$E000 +13480 ; +13481 9247 SB1: +13482 9247 A4 90 ldy SPCH ; get high part +13483 9249 8C 53 92 sty SBMOD+2 ; and self mod my code +13484 924C A4 8F ldy SPCL ; and get the low part +13485 924E 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13486 9251 SBMOD: +13487 9251 99 00 D0 sta Z3BEGIN,Y ; store the little byte +13488 9254 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13489 9257 SBEXI: +13490 9257 8D 04 C0 sta WRTBNK+MAIN ; and write to main +13491 925A 60 rts +13492 ; +13493 ; FETCHB - fetch a byte from either main memory, aux memory, or upper +13494 ; Aux memory +13495 ; +13496 925B FETCHB: +13497 925B A4 8E ldy FPCBNK ; get the bank +13498 925D 30 04 bmi FB1 ; must be in upper RAM +13499 925F 20 D1 00 jsr ZERO_FB ; go to low end fetch +13500 9262 60 rts +13501 ; +13502 ; this is in aux mem, >$E000 +13503 ; +13504 9263 FB1: +13505 9263 A5 8D lda FPCH ; get which page +13506 9265 8D 6F 92 sta FBMOD+2 ; and show in operand +13507 9268 A4 8C ldy FPCL ; get which byte +13508 926A 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13509 926D B9 00 D0 FBMOD: lda Z3BEGIN,Y ; get the sucker +13510 9270 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13511 9273 A8 tay ; set condition code +13512 9274 60 rts +13513 ; +13514 ; ZFETCH - after checking for which bank (main, aux 1 or aux 2), go get +13515 ; the byte @ ZPCPNT, with the offset being in [Y] +13516 ; +13517 9275 ZFETCH: +13518 9275 A6 85 ldx ZPCBNK ; get the bank +13519 9277 30 04 bmi ZFB1 ; must be in upper RAM +13520 9279 20 DC 00 jsr ZERO_ZF ; go to low end fetch +13521 927C 60 rts +13522 ; +13523 ; this is in aux mem, >$D000 +13524 ; +13525 927D ZFB1: +13526 927D A5 84 lda ZPNTH ; which page are we talking about +13527 927F 8D 87 92 sta ZBMOD+2 ; show in the operand +13528 9282 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13529 9285 B9 00 D0 ZBMOD: lda Z3BEGIN,Y ; get the sucker +13530 9288 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13531 928B AA tax ; set condition code +13532 928C 60 rts +13533 ; +13534 ; MFETCH - after checking for which bank (main, aux 1 or aux 2), go get +13535 ; the byte @MPCPNT, with the offset being in [Y] +13536 ; +13537 928D MFETCH: +13538 928D A6 8B ldx MPCBNK ; get the bank +13539 928F 30 04 bmi MB1 ; must be in upper RAM +13540 9291 20 E5 00 jsr ZERO_MF ; go to low end fetch +13541 9294 60 rts +13542 ; +13543 ; this is in aux mem, >$D000 +13544 ; +13545 9295 MB1: +13546 9295 A5 8A lda MPNTH ; which page are we talking about +13547 9297 8D 9F 92 sta MBMOD+2 ; show in the operand +13548 929A 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13549 +13550 929D B9 00 D0 MBMOD: lda Z3BEGIN,Y ; get the sucker +13551 +13552 92A0 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13553 92A3 AA tax ; set condition code + Wed Jun 7 1989 12:04 Page 201 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13554 92A4 60 rts +13555 +13556 +13557 92A5 END +13558 +13559 92A5 INCLUDE ZSTRING.ASM +13560 PAGE + Wed Jun 7 1989 12:04 Page 202 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13561 92A5 STTL "--- Z-STRING HANDLERS ---" +13562 +13563 ; ----------------------- +13564 ; POINT MPC TO ZSTRING IN [I], using SOFF +13565 ; ----------------------- +13566 +13567 92A5 SETSTR: +13568 92A5 A5 78 lda I+LO +13569 92A7 85 86 sta MPCL ; save in lo part +13570 92A9 A5 79 lda I+HI +13571 92AB 85 87 sta MPCM ; middle part +13572 92AD A9 00 lda #0 ; clear hi part +13573 92AF 85 88 sta MPCH ; okay, we did +13574 92B1 06 86 asl MPCL ; *2 +13575 92B3 26 87 rol MPCM +13576 92B5 26 88 rol MPCH +13577 92B7 06 86 asl MPCL ; *4 +13578 92B9 26 87 rol MPCM +13579 92BB 26 88 rol MPCH +13580 ; +13581 ; now add the offset +13582 ; +13583 92BD A5 86 lda MPCL ; carry clear from above +13584 92BF 65 60 adc SOFFL ; add lo part of offset +13585 92C1 85 86 sta MPCL ; save +13586 92C3 A5 87 lda MPCM +13587 92C5 65 5F adc SOFFM +13588 92C7 85 87 sta MPCM +13589 92C9 A5 88 lda MPCH +13590 92CB 65 5E adc SOFFH +13591 92CD 85 88 sta MPCH +13592 92CF 4C 85 90 jmp VLDMPC ; make MPCPNT to it +13593 +13594 +13595 92D2 60 ZSTEX: RTS +13596 +13597 ; ----------------------- +13598 ; PRINT Z-STRING AT [MPC] +13599 ; ----------------------- +13600 92D3 PZSTR: +13601 92D3 A2 00 ldx #0 +13602 92D5 86 96 stx PSET ; ASSUME PERMANENT CHARSET +13603 92D7 86 9A stx ZFLAG ; CLEAR BYTE FLAG +13604 92D9 CA dex ; = $FF +13605 92DA 86 97 stx TSET ; NO TEMPSET ACTIVE +13606 92DC PZTOP: +13607 92DC 20 CF 93 jsr GETZCH ; GET A Z-CHAR +13608 92DF B0 F1 bcs ZSTEX ; END OF STRING IF CARRY IS SET +13609 92E1 85 98 sta ZCHAR ; ELSE SAVE CHAR HERE +13610 92E3 AA tax ; SET FLAGS +13611 92E4 F0 45 beq BLANK ; PRINT SPACE IF CHAR = 0 +13612 92E6 C9 04 cmp #4 ; IS THIS AN F-WORD? +13613 92E8 90 5F bcc DOFREQ ; APPARENTLY SO +13614 92EA C9 06 cmp #6 ; PERHAPS A SHIFT CODE? +13615 92EC 90 41 bcc NEWSET ; YES, CHANGE CHARSETS +13616 92EE 20 B1 93 jsr GETSET ; ELSE GET CHARSET +13617 92F1 AA tax ; SET FLAGS +13618 92F2 D0 14 bne SET1 ; SKIP IF NOT CHARSET #0 +13619 ; +13620 ; PRINT A LOWER-CASE CHAR (CHARSET #0) +13621 ; +13622 92F4 A9 FA lda #$FA ; what to add to get offset into char table +13623 92F6 TOASC: +13624 92F6 8D FD 92 sta TOASCM+1 ; modify code +13625 92F9 A5 98 lda ZCHAR ; use char as offset +13626 92FB 18 clc ; make char be an index +13627 92FC 69 06 TOASCM: adc #6 ; we just did +13628 92FE AA tax ; now use as index +13629 92FF BD 8C 1F lda CHARSET,X ; go get that char in charset zero +13630 9302 SHOVE: +13631 9302 20 06 53 jsr COUT ; SHOW THE CHAR +13632 9305 4C DC 92 jmp PZTOP ; AND GRAB NEXT CHAR +13633 ; +13634 ; PRINT AN UPPER-CASE CHAR (CHARSET #1) +13635 ; + Wed Jun 7 1989 12:04 Page 203 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13636 9308 SET1: +13637 9308 C9 01 cmp #1 ; make sure it's set #1 +13638 930A D0 04 bne SET2 ; else must be set #2 +13639 930C A9 14 lda #20 ; skip into Charset 1 part of table +13640 930E D0 E6 bne TOASC ; fix just like the others +13641 ; +13642 ; PRINT FROM CHARSET #2 +13643 ; +13644 9310 SET2: +13645 9310 A5 98 lda ZCHAR ; retrieve the z-char +13646 9312 C9 06 cmp #6 ; is it a special ascii char? +13647 9314 F0 04 beq DIRECT ; yes, so do it special +13648 9316 A9 2E lda #46 ; nothing special, just get offset +13649 9318 D0 DC bne TOASC ; and jump +13650 ; +13651 ; DECODE A "DIRECT" ASCII CHAR +13652 ; +13653 931A DIRECT: +13654 931A 20 CF 93 jsr GETZCH ; FETCH NEXT Z-CHAR +13655 931D 0A asl A +13656 931E 0A asl A +13657 931F 0A asl A +13658 9320 0A asl A +13659 9321 0A asl A ; SHIFT INTO POSITION +13660 9322 85 98 sta ZCHAR ; AND SAVE HERE +13661 9324 20 CF 93 jsr GETZCH ; GRAB YET ANOTHER Z-CHAR +13662 9327 05 98 ora ZCHAR ; SUPERIMPOSE THE 2ND BYTE +13663 9329 D0 D7 bne SHOVE ; AND PRINT THE RESULT +13664 ; +13665 ; PRINT A SPACE +13666 ; +13667 932B BLANK: +13668 932B A9 20 lda #SPACE ; ASCII SPACE CHAR +13669 932D D0 D3 bne SHOVE +13670 +13671 ; CHANGE CHARSET +13672 +13673 932F 38 NEWSET: SEC ; CONVERT THE SHIFT CODE +13674 9330 E9 03 SBC #3 ; TO 1 OR 2 +13675 9332 A8 TAY +13676 9333 20 B1 93 JSR GETSET ; IS MODE TEMPORARY? +13677 9336 D0 05 BNE TOPERM ; YES, DO A PERMSHIFT +13678 9338 84 97 STY TSET ; ELSE JUST A TEMPSHIFT +13679 933A 4C DC 92 JMP PZTOP ; AND CONTINUE +13680 933D 84 96 TOPERM: STY PSET ; SET PERM CHARSET +13681 933F C5 96 CMP PSET ; SAME AS BEFORE? +13682 9341 F0 99 BEQ PZTOP ; YES, CONTINUE +13683 9343 A9 00 LDA #0 +13684 9345 85 96 STA PSET ; ELSE RESET CHARSET +13685 9347 F0 93 BEQ PZTOP ; BEFORE LOOPING BACK +13686 +13687 ; PRINT AN F-WORD +13688 +13689 9349 38 DOFREQ: SEC +13690 934A E9 01 SBC #1 ; ZERO-ALIGN THE CODE +13691 934C 0A ASL A ; AND MULTIPLY TIMES 64 +13692 934D 0A ASL A ; TO OBTAIN THE SEGMENT OFFSET +13693 934E 0A ASL A ; INTO THE F-WORDS TABLE +13694 934F 0A ASL A +13695 9350 0A ASL A +13696 9351 0A ASL A +13697 9352 85 99 STA OFFSET ; SAVE OFFSET FOR LATER +13698 9354 20 CF 93 JSR GETZCH ; NOW GET THE F-WORD POINTER +13699 9357 0A ASL A ; WORD-ALIGN IT +13700 9358 18 CLC ; AND +13701 9359 65 99 ADC OFFSET ; ADD THE SEGMENT OFFSET +13702 ; +13703 ; set up FPC to point to FWORDS table +13704 ; +13705 935B A6 57 ldx FWORDS+ABANK +13706 935D 86 8E stx FPCBNK +13707 935F A6 56 ldx FWORDS+HI +13708 9361 86 8D stx FPCH +13709 9363 A6 55 ldx FWORDS+LO +13710 9365 86 8C stx FPCL + Wed Jun 7 1989 12:04 Page 204 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13711 9367 20 E3 8F jsr ADDFPC ; add offset of the F-word +13712 936A 20 5B 92 jsr FETCHB ; and get MSB of F-word +13713 936D 85 79 sta I+HI ; and save it +13714 936F 20 C3 8F jsr NEXTFPC ; and point to LSB +13715 9372 20 5B 92 jsr FETCHB ; and get it +13716 9375 85 78 sta I+LO ; and save it +13717 ; +13718 ; SAVE THE STATE OF CURRENT Z-STRING +13719 ; +13720 9377 A5 88 LDA MPCH +13721 9379 48 PHA +13722 937A A5 87 LDA MPCM +13723 937C 48 PHA +13724 937D A5 86 LDA MPCL +13725 937F 48 PHA +13726 9380 A5 96 LDA PSET +13727 9382 48 PHA +13728 9383 A5 9A LDA ZFLAG +13729 9385 48 PHA +13730 9386 A5 9C LDA ZWORD+HI +13731 9388 48 PHA +13732 9389 A5 9B LDA ZWORD+LO +13733 938B 48 PHA +13734 938C 20 BD 93 JSR SETFWD ; PRINT THE Z-STRING +13735 938F 20 D3 92 JSR PZSTR ; IN [I] +13736 ; +13737 ; RESTORE OLD Z-STRING +13738 ; +13739 9392 68 PLA +13740 9393 85 9B STA ZWORD+LO +13741 9395 68 PLA +13742 9396 85 9C STA ZWORD+HI +13743 9398 68 PLA +13744 9399 85 9A STA ZFLAG +13745 939B 68 PLA +13746 939C 85 96 STA PSET +13747 939E 68 PLA +13748 939F 85 86 STA MPCL +13749 93A1 68 PLA +13750 93A2 85 87 STA MPCM +13751 93A4 68 PLA +13752 93A5 85 88 STA MPCH +13753 93A7 A2 FF LDX #$FF +13754 93A9 86 97 STX TSET ; DISABLE TEMP CHARSET +13755 93AB 20 85 90 JSR VLDMPC +13756 93AE 4C DC 92 JMP PZTOP ; CONTINUE INNOCENTLY +13757 +13758 +13759 ; ---------------------- +13760 ; RETURN CURRENT CHARSET +13761 ; ---------------------- +13762 +13763 93B1 A5 97 GETSET: LDA TSET +13764 93B3 10 03 BPL GS +13765 93B5 A5 96 LDA PSET +13766 93B7 60 RTS +13767 93B8 A0 FF GS: LDY #$FF +13768 93BA 84 97 STY TSET +13769 93BC 60 RTS +13770 +13771 +13772 ; ------------------------- +13773 ; POINT [I] AT FWORD STRING +13774 ; ------------------------- +13775 +13776 93BD A5 78 SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS +13777 93BF 0A ASL A +13778 93C0 85 86 STA MPCL +13779 93C2 A5 79 LDA I+HI +13780 93C4 2A ROL A +13781 93C5 85 87 STA MPCM +13782 93C7 A9 00 LDA #0 +13783 93C9 2A ROL A +13784 93CA 85 88 STA MPCH +13785 93CC 4C 85 90 JMP VLDMPC + Wed Jun 7 1989 12:04 Page 205 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13786 +13787 +13788 ; ----------------- +13789 ; FETCH NEXT Z-CHAR +13790 ; ----------------- +13791 +13792 93CF A5 9A GETZCH: LDA ZFLAG ; WHICH BYTE IS THIS? +13793 93D1 10 02 BPL GTZ0 ; $FF = LAST +13794 93D3 38 SEC ; SET CARRY TO INDICATE +13795 93D4 60 RTS ; NO MORE CHARS +13796 93D5 D0 13 GTZ0: BNE GETZ1 ; NOT FIRST CHAR, EITHER +13797 +13798 ; GET A Z-WORD INTO [ZWORD], RETURN 1ST CHAR IN TRIPLET +13799 +13800 93D7 E6 9A INC ZFLAG ; UPDATE CHAR COUNT +13801 93D9 20 0E 92 JSR GETBYT ; GET TRIPLET AT [MPC] +13802 93DC 85 9C STA ZWORD+HI ; INTO [ZWORD] +13803 93DE 20 0E 92 JSR GETBYT +13804 93E1 85 9B STA ZWORD+LO +13805 93E3 A5 9C LDA ZWORD+HI +13806 93E5 4A LSR A +13807 93E6 4A LSR A ; SHIFT 1ST CHAR INTO PLACE +13808 93E7 4C 13 94 JMP GTEXIT ; AND RETURN IT +13809 93EA 38 GETZ1: SEC +13810 93EB E9 01 SBC #1 +13811 93ED D0 16 BNE GETZ2 ; LAST CHAR IN TRIPLET IF ZERO +13812 93EF A9 02 LDA #2 ; ELSE +13813 93F1 85 9A STA ZFLAG ; RESET CHAR INDEX +13814 93F3 A5 9B LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET +13815 93F5 85 78 STA I+LO ; MOVE HERE FOR SHIFTING +13816 93F7 A5 9C LDA ZWORD+HI ; GET TOP HALF +13817 93F9 06 78 ASL I+LO ; SHIFT THE TOP 3 BITS OF LOWER HALF +13818 93FB 2A ROL A ; INTO THE BOTTOM OF THE TOP HALF +13819 93FC 06 78 ASL I+LO +13820 93FE 2A ROL A +13821 93FF 06 78 ASL I+LO +13822 9401 2A ROL A +13823 9402 4C 13 94 JMP GTEXIT +13824 9405 A9 00 GETZ2: LDA #0 ; SET FLAG TO INDICATE +13825 9407 85 9A STA ZFLAG ; END OF TRIPLET +13826 9409 A5 9C LDA ZWORD+HI ; TEST TOP HALF OF TRIPLET +13827 940B 10 04 BPL GETZ3 ; CONTINUE IF NOT END OF STRING +13828 940D A9 FF LDA #$FF ; ELSE +13829 940F 85 9A STA ZFLAG ; INDICATE LAST TRIPLET IN STRING +13830 9411 A5 9B GETZ3: LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET +13831 9413 29 1F GTEXIT: AND #%00011111 ; MASK OUT GARBAGE BITS +13832 9415 18 CLC +13833 9416 60 RTS +13834 +13835 +13836 ; --------------------------------- +13837 ; CONVERT [IN] TO Z-STRING IN [OUT] +13838 ; --------------------------------- +13839 9417 CONZST: +13840 9417 A9 05 lda #5 ; FILL OUTPUT BUFFER +13841 9419 A2 08 ldx #8 ; WITH PAD CHARS ($05) +13842 941B CZSL: +13843 941B 9D 9E 6C sta OUT,X +13844 941E CA dex +13845 941F 10 FA bpl CZSL +13846 +13847 9421 A9 09 lda #9 ; INIT +13848 9423 85 9D sta CONCNT ; CHAR COUNT +13849 9425 A9 00 lda #0 ; CLEAR +13850 9427 85 9E sta CONIN ; SOURCE AND +13851 9429 85 9F sta CONOUT ; OUTPUT INDEXES +13852 942B CONTOP: +13853 942B A6 9E ldx CONIN ; fetch source index +13854 942D E6 9E inc CONIN ; and update +13855 942F BD 95 6C lda IN,X ; grab an ascii char +13856 9432 85 98 sta ZCHAR ; save it here +13857 9434 D0 04 bne NEXTZ ; continue if char was nz +13858 9436 A9 05 lda #5 ; else ship out +13859 9438 D0 27 bne CSHIP1 ; a pad char +13860 943A NEXTZ: + Wed Jun 7 1989 12:04 Page 206 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13861 943A 20 66 94 jsr FINDCHAR ; find out where it tis +13862 943D F0 21 beq CSHIP ; no shift for charset zero +13863 943F 18 clc ; else do a temp-shift +13864 9440 69 03 adc #3 ; 4 = charset 1, 5 = charset 2 +13865 9442 20 94 94 jsr CSTASH ; save the char in outbuf +13866 9445 C9 05 cmp #5 ; charset 2? +13867 9447 D0 17 bne CSHIP ; nope +13868 9449 E0 06 cpx #6 ; ascii escape? +13869 944B D0 13 bne CSHIP ; nope +13870 ; +13871 ; Handle special Ascii escape sequence +13872 ; +13873 944D 8A txa ; get ASCII alert char (#6) +13874 944E 20 94 94 jsr CSTASH ; shove it away +13875 ; +13876 ; do 1st half of "direct" +13877 ; +13878 9451 A5 98 lda ZCHAR ; re-fetch char +13879 9453 4A lsr A ; get upper 2 bits in lower 2 bits +13880 9454 4A lsr A +13881 9455 4A lsr A +13882 9456 4A lsr A +13883 9457 4A lsr A +13884 9458 20 94 94 jsr CSTASH +13885 ; +13886 ; SEND 2ND HALF OF "DIRECT" +13887 ; +13888 945B A5 98 lda ZCHAR ; get char yet again +13889 945D 29 1F and #%00011111 ; and get lower 5 bits +13890 945F AA tax ; this is where it is expected +13891 ; +13892 ; SHIP Z-CHAR TO OUTPUT BUFFER +13893 ; +13894 9460 CSHIP: +13895 9460 8A txa ; get char +13896 9461 CSHIP1: +13897 9461 20 94 94 jsr CSTASH ; put char away +13898 9464 D0 C5 bne CONTOP ; do again +13899 ; +13900 ; FINDCHAR - look through the charset table for the character. If found, +13901 ; figger out which shift it is. If not found, return charset 2, +13902 ; character #6. +13903 ; Enter: +13904 ; [A] = Char we are looking for +13905 ; Returns: +13906 ; [A] = Charset (0-2) +13907 ; [X] = Character # (6-31) +13908 ; +13909 9466 FINDCHAR: +13910 9466 A2 00 ldx #0 ; start at first char, first set +13911 9468 A0 4E ldy #78 ; there are 78 characters +13912 946A FNDCL: +13913 946A DD 8C 1F cmp CHARSET,X ; found it? +13914 946D F0 09 beq FNDCLX ; yes +13915 946F E8 inx ; next char +13916 9470 88 dey ; count char +13917 9471 D0 F7 bne FNDCL ; go check next char +13918 ; +13919 ; not found in table, use ASCII escape sequence +13920 ; +13921 9473 A9 02 lda #2 ; escape sequence is char set 2 +13922 9475 A2 06 ldx #6 ; character 6 +13923 9477 60 rts ; and done +13924 9478 FNDCLX: +13925 9478 8A txa ; put here for compares/action +13926 9479 A0 00 ldy #0 ; this is char set 0 +13927 947B A2 FA ldx #$FA ; what to "subtract" to get +6 +13928 947D C9 1A cmp #26 ; how we doin'? +13929 947F 90 0A bcc FNDCHX ; all done +13930 9481 C8 iny ; char set 1 +13931 9482 A2 14 ldx #20 ; char set 1 offset +13932 9484 C9 34 cmp #52 ; well? +13933 9486 90 03 bcc FNDCHX ; must be char set 1 +13934 9488 A2 2E ldx #46 ; for char set 2 setting up +13935 948A C8 iny ; must be char set 2 then + Wed Jun 7 1989 12:04 Page 207 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13936 948B FNDCHX: +13937 948B 8E 90 94 stx FNDCHM+1 ; what to subtract to get offset +13938 948E 38 sec ; doing subtract +13939 948F E9 06 FNDCHM: sbc #6 ; make good offset +13940 9491 AA tax ; put here for return +13941 9492 98 tya ; and here to set flag +13942 9493 60 rts +13943 ; +13944 ; CSTASH - put the char in OUT. If we run out of room don't return, just +13945 ; jump to ZCRUSH as final destination +13946 ; [A] - char to be put away +13947 ; +13948 9494 CSTASH: +13949 9494 A4 9F ldy CONOUT ; fetch output index +13950 9496 99 9E 6C sta OUT,Y ; send the shift char +13951 9499 E6 9F inc CONOUT ; update index +13952 949B C6 9D dec CONCNT ; and char count +13953 949D D0 05 bne CSTX ; plenty more room +13954 949F 68 pla ; get rid of return spot +13955 94A0 68 pla ; fine +13956 94A1 4C A5 94 jmp ZCRUSH ; if out of room, crush 'em! +13957 94A4 CSTX: +13958 94A4 60 rts +13959 ; ---------------------- +13960 ; CRUSH Z-CHARS IN [OUT], mushing them into small 5 bit pieces +13961 ; ---------------------- +13962 94A5 ZCRUSH: +13963 94A5 AD 9F 6C LDA OUT+1 ; GET 2ND Z-CHAR +13964 94A8 0A ASL A ; SHIFT BITS INTO POSITION +13965 94A9 0A ASL A +13966 94AA 0A ASL A +13967 94AB 0A ASL A +13968 94AC 2E 9E 6C ROL OUT ; ALONG WITH 1ST Z-CHAR +13969 94AF 0A ASL A +13970 94B0 2E 9E 6C ROL OUT +13971 94B3 0D A0 6C ORA OUT+2 ; SUPERIMPOSE 3RD Z-CHAR +13972 94B6 8D 9F 6C STA OUT+1 +13973 94B9 AD A2 6C LDA OUT+4 ; GET 5TH Z-CHAR +13974 94BC 0A ASL A ; SHIFT BITS +13975 94BD 0A ASL A +13976 94BE 0A ASL A +13977 94BF 0A ASL A +13978 94C0 2E A1 6C ROL OUT+3 ; ALONG WITH 4TH Z-CHAR +13979 94C3 0A ASL A +13980 94C4 2E A1 6C ROL OUT+3 +13981 94C7 0D A3 6C ORA OUT+5 ; SUPERIMPOSE 6TH Z-CHAR +13982 94CA AA TAX ; SAVE HERE +13983 94CB AD A1 6C LDA OUT+3 ; GRAB 4TH Z-CHAR +13984 94CE 8D A0 6C STA OUT+2 ; MOVE CRUSHED Z-WORD +13985 94D1 8E A1 6C STX OUT+3 ; INTO PLACE +13986 94D4 AD A5 6C LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) +13987 94D7 0A ASL A ; SHIFT BITS +13988 94D8 0A ASL A +13989 94D9 0A ASL A +13990 94DA 0A ASL A +13991 94DB 2E A4 6C ROL OUT+6 ; ALONG WITH 7TH Z-CHAR +13992 94DE 0A ASL A +13993 94DF 2E A4 6C ROL OUT+6 +13994 94E2 0D A6 6C ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR +13995 94E5 8D A3 6C STA OUT+5 ; SAVE HERE +13996 94E8 AD A4 6C LDA OUT+6 ; GRAB 7TH Z-CHAR +13997 94EB 09 80 ORA #%10000000 ; SET HIGH BIT +13998 94ED 8D A2 6C STA OUT+4 ; MOVE CRUSHED Z-WORD INTO PLACE +13999 94F0 60 RTS +14000 +14001 94F1 END +14002 +14003 94F1 INCLUDE OBJECTS.ASM +14004 94F1 STTL "--- OBJECT & PROPERTY HANDLERS ---" +14005 PAGE + Wed Jun 7 1989 12:04 Page 208 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + +14006 +14007 ; ---------------------------------- +14008 ; GET ABSOLUTE ADDRESS OF OBJECT [A] +14009 ; ---------------------------------- +14010 ; ENTER: OBJECT IN A/X (LO/HI) +14011 ; EXIT: ADDRESS IN [FPC] +14012 94F1 OBJLOC: +14013 94F1 86 79 STX I+HI ; SAVE MSB FOR SHIFTING +14014 94F3 0A ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) +14015 94F4 85 78 STA I+LO +14016 94F6 26 79 ROL I+HI +14017 94F8 A6 79 LDX I+HI +14018 94FA 0A ASL A +14019 94FB 26 79 ROL I+HI ; *4 +14020 94FD 0A ASL A +14021 94FE 26 79 ROL I+HI ; *8 +14022 9500 0A ASL A +14023 9501 26 79 ROL I+HI ; *16 +14024 9503 38 SEC +14025 9504 E5 78 SBC I+LO ; -(*2) +14026 9506 85 78 STA I+LO ; SO IS *14 TOTAL +14027 9508 A5 79 LDA I+HI +14028 950A 86 79 STX I+HI +14029 950C E5 79 SBC I+HI +14030 950E 85 79 STA I+HI +14031 9510 A5 78 LDA I+LO +14032 9512 18 CLC +14033 9513 69 70 ADC #112 ; ADD OBJECT TABLE OFFSET +14034 9515 90 02 BCC OBJ3 +14035 9517 E6 79 INC I+HI +14036 9519 OBJ3: +14037 9519 18 clc ; NEXT ADD THE relative ADDR +14038 951A 6D 0B 96 adc ZBEGIN+ZOBJEC+1 ; OF THE OBJECT TABLE +14039 951D 85 8C sta FPCL ; save lo byte +14040 951F A5 79 lda I+HI +14041 9521 6D 0A 96 adc ZBEGIN+ZOBJEC ; now work on page +14042 9524 20 7C 8F jsr SETPC ; now get page/bank +14043 9527 85 8D sta FPCH ; this is hi part +14044 9529 84 8E sty FPCBNK ; and this is the bank +14045 952B 60 rts +14046 ; ----------------------------- +14047 ; GET ADDRESS OF PROPERTY TABLE +14048 ; ----------------------------- +14049 ; EXIT: [FPC] HAS ABSOLUTE ADDR OF PROPERTY TABLE +14050 ; including OFFSET TO START OF PROP IDS +14051 952C PROPB: +14052 952C A5 63 lda ARG1+LO +14053 952E A6 64 ldx ARG1+HI ; get address +14054 9530 20 F1 94 jsr OBJLOC ; put table location into FPC +14055 9533 A9 0C lda #12 ; add 12 to get to beginning +14056 9535 20 E3 8F jsr ADDFPC ; and add it to FPC +14057 9538 20 5B 92 jsr FETCHB ; get MSB of P-TABLE Address +14058 953B 48 pha ; and save it for a moment +14059 953C 20 C3 8F jsr NEXTFPC ; to get LSB +14060 953F 20 5B 92 jsr FETCHB ; get LSB of P-TABLE Address +14061 9542 85 8C sta FPCL ; and save lo part +14062 9544 68 pla ; get page back +14063 9545 20 7C 8F jsr SETPC ; and set up memory bank/page +14064 9548 85 8D sta FPCH ; save page +14065 954A 84 8E sty FPCBNK ; and bank +14066 954C 20 5B 92 jsr FETCHB ; get length of short description +14067 954F 0A asl A ; WORD-ALIGN IT +14068 9550 20 E3 8F jsr ADDFPC ; and add it to FPC +14069 9553 20 C3 8F jsr NEXTFPC ; POINT JUST PAST THE DESCRIPTION +14070 9556 60 rts +14071 +14072 +14073 ; ------------------- +14074 ; FETCH A PROPERTY ID +14075 ; ------------------- +14076 ; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +14077 ; +14078 9557 PROPN: +14079 9557 20 5B 92 jsr FETCHB ; get the byte +14080 955A 29 3F and #%00111111 ; MASK OUT LENGTH BITS (EZIP) + Wed Jun 7 1989 12:04 Page 209 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + +14081 955C 60 rts +14082 +14083 ; ------------------------------- +14084 ; FETCH # BYTES IN PROPERTY VALUE +14085 ; ------------------------------- +14086 ; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +14087 ; +14088 955D PROPL: +14089 955D 20 5B 92 jsr FETCHB ; CHECK LENGTH FLAGS +14090 9560 AA tax ; save it +14091 9561 10 09 bpl SHORT ; OFF, SO 1 OR 2 BYTES +14092 9563 20 C3 8F jsr NEXTFPC +14093 9566 20 5B 92 jsr FETCHB ; NEXT BYTE HAS LENGTH +14094 9569 29 3F and #%00111111 ; MASK OFF EXTRA BITS +14095 956B 60 rts +14096 956C SHORT: +14097 956C 29 40 and #%01000000 ; BIT 6 +14098 956E F0 03 beq ONE +14099 9570 A9 02 lda #2 ; BIT 6 = 1, LENGTH =2 +14100 9572 60 rts +14101 9573 ONE: +14102 9573 A9 01 lda #1 ; BIT 6 = 0, LENGTH =1 +14103 9575 60 rts +14104 +14105 ; ---------------------- +14106 ; POINT TO NEXT PROPERTY +14107 ; ---------------------- +14108 ; ENTRY: LIKE "PROPB" EXIT (i.e. - in [FPC]) +14109 ; +14110 9576 PROPNX: +14111 9576 20 5D 95 jsr PROPL ; GET LENGTH OF CURRENT PROP +14112 9579 A8 tay ; move one more for correct alignment +14113 957A C8 iny ; okay, done it +14114 957B 98 tya ; thanks +14115 957C 20 E3 8F jsr ADDFPC ; add to [FPC] +14116 957F 60 rts +14117 ; +14118 ; ---------------- +14119 ; GET OBJECT FLAGS +14120 ; ---------------- +14121 ; ENTRY: OBJECT # IN [ARG1], FLAG # IN [ARG2] +14122 ; EXIT: FLAG WORD IN [K], BIT ID IN [J], +14123 ; FLAG WORD ADDRESS IN [FPC] +14124 ; +14125 9580 FLAGSU: +14126 9580 A5 63 LDA ARG1+LO ; get table offset +14127 9582 A6 64 LDX ARG1+HI +14128 9584 20 F1 94 JSR OBJLOC ; GET OBJECT ADDR IN [FPC] +14129 9587 A5 65 LDA ARG2+LO ; LOOK AT FLAG ID +14130 9589 C9 10 CMP #$10 ; FIRST SET OF FLAGS? +14131 958B 90 14 BCC FLS1 ; YES, ADDR IN [FPC] IS CORRECT +14132 958D E9 10 SBC #16 ; ELSE ZERO-ALIGN FLAG INDEX +14133 958F AA TAX ; SAVE IT HERE +14134 9590 C9 10 CMP #$10 ; CHECK IF IN 2ND WORD +14135 9592 90 07 BCC FLS ; YES, GO ALIGN FOR THAT +14136 9594 E9 10 SBC #16 ; ELSE ALIGN TO 3RD WORD +14137 9596 AA TAX +14138 9597 A9 04 lda #4 ; 3rd Flag word +14139 9599 D0 02 bne FLSx ; and add it in +14140 959B FLS: +14141 959B A9 02 lda #2 ; 2nd Flag word +14142 959D FLSx: +14143 959D 20 E3 8F jsr ADDFPC +14144 95A0 FLS0: +14145 95A0 8A TXA ; RESTORE INDEX +14146 95A1 FLS1: +14147 95A1 85 7C STA K+LO ; SAVE FLAG ID HERE +14148 95A3 A2 01 LDX #1 ; INIT THE +14149 95A5 86 7A STX J+LO ; FLAG WORD TO +14150 95A7 CA DEX ; $0001 +14151 95A8 86 7B STX J+HI +14152 95AA A9 0F LDA #15 ; SUBTRACT THE BIT POSITION +14153 95AC 38 SEC ; FROM 15 +14154 95AD E5 7C SBC K+LO ; TO GET THE SHIFT LOOP +14155 95AF AA TAX ; INDEX + Wed Jun 7 1989 12:04 Page 210 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + +14156 95B0 F0 07 BEQ FLS2 ; EXIT NOW IF NO SHIFT NEEDED +14157 95B2 06 7A FLSL: ASL J+LO ; SHIFT THE BIT +14158 95B4 26 7B ROL J+HI ; INTO POSITION +14159 95B6 CA DEX +14160 95B7 D0 F9 BNE FLSL +14161 95B9 FLS2: +14162 95B9 20 5B 92 jsr FETCHB ; MOVE THE FLAG WORD +14163 95BC 85 7D sta K+HI ; INTO [K] - FIRST THE MSB +14164 95BE 20 C3 8F jsr NEXTFPC ; and then get get LSB +14165 95C1 20 5B 92 jsr FETCHB +14166 95C4 85 7C sta K+LO ; THEN THE LSB +14167 95C6 4C 29 90 jmp PREVFPC ; point back to flag word +14168 +14169 95C9 END +14170 +14171 +14172 95C9 BLKB ZBEGIN-$,0 +14173 9600 END + + + + Lines Assembled : 14173 Assembly Errors : 0 + + + \ No newline at end of file diff --git a/apple/yzip/rel.13/zbegin.asm b/apple/yzip/rel.13/zbegin.asm new file mode 100644 index 0000000..0f6ff06 --- /dev/null +++ b/apple/yzip/rel.13/zbegin.asm @@ -0,0 +1,100 @@ + STTL "--- START OF APPLE ][ INTERPRETER ---" + PAGE + + ORG INTR_BEGIN +; +; Set up for Double HiRes full screen graphics +; + lda PAGE2SW+OFF ; turn off page 2 + sta TEXTSW+OFF ; turn off text - turn on graphics + sta HIRESSW+ON ; turn on high resolution + sta MIXEDSW+OFF ; full screen graphics + sta COL80SW+ON ; turn on 80 column + sta IOUDIS+OFF ; turn ON (it too is backwards) Dhires switch + sta DHIRESW+OFF ; turn ON (it's backwards!) Dhires + + sta STORE80+ON ; turn on aux page display ability + lda BNK2SET ; read/write RAM, bank 2 + lda BNK2SET +; +; copy in progame from boot code +; + ldx #0 ; start at first letter +MVPRE: + lda BORG+3,X ; get letter + beq MVPREX ; all done + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + sta GAME,X ; save for asking about later + inx ; next letter + bne MVPRE ; do gen +MVPREX: + stx GAMEL ; save length of game name + lda #'.' ; get extension for names + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + inx ; next letter + lda #'D' ; for data segments + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + inx ; points to number + inx ; inclusive count for length + stx GAME1NML ; save length of name + stx GAME2NML ; save length of name + + lda #VERSID ; put in version number + sta ZBEGIN+ZINTWD+1 + + inc ZSP+LO ; INIT Z-STACK POINTERS + inc OLDZSP+LO ; TO "1" + inc SCREENF ; TURN DISPLAY ON + inc SCRIPT ; enable scripting + inc CRLF_CHECK ; do CR functino check + + lda WINTABLE+LO ; set WINDOW to point to window 0 + sta WINDOW+LO + lda WINTABLE+HI + sta WINDOW+HI ; okay, it does + + lda ARG1+LO ; using mouse? + beq ZBEGIN1 ; nope + ora #$78 ; point to correct screen holes + sta MSFIX0+1 + sta MSFIX1+1 ; and modify code to point to correct spot + sta MSFIX2+1 + lda ARG1+LO + ora #$F8 ; and one more + sta MSFIX2+1 +ZBEGIN1: + lda #$FF ; do a clear -1 to start off + sta ARG1+LO ; so arg 1 is this + jsr ZCLR ; doing it + + GET_PREFIX GPRE_PB ; get where we are to start + + lda D2SEG+HI ; start DSEGS at .D2 + sta DSEGS+HI + lda D2SEG+LO + sta DSEGS+LO + + lda #1 ; open game file .D2 please + jsr FETCH_FILE ; we did that + lda INFODOS ; are we on little dos? + beq ZBEGIN2 ; nope + jsr GET_SPECIAL ; do special preloading if so +ZBEGIN2: + lda D3SEG+HI ; this is cuz we be openin' .D3 + sta DSEGS+HI + lda D3SEG+LO + sta DSEGS+LO + lda #2 ; and just for giggles, do the + jsr FETCH_FILE ; same for game file .D3 + + jsr VLDZPC ; MAKE ZPC VALID + jsr NEXTPC ; skip over # of locals + + ; ... AND FALL INTO MAIN LOOP + + END + + diff --git a/apple/yzip/rel.13/zboot.asm b/apple/yzip/rel.13/zboot.asm new file mode 100644 index 0000000..c99e5d4 --- /dev/null +++ b/apple/yzip/rel.13/zboot.asm @@ -0,0 +1,261 @@ + PAGE + STTL "--- ZIP CODE BOOT PART ---" +ZBOOT: +; +; clear out ZERO page stuff +; + lda ARG2+LO ; get machine id! + sta ZBEGIN+ZINTWD ; save before it gets zeroed + + ldx #LASTWV-1 ; start at end of first part + lda #0 ; and clear to zero +ZEROL: + sta 0,X ; clear out zero page loc + dex ; next loc + bpl ZEROL ; and do next one + + ldx #ZEROPG ; now do other part +ZEROL1: + sta 0,X ; zero this one + inx ; point to next one + cpx #LASTZP ; find the last + bne ZEROL1 ; okay, so do it +; +; get game code from data and set up absolute pointers +; + lda ZBEGIN+ZVERS ; IS GAME A YZIP? + cmp #6 ; (X) + beq YESEZ ; YES, CONTINUE + +; *** ERROR #15 -- NOT AN EZIP GAME *** + lda #15 + ldy #0 + jmp ZERROR +YESEZ: + lda #%00111011 ; ENABLE SOUND, underline, MONOSPACING (X) + sta ZBEGIN+ZMODE + + lda #0 ; CLEAR HIGH BYTE + sta MOUSEF ; init mouse flag to no mouse + sta ZBEGIN+ZHWRD + sta ZBEGIN+ZVWRD + lda #MAXWIDTH ; SET SCREEN PARAMETERS + sta ZBEGIN+ZHWRD+1 + lda #MAXWIDTH/3 ; number of mono spaces on a line + sta ZBEGIN+ZSCRWD+1 + lda #MAXHEIGHT + sta ZBEGIN+ZVWRD+1 + lda #MAXHEIGHT/FONT_H + sta ZBEGIN+ZSCRWD ; number of lines of chars + lda #FONT_H ; height of font + sta ZBEGIN+ZFWRD + lda #3 ; width of font (2 spaces == 8 pixels) + sta ZBEGIN+ZFWRD+1 + lda #9 ; the color white is the foreground color + sta ZBEGIN+ZCLRWD+1 ; show Z game too + lda #2 ; black is the background color + sta ZBEGIN+ZCLRWD ; tell game about it +; +; just move global address to zero page for quick working +; + lda ZBEGIN+ZGLOBAL ; get page + sta GLOBAL+HI ; save which page + lda ZBEGIN+ZGLOBAL+1 ; LSB NEEDN'T CHANGE + sta GLOBAL+LO ; so just store it away +; +; figger absolute address for the fword table +; + lda ZBEGIN+ZFWORD ; get fword page number + jsr SETPC ; and get absolute address + sta FWORDS+HI ; show high addr of table + sty FWORDS+ABANK ; show which bank + lda ZBEGIN+ZFWORD+1 ; LSB NEEDN'T CHANGE + sta FWORDS+LO ; so just save it +; +; figger absolute address for the vocab table +; + lda ZBEGIN+ZVOCAB ; get fword page number + jsr SETPC ; and get absolute address + sta VOCAB+HI ; show high addr of table + sty VOCAB+ABANK ; show which bank + lda #0 ; this is always zero (get lo part from MPCL) + sta VOCAB+LO ; so just save it +; +; now do somethin' with the TCHAR table (maybe, if <> 0) +; + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + ora ZBEGIN+ZTCHAR+1 ; is it zero though? + bne TCH1 ; no, so copy it to somewhere useful + sta TCHARTBL ; not there, so zero first byte in table + beq TCHj ; jmp +TCH1: + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + jsr SETPC ; and now make absolute + sta FPCH ; Save in FPC + sty FPCBNK + lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + sta FPCL ; now move pointer to fetch spot + + lda #0 ; and set index + sta I ; thank you +TCHLP: + jsr FETCHB ; get the byte in [a] + ldx I ; get offset + inc I ; and point to next one + sta TCHARTBL,X ; save in lower memory, thank you + cmp #0 ; are we done yet? + beq TCHj ; NULL TERMINATED STRING + cmp #$FF ; $ff means all >128 chars are terminators + bne TCHLNEXT ; nope + lda #1 ; yes, + sta ALLFLG ; so set flag to say so +TCHLNEXT: + jsr NEXTFPC ; point to next one + jmp TCHLP ; and go get it +TCHj: + jsr DO_DSEGS ; set up disk segment pointers +; +; use mouse/joystick, see if either is connected +; + lda ZBEGIN+ZFLAGS+1 ; get game flags + and #FMOUS ; uses a mouse? + beq ZBEND ; nope, so don't ask + jsr MHOME ; clear & home +MSLOOP: + DLINE MMSG ; ask about Mouse/Joystick/Keyboard + lda #1 ; move to left + sta CHZ ; move to column 1 + jsr MBASCAL ; move cursor there! + lda #EOL.OR.$80 ; send out eol + jsr MCOUT ; bye + jsr MRDKEY ; get a key please + jsr MCOUT ; put key out there + and #$7F ; turn off hi bit + cmp #'M' ; mouse? + beq DO_MOUSE ; yup + cmp #'m' + beq DO_MOUSE + cmp #'J' ; Joystick? + beq DO_STICK ; yup + cmp #'j' + beq DO_STICK + cmp #'N' ; neither + beq DO_NEITHER ; yup + cmp #'n' + beq DO_NEITHER +MSLOOP1: + jsr MBELL ; complain + jmp MSLOOP ; and do again +DO_MOUSE: + jsr INST_MOUSE ; install mouse handlers + bcs MSLOOP1 ; problems, try again + bcc ZBEND ; continue +DO_STICK: + jsr INST_STICK ; install joystick handler + bcs MSLOOP1 ; try again + bcc ZBEND ; continue, please +DO_NEITHER: +ZBEND: +; +; now, set flags like I want them + lda #FMONO^FDISP^FCOLO + ldx MOUSEF ; doing mousey stuff? + beq ZBEND0 ; nope + ora #FMOUS ; then turn on that bit too +ZBEND0: + sta ZBEGIN+ZFLAGS+1 ; set game flags +; +; +; Multiply ZFOFF & ZSOFF * 8 to get actual offset +; + lda ZBEGIN+ZFOFF ; hi part + sta FOFFM ; this'll be the middle part + lda ZBEGIN+ZFOFF+1 ; lo part + asl A ; *2 + rol FOFFM + rol FOFFH + asl A ; *4 + rol FOFFM + rol FOFFH + asl A ; *8 + rol FOFFM + rol FOFFH + sta FOFFL ; lo part here too +; +; now do string offset +; + lda ZBEGIN+ZSOFF ; hi part + sta SOFFM ; this'll be the middle part + lda ZBEGIN+ZSOFF+1 ; lo part + asl A ; *2 + rol SOFFM + rol SOFFH + asl A ; *4 + rol SOFFM + rol SOFFH + asl A ; *8 + rol SOFFM + rol SOFFH + sta SOFFL ; lo part here too + + lda ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + sta ZPCM ; MSB + lda ZBEGIN+ZGO+1 ; AND LSB + asl A ; *2 + rol ZPCM + rol ZPCH + asl A ; *4 + rol ZPCM + rol ZPCH +; +; now add offset +; + clc ; doing adding + adc FOFFL ; add in lo part + sta ZPCL + lda ZPCM + adc FOFFM + sta ZPCM + lda ZPCH + adc FOFFH + sta ZPCH +; +; now, set up TBLPUR, FUNPRE, and FUNPUR +; + lda SEGTBL+SGTTBLE+1 ; get last page of table preload + asl A ; make 256K page + sta TBLPUR ; show last pre table + inc TBLPUR ; but we want first pure table address + inc TBLPUR ; so point to it + lda TBLPUR ; does table preload take up all preload? + cmp #PGBEGIN ; reach 1st paged page? + bcs ZBEND1 ; ayyup, no function preload + + lda SEGTBL+SGTFUNS+1 ; get first page of function preload + asl A ; make 256K page + sta FUNPRE ; show me + lda SEGTBL+SGTFUNE+1 ; last page of function preload + asl A ; make 256K page + sta FUNPUR ; show last pre function + inc FUNPUR ; but we want first pure function + inc FUNPUR ; now we point to it + + lda TBLPUR ; now figger out negative number to + sec ; add to function preload addres to + sbc FUNPRE ; get page offset in memory + sta FUNPGE ; set up offset +; +; and now to set up extension table pointer +; +ZBEND1: + lda ZBEGIN+ZEXTAB+1 ; LSB of table + sta MSTBL+LO ; stays the same + lda ZBEGIN+ZEXTAB ; MSB of table + jsr SETPC ; get me the memory addres + sty MSTBL+ABANK ; save bank + sta MSTBL+HI ; and page + + jsr INIT_CHARSET ; initialize the charset + jmp INITPAG ; set up paging system + + END diff --git a/apple/yzip/rel.13/zdos.asm b/apple/yzip/rel.13/zdos.asm new file mode 100644 index 0000000..40ddda8 --- /dev/null +++ b/apple/yzip/rel.13/zdos.asm @@ -0,0 +1,967 @@ + STTL "--- ZDOS (SEEKING, READING, WRITING) ---" + PAGE +; +; some ProDOS parameter blocks here +; +READ_PB: ; for READING files + db 4 ; 4 parameters +GMREF: db 0 ; refnum + dw IOBUFF ; read into io buffer + dw PAGELEN ; 512 byte buffer + dw 0 ; length actually read +OPEN_FILE: ; opening up the pure file + db 3 ; 3 parameters + dw GAME1NM ; name of pure file + dw GAME1FIO ; game file buffer + db 0 ; where refnum goes +PSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +SET_PB: + db 1 ; just one parameter + dw GAMEPL ; where to go to +; +; some messages +; +SWAPSAVE: db EOL, "Take out save disk and insert ", EOL +SWAPSAVEL EQU $-SWAPSAVE +NOSWAP: db "game disk." +NOSWAPL EQU $-NOSWAP +INS_MSG: db EOL,"Insert " +INS_MSGL EQU $-INS_MSG +SIDEMSG: db ", Side " +SIDEMSGL EQU $-SIDEMSG +DRIVE_MSG: db ", in Disk Drive " +DRIVE_MSGL EQU $-DRIVE_MSG + +RESEAT_MSG1: db EOL, "Having problems reading side #" +RESEAT_MSG1L EQU $-RESEAT_MSG1 +RESEAT_MSG2: db ".",EOL,"Please re-insert it.",EOL,EOL +RESEAT_MSG2L EQU $-RESEAT_MSG2 + IF CHECKSUM +RETRYING: db "RETRYING . . ." +RETRYINGL EQU $-RETRYING + ENDIF +; +; place to stash prefixes and names +; +GPRE_PB: ; game prefix spot + db 1 ; 1 parm + dw GAMEPL ; where to put prefix +GAMEL: db 0 +GAME: ds 15 ; longest name + +GAME1NM: +GAME1NML: + db 0 ; not sure how long +GAME1NAME: + BLKB 15,0 ; room for name +GAME1REF: db 0 ; save refnum here +GAME1NUM: db 0 ; number (0-3) of side + +GAME2NM: +GAME2NML: + db 0 ; not sure how long +GAME2NAME: + BLKB 15,0 ; room for name +GAME2REF: db 0 ; refnum for game file 2 +GAME2NUM: db 0 ; number (0-3) of side +GAMEPL: db 0 ; name of prefix for game file +GAMEP: ds 64-15 ; max len +; -------------------- +; READ A VIRTUAL PAGE +; -------------------- +; ENTRY: V-BLOCK TO READ IN [DBLOCK] +; BUFFER ADDRESS IN [DBUFF] +; DSKBNK SAYS WHERE TO PUT PAGE (AUX OR MAIN) +; EXIT: DATA AT [DBUFF] +; +RFLAG: ds 1 +RCHKS: ds 1 +GETDSK: + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now + + IF DEBUG + lda #0 + sta RFLAG ; show no retries + sta RCHKS ; and checksum for it + ENDIF + + jsr FINDSEG ; find the segment and point to it +GETDSKL: + SET_MARK PSEEK ; move to the block + bcs GDBAD ; just die then + jsr READ_DOS ; do the read, thank you + bcc GDEX ; okay, just fine + inc RFLAG + jsr RETRY ; try again + bcc GETDSKL ; try all over +GDEX: + lda READ_PB+RD_LENGTH+HI ; Get how much read in + cmp READ_PB+RD_BUFFLEN+HI ; same as we wanted? + beq GDEX1 ; yes + lda #23 + jmp ZERROR +GDEX1: + IF DEBUG + lda RFLAG ; see if we retried + beq GDEX3 ; nope + lda RCHKS ; did retry checksum? + bne GDEX2 + inc RCHKS ; now we have + ldy #0 ; save block + sty $B00 + clc +GDEXL: + lda IOBUFF,Y + sta $A00,Y + adc $B00 + sta $B00 + iny + bne GDEXL + beq GETDSKL +GDEX2: + ldy #0 + clc + sty RFLAG +GDEX2L: + lda IOBUFF,Y + adc RFLAG + sta RFLAG + iny + bne GDEX2L + lda RFLAG + cmp $B00 + beq GDEX3 + lda #24 + jmp ZERROR + ENDIF +GDEX3: + lda #>IOBUFF ; first 256 byte page + jsr COPY_DATA ; and copy from IOBUFF to DBUFF + inc DBUFF+HI ; point to next one + lda #>IOBUFF+1 ; next 256 byte page + jmp COPY_DATA ; and copy it over +GDBAD: + jmp DISK_FATAL ; just die then +RETRY: + IF CHECKSUM + DLINE RETRYING ; show me the way to go home + ENDIF + + dec RETRIES ; count this try + bmi GDBAD ; it's dead jim + beq RETRY0 ; ask for reset + cmp #1 ; down to last time? + bne RETRYX ; just try again + lda PSEEK+SM_FPOS+0 + pha + lda PSEEK+SM_FPOS+1 + pha + lda PSEEK+SM_FPOS+2 + pha + lda #0 ; seek to zero + sta PSEEK+SM_FPOS+0 ; save here for now + sta PSEEK+SM_FPOS+1 ; save here for now + sta PSEEK+SM_FPOS+2 ; save here for now + SET_MARK PSEEK ; move to the block + pla + sta PSEEK+SM_FPOS+2 + pla + sta PSEEK+SM_FPOS+1 + pla + sta PSEEK+SM_FPOS+0 + bcc RETRYX ; all done +RETRY0: + pha ; save disk error + jsr SWAP2INFOW ; go to window zero + DLINE RESEAT_MSG1 ; ask to move the disk around + lda GMREF ; get ref num + cmp GAME2REF ; game2? + bne RETRY1 ; nope + ldy GAME2NML ; get length + lda GAME2NM,Y ; and side # + bne RETRY2 ; and continue +RETRY1: + ldy GAME1NML ; get length + lda GAME1NM,Y ; and side # +RETRY2: + jsr CHAR ; send char out there + DLINE RESEAT_MSG2 ; and finish statement + pla ; get disk error back + jsr DISK_ERR ; tell the error + jsr SWAPBACK ; back to current window +RETRYX: + clc ; show goodness + rts ; and done +; +; this is the fatal error spot +; +DISK_FATAL: + jsr DISK_ERR ; print out problem +DRIVE_ERR: + lda #14 + jmp ZERROR ; DRIVE ACCESS ERROR +; +; this routine prints out the string associated with the error and +; returns with the carry set, like most routines do when there is +; an error. The error should be in [A]. +; +UNK_DISK: db "ProDOS error $" +UNK_DISKL EQU $-UNK_DISK + +DISK_ERR: + pha ; save [A] + jsr SWAP2INFOW ; point to information window + pla ; get it back + + ldx #ELISTL ; scan the error table +DSKE: + cmp ELIST,X ; is it this one + beq DSKE1 ; ayyup + dex ; now skip the address + dex ; of the description + dex ; point to next error number + bpl DSKE ; jump to start +; +; if we are here print out unknown error and it's value +; + pha ; save [A] + DLINE UNK_DISK ; show error + pla ; get [A] + jsr HEXNUM ; print [A] + jmp DSK_EXIT ; done +DSKE1: + inx ; point to string address + lda ELIST,X ; get lo part + sta L+LO ; save it + inx ; point to hi part + lda ELIST,X ; get hi part + tax ; save here + sta L+HI ; and here + ldy #0 ; for offset + lda (L),Y ; get length of string + tay ; save in y + inc L+LO ; point past length + lda L+LO ; get it + bne DSKPR ; for printing + inx ; wrapped +DSKPR: + txa ; hi part in a + ldx L+LO ; lo part in X + jsr DLINE ; print out message +DSK_EXIT: + jsr GETRET ; wait for RETURN + jsr SWAPBACK ; all done + sec ; show badness again + rts ; and be done with it +; +; HEXNUM - print out the HEX value of [A] at the current cursor +; location +; +HEXNUM: + pha + lsr A + lsr A + lsr A + lsr A + jsr NIB1 + pla +NIB1: + and #%00001111 + tay + lda HCHARS,Y + jsr CHAR ; print it out + rts +HCHARS: DB "0123456789ABCDEF" + +; ---------------------- +; WRITE [DBUFF] TO DISK +; ---------------------- +; ENTRY: File already open and positioned, ready to be written to +; from page in (DBUFF). Writes out 512bytes, starting @ DBUFF. +; EXIT: CARRY CLEAR IF OKAY, SET IF FAILED + +PUTDSK: + ldx DSKBNK ; get bank + ldy #0 ; clear Y + lda #>IOBUFF ; first buffer + jsr SAVE_DATA ; and copy from DBUFF to IOBUFF + + IF CHECKSUM == 1 + lda #>IOBUFF + jsr CKS_BLOCK + ENDIF + + jsr NEXT_DBUFF ; point to next buffer + ldx DSKBNK ; go get new DSKBNK + ldy #0 ; clear Y again + lda #>IOBUFF+1 ; top part + jsr SAVE_DATA ; copy to IOBUFF + + IF CHECKSUM == 1 + lda #>IOBUFF+1 + jsr CKS_BLOCK + ENDIF + + jsr NEXT_DBUFF ; count buffer + jmp WRITE_DOS ; and now write it +; --------------------- +; READ DBLOCK FROM DISK +; --------------------- +; CALLED BY RESTORE +; ENTER: with file already set up as it DBUFF +; L+LO == # of 256k blocks to read +; +GETRES: + lda L+LO ; get # of blocks + sta READ_PB+RD_BUFFLEN+HI + jsr READ_DOS + ldx #>PAGELEN ; get starting number of pages + stx READ_PB+RD_BUFFLEN+HI + bcc GTROK ; everything is fine + rts ; error if c == set +GTROK: + lda #>IOBUFF ; start at first block + sta L+HI ; we can use L+HI +GTRLOOP: + lda L+HI ; doing this block + + IF CHECKSUM == 1 + jsr CKS_BLOCK ; check check sum + ENDIF + + jsr COPY_DATA ; and copy from IOBUFF to DBUFF + jsr NEXT_DBUFF ; check for wrap + inc L+HI ; count this block + dec L+LO ; count this block + bne GTRLOOP ; do next one + rts ; all finished +; +; NEXT_DBUFF +; increment DBUFF to count the 2 pages done +; +NEXT_DBUFF: + inc DBUFF+HI ; point to next page + lda DBUFF+HI ; see where we are + cmp #>PRGLBL ; wrapping? + bne GTREX ; okay then + lda DSKBNK ; which bank we be in + bne GTR1 ; aux, so go to page 3 + inc DSKBNK ; point to aux + lda #Z2PAGE ; start of page 2 + bne GTREX ; so tell me which page +GTR1: + lda #P3BANK ; show page 3 bank + sta DSKBNK ; okay + lda #Z3PAGE ; page 3 of things +GTREX: + sta DBUFF+HI ; saved + rts ; all done +; +WRITE_DOS: + WRITE WRITE_SV ; write out save buffer + rts ; done +READ_DOS: + READ READ_PB ; read it + rts ; go home +; +; COPY_DATA - +; now move the data from iobuff to dbuff (in some bank) +; which part of IOBUFF is in [a] ($08 - $0B) +; +COPY_DATA: + sta SDLP3+2 ; self-modify code to get from IOBUFF + sta RDBNK+MAIN ; read from main + ldx DSKBNK ; get which bank it's going to + bmi CPD1 ; oh oh, third bank + sta WRTBNK,X ; and select that bank for writing + bpl CPD2 ; okay, bank selected +CPD1: + lda DBUFF+HI ; get from this zero page + sta ALTZP+AUX ; talk about aux mem + sta DBUFF+HI ; and save this in aux mem ZP +CPD2: + ldy #0 ; start at beginning + sty DBUFF+LO ; just to be sure +SDLP3: + lda IOBUFF,Y ; this becomes modified! + sta (DBUFF),Y ; to [DBUFF] + iny + bne SDLP3 + sta ALTZP+MAIN ; talk about main page again + sta WRTBNK+MAIN ; end up back at main + rts +; +; Segment table handling routines +; + +; +; FINDSEG - find the Virtual page in DBLOCK by searching through +; the SEGTBL. +; +DISKPAGE: ds 2 ; spot to put starting disk page +BIGPAGE: ds 2 ; DBLOCK/2 for 512 pages +FINDSEG: + lda DBLOCK+HI ; work with MSB first + lsr A ; /2 + sta BIGPAGE+HI + lda DBLOCK+LO ; now LSB + ror A ; /2 + sta BIGPAGE+LO + lda GAME1NUM ; get number for disk 1 + jsr SCANSEG ; scan through the current disk table + lda GAME1REF ; save refnum + bcc FNDSG1 ; found it, figger it out + lda GAME2NUM ; get number for disk 2 + jsr SCANSEG ; see if it is here + lda GAME2REF ; save refnum + bcc FNDSG1 ; ayyup + jsr SEGQUEST ; get correct disk/file with segment +FNDSG1: + sta PSEEK+SM_REFNUM ; for seeking + sta GMREF ; and for reading + lda (DSEGS),Y ; pick up MSB of disk page + sta DISKPAGE+HI ; save it + iny ; point to LSB + lda (DSEGS),Y ; get it + sta DISKPAGE+LO ; save it +; now point to Starting page again + dey + dey + dey + dey + lda BIGPAGE+LO ; LSB of desired page + sec ; doing subtract + sbc (DSEGS),Y ; get rid of LSB of starting page + sta PSEEK+SM_FPOS+1 ; save here for now + dey ; point to MSB of starting page + lda BIGPAGE+HI ; get DBLOCK MSB + sbc (DSEGS),Y ; get offset + sta PSEEK+SM_FPOS+2 ; save here temporarily + clc ; now add offset to starting disk page + lda DISKPAGE+LO ; get starting disk page + adc PSEEK+SM_FPOS+1 ; add inter-segment offset + sta PSEEK+SM_FPOS+1 ; save LSB + lda DISKPAGE+HI ; get MSB of segment disk page + adc PSEEK+SM_FPOS+2 ; add inter-segment offset + sta PSEEK+SM_FPOS+2 ; save MSB of disk page + asl PSEEK+SM_FPOS+1 ; *2 for 256Kb pages + rol PSEEK+SM_FPOS+2 ; okay, we did + lda DBLOCK+LO ; check to see which page in 512 we are + and #$01 ; if odd, then add one more + beq FNDEX ; all done then + inc PSEEK+SM_FPOS+1 ; one more page + bne FNDEX ; all done if no wrap + inc PSEEK+SM_FPOS+2 ; nother page +FNDEX: + rts ; done +; +; SCANSEG - look through the current segment table for the desired +; address found in BIGPAGE. Return with Y pointing to disk page +; and carry cleared if found. Otherwise, return carry set. +; [A] = which side number we are checking (0-n) +; +SCANSEG: + pha ; save which disk + asl A ; make word index + tax ; make it an index + lda DSKSEG+LO,X ; get LSB + sta DSEGS+LO + lda DSKSEG+HI,X + sta DSEGS+HI + ldy #SGTNSEG+1 ; point to segment count + lda (DSEGS),Y ; get it + tax ; use x as counter + pla ; get which side + tay ; is it side zero + bne SCANSG1 ; nope + ldy #SGTSEG+6 ; skip first entry, cuz they're preload + bne SCANNING ; okay ready to go +SCANSG1: + ldy #SGTSEG ; begin at beginning +SCANNING: + lda (DSEGS),Y ; get MSB of start + cmp BIGPAGE+HI ; check against block we want + beq SCAN1 ; might be okay + bcc SCAN2 ; PAGE > start seg, check end seg + iny ; LSB of start +SCAN0: + iny ; MSB of end + bcs NEXTSEG ; not this one +SCAN1: + iny ; point to LSB of start + lda (DSEGS),Y ; get LSB + cmp BIGPAGE+LO ; check against desired LSB + beq GOTSEG ; we found it + bcs SCAN0 ; DBLOCK LSB < then start LSB, not found + dey ; point back to MSB of start +SCAN2: + iny ; LSB of start + iny ; MSB of end + lda (DSEGS),Y ; get MSB of end + cmp BIGPAGE+HI ; check against DBLOCK MSB + bcc NEXTSEG ; end < DBLOCK, check next segment + bne GOTSEG1 ; end > DBLOCK, must be in this segment + iny ; point to end LSB + lda (DSEGS),Y ; get LSB + cmp BIGPAGE+LO ; how does it compare to desired LSB + bcs GOTSEG2 ; it's <= end, so it is here + dey ; point back to MSB +NEXTSEG: + iny ; point to LSB of end + iny ; MSB of disk page + iny ; LSB of disk page + iny ; MSB of next start page + dex ; count this segment + bne SCANNING ; check this segment + + sec ; show not on this disk + rts ; and done +GOTSEG: + iny ; MSB of end page +GOTSEG1: + iny ; LSB of end page +GOTSEG2: + iny ; MSB of disk offset + clc ; show we found it + rts ; all done +; +; SEGQUEST - find the correct disk/file with the desired page on +; it. Returns SCANSEG's stuff. +; +DISKCNTR: ds 1 ; disk count down +PAGENF: + db "Page not found in segment table: " +PAGENFL EQU $-PAGENF +SEGQUEST: + lda #1 ; start at first disk + sta DISKCNTR ; init counter +SEGQL: + lda DISKCNTR ; get disk + cmp SEGTBL+SGTDISKS+1 ; looked at all the disks? + bne SEGQL1 ; nope +; +; as a last resort, check disk 1, the boot disk +; + lda #0 ; set up DISKCNTR + sta DISKCNTR ; we did + jsr SCANSEG ; see if it is there + bcc SEGQ1 ; we found it + + DLINE PAGENF ; page not found + lda BIGPAGE+HI ; show MSB + jsr HEXNUM ; printed + lda BIGPAGE+LO ; and LSB + jsr HEXNUM ; we did + + lda #17 ; bad page + jmp ZERROR ; die a horrible death +SEGQL1: + lda DISKCNTR ; get which disk we be working on + jsr SCANSEG ; find out if it is here + bcc SEGQ1 ; it is, so open up file + inc DISKCNTR ; not in this disk + bne SEGQL ; and try again +; +; we have found the disk it is in, so ask for it if necessary +; +SEGQ1: + tya ; save the y pointer + pha ; it is saved + lda DISKCNTR ; get which disk we found it under + jsr FETCH_FILE ; go get the disk desired + pla ; get the Y reg back + tay ; and show it + lda GMREF ; get reference number again + rts ; all done +; +; FETCH_FILE: check to see if we can open GAMEFILE# (where # is in [A]) +; if not, ask for DISK#. +; +SAVENUM: db 0 ; spot to save ascii number +FETCH_FILE: + clc ; adding to make + adc #$30 ; it an ascii number + sta SAVENUM ; just save a minute + inc SAVENUM ; make name be one based + ldx GAME1NML ; get length of name + lda SAVENUM ; get name back + cmp #'3' ; are we looking for disk 1 or 2? + bcs FEFI1 ; disks 3 and up handled special +FEFI00: + cmp GAME1NM,X ; is it the current open one? + bne FEFI0 ; nope, so we need to open it + ldy GAME1REF ; get game 1 refnum + bne FEFIX ; all set, so point to it +FEFI0: + jsr DO_GAME1 ; handle it special + lda GAME1REF ; fetch refnum + jsr GET_PDATA ; now get the picture data + ldy GAME1REF ; refetch refnum + bne FEFIX ; so all done +FEFI1: + ldx GAME2NML ; get length of second name + cmp GAME2NM,X ; how bout second open file? + bne FEFI2 ; nope, so we need to open it + ldy GAME2REF ; it is second one, so show me + bne FEFIX ; it is open too +FEFI2: + lda GAME2REF ; get its refnum + beq FEFI20 ; nothing to close, thank you + sta CLOSE_PB+CL_REFNUM ; show close who to close + CLOSE CLOSE_PB ; close it up tight +FEFI20: + jsr OPEN_GAME2 ; open up GAME2 file + lda GAME2REF ; get refnum for this file + jsr GET_PDATA ; now get the picture data + ldy GAME2REF ; get ref back, please +FEFIX: + sty PSEEK+SM_REFNUM ; for seeking + sty GMREF ; and for reading + rts ; did it +; +; OPEN_GAME2 - open up the file that GAME2NM is pointing to, +; returning the REFNUM in [A], after storing in GAME2REF, +; and the 2 picture structures +; +OPEN_GAME2: + ldx GAME2NML ; get end of name + lda SAVENUM ; get new name + sta GAME2NM,X ; using second file + lda #>GAME2NM ; get lo byte + sta OPEN_FILE+OP_PATHNAME+HI + lda #GAME2FIO ; now set up file i/o buffer + sta OPEN_FILE+OP_FILEBUFF+HI + lda #0 if multi disk game + +SET_GAMEPRE: + jsr SWAP2INFOW ; point to info window + lda SWAPPED ; are we swapping disks? + beq SETGP ; nope, don't change game prefix + lda SAVENUM ; get which disk to put it + ldy GAMEPL ; get length of prefix + dey ; subtract 2 to point to prefix + dey ; number + sta GAMEP,Y ; set number for prefix +SETGP: + lda #>GAMEPL ; set up parm block + sta SET_PB+SP_PATHNAME+HI + lda #= side 3, must be disk drive 2 + bcs SEGTP02 ; fine, send that message out + lda #'1' ; ask for drive 1 then +SEGTP02: + jsr CHAR ; save which drive + lda #'.' ; finish sentence + jsr CHAR ; okay +SEGTP03: + jsr GETRET ; wait for + jmp SETGP0 ; try again +SETGP1: + jmp SWAPBACK ; pointing to disk +; +; DO_GAME1 - open up the special game 1 file and point to it +; +DO_GAME1: + ldy GAME1REF ; get the current game 1 ref num + beq DOG1 ; not currently open + pha ; save Name + sty CLOSE_PB+CL_REFNUM ; show close + CLOSE CLOSE_PB ; and close it + pla ; get name back +DOG1: + ldx GAME1NML ; get length of name + lda SAVENUM ; get new number + sta GAME1NM,X ; save name + pha ; save it for later use + lda #>GAME1NM ; get lo byte + sta OPEN_FILE+OP_PATHNAME+HI + lda #GAME1FIO ; now set up file i/o buffer + sta OPEN_FILE+OP_FILEBUFF+HI + lda # + jsr CHAR ; printed + dex ; count back one, as loop starts with inx + bne LSTVL ; go do next one +LSTVEX: + rts ; toots finis +; +; CHECKVOLS - set prefix to particular volume that is currently online +; +CHECKVOLS: + lda CHPTR+HI ; is it zero? + bne CHV1 ; if not, then get next volume + ONLINE ONLINE_PB ; get online volumes + bcc CHV0 ; okey dokey +CHVBX: + sec ; show badness + rts ; all done +CHV0: + lda #<(IOBUFF-16) ; get LSB (-16 cuz we start with add) + sta CHPTR+LO + lda #>IOBUFF ; and mSB + sta CHPTR+HI + lda #>SCRBUFF ; this is where we will work on it + sta SET_PB+SP_PATHNAME+HI + lda #SP_START ; where does it go? + sta L+HI ; L is pointer to there +GTS_RD: + lda #MAIN ; make sure we are in main + sta WRTBNK+MAIN + READ READ_PB ; go get 1Kb + bcc GTS_RD1 ; just fine + jsr RETRY ; try again + bcc GTS_RDL ; and do it again +GTS_RD1: + ldx #SP_BANK ; get bank that special is in + sta WRTBNK,X + lda #>IOBUFF ; get MSB of start + sta K+HI ; K is source + ldx #2 ; 2 blocks of 256 bytes each +GTS_CPL0: + ldy #0 ; indexer +GTS_CPL: + lda (K),y ; get it + sta (L),y ; store it + iny ; next + bne GTS_CPL ; gwon then + inc K+HI ; point to next block + inc L+HI ; for destination too + dex ; count block + bne GTS_CPL0 ; next block + dec J+LO ; count this 1Kb + bne GTS_RD ; go get next one + + sta WRTBNK+MAIN ; make sure we are in main +; +; now figger out last page +; + ldy #SGTSEG+1 ; get start segment LSB + lda (INFODOS),Y ; got it + clc ; doing add + adc #SP_SIZE ; add in size MSB + sta INFODOS_END+HI ; and save it + lda INFODOS_END+LO ; now, subtract one to make + bne GTS_END ; it inclusive + dec INFODOS_END+HI ; wrapped, so dec MSB +GTS_END: + dec INFODOS_END+LO ; make pointers inclusive + + rts ; done + + IF CHECKSUM == 1 +CKS_COUNT: db 0 +CKSB: db 0 +CKS_BLOCK: + pha + sta CKSMOD+2 + ldy #0 + lda CKSB +CKSLP: + clc +CKSMOD: adc IOBUFF,Y + iny + bne CKSLP + + sta CKSB + inc CKS_COUNT + pla + rts + + IF 0 + jsr HEXNUM + lda CKS_COUNT + cmp #$F + bne CKSCNT + lda #0 + sta CKS_COUNT + lda #EOL + bne CKSSEND +CKSCNT: + inc CKS_COUNT + lda #SPACE +CKSSEND: + jsr CHAR + jsr DISP_LINE + pla + rts + ENDIF + + ENDIF + + END diff --git a/apple/yzip/rel.13/zero.equ b/apple/yzip/rel.13/zero.equ new file mode 100644 index 0000000..f6f7c7f --- /dev/null +++ b/apple/yzip/rel.13/zero.equ @@ -0,0 +1,175 @@ + STTL "--- ZERO PAGE VARIABLES ---" + PAGE + +SCRCX EQU 0 ; CURSOR HORIZONTAL +SCRCY EQU SCRCX+1 ; CURSOR VERTICAL +SCRBTM EQU SCRCY+1 ; first line outside current window +MAXLINES EQU SCRBTM+1 ; maximum number of lines in window +LEFTMRG EQU MAXLINES+1 ; left edge + left margin in current window +WINDOW EQU LEFTMRG+1 ; (WORD) address of current window structure +LINE_X EQU WINDOW+2 ; (WORD) width of line counter +CC_OFF EQU LINE_X+2 ; save offset for char drawing +CLSLEFT EQU CC_OFF+1 ; screen limits for CLS code +CLSTOP EQU CLSLEFT+1 ; top of screen +CLSWIDTH EQU CLSTOP+1 ; # of columns +CLSHEIGHT EQU CLSWIDTH+1 ; # of lines +; +; some variables for all the screen positioning code +; +NY_DATA EQU CLSHEIGHT+1 ; place for GET/PUT_NYBBLE to use +CH_OFFSET EQU NY_DATA+1 ; offset into char data table +DATALOOP EQU CH_OFFSET+1 ; loop counter for byte works +BITOFF EQU DATALOOP+1 ; bit offset into screen byte +CH_DATA EQU BITOFF+1 ; actual char data being worked on +SCR_DATA EQU CH_DATA+1 ; screen byte being worked on +SH_LOOP EQU SCR_DATA+1 ; loop counter for bit shifting +SCROLLY EQU SH_LOOP+1 ; save spot for y pos when scrolling +RETRIES EQU SCROLLY+1 ; (BYTE) Machine ID +CHRMAX EQU RETRIES+1 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD +SCLLINES EQU CHRMAX+1 ; (BYTE) how many lines to scroll +FMTTBL EQU SCLLINES+1 ; (BYTE) flag to show formatted table output +STMASK EQU FMTTBL+1 ; (BYTE) Mask to use on first byte of CLS +ENDMASK EQU STMASK+1 ; (BYTE) Mask to use on last byte of CLS +CHPTR EQU ENDMASK+1 ; (WORD) pointer to char data +SCOFF EQU CHPTR ;(BYTE) Offset used by scroll +SCLDIR EQU CHPTR+1 ;(BYTE) Direction of scroll - >0 up, <0 down +DSEGS EQU CHPTR+2 ; (WORD) Pointer to current disk's segments +;WIDE_FLAG EQU SCOFF+1 ; (BYTE) <> 0 if 16 bytes in char data +;DSEGS EQU WIDE_FLAG+1 ; (WORD) Pointer to current disk's segments +LASTWV EQU DSEGS+2 ; last of the WINDOW variables + +ZEROPG EQU $50 ; FIRST FREE Z-PAGE LOCATION +; +; these are first, cuz ZBOOT inits them so we don't want to clear them +; at ZBEGIN warm start +; +GLOBAL EQU ZEROPG ; (Relative Addr.) GLOBAL VARIABLE POINTER +VOCAB EQU GLOBAL+2 ; (ADDRESS) Vocab table pointer +FWORDS EQU VOCAB+3 ; (ADDRESS) F-WORDS TABLE POINTER +MOUSEF EQU FWORDS+3 ; (BYTE) ==-1/1 if we have mouse/joystick +INFODOS EQU MOUSEF+1 ; (WORD) if <>0, then pointer to D2SEG +FUNOFF EQU INFODOS+2 ; (ADDRESS) Function Offset (ZFOFF*8) +FOFFH EQU FUNOFF ; (BYTE) Hi part +FOFFM EQU FUNOFF+1 ; (BYTE) Middle part +FOFFL EQU FUNOFF+2 ; (BYTE) Lo part +STROFF EQU FUNOFF+3 ; (ADDRESS) String Offset (ZSOFF*8) +SOFFH EQU STROFF ; (BYTE) Hi part +SOFFM EQU STROFF+1 ; (BYTE) Middle part +SOFFL EQU STROFF+2 ; (BYTE) Lo part +; +; Beginning of warm start zeroing +; +OPCODE EQU STROFF+3 ; (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 +ARG5 EQU OPCODE+10 ; (WORD) +ARG6 EQU OPCODE+12 ; (WORD) +ARG7 EQU OPCODE+14 ; (WORD) +ARG8 EQU OPCODE+16 ; (WORD) +ABYTE EQU OPCODE+18 ; (BYTE) X-OP ARGUMENT BYTE +BBYTE EQU OPCODE+19 ; (BYTE) XCALL ARG BYTE (EZIP) +ADEX EQU OPCODE+20 ; (BYTE) X-OP ARGUMENT INDEX +VALUE EQU OPCODE+21 ; (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 +L EQU VALUE+8 ; (WORD) GEN-PURPOSE REGISTER #4 +ZPC EQU VALUE+10 ; (3 BYTES) ZIP PROGRAM COUNTER +ZPCL EQU ZPC ; (BYTE) <8 BITS OF [ZPC] +ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] +ZPCH EQU ZPC+2 ; (BYTE) >BIT OF [ZPC] +ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE +ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +ZPNTH EQU ZPCPNT+1 ; (BYTE) +ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +MPC EQU ZPCPNT+3 ; (3 BYTES) MEMORY PROGRAM COUNTER +MPCL EQU MPC ; (BYTE) <8 BITS OF [MPC] +MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] +MPCH EQU MPC+2 ; (BYTE) >BIT OF [MPC] +MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE +MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +MPNTH EQU MPCPNT+1 ; (BYTE) +MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +FPC EQU MPCBNK+1 ; (3 Bytes) Fetch pointer +FPCL EQU FPC ; (BYTE) Low part +FPCH EQU FPCL+1 ; (BYTE) High Part +FPCBNK EQU FPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) +SPC EQU FPCBNK+1 ; (3 Bytes) Fetch pointer +SPCL EQU SPC ; (BYTE) Low part +SPCH EQU SPCL+1 ; (BYTE) High Part +SPCBNK EQU SPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + +; Z-STRING MANIPULATION VARIABLES + +LINLEN EQU SPCBNK+1 ; (BYTE) LENGTH OF CURRENT LINE +SOURCE EQU LINLEN+1 ; (BYTE) counter for read +WRDLEN EQU SOURCE+1 ; (BYTE) LENGTH OF CURRENT WORD +ESIZE EQU WRDLEN+1 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES +PSET EQU ESIZE+1 ; (BYTE) PERMANENT CHARSET +TSET EQU PSET+1 ; (BYTE) TEMPORARY CHARSET +ZCHAR EQU TSET+1 ; (BYTE) CURRENT Z-CHAR +OFFSET EQU ZCHAR+1 ; (BYTE) F-WORD TABLE OFFSET +ZFLAG EQU OFFSET+1 ; (BYTE) Z-WORD ACCESS FLAG +ZWORD EQU ZFLAG+1 ; (WORD) CURRENT Z-WORD +CONCNT EQU ZWORD+2 ; (BYTE) Z-STRING SOURCE COUNTER +CONIN EQU CONCNT+1 ; (BYTE) CONVERSION SOURCE INDEX +CONOUT EQU CONIN+1 ; (BYTE) CONVERSION DEST INDEX +DIRTBL EQU CONOUT+1 ; (WORD) CONTAINS TBLE TO STORE CHARS TO +XSIZE EQU DIRTBL+2 ; (WORD) SCREEN WIDTH FOR TESTS +RAND EQU XSIZE+2 ; (WORD) Random number offset +CURWIN EQU RAND+2 ; (BYTE) WHICH WINDOW TO WRITE IN +LENGTH EQU CURWIN+1 ; (WORD) CHAR POSITION ON THE SCREEN +CHRCNT EQU LENGTH+2 ; (BYTE) CHAR POSITION IN [LBUFF] +SCRIPT EQU CHRCNT+1 ; (BYTE) SCRIPT ENABLE FLAG +LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER +IOCHAR EQU LINCNT+1 ; (BYTE) CHARACTER BUFFER +COLORP EQU IOCHAR+1 ; (WORD) Pointer to current background color +ZSP EQU COLORP+2 ; (WORD) Z Stack +SCREENF EQU ZSP+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT +TABLEF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT +VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH +DBUFF EQU VOCEND+3 ; (WORD) RAM PG TO ACCESS (LSB = 0) +DSKBNK EQU DBUFF+2 ; (BYTE) MAIN/AUX bank +ALLFLG EQU DSKBNK+1 ; (BYTE) IF =1 ALL FCN KEYS (>127) ARE TCHARS +UNDFLG EQU ALLFLG+1 ; (BYTE) Underlining flag +INVFLG EQU UNDFLG+1 ; (BYTE) Inverse flag +MEMPAGE EQU INVFLG+1 ; (BYTE) Save spot for XPAGING stuff +CPY_COUNT EQU MEMPAGE+1 ; (BYTE) Number of bytes for copy line +TBLHEIGHT EQU CPY_COUNT+1 ;(BYTE) Number of lines in printing table +TBLWIDTH EQU TBLHEIGHT+1 ;(BYTE) Number of bytes per line +TBLCNT EQU TBLWIDTH+1 ;(BYTE) Counter for table printing +FONTFLG EQU TBLCNT+1 ;(BYTE) Which font (!=0 is width) +TBLPUR EQU FONTFLG+1 ;(BYTE) first pure table page +FUNPRE EQU TBLPUR+1 ;(BYTE) first preloaded function page +FUNPUR EQU FUNPRE+1 ;(BYTE) first pure function page +FUNPGE EQU FUNPUR+1 ;(BYTE) -number to get function preload page +DELAY_COUNTER EQU FUNPGE+1 ;(BYTE) counter for delay loop +; +; some char-to-screen variables +; +CHAR_D1 EQU DELAY_COUNTER+1 ; (BYTE) character data, part 1 +CHAR_D2 EQU CHAR_D1+1 ; (BYTE) char data, part 2 +CW EQU CHAR_D2+1 ; (BYTE) width of the character +CLKCTR EQU CW+1 ; (BYTE) counter for mouse clicking +MSX EQU CLKCTR+1 ; (BYTE) mouse cursor X +MSY EQU MSX+1 ; (BYTE) mouse cursor Y +CURRENT EQU MSY+1 ; (BYTE) current paging bufer +;CURSOR_OFF EQU CURRENT+1 ; (BYTE) ==1 if "don't show the blinking cursor" +MSTBL EQU CURRENT+1 ; (ADDRESS) pointer to extension table +LASTZP EQU MSTBL+3 ; just checking +; +; these routines are in non-swapped memory +; +ZERO_FB EQU LASTZP ; put fetch byte routine in at end of ZP +ZERO_ZF EQU ZERO_FB+11 ; and ZPCPNT fetch after that +ZERO_MF EQU ZERO_ZF+9 ; and MPCPNT fetch after that +SAVE_DATA EQU ZERO_MF+9 ; copy data from DBUFF to IOBUFF routine +; +; and just to check the end +; +ZEE_END EQU SAVE_DATA+17 ; should be == 100 + + END diff --git a/apple/yzip/rel.13/zip.equ b/apple/yzip/rel.13/zip.equ new file mode 100644 index 0000000..22bb0b8 --- /dev/null +++ b/apple/yzip/rel.13/zip.equ @@ -0,0 +1,116 @@ + STTL "--- YZIP EQUATES ---" + PAGE + +VERSID EQU 13 ; VERSION OF INTERPRETER + ; See file "versions" for complete descriptions + +TRUE EQU $FF +FALSE EQU 0 + +; --------------------- +; Segment table equates +; --------------------- +SGTDISKS EQU 0 ; number of disks +SGTPAD EQU SGTDISKS+2 ; just some extra room +SGTCHKS1 EQU SGTPAD+16 ; Checksum for disk 1 (PRELOAD) +SGTPICOF1 EQU SGTCHKS1+2 ; N/A +SGTSEG1 EQU SGTPICOF1+2 ; # of segments +SGTGPOF1 EQU SGTSEG1+2 ; Global Picture Directory +SGTTBLS EQU SGTGPOF1+2 ; Start of table preload (should be 0) +SGTTBLE EQU SGTTBLS+2 ; Last page of table preload +SGTTBLX EQU SGTTBLE+2 ; N/A +SGTFUNS EQU SGTTBLX+2 ; First page of function preload +SGTFUNE EQU SGTFUNS+2 ; End page of function preload +SGTFUNX EQU SGTFUNE+2 ; N/A +SGTDSK EQU SGTFUNX+2 ; Actual start of disk segment tables + +SGTCHKS EQU 0 ; check sum for file +SGTPICOF EQU 2 ; picture data offset +SGTNSEG EQU 4 ; # of segments in this list +SGTGPOF EQU 6 ; Global Directory Offset +SGTSEG EQU 8 ; start of segments +; --------------------- +; Z-CODE HEADER OFFSETS +; --------------------- + +ZVERS EQU 0 ; VERSION BYTE +ZMODE EQU 1 ; MODE SELECT BYTE +ZID EQU 2 ; GAME ID WORD +ZENDLD EQU 4 ; # OF QUADWORDS ON SIDE 1 OF DISK +ZGO EQU 6 ; EXECUTION ADDRESS +ZVOCAB EQU 8 ; START OF VOCABULARY TABLE +ZOBJEC EQU 10 ; START OF OBJECT TABLE +ZGLOBAL EQU 12 ; START OF GLOBAL VARIABLE TABLE +ZPURBT EQU 14 ; START OF "PURE" Z-CODE +ZFLAGS EQU 16 ; FLAG WORD +ZSERIA EQU 18 ; 3-WORD 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 +ZINTWD EQU 30 ; INTERPRETER ID WORD (SUPPLIED BY EZIP) +ZSCRWD EQU 32 ; SCREEN PARAMETER WORD ( " " " ) +ZHWRD EQU 34 ; DISPLAY WIDTH IN PIXELS +ZVWRD EQU 36 ; DISPLAY HEIGHT IN PIXELS +ZFWRD EQU 38 ; FONT HEIGHT, FONT WIDTH +ZFOFF EQU 40 ; FUNCTION OFFSET +ZSOFF EQU 42 ; STRING OFFSET +ZCLRWD EQU 44 ; FORGROUND COLOR, BACKGROUND COLOR +ZTCHAR EQU 46 ; POINTER TO TBL OF TERMINATING CHARS +ZTWIDTH EQU 48 ; Running counter for table output char width +ZCRFUNC EQU 50 ; FUNCTION FOR CARRIAGE RETURNS +ZCHRSET EQU 52 ; POINTER TO CHAR SET TBL +ZEXTAB EQU 54 ; Points to extension table, if needed +; +; Extension table offsets +; +ZEXTLEN EQU 0 ; Length of extension table +ZMSLOCX EQU 2 ; x location of mouse +ZMSLOCY EQU 4 ; y location of mouse +ZMSETBL EQU 6 ; MOUSE TBL CHANGE WORD +ZMSEDIR EQU 8 ; DIRECTION MENU +ZMSEINV EQU 10 ; INVENTORY MENU +ZMSEVRB EQU 12 ; FREQUENT VERB MENU +ZMSEWRD EQU 14 ; FREQUENT WORD MENU +ZBUTTN EQU 16 ; BUTTON HANDLER +ZJOYST EQU 18 ; JOYSTICK HANDLER +ZBSTAT EQU 20 ; BUTTON STATUS +ZJSTAT EQU 22 ; JOYSTICK STATUS +; +; ZFLAGS values +; +FSCRI EQU $01 ; scripting? +FMONO EQU $02 ; mono spaced font? +FSTAT EQU $04 ; status line refresh? +FDISP EQU $08 ; uses DISPLAY operations? +FUNDO EQU $10 ; uses UNDO? +FMOUS EQU $20 ; uses mouse? +FCOLO EQU $40 ; uses color? +FMENU EQU $80 ; uses menus? +;--------------- +; Picture data +;--------------- +;=== DATA HEADER === +PHFID EQU 0 ; File ID +PHFLG EQU PHFID+1 ; Flags +PHHUFF EQU PHFLG+1 ; Pointer to Huffman data +PHNLD EQU PHHUFF+2 ; # entries in local directory +PHNGD EQU PHNLD+2 ; # entries in global directory +PHDSIZE EQU PHNGD+2 ; Local directory entry size +PHCHKS EQU PHDSIZE+2 ; File Checksum +PHFVERS EQU PHCHKS+2 ; File Version (N/A) +PHEXTRA EQU PHFVERS+2 ; Extra room for getting fatter +PHSIZE EQU 16 ; 16 bytes is header size +;=== DATA HEADER FLAGS === +PHFGD EQU $1 ; data has global directory +PHFHUFF EQU $2 ; Huffman encoded pictures +PHFHUFF1 EQU $4 ; All pictures use same Huff tree +PHFPAL EQU $8 ; No pallette information +;=== LOCAL DIRECTORY === +PLDID EQU 0 ; Picture ID +PLDWID EQU PLDID+2 ; Picture Width +PLDHGHT EQU PLDWID+1 ; Picture Height +PLDFLG EQU PLDHGHT+1 ; Flags +PLDPTR EQU PLDFLG+1 ; Pointer to picture data +PLDSIZE EQU PLDPTR+3 ; size of local directory entry + + END diff --git a/apple/yzip/rel.13/zsavres.asm b/apple/yzip/rel.13/zsavres.asm new file mode 100644 index 0000000..f82ce0c --- /dev/null +++ b/apple/yzip/rel.13/zsavres.asm @@ -0,0 +1,721 @@ + + STTL "--- ZIP SAVE AND RESTORE ROUTINES ---" + PAGE +; ----------------------------- +; SET UP SAVE & RESTORE SCREENS +; ----------------------------- +SAVRES: + jsr ZCRLF ; CLEAR THE LINE BUFFER + lda #0 + sta SCRIPT ; DISABLE SCRIPTING + lda PAGE2SW+MAIN ; just do this for the heck of it + lda BNK2SET ; this stuff too + lda BNK2SET + + rts + +; ----------------------------- +; SAVE & RESTORE STRINGS +; ----------------------------- +YES: DB "YES" + DB EOL +YESL EQU $-YES +NO: DB "NO" + DB EOL +NOL EQU $-NO + +NAMEQ: db EOL + db "Insert save disk and enter " + db "full pathname of save file: " + db EOL + db "Hit '?' key to get a list of online volumes." + db EOL + db "Current pathname is:", + db EOL +NAMEQL EQU $-NAMEQ +SNDATA: ; show start of name and length +SNAMEL: db 0 ; place to save length of name +SAVENAME: ds 64+15 ; save plenty of room for max name + +DELQ: db EOL,"File exists, delete it (Yes/No)? " +DELQL EQU $-DELQ+1 ; include this following EOL +RETQ: db EOL,"Please hit [RETURN]",EOL +RETQL EQU $-RETQ +PREFIX_ERR: db EOL,"Name must have prefix, " + db "i.e.: /DISKNAME/FILENAME",EOL +PREFIX_ERRL EQU $-PREFIX_ERR +; ----------------------------- +; SAVE/RESTORE Parameter Blocks +; ----------------------------- +CREATE_PB: + db 7 ; 7 parameters + dw SNDATA ; pointer to name + db $C3 ; full access to file + db $06 ; BIN file type + dw 0 ; no aux data + db $01 ; standard file + dw 0 ; create date + dw 0 + ; creation time +SETEOF_PB: + db 2 ; 1 parameter + db 0 ; refnum + db 0,0,0 ; set to zero spot to clear it out +OPEN_SV: + db 3 ; 3 parameters + dw SNDATA ; name + dw GAME1FIO ; file buffer + db 0 ; ref num +CLOSE_PB: + db 1 ; only one parm + db 0 ; the refnum +WRITE_SV: + db 4 ; parm count + db 0 ; refnum + dw IOBUFF ; data is always here + dw 512 ; 1 page worth + dw 0 ; how many actually went + +; get the save file name. If user hits the ESC key, then abort the +; save by return with the carry set. +; +GET_SNAME: + jsr CLOSE_GAME ; close the game files + jsr SWAP2INFOW ; goto information window +GTSN0: + DLINE NAMEQ ; ask about name + lda SNAMEL ; is there a name yet? + beq GTSN00 ; nope + DLINE SAVENAME,SNAMEL ; show current name of file +GTSN00: + lda #0 ; clear line count + sta CLOSE_PB+CL_REFNUM ; clear this too + ldx SNAMEL ; get length + stx CHRCNT ; okay + ldy SNAMEL ; point to copy + dey ; one less +GCOPY: + lda SNAMEL,X ; get char + sta LBUFF,Y ; save it + dex ; point to previous one + dey ; previous pointer + bpl GCOPY ; copy until length byte +GNAME: + jsr GETKEY ; WAIT FOR A KEY + cmp #EOL ; IF [RETURN], + beq GOTNAME ; got the name + cmp #ESCAPE ; hit escape key? + sec ; just in case it does exit + bne GNM2 + jmp GNX ; all done then +GNM2: + cmp #BACKSPACE ; erasing things? + bne GNM1 ; nope + + ldx CHRCNT ; make sure there are chars there + bne GNMBP ; ayyup, do delete +GNMBAD: + jsr BEEP ; no room for delete + jmp GNAME ; okay +GNMBP: + dex ; point down one + stx CHRCNT ; count one down + lda LBUFF,X ; get char to delete + tax ; show in [X] + lda #BACKSPACE ; and doing a backspace + bne GNMSHOW ; okay, delete char on screen +GNM1: + cmp #'/' ; slash is the only good non-numeric char + beq GNMGOOD ; fine, use it + cmp #'.' ; well, maybe a . too + beq GNMGOOD ; fine, here it is + cmp #VOLCHAR ; does user want list of volumes? + bne GNM1x ; nope + + lda #0 ; clear out current name + sta CHRCNT ; okay, we did + jsr LISTVOLS ; show them + jmp GTSN0 ; start over, kind of +GNM1x: + cmp #'0' ; is it a number + bcc GNMBAD ; nope + cmp #'9'+1 ; well? + bcc GNMGOOD ; yup + cmp #'z'+1 ; make sure it is alpha numeric + bcs GNMBAD ; nope + cmp #'A' ; well? + bcc GNMBAD ; nope + cmp #'a' ; little char? + bcs GNMGOOD ; yup + cmp #'Z'+1 ; big char + bcs GNMBAD ; nope +GNMGOOD: + ldx CHRCNT ; get name index + inc CHRCNT ; point to next char + sta LBUFF,X ; save name char +GNMSHOW: + jsr CHAR ; show character + jsr DISP_LINE ; make sure it is there + jmp GNAME ; go get next char +; +; got the name, so copy it to the SAVENAME buffer +; +GOTNAME: + lda CHRCNT ; did we get any? + beq GTNMERR ; nope + lda LBUFF ; make sure first name is a directory + cmp #'/' ; is it? + beq GTNM1 ; yup, probly okay then +GTNMERR: + lda #0 ; clear CHRCNT so name doesn't get + sta CHRCNT ; output again + DLINE PREFIX_ERR ; complain and die + sec ; show bad name + bcs GNX ; all done +GTNM1: + ldx #0 ; now check to make sure there are 2 + ldy #$FE ; use this as counter +GTNMCHK: + lda LBUFF,X ; get char + inx ; next char + cmp #'/' ; prefix deliminator? + bne GTNMCHK1 ; nope + iny ; count this one + beq GTNM2 ; we have 2 of them +GTNMCHK1: + cpx CHRCNT ; at end? + beq GTNMERR ; yes, and no 2 '/'s + bne GTNMCHK ; go check next char +GTNM2: + cpx CHRCNT ; make sure there are chars after prefix + beq GTNMERR ; nope, still an error + ldx CHRCNT ; get how many characters + stx SNAMEL ; save in length byte + dex ; points one too far +GNL: + lda LBUFF,X ; get the char + sta SAVENAME,X ; save the char + dex ; point to previous one + bpl GNL ; and go get it + clc ; show did just fine +GNX: + php ; save status + lda #0 ; and clear CHRCNT + sta CHRCNT ; okay + lda #EOL ; print EOL + jsr CHAR ; okay + jsr SWAPBACK ; change back to old window + plp ; get status back + rts ; all done +; +; open up a save file, by first trying to create it. If it already exists +; then make sure the player wants to delete the file, then get rid of it. +; Finally open the file. Return with carry set if user aborts the save. +; Store the ref number into the write parm block. +; +OPEN_SAVE: + CREATE CREATE_PB ; first try to create the file + bcc OPSV_OPEN ; created just fine, so open it +; +; can't create the file, check out why +; + cmp #$47 ; this means file already there + beq OPSV1 ; nope, not that + jmp DISK_ERR ; show badness +OPSV1: + DLINE DELQ ; ask about deleting this file + jsr GETYN ; get me the yes or no + bcc OPSV_OPEN ; so then delete it if yes + rts ; nope, so just quit +OPSV_OPEN: + OPEN OPEN_SV ; open the save file + bcc OPSV_OP1 ; okey, things worked just fine + jmp DISK_ERR ; complain about error +OPSV_OP1: + lda OPEN_SV+OP_REFNUM ; get the ref number + sta WRITE_SV+WR_REFNUM ; save the ref number + sta CLOSE_PB+CL_REFNUM ; to close parm too + sta SETEOF_PB+SE_REFNUM ; for cleansing file + SET_EOF SETEOF_PB ; clear out file + bcc OPSVEX ; no problems + jsr DISK_ERR ; complain +OPSVEX: + rts ; file has been opened, return +; +; OPEN_RES - open the save file +; +OPEN_RES: + OPEN OPEN_SV ; open it up + bcc OPR1 ; okay, it worked + rts ; okay, it didn't +OPR1: + lda OPEN_SV+OP_REFNUM ; get reference number + sta READ_PB+RD_REFNUM ; save for read + sta CLOSE_PB+CL_REFNUM ; and for close + rts +; +; CLOSE_SAVE - close up the save file if it is open, and +; restore open game files +; +CLOSE_SAVE: + lda CLOSE_PB+CL_REFNUM ; check if it opened + beq CLSVX ; okay, nothing + CLOSE CLOSE_PB ; close the save file +CLSVX: +; lda #1 ; flag is true +; sta SAVEDISK ; show we have a save disk in there +; jsr SET_GAMEPRE ; go get the last one used +; jsr FETCH_FILE ; this does it + ldx GAME1NML ; get length of current name + lda GAME1NM,X ; get the number of the file + sta SAVENUM ; we need this to look for prefix + sta SAVEDISK ; show taking out save disk, not game disk + jsr DO_GAME1 ; open up GAME1 file + lda D2SEG+HI ; set DSEGS to point to #2 + sta DSEGS+HI + lda D2SEG+LO + sta DSEGS+LO + ldx GAME2NML ; get length of current name + lda GAME2NM,X ; get the number of the file + sta SAVENUM ; we need this to look for prefix + jsr OPEN_GAME2 ; open up GAME2 file + ldy #0 ; open up GAME2 file, just for kicks + sty SAVEDISK ; show we have a save disk in there + sty CLOSE_PB+CL_REFNUM ; clear close + iny ; set for true + sty SCRIPT ; allow scripting again + rts ; DONE +; +; CLOSE_GAME - close the current game file(s) +; and set DSEGS to point to preload so it will reopen them +; +CLOSE_GAME: + lda #0 ; show no files are open + sta CLOSE_PB+CL_REFNUM ; 0 closes all files + sta GAME1REF ; zero out two game files too + sta GAME2REF ; and here is number 2 + sta PF_FID ; clear this too + CLOSE CLOSE_PB ; now all are closed + rts +; +; Get answer to Yes/No question. Return with C==0 for yes, and C==1 +; for a no. RETURN == Yes, ESCAPE == NO +; +GETYN: + jsr GETKEY ; get the key strok + cmp #'y' ; IF REPLY IS "Y" + beq ALLSET ; ACCEPT RESPONSES + cmp #'Y' ; get both y's + beq ALLSET + cmp #EOL ; EOL IS ALSO ACCEPTABLE + beq ALLSET + cmp #'n' ; IF REPLY IS "N" + beq NOTSAT ; return with carry set + cmp #'N' ; check both n's + beq NOTSAT + cmp #ESCAPE ; check for ESC key too + beq NOTSAT ; which means no + jsr BEEP ; ELSE BEEP + jmp GETYN ; INSIST ON Y OR N +NOTSAT: + DLINE NO ; PRINT "NO"/EOL + sec ; set the carry + rts ; and show it +ALLSET: + DLINE YES ; Print "YES"/EOL + clc ; clear the carry + rts +GETRET: + DLINE RETQ ; ask for return +GETRETL: + jsr GETKEY ; get a key + cmp #EOL ; return key? + bne GETRETL ; nope + jsr CHAR ; show the + rts + +; --------- +; SAVE GAME +; --------- +ZSAVE: + lda #'N' + ldx NARGS + beq OLDSAV ; NORMAL, COMPLETE SAVE + lda #'P' +OLDSAV: + sta TYPE + jsr SAVRES ; set up screen + jsr GET_SNAME ; get the name of the save file + bcs ZSEXIT ; don't wanna after all + jsr OPEN_SAVE ; open the file + bcs ZSEXIT ; don't really care to +; +; SAVE GAME PARAMETERS IN [BUFSAV] +; + lda ZBEGIN+ZID ; MOVE GAME ID + sta BUFSAV+0 ; INTO 1ST 2 BYTES + lda ZBEGIN+ZID+1 ; OF THE A + sta BUFSAV+1 + lda ZSP+LO ; MOVE [ZSP] + sta BUFSAV+2 + lda ZSP+HI + sta BUFSAV+3 + lda OLDZSP+LO + sta BUFSAV+4 + lda OLDZSP+HI ; MOVE [OLDZSP] + sta BUFSAV+5 + ldx #2 ; MOVE CONTENTS OF [ZPC] +ZSL1: lda ZPC,X ; TO BYTES 7-9 + sta BUFSAV+6,X ; OF [BUFSAV] + dex + bpl ZSL1 + lda TYPE + sta BUFSAV+9 ; NORMAL OR PARTIAL + cmp #'P' + bne ZSNONM ; NORMAL SAVE SO NO name TO SAVE + + lda ARG3+LO ; set up FPC to get save name + sta FPCL ; lo part is okay + lda ARG3+HI ; get page + jsr SETPC ; get memory addr + sta FPCH ; page number + sty FPCBNK ; and bank + jsr FETCHB ; get count + sta I ; and save it + jsr NEXTFPC ; point to next byte + lda #0 ; set up data offset + sta J ; did it +ZSL3: + jsr FETCHB ; get data byte + ldy J ; get offset + sta BUFSAV+10,Y ; save into buffer + jsr NEXTFPC ; point to next byte + inc J ; next byte + dec I ; count it + bne ZSL3 ; loop again +ZSNONM: +; +; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK +; + lda #MAIN ; in the main bank + sta DSKBNK ; thank you + lda #>LOCALS ; start at locals + sta DBUFF+HI ; POINT TO THE PAGE + jsr PUTDSK ; AND WRITE IT OUT + bcc ZSOK ; IF SUCCEEDED, WRITE STACK +ZSBAD: + jsr DISK_ERR ; print error message + SET_EOF SETEOF_PB ; clear out file, maybe +ZSEXIT: + jsr CLOSE_SAVE ; else get game file back + jmp RET0 ; AND FAIL +; +; IF A PARTIAL SAVE WRITE FROM ARG1 FOR ARG2 BYTES TO DISK +; (ROUNDED TO PGS) SKIPPING ZSTACK WRITE +; +ZSOK: + lda TYPE + cmp #'P' + bne ZSALL + lda ARG1+HI ; find where to start & how far to go + jsr SETPC ; get page in memory + pha ; save for minute + and #$01 ; check for odd page + beq ZSP1 ; nope, don't make one more page + inc ARG2+HI ; go get one more page +ZSP1: + pla ; get it back + and #$FE ; must be on block boundary + sta DBUFF+HI ; this is page + sty DSKBNK ; which bank + ldx ARG2+HI ; get MSB of count + lda ARG1+LO ; get lo offset + clc ; add + adc ARG2+LO ; lo count + bcc ZSPINC ; no extra page + inx ; wrapped extra page +ZSPINC: + bne SAVE2DISK ; go copy it now +; +; WRITE CONTENTS OF Z-STACK TO DISK +; +ZSALL: + lda #>ZSTKBL ; point to 1st page + sta DBUFF+HI + jsr PUTDSK ; write them, first one + bcs ZSBAD + jsr PUTDSK ; write them, second one + bcs ZSBAD +; +; WRITE ENTIRE GAME PRELOAD TO DISK +; + lda #>ZBEGIN ; POINT TO 1ST PAGE + sta DBUFF+HI ; OF PRELOAD + ldx ZBEGIN+ZPURBT ; GET # IMPURE PAGES +SAVE2DISK: + inx ; use for counting + stx I+LO + lsr I+LO ; /2 for 512byte pages + bcc ZSL2 ; no wrapping + inc I+LO ; wrapped once +ZSL2: + jsr PUTDSK ; this does the write + bcs ZSBAD + dec I+LO ; count one page + bne ZSL2 ; not done yet + + jsr CLOSE_SAVE ; prompt for game file + + IF CHECKSUM == 1 + lda CKS_COUNT + jsr HEXNUM + lda CKSB + jsr HEXNUM + lda #EOL + jsr CHAR + ENDIF + + lda #1 ; set to mark + ldx #0 + jmp PUTBYT ; SUCCESS + +; ------------ +; RESTORE GAME +; ------------ + +ZREST: + lda #'N' + ldx NARGS + beq OLDRES ; NORMAL, COMPLETE RESTORE + lda #'P' ; partial restore +OLDRES: + sta TYPE ; save which kind of restore +; +; SAVE LOCALS IN CASE OF ERROR +; + ldx #31 +LOCSAV: lda LOCALS,X ; COPY ALL LOCALS + sta LOCAL_SV,X ; to a save spot + dex + bpl LOCSAV + + jsr GET_SNAME ; get the name of the file + bcs ZRQUIT ; okay, don't do it + jsr OPEN_RES ; open the restore file + bcs ZRBAD ; can't do it + + lda TYPE ; PARTIAL SAVE DIFFERS STARTING HERE + cmp #'P' + bne ZRNRML + jmp ZPARTR ; just a partial restore +ZRNRML: + lda #MAIN + sta DSKBNK ; SET TO WRITE TO MAIN BANK + lda #>LOCALS + sta DBUFF+HI + lda #2 ; must read in two pages + sta L+LO + jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + bcs ZRBAD ; didn't work! + lda READ_PB+RD_LENGTH+HI ; see how much was read in + cmp #2 ; were 2 blocks read in? + bne ZRQUIT ; wrong kind of file for complete save + + lda BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID + cmp ZBEGIN+ZID ; MATCH THE CURRENT ID? + bne ZRQUIT ; WRONG DISK IF NOT + + lda BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE? + cmp ZBEGIN+ZID+1 + beq ZROK ; CONTINUE IF BOTH BYTES MATCH + bne ZRQUIT ; skip disk error message +; +; HANDLE RESTORE ERROR +; +ZRBAD: + jsr DISK_ERR ; print error message +ZRQUIT: + ldx #31 ; RESTORE ALL SAVED LOCALS +ZRL2: lda LOCAL_SV,X + sta LOCALS,X + dex + bpl ZRL2 +BADRES: + jsr CLOSE_SAVE ; PROMPT FOR GAME DISK + jmp RET0 ; PREDICATE FAILS +; +; CONTINUE RESTORE +; +ZROK: + lda ZBEGIN+ZFLAGS ; save both flag bytes + sta J+LO + lda ZBEGIN+ZFLAGS+1 + sta J+HI + + lda #>ZSTKBL ; retrieve old contents of + sta DBUFF+HI ; z-stack + lda #4 ; do 4 pages + sta L+LO ; tell GETRES how many pages + jsr GETRES ; get 4 pages of z-stack + bcc ZROKL1 + jmp DISK_FATAL ; if here, mix of good & bad so die +ZROKL1: + lda #>ZBEGIN ; get where we are + sta DBUFF+HI + lda ZBEGIN+ZPURBT ; get # pages to load + sta I+LO + inc I+LO ; go get last page if possible +LREST0: + lda I+LO ; how many pages left + beq LRESTj ; finis + sec ; doing subtract + sbc #4 ; doing it 4 blocks at a time + bcc LREST1 ; <4 blocks left so deal with it special + sta I+LO ; save remenants +LREST: + lda #4 ; assume at least 4 pages + sta L+LO ; this tells GETRES how many to read in + jsr GETRES ; fetch the remainder + bcc LREST0 + jmp DISK_FATAL +LREST1: + lda I+LO ; get how many left + sta L+LO ; and show it to GETRES + and #$1 ; is it odd? + beq LREST2 ; nope + inc L+LO ; read one more +LREST2: + jsr GETRES ; and finish it up +; +; RESTORE THE STATE OF THE SAVED GAME +; +LRESTj: + lda J+LO ; RESTORE THE STATE + sta ZBEGIN+ZFLAGS ; OF THE FLAG WORD + lda J+HI + sta ZBEGIN+ZFLAGS+1 + + lda BUFSAV+2 ; RESTORE THE [ZSP] + sta ZSP+LO + lda BUFSAV+3 + sta ZSP+HI + lda BUFSAV+4 + sta OLDZSP+LO + lda BUFSAV+5 ; AND THE [OLDZSP] + sta OLDZSP+HI + + ldx #2 ; RESTORE THE [ZPC] +ZRL4: lda BUFSAV+6,X + sta ZPC,X + dex + bpl ZRL4 + +ZROUT: jsr CLOSE_SAVE ; PROMPT FOR GAME DISK + jsr VLDZPC ; MAKE VALID (MUST DO AFTER GET DISK) + + IF CHECKSUM == 1 + lda CKS_COUNT + jsr HEXNUM + lda CKSB + jsr HEXNUM + lda #EOL + jsr CHAR + ENDIF + + lda #2 ; SET TO + ldx #0 + jmp PUTBYT ; SUCCESS + + + ; DO PARTIAL RESTORE GETTING 1ST PAGE + ; AND LAST PAGE BYTE ALIGNMENT CORRECT + ; WRITE LOCALS TO IOBUFF JUST TO LOOK AT NAME +ZPARTR: + lda #MAIN + sta DSKBNK + lda #>IOBUFF ; DON'T READ TO LOCALS YET (X) + sta DBUFF+HI + lda #2 ; just one block please + sta L+LO + jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + bcc ZRN2 ; worked just fine +ZPBAD: + jmp BADRES ; names don't match, die +ZRN2: + lda ARG3+LO ; set up FPC to get save name + sta FPCL ; lo part is okay + lda ARG3+HI ; get page + jsr SETPC ; get memory addr + sta FPCH ; page number + sty FPCBNK ; and bank + jsr FETCHB ; get count + sta I ; and save it + jsr NEXTFPC ; point to next byte + lda #IOBUFF ; get 1st page + sta DBUFF+HI ; getres should keep in iobuff + sta ZPARTMOD+2 ; and show where to get it from + lda #$01 ; is it odd + bit SPCH ; get page destination + beq ZPARTx ; nope + inc ZPARTMOD+2 ; then get second page worth +ZPARTx: + lda #2 ; just do one block + sta L+LO + jsr GETRES + bcc ZPART0 + jmp DISK_FATAL ; ALL MESSED UP, JUST QUIT +ZPART0: + ldy ARG1+LO ; START BYTE FIRST PAGE +ZPARTMOD: + lda IOBUFF,Y ; this gets modified with good page # + jsr STASHB + jsr NEXTSPC + jsr DECJ + bcs ZPART1 ; CARRY CLEAR IF $FFFF RESULT + jmp ZROUT +ZPART1: + inc ARG1+LO + bne ZPART0 + lda #>IOBUFF+1 ; this is second page address + cmp ZPARTMOD+2 ; is it second one already? + beq POK ; yes, so read in a new block + sta ZPARTMOD+2 ; then update it + bne ZPART0 ; and do it again +; +; THE OLD SAVE & RESTORE STILL HAVE OPCODES +; SO JUST PUT IN A PLACE FOR THEM HERE FOR NOW +; +OSAVE: +OREST: RTS + +ZISAVE: +ZIREST: JMP RET0 ; NOT IMPLEMENTED ON APPLE + END diff --git a/apple/yzip/rel.13/zstring.asm b/apple/yzip/rel.13/zstring.asm new file mode 100644 index 0000000..0d23bdb --- /dev/null +++ b/apple/yzip/rel.13/zstring.asm @@ -0,0 +1,443 @@ + PAGE + STTL "--- Z-STRING HANDLERS ---" + +; ----------------------- +; POINT MPC TO ZSTRING IN [I], using SOFF +; ----------------------- + +SETSTR: + lda I+LO + sta MPCL ; save in lo part + lda I+HI + sta MPCM ; middle part + lda #0 ; clear hi part + sta MPCH ; okay, we did + asl MPCL ; *2 + rol MPCM + rol MPCH + asl MPCL ; *4 + rol MPCM + rol MPCH +; +; now add the offset +; + lda MPCL ; carry clear from above + adc SOFFL ; add lo part of offset + sta MPCL ; save + lda MPCM + adc SOFFM + sta MPCM + lda MPCH + adc SOFFH + sta MPCH + jmp VLDMPC ; make MPCPNT to it + + +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 #$FA ; what to add to get offset into char table +TOASC: + sta TOASCM+1 ; modify code + lda ZCHAR ; use char as offset + clc ; make char be an index +TOASCM: adc #6 ; we just did + tax ; now use as index + lda CHARSET,X ; go get that char in charset zero +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 #20 ; skip into Charset 1 part of table + bne TOASC ; fix just like the others +; +; PRINT FROM CHARSET #2 +; +SET2: + lda ZCHAR ; retrieve the z-char + cmp #6 ; is it a special ascii char? + beq DIRECT ; yes, so do it special + lda #46 ; nothing special, just get offset + bne TOASC ; and jump +; +; 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 + bne 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 +; +; set up FPC to point to FWORDS table +; + ldx FWORDS+ABANK + stx FPCBNK + ldx FWORDS+HI + stx FPCH + ldx FWORDS+LO + stx FPCL + jsr ADDFPC ; add offset of the F-word + jsr FETCHB ; and get MSB of F-word + sta I+HI ; and save it + jsr NEXTFPC ; and point to LSB + jsr FETCHB ; and get it + sta I+LO ; and save it +; +; 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 SETFWD ; 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 + JSR VLDMPC + JMP PZTOP ; CONTINUE INNOCENTLY + + +; ---------------------- +; RETURN CURRENT CHARSET +; ---------------------- + +GETSET: LDA TSET + BPL GS + LDA PSET + RTS +GS: LDY #$FF + STY TSET + RTS + + +; ------------------------- +; POINT [I] AT FWORD STRING +; ------------------------- + +SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS + ASL A + STA MPCL + LDA I+HI + ROL A + STA MPCM + LDA #0 + ROL A + STA MPCH + JMP VLDMPC + + +; ----------------- +; 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 #5 ; FILL OUTPUT BUFFER + ldx #8 ; WITH PAD CHARS ($05) +CZSL: + sta OUT,X + dex + bpl CZSL + + lda #9 ; 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 CSHIP1 ; a pad char +NEXTZ: + jsr FINDCHAR ; find out where it tis + beq CSHIP ; no shift for charset zero + clc ; else do a temp-shift + adc #3 ; 4 = charset 1, 5 = charset 2 + jsr CSTASH ; save the char in outbuf + cmp #5 ; charset 2? + bne CSHIP ; nope + cpx #6 ; ascii escape? + bne CSHIP ; nope +; +; Handle special Ascii escape sequence +; + txa ; get ASCII alert char (#6) + jsr CSTASH ; shove it away +; +; do 1st half of "direct" +; + lda ZCHAR ; re-fetch char + lsr A ; get upper 2 bits in lower 2 bits + lsr A + lsr A + lsr A + lsr A + jsr CSTASH +; +; SEND 2ND HALF OF "DIRECT" +; + lda ZCHAR ; get char yet again + and #%00011111 ; and get lower 5 bits + tax ; this is where it is expected +; +; SHIP Z-CHAR TO OUTPUT BUFFER +; +CSHIP: + txa ; get char +CSHIP1: + jsr CSTASH ; put char away + bne CONTOP ; do again +; +; FINDCHAR - look through the charset table for the character. If found, +; figger out which shift it is. If not found, return charset 2, +; character #6. +; Enter: +; [A] = Char we are looking for +; Returns: +; [A] = Charset (0-2) +; [X] = Character # (6-31) +; +FINDCHAR: + ldx #0 ; start at first char, first set + ldy #78 ; there are 78 characters +FNDCL: + cmp CHARSET,X ; found it? + beq FNDCLX ; yes + inx ; next char + dey ; count char + bne FNDCL ; go check next char +; +; not found in table, use ASCII escape sequence +; + lda #2 ; escape sequence is char set 2 + ldx #6 ; character 6 + rts ; and done +FNDCLX: + txa ; put here for compares/action + ldy #0 ; this is char set 0 + ldx #$FA ; what to "subtract" to get +6 + cmp #26 ; how we doin'? + bcc FNDCHX ; all done + iny ; char set 1 + ldx #20 ; char set 1 offset + cmp #52 ; well? + bcc FNDCHX ; must be char set 1 + ldx #46 ; for char set 2 setting up + iny ; must be char set 2 then +FNDCHX: + stx FNDCHM+1 ; what to subtract to get offset + sec ; doing subtract +FNDCHM: sbc #6 ; make good offset + tax ; put here for return + tya ; and here to set flag + rts +; +; CSTASH - put the char in OUT. If we run out of room don't return, just +; jump to ZCRUSH as final destination +; [A] - char to be put away +; +CSTASH: + ldy CONOUT ; fetch output index + sta OUT,Y ; send the shift char + inc CONOUT ; update index + dec CONCNT ; and char count + bne CSTX ; plenty more room + pla ; get rid of return spot + pla ; fine + jmp ZCRUSH ; if out of room, crush 'em! +CSTX: + rts +; ---------------------- +; CRUSH Z-CHARS IN [OUT], mushing them into small 5 bit pieces +; ---------------------- +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 + STA OUT+2 ; MOVE CRUSHED Z-WORD + STX OUT+3 ; INTO PLACE + LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) + ASL A ; SHIFT BITS + ASL A + ASL A + ASL A + ROL OUT+6 ; ALONG WITH 7TH Z-CHAR + ASL A + ROL OUT+6 + ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR + STA OUT+5 ; SAVE HERE + LDA OUT+6 ; GRAB 7TH Z-CHAR + ORA #%10000000 ; SET HIGH BIT + STA OUT+4 ; MOVE CRUSHED Z-WORD INTO PLACE + RTS + + END + diff --git a/apple/yzip/rel.15/apple.equ b/apple/yzip/rel.15/apple.equ new file mode 100644 index 0000000..fb84363 --- /dev/null +++ b/apple/yzip/rel.15/apple.equ @@ -0,0 +1,298 @@ + STTL "--- APPLE ][ HARDWARE STUFF ---" + PAGE +; ------------------- +; APPLE II MEMORY MAP +; ------------------- +AUX EQU 1 ; offset to Auxillary mem switches +MAIN EQU 0 ; for main memory switches + +; +; some hardware spots +; +SCREEN EQU $2000 ; START OF Double HiRes SCREEN RAM + +PRGLBL EQU $BF00 ; ProDOS Globals page in main mem +PR_BITMAP EQU $BF58 ; ProDOS system bitmap +KVERSION EQU $BFFF ; ProDOS version (== $FF if InfoDOS) +INFODOS_ID EQU $FF + +IOADDR EQU $C000 ; start of I/O registers +PROADR EQU $D000 ; start of ProDOS + +LBUFF EQU $0200 ; LINE INPUT BUFFER +PIC1BUF EQU $0300-141 ; we can use line buffer for one picture buffer +SCRBUFF EQU LBUFF+$80 ; screen line buffer +BORG EQU $2000 ; ORIGIN OF .SYSTEM CODE +; +; some page 3 storage relocated stuff +; +PAGE3STUFF EQU $300 +MOUSER EQU PAGE3STUFF ; this is where mouse subroutine goes +COLORS EQU MOUSER+$12 +XPOSTBL EQU COLORS+$40 + +SV_PCL EQU $400 ; for scrolling data +SV_PCH EQU $600 + +IOBUFF EQU $0800 ; 1Kb DATA BUFFER BUFFER + +PAGING_MEM EQU IOBUFF+$400 ; Paging table stuff +NEXTPNT EQU PAGING_MEM +PREVPNT EQU NEXTPNT+$40 +VPAGEH EQU PREVPNT+$40 +VPAGEL EQU VPAGEH+$40 +PAGELEN EQU $200 ; length of paged read + +ZSTKBL EQU PAGING_MEM+$100 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) +ZSTKTL EQU ZSTKBL+$100 ; TOP, LO +ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI +ZSTKTH EQU ZSTKBL+$300 ; TOP, HI +; +; now define some file i/o buffers and such +; +GAME1FIO EQU ZSTKBL+$400 ; Game file I/O buffer +GAME2FIO EQU GAME1FIO+$400 ; Second game file i/o buffer +SEGTBL EQU GAME2FIO+$400 ; segment table for multi disks +PIC2BUF EQU SEGTBL+($400-140) ; picture buffer is 140 bytes long +TCHARTBL EQU SEGTBL+$400 ; 208 bytes for (possible) terminating +COPY_LINE EQU TCHARTBL+$50 ; copy line in screen memory +CPY_MOD1_SRC equ COPY_LINE+$2C ; special self-modifying places +CPY_MOD1_DST equ CPY_MOD1_SRC+3 +CPY_MOD2_SRC equ COPY_LINE+$50 +CPY_MOD2_DST equ CPY_MOD2_SRC+3 + +DSKSEG EQU TCHARTBL+$D0 ; spot to stash pointers for disk segments +D1SEG EQU DSKSEG ; where in SEGTBL for Disk 1 +D2SEG EQU D1SEG+2 +D3SEG EQU D2SEG+2 +D4SEG EQU D3SEG+2 +D5SEG EQU D4SEG+2 +D6SEG EQU D5SEG+2 +D7SEG EQU D6SEG+2 +D8SEG EQU D7SEG+2 +LOCAL_SV EQU TCHARTBL+$E0 ; to save locals before restore +LOCALS EQU TCHARTBL+$100 ; LOCAL VARIABLE STORAGE (30 BYTES) +BUFSAV EQU LOCALS+$20 ; TEMP SPACE FOR SAVE/RESTORE (80 BYTES) +SCR_LINE EQU LOCALS+$100 ; place to build displayed line +CHARSET EQU SCR_LINE+140 ; spot for charset to go +; +; now for some interpreter data +; +INTR_BEGIN EQU $4000 ; START OF Interpreter CODE in main +INTR_SIZE EQU (43*512) ; size of interpreter + +ZBEGIN EQU (INTR_BEGIN+INTR_SIZE) ; start of Z code +MMSIZE EQU PRGLBL-INTR_BEGIN ; free memory in main bank +Z1SIZE EQU >(PRGLBL-ZBEGIN) ; size of preload, part 1 +; +; this is in Bank 2, Main mem +; +; +; Picture directory goes in Bank 2, Aux mem +; +PIC_DIR EQU $D000 ; picture local directory +GBL_DIR EQU $DC00 ; global directory +; +; some special markers if we are using InfoDOS +; +SP_BANK EQU MAIN +SP_START EQU $D000 ; start of special area +SP_SIZE EQU ((($FE->SP_START)*256)/512) ; how many pages +;SP_SIZE EQU (((>SCREEN->SP_START)*256)/512) ; how many pages + +PB_BANK EQU AUX ; paging buffers in which bank +PBEGIN EQU $0800 ; start of paging buffers +NUMBUFS EQU >(SCREEN-PBEGIN) ; how many 256k paging buffers +;NUMBUFS EQU >($100-PBEGIN) ; how many 256k paging buffers + +P2PAGE EQU >(PRGLBL-ZBEGIN) ; first page of zcode in aux bank +Z2BEGIN EQU $4000 ; start of part 2 in aux mem + ; just after the dhires screen +Z2PAGE EQU >Z2BEGIN ; get me just the page address +Z2SIZE EQU >(PRGLBL-Z2BEGIN) ; size of preload, part 2 +P3PAGE EQU Z1SIZE+Z2SIZE ; first page in aux mem part 3 +Z3BEGIN EQU $D000 ; start of 3 part in aux mem +Z3PAGE EQU >Z3BEGIN ; get me page number too +Z3SIZE EQU <($FE-Z3PAGE) ; size of part 3, in pages + +; +; other numba's +; +PGBEGIN EQU (P3PAGE+Z3SIZE) ; first paged page +PRESIZE EQU (Z1SIZE+Z2SIZE+Z3SIZE) ; size of preload, # pages +SCRSZE EQU INTR_BEGIN-SCREEN ; size of Double HiRes screen (8k, each bank) +RAMDSK EQU (119*512) ; size of RAM disk in aux mem +RAMSAVE EQU $B500 ; save this much to cover HiRes screen in + ; aux and the rest of the preload, up to + ; PRGLBL ($bf00) +FREERAM EQU RAMDSK-RAMSAVE ; size of Free RAM after 'saving' + ; special AUX memory +DSKSZE EQU (512*273) ; size of ProDOS data disk file + +; --------- +; CONSTANTS +; --------- + +IIeID EQU 2 ; Apple ][e Yzip +IIcID EQU 9 ; ][c Yzip +IIgsID EQU 10 ; ][gs Yzip + +P3BANK EQU $FF ; show upper aux mem +LO EQU 0 +HI EQU 1 +ABANK EQU 2 ; for address variables + +OFF EQU 0 ; for toggling soft-switches +ON EQU 1 + +RETRY_COUNT EQU 3 ; how many retries before message + +TAB EQU $09 ; Tab char +EOS EQU $0B ; End of Sentence +EOL EQU $0D ; EOL CHAR +LF EQU $0A ; LINE FEED +SPACE EQU $20 ; SPACE CHAR +BACKSPACE EQU $08 ; BACKSPACE CHAR +ESCAPE EQU $1B ; ESCAPE Key +VOLCHAR EQU '?' ; Key to hit for ONLINE command +; +; Screen Defs +; +MAXWIDTH EQU 140 ; 560 / 4 = max "pixels" +REAL_MAXW EQU MAXWIDTH*4 +MAXHEIGHT EQU 192 ; 192 screen lines +FONT_W EQU 2 ; font width (for game, anyway) +FONT_H EQU 9 ; font height +MFONT_W EQU 3 ; mono spaced font width, to game +MONOFONT_W EQU MFONT_W*4 ; how wide the mono font really is + +SPACE_WIDTH EQU 8 ; default space width +BLINK_RATE EQU 3 ; tenths of seconds between blinks + +OUTER_DELAY EQU $1C ; outside delay loop counter +INNER_DELAY EQU 3 ; inner delay loop + +GS_OUTER_DELAY EQU $72 ; ][gs outside counter +GS_INNER_DELAY EQU 2 ; ][gs inside counter + +; ---------------------- +; BOOT ZERO PAGE EQUATES +; ---------------------- + +BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS +BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT + +START_NAME EQU $280 ; name upon boot is stored here +; ---------------- +; HARDWARE EQUATES +; ---------------- + +KBD EQU $C000 ; KEY STROBE +STORE80 EQU $C000 ; video aux mem switch +RDBNK EQU $C002 ; READ MAIN MEMORY (+MAIN, +AUX) +WRTBNK EQU $C004 ; WRITE MAIN 48K OF MEMORY (+MAIN, +AUX) +ALTZP EQU $C008 ; R/W MAIN (C009 = AUX) >MEM +COL80SW EQU $C00C ; 80 Column switch +ANYKEY EQU $C010 ; ANY KEY DOWN FLAG +VERTBLNK EQU $C019 ; Vertical Blanking Flag +IIGSVID EQU $C029 ; GS MEGA ][ video register +SPKR EQU $C030 ; SPEAKER FLAG (MAKE A NOISE) +IIGSSHD EQU $C035 ; ][GS shadowing reg +TEXTSW EQU $C050 ; Graphics Switch +MIXEDSW EQU $C052 ; Mixed Text/Graphics +PAGE2SW EQU $C054 ; Page select +HIRESSW EQU $C056 ; Select HiRes +DHIRESW EQU $C05E ; Double HiRes switch (backwards: +0 on +1 off) +IOUDIS EQU $C07E ; Double HiRes Switch enabler (same backass way) +BNK2SET EQU $C083 ;READ/READ READ RAM WRITE RAM BANK 2 +BNK1SET EQU $C08B ;READ/READ READ RAM WRITE RAM BANK 1 +RDROM EQU $C082 ; READ READ ROM NO WRITE +RDBNK1 EQU $C088 ; READ ram, bank 1 +RDBNK2 EQU $C080 ; Read ram, bank 2 + +; ----------------- +; MONITOR VARIABLES +; ----------------- + +CSW EQU $36 ; CHARACTER OUTPUT VECTOR (for scripting) +APKEY1 EQU $C061 ; open apple key flag +APKEY2 EQU $C062 ; closed apple key flag + +CURSW EQU 2 ; width of cursor +CURSH EQU 4 ; height of cursor +; ----------- +; MOUSE STUFF +; ----------- +MTABLE EQU $C412 ; Mouse ROM table +MSVECTOR EQU MOUSER+16 ; where vector is stored +MSMOVEF EQU MSVECTOR+2 ; Mouse moved flag +MSBTNF EQU MSMOVEF+1 ; Mouse button flag +; +; MOUSE screen holes +; +CLMPMINL EQU $478 ; lo part of clamping min +CLMPMINH EQU $578 ; hi part of " " +CLMPMAXL EQU $4F8 ; lo part of clamping max +CLMPMAXH EQU $5F8 ; hi part of " " +MOUSEXL EQU $478 ; lo part of mouse X +MOUSEXH EQU $578 ; hi part of mouse X +MOUSEYL EQU $4F8 ; lo part of mouse Y +MOUSEYH EQU $5F8 ; hi part of mouse Y +MOUSEST EQU $778 ; status byte +; +; some mouse constants +; +SGL_CLK EQU $81 ; single click char +DBL_CLK EQU $82 ; double click char +CLK_CNT EQU 6 ; counts between single and double click +; Subroutine offsets +SETM EQU 0 +SERVEM EQU 1 +READM EQU 2 +CLEARM EQU 3 +POSM EQU 4 +CLAMPM EQU 5 +HOMEM EQU 6 +INITM EQU 7 + +; -------------- +; PRODOS GLOBALS +; -------------- +PRODATE EQU $BF90 ; date and +PROTIME EQU $BF92 ; time +MACHID EQU $BF98 ; machine id + +; ---------------- +; MONITOR ROUTINES +; ---------------- +MPREAD EQU $FB1E ; Read for joystick control +MBASCAL EQU $FC22 ; CALC LINE BASE ADDRESS +MBELL EQU $FF3A ; MAKE A NOISE +RESET_VECTOR EQU $FFFC ; force warm reboot +MCLEOL EQU $FC9C ; CLEAR TO END OF LINE +MCLEOS EQU $FC42 ; CLEAR TO END OF SCREEN +MHOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR +MCOUT EQU $FDED ; CHAR OUTPUT +MCOUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN +MRDKEY EQU $FD0C ; READ KEY +MGETLN1 EQU $FD6F ; GET LINE +MWAIT EQU $FCA8 ; WASTE SO MUCH TIME +; +; Some /RAM spots +; +RAMVEC EQU $BF26 ; /RAM drive vector +OLDVEC EQU $77E ; spot to save the drive vector +UNSVEC EQU $BF16 ; "Uninstalled Device" vector +DEVCNT EQU $BF31 ; Device count +DEVNUM EQU $BF32 ; Device list + +; +; machine info spots +; +MACHID1 EQU $FBB3 ; first part +MACHID2 EQU $FBC0 ; second part +MACHCHK EQU $FE1F ; differentiate between ][e and gs + ; do sec, then jsr, and if still set, = ][e + END + + diff --git a/apple/yzip/rel.15/boot.asm b/apple/yzip/rel.15/boot.asm new file mode 100644 index 0000000..f105000 --- /dev/null +++ b/apple/yzip/rel.15/boot.asm @@ -0,0 +1,380 @@ + TITLE "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + + INCLUDE ZIP.EQU + INCLUDE ZERO.EQU + INCLUDE PRODOS.EQU + INCLUDE APPLE.EQU + INCLUDE MACROS.ASM + + STTL "--- APPLE ProDOS BOOT CODE ---" + PAGE + +CHZ EQU $24 ; CURSOR HORIZONTAL +EHZ EQU $57B ; CURSOR HORIZONTAL +CVT EQU $25 ; CURSOR VERTICAL + +; +; my own little error checking macro +; +ERRVAL .VAR 0 +; +; this macros checks for carry being set (ProDOS error) and if it is +; loads an error code in x and jumps to the error handler +ERRCHK .MACRO +ERRVAL .VAR ERRVAL+1 + bcc BOOT| + ldy #ERRVAL + jmp BOOT_ERROR +BOOT|: + .MACEND + + ORG BORG + jmp BOOT_BEGIN ; just jump to beginning +PROGNAME: + BLKB 9,0 ; 8 bytes for name + 1 for ending zero +BOOT_BEGIN: + lda RDROM ; swap in rom + sta TEXTSW+ON ; turn on text + sta COL80SW+OFF ; turn on 80 column + +; +; make sure we are on a ][c, or ][e+ +; + jsr MACHINE ; check it out, returns if good + lda ARG2+LO ; check machine + cmp #IIgsID ; 2gs? + bne ZBOOTGS ; nope + lda IIGSVID ; get current video setting + and #$1F ; turn off upper 3 bits + sta IIGSVID ; make sure double hires works + lda IIGSSHD ; get shadowing reg + and #$A0 ; turn on shadowing everywhere + sta IIGSSHD ; okay +ZBOOTGS: + jsr FIXRAM ; check and clear RAM disk + jsr DO_PREFIX ; go set my current prefix + + jsr MHOME ; clear and home + lda #9 ; CENTER DISPLAY + sta CVT + lda #8 + sta CHZ + sta EHZ + jsr MBASCAL ; move cursor there! + DLINE STRYM +; +; move down to lower left and print out version number +; + lda #21 + sta CVT + lda #1 + sta CHZ ; move to 1,20 + sta EHZ + jsr MBASCAL ; move cursor there! + DLINE VERMSG ; show me the version + lda #VERSID/10 ; get version + ora #$B0 ; make normal char for ][ + jsr MCOUT + lda #VERSID.MOD.10 + ora #$B0 ; make normal char for ][ + jsr MCOUT + + lda #$FF ; init invflg to normal + sta INVFLG ; okay + + lda #0 ; zero out bit map + ldx #$17 ; 17 bytes in ProDOS system bitmap +CLRPRD: + sta PR_BITMAP,X ; and zero out the memory + dex + bpl CLRPRD ; and zero entire bitmap + + lda #$C0 ; start out the bitmap with c0 at start + sta PR_BITMAP + lda #$01 ; and a 1 at the end + sta PR_BITMAP+$17 ; thankx +; +; now we need to load in the interpreter +; + OPEN INTR_OPEN ; open up interpreter file + ERRCHK + + lda INTR_OPEN+OP_REFNUM ; get refnum for intr file + sta READ_BLOCK+RD_REFNUM ; and save for read + sta CLOSE_BLOCK+CL_REFNUM ; close up interpreter file + + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now +RDINTR: + READ READ_BLOCK ; read in interpreter + bcc RDINTR1 ; it worked fine + dec RETRIES ; try again + bpl RDINTR ; fine + ERRCHK ; then just die +RDINTR1: + CLOSE CLOSE_BLOCK ; done with interpreter +; +; now read in first part of preload +; + ldx #0 ; start at first letter +MVPRE: + lda PROGNAME,X ; get letter + beq MVPREX ; all done + sta PRE_NAME,X ; save letter + inx ; next letter + bne MVPRE ; do gen +MVPREX: +; +; now add on ".d1" suffix for the preload +; + lda #'.' ; get '.' + sta PRE_NAME,X ; save it + inx ; next char + lda #'D' ; 'D' char + sta PRE_NAME,X ; save it + inx ; next char + lda #'1' ; preload is .1 + sta PRE_NAME,X ; saved + inx ; count the .1 + stx PRELOAD_NAME ; save length of name + + OPEN PRELOAD_OPEN ; so now open preload file + ERRCHK + + lda PRELOAD_OPEN+OP_REFNUM ; get refnum + sta READ_BLOCK+RD_REFNUM ; save refnum for read + sta PSEEK+SM_REFNUM ; and for moving around +; +; first, get the segment table +; + lda #>IOBUFF ; just read in size + sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + lda #4 ; read in first 1 Kb + sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + lda #0 ; get size in words + sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + + READ READ_BLOCK ; and read first block + ERRCHK +; +; now copy segtable to low mem +; + lda #>IOBUFF + sta J+HI + lda #(SEGTBL-2) + sta K+HI + lda #<(SEGTBL-2) + sta K+LO + + lda IOBUFF+1 ; get LSB + asl A ; *2, to pick up the carry + lda IOBUFF ; get how many words + rol A ; *2 for number of bytes + sta PSEEK+SM_FPOS+HI ; set page number + tax ; make it a counter + ldy #2 ; start at second byte, after length +CPSEGT: + lda (J),y ; get byte + sta (K),y ; save byte + iny ; next byte + bne CPSEGT ; go do it + inc J+HI + inc K+HI + ldy #0 ; restart at beginning of block + dex ; count page + bpl CPSEGT ; next page +; +; now, seek to page following seg table +; + inc PSEEK+SM_FPOS+HI ; next page + lda PSEEK+SM_FPOS+HI ; make sure it is an even 512 page + and #$01 ; is it odd? + beq BTSK0 ; nope, so we be okay + inc PSEEK+SM_FPOS+HI ; next page + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now +BTSK0: + SET_MARK PSEEK ; and point to beginning of game data + + lda #>ZBEGIN ; begining of game code + sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + lda #(Z1SIZE&$FE) ; get size + sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + lda #0 ; get size in words + sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + READ READ_BLOCK ; and read in part 1 of preload + bcc BTSK00 ; just fine + dec RETRIES ; try again + bpl BTSK0 ; fine + ERRCHK ; then just die +BTSK00: + lda #4 ; 4 pages per read + sta READ_BLOCK+RD_BUFFLEN+HI ; and lots + lda #>IOBUFF ; read into my io buffer + sta READ_BLOCK+RD_BUFFER+HI ; hi part of address + + IF Z1SIZE & 1 ; if odd, do something special + READ READ_BLOCK + ldy #0 ; copy second page +C2LOOP: + lda IOBUFF,Y + sta ZBEGIN+(Z1SIZE*$100)-$100,Y + iny + bne C2LOOP + lda #(>Z2BEGIN-1) ; don't need first block + sta MODOP+2 + bne RD10 ; skip that first read + ENDIF +AUXRDL: + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now +AUXRDL0: + READ READ_BLOCK ; and do the read + bcc RD10 + cmp #$4C ; this just means EOF already + beq BT12 ; otherwise, blech + dec RETRIES ; try again + bpl AUXRDL0 ; fine + ERRCHK ; then just die +RD10: + lda #>IOBUFF ; read into my io buffer + sta CLOOP+2 ; start at IOBUFF + lda #4 ; 4 copies + sta L ; okay +RD11: + ldy #0 ; start at zero, of course + lda MODOP+2 ; check where we are reading too + beq BT12 ; wrapped, so we had better be done + cmp #>PRGLBL ; done with aux mem, part 1? + bcc LOOPST ; nope + bne RD12 ; no need to change + lda #Z3PAGE ; restart at top of memory + sta MODOP+2 ; and do some self modifying code +RD12: + sta ALTZP+AUX ; turn on alt ZP + lda BNK2SET ; write to upper mem + lda BNK2SET ; write to upper mem +LOOPST: + sta WRTBNK+AUX ; always aux mem +CLOOP: + lda IOBUFF,Y ; get char +MODOP: sta Z2BEGIN,Y ; save + iny ; point to next one + bne CLOOP ; get next one + + lda RDROM ; swap back rom, just in case + lda RDROM ; swap back rom, just in case + sta ALTZP+MAIN ; and back to main page + sta WRTBNK+MAIN ; read into main bank + + inc MODOP+2 ; point to next page + inc CLOOP+2 ; point to next page + dec L ; next page + bne RD11 ; and get it + + jmp AUXRDL ; get next 1k +BT12: + lda READ_BLOCK+RD_REFNUM ; get refnum for + sta CLOSE_BLOCK+CL_REFNUM ; closing the file + CLOSE CLOSE_BLOCK ; okay, closed +; +; relocate the Zero Page routines +; + ldx #RLCLEN ; length of routine +RLOC: + lda FETCHBx,X ; get byte + sta ZERO_FB,X ; save byte + dex ; get next one + bpl RLOC ; thank you +; +; and now for the copying screen line sub +; + ldx #CPYLEN +CPYCPLP: + lda CPYx,X + sta COPY_LINE,X + dex + bpl CPYCPLP +; +; now relocate page 3 stuff +; + ldx #PAGE3RELL+1 ; get length of page 3 stuff +MSRCL: + lda PAGE3REL-1,X ; get byte + sta PAGE3STUFF-1,X ; save byte + dex ; count byte + bne MSRCL ; get next? + + jsr ZBOOT ; set up ZIP stuff + + JMP INTR_BEGIN ; jump to the interpreter + + INCLUDE ZBOOT.ASM ; ZBOOT subroutine + INCLUDE BREL.ASM ; relocated subroutines + INCLUDE BSUBS.ASM ; subs for e to use + + PAGE + STTL "--- BOOT DATA STRUCTURES ---" +INTR_OPEN: + DB 3 ; 3 parameters + DW INTR_NAME ; name of file + DW GAME1FIO ; file data buffer + DS 1 ; refnum goes here +CLOSE_BLOCK: + DB 1 ; 1 parameter + DS 2 ; room for ref num +PSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +PRELOAD_OPEN: + DB 3 + DW PRELOAD_NAME + DW GAME1FIO ; close interpreter first! + DS 1 ; refnum here +; +; start with interpreter data +; +READ_BLOCK: + DB 4 ; 4 parms + DB 0 ; refnum + DW INTR_BEGIN ; where to start the interpreter + DW INTR_SIZE ; and how big could it be + DW 0 ; actual length of interpreter +INTR_NAME: + DB INAME_LEN ; length of name +I_NAME: + DB "INFOCOM" ; interpreter name +INAME_LEN EQU $-I_NAME + +PRELOAD_NAME: + DB 0 ; length of name +PRE_NAME: + DS 20 ; spot for preload name +PRELEN EQU $-PRE_NAME + +DH_SAVE: ; to actual 'write' the data + DB 4 ; 4 parms for write + DB 0 ; refnum goes here + DW 0 ; just 'copy' junk + DW RAMSAVE ; to preserve this much mem in AUX + DW 0 ; how much is done + +STRYM: DB "The story is loading ..." +STRYML EQU $-STRYM +MMSG: DB EOL,"Enter the letter of the pointing",EOL + DB "device you will be using:",EOL + DB "J)oystick M)ouse N)either",EOL,EOL +MMSGL EQU $-MMSG +MSLT: DB EOL,"Enter the slot number in which the",EOL + db "mouse card is installed >" +MSLTL EQU $-MSLT +MSLTBAD: DB EOL,"Slot number must be between",EOL + db "ONE and SEVEN! Try again!",EOL +MSLTBADL EQU $-MSLTBAD +VERMSG: db EOL,"Version: " +VERMSGL equ $-VERMSG + END + diff --git a/apple/yzip/rel.15/boot.bin b/apple/yzip/rel.15/boot.bin new file mode 100644 index 0000000..85cf59a Binary files /dev/null and b/apple/yzip/rel.15/boot.bin differ diff --git a/apple/yzip/rel.15/boot.lst b/apple/yzip/rel.15/boot.lst new file mode 100644 index 0000000..3935d3a --- /dev/null +++ b/apple/yzip/rel.15/boot.lst @@ -0,0 +1,2730 @@ + Tue Jun 13 1989 10:05 Page 1 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT DATA STRUCTURES ---" + + + + + 2500 A.D. 6502 Macro Assembler - Version 4.01a + ------------------------------------------------ + + Input Filename : BOOT.asm + Output Filename : BOOT.obj + + + 1 0000 TITLE "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + 2 + 3 0000 INCLUDE ZIP.EQU + 4 0000 STTL "--- YZIP EQUATES ---" + 5 PAGE + Tue Jun 13 1989 10:05 Page 2 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- YZIP EQUATES ---" + + 6 + 7 000F VERSID EQU 15 ; VERSION OF INTERPRETER + 8 ; See file "versions" for complete descriptions + 9 + 10 00FF TRUE EQU $FF + 11 0000 FALSE EQU 0 + 12 + 13 ; --------------------- + 14 ; Segment table equates + 15 ; --------------------- + 16 0000 SGTDISKS EQU 0 ; number of disks + 17 0002 SGTPAD EQU SGTDISKS+2 ; just some extra room + 18 0012 SGTCHKS1 EQU SGTPAD+16 ; Checksum for disk 1 (PRELOAD) + 19 0014 SGTPICOF1 EQU SGTCHKS1+2 ; N/A + 20 0016 SGTSEG1 EQU SGTPICOF1+2 ; # of segments + 21 0018 SGTGPOF1 EQU SGTSEG1+2 ; Global Picture Directory + 22 001A SGTTBLS EQU SGTGPOF1+2 ; Start of table preload (should be 0) + 23 001C SGTTBLE EQU SGTTBLS+2 ; Last page of table preload + 24 001E SGTTBLX EQU SGTTBLE+2 ; N/A + 25 0020 SGTFUNS EQU SGTTBLX+2 ; First page of function preload + 26 0022 SGTFUNE EQU SGTFUNS+2 ; End page of function preload + 27 0024 SGTFUNX EQU SGTFUNE+2 ; N/A + 28 0026 SGTDSK EQU SGTFUNX+2 ; Actual start of disk segment tables + 29 + 30 0000 SGTCHKS EQU 0 ; check sum for file + 31 0002 SGTPICOF EQU 2 ; picture data offset + 32 0004 SGTNSEG EQU 4 ; # of segments in this list + 33 0006 SGTGPOF EQU 6 ; Global Directory Offset + 34 0008 SGTSEG EQU 8 ; start of segments + 35 ; --------------------- + 36 ; Z-CODE HEADER OFFSETS + 37 ; --------------------- + 38 + 39 0000 ZVERS EQU 0 ; VERSION BYTE + 40 0001 ZMODE EQU 1 ; MODE SELECT BYTE + 41 0002 ZID EQU 2 ; GAME ID WORD + 42 0004 ZENDLD EQU 4 ; # OF QUADWORDS ON SIDE 1 OF DISK + 43 0006 ZGO EQU 6 ; EXECUTION ADDRESS + 44 0008 ZVOCAB EQU 8 ; START OF VOCABULARY TABLE + 45 000A ZOBJEC EQU 10 ; START OF OBJECT TABLE + 46 000C ZGLOBAL EQU 12 ; START OF GLOBAL VARIABLE TABLE + 47 000E ZPURBT EQU 14 ; START OF "PURE" Z-CODE + 48 0010 ZFLAGS EQU 16 ; FLAG WORD + 49 0012 ZSERIA EQU 18 ; 3-WORD SERIAL NUMBER + 50 0018 ZFWORD EQU 24 ; START OF FWORDS TABLE + 51 001A ZLENTH EQU 26 ; LENGTH OF Z-PROGRAM IN WORDS + 52 001C ZCHKSM EQU 28 ; Z-CODE CHECKSUM WORD + 53 001E ZINTWD EQU 30 ; INTERPRETER ID WORD (SUPPLIED BY EZIP) + 54 0020 ZSCRWD EQU 32 ; SCREEN PARAMETER WORD ( " " " ) + 55 0022 ZHWRD EQU 34 ; DISPLAY WIDTH IN PIXELS + 56 0024 ZVWRD EQU 36 ; DISPLAY HEIGHT IN PIXELS + 57 0026 ZFWRD EQU 38 ; FONT HEIGHT, FONT WIDTH + 58 0028 ZFOFF EQU 40 ; FUNCTION OFFSET + 59 002A ZSOFF EQU 42 ; STRING OFFSET + 60 002C ZCLRWD EQU 44 ; FORGROUND COLOR, BACKGROUND COLOR + 61 002E ZTCHAR EQU 46 ; POINTER TO TBL OF TERMINATING CHARS + 62 0030 ZTWIDTH EQU 48 ; Running counter for table output char width + Tue Jun 13 1989 10:05 Page 3 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- YZIP EQUATES ---" + + 63 0032 ZCRFUNC EQU 50 ; FUNCTION FOR CARRIAGE RETURNS + 64 0034 ZCHRSET EQU 52 ; POINTER TO CHAR SET TBL + 65 0036 ZEXTAB EQU 54 ; Points to extension table, if needed + 66 ; + 67 ; Extension table offsets + 68 ; + 69 0000 ZEXTLEN EQU 0 ; Length of extension table + 70 0002 ZMSLOCX EQU 2 ; x location of mouse + 71 0004 ZMSLOCY EQU 4 ; y location of mouse + 72 0006 ZMSETBL EQU 6 ; MOUSE TBL CHANGE WORD + 73 0008 ZMSEDIR EQU 8 ; DIRECTION MENU + 74 000A ZMSEINV EQU 10 ; INVENTORY MENU + 75 000C ZMSEVRB EQU 12 ; FREQUENT VERB MENU + 76 000E ZMSEWRD EQU 14 ; FREQUENT WORD MENU + 77 0010 ZBUTTN EQU 16 ; BUTTON HANDLER + 78 0012 ZJOYST EQU 18 ; JOYSTICK HANDLER + 79 0014 ZBSTAT EQU 20 ; BUTTON STATUS + 80 0016 ZJSTAT EQU 22 ; JOYSTICK STATUS + 81 ; + 82 ; ZFLAGS values + 83 ; + 84 0001 FSCRI EQU $01 ; scripting? + 85 0002 FMONO EQU $02 ; mono spaced font? + 86 0004 FSTAT EQU $04 ; status line refresh? + 87 0008 FDISP EQU $08 ; uses DISPLAY operations? + 88 0010 FUNDO EQU $10 ; uses UNDO? + 89 0020 FMOUS EQU $20 ; uses mouse? + 90 0040 FCOLO EQU $40 ; uses color? + 91 0080 FMENU EQU $80 ; uses menus? + 92 ;--------------- + 93 ; Picture data + 94 ;--------------- + 95 ;=== DATA HEADER === + 96 0000 PHFID EQU 0 ; File ID + 97 0001 PHFLG EQU PHFID+1 ; Flags + 98 0002 PHHUFF EQU PHFLG+1 ; Pointer to Huffman data + 99 0004 PHNLD EQU PHHUFF+2 ; # entries in local directory + 100 0006 PHNGD EQU PHNLD+2 ; # entries in global directory + 101 0008 PHDSIZE EQU PHNGD+2 ; Local directory entry size + 102 000A PHCHKS EQU PHDSIZE+2 ; File Checksum + 103 000C PHFVERS EQU PHCHKS+2 ; File Version (N/A) + 104 000E PHEXTRA EQU PHFVERS+2 ; Extra room for getting fatter + 105 0010 PHSIZE EQU 16 ; 16 bytes is header size + 106 ;=== DATA HEADER FLAGS === + 107 0001 PHFGD EQU $1 ; data has global directory + 108 0002 PHFHUFF EQU $2 ; Huffman encoded pictures + 109 0004 PHFHUFF1 EQU $4 ; All pictures use same Huff tree + 110 0008 PHFPAL EQU $8 ; No pallette information + 111 ;=== LOCAL DIRECTORY === + 112 0000 PLDID EQU 0 ; Picture ID + 113 0002 PLDWID EQU PLDID+2 ; Picture Width + 114 0003 PLDHGHT EQU PLDWID+1 ; Picture Height + 115 0004 PLDFLG EQU PLDHGHT+1 ; Flags + 116 0005 PLDPTR EQU PLDFLG+1 ; Pointer to picture data + 117 0008 PLDSIZE EQU PLDPTR+3 ; size of local directory entry + 118 + 119 0000 END + Tue Jun 13 1989 10:05 Page 4 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- YZIP EQUATES ---" + + 120 + 121 0000 INCLUDE ZERO.EQU + 122 0000 STTL "--- ZERO PAGE VARIABLES ---" + 123 PAGE + Tue Jun 13 1989 10:05 Page 5 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 124 + 125 0000 SCRCX EQU 0 ; CURSOR HORIZONTAL + 126 0001 SCRCY EQU SCRCX+1 ; CURSOR VERTICAL + 127 0002 SCRBTM EQU SCRCY+1 ; first line outside current window + 128 0003 MAXLINES EQU SCRBTM+1 ; maximum number of lines in window + 129 0004 LEFTMRG EQU MAXLINES+1 ; left edge + left margin in current window + 130 0005 WINDOW EQU LEFTMRG+1 ; (WORD) address of current window structure + 131 0007 LINE_X EQU WINDOW+2 ; (WORD) width of line counter + 132 0009 CC_OFF EQU LINE_X+2 ; save offset for char drawing + 133 000A CLSLEFT EQU CC_OFF+1 ; screen limits for CLS code + 134 000B CLSTOP EQU CLSLEFT+1 ; top of screen + 135 000C CLSWIDTH EQU CLSTOP+1 ; # of columns + 136 000D CLSHEIGHT EQU CLSWIDTH+1 ; # of lines + 137 ; + 138 ; some variables for all the screen positioning code + 139 ; + 140 000E NY_DATA EQU CLSHEIGHT+1 ; place for GET/PUT_NYBBLE to use + 141 000F CH_OFFSET EQU NY_DATA+1 ; offset into char data table + 142 0010 DATALOOP EQU CH_OFFSET+1 ; loop counter for byte works + 143 0011 BITOFF EQU DATALOOP+1 ; bit offset into screen byte + 144 0012 CH_DATA EQU BITOFF+1 ; actual char data being worked on + 145 0013 SCR_DATA EQU CH_DATA+1 ; screen byte being worked on + 146 0014 SH_LOOP EQU SCR_DATA+1 ; loop counter for bit shifting + 147 0015 SCROLLY EQU SH_LOOP+1 ; save spot for y pos when scrolling + 148 0016 RETRIES EQU SCROLLY+1 ; (BYTE) Machine ID + 149 0017 CHRMAX EQU RETRIES+1 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD + 150 0018 SCLLINES EQU CHRMAX+1 ; (BYTE) how many lines to scroll + 151 0019 FMTTBL EQU SCLLINES+1 ; (BYTE) flag to show formatted table output + 152 001A STMASK EQU FMTTBL+1 ; (BYTE) Mask to use on first byte of CLS + 153 001B ENDMASK EQU STMASK+1 ; (BYTE) Mask to use on last byte of CLS + 154 001C CHPTR EQU ENDMASK+1 ; (WORD) pointer to char data + 155 001C SCOFF EQU CHPTR ;(BYTE) Offset used by scroll + 156 001D SCLDIR EQU CHPTR+1 ;(BYTE) Direction of scroll - >0 up, <0 down + 157 001E DSEGS EQU CHPTR+2 ; (WORD) Pointer to current disk's segments + 158 ;WIDE_FLAG EQU SCOFF+1 ; (BYTE) <> 0 if 16 bytes in char data + 159 ;DSEGS EQU WIDE_FLAG+1 ; (WORD) Pointer to current disk's segments + 160 0020 LASTWV EQU DSEGS+2 ; last of the WINDOW variables + 161 + 162 0050 ZEROPG EQU $50 ; FIRST FREE Z-PAGE LOCATION + 163 ; + 164 ; these are first, cuz ZBOOT inits them so we don't want to clear them + 165 ; at ZBEGIN warm start + 166 ; + 167 0050 GLOBAL EQU ZEROPG ; (Relative Addr.) GLOBAL VARIABLE POINTER + 168 0052 VOCAB EQU GLOBAL+2 ; (ADDRESS) Vocab table pointer + 169 0055 FWORDS EQU VOCAB+3 ; (ADDRESS) F-WORDS TABLE POINTER + 170 0058 MOUSEF EQU FWORDS+3 ; (BYTE) ==-1/1 if we have mouse/joystick + 171 0059 INFODOS EQU MOUSEF+1 ; (WORD) if <>0, then pointer to D2SEG + 172 005B FUNOFF EQU INFODOS+2 ; (ADDRESS) Function Offset (ZFOFF*8) + 173 005B FOFFH EQU FUNOFF ; (BYTE) Hi part + 174 005C FOFFM EQU FUNOFF+1 ; (BYTE) Middle part + 175 005D FOFFL EQU FUNOFF+2 ; (BYTE) Lo part + 176 005E STROFF EQU FUNOFF+3 ; (ADDRESS) String Offset (ZSOFF*8) + 177 005E SOFFH EQU STROFF ; (BYTE) Hi part + 178 005F SOFFM EQU STROFF+1 ; (BYTE) Middle part + 179 0060 SOFFL EQU STROFF+2 ; (BYTE) Lo part + 180 ; + Tue Jun 13 1989 10:05 Page 6 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 181 ; Beginning of warm start zeroing + 182 ; + 183 0061 OPCODE EQU STROFF+3 ; (BYTE) CURRENT OPCODE + 184 0062 NARGS EQU OPCODE+1 ; (BYTE) # ARGUMENTS + 185 0063 ARG1 EQU OPCODE+2 ; (WORD) ARGUMENT #1 + 186 0065 ARG2 EQU OPCODE+4 ; (WORD) ARGUMENT #2 + 187 0067 ARG3 EQU OPCODE+6 ; (WORD) ARGUMENT #3 + 188 0069 ARG4 EQU OPCODE+8 ; (WORD) ARGUMENT #4 + 189 006B ARG5 EQU OPCODE+10 ; (WORD) + 190 006D ARG6 EQU OPCODE+12 ; (WORD) + 191 006F ARG7 EQU OPCODE+14 ; (WORD) + 192 0071 ARG8 EQU OPCODE+16 ; (WORD) + 193 0073 ABYTE EQU OPCODE+18 ; (BYTE) X-OP ARGUMENT BYTE + 194 0074 BBYTE EQU OPCODE+19 ; (BYTE) XCALL ARG BYTE (EZIP) + 195 0075 ADEX EQU OPCODE+20 ; (BYTE) X-OP ARGUMENT INDEX + 196 0076 VALUE EQU OPCODE+21 ; (WORD) VALUE RETURN REGISTER + 197 0078 I EQU VALUE+2 ; (WORD) GEN-PURPOSE REGISTER #1 + 198 007A J EQU VALUE+4 ; (WORD) GEN-PURPOSE REGISTER #2 + 199 007C K EQU VALUE+6 ; (WORD) GEN-PURPOSE REGISTER #3 + 200 007E L EQU VALUE+8 ; (WORD) GEN-PURPOSE REGISTER #4 + 201 0080 ZPC EQU VALUE+10 ; (3 BYTES) ZIP PROGRAM COUNTER + 202 0080 ZPCL EQU ZPC ; (BYTE) <8 BITS OF [ZPC] + 203 0081 ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] + 204 0082 ZPCH EQU ZPC+2 ; (BYTE) >BIT OF [ZPC] + 205 0083 ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE + 206 0083 ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 207 0084 ZPNTH EQU ZPCPNT+1 ; (BYTE) + 208 0085 ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 209 0086 MPC EQU ZPCPNT+3 ; (3 BYTES) MEMORY PROGRAM COUNTER + 210 0086 MPCL EQU MPC ; (BYTE) <8 BITS OF [MPC] + 211 0087 MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] + 212 0088 MPCH EQU MPC+2 ; (BYTE) >BIT OF [MPC] + 213 0089 MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE + 214 0089 MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 215 008A MPNTH EQU MPCPNT+1 ; (BYTE) + 216 008B MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 217 008C FPC EQU MPCBNK+1 ; (3 Bytes) Fetch pointer + 218 008C FPCL EQU FPC ; (BYTE) Low part + 219 008D FPCH EQU FPCL+1 ; (BYTE) High Part + 220 008E FPCBNK EQU FPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 221 008F SPC EQU FPCBNK+1 ; (3 Bytes) Fetch pointer + 222 008F SPCL EQU SPC ; (BYTE) Low part + 223 0090 SPCH EQU SPCL+1 ; (BYTE) High Part + 224 0091 SPCBNK EQU SPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 225 + 226 ; Z-STRING MANIPULATION VARIABLES + 227 + 228 0092 LINLEN EQU SPCBNK+1 ; (BYTE) LENGTH OF CURRENT LINE + 229 0093 SOURCE EQU LINLEN+1 ; (BYTE) counter for read + 230 0094 WRDLEN EQU SOURCE+1 ; (BYTE) LENGTH OF CURRENT WORD + 231 0095 ESIZE EQU WRDLEN+1 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES + 232 0096 PSET EQU ESIZE+1 ; (BYTE) PERMANENT CHARSET + 233 0097 TSET EQU PSET+1 ; (BYTE) TEMPORARY CHARSET + 234 0098 ZCHAR EQU TSET+1 ; (BYTE) CURRENT Z-CHAR + 235 0099 OFFSET EQU ZCHAR+1 ; (BYTE) F-WORD TABLE OFFSET + 236 009A ZFLAG EQU OFFSET+1 ; (BYTE) Z-WORD ACCESS FLAG + 237 009B ZWORD EQU ZFLAG+1 ; (WORD) CURRENT Z-WORD + Tue Jun 13 1989 10:05 Page 7 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 238 009D CONCNT EQU ZWORD+2 ; (BYTE) Z-STRING SOURCE COUNTER + 239 009E CONIN EQU CONCNT+1 ; (BYTE) CONVERSION SOURCE INDEX + 240 009F CONOUT EQU CONIN+1 ; (BYTE) CONVERSION DEST INDEX + 241 00A0 DIRTBL EQU CONOUT+1 ; (WORD) CONTAINS TBLE TO STORE CHARS TO + 242 00A2 XSIZE EQU DIRTBL+2 ; (WORD) SCREEN WIDTH FOR TESTS + 243 00A4 RAND EQU XSIZE+2 ; (WORD) Random number offset + 244 00A6 CURWIN EQU RAND+2 ; (BYTE) WHICH WINDOW TO WRITE IN + 245 00A7 LENGTH EQU CURWIN+1 ; (WORD) CHAR POSITION ON THE SCREEN + 246 00A9 CHRCNT EQU LENGTH+2 ; (BYTE) CHAR POSITION IN [LBUFF] + 247 00AA SCRIPT EQU CHRCNT+1 ; (BYTE) SCRIPT ENABLE FLAG + 248 00AB LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER + 249 00AC IOCHAR EQU LINCNT+1 ; (BYTE) CHARACTER BUFFER + 250 00AD COLORP EQU IOCHAR+1 ; (WORD) Pointer to current background color + 251 00AF ZSP EQU COLORP+2 ; (WORD) Z Stack + 252 00B1 SCREENF EQU ZSP+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT + 253 00B2 TABLEF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT + 254 00B3 VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH + 255 00B6 DBUFF EQU VOCEND+3 ; (WORD) RAM PG TO ACCESS (LSB = 0) + 256 00B8 DSKBNK EQU DBUFF+2 ; (BYTE) MAIN/AUX bank + 257 00B9 ALLFLG EQU DSKBNK+1 ; (BYTE) IF =1 ALL FCN KEYS (>127) ARE TCHARS + 258 00BA UNDFLG EQU ALLFLG+1 ; (BYTE) Underlining flag + 259 00BB INVFLG EQU UNDFLG+1 ; (BYTE) Inverse flag + 260 00BC MEMPAGE EQU INVFLG+1 ; (BYTE) Save spot for XPAGING stuff + 261 00BD CPY_COUNT EQU MEMPAGE+1 ; (BYTE) Number of bytes for copy line + 262 00BE TBLHEIGHT EQU CPY_COUNT+1 ;(BYTE) Number of lines in printing table + 263 00BF TBLWIDTH EQU TBLHEIGHT+1 ;(BYTE) Number of bytes per line + 264 00C0 TBLCNT EQU TBLWIDTH+1 ;(BYTE) Counter for table printing + 265 00C1 FONTFLG EQU TBLCNT+1 ;(BYTE) Which font (!=0 is width) + 266 00C2 TBLPUR EQU FONTFLG+1 ;(BYTE) first pure table page + 267 00C3 FUNPRE EQU TBLPUR+1 ;(BYTE) first preloaded function page + 268 00C4 FUNPUR EQU FUNPRE+1 ;(BYTE) first pure function page + 269 00C5 FUNPGE EQU FUNPUR+1 ;(BYTE) -number to get function preload page + 270 00C6 DELAY_COUNTER EQU FUNPGE+1 ;(BYTE) counter for delay loop + 271 ; + 272 ; some char-to-screen variables + 273 ; + 274 00C7 CHAR_D1 EQU DELAY_COUNTER+1 ; (BYTE) character data, part 1 + 275 00C8 CHAR_D2 EQU CHAR_D1+1 ; (BYTE) char data, part 2 + 276 00C9 CW EQU CHAR_D2+1 ; (BYTE) width of the character + 277 00CA CLKCTR EQU CW+1 ; (BYTE) counter for mouse clicking + 278 00CB MSX EQU CLKCTR+1 ; (BYTE) mouse cursor X + 279 00CC MSY EQU MSX+1 ; (BYTE) mouse cursor Y + 280 00CD CURRENT EQU MSY+1 ; (BYTE) current paging bufer + 281 ;CURSOR_OFF EQU CURRENT+1 ; (BYTE) ==1 if "don't show the blinking cursor" + 282 00CE MSTBL EQU CURRENT+1 ; (ADDRESS) pointer to extension table + 283 00D1 LASTZP EQU MSTBL+3 ; just checking + 284 ; + 285 ; these routines are in non-swapped memory + 286 ; + 287 00D1 ZERO_FB EQU LASTZP ; put fetch byte routine in at end of ZP + 288 00DC ZERO_ZF EQU ZERO_FB+11 ; and ZPCPNT fetch after that + 289 00E5 ZERO_MF EQU ZERO_ZF+9 ; and MPCPNT fetch after that + 290 00EE SAVE_DATA EQU ZERO_MF+9 ; copy data from DBUFF to IOBUFF routine + 291 ; + 292 ; and just to check the end + 293 ; + 294 00FF ZEE_END EQU SAVE_DATA+17 ; should be == 100 + Tue Jun 13 1989 10:05 Page 8 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 295 + 296 0000 END + 297 + 298 0000 INCLUDE PRODOS.EQU + 299 0000 STTL "--- ProDOS EQUATES ---" + 300 PAGE + Tue Jun 13 1989 10:05 Page 9 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ProDOS EQUATES ---" + + 301 + 302 ; + 303 ; some parameter structures + 304 ; + 305 0000 OPEN_PARM EQU 0 + 306 0000 OP_PCOUNT EQU OPEN_PARM ; must be 3 for open + 307 0001 OP_PATHNAME EQU OP_PCOUNT+1 ; address of pathname + 308 0003 OP_FILEBUFF EQU OP_PATHNAME+2 ; address of file data buffer + 309 0005 OP_REFNUM EQU OP_FILEBUFF+2 ; file reference number + 310 0006 OPEN_PSIZE EQU OP_REFNUM+1 ; size of parameter buffer + 311 + 312 0000 READ_PARM EQU 0 ; to read things + 313 0000 RD_PCOUNT EQU READ_PARM ; param count (=4) + 314 0001 RD_REFNUM EQU RD_PCOUNT+1 ; ref num of file + 315 0002 RD_BUFFER EQU RD_REFNUM+1 ; where to + 316 0004 RD_BUFFLEN EQU RD_BUFFER+2 ; length of buffer + 317 0006 RD_LENGTH EQU RD_BUFFLEN+2 ; actual length of read + 318 0008 READ_PSIZE EQU RD_LENGTH+2 ; length of parm block + 319 + 320 0000 CLOSE_PARM EQU 0 ; for closing file + 321 0000 CL_PCOUNT EQU CLOSE_PARM ; paramter count (=1) + 322 0001 CL_REFNUM EQU CL_PCOUNT+1 ; refnum of file to be closed + 323 0002 CLOSE_PSIZE EQU CL_REFNUM+1 ; this is the size, thank you + 324 + 325 0000 WRITE_PARM EQU 0 ; to write things + 326 0000 WR_PCOUNT EQU WRITE_PARM ; parm count (= 4) + 327 0001 WR_REFNUM EQU WR_PCOUNT+1 ; file refnum + 328 0002 WR_BUFFER EQU WR_REFNUM+1 ; data buffer address + 329 0004 WR_BUFFLEN EQU WR_BUFFER+2 ; data buffer length + 330 0006 WR_LENGTH EQU WR_BUFFLEN+2 ; actual length written + 331 0008 WRITE_PSIZE EQU WR_LENGTH+2 ; length of parm block + 332 + 333 0000 SETMARK_PARM EQU 0 + 334 0000 SM_PCOUNT EQU SETMARK_PARM ; parm count (=2) + 335 0001 SM_REFNUM EQU SM_PCOUNT+1 ; file refnum + 336 0002 SM_FPOS EQU SM_REFNUM+1 ; 3 byte file pos + 337 0005 SETMARK_PSIZE EQU SM_FPOS+3 ; length of parm block + 338 + 339 0000 SETPREFIX_PARM EQU 0 + 340 0000 SP_PCOUNT EQU SETPREFIX_PARM ; parm count (=1) + 341 0001 SP_PATHNAME EQU SP_PCOUNT+1 ; pointer to path name + 342 0003 SETPREFIX_PSIZE EQU SP_PATHNAME+2 ; length of block + 343 + 344 0000 SETEOF_PARM EQU 0 + 345 0000 SE_PCOUNT EQU SETEOF_PARM ; parm count (=2) + 346 0001 SE_REFNUM EQU SE_PCOUNT+1 ; reference number + 347 0002 SE_NEWEOF EQU SE_REFNUM+1 ; new EOF position + 348 0005 SETEOF_PSIZE EQU SE_NEWEOF+3 ; length of parm block + 349 + 350 0000 END + 351 + 352 0000 INCLUDE APPLE.EQU + 353 0000 STTL "--- APPLE ][ HARDWARE STUFF ---" + 354 PAGE + Tue Jun 13 1989 10:05 Page 10 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 355 ; ------------------- + 356 ; APPLE II MEMORY MAP + 357 ; ------------------- + 358 0001 AUX EQU 1 ; offset to Auxillary mem switches + 359 0000 MAIN EQU 0 ; for main memory switches + 360 + 361 ; + 362 ; some hardware spots + 363 ; + 364 2000 SCREEN EQU $2000 ; START OF Double HiRes SCREEN RAM + 365 + 366 BF00 PRGLBL EQU $BF00 ; ProDOS Globals page in main mem + 367 BF58 PR_BITMAP EQU $BF58 ; ProDOS system bitmap + 368 BFFF KVERSION EQU $BFFF ; ProDOS version (== $FF if InfoDOS) + 369 00FF INFODOS_ID EQU $FF + 370 + 371 C000 IOADDR EQU $C000 ; start of I/O registers + 372 D000 PROADR EQU $D000 ; start of ProDOS + 373 + 374 0200 LBUFF EQU $0200 ; LINE INPUT BUFFER + 375 0273 PIC1BUF EQU $0300-141 ; we can use line buffer for one picture buffer + 376 0280 SCRBUFF EQU LBUFF+$80 ; screen line buffer + 377 2000 BORG EQU $2000 ; ORIGIN OF .SYSTEM CODE + 378 ; + 379 ; some page 3 storage relocated stuff + 380 ; + 381 0300 PAGE3STUFF EQU $300 + 382 0300 MOUSER EQU PAGE3STUFF ; this is where mouse subroutine goes + 383 0312 COLORS EQU MOUSER+$12 + 384 0352 XPOSTBL EQU COLORS+$40 + 385 + 386 0400 SV_PCL EQU $400 ; for scrolling data + 387 0600 SV_PCH EQU $600 + 388 + 389 0800 IOBUFF EQU $0800 ; 1Kb DATA BUFFER BUFFER + 390 + 391 0C00 PAGING_MEM EQU IOBUFF+$400 ; Paging table stuff + 392 0C00 NEXTPNT EQU PAGING_MEM + 393 0C40 PREVPNT EQU NEXTPNT+$40 + 394 0C80 VPAGEH EQU PREVPNT+$40 + 395 0CC0 VPAGEL EQU VPAGEH+$40 + 396 0200 PAGELEN EQU $200 ; length of paged read + 397 + 398 0D00 ZSTKBL EQU PAGING_MEM+$100 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) + 399 0E00 ZSTKTL EQU ZSTKBL+$100 ; TOP, LO + 400 0F00 ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI + 401 1000 ZSTKTH EQU ZSTKBL+$300 ; TOP, HI + 402 ; + 403 ; now define some file i/o buffers and such + 404 ; + 405 1100 GAME1FIO EQU ZSTKBL+$400 ; Game file I/O buffer + 406 1500 GAME2FIO EQU GAME1FIO+$400 ; Second game file i/o buffer + 407 1900 SEGTBL EQU GAME2FIO+$400 ; segment table for multi disks + 408 1C74 PIC2BUF EQU SEGTBL+($400-140) ; picture buffer is 140 bytes long + 409 1D00 TCHARTBL EQU SEGTBL+$400 ; 208 bytes for (possible) terminating + 410 1D50 COPY_LINE EQU TCHARTBL+$50 ; copy line in screen memory + 411 1D7C CPY_MOD1_SRC equ COPY_LINE+$2C ; special self-modifying places + Tue Jun 13 1989 10:05 Page 11 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 412 1D7F CPY_MOD1_DST equ CPY_MOD1_SRC+3 + 413 1DA0 CPY_MOD2_SRC equ COPY_LINE+$50 + 414 1DA3 CPY_MOD2_DST equ CPY_MOD2_SRC+3 + 415 + 416 1DD0 DSKSEG EQU TCHARTBL+$D0 ; spot to stash pointers for disk segments + 417 1DD0 D1SEG EQU DSKSEG ; where in SEGTBL for Disk 1 + 418 1DD2 D2SEG EQU D1SEG+2 + 419 1DD4 D3SEG EQU D2SEG+2 + 420 1DD6 D4SEG EQU D3SEG+2 + 421 1DD8 D5SEG EQU D4SEG+2 + 422 1DDA D6SEG EQU D5SEG+2 + 423 1DDC D7SEG EQU D6SEG+2 + 424 1DDE D8SEG EQU D7SEG+2 + 425 1DE0 LOCAL_SV EQU TCHARTBL+$E0 ; to save locals before restore + 426 1E00 LOCALS EQU TCHARTBL+$100 ; LOCAL VARIABLE STORAGE (30 BYTES) + 427 1E20 BUFSAV EQU LOCALS+$20 ; TEMP SPACE FOR SAVE/RESTORE (80 BYTES) + 428 1F00 SCR_LINE EQU LOCALS+$100 ; place to build displayed line + 429 1F8C CHARSET EQU SCR_LINE+140 ; spot for charset to go + 430 ; + 431 ; now for some interpreter data + 432 ; + 433 4000 INTR_BEGIN EQU $4000 ; START OF Interpreter CODE in main + 434 5600 INTR_SIZE EQU (43*512) ; size of interpreter + 435 + 436 9600 ZBEGIN EQU (INTR_BEGIN+INTR_SIZE) ; start of Z code + 437 7F00 MMSIZE EQU PRGLBL-INTR_BEGIN ; free memory in main bank + 438 0029 Z1SIZE EQU >(PRGLBL-ZBEGIN) ; size of preload, part 1 + 439 ; + 440 ; this is in Bank 2, Main mem + 441 ; + 442 ; + 443 ; Picture directory goes in Bank 2, Aux mem + 444 ; + 445 D000 PIC_DIR EQU $D000 ; picture local directory + 446 DC00 GBL_DIR EQU $DC00 ; global directory + 447 ; + 448 ; some special markers if we are using InfoDOS + 449 ; + 450 0000 SP_BANK EQU MAIN + 451 D000 SP_START EQU $D000 ; start of special area + 452 0017 SP_SIZE EQU ((($FE->SP_START)*256)/512) ; how many pages + 453 ;SP_SIZE EQU (((>SCREEN->SP_START)*256)/512) ; how many pages + 454 + 455 0001 PB_BANK EQU AUX ; paging buffers in which bank + 456 0800 PBEGIN EQU $0800 ; start of paging buffers + 457 0018 NUMBUFS EQU >(SCREEN-PBEGIN) ; how many 256k paging buffers + 458 ;NUMBUFS EQU >($100-PBEGIN) ; how many 256k paging buffers + 459 + 460 0029 P2PAGE EQU >(PRGLBL-ZBEGIN) ; first page of zcode in aux bank + 461 4000 Z2BEGIN EQU $4000 ; start of part 2 in aux mem + 462 ; just after the dhires screen + 463 0040 Z2PAGE EQU >Z2BEGIN ; get me just the page address + 464 007F Z2SIZE EQU >(PRGLBL-Z2BEGIN) ; size of preload, part 2 + 465 00A8 P3PAGE EQU Z1SIZE+Z2SIZE ; first page in aux mem part 3 + 466 D000 Z3BEGIN EQU $D000 ; start of 3 part in aux mem + 467 00D0 Z3PAGE EQU >Z3BEGIN ; get me page number too + 468 002E Z3SIZE EQU <($FE-Z3PAGE) ; size of part 3, in pages + Tue Jun 13 1989 10:05 Page 12 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 469 + 470 ; + 471 ; other numba's + 472 ; + 473 00D6 PGBEGIN EQU (P3PAGE+Z3SIZE) ; first paged page + 474 00D6 PRESIZE EQU (Z1SIZE+Z2SIZE+Z3SIZE) ; size of preload, # pages + 475 2000 SCRSZE EQU INTR_BEGIN-SCREEN ; size of Double HiRes screen (8k, each bank) + 476 EE00 RAMDSK EQU (119*512) ; size of RAM disk in aux mem + 477 B500 RAMSAVE EQU $B500 ; save this much to cover HiRes screen in + 478 ; aux and the rest of the preload, up to + 479 ; PRGLBL ($bf00) + 480 3900 FREERAM EQU RAMDSK-RAMSAVE ; size of Free RAM after 'saving' + 481 ; special AUX memory + 482 2200 DSKSZE EQU (512*273) ; size of ProDOS data disk file + 483 + 484 ; --------- + 485 ; CONSTANTS + 486 ; --------- + 487 + 488 0002 IIeID EQU 2 ; Apple ][e Yzip + 489 0009 IIcID EQU 9 ; ][c Yzip + 490 000A IIgsID EQU 10 ; ][gs Yzip + 491 + 492 00FF P3BANK EQU $FF ; show upper aux mem + 493 0000 LO EQU 0 + 494 0001 HI EQU 1 + 495 0002 ABANK EQU 2 ; for address variables + 496 + 497 0000 OFF EQU 0 ; for toggling soft-switches + 498 0001 ON EQU 1 + 499 + 500 0003 RETRY_COUNT EQU 3 ; how many retries before message + 501 + 502 0009 TAB EQU $09 ; Tab char + 503 000B EOS EQU $0B ; End of Sentence + 504 000D EOL EQU $0D ; EOL CHAR + 505 000A LF EQU $0A ; LINE FEED + 506 0020 SPACE EQU $20 ; SPACE CHAR + 507 0008 BACKSPACE EQU $08 ; BACKSPACE CHAR + 508 001B ESCAPE EQU $1B ; ESCAPE Key + 509 003F VOLCHAR EQU '?' ; Key to hit for ONLINE command + 510 ; + 511 ; Screen Defs + 512 ; + 513 008C MAXWIDTH EQU 140 ; 560 / 4 = max "pixels" + 514 0230 REAL_MAXW EQU MAXWIDTH*4 + 515 00C0 MAXHEIGHT EQU 192 ; 192 screen lines + 516 0002 FONT_W EQU 2 ; font width (for game, anyway) + 517 0009 FONT_H EQU 9 ; font height + 518 0003 MFONT_W EQU 3 ; mono spaced font width, to game + 519 000C MONOFONT_W EQU MFONT_W*4 ; how wide the mono font really is + 520 + 521 0008 SPACE_WIDTH EQU 8 ; default space width + 522 0003 BLINK_RATE EQU 3 ; tenths of seconds between blinks + 523 + 524 001C OUTER_DELAY EQU $1C ; outside delay loop counter + 525 0003 INNER_DELAY EQU 3 ; inner delay loop + Tue Jun 13 1989 10:05 Page 13 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 526 + 527 0072 GS_OUTER_DELAY EQU $72 ; ][gs outside counter + 528 0002 GS_INNER_DELAY EQU 2 ; ][gs inside counter + 529 + 530 ; ---------------------- + 531 ; BOOT ZERO PAGE EQUATES + 532 ; ---------------------- + 533 + 534 0026 BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS + 535 002B BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT + 536 + 537 0280 START_NAME EQU $280 ; name upon boot is stored here + 538 ; ---------------- + 539 ; HARDWARE EQUATES + 540 ; ---------------- + 541 + 542 C000 KBD EQU $C000 ; KEY STROBE + 543 C000 STORE80 EQU $C000 ; video aux mem switch + 544 C002 RDBNK EQU $C002 ; READ MAIN MEMORY (+MAIN, +AUX) + 545 C004 WRTBNK EQU $C004 ; WRITE MAIN 48K OF MEMORY (+MAIN, +AUX) + 546 C008 ALTZP EQU $C008 ; R/W MAIN (C009 = AUX) >MEM + 547 C00C COL80SW EQU $C00C ; 80 Column switch + 548 C010 ANYKEY EQU $C010 ; ANY KEY DOWN FLAG + 549 C019 VERTBLNK EQU $C019 ; Vertical Blanking Flag + 550 C029 IIGSVID EQU $C029 ; GS MEGA ][ video register + 551 C030 SPKR EQU $C030 ; SPEAKER FLAG (MAKE A NOISE) + 552 C035 IIGSSHD EQU $C035 ; ][GS shadowing reg + 553 C050 TEXTSW EQU $C050 ; Graphics Switch + 554 C052 MIXEDSW EQU $C052 ; Mixed Text/Graphics + 555 C054 PAGE2SW EQU $C054 ; Page select + 556 C056 HIRESSW EQU $C056 ; Select HiRes + 557 C05E DHIRESW EQU $C05E ; Double HiRes switch (backwards: +0 on +1 off) + 558 C07E IOUDIS EQU $C07E ; Double HiRes Switch enabler (same backass way) + 559 C083 BNK2SET EQU $C083 ;READ/READ READ RAM WRITE RAM BANK 2 + 560 C08B BNK1SET EQU $C08B ;READ/READ READ RAM WRITE RAM BANK 1 + 561 C082 RDROM EQU $C082 ; READ READ ROM NO WRITE + 562 C088 RDBNK1 EQU $C088 ; READ ram, bank 1 + 563 C080 RDBNK2 EQU $C080 ; Read ram, bank 2 + 564 + 565 ; ----------------- + 566 ; MONITOR VARIABLES + 567 ; ----------------- + 568 + 569 0036 CSW EQU $36 ; CHARACTER OUTPUT VECTOR (for scripting) + 570 C061 APKEY1 EQU $C061 ; open apple key flag + 571 C062 APKEY2 EQU $C062 ; closed apple key flag + 572 + 573 0002 CURSW EQU 2 ; width of cursor + 574 0004 CURSH EQU 4 ; height of cursor + 575 ; ----------- + 576 ; MOUSE STUFF + 577 ; ----------- + 578 C412 MTABLE EQU $C412 ; Mouse ROM table + 579 0310 MSVECTOR EQU MOUSER+16 ; where vector is stored + 580 0312 MSMOVEF EQU MSVECTOR+2 ; Mouse moved flag + 581 0313 MSBTNF EQU MSMOVEF+1 ; Mouse button flag + 582 ; + Tue Jun 13 1989 10:05 Page 14 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 583 ; MOUSE screen holes + 584 ; + 585 0478 CLMPMINL EQU $478 ; lo part of clamping min + 586 0578 CLMPMINH EQU $578 ; hi part of " " + 587 04F8 CLMPMAXL EQU $4F8 ; lo part of clamping max + 588 05F8 CLMPMAXH EQU $5F8 ; hi part of " " + 589 0478 MOUSEXL EQU $478 ; lo part of mouse X + 590 0578 MOUSEXH EQU $578 ; hi part of mouse X + 591 04F8 MOUSEYL EQU $4F8 ; lo part of mouse Y + 592 05F8 MOUSEYH EQU $5F8 ; hi part of mouse Y + 593 0778 MOUSEST EQU $778 ; status byte + 594 ; + 595 ; some mouse constants + 596 ; + 597 0081 SGL_CLK EQU $81 ; single click char + 598 0082 DBL_CLK EQU $82 ; double click char + 599 0006 CLK_CNT EQU 6 ; counts between single and double click + 600 ; Subroutine offsets + 601 0000 SETM EQU 0 + 602 0001 SERVEM EQU 1 + 603 0002 READM EQU 2 + 604 0003 CLEARM EQU 3 + 605 0004 POSM EQU 4 + 606 0005 CLAMPM EQU 5 + 607 0006 HOMEM EQU 6 + 608 0007 INITM EQU 7 + 609 + 610 ; -------------- + 611 ; PRODOS GLOBALS + 612 ; -------------- + 613 BF90 PRODATE EQU $BF90 ; date and + 614 BF92 PROTIME EQU $BF92 ; time + 615 BF98 MACHID EQU $BF98 ; machine id + 616 + 617 ; ---------------- + 618 ; MONITOR ROUTINES + 619 ; ---------------- + 620 FB1E MPREAD EQU $FB1E ; Read for joystick control + 621 FC22 MBASCAL EQU $FC22 ; CALC LINE BASE ADDRESS + 622 FF3A MBELL EQU $FF3A ; MAKE A NOISE + 623 FFFC RESET_VECTOR EQU $FFFC ; force warm reboot + 624 FC9C MCLEOL EQU $FC9C ; CLEAR TO END OF LINE + 625 FC42 MCLEOS EQU $FC42 ; CLEAR TO END OF SCREEN + 626 FC58 MHOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR + 627 FDED MCOUT EQU $FDED ; CHAR OUTPUT + 628 FDF0 MCOUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN + 629 FD0C MRDKEY EQU $FD0C ; READ KEY + 630 FD6F MGETLN1 EQU $FD6F ; GET LINE + 631 FCA8 MWAIT EQU $FCA8 ; WASTE SO MUCH TIME + 632 ; + 633 ; Some /RAM spots + 634 ; + 635 BF26 RAMVEC EQU $BF26 ; /RAM drive vector + 636 077E OLDVEC EQU $77E ; spot to save the drive vector + 637 BF16 UNSVEC EQU $BF16 ; "Uninstalled Device" vector + 638 BF31 DEVCNT EQU $BF31 ; Device count + 639 BF32 DEVNUM EQU $BF32 ; Device list + Tue Jun 13 1989 10:05 Page 15 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 640 + 641 ; + 642 ; machine info spots + 643 ; + 644 FBB3 MACHID1 EQU $FBB3 ; first part + 645 FBC0 MACHID2 EQU $FBC0 ; second part + 646 FE1F MACHCHK EQU $FE1F ; differentiate between ][e and gs + 647 ; do sec, then jsr, and if still set, = ][e + 648 0000 END + 649 + 650 0000 INCLUDE MACROS.ASM + 651 0000 STTL "--- MACROS ---" + 652 PAGE + Tue Jun 13 1989 10:05 Page 16 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- MACROS ---" + + 653 + 654 ; + 655 ; MACROS for Apple ][ Yzip + 656 ; + 657 DLINE: .MACRO STRING,SLEN + 658 ldx #STRING ; get other part of string + 660 IFMA 2 ; check to see if length passed in + 661 ldy SLEN ; then just fetch it + 662 ELSE + 663 ldy #STRING|L ; get length of string + 664 ENDIF + 665 jsr DLINE ; print the string + 666 .MACEND + 667 ; + 668 ; ProDOS macros + 669 ; + 670 PRODOS: .MACRO CODE, PADDR + 671 jsr $BF00 ; ProDOS handler + 672 DB CODE ; ProDOS function code + 673 DW PADDR ; Function Parameter Block address + 674 .MACEND + 675 + 676 QUIT: .MACRO PBLOCK + 677 PRODOS $65, PBLOCK + 678 .MACEND + 679 + 680 READ_BLOCK: .MACRO PBLOCK + 681 PRODOS $80, PBLOCK + 682 .MACEND + 683 + 684 WRITE_BLOCK: .MACRO PBLOCK + 685 PRODOS $81, PBLOCK + 686 .MACEND + 687 + 688 GET_TIME: .MACRO PBLOCK + 689 PRODOS $82, PBLOCK + 690 .MACEND + 691 + 692 CREATE: .MACRO PBLOCK + 693 PRODOS $C0, PBLOCK + 694 .MACEND + 695 + 696 DESTROY: .MACRO PBLOCK + 697 PRODOS $C1, PBLOCK + 698 .MACEND + 699 + 700 RENAME: .MACRO PBLOCK + 701 PRODOS $C2, PBLOCK + 702 .MACEND + 703 + 704 SET_FILE_INFO: .MACRO PBLOCK + 705 PRODOS $C3, PBLOCK + 706 .MACEND + 707 + 708 GET_FILE_INFO: .MACRO PBLOCK + 709 PRODOS $C4, PBLOCK + Tue Jun 13 1989 10:05 Page 17 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- MACROS ---" + + 710 .MACEND + 711 + 712 ONLINE: .MACRO PBLOCK + 713 PRODOS $C5, PBLOCK + 714 .MACEND + 715 + 716 SET_PREFIX: .MACRO PBLOCK + 717 PRODOS $C6, PBLOCK + 718 .MACEND + 719 + 720 GET_PREFIX: .MACRO PBLOCK + 721 PRODOS $C7, PBLOCK + 722 .MACEND + 723 + 724 OPEN: .MACRO PBLOCK + 725 PRODOS $C8, PBLOCK + 726 .MACEND + 727 + 728 NEWLINE: .MACRO PBLOCK + 729 PRODOS $C9, PBLOCK + 730 .MACEND + 731 + 732 READ: .MACRO PBLOCK + 733 PRODOS $CA, PBLOCK + 734 .MACEND + 735 + 736 WRITE: .MACRO PBLOCK + 737 PRODOS $CB, PBLOCK + 738 .MACEND + 739 + 740 CLOSE: .MACRO PBLOCK + 741 PRODOS $CC, PBLOCK + 742 .MACEND + 743 + 744 FLUSH: .MACRO PBLOCK + 745 PRODOS $CD, PBLOCK + 746 .MACEND + 747 + 748 SET_MARK: .MACRO PBLOCK + 749 PRODOS $CE, PBLOCK + 750 .MACEND + 751 + 752 GET_MARK: .MACRO PBLOCK + 753 PRODOS $CF, PBLOCK + 754 .MACEND + 755 + 756 SET_EOF: .MACRO PBLOCK + 757 PRODOS $D0, PBLOCK + 758 .MACEND + 759 + 760 SET_BUF: .MACRO PBLOCK + 761 PRODOS $D1, PBLOCK + 762 .MACEND + 763 + 764 GET_BUF: .MACRO PBLOCK + 765 PRODOS $D2, PBLOCK + 766 .MACEND + Tue Jun 13 1989 10:05 Page 18 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- MACROS ---" + + 767 + 768 0000 END + 769 + 770 + 771 0000 STTL "--- APPLE ProDOS BOOT CODE ---" + 772 PAGE + Tue Jun 13 1989 10:05 Page 19 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 773 + 774 0024 CHZ EQU $24 ; CURSOR HORIZONTAL + 775 057B EHZ EQU $57B ; CURSOR HORIZONTAL + 776 0025 CVT EQU $25 ; CURSOR VERTICAL + 777 + 778 ; + 779 ; my own little error checking macro + 780 ; + 781 0000 ERRVAL .VAR 0 + 782 ; + 783 ; this macros checks for carry being set (ProDOS error) and if it is + 784 ; loads an error code in x and jumps to the error handler + 785 ERRCHK .MACRO + 786 ERRVAL .VAR ERRVAL+1 + 787 bcc BOOT| + 788 ldy #ERRVAL + 789 jmp BOOT_ERROR + 790 BOOT|: + 791 .MACEND + 792 + 793 2000 ORG BORG + 794 2000 4C 0C 20 jmp BOOT_BEGIN ; just jump to beginning + 795 2003 PROGNAME: + 796 2003 BLKB 9,0 ; 8 bytes for name + 1 for ending zero + 797 200C BOOT_BEGIN: + 798 200C AD 82 C0 lda RDROM ; swap in rom + 799 200F 8D 51 C0 sta TEXTSW+ON ; turn on text + 800 2012 8D 0C C0 sta COL80SW+OFF ; turn on 80 column + 801 + 802 ; + 803 ; make sure we are on a ][c, or ][e+ + 804 ; + 805 2015 20 AE 26 jsr MACHINE ; check it out, returns if good + 806 2018 A5 65 lda ARG2+LO ; check machine + 807 201A C9 0A cmp #IIgsID ; 2gs? + 808 201C D0 10 bne ZBOOTGS ; nope + 809 201E AD 29 C0 lda IIGSVID ; get current video setting + 810 2021 29 1F and #$1F ; turn off upper 3 bits + 811 2023 8D 29 C0 sta IIGSVID ; make sure double hires works + 812 2026 AD 35 C0 lda IIGSSHD ; get shadowing reg + 813 2029 29 A0 and #$A0 ; turn on shadowing everywhere + 814 202B 8D 35 C0 sta IIGSSHD ; okay + 815 202E ZBOOTGS: + 816 202E 20 5C 28 jsr FIXRAM ; check and clear RAM disk + 817 2031 20 6C 29 jsr DO_PREFIX ; go set my current prefix + 818 + 819 2034 20 58 FC jsr MHOME ; clear and home + 820 2037 A9 09 lda #9 ; CENTER DISPLAY + 821 2039 85 25 sta CVT + 822 203B A9 08 lda #8 + 823 203D 85 24 sta CHZ + 824 203F 8D 7B 05 sta EHZ + 825 2042 20 22 FC jsr MBASCAL ; move cursor there! + 826 2045 DLINE STRYM + 827 2045 A2 5C ldx #STRYM ; get other part of string + 829 [01] IFMA 2 ; check to see if length passed in + Tue Jun 13 1989 10:05 Page 20 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 830 ldy M ; then just fetch it + 831 [01] ELSE + 832 2049 A0 18 ldy #STRYML ; get length of string + 833 [00] ENDIF + 834 204B 20 D5 26 jsr DLINE ; print the string + 835 204E .MACEND + 836 ; + 837 ; move down to lower left and print out version number + 838 ; + 839 204E A9 15 lda #21 + 840 2050 85 25 sta CVT + 841 2052 A9 01 lda #1 + 842 2054 85 24 sta CHZ ; move to 1,20 + 843 2056 8D 7B 05 sta EHZ + 844 2059 20 22 FC jsr MBASCAL ; move cursor there! + 845 205C DLINE VERMSG ; show me the version + 846 205C A2 42 ldx #VERMSG ; get other part of string + 848 [01] IFMA 2 ; check to see if length passed in + 849 ldy ; then just fetch it + 850 [01] ELSE + 851 2060 A0 0A ldy #VERMSGL ; get length of string + 852 [00] ENDIF + 853 2062 20 D5 26 jsr DLINE ; print the string + 854 2065 .MACEND + 855 2065 A9 01 lda #VERSID/10 ; get version + 856 2067 09 B0 ora #$B0 ; make normal char for ][ + 857 2069 20 ED FD jsr MCOUT + 858 206C A9 05 lda #VERSID.MOD.10 + 859 206E 09 B0 ora #$B0 ; make normal char for ][ + 860 2070 20 ED FD jsr MCOUT + 861 + 862 2073 A9 FF lda #$FF ; init invflg to normal + 863 2075 85 BB sta INVFLG ; okay + 864 + 865 2077 A9 00 lda #0 ; zero out bit map + 866 2079 A2 17 ldx #$17 ; 17 bytes in ProDOS system bitmap + 867 207B CLRPRD: + 868 207B 9D 58 BF sta PR_BITMAP,X ; and zero out the memory + 869 207E CA dex + 870 207F 10 FA bpl CLRPRD ; and zero entire bitmap + 871 + 872 2081 A9 C0 lda #$C0 ; start out the bitmap with c0 at start + 873 2083 8D 58 BF sta PR_BITMAP + 874 2086 A9 01 lda #$01 ; and a 1 at the end + 875 2088 8D 6F BF sta PR_BITMAP+$17 ; thankx + 876 ; + 877 ; now we need to load in the interpreter + 878 ; + 879 208B OPEN INTR_OPEN ; open up interpreter file + 880 208B PRODOS $C8, INTR_OPEN + 881 208B 20 00 BF jsr $BF00 ; ProDOS handler + 882 208E C8 DB $C8 ; ProDOS function code + 883 208F 1B2A DW INTR_OPEN ; Function Parameter Block address + 884 2091 .MACEND + 885 2091 .MACEND + 886 2091 ERRCHK + Tue Jun 13 1989 10:05 Page 21 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 887 0001 ERRVAL .VAR ERRVAL+1 + 888 2091 90 05 bcc BOOT1 + 889 2093 A0 01 ldy #ERRVAL + 890 2095 4C AB 26 jmp BOOT_ERROR + 891 2098 BOOT1: + 892 2098 .MACEND + 893 + 894 2098 AD 20 2A lda INTR_OPEN+OP_REFNUM ; get refnum for intr file + 895 209B 8D 30 2A sta READ_BLOCK+RD_REFNUM ; and save for read + 896 209E 8D 22 2A sta CLOSE_BLOCK+CL_REFNUM ; close up interpreter file + 897 + 898 20A1 A9 03 lda #RETRY_COUNT ; set retry + 899 20A3 85 16 sta RETRIES ; just use this for now + 900 20A5 RDINTR: + 901 20A5 READ READ_BLOCK ; read in interpreter + 902 20A5 PRODOS $CA, READ_BLOCK + 903 20A5 20 00 BF jsr $BF00 ; ProDOS handler + 904 20A8 CA DB $CA ; ProDOS function code + 905 20A9 2F2A DW READ_BLOCK ; Function Parameter Block address + 906 20AB .MACEND + 907 20AB .MACEND + 908 20AB 90 0B bcc RDINTR1 ; it worked fine + 909 20AD C6 16 dec RETRIES ; try again + 910 20AF 10 F4 bpl RDINTR ; fine + 911 20B1 ERRCHK ; then just die + 912 0002 ERRVAL .VAR ERRVAL+1 + 913 20B1 90 05 bcc BOOT2 + 914 20B3 A0 02 ldy #ERRVAL + 915 20B5 4C AB 26 jmp BOOT_ERROR + 916 20B8 BOOT2: + 917 20B8 .MACEND + 918 20B8 RDINTR1: + 919 20B8 CLOSE CLOSE_BLOCK ; done with interpreter + 920 20B8 PRODOS $CC, CLOSE_BLOCK + 921 20B8 20 00 BF jsr $BF00 ; ProDOS handler + 922 20BB CC DB $CC ; ProDOS function code + 923 20BC 212A DW CLOSE_BLOCK ; Function Parameter Block address + 924 20BE .MACEND + 925 20BE .MACEND + 926 ; + 927 ; now read in first part of preload + 928 ; + 929 20BE A2 00 ldx #0 ; start at first letter + 930 20C0 MVPRE: + 931 20C0 BD 03 20 lda PROGNAME,X ; get letter + 932 20C3 F0 06 beq MVPREX ; all done + 933 20C5 9D 40 2A sta PRE_NAME,X ; save letter + 934 20C8 E8 inx ; next letter + 935 20C9 D0 F5 bne MVPRE ; do gen + 936 20CB MVPREX: + 937 ; + 938 ; now add on ".d1" suffix for the preload + 939 ; + 940 20CB A9 2E lda #'.' ; get '.' + 941 20CD 9D 40 2A sta PRE_NAME,X ; save it + 942 20D0 E8 inx ; next char + 943 20D1 A9 44 lda #'D' ; 'D' char + Tue Jun 13 1989 10:05 Page 22 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 944 20D3 9D 40 2A sta PRE_NAME,X ; save it + 945 20D6 E8 inx ; next char + 946 20D7 A9 31 lda #'1' ; preload is .1 + 947 20D9 9D 40 2A sta PRE_NAME,X ; saved + 948 20DC E8 inx ; count the .1 + 949 20DD 8E 3F 2A stx PRELOAD_NAME ; save length of name + 950 + 951 20E0 OPEN PRELOAD_OPEN ; so now open preload file + 952 20E0 PRODOS $C8, PRELOAD_OPEN + 953 20E0 20 00 BF jsr $BF00 ; ProDOS handler + 954 20E3 C8 DB $C8 ; ProDOS function code + 955 20E4 292A DW PRELOAD_OPEN ; Function Parameter Block address + 956 20E6 .MACEND + 957 20E6 .MACEND + 958 20E6 ERRCHK + 959 0003 ERRVAL .VAR ERRVAL+1 + 960 20E6 90 05 bcc BOOT3 + 961 20E8 A0 03 ldy #ERRVAL + 962 20EA 4C AB 26 jmp BOOT_ERROR + 963 20ED BOOT3: + 964 20ED .MACEND + 965 + 966 20ED AD 2E 2A lda PRELOAD_OPEN+OP_REFNUM ; get refnum + 967 20F0 8D 30 2A sta READ_BLOCK+RD_REFNUM ; save refnum for read + 968 20F3 8D 25 2A sta PSEEK+SM_REFNUM ; and for moving around + 969 ; + 970 ; first, get the segment table + 971 ; + 972 20F6 A9 08 lda #>IOBUFF ; just read in size + 973 20F8 8D 32 2A sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + 974 20FB A9 04 lda #4 ; read in first 1 Kb + 975 20FD 8D 34 2A sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + 976 2100 A9 00 lda #0 ; get size in words + 977 2102 8D 33 2A sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + 978 2105 + 979 2105 READ READ_BLOCK ; and read first block + 980 2105 PRODOS $CA, READ_BLOCK + 981 2105 20 00 BF jsr $BF00 ; ProDOS handler + 982 2108 CA DB $CA ; ProDOS function code + 983 2109 2F2A DW READ_BLOCK ; Function Parameter Block address + 984 210B .MACEND + 985 210B .MACEND + 986 210B ERRCHK + 987 0004 ERRVAL .VAR ERRVAL+1 + 988 210B 90 05 bcc BOOT4 + 989 210D A0 04 ldy #ERRVAL + 990 210F 4C AB 26 jmp BOOT_ERROR + 991 2112 BOOT4: + 992 2112 .MACEND + 993 ; + 994 ; now copy segtable to low mem + 995 ; + 996 2112 A9 08 lda #>IOBUFF + 997 2114 85 7B sta J+HI + 998 2116 A9 00 lda #(SEGTBL-2) + Tue Jun 13 1989 10:05 Page 23 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1001 211C 85 7D sta K+HI + 1002 211E A9 FE lda #<(SEGTBL-2) + 1003 2120 85 7C sta K+LO + 1004 + 1005 2122 AD 01 08 lda IOBUFF+1 ; get LSB + 1006 2125 0A asl A ; *2, to pick up the carry + 1007 2126 AD 00 08 lda IOBUFF ; get how many words + 1008 2129 2A rol A ; *2 for number of bytes + 1009 212A 8D 27 2A sta PSEEK+SM_FPOS+HI ; set page number + 1010 212D AA tax ; make it a counter + 1011 212E A0 02 ldy #2 ; start at second byte, after length + 1012 2130 CPSEGT: + 1013 2130 B1 7A lda (J),y ; get byte + 1014 2132 91 7C sta (K),y ; save byte + 1015 2134 C8 iny ; next byte + 1016 2135 D0 F9 bne CPSEGT ; go do it + 1017 2137 E6 7B inc J+HI + 1018 2139 E6 7D inc K+HI + 1019 213B A0 00 ldy #0 ; restart at beginning of block + 1020 213D CA dex ; count page + 1021 213E 10 F0 bpl CPSEGT ; next page + 1022 ; + 1023 ; now, seek to page following seg table + 1024 ; + 1025 2140 EE 27 2A inc PSEEK+SM_FPOS+HI ; next page + 1026 2143 AD 27 2A lda PSEEK+SM_FPOS+HI ; make sure it is an even 512 page + 1027 2146 29 01 and #$01 ; is it odd? + 1028 2148 F0 07 beq BTSK0 ; nope, so we be okay + 1029 214A EE 27 2A inc PSEEK+SM_FPOS+HI ; next page + 1030 214D A9 03 lda #RETRY_COUNT ; set retry + 1031 214F 85 16 sta RETRIES ; just use this for now + 1032 2151 BTSK0: + 1033 2151 SET_MARK PSEEK ; and point to beginning of game data + 1034 2151 PRODOS $CE, PSEEK + 1035 2151 20 00 BF jsr $BF00 ; ProDOS handler + 1036 2154 CE DB $CE ; ProDOS function code + 1037 2155 242A DW PSEEK ; Function Parameter Block address + 1038 2157 .MACEND + 1039 2157 .MACEND + 1040 + 1041 2157 A9 96 lda #>ZBEGIN ; begining of game code + 1042 2159 8D 32 2A sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + 1043 215C A9 28 lda #(Z1SIZE&$FE) ; get size + 1044 215E 8D 34 2A sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + 1045 2161 A9 00 lda #0 ; get size in words + 1046 2163 8D 33 2A sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + 1047 2166 READ READ_BLOCK ; and read in part 1 of preload + 1048 2166 PRODOS $CA, READ_BLOCK + 1049 2166 20 00 BF jsr $BF00 ; ProDOS handler + 1050 2169 CA DB $CA ; ProDOS function code + 1051 216A 2F2A DW READ_BLOCK ; Function Parameter Block address + 1052 216C .MACEND + 1053 216C .MACEND + 1054 216C 90 0B bcc BTSK00 ; just fine + 1055 216E C6 16 dec RETRIES ; try again + 1056 2170 10 DF bpl BTSK0 ; fine + 1057 2172 ERRCHK ; then just die + Tue Jun 13 1989 10:05 Page 24 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1058 0005 ERRVAL .VAR ERRVAL+1 + 1059 2172 90 05 bcc BOOT5 + 1060 2174 A0 05 ldy #ERRVAL + 1061 2176 4C AB 26 jmp BOOT_ERROR + 1062 2179 BOOT5: + 1063 2179 .MACEND + 1064 2179 BTSK00: + 1065 2179 A9 04 lda #4 ; 4 pages per read + 1066 217B 8D 34 2A sta READ_BLOCK+RD_BUFFLEN+HI ; and lots + 1067 217E A9 08 lda #>IOBUFF ; read into my io buffer + 1068 2180 8D 32 2A sta READ_BLOCK+RD_BUFFER+HI ; hi part of address + 1069 + 1070 [01] IF Z1SIZE & 1 ; if odd, do something special + 1071 2183 READ READ_BLOCK + 1072 2183 PRODOS $CA, READ_BLOCK + 1073 2183 20 00 BF jsr $BF00 ; ProDOS handler + 1074 2186 CA DB $CA ; ProDOS function code + 1075 2187 2F2A DW READ_BLOCK ; Function Parameter Block address + 1076 2189 .MACEND + 1077 2189 .MACEND + 1078 2189 A0 00 ldy #0 ; copy second page + 1079 218B C2LOOP: + 1080 218B B9 00 08 lda IOBUFF,Y + 1081 218E 99 00 BE sta ZBEGIN+(Z1SIZE*$100)-$100,Y + 1082 2191 C8 iny + 1083 2192 D0 F7 bne C2LOOP + 1084 2194 A9 3F lda #(>Z2BEGIN-1) ; don't need first block + 1085 2196 8D E2 21 sta MODOP+2 + 1086 2199 D0 1B bne RD10 ; skip that first read + 1087 [00] ENDIF + 1088 219B AUXRDL: + 1089 219B A9 03 lda #RETRY_COUNT ; set retry + 1090 219D 85 16 sta RETRIES ; just use this for now + 1091 219F AUXRDL0: + 1092 219F READ READ_BLOCK ; and do the read + 1093 219F PRODOS $CA, READ_BLOCK + 1094 219F 20 00 BF jsr $BF00 ; ProDOS handler + 1095 21A2 CA DB $CA ; ProDOS function code + 1096 21A3 2F2A DW READ_BLOCK ; Function Parameter Block address + 1097 21A5 .MACEND + 1098 21A5 .MACEND + 1099 21A5 90 0F bcc RD10 + 1100 21A7 C9 4C cmp #$4C ; this just means EOF already + 1101 21A9 F0 54 beq BT12 ; otherwise, blech + 1102 21AB C6 16 dec RETRIES ; try again + 1103 21AD 10 F0 bpl AUXRDL0 ; fine + 1104 21AF ERRCHK ; then just die + 1105 0006 ERRVAL .VAR ERRVAL+1 + 1106 21AF 90 05 bcc BOOT6 + 1107 21B1 A0 06 ldy #ERRVAL + 1108 21B3 4C AB 26 jmp BOOT_ERROR + 1109 21B6 BOOT6: + 1110 21B6 .MACEND + 1111 21B6 RD10: + 1112 21B6 A9 08 lda #>IOBUFF ; read into my io buffer + 1113 21B8 8D DF 21 sta CLOOP+2 ; start at IOBUFF + 1114 21BB A9 04 lda #4 ; 4 copies + Tue Jun 13 1989 10:05 Page 25 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1115 21BD 85 7E sta L ; okay + 1116 21BF RD11: + 1117 21BF A0 00 ldy #0 ; start at zero, of course + 1118 21C1 AD E2 21 lda MODOP+2 ; check where we are reading too + 1119 21C4 F0 39 beq BT12 ; wrapped, so we had better be done + 1120 21C6 C9 BF cmp #>PRGLBL ; done with aux mem, part 1? + 1121 21C8 90 10 bcc LOOPST ; nope + 1122 21CA D0 05 bne RD12 ; no need to change + 1123 21CC A9 D0 lda #Z3PAGE ; restart at top of memory + 1124 21CE 8D E2 21 sta MODOP+2 ; and do some self modifying code + 1125 21D1 RD12: + 1126 21D1 8D 09 C0 sta ALTZP+AUX ; turn on alt ZP + 1127 21D4 AD 83 C0 lda BNK2SET ; write to upper mem + 1128 21D7 AD 83 C0 lda BNK2SET ; write to upper mem + 1129 21DA LOOPST: + 1130 21DA 8D 05 C0 sta WRTBNK+AUX ; always aux mem + 1131 21DD CLOOP: + 1132 21DD B9 00 08 lda IOBUFF,Y ; get char + 1133 21E0 99 00 40 MODOP: sta Z2BEGIN,Y ; save + 1134 21E3 C8 iny ; point to next one + 1135 21E4 D0 F7 bne CLOOP ; get next one + 1136 + 1137 21E6 AD 82 C0 lda RDROM ; swap back rom, just in case + 1138 21E9 AD 82 C0 lda RDROM ; swap back rom, just in case + 1139 21EC 8D 08 C0 sta ALTZP+MAIN ; and back to main page + 1140 21EF 8D 04 C0 sta WRTBNK+MAIN ; read into main bank + 1141 + 1142 21F2 EE E2 21 inc MODOP+2 ; point to next page + 1143 21F5 EE DF 21 inc CLOOP+2 ; point to next page + 1144 21F8 C6 7E dec L ; next page + 1145 21FA D0 C3 bne RD11 ; and get it + 1146 + 1147 21FC 4C 9B 21 jmp AUXRDL ; get next 1k + 1148 21FF BT12: + 1149 21FF AD 30 2A lda READ_BLOCK+RD_REFNUM ; get refnum for + 1150 2202 8D 22 2A sta CLOSE_BLOCK+CL_REFNUM ; closing the file + 1151 2205 CLOSE CLOSE_BLOCK ; okay, closed + 1152 2205 PRODOS $CC, CLOSE_BLOCK + 1153 2205 20 00 BF jsr $BF00 ; ProDOS handler + 1154 2208 CC DB $CC ; ProDOS function code + 1155 2209 212A DW CLOSE_BLOCK ; Function Parameter Block address + 1156 220B .MACEND + 1157 220B .MACEND + 1158 ; + 1159 ; relocate the Zero Page routines + 1160 ; + 1161 220B A2 2D ldx #RLCLEN ; length of routine + 1162 220D RLOC: + 1163 220D BD E2 23 lda FETCHBx,X ; get byte + 1164 2210 95 D1 sta ZERO_FB,X ; save byte + 1165 2212 CA dex ; get next one + 1166 2213 10 F8 bpl RLOC ; thank you + 1167 ; + 1168 ; and now for the copying screen line sub + 1169 ; + 1170 2215 A2 7C ldx #CPYLEN + 1171 2217 CPYCPLP: + Tue Jun 13 1989 10:05 Page 26 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1172 2217 BD 10 24 lda CPYx,X + 1173 221A 9D 50 1D sta COPY_LINE,X + 1174 221D CA dex + 1175 221E 10 F7 bpl CPYCPLP + 1176 ; + 1177 ; now relocate page 3 stuff + 1178 ; + 1179 2220 A2 DF ldx #PAGE3RELL+1 ; get length of page 3 stuff + 1180 2222 MSRCL: + 1181 2222 BD 8C 24 lda PAGE3REL-1,X ; get byte + 1182 2225 9D FF 02 sta PAGE3STUFF-1,X ; save byte + 1183 2228 CA dex ; count byte + 1184 2229 D0 F7 bne MSRCL ; get next? + 1185 + 1186 222B 20 31 22 jsr ZBOOT ; set up ZIP stuff + 1187 + 1188 222E 4C 00 40 JMP INTR_BEGIN ; jump to the interpreter + 1189 + 1190 2231 INCLUDE ZBOOT.ASM ; ZBOOT subroutine + 1191 PAGE + Tue Jun 13 1989 10:05 Page 27 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1192 2231 STTL "--- ZIP CODE BOOT PART ---" + 1193 2231 ZBOOT: + 1194 ; + 1195 ; clear out ZERO page stuff + 1196 ; + 1197 2231 A5 65 lda ARG2+LO ; get machine id! + 1198 2233 8D 1E 96 sta ZBEGIN+ZINTWD ; save before it gets zeroed + 1199 + 1200 2236 A2 1F ldx #LASTWV-1 ; start at end of first part + 1201 2238 A9 00 lda #0 ; and clear to zero + 1202 223A ZEROL: + 1203 223A 95 00 sta 0,X ; clear out zero page loc + 1204 223C CA dex ; next loc + 1205 223D 10 FB bpl ZEROL ; and do next one + 1206 + 1207 223F A2 50 ldx #ZEROPG ; now do other part + 1208 2241 ZEROL1: + 1209 2241 95 00 sta 0,X ; zero this one + 1210 2243 E8 inx ; point to next one + 1211 2244 E0 D1 cpx #LASTZP ; find the last + 1212 2246 D0 F9 bne ZEROL1 ; okay, so do it + 1213 ; + 1214 ; get game code from data and set up absolute pointers + 1215 ; + 1216 2248 AD 00 96 lda ZBEGIN+ZVERS ; IS GAME A YZIP? + 1217 224B C9 06 cmp #6 ; (X) + 1218 224D F0 07 beq YESEZ ; YES, CONTINUE + 1219 + 1220 ; *** ERROR #15 -- NOT AN EZIP GAME *** + 1221 224F A9 0F lda #15 + 1222 2251 A0 00 ldy #0 + 1223 2253 4C 94 25 jmp ZERROR + 1224 2256 YESEZ: + 1225 2256 A9 3B lda #%00111011 ; ENABLE SOUND, underline, MONOSPACING (X) + 1226 2258 8D 01 96 sta ZBEGIN+ZMODE + 1227 + 1228 225B A9 00 lda #0 ; CLEAR HIGH BYTE + 1229 225D 85 58 sta MOUSEF ; init mouse flag to no mouse + 1230 225F 8D 22 96 sta ZBEGIN+ZHWRD + 1231 2262 8D 24 96 sta ZBEGIN+ZVWRD + 1232 2265 A9 8C lda #MAXWIDTH ; SET SCREEN PARAMETERS + 1233 2267 8D 23 96 sta ZBEGIN+ZHWRD+1 + 1234 226A A9 2E lda #MAXWIDTH/3 ; number of mono spaces on a line + 1235 226C 8D 21 96 sta ZBEGIN+ZSCRWD+1 + 1236 226F A9 C0 lda #MAXHEIGHT + 1237 2271 8D 25 96 sta ZBEGIN+ZVWRD+1 + 1238 2274 A9 15 lda #MAXHEIGHT/FONT_H + 1239 2276 8D 20 96 sta ZBEGIN+ZSCRWD ; number of lines of chars + 1240 2279 A9 09 lda #FONT_H ; height of font + 1241 227B 8D 26 96 sta ZBEGIN+ZFWRD + 1242 227E A9 03 lda #3 ; width of font (2 spaces == 8 pixels) + 1243 2280 8D 27 96 sta ZBEGIN+ZFWRD+1 + 1244 2283 A9 09 lda #9 ; the color white is the foreground color + 1245 2285 8D 2D 96 sta ZBEGIN+ZCLRWD+1 ; show Z game too + 1246 2288 A9 02 lda #2 ; black is the background color + 1247 228A 8D 2C 96 sta ZBEGIN+ZCLRWD ; tell game about it + 1248 ; + Tue Jun 13 1989 10:05 Page 28 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1249 ; just move global address to zero page for quick working + 1250 ; + 1251 228D AD 0C 96 lda ZBEGIN+ZGLOBAL ; get page + 1252 2290 85 51 sta GLOBAL+HI ; save which page + 1253 2292 AD 0D 96 lda ZBEGIN+ZGLOBAL+1 ; LSB NEEDN'T CHANGE + 1254 2295 85 50 sta GLOBAL+LO ; so just store it away + 1255 ; + 1256 ; figger absolute address for the fword table + 1257 ; + 1258 2297 AD 18 96 lda ZBEGIN+ZFWORD ; get fword page number + 1259 229A 20 ED 26 jsr SETPC ; and get absolute address + 1260 229D 85 56 sta FWORDS+HI ; show high addr of table + 1261 229F 84 57 sty FWORDS+ABANK ; show which bank + 1262 22A1 AD 19 96 lda ZBEGIN+ZFWORD+1 ; LSB NEEDN'T CHANGE + 1263 22A4 85 55 sta FWORDS+LO ; so just save it + 1264 ; + 1265 ; figger absolute address for the vocab table + 1266 ; + 1267 22A6 AD 08 96 lda ZBEGIN+ZVOCAB ; get fword page number + 1268 22A9 20 ED 26 jsr SETPC ; and get absolute address + 1269 22AC 85 53 sta VOCAB+HI ; show high addr of table + 1270 22AE 84 54 sty VOCAB+ABANK ; show which bank + 1271 22B0 A9 00 lda #0 ; this is always zero (get lo part from MPCL) + 1272 22B2 85 52 sta VOCAB+LO ; so just save it + 1273 ; + 1274 ; now do somethin' with the TCHAR table (maybe, if <> 0) + 1275 ; + 1276 22B4 AD 2E 96 lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + 1277 22B7 0D 2F 96 ora ZBEGIN+ZTCHAR+1 ; is it zero though? + 1278 22BA D0 05 bne TCH1 ; no, so copy it to somewhere useful + 1279 22BC 8D 00 1D sta TCHARTBL ; not there, so zero first byte in table + 1280 22BF F0 2F beq TCHj ; jmp + 1281 22C1 TCH1: + 1282 22C1 AD 2E 96 lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + 1283 22C4 20 ED 26 jsr SETPC ; and now make absolute + 1284 22C7 85 8D sta FPCH ; Save in FPC + 1285 22C9 84 8E sty FPCBNK + 1286 22CB AD 2F 96 lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + 1287 22CE 85 8C sta FPCL ; now move pointer to fetch spot + 1288 + 1289 22D0 A9 00 lda #0 ; and set index + 1290 22D2 85 78 sta I ; thank you + 1291 22D4 TCHLP: + 1292 22D4 20 14 27 jsr FETCHB ; get the byte in [a] + 1293 22D7 A6 78 ldx I ; get offset + 1294 22D9 E6 78 inc I ; and point to next one + 1295 22DB 9D 00 1D sta TCHARTBL,X ; save in lower memory, thank you + 1296 22DE C9 00 cmp #0 ; are we done yet? + 1297 22E0 F0 0E beq TCHj ; NULL TERMINATED STRING + 1298 22E2 C9 FF cmp #$FF ; $ff means all >128 chars are terminators + 1299 22E4 D0 04 bne TCHLNEXT ; nope + 1300 22E6 A9 01 lda #1 ; yes, + 1301 22E8 85 B9 sta ALLFLG ; so set flag to say so + 1302 22EA TCHLNEXT: + 1303 22EA 20 38 27 jsr NEXTFPC ; point to next one + 1304 22ED 4C D4 22 jmp TCHLP ; and go get it + 1305 22F0 TCHj: + Tue Jun 13 1989 10:05 Page 29 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1306 22F0 20 C6 28 jsr DO_DSEGS ; set up disk segment pointers + 1307 ; + 1308 ; use mouse/joystick, see if either is connected + 1309 ; + 1310 22F3 AD 11 96 lda ZBEGIN+ZFLAGS+1 ; get game flags + 1311 22F6 29 20 and #FMOUS ; uses a mouse? + 1312 22F8 F0 4C beq ZBEND ; nope, so don't ask + 1313 22FA 20 58 FC jsr MHOME ; clear & home + 1314 22FD MSLOOP: + 1315 22FD DLINE MMSG ; ask about Mouse/Joystick/Keyboard + 1316 22FD A2 74 ldx #MMSG ; get other part of string + 1318 [01] IFMA 2 ; check to see if length passed in + 1319 ldy ; then just fetch it + 1320 [01] ELSE + 1321 2301 A0 59 ldy #MMSGL ; get length of string + 1322 [00] ENDIF + 1323 2303 20 D5 26 jsr DLINE ; print the string + 1324 2306 .MACEND + 1325 2306 A9 01 lda #1 ; move to left + 1326 2308 85 24 sta CHZ ; move to column 1 + 1327 230A 20 22 FC jsr MBASCAL ; move cursor there! + 1328 230D A9 8D lda #EOL.OR.$80 ; send out eol + 1329 230F 20 ED FD jsr MCOUT ; bye + 1330 2312 20 0C FD jsr MRDKEY ; get a key please + 1331 2315 20 ED FD jsr MCOUT ; put key out there + 1332 2318 29 7F and #$7F ; turn off hi bit + 1333 231A C9 4D cmp #'M' ; mouse? + 1334 231C F0 1A beq DO_MOUSE ; yup + 1335 231E C9 6D cmp #'m' + 1336 2320 F0 16 beq DO_MOUSE + 1337 2322 C9 4A cmp #'J' ; Joystick? + 1338 2324 F0 19 beq DO_STICK ; yup + 1339 2326 C9 6A cmp #'j' + 1340 2328 F0 15 beq DO_STICK + 1341 232A C9 4E cmp #'N' ; neither + 1342 232C F0 18 beq DO_NEITHER ; yup + 1343 232E C9 6E cmp #'n' + 1344 2330 F0 14 beq DO_NEITHER + 1345 2332 MSLOOP1: + 1346 2332 20 3A FF jsr MBELL ; complain + 1347 2335 4C FD 22 jmp MSLOOP ; and do again + 1348 2338 DO_MOUSE: + 1349 2338 20 58 27 jsr INST_MOUSE ; install mouse handlers + 1350 233B B0 F5 bcs MSLOOP1 ; problems, try again + 1351 233D 90 07 bcc ZBEND ; continue + 1352 233F DO_STICK: + 1353 233F 20 E2 27 jsr INST_STICK ; install joystick handler + 1354 2342 B0 EE bcs MSLOOP1 ; try again + 1355 2344 90 00 bcc ZBEND ; continue, please + 1356 2346 DO_NEITHER: + 1357 2346 ZBEND: + 1358 ; + 1359 ; now, set flags like I want them + 1360 2346 A9 4A lda #FMONO^FDISP^FCOLO + 1361 2348 A6 58 ldx MOUSEF ; doing mousey stuff? + 1362 234A F0 02 beq ZBEND0 ; nope + Tue Jun 13 1989 10:05 Page 30 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1363 234C 09 20 ora #FMOUS ; then turn on that bit too + 1364 234E ZBEND0: + 1365 234E 8D 11 96 sta ZBEGIN+ZFLAGS+1 ; set game flags + 1366 ; + 1367 ; + 1368 ; Multiply ZFOFF & ZSOFF * 8 to get actual offset + 1369 ; + 1370 2351 AD 28 96 lda ZBEGIN+ZFOFF ; hi part + 1371 2354 85 5C sta FOFFM ; this'll be the middle part + 1372 2356 AD 29 96 lda ZBEGIN+ZFOFF+1 ; lo part + 1373 2359 0A asl A ; *2 + 1374 235A 26 5C rol FOFFM + 1375 235C 26 5B rol FOFFH + 1376 235E 0A asl A ; *4 + 1377 235F 26 5C rol FOFFM + 1378 2361 26 5B rol FOFFH + 1379 2363 0A asl A ; *8 + 1380 2364 26 5C rol FOFFM + 1381 2366 26 5B rol FOFFH + 1382 2368 85 5D sta FOFFL ; lo part here too + 1383 ; + 1384 ; now do string offset + 1385 ; + 1386 236A AD 2A 96 lda ZBEGIN+ZSOFF ; hi part + 1387 236D 85 5F sta SOFFM ; this'll be the middle part + 1388 236F AD 2B 96 lda ZBEGIN+ZSOFF+1 ; lo part + 1389 2372 0A asl A ; *2 + 1390 2373 26 5F rol SOFFM + 1391 2375 26 5E rol SOFFH + 1392 2377 0A asl A ; *4 + 1393 2378 26 5F rol SOFFM + 1394 237A 26 5E rol SOFFH + 1395 237C 0A asl A ; *8 + 1396 237D 26 5F rol SOFFM + 1397 237F 26 5E rol SOFFH + 1398 2381 85 60 sta SOFFL ; lo part here too + 1399 + 1400 2383 AD 06 96 lda ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + 1401 2386 85 81 sta ZPCM ; MSB + 1402 2388 AD 07 96 lda ZBEGIN+ZGO+1 ; AND LSB + 1403 238B 0A asl A ; *2 + 1404 238C 26 81 rol ZPCM + 1405 238E 26 82 rol ZPCH + 1406 2390 0A asl A ; *4 + 1407 2391 26 81 rol ZPCM + 1408 2393 26 82 rol ZPCH + 1409 ; + 1410 ; now add offset + 1411 ; + 1412 2395 18 clc ; doing adding + 1413 2396 65 5D adc FOFFL ; add in lo part + 1414 2398 85 80 sta ZPCL + 1415 239A A5 81 lda ZPCM + 1416 239C 65 5C adc FOFFM + 1417 239E 85 81 sta ZPCM + 1418 23A0 A5 82 lda ZPCH + 1419 23A2 65 5B adc FOFFH + Tue Jun 13 1989 10:05 Page 31 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1420 23A4 85 82 sta ZPCH + 1421 ; + 1422 ; now, set up TBLPUR, FUNPRE, and FUNPUR + 1423 ; + 1424 23A6 AD 1D 19 lda SEGTBL+SGTTBLE+1 ; get last page of table preload + 1425 23A9 0A asl A ; make 256K page + 1426 23AA 85 C2 sta TBLPUR ; show last pre table + 1427 23AC E6 C2 inc TBLPUR ; but we want first pure table address + 1428 23AE E6 C2 inc TBLPUR ; so point to it + 1429 23B0 A5 C2 lda TBLPUR ; does table preload take up all preload? + 1430 23B2 C9 D6 cmp #PGBEGIN ; reach 1st paged page? + 1431 23B4 B0 17 bcs ZBEND1 ; ayyup, no function preload + 1432 + 1433 23B6 AD 21 19 lda SEGTBL+SGTFUNS+1 ; get first page of function preload + 1434 23B9 0A asl A ; make 256K page + 1435 23BA 85 C3 sta FUNPRE ; show me + 1436 23BC AD 23 19 lda SEGTBL+SGTFUNE+1 ; last page of function preload + 1437 23BF 0A asl A ; make 256K page + 1438 23C0 85 C4 sta FUNPUR ; show last pre function + 1439 23C2 E6 C4 inc FUNPUR ; but we want first pure function + 1440 23C4 E6 C4 inc FUNPUR ; now we point to it + 1441 23C6 + 1442 23C6 A5 C2 lda TBLPUR ; now figger out negative number to + 1443 23C8 38 sec ; add to function preload addres to + 1444 23C9 E5 C3 sbc FUNPRE ; get page offset in memory + 1445 23CB 85 C5 sta FUNPGE ; set up offset + 1446 ; + 1447 ; and now to set up extension table pointer + 1448 ; + 1449 23CD ZBEND1: + 1450 23CD AD 37 96 lda ZBEGIN+ZEXTAB+1 ; LSB of table + 1451 23D0 85 CE sta MSTBL+LO ; stays the same + 1452 23D2 AD 36 96 lda ZBEGIN+ZEXTAB ; MSB of table + 1453 23D5 20 ED 26 jsr SETPC ; get me the memory addres + 1454 23D8 84 D0 sty MSTBL+ABANK ; save bank + 1455 23DA 85 CF sta MSTBL+HI ; and page + 1456 23DC + 1457 23DC 20 D7 29 jsr INIT_CHARSET ; initialize the charset + 1458 23DF 4C 34 29 jmp INITPAG ; set up paging system + 1459 + 1460 23E2 END + 1461 + 1462 23E2 INCLUDE BREL.ASM ; relocated subroutines + 1463 23E2 STTL "--- RELOCATED SUBROUTINES ---" + 1464 PAGE + Tue Jun 13 1989 10:05 Page 32 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1465 + 1466 ; + 1467 ; FETCHB - use FPC to get a byte in either aux or main mem + 1468 ; + 1469 23E2 FETCHBx: + 1470 23E2 99 02 C0 sta RDBNK,Y ; set bank, lower + 1471 23E5 A0 00 ldy #0 ; gotta use Y + 1472 23E7 B1 8C lda (FPC),Y ; so go get it + 1473 23E9 8D 02 C0 sta RDBNK ; go back to main bank + 1474 23EC 60 rts ; and return + 1475 ; + 1476 ; ZFETCH - fetch byte at (ZPCPNT),Y - offset from (ZPCPNT) + 1477 ; + 1478 23ED ZFETCHx: + 1479 23ED 9D 02 C0 sta RDBNK,X ; set lower bank + 1480 23F0 B1 83 lda (ZPCPNT),Y ; so go get it + 1481 23F2 8D 02 C0 sta RDBNK ; go back to main bank + 1482 23F5 60 rts ; bye + 1483 ; + 1484 ; MFETCH - fetch byte at (MPCPNT),Y - offset from (MPCPNT) + 1485 ; + 1486 23F6 MFETCHx: + 1487 23F6 9D 02 C0 sta RDBNK,X ; set bank + 1488 23F9 B1 89 lda (MPCPNT),Y ; so go get it + 1489 23FB 8D 02 C0 sta RDBNK ; go back to main bank + 1490 23FE 60 rts ; bye + 1491 ; + 1492 ; SAVE_DATA - copy data from [DBUFF] to IOBUFF + 1493 ; [Y] must == 0; [X] == DSKBNK; [A] == IOBUFF ($8 or $9) + 1494 ; + 1495 23FF 9D 02 C0 sta RDBNK,X ; and select that bank for reading + 1496 2402 85 F7 sta SAVE_DATA+9 ; show which part of iobuff + 1497 2404 SDAT1: + 1498 2404 B1 B6 lda (DBUFF),Y ; get me that byte + 1499 2406 SDAT2: + 1500 2406 99 00 08 sta IOBUFF,Y ; MODIFIED ABOVE + 1501 2409 C8 iny + 1502 240A D0 F8 bne SDAT1 + 1503 240C 8D 02 C0 sta RDBNK+MAIN ; and back to main + 1504 240F 60 rts + 1505 002D RLCLEN EQU $-FETCHBx-1 ; mark length + 1506 ; + 1507 ; COPY_LINE: + 1508 ; SPC - source pointer + 1509 ; FPC - destination pointer + 1510 ; SPCBNK - bank the above two are talking about + 1511 ; CPY_COUNT - end-start bytes to move + 1512 ; STMASK - mask to use on first byte (0 if none) + 1513 ; ENDMASK - mask to use for end byte (0 if none) + 1514 ; + 1515 ; MODIFIED CODE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + 1516 ; The definitions for CPY_MODs are HARD CODED in apple.equ - they MUST + 1517 ; match the definitions below for similar xCPY_MODs!!!!!!!! + 1518 ; DON'T CHANGE WITHOUT FIXING THOSE OFFSETS IN APPLE.EQU!!!!! + 1519 ; + 1520 2410 CPYx EQU * + 1521 2410 A6 91 ldx SPCBNK ; set up banks for first byte + Tue Jun 13 1989 10:05 Page 33 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1522 2412 BD 54 C0 lda PAGE2SW,X ; r/w which bank in display mem + 1523 2415 A0 00 ldy #0 ; use Y reg + 1524 2417 A5 1A lda STMASK ; get start mask + 1525 2419 F0 0E beq CPLOOP ; no start mask, start in middle of loop + 1526 241B 31 8C and (FPC),Y ; turn off changing bits, keep good bits + 1527 241D 91 8C sta (FPC),Y ; save it + 1528 241F A5 1A lda STMASK ; get changing bits + 1529 2421 49 FF eor #$FF ; turn on changing bits + 1530 2423 31 8F and (SPC),Y ; get SPC byte + 1531 2425 11 8C ora (FPC),Y ; turn them on in destination too + 1532 2427 91 8C sta (FPC),Y ; and destiny + 1533 2429 CPLOOP: + 1534 2429 A5 BD lda CPY_COUNT ; get count + 1535 242B 4A lsr A ; /2 for number in this bank + 1536 242C AA tax ; put in X for indexing + 1537 242D F0 15 beq CPLP2 ; then done! + 1538 242F CA dex ; zero base the number + 1539 2430 A5 1A lda STMASK ; special start? + 1540 2432 F0 07 beq CPL1 ; nope + 1541 2434 EE 7C 1D inc CPY_MOD1_SRC ; first one already done + 1542 2437 EE 7F 1D inc CPY_MOD1_DST ; point to next one + 1543 243A CA dex ; and count first one as done + 1544 243B CPL1: + 1545 243B BD 00 20 lda SCREEN,X ; get byte + 1546 243E 9D 00 20 sta SCREEN,X ; store byte + 1547 2441 CA dex ; count down + 1548 2442 10 F7 bpl CPL1 ; and do it all again + 1549 2444 CPLP2: + 1550 2444 A0 00 ldy #0 ; reset y + 1551 2446 A5 91 lda SPCBNK ; get current bank + 1552 2448 49 01 eor #1 ; toggle to point to the other one + 1553 244A AA tax + 1554 244B BD 54 C0 lda PAGE2SW,X + 1555 244E 8A txa ; which bank? + 1556 244F F0 07 beq CPLP21 ; we are now in main, things are fine + 1557 2451 EE A0 1D inc CPY_MOD2_SRC ; start one more if now in AUX + 1558 2454 EE A3 1D inc CPY_MOD2_DST + 1559 2457 CA dex ; and count as done + 1560 2458 CPLP21: + 1561 2458 A5 BD lda CPY_COUNT ; get count again + 1562 245A 4A lsr A ; /2 for bytes in this bank + 1563 245B AA tax ; put in X for counter + 1564 245C F0 0A beq CPDONE ; nothing here + 1565 245E CA dex ; zero base the number + 1566 245F CPL2: + 1567 245F BD 00 20 lda SCREEN,X ; get byte + 1568 2462 9D 00 20 sta SCREEN,X ; store byte + 1569 2465 CA dex ; count byte + 1570 2466 10 F7 bpl CPL2 ; and swing by again + 1571 2468 CPDONE: + 1572 2468 A5 1B lda ENDMASK ; do same mucking as when starting + 1573 246A F0 1D beq CPEXIT ; no mucking + 1574 246C 48 pha ; save endmask + 1575 246D A5 BD lda CPY_COUNT ; get how many bytes being copied + 1576 246F 4A lsr A ; /2 + 1577 2470 90 07 bcc CPDONE1 ; if even, then we are pointing to correct + 1578 2472 48 pha ; save a + Tue Jun 13 1989 10:05 Page 34 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1579 2473 A6 91 ldx SPCBNK ; get original bank + 1580 2475 BD 54 C0 lda PAGE2SW,X ; and point to it + 1581 2478 68 pla ; get it back + 1582 2479 CPDONE1: + 1583 2479 A8 tay ; get offset + 1584 247A 68 pla ; get end mask back + 1585 247B 49 FF eor #$FF ; turn on all off bits + 1586 247D 31 8C and (FPC),Y ; turn off changing bits + 1587 247F 91 8C sta (FPC),Y ; save it + 1588 2481 B1 8F lda (SPC),Y ; get source byte + 1589 2483 25 1B and ENDMASK ; turn on changing bits + 1590 2485 11 8C ora (FPC),Y ; turn them on in destination too + 1591 2487 91 8C sta (FPC),Y ; and destiny + 1592 2489 CPEXIT: + 1593 2489 AD 54 C0 lda PAGE2SW ; set back to main mem + 1594 248C 60 rts + 1595 007C CPYLEN EQU $-CPYx-1 + 1596 002C xCPY_MOD1 equ (CPL1-CPYx+1) + 1597 002F xCPY_MOD1_DST equ xCPY_MOD1+3 + 1598 0050 xCPY_MOD2 equ (CPL2-CPYx+1) + 1599 0053 xCPY_MOD2_DST equ xCPY_MOD2+3 + 1600 248D PAGE3REL: + 1601 ; + 1602 ; MOUSER - this vectors the call to the correct place + 1603 ; + 1604 248D MOUSERx: + 1605 248D 48 pha ; save A for a sec + 1606 248E BD 12 C4 MSX1: lda MTABLE,X ; get lo part of address + 1607 2491 8D 10 03 sta MSVECTOR+LO ; save lo part of address + 1608 2494 68 pla ; get A back + 1609 2495 EA nop + 1610 2496 A2 C4 MSX2: ldx #$C4 ; might be changed, depending on slot + 1611 2498 A0 40 MSX3: ldy #$40 ; hopefully, this doesn't + 1612 249A 6C 10 03 jmp (MSVECTOR) ; and away we go + 1613 000F MSRxLEN EQU $-MOUSERx-1 ; show how long this is + 1614 249D MSVECTORx: + 1615 249D ds 1 ; where lo part of vector goes + 1616 249E C4 MSX4: db $C4 ; slot where mouse is + 1617 0011 MSRLEN EQU $-MOUSERx-1 ; length or routine + 1618 ; + 1619 ; colors for screen lines + 1620 ; + 1621 RADIX H + 1622 249F COLORSx: + 1623 249F 00 00 00 00 db 00,00,00,00 ; black + 1624 24A3 08 11 22 44 db 08,11,22,44 ; magenta + 1625 24A7 44 08 11 22 db 44,08,11,22 ; brown + 1626 24AB 4C 19 33 66 db 4C,19,33,66 ; orange + 1627 24AF 22 44 08 11 db 22,44,08,11 ; dark green + 1628 24B3 2A 55 2A 55 db 2A,55,2A,55 ; gray 1 + 1629 24B7 66 4C 19 33 db 66,4C,19,33 ; green + 1630 24BB 6E 5D 3B 77 db 6E,5D,3B,77 ; yellow + 1631 24BF 11 22 44 08 db 11,22,44,08 ; dark blue + 1632 24C3 19 33 66 4C db 19,33,66,4C ; purple + 1633 24C7 55 2A 55 2A db 55,2A,55,2A ; gray 2 + 1634 24CB 5D 3B 77 6E db 5D,3B,77,6E ; pink + 1635 24CF 33 66 4C 19 db 33,66,4C,19 ; medium blue + Tue Jun 13 1989 10:05 Page 35 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1636 24D3 3B 77 6E 5D db 3B,77,6E,5D ; light blue + 1637 24D7 77 6E 5D 3B db 77,6E,5D,3B ; aqua + 1638 24DB 7F 7F 7F 7F db 7F,7F,7F,7F ; white + 1639 24DF XPOSTBLx: + 1640 24DF 00 DB 0 + 1641 24E0 00 01 01 02 02 DB 0,1,1,2,2,3,4 + 24E5 03 04 + 1642 24E7 04 05 05 06 06 DB 4,5,5,6,6,7,8 + 24EC 07 08 + 1643 24EE 08 09 09 0A 0A DB 8,9,9,0a,0a,0b,0c + 24F3 0B 0C + 1644 24F5 0C 0D 0D 0E 0E DB 0c,0d,0d,0e,0e,0f,10 + 24FA 0F 10 + 1645 24FC 10 11 11 12 12 DB 10,11,11,12,12,13,14 + 2501 13 14 + 1646 2503 14 15 15 16 16 DB 14,15,15,16,16,17,18 + 2508 17 18 + 1647 250A 18 19 19 1A 1A DB 18,19,19,1a,1a,1b,1c + 250F 1B 1C + 1648 2511 1C 1D 1D 1E 1E DB 1c,1d,1d,1e,1e,1f,20 + 2516 1F 20 + 1649 2518 20 21 21 22 22 DB 20,21,21,22,22,23,24 + 251D 23 24 + 1650 251F 24 25 25 26 26 DB 24,25,25,26,26,27,28 + 2524 27 28 + 1651 2526 28 29 29 2A 2A DB 28,29,29,2a,2a,2b,2c + 252B 2B 2C + 1652 252D 2C 2D 2D 2E 2E DB 2c,2d,2d,2e,2e,2f,30 + 2532 2F 30 + 1653 2534 30 31 31 32 32 DB 30,31,31,32,32,33,34 + 2539 33 34 + 1654 253B 34 35 35 36 36 DB 34,35,35,36,36,37,38 + 2540 37 38 + 1655 2542 38 39 39 3A 3A DB 38,39,39,3a,3a,3b,3c + 2547 3B 3C + 1656 2549 3C 3D 3D 3E 3E DB 3c,3d,3d,3e,3e,3f,40 + 254E 3F 40 + 1657 2550 40 41 41 42 42 DB 40,41,41,42,42,43,44 + 2555 43 44 + 1658 2557 44 45 45 46 46 DB 44,45,45,46,46,47,48 + 255C 47 48 + 1659 255E 48 49 49 4A 4A DB 48,49,49,4a,4a,4b,4c + 2563 4B 4C + 1660 2565 4C 4D 4D 4E 4E DB 4c,4d,4d,4e,4e,4f,50 + 256A 4F 50 + 1661 RADIX D + 1662 00DE PAGE3RELL EQU $-PAGE3REL-1 + 1663 256C END + 1664 + 1665 256C INCLUDE BSUBS.ASM ; subs for e to use + 1666 PAGE + Tue Jun 13 1989 10:05 Page 36 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1667 256C STTL "--- BOOT CODE SUBROUTINES ---" + 1668 + 1669 256C 0D 0D ERRM: DB EOL,EOL + 1670 256E 49 6E 74 65 72 DB "Internal error " + 2573 6E 61 6C 20 65 + 2578 72 72 6F 72 20 + 1671 257D 30 30 ENUMB: DB "00" + 1672 257F 30 30 2E 20 20 DB "00. " + 1673 0018 ERRML EQU $-ERRM + 1674 2584 30 31 32 33 34 HCHARS: DB "0123456789ABCDEF" + 2589 35 36 37 38 39 + 258E 41 42 43 44 45 + 2593 46 + 1675 ; + 1676 ; ZERROR: print out error code in HexWord: [A][Y]. + 1677 ; + 1678 2594 ZERROR: + 1679 2594 48 pha ; save [A] + 1680 2595 98 tya ; and put y to a for figgering + 1681 2596 A0 03 ldy #3 ; CONVERT ERROR BYTE IN [A] + 1682 2598 ZERR0: + 1683 2598 48 pha + 1684 2599 29 0F and #%00001111 + 1685 259B AA tax + 1686 259C BD 84 25 lda HCHARS,X + 1687 259F 99 7D 25 sta ENUMB,Y + 1688 25A2 68 pla + 1689 25A3 4A LSR A + 1690 25A4 4A LSR A + 1691 25A5 4A lsr A + 1692 25A6 4A lsr A + 1693 25A7 AA tax + 1694 25A8 BD 84 25 lda HCHARS,X + 1695 25AB 88 dey + 1696 25AC 99 7D 25 sta ENUMB,Y + 1697 25AF F0 05 beq ZR1 ; done + 1698 25B1 + 1699 25B1 68 pla ; done with first number + 1700 25B2 88 dey ; and point one more down + 1701 25B3 4C 98 25 jmp ZERR0 ; so work on second number + 1702 25B6 ZR1: + 1703 25B6 A2 6C ldx #ERRM + 1705 25BA A0 18 ldy #ERRML + 1706 25BC 20 D5 26 jsr DLINE ; PRINT ERROR MESSAGE + 1707 25BF 20 01 26 jsr GETRET ; wait for + 1708 25C2 4C 19 26 jmp ZQUIT + 1709 + 1710 25C5 0D 50 6C 65 61 RETQ: db EOL,"Please insert new disk to boot." + 25CA 73 65 20 69 6E + 25CF 73 65 72 74 20 + 25D4 6E 65 77 20 64 + 25D9 69 73 6B 20 74 + 25DE 6F 20 62 6F 6F + 25E3 74 2E + 1711 25E5 0D 41 6E 64 20 db EOL, "And hit RETURN when ready.",EOL + 25EA 68 69 74 20 52 + Tue Jun 13 1989 10:05 Page 37 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 25EF 45 54 55 52 4E + 25F4 20 77 68 65 6E + 25F9 20 72 65 61 64 + 25FE 79 2E 0D + 1712 003C RETQL EQU $-RETQ + 1713 2601 GETRET: + 1714 2601 DLINE RETQ ; ask for return + 1715 2601 A2 C5 ldx #RETQ ; get other part of string + 1717 [01] IFMA 2 ; check to see if length passed in + 1718 ldy ; then just fetch it + 1719 [01] ELSE + 1720 2605 A0 3C ldy #RETQL ; get length of string + 1721 [00] ENDIF + 1722 2607 20 D5 26 jsr DLINE ; print the string + 1723 260A .MACEND + 1724 260A GETRETL: + 1725 260A AD 00 C0 lda KBD ; get a key + 1726 260D 10 FB bpl GETRETL ; no key + 1727 260F 29 7F and #$7f ; make a good key + 1728 2611 C9 0D cmp #EOL ; return key? + 1729 2613 D0 F5 bne GETRETL ; nope + 1730 2615 20 ED FD jsr MCOUT ; show the + 1731 2618 60 rts + 1732 2619 + 1733 + 1734 ; ---- + 1735 ; QUIT + 1736 ; ---- + 1737 + 1738 2619 ZQUIT: + 1739 2619 A5 59 lda INFODOS ; in dinky-dos? + 1740 261B F0 17 beq ZQUIT2 ; nope + 1741 261D A9 00 lda #0 ; clear power up byte + 1742 261F 8D F4 03 sta $3F4 ; make it do cold boot + 1743 2622 AD FD FF lda RESET_VECTOR+HI ; now, set up where to die to + 1744 2625 8D 33 26 sta ZQUITR1+2 + 1745 2628 AD FC FF lda RESET_VECTOR+LO + 1746 262B 8D 32 26 sta ZQUITR1+1 + 1747 262E AD 82 C0 lda RDROM ; get ROM back + 1748 2631 ZQUITR1: + 1749 2631 4C FC FF jmp RESET_VECTOR ; just reset things + 1750 ; + 1751 ; re-enable /RAM + 1752 ; + 1753 2634 ZQUIT2: + 1754 2634 AE 31 BF ldx DEVCNT ; put device in at end + 1755 2637 E8 inx ; point to one past end + 1756 2638 8E 31 BF stx DEVCNT ; show new count + 1757 263B A9 BF lda #$BF ; /RAM ID + 1758 263D 9D 32 BF sta DEVNUM,X ; save it + 1759 2640 AD 7F 07 lda OLDVEC+HI ; restore old vector + 1760 2643 8D 27 BF sta RAMVEC+HI + 1761 2646 AD 7E 07 lda OLDVEC+LO + 1762 2649 8D 26 BF sta RAMVEC+LO + 1763 ; + 1764 ; now format /RAM + Tue Jun 13 1989 10:05 Page 38 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1765 ; + 1766 264C A9 03 lda #3 ; stash into FORMAT parm block + 1767 264E 85 42 sta $42 ; it goes here, oddly enough + 1768 2650 A9 B0 lda #$B0 ; device id for /RAM + 1769 2652 85 43 sta $43 ; and here it goes + 1770 2654 A9 11 lda #>GAME1FIO ; IO buffer + 1771 2656 85 45 sta $45 ; this is where it goes + 1772 2658 A9 00 lda #ZBEGIN ; ADD OFFSET TO GET RAM PAGE + 1859 26F5 A0 00 ldy #MAIN ; in the main bank + 1860 26F7 F0 12 beq VFEXI ; BRA to fetch + 1861 26F9 VF2: + 1862 26F9 C9 D6 cmp #PGBEGIN ; is it paged? + 1863 26FB B0 12 bcs VFERR ; yes it be paged, so can't deal with it + 1864 26FD C9 A8 cmp #P3PAGE ; is it in Aux Mem, Part 2? + 1865 26FF B0 06 bcs VF3 ; yes, so subtract different amount + 1866 ; + 1867 ; this is in lower aux + 1868 ; + Tue Jun 13 1989 10:05 Page 40 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1869 2701 A9 17 lda #(Z2PAGE-Z1SIZE) ; subtract size from offset + 1870 2703 A0 01 ldy #AUX ; show aux mem + 1871 2705 D0 04 bne VFEXI ; jump to end + 1872 2707 VF3: + 1873 2707 A9 28 lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides + 1874 2709 A0 FF ldy #P3BANK ; show page 3 bank + 1875 270B VFEXI: + 1876 270B 18 clc ; get ready for addition + 1877 270C 65 BC adc MEMPAGE ; now get actual offset + 1878 270E 60 rts + 1879 270F VFERR: + 1880 ; + 1881 ; out of range + 1882 ; + 1883 270F A9 22 lda #$22 + 1884 2711 4C 94 25 jmp ZERROR + 1885 + 1886 ; + 1887 ; FETCHB - fetch a byte from either main memory, aux memory, or upper + 1888 ; Aux memory + 1889 ; + 1890 2714 FETCHB: + 1891 2714 A4 8E ldy FPCBNK ; get the bank + 1892 2716 30 03 bmi FB1 ; must be in upper RAM + 1893 2718 4C D1 00 jmp ZERO_FB ; go to low end fetch + 1894 ; + 1895 ; this is in aux mem, >$E000 + 1896 ; + 1897 271B FB1: + 1898 271B A5 8D lda FPCH ; get which page + 1899 271D 8D 2D 27 sta FBMOD+2 ; and show in operand + 1900 2720 A4 8C ldy FPCL ; get which byte + 1901 2722 8D 09 C0 sta ALTZP+AUX ; talk about aux mem + 1902 2725 AD 8B C0 lda BNK1SET ; set up read/write ram in upper mem + 1903 2728 AD 8B C0 lda BNK1SET ; set up read/write ram in upper mem + 1904 272B B9 00 D0 FBMOD: lda Z3BEGIN,Y ; get the sucker + 1905 272E 8D 08 C0 sta ALTZP+MAIN ; go back to main mem + 1906 2731 AE 82 C0 ldx RDROM ; now use ROM please + 1907 2734 AE 82 C0 ldx RDROM ; now use ROM please + 1908 2737 60 rts + 1909 ; + 1910 ; NEXTFPC - inc DPCL and check for wrapping round to next bank + 1911 ; + 1912 2738 NEXTFPC: + 1913 2738 E6 8C inc FPCL ; next lo byte + 1914 273A D0 1B bne NXFP_EXIT ; no change then + 1915 273C E6 8D inc FPCH ; next page + 1916 273E A5 8D lda FPCH ; and get it for checking + 1917 2740 C9 BF cmp #>PRGLBL ; have we reached end of line? + 1918 2742 D0 13 bne NXFP_EXIT ; we be okay + 1919 2744 A5 8E lda FPCBNK ; get bank + 1920 2746 D0 07 bne NXFP1 ; must skip over stuff in middle + 1921 2748 E6 8E inc FPCBNK ; so point to aux bank + 1922 274A A9 40 lda #Z2PAGE ; first page in aux + 1923 274C 85 8D sta FPCH ; and point to it + 1924 274E 60 rts ; toots finis + 1925 274F NXFP1: + Tue Jun 13 1989 10:05 Page 41 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1926 274F A9 D0 lda #Z3PAGE ; start of part 3 + 1927 2751 85 8D sta FPCH ; so show me + 1928 2753 A9 FF lda #P3BANK ; and point to this bank + 1929 2755 85 8E sta FPCBNK ; okey + 1930 2757 NXFP_EXIT: + 1931 2757 60 rts + 1932 ; + 1933 ; INST_MOUSE - install mouse handler IRQ + 1934 ; + 1935 0303 MFIX1 EQU (MSX1-MOUSERx)+PAGE3STUFF+2 + 1936 030A MFIX2 EQU (MSX2-MOUSERx)+PAGE3STUFF+1 + 1937 0311 MFIX3 EQU (MSX4-MOUSERx)+PAGE3STUFF + 1938 030C MFIX4 EQU (MSX3-MOUSERx)+PAGE3STUFF+1 + 1939 2758 INST_MOUSE: + 1940 2758 20 CA 27 jsr FINDMOUSE ; find which slot the mouse is in + 1941 275B 90 01 bcc INMS1 ; everything is fine + 1942 275D 60 rts ; can't find the mouse + 1943 275E INMS1: + 1944 275E 8D 03 03 sta MFIX1 + 1945 2761 8D 0A 03 sta MFIX2 + 1946 2764 8D 11 03 sta MFIX3 ; okay, everyone knows now + 1947 2767 29 0F and #$0f ; pick up low byte + 1948 2769 85 63 sta ARG1+LO ; save for program to pick up + 1949 276B 0A asl A ; shift slot number to upper nybble + 1950 276C 0A asl A + 1951 276D 0A asl A + 1952 276E 0A asl A + 1953 276F 8D 0C 03 sta MFIX4 ; and save here + 1954 ; + 1955 ; now init mouse, please + 1956 ; + 1957 2772 A2 07 ldx #INITM ; init first + 1958 2774 20 00 03 jsr MOUSER ; so do it + 1959 2777 A2 00 ldx #SETM ; setup mouse + 1960 2779 A9 01 lda #$01 ; transparent mode + 1961 277B 20 00 03 jsr MOUSER ; we do that + 1962 277E A2 03 ldx #CLEARM ; and clear mouse pos + 1963 2780 20 00 03 jsr MOUSER ; we did + 1964 ; + 1965 ; now set min and max for clamping. + 1966 ; 0 <= xpos <= 139 + 1967 ; 0 <= ypos <= 191 + 1968 ; + 1969 2783 A9 00 lda #0 ; zero out a few of the things + 1970 2785 8D 78 05 sta CLMPMINH ; hi part of min clamp + 1971 2788 8D 78 04 sta CLMPMINL ; lo part of min clamp + 1972 278B A9 89 lda #<137 ; max X + 1973 278D 8D F8 04 sta CLMPMAXL ; stash in lo part + 1974 2790 A9 00 lda #>137 ; max X + 1975 2792 8D F8 05 sta CLMPMAXH ; hi part of clamp + 1976 2795 A9 00 lda #0 ; show setting X clamp + 1977 2797 A2 05 ldx #CLAMPM ; do clamping + 1978 2799 20 00 03 jsr MOUSER ; okay, we did + 1979 279C A9 BD lda #<189 ; now for Y + 1980 279E 8D F8 04 sta CLMPMAXL ; saved in lo part + 1981 27A1 A9 00 lda #>189 ; now for Y + 1982 27A3 8D F8 05 sta CLMPMAXH ; saved in lo part + Tue Jun 13 1989 10:05 Page 42 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1983 27A6 A9 01 lda #1 ; set y boundries + 1984 27A8 A2 05 ldx #CLAMPM ; okay, show which routine + 1985 27AA 20 00 03 jsr MOUSER ; and do it + 1986 + 1987 ; + 1988 ; initialize the mouse position + 1989 ; + 1990 27AD A9 00 lda #0 ; clear MSB + 1991 27AF 8D 78 05 sta MOUSEXH + 1992 27B2 8D F8 05 sta MOUSEYH + 1993 27B5 A9 C0 lda #MAXHEIGHT + 1994 27B7 8D F8 04 sta MOUSEYL + 1995 27BA A9 8C lda #MAXWIDTH + 1996 27BC 8D 78 04 sta MOUSEXL + 1997 + 1998 27BF A2 04 ldx #POSM + 1999 27C1 20 00 03 jsr MOUSER ; and move it + 2000 + 2001 ; cli ; enable interrupts now + 2002 27C4 A9 FF lda #$FF ; < 0 show mouse + 2003 27C6 85 58 sta MOUSEF ; so show it + 2004 27C8 18 clc ; show everything is fine + 2005 27C9 60 rts ; done + 2006 ; + 2007 ; FINDMOUSE - scan the slots for a mouse + 2008 ; + 2009 27CA FINDMOUSE: + 2010 27CA AD FB C1 lda $C1FB ; check for mouse ID == D6 + 2011 27CD C9 D6 cmp #$D6 ; mouse ID + 2012 27CF D0 05 bne FNDM1 ; not it + 2013 27D1 AD CC 27 lda FINDMOUSE+2 ; get slot + 2014 27D4 18 clc ; show okay-ness + 2015 27D5 60 rts ; and return + 2016 27D6 FNDM1: + 2017 27D6 EE CC 27 inc FINDMOUSE+2 ; point to next slot + 2018 27D9 AD CC 27 lda FINDMOUSE+2 ; reached last one yet? + 2019 27DC C9 C8 cmp #$C8 ; no slot eight + 2020 27DE 90 EA bcc FINDMOUSE ; go look again + 2021 27E0 38 sec ; show no mouse + 2022 27E1 60 rts + 2023 ; + 2024 ; INST_STICK - install the joystick handler + 2025 27E2 INST_STICK: + 2026 27E2 A9 01 lda #$1 ; > 0 show joystick + 2027 27E4 85 58 sta MOUSEF ; okay, we do + 2028 27E6 18 clc ; show it worked + 2029 27E7 60 rts + 2030 27E8 RAMINFO: + 2031 27E8 0A db 10 ; 10 parms + 2032 27E9 FA27 dw RAMNAME ; name + 2033 27EB ds 15 ; room for stuff + 2034 27FA RAMNAME: + 2035 27FA 05 db 5 ; length of name + 2036 27FB 2F 52 41 4D 2F db "/RAM/" ; name + 2037 2800 0D 54 68 69 73 RAMQ: db EOL,"This program disables /RAM and it",EOL + 2805 20 70 72 6F 67 + 280A 72 61 6D 20 64 + Tue Jun 13 1989 10:05 Page 43 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 280F 69 73 61 62 6C + 2814 65 73 20 2F 52 + 2819 41 4D 20 61 6E + 281E 64 20 69 74 0D + 2038 2823 69 73 20 6E 6F db "is not empty. Do you want to" + 2828 74 20 65 6D 70 + 282D 74 79 2E 20 20 + 2832 44 6F 20 79 6F + 2837 75 20 77 61 6E + 283C 74 20 74 6F + 2039 2840 0D 63 6F 6E 74 db EOL,"continue (Y destroys /RAM)?" + 2845 69 6E 75 65 20 + 284A 28 59 20 64 65 + 284F 73 74 72 6F 79 + 2854 73 20 2F 52 41 + 2859 4D 29 3F + 2040 005C RAMQL EQU $-RAMQ + 2041 285C FIXRAM: + 2042 285C GET_FILE_INFO RAMINFO ; get the volumn size + 2043 285C PRODOS $C4, RAMINFO + 2044 285C 20 00 BF jsr $BF00 ; ProDOS handler + 2045 285F C4 DB $C4 ; ProDOS function code + 2046 2860 E827 DW RAMINFO ; Function Parameter Block address + 2047 2862 .MACEND + 2048 2862 .MACEND + 2049 2862 B0 28 bcs FIXR1 ; problem, so we'll just disable it + 2050 + 2051 2864 AD F1 27 lda RAMINFO+9 ; get amount used + 2052 2867 D0 07 bne ASKUSER ; some files there complain + 2053 2869 AD F0 27 lda RAMINFO+8 ; get LSB of used + 2054 286C C9 09 cmp #9 ; if >= 9, must be being used + 2055 286E 90 1C bcc FIXR1 ; no problem, disable /RAM + 2056 2870 ASKUSER: + 2057 2870 20 58 FC jsr MHOME ; clear and home + 2058 2873 DLINE RAMQ ; ask about continuing + 2059 2873 A2 00 ldx #RAMQ ; get other part of string + 2061 [01] IFMA 2 ; check to see if length passed in + 2062 ldy ; then just fetch it + 2063 [01] ELSE + 2064 2877 A0 5C ldy #RAMQL ; get length of string + 2065 [00] ENDIF + 2066 2879 20 D5 26 jsr DLINE ; print the string + 2067 287C .MACEND + 2068 287C 20 0C FD jsr MRDKEY ; get answer + 2069 287F 29 7F and #$7F ; turn off hi bit + 2070 2881 C9 79 cmp #'y' ; check for yes + 2071 2883 F0 07 beq FIXR1 ; then continue + 2072 2885 C9 59 cmp #'Y' ; also, captital Y + 2073 2887 F0 03 beq FIXR1 ; okay again + 2074 2889 4C 19 26 jmp ZQUIT ; so die + 2075 288C FIXR1: + 2076 288C AD 26 BF lda RAMVEC+LO ; get current /RAM vector + 2077 288F 8D 7E 07 sta OLDVEC+LO ; save it for reinstalling + 2078 2892 AD 27 BF lda RAMVEC+HI + 2079 2895 8D 7F 07 sta OLDVEC+HI + 2080 2898 AD 16 BF lda UNSVEC+LO ; point /RAM vector to uninstalled device + Tue Jun 13 1989 10:05 Page 44 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2081 289B 8D 26 BF sta RAMVEC+LO + 2082 289E AD 17 BF lda UNSVEC+HI + 2083 28A1 8D 27 BF sta RAMVEC+HI + 2084 28A4 AE 31 BF ldx DEVCNT ; get how many devices + 2085 28A7 DEVLP: + 2086 28A7 BD 32 BF lda DEVNUM,X ; try to find /RAM device + 2087 28AA 29 70 and #$70 ; isolate slot + 2088 28AC C9 30 cmp #$30 ; look for slot 3 + 2089 28AE F0 04 beq GOTSLT ; got it + 2090 28B0 CA dex ; missed it + 2091 28B1 10 F4 bpl DEVLP ; try again + 2092 28B3 60 rts ; didn't find it (?) + 2093 28B4 GOTSLT: + 2094 28B4 BD 33 BF lda DEVNUM+1,X ; now move all down one + 2095 28B7 9D 32 BF sta DEVNUM,X ; down one + 2096 28BA EC 31 BF cpx DEVCNT ; done yet + 2097 28BD F0 03 beq FIXREX ; ayyup + 2098 28BF E8 inx ; point to next slot + 2099 28C0 D0 F2 bne GOTSLT ; continue on + 2100 28C2 FIXREX: + 2101 28C2 CE 31 BF dec DEVCNT ; one less device, thank you + 2102 28C5 60 rts ; all done + 2103 ; + 2104 ; DO_DSEGS - scan through the disk segment table and point to the + 2105 ; beginning of the segment list for each of the disks in the + 2106 ; file. + 2107 28C6 DO_DSEGS: + 2108 28C6 AD 01 19 lda SEGTBL+SGTDISKS+1 ; get # number disks + 2109 28C9 85 7A sta J ; save in counter + 2110 28CB C6 7A dec J ; we hand hold #1 + 2111 28CD A9 19 lda #>(SEGTBL+SGTCHKS1) ; start off at beginning + 2112 28CF 8D D1 1D sta D1SEG+HI ; here is first one + 2113 28D2 A9 12 lda #<(SEGTBL+SGTCHKS1); and here is LSB + 2114 28D4 8D D0 1D sta D1SEG+LO ; save it + 2115 28D7 AC 17 19 ldy SEGTBL+SGTSEG1+1 ; get number of segs in first disk + 2116 28DA A2 02 ldx #2 ; start at second one + 2117 28DC DODSL: + 2118 28DC BD CE 1D lda DSKSEG-2+LO,X ; get LSB of previous start + 2119 28DF 18 clc ; doing some adding + 2120 28E0 69 08 adc #SGTSEG ; point to start of segment list + 2121 28E2 9D D0 1D sta DSKSEG+LO,X ; save in working segment pointer + 2122 28E5 BD CF 1D lda DSKSEG-2+HI,X ; now work on MSB + 2123 28E8 69 00 adc #0 ; pick up possible carry + 2124 28EA 9D D1 1D sta DSKSEG+HI,X ; and save in new pointer + 2125 28ED ADDLOOP: + 2126 28ED 18 clc ; doing add + 2127 28EE A9 06 lda #6 ; size of segment entry + 2128 28F0 7D D0 1D adc DSKSEG+LO,X ; counting + 2129 28F3 9D D0 1D sta DSKSEG+LO,X ; counting + 2130 28F6 90 03 bcc ADDL1 ; no wrap + 2131 28F8 FE D1 1D inc DSKSEG+HI,X ; add one to hi + 2132 28FB ADDL1: + 2133 28FB 88 dey ; count segment + 2134 28FC D0 EF bne ADDLOOP ; okay, not done yet + 2135 28FE BD D0 1D lda DSKSEG+LO,X ; get pointer to #segs in this one + 2136 2901 85 1E sta DSEGS+LO ; save ptr + 2137 2903 BD D1 1D lda DSKSEG+HI,X ; get MSB + Tue Jun 13 1989 10:05 Page 45 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2138 2906 85 1F sta DSEGS+HI ; save ptr + 2139 2908 A0 05 ldy #SGTNSEG+1 ; just need LSB + 2140 290A B1 1E lda (DSEGS),Y ; get #segs in this segment + 2141 290C A8 tay ; save in counter Y + 2142 290D E8 inx + 2143 290E E8 inx ; point to new pointer loc + 2144 290F C6 7A dec J ; count this disk + 2145 2911 D0 C9 bne DODSL ; and do it again + 2146 ; + 2147 ; now, init DSEGS to point to beginnning again + 2148 ; + 2149 2913 AD D1 1D lda D1SEG+HI ; here is first one + 2150 2916 85 1F sta DSEGS+HI + 2151 2918 AD D0 1D lda D1SEG+LO ; save it + 2152 291B 85 1E sta DSEGS+LO + 2153 ; + 2154 ; check to see if we are using infoDOS, and set pointer to second + 2155 ; disk segment table if we are. + 2156 ; + 2157 291D AD FF BF lda KVERSION ; get "version" number + 2158 2920 C9 FF cmp #INFODOS_ID ; is in our DOS? + 2159 2922 D0 0B bne DODX ; nope, it ain't + 2160 2924 AD D3 1D lda D2SEG+HI ; then have infoDOS flag to point + 2161 2927 85 5A sta INFODOS+HI ; to the D2SEG, cuz that's what + 2162 2929 AD D2 1D lda D2SEG+LO ; we use to check all the ZPC's + 2163 292C 85 59 sta INFODOS+LO + 2164 292E 60 rts + 2165 292F DODX: + 2166 292F A9 00 lda #0 ; regular ProDOS + 2167 2931 85 59 sta INFODOS ; show nothing there! + 2168 2933 60 rts + 2169 + 2170 ; + 2171 ; INITPAG - init the paging buffers, thank you + 2172 ; + 2173 2934 INITPAG: + 2174 2934 A2 17 LDX #NUMBUFS-1 ;*** + 2175 2936 86 CD STX CURRENT ; make last one first one to be used + 2176 2938 C6 CD dec CURRENT ; using only even pages + 2177 293A A9 FF LDA #$FF + 2178 293C INILP: + 2179 293C 9D 80 0C STA VPAGEH,X + 2180 293F CA DEX + 2181 2940 10 FA BPL INILP + 2182 2942 A2 00 LDX #0 + 2183 2944 A0 02 LDY #2 ;*** + 2184 2946 INILP2: + 2185 2946 98 TYA + 2186 2947 9D 40 0C STA PREVPNT,X + 2187 294A E8 INX + 2188 294B E8 inx ;*** + 2189 294C C8 INY + 2190 294D C8 iny ;*** + 2191 294E E0 18 CPX #NUMBUFS + 2192 2950 90 F4 BCC INILP2 + 2193 2952 A9 00 LDA #00 + 2194 2954 CA DEX + Tue Jun 13 1989 10:05 Page 46 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2195 2955 CA dex ;*** + 2196 2956 9D 40 0C STA PREVPNT,X + 2197 2959 A2 00 LDX #0 ;*** + 2198 295B A0 FE LDY #$FE ;*** + 2199 295D A9 16 LDA #NUMBUFS-2 ;*** + 2200 295F INILP3: + 2201 295F 9D 00 0C STA NEXTPNT,X + 2202 2962 E8 INX + 2203 2963 E8 inx ;*** + 2204 2964 C8 iny ;*** + 2205 2965 C8 INY + 2206 2966 98 TYA + 2207 2967 E0 18 CPX #NUMBUFS + 2208 2969 90 F4 BCC INILP3 + 2209 296B 60 rts + 2210 + 2211 ; + 2212 ; DO_PREFIX - check out the program name at $280. If there is a prefix + 2213 ; in there, just set prefix to it, so my default prefix is just fine. + 2214 ; + 2215 296C DO_PREFIX: + 2216 296C AE 80 02 ldx START_NAME ; get length of name + 2217 296F DOPLOOP: + 2218 296F BD 80 02 lda START_NAME,x ; get char + 2219 2972 29 7F and #$7F ; make it real ASCII + 2220 2974 C9 2F cmp #'/' ; directory seperator? + 2221 2976 F0 04 beq DOPLX ; yup, found the prefix + 2222 2978 CA dex ; previous char + 2223 2979 D0 F4 bne DOPLOOP ; go do it + 2224 297B 60 rts ; prefix is just fine as it is + 2225 297C DOPLX: + 2226 297C 8E 80 02 stx START_NAME ; just reuse the name + 2227 297F SET_PREFIX START_PREFIX ; and go set it to this one + 2228 297F PRODOS $C6, START_PREFIX + 2229 297F 20 00 BF jsr $BF00 ; ProDOS handler + 2230 2982 C6 DB $C6 ; ProDOS function code + 2231 2983 8629 DW START_PREFIX ; Function Parameter Block address + 2232 2985 .MACEND + 2233 2985 .MACEND + 2234 2985 60 rts + 2235 2986 START_PREFIX: + 2236 2986 01 DB 1 ; just one parm + 2237 2987 8002 DW START_NAME ; use my start up name + 2238 ; + 2239 ; INIT_CHARSET - move the default charset into lower memory + 2240 ; + 2241 2989 ICHARS: + 2242 2989 61 62 63 64 65 db "abcdefghijklmnopqrstuvwxyz" ; CHARSET 1 + 298E 66 67 68 69 6A + 2993 6B 6C 6D 6E 6F + 2998 70 71 72 73 74 + 299D 75 76 77 78 79 + 29A2 7A + 2243 29A3 41 42 43 44 45 db "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; CHARSET 2 + 29A8 46 47 48 49 4A + 29AD 4B 4C 4D 4E 4F + 29B2 50 51 52 53 54 + Tue Jun 13 1989 10:05 Page 47 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 29B7 55 56 57 58 59 + 29BC 5A + 2244 29BD 00 0D 30 31 32 db 0,EOL,"0123456789.,!?_#'""/\-:()" ; CHARSET 3 + 29C2 33 34 35 36 37 + 29C7 38 39 2E 2C 21 + 29CC 3F 5F 23 27 22 + 29D1 2F 5C 2D 3A 28 + 29D6 29 + 2245 004D ICHARSL EQU $-ICHARS-1 + 2246 + 2247 29D7 INIT_CHARSET: + 2248 29D7 AD 34 96 lda ZBEGIN+ZCHRSET ; see if game has passed one + 2249 29DA 0D 35 96 ora ZBEGIN+ZCHRSET+1 ; well? + 2250 29DD D0 0C bne INITCHG ; yes, so use that one + 2251 29DF A2 4D ldx #ICHARSL + 2252 29E1 INITCL: + 2253 29E1 BD 89 29 lda ICHARS,X ; get char + 2254 29E4 9D 8C 1F sta CHARSET,X ; save char + 2255 29E7 CA dex ; next char + 2256 29E8 10 F7 bpl INITCL ; go get it + 2257 29EA 60 rts + 2258 29EB INITCHG: + 2259 29EB AD 34 96 lda ZBEGIN+ZCHRSET ; get game page + 2260 29EE 20 ED 26 jsr SETPC ; find out where in memory it be + 2261 29F1 85 8D sta FPCH ; save page + 2262 29F3 84 8E sty FPCBNK ; and save the bank + 2263 29F5 AD 35 96 lda ZBEGIN+ZCHRSET+1 ; get the LSB + 2264 29F8 85 8C sta FPCL ; just save it + 2265 29FA A9 4E lda #78 ; 78 characters are in it + 2266 29FC 85 7A sta J ; use J as counter + 2267 29FE A9 00 lda #0 ; set up index + 2268 2A00 85 7C sta K ; in K + 2269 2A02 INCGL: + 2270 2A02 20 14 27 jsr FETCHB ; go get the character + 2271 2A05 A6 7C ldx K ; this is index + 2272 2A07 9D 8C 1F sta CHARSET,X ; save game character + 2273 2A0A 20 38 27 jsr NEXTFPC ; point to next character + 2274 2A0D E6 7C inc K ; point to next storage byte + 2275 2A0F C6 7A dec J ; count character + 2276 2A11 D0 EF bne INCGL ; go get next char + 2277 + 2278 2A13 A9 0D lda #EOL ; make sure EOL is in list + 2279 2A15 A2 35 ldx #53 ; offset of 53 + 2280 2A17 9D 8C 1F sta CHARSET,X ; and away it goes + 2281 + 2282 2A1A 60 rts ; done + 2283 2A1B + 2284 2A1B END + 2285 + 2286 + 2287 PAGE + Tue Jun 13 1989 10:05 Page 48 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2288 2A1B STTL "--- BOOT DATA STRUCTURES ---" + 2289 2A1B INTR_OPEN: + 2290 2A1B 03 DB 3 ; 3 parameters + 2291 2A1C 372A DW INTR_NAME ; name of file + 2292 2A1E 0011 DW GAME1FIO ; file data buffer + 2293 2A20 DS 1 ; refnum goes here + 2294 2A21 CLOSE_BLOCK: + 2295 2A21 01 DB 1 ; 1 parameter + 2296 2A22 DS 2 ; room for ref num + 2297 2A24 PSEEK: + 2298 2A24 02 db 2 ; 2 pararmeters + 2299 2A25 00 db 0 ; refnum + 2300 2A26 00 00 00 db 0,0,0 ; 3 byte new file pos + 2301 2A29 PRELOAD_OPEN: + 2302 2A29 03 DB 3 + 2303 2A2A 3F2A DW PRELOAD_NAME + 2304 2A2C 0011 DW GAME1FIO ; close interpreter first! + 2305 2A2E DS 1 ; refnum here + 2306 ; + 2307 ; start with interpreter data + 2308 ; + 2309 2A2F READ_BLOCK: + 2310 2A2F 04 DB 4 ; 4 parms + 2311 2A30 00 DB 0 ; refnum + 2312 2A31 0040 DW INTR_BEGIN ; where to start the interpreter + 2313 2A33 0056 DW INTR_SIZE ; and how big could it be + 2314 2A35 0000 DW 0 ; actual length of interpreter + 2315 2A37 INTR_NAME: + 2316 2A37 07 DB INAME_LEN ; length of name + 2317 2A38 I_NAME: + 2318 2A38 49 4E 46 4F 43 DB "INFOCOM" ; interpreter name + 2A3D 4F 4D + 2319 0007 INAME_LEN EQU $-I_NAME + 2320 + 2321 2A3F PRELOAD_NAME: + 2322 2A3F 00 DB 0 ; length of name + 2323 2A40 PRE_NAME: + 2324 2A40 DS 20 ; spot for preload name + 2325 0014 PRELEN EQU $-PRE_NAME + 2326 2A54 + 2327 DH_SAVE: ; to actual 'write' the data + 2328 2A54 04 DB 4 ; 4 parms for write + 2329 2A55 00 DB 0 ; refnum goes here + 2330 2A56 0000 DW 0 ; just 'copy' junk + 2331 2A58 00B5 DW RAMSAVE ; to preserve this much mem in AUX + 2332 2A5A 0000 DW 0 ; how much is done + 2333 2A5C + 2334 2A5C 54 68 65 20 73 STRYM: DB "The story is loading ..." + 2A61 74 6F 72 79 20 + 2A66 69 73 20 6C 6F + 2A6B 61 64 69 6E 67 + 2A70 20 2E 2E 2E + 2335 0018 STRYML EQU $-STRYM + 2336 2A74 0D 45 6E 74 65 MMSG: DB EOL,"Enter the letter of the pointing",EOL + 2A79 72 20 74 68 65 + 2A7E 20 6C 65 74 74 + 2A83 65 72 20 6F 66 + Tue Jun 13 1989 10:05 Page 49 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT DATA STRUCTURES ---" + + 2A88 20 74 68 65 20 + 2A8D 70 6F 69 6E 74 + 2A92 69 6E 67 0D + 2337 2A96 64 65 76 69 63 DB "device you will be using:",EOL + 2A9B 65 20 79 6F 75 + 2AA0 20 77 69 6C 6C + 2AA5 20 62 65 20 75 + 2AAA 73 69 6E 67 3A + 2AAF 0D + 2338 2AB0 4A 29 6F 79 73 DB "J)oystick M)ouse N)either",EOL,EOL + 2AB5 74 69 63 6B 20 + 2ABA 20 4D 29 6F 75 + 2ABF 73 65 20 20 4E + 2AC4 29 65 69 74 68 + 2AC9 65 72 0D 0D + 2339 0059 MMSGL EQU $-MMSG + 2340 2ACD 0D 45 6E 74 65 MSLT: DB EOL,"Enter the slot number in which the",EOL + 2AD2 72 20 74 68 65 + 2AD7 20 73 6C 6F 74 + 2ADC 20 6E 75 6D 62 + 2AE1 65 72 20 69 6E + 2AE6 20 77 68 69 63 + 2AEB 68 20 74 68 65 + 2AF0 0D + 2341 2AF1 6D 6F 75 73 65 db "mouse card is installed >" + 2AF6 20 63 61 72 64 + 2AFB 20 69 73 20 69 + 2B00 6E 73 74 61 6C + 2B05 6C 65 64 20 3E + 2342 003D MSLTL EQU $-MSLT + 2343 2B0A 0D 53 6C 6F 74 MSLTBAD: DB EOL,"Slot number must be between",EOL + 2B0F 20 6E 75 6D 62 + 2B14 65 72 20 6D 75 + 2B19 73 74 20 62 65 + 2B1E 20 62 65 74 77 + 2B23 65 65 6E 0D + 2344 2B27 4F 4E 45 20 61 db "ONE and SEVEN! Try again!",EOL + 2B2C 6E 64 20 53 45 + 2B31 56 45 4E 21 20 + 2B36 20 54 72 79 20 + 2B3B 61 67 61 69 6E + 2B40 21 0D + 2345 0038 MSLTBADL EQU $-MSLTBAD + 2346 2B42 0D 56 65 72 73 VERMSG: db EOL,"Version: " + 2B47 69 6F 6E 3A 20 + 2347 000A VERMSGL equ $-VERMSG + 2348 2B4C END + + + + Lines Assembled : 2348 Assembly Errors : 0 + + + \ No newline at end of file diff --git a/apple/yzip/rel.15/brel.asm b/apple/yzip/rel.15/brel.asm new file mode 100644 index 0000000..9369bd5 --- /dev/null +++ b/apple/yzip/rel.15/brel.asm @@ -0,0 +1,203 @@ + STTL "--- RELOCATED SUBROUTINES ---" + PAGE + +; +; FETCHB - use FPC to get a byte in either aux or main mem +; +FETCHBx: + sta RDBNK,Y ; set bank, lower + ldy #0 ; gotta use Y + lda (FPC),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; and return +; +; ZFETCH - fetch byte at (ZPCPNT),Y - offset from (ZPCPNT) +; +ZFETCHx: + sta RDBNK,X ; set lower bank + lda (ZPCPNT),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; bye +; +; MFETCH - fetch byte at (MPCPNT),Y - offset from (MPCPNT) +; +MFETCHx: + sta RDBNK,X ; set bank + lda (MPCPNT),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; bye +; +; SAVE_DATA - copy data from [DBUFF] to IOBUFF +; [Y] must == 0; [X] == DSKBNK; [A] == IOBUFF ($8 or $9) +; + sta RDBNK,X ; and select that bank for reading + sta SAVE_DATA+9 ; show which part of iobuff +SDAT1: + lda (DBUFF),Y ; get me that byte +SDAT2: + sta IOBUFF,Y ; MODIFIED ABOVE + iny + bne SDAT1 + sta RDBNK+MAIN ; and back to main + rts +RLCLEN EQU $-FETCHBx-1 ; mark length +; +; COPY_LINE: +; SPC - source pointer +; FPC - destination pointer +; SPCBNK - bank the above two are talking about +; CPY_COUNT - end-start bytes to move +; STMASK - mask to use on first byte (0 if none) +; ENDMASK - mask to use for end byte (0 if none) +; +; MODIFIED CODE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +; The definitions for CPY_MODs are HARD CODED in apple.equ - they MUST +; match the definitions below for similar xCPY_MODs!!!!!!!! +; DON'T CHANGE WITHOUT FIXING THOSE OFFSETS IN APPLE.EQU!!!!! +; +CPYx EQU * + ldx SPCBNK ; set up banks for first byte + lda PAGE2SW,X ; r/w which bank in display mem + ldy #0 ; use Y reg + lda STMASK ; get start mask + beq CPLOOP ; no start mask, start in middle of loop + and (FPC),Y ; turn off changing bits, keep good bits + sta (FPC),Y ; save it + lda STMASK ; get changing bits + eor #$FF ; turn on changing bits + and (SPC),Y ; get SPC byte + ora (FPC),Y ; turn them on in destination too + sta (FPC),Y ; and destiny +CPLOOP: + lda CPY_COUNT ; get count + lsr A ; /2 for number in this bank + tax ; put in X for indexing + beq CPLP2 ; then done! + dex ; zero base the number + lda STMASK ; special start? + beq CPL1 ; nope + inc CPY_MOD1_SRC ; first one already done + inc CPY_MOD1_DST ; point to next one + dex ; and count first one as done +CPL1: + lda SCREEN,X ; get byte + sta SCREEN,X ; store byte + dex ; count down + bpl CPL1 ; and do it all again +CPLP2: + ldy #0 ; reset y + lda SPCBNK ; get current bank + eor #1 ; toggle to point to the other one + tax + lda PAGE2SW,X + txa ; which bank? + beq CPLP21 ; we are now in main, things are fine + inc CPY_MOD2_SRC ; start one more if now in AUX + inc CPY_MOD2_DST + dex ; and count as done +CPLP21: + lda CPY_COUNT ; get count again + lsr A ; /2 for bytes in this bank + tax ; put in X for counter + beq CPDONE ; nothing here + dex ; zero base the number +CPL2: + lda SCREEN,X ; get byte + sta SCREEN,X ; store byte + dex ; count byte + bpl CPL2 ; and swing by again +CPDONE: + lda ENDMASK ; do same mucking as when starting + beq CPEXIT ; no mucking + pha ; save endmask + lda CPY_COUNT ; get how many bytes being copied + lsr A ; /2 + bcc CPDONE1 ; if even, then we are pointing to correct + pha ; save a + ldx SPCBNK ; get original bank + lda PAGE2SW,X ; and point to it + pla ; get it back +CPDONE1: + tay ; get offset + pla ; get end mask back + eor #$FF ; turn on all off bits + and (FPC),Y ; turn off changing bits + sta (FPC),Y ; save it + lda (SPC),Y ; get source byte + and ENDMASK ; turn on changing bits + ora (FPC),Y ; turn them on in destination too + sta (FPC),Y ; and destiny +CPEXIT: + lda PAGE2SW ; set back to main mem + rts +CPYLEN EQU $-CPYx-1 +xCPY_MOD1 equ (CPL1-CPYx+1) +xCPY_MOD1_DST equ xCPY_MOD1+3 +xCPY_MOD2 equ (CPL2-CPYx+1) +xCPY_MOD2_DST equ xCPY_MOD2+3 +PAGE3REL: +; +; MOUSER - this vectors the call to the correct place +; +MOUSERx: + pha ; save A for a sec +MSX1: lda MTABLE,X ; get lo part of address + sta MSVECTOR+LO ; save lo part of address + pla ; get A back + nop +MSX2: ldx #$C4 ; might be changed, depending on slot +MSX3: ldy #$40 ; hopefully, this doesn't + jmp (MSVECTOR) ; and away we go +MSRxLEN EQU $-MOUSERx-1 ; show how long this is +MSVECTORx: + ds 1 ; where lo part of vector goes +MSX4: db $C4 ; slot where mouse is +MSRLEN EQU $-MOUSERx-1 ; length or routine +; +; colors for screen lines +; + RADIX H +COLORSx: + db 00,00,00,00 ; black + db 08,11,22,44 ; magenta + db 44,08,11,22 ; brown + db 4C,19,33,66 ; orange + db 22,44,08,11 ; dark green + db 2A,55,2A,55 ; gray 1 + db 66,4C,19,33 ; green + db 6E,5D,3B,77 ; yellow + db 11,22,44,08 ; dark blue + db 19,33,66,4C ; purple + db 55,2A,55,2A ; gray 2 + db 5D,3B,77,6E ; pink + db 33,66,4C,19 ; medium blue + db 3B,77,6E,5D ; light blue + db 77,6E,5D,3B ; aqua + db 7F,7F,7F,7F ; white +XPOSTBLx: + DB 0 + DB 0,1,1,2,2,3,4 + DB 4,5,5,6,6,7,8 + DB 8,9,9,0a,0a,0b,0c + DB 0c,0d,0d,0e,0e,0f,10 + DB 10,11,11,12,12,13,14 + DB 14,15,15,16,16,17,18 + DB 18,19,19,1a,1a,1b,1c + DB 1c,1d,1d,1e,1e,1f,20 + DB 20,21,21,22,22,23,24 + DB 24,25,25,26,26,27,28 + DB 28,29,29,2a,2a,2b,2c + DB 2c,2d,2d,2e,2e,2f,30 + DB 30,31,31,32,32,33,34 + DB 34,35,35,36,36,37,38 + DB 38,39,39,3a,3a,3b,3c + DB 3c,3d,3d,3e,3e,3f,40 + DB 40,41,41,42,42,43,44 + DB 44,45,45,46,46,47,48 + DB 48,49,49,4a,4a,4b,4c + DB 4c,4d,4d,4e,4e,4f,50 + RADIX D +PAGE3RELL EQU $-PAGE3REL-1 + END + + diff --git a/apple/yzip/rel.15/bsubs.asm b/apple/yzip/rel.15/bsubs.asm new file mode 100644 index 0000000..8dd9d7e --- /dev/null +++ b/apple/yzip/rel.15/bsubs.asm @@ -0,0 +1,584 @@ + PAGE + STTL "--- BOOT CODE SUBROUTINES ---" + +ERRM: DB EOL,EOL + DB "Internal error " +ENUMB: DB "00" + DB "00. " +ERRML EQU $-ERRM +HCHARS: DB "0123456789ABCDEF" +; +; ZERROR: print out error code in HexWord: [A][Y]. +; +ZERROR: + pha ; save [A] + tya ; and put y to a for figgering + ldy #3 ; CONVERT ERROR BYTE IN [A] +ZERR0: + pha + and #%00001111 + tax + lda HCHARS,X + sta ENUMB,Y + pla + LSR A + LSR A + lsr A + lsr A + tax + lda HCHARS,X + dey + sta ENUMB,Y + beq ZR1 ; done + + pla ; done with first number + dey ; and point one more down + jmp ZERR0 ; so work on second number +ZR1: + ldx #ERRM + ldy #ERRML + jsr DLINE ; PRINT ERROR MESSAGE + jsr GETRET ; wait for + jmp ZQUIT + +RETQ: db EOL,"Please insert new disk to boot." + db EOL, "And hit RETURN when ready.",EOL +RETQL EQU $-RETQ +GETRET: + DLINE RETQ ; ask for return +GETRETL: + lda KBD ; get a key + bpl GETRETL ; no key + and #$7f ; make a good key + cmp #EOL ; return key? + bne GETRETL ; nope + jsr MCOUT ; show the + rts + + + ; ---- + ; QUIT + ; ---- + +ZQUIT: + lda INFODOS ; in dinky-dos? + beq ZQUIT2 ; nope + lda #0 ; clear power up byte + sta $3F4 ; make it do cold boot + lda RESET_VECTOR+HI ; now, set up where to die to + sta ZQUITR1+2 + lda RESET_VECTOR+LO + sta ZQUITR1+1 + lda RDROM ; get ROM back +ZQUITR1: + jmp RESET_VECTOR ; just reset things +; +; re-enable /RAM +; +ZQUIT2: + ldx DEVCNT ; put device in at end + inx ; point to one past end + stx DEVCNT ; show new count + lda #$BF ; /RAM ID + sta DEVNUM,X ; save it + lda OLDVEC+HI ; restore old vector + sta RAMVEC+HI + lda OLDVEC+LO + sta RAMVEC+LO +; +; now format /RAM +; + lda #3 ; stash into FORMAT parm block + sta $42 ; it goes here, oddly enough + lda #$B0 ; device id for /RAM + sta $43 ; and here it goes + lda #>GAME1FIO ; IO buffer + sta $45 ; this is where it goes + lda #ZBEGIN ; ADD OFFSET TO GET RAM PAGE + ldy #MAIN ; in the main bank + beq VFEXI ; BRA to fetch +VF2: + cmp #PGBEGIN ; is it paged? + bcs VFERR ; yes it be paged, so can't deal with it + cmp #P3PAGE ; is it in Aux Mem, Part 2? + bcs VF3 ; yes, so subtract different amount +; +; this is in lower aux +; + lda #(Z2PAGE-Z1SIZE) ; subtract size from offset + ldy #AUX ; show aux mem + bne VFEXI ; jump to end +VF3: + lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides + ldy #P3BANK ; show page 3 bank +VFEXI: + clc ; get ready for addition + adc MEMPAGE ; now get actual offset + rts +VFERR: +; +; out of range +; + lda #$22 + jmp ZERROR + +; +; FETCHB - fetch a byte from either main memory, aux memory, or upper +; Aux memory +; +FETCHB: + ldy FPCBNK ; get the bank + bmi FB1 ; must be in upper RAM + jmp ZERO_FB ; go to low end fetch +; +; this is in aux mem, >$E000 +; +FB1: + lda FPCH ; get which page + sta FBMOD+2 ; and show in operand + ldy FPCL ; get which byte + sta ALTZP+AUX ; talk about aux mem + lda BNK1SET ; set up read/write ram in upper mem + lda BNK1SET ; set up read/write ram in upper mem +FBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + ldx RDROM ; now use ROM please + ldx RDROM ; now use ROM please + rts +; +; NEXTFPC - inc DPCL and check for wrapping round to next bank +; +NEXTFPC: + inc FPCL ; next lo byte + bne NXFP_EXIT ; no change then + inc FPCH ; next page + lda FPCH ; and get it for checking + cmp #>PRGLBL ; have we reached end of line? + bne NXFP_EXIT ; we be okay + lda FPCBNK ; get bank + bne NXFP1 ; must skip over stuff in middle + inc FPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta FPCH ; and point to it + rts ; toots finis +NXFP1: + lda #Z3PAGE ; start of part 3 + sta FPCH ; so show me + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey +NXFP_EXIT: + rts +; +; INST_MOUSE - install mouse handler IRQ +; +MFIX1 EQU (MSX1-MOUSERx)+PAGE3STUFF+2 +MFIX2 EQU (MSX2-MOUSERx)+PAGE3STUFF+1 +MFIX3 EQU (MSX4-MOUSERx)+PAGE3STUFF +MFIX4 EQU (MSX3-MOUSERx)+PAGE3STUFF+1 +INST_MOUSE: + jsr FINDMOUSE ; find which slot the mouse is in + bcc INMS1 ; everything is fine + rts ; can't find the mouse +INMS1: + sta MFIX1 + sta MFIX2 + sta MFIX3 ; okay, everyone knows now + and #$0f ; pick up low byte + sta ARG1+LO ; save for program to pick up + asl A ; shift slot number to upper nybble + asl A + asl A + asl A + sta MFIX4 ; and save here +; +; now init mouse, please +; + ldx #INITM ; init first + jsr MOUSER ; so do it + ldx #SETM ; setup mouse + lda #$01 ; transparent mode + jsr MOUSER ; we do that + ldx #CLEARM ; and clear mouse pos + jsr MOUSER ; we did +; +; now set min and max for clamping. +; 0 <= xpos <= 139 +; 0 <= ypos <= 191 +; + lda #0 ; zero out a few of the things + sta CLMPMINH ; hi part of min clamp + sta CLMPMINL ; lo part of min clamp + lda #<137 ; max X + sta CLMPMAXL ; stash in lo part + lda #>137 ; max X + sta CLMPMAXH ; hi part of clamp + lda #0 ; show setting X clamp + ldx #CLAMPM ; do clamping + jsr MOUSER ; okay, we did + lda #<189 ; now for Y + sta CLMPMAXL ; saved in lo part + lda #>189 ; now for Y + sta CLMPMAXH ; saved in lo part + lda #1 ; set y boundries + ldx #CLAMPM ; okay, show which routine + jsr MOUSER ; and do it + +; +; initialize the mouse position +; + lda #0 ; clear MSB + sta MOUSEXH + sta MOUSEYH + lda #MAXHEIGHT + sta MOUSEYL + lda #MAXWIDTH + sta MOUSEXL + + ldx #POSM + jsr MOUSER ; and move it + +; cli ; enable interrupts now + lda #$FF ; < 0 show mouse + sta MOUSEF ; so show it + clc ; show everything is fine + rts ; done +; +; FINDMOUSE - scan the slots for a mouse +; +FINDMOUSE: + lda $C1FB ; check for mouse ID == D6 + cmp #$D6 ; mouse ID + bne FNDM1 ; not it + lda FINDMOUSE+2 ; get slot + clc ; show okay-ness + rts ; and return +FNDM1: + inc FINDMOUSE+2 ; point to next slot + lda FINDMOUSE+2 ; reached last one yet? + cmp #$C8 ; no slot eight + bcc FINDMOUSE ; go look again + sec ; show no mouse + rts +; +; INST_STICK - install the joystick handler +INST_STICK: + lda #$1 ; > 0 show joystick + sta MOUSEF ; okay, we do + clc ; show it worked + rts +RAMINFO: + db 10 ; 10 parms + dw RAMNAME ; name + ds 15 ; room for stuff +RAMNAME: + db 5 ; length of name + db "/RAM/" ; name +RAMQ: db EOL,"This program disables /RAM and it",EOL + db "is not empty. Do you want to" + db EOL,"continue (Y destroys /RAM)?" +RAMQL EQU $-RAMQ +FIXRAM: + GET_FILE_INFO RAMINFO ; get the volumn size + bcs FIXR1 ; problem, so we'll just disable it + + lda RAMINFO+9 ; get amount used + bne ASKUSER ; some files there complain + lda RAMINFO+8 ; get LSB of used + cmp #9 ; if >= 9, must be being used + bcc FIXR1 ; no problem, disable /RAM +ASKUSER: + jsr MHOME ; clear and home + DLINE RAMQ ; ask about continuing + jsr MRDKEY ; get answer + and #$7F ; turn off hi bit + cmp #'y' ; check for yes + beq FIXR1 ; then continue + cmp #'Y' ; also, captital Y + beq FIXR1 ; okay again + jmp ZQUIT ; so die +FIXR1: + lda RAMVEC+LO ; get current /RAM vector + sta OLDVEC+LO ; save it for reinstalling + lda RAMVEC+HI + sta OLDVEC+HI + lda UNSVEC+LO ; point /RAM vector to uninstalled device + sta RAMVEC+LO + lda UNSVEC+HI + sta RAMVEC+HI + ldx DEVCNT ; get how many devices +DEVLP: + lda DEVNUM,X ; try to find /RAM device + and #$70 ; isolate slot + cmp #$30 ; look for slot 3 + beq GOTSLT ; got it + dex ; missed it + bpl DEVLP ; try again + rts ; didn't find it (?) +GOTSLT: + lda DEVNUM+1,X ; now move all down one + sta DEVNUM,X ; down one + cpx DEVCNT ; done yet + beq FIXREX ; ayyup + inx ; point to next slot + bne GOTSLT ; continue on +FIXREX: + dec DEVCNT ; one less device, thank you + rts ; all done +; +; DO_DSEGS - scan through the disk segment table and point to the +; beginning of the segment list for each of the disks in the +; file. +DO_DSEGS: + lda SEGTBL+SGTDISKS+1 ; get # number disks + sta J ; save in counter + dec J ; we hand hold #1 + lda #>(SEGTBL+SGTCHKS1) ; start off at beginning + sta D1SEG+HI ; here is first one + lda #<(SEGTBL+SGTCHKS1); and here is LSB + sta D1SEG+LO ; save it + ldy SEGTBL+SGTSEG1+1 ; get number of segs in first disk + ldx #2 ; start at second one +DODSL: + lda DSKSEG-2+LO,X ; get LSB of previous start + clc ; doing some adding + adc #SGTSEG ; point to start of segment list + sta DSKSEG+LO,X ; save in working segment pointer + lda DSKSEG-2+HI,X ; now work on MSB + adc #0 ; pick up possible carry + sta DSKSEG+HI,X ; and save in new pointer +ADDLOOP: + clc ; doing add + lda #6 ; size of segment entry + adc DSKSEG+LO,X ; counting + sta DSKSEG+LO,X ; counting + bcc ADDL1 ; no wrap + inc DSKSEG+HI,X ; add one to hi +ADDL1: + dey ; count segment + bne ADDLOOP ; okay, not done yet + lda DSKSEG+LO,X ; get pointer to #segs in this one + sta DSEGS+LO ; save ptr + lda DSKSEG+HI,X ; get MSB + sta DSEGS+HI ; save ptr + ldy #SGTNSEG+1 ; just need LSB + lda (DSEGS),Y ; get #segs in this segment + tay ; save in counter Y + inx + inx ; point to new pointer loc + dec J ; count this disk + bne DODSL ; and do it again +; +; now, init DSEGS to point to beginnning again +; + lda D1SEG+HI ; here is first one + sta DSEGS+HI + lda D1SEG+LO ; save it + sta DSEGS+LO +; +; check to see if we are using infoDOS, and set pointer to second +; disk segment table if we are. +; + lda KVERSION ; get "version" number + cmp #INFODOS_ID ; is in our DOS? + bne DODX ; nope, it ain't + lda D2SEG+HI ; then have infoDOS flag to point + sta INFODOS+HI ; to the D2SEG, cuz that's what + lda D2SEG+LO ; we use to check all the ZPC's + sta INFODOS+LO + rts +DODX: + lda #0 ; regular ProDOS + sta INFODOS ; show nothing there! + rts + +; +; INITPAG - init the paging buffers, thank you +; +INITPAG: + LDX #NUMBUFS-1 ;*** + STX CURRENT ; make last one first one to be used + dec CURRENT ; using only even pages + LDA #$FF +INILP: + STA VPAGEH,X + DEX + BPL INILP + LDX #0 + LDY #2 ;*** +INILP2: + TYA + STA PREVPNT,X + INX + inx ;*** + INY + iny ;*** + CPX #NUMBUFS + BCC INILP2 + LDA #00 + DEX + dex ;*** + STA PREVPNT,X + LDX #0 ;*** + LDY #$FE ;*** + LDA #NUMBUFS-2 ;*** +INILP3: + STA NEXTPNT,X + INX + inx ;*** + iny ;*** + INY + TYA + CPX #NUMBUFS + BCC INILP3 + rts + +; +; DO_PREFIX - check out the program name at $280. If there is a prefix +; in there, just set prefix to it, so my default prefix is just fine. +; +DO_PREFIX: + ldx START_NAME ; get length of name +DOPLOOP: + lda START_NAME,x ; get char + and #$7F ; make it real ASCII + cmp #'/' ; directory seperator? + beq DOPLX ; yup, found the prefix + dex ; previous char + bne DOPLOOP ; go do it + rts ; prefix is just fine as it is +DOPLX: + stx START_NAME ; just reuse the name + SET_PREFIX START_PREFIX ; and go set it to this one + rts +START_PREFIX: + DB 1 ; just one parm + DW START_NAME ; use my start up name +; +; INIT_CHARSET - move the default charset into lower memory +; +ICHARS: + db "abcdefghijklmnopqrstuvwxyz" ; CHARSET 1 + db "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; CHARSET 2 + db 0,EOL,"0123456789.,!?_#'""/\-:()" ; CHARSET 3 +ICHARSL EQU $-ICHARS-1 + +INIT_CHARSET: + lda ZBEGIN+ZCHRSET ; see if game has passed one + ora ZBEGIN+ZCHRSET+1 ; well? + bne INITCHG ; yes, so use that one + ldx #ICHARSL +INITCL: + lda ICHARS,X ; get char + sta CHARSET,X ; save char + dex ; next char + bpl INITCL ; go get it + rts +INITCHG: + lda ZBEGIN+ZCHRSET ; get game page + jsr SETPC ; find out where in memory it be + sta FPCH ; save page + sty FPCBNK ; and save the bank + lda ZBEGIN+ZCHRSET+1 ; get the LSB + sta FPCL ; just save it + lda #78 ; 78 characters are in it + sta J ; use J as counter + lda #0 ; set up index + sta K ; in K +INCGL: + jsr FETCHB ; go get the character + ldx K ; this is index + sta CHARSET,X ; save game character + jsr NEXTFPC ; point to next character + inc K ; point to next storage byte + dec J ; count character + bne INCGL ; go get next char + + lda #EOL ; make sure EOL is in list + ldx #53 ; offset of 53 + sta CHARSET,X ; and away it goes + + rts ; done + + END + diff --git a/apple/yzip/rel.15/bugger.asm b/apple/yzip/rel.15/bugger.asm new file mode 100644 index 0000000..bde7b6e --- /dev/null +++ b/apple/yzip/rel.15/bugger.asm @@ -0,0 +1,257 @@ + PAGE + SBTTL "--- DEBUGGER: APPLE ---" + + ; -------------- + ; APPLE DEBUGGER + ; -------------- + + ; ENTRY: BREAKPOINT ID IN [A] + + ; SMALL DEBUGGER DBG1 (CONVERTS) DBG2 (JUST DISPLAYS) [A] + +DLCNT: DB 0 + +DBG1: + INC DLCNT + BNE DBG1m + PHA + JSR GETKEY + PLA +DBG1m: + PHA + LSR A + LSR A + LSR A + LSR A + JSR NIB1 + PLA + +NIB1: AND #%00001111 + TAY + LDA HCHARS,Y + JSR MCOUT + RTS + +DBG2: +; CMP #' ' +; BEQ DBG3 +; JSR MCOUT +; LDA #' ' +DBG3: JSR MCOUT + RTS + +HCHARS: DB "0123456789ABCDEF" + + END + +BLINE: DB "B: OP: PC: S: V: 1: 2: 3: 4: 5: 6: 7: 8: 9: " + DB EOL +BLINL EQU $-BLINE + +BUGLIN EQU LSTLNE + +DOBUG: LDX KBD ; WAS CTRL-S PRESSED? + CPX #$13 + BNE DO1 + RTS ; YES, SO LEAVE + +DO1: CMP #0 + BEQ BUGIT + RTS + + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + +BUGIT: LDX #2 ; INIT "CURSOR" + 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 BLINE,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 [ZSP] + LDA ZSP + JSR HEX + + LDX #29 ; CURSOR FOR [MPC] + LDA MPCH + JSR HEX + LDA MPCM + JSR HEX + LDA MPCL + JSR HEX + + LDX #38 + LDA BONE + JSR HEX + + LDX #43 + LDA BTWO + JSR HEX + + LDX #48 + LDA BTHREE + JSR HEX + + LDX #53 + LDA BFOUR + JSR HEX + + LDX #58 + LDA BFIVE + JSR HEX + + LDX #63 + LDA BSIX + JSR HEX + + LDX #68 + LDA BSEVEN + JSR HEX + + LDX #73 + LDA BEIGHT + JSR HEX + + LDX #78 + LDA BNINE + JSR HEX + +; TO SEND TO PRINTER IF WANTED +; LDA CSW+LO +; PHA +; LDA CSW+HI +; PHA +; LDA EH +; PHA +; LDA ALTCSW+LO +; STA CSW+LO +; LDA ALTCSW+HI +; STA CSW+HI +; +; LDA PSTAT +; BNE PPP +; +; LDA #$C1 +; STA CSW+HI +; LDA #$00 +; STA CSW+LO +; +; LDA #$89 +; JSR MCOUT +; LDA CSW+HI +; STA ALTCSW+HI +; LDA CSW+LO +; STA ALTCSW+LO +; LDA #$B8 +; JSR MCOUT +; LDA #$B0 +; JSR MCOUT +; LDA #$CE +; JSR MCOUT +; LDA #$8D +; JSR MCOUT + +PPP: LDX #2 +DBUG1: LDA BLINE,X ; PRINT DEBUGGER TEXT +; JSR MCOUT + JSR CHAR + INX + CPX #BLINL + BCC DBUG1 + +; PLA +; STA EH +; PLA +; STA CSW+HI +; PLA +; STA CSW+LO + +; BIT KBD +; BPL LETEX ; NO KEY PRESSED + + BIT ANYKEY ; CLEAR IT +BUGWAT: BIT KBD ; WAIT FOR A KEY + BPL BUGWAT + + LDA KBD + CMP #$8D + BNE LETEX + BRK + +LETEX: BIT ANYKEY ; CLEAR FOR NEXT ONE + 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 + ORA #%10000000 + STA BLINE,X + INX + RTS + +HCHARS: DB "0123456789ABCDEF" + +BONE: DB 0 +BTWO: DB 0 +BTHREE: DB 0 +BFOUR: DB 0 +BFIVE: DB 0 +BSIX: DB 0 +BSEVEN: DB 0 +BEIGHT: DB 0 +BNINE: DB 0 + + END + + \ No newline at end of file diff --git a/apple/yzip/rel.15/dispatch.asm b/apple/yzip/rel.15/dispatch.asm new file mode 100644 index 0000000..17f2bcc --- /dev/null +++ b/apple/yzip/rel.15/dispatch.asm @@ -0,0 +1,281 @@ + PAGE + STTL "--- OPCODE DISPATCH TABLES ---" + + + ; 0-OPS + +OPT0H: DB >ZRTRUE ;B0 + DB >ZRFALS ;B1 + DB >ZPRI ;B2 + DB >ZPRR ;B3 + DB >ZNOOP ;B4 + DB >OSAVE ;B5 + DB >OREST ;B6 + DB >ZSTART ;B7 + DB >ZRSTAK ;B8 + DB >ZCATCH ;B9 + DB >ZQUIT ;BA + DB >ZZCRLF ;BB + DB >ZUSL ;BC + DB >ZVER ;BD + DB >ZEXTOP ;BE + DB >ZORIG ;BF + +OPT0L: DB ZZERO ;80,90,A0 + DB >ZNEXT ;81 + DB >ZFIRST ;82 + DB >ZLOC ;83 + DB >ZPTSIZ ;84 + DB >ZINC ;85 + DB >ZDEC ;86 + DB >ZPRB ;87 + DB >ZCALL1 ;88 (EZIP) + DB >ZREMOV ;89 + DB >ZPRD ;8A + DB >ZRET ;8B + DB >ZJUMP ;8C + DB >ZPRINT ;8D + DB >ZVALUE ;8E + DB >ZICLL1 ;8F + +OPT1L: DB BADOP2 ;00 (UNDEFINED) + DB >ZEQUAL ;01 + DB >ZLESS ;02 + DB >ZGRTR ;03 + DB >ZDLESS ;04 + DB >ZIGRTR ;05 + DB >ZIN ;06 + DB >ZBTST ;07 + DB >ZBOR ;08 + DB >ZBAND ;09 + DB >ZFSETP ;0A + DB >ZFSET ;0B + DB >ZFCLR ;0C + DB >ZSET ;0D + DB >ZMOVE ;0E + DB >ZGET ;0F + DB >ZGETB ;10 + DB >ZGETP ;11 + DB >ZGETPT ;12 + DB >ZNEXTP ;13 + DB >ZADD ;14 + DB >ZSUB ;15 + DB >ZMUL ;16 + DB >ZDIV ;17 + DB >ZMOD ;18 + DB >ZCALL2 ;19 (EZIP) + DB >ZICLL2 ;1A + DB >ZCOLOR ;1B + DB >ZTHROW ;1C + DB >BADOP2 ;1D + DB >BADOP2 ;1E + DB >BADOP2 ;1F + +OPT2L: DB ZCALL ;E0 + DB >ZPUT ;E1 + DB >ZPUTB ;E2 + DB >ZPUTP ;E3 + DB >ZREAD ;E4 + DB >ZPRC ;E5 + DB >ZPRN ;E6 + DB >ZRAND ;E7 + DB >ZPUSH ;E8 + DB >ZPOP ;E9 + DB >ZSPLIT ;EA + DB >ZSCRN ;EB + + ; (EZIPS FROM HERE ON) + DB >ZXCALL ;EC + DB >ZCLR ;ED + DB >ZERASE ;EE + DB >ZCURST ;EF + DB >ZCURGT ;F0 + DB >ZLIGHT ;F1 + DB >ZBUFOUT ;F2 + DB >ZDIRT ;F3 + DB >ZDIRIN ;F4 (NOT IMPLEMENTED) + DB >ZSOUND ;F5 + DB >ZINPUT ;F6 + DB >ZINTBL ;F7 + DB >ZBCOM ;F8 + DB >ZICALL ;F9 + DB >ZIXCLL ;FA + DB >ZLEX ;FB + DB >ZWSTR ;FC + DB >ZCOPYT ;FD + DB >ZPRNTT ;FE + DB >ZASSND ;FF + +OPTXL: DB ZSAVE ;100 + DB >ZREST ;101 + DB >ZSHIFT ;102 + DB >ZASHFT ;103 + DB >ZFONT ;104 + DB >ZDISPL ;105 + DB >ZPICNF ;106 + DB >ZDCLR ;107 + DB >ZMARG ;108 + DB >ZISAVE ;109 + DB >ZIREST ;10A + DB >BADEXT ;10B - NOT USED + DB >BADEXT ;10C - NOT USED + DB >BADEXT ;10D - NOT USED + DB >BADEXT ;10E - NOT USED + DB >BADEXT ;10F - NOT USED + DB >ZWINPOS ;110 + DB >ZWINSIZE ;111 + DB >ZWINATTR ;112 + DB >ZWINGET ;113 + DB >ZSCROLL ;114 + DB >ZFSTACK ;115 + DB >ZMINFO ;116 + DB >ZMLIMIT ;117 + DB >ZXPUSH ;118 + DB >ZWINPUT ;119 + DB >ZPRINTF ;11A + DB >ZMENU ;11B + DB >ZPICSET ;11c + +EXTLEN EQU $-EXTOPH + +EXTOPL: DB + lda INFODOS ; in dinky-dos? + beq ZQUIT2 ; nope + lda #0 ; clear power up byte + sta $3F4 ; make it do cold boot + lda RESET_VECTOR+HI ; now, set up where to die to + sta ZQUITR1+2 + lda RESET_VECTOR+LO + sta ZQUITR1+1 + lda RDROM ; get ROM back +ZQUITR1: + jmp RESET_VECTOR ; just reset things +; +; re-enable /RAM +; +ZQUIT2: + ldx DEVCNT ; put device in at end + inx ; point to one past end + stx DEVCNT ; show new count + lda #$BF ; /RAM ID + sta DEVNUM,X ; save it + lda OLDVEC+HI ; restore old vector + sta RAMVEC+HI + lda OLDVEC+LO + sta RAMVEC+LO +; +; now format /RAM +; + lda #3 ; stash into FORMAT parm block + sta $42 ; it goes here, oddly enough + lda #$B0 ; device id for /RAM + sta $43 ; and here it goes + lda #>GAME1FIO ; IO buffer + sta $45 ; this is where it goes + lda #BOOTNAME + sta OPEN_FILE+OP_PATHNAME+HI + lda #'1' ; set disk name to disk #1 + sta SAVENUM ; show open_gamef + jsr OPEN_GAMEF ; okay + + lda OPEN_FILE+OP_REFNUM ; get ref num + sta BOOT_RD+RD_REFNUM ; save ref num + sta CLOSE_PB+CL_REFNUM + READ BOOT_RD ; read in boot system + bcc ZSTRTX ; okay, everything is fine + jmp DISK_FATAL ; die otherwise +ZSTRTX: + CLOSE CLOSE_PB ; and close it up + jmp BORG ; and go to it + + ; -------------------------------- + ; RETURN RANDOM BYTES IN [A] & [X] + ; -------------------------------- +RANDOM: + inc RAND+HI + dec RAND+LO + lda RAND+LO ; get LSB + adc RAND+HI ; add MSB + and #$7F ; don't let it go into $C0 page + sta RAND+HI ; new MSB + tay ; get random offset + lda (RAND),Y ; get random number + tax ; save in X + adc RAND+LO ; and go to another spot + and #$7F ; don't go above $80 + sta RAND+HI ; okay + tay ; more randomness + lda (RAND),Y ; and get it again + ora RAND+HI ; set more bits + rts + + + ; ------------------- + ; Z-PRINT A CHARACTER + ; ------------------- + ; ENTRY: ASCII CHAR IN [A] + ; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, + ; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN + ; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME + ; (DIROUT CHANGES 6/24/85) + +COUT: + sta IOCHAR ; HOLD IT A SEC + ldx TABLEF ; OUTPUT TO TABLE? + beq COUT1 ; NO + ldx FMTTBL ; formatted table? + bne COUT5 ; yes, so just do it normal + jmp TBLOUT ; just put into table +COUT1: + ldx SCREENF ; OUTPUT TO SCREEN? + bne COUT5 ; YES + ldx SCRIPTF ; OUTPUT TO PRINTER? + bne COUT5 ; YES + rts ; NO, SO DONE +COUT5: + lda IOCHAR ; RETRIEVE CHAR + bmi COUT2 ; highlight chars have no width +; +; this is an entry point for DLINE, so it doesn't check any of the above +; things. Enter with character in [A] +; +DIRECT_OUT: + cmp #EOL ; IF ASCII EOL, just handle it special + bne COUT0 + + jmp ZCRLF ; DO IT +COUT0: + bcs COUT02 ; not control character + cmp #EOS ; control-k (end of sentence)? + beq COUT01 ; yes, so put out 2 spaces + cmp #TAB ; tab char? + bne CEX ; ignore all other control chars +; +; this means do a couple of spaces +; + lda #SPACE ; do 3 spaces for start of line + jsr COUT ; a little recursion never hurt! + ldx CHRCNT ; back to beginning of line? + bne COUT01 ; nope +COUT010: + rts ; don't do any to start line +COUT01: + lda #SPACE ; 2 more spaces + jsr COUT + ldx CHRCNT ; back to zero? + beq COUT010 ; yes, so don't add to start of line + + lda #SPACE ; last one + jmp COUT ; finally +COUT02: + tax ; use char as index + lda FONTFLG ; get which font we be using + beq COUTF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne COUTF2 ; okay, now do add +COUTF1: + lda CHWID,X ; get width of char +COUTF2: + clc ; get ready for add + adc LENGTH+LO ; ADD LINE LENGTH COUNTER + sta LENGTH+LO ; update length + bcc COUT0C ; no wrap + inc LENGTH+HI ; okay, wrap then +COUT0C: + lda LENGTH+HI ; get MSB + cmp XSIZE+HI ; check MSB first + bcc COUT2 ; no need to check lsb + bne COUT00 ; XSIZE < LENGTH? + + lda LENGTH+LO ; check LSB + cmp XSIZE+LO ; END OF SCREEN LINE? + bcc COUT2 ; haven't reached the end if XSIZE >= LENGTH + beq COUT2 ; okay +COUT00: + ldy WRPFLG ; are we wrapping + beq CEX ; no, so truncate + ldx CHRCNT ; get character count + lda IOCHAR ; get the character + sta LBUFF,X ; save current char in buffer + jmp FLUSH ; YES, FLUSH THE LINE +COUT2: + ldx CHRCNT ; GET LINE POINTER + lda IOCHAR ; get char back + sta LBUFF,X ; ADD CHAR TO BUFFER + inc CHRCNT ; and point to next CHRCNT +CEX: + rts + + ; --------------- + ; OUTPUT TO TABLE + ; --------------- +; +; this one just puts a char into the table +; +TBLOUT: + tax ; HOLD CHAR A SEC. +; +; figger out length of line in there +; + lda FONTFLG ; get which font we be using + beq TBLOUT1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne TBLOUT2 ; okay, now do add +TBLOUT1: + lda CHWID,X ; get width of char +TBLOUT2: + clc ; add width + adc ZBEGIN+ZTWIDTH+1 ; to current line width + sta ZBEGIN+ZTWIDTH+1 ; save current width + bcc TBLOUT3 ; no wrap + inc ZBEGIN+ZTWIDTH+0 ; wrap, then dammit +TBLOUT3: +; +; PUT BYTE IN TABLE AT CURRENT OFFSET +; + lda DIRITM+LO ; ADD IN OFFSET + clc + adc DIRTBL+LO + sta SPCL ; and make it lo part + lda DIRITM+HI + adc DIRTBL+HI + jsr SETPC ; set the PC + sta SPCH ; and this is high part + sty SPCBNK ; and the bank + txa ; PICK UP ASCII CHAR + jsr STASHB ; and save it +; +; SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER +; + inc DIRITM+LO ; INC OFFSET TO NEXT BYTE + bne TBLRTS + inc DIRITM+HI +TBLRTS: + rts +; +; PUT LBUFF IN TABLE AT CURRENT OFFSET +; +TBLRTN: + lda DIRITM+LO ; get where we are + clc + adc DIRTBL+LO ; add in offset + sta SPCL ; and make it lo part + sta FPCL ; save for later usage + lda DIRITM+HI ; get hi part + adc DIRTBL+HI + jsr SETPC ; set the PC + sta SPCH ; and this is high part + sta FPCH ; saving + sty SPCBNK ; and the bank + sty FPCBNK ; and here too + lda #0 ; start counter off at zero + sta J ; use J + sta K+HI ; this will be line length + sta K+LO ; both parts, please + jsr NEXTSPC ; point past the (word) counter + jsr NEXTSPC ; point past the counter +TBLOOP: + ldy J ; get offset + lda LBUFF,Y ; get char + tax ; save char + bmi TBLP1 ; don't count hi light chars + cmp #SPACE ; see if less than a space + bcc TBLP1 ; no width if <$20 + tax ; use char as index + + lda FONTFLG ; get which font we be using + beq TBLF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne TBLF2 ; okay, now do add +TBLF1: + lda CHWID,X ; get width of char +TBLF2: + clc ; add width + adc K+LO ; to current line width + sta K+LO ; save current width + bcc TBLP1 ; no wrap + inc K+HI ; wrap, then dammit +TBLP1: + txa ; get char back + jsr STASHB ; and save it + jsr NEXTSPC ; next table entry + inc J ; point to next char + dec CHRCNT ; decrement counter + bne TBLOOP ; get next one +; +; now fill with necessary spaces +; + lda FONTFLG ; first, set up width to be added + beq TBLSPF1 ; must be variable width font + lda #MONOFONT_W ; get mono width + bne TBLSPF2 ; okay +TBLSPF1: + ldx #SPACE ; get space index + lda CHWID,X ; okay +TBLSPF2: + sta ARG8 ; use temporarily +TBLSP: + lda K+LO ; get how big line is + clc ; add in space + adc ARG8 ; pick up space width + sta K+LO ; saved + bcc TBLSP1 ; no wrap? + inc K+HI ; yes, wrapping +TBLSP1: + lda XSIZE+HI ; check against end + cmp K+HI ; compare against max width + bcc TBLSPX ; all done then + bne TBLSP2 ; no need to check if <> + lda XSIZE+LO ; check LSB + cmp K+LO ; well? + bcc TBLSPX ; all done then +TBLSP2: + lda #SPACE ; get it + jsr STASHB ; save it + jsr NEXTSPC ; point to next one + inc J ; count it + bne TBLSP ; and continue +TBLSPX: + lda #0 ; show end of table + sta LENGTH+LO ; clear out line length too + sta LENGTH+HI ; and hi part too + jsr STASHB ; marked with a zero + jsr NEXTSPC ; point to LSB of next count + lda #0 ; and stash another zero there + jsr STASHB ; away it goes + jsr FP2SP ; have SPC point to beginning + lda #0 ; upper byte of count is zero + jsr STASHB ; show it + jsr NEXTSPC ; point to LSB + lda J ; get how many chars are there + jsr STASHB ; save at beginning of line + inc J ; count (word) counter in offset + inc J ; count counter in offset + lda J ; get J back + clc ; add in where we were + adc DIRITM+LO ; okay with lo part + sta DIRITM+LO ; save it + lda DIRITM+HI ; and now the hi part + adc #0 ; pick up carry, maybe + sta DIRITM+HI ; and save it + rts + + ; ------------------- + ; FLUSH OUTPUT BUFFER + ; ------------------- + ; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: + txa ; is it zero? + bne FL00 ; nope + rts ; just ignore if only one character +FL00: + lda #SPACE ; SPACE CHAR + stx OLDEND ; SAVE CURRENT END OF LINE +FL0: + cmp LBUFF,X ; FIND LAST SPACE CHAR + beq FL1 ; IN THE LINE + dex + bne FL0 ; IF NONE FOUND, + ldx CHRCNT ; FLUSH ENTIRE LINE + dex ; minus last one +FL1: + stx OLDLEN ; SAVE OLD LINE POS HERE + stx CHRCNT ; MAKE IT THE NEW LINE LENGTH + + lda TABLEF ; are we doing table I/O? + beq FL11 ; nope + jsr TBLRTN ; YES, DO IT + jmp FL12 ; so refill line +FL11: + jsr ZCRLF ; PRINT LINE UP TO LAST SPACE +; +; START NEW LINE WITH REMAINDER OF OLD +; +FL12: + ldx OLDLEN ; GET OLD LINE POS + ldy #0 ; START NEW LINE AT BEGINNING +FL2: + inx + cpx OLDEND ; CONTINUE IF + bcc FL3 ; INSIDE of end of line + beq FL3 ; or at end of line + sty CHRCNT + rts +FL3: + lda LBUFF,X ; GET CHAR FROM OLD LINE + cmp #SPACE ; don't move start spaces in either + beq FL4 ; fine, I won't + sta LBUFF,Y ; MOVE TO START OF NEW LINE + bmi FL4 ; don't count hi light chars + cmp #SPACE ; don't count control chars + bcc FL4 ; okay + txa ; save current x + pha ; saved + lda FONTFLG ; get which font we be using + beq FLSF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne FLSF2 ; okay, now do add +FLSF1: + lda LBUFF,X ; get char back + tax ; make index + lda CHWID,X ; get width of char +FLSF2: + clc ; get ready for add + adc LENGTH+LO ; okay, now add char width + sta LENGTH+LO ; save new length + pla ; get old X back + tax ; okay + bcc FL4 ; no wrap + inc LENGTH+HI +FL4: + iny ; UPDATE # OF chars in NEW LINE + bne FL2 ; (ALWAYS) + + + ; --------------- + ; CARRIAGE RETURN + ; --------------- + +ZZCRLF: + ldx TABLEF ; OUTPUT TO TABLE? + beq ZCRLF ; NO +; +; if putting a into table, just add to line buffer and flush +; + lda #EOL ; get carriage return char + ldy CHRCNT ; add to lbuff + sta LBUFF,Y ; got it + inc CHRCNT ; now flush it + jsr TBLRTN ; YES, DO IT (TBL ONLY) + jmp ZCRLFX ; git out +ZCRLF: + ldx CHRCNT ; how far have we gone + lda #EOL ; get carriage return char + sta LBUFF,X ; END OF CURRENT LINE + inc CHRCNT ; UPDATE LINE LENGTH + jsr LINOUT ; DISPLAY LINE + +; +; now check about line count +; + lda #0 + sta CHRCNT ; AND RESET LINE COUNT + sta LENGTH+LO ; okay + sta LENGTH+HI ; okay + + jsr CHKFNC ; CHECK FOR CR FUNCTION (XZIP) + + lda SCREENF ; CHECK IF DISPLAYING TO SCREEN + beq ZCRLFX ; NO, GO HANDLE IF PRINTING + lda SCRLFLG ; is it a scrolling window? + beq ZCRLFX ; nope, so no more + inc LINCNT ; NEW LINE GOING OUT + + ldx LINCNT ; IS IT TIME TO + cpx MAXLINES ; PRINT "MORE" YET? + bcc ZCRLFX ; NO, CONTINUE + + lda #1 ; leave one line from last screen, and input line + sta LINCNT ; RESET LINE COUNTER + lda LEFTMRG ; SET LEFT MARGIN + sta SCRCX + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay +; +; print [MORE] out myself, to avoid re-entrancy problems +; + lda SCRIPTF ; make sure we don't script + pha + ldx #0 ; start with first char + stx SCRIPTF ; clear script flag + stx SCLLINES ; use this as a counter +MORELOOP: + lda MORE,X ; get char + sta IOCHAR ; save it + jsr DIRECT_OUT ; pump it out there + inc SCLLINES ; count char + ldx SCLLINES ; how many have we done + cpx #MOREL ; done? + bne MORELOOP ; nope + + jsr CLRBUF ; make sure it shows +WAIT: + jsr GETKEY ; wait for key please + lda #MOREL-1 ; how many backspaces + sta LENGTH ; just use this as counter +WM11: + ldx LENGTH ; which char? + lda MORE,X ; get char + tax ; put here for erase + lda #BACKSPACE ; erase char + jsr CHAR + dec LENGTH ; count it + bpl WM11 + pla ; get script flag back + sta SCRIPTF ; fine + lda LEFTMRG ; move back to left margin + sta SCRCX ; okay + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay +ZCRLFX: + lda #0 + sta CHRCNT ; AND RESET LINE COUNT + sta LENGTH+LO ; okay + sta LENGTH+HI + rts +LINOUT: + ldy CHRCNT ; IF BUFFER EMPTY, + beq LINEX ; DON'T PRINT ANYTHING + sty PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + lda SCREENF ; DISPLAY TO SCREEN? + bne LOUT0 ; yes, so do it + lda FMTTBL ; formatted table? + beq LOUT1 ; check scripting + jmp TBLRTN ; flush to table +LOUT0: + ldx #0 ; SEND CONTENTS OF [LBUFF] +LOUT: + lda LBUFF,X ; TO SCREEN + jsr CHAR + inx + dey + bne LOUT + jsr DISP_LINE ; make sure line gets printed +LOUT1: JSR PPRINT ; PRINT [LBUFF] IF ENABLED +LINEX: + rts ; AND RETURN +; +; CHECK IF THERE IS A PENDING FUNCTION CALL ASSOCIATED WITH 'S +; +CHKFNC: + ldy #WINCRC+HI ; get function offset + lda (WINDOW),Y ; IF NULL IGNORE + dey ; point to lo part + ora (WINDOW),Y + beq CHKOUT + + lda CRLF_CHECK ; do we really want to do this? + beq CHKOUT ; nope + + lda (WINDOW),Y ; DECR COUNTER + sec + sbc #1 + sta (WINDOW),Y + iny + lda (WINDOW),Y ; work on hi part + sbc #0 ; pick up carry + sta (WINDOW),Y ; save it + dey + ora (WINDOW),Y ; if NULL NOW, CALL FCN + bne CHKOUT + + ldy #WINCRF+LO ; pointing to routine + lda (WINDOW),Y ; get lo part + sta J+LO ; and save in J + iny ; point to hi part + lda (WINDOW),Y ; got it + sta J+HI + jsr INTCLL ; DO FUNCTION CALL +CHKOUT: + rts + + + ; ---------------------- + ; UPDATE THE STATUS LINE + ; ---------------------- + ; NOT APPLICABLE IN EZIP. + +ZUSL: RTS + +; ------ +; BUFOUT +; ------ +; ENTER: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE +; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO +; +; shouldn't need this in YZIP ?! +; +ZBUFOUT: +; +; CLEAR OUTPUT BUFFER BEFORE DOING ANYTHING FANCY +; +CLRBUF: + jsr LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) + ldx #0 + stx CHRCNT + rts + + ; ------ + ; DIROUT + ; ------ + ; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT + ; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT + ; MULTIPLE DEVICE USAGE IS POSSIBLE. + +SAVEXSIZE: db 0,0 ; for formatted table saving + +ZDIRT: + jsr CLRBUF ; send out anything there now! + + ldx ARG1+LO + bmi DIRRES ; NEGATIVE VALUE, DESELECTING + dex + beq DIR1 ; 1 = SET OUTPUT TO SCREEN + dex + beq DIR2 ; 2 = SCRIPTING + dex + beq DIR3 ; 3 = TABLE + rts ; INVALID VALUE +DIRRES: + inx + beq DRES1 ; -1 = RESET TO SCREEN + inx + beq DRES2 + inx + beq DRES3 + rts ; INVALID VALUE, JUST LEAVE +DIR1: + jsr CLRBUF + lda #1 ; turn screen on + sta SCREENF + rts +DRES1: + jsr CLRBUF + lda #0 + sta SCREENF ; 0, TURN SCREEN OFF + rts +DIR2: + inx + stx SCRIPTF ; SET SCRIPT FLAG ON + lda ZBEGIN+ZFLAGS+1 ; SET GAME FLAG ALSO + ora #%00000001 + sta ZBEGIN+ZFLAGS+1 + lda PSTAT ; CHECK IF PRINTER ALREADY INIT'D + bne DIR2A + jsr PCHK ; NO, GO DO IT +DIR2A: + rts ; YES, READY TO LEAVE +DRES2: + stx SCRIPTF ; TURN PRINTER OFF + lda ZBEGIN+ZFLAGS+1 ; AND TURN OFF GAME FLAG TOO + and #%11111110 + sta ZBEGIN+ZFLAGS+1 + rts +DIR3: + stx SCREENF ; turn off screen + inx + stx TABLEF ; TURN TABLE OUTPUT FLAG ON + jmp START_TABLE ; and set things up +DRES3: + lda TABLEF ; IF OFF ALREADY + beq OUT3 ; LEAVE AS IS + + stx TABLEF ; TURN TBL OUTPUT OFF + inx ; turn screen back on + stx SCREENF ; screen back on + + lda #3 ; add three to make it wrap + clc ; ready for add + adc ZBEGIN+ZTWIDTH+1 ; do it + sta ZBEGIN+ZTWIDTH+1 + bcc DRESCC ; no wrap into MSB + inc ZBEGIN+ZTWIDTH +DRESCC: + lsr ZBEGIN+ZTWIDTH+0 ; /4 to get # of pixels + ror ZBEGIN+ZTWIDTH+1 + lsr ZBEGIN+ZTWIDTH+0 + ror ZBEGIN+ZTWIDTH+1 + + + lda FMTTBL ; did we do a formatted table? + bne DRESFT ; yes, so fix things +; +; not formatted table, so put count into table +; + lda DIRTBL+LO ; and put count into second byte of table + sta SPCL ; points to low par + lda DIRTBL+HI ; get page + jsr SETPC ; okay, page and bank + sta SPCH + sty SPCBNK + lda DIRITM+LO ; (2 LESS THAN [DIRITM]) + sec + sbc #2 + sta DIRITM+LO ; save this new count + bcs RESET0 + dec DIRITM+HI ; wrapped downwards +RESET0: + lda DIRITM+HI ; get hi part + jsr STASHB ; saved that count + jsr NEXTSPC ; and point to lo part + lda DIRITM+LO ; and get lo part + jmp STASHB ; and save it, and done +DRESFT: + lda CHRCNT ; anything in buffer? + beq DRES31 ; nope + jsr TBLRTN ; then fill out last line +DRES31: + lda SAVEXSIZE+LO ; get old xsize back + sta XSIZE+LO ; restored + lda SAVEXSIZE+HI + sta XSIZE+HI + lda #0 ; reset this flag too + sta FMTTBL ; cleared +OUT3: + rts +; +; set things up for doing table output +; +START_TABLE: + + lda ARG2+HI ; SET UP TBL + sta DIRTBL+HI + lda ARG2+LO ; TO STORE CHARS IN + sta DIRTBL+LO + lda #2 + sta DIRITM+LO ; start at second char + lda #0 ; zero item counter + sta DIRITM+HI + sta ZBEGIN+ZTWIDTH+1 ; clear width count + sta ZBEGIN+ZTWIDTH+0 +; +; check to see if we have formatted table +; + lda NARGS ; get # of arguments + cmp #3 ; if == 3, then we wrap it + beq DIR30 ; nope + rts ; all done other wise +DIR30: + stx FMTTBL ; set formatted table flag + lda XSIZE+LO ; save the current XSIZE + sta SAVEXSIZE+LO ; okay, did it + lda XSIZE+HI ; and MSB + sta SAVEXSIZE+HI ; okay + lda ARG3+LO ; this is the actual amount + ldx ARG3+HI ; get interesting arg + bmi DIRFT1 ; check for negative width + jsr SETWJ ; get the window offset + ldy #WINXSZ ; get its XSIZE + lda (J),Y ; got it + sta XSIZE+LO ; aren't we nice + bne DIR31 ; jump to end +DIRFT1: + eor #$FF ; turn to a positive number + sta XSIZE+LO ; save it + inc XSIZE+LO ; to make it right +DIR31: + lda #0 ; items starts at zero + sta DIRITM+LO ; okay + sta XSIZE+HI ; clear out highness + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + rts + + ; ------ + ; CURSET + ; ------ + ; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW + ; AND AT COLUMN (ARG2) in (optional) window ARG3 + +ZCURST: + jsr CLRBUF ; CLEAR OUT ANY NON DISPLAYED TEXT 1ST + lda ARG1+LO ; see if < 0 + cmp #$FF ; -1 == turn off cursor + bne ZCURS00 ; nope + lda #1 ; show cursor off + bne ZCURSTXX ; go do it and return +ZCURS00: + cmp #$FE ; -2 == turn cursor on + bne ZCURS0 ; nope, just deal with normally + lda #0 ; show cursor not off +ZCURSTXX: + sta CURSOR_OFF ; show current cursor state + rts +ZCURS0: + dec ARG1+LO ; zero base both args + dec ARG2+LO ; thanx + + lda NARGS ; check for id + cmp #3 ; if 3 args, then window ID specified + beq ZCURS1 ; not 3, so use current window + + lda CURWIN ; show current window being done + sta ARG3+LO ; thanx +ZCURS1: + lda ARG3+LO ; get window ID + jsr SETWJ ; put address into J + lda ARG1+LO ; GET LINE + ldy #WINHGHT ; check against height + cmp (J),Y ; too far? + bcc ZCURS3 ; no, so use it + lda (J),Y ; got max out + tay ; but one too far + dey ; all better now + tya ; back to A +ZCURS3: + clc ; get ready for add + ldy #WINTOP ; do y pos first + adc (J),Y ; add in top to get absolute value + ldy #WINY ; get y pos offset + sta (J),Y ; save here + lda ARG2+LO ; GET COLUMN + ldy #WINWID ; check against width + cmp (J),Y ; is it to for right (like Reagan?) + bcc ZCURS4 ; nope, must be dukakis + lda (J),Y ; get max + tay ; for going down one + dey ; done it + tya ; back to A for usefullness +ZCURS4: + ldy #WINLEFT ; get left edge to absolute it + adc (J),Y ; carry clear from above + ldy #WINX ; this is the x pos + sta (J),Y ; into the structure +; +; now check for current window again, move cursor anyway +; + jmp GET_CURSOR ; get cursor pos from WINDOW + + ; ------ + ; CURGET + ; ------ + +ZCURGT: + jsr CLRBUF ; flush the buffer + + jsr SAVE_CURSOR ; save the current position + + dec NARGS ; see how many arguments + beq ZCURG1 ; use main window + lda ARG2+LO ; get window id + bpl ZCURG2 ; and figger it out +ZCURG1: + lda CURWIN ; use current window +ZCURG2: + jsr SETWJ ; make J point to right place + + lda ARG1+HI ; get table address + jsr SETPC ; get real address in memory + sty SPCBNK ; set bank + sta SPCH ; and page + lda ARG1+LO ; get table offset + sta SPCL ; and save it + + lda #0 ; zero hi part of Y pos + jsr STASHB ; and save it + jsr NEXTSPC ; and point to next one + jsr FETCHCY ; Fetch Y pos + jsr STASHB ; and save it + jsr NEXTSPC +; +; now for the X pos + lda #0 ; zero top byte of x pos + jsr STASHB + jsr NEXTSPC + jsr FETCHCX ; and now the X pos, and return + jmp STASHB ; and stash it away + +; +; FETCHCY - get the relativized Y pos into [A] +; J points to window structure +FETCHCY: + ldy #WINY ; get Y pos of window's cursor + lda (J),Y ; got it + ldy #WINTOP ; need to de-absolute it + sec ; get ready for sub + sbc (J),Y ; get relative pos + tax ; for 1 basing it + inx ; 1 align it + txa ; and put for save + rts +; +; FETCHCX - get relativized X pos into [A] +; J points to window structure +FETCHCX: + ldy #WINX ; get X pos of cursor + lda (J),Y ; got it + ldy #WINLEFT ; relativize it + sec ; get ready for sub + sbc (J),Y ; subtract left edge + tax ; for incing + inx ; 1 ALIGN IT + txa + rts + + ; ----- + ; DIRIN + ; ----- + ; NOT YET IMPLEMENTED, BUT RESERVED + +ZDIRIN: RTS + +; +; SETWJ - set up J to point to window structure for window ID in [A] +; +SETWJ: + tay ; check for -3 (current window) + bpl SWJ1 ; nope, window ID here + lda CURWIN ; -3 means current window +SWJ1: + asl A ; shift to make word index + tay ; and now make index + lda WINTABLE,Y ; get lo part of window struct address + sta J+LO ; and save it + lda WINTABLE+1,Y ; here's the hi part + sta J+HI ; prove it + rts + + ; ----- + ; ERASE + ; ----- + +ZERASE: + lda ARG1+LO + cmp #1 + bne ZEROUT ; not clreol + + jsr CLRBUF + jmp CLREOL ; CLEAR TO END OF LINE +ZEROUT: + sta CLSWIDTH ; this many pixels wide + lda #FONT_H ; pixels of font_height + sta CLSHEIGHT + lda SCRCX ; start at current cursor pos + sta CLSLEFT + lda SCRCY + sta CLSTOP + jmp CLS ; and do it + +; ----- +; CLEAR the current window +; ----- +SAVEXY: dw 0 + +ZCLR: + jsr CLRBUF ; flush the current buffer + jsr SAVE_CURSOR ; save the cursor pos + + lda ARG1+LO ; CHECK WHAT TO DO + bpl CLRW ; a particular window + cmp #$FD ; -3 means current window + beq CLRW ; so just handle it regular + cmp #$FE ; clear with nothing social + beq CLRCLS ; just clear the screen +; +; UNSPLIT SCREEN & CLEAR IT +; + lda #0 ; just use SPLIT 0 + sta ARG1+LO ; as if called normally + jsr ZSPLIT ; do the split +; +; just clear the entire screen +; +CLRCLS: + lda #0 ; clear the entire screen + sta CLSLEFT ; from top left + sta CLSTOP + lda #MAXWIDTH ; to bottom right + sta CLSWIDTH + lda #MAXHEIGHT + sta CLSHEIGHT + + jsr CLS ; do the clear screen (no cursor movement) + lda ARG1+LO ; check for -2 + bmi ZCLRX ; it is, don't move cursor + bpl ZCLEARX ; move cursor +CLRW: + jsr SETWJ ; get me the window pointer + ldy #WINTOP ; step thro to get data + lda (J),Y ; TOP + sta CLSTOP ; save for clear + iny ; point to left + lda (J),Y ; get it + sta CLSLEFT ; tell CLS + iny ; now at WINHGHT + lda (J),Y ; got it + sta CLSHEIGHT ; save for clear + iny ; now at WINWID + lda (J),Y ; get height + sta CLSWIDTH ; saved + jsr CLS ; screen cleared +; +; now move the cursor to 1,1, if not == -2 +; +ZCLEARX: + lda ARG1+LO ; check arg + jsr SETWJ ; make sure J still points to window + ldy #WINTOP ; put at top left of window + lda (J),Y ; get top + ldy #WINY ; and make it the y pos + sta (J),Y ; of the cursor + ldy #WINLEFT ; and the left is + lda (J),Y ; the + clc ; add in the left margin + ldy #WINLM ; here's the left margin + adc (J),Y ; added it + ldy #WINX ; x pos of the + sta (J),Y ; cursor + lda #0 ; and clear out line count + ldy #WINLCNT ; line count + sta (J),Y ; okay + ldy #WINLLEN ; and length of current line + sta (J),Y ; okay + iny ; do hi + sta (J),Y ; okay +ZCLRX: + jmp GET_CURSOR ; restore the cursor pos for the current window + +; ------ +; PRINTT +; ------ +; PRINT A TABLE TO SCREEN, ARG1 = # OF BYTES +; ARG2 = WIDTH, ARG3 (DEF = 1) = HEIGHT + +OLDCHZ EQU I+LO ; EASIER TO READ +OLDEHZ EQU I+HI +OLDCVT EQU L+LO + +TBL_LEN DW 0 ; save for length + +ZPRNTT: + lda ARG1+LO ; USE GETBYT AS TBL COULD + sta MPCL ; BE ANYWHERE + lda ARG1+HI + sta MPCM + lda #0 + sta MPCH + jsr VLDMPC + + lda ARG2+LO ; ONLY A BYTE AS MAX + beq PTTDUN ; QUIT NOW IF NULL + + sta TBLWIDTH ; width of the table + sta TBLCNT ; start counter off at width + dec NARGS ; count down to 1 (maybe) + lda NARGS + cmp #1 + beq NOHIGHT ; DEFAULT HEIGHT IS 1 + lda ARG3+LO ; get passed height +NOHIGHT: + sta TBLHEIGHT ; height of the table (at least 1) + lda SCRCX + sta OLDEHZ + sec ; subtract left margin to get how long line is + sbc LEFTMRG ; okay we did that + sta TBL_LEN+LO ; this is how big line is too + lda #0 ; clear MSB + asl TBL_LEN+LO ; *2 + rol A + asl TBL_LEN+LO ; *4 + rol A + sta TBL_LEN+HI ; save +PTTLP: + jsr GETBYT ; GET A BYTE + jsr COUT ; and send it out + + dec TBLCNT ; one more byte done + bne PTTLP + dec TBLHEIGHT ; IF DONE ALL LINES + beq PTTDUN ; LEAVE + + jsr CLRBUF ; so send out stuff that's there + + lda OLDEHZ ; get old x pos + sta SCRCX ; and restore it + lda #1 ; show cursor changed + sta CURSFLG ; okay + lda SCRCY ; point to next line + clc ; by adding in the font height + adc #FONT_H ; okay, goody + sta SCRCY ; and here we are + + lda TBL_LEN+HI ; reset length + sta LENGTH+HI ; hi part + lda TBL_LEN+LO ; lo part + sta LENGTH+LO ; just a lo + + lda TBLWIDTH ; RESET COUNT + sta TBLCNT ; thanx + bne PTTLP ; GO DO NEXT LINE +PTTDUN: + rts +;-------------- +; ZPRINTF +;-------------- +; ZPRINTF - print a formatted table +; +ZPRINTF: + lda ARG1+LO ; USE GETBYT AS TBL COULD + sta MPCL ; BE ANYWHERE + lda ARG1+HI + sta MPCM + lda #0 + sta MPCH + jsr VLDMPC + + lda SCRCX ; save the X pos + sta OLDEHZ ; saved here +ZPFL1: + jsr GETBYT ; get the length byte, MSB, & ignore + jsr GETBYT ; get the length byte + beq ZPFX ; no more if == 0 + sta TBLWIDTH ; keep track of it +ZPFL2: + jsr GETBYT ; now get the char byte + jsr CHAR ; and send it yt + dec TBLWIDTH ; any more? + bne ZPFL2 ; ayyup + + jsr DISP_LINE ; make sure line goes out + lda OLDEHZ ; reset a few things + sta SCRCX ; including x pos + lda #1 ; show cursor changed + sta CURSFLG ; okay + lda SCRCY ; point to next line + clc ; by adding in the font height + adc #FONT_H ; okay, goody + sta SCRCY ; and here we are + bne ZPFL1 ; and do it again +ZPFX: + rts +; ------------ +; SET NEW FONT +; ------------ + +; Font 4 is mono-spaced font. + +ZFONT: + jsr CLRBUF ; clear the buffer first + + dec NARGS ; did we get passed a window id? + bne ZFNTWID ; yup + lda #$FD ; -3 means current window + sta ARG2+LO ; make it the arg2 then +ZFNTWID: + lda ARG2+LO ; get window we are interested in + jsr SETWJ ; make [J] point to window struct + + lda ARG1+LO ; check for + cmp #1 ; font 1 + beq ZFNT1 ; or + cmp #4 ; font 4 (monospace) + bne ZFBAD ; nope, so die +; +; font 4 is the monospaced font +; + ldy #WINFSIZE ; point to width + lda #MFONT_W ; get game width + sta (J),Y ; store the width + lda #3 ; set font ID + bne ZFNTEX ; all done +ZFNT1: + ldy #WINFSIZE ; point to width + lda #FONT_W ; get game width + sta (J),Y ; store the width + lda #0 ; set font ID +ZFNTEX: + ldy #WINFONT ; set font + pha ; save font id + lda (J),Y ; get old font id + tax ; save old font id + pla ; get new one back + sta (J),Y ; save in structure + lda (WINDOW),Y ; get current window font + beq ZFNT0X ; set flag with zero + lda #MONOFONT_W ; get width of mono spaced font +ZFNT0X: + sta FONTFLG ; and set flag too + inx ; make it say correct font ID for game + txa ; put in A for put val + ldx #0 ; clear X + jmp PUTVAL ; and return it +ZFBAD: + jmp RET0 ; TELL IT DOESN'T WORK +; ------------------------------ +; FETCH A LINE OF INPUT FOR READ +; ------------------------------ +; ENTRY: Relative READ table address in RDTBL1 +; EXIT: # CHARS READ IN [A] +SV_SPC: ds 3 ; save SPC here for later usage +INP_X: dw 0 ; saved cursor position + +INPUT: + jsr CLRBUF ; FLUSH [LBUFF] + ldy #0 ; RESET LINE COUNT + sty I+HI ; clear local variables + sty I+LO + sty J+HI + sty J+LO + sty BRKCHR ; init break char + sty LINCNT ; RESET LINE COUNT + sty PTR_COUNT ; we start by looking at pointer + lda CURSFLG ; really move the cursor? + beq IO_CURS ; nope +; +; re-doing the (hopefully) saved read, so put cursor back +; + lda INP_X+HI ; first, the MSB + sta CHR_X+HI + lda INP_X+LO ; now the LSB + sta CHR_X+LO + sty CURSFLG ; make sure we don't change cursor +IO_CURS: +; +; check for new TCHARS table +; + lda ZBEGIN+ZTCHAR+1 ; so check lower byte for different tchars + cmp SVTCHAR+LO ; is it different? + bne IO_DOT ; ayyup, get new one + lda ZBEGIN+ZTCHAR ; get current TCHARS hi part + cmp SVTCHAR+HI ; is it the same as saved one? + beq IOj ; yes, so don't muck with it +IO_DOT: + jsr DO_TCHARS ; new table, so copy it over +; +; now set up FPC +; +IOj: + lda RDTBL1+HI ; get page of table + jsr SETPC ; and get me the memory page and bank + sta FPCH ; save page + sty FPCBNK ; and bank + lda RDTBL1+LO ; and get offset + sta FPCL ; set up FPC/SPC + jsr FETCHB ; get length of line + tay ; for dec'ing + dey ; don't count the offset byte + dey ; and leave room for terminator + sty CHRMAX ; and save it + jsr NEXTFPC ; point to next byte + jsr FETCHB ; get current offset into buffer + sta CHARCNT ; save how many chars out there + jsr NEXTFPC ; point to beginning of data buffer +; +; now finish setting up saved SPC +; + ldx #2 +INSVCL: + lda FPC,X ; get byte to saved for use later on + sta SV_SPC,X ; it is saved here + dex + bpl INSVCL ; next! +; +; now copy current buffer into local buffer +; + lda CHARCNT ; make sure we have some + beq CPIOLX ; nope, none in there now + ldx #0 ; start at first char +CPIOL: + jsr FETCHB ; get a char + sta LBUFF,X ; save char + jsr NEXTFPC ; point to next one + inx ; next char + cpx CHARCNT ; got them all yet? + bne CPIOL ; nope +CPIOLX: + jsr CHKTME ; START TIME LIMIT +; +; this is the get-a-key-and-whack-on-it loop +; +INLOOP: + lda I+HI ; is there a time? + beq INPL1 ; nope + jsr TIMIN ; do timed input + bcc INPL2 ; got a char, process it + jmp LEXBAD ; timed out with nothing there! +INPL1: + jsr GETKEY ; let apple do the walking +INPL2: + jsr ISTCHR ; CHECK IF IT'S AN ACCEPTABLE TERMINATOR KEY + bcs NOTYET + + sta BRKCHR + cmp #EOL ; IF EOL PUT TO SCREEN + beq ENDLINx + jmp ENDIN ; ELSE JUST END +ENDLINx: + jmp ENDLIN ; can't reach with a branch +NOTYET: + ldy #$FF ; restart pointer device counter + sty PTR_COUNT ; and start again + tay ; check for functions keys that aren't + bmi CBAD ; terminators and feep if it is + cmp #EOL ; EOL? + beq ENDLIN ; LINE DONE IF SO + cmp ESCAPE ; don't allow escape char's thru + beq CBAD ; okay, I won't + + cmp #BACKSPACE ; BACKSPACE? + beq BACKUP ; SPECIAL HANDLING + cmp #ESCAPE ; ESCAPE char? + beq CBAD ; don't like it + + ldy CHARCNT ; where do we put char? + cpy CHRMAX ; are we filled up? + bcs CBAD ; boy, am i full + + pha ; save it + tax ; use as index + lda LENGTH+LO ; GET LINE LENGTH COUNTER + clc ; get ready for add + adc CHWID,X ; add width + tay ; save LSB in Y + ldx LENGTH+HI ; get high byte + bcc INP0C ; no wrap + inx ; okay, wrap then +INP0C: + pla ; get char back + cpx XSIZE+HI ; check MSB first + bcc NOIOWRAP ; no need to check lsb + cpy XSIZE+LO ; end of screen line? + bcs CBAD ; reached end, so just beep +NOIOWRAP: + stx LENGTH+HI ; save MSB + sty LENGTH+LO ; and LSB + ldx CHARCNT ; for putting in line buffer + sta LBUFF,X ; and save it in case we goto printer + jsr CHAR ; SEND TO SCREEN + jsr DISP_LINE ; show char + inc CHARCNT ; NEXT POSITION IN LINE + jmp INLOOP ; NO, GET ANOTHER CHAR +; +; HANDLE BACKSPACE +; +BACKUP: + ldx CHARCNT ; if == 2 then empty + beq CBAD ; JMP to beeping + dex ; get rid of char + stx CHARCNT ; saved + lda LBUFF,X ; get char we are interested in + tax ; put in x + + lda LENGTH+LO ; GET LINE LENGTH COUNTER + sec ; get ready for sub + sbc CHWID,X ; sub width + sta LENGTH+LO ; update length + bcs BCKP1 ; no wrap + dec LENGTH+HI ; okay, wrap then +BCKP1: + lda #BACKSPACE ; so do erasing backspace + jsr CHAR + jmp INLOOP +CBAD: + jsr BEEP ; ELSE SCREAM WITH PAIN + jmp INLOOP ; AND WAIT FOR SOMETHING BETTER +; +; HANDLE END OF LINE KEY +; +ENDLIN: + sta BRKCHR + lda #EOL ; get EOL char + jsr CHAR ; SEND EOL TO SCREEN + lda #0 ; and show 0 length of line out there + sta LENGTH+LO ; thanx + sta LENGTH+HI ; and msb + inc LINCNT ; take into account the at EOL +ENDIN: +; +; now save lbuff in table for posterity +; + lda SV_SPC+ABANK ; get bank first + sta SPCBNK ; saved + lda SV_SPC+HI + sta SPCH + lda SV_SPC+LO + sta SPCL + ldx #0 ; start with first char in buffer +ENDLOOP: + cpx CHARCNT ; done yet? + beq INP111 + lda LBUFF,X ; get char + cmp #'A' ; IF CHAR IS UPPERCASE ALPHA, + bcc LEX ; CONVERT TO LOWER CASE + cmp #'Z'+1 + bcs LEX + adc #$20 ; converting away +LEX: + jsr STASHB ; okay, stashing away + jsr NEXTSPC ; and point to next char in table + inx ; point to next char + bne ENDLOOP ; so get next one +INP111: + lda #00 ; to show end of line + jsr STASHB ; so put it in buffer +; +; now put in new line length +; + lda RDTBL1+HI ; get page of table + jsr SETPC ; and get me the memory page and bank + sta SPCH ; save page + sty SPCBNK ; and bank + lda RDTBL1+LO ; and get offset + sta SPCL + jsr NEXTSPC ; and point to char count + lda CHARCNT ; get character count + jsr STASHB ; and shove it away +LEXBAD: + ldy #0 ; clear out + sty PTR_COUNT ; pointer flag +; +; now, save CHR_X, in case we redo this read +; + lda CHR_X+HI ; first, the MSB + sta INP_X+HI + lda CHR_X+LO ; now the LSB + sta INP_X+LO + rts ; Length is in [A] +; +; Copy over a new TCHARS table +; +DO_TCHARS: +; +; now do somethin' with the TCHAR table (maybe, if <> 0) +; + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + sta SVTCHAR+HI ; save it for checking + jsr SETPC ; and now make absolute + sta FPCH ; Save in FPC + sty FPCBNK + lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + sta SVTCHAR+LO ; and save for later check + sta FPCL ; now move pointer to fetch spot + + lda #0 ; and set index + sta I ; thank you + sta ALLFLG ; turn it off +TCHLP: + jsr FETCHB ; get the byte in [a] + jsr NEXTFPC ; point to next one + ldx I ; get offset + inc I ; and point to next one + sta TCHARTBL,X ; save in lower memory, thank you + cmp #0 ; are we done yet? + beq TCHj ; NULL TERMINATED STRING + cmp #$FF ; $ff means all >128 chars are terminators + bne TCHLNEXT ; nope + lda #1 ; yes, + sta ALLFLG ; so set flag to say so +TCHLNEXT: + bne TCHLP ; and go get it +TCHj: + rts + + ; ------------------------ + ; IS IT A TERMINATOR CHAR? + ; ------------------------ + +ISTCHR: + ldx TCHARTBL ; check for chars in TCHAR table + beq ISNOT ; nope + + ldx ALLFLG ; ARE ALL FCN KEYS (<127) TERMINATORS + beq ISCHK ; 0 = NO, GO CHECK LIST + tax ; check for minus + bmi ISFND ; YUP + bpl ISNOT +ISCHK: + ldy #0 +ISLP: + cmp TCHARTBL,Y ; IS CHAR WE HAVE A TCHAR? + beq ISFND ; YES + ldx TCHARTBL,Y ; NULL = END OF STRING + beq ISNOT + iny + bne ISLP ; SHOULD ALWAYS LOOP +ISNOT: + sec + rts ; NOT FOUND +ISFND: + clc + rts + + ; ----- + ; INPUT 1 char, no printing + ; ----- + +ZINPUT: + JSR CLRBUF + + ldy #0 + sty LINCNT + sty CHRCNT + sty I+HI ; init locals too + sty I+LO + sty J+HI + sty J+LO + sty PTR_COUNT ; always check the pointer + + DEC NARGS + BEQ ZINP3 ; NO TIME LIMIT + LDA ARG2+LO ; GET DELAY WANTED + STA I+HI + DEC NARGS + BEQ ZINP4 ; NO FCN + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI +ZINP4: + JSR TIMIN ; CALL timed input rotine + BCC ZINPRK ; send char on home + JMP RET0 ; time out without character +ZINP3: + jsr GETKEY ; ok, find which char was pressed + cmp #ESCAPE ; don't use escape char + bne ZINPRK ; fine + jsr BEEP ; complain + jmp ZINP3 ; do again +ZINPRK: + LDX #0 + JMP PUTBYT ; RETURN CHAR + + +INTCLL: + LDA I+HI ; SAVE VALUES FOR CALLING RTN + PHA + LDA I+LO + PHA + LDA J+HI + STA ARG1+HI ; pretend it's arg1 + PHA + LDA J+LO + STA ARG1+LO ; and this is the other half + PHA + + LDX #1 + STX NARGS ; 0 args for internal call + DEX + STX IRET ; make sure it returns here! + + LDA ZPCL ; a fake one to say we + PHA ; are an internal call + LDA ZPCM ; so save real one + PHA + LDA ZPCH + PHA + + LDA #0 ; return addr of zero is + STA ZPCH ; internal call! + STA ZPCM + STA ZPCL + + JSR DOCALL + + JMP MLOOP ; GO DO FCN +; +; RETURN FROM FCN WILL COME HERE +; +ZIRET: + PLA ; GET RID OF RTS FROM ZRET + PLA + + PLA ; get old zpc back + STA ZPCH + PLA + STA ZPCM + PLA + STA ZPCL + JSR VLDZPC ; and validate it + + PLA ; RESTORE FOR CALLING RTN + STA J+LO + PLA + STA J+HI + PLA + STA I+LO + PLA + STA I+HI + RTS ; GO BACK TO CALLER + +; INPUT: routine locals! +CHARCNT: DB 0 ; where into buffer goes char +SVCHAR: DB 0 ; where to save the char before printing + +IRET: DB 0 ; FLAG TELLS IF RETURNLESS CALL + +MTEMP: DB 00,00 ; temp spot for math routines +TYPE: DB 0 ; PARTIAL OR NORMAL (WHOLE) SAVE/RESTORE +ASSVLU: DB 0 ; how many args to this subroutine +BRKCHR: DB 0 ; READ BREAK CHAR +RDFLAG: DB 0 ; 0 - only read 1 - do lex on it +MORE: DB "[MORE]" +MOREL EQU $-MORE + END + + diff --git a/apple/yzip/rel.15/machine.asm b/apple/yzip/rel.15/machine.asm new file mode 100644 index 0000000..4ccd759 --- /dev/null +++ b/apple/yzip/rel.15/machine.asm @@ -0,0 +1,945 @@ + STTL "--- MACHINE-DEPENDENT I/O: APPLE II ---" + PAGE +; ----------------------- +; DIRECT PRINT LINE [X/A] +; ----------------------- +; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB) +; STRING LENGTH IN [Y] +DLCNT: db 0 +DLOFF: db 0 +DLINE: + stx STRING+LO ; DROP STRING ADDRESS + sta STRING+HI ; INTO DUMMY BYTES + sty DLCNT ; COUNTER + jsr CLRBUF ; send out what's out + lda SCREENF ; save output flag + pha + ldx #1 ; INIT CHAR-FETCH INDEX + stx SCREENF ; make sure screen output is on + dex + stx CRLF_CHECK ; don't let swap happen + stx SCRIPT ; don't script any of my internal +DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE +STRING: DW $0000 ; DUMMY OPERAND BYTES + stx DLOFF ; save X + sta IOCHAR ; save here for DIRECT_OUT +DOUT1: jsr DIRECT_OUT ; send directly out there + ldx DLOFF ; get x back + inx + dec DLCNT ; LOOP TILL + bne DOUT ; OUT OF CHARS + jsr CLRBUF ; and force the chars out + ldx #1 ; allow scripting again + stx SCRIPT ; okay, we did + stx CRLF_CHECK ; and turn on check + pla ; get screen flag back + sta SCREENF ; bingo + rts ; done + +; SWAP2INFOW - save current state and swap to the information window, +; which is currently window zero +SWAPA1: ds 1 ; save for current ARG1 +SWAPCW: ds 1 ; save for current window +SWAPFLG: db 0 ; flag == 1 if we have already swapped +SWAP2INFOW: + lda SWAPFLG ; already swapped? + bne SWP2 ; ayyup + jsr CLRBUF ; clear out the buffer + jsr SAVE_CURSOR ; save current postion of cursor + lda ARG1+LO ; get current arg1 + sta SWAPA1 ; save it + lda CURWIN ; get current window + sta SWAPCW ; save it + lda #0 ; swap to window zero for messages + sta ARG1+LO ; okay + jsr ZSCRN ; and swap to it +SWP2: + inc SWAPFLG ; show we are in swap window +SWAPEX: + rts ; all done +; +; SWAPBACK - swap out of info window, and back to old window +; +SWAPBACK: + dec SWAPFLG ; are we finally leaving for good? + bne SWAPEX ; nope + lda SWAPCW ; and now for current window + sta ARG1+LO ; swap to it + jsr ZSCRN ; we did + lda SWAPA1 ; and get arg1 back + sta ARG1+LO ; we did + jmp GET_CURSOR ; and get cursor back + +; ----------------------- +; SEND [LBUFF] TO PRINTER +; ----------------------- +; ENTRY: LENTH OF LINE IN [PRLEN] + +PLEAV: RTS + +PPRINT: + lda SCRIPT ; SCRIPTING INTERNALLY ENABLED? + and SCRIPTF ; SCRIPTING ON? + and SCRIPTFLG ; Window allow scripting? + beq PLEAV ; NO, EXIT + lda CSW+LO ; SAVE NORMAL OUTPUT HOOK + pha + lda CSW+HI + pha + lda ALTCSW+LO ; LOAD SCRIPTING HOOK + sta CSW+LO + lda ALTCSW+HI + sta CSW+HI + lda RDROM ; put system ROM in for printer out + ldy #0 +PP5: + lda LBUFF,Y ;GET A CHAR TO SEND OUT + bmi PP6 ; don't do highlighting + ora #$80 ; make it apple happy + jsr MCOUT +PP6: + iny + dec PRLEN ;LINE COUNT + bne PP5 ;PRINT WHOLE LINE +; +; ALL DONE, RESET TO NORMAL AND LEAVE +; + lda BNK2SET ; write RAM, bank 1 + lda BNK2SET + pla + sta CSW+HI + pla + sta CSW+LO + rts + +PSTAT: DB 0 ;SET TO CLEAR WHEN BOOT, + ;I PUT IT HERE SO RESTART WON'T ALTER +ALTCSW: DB 0,0 ;(WORD) PRINTER COUT + + ; FIRST TIME USING PRINTER, INITIALIZE IT +SLOTM: DB EOL + DB "Printer Slot 1-7: " +SLOTML EQU $-SLOTM + +PCHK: + jsr SWAP2INFOW ; point to info window +PCHK1: + DLINE SLOTM + jsr GETKEY + cmp #'8' ;1-7 + bcs PCHK1 ;OOPS + cmp #'1' ; less than '1'? + bcc PCHK1 ; ayyup +PC2: + eor #$F0 ; make it a slot address + sta ALTCSW+HI + lda #EOL + jsr CHAR ;SEND >CR< TO SCREEN FOR NEATNESS + inc PSTAT ;SET TO ON + lda CSW+LO ;SAVE NORMAL OUTPUT HOOK + pha + lda CSW+HI + pha + lda ALTCSW+LO ;LOAD SCRIPTING HOOK + sta CSW+LO + lda ALTCSW+HI + sta CSW+HI + jsr INITPRT ; now, init it + + lda RDROM ; bring in system ROM + lda #$89 ; OUTPUT PRINTER SETUP SEQUENCE + jsr MCOUT ; START WITH COMMAND CHAR >CTRL-I< + lda #$B8 ; 8 (80 COL WIDE) + jsr MCOUT + lda #$B0 ; 0 + jsr MCOUT + lda #$CE ; N (LF AFTER CR) + jsr MCOUT + lda CSW+LO ; SAVE REAL PRINTER OUTPUT + sta ALTCSW+LO ; LOC. FOR NEXT TIME + lda CSW+HI + sta ALTCSW+HI + pla ; RESET NORMAL OUTPUT + sta CSW+HI + pla + sta CSW+LO + lda BNK2SET ; and bring back top RAM + lda BNK2SET ; okay + jmp SWAPBACK ; and back to the old window +INITPRT: + lda #0 ; jump to $Cn00 + sta CSW+LO ; make LSB == 0 + jmp (CSW) ; and goto it + + +SAVE_CURSOR: + lda SCRCY ; save the cursor pos + ldy #WINY ; get offset + sta (WINDOW),Y ; first y pos + iny ; now x pos + lda SCRCX ; got it + sta (WINDOW),Y ; saved it + ldy #WINLCNT ; reset line count too + lda LINCNT ; okay + sta (WINDOW),Y ; get it + rts + +GET_CURSOR: + ldy #WINY ; get cursor pos back + lda (WINDOW),Y ; got y pos + sta SCRCY ; saved + iny ; point to x pos + lda (WINDOW),Y ; got it + sta SCRCX ; make it better + sec ; subtract left margin to get how long line is + sbc LEFTMRG ; okay we did that + bcs GETCR1 ; make sure left margin is not > cur x pos + lda #0 ; otherwise, pretend length is zero +GETCR1: + sta LENGTH+LO ; this is how big line is too + lda #0 ; clear MSB + sta LENGTH+HI + asl LENGTH+LO ; *2 + rol LENGTH+HI + asl LENGTH+LO ; *4 + rol LENGTH+HI + + ldy #WINLCNT ; reset line count too + lda (WINDOW),Y ; get it + sta LINCNT ; okay + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay + rts + +; ------------ +; SPLIT SCREEN +; ------------ +; +; SPLIT SCREEN AT LINE [ARG1] putting screen 1 at top and screen +; 0 at bottom. +; DISABLE SPLIT IF [ARG1] = 0 +; +ZSPLIT: + jsr SAVE_CURSOR ; save the cursor pos +; +; first muck with window 1 +; + lda ARG1+LO ; get split arg back + sta WINDOW1+WINHGHT ; this becomes the height of window 1 + lda #0 ; put top of 1 to top of screen + sta WINDOW1+WINTOP ; okay, we did it + lda ARG1+LO ; get new height + ldx #$FF ; this is the counter + sec ; get ready for subs +ZSPLIT0: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZSPLIT0 ; still some lines + dex ; save input line + stx WINDOW1+WINLINES ; saved + + lda WINDOW1+WINY ; check cursor pos + cmp ARG1+LO ; against height + bcc ZSPL1 ; inside window, so save it +ZSPL0: + lda #0 ; reset to top left + sta WINDOW1+WINY ; y pos at top + sta WINDOW1+WINX ; x pos at left + sta WINDOW1+WINLLEN+LO ; line length + sta WINDOW1+WINLLEN+HI ; line length + sta WINDOW1+WINLCNT ; line counter +; +; now muck with window 0 +; +ZSPL1: + lda WINDOW0+WINTOP ; top of window 0 + sec ; doing sub + sbc ARG1+LO ; subtract out the new top + clc ; adding + adc WINDOW0+WINHGHT ; to get the new height +; bcc ZSPLIT1 ; okay, positive height +; lda #0 ; make height 0 +ZSPLIT1: + sta WINDOW0+WINHGHT ; and save new height + + ldx #$FF ; this is the counter + sec ; get ready for subs +ZSPLIT2: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZSPLIT2 ; still some lines + dex ; to save input line + stx WINDOW0+WINLINES ; saved + + lda ARG1+LO ; this is the new top + sta WINDOW0+WINTOP ; set in structure + cmp WINDOW0+WINY ; make sure cursor is still in window + beq ZSPL5 ; nope, at the top + bcc ZSPL5 ; or under it + sta WINDOW0+WINY ; put cursor at top + lda #0 ; left of new + sta WINDOW0+WINX ; window 0 + sta WINDOW0+WINLLEN+LO ; linelength + sta WINDOW0+WINLLEN+HI ; linelength + sta WINDOW0+WINLCNT ; line counter +ZSPL5: + jsr GET_CURSOR ; get the cursor pos back + + lda #0 ; now switch to window zero + sta ARG1+LO ; good bye + jmp ZSCRN ; making window 0 be current + +; ------ +; MARGIN +; ------ +; +; Set the margins for the window +; +; ARG1 - left margin +; ARG2 - right margin +; ARG3 - window ID (optional) +; +ZMARG: + jsr CLRBUF ; CLEAR LBUFF BEFORE RESETTING LINE MARGINS + jsr SAVE_CURSOR ; save current cursor pos + + lda NARGS ; see if window ID was passed + cmp #3 ; if ==3, then it's there + beq ZMRG1 ; okay, so use it + lda CURWIN ; get the current window + sta ARG3+LO ; and use as the default +ZMRG1: + lda ARG3+LO ; check what window + jsr SETWJ ; get window offset into J + lda ARG1+LO ; do left margin first + ldy #WINLM ; get offset + sta (J),Y ; save for window + iny ; point to right margin + lda ARG2+LO ; get right margin + sta (J),Y ; save right margin + ldy #WINWID ; get full width of window + lda (J),Y ; got it + sec ; subtract off the 2 margins + ldy #WINLM ; first the left margin + sbc (J),Y ; okay, gone + iny ; point to right margin + sbc (J),Y ; and take it off + ldy #WINXSZ ; set width of usable window + sta (J),Y ; see, here it is +; +; move cursor to left margin +; + ldy #WINLEFT ; get left edge + lda (J),Y ; got it + ldy #WINLM ; and add left margin + clc ; adding + adc (J),Y ; to get minimum X + ldy #WINX ; check to make sure X pos is okay + sta (J),Y ; then reset it +; +; now see if we changed the current window +; +ZMRGXP: + ldx ARG3+LO ; get the window + bmi ZMRG3 ; -3 means current window + cpx CURWIN ; check against the current window + bne ZMRGX ; nope, so we be done +ZMRG3: + sta LEFTMRG ; [A] already has left margin + ldy #WINXSZ ; get xsize to set + lda (WINDOW),Y ; got it + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + jsr GET_CURSOR ; restore the cursor pos +ZMRGX: + rts +; +; SOUND +; ----- +; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID +; (EZIP) + +ZSOUND: + ldx ARG1+LO ; GET SOUND WANTED + dex + beq BEEP + dex + bne ZSOEX ; INVALID + ldy #$FF ; DURATION ($C0 = .1 SEC) +BOOP: + lda #$10 ; TONE ($0C = 1 KHZ) + jsr WAIT10 + lda SPKR ; TOGGLE SPEAKER + dey + bne BOOP +ZSOEX: + rts + +BEEP: + lda RDROM + jsr MBELL ; just use system beep + lda BNK2SET ; back to bank 2 + lda BNK2SET ; back to bank 2 + rts +; +; just do the background color - foreground is always white/black +; +; +; ZIPCOLOR - maps ZIP colors to screen colors +; +ZCOLOR: + jsr CLRBUF ; print out what we have + + lda NARGS ; check if window was passed + cmp #3 ; was it? + beq ZCLR0 ; ayyup + lda CURWIN ; make it current window + sta ARG3+LO ; it is now +ZCLR0: + lda ARG3+LO ; get window ID + jsr SETWJ ; and put pointer into J + + ldx ARG2+LO ; get background color + beq ZCLR2 ; check fore ground color + bpl ZCLR01 ; not -1 + jsr GET_NYBBLE ; get me the color nybble here + jmp ZCLR11 ; and use as background color +ZCLR01: + dex ; check for default + bne ZCLR1 ; nope, find the color + ldx #1 ; use black as default back color +ZCLR1: + dex ; zero base the color + lda ZIPCOLOR,X ; get my color from the zip color +ZCLR11: + ldy #WINBGND ; get background offset + sta (J),Y ; saved color +; +; now do foreground color +; +ZCLR2: + ldx ARG1+LO ; get foreground color + beq ZCLREX ; no change + dex ; check for default + bne ZCLR3 ; nope, find the color + ldx #8 ; use white as default fore color +ZCLR3: + dex ; zero base the color + lda ZIPCOLOR,X ; get my color from the zip color + ldy #WINFORE ; foreground color offset + sta (J),Y ; save in structure +ZCLREX: + rts + +; +; CHKTME RTN - CALLED BY INPUT & ZINPUT +; +CHKTME: + lda NARGS ; CHECK IF TIME LIMIT + cmp #2 + beq CHKT1 ; NO + lda ARG3+LO ; GET DELAY WANTED + sta I+HI + lda NARGS ; IS THERE A FCN? + cmp #4 + bne CHKT1 ; NO + lda ARG4+LO ; YES, SET IT + sta J+LO + lda ARG4+HI + sta J+HI +CHKT1: + rts ; just set things up, please + +WAIT10: + lda #2 ; do this twice (maybe) + sta DELAY_COUNTER ; put in counter +WAIT0: + lda RDROM ; get roms in + ldx #4 ; .04 SEC (time to do other stuff) +TIME1: lda #$30 ; .01 SEC + jsr MWAIT + dex + bne TIME1 + + lda BNK2SET ; get roms out + lda BNK2SET + + lda MOUSEF ; move mouse cursor? + beq WAIT1 ; nope + lda PTR_COUNT ; but do we really want to check it + bne WAIT1 ; nope + jmp MOVE_MC ; move cursor, if necessary +WAIT1: + dec DELAY_COUNTER ; count loop + bne WAIT0 ; go do again + rts +; +; tick the ol timer +; +TIMEK: + lda #BLINK_RATE ; how often to blink + sta CURCOUNT ; okay! +TIMEST: + lda I+LO ; don't reset if not zero + bne TIMELOOP ; so keep goin' then + lda I+HI + sta I+LO + jsr STCUR ; start the cursor +TIMELOOP: + jsr WAIT10 ; wait .10 secs + + jsr FKEYX ; Check for Keystroke + bmi TIME2 ; OK, HE'S THERE, CONTINUE + + dec CURCOUNT ; count down to toggle + bne TMCNT ; okay, no blink + jsr STCUR ; blink cursor + lda #BLINK_RATE ; once per second + sta CURCOUNT ; okay! +TMCNT: + dec I+LO ; 10TH'S OF SECONDS TO WAIT + beq TIMEOUT ; SOME TIME LEFT + + bne TIMELOOP ; so gwon back and try again! (JMP) +; +; THERE IS A TIME OUT, CHECK FOR A FCN +; +TIMEOUT: + jsr ERCUR ; after erasing cursor + lda J+HI ; IS THERE A FCN + beq TIMEBAD ; NO FCN, LEAVE WITH NOTHING +TIME3: + jsr INTCLL ; INTERNALLY CALL THE FCN + lda VALUE+LO ; CHECK RESULTS + beq TIMEST ; ELSE TRY AGAIN + bne TIMEBAD ; else die a horrible death! +TIME2: + jsr ERCUR ; after erasing cursor + clc ; GOT A KEY + rts +TIMEBAD: + sec + rts +; +; display the cursor in the current spot +; +CURSTATE: db $80 ; blinking cursor state +CURCOUNT: db 0 ; toggle counter + +STCUR: + ldx CURSOR_OFF ; is the cursor off? + beq STCUR1 ; no + rts ; yes, so don't do nuthin' +STCUR1: + pha ; save a + lda INVFLG ; get current INVFLG + pha ; save it + lda #$80 ; make it all be ones + sta INVFLG ; and blink + + lda #SPACE ; space for cursor + sta SHOW_CURSOR ; show that we are doing cursor + jsr CHAR ; and print it out + jsr DISP_LINE ; send it out + + lda CURSTATE ; get current state + eor #$80 ; toggle it + sta CURSTATE ; save it + pla ; get invflg + sta INVFLG ; restored + lda #0 ; clear cursor flag + sta SHOW_CURSOR ; okay + + pla ; get [A] back + rts +; +; just erase the cusor char, but leave cursor in its old place +; +ERCUR: + pha ; save a + lda CURSTATE ; get current state + bne ERCURX ; not on, leave alone + jsr STCUR ; 'start' it out +ERCURX: + pla ; retrieve [A] + rts +; +; timed key input loop +; +; carry set if timed out +; char in [A], if there is one! +TIMIN: + lda MOUSEF ; is there a mouse/joystick? + beq TIMIN1 ; nope + jsr MSCON ; turn on mouse cursor +TIMIN1: + jsr TIMEK ; check for keystroke + bcs TMBAD ; ELSE ABORT +TM1: + jsr PARSEKEY ; GET ASCII INTO [A] AND [IOCHAR] + bcs TIMIN1 ; c==1 means no good char +TMBAD: + ldx MOUSEF ; is there a mouse/joystick? + beq TIMIN2 ; nope + php ; save status + pha ; save (possible) char + jsr MSCOFF ; turn off mouse cursor + pla ; get char back + plp ; get return status +TIMIN2: + rts ; and away we go +; +; FKEYX - move the mouse cursor if any, then check for keystroke +; +FKEYX: + lda MOUSEF ; is there a mouse cursor? + beq KEYX ; nope + bmi KEYMOUSE ; handle mouse + jsr DO_STICK ; handle joystick + bpl KEYX ; go look for key still + bmi KEYBTN ; do button handling +KEYMOUSE: + jsr DO_MOUSE ; handle mouse stuff + bpl KEYX ; go look for key still +; +; button hit, so show pos in MSTBL +; +KEYBTN: + pha ; save status + lda MSTBL+LO + sta SPCL + lda MSTBL+HI + sta SPCH + lda MSTBL+ABANK + sta SPCBNK + lda #ZMSLOCX+1 ; point to LSB of mouse x + jsr ADDSPC ; add to point + lda MSX ; get X + clc ; center the hot spot + adc #CURSW/2 ; add 1/2 width + jsr STASHB ; and stuff it away + lda #2 ; 2 more to get to mouse y + jsr ADDSPC ; okay + lda MSY ; now show the world the y pos + clc ; and center vertically too + adc #CURSH/2 ; add 1/2 height + jsr STASHB ; and it is away + pla ; get status back + tay ; and set it again + rts ; otherwise, done +KEYX: + lda KBD ; check keyboard strobe + bpl KEYXX ; nothing + sta ANYKEY ; reset strobe +KEYXX: + rts +; +; MOVE_MC - move the mouse/joystick cursor, if necessary +; +MOVE_MC: + lda MOUSEF ; check which kind to move + bpl MOVE_MC1 ; move joystick cursor + jsr CHK_MOUSE ; move the mouse cursor + jmp MOVE_MC2 ; and print it +MOVE_MC1: + jsr MOVE_STICK ; okay, checked it out +MOVE_MC2 + lda MSMOVEF ; did it move? + beq MOVE_MCX ; nope + jmp MSCURS ; print it +MOVE_MCX: + rts ; done +; +; CHK_MOUSE - check the mouse position and button state, and flag any change +; +CHK_MOUSE: + lda PAGE2SW ; make sure we are pointing to main bank + + ldx #READM ; get me current cursor pos + jsr MOUSER ; turn off interrupts and set current pos + + lda BNK2SET ; make sure we are pointing to second bank + lda BNK2SET ; okay + +MSFIX0 lda MOUSEST ; get status byte + tay ; save for a sec + and #$20 ; moved since last time? + beq CHKM1 ; nope + sta MSMOVEF ; show movement +MSFIX1 lda MOUSEXL ; get mouse X pos + sta MSX ; save new one +MSFIX2 lda MOUSEYL ; and the y pos + sta MSY ; save for me +CHKM1: + tya ; get status back + and #$C0 ; is button down? + beq CHKMX ; nope + lda #$80 ; show down state +CHKMX: + jmp CHK_BTN ; check button state +; +; there is a mouse, so check it +; +DO_MOUSE: + jsr CHK_MOUSE ; check the mouse please +; FALL THROUGH TO BUTTON CLICKING HANDLER +; jmp DO_BUTTON ; handle button clicking +; +; DO_BUTTON - handle button clicking, working with the timer to +; check for double clicking or not +; +DO_BUTTON: + lda MSMOVEF ; check moved flag + beq DOM01 ; nope + jsr MSCURS ; move mouse cursor +DOM01: + lda #0 ; show no char + ldy MSBTNF ; check button flag + bpl DOBX ; none +; +; button strike, check for double click +; + sty JB_STATE ; show new state + ldy CLKCTR ; have we started click counter? + bpl DOB02 ; nope + ldy #1 ; this resets counter + sty CLKCTR ; reset it + lda #DBL_CLK ; show double click char + bne DOBEXIT ; and finis +DOB02: + ldy #-CLK_CNT ; set to double click timeout + sty CLKCTR ; okay + bmi DOBEXIT ;done +DOBX: + ldy CLKCTR ; click counter counting? + bpl DOBEXIT ; nope + inc CLKCTR ; count it then + bne DOBEXIT ; all done + ldy #1 ; reset counter + sty CLKCTR ; okay + lda #SGL_CLK ; set as char +DOBEXIT: + ldy #0 ; clear out flags + sty MSBTNF ; button flag + sty MSMOVEF ; moved flag + tay ; set flag to show any char + rts ; return char +; +; DO_STICK - handle the joystick 'interrupt' +; +DO_STICK: + jsr MOVE_STICK ; first move it + jmp DO_BUTTON ; now handle it +MOVE_STICK: + lda #0 ; get horizontal change + jsr READ_STICK ; puts value in Y + cpy #80 ; if < 80, then jump to the left + bcs DOST1 ; it is not + lda MSX ; make sure X is > 0 + beq DOST2 ; it is == 0, can't get smaller + sta MSMOVEF ; show movement + dec MSX ; move one to the left + dec MSX ; move two to the left + bne DOST2 ; now check vertical +DOST1: + cpy #180 ; if > 160, then move right + bcc DOST2 ; nope + lda MSX ; make sure X is in bounds + cmp #MAXWIDTH-4 ; don't go too far + bcs DOST2 ; already maxxed out + sty MSMOVEF ; show movement + inc MSX ; one step to the left + inc MSX ; and another one +DOST2: + lda #1 ; now check vertical + jsr READ_STICK ; ask the monitor + cpy #80 ; if < 80, move up + bcs DOST3 ; nope + lda MSY ; don't go negative + beq DOST4 ; already minned out + sta MSMOVEF ; show movement + dec MSY ; count down + dec MSY ; twice + bne DOST4 ; all done +DOST3: + cpy #180 ; check for downward motion + bcc DOST4 ; none + lda MSY ; check for maximum + cmp #MAXHEIGHT-3 ; don't go below water + bcs DOST4 ; gone, thanx + sty MSMOVEF ; show movement + inc MSY ; go further down + inc MSY ; twice as far for joystick +DOST4: + rts ; done +; +; READ_STICK - read the x or y value of the stick in mind. +; [A] == 0 or 1 - the "stick" you are interested in +; Also, check the button status. +; +JB_STATE db 0 ; last state of joystick button +READ_STICK: + pha ; save which stick we want + ldx #$E0 ; oh, pick something random +READST2: + jsr CHECK_JOYBTN ; check the joystick button + dex + bne READST2 + pla ; get x back + tax ; got it + lda RDROM ; bring ROM back + jsr MPREAD ; NOW do the read + lda BNK2SET ; back to RAM + lda BNK2SET ; back to RAM + rts +CHECK_JOYBTN: + lda MOUSEF ; check which kind to move + bpl DO_JBTN ; no joystick, check mouse + jmp CHK_MOUSE ; then do the mouse +DO_JBTN: + lda APKEY1 ; get joystick button +CHK_BTN: + bmi READST3 ; button down + sta JB_STATE ; show button went up +READST3: + eor JB_STATE ; toggle previous state + sta MSBTNF ; set button flag + rts +; ---------------------------- +; FETCH ASCII KEYCODE INTO [A] +; ---------------------------- +; EXIT: ASCII IN [A] & [IOCHAR] + +GETKEY: + lda #BLINK_RATE ; flag as wait for good key + sta CURCOUNT ; clear blinker + lda MOUSEF ; is there a mouse/joystick? + beq GTK0 ; nope + jsr MSCON ; turn on mouse cursor +GTK0: + lda #0 ; clear line counter + sta LINCNT ; okay, we did + txa ; SAVE [X] & [Y] + pha + tya + pha +GKEY0: + inc RAND+HI ; just whack on random number + dec RAND+LO ; and more + jsr FKEYX ; is there a key? + bmi GKEY01 ; got the key + + jsr WAIT10 ; wait .1 seconds, moving mouse cursor + + lda MOUSEF ; do we have a joystick/mouse? + beq GKEY02 ; nope + lda PTR_COUNT ; count down counter? + beq GKEY00 ; nope + dec PTR_COUNT ; count one wait cycle + bne GKEY02 ; don't check yet +GKEY00: + jsr CHECK_JOYBTN ; check the joystick button, just fur the heckuvit +GKEY02: + dec CURCOUNT ; down one + bne GKEY0 ; no toggle + jsr STCUR ; okay, toggle + lda #BLINK_RATE ; 1 per second + sta CURCOUNT ; okay + bne GKEY0 ; check for key +GKEY01: + pha ; save char + lda MOUSEF ; any mouse cursor? + beq GTK1 ; nope + jsr MSCOFF ; turn mouse cursor off +GTK1: + pla ; get char back + jsr ERCUR ; so erase cursor +CHKKEY: + jsr PARSEKEY ; how was the key? + bcs GKEY0 ;TRY AGAIN + sta IOCHAR ;HOLD ON TO IT + pla ; RESTORE + tay ; EVERYTHING + pla + tax + lda IOCHAR ; GET CHAR INTO [A] + rts ; AND RETURN IT + +; +; CHECK TO MAKE SURE KEY IS VALID, ONLY ACCEPT IT IF IT IS +; +PARSEKEY: + and #$7F ;SCREEN OUT SHIFTS +; +;CHECK FOR "ARROWS" & FUNCTION KEYS (X), CONVERT FOR USE (EZIP) +;ALSO : CHANGE <_>)@%^&*( TO ,-.0256789 - and 'mouse' clicks +; and other kinds of special chars +; +GK0: + ldx #ENDKEY ; GET LENGTH OF LIST +GK2: + cmp HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + beq GK3 ; FOUND IT + dex + bpl GK2 ; CHECK THEM ALL + bmi GK4 ; NOT FOUND, CONTINUE OTHER CHECKS +GK3: + lda WANT,X ; GET KEY TO USE INSTEAD + clc ; show niceness + rts ; done +GK4: + cmp #SPACE ; NO CTRL CHARS ACCEPTABLE + bcc BADKEY ; IF < SPACE, BAD + + cmp #'<' ; pick up numbers and most punctuation + bcc OK ; we did + + cmp #'z'+1 ;PICK OUT LETTERS NOW + bcs BADKEY ;IF > BAD + cmp #'a' + bcs OK ;IF > OK + cmp #'A' + bcc BADKEY + CMP #'Z'+1 + BCC OK ;IF < OK +BADKEY: + jsr BEEP ;BAD KEY, GIVE WARNING NOISE, gwon back + sec ; show badness + rts ; and done +OK: + cmp #'0' ; check for number keys + bcc OKj ; nope, < 0 + cmp #'9'+1 ; more than a nine? + bcs OKj ; ayyup +; +; here we check for the closed apple key being down too +; + ldx APKEY2 ; how about the closed apple key + bpl OKj ; not pressed, so use as number key +; +; transform number key into a function key +; + CLC ; get ready for add + ADC #84 ; transforms '1'-'9' to 133-141 + CMP #132 ; but '0' wants to be a 142! + BNE OKj ; but it's not it + CLC ; again, don't want carry + ADC #10 ; voila! +OKj: + clc ; show a wicked good character is about to arrive + rts ; toots finis + +HAVE: DB $0B,$0A,$08,$15,$7f,ESCAPE,$3C,$7C,$3F + DB $3C,$5F,$3E,$40,$25,$5E,$26,$01,$02, EOL +WANT: DB 129,130,131,132,08,ESCAPE,$3C,$7C,$3F + DB $2C,$2D,$2E,$32,$35,$36,$37,254,253, EOL +ENDKEY EQU $-WANT-1 + + END + + diff --git a/apple/yzip/rel.15/macros.asm b/apple/yzip/rel.15/macros.asm new file mode 100644 index 0000000..645c8b0 --- /dev/null +++ b/apple/yzip/rel.15/macros.asm @@ -0,0 +1,120 @@ + STTL "--- MACROS ---" + PAGE + +; +; MACROS for Apple ][ Yzip +; +DLINE: .MACRO STRING,SLEN + ldx #STRING ; get other part of string + IFMA 2 ; check to see if length passed in + ldy SLEN ; then just fetch it + ELSE + ldy #STRING|L ; get length of string + ENDIF + jsr DLINE ; print the string + .MACEND +; +; ProDOS macros +; +PRODOS: .MACRO CODE, PADDR + jsr $BF00 ; ProDOS handler + DB CODE ; ProDOS function code + DW PADDR ; Function Parameter Block address + .MACEND + +QUIT: .MACRO PBLOCK + PRODOS $65, PBLOCK + .MACEND + +READ_BLOCK: .MACRO PBLOCK + PRODOS $80, PBLOCK + .MACEND + +WRITE_BLOCK: .MACRO PBLOCK + PRODOS $81, PBLOCK + .MACEND + +GET_TIME: .MACRO PBLOCK + PRODOS $82, PBLOCK + .MACEND + +CREATE: .MACRO PBLOCK + PRODOS $C0, PBLOCK + .MACEND + +DESTROY: .MACRO PBLOCK + PRODOS $C1, PBLOCK + .MACEND + +RENAME: .MACRO PBLOCK + PRODOS $C2, PBLOCK + .MACEND + +SET_FILE_INFO: .MACRO PBLOCK + PRODOS $C3, PBLOCK + .MACEND + +GET_FILE_INFO: .MACRO PBLOCK + PRODOS $C4, PBLOCK + .MACEND + +ONLINE: .MACRO PBLOCK + PRODOS $C5, PBLOCK + .MACEND + +SET_PREFIX: .MACRO PBLOCK + PRODOS $C6, PBLOCK + .MACEND + +GET_PREFIX: .MACRO PBLOCK + PRODOS $C7, PBLOCK + .MACEND + +OPEN: .MACRO PBLOCK + PRODOS $C8, PBLOCK + .MACEND + +NEWLINE: .MACRO PBLOCK + PRODOS $C9, PBLOCK + .MACEND + +READ: .MACRO PBLOCK + PRODOS $CA, PBLOCK + .MACEND + +WRITE: .MACRO PBLOCK + PRODOS $CB, PBLOCK + .MACEND + +CLOSE: .MACRO PBLOCK + PRODOS $CC, PBLOCK + .MACEND + +FLUSH: .MACRO PBLOCK + PRODOS $CD, PBLOCK + .MACEND + +SET_MARK: .MACRO PBLOCK + PRODOS $CE, PBLOCK + .MACEND + +GET_MARK: .MACRO PBLOCK + PRODOS $CF, PBLOCK + .MACEND + +SET_EOF: .MACRO PBLOCK + PRODOS $D0, PBLOCK + .MACEND + +SET_BUF: .MACRO PBLOCK + PRODOS $D1, PBLOCK + .MACEND + +GET_BUF: .MACRO PBLOCK + PRODOS $D2, PBLOCK + .MACEND + + END + + \ No newline at end of file diff --git a/apple/yzip/rel.15/main.asm b/apple/yzip/rel.15/main.asm new file mode 100644 index 0000000..927d138 --- /dev/null +++ b/apple/yzip/rel.15/main.asm @@ -0,0 +1,328 @@ + STTL "--- MAIN LOOP ---" + PAGE + +MD_ADDR EQU ZBEGIN +MDEBUG EQU 1 + +MLOOP: + IF 0 + lda MD_ADDR ; get interesting address + bne MLOOPx ; just fine, thank you + brk ; then die +MLOOPx: + ENDIF + + lda #0 + sta NARGS ; reset number of args + lda PAGE2SW+OFF ; just do this for the heck of it + lda BNK2SET + lda BNK2SET + sta STORE80+ON ; must always be on + + jsr NEXTPC ; get op code + sta OPCODE ; SAVE IT HERE + + IF MDEBUG +; +; special debugging code +; + ldy SPCSV + lda OPCODE + sta SAVEOP,Y + lda ZPCH + sta SAVEZH,Y + lda ZPCM + sta SAVEZM,Y + lda ZPCL + sta SAVEZL,Y + lda ZPCBNK + sta SAVEZB,Y + lda ZPCPNT+HI + sta SAVEZP,Y + ldy SPCSV + iny + tya + and #$0F + sta SPCSV + lda OPCODE + bne MAINDB +SPCSV: db 0 + ORG $+15 + ORG $.SHR.4 + ORG $.SHL.4 +SAVEOP: ds 16 +SAVEZH: ds 16 +SAVEZM: ds 16 +SAVEZL: ds 16 +SAVEZB: ds 16 +SAVEZP: ds 16 +MAINDB: + ENDIF +; +; DECODE AN OPCODE +; + tay ; 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: CMP #236 ; XCALL? + BNE OPX5 + JMP OPXCLL ; YES, PROCESS SEPARATELY +OPX5: CMP #250 ; IXCALL + BNE OPX6 + JMP OPXCLL +OPX6: 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 + CMP #$C0 ; IS IT NEW OPCODE RANGE? + BCC ZEXTOP ; YES + JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + +DOXOP: AND #%00011111 ; ISOLATE ID BITS + TAY + LDA OPTXL,Y + STA GOX+1+LO + LDA OPTXH,Y + STA GOX+1+HI +GOX: JSR $FFFF ;DUMMY + JMP MLOOP + + ; HANDLE EXTENDED OPCODE RANGE OPS + +ZEXTOP: CMP #EXTLEN ; OUT OF RANGE? + BCS BADEXT + TAY ; OFFSET ALREADY CORRECT + LDA EXTOPL,Y + STA GOE+1+LO + LDA EXTOPH,Y + STA GOE+1+HI +GOE: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #1 -- ILLEGAL X-OP *** + +BADOPX: LDA #1 + JMP ZERROR + + ; *** ERROR #16 -- ILLEGAL EXTENDED RANGE X-OP *** + +BADEXT: LDA #16 + JMP ZERROR + + ; HANDLE AN XCALL OPCODE + +OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + STA ABYTE + JSR NEXTPC + STA BBYTE + LDA ABYTE ; ONE TO START WITH + LDX #0 + STX ADEX ; INIT ARGUMENT INDEX + BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP +XCALL1: LDA ABYTE ; GET ARG BYTE + ASL A ; SHIFT NEXT 2 BITS + ASL A ; INTO BITS 7 & 6 + STA ABYTE ; HOLD FOR LATER +XCALL2: AND #%11000000 ; MASK OUT GARBAGE + BNE XCALL3 + JSR GETLNG ; 00 = LONG IMMEDIATE + JMP XCNXT +XCALL3: CMP #%01000000 ; SHORT IMMED? + BNE XCALL4 ; NO, TRY ANOTHER + JSR GETSHT ; 01 = SHORT IMMED. + JMP XCNXT +XCALL4: CMP #%10000000 ; LAST TEST + BNE OPX4 ; 11 = NO MORE ARGS + JSR GETVAR ; 10 = VARIABLE +XCNXT: LDX ADEX + LDA VALUE+LO + STA ARG1+LO,X + LDA VALUE+HI + STA ARG1+HI,X + INC NARGS + INX + INX + STX ADEX + CPX #16 + BNE XCALL5 + JMP OPX4 ; DONE, GO DO IT +XCALL5: CPX #8 ; DONE 1ST MODE BYTE? + BNE XCALL1 ; NOT QUITE YET + LDA BBYTE ; SET UP FOR NEXT + STA ABYTE ; MODE BYTE + JMP XCALL2 ; GO DO IT + +; ------------- +; HANDLE A 0-OP +; ------------- + +OP0: CMP #190 ; IS IT EXTOP OP + BEQ EXTOP ; YES + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT0L,Y + STA GO0+1+LO + LDA OPT0H,Y + STA GO0+1+HI +GO0: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #2 -- ILLEGAL 0-OP *** + +BADOP0: LDA #2 + JMP ZERROR + + ; THIS OPCODE TELLS THAT NEXT OP IS PART OF THE + ; EXTENDED RANGE OF OPCODES, GET IT AND PROCESS IT + ; (THEY ARE ALL XOPS) + +EXTOP: JSR NEXTPC ; GO GET EXTENDED RANGE OP + STA OPCODE ; SAVE IT + JMP OPEXT ; AND HANDLE IT + + +; ------------- +; HANDLE A 1-OP +; ------------- + +OP1: + and #%00110000 ; ISOLATE ARGUMENT BITS + bne OP1A + jsr NEXTPC ; get next byte + tay + jmp OP1A1 +OP1A: and #%00100000 ; TEST AGAIN + bne OP1B +; +; 01 = SHORT IMMEDIATE +; +OP1A1: sta ARG1+HI + jsr NEXTPC + sta ARG1+LO + inc NARGS + jmp OP1EX1 +OP1B: JSR GETVAR ; 10 = VARIABLE +OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] +OP1EX1: LDA OPCODE + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT1L,Y + STA GO1+1+LO + LDA OPT1H,Y + STA GO1+1+HI +GO1: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** ERROR #3 -- ILLEGAL 1-OP *** + +BADOP1: LDA #3 + JMP ZERROR + + + +; ------------- +; HANDLE A 2-OP +; ------------- + +OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT + BNE OP2A +; +; 0 = SHORT IMMEDIATE +; + sta ARG1+HI + jsr NEXTPC + sta ARG1+LO + inc NARGS + jmp OP2B1 +OP2A: jsr GETVAR ; 1 = VARIABLE +OP2B: jsr V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] +OP2B1: lda OPCODE ; RESTORE OPCODE BYTE + and #%00100000 ; ISOLATE 2ND ARG BIT + bne OP2C + sta ARG2+HI + jsr NEXTPC + sta ARG2+LO + jmp OP2D1 +OP2C: jsr GETVAR ; 1 = VARIABLE +OP2D: lda VALUE+LO ; MOVE 2ND [VALUE] + sta ARG2+LO ; INTO [ARG2] + lda VALUE+HI + sta ARG2+HI +OP2D1: inc NARGS ; UPDATE ARGUMENT COUNT + + ; EXECUTE A 2-OP OR EXTENDED 2-OP + +OP2EX: LDA OPCODE + AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT2L,Y + STA GO2+1+LO + LDA OPT2H,Y + STA GO2+1+HI +GO2: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 + diff --git a/apple/yzip/rel.15/objects.asm b/apple/yzip/rel.15/objects.asm new file mode 100644 index 0000000..a7f6f78 --- /dev/null +++ b/apple/yzip/rel.15/objects.asm @@ -0,0 +1,167 @@ + STTL "--- OBJECT & PROPERTY HANDLERS ---" + PAGE + +; ---------------------------------- +; GET ABSOLUTE ADDRESS OF OBJECT [A] +; ---------------------------------- +; ENTER: OBJECT IN A/X (LO/HI) +; EXIT: ADDRESS IN [FPC] +OBJLOC: + STX I+HI ; SAVE MSB FOR SHIFTING + ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) + STA I+LO + ROL I+HI + LDX I+HI + ASL A + ROL I+HI ; *4 + ASL A + ROL I+HI ; *8 + ASL A + ROL I+HI ; *16 + SEC + SBC I+LO ; -(*2) + STA I+LO ; SO IS *14 TOTAL + LDA I+HI + STX I+HI + SBC I+HI + STA I+HI + LDA I+LO + CLC + ADC #112 ; ADD OBJECT TABLE OFFSET + BCC OBJ3 + INC I+HI +OBJ3: + clc ; NEXT ADD THE relative ADDR + adc ZBEGIN+ZOBJEC+1 ; OF THE OBJECT TABLE + sta FPCL ; save lo byte + lda I+HI + adc ZBEGIN+ZOBJEC ; now work on page + jsr SETPC ; now get page/bank + sta FPCH ; this is hi part + sty FPCBNK ; and this is the bank + rts +; ----------------------------- +; GET ADDRESS OF PROPERTY TABLE +; ----------------------------- +; EXIT: [FPC] HAS ABSOLUTE ADDR OF PROPERTY TABLE +; including OFFSET TO START OF PROP IDS +PROPB: + lda ARG1+LO + ldx ARG1+HI ; get address + jsr OBJLOC ; put table location into FPC + lda #12 ; add 12 to get to beginning + jsr ADDFPC ; and add it to FPC + jsr FETCHB ; get MSB of P-TABLE Address + pha ; and save it for a moment + jsr NEXTFPC ; to get LSB + jsr FETCHB ; get LSB of P-TABLE Address + sta FPCL ; and save lo part + pla ; get page back + jsr SETPC ; and set up memory bank/page + sta FPCH ; save page + sty FPCBNK ; and bank + jsr FETCHB ; get length of short description + asl A ; WORD-ALIGN IT + jsr ADDFPC ; and add it to FPC + jsr NEXTFPC ; POINT JUST PAST THE DESCRIPTION + rts + + +; ------------------- +; FETCH A PROPERTY ID +; ------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +; +PROPN: + jsr FETCHB ; get the byte + and #%00111111 ; MASK OUT LENGTH BITS (EZIP) + rts + +; ------------------------------- +; FETCH # BYTES IN PROPERTY VALUE +; ------------------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +; +PROPL: + jsr FETCHB ; CHECK LENGTH FLAGS + tax ; save it + bpl SHORT ; OFF, SO 1 OR 2 BYTES + jsr NEXTFPC + jsr FETCHB ; NEXT BYTE HAS LENGTH + and #%00111111 ; MASK OFF EXTRA BITS + rts +SHORT: + and #%01000000 ; BIT 6 + beq ONE + lda #2 ; BIT 6 = 1, LENGTH =2 + rts +ONE: + lda #1 ; BIT 6 = 0, LENGTH =1 + rts + +; ---------------------- +; POINT TO NEXT PROPERTY +; ---------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - in [FPC]) +; +PROPNX: + jsr PROPL ; GET LENGTH OF CURRENT PROP + tay ; move one more for correct alignment + iny ; okay, done it + tya ; thanks + jsr ADDFPC ; add to [FPC] + rts +; +; ---------------- +; GET OBJECT FLAGS +; ---------------- +; ENTRY: OBJECT # IN [ARG1], FLAG # IN [ARG2] +; EXIT: FLAG WORD IN [K], BIT ID IN [J], +; FLAG WORD ADDRESS IN [FPC] +; +FLAGSU: + LDA ARG1+LO ; get table offset + LDX ARG1+HI + JSR OBJLOC ; GET OBJECT ADDR IN [FPC] + LDA ARG2+LO ; LOOK AT FLAG ID + CMP #$10 ; FIRST SET OF FLAGS? + BCC FLS1 ; YES, ADDR IN [FPC] IS CORRECT + SBC #16 ; ELSE ZERO-ALIGN FLAG INDEX + TAX ; SAVE IT HERE + CMP #$10 ; CHECK IF IN 2ND WORD + BCC FLS ; YES, GO ALIGN FOR THAT + SBC #16 ; ELSE ALIGN TO 3RD WORD + TAX + lda #4 ; 3rd Flag word + bne FLSx ; and add it in +FLS: + lda #2 ; 2nd Flag word +FLSx: + jsr ADDFPC +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: + jsr FETCHB ; MOVE THE FLAG WORD + sta K+HI ; INTO [K] - FIRST THE MSB + jsr NEXTFPC ; and then get get LSB + jsr FETCHB + sta K+LO ; THEN THE LSB + jmp PREVFPC ; point back to flag word + + END + \ No newline at end of file diff --git a/apple/yzip/rel.15/ops012.asm b/apple/yzip/rel.15/ops012.asm new file mode 100644 index 0000000..329d754 --- /dev/null +++ b/apple/yzip/rel.15/ops012.asm @@ -0,0 +1,1215 @@ + STTL "--- 0-OPS ---" + PAGE + + +; ----- +; 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: LDX #5 ;MOVE ZPC INTO MPC +ZPRI1: + LDA ZPC,X + STA MPC,X + DEX + BPL ZPRI1 ;NO NEED TO VALIDATE AS ZPC WAS VALID ANYWAY + JSR PZSTR ; PRINT THE Z-STRING AT [MPC] + LDX #5 ; COPY STATE OF [MPC] +ZPRI2: LDA MPC,X ; INTO [ZPC] + STA ZPC,X + DEX + BPL ZPRI2 + RTS + + +; ------ +; PRINTR +; ------ +; DO A "PRINTI," FOLLOWED BY "CRLF" AND "RTRUE" + +ZPRR: JSR ZPRI + JSR ZZCRLF + JMP ZRTRUE + + +; ------ +; RSTACK +; ------ +; "RETURN" WITH VALUE ON STACK + +ZRSTAK: JSR POPVAL ; GET VALUE INTO [X/A] + JMP ZRT1 ; AND GIVE IT TO "RETURN" + + +; ----- +; CATCH +; ----- + +ZCATCH: LDX OLDZSP+HI ; RETURN ZSTACK POINTER AS + LDA OLDZSP+LO ; ZRET WILL NEED IT + JMP PUTBYT + + +; --------- +; ORIGINAL? +; --------- + +; COPY PROTECTION DEVICE, RETURNS TRUE FOR NOW + +ZORIG: JMP PREDS + + + STTL "--- 1-OPS ---" + PAGE + + +; ----- +; 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC ; GET OBJECT ADDR INTO [FPC] + lda #8 ; POINT TO "NEXT" SLOT (EZIP) + jsr ADDFPC ; and point to it + jmp FIRST1 ; JMP to get it + +; ------ +; FIRST? +; ------ +; RETURN "FIRST" POINTER IN OBJECT [ARG1] ; +; FAIL IF LAST AND RETURN ZERO +; (EZIP ALTERATIONS) + +ZFIRST: + lda ARG1+LO + ldx ARG1+HI + jsr OBJLOC ; GET OBJECT ADDR INTO [FPC] + lda #10 ; point to "First" slot + jsr ADDFPC ; and add it +FIRST1: + jsr FETCHB ; and get it + pha ; save it + jsr NEXTFPC + jsr FETCHB ; and next one + tay ; now dance around a little; save LSB + pla ; get MSB back + tax ; and put to x + tya ; and put LSB back into [A] + jsr PUTBYT ; PASS IT TO VARIABLE + lda VALUE+LO ; EXAMINE THE VALUE JUST "PUT" + bne PFINE + lda VALUE+HI + beq PYUCK ; FAIL IF IT WAS ZERO +PFINE: + jmp PREDS ; ELSE REJOICE + +; --- +; LOC +; --- +; RETURN THE OBJECT CONTAINING OBJECT [ARG1] ; +; RETURN ZERO IF NONE +; (EZIP ALTERED) + +ZLOC: + lda ARG1+LO + ldx ARG1+HI + cpx #$20 ; don't let it get too high + bcc ZLOC1 ; fine + lda #22 ; too big object + jmp ZERROR ; and die +ZLOC1: + jsr OBJLOC ; GET ADDR OF OBJECT INTO [FPC] + lda #6 ; POINT TO "LOC" SLOT + jsr ADDFPC ; and make FPC point there + jsr FETCHB ; go get byte + pha ; save this please + jsr NEXTFPC ; and point to next one + jsr FETCHB ; and get it in [A] + tay ; save LSB + pla ; get MSB back + tax ; and put to [X] + tya ; and put LSB into a + jmp PUTBYT ; AND SHIP IT OUT + +; ------ +; PTSIZE +; ------ +; RETURN LENGTH OF PROP TABLE [ARG1] IN BYTES + +ZPTSIZ: + lda ARG1+HI ; MOVE ABS ADDR OF + jsr SETPC ; get bank/page + sta FPCH ; save page + sty FPCBNK ; and bank + lda ARG1+LO + sta FPCL ; and save lo part + jsr PREVFPC ; Decrement address while moving LSB +PTZ0: + jsr FETCHB ; get length of property + bmi PTZ2 ; BIT 7 = 1, LENGTH > 2 BYTES + and #%01000000 + beq PTZ1 ; BIT 6 = 0, LENGTH = 1 + lda #2 ; BIT 6 = 1, LENGTH = 2 + bne PTZ3 ; JMP +PTZ1: + lda #1 + bne PTZ3 ; JMP +PTZ2: + jsr FETCHB ; and get it + and #%00111111 ; ELSE PICK UP SIZE > 2 +PTZ3: + ldx #0 ; CLEAR FOR PUTBYT + jmp PUTBYT +; --- +; INC +; --- +; INCREMENT VARIABLE [ARG1] + +ZINC: LDA ARG1+LO + JSR VARGET ; FETCH VARIABLE INTO [VALUE] + INC VALUE+LO + BNE ZINC1 + INC VALUE+HI +ZINC1: JMP ZD0 + + +; --- +; DEC +; --- +; DECREMENT VARIABLE [ARG1] + +ZDEC: LDA ARG1+LO + JSR VARGET ; FETCH VAR INTO [VALUE] + LDA VALUE+LO + SEC + SBC #1 + STA VALUE+LO + LDA VALUE+HI + SBC #0 + STA VALUE+HI +ZD0: LDA ARG1+LO ; PUT RESULT BACK + JMP VARPUT ; INTO THE SAME VARIABLE + + +; ------ +; PRINTB +; ------ +; PRINT Z-STRING AT [ARG1] + +ZPRB: + lda ARG1+LO ; move arg1 to I + sta I+LO ; lo part + lda ARG1+HI ; and now for arg1 hi + sta I+HI ; okay + jsr SETWRD ; make [MPC] point to it + jmp PZSTR ; and print it + +; ------ +; REMOVE +; ------ +; MOVE OBJECT [ARG1] INTO PSEUDO-OBJECT #0 +; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO +; 2) MOVES AND COMPARES 2 BYTES) + +SAVEFPC: ds 3 ; spot to save the FPC +SAVEOBJ: ds 1 ; check for zero object + +ZREMOV: + lda ARG1+LO ; GET SOURCE OBJECT ADDR + ldx ARG1+HI + jsr OBJLOC ; INTO [FPC] +; +; now save this objects address in I,J +; + lda #6 ; point to the LOC slot + jsr ADDFPC ; thank you + lda FPCL ; COPY THE SOURCE ADDR + sta SAVEFPC+LO ; INTO [J] + lda FPCH ; FOR LATER REFERENCE + sta SAVEFPC+HI + lda FPCBNK + sta SAVEFPC+ABANK +; +; now go get object this one is in +; + jsr FETCHB ; get the data + sta K ; HOLD IT + jsr NEXTFPC ; get lo part + jsr FETCHB ; now get part + tay ; save it + ora K ; COMPARE BYTES + bne REMVj ; check for object + jmp REMVEX ; SCRAM IF NO OBJECT +REMVj: + tya ; get lo part + ldx K ; and hi part + jsr OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [FPC] + lda #11 ; POINT TO "FIRST" SLOT, LSB + jsr ADDFPC ; and point to it + jsr FETCHB ; and get it + pha ; save LSB + jsr PREVFPC ; point to MSB + jsr FETCHB ; A=LO, X=HI + tax ; put into x + pla ; get LSB back + cmp ARG1+LO ; IS THIS THE FIRST? + bne REMVC1 ; NO, KEEP SEARCHING + cpx ARG1+HI ; HM? + beq DO_REMOVE ; yes, so use it +REMVC1: + jsr OBJLOC ; get object + lda #9 ; GET "NEXT" slot address + jsr ADDFPC ; into FPC + jsr FETCHB ; get the byte + pha ; save LSB for later + jsr PREVFPC ; and this is the hi part + jsr FETCHB + sta SAVEOBJ ; save for later check + tax ; and put into x for (possible) check + pla ; get lo part back + tay ; save a minute + ora SAVEOBJ ; well, is it zero? + bne REMVC2 ; no, so check it + lda #21 ; so die + jmp ZERROR ; and croak +REMVC2: + tya ; put back into [A] + cmp ARG1+LO ; FOUND IT? + bne REMVC1 ; NO, KEEP TRYING + cpx ARG1+HI + bne REMVC1 +DO_REMOVE: +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; copied +; +; now get removed one's address for fetching +; + lda SAVEFPC+ABANK ; this is where bank is + sta FPCBNK ; so show it + lda SAVEFPC+HI ; and here's the hi/lo part + sta FPCH + lda SAVEFPC+LO + sta FPCL + lda #2 ; so get to source's "NEXT" slot + jsr ADDFPC ; point to next slot + jsr FETCHB ; get the hi byte + jsr STASHB ; and save it + jsr NEXTSPC ; point to next one + jsr NEXTFPC ; and from the source too + jsr FETCHB ; get lo byte + jsr STASHB ; and save it away +; +; now zero out SOURCE's loc and next spots +; + lda SAVEFPC+ABANK ; bank of source + sta SPCBNK + lda SAVEFPC+HI ; and addr of source LOC slot + sta SPCH + lda SAVEFPC+LO + sta SPCL +; +; zero out NEXT and LOC of source +; + lda #0 ; zero out 4 locations (LOC MSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (LOC LSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (NEXT MSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (NEXT LSB) + jsr STASHB + jsr NEXTSPC +REMVEX: + RTS + + +; ------ +; PRINTD +; ------ +; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + +ZPRD: + lda ARG1+LO + ldx ARG1+HI ; (EZIP) + jsr OBJLOC ; GET ADDR OF OBJECT INTO [FPC] + lda #13 ; GET PROP TABLE POINTER (EZIP) + jsr ADDFPC ; and point to LSB + jsr FETCHB ; fetch LSB + pha ; SAVE IT HERE + jsr PREVFPC ; and now fetch MSB + jsr FETCHB ; thank you + sta I+HI ; AND MSB + pla ; get LSB back + sta I+LO ; STORE LSB + 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+LO ; RE-SYNC THE + STA ZSP+LO ; Z-STACK POINTER + LDA OLDZSP+HI + STA ZSP+HI + JSR POPVAL ; POP # LOCALS INTO [X/A] + STX I+HI ; SAVE HERE + JSR POPVAL ; now we need number of args + STA ASSVLU ; for ASSIGNED? + + LDX I+HI ; see how many 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 IRET + STA ZPCL + JSR POPVAL + STX OLDZSP+LO + STA OLDZSP+HI + + LDA ZPCL ; check for zero zpc + BNE RETj ; which means we are returning to + LDA ZPCM ; an internal call + BNE RETj ; rather than just a normal + LDA ZPCH ; return + BNE RETj ; but so far it isn't + + JSR A12VAL ; MOVE [ARG1] TO [VALUE] + JMP ZIRET ; so then do internal return +RETj: + JSR VLDZPC ; MAKE VALID + LDA IRET ; CHECK IF SHOULD RETURN A VALUE + BEQ RETYES ; (0 = RET, 1 = NO RETURN) + RTS ; NO, SO JUST GET OUT OF HERE +RETYES: + 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 (QUAD) 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 + + + + STTL "--- 2-OPS ---" + PAGE + + +; ----- +; 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 + + +; ----------------- +; SIGNED COMPARISON +; ----------------- +; ENTRY: VALUES IN [VALUE] AND [I] +; +; IS [VALUE] > [I] +; +COMPAR: + LDA I+HI + EOR VALUE+HI + BPL SCMP + LDA I+HI + CMP VALUE+HI + BCC PGOOD + JMP PREDF + +SCMP: LDA VALUE+HI + CMP I+HI + BNE SCEX + LDA VALUE+LO + CMP I+LO +SCEX: BCC PGOOD + JMP PREDF + + +; --- +; IN? +; --- +; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? +ZIN: + LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [FPC] + LDA #6 ; POINT TO "LOC" SLOT + jsr ADDFPC ; and point to it + jsr FETCHB ; well? + CMP ARG2+HI ; IS IT THERE? + BNE PBAD ; NO + jsr NEXTFPC ; point to lo part + jsr FETCHB ; and get it + CMP ARG2+LO + 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 + + ; FALL THROUGH ... + + +; --------------------- +; RETURN VALUE IN [X/A] +; --------------------- + +VEXIT: STX VALUE+LO + STA VALUE+HI + JMP PUTVAL + + +; ---- +; BAND +; ---- +; RETURN [ARG1] "AND" [ARG2] + +ZBAND: LDA ARG1+LO + AND ARG2+LO + TAX + LDA ARG1+HI + AND ARG2+HI + JMP VEXIT + + +; ----- +; FSET? +; ----- +; IS FLAG [ARG2] SET IN OBJECT [ARG1]? + +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 [FPC] +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; okay, done it + lda K+HI ; FIRST DO MSBS + ora J+HI + jsr STASHB + jsr NEXTSPC + lda K+LO ; THEN LSBS + ora J+LO + jsr STASHB + rts + + +; ------ +; FCLEAR +; ------ +; CLEAR FLAG [ARG2] IN OBJECT [ARG1] + +ZFCLR: + jsr FLAGSU ; GETS BITS INTO [J] & [K], ADDR IN [FPC] +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; okey dokey + + lda J+HI ; FETCH MSB + eor #$FF ; COMPLEMENT IT + and K+HI ; RUB OUT FLAG + jsr STASHB ; and save it + jsr NEXTSPC ; point to lo part + lda J+LO ; SAME FOR LSB + eor #$FF + and K+LO + jsr STASHB ; and show it to the world + 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] +; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + +ZMOVE: + jsr ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS +; +; Make [ARG1] be first in [ARG2]'s chain. +; + lda ARG2+LO + ldx ARG2+HI ; Get parent's address + jsr OBJLOC ; into [FPC] + lda #10 ; point to FIRST slot + jsr ADDFPC ; okay + jsr FETCHB ; get old first one (MSB) + sta K+HI ; save it + jsr NEXTFPC ; point to next part + jsr FETCHB ; and get it + sta K+LO ; okay, saved + jsr FP2SP ; make FPC == SPC +; +; now make object [ARG1] be first in object [ARG2] +; SPC is currently pointing to LSB of [ARG2]'s FIRST slot +; + lda ARG1+LO ; stash away low part first + jsr STASHB ; stashed + jsr PREVSPC ; point to high part + lda ARG1+HI ; get hi part of source + jsr STASHB ; save it +; +; now point to object [ARG1] to update its slots +; + ldx ARG1+HI ; put hi part here + lda ARG1+LO ; and lo part here for OBJLOC + jsr OBJLOC ; get me the SOURCE of all confusion + lda #6 ; point to LOC slot + jsr ADDFPC ; and now FPC points there + jsr FP2SP ; now make it the STASH pointer +; +; update [ARG1]s LOC pointer to be [ARG2] +; SPC points to LOC slot +; + lda ARG2+HI ; get PARENT number + jsr STASHB ; and save it in LOC + jsr NEXTSPC ; and point to LSB of LOC + lda ARG2+LO ; got parent's lowness + jsr STASHB ; and saved it in ARG1 +; +; Move old FIRST object and make it [ARG1]s NEXT +; now SPC points to [ARG1]s NEXT slot +; + jsr NEXTSPC ; point to MSB of NEXT + lda K+HI ; get old FIRST one + jsr STASHB ; and save it + jsr NEXTSPC ; and point to LSB now + lda K+LO ; get LSB of this + jsr STASHB ; saved + 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 + LDA #0 + 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 + ADC #0 ; PICK UP CARRY FROM MPCM + STA MPCH ; TO GET TOP BIT + JMP VLDMPC + + +; ---- +; GETP +; ---- +; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 + +ZGETP: + jsr PROPB ; set up FPC +GETP1: + jsr PROPN ; GET ID OF PROP TBL + cmp ARG2+LO ; Compare PROP ID + beq GETP3 ; FOUND IT + bcc GETP2 ; NOT THERE + jsr PROPNX ; GET NEXT PROP, ALIGN [FPC] TO IT + jmp GETP1 ; TRY AGAIN WITH NEXT PROP +; +; PROPERTY NOT THERE, GET DEFAULT +; +GETP2: + lda ARG2+LO ; GET PROPERTY # + sec ; ZERO-ALIGN IT + sbc #1 + asl A ; WORD-ALIGN IT + clc ; add in table start + adc ZBEGIN+ZOBJEC+1 ; add lo part + sta FPCL ; save for fetch + lda ZBEGIN+ZOBJEC ; now get hi part + adc #0 ; pick up carry, if any + jsr SETPC ; get memory spot for this page + sta FPCH ; page and + sty FPCBNK ; bank + jsr FETCHB ; GET MSB OF PROPERTY + sta VALUE+HI + jsr NEXTFPC + jsr FETCHB ; DO SAME WITH LSB + sta VALUE+LO + jmp PUTVAL ; RETURN DEFAULT IN [VALUE] +GETP3: + jsr PROPL ; GET LENGTH OF PROP INTO [A] + tax ; save [A] + jsr NEXTFPC ; MAKE [FPC] POINT TO 1ST BYTE OF PROP + cpx #1 ; IF LENGTH =1 + beq GETPB ; GET A BYTE PROPERTY + cpx #2 ; IF LENGTH = 2 + beq GETPW ; GET A WORD PROPERTY + + ; *** ERROR #7: PROPERTY LENGTH *** + + LDA #7 + JMP ZERROR +; +; GET A 1-BYTE PROPERTY +; +GETPB: + jsr FETCHB ; GET LSB INTO [A] + sta VALUE+LO ; STORE LSB + lda #0 ; CLEAR MSB + sta VALUE+HI ; and zero it + beq ETPEX +; +; GET A 2-BYTE PROPERTY +; +GETPW: + jsr FETCHB ; GET MSB + sta VALUE+HI ; store MSB + jsr NEXTFPC ; POINT TO LSB + jsr FETCHB ; GET IT INTO [A] + sta VALUE+LO ; AND MSB +ETPEX: + jmp PUTVAL + +; ----- +; GETPT +; ----- +; RETURN POINTER TO PROP TABLE [ARG2] +; IN OBJECT [ARG1] + +ZGETPT: + lda ARG1+LO + ldx ARG1+HI ; (EZIP) + jsr OBJLOC ; put location into [FPC] + lda #12 ; get offset table pointer + jsr ADDFPC ; and point to it + jsr FETCHB ; get MSB of table pointer + pha ; save page + jsr NEXTFPC ; point to LSB + jsr FETCHB ; and get it + sta FPCL ; and save it + pla ; get page address back + jsr SETPC ; and absolutize it + sta FPCH ; and save page + sty FPCBNK ; and bank + jsr FETCHB ; GET LENGTH OF SHORT DESC + asl A ; WORD-ALIGN IT + tay ; now point to just past it + iny ; thank you + tya ; for adding + jsr ADDFPC ; and POINT JUST PAST THE DESCRIPTION +GETPT1: + jsr PROPN ; get prop ID + cmp ARG2+LO ; CHECK ID + beq GETPT2 + bcs DDD ; .GE. so check some more + jmp DORET ; BEYOND IT, SO NOT THERE +DDD: + jsr PROPNX ; point to next one + jmp GETPT1 ; next please +GETPT2: + jsr PROPL ; get the length of this property + jsr NEXTFPC ; INC TO POINT AT PROPERTY VALUE (EZIP) +; +; now subtract absolute address to get relative address for returning +; what a pain in the neck +; + lda FPCBNK ; check which bank we are in + beq GETPB0 ; in main bank, it's easier +; +; if in AUX bank, then we must subtract beginning of AUX mem, then +; add in size of MAIN bank +; + lda FPCH ; get page + cmp #>Z3BEGIN ; in part 2 of aux? + bcs GETPB3 ; ayyup + sec ; and subtract + sbc #>Z2BEGIN ; first page in aux + clc ; now add in how many pages in main + adc #P2PAGE ; now we have relative start + bne GETP15 ; JUMP to putval +GETPB3: + sec ; and subtract + sbc #>Z3BEGIN ; first page in aux, part 2 + clc ; now add in how many pages in main + adc #P3PAGE ; now we have relative start + bne GETP15 ; jump to putval +GETPB0: + lda FPCH ; get page in main mem + sec ; and then subtract + sbc #>ZBEGIN ; start of main mem +GETP15: + sta VALUE+HI ; save hi part for returning + lda FPCL ; and just save lo part + sta VALUE+LO ; okay? + jmp PUTVAL ; AND RETURN +DORET: + jmp RET0 ; ELSE RETURN A ZERO + + +; ----- +; NEXTP +; ----- +; RETURN INDEX # OF PROP FOLLOWING PROP [ARG2] IN OBJECT [AR +; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO + +ZNEXTP: + JSR PROPB ; ALIGN [FPC] AT PROPERTY TBL'S 1ST ENTRY + 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 (EZIP) + JMP NXTP1 +NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +NXTP3: JSR PROPN ; GET THE PROPERTY # + LDX #0 ; FOR PUTBYT (EZIP) + 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 + + +; ----- +; THROW +; ----- + +ZTHROW: + lda ARG2+LO ; check to see if we are ready to do return + cmp OLDZSP+LO + bne ZTHLOOP ; nope, keep unwinding the stack + lda ARG2+HI + cmp OLDZSP+HI ; have we found the right frame yet? + beq ZTHDO ; yes +ZTHLOOP: + jsr ZRET ; do another return + jmp ZTHROW ; and try again +ZTHDO: + lda ARG2+LO ; SET ZSTACK POINTER + sta OLDZSP+LO ; UP FOR ZRET + lda ARG2+HI + sta OLDZSP+HI + jmp ZRET + + END diff --git a/apple/yzip/rel.15/opsx.asm b/apple/yzip/rel.15/opsx.asm new file mode 100644 index 0000000..774df57 --- /dev/null +++ b/apple/yzip/rel.15/opsx.asm @@ -0,0 +1,903 @@ + PAGE + STTL "--- X-OPS ---" + + + ; ------ + ; EQUAL? + ; ------ + ; IS [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? + +ZEQUAL: + DEC NARGS ; DOUBLE-CHECK # ARGS + 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!) + + +; ---------------------------- +; ICALL,ICALL1, ICALL2, IXCALL +; ---------------------------- + +ZICALL: +ZICLL1: +ZICLL2: +ZIXCLL: LDA #1 ; SET FLAG FOR RETURNLESS CALL + STA IRET + BNE IENTR ; JMP OVER NORMAL SETTING + + +; ------------------- +; XCALL, CALL1, CALL2 +; ------------------- + +ZXCALL: ; DROP THROUGH +ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +ZCALL2: + +; ---- +; CALL +; ---- +; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +; ([ARG5]-[ARG8] FOR XCALL (EZIP)) + +ZCALL: LDA #0 + STA IRET ; SET FLAG TO RETURN SOMETHING +IENTR: LDA ARG1+LO + ORA ARG1+HI ; IS CALL ADDRESS ZERO? + BNE DOCALL ; NO, CONTINUE + LDA IRET ; any ret value? + BEQ Ij ; yes, so return a zero + + RTS ; otherwise, just end +Ij: + LDX #0 + JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER + LDA OLDZSP+HI + JSR PUSHXA + LDA ZPCL ; AND LSB OF [ZPC] + LDX IRET ; AND RETURN FLAG + 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 + ASL ARG1+LO ; MULTIPLY [ARG1] + ROL ARG1+HI ; (BY 2) + ROL A ; >BIT INTO [A] + ASL ARG1+LO ; BY 4 (EZIP) + ROL ARG1+HI + ROL A + STA ZPCH ; NEW >BIT OF [ZPC] + LDA ARG1+HI ; GET NEW 0, just ignore! + ORA ARG3+LO + BEQ INTNF ; SAY NOT FOUND + + LDA NARGS ; IS THERE A RECORD SPEC? + CMP #4 + BEQ SET4 +SETDEF: LDA #130 ; NO, SET DEFAULT + STA ARG4+LO + +SET4: LDA ARG4+LO + BEQ SETDEF ; GO BACK AND GET VALUE + LDA #0 ; COMPARE BYTE OR WORD? + ASL ARG4+LO + ROL A ; PICK UP INDICATOR + LSR ARG4+LO ; CLEAR FROM RECORD LENGTH + STA TYPE ; BYTE (0) OR WORD (1) + LDA TYPE ; SET FLAG + BNE SETTBL + LDA ARG1+LO ; IF ONLY BYTE, MOVE IT + STA ARG1+HI ; TO FIRST BYTE CHECKED +SETTBL: + LDA ARG2+LO ; PICK UP TBL ADDR + STA MPCL + LDA ARG2+HI + STA MPCM + LDA #0 + STA MPCH ; ONLY A WORD ADDR, SO IN 1ST 64K + JSR VLDMPC + +INTLP: LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + JSR GETBYT ; GET 1ST BYTE + CMP ARG1+HI ; DOES IT = THE VALUE LOOKING FOR? + BNE INTNXT ; NO + LDA TYPE + BEQ INTFND ; ONLY COMPARING A BYTE SO FOUND! + JSR GETBYT + CMP ARG1+LO + BEQ INTFND ; YES, FOUND IT +INTNXT: + LDA VWCUR+0 ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC ARG4+LO ; ENTRY + STA MPCL + BCC INEXT0 + + LDA VWCUR+1 ; PICK UP CARRY + ADC #0 + STA MPCM + LDA VWCUR+2 + ADC #0 + STA MPCH + JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE + +INEXT0: DEC ARG3+LO ; CHECKED ALL ENTRIES? + BNE INTLP + LDA ARG3+HI + BEQ INTNF + DEC ARG3+HI + BNE INTLP + +INTNF: + LDA #0 ; 0 = NOT FOUND + STA VALUE+LO + STA VALUE+HI + JSR PUTVAL + JMP PREDF ; FAILED! + +INTFND: + LDA VWCUR+LO + STA VALUE+LO ; AND SET TO RETURN THE VALUE + LDA VWCUR+HI + STA VALUE+HI + JSR PUTVAL ; SEND IT BACK + JMP PREDS ; AND SCREEM SUCCESS + +; ---- +; BCOM +; ---- +; COMPLEMENT [ARG1] + +ZBCOM: LDA ARG1+LO + EOR #$FF + STA VALUE+LO + LDA ARG1+HI + EOR #$FF + STA VALUE+HI + JMP PUTVAL + + +; ----- +; COPYT +; ----- + +ZCOPYT: + LDA ARG2+LO ; CHECK OUT WHAT'S TO BE DONE + ORA ARG2+HI + BNE ZC0 + JMP CASE1 ; ZERO LENGTH BYTES OF SOURCE +ZC0: + LDA ARG3+HI + CMP #$7F + BCC CASE2 + JMP CASE3 ; FORWARD COPY + + ; CASE2 - CHECK IF FORWARD OR BACKWARD COPY + +CASE2: LDA ARG1+HI ; IF SRC < DEST + CMP ARG2+HI + BCC CHK2 + BEQ ZC1 + JMP FRWRD ; NO +ZC1: LDA ARG1+LO + CMP ARG2+LO + BEQ CHK2 + BCS FRWRD ; NO +CHK2: LDA ARG1+LO ; AND SRC + LENGTH > DEST + CLC + ADC ARG3+LO + STA I+LO + LDA ARG1+HI + ADC ARG3+HI + CMP ARG2+HI + BCC FRWRD ; NO + BNE BKWRD ; YES + LDA I+LO + CMP ARG2+LO + BEQ FRWRD ; DEBUG, IF EQUAL REALLY LESS + BCS BKWRD ; OVERLAPS SO DO BACKWARD COPY + + ; ELSE FALL THROUGH TO FORWARD COPY + +FRWRD: LDA #0 ; USE GETBYT CAUSE MAY BE + STA MPCH ; BEYOND MAIN MEMORY + LDA ARG1+HI + STA MPCM + LDA ARG1+LO + STA MPCL + JSR VLDMPC ; AND ALIGN TO CORRECT PAGE + LDA ARG2+LO + STA SPCL + LDA ARG2+HI + jsr SETPC ; get memory spot + sta SPCH ; high part + sty SPCBNK ; and the bank part + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI +FRLP: + jsr DECJ + bcc FRDUN ; CARRY CLEAR ON $FFFF + jsr GETBYT + jsr STASHB ; and save it + jsr NEXTSPC ; and point to next one + jmp FRLP +FRDUN: + rts + + +BKWRD: + LDA ARG3+LO ; DECR 1ST TO GET CORRECT OFFSET + STA J+LO + LDA ARG3+HI + STA J+HI + JSR DECJ + LDA ARG1+LO ; SET TO END OF SOURCE & DEST. + CLC + ADC J+LO + sta FPCL ; set up fetch pointer + LDA ARG1+HI + ADC J+HI + jsr SETPC ; and get mem locations + sta FPCH + sty FPCBNK + LDA ARG2+LO + CLC + ADC J+LO + sta SPCL ; and now set up stash pointer + LDA ARG2+HI + ADC J+HI + jsr SETPC ; and get me page/bank + sta SPCH + sty SPCBNK +BKLP: + jsr FETCHB ; get byte + jsr STASHB ; and save it + jsr PREVFPC ; going backwards + jsr PREVSPC ; and here too + jsr DECJ ; RETURNS CARRY CLEAR ON $FFFF + bcs BKLP +BKDUN: + RTS + + ; ZERO LENGTH # OF BYTES OF SOURCE + +CASE1: LDA ARG1+LO + STA SPCL ; set stash pointer + LDA ARG1+HI + jsr SETPC ; get page/bank + sta SPCH + sty SPCBNK + LDA ARG3+LO ; SET UP COUNTER + STA J+LO + LDA ARG3+HI + STA J+HI +C1LP: + jsr DECJ ; CARRY CLEAR WHEN J = $FFFF + bcc C1DUN + lda #0 + jsr STASHB ; and zero it + jsr NEXTSPC ; and point to next one + jmp C1LP +C1DUN: + rts + + ; 2'S COMPLEMENT LENGTH (XOR + 1) THEN DO FORWARD COPY + +CASE3: + LDA ARG3+LO + EOR #$FF + STA ARG3+LO + LDA ARG3+HI + EOR #$FF + STA ARG3+HI + INC ARG3+LO + BNE GOFRWD + INC ARG3+HI +GOFRWD: JMP FRWRD + + +; --------- +; ASSIGNED? +; --------- + + +ZASSND: + LDA ARG1+LO ; COMPARE TO # OF OPTIONALS FROM LAST CALL + CMP ASSVLU + BCC DOYES ; IF LESS OR EQUAL, WAS ASSIGNED + BEQ DOYES + JMP PREDF +DOYES: + JMP PREDS + + +; ------------- +; LOGICAL SHIFT +; ------------- +; SHIFT ARG1, ARG2 BITS (LEFT IF ARG2 IS POS. RIGHT IF NEG.) + +ZSHIFT: LDA ARG1+LO ; SET UP FOR SHIFT + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCS SRIGHT + + ; SHIFT LEFT + + TAY ; COUNT +SLP1: ASL VALUE+LO + ROL VALUE+HI + DEY + BNE SLP1 + JMP PUTVAL ; AND RETURN THE VALUE + +SRIGHT: EOR #$FF ; COMPLEMENT + TAY +SLP2: LSR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL SLP2 + JMP PUTVAL + + +; ---------------- +; ARITHMETIC SHIFT +; ---------------- +; PROPAGATING SIGN BIT ON RIGHT SHIFT + +ZASHFT: LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCC ZSHIFT ; SAME AS LOGICAL SHIFT + LDX ARG1+LO ; SET UP FOR SHIFT + STX VALUE+LO + LDX ARG1+HI + STX VALUE+HI + + EOR #$FF ; COMPLEMENT COUNT + TAY +ASLP2: LDA ARG1+HI + ASL A ; GET SIGN BIT + ROR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL ASLP2 + JMP PUTVAL + +; -------- +; XPUSH +; -------- +ZXPUSH: + lda ARG2+LO ; get me the address of the LTABLE + sta FPCL ; for munging with + lda ARG2+HI ; this is page + jsr SETPC ; get me actual page/bank + sta FPCH ; set page + sty FPCBNK ; and bank + + jsr FETCHB ; this is hi part of counter + sta J+HI ; save it + jsr NEXTFPC ; point to lo part + jsr FETCHB ; get it + sta J+LO ; thanx + ora J+HI ; check for zero elements left + bne ZXP0 ; yes, there is room at the inn + + jmp PREDF ; no room here! +ZXP0: + jsr FP2SP ; set up to stash back in beginning of LTABLE + lda J+HI ; now the MSB + sta K+HI ; and saved it + lda J+LO ; save this + sta K+LO ; save it +; +; now count this one and stash it into the table +; + bne ZXP1 ; nope, dec okay + dec J+HI ; decrement MSB +ZXP1: + dec J+LO ; and the LSB + lda J+LO ; LSB first + jsr STASHB ; saved it + jsr PREVSPC ; point to MSB + lda J+HI ; get it + jsr STASHB ; saved it +; +; finally, we can save the arg into the stack +; + asl K+LO ; make a word offset (*2) + rol K+HI ; pick up carry maybe + lda K+LO ; add in arg offset + clc ; adding + adc ARG2+LO ; figger offset + sta SPCL ; this goes here for stashing + lda K+HI ; now page + adc ARG2+HI ; add in start of table + jsr SETPC ; get me memory page + sta SPCH ; page + sty SPCBNK ; and bank + + lda ARG1+HI ; push MSB + jsr STASHB ; saved + jsr NEXTSPC ; point to next one + lda ARG1+LO ; and now LSB + jsr STASHB ; into the stack + jmp PREDS ; show we worked good +;--------- +; ZFSTACK +;--------- +ZFSTACK: + dec NARGS ; how many args there? + bne ZFS1 ; flush ARG2 stack +; +; pop from system stack +; + lda ARG1+LO ; just add number to system counter + clc ; adding + adc ZSP+LO ; added + sta ZSP+LO ; and saved + lda ARG1+HI ; get hi part + adc ZSP+HI ; add in hi part + sta ZSP+HI ; save hi part + rts +ZFS1: + lda ARG2+LO ; get LTABLE we are interested in + sta FPCL ; set up FPC first + lda ARG2+HI ; and page + jsr SETPC ; tell me where + sta FPCH ; save me where + sty FPCBNK ; FPC all set + jsr FP2SP ; have SPC point to stack too + + jsr FETCHB ; get MSB of counter + sta J+HI ; save MSB + jsr NEXTFPC ; point to LSB + jsr FETCHB ; get LSB + sta J+LO ; save LSB + + lda J+LO ; get LSB back + clc ; get ready for add + adc ARG1+LO ; add how many to get rid off + sta J+LO ; save new counter + lda J+HI ; get MSB + adc ARG1+HI ; add MSB + + jsr STASHB ; save Msb of new counter + jsr NEXTSPC ; point to LSB + lda J+LO ; get lsb + jsr STASHB ; okay, reset the counter + rts + +; +; no mouse stuff yet +; +ZMINFO: +ZMLIMIT: + rts +ZMENU: + jmp PREDF ; no menu stuff either + + END diff --git a/apple/yzip/rel.15/pic.asm b/apple/yzip/rel.15/pic.asm new file mode 100644 index 0000000..09d616f --- /dev/null +++ b/apple/yzip/rel.15/pic.asm @@ -0,0 +1,826 @@ + STTL "--- Picture Op Codes ---" + PAGE +PFILE_RD: ; for READING files + db 4 ; 4 parameters + db 0 ; refnum + dw IOBUFF ; read into io buffer + dw $400 ; 1Kb buffer + dw 0 ; length actually read +PFSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +PICCNT: dw 0 ; counter of the entries +PF_REFNUM: db 0 ; place to store refnum +PF_FID: db $FF ; File ID of local directory data +P_IDX: db 0 +P_BCNT: db 0 +P_LOFF: db 0 +GBL_FLAG: db 0 ; found global directory? +PIC_FLAG: db 0 ; found pictures? +PF_NAME: db 0 ; name we are looking at + db 0 ; name we found + +PICINFO: + ds PLDSIZE ; get room for picture data + +TRANSCLR: DB 0 ; transparent color +UNKPIC: + + db EOL,"Unknown Picture #" +UNKPICL EQU $-UNKPIC +ZDISPL: + jsr CLRBUF ; put out any and all text + + jsr GET_PICINF ; get the necessary data + bcc ZDSP1 ; everything just fine + + DLINE UNKPIC ; unknown picture number error + lda ARG1+HI ; get MSB + jsr HEXNUM ; print it + lda ARG1+LO ; and LSB + jsr HEXNUM + lda #$14 ; bad picture number error + jmp ZERROR ; and croak +ZDSP1: + jsr SAVE_CURSOR ; save the cursor + + lda #0 ; show no cursor change + sta CURSFLG ; start with none, anyway + + dec NARGS ; x,y pos passed? + beq ZDSP10 ; nope, just use as is + + lda ARG2+LO ; get passed y pos + beq ZDSP01 ; don't change + sta SCRCY ; change, then + dec SCRCY ; zero base it + ldy #WINTOP ; get top edge of window + lda (WINDOW),Y ; got it + clc ; get ready for add + adc SCRCY ; add the offset + sta SCRCY ; and make it Y pos + lda #1 ; show cursor change anyway + sta CURSFLG ; okay, we did +ZDSP01: + dec NARGS ; x pos passed? + beq ZDSP10 ; nope + + lda ARG3+LO ; get x pos + beq ZDSP10 ; if == 0, don't change + sta SCRCX ; set as passed + dec SCRCX ; zero base it + ldy #WINLEFT ; get left hand edge of window + lda (WINDOW),Y ; got it + clc ; get ready for add + adc SCRCX ; add the offset + sta SCRCX ; and make it X pos + lda #1 ; show cursor change anyway + sta CURSFLG ; okay, we did +ZDSP10: + lda SCRCX ; get current X + pha ; save it + clc ; adding + adc PICINFO+PLDWID ; add in pic width + sta SCRCX ; save here + pla ; get start X pos back + sta SCRCX ; restored +ZDSP101: + lda PICINFO+PLDFLG ; get flag byte + and #1 ; is there a transparent color? + bne ZDSP11 ; ayyup + lda #$FF ; make TRANSCLR be $FF + bne ZDSP12 ; okay +ZDSP11: + lda PICINFO+PLDFLG ; get hi byte of flag word + lsr A ; put in lower byte + lsr A ; put in lower byte + lsr A ; put in lower byte + lsr A ; put in lower byte +ZDSP12: + sta TRANSCLR ; save transparent color + + lda PICINFO+PLDPTR ; MSB of offset + sta PFSEEK+SM_FPOS+2 ; MSB of seek + lda PICINFO+PLDPTR+1 ; Middle + and #$FE ; seek only to 512byte boundary + sta PFSEEK+SM_FPOS+1 + + SET_MARK PFSEEK ; go to pic data + lda #>PIC1BUF ; set up pointers to decode buffers + sta J+HI + lda #PIC2BUF + sta K+HI + lda #IOBUFF ; now get data buffer address + sta L+HI + lda #4 ; 4 pages read in at once + sta P_BCNT ; okay + lda #3 ; 3 bytes of width data start it + clc ; doing add + adc PICINFO+PLDPTR+2 ; pick up LSB pointer + sta P_IDX ; start index + bcc ZDLPCC ; no wrap + inc L+HI ; start at second one + dec P_BCNT ; one less block +ZDLPCC: + lda PICINFO+PLDPTR+1 ; tells which block it is in + and #$01 ; pick up which 256 block + beq ZDLP0 ; start at first one + inc L+HI ; start at next one + dec P_BCNT ; one less block +ZDLP0: + lda #IOBUFF ; reset data buffer address + sta L+HI + lda #GBL_DIR ; start destination off here + jsr READ_IN_PDATA ; go get global directory, if any + sta GBL_FLAG ; indicate whether there is a global +GTPG1: + lda SAVENUM ; get which file is being opened + and #$0F ; just make it binary + cmp PF_FID ; same as the file we already have? + beq GETPGX ; yes, so don't bother + ldy #SGTPICOF ; point to picture offset + lda #>PIC_DIR ; start destination off here + jsr READ_IN_PDATA ; go get the data for local pictures + sta PIC_FLAG ; any picture data +GETPGX: + rts +; +; READ_IN_PDATA - check for desired data being in file, and skip to it if +; it is. Then, read it in in 1Kb chunks, stashing it away into the +; upper bank of the aux mem language card. +; Enter with: +; [A] = Destination page +; [Y] = Offset into Segment table +; +READ_IN_PDATA: + pha ; save destination page + lda (DSEGS),Y ; get MSB + sta PFSEEK+SM_FPOS+2 ; Byte 2 + iny ; point to LSB + ora (DSEGS),Y ; is there any pic data? + bne GTPD00 ; yes + pla ; get page back + lda #0 ; show not here + rts ; nope +GTPD00: + lda (DSEGS),Y ; get it for shifting + asl A ; *2 + sta PFSEEK+SM_FPOS+1 ; stash away + rol PFSEEK+SM_FPOS+2 ; pick up carry + lda #0 ; clear out MSB + sta PFILE_RD+RD_BUFFLEN+HI + sta PFSEEK+SM_FPOS ; and LSB of seeking + + lda PF_REFNUM ; get file ref number + sta PFILE_RD+RD_REFNUM ; and save it for reading and + sta PFSEEK+SM_REFNUM ; for seeking + + lda #RETRY_COUNT ; set retry + sta NY_DATA ; just use this for now +GTPDRD0: + SET_MARK PFSEEK ; and go to beginning + + lda #4 ; read in 4 256 blocks + sta PFILE_RD+RD_BUFFLEN+HI + READ PFILE_RD ; go get the next 4Kb worth + bcc GTPD1 ; fine + jsr RETRY ; well, do it again? + bcc GTPDRD0 ; yes +GTPD1: + pla ; get destination page back + cmp #>PIC_DIR ; if doing local directory, set up + bne GTPD2 ; picture count + ldx IOBUFF+PHNLD ; get number of pictures + stx PICCNT+HI ; save for count down too + ldx IOBUFF+PHNLD+1 ; and here is LSB + stx PICCNT+LO ; saving for counting + ldx IOBUFF+PHFID ; get file ID + stx PF_FID ; and save for later + ldx #(256/PLDSIZE) ; how many entries in 256 bytes + bne GTPD3 ; done +GTPD2: + ldx IOBUFF ; get MSB of how many + stx PICCNT+HI ; show me + ldx IOBUFF+1 ; get LSB of count + stx PICCNT+LO + ldx #(256/2) ; how many entries / 256 bytes +GTPD3: + stx GTPMOD+1 ; set up how big entry is + sta ALTZP+AUX ; use aux mem for most of this + sta K+HI ; MSB of destination + lda #0 ; clear a few things + sta J+LO ; J = source + sta K+LO ; K = destination + lda #4 ; 4 * (4*256) bytes max + sta PFILE_RD+RD_BUFFLEN+HI ; show the read too + sta P_IDX ; save here for counting +GTPDL: + ldy #0 ; start y + lda #>IOBUFF ; get where source is + sta J+HI ; MSB of source + lda #4 ; 4 blocks worth of 256 + sta P_BCNT ; used as counter + lda BNK1SET ; we be using bank 1 @$D000 + lda BNK1SET ; we be using bank 1 @$D000 +GTPDL1: + lda (J),Y ; get the data byte + sta (K),Y ; store in upper aux + iny ; point to the next one + bne GTPDL1 ; and go get it + + inc J+HI ; next block please + inc K+HI ; for destination too + lda PICCNT+LO ; how many entries? + sec ; doing sbc +GTPMOD: sbc #(256/PLDSIZE) ; how many entries in 256 bytes? + sta PICCNT+LO ; save result + bcs GTPDL2 ; no wrapping + dec PICCNT+HI ; wrap + bmi GTPDLX ; all done if we go negative +GTPDL2: + ora PICCNT+HI ; make sure both are not zero + beq GTPDLX ; if they are, then we are done + dec P_BCNT ; count this block + bne GTPDL1 ; go fetch next 256 bytes + sta ALTZP+MAIN ; swap back to main for read + + lda #RETRY_COUNT ; set retry + sta NY_DATA ; just use this for now +GTPDRD: + READ PFILE_RD ; go get the next 4Kb worth + bcc GTPDRDG ; fine + jsr RETRY ; well, do it again? + bcc GTPDRD ; yes +GTPDRDG: + sta ALTZP+AUX ; and back to aux for working + dec P_IDX ; max 4Kb worth of reading + bne GTPDL ; and read in more +GTPDLX: + sta ALTZP+MAIN ; back to main bank of mem + lda BNK2SET ; back to bank 2 + lda BNK2SET ; yes please + lda #1 ; show we found it + rts ; all done + +GTPFLAG: db 0 ; if 1 when opening next file, then + ; this is the next file, so unable to + ; find picture number +GET_PICINF: + lda #0 ; set flag for double check + sta GTPFLAG ; start at zero +GTPLOOP: + lda ARG1+LO ; check argument for zero + ora ARG1+HI ; is it zero? + bne GTPINDX ; jump to look at first block + clc ; found some pictures + rts ; if zero, just give count +GTPINDX: + ldy ARG1+LO ; get arg, as we are swapping + ldx ARG1+HI ; to aux mem + sta ALTZP+AUX ; look at AUX mem + lda BNK1SET ; bank 1 + lda BNK1SET ; bank 1 + lda PIC_DIR+PHNLD ; get # of entries + sta PICCNT+HI + lda PIC_DIR+PHNLD+1 ; it's in reverse order + sta PICCNT+LO + sty ARG1+LO ; use aux mem zero page + stx ARG1+HI ; for new arg1 + lda #>PIC_DIR ; start at beginning of block + sta MPNTH ; hi part + lda #GBL_DIR ; start at beginning of block + sta MPNTH ; hi part + lda #GE< 1 WORD, CONTINUE + BNE FWM1 + LDA VWLEN+1 + BNE FWM1 + LDA VWLEN+0 + CMP ESIZE + BCC FWFAIL +FWM1: + JMP FWLOOP ; AND TRY AGAIN + +FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD + STA VALUE+LO + LDA VWCUR+1 + STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY + RTS ; WORD VALUE RETURNABLE +FWFAIL: + LDA #0 ; NOT FOUND + STA VALUE+LO + STA VALUE+HI + RTS ; THEN RETURN WITH [VALUE] = 0 +; +; DO UNSORTED SEARCH ON VOCAB TBL IN MPC +; +UNSORTED: + LDA #$FF ; 2'S COMPLEMENT LENGTH + EOR NENTS+HI ; TO GET REAL LENGTH + STA NENTS+HI ; WAS NEGATIVE TO SIGNIFY + LDA #$FF ; UNSORTED VOCAB TBL + EOR NENTS+LO + STA NENTS+LO + INC NENTS+LO ; 2'S CMPL + BNE UNSRT0 + INC NENTS+HI +UNSRT0: + LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + + JSR GETBYT ; GET 1ST BYTE OF ENTRY + CMP OUT ; MATCH 1ST BYTE OF TARGET? + BNE FNEXT ; LESS + JSR GETBYT + CMP OUT+1 ; 2ND BYTE MATCHED? + BNE FNEXT + JSR GETBYT + CMP OUT+2 ; 3RD BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+3 ; 4TH BYTE + BNE FNEXT + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + +FNEXT: LDA VWCUR+LO ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC ESIZE ; ENTRY + STA MPCL + BCC FNEXT0 + + LDA VWCUR+HI ; PICK UP CARRY + ADC #0 + STA MPCM + LDA #0 + STA MPCH + JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE + +FNEXT0: DEC NENTS+LO ; CHECKED ALL ENTRIES? + BNE UNSRT0 + LDA NENTS+HI + BEQ FWFAIL ; GO INDICATE NO FIND + DEC NENTS+HI ; OR DO NEXT 256 ENTRIES + JMP UNSRT0 + + END + \ No newline at end of file diff --git a/apple/yzip/rel.15/screen.asm b/apple/yzip/rel.15/screen.asm new file mode 100644 index 0000000..627a68e --- /dev/null +++ b/apple/yzip/rel.15/screen.asm @@ -0,0 +1,949 @@ + STTL "--- APPLE ][ SCREEN STUFF ---" + PAGE + +; ----------------- +; PRINT CHAR IN [A] AT CV,CH +; ----------------- +; +; uses memory register [L] +; +SAVECY DB 0 ; spot to save current screen y pos +SAVECX DB 0 ; spot for x pos + +CHAR: + sta IOCHAR ; SAVE HERE + txa ; SAVE [X] AND [Y] + pha + tya + pha + + lda IOCHAR ; get it back + cmp #BACKSPACE ; is it backspace with erase? + bne CHCX ; nope + + jmp DO_BSPC ; so handle backspace +CHCX: + cmp #EOL ; is it ? + bne CHCONT ; just let dline handle it + + jmp DO_EOL ; handle +; +; so save some stuff and do all the necessary figgering +; +CHCONT: + ldx SCRCNT ; just stash character + sta SCRBUFF,X ; save it + inc SCRCNT ; and count it +CH_EXIT: + pla ; RESTORE [X] AND [Y] + tay + pla + tax + rts +; +; PUT_NYBBLE - put 4 bits to the screen at SCRCX, SCRCY (the lower 4 bits +; in [A]). +; +PUT_NYBBLE: + sta NY_DATA ; save [A] for mucking with + jsr SETPOS ; set up offsets using SCRCX + + lda #$8 ; start at first bit, left to right + sta DATALOOP ; and init the counter with it +PNY0: + ldx FPCBNK ; which bank + lda PAGE2SW,X ; select it + ldy #0 ; start with zero + lda (FPC),Y ; get it + sta SCR_DATA ; and save it +PNY1: + ldx BITOFF ; get which interesting bit we want + lda GT_BITS,X ; get bit + pha ; save bit pictures + lda DATALOOP ; see if we have done all 4 bits in this 'pixel' + beq PNY_EXIT ; toots finis + lsr DATALOOP ; point to next bit + bit NY_DATA ; is this bit set? + bne PNY_SET ; yes it is, so we will handle different +; +; Bit is clear, so clear appropriate one in the SCR_DATA byte +; + pla ; get bit picture back + eor #$FF ; turn bits all around + and SCR_DATA ; turn off bit in screen data + jmp PNY_NEXT ; and continue +PNY_SET: + pla ; get bit mask back + ora SCR_DATA ; turn on bit +PNY_NEXT: + sta SCR_DATA ; save result + inc BITOFF ; we're looking at next bit + lda BITOFF ; now check how we're doing + cmp #7 ; only doing bits 0-6 + bne PNY1 ; check next bit +; +; we've finished this byte in screen memory, point to next one +; + lda #0 ; start at zero'th bit + sta BITOFF ; thank you + lda SCR_DATA ; now stash this one in the screen + sta (FPC),Y ; y is still zero; still pointing to bank + jsr NEXT_SCR ; make SPC/FPC point to next spot + jmp PNY0 ; and continue on please +; +; all done, so make sure we stash anything out there +; +PNY_EXIT: + pla ; get bit mask back to fix stack + lda SCR_DATA ; put away the current data byte + sta (FPC),Y ; y is still zero; still pointing to bank + lda PAGE2SW+MAIN ; back to MAIN page 2 + rts +; +; NEXT_SCR - make FPC/SPC point to next screen byte +; +NEXT_SCR: +; +; if in main bank, when we go to aux bank, we need to look at the next +; byte in memory +; + lda FPCBNK ; get what bank we're talking to currently + bne NXS0 ; 0 = main bank, 1 = aux bank + inc SPCL ; point to next byte + inc FPCL ; and for fetching + lda #AUX ; and point to aux bank + bne NXS1 ; (BRANCH) and continue on +; +; if in aux bank, all we need to do is switch banks +; +NXS0: + lda #MAIN ; just make it main bank +NXS1: + sta SPCBNK ; for stashing and + sta FPCBNK ; fetching + rts +; +; GET_NYBBLE - get the 4 bits which represent the screen at position +; SCRCX, SCRCY; return nybble in low 4 bits of [A] +; +GT_BITS: db 1,2,4,8,$10,$20,$40 +GET_NYBBLE: + jsr SETPOS ; set up offsets using SCRCX + + lda #0 ; clear out my data spot + sta NY_DATA ; for mucking with + + lda #$10 ; setting bits 0-3, starting with shift + sta DATALOOP ; so init the setter +GNY0: + ldx FPCBNK ; which bank + lda PAGE2SW,X ; save which bank + ldy #0 ; zero y + lda (FPC),Y ; get byte + sta SCR_DATA ; and save it +GNY1: + lsr DATALOOP ; see if we have done all 4 bits in this 'pixel' + beq GNY_EXIT ; all done! + + ldx BITOFF ; get bit offset + lda GT_BITS,X ; get bit pattern +; +; now check appropriate bit in Screen Data +; + and SCR_DATA ; see if it is set + beq GNY3 ; no bit set here +; +; bit is set, so set it in my data nybble +; + lda DATALOOP ; get bit setter + ora NY_DATA ; and put it into my data byte + sta NY_DATA ; and save it +GNY3: + inc BITOFF ; we're looking at next bit + lda BITOFF ; now check how we're doing + cmp #7 ; only doing bits 0-6 + bne GNY1 ; check next bit +; +; we've finished this byte in screen memory, point to next one +; + lda #0 ; start at zero'th bit + sta BITOFF ; thank you + jsr NEXT_SCR ; point to next byte + jmp GNY0 ; and continue on please +GNY_EXIT: + lda PAGE2SW+MAIN ; back to main page 2 + lda NY_DATA ; get the nybble desired + rts +; +; SETPOS - get the byte offset and the bit offset from the table using +; SCRCX +; +; USES: SCRCX, SCRCY +; SETS: FPC - pointer to correct screen memory location +; BITOFF - bit offset to get to start of byte (N.B. this is left to +; right count, while in memory it is right to left!) +SETPOS: + lda SCRCX ; get the x pos + tax ; put where we can use it + lda XPOSTBL,X ; get byte # + sta FPCL ; okay, saved + lda XBITTBL,X ; get bitoffset + sta BITOFF ; where it wants it + + lda FPCL ; check for correct bank + and #$01 ; if odd, then must be main bank + bne STP11 ; okay, it be odd + lda #AUX ; aux bank + bne STP22 ; jump +STP11: + lda #MAIN ; main bank +STP22: + sta FPCBNK ; save it + lda FPCL ; get for fetch + lsr A ; /2 to get correct byte offset + ldx SCRCY ; get vertical pos + clc ; get ready for adding + adc BASEL,X ; add low part + sta FPCL ; save low part + lda BASEH,X ; get high part + sta FPCH ; save high part + rts ; done !? +; +; DO_EOL - if this is end of line, check if we are at end of window +; and if we are, and it is a scrollable window, scroll. Then move +; the cursor to the left margin of said window +; +DO_EOL: + jsr DISP_LINE ; make sure line gets out there + lda SCRCY ; get current vertical pos + clc ; add font height + adc #FONT_H ; thank you + pha ; save this position + adc #FONT_H ; make sure we have room for characters here + cmp SCRBTM ; so check against the bottom + beq SAVECV ; no scroll yet + bcs SCROLLCITY ; nope, can't use it +SAVECV: + pla ; get new CV + sta SCRCY ; and save it + bne DEL1 ; JUMP +SCROLLCITY: + pla ; get bad y pos + lda SCRLFLG ; is this a scrolling window? + beq DEL1 ; nope, just move to left edge + jsr SCROLL_UP ; and scroll window +DEL1: +; +; move cursor back to left margin +; + lda LEFTMRG ; get left margin + sta SCRCX ; and set itpositions + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay + lda #0 ; clear length too + sta LENGTH+LO ; no more on line + sta LENGTH+HI ; no more on line + jmp CH_EXIT ; now finish it up +; +; DO_BSPC - do a backspace, by erasing char just before cursor to +; background color, and moving cursor back one space +; [X] == character to delete +; +SAVECHX: DW 0 + +DO_BSPC: + lda CHR_X+LO ; figger new CHR_X + sec ; subtract width + ldy FONTFLG ; get which font we be using + beq DOBSP0 ; must be variable width + sbc #MONOFONT_W ; get width then of mono font + jmp DOBSP1 ; okay, now do add +DOBSP0: + sbc CHWID,X ; get width of char to be erased +DOBSP1: + sta CHR_X+LO ; show new one + sta SAVECHX+LO ; save to restore later + lda CHR_X+HI ; and pick up carry + sbc #0 ; okay, did it + sta CHR_X+HI ; save it + sta SAVECHX+HI ; okay + ldy #SPACE ; get SPACE offset + lda FONTFLG ; monospaced font? + beq DOBSP2 ; nope + lda #MONOFONT_W ; make monospaced wide + bne DOBSP3 ; fine +DOBSP2: + lda CHWID,X ; get width of char +DOBSP3: + sta CHWID,Y ; set space to be this wide + sty SCRBUFF ; make space for erasing + lda #1 ; show one char + sta SCRCNT ; assume it used to be zero + jsr DISP_LINE ; put that space out + lda SAVECHX+LO ; restore old/new x pos + sta CHR_X+LO + lda SAVECHX+HI + sta CHR_X+HI + jsr GET_SCRCX ; update SCRCX please + + lda #SPACE_WIDTH ; restore width of space char + ldy #SPACE ; get offset + sta CHWID,Y ; okay + + jmp CH_EXIT ; done +; +; CLS - clear the window, using CLS parameters +; +CLS: + lda SCRCX ; save the current X,Y + sta SAVECX ; x + lda SCRCY + sta SAVECY ; saved + lda CLSTOP ; get top line + sta SCRCY ; and set up a y pos + + jsr SETMASK ; set up masks and ending point + + lda CPY_COUNT ; get count + sta SH_LOOP ; save count + lda CLSLEFT ; get left edge + sta SCRCX ; set up as X pos + ldy #WINBGND ; get background offset + lda (WINDOW),Y ; get background color + sta ARG8 ; save it here + lda CLSWIDTH ; how wide we be? + bne CLSOKAY ; not a zero width + lda #25 ; zero can't do zero width + jmp ZERROR ; so die +CLSOKAY: + cmp #3 ; if skinny, handle special + bcs L1L0 ; nope + sta ARG7 ; make this be the counter + lda CLSHEIGHT ; just use PUT/GET NYBBLE if only one wide + bne CLSOKAY1 ; not a zero height either + lda #25 ; bad error + jmp ZERROR +CLSOKAY1: + sta J ; save here +CLS1W: + lda ARG8 ; get color + jsr PUT_NYBBLE ; put it + inc SCRCX ; next x + dec ARG7 ; counter + bne CLS1W ; do next X + lda CLSLEFT ; get left edge again + sta SCRCX ; point to it + inc SCRCY ; next line + lda CLSWIDTH ; restore width count + sta ARG7 ; thanks + dec J ; count + bne CLS1W ; do it + beq CLSEXIT ; all done then +L1L0: + sta J ; use j as counter +L1L: + lda ARG8 ; a color please + jsr PUT_NYBBLE ; do first line easy + inc SCRCX ; next nybble + dec J ; done yet? + bne L1L ; nope + + lda CLSLEFT ; where is left column + sta SCRCX ; here! + jsr SETPOS ; get the address + jsr FP2SP ; SPC is source PC, now! + lda CLSHEIGHT ; how many lines are we clearing + bne CLSOKAY2 ; not a zero height either + lda #25 ; bad error + jmp ZERROR +CLSOKAY2: + sta J ; j is counter again + dec J ; already cleared one line + beq CLSEXIT ; only one line to do! +CLSLOOP: + lda SPCH ; now, modify COPY_LINE + sta CPY_MOD1_SRC+HI + sta CPY_MOD2_SRC+HI + lda SPCL + sta CPY_MOD1_SRC+LO + sta CPY_MOD2_SRC+LO + inc SCRCY ; clear this line + jsr SETPOS ; where am i? + lda FPCH ; now, modify COPY_LINE + sta CPY_MOD1_DST+HI + sta CPY_MOD2_DST+HI + lda FPCL + sta CPY_MOD1_DST+LO + sta CPY_MOD2_DST+LO + lda SH_LOOP ; get count + sta CPY_COUNT ; and save it + jsr COPY_LINE ; did the copy (i hope) + dec J ; count it + bne CLSLOOP ; next one please +CLSEXIT: + lda SAVECX ; get X,Y back + sta SCRCX ; got it + lda SAVECY ; now for y + sta SCRCY ; restored! + + rts +; +; SETMASK - figger out the start and end masks, as well as setting +; stuff to point to stopping address. Use CLSLEFT and CLSWIDTH +; +ST_BITS: db 0,1,3,7,$f,$1f,$3f +SETMASK: + lda CLSLEFT ; munge with SCRX + sta SCRCX ; okay + jsr SETPOS ; get me the bit offset of start + + ldx BITOFF ; now set up mask + lda ST_BITS,X ; get the bit pattern + sta STMASK ; save it + + lda CLSLEFT ; get left edge again + clc ; add width + adc CLSWIDTH ; to get where to stop + tax ; make index + stx SCRCX ; set cur pos + lda XPOSTBL,X ; get how many bytes + ldx CLSLEFT ; subtract from byte offset of start + sec ; subbing + sbc XPOSTBL,X + sta CPY_COUNT ; and save it + inc CPY_COUNT ; and make it inclusive count + + jsr SETPOS ; so get its address + + ldx BITOFF ; get bit offset + lda ST_BITS,X ; get pattern + sta ENDMASK ; okay! + rts +; +; SCROLL_UP - roll the current window by FONT_H lines +; +SCROLL_UP: + lda #FONT_H ; show one line + sta SCLLINES ; done + sta SCLDIR ; show scroll up with positive number + ldy #WINTOP ; get top of screen + lda (WINDOW),Y ; got it + sta CLSTOP ; saved it + iny ; point to left edge + lda (WINDOW),Y ; get left edge + sta CLSLEFT ; save + iny ; this is now the height + lda (WINDOW),Y ; get window height + sta CLSHEIGHT ; show me + iny ; and now for the width + lda (WINDOW),Y ; get width + sta CLSWIDTH ; saved it + ; so fall thru + ; and do the scrolling +; FALLING THRU +; | +; \ / +; +; +; DO_SCROLL - scroll SCLLINES withing the window as defined by +; CLSLEFT,TOP,WIDTH, and HEIGHT +; +DO_SCROLL: + lda SCRCX ; save the current X,Y + sta SAVECX ; x + lda SCRCY + sta SAVECY ; saved + lda SCLLINES ; how many lines? + + ldx SCLDIR ; which direction? + bpl SC1 ; >0 means scroll up +; +; scroll down, so we are going to start at the bottom and copy downwards +; until we reach the top +; +; now modify code so we do adds to get destination line and subtracts +; to get new src line +; + ldy #$C6 ; 'dec' opcode + bne SC2 ; jump to modify +SC1: +; +; scroll up - start at top and copy upwards until we reach the bottom +; + ldy #$E6 ; 'inc' opcode + ldx SCLLINES ; get # of scrolling lines +SC2: + sty SCMOD1 ; make inc/dec + sty SCMOD2 ; either inc or dec + stx SCOFF ; save the offset between SRC and DST + + lda SCLDIR ; which direction? + bpl SC3 ; must be normal scroll +; +; if scrolling downwards, we need to start source at bottom-offset and +; end when the destination is at top+offset +; + lda CLSHEIGHT ; get # of lines in window + sec ; subbing + sbc SCOFF ; subtract offset to get source + clc ; adding + adc CLSTOP ; and get absolute position + tax ; put in X + dex ; for 0 offset it + lda CLSTOP ; now figger last line to copy + clc ; adding + adc CLSHEIGHT ; get me last line + tay ; for later storage + dey ; make 0 based + bne SC4 ; always jumps +SC3: +; +; if scrolling upwards, start src at top+offset and end when destination +; is at bottom-offset +; + lda CLSTOP ; get top + clc ; adding + adc SCOFF ; add in offset + tax ; for later on + ldy CLSTOP ; first destination is top of window +SC4: + stx SCRCY ; Starting Source + sty SCROLLY ; Starting Destination + + jsr SETMASK ; set the masks and horizontal endpoint + lda CPY_COUNT ; save for future generations + sta SH_LOOP ; save it + lda CLSHEIGHT ; how high + sta DATALOOP ; save as counter + sec ; for subbing + sbc SCOFF ; subtract scrolling amount + sta CLSHEIGHT ; this is how many lines to copy + lda SCRCY ; save Start Source + pha + lda CLSTOP ; start at Y pos + sta SCRCY + lda CLSLEFT ; and x pos + sta SCRCX ; thank you + lda PAGE2SW+MAIN ; make sure main memory page is in there +SCRL1: + jsr SETPOS ; set up line pointer + ldy SCRCY ; get top + cpy #120 ; 120 bytes per list + bcc SCRLY ; all set + tya ; for adding + clc + adc #8 + tay +SCRLY: + lda FPCH + sta SV_PCH,Y + lda FPCL + sta SV_PCL,Y + inc SCRCY ; next line please + dec DATALOOP + bne SCRL1 + + pla ; get StartSource back + sta SCRCY + lda FPCBNK ; init SPC bank too + sta SPCBNK ; fine, we did +SCROLLING: + ldy SCRCY ; get source Y for index + cpy #120 ; jump over junk + bcc SCLYY + tya + clc + adc #8 + tay +SCLYY: + lda SV_PCH,Y + sta SPCH + sta CPY_MOD1_SRC+HI + sta CPY_MOD2_SRC+HI + lda SV_PCL,Y + sta CPY_MOD1_SRC+LO + sta CPY_MOD2_SRC+LO + sta SPCL + + ldy SCROLLY ; get destination Y pos + cpy #120 ; jump over junk + bcc SCLYY1 + tya + clc + adc #8 + tay +SCLYY1: + lda SV_PCH,Y + sta FPCH + sta CPY_MOD1_DST+HI + sta CPY_MOD2_DST+HI + lda SV_PCL,Y + sta CPY_MOD1_DST+LO + sta CPY_MOD2_DST+LO + sta FPCL + + lda SH_LOOP ; get byte counter + sta CPY_COUNT ; show copy line + jsr COPY_LINE ; and do the copy +SCMOD1: inc SCRCY ; inc or dec to get next one +SCMOD2: inc SCROLLY ; inc/dec for next destination Y + dec CLSHEIGHT ; count down + bne SCROLLING ; nope + + ldx SCLDIR ; scroll up or down? + bpl SCLCLR1 ; clear a little different +; +; if scrolling down, clear from current Y+1 +; + lda SCRCY ; get current source + sta CLSTOP ; save in top spot + inc CLSTOP ; get inside window + jmp SCLCLR2 +SCLCLR1: + lda SCROLLY ; get last destination + sta CLSTOP ; and save it +SCLCLR2: + lda SCOFF ; and both clear this many lines + sta CLSHEIGHT ; okay? + + lda SAVECX ; now restore X and Y + sta SCRCX ; x + lda SAVECY ; and + sta SCRCY ; y + + jsr CLS ; WIDTH and LEFT should be okay still + + rts +; +; CLREOL - clear from current cursor position to end of line by +; using CLS after changing the window size +; +CLREOL: + lda SCRCX ; and make left be where cursor is + sta CLSLEFT + lda SCRCY ; and top be where Y is + sta CLSTOP + lda #FONT_H ; and bottom be bottom of char + sta CLSHEIGHT + ldy #WINWID ; get width + lda (WINDOW),Y ; got it + clc ; now adding + ldy #WINLEFT ; the left edge + adc (WINDOW),Y ; to get the right edge + sec ; subbing + sbc CLSLEFT ; and subtract left to get width + ldy #WINRM ; remove the size of the right margin + sbc (WINDOW),Y ; that too + sta CLSWIDTH ; okay? + jmp CLS ; now clear the screen +; +; COPY_SCRL - copy from SCR_LINE onto the screen. CH_OFFSET says how +; many bytes in SCR_LINE to copy. FPC is assumed to be pointing +; to start of screen bytes. BITTER has the original BITOFF from +; SETPOS. ENDBIT shows how many significant bits in last byte. +; +COPY_SCRL: + ldx SHOW_CURSOR ; are we showing the cursor (ugh) + beq COPYL2 ; nope + jmp DO_CURSOR ; then XOR cursor in +COPYL2: + ldy #WINBGND ; get background offset + lda (WINDOW),Y ; get current background color + beq COPY_SCRL1 ; if black, ignore this + jsr FIX_COLOR ; or in the color, please +; +; Alternate entry point for COPY_SCRL, used by picture drawing routine +; to avoid using background color and checking for cursor +; +COPY_SCRL1: + ldx FPCBNK ; set up bank + lda PAGE2SW,X ; set first bank + lda ENDBIT ; did we end evenly? + bne COPYL22 ; nope + inc CH_OFFSET ; make CH_OFFSET be a counter +COPYL22: + ldy #0 ; zero y + + lda CH_OFFSET ; if only one, then handle real special + bne COPYL21 ; nope + + ldx BITTER ; get starting bit offset + lda ST_BITS,X ; get starting bit mask + sta IOCHAR ; save it + ldx ENDBIT ; get ending bit offset + lda ST_BITS,X ; combine with ending mask bits + eor #$FF ; set for good ones + ora IOCHAR ; set up mask for bits + and (FPC),Y ; get me interesting bits + sta (FPC),Y ; save + lda IOCHAR ; get flag for data + eor #$FF ; flip to get good data +CPYSM1: and SCR_LINE ; pick up my bits + ora (FPC),Y ; and or in screen data + sta (FPC),Y ; and save it + jmp COPYLEX ; go away now +COPYL21: + lda CH_OFFSET ; get # of chars + lsr A ; /2 get number in this bank + adc #0 ; pick up carry for first one + sta DATALOOP ; and save it to work on + + ldx BITTER ; do we have a weird start? + beq DLL2 ; nope +; +; need to do the first one special +; + lda (FPC),Y ; get byte + and ST_BITS,X ; get masking bits + sta IOCHAR ; save for later + lda ST_BITS,X ; get masking bits again + eor #$FF ; get good bits +CPYSM2: and SCR_LINE ; get first data byte + ora IOCHAR ; pick up screen bits + sta (FPC),Y ; pointing + iny ; next byte + ldx #2 ; start at next one for this bank + dec DATALOOP ; kount as done +COPYLOOP: + beq CPYLP2 ; all done with this part of line +DLL2: +CPYSM3: lda SCR_LINE,X ; get data + sta (FPC),Y ; pointing + iny ; next byte + inx ; next one + inx ; next one + dec DATALOOP ; count as used + bpl COPYLOOP ; start loop again +CPYLP2: + ldy #0 ; reset Y + lda FPCBNK ; which bank were we at + eor #1 ; swap to other one + tax ; make it in x + lda PAGE2SW,X ; swap to write bank + txa ; check which one + beq CPYLP23 ; correct offset + iny ; fix offset if going from main to aux +CPYLP23: + ldx #1 ; start at second byte in screen line + lda CH_OFFSET ; get starting number + lsr A ; /2 to get how many for this bank + sta DATALOOP ; and show it +COPYLOOP2: + beq LINE_DONE ; all done with this part of line + +CPYSM4: lda SCR_LINE,X ; get data + sta (FPC),Y ; pointing + iny ; next byte + inx ; next one + inx ; next one + dec DATALOOP ; count as used + bpl COPYLOOP2 ; start loop again +LINE_DONE: +; +; do the last byte special +; + stx DATALOOP ; save pointer + lda ENDBIT ; get ending bit offset + beq COPYLEX ; all done if nothing funky + lsr CH_OFFSET ; get line offset + pha ; save [A] + bcs LINED1 ; if odd, point at right things + dec DATALOOP ; one less then + ldx FPCBNK ; get original bank + lda PAGE2SW,X ; switch to it + txa ; which bank did we do? + bne LINED1 ; no need to step back one + dey ; point one less here too +LINED1: + pla ; get ENDBIT back + tax ; make end bits be index + lda ST_BITS,X ; get end mask + sta IOCHAR ; save mask bits + eor #$FF ; toggle every bit + and (FPC),Y ; get the interesting bits in byte + sta (FPC),Y ; save it + ldx DATALOOP ; get data pointer +CPYSM5: lda SCR_LINE,X ; turn on my bits + and IOCHAR ; pick up my good bits + ora (FPC),Y ; bring everything together + sta (FPC),Y ; save the byte +COPYLEX: + lda PAGE2SW+MAIN ; back to main, thanks + rts + +FIX_COLOR: + inc CH_OFFSET ; just to make checking easier for now + + asl A ; *2 + asl A ; *4 to get correct offset + adc #COLORS ; get hi part + adc #0 ; pick up maybe carry + sta COLORP+HI ; save pointer + ldx #$11 ; ORA (),Y opcode + ldy #WINFORE ; check foreground color + lda (WINDOW),Y ; check what color + bne FIXC1 ; just leave white if not black + ldx #0 ; start at beginning +FIXMUNGEL: + lda SCR_LINE,X ; get byte + eor #$FF ; swap all the bits + sta SCR_LINE,X ; store back + inx ; count it + cpx CH_OFFSET ; done? + bcc FIXMUNGEL ; nope + ldx #$31 ; AND (),Y opcode +FIXC1: + stx FCLM ; self mod my code (again . . . sigh) + lda BITTER ; get starting offset + and #3 ; pick up wrap + tay ; make index + ldx #0 ; start at zero line +FIXLOOP: +FCM1: lda SCR_LINE,X ; get screen byte +FCLM: ora (COLORP),Y ; or with color byte +FCM2: sta SCR_LINE,X ; save it + iny ; next color byte + cpy #4 ; wrapped? + bne FIXLP1 ; nope + ldy #0 ; restart +FIXLP1: + inx ; next screen byte + cpx CH_OFFSET ; done yet? + bcc FIXLOOP ; nope + + dec CH_OFFSET ; fix counter + rts ; now we are done +; +; MSCURS - Erase the cursor from the old spot and write it in the +; new spot +; +MOLDX: db MAXWIDTH ; spot to save x,y of mouse +MOLDY: db MAXHEIGHT +MSCCNT: ds 1 +SVCURS: ds CURSW*CURSH ; save room +MSWCNT: db 1 +MSSTATE: db 0 ; 0 == off, 1 == on +MSCOLOR: db $f,7,7,7,7,7,7,7 +; +MSCURS: + lda #0 ; clear moved flag + sta MSMOVEF ; we did + jsr MSCOFF ; turn cursor off at current pos + jmp MSCON ; and turn it on in new spot + +; +; MSCOFF - mouse cursor off +; Copy info from saved spot back onto screen @ MOLDX, MOLDY +MSCOFF: + lda MSSTATE ; already off? + bne MSCOFF1 ; no + rts ; done then +MSCOFF1: + lda SCRCY ; save X,Y + sta SAVECY + lda SCRCX + sta SAVECX + lda MOLDX ; point to old X,Y + sta SCRCX + lda MOLDY + sta SCRCY + lda #0 ; start at beginning of saved area + sta MSCCNT ; save counter + lda #CURSW ; restore width + sta MSWCNT ; and counter +RENEWL: + lda SCRCY ; check bounds + cmp #MAXHEIGHT + bcs MSC1 ; all done +RENEWL0: + lda SCRCX + cmp #MAXWIDTH + bcs RENEWL1 ; might not be done + jsr GET_NYBBLE ; get screen nybble + ldx MSCCNT ; get counter +; eor MSCOLOR,X ; xor to turn off + eor #$0F ; turn white/black + jsr PUT_NYBBLE ; save nybble + inc MSCCNT ; point to next one + lda MSCCNT ; get counter + cmp #(CURSW*CURSH) ; done yet? + beq MSC1 ; yup + dec MSWCNT ; count down one width + beq RENEWL1 ; it is + inc SCRCX ; next x + bne RENEWL0 ; try again +RENEWL1: + lda MOLDX ; reset X + sta SCRCX + lda #CURSW ; restore width + sta MSWCNT ; and counter + inc SCRCY ; next y + bne RENEWL ; okay try some more +MSC1: + jmp MSCON4 ; done turning it off +; +; MSCON - turn mouse cursor on +; Copy white pixels into area specified by MSX, MSY +; +MSCON: + lda MSSTATE ; already on? + beq MSCON0 ; no + rts ; don't bother +MSCON0: + lda SCRCY ; save X,Y + sta SAVECY + lda SCRCX + sta SAVECX + + lda MSX ; get mouse x + sta SCRCX ; set mouse X + sta MOLDX ; save mouse x + lda MSY ; get mouse y + sta SCRCY ; set mouse Y + sta MOLDY ; and mouse Y + lda #0 ; start at beginning of saved area + sta MSCCNT ; save counter + lda #CURSW ; restore width + sta MSWCNT ; and counter +MSCON1: + lda SCRCY ; check bounds + cmp #MAXHEIGHT + bcs MSCON4 ; all done +MSCON2: + lda SCRCX + cmp #MAXWIDTH + bcs MSCON3 ; might not be done + jsr GET_NYBBLE ; save nybble + ldx MSCCNT ; get counter +; eor MSCOLOR,X ; get cursor color + eor #$0F ; turn white/black + jsr PUT_NYBBLE ; put nybble + inc MSCCNT ; point to next one + lda MSCCNT ; check ending + cmp #(CURSW*CURSH) ; done yet? + beq MSCON4 ; yup + dec MSWCNT ; count down one width + beq MSCON3 ; finished for line + inc SCRCX ; next x + bne MSCON2 ; try again +MSCON3: + lda MSX ; reset X + sta SCRCX + lda #CURSW ; restore width + sta MSWCNT ; and counter + inc SCRCY ; next y + bne MSCON1 ; okay try some more +MSCON4: + lda MSSTATE ; get current state + eor #$01 ; toggle it + sta MSSTATE ; bang + lda SAVECX ; restore X,Y + sta SCRCX + lda SAVECY + sta SCRCY + rts + + + END diff --git a/apple/yzip/rel.15/subs.asm b/apple/yzip/rel.15/subs.asm new file mode 100644 index 0000000..63703e7 --- /dev/null +++ b/apple/yzip/rel.15/subs.asm @@ -0,0 +1,376 @@ + STTL "--- OPCODE SUPPORT SUBROUTINES ---" + PAGE + +; ----------------------- +; 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 LOW = 16, + BCS GETVRG ; IT'S GLOBAL + +; HANDLE A LOCAL VARIABLE + +GETVRL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA LOCALS-2+LO,X ; GRAB LSB + STA VALUE+LO + LDA LOCALS-2+HI,X ; AND MSB + STA VALUE+HI + RTS +; +; HANDLE A GLOBAL VARIABLE +; +GETVRG: + jsr GVCALC ; GET ADDRESS OF GLOBAL INTO [FPC] + jsr FETCHB ; and get hi part + sta VALUE+HI + jsr NEXTFPC ; and point to next part + jsr FETCHB ; and go get it + sta VALUE+LO ; SAVE IT + rts ; AND WE'RE DONE + +; ---------------------------------- +; POP Z-STACK INTO [VALUE] AND [X/A] +; ---------------------------------- +; ZSTACK DOUBLED IN SIZE FOR EZIP +; SO THIS RTN ALL NEW + +POPVAL: LDA ZSP+LO ; IF ZSP+LO IS 0 + BNE POP1 + STA ZSP+HI ; MUST DEC. HI (HI = 0 OR 1 ONLY) +POP1: DEC ZSP+LO ; THEN DEC ZSP LO + BNE POP2 + ORA ZSP+HI ; LO + HI BOTH 0? + BEQ UNDER ; UNDERFLOW IF ZERO! +POP2: LDY ZSP+LO + LDA ZSP+HI + BEQ POP3 ; BOTTOM HALF OF ZSTACK + LDA ZSTKTL,Y ; GET VALUE FROM TOP HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKTH,Y + STA VALUE+HI + RTS + +POP3: LDA ZSTKBL,Y ; GET VALUE FROM BOTTOM HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKBH,Y + STA VALUE+HI + 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: PHA ; HOLD VALUE IN [A] A SEC. + LDY ZSP+LO + LDA ZSP+HI + BEQ PSHBOT ; ON BOTTOM HALF OF STACK + TXA + STA ZSTKTL,Y ; PUSH VALUE ONTO TOP HALF OF STACK + PLA + STA ZSTKTH,Y + JMP PSHUPD ; NOW UPDATE POINTER + +PSHBOT: TXA ; PLACE VALUE ON ZSTACK + STA ZSTKBL,Y + PLA + STA ZSTKBH,Y +PSHUPD: INC ZSP+LO ; UPDATE ZSTACK POINTER + BNE PSHEX + LDA ZSP+LO + ORA ZSP+HI + BNE OVER ; OVERFLOW IF $200 + INC ZSP+HI ; TO 1 +PSHEX: 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 + +; FLUSH TOP WORD OFF STACK +; AND REPLACE WITH [VALUE] + + LDA ZSP+LO ; IF ZSP+LO =0 + BNE VAR1 ; THEN HI =1 (GUARDED ELSEWHERE) + STA ZSP+HI ; DECREMENT HI (ONLY 0 OR 1) +VAR1: DEC ZSP+LO ; NOW DEC LOW BYTE + BNE PSHVAL + ORA ZSP+HI + BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + BNE PSHVAL + + ; RETURN A ZERO +RET0: + lda #0 + tax ; zero's all +; +; RETURN WORD IN [A], [X] (LO,HI) (EZIP EXPANDED TO A WORD) +; +PUTBYT: + STA VALUE+LO + STX 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 LOW = 16, + BCS PUTVLG ; IT'S GLOBAL +; +; PUT A LOCAL VARIABLE +; +PUTVLL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA VALUE+LO ; GRAB LSB + STA LOCALS-2+LO,X ; SAVE IN LOCAL TABLE + LDA VALUE+HI ; DO SAME TO + STA LOCALS-2+HI,X ; MSB + RTS +; +; RETURN A GLOBAL VARIABLE +; +PUTVLG: + JSR GVCALC ; put address in [FPC] + lda FPCBNK ; and move it to stash spot + sta SPCBNK + lda FPCH + sta SPCH + lda FPCL + sta SPCL + lda VALUE+HI ; GET MSB + jsr STASHB ; and save it + jsr NEXTSPC ; point to next byte + lda VALUE+LO ; NOW GET LSB + jsr STASHB ; and send it out + rts + +; ----------------------- +; CALC GLOBAL WORD OFFSET +; ----------------------- +; ENTRY: VAR-I BYTE (16-255) IN [A] +; EXIT: ABSOLUTE ADDRESS OF GLOBAL VAR IN [FPC] +GVCALC: + sec ; time for a subtract + 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 FPCL ; ADDRESS OF THE + lda I+HI ; DESIRED GLOBAL VARIABLE + adc GLOBAL+HI ; STORE ADDRESS BACK IN [FPC] + jsr SETPC ; now get memory page and bank + sta FPCH ; hi part + sty FPCBNK ; and bank +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 PREDB7 ; 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 +PREDB7: 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: LDA VALUE+LO ; SUBTRACT 2 FROM OFFSET + SEC ; IN [VALUE] + SBC #2 + TAX ;SAVE LO BYTE + LDA VALUE+HI + SBC #0 + STA I+LO ;MSB OF OFFSET = LSB OF [I] + LDY #0 ; CLEAR THE MSB + STY I+HI ; OF [I] + ASL A ; EXTEND THE SIGN OF OFFSET + ROL I+HI ; INTO MSB OF [I] + ASL A + ROL I+HI ; (EZIP) + asl A + rol I+HI ; (YZIP) ??!! + TXA ; GET LSB OF OFFSET + 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 PREDB6 + LDA I+LO ; ELSE CALC NEW UPPER BITS + CLC + ADC ZPCM + STA ZPCM + LDA I+HI + ADC ZPCH + AND #%00000111 + STA ZPCH + JMP VLDZPC ;MAKE VALID +PREDB6: + + ; FALL THROUGH ... + +; ---- +; NOOP +; ---- + +ZNOOP: RTS + + +; ---------------------- +; MOVE [ARG1] TO [VALUE] +; ---------------------- + +A12VAL: LDA ARG1+LO + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + RTS + + +; ----------------------------------- +; INDICATE STATUS LINE REFRESH NEEDED +; ----------------------------------- + +REFRSH: LDA ZBEGIN+ZFLAGS+1 ; PICK UP LOW BYTE OF FLAG WORD + ORA #%00000100 ; SET BIT 2 + STA ZBEGIN+ZFLAGS+1 ; AND PUT IT BACK + RTS + + +;DECJ RETURNS C=0 WHEN J=$FFFF + +DECJ: LDA J+LO + SEC + SBC #1 + STA J+LO + LDA J+HI + SBC #0 + STA J+HI + RTS + + END diff --git a/apple/yzip/rel.15/tables.asm b/apple/yzip/rel.15/tables.asm new file mode 100644 index 0000000..80220e9 --- /dev/null +++ b/apple/yzip/rel.15/tables.asm @@ -0,0 +1,329 @@ + STTL "--- ZIP DATA TABLES ---" + PAGE +CHADR_H: + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db >C20,>C21,>C22,>C23,>C24,>C25,>C26,>C27 + DB >C28,>C29,>C2A,>C2B,>C2C,>C2D,>C2E,>C2F + db >C30,>C31,>C32,>C33,>C34,>C35,>C36,>C37 + DB >C38,>C39,>C3A,>C3B,>C3C,>C3D,>C3E,>C3F + db >C40,>C41,>C42,>C43,>C44,>C45,>C46,>C47 + DB >C48,>C49,>C4A,>C4B,>C4C,>C4D,>C4E,>C4F + db >C50,>C51,>C52,>C53,>C54,>C55,>C56,>C57 + DB >C58,>C59,>C5A,>C5B,>C5C,>C5D,>C5E,>C5F + db >C60,>C61,>C62,>C63,>C64,>C65,>C66,>C67 + DB >C68,>C69,>C6A,>C6B,>C6C,>C6D,>C6E,>C6F + db >C70,>C71,>C72,>C73,>C74,>C75,>C76,>C77 + DB >C78,>C79,>C7A,>C7B,>C7C,>C7D,>C7E +CHADR_L: + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 8 +C3F DB 3f,80,71,c0,03,80,0e,00,0e,00,00,00,0e,00,00,00,00,00 ;? 10 +C40 DB 1f,f8,e0,0e,e3,e7,e6,77,e6,77,e3,bc,e0,00,1f,f8,00,00 ;@ 16 +C41 DB 3f,80,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;A 10 +C42 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,7f,80,00,00,00,00 ;B 10 +C43 DB 3f,80,71,c0,70,00,70,00,70,00,71,c0,3f,80,00,00,00,00 ;C 10 +C44 DB 7f,80,71,c0,71,c0,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;D 10 +C45 DB 7f,70,70,7f,70,70,7f,00,00 ;E 8 +C46 DB 7f,70,70,7e,70,70,70,00,00 ;F 8 +C47 DB 3f,80,71,c0,70,00,73,c0,71,c0,71,c0,3f,80,00,00,00,00 ;G 10 +C48 DB 71,c0,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;H 10 +C49 DB 70,70,70,70,70,70,70,00,00 ;I 4 +C4A DB 01,c0,01,c0,01,c0,01,c0,71,c0,71,c0,3f,80,00,00,00,00 ;J 10 +C4B DB 70,e0,71,c0,73,80,7f,00,73,80,71,c0,70,e0,00,00,00,00 ;K 11 +C4C DB 70,70,70,70,70,70,7f,00,00 ;L 8 +C4D DB 78,3c,7c,7c,7e,fc,77,dc,73,9c,70,1c,70,1c,00,00,00,00 ;M 14 +C4E DB 78,70,7c,70,7e,70,77,70,73,f0,71,f0,70,f0,00,00,00,00 ;N 12 +C4F DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;O 10 +C50 DB 7f,80,71,c0,71,c0,7f,80,70,00,70,00,70,00,00,00,00,00 ;P 10 +C51 DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,00,03,c0,00,00 ;Q 10 +C52 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,71,c0,00,00,00,00 ;R 10 +C53 DB 3f,80,71,c0,78,00,1f,00,03,c0,71,c0,3f,80,00,00,00,00 ;S 10 +C54 DB 7f,c0,0e,00,0e,00,0e,00,0e,00,0e,00,0e,00,00,00,00,00 ;T 10 +C55 DB 71,c0,71,c0,71,c0,71,c0,71,c0,71,c0,1f,00,00,00,00,00 ;U 10 +C56 DB 71,c0,71,c0,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;V 10 +C57 DB 71,c7,71,c7,71,c7,71,c7,71,c7,71,dc,7f,f8,00,00,00,00 ;W 16 +C58 DB 71,c0,71,c0,71,c0,1f,00,71,c0,71,c0,71,c0,00,00,00,00 ;X 10 +C59 DB 71,c0,71,c0,71,c0,3f,80,0e,00,0e,00,0e,00,00,00,00,00 ;Y 10 +C5A DB 7f,c0,01,c0,03,80,0e,00,38,00,70,00,7f,c0,00,00,00,00 ;Z 10 +C5B DB 7f,70,70,70,70,70,7f,00,00 ;[ 8 +C5C DB 70,00,38,00,1c,00,0e,00,07,00,03,80,01,c0,00,00,00,00 ;\ 10 +C5D DB 7f,07,07,07,07,07,7f,00,00 ;] 8 +C5E DB 00,00,0c,00,3f,00,e1,c0,00,00,00,00,00,00,00,00,00,00 ;^ 10 +C5F DB 00,00,00,00,00,00,00,ff,00 ;_ 8 +C60 DB 70,38,1c,00,00,00,00,00,00 ;` 6 +C61 DB 00,00,00,00,3f,80,01,c0,3f,c0,71,c0,3f,c0,00,00,00,00 ;a 10 +C62 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;b 10 +C63 DB 00,00,00,00,3f,80,71,c0,70,00,71,c0,3f,80,00,00,00,00 ;c 10 +C64 DB 01,c0,01,c0,3f,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;d 10 +C65 DB 00,00,00,00,3f,80,79,c0,7f,c0,70,00,3f,80,00,00,00,00 ;e 10 +C66 DB 0f,1c,7f,1c,1c,1c,1c,00,00 ;f 8 +C67 DB 00,00,00,00,3f,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;g 10 +C68 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;h 10 +C69 DB 70,00,70,70,70,70,70,00,00 ;i 5 +C6A DB 0e,00,0e,0e,0e,0e,0e,0e,7c ;j 8 +C6B DB 70,00,70,00,71,c0,73,80,7f,00,73,80,71,c0,00,00,00,00 ;k 10 +C6C DB 70,70,70,70,70,70,70,00,00 ;l 5 +C6D DB 00,00,00,00,7f,fc,73,9c,73,9c,73,9c,73,9c,00,00,00,00 ;m 14 +C6E DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;n 10 +C6F DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;o 10 +C70 DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,7f,80,70,00,70,00 ;p 10 +C71 DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,c0,01,c0,01,c0 ;q 10 +C72 DB 00,00,77,7c,70,70,70,00,00 ;r 8 +C73 DB 00,00,00,00,3f,00,70,00,1e,00,03,80,3f,00,00,00,00,00 ;s 9 +C74 DB 1c,1c,7f,1c,1c,1c,0f,00,00 ;t 8 +C75 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;u 10 +C76 DB 00,00,00,00,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;v 10 +C77 DB 00,00,00,00,73,9c,73,9c,73,9c,73,9c,7f,f8,00,00,00,00 ;w 14 +C78 DB 00,00,00,00,71,c0,71,c0,1f,00,71,c0,71,c0,00,00,00,00 ;x 10 +C79 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;y 10 +C7A DB 00,00,00,00,7f,c0,03,80,0e,00,38,00,7f,c0,00,00,00,00 ;z 10 +C7B DB 1f,38,38,f0,38,38,1f,00,00 ;} 8 +C7C DB 70,70,70,70,70,70,70,70,70 ;| 5 +C7D DB f8,1c,1c,0f,1c,1c,f8,00,00 ;} 8 +C7E DB 00,00,00,00,3c,e0,e7,80,00,00,00,00,00,00,00,00,00,00 ;~ 11 +; +; base addresses for the screen lines +; +BASEL: + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 +BASEH: + DB 20,24,28,2C,30,34,38,3C + DB 20,24,28,2C,30,34,38,3C + DB 21,25,29,2D,31,35,39,3D + DB 21,25,29,2D,31,35,39,3D + DB 22,26,2A,2E,32,36,3A,3E + DB 22,26,2A,2E,32,36,3A,3E + DB 23,27,2B,2F,33,37,3B,3F + DB 23,27,2B,2F,33,37,3B,3F + DB 20,24,28,2C,30,34,38,3C + DB 20,24,28,2C,30,34,38,3C + DB 21,25,29,2D,31,35,39,3D + DB 21,25,29,2D,31,35,39,3D + DB 22,26,2A,2E,32,36,3A,3E + DB 22,26,2A,2E,32,36,3A,3E + DB 23,27,2B,2F,33,37,3B,3F + DB 23,27,2B,2F,33,37,3B,3F + DB 20,24,28,2C,30,34,38,3C + DB 20,24,28,2C,30,34,38,3C + DB 21,25,29,2D,31,35,39,3D + DB 21,25,29,2D,31,35,39,3D + DB 22,26,2A,2E,32,36,3A,3E + DB 22,26,2A,2E,32,36,3A,3E + DB 23,27,2B,2F,33,37,3B,3F + DB 23,27,2B,2F,33,37,3B,3F +; +; this gives the bit offset for each one +; +XBITTBL: + DB 0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + RADIX D +ZIPCOLOR: db 0,1,6,7,$C,$B,$E,$F +APLCOLOR: db 2,3,$FF,$FF,$FF,$FF,4,5,$FF,$FF,$FF,7,$FF,$FF,8,9 +OLDZV: +; +; Variables that used to be in the zero page but got moved out +; +PSVFLG EQU OLDZV ; (BYTE) PRESERVE FLAG FOR LEX 0=DON'T 1=DO +VOCFLG EQU PSVFLG+1 ; (BYTE) WHICH VOC TBL, 0=NORMAL 1= ARG3 +DBLOCK EQU VOCFLG+1 ; (WORD) Z-BLOCK TO READ +QUOT EQU DBLOCK+2 ; (WORD) QUOTIENT FOR DIVISION +REMAIN EQU QUOT+2 ; (WORD) REMAINDER FOR DIVISION +QSIGN EQU REMAIN+2 ; (BYTE) SIGN OF QUOTIENT +RSIGN EQU QSIGN+1 ; (BYTE) SIGN OF REMAINDER +DIGITS EQU RSIGN+1 ; (BYTE) DIGIT COUNT FOR "PRINTN" +OLDLEN EQU DIGITS+1 ; (BYTE) OLD LINE LENGTH +OLDEND EQU OLDLEN+1 ; (BYTE) OLD LAST CHAR IN [LBUFF] +SPSTAT EQU OLDEND+1 ; (BYTE) SPLIT SCREEN STATUS FLAG +LFROM EQU SPSTAT+1 ; (WORD) "FROM" LINE ADDRESS +LTO EQU LFROM+2 ; (WORD) "TO" LINE ADDRESS +PRLEN EQU LTO+2 ; (BYTE) SCRIPT LINE LENGTH +GPOSIT EQU PRLEN+1 ; (BYTE) DEFAULT SAVE POSITION +GDRIVE EQU GPOSIT+1 ; (BYTE) DEFAULT SAVE DRIVE +TPOSIT EQU GDRIVE+1 ; (BYTE) TEMP SAVE POSITION +TDRIVE EQU TPOSIT+1 ; (BYTE) TEMP SAVE DRIVE +TSLOT EQU TDRIVE+1 ; (BYTE) TEMP SAVE SLOT +DRIVE EQU TSLOT+1 ; (BYTE) CURRENT DRIVE +SIDEFLG EQU DRIVE+1 ; (BYTE) which disk side are we on +SRHOLD EQU SIDEFLG+1 ; (WORD) <>0 if doing sequential random +SCRIPTF EQU SRHOLD+2 ; (BYTE) DIROUT FLAG FOR PRINTER OUTPUT +SCRIPTFLG EQU SCRIPTF+1 ; (BYTE) Does window allow scripting? +OLDZSP EQU SCRIPTFLG+1 ; (WORD) +CURSFLG EQU OLDZSP+2 ; (BYTE) 1==New cursor X for DLINE +DBLK EQU CURSFLG+1 ; (WORD) +RDTBL1 EQU DBLK+2 ; (WORD) READ TABLE 1 (Game Relative) +RDTBL2 EQU RDTBL1+2 ; (WORD) READ TABLE 2 +NENTS EQU RDTBL2+2 ; (WORD) # ENTRIES IN VOCAB TABLE +DIRITM EQU NENTS+2 ; (WORD) OFFSET IN OUTPUT TBL (DIRTBL) +DIRCNT EQU DIRITM+2 ; (WORD) COUNT OF CHARS IN TBL (DIRTBL) +SVTCHAR EQU DIRCNT+2 ; (WORD) Old TCHARS table address +VOCMPC EQU SVTCHAR+2 ; (3 BYTES) Save for vocabulary MPC +VCESVE EQU VOCMPC+3 ; (3 BYTES) Save for VOCEND +VWLSVE EQU VCESVE+3 ; (3 BYTES) Save for VOCLEN +DIDVTBL EQU VWLSVE+3 ; (BYTE) <>0 if we have done default table +IN EQU DIDVTBL+1 ; (9 BYTES) INPUT BUFFER +OUT EQU IN+9 ; (9 BYTES) OUTPUT BUFFER +CURSOR_OFF EQU OUT+9 ; (BYTE) ==1 if char cursor not to be on +CRLF_CHECK EQU CURSOR_OFF+1 ; (BYTE) ==1 to do CRLF function check +PTR_COUNT EQU CRLF_CHECK+1 ; (BYTE) ==0 if checking pointer movement +INFODOS_END EQU PTR_COUNT+1 ; (WORD) last segment of infodos special +OLDZVLEN EQU INFODOS_END-PSVFLG+2 ; this is how much to reserve + + BLKB OLDZVLEN,0 ; and zero it out + +; ------------------ +; ERROR MESSAGE STRINGS +; ------------------ +E27: db E27L + db "Disk I/O Error" +E27L EQU $-E27-1 +E2B: db E2BL + db "Disk write protected" +E2BL EQU $-E2B-1 +E40: db E40L + db "Bad Filename" +E40L EQU $-E40-1 +E44: db E44L + db "Path not found" +E44L: EQU $-E44-1 +E45: db E45L + db "Volume not found" +E45L EQU $-E45-1 +E46: db E46L + db "File Not Found" +E46L EQU $-E46-1 +E48: db E48L + db "Disk Full" +E48L EQU $-E48-1 +E49: db E49L + db "LaneDOS limit: 12 files/directory" +E49L EQU $-E49-1 +E4E: db E4EL + db "LaneDOS limit: No writes to TREE files" +E4EL EQU $-E4E-1 +E4C: db E4CL + db "Unexpected EOF" +E4CL EQU $-E4C-1 + +ELIST: db $27 + dw E27 + db $2B + dw E2B + db $40 + dw E40 + db $44 + dw E44 + db $45 + dw E45 + db $46 + dw E46 + db $48 + dw E48 + db $49 + dw E49 + db $4C + dw E4C + db $4E + dw E4E +ELISTL EQU $-ELIST-3 ; mark last error code + + END + diff --git a/apple/yzip/rel.15/verify.asm b/apple/yzip/rel.15/verify.asm new file mode 100644 index 0000000..b2cd98a --- /dev/null +++ b/apple/yzip/rel.15/verify.asm @@ -0,0 +1,252 @@ + STTL "--- VERIFY CODE ---" + PAGE + + ; ------ + ; VERIFY + ; ------ + ; VERIFY GAME CODE ON DISK +VERBAD: DB EOL,"The data segment of file is BAD!",EOL +VERBADL EQU $-VERBAD +VERPBAD: DB EOL,"The picture data of file is BAD!",EOL +VERPBADL EQU $-VERPBAD +ZVFLAG: db 0 ; set to indicate ugliness +STARTPOS EQU I+LO ; this is where to start block +ZVER: + jsr CLOSE_GAME ; make sure the game files are closed + ldy GAME2NML ; get length of name + lda GAME2NM,Y ; get last char + eor #$30 ; make normal number + tay ; -1 to make ready for FETCH_FILE + dey ; F_F incs first + tya ; to push onto stack + pha ; and save for restoring later + lda #0 ; clear a few counters + sta ZVFLAG ; ==0 - verify worked; !=0 - verify broke + lda SEGTBL+SGTDISKS+1 ; get how many disks are here + sta DISKCNTR ; this shows which disk we are working on + dec DISKCNTR ; start down by one +VERIFY_LOOP: + jsr VERIFY_DATA ; check data in this file + jsr VERIFY_PICD ; check (possible) picture data in this file + lda GMREF ; get reference number + sta CLOSE_PB+CL_REFNUM ; and show CLOSE + CLOSE CLOSE_PB ; and shut it up + dec DISKCNTR ; next please + bpl VERIFY_LOOP ; and check the next file +ZVERX: + lda #>PAGELEN ; reset read buffer length + sta READ_PB+RD_BUFFLEN+HI ; to be $100 + lda # 0, then it isn't + jsr SETUP_DISK0 ; move around to point to start of data +VERD1: + ldy #SGTPICOF ; find where picture data starts + lda (DSEGS),Y ; MSB + sta J+HI ; J is the page counter + iny ; point to LSB + ora (DSEGS),Y ; any picture file? + bne VERD01 ; yes, so mark end of data + lda #$FF ; set J to be a real big number + sta J+LO ; okay + sta J+HI ; and this one + bne VERD11 ; all done +VERD01: + lda (DSEGS),Y ; and here it is + asl A ; *2 to make 512 pages be 256 pages + sta J+LO ; this is where it ends up + rol J+HI ; move in carry to MSB + lda J+LO ; now, subtract any skipping + sec ; doing sub + sbc PSEEK+SM_FPOS+1 ; take away any skipped amount + sta J+LO ; and save it + lda J+HI ; pick up carry + sbc #0 ; we will + sta J+HI ; we did +VERD11: + jsr VERIFY_FILE ; now, actually do the work + bcc VERDX ; worked just fine + DLINE VERBAD ; puke, gag, argh +; +; This prints out which file is garfed +; +VER_FMSG: + lda DISKCNTR ; which file did we do? + cmp #2 ; 0,1 are in one place + bcs VERDB1 ; nope it isn't it + DLINE GAME1NAME,GAME1NML + jmp VERDB2 +VERDB1: + DLINE GAME2NAME,GAME2NML ; 2,3 are in another +VERDB2: + inc ZVFLAG ; show bad file + jsr GETRET ; just wait for +VERDX: + rts ; all done +; +; VERIFY_PICD - verify the picture data in a file. First check to see if +; there is any. If so, seek to it, set J==0 to show VERIFY_FILE to read +; til EOF, and print out bad picture data message if necessary. +; +VERIFY_PICD: + lda #$FF ; gonna zero bunch of stuff + sta J+HI ; and the counter + sta J+LO ; which means now goto EOF + ldy #SGTPICOF ; fetch the picture data offset + lda (DSEGS),Y ; get MSB + sta PSEEK+SM_FPOS+2 ; we are doing pages + iny ; pointing to LSB + ora (DSEGS),Y ; first, check for all zeros + bne VERP1 ; nope, some picture data is there + rts ; just gwon back if nothing here +VERP1: + lda (DSEGS),Y ; go get LSB + asl A ; *2 to get 256 byte pages + sta PSEEK+SM_FPOS+1 ; put away here + rol PSEEK+SM_FPOS+2 ; pick up carry + lda #PHSIZE ; skip over header of file + sta STARTPOS ; show offset in first block +VERP11: + SET_MARK PSEEK ; and move to picture data spot + jsr VERIFY_FILE ; read in the data + SET_MARK PSEEK ; get back to beginning of pic data + READ READ_PB ; read in a block worth + lda IOBUFF+PHCHKS ; get MSB of picture checksum + cmp L+HI ; same as what we got? + bne VERPB ; nope + lda IOBUFF+PHCHKS+1 ; get LSB of picture checksum + cmp L+LO ; same as mine? + beq VERPX ; yup, checked out fine +VERPB: + DLINE VERPBAD ; picture data bad + jmp VER_FMSG ; print out file name +VERPX: + rts ; tootis finis +; +; VERIFY_FILE - Files is already open and pointing to start of checksummed +; data. Works along til J == 0 or EOF, which ever comes first. Starts by +; dec'ing J, so if J starts as 0, effectively means goto EOF. +; +VERIFY_FILE: + lda #0 ; clear out checksum counter + sta L+HI ; MSB + sta L+LO ; LSB + sta READ_PB+RD_BUFFLEN+LO + lda #4 ; make read read $400 (1Kb) + sta READ_PB+RD_BUFFLEN+HI +VFLOOP: + lda #RETRY_COUNT ; and set up retry count + sta RETRIES + lda #IOBUFF ; reading all the data + sta K+HI ; into, using as pointer +VFLRD: + READ READ_PB ; read in 1Kb of data + bcc VERF0 ; just fine read + cmp #$4C ; EOF error? + beq VFCHECK ; yes, so wee bee done + cmp #$4D ; InfoDOS EOF error? + beq VFCHECK ; ayyup + jsr RETRY ; check about retrying + bcc VFLRD ; and do again +VERF0: + lda J+LO ; count the block to be read + bne VERF1 ; no wrapping + lda J+HI ; anything left? + beq VFCHECK ; nope, all done then + dec J+HI ; count one block +VERF1: + dec J+LO ; count block + ldy STARTPOS ; and begin +VERF2: + lda (K),Y ; get byte + clc ; doing add + adc L+LO ; add it in + sta L+LO ; save it + bcc VERF3 ; no wrap + inc L+HI ; yes ther is +VERF3: + iny ; next byte + bne VERF2 ; back to start of inner tloop + + lda #0 ; start at first byte + sta STARTPOS ; okay + inc K+HI ; point to next block + dec READ_PB+RD_LENGTH+HI ; count this one + beq VFLOOP ; go read some more + bne VERF0 ; go do next 256 byte block +VFCHECK: + ldy #SGTCHKS ; get check sum + lda L+HI ; start with MSB + cmp (DSEGS),Y ; well . . . ? + bne VFBAD ; nope, it is wrong + iny ; first byte is okay + lda L+LO ; so check LSB + cmp (DSEGS),Y ; well . . . ? + bne VFBAD ; die a slow ugly death + clc ; clear carry to show niceness + rts +VFBAD: + sec ; carry is set if bad + rts ; and return to your fate +; +; SETUP_DISK0 - this routine does some special processing to get the file +; pointer to the beginning of data for the preload file. It skips over +; segment table. +SETUP_DISK0: + READ READ_PB ; read in first block + lda IOBUFF ; MSB of segment table size (in words) + sta PSEEK+SM_FPOS+1 ; middle part of offset + lda IOBUFF+1 ; LSB of size + asl A ; *2 to pick up carry + rol PSEEK+SM_FPOS+1 ; rotate in carry + rol PSEEK+SM_FPOS+2 ; and once more + tay ; check for wrapping upwards + beq STD01 ; no wrap up then +STD00: + inc PSEEK+SM_FPOS+1 ; wee did + bne STD01 ; no more wrapping + inc PSEEK+SM_FPOS+2 ; yes there is +STD01: + lda PSEEK+SM_FPOS+1 ; make sure it is a 512 byte page + and #$1 ; even page? + bne STD00 ; inc again, please +STD0X: + SET_MARK PSEEK ; skip the segment table stuff + rts ; all done + + END diff --git a/apple/yzip/rel.15/versions b/apple/yzip/rel.15/versions new file mode 100644 index 0000000..ce2315f --- /dev/null +++ b/apple/yzip/rel.15/versions @@ -0,0 +1,686 @@ +This is just a list of all the version changes for the Apple ][ YZIP + +; +; 1 - 7/29/88 New numbering scheme +; Faster text handling +; +; 2 - 8/17/88 Gargantu-Games handling +; Fixed Restart +; Handle COLOR -1 +; Handle transparent colors in pictures +; +; 3 - 8/24/88 Joystick/Mouse handling +; +; 4 - 8/30/88 Heavily debugged with/for ZORK0 +; +; 5 - 9/1/88 Fix cursor x,y in WINGET +; Make CLS work on REAL skinny windows +; +; 6 - 9/2/88 No status check on CLOSEs +; Only allow alphanumerics for save names +; +; 7 - 9/2/88 Don't clear strobe first, do it after getting key +; Add /RAM check to boot code - restore /RAM after QUIT +; +; 8 - 9/7/88 Flag day +; Changed WINGET/WINPUT to like GET/PUT +; Add in multi disk stuff +; +; 9 - 9/15/88 Preload is in SEGMENT table now +; Program name in BOOT.ASM +; Copy name to correct place in boot and interpreter +; New name of interpreter is now "INFOCOM" +; Add verify code too +; +;10 - 9/16/88 Keep running count of dirout char width in lo core +; Set up pure and pre pointers for tables and functions +; +;11 - 9/20/88 Don't forget to add one to x,y pos of window and cursor +; in WINGET +; Init vocab pointers for default vocab table and use them +; +;12 - 9/28/88 Zero zero page stuff in two passes - used to wipe out ProDOS zero page +; Data length in pic files is now 3 bytes + +; +;13 - 10/11/88 Picture files and Data files are one and the same now +; +;14 - October 24, 1988 +; Add volumn command to save/restore get name routine +; +;15 - November 8, 1988 +; Search on disk 1 in last resort (hints are probably there) +; Use mouse in passive mode +; +;16 - November 14, 1988 +; Make mouse stuff be passive, rather than interrupt driven +; +;17- November 15, 1988 +; Few more fixes 'n' stuff +; +;18-November 15, 1988 +; Clear ZTWIDTH when starting table output +; +;19-November 28, 1988 +; Fix up PUT_NYBBLE and GET_NYBBLE +; Reset DSEGS after closing save file +; Make FONTSIZE word be Width/Height +; Make Chars/line reflect mono spaced char width of 3 in lo core +; Change ZTWIDTH to be MSB/LSB, rather than LSB/MSB word +; Point to main bank in CHK_MOUSE +; Clamp mouse to 136,189, and don't do shift when getting pos +; Make CLK_CNT be negative, and set flag to show button state +; Set up point to MSTBL (extension table for mouse clicks) +; Put X,Y coordinates in MSTBL after click +; +;20-December 1, 1988 +; Don't use [A] in DO_MOUSE unless it is a character +; Clear LSB in seek pblock before doing seek +; No, really, DON'T use [A] in DO_MOUSE +; Make CLK_CNT be 8 +; Exit normally if double click +; Split mouse cursor routine into 2 pieces - off and on +; If can't find picture, try opening other file. If it isn't there +; then die with error #$14 +; Move XPOSTBL and COLORS to page 3 for some elbow room +; Save/restore refnum when opening new picture file +; +;21-December 2, 1988 +; Swap back to Bank 1 in pic.asm +; +;22-December 5, 1988 +; Save/restore DSEG in verify +; Dec saved filename for passing to Fetch_file in Verify +; Fix addition for getting to Picture data in Verify +; Check for files 0 & 1 names in different place than 2 & 3 (Verify) +; Add STARTPOS to verify +; Copy BITOFF to BITTER in picture stuff +; +;23-December 6, 1988 +; Get picture data checksum from the right place +; Init counter for picture data checksum to be $FF, not 0 +; Move "mouse" cursor for joystick too +; Do "mouse" cursor pos for button for joystick too +; Change movement thresholds for joystick to 120/135 +; Double movement rate for joystick +; Change boundaries check in stick movement to bcs, not beq +; Save/restore cursor position in DLINE +; Create SWAP2INFOW/SWAPBACK to go to/from info window +; and have DLINE & GETSNAME use them +; Have only one exit point in GETSNAME +; Make DLINE do a CLRBUF upon exitting +; Add EOL to end of DELQ +; Muck with a few messages in ZSAVRES +; Change GAMEPL to maximum (64-15) as can only be a list of directories +; Add "Unexpected EOF" error string +; +;24-December 8, 1988 +; Game data starts out on even (512 byte) page boundary +; +;25-December 13, 1988 +; Make pop's FETCHB store afterwards +; Make WINGET handle 0-15 words to get +; Change order of window parameters, to make user ones the first +; 16 available +; Don't SWAP to infowindow in DLINE, rather do it in routines that +; call DLINE +; Fix color green in COLORS table +; +;26-December 14, 1988 +; Change PBEGIN to $0200 +; Scan for mouse slot, rather than asking or assuming +; After finding it, save lo byte in arg1+lo to change interpreter +; screen holes for interesting stuff +; Save/restore printer slot before/after SWAPBACK call +; +;27-December 15, 1988 +; Put paging buffer start back to $0800, cuz screen holes in aux +; mem really screw things up +; Make only closed-apple key work as function key faker +; +;28-December 16, 1988 +; Need only 8 chars for name, as .SYSTEM adds 7 more, to max 15 +; Make ZQUIT read RDBNK2, not write +; +;29-December 19, 1988 +; Save disk number when saving refnum, so that we can scan the two +; disks currently inserted, then look at all the rest +; Pass starting offset for segment list, cuz segments for side 1 +; start a little weird, cuz preload is the first set of +; segments, then the list starts normally +; Don't forget to save refnum in all the right places +; +;30-December 20, 1988 +; Use BIT_BITS in both CHAR_LINE and picture stuff +; Take out retries - it just doesn't work +; Add check for save disk when asking about swapping disk +; Copy read buffer to local buffer before doing read +; +;31-December 22, 1988 +; Play with bounds for joystick movement a little further out +; Don't script input line +; Fix input with timeout, so that the key gets parsed correctly +; Only look at button zero for joystick +; Call FKEYX instead of KEYX in TIMEK +; Check all online volumes before asking for disk by name +; Fix length byte before you do +; Use CHPTR in volume checking routine +; Copy path name to SCRBUFF so we can prepend a '/' in checking volumes +; And don't forget to count it in the length byte +; Quit if no more volumes to check +; More changes to avoid errors in set_prefix, which really seem to gum +; up the works +; +;32-December 23, 1988 +; Don't clear interrupts before reading paddles +; +;33-January 3, 1989 +; Spell volume right in error message +; Save cursor a little earlier in zdispl +; Set/clear savedisk only in close_save +; +;34-January 4, 1989 +; Make sure carry is set before returning from DISK_ERR +; Have SET_GAMEPRE use SAVENUM +; Push current INVFLG instead of saving in variable in ST_CUR +; Check for mouse cursor in timed input please too +; Took GOTKEY out, cuz no-one used it any more +; Changed order in TIMIN for goodness sake +; +;35-January 5, 1989 +; Try for 512 byte paging buffers +; +;36-January 6, 1989 +; Fix up some more for 512 byte buffers +; Muck with paging scheme (oh oh) +; Make GETRES take from one to four blocks +; Make restore use 4 blocks when doing full restore +; +;37-January 9, 1989 +; Fix multiple block restore problems +; Don't destroy DOS return code in GETRES +; Clear CLOSE_PB refnum +; Make DOS routine be READ_DOS and WRITE_DOS +; Fix read so SIB's increment word start +; Make WAIT10 check for mouse/joystick cursor movement +; Use FKEYX for [MORE] so buttons can be used +; +;38-January 10, 1989 +; Mess with PCHK and other scripting stuff +; Use GETKEY for [MORE] +; Put in delay before calling PREAD to get joystick status +; +;39-January 11, 1989 +; Make mouse cursor be two colors +; Change WAIT10 to be a loop, not an MWAIT call +; Clear MSMOVEF flag in MSCURS +; Don't check GETKEY's return in MORE +; Joystick is > 0, mouse is < 0 +; Leave mouse status in [A] for CHK_MOUSE +; Add DELAY_COUNTER for WAIT10 +; +;40-January 12, 1989 +; Fix shift (asl -> rol) when getting position of picture T.O.C. +; Don't split Mouse moving/button +; Play with Delay counter, doubling it if on a GS +; Make sure interrupts are turned back on in CHK mouse +; Only turn on button flag in CHK mouse, never turn it off +; Add another delay loop inside WAIT10 +; Make INNER & OUTER constant counters, with special ones for GS +; +;41-January 13, 1989 +; Add printer init call to pchk +; Play with SCRIPT flag (which allows scripting) +; Turn on initially +; Turn off at start of save/restore +; Turn on at end of save/restore +; Add SCRIPTFLG, which says whether window allows scripting +; +;42-January 19, 1989 +; Change to always seek to 512byte block boundary for new DOS +; pic.asm +; +;43-January 20, 1989 +; Move copy line for $D000 down to lower memory +; Add INFODOS flag for conditional assembly for special dos +; Play with boot to get it to work with 512byte blocks +; Take out all ROM calls, cept printer stuff; default is now +; BNK1SET +; +;44-January 26, 1989 +; Change DESTROY to SETEOF for new InfoDOS. +; +;45-January 31, 1989 +; Make paging stuff goto Bank 2, not bank 1 +; Make picture stuff goto Bank 1 +; Add INFODOS flag +; Non-sequential page map +; If INFODOS==1, then 12Kb preload in $D0-$FF, main bank, bank 2 +; and check for it in xpaging +; Just loop if using InfoDOS upon quit +; +;46-February 1, 1989 +; Don't muck with interrupts cuz InfoDOS don't like it +; +;47-February 4, 1989 +; Fixed set_eof to delete file. +; Ignore error returns for set_eof, cuz InfoDOS doesn't like to +; SET_EOF on an empty file. +; Make boot.asm print out version too +; Change special load from Kb's to pages +; Do special load 1 page at a time, rather than 2 +; +;48-February 6, 1989 +; Change get_special counter to count 2 blocks, not 4 +; Fix SAVE/RESTORE to do 512 byte pages for InfoDOS +; All reads in restore must be 512 bytes minimum +; +;49-February 7, 1989 +; Make SAVE_DATA self-modification be absolute, not relative +; Put version number into lower left corner of boot screen +; Fix scroll to move cursor to last line before doing any work +; and have it count the lines in lincnt, but not +; against the scrolling lines +; +;50-February 10, 1989 +; Add no write to TREE files error +; Add set_prefix call to OPEN_GAMEF, before opening file the +; first time +; Start Set-PB off pointing to game boot prefix +; Init a few GS registers in boot +; Put SET_EOF error check back +; Jump to reset vector if in InfoDOS +; +;51-February 13, 1989 +; Swap ROM back in if reading joystick +; Do a SET_EOF if bad save +; Check button click for joystick in delay loop +; Swap in ROM for jump to reset_vector +; Make restart load INFOCOM.SYSTEM +; Swap in ROM at start of boot task +; Try to get click/double click for joystick to work +; Add JB_STATE to show changing state +; Only check bit 7 +; Set CLK_CNT to 3 +; Only one loop in read_stick +; Fix restore of SCRCX in disp_line (nothing passed in [A]) +; In displaying cursor, always set up CHR_X, but don't change +; SCRCX +; +;52-February 14, 1989 +; Set CURSFLG at start of input and zinput +; Change display_line to not update for just show_cursor +; Don't let GET_SCRCX change chr_x +; Use my toggle for mouse button up&down +; Put in more check for joystick button +; Add Cursor off/on on curset of -1/-2 +; Go to prefix that was there on a save +; Take it out of zdos and put in close_save +; Just ask to put back game disk, not particular disk +; Fix set_gamepre - getret does not return == +; +;53-February 15, 1989 +; Wrap correctly if picture data starts near 256 byte boundary +; Add DIRECT_OUT call to DLINE/COUT to skip over checks like +; formatted table output and scripting +; Fix CHECK_JYBTN to check mouse if there is a mouse +; +;54-February 16, 1989 +; Fix check for -1/-2 in CURSET +; +;55-February 16, 1989 +; Major changes to COPY_LINE +; Change (zzz),Y to zzz,X +; Take out one of the counters +; +;56-February 17, 1989 +; Don't do CRLF check if doing interpreter printing +; +;57-February 21, 1989 +; Don't set function preload if tables take up all preload +; +;58-February 25, 1989 +; Ignore LINCNT during call to ZSCROLL +; Jump to ZRQUIT, not ZRBAD, when no restore name given +; Get updated DSKBNK in PUTDSK +; Make mouse hotspot be in middle of cursor +; +;59-February 28, 1989 +; Add Global Directory Offset to segment table structure +; Fix transparent color skipping to New X pos +; Add "Version:" to boot screen +; Move cursor to left most column for M/J/N question +; Ask for particular Game disk side after taking out save disk +; +;60-March 1, 1989 +; Change CHZ to good spot in boot.asm +; Add Global dir offset to segment 1 structure too +; Move Scrcx for good color in picture drawing too +; Send out eol too to position cursor in boot +; Don't ask for particular disk side after save, cuz I can't be sure +; whether it is a one disk or multi disk game (i.e. on a +; 3.5" disk, I don't want to ask for a particular side). If +; users puts in wrong disk, I will then ask for a particular +; side). +; Add SWAPPED flag to show a multi disk game, which requires special +; detailed question +; Check for $4D error in verify, cuz InfoDOS returns it instead of +; $4C on EOF +; +;61-March 2, 1989 +; Add SET_PREFIX to boot code startup +; Don't check for pointer movement if a key has been hit, at least +; not for a while (PTR_COUNT) +; +;62-March 4, 1989 +; Clear PTR_COUNT at start of ZINPUT and end of INPUT +; +;63-March 6, 1989 +; Don't set CURSFLG in ZINPUT/INPUT, cuz cursor doesn't want to +; move in an aborted one +; Make cursor always end up at top right of picture +; Move PIC1BUFF so it doesn't tromp input buffer +; Make RESTART use FETCH_FILE to get correct disk before rebooting +; Make CLOSE_SAVE use DO_GAME1 to get GAME1 file +; +;64-March 7, 1989 +; Make INPUT explicitly clear CURSFLG +; CLOSE_GAME should call DO_GAME1 first +; And don't forget to set SAVEDISK flag still +; Use OPEN_GAMEF, not FETCH_FILE in restart +; Make mouse x,y be one based +; Make sure there is a prefix in the save name +; Add check for zero length save file name +; Fix COPY_LINE to do ENDMASK correctly +; Update COPY_LINE's source address every loop in CLS +; Have call to buffout fall thru to CLRBUF +; +;65-March 7, 1989 +; Increased interpreter size to 42 pages +; Add clrbuf call to zfont +; Make random go fetch a word from memory +; Take out RNUM, just use RAND +; Add in Global directory handling +; +;66-March 8, 1989 +; Fix special case in SCANSEG for side 1 (skip 6, not 14) +; Add UNDERF to disp_line, so underline flag gets reset correctly +; Make partial save/restore work better, including by always readin +; in 2 pages worth +; +;67-March 9, 1989 +; Change some messages for inserting disks +; Fix get_save_name so it doesn't double print name on prefix error +; Modify some messages in save/restore +; Don't let user wrap input line +; +;68-March 9, 1989 +; Move Special to Aux bank, and paging to main bank +; +;69-March 10, 1989 +; Make CLREOL show inclusive width +; +;70-March 13, 1989 +; Don't make mouse x/y be one based (why?) +; When *2 for segment table size in boot, use both LSB & MSB +; +;71-March 14, 1989 +; Add in global dir handlers +; pic.asm - add OPEN_NEW_PF, FIND_PIC_DISK, and an expanded +; FIND_GBL +; zdos.asm - look for picture data in all files, including 1 & 2 +; Try to make keyboard read a little more responsive +; Set flags word to Apple ][ stuff in zbegin +; Add retry to GET_SPECIAL and GETDSK and VERIFY +; +;72-March 15, 1989 +; Don't forget to send side # out for RESEAT message +; Add CHARSET stuff +; Take into account the margins in CLREOL +; Modify how big entry is in getting picture/global directory +; Handle Ctrl-K (end of sentence) and Ctrl-I (start of paragraph) in +; COUT +; Go back to using MWAIT in WAIT10 +; Had NEXTPICF check backwards +; +;73-March 16, 1989 +; Make ISTCHARS function key check use tax/bmi sequence - no CMP +; Save LOCALS first in ZREST:, in case of early error +; Change where we display disk error (after RESEAT msg). +; Don't forget to save/restore the disk error # +; Fix check for double picture lookup +; Save cursor before drawing picture/restore it after +; Make FIX_COLOR handle either black or white foreground +; +;74-March 16, 1989 +; Make [MORE] get printed out without call to DLINE +; Set/restore DSEGS upon call to get picture data, just +; to make sure it's right. Also, don't bother going to +; get the data if it is the stuff already in memory +; Try to get more random +; Make sure GET_SPECIAL get's from the start of .D2 +; and all LSB's are zero'd +; +;75-March 17, 1989 +; Make sure disk error gets saved/restored while in RETRY +; Just tell user where to put disk, rather than what to take out +; and then tell what disk to put in +; Add APLCOLOR table for winget on color +; +;76-March 21, 1989 +; Reset find_gbl counter upon finding a picture +; Don't look for another global directory if we already have one +; Make findpicdisk stop trouncing on its data, and check both +; the disks that are in there +; Make the disk findpicdisk asks for be zero relative +; Change CLREOL width again - just make it # of pixels to clear +; User lower 4 bits in Long Jump ZPC MSB, and shift over once more? +; Allow game to set line count +; Go get picture data even if file is already open, if it isn't the +; one currently in memory +; Don't add extra spaces to start of line for tab/eos chars +; +;77-March 22, 1989 +; 'nother day, 'nother version +; Turn screen on/off with table output off/on +; Swap returned fore/back colors in winget +; Set length to zero if x pos < left margin +; Probably ought to be fixed better, perhaps by not taking +; left margin into account in XSIZE, and starting length off +; at left margin on CRLF/wrap +; Implement ERASE n, where n > 1 +; Make sure picture file directory gets read in, even if the file +; is already open, if it is not the data in memory +; Clear LINCNT on every ZCRLF in ZSCROLL +; Don't take into account the left margin in CLREOL +; Count byte if special start/end in COPY_LINE +; +;78-March 23, 1989 +; Try once more . . . +; Fix verify so it counts down correctly, and count the block at +; start of add, not end +; Make take out save disk message wrap better +; Make sure EOL is in CHARSET table, even if a table is passed to +; me +; Fix MSB/LSB of piccnt in FIND_GBL +; Save File ID of local directory, for later checking +; Don't move in starting spaces in FLUSH +; Make sure SCREENF is on while in DLINE +; +;79-March 24, 1989 +; This is so much fun, I just wanted to do it again . . . +; Wrap TWIDTH up before /4 +; Don't set undo bit in flag word +; Don't script [MORE] +; +;80-March 27, 1989 +; 'nother week, 'nother interpreter (are we having fun yet?) +; Change CLICK_CNT to 4 +; Swap to infowindow before zerror +; Just check passed arguments for fitness in WINSIZE/WINPOS, not +; the results +; +;81-March 28, 1989 +; Make sure the clear operand in the window attributes command works +; correctly +; Change LINCNT check in ZCRLF to be bcc, not bne +; Make sure first read in full restore has 2 blocks, to maybe catch +; a define save +; Make sure ROM is NOT in there when doing a reset +; Add some retries to boot disk +; +;82-March 29, 1989 +; Add one to PURBT size on restore and make sure last read is an +; 512 page +; Use TBLRTN on formatted table in flush +; +;83-March 30, 1989 +; Put in some retries in boot reads +; Make sure winput puts LINCNT +; Update attributes if -3 passed to WINATTR too +; Do CLRBUF in DIROUT +; Just set SCRIPT to true, not inc it, in CLOSE_SAVE +; +;84-March 31, 1989 +; Fix verify's handling of disk 1, and don't bother to skip 64 bytes +; of lo core +; +;85-April 3, 1989 +; Munge power up valid byte before jump to RESET_VECTOR +; Set ZFLAGS word correctly +; Try to turn on more bits in hi byte of random number +; +;86-April 5, 1989 +; Don't save/restore DSEG/GMREF in verify - just let fetch_file do +; the work +; Clear PF_FID in CLOSE_GAME +; Try to make RESET_VECTOR work, but getting/storing RESET_VECTOR, +; loading in ROM, then jumping to vector +; +;87-April 6, 1989 +; On error in GTS, restart whole process +; Load length of Game 2 name before checking in fetch file +; +;88-April 10, 1989 +; Don't script SCROLL call +; XOR mouse cursor onto screen +; Don't update LENGTH in INPUT til we've made sure it fits +; Handle monospaced font in BACKSPACE +; Don't script special chars +; Don't die on bad call to picinf, just on disp pic +; +;89-April 11, 1989 +; Check for zero object in REMOVE +; Make sure soft switches are good in ZSAVE +; Make sure restore gets correct number of blocks if even multiple +; of 4 is saved +; Don't allow escape key +; Swap to info window on reseat message +; Try doing online call before checking volume name again +; +;90-April 12, 1989 +; Make sample filename for save be in uppercase, cuz Hollywood's a +; turkey +; +;91-April 13, 1989 +; One more for the gipper +; Don't bother printing the prefix on bad file verify message +; Print spaces to delete MORE, not CLREOL +; +;92-April 18, 1989 +; Add IPAGE to INFO_PAGE +; Clear [MORE] with backspaces +; +;93-April 19, 1989 +; If no bit in global directory, assume picture is on disk 1 +; +;94-April 20, 1989 +; Add more debugging code (save ZPC, ZPCPNT, and OPCODE) +; +;95-April 21, 1989 +; Add fatal error on clear of zero width/height (#25) screen +; +;96-April 22, 1989 +; Unwind the stack on a THROW +; +;97-April 26, 1989 +; Take out unscripting of control chars, so we get EOL +; +;98-April 27, 1989 +; Give back version number of pic file +; Move file pointer to beginning of file in verify, before calling +; SETUP_DISK0 +; Don't count skipped data on side 1, verify +; +;99-April 28, 1989 +; 'Nother new version, just cuz it's so much fun messing with +; Hollywood's pea brain +; Make sure bank 2 is still in after mouse call +; +;1-May 1, 1989 +; Shipped version +; +;2-May 2, 1989 +; HA! +; Do 5 retries, reseeking to zero and back before asking for reseat +; +;3-May 8, 1989 +; Let's pretend this is the shipped version +; Let's first retry the set prefix a few times before asking again +; +;4-May 11, 1989 +; Put in more debugging stuff for SHOGUN problems +; +;5-May 18, 1989 +; Take out ONLINE call in SET_PREFIX +; Make all PAGE2SW be READS!! not WRITES!! +; Make sure we leave off pointing to MAIN PAGE 2 always! +; Don't ever mess with STORE80 switch - ALWAYS ON +; +;6-May 19, 1989 +; Take out debugging stuff +; Make version number for pic files be swapped +; +;7-May 22, 1989 +; Put debugging code back in +; Make sure main bank is in there before starting scroll stuff +; Just scroll up X lines, don't bother with ZCRLF stuff +; +;8-May 23, 1989 +; Let's ship this version +; Move the SWAPBACK call on retry +; ORA char with $80 before shipping to printer +; Don't do clrbuf's at the start/end of PRINTT +; +;9-May 24, 1989 +; SHOGUN version, without PRINTT change +; +;10-May 24, 1989 +; Continued version, with PRINTT change +; +;11-June 2, 1989 +; Make formatted table have char count at front of line be a full +; word, for some dumb ass reason +; +;12-June 6, 1989 +; Make erase width be zero-based +; +;13-June 7, 1989 +; Take above "fix" out, please +; Increment CPY_COUNT to make it an inclusive count in SET_MASK +; Don't flush to screen just one character +; Only allow so many characters in save name +; +;14-June 12, 1989 +; Make count at beginning of line in formatted table be a word +; Start at word zero for formatted table +; Check for formatted table output in LINOUT and jump to tblrtn +; Make ending zero of formatted table be a word +; Get rid of spurious txa in zcolor +; +;15-June 13, 1989 +; Released to testing +; Save the cursor position after read, so if we redo this read we +; know where to put the cursor (hopefully) - if of course, +; CURSFLG is set +; diff --git a/apple/yzip/rel.15/windows.asm b/apple/yzip/rel.15/windows.asm new file mode 100644 index 0000000..67be2b6 --- /dev/null +++ b/apple/yzip/rel.15/windows.asm @@ -0,0 +1,769 @@ + + STTL "--- WINDOW OPERATIONS ---" + PAGE +; +; these are the data structures for all 8 WINDOW. They are identical and +; are just seperated cuz I use the addresses in the table that follows. +; All numbers are inclusive, absolute, and zero-based. +; +WINDSTRUCT EQU 0 +WINTOP EQU WINDSTRUCT ; first line of the window +WINLEFT EQU WINTOP+1 ; left edge of the window +WINHGHT EQU WINLEFT+1 ; height of the window +WINWID EQU WINHGHT+1 ; width of the window, in pixels +WINY EQU WINWID+1 ; y pos of cursor (pos, not relative) +WINX EQU WINY+1 ; x pos of cursor (remember, ABSOLUTE) +WINLM EQU WINX+1 ; left margin +WINRM EQU WINLM+1 ; right margin +WINCRF EQU WINRM+1 ; (WORD) function +WINCRC EQU WINCRF+2 ; (WORD) counter +WINHIGHL EQU WINCRC+2 ; highlight mode +WINFORE EQU WINHIGHL+1 ; foreground color (0=black-7=white) +WINBGND EQU WINFORE+1 ; background color (0=black-7=white) +WINFONT EQU WINBGND+1 ; window font (0=normal/4=monospaced) +WINFSIZE EQU WINFONT+1 ; (WORD) font Height/Width +WINATR EQU WINFSIZE+2 ; Window Attributes +WINLCNT EQU WINATR+1 ; current number of lines +; +; these are my interesting things +; +WINXSZ EQU WINLCNT+1 ; width of window, in pixels, using margin +WINLLEN EQU WINXSZ+1 ; length of current line +WINLINES EQU WINLLEN+2 ; max # of lines for window + +WINDOW0: + DB 0 ; WINTOP - first line of the window + DB 0 ; WINLEFT - left edge of the window + DB MAXHEIGHT ; WINHGHT - height of window + DB MAXWIDTH ; WINWID - width of window + DB 0 ; WINY - y pos of cursor (pos, not relative) + DB 0 ; WINX - x pos of cursor (remember, ABSOLUTE) + DB 0 ; WINLM - left margin + DB 0 ; WINRM - right margin + DW 0 ; WINCRF - function + DW 0 ; WINCRC - counter + DB 0 ; WINHIGHL - Highlights + DB $f ; WINFORE - foreground color default of white + DB 0 ; WINBGND - background color + DB 0 ; WINFONT - window font (0=normal/1=alternate) + DB 2,FONT_H ; WINFSIZE - Width/Height + DB $0f ; WINATR - all attributes on for window 0 + DB 0 ; WINLCNT - current number of lines + DB MAXWIDTH ; WINXSZ - width of window, in pixels, using margin + DB 0,0 ; WINLLEN - length of current line + DB (MAXHEIGHT/FONT_H)-1 ; WINLINES - max # of lines for window +; +; same start as window 0, but with 0 length +; +WINDOW1: + DB 0,0,0,MAXWIDTH,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,MAXWIDTH,0,0,0 +; +; the rest have no width/height/attributes (except buffering) +; +WINDOW2: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW3: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW4: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW5: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW6: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW7: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + +WINTABLE: + DW WINDOW0,WINDOW1,WINDOW2,WINDOW3 + DW WINDOW4,WINDOW5,WINDOW6,WINDOW7 + PAGE + +; ------ +; SCREEN +; ------ +; Move to the screen specified, by updating CURWIN and the cursor +; X,Y pos (SCRX,SCRY). Also put address of that window's structure +; in WINDOW. Save a bunch of the old stuff in old window's structure then +; update the same bunch with the new window's stuff. +; +; ARG1 - new screen id: 0-7 +; +ZSCRN: + jsr CLRBUF ; EMPTY OUTPUT BUFFER BEFORE MOVING +; +; now, save a few things from the common variables +; + ldy #WINLLEN ; current line length + lda LENGTH+LO ; get current line length + sta (WINDOW),Y ; save for later referencing + iny ; point to msb + lda LENGTH+HI ; get MSB + sta (WINDOW),Y ; saved + jsr SAVE_CURSOR ; save the x,y pos of cursor + lda INVFLG ; get inverse flag + beq ZSCA1 ; not set + lda #1 ; set 1 bit + bne ZSCA2 ; set in window +ZSCA1: + lda UNDFLG ; how about underlining + beq ZSCA2 ; nope + lda #4 ; 4 == underlining +ZSCA2: + ldy #WINHIGHL ; set new highlight + sta (WINDOW),Y ; save current attributes +; +; now it is time to update for new screen +; + lda ARG1+LO ; get which window + sta CURWIN ; save window number + asl A ; shift to make word indes + tax ; swap to indexing reg + lda WINTABLE,X ; get the address of the new WINDOW + sta WINDOW+LO ; lo part comes first + lda WINTABLE+1,X ; so go get hi part + sta WINDOW+HI ; save the hi part of the address + + jsr GET_CURSOR ; restore the cursor pos + + ldy #WINXSZ ; get line length + lda (WINDOW),Y ; update zero page variable + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + ldy #WINLLEN ; get current line length + lda (WINDOW),Y ; from before + sta LENGTH+LO ; save for later checking + iny + lda (WINDOW),Y + sta LENGTH+HI + ldy #WINLCNT ; how many lines already out there + lda (WINDOW),Y ; has been already saved + sta LINCNT ; and save 'ere too + ldy #WINLINES ; how many lines in this + lda (WINDOW),Y ; window, anyway? + sta MAXLINES ; show for everyone to see + ldy #WINLEFT ; show left margin + lda (WINDOW),Y ; get left edge + ldy #WINLM ; left margin + clc ; adding + adc (WINDOW),Y ; to find new left margin + sta LEFTMRG ; set up left margin for ease of use + ldy #WINTOP ; get top of window + lda (WINDOW),Y ; got it + clc ; adding + ldy #WINHGHT ; add height + adc (WINDOW),Y ; did it + sta SCRBTM ; this is first line outside window + ldy #WINHIGHL ; get highlighting modes + lda (WINDOW),Y ; first for inverse video + and #1 ; check for inverse video + beq SCRINV ; nope + lda #$80 ; means inverse video +SCRINV: + sta INVFLG ; there it be + lda (WINDOW),Y ; point to underline flag + and #4 ; check for underlining + beq SCRUND ; nope + lda #$80 ; means underlining +SCRUND: + sta UNDFLG ; save for everyone + + ldy #WINATR ; get the current attributes + lda (WINDOW),Y ; gottem + jsr SET_ATTRIBUTES ; set the flags, thank you + ldy #WINFONT ; get the font + lda (WINDOW),Y ; thank you + beq SCRFNT0 ; is it font zero? + lda #MONOFONT_W ; must be mono font, set width +SCRFNT0: + sta FONTFLG ; mark normal font +ZSCREX: + rts +;-------------- +; ZWINPOS +;-------------- +; +; change the window ARG1's top left corner to the new position +; +; ARG1 - window id from 0-7 +; ARG2 - new top y pos +; ARG3 - new top x pos +; +ZWINPOS: + dec ARG2+LO ; make pos be zero based + dec ARG3+LO ; now they are! +; +; if moving current window, save current cursor pos +; +ZWPOS0: + jsr SAVE_CURSOR ; saving +; +; let's set up [J] to point to window we are talking about +; +ZWPOS1: + lda ARG1+LO ; get window ID + jsr SETWJ ; get J to point to it + + lda ARG2+LO ; first, check the top + cmp #MAXHEIGHT ; < max height? + bcc CKWA1 ; fine + lda #0 ; make it zero then + sta ARG2+LO ; it is now +CKWA1: + lda ARG3+LO ; now check left edge + cmp #MAXWIDTH ; howzit compare + bcc CKWA2 ; just fine + lda #0 ; this too + sta ARG3+LO ; it is now +CKWA2: +; +; make the cursor pos be relative, so we can change back to +; absolute using new window pos +; + ldy #WINY ; let's do y pos first + lda (J),Y ; get the old y pos + ldy #WINTOP ; and subtract the top to make + sec ; (getting ready) + sbc (J),Y ; the pos relative + clc ; now add in new top + adc ARG2+LO ; this will be new top + ldy #WINY ; get y offset again + sta (J),Y ; and save new absolute y pos + ldy #WINX ; now we be talking about x pos + lda (J),Y ; get old x pos + sec ; getting ready for sub + ldy #WINLEFT ; get rid of left ness + sbc (J),Y ; now it's relative + clc ; get ready to add in new left ness + adc ARG3+LO ; done + ldy #WINX ; get x offset again + sta (J),Y ; save in structure +; +; now we can change the top and left of the window +; + lda ARG2+LO ; this is top of window + ldy #WINTOP ; TOP offset + sta (J),Y ; save the new top + lda ARG3+LO ; here is the left edge + ldy #WINLEFT ; offset into struct + sta (J),Y ; saved ! +; +; we might have moved current window so update screen cursor and left margin +; + jsr GET_CURSOR ; restore cursor + ldy #WINLEFT ; get left edge + lda (WINDOW),Y ; okay + ldy #WINLM ; add in left margin + clc ; adding + adc (WINDOW),Y ; to find new left edge + sta LEFTMRG ; store for ease of use + ldy #WINXSZ ; get xsize + lda (J),Y ; okay + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI +ZWPOSX: + rts +;------------ +; ZWINSIZE +;------------ +; +; Change the size of window ARG1. If cursor is outside of window, +; move to it. +; +; ARG1 - window ID +; ARG2 - height +; ARG3 - width +; +; Uses [J]. +; +ZWINSIZE: +; +; first put SCRCX,CY into window structure, just in case +; + jsr SAVE_CURSOR ; saved +; +; now do everything +; + lda ARG1+LO ; get the window ID + jsr SETWJ ; and get window pointer + + lda ARG2+LO ; first, check the top + cmp #MAXHEIGHT ; < max height? + bcc CKWA11 ; fine + lda #MAXHEIGHT ; make better + sta ARG2+LO ; it is now +CKWA11: + lda ARG3+LO ; now check left edge + cmp #MAXWIDTH ; howzit compare + bcc CKWA21 ; just fine + lda #MAXWIDTH ; make it the max + sta ARG3+LO ; it is now +CKWA21: + lda ARG2+LO ; get new height + ldy #WINHGHT ; offset + sta (J),Y ; save new height + lda ARG3+LO ; get width + ldy #WINWID ; store width + sta (J),Y ; okay +; +; now we need to figger out new XSIZE, MAXLINES +; + ldy #WINWID ; store width + lda (J),Y ; get width + sec ; have width, subtract margins + ldy #WINRM ; first right margin + sbc (J),Y ; subtracted right margin + ldy #WINLM ; and now for the left margin + sbc (J),Y ; now we have new XSIZE + ldy #WINXSZ ; get offset + sta (J),Y ; save for later ref + lda ARG2+LO ; get new height + ldx #$FF ; this is the counter + sec ; get ready for subs +ZWSZ1: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZWSZ1 ; still some lines + dex ; to keep the input line on screen + txa ; get line count for storage + ldy #WINLINES ; this is how many lines are allowed + sta (J),Y ; saved +; +; check to make sure the cursor is still in the window +; + ldy #WINLM ; get left margin + clc ; for adding + adc (J),Y ; for figgering out right edge + ldy #WINLEFT ; add in left edge + adc (J),Y ; get right column by adding in left one + ldy #WINX ; check X pos + cmp (J),Y ; see if X is still inside? + beq ZWSZ2 ; must move to top left + bcc ZWSZ2 ; ditto if X >= margin + ldy #WINTOP ; get top to figger last line + lda (J),Y ; from the structure + ldy #WINHGHT ; and add in the height + clc ; getting ready for add + adc (J),Y ; to find first line outside of range + ldy #WINY ; now check y + cmp (J),Y ; now check y then + beq ZWSZ2 ; outside, move to top left + bcs ZWSZ3 ; inside so quit +; +; move the cursor to top left if outside of resized window +; +ZWSZ2: + ldy #WINTOP ; top line is here + lda (J),Y ; so get me it + ldy #WINY ; now we be doing y + sta (J),Y ; change Y + ldy #WINLEFT ; move X to left margin + lda (J),Y ; first get left edge + ldy #WINLM ; and add in left margin + clc ; (adding) + adc (J),Y ; to get left spot of cursor + ldy #WINX ; this is x offset + sta (J),Y ; so move X there +; +; now check to see if we mucked with current window +; +ZWSZ3: + lda ARG1+HI ; this is the id + bmi ZWSZ4 ; must be current window + cmp CURWIN ; is it current window? + bne ZWSZX ; nope, so done +ZWSZ4: + ldy #WINLINES ; get how many lines + lda (J),Y ; get number of lines + sta MAXLINES ; set global + ldy #WINXSZ ; get new XSIZE too + lda (J),Y ; get it + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + jsr GET_CURSOR ; fix the cursor pos +ZWSZX: + rts +; +;CHECK_WIN_ARGS +; check args to make sure they be okay +; +; ARG2 = top/height +; ARG3 = right/width +; +CHECK_WIN_ARGS: + rts + + ; ------ + ; HLIGHT + ; ------ + +ZLIGHT: + lda ARG1+LO ; get argument + cmp #$10 ; must be <= 8 + bcs ZLIEX ; nope it aint + ora #$80 ; turn on hi bit + jsr COUT ; send it out then +ZLIEX: + rts ; done +; +; actually set the highlight flags according to [A] +; +HLIGHT: +; +; TURN OFF ALL HIGHLIGHTS +; + and #$7F ; turn off high bit + bne ZL1 ; nope, must be something + sta UNDFLG ; and turn of underlining flag + sta INVFLG ; and inverse + rts ; all done +ZL1: + cmp #4 ; underlining + bne ZL_REV ; maybe its INVERSE? + + lda #$80 ; turn on UNDFLG + sta UNDFLG ; with an FF + rts ; done +ZL_REV: + cmp #1 ; INVERSE? + bne ZL_MONO ; maybe monospaced then + lda #$80 ; must be inverse video + sta INVFLG ; and put it in invflg + rts +ZL_MONO: + rts ; fuck it for now! +; +; ZWINATTER - change the scrolling/buffering/scripting/wrapping attributes +; of the window. +; +; ARG1 - window id +; ARG2 - interesting bits +; | buffering | scripting | scrolling | wrapping | +; ARG3 - operation - 0 MOVE +; 1 SET +; 2 CLEAR +; 3 COMPLEMENT +; +ZWINATTR: + lda NARGS ; see how many args + cmp #3 ; check for operation args + beq ZWAT1 ; yes, already there + lda #0 ; zero means MOVE + sta ARG3+LO ; so show it as default +ZWAT1: + lda ARG1+LO ; get window ID + jsr SETWJ ; put window address into [J] + + ldy #WINATR ; get attribute offset + lda (J),Y ; get current attribute + clc ; so we can just branch + + dec ARG3+LO ; decrement to find out what to do + bmi ZWMOVE ; do a move + beq ZWSET ; do a set + dec ARG3+LO ; check once more + beq ZWCLEAR ; clear set ones +; +; this is for the COMPLEMENT operations +; + eor ARG2+LO ; complement bits + bcc ZWAT2 ; done +ZWMOVE: +; +; move into the flag word +; + lda ARG2+LO ; get new flags + bcc ZWAT2 ; done +ZWSET: +; +; set turned on ones +; + ora ARG2+LO ; set'em up + bcc ZWAT2 ; done +ZWCLEAR: +; +; clear just the ones that are on +; + lda ARG2+LO ; get argument + eor #$FF ; turn on all the off ones + and (J),Y ; keep all the other ones +ZWAT2: + sta (J),Y ; and save it back +; +; now, if current window, set necessary flags +; + ldx ARG1+LO ; get window ID + bmi SET_ATTRIBUTES ; assume negative is current window + cpx CURWIN ; is this the current one? + bne ZWATX ; nope, so leave +SET_ATTRIBUTES: +; +; current window, so set flags accordingly +; + ldx #0 ; to turn off flag + ldy #1 ; to turn on flag + ror A ; get wrapping flag into carry + bcc ZWAT3 ; clear it + sty WRPFLG ; set wrapping on + bcs ZWAT33 ; okay +ZWAT3: + stx WRPFLG ; clear wrapping flag +ZWAT33: + ror A ; now check thes crolling flag + bcc ZWAT4 ; not set + sty SCRLFLG ; turn on scrolling flag + bcs ZWAT44 ; okay, next please +ZWAT4: + stx SCRLFLG ; turn off scrolling +ZWAT44: + ror A ; checking the scripting flag + bcc ZWAT5 ; not set + sty SCRIPTFLG ; allow scripting? yes + bcs ZWAT55 ; next flag +ZWAT5: + stx SCRIPTFLG ; allow scripting? no +ZWAT55: + ror A ; this checks the buffering flag + bcc ZWAT6 ; not set + sty BUFFLG ; turn on buffering + bcs ZWATX ; scram +ZWAT6: + stx BUFFLG ; turn off buffering +ZWATX: + rts +; +; ZWINGET - put the window stuff into a table +; +; ARG1 - Window id +; ARG2 - offset +; +ZWINGET: + jsr SAVE_CURSOR ; save x,y into structure + + lda ARG1+LO ; get window ID + jsr SETWJ ; set up window address + + lda ARG2+LO ; get where to start getting + asl A ; make word index + tax ; make index + lda ZWGTBL+LO,X ; get lo part of address + sta K+LO ; save for jumping + lda ZWGTBL+HI,X ; get hi part + sta K+HI ; saved + jsr ZWGVEC ; do the vectoring + stx VALUE+HI ; save hi part + sta VALUE+LO ; and the lo part + jmp PUTVAL ; and return it +ZWGVEC: + jmp (K) ; and goto it boys +ZWG0: + ldx #0 ; zero out high part + ldy #WINTOP ; get window y pos + lda (J),Y ; got it + tay ; need to inc it + iny ; to make it a one-based number + tya ; back to a + rts +ZWG1: + ldx #0 ; zero out high part + ldy #WINLEFT ; get window x pos + lda (J),Y ; got it + tay ; need to inc it + iny ; to make it a one-based number + tya ; back to a + rts +ZWG2: + ldx #0 ; zero out high part + ldy #WINHGHT ; get window height + lda (J),Y ; got it + rts +ZWG3: + ldx #0 ; zero out high part + ldy #WINWID ; window width + lda (J),Y ; got it + rts +ZWG4: + jsr FETCHCY ; get the current Y pos + ldx #0 ; zero out high part + rts +ZWG5: + jsr FETCHCX ; fetch the current X pos + ldx #0 ; zero out high part + rts +ZWG6: + ldx #0 ; zero out high part + ldy #WINLM ; left margin + lda (J),Y ; got it + rts +ZWG7: + ldx #0 ; zero out high part + ldy #WINRM ; right margin + lda (J),Y ; got it + rts +ZWG8: + ldy #WINCRF+HI ; function + lda (J),Y ; got it, lo part + tax ; save hi part + dey ; point to lo part + lda (J),Y ; got lo part + rts +ZWG9: + ldy #WINCRC+HI ; count + lda (J),Y ; got it, hi part + tax ; save it + dey ; now to lo part + lda (J),Y ; got it + rts +ZWG10: + ldy #WINHIGHL ; get high light mode + lda (J),Y ; got it + ldx #0 ; zero out high part + rts +ZWG11: + ldy #WINBGND ; and background + lda (J),Y ; got it + tay ; make index + lda APLCOLOR,Y ; get apl->zip color + tax ; save for return + ldy #WINFORE ; get foreground + lda (J),Y ; got it + tay ; save it + lda APLCOLOR,Y ; get apl->zip color + rts +ZWG12: + ldy #WINFONT ; now for font id + lda (J),Y ; got it + ldx #0 ; zero out high part + rts +ZWG13: + ldy #WINFSIZE+1 ; font size (width) + lda (J),Y ; got it + tax ; save it + dey ; font size (height) + lda (J),Y ; got it + rts +ZWG14: + ldx #0 ; zero out high part + ldy #WINATR ; attributes + lda (J),Y ; got it + rts ; got them! +ZWG15: + ldx #0 ; only 1 byte worth + ldy #WINLCNT ; offset + lda (J),Y ; get more counter + rts +; +; jump table for figgering out where to start filling +; +ZWGTBL: + DW ZWG0,ZWG1,ZWG2,ZWG3,ZWG4,ZWG5,ZWG6,ZWG7 + DW ZWG8,ZWG9,ZWG10,ZWG11,ZWG12,ZWG13,ZWG14,ZWG15 +; +; ZSCROLL - scroll the specified window up or down +; +; ARG1 - window ID +; ARG2 - lines to scroll; <0 scrolls down +; +ZSCROLL: + jsr SAVE_CURSOR ; save where cursor is + + lda #0 ; don't script scroll + sta SCRIPT ; fine, we won't now + + lda ARG1+LO ; get which window + jsr SETWJ ; set up pointer + dec NARGS ; see what we have for lines + bne ZSCR1 ; a passed arg + lda #1 ; 1 line is default + sta ARG2+LO ; so say so +ZSCR1: + ldy #WINTOP ; get me window limits + lda (J),Y ; first top + sta CLSTOP ; save for usage + iny ; now left + lda (J),Y ; okay, get for this window + sta CLSLEFT ; save left + iny ; now it's width + lda (J),Y ; got the window height + sta CLSHEIGHT ; this is it + iny ; this is height + lda (J),Y ; get window's height + sta CLSWIDTH ; save + lda ARG2+HI ; is it negative? + sta SCLDIR ; show direction of scroll + bpl ZSCRL1 ; nope + ldx ARG2+LO ; get how many lines + eor #$FF ; make pos + tax ; put in X for inc + inx ; and make right + bne ZSCRLEX ; done +ZSCRL1: + ldx ARG2+LO ; get how many lines +ZSCRLEX: + stx SCLLINES ; save for routine + jsr DO_SCROLL ; and do the scroll +ZSCRLEX1: + lda #1 ; allow scripting + sta SCRIPT ; we do + jmp GET_CURSOR ; restore the cursor, thank you +; +; ZWINPUT - put some information into window structure. Just CRF/CRC +; is legit now. +; +; ARG1 - window ID +; ARG2 - Word to be saved +; ARG3 - offset of value +; +ZWINPUT: + jsr SAVE_CURSOR ; save the cursor pos + lda ARG1+LO ; get window ID + jsr SETWJ ; have J point to structure + + lda ARG2+LO ; get first value in table + cmp #8 ; 8 = function + beq ZWIPCRF ; so save that + cmp #9 ; this is counter + beq ZWIPCRC ; so set counter + cmp #15 ; LINCNT? + beq ZIPLCT ; then set it too + rts ; just die then +ZIPLCT: + ldy #WINLCNT ; point to line count + bne ZWINPUT2 ; and stash it away +ZWIPCRF: + ldy #WINCRF+1 ; point to window's CR function + bne ZWINPUT1 ; and put it +ZWIPCRC: + ldy #WINCRC+1 ; point to window's CR counter +ZWINPUT1: + lda ARG3+HI ; now get hi part + sta (J),Y ; saved! + dey ; point to lo part +ZWINPUT2: + lda ARG3+LO ; start with lo part + sta (J),Y ; save lo part +ZWIPLCT: + jmp GET_CURSOR ; restore cursor/lincnt + + END diff --git a/apple/yzip/rel.15/xpaging.asm b/apple/yzip/rel.15/xpaging.asm new file mode 100644 index 0000000..ebce363 --- /dev/null +++ b/apple/yzip/rel.15/xpaging.asm @@ -0,0 +1,681 @@ + STTL "--- MEMORY PAGING ROUTINES ---" + PAGE + +; ------------------------- +; POINT [MPC] TO V-ADDR [I] +; ------------------------- + +SETWRD: LDA I+LO + STA MPCL + LDA I+HI + STA MPCM + LDA #0 + STA MPCH ; ZERO TOP BIT + JMP VLDMPC + +; +WANTED: DB 00,00 +; +NEXT: DB 00 +NSUBA: DB 00 +PSUBA: DB 00 +; +YTEMP: DB 00 +ATEMP: DB 00 +NSUBY: DB 00 +; +; set [A](page), [Y](bank) to point to memory page where page in [A] is +; +SETPC: + sta MEMPAGE ; save it for later addition + cmp #P2PAGE ; IS IT A PAGE IN MAIN + bcs VF2 ; No, it might be in aux mem + + lda #>ZBEGIN ; ADD OFFSET TO GET RAM PAGE + ldy #MAIN ; in the main bank + beq VFEXI ; BRA to fetch +VF2: + cmp #PGBEGIN ; is it paged? + bcs VFERR ; yes it be paged, so can't deal with it + cmp #P3PAGE ; is it in Aux Mem, Part 2? + bcs VF3 ; yes, so subtract different amount +; +; this is in lower aux +; + lda #(Z2PAGE-Z1SIZE) ; subtract size from offset + ldy #AUX ; show aux mem + bne VFEXI ; jump to end +VF3: + lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides + ldy #P3BANK ; show page 3 bank +VFEXI: + clc ; get ready for addition + adc MEMPAGE ; now get actual offset + rts +VFERR: +; +; out of range +; + lda #18 + jmp ZERROR +; +; NEXTSPC - inc SPCL and check for wrapping round to next bank +; +NEXTSPC: + inc SPCL ; next lo byte + bne NXSP_EXIT ; no change then + inc SPCH ; next page + lda SPCH ; so get page + cmp #>PRGLBL ; have we reached end of line? + bne NXSP_EXIT ; we be okay + lda SPCBNK ; get bank + bne NXSP1 ; must go to Part 3 + inc SPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta SPCH ; and point to it + rts ; and all done +NXSP1: + lda #Z3PAGE ; get start of page 3 + sta SPCH ; and point there + lda #P3BANK ; and point to this bank + sta SPCBNK ; okey +NXSP_EXIT: + rts +; +; NEXTFPC - inc DPCL and check for wrapping round to next bank +; +NEXTFPC: + inc FPCL ; next lo byte + bne NXFP_EXIT ; no change then + inc FPCH ; next page + lda FPCH ; and get it for checking + cmp #>PRGLBL ; have we reached end of line? + bne NXFP_EXIT ; we be okay + lda FPCBNK ; get bank + bne NXFP1 ; must skip over stuff in middle + inc FPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta FPCH ; and point to it + rts ; toots finis +NXFP1: + lda #Z3PAGE ; start of part 3 + sta FPCH ; so show me + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey +NXFP_EXIT: + rts +; +; ADDFPC - add amount in [A] to current FPC and check for bank wrap +; +ADDFPC: + clc ; get ready for add + adc FPCL ; add lo part + sta FPCL ; and save it + bcc AFPX ; all done if no page wrap + inc FPCH ; point to next page + lda FPCH ; get it for compare + cmp #>PRGLBL ; at end of line in main bank? + bne AFPX ; nope, all done then + lda FPCBNK ; get bank + beq AFP1 ; it is main, so we be ok + lda #Z3PAGE ; must go to part 3 if in aux mem + sta FPCH ; thanx + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey + rts ; done +AFP1: + inc FPCBNK ; point to aux + lda #Z2PAGE ; get start in aux + sta FPCH ; and save it +AFPX: + rts +; +; ADDSPC - add amount in [A] to current SPC and check for bank wrap +; +ADDSPC: + clc ; get ready for add + adc SPCL ; add lo part + sta SPCL ; and save it + bcc ASPX ; all done if no page wrap + inc SPCH ; point to next page + lda SPCH ; get it for compare + cmp #>PRGLBL ; at end of line in main bank? + bne ASPX ; nope, all done then + lda SPCBNK ; get bank + beq ASP1 ; it is main, so we be ok + lda #Z3PAGE ; must go to part 3 if in aux mem + sta SPCH ; thanx + lda #P3BANK ; and point to this bank + sta SPCBNK ; okey + rts ; done +ASP1: + inc SPCBNK ; point to aux + lda #Z2PAGE ; get start in aux + sta SPCH ; and save it +ASPX: + rts +; +; PREVFPC - DEC FPCL and check for wrapping round to next bank +; +PREVFPC: + lda FPCL ; get lo part + bne PFPC2 ; it's not zero, so no wrapping + lda FPCH ; get current page + cmp #Z2PAGE ; have we reached beginning of page 2? + beq PFPC1 ; wrap to first bank + cmp #Z3PAGE ; beginning of part 3? + beq PFPC3 ; ayyup + dec FPCH ; point to previous page + bne PFPC2 ; okay +PFPC1: + lda FPCBNK ; get bank + beq VF1ERR ; oops, can't go backwards from main bank + lda #MAIN ; so point to main bank + beq PFPC4 ; and store it away +PFPC3: + lda #AUX ; and point to this bank +PFPC4: + sta FPCBNK ; okey + lda #(>PRGLBL)-1 ; get me last page in part 2 + sta FPCH ; and show me +PFPC2: + dec FPCL ; and point to previous byte + rts +VF1ERR: +; +; out of range +; + lda #19 + jmp ZERROR +; +; PREVSPC - DEC SPCL and check for wrapping round to main bank +; +PREVSPC: + lda SPCL ; get lo part + bne PSPC2 ; it's not zero, so no wrapping + lda SPCH ; get current page + cmp #Z2PAGE ; have we reached beginning of page 2? + beq PSPC1 ; wrap to first bank + cmp #Z3PAGE ; down past page 3? + beq PSPC3 ; sure is + dec SPCH ; point to previous page + bne PSPC2 ; okay +PSPC1: + lda SPCBNK ; get bank + beq VF1ERR ; oops, can't go backwards from main bank + lda #MAIN ; so point to main bank + beq PSPC4 ; so save it +PSPC3: + lda #AUX ; and point to this bank +PSPC4: + sta FPCBNK ; okey + lda #>PRGLBL-1 ; get me last page in low part + sta SPCH ; and show me +PSPC2: + dec SPCL ; and point to previous byte + rts +; +; FP2SP - copy the 3 parts of FPC to SPC +; +FP2SP: + lda FPCBNK + sta SPCBNK + lda FPCH + sta SPCH + lda FPCL + sta SPCL + rts + +; MAKE [MPCPNT],[MPCBNK] POINT TO +; THE RAM PAGE AND BANK THAT HOLDS +; THE V-PAGE MPCH,M +; +VLDMPC: + lda MPCH ; check hi part + bne VLD3 ; NOT IN FIRST V-64K, so must be paged + lda MPCM ; check to see if it is paged + jsr CHECKPRE ; is it preloaded? + bcs VLD3 ; no, so it be paged + jsr SETPC ; so put page/bank into A/Y + sty MPCBNK + sta MPCPNT+HI +NOMUCK: + rts +; +; must be paged, so check for it or read it in +; +VLD3: + lda MPCH + ldy MPCM + jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + clc + adc #>PBEGIN + sta MPCPNT+HI + ldy #PB_BANK ; paging buffers are in aux mem + sty MPCBNK +; +; TEST FOR MUCK +; + lda MUCKFLG + beq NOMUCK + bne VLDZPC ;MAY HAVE MUCKED ZPC SO GO FIX +; +; SAME IDEA AS VLDMPC +; +VLDZPC: + lda INFODOS ; check first for InfoDOS page + beq VLDZ1 ; none + jsr INFO_PAGE ; well, is it? + bcc VLDZ1 ; nope + rts ; all set otherwise +VLDZ1: + lda ZPCH + bne VLDZ3 ;NOT IN FIRST V-64K, so must be paged + lda ZPCM ; check to see if it is paged + jsr CHECKPRE ; is it preloaded? + bcs VLDZ3 ; no, so it must be paged + jsr SETPC ; point to correct bank and page + sty ZPCBNK ; set bank + sta ZPCPNT+HI ; and MSB of pointer +NOZMUCK: + rts +VLDZ3: ;MUST BE PAGED + lda ZPCH + ldy ZPCM + jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + clc + adc #>PBEGIN + sta ZPCPNT+HI + ldy #PB_BANK + sty ZPCBNK +; +; TEST MUCKING +; + lda MUCKFLG + beq NOZMUCK + jmp VLDMPC ;MAY HAVE MUCKED MPC SO GO FIX + + +; FIND V-PAGE A,Y IF IT IS IN MEM +; AND RETURN WITH LINKED LIST +; PROPERLY MAINTAINED +; IF V-PAGE A,Y NOT IN MEM +; GET FROM DISK AND PUT IN RIGHT +; PLACE + +MUCKFLG: DB 00 ;00 IF PAGING BUFFERS NOT MUCKED + +PAGE: + sta WANTED+HI + sty WANTED+LO + ldx #0 + stx MUCKFLG ; CLEAR MUCK FLAG + jsr WHERE + bcc TOUGH ; PAGE IS RESIDENT IN PAGING SPACE +; +; PAGE MUST BE BROUGHT IN FROM DISK +; + ldx CURRENT ;GET BUFFER TO PUT PAGE INTO + lda NEXTPNT,X ;BY LOOKING AT NEXT POINTER + sta CURRENT ;MAKE IT THE CURRENT BUFFER + tax + lda WANTED+HI ;LET BUFFER MAP KNOW + sta VPAGEH,X ;WHICH PAGE + lda WANTED+LO ;IS GOING TO + and #$FE ; make address be even + sta VPAGEL,X ;BE THERE +;*** +; point to the next page too +; + ora #1 ; add one to point to next 256 byte page + pha ; save it + txa ; get pointer + tay ; into y + iny ; point to next buffer + pla ; get second buffer back + sta VPAGEL,Y ; so point to it + lda VPAGEH,X ; get MSB + sta VPAGEH,Y ; and save it +; +; A = WANTED+HI +; Y = WANTED+LO +; X = BUFFER +; + lda WANTED+LO + and #$FE ; clear low bit to make it even + tay ; want it in y +;*** + lda WANTED+HI + ldx CURRENT + jsr GETVPAGE ; PUT V-PAGE A,Y INTO PAGING BUFFER X +;*** + dec MUCKFLG ; INDICATE A MUCKING + bne PAGEXIT ; and return current buffer +TOUGH: + and #$FE ; make even page, please + sta NEXT + cmp CURRENT ; GETS REALY SCREWED IF CURRENT==NEXT + beq PAGEXIT ; DO NOT CHANGE POINTERS IF IT DOES +; +; Y=NEXT(CURRENT) +; DO THE RIGHT THING TO THE POINTERS +; +; ldy CURRENT +; lda NEXTPNT,Y +; sta NSUBCUR + lda NEXT + jsr DETATCH + ldy CURRENT + lda NEXT + jsr INSERT + lda NEXT + sta CURRENT +PAGEXIT: +;*** perhaps add one to point to correct buffer + lda WANTED+LO ; get LSB + and #$01 ; pick up even/odd bit + clc ; doing add + adc CURRENT ; point to correct buffer + rts + +GETVPAGE: + sta DBLOCK+HI + sty DBLOCK+LO + txa ; get which paging buffer + clc + adc #>PBEGIN ; and set up abs addr + sta DBUFF+HI ; thank you, that's much better + ldx #PB_BANK + stx DSKBNK + jmp GETDSK + +; INSERT A AFTER Y +; A.next = Y.next +; Y.next = A +; A.previous = Y +; [Y.next].previous = A +INSERT: + tax + lda NEXTPNT,Y ; Y.next + sta NEXTPNT,X ; A.next = Y.next + pha ; save Y.next for later + txa + sta NEXTPNT,Y ; Y.next = A + tya + sta PREVPNT,X ; A.prev = Y + pla ; get Y.next back + tay ; [Y.next].previous + txa + sta PREVPNT,Y ; [Y.next].previous = A + rts + + IF 0 +; +; old one, which puts A AFTER! Y +; +; PREV(A)=Y +; PREV(NEXT(Y))=A +; NEXT(A)=NEXT(Y) +; NEXT(Y)=A + + sta ATEMP + sty YTEMP + tax + tya + sta PREVPNT,X + + lda NEXTPNT,Y + sta NSUBY + txa + ldx NSUBY + sta PREVPNT,X + + txa + ldx ATEMP + sta NEXTPNT,X + + lda ATEMP + sta NEXTPNT,Y + rts + ENDIF + +; DETATCH BUFFER >A< +; NEXT(PREV(A))=NEXT(A) +; PREV(NEXT(A))=PREV(A) + +DETATCH: + tax + lda NEXTPNT,X + tay ; Y == A.next + lda PREVPNT,X ; get A.previous + tax ; X == A.previous + tya ; get A.next + sta NEXTPNT,X ; [A.previous].next = A.next + txa ; get A.previous + sta PREVPNT,Y ; [A.next].previous = A.previous + rts + + +; RETURN BUFFER OF PAGE [WANTED] +; IN >A< ELSE SEC (Y=WANTED+LO) + +WHERE: LDX #NUMBUFS-1 +WHLOOP: + LDA WANTED+HI + CMP VPAGEH,X ;>SAME + BEQ WHGOT +WHNOGOT: + DEX + BPL WHLOOP + SEC + RTS +WHGOT: + TYA + CMP VPAGEL,X + BNE WHNOGOT + TXA + CLC + RTS +; +; CHECKPRE - check to see if page in [A] is in preloaded +; +CHECKPRE: + cmp TBLPUR ; check against PURE tables + bcc CHKPEXY ; must be preloaded then +CHKP1: + cmp FUNPRE ; is it in function preload? + bcc CHKPEXN ; preloaded function > desired, not preloaded + cmp FUNPUR ; how bout at end? + bcs CHKPEXN ; it is not preloaded +CHKP3: + clc ; doing add + adc FUNPGE ; get me memory page for function +CHKPEXY: + clc ; show it is preloaded + rts ; then we got it +CHKPEXN: + sec ; show it ain't here + rts +; +; INFO_PAGE - is it one of the special preloaded pages for infoDOS? If it +; is, then set up ZPCPNTR to point to it, and set carry. Otherwise, +; clear carry to show it ain't. +IPAGE: ds 2 +INFO_PAGE: + lda ZPCH ; get 2 parts + sta IPAGE+HI + lda ZPCM + sta IPAGE+LO + lsr IPAGE+HI ; /2 to get 512 block + ror IPAGE+LO + ldy #SGTSEG ; point to first segment, MSB + lda (INFODOS),Y ; howzit look? + iny ; point to LSB + cmp IPAGE+HI + bcc INFP1 ; might be interesting + bne INFPNX ; not here, < than minimum + lda (INFODOS),Y ; how bout LSB + cmp IPAGE+LO + beq INFPYX ; found it + bcs INFPNX ; nope, < than minimum again +; +; here, it's at least > than minimum +; +INFP1: +; iny ; point at end block, MSB + lda INFODOS_END+HI ; howz end segment look + cmp IPAGE+HI + bcc INFPNX ; nope, > than maximum of special + bne INFPYX ; yup, < than maximum of special +; iny ; LSB of last one + lda INFODOS_END+LO ; is LSB < special? + cmp IPAGE+LO ; MSB of current one == MSB of special + bcc INFPNX ; nope, not here +INFPYX: + ldy #SGTSEG+1 ; point back to start block, LSB + lda (INFODOS),Y ; get start block + asl A ; *2 to get start page + sta IPAGE+LO ; save it + lda ZPCM + sec ; doing sub + sbc IPAGE+LO ; get offset into special block + clc ; now add in offset + adc #>SP_START ; get the start of special area + sta ZPCPNT+HI ; show ZPCPNTR + lda #SP_BANK ; which bank + sta ZPCBNK ; okey + sec ; show it was here + rts +INFPNX: + clc ; show not here + rts ; g'day + + + +CHKPEXN0: + +GETBYT: + ldy MPCL + jsr MFETCH ; go and get it + inc MPCL ;POINT TO NEXT BYTE + bne GETGOT ;IF NO CROSS WE ARE STILL VALID + inc MPCM + bne GET1 + inc MPCH +GET1: + pha ; save byte + jsr VLDMPC + pla ; and get it back +GETGOT: + tay ;SET FLAGS + rts ;RED SLIPPER TIME +; +; NEXTPC - Fetch the byte at the current ZPC, point to next byte and +; validate pointer +; +NEXTPC: + ldy ZPCL ; get low pointer + jsr ZFETCH ; fetch @ZPCPNT + inc ZPCL + bne NXTGOT + inc ZPCM + bne CRSZ1 + inc ZPCH +CRSZ1: + pha ; save opcode + jsr VLDZPC + pla ; and get it back +NXTGOT: + tay + rts + +; +; STASHB - use SPC to save a byte in either aux or main mem +; +STASHB: + ldy SPCBNK ; get the bank + bmi SB1 ; must be in upper RAM + sta WRTBNK,Y ; set bank + ldy #0 ; can only do this with Y + sta (SPC),Y ; get the sucker + beq SBEXI ; jump to end it +; +; this is in aux mem, >$E000 +; +SB1: + ldy SPCH ; get high part + sty SBMOD+2 ; and self mod my code + ldy SPCL ; and get the low part + sta ALTZP+AUX ; talk about aux mem +SBMOD: + sta Z3BEGIN,Y ; store the little byte + sta ALTZP+MAIN ; go back to main mem +SBEXI: + sta WRTBNK+MAIN ; and write to main + rts +; +; FETCHB - fetch a byte from either main memory, aux memory, or upper +; Aux memory +; +FETCHB: + ldy FPCBNK ; get the bank + bmi FB1 ; must be in upper RAM + jsr ZERO_FB ; go to low end fetch + rts +; +; this is in aux mem, >$E000 +; +FB1: + lda FPCH ; get which page + sta FBMOD+2 ; and show in operand + ldy FPCL ; get which byte + sta ALTZP+AUX ; talk about aux mem +FBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + tay ; set condition code + rts +; +; ZFETCH - after checking for which bank (main, aux 1 or aux 2), go get +; the byte @ ZPCPNT, with the offset being in [Y] +; +ZFETCH: + ldx ZPCBNK ; get the bank + bmi ZFB1 ; must be in upper RAM + jsr ZERO_ZF ; go to low end fetch + rts +; +; this is in aux mem, >$D000 +; +ZFB1: + lda ZPNTH ; which page are we talking about + sta ZBMOD+2 ; show in the operand + sta ALTZP+AUX ; talk about aux mem +ZBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + tax ; set condition code + rts +; +; MFETCH - after checking for which bank (main, aux 1 or aux 2), go get +; the byte @MPCPNT, with the offset being in [Y] +; +MFETCH: + ldx MPCBNK ; get the bank + bmi MB1 ; must be in upper RAM + jsr ZERO_MF ; go to low end fetch + rts +; +; this is in aux mem, >$D000 +; +MB1: + lda MPNTH ; which page are we talking about + sta MBMOD+2 ; show in the operand + sta ALTZP+AUX ; talk about aux mem + +MBMOD: lda Z3BEGIN,Y ; get the sucker + + sta ALTZP+MAIN ; go back to main mem + tax ; set condition code + rts + + + END diff --git a/apple/yzip/rel.15/yzip.asm b/apple/yzip/rel.15/yzip.asm new file mode 100644 index 0000000..40cef6e --- /dev/null +++ b/apple/yzip/rel.15/yzip.asm @@ -0,0 +1,86 @@ + ; -------------------------- + ; YZIP + ; Z-CODE INTERPRETER PROGRAM + ; FOR APPLE ][e/][c/][gs + ; -------------------------- + + ; INFOCOM, INC. + ; 125 CAMBRIDGEPARK DRIVE + ; CAMBRIDGE, MA 02140 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + + PL 50000 ; PAGE LENGTH OF PRINTER + +DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER (1 = YES) +CHECKSUM EQU 0 ; == 1 for generating save/restore checksum + + ; ----------- + ; 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 -- IMPURE CODE TOO LARGE (BM 1/20/86) + ; 14 -- DRIVE ACCESS + ; 15 -- NOT AN EZIP GAME + ; 16 -- ILLEGAL EXTENDED RANGE X-OP + ; 17 -- BAD VIRTUAL PAGE + ; 18 -- SETPC NOT PRELOADED + ; 19 -- PREVIOUS (SPC/FPC) NOT POSSIBLE + ; 20 -- PICTURE NOT FOUND + ; 21 -- ZERO OBJECT TO BE REMOVED + ; 22 -- OBJECT TOO BIG (ZLOC) + ; 23 -- Bad read: Read != Asked for + ; 24 -- Bad read: Retry 1 != Retry 2 + ; 25 -- Clear of zero height/width window + + TITLE "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + INCLUDE ZIP.EQU + INCLUDE ZERO.EQU + INCLUDE PRODOS.EQU + INCLUDE APPLE.EQU + INCLUDE MACROS.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + INCLUDE ZBEGIN.ASM + INCLUDE MAIN.ASM + INCLUDE SUBS.ASM + INCLUDE DISPATCH.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + INCLUDE ZDOS.ASM + INCLUDE MACHINE.ASM + INCLUDE IO.ASM + INCLUDE VERIFY.ASM + INCLUDE SCREEN.ASM + INCLUDE TABLES.ASM + INCLUDE WINDOWS.ASM + INCLUDE DLINE.ASM + INCLUDE PIC.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + INCLUDE OPS012.ASM + INCLUDE OPSX.ASM + INCLUDE READ.ASM + INCLUDE ZSAVRES.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + INCLUDE XPAGING.ASM + INCLUDE ZSTRING.ASM + INCLUDE OBJECTS.ASM + + BLKB ZBEGIN-$,0 + END + diff --git a/apple/yzip/rel.15/yzip.bin b/apple/yzip/rel.15/yzip.bin new file mode 100644 index 0000000..144a86e Binary files /dev/null and b/apple/yzip/rel.15/yzip.bin differ diff --git a/apple/yzip/rel.15/yzip.lst b/apple/yzip/rel.15/yzip.lst new file mode 100644 index 0000000..2969303 --- /dev/null +++ b/apple/yzip/rel.15/yzip.lst @@ -0,0 +1,15807 @@ + Tue Jun 13 1989 11:42 Page 1 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + + + + + 2500 A.D. 6502 Macro Assembler - Version 4.01a + ------------------------------------------------ + + Input Filename : YZIP.asm + Output Filename : YZIP.obj + + + 1 ; -------------------------- + 2 ; YZIP + 3 ; Z-CODE INTERPRETER PROGRAM + 4 ; FOR APPLE ][e/][c/][gs + 5 ; -------------------------- + 6 + 7 ; INFOCOM, INC. + 8 ; 125 CAMBRIDGEPARK DRIVE + 9 ; CAMBRIDGE, MA 02140 + 10 + 11 ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + 12 + 13 PL 50000 ; PAGE LENGTH OF PRINTER + 14 + 15 0000 DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER (1 = YES) + 16 0000 CHECKSUM EQU 0 ; == 1 for generating save/restore checksum + 17 + 18 ; ----------- + 19 ; ERROR CODES + 20 ; ----------- + 21 + 22 ; 00 -- INSUFFICIENT RAM + 23 ; 01 -- ILLEGAL X-OP + 24 ; 02 -- ILLEGAL 0-OP + 25 ; 03 -- ILLEGAL 1-OP + 26 ; 04 -- ILLEGAL 2-OP + 27 ; 05 -- Z-STACK UNDERFLOW + 28 ; 06 -- Z-STACK OVERFLOW + 29 ; 07 -- ILLEGAL PROPERTY LENGTH (GETP) + 30 ; 08 -- DIVISION BY ZERO + 31 ; 09 -- ILLEGAL ARGUMENT COUNT (EQUAL?) + 32 ; 10 -- ILLEGAL PROPERTY ID (PUTP) + 33 ; 11 -- ILLEGAL PROPERTY LENGTH (PUTP) + 34 ; 12 -- DISK ADDRESS OUT OF RANGE + 35 ; 13 -- IMPURE CODE TOO LARGE (BM 1/20/86) + 36 ; 14 -- DRIVE ACCESS + 37 ; 15 -- NOT AN EZIP GAME + 38 ; 16 -- ILLEGAL EXTENDED RANGE X-OP + 39 ; 17 -- BAD VIRTUAL PAGE + 40 ; 18 -- SETPC NOT PRELOADED + 41 ; 19 -- PREVIOUS (SPC/FPC) NOT POSSIBLE + 42 ; 20 -- PICTURE NOT FOUND + 43 ; 21 -- ZERO OBJECT TO BE REMOVED + 44 ; 22 -- OBJECT TOO BIG (ZLOC) + 45 ; 23 -- Bad read: Read != Asked for + 46 ; 24 -- Bad read: Retry 1 != Retry 2 + 47 ; 25 -- Clear of zero height/width window + 48 0000 + 49 0000 TITLE "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + 50 0000 INCLUDE ZIP.EQU + 51 0000 STTL "--- YZIP EQUATES ---" + 52 PAGE + Tue Jun 13 1989 11:42 Page 2 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- YZIP EQUATES ---" + + 53 + 54 000F VERSID EQU 15 ; VERSION OF INTERPRETER + 55 ; See file "versions" for complete descriptions + 56 + 57 00FF TRUE EQU $FF + 58 0000 FALSE EQU 0 + 59 + 60 ; --------------------- + 61 ; Segment table equates + 62 ; --------------------- + 63 0000 SGTDISKS EQU 0 ; number of disks + 64 0002 SGTPAD EQU SGTDISKS+2 ; just some extra room + 65 0012 SGTCHKS1 EQU SGTPAD+16 ; Checksum for disk 1 (PRELOAD) + 66 0014 SGTPICOF1 EQU SGTCHKS1+2 ; N/A + 67 0016 SGTSEG1 EQU SGTPICOF1+2 ; # of segments + 68 0018 SGTGPOF1 EQU SGTSEG1+2 ; Global Picture Directory + 69 001A SGTTBLS EQU SGTGPOF1+2 ; Start of table preload (should be 0) + 70 001C SGTTBLE EQU SGTTBLS+2 ; Last page of table preload + 71 001E SGTTBLX EQU SGTTBLE+2 ; N/A + 72 0020 SGTFUNS EQU SGTTBLX+2 ; First page of function preload + 73 0022 SGTFUNE EQU SGTFUNS+2 ; End page of function preload + 74 0024 SGTFUNX EQU SGTFUNE+2 ; N/A + 75 0026 SGTDSK EQU SGTFUNX+2 ; Actual start of disk segment tables + 76 + 77 0000 SGTCHKS EQU 0 ; check sum for file + 78 0002 SGTPICOF EQU 2 ; picture data offset + 79 0004 SGTNSEG EQU 4 ; # of segments in this list + 80 0006 SGTGPOF EQU 6 ; Global Directory Offset + 81 0008 SGTSEG EQU 8 ; start of segments + 82 ; --------------------- + 83 ; Z-CODE HEADER OFFSETS + 84 ; --------------------- + 85 + 86 0000 ZVERS EQU 0 ; VERSION BYTE + 87 0001 ZMODE EQU 1 ; MODE SELECT BYTE + 88 0002 ZID EQU 2 ; GAME ID WORD + 89 0004 ZENDLD EQU 4 ; # OF QUADWORDS ON SIDE 1 OF DISK + 90 0006 ZGO EQU 6 ; EXECUTION ADDRESS + 91 0008 ZVOCAB EQU 8 ; START OF VOCABULARY TABLE + 92 000A ZOBJEC EQU 10 ; START OF OBJECT TABLE + 93 000C ZGLOBAL EQU 12 ; START OF GLOBAL VARIABLE TABLE + 94 000E ZPURBT EQU 14 ; START OF "PURE" Z-CODE + 95 0010 ZFLAGS EQU 16 ; FLAG WORD + 96 0012 ZSERIA EQU 18 ; 3-WORD SERIAL NUMBER + 97 0018 ZFWORD EQU 24 ; START OF FWORDS TABLE + 98 001A ZLENTH EQU 26 ; LENGTH OF Z-PROGRAM IN WORDS + 99 001C ZCHKSM EQU 28 ; Z-CODE CHECKSUM WORD + 100 001E ZINTWD EQU 30 ; INTERPRETER ID WORD (SUPPLIED BY EZIP) + 101 0020 ZSCRWD EQU 32 ; SCREEN PARAMETER WORD ( " " " ) + 102 0022 ZHWRD EQU 34 ; DISPLAY WIDTH IN PIXELS + 103 0024 ZVWRD EQU 36 ; DISPLAY HEIGHT IN PIXELS + 104 0026 ZFWRD EQU 38 ; FONT HEIGHT, FONT WIDTH + 105 0028 ZFOFF EQU 40 ; FUNCTION OFFSET + 106 002A ZSOFF EQU 42 ; STRING OFFSET + 107 002C ZCLRWD EQU 44 ; FORGROUND COLOR, BACKGROUND COLOR + 108 002E ZTCHAR EQU 46 ; POINTER TO TBL OF TERMINATING CHARS + 109 0030 ZTWIDTH EQU 48 ; Running counter for table output char width + 110 0032 ZCRFUNC EQU 50 ; FUNCTION FOR CARRIAGE RETURNS + 111 0034 ZCHRSET EQU 52 ; POINTER TO CHAR SET TBL + 112 0036 ZEXTAB EQU 54 ; Points to extension table, if needed + 113 ; + 114 ; Extension table offsets + 115 ; + 116 0000 ZEXTLEN EQU 0 ; Length of extension table + 117 0002 ZMSLOCX EQU 2 ; x location of mouse + 118 0004 ZMSLOCY EQU 4 ; y location of mouse + 119 0006 ZMSETBL EQU 6 ; MOUSE TBL CHANGE WORD + 120 0008 ZMSEDIR EQU 8 ; DIRECTION MENU + 121 000A ZMSEINV EQU 10 ; INVENTORY MENU + 122 000C ZMSEVRB EQU 12 ; FREQUENT VERB MENU + 123 000E ZMSEWRD EQU 14 ; FREQUENT WORD MENU + 124 0010 ZBUTTN EQU 16 ; BUTTON HANDLER + 125 0012 ZJOYST EQU 18 ; JOYSTICK HANDLER + 126 0014 ZBSTAT EQU 20 ; BUTTON STATUS + 127 0016 ZJSTAT EQU 22 ; JOYSTICK STATUS + Tue Jun 13 1989 11:42 Page 3 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- YZIP EQUATES ---" + + 128 ; + 129 ; ZFLAGS values + 130 ; + 131 0001 FSCRI EQU $01 ; scripting? + 132 0002 FMONO EQU $02 ; mono spaced font? + 133 0004 FSTAT EQU $04 ; status line refresh? + 134 0008 FDISP EQU $08 ; uses DISPLAY operations? + 135 0010 FUNDO EQU $10 ; uses UNDO? + 136 0020 FMOUS EQU $20 ; uses mouse? + 137 0040 FCOLO EQU $40 ; uses color? + 138 0080 FMENU EQU $80 ; uses menus? + 139 ;--------------- + 140 ; Picture data + 141 ;--------------- + 142 ;=== DATA HEADER === + 143 0000 PHFID EQU 0 ; File ID + 144 0001 PHFLG EQU PHFID+1 ; Flags + 145 0002 PHHUFF EQU PHFLG+1 ; Pointer to Huffman data + 146 0004 PHNLD EQU PHHUFF+2 ; # entries in local directory + 147 0006 PHNGD EQU PHNLD+2 ; # entries in global directory + 148 0008 PHDSIZE EQU PHNGD+2 ; Local directory entry size + 149 000A PHCHKS EQU PHDSIZE+2 ; File Checksum + 150 000C PHFVERS EQU PHCHKS+2 ; File Version (N/A) + 151 000E PHEXTRA EQU PHFVERS+2 ; Extra room for getting fatter + 152 0010 PHSIZE EQU 16 ; 16 bytes is header size + 153 ;=== DATA HEADER FLAGS === + 154 0001 PHFGD EQU $1 ; data has global directory + 155 0002 PHFHUFF EQU $2 ; Huffman encoded pictures + 156 0004 PHFHUFF1 EQU $4 ; All pictures use same Huff tree + 157 0008 PHFPAL EQU $8 ; No pallette information + 158 ;=== LOCAL DIRECTORY === + 159 0000 PLDID EQU 0 ; Picture ID + 160 0002 PLDWID EQU PLDID+2 ; Picture Width + 161 0003 PLDHGHT EQU PLDWID+1 ; Picture Height + 162 0004 PLDFLG EQU PLDHGHT+1 ; Flags + 163 0005 PLDPTR EQU PLDFLG+1 ; Pointer to picture data + 164 0008 PLDSIZE EQU PLDPTR+3 ; size of local directory entry + 165 + 166 0000 END + 167 + 168 0000 INCLUDE ZERO.EQU + 169 0000 STTL "--- ZERO PAGE VARIABLES ---" + 170 PAGE + Tue Jun 13 1989 11:42 Page 4 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ZERO PAGE VARIABLES ---" + + 171 + 172 0000 SCRCX EQU 0 ; CURSOR HORIZONTAL + 173 0001 SCRCY EQU SCRCX+1 ; CURSOR VERTICAL + 174 0002 SCRBTM EQU SCRCY+1 ; first line outside current window + 175 0003 MAXLINES EQU SCRBTM+1 ; maximum number of lines in window + 176 0004 LEFTMRG EQU MAXLINES+1 ; left edge + left margin in current window + 177 0005 WINDOW EQU LEFTMRG+1 ; (WORD) address of current window structure + 178 0007 LINE_X EQU WINDOW+2 ; (WORD) width of line counter + 179 0009 CC_OFF EQU LINE_X+2 ; save offset for char drawing + 180 000A CLSLEFT EQU CC_OFF+1 ; screen limits for CLS code + 181 000B CLSTOP EQU CLSLEFT+1 ; top of screen + 182 000C CLSWIDTH EQU CLSTOP+1 ; # of columns + 183 000D CLSHEIGHT EQU CLSWIDTH+1 ; # of lines + 184 ; + 185 ; some variables for all the screen positioning code + 186 ; + 187 000E NY_DATA EQU CLSHEIGHT+1 ; place for GET/PUT_NYBBLE to use + 188 000F CH_OFFSET EQU NY_DATA+1 ; offset into char data table + 189 0010 DATALOOP EQU CH_OFFSET+1 ; loop counter for byte works + 190 0011 BITOFF EQU DATALOOP+1 ; bit offset into screen byte + 191 0012 CH_DATA EQU BITOFF+1 ; actual char data being worked on + 192 0013 SCR_DATA EQU CH_DATA+1 ; screen byte being worked on + 193 0014 SH_LOOP EQU SCR_DATA+1 ; loop counter for bit shifting + 194 0015 SCROLLY EQU SH_LOOP+1 ; save spot for y pos when scrolling + 195 0016 RETRIES EQU SCROLLY+1 ; (BYTE) Machine ID + 196 0017 CHRMAX EQU RETRIES+1 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD + 197 0018 SCLLINES EQU CHRMAX+1 ; (BYTE) how many lines to scroll + 198 0019 FMTTBL EQU SCLLINES+1 ; (BYTE) flag to show formatted table output + 199 001A STMASK EQU FMTTBL+1 ; (BYTE) Mask to use on first byte of CLS + 200 001B ENDMASK EQU STMASK+1 ; (BYTE) Mask to use on last byte of CLS + 201 001C CHPTR EQU ENDMASK+1 ; (WORD) pointer to char data + 202 001C SCOFF EQU CHPTR ;(BYTE) Offset used by scroll + 203 001D SCLDIR EQU CHPTR+1 ;(BYTE) Direction of scroll - >0 up, <0 down + 204 001E DSEGS EQU CHPTR+2 ; (WORD) Pointer to current disk's segments + 205 ;WIDE_FLAG EQU SCOFF+1 ; (BYTE) <> 0 if 16 bytes in char data + 206 ;DSEGS EQU WIDE_FLAG+1 ; (WORD) Pointer to current disk's segments + 207 0020 LASTWV EQU DSEGS+2 ; last of the WINDOW variables + 208 + 209 0050 ZEROPG EQU $50 ; FIRST FREE Z-PAGE LOCATION + 210 ; + 211 ; these are first, cuz ZBOOT inits them so we don't want to clear them + 212 ; at ZBEGIN warm start + 213 ; + 214 0050 GLOBAL EQU ZEROPG ; (Relative Addr.) GLOBAL VARIABLE POINTER + 215 0052 VOCAB EQU GLOBAL+2 ; (ADDRESS) Vocab table pointer + 216 0055 FWORDS EQU VOCAB+3 ; (ADDRESS) F-WORDS TABLE POINTER + 217 0058 MOUSEF EQU FWORDS+3 ; (BYTE) ==-1/1 if we have mouse/joystick + 218 0059 INFODOS EQU MOUSEF+1 ; (WORD) if <>0, then pointer to D2SEG + 219 005B FUNOFF EQU INFODOS+2 ; (ADDRESS) Function Offset (ZFOFF*8) + 220 005B FOFFH EQU FUNOFF ; (BYTE) Hi part + 221 005C FOFFM EQU FUNOFF+1 ; (BYTE) Middle part + 222 005D FOFFL EQU FUNOFF+2 ; (BYTE) Lo part + 223 005E STROFF EQU FUNOFF+3 ; (ADDRESS) String Offset (ZSOFF*8) + 224 005E SOFFH EQU STROFF ; (BYTE) Hi part + 225 005F SOFFM EQU STROFF+1 ; (BYTE) Middle part + 226 0060 SOFFL EQU STROFF+2 ; (BYTE) Lo part + 227 ; + 228 ; Beginning of warm start zeroing + 229 ; + 230 0061 OPCODE EQU STROFF+3 ; (BYTE) CURRENT OPCODE + 231 0062 NARGS EQU OPCODE+1 ; (BYTE) # ARGUMENTS + 232 0063 ARG1 EQU OPCODE+2 ; (WORD) ARGUMENT #1 + 233 0065 ARG2 EQU OPCODE+4 ; (WORD) ARGUMENT #2 + 234 0067 ARG3 EQU OPCODE+6 ; (WORD) ARGUMENT #3 + 235 0069 ARG4 EQU OPCODE+8 ; (WORD) ARGUMENT #4 + 236 006B ARG5 EQU OPCODE+10 ; (WORD) + 237 006D ARG6 EQU OPCODE+12 ; (WORD) + 238 006F ARG7 EQU OPCODE+14 ; (WORD) + 239 0071 ARG8 EQU OPCODE+16 ; (WORD) + 240 0073 ABYTE EQU OPCODE+18 ; (BYTE) X-OP ARGUMENT BYTE + 241 0074 BBYTE EQU OPCODE+19 ; (BYTE) XCALL ARG BYTE (EZIP) + 242 0075 ADEX EQU OPCODE+20 ; (BYTE) X-OP ARGUMENT INDEX + 243 0076 VALUE EQU OPCODE+21 ; (WORD) VALUE RETURN REGISTER + 244 0078 I EQU VALUE+2 ; (WORD) GEN-PURPOSE REGISTER #1 + 245 007A J EQU VALUE+4 ; (WORD) GEN-PURPOSE REGISTER #2 + Tue Jun 13 1989 11:42 Page 5 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ZERO PAGE VARIABLES ---" + + 246 007C K EQU VALUE+6 ; (WORD) GEN-PURPOSE REGISTER #3 + 247 007E L EQU VALUE+8 ; (WORD) GEN-PURPOSE REGISTER #4 + 248 0080 ZPC EQU VALUE+10 ; (3 BYTES) ZIP PROGRAM COUNTER + 249 0080 ZPCL EQU ZPC ; (BYTE) <8 BITS OF [ZPC] + 250 0081 ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] + 251 0082 ZPCH EQU ZPC+2 ; (BYTE) >BIT OF [ZPC] + 252 0083 ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE + 253 0083 ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 254 0084 ZPNTH EQU ZPCPNT+1 ; (BYTE) + 255 0085 ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 256 0086 MPC EQU ZPCPNT+3 ; (3 BYTES) MEMORY PROGRAM COUNTER + 257 0086 MPCL EQU MPC ; (BYTE) <8 BITS OF [MPC] + 258 0087 MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] + 259 0088 MPCH EQU MPC+2 ; (BYTE) >BIT OF [MPC] + 260 0089 MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE + 261 0089 MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 262 008A MPNTH EQU MPCPNT+1 ; (BYTE) + 263 008B MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 264 008C FPC EQU MPCBNK+1 ; (3 Bytes) Fetch pointer + 265 008C FPCL EQU FPC ; (BYTE) Low part + 266 008D FPCH EQU FPCL+1 ; (BYTE) High Part + 267 008E FPCBNK EQU FPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 268 008F SPC EQU FPCBNK+1 ; (3 Bytes) Fetch pointer + 269 008F SPCL EQU SPC ; (BYTE) Low part + 270 0090 SPCH EQU SPCL+1 ; (BYTE) High Part + 271 0091 SPCBNK EQU SPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 272 + 273 ; Z-STRING MANIPULATION VARIABLES + 274 + 275 0092 LINLEN EQU SPCBNK+1 ; (BYTE) LENGTH OF CURRENT LINE + 276 0093 SOURCE EQU LINLEN+1 ; (BYTE) counter for read + 277 0094 WRDLEN EQU SOURCE+1 ; (BYTE) LENGTH OF CURRENT WORD + 278 0095 ESIZE EQU WRDLEN+1 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES + 279 0096 PSET EQU ESIZE+1 ; (BYTE) PERMANENT CHARSET + 280 0097 TSET EQU PSET+1 ; (BYTE) TEMPORARY CHARSET + 281 0098 ZCHAR EQU TSET+1 ; (BYTE) CURRENT Z-CHAR + 282 0099 OFFSET EQU ZCHAR+1 ; (BYTE) F-WORD TABLE OFFSET + 283 009A ZFLAG EQU OFFSET+1 ; (BYTE) Z-WORD ACCESS FLAG + 284 009B ZWORD EQU ZFLAG+1 ; (WORD) CURRENT Z-WORD + 285 009D CONCNT EQU ZWORD+2 ; (BYTE) Z-STRING SOURCE COUNTER + 286 009E CONIN EQU CONCNT+1 ; (BYTE) CONVERSION SOURCE INDEX + 287 009F CONOUT EQU CONIN+1 ; (BYTE) CONVERSION DEST INDEX + 288 00A0 DIRTBL EQU CONOUT+1 ; (WORD) CONTAINS TBLE TO STORE CHARS TO + 289 00A2 XSIZE EQU DIRTBL+2 ; (WORD) SCREEN WIDTH FOR TESTS + 290 00A4 RAND EQU XSIZE+2 ; (WORD) Random number offset + 291 00A6 CURWIN EQU RAND+2 ; (BYTE) WHICH WINDOW TO WRITE IN + 292 00A7 LENGTH EQU CURWIN+1 ; (WORD) CHAR POSITION ON THE SCREEN + 293 00A9 CHRCNT EQU LENGTH+2 ; (BYTE) CHAR POSITION IN [LBUFF] + 294 00AA SCRIPT EQU CHRCNT+1 ; (BYTE) SCRIPT ENABLE FLAG + 295 00AB LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER + 296 00AC IOCHAR EQU LINCNT+1 ; (BYTE) CHARACTER BUFFER + 297 00AD COLORP EQU IOCHAR+1 ; (WORD) Pointer to current background color + 298 00AF ZSP EQU COLORP+2 ; (WORD) Z Stack + 299 00B1 SCREENF EQU ZSP+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT + 300 00B2 TABLEF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT + 301 00B3 VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH + 302 00B6 DBUFF EQU VOCEND+3 ; (WORD) RAM PG TO ACCESS (LSB = 0) + 303 00B8 DSKBNK EQU DBUFF+2 ; (BYTE) MAIN/AUX bank + 304 00B9 ALLFLG EQU DSKBNK+1 ; (BYTE) IF =1 ALL FCN KEYS (>127) ARE TCHARS + 305 00BA UNDFLG EQU ALLFLG+1 ; (BYTE) Underlining flag + 306 00BB INVFLG EQU UNDFLG+1 ; (BYTE) Inverse flag + 307 00BC MEMPAGE EQU INVFLG+1 ; (BYTE) Save spot for XPAGING stuff + 308 00BD CPY_COUNT EQU MEMPAGE+1 ; (BYTE) Number of bytes for copy line + 309 00BE TBLHEIGHT EQU CPY_COUNT+1 ;(BYTE) Number of lines in printing table + 310 00BF TBLWIDTH EQU TBLHEIGHT+1 ;(BYTE) Number of bytes per line + 311 00C0 TBLCNT EQU TBLWIDTH+1 ;(BYTE) Counter for table printing + 312 00C1 FONTFLG EQU TBLCNT+1 ;(BYTE) Which font (!=0 is width) + 313 00C2 TBLPUR EQU FONTFLG+1 ;(BYTE) first pure table page + 314 00C3 FUNPRE EQU TBLPUR+1 ;(BYTE) first preloaded function page + 315 00C4 FUNPUR EQU FUNPRE+1 ;(BYTE) first pure function page + 316 00C5 FUNPGE EQU FUNPUR+1 ;(BYTE) -number to get function preload page + 317 00C6 DELAY_COUNTER EQU FUNPGE+1 ;(BYTE) counter for delay loop + 318 ; + 319 ; some char-to-screen variables + 320 ; + Tue Jun 13 1989 11:42 Page 6 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ZERO PAGE VARIABLES ---" + + 321 00C7 CHAR_D1 EQU DELAY_COUNTER+1 ; (BYTE) character data, part 1 + 322 00C8 CHAR_D2 EQU CHAR_D1+1 ; (BYTE) char data, part 2 + 323 00C9 CW EQU CHAR_D2+1 ; (BYTE) width of the character + 324 00CA CLKCTR EQU CW+1 ; (BYTE) counter for mouse clicking + 325 00CB MSX EQU CLKCTR+1 ; (BYTE) mouse cursor X + 326 00CC MSY EQU MSX+1 ; (BYTE) mouse cursor Y + 327 00CD CURRENT EQU MSY+1 ; (BYTE) current paging bufer + 328 ;CURSOR_OFF EQU CURRENT+1 ; (BYTE) ==1 if "don't show the blinking cursor" + 329 00CE MSTBL EQU CURRENT+1 ; (ADDRESS) pointer to extension table + 330 00D1 LASTZP EQU MSTBL+3 ; just checking + 331 ; + 332 ; these routines are in non-swapped memory + 333 ; + 334 00D1 ZERO_FB EQU LASTZP ; put fetch byte routine in at end of ZP + 335 00DC ZERO_ZF EQU ZERO_FB+11 ; and ZPCPNT fetch after that + 336 00E5 ZERO_MF EQU ZERO_ZF+9 ; and MPCPNT fetch after that + 337 00EE SAVE_DATA EQU ZERO_MF+9 ; copy data from DBUFF to IOBUFF routine + 338 ; + 339 ; and just to check the end + 340 ; + 341 00FF ZEE_END EQU SAVE_DATA+17 ; should be == 100 + 342 + 343 0000 END + 344 + 345 0000 INCLUDE PRODOS.EQU + 346 0000 STTL "--- ProDOS EQUATES ---" + 347 PAGE + Tue Jun 13 1989 11:42 Page 7 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ProDOS EQUATES ---" + + 348 + 349 ; + 350 ; some parameter structures + 351 ; + 352 0000 OPEN_PARM EQU 0 + 353 0000 OP_PCOUNT EQU OPEN_PARM ; must be 3 for open + 354 0001 OP_PATHNAME EQU OP_PCOUNT+1 ; address of pathname + 355 0003 OP_FILEBUFF EQU OP_PATHNAME+2 ; address of file data buffer + 356 0005 OP_REFNUM EQU OP_FILEBUFF+2 ; file reference number + 357 0006 OPEN_PSIZE EQU OP_REFNUM+1 ; size of parameter buffer + 358 + 359 0000 READ_PARM EQU 0 ; to read things + 360 0000 RD_PCOUNT EQU READ_PARM ; param count (=4) + 361 0001 RD_REFNUM EQU RD_PCOUNT+1 ; ref num of file + 362 0002 RD_BUFFER EQU RD_REFNUM+1 ; where to + 363 0004 RD_BUFFLEN EQU RD_BUFFER+2 ; length of buffer + 364 0006 RD_LENGTH EQU RD_BUFFLEN+2 ; actual length of read + 365 0008 READ_PSIZE EQU RD_LENGTH+2 ; length of parm block + 366 + 367 0000 CLOSE_PARM EQU 0 ; for closing file + 368 0000 CL_PCOUNT EQU CLOSE_PARM ; paramter count (=1) + 369 0001 CL_REFNUM EQU CL_PCOUNT+1 ; refnum of file to be closed + 370 0002 CLOSE_PSIZE EQU CL_REFNUM+1 ; this is the size, thank you + 371 + 372 0000 WRITE_PARM EQU 0 ; to write things + 373 0000 WR_PCOUNT EQU WRITE_PARM ; parm count (= 4) + 374 0001 WR_REFNUM EQU WR_PCOUNT+1 ; file refnum + 375 0002 WR_BUFFER EQU WR_REFNUM+1 ; data buffer address + 376 0004 WR_BUFFLEN EQU WR_BUFFER+2 ; data buffer length + 377 0006 WR_LENGTH EQU WR_BUFFLEN+2 ; actual length written + 378 0008 WRITE_PSIZE EQU WR_LENGTH+2 ; length of parm block + 379 + 380 0000 SETMARK_PARM EQU 0 + 381 0000 SM_PCOUNT EQU SETMARK_PARM ; parm count (=2) + 382 0001 SM_REFNUM EQU SM_PCOUNT+1 ; file refnum + 383 0002 SM_FPOS EQU SM_REFNUM+1 ; 3 byte file pos + 384 0005 SETMARK_PSIZE EQU SM_FPOS+3 ; length of parm block + 385 + 386 0000 SETPREFIX_PARM EQU 0 + 387 0000 SP_PCOUNT EQU SETPREFIX_PARM ; parm count (=1) + 388 0001 SP_PATHNAME EQU SP_PCOUNT+1 ; pointer to path name + 389 0003 SETPREFIX_PSIZE EQU SP_PATHNAME+2 ; length of block + 390 + 391 0000 SETEOF_PARM EQU 0 + 392 0000 SE_PCOUNT EQU SETEOF_PARM ; parm count (=2) + 393 0001 SE_REFNUM EQU SE_PCOUNT+1 ; reference number + 394 0002 SE_NEWEOF EQU SE_REFNUM+1 ; new EOF position + 395 0005 SETEOF_PSIZE EQU SE_NEWEOF+3 ; length of parm block + 396 + 397 0000 END + 398 + 399 0000 INCLUDE APPLE.EQU + 400 0000 STTL "--- APPLE ][ HARDWARE STUFF ---" + 401 PAGE + Tue Jun 13 1989 11:42 Page 8 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 402 ; ------------------- + 403 ; APPLE II MEMORY MAP + 404 ; ------------------- + 405 0001 AUX EQU 1 ; offset to Auxillary mem switches + 406 0000 MAIN EQU 0 ; for main memory switches + 407 + 408 ; + 409 ; some hardware spots + 410 ; + 411 2000 SCREEN EQU $2000 ; START OF Double HiRes SCREEN RAM + 412 + 413 BF00 PRGLBL EQU $BF00 ; ProDOS Globals page in main mem + 414 BF58 PR_BITMAP EQU $BF58 ; ProDOS system bitmap + 415 BFFF KVERSION EQU $BFFF ; ProDOS version (== $FF if InfoDOS) + 416 00FF INFODOS_ID EQU $FF + 417 + 418 C000 IOADDR EQU $C000 ; start of I/O registers + 419 D000 PROADR EQU $D000 ; start of ProDOS + 420 + 421 0200 LBUFF EQU $0200 ; LINE INPUT BUFFER + 422 0273 PIC1BUF EQU $0300-141 ; we can use line buffer for one picture buffer + 423 0280 SCRBUFF EQU LBUFF+$80 ; screen line buffer + 424 2000 BORG EQU $2000 ; ORIGIN OF .SYSTEM CODE + 425 ; + 426 ; some page 3 storage relocated stuff + 427 ; + 428 0300 PAGE3STUFF EQU $300 + 429 0300 MOUSER EQU PAGE3STUFF ; this is where mouse subroutine goes + 430 0312 COLORS EQU MOUSER+$12 + 431 0352 XPOSTBL EQU COLORS+$40 + 432 + 433 0400 SV_PCL EQU $400 ; for scrolling data + 434 0600 SV_PCH EQU $600 + 435 + 436 0800 IOBUFF EQU $0800 ; 1Kb DATA BUFFER BUFFER + 437 + 438 0C00 PAGING_MEM EQU IOBUFF+$400 ; Paging table stuff + 439 0C00 NEXTPNT EQU PAGING_MEM + 440 0C40 PREVPNT EQU NEXTPNT+$40 + 441 0C80 VPAGEH EQU PREVPNT+$40 + 442 0CC0 VPAGEL EQU VPAGEH+$40 + 443 0200 PAGELEN EQU $200 ; length of paged read + 444 + 445 0D00 ZSTKBL EQU PAGING_MEM+$100 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) + 446 0E00 ZSTKTL EQU ZSTKBL+$100 ; TOP, LO + 447 0F00 ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI + 448 1000 ZSTKTH EQU ZSTKBL+$300 ; TOP, HI + 449 ; + 450 ; now define some file i/o buffers and such + 451 ; + 452 1100 GAME1FIO EQU ZSTKBL+$400 ; Game file I/O buffer + 453 1500 GAME2FIO EQU GAME1FIO+$400 ; Second game file i/o buffer + 454 1900 SEGTBL EQU GAME2FIO+$400 ; segment table for multi disks + 455 1C74 PIC2BUF EQU SEGTBL+($400-140) ; picture buffer is 140 bytes long + 456 1D00 TCHARTBL EQU SEGTBL+$400 ; 208 bytes for (possible) terminating + 457 1D50 COPY_LINE EQU TCHARTBL+$50 ; copy line in screen memory + 458 1D7C CPY_MOD1_SRC equ COPY_LINE+$2C ; special self-modifying places + 459 1D7F CPY_MOD1_DST equ CPY_MOD1_SRC+3 + 460 1DA0 CPY_MOD2_SRC equ COPY_LINE+$50 + 461 1DA3 CPY_MOD2_DST equ CPY_MOD2_SRC+3 + 462 + 463 1DD0 DSKSEG EQU TCHARTBL+$D0 ; spot to stash pointers for disk segments + 464 1DD0 D1SEG EQU DSKSEG ; where in SEGTBL for Disk 1 + 465 1DD2 D2SEG EQU D1SEG+2 + 466 1DD4 D3SEG EQU D2SEG+2 + 467 1DD6 D4SEG EQU D3SEG+2 + 468 1DD8 D5SEG EQU D4SEG+2 + 469 1DDA D6SEG EQU D5SEG+2 + 470 1DDC D7SEG EQU D6SEG+2 + 471 1DDE D8SEG EQU D7SEG+2 + 472 1DE0 LOCAL_SV EQU TCHARTBL+$E0 ; to save locals before restore + 473 1E00 LOCALS EQU TCHARTBL+$100 ; LOCAL VARIABLE STORAGE (30 BYTES) + 474 1E20 BUFSAV EQU LOCALS+$20 ; TEMP SPACE FOR SAVE/RESTORE (80 BYTES) + 475 1F00 SCR_LINE EQU LOCALS+$100 ; place to build displayed line + 476 1F8C CHARSET EQU SCR_LINE+140 ; spot for charset to go + Tue Jun 13 1989 11:42 Page 9 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 477 ; + 478 ; now for some interpreter data + 479 ; + 480 4000 INTR_BEGIN EQU $4000 ; START OF Interpreter CODE in main + 481 5600 INTR_SIZE EQU (43*512) ; size of interpreter + 482 + 483 9600 ZBEGIN EQU (INTR_BEGIN+INTR_SIZE) ; start of Z code + 484 7F00 MMSIZE EQU PRGLBL-INTR_BEGIN ; free memory in main bank + 485 0029 Z1SIZE EQU >(PRGLBL-ZBEGIN) ; size of preload, part 1 + 486 ; + 487 ; this is in Bank 2, Main mem + 488 ; + 489 ; + 490 ; Picture directory goes in Bank 2, Aux mem + 491 ; + 492 D000 PIC_DIR EQU $D000 ; picture local directory + 493 DC00 GBL_DIR EQU $DC00 ; global directory + 494 ; + 495 ; some special markers if we are using InfoDOS + 496 ; + 497 0000 SP_BANK EQU MAIN + 498 D000 SP_START EQU $D000 ; start of special area + 499 0017 SP_SIZE EQU ((($FE->SP_START)*256)/512) ; how many pages + 500 ;SP_SIZE EQU (((>SCREEN->SP_START)*256)/512) ; how many pages + 501 + 502 0001 PB_BANK EQU AUX ; paging buffers in which bank + 503 0800 PBEGIN EQU $0800 ; start of paging buffers + 504 0018 NUMBUFS EQU >(SCREEN-PBEGIN) ; how many 256k paging buffers + 505 ;NUMBUFS EQU >($100-PBEGIN) ; how many 256k paging buffers + 506 + 507 0029 P2PAGE EQU >(PRGLBL-ZBEGIN) ; first page of zcode in aux bank + 508 4000 Z2BEGIN EQU $4000 ; start of part 2 in aux mem + 509 ; just after the dhires screen + 510 0040 Z2PAGE EQU >Z2BEGIN ; get me just the page address + 511 007F Z2SIZE EQU >(PRGLBL-Z2BEGIN) ; size of preload, part 2 + 512 00A8 P3PAGE EQU Z1SIZE+Z2SIZE ; first page in aux mem part 3 + 513 D000 Z3BEGIN EQU $D000 ; start of 3 part in aux mem + 514 00D0 Z3PAGE EQU >Z3BEGIN ; get me page number too + 515 002E Z3SIZE EQU <($FE-Z3PAGE) ; size of part 3, in pages + 516 + 517 ; + 518 ; other numba's + 519 ; + 520 00D6 PGBEGIN EQU (P3PAGE+Z3SIZE) ; first paged page + 521 00D6 PRESIZE EQU (Z1SIZE+Z2SIZE+Z3SIZE) ; size of preload, # pages + 522 2000 SCRSZE EQU INTR_BEGIN-SCREEN ; size of Double HiRes screen (8k, each bank) + 523 EE00 RAMDSK EQU (119*512) ; size of RAM disk in aux mem + 524 B500 RAMSAVE EQU $B500 ; save this much to cover HiRes screen in + 525 ; aux and the rest of the preload, up to + 526 ; PRGLBL ($bf00) + 527 3900 FREERAM EQU RAMDSK-RAMSAVE ; size of Free RAM after 'saving' + 528 ; special AUX memory + 529 2200 DSKSZE EQU (512*273) ; size of ProDOS data disk file + 530 + 531 ; --------- + 532 ; CONSTANTS + 533 ; --------- + 534 + 535 0002 IIeID EQU 2 ; Apple ][e Yzip + 536 0009 IIcID EQU 9 ; ][c Yzip + 537 000A IIgsID EQU 10 ; ][gs Yzip + 538 + 539 00FF P3BANK EQU $FF ; show upper aux mem + 540 0000 LO EQU 0 + 541 0001 HI EQU 1 + 542 0002 ABANK EQU 2 ; for address variables + 543 + 544 0000 OFF EQU 0 ; for toggling soft-switches + 545 0001 ON EQU 1 + 546 + 547 0003 RETRY_COUNT EQU 3 ; how many retries before message + 548 + 549 0009 TAB EQU $09 ; Tab char + 550 000B EOS EQU $0B ; End of Sentence + 551 000D EOL EQU $0D ; EOL CHAR + Tue Jun 13 1989 11:42 Page 10 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 552 000A LF EQU $0A ; LINE FEED + 553 0020 SPACE EQU $20 ; SPACE CHAR + 554 0008 BACKSPACE EQU $08 ; BACKSPACE CHAR + 555 001B ESCAPE EQU $1B ; ESCAPE Key + 556 003F VOLCHAR EQU '?' ; Key to hit for ONLINE command + 557 ; + 558 ; Screen Defs + 559 ; + 560 008C MAXWIDTH EQU 140 ; 560 / 4 = max "pixels" + 561 0230 REAL_MAXW EQU MAXWIDTH*4 + 562 00C0 MAXHEIGHT EQU 192 ; 192 screen lines + 563 0002 FONT_W EQU 2 ; font width (for game, anyway) + 564 0009 FONT_H EQU 9 ; font height + 565 0003 MFONT_W EQU 3 ; mono spaced font width, to game + 566 000C MONOFONT_W EQU MFONT_W*4 ; how wide the mono font really is + 567 + 568 0008 SPACE_WIDTH EQU 8 ; default space width + 569 0003 BLINK_RATE EQU 3 ; tenths of seconds between blinks + 570 + 571 001C OUTER_DELAY EQU $1C ; outside delay loop counter + 572 0003 INNER_DELAY EQU 3 ; inner delay loop + 573 + 574 0072 GS_OUTER_DELAY EQU $72 ; ][gs outside counter + 575 0002 GS_INNER_DELAY EQU 2 ; ][gs inside counter + 576 + 577 ; ---------------------- + 578 ; BOOT ZERO PAGE EQUATES + 579 ; ---------------------- + 580 + 581 0026 BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS + 582 002B BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT + 583 + 584 0280 START_NAME EQU $280 ; name upon boot is stored here + 585 ; ---------------- + 586 ; HARDWARE EQUATES + 587 ; ---------------- + 588 + 589 C000 KBD EQU $C000 ; KEY STROBE + 590 C000 STORE80 EQU $C000 ; video aux mem switch + 591 C002 RDBNK EQU $C002 ; READ MAIN MEMORY (+MAIN, +AUX) + 592 C004 WRTBNK EQU $C004 ; WRITE MAIN 48K OF MEMORY (+MAIN, +AUX) + 593 C008 ALTZP EQU $C008 ; R/W MAIN (C009 = AUX) >MEM + 594 C00C COL80SW EQU $C00C ; 80 Column switch + 595 C010 ANYKEY EQU $C010 ; ANY KEY DOWN FLAG + 596 C019 VERTBLNK EQU $C019 ; Vertical Blanking Flag + 597 C029 IIGSVID EQU $C029 ; GS MEGA ][ video register + 598 C030 SPKR EQU $C030 ; SPEAKER FLAG (MAKE A NOISE) + 599 C035 IIGSSHD EQU $C035 ; ][GS shadowing reg + 600 C050 TEXTSW EQU $C050 ; Graphics Switch + 601 C052 MIXEDSW EQU $C052 ; Mixed Text/Graphics + 602 C054 PAGE2SW EQU $C054 ; Page select + 603 C056 HIRESSW EQU $C056 ; Select HiRes + 604 C05E DHIRESW EQU $C05E ; Double HiRes switch (backwards: +0 on +1 off) + 605 C07E IOUDIS EQU $C07E ; Double HiRes Switch enabler (same backass way) + 606 C083 BNK2SET EQU $C083 ;READ/READ READ RAM WRITE RAM BANK 2 + 607 C08B BNK1SET EQU $C08B ;READ/READ READ RAM WRITE RAM BANK 1 + 608 C082 RDROM EQU $C082 ; READ READ ROM NO WRITE + 609 C088 RDBNK1 EQU $C088 ; READ ram, bank 1 + 610 C080 RDBNK2 EQU $C080 ; Read ram, bank 2 + 611 + 612 ; ----------------- + 613 ; MONITOR VARIABLES + 614 ; ----------------- + 615 + 616 0036 CSW EQU $36 ; CHARACTER OUTPUT VECTOR (for scripting) + 617 C061 APKEY1 EQU $C061 ; open apple key flag + 618 C062 APKEY2 EQU $C062 ; closed apple key flag + 619 + 620 0002 CURSW EQU 2 ; width of cursor + 621 0004 CURSH EQU 4 ; height of cursor + 622 ; ----------- + 623 ; MOUSE STUFF + 624 ; ----------- + 625 C412 MTABLE EQU $C412 ; Mouse ROM table + 626 0310 MSVECTOR EQU MOUSER+16 ; where vector is stored + Tue Jun 13 1989 11:42 Page 11 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 627 0312 MSMOVEF EQU MSVECTOR+2 ; Mouse moved flag + 628 0313 MSBTNF EQU MSMOVEF+1 ; Mouse button flag + 629 ; + 630 ; MOUSE screen holes + 631 ; + 632 0478 CLMPMINL EQU $478 ; lo part of clamping min + 633 0578 CLMPMINH EQU $578 ; hi part of " " + 634 04F8 CLMPMAXL EQU $4F8 ; lo part of clamping max + 635 05F8 CLMPMAXH EQU $5F8 ; hi part of " " + 636 0478 MOUSEXL EQU $478 ; lo part of mouse X + 637 0578 MOUSEXH EQU $578 ; hi part of mouse X + 638 04F8 MOUSEYL EQU $4F8 ; lo part of mouse Y + 639 05F8 MOUSEYH EQU $5F8 ; hi part of mouse Y + 640 0778 MOUSEST EQU $778 ; status byte + 641 ; + 642 ; some mouse constants + 643 ; + 644 0081 SGL_CLK EQU $81 ; single click char + 645 0082 DBL_CLK EQU $82 ; double click char + 646 0006 CLK_CNT EQU 6 ; counts between single and double click + 647 ; Subroutine offsets + 648 0000 SETM EQU 0 + 649 0001 SERVEM EQU 1 + 650 0002 READM EQU 2 + 651 0003 CLEARM EQU 3 + 652 0004 POSM EQU 4 + 653 0005 CLAMPM EQU 5 + 654 0006 HOMEM EQU 6 + 655 0007 INITM EQU 7 + 656 + 657 ; -------------- + 658 ; PRODOS GLOBALS + 659 ; -------------- + 660 BF90 PRODATE EQU $BF90 ; date and + 661 BF92 PROTIME EQU $BF92 ; time + 662 BF98 MACHID EQU $BF98 ; machine id + 663 + 664 ; ---------------- + 665 ; MONITOR ROUTINES + 666 ; ---------------- + 667 FB1E MPREAD EQU $FB1E ; Read for joystick control + 668 FC22 MBASCAL EQU $FC22 ; CALC LINE BASE ADDRESS + 669 FF3A MBELL EQU $FF3A ; MAKE A NOISE + 670 FFFC RESET_VECTOR EQU $FFFC ; force warm reboot + 671 FC9C MCLEOL EQU $FC9C ; CLEAR TO END OF LINE + 672 FC42 MCLEOS EQU $FC42 ; CLEAR TO END OF SCREEN + 673 FC58 MHOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR + 674 FDED MCOUT EQU $FDED ; CHAR OUTPUT + 675 FDF0 MCOUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN + 676 FD0C MRDKEY EQU $FD0C ; READ KEY + 677 FD6F MGETLN1 EQU $FD6F ; GET LINE + 678 FCA8 MWAIT EQU $FCA8 ; WASTE SO MUCH TIME + 679 ; + 680 ; Some /RAM spots + 681 ; + 682 BF26 RAMVEC EQU $BF26 ; /RAM drive vector + 683 077E OLDVEC EQU $77E ; spot to save the drive vector + 684 BF16 UNSVEC EQU $BF16 ; "Uninstalled Device" vector + 685 BF31 DEVCNT EQU $BF31 ; Device count + 686 BF32 DEVNUM EQU $BF32 ; Device list + 687 + 688 ; + 689 ; machine info spots + 690 ; + 691 FBB3 MACHID1 EQU $FBB3 ; first part + 692 FBC0 MACHID2 EQU $FBC0 ; second part + 693 FE1F MACHCHK EQU $FE1F ; differentiate between ][e and gs + 694 ; do sec, then jsr, and if still set, = ][e + 695 0000 END + 696 + 697 0000 INCLUDE MACROS.ASM + 698 0000 STTL "--- MACROS ---" + 699 PAGE + Tue Jun 13 1989 11:42 Page 12 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- MACROS ---" + + 700 + 701 ; + 702 ; MACROS for Apple ][ Yzip + 703 ; + 704 DLINE: .MACRO STRING,SLEN + 705 ldx #STRING ; get other part of string + 707 IFMA 2 ; check to see if length passed in + 708 ldy SLEN ; then just fetch it + 709 ELSE + 710 ldy #STRING|L ; get length of string + 711 ENDIF + 712 jsr DLINE ; print the string + 713 .MACEND + 714 ; + 715 ; ProDOS macros + 716 ; + 717 PRODOS: .MACRO CODE, PADDR + 718 jsr $BF00 ; ProDOS handler + 719 DB CODE ; ProDOS function code + 720 DW PADDR ; Function Parameter Block address + 721 .MACEND + 722 + 723 QUIT: .MACRO PBLOCK + 724 PRODOS $65, PBLOCK + 725 .MACEND + 726 + 727 READ_BLOCK: .MACRO PBLOCK + 728 PRODOS $80, PBLOCK + 729 .MACEND + 730 + 731 WRITE_BLOCK: .MACRO PBLOCK + 732 PRODOS $81, PBLOCK + 733 .MACEND + 734 + 735 GET_TIME: .MACRO PBLOCK + 736 PRODOS $82, PBLOCK + 737 .MACEND + 738 + 739 CREATE: .MACRO PBLOCK + 740 PRODOS $C0, PBLOCK + 741 .MACEND + 742 + 743 DESTROY: .MACRO PBLOCK + 744 PRODOS $C1, PBLOCK + 745 .MACEND + 746 + 747 RENAME: .MACRO PBLOCK + 748 PRODOS $C2, PBLOCK + 749 .MACEND + 750 + 751 SET_FILE_INFO: .MACRO PBLOCK + 752 PRODOS $C3, PBLOCK + 753 .MACEND + 754 + 755 GET_FILE_INFO: .MACRO PBLOCK + 756 PRODOS $C4, PBLOCK + 757 .MACEND + 758 + 759 ONLINE: .MACRO PBLOCK + 760 PRODOS $C5, PBLOCK + 761 .MACEND + 762 + 763 SET_PREFIX: .MACRO PBLOCK + 764 PRODOS $C6, PBLOCK + 765 .MACEND + 766 + 767 GET_PREFIX: .MACRO PBLOCK + 768 PRODOS $C7, PBLOCK + 769 .MACEND + 770 + 771 OPEN: .MACRO PBLOCK + 772 PRODOS $C8, PBLOCK + 773 .MACEND + 774 + Tue Jun 13 1989 11:42 Page 13 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- MACROS ---" + + 775 NEWLINE: .MACRO PBLOCK + 776 PRODOS $C9, PBLOCK + 777 .MACEND + 778 + 779 READ: .MACRO PBLOCK + 780 PRODOS $CA, PBLOCK + 781 .MACEND + 782 + 783 WRITE: .MACRO PBLOCK + 784 PRODOS $CB, PBLOCK + 785 .MACEND + 786 + 787 CLOSE: .MACRO PBLOCK + 788 PRODOS $CC, PBLOCK + 789 .MACEND + 790 + 791 FLUSH: .MACRO PBLOCK + 792 PRODOS $CD, PBLOCK + 793 .MACEND + 794 + 795 SET_MARK: .MACRO PBLOCK + 796 PRODOS $CE, PBLOCK + 797 .MACEND + 798 + 799 GET_MARK: .MACRO PBLOCK + 800 PRODOS $CF, PBLOCK + 801 .MACEND + 802 + 803 SET_EOF: .MACRO PBLOCK + 804 PRODOS $D0, PBLOCK + 805 .MACEND + 806 + 807 SET_BUF: .MACRO PBLOCK + 808 PRODOS $D1, PBLOCK + 809 .MACEND + 810 + 811 GET_BUF: .MACRO PBLOCK + 812 PRODOS $D2, PBLOCK + 813 .MACEND + 814 + 815 0000 END + 816 + 817 + 818 0000 TITLE "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + 819 0000 INCLUDE ZBEGIN.ASM + 820 0000 STTL "--- START OF APPLE ][ INTERPRETER ---" + 821 PAGE + Tue Jun 13 1989 11:42 Page 14 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- START OF APPLE ][ INTERPRETER ---" + + 822 + 823 4000 ORG INTR_BEGIN + 824 ; + 825 ; Set up for Double HiRes full screen graphics + 826 ; + 827 4000 AD 54 C0 lda PAGE2SW+OFF ; turn off page 2 + 828 4003 8D 50 C0 sta TEXTSW+OFF ; turn off text - turn on graphics + 829 4006 8D 57 C0 sta HIRESSW+ON ; turn on high resolution + 830 4009 8D 52 C0 sta MIXEDSW+OFF ; full screen graphics + 831 400C 8D 0D C0 sta COL80SW+ON ; turn on 80 column + 832 400F 8D 7E C0 sta IOUDIS+OFF ; turn ON (it too is backwards) Dhires switch + 833 4012 8D 5E C0 sta DHIRESW+OFF ; turn ON (it's backwards!) Dhires + 834 + 835 4015 8D 01 C0 sta STORE80+ON ; turn on aux page display ability + 836 4018 AD 83 C0 lda BNK2SET ; read/write RAM, bank 2 + 837 401B AD 83 C0 lda BNK2SET + 838 ; + 839 ; copy in progame from boot code + 840 ; + 841 401E A2 00 ldx #0 ; start at first letter + 842 4020 MVPRE: + 843 4020 BD 03 20 lda BORG+3,X ; get letter + 844 4023 F0 0C beq MVPREX ; all done + 845 4025 9D 68 46 sta GAME1NAME,X ; save letter + 846 4028 9D 7A 46 sta GAME2NAME,X ; save letter + 847 402B 9D 58 46 sta GAME,X ; save for asking about later + 848 402E E8 inx ; next letter + 849 402F D0 EF bne MVPRE ; do gen + 850 4031 MVPREX: + 851 4031 8E 57 46 stx GAMEL ; save length of game name + 852 4034 A9 2E lda #'.' ; get extension for names + 853 4036 9D 68 46 sta GAME1NAME,X ; save letter + 854 4039 9D 7A 46 sta GAME2NAME,X ; save letter + 855 403C E8 inx ; next letter + 856 403D A9 44 lda #'D' ; for data segments + 857 403F 9D 68 46 sta GAME1NAME,X ; save letter + 858 4042 9D 7A 46 sta GAME2NAME,X ; save letter + 859 4045 E8 inx ; points to number + 860 4046 E8 inx ; inclusive count for length + 861 4047 8E 67 46 stx GAME1NML ; save length of name + 862 404A 8E 79 46 stx GAME2NML ; save length of name + 863 + 864 404D A9 0F lda #VERSID ; put in version number + 865 404F 8D 1F 96 sta ZBEGIN+ZINTWD+1 + 866 + 867 4052 E6 AF inc ZSP+LO ; INIT Z-STACK POINTERS + 868 4054 EE A3 6C inc OLDZSP+LO ; TO "1" + 869 4057 E6 B1 inc SCREENF ; TURN DISPLAY ON + 870 4059 E6 AA inc SCRIPT ; enable scripting + 871 405B EE D1 6C inc CRLF_CHECK ; do CR functino check + 872 + 873 405E AD 75 6E lda WINTABLE+LO ; set WINDOW to point to window 0 + 874 4061 85 05 sta WINDOW+LO + 875 4063 AD 76 6E lda WINTABLE+HI + 876 4066 85 06 sta WINDOW+HI ; okay, it does + 877 + 878 4068 A5 63 lda ARG1+LO ; using mouse? + 879 406A F0 12 beq ZBEGIN1 ; nope + 880 406C 09 78 ora #$78 ; point to correct screen holes + 881 406E 8D 3F 50 sta MSFIX0+1 + 882 4071 8D 4A 50 sta MSFIX1+1 ; and modify code to point to correct spot + 883 4074 8D 4F 50 sta MSFIX2+1 + 884 4077 A5 63 lda ARG1+LO + 885 4079 09 F8 ora #$F8 ; and one more + 886 407B 8D 4F 50 sta MSFIX2+1 + 887 407E ZBEGIN1: + 888 407E A9 FF lda #$FF ; do a clear -1 to start off + 889 4080 85 63 sta ARG1+LO ; so arg 1 is this + 890 4082 20 B8 57 jsr ZCLR ; doing it + 891 + 892 4085 GET_PREFIX GPRE_PB ; get where we are to start + 893 4085 PRODOS $C7, GPRE_PB + 894 4085 20 00 BF jsr $BF00 ; ProDOS handler + 895 4088 C7 DB $C7 ; ProDOS function code + 896 4089 5446 DW GPRE_PB ; Function Parameter Block address + Tue Jun 13 1989 11:42 Page 15 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- START OF APPLE ][ INTERPRETER ---" + + 897 408B .MACEND + 898 408B .MACEND + 899 + 900 408B AD D3 1D lda D2SEG+HI ; start DSEGS at .D2 + 901 408E 85 1F sta DSEGS+HI + 902 4090 AD D2 1D lda D2SEG+LO + 903 4093 85 1E sta DSEGS+LO + 904 + 905 4095 A9 01 lda #1 ; open game file .D2 please + 906 4097 20 B6 49 jsr FETCH_FILE ; we did that + 907 409A A5 59 lda INFODOS ; are we on little dos? + 908 409C F0 03 beq ZBEGIN2 ; nope + 909 409E 20 E1 4B jsr GET_SPECIAL ; do special preloading if so + 910 40A1 ZBEGIN2: + 911 40A1 AD D5 1D lda D3SEG+HI ; this is cuz we be openin' .D3 + 912 40A4 85 1F sta DSEGS+HI + 913 40A6 AD D4 1D lda D3SEG+LO + 914 40A9 85 1E sta DSEGS+LO + 915 40AB A9 02 lda #2 ; and just for giggles, do the + 916 40AD 20 B6 49 jsr FETCH_FILE ; same for game file .D3 + 917 + 918 40B0 20 DC 90 jsr VLDZPC ; MAKE ZPC VALID + 919 40B3 20 51 92 jsr NEXTPC ; skip over # of locals + 920 + 921 ; ... AND FALL INTO MAIN LOOP + 922 + 923 40B6 END + 924 + 925 40B6 INCLUDE MAIN.ASM + 926 40B6 STTL "--- MAIN LOOP ---" + 927 PAGE + Tue Jun 13 1989 11:42 Page 16 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 928 + 929 9600 MD_ADDR EQU ZBEGIN + 930 0001 MDEBUG EQU 1 + 931 + 932 40B6 MLOOP: + 933 [01] IF 0 + 934 lda MD_ADDR ; get interesting address + 935 bne MLOOPx ; just fine, thank you + 936 brk ; then die + 937 MLOOPx: + 938 [00] ENDIF + 939 + 940 40B6 A9 00 lda #0 + 941 40B8 85 62 sta NARGS ; reset number of args + 942 40BA AD 54 C0 lda PAGE2SW+OFF ; just do this for the heck of it + 943 40BD AD 83 C0 lda BNK2SET + 944 40C0 AD 83 C0 lda BNK2SET + 945 40C3 8D 01 C0 sta STORE80+ON ; must always be on + 946 + 947 40C6 20 51 92 jsr NEXTPC ; get op code + 948 40C9 85 61 sta OPCODE ; SAVE IT HERE + 949 + 950 [01] IF MDEBUG + 951 ; + 952 ; special debugging code + 953 ; + 954 40CB AC FA 40 ldy SPCSV + 955 40CE A5 61 lda OPCODE + 956 40D0 99 00 41 sta SAVEOP,Y + 957 40D3 A5 82 lda ZPCH + 958 40D5 99 10 41 sta SAVEZH,Y + 959 40D8 A5 81 lda ZPCM + 960 40DA 99 20 41 sta SAVEZM,Y + 961 40DD A5 80 lda ZPCL + 962 40DF 99 30 41 sta SAVEZL,Y + 963 40E2 A5 85 lda ZPCBNK + 964 40E4 99 40 41 sta SAVEZB,Y + 965 40E7 A5 84 lda ZPCPNT+HI + 966 40E9 99 50 41 sta SAVEZP,Y + 967 40EC AC FA 40 ldy SPCSV + 968 40EF C8 iny + 969 40F0 98 tya + 970 40F1 29 0F and #$0F + 971 40F3 8D FA 40 sta SPCSV + 972 40F6 A5 61 lda OPCODE + 973 40F8 D0 66 bne MAINDB + 974 40FA 00 SPCSV: db 0 + 975 410A ORG $+15 + 976 0410 ORG $.SHR.4 + 977 4100 ORG $.SHL.4 + 978 4100 SAVEOP: ds 16 + 979 4110 SAVEZH: ds 16 + 980 4120 SAVEZM: ds 16 + 981 4130 SAVEZL: ds 16 + 982 4140 SAVEZB: ds 16 + 983 4150 SAVEZP: ds 16 + 984 4160 MAINDB: + 985 [00] ENDIF + 986 ; + 987 ; DECODE AN OPCODE + 988 ; + 989 4160 A8 tay ; set flags + 990 4161 30 03 bmi DC0 ; IF POSITIVE, + 991 4163 4C BD 42 jmp OP2 ; IT'S A 2-OP + 992 4166 C9 B0 DC0: cmp #$B0 + 993 4168 B0 03 bcs DC1 + 994 416A 4C 80 42 jmp OP1 ; OR MAYBE A 1-OP + 995 416D C9 C0 DC1: cmp #$C0 + 996 416F B0 03 bcs OPEXT + 997 4171 4C 5A 42 jmp OP0 ; PERHAPS A 0-OP + 998 + 999 ; -------------- + 1000 ; HANDLE AN X-OP + 1001 ; -------------- + 1002 + Tue Jun 13 1989 11:42 Page 17 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1003 4174 C9 EC OPEXT: CMP #236 ; XCALL? + 1004 4176 D0 03 BNE OPX5 + 1005 4178 4C 05 42 JMP OPXCLL ; YES, PROCESS SEPARATELY + 1006 417B C9 FA OPX5: CMP #250 ; IXCALL + 1007 417D D0 03 BNE OPX6 + 1008 417F 4C 05 42 JMP OPXCLL + 1009 4182 20 51 92 OPX6: JSR NEXTPC ; GRAB THE ARGUMENT ID BYTE + 1010 4185 85 73 STA ABYTE ; HOLD IT HERE + 1011 4187 A2 00 LDX #0 + 1012 4189 86 75 STX ADEX ; INIT ARGUMENT INDEX + 1013 418B F0 06 BEQ OPX1 ; JUMP TO TOP OF LOOP + 1014 418D A5 73 OPX0: LDA ABYTE ; GET ARG BYTE + 1015 418F 0A ASL A ; SHIFT NEXT 2 ARG BITS + 1016 4190 0A ASL A ; INTO BITS 7 & 6 + 1017 4191 85 73 STA ABYTE ; HOLD FOR LATER + 1018 4193 29 C0 OPX1: AND #%11000000 ; MASK OUT GARBAGE BITS + 1019 4195 D0 06 BNE OPX2 + 1020 4197 20 1B 43 JSR GETLNG ; 00 = LONG IMMEDIATE + 1021 419A 4C AE 41 JMP OPXNXT + 1022 419D C9 40 OPX2: CMP #%01000000 ; IS IT A SHORT IMMEDIATE? + 1023 419F D0 06 BNE OPX3 ; NO, KEEP GUESSING + 1024 41A1 20 17 43 JSR GETSHT ; 01 = SHORT IMMEDIATE + 1025 41A4 4C AE 41 JMP OPXNXT + 1026 41A7 C9 80 OPX3: CMP #%10000000 ; LAST TEST + 1027 41A9 D0 17 BNE OPX4 ; 11 = NO MORE ARGUMENTS + 1028 41AB 20 2F 43 JSR GETVAR ; 10 = VARIABLE + 1029 41AE A6 75 OPXNXT: LDX ADEX ; RETRIEVE ARGUMENT INDEX + 1030 41B0 A5 76 LDA VALUE+LO ; GRAB LSB OF VALUE + 1031 41B2 95 63 STA ARG1+LO,X ; STORE IN ARGUMENT TABLE + 1032 41B4 A5 77 LDA VALUE+HI ; GRAB MSB OF VALUE + 1033 41B6 95 64 STA ARG1+HI,X ; STORE THAT, TOO + 1034 41B8 E6 62 INC NARGS ; UPDATE ARGUMENT COUNTER + 1035 41BA E8 INX + 1036 41BB E8 INX + 1037 41BC 86 75 STX ADEX ; UPDATE INDEX + 1038 41BE E0 08 CPX #8 ; DONE 4 ARGUMENTS YET? + 1039 41C0 90 CB BCC OPX0 ; NO, GET SOME MORE + 1040 + 1041 ; ALL X-OP ARGUMENTS READY + 1042 + 1043 41C2 A5 61 OPX4: LDA OPCODE ; IS THIS + 1044 41C4 C9 E0 CMP #$E0 ; AN EXTENDED 2-OP? + 1045 41C6 B0 07 BCS DOXOP ; NO, IT'S A REAL X-OP + 1046 41C8 C9 C0 CMP #$C0 ; IS IT NEW OPCODE RANGE? + 1047 41CA 90 18 BCC ZEXTOP ; YES + 1048 41CC 4C F0 42 JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + 1049 + 1050 41CF 29 1F DOXOP: AND #%00011111 ; ISOLATE ID BITS + 1051 41D1 A8 TAY + 1052 41D2 B9 64 45 LDA OPTXL,Y + 1053 41D5 8D DF 41 STA GOX+1+LO + 1054 41D8 B9 44 45 LDA OPTXH,Y + 1055 41DB 8D E0 41 STA GOX+1+HI + 1056 41DE 20 FF FF GOX: JSR $FFFF ;DUMMY + 1057 41E1 4C B6 40 JMP MLOOP + 1058 + 1059 ; HANDLE EXTENDED OPCODE RANGE OPS + 1060 + 1061 41E4 C9 1D ZEXTOP: CMP #EXTLEN ; OUT OF RANGE? + 1062 41E6 B0 18 BCS BADEXT + 1063 41E8 A8 TAY ; OFFSET ALREADY CORRECT + 1064 41E9 B9 A1 45 LDA EXTOPL,Y + 1065 41EC 8D F6 41 STA GOE+1+LO + 1066 41EF B9 84 45 LDA EXTOPH,Y + 1067 41F2 8D F7 41 STA GOE+1+HI + 1068 41F5 20 FF FF GOE: JSR $FFFF ;DUMMY + 1069 41F8 4C B6 40 JMP MLOOP + 1070 + 1071 ; *** ERROR #1 -- ILLEGAL X-OP *** + 1072 + 1073 41FB A9 01 BADOPX: LDA #1 + 1074 41FD 4C F9 51 JMP ZERROR + 1075 + 1076 ; *** ERROR #16 -- ILLEGAL EXTENDED RANGE X-OP *** + 1077 + Tue Jun 13 1989 11:42 Page 18 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1078 4200 A9 10 BADEXT: LDA #16 + 1079 4202 4C F9 51 JMP ZERROR + 1080 + 1081 ; HANDLE AN XCALL OPCODE + 1082 + 1083 4205 20 51 92 OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + 1084 4208 85 73 STA ABYTE + 1085 420A 20 51 92 JSR NEXTPC + 1086 420D 85 74 STA BBYTE + 1087 420F A5 73 LDA ABYTE ; ONE TO START WITH + 1088 4211 A2 00 LDX #0 + 1089 4213 86 75 STX ADEX ; INIT ARGUMENT INDEX + 1090 4215 F0 06 BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP + 1091 4217 A5 73 XCALL1: LDA ABYTE ; GET ARG BYTE + 1092 4219 0A ASL A ; SHIFT NEXT 2 BITS + 1093 421A 0A ASL A ; INTO BITS 7 & 6 + 1094 421B 85 73 STA ABYTE ; HOLD FOR LATER + 1095 421D 29 C0 XCALL2: AND #%11000000 ; MASK OUT GARBAGE + 1096 421F D0 06 BNE XCALL3 + 1097 4221 20 1B 43 JSR GETLNG ; 00 = LONG IMMEDIATE + 1098 4224 4C 38 42 JMP XCNXT + 1099 4227 C9 40 XCALL3: CMP #%01000000 ; SHORT IMMED? + 1100 4229 D0 06 BNE XCALL4 ; NO, TRY ANOTHER + 1101 422B 20 17 43 JSR GETSHT ; 01 = SHORT IMMED. + 1102 422E 4C 38 42 JMP XCNXT + 1103 4231 C9 80 XCALL4: CMP #%10000000 ; LAST TEST + 1104 4233 D0 8D BNE OPX4 ; 11 = NO MORE ARGS + 1105 4235 20 2F 43 JSR GETVAR ; 10 = VARIABLE + 1106 4238 A6 75 XCNXT: LDX ADEX + 1107 423A A5 76 LDA VALUE+LO + 1108 423C 95 63 STA ARG1+LO,X + 1109 423E A5 77 LDA VALUE+HI + 1110 4240 95 64 STA ARG1+HI,X + 1111 4242 E6 62 INC NARGS + 1112 4244 E8 INX + 1113 4245 E8 INX + 1114 4246 86 75 STX ADEX + 1115 4248 E0 10 CPX #16 + 1116 424A D0 03 BNE XCALL5 + 1117 424C 4C C2 41 JMP OPX4 ; DONE, GO DO IT + 1118 424F E0 08 XCALL5: CPX #8 ; DONE 1ST MODE BYTE? + 1119 4251 D0 C4 BNE XCALL1 ; NOT QUITE YET + 1120 4253 A5 74 LDA BBYTE ; SET UP FOR NEXT + 1121 4255 85 73 STA ABYTE ; MODE BYTE + 1122 4257 4C 1D 42 JMP XCALL2 ; GO DO IT + 1123 + 1124 ; ------------- + 1125 ; HANDLE A 0-OP + 1126 ; ------------- + 1127 + 1128 425A C9 BE OP0: CMP #190 ; IS IT EXTOP OP + 1129 425C F0 1A BEQ EXTOP ; YES + 1130 425E 29 0F AND #%00001111 ; ISOLATE 0-OP ID BITS + 1131 4260 A8 TAY + 1132 4261 B9 D4 44 LDA OPT0L,Y + 1133 4264 8D 6E 42 STA GO0+1+LO + 1134 4267 B9 C4 44 LDA OPT0H,Y + 1135 426A 8D 6F 42 STA GO0+1+HI + 1136 426D 20 FF FF GO0: JSR $FFFF ;DUMMY + 1137 4270 4C B6 40 JMP MLOOP + 1138 + 1139 ; *** ERROR #2 -- ILLEGAL 0-OP *** + 1140 + 1141 4273 A9 02 BADOP0: LDA #2 + 1142 4275 4C F9 51 JMP ZERROR + 1143 + 1144 ; THIS OPCODE TELLS THAT NEXT OP IS PART OF THE + 1145 ; EXTENDED RANGE OF OPCODES, GET IT AND PROCESS IT + 1146 ; (THEY ARE ALL XOPS) + 1147 + 1148 4278 20 51 92 EXTOP: JSR NEXTPC ; GO GET EXTENDED RANGE OP + 1149 427B 85 61 STA OPCODE ; SAVE IT + 1150 427D 4C 74 41 JMP OPEXT ; AND HANDLE IT + 1151 + 1152 + Tue Jun 13 1989 11:42 Page 19 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1153 ; ------------- + 1154 ; HANDLE A 1-OP + 1155 ; ------------- + 1156 + 1157 4280 OP1: + 1158 4280 29 30 and #%00110000 ; ISOLATE ARGUMENT BITS + 1159 4282 D0 07 bne OP1A + 1160 4284 20 51 92 jsr NEXTPC ; get next byte + 1161 4287 A8 tay + 1162 4288 4C 8F 42 jmp OP1A1 + 1163 428B 29 20 OP1A: and #%00100000 ; TEST AGAIN + 1164 428D D0 0C bne OP1B + 1165 ; + 1166 ; 01 = SHORT IMMEDIATE + 1167 ; + 1168 428F 85 64 OP1A1: sta ARG1+HI + 1169 4291 20 51 92 jsr NEXTPC + 1170 4294 85 63 sta ARG1+LO + 1171 4296 E6 62 inc NARGS + 1172 4298 4C A1 42 jmp OP1EX1 + 1173 429B 20 2F 43 OP1B: JSR GETVAR ; 10 = VARIABLE + 1174 429E 20 0C 43 OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] + 1175 42A1 A5 61 OP1EX1: LDA OPCODE + 1176 42A3 29 0F AND #%00001111 ; ISOLATE 0-OP ID BITS + 1177 42A5 A8 TAY + 1178 42A6 B9 F4 44 LDA OPT1L,Y + 1179 42A9 8D B3 42 STA GO1+1+LO + 1180 42AC B9 E4 44 LDA OPT1H,Y + 1181 42AF 8D B4 42 STA GO1+1+HI + 1182 42B2 20 FF FF GO1: JSR $FFFF ;DUMMY + 1183 42B5 4C B6 40 JMP MLOOP + 1184 + 1185 ; *** ERROR #3 -- ILLEGAL 1-OP *** + 1186 + 1187 42B8 A9 03 BADOP1: LDA #3 + 1188 42BA 4C F9 51 JMP ZERROR + 1189 + 1190 + 1191 + 1192 ; ------------- + 1193 ; HANDLE A 2-OP + 1194 ; ------------- + 1195 + 1196 42BD 29 40 OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT + 1197 42BF D0 0C BNE OP2A + 1198 ; + 1199 ; 0 = SHORT IMMEDIATE + 1200 ; + 1201 42C1 85 64 sta ARG1+HI + 1202 42C3 20 51 92 jsr NEXTPC + 1203 42C6 85 63 sta ARG1+LO + 1204 42C8 E6 62 inc NARGS + 1205 42CA 4C D3 42 jmp OP2B1 + 1206 42CD 20 2F 43 OP2A: jsr GETVAR ; 1 = VARIABLE + 1207 42D0 20 0C 43 OP2B: jsr V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] + 1208 42D3 A5 61 OP2B1: lda OPCODE ; RESTORE OPCODE BYTE + 1209 42D5 29 20 and #%00100000 ; ISOLATE 2ND ARG BIT + 1210 42D7 D0 0A bne OP2C + 1211 42D9 85 66 sta ARG2+HI + 1212 42DB 20 51 92 jsr NEXTPC + 1213 42DE 85 65 sta ARG2+LO + 1214 42E0 4C EE 42 jmp OP2D1 + 1215 42E3 20 2F 43 OP2C: jsr GETVAR ; 1 = VARIABLE + 1216 42E6 A5 76 OP2D: lda VALUE+LO ; MOVE 2ND [VALUE] + 1217 42E8 85 65 sta ARG2+LO ; INTO [ARG2] + 1218 42EA A5 77 lda VALUE+HI + 1219 42EC 85 66 sta ARG2+HI + 1220 42EE E6 62 OP2D1: inc NARGS ; UPDATE ARGUMENT COUNT + 1221 + 1222 ; EXECUTE A 2-OP OR EXTENDED 2-OP + 1223 + 1224 42F0 A5 61 OP2EX: LDA OPCODE + 1225 42F2 29 1F AND #%00011111 ; ISOLATE 0-OP ID BITS + 1226 42F4 A8 TAY + 1227 42F5 B9 24 45 LDA OPT2L,Y + Tue Jun 13 1989 11:42 Page 20 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1228 42F8 8D 02 43 STA GO2+1+LO + 1229 42FB B9 04 45 LDA OPT2H,Y + 1230 42FE 8D 03 43 STA GO2+1+HI + 1231 4301 20 FF FF GO2: JSR $FFFF ;DUMMY + 1232 4304 4C B6 40 JMP MLOOP + 1233 + 1234 ; *** ERROR #4 -- ILLEGAL 2-OP **** + 1235 + 1236 4307 A9 04 BADOP2: LDA #4 + 1237 4309 4C F9 51 JMP ZERROR + 1238 + 1239 + 1240 + 1241 ; -------------------------------------- + 1242 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] + 1243 ; -------------------------------------- + 1244 + 1245 430C A5 76 V2A1: LDA VALUE+LO + 1246 430E 85 63 STA ARG1+LO + 1247 4310 A5 77 LDA VALUE+HI + 1248 4312 85 64 STA ARG1+HI + 1249 4314 E6 62 INC NARGS + 1250 4316 60 RTS + 1251 + 1252 4317 END + 1253 + 1254 4317 INCLUDE SUBS.ASM + 1255 4317 STTL "--- OPCODE SUPPORT SUBROUTINES ---" + 1256 PAGE + Tue Jun 13 1989 11:42 Page 21 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1257 + 1258 ; ----------------------- + 1259 ; FETCH A SHORT IMMEDIATE + 1260 ; ----------------------- + 1261 + 1262 4317 A9 00 GETSHT: LDA #0 ; MSB IS ZERO + 1263 4319 F0 03 BEQ GETV ; FETCH LSB FROM Z-CODE + 1264 + 1265 + 1266 ; ---------------------- + 1267 ; FETCH A LONG IMMEDIATE + 1268 ; ---------------------- + 1269 + 1270 431B 20 51 92 GETLNG: JSR NEXTPC ; GRAB MSB + 1271 431E 85 77 GETV: STA VALUE+HI + 1272 4320 20 51 92 JSR NEXTPC ; GRAB LSB + 1273 4323 85 76 STA VALUE+LO + 1274 4325 60 RTS + 1275 + 1276 + 1277 ; ---------------- + 1278 ; FETCH A VARIABLE + 1279 ; ---------------- + 1280 ; FROM INSIDE AN OPCODE (VARIABLE ID IN [A]) + 1281 + 1282 4326 AA VARGET: TAX ; IF NON-ZERO, + 1283 4327 D0 0B BNE GETVR1 ; ACCESS A VARIABLE + 1284 4329 20 56 43 JSR POPVAL ; ELSE PULL VAR OFF Z-STACK + 1285 432C 4C 87 43 JMP PSHVAL ; WITHOUT ALTERING STACK + 1286 + 1287 ; FROM THE MAIN LOOP (VARIABLE ID IN Z-CODE) + 1288 + 1289 432F 20 51 92 GETVAR: JSR NEXTPC ; GRAB VAR-TYPE BYTE + 1290 4332 F0 22 BEQ POPVAL ; VALUE IS ON Z-STACK + 1291 + 1292 ; IS VARIABLE LOCAL OR GLOBAL? + 1293 + 1294 4334 C9 10 GETVR1: CMP #$10 ; IF LOW = 16, + 1295 4336 B0 0D BCS GETVRG ; IT'S GLOBAL + 1296 + 1297 ; HANDLE A LOCAL VARIABLE + 1298 + 1299 4338 0A GETVRL: ASL A ; WORD INDEX + 1300 4339 AA TAX ; INTO THE [LOCALS] TABLE + 1301 433A BD FE 1D LDA LOCALS-2+LO,X ; GRAB LSB + 1302 433D 85 76 STA VALUE+LO + 1303 433F BD FF 1D LDA LOCALS-2+HI,X ; AND MSB + 1304 4342 85 77 STA VALUE+HI + 1305 4344 60 RTS + 1306 ; + 1307 ; HANDLE A GLOBAL VARIABLE + 1308 ; + 1309 4345 GETVRG: + 1310 4345 20 04 44 jsr GVCALC ; GET ADDRESS OF GLOBAL INTO [FPC] + 1311 4348 20 88 92 jsr FETCHB ; and get hi part + 1312 434B 85 77 sta VALUE+HI + 1313 434D 20 F0 8F jsr NEXTFPC ; and point to next part + 1314 4350 20 88 92 jsr FETCHB ; and go get it + 1315 4353 85 76 sta VALUE+LO ; SAVE IT + 1316 4355 60 rts ; AND WE'RE DONE + 1317 + 1318 ; ---------------------------------- + 1319 ; POP Z-STACK INTO [VALUE] AND [X/A] + 1320 ; ---------------------------------- + 1321 ; ZSTACK DOUBLED IN SIZE FOR EZIP + 1322 ; SO THIS RTN ALL NEW + 1323 + 1324 4356 A5 AF POPVAL: LDA ZSP+LO ; IF ZSP+LO IS 0 + 1325 4358 D0 02 BNE POP1 + 1326 435A 85 B0 STA ZSP+HI ; MUST DEC. HI (HI = 0 OR 1 ONLY) + 1327 435C C6 AF POP1: DEC ZSP+LO ; THEN DEC ZSP LO + 1328 435E D0 04 BNE POP2 + 1329 4360 05 B0 ORA ZSP+HI ; LO + HI BOTH 0? + 1330 4362 F0 1E BEQ UNDER ; UNDERFLOW IF ZERO! + 1331 4364 A4 AF POP2: LDY ZSP+LO + Tue Jun 13 1989 11:42 Page 22 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1332 4366 A5 B0 LDA ZSP+HI + 1333 4368 F0 0C BEQ POP3 ; BOTTOM HALF OF ZSTACK + 1334 436A B9 00 0E LDA ZSTKTL,Y ; GET VALUE FROM TOP HALF + 1335 436D 85 76 STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + 1336 436F AA TAX + 1337 4370 B9 00 10 LDA ZSTKTH,Y + 1338 4373 85 77 STA VALUE+HI + 1339 4375 60 RTS + 1340 + 1341 4376 B9 00 0D POP3: LDA ZSTKBL,Y ; GET VALUE FROM BOTTOM HALF + 1342 4379 85 76 STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + 1343 437B AA TAX + 1344 437C B9 00 0F LDA ZSTKBH,Y + 1345 437F 85 77 STA VALUE+HI + 1346 4381 60 RTS + 1347 + 1348 ; *** ERROR #5 -- Z-STACK UNDERFLOW *** + 1349 4382 A9 05 UNDER: LDA #5 + 1350 4384 4C F9 51 JMP ZERROR + 1351 + 1352 ; ----------------------- + 1353 ; PUSH [VALUE] TO Z-STACK + 1354 ; ----------------------- + 1355 + 1356 4387 A6 76 PSHVAL: LDX VALUE+LO + 1357 4389 A5 77 LDA VALUE+HI + 1358 + 1359 ; --------------------- + 1360 ; PUSH [X/A] TO Z-STACK + 1361 ; --------------------- + 1362 + 1363 438B 48 PUSHXA: PHA ; HOLD VALUE IN [A] A SEC. + 1364 438C A4 AF LDY ZSP+LO + 1365 438E A5 B0 LDA ZSP+HI + 1366 4390 F0 0B BEQ PSHBOT ; ON BOTTOM HALF OF STACK + 1367 4392 8A TXA + 1368 4393 99 00 0E STA ZSTKTL,Y ; PUSH VALUE ONTO TOP HALF OF STACK + 1369 4396 68 PLA + 1370 4397 99 00 10 STA ZSTKTH,Y + 1371 439A 4C A5 43 JMP PSHUPD ; NOW UPDATE POINTER + 1372 + 1373 439D 8A PSHBOT: TXA ; PLACE VALUE ON ZSTACK + 1374 439E 99 00 0D STA ZSTKBL,Y + 1375 43A1 68 PLA + 1376 43A2 99 00 0F STA ZSTKBH,Y + 1377 43A5 E6 AF PSHUPD: INC ZSP+LO ; UPDATE ZSTACK POINTER + 1378 43A7 D0 08 BNE PSHEX + 1379 43A9 A5 AF LDA ZSP+LO + 1380 43AB 05 B0 ORA ZSP+HI + 1381 43AD D0 03 BNE OVER ; OVERFLOW IF $200 + 1382 43AF E6 B0 INC ZSP+HI ; TO 1 + 1383 43B1 60 PSHEX: RTS + 1384 + 1385 ; *** ERROR #6 -- Z-STACK OVERFLOW *** + 1386 43B2 A9 06 OVER: LDA #6 + 1387 43B4 4C F9 51 JMP ZERROR + 1388 + 1389 + 1390 ; -------------- + 1391 ; RETURN A VALUE + 1392 ; -------------- + 1393 ; FROM WITHIN AN OPCODE (VARIABLE ID IN [A]) + 1394 + 1395 43B7 AA VARPUT: TAX ; IF ZERO, + 1396 43B8 D0 1C BNE PUTVR1 + 1397 + 1398 ; FLUSH TOP WORD OFF STACK + 1399 ; AND REPLACE WITH [VALUE] + 1400 + 1401 43BA A5 AF LDA ZSP+LO ; IF ZSP+LO =0 + 1402 43BC D0 02 BNE VAR1 ; THEN HI =1 (GUARDED ELSEWHERE) + 1403 43BE 85 B0 STA ZSP+HI ; DECREMENT HI (ONLY 0 OR 1) + 1404 43C0 C6 AF VAR1: DEC ZSP+LO ; NOW DEC LOW BYTE + 1405 43C2 D0 C3 BNE PSHVAL + 1406 43C4 05 B0 ORA ZSP+HI + Tue Jun 13 1989 11:42 Page 23 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1407 43C6 F0 BA BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + 1408 43C8 D0 BD BNE PSHVAL + 1409 + 1410 ; RETURN A ZERO + 1411 43CA RET0: + 1412 43CA A9 00 lda #0 + 1413 43CC AA tax ; zero's all + 1414 ; + 1415 ; RETURN WORD IN [A], [X] (LO,HI) (EZIP EXPANDED TO A WORD) + 1416 ; + 1417 43CD PUTBYT: + 1418 43CD 85 76 STA VALUE+LO + 1419 43CF 86 77 STX VALUE+HI ; CLEAR MSB + 1420 ; + 1421 ; RETURN [VALUE] + 1422 ; + 1423 43D1 20 51 92 PUTVAL: JSR NEXTPC ; GET VARIABLE ID BYTE + 1424 43D4 F0 B1 BEQ PSHVAL ; [VALUE] GOES TO Z-STACK + 1425 ; + 1426 ; LOCAL OR GLOBAL VARIABLE? + 1427 ; + 1428 43D6 C9 10 PUTVR1: CMP #$10 ; IF LOW = 16, + 1429 43D8 B0 0D BCS PUTVLG ; IT'S GLOBAL + 1430 ; + 1431 ; PUT A LOCAL VARIABLE + 1432 ; + 1433 43DA 0A PUTVLL: ASL A ; WORD INDEX + 1434 43DB AA TAX ; INTO THE [LOCALS] TABLE + 1435 43DC A5 76 LDA VALUE+LO ; GRAB LSB + 1436 43DE 9D FE 1D STA LOCALS-2+LO,X ; SAVE IN LOCAL TABLE + 1437 43E1 A5 77 LDA VALUE+HI ; DO SAME TO + 1438 43E3 9D FF 1D STA LOCALS-2+HI,X ; MSB + 1439 43E6 60 RTS + 1440 ; + 1441 ; RETURN A GLOBAL VARIABLE + 1442 ; + 1443 43E7 PUTVLG: + 1444 43E7 20 04 44 JSR GVCALC ; put address in [FPC] + 1445 43EA A5 8E lda FPCBNK ; and move it to stash spot + 1446 43EC 85 91 sta SPCBNK + 1447 43EE A5 8D lda FPCH + 1448 43F0 85 90 sta SPCH + 1449 43F2 A5 8C lda FPCL + 1450 43F4 85 8F sta SPCL + 1451 43F6 A5 77 lda VALUE+HI ; GET MSB + 1452 43F8 20 67 92 jsr STASHB ; and save it + 1453 43FB 20 D0 8F jsr NEXTSPC ; point to next byte + 1454 43FE A5 76 lda VALUE+LO ; NOW GET LSB + 1455 4400 20 67 92 jsr STASHB ; and send it out + 1456 4403 60 rts + 1457 + 1458 ; ----------------------- + 1459 ; CALC GLOBAL WORD OFFSET + 1460 ; ----------------------- + 1461 ; ENTRY: VAR-I BYTE (16-255) IN [A] + 1462 ; EXIT: ABSOLUTE ADDRESS OF GLOBAL VAR IN [FPC] + 1463 4404 GVCALC: + 1464 4404 38 sec ; time for a subtract + 1465 4405 E9 10 sbc #$10 ; FORM A ZERO-ALIGNED INDEX + 1466 4407 A0 00 ldy #0 ; MAKE SURE MSB OF OFFSET AND [Y] + 1467 4409 84 79 sty I+HI ; ARE CLEARED + 1468 440B 0A asl A ; MULTIPLY OFFSET BY 2 + 1469 440C 26 79 rol I+HI ; TO WORD-ALIGN IT + 1470 440E 18 clc ; ADD OFFSET TO ADDR OF GLOBAL TABLE + 1471 440F 65 50 adc GLOBAL+LO ; TO FORM THE ABSOLUTE + 1472 4411 85 8C sta FPCL ; ADDRESS OF THE + 1473 4413 A5 79 lda I+HI ; DESIRED GLOBAL VARIABLE + 1474 4415 65 51 adc GLOBAL+HI ; STORE ADDRESS BACK IN [FPC] + 1475 4417 20 A9 8F jsr SETPC ; now get memory page and bank + 1476 441A 85 8D sta FPCH ; hi part + 1477 441C 84 8E sty FPCBNK ; and bank + 1478 441E WCEX: + 1479 441E 60 rts + 1480 + 1481 + Tue Jun 13 1989 11:42 Page 24 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1482 ; --------------- + 1483 ; PREDICATE FAILS + 1484 ; --------------- + 1485 + 1486 441F 20 51 92 PREDF: JSR NEXTPC ; GET 1ST BRANCH BYTE + 1487 4422 10 0C BPL PREDB ; DO BRANCH IF BIT 7 OFF + 1488 + 1489 + 1490 ; ----------------------- + 1491 ; IGNORE PREDICATE BRANCH + 1492 ; ----------------------- + 1493 ; ENTRY: 1ST BRANCH BYTE IN [A] + 1494 + 1495 4424 29 40 PREDNB: AND #%01000000 ; TEST BIT 6 + 1496 4426 D0 F6 BNE WCEX ; SHORT BRANCH IF SET + 1497 4428 4C 51 92 JMP NEXTPC ; ELSE SKIP OVER 2ND BRANCH BYTE + 1498 + 1499 + 1500 ; ------------------ + 1501 ; PREDICATE SUCCEEDS + 1502 ; ------------------ + 1503 + 1504 442B 20 51 92 PREDS: JSR NEXTPC ; GET 1ST BRANCH BYTE + 1505 442E 10 F4 BPL PREDNB ; DON'T BRANCH IF BIT 7 CLEAR + 1506 + 1507 + 1508 ; -------------------------- + 1509 ; PERFORM A PREDICATE BRANCH + 1510 ; -------------------------- + 1511 ; ENTRY: 1ST PRED BYTE IN [A] + 1512 + 1513 4430 AA PREDB: TAX ; SAVE HERE + 1514 4431 29 40 AND #%01000000 ; LONG OR SHORT BRANCH? + 1515 4433 F0 0B BEQ PREDLB ; LONG IF BIT 6 IS CLEAR + 1516 + 1517 ; HANDLE A SHORT BRANCH + 1518 + 1519 4435 8A TXA ; RESTORE PRED BYTE + 1520 4436 29 3F AND #%00111111 ; FORM SHORT OFFSET + 1521 4438 85 76 STA VALUE+LO ; USE AS LSB OF BRANCH OFFSET + 1522 443A A9 00 LDA #0 + 1523 443C 85 77 STA VALUE+HI ; MSB OF OFFSET IS ZERO + 1524 443E F0 17 BEQ PREDB7 ; DO THE BRANCH + 1525 + 1526 ; HANDLE A LONG BRANCH + 1527 + 1528 4440 8A PREDLB: TXA ; RESTORE 1ST PRED BYTE + 1529 4441 29 3F AND #%00111111 ; FORM MSB OF OFFSET + 1530 4443 AA TAX ; SAVE HERE FOR REFERENCE + 1531 4444 29 20 AND #%00100000 ; CHECK SIGN OF 14-BIT VALUE + 1532 4446 F0 04 BEQ DOB2 ; POSITIVE IF ZERO, SO USE [X] + 1533 4448 8A TXA ; ELSE RESTORE BYTE + 1534 4449 09 E0 ORA #%11100000 ; EXTEND THE SIGN BIT + 1535 444B AA TAX ; BACK HERE FOR STORAGE + 1536 444C 86 77 DOB2: STX VALUE+HI + 1537 444E 20 51 92 JSR NEXTPC ; FETCH LSB OF 14-BIT OFFSET + 1538 4451 85 76 STA VALUE+LO + 1539 + 1540 ; BRANCH TO Z-ADDRESS IN [VALUE] + 1541 + 1542 4453 A5 77 PREDB1: LDA VALUE+HI ; CHECK MSB OF OFFSET + 1543 4455 D0 0E BNE PREDB3 ; DO BRANCH IF NZ + 1544 4457 A5 76 PREDB7: LDA VALUE+LO ; IF LSB IS NON-ZERO, + 1545 4459 D0 03 BNE PREDB2 ; MAKE SURE IT ISN'T 1 + 1546 445B 4C 8F 79 JMP ZRFALS ; ELSE DO AN "RFALSE" + 1547 445E C9 01 PREDB2: CMP #1 ; IF OFFSET = 1 + 1548 4460 D0 03 BNE PREDB3 + 1549 4462 4C 84 79 JMP ZRTRUE ; DO AN "RTRUE" + 1550 + 1551 ; ENTRY POINT FOR "JUMP" + 1552 + 1553 4465 A5 76 PREDB3: LDA VALUE+LO ; SUBTRACT 2 FROM OFFSET + 1554 4467 38 SEC ; IN [VALUE] + 1555 4468 E9 02 SBC #2 + 1556 446A AA TAX ;SAVE LO BYTE + Tue Jun 13 1989 11:42 Page 25 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1557 446B A5 77 LDA VALUE+HI + 1558 446D E9 00 SBC #0 + 1559 446F 85 78 STA I+LO ;MSB OF OFFSET = LSB OF [I] + 1560 4471 A0 00 LDY #0 ; CLEAR THE MSB + 1561 4473 84 79 STY I+HI ; OF [I] + 1562 4475 0A ASL A ; EXTEND THE SIGN OF OFFSET + 1563 4476 26 79 ROL I+HI ; INTO MSB OF [I] + 1564 4478 0A ASL A + 1565 4479 26 79 ROL I+HI ; (EZIP) + 1566 447B 0A asl A + 1567 447C 26 79 rol I+HI ; (YZIP) ??!! + 1568 447E 8A TXA ; GET LSB OF OFFSET + 1569 447F 65 80 ADC ZPCL ; ADD LOW 8 BITS OF ZPC + 1570 4481 90 06 BCC PREDB5 ; IF OVERFLOWED, + 1571 4483 E6 78 INC I+LO ; UPDATE UPPER 9 BITS + 1572 4485 D0 02 BNE PREDB5 + 1573 4487 E6 79 INC I+HI + 1574 4489 85 80 PREDB5: STA ZPCL ; UPDATE ZPC + 1575 448B A5 78 LDA I+LO ; IF UPPER 9 BITS ARE ZERO, + 1576 448D 05 79 ORA I+HI ; NO NEED TO CHANGE PAGES + 1577 448F F0 12 BEQ PREDB6 + 1578 4491 A5 78 LDA I+LO ; ELSE CALC NEW UPPER BITS + 1579 4493 18 CLC + 1580 4494 65 81 ADC ZPCM + 1581 4496 85 81 STA ZPCM + 1582 4498 A5 79 LDA I+HI + 1583 449A 65 82 ADC ZPCH + 1584 449C 29 07 AND #%00000111 + 1585 449E 85 82 STA ZPCH + 1586 44A0 4C DC 90 JMP VLDZPC ;MAKE VALID + 1587 44A3 PREDB6: + 1588 + 1589 ; FALL THROUGH ... + 1590 + 1591 ; ---- + 1592 ; NOOP + 1593 ; ---- + 1594 + 1595 44A3 60 ZNOOP: RTS + 1596 + 1597 + 1598 ; ---------------------- + 1599 ; MOVE [ARG1] TO [VALUE] + 1600 ; ---------------------- + 1601 + 1602 44A4 A5 63 A12VAL: LDA ARG1+LO + 1603 44A6 85 76 STA VALUE+LO + 1604 44A8 A5 64 LDA ARG1+HI + 1605 44AA 85 77 STA VALUE+HI + 1606 44AC 60 RTS + 1607 + 1608 + 1609 ; ----------------------------------- + 1610 ; INDICATE STATUS LINE REFRESH NEEDED + 1611 ; ----------------------------------- + 1612 + 1613 44AD AD 11 96 REFRSH: LDA ZBEGIN+ZFLAGS+1 ; PICK UP LOW BYTE OF FLAG WORD + 1614 44B0 09 04 ORA #%00000100 ; SET BIT 2 + 1615 44B2 8D 11 96 STA ZBEGIN+ZFLAGS+1 ; AND PUT IT BACK + 1616 44B5 60 RTS + 1617 + 1618 + 1619 ;DECJ RETURNS C=0 WHEN J=$FFFF + 1620 + 1621 44B6 A5 7A DECJ: LDA J+LO + 1622 44B8 38 SEC + 1623 44B9 E9 01 SBC #1 + 1624 44BB 85 7A STA J+LO + 1625 44BD A5 7B LDA J+HI + 1626 44BF E9 00 SBC #0 + 1627 44C1 85 7B STA J+HI + 1628 44C3 60 RTS + 1629 + 1630 44C4 END + 1631 + Tue Jun 13 1989 11:42 Page 26 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1632 44C4 INCLUDE DISPATCH.ASM + 1633 PAGE + Tue Jun 13 1989 11:42 Page 27 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1634 44C4 STTL "--- OPCODE DISPATCH TABLES ---" + 1635 + 1636 + 1637 ; 0-OPS + 1638 + 1639 44C4 79 OPT0H: DB >ZRTRUE ;B0 + 1640 44C5 79 DB >ZRFALS ;B1 + 1641 44C6 79 DB >ZPRI ;B2 + 1642 44C7 79 DB >ZPRR ;B3 + 1643 44C8 44 DB >ZNOOP ;B4 + 1644 44C9 8F DB >OSAVE ;B5 + 1645 44CA 8F DB >OREST ;B6 + 1646 44CB 52 DB >ZSTART ;B7 + 1647 44CC 79 DB >ZRSTAK ;B8 + 1648 44CD 79 DB >ZCATCH ;B9 + 1649 44CE 52 DB >ZQUIT ;BA + 1650 44CF 54 DB >ZZCRLF ;BB + 1651 44D0 55 DB >ZUSL ;BC + 1652 44D1 5B DB >ZVER ;BD + 1653 44D2 41 DB >ZEXTOP ;BE + 1654 44D3 79 DB >ZORIG ;BF + 1655 + 1656 44D4 84 OPT0L: DB ZZERO ;80,90,A0 + 1676 44E5 79 DB >ZNEXT ;81 + 1677 44E6 79 DB >ZFIRST ;82 + 1678 44E7 7A DB >ZLOC ;83 + 1679 44E8 7A DB >ZPTSIZ ;84 + 1680 44E9 7A DB >ZINC ;85 + 1681 44EA 7A DB >ZDEC ;86 + 1682 44EB 7A DB >ZPRB ;87 + 1683 44EC 7F DB >ZCALL1 ;88 (EZIP) + 1684 44ED 7A DB >ZREMOV ;89 + 1685 44EE 7B DB >ZPRD ;8A + 1686 44EF 7B DB >ZRET ;8B + 1687 44F0 7B DB >ZJUMP ;8C + 1688 44F1 7B DB >ZPRINT ;8D + 1689 44F2 7C DB >ZVALUE ;8E + 1690 44F3 7F DB >ZICLL1 ;8F + 1691 + 1692 44F4 C4 OPT1L: DB BADOP2 ;00 (UNDEFINED) + 1712 4505 7F DB >ZEQUAL ;01 + 1713 4506 7C DB >ZLESS ;02 + 1714 4507 7C DB >ZGRTR ;03 + 1715 4508 7C DB >ZDLESS ;04 + 1716 4509 7C DB >ZIGRTR ;05 + 1717 450A 7C DB >ZIN ;06 + 1718 450B 7C DB >ZBTST ;07 + 1719 450C 7C DB >ZBOR ;08 + 1720 450D 7C DB >ZBAND ;09 + 1721 450E 7C DB >ZFSETP ;0A + 1722 450F 7C DB >ZFSET ;0B + 1723 4510 7C DB >ZFCLR ;0C + 1724 4511 7C DB >ZSET ;0D + 1725 4512 7C DB >ZMOVE ;0E + 1726 4513 7D DB >ZGET ;0F + 1727 4514 7D DB >ZGETB ;10 + 1728 4515 7D DB >ZGETP ;11 + 1729 4516 7D DB >ZGETPT ;12 + 1730 4517 7E DB >ZNEXTP ;13 + 1731 4518 7E DB >ZADD ;14 + 1732 4519 7E DB >ZSUB ;15 + 1733 451A 7E DB >ZMUL ;16 + 1734 451B 7E DB >ZDIV ;17 + 1735 451C 7E DB >ZMOD ;18 + 1736 451D 7F DB >ZCALL2 ;19 (EZIP) + 1737 451E 7F DB >ZICLL2 ;1A + 1738 451F 4E DB >ZCOLOR ;1B + 1739 4520 7F DB >ZTHROW ;1C + 1740 4521 43 DB >BADOP2 ;1D + 1741 4522 43 DB >BADOP2 ;1E + 1742 4523 43 DB >BADOP2 ;1F + 1743 + 1744 4524 07 OPT2L: DB ZCALL ;E0 + 1780 4545 80 DB >ZPUT ;E1 + 1781 4546 80 DB >ZPUTB ;E2 + 1782 4547 81 DB >ZPUTP ;E3 + 1783 4548 85 DB >ZREAD ;E4 + Tue Jun 13 1989 11:42 Page 29 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE DISPATCH TABLES ---" + + 1784 4549 81 DB >ZPRC ;E5 + 1785 454A 81 DB >ZPRN ;E6 + 1786 454B 81 DB >ZRAND ;E7 + 1787 454C 82 DB >ZPUSH ;E8 + 1788 454D 82 DB >ZPOP ;E9 + 1789 454E 4D DB >ZSPLIT ;EA + 1790 454F 6E DB >ZSCRN ;EB + 1791 + 1792 ; (EZIPS FROM HERE ON) + 1793 4550 7F DB >ZXCALL ;EC + 1794 4551 57 DB >ZCLR ;ED + 1795 4552 57 DB >ZERASE ;EE + 1796 4553 56 DB >ZCURST ;EF + 1797 4554 57 DB >ZCURGT ;F0 + 1798 4555 70 DB >ZLIGHT ;F1 + 1799 4556 55 DB >ZBUFOUT ;F2 + 1800 4557 55 DB >ZDIRT ;F3 + 1801 4558 57 DB >ZDIRIN ;F4 (NOT IMPLEMENTED) + 1802 4559 4E DB >ZSOUND ;F5 + 1803 455A 5A DB >ZINPUT ;F6 + 1804 455B 82 DB >ZINTBL ;F7 + 1805 455C 83 DB >ZBCOM ;F8 + 1806 455D 7F DB >ZICALL ;F9 + 1807 455E 7F DB >ZIXCLL ;FA + 1808 455F 86 DB >ZLEX ;FB + 1809 4560 86 DB >ZWSTR ;FC + 1810 4561 83 DB >ZCOPYT ;FD + 1811 4562 58 DB >ZPRNTT ;FE + 1812 4563 84 DB >ZASSND ;FF + 1813 + 1814 4564 E0 OPTXL: DB ZSAVE ;100 + 1851 4585 8E DB >ZREST ;101 + 1852 4586 84 DB >ZSHIFT ;102 + 1853 4587 84 DB >ZASHFT ;103 + 1854 4588 58 DB >ZFONT ;104 + 1855 4589 74 DB >ZDISPL ;105 + 1856 458A 78 DB >ZPICNF ;106 + 1857 458B 79 DB >ZDCLR ;107 + 1858 458C 4E DB >ZMARG ;108 + Tue Jun 13 1989 11:42 Page 30 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE DISPATCH TABLES ---" + + 1859 458D 8F DB >ZISAVE ;109 + 1860 458E 8F DB >ZIREST ;10A + 1861 458F 42 DB >BADEXT ;10B - NOT USED + 1862 4590 42 DB >BADEXT ;10C - NOT USED + 1863 4591 42 DB >BADEXT ;10D - NOT USED + 1864 4592 42 DB >BADEXT ;10E - NOT USED + 1865 4593 42 DB >BADEXT ;10F - NOT USED + 1866 4594 6F DB >ZWINPOS ;110 + 1867 4595 6F DB >ZWINSIZE ;111 + 1868 4596 70 DB >ZWINATTR ;112 + 1869 4597 70 DB >ZWINGET ;113 + 1870 4598 71 DB >ZSCROLL ;114 + 1871 4599 84 DB >ZFSTACK ;115 + 1872 459A 85 DB >ZMINFO ;116 + 1873 459B 85 DB >ZMLIMIT ;117 + 1874 459C 84 DB >ZXPUSH ;118 + 1875 459D 71 DB >ZWINPUT ;119 + 1876 459E 58 DB >ZPRINTF ;11A + 1877 459F 85 DB >ZMENU ;11B + 1878 45A0 79 DB >ZPICSET ;11c + 1879 + 1880 001D EXTLEN EQU $-EXTOPH + 1881 + 1882 45A1 21 EXTOPL: DB IOBUFF ; first 256 byte page + 2065 46EA 20 4D 48 jsr COPY_DATA ; and copy from IOBUFF to DBUFF + 2066 46ED E6 B7 inc DBUFF+HI ; point to next one + 2067 46EF A9 09 lda #>IOBUFF+1 ; next 256 byte page + 2068 46F1 4C 4D 48 jmp COPY_DATA ; and copy it over + 2069 46F4 GDBAD: + 2070 46F4 4C 64 47 jmp DISK_FATAL ; just die then + 2071 46F7 RETRY: + 2072 [01] IF CHECKSUM + 2073 DLINE RETRYING ; show me the way to go home + 2074 [00] ENDIF + 2075 + 2076 46F7 C6 16 dec RETRIES ; count this try + 2077 46F9 30 F9 bmi GDBAD ; it's dead jim + 2078 46FB F0 2F beq RETRY0 ; ask for reset + 2079 46FD C9 01 cmp #1 ; down to last time? + 2080 46FF D0 61 bne RETRYX ; just try again + 2081 4701 AD CE 45 lda PSEEK+SM_FPOS+0 + 2082 4704 48 pha + 2083 4705 AD CF 45 lda PSEEK+SM_FPOS+1 + 2084 4708 48 pha + 2085 4709 AD D0 45 lda PSEEK+SM_FPOS+2 + 2086 470C 48 pha + 2087 470D A9 00 lda #0 ; seek to zero + 2088 470F 8D CE 45 sta PSEEK+SM_FPOS+0 ; save here for now + 2089 4712 8D CF 45 sta PSEEK+SM_FPOS+1 ; save here for now + 2090 4715 8D D0 45 sta PSEEK+SM_FPOS+2 ; save here for now + 2091 4718 SET_MARK PSEEK ; move to the block + 2092 4718 PRODOS $CE, PSEEK + 2093 4718 20 00 BF jsr $BF00 ; ProDOS handler + 2094 471B CE DB $CE ; ProDOS function code + 2095 471C CC45 DW PSEEK ; Function Parameter Block address + 2096 471E .MACEND + 2097 471E .MACEND + 2098 471E 68 pla + 2099 471F 8D D0 45 sta PSEEK+SM_FPOS+2 + 2100 4722 68 pla + 2101 4723 8D CF 45 sta PSEEK+SM_FPOS+1 + 2102 4726 68 pla + 2103 4727 8D CE 45 sta PSEEK+SM_FPOS+0 + 2104 472A 90 36 bcc RETRYX ; all done + 2105 472C RETRY0: + 2106 472C 48 pha ; save disk error + 2107 472D 20 99 4C jsr SWAP2INFOW ; go to window zero + 2108 4730 DLINE RESEAT_MSG1 ; ask to move the disk around + 2109 4730 A2 1D ldx #RESEAT_MSG1 ; get other part of string + 2111 [01] IFMA 2 ; check to see if length passed in + 2112 ldy ; then just fetch it + 2113 [01] ELSE + 2114 4734 A0 1F ldy #RESEAT_MSG1L ; get length of string + 2115 [00] ENDIF + 2116 4736 20 5B 4C jsr DLINE ; print the string + 2117 4739 .MACEND + 2118 4739 AD BF 45 lda GMREF ; get ref num + 2119 473C CD 89 46 cmp GAME2REF ; game2? + 2120 473F D0 08 bne RETRY1 ; nope + 2121 4741 AC 79 46 ldy GAME2NML ; get length + Tue Jun 13 1989 11:42 Page 34 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2122 4744 B9 79 46 lda GAME2NM,Y ; and side # + 2123 4747 D0 06 bne RETRY2 ; and continue + 2124 4749 RETRY1: + 2125 4749 AC 67 46 ldy GAME1NML ; get length + 2126 474C B9 67 46 lda GAME1NM,Y ; and side # + 2127 474F RETRY2: + 2128 474F 20 A9 5D jsr CHAR ; send char out there + 2129 4752 DLINE RESEAT_MSG2 ; and finish statement + 2130 4752 A2 3C ldx #RESEAT_MSG2 ; get other part of string + 2132 [01] IFMA 2 ; check to see if length passed in + 2133 ldy ; then just fetch it + 2134 [01] ELSE + 2135 4756 A0 18 ldy #RESEAT_MSG2L ; get length of string + 2136 [00] ENDIF + 2137 4758 20 5B 4C jsr DLINE ; print the string + 2138 475B .MACEND + 2139 475B 68 pla ; get disk error back + 2140 475C 20 7A 47 jsr DISK_ERR ; tell the error + 2141 475F 20 B9 4C jsr SWAPBACK ; back to current window + 2142 4762 RETRYX: + 2143 4762 18 clc ; show goodness + 2144 4763 60 rts ; and done + 2145 ; + 2146 ; this is the fatal error spot + 2147 ; + 2148 4764 DISK_FATAL: + 2149 4764 20 7A 47 jsr DISK_ERR ; print out problem + 2150 4767 DRIVE_ERR: + 2151 4767 A9 0E lda #14 + 2152 4769 4C F9 51 jmp ZERROR ; DRIVE ACCESS ERROR + 2153 ; + 2154 ; this routine prints out the string associated with the error and + 2155 ; returns with the carry set, like most routines do when there is + 2156 ; an error. The error should be in [A]. + 2157 ; + 2158 476C 50 72 6F 44 4F UNK_DISK: db "ProDOS error $" + 4771 53 20 65 72 72 + 4776 6F 72 20 24 + 2159 000E UNK_DISKL EQU $-UNK_DISK + 2160 + 2161 477A DISK_ERR: + 2162 477A 48 pha ; save [A] + 2163 477B 20 99 4C jsr SWAP2INFOW ; point to information window + 2164 477E 68 pla ; get it back + 2165 + 2166 477F A2 1B ldx #ELISTL ; scan the error table + 2167 4781 DSKE: + 2168 4781 DD 97 6D cmp ELIST,X ; is it this one + 2169 4784 F0 16 beq DSKE1 ; ayyup + 2170 4786 CA dex ; now skip the address + 2171 4787 CA dex ; of the description + 2172 4788 CA dex ; point to next error number + 2173 4789 10 F6 bpl DSKE ; jump to start + 2174 ; + 2175 ; if we are here print out unknown error and it's value + 2176 ; + 2177 478B 48 pha ; save [A] + 2178 478C DLINE UNK_DISK ; show error + 2179 478C A2 6C ldx #UNK_DISK ; get other part of string + 2181 [01] IFMA 2 ; check to see if length passed in + 2182 ldy ; then just fetch it + 2183 [01] ELSE + 2184 4790 A0 0E ldy #UNK_DISKL ; get length of string + 2185 [00] ENDIF + 2186 4792 20 5B 4C jsr DLINE ; print the string + 2187 4795 .MACEND + 2188 4795 68 pla ; get [A] + 2189 4796 20 C3 47 jsr HEXNUM ; print [A] + 2190 4799 4C BB 47 jmp DSK_EXIT ; done + 2191 479C DSKE1: + 2192 479C E8 inx ; point to string address + 2193 479D BD 97 6D lda ELIST,X ; get lo part + 2194 47A0 85 7E sta L+LO ; save it + Tue Jun 13 1989 11:42 Page 35 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2195 47A2 E8 inx ; point to hi part + 2196 47A3 BD 97 6D lda ELIST,X ; get hi part + 2197 47A6 AA tax ; save here + 2198 47A7 85 7F sta L+HI ; and here + 2199 47A9 A0 00 ldy #0 ; for offset + 2200 47AB B1 7E lda (L),Y ; get length of string + 2201 47AD A8 tay ; save in y + 2202 47AE E6 7E inc L+LO ; point past length + 2203 47B0 A5 7E lda L+LO ; get it + 2204 47B2 D0 01 bne DSKPR ; for printing + 2205 47B4 E8 inx ; wrapped + 2206 47B5 DSKPR: + 2207 47B5 8A txa ; hi part in a + 2208 47B6 A6 7E ldx L+LO ; lo part in X + 2209 47B8 20 5B 4C jsr DLINE ; print out message + 2210 47BB DSK_EXIT: + 2211 47BB 20 0D 8D jsr GETRET ; wait for RETURN + 2212 47BE 20 B9 4C jsr SWAPBACK ; all done + 2213 47C1 38 sec ; show badness again + 2214 47C2 60 rts ; and be done with it + 2215 ; + 2216 ; HEXNUM - print out the HEX value of [A] at the current cursor + 2217 ; location + 2218 ; + 2219 47C3 HEXNUM: + 2220 47C3 48 pha + 2221 47C4 4A lsr A + 2222 47C5 4A lsr A + 2223 47C6 4A lsr A + 2224 47C7 4A lsr A + 2225 47C8 20 CC 47 jsr NIB1 + 2226 47CB 68 pla + 2227 47CC NIB1: + 2228 47CC 29 0F and #%00001111 + 2229 47CE A8 tay + 2230 47CF B9 D6 47 lda HCHARS,Y + 2231 47D2 20 A9 5D jsr CHAR ; print it out + 2232 47D5 60 rts + 2233 47D6 30 31 32 33 34 HCHARS: DB "0123456789ABCDEF" + 47DB 35 36 37 38 39 + 47E0 41 42 43 44 45 + 47E5 46 + 2234 + 2235 ; ---------------------- + 2236 ; WRITE [DBUFF] TO DISK + 2237 ; ---------------------- + 2238 ; ENTRY: File already open and positioned, ready to be written to + 2239 ; from page in (DBUFF). Writes out 512bytes, starting @ DBUFF. + 2240 ; EXIT: CARRY CLEAR IF OKAY, SET IF FAILED + 2241 + 2242 47E6 PUTDSK: + 2243 47E6 A6 B8 ldx DSKBNK ; get bank + 2244 47E8 A0 00 ldy #0 ; clear Y + 2245 47EA A9 08 lda #>IOBUFF ; first buffer + 2246 47EC 20 EE 00 jsr SAVE_DATA ; and copy from DBUFF to IOBUFF + 2247 + 2248 [01] IF CHECKSUM == 1 + 2249 lda #>IOBUFF + 2250 jsr CKS_BLOCK + 2251 [00] ENDIF + 2252 + 2253 47EF 20 24 48 jsr NEXT_DBUFF ; point to next buffer + 2254 47F2 A6 B8 ldx DSKBNK ; go get new DSKBNK + 2255 47F4 A0 00 ldy #0 ; clear Y again + 2256 47F6 A9 09 lda #>IOBUFF+1 ; top part + 2257 47F8 20 EE 00 jsr SAVE_DATA ; copy to IOBUFF + 2258 + 2259 [01] IF CHECKSUM == 1 + 2260 lda #>IOBUFF+1 + 2261 jsr CKS_BLOCK + 2262 [00] ENDIF + 2263 + 2264 47FB 20 24 48 jsr NEXT_DBUFF ; count buffer + 2265 47FE 4C 3F 48 jmp WRITE_DOS ; and now write it + 2266 ; --------------------- + Tue Jun 13 1989 11:42 Page 36 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2267 ; READ DBLOCK FROM DISK + 2268 ; --------------------- + 2269 ; CALLED BY RESTORE + 2270 ; ENTER: with file already set up as it DBUFF + 2271 ; L+LO == # of 256k blocks to read + 2272 ; + 2273 4801 GETRES: + 2274 4801 A5 7E lda L+LO ; get # of blocks + 2275 4803 8D C3 45 sta READ_PB+RD_BUFFLEN+HI + 2276 4806 20 46 48 jsr READ_DOS + 2277 4809 A2 02 ldx #>PAGELEN ; get starting number of pages + 2278 480B 8E C3 45 stx READ_PB+RD_BUFFLEN+HI + 2279 480E 90 01 bcc GTROK ; everything is fine + 2280 4810 60 rts ; error if c == set + 2281 4811 GTROK: + 2282 4811 A9 08 lda #>IOBUFF ; start at first block + 2283 4813 85 7F sta L+HI ; we can use L+HI + 2284 4815 GTRLOOP: + 2285 4815 A5 7F lda L+HI ; doing this block + 2286 + 2287 [01] IF CHECKSUM == 1 + 2288 jsr CKS_BLOCK ; check check sum + 2289 [00] ENDIF + 2290 + 2291 4817 20 4D 48 jsr COPY_DATA ; and copy from IOBUFF to DBUFF + 2292 481A 20 24 48 jsr NEXT_DBUFF ; check for wrap + 2293 481D E6 7F inc L+HI ; count this block + 2294 481F C6 7E dec L+LO ; count this block + 2295 4821 D0 F2 bne GTRLOOP ; do next one + 2296 4823 60 rts ; all finished + 2297 ; + 2298 ; NEXT_DBUFF + 2299 ; increment DBUFF to count the 2 pages done + 2300 ; + 2301 4824 NEXT_DBUFF: + 2302 4824 E6 B7 inc DBUFF+HI ; point to next page + 2303 4826 A5 B7 lda DBUFF+HI ; see where we are + 2304 4828 C9 BF cmp #>PRGLBL ; wrapping? + 2305 482A D0 10 bne GTREX ; okay then + 2306 482C A5 B8 lda DSKBNK ; which bank we be in + 2307 482E D0 06 bne GTR1 ; aux, so go to page 3 + 2308 4830 E6 B8 inc DSKBNK ; point to aux + 2309 4832 A9 40 lda #Z2PAGE ; start of page 2 + 2310 4834 D0 06 bne GTREX ; so tell me which page + 2311 4836 GTR1: + 2312 4836 A9 FF lda #P3BANK ; show page 3 bank + 2313 4838 85 B8 sta DSKBNK ; okay + 2314 483A A9 D0 lda #Z3PAGE ; page 3 of things + 2315 483C GTREX: + 2316 483C 85 B7 sta DBUFF+HI ; saved + 2317 483E 60 rts ; all done + 2318 ; + 2319 483F WRITE_DOS: + 2320 483F WRITE WRITE_SV ; write out save buffer + 2321 483F PRODOS $CB, WRITE_SV + 2322 483F 20 00 BF jsr $BF00 ; ProDOS handler + 2323 4842 CB DB $CB ; ProDOS function code + 2324 4843 368B DW WRITE_SV ; Function Parameter Block address + 2325 4845 .MACEND + 2326 4845 .MACEND + 2327 4845 60 rts ; done + 2328 4846 READ_DOS: + 2329 4846 READ READ_PB ; read it + 2330 4846 PRODOS $CA, READ_PB + 2331 4846 20 00 BF jsr $BF00 ; ProDOS handler + 2332 4849 CA DB $CA ; ProDOS function code + 2333 484A BE45 DW READ_PB ; Function Parameter Block address + 2334 484C .MACEND + 2335 484C .MACEND + 2336 484C 60 rts ; go home + 2337 ; + 2338 ; COPY_DATA - + 2339 ; now move the data from iobuff to dbuff (in some bank) + 2340 ; which part of IOBUFF is in [a] ($08 - $0B) + 2341 ; + Tue Jun 13 1989 11:42 Page 37 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2342 484D COPY_DATA: + 2343 484D 8D 69 48 sta SDLP3+2 ; self-modify code to get from IOBUFF + 2344 4850 8D 02 C0 sta RDBNK+MAIN ; read from main + 2345 4853 A6 B8 ldx DSKBNK ; get which bank it's going to + 2346 4855 30 05 bmi CPD1 ; oh oh, third bank + 2347 4857 9D 04 C0 sta WRTBNK,X ; and select that bank for writing + 2348 485A 10 07 bpl CPD2 ; okay, bank selected + 2349 485C CPD1: + 2350 485C A5 B7 lda DBUFF+HI ; get from this zero page + 2351 485E 8D 09 C0 sta ALTZP+AUX ; talk about aux mem + 2352 4861 85 B7 sta DBUFF+HI ; and save this in aux mem ZP + 2353 4863 CPD2: + 2354 4863 A0 00 ldy #0 ; start at beginning + 2355 4865 84 B6 sty DBUFF+LO ; just to be sure + 2356 4867 SDLP3: + 2357 4867 B9 00 08 lda IOBUFF,Y ; this becomes modified! + 2358 486A 91 B6 sta (DBUFF),Y ; to [DBUFF] + 2359 486C C8 iny + 2360 486D D0 F8 bne SDLP3 + 2361 486F 8D 08 C0 sta ALTZP+MAIN ; talk about main page again + 2362 4872 8D 04 C0 sta WRTBNK+MAIN ; end up back at main + 2363 4875 60 rts + 2364 ; + 2365 ; Segment table handling routines + 2366 ; + 2367 + 2368 ; + 2369 ; FINDSEG - find the Virtual page in DBLOCK by searching through + 2370 ; the SEGTBL. + 2371 ; + 2372 4876 DISKPAGE: ds 2 ; spot to put starting disk page + 2373 4878 BIGPAGE: ds 2 ; DBLOCK/2 for 512 pages + 2374 487A FINDSEG: + 2375 487A AD 88 6C lda DBLOCK+HI ; work with MSB first + 2376 487D 4A lsr A ; /2 + 2377 487E 8D 79 48 sta BIGPAGE+HI + 2378 4881 AD 87 6C lda DBLOCK+LO ; now LSB + 2379 4884 6A ror A ; /2 + 2380 4885 8D 78 48 sta BIGPAGE+LO + 2381 4888 AD 78 46 lda GAME1NUM ; get number for disk 1 + 2382 488B 20 F1 48 jsr SCANSEG ; scan through the current disk table + 2383 488E AD 77 46 lda GAME1REF ; save refnum + 2384 4891 90 0E bcc FNDSG1 ; found it, figger it out + 2385 4893 AD 8A 46 lda GAME2NUM ; get number for disk 2 + 2386 4896 20 F1 48 jsr SCANSEG ; see if it is here + 2387 4899 AD 89 46 lda GAME2REF ; save refnum + 2388 489C 90 03 bcc FNDSG1 ; ayyup + 2389 489E 20 69 49 jsr SEGQUEST ; get correct disk/file with segment + 2390 48A1 FNDSG1: + 2391 48A1 8D CD 45 sta PSEEK+SM_REFNUM ; for seeking + 2392 48A4 8D BF 45 sta GMREF ; and for reading + 2393 48A7 B1 1E lda (DSEGS),Y ; pick up MSB of disk page + 2394 48A9 8D 77 48 sta DISKPAGE+HI ; save it + 2395 48AC C8 iny ; point to LSB + 2396 48AD B1 1E lda (DSEGS),Y ; get it + 2397 48AF 8D 76 48 sta DISKPAGE+LO ; save it + 2398 ; now point to Starting page again + 2399 48B2 88 dey + 2400 48B3 88 dey + 2401 48B4 88 dey + 2402 48B5 88 dey + 2403 48B6 AD 78 48 lda BIGPAGE+LO ; LSB of desired page + 2404 48B9 38 sec ; doing subtract + 2405 48BA F1 1E sbc (DSEGS),Y ; get rid of LSB of starting page + 2406 48BC 8D CF 45 sta PSEEK+SM_FPOS+1 ; save here for now + 2407 48BF 88 dey ; point to MSB of starting page + 2408 48C0 AD 79 48 lda BIGPAGE+HI ; get DBLOCK MSB + 2409 48C3 F1 1E sbc (DSEGS),Y ; get offset + 2410 48C5 8D D0 45 sta PSEEK+SM_FPOS+2 ; save here temporarily + 2411 48C8 18 clc ; now add offset to starting disk page + 2412 48C9 AD 76 48 lda DISKPAGE+LO ; get starting disk page + 2413 48CC 6D CF 45 adc PSEEK+SM_FPOS+1 ; add inter-segment offset + 2414 48CF 8D CF 45 sta PSEEK+SM_FPOS+1 ; save LSB + 2415 48D2 AD 77 48 lda DISKPAGE+HI ; get MSB of segment disk page + 2416 48D5 6D D0 45 adc PSEEK+SM_FPOS+2 ; add inter-segment offset + Tue Jun 13 1989 11:42 Page 38 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2417 48D8 8D D0 45 sta PSEEK+SM_FPOS+2 ; save MSB of disk page + 2418 48DB 0E CF 45 asl PSEEK+SM_FPOS+1 ; *2 for 256Kb pages + 2419 48DE 2E D0 45 rol PSEEK+SM_FPOS+2 ; okay, we did + 2420 48E1 AD 87 6C lda DBLOCK+LO ; check to see which page in 512 we are + 2421 48E4 29 01 and #$01 ; if odd, then add one more + 2422 48E6 F0 08 beq FNDEX ; all done then + 2423 48E8 EE CF 45 inc PSEEK+SM_FPOS+1 ; one more page + 2424 48EB D0 03 bne FNDEX ; all done if no wrap + 2425 48ED EE D0 45 inc PSEEK+SM_FPOS+2 ; nother page + 2426 48F0 FNDEX: + 2427 48F0 60 rts ; done + 2428 ; + 2429 ; SCANSEG - look through the current segment table for the desired + 2430 ; address found in BIGPAGE. Return with Y pointing to disk page + 2431 ; and carry cleared if found. Otherwise, return carry set. + 2432 ; [A] = which side number we are checking (0-n) + 2433 ; + 2434 48F1 SCANSEG: + 2435 48F1 48 pha ; save which disk + 2436 48F2 0A asl A ; make word index + 2437 48F3 AA tax ; make it an index + 2438 48F4 BD D0 1D lda DSKSEG+LO,X ; get LSB + 2439 48F7 85 1E sta DSEGS+LO + 2440 48F9 BD D1 1D lda DSKSEG+HI,X + 2441 48FC 85 1F sta DSEGS+HI + 2442 48FE A0 05 ldy #SGTNSEG+1 ; point to segment count + 2443 4900 B1 1E lda (DSEGS),Y ; get it + 2444 4902 AA tax ; use x as counter + 2445 4903 68 pla ; get which side + 2446 4904 A8 tay ; is it side zero + 2447 4905 D0 04 bne SCANSG1 ; nope + 2448 4907 A0 0E ldy #SGTSEG+6 ; skip first entry, cuz they're preload + 2449 4909 D0 02 bne SCANNING ; okay ready to go + 2450 490B SCANSG1: + 2451 490B A0 08 ldy #SGTSEG ; begin at beginning + 2452 490D SCANNING: + 2453 490D B1 1E lda (DSEGS),Y ; get MSB of start + 2454 490F CD 79 48 cmp BIGPAGE+HI ; check against block we want + 2455 4912 F0 06 beq SCAN1 ; might be okay + 2456 4914 90 0F bcc SCAN2 ; PAGE > start seg, check end seg + 2457 4916 C8 iny ; LSB of start + 2458 4917 SCAN0: + 2459 4917 C8 iny ; MSB of end + 2460 4918 B0 1F bcs NEXTSEG ; not this one + 2461 491A SCAN1: + 2462 491A C8 iny ; point to LSB of start + 2463 491B B1 1E lda (DSEGS),Y ; get LSB + 2464 491D CD 78 48 cmp BIGPAGE+LO ; check against desired LSB + 2465 4920 F0 20 beq GOTSEG ; we found it + 2466 4922 B0 F3 bcs SCAN0 ; DBLOCK LSB < then start LSB, not found + 2467 4924 88 dey ; point back to MSB of start + 2468 4925 SCAN2: + 2469 4925 C8 iny ; LSB of start + 2470 4926 C8 iny ; MSB of end + 2471 4927 B1 1E lda (DSEGS),Y ; get MSB of end + 2472 4929 CD 79 48 cmp BIGPAGE+HI ; check against DBLOCK MSB + 2473 492C 90 0B bcc NEXTSEG ; end < DBLOCK, check next segment + 2474 492E D0 13 bne GOTSEG1 ; end > DBLOCK, must be in this segment + 2475 4930 C8 iny ; point to end LSB + 2476 4931 B1 1E lda (DSEGS),Y ; get LSB + 2477 4933 CD 78 48 cmp BIGPAGE+LO ; how does it compare to desired LSB + 2478 4936 B0 0C bcs GOTSEG2 ; it's <= end, so it is here + 2479 4938 88 dey ; point back to MSB + 2480 4939 NEXTSEG: + 2481 4939 C8 iny ; point to LSB of end + 2482 493A C8 iny ; MSB of disk page + 2483 493B C8 iny ; LSB of disk page + 2484 493C C8 iny ; MSB of next start page + 2485 493D CA dex ; count this segment + 2486 493E D0 CD bne SCANNING ; check this segment + 2487 + 2488 4940 38 sec ; show not on this disk + 2489 4941 60 rts ; and done + 2490 4942 GOTSEG: + 2491 4942 C8 iny ; MSB of end page + Tue Jun 13 1989 11:42 Page 39 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2492 4943 GOTSEG1: + 2493 4943 C8 iny ; LSB of end page + 2494 4944 GOTSEG2: + 2495 4944 C8 iny ; MSB of disk offset + 2496 4945 18 clc ; show we found it + 2497 4946 60 rts ; all done + 2498 ; + 2499 ; SEGQUEST - find the correct disk/file with the desired page on + 2500 ; it. Returns SCANSEG's stuff. + 2501 ; + 2502 4947 DISKCNTR: ds 1 ; disk count down + 2503 4948 PAGENF: + 2504 4948 50 61 67 65 20 db "Page not found in segment table: " + 494D 6E 6F 74 20 66 + 4952 6F 75 6E 64 20 + 4957 69 6E 20 73 65 + 495C 67 6D 65 6E 74 + 4961 20 74 61 62 6C + 4966 65 3A 20 + 2505 0021 PAGENFL EQU $-PAGENF + 2506 4969 SEGQUEST: + 2507 4969 A9 01 lda #1 ; start at first disk + 2508 496B 8D 47 49 sta DISKCNTR ; init counter + 2509 496E SEGQL: + 2510 496E AD 47 49 lda DISKCNTR ; get disk + 2511 4971 CD 01 19 cmp SEGTBL+SGTDISKS+1 ; looked at all the disks? + 2512 4974 D0 24 bne SEGQL1 ; nope + 2513 ; + 2514 ; as a last resort, check disk 1, the boot disk + 2515 ; + 2516 4976 A9 00 lda #0 ; set up DISKCNTR + 2517 4978 8D 47 49 sta DISKCNTR ; we did + 2518 497B 20 F1 48 jsr SCANSEG ; see if it is there + 2519 497E 90 27 bcc SEGQ1 ; we found it + 2520 + 2521 4980 DLINE PAGENF ; page not found + 2522 4980 A2 48 ldx #PAGENF ; get other part of string + 2524 [01] IFMA 2 ; check to see if length passed in + 2525 ldy ; then just fetch it + 2526 [01] ELSE + 2527 4984 A0 21 ldy #PAGENFL ; get length of string + 2528 [00] ENDIF + 2529 4986 20 5B 4C jsr DLINE ; print the string + 2530 4989 .MACEND + 2531 4989 AD 79 48 lda BIGPAGE+HI ; show MSB + 2532 498C 20 C3 47 jsr HEXNUM ; printed + 2533 498F AD 78 48 lda BIGPAGE+LO ; and LSB + 2534 4992 20 C3 47 jsr HEXNUM ; we did + 2535 + 2536 4995 A9 11 lda #17 ; bad page + 2537 4997 4C F9 51 jmp ZERROR ; die a horrible death + 2538 499A SEGQL1: + 2539 499A AD 47 49 lda DISKCNTR ; get which disk we be working on + 2540 499D 20 F1 48 jsr SCANSEG ; find out if it is here + 2541 49A0 90 05 bcc SEGQ1 ; it is, so open up file + 2542 49A2 EE 47 49 inc DISKCNTR ; not in this disk + 2543 49A5 D0 C7 bne SEGQL ; and try again + 2544 ; + 2545 ; we have found the disk it is in, so ask for it if necessary + 2546 ; + 2547 49A7 SEGQ1: + 2548 49A7 98 tya ; save the y pointer + 2549 49A8 48 pha ; it is saved + 2550 49A9 AD 47 49 lda DISKCNTR ; get which disk we found it under + 2551 49AC 20 B6 49 jsr FETCH_FILE ; go get the disk desired + 2552 49AF 68 pla ; get the Y reg back + 2553 49B0 A8 tay ; and show it + 2554 49B1 AD BF 45 lda GMREF ; get reference number again + 2555 49B4 60 rts ; all done + 2556 ; + 2557 ; FETCH_FILE: check to see if we can open GAMEFILE# (where # is in [A]) + 2558 ; if not, ask for DISK#. + 2559 ; + 2560 49B5 00 SAVENUM: db 0 ; spot to save ascii number + Tue Jun 13 1989 11:42 Page 40 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2561 49B6 FETCH_FILE: + 2562 49B6 18 clc ; adding to make + 2563 49B7 69 30 adc #$30 ; it an ascii number + 2564 49B9 8D B5 49 sta SAVENUM ; just save a minute + 2565 49BC EE B5 49 inc SAVENUM ; make name be one based + 2566 49BF AE 67 46 ldx GAME1NML ; get length of name + 2567 49C2 AD B5 49 lda SAVENUM ; get name back + 2568 49C5 C9 33 cmp #'3' ; are we looking for disk 1 or 2? + 2569 49C7 B0 18 bcs FEFI1 ; disks 3 and up handled special + 2570 49C9 FEFI00: + 2571 49C9 DD 67 46 cmp GAME1NM,X ; is it the current open one? + 2572 49CC D0 05 bne FEFI0 ; nope, so we need to open it + 2573 49CE AC 77 46 ldy GAME1REF ; get game 1 refnum + 2574 49D1 D0 35 bne FEFIX ; all set, so point to it + 2575 49D3 FEFI0: + 2576 49D3 20 D1 4A jsr DO_GAME1 ; handle it special + 2577 49D6 AD 77 46 lda GAME1REF ; fetch refnum + 2578 49D9 20 49 76 jsr GET_PDATA ; now get the picture data + 2579 49DC AC 77 46 ldy GAME1REF ; refetch refnum + 2580 49DF D0 27 bne FEFIX ; so all done + 2581 49E1 FEFI1: + 2582 49E1 AE 79 46 ldx GAME2NML ; get length of second name + 2583 49E4 DD 79 46 cmp GAME2NM,X ; how bout second open file? + 2584 49E7 D0 05 bne FEFI2 ; nope, so we need to open it + 2585 49E9 AC 89 46 ldy GAME2REF ; it is second one, so show me + 2586 49EC D0 1A bne FEFIX ; it is open too + 2587 49EE FEFI2: + 2588 49EE AD 89 46 lda GAME2REF ; get its refnum + 2589 49F1 F0 09 beq FEFI20 ; nothing to close, thank you + 2590 49F3 8D 35 8B sta CLOSE_PB+CL_REFNUM ; show close who to close + 2591 49F6 CLOSE CLOSE_PB ; close it up tight + 2592 49F6 PRODOS $CC, CLOSE_PB + 2593 49F6 20 00 BF jsr $BF00 ; ProDOS handler + 2594 49F9 CC DB $CC ; ProDOS function code + 2595 49FA 348B DW CLOSE_PB ; Function Parameter Block address + 2596 49FC .MACEND + 2597 49FC .MACEND + 2598 49FC FEFI20: + 2599 49FC 20 0F 4A jsr OPEN_GAME2 ; open up GAME2 file + 2600 49FF AD 89 46 lda GAME2REF ; get refnum for this file + 2601 4A02 20 49 76 jsr GET_PDATA ; now get the picture data + 2602 4A05 AC 89 46 ldy GAME2REF ; get ref back, please + 2603 4A08 FEFIX: + 2604 4A08 8C CD 45 sty PSEEK+SM_REFNUM ; for seeking + 2605 4A0B 8C BF 45 sty GMREF ; and for reading + 2606 4A0E 60 rts ; did it + 2607 ; + 2608 ; OPEN_GAME2 - open up the file that GAME2NM is pointing to, + 2609 ; returning the REFNUM in [A], after storing in GAME2REF, + 2610 ; and the 2 picture structures + 2611 ; + 2612 4A0F OPEN_GAME2: + 2613 4A0F AE 79 46 ldx GAME2NML ; get end of name + 2614 4A12 AD B5 49 lda SAVENUM ; get new name + 2615 4A15 9D 79 46 sta GAME2NM,X ; using second file + 2616 4A18 A9 46 lda #>GAME2NM ; get lo byte + 2617 4A1A 8D C8 45 sta OPEN_FILE+OP_PATHNAME+HI + 2618 4A1D A9 79 lda #GAME2FIO ; now set up file i/o buffer + 2621 4A24 8D CA 45 sta OPEN_FILE+OP_FILEBUFF+HI + 2622 4A27 A9 00 lda #0 if multi disk game + 2638 + 2639 4A46 SET_GAMEPRE: + 2640 4A46 20 99 4C jsr SWAP2INFOW ; point to info window + 2641 4A49 AD 45 4A lda SWAPPED ; are we swapping disks? + 2642 4A4C F0 0B beq SETGP ; nope, don't change game prefix + 2643 4A4E AD B5 49 lda SAVENUM ; get which disk to put it + 2644 4A51 AC 8B 46 ldy GAMEPL ; get length of prefix + 2645 4A54 88 dey ; subtract 2 to point to prefix + 2646 4A55 88 dey ; number + 2647 4A56 99 8C 46 sta GAMEP,Y ; set number for prefix + 2648 4A59 SETGP: + 2649 4A59 A9 46 lda #>GAMEPL ; set up parm block + 2650 4A5B 8D D3 45 sta SET_PB+SP_PATHNAME+HI + 2651 4A5E A9 8B lda #SWAPSAVE ; get other part of string + 2670 [01] IFMA 2 ; check to see if length passed in + 2671 ldy ; then just fetch it + 2672 [01] ELSE + 2673 4A74 A0 20 ldy #SWAPSAVEL ; get length of string + 2674 [00] ENDIF + 2675 4A76 20 5B 4C jsr DLINE ; print the string + 2676 4A79 .MACEND + 2677 4A79 AD 45 4A lda SWAPPED ; should we ask for specific disk? + 2678 4A7C D0 15 bne SEGTP01 ; yes, so ask for it + 2679 4A7E DLINE NOSWAP ; no, so just get game disk + 2680 4A7E A2 F4 ldx #NOSWAP ; get other part of string + 2682 [01] IFMA 2 ; check to see if length passed in + 2683 ldy ; then just fetch it + 2684 [01] ELSE + 2685 4A82 A0 0A ldy #NOSWAPL ; get length of string + 2686 [00] ENDIF + 2687 4A84 20 5B 4C jsr DLINE ; print the string + 2688 4A87 .MACEND + 2689 4A87 4C C8 4A jmp SEGTP03 ; and continue + 2690 4A8A SEGTP00: + 2691 4A8A DLINE INS_MSG ; ask for game disk + 2692 4A8A A2 FE ldx #INS_MSG ; get other part of string + 2694 [01] IFMA 2 ; check to see if length passed in + 2695 ldy ; then just fetch it + 2696 [01] ELSE + 2697 4A8E A0 08 ldy #INS_MSGL ; get length of string + 2698 [00] ENDIF + 2699 4A90 20 5B 4C jsr DLINE ; print the string + 2700 4A93 .MACEND + 2701 4A93 SEGTP01: + 2702 4A93 DLINE GAME, GAMEL ; this is the name of the game + 2703 4A93 A2 58 ldx #GAME ; get other part of string + 2705 [01] IFMA 2 ; check to see if length passed in + 2706 4A97 AC 57 46 ldy GAMEL ; then just fetch it + 2707 [01] ELSE + 2708 ldy #GAMEL ; get length of string + 2709 [00] ENDIF + 2710 4A9A 20 5B 4C jsr DLINE ; print the string + Tue Jun 13 1989 11:42 Page 42 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2711 4A9D .MACEND + 2712 4A9D DLINE SIDEMSG ; part 2 of message + 2713 4A9D A2 06 ldx #SIDEMSG ; get other part of string + 2715 [01] IFMA 2 ; check to see if length passed in + 2716 ldy ; then just fetch it + 2717 [01] ELSE + 2718 4AA1 A0 07 ldy #SIDEMSGL ; get length of string + 2719 [00] ENDIF + 2720 4AA3 20 5B 4C jsr DLINE ; print the string + 2721 4AA6 .MACEND + 2722 4AA6 AD B5 49 lda SAVENUM ; get which disk to put it + 2723 4AA9 20 A9 5D jsr CHAR ; print it out + 2724 4AAC DLINE DRIVE_MSG ; tell about drive + 2725 4AAC A2 0D ldx #DRIVE_MSG ; get other part of string + 2727 [01] IFMA 2 ; check to see if length passed in + 2728 ldy ; then just fetch it + 2729 [01] ELSE + 2730 4AB0 A0 10 ldy #DRIVE_MSGL ; get length of string + 2731 [00] ENDIF + 2732 4AB2 20 5B 4C jsr DLINE ; print the string + 2733 4AB5 .MACEND + 2734 4AB5 A9 32 lda #'2' ; assume it's drive 2 + 2735 4AB7 AE B5 49 ldx SAVENUM ; get which disk we want + 2736 4ABA E0 33 cpx #'3' ; >= side 3, must be disk drive 2 + 2737 4ABC B0 02 bcs SEGTP02 ; fine, send that message out + 2738 4ABE A9 31 lda #'1' ; ask for drive 1 then + 2739 4AC0 SEGTP02: + 2740 4AC0 20 A9 5D jsr CHAR ; save which drive + 2741 4AC3 A9 2E lda #'.' ; finish sentence + 2742 4AC5 20 A9 5D jsr CHAR ; okay + 2743 4AC8 SEGTP03: + 2744 4AC8 20 0D 8D jsr GETRET ; wait for + 2745 4ACB 4C 63 4A jmp SETGP0 ; try again + 2746 4ACE SETGP1: + 2747 4ACE 4C B9 4C jmp SWAPBACK ; pointing to disk + 2748 ; + 2749 ; DO_GAME1 - open up the special game 1 file and point to it + 2750 ; + 2751 4AD1 DO_GAME1: + 2752 4AD1 AC 77 46 ldy GAME1REF ; get the current game 1 ref num + 2753 4AD4 F0 0B beq DOG1 ; not currently open + 2754 4AD6 48 pha ; save Name + 2755 4AD7 8C 35 8B sty CLOSE_PB+CL_REFNUM ; show close + 2756 4ADA CLOSE CLOSE_PB ; and close it + 2757 4ADA PRODOS $CC, CLOSE_PB + 2758 4ADA 20 00 BF jsr $BF00 ; ProDOS handler + 2759 4ADD CC DB $CC ; ProDOS function code + 2760 4ADE 348B DW CLOSE_PB ; Function Parameter Block address + 2761 4AE0 .MACEND + 2762 4AE0 .MACEND + 2763 4AE0 68 pla ; get name back + 2764 4AE1 DOG1: + 2765 4AE1 AE 67 46 ldx GAME1NML ; get length of name + 2766 4AE4 AD B5 49 lda SAVENUM ; get new number + 2767 4AE7 9D 67 46 sta GAME1NM,X ; save name + 2768 4AEA 48 pha ; save it for later use + 2769 4AEB A9 46 lda #>GAME1NM ; get lo byte + 2770 4AED 8D C8 45 sta OPEN_FILE+OP_PATHNAME+HI + 2771 4AF0 A9 67 lda #GAME1FIO ; now set up file i/o buffer + 2774 4AF7 8D CA 45 sta OPEN_FILE+OP_FILEBUFF+HI + 2775 4AFA A9 00 lda #LSTVM ; get other part of string + 2832 [01] IFMA 2 ; check to see if length passed in + 2833 ldy ; then just fetch it + 2834 [01] ELSE + 2835 4B51 A0 0B ldy #LSTVML ; get length of string + 2836 [00] ENDIF + 2837 4B53 20 5B 4C jsr DLINE ; print the string + 2838 4B56 .MACEND + 2839 + 2840 4B56 ONLINE ONLINE_PB + 2841 4B56 PRODOS $C5, ONLINE_PB + 2842 4B56 20 00 BF jsr $BF00 ; ProDOS handler + 2843 4B59 C5 DB $C5 ; ProDOS function code + 2844 4B5A 3E4B DW ONLINE_PB ; Function Parameter Block address + 2845 4B5C .MACEND + 2846 4B5C .MACEND + 2847 4B5C 90 05 bcc LSTV1 ; worked fine + 2848 4B5E 20 7A 47 jsr DISK_ERR ; complain if we had an error + 2849 4B61 B0 31 bcs LSTVEX ; all done + 2850 4B63 LSTV1: + 2851 4B63 A9 00 lda #0 ; start at byte zero + 2852 4B65 48 pha ; saved on stack + 2853 4B66 LSTVL: + 2854 4B66 68 pla ; get index + 2855 4B67 AA tax ; make it an index + 2856 4B68 BD 00 08 lda IOBUFF,X ; get drive/length byte + 2857 4B6B F0 27 beq LSTVEX ; all done if == 0 + 2858 4B6D 29 0F and #$0F ; just care about length + Tue Jun 13 1989 11:42 Page 44 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2859 4B6F A8 tay ; save in [Y] for now + 2860 4B70 8A txa ; into [A] for addition + 2861 4B71 18 clc ; doing add + 2862 4B72 69 10 adc #16 ; point to next entry + 2863 4B74 48 pha ; save for later reference + 2864 4B75 98 tya ; check for zero length + 2865 4B76 F0 EE beq LSTVL ; nothing here but an error + 2866 4B78 A9 2F lda #'/' ; start with / to be better + 2867 4B7A 20 A9 5D jsr CHAR ; and it is out there + 2868 4B7D LSTVCL: + 2869 4B7D E8 inx ; point to next char + 2870 4B7E BD 00 08 lda IOBUFF,X ; get char + 2871 4B81 20 A9 5D jsr CHAR ; print it out + 2872 4B84 88 dey ; count char + 2873 4B85 D0 F6 bne LSTVCL ; go get next char + 2874 4B87 A9 2F lda #'/' ; end with '/' to show volume status + 2875 4B89 20 A9 5D jsr CHAR ; and awaaaaay we go + 2876 4B8C A9 0D lda #EOL ; do a + 2877 4B8E 20 A9 5D jsr CHAR ; printed + 2878 4B91 CA dex ; count back one, as loop starts with inx + 2879 4B92 D0 D2 bne LSTVL ; go do next one + 2880 4B94 LSTVEX: + 2881 4B94 60 rts ; toots finis + 2882 ; + 2883 ; CHECKVOLS - set prefix to particular volume that is currently online + 2884 ; + 2885 4B95 CHECKVOLS: + 2886 4B95 A5 1D lda CHPTR+HI ; is it zero? + 2887 4B97 D0 1C bne CHV1 ; if not, then get next volume + 2888 4B99 ONLINE ONLINE_PB ; get online volumes + 2889 4B99 PRODOS $C5, ONLINE_PB + 2890 4B99 20 00 BF jsr $BF00 ; ProDOS handler + 2891 4B9C C5 DB $C5 ; ProDOS function code + 2892 4B9D 3E4B DW ONLINE_PB ; Function Parameter Block address + 2893 4B9F .MACEND + 2894 4B9F .MACEND + 2895 4B9F 90 02 bcc CHV0 ; okey dokey + 2896 4BA1 CHVBX: + 2897 4BA1 38 sec ; show badness + 2898 4BA2 60 rts ; all done + 2899 4BA3 CHV0: + 2900 4BA3 A9 F0 lda #<(IOBUFF-16) ; get LSB (-16 cuz we start with add) + 2901 4BA5 85 1C sta CHPTR+LO + 2902 4BA7 A9 08 lda #>IOBUFF ; and mSB + 2903 4BA9 85 1D sta CHPTR+HI + 2904 4BAB A9 02 lda #>SCRBUFF ; this is where we will work on it + 2905 4BAD 8D D3 45 sta SET_PB+SP_PATHNAME+HI + 2906 4BB0 A9 80 lda #SP_START ; where does it go? + 2965 4C05 85 7F sta L+HI ; L is pointer to there + 2966 4C07 GTS_RD: + 2967 4C07 A9 00 lda #MAIN ; make sure we are in main + 2968 4C09 8D 04 C0 sta WRTBNK+MAIN + 2969 4C0C READ READ_PB ; go get 1Kb + 2970 4C0C PRODOS $CA, READ_PB + 2971 4C0C 20 00 BF jsr $BF00 ; ProDOS handler + 2972 4C0F CA DB $CA ; ProDOS function code + 2973 4C10 BE45 DW READ_PB ; Function Parameter Block address + 2974 4C12 .MACEND + 2975 4C12 .MACEND + 2976 4C12 90 05 bcc GTS_RD1 ; just fine + 2977 4C14 20 F7 46 jsr RETRY ; try again + 2978 4C17 90 CC bcc GTS_RDL ; and do it again + 2979 4C19 GTS_RD1: + 2980 4C19 A2 00 ldx #SP_BANK ; get bank that special is in + 2981 4C1B 9D 04 C0 sta WRTBNK,X + 2982 4C1E A9 08 lda #>IOBUFF ; get MSB of start + 2983 4C20 85 7D sta K+HI ; K is source + 2984 4C22 A2 02 ldx #2 ; 2 blocks of 256 bytes each + 2985 4C24 GTS_CPL0: + 2986 4C24 A0 00 ldy #0 ; indexer + 2987 4C26 GTS_CPL: + 2988 4C26 B1 7C lda (K),y ; get it + 2989 4C28 91 7E sta (L),y ; store it + 2990 4C2A C8 iny ; next + 2991 4C2B D0 F9 bne GTS_CPL ; gwon then + 2992 4C2D E6 7D inc K+HI ; point to next block + 2993 4C2F E6 7F inc L+HI ; for destination too + 2994 4C31 CA dex ; count block + 2995 4C32 D0 F0 bne GTS_CPL0 ; next block + 2996 4C34 C6 7A dec J+LO ; count this 1Kb + 2997 4C36 D0 CF bne GTS_RD ; go get next one + 2998 4C38 + 2999 4C38 8D 04 C0 sta WRTBNK+MAIN ; make sure we are in main + 3000 ; + 3001 ; now figger out last page + 3002 ; + 3003 4C3B A0 09 ldy #SGTSEG+1 ; get start segment LSB + 3004 4C3D B1 59 lda (INFODOS),Y ; got it + 3005 4C3F 18 clc ; doing add + 3006 4C40 69 17 adc #SP_SIZE ; add in size MSB + 3011 4C4A 8D D4 6C sta INFODOS_END+HI ; and save it + 3012 4C4D AD D3 6C lda INFODOS_END+LO ; now, subtract one to make + 3013 4C50 D0 03 bne GTS_END ; it inclusive + 3014 4C52 CE D4 6C dec INFODOS_END+HI ; wrapped, so dec MSB + 3015 4C55 GTS_END: + 3016 4C55 CE D3 6C dec INFODOS_END+LO ; make pointers inclusive + 3017 + 3018 4C58 60 rts ; done + 3019 + 3020 [01] IF CHECKSUM == 1 + 3021 CKS_COUNT: db 0 + 3022 CKSB: db 0 + 3023 CKS_BLOCK: + 3024 pha + 3025 sta CKSMOD+2 + 3026 ldy #0 + 3027 lda CKSB + 3028 CKSLP: + 3029 clc + 3030 CKSMOD: adc IOBUFF,Y + 3031 iny + 3032 bne CKSLP + 3033 + 3034 sta CKSB + 3035 inc CKS_COUNT + 3036 pla + 3037 rts + 3038 + 3039 [02] IF 0 + 3040 jsr HEXNUM + 3041 lda CKS_COUNT + 3042 cmp #$F + 3043 bne CKSCNT + 3044 lda #0 + 3045 sta CKS_COUNT + 3046 lda #EOL + 3047 bne CKSSEND + 3048 CKSCNT: + 3049 inc CKS_COUNT + 3050 lda #SPACE + 3051 CKSSEND: + 3052 jsr CHAR + 3053 jsr DISP_LINE + 3054 pla + 3055 rts + 3056 [01] ENDIF + 3057 + 3058 [00] ENDIF + 3059 + 3060 4C59 END + 3061 + 3062 4C59 INCLUDE MACHINE.ASM + 3063 4C59 STTL "--- MACHINE-DEPENDENT I/O: APPLE II ---" + 3064 PAGE + Tue Jun 13 1989 11:42 Page 47 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3065 ; ----------------------- + 3066 ; DIRECT PRINT LINE [X/A] + 3067 ; ----------------------- + 3068 ; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB) + 3069 ; STRING LENGTH IN [Y] + 3070 4C59 00 DLCNT: db 0 + 3071 4C5A 00 DLOFF: db 0 + 3072 4C5B DLINE: + 3073 4C5B 8E 75 4C stx STRING+LO ; DROP STRING ADDRESS + 3074 4C5E 8D 76 4C sta STRING+HI ; INTO DUMMY BYTES + 3075 4C61 8C 59 4C sty DLCNT ; COUNTER + 3076 4C64 20 BE 55 jsr CLRBUF ; send out what's out + 3077 4C67 A5 B1 lda SCREENF ; save output flag + 3078 4C69 48 pha + 3079 4C6A A2 01 ldx #1 ; INIT CHAR-FETCH INDEX + 3080 4C6C 86 B1 stx SCREENF ; make sure screen output is on + 3081 4C6E CA dex + 3082 4C6F 8E D1 6C stx CRLF_CHECK ; don't let swap happen + 3083 4C72 86 AA stx SCRIPT ; don't script any of my internal + 3084 4C74 BD DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE + 3085 4C75 0000 STRING: DW $0000 ; DUMMY OPERAND BYTES + 3086 4C77 8E 5A 4C stx DLOFF ; save X + 3087 4C7A 85 AC sta IOCHAR ; save here for DIRECT_OUT + 3088 4C7C 20 10 53 DOUT1: jsr DIRECT_OUT ; send directly out there + 3089 4C7F AE 5A 4C ldx DLOFF ; get x back + 3090 4C82 E8 inx + 3091 4C83 CE 59 4C dec DLCNT ; LOOP TILL + 3092 4C86 D0 EC bne DOUT ; OUT OF CHARS + 3093 4C88 20 BE 55 jsr CLRBUF ; and force the chars out + 3094 4C8B A2 01 ldx #1 ; allow scripting again + 3095 4C8D 86 AA stx SCRIPT ; okay, we did + 3096 4C8F 8E D1 6C stx CRLF_CHECK ; and turn on check + 3097 4C92 68 pla ; get screen flag back + 3098 4C93 85 B1 sta SCREENF ; bingo + 3099 4C95 60 rts ; done + 3100 + 3101 ; SWAP2INFOW - save current state and swap to the information window, + 3102 ; which is currently window zero + 3103 4C96 SWAPA1: ds 1 ; save for current ARG1 + 3104 4C97 SWAPCW: ds 1 ; save for current window + 3105 4C98 00 SWAPFLG: db 0 ; flag == 1 if we have already swapped + 3106 4C99 SWAP2INFOW: + 3107 4C99 AD 98 4C lda SWAPFLG ; already swapped? + 3108 4C9C D0 17 bne SWP2 ; ayyup + 3109 4C9E 20 BE 55 jsr CLRBUF ; clear out the buffer + 3110 4CA1 20 8F 4D jsr SAVE_CURSOR ; save current postion of cursor + 3111 4CA4 A5 63 lda ARG1+LO ; get current arg1 + 3112 4CA6 8D 96 4C sta SWAPA1 ; save it + 3113 4CA9 A5 A6 lda CURWIN ; get current window + 3114 4CAB 8D 97 4C sta SWAPCW ; save it + 3115 4CAE A9 00 lda #0 ; swap to window zero for messages + 3116 4CB0 85 63 sta ARG1+LO ; okay + 3117 4CB2 20 85 6E jsr ZSCRN ; and swap to it + 3118 4CB5 SWP2: + 3119 4CB5 EE 98 4C inc SWAPFLG ; show we are in swap window + 3120 4CB8 SWAPEX: + 3121 4CB8 60 rts ; all done + 3122 ; + 3123 ; SWAPBACK - swap out of info window, and back to old window + 3124 ; + 3125 4CB9 SWAPBACK: + 3126 4CB9 CE 98 4C dec SWAPFLG ; are we finally leaving for good? + 3127 4CBC D0 FA bne SWAPEX ; nope + 3128 4CBE AD 97 4C lda SWAPCW ; and now for current window + 3129 4CC1 85 63 sta ARG1+LO ; swap to it + 3130 4CC3 20 85 6E jsr ZSCRN ; we did + 3131 4CC6 AD 96 4C lda SWAPA1 ; and get arg1 back + 3132 4CC9 85 63 sta ARG1+LO ; we did + 3133 4CCB 4C A1 4D jmp GET_CURSOR ; and get cursor back + 3134 + 3135 ; ----------------------- + 3136 ; SEND [LBUFF] TO PRINTER + 3137 ; ----------------------- + 3138 ; ENTRY: LENTH OF LINE IN [PRLEN] + 3139 + Tue Jun 13 1989 11:42 Page 48 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3140 4CCE 60 PLEAV: RTS + 3141 + 3142 4CCF PPRINT: + 3143 4CCF A5 AA lda SCRIPT ; SCRIPTING INTERNALLY ENABLED? + 3144 4CD1 2D A1 6C and SCRIPTF ; SCRIPTING ON? + 3145 4CD4 2D A2 6C and SCRIPTFLG ; Window allow scripting? + 3146 4CD7 F0 F5 beq PLEAV ; NO, EXIT + 3147 4CD9 A5 36 lda CSW+LO ; SAVE NORMAL OUTPUT HOOK + 3148 4CDB 48 pha + 3149 4CDC A5 37 lda CSW+HI + 3150 4CDE 48 pha + 3151 4CDF AD 0C 4D lda ALTCSW+LO ; LOAD SCRIPTING HOOK + 3152 4CE2 85 36 sta CSW+LO + 3153 4CE4 AD 0D 4D lda ALTCSW+HI + 3154 4CE7 85 37 sta CSW+HI + 3155 4CE9 AD 82 C0 lda RDROM ; put system ROM in for printer out + 3156 4CEC A0 00 ldy #0 + 3157 4CEE PP5: + 3158 4CEE B9 00 02 lda LBUFF,Y ;GET A CHAR TO SEND OUT + 3159 4CF1 30 05 bmi PP6 ; don't do highlighting + 3160 4CF3 09 80 ora #$80 ; make it apple happy + 3161 4CF5 20 ED FD jsr MCOUT + 3162 4CF8 PP6: + 3163 4CF8 C8 iny + 3164 4CF9 CE 97 6C dec PRLEN ;LINE COUNT + 3165 4CFC D0 F0 bne PP5 ;PRINT WHOLE LINE + 3166 ; + 3167 ; ALL DONE, RESET TO NORMAL AND LEAVE + 3168 ; + 3169 4CFE AD 83 C0 lda BNK2SET ; write RAM, bank 1 + 3170 4D01 AD 83 C0 lda BNK2SET + 3171 4D04 68 pla + 3172 4D05 85 37 sta CSW+HI + 3173 4D07 68 pla + 3174 4D08 85 36 sta CSW+LO + 3175 4D0A 60 rts + 3176 + 3177 4D0B 00 PSTAT: DB 0 ;SET TO CLEAR WHEN BOOT, + 3178 ;I PUT IT HERE SO RESTART WON'T ALTER + 3179 4D0C 00 00 ALTCSW: DB 0,0 ;(WORD) PRINTER COUT + 3180 + 3181 ; FIRST TIME USING PRINTER, INITIALIZE IT + 3182 4D0E 0D SLOTM: DB EOL + 3183 4D0F 50 72 69 6E 74 DB "Printer Slot 1-7: " + 4D14 65 72 20 53 6C + 4D19 6F 74 20 31 2D + 4D1E 37 3A 20 + 3184 0013 SLOTML EQU $-SLOTM + 3185 + 3186 4D21 PCHK: + 3187 4D21 20 99 4C jsr SWAP2INFOW ; point to info window + 3188 4D24 PCHK1: + 3189 4D24 DLINE SLOTM + 3190 4D24 A2 0E ldx #SLOTM ; get other part of string + 3192 [01] IFMA 2 ; check to see if length passed in + 3193 ldy M ; then just fetch it + 3194 [01] ELSE + 3195 4D28 A0 13 ldy #SLOTML ; get length of string + 3196 [00] ENDIF + 3197 4D2A 20 5B 4C jsr DLINE ; print the string + 3198 4D2D .MACEND + 3199 4D2D 20 20 51 jsr GETKEY + 3200 4D30 C9 38 cmp #'8' ;1-7 + 3201 4D32 B0 F0 bcs PCHK1 ;OOPS + 3202 4D34 C9 31 cmp #'1' ; less than '1'? + 3203 4D36 90 EC bcc PCHK1 ; ayyup + 3204 4D38 PC2: + 3205 4D38 49 F0 eor #$F0 ; make it a slot address + 3206 4D3A 8D 0D 4D sta ALTCSW+HI + 3207 4D3D A9 0D lda #EOL + 3208 4D3F 20 A9 5D jsr CHAR ;SEND >CR< TO SCREEN FOR NEATNESS + 3209 4D42 EE 0B 4D inc PSTAT ;SET TO ON + 3210 4D45 A5 36 lda CSW+LO ;SAVE NORMAL OUTPUT HOOK + 3211 4D47 48 pha + Tue Jun 13 1989 11:42 Page 49 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3212 4D48 A5 37 lda CSW+HI + 3213 4D4A 48 pha + 3214 4D4B AD 0C 4D lda ALTCSW+LO ;LOAD SCRIPTING HOOK + 3215 4D4E 85 36 sta CSW+LO + 3216 4D50 AD 0D 4D lda ALTCSW+HI + 3217 4D53 85 37 sta CSW+HI + 3218 4D55 20 88 4D jsr INITPRT ; now, init it + 3219 + 3220 4D58 AD 82 C0 lda RDROM ; bring in system ROM + 3221 4D5B A9 89 lda #$89 ; OUTPUT PRINTER SETUP SEQUENCE + 3222 4D5D 20 ED FD jsr MCOUT ; START WITH COMMAND CHAR >CTRL-I< + 3223 4D60 A9 B8 lda #$B8 ; 8 (80 COL WIDE) + 3224 4D62 20 ED FD jsr MCOUT + 3225 4D65 A9 B0 lda #$B0 ; 0 + 3226 4D67 20 ED FD jsr MCOUT + 3227 4D6A A9 CE lda #$CE ; N (LF AFTER CR) + 3228 4D6C 20 ED FD jsr MCOUT + 3229 4D6F A5 36 lda CSW+LO ; SAVE REAL PRINTER OUTPUT + 3230 4D71 8D 0C 4D sta ALTCSW+LO ; LOC. FOR NEXT TIME + 3231 4D74 A5 37 lda CSW+HI + 3232 4D76 8D 0D 4D sta ALTCSW+HI + 3233 4D79 68 pla ; RESET NORMAL OUTPUT + 3234 4D7A 85 37 sta CSW+HI + 3235 4D7C 68 pla + 3236 4D7D 85 36 sta CSW+LO + 3237 4D7F AD 83 C0 lda BNK2SET ; and bring back top RAM + 3238 4D82 AD 83 C0 lda BNK2SET ; okay + 3239 4D85 4C B9 4C jmp SWAPBACK ; and back to the old window + 3240 4D88 INITPRT: + 3241 4D88 A9 00 lda #0 ; jump to $Cn00 + 3242 4D8A 85 36 sta CSW+LO ; make LSB == 0 + 3243 4D8C 6C 36 00 jmp (CSW) ; and goto it + 3244 + 3245 + 3246 4D8F SAVE_CURSOR: + 3247 4D8F A5 01 lda SCRCY ; save the cursor pos + 3248 4D91 A0 04 ldy #WINY ; get offset + 3249 4D93 91 05 sta (WINDOW),Y ; first y pos + 3250 4D95 C8 iny ; now x pos + 3251 4D96 A5 00 lda SCRCX ; got it + 3252 4D98 91 05 sta (WINDOW),Y ; saved it + 3253 4D9A A0 13 ldy #WINLCNT ; reset line count too + 3254 4D9C A5 AB lda LINCNT ; okay + 3255 4D9E 91 05 sta (WINDOW),Y ; get it + 3256 4DA0 60 rts + 3257 + 3258 4DA1 GET_CURSOR: + 3259 4DA1 A0 04 ldy #WINY ; get cursor pos back + 3260 4DA3 B1 05 lda (WINDOW),Y ; got y pos + 3261 4DA5 85 01 sta SCRCY ; saved + 3262 4DA7 C8 iny ; point to x pos + 3263 4DA8 B1 05 lda (WINDOW),Y ; got it + 3264 4DAA 85 00 sta SCRCX ; make it better + 3265 4DAC 38 sec ; subtract left margin to get how long line is + 3266 4DAD E5 04 sbc LEFTMRG ; okay we did that + 3267 4DAF B0 02 bcs GETCR1 ; make sure left margin is not > cur x pos + 3268 4DB1 A9 00 lda #0 ; otherwise, pretend length is zero + 3269 4DB3 GETCR1: + 3270 4DB3 85 A7 sta LENGTH+LO ; this is how big line is too + 3271 4DB5 A9 00 lda #0 ; clear MSB + 3272 4DB7 85 A8 sta LENGTH+HI + 3273 4DB9 06 A7 asl LENGTH+LO ; *2 + 3274 4DBB 26 A8 rol LENGTH+HI + 3275 4DBD 06 A7 asl LENGTH+LO ; *4 + 3276 4DBF 26 A8 rol LENGTH+HI + 3277 4DC1 + 3278 4DC1 A0 13 ldy #WINLCNT ; reset line count too + 3279 4DC3 B1 05 lda (WINDOW),Y ; get it + 3280 4DC5 85 AB sta LINCNT ; okay + 3281 4DC7 A9 01 lda #1 ; show cursor changed (maybe) + 3282 4DC9 8D A5 6C sta CURSFLG ; okay + 3283 4DCC 60 rts + 3284 + 3285 ; ------------ + 3286 ; SPLIT SCREEN + Tue Jun 13 1989 11:42 Page 50 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3287 ; ------------ + 3288 ; + 3289 ; SPLIT SCREEN AT LINE [ARG1] putting screen 1 at top and screen + 3290 ; 0 at bottom. + 3291 ; DISABLE SPLIT IF [ARG1] = 0 + 3292 ; + 3293 4DCD ZSPLIT: + 3294 4DCD 20 8F 4D jsr SAVE_CURSOR ; save the cursor pos + 3295 ; + 3296 ; first muck with window 1 + 3297 ; + 3298 4DD0 A5 63 lda ARG1+LO ; get split arg back + 3299 4DD2 8D CF 6D sta WINDOW1+WINHGHT ; this becomes the height of window 1 + 3300 4DD5 A9 00 lda #0 ; put top of 1 to top of screen + 3301 4DD7 8D CD 6D sta WINDOW1+WINTOP ; okay, we did it + 3302 4DDA A5 63 lda ARG1+LO ; get new height + 3303 4DDC A2 FF ldx #$FF ; this is the counter + 3304 4DDE 38 sec ; get ready for subs + 3305 4DDF ZSPLIT0: + 3306 4DDF E8 inx ; count this line + 3307 4DE0 E9 09 sbc #FONT_H ; subtract off font height + 3308 4DE2 B0 FB bcs ZSPLIT0 ; still some lines + 3309 4DE4 CA dex ; save input line + 3310 4DE5 8E E4 6D stx WINDOW1+WINLINES ; saved + 3311 + 3312 4DE8 AD D1 6D lda WINDOW1+WINY ; check cursor pos + 3313 4DEB C5 63 cmp ARG1+LO ; against height + 3314 4DED 90 11 bcc ZSPL1 ; inside window, so save it + 3315 4DEF ZSPL0: + 3316 4DEF A9 00 lda #0 ; reset to top left + 3317 4DF1 8D D1 6D sta WINDOW1+WINY ; y pos at top + 3318 4DF4 8D D2 6D sta WINDOW1+WINX ; x pos at left + 3319 4DF7 8D E2 6D sta WINDOW1+WINLLEN+LO ; line length + 3320 4DFA 8D E3 6D sta WINDOW1+WINLLEN+HI ; line length + 3321 4DFD 8D E0 6D sta WINDOW1+WINLCNT ; line counter + 3322 ; + 3323 ; now muck with window 0 + 3324 ; + 3325 4E00 ZSPL1: + 3326 4E00 AD B5 6D lda WINDOW0+WINTOP ; top of window 0 + 3327 4E03 38 sec ; doing sub + 3328 4E04 E5 63 sbc ARG1+LO ; subtract out the new top + 3329 4E06 18 clc ; adding + 3330 4E07 6D B7 6D adc WINDOW0+WINHGHT ; to get the new height + 3331 ; bcc ZSPLIT1 ; okay, positive height + 3332 ; lda #0 ; make height 0 + 3333 4E0A ZSPLIT1: + 3334 4E0A 8D B7 6D sta WINDOW0+WINHGHT ; and save new height + 3335 4E0D + 3336 4E0D A2 FF ldx #$FF ; this is the counter + 3337 4E0F 38 sec ; get ready for subs + 3338 4E10 ZSPLIT2: + 3339 4E10 E8 inx ; count this line + 3340 4E11 E9 09 sbc #FONT_H ; subtract off font height + 3341 4E13 B0 FB bcs ZSPLIT2 ; still some lines + 3342 4E15 CA dex ; to save input line + 3343 4E16 8E CC 6D stx WINDOW0+WINLINES ; saved + 3344 + 3345 4E19 A5 63 lda ARG1+LO ; this is the new top + 3346 4E1B 8D B5 6D sta WINDOW0+WINTOP ; set in structure + 3347 4E1E CD B9 6D cmp WINDOW0+WINY ; make sure cursor is still in window + 3348 4E21 F0 13 beq ZSPL5 ; nope, at the top + 3349 4E23 90 11 bcc ZSPL5 ; or under it + 3350 4E25 8D B9 6D sta WINDOW0+WINY ; put cursor at top + 3351 4E28 A9 00 lda #0 ; left of new + 3352 4E2A 8D BA 6D sta WINDOW0+WINX ; window 0 + 3353 4E2D 8D CA 6D sta WINDOW0+WINLLEN+LO ; linelength + 3354 4E30 8D CB 6D sta WINDOW0+WINLLEN+HI ; linelength + 3355 4E33 8D C8 6D sta WINDOW0+WINLCNT ; line counter + 3356 4E36 ZSPL5: + 3357 4E36 20 A1 4D jsr GET_CURSOR ; get the cursor pos back + 3358 + 3359 4E39 A9 00 lda #0 ; now switch to window zero + 3360 4E3B 85 63 sta ARG1+LO ; good bye + 3361 4E3D 4C 85 6E jmp ZSCRN ; making window 0 be current + Tue Jun 13 1989 11:42 Page 51 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3362 + 3363 ; ------ + 3364 ; MARGIN + 3365 ; ------ + 3366 ; + 3367 ; Set the margins for the window + 3368 ; + 3369 ; ARG1 - left margin + 3370 ; ARG2 - right margin + 3371 ; ARG3 - window ID (optional) + 3372 ; + 3373 4E40 ZMARG: + 3374 4E40 20 BE 55 jsr CLRBUF ; CLEAR LBUFF BEFORE RESETTING LINE MARGINS + 3375 4E43 20 8F 4D jsr SAVE_CURSOR ; save current cursor pos + 3376 4E46 + 3377 4E46 A5 62 lda NARGS ; see if window ID was passed + 3378 4E48 C9 03 cmp #3 ; if ==3, then it's there + 3379 4E4A F0 04 beq ZMRG1 ; okay, so use it + 3380 4E4C A5 A6 lda CURWIN ; get the current window + 3381 4E4E 85 67 sta ARG3+LO ; and use as the default + 3382 4E50 ZMRG1: + 3383 4E50 A5 67 lda ARG3+LO ; check what window + 3384 4E52 20 87 57 jsr SETWJ ; get window offset into J + 3385 4E55 A5 63 lda ARG1+LO ; do left margin first + 3386 4E57 A0 06 ldy #WINLM ; get offset + 3387 4E59 91 7A sta (J),Y ; save for window + 3388 4E5B C8 iny ; point to right margin + 3389 4E5C A5 65 lda ARG2+LO ; get right margin + 3390 4E5E 91 7A sta (J),Y ; save right margin + 3391 4E60 A0 03 ldy #WINWID ; get full width of window + 3392 4E62 B1 7A lda (J),Y ; got it + 3393 4E64 38 sec ; subtract off the 2 margins + 3394 4E65 A0 06 ldy #WINLM ; first the left margin + 3395 4E67 F1 7A sbc (J),Y ; okay, gone + 3396 4E69 C8 iny ; point to right margin + 3397 4E6A F1 7A sbc (J),Y ; and take it off + 3398 4E6C A0 14 ldy #WINXSZ ; set width of usable window + 3399 4E6E 91 7A sta (J),Y ; see, here it is + 3400 ; + 3401 ; move cursor to left margin + 3402 ; + 3403 4E70 A0 01 ldy #WINLEFT ; get left edge + 3404 4E72 B1 7A lda (J),Y ; got it + 3405 4E74 A0 06 ldy #WINLM ; and add left margin + 3406 4E76 18 clc ; adding + 3407 4E77 71 7A adc (J),Y ; to get minimum X + 3408 4E79 A0 05 ldy #WINX ; check to make sure X pos is okay + 3409 4E7B 91 7A sta (J),Y ; then reset it + 3410 ; + 3411 ; now see if we changed the current window + 3412 ; + 3413 4E7D ZMRGXP: + 3414 4E7D A6 67 ldx ARG3+LO ; get the window + 3415 4E7F 30 04 bmi ZMRG3 ; -3 means current window + 3416 4E81 E4 A6 cpx CURWIN ; check against the current window + 3417 4E83 D0 17 bne ZMRGX ; nope, so we be done + 3418 4E85 ZMRG3: + 3419 4E85 85 04 sta LEFTMRG ; [A] already has left margin + 3420 4E87 A0 14 ldy #WINXSZ ; get xsize to set + 3421 4E89 B1 05 lda (WINDOW),Y ; got it + 3422 4E8B 85 A2 sta XSIZE+LO ; this is for quicky comparing + 3423 4E8D A9 00 lda #0 ; clear MSB + 3424 4E8F 85 A3 sta XSIZE+HI + 3425 4E91 06 A2 asl XSIZE+LO ; *2 + 3426 4E93 26 A3 rol XSIZE+HI + 3427 4E95 06 A2 asl XSIZE+LO ; *4 + 3428 4E97 26 A3 rol XSIZE+HI + 3429 4E99 20 A1 4D jsr GET_CURSOR ; restore the cursor pos + 3430 4E9C ZMRGX: + 3431 4E9C 60 rts + 3432 ; + 3433 ; SOUND + 3434 ; ----- + 3435 ; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID + 3436 ; (EZIP) + Tue Jun 13 1989 11:42 Page 52 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3437 + 3438 4E9D ZSOUND: + 3439 4E9D A6 63 ldx ARG1+LO ; GET SOUND WANTED + 3440 4E9F CA dex + 3441 4EA0 F0 11 beq BEEP + 3442 4EA2 CA dex + 3443 4EA3 D0 0D bne ZSOEX ; INVALID + 3444 4EA5 A0 FF ldy #$FF ; DURATION ($C0 = .1 SEC) + 3445 4EA7 BOOP: + 3446 4EA7 A9 10 lda #$10 ; TONE ($0C = 1 KHZ) + 3447 4EA9 20 16 4F jsr WAIT10 + 3448 4EAC AD 30 C0 lda SPKR ; TOGGLE SPEAKER + 3449 4EAF 88 dey + 3450 4EB0 D0 F5 bne BOOP + 3451 4EB2 ZSOEX: + 3452 4EB2 60 rts + 3453 + 3454 4EB3 BEEP: + 3455 4EB3 AD 82 C0 lda RDROM + 3456 4EB6 20 3A FF jsr MBELL ; just use system beep + 3457 4EB9 AD 83 C0 lda BNK2SET ; back to bank 2 + 3458 4EBC AD 83 C0 lda BNK2SET ; back to bank 2 + 3459 4EBF 60 rts + 3460 ; + 3461 ; just do the background color - foreground is always white/black + 3462 ; + 3463 ; + 3464 ; ZIPCOLOR - maps ZIP colors to screen colors + 3465 ; + 3466 4EC0 ZCOLOR: + 3467 4EC0 20 BE 55 jsr CLRBUF ; print out what we have + 3468 + 3469 4EC3 A5 62 lda NARGS ; check if window was passed + 3470 4EC5 C9 03 cmp #3 ; was it? + 3471 4EC7 F0 04 beq ZCLR0 ; ayyup + 3472 4EC9 A5 A6 lda CURWIN ; make it current window + 3473 4ECB 85 67 sta ARG3+LO ; it is now + 3474 4ECD ZCLR0: + 3475 4ECD A5 67 lda ARG3+LO ; get window ID + 3476 4ECF 20 87 57 jsr SETWJ ; and put pointer into J + 3477 + 3478 4ED2 A6 65 ldx ARG2+LO ; get background color + 3479 4ED4 F0 15 beq ZCLR2 ; check fore ground color + 3480 4ED6 10 06 bpl ZCLR01 ; not -1 + 3481 4ED8 20 37 5E jsr GET_NYBBLE ; get me the color nybble here + 3482 4EDB 4C E7 4E jmp ZCLR11 ; and use as background color + 3483 4EDE ZCLR01: + 3484 4EDE CA dex ; check for default + 3485 4EDF D0 02 bne ZCLR1 ; nope, find the color + 3486 4EE1 A2 01 ldx #1 ; use black as default back color + 3487 4EE3 ZCLR1: + 3488 4EE3 CA dex ; zero base the color + 3489 4EE4 BD 6D 6C lda ZIPCOLOR,X ; get my color from the zip color + 3490 4EE7 ZCLR11: + 3491 4EE7 A0 0E ldy #WINBGND ; get background offset + 3492 4EE9 91 7A sta (J),Y ; saved color + 3493 ; + 3494 ; now do foreground color + 3495 ; + 3496 4EEB ZCLR2: + 3497 4EEB A6 63 ldx ARG1+LO ; get foreground color + 3498 4EED F0 0D beq ZCLREX ; no change + 3499 4EEF CA dex ; check for default + 3500 4EF0 D0 02 bne ZCLR3 ; nope, find the color + 3501 4EF2 A2 08 ldx #8 ; use white as default fore color + 3502 4EF4 ZCLR3: + 3503 4EF4 CA dex ; zero base the color + 3504 4EF5 BD 6D 6C lda ZIPCOLOR,X ; get my color from the zip color + 3505 4EF8 A0 0D ldy #WINFORE ; foreground color offset + 3506 4EFA 91 7A sta (J),Y ; save in structure + 3507 4EFC ZCLREX: + 3508 4EFC 60 rts + 3509 + 3510 ; + 3511 ; CHKTME RTN - CALLED BY INPUT & ZINPUT + Tue Jun 13 1989 11:42 Page 53 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3512 ; + 3513 4EFD CHKTME: + 3514 4EFD A5 62 lda NARGS ; CHECK IF TIME LIMIT + 3515 4EFF C9 02 cmp #2 + 3516 4F01 F0 12 beq CHKT1 ; NO + 3517 4F03 A5 67 lda ARG3+LO ; GET DELAY WANTED + 3518 4F05 85 79 sta I+HI + 3519 4F07 A5 62 lda NARGS ; IS THERE A FCN? + 3520 4F09 C9 04 cmp #4 + 3521 4F0B D0 08 bne CHKT1 ; NO + 3522 4F0D A5 69 lda ARG4+LO ; YES, SET IT + 3523 4F0F 85 7A sta J+LO + 3524 4F11 A5 6A lda ARG4+HI + 3525 4F13 85 7B sta J+HI + 3526 4F15 CHKT1: + 3527 4F15 60 rts ; just set things up, please + 3528 + 3529 4F16 WAIT10: + 3530 4F16 A9 02 lda #2 ; do this twice (maybe) + 3531 4F18 85 C6 sta DELAY_COUNTER ; put in counter + 3532 4F1A WAIT0: + 3533 4F1A AD 82 C0 lda RDROM ; get roms in + 3534 4F1D A2 04 ldx #4 ; .04 SEC (time to do other stuff) + 3535 4F1F A9 30 TIME1: lda #$30 ; .01 SEC + 3536 4F21 20 A8 FC jsr MWAIT + 3537 4F24 CA dex + 3538 4F25 D0 F8 bne TIME1 + 3539 + 3540 4F27 AD 83 C0 lda BNK2SET ; get roms out + 3541 4F2A AD 83 C0 lda BNK2SET + 3542 + 3543 4F2D A5 58 lda MOUSEF ; move mouse cursor? + 3544 4F2F F0 08 beq WAIT1 ; nope + 3545 4F31 AD D2 6C lda PTR_COUNT ; but do we really want to check it + 3546 4F34 D0 03 bne WAIT1 ; nope + 3547 4F36 4C 1A 50 jmp MOVE_MC ; move cursor, if necessary + 3548 4F39 WAIT1: + 3549 4F39 C6 C6 dec DELAY_COUNTER ; count loop + 3550 4F3B D0 DD bne WAIT0 ; go do again + 3551 4F3D 60 rts + 3552 ; + 3553 ; tick the ol timer + 3554 ; + 3555 4F3E TIMEK: + 3556 4F3E A9 03 lda #BLINK_RATE ; how often to blink + 3557 4F40 8D 81 4F sta CURCOUNT ; okay! + 3558 4F43 TIMEST: + 3559 4F43 A5 78 lda I+LO ; don't reset if not zero + 3560 4F45 D0 07 bne TIMELOOP ; so keep goin' then + 3561 4F47 A5 79 lda I+HI + 3562 4F49 85 78 sta I+LO + 3563 4F4B 20 82 4F jsr STCUR ; start the cursor + 3564 4F4E TIMELOOP: + 3565 4F4E 20 16 4F jsr WAIT10 ; wait .10 secs + 3566 + 3567 4F51 20 D5 4F jsr FKEYX ; Check for Keystroke + 3568 4F54 30 23 bmi TIME2 ; OK, HE'S THERE, CONTINUE + 3569 + 3570 4F56 CE 81 4F dec CURCOUNT ; count down to toggle + 3571 4F59 D0 08 bne TMCNT ; okay, no blink + 3572 4F5B 20 82 4F jsr STCUR ; blink cursor + 3573 4F5E A9 03 lda #BLINK_RATE ; once per second + 3574 4F60 8D 81 4F sta CURCOUNT ; okay! + 3575 4F63 TMCNT: + 3576 4F63 C6 78 dec I+LO ; 10TH'S OF SECONDS TO WAIT + 3577 4F65 F0 02 beq TIMEOUT ; SOME TIME LEFT + 3578 + 3579 4F67 D0 E5 bne TIMELOOP ; so gwon back and try again! (JMP) + 3580 ; + 3581 ; THERE IS A TIME OUT, CHECK FOR A FCN + 3582 ; + 3583 4F69 TIMEOUT: + 3584 4F69 20 AD 4F jsr ERCUR ; after erasing cursor + 3585 4F6C A5 7B lda J+HI ; IS THERE A FCN + 3586 4F6E F0 0E beq TIMEBAD ; NO FCN, LEAVE WITH NOTHING + Tue Jun 13 1989 11:42 Page 54 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3587 4F70 TIME3: + 3588 4F70 20 3F 5B jsr INTCLL ; INTERNALLY CALL THE FCN + 3589 4F73 A5 76 lda VALUE+LO ; CHECK RESULTS + 3590 4F75 F0 CC beq TIMEST ; ELSE TRY AGAIN + 3591 4F77 D0 05 bne TIMEBAD ; else die a horrible death! + 3592 4F79 TIME2: + 3593 4F79 20 AD 4F jsr ERCUR ; after erasing cursor + 3594 4F7C 18 clc ; GOT A KEY + 3595 4F7D 60 rts + 3596 4F7E TIMEBAD: + 3597 4F7E 38 sec + 3598 4F7F 60 rts + 3599 ; + 3600 ; display the cursor in the current spot + 3601 ; + 3602 4F80 80 CURSTATE: db $80 ; blinking cursor state + 3603 4F81 00 CURCOUNT: db 0 ; toggle counter + 3604 + 3605 4F82 STCUR: + 3606 4F82 AE D0 6C ldx CURSOR_OFF ; is the cursor off? + 3607 4F85 F0 01 beq STCUR1 ; no + 3608 4F87 60 rts ; yes, so don't do nuthin' + 3609 4F88 STCUR1: + 3610 4F88 48 pha ; save a + 3611 4F89 A5 BB lda INVFLG ; get current INVFLG + 3612 4F8B 48 pha ; save it + 3613 4F8C A9 80 lda #$80 ; make it all be ones + 3614 4F8E 85 BB sta INVFLG ; and blink + 3615 + 3616 4F90 A9 20 lda #SPACE ; space for cursor + 3617 4F92 8D 0C 72 sta SHOW_CURSOR ; show that we are doing cursor + 3618 4F95 20 A9 5D jsr CHAR ; and print it out + 3619 4F98 20 1A 72 jsr DISP_LINE ; send it out + 3620 + 3621 4F9B AD 80 4F lda CURSTATE ; get current state + 3622 4F9E 49 80 eor #$80 ; toggle it + 3623 4FA0 8D 80 4F sta CURSTATE ; save it + 3624 4FA3 68 pla ; get invflg + 3625 4FA4 85 BB sta INVFLG ; restored + 3626 4FA6 A9 00 lda #0 ; clear cursor flag + 3627 4FA8 8D 0C 72 sta SHOW_CURSOR ; okay + 3628 4FAB + 3629 4FAB 68 pla ; get [A] back + 3630 4FAC 60 rts + 3631 ; + 3632 ; just erase the cusor char, but leave cursor in its old place + 3633 ; + 3634 4FAD ERCUR: + 3635 4FAD 48 pha ; save a + 3636 4FAE AD 80 4F lda CURSTATE ; get current state + 3637 4FB1 D0 03 bne ERCURX ; not on, leave alone + 3638 4FB3 20 82 4F jsr STCUR ; 'start' it out + 3639 4FB6 ERCURX: + 3640 4FB6 68 pla ; retrieve [A] + 3641 4FB7 60 rts + 3642 ; + 3643 ; timed key input loop + 3644 ; + 3645 ; carry set if timed out + 3646 ; char in [A], if there is one! + 3647 4FB8 TIMIN: + 3648 4FB8 A5 58 lda MOUSEF ; is there a mouse/joystick? + 3649 4FBA F0 03 beq TIMIN1 ; nope + 3650 4FBC 20 E3 62 jsr MSCON ; turn on mouse cursor + 3651 4FBF TIMIN1: + 3652 4FBF 20 3E 4F jsr TIMEK ; check for keystroke + 3653 4FC2 B0 05 bcs TMBAD ; ELSE ABORT + 3654 4FC4 TM1: + 3655 4FC4 20 7A 51 jsr PARSEKEY ; GET ASCII INTO [A] AND [IOCHAR] + 3656 4FC7 B0 F6 bcs TIMIN1 ; c==1 means no good char + 3657 4FC9 TMBAD: + 3658 4FC9 A6 58 ldx MOUSEF ; is there a mouse/joystick? + 3659 4FCB F0 07 beq TIMIN2 ; nope + 3660 4FCD 08 php ; save status + 3661 4FCE 48 pha ; save (possible) char + Tue Jun 13 1989 11:42 Page 55 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3662 4FCF 20 84 62 jsr MSCOFF ; turn off mouse cursor + 3663 4FD2 68 pla ; get char back + 3664 4FD3 28 plp ; get return status + 3665 4FD4 TIMIN2: + 3666 4FD4 60 rts ; and away we go + 3667 ; + 3668 ; FKEYX - move the mouse cursor if any, then check for keystroke + 3669 ; + 3670 4FD5 FKEYX: + 3671 4FD5 A5 58 lda MOUSEF ; is there a mouse cursor? + 3672 4FD7 F0 38 beq KEYX ; nope + 3673 4FD9 30 07 bmi KEYMOUSE ; handle mouse + 3674 4FDB 20 9C 50 jsr DO_STICK ; handle joystick + 3675 4FDE 10 31 bpl KEYX ; go look for key still + 3676 4FE0 30 05 bmi KEYBTN ; do button handling + 3677 4FE2 KEYMOUSE: + 3678 4FE2 20 5D 50 jsr DO_MOUSE ; handle mouse stuff + 3679 4FE5 10 2A bpl KEYX ; go look for key still + 3680 ; + 3681 ; button hit, so show pos in MSTBL + 3682 ; + 3683 4FE7 KEYBTN: + 3684 4FE7 48 pha ; save status + 3685 4FE8 A5 CE lda MSTBL+LO + 3686 4FEA 85 8F sta SPCL + 3687 4FEC A5 CF lda MSTBL+HI + 3688 4FEE 85 90 sta SPCH + 3689 4FF0 A5 D0 lda MSTBL+ABANK + 3690 4FF2 85 91 sta SPCBNK + 3691 4FF4 A9 03 lda #ZMSLOCX+1 ; point to LSB of mouse x + 3692 4FF6 20 33 90 jsr ADDSPC ; add to point + 3693 4FF9 A5 CB lda MSX ; get X + 3694 4FFB 18 clc ; center the hot spot + 3695 4FFC 69 01 adc #CURSW/2 ; add 1/2 width + 3696 4FFE 20 67 92 jsr STASHB ; and stuff it away + 3697 5001 A9 02 lda #2 ; 2 more to get to mouse y + 3698 5003 20 33 90 jsr ADDSPC ; okay + 3699 5006 A5 CC lda MSY ; now show the world the y pos + 3700 5008 18 clc ; and center vertically too + 3701 5009 69 02 adc #CURSH/2 ; add 1/2 height + 3702 500B 20 67 92 jsr STASHB ; and it is away + 3703 500E 68 pla ; get status back + 3704 500F A8 tay ; and set it again + 3705 5010 60 rts ; otherwise, done + 3706 5011 KEYX: + 3707 5011 AD 00 C0 lda KBD ; check keyboard strobe + 3708 5014 10 03 bpl KEYXX ; nothing + 3709 5016 8D 10 C0 sta ANYKEY ; reset strobe + 3710 5019 KEYXX: + 3711 5019 60 rts + 3712 ; + 3713 ; MOVE_MC - move the mouse/joystick cursor, if necessary + 3714 ; + 3715 501A MOVE_MC: + 3716 501A A5 58 lda MOUSEF ; check which kind to move + 3717 501C 10 06 bpl MOVE_MC1 ; move joystick cursor + 3718 501E 20 30 50 jsr CHK_MOUSE ; move the mouse cursor + 3719 5021 4C 27 50 jmp MOVE_MC2 ; and print it + 3720 5024 MOVE_MC1: + 3721 5024 20 A2 50 jsr MOVE_STICK ; okay, checked it out + 3722 5027 MOVE_MC2 + 3723 5027 AD 12 03 lda MSMOVEF ; did it move? + 3724 502A F0 03 beq MOVE_MCX ; nope + 3725 502C 4C 79 62 jmp MSCURS ; print it + 3726 502F MOVE_MCX: + 3727 502F 60 rts ; done + 3728 ; + 3729 ; CHK_MOUSE - check the mouse position and button state, and flag any change + 3730 ; + 3731 5030 CHK_MOUSE: + 3732 5030 AD 54 C0 lda PAGE2SW ; make sure we are pointing to main bank + 3733 + 3734 5033 A2 02 ldx #READM ; get me current cursor pos + 3735 5035 20 00 03 jsr MOUSER ; turn off interrupts and set current pos + 3736 + Tue Jun 13 1989 11:42 Page 56 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3737 5038 AD 83 C0 lda BNK2SET ; make sure we are pointing to second bank + 3738 503B AD 83 C0 lda BNK2SET ; okay + 3739 + 3740 503E AD 78 07 MSFIX0 lda MOUSEST ; get status byte + 3741 5041 A8 tay ; save for a sec + 3742 5042 29 20 and #$20 ; moved since last time? + 3743 5044 F0 0D beq CHKM1 ; nope + 3744 5046 8D 12 03 sta MSMOVEF ; show movement + 3745 5049 AD 78 04 MSFIX1 lda MOUSEXL ; get mouse X pos + 3746 504C 85 CB sta MSX ; save new one + 3747 504E AD F8 04 MSFIX2 lda MOUSEYL ; and the y pos + 3748 5051 85 CC sta MSY ; save for me + 3749 5053 CHKM1: + 3750 5053 98 tya ; get status back + 3751 5054 29 C0 and #$C0 ; is button down? + 3752 5056 F0 02 beq CHKMX ; nope + 3753 5058 A9 80 lda #$80 ; show down state + 3754 505A CHKMX: + 3755 505A 4C 14 51 jmp CHK_BTN ; check button state + 3756 ; + 3757 ; there is a mouse, so check it + 3758 ; + 3759 505D DO_MOUSE: + 3760 505D 20 30 50 jsr CHK_MOUSE ; check the mouse please + 3761 ; FALL THROUGH TO BUTTON CLICKING HANDLER + 3762 ; jmp DO_BUTTON ; handle button clicking + 3763 ; + 3764 ; DO_BUTTON - handle button clicking, working with the timer to + 3765 ; check for double clicking or not + 3766 ; + 3767 5060 DO_BUTTON: + 3768 5060 AD 12 03 lda MSMOVEF ; check moved flag + 3769 5063 F0 03 beq DOM01 ; nope + 3770 5065 20 79 62 jsr MSCURS ; move mouse cursor + 3771 5068 DOM01: + 3772 5068 A9 00 lda #0 ; show no char + 3773 506A AC 13 03 ldy MSBTNF ; check button flag + 3774 506D 10 15 bpl DOBX ; none + 3775 ; + 3776 ; button strike, check for double click + 3777 ; + 3778 506F 8C F1 50 sty JB_STATE ; show new state + 3779 5072 A4 CA ldy CLKCTR ; have we started click counter? + 3780 5074 10 08 bpl DOB02 ; nope + 3781 5076 A0 01 ldy #1 ; this resets counter + 3782 5078 84 CA sty CLKCTR ; reset it + 3783 507A A9 82 lda #DBL_CLK ; show double click char + 3784 507C D0 14 bne DOBEXIT ; and finis + 3785 507E DOB02: + 3786 507E A0 FA ldy #-CLK_CNT ; set to double click timeout + 3787 5080 84 CA sty CLKCTR ; okay + 3788 5082 30 0E bmi DOBEXIT ;done + 3789 5084 DOBX: + 3790 5084 A4 CA ldy CLKCTR ; click counter counting? + 3791 5086 10 0A bpl DOBEXIT ; nope + 3792 5088 E6 CA inc CLKCTR ; count it then + 3793 508A D0 06 bne DOBEXIT ; all done + 3794 508C A0 01 ldy #1 ; reset counter + 3795 508E 84 CA sty CLKCTR ; okay + 3796 5090 A9 81 lda #SGL_CLK ; set as char + 3797 5092 DOBEXIT: + 3798 5092 A0 00 ldy #0 ; clear out flags + 3799 5094 8C 13 03 sty MSBTNF ; button flag + 3800 5097 8C 12 03 sty MSMOVEF ; moved flag + 3801 509A A8 tay ; set flag to show any char + 3802 509B 60 rts ; return char + 3803 ; + 3804 ; DO_STICK - handle the joystick 'interrupt' + 3805 ; + 3806 509C DO_STICK: + 3807 509C 20 A2 50 jsr MOVE_STICK ; first move it + 3808 509F 4C 60 50 jmp DO_BUTTON ; now handle it + 3809 50A2 MOVE_STICK: + 3810 50A2 A9 00 lda #0 ; get horizontal change + 3811 50A4 20 F2 50 jsr READ_STICK ; puts value in Y + Tue Jun 13 1989 11:42 Page 57 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3812 50A7 C0 50 cpy #80 ; if < 80, then jump to the left + 3813 50A9 B0 0D bcs DOST1 ; it is not + 3814 50AB A5 CB lda MSX ; make sure X is > 0 + 3815 50AD F0 1A beq DOST2 ; it is == 0, can't get smaller + 3816 50AF 8D 12 03 sta MSMOVEF ; show movement + 3817 50B2 C6 CB dec MSX ; move one to the left + 3818 50B4 C6 CB dec MSX ; move two to the left + 3819 50B6 D0 11 bne DOST2 ; now check vertical + 3820 50B8 DOST1: + 3821 50B8 C0 B4 cpy #180 ; if > 160, then move right + 3822 50BA 90 0D bcc DOST2 ; nope + 3823 50BC A5 CB lda MSX ; make sure X is in bounds + 3824 50BE C9 88 cmp #MAXWIDTH-4 ; don't go too far + 3825 50C0 B0 07 bcs DOST2 ; already maxxed out + 3826 50C2 8C 12 03 sty MSMOVEF ; show movement + 3827 50C5 E6 CB inc MSX ; one step to the left + 3828 50C7 E6 CB inc MSX ; and another one + 3829 50C9 DOST2: + 3830 50C9 A9 01 lda #1 ; now check vertical + 3831 50CB 20 F2 50 jsr READ_STICK ; ask the monitor + 3832 50CE C0 50 cpy #80 ; if < 80, move up + 3833 50D0 B0 0D bcs DOST3 ; nope + 3834 50D2 A5 CC lda MSY ; don't go negative + 3835 50D4 F0 1A beq DOST4 ; already minned out + 3836 50D6 8D 12 03 sta MSMOVEF ; show movement + 3837 50D9 C6 CC dec MSY ; count down + 3838 50DB C6 CC dec MSY ; twice + 3839 50DD D0 11 bne DOST4 ; all done + 3840 50DF DOST3: + 3841 50DF C0 B4 cpy #180 ; check for downward motion + 3842 50E1 90 0D bcc DOST4 ; none + 3843 50E3 A5 CC lda MSY ; check for maximum + 3844 50E5 C9 BD cmp #MAXHEIGHT-3 ; don't go below water + 3845 50E7 B0 07 bcs DOST4 ; gone, thanx + 3846 50E9 8C 12 03 sty MSMOVEF ; show movement + 3847 50EC E6 CC inc MSY ; go further down + 3848 50EE E6 CC inc MSY ; twice as far for joystick + 3849 50F0 DOST4: + 3850 50F0 60 rts ; done + 3851 ; + 3852 ; READ_STICK - read the x or y value of the stick in mind. + 3853 ; [A] == 0 or 1 - the "stick" you are interested in + 3854 ; Also, check the button status. + 3855 ; + 3856 50F1 00 JB_STATE db 0 ; last state of joystick button + 3857 50F2 READ_STICK: + 3858 50F2 48 pha ; save which stick we want + 3859 50F3 A2 E0 ldx #$E0 ; oh, pick something random + 3860 50F5 READST2: + 3861 50F5 20 0A 51 jsr CHECK_JOYBTN ; check the joystick button + 3862 50F8 CA dex + 3863 50F9 D0 FA bne READST2 + 3864 50FB 68 pla ; get x back + 3865 50FC AA tax ; got it + 3866 50FD AD 82 C0 lda RDROM ; bring ROM back + 3867 5100 20 1E FB jsr MPREAD ; NOW do the read + 3868 5103 AD 83 C0 lda BNK2SET ; back to RAM + 3869 5106 AD 83 C0 lda BNK2SET ; back to RAM + 3870 5109 60 rts + 3871 510A CHECK_JOYBTN: + 3872 510A A5 58 lda MOUSEF ; check which kind to move + 3873 510C 10 03 bpl DO_JBTN ; no joystick, check mouse + 3874 510E 4C 30 50 jmp CHK_MOUSE ; then do the mouse + 3875 5111 DO_JBTN: + 3876 5111 AD 61 C0 lda APKEY1 ; get joystick button + 3877 5114 CHK_BTN: + 3878 5114 30 03 bmi READST3 ; button down + 3879 5116 8D F1 50 sta JB_STATE ; show button went up + 3880 5119 READST3: + 3881 5119 4D F1 50 eor JB_STATE ; toggle previous state + 3882 511C 8D 13 03 sta MSBTNF ; set button flag + 3883 511F 60 rts + 3884 ; ---------------------------- + 3885 ; FETCH ASCII KEYCODE INTO [A] + 3886 ; ---------------------------- + Tue Jun 13 1989 11:42 Page 58 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3887 ; EXIT: ASCII IN [A] & [IOCHAR] + 3888 + 3889 5120 GETKEY: + 3890 5120 A9 03 lda #BLINK_RATE ; flag as wait for good key + 3891 5122 8D 81 4F sta CURCOUNT ; clear blinker + 3892 5125 A5 58 lda MOUSEF ; is there a mouse/joystick? + 3893 5127 F0 03 beq GTK0 ; nope + 3894 5129 20 E3 62 jsr MSCON ; turn on mouse cursor + 3895 512C GTK0: + 3896 512C A9 00 lda #0 ; clear line counter + 3897 512E 85 AB sta LINCNT ; okay, we did + 3898 5130 8A txa ; SAVE [X] & [Y] + 3899 5131 48 pha + 3900 5132 98 tya + 3901 5133 48 pha + 3902 5134 GKEY0: + 3903 5134 E6 A5 inc RAND+HI ; just whack on random number + 3904 5136 C6 A4 dec RAND+LO ; and more + 3905 5138 20 D5 4F jsr FKEYX ; is there a key? + 3906 513B 30 23 bmi GKEY01 ; got the key + 3907 + 3908 513D 20 16 4F jsr WAIT10 ; wait .1 seconds, moving mouse cursor + 3909 + 3910 5140 A5 58 lda MOUSEF ; do we have a joystick/mouse? + 3911 5142 F0 0D beq GKEY02 ; nope + 3912 5144 AD D2 6C lda PTR_COUNT ; count down counter? + 3913 5147 F0 05 beq GKEY00 ; nope + 3914 5149 CE D2 6C dec PTR_COUNT ; count one wait cycle + 3915 514C D0 03 bne GKEY02 ; don't check yet + 3916 514E GKEY00: + 3917 514E 20 0A 51 jsr CHECK_JOYBTN ; check the joystick button, just fur the heckuvit + 3918 5151 GKEY02: + 3919 5151 CE 81 4F dec CURCOUNT ; down one + 3920 5154 D0 DE bne GKEY0 ; no toggle + 3921 5156 20 82 4F jsr STCUR ; okay, toggle + 3922 5159 A9 03 lda #BLINK_RATE ; 1 per second + 3923 515B 8D 81 4F sta CURCOUNT ; okay + 3924 515E D0 D4 bne GKEY0 ; check for key + 3925 5160 GKEY01: + 3926 5160 48 pha ; save char + 3927 5161 A5 58 lda MOUSEF ; any mouse cursor? + 3928 5163 F0 03 beq GTK1 ; nope + 3929 5165 20 84 62 jsr MSCOFF ; turn mouse cursor off + 3930 5168 GTK1: + 3931 5168 68 pla ; get char back + 3932 5169 20 AD 4F jsr ERCUR ; so erase cursor + 3933 516C CHKKEY: + 3934 516C 20 7A 51 jsr PARSEKEY ; how was the key? + 3935 516F B0 C3 bcs GKEY0 ;TRY AGAIN + 3936 5171 85 AC sta IOCHAR ;HOLD ON TO IT + 3937 5173 68 pla ; RESTORE + 3938 5174 A8 tay ; EVERYTHING + 3939 5175 68 pla + 3940 5176 AA tax + 3941 5177 A5 AC lda IOCHAR ; GET CHAR INTO [A] + 3942 5179 60 rts ; AND RETURN IT + 3943 + 3944 ; + 3945 ; CHECK TO MAKE SURE KEY IS VALID, ONLY ACCEPT IT IF IT IS + 3946 ; + 3947 517A PARSEKEY: + 3948 517A 29 7F and #$7F ;SCREEN OUT SHIFTS + 3949 ; + 3950 ;CHECK FOR "ARROWS" & FUNCTION KEYS (X), CONVERT FOR USE (EZIP) + 3951 ;ALSO : CHANGE <_>)@%^&*( TO ,-.0256789 - and 'mouse' clicks + 3952 ; and other kinds of special chars + 3953 ; + 3954 517C GK0: + 3955 517C A2 12 ldx #ENDKEY ; GET LENGTH OF LIST + 3956 517E GK2: + 3957 517E DD C3 51 cmp HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + 3958 5181 F0 05 beq GK3 ; FOUND IT + 3959 5183 CA dex + 3960 5184 10 F8 bpl GK2 ; CHECK THEM ALL + 3961 5186 30 05 bmi GK4 ; NOT FOUND, CONTINUE OTHER CHECKS + Tue Jun 13 1989 11:42 Page 59 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3962 5188 GK3: + 3963 5188 BD D6 51 lda WANT,X ; GET KEY TO USE INSTEAD + 3964 518B 18 clc ; show niceness + 3965 518C 60 rts ; done + 3966 518D GK4: + 3967 518D C9 20 cmp #SPACE ; NO CTRL CHARS ACCEPTABLE + 3968 518F 90 14 bcc BADKEY ; IF < SPACE, BAD + 3969 + 3970 5191 C9 3C cmp #'<' ; pick up numbers and most punctuation + 3971 5193 90 15 bcc OK ; we did + 3972 + 3973 5195 C9 7B cmp #'z'+1 ;PICK OUT LETTERS NOW + 3974 5197 B0 0C bcs BADKEY ;IF > BAD + 3975 5199 C9 61 cmp #'a' + 3976 519B B0 0D bcs OK ;IF > OK + 3977 519D C9 41 cmp #'A' + 3978 519F 90 04 bcc BADKEY + 3979 51A1 C9 5B CMP #'Z'+1 + 3980 51A3 90 05 BCC OK ;IF < OK + 3981 51A5 BADKEY: + 3982 51A5 20 B3 4E jsr BEEP ;BAD KEY, GIVE WARNING NOISE, gwon back + 3983 51A8 38 sec ; show badness + 3984 51A9 60 rts ; and done + 3985 51AA OK: + 3986 51AA C9 30 cmp #'0' ; check for number keys + 3987 51AC 90 13 bcc OKj ; nope, < 0 + 3988 51AE C9 3A cmp #'9'+1 ; more than a nine? + 3989 51B0 B0 0F bcs OKj ; ayyup + 3990 ; + 3991 ; here we check for the closed apple key being down too + 3992 ; + 3993 51B2 AE 62 C0 ldx APKEY2 ; how about the closed apple key + 3994 51B5 10 0A bpl OKj ; not pressed, so use as number key + 3995 ; + 3996 ; transform number key into a function key + 3997 ; + 3998 51B7 18 CLC ; get ready for add + 3999 51B8 69 54 ADC #84 ; transforms '1'-'9' to 133-141 + 4000 51BA C9 84 CMP #132 ; but '0' wants to be a 142! + 4001 51BC D0 03 BNE OKj ; but it's not it + 4002 51BE 18 CLC ; again, don't want carry + 4003 51BF 69 0A ADC #10 ; voila! + 4004 51C1 OKj: + 4005 51C1 18 clc ; show a wicked good character is about to arrive + 4006 51C2 60 rts ; toots finis + 4007 + 4008 51C3 0B 0A 08 15 7F HAVE: DB $0B,$0A,$08,$15,$7f,ESCAPE,$3C,$7C,$3F + 51C8 1B 3C 7C 3F + 4009 51CC 3C 5F 3E 40 25 DB $3C,$5F,$3E,$40,$25,$5E,$26,$01,$02, EOL + 51D1 5E 26 01 02 0D + 4010 51D6 81 82 83 84 08 WANT: DB 129,130,131,132,08,ESCAPE,$3C,$7C,$3F + 51DB 1B 3C 7C 3F + 4011 51DF 2C 2D 2E 32 35 DB $2C,$2D,$2E,$32,$35,$36,$37,254,253, EOL + 51E4 36 37 FE FD 0D + 4012 0012 ENDKEY EQU $-WANT-1 + 4013 + 4014 51E9 END + 4015 + 4016 51E9 INCLUDE IO.ASM + 4017 51E9 STTL "--- GAME I/O: APPLE II ---" + 4018 PAGE + Tue Jun 13 1989 11:42 Page 60 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4019 + 4020 ; -------------- + 4021 ; INTERNAL ERROR + 4022 ; -------------- + 4023 ; ENTRY: ERROR CODE IN [A] + 4024 ; EXIT: HA! + 4025 + 4026 51E9 0D 49 6E 74 65 ERRM: DB EOL,"Internal error " + 51EE 72 6E 61 6C 20 + 51F3 65 72 72 6F 72 + 51F8 20 + 4027 0010 ERRML EQU $-ERRM + 4028 + 4029 51F9 ZERROR: + 4030 51F9 48 pha ; save err number + 4031 51FA 20 99 4C jsr SWAP2INFOW ; go to the info window (window 0)` + 4032 51FD DLINE ERRM ; print message + 4033 51FD A2 E9 ldx #ERRM ; get other part of string + 4035 [01] IFMA 2 ; check to see if length passed in + 4036 ldy ; then just fetch it + 4037 [01] ELSE + 4038 5201 A0 10 ldy #ERRML ; get length of string + 4039 [00] ENDIF + 4040 5203 20 5B 4C jsr DLINE ; print the string + 4041 5206 .MACEND + 4042 5206 68 pla ; get error number + 4043 5207 20 C3 47 jsr HEXNUM ; print error number + 4044 520A 4C 10 52 jmp ZQUIT1 ; and die + 4045 + 4046 + 4047 ; ---- + 4048 ; QUIT + 4049 ; ---- + 4050 + 4051 520D 20 E9 54 ZQUIT: JSR ZCRLF ; FLUSH BUFFER + 4052 5210 ZQUIT1: + 4053 5210 DLINE ENDM ; print ending message + 4054 5210 A2 7B ldx #ENDM ; get other part of string + 4056 [01] IFMA 2 ; check to see if length passed in + 4057 ldy ; then just fetch it + 4058 [01] ELSE + 4059 5214 A0 10 ldy #ENDML ; get length of string + 4060 [00] ENDIF + 4061 5216 20 5B 4C jsr DLINE ; print the string + 4062 5219 .MACEND + 4063 5219 20 0D 8D jsr GETRET ; wait for + 4064 521C A5 59 lda INFODOS ; in dinky-dos? + 4065 521E F0 17 beq ZQUIT2 ; nope + 4066 5220 A9 00 lda #0 ; clear power up byte + 4067 5222 8D F4 03 sta $3F4 ; make it do cold boot + 4068 5225 AD FD FF lda RESET_VECTOR+HI ; now, set up where to die to + 4069 5228 8D 36 52 sta ZQUITR1+2 + 4070 522B AD FC FF lda RESET_VECTOR+LO + 4071 522E 8D 35 52 sta ZQUITR1+1 + 4072 5231 AD 82 C0 lda RDROM ; get ROM back + 4073 5234 ZQUITR1: + 4074 5234 4C FC FF jmp RESET_VECTOR ; just reset things + 4075 ; + 4076 ; re-enable /RAM + 4077 ; + 4078 5237 ZQUIT2: + 4079 5237 AE 31 BF ldx DEVCNT ; put device in at end + 4080 523A E8 inx ; point to one past end + 4081 523B 8E 31 BF stx DEVCNT ; show new count + 4082 523E A9 BF lda #$BF ; /RAM ID + 4083 5240 9D 32 BF sta DEVNUM,X ; save it + 4084 5243 AD 7F 07 lda OLDVEC+HI ; restore old vector + 4085 5246 8D 27 BF sta RAMVEC+HI + 4086 5249 AD 7E 07 lda OLDVEC+LO + 4087 524C 8D 26 BF sta RAMVEC+LO + 4088 ; + 4089 ; now format /RAM + 4090 ; + Tue Jun 13 1989 11:42 Page 61 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4091 524F A9 03 lda #3 ; stash into FORMAT parm block + 4092 5251 85 42 sta $42 ; it goes here, oddly enough + 4093 5253 A9 B0 lda #$B0 ; device id for /RAM + 4094 5255 85 43 sta $43 ; and here it goes + 4095 5257 A9 11 lda #>GAME1FIO ; IO buffer + 4096 5259 85 45 sta $45 ; this is where it goes + 4097 525B A9 00 lda #BOOTNAME + 4141 52B1 8D C8 45 sta OPEN_FILE+OP_PATHNAME+HI + 4142 52B4 A9 31 lda #'1' ; set disk name to disk #1 + 4143 52B6 8D B5 49 sta SAVENUM ; show open_gamef + 4144 52B9 20 12 4B jsr OPEN_GAMEF ; okay + 4145 + 4146 52BC AD CB 45 lda OPEN_FILE+OP_REFNUM ; get ref num + 4147 52BF 8D 8C 52 sta BOOT_RD+RD_REFNUM ; save ref num + 4148 52C2 8D 35 8B sta CLOSE_PB+CL_REFNUM + 4149 52C5 READ BOOT_RD ; read in boot system + 4150 52C5 PRODOS $CA, BOOT_RD + 4151 52C5 20 00 BF jsr $BF00 ; ProDOS handler + 4152 52C8 CA DB $CA ; ProDOS function code + 4153 52C9 8B52 DW BOOT_RD ; Function Parameter Block address + 4154 52CB .MACEND + 4155 52CB .MACEND + 4156 52CB 90 03 bcc ZSTRTX ; okay, everything is fine + 4157 52CD 4C 64 47 jmp DISK_FATAL ; die otherwise + 4158 52D0 ZSTRTX: + 4159 52D0 CLOSE CLOSE_PB ; and close it up + Tue Jun 13 1989 11:42 Page 62 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4160 52D0 PRODOS $CC, CLOSE_PB + 4161 52D0 20 00 BF jsr $BF00 ; ProDOS handler + 4162 52D3 CC DB $CC ; ProDOS function code + 4163 52D4 348B DW CLOSE_PB ; Function Parameter Block address + 4164 52D6 .MACEND + 4165 52D6 .MACEND + 4166 52D6 4C 00 20 jmp BORG ; and go to it + 4167 52D9 + 4168 ; -------------------------------- + 4169 ; RETURN RANDOM BYTES IN [A] & [X] + 4170 ; -------------------------------- + 4171 52D9 RANDOM: + 4172 52D9 E6 A5 inc RAND+HI + 4173 52DB C6 A4 dec RAND+LO + 4174 52DD A5 A4 lda RAND+LO ; get LSB + 4175 52DF 65 A5 adc RAND+HI ; add MSB + 4176 52E1 29 7F and #$7F ; don't let it go into $C0 page + 4177 52E3 85 A5 sta RAND+HI ; new MSB + 4178 52E5 A8 tay ; get random offset + 4179 52E6 B1 A4 lda (RAND),Y ; get random number + 4180 52E8 AA tax ; save in X + 4181 52E9 65 A4 adc RAND+LO ; and go to another spot + 4182 52EB 29 7F and #$7F ; don't go above $80 + 4183 52ED 85 A5 sta RAND+HI ; okay + 4184 52EF A8 tay ; more randomness + 4185 52F0 B1 A4 lda (RAND),Y ; and get it again + 4186 52F2 05 A5 ora RAND+HI ; set more bits + 4187 52F4 60 rts + 4188 + 4189 + 4190 ; ------------------- + 4191 ; Z-PRINT A CHARACTER + 4192 ; ------------------- + 4193 ; ENTRY: ASCII CHAR IN [A] + 4194 ; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, + 4195 ; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN + 4196 ; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME + 4197 ; (DIROUT CHANGES 6/24/85) + 4198 + 4199 52F5 COUT: + 4200 52F5 85 AC sta IOCHAR ; HOLD IT A SEC + 4201 52F7 A6 B2 ldx TABLEF ; OUTPUT TO TABLE? + 4202 52F9 F0 07 beq COUT1 ; NO + 4203 52FB A6 19 ldx FMTTBL ; formatted table? + 4204 52FD D0 0D bne COUT5 ; yes, so just do it normal + 4205 52FF 4C 77 53 jmp TBLOUT ; just put into table + 4206 5302 COUT1: + 4207 5302 A6 B1 ldx SCREENF ; OUTPUT TO SCREEN? + 4208 5304 D0 06 bne COUT5 ; YES + 4209 5306 AE A1 6C ldx SCRIPTF ; OUTPUT TO PRINTER? + 4210 5309 D0 01 bne COUT5 ; YES + 4211 530B 60 rts ; NO, SO DONE + 4212 530C COUT5: + 4213 530C A5 AC lda IOCHAR ; RETRIEVE CHAR + 4214 530E 30 5D bmi COUT2 ; highlight chars have no width + 4215 ; + 4216 ; this is an entry point for DLINE, so it doesn't check any of the above + 4217 ; things. Enter with character in [A] + 4218 ; + 4219 5310 DIRECT_OUT: + 4220 5310 C9 0D cmp #EOL ; IF ASCII EOL, just handle it special + 4221 5312 D0 03 bne COUT0 + 4222 + 4223 5314 4C E9 54 jmp ZCRLF ; DO IT + 4224 5317 COUT0: + 4225 5317 B0 20 bcs COUT02 ; not control character + 4226 5319 C9 0B cmp #EOS ; control-k (end of sentence)? + 4227 531B F0 0E beq COUT01 ; yes, so put out 2 spaces + 4228 531D C9 09 cmp #TAB ; tab char? + 4229 531F D0 55 bne CEX ; ignore all other control chars + 4230 ; + 4231 ; this means do a couple of spaces + 4232 ; + 4233 5321 A9 20 lda #SPACE ; do 3 spaces for start of line + 4234 5323 20 F5 52 jsr COUT ; a little recursion never hurt! + Tue Jun 13 1989 11:42 Page 63 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4235 5326 A6 A9 ldx CHRCNT ; back to beginning of line? + 4236 5328 D0 01 bne COUT01 ; nope + 4237 532A COUT010: + 4238 532A 60 rts ; don't do any to start line + 4239 532B COUT01: + 4240 532B A9 20 lda #SPACE ; 2 more spaces + 4241 532D 20 F5 52 jsr COUT + 4242 5330 A6 A9 ldx CHRCNT ; back to zero? + 4243 5332 F0 F6 beq COUT010 ; yes, so don't add to start of line + 4244 + 4245 5334 A9 20 lda #SPACE ; last one + 4246 5336 4C F5 52 jmp COUT ; finally + 4247 5339 COUT02: + 4248 5339 AA tax ; use char as index + 4249 533A A5 C1 lda FONTFLG ; get which font we be using + 4250 533C F0 04 beq COUTF1 ; must be variable width + 4251 533E A9 0C lda #MONOFONT_W ; get width then of mono font + 4252 5340 D0 03 bne COUTF2 ; okay, now do add + 4253 5342 COUTF1: + 4254 5342 BD 53 64 lda CHWID,X ; get width of char + 4255 5345 COUTF2: + 4256 5345 18 clc ; get ready for add + 4257 5346 65 A7 adc LENGTH+LO ; ADD LINE LENGTH COUNTER + 4258 5348 85 A7 sta LENGTH+LO ; update length + 4259 534A 90 02 bcc COUT0C ; no wrap + 4260 534C E6 A8 inc LENGTH+HI ; okay, wrap then + 4261 534E COUT0C: + 4262 534E A5 A8 lda LENGTH+HI ; get MSB + 4263 5350 C5 A3 cmp XSIZE+HI ; check MSB first + 4264 5352 90 19 bcc COUT2 ; no need to check lsb + 4265 5354 D0 08 bne COUT00 ; XSIZE < LENGTH? + 4266 5356 + 4267 5356 A5 A7 lda LENGTH+LO ; check LSB + 4268 5358 C5 A2 cmp XSIZE+LO ; END OF SCREEN LINE? + 4269 535A 90 11 bcc COUT2 ; haven't reached the end if XSIZE >= LENGTH + 4270 535C F0 0F beq COUT2 ; okay + 4271 535E COUT00: + 4272 535E AC 04 72 ldy WRPFLG ; are we wrapping + 4273 5361 F0 13 beq CEX ; no, so truncate + 4274 5363 A6 A9 ldx CHRCNT ; get character count + 4275 5365 A5 AC lda IOCHAR ; get the character + 4276 5367 9D 00 02 sta LBUFF,X ; save current char in buffer + 4277 536A 4C 71 54 jmp FLUSH ; YES, FLUSH THE LINE + 4278 536D COUT2: + 4279 536D A6 A9 ldx CHRCNT ; GET LINE POINTER + 4280 536F A5 AC lda IOCHAR ; get char back + 4281 5371 9D 00 02 sta LBUFF,X ; ADD CHAR TO BUFFER + 4282 5374 E6 A9 inc CHRCNT ; and point to next CHRCNT + 4283 5376 CEX: + 4284 5376 60 rts + 4285 5377 + 4286 ; --------------- + 4287 ; OUTPUT TO TABLE + 4288 ; --------------- + 4289 ; + 4290 ; this one just puts a char into the table + 4291 ; + 4292 5377 TBLOUT: + 4293 5377 AA tax ; HOLD CHAR A SEC. + 4294 ; + 4295 ; figger out length of line in there + 4296 ; + 4297 5378 A5 C1 lda FONTFLG ; get which font we be using + 4298 537A F0 04 beq TBLOUT1 ; must be variable width + 4299 537C A9 0C lda #MONOFONT_W ; get width then of mono font + 4300 537E D0 03 bne TBLOUT2 ; okay, now do add + 4301 5380 TBLOUT1: + 4302 5380 BD 53 64 lda CHWID,X ; get width of char + 4303 5383 TBLOUT2: + 4304 5383 18 clc ; add width + 4305 5384 6D 31 96 adc ZBEGIN+ZTWIDTH+1 ; to current line width + 4306 5387 8D 31 96 sta ZBEGIN+ZTWIDTH+1 ; save current width + 4307 538A 90 03 bcc TBLOUT3 ; no wrap + 4308 538C EE 30 96 inc ZBEGIN+ZTWIDTH+0 ; wrap, then dammit + 4309 538F TBLOUT3: + Tue Jun 13 1989 11:42 Page 64 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4310 ; + 4311 ; PUT BYTE IN TABLE AT CURRENT OFFSET + 4312 ; + 4313 538F AD AE 6C lda DIRITM+LO ; ADD IN OFFSET + 4314 5392 18 clc + 4315 5393 65 A0 adc DIRTBL+LO + 4316 5395 85 8F sta SPCL ; and make it lo part + 4317 5397 AD AF 6C lda DIRITM+HI + 4318 539A 65 A1 adc DIRTBL+HI + 4319 539C 20 A9 8F jsr SETPC ; set the PC + 4320 539F 85 90 sta SPCH ; and this is high part + 4321 53A1 84 91 sty SPCBNK ; and the bank + 4322 53A3 8A txa ; PICK UP ASCII CHAR + 4323 53A4 20 67 92 jsr STASHB ; and save it + 4324 ; + 4325 ; SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER + 4326 ; + 4327 53A7 EE AE 6C inc DIRITM+LO ; INC OFFSET TO NEXT BYTE + 4328 53AA D0 03 bne TBLRTS + 4329 53AC EE AF 6C inc DIRITM+HI + 4330 53AF TBLRTS: + 4331 53AF 60 rts + 4332 ; + 4333 ; PUT LBUFF IN TABLE AT CURRENT OFFSET + 4334 ; + 4335 53B0 TBLRTN: + 4336 53B0 AD AE 6C lda DIRITM+LO ; get where we are + 4337 53B3 18 clc + 4338 53B4 65 A0 adc DIRTBL+LO ; add in offset + 4339 53B6 85 8F sta SPCL ; and make it lo part + 4340 53B8 85 8C sta FPCL ; save for later usage + 4341 53BA AD AF 6C lda DIRITM+HI ; get hi part + 4342 53BD 65 A1 adc DIRTBL+HI + 4343 53BF 20 A9 8F jsr SETPC ; set the PC + 4344 53C2 85 90 sta SPCH ; and this is high part + 4345 53C4 85 8D sta FPCH ; saving + 4346 53C6 84 91 sty SPCBNK ; and the bank + 4347 53C8 84 8E sty FPCBNK ; and here too + 4348 53CA A9 00 lda #0 ; start counter off at zero + 4349 53CC 85 7A sta J ; use J + 4350 53CE 85 7D sta K+HI ; this will be line length + 4351 53D0 85 7C sta K+LO ; both parts, please + 4352 53D2 20 D0 8F jsr NEXTSPC ; point past the (word) counter + 4353 53D5 20 D0 8F jsr NEXTSPC ; point past the counter + 4354 53D8 TBLOOP: + 4355 53D8 A4 7A ldy J ; get offset + 4356 53DA B9 00 02 lda LBUFF,Y ; get char + 4357 53DD AA tax ; save char + 4358 53DE 30 19 bmi TBLP1 ; don't count hi light chars + 4359 53E0 C9 20 cmp #SPACE ; see if less than a space + 4360 53E2 90 15 bcc TBLP1 ; no width if <$20 + 4361 53E4 AA tax ; use char as index + 4362 + 4363 53E5 A5 C1 lda FONTFLG ; get which font we be using + 4364 53E7 F0 04 beq TBLF1 ; must be variable width + 4365 53E9 A9 0C lda #MONOFONT_W ; get width then of mono font + 4366 53EB D0 03 bne TBLF2 ; okay, now do add + 4367 53ED TBLF1: + 4368 53ED BD 53 64 lda CHWID,X ; get width of char + 4369 53F0 TBLF2: + 4370 53F0 18 clc ; add width + 4371 53F1 65 7C adc K+LO ; to current line width + 4372 53F3 85 7C sta K+LO ; save current width + 4373 53F5 90 02 bcc TBLP1 ; no wrap + 4374 53F7 E6 7D inc K+HI ; wrap, then dammit + 4375 53F9 TBLP1: + 4376 53F9 8A txa ; get char back + 4377 53FA 20 67 92 jsr STASHB ; and save it + 4378 53FD 20 D0 8F jsr NEXTSPC ; next table entry + 4379 5400 E6 7A inc J ; point to next char + 4380 5402 C6 A9 dec CHRCNT ; decrement counter + 4381 5404 D0 D2 bne TBLOOP ; get next one + 4382 ; + 4383 ; now fill with necessary spaces + 4384 ; + Tue Jun 13 1989 11:42 Page 65 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4385 5406 A5 C1 lda FONTFLG ; first, set up width to be added + 4386 5408 F0 04 beq TBLSPF1 ; must be variable width font + 4387 540A A9 0C lda #MONOFONT_W ; get mono width + 4388 540C D0 05 bne TBLSPF2 ; okay + 4389 540E TBLSPF1: + 4390 540E A2 20 ldx #SPACE ; get space index + 4391 5410 BD 53 64 lda CHWID,X ; okay + 4392 5413 TBLSPF2: + 4393 5413 85 71 sta ARG8 ; use temporarily + 4394 5415 TBLSP: + 4395 5415 A5 7C lda K+LO ; get how big line is + 4396 5417 18 clc ; add in space + 4397 5418 65 71 adc ARG8 ; pick up space width + 4398 541A 85 7C sta K+LO ; saved + 4399 541C 90 02 bcc TBLSP1 ; no wrap? + 4400 541E E6 7D inc K+HI ; yes, wrapping + 4401 5420 TBLSP1: + 4402 5420 A5 A3 lda XSIZE+HI ; check against end + 4403 5422 C5 7D cmp K+HI ; compare against max width + 4404 5424 90 14 bcc TBLSPX ; all done then + 4405 5426 D0 06 bne TBLSP2 ; no need to check if <> + 4406 5428 A5 A2 lda XSIZE+LO ; check LSB + 4407 542A C5 7C cmp K+LO ; well? + 4408 542C 90 0C bcc TBLSPX ; all done then + 4409 542E TBLSP2: + 4410 542E A9 20 lda #SPACE ; get it + 4411 5430 20 67 92 jsr STASHB ; save it + 4412 5433 20 D0 8F jsr NEXTSPC ; point to next one + 4413 5436 E6 7A inc J ; count it + 4414 5438 D0 DB bne TBLSP ; and continue + 4415 543A TBLSPX: + 4416 543A A9 00 lda #0 ; show end of table + 4417 543C 85 A7 sta LENGTH+LO ; clear out line length too + 4418 543E 85 A8 sta LENGTH+HI ; and hi part too + 4419 5440 20 67 92 jsr STASHB ; marked with a zero + 4420 5443 20 D0 8F jsr NEXTSPC ; point to LSB of next count + 4421 5446 A9 00 lda #0 ; and stash another zero there + 4422 5448 20 67 92 jsr STASHB ; away it goes + 4423 544B 20 A5 90 jsr FP2SP ; have SPC point to beginning + 4424 544E A9 00 lda #0 ; upper byte of count is zero + 4425 5450 20 67 92 jsr STASHB ; show it + 4426 5453 20 D0 8F jsr NEXTSPC ; point to LSB + 4427 5456 A5 7A lda J ; get how many chars are there + 4428 5458 20 67 92 jsr STASHB ; save at beginning of line + 4429 545B E6 7A inc J ; count (word) counter in offset + 4430 545D E6 7A inc J ; count counter in offset + 4431 545F A5 7A lda J ; get J back + 4432 5461 18 clc ; add in where we were + 4433 5462 6D AE 6C adc DIRITM+LO ; okay with lo part + 4434 5465 8D AE 6C sta DIRITM+LO ; save it + 4435 5468 AD AF 6C lda DIRITM+HI ; and now the hi part + 4436 546B 69 00 adc #0 ; pick up carry, maybe + 4437 546D 8D AF 6C sta DIRITM+HI ; and save it + 4438 5470 60 rts + 4439 + 4440 ; ------------------- + 4441 ; FLUSH OUTPUT BUFFER + 4442 ; ------------------- + 4443 ; ENTRY: LENGTH OF BUFFER IN [X] + 4444 + 4445 5471 FLUSH: + 4446 5471 8A txa ; is it zero? + 4447 5472 D0 01 bne FL00 ; nope + 4448 5474 60 rts ; just ignore if only one character + 4449 5475 FL00: + 4450 5475 A9 20 lda #SPACE ; SPACE CHAR + 4451 5477 8E 91 6C stx OLDEND ; SAVE CURRENT END OF LINE + 4452 547A FL0: + 4453 547A DD 00 02 cmp LBUFF,X ; FIND LAST SPACE CHAR + 4454 547D F0 06 beq FL1 ; IN THE LINE + 4455 547F CA dex + 4456 5480 D0 F8 bne FL0 ; IF NONE FOUND, + 4457 5482 A6 A9 ldx CHRCNT ; FLUSH ENTIRE LINE + 4458 5484 CA dex ; minus last one + 4459 5485 FL1: + Tue Jun 13 1989 11:42 Page 66 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4460 5485 8E 90 6C stx OLDLEN ; SAVE OLD LINE POS HERE + 4461 5488 86 A9 stx CHRCNT ; MAKE IT THE NEW LINE LENGTH + 4462 548A + 4463 548A A5 B2 lda TABLEF ; are we doing table I/O? + 4464 548C F0 06 beq FL11 ; nope + 4465 548E 20 B0 53 jsr TBLRTN ; YES, DO IT + 4466 5491 4C 97 54 jmp FL12 ; so refill line + 4467 5494 FL11: + 4468 5494 20 E9 54 jsr ZCRLF ; PRINT LINE UP TO LAST SPACE + 4469 ; + 4470 ; START NEW LINE WITH REMAINDER OF OLD + 4471 ; + 4472 5497 FL12: + 4473 5497 AE 90 6C ldx OLDLEN ; GET OLD LINE POS + 4474 549A A0 00 ldy #0 ; START NEW LINE AT BEGINNING + 4475 549C FL2: + 4476 549C E8 inx + 4477 549D EC 91 6C cpx OLDEND ; CONTINUE IF + 4478 54A0 90 05 bcc FL3 ; INSIDE of end of line + 4479 54A2 F0 03 beq FL3 ; or at end of line + 4480 54A4 84 A9 sty CHRCNT + 4481 54A6 60 rts + 4482 54A7 FL3: + 4483 54A7 BD 00 02 lda LBUFF,X ; GET CHAR FROM OLD LINE + 4484 54AA C9 20 cmp #SPACE ; don't move start spaces in either + 4485 54AC F0 25 beq FL4 ; fine, I won't + 4486 54AE 99 00 02 sta LBUFF,Y ; MOVE TO START OF NEW LINE + 4487 54B1 30 20 bmi FL4 ; don't count hi light chars + 4488 54B3 C9 20 cmp #SPACE ; don't count control chars + 4489 54B5 90 1C bcc FL4 ; okay + 4490 54B7 8A txa ; save current x + 4491 54B8 48 pha ; saved + 4492 54B9 A5 C1 lda FONTFLG ; get which font we be using + 4493 54BB F0 04 beq FLSF1 ; must be variable width + 4494 54BD A9 0C lda #MONOFONT_W ; get width then of mono font + 4495 54BF D0 07 bne FLSF2 ; okay, now do add + 4496 54C1 FLSF1: + 4497 54C1 BD 00 02 lda LBUFF,X ; get char back + 4498 54C4 AA tax ; make index + 4499 54C5 BD 53 64 lda CHWID,X ; get width of char + 4500 54C8 FLSF2: + 4501 54C8 18 clc ; get ready for add + 4502 54C9 65 A7 adc LENGTH+LO ; okay, now add char width + 4503 54CB 85 A7 sta LENGTH+LO ; save new length + 4504 54CD 68 pla ; get old X back + 4505 54CE AA tax ; okay + 4506 54CF 90 02 bcc FL4 ; no wrap + 4507 54D1 E6 A8 inc LENGTH+HI + 4508 54D3 FL4: + 4509 54D3 C8 iny ; UPDATE # OF chars in NEW LINE + 4510 54D4 D0 C6 bne FL2 ; (ALWAYS) + 4511 + 4512 + 4513 ; --------------- + 4514 ; CARRIAGE RETURN + 4515 ; --------------- + 4516 + 4517 54D6 ZZCRLF: + 4518 54D6 A6 B2 ldx TABLEF ; OUTPUT TO TABLE? + 4519 54D8 F0 0F beq ZCRLF ; NO + 4520 ; + 4521 ; if putting a into table, just add to line buffer and flush + 4522 ; + 4523 54DA A9 0D lda #EOL ; get carriage return char + 4524 54DC A4 A9 ldy CHRCNT ; add to lbuff + 4525 54DE 99 00 02 sta LBUFF,Y ; got it + 4526 54E1 E6 A9 inc CHRCNT ; now flush it + 4527 54E3 20 B0 53 jsr TBLRTN ; YES, DO IT (TBL ONLY) + 4528 54E6 4C 5F 55 jmp ZCRLFX ; git out + 4529 54E9 ZCRLF: + 4530 54E9 A6 A9 ldx CHRCNT ; how far have we gone + 4531 54EB A9 0D lda #EOL ; get carriage return char + 4532 54ED 9D 00 02 sta LBUFF,X ; END OF CURRENT LINE + 4533 54F0 E6 A9 inc CHRCNT ; UPDATE LINE LENGTH + 4534 54F2 20 68 55 jsr LINOUT ; DISPLAY LINE + Tue Jun 13 1989 11:42 Page 67 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4535 + 4536 ; + 4537 ; now check about line count + 4538 ; + 4539 54F5 A9 00 lda #0 + 4540 54F7 85 A9 sta CHRCNT ; AND RESET LINE COUNT + 4541 54F9 85 A7 sta LENGTH+LO ; okay + 4542 54FB 85 A8 sta LENGTH+HI ; okay + 4543 + 4544 54FD 20 8D 55 jsr CHKFNC ; CHECK FOR CR FUNCTION (XZIP) + 4545 + 4546 5500 A5 B1 lda SCREENF ; CHECK IF DISPLAYING TO SCREEN + 4547 5502 F0 5B beq ZCRLFX ; NO, GO HANDLE IF PRINTING + 4548 5504 AD 05 72 lda SCRLFLG ; is it a scrolling window? + 4549 5507 F0 56 beq ZCRLFX ; nope, so no more + 4550 5509 E6 AB inc LINCNT ; NEW LINE GOING OUT + 4551 + 4552 550B A6 AB ldx LINCNT ; IS IT TIME TO + 4553 550D E4 03 cpx MAXLINES ; PRINT "MORE" YET? + 4554 550F 90 4E bcc ZCRLFX ; NO, CONTINUE + 4555 + 4556 5511 A9 01 lda #1 ; leave one line from last screen, and input line + 4557 5513 85 AB sta LINCNT ; RESET LINE COUNTER + 4558 5515 A5 04 lda LEFTMRG ; SET LEFT MARGIN + 4559 5517 85 00 sta SCRCX + 4560 5519 A9 01 lda #1 ; show cursor changed (maybe) + 4561 551B 8D A5 6C sta CURSFLG ; okay + 4562 ; + 4563 ; print [MORE] out myself, to avoid re-entrancy problems + 4564 ; + 4565 551E AD A1 6C lda SCRIPTF ; make sure we don't script + 4566 5521 48 pha + 4567 5522 A2 00 ldx #0 ; start with first char + 4568 5524 8E A1 6C stx SCRIPTF ; clear script flag + 4569 5527 86 18 stx SCLLINES ; use this as a counter + 4570 5529 MORELOOP: + 4571 5529 BD 92 5B lda MORE,X ; get char + 4572 552C 85 AC sta IOCHAR ; save it + 4573 552E 20 10 53 jsr DIRECT_OUT ; pump it out there + 4574 5531 E6 18 inc SCLLINES ; count char + 4575 5533 A6 18 ldx SCLLINES ; how many have we done + 4576 5535 E0 06 cpx #MOREL ; done? + 4577 5537 D0 F0 bne MORELOOP ; nope + 4578 + 4579 5539 20 BE 55 jsr CLRBUF ; make sure it shows + 4580 553C WAIT: + 4581 553C 20 20 51 jsr GETKEY ; wait for key please + 4582 553F A9 05 lda #MOREL-1 ; how many backspaces + 4583 5541 85 A7 sta LENGTH ; just use this as counter + 4584 5543 WM11: + 4585 5543 A6 A7 ldx LENGTH ; which char? + 4586 5545 BD 92 5B lda MORE,X ; get char + 4587 5548 AA tax ; put here for erase + 4588 5549 A9 08 lda #BACKSPACE ; erase char + 4589 554B 20 A9 5D jsr CHAR + 4590 554E C6 A7 dec LENGTH ; count it + 4591 5550 10 F1 bpl WM11 + 4592 5552 68 pla ; get script flag back + 4593 5553 8D A1 6C sta SCRIPTF ; fine + 4594 5556 A5 04 lda LEFTMRG ; move back to left margin + 4595 5558 85 00 sta SCRCX ; okay + 4596 555A A9 01 lda #1 ; show cursor changed (maybe) + 4597 555C 8D A5 6C sta CURSFLG ; okay + 4598 555F ZCRLFX: + 4599 555F A9 00 lda #0 + 4600 5561 85 A9 sta CHRCNT ; AND RESET LINE COUNT + 4601 5563 85 A7 sta LENGTH+LO ; okay + 4602 5565 85 A8 sta LENGTH+HI + 4603 5567 60 rts + 4604 5568 LINOUT: + 4605 5568 A4 A9 ldy CHRCNT ; IF BUFFER EMPTY, + 4606 556A F0 20 beq LINEX ; DON'T PRINT ANYTHING + 4607 556C 8C 97 6C sty PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + 4608 556F A5 B1 lda SCREENF ; DISPLAY TO SCREEN? + 4609 5571 D0 07 bne LOUT0 ; yes, so do it + Tue Jun 13 1989 11:42 Page 68 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4610 5573 A5 19 lda FMTTBL ; formatted table? + 4611 5575 F0 12 beq LOUT1 ; check scripting + 4612 5577 4C B0 53 jmp TBLRTN ; flush to table + 4613 557A LOUT0: + 4614 557A A2 00 ldx #0 ; SEND CONTENTS OF [LBUFF] + 4615 557C LOUT: + 4616 557C BD 00 02 lda LBUFF,X ; TO SCREEN + 4617 557F 20 A9 5D jsr CHAR + 4618 5582 E8 inx + 4619 5583 88 dey + 4620 5584 D0 F6 bne LOUT + 4621 5586 20 1A 72 jsr DISP_LINE ; make sure line gets printed + 4622 5589 20 CF 4C LOUT1: JSR PPRINT ; PRINT [LBUFF] IF ENABLED + 4623 558C LINEX: + 4624 558C 60 rts ; AND RETURN + 4625 ; + 4626 ; CHECK IF THERE IS A PENDING FUNCTION CALL ASSOCIATED WITH 'S + 4627 ; + 4628 558D CHKFNC: + 4629 558D A0 0B ldy #WINCRC+HI ; get function offset + 4630 558F B1 05 lda (WINDOW),Y ; IF NULL IGNORE + 4631 5591 88 dey ; point to lo part + 4632 5592 11 05 ora (WINDOW),Y + 4633 5594 F0 26 beq CHKOUT + 4634 + 4635 5596 AD D1 6C lda CRLF_CHECK ; do we really want to do this? + 4636 5599 F0 21 beq CHKOUT ; nope + 4637 + 4638 559B B1 05 lda (WINDOW),Y ; DECR COUNTER + 4639 559D 38 sec + 4640 559E E9 01 sbc #1 + 4641 55A0 91 05 sta (WINDOW),Y + 4642 55A2 C8 iny + 4643 55A3 B1 05 lda (WINDOW),Y ; work on hi part + 4644 55A5 E9 00 sbc #0 ; pick up carry + 4645 55A7 91 05 sta (WINDOW),Y ; save it + 4646 55A9 88 dey + 4647 55AA 11 05 ora (WINDOW),Y ; if NULL NOW, CALL FCN + 4648 55AC D0 0E bne CHKOUT + 4649 + 4650 55AE A0 08 ldy #WINCRF+LO ; pointing to routine + 4651 55B0 B1 05 lda (WINDOW),Y ; get lo part + 4652 55B2 85 7A sta J+LO ; and save in J + 4653 55B4 C8 iny ; point to hi part + 4654 55B5 B1 05 lda (WINDOW),Y ; got it + 4655 55B7 85 7B sta J+HI + 4656 55B9 20 3F 5B jsr INTCLL ; DO FUNCTION CALL + 4657 55BC CHKOUT: + 4658 55BC 60 rts + 4659 + 4660 + 4661 ; ---------------------- + 4662 ; UPDATE THE STATUS LINE + 4663 ; ---------------------- + 4664 ; NOT APPLICABLE IN EZIP. + 4665 + 4666 55BD 60 ZUSL: RTS + 4667 + 4668 ; ------ + 4669 ; BUFOUT + 4670 ; ------ + 4671 ; ENTER: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE + 4672 ; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO + 4673 ; + 4674 ; shouldn't need this in YZIP ?! + 4675 ; + 4676 55BE ZBUFOUT: + 4677 ; + 4678 ; CLEAR OUTPUT BUFFER BEFORE DOING ANYTHING FANCY + 4679 ; + 4680 55BE CLRBUF: + 4681 55BE 20 68 55 jsr LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) + 4682 55C1 A2 00 ldx #0 + 4683 55C3 86 A9 stx CHRCNT + 4684 55C5 60 rts + Tue Jun 13 1989 11:42 Page 69 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4685 + 4686 ; ------ + 4687 ; DIROUT + 4688 ; ------ + 4689 ; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT + 4690 ; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT + 4691 ; MULTIPLE DEVICE USAGE IS POSSIBLE. + 4692 + 4693 55C6 00 00 SAVEXSIZE: db 0,0 ; for formatted table saving + 4694 + 4695 55C8 ZDIRT: + 4696 55C8 20 BE 55 jsr CLRBUF ; send out anything there now! + 4697 + 4698 55CB A6 63 ldx ARG1+LO + 4699 55CD 30 0A bmi DIRRES ; NEGATIVE VALUE, DESELECTING + 4700 55CF CA dex + 4701 55D0 F0 11 beq DIR1 ; 1 = SET OUTPUT TO SCREEN + 4702 55D2 CA dex + 4703 55D3 F0 1E beq DIR2 ; 2 = SCRIPTING + 4704 55D5 CA dex + 4705 55D6 F0 3C beq DIR3 ; 3 = TABLE + 4706 55D8 60 rts ; INVALID VALUE + 4707 55D9 DIRRES: + 4708 55D9 E8 inx + 4709 55DA F0 0F beq DRES1 ; -1 = RESET TO SCREEN + 4710 55DC E8 inx + 4711 55DD F0 29 beq DRES2 + 4712 55DF E8 inx + 4713 55E0 F0 3A beq DRES3 + 4714 55E2 60 rts ; INVALID VALUE, JUST LEAVE + 4715 55E3 DIR1: + 4716 55E3 20 BE 55 jsr CLRBUF + 4717 55E6 A9 01 lda #1 ; turn screen on + 4718 55E8 85 B1 sta SCREENF + 4719 55EA 60 rts + 4720 55EB DRES1: + 4721 55EB 20 BE 55 jsr CLRBUF + 4722 55EE A9 00 lda #0 + 4723 55F0 85 B1 sta SCREENF ; 0, TURN SCREEN OFF + 4724 55F2 60 rts + 4725 55F3 DIR2: + 4726 55F3 E8 inx + 4727 55F4 8E A1 6C stx SCRIPTF ; SET SCRIPT FLAG ON + 4728 55F7 AD 11 96 lda ZBEGIN+ZFLAGS+1 ; SET GAME FLAG ALSO + 4729 55FA 09 01 ora #%00000001 + 4730 55FC 8D 11 96 sta ZBEGIN+ZFLAGS+1 + 4731 55FF AD 0B 4D lda PSTAT ; CHECK IF PRINTER ALREADY INIT'D + 4732 5602 D0 03 bne DIR2A + 4733 5604 20 21 4D jsr PCHK ; NO, GO DO IT + 4734 5607 DIR2A: + 4735 5607 60 rts ; YES, READY TO LEAVE + 4736 5608 DRES2: + 4737 5608 8E A1 6C stx SCRIPTF ; TURN PRINTER OFF + 4738 560B AD 11 96 lda ZBEGIN+ZFLAGS+1 ; AND TURN OFF GAME FLAG TOO + 4739 560E 29 FE and #%11111110 + 4740 5610 8D 11 96 sta ZBEGIN+ZFLAGS+1 + 4741 5613 60 rts + 4742 5614 DIR3: + 4743 5614 86 B1 stx SCREENF ; turn off screen + 4744 5616 E8 inx + 4745 5617 86 B2 stx TABLEF ; TURN TABLE OUTPUT FLAG ON + 4746 5619 4C 83 56 jmp START_TABLE ; and set things up + 4747 561C DRES3: + 4748 561C A5 B2 lda TABLEF ; IF OFF ALREADY + 4749 561E F0 62 beq OUT3 ; LEAVE AS IS + 4750 + 4751 5620 86 B2 stx TABLEF ; TURN TBL OUTPUT OFF + 4752 5622 E8 inx ; turn screen back on + 4753 5623 86 B1 stx SCREENF ; screen back on + 4754 + 4755 5625 A9 03 lda #3 ; add three to make it wrap + 4756 5627 18 clc ; ready for add + 4757 5628 6D 31 96 adc ZBEGIN+ZTWIDTH+1 ; do it + 4758 562B 8D 31 96 sta ZBEGIN+ZTWIDTH+1 + 4759 562E 90 03 bcc DRESCC ; no wrap into MSB + Tue Jun 13 1989 11:42 Page 70 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4760 5630 EE 30 96 inc ZBEGIN+ZTWIDTH + 4761 5633 DRESCC: + 4762 5633 4E 30 96 lsr ZBEGIN+ZTWIDTH+0 ; /4 to get # of pixels + 4763 5636 6E 31 96 ror ZBEGIN+ZTWIDTH+1 + 4764 5639 4E 30 96 lsr ZBEGIN+ZTWIDTH+0 + 4765 563C 6E 31 96 ror ZBEGIN+ZTWIDTH+1 + 4766 + 4767 + 4768 563F A5 19 lda FMTTBL ; did we do a formatted table? + 4769 5641 D0 2A bne DRESFT ; yes, so fix things + 4770 ; + 4771 ; not formatted table, so put count into table + 4772 ; + 4773 5643 A5 A0 lda DIRTBL+LO ; and put count into second byte of table + 4774 5645 85 8F sta SPCL ; points to low par + 4775 5647 A5 A1 lda DIRTBL+HI ; get page + 4776 5649 20 A9 8F jsr SETPC ; okay, page and bank + 4777 564C 85 90 sta SPCH + 4778 564E 84 91 sty SPCBNK + 4779 5650 AD AE 6C lda DIRITM+LO ; (2 LESS THAN [DIRITM]) + 4780 5653 38 sec + 4781 5654 E9 02 sbc #2 + 4782 5656 8D AE 6C sta DIRITM+LO ; save this new count + 4783 5659 B0 03 bcs RESET0 + 4784 565B CE AF 6C dec DIRITM+HI ; wrapped downwards + 4785 565E RESET0: + 4786 565E AD AF 6C lda DIRITM+HI ; get hi part + 4787 5661 20 67 92 jsr STASHB ; saved that count + 4788 5664 20 D0 8F jsr NEXTSPC ; and point to lo part + 4789 5667 AD AE 6C lda DIRITM+LO ; and get lo part + 4790 566A 4C 67 92 jmp STASHB ; and save it, and done + 4791 566D DRESFT: + 4792 566D A5 A9 lda CHRCNT ; anything in buffer? + 4793 566F F0 03 beq DRES31 ; nope + 4794 5671 20 B0 53 jsr TBLRTN ; then fill out last line + 4795 5674 DRES31: + 4796 5674 AD C6 55 lda SAVEXSIZE+LO ; get old xsize back + 4797 5677 85 A2 sta XSIZE+LO ; restored + 4798 5679 AD C7 55 lda SAVEXSIZE+HI + 4799 567C 85 A3 sta XSIZE+HI + 4800 567E A9 00 lda #0 ; reset this flag too + 4801 5680 85 19 sta FMTTBL ; cleared + 4802 5682 OUT3: + 4803 5682 60 rts + 4804 ; + 4805 ; set things up for doing table output + 4806 ; + 4807 5683 START_TABLE: + 4808 + 4809 5683 A5 66 lda ARG2+HI ; SET UP TBL + 4810 5685 85 A1 sta DIRTBL+HI + 4811 5687 A5 65 lda ARG2+LO ; TO STORE CHARS IN + 4812 5689 85 A0 sta DIRTBL+LO + 4813 568B A9 02 lda #2 + 4814 568D 8D AE 6C sta DIRITM+LO ; start at second char + 4815 5690 A9 00 lda #0 ; zero item counter + 4816 5692 8D AF 6C sta DIRITM+HI + 4817 5695 8D 31 96 sta ZBEGIN+ZTWIDTH+1 ; clear width count + 4818 5698 8D 30 96 sta ZBEGIN+ZTWIDTH+0 + 4819 ; + 4820 ; check to see if we have formatted table + 4821 ; + 4822 569B A5 62 lda NARGS ; get # of arguments + 4823 569D C9 03 cmp #3 ; if == 3, then we wrap it + 4824 569F F0 01 beq DIR30 ; nope + 4825 56A1 60 rts ; all done other wise + 4826 56A2 DIR30: + 4827 56A2 86 19 stx FMTTBL ; set formatted table flag + 4828 56A4 A5 A2 lda XSIZE+LO ; save the current XSIZE + 4829 56A6 8D C6 55 sta SAVEXSIZE+LO ; okay, did it + 4830 56A9 A5 A3 lda XSIZE+HI ; and MSB + 4831 56AB 8D C7 55 sta SAVEXSIZE+HI ; okay + 4832 56AE A5 67 lda ARG3+LO ; this is the actual amount + 4833 56B0 A6 68 ldx ARG3+HI ; get interesting arg + 4834 56B2 30 0B bmi DIRFT1 ; check for negative width + Tue Jun 13 1989 11:42 Page 71 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4835 56B4 20 87 57 jsr SETWJ ; get the window offset + 4836 56B7 A0 14 ldy #WINXSZ ; get its XSIZE + 4837 56B9 B1 7A lda (J),Y ; got it + 4838 56BB 85 A2 sta XSIZE+LO ; aren't we nice + 4839 56BD D0 06 bne DIR31 ; jump to end + 4840 56BF DIRFT1: + 4841 56BF 49 FF eor #$FF ; turn to a positive number + 4842 56C1 85 A2 sta XSIZE+LO ; save it + 4843 56C3 E6 A2 inc XSIZE+LO ; to make it right + 4844 56C5 DIR31: + 4845 56C5 A9 00 lda #0 ; items starts at zero + 4846 56C7 8D AE 6C sta DIRITM+LO ; okay + 4847 56CA 85 A3 sta XSIZE+HI ; clear out highness + 4848 56CC 06 A2 asl XSIZE+LO ; *2 + 4849 56CE 26 A3 rol XSIZE+HI + 4850 56D0 06 A2 asl XSIZE+LO ; *4 + 4851 56D2 26 A3 rol XSIZE+HI + 4852 56D4 60 rts + 4853 + 4854 ; ------ + 4855 ; CURSET + 4856 ; ------ + 4857 ; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW + 4858 ; AND AT COLUMN (ARG2) in (optional) window ARG3 + 4859 + 4860 56D5 ZCURST: + 4861 56D5 20 BE 55 jsr CLRBUF ; CLEAR OUT ANY NON DISPLAYED TEXT 1ST + 4862 56D8 A5 63 lda ARG1+LO ; see if < 0 + 4863 56DA C9 FF cmp #$FF ; -1 == turn off cursor + 4864 56DC D0 04 bne ZCURS00 ; nope + 4865 56DE A9 01 lda #1 ; show cursor off + 4866 56E0 D0 06 bne ZCURSTXX ; go do it and return + 4867 56E2 ZCURS00: + 4868 56E2 C9 FE cmp #$FE ; -2 == turn cursor on + 4869 56E4 D0 06 bne ZCURS0 ; nope, just deal with normally + 4870 56E6 A9 00 lda #0 ; show cursor not off + 4871 56E8 ZCURSTXX: + 4872 56E8 8D D0 6C sta CURSOR_OFF ; show current cursor state + 4873 56EB 60 rts + 4874 56EC ZCURS0: + 4875 56EC C6 63 dec ARG1+LO ; zero base both args + 4876 56EE C6 65 dec ARG2+LO ; thanx + 4877 56F0 + 4878 56F0 A5 62 lda NARGS ; check for id + 4879 56F2 C9 03 cmp #3 ; if 3 args, then window ID specified + 4880 56F4 F0 04 beq ZCURS1 ; not 3, so use current window + 4881 + 4882 56F6 A5 A6 lda CURWIN ; show current window being done + 4883 56F8 85 67 sta ARG3+LO ; thanx + 4884 56FA ZCURS1: + 4885 56FA A5 67 lda ARG3+LO ; get window ID + 4886 56FC 20 87 57 jsr SETWJ ; put address into J + 4887 56FF A5 63 lda ARG1+LO ; GET LINE + 4888 5701 A0 02 ldy #WINHGHT ; check against height + 4889 5703 D1 7A cmp (J),Y ; too far? + 4890 5705 90 05 bcc ZCURS3 ; no, so use it + 4891 5707 B1 7A lda (J),Y ; got max out + 4892 5709 A8 tay ; but one too far + 4893 570A 88 dey ; all better now + 4894 570B 98 tya ; back to A + 4895 570C ZCURS3: + 4896 570C 18 clc ; get ready for add + 4897 570D A0 00 ldy #WINTOP ; do y pos first + 4898 570F 71 7A adc (J),Y ; add in top to get absolute value + 4899 5711 A0 04 ldy #WINY ; get y pos offset + 4900 5713 91 7A sta (J),Y ; save here + 4901 5715 A5 65 lda ARG2+LO ; GET COLUMN + 4902 5717 A0 03 ldy #WINWID ; check against width + 4903 5719 D1 7A cmp (J),Y ; is it to for right (like Reagan?) + 4904 571B 90 05 bcc ZCURS4 ; nope, must be dukakis + 4905 571D B1 7A lda (J),Y ; get max + 4906 571F A8 tay ; for going down one + 4907 5720 88 dey ; done it + 4908 5721 98 tya ; back to A for usefullness + 4909 5722 ZCURS4: + Tue Jun 13 1989 11:42 Page 72 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4910 5722 A0 01 ldy #WINLEFT ; get left edge to absolute it + 4911 5724 71 7A adc (J),Y ; carry clear from above + 4912 5726 A0 05 ldy #WINX ; this is the x pos + 4913 5728 91 7A sta (J),Y ; into the structure + 4914 ; + 4915 ; now check for current window again, move cursor anyway + 4916 ; + 4917 572A 4C A1 4D jmp GET_CURSOR ; get cursor pos from WINDOW + 4918 + 4919 ; ------ + 4920 ; CURGET + 4921 ; ------ + 4922 + 4923 572D ZCURGT: + 4924 572D 20 BE 55 jsr CLRBUF ; flush the buffer + 4925 + 4926 5730 20 8F 4D jsr SAVE_CURSOR ; save the current position + 4927 + 4928 5733 C6 62 dec NARGS ; see how many arguments + 4929 5735 F0 04 beq ZCURG1 ; use main window + 4930 5737 A5 65 lda ARG2+LO ; get window id + 4931 5739 10 02 bpl ZCURG2 ; and figger it out + 4932 573B ZCURG1: + 4933 573B A5 A6 lda CURWIN ; use current window + 4934 573D ZCURG2: + 4935 573D 20 87 57 jsr SETWJ ; make J point to right place + 4936 + 4937 5740 A5 64 lda ARG1+HI ; get table address + 4938 5742 20 A9 8F jsr SETPC ; get real address in memory + 4939 5745 84 91 sty SPCBNK ; set bank + 4940 5747 85 90 sta SPCH ; and page + 4941 5749 A5 63 lda ARG1+LO ; get table offset + 4942 574B 85 8F sta SPCL ; and save it + 4943 + 4944 574D A9 00 lda #0 ; zero hi part of Y pos + 4945 574F 20 67 92 jsr STASHB ; and save it + 4946 5752 20 D0 8F jsr NEXTSPC ; and point to next one + 4947 5755 20 6C 57 jsr FETCHCY ; Fetch Y pos + 4948 5758 20 67 92 jsr STASHB ; and save it + 4949 575B 20 D0 8F jsr NEXTSPC + 4950 ; + 4951 ; now for the X pos + 4952 575E A9 00 lda #0 ; zero top byte of x pos + 4953 5760 20 67 92 jsr STASHB + 4954 5763 20 D0 8F jsr NEXTSPC + 4955 5766 20 79 57 jsr FETCHCX ; and now the X pos, and return + 4956 5769 4C 67 92 jmp STASHB ; and stash it away + 4957 + 4958 ; + 4959 ; FETCHCY - get the relativized Y pos into [A] + 4960 ; J points to window structure + 4961 576C FETCHCY: + 4962 576C A0 04 ldy #WINY ; get Y pos of window's cursor + 4963 576E B1 7A lda (J),Y ; got it + 4964 5770 A0 00 ldy #WINTOP ; need to de-absolute it + 4965 5772 38 sec ; get ready for sub + 4966 5773 F1 7A sbc (J),Y ; get relative pos + 4967 5775 AA tax ; for 1 basing it + 4968 5776 E8 inx ; 1 align it + 4969 5777 8A txa ; and put for save + 4970 5778 60 rts + 4971 ; + 4972 ; FETCHCX - get relativized X pos into [A] + 4973 ; J points to window structure + 4974 5779 FETCHCX: + 4975 5779 A0 05 ldy #WINX ; get X pos of cursor + 4976 577B B1 7A lda (J),Y ; got it + 4977 577D A0 01 ldy #WINLEFT ; relativize it + 4978 577F 38 sec ; get ready for sub + 4979 5780 F1 7A sbc (J),Y ; subtract left edge + 4980 5782 AA tax ; for incing + 4981 5783 E8 inx ; 1 ALIGN IT + 4982 5784 8A txa + 4983 5785 60 rts + 4984 + Tue Jun 13 1989 11:42 Page 73 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4985 ; ----- + 4986 ; DIRIN + 4987 ; ----- + 4988 ; NOT YET IMPLEMENTED, BUT RESERVED + 4989 + 4990 5786 60 ZDIRIN: RTS + 4991 + 4992 ; + 4993 ; SETWJ - set up J to point to window structure for window ID in [A] + 4994 ; + 4995 5787 SETWJ: + 4996 5787 A8 tay ; check for -3 (current window) + 4997 5788 10 02 bpl SWJ1 ; nope, window ID here + 4998 578A A5 A6 lda CURWIN ; -3 means current window + 4999 578C SWJ1: + 5000 578C 0A asl A ; shift to make word index + 5001 578D A8 tay ; and now make index + 5002 578E B9 75 6E lda WINTABLE,Y ; get lo part of window struct address + 5003 5791 85 7A sta J+LO ; and save it + 5004 5793 B9 76 6E lda WINTABLE+1,Y ; here's the hi part + 5005 5796 85 7B sta J+HI ; prove it + 5006 5798 60 rts + 5007 + 5008 ; ----- + 5009 ; ERASE + 5010 ; ----- + 5011 + 5012 5799 ZERASE: + 5013 5799 A5 63 lda ARG1+LO + 5014 579B C9 01 cmp #1 + 5015 579D D0 06 bne ZEROUT ; not clreol + 5016 + 5017 579F 20 BE 55 jsr CLRBUF + 5018 57A2 4C 2B 61 jmp CLREOL ; CLEAR TO END OF LINE + 5019 57A5 ZEROUT: + 5020 57A5 85 0C sta CLSWIDTH ; this many pixels wide + 5021 57A7 A9 09 lda #FONT_H ; pixels of font_height + 5022 57A9 85 0D sta CLSHEIGHT + 5023 57AB A5 00 lda SCRCX ; start at current cursor pos + 5024 57AD 85 0A sta CLSLEFT + 5025 57AF A5 01 lda SCRCY + 5026 57B1 85 0B sta CLSTOP + 5027 57B3 4C 2C 5F jmp CLS ; and do it + 5028 + 5029 ; ----- + 5030 ; CLEAR the current window + 5031 ; ----- + 5032 57B6 0000 SAVEXY: dw 0 + 5033 + 5034 57B8 ZCLR: + 5035 57B8 20 BE 55 jsr CLRBUF ; flush the current buffer + 5036 57BB 20 8F 4D jsr SAVE_CURSOR ; save the cursor pos + 5037 + 5038 57BE A5 63 lda ARG1+LO ; CHECK WHAT TO DO + 5039 57C0 10 26 bpl CLRW ; a particular window + 5040 57C2 C9 FD cmp #$FD ; -3 means current window + 5041 57C4 F0 22 beq CLRW ; so just handle it regular + 5042 57C6 C9 FE cmp #$FE ; clear with nothing social + 5043 57C8 F0 07 beq CLRCLS ; just clear the screen + 5044 ; + 5045 ; UNSPLIT SCREEN & CLEAR IT + 5046 ; + 5047 57CA A9 00 lda #0 ; just use SPLIT 0 + 5048 57CC 85 63 sta ARG1+LO ; as if called normally + 5049 57CE 20 CD 4D jsr ZSPLIT ; do the split + 5050 ; + 5051 ; just clear the entire screen + 5052 ; + 5053 57D1 CLRCLS: + 5054 57D1 A9 00 lda #0 ; clear the entire screen + 5055 57D3 85 0A sta CLSLEFT ; from top left + 5056 57D5 85 0B sta CLSTOP + 5057 57D7 A9 8C lda #MAXWIDTH ; to bottom right + 5058 57D9 85 0C sta CLSWIDTH + 5059 57DB A9 C0 lda #MAXHEIGHT + Tue Jun 13 1989 11:42 Page 74 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5060 57DD 85 0D sta CLSHEIGHT + 5061 + 5062 57DF 20 2C 5F jsr CLS ; do the clear screen (no cursor movement) + 5063 57E2 A5 63 lda ARG1+LO ; check for -2 + 5064 57E4 30 44 bmi ZCLRX ; it is, don't move cursor + 5065 57E6 10 1B bpl ZCLEARX ; move cursor + 5066 57E8 CLRW: + 5067 57E8 20 87 57 jsr SETWJ ; get me the window pointer + 5068 57EB A0 00 ldy #WINTOP ; step thro to get data + 5069 57ED B1 7A lda (J),Y ; TOP + 5070 57EF 85 0B sta CLSTOP ; save for clear + 5071 57F1 C8 iny ; point to left + 5072 57F2 B1 7A lda (J),Y ; get it + 5073 57F4 85 0A sta CLSLEFT ; tell CLS + 5074 57F6 C8 iny ; now at WINHGHT + 5075 57F7 B1 7A lda (J),Y ; got it + 5076 57F9 85 0D sta CLSHEIGHT ; save for clear + 5077 57FB C8 iny ; now at WINWID + 5078 57FC B1 7A lda (J),Y ; get height + 5079 57FE 85 0C sta CLSWIDTH ; saved + 5080 5800 20 2C 5F jsr CLS ; screen cleared + 5081 ; + 5082 ; now move the cursor to 1,1, if not == -2 + 5083 ; + 5084 5803 ZCLEARX: + 5085 5803 A5 63 lda ARG1+LO ; check arg + 5086 5805 20 87 57 jsr SETWJ ; make sure J still points to window + 5087 5808 A0 00 ldy #WINTOP ; put at top left of window + 5088 580A B1 7A lda (J),Y ; get top + 5089 580C A0 04 ldy #WINY ; and make it the y pos + 5090 580E 91 7A sta (J),Y ; of the cursor + 5091 5810 A0 01 ldy #WINLEFT ; and the left is + 5092 5812 B1 7A lda (J),Y ; the + 5093 5814 18 clc ; add in the left margin + 5094 5815 A0 06 ldy #WINLM ; here's the left margin + 5095 5817 71 7A adc (J),Y ; added it + 5096 5819 A0 05 ldy #WINX ; x pos of the + 5097 581B 91 7A sta (J),Y ; cursor + 5098 581D A9 00 lda #0 ; and clear out line count + 5099 581F A0 13 ldy #WINLCNT ; line count + 5100 5821 91 7A sta (J),Y ; okay + 5101 5823 A0 15 ldy #WINLLEN ; and length of current line + 5102 5825 91 7A sta (J),Y ; okay + 5103 5827 C8 iny ; do hi + 5104 5828 91 7A sta (J),Y ; okay + 5105 582A ZCLRX: + 5106 582A 4C A1 4D jmp GET_CURSOR ; restore the cursor pos for the current window + 5107 + 5108 ; ------ + 5109 ; PRINTT + 5110 ; ------ + 5111 ; PRINT A TABLE TO SCREEN, ARG1 = # OF BYTES + 5112 ; ARG2 = WIDTH, ARG3 (DEF = 1) = HEIGHT + 5113 + 5114 0078 OLDCHZ EQU I+LO ; EASIER TO READ + 5115 0079 OLDEHZ EQU I+HI + 5116 007E OLDCVT EQU L+LO + 5117 + 5118 582D 0000 TBL_LEN DW 0 ; save for length + 5119 + 5120 582F ZPRNTT: + 5121 582F A5 63 lda ARG1+LO ; USE GETBYT AS TBL COULD + 5122 5831 85 86 sta MPCL ; BE ANYWHERE + 5123 5833 A5 64 lda ARG1+HI + 5124 5835 85 87 sta MPCM + 5125 5837 A9 00 lda #0 + 5126 5839 85 88 sta MPCH + 5127 583B 20 B2 90 jsr VLDMPC + 5128 + 5129 583E A5 65 lda ARG2+LO ; ONLY A BYTE AS MAX + 5130 5840 F0 58 beq PTTDUN ; QUIT NOW IF NULL + 5131 + 5132 5842 85 BF sta TBLWIDTH ; width of the table + 5133 5844 85 C0 sta TBLCNT ; start counter off at width + 5134 5846 C6 62 dec NARGS ; count down to 1 (maybe) + Tue Jun 13 1989 11:42 Page 75 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5135 5848 A5 62 lda NARGS + 5136 584A C9 01 cmp #1 + 5137 584C F0 02 beq NOHIGHT ; DEFAULT HEIGHT IS 1 + 5138 584E A5 67 lda ARG3+LO ; get passed height + 5139 5850 NOHIGHT: + 5140 5850 85 BE sta TBLHEIGHT ; height of the table (at least 1) + 5141 5852 A5 00 lda SCRCX + 5142 5854 85 79 sta OLDEHZ + 5143 5856 38 sec ; subtract left margin to get how long line is + 5144 5857 E5 04 sbc LEFTMRG ; okay we did that + 5145 5859 8D 2D 58 sta TBL_LEN+LO ; this is how big line is too + 5146 585C A9 00 lda #0 ; clear MSB + 5147 585E 0E 2D 58 asl TBL_LEN+LO ; *2 + 5148 5861 2A rol A + 5149 5862 0E 2D 58 asl TBL_LEN+LO ; *4 + 5150 5865 2A rol A + 5151 5866 8D 2E 58 sta TBL_LEN+HI ; save + 5152 5869 PTTLP: + 5153 5869 20 3B 92 jsr GETBYT ; GET A BYTE + 5154 586C 20 F5 52 jsr COUT ; and send it out + 5155 + 5156 586F C6 C0 dec TBLCNT ; one more byte done + 5157 5871 D0 F6 bne PTTLP + 5158 5873 C6 BE dec TBLHEIGHT ; IF DONE ALL LINES + 5159 5875 F0 23 beq PTTDUN ; LEAVE + 5160 + 5161 5877 20 BE 55 jsr CLRBUF ; so send out stuff that's there + 5162 + 5163 587A A5 79 lda OLDEHZ ; get old x pos + 5164 587C 85 00 sta SCRCX ; and restore it + 5165 587E A9 01 lda #1 ; show cursor changed + 5166 5880 8D A5 6C sta CURSFLG ; okay + 5167 5883 A5 01 lda SCRCY ; point to next line + 5168 5885 18 clc ; by adding in the font height + 5169 5886 69 09 adc #FONT_H ; okay, goody + 5170 5888 85 01 sta SCRCY ; and here we are + 5171 + 5172 588A AD 2E 58 lda TBL_LEN+HI ; reset length + 5173 588D 85 A8 sta LENGTH+HI ; hi part + 5174 588F AD 2D 58 lda TBL_LEN+LO ; lo part + 5175 5892 85 A7 sta LENGTH+LO ; just a lo + 5176 + 5177 5894 A5 BF lda TBLWIDTH ; RESET COUNT + 5178 5896 85 C0 sta TBLCNT ; thanx + 5179 5898 D0 CF bne PTTLP ; GO DO NEXT LINE + 5180 589A PTTDUN: + 5181 589A 60 rts + 5182 ;-------------- + 5183 ; ZPRINTF + 5184 ;-------------- + 5185 ; ZPRINTF - print a formatted table + 5186 ; + 5187 589B ZPRINTF: + 5188 589B A5 63 lda ARG1+LO ; USE GETBYT AS TBL COULD + 5189 589D 85 86 sta MPCL ; BE ANYWHERE + 5190 589F A5 64 lda ARG1+HI + 5191 58A1 85 87 sta MPCM + 5192 58A3 A9 00 lda #0 + 5193 58A5 85 88 sta MPCH + 5194 58A7 20 B2 90 jsr VLDMPC + 5195 + 5196 58AA A5 00 lda SCRCX ; save the X pos + 5197 58AC 85 79 sta OLDEHZ ; saved here + 5198 58AE ZPFL1: + 5199 58AE 20 3B 92 jsr GETBYT ; get the length byte, MSB, & ignore + 5200 58B1 20 3B 92 jsr GETBYT ; get the length byte + 5201 58B4 F0 21 beq ZPFX ; no more if == 0 + 5202 58B6 85 BF sta TBLWIDTH ; keep track of it + 5203 58B8 ZPFL2: + 5204 58B8 20 3B 92 jsr GETBYT ; now get the char byte + 5205 58BB 20 A9 5D jsr CHAR ; and send it yt + 5206 58BE C6 BF dec TBLWIDTH ; any more? + 5207 58C0 D0 F6 bne ZPFL2 ; ayyup + 5208 + 5209 58C2 20 1A 72 jsr DISP_LINE ; make sure line goes out + Tue Jun 13 1989 11:42 Page 76 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5210 58C5 A5 79 lda OLDEHZ ; reset a few things + 5211 58C7 85 00 sta SCRCX ; including x pos + 5212 58C9 A9 01 lda #1 ; show cursor changed + 5213 58CB 8D A5 6C sta CURSFLG ; okay + 5214 58CE A5 01 lda SCRCY ; point to next line + 5215 58D0 18 clc ; by adding in the font height + 5216 58D1 69 09 adc #FONT_H ; okay, goody + 5217 58D3 85 01 sta SCRCY ; and here we are + 5218 58D5 D0 D7 bne ZPFL1 ; and do it again + 5219 58D7 ZPFX: + 5220 58D7 60 rts + 5221 ; ------------ + 5222 ; SET NEW FONT + 5223 ; ------------ + 5224 + 5225 ; Font 4 is mono-spaced font. + 5226 + 5227 58D8 ZFONT: + 5228 58D8 20 BE 55 jsr CLRBUF ; clear the buffer first + 5229 + 5230 58DB C6 62 dec NARGS ; did we get passed a window id? + 5231 58DD D0 04 bne ZFNTWID ; yup + 5232 58DF A9 FD lda #$FD ; -3 means current window + 5233 58E1 85 65 sta ARG2+LO ; make it the arg2 then + 5234 58E3 ZFNTWID: + 5235 58E3 A5 65 lda ARG2+LO ; get window we are interested in + 5236 58E5 20 87 57 jsr SETWJ ; make [J] point to window struct + 5237 + 5238 58E8 A5 63 lda ARG1+LO ; check for + 5239 58EA C9 01 cmp #1 ; font 1 + 5240 58EC F0 0E beq ZFNT1 ; or + 5241 58EE C9 04 cmp #4 ; font 4 (monospace) + 5242 58F0 D0 2A bne ZFBAD ; nope, so die + 5243 ; + 5244 ; font 4 is the monospaced font + 5245 ; + 5246 58F2 A0 10 ldy #WINFSIZE ; point to width + 5247 58F4 A9 03 lda #MFONT_W ; get game width + 5248 58F6 91 7A sta (J),Y ; store the width + 5249 58F8 A9 03 lda #3 ; set font ID + 5250 58FA D0 08 bne ZFNTEX ; all done + 5251 58FC ZFNT1: + 5252 58FC A0 10 ldy #WINFSIZE ; point to width + 5253 58FE A9 02 lda #FONT_W ; get game width + 5254 5900 91 7A sta (J),Y ; store the width + 5255 5902 A9 00 lda #0 ; set font ID + 5256 5904 ZFNTEX: + 5257 5904 A0 0F ldy #WINFONT ; set font + 5258 5906 48 pha ; save font id + 5259 5907 B1 7A lda (J),Y ; get old font id + 5260 5909 AA tax ; save old font id + 5261 590A 68 pla ; get new one back + 5262 590B 91 7A sta (J),Y ; save in structure + 5263 590D B1 05 lda (WINDOW),Y ; get current window font + 5264 590F F0 02 beq ZFNT0X ; set flag with zero + 5265 5911 A9 0C lda #MONOFONT_W ; get width of mono spaced font + 5266 5913 ZFNT0X: + 5267 5913 85 C1 sta FONTFLG ; and set flag too + 5268 5915 E8 inx ; make it say correct font ID for game + 5269 5916 8A txa ; put in A for put val + 5270 5917 A2 00 ldx #0 ; clear X + 5271 5919 4C D1 43 jmp PUTVAL ; and return it + 5272 591C ZFBAD: + 5273 591C 4C CA 43 jmp RET0 ; TELL IT DOESN'T WORK + 5274 ; ------------------------------ + 5275 ; FETCH A LINE OF INPUT FOR READ + 5276 ; ------------------------------ + 5277 ; ENTRY: Relative READ table address in RDTBL1 + 5278 ; EXIT: # CHARS READ IN [A] + 5279 591F SV_SPC: ds 3 ; save SPC here for later usage + 5280 5922 0000 INP_X: dw 0 ; saved cursor position + 5281 + 5282 5924 INPUT: + 5283 5924 20 BE 55 jsr CLRBUF ; FLUSH [LBUFF] + 5284 5927 A0 00 ldy #0 ; RESET LINE COUNT + Tue Jun 13 1989 11:42 Page 77 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5285 5929 84 79 sty I+HI ; clear local variables + 5286 592B 84 78 sty I+LO + 5287 592D 84 7B sty J+HI + 5288 592F 84 7A sty J+LO + 5289 5931 8C 90 5B sty BRKCHR ; init break char + 5290 5934 84 AB sty LINCNT ; RESET LINE COUNT + 5291 5936 8C D2 6C sty PTR_COUNT ; we start by looking at pointer + 5292 5939 AD A5 6C lda CURSFLG ; really move the cursor? + 5293 593C F0 0F beq IO_CURS ; nope + 5294 ; + 5295 ; re-doing the (hopefully) saved read, so put cursor back + 5296 ; + 5297 593E AD 23 59 lda INP_X+HI ; first, the MSB + 5298 5941 8D 02 72 sta CHR_X+HI + 5299 5944 AD 22 59 lda INP_X+LO ; now the LSB + 5300 5947 8D 01 72 sta CHR_X+LO + 5301 594A 8C A5 6C sty CURSFLG ; make sure we don't change cursor + 5302 594D IO_CURS: + 5303 ; + 5304 ; check for new TCHARS table + 5305 ; + 5306 594D AD 2F 96 lda ZBEGIN+ZTCHAR+1 ; so check lower byte for different tchars + 5307 5950 CD B2 6C cmp SVTCHAR+LO ; is it different? + 5308 5953 D0 08 bne IO_DOT ; ayyup, get new one + 5309 5955 AD 2E 96 lda ZBEGIN+ZTCHAR ; get current TCHARS hi part + 5310 5958 CD B3 6C cmp SVTCHAR+HI ; is it the same as saved one? + 5311 595B F0 03 beq IOj ; yes, so don't muck with it + 5312 595D IO_DOT: + 5313 595D 20 A5 5A jsr DO_TCHARS ; new table, so copy it over + 5314 ; + 5315 ; now set up FPC + 5316 ; + 5317 5960 IOj: + 5318 5960 AD A9 6C lda RDTBL1+HI ; get page of table + 5319 5963 20 A9 8F jsr SETPC ; and get me the memory page and bank + 5320 5966 85 8D sta FPCH ; save page + 5321 5968 84 8E sty FPCBNK ; and bank + 5322 596A AD A8 6C lda RDTBL1+LO ; and get offset + 5323 596D 85 8C sta FPCL ; set up FPC/SPC + 5324 596F 20 88 92 jsr FETCHB ; get length of line + 5325 5972 A8 tay ; for dec'ing + 5326 5973 88 dey ; don't count the offset byte + 5327 5974 88 dey ; and leave room for terminator + 5328 5975 84 17 sty CHRMAX ; and save it + 5329 5977 20 F0 8F jsr NEXTFPC ; point to next byte + 5330 597A 20 88 92 jsr FETCHB ; get current offset into buffer + 5331 597D 8D 89 5B sta CHARCNT ; save how many chars out there + 5332 5980 20 F0 8F jsr NEXTFPC ; point to beginning of data buffer + 5333 ; + 5334 ; now finish setting up saved SPC + 5335 ; + 5336 5983 A2 02 ldx #2 + 5337 5985 INSVCL: + 5338 5985 B5 8C lda FPC,X ; get byte to saved for use later on + 5339 5987 9D 1F 59 sta SV_SPC,X ; it is saved here + 5340 598A CA dex + 5341 598B 10 F8 bpl INSVCL ; next! + 5342 ; + 5343 ; now copy current buffer into local buffer + 5344 ; + 5345 598D AD 89 5B lda CHARCNT ; make sure we have some + 5346 5990 F0 11 beq CPIOLX ; nope, none in there now + 5347 5992 A2 00 ldx #0 ; start at first char + 5348 5994 CPIOL: + 5349 5994 20 88 92 jsr FETCHB ; get a char + 5350 5997 9D 00 02 sta LBUFF,X ; save char + 5351 599A 20 F0 8F jsr NEXTFPC ; point to next one + 5352 599D E8 inx ; next char + 5353 599E EC 89 5B cpx CHARCNT ; got them all yet? + 5354 59A1 D0 F1 bne CPIOL ; nope + 5355 59A3 CPIOLX: + 5356 59A3 20 FD 4E jsr CHKTME ; START TIME LIMIT + 5357 ; + 5358 ; this is the get-a-key-and-whack-on-it loop + 5359 ; + Tue Jun 13 1989 11:42 Page 78 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5360 59A6 INLOOP: + 5361 59A6 A5 79 lda I+HI ; is there a time? + 5362 59A8 F0 08 beq INPL1 ; nope + 5363 59AA 20 B8 4F jsr TIMIN ; do timed input + 5364 59AD 90 06 bcc INPL2 ; got a char, process it + 5365 59AF 4C 93 5A jmp LEXBAD ; timed out with nothing there! + 5366 59B2 INPL1: + 5367 59B2 20 20 51 jsr GETKEY ; let apple do the walking + 5368 59B5 INPL2: + 5369 59B5 20 DC 5A jsr ISTCHR ; CHECK IF IT'S AN ACCEPTABLE TERMINATOR KEY + 5370 59B8 B0 0D bcs NOTYET + 5371 + 5372 59BA 8D 90 5B sta BRKCHR + 5373 59BD C9 0D cmp #EOL ; IF EOL PUT TO SCREEN + 5374 59BF F0 03 beq ENDLINx + 5375 59C1 4C 4A 5A jmp ENDIN ; ELSE JUST END + 5376 59C4 ENDLINx: + 5377 59C4 4C 3A 5A jmp ENDLIN ; can't reach with a branch + 5378 59C7 NOTYET: + 5379 59C7 A0 FF ldy #$FF ; restart pointer device counter + 5380 59C9 8C D2 6C sty PTR_COUNT ; and start again + 5381 59CC A8 tay ; check for functions keys that aren't + 5382 59CD 30 65 bmi CBAD ; terminators and feep if it is + 5383 59CF C9 0D cmp #EOL ; EOL? + 5384 59D1 F0 67 beq ENDLIN ; LINE DONE IF SO + 5385 59D3 C5 1B cmp ESCAPE ; don't allow escape char's thru + 5386 59D5 F0 5D beq CBAD ; okay, I won't + 5387 + 5388 59D7 C9 08 cmp #BACKSPACE ; BACKSPACE? + 5389 59D9 F0 38 beq BACKUP ; SPECIAL HANDLING + 5390 59DB C9 1B cmp #ESCAPE ; ESCAPE char? + 5391 59DD F0 55 beq CBAD ; don't like it + 5392 + 5393 59DF AC 89 5B ldy CHARCNT ; where do we put char? + 5394 59E2 C4 17 cpy CHRMAX ; are we filled up? + 5395 59E4 B0 4E bcs CBAD ; boy, am i full + 5396 + 5397 59E6 48 pha ; save it + 5398 59E7 AA tax ; use as index + 5399 59E8 A5 A7 lda LENGTH+LO ; GET LINE LENGTH COUNTER + 5400 59EA 18 clc ; get ready for add + 5401 59EB 7D 53 64 adc CHWID,X ; add width + 5402 59EE A8 tay ; save LSB in Y + 5403 59EF A6 A8 ldx LENGTH+HI ; get high byte + 5404 59F1 90 01 bcc INP0C ; no wrap + 5405 59F3 E8 inx ; okay, wrap then + 5406 59F4 INP0C: + 5407 59F4 68 pla ; get char back + 5408 59F5 E4 A3 cpx XSIZE+HI ; check MSB first + 5409 59F7 90 04 bcc NOIOWRAP ; no need to check lsb + 5410 59F9 C4 A2 cpy XSIZE+LO ; end of screen line? + 5411 59FB B0 37 bcs CBAD ; reached end, so just beep + 5412 59FD NOIOWRAP: + 5413 59FD 86 A8 stx LENGTH+HI ; save MSB + 5414 59FF 84 A7 sty LENGTH+LO ; and LSB + 5415 5A01 AE 89 5B ldx CHARCNT ; for putting in line buffer + 5416 5A04 9D 00 02 sta LBUFF,X ; and save it in case we goto printer + 5417 5A07 20 A9 5D jsr CHAR ; SEND TO SCREEN + 5418 5A0A 20 1A 72 jsr DISP_LINE ; show char + 5419 5A0D EE 89 5B inc CHARCNT ; NEXT POSITION IN LINE + 5420 5A10 4C A6 59 jmp INLOOP ; NO, GET ANOTHER CHAR + 5421 ; + 5422 ; HANDLE BACKSPACE + 5423 ; + 5424 5A13 BACKUP: + 5425 5A13 AE 89 5B ldx CHARCNT ; if == 2 then empty + 5426 5A16 F0 1C beq CBAD ; JMP to beeping + 5427 5A18 CA dex ; get rid of char + 5428 5A19 8E 89 5B stx CHARCNT ; saved + 5429 5A1C BD 00 02 lda LBUFF,X ; get char we are interested in + 5430 5A1F AA tax ; put in x + 5431 + 5432 5A20 A5 A7 lda LENGTH+LO ; GET LINE LENGTH COUNTER + 5433 5A22 38 sec ; get ready for sub + 5434 5A23 FD 53 64 sbc CHWID,X ; sub width + Tue Jun 13 1989 11:42 Page 79 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5435 5A26 85 A7 sta LENGTH+LO ; update length + 5436 5A28 B0 02 bcs BCKP1 ; no wrap + 5437 5A2A C6 A8 dec LENGTH+HI ; okay, wrap then + 5438 5A2C BCKP1: + 5439 5A2C A9 08 lda #BACKSPACE ; so do erasing backspace + 5440 5A2E 20 A9 5D jsr CHAR + 5441 5A31 4C A6 59 jmp INLOOP + 5442 5A34 CBAD: + 5443 5A34 20 B3 4E jsr BEEP ; ELSE SCREAM WITH PAIN + 5444 5A37 4C A6 59 jmp INLOOP ; AND WAIT FOR SOMETHING BETTER + 5445 ; + 5446 ; HANDLE END OF LINE KEY + 5447 ; + 5448 5A3A ENDLIN: + 5449 5A3A 8D 90 5B sta BRKCHR + 5450 5A3D A9 0D lda #EOL ; get EOL char + 5451 5A3F 20 A9 5D jsr CHAR ; SEND EOL TO SCREEN + 5452 5A42 A9 00 lda #0 ; and show 0 length of line out there + 5453 5A44 85 A7 sta LENGTH+LO ; thanx + 5454 5A46 85 A8 sta LENGTH+HI ; and msb + 5455 5A48 E6 AB inc LINCNT ; take into account the at EOL + 5456 5A4A ENDIN: + 5457 ; + 5458 ; now save lbuff in table for posterity + 5459 ; + 5460 5A4A AD 21 59 lda SV_SPC+ABANK ; get bank first + 5461 5A4D 85 91 sta SPCBNK ; saved + 5462 5A4F AD 20 59 lda SV_SPC+HI + 5463 5A52 85 90 sta SPCH + 5464 5A54 AD 1F 59 lda SV_SPC+LO + 5465 5A57 85 8F sta SPCL + 5466 5A59 A2 00 ldx #0 ; start with first char in buffer + 5467 5A5B ENDLOOP: + 5468 5A5B EC 89 5B cpx CHARCNT ; done yet? + 5469 5A5E F0 16 beq INP111 + 5470 5A60 BD 00 02 lda LBUFF,X ; get char + 5471 5A63 C9 41 cmp #'A' ; IF CHAR IS UPPERCASE ALPHA, + 5472 5A65 90 06 bcc LEX ; CONVERT TO LOWER CASE + 5473 5A67 C9 5B cmp #'Z'+1 + 5474 5A69 B0 02 bcs LEX + 5475 5A6B 69 20 adc #$20 ; converting away + 5476 5A6D LEX: + 5477 5A6D 20 67 92 jsr STASHB ; okay, stashing away + 5478 5A70 20 D0 8F jsr NEXTSPC ; and point to next char in table + 5479 5A73 E8 inx ; point to next char + 5480 5A74 D0 E5 bne ENDLOOP ; so get next one + 5481 5A76 INP111: + 5482 5A76 A9 00 lda #00 ; to show end of line + 5483 5A78 20 67 92 jsr STASHB ; so put it in buffer + 5484 ; + 5485 ; now put in new line length + 5486 ; + 5487 5A7B AD A9 6C lda RDTBL1+HI ; get page of table + 5488 5A7E 20 A9 8F jsr SETPC ; and get me the memory page and bank + 5489 5A81 85 90 sta SPCH ; save page + 5490 5A83 84 91 sty SPCBNK ; and bank + 5491 5A85 AD A8 6C lda RDTBL1+LO ; and get offset + 5492 5A88 85 8F sta SPCL + 5493 5A8A 20 D0 8F jsr NEXTSPC ; and point to char count + 5494 5A8D AD 89 5B lda CHARCNT ; get character count + 5495 5A90 20 67 92 jsr STASHB ; and shove it away + 5496 5A93 LEXBAD: + 5497 5A93 A0 00 ldy #0 ; clear out + 5498 5A95 8C D2 6C sty PTR_COUNT ; pointer flag + 5499 ; + 5500 ; now, save CHR_X, in case we redo this read + 5501 ; + 5502 5A98 AD 02 72 lda CHR_X+HI ; first, the MSB + 5503 5A9B 8D 23 59 sta INP_X+HI + 5504 5A9E AD 01 72 lda CHR_X+LO ; now the LSB + 5505 5AA1 8D 22 59 sta INP_X+LO + 5506 5AA4 60 rts ; Length is in [A] + 5507 ; + 5508 ; Copy over a new TCHARS table + 5509 ; + Tue Jun 13 1989 11:42 Page 80 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5510 5AA5 DO_TCHARS: + 5511 ; + 5512 ; now do somethin' with the TCHAR table (maybe, if <> 0) + 5513 ; + 5514 5AA5 AD 2E 96 lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + 5515 5AA8 8D B3 6C sta SVTCHAR+HI ; save it for checking + 5516 5AAB 20 A9 8F jsr SETPC ; and now make absolute + 5517 5AAE 85 8D sta FPCH ; Save in FPC + 5518 5AB0 84 8E sty FPCBNK + 5519 5AB2 AD 2F 96 lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + 5520 5AB5 8D B2 6C sta SVTCHAR+LO ; and save for later check + 5521 5AB8 85 8C sta FPCL ; now move pointer to fetch spot + 5522 + 5523 5ABA A9 00 lda #0 ; and set index + 5524 5ABC 85 78 sta I ; thank you + 5525 5ABE 85 B9 sta ALLFLG ; turn it off + 5526 5AC0 TCHLP: + 5527 5AC0 20 88 92 jsr FETCHB ; get the byte in [a] + 5528 5AC3 20 F0 8F jsr NEXTFPC ; point to next one + 5529 5AC6 A6 78 ldx I ; get offset + 5530 5AC8 E6 78 inc I ; and point to next one + 5531 5ACA 9D 00 1D sta TCHARTBL,X ; save in lower memory, thank you + 5532 5ACD C9 00 cmp #0 ; are we done yet? + 5533 5ACF F0 0A beq TCHj ; NULL TERMINATED STRING + 5534 5AD1 C9 FF cmp #$FF ; $ff means all >128 chars are terminators + 5535 5AD3 D0 04 bne TCHLNEXT ; nope + 5536 5AD5 A9 01 lda #1 ; yes, + 5537 5AD7 85 B9 sta ALLFLG ; so set flag to say so + 5538 5AD9 TCHLNEXT: + 5539 5AD9 D0 E5 bne TCHLP ; and go get it + 5540 5ADB TCHj: + 5541 5ADB 60 rts + 5542 + 5543 ; ------------------------ + 5544 ; IS IT A TERMINATOR CHAR? + 5545 ; ------------------------ + 5546 + 5547 5ADC ISTCHR: + 5548 5ADC AE 00 1D ldx TCHARTBL ; check for chars in TCHAR table + 5549 5ADF F0 18 beq ISNOT ; nope + 5550 + 5551 5AE1 A6 B9 ldx ALLFLG ; ARE ALL FCN KEYS (<127) TERMINATORS + 5552 5AE3 F0 05 beq ISCHK ; 0 = NO, GO CHECK LIST + 5553 5AE5 AA tax ; check for minus + 5554 5AE6 30 13 bmi ISFND ; YUP + 5555 5AE8 10 0F bpl ISNOT + 5556 5AEA ISCHK: + 5557 5AEA A0 00 ldy #0 + 5558 5AEC ISLP: + 5559 5AEC D9 00 1D cmp TCHARTBL,Y ; IS CHAR WE HAVE A TCHAR? + 5560 5AEF F0 0A beq ISFND ; YES + 5561 5AF1 BE 00 1D ldx TCHARTBL,Y ; NULL = END OF STRING + 5562 5AF4 F0 03 beq ISNOT + 5563 5AF6 C8 iny + 5564 5AF7 D0 F3 bne ISLP ; SHOULD ALWAYS LOOP + 5565 5AF9 ISNOT: + 5566 5AF9 38 sec + 5567 5AFA 60 rts ; NOT FOUND + 5568 5AFB ISFND: + 5569 5AFB 18 clc + 5570 5AFC 60 rts + 5571 + 5572 ; ----- + 5573 ; INPUT 1 char, no printing + 5574 ; ----- + 5575 + 5576 5AFD ZINPUT: + 5577 5AFD 20 BE 55 JSR CLRBUF + 5578 + 5579 5B00 A0 00 ldy #0 + 5580 5B02 84 AB sty LINCNT + 5581 5B04 84 A9 sty CHRCNT + 5582 5B06 84 79 sty I+HI ; init locals too + 5583 5B08 84 78 sty I+LO + 5584 5B0A 84 7B sty J+HI + Tue Jun 13 1989 11:42 Page 81 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5585 5B0C 84 7A sty J+LO + 5586 5B0E 8C D2 6C sty PTR_COUNT ; always check the pointer + 5587 5B11 + 5588 5B11 C6 62 DEC NARGS + 5589 5B13 F0 18 BEQ ZINP3 ; NO TIME LIMIT + 5590 5B15 A5 65 LDA ARG2+LO ; GET DELAY WANTED + 5591 5B17 85 79 STA I+HI + 5592 5B19 C6 62 DEC NARGS + 5593 5B1B F0 08 BEQ ZINP4 ; NO FCN + 5594 5B1D A5 67 LDA ARG3+LO + 5595 5B1F 85 7A STA J+LO + 5596 5B21 A5 68 LDA ARG3+HI + 5597 5B23 85 7B STA J+HI + 5598 5B25 ZINP4: + 5599 5B25 20 B8 4F JSR TIMIN ; CALL timed input rotine + 5600 5B28 90 10 BCC ZINPRK ; send char on home + 5601 5B2A 4C CA 43 JMP RET0 ; time out without character + 5602 5B2D ZINP3: + 5603 5B2D 20 20 51 jsr GETKEY ; ok, find which char was pressed + 5604 5B30 C9 1B cmp #ESCAPE ; don't use escape char + 5605 5B32 D0 06 bne ZINPRK ; fine + 5606 5B34 20 B3 4E jsr BEEP ; complain + 5607 5B37 4C 2D 5B jmp ZINP3 ; do again + 5608 5B3A ZINPRK: + 5609 5B3A A2 00 LDX #0 + 5610 5B3C 4C CD 43 JMP PUTBYT ; RETURN CHAR + 5611 + 5612 + 5613 5B3F INTCLL: + 5614 5B3F A5 79 LDA I+HI ; SAVE VALUES FOR CALLING RTN + 5615 5B41 48 PHA + 5616 5B42 A5 78 LDA I+LO + 5617 5B44 48 PHA + 5618 5B45 A5 7B LDA J+HI + 5619 5B47 85 64 STA ARG1+HI ; pretend it's arg1 + 5620 5B49 48 PHA + 5621 5B4A A5 7A LDA J+LO + 5622 5B4C 85 63 STA ARG1+LO ; and this is the other half + 5623 5B4E 48 PHA + 5624 + 5625 5B4F A2 01 LDX #1 + 5626 5B51 86 62 STX NARGS ; 0 args for internal call + 5627 5B53 CA DEX + 5628 5B54 8E 8B 5B STX IRET ; make sure it returns here! + 5629 5B57 + 5630 5B57 A5 80 LDA ZPCL ; a fake one to say we + 5631 5B59 48 PHA ; are an internal call + 5632 5B5A A5 81 LDA ZPCM ; so save real one + 5633 5B5C 48 PHA + 5634 5B5D A5 82 LDA ZPCH + 5635 5B5F 48 PHA + 5636 + 5637 5B60 A9 00 LDA #0 ; return addr of zero is + 5638 5B62 85 82 STA ZPCH ; internal call! + 5639 5B64 85 81 STA ZPCM + 5640 5B66 85 80 STA ZPCL + 5641 + 5642 5B68 20 F6 7F JSR DOCALL + 5643 + 5644 5B6B 4C B6 40 JMP MLOOP ; GO DO FCN + 5645 ; + 5646 ; RETURN FROM FCN WILL COME HERE + 5647 ; + 5648 5B6E ZIRET: + 5649 5B6E 68 PLA ; GET RID OF RTS FROM ZRET + 5650 5B6F 68 PLA + 5651 + 5652 5B70 68 PLA ; get old zpc back + 5653 5B71 85 82 STA ZPCH + 5654 5B73 68 PLA + 5655 5B74 85 81 STA ZPCM + 5656 5B76 68 PLA + 5657 5B77 85 80 STA ZPCL + 5658 5B79 20 DC 90 JSR VLDZPC ; and validate it + 5659 + Tue Jun 13 1989 11:42 Page 82 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5660 5B7C 68 PLA ; RESTORE FOR CALLING RTN + 5661 5B7D 85 7A STA J+LO + 5662 5B7F 68 PLA + 5663 5B80 85 7B STA J+HI + 5664 5B82 68 PLA + 5665 5B83 85 78 STA I+LO + 5666 5B85 68 PLA + 5667 5B86 85 79 STA I+HI + 5668 5B88 60 RTS ; GO BACK TO CALLER + 5669 + 5670 ; INPUT: routine locals! + 5671 5B89 00 CHARCNT: DB 0 ; where into buffer goes char + 5672 5B8A 00 SVCHAR: DB 0 ; where to save the char before printing + 5673 + 5674 5B8B 00 IRET: DB 0 ; FLAG TELLS IF RETURNLESS CALL + 5675 + 5676 5B8C 00 00 MTEMP: DB 00,00 ; temp spot for math routines + 5677 5B8E 00 TYPE: DB 0 ; PARTIAL OR NORMAL (WHOLE) SAVE/RESTORE + 5678 5B8F 00 ASSVLU: DB 0 ; how many args to this subroutine + 5679 5B90 00 BRKCHR: DB 0 ; READ BREAK CHAR + 5680 5B91 00 RDFLAG: DB 0 ; 0 - only read 1 - do lex on it + 5681 5B92 5B 4D 4F 52 45 MORE: DB "[MORE]" + 5B97 5D + 5682 0006 MOREL EQU $-MORE + 5683 5B98 END + 5684 + 5685 5B98 INCLUDE VERIFY.ASM + 5686 5B98 STTL "--- VERIFY CODE ---" + 5687 PAGE + Tue Jun 13 1989 11:42 Page 83 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5688 + 5689 ; ------ + 5690 ; VERIFY + 5691 ; ------ + 5692 ; VERIFY GAME CODE ON DISK + 5693 5B98 0D 54 68 65 20 VERBAD: DB EOL,"The data segment of file is BAD!",EOL + 5B9D 64 61 74 61 20 + 5BA2 73 65 67 6D 65 + 5BA7 6E 74 20 6F 66 + 5BAC 20 66 69 6C 65 + 5BB1 20 69 73 20 42 + 5BB6 41 44 21 0D + 5694 0022 VERBADL EQU $-VERBAD + 5695 5BBA 0D 54 68 65 20 VERPBAD: DB EOL,"The picture data of file is BAD!",EOL + 5BBF 70 69 63 74 75 + 5BC4 72 65 20 64 61 + 5BC9 74 61 20 6F 66 + 5BCE 20 66 69 6C 65 + 5BD3 20 69 73 20 42 + 5BD8 41 44 21 0D + 5696 0022 VERPBADL EQU $-VERPBAD + 5697 5BDC 00 ZVFLAG: db 0 ; set to indicate ugliness + 5698 0078 STARTPOS EQU I+LO ; this is where to start block + 5699 5BDD ZVER: + 5700 5BDD 20 C1 8C jsr CLOSE_GAME ; make sure the game files are closed + 5701 5BE0 AC 79 46 ldy GAME2NML ; get length of name + 5702 5BE3 B9 79 46 lda GAME2NM,Y ; get last char + 5703 5BE6 49 30 eor #$30 ; make normal number + 5704 5BE8 A8 tay ; -1 to make ready for FETCH_FILE + 5705 5BE9 88 dey ; F_F incs first + 5706 5BEA 98 tya ; to push onto stack + 5707 5BEB 48 pha ; and save for restoring later + 5708 5BEC A9 00 lda #0 ; clear a few counters + 5709 5BEE 8D DC 5B sta ZVFLAG ; ==0 - verify worked; !=0 - verify broke + 5710 5BF1 AD 01 19 lda SEGTBL+SGTDISKS+1 ; get how many disks are here + 5711 5BF4 8D 47 49 sta DISKCNTR ; this shows which disk we are working on + 5712 5BF7 CE 47 49 dec DISKCNTR ; start down by one + 5713 5BFA VERIFY_LOOP: + 5714 5BFA 20 32 5C jsr VERIFY_DATA ; check data in this file + 5715 5BFD 20 BD 5C jsr VERIFY_PICD ; check (possible) picture data in this file + 5716 5C00 AD BF 45 lda GMREF ; get reference number + 5717 5C03 8D 35 8B sta CLOSE_PB+CL_REFNUM ; and show CLOSE + 5718 5C06 CLOSE CLOSE_PB ; and shut it up + 5719 5C06 PRODOS $CC, CLOSE_PB + 5720 5C06 20 00 BF jsr $BF00 ; ProDOS handler + 5721 5C09 CC DB $CC ; ProDOS function code + 5722 5C0A 348B DW CLOSE_PB ; Function Parameter Block address + 5723 5C0C .MACEND + 5724 5C0C .MACEND + 5725 5C0C CE 47 49 dec DISKCNTR ; next please + 5726 5C0F 10 E9 bpl VERIFY_LOOP ; and check the next file + 5727 5C11 ZVERX: + 5728 5C11 A9 02 lda #>PAGELEN ; reset read buffer length + 5729 5C13 8D C3 45 sta READ_PB+RD_BUFFLEN+HI ; to be $100 + 5730 5C16 A9 00 lda # 0, then it isn't + 5772 5C5F 20 78 5D jsr SETUP_DISK0 ; move around to point to start of data + 5773 5C62 VERD1: + 5774 5C62 A0 02 ldy #SGTPICOF ; find where picture data starts + 5775 5C64 B1 1E lda (DSEGS),Y ; MSB + 5776 5C66 85 7B sta J+HI ; J is the page counter + 5777 5C68 C8 iny ; point to LSB + 5778 5C69 11 1E ora (DSEGS),Y ; any picture file? + 5779 5C6B D0 08 bne VERD01 ; yes, so mark end of data + 5780 5C6D A9 FF lda #$FF ; set J to be a real big number + 5781 5C6F 85 7A sta J+LO ; okay + 5782 5C71 85 7B sta J+HI ; and this one + 5783 5C73 D0 15 bne VERD11 ; all done + 5784 5C75 VERD01: + 5785 5C75 B1 1E lda (DSEGS),Y ; and here it is + 5786 5C77 0A asl A ; *2 to make 512 pages be 256 pages + 5787 5C78 85 7A sta J+LO ; this is where it ends up + 5788 5C7A 26 7B rol J+HI ; move in carry to MSB + 5789 5C7C A5 7A lda J+LO ; now, subtract any skipping + 5790 5C7E 38 sec ; doing sub + 5791 5C7F ED CF 45 sbc PSEEK+SM_FPOS+1 ; take away any skipped amount + 5792 5C82 85 7A sta J+LO ; and save it + 5793 5C84 A5 7B lda J+HI ; pick up carry + 5794 5C86 E9 00 sbc #0 ; we will + 5795 5C88 85 7B sta J+HI ; we did + 5796 5C8A VERD11: + 5797 5C8A 20 0D 5D jsr VERIFY_FILE ; now, actually do the work + 5798 5C8D 90 2D bcc VERDX ; worked just fine + 5799 5C8F DLINE VERBAD ; puke, gag, argh + 5800 5C8F A2 98 ldx #VERBAD ; get other part of string + 5802 [01] IFMA 2 ; check to see if length passed in + 5803 ldy ; then just fetch it + 5804 [01] ELSE + 5805 5C93 A0 22 ldy #VERBADL ; get length of string + 5806 [00] ENDIF + 5807 5C95 20 5B 4C jsr DLINE ; print the string + 5808 5C98 .MACEND + 5809 ; + 5810 ; This prints out which file is garfed + 5811 ; + 5812 5C98 VER_FMSG: + 5813 5C98 AD 47 49 lda DISKCNTR ; which file did we do? + 5814 5C9B C9 02 cmp #2 ; 0,1 are in one place + 5815 5C9D B0 0D bcs VERDB1 ; nope it isn't it + 5816 5C9F DLINE GAME1NAME,GAME1NML + 5817 5C9F A2 68 ldx #GAME1NAME ; get other part of string + 5819 [01] IFMA 2 ; check to see if length passed in + 5820 5CA3 AC 67 46 ldy GAME1NML ; then just fetch it + 5821 [01] ELSE + 5822 ldy #GAME1NAMEL ; get length of string + 5823 [00] ENDIF + 5824 5CA6 20 5B 4C jsr DLINE ; print the string + 5825 5CA9 .MACEND + Tue Jun 13 1989 11:42 Page 85 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5826 5CA9 4C B6 5C jmp VERDB2 + 5827 5CAC VERDB1: + 5828 5CAC DLINE GAME2NAME,GAME2NML ; 2,3 are in another + 5829 5CAC A2 7A ldx #GAME2NAME ; get other part of string + 5831 [01] IFMA 2 ; check to see if length passed in + 5832 5CB0 AC 79 46 ldy GAME2NML ; then just fetch it + 5833 [01] ELSE + 5834 ldy #GAME2NAMEL ; get length of string + 5835 [00] ENDIF + 5836 5CB3 20 5B 4C jsr DLINE ; print the string + 5837 5CB6 .MACEND + 5838 5CB6 VERDB2: + 5839 5CB6 EE DC 5B inc ZVFLAG ; show bad file + 5840 5CB9 20 0D 8D jsr GETRET ; just wait for + 5841 5CBC VERDX: + 5842 5CBC 60 rts ; all done + 5843 ; + 5844 ; VERIFY_PICD - verify the picture data in a file. First check to see if + 5845 ; there is any. If so, seek to it, set J==0 to show VERIFY_FILE to read + 5846 ; til EOF, and print out bad picture data message if necessary. + 5847 ; + 5848 5CBD VERIFY_PICD: + 5849 5CBD A9 FF lda #$FF ; gonna zero bunch of stuff + 5850 5CBF 85 7B sta J+HI ; and the counter + 5851 5CC1 85 7A sta J+LO ; which means now goto EOF + 5852 5CC3 A0 02 ldy #SGTPICOF ; fetch the picture data offset + 5853 5CC5 B1 1E lda (DSEGS),Y ; get MSB + 5854 5CC7 8D D0 45 sta PSEEK+SM_FPOS+2 ; we are doing pages + 5855 5CCA C8 iny ; pointing to LSB + 5856 5CCB 11 1E ora (DSEGS),Y ; first, check for all zeros + 5857 5CCD D0 01 bne VERP1 ; nope, some picture data is there + 5858 5CCF 60 rts ; just gwon back if nothing here + 5859 5CD0 VERP1: + 5860 5CD0 B1 1E lda (DSEGS),Y ; go get LSB + 5861 5CD2 0A asl A ; *2 to get 256 byte pages + 5862 5CD3 8D CF 45 sta PSEEK+SM_FPOS+1 ; put away here + 5863 5CD6 2E D0 45 rol PSEEK+SM_FPOS+2 ; pick up carry + 5864 5CD9 A9 10 lda #PHSIZE ; skip over header of file + 5865 5CDB 85 78 sta STARTPOS ; show offset in first block + 5866 5CDD VERP11: + 5867 5CDD SET_MARK PSEEK ; and move to picture data spot + 5868 5CDD PRODOS $CE, PSEEK + 5869 5CDD 20 00 BF jsr $BF00 ; ProDOS handler + 5870 5CE0 CE DB $CE ; ProDOS function code + 5871 5CE1 CC45 DW PSEEK ; Function Parameter Block address + 5872 5CE3 .MACEND + 5873 5CE3 .MACEND + 5874 5CE3 20 0D 5D jsr VERIFY_FILE ; read in the data + 5875 5CE6 SET_MARK PSEEK ; get back to beginning of pic data + 5876 5CE6 PRODOS $CE, PSEEK + 5877 5CE6 20 00 BF jsr $BF00 ; ProDOS handler + 5878 5CE9 CE DB $CE ; ProDOS function code + 5879 5CEA CC45 DW PSEEK ; Function Parameter Block address + 5880 5CEC .MACEND + 5881 5CEC .MACEND + 5882 5CEC READ READ_PB ; read in a block worth + 5883 5CEC PRODOS $CA, READ_PB + 5884 5CEC 20 00 BF jsr $BF00 ; ProDOS handler + 5885 5CEF CA DB $CA ; ProDOS function code + 5886 5CF0 BE45 DW READ_PB ; Function Parameter Block address + 5887 5CF2 .MACEND + 5888 5CF2 .MACEND + 5889 5CF2 AD 0A 08 lda IOBUFF+PHCHKS ; get MSB of picture checksum + 5890 5CF5 C5 7F cmp L+HI ; same as what we got? + 5891 5CF7 D0 07 bne VERPB ; nope + 5892 5CF9 AD 0B 08 lda IOBUFF+PHCHKS+1 ; get LSB of picture checksum + 5893 5CFC C5 7E cmp L+LO ; same as mine? + 5894 5CFE F0 0C beq VERPX ; yup, checked out fine + 5895 5D00 VERPB: + 5896 5D00 DLINE VERPBAD ; picture data bad + 5897 5D00 A2 BA ldx #VERPBAD ; get other part of string + 5899 [01] IFMA 2 ; check to see if length passed in + 5900 ldy ; then just fetch it + Tue Jun 13 1989 11:42 Page 86 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5901 [01] ELSE + 5902 5D04 A0 22 ldy #VERPBADL ; get length of string + 5903 [00] ENDIF + 5904 5D06 20 5B 4C jsr DLINE ; print the string + 5905 5D09 .MACEND + 5906 5D09 4C 98 5C jmp VER_FMSG ; print out file name + 5907 5D0C VERPX: + 5908 5D0C 60 rts ; tootis finis + 5909 ; + 5910 ; VERIFY_FILE - Files is already open and pointing to start of checksummed + 5911 ; data. Works along til J == 0 or EOF, which ever comes first. Starts by + 5912 ; dec'ing J, so if J starts as 0, effectively means goto EOF. + 5913 ; + 5914 5D0D VERIFY_FILE: + 5915 5D0D A9 00 lda #0 ; clear out checksum counter + 5916 5D0F 85 7F sta L+HI ; MSB + 5917 5D11 85 7E sta L+LO ; LSB + 5918 5D13 8D C2 45 sta READ_PB+RD_BUFFLEN+LO + 5919 5D16 A9 04 lda #4 ; make read read $400 (1Kb) + 5920 5D18 8D C3 45 sta READ_PB+RD_BUFFLEN+HI + 5921 5D1B VFLOOP: + 5922 5D1B A9 03 lda #RETRY_COUNT ; and set up retry count + 5923 5D1D 85 16 sta RETRIES + 5924 5D1F A9 00 lda #IOBUFF ; reading all the data + 5927 5D25 85 7D sta K+HI ; into, using as pointer + 5928 5D27 VFLRD: + 5929 5D27 READ READ_PB ; read in 1Kb of data + 5930 5D27 PRODOS $CA, READ_PB + 5931 5D27 20 00 BF jsr $BF00 ; ProDOS handler + 5932 5D2A CA DB $CA ; ProDOS function code + 5933 5D2B BE45 DW READ_PB ; Function Parameter Block address + 5934 5D2D .MACEND + 5935 5D2D .MACEND + 5936 5D2D 90 0D bcc VERF0 ; just fine read + 5937 5D2F C9 4C cmp #$4C ; EOF error? + 5938 5D31 F0 32 beq VFCHECK ; yes, so wee bee done + 5939 5D33 C9 4D cmp #$4D ; InfoDOS EOF error? + 5940 5D35 F0 2E beq VFCHECK ; ayyup + 5941 5D37 20 F7 46 jsr RETRY ; check about retrying + 5942 5D3A 90 EB bcc VFLRD ; and do again + 5943 5D3C VERF0: + 5944 5D3C A5 7A lda J+LO ; count the block to be read + 5945 5D3E D0 06 bne VERF1 ; no wrapping + 5946 5D40 A5 7B lda J+HI ; anything left? + 5947 5D42 F0 21 beq VFCHECK ; nope, all done then + 5948 5D44 C6 7B dec J+HI ; count one block + 5949 5D46 VERF1: + 5950 5D46 C6 7A dec J+LO ; count block + 5951 5D48 A4 78 ldy STARTPOS ; and begin + 5952 5D4A VERF2: + 5953 5D4A B1 7C lda (K),Y ; get byte + 5954 5D4C 18 clc ; doing add + 5955 5D4D 65 7E adc L+LO ; add it in + 5956 5D4F 85 7E sta L+LO ; save it + 5957 5D51 90 02 bcc VERF3 ; no wrap + 5958 5D53 E6 7F inc L+HI ; yes ther is + 5959 5D55 VERF3: + 5960 5D55 C8 iny ; next byte + 5961 5D56 D0 F2 bne VERF2 ; back to start of inner tloop + 5962 + 5963 5D58 A9 00 lda #0 ; start at first byte + 5964 5D5A 85 78 sta STARTPOS ; okay + 5965 5D5C E6 7D inc K+HI ; point to next block + 5966 5D5E CE C5 45 dec READ_PB+RD_LENGTH+HI ; count this one + 5967 5D61 F0 B8 beq VFLOOP ; go read some more + 5968 5D63 D0 D7 bne VERF0 ; go do next 256 byte block + 5969 5D65 VFCHECK: + 5970 5D65 A0 00 ldy #SGTCHKS ; get check sum + 5971 5D67 A5 7F lda L+HI ; start with MSB + 5972 5D69 D1 1E cmp (DSEGS),Y ; well . . . ? + 5973 5D6B D0 09 bne VFBAD ; nope, it is wrong + 5974 5D6D C8 iny ; first byte is okay + 5975 5D6E A5 7E lda L+LO ; so check LSB + Tue Jun 13 1989 11:42 Page 87 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5976 5D70 D1 1E cmp (DSEGS),Y ; well . . . ? + 5977 5D72 D0 02 bne VFBAD ; die a slow ugly death + 5978 5D74 18 clc ; clear carry to show niceness + 5979 5D75 60 rts + 5980 5D76 VFBAD: + 5981 5D76 38 sec ; carry is set if bad + 5982 5D77 60 rts ; and return to your fate + 5983 ; + 5984 ; SETUP_DISK0 - this routine does some special processing to get the file + 5985 ; pointer to the beginning of data for the preload file. It skips over + 5986 ; segment table. + 5987 5D78 SETUP_DISK0: + 5988 5D78 READ READ_PB ; read in first block + 5989 5D78 PRODOS $CA, READ_PB + 5990 5D78 20 00 BF jsr $BF00 ; ProDOS handler + 5991 5D7B CA DB $CA ; ProDOS function code + 5992 5D7C BE45 DW READ_PB ; Function Parameter Block address + 5993 5D7E .MACEND + 5994 5D7E .MACEND + 5995 5D7E AD 00 08 lda IOBUFF ; MSB of segment table size (in words) + 5996 5D81 8D CF 45 sta PSEEK+SM_FPOS+1 ; middle part of offset + 5997 5D84 AD 01 08 lda IOBUFF+1 ; LSB of size + 5998 5D87 0A asl A ; *2 to pick up carry + 5999 5D88 2E CF 45 rol PSEEK+SM_FPOS+1 ; rotate in carry + 6000 5D8B 2E D0 45 rol PSEEK+SM_FPOS+2 ; and once more + 6001 5D8E A8 tay ; check for wrapping upwards + 6002 5D8F F0 08 beq STD01 ; no wrap up then + 6003 5D91 STD00: + 6004 5D91 EE CF 45 inc PSEEK+SM_FPOS+1 ; wee did + 6005 5D94 D0 03 bne STD01 ; no more wrapping + 6006 5D96 EE D0 45 inc PSEEK+SM_FPOS+2 ; yes there is + 6007 5D99 STD01: + 6008 5D99 AD CF 45 lda PSEEK+SM_FPOS+1 ; make sure it is a 512 byte page + 6009 5D9C 29 01 and #$1 ; even page? + 6010 5D9E D0 F1 bne STD00 ; inc again, please + 6011 5DA0 STD0X: + 6012 5DA0 SET_MARK PSEEK ; skip the segment table stuff + 6013 5DA0 PRODOS $CE, PSEEK + 6014 5DA0 20 00 BF jsr $BF00 ; ProDOS handler + 6015 5DA3 CE DB $CE ; ProDOS function code + 6016 5DA4 CC45 DW PSEEK ; Function Parameter Block address + 6017 5DA6 .MACEND + 6018 5DA6 .MACEND + 6019 5DA6 60 rts ; all done + 6020 + 6021 5DA7 END + 6022 + 6023 5DA7 INCLUDE SCREEN.ASM + 6024 5DA7 STTL "--- APPLE ][ SCREEN STUFF ---" + 6025 PAGE + Tue Jun 13 1989 11:42 Page 88 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6026 + 6027 ; ----------------- + 6028 ; PRINT CHAR IN [A] AT CV,CH + 6029 ; ----------------- + 6030 ; + 6031 ; uses memory register [L] + 6032 ; + 6033 5DA7 00 SAVECY DB 0 ; spot to save current screen y pos + 6034 5DA8 00 SAVECX DB 0 ; spot for x pos + 6035 + 6036 5DA9 CHAR: + 6037 5DA9 85 AC sta IOCHAR ; SAVE HERE + 6038 5DAB 8A txa ; SAVE [X] AND [Y] + 6039 5DAC 48 pha + 6040 5DAD 98 tya + 6041 5DAE 48 pha + 6042 5DAF + 6043 5DAF A5 AC lda IOCHAR ; get it back + 6044 5DB1 C9 08 cmp #BACKSPACE ; is it backspace with erase? + 6045 5DB3 D0 03 bne CHCX ; nope + 6046 + 6047 5DB5 4C D7 5E jmp DO_BSPC ; so handle backspace + 6048 5DB8 CHCX: + 6049 5DB8 C9 0D cmp #EOL ; is it ? + 6050 5DBA D0 03 bne CHCONT ; just let dline handle it + 6051 5DBC + 6052 5DBC 4C A4 5E jmp DO_EOL ; handle + 6053 ; + 6054 ; so save some stuff and do all the necessary figgering + 6055 ; + 6056 5DBF CHCONT: + 6057 5DBF AE 0D 72 ldx SCRCNT ; just stash character + 6058 5DC2 9D 80 02 sta SCRBUFF,X ; save it + 6059 5DC5 EE 0D 72 inc SCRCNT ; and count it + 6060 5DC8 CH_EXIT: + 6061 5DC8 68 pla ; RESTORE [X] AND [Y] + 6062 5DC9 A8 tay + 6063 5DCA 68 pla + 6064 5DCB AA tax + 6065 5DCC 60 rts + 6066 ; + 6067 ; PUT_NYBBLE - put 4 bits to the screen at SCRCX, SCRCY (the lower 4 bits + 6068 ; in [A]). + 6069 ; + 6070 5DCD PUT_NYBBLE: + 6071 5DCD 85 0E sta NY_DATA ; save [A] for mucking with + 6072 5DCF 20 78 5E jsr SETPOS ; set up offsets using SCRCX + 6073 + 6074 5DD2 A9 08 lda #$8 ; start at first bit, left to right + 6075 5DD4 85 10 sta DATALOOP ; and init the counter with it + 6076 5DD6 PNY0: + 6077 5DD6 A6 8E ldx FPCBNK ; which bank + 6078 5DD8 BD 54 C0 lda PAGE2SW,X ; select it + 6079 5DDB A0 00 ldy #0 ; start with zero + 6080 5DDD B1 8C lda (FPC),Y ; get it + 6081 5DDF 85 13 sta SCR_DATA ; and save it + 6082 5DE1 PNY1: + 6083 5DE1 A6 11 ldx BITOFF ; get which interesting bit we want + 6084 5DE3 BD 30 5E lda GT_BITS,X ; get bit + 6085 5DE6 48 pha ; save bit pictures + 6086 5DE7 A5 10 lda DATALOOP ; see if we have done all 4 bits in this 'pixel' + 6087 5DE9 F0 29 beq PNY_EXIT ; toots finis + 6088 5DEB 46 10 lsr DATALOOP ; point to next bit + 6089 5DED 24 0E bit NY_DATA ; is this bit set? + 6090 5DEF D0 08 bne PNY_SET ; yes it is, so we will handle different + 6091 ; + 6092 ; Bit is clear, so clear appropriate one in the SCR_DATA byte + 6093 ; + 6094 5DF1 68 pla ; get bit picture back + 6095 5DF2 49 FF eor #$FF ; turn bits all around + 6096 5DF4 25 13 and SCR_DATA ; turn off bit in screen data + 6097 5DF6 4C FC 5D jmp PNY_NEXT ; and continue + 6098 5DF9 PNY_SET: + 6099 5DF9 68 pla ; get bit mask back + 6100 5DFA 05 13 ora SCR_DATA ; turn on bit + Tue Jun 13 1989 11:42 Page 89 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6101 5DFC PNY_NEXT: + 6102 5DFC 85 13 sta SCR_DATA ; save result + 6103 5DFE E6 11 inc BITOFF ; we're looking at next bit + 6104 5E00 A5 11 lda BITOFF ; now check how we're doing + 6105 5E02 C9 07 cmp #7 ; only doing bits 0-6 + 6106 5E04 D0 DB bne PNY1 ; check next bit + 6107 ; + 6108 ; we've finished this byte in screen memory, point to next one + 6109 ; + 6110 5E06 A9 00 lda #0 ; start at zero'th bit + 6111 5E08 85 11 sta BITOFF ; thank you + 6112 5E0A A5 13 lda SCR_DATA ; now stash this one in the screen + 6113 5E0C 91 8C sta (FPC),Y ; y is still zero; still pointing to bank + 6114 5E0E 20 1D 5E jsr NEXT_SCR ; make SPC/FPC point to next spot + 6115 5E11 4C D6 5D jmp PNY0 ; and continue on please + 6116 ; + 6117 ; all done, so make sure we stash anything out there + 6118 ; + 6119 5E14 PNY_EXIT: + 6120 5E14 68 pla ; get bit mask back to fix stack + 6121 5E15 A5 13 lda SCR_DATA ; put away the current data byte + 6122 5E17 91 8C sta (FPC),Y ; y is still zero; still pointing to bank + 6123 5E19 AD 54 C0 lda PAGE2SW+MAIN ; back to MAIN page 2 + 6124 5E1C 60 rts + 6125 ; + 6126 ; NEXT_SCR - make FPC/SPC point to next screen byte + 6127 ; + 6128 5E1D NEXT_SCR: + 6129 ; + 6130 ; if in main bank, when we go to aux bank, we need to look at the next + 6131 ; byte in memory + 6132 ; + 6133 5E1D A5 8E lda FPCBNK ; get what bank we're talking to currently + 6134 5E1F D0 08 bne NXS0 ; 0 = main bank, 1 = aux bank + 6135 5E21 E6 8F inc SPCL ; point to next byte + 6136 5E23 E6 8C inc FPCL ; and for fetching + 6137 5E25 A9 01 lda #AUX ; and point to aux bank + 6138 5E27 D0 02 bne NXS1 ; (BRANCH) and continue on + 6139 ; + 6140 ; if in aux bank, all we need to do is switch banks + 6141 ; + 6142 5E29 NXS0: + 6143 5E29 A9 00 lda #MAIN ; just make it main bank + 6144 5E2B NXS1: + 6145 5E2B 85 91 sta SPCBNK ; for stashing and + 6146 5E2D 85 8E sta FPCBNK ; fetching + 6147 5E2F 60 rts + 6148 ; + 6149 ; GET_NYBBLE - get the 4 bits which represent the screen at position + 6150 ; SCRCX, SCRCY; return nybble in low 4 bits of [A] + 6151 ; + 6152 5E30 01 02 04 08 10 GT_BITS: db 1,2,4,8,$10,$20,$40 + 5E35 20 40 + 6153 5E37 GET_NYBBLE: + 6154 5E37 20 78 5E jsr SETPOS ; set up offsets using SCRCX + 6155 + 6156 5E3A A9 00 lda #0 ; clear out my data spot + 6157 5E3C 85 0E sta NY_DATA ; for mucking with + 6158 + 6159 5E3E A9 10 lda #$10 ; setting bits 0-3, starting with shift + 6160 5E40 85 10 sta DATALOOP ; so init the setter + 6161 5E42 GNY0: + 6162 5E42 A6 8E ldx FPCBNK ; which bank + 6163 5E44 BD 54 C0 lda PAGE2SW,X ; save which bank + 6164 5E47 A0 00 ldy #0 ; zero y + 6165 5E49 B1 8C lda (FPC),Y ; get byte + 6166 5E4B 85 13 sta SCR_DATA ; and save it + 6167 5E4D GNY1: + 6168 5E4D 46 10 lsr DATALOOP ; see if we have done all 4 bits in this 'pixel' + 6169 5E4F F0 21 beq GNY_EXIT ; all done! + 6170 + 6171 5E51 A6 11 ldx BITOFF ; get bit offset + 6172 5E53 BD 30 5E lda GT_BITS,X ; get bit pattern + 6173 ; + 6174 ; now check appropriate bit in Screen Data + Tue Jun 13 1989 11:42 Page 90 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6175 ; + 6176 5E56 25 13 and SCR_DATA ; see if it is set + 6177 5E58 F0 06 beq GNY3 ; no bit set here + 6178 ; + 6179 ; bit is set, so set it in my data nybble + 6180 ; + 6181 5E5A A5 10 lda DATALOOP ; get bit setter + 6182 5E5C 05 0E ora NY_DATA ; and put it into my data byte + 6183 5E5E 85 0E sta NY_DATA ; and save it + 6184 5E60 GNY3: + 6185 5E60 E6 11 inc BITOFF ; we're looking at next bit + 6186 5E62 A5 11 lda BITOFF ; now check how we're doing + 6187 5E64 C9 07 cmp #7 ; only doing bits 0-6 + 6188 5E66 D0 E5 bne GNY1 ; check next bit + 6189 ; + 6190 ; we've finished this byte in screen memory, point to next one + 6191 ; + 6192 5E68 A9 00 lda #0 ; start at zero'th bit + 6193 5E6A 85 11 sta BITOFF ; thank you + 6194 5E6C 20 1D 5E jsr NEXT_SCR ; point to next byte + 6195 5E6F 4C 42 5E jmp GNY0 ; and continue on please + 6196 5E72 GNY_EXIT: + 6197 5E72 AD 54 C0 lda PAGE2SW+MAIN ; back to main page 2 + 6198 5E75 A5 0E lda NY_DATA ; get the nybble desired + 6199 5E77 60 rts + 6200 ; + 6201 ; SETPOS - get the byte offset and the bit offset from the table using + 6202 ; SCRCX + 6203 ; + 6204 ; USES: SCRCX, SCRCY + 6205 ; SETS: FPC - pointer to correct screen memory location + 6206 ; BITOFF - bit offset to get to start of byte (N.B. this is left to + 6207 ; right count, while in memory it is right to left!) + 6208 5E78 SETPOS: + 6209 5E78 A5 00 lda SCRCX ; get the x pos + 6210 5E7A AA tax ; put where we can use it + 6211 5E7B BD 52 03 lda XPOSTBL,X ; get byte # + 6212 5E7E 85 8C sta FPCL ; okay, saved + 6213 5E80 BD E0 6B lda XBITTBL,X ; get bitoffset + 6214 5E83 85 11 sta BITOFF ; where it wants it + 6215 + 6216 5E85 A5 8C lda FPCL ; check for correct bank + 6217 5E87 29 01 and #$01 ; if odd, then must be main bank + 6218 5E89 D0 04 bne STP11 ; okay, it be odd + 6219 5E8B A9 01 lda #AUX ; aux bank + 6220 5E8D D0 02 bne STP22 ; jump + 6221 5E8F STP11: + 6222 5E8F A9 00 lda #MAIN ; main bank + 6223 5E91 STP22: + 6224 5E91 85 8E sta FPCBNK ; save it + 6225 5E93 A5 8C lda FPCL ; get for fetch + 6226 5E95 4A lsr A ; /2 to get correct byte offset + 6227 5E96 A6 01 ldx SCRCY ; get vertical pos + 6228 5E98 18 clc ; get ready for adding + 6229 5E99 7D 60 6A adc BASEL,X ; add low part + 6230 5E9C 85 8C sta FPCL ; save low part + 6231 5E9E BD 20 6B lda BASEH,X ; get high part + 6232 5EA1 85 8D sta FPCH ; save high part + 6233 5EA3 60 rts ; done !? + 6234 ; + 6235 ; DO_EOL - if this is end of line, check if we are at end of window + 6236 ; and if we are, and it is a scrollable window, scroll. Then move + 6237 ; the cursor to the left margin of said window + 6238 ; + 6239 5EA4 DO_EOL: + 6240 5EA4 20 1A 72 jsr DISP_LINE ; make sure line gets out there + 6241 5EA7 A5 01 lda SCRCY ; get current vertical pos + 6242 5EA9 18 clc ; add font height + 6243 5EAA 69 09 adc #FONT_H ; thank you + 6244 5EAC 48 pha ; save this position + 6245 5EAD 69 09 adc #FONT_H ; make sure we have room for characters here + 6246 5EAF C5 02 cmp SCRBTM ; so check against the bottom + 6247 5EB1 F0 02 beq SAVECV ; no scroll yet + 6248 5EB3 B0 05 bcs SCROLLCITY ; nope, can't use it + 6249 5EB5 SAVECV: + Tue Jun 13 1989 11:42 Page 91 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6250 5EB5 68 pla ; get new CV + 6251 5EB6 85 01 sta SCRCY ; and save it + 6252 5EB8 D0 09 bne DEL1 ; JUMP + 6253 5EBA SCROLLCITY: + 6254 5EBA 68 pla ; get bad y pos + 6255 5EBB AD 05 72 lda SCRLFLG ; is this a scrolling window? + 6256 5EBE F0 03 beq DEL1 ; nope, just move to left edge + 6257 5EC0 20 16 60 jsr SCROLL_UP ; and scroll window + 6258 5EC3 DEL1: + 6259 ; + 6260 ; move cursor back to left margin + 6261 ; + 6262 5EC3 A5 04 lda LEFTMRG ; get left margin + 6263 5EC5 85 00 sta SCRCX ; and set itpositions + 6264 5EC7 A9 01 lda #1 ; show cursor changed (maybe) + 6265 5EC9 8D A5 6C sta CURSFLG ; okay + 6266 5ECC A9 00 lda #0 ; clear length too + 6267 5ECE 85 A7 sta LENGTH+LO ; no more on line + 6268 5ED0 85 A8 sta LENGTH+HI ; no more on line + 6269 5ED2 4C C8 5D jmp CH_EXIT ; now finish it up + 6270 ; + 6271 ; DO_BSPC - do a backspace, by erasing char just before cursor to + 6272 ; background color, and moving cursor back one space + 6273 ; [X] == character to delete + 6274 ; + 6275 5ED5 0000 SAVECHX: DW 0 + 6276 + 6277 5ED7 DO_BSPC: + 6278 5ED7 AD 01 72 lda CHR_X+LO ; figger new CHR_X + 6279 5EDA 38 sec ; subtract width + 6280 5EDB A4 C1 ldy FONTFLG ; get which font we be using + 6281 5EDD F0 05 beq DOBSP0 ; must be variable width + 6282 5EDF E9 0C sbc #MONOFONT_W ; get width then of mono font + 6283 5EE1 4C E7 5E jmp DOBSP1 ; okay, now do add + 6284 5EE4 DOBSP0: + 6285 5EE4 FD 53 64 sbc CHWID,X ; get width of char to be erased + 6286 5EE7 DOBSP1: + 6287 5EE7 8D 01 72 sta CHR_X+LO ; show new one + 6288 5EEA 8D D5 5E sta SAVECHX+LO ; save to restore later + 6289 5EED AD 02 72 lda CHR_X+HI ; and pick up carry + 6290 5EF0 E9 00 sbc #0 ; okay, did it + 6291 5EF2 8D 02 72 sta CHR_X+HI ; save it + 6292 5EF5 8D D6 5E sta SAVECHX+HI ; okay + 6293 5EF8 A0 20 ldy #SPACE ; get SPACE offset + 6294 5EFA A5 C1 lda FONTFLG ; monospaced font? + 6295 5EFC F0 04 beq DOBSP2 ; nope + 6296 5EFE A9 0C lda #MONOFONT_W ; make monospaced wide + 6297 5F00 D0 03 bne DOBSP3 ; fine + 6298 5F02 DOBSP2: + 6299 5F02 BD 53 64 lda CHWID,X ; get width of char + 6300 5F05 DOBSP3: + 6301 5F05 99 53 64 sta CHWID,Y ; set space to be this wide + 6302 5F08 8C 80 02 sty SCRBUFF ; make space for erasing + 6303 5F0B A9 01 lda #1 ; show one char + 6304 5F0D 8D 0D 72 sta SCRCNT ; assume it used to be zero + 6305 5F10 20 1A 72 jsr DISP_LINE ; put that space out + 6306 5F13 AD D5 5E lda SAVECHX+LO ; restore old/new x pos + 6307 5F16 8D 01 72 sta CHR_X+LO + 6308 5F19 AD D6 5E lda SAVECHX+HI + 6309 5F1C 8D 02 72 sta CHR_X+HI + 6310 5F1F 20 B3 73 jsr GET_SCRCX ; update SCRCX please + 6311 + 6312 5F22 A9 08 lda #SPACE_WIDTH ; restore width of space char + 6313 5F24 A0 20 ldy #SPACE ; get offset + 6314 5F26 99 53 64 sta CHWID,Y ; okay + 6315 + 6316 5F29 4C C8 5D jmp CH_EXIT ; done + 6317 ; + 6318 ; CLS - clear the window, using CLS parameters + 6319 ; + 6320 5F2C CLS: + 6321 5F2C A5 00 lda SCRCX ; save the current X,Y + 6322 5F2E 8D A8 5D sta SAVECX ; x + 6323 5F31 A5 01 lda SCRCY + 6324 5F33 8D A7 5D sta SAVECY ; saved + Tue Jun 13 1989 11:42 Page 92 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6325 5F36 A5 0B lda CLSTOP ; get top line + 6326 5F38 85 01 sta SCRCY ; and set up a y pos + 6327 + 6328 5F3A 20 E8 5F jsr SETMASK ; set up masks and ending point + 6329 + 6330 5F3D A5 BD lda CPY_COUNT ; get count + 6331 5F3F 85 14 sta SH_LOOP ; save count + 6332 5F41 A5 0A lda CLSLEFT ; get left edge + 6333 5F43 85 00 sta SCRCX ; set up as X pos + 6334 5F45 A0 0E ldy #WINBGND ; get background offset + 6335 5F47 B1 05 lda (WINDOW),Y ; get background color + 6336 5F49 85 71 sta ARG8 ; save it here + 6337 5F4B A5 0C lda CLSWIDTH ; how wide we be? + 6338 5F4D D0 05 bne CLSOKAY ; not a zero width + 6339 5F4F A9 19 lda #25 ; zero can't do zero width + 6340 5F51 4C F9 51 jmp ZERROR ; so die + 6341 5F54 CLSOKAY: + 6342 5F54 C9 03 cmp #3 ; if skinny, handle special + 6343 5F56 B0 28 bcs L1L0 ; nope + 6344 5F58 85 6F sta ARG7 ; make this be the counter + 6345 5F5A A5 0D lda CLSHEIGHT ; just use PUT/GET NYBBLE if only one wide + 6346 5F5C D0 05 bne CLSOKAY1 ; not a zero height either + 6347 5F5E A9 19 lda #25 ; bad error + 6348 5F60 4C F9 51 jmp ZERROR + 6349 5F63 CLSOKAY1: + 6350 5F63 85 7A sta J ; save here + 6351 5F65 CLS1W: + 6352 5F65 A5 71 lda ARG8 ; get color + 6353 5F67 20 CD 5D jsr PUT_NYBBLE ; put it + 6354 5F6A E6 00 inc SCRCX ; next x + 6355 5F6C C6 6F dec ARG7 ; counter + 6356 5F6E D0 F5 bne CLS1W ; do next X + 6357 5F70 A5 0A lda CLSLEFT ; get left edge again + 6358 5F72 85 00 sta SCRCX ; point to it + 6359 5F74 E6 01 inc SCRCY ; next line + 6360 5F76 A5 0C lda CLSWIDTH ; restore width count + 6361 5F78 85 6F sta ARG7 ; thanks + 6362 5F7A C6 7A dec J ; count + 6363 5F7C D0 E7 bne CLS1W ; do it + 6364 5F7E F0 56 beq CLSEXIT ; all done then + 6365 5F80 L1L0: + 6366 5F80 85 7A sta J ; use j as counter + 6367 5F82 L1L: + 6368 5F82 A5 71 lda ARG8 ; a color please + 6369 5F84 20 CD 5D jsr PUT_NYBBLE ; do first line easy + 6370 5F87 E6 00 inc SCRCX ; next nybble + 6371 5F89 C6 7A dec J ; done yet? + 6372 5F8B D0 F5 bne L1L ; nope + 6373 + 6374 5F8D A5 0A lda CLSLEFT ; where is left column + 6375 5F8F 85 00 sta SCRCX ; here! + 6376 5F91 20 78 5E jsr SETPOS ; get the address + 6377 5F94 20 A5 90 jsr FP2SP ; SPC is source PC, now! + 6378 5F97 A5 0D lda CLSHEIGHT ; how many lines are we clearing + 6379 5F99 D0 05 bne CLSOKAY2 ; not a zero height either + 6380 5F9B A9 19 lda #25 ; bad error + 6381 5F9D 4C F9 51 jmp ZERROR + 6382 5FA0 CLSOKAY2: + 6383 5FA0 85 7A sta J ; j is counter again + 6384 5FA2 C6 7A dec J ; already cleared one line + 6385 5FA4 F0 30 beq CLSEXIT ; only one line to do! + 6386 5FA6 CLSLOOP: + 6387 5FA6 A5 90 lda SPCH ; now, modify COPY_LINE + 6388 5FA8 8D 7D 1D sta CPY_MOD1_SRC+HI + 6389 5FAB 8D A1 1D sta CPY_MOD2_SRC+HI + 6390 5FAE A5 8F lda SPCL + 6391 5FB0 8D 7C 1D sta CPY_MOD1_SRC+LO + 6392 5FB3 8D A0 1D sta CPY_MOD2_SRC+LO + 6393 5FB6 E6 01 inc SCRCY ; clear this line + 6394 5FB8 20 78 5E jsr SETPOS ; where am i? + 6395 5FBB A5 8D lda FPCH ; now, modify COPY_LINE + 6396 5FBD 8D 80 1D sta CPY_MOD1_DST+HI + 6397 5FC0 8D A4 1D sta CPY_MOD2_DST+HI + 6398 5FC3 A5 8C lda FPCL + 6399 5FC5 8D 7F 1D sta CPY_MOD1_DST+LO + Tue Jun 13 1989 11:42 Page 93 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6400 5FC8 8D A3 1D sta CPY_MOD2_DST+LO + 6401 5FCB A5 14 lda SH_LOOP ; get count + 6402 5FCD 85 BD sta CPY_COUNT ; and save it + 6403 5FCF 20 50 1D jsr COPY_LINE ; did the copy (i hope) + 6404 5FD2 C6 7A dec J ; count it + 6405 5FD4 D0 D0 bne CLSLOOP ; next one please + 6406 5FD6 CLSEXIT: + 6407 5FD6 AD A8 5D lda SAVECX ; get X,Y back + 6408 5FD9 85 00 sta SCRCX ; got it + 6409 5FDB AD A7 5D lda SAVECY ; now for y + 6410 5FDE 85 01 sta SCRCY ; restored! + 6411 + 6412 5FE0 60 rts + 6413 ; + 6414 ; SETMASK - figger out the start and end masks, as well as setting + 6415 ; stuff to point to stopping address. Use CLSLEFT and CLSWIDTH + 6416 ; + 6417 5FE1 00 01 03 07 0F ST_BITS: db 0,1,3,7,$f,$1f,$3f + 5FE6 1F 3F + 6418 5FE8 SETMASK: + 6419 5FE8 A5 0A lda CLSLEFT ; munge with SCRX + 6420 5FEA 85 00 sta SCRCX ; okay + 6421 5FEC 20 78 5E jsr SETPOS ; get me the bit offset of start + 6422 + 6423 5FEF A6 11 ldx BITOFF ; now set up mask + 6424 5FF1 BD E1 5F lda ST_BITS,X ; get the bit pattern + 6425 5FF4 85 1A sta STMASK ; save it + 6426 + 6427 5FF6 A5 0A lda CLSLEFT ; get left edge again + 6428 5FF8 18 clc ; add width + 6429 5FF9 65 0C adc CLSWIDTH ; to get where to stop + 6430 5FFB AA tax ; make index + 6431 5FFC 86 00 stx SCRCX ; set cur pos + 6432 5FFE BD 52 03 lda XPOSTBL,X ; get how many bytes + 6433 6001 A6 0A ldx CLSLEFT ; subtract from byte offset of start + 6434 6003 38 sec ; subbing + 6435 6004 FD 52 03 sbc XPOSTBL,X + 6436 6007 85 BD sta CPY_COUNT ; and save it + 6437 6009 E6 BD inc CPY_COUNT ; and make it inclusive count + 6438 + 6439 600B 20 78 5E jsr SETPOS ; so get its address + 6440 + 6441 600E A6 11 ldx BITOFF ; get bit offset + 6442 6010 BD E1 5F lda ST_BITS,X ; get pattern + 6443 6013 85 1B sta ENDMASK ; okay! + 6444 6015 60 rts + 6445 ; + 6446 ; SCROLL_UP - roll the current window by FONT_H lines + 6447 ; + 6448 6016 SCROLL_UP: + 6449 6016 A9 09 lda #FONT_H ; show one line + 6450 6018 85 18 sta SCLLINES ; done + 6451 601A 85 1D sta SCLDIR ; show scroll up with positive number + 6452 601C A0 00 ldy #WINTOP ; get top of screen + 6453 601E B1 05 lda (WINDOW),Y ; got it + 6454 6020 85 0B sta CLSTOP ; saved it + 6455 6022 C8 iny ; point to left edge + 6456 6023 B1 05 lda (WINDOW),Y ; get left edge + 6457 6025 85 0A sta CLSLEFT ; save + 6458 6027 C8 iny ; this is now the height + 6459 6028 B1 05 lda (WINDOW),Y ; get window height + 6460 602A 85 0D sta CLSHEIGHT ; show me + 6461 602C C8 iny ; and now for the width + 6462 602D B1 05 lda (WINDOW),Y ; get width + 6463 602F 85 0C sta CLSWIDTH ; saved it + 6464 ; so fall thru + 6465 ; and do the scrolling + 6466 ; FALLING THRU + 6467 ; | + 6468 ; \ / + 6469 ; + 6470 ; + 6471 ; DO_SCROLL - scroll SCLLINES withing the window as defined by + 6472 ; CLSLEFT,TOP,WIDTH, and HEIGHT + 6473 ; + Tue Jun 13 1989 11:42 Page 94 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6474 6031 DO_SCROLL: + 6475 6031 A5 00 lda SCRCX ; save the current X,Y + 6476 6033 8D A8 5D sta SAVECX ; x + 6477 6036 A5 01 lda SCRCY + 6478 6038 8D A7 5D sta SAVECY ; saved + 6479 603B A5 18 lda SCLLINES ; how many lines? + 6480 + 6481 603D A6 1D ldx SCLDIR ; which direction? + 6482 603F 10 04 bpl SC1 ; >0 means scroll up + 6483 ; + 6484 ; scroll down, so we are going to start at the bottom and copy downwards + 6485 ; until we reach the top + 6486 ; + 6487 ; now modify code so we do adds to get destination line and subtracts + 6488 ; to get new src line + 6489 ; + 6490 6041 A0 C6 ldy #$C6 ; 'dec' opcode + 6491 6043 D0 04 bne SC2 ; jump to modify + 6492 6045 SC1: + 6493 ; + 6494 ; scroll up - start at top and copy upwards until we reach the bottom + 6495 ; + 6496 6045 A0 E6 ldy #$E6 ; 'inc' opcode + 6497 6047 A6 18 ldx SCLLINES ; get # of scrolling lines + 6498 6049 SC2: + 6499 6049 8C 00 61 sty SCMOD1 ; make inc/dec + 6500 604C 8C 02 61 sty SCMOD2 ; either inc or dec + 6501 604F 86 1C stx SCOFF ; save the offset between SRC and DST + 6502 + 6503 6051 A5 1D lda SCLDIR ; which direction? + 6504 6053 10 13 bpl SC3 ; must be normal scroll + 6505 ; + 6506 ; if scrolling downwards, we need to start source at bottom-offset and + 6507 ; end when the destination is at top+offset + 6508 ; + 6509 6055 A5 0D lda CLSHEIGHT ; get # of lines in window + 6510 6057 38 sec ; subbing + 6511 6058 E5 1C sbc SCOFF ; subtract offset to get source + 6512 605A 18 clc ; adding + 6513 605B 65 0B adc CLSTOP ; and get absolute position + 6514 605D AA tax ; put in X + 6515 605E CA dex ; for 0 offset it + 6516 605F A5 0B lda CLSTOP ; now figger last line to copy + 6517 6061 18 clc ; adding + 6518 6062 65 0D adc CLSHEIGHT ; get me last line + 6519 6064 A8 tay ; for later storage + 6520 6065 88 dey ; make 0 based + 6521 6066 D0 08 bne SC4 ; always jumps + 6522 6068 SC3: + 6523 ; + 6524 ; if scrolling upwards, start src at top+offset and end when destination + 6525 ; is at bottom-offset + 6526 ; + 6527 6068 A5 0B lda CLSTOP ; get top + 6528 606A 18 clc ; adding + 6529 606B 65 1C adc SCOFF ; add in offset + 6530 606D AA tax ; for later on + 6531 606E A4 0B ldy CLSTOP ; first destination is top of window + 6532 6070 SC4: + 6533 6070 86 01 stx SCRCY ; Starting Source + 6534 6072 84 15 sty SCROLLY ; Starting Destination + 6535 + 6536 6074 20 E8 5F jsr SETMASK ; set the masks and horizontal endpoint + 6537 6077 A5 BD lda CPY_COUNT ; save for future generations + 6538 6079 85 14 sta SH_LOOP ; save it + 6539 607B A5 0D lda CLSHEIGHT ; how high + 6540 607D 85 10 sta DATALOOP ; save as counter + 6541 607F 38 sec ; for subbing + 6542 6080 E5 1C sbc SCOFF ; subtract scrolling amount + 6543 6082 85 0D sta CLSHEIGHT ; this is how many lines to copy + 6544 6084 A5 01 lda SCRCY ; save Start Source + 6545 6086 48 pha + 6546 6087 A5 0B lda CLSTOP ; start at Y pos + 6547 6089 85 01 sta SCRCY + 6548 608B A5 0A lda CLSLEFT ; and x pos + Tue Jun 13 1989 11:42 Page 95 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6549 608D 85 00 sta SCRCX ; thank you + 6550 608F AD 54 C0 lda PAGE2SW+MAIN ; make sure main memory page is in there + 6551 6092 SCRL1: + 6552 6092 20 78 5E jsr SETPOS ; set up line pointer + 6553 6095 A4 01 ldy SCRCY ; get top + 6554 6097 C0 78 cpy #120 ; 120 bytes per list + 6555 6099 90 05 bcc SCRLY ; all set + 6556 609B 98 tya ; for adding + 6557 609C 18 clc + 6558 609D 69 08 adc #8 + 6559 609F A8 tay + 6560 60A0 SCRLY: + 6561 60A0 A5 8D lda FPCH + 6562 60A2 99 00 06 sta SV_PCH,Y + 6563 60A5 A5 8C lda FPCL + 6564 60A7 99 00 04 sta SV_PCL,Y + 6565 60AA E6 01 inc SCRCY ; next line please + 6566 60AC C6 10 dec DATALOOP + 6567 60AE D0 E2 bne SCRL1 + 6568 + 6569 60B0 68 pla ; get StartSource back + 6570 60B1 85 01 sta SCRCY + 6571 60B3 A5 8E lda FPCBNK ; init SPC bank too + 6572 60B5 85 91 sta SPCBNK ; fine, we did + 6573 60B7 SCROLLING: + 6574 60B7 A4 01 ldy SCRCY ; get source Y for index + 6575 60B9 C0 78 cpy #120 ; jump over junk + 6576 60BB 90 05 bcc SCLYY + 6577 60BD 98 tya + 6578 60BE 18 clc + 6579 60BF 69 08 adc #8 + 6580 60C1 A8 tay + 6581 60C2 SCLYY: + 6582 60C2 B9 00 06 lda SV_PCH,Y + 6583 60C5 85 90 sta SPCH + 6584 60C7 8D 7D 1D sta CPY_MOD1_SRC+HI + 6585 60CA 8D A1 1D sta CPY_MOD2_SRC+HI + 6586 60CD B9 00 04 lda SV_PCL,Y + 6587 60D0 8D 7C 1D sta CPY_MOD1_SRC+LO + 6588 60D3 8D A0 1D sta CPY_MOD2_SRC+LO + 6589 60D6 85 8F sta SPCL + 6590 + 6591 60D8 A4 15 ldy SCROLLY ; get destination Y pos + 6592 60DA C0 78 cpy #120 ; jump over junk + 6593 60DC 90 05 bcc SCLYY1 + 6594 60DE 98 tya + 6595 60DF 18 clc + 6596 60E0 69 08 adc #8 + 6597 60E2 A8 tay + 6598 60E3 SCLYY1: + 6599 60E3 B9 00 06 lda SV_PCH,Y + 6600 60E6 85 8D sta FPCH + 6601 60E8 8D 80 1D sta CPY_MOD1_DST+HI + 6602 60EB 8D A4 1D sta CPY_MOD2_DST+HI + 6603 60EE B9 00 04 lda SV_PCL,Y + 6604 60F1 8D 7F 1D sta CPY_MOD1_DST+LO + 6605 60F4 8D A3 1D sta CPY_MOD2_DST+LO + 6606 60F7 85 8C sta FPCL + 6607 + 6608 60F9 A5 14 lda SH_LOOP ; get byte counter + 6609 60FB 85 BD sta CPY_COUNT ; show copy line + 6610 60FD 20 50 1D jsr COPY_LINE ; and do the copy + 6611 6100 E6 01 SCMOD1: inc SCRCY ; inc or dec to get next one + 6612 6102 E6 15 SCMOD2: inc SCROLLY ; inc/dec for next destination Y + 6613 6104 C6 0D dec CLSHEIGHT ; count down + 6614 6106 D0 AF bne SCROLLING ; nope + 6615 + 6616 6108 A6 1D ldx SCLDIR ; scroll up or down? + 6617 610A 10 09 bpl SCLCLR1 ; clear a little different + 6618 ; + 6619 ; if scrolling down, clear from current Y+1 + 6620 ; + 6621 610C A5 01 lda SCRCY ; get current source + 6622 610E 85 0B sta CLSTOP ; save in top spot + 6623 6110 E6 0B inc CLSTOP ; get inside window + Tue Jun 13 1989 11:42 Page 96 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6624 6112 4C 19 61 jmp SCLCLR2 + 6625 6115 SCLCLR1: + 6626 6115 A5 15 lda SCROLLY ; get last destination + 6627 6117 85 0B sta CLSTOP ; and save it + 6628 6119 SCLCLR2: + 6629 6119 A5 1C lda SCOFF ; and both clear this many lines + 6630 611B 85 0D sta CLSHEIGHT ; okay? + 6631 + 6632 611D AD A8 5D lda SAVECX ; now restore X and Y + 6633 6120 85 00 sta SCRCX ; x + 6634 6122 AD A7 5D lda SAVECY ; and + 6635 6125 85 01 sta SCRCY ; y + 6636 + 6637 6127 20 2C 5F jsr CLS ; WIDTH and LEFT should be okay still + 6638 + 6639 612A 60 rts + 6640 ; + 6641 ; CLREOL - clear from current cursor position to end of line by + 6642 ; using CLS after changing the window size + 6643 ; + 6644 612B CLREOL: + 6645 612B A5 00 lda SCRCX ; and make left be where cursor is + 6646 612D 85 0A sta CLSLEFT + 6647 612F A5 01 lda SCRCY ; and top be where Y is + 6648 6131 85 0B sta CLSTOP + 6649 6133 A9 09 lda #FONT_H ; and bottom be bottom of char + 6650 6135 85 0D sta CLSHEIGHT + 6651 6137 A0 03 ldy #WINWID ; get width + 6652 6139 B1 05 lda (WINDOW),Y ; got it + 6653 613B 18 clc ; now adding + 6654 613C A0 01 ldy #WINLEFT ; the left edge + 6655 613E 71 05 adc (WINDOW),Y ; to get the right edge + 6656 6140 38 sec ; subbing + 6657 6141 E5 0A sbc CLSLEFT ; and subtract left to get width + 6658 6143 A0 07 ldy #WINRM ; remove the size of the right margin + 6659 6145 F1 05 sbc (WINDOW),Y ; that too + 6660 6147 85 0C sta CLSWIDTH ; okay? + 6661 6149 4C 2C 5F jmp CLS ; now clear the screen + 6662 ; + 6663 ; COPY_SCRL - copy from SCR_LINE onto the screen. CH_OFFSET says how + 6664 ; many bytes in SCR_LINE to copy. FPC is assumed to be pointing + 6665 ; to start of screen bytes. BITTER has the original BITOFF from + 6666 ; SETPOS. ENDBIT shows how many significant bits in last byte. + 6667 ; + 6668 614C COPY_SCRL: + 6669 614C AE 0C 72 ldx SHOW_CURSOR ; are we showing the cursor (ugh) + 6670 614F F0 03 beq COPYL2 ; nope + 6671 6151 4C CB 73 jmp DO_CURSOR ; then XOR cursor in + 6672 6154 COPYL2: + 6673 6154 A0 0E ldy #WINBGND ; get background offset + 6674 6156 B1 05 lda (WINDOW),Y ; get current background color + 6675 6158 F0 03 beq COPY_SCRL1 ; if black, ignore this + 6676 615A 20 1B 62 jsr FIX_COLOR ; or in the color, please + 6677 ; + 6678 ; Alternate entry point for COPY_SCRL, used by picture drawing routine + 6679 ; to avoid using background color and checking for cursor + 6680 ; + 6681 615D COPY_SCRL1: + 6682 615D A6 8E ldx FPCBNK ; set up bank + 6683 615F BD 54 C0 lda PAGE2SW,X ; set first bank + 6684 6162 AD 03 72 lda ENDBIT ; did we end evenly? + 6685 6165 D0 02 bne COPYL22 ; nope + 6686 6167 E6 0F inc CH_OFFSET ; make CH_OFFSET be a counter + 6687 6169 COPYL22: + 6688 6169 A0 00 ldy #0 ; zero y + 6689 + 6690 616B A5 0F lda CH_OFFSET ; if only one, then handle real special + 6691 616D D0 24 bne COPYL21 ; nope + 6692 + 6693 616F AE 0A 72 ldx BITTER ; get starting bit offset + 6694 6172 BD E1 5F lda ST_BITS,X ; get starting bit mask + 6695 6175 85 AC sta IOCHAR ; save it + 6696 6177 AE 03 72 ldx ENDBIT ; get ending bit offset + 6697 617A BD E1 5F lda ST_BITS,X ; combine with ending mask bits + 6698 617D 49 FF eor #$FF ; set for good ones + Tue Jun 13 1989 11:42 Page 97 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6699 617F 05 AC ora IOCHAR ; set up mask for bits + 6700 6181 31 8C and (FPC),Y ; get me interesting bits + 6701 6183 91 8C sta (FPC),Y ; save + 6702 6185 A5 AC lda IOCHAR ; get flag for data + 6703 6187 49 FF eor #$FF ; flip to get good data + 6704 6189 2D 00 1F CPYSM1: and SCR_LINE ; pick up my bits + 6705 618C 11 8C ora (FPC),Y ; and or in screen data + 6706 618E 91 8C sta (FPC),Y ; and save it + 6707 6190 4C 17 62 jmp COPYLEX ; go away now + 6708 6193 COPYL21: + 6709 6193 A5 0F lda CH_OFFSET ; get # of chars + 6710 6195 4A lsr A ; /2 get number in this bank + 6711 6196 69 00 adc #0 ; pick up carry for first one + 6712 6198 85 10 sta DATALOOP ; and save it to work on + 6713 + 6714 619A AE 0A 72 ldx BITTER ; do we have a weird start? + 6715 619D F0 1A beq DLL2 ; nope + 6716 ; + 6717 ; need to do the first one special + 6718 ; + 6719 619F B1 8C lda (FPC),Y ; get byte + 6720 61A1 3D E1 5F and ST_BITS,X ; get masking bits + 6721 61A4 85 AC sta IOCHAR ; save for later + 6722 61A6 BD E1 5F lda ST_BITS,X ; get masking bits again + 6723 61A9 49 FF eor #$FF ; get good bits + 6724 61AB 2D 00 1F CPYSM2: and SCR_LINE ; get first data byte + 6725 61AE 05 AC ora IOCHAR ; pick up screen bits + 6726 61B0 91 8C sta (FPC),Y ; pointing + 6727 61B2 C8 iny ; next byte + 6728 61B3 A2 02 ldx #2 ; start at next one for this bank + 6729 61B5 C6 10 dec DATALOOP ; kount as done + 6730 61B7 COPYLOOP: + 6731 61B7 F0 0C beq CPYLP2 ; all done with this part of line + 6732 61B9 DLL2: + 6733 61B9 BD 00 1F CPYSM3: lda SCR_LINE,X ; get data + 6734 61BC 91 8C sta (FPC),Y ; pointing + 6735 61BE C8 iny ; next byte + 6736 61BF E8 inx ; next one + 6737 61C0 E8 inx ; next one + 6738 61C1 C6 10 dec DATALOOP ; count as used + 6739 61C3 10 F2 bpl COPYLOOP ; start loop again + 6740 61C5 CPYLP2: + 6741 61C5 A0 00 ldy #0 ; reset Y + 6742 61C7 A5 8E lda FPCBNK ; which bank were we at + 6743 61C9 49 01 eor #1 ; swap to other one + 6744 61CB AA tax ; make it in x + 6745 61CC BD 54 C0 lda PAGE2SW,X ; swap to write bank + 6746 61CF 8A txa ; check which one + 6747 61D0 F0 01 beq CPYLP23 ; correct offset + 6748 61D2 C8 iny ; fix offset if going from main to aux + 6749 61D3 CPYLP23: + 6750 61D3 A2 01 ldx #1 ; start at second byte in screen line + 6751 61D5 A5 0F lda CH_OFFSET ; get starting number + 6752 61D7 4A lsr A ; /2 to get how many for this bank + 6753 61D8 85 10 sta DATALOOP ; and show it + 6754 61DA COPYLOOP2: + 6755 61DA F0 0C beq LINE_DONE ; all done with this part of line + 6756 + 6757 61DC BD 00 1F CPYSM4: lda SCR_LINE,X ; get data + 6758 61DF 91 8C sta (FPC),Y ; pointing + 6759 61E1 C8 iny ; next byte + 6760 61E2 E8 inx ; next one + 6761 61E3 E8 inx ; next one + 6762 61E4 C6 10 dec DATALOOP ; count as used + 6763 61E6 10 F2 bpl COPYLOOP2 ; start loop again + 6764 61E8 LINE_DONE: + 6765 ; + 6766 ; do the last byte special + 6767 ; + 6768 61E8 86 10 stx DATALOOP ; save pointer + 6769 61EA AD 03 72 lda ENDBIT ; get ending bit offset + 6770 61ED F0 28 beq COPYLEX ; all done if nothing funky + 6771 61EF 46 0F lsr CH_OFFSET ; get line offset + 6772 61F1 48 pha ; save [A] + 6773 61F2 B0 0B bcs LINED1 ; if odd, point at right things + Tue Jun 13 1989 11:42 Page 98 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6774 61F4 C6 10 dec DATALOOP ; one less then + 6775 61F6 A6 8E ldx FPCBNK ; get original bank + 6776 61F8 BD 54 C0 lda PAGE2SW,X ; switch to it + 6777 61FB 8A txa ; which bank did we do? + 6778 61FC D0 01 bne LINED1 ; no need to step back one + 6779 61FE 88 dey ; point one less here too + 6780 61FF LINED1: + 6781 61FF 68 pla ; get ENDBIT back + 6782 6200 AA tax ; make end bits be index + 6783 6201 BD E1 5F lda ST_BITS,X ; get end mask + 6784 6204 85 AC sta IOCHAR ; save mask bits + 6785 6206 49 FF eor #$FF ; toggle every bit + 6786 6208 31 8C and (FPC),Y ; get the interesting bits in byte + 6787 620A 91 8C sta (FPC),Y ; save it + 6788 620C A6 10 ldx DATALOOP ; get data pointer + 6789 620E BD 00 1F CPYSM5: lda SCR_LINE,X ; turn on my bits + 6790 6211 25 AC and IOCHAR ; pick up my good bits + 6791 6213 11 8C ora (FPC),Y ; bring everything together + 6792 6215 91 8C sta (FPC),Y ; save the byte + 6793 6217 COPYLEX: + 6794 6217 AD 54 C0 lda PAGE2SW+MAIN ; back to main, thanks + 6795 621A 60 rts + 6796 + 6797 621B FIX_COLOR: + 6798 621B E6 0F inc CH_OFFSET ; just to make checking easier for now + 6799 + 6800 621D 0A asl A ; *2 + 6801 621E 0A asl A ; *4 to get correct offset + 6802 621F 69 12 adc #COLORS ; get hi part + 6805 6225 69 00 adc #0 ; pick up maybe carry + 6806 6227 85 AE sta COLORP+HI ; save pointer + 6807 6229 A2 11 ldx #$11 ; ORA (),Y opcode + 6808 622B A0 0D ldy #WINFORE ; check foreground color + 6809 622D B1 05 lda (WINDOW),Y ; check what color + 6810 622F D0 11 bne FIXC1 ; just leave white if not black + 6811 6231 A2 00 ldx #0 ; start at beginning + 6812 6233 FIXMUNGEL: + 6813 6233 BD 00 1F lda SCR_LINE,X ; get byte + 6814 6236 49 FF eor #$FF ; swap all the bits + 6815 6238 9D 00 1F sta SCR_LINE,X ; store back + 6816 623B E8 inx ; count it + 6817 623C E4 0F cpx CH_OFFSET ; done? + 6818 623E 90 F3 bcc FIXMUNGEL ; nope + 6819 6240 A2 31 ldx #$31 ; AND (),Y opcode + 6820 6242 FIXC1: + 6821 6242 8E 50 62 stx FCLM ; self mod my code (again . . . sigh) + 6822 6245 AD 0A 72 lda BITTER ; get starting offset + 6823 6248 29 03 and #3 ; pick up wrap + 6824 624A A8 tay ; make index + 6825 624B A2 00 ldx #0 ; start at zero line + 6826 624D FIXLOOP: + 6827 624D BD 00 1F FCM1: lda SCR_LINE,X ; get screen byte + 6828 6250 11 AD FCLM: ora (COLORP),Y ; or with color byte + 6829 6252 9D 00 1F FCM2: sta SCR_LINE,X ; save it + 6830 6255 C8 iny ; next color byte + 6831 6256 C0 04 cpy #4 ; wrapped? + 6832 6258 D0 02 bne FIXLP1 ; nope + 6833 625A A0 00 ldy #0 ; restart + 6834 625C FIXLP1: + 6835 625C E8 inx ; next screen byte + 6836 625D E4 0F cpx CH_OFFSET ; done yet? + 6837 625F 90 EC bcc FIXLOOP ; nope + 6838 6261 + 6839 6261 C6 0F dec CH_OFFSET ; fix counter + 6840 6263 60 rts ; now we are done + 6841 ; + 6842 ; MSCURS - Erase the cursor from the old spot and write it in the + 6843 ; new spot + 6844 ; + 6845 6264 8C MOLDX: db MAXWIDTH ; spot to save x,y of mouse + 6846 6265 C0 MOLDY: db MAXHEIGHT + 6847 6266 MSCCNT: ds 1 + 6848 6267 SVCURS: ds CURSW*CURSH ; save room + Tue Jun 13 1989 11:42 Page 99 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6849 626F 01 MSWCNT: db 1 + 6850 6270 00 MSSTATE: db 0 ; 0 == off, 1 == on + 6851 6271 0F 07 07 07 07 MSCOLOR: db $f,7,7,7,7,7,7,7 + 6276 07 07 07 + 6852 ; + 6853 6279 MSCURS: + 6854 6279 A9 00 lda #0 ; clear moved flag + 6855 627B 8D 12 03 sta MSMOVEF ; we did + 6856 627E 20 84 62 jsr MSCOFF ; turn cursor off at current pos + 6857 6281 4C E3 62 jmp MSCON ; and turn it on in new spot + 6858 + 6859 ; + 6860 ; MSCOFF - mouse cursor off + 6861 ; Copy info from saved spot back onto screen @ MOLDX, MOLDY + 6862 6284 MSCOFF: + 6863 6284 AD 70 62 lda MSSTATE ; already off? + 6864 6287 D0 01 bne MSCOFF1 ; no + 6865 6289 60 rts ; done then + 6866 628A MSCOFF1: + 6867 628A A5 01 lda SCRCY ; save X,Y + 6868 628C 8D A7 5D sta SAVECY + 6869 628F A5 00 lda SCRCX + 6870 6291 8D A8 5D sta SAVECX + 6871 6294 AD 64 62 lda MOLDX ; point to old X,Y + 6872 6297 85 00 sta SCRCX + 6873 6299 AD 65 62 lda MOLDY + 6874 629C 85 01 sta SCRCY + 6875 629E A9 00 lda #0 ; start at beginning of saved area + 6876 62A0 8D 66 62 sta MSCCNT ; save counter + 6877 62A3 A9 02 lda #CURSW ; restore width + 6878 62A5 8D 6F 62 sta MSWCNT ; and counter + 6879 62A8 RENEWL: + 6880 62A8 A5 01 lda SCRCY ; check bounds + 6881 62AA C9 C0 cmp #MAXHEIGHT + 6882 62AC B0 32 bcs MSC1 ; all done + 6883 62AE RENEWL0: + 6884 62AE A5 00 lda SCRCX + 6885 62B0 C9 8C cmp #MAXWIDTH + 6886 62B2 B0 1E bcs RENEWL1 ; might not be done + 6887 62B4 20 37 5E jsr GET_NYBBLE ; get screen nybble + 6888 62B7 AE 66 62 ldx MSCCNT ; get counter + 6889 ; eor MSCOLOR,X ; xor to turn off + 6890 62BA 49 0F eor #$0F ; turn white/black + 6891 62BC 20 CD 5D jsr PUT_NYBBLE ; save nybble + 6892 62BF EE 66 62 inc MSCCNT ; point to next one + 6893 62C2 AD 66 62 lda MSCCNT ; get counter + 6894 62C5 C9 08 cmp #(CURSW*CURSH) ; done yet? + 6895 62C7 F0 17 beq MSC1 ; yup + 6896 62C9 CE 6F 62 dec MSWCNT ; count down one width + 6897 62CC F0 04 beq RENEWL1 ; it is + 6898 62CE E6 00 inc SCRCX ; next x + 6899 62D0 D0 DC bne RENEWL0 ; try again + 6900 62D2 RENEWL1: + 6901 62D2 AD 64 62 lda MOLDX ; reset X + 6902 62D5 85 00 sta SCRCX + 6903 62D7 A9 02 lda #CURSW ; restore width + 6904 62D9 8D 6F 62 sta MSWCNT ; and counter + 6905 62DC E6 01 inc SCRCY ; next y + 6906 62DE D0 C8 bne RENEWL ; okay try some more + 6907 62E0 MSC1: + 6908 62E0 4C 42 63 jmp MSCON4 ; done turning it off + 6909 ; + 6910 ; MSCON - turn mouse cursor on + 6911 ; Copy white pixels into area specified by MSX, MSY + 6912 ; + 6913 62E3 MSCON: + 6914 62E3 AD 70 62 lda MSSTATE ; already on? + 6915 62E6 F0 01 beq MSCON0 ; no + 6916 62E8 60 rts ; don't bother + 6917 62E9 MSCON0: + 6918 62E9 A5 01 lda SCRCY ; save X,Y + 6919 62EB 8D A7 5D sta SAVECY + 6920 62EE A5 00 lda SCRCX + 6921 62F0 8D A8 5D sta SAVECX + 6922 + Tue Jun 13 1989 11:42 Page 100 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6923 62F3 A5 CB lda MSX ; get mouse x + 6924 62F5 85 00 sta SCRCX ; set mouse X + 6925 62F7 8D 64 62 sta MOLDX ; save mouse x + 6926 62FA A5 CC lda MSY ; get mouse y + 6927 62FC 85 01 sta SCRCY ; set mouse Y + 6928 62FE 8D 65 62 sta MOLDY ; and mouse Y + 6929 6301 A9 00 lda #0 ; start at beginning of saved area + 6930 6303 8D 66 62 sta MSCCNT ; save counter + 6931 6306 A9 02 lda #CURSW ; restore width + 6932 6308 8D 6F 62 sta MSWCNT ; and counter + 6933 630B MSCON1: + 6934 630B A5 01 lda SCRCY ; check bounds + 6935 630D C9 C0 cmp #MAXHEIGHT + 6936 630F B0 31 bcs MSCON4 ; all done + 6937 6311 MSCON2: + 6938 6311 A5 00 lda SCRCX + 6939 6313 C9 8C cmp #MAXWIDTH + 6940 6315 B0 1E bcs MSCON3 ; might not be done + 6941 6317 20 37 5E jsr GET_NYBBLE ; save nybble + 6942 631A AE 66 62 ldx MSCCNT ; get counter + 6943 ; eor MSCOLOR,X ; get cursor color + 6944 631D 49 0F eor #$0F ; turn white/black + 6945 631F 20 CD 5D jsr PUT_NYBBLE ; put nybble + 6946 6322 EE 66 62 inc MSCCNT ; point to next one + 6947 6325 AD 66 62 lda MSCCNT ; check ending + 6948 6328 C9 08 cmp #(CURSW*CURSH) ; done yet? + 6949 632A F0 16 beq MSCON4 ; yup + 6950 632C CE 6F 62 dec MSWCNT ; count down one width + 6951 632F F0 04 beq MSCON3 ; finished for line + 6952 6331 E6 00 inc SCRCX ; next x + 6953 6333 D0 DC bne MSCON2 ; try again + 6954 6335 MSCON3: + 6955 6335 A5 CB lda MSX ; reset X + 6956 6337 85 00 sta SCRCX + 6957 6339 A9 02 lda #CURSW ; restore width + 6958 633B 8D 6F 62 sta MSWCNT ; and counter + 6959 633E E6 01 inc SCRCY ; next y + 6960 6340 D0 C9 bne MSCON1 ; okay try some more + 6961 6342 MSCON4: + 6962 6342 AD 70 62 lda MSSTATE ; get current state + 6963 6345 49 01 eor #$01 ; toggle it + 6964 6347 8D 70 62 sta MSSTATE ; bang + 6965 634A AD A8 5D lda SAVECX ; restore X,Y + 6966 634D 85 00 sta SCRCX + 6967 634F AD A7 5D lda SAVECY + 6968 6352 85 01 sta SCRCY + 6969 6354 60 rts + 6970 6355 + 6971 + 6972 6355 END + 6973 + 6974 6355 INCLUDE TABLES.ASM + 6975 6355 STTL "--- ZIP DATA TABLES ---" + 6976 PAGE + Tue Jun 13 1989 11:42 Page 101 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6977 6355 CHADR_H: + 6978 6355 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 635A 00 00 00 00 00 + 635F 00 00 00 00 00 + 6364 00 + 6979 6365 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 636A 00 00 00 00 00 + 636F 00 00 00 00 00 + 6374 00 + 6980 6375 64 64 64 64 65 db >C20,>C21,>C22,>C23,>C24,>C25,>C26,>C27 + 637A 65 65 65 + 6981 637D 65 65 65 65 65 DB >C28,>C29,>C2A,>C2B,>C2C,>C2D,>C2E,>C2F + 6382 65 65 65 + 6982 6385 65 65 65 65 65 db >C30,>C31,>C32,>C33,>C34,>C35,>C36,>C37 + 638A 65 66 66 + 6983 638D 66 66 66 66 66 DB >C38,>C39,>C3A,>C3B,>C3C,>C3D,>C3E,>C3F + 6392 66 66 66 + 6984 6395 66 66 66 66 66 db >C40,>C41,>C42,>C43,>C44,>C45,>C46,>C47 + 639A 66 66 66 + 6985 639D 67 67 67 67 67 DB >C48,>C49,>C4A,>C4B,>C4C,>C4D,>C4E,>C4F + 63A2 67 67 67 + 6986 63A5 67 67 67 67 67 db >C50,>C51,>C52,>C53,>C54,>C55,>C56,>C57 + 63AA 67 67 68 + 6987 63AD 68 68 68 68 68 DB >C58,>C59,>C5A,>C5B,>C5C,>C5D,>C5E,>C5F + 63B2 68 68 68 + 6988 63B5 68 68 68 68 68 db >C60,>C61,>C62,>C63,>C64,>C65,>C66,>C67 + 63BA 68 68 68 + 6989 63BD 69 69 69 69 69 DB >C68,>C69,>C6A,>C6B,>C6C,>C6D,>C6E,>C6F + 63C2 69 69 69 + 6990 63C5 69 69 69 69 69 db >C70,>C71,>C72,>C73,>C74,>C75,>C76,>C77 + 63CA 69 69 69 + 6991 63CD 69 6A 6A 6A 6A DB >C78,>C79,>C7A,>C7B,>C7C,>C7D,>C7E + 63D2 6A 6A + 6992 63D4 CHADR_L: + 6993 63D4 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 63D9 00 00 00 00 00 + 63DE 00 00 00 00 00 + 63E3 00 + 6994 63E4 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 63E9 00 00 00 00 00 + 63EE 00 00 00 00 00 + 63F3 00 + 6995 63F4 D2 E4 ED FF 11 db 8 + 6675 70 00 00 00 + 7050 6679 3F 80 71 C0 03 C3F DB 3f,80,71,c0,03,80,0e,00,0e,00,00,00,0e,00,00,00,00,00 ;? 10 + 667E 80 0E 00 0E 00 + 6683 00 00 0E 00 00 + 6688 00 00 00 + 7051 668B 1F F8 E0 0E E3 C40 DB 1f,f8,e0,0e,e3,e7,e6,77,e6,77,e3,bc,e0,00,1f,f8,00,00 ;@ 16 + 6690 E7 E6 77 E6 77 + 6695 E3 BC E0 00 1F + 669A F8 00 00 + 7052 669D 3F 80 71 C0 71 C41 DB 3f,80,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;A 10 + 66A2 C0 7F C0 71 C0 + 66A7 71 C0 71 C0 00 + 66AC 00 00 00 + 7053 66AF 7F 80 71 C0 71 C42 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,7f,80,00,00,00,00 ;B 10 + 66B4 C0 7F 00 71 C0 + 66B9 71 C0 7F 80 00 + 66BE 00 00 00 + 7054 66C1 3F 80 71 C0 70 C43 DB 3f,80,71,c0,70,00,70,00,70,00,71,c0,3f,80,00,00,00,00 ;C 10 + 66C6 00 70 00 70 00 + 66CB 71 C0 3F 80 00 + 66D0 00 00 00 + 7055 66D3 7F 80 71 C0 71 C44 DB 7f,80,71,c0,71,c0,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;D 10 + 66D8 C0 71 C0 71 C0 + 66DD 71 C0 7F 80 00 + 66E2 00 00 00 + 7056 66E5 7F 70 70 7F 70 C45 DB 7f,70,70,7f,70,70,7f,00,00 ;E 8 + 66EA 70 7F 00 00 + 7057 66EE 7F 70 70 7E 70 C46 DB 7f,70,70,7e,70,70,70,00,00 ;F 8 + 66F3 70 70 00 00 + 7058 66F7 3F 80 71 C0 70 C47 DB 3f,80,71,c0,70,00,73,c0,71,c0,71,c0,3f,80,00,00,00,00 ;G 10 + 66FC 00 73 C0 71 C0 + Tue Jun 13 1989 11:42 Page 104 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6701 71 C0 3F 80 00 + 6706 00 00 00 + 7059 6709 71 C0 71 C0 71 C48 DB 71,c0,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;H 10 + 670E C0 7F C0 71 C0 + 6713 71 C0 71 C0 00 + 6718 00 00 00 + 7060 671B 70 70 70 70 70 C49 DB 70,70,70,70,70,70,70,00,00 ;I 4 + 6720 70 70 00 00 + 7061 6724 01 C0 01 C0 01 C4A DB 01,c0,01,c0,01,c0,01,c0,71,c0,71,c0,3f,80,00,00,00,00 ;J 10 + 6729 C0 01 C0 71 C0 + 672E 71 C0 3F 80 00 + 6733 00 00 00 + 7062 6736 70 E0 71 C0 73 C4B DB 70,e0,71,c0,73,80,7f,00,73,80,71,c0,70,e0,00,00,00,00 ;K 11 + 673B 80 7F 00 73 80 + 6740 71 C0 70 E0 00 + 6745 00 00 00 + 7063 6748 70 70 70 70 70 C4C DB 70,70,70,70,70,70,7f,00,00 ;L 8 + 674D 70 7F 00 00 + 7064 6751 78 3C 7C 7C 7E C4D DB 78,3c,7c,7c,7e,fc,77,dc,73,9c,70,1c,70,1c,00,00,00,00 ;M 14 + 6756 FC 77 DC 73 9C + 675B 70 1C 70 1C 00 + 6760 00 00 00 + 7065 6763 78 70 7C 70 7E C4E DB 78,70,7c,70,7e,70,77,70,73,f0,71,f0,70,f0,00,00,00,00 ;N 12 + 6768 70 77 70 73 F0 + 676D 71 F0 70 F0 00 + 6772 00 00 00 + 7066 6775 3F 80 71 C0 71 C4F DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;O 10 + 677A C0 71 C0 71 C0 + 677F 71 C0 3F 80 00 + 6784 00 00 00 + 7067 6787 7F 80 71 C0 71 C50 DB 7f,80,71,c0,71,c0,7f,80,70,00,70,00,70,00,00,00,00,00 ;P 10 + 678C C0 7F 80 70 00 + 6791 70 00 70 00 00 + 6796 00 00 00 + 7068 6799 3F 80 71 C0 71 C51 DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,00,03,c0,00,00 ;Q 10 + 679E C0 71 C0 71 C0 + 67A3 71 C0 3F 00 03 + 67A8 C0 00 00 + 7069 67AB 7F 80 71 C0 71 C52 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,71,c0,00,00,00,00 ;R 10 + 67B0 C0 7F 00 71 C0 + 67B5 71 C0 71 C0 00 + 67BA 00 00 00 + 7070 67BD 3F 80 71 C0 78 C53 DB 3f,80,71,c0,78,00,1f,00,03,c0,71,c0,3f,80,00,00,00,00 ;S 10 + 67C2 00 1F 00 03 C0 + 67C7 71 C0 3F 80 00 + 67CC 00 00 00 + 7071 67CF 7F C0 0E 00 0E C54 DB 7f,c0,0e,00,0e,00,0e,00,0e,00,0e,00,0e,00,00,00,00,00 ;T 10 + 67D4 00 0E 00 0E 00 + 67D9 0E 00 0E 00 00 + 67DE 00 00 00 + 7072 67E1 71 C0 71 C0 71 C55 DB 71,c0,71,c0,71,c0,71,c0,71,c0,71,c0,1f,00,00,00,00,00 ;U 10 + 67E6 C0 71 C0 71 C0 + 67EB 71 C0 1F 00 00 + 67F0 00 00 00 + 7073 67F3 71 C0 71 C0 71 C56 DB 71,c0,71,c0,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;V 10 + 67F8 C0 71 C0 73 80 + 67FD 77 00 7E 00 00 + 6802 00 00 00 + 7074 6805 71 C7 71 C7 71 C57 DB 71,c7,71,c7,71,c7,71,c7,71,c7,71,dc,7f,f8,00,00,00,00 ;W 16 + 680A C7 71 C7 71 C7 + 680F 71 DC 7F F8 00 + 6814 00 00 00 + 7075 6817 71 C0 71 C0 71 C58 DB 71,c0,71,c0,71,c0,1f,00,71,c0,71,c0,71,c0,00,00,00,00 ;X 10 + 681C C0 1F 00 71 C0 + 6821 71 C0 71 C0 00 + 6826 00 00 00 + 7076 6829 71 C0 71 C0 71 C59 DB 71,c0,71,c0,71,c0,3f,80,0e,00,0e,00,0e,00,00,00,00,00 ;Y 10 + 682E C0 3F 80 0E 00 + 6833 0E 00 0E 00 00 + 6838 00 00 00 + 7077 683B 7F C0 01 C0 03 C5A DB 7f,c0,01,c0,03,80,0e,00,38,00,70,00,7f,c0,00,00,00,00 ;Z 10 + 6840 80 0E 00 38 00 + 6845 70 00 7F C0 00 + 684A 00 00 00 + 7078 684D 7F 70 70 70 70 C5B DB 7f,70,70,70,70,70,7f,00,00 ;[ 8 + Tue Jun 13 1989 11:42 Page 105 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6852 70 7F 00 00 + 7079 6856 70 00 38 00 1C C5C DB 70,00,38,00,1c,00,0e,00,07,00,03,80,01,c0,00,00,00,00 ;\ 10 + 685B 00 0E 00 07 00 + 6860 03 80 01 C0 00 + 6865 00 00 00 + 7080 6868 7F 07 07 07 07 C5D DB 7f,07,07,07,07,07,7f,00,00 ;] 8 + 686D 07 7F 00 00 + 7081 6871 00 00 0C 00 3F C5E DB 00,00,0c,00,3f,00,e1,c0,00,00,00,00,00,00,00,00,00,00 ;^ 10 + 6876 00 E1 C0 00 00 + 687B 00 00 00 00 00 + 6880 00 00 00 + 7082 6883 00 00 00 00 00 C5F DB 00,00,00,00,00,00,00,ff,00 ;_ 8 + 6888 00 00 FF 00 + 7083 688C 70 38 1C 00 00 C60 DB 70,38,1c,00,00,00,00,00,00 ;` 6 + 6891 00 00 00 00 + 7084 6895 00 00 00 00 3F C61 DB 00,00,00,00,3f,80,01,c0,3f,c0,71,c0,3f,c0,00,00,00,00 ;a 10 + 689A 80 01 C0 3F C0 + 689F 71 C0 3F C0 00 + 68A4 00 00 00 + 7085 68A7 70 00 70 00 7F C62 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;b 10 + 68AC 80 71 C0 71 C0 + 68B1 71 C0 7F 80 00 + 68B6 00 00 00 + 7086 68B9 00 00 00 00 3F C63 DB 00,00,00,00,3f,80,71,c0,70,00,71,c0,3f,80,00,00,00,00 ;c 10 + 68BE 80 71 C0 70 00 + 68C3 71 C0 3F 80 00 + 68C8 00 00 00 + 7087 68CB 01 C0 01 C0 3F C64 DB 01,c0,01,c0,3f,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;d 10 + 68D0 C0 71 C0 71 C0 + 68D5 71 C0 3F C0 00 + 68DA 00 00 00 + 7088 68DD 00 00 00 00 3F C65 DB 00,00,00,00,3f,80,79,c0,7f,c0,70,00,3f,80,00,00,00,00 ;e 10 + 68E2 80 79 C0 7F C0 + 68E7 70 00 3F 80 00 + 68EC 00 00 00 + 7089 68EF 0F 1C 7F 1C 1C C66 DB 0f,1c,7f,1c,1c,1c,1c,00,00 ;f 8 + 68F4 1C 1C 00 00 + 7090 68F8 00 00 00 00 3F C67 DB 00,00,00,00,3f,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;g 10 + 68FD C0 71 C0 71 C0 + 6902 71 C0 3F C0 01 + 6907 C0 3F 80 + 7091 690A 70 00 70 00 7F C68 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;h 10 + 690F 80 71 C0 71 C0 + 6914 71 C0 71 C0 00 + 6919 00 00 00 + 7092 691C 70 00 70 70 70 C69 DB 70,00,70,70,70,70,70,00,00 ;i 5 + 6921 70 70 00 00 + 7093 6925 0E 00 0E 0E 0E C6A DB 0e,00,0e,0e,0e,0e,0e,0e,7c ;j 8 + 692A 0E 0E 0E 7C + 7094 692E 70 00 70 00 71 C6B DB 70,00,70,00,71,c0,73,80,7f,00,73,80,71,c0,00,00,00,00 ;k 10 + 6933 C0 73 80 7F 00 + 6938 73 80 71 C0 00 + 693D 00 00 00 + 7095 6940 70 70 70 70 70 C6C DB 70,70,70,70,70,70,70,00,00 ;l 5 + 6945 70 70 00 00 + 7096 6949 00 00 00 00 7F C6D DB 00,00,00,00,7f,fc,73,9c,73,9c,73,9c,73,9c,00,00,00,00 ;m 14 + 694E FC 73 9C 73 9C + 6953 73 9C 73 9C 00 + 6958 00 00 00 + 7097 695B 00 00 00 00 7F C6E DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;n 10 + 6960 80 71 C0 71 C0 + 6965 71 C0 71 C0 00 + 696A 00 00 00 + 7098 696D 00 00 00 00 3F C6F DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;o 10 + 6972 80 71 C0 71 C0 + 6977 71 C0 3F 80 00 + 697C 00 00 00 + 7099 697F 00 00 00 00 7F C70 DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,7f,80,70,00,70,00 ;p 10 + 6984 80 71 C0 71 C0 + 6989 71 C0 7F 80 70 + 698E 00 70 00 + 7100 6991 00 00 00 00 3F C71 DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,c0,01,c0,01,c0 ;q 10 + 6996 80 71 C0 71 C0 + 699B 71 C0 3F C0 01 + 69A0 C0 01 C0 + Tue Jun 13 1989 11:42 Page 106 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 7101 69A3 00 00 77 7C 70 C72 DB 00,00,77,7c,70,70,70,00,00 ;r 8 + 69A8 70 70 00 00 + 7102 69AC 00 00 00 00 3F C73 DB 00,00,00,00,3f,00,70,00,1e,00,03,80,3f,00,00,00,00,00 ;s 9 + 69B1 00 70 00 1E 00 + 69B6 03 80 3F 00 00 + 69BB 00 00 00 + 7103 69BE 1C 1C 7F 1C 1C C74 DB 1c,1c,7f,1c,1c,1c,0f,00,00 ;t 8 + 69C3 1C 0F 00 00 + 7104 69C7 00 00 00 00 71 C75 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;u 10 + 69CC C0 71 C0 71 C0 + 69D1 71 C0 3F C0 00 + 69D6 00 00 00 + 7105 69D9 00 00 00 00 71 C76 DB 00,00,00,00,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;v 10 + 69DE C0 71 C0 73 80 + 69E3 77 00 7E 00 00 + 69E8 00 00 00 + 7106 69EB 00 00 00 00 73 C77 DB 00,00,00,00,73,9c,73,9c,73,9c,73,9c,7f,f8,00,00,00,00 ;w 14 + 69F0 9C 73 9C 73 9C + 69F5 73 9C 7F F8 00 + 69FA 00 00 00 + 7107 69FD 00 00 00 00 71 C78 DB 00,00,00,00,71,c0,71,c0,1f,00,71,c0,71,c0,00,00,00,00 ;x 10 + 6A02 C0 71 C0 1F 00 + 6A07 71 C0 71 C0 00 + 6A0C 00 00 00 + 7108 6A0F 00 00 00 00 71 C79 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;y 10 + 6A14 C0 71 C0 71 C0 + 6A19 71 C0 3F C0 01 + 6A1E C0 3F 80 + 7109 6A21 00 00 00 00 7F C7A DB 00,00,00,00,7f,c0,03,80,0e,00,38,00,7f,c0,00,00,00,00 ;z 10 + 6A26 C0 03 80 0E 00 + 6A2B 38 00 7F C0 00 + 6A30 00 00 00 + 7110 6A33 1F 38 38 F0 38 C7B DB 1f,38,38,f0,38,38,1f,00,00 ;} 8 + 6A38 38 1F 00 00 + 7111 6A3C 70 70 70 70 70 C7C DB 70,70,70,70,70,70,70,70,70 ;| 5 + 6A41 70 70 70 70 + 7112 6A45 F8 1C 1C 0F 1C C7D DB f8,1c,1c,0f,1c,1c,f8,00,00 ;} 8 + 6A4A 1C F8 00 00 + 7113 6A4E 00 00 00 00 3C C7E DB 00,00,00,00,3c,e0,e7,80,00,00,00,00,00,00,00,00,00,00 ;~ 11 + 6A53 E0 E7 80 00 00 + 6A58 00 00 00 00 00 + 6A5D 00 00 00 + 7114 ; + 7115 ; base addresses for the screen lines + 7116 ; + 7117 6A60 BASEL: + 7118 6A60 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A65 00 00 00 + 7119 6A68 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A6D 80 80 80 + 7120 6A70 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A75 00 00 00 + 7121 6A78 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A7D 80 80 80 + 7122 6A80 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A85 00 00 00 + 7123 6A88 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A8D 80 80 80 + 7124 6A90 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A95 00 00 00 + 7125 6A98 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A9D 80 80 80 + 7126 6AA0 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + 6AA5 28 28 28 + 7127 6AA8 A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6AAD A8 A8 A8 + 7128 6AB0 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + 6AB5 28 28 28 + 7129 6AB8 A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6ABD A8 A8 A8 + 7130 6AC0 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + 6AC5 28 28 28 + 7131 6AC8 A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6ACD A8 A8 A8 + 7132 6AD0 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + Tue Jun 13 1989 11:42 Page 107 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6AD5 28 28 28 + 7133 6AD8 A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6ADD A8 A8 A8 + 7134 6AE0 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6AE5 50 50 50 + 7135 6AE8 D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6AED D0 D0 D0 + 7136 6AF0 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6AF5 50 50 50 + 7137 6AF8 D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6AFD D0 D0 D0 + 7138 6B00 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6B05 50 50 50 + 7139 6B08 D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6B0D D0 D0 D0 + 7140 6B10 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6B15 50 50 50 + 7141 6B18 D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6B1D D0 D0 D0 + 7142 6B20 BASEH: + 7143 6B20 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B25 34 38 3C + 7144 6B28 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B2D 34 38 3C + 7145 6B30 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B35 35 39 3D + 7146 6B38 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B3D 35 39 3D + 7147 6B40 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B45 36 3A 3E + 7148 6B48 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B4D 36 3A 3E + 7149 6B50 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B55 37 3B 3F + 7150 6B58 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B5D 37 3B 3F + 7151 6B60 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B65 34 38 3C + 7152 6B68 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B6D 34 38 3C + 7153 6B70 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B75 35 39 3D + 7154 6B78 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B7D 35 39 3D + 7155 6B80 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B85 36 3A 3E + 7156 6B88 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B8D 36 3A 3E + 7157 6B90 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B95 37 3B 3F + 7158 6B98 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B9D 37 3B 3F + 7159 6BA0 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6BA5 34 38 3C + 7160 6BA8 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6BAD 34 38 3C + 7161 6BB0 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6BB5 35 39 3D + 7162 6BB8 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6BBD 35 39 3D + 7163 6BC0 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6BC5 36 3A 3E + 7164 6BC8 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6BCD 36 3A 3E + 7165 6BD0 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6BD5 37 3B 3F + 7166 6BD8 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6BDD 37 3B 3F + 7167 ; + 7168 ; this gives the bit offset for each one + 7169 ; + 7170 6BE0 XBITTBL: + 7171 6BE0 00 DB 0 + 7172 6BE1 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BE6 03 00 + Tue Jun 13 1989 11:42 Page 108 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 7173 6BE8 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BED 03 00 + 7174 6BEF 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BF4 03 00 + 7175 6BF6 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BFB 03 00 + 7176 6BFD 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C02 03 00 + 7177 6C04 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C09 03 00 + 7178 6C0B 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C10 03 00 + 7179 6C12 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C17 03 00 + 7180 6C19 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C1E 03 00 + 7181 6C20 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C25 03 00 + 7182 6C27 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C2C 03 00 + 7183 6C2E 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C33 03 00 + 7184 6C35 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C3A 03 00 + 7185 6C3C 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C41 03 00 + 7186 6C43 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C48 03 00 + 7187 6C4A 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C4F 03 00 + 7188 6C51 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C56 03 00 + 7189 6C58 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C5D 03 00 + 7190 6C5F 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C64 03 00 + 7191 6C66 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C6B 03 00 + 7192 RADIX D + 7193 6C6D 00 01 06 07 0C ZIPCOLOR: db 0,1,6,7,$C,$B,$E,$F + 6C72 0B 0E 0F + 7194 6C75 02 03 FF FF FF APLCOLOR: db 2,3,$FF,$FF,$FF,$FF,4,5,$FF,$FF,$FF,7,$FF,$FF,8,9 + 6C7A FF 04 05 FF FF + 6C7F FF 07 FF FF 08 + 6C84 09 + 7195 6C85 OLDZV: + 7196 ; + 7197 ; Variables that used to be in the zero page but got moved out + 7198 ; + 7199 6C85 PSVFLG EQU OLDZV ; (BYTE) PRESERVE FLAG FOR LEX 0=DON'T 1=DO + 7200 6C86 VOCFLG EQU PSVFLG+1 ; (BYTE) WHICH VOC TBL, 0=NORMAL 1= ARG3 + 7201 6C87 DBLOCK EQU VOCFLG+1 ; (WORD) Z-BLOCK TO READ + 7202 6C89 QUOT EQU DBLOCK+2 ; (WORD) QUOTIENT FOR DIVISION + 7203 6C8B REMAIN EQU QUOT+2 ; (WORD) REMAINDER FOR DIVISION + 7204 6C8D QSIGN EQU REMAIN+2 ; (BYTE) SIGN OF QUOTIENT + 7205 6C8E RSIGN EQU QSIGN+1 ; (BYTE) SIGN OF REMAINDER + 7206 6C8F DIGITS EQU RSIGN+1 ; (BYTE) DIGIT COUNT FOR "PRINTN" + 7207 6C90 OLDLEN EQU DIGITS+1 ; (BYTE) OLD LINE LENGTH + 7208 6C91 OLDEND EQU OLDLEN+1 ; (BYTE) OLD LAST CHAR IN [LBUFF] + 7209 6C92 SPSTAT EQU OLDEND+1 ; (BYTE) SPLIT SCREEN STATUS FLAG + 7210 6C93 LFROM EQU SPSTAT+1 ; (WORD) "FROM" LINE ADDRESS + 7211 6C95 LTO EQU LFROM+2 ; (WORD) "TO" LINE ADDRESS + 7212 6C97 PRLEN EQU LTO+2 ; (BYTE) SCRIPT LINE LENGTH + 7213 6C98 GPOSIT EQU PRLEN+1 ; (BYTE) DEFAULT SAVE POSITION + 7214 6C99 GDRIVE EQU GPOSIT+1 ; (BYTE) DEFAULT SAVE DRIVE + 7215 6C9A TPOSIT EQU GDRIVE+1 ; (BYTE) TEMP SAVE POSITION + 7216 6C9B TDRIVE EQU TPOSIT+1 ; (BYTE) TEMP SAVE DRIVE + 7217 6C9C TSLOT EQU TDRIVE+1 ; (BYTE) TEMP SAVE SLOT + 7218 6C9D DRIVE EQU TSLOT+1 ; (BYTE) CURRENT DRIVE + 7219 6C9E SIDEFLG EQU DRIVE+1 ; (BYTE) which disk side are we on + 7220 6C9F SRHOLD EQU SIDEFLG+1 ; (WORD) <>0 if doing sequential random + 7221 6CA1 SCRIPTF EQU SRHOLD+2 ; (BYTE) DIROUT FLAG FOR PRINTER OUTPUT + 7222 6CA2 SCRIPTFLG EQU SCRIPTF+1 ; (BYTE) Does window allow scripting? + 7223 6CA3 OLDZSP EQU SCRIPTFLG+1 ; (WORD) + 7224 6CA5 CURSFLG EQU OLDZSP+2 ; (BYTE) 1==New cursor X for DLINE + Tue Jun 13 1989 11:42 Page 109 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 7225 6CA6 DBLK EQU CURSFLG+1 ; (WORD) + 7226 6CA8 RDTBL1 EQU DBLK+2 ; (WORD) READ TABLE 1 (Game Relative) + 7227 6CAA RDTBL2 EQU RDTBL1+2 ; (WORD) READ TABLE 2 + 7228 6CAC NENTS EQU RDTBL2+2 ; (WORD) # ENTRIES IN VOCAB TABLE + 7229 6CAE DIRITM EQU NENTS+2 ; (WORD) OFFSET IN OUTPUT TBL (DIRTBL) + 7230 6CB0 DIRCNT EQU DIRITM+2 ; (WORD) COUNT OF CHARS IN TBL (DIRTBL) + 7231 6CB2 SVTCHAR EQU DIRCNT+2 ; (WORD) Old TCHARS table address + 7232 6CB4 VOCMPC EQU SVTCHAR+2 ; (3 BYTES) Save for vocabulary MPC + 7233 6CB7 VCESVE EQU VOCMPC+3 ; (3 BYTES) Save for VOCEND + 7234 6CBA VWLSVE EQU VCESVE+3 ; (3 BYTES) Save for VOCLEN + 7235 6CBD DIDVTBL EQU VWLSVE+3 ; (BYTE) <>0 if we have done default table + 7236 6CBE IN EQU DIDVTBL+1 ; (9 BYTES) INPUT BUFFER + 7237 6CC7 OUT EQU IN+9 ; (9 BYTES) OUTPUT BUFFER + 7238 6CD0 CURSOR_OFF EQU OUT+9 ; (BYTE) ==1 if char cursor not to be on + 7239 6CD1 CRLF_CHECK EQU CURSOR_OFF+1 ; (BYTE) ==1 to do CRLF function check + 7240 6CD2 PTR_COUNT EQU CRLF_CHECK+1 ; (BYTE) ==0 if checking pointer movement + 7241 6CD3 INFODOS_END EQU PTR_COUNT+1 ; (WORD) last segment of infodos special + 7242 0050 OLDZVLEN EQU INFODOS_END-PSVFLG+2 ; this is how much to reserve + 7243 + 7244 6C85 BLKB OLDZVLEN,0 ; and zero it out + 7245 + 7246 ; ------------------ + 7247 ; ERROR MESSAGE STRINGS + 7248 ; ------------------ + 7249 6CD5 0E E27: db E27L + 7250 6CD6 44 69 73 6B 20 db "Disk I/O Error" + 6CDB 49 2F 4F 20 45 + 6CE0 72 72 6F 72 + 7251 000E E27L EQU $-E27-1 + 7252 6CE4 14 E2B: db E2BL + 7253 6CE5 44 69 73 6B 20 db "Disk write protected" + 6CEA 77 72 69 74 65 + 6CEF 20 70 72 6F 74 + 6CF4 65 63 74 65 64 + 7254 0014 E2BL EQU $-E2B-1 + 7255 6CF9 0C E40: db E40L + 7256 6CFA 42 61 64 20 46 db "Bad Filename" + 6CFF 69 6C 65 6E 61 + 6D04 6D 65 + 7257 000C E40L EQU $-E40-1 + 7258 6D06 0E E44: db E44L + 7259 6D07 50 61 74 68 20 db "Path not found" + 6D0C 6E 6F 74 20 66 + 6D11 6F 75 6E 64 + 7260 000E E44L: EQU $-E44-1 + 7261 6D15 10 E45: db E45L + 7262 6D16 56 6F 6C 75 6D db "Volume not found" + 6D1B 65 20 6E 6F 74 + 6D20 20 66 6F 75 6E + 6D25 64 + 7263 0010 E45L EQU $-E45-1 + 7264 6D26 0E E46: db E46L + 7265 6D27 46 69 6C 65 20 db "File Not Found" + 6D2C 4E 6F 74 20 46 + 6D31 6F 75 6E 64 + 7266 000E E46L EQU $-E46-1 + 7267 6D35 09 E48: db E48L + 7268 6D36 44 69 73 6B 20 db "Disk Full" + 6D3B 46 75 6C 6C + 7269 0009 E48L EQU $-E48-1 + 7270 6D3F 21 E49: db E49L + 7271 6D40 4C 61 6E 65 44 db "LaneDOS limit: 12 files/directory" + 6D45 4F 53 20 6C 69 + 6D4A 6D 69 74 3A 20 + 6D4F 31 32 20 66 69 + 6D54 6C 65 73 2F 64 + 6D59 69 72 65 63 74 + 6D5E 6F 72 79 + 7272 0021 E49L EQU $-E49-1 + 7273 6D61 26 E4E: db E4EL + 7274 6D62 4C 61 6E 65 44 db "LaneDOS limit: No writes to TREE files" + 6D67 4F 53 20 6C 69 + 6D6C 6D 69 74 3A 20 + 6D71 4E 6F 20 77 72 + 6D76 69 74 65 73 20 + Tue Jun 13 1989 11:42 Page 110 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6D7B 74 6F 20 54 52 + 6D80 45 45 20 66 69 + 6D85 6C 65 73 + 7275 0026 E4EL EQU $-E4E-1 + 7276 6D88 0E E4C: db E4CL + 7277 6D89 55 6E 65 78 70 db "Unexpected EOF" + 6D8E 65 63 74 65 64 + 6D93 20 45 4F 46 + 7278 000E E4CL EQU $-E4C-1 + 7279 + 7280 6D97 27 ELIST: db $27 + 7281 6D98 D56C dw E27 + 7282 6D9A 2B db $2B + 7283 6D9B E46C dw E2B + 7284 6D9D 40 db $40 + 7285 6D9E F96C dw E40 + 7286 6DA0 44 db $44 + 7287 6DA1 066D dw E44 + 7288 6DA3 45 db $45 + 7289 6DA4 156D dw E45 + 7290 6DA6 46 db $46 + 7291 6DA7 266D dw E46 + 7292 6DA9 48 db $48 + 7293 6DAA 356D dw E48 + 7294 6DAC 49 db $49 + 7295 6DAD 3F6D dw E49 + 7296 6DAF 4C db $4C + 7297 6DB0 886D dw E4C + 7298 6DB2 4E db $4E + 7299 6DB3 616D dw E4E + 7300 001B ELISTL EQU $-ELIST-3 ; mark last error code + 7301 + 7302 6DB5 END + 7303 + 7304 6DB5 INCLUDE WINDOWS.ASM + 7305 + 7306 6DB5 STTL "--- WINDOW OPERATIONS ---" + 7307 PAGE + Tue Jun 13 1989 11:42 Page 111 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7308 ; + 7309 ; these are the data structures for all 8 WINDOW. They are identical and + 7310 ; are just seperated cuz I use the addresses in the table that follows. + 7311 ; All numbers are inclusive, absolute, and zero-based. + 7312 ; + 7313 0000 WINDSTRUCT EQU 0 + 7314 0000 WINTOP EQU WINDSTRUCT ; first line of the window + 7315 0001 WINLEFT EQU WINTOP+1 ; left edge of the window + 7316 0002 WINHGHT EQU WINLEFT+1 ; height of the window + 7317 0003 WINWID EQU WINHGHT+1 ; width of the window, in pixels + 7318 0004 WINY EQU WINWID+1 ; y pos of cursor (pos, not relative) + 7319 0005 WINX EQU WINY+1 ; x pos of cursor (remember, ABSOLUTE) + 7320 0006 WINLM EQU WINX+1 ; left margin + 7321 0007 WINRM EQU WINLM+1 ; right margin + 7322 0008 WINCRF EQU WINRM+1 ; (WORD) function + 7323 000A WINCRC EQU WINCRF+2 ; (WORD) counter + 7324 000C WINHIGHL EQU WINCRC+2 ; highlight mode + 7325 000D WINFORE EQU WINHIGHL+1 ; foreground color (0=black-7=white) + 7326 000E WINBGND EQU WINFORE+1 ; background color (0=black-7=white) + 7327 000F WINFONT EQU WINBGND+1 ; window font (0=normal/4=monospaced) + 7328 0010 WINFSIZE EQU WINFONT+1 ; (WORD) font Height/Width + 7329 0012 WINATR EQU WINFSIZE+2 ; Window Attributes + 7330 0013 WINLCNT EQU WINATR+1 ; current number of lines + 7331 ; + 7332 ; these are my interesting things + 7333 ; + 7334 0014 WINXSZ EQU WINLCNT+1 ; width of window, in pixels, using margin + 7335 0015 WINLLEN EQU WINXSZ+1 ; length of current line + 7336 0017 WINLINES EQU WINLLEN+2 ; max # of lines for window + 7337 + 7338 6DB5 WINDOW0: + 7339 6DB5 00 DB 0 ; WINTOP - first line of the window + 7340 6DB6 00 DB 0 ; WINLEFT - left edge of the window + 7341 6DB7 C0 DB MAXHEIGHT ; WINHGHT - height of window + 7342 6DB8 8C DB MAXWIDTH ; WINWID - width of window + 7343 6DB9 00 DB 0 ; WINY - y pos of cursor (pos, not relative) + 7344 6DBA 00 DB 0 ; WINX - x pos of cursor (remember, ABSOLUTE) + 7345 6DBB 00 DB 0 ; WINLM - left margin + 7346 6DBC 00 DB 0 ; WINRM - right margin + 7347 6DBD 0000 DW 0 ; WINCRF - function + 7348 6DBF 0000 DW 0 ; WINCRC - counter + 7349 6DC1 00 DB 0 ; WINHIGHL - Highlights + 7350 6DC2 0F DB $f ; WINFORE - foreground color default of white + 7351 6DC3 00 DB 0 ; WINBGND - background color + 7352 6DC4 00 DB 0 ; WINFONT - window font (0=normal/1=alternate) + 7353 6DC5 02 09 DB 2,FONT_H ; WINFSIZE - Width/Height + 7354 6DC7 0F DB $0f ; WINATR - all attributes on for window 0 + 7355 6DC8 00 DB 0 ; WINLCNT - current number of lines + 7356 6DC9 8C DB MAXWIDTH ; WINXSZ - width of window, in pixels, using margin + 7357 6DCA 00 00 DB 0,0 ; WINLLEN - length of current line + 7358 6DCC 14 DB (MAXHEIGHT/FONT_H)-1 ; WINLINES - max # of lines for window + 7359 ; + 7360 ; same start as window 0, but with 0 length + 7361 ; + 7362 6DCD WINDOW1: + 7363 6DCD 00 00 00 8C 00 DB 0,0,0,MAXWIDTH,0,0,0,0,0,0,0,0,0 + 6DD2 00 00 00 00 00 + 6DD7 00 00 00 + 7364 6DDA 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,MAXWIDTH,0,0,0 + 6DDF 08 00 8C 00 00 + 6DE4 00 + 7365 ; + 7366 ; the rest have no width/height/attributes (except buffering) + 7367 ; + 7368 6DE5 WINDOW2: + 7369 6DE5 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6DEA 00 00 00 00 00 + 6DEF 00 00 00 + 7370 6DF2 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6DF7 08 00 00 00 00 + 6DFC 00 + 7371 6DFD WINDOW3: + 7372 6DFD 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6E02 00 00 00 00 00 + 6E07 00 00 00 + Tue Jun 13 1989 11:42 Page 112 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7373 6E0A 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6E0F 08 00 00 00 00 + 6E14 00 + 7374 6E15 WINDOW4: + 7375 6E15 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6E1A 00 00 00 00 00 + 6E1F 00 00 00 + 7376 6E22 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6E27 08 00 00 00 00 + 6E2C 00 + 7377 6E2D WINDOW5: + 7378 6E2D 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6E32 00 00 00 00 00 + 6E37 00 00 00 + 7379 6E3A 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6E3F 08 00 00 00 00 + 6E44 00 + 7380 6E45 WINDOW6: + 7381 6E45 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6E4A 00 00 00 00 00 + 6E4F 00 00 00 + 7382 6E52 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6E57 08 00 00 00 00 + 6E5C 00 + 7383 6E5D WINDOW7: + 7384 6E5D 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6E62 00 00 00 00 00 + 6E67 00 00 00 + 7385 6E6A 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6E6F 08 00 00 00 00 + 6E74 00 + 7386 + 7387 6E75 WINTABLE: + 7388 6E75 B56D CD6D E56D DW WINDOW0,WINDOW1,WINDOW2,WINDOW3 + 6E7B FD6D + 7389 6E7D 156E 2D6E 456E DW WINDOW4,WINDOW5,WINDOW6,WINDOW7 + 6E83 5D6E + 7390 PAGE + Tue Jun 13 1989 11:42 Page 113 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7391 + 7392 ; ------ + 7393 ; SCREEN + 7394 ; ------ + 7395 ; Move to the screen specified, by updating CURWIN and the cursor + 7396 ; X,Y pos (SCRX,SCRY). Also put address of that window's structure + 7397 ; in WINDOW. Save a bunch of the old stuff in old window's structure then + 7398 ; update the same bunch with the new window's stuff. + 7399 ; + 7400 ; ARG1 - new screen id: 0-7 + 7401 ; + 7402 6E85 ZSCRN: + 7403 6E85 20 BE 55 jsr CLRBUF ; EMPTY OUTPUT BUFFER BEFORE MOVING + 7404 ; + 7405 ; now, save a few things from the common variables + 7406 ; + 7407 6E88 A0 15 ldy #WINLLEN ; current line length + 7408 6E8A A5 A7 lda LENGTH+LO ; get current line length + 7409 6E8C 91 05 sta (WINDOW),Y ; save for later referencing + 7410 6E8E C8 iny ; point to msb + 7411 6E8F A5 A8 lda LENGTH+HI ; get MSB + 7412 6E91 91 05 sta (WINDOW),Y ; saved + 7413 6E93 20 8F 4D jsr SAVE_CURSOR ; save the x,y pos of cursor + 7414 6E96 A5 BB lda INVFLG ; get inverse flag + 7415 6E98 F0 04 beq ZSCA1 ; not set + 7416 6E9A A9 01 lda #1 ; set 1 bit + 7417 6E9C D0 06 bne ZSCA2 ; set in window + 7418 6E9E ZSCA1: + 7419 6E9E A5 BA lda UNDFLG ; how about underlining + 7420 6EA0 F0 02 beq ZSCA2 ; nope + 7421 6EA2 A9 04 lda #4 ; 4 == underlining + 7422 6EA4 ZSCA2: + 7423 6EA4 A0 0C ldy #WINHIGHL ; set new highlight + 7424 6EA6 91 05 sta (WINDOW),Y ; save current attributes + 7425 ; + 7426 ; now it is time to update for new screen + 7427 ; + 7428 6EA8 A5 63 lda ARG1+LO ; get which window + 7429 6EAA 85 A6 sta CURWIN ; save window number + 7430 6EAC 0A asl A ; shift to make word indes + 7431 6EAD AA tax ; swap to indexing reg + 7432 6EAE BD 75 6E lda WINTABLE,X ; get the address of the new WINDOW + 7433 6EB1 85 05 sta WINDOW+LO ; lo part comes first + 7434 6EB3 BD 76 6E lda WINTABLE+1,X ; so go get hi part + 7435 6EB6 85 06 sta WINDOW+HI ; save the hi part of the address + 7436 + 7437 6EB8 20 A1 4D jsr GET_CURSOR ; restore the cursor pos + 7438 + 7439 6EBB A0 14 ldy #WINXSZ ; get line length + 7440 6EBD B1 05 lda (WINDOW),Y ; update zero page variable + 7441 6EBF 85 A2 sta XSIZE+LO ; this is for quicky comparing + 7442 6EC1 A9 00 lda #0 ; clear MSB + 7443 6EC3 85 A3 sta XSIZE+HI + 7444 6EC5 06 A2 asl XSIZE+LO ; *2 + 7445 6EC7 26 A3 rol XSIZE+HI + 7446 6EC9 06 A2 asl XSIZE+LO ; *4 + 7447 6ECB 26 A3 rol XSIZE+HI + 7448 6ECD A0 15 ldy #WINLLEN ; get current line length + 7449 6ECF B1 05 lda (WINDOW),Y ; from before + 7450 6ED1 85 A7 sta LENGTH+LO ; save for later checking + 7451 6ED3 C8 iny + 7452 6ED4 B1 05 lda (WINDOW),Y + 7453 6ED6 85 A8 sta LENGTH+HI + 7454 6ED8 A0 13 ldy #WINLCNT ; how many lines already out there + 7455 6EDA B1 05 lda (WINDOW),Y ; has been already saved + 7456 6EDC 85 AB sta LINCNT ; and save 'ere too + 7457 6EDE A0 17 ldy #WINLINES ; how many lines in this + 7458 6EE0 B1 05 lda (WINDOW),Y ; window, anyway? + 7459 6EE2 85 03 sta MAXLINES ; show for everyone to see + 7460 6EE4 A0 01 ldy #WINLEFT ; show left margin + 7461 6EE6 B1 05 lda (WINDOW),Y ; get left edge + 7462 6EE8 A0 06 ldy #WINLM ; left margin + 7463 6EEA 18 clc ; adding + 7464 6EEB 71 05 adc (WINDOW),Y ; to find new left margin + 7465 6EED 85 04 sta LEFTMRG ; set up left margin for ease of use + Tue Jun 13 1989 11:42 Page 114 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7466 6EEF A0 00 ldy #WINTOP ; get top of window + 7467 6EF1 B1 05 lda (WINDOW),Y ; got it + 7468 6EF3 18 clc ; adding + 7469 6EF4 A0 02 ldy #WINHGHT ; add height + 7470 6EF6 71 05 adc (WINDOW),Y ; did it + 7471 6EF8 85 02 sta SCRBTM ; this is first line outside window + 7472 6EFA A0 0C ldy #WINHIGHL ; get highlighting modes + 7473 6EFC B1 05 lda (WINDOW),Y ; first for inverse video + 7474 6EFE 29 01 and #1 ; check for inverse video + 7475 6F00 F0 02 beq SCRINV ; nope + 7476 6F02 A9 80 lda #$80 ; means inverse video + 7477 6F04 SCRINV: + 7478 6F04 85 BB sta INVFLG ; there it be + 7479 6F06 B1 05 lda (WINDOW),Y ; point to underline flag + 7480 6F08 29 04 and #4 ; check for underlining + 7481 6F0A F0 02 beq SCRUND ; nope + 7482 6F0C A9 80 lda #$80 ; means underlining + 7483 6F0E SCRUND: + 7484 6F0E 85 BA sta UNDFLG ; save for everyone + 7485 + 7486 6F10 A0 12 ldy #WINATR ; get the current attributes + 7487 6F12 B1 05 lda (WINDOW),Y ; gottem + 7488 6F14 20 96 70 jsr SET_ATTRIBUTES ; set the flags, thank you + 7489 6F17 A0 0F ldy #WINFONT ; get the font + 7490 6F19 B1 05 lda (WINDOW),Y ; thank you + 7491 6F1B F0 02 beq SCRFNT0 ; is it font zero? + 7492 6F1D A9 0C lda #MONOFONT_W ; must be mono font, set width + 7493 6F1F SCRFNT0: + 7494 6F1F 85 C1 sta FONTFLG ; mark normal font + 7495 6F21 ZSCREX: + 7496 6F21 60 rts + 7497 ;-------------- + 7498 ; ZWINPOS + 7499 ;-------------- + 7500 ; + 7501 ; change the window ARG1's top left corner to the new position + 7502 ; + 7503 ; ARG1 - window id from 0-7 + 7504 ; ARG2 - new top y pos + 7505 ; ARG3 - new top x pos + 7506 ; + 7507 6F22 ZWINPOS: + 7508 6F22 C6 65 dec ARG2+LO ; make pos be zero based + 7509 6F24 C6 67 dec ARG3+LO ; now they are! + 7510 ; + 7511 ; if moving current window, save current cursor pos + 7512 ; + 7513 6F26 ZWPOS0: + 7514 6F26 20 8F 4D jsr SAVE_CURSOR ; saving + 7515 ; + 7516 ; let's set up [J] to point to window we are talking about + 7517 ; + 7518 6F29 ZWPOS1: + 7519 6F29 A5 63 lda ARG1+LO ; get window ID + 7520 6F2B 20 87 57 jsr SETWJ ; get J to point to it + 7521 + 7522 6F2E A5 65 lda ARG2+LO ; first, check the top + 7523 6F30 C9 C0 cmp #MAXHEIGHT ; < max height? + 7524 6F32 90 04 bcc CKWA1 ; fine + 7525 6F34 A9 00 lda #0 ; make it zero then + 7526 6F36 85 65 sta ARG2+LO ; it is now + 7527 6F38 CKWA1: + 7528 6F38 A5 67 lda ARG3+LO ; now check left edge + 7529 6F3A C9 8C cmp #MAXWIDTH ; howzit compare + 7530 6F3C 90 04 bcc CKWA2 ; just fine + 7531 6F3E A9 00 lda #0 ; this too + 7532 6F40 85 67 sta ARG3+LO ; it is now + 7533 6F42 CKWA2: + 7534 ; + 7535 ; make the cursor pos be relative, so we can change back to + 7536 ; absolute using new window pos + 7537 ; + 7538 6F42 A0 04 ldy #WINY ; let's do y pos first + 7539 6F44 B1 7A lda (J),Y ; get the old y pos + 7540 6F46 A0 00 ldy #WINTOP ; and subtract the top to make + Tue Jun 13 1989 11:42 Page 115 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7541 6F48 38 sec ; (getting ready) + 7542 6F49 F1 7A sbc (J),Y ; the pos relative + 7543 6F4B 18 clc ; now add in new top + 7544 6F4C 65 65 adc ARG2+LO ; this will be new top + 7545 6F4E A0 04 ldy #WINY ; get y offset again + 7546 6F50 91 7A sta (J),Y ; and save new absolute y pos + 7547 6F52 A0 05 ldy #WINX ; now we be talking about x pos + 7548 6F54 B1 7A lda (J),Y ; get old x pos + 7549 6F56 38 sec ; getting ready for sub + 7550 6F57 A0 01 ldy #WINLEFT ; get rid of left ness + 7551 6F59 F1 7A sbc (J),Y ; now it's relative + 7552 6F5B 18 clc ; get ready to add in new left ness + 7553 6F5C 65 67 adc ARG3+LO ; done + 7554 6F5E A0 05 ldy #WINX ; get x offset again + 7555 6F60 91 7A sta (J),Y ; save in structure + 7556 ; + 7557 ; now we can change the top and left of the window + 7558 ; + 7559 6F62 A5 65 lda ARG2+LO ; this is top of window + 7560 6F64 A0 00 ldy #WINTOP ; TOP offset + 7561 6F66 91 7A sta (J),Y ; save the new top + 7562 6F68 A5 67 lda ARG3+LO ; here is the left edge + 7563 6F6A A0 01 ldy #WINLEFT ; offset into struct + 7564 6F6C 91 7A sta (J),Y ; saved ! + 7565 ; + 7566 ; we might have moved current window so update screen cursor and left margin + 7567 ; + 7568 6F6E 20 A1 4D jsr GET_CURSOR ; restore cursor + 7569 6F71 A0 01 ldy #WINLEFT ; get left edge + 7570 6F73 B1 05 lda (WINDOW),Y ; okay + 7571 6F75 A0 06 ldy #WINLM ; add in left margin + 7572 6F77 18 clc ; adding + 7573 6F78 71 05 adc (WINDOW),Y ; to find new left edge + 7574 6F7A 85 04 sta LEFTMRG ; store for ease of use + 7575 6F7C A0 14 ldy #WINXSZ ; get xsize + 7576 6F7E B1 7A lda (J),Y ; okay + 7577 6F80 85 A2 sta XSIZE+LO ; this is for quicky comparing + 7578 6F82 A9 00 lda #0 ; clear MSB + 7579 6F84 85 A3 sta XSIZE+HI + 7580 6F86 06 A2 asl XSIZE+LO ; *2 + 7581 6F88 26 A3 rol XSIZE+HI + 7582 6F8A 06 A2 asl XSIZE+LO ; *4 + 7583 6F8C 26 A3 rol XSIZE+HI + 7584 6F8E ZWPOSX: + 7585 6F8E 60 rts + 7586 ;------------ + 7587 ; ZWINSIZE + 7588 ;------------ + 7589 ; + 7590 ; Change the size of window ARG1. If cursor is outside of window, + 7591 ; move to it. + 7592 ; + 7593 ; ARG1 - window ID + 7594 ; ARG2 - height + 7595 ; ARG3 - width + 7596 ; + 7597 ; Uses [J]. + 7598 ; + 7599 6F8F ZWINSIZE: + 7600 ; + 7601 ; first put SCRCX,CY into window structure, just in case + 7602 ; + 7603 6F8F 20 8F 4D jsr SAVE_CURSOR ; saved + 7604 ; + 7605 ; now do everything + 7606 ; + 7607 6F92 A5 63 lda ARG1+LO ; get the window ID + 7608 6F94 20 87 57 jsr SETWJ ; and get window pointer + 7609 + 7610 6F97 A5 65 lda ARG2+LO ; first, check the top + 7611 6F99 C9 C0 cmp #MAXHEIGHT ; < max height? + 7612 6F9B 90 04 bcc CKWA11 ; fine + 7613 6F9D A9 C0 lda #MAXHEIGHT ; make better + 7614 6F9F 85 65 sta ARG2+LO ; it is now + 7615 6FA1 CKWA11: + Tue Jun 13 1989 11:42 Page 116 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7616 6FA1 A5 67 lda ARG3+LO ; now check left edge + 7617 6FA3 C9 8C cmp #MAXWIDTH ; howzit compare + 7618 6FA5 90 04 bcc CKWA21 ; just fine + 7619 6FA7 A9 8C lda #MAXWIDTH ; make it the max + 7620 6FA9 85 67 sta ARG3+LO ; it is now + 7621 6FAB CKWA21: + 7622 6FAB A5 65 lda ARG2+LO ; get new height + 7623 6FAD A0 02 ldy #WINHGHT ; offset + 7624 6FAF 91 7A sta (J),Y ; save new height + 7625 6FB1 A5 67 lda ARG3+LO ; get width + 7626 6FB3 A0 03 ldy #WINWID ; store width + 7627 6FB5 91 7A sta (J),Y ; okay + 7628 ; + 7629 ; now we need to figger out new XSIZE, MAXLINES + 7630 ; + 7631 6FB7 A0 03 ldy #WINWID ; store width + 7632 6FB9 B1 7A lda (J),Y ; get width + 7633 6FBB 38 sec ; have width, subtract margins + 7634 6FBC A0 07 ldy #WINRM ; first right margin + 7635 6FBE F1 7A sbc (J),Y ; subtracted right margin + 7636 6FC0 A0 06 ldy #WINLM ; and now for the left margin + 7637 6FC2 F1 7A sbc (J),Y ; now we have new XSIZE + 7638 6FC4 A0 14 ldy #WINXSZ ; get offset + 7639 6FC6 91 7A sta (J),Y ; save for later ref + 7640 6FC8 A5 65 lda ARG2+LO ; get new height + 7641 6FCA A2 FF ldx #$FF ; this is the counter + 7642 6FCC 38 sec ; get ready for subs + 7643 6FCD ZWSZ1: + 7644 6FCD E8 inx ; count this line + 7645 6FCE E9 09 sbc #FONT_H ; subtract off font height + 7646 6FD0 B0 FB bcs ZWSZ1 ; still some lines + 7647 6FD2 CA dex ; to keep the input line on screen + 7648 6FD3 8A txa ; get line count for storage + 7649 6FD4 A0 17 ldy #WINLINES ; this is how many lines are allowed + 7650 6FD6 91 7A sta (J),Y ; saved + 7651 ; + 7652 ; check to make sure the cursor is still in the window + 7653 ; + 7654 6FD8 A0 06 ldy #WINLM ; get left margin + 7655 6FDA 18 clc ; for adding + 7656 6FDB 71 7A adc (J),Y ; for figgering out right edge + 7657 6FDD A0 01 ldy #WINLEFT ; add in left edge + 7658 6FDF 71 7A adc (J),Y ; get right column by adding in left one + 7659 6FE1 A0 05 ldy #WINX ; check X pos + 7660 6FE3 D1 7A cmp (J),Y ; see if X is still inside? + 7661 6FE5 F0 13 beq ZWSZ2 ; must move to top left + 7662 6FE7 90 11 bcc ZWSZ2 ; ditto if X >= margin + 7663 6FE9 A0 00 ldy #WINTOP ; get top to figger last line + 7664 6FEB B1 7A lda (J),Y ; from the structure + 7665 6FED A0 02 ldy #WINHGHT ; and add in the height + 7666 6FEF 18 clc ; getting ready for add + 7667 6FF0 71 7A adc (J),Y ; to find first line outside of range + 7668 6FF2 A0 04 ldy #WINY ; now check y + 7669 6FF4 D1 7A cmp (J),Y ; now check y then + 7670 6FF6 F0 02 beq ZWSZ2 ; outside, move to top left + 7671 6FF8 B0 15 bcs ZWSZ3 ; inside so quit + 7672 ; + 7673 ; move the cursor to top left if outside of resized window + 7674 ; + 7675 6FFA ZWSZ2: + 7676 6FFA A0 00 ldy #WINTOP ; top line is here + 7677 6FFC B1 7A lda (J),Y ; so get me it + 7678 6FFE A0 04 ldy #WINY ; now we be doing y + 7679 7000 91 7A sta (J),Y ; change Y + 7680 7002 A0 01 ldy #WINLEFT ; move X to left margin + 7681 7004 B1 7A lda (J),Y ; first get left edge + 7682 7006 A0 06 ldy #WINLM ; and add in left margin + 7683 7008 18 clc ; (adding) + 7684 7009 71 7A adc (J),Y ; to get left spot of cursor + 7685 700B A0 05 ldy #WINX ; this is x offset + 7686 700D 91 7A sta (J),Y ; so move X there + 7687 ; + 7688 ; now check to see if we mucked with current window + 7689 ; + 7690 700F ZWSZ3: + Tue Jun 13 1989 11:42 Page 117 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7691 700F A5 64 lda ARG1+HI ; this is the id + 7692 7011 30 04 bmi ZWSZ4 ; must be current window + 7693 7013 C5 A6 cmp CURWIN ; is it current window? + 7694 7015 D0 1B bne ZWSZX ; nope, so done + 7695 7017 ZWSZ4: + 7696 7017 A0 17 ldy #WINLINES ; get how many lines + 7697 7019 B1 7A lda (J),Y ; get number of lines + 7698 701B 85 03 sta MAXLINES ; set global + 7699 701D A0 14 ldy #WINXSZ ; get new XSIZE too + 7700 701F B1 7A lda (J),Y ; get it + 7701 7021 85 A2 sta XSIZE+LO ; this is for quicky comparing + 7702 7023 A9 00 lda #0 ; clear MSB + 7703 7025 85 A3 sta XSIZE+HI + 7704 7027 06 A2 asl XSIZE+LO ; *2 + 7705 7029 26 A3 rol XSIZE+HI + 7706 702B 06 A2 asl XSIZE+LO ; *4 + 7707 702D 26 A3 rol XSIZE+HI + 7708 702F 20 A1 4D jsr GET_CURSOR ; fix the cursor pos + 7709 7032 ZWSZX: + 7710 7032 60 rts + 7711 ; + 7712 ;CHECK_WIN_ARGS + 7713 ; check args to make sure they be okay + 7714 ; + 7715 ; ARG2 = top/height + 7716 ; ARG3 = right/width + 7717 ; + 7718 7033 CHECK_WIN_ARGS: + 7719 7033 60 rts + 7720 + 7721 ; ------ + 7722 ; HLIGHT + 7723 ; ------ + 7724 + 7725 7034 ZLIGHT: + 7726 7034 A5 63 lda ARG1+LO ; get argument + 7727 7036 C9 10 cmp #$10 ; must be <= 8 + 7728 7038 B0 05 bcs ZLIEX ; nope it aint + 7729 703A 09 80 ora #$80 ; turn on hi bit + 7730 703C 20 F5 52 jsr COUT ; send it out then + 7731 703F ZLIEX: + 7732 703F 60 rts ; done + 7733 ; + 7734 ; actually set the highlight flags according to [A] + 7735 ; + 7736 7040 HLIGHT: + 7737 ; + 7738 ; TURN OFF ALL HIGHLIGHTS + 7739 ; + 7740 7040 29 7F and #$7F ; turn off high bit + 7741 7042 D0 05 bne ZL1 ; nope, must be something + 7742 7044 85 BA sta UNDFLG ; and turn of underlining flag + 7743 7046 85 BB sta INVFLG ; and inverse + 7744 7048 60 rts ; all done + 7745 7049 ZL1: + 7746 7049 C9 04 cmp #4 ; underlining + 7747 704B D0 05 bne ZL_REV ; maybe its INVERSE? + 7748 + 7749 704D A9 80 lda #$80 ; turn on UNDFLG + 7750 704F 85 BA sta UNDFLG ; with an FF + 7751 7051 60 rts ; done + 7752 7052 ZL_REV: + 7753 7052 C9 01 cmp #1 ; INVERSE? + 7754 7054 D0 05 bne ZL_MONO ; maybe monospaced then + 7755 7056 A9 80 lda #$80 ; must be inverse video + 7756 7058 85 BB sta INVFLG ; and put it in invflg + 7757 705A 60 rts + 7758 705B ZL_MONO: + 7759 705B 60 rts ; fuck it for now! + 7760 ; + 7761 ; ZWINATTER - change the scrolling/buffering/scripting/wrapping attributes + 7762 ; of the window. + 7763 ; + 7764 ; ARG1 - window id + 7765 ; ARG2 - interesting bits + Tue Jun 13 1989 11:42 Page 118 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7766 ; | buffering | scripting | scrolling | wrapping | + 7767 ; ARG3 - operation - 0 MOVE + 7768 ; 1 SET + 7769 ; 2 CLEAR + 7770 ; 3 COMPLEMENT + 7771 ; + 7772 705C ZWINATTR: + 7773 705C A5 62 lda NARGS ; see how many args + 7774 705E C9 03 cmp #3 ; check for operation args + 7775 7060 F0 04 beq ZWAT1 ; yes, already there + 7776 7062 A9 00 lda #0 ; zero means MOVE + 7777 7064 85 67 sta ARG3+LO ; so show it as default + 7778 7066 ZWAT1: + 7779 7066 A5 63 lda ARG1+LO ; get window ID + 7780 7068 20 87 57 jsr SETWJ ; put window address into [J] + 7781 + 7782 706B A0 12 ldy #WINATR ; get attribute offset + 7783 706D B1 7A lda (J),Y ; get current attribute + 7784 706F 18 clc ; so we can just branch + 7785 + 7786 7070 C6 67 dec ARG3+LO ; decrement to find out what to do + 7787 7072 30 0A bmi ZWMOVE ; do a move + 7788 7074 F0 0C beq ZWSET ; do a set + 7789 7076 C6 67 dec ARG3+LO ; check once more + 7790 7078 F0 0C beq ZWCLEAR ; clear set ones + 7791 ; + 7792 ; this is for the COMPLEMENT operations + 7793 ; + 7794 707A 45 65 eor ARG2+LO ; complement bits + 7795 707C 90 0E bcc ZWAT2 ; done + 7796 707E ZWMOVE: + 7797 ; + 7798 ; move into the flag word + 7799 ; + 7800 707E A5 65 lda ARG2+LO ; get new flags + 7801 7080 90 0A bcc ZWAT2 ; done + 7802 7082 ZWSET: + 7803 ; + 7804 ; set turned on ones + 7805 ; + 7806 7082 05 65 ora ARG2+LO ; set'em up + 7807 7084 90 06 bcc ZWAT2 ; done + 7808 7086 ZWCLEAR: + 7809 ; + 7810 ; clear just the ones that are on + 7811 ; + 7812 7086 A5 65 lda ARG2+LO ; get argument + 7813 7088 49 FF eor #$FF ; turn on all the off ones + 7814 708A 31 7A and (J),Y ; keep all the other ones + 7815 708C ZWAT2: + 7816 708C 91 7A sta (J),Y ; and save it back + 7817 ; + 7818 ; now, if current window, set necessary flags + 7819 ; + 7820 708E A6 63 ldx ARG1+LO ; get window ID + 7821 7090 30 04 bmi SET_ATTRIBUTES ; assume negative is current window + 7822 7092 E4 A6 cpx CURWIN ; is this the current one? + 7823 7094 D0 30 bne ZWATX ; nope, so leave + 7824 7096 SET_ATTRIBUTES: + 7825 ; + 7826 ; current window, so set flags accordingly + 7827 ; + 7828 7096 A2 00 ldx #0 ; to turn off flag + 7829 7098 A0 01 ldy #1 ; to turn on flag + 7830 709A 6A ror A ; get wrapping flag into carry + 7831 709B 90 05 bcc ZWAT3 ; clear it + 7832 709D 8C 04 72 sty WRPFLG ; set wrapping on + 7833 70A0 B0 03 bcs ZWAT33 ; okay + 7834 70A2 ZWAT3: + 7835 70A2 8E 04 72 stx WRPFLG ; clear wrapping flag + 7836 70A5 ZWAT33: + 7837 70A5 6A ror A ; now check thes crolling flag + 7838 70A6 90 05 bcc ZWAT4 ; not set + 7839 70A8 8C 05 72 sty SCRLFLG ; turn on scrolling flag + 7840 70AB B0 03 bcs ZWAT44 ; okay, next please + Tue Jun 13 1989 11:42 Page 119 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7841 70AD ZWAT4: + 7842 70AD 8E 05 72 stx SCRLFLG ; turn off scrolling + 7843 70B0 ZWAT44: + 7844 70B0 6A ror A ; checking the scripting flag + 7845 70B1 90 05 bcc ZWAT5 ; not set + 7846 70B3 8C A2 6C sty SCRIPTFLG ; allow scripting? yes + 7847 70B6 B0 03 bcs ZWAT55 ; next flag + 7848 70B8 ZWAT5: + 7849 70B8 8E A2 6C stx SCRIPTFLG ; allow scripting? no + 7850 70BB ZWAT55: + 7851 70BB 6A ror A ; this checks the buffering flag + 7852 70BC 90 05 bcc ZWAT6 ; not set + 7853 70BE 8C 06 72 sty BUFFLG ; turn on buffering + 7854 70C1 B0 03 bcs ZWATX ; scram + 7855 70C3 ZWAT6: + 7856 70C3 8E 06 72 stx BUFFLG ; turn off buffering + 7857 70C6 ZWATX: + 7858 70C6 60 rts + 7859 ; + 7860 ; ZWINGET - put the window stuff into a table + 7861 ; + 7862 ; ARG1 - Window id + 7863 ; ARG2 - offset + 7864 ; + 7865 70C7 ZWINGET: + 7866 70C7 20 8F 4D jsr SAVE_CURSOR ; save x,y into structure + 7867 + 7868 70CA A5 63 lda ARG1+LO ; get window ID + 7869 70CC 20 87 57 jsr SETWJ ; set up window address + 7870 + 7871 70CF A5 65 lda ARG2+LO ; get where to start getting + 7872 70D1 0A asl A ; make word index + 7873 70D2 AA tax ; make index + 7874 70D3 BD 6F 71 lda ZWGTBL+LO,X ; get lo part of address + 7875 70D6 85 7C sta K+LO ; save for jumping + 7876 70D8 BD 70 71 lda ZWGTBL+HI,X ; get hi part + 7877 70DB 85 7D sta K+HI ; saved + 7878 70DD 20 E7 70 jsr ZWGVEC ; do the vectoring + 7879 70E0 86 77 stx VALUE+HI ; save hi part + 7880 70E2 85 76 sta VALUE+LO ; and the lo part + 7881 70E4 4C D1 43 jmp PUTVAL ; and return it + 7882 70E7 ZWGVEC: + 7883 70E7 6C 7C 00 jmp (K) ; and goto it boys + 7884 70EA ZWG0: + 7885 70EA A2 00 ldx #0 ; zero out high part + 7886 70EC A0 00 ldy #WINTOP ; get window y pos + 7887 70EE B1 7A lda (J),Y ; got it + 7888 70F0 A8 tay ; need to inc it + 7889 70F1 C8 iny ; to make it a one-based number + 7890 70F2 98 tya ; back to a + 7891 70F3 60 rts + 7892 70F4 ZWG1: + 7893 70F4 A2 00 ldx #0 ; zero out high part + 7894 70F6 A0 01 ldy #WINLEFT ; get window x pos + 7895 70F8 B1 7A lda (J),Y ; got it + 7896 70FA A8 tay ; need to inc it + 7897 70FB C8 iny ; to make it a one-based number + 7898 70FC 98 tya ; back to a + 7899 70FD 60 rts + 7900 70FE ZWG2: + 7901 70FE A2 00 ldx #0 ; zero out high part + 7902 7100 A0 02 ldy #WINHGHT ; get window height + 7903 7102 B1 7A lda (J),Y ; got it + 7904 7104 60 rts + 7905 7105 ZWG3: + 7906 7105 A2 00 ldx #0 ; zero out high part + 7907 7107 A0 03 ldy #WINWID ; window width + 7908 7109 B1 7A lda (J),Y ; got it + 7909 710B 60 rts + 7910 710C ZWG4: + 7911 710C 20 6C 57 jsr FETCHCY ; get the current Y pos + 7912 710F A2 00 ldx #0 ; zero out high part + 7913 7111 60 rts + 7914 7112 ZWG5: + 7915 7112 20 79 57 jsr FETCHCX ; fetch the current X pos + Tue Jun 13 1989 11:42 Page 120 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7916 7115 A2 00 ldx #0 ; zero out high part + 7917 7117 60 rts + 7918 7118 ZWG6: + 7919 7118 A2 00 ldx #0 ; zero out high part + 7920 711A A0 06 ldy #WINLM ; left margin + 7921 711C B1 7A lda (J),Y ; got it + 7922 711E 60 rts + 7923 711F ZWG7: + 7924 711F A2 00 ldx #0 ; zero out high part + 7925 7121 A0 07 ldy #WINRM ; right margin + 7926 7123 B1 7A lda (J),Y ; got it + 7927 7125 60 rts + 7928 7126 ZWG8: + 7929 7126 A0 09 ldy #WINCRF+HI ; function + 7930 7128 B1 7A lda (J),Y ; got it, lo part + 7931 712A AA tax ; save hi part + 7932 712B 88 dey ; point to lo part + 7933 712C B1 7A lda (J),Y ; got lo part + 7934 712E 60 rts + 7935 712F ZWG9: + 7936 712F A0 0B ldy #WINCRC+HI ; count + 7937 7131 B1 7A lda (J),Y ; got it, hi part + 7938 7133 AA tax ; save it + 7939 7134 88 dey ; now to lo part + 7940 7135 B1 7A lda (J),Y ; got it + 7941 7137 60 rts + 7942 7138 ZWG10: + 7943 7138 A0 0C ldy #WINHIGHL ; get high light mode + 7944 713A B1 7A lda (J),Y ; got it + 7945 713C A2 00 ldx #0 ; zero out high part + 7946 713E 60 rts + 7947 713F ZWG11: + 7948 713F A0 0E ldy #WINBGND ; and background + 7949 7141 B1 7A lda (J),Y ; got it + 7950 7143 A8 tay ; make index + 7951 7144 B9 75 6C lda APLCOLOR,Y ; get apl->zip color + 7952 7147 AA tax ; save for return + 7953 7148 A0 0D ldy #WINFORE ; get foreground + 7954 714A B1 7A lda (J),Y ; got it + 7955 714C A8 tay ; save it + 7956 714D B9 75 6C lda APLCOLOR,Y ; get apl->zip color + 7957 7150 60 rts + 7958 7151 ZWG12: + 7959 7151 A0 0F ldy #WINFONT ; now for font id + 7960 7153 B1 7A lda (J),Y ; got it + 7961 7155 A2 00 ldx #0 ; zero out high part + 7962 7157 60 rts + 7963 7158 ZWG13: + 7964 7158 A0 11 ldy #WINFSIZE+1 ; font size (width) + 7965 715A B1 7A lda (J),Y ; got it + 7966 715C AA tax ; save it + 7967 715D 88 dey ; font size (height) + 7968 715E B1 7A lda (J),Y ; got it + 7969 7160 60 rts + 7970 7161 ZWG14: + 7971 7161 A2 00 ldx #0 ; zero out high part + 7972 7163 A0 12 ldy #WINATR ; attributes + 7973 7165 B1 7A lda (J),Y ; got it + 7974 7167 60 rts ; got them! + 7975 7168 ZWG15: + 7976 7168 A2 00 ldx #0 ; only 1 byte worth + 7977 716A A0 13 ldy #WINLCNT ; offset + 7978 716C B1 7A lda (J),Y ; get more counter + 7979 716E 60 rts + 7980 ; + 7981 ; jump table for figgering out where to start filling + 7982 ; + 7983 716F ZWGTBL: + 7984 716F EA70 F470 FE70 DW ZWG0,ZWG1,ZWG2,ZWG3,ZWG4,ZWG5,ZWG6,ZWG7 + 7175 0571 0C71 1271 + 717B 1871 1F71 + 7985 717F 2671 2F71 3871 DW ZWG8,ZWG9,ZWG10,ZWG11,ZWG12,ZWG13,ZWG14,ZWG15 + 7185 3F71 5171 5871 + 718B 6171 6871 + 7986 ; + Tue Jun 13 1989 11:42 Page 121 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7987 ; ZSCROLL - scroll the specified window up or down + 7988 ; + 7989 ; ARG1 - window ID + 7990 ; ARG2 - lines to scroll; <0 scrolls down + 7991 ; + 7992 718F ZSCROLL: + 7993 718F 20 8F 4D jsr SAVE_CURSOR ; save where cursor is + 7994 + 7995 7192 A9 00 lda #0 ; don't script scroll + 7996 7194 85 AA sta SCRIPT ; fine, we won't now + 7997 + 7998 7196 A5 63 lda ARG1+LO ; get which window + 7999 7198 20 87 57 jsr SETWJ ; set up pointer + 8000 719B C6 62 dec NARGS ; see what we have for lines + 8001 719D D0 04 bne ZSCR1 ; a passed arg + 8002 719F A9 01 lda #1 ; 1 line is default + 8003 71A1 85 65 sta ARG2+LO ; so say so + 8004 71A3 ZSCR1: + 8005 71A3 A0 00 ldy #WINTOP ; get me window limits + 8006 71A5 B1 7A lda (J),Y ; first top + 8007 71A7 85 0B sta CLSTOP ; save for usage + 8008 71A9 C8 iny ; now left + 8009 71AA B1 7A lda (J),Y ; okay, get for this window + 8010 71AC 85 0A sta CLSLEFT ; save left + 8011 71AE C8 iny ; now it's width + 8012 71AF B1 7A lda (J),Y ; got the window height + 8013 71B1 85 0D sta CLSHEIGHT ; this is it + 8014 71B3 C8 iny ; this is height + 8015 71B4 B1 7A lda (J),Y ; get window's height + 8016 71B6 85 0C sta CLSWIDTH ; save + 8017 71B8 A5 66 lda ARG2+HI ; is it negative? + 8018 71BA 85 1D sta SCLDIR ; show direction of scroll + 8019 71BC 10 08 bpl ZSCRL1 ; nope + 8020 71BE A6 65 ldx ARG2+LO ; get how many lines + 8021 71C0 49 FF eor #$FF ; make pos + 8022 71C2 AA tax ; put in X for inc + 8023 71C3 E8 inx ; and make right + 8024 71C4 D0 02 bne ZSCRLEX ; done + 8025 71C6 ZSCRL1: + 8026 71C6 A6 65 ldx ARG2+LO ; get how many lines + 8027 71C8 ZSCRLEX: + 8028 71C8 86 18 stx SCLLINES ; save for routine + 8029 71CA 20 31 60 jsr DO_SCROLL ; and do the scroll + 8030 71CD ZSCRLEX1: + 8031 71CD A9 01 lda #1 ; allow scripting + 8032 71CF 85 AA sta SCRIPT ; we do + 8033 71D1 4C A1 4D jmp GET_CURSOR ; restore the cursor, thank you + 8034 ; + 8035 ; ZWINPUT - put some information into window structure. Just CRF/CRC + 8036 ; is legit now. + 8037 ; + 8038 ; ARG1 - window ID + 8039 ; ARG2 - Word to be saved + 8040 ; ARG3 - offset of value + 8041 ; + 8042 71D4 ZWINPUT: + 8043 71D4 20 8F 4D jsr SAVE_CURSOR ; save the cursor pos + 8044 71D7 A5 63 lda ARG1+LO ; get window ID + 8045 71D9 20 87 57 jsr SETWJ ; have J point to structure + 8046 + 8047 71DC A5 65 lda ARG2+LO ; get first value in table + 8048 71DE C9 08 cmp #8 ; 8 = function + 8049 71E0 F0 0D beq ZWIPCRF ; so save that + 8050 71E2 C9 09 cmp #9 ; this is counter + 8051 71E4 F0 0D beq ZWIPCRC ; so set counter + 8052 71E6 C9 0F cmp #15 ; LINCNT? + 8053 71E8 F0 01 beq ZIPLCT ; then set it too + 8054 71EA 60 rts ; just die then + 8055 71EB ZIPLCT: + 8056 71EB A0 13 ldy #WINLCNT ; point to line count + 8057 71ED D0 0B bne ZWINPUT2 ; and stash it away + 8058 71EF ZWIPCRF: + 8059 71EF A0 09 ldy #WINCRF+1 ; point to window's CR function + 8060 71F1 D0 02 bne ZWINPUT1 ; and put it + 8061 71F3 ZWIPCRC: + Tue Jun 13 1989 11:42 Page 122 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 8062 71F3 A0 0B ldy #WINCRC+1 ; point to window's CR counter + 8063 71F5 ZWINPUT1: + 8064 71F5 A5 68 lda ARG3+HI ; now get hi part + 8065 71F7 91 7A sta (J),Y ; saved! + 8066 71F9 88 dey ; point to lo part + 8067 71FA ZWINPUT2: + 8068 71FA A5 67 lda ARG3+LO ; start with lo part + 8069 71FC 91 7A sta (J),Y ; save lo part + 8070 71FE ZWIPLCT: + 8071 71FE 4C A1 4D jmp GET_CURSOR ; restore cursor/lincnt + 8072 7201 + 8073 7201 END + 8074 + 8075 7201 INCLUDE DLINE.ASM + 8076 7201 STTL "--- Display line Routine ---" + 8077 PAGE + Tue Jun 13 1989 11:42 Page 123 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8078 ; + 8079 ; some aux mem zero page stuff + 8080 ; + 8081 7201 DLVARS: + 8082 7201 CHR_X EQU DLVARS ; (WORD) X pos for char (0-559) + 8083 7203 ENDBIT EQU CHR_X+2 ; (BYTE) ending bit offset + 8084 7204 WRPFLG EQU ENDBIT+1 ; wrapping flag + 8085 7205 SCRLFLG EQU WRPFLG+1 ; scrolling flag + 8086 7206 BUFFLG EQU SCRLFLG+1 ; buffering flag + 8087 7207 SAVEX EQU BUFFLG+1 ; (BYTE) save original X + 8088 7208 CHR_Y EQU SAVEX+1 ; (BYTE) Working cursor Y pos + 8089 7209 LINECHAR EQU CHR_Y+1 ; (BYTE) working char counter + 8090 720A BITTER EQU LINECHAR+1 ; (BYTE) bit twiddler counter + 8091 720B INCFLG EQU BITTER+1 ; (BYTE) ==1 if NEXT_SCR needed after setpos + 8092 720C SHOW_CURSOR EQU INCFLG+1 ; (BYTE) flag as to whether we are doing cursor + 8093 720D SCRCNT EQU SHOW_CURSOR+1 ; (BYTE) screen buffer offset + 8094 720E SV_UND EQU SCRCNT+1 ; (BYTE) spot to save underline flag + 8095 720F SV_INV EQU SV_UND+1 ; (BYTE) save starting INVFLG + 8096 7210 UNDERF EQU SV_INV+1 ; (BYTE) underline flag used internally + 8097 7211 LINE_HEIGHT EQU UNDERF+1 ; (BYTE) counter for height + 8098 0011 DLVARSL EQU LINE_HEIGHT-CHR_X+1 + 8099 + 8100 7201 BLKB DLVARSL,0 + 8101 + 8102 7212 07 06 05 04 03 BIT_BITS: DB 7,6,5,4,3,2,1,0 ; number significant bits in last byte + 7217 02 01 00 + 8103 + 8104 721A DISP_LINE: + 8105 721A AD 0D 72 lda SCRCNT ; make sure there are characters + 8106 721D D0 01 bne DPL1 ; ayyup + 8107 721F 60 rts ; no chars, don't do anything + 8108 7220 DPL1: + 8109 7220 A9 00 lda #0 ; start at zero + 8110 7222 85 09 sta CC_OFF ; which byte to use + 8111 7224 8D 0B 72 sta INCFLG ; and clear out inc'er flag + 8112 7227 + 8113 7227 A9 08 lda #FONT_H-1 ; do for height of char + 8114 7229 8D 11 72 sta LINE_HEIGHT ; height counter + 8115 + 8116 722C A4 01 ldy SCRCY ; and starting y + 8117 722E 8C 08 72 sty CHR_Y ; saved + 8118 7231 A4 00 ldy SCRCX ; save x to + 8119 7233 8C 07 72 sty SAVEX ; save it + 8120 7236 A5 BB lda INVFLG ; get current state + 8121 7238 8D 0F 72 sta SV_INV ; and save it + 8122 723B A5 BA lda UNDFLG ; get current underline state + 8123 723D 8D 0E 72 sta SV_UND ; and save it too + 8124 + 8125 7240 AD A5 6C lda CURSFLG ; changed x pos? + 8126 7243 F0 12 beq DPL2 ; no new figgering + 8127 7245 A2 00 ldx #0 + 8128 7247 8E 02 72 stx CHR_X+HI ; clear out msb + 8129 + 8130 724A A5 00 lda SCRCX ; get new cursor x pos + 8131 724C 0A asl A ; *2 + 8132 724D 2E 02 72 rol CHR_X+HI + 8133 7250 0A asl A ; *4 + 8134 7251 8D 01 72 sta CHR_X+LO + 8135 7254 2E 02 72 rol CHR_X+HI + 8136 7257 DPL2: + 8137 7257 AD 01 72 lda CHR_X+LO + 8138 725A 85 00 sta SCRCX + 8139 725C 29 03 and #3 ; pick up 2 bits rolling out + 8140 725E 8D 0A 72 sta BITTER ; what to add + 8141 7261 AD 02 72 lda CHR_X+HI + 8142 7264 4A lsr A ; /2 + 8143 7265 66 00 ror SCRCX + 8144 7267 4A lsr A ; /4 + 8145 7268 66 00 ror SCRCX + 8146 726A 20 78 5E jsr SETPOS ; set up pointers + 8147 + 8148 726D AD 0A 72 lda BITTER ; get extra + 8149 7270 18 clc ; add in + 8150 7271 65 11 adc BITOFF ; normal bit offset + 8151 7273 8D 0A 72 sta BITTER ; and make it new one + Tue Jun 13 1989 11:42 Page 124 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8152 7276 C9 07 cmp #7 ; but can't be greater than 6 + 8153 7278 90 08 bcc DO_LINE ; okay, it's not + 8154 727A 8D 0B 72 sta INCFLG ; show needing NEXT_SCR call + 8155 727D E9 07 sbc #7 ; so shrink it + 8156 727F 8D 0A 72 sta BITTER ; save it + 8157 7282 DO_LINE: + 8158 7282 20 78 5E jsr SETPOS ; set up pointers + 8159 7285 AD 0B 72 lda INCFLG ; do we need to go one more? + 8160 7288 F0 03 beq DOL1 ; nope + 8161 728A 20 1D 5E jsr NEXT_SCR ; and point to next screen byte + 8162 728D DOL1: + 8163 728D AE 0A 72 ldx BITTER ; get bit off set + 8164 7290 86 11 stx BITOFF ; and save here + 8165 7292 A9 00 lda #0 ; init a few things + 8166 7294 85 13 sta SCR_DATA ; init screen data byte + 8167 7296 8D 09 72 sta LINECHAR ; which character on the line + 8168 7299 85 0F sta CH_OFFSET ; which byte in line on screen + 8169 729B 85 07 sta LINE_X+LO ; X pos of line + 8170 729D 85 08 sta LINE_X+HI ; part 2 + 8171 729F 8D 10 72 sta UNDERF ; make sure this be zero + 8172 + 8173 72A2 AD 0F 72 lda SV_INV ; get starting INV state + 8174 72A5 85 BB sta INVFLG ; okay! + 8175 72A7 AD 0E 72 lda SV_UND ; get starting UNDERLINE state + 8176 72AA 85 BA sta UNDFLG ; and restart it + 8177 + 8178 72AC C6 0F dec CH_OFFSET ; inclusive count + 8179 72AE A6 11 ldx BITOFF ; make bitoff be a count + 8180 72B0 BD 12 72 lda BIT_BITS,X ; get count + 8181 72B3 AA tax ; x is bit counter + 8182 72B4 CHARL: + 8183 72B4 AC 09 72 ldy LINECHAR ; get the char + 8184 72B7 CC 0D 72 cpy SCRCNT ; done with line? + 8185 72BA D0 03 bne CHARL1 ; nope + 8186 72BC 4C 60 73 jmp COPYL ; okay, move onto screen + 8187 72BF CHARL1: + 8188 72BF EE 09 72 inc LINECHAR ; point to next one + 8189 72C2 B9 80 02 lda SCRBUFF,Y ; got it + 8190 72C5 10 06 bpl CHARL3 ; not a highlight char + 8191 + 8192 72C7 20 40 70 jsr HLIGHT ; so check it out + 8193 72CA 4C B4 72 jmp CHARL ; done + 8194 72CD CHARL3: + 8195 72CD C9 20 cmp #SPACE ; is it a highlight char? + 8196 72CF 90 E3 bcc CHARL ; ignore this one then + 8197 72D1 CHARL2: + 8198 72D1 A8 tay ; use as index + 8199 72D2 B9 55 63 lda CHADR_H,Y ; get high part of address + 8200 72D5 85 1D sta CHPTR+HI ; point to it + 8201 72D7 B9 D4 63 lda CHADR_L,Y ; get lo part + 8202 72DA 85 1C sta CHPTR+LO ; save it + 8203 72DC B9 53 64 lda CHWID,Y ; get how wide the char is + 8204 72DF 85 C9 sta CW ; save it + 8205 72E1 A5 09 lda CC_OFF ; to get data + 8206 72E3 A4 C9 ldy CW ; see how wide the char is + 8207 72E5 C0 0A cpy #10 ; if <= 8, only one byte of info + 8208 72E7 90 01 bcc CHRLCW ; it is, so skip shift + 8209 72E9 0A asl A ; *2 for bigger chars + 8210 72EA CHRLCW: + 8211 72EA A8 tay ; get the index + 8212 72EB B1 1C lda (CHPTR),Y ; get first byte + 8213 72ED 85 C7 sta CHAR_D1 ; part one + 8214 72EF C8 iny ; point to next part + 8215 72F0 B1 1C lda (CHPTR),Y ; get second byte + 8216 72F2 85 C8 sta CHAR_D2 ; and save it + 8217 72F4 A5 C9 lda CW ; get width back + 8218 72F6 C9 0A cmp #10 ; if <= 8 zero byte 2 of char data + 8219 72F8 B0 04 bcs CHRLCW1 ; nope + 8220 72FA A9 00 lda #0 ; clear out byte 2 + 8221 72FC 85 C8 sta CHAR_D2 ; okay + 8222 72FE CHRLCW1: + 8223 72FE A5 C1 lda FONTFLG ; is this monospacing? + 8224 7300 F0 28 beq CHRLFX ; nope + 8225 ; + 8226 ; if monospacing, see if it char is < mono width, and try to split + Tue Jun 13 1989 11:42 Page 125 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8227 ; the difference if so + 8228 ; + 8229 7302 C5 C9 cmp CW ; check against current width + 8230 7304 B0 12 bcs CHRLF0 ; CW < monowidth, so center + 8231 ; + 8232 ; too big, so take a little off front end too + 8233 ; + 8234 7306 A5 C9 lda CW ; get current width + 8235 7308 38 sec ; get ready for subbing + 8236 7309 E9 0C sbc #MONOFONT_W ; take away mono width + 8237 730B 4A lsr A ; /2 to get front half + 8238 730C A8 tay ; use as counter + 8239 730D F0 17 beq CHRLF1 ; nothing to do + 8240 730F CHRLFX1: + 8241 730F 06 C8 asl CHAR_D2 ; step to the left + 8242 7311 26 C7 rol CHAR_D1 ; pick up char + 8243 7313 88 dey ; count one + 8244 7314 D0 F9 bne CHRLFX1 ; do next one + 8245 7316 F0 0E beq CHRLF1 ; all done + 8246 7318 CHRLF0: + 8247 7318 38 sec ; do sub + 8248 7319 E5 C9 sbc CW ; subtract CW + 8249 731B 4A lsr A ; /2 to get front part + 8250 731C A8 tay ; put in counter + 8251 731D F0 07 beq CHRLF1 ; no need to do anything + 8252 731F CHRLFL: + 8253 731F 46 C7 lsr CHAR_D1 ; shift to right + 8254 7321 66 C8 ror CHAR_D2 ; this part too + 8255 7323 88 dey ; count shift + 8256 7324 D0 F9 bne CHRLFL ; not done shifting yet + 8257 7326 CHRLF1: + 8258 7326 A9 0C lda #MONOFONT_W ; get mono font width + 8259 7328 85 C9 sta CW ; chop at mono width + 8260 732A CHRLFX: + 8261 732A AD 11 72 lda LINE_HEIGHT ; if == 0, then pick up underlining + 8262 732D D0 05 bne CHRL3 ; nope + 8263 + 8264 732F A5 BA lda UNDFLG ; get underlining flag + 8265 7331 8D 10 72 sta UNDERF ; and mark for later + 8266 7334 CHRL3: + 8267 7334 A5 13 lda SCR_DATA ; get starting data + 8268 7336 DATAL: + 8269 7336 26 C8 rol CHAR_D2 ; it's a step to the left + 8270 7338 26 C7 rol CHAR_D1 ; nother one + 8271 733A 6A ror A ; and put into screen byte + 8272 733B 45 BB eor INVFLG ; pick up inversing + 8273 733D 0D 10 72 ora UNDERF ; pick up underline flag + 8274 7340 E6 07 inc LINE_X+LO ; next X pos too + 8275 7342 D0 02 bne DATAL0 ; no wrap + 8276 7344 E6 08 inc LINE_X+HI ; wrapped + 8277 7346 DATAL0: + 8278 7346 CA dex ; next bit pos + 8279 7347 D0 0C bne DATAL1 ; nope + 8280 ; + 8281 ; save the byte and point to next byte + 8282 ; + 8283 7349 STCH: + 8284 7349 4A lsr A ; put in lower 7 bits + 8285 734A E6 0F inc CH_OFFSET ; point to next one + 8286 734C A4 0F ldy CH_OFFSET ; get current offset + 8287 734E 99 00 1F sta SCR_LINE,Y ; save in line + 8288 7351 A2 07 ldx #7 ; and start bitoff at 7 + 8289 7353 A9 00 lda #0 ; clear a few locals + 8290 7355 DATAL1: + 8291 7355 C6 C9 dec CW ; well? + 8292 7357 30 1F bmi COPYL1 ; all done, start copying + 8293 7359 D0 DB bne DATAL ; nope + 8294 735B 85 13 sta SCR_DATA ; save current screen byte stuff here + 8295 735D 4C B4 72 jmp CHARL ; do next char + 8296 7360 COPYL: + 8297 7360 A5 07 lda LINE_X+LO ; see if we have any at all + 8298 7362 05 08 ora LINE_X+HI ; well, did we go anywhere? + 8299 7364 F0 21 beq LINE_EXIT ; then quit + 8300 7366 BD 12 72 lda BIT_BITS,X ; get number of significant bits + 8301 7369 8D 03 72 sta ENDBIT ; save this one + Tue Jun 13 1989 11:42 Page 126 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8302 736C E0 07 cpx #7 ; has it been renewed? + 8303 736E F0 08 beq COPYL1 ; no last byte + 8304 7370 A5 13 lda SCR_DATA ; get screen data + 8305 7372 COPYSH: + 8306 7372 4A lsr A ; put down low, please + 8307 7373 CA dex ; one more + 8308 7374 D0 FC bne COPYSH ; and do it again + 8309 7376 F0 D1 beq STCH ; now save this char + 8310 7378 COPYL1: + 8311 7378 20 4C 61 jsr COPY_SCRL ; copy SCR_LINE to screen + 8312 737B LED2: + 8313 737B E6 01 inc SCRCY ; point to next line + 8314 737D CE 11 72 dec LINE_HEIGHT ; count this line + 8315 7380 30 05 bmi LINE_EXIT ; all done! + 8316 + 8317 7382 E6 09 inc CC_OFF ; point to next byte + 8318 7384 4C 82 72 jmp DO_LINE ; and do next line + 8319 7387 LINE_EXIT: + 8320 7387 AE 07 72 ldx SAVEX ; get x back + 8321 738A 86 00 stx SCRCX ; restore it + 8322 + 8323 738C AD 0C 72 lda SHOW_CURSOR ; are we just doing cursor? + 8324 738F D0 14 bne DLXX ; yes, don't change char pos + 8325 + 8326 7391 18 clc ; add in length of this line + 8327 7392 A5 07 lda LINE_X+LO ; get length of line + 8328 7394 6D 01 72 adc CHR_X+LO ; add to start pos + 8329 7397 8D 01 72 sta CHR_X+LO ; save it + 8330 739A A5 08 lda LINE_X+HI ; and the MSB + 8331 739C 6D 02 72 adc CHR_X+HI ; okay + 8332 739F 8D 02 72 sta CHR_X+HI ; save for a rainy day + 8333 73A2 20 B3 73 jsr GET_SCRCX ; set SCRCX back up + 8334 73A5 DLXX: + 8335 73A5 AD 08 72 lda CHR_Y ; restore the + 8336 73A8 85 01 sta SCRCY ; y pos + 8337 73AA A9 00 lda #0 ; clear out counter + 8338 73AC 8D 0D 72 sta SCRCNT ; okay + 8339 73AF 8D A5 6C sta CURSFLG ; reset this flag too + 8340 73B2 60 rts + 8341 + 8342 73B3 GET_SCRCX: + 8343 73B3 AD 01 72 lda CHR_X+LO ; pick this back up + 8344 73B6 85 00 sta SCRCX + 8345 73B8 AD 02 72 lda CHR_X+HI ; /2 + 8346 73BB 4A lsr A ; pick up remainder + 8347 73BC 66 00 ror SCRCX ; /4 + 8348 73BE 4A lsr A ; pick up remainder + 8349 73BF 66 00 ror SCRCX ; got it + 8350 73C1 AD 01 72 lda CHR_X+LO ; any remainder? + 8351 73C4 29 03 and #3 ; well? + 8352 73C6 F0 DD beq DLXX ; nope + 8353 73C8 E6 00 inc SCRCX ; point to next pos + 8354 73CA 60 rts + 8355 + 8356 ; + 8357 ; DO_CURSOR - read in the screen byte, XOR cursor data, store it + 8358 ; + 8359 73CB DO_CURSOR: + 8360 73CB A0 00 ldy #0 ; and zero y + 8361 73CD 84 10 sty DATALOOP ; init this counter + 8362 73CF DOCLOOP: + 8363 + 8364 73CF A0 00 ldy #0 ; must use Y + 8365 73D1 A6 8E ldx FPCBNK ; what bank + 8366 73D3 BD 54 C0 lda PAGE2SW,X ; select it + 8367 73D6 B1 8C lda (FPC),Y ; okay, get byte + 8368 73D8 A6 10 ldx DATALOOP ; get offset + 8369 73DA 5D 00 1F eor SCR_LINE,X ; get data + 8370 73DD 91 8C sta (FPC),Y ; save data + 8371 73DF 20 1D 5E jsr NEXT_SCR ; point to next screen byte + 8372 73E2 E6 10 inc DATALOOP ; point to next char + 8373 73E4 C6 0F dec CH_OFFSET ; count one char + 8374 73E6 10 E7 bpl DOCLOOP ; all done with this line? + 8375 73E8 AD 54 C0 lda PAGE2SW+MAIN ; make sure we are point to MAIN + 8376 73EB 60 rts + Tue Jun 13 1989 11:42 Page 127 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8377 + 8378 73EC END + 8379 + 8380 73EC INCLUDE PIC.ASM + 8381 73EC STTL "--- Picture Op Codes ---" + 8382 PAGE + Tue Jun 13 1989 11:42 Page 128 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8383 PFILE_RD: ; for READING files + 8384 73EC 04 db 4 ; 4 parameters + 8385 73ED 00 db 0 ; refnum + 8386 73EE 0008 dw IOBUFF ; read into io buffer + 8387 73F0 0004 dw $400 ; 1Kb buffer + 8388 73F2 0000 dw 0 ; length actually read + 8389 73F4 PFSEEK: + 8390 73F4 02 db 2 ; 2 pararmeters + 8391 73F5 00 db 0 ; refnum + 8392 73F6 00 00 00 db 0,0,0 ; 3 byte new file pos + 8393 73F9 0000 PICCNT: dw 0 ; counter of the entries + 8394 73FB 00 PF_REFNUM: db 0 ; place to store refnum + 8395 73FC FF PF_FID: db $FF ; File ID of local directory data + 8396 73FD 00 P_IDX: db 0 + 8397 73FE 00 P_BCNT: db 0 + 8398 73FF 00 P_LOFF: db 0 + 8399 7400 00 GBL_FLAG: db 0 ; found global directory? + 8400 7401 00 PIC_FLAG: db 0 ; found pictures? + 8401 7402 00 PF_NAME: db 0 ; name we are looking at + 8402 7403 00 db 0 ; name we found + 8403 + 8404 7404 PICINFO: + 8405 7404 ds PLDSIZE ; get room for picture data + 8406 + 8407 740C 00 TRANSCLR: DB 0 ; transparent color + 8408 740D UNKPIC: + 8409 + 8410 740D 0D 55 6E 6B 6E db EOL,"Unknown Picture #" + 7412 6F 77 6E 20 50 + 7417 69 63 74 75 72 + 741C 65 20 23 + 8411 0012 UNKPICL EQU $-UNKPIC + 8412 741F ZDISPL: + 8413 741F 20 BE 55 jsr CLRBUF ; put out any and all text + 8414 + 8415 7422 20 76 77 jsr GET_PICINF ; get the necessary data + 8416 7425 90 18 bcc ZDSP1 ; everything just fine + 8417 + 8418 7427 DLINE UNKPIC ; unknown picture number error + 8419 7427 A2 0D ldx #UNKPIC ; get other part of string + 8421 [01] IFMA 2 ; check to see if length passed in + 8422 ldy ; then just fetch it + 8423 [01] ELSE + 8424 742B A0 12 ldy #UNKPICL ; get length of string + 8425 [00] ENDIF + 8426 742D 20 5B 4C jsr DLINE ; print the string + 8427 7430 .MACEND + 8428 7430 A5 64 lda ARG1+HI ; get MSB + 8429 7432 20 C3 47 jsr HEXNUM ; print it + 8430 7435 A5 63 lda ARG1+LO ; and LSB + 8431 7437 20 C3 47 jsr HEXNUM + 8432 743A A9 14 lda #$14 ; bad picture number error + 8433 743C 4C F9 51 jmp ZERROR ; and croak + 8434 743F ZDSP1: + 8435 743F 20 8F 4D jsr SAVE_CURSOR ; save the cursor + 8436 + 8437 7442 A9 00 lda #0 ; show no cursor change + 8438 7444 8D A5 6C sta CURSFLG ; start with none, anyway + 8439 + 8440 7447 C6 62 dec NARGS ; x,y pos passed? + 8441 7449 F0 30 beq ZDSP10 ; nope, just use as is + 8442 + 8443 744B A5 65 lda ARG2+LO ; get passed y pos + 8444 744D F0 12 beq ZDSP01 ; don't change + 8445 744F 85 01 sta SCRCY ; change, then + 8446 7451 C6 01 dec SCRCY ; zero base it + 8447 7453 A0 00 ldy #WINTOP ; get top edge of window + 8448 7455 B1 05 lda (WINDOW),Y ; got it + 8449 7457 18 clc ; get ready for add + 8450 7458 65 01 adc SCRCY ; add the offset + 8451 745A 85 01 sta SCRCY ; and make it Y pos + 8452 745C A9 01 lda #1 ; show cursor change anyway + 8453 745E 8D A5 6C sta CURSFLG ; okay, we did + 8454 7461 ZDSP01: + Tue Jun 13 1989 11:42 Page 129 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8455 7461 C6 62 dec NARGS ; x pos passed? + 8456 7463 F0 16 beq ZDSP10 ; nope + 8457 + 8458 7465 A5 67 lda ARG3+LO ; get x pos + 8459 7467 F0 12 beq ZDSP10 ; if == 0, don't change + 8460 7469 85 00 sta SCRCX ; set as passed + 8461 746B C6 00 dec SCRCX ; zero base it + 8462 746D A0 01 ldy #WINLEFT ; get left hand edge of window + 8463 746F B1 05 lda (WINDOW),Y ; got it + 8464 7471 18 clc ; get ready for add + 8465 7472 65 00 adc SCRCX ; add the offset + 8466 7474 85 00 sta SCRCX ; and make it X pos + 8467 7476 A9 01 lda #1 ; show cursor change anyway + 8468 7478 8D A5 6C sta CURSFLG ; okay, we did + 8469 747B ZDSP10: + 8470 747B A5 00 lda SCRCX ; get current X + 8471 747D 48 pha ; save it + 8472 747E 18 clc ; adding + 8473 747F 6D 06 74 adc PICINFO+PLDWID ; add in pic width + 8474 7482 85 00 sta SCRCX ; save here + 8475 7484 68 pla ; get start X pos back + 8476 7485 85 00 sta SCRCX ; restored + 8477 7487 ZDSP101: + 8478 7487 AD 08 74 lda PICINFO+PLDFLG ; get flag byte + 8479 748A 29 01 and #1 ; is there a transparent color? + 8480 748C D0 04 bne ZDSP11 ; ayyup + 8481 748E A9 FF lda #$FF ; make TRANSCLR be $FF + 8482 7490 D0 07 bne ZDSP12 ; okay + 8483 7492 ZDSP11: + 8484 7492 AD 08 74 lda PICINFO+PLDFLG ; get hi byte of flag word + 8485 7495 4A lsr A ; put in lower byte + 8486 7496 4A lsr A ; put in lower byte + 8487 7497 4A lsr A ; put in lower byte + 8488 7498 4A lsr A ; put in lower byte + 8489 7499 ZDSP12: + 8490 7499 8D 0C 74 sta TRANSCLR ; save transparent color + 8491 + 8492 749C AD 09 74 lda PICINFO+PLDPTR ; MSB of offset + 8493 749F 8D F8 73 sta PFSEEK+SM_FPOS+2 ; MSB of seek + 8494 74A2 AD 0A 74 lda PICINFO+PLDPTR+1 ; Middle + 8495 74A5 29 FE and #$FE ; seek only to 512byte boundary + 8496 74A7 8D F7 73 sta PFSEEK+SM_FPOS+1 + 8497 + 8498 74AA SET_MARK PFSEEK ; go to pic data + 8499 74AA PRODOS $CE, PFSEEK + 8500 74AA 20 00 BF jsr $BF00 ; ProDOS handler + 8501 74AD CE DB $CE ; ProDOS function code + 8502 74AE F473 DW PFSEEK ; Function Parameter Block address + 8503 74B0 .MACEND + 8504 74B0 .MACEND + 8505 74B0 A9 02 lda #>PIC1BUF ; set up pointers to decode buffers + 8506 74B2 85 7B sta J+HI + 8507 74B4 A9 73 lda #PIC2BUF + 8510 74BA 85 7D sta K+HI + 8511 74BC A9 74 lda #IOBUFF ; now get data buffer address + 8523 74D0 85 7F sta L+HI + 8524 74D2 A9 04 lda #4 ; 4 pages read in at once + 8525 74D4 8D FE 73 sta P_BCNT ; okay + 8526 74D7 A9 03 lda #3 ; 3 bytes of width data start it + 8527 74D9 18 clc ; doing add + 8528 74DA 6D 0B 74 adc PICINFO+PLDPTR+2 ; pick up LSB pointer + 8529 74DD 8D FD 73 sta P_IDX ; start index + Tue Jun 13 1989 11:42 Page 130 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8530 74E0 90 05 bcc ZDLPCC ; no wrap + 8531 74E2 E6 7F inc L+HI ; start at second one + 8532 74E4 CE FE 73 dec P_BCNT ; one less block + 8533 74E7 ZDLPCC: + 8534 74E7 AD 0A 74 lda PICINFO+PLDPTR+1 ; tells which block it is in + 8535 74EA 29 01 and #$01 ; pick up which 256 block + 8536 74EC F0 05 beq ZDLP0 ; start at first one + 8537 74EE E6 7F inc L+HI ; start at next one + 8538 74F0 CE FE 73 dec P_BCNT ; one less block + 8539 74F3 ZDLP0: + 8540 74F3 A9 00 lda #IOBUFF ; reset data buffer address + 8735 762A 85 7F sta L+HI + 8736 762C A9 00 lda #GBL_DIR ; start destination off here + 8793 7678 20 93 76 jsr READ_IN_PDATA ; go get global directory, if any + 8794 767B 8D 00 74 sta GBL_FLAG ; indicate whether there is a global + 8795 767E GTPG1: + 8796 767E AD B5 49 lda SAVENUM ; get which file is being opened + 8797 7681 29 0F and #$0F ; just make it binary + 8798 7683 CD FC 73 cmp PF_FID ; same as the file we already have? + 8799 7686 F0 0A beq GETPGX ; yes, so don't bother + 8800 7688 A0 02 ldy #SGTPICOF ; point to picture offset + 8801 768A A9 D0 lda #>PIC_DIR ; start destination off here + 8802 768C 20 93 76 jsr READ_IN_PDATA ; go get the data for local pictures + 8803 768F 8D 01 74 sta PIC_FLAG ; any picture data + 8804 7692 GETPGX: + 8805 7692 60 rts + 8806 ; + 8807 ; READ_IN_PDATA - check for desired data being in file, and skip to it if + 8808 ; it is. Then, read it in in 1Kb chunks, stashing it away into the + 8809 ; upper bank of the aux mem language card. + 8810 ; Enter with: + 8811 ; [A] = Destination page + 8812 ; [Y] = Offset into Segment table + 8813 ; + 8814 7693 READ_IN_PDATA: + 8815 7693 48 pha ; save destination page + 8816 7694 B1 1E lda (DSEGS),Y ; get MSB + 8817 7696 8D F8 73 sta PFSEEK+SM_FPOS+2 ; Byte 2 + 8818 7699 C8 iny ; point to LSB + 8819 769A 11 1E ora (DSEGS),Y ; is there any pic data? + 8820 769C D0 04 bne GTPD00 ; yes + 8821 769E 68 pla ; get page back + 8822 769F A9 00 lda #0 ; show not here + 8823 76A1 60 rts ; nope + 8824 76A2 GTPD00: + 8825 76A2 B1 1E lda (DSEGS),Y ; get it for shifting + 8826 76A4 0A asl A ; *2 + 8827 76A5 8D F7 73 sta PFSEEK+SM_FPOS+1 ; stash away + 8828 76A8 2E F8 73 rol PFSEEK+SM_FPOS+2 ; pick up carry + 8829 76AB A9 00 lda #0 ; clear out MSB + Tue Jun 13 1989 11:42 Page 134 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8830 76AD 8D F1 73 sta PFILE_RD+RD_BUFFLEN+HI + 8831 76B0 8D F6 73 sta PFSEEK+SM_FPOS ; and LSB of seeking + 8832 + 8833 76B3 AD FB 73 lda PF_REFNUM ; get file ref number + 8834 76B6 8D ED 73 sta PFILE_RD+RD_REFNUM ; and save it for reading and + 8835 76B9 8D F5 73 sta PFSEEK+SM_REFNUM ; for seeking + 8836 + 8837 76BC A9 03 lda #RETRY_COUNT ; set retry + 8838 76BE 85 0E sta NY_DATA ; just use this for now + 8839 76C0 GTPDRD0: + 8840 76C0 SET_MARK PFSEEK ; and go to beginning + 8841 76C0 PRODOS $CE, PFSEEK + 8842 76C0 20 00 BF jsr $BF00 ; ProDOS handler + 8843 76C3 CE DB $CE ; ProDOS function code + 8844 76C4 F473 DW PFSEEK ; Function Parameter Block address + 8845 76C6 .MACEND + 8846 76C6 .MACEND + 8847 + 8848 76C6 A9 04 lda #4 ; read in 4 256 blocks + 8849 76C8 8D F1 73 sta PFILE_RD+RD_BUFFLEN+HI + 8850 76CB READ PFILE_RD ; go get the next 4Kb worth + 8851 76CB PRODOS $CA, PFILE_RD + 8852 76CB 20 00 BF jsr $BF00 ; ProDOS handler + 8853 76CE CA DB $CA ; ProDOS function code + 8854 76CF EC73 DW PFILE_RD ; Function Parameter Block address + 8855 76D1 .MACEND + 8856 76D1 .MACEND + 8857 76D1 90 05 bcc GTPD1 ; fine + 8858 76D3 20 F7 46 jsr RETRY ; well, do it again? + 8859 76D6 90 E8 bcc GTPDRD0 ; yes + 8860 76D8 GTPD1: + 8861 76D8 68 pla ; get destination page back + 8862 76D9 C9 D0 cmp #>PIC_DIR ; if doing local directory, set up + 8863 76DB D0 16 bne GTPD2 ; picture count + 8864 76DD AE 04 08 ldx IOBUFF+PHNLD ; get number of pictures + 8865 76E0 8E FA 73 stx PICCNT+HI ; save for count down too + 8866 76E3 AE 05 08 ldx IOBUFF+PHNLD+1 ; and here is LSB + 8867 76E6 8E F9 73 stx PICCNT+LO ; saving for counting + 8868 76E9 AE 00 08 ldx IOBUFF+PHFID ; get file ID + 8869 76EC 8E FC 73 stx PF_FID ; and save for later + 8870 76EF A2 20 ldx #(256/PLDSIZE) ; how many entries in 256 bytes + 8871 76F1 D0 0E bne GTPD3 ; done + 8872 76F3 GTPD2: + 8873 76F3 AE 00 08 ldx IOBUFF ; get MSB of how many + 8874 76F6 8E FA 73 stx PICCNT+HI ; show me + 8875 76F9 AE 01 08 ldx IOBUFF+1 ; get LSB of count + 8876 76FC 8E F9 73 stx PICCNT+LO + 8877 76FF A2 80 ldx #(256/2) ; how many entries / 256 bytes + 8878 7701 GTPD3: + 8879 7701 8E 38 77 stx GTPMOD+1 ; set up how big entry is + 8880 7704 8D 09 C0 sta ALTZP+AUX ; use aux mem for most of this + 8881 7707 85 7D sta K+HI ; MSB of destination + 8882 7709 A9 00 lda #0 ; clear a few things + 8883 770B 85 7A sta J+LO ; J = source + 8884 770D 85 7C sta K+LO ; K = destination + 8885 770F A9 04 lda #4 ; 4 * (4*256) bytes max + 8886 7711 8D F1 73 sta PFILE_RD+RD_BUFFLEN+HI ; show the read too + 8887 7714 8D FD 73 sta P_IDX ; save here for counting + 8888 7717 GTPDL: + 8889 7717 A0 00 ldy #0 ; start y + 8890 7719 A9 08 lda #>IOBUFF ; get where source is + 8891 771B 85 7B sta J+HI ; MSB of source + 8892 771D A9 04 lda #4 ; 4 blocks worth of 256 + 8893 771F 8D FE 73 sta P_BCNT ; used as counter + 8894 7722 AD 8B C0 lda BNK1SET ; we be using bank 1 @$D000 + 8895 7725 AD 8B C0 lda BNK1SET ; we be using bank 1 @$D000 + 8896 7728 GTPDL1: + 8897 7728 B1 7A lda (J),Y ; get the data byte + 8898 772A 91 7C sta (K),Y ; store in upper aux + 8899 772C C8 iny ; point to the next one + 8900 772D D0 F9 bne GTPDL1 ; and go get it + 8901 772F + 8902 772F E6 7B inc J+HI ; next block please + 8903 7731 E6 7D inc K+HI ; for destination too + 8904 7733 AD F9 73 lda PICCNT+LO ; how many entries? + Tue Jun 13 1989 11:42 Page 135 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8905 7736 38 sec ; doing sbc + 8906 7737 E9 20 GTPMOD: sbc #(256/PLDSIZE) ; how many entries in 256 bytes? + 8907 7739 8D F9 73 sta PICCNT+LO ; save result + 8908 773C B0 05 bcs GTPDL2 ; no wrapping + 8909 773E CE FA 73 dec PICCNT+HI ; wrap + 8910 7741 30 26 bmi GTPDLX ; all done if we go negative + 8911 7743 GTPDL2: + 8912 7743 0D FA 73 ora PICCNT+HI ; make sure both are not zero + 8913 7746 F0 21 beq GTPDLX ; if they are, then we are done + 8914 7748 CE FE 73 dec P_BCNT ; count this block + 8915 774B D0 DB bne GTPDL1 ; go fetch next 256 bytes + 8916 774D 8D 08 C0 sta ALTZP+MAIN ; swap back to main for read + 8917 + 8918 7750 A9 03 lda #RETRY_COUNT ; set retry + 8919 7752 85 0E sta NY_DATA ; just use this for now + 8920 7754 GTPDRD: + 8921 7754 READ PFILE_RD ; go get the next 4Kb worth + 8922 7754 PRODOS $CA, PFILE_RD + 8923 7754 20 00 BF jsr $BF00 ; ProDOS handler + 8924 7757 CA DB $CA ; ProDOS function code + 8925 7758 EC73 DW PFILE_RD ; Function Parameter Block address + 8926 775A .MACEND + 8927 775A .MACEND + 8928 775A 90 05 bcc GTPDRDG ; fine + 8929 775C 20 F7 46 jsr RETRY ; well, do it again? + 8930 775F 90 F3 bcc GTPDRD ; yes + 8931 7761 GTPDRDG: + 8932 7761 8D 09 C0 sta ALTZP+AUX ; and back to aux for working + 8933 7764 CE FD 73 dec P_IDX ; max 4Kb worth of reading + 8934 7767 D0 AE bne GTPDL ; and read in more + 8935 7769 GTPDLX: + 8936 7769 8D 08 C0 sta ALTZP+MAIN ; back to main bank of mem + 8937 776C AD 83 C0 lda BNK2SET ; back to bank 2 + 8938 776F AD 83 C0 lda BNK2SET ; yes please + 8939 7772 A9 01 lda #1 ; show we found it + 8940 7774 60 rts ; all done + 8941 + 8942 7775 00 GTPFLAG: db 0 ; if 1 when opening next file, then + 8943 ; this is the next file, so unable to + 8944 ; find picture number + 8945 7776 GET_PICINF: + 8946 7776 A9 00 lda #0 ; set flag for double check + 8947 7778 8D 75 77 sta GTPFLAG ; start at zero + 8948 777B GTPLOOP: + 8949 777B A5 63 lda ARG1+LO ; check argument for zero + 8950 777D 05 64 ora ARG1+HI ; is it zero? + 8951 777F D0 02 bne GTPINDX ; jump to look at first block + 8952 7781 18 clc ; found some pictures + 8953 7782 60 rts ; if zero, just give count + 8954 7783 GTPINDX: + 8955 7783 A4 63 ldy ARG1+LO ; get arg, as we are swapping + 8956 7785 A6 64 ldx ARG1+HI ; to aux mem + 8957 7787 8D 09 C0 sta ALTZP+AUX ; look at AUX mem + 8958 778A AD 8B C0 lda BNK1SET ; bank 1 + 8959 778D AD 8B C0 lda BNK1SET ; bank 1 + 8960 7790 AD 04 D0 lda PIC_DIR+PHNLD ; get # of entries + 8961 7793 8D FA 73 sta PICCNT+HI + 8962 7796 AD 05 D0 lda PIC_DIR+PHNLD+1 ; it's in reverse order + 8963 7799 8D F9 73 sta PICCNT+LO + 8964 779C 84 63 sty ARG1+LO ; use aux mem zero page + 8965 779E 86 64 stx ARG1+HI ; for new arg1 + 8966 77A0 A9 D0 lda #>PIC_DIR ; start at beginning of block + 8967 77A2 85 8A sta MPNTH ; hi part + 8968 77A4 A9 00 lda #GBL_DIR ; start at beginning of block + 9057 7839 85 8A sta MPNTH ; hi part + 9058 783B A9 00 lda # 2 BYTES + 9441 7A3F 29 40 and #%01000000 + 9442 7A41 F0 04 beq PTZ1 ; BIT 6 = 0, LENGTH = 1 + 9443 7A43 A9 02 lda #2 ; BIT 6 = 1, LENGTH = 2 + 9444 7A45 D0 09 bne PTZ3 ; JMP + 9445 7A47 PTZ1: + 9446 7A47 A9 01 lda #1 + 9447 7A49 D0 05 bne PTZ3 ; JMP + 9448 7A4B PTZ2: + 9449 7A4B 20 88 92 jsr FETCHB ; and get it + 9450 7A4E 29 3F and #%00111111 ; ELSE PICK UP SIZE > 2 + 9451 7A50 PTZ3: + 9452 7A50 A2 00 ldx #0 ; CLEAR FOR PUTBYT + 9453 7A52 4C CD 43 jmp PUTBYT + 9454 ; --- + 9455 ; INC + 9456 ; --- + 9457 ; INCREMENT VARIABLE [ARG1] + 9458 + 9459 7A55 A5 63 ZINC: LDA ARG1+LO + 9460 7A57 20 26 43 JSR VARGET ; FETCH VARIABLE INTO [VALUE] + 9461 7A5A E6 76 INC VALUE+LO + 9462 7A5C D0 02 BNE ZINC1 + 9463 7A5E E6 77 INC VALUE+HI + 9464 7A60 4C 75 7A ZINC1: JMP ZD0 + 9465 + 9466 + 9467 ; --- + 9468 ; DEC + 9469 ; --- + 9470 ; DECREMENT VARIABLE [ARG1] + 9471 + 9472 7A63 A5 63 ZDEC: LDA ARG1+LO + 9473 7A65 20 26 43 JSR VARGET ; FETCH VAR INTO [VALUE] + 9474 7A68 A5 76 LDA VALUE+LO + 9475 7A6A 38 SEC + 9476 7A6B E9 01 SBC #1 + 9477 7A6D 85 76 STA VALUE+LO + 9478 7A6F A5 77 LDA VALUE+HI + 9479 7A71 E9 00 SBC #0 + 9480 7A73 85 77 STA VALUE+HI + 9481 7A75 A5 63 ZD0: LDA ARG1+LO ; PUT RESULT BACK + 9482 7A77 4C B7 43 JMP VARPUT ; INTO THE SAME VARIABLE + 9483 + 9484 + 9485 ; ------ + 9486 ; PRINTB + 9487 ; ------ + 9488 ; PRINT Z-STRING AT [ARG1] + 9489 + Tue Jun 13 1989 11:42 Page 144 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9490 7A7A ZPRB: + 9491 7A7A A5 63 lda ARG1+LO ; move arg1 to I + 9492 7A7C 85 78 sta I+LO ; lo part + 9493 7A7E A5 64 lda ARG1+HI ; and now for arg1 hi + 9494 7A80 85 79 sta I+HI ; okay + 9495 7A82 20 92 8F jsr SETWRD ; make [MPC] point to it + 9496 7A85 4C 00 93 jmp PZSTR ; and print it + 9497 + 9498 ; ------ + 9499 ; REMOVE + 9500 ; ------ + 9501 ; MOVE OBJECT [ARG1] INTO PSEUDO-OBJECT #0 + 9502 ; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO + 9503 ; 2) MOVES AND COMPARES 2 BYTES) + 9504 + 9505 7A88 SAVEFPC: ds 3 ; spot to save the FPC + 9506 7A8B SAVEOBJ: ds 1 ; check for zero object + 9507 + 9508 7A8C ZREMOV: + 9509 7A8C A5 63 lda ARG1+LO ; GET SOURCE OBJECT ADDR + 9510 7A8E A6 64 ldx ARG1+HI + 9511 7A90 20 1E 95 jsr OBJLOC ; INTO [FPC] + 9512 ; + 9513 ; now save this objects address in I,J + 9514 ; + 9515 7A93 A9 06 lda #6 ; point to the LOC slot + 9516 7A95 20 10 90 jsr ADDFPC ; thank you + 9517 7A98 A5 8C lda FPCL ; COPY THE SOURCE ADDR + 9518 7A9A 8D 88 7A sta SAVEFPC+LO ; INTO [J] + 9519 7A9D A5 8D lda FPCH ; FOR LATER REFERENCE + 9520 7A9F 8D 89 7A sta SAVEFPC+HI + 9521 7AA2 A5 8E lda FPCBNK + 9522 7AA4 8D 8A 7A sta SAVEFPC+ABANK + 9523 ; + 9524 ; now go get object this one is in + 9525 ; + 9526 7AA7 20 88 92 jsr FETCHB ; get the data + 9527 7AAA 85 7C sta K ; HOLD IT + 9528 7AAC 20 F0 8F jsr NEXTFPC ; get lo part + 9529 7AAF 20 88 92 jsr FETCHB ; now get part + 9530 7AB2 A8 tay ; save it + 9531 7AB3 05 7C ora K ; COMPARE BYTES + 9532 7AB5 D0 03 bne REMVj ; check for object + 9533 7AB7 4C 5C 7B jmp REMVEX ; SCRAM IF NO OBJECT + 9534 7ABA REMVj: + 9535 7ABA 98 tya ; get lo part + 9536 7ABB A6 7C ldx K ; and hi part + 9537 7ABD 20 1E 95 jsr OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [FPC] + 9538 7AC0 A9 0B lda #11 ; POINT TO "FIRST" SLOT, LSB + 9539 7AC2 20 10 90 jsr ADDFPC ; and point to it + 9540 7AC5 20 88 92 jsr FETCHB ; and get it + 9541 7AC8 48 pha ; save LSB + 9542 7AC9 20 56 90 jsr PREVFPC ; point to MSB + 9543 7ACC 20 88 92 jsr FETCHB ; A=LO, X=HI + 9544 7ACF AA tax ; put into x + 9545 7AD0 68 pla ; get LSB back + 9546 7AD1 C5 63 cmp ARG1+LO ; IS THIS THE FIRST? + 9547 7AD3 D0 04 bne REMVC1 ; NO, KEEP SEARCHING + 9548 7AD5 E4 64 cpx ARG1+HI ; HM? + 9549 7AD7 F0 2B beq DO_REMOVE ; yes, so use it + 9550 7AD9 REMVC1: + 9551 7AD9 20 1E 95 jsr OBJLOC ; get object + 9552 7ADC A9 09 lda #9 ; GET "NEXT" slot address + 9553 7ADE 20 10 90 jsr ADDFPC ; into FPC + 9554 7AE1 20 88 92 jsr FETCHB ; get the byte + 9555 7AE4 48 pha ; save LSB for later + 9556 7AE5 20 56 90 jsr PREVFPC ; and this is the hi part + 9557 7AE8 20 88 92 jsr FETCHB + 9558 7AEB 8D 8B 7A sta SAVEOBJ ; save for later check + 9559 7AEE AA tax ; and put into x for (possible) check + 9560 7AEF 68 pla ; get lo part back + 9561 7AF0 A8 tay ; save a minute + 9562 7AF1 0D 8B 7A ora SAVEOBJ ; well, is it zero? + 9563 7AF4 D0 05 bne REMVC2 ; no, so check it + 9564 7AF6 A9 15 lda #21 ; so die + Tue Jun 13 1989 11:42 Page 145 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9565 7AF8 4C F9 51 jmp ZERROR ; and croak + 9566 7AFB REMVC2: + 9567 7AFB 98 tya ; put back into [A] + 9568 7AFC C5 63 cmp ARG1+LO ; FOUND IT? + 9569 7AFE D0 D9 bne REMVC1 ; NO, KEEP TRYING + 9570 7B00 E4 64 cpx ARG1+HI + 9571 7B02 D0 D5 bne REMVC1 + 9572 7B04 DO_REMOVE: + 9573 ; + 9574 ; now, copy from FPC to SPC for stashing away + 9575 ; + 9576 7B04 20 A5 90 jsr FP2SP ; copied + 9577 ; + 9578 ; now get removed one's address for fetching + 9579 ; + 9580 7B07 AD 8A 7A lda SAVEFPC+ABANK ; this is where bank is + 9581 7B0A 85 8E sta FPCBNK ; so show it + 9582 7B0C AD 89 7A lda SAVEFPC+HI ; and here's the hi/lo part + 9583 7B0F 85 8D sta FPCH + 9584 7B11 AD 88 7A lda SAVEFPC+LO + 9585 7B14 85 8C sta FPCL + 9586 7B16 A9 02 lda #2 ; so get to source's "NEXT" slot + 9587 7B18 20 10 90 jsr ADDFPC ; point to next slot + 9588 7B1B 20 88 92 jsr FETCHB ; get the hi byte + 9589 7B1E 20 67 92 jsr STASHB ; and save it + 9590 7B21 20 D0 8F jsr NEXTSPC ; point to next one + 9591 7B24 20 F0 8F jsr NEXTFPC ; and from the source too + 9592 7B27 20 88 92 jsr FETCHB ; get lo byte + 9593 7B2A 20 67 92 jsr STASHB ; and save it away + 9594 ; + 9595 ; now zero out SOURCE's loc and next spots + 9596 ; + 9597 7B2D AD 8A 7A lda SAVEFPC+ABANK ; bank of source + 9598 7B30 85 91 sta SPCBNK + 9599 7B32 AD 89 7A lda SAVEFPC+HI ; and addr of source LOC slot + 9600 7B35 85 90 sta SPCH + 9601 7B37 AD 88 7A lda SAVEFPC+LO + 9602 7B3A 85 8F sta SPCL + 9603 ; + 9604 ; zero out NEXT and LOC of source + 9605 ; + 9606 7B3C A9 00 lda #0 ; zero out 4 locations (LOC MSB) + 9607 7B3E 20 67 92 jsr STASHB + 9608 7B41 20 D0 8F jsr NEXTSPC + 9609 7B44 + 9610 7B44 A9 00 lda #0 ; zero out 4 locations (LOC LSB) + 9611 7B46 20 67 92 jsr STASHB + 9612 7B49 20 D0 8F jsr NEXTSPC + 9613 7B4C + 9614 7B4C A9 00 lda #0 ; zero out 4 locations (NEXT MSB) + 9615 7B4E 20 67 92 jsr STASHB + 9616 7B51 20 D0 8F jsr NEXTSPC + 9617 7B54 + 9618 7B54 A9 00 lda #0 ; zero out 4 locations (NEXT LSB) + 9619 7B56 20 67 92 jsr STASHB + 9620 7B59 20 D0 8F jsr NEXTSPC + 9621 7B5C REMVEX: + 9622 7B5C 60 RTS + 9623 + 9624 + 9625 ; ------ + 9626 ; PRINTD + 9627 ; ------ + 9628 ; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + 9629 + 9630 7B5D ZPRD: + 9631 7B5D A5 63 lda ARG1+LO + 9632 7B5F A6 64 ldx ARG1+HI ; (EZIP) + 9633 7B61 20 1E 95 jsr OBJLOC ; GET ADDR OF OBJECT INTO [FPC] + 9634 7B64 A9 0D lda #13 ; GET PROP TABLE POINTER (EZIP) + 9635 7B66 20 10 90 jsr ADDFPC ; and point to LSB + 9636 7B69 20 88 92 jsr FETCHB ; fetch LSB + 9637 7B6C 48 pha ; SAVE IT HERE + 9638 7B6D 20 56 90 jsr PREVFPC ; and now fetch MSB + 9639 7B70 20 88 92 jsr FETCHB ; thank you + Tue Jun 13 1989 11:42 Page 146 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9640 7B73 85 79 sta I+HI ; AND MSB + 9641 7B75 68 pla ; get LSB back + 9642 7B76 85 78 sta I+LO ; STORE LSB + 9643 7B78 E6 78 inc I+LO ; POINT PAST THE + 9644 7B7A D0 02 bne PDC0 ; LENGTH BYTE + 9645 7B7C E6 79 inc I+HI + 9646 7B7E 20 92 8F PDC0: jsr SETWRD ; CALC Z-STRING ADDR + 9647 7B81 4C 00 93 jmp PZSTR ; AND PRINT IT + 9648 + 9649 + 9650 ; ------ + 9651 ; RETURN + 9652 ; ------ + 9653 ; RETURN FROM "CALL" WITH VALUE [ARG1] + 9654 + 9655 7B84 ZRET: + 9656 7B84 AD A3 6C LDA OLDZSP+LO ; RE-SYNC THE + 9657 7B87 85 AF STA ZSP+LO ; Z-STACK POINTER + 9658 7B89 AD A4 6C LDA OLDZSP+HI + 9659 7B8C 85 B0 STA ZSP+HI + 9660 7B8E 20 56 43 JSR POPVAL ; POP # LOCALS INTO [X/A] + 9661 7B91 86 79 STX I+HI ; SAVE HERE + 9662 7B93 20 56 43 JSR POPVAL ; now we need number of args + 9663 7B96 8D 8F 5B STA ASSVLU ; for ASSIGNED? + 9664 + 9665 7B99 A6 79 LDX I+HI ; see how many locals + 9666 7B9B F0 19 BEQ RET2 ; SKIP IF NOT + 9667 + 9668 ; RESTORE PUSHED LOCALS + 9669 + 9670 7B9D CA DEX ; ZERO-ALIGN + 9671 7B9E 8A TXA ; AND + 9672 7B9F 0A ASL A ; WORD-ALIGN # LOCALS + 9673 7BA0 85 78 STA I+LO ; FOR USE AS A STORAGE INDEX + 9674 7BA2 20 56 43 RET1: JSR POPVAL ; POP A LOCAL INTO [X/A] + 9675 7BA5 A4 78 LDY I+LO ; RETRIEVE STORAGE INDEX + 9676 7BA7 99 01 1E STA LOCALS+HI,Y ; STORE MSB OF LOCAL + 9677 7BAA 8A TXA ; MOVE LSB + 9678 7BAB 99 00 1E STA LOCALS+LO,Y ; AND STORE THAT TOO + 9679 7BAE C6 78 DEC I+LO + 9680 7BB0 C6 78 DEC I+LO ; UPDATE STORAGE INDEX + 9681 7BB2 C6 79 DEC I+HI ; AND LOCALS COUNT + 9682 7BB4 D0 EC BNE RET1 ; POP TILL NO MORE LOCALS + 9683 + 9684 ; RESTORE OTHER VARIABLES + 9685 + 9686 7BB6 RET2: + 9687 7BB6 20 56 43 JSR POPVAL ; POP [ZPCH] AND [ZPCM] + 9688 7BB9 86 81 STX ZPCM + 9689 7BBB 85 82 STA ZPCH + 9690 7BBD 20 56 43 JSR POPVAL ; POP AND RESTORE + 9691 7BC0 8E 8B 5B STX IRET + 9692 7BC3 85 80 STA ZPCL + 9693 7BC5 20 56 43 JSR POPVAL + 9694 7BC8 8E A3 6C STX OLDZSP+LO + 9695 7BCB 8D A4 6C STA OLDZSP+HI + 9696 + 9697 7BCE A5 80 LDA ZPCL ; check for zero zpc + 9698 7BD0 D0 0E BNE RETj ; which means we are returning to + 9699 7BD2 A5 81 LDA ZPCM ; an internal call + 9700 7BD4 D0 0A BNE RETj ; rather than just a normal + 9701 7BD6 A5 82 LDA ZPCH ; return + 9702 7BD8 D0 06 BNE RETj ; but so far it isn't + 9703 + 9704 7BDA 20 A4 44 JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9705 7BDD 4C 6E 5B JMP ZIRET ; so then do internal return + 9706 7BE0 RETj: + 9707 7BE0 20 DC 90 JSR VLDZPC ; MAKE VALID + 9708 7BE3 AD 8B 5B LDA IRET ; CHECK IF SHOULD RETURN A VALUE + 9709 7BE6 F0 01 BEQ RETYES ; (0 = RET, 1 = NO RETURN) + 9710 7BE8 60 RTS ; NO, SO JUST GET OUT OF HERE + 9711 7BE9 RETYES: + 9712 7BE9 20 A4 44 JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9713 7BEC 4C D1 43 JMP PUTVAL ; AND RETURN IT + 9714 + Tue Jun 13 1989 11:42 Page 147 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9715 + 9716 ; ---- + 9717 ; JUMP + 9718 ; ---- + 9719 ; JUMP TO Z-LOCATION IN [ARG1] + 9720 + 9721 7BEF 20 A4 44 ZJUMP: JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9722 7BF2 4C 65 44 JMP PREDB3 ; A BRANCH THAT ALWAYS SUCCEEDS + 9723 + 9724 + 9725 ; ----- + 9726 ; PRINT + 9727 ; ----- + 9728 ; PRINT Z-STRING AT WORD (QUAD) POINTER [ARG1] + 9729 + 9730 7BF5 ZPRINT: + 9731 7BF5 A5 63 LDA ARG1+LO + 9732 7BF7 85 78 STA I+LO + 9733 7BF9 A5 64 LDA ARG1+HI + 9734 7BFB 85 79 STA I+HI + 9735 7BFD 20 D2 92 JSR SETSTR ; CALC STRING ADDRESS + 9736 7C00 4C 00 93 JMP PZSTR ; AND PRINT IT + 9737 + 9738 + 9739 ; ----- + 9740 ; VALUE + 9741 ; ----- + 9742 ; RETURN VALUE OF VARIABLE [ARG1] + 9743 + 9744 7C03 ZVALUE: + 9745 7C03 A5 63 LDA ARG1+LO + 9746 7C05 20 26 43 JSR VARGET ; GET THE VALUE + 9747 7C08 4C D1 43 JMP PUTVAL ; EASY ENOUGH + 9748 + 9749 + 9750 + 9751 7C0B STTL "--- 2-OPS ---" + 9752 PAGE + Tue Jun 13 1989 11:42 Page 148 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9753 + 9754 + 9755 ; ----- + 9756 ; LESS? + 9757 ; ----- + 9758 ; [ARG1] < [ARG2]? + 9759 + 9760 7C0B ZLESS: + 9761 7C0B 20 A4 44 JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9762 7C0E 4C 14 7C JMP DLS0 ; MOVE [ARG2] TO [I] & COMPARE + 9763 + 9764 + 9765 ; ------ + 9766 ; DLESS? + 9767 ; ------ + 9768 ; DECREMENT [ARG1] ; SUCCEED IF < [ARG2] + 9769 + 9770 7C11 ZDLESS: + 9771 7C11 20 63 7A JSR ZDEC ; MOVES ([ARG1]-1) TO [VALUE] + 9772 7C14 A5 65 DLS0: LDA ARG2+LO ; MOVE [ARG2] TO [I] + 9773 7C16 85 78 STA I+LO + 9774 7C18 A5 66 LDA ARG2+HI + 9775 7C1A 85 79 STA I+HI + 9776 7C1C 4C 3D 7C JMP COMPAR ; COMPARE & RETURN + 9777 + 9778 + 9779 ; ----- + 9780 ; GRTR? + 9781 ; ----- + 9782 ; [ARG1] < [ARG2]? + 9783 + 9784 7C1F A5 63 ZGRTR: LDA ARG1+LO ; MOVE [ARG1] TO [I] + 9785 7C21 85 78 STA I+LO + 9786 7C23 A5 64 LDA ARG1+HI + 9787 7C25 85 79 STA I+HI + 9788 7C27 4C 35 7C JMP A2VAL ; MOVE [ARG2] TO [VALUE] & COMPARE + 9789 + 9790 + 9791 ; ------ + 9792 ; IGRTR? + 9793 ; ------ + 9794 ; INCREMENT [ARG1] ; SUCCEED IF GREATER THAN [ARG2] + 9795 + 9796 7C2A 20 55 7A ZIGRTR: JSR ZINC ; GET ([ARG1]+1) INTO [VALUE] + 9797 7C2D A5 76 LDA VALUE+LO ; MOVE [VALUE] TO [I] + 9798 7C2F 85 78 STA I+LO + 9799 7C31 A5 77 LDA VALUE+HI + 9800 7C33 85 79 STA I+HI + 9801 7C35 A5 65 A2VAL: LDA ARG2+LO ; MOVE [ARG2] TO [VALUE] + 9802 7C37 85 76 STA VALUE+LO + 9803 7C39 A5 66 LDA ARG2+HI + 9804 7C3B 85 77 STA VALUE+HI + 9805 + 9806 + 9807 ; ----------------- + 9808 ; SIGNED COMPARISON + 9809 ; ----------------- + 9810 ; ENTRY: VALUES IN [VALUE] AND [I] + 9811 ; + 9812 ; IS [VALUE] > [I] + 9813 ; + 9814 7C3D COMPAR: + 9815 7C3D A5 79 LDA I+HI + 9816 7C3F 45 77 EOR VALUE+HI + 9817 7C41 10 09 BPL SCMP + 9818 7C43 A5 79 LDA I+HI + 9819 7C45 C5 77 CMP VALUE+HI + 9820 7C47 90 42 BCC PGOOD + 9821 7C49 4C 1F 44 JMP PREDF + 9822 + 9823 7C4C A5 77 SCMP: LDA VALUE+HI + 9824 7C4E C5 79 CMP I+HI + 9825 7C50 D0 04 BNE SCEX + 9826 7C52 A5 76 LDA VALUE+LO + 9827 7C54 C5 78 CMP I+LO + Tue Jun 13 1989 11:42 Page 149 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9828 7C56 90 33 SCEX: BCC PGOOD + 9829 7C58 4C 1F 44 JMP PREDF + 9830 + 9831 + 9832 ; --- + 9833 ; IN? + 9834 ; --- + 9835 ; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? + 9836 7C5B ZIN: + 9837 7C5B A5 63 LDA ARG1+LO + 9838 7C5D A6 64 LDX ARG1+HI + 9839 7C5F 20 1E 95 JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [FPC] + 9840 7C62 A9 06 LDA #6 ; POINT TO "LOC" SLOT + 9841 7C64 20 10 90 jsr ADDFPC ; and point to it + 9842 7C67 20 88 92 jsr FETCHB ; well? + 9843 7C6A C5 66 CMP ARG2+HI ; IS IT THERE? + 9844 7C6C D0 0A BNE PBAD ; NO + 9845 7C6E 20 F0 8F jsr NEXTFPC ; point to lo part + 9846 7C71 20 88 92 jsr FETCHB ; and get it + 9847 7C74 C5 65 CMP ARG2+LO + 9848 7C76 F0 13 BEQ PGOOD ; YES, SUCCEED + 9849 7C78 4C 1F 44 PBAD: JMP PREDF ; TOO BAD, CHUM ... + 9850 + 9851 + 9852 ; ---- + 9853 ; BTST + 9854 ; ---- + 9855 ; IS EVERY "ON" BIT IN [ARG1] + 9856 ; ALSO "ON" IN [ARG2]? + 9857 + 9858 7C7B A5 65 ZBTST: LDA ARG2+LO ; FIRST CHECK LSBS + 9859 7C7D 25 63 AND ARG1+LO + 9860 7C7F C5 65 CMP ARG2+LO ; LSBS MATCH? + 9861 7C81 D0 F5 BNE PBAD ; NO, EXIT NOW + 9862 7C83 A5 66 LDA ARG2+HI ; ELSE CHECK MSBS + 9863 7C85 25 64 AND ARG1+HI + 9864 7C87 C5 66 CMP ARG2+HI ; MATCHED? + 9865 7C89 D0 ED BNE PBAD ; SORRY ... + 9866 7C8B PGOOD: + 9867 7C8B 4C 2B 44 JMP PREDS + 9868 + 9869 + 9870 ; --- + 9871 ; BOR + 9872 ; --- + 9873 ; RETURN [ARG1] "OR" [ARG2] + 9874 + 9875 7C8E A5 63 ZBOR: LDA ARG1+LO + 9876 7C90 05 65 ORA ARG2+LO + 9877 7C92 AA TAX + 9878 7C93 A5 64 LDA ARG1+HI + 9879 7C95 05 66 ORA ARG2+HI + 9880 + 9881 ; FALL THROUGH ... + 9882 + 9883 + 9884 ; --------------------- + 9885 ; RETURN VALUE IN [X/A] + 9886 ; --------------------- + 9887 + 9888 7C97 86 76 VEXIT: STX VALUE+LO + 9889 7C99 85 77 STA VALUE+HI + 9890 7C9B 4C D1 43 JMP PUTVAL + 9891 + 9892 + 9893 ; ---- + 9894 ; BAND + 9895 ; ---- + 9896 ; RETURN [ARG1] "AND" [ARG2] + 9897 + 9898 7C9E A5 63 ZBAND: LDA ARG1+LO + 9899 7CA0 25 65 AND ARG2+LO + 9900 7CA2 AA TAX + 9901 7CA3 A5 64 LDA ARG1+HI + 9902 7CA5 25 66 AND ARG2+HI + Tue Jun 13 1989 11:42 Page 150 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9903 7CA7 4C 97 7C JMP VEXIT + 9904 + 9905 + 9906 ; ----- + 9907 ; FSET? + 9908 ; ----- + 9909 ; IS FLAG [ARG2] SET IN OBJECT [ARG1]? + 9910 + 9911 7CAA 20 AD 95 ZFSETP: JSR FLAGSU ; GET BITS INTO [K] AND [J] + 9912 7CAD A5 7D LDA K+HI ; DO MSBS + 9913 7CAF 25 7B AND J+HI + 9914 7CB1 85 7D STA K+HI + 9915 7CB3 A5 7C LDA K+LO ; DO LSBS + 9916 7CB5 25 7A AND J+LO + 9917 7CB7 05 7D ORA K+HI ; ANY BITS ON? + 9918 7CB9 D0 D0 BNE PGOOD ; TARGET BIT MUST BE ON + 9919 7CBB 4C 1F 44 JMP PREDF + 9920 + 9921 + 9922 ; ---- + 9923 ; FSET + 9924 ; ---- + 9925 ; SET FLAG [ARG2] IN OBJECT [ARG1] + 9926 + 9927 7CBE ZFSET: + 9928 7CBE 20 AD 95 JSR FLAGSU ; GET BITS INTO [K] & [J], ADDR IN [FPC] + 9929 ; + 9930 ; now, copy from FPC to SPC for stashing away + 9931 ; + 9932 7CC1 20 A5 90 jsr FP2SP ; okay, done it + 9933 7CC4 A5 7D lda K+HI ; FIRST DO MSBS + 9934 7CC6 05 7B ora J+HI + 9935 7CC8 20 67 92 jsr STASHB + 9936 7CCB 20 D0 8F jsr NEXTSPC + 9937 7CCE A5 7C lda K+LO ; THEN LSBS + 9938 7CD0 05 7A ora J+LO + 9939 7CD2 20 67 92 jsr STASHB + 9940 7CD5 60 rts + 9941 + 9942 + 9943 ; ------ + 9944 ; FCLEAR + 9945 ; ------ + 9946 ; CLEAR FLAG [ARG2] IN OBJECT [ARG1] + 9947 + 9948 7CD6 ZFCLR: + 9949 7CD6 20 AD 95 jsr FLAGSU ; GETS BITS INTO [J] & [K], ADDR IN [FPC] + 9950 ; + 9951 ; now, copy from FPC to SPC for stashing away + 9952 ; + 9953 7CD9 20 A5 90 jsr FP2SP ; okey dokey + 9954 + 9955 7CDC A5 7B lda J+HI ; FETCH MSB + 9956 7CDE 49 FF eor #$FF ; COMPLEMENT IT + 9957 7CE0 25 7D and K+HI ; RUB OUT FLAG + 9958 7CE2 20 67 92 jsr STASHB ; and save it + 9959 7CE5 20 D0 8F jsr NEXTSPC ; point to lo part + 9960 7CE8 A5 7A lda J+LO ; SAME FOR LSB + 9961 7CEA 49 FF eor #$FF + 9962 7CEC 25 7C and K+LO + 9963 7CEE 20 67 92 jsr STASHB ; and show it to the world + 9964 7CF1 60 rts + 9965 + 9966 + 9967 ; --- + 9968 ; SET + 9969 ; --- + 9970 ; SET VARIABLE [ARG1] EQUAL TO [ARG2] + 9971 + 9972 7CF2 A5 65 ZSET: LDA ARG2+LO ; MOVE THE VALUE + 9973 7CF4 85 76 STA VALUE+LO ; INTO [VALUE] + 9974 7CF6 A5 66 LDA ARG2+HI + 9975 7CF8 85 77 STA VALUE+HI + 9976 7CFA A5 63 LDA ARG1+LO ; GET VARIABLE ID + 9977 7CFC 4C B7 43 JMP VARPUT ; AND CHANGE THE VARIABLE + Tue Jun 13 1989 11:42 Page 151 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9978 + 9979 + 9980 ; ---- + 9981 ; MOVE + 9982 ; ---- + 9983 ; MOVE OBJECT [ARG1] INTO OBJECT [ARG2] + 9984 ; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + 9985 + 9986 7CFF ZMOVE: + 9987 7CFF 20 8C 7A jsr ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS + 9988 ; + 9989 ; Make [ARG1] be first in [ARG2]'s chain. + 9990 ; + 9991 7D02 A5 65 lda ARG2+LO + 9992 7D04 A6 66 ldx ARG2+HI ; Get parent's address + 9993 7D06 20 1E 95 jsr OBJLOC ; into [FPC] + 9994 7D09 A9 0A lda #10 ; point to FIRST slot + 9995 7D0B 20 10 90 jsr ADDFPC ; okay + 9996 7D0E 20 88 92 jsr FETCHB ; get old first one (MSB) + 9997 7D11 85 7D sta K+HI ; save it + 9998 7D13 20 F0 8F jsr NEXTFPC ; point to next part + 9999 7D16 20 88 92 jsr FETCHB ; and get it +10000 7D19 85 7C sta K+LO ; okay, saved +10001 7D1B 20 A5 90 jsr FP2SP ; make FPC == SPC +10002 ; +10003 ; now make object [ARG1] be first in object [ARG2] +10004 ; SPC is currently pointing to LSB of [ARG2]'s FIRST slot +10005 ; +10006 7D1E A5 63 lda ARG1+LO ; stash away low part first +10007 7D20 20 67 92 jsr STASHB ; stashed +10008 7D23 20 80 90 jsr PREVSPC ; point to high part +10009 7D26 A5 64 lda ARG1+HI ; get hi part of source +10010 7D28 20 67 92 jsr STASHB ; save it +10011 ; +10012 ; now point to object [ARG1] to update its slots +10013 ; +10014 7D2B A6 64 ldx ARG1+HI ; put hi part here +10015 7D2D A5 63 lda ARG1+LO ; and lo part here for OBJLOC +10016 7D2F 20 1E 95 jsr OBJLOC ; get me the SOURCE of all confusion +10017 7D32 A9 06 lda #6 ; point to LOC slot +10018 7D34 20 10 90 jsr ADDFPC ; and now FPC points there +10019 7D37 20 A5 90 jsr FP2SP ; now make it the STASH pointer +10020 ; +10021 ; update [ARG1]s LOC pointer to be [ARG2] +10022 ; SPC points to LOC slot +10023 ; +10024 7D3A A5 66 lda ARG2+HI ; get PARENT number +10025 7D3C 20 67 92 jsr STASHB ; and save it in LOC +10026 7D3F 20 D0 8F jsr NEXTSPC ; and point to LSB of LOC +10027 7D42 A5 65 lda ARG2+LO ; got parent's lowness +10028 7D44 20 67 92 jsr STASHB ; and saved it in ARG1 +10029 ; +10030 ; Move old FIRST object and make it [ARG1]s NEXT +10031 ; now SPC points to [ARG1]s NEXT slot +10032 ; +10033 7D47 20 D0 8F jsr NEXTSPC ; point to MSB of NEXT +10034 7D4A A5 7D lda K+HI ; get old FIRST one +10035 7D4C 20 67 92 jsr STASHB ; and save it +10036 7D4F 20 D0 8F jsr NEXTSPC ; and point to LSB now +10037 7D52 A5 7C lda K+LO ; get LSB of this +10038 7D54 20 67 92 jsr STASHB ; saved +10039 7D57 60 rts +10040 +10041 ; --- +10042 ; GET +10043 ; --- +10044 ; RETURN ITEM [ARG2] IN WORD-TABLE [ARG1] +10045 +10046 7D58 ZGET: +10047 7D58 20 6F 7D JSR WCALC ; CALC ADDRESS +10048 7D5B 20 3B 92 JSR GETBYT ; GET 1ST BYTE (MSB) +10049 7D5E 85 77 DOGET: STA VALUE+HI ; SAVE MSB +10050 7D60 20 3B 92 JSR GETBYT ; GET LSB +10051 7D63 85 76 STA VALUE+LO ; SAVE AND +10052 7D65 4C D1 43 jmp PUTVAL ; HAND IT OVER + Tue Jun 13 1989 11:42 Page 152 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10053 +10054 +10055 ; ---- +10056 ; GETB +10057 ; ---- +10058 ; RETURN ITEM [ARG2] IN BYTE-TABLE AT [ARG1] +10059 +10060 7D68 ZGETB: +10061 7D68 20 73 7D JSR BCALC +10062 7D6B A9 00 LDA #0 +10063 7D6D F0 EF BEQ DOGET ; [A] = 0, SO CLEAR MSB OF [VALUE] +10064 +10065 +10066 ; -------------------- +10067 ; CALC TABLE ADDRESSES +10068 ; -------------------- +10069 ; WORD-ALIGNED ENTRY +10070 +10071 7D6F WCALC: +10072 7D6F 06 65 ASL ARG2+LO ; WORD-ALIGN FOR +10073 7D71 26 66 ROL ARG2+HI ; WORD ACCESS +10074 ; +10075 ; BYTE-ALIGNED ENTRY +10076 ; +10077 7D73 BCALC: +10078 7D73 A5 65 LDA ARG2+LO ; ADD BASE ADDR OF TABLE +10079 7D75 18 CLC ; TO ITEM +10080 7D76 65 63 ADC ARG1+LO ; INDEX +10081 7D78 85 86 STA MPCL +10082 7D7A A5 66 LDA ARG2+HI ; SAME FOR MSBS +10083 7D7C 65 64 ADC ARG1+HI +10084 7D7E 85 87 STA MPCM +10085 7D80 A9 00 LDA #0 +10086 7D82 69 00 ADC #0 ; PICK UP CARRY FROM MPCM +10087 7D84 85 88 STA MPCH ; TO GET TOP BIT +10088 7D86 4C B2 90 JMP VLDMPC +10089 +10090 +10091 ; ---- +10092 ; GETP +10093 ; ---- +10094 ; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +10095 ; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 +10096 +10097 7D89 ZGETP: +10098 7D89 20 59 95 jsr PROPB ; set up FPC +10099 7D8C GETP1: +10100 7D8C 20 84 95 jsr PROPN ; GET ID OF PROP TBL +10101 7D8F C5 65 cmp ARG2+LO ; Compare PROP ID +10102 7D91 F0 30 beq GETP3 ; FOUND IT +10103 7D93 90 06 bcc GETP2 ; NOT THERE +10104 7D95 20 A3 95 jsr PROPNX ; GET NEXT PROP, ALIGN [FPC] TO IT +10105 7D98 4C 8C 7D jmp GETP1 ; TRY AGAIN WITH NEXT PROP +10106 ; +10107 ; PROPERTY NOT THERE, GET DEFAULT +10108 ; +10109 7D9B GETP2: +10110 7D9B A5 65 lda ARG2+LO ; GET PROPERTY # +10111 7D9D 38 sec ; ZERO-ALIGN IT +10112 7D9E E9 01 sbc #1 +10113 7DA0 0A asl A ; WORD-ALIGN IT +10114 7DA1 18 clc ; add in table start +10115 7DA2 6D 0B 96 adc ZBEGIN+ZOBJEC+1 ; add lo part +10116 7DA5 85 8C sta FPCL ; save for fetch +10117 7DA7 AD 0A 96 lda ZBEGIN+ZOBJEC ; now get hi part +10118 7DAA 69 00 adc #0 ; pick up carry, if any +10119 7DAC 20 A9 8F jsr SETPC ; get memory spot for this page +10120 7DAF 85 8D sta FPCH ; page and +10121 7DB1 84 8E sty FPCBNK ; bank +10122 7DB3 20 88 92 jsr FETCHB ; GET MSB OF PROPERTY +10123 7DB6 85 77 sta VALUE+HI +10124 7DB8 20 F0 8F jsr NEXTFPC +10125 7DBB 20 88 92 jsr FETCHB ; DO SAME WITH LSB +10126 7DBE 85 76 sta VALUE+LO +10127 7DC0 4C D1 43 jmp PUTVAL ; RETURN DEFAULT IN [VALUE] + Tue Jun 13 1989 11:42 Page 153 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10128 7DC3 GETP3: +10129 7DC3 20 8A 95 jsr PROPL ; GET LENGTH OF PROP INTO [A] +10130 7DC6 AA tax ; save [A] +10131 7DC7 20 F0 8F jsr NEXTFPC ; MAKE [FPC] POINT TO 1ST BYTE OF PROP +10132 7DCA E0 01 cpx #1 ; IF LENGTH =1 +10133 7DCC F0 09 beq GETPB ; GET A BYTE PROPERTY +10134 7DCE E0 02 cpx #2 ; IF LENGTH = 2 +10135 7DD0 F0 10 beq GETPW ; GET A WORD PROPERTY +10136 +10137 ; *** ERROR #7: PROPERTY LENGTH *** +10138 +10139 7DD2 A9 07 LDA #7 +10140 7DD4 4C F9 51 JMP ZERROR +10141 ; +10142 ; GET A 1-BYTE PROPERTY +10143 ; +10144 7DD7 GETPB: +10145 7DD7 20 88 92 jsr FETCHB ; GET LSB INTO [A] +10146 7DDA 85 76 sta VALUE+LO ; STORE LSB +10147 7DDC A9 00 lda #0 ; CLEAR MSB +10148 7DDE 85 77 sta VALUE+HI ; and zero it +10149 7DE0 F0 0D beq ETPEX +10150 ; +10151 ; GET A 2-BYTE PROPERTY +10152 ; +10153 7DE2 GETPW: +10154 7DE2 20 88 92 jsr FETCHB ; GET MSB +10155 7DE5 85 77 sta VALUE+HI ; store MSB +10156 7DE7 20 F0 8F jsr NEXTFPC ; POINT TO LSB +10157 7DEA 20 88 92 jsr FETCHB ; GET IT INTO [A] +10158 7DED 85 76 sta VALUE+LO ; AND MSB +10159 7DEF ETPEX: +10160 7DEF 4C D1 43 jmp PUTVAL +10161 +10162 ; ----- +10163 ; GETPT +10164 ; ----- +10165 ; RETURN POINTER TO PROP TABLE [ARG2] +10166 ; IN OBJECT [ARG1] +10167 +10168 7DF2 ZGETPT: +10169 7DF2 A5 63 lda ARG1+LO +10170 7DF4 A6 64 ldx ARG1+HI ; (EZIP) +10171 7DF6 20 1E 95 jsr OBJLOC ; put location into [FPC] +10172 7DF9 A9 0C lda #12 ; get offset table pointer +10173 7DFB 20 10 90 jsr ADDFPC ; and point to it +10174 7DFE 20 88 92 jsr FETCHB ; get MSB of table pointer +10175 7E01 48 pha ; save page +10176 7E02 20 F0 8F jsr NEXTFPC ; point to LSB +10177 7E05 20 88 92 jsr FETCHB ; and get it +10178 7E08 85 8C sta FPCL ; and save it +10179 7E0A 68 pla ; get page address back +10180 7E0B 20 A9 8F jsr SETPC ; and absolutize it +10181 7E0E 85 8D sta FPCH ; and save page +10182 7E10 84 8E sty FPCBNK ; and bank +10183 7E12 20 88 92 jsr FETCHB ; GET LENGTH OF SHORT DESC +10184 7E15 0A asl A ; WORD-ALIGN IT +10185 7E16 A8 tay ; now point to just past it +10186 7E17 C8 iny ; thank you +10187 7E18 98 tya ; for adding +10188 7E19 20 10 90 jsr ADDFPC ; and POINT JUST PAST THE DESCRIPTION +10189 7E1C GETPT1: +10190 7E1C 20 84 95 jsr PROPN ; get prop ID +10191 7E1F C5 65 cmp ARG2+LO ; CHECK ID +10192 7E21 F0 0B beq GETPT2 +10193 7E23 B0 03 bcs DDD ; .GE. so check some more +10194 7E25 4C 5C 7E jmp DORET ; BEYOND IT, SO NOT THERE +10195 7E28 DDD: +10196 7E28 20 A3 95 jsr PROPNX ; point to next one +10197 7E2B 4C 1C 7E jmp GETPT1 ; next please +10198 7E2E GETPT2: +10199 7E2E 20 8A 95 jsr PROPL ; get the length of this property +10200 7E31 20 F0 8F jsr NEXTFPC ; INC TO POINT AT PROPERTY VALUE (EZIP) +10201 ; +10202 ; now subtract absolute address to get relative address for returning + Tue Jun 13 1989 11:42 Page 154 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10203 ; what a pain in the neck +10204 ; +10205 7E34 A5 8E lda FPCBNK ; check which bank we are in +10206 7E36 F0 16 beq GETPB0 ; in main bank, it's easier +10207 ; +10208 ; if in AUX bank, then we must subtract beginning of AUX mem, then +10209 ; add in size of MAIN bank +10210 ; +10211 7E38 A5 8D lda FPCH ; get page +10212 7E3A C9 D0 cmp #>Z3BEGIN ; in part 2 of aux? +10213 7E3C B0 08 bcs GETPB3 ; ayyup +10214 7E3E 38 sec ; and subtract +10215 7E3F E9 40 sbc #>Z2BEGIN ; first page in aux +10216 7E41 18 clc ; now add in how many pages in main +10217 7E42 69 29 adc #P2PAGE ; now we have relative start +10218 7E44 D0 0D bne GETP15 ; JUMP to putval +10219 7E46 GETPB3: +10220 7E46 38 sec ; and subtract +10221 7E47 E9 D0 sbc #>Z3BEGIN ; first page in aux, part 2 +10222 7E49 18 clc ; now add in how many pages in main +10223 7E4A 69 A8 adc #P3PAGE ; now we have relative start +10224 7E4C D0 05 bne GETP15 ; jump to putval +10225 7E4E GETPB0: +10226 7E4E A5 8D lda FPCH ; get page in main mem +10227 7E50 38 sec ; and then subtract +10228 7E51 E9 96 sbc #>ZBEGIN ; start of main mem +10229 7E53 GETP15: +10230 7E53 85 77 sta VALUE+HI ; save hi part for returning +10231 7E55 A5 8C lda FPCL ; and just save lo part +10232 7E57 85 76 sta VALUE+LO ; okay? +10233 7E59 4C D1 43 jmp PUTVAL ; AND RETURN +10234 7E5C DORET: +10235 7E5C 4C CA 43 jmp RET0 ; ELSE RETURN A ZERO +10236 +10237 +10238 ; ----- +10239 ; NEXTP +10240 ; ----- +10241 ; RETURN INDEX # OF PROP FOLLOWING PROP [ARG2] IN OBJECT [AR +10242 ; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO +10243 +10244 7E5F ZNEXTP: +10245 7E5F 20 59 95 JSR PROPB ; ALIGN [FPC] AT PROPERTY TBL'S 1ST ENTRY +10246 7E62 A5 65 LDA ARG2+LO ; IF [ARG2]=0 +10247 7E64 F0 12 BEQ NXTP3 ; RETURN "FIRST" SLOT +10248 7E66 NXTP1: +10249 7E66 20 84 95 JSR PROPN ; FETCH PROPERTY # +10250 7E69 C5 65 CMP ARG2+LO ; COMPARE TO TARGET # +10251 7E6B F0 08 BEQ NXTP2 ; FOUND IT! +10252 7E6D 90 ED BCC DORET ; LAST PROP, SO RETURN ZERO +10253 7E6F 20 A3 95 JSR PROPNX ; ELSE TRY NEXT PROPERTY (EZIP) +10254 7E72 4C 66 7E JMP NXTP1 +10255 7E75 20 A3 95 NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +10256 7E78 20 84 95 NXTP3: JSR PROPN ; GET THE PROPERTY # +10257 7E7B A2 00 LDX #0 ; FOR PUTBYT (EZIP) +10258 7E7D 4C CD 43 JMP PUTBYT ; AND RETURN IT +10259 +10260 +10261 ; --- +10262 ; ADD +10263 ; --- +10264 ; RETURN [ARG1] + [ARG2] +10265 +10266 7E80 A5 63 ZADD: LDA ARG1+LO ; ADD LSBS +10267 7E82 18 CLC +10268 7E83 65 65 ADC ARG2+LO +10269 7E85 AA TAX ; SAVE LSB HERE +10270 7E86 A5 64 LDA ARG1+HI ; ADD MSBS +10271 7E88 65 66 ADC ARG2+HI +10272 7E8A 4C 97 7C JMP VEXIT +10273 +10274 +10275 ; --- +10276 ; SUB +10277 ; --- + Tue Jun 13 1989 11:42 Page 155 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10278 ; RETURN [ARG1] - [ARG2] +10279 +10280 7E8D A5 63 ZSUB: LDA ARG1+LO ; SUBTRACT LSBS +10281 7E8F 38 SEC +10282 7E90 E5 65 SBC ARG2+LO +10283 7E92 AA TAX ; SAVE LSB HERE +10284 7E93 A5 64 LDA ARG1+HI ; SUBTRACT MSBS +10285 7E95 E5 66 SBC ARG2+HI +10286 7E97 4C 97 7C JMP VEXIT ; EXIT WITH [X]=LSB, [A]=MSB +10287 +10288 +10289 ; --- +10290 ; MUL +10291 ; --- +10292 ; RETURN [ARG1] * [ARG2] +10293 +10294 7E9A 20 80 7F ZMUL: JSR MINIT ; INIT THINGS +10295 7E9D 6E 8D 5B ZMLOOP: ROR MTEMP+HI +10296 7EA0 6E 8C 5B ROR MTEMP+LO +10297 7EA3 66 66 ROR ARG2+HI +10298 7EA5 66 65 ROR ARG2+LO +10299 7EA7 90 11 BCC ZMNEXT +10300 7EA9 A5 63 LDA ARG1+LO +10301 7EAB 18 CLC +10302 7EAC 6D 8C 5B ADC MTEMP+LO +10303 7EAF 8D 8C 5B STA MTEMP+LO +10304 7EB2 A5 64 LDA ARG1+HI +10305 7EB4 6D 8D 5B ADC MTEMP+HI +10306 7EB7 8D 8D 5B STA MTEMP+HI +10307 7EBA CA ZMNEXT: DEX +10308 7EBB 10 E0 BPL ZMLOOP +10309 7EBD A6 65 LDX ARG2+LO ; PUT LSB OF PRODUCT +10310 7EBF A5 66 LDA ARG2+HI ; AND MSB +10311 7EC1 4C 97 7C JMP VEXIT ; WHERE "VEXIT" EXPECTS THEM +10312 +10313 +10314 ; --- +10315 ; DIV +10316 ; --- +10317 ; RETURN QUOTIENT OF [ARG1] / [ARG2] +10318 +10319 7EC4 20 DC 7E ZDIV: JSR DIVIDE +10320 7EC7 AE 89 6C LDX QUOT+LO +10321 7ECA AD 8A 6C LDA QUOT+HI +10322 7ECD 4C 97 7C JMP VEXIT +10323 +10324 +10325 ; --- +10326 ; MOD +10327 ; --- +10328 ; RETURN REMAINDER OF [ARG1] / [ARG2] +10329 +10330 7ED0 20 DC 7E ZMOD: JSR DIVIDE +10331 7ED3 AE 8B 6C LDX REMAIN+LO ; FETCH THE REMAINDER +10332 7ED6 AD 8C 6C LDA REMAIN+HI ; IN [REMAIN] +10333 7ED9 4C 97 7C JMP VEXIT ; AND RETURN IT +10334 +10335 +10336 ; --------------- +10337 ; SIGNED DIVISION +10338 ; --------------- +10339 ; ENTRY: DIVIDEND IN [ARG1], DIVISOR IN [ARG2] +10340 ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] +10341 +10342 7EDC DIVIDE: +10343 7EDC A5 64 LDA ARG1+HI ; SIGN OF REMAINDER +10344 7EDE 8D 8E 6C STA RSIGN ; IS THE SIGN OF THE DIVIDEND +10345 7EE1 45 66 EOR ARG2+HI ; SIGN OF QUOTIENT IS POSITIVE +10346 7EE3 8D 8D 6C STA QSIGN ; IF SIGNS OF TERMS ARE THE SAME +10347 7EE6 A5 63 LDA ARG1+LO ; MOVE [ARG1] TO [QUOT] +10348 7EE8 8D 89 6C STA QUOT+LO +10349 7EEB A5 64 LDA ARG1+HI +10350 7EED 8D 8A 6C STA QUOT+HI ; IF DIVIDEND IS POSITIVE +10351 7EF0 10 03 BPL ABSDIV ; MOVE DIVISOR +10352 7EF2 20 26 7F JSR ABQUOT ; ELSE CALC ABS(DIVIDEND) FIRST + Tue Jun 13 1989 11:42 Page 156 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10353 7EF5 A5 65 ABSDIV: LDA ARG2+LO +10354 7EF7 8D 8B 6C STA REMAIN+LO +10355 7EFA A5 66 LDA ARG2+HI +10356 7EFC 8D 8C 6C STA REMAIN+HI ; IF REMAINDER IS POSITIVE +10357 7EFF 10 03 BPL GODIV ; WE'RE READY TO DIVIDE +10358 7F01 20 14 7F JSR ABREM ; ELSE CALC ABS(DIVISOR) +10359 7F04 20 38 7F GODIV: JSR UDIV ; DO UNSIGNED DIVIDE +10360 7F07 AD 8D 6C LDA QSIGN ; SHOULD QUOTIENT BE FLIPPED? +10361 7F0A 10 03 BPL RFLIP ; NO, TEST REMAINDER +10362 7F0C 20 26 7F JSR ABQUOT ; ELSE GET ABSOLUTE VALUE +10363 7F0F AD 8E 6C RFLIP: LDA RSIGN ; SHOULD EMAINDER BE FLIPPED? +10364 7F12 10 11 BPL DIVEX ; NO, WE'RE DONE +10365 +10366 ; ELSE FALL THROUGH ... +10367 +10368 +10369 ; ---------------- +10370 ; CALC ABS(REMAIN) +10371 ; ---------------- +10372 +10373 7F14 A9 00 ABREM: LDA #0 +10374 7F16 38 SEC +10375 7F17 ED 8B 6C SBC REMAIN+LO +10376 7F1A 8D 8B 6C STA REMAIN+LO +10377 7F1D A9 00 LDA #0 +10378 7F1F ED 8C 6C SBC REMAIN+HI +10379 7F22 8D 8C 6C STA REMAIN+HI +10380 7F25 60 DIVEX: RTS +10381 +10382 +10383 ; -------------- +10384 ; CALC ABS(QUOT) +10385 ; -------------- +10386 +10387 7F26 A9 00 ABQUOT: LDA #0 +10388 7F28 38 SEC +10389 7F29 ED 89 6C SBC QUOT+LO +10390 7F2C 8D 89 6C STA QUOT+LO +10391 7F2F A9 00 LDA #0 +10392 7F31 ED 8A 6C SBC QUOT+HI +10393 7F34 8D 8A 6C STA QUOT+HI +10394 7F37 60 RTS +10395 +10396 +10397 ; ----------------- +10398 ; UNSIGNED DIVISION +10399 ; ----------------- +10400 ; ENTRY: DIVIDEND IN [QUOT], DIVISOR IN [REMAIN] +10401 ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] +10402 +10403 7F38 UDIV: +10404 7F38 AD 8B 6C LDA REMAIN+LO ; CHECK [REMAIN] +10405 7F3B 0D 8C 6C ORA REMAIN+HI ; BEFORE PROCEEDING +10406 7F3E F0 3B BEQ DIVERR ; CAN'T DIVIDE BY ZERO! +10407 7F40 20 80 7F JSR MINIT ; SET IT ALL UP +10408 7F43 2E 89 6C UDLOOP: ROL QUOT+LO +10409 7F46 2E 8A 6C ROL QUOT+HI +10410 7F49 2E 8C 5B ROL MTEMP+LO +10411 7F4C 2E 8D 5B ROL MTEMP+HI +10412 7F4F AD 8C 5B LDA MTEMP+LO +10413 7F52 38 SEC +10414 7F53 ED 8B 6C SBC REMAIN+LO +10415 7F56 A8 TAY ; SAVE HERE +10416 7F57 AD 8D 5B LDA MTEMP+HI +10417 7F5A ED 8C 6C SBC REMAIN+HI +10418 7F5D 90 06 BCC UDNEXT +10419 7F5F 8C 8C 5B STY MTEMP+LO +10420 7F62 8D 8D 5B STA MTEMP+HI +10421 7F65 CA UDNEXT: DEX +10422 7F66 D0 DB BNE UDLOOP +10423 7F68 2E 89 6C ROL QUOT+LO ; SHIFT LAST CARRY FOR QUOTIENT +10424 7F6B 2E 8A 6C ROL QUOT+HI +10425 7F6E AD 8C 5B LDA MTEMP+LO ; MOVE REMAINDER +10426 7F71 8D 8B 6C STA REMAIN+LO ; INTO [REMAIN] +10427 7F74 AD 8D 5B LDA MTEMP+HI + Tue Jun 13 1989 11:42 Page 157 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10428 7F77 8D 8C 6C STA REMAIN+HI +10429 7F7A 60 RTS +10430 +10431 ; *** ERROR #8: DIVISION BY ZERO *** +10432 +10433 7F7B A9 08 DIVERR: LDA #8 +10434 7F7D 4C F9 51 JMP ZERROR +10435 +10436 +10437 ; --------- +10438 ; MATH INIT +10439 ; --------- +10440 +10441 7F80 A2 10 MINIT: LDX #16 ; INIT LOOPING INDEX +10442 7F82 A9 00 LDA #0 +10443 7F84 8D 8C 5B STA MTEMP+LO ; CLEAR TEMP +10444 7F87 8D 8D 5B STA MTEMP+HI ; REGISTER +10445 7F8A 18 CLC ; AND CARRY +10446 7F8B 60 RTS +10447 +10448 +10449 ; ----- +10450 ; THROW +10451 ; ----- +10452 +10453 7F8C ZTHROW: +10454 7F8C A5 65 lda ARG2+LO ; check to see if we are ready to do return +10455 7F8E CD A3 6C cmp OLDZSP+LO +10456 7F91 D0 07 bne ZTHLOOP ; nope, keep unwinding the stack +10457 7F93 A5 66 lda ARG2+HI +10458 7F95 CD A4 6C cmp OLDZSP+HI ; have we found the right frame yet? +10459 7F98 F0 06 beq ZTHDO ; yes +10460 7F9A ZTHLOOP: +10461 7F9A 20 84 7B jsr ZRET ; do another return +10462 7F9D 4C 8C 7F jmp ZTHROW ; and try again +10463 7FA0 ZTHDO: +10464 7FA0 A5 65 lda ARG2+LO ; SET ZSTACK POINTER +10465 7FA2 8D A3 6C sta OLDZSP+LO ; UP FOR ZRET +10466 7FA5 A5 66 lda ARG2+HI +10467 7FA7 8D A4 6C sta OLDZSP+HI +10468 7FAA 4C 84 7B jmp ZRET +10469 +10470 7FAD END +10471 +10472 7FAD INCLUDE OPSX.ASM +10473 PAGE + Tue Jun 13 1989 11:42 Page 158 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10474 7FAD STTL "--- X-OPS ---" +10475 +10476 +10477 ; ------ +10478 ; EQUAL? +10479 ; ------ +10480 ; IS [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? +10481 +10482 7FAD ZEQUAL: +10483 7FAD C6 62 DEC NARGS ; DOUBLE-CHECK # ARGS +10484 7FAF A5 63 LDA ARG1+LO ; FETCH LSB +10485 7FB1 A6 64 LDX ARG1+HI ; AND MSB OF [ARG1] +10486 7FB3 C5 65 CMP ARG2+LO ; TEST LSB OF [ARG2] +10487 7FB5 D0 04 BNE TRY2 ; NO GOOD, LOOK FOR ANOTHER ARG +10488 7FB7 E4 66 CPX ARG2+HI ; ELSE TRY MSB OF [ARG2] +10489 7FB9 F0 18 BEQ EQOK ; MATCHED! +10490 7FBB C6 62 TRY2: DEC NARGS ; OUT OF ARGS YET? +10491 7FBD F0 17 BEQ EQBAD ; YES, WE FAILED +10492 7FBF C5 67 CMP ARG3+LO ; TRY LSB OF [ARG3] +10493 7FC1 D0 04 BNE TRY3 ; NO GOOD, LOOK FOR ANOTHER ARG +10494 7FC3 E4 68 CPX ARG3+HI ; HOW ABOUT MSB OF [ARG3]? +10495 7FC5 F0 0C BEQ EQOK ; YAY! +10496 7FC7 C6 62 TRY3: DEC NARGS ; OUT OF ARGS YET? +10497 7FC9 F0 0B BEQ EQBAD ; IF NOT ... +10498 7FCB C5 69 CMP ARG4+LO ; TRY [ARG4] +10499 7FCD D0 07 BNE EQBAD ; SORRY, CHUM +10500 7FCF E4 6A CPX ARG4+HI ; MSB MATCHED? +10501 7FD1 D0 03 BNE EQBAD ; TOO BAD +10502 +10503 7FD3 4C 2B 44 EQOK: JMP PREDS ; FINALLY MATCHED! +10504 +10505 7FD6 4C 1F 44 EQBAD: JMP PREDF ; FAILURE (SNIFF!) +10506 +10507 +10508 ; ---------------------------- +10509 ; ICALL,ICALL1, ICALL2, IXCALL +10510 ; ---------------------------- +10511 +10512 7FD9 ZICALL: +10513 7FD9 ZICLL1: +10514 7FD9 ZICLL2: +10515 7FD9 A9 01 ZIXCLL: LDA #1 ; SET FLAG FOR RETURNLESS CALL +10516 7FDB 8D 8B 5B STA IRET +10517 7FDE D0 05 BNE IENTR ; JMP OVER NORMAL SETTING +10518 +10519 +10520 ; ------------------- +10521 ; XCALL, CALL1, CALL2 +10522 ; ------------------- +10523 +10524 ZXCALL: ; DROP THROUGH +10525 ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +10526 7FE0 ZCALL2: +10527 +10528 ; ---- +10529 ; CALL +10530 ; ---- +10531 ; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +10532 ; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +10533 ; ([ARG5]-[ARG8] FOR XCALL (EZIP)) +10534 +10535 7FE0 A9 00 ZCALL: LDA #0 +10536 7FE2 8D 8B 5B STA IRET ; SET FLAG TO RETURN SOMETHING +10537 7FE5 A5 63 IENTR: LDA ARG1+LO +10538 7FE7 05 64 ORA ARG1+HI ; IS CALL ADDRESS ZERO? +10539 7FE9 D0 0B BNE DOCALL ; NO, CONTINUE +10540 7FEB AD 8B 5B LDA IRET ; any ret value? +10541 7FEE F0 01 BEQ Ij ; yes, so return a zero +10542 +10543 7FF0 60 RTS ; otherwise, just end +10544 7FF1 Ij: +10545 7FF1 A2 00 LDX #0 +10546 7FF3 4C CD 43 JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +10547 7FF6 AE A3 6C DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER +10548 7FF9 AD A4 6C LDA OLDZSP+HI + Tue Jun 13 1989 11:42 Page 159 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +10549 7FFC 20 8B 43 JSR PUSHXA +10550 7FFF A5 80 LDA ZPCL ; AND LSB OF [ZPC] +10551 8001 AE 8B 5B LDX IRET ; AND RETURN FLAG +10552 8004 20 8B 43 JSR PUSHXA ; ON THE Z-STACK +10553 8007 A6 81 LDX ZPCM ; SAVE MIDDLE 8 BITS +10554 8009 A5 82 LDA ZPCH ; AND TOP BIT OF [ZPC] +10555 800B 20 8B 43 JSR PUSHXA ; AS WELL +10556 +10557 ; FORM 16-BIT ADDRESS FROM [ARG1] +10558 +10559 800E A9 00 LDA #0 +10560 8010 06 63 ASL ARG1+LO ; MULTIPLY [ARG1] +10561 8012 26 64 ROL ARG1+HI ; (BY 2) +10562 8014 2A ROL A ; >BIT INTO [A] +10563 8015 06 63 ASL ARG1+LO ; BY 4 (EZIP) +10564 8017 26 64 ROL ARG1+HI +10565 8019 2A ROL A +10566 801A 85 82 STA ZPCH ; NEW >BIT OF [ZPC] +10567 801C A5 64 LDA ARG1+HI ; GET NEW 0, just ignore! +10958 8297 05 67 ORA ARG3+LO +10959 8299 F0 79 BEQ INTNF ; SAY NOT FOUND +10960 +10961 829B A5 62 LDA NARGS ; IS THERE A RECORD SPEC? +10962 829D C9 04 CMP #4 +10963 829F F0 04 BEQ SET4 +10964 82A1 A9 82 SETDEF: LDA #130 ; NO, SET DEFAULT +10965 82A3 85 69 STA ARG4+LO +10966 +10967 82A5 A5 69 SET4: LDA ARG4+LO +10968 82A7 F0 F8 BEQ SETDEF ; GO BACK AND GET VALUE +10969 82A9 A9 00 LDA #0 ; COMPARE BYTE OR WORD? +10970 82AB 06 69 ASL ARG4+LO +10971 82AD 2A ROL A ; PICK UP INDICATOR +10972 82AE 46 69 LSR ARG4+LO ; CLEAR FROM RECORD LENGTH +10973 82B0 8D 8E 5B STA TYPE ; BYTE (0) OR WORD (1) +10974 82B3 AD 8E 5B LDA TYPE ; SET FLAG +10975 82B6 D0 04 BNE SETTBL +10976 82B8 A5 63 LDA ARG1+LO ; IF ONLY BYTE, MOVE IT +10977 82BA 85 64 STA ARG1+HI ; TO FIRST BYTE CHECKED +10978 82BC SETTBL: +10979 82BC A5 65 LDA ARG2+LO ; PICK UP TBL ADDR +10980 82BE 85 86 STA MPCL +10981 82C0 A5 66 LDA ARG2+HI +10982 82C2 85 87 STA MPCM +10983 82C4 A9 00 LDA #0 +10984 82C6 85 88 STA MPCH ; ONLY A WORD ADDR, SO IN 1ST 64K +10985 82C8 20 B2 90 JSR VLDMPC +10986 +10987 82CB A5 86 INTLP: LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS +10988 82CD 8D 7B 00 STA VWCUR+0 +10989 82D0 A5 87 LDA MPCM +10990 82D2 8D 7C 00 STA VWCUR+1 +10991 82D5 A5 88 LDA MPCH +10992 82D7 8D 7D 00 STA VWCUR+2 +10993 82DA 20 3B 92 JSR GETBYT ; GET 1ST BYTE +10994 82DD C5 64 CMP ARG1+HI ; DOES IT = THE VALUE LOOKING FOR? +10995 82DF D0 0C BNE INTNXT ; NO +10996 82E1 AD 8E 5B LDA TYPE +10997 82E4 F0 3A BEQ INTFND ; ONLY COMPARING A BYTE SO FOUND! +10998 82E6 20 3B 92 JSR GETBYT + Tue Jun 13 1989 11:42 Page 165 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +10999 82E9 C5 63 CMP ARG1+LO +11000 82EB F0 33 BEQ INTFND ; YES, FOUND IT +11001 82ED INTNXT: +11002 82ED AD 7B 00 LDA VWCUR+0 ; TO MOVE UP, JUST ADD +11003 82F0 18 CLC ; OFFSET FROM START OF THIS +11004 82F1 65 69 ADC ARG4+LO ; ENTRY +11005 82F3 85 86 STA MPCL +11006 82F5 90 11 BCC INEXT0 +11007 +11008 82F7 AD 7C 00 LDA VWCUR+1 ; PICK UP CARRY +11009 82FA 69 00 ADC #0 +11010 82FC 85 87 STA MPCM +11011 82FE AD 7D 00 LDA VWCUR+2 +11012 8301 69 00 ADC #0 +11013 8303 85 88 STA MPCH +11014 8305 20 B2 90 JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE +11015 +11016 8308 C6 67 INEXT0: DEC ARG3+LO ; CHECKED ALL ENTRIES? +11017 830A D0 BF BNE INTLP +11018 830C A5 68 LDA ARG3+HI +11019 830E F0 04 BEQ INTNF +11020 8310 C6 68 DEC ARG3+HI +11021 8312 D0 B7 BNE INTLP +11022 +11023 8314 INTNF: +11024 8314 A9 00 LDA #0 ; 0 = NOT FOUND +11025 8316 85 76 STA VALUE+LO +11026 8318 85 77 STA VALUE+HI +11027 831A 20 D1 43 JSR PUTVAL +11028 831D 4C 1F 44 JMP PREDF ; FAILED! +11029 +11030 8320 INTFND: +11031 8320 AD 7B 00 LDA VWCUR+LO +11032 8323 85 76 STA VALUE+LO ; AND SET TO RETURN THE VALUE +11033 8325 AD 7C 00 LDA VWCUR+HI +11034 8328 85 77 STA VALUE+HI +11035 832A 20 D1 43 JSR PUTVAL ; SEND IT BACK +11036 832D 4C 2B 44 JMP PREDS ; AND SCREEM SUCCESS +11037 +11038 ; ---- +11039 ; BCOM +11040 ; ---- +11041 ; COMPLEMENT [ARG1] +11042 +11043 8330 A5 63 ZBCOM: LDA ARG1+LO +11044 8332 49 FF EOR #$FF +11045 8334 85 76 STA VALUE+LO +11046 8336 A5 64 LDA ARG1+HI +11047 8338 49 FF EOR #$FF +11048 833A 85 77 STA VALUE+HI +11049 833C 4C D1 43 JMP PUTVAL +11050 +11051 +11052 ; ----- +11053 ; COPYT +11054 ; ----- +11055 +11056 833F ZCOPYT: +11057 833F A5 65 LDA ARG2+LO ; CHECK OUT WHAT'S TO BE DONE +11058 8341 05 66 ORA ARG2+HI +11059 8343 D0 03 BNE ZC0 +11060 8345 4C F4 83 JMP CASE1 ; ZERO LENGTH BYTES OF SOURCE +11061 8348 ZC0: +11062 8348 A5 68 LDA ARG3+HI +11063 834A C9 7F CMP #$7F +11064 834C 90 03 BCC CASE2 +11065 834E 4C 1A 84 JMP CASE3 ; FORWARD COPY +11066 +11067 ; CASE2 - CHECK IF FORWARD OR BACKWARD COPY +11068 +11069 8351 A5 64 CASE2: LDA ARG1+HI ; IF SRC < DEST +11070 8353 C5 66 CMP ARG2+HI +11071 8355 90 0D BCC CHK2 +11072 8357 F0 03 BEQ ZC1 +11073 8359 4C 7D 83 JMP FRWRD ; NO + Tue Jun 13 1989 11:42 Page 166 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11074 835C A5 63 ZC1: LDA ARG1+LO +11075 835E C5 65 CMP ARG2+LO +11076 8360 F0 02 BEQ CHK2 +11077 8362 B0 19 BCS FRWRD ; NO +11078 8364 A5 63 CHK2: LDA ARG1+LO ; AND SRC + LENGTH > DEST +11079 8366 18 CLC +11080 8367 65 67 ADC ARG3+LO +11081 8369 85 78 STA I+LO +11082 836B A5 64 LDA ARG1+HI +11083 836D 65 68 ADC ARG3+HI +11084 836F C5 66 CMP ARG2+HI +11085 8371 90 0A BCC FRWRD ; NO +11086 8373 D0 3E BNE BKWRD ; YES +11087 8375 A5 78 LDA I+LO +11088 8377 C5 65 CMP ARG2+LO +11089 8379 F0 02 BEQ FRWRD ; DEBUG, IF EQUAL REALLY LESS +11090 837B B0 36 BCS BKWRD ; OVERLAPS SO DO BACKWARD COPY +11091 +11092 ; ELSE FALL THROUGH TO FORWARD COPY +11093 +11094 837D A9 00 FRWRD: LDA #0 ; USE GETBYT CAUSE MAY BE +11095 837F 85 88 STA MPCH ; BEYOND MAIN MEMORY +11096 8381 A5 64 LDA ARG1+HI +11097 8383 85 87 STA MPCM +11098 8385 A5 63 LDA ARG1+LO +11099 8387 85 86 STA MPCL +11100 8389 20 B2 90 JSR VLDMPC ; AND ALIGN TO CORRECT PAGE +11101 838C A5 65 LDA ARG2+LO +11102 838E 85 8F STA SPCL +11103 8390 A5 66 LDA ARG2+HI +11104 8392 20 A9 8F jsr SETPC ; get memory spot +11105 8395 85 90 sta SPCH ; high part +11106 8397 84 91 sty SPCBNK ; and the bank part +11107 8399 A5 67 LDA ARG3+LO +11108 839B 85 7A STA J+LO +11109 839D A5 68 LDA ARG3+HI +11110 839F 85 7B STA J+HI +11111 83A1 FRLP: +11112 83A1 20 B6 44 jsr DECJ +11113 83A4 90 0C bcc FRDUN ; CARRY CLEAR ON $FFFF +11114 83A6 20 3B 92 jsr GETBYT +11115 83A9 20 67 92 jsr STASHB ; and save it +11116 83AC 20 D0 8F jsr NEXTSPC ; and point to next one +11117 83AF 4C A1 83 jmp FRLP +11118 83B2 FRDUN: +11119 83B2 60 rts +11120 +11121 +11122 83B3 BKWRD: +11123 83B3 A5 67 LDA ARG3+LO ; DECR 1ST TO GET CORRECT OFFSET +11124 83B5 85 7A STA J+LO +11125 83B7 A5 68 LDA ARG3+HI +11126 83B9 85 7B STA J+HI +11127 83BB 20 B6 44 JSR DECJ +11128 83BE A5 63 LDA ARG1+LO ; SET TO END OF SOURCE & DEST. +11129 83C0 18 CLC +11130 83C1 65 7A ADC J+LO +11131 83C3 85 8C sta FPCL ; set up fetch pointer +11132 83C5 A5 64 LDA ARG1+HI +11133 83C7 65 7B ADC J+HI +11134 83C9 20 A9 8F jsr SETPC ; and get mem locations +11135 83CC 85 8D sta FPCH +11136 83CE 84 8E sty FPCBNK +11137 83D0 A5 65 LDA ARG2+LO +11138 83D2 18 CLC +11139 83D3 65 7A ADC J+LO +11140 83D5 85 8F sta SPCL ; and now set up stash pointer +11141 83D7 A5 66 LDA ARG2+HI +11142 83D9 65 7B ADC J+HI +11143 83DB 20 A9 8F jsr SETPC ; and get me page/bank +11144 83DE 85 90 sta SPCH +11145 83E0 84 91 sty SPCBNK +11146 83E2 BKLP: +11147 83E2 20 88 92 jsr FETCHB ; get byte +11148 83E5 20 67 92 jsr STASHB ; and save it + Tue Jun 13 1989 11:42 Page 167 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11149 83E8 20 56 90 jsr PREVFPC ; going backwards +11150 83EB 20 80 90 jsr PREVSPC ; and here too +11151 83EE 20 B6 44 jsr DECJ ; RETURNS CARRY CLEAR ON $FFFF +11152 83F1 B0 EF bcs BKLP +11153 83F3 BKDUN: +11154 83F3 60 RTS +11155 +11156 ; ZERO LENGTH # OF BYTES OF SOURCE +11157 +11158 83F4 A5 63 CASE1: LDA ARG1+LO +11159 83F6 85 8F STA SPCL ; set stash pointer +11160 83F8 A5 64 LDA ARG1+HI +11161 83FA 20 A9 8F jsr SETPC ; get page/bank +11162 83FD 85 90 sta SPCH +11163 83FF 84 91 sty SPCBNK +11164 8401 A5 67 LDA ARG3+LO ; SET UP COUNTER +11165 8403 85 7A STA J+LO +11166 8405 A5 68 LDA ARG3+HI +11167 8407 85 7B STA J+HI +11168 8409 C1LP: +11169 8409 20 B6 44 jsr DECJ ; CARRY CLEAR WHEN J = $FFFF +11170 840C 90 0B bcc C1DUN +11171 840E A9 00 lda #0 +11172 8410 20 67 92 jsr STASHB ; and zero it +11173 8413 20 D0 8F jsr NEXTSPC ; and point to next one +11174 8416 4C 09 84 jmp C1LP +11175 8419 C1DUN: +11176 8419 60 rts +11177 +11178 ; 2'S COMPLEMENT LENGTH (XOR + 1) THEN DO FORWARD COPY +11179 +11180 841A CASE3: +11181 841A A5 67 LDA ARG3+LO +11182 841C 49 FF EOR #$FF +11183 841E 85 67 STA ARG3+LO +11184 8420 A5 68 LDA ARG3+HI +11185 8422 49 FF EOR #$FF +11186 8424 85 68 STA ARG3+HI +11187 8426 E6 67 INC ARG3+LO +11188 8428 D0 02 BNE GOFRWD +11189 842A E6 68 INC ARG3+HI +11190 842C 4C 7D 83 GOFRWD: JMP FRWRD +11191 +11192 +11193 ; --------- +11194 ; ASSIGNED? +11195 ; --------- +11196 +11197 +11198 842F ZASSND: +11199 842F A5 63 LDA ARG1+LO ; COMPARE TO # OF OPTIONALS FROM LAST CALL +11200 8431 CD 8F 5B CMP ASSVLU +11201 8434 90 05 BCC DOYES ; IF LESS OR EQUAL, WAS ASSIGNED +11202 8436 F0 03 BEQ DOYES +11203 8438 4C 1F 44 JMP PREDF +11204 843B DOYES: +11205 843B 4C 2B 44 JMP PREDS +11206 +11207 +11208 ; ------------- +11209 ; LOGICAL SHIFT +11210 ; ------------- +11211 ; SHIFT ARG1, ARG2 BITS (LEFT IF ARG2 IS POS. RIGHT IF NEG.) +11212 +11213 843E A5 63 ZSHIFT: LDA ARG1+LO ; SET UP FOR SHIFT +11214 8440 85 76 STA VALUE+LO +11215 8442 A5 64 LDA ARG1+HI +11216 8444 85 77 STA VALUE+HI +11217 8446 A5 65 LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT +11218 8448 C9 80 CMP #$80 +11219 844A B0 0B BCS SRIGHT +11220 +11221 ; SHIFT LEFT +11222 +11223 844C A8 TAY ; COUNT + Tue Jun 13 1989 11:42 Page 168 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11224 844D 06 76 SLP1: ASL VALUE+LO +11225 844F 26 77 ROL VALUE+HI +11226 8451 88 DEY +11227 8452 D0 F9 BNE SLP1 +11228 8454 4C D1 43 JMP PUTVAL ; AND RETURN THE VALUE +11229 +11230 8457 49 FF SRIGHT: EOR #$FF ; COMPLEMENT +11231 8459 A8 TAY +11232 845A 46 77 SLP2: LSR VALUE+HI ; SHIFT +11233 845C 66 76 ROR VALUE+LO +11234 845E 88 DEY +11235 845F 10 F9 BPL SLP2 +11236 8461 4C D1 43 JMP PUTVAL +11237 +11238 +11239 ; ---------------- +11240 ; ARITHMETIC SHIFT +11241 ; ---------------- +11242 ; PROPAGATING SIGN BIT ON RIGHT SHIFT +11243 +11244 8464 A5 65 ZASHFT: LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT +11245 8466 C9 80 CMP #$80 +11246 8468 90 D4 BCC ZSHIFT ; SAME AS LOGICAL SHIFT +11247 846A A6 63 LDX ARG1+LO ; SET UP FOR SHIFT +11248 846C 86 76 STX VALUE+LO +11249 846E A6 64 LDX ARG1+HI +11250 8470 86 77 STX VALUE+HI +11251 +11252 8472 49 FF EOR #$FF ; COMPLEMENT COUNT +11253 8474 A8 TAY +11254 8475 A5 64 ASLP2: LDA ARG1+HI +11255 8477 0A ASL A ; GET SIGN BIT +11256 8478 66 77 ROR VALUE+HI ; SHIFT +11257 847A 66 76 ROR VALUE+LO +11258 847C 88 DEY +11259 847D 10 F6 BPL ASLP2 +11260 847F 4C D1 43 JMP PUTVAL +11261 8482 +11262 ; -------- +11263 ; XPUSH +11264 ; -------- +11265 8482 ZXPUSH: +11266 8482 A5 65 lda ARG2+LO ; get me the address of the LTABLE +11267 8484 85 8C sta FPCL ; for munging with +11268 8486 A5 66 lda ARG2+HI ; this is page +11269 8488 20 A9 8F jsr SETPC ; get me actual page/bank +11270 848B 85 8D sta FPCH ; set page +11271 848D 84 8E sty FPCBNK ; and bank +11272 +11273 848F 20 88 92 jsr FETCHB ; this is hi part of counter +11274 8492 85 7B sta J+HI ; save it +11275 8494 20 F0 8F jsr NEXTFPC ; point to lo part +11276 8497 20 88 92 jsr FETCHB ; get it +11277 849A 85 7A sta J+LO ; thanx +11278 849C 05 7B ora J+HI ; check for zero elements left +11279 849E D0 03 bne ZXP0 ; yes, there is room at the inn +11280 +11281 84A0 4C 1F 44 jmp PREDF ; no room here! +11282 84A3 ZXP0: +11283 84A3 20 A5 90 jsr FP2SP ; set up to stash back in beginning of LTABLE +11284 84A6 A5 7B lda J+HI ; now the MSB +11285 84A8 85 7D sta K+HI ; and saved it +11286 84AA A5 7A lda J+LO ; save this +11287 84AC 85 7C sta K+LO ; save it +11288 ; +11289 ; now count this one and stash it into the table +11290 ; +11291 84AE D0 02 bne ZXP1 ; nope, dec okay +11292 84B0 C6 7B dec J+HI ; decrement MSB +11293 84B2 ZXP1: +11294 84B2 C6 7A dec J+LO ; and the LSB +11295 84B4 A5 7A lda J+LO ; LSB first +11296 84B6 20 67 92 jsr STASHB ; saved it +11297 84B9 20 80 90 jsr PREVSPC ; point to MSB +11298 84BC A5 7B lda J+HI ; get it + Tue Jun 13 1989 11:42 Page 169 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11299 84BE 20 67 92 jsr STASHB ; saved it +11300 ; +11301 ; finally, we can save the arg into the stack +11302 ; +11303 84C1 06 7C asl K+LO ; make a word offset (*2) +11304 84C3 26 7D rol K+HI ; pick up carry maybe +11305 84C5 A5 7C lda K+LO ; add in arg offset +11306 84C7 18 clc ; adding +11307 84C8 65 65 adc ARG2+LO ; figger offset +11308 84CA 85 8F sta SPCL ; this goes here for stashing +11309 84CC A5 7D lda K+HI ; now page +11310 84CE 65 66 adc ARG2+HI ; add in start of table +11311 84D0 20 A9 8F jsr SETPC ; get me memory page +11312 84D3 85 90 sta SPCH ; page +11313 84D5 84 91 sty SPCBNK ; and bank +11314 +11315 84D7 A5 64 lda ARG1+HI ; push MSB +11316 84D9 20 67 92 jsr STASHB ; saved +11317 84DC 20 D0 8F jsr NEXTSPC ; point to next one +11318 84DF A5 63 lda ARG1+LO ; and now LSB +11319 84E1 20 67 92 jsr STASHB ; into the stack +11320 84E4 4C 2B 44 jmp PREDS ; show we worked good +11321 ;--------- +11322 ; ZFSTACK +11323 ;--------- +11324 84E7 ZFSTACK: +11325 84E7 C6 62 dec NARGS ; how many args there? +11326 84E9 D0 0E bne ZFS1 ; flush ARG2 stack +11327 ; +11328 ; pop from system stack +11329 ; +11330 84EB A5 63 lda ARG1+LO ; just add number to system counter +11331 84ED 18 clc ; adding +11332 84EE 65 AF adc ZSP+LO ; added +11333 84F0 85 AF sta ZSP+LO ; and saved +11334 84F2 A5 64 lda ARG1+HI ; get hi part +11335 84F4 65 B0 adc ZSP+HI ; add in hi part +11336 84F6 85 B0 sta ZSP+HI ; save hi part +11337 84F8 60 rts +11338 84F9 ZFS1: +11339 84F9 A5 65 lda ARG2+LO ; get LTABLE we are interested in +11340 84FB 85 8C sta FPCL ; set up FPC first +11341 84FD A5 66 lda ARG2+HI ; and page +11342 84FF 20 A9 8F jsr SETPC ; tell me where +11343 8502 85 8D sta FPCH ; save me where +11344 8504 84 8E sty FPCBNK ; FPC all set +11345 8506 20 A5 90 jsr FP2SP ; have SPC point to stack too +11346 +11347 8509 20 88 92 jsr FETCHB ; get MSB of counter +11348 850C 85 7B sta J+HI ; save MSB +11349 850E 20 F0 8F jsr NEXTFPC ; point to LSB +11350 8511 20 88 92 jsr FETCHB ; get LSB +11351 8514 85 7A sta J+LO ; save LSB +11352 8516 +11353 8516 A5 7A lda J+LO ; get LSB back +11354 8518 18 clc ; get ready for add +11355 8519 65 63 adc ARG1+LO ; add how many to get rid off +11356 851B 85 7A sta J+LO ; save new counter +11357 851D A5 7B lda J+HI ; get MSB +11358 851F 65 64 adc ARG1+HI ; add MSB +11359 +11360 8521 20 67 92 jsr STASHB ; save Msb of new counter +11361 8524 20 D0 8F jsr NEXTSPC ; point to LSB +11362 8527 A5 7A lda J+LO ; get lsb +11363 8529 20 67 92 jsr STASHB ; okay, reset the counter +11364 852C 60 rts +11365 +11366 ; +11367 ; no mouse stuff yet +11368 ; +11369 852D ZMINFO: +11370 852D ZMLIMIT: +11371 852D 60 rts +11372 852E ZMENU: +11373 852E 4C 1F 44 jmp PREDF ; no menu stuff either + Tue Jun 13 1989 11:42 Page 170 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11374 +11375 8531 END +11376 +11377 8531 INCLUDE READ.ASM +11378 8531 STTL "--- READ HANDLER ---" +11379 PAGE + Tue Jun 13 1989 11:42 Page 171 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11380 ; ---- +11381 ; READ +11382 ; ---- +11383 ; READ LINE INTO TABLE [ARG1] ; PARSE INTO TABLE [ARG2] (IF ARG2 IS THERE) +11384 +11385 8531 00 MAXWORDS DB 0 ; maximum number of words in table +11386 8532 00 WORDCNT DB 0 ; how many words read so far +11387 8533 00 WORDSTART DB 0 ; table offset of word +11388 8534 SAVESPC DS 3 ; SPC that points to Word Count +11389 +11390 8537 ZREAD: +11391 8537 A5 64 lda ARG1+HI ; MAKE THE TABLE ADDRESSES +11392 8539 8D A9 6C sta RDTBL1+HI ; AND PLACE IT HERE TO USE +11393 853C A5 63 lda ARG1+LO +11394 853E 8D A8 6C sta RDTBL1+LO ; LSBS NEED NOT CHANGE +11395 +11396 8541 A9 00 lda #0 ; TURN OFF FLAGS +11397 8543 8D 85 6C sta PSVFLG ; FOR ZLEX +11398 8546 8D 86 6C sta VOCFLG +11399 +11400 8549 A6 62 ldx NARGS +11401 854B CA dex ; IF 2ND TBL ADDR 0 OR NOT THERE +11402 854C F0 14 beq ONLYRD ; JUST READ IN DON'T DO CONVERSION (X) +11403 854E A2 00 ldx #0 ; JIC +11404 8550 A5 66 lda ARG2+HI +11405 8552 05 65 ora ARG2+LO +11406 8554 F0 0C beq ONLYRD +11407 +11408 8556 A5 66 lda ARG2+HI +11409 8558 8D AB 6C sta RDTBL2+HI +11410 855B A5 65 lda ARG2+LO +11411 855D 8D AA 6C sta RDTBL2+LO +11412 +11413 8560 A2 01 ldx #1 ; 1 = DO IT ALL (X) +11414 8562 ONLYRD: +11415 8562 8E 91 5B stx RDFLAG ; CHECK AGAIN AFTER READ IN WHAT TO DO +11416 8565 20 24 59 jsr INPUT ; READ LINE; RETURN LENGTH IN [RDTBL1],1 +11417 +11418 8568 AD 91 5B lda RDFLAG ; FLAG (X) +11419 856B F0 03 beq RDEX ; IF INPUT ONLY, LEAVE NOW +11420 856D 20 7D 85 jsr DOREST +11421 8570 RDEX: +11422 8570 A9 F0 lda #$F0 ; RETURN NOW ONLY WANTED READ PART +11423 8572 8D 91 5B sta RDFLAG +11424 8575 AD 90 5B lda BRKCHR ; GET BREAK CHAR +11425 8578 A2 00 ldx #0 +11426 857A 4C CD 43 jmp PUTBYT ; RETURN IT +11427 ; +11428 ; IF TIMEOUT, [A]=0 SO WILL QUIT W/NO RESULTS +11429 ; +11430 857D DOREST: +11431 857D AD AB 6C lda RDTBL2+HI ; get max number of words +11432 8580 20 A9 8F jsr SETPC ; tell me memory and bank +11433 8583 85 8D sta FPCH ; save page +11434 8585 84 8E sty FPCBNK ; and bank +11435 8587 AD AA 6C lda RDTBL2+LO ; and for LSB +11436 858A 85 8C sta FPCL ; it is same +11437 858C 20 88 92 jsr FETCHB ; get max # of words in table +11438 858F F0 04 beq RDERR ; (5/14/85 - FORCE # WORDS TO +11439 8591 C9 3B cmp #59 ; BE BETWEEN 1 AND 59) +11440 8593 90 02 bcc RD0 +11441 8595 RDERR: +11442 8595 A9 3A lda #58 ; (5/16/86 - MAKE IT 58, 59 LOST) +11443 8597 RD0: +11444 8597 8D 31 85 sta MAXWORDS ; save max words +11445 859A A9 00 lda #0 ; start at 0 words +11446 859C 8D 32 85 sta WORDCNT ; save it +11447 859F 85 94 sta WRDLEN ; INIT # CHARS IN WORD COUNTER +11448 85A1 A9 02 lda #2 +11449 85A3 85 93 sta SOURCE ; INIT SOURCE TABLE PNTR +11450 ; +11451 ; now futz with destination table a little +11452 ; +11453 85A5 20 F0 8F jsr NEXTFPC ; now we point to # words read +11454 85A8 A5 8E lda FPCBNK ; and save this pointer + Tue Jun 13 1989 11:42 Page 172 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11455 85AA 8D 34 85 sta SAVESPC ; for stashing at the end +11456 85AD A5 8D lda FPCH +11457 85AF 8D 35 85 sta SAVESPC+1 +11458 85B2 A5 8C lda FPCL +11459 85B4 8D 36 85 sta SAVESPC+2 +11460 +11461 85B7 A9 04 lda #4 ; offset to end of first entry +11462 85B9 20 10 90 jsr ADDFPC ; and point to end of first entry +11463 85BC 20 A5 90 jsr FP2SP ; now put RDTBL2 into stash pointer +11464 ; +11465 ; now get source table +11466 ; +11467 85BF AD A9 6C lda RDTBL1+HI ; get page +11468 85C2 20 A9 8F jsr SETPC ; and tell me what mem page and bank +11469 85C5 85 8D sta FPCH ; set up fetch counter +11470 85C7 84 8E sty FPCBNK ; and bank +11471 85C9 AD A8 6C lda RDTBL1+LO ; and lo stays the same +11472 85CC 85 8C sta FPCL ; and save it +11473 85CE 20 F0 8F jsr NEXTFPC ; get # of chars in buffer +11474 85D1 20 88 92 jsr FETCHB ; and tell me about it +11475 85D4 85 92 sta LINLEN ; SAVE # CHARS IN LINE +11476 85D6 20 F0 8F jsr NEXTFPC ; now point to first char in line +11477 ; +11478 ; MAIN LOOP STARTS HERE +11479 ; +11480 85D9 READL: +11481 85D9 AD 31 85 lda MAXWORDS ; how we doin'? +11482 85DC CD 32 85 cmp WORDCNT ; see if we have maxxed out +11483 85DF 90 06 bcc RLEX ; all done, thank you +11484 +11485 85E1 A5 92 lda LINLEN +11486 85E3 05 94 ora WRDLEN ; OUT OF CHARS AND WORDS? +11487 85E5 D0 16 bne RL2 ; NOT YET +11488 85E7 RLEX: +11489 85E7 AD 34 85 lda SAVESPC ; now set SPC to point to # words +11490 85EA 85 91 sta SPCBNK ; read byte, as saved at the beginning +11491 85EC AD 35 85 lda SAVESPC+1 +11492 85EF 85 90 sta SPCH +11493 85F1 AD 36 85 lda SAVESPC+2 +11494 85F4 85 8F sta SPCL +11495 85F6 AD 32 85 lda WORDCNT ; get word count +11496 85F9 20 67 92 jsr STASHB ; and save it +11497 85FC 60 rts +11498 85FD RL2: +11499 85FD A5 94 lda WRDLEN ; GET WORD LENGTH +11500 85FF C9 09 cmp #9 ; 9 CHARS DONE? (EZIP) +11501 8601 90 03 bcc RL3 ; NO, KEEP GOING +11502 8603 20 34 87 jsr FLUSHW ; ELSE FLUSH REMAINDER OF WORD +11503 8606 RL3: +11504 8606 A5 94 lda WRDLEN ; GET WORD LENGTH AGAIN +11505 8608 D0 24 bne READL2 ; CONTINUE IF NOT FIRST CHAR +11506 ; +11507 ; START A NEW WORD +11508 ; +11509 860A A2 08 ldx #8 ; CLEAR Z-WORD INPUT BUFFER +11510 860C 9D BE 6C RLL: sta IN,X ; [A] = 0 +11511 860F CA dex +11512 8610 10 FA bpl RLL +11513 +11514 8612 A5 93 lda SOURCE ; STORE THE START POS OF THE WORD +11515 8614 8D 33 85 sta WORDSTART ; and save it for later +11516 8617 20 88 92 jsr FETCHB ; GET A CHAR FROM SOURCE BUFFER +11517 861A 20 65 87 jsr SIB ; IS IT A SELF-INSERTING BREAK? +11518 861D B0 2C bcs DOSIB ; YES IF CARRY WAS SET +11519 861F 20 59 87 jsr NORM ; IS IT A "NORMAL" BREAK? +11520 8622 90 0A bcc READL2 ; NO, CONTINUE +11521 8624 E6 93 inc SOURCE ; ELSE FLUSH THE STRANDED BREAK +11522 8626 20 F0 8F jsr NEXTFPC ; and point to next char +11523 8629 C6 92 dec LINLEN ; UPDATE # CHARS LEFT IN LINE +11524 862B 4C D9 85 jmp READL ; AND LOOP +11525 862E READL2: +11526 862E A5 92 lda LINLEN ; OUT OF CHARS YET? +11527 8630 F0 25 beq READL3 ; LOOKS THAT WAY +11528 8632 20 88 92 jsr FETCHB ; Grab the char +11529 8635 20 54 87 jsr BREAK ; IS IT A BREAK? + Tue Jun 13 1989 11:42 Page 173 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11530 8638 B0 1D bcs READL3 ; YES IF CARRY WAS SET +11531 863A A6 94 ldx WRDLEN ; ELSE STORE THE CHAR +11532 863C 9D BE 6C sta IN,X ; INTO THE INPUT BUFFER +11533 863F C6 92 dec LINLEN ; ONE LESS CHAR IN LINE +11534 8641 E6 94 inc WRDLEN ; ONE MORE IN WORD +11535 8643 E6 93 inc SOURCE ; and update next source +11536 8645 20 F0 8F jsr NEXTFPC ; POINT TO NEXT CHAR IN SOURCE +11537 8648 4C D9 85 jmp READL ; AND LOOP BACK +11538 ; +11539 ; handle self-inserting breaks +11540 864B DOSIB: +11541 864B 8D BE 6C sta IN ; put the break into 1st word slot +11542 864E C6 92 dec LINLEN ; one less char in line +11543 8650 E6 94 inc WRDLEN ; one more in word buffer +11544 8652 E6 93 inc SOURCE ; and update next source +11545 8654 20 F0 8F jsr NEXTFPC ; point to next source char +11546 8657 READL3: +11547 8657 A5 94 lda WRDLEN ; ANY CHARS IN WORD YET? +11548 8659 D0 03 bne READL31 ; yup, so deal with word +11549 865B 4C D9 85 jmp READL ; then go get next word +11550 865E READL31: +11551 865E 20 44 94 jsr CONZST ; CONVERT ASCII IN [IN] TO Z-STRING +11552 8661 20 95 87 jsr FINDW ; AND LOOK IT UP IN VOCABULARY +11553 +11554 8664 AD 33 85 lda WORDSTART ; get where it starts +11555 8667 20 67 92 jsr STASHB ; and save it +11556 866A 20 80 90 jsr PREVSPC ; step backwards to point to length +11557 866D A5 94 lda WRDLEN ; and get length +11558 866F 20 67 92 jsr STASHB ; and save it away +11559 8672 20 80 90 jsr PREVSPC ; and backwards to LSB of offset +11560 8675 A2 06 ldx #6 ; offset to point to end of next entry +11561 +11562 8677 EE 32 85 inc WORDCNT ; increment # words read +11563 +11564 867A AD 85 6C lda PSVFLG ; IF SHOULD PRESERVE WHAT'S IN +11565 867D F0 06 beq READL4 +11566 867F A5 77 lda VALUE+HI ; RDTBL2 AND NOT FOUND (VALUE = 0) +11567 8681 05 76 ora VALUE+LO +11568 8683 F0 0F beq READL5 ; JUST SKIP OVER +11569 8685 READL4: +11570 8685 A5 76 lda VALUE+LO ; GET LSB OF VOCAB ENTRY ADDRESS +11571 8687 20 67 92 jsr STASHB ; and stash it away +11572 868A 20 80 90 jsr PREVSPC ; point to MSB part +11573 868D A5 77 lda VALUE+HI ; ALSO STORE MSB IN 2ND SLOT +11574 868F 20 67 92 jsr STASHB ; and send it out +11575 8692 A2 07 ldx #7 ; offset to point to end of next entry +11576 8694 READL5: +11577 8694 A9 00 lda #0 +11578 8696 85 94 sta WRDLEN ; CLEAR # CHARS IN WORD +11579 8698 8A txa ; get offset +11580 8699 20 33 90 jsr ADDSPC ; and point to end of next entry +11581 869C 4C D9 85 jmp READL ; AND LOOP BACK +11582 +11583 ; --- +11584 ; LEX +11585 ; --- +11586 ; DO PARSE OF TBL1 INTO TBL2 (2ND HALF OF READ) +11587 +11588 869F ZLEX: +11589 869F A5 64 LDA ARG1+HI ; MAKE THE TABLE ADDRESSES +11590 86A1 8D A9 6C STA RDTBL1+HI ; AND PLACE IT HERE TO USE +11591 86A4 A5 63 LDA ARG1+LO +11592 86A6 8D A8 6C STA RDTBL1+LO ; LSBS NEED NOT CHANGE +11593 +11594 86A9 A5 66 LDA ARG2+HI +11595 86AB 8D AB 6C STA RDTBL2+HI +11596 86AE A5 65 LDA ARG2+LO +11597 86B0 8D AA 6C STA RDTBL2+LO +11598 +11599 86B3 C6 62 DEC NARGS +11600 86B5 C6 62 DEC NARGS +11601 86B7 F0 13 BEQ NORMLEX ; USE NORMAL VOCAB TBL +11602 +11603 86B9 A9 01 LDA #1 ; USE ARG3 VOCAB TBL +11604 86BB 8D 86 6C STA VOCFLG + Tue Jun 13 1989 11:42 Page 174 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11605 86BE A9 00 LDA #0 +11606 86C0 C6 62 DEC NARGS +11607 86C2 F0 02 BEQ NOSAVE ; ZERO UNFOUND WORDS +11608 86C4 A9 01 LDA #1 ; PRESERVE UNFOUND WORD SLOT FLAG +11609 86C6 8D 85 6C NOSAVE: STA PSVFLG +11610 86C9 4C D4 86 JMP DOLEX +11611 +11612 86CC A9 00 NORMLEX: LDA #0 +11613 86CE 8D 86 6C STA VOCFLG ; USE NORMAL VOCAB TBL +11614 86D1 8D 85 6C STA PSVFLG ; AND WILL BE NO PRESERVING +11615 +11616 86D4 4C 7D 85 DOLEX: JMP DOREST ; GO DO LEXICAL CONVERSION AND JUST RETURN +11617 +11618 +11619 ; ----- +11620 ; ZWSTR +11621 ; ----- +11622 ; CONVERT A WORD TO A ZWORD, PLACE IN ARG4 TBL +11623 86D7 ZWSTR: +11624 86D7 A5 64 lda ARG1+HI ; Make ARG1 be the FPC +11625 86D9 20 A9 8F jsr SETPC ; so get absolute mem bank/page +11626 86DC 84 8E sty FPCBNK ; save bank and +11627 86DE 85 8D sta FPCH ; page +11628 86E0 A5 63 lda ARG1+LO +11629 86E2 85 8C sta FPCL ; LSBS NEED NOT CHANGE +11630 ; +11631 ; (IGNORE WORD LENGTH CAUSE CHECK FOR BREAK CHAR (9 CHAR MAX)) +11632 ; +11633 86E4 A5 67 lda ARG3+LO ; ADD OFFSET INTO INBUF +11634 86E6 20 10 90 jsr ADDFPC ; add it to the FPC +11635 +11636 86E9 A5 6A lda ARG4+HI ; now fix the SPC too +11637 86EB 20 A9 8F jsr SETPC ; get me bank and page +11638 86EE 84 91 sty SPCBNK ; save bank +11639 86F0 85 90 sta SPCH ; save page +11640 86F2 A5 69 lda ARG4+LO +11641 86F4 85 8F sta SPCL ; LSB doesn't change +11642 ; +11643 ; START A NEW WORD +11644 ; +11645 86F6 A9 09 lda #9 +11646 86F8 85 92 sta LINLEN ; 1 WORD'S WORTH +11647 86FA A9 00 lda #0 +11648 86FC 85 94 sta WRDLEN +11649 +11650 86FE A2 08 ldx #8 ; CLEAR Z-WORD INPUT BUFFER +11651 8700 9D BE 6C WSTR1: sta IN,X ; [A] = 0 +11652 8703 CA dex +11653 8704 10 FA bpl WSTR1 +11654 ; +11655 ; THIS LOOP READS FROM INBUF TIL BREAK OR 9 CHARS READ +11656 ; +11657 8706 WSTR2: +11658 8706 20 88 92 jsr FETCHB ; grab the next char +11659 8709 20 54 87 jsr BREAK ; IS IT A BREAK? +11660 870C B0 0E bcs WSTR3 ; YES IF CARRY WAS SET +11661 870E A6 94 ldx WRDLEN ; ELSE STORE THE CHAR +11662 8710 9D BE 6C sta IN,X ; INTO THE INPUT BUFFER +11663 8713 E6 94 inc WRDLEN ; ONE MORE CHAR IN WORD +11664 8715 C6 92 dec LINLEN ; ONE LESS IN LINE +11665 8717 20 F0 8F jsr NEXTFPC ; point to next char +11666 871A D0 EA bne WSTR2 ; AND LOOP BACK TIL DONE +11667 871C WSTR3: +11668 871C A5 94 lda WRDLEN ; ANY CHARS IN WORD YET? +11669 871E F0 13 beq WOOPS ; APPARENTLY NOT, OOPS +11670 8720 20 44 94 jsr CONZST ; CONVERT ASCII IN [IN] TO Z-STRING +11671 +11672 8723 A2 00 ldx #0 ; MOVE FROM [OUT] TO RDTBL2 +11673 8725 BD C7 6C WSTR4: lda OUT,X +11674 8728 20 67 92 jsr STASHB ; and stash it into ZWORD table +11675 872B 20 D0 8F jsr NEXTSPC ; and point to next byte +11676 872E E8 inx +11677 872F E0 06 cpx #6 ; max 6 word table +11678 8731 D0 F2 bne WSTR4 ; not done yet +11679 8733 WOOPS: + Tue Jun 13 1989 11:42 Page 175 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11680 8733 60 rts +11681 +11682 ; ---------- +11683 ; FLUSH WORD +11684 ; ---------- +11685 +11686 8734 FLUSHW: +11687 8734 A5 92 lda LINLEN ; ANY CHARS LEFT IN LINE? +11688 8736 F0 14 beq FLEX ; NO, SCRAM +11689 8738 20 88 92 jsr FETCHB ; GRAB A CHAR +11690 873B 20 54 87 jsr BREAK ; IS IT A BREAK? +11691 873E B0 0C bcs FLEX ; EXIT IF SO +11692 8740 C6 92 dec LINLEN ; ELSE UPDATE CHAR COUNT +11693 8742 E6 94 inc WRDLEN ; AND WORD-CHAR COUNT +11694 8744 E6 93 inc SOURCE ; AND CHAR POINTER +11695 8746 20 F0 8F jsr NEXTFPC ; and FPC pointer too +11696 8749 4C 34 87 jmp FLUSHW ; AND LOOP BACK (ALWAYS) +11697 874C FLEX: +11698 874C 60 rts +11699 +11700 +11701 ; --------------------------------- +11702 ; IS CHAR IN [A] ANY TYPE OF BREAK? +11703 ; --------------------------------- +11704 ; ------------------ +11705 ; NORMAL BREAK CHARS +11706 ; ------------------ +11707 +11708 874D 21 3F 2C 2E BRKTBL: DB '!?,.' ; IN ORDER OF +11709 8751 0D DB $0D ; ASCII ENDING FREQUENCY +11710 8752 20 DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED +11711 8753 00 DB 0 ; ZERO ADDED FOR ZWSTR (X) +11712 0007 NBRKS EQU $-BRKTBL ; # NORMAL BREAKS +11713 +11714 8754 20 65 87 BREAK: JSR SIB ; CHECK FOR A SIB FIRST +11715 8757 B0 3A BCS FBRK ; EXIT NOW IF MATCHED +11716 +11717 ; ELSE FALL THROUGH ... +11718 +11719 +11720 ; -------------------------------- +11721 ; IS CHAR IN [A] A "NORMAL" BREAK? +11722 ; -------------------------------- +11723 +11724 8759 A2 06 NORM: LDX #NBRKS-1 ; NUMBER OF "NORMAL" BREAKS +11725 875B DD 4D 87 NBL: CMP BRKTBL,X ; MATCHED? +11726 875E F0 33 BEQ FBRK ; YES, EXIT +11727 8760 CA DEX +11728 8761 10 F8 BPL NBL ; NO, KEEP LOOKING +11729 8763 18 CLC ; NO MATCH, CLEAR CARRY +11730 8764 60 RTS ; AND RETURN +11731 +11732 +11733 ; --------------------- +11734 ; IS CHAR IN [A] A SIB? +11735 ; --------------------- +11736 +11737 8765 85 AC SIB: STA IOCHAR ; SAVE TEST CHAR +11738 8767 A5 54 lda VOCAB+ABANK ; get bank +11739 8769 85 8B sta MPCBNK ; and save it +11740 876B A5 53 lda VOCAB+HI ; and hi part +11741 876D 85 8A sta MPCPNT+HI ; and save it +11742 876F AD 08 96 lda ZBEGIN+ZVOCAB+0 ; GET 1ST BYTE IN VOCAB TABLE +11743 8772 AC 09 96 LDY ZBEGIN+ZVOCAB+1 +11744 8775 85 87 STA MPCM +11745 8777 84 86 STY MPCL +11746 8779 A9 00 LDA #0 +11747 877B 85 88 STA MPCH ; now everything is set up +11748 877D 20 3B 92 JSR GETBYT ; HAS # SIBS +11749 8780 85 7A STA J ; USE AS AN INDEX +11750 8782 20 3B 92 SBL: JSR GETBYT ; GET NEXT SIB +11751 8785 C5 AC CMP IOCHAR ; MATCHED? +11752 8787 F0 08 BEQ FBRK0 ; YES, REPORT IT +11753 8789 C6 7A DEC J +11754 878B D0 F5 BNE SBL ; ELSE KEEP LOOPING + Tue Jun 13 1989 11:42 Page 176 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11755 878D A5 AC LDA IOCHAR +11756 878F 18 CLC ; NO MATCH, SO +11757 8790 60 RTS ; EXIT WITH CARRY CLEAR +11758 8791 A5 AC FBRK0: LDA IOCHAR +11759 8793 38 FBRK: SEC ; EXIT WITH CARRY SET +11760 8794 60 RTS ; IF MATCHED WITH A BREAK CHAR +11761 +11762 +11763 ; ----------------- +11764 ; VOCABULARY SEARCH +11765 ; ----------------- +11766 ; ENTRY: 6-BYTE TARGET Z-WORD IN [OUT] +11767 ; EXIT: VIRTUAL ENTRY ADDRESS IN [VALUE] IF FOUND ; +11768 ; OTHERWISE [VALUE] = 0 +11769 +11770 0078 VWLEN EQU I ; ********** +11771 007B VWCUR EQU J+HI +11772 +11773 8795 FINDW: +11774 8795 AD 86 6C lda VOCFLG ; USE WHAT VOCAB TBL? +11775 8798 F0 07 beq FWL2 ; NORMAL +11776 879A A5 68 lda ARG3+HI ; IF ALTERNATE VOCTBL +11777 879C A4 67 ldy ARG3+LO ; IT'S ADDR IS IN ARG3 +11778 879E 4C C8 87 jmp FWL3 +11779 87A1 FWL2: +11780 87A1 AD BD 6C lda DIDVTBL ; have we done default vocab table? +11781 87A4 F0 17 beq FWLNEW ; nope, so do it the first time +11782 87A6 A2 02 ldx #2 ; restore pointers +11783 87A8 FWRSTL: +11784 87A8 BD B4 6C lda VOCMPC,X ; get it +11785 87AB 95 86 sta MPC,X ; save it +11786 87AD BD B7 6C lda VCESVE,X ; save VOCEND too +11787 87B0 95 B3 sta VOCEND,X ; okay, we have +11788 87B2 BD BA 6C lda VWLSVE,X ; and starting length +11789 87B5 95 78 sta VWLEN,X ; we have +11790 87B7 CA dex ; count +11791 87B8 10 EE bpl FWRSTL ; okay, next one +11792 87BA 4C 9E 88 jmp FWLOOP ; and go do it +11793 87BD FWLNEW: +11794 87BD A9 FF lda #$FF ; show we are doing default table +11795 87BF 8D BD 6C sta DIDVTBL ; we shall +11796 +11797 87C2 AD 08 96 lda ZBEGIN+ZVOCAB ; GET VIRTUAL ADDR OF VOCAB TBL +11798 87C5 AC 09 96 ldy ZBEGIN+ZVOCAB+1 +11799 87C8 FWL3: +11800 87C8 85 87 STA MPCM +11801 87CA 84 86 STY MPCL +11802 87CC A9 00 LDA #0 +11803 87CE 85 88 STA MPCH +11804 87D0 20 B2 90 JSR VLDMPC ; SET TO NEW PAGE +11805 87D3 20 3B 92 JSR GETBYT ; GET # SIBS +11806 87D6 18 CLC +11807 87D7 65 86 ADC MPCL ; GET ACTUAL BASE ADDR OF VOCAB ENTRIES +11808 87D9 85 86 STA MPCL +11809 87DB 90 02 BCC FWL0 +11810 87DD E6 87 INC MPCM +11811 87DF 20 B2 90 FWL0: JSR VLDMPC ; SET TO NEW PAGE +11812 87E2 20 3B 92 JSR GETBYT ; GET # BYTES PER ENTRY (AND MOVE TO NEXT BYTE) +11813 87E5 85 95 STA ESIZE ; SAVE IT HERE +11814 87E7 85 78 STA VWLEN+0 ; AND HERE +11815 87E9 A9 00 LDA #0 ; CLEAR REST OF COUNTER +11816 87EB 85 79 STA VWLEN+1 +11817 87ED 85 7A STA VWLEN+2 +11818 +11819 87EF 20 3B 92 JSR GETBYT ; GET # OF ENTRIES IN TBL (MSB) +11820 87F2 8D AD 6C STA NENTS+HI ; AND STUFF IT IN [NENTS] +11821 87F5 20 3B 92 JSR GETBYT ; DON'T FORGET THE LSB! +11822 87F8 8D AC 6C STA NENTS+LO +11823 87FB AD AD 6C LDA NENTS+HI +11824 87FE 10 03 BPL SORTED +11825 8800 4C 57 89 JMP UNSORTED ; VOCAB LIST IS UNSORTED, HANDLE DIFFERENTLY +11826 8803 SORTED: +11827 8803 A9 00 LDA #0 ; FIND SIZE OF VAOCAB TBL +11828 8805 85 B3 STA VOCEND ; TO LOCATE THE END OF IT +11829 8807 85 B4 STA VOCEND+1 + Tue Jun 13 1989 11:42 Page 177 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11830 8809 85 B5 STA VOCEND+2 +11831 880B A6 95 LDX ESIZE +11832 880D FWL1: +11833 880D 18 CLC +11834 880E A5 B3 LDA VOCEND ; (# OF ENTRIES) * (ENTRY SIZE) +11835 8810 6D AC 6C ADC NENTS+LO +11836 8813 85 B3 STA VOCEND +11837 8815 A5 B4 LDA VOCEND+1 +11838 8817 6D AD 6C ADC NENTS+HI +11839 881A 85 B4 STA VOCEND+1 +11840 881C 90 02 bcc FWL11 +11841 881E E6 B5 inc VOCEND+2 +11842 8820 FWL11: +11843 8820 CA DEX +11844 8821 D0 EA BNE FWL1 +11845 +11846 8823 18 CLC +11847 8824 A5 B3 LDA VOCEND ; AND ADD LENGTH TO START OF TBL +11848 8826 65 86 ADC MPCL ; TO GET END OF TBL +11849 8828 85 B3 STA VOCEND +11850 882A A5 B4 LDA VOCEND+1 +11851 882C 65 87 ADC MPCM +11852 882E 85 B4 STA VOCEND+1 +11853 8830 A5 B5 LDA VOCEND+2 +11854 8832 65 88 ADC MPCH +11855 8834 85 B5 STA VOCEND+2 ; TO SAVE FOR TESTING IF PAST END +11856 +11857 8836 A5 B3 LDA VOCEND ; SUBTRACT [ESIZE] SO THAT +11858 8838 38 SEC ; [VOCEND] POINTS TO REAL LAST ENTRY +11859 8839 E5 95 SBC ESIZE +11860 883B 85 B3 STA VOCEND +11861 883D A5 B4 LDA VOCEND+1 +11862 883F E9 00 SBC #0 +11863 8841 85 B4 STA VOCEND+1 +11864 ; +11865 ; BEGIN THE SEARCH! [MPC] NOW POINTS TO 1ST ENTRY +11866 ; +11867 8843 4E AD 6C LSR NENTS+HI ; 2 ALIGN # OF ENTRIES +11868 8846 6E AC 6C ROR NENTS+LO ; 2 point to middle of table +11869 8849 06 78 FWCALC: ASL VWLEN+0 ; CALCULATE INITIAL OFFSET FOR SEARCH +11870 884B 26 79 ROL VWLEN+1 +11871 884D 26 7A ROL VWLEN+2 +11872 884F 4E AD 6C LSR NENTS+HI +11873 8852 6E AC 6C ROR NENTS+LO +11874 8855 D0 F2 BNE FWCALC +11875 +11876 8857 18 CLC ; ADD 1ST OFFSET INTO START OF VOCABULARL +11877 8858 A5 86 LDA MPCL ; WHICH IS CURRENTLY IN MPC +11878 885A 65 78 ADC VWLEN+0 +11879 885C 85 86 STA MPCL +11880 885E A5 87 LDA MPCM +11881 8860 65 79 ADC VWLEN+1 +11882 8862 85 87 STA MPCM +11883 8864 A5 88 LDA MPCH +11884 8866 65 7A ADC VWLEN+2 +11885 8868 85 88 STA MPCH +11886 +11887 886A 38 SEC ; AVOID FENCE-POST BUG FOR +11888 886B A5 86 LDA MPCL ; EXACT-POWER-OF-2 TBL (DUNCAN) +11889 886D E5 95 SBC ESIZE +11890 886F 85 86 STA MPCL +11891 8871 B0 0F BCS FWSAVE +11892 8873 A5 87 LDA MPCM +11893 8875 38 SEC +11894 8876 E9 01 SBC #1 +11895 8878 85 87 STA MPCM +11896 887A B0 06 BCS FWSAVE +11897 887C A5 88 LDA MPCH +11898 887E E9 00 SBC #0 +11899 8880 85 88 STA MPCH +11900 8882 FWSAVE: +11901 8882 AD BD 6C lda DIDVTBL ; are we installing default table? +11902 8885 10 17 bpl FWLOOP ; already have? +11903 8887 A2 02 ldx #2 ; save MPC +11904 8889 8E BD 6C stx DIDVTBL ; show we have saved it + Tue Jun 13 1989 11:42 Page 178 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11905 888C FWSVL: +11906 888C B5 86 lda MPC,X ; get it +11907 888E 9D B4 6C sta VOCMPC,X ; save it +11908 8891 B5 B3 lda VOCEND,X ; save VOCEND too +11909 8893 9D B7 6C sta VCESVE,X ; okay, we have +11910 8896 B5 78 lda VWLEN,X ; and starting length +11911 8898 9D BA 6C sta VWLSVE,X ; we have +11912 889B CA dex ; count +11913 889C 10 EE bpl FWSVL ; okay, next one +11914 889E FWLOOP: +11915 889E 46 7A lsr VWLEN+2 ; SET FOR NEXT OFFSET, +11916 88A0 66 79 ror VWLEN+1 ; WHICH IS HALF THIS ONE +11917 88A2 66 78 ror VWLEN+0 +11918 +11919 88A4 A5 86 lda MPCL ; HOLD START ADDR, MPC WILL BE A MESS +11920 88A6 85 7B sta VWCUR+0 +11921 88A8 A5 87 lda MPCM +11922 88AA 85 7C sta VWCUR+1 +11923 88AC A5 88 lda MPCH +11924 88AE 85 7D sta VWCUR+2 +11925 +11926 88B0 20 B2 90 jsr VLDMPC ; SET TO NEW PAGE +11927 88B3 20 3B 92 jsr GETBYT ; GET 1ST BYTE OF ENTRY +11928 88B6 CD C7 6C cmp OUT ; MATCH 1ST BYTE OF TARGET? +11929 88B9 90 34 bcc WNEXT ; LESS +11930 88BB D0 66 bne FWPREV ; GREATER +11931 88BD 20 3B 92 jsr GETBYT +11932 88C0 CD C8 6C cmp OUT+1 ; 2ND BYTE MATCHED? +11933 88C3 90 2A bcc WNEXT +11934 88C5 D0 5C bne FWPREV ; NOPE +11935 88C7 20 3B 92 jsr GETBYT +11936 88CA CD C9 6C cmp OUT+2 ; 3RD BYTE? +11937 88CD 90 20 bcc WNEXT +11938 88CF D0 52 bne FWPREV ; SORRY ... +11939 88D1 20 3B 92 jsr GETBYT +11940 88D4 CD CA 6C cmp OUT+3 ; 4TH BYTE +11941 88D7 90 16 bcc WNEXT +11942 88D9 D0 48 BNE FWPREV +11943 88DB 20 3B 92 JSR GETBYT +11944 88DE CD CB 6C CMP OUT+4 ; 5TH BYTE? +11945 88E1 90 0C BCC WNEXT +11946 88E3 D0 3E BNE FWPREV ; SORRY ... +11947 88E5 20 3B 92 JSR GETBYT +11948 88E8 CD CC 6C CMP OUT+5 ; LAST BYTE? +11949 88EB F0 5A BEQ FWSUCC ; FOUND IT! +11950 88ED B0 34 BCS FWPREV ; ELSE BACK UP ... +11951 88EF WNEXT: +11952 88EF A5 7B LDA VWCUR+0 ; TO MOVE UP, JUST ADD +11953 88F1 18 CLC ; OFFSET FROM START OF THIS +11954 88F2 65 78 ADC VWLEN+0 ; ENTRY +11955 88F4 85 86 STA MPCL +11956 88F6 A5 7C LDA VWCUR+1 +11957 88F8 65 79 ADC VWLEN+1 +11958 88FA B0 18 BCS WNXT2 ; SAVES CODE (?) +11959 +11960 88FC 85 87 STA MPCM +11961 88FE A9 00 LDA #0 +11962 8900 85 88 STA MPCH +11963 8902 WNXT0: +11964 8902 A5 87 LDA MPCM ; GONE PAST END? +11965 8904 C5 B4 CMP VOCEND+1 +11966 8906 F0 04 BEQ WNXT1 ; MAYBE +11967 8908 B0 0A BCS WNXT2 ; YES +11968 890A 90 2A BCC FWMORE ; NO +11969 890C WNXT1: +11970 890C A5 86 LDA MPCL +11971 890E C5 B3 CMP VOCEND +11972 8910 90 24 BCC FWMORE ; NO +11973 8912 F0 22 BEQ FWMORE ; NO, EQUAL +11974 8914 WNXT2: +11975 8914 A5 B3 LDA VOCEND ; YES, SO POINT TO END OF TBL +11976 8916 85 86 STA MPCL +11977 8918 A5 B4 LDA VOCEND+1 +11978 891A 85 87 STA MPCM +11979 891C A5 B5 LDA VOCEND+2 + Tue Jun 13 1989 11:42 Page 179 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11980 891E 85 88 STA MPCH +11981 8920 4C 36 89 JMP FWMORE +11982 8923 FWPREV: +11983 8923 A5 7B LDA VWCUR+0 ; TO MOVE DOWN, JUST SUBTRACT +11984 8925 38 SEC ; OFFSET FROM START OF THIS +11985 8926 E5 78 SBC VWLEN+0 ; ENTRY +11986 8928 85 86 STA MPCL +11987 892A A5 7C LDA VWCUR+1 +11988 892C E5 79 SBC VWLEN+1 +11989 892E 85 87 STA MPCM +11990 8930 A5 7D LDA VWCUR+2 +11991 8932 E5 7A SBC VWLEN+2 +11992 8934 85 88 STA MPCH +11993 8936 FWMORE: +11994 8936 A5 7A LDA VWLEN+2 ; IF OFFSET >GE< 1 WORD, CONTINUE +11995 8938 D0 0A BNE FWM1 +11996 893A A5 79 LDA VWLEN+1 +11997 893C D0 06 BNE FWM1 +11998 893E A5 78 LDA VWLEN+0 +11999 8940 C5 95 CMP ESIZE +12000 8942 90 0C BCC FWFAIL +12001 8944 FWM1: +12002 8944 4C 9E 88 JMP FWLOOP ; AND TRY AGAIN +12003 +12004 8947 A5 7B FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD +12005 8949 85 76 STA VALUE+LO +12006 894B A5 7C LDA VWCUR+1 +12007 894D 85 77 STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY +12008 894F 60 RTS ; WORD VALUE RETURNABLE +12009 8950 FWFAIL: +12010 8950 A9 00 LDA #0 ; NOT FOUND +12011 8952 85 76 STA VALUE+LO +12012 8954 85 77 STA VALUE+HI +12013 8956 60 RTS ; THEN RETURN WITH [VALUE] = 0 +12014 ; +12015 ; DO UNSORTED SEARCH ON VOCAB TBL IN MPC +12016 ; +12017 8957 UNSORTED: +12018 8957 A9 FF LDA #$FF ; 2'S COMPLEMENT LENGTH +12019 8959 4D AD 6C EOR NENTS+HI ; TO GET REAL LENGTH +12020 895C 8D AD 6C STA NENTS+HI ; WAS NEGATIVE TO SIGNIFY +12021 895F A9 FF LDA #$FF ; UNSORTED VOCAB TBL +12022 8961 4D AC 6C EOR NENTS+LO +12023 8964 8D AC 6C STA NENTS+LO +12024 8967 EE AC 6C INC NENTS+LO ; 2'S CMPL +12025 896A D0 03 BNE UNSRT0 +12026 896C EE AD 6C INC NENTS+HI +12027 896F UNSRT0: +12028 896F A5 86 LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS +12029 8971 85 7B STA VWCUR+0 +12030 8973 A5 87 LDA MPCM +12031 8975 85 7C STA VWCUR+1 +12032 8977 A5 88 LDA MPCH +12033 8979 85 7D STA VWCUR+2 +12034 +12035 897B 20 3B 92 JSR GETBYT ; GET 1ST BYTE OF ENTRY +12036 897E CD C7 6C CMP OUT ; MATCH 1ST BYTE OF TARGET? +12037 8981 D0 28 BNE FNEXT ; LESS +12038 8983 20 3B 92 JSR GETBYT +12039 8986 CD C8 6C CMP OUT+1 ; 2ND BYTE MATCHED? +12040 8989 D0 20 BNE FNEXT +12041 898B 20 3B 92 JSR GETBYT +12042 898E CD C9 6C CMP OUT+2 ; 3RD BYTE? +12043 8991 D0 18 BNE FNEXT +12044 8993 20 3B 92 JSR GETBYT +12045 8996 CD CA 6C CMP OUT+3 ; 4TH BYTE +12046 8999 D0 10 BNE FNEXT +12047 899B 20 3B 92 JSR GETBYT +12048 899E CD CB 6C CMP OUT+4 ; 5TH BYTE? +12049 89A1 D0 08 BNE FNEXT +12050 89A3 20 3B 92 JSR GETBYT +12051 89A6 CD CC 6C CMP OUT+5 ; LAST BYTE? +12052 89A9 F0 9C BEQ FWSUCC ; FOUND IT! +12053 +12054 89AB A5 7B FNEXT: LDA VWCUR+LO ; TO MOVE UP, JUST ADD + Tue Jun 13 1989 11:42 Page 180 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +12055 89AD 18 CLC ; OFFSET FROM START OF THIS +12056 89AE 65 95 ADC ESIZE ; ENTRY +12057 89B0 85 86 STA MPCL +12058 89B2 90 0D BCC FNEXT0 +12059 +12060 89B4 A5 7C LDA VWCUR+HI ; PICK UP CARRY +12061 89B6 69 00 ADC #0 +12062 89B8 85 87 STA MPCM +12063 89BA A9 00 LDA #0 +12064 89BC 85 88 STA MPCH +12065 89BE 20 B2 90 JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE +12066 +12067 89C1 CE AC 6C FNEXT0: DEC NENTS+LO ; CHECKED ALL ENTRIES? +12068 89C4 D0 A9 BNE UNSRT0 +12069 89C6 AD AD 6C LDA NENTS+HI +12070 89C9 F0 85 BEQ FWFAIL ; GO INDICATE NO FIND +12071 89CB CE AD 6C DEC NENTS+HI ; OR DO NEXT 256 ENTRIES +12072 89CE 4C 6F 89 JMP UNSRT0 +12073 +12074 89D1 END +12075 +12076 89D1 INCLUDE ZSAVRES.ASM +12077 +12078 89D1 STTL "--- ZIP SAVE AND RESTORE ROUTINES ---" +12079 PAGE + Tue Jun 13 1989 11:42 Page 181 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12080 ; ----------------------------- +12081 ; SET UP SAVE & RESTORE SCREENS +12082 ; ----------------------------- +12083 89D1 SAVRES: +12084 89D1 20 E9 54 jsr ZCRLF ; CLEAR THE LINE BUFFER +12085 89D4 A9 00 lda #0 +12086 89D6 85 AA sta SCRIPT ; DISABLE SCRIPTING +12087 89D8 AD 54 C0 lda PAGE2SW+MAIN ; just do this for the heck of it +12088 89DB AD 83 C0 lda BNK2SET ; this stuff too +12089 89DE AD 83 C0 lda BNK2SET +12090 +12091 89E1 60 rts +12092 +12093 ; ----------------------------- +12094 ; SAVE & RESTORE STRINGS +12095 ; ----------------------------- +12096 89E2 59 45 53 YES: DB "YES" +12097 89E5 0D DB EOL +12098 0004 YESL EQU $-YES +12099 89E6 4E 4F NO: DB "NO" +12100 89E8 0D DB EOL +12101 0003 NOL EQU $-NO +12102 +12103 89E9 0D NAMEQ: db EOL +12104 89EA 49 6E 73 65 72 db "Insert save disk and enter " + 89EF 74 20 73 61 76 + 89F4 65 20 64 69 73 + 89F9 6B 20 61 6E 64 + 89FE 20 65 6E 74 65 + 8A03 72 20 +12105 8A05 66 75 6C 6C 20 db "full pathname of save file: " + 8A0A 70 61 74 68 6E + 8A0F 61 6D 65 20 6F + 8A14 66 20 73 61 76 + 8A19 65 20 66 69 6C + 8A1E 65 3A 20 +12106 8A21 0D db EOL +12107 8A22 48 69 74 20 27 db "Hit '?' key to get a list of online volumes." + 8A27 3F 27 20 6B 65 + 8A2C 79 20 74 6F 20 + 8A31 67 65 74 20 61 + 8A36 20 6C 69 73 74 + 8A3B 20 6F 66 20 6F + 8A40 6E 6C 69 6E 65 + 8A45 20 76 6F 6C 75 + 8A4A 6D 65 73 2E +12108 8A4E 0D db EOL +12109 8A4F 43 75 72 72 65 db "Current pathname is:", + 8A54 6E 74 20 70 61 + 8A59 74 68 6E 61 6D + 8A5E 65 20 69 73 3A + 8A63 00 +12110 8A64 0D db EOL +12111 007C NAMEQL EQU $-NAMEQ +12112 SNDATA: ; show start of name and length +12113 8A65 00 SNAMEL: db 0 ; place to save length of name +12114 8A66 SAVENAME: ds 64+15 ; save plenty of room for max name +12115 +12116 8AB5 0D 46 69 6C 65 DELQ: db EOL,"File exists, delete it (Yes/No)? " + 8ABA 20 65 78 69 73 + 8ABF 74 73 2C 20 64 + 8AC4 65 6C 65 74 65 + 8AC9 20 69 74 20 28 + 8ACE 59 65 73 2F 4E + 8AD3 6F 29 3F 20 +12117 0023 DELQL EQU $-DELQ+1 ; include this following EOL +12118 8AD7 0D 50 6C 65 61 RETQ: db EOL,"Please hit [RETURN]",EOL + 8ADC 73 65 20 68 69 + 8AE1 74 20 5B 52 45 + 8AE6 54 55 52 4E 5D + 8AEB 0D +12119 0015 RETQL EQU $-RETQ +12120 8AEC 0D 4E 61 6D 65 PREFIX_ERR: db EOL,"Name must have prefix, " + 8AF1 20 6D 75 73 74 + 8AF6 20 68 61 76 65 + Tue Jun 13 1989 11:42 Page 182 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + + 8AFB 20 70 72 65 66 + 8B00 69 78 2C 20 +12121 8B04 69 2E 65 2E 3A db "i.e.: /DISKNAME/FILENAME",EOL + 8B09 20 2F 44 49 53 + 8B0E 4B 4E 41 4D 45 + 8B13 2F 46 49 4C 45 + 8B18 4E 41 4D 45 0D +12122 0031 PREFIX_ERRL EQU $-PREFIX_ERR +12123 +12124 002D MAX_SAVENAME EQU 45 ; max # of chars allowed in save name +12125 +12126 ; ----------------------------- +12127 ; SAVE/RESTORE Parameter Blocks +12128 ; ----------------------------- +12129 8B1D CREATE_PB: +12130 8B1D 07 db 7 ; 7 parameters +12131 8B1E 658A dw SNDATA ; pointer to name +12132 8B20 C3 db $C3 ; full access to file +12133 8B21 06 db $06 ; BIN file type +12134 8B22 0000 dw 0 ; no aux data +12135 8B24 01 db $01 ; standard file +12136 8B25 0000 dw 0 ; create date +12137 8B27 0000 dw 0 +12138 ; creation time +12139 8B29 SETEOF_PB: +12140 8B29 02 db 2 ; 1 parameter +12141 8B2A 00 db 0 ; refnum +12142 8B2B 00 00 00 db 0,0,0 ; set to zero spot to clear it out +12143 8B2E OPEN_SV: +12144 8B2E 03 db 3 ; 3 parameters +12145 8B2F 658A dw SNDATA ; name +12146 8B31 0011 dw GAME1FIO ; file buffer +12147 8B33 00 db 0 ; ref num +12148 8B34 CLOSE_PB: +12149 8B34 01 db 1 ; only one parm +12150 8B35 00 db 0 ; the refnum +12151 8B36 WRITE_SV: +12152 8B36 04 db 4 ; parm count +12153 8B37 00 db 0 ; refnum +12154 8B38 0008 dw IOBUFF ; data is always here +12155 8B3A 0002 dw 512 ; 1 page worth +12156 8B3C 0000 dw 0 ; how many actually went +12157 +12158 ; get the save file name. If user hits the ESC key, then abort the +12159 ; save by return with the carry set. +12160 ; +12161 8B3E GET_SNAME: +12162 8B3E 20 C1 8C jsr CLOSE_GAME ; close the game files +12163 8B41 20 99 4C jsr SWAP2INFOW ; goto information window +12164 8B44 GTSN0: +12165 8B44 DLINE NAMEQ ; ask about name +12166 8B44 A2 E9 ldx #NAMEQ ; get other part of string +12168 [01] IFMA 2 ; check to see if length passed in +12169 ldy ; then just fetch it +12170 [01] ELSE +12171 8B48 A0 7C ldy #NAMEQL ; get length of string +12172 [00] ENDIF +12173 8B4A 20 5B 4C jsr DLINE ; print the string +12174 8B4D .MACEND +12175 8B4D AD 65 8A lda SNAMEL ; is there a name yet? +12176 8B50 F0 0A beq GTSN00 ; nope +12177 8B52 DLINE SAVENAME,SNAMEL ; show current name of file +12178 8B52 A2 66 ldx #SAVENAME ; get other part of string +12180 [01] IFMA 2 ; check to see if length passed in +12181 8B56 AC 65 8A ldy SNAMEL ; then just fetch it +12182 [01] ELSE +12183 ldy #SAVENAMEL ; get length of string +12184 [00] ENDIF +12185 8B59 20 5B 4C jsr DLINE ; print the string +12186 8B5C .MACEND +12187 8B5C GTSN00: +12188 8B5C A9 00 lda #0 ; clear line count +12189 8B5E 8D 35 8B sta CLOSE_PB+CL_REFNUM ; clear this too + Tue Jun 13 1989 11:42 Page 183 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12190 8B61 AE 65 8A ldx SNAMEL ; get length +12191 8B64 86 A9 stx CHRCNT ; okay +12192 8B66 AC 65 8A ldy SNAMEL ; point to copy +12193 8B69 88 dey ; one less +12194 8B6A GCOPY: +12195 8B6A BD 65 8A lda SNAMEL,X ; get char +12196 8B6D 99 00 02 sta LBUFF,Y ; save it +12197 8B70 CA dex ; point to previous one +12198 8B71 88 dey ; previous pointer +12199 8B72 10 F6 bpl GCOPY ; copy until length byte +12200 8B74 GNAME: +12201 8B74 20 20 51 jsr GETKEY ; WAIT FOR A KEY +12202 8B77 C9 0D cmp #EOL ; IF [RETURN], +12203 8B79 F0 63 beq GOTNAME ; got the name +12204 8B7B C9 1B cmp #ESCAPE ; hit escape key? +12205 8B7D 38 sec ; just in case it does exit +12206 8B7E D0 03 bne GNM2 +12207 8B80 4C 22 8C jmp GNX ; all done then +12208 8B83 GNM2: +12209 8B83 C9 08 cmp #BACKSPACE ; erasing things? +12210 8B85 D0 15 bne GNM1 ; nope +12211 +12212 8B87 A6 A9 ldx CHRCNT ; make sure there are chars there +12213 8B89 D0 06 bne GNMBP ; ayyup, do delete +12214 8B8B GNMBAD: +12215 8B8B 20 B3 4E jsr BEEP ; no room for delete +12216 8B8E 4C 74 8B jmp GNAME ; okay +12217 8B91 GNMBP: +12218 8B91 CA dex ; point down one +12219 8B92 86 A9 stx CHRCNT ; count one down +12220 8B94 BD 00 02 lda LBUFF,X ; get char to delete +12221 8B97 AA tax ; show in [X] +12222 8B98 A9 08 lda #BACKSPACE ; and doing a backspace +12223 8B9A D0 39 bne GNMSHOW ; okay, delete char on screen +12224 8B9C GNM1: +12225 8B9C C9 2F cmp #'/' ; slash is the only good non-numeric char +12226 8B9E F0 2A beq GNMGOOD ; fine, use it +12227 8BA0 C9 2E cmp #'.' ; well, maybe a . too +12228 8BA2 F0 26 beq GNMGOOD ; fine, here it is +12229 8BA4 C9 3F cmp #VOLCHAR ; does user want list of volumes? +12230 8BA6 D0 0A bne GNM1x ; nope +12231 +12232 8BA8 A9 00 lda #0 ; clear out current name +12233 8BAA 85 A9 sta CHRCNT ; okay, we did +12234 8BAC 20 4D 4B jsr LISTVOLS ; show them +12235 8BAF 4C 44 8B jmp GTSN0 ; start over, kind of +12236 8BB2 GNM1x: +12237 8BB2 C9 30 cmp #'0' ; is it a number +12238 8BB4 90 D5 bcc GNMBAD ; nope +12239 8BB6 C9 3A cmp #'9'+1 ; well? +12240 8BB8 90 10 bcc GNMGOOD ; yup +12241 8BBA C9 7B cmp #'z'+1 ; make sure it is alpha numeric +12242 8BBC B0 CD bcs GNMBAD ; nope +12243 8BBE C9 41 cmp #'A' ; well? +12244 8BC0 90 C9 bcc GNMBAD ; nope +12245 8BC2 C9 61 cmp #'a' ; little char? +12246 8BC4 B0 04 bcs GNMGOOD ; yup +12247 8BC6 C9 5B cmp #'Z'+1 ; big char +12248 8BC8 B0 C1 bcs GNMBAD ; nope +12249 8BCA GNMGOOD: +12250 8BCA A6 A9 ldx CHRCNT ; get name index +12251 8BCC E0 2D cpx #MAX_SAVENAME ; just get so many characters +12252 8BCE B0 BB bcs GNMBAD ; beep at user +12253 8BD0 E6 A9 inc CHRCNT ; point to next char +12254 8BD2 9D 00 02 sta LBUFF,X ; save name char +12255 8BD5 GNMSHOW: +12256 8BD5 20 A9 5D jsr CHAR ; show character +12257 8BD8 20 1A 72 jsr DISP_LINE ; make sure it is there +12258 8BDB 4C 74 8B jmp GNAME ; go get next char +12259 ; +12260 ; got the name, so copy it to the SAVENAME buffer +12261 ; +12262 8BDE GOTNAME: +12263 8BDE A5 A9 lda CHRCNT ; did we get any? +12264 8BE0 F0 07 beq GTNMERR ; nope + Tue Jun 13 1989 11:42 Page 184 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12265 8BE2 AD 00 02 lda LBUFF ; make sure first name is a directory +12266 8BE5 C9 2F cmp #'/' ; is it? +12267 8BE7 F0 10 beq GTNM1 ; yup, probly okay then +12268 8BE9 GTNMERR: +12269 8BE9 A9 00 lda #0 ; clear CHRCNT so name doesn't get +12270 8BEB 85 A9 sta CHRCNT ; output again +12271 8BED DLINE PREFIX_ERR ; complain and die +12272 8BED A2 EC ldx #PREFIX_ERR ; get other part of string +12274 [01] IFMA 2 ; check to see if length passed in +12275 ldy ; then just fetch it +12276 [01] ELSE +12277 8BF1 A0 31 ldy #PREFIX_ERRL ; get length of string +12278 [00] ENDIF +12279 8BF3 20 5B 4C jsr DLINE ; print the string +12280 8BF6 .MACEND +12281 8BF6 38 sec ; show bad name +12282 8BF7 B0 29 bcs GNX ; all done +12283 8BF9 GTNM1: +12284 8BF9 A2 00 ldx #0 ; now check to make sure there are 2 +12285 8BFB A0 FE ldy #$FE ; use this as counter +12286 8BFD GTNMCHK: +12287 8BFD BD 00 02 lda LBUFF,X ; get char +12288 8C00 E8 inx ; next char +12289 8C01 C9 2F cmp #'/' ; prefix deliminator? +12290 8C03 D0 03 bne GTNMCHK1 ; nope +12291 8C05 C8 iny ; count this one +12292 8C06 F0 06 beq GTNM2 ; we have 2 of them +12293 8C08 GTNMCHK1: +12294 8C08 E4 A9 cpx CHRCNT ; at end? +12295 8C0A F0 DD beq GTNMERR ; yes, and no 2 '/'s +12296 8C0C D0 EF bne GTNMCHK ; go check next char +12297 8C0E GTNM2: +12298 8C0E E4 A9 cpx CHRCNT ; make sure there are chars after prefix +12299 8C10 F0 D7 beq GTNMERR ; nope, still an error +12300 8C12 A6 A9 ldx CHRCNT ; get how many characters +12301 8C14 8E 65 8A stx SNAMEL ; save in length byte +12302 8C17 CA dex ; points one too far +12303 8C18 GNL: +12304 8C18 BD 00 02 lda LBUFF,X ; get the char +12305 8C1B 9D 66 8A sta SAVENAME,X ; save the char +12306 8C1E CA dex ; point to previous one +12307 8C1F 10 F7 bpl GNL ; and go get it +12308 8C21 18 clc ; show did just fine +12309 8C22 GNX: +12310 8C22 08 php ; save status +12311 8C23 A9 00 lda #0 ; and clear CHRCNT +12312 8C25 85 A9 sta CHRCNT ; okay +12313 8C27 A9 0D lda #EOL ; print EOL +12314 8C29 20 A9 5D jsr CHAR ; okay +12315 8C2C 20 B9 4C jsr SWAPBACK ; change back to old window +12316 8C2F 28 plp ; get status back +12317 8C30 60 rts ; all done +12318 ; +12319 ; open up a save file, by first trying to create it. If it already exists +12320 ; then make sure the player wants to delete the file, then get rid of it. +12321 ; Finally open the file. Return with carry set if user aborts the save. +12322 ; Store the ref number into the write parm block. +12323 ; +12324 8C31 OPEN_SAVE: +12325 8C31 CREATE CREATE_PB ; first try to create the file +12326 8C31 PRODOS $C0, CREATE_PB +12327 8C31 20 00 BF jsr $BF00 ; ProDOS handler +12328 8C34 C0 DB $C0 ; ProDOS function code +12329 8C35 1D8B DW CREATE_PB ; Function Parameter Block address +12330 8C37 .MACEND +12331 8C37 .MACEND +12332 8C37 90 16 bcc OPSV_OPEN ; created just fine, so open it +12333 ; +12334 ; can't create the file, check out why +12335 ; +12336 8C39 C9 47 cmp #$47 ; this means file already there +12337 8C3B F0 03 beq OPSV1 ; nope, not that +12338 8C3D 4C 7A 47 jmp DISK_ERR ; show badness +12339 8C40 OPSV1: + Tue Jun 13 1989 11:42 Page 185 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12340 8C40 DLINE DELQ ; ask about deleting this file +12341 8C40 A2 B5 ldx #DELQ ; get other part of string +12343 [01] IFMA 2 ; check to see if length passed in +12344 ldy ; then just fetch it +12345 [01] ELSE +12346 8C44 A0 23 ldy #DELQL ; get length of string +12347 [00] ENDIF +12348 8C46 20 5B 4C jsr DLINE ; print the string +12349 8C49 .MACEND +12350 8C49 20 D6 8C jsr GETYN ; get me the yes or no +12351 8C4C 90 01 bcc OPSV_OPEN ; so then delete it if yes +12352 8C4E 60 rts ; nope, so just quit +12353 8C4F OPSV_OPEN: +12354 8C4F OPEN OPEN_SV ; open the save file +12355 8C4F PRODOS $C8, OPEN_SV +12356 8C4F 20 00 BF jsr $BF00 ; ProDOS handler +12357 8C52 C8 DB $C8 ; ProDOS function code +12358 8C53 2E8B DW OPEN_SV ; Function Parameter Block address +12359 8C55 .MACEND +12360 8C55 .MACEND +12361 8C55 90 03 bcc OPSV_OP1 ; okey, things worked just fine +12362 8C57 4C 7A 47 jmp DISK_ERR ; complain about error +12363 8C5A OPSV_OP1: +12364 8C5A AD 33 8B lda OPEN_SV+OP_REFNUM ; get the ref number +12365 8C5D 8D 37 8B sta WRITE_SV+WR_REFNUM ; save the ref number +12366 8C60 8D 35 8B sta CLOSE_PB+CL_REFNUM ; to close parm too +12367 8C63 8D 2A 8B sta SETEOF_PB+SE_REFNUM ; for cleansing file +12368 8C66 SET_EOF SETEOF_PB ; clear out file +12369 8C66 PRODOS $D0, SETEOF_PB +12370 8C66 20 00 BF jsr $BF00 ; ProDOS handler +12371 8C69 D0 DB $D0 ; ProDOS function code +12372 8C6A 298B DW SETEOF_PB ; Function Parameter Block address +12373 8C6C .MACEND +12374 8C6C .MACEND +12375 8C6C 90 03 bcc OPSVEX ; no problems +12376 8C6E 20 7A 47 jsr DISK_ERR ; complain +12377 8C71 OPSVEX: +12378 8C71 60 rts ; file has been opened, return +12379 ; +12380 ; OPEN_RES - open the save file +12381 ; +12382 8C72 OPEN_RES: +12383 8C72 OPEN OPEN_SV ; open it up +12384 8C72 PRODOS $C8, OPEN_SV +12385 8C72 20 00 BF jsr $BF00 ; ProDOS handler +12386 8C75 C8 DB $C8 ; ProDOS function code +12387 8C76 2E8B DW OPEN_SV ; Function Parameter Block address +12388 8C78 .MACEND +12389 8C78 .MACEND +12390 8C78 90 01 bcc OPR1 ; okay, it worked +12391 8C7A 60 rts ; okay, it didn't +12392 8C7B OPR1: +12393 8C7B AD 33 8B lda OPEN_SV+OP_REFNUM ; get reference number +12394 8C7E 8D BF 45 sta READ_PB+RD_REFNUM ; save for read +12395 8C81 8D 35 8B sta CLOSE_PB+CL_REFNUM ; and for close +12396 8C84 60 rts +12397 ; +12398 ; CLOSE_SAVE - close up the save file if it is open, and +12399 ; restore open game files +12400 ; +12401 8C85 CLOSE_SAVE: +12402 8C85 AD 35 8B lda CLOSE_PB+CL_REFNUM ; check if it opened +12403 8C88 F0 06 beq CLSVX ; okay, nothing +12404 8C8A CLOSE CLOSE_PB ; close the save file +12405 8C8A PRODOS $CC, CLOSE_PB +12406 8C8A 20 00 BF jsr $BF00 ; ProDOS handler +12407 8C8D CC DB $CC ; ProDOS function code +12408 8C8E 348B DW CLOSE_PB ; Function Parameter Block address +12409 8C90 .MACEND +12410 8C90 .MACEND +12411 8C90 CLSVX: +12412 ; lda #1 ; flag is true +12413 ; sta SAVEDISK ; show we have a save disk in there +12414 ; jsr SET_GAMEPRE ; go get the last one used + Tue Jun 13 1989 11:42 Page 186 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12415 ; jsr FETCH_FILE ; this does it +12416 8C90 AE 67 46 ldx GAME1NML ; get length of current name +12417 8C93 BD 67 46 lda GAME1NM,X ; get the number of the file +12418 8C96 8D B5 49 sta SAVENUM ; we need this to look for prefix +12419 8C99 8D 44 4A sta SAVEDISK ; show taking out save disk, not game disk +12420 8C9C 20 D1 4A jsr DO_GAME1 ; open up GAME1 file +12421 8C9F AD D3 1D lda D2SEG+HI ; set DSEGS to point to #2 +12422 8CA2 85 1F sta DSEGS+HI +12423 8CA4 AD D2 1D lda D2SEG+LO +12424 8CA7 85 1E sta DSEGS+LO +12425 8CA9 AE 79 46 ldx GAME2NML ; get length of current name +12426 8CAC BD 79 46 lda GAME2NM,X ; get the number of the file +12427 8CAF 8D B5 49 sta SAVENUM ; we need this to look for prefix +12428 8CB2 20 0F 4A jsr OPEN_GAME2 ; open up GAME2 file +12429 8CB5 A0 00 ldy #0 ; open up GAME2 file, just for kicks +12430 8CB7 8C 44 4A sty SAVEDISK ; show we have a save disk in there +12431 8CBA 8C 35 8B sty CLOSE_PB+CL_REFNUM ; clear close +12432 8CBD C8 iny ; set for true +12433 8CBE 84 AA sty SCRIPT ; allow scripting again +12434 8CC0 60 rts ; DONE +12435 ; +12436 ; CLOSE_GAME - close the current game file(s) +12437 ; and set DSEGS to point to preload so it will reopen them +12438 ; +12439 8CC1 CLOSE_GAME: +12440 8CC1 A9 00 lda #0 ; show no files are open +12441 8CC3 8D 35 8B sta CLOSE_PB+CL_REFNUM ; 0 closes all files +12442 8CC6 8D 77 46 sta GAME1REF ; zero out two game files too +12443 8CC9 8D 89 46 sta GAME2REF ; and here is number 2 +12444 8CCC 8D FC 73 sta PF_FID ; clear this too +12445 8CCF CLOSE CLOSE_PB ; now all are closed +12446 8CCF PRODOS $CC, CLOSE_PB +12447 8CCF 20 00 BF jsr $BF00 ; ProDOS handler +12448 8CD2 CC DB $CC ; ProDOS function code +12449 8CD3 348B DW CLOSE_PB ; Function Parameter Block address +12450 8CD5 .MACEND +12451 8CD5 .MACEND +12452 8CD5 60 rts +12453 ; +12454 ; Get answer to Yes/No question. Return with C==0 for yes, and C==1 +12455 ; for a no. RETURN == Yes, ESCAPE == NO +12456 ; +12457 8CD6 GETYN: +12458 8CD6 20 20 51 jsr GETKEY ; get the key strok +12459 8CD9 C9 79 cmp #'y' ; IF REPLY IS "Y" +12460 8CDB F0 25 beq ALLSET ; ACCEPT RESPONSES +12461 8CDD C9 59 cmp #'Y' ; get both y's +12462 8CDF F0 21 beq ALLSET +12463 8CE1 C9 0D cmp #EOL ; EOL IS ALSO ACCEPTABLE +12464 8CE3 F0 1D beq ALLSET +12465 8CE5 C9 6E cmp #'n' ; IF REPLY IS "N" +12466 8CE7 F0 0E beq NOTSAT ; return with carry set +12467 8CE9 C9 4E cmp #'N' ; check both n's +12468 8CEB F0 0A beq NOTSAT +12469 8CED C9 1B cmp #ESCAPE ; check for ESC key too +12470 8CEF F0 06 beq NOTSAT ; which means no +12471 8CF1 20 B3 4E jsr BEEP ; ELSE BEEP +12472 8CF4 4C D6 8C jmp GETYN ; INSIST ON Y OR N +12473 8CF7 NOTSAT: +12474 8CF7 DLINE NO ; PRINT "NO"/EOL +12475 8CF7 A2 E6 ldx #NO ; get other part of string +12477 [01] IFMA 2 ; check to see if length passed in +12478 ldy ; then just fetch it +12479 [01] ELSE +12480 8CFB A0 03 ldy #NOL ; get length of string +12481 [00] ENDIF +12482 8CFD 20 5B 4C jsr DLINE ; print the string +12483 8D00 .MACEND +12484 8D00 38 sec ; set the carry +12485 8D01 60 rts ; and show it +12486 8D02 ALLSET: +12487 8D02 DLINE YES ; Print "YES"/EOL +12488 8D02 A2 E2 ldx #YES ; get other part of string + Tue Jun 13 1989 11:42 Page 187 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12490 [01] IFMA 2 ; check to see if length passed in +12491 ldy ; then just fetch it +12492 [01] ELSE +12493 8D06 A0 04 ldy #YESL ; get length of string +12494 [00] ENDIF +12495 8D08 20 5B 4C jsr DLINE ; print the string +12496 8D0B .MACEND +12497 8D0B 18 clc ; clear the carry +12498 8D0C 60 rts +12499 8D0D GETRET: +12500 8D0D DLINE RETQ ; ask for return +12501 8D0D A2 D7 ldx #RETQ ; get other part of string +12503 [01] IFMA 2 ; check to see if length passed in +12504 ldy ; then just fetch it +12505 [01] ELSE +12506 8D11 A0 15 ldy #RETQL ; get length of string +12507 [00] ENDIF +12508 8D13 20 5B 4C jsr DLINE ; print the string +12509 8D16 .MACEND +12510 8D16 GETRETL: +12511 8D16 20 20 51 jsr GETKEY ; get a key +12512 8D19 C9 0D cmp #EOL ; return key? +12513 8D1B D0 F9 bne GETRETL ; nope +12514 8D1D 20 A9 5D jsr CHAR ; show the +12515 8D20 60 rts +12516 8D21 +12517 ; --------- +12518 ; SAVE GAME +12519 ; --------- +12520 8D21 ZSAVE: +12521 8D21 A9 4E lda #'N' +12522 8D23 A6 62 ldx NARGS +12523 8D25 F0 02 beq OLDSAV ; NORMAL, COMPLETE SAVE +12524 8D27 A9 50 lda #'P' +12525 8D29 OLDSAV: +12526 8D29 8D 8E 5B sta TYPE +12527 8D2C 20 D1 89 jsr SAVRES ; set up screen +12528 8D2F 20 3E 8B jsr GET_SNAME ; get the name of the save file +12529 8D32 B0 7B bcs ZSEXIT ; don't wanna after all +12530 8D34 20 31 8C jsr OPEN_SAVE ; open the file +12531 8D37 B0 76 bcs ZSEXIT ; don't really care to +12532 ; +12533 ; SAVE GAME PARAMETERS IN [BUFSAV] +12534 ; +12535 8D39 AD 02 96 lda ZBEGIN+ZID ; MOVE GAME ID +12536 8D3C 8D 20 1E sta BUFSAV+0 ; INTO 1ST 2 BYTES +12537 8D3F AD 03 96 lda ZBEGIN+ZID+1 ; OF THE A +12538 8D42 8D 21 1E sta BUFSAV+1 +12539 8D45 A5 AF lda ZSP+LO ; MOVE [ZSP] +12540 8D47 8D 22 1E sta BUFSAV+2 +12541 8D4A A5 B0 lda ZSP+HI +12542 8D4C 8D 23 1E sta BUFSAV+3 +12543 8D4F AD A3 6C lda OLDZSP+LO +12544 8D52 8D 24 1E sta BUFSAV+4 +12545 8D55 AD A4 6C lda OLDZSP+HI ; MOVE [OLDZSP] +12546 8D58 8D 25 1E sta BUFSAV+5 +12547 8D5B A2 02 ldx #2 ; MOVE CONTENTS OF [ZPC] +12548 8D5D B5 80 ZSL1: lda ZPC,X ; TO BYTES 7-9 +12549 8D5F 9D 26 1E sta BUFSAV+6,X ; OF [BUFSAV] +12550 8D62 CA dex +12551 8D63 10 F8 bpl ZSL1 +12552 8D65 AD 8E 5B lda TYPE +12553 8D68 8D 29 1E sta BUFSAV+9 ; NORMAL OR PARTIAL +12554 8D6B C9 50 cmp #'P' +12555 8D6D D0 2A bne ZSNONM ; NORMAL SAVE SO NO name TO SAVE +12556 +12557 8D6F A5 67 lda ARG3+LO ; set up FPC to get save name +12558 8D71 85 8C sta FPCL ; lo part is okay +12559 8D73 A5 68 lda ARG3+HI ; get page +12560 8D75 20 A9 8F jsr SETPC ; get memory addr +12561 8D78 85 8D sta FPCH ; page number +12562 8D7A 84 8E sty FPCBNK ; and bank +12563 8D7C 20 88 92 jsr FETCHB ; get count +12564 8D7F 85 78 sta I ; and save it + Tue Jun 13 1989 11:42 Page 188 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12565 8D81 20 F0 8F jsr NEXTFPC ; point to next byte +12566 8D84 A9 00 lda #0 ; set up data offset +12567 8D86 85 7A sta J ; did it +12568 8D88 ZSL3: +12569 8D88 20 88 92 jsr FETCHB ; get data byte +12570 8D8B A4 7A ldy J ; get offset +12571 8D8D 99 2A 1E sta BUFSAV+10,Y ; save into buffer +12572 8D90 20 F0 8F jsr NEXTFPC ; point to next byte +12573 8D93 E6 7A inc J ; next byte +12574 8D95 C6 78 dec I ; count it +12575 8D97 D0 EF bne ZSL3 ; loop again +12576 8D99 ZSNONM: +12577 ; +12578 ; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK +12579 ; +12580 8D99 A9 00 lda #MAIN ; in the main bank +12581 8D9B 85 B8 sta DSKBNK ; thank you +12582 8D9D A9 1E lda #>LOCALS ; start at locals +12583 8D9F 85 B7 sta DBUFF+HI ; POINT TO THE PAGE +12584 8DA1 20 E6 47 jsr PUTDSK ; AND WRITE IT OUT +12585 8DA4 90 0F bcc ZSOK ; IF SUCCEEDED, WRITE STACK +12586 8DA6 ZSBAD: +12587 8DA6 20 7A 47 jsr DISK_ERR ; print error message +12588 8DA9 SET_EOF SETEOF_PB ; clear out file, maybe +12589 8DA9 PRODOS $D0, SETEOF_PB +12590 8DA9 20 00 BF jsr $BF00 ; ProDOS handler +12591 8DAC D0 DB $D0 ; ProDOS function code +12592 8DAD 298B DW SETEOF_PB ; Function Parameter Block address +12593 8DAF .MACEND +12594 8DAF .MACEND +12595 8DAF ZSEXIT: +12596 8DAF 20 85 8C jsr CLOSE_SAVE ; else get game file back +12597 8DB2 4C CA 43 jmp RET0 ; AND FAIL +12598 ; +12599 ; IF A PARTIAL SAVE WRITE FROM ARG1 FOR ARG2 BYTES TO DISK +12600 ; (ROUNDED TO PGS) SKIPPING ZSTACK WRITE +12601 ; +12602 8DB5 ZSOK: +12603 8DB5 AD 8E 5B lda TYPE +12604 8DB8 C9 50 cmp #'P' +12605 8DBA D0 1F bne ZSALL +12606 8DBC A5 64 lda ARG1+HI ; find where to start & how far to go +12607 8DBE 20 A9 8F jsr SETPC ; get page in memory +12608 8DC1 48 pha ; save for minute +12609 8DC2 29 01 and #$01 ; check for odd page +12610 8DC4 F0 02 beq ZSP1 ; nope, don't make one more page +12611 8DC6 E6 66 inc ARG2+HI ; go get one more page +12612 8DC8 ZSP1: +12613 8DC8 68 pla ; get it back +12614 8DC9 29 FE and #$FE ; must be on block boundary +12615 8DCB 85 B7 sta DBUFF+HI ; this is page +12616 8DCD 84 B8 sty DSKBNK ; which bank +12617 8DCF A6 66 ldx ARG2+HI ; get MSB of count +12618 8DD1 A5 63 lda ARG1+LO ; get lo offset +12619 8DD3 18 clc ; add +12620 8DD4 65 65 adc ARG2+LO ; lo count +12621 8DD6 90 01 bcc ZSPINC ; no extra page +12622 8DD8 E8 inx ; wrapped extra page +12623 8DD9 ZSPINC: +12624 8DD9 D0 15 bne SAVE2DISK ; go copy it now +12625 ; +12626 ; WRITE CONTENTS OF Z-STACK TO DISK +12627 ; +12628 8DDB ZSALL: +12629 8DDB A9 0D lda #>ZSTKBL ; point to 1st page +12630 8DDD 85 B7 sta DBUFF+HI +12631 8DDF 20 E6 47 jsr PUTDSK ; write them, first one +12632 8DE2 B0 C2 bcs ZSBAD +12633 8DE4 20 E6 47 jsr PUTDSK ; write them, second one +12634 8DE7 B0 BD bcs ZSBAD +12635 ; +12636 ; WRITE ENTIRE GAME PRELOAD TO DISK +12637 ; +12638 8DE9 A9 96 lda #>ZBEGIN ; POINT TO 1ST PAGE +12639 8DEB 85 B7 sta DBUFF+HI ; OF PRELOAD + Tue Jun 13 1989 11:42 Page 189 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12640 8DED AE 0E 96 ldx ZBEGIN+ZPURBT ; GET # IMPURE PAGES +12641 8DF0 SAVE2DISK: +12642 8DF0 E8 inx ; use for counting +12643 8DF1 86 78 stx I+LO +12644 8DF3 46 78 lsr I+LO ; /2 for 512byte pages +12645 8DF5 90 02 bcc ZSL2 ; no wrapping +12646 8DF7 E6 78 inc I+LO ; wrapped once +12647 8DF9 ZSL2: +12648 8DF9 20 E6 47 jsr PUTDSK ; this does the write +12649 8DFC B0 A8 bcs ZSBAD +12650 8DFE C6 78 dec I+LO ; count one page +12651 8E00 D0 F7 bne ZSL2 ; not done yet +12652 +12653 8E02 20 85 8C jsr CLOSE_SAVE ; prompt for game file +12654 +12655 [01] IF CHECKSUM == 1 +12656 lda CKS_COUNT +12657 jsr HEXNUM +12658 lda CKSB +12659 jsr HEXNUM +12660 lda #EOL +12661 jsr CHAR +12662 [00] ENDIF +12663 +12664 8E05 A9 01 lda #1 ; set to mark +12665 8E07 A2 00 ldx #0 +12666 8E09 4C CD 43 jmp PUTBYT ; SUCCESS +12667 +12668 ; ------------ +12669 ; RESTORE GAME +12670 ; ------------ +12671 +12672 8E0C ZREST: +12673 8E0C A9 4E lda #'N' +12674 8E0E A6 62 ldx NARGS +12675 8E10 F0 02 beq OLDRES ; NORMAL, COMPLETE RESTORE +12676 8E12 A9 50 lda #'P' ; partial restore +12677 8E14 OLDRES: +12678 8E14 8D 8E 5B sta TYPE ; save which kind of restore +12679 ; +12680 ; SAVE LOCALS IN CASE OF ERROR +12681 ; +12682 8E17 A2 1F ldx #31 +12683 8E19 BD 00 1E LOCSAV: lda LOCALS,X ; COPY ALL LOCALS +12684 8E1C 9D E0 1D sta LOCAL_SV,X ; to a save spot +12685 8E1F CA dex +12686 8E20 10 F7 bpl LOCSAV +12687 +12688 8E22 20 3E 8B jsr GET_SNAME ; get the name of the file +12689 8E25 B0 3C bcs ZRQUIT ; okay, don't do it +12690 8E27 20 72 8C jsr OPEN_RES ; open the restore file +12691 8E2A B0 34 bcs ZRBAD ; can't do it +12692 +12693 8E2C AD 8E 5B lda TYPE ; PARTIAL SAVE DIFFERS STARTING HERE +12694 8E2F C9 50 cmp #'P' +12695 8E31 D0 03 bne ZRNRML +12696 8E33 4C F4 8E jmp ZPARTR ; just a partial restore +12697 8E36 ZRNRML: +12698 8E36 A9 00 lda #MAIN +12699 8E38 85 B8 sta DSKBNK ; SET TO WRITE TO MAIN BANK +12700 8E3A A9 1E lda #>LOCALS +12701 8E3C 85 B7 sta DBUFF+HI +12702 8E3E A9 02 lda #2 ; must read in two pages +12703 8E40 85 7E sta L+LO +12704 8E42 20 01 48 jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD +12705 8E45 B0 19 bcs ZRBAD ; didn't work! +12706 8E47 AD C5 45 lda READ_PB+RD_LENGTH+HI ; see how much was read in +12707 8E4A C9 02 cmp #2 ; were 2 blocks read in? +12708 8E4C D0 15 bne ZRQUIT ; wrong kind of file for complete save +12709 +12710 8E4E AD 20 1E lda BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID +12711 8E51 CD 02 96 cmp ZBEGIN+ZID ; MATCH THE CURRENT ID? +12712 8E54 D0 0D bne ZRQUIT ; WRONG DISK IF NOT +12713 +12714 8E56 AD 21 1E lda BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE? + Tue Jun 13 1989 11:42 Page 190 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12715 8E59 CD 03 96 cmp ZBEGIN+ZID+1 +12716 8E5C F0 16 beq ZROK ; CONTINUE IF BOTH BYTES MATCH +12717 8E5E D0 03 bne ZRQUIT ; skip disk error message +12718 ; +12719 ; HANDLE RESTORE ERROR +12720 ; +12721 8E60 ZRBAD: +12722 8E60 20 7A 47 jsr DISK_ERR ; print error message +12723 8E63 ZRQUIT: +12724 8E63 A2 1F ldx #31 ; RESTORE ALL SAVED LOCALS +12725 8E65 BD E0 1D ZRL2: lda LOCAL_SV,X +12726 8E68 9D 00 1E sta LOCALS,X +12727 8E6B CA dex +12728 8E6C 10 F7 bpl ZRL2 +12729 8E6E BADRES: +12730 8E6E 20 85 8C jsr CLOSE_SAVE ; PROMPT FOR GAME DISK +12731 8E71 4C CA 43 jmp RET0 ; PREDICATE FAILS +12732 ; +12733 ; CONTINUE RESTORE +12734 ; +12735 8E74 ZROK: +12736 8E74 AD 10 96 lda ZBEGIN+ZFLAGS ; save both flag bytes +12737 8E77 85 7A sta J+LO +12738 8E79 AD 11 96 lda ZBEGIN+ZFLAGS+1 +12739 8E7C 85 7B sta J+HI +12740 +12741 8E7E A9 0D lda #>ZSTKBL ; retrieve old contents of +12742 8E80 85 B7 sta DBUFF+HI ; z-stack +12743 8E82 A9 04 lda #4 ; do 4 pages +12744 8E84 85 7E sta L+LO ; tell GETRES how many pages +12745 8E86 20 01 48 jsr GETRES ; get 4 pages of z-stack +12746 8E89 90 03 bcc ZROKL1 +12747 8E8B 4C 64 47 jmp DISK_FATAL ; if here, mix of good & bad so die +12748 8E8E ZROKL1: +12749 8E8E A9 96 lda #>ZBEGIN ; get where we are +12750 8E90 85 B7 sta DBUFF+HI +12751 8E92 AD 0E 96 lda ZBEGIN+ZPURBT ; get # pages to load +12752 8E95 85 78 sta I+LO +12753 8E97 E6 78 inc I+LO ; go get last page if possible +12754 8E99 LREST0: +12755 8E99 A5 78 lda I+LO ; how many pages left +12756 8E9B F0 20 beq LRESTj ; finis +12757 8E9D 38 sec ; doing subtract +12758 8E9E E9 04 sbc #4 ; doing it 4 blocks at a time +12759 8EA0 90 0E bcc LREST1 ; <4 blocks left so deal with it special +12760 8EA2 85 78 sta I+LO ; save remenants +12761 8EA4 LREST: +12762 8EA4 A9 04 lda #4 ; assume at least 4 pages +12763 8EA6 85 7E sta L+LO ; this tells GETRES how many to read in +12764 8EA8 20 01 48 jsr GETRES ; fetch the remainder +12765 8EAB 90 EC bcc LREST0 +12766 8EAD 4C 64 47 jmp DISK_FATAL +12767 8EB0 LREST1: +12768 8EB0 A5 78 lda I+LO ; get how many left +12769 8EB2 85 7E sta L+LO ; and show it to GETRES +12770 8EB4 29 01 and #$1 ; is it odd? +12771 8EB6 F0 02 beq LREST2 ; nope +12772 8EB8 E6 7E inc L+LO ; read one more +12773 8EBA LREST2: +12774 8EBA 20 01 48 jsr GETRES ; and finish it up +12775 ; +12776 ; RESTORE THE STATE OF THE SAVED GAME +12777 ; +12778 8EBD LRESTj: +12779 8EBD A5 7A lda J+LO ; RESTORE THE STATE +12780 8EBF 8D 10 96 sta ZBEGIN+ZFLAGS ; OF THE FLAG WORD +12781 8EC2 A5 7B lda J+HI +12782 8EC4 8D 11 96 sta ZBEGIN+ZFLAGS+1 +12783 +12784 8EC7 AD 22 1E lda BUFSAV+2 ; RESTORE THE [ZSP] +12785 8ECA 85 AF sta ZSP+LO +12786 8ECC AD 23 1E lda BUFSAV+3 +12787 8ECF 85 B0 sta ZSP+HI +12788 8ED1 AD 24 1E lda BUFSAV+4 +12789 8ED4 8D A3 6C sta OLDZSP+LO + Tue Jun 13 1989 11:42 Page 191 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12790 8ED7 AD 25 1E lda BUFSAV+5 ; AND THE [OLDZSP] +12791 8EDA 8D A4 6C sta OLDZSP+HI +12792 +12793 8EDD A2 02 ldx #2 ; RESTORE THE [ZPC] +12794 8EDF BD 26 1E ZRL4: lda BUFSAV+6,X +12795 8EE2 95 80 sta ZPC,X +12796 8EE4 CA dex +12797 8EE5 10 F8 bpl ZRL4 +12798 +12799 8EE7 20 85 8C ZROUT: jsr CLOSE_SAVE ; PROMPT FOR GAME DISK +12800 8EEA 20 DC 90 jsr VLDZPC ; MAKE VALID (MUST DO AFTER GET DISK) +12801 +12802 [01] IF CHECKSUM == 1 +12803 lda CKS_COUNT +12804 jsr HEXNUM +12805 lda CKSB +12806 jsr HEXNUM +12807 lda #EOL +12808 jsr CHAR +12809 [00] ENDIF +12810 +12811 8EED A9 02 lda #2 ; SET TO +12812 8EEF A2 00 ldx #0 +12813 8EF1 4C CD 43 jmp PUTBYT ; SUCCESS +12814 +12815 +12816 ; DO PARTIAL RESTORE GETTING 1ST PAGE +12817 ; AND LAST PAGE BYTE ALIGNMENT CORRECT +12818 ; WRITE LOCALS TO IOBUFF JUST TO LOOK AT NAME +12819 8EF4 ZPARTR: +12820 8EF4 A9 00 lda #MAIN +12821 8EF6 85 B8 sta DSKBNK +12822 8EF8 A9 08 lda #>IOBUFF ; DON'T READ TO LOCALS YET (X) +12823 8EFA 85 B7 sta DBUFF+HI +12824 8EFC A9 02 lda #2 ; just one block please +12825 8EFE 85 7E sta L+LO +12826 8F00 20 01 48 jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD +12827 8F03 90 03 bcc ZRN2 ; worked just fine +12828 8F05 ZPBAD: +12829 8F05 4C 6E 8E jmp BADRES ; names don't match, die +12830 8F08 ZRN2: +12831 8F08 A5 67 lda ARG3+LO ; set up FPC to get save name +12832 8F0A 85 8C sta FPCL ; lo part is okay +12833 8F0C A5 68 lda ARG3+HI ; get page +12834 8F0E 20 A9 8F jsr SETPC ; get memory addr +12835 8F11 85 8D sta FPCH ; page number +12836 8F13 84 8E sty FPCBNK ; and bank +12837 8F15 20 88 92 jsr FETCHB ; get count +12838 8F18 85 78 sta I ; and save it +12839 8F1A 20 F0 8F jsr NEXTFPC ; point to next byte +12840 8F1D A9 20 lda #IOBUFF ; get 1st page +12869 8F51 85 B7 sta DBUFF+HI ; getres should keep in iobuff +12870 8F53 8D 6F 8F sta ZPARTMOD+2 ; and show where to get it from +12871 8F56 A9 01 lda #$01 ; is it odd +12872 8F58 24 90 bit SPCH ; get page destination +12873 8F5A F0 03 beq ZPARTx ; nope +12874 8F5C EE 6F 8F inc ZPARTMOD+2 ; then get second page worth +12875 8F5F ZPARTx: +12876 8F5F A9 02 lda #2 ; just do one block +12877 8F61 85 7E sta L+LO +12878 8F63 20 01 48 jsr GETRES +12879 8F66 90 03 bcc ZPART0 +12880 8F68 4C 64 47 jmp DISK_FATAL ; ALL MESSED UP, JUST QUIT +12881 8F6B ZPART0: +12882 8F6B A4 63 ldy ARG1+LO ; START BYTE FIRST PAGE +12883 8F6D ZPARTMOD: +12884 8F6D B9 00 08 lda IOBUFF,Y ; this gets modified with good page # +12885 8F70 20 67 92 jsr STASHB +12886 8F73 20 D0 8F jsr NEXTSPC +12887 8F76 20 B6 44 jsr DECJ +12888 8F79 B0 03 bcs ZPART1 ; CARRY CLEAR IF $FFFF RESULT +12889 8F7B 4C E7 8E jmp ZROUT +12890 8F7E ZPART1: +12891 8F7E E6 63 inc ARG1+LO +12892 8F80 D0 E9 bne ZPART0 +12893 8F82 A9 09 lda #>IOBUFF+1 ; this is second page address +12894 8F84 CD 6F 8F cmp ZPARTMOD+2 ; is it second one already? +12895 8F87 F0 C6 beq POK ; yes, so read in a new block +12896 8F89 8D 6F 8F sta ZPARTMOD+2 ; then update it +12897 8F8C D0 DD bne ZPART0 ; and do it again +12898 ; +12899 ; THE OLD SAVE & RESTORE STILL HAVE OPCODES +12900 ; SO JUST PUT IN A PLACE FOR THEM HERE FOR NOW +12901 ; +12902 8F8E OSAVE: +12903 8F8E 60 OREST: RTS +12904 +12905 8F8F ZISAVE: +12906 8F8F 4C CA 43 ZIREST: JMP RET0 ; NOT IMPLEMENTED ON APPLE +12907 8F92 END +12908 +12909 +12910 8F92 TITLE "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" +12911 8F92 INCLUDE XPAGING.ASM +12912 8F92 STTL "--- MEMORY PAGING ROUTINES ---" +12913 PAGE + Tue Jun 13 1989 11:42 Page 193 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +12914 +12915 ; ------------------------- +12916 ; POINT [MPC] TO V-ADDR [I] +12917 ; ------------------------- +12918 +12919 8F92 A5 78 SETWRD: LDA I+LO +12920 8F94 85 86 STA MPCL +12921 8F96 A5 79 LDA I+HI +12922 8F98 85 87 STA MPCM +12923 8F9A A9 00 LDA #0 +12924 8F9C 85 88 STA MPCH ; ZERO TOP BIT +12925 8F9E 4C B2 90 JMP VLDMPC +12926 +12927 ; +12928 8FA1 00 00 WANTED: DB 00,00 +12929 ; +12930 8FA3 00 NEXT: DB 00 +12931 8FA4 00 NSUBA: DB 00 +12932 8FA5 00 PSUBA: DB 00 +12933 ; +12934 8FA6 00 YTEMP: DB 00 +12935 8FA7 00 ATEMP: DB 00 +12936 8FA8 00 NSUBY: DB 00 +12937 ; +12938 ; set [A](page), [Y](bank) to point to memory page where page in [A] is +12939 ; +12940 8FA9 SETPC: +12941 8FA9 85 BC sta MEMPAGE ; save it for later addition +12942 8FAB C9 29 cmp #P2PAGE ; IS IT A PAGE IN MAIN +12943 8FAD B0 06 bcs VF2 ; No, it might be in aux mem +12944 +12945 8FAF A9 96 lda #>ZBEGIN ; ADD OFFSET TO GET RAM PAGE +12946 8FB1 A0 00 ldy #MAIN ; in the main bank +12947 8FB3 F0 12 beq VFEXI ; BRA to fetch +12948 8FB5 VF2: +12949 8FB5 C9 D6 cmp #PGBEGIN ; is it paged? +12950 8FB7 B0 12 bcs VFERR ; yes it be paged, so can't deal with it +12951 8FB9 C9 A8 cmp #P3PAGE ; is it in Aux Mem, Part 2? +12952 8FBB B0 06 bcs VF3 ; yes, so subtract different amount +12953 ; +12954 ; this is in lower aux +12955 ; +12956 8FBD A9 17 lda #(Z2PAGE-Z1SIZE) ; subtract size from offset +12957 8FBF A0 01 ldy #AUX ; show aux mem +12958 8FC1 D0 04 bne VFEXI ; jump to end +12959 8FC3 VF3: +12960 8FC3 A9 28 lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides +12961 8FC5 A0 FF ldy #P3BANK ; show page 3 bank +12962 8FC7 VFEXI: +12963 8FC7 18 clc ; get ready for addition +12964 8FC8 65 BC adc MEMPAGE ; now get actual offset +12965 8FCA 60 rts +12966 8FCB VFERR: +12967 ; +12968 ; out of range +12969 ; +12970 8FCB A9 12 lda #18 +12971 8FCD 4C F9 51 jmp ZERROR +12972 ; +12973 ; NEXTSPC - inc SPCL and check for wrapping round to next bank +12974 ; +12975 8FD0 NEXTSPC: +12976 8FD0 E6 8F inc SPCL ; next lo byte +12977 8FD2 D0 1B bne NXSP_EXIT ; no change then +12978 8FD4 E6 90 inc SPCH ; next page +12979 8FD6 A5 90 lda SPCH ; so get page +12980 8FD8 C9 BF cmp #>PRGLBL ; have we reached end of line? +12981 8FDA D0 13 bne NXSP_EXIT ; we be okay +12982 8FDC A5 91 lda SPCBNK ; get bank +12983 8FDE D0 07 bne NXSP1 ; must go to Part 3 +12984 8FE0 E6 91 inc SPCBNK ; so point to aux bank +12985 8FE2 A9 40 lda #Z2PAGE ; first page in aux +12986 8FE4 85 90 sta SPCH ; and point to it +12987 8FE6 60 rts ; and all done +12988 8FE7 NXSP1: + Tue Jun 13 1989 11:42 Page 194 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +12989 8FE7 A9 D0 lda #Z3PAGE ; get start of page 3 +12990 8FE9 85 90 sta SPCH ; and point there +12991 8FEB A9 FF lda #P3BANK ; and point to this bank +12992 8FED 85 91 sta SPCBNK ; okey +12993 8FEF NXSP_EXIT: +12994 8FEF 60 rts +12995 ; +12996 ; NEXTFPC - inc DPCL and check for wrapping round to next bank +12997 ; +12998 8FF0 NEXTFPC: +12999 8FF0 E6 8C inc FPCL ; next lo byte +13000 8FF2 D0 1B bne NXFP_EXIT ; no change then +13001 8FF4 E6 8D inc FPCH ; next page +13002 8FF6 A5 8D lda FPCH ; and get it for checking +13003 8FF8 C9 BF cmp #>PRGLBL ; have we reached end of line? +13004 8FFA D0 13 bne NXFP_EXIT ; we be okay +13005 8FFC A5 8E lda FPCBNK ; get bank +13006 8FFE D0 07 bne NXFP1 ; must skip over stuff in middle +13007 9000 E6 8E inc FPCBNK ; so point to aux bank +13008 9002 A9 40 lda #Z2PAGE ; first page in aux +13009 9004 85 8D sta FPCH ; and point to it +13010 9006 60 rts ; toots finis +13011 9007 NXFP1: +13012 9007 A9 D0 lda #Z3PAGE ; start of part 3 +13013 9009 85 8D sta FPCH ; so show me +13014 900B A9 FF lda #P3BANK ; and point to this bank +13015 900D 85 8E sta FPCBNK ; okey +13016 900F NXFP_EXIT: +13017 900F 60 rts +13018 ; +13019 ; ADDFPC - add amount in [A] to current FPC and check for bank wrap +13020 ; +13021 9010 ADDFPC: +13022 9010 18 clc ; get ready for add +13023 9011 65 8C adc FPCL ; add lo part +13024 9013 85 8C sta FPCL ; and save it +13025 9015 90 1B bcc AFPX ; all done if no page wrap +13026 9017 E6 8D inc FPCH ; point to next page +13027 9019 A5 8D lda FPCH ; get it for compare +13028 901B C9 BF cmp #>PRGLBL ; at end of line in main bank? +13029 901D D0 13 bne AFPX ; nope, all done then +13030 901F A5 8E lda FPCBNK ; get bank +13031 9021 F0 09 beq AFP1 ; it is main, so we be ok +13032 9023 A9 D0 lda #Z3PAGE ; must go to part 3 if in aux mem +13033 9025 85 8D sta FPCH ; thanx +13034 9027 A9 FF lda #P3BANK ; and point to this bank +13035 9029 85 8E sta FPCBNK ; okey +13036 902B 60 rts ; done +13037 902C AFP1: +13038 902C E6 8E inc FPCBNK ; point to aux +13039 902E A9 40 lda #Z2PAGE ; get start in aux +13040 9030 85 8D sta FPCH ; and save it +13041 9032 AFPX: +13042 9032 60 rts +13043 ; +13044 ; ADDSPC - add amount in [A] to current SPC and check for bank wrap +13045 ; +13046 9033 ADDSPC: +13047 9033 18 clc ; get ready for add +13048 9034 65 8F adc SPCL ; add lo part +13049 9036 85 8F sta SPCL ; and save it +13050 9038 90 1B bcc ASPX ; all done if no page wrap +13051 903A E6 90 inc SPCH ; point to next page +13052 903C A5 90 lda SPCH ; get it for compare +13053 903E C9 BF cmp #>PRGLBL ; at end of line in main bank? +13054 9040 D0 13 bne ASPX ; nope, all done then +13055 9042 A5 91 lda SPCBNK ; get bank +13056 9044 F0 09 beq ASP1 ; it is main, so we be ok +13057 9046 A9 D0 lda #Z3PAGE ; must go to part 3 if in aux mem +13058 9048 85 90 sta SPCH ; thanx +13059 904A A9 FF lda #P3BANK ; and point to this bank +13060 904C 85 91 sta SPCBNK ; okey +13061 904E 60 rts ; done +13062 904F ASP1: +13063 904F E6 91 inc SPCBNK ; point to aux + Tue Jun 13 1989 11:42 Page 195 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13064 9051 A9 40 lda #Z2PAGE ; get start in aux +13065 9053 85 90 sta SPCH ; and save it +13066 9055 ASPX: +13067 9055 60 rts +13068 ; +13069 ; PREVFPC - DEC FPCL and check for wrapping round to next bank +13070 ; +13071 9056 PREVFPC: +13072 9056 A5 8C lda FPCL ; get lo part +13073 9058 D0 1E bne PFPC2 ; it's not zero, so no wrapping +13074 905A A5 8D lda FPCH ; get current page +13075 905C C9 40 cmp #Z2PAGE ; have we reached beginning of page 2? +13076 905E F0 08 beq PFPC1 ; wrap to first bank +13077 9060 C9 D0 cmp #Z3PAGE ; beginning of part 3? +13078 9062 F0 0C beq PFPC3 ; ayyup +13079 9064 C6 8D dec FPCH ; point to previous page +13080 9066 D0 10 bne PFPC2 ; okay +13081 9068 PFPC1: +13082 9068 A5 8E lda FPCBNK ; get bank +13083 906A F0 0F beq VF1ERR ; oops, can't go backwards from main bank +13084 906C A9 00 lda #MAIN ; so point to main bank +13085 906E F0 02 beq PFPC4 ; and store it away +13086 9070 PFPC3: +13087 9070 A9 01 lda #AUX ; and point to this bank +13088 9072 PFPC4: +13089 9072 85 8E sta FPCBNK ; okey +13090 9074 A9 BE lda #(>PRGLBL)-1 ; get me last page in part 2 +13091 9076 85 8D sta FPCH ; and show me +13092 9078 PFPC2: +13093 9078 C6 8C dec FPCL ; and point to previous byte +13094 907A 60 rts +13095 907B VF1ERR: +13096 ; +13097 ; out of range +13098 ; +13099 907B A9 13 lda #19 +13100 907D 4C F9 51 jmp ZERROR +13101 ; +13102 ; PREVSPC - DEC SPCL and check for wrapping round to main bank +13103 ; +13104 9080 PREVSPC: +13105 9080 A5 8F lda SPCL ; get lo part +13106 9082 D0 1E bne PSPC2 ; it's not zero, so no wrapping +13107 9084 A5 90 lda SPCH ; get current page +13108 9086 C9 40 cmp #Z2PAGE ; have we reached beginning of page 2? +13109 9088 F0 08 beq PSPC1 ; wrap to first bank +13110 908A C9 D0 cmp #Z3PAGE ; down past page 3? +13111 908C F0 0C beq PSPC3 ; sure is +13112 908E C6 90 dec SPCH ; point to previous page +13113 9090 D0 10 bne PSPC2 ; okay +13114 9092 PSPC1: +13115 9092 A5 91 lda SPCBNK ; get bank +13116 9094 F0 E5 beq VF1ERR ; oops, can't go backwards from main bank +13117 9096 A9 00 lda #MAIN ; so point to main bank +13118 9098 F0 02 beq PSPC4 ; so save it +13119 909A PSPC3: +13120 909A A9 01 lda #AUX ; and point to this bank +13121 909C PSPC4: +13122 909C 85 8E sta FPCBNK ; okey +13123 909E A9 BE lda #>PRGLBL-1 ; get me last page in low part +13124 90A0 85 90 sta SPCH ; and show me +13125 90A2 PSPC2: +13126 90A2 C6 8F dec SPCL ; and point to previous byte +13127 90A4 60 rts +13128 ; +13129 ; FP2SP - copy the 3 parts of FPC to SPC +13130 ; +13131 90A5 FP2SP: +13132 90A5 A5 8E lda FPCBNK +13133 90A7 85 91 sta SPCBNK +13134 90A9 A5 8D lda FPCH +13135 90AB 85 90 sta SPCH +13136 90AD A5 8C lda FPCL +13137 90AF 85 8F sta SPCL +13138 90B1 60 rts + Tue Jun 13 1989 11:42 Page 196 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13139 90B2 +13140 ; MAKE [MPCPNT],[MPCBNK] POINT TO +13141 ; THE RAM PAGE AND BANK THAT HOLDS +13142 ; THE V-PAGE MPCH,M +13143 ; +13144 90B2 VLDMPC: +13145 90B2 A5 88 lda MPCH ; check hi part +13146 90B4 D0 0F bne VLD3 ; NOT IN FIRST V-64K, so must be paged +13147 90B6 A5 87 lda MPCM ; check to see if it is paged +13148 90B8 20 D4 91 jsr CHECKPRE ; is it preloaded? +13149 90BB B0 08 bcs VLD3 ; no, so it be paged +13150 90BD 20 A9 8F jsr SETPC ; so put page/bank into A/Y +13151 90C0 84 8B sty MPCBNK +13152 90C2 85 8A sta MPCPNT+HI +13153 90C4 NOMUCK: +13154 90C4 60 rts +13155 ; +13156 ; must be paged, so check for it or read it in +13157 ; +13158 90C5 VLD3: +13159 90C5 A5 88 lda MPCH +13160 90C7 A4 87 ldy MPCM +13161 90C9 20 12 91 jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y +13162 90CC 18 clc +13163 90CD 69 08 adc #>PBEGIN +13164 90CF 85 8A sta MPCPNT+HI +13165 90D1 A0 01 ldy #PB_BANK ; paging buffers are in aux mem +13166 90D3 84 8B sty MPCBNK +13167 ; +13168 ; TEST FOR MUCK +13169 ; +13170 90D5 AD 11 91 lda MUCKFLG +13171 90D8 F0 EA beq NOMUCK +13172 90DA D0 00 bne VLDZPC ;MAY HAVE MUCKED ZPC SO GO FIX +13173 ; +13174 ; SAME IDEA AS VLDMPC +13175 ; +13176 90DC VLDZPC: +13177 90DC A5 59 lda INFODOS ; check first for InfoDOS page +13178 90DE F0 06 beq VLDZ1 ; none +13179 90E0 20 E9 91 jsr INFO_PAGE ; well, is it? +13180 90E3 90 01 bcc VLDZ1 ; nope +13181 90E5 60 rts ; all set otherwise +13182 90E6 VLDZ1: +13183 90E6 A5 82 lda ZPCH +13184 90E8 D0 0F bne VLDZ3 ;NOT IN FIRST V-64K, so must be paged +13185 90EA A5 81 lda ZPCM ; check to see if it is paged +13186 90EC 20 D4 91 jsr CHECKPRE ; is it preloaded? +13187 90EF B0 08 bcs VLDZ3 ; no, so it must be paged +13188 90F1 20 A9 8F jsr SETPC ; point to correct bank and page +13189 90F4 84 85 sty ZPCBNK ; set bank +13190 90F6 85 84 sta ZPCPNT+HI ; and MSB of pointer +13191 90F8 NOZMUCK: +13192 90F8 60 rts +13193 VLDZ3: ;MUST BE PAGED +13194 90F9 A5 82 lda ZPCH +13195 90FB A4 81 ldy ZPCM +13196 90FD 20 12 91 jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y +13197 9100 18 clc +13198 9101 69 08 adc #>PBEGIN +13199 9103 85 84 sta ZPCPNT+HI +13200 9105 A0 01 ldy #PB_BANK +13201 9107 84 85 sty ZPCBNK +13202 ; +13203 ; TEST MUCKING +13204 ; +13205 9109 AD 11 91 lda MUCKFLG +13206 910C F0 EA beq NOZMUCK +13207 910E 4C B2 90 jmp VLDMPC ;MAY HAVE MUCKED MPC SO GO FIX +13208 +13209 +13210 ; FIND V-PAGE A,Y IF IT IS IN MEM +13211 ; AND RETURN WITH LINKED LIST +13212 ; PROPERLY MAINTAINED +13213 ; IF V-PAGE A,Y NOT IN MEM + Tue Jun 13 1989 11:42 Page 197 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13214 ; GET FROM DISK AND PUT IN RIGHT +13215 ; PLACE +13216 +13217 9111 00 MUCKFLG: DB 00 ;00 IF PAGING BUFFERS NOT MUCKED +13218 +13219 9112 PAGE: +13220 9112 8D A2 8F sta WANTED+HI +13221 9115 8C A1 8F sty WANTED+LO +13222 9118 A2 00 ldx #0 +13223 911A 8E 11 91 stx MUCKFLG ; CLEAR MUCK FLAG +13224 911D 20 BC 91 jsr WHERE +13225 9120 90 39 bcc TOUGH ; PAGE IS RESIDENT IN PAGING SPACE +13226 ; +13227 ; PAGE MUST BE BROUGHT IN FROM DISK +13228 ; +13229 9122 A6 CD ldx CURRENT ;GET BUFFER TO PUT PAGE INTO +13230 9124 BD 00 0C lda NEXTPNT,X ;BY LOOKING AT NEXT POINTER +13231 9127 85 CD sta CURRENT ;MAKE IT THE CURRENT BUFFER +13232 9129 AA tax +13233 912A AD A2 8F lda WANTED+HI ;LET BUFFER MAP KNOW +13234 912D 9D 80 0C sta VPAGEH,X ;WHICH PAGE +13235 9130 AD A1 8F lda WANTED+LO ;IS GOING TO +13236 9133 29 FE and #$FE ; make address be even +13237 9135 9D C0 0C sta VPAGEL,X ;BE THERE +13238 ;*** +13239 ; point to the next page too +13240 ; +13241 9138 09 01 ora #1 ; add one to point to next 256 byte page +13242 913A 48 pha ; save it +13243 913B 8A txa ; get pointer +13244 913C A8 tay ; into y +13245 913D C8 iny ; point to next buffer +13246 913E 68 pla ; get second buffer back +13247 913F 99 C0 0C sta VPAGEL,Y ; so point to it +13248 9142 BD 80 0C lda VPAGEH,X ; get MSB +13249 9145 99 80 0C sta VPAGEH,Y ; and save it +13250 ; +13251 ; A = WANTED+HI +13252 ; Y = WANTED+LO +13253 ; X = BUFFER +13254 ; +13255 9148 AD A1 8F lda WANTED+LO +13256 914B 29 FE and #$FE ; clear low bit to make it even +13257 914D A8 tay ; want it in y +13258 ;*** +13259 914E AD A2 8F lda WANTED+HI +13260 9151 A6 CD ldx CURRENT +13261 9153 20 80 91 jsr GETVPAGE ; PUT V-PAGE A,Y INTO PAGING BUFFER X +13262 ;*** +13263 9156 CE 11 91 dec MUCKFLG ; INDICATE A MUCKING +13264 9159 D0 1C bne PAGEXIT ; and return current buffer +13265 915B TOUGH: +13266 915B 29 FE and #$FE ; make even page, please +13267 915D 8D A3 8F sta NEXT +13268 9160 C5 CD cmp CURRENT ; GETS REALY SCREWED IF CURRENT==NEXT +13269 9162 F0 13 beq PAGEXIT ; DO NOT CHANGE POINTERS IF IT DOES +13270 ; +13271 ; Y=NEXT(CURRENT) +13272 ; DO THE RIGHT THING TO THE POINTERS +13273 ; +13274 ; ldy CURRENT +13275 ; lda NEXTPNT,Y +13276 ; sta NSUBCUR +13277 9164 AD A3 8F lda NEXT +13278 9167 20 AA 91 jsr DETATCH +13279 916A A4 CD ldy CURRENT +13280 916C AD A3 8F lda NEXT +13281 916F 20 93 91 jsr INSERT +13282 9172 AD A3 8F lda NEXT +13283 9175 85 CD sta CURRENT +13284 9177 PAGEXIT: +13285 ;*** perhaps add one to point to correct buffer +13286 9177 AD A1 8F lda WANTED+LO ; get LSB +13287 917A 29 01 and #$01 ; pick up even/odd bit +13288 917C 18 clc ; doing add + Tue Jun 13 1989 11:42 Page 198 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13289 917D 65 CD adc CURRENT ; point to correct buffer +13290 917F 60 rts +13291 +13292 9180 GETVPAGE: +13293 9180 8D 88 6C sta DBLOCK+HI +13294 9183 8C 87 6C sty DBLOCK+LO +13295 9186 8A txa ; get which paging buffer +13296 9187 18 clc +13297 9188 69 08 adc #>PBEGIN ; and set up abs addr +13298 918A 85 B7 sta DBUFF+HI ; thank you, that's much better +13299 918C A2 01 ldx #PB_BANK +13300 918E 86 B8 stx DSKBNK +13301 9190 4C BF 46 jmp GETDSK +13302 +13303 ; INSERT A AFTER Y +13304 ; A.next = Y.next +13305 ; Y.next = A +13306 ; A.previous = Y +13307 ; [Y.next].previous = A +13308 9193 INSERT: +13309 9193 AA tax +13310 9194 B9 00 0C lda NEXTPNT,Y ; Y.next +13311 9197 9D 00 0C sta NEXTPNT,X ; A.next = Y.next +13312 919A 48 pha ; save Y.next for later +13313 919B 8A txa +13314 919C 99 00 0C sta NEXTPNT,Y ; Y.next = A +13315 919F 98 tya +13316 91A0 9D 40 0C sta PREVPNT,X ; A.prev = Y +13317 91A3 68 pla ; get Y.next back +13318 91A4 A8 tay ; [Y.next].previous +13319 91A5 8A txa +13320 91A6 99 40 0C sta PREVPNT,Y ; [Y.next].previous = A +13321 91A9 60 rts +13322 +13323 [01] IF 0 +13324 ; +13325 ; old one, which puts A AFTER! Y +13326 ; +13327 ; PREV(A)=Y +13328 ; PREV(NEXT(Y))=A +13329 ; NEXT(A)=NEXT(Y) +13330 ; NEXT(Y)=A +13331 +13332 sta ATEMP +13333 sty YTEMP +13334 tax +13335 tya +13336 sta PREVPNT,X +13337 +13338 lda NEXTPNT,Y +13339 sta NSUBY +13340 txa +13341 ldx NSUBY +13342 sta PREVPNT,X +13343 +13344 txa +13345 ldx ATEMP +13346 sta NEXTPNT,X +13347 +13348 lda ATEMP +13349 sta NEXTPNT,Y +13350 rts +13351 [00] ENDIF +13352 +13353 ; DETATCH BUFFER >A< +13354 ; NEXT(PREV(A))=NEXT(A) +13355 ; PREV(NEXT(A))=PREV(A) +13356 +13357 91AA DETATCH: +13358 91AA AA tax +13359 91AB BD 00 0C lda NEXTPNT,X +13360 91AE A8 tay ; Y == A.next +13361 91AF BD 40 0C lda PREVPNT,X ; get A.previous +13362 91B2 AA tax ; X == A.previous +13363 91B3 98 tya ; get A.next + Tue Jun 13 1989 11:42 Page 199 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13364 91B4 9D 00 0C sta NEXTPNT,X ; [A.previous].next = A.next +13365 91B7 8A txa ; get A.previous +13366 91B8 99 40 0C sta PREVPNT,Y ; [A.next].previous = A.previous +13367 91BB 60 rts +13368 +13369 +13370 ; RETURN BUFFER OF PAGE [WANTED] +13371 ; IN >A< ELSE SEC (Y=WANTED+LO) +13372 +13373 91BC A2 17 WHERE: LDX #NUMBUFS-1 +13374 91BE WHLOOP: +13375 91BE AD A2 8F LDA WANTED+HI +13376 91C1 DD 80 0C CMP VPAGEH,X ;>SAME +13377 91C4 F0 05 BEQ WHGOT +13378 91C6 WHNOGOT: +13379 91C6 CA DEX +13380 91C7 10 F5 BPL WHLOOP +13381 91C9 38 SEC +13382 91CA 60 RTS +13383 91CB WHGOT: +13384 91CB 98 TYA +13385 91CC DD C0 0C CMP VPAGEL,X +13386 91CF D0 F5 BNE WHNOGOT +13387 91D1 8A TXA +13388 91D2 18 CLC +13389 91D3 60 RTS +13390 ; +13391 ; CHECKPRE - check to see if page in [A] is in preloaded +13392 ; +13393 91D4 CHECKPRE: +13394 91D4 C5 C2 cmp TBLPUR ; check against PURE tables +13395 91D6 90 0B bcc CHKPEXY ; must be preloaded then +13396 91D8 CHKP1: +13397 91D8 C5 C3 cmp FUNPRE ; is it in function preload? +13398 91DA 90 09 bcc CHKPEXN ; preloaded function > desired, not preloaded +13399 91DC C5 C4 cmp FUNPUR ; how bout at end? +13400 91DE B0 05 bcs CHKPEXN ; it is not preloaded +13401 91E0 CHKP3: +13402 91E0 18 clc ; doing add +13403 91E1 65 C5 adc FUNPGE ; get me memory page for function +13404 91E3 CHKPEXY: +13405 91E3 18 clc ; show it is preloaded +13406 91E4 60 rts ; then we got it +13407 91E5 CHKPEXN: +13408 91E5 38 sec ; show it ain't here +13409 91E6 60 rts +13410 ; +13411 ; INFO_PAGE - is it one of the special preloaded pages for infoDOS? If it +13412 ; is, then set up ZPCPNTR to point to it, and set carry. Otherwise, +13413 ; clear carry to show it ain't. +13414 91E7 IPAGE: ds 2 +13415 91E9 INFO_PAGE: +13416 91E9 A5 82 lda ZPCH ; get 2 parts +13417 91EB 8D E8 91 sta IPAGE+HI +13418 91EE A5 81 lda ZPCM +13419 91F0 8D E7 91 sta IPAGE+LO +13420 91F3 4E E8 91 lsr IPAGE+HI ; /2 to get 512 block +13421 91F6 6E E7 91 ror IPAGE+LO +13422 91F9 A0 08 ldy #SGTSEG ; point to first segment, MSB +13423 91FB B1 59 lda (INFODOS),Y ; howzit look? +13424 91FD C8 iny ; point to LSB +13425 91FE CD E8 91 cmp IPAGE+HI +13426 9201 90 0B bcc INFP1 ; might be interesting +13427 9203 D0 34 bne INFPNX ; not here, < than minimum +13428 9205 B1 59 lda (INFODOS),Y ; how bout LSB +13429 9207 CD E7 91 cmp IPAGE+LO +13430 920A F0 14 beq INFPYX ; found it +13431 920C B0 2B bcs INFPNX ; nope, < than minimum again +13432 ; +13433 ; here, it's at least > than minimum +13434 ; +13435 920E INFP1: +13436 ; iny ; point at end block, MSB +13437 920E AD D4 6C lda INFODOS_END+HI ; howz end segment look +13438 9211 CD E8 91 cmp IPAGE+HI + Tue Jun 13 1989 11:42 Page 200 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13439 9214 90 23 bcc INFPNX ; nope, > than maximum of special +13440 9216 D0 08 bne INFPYX ; yup, < than maximum of special +13441 ; iny ; LSB of last one +13442 9218 AD D3 6C lda INFODOS_END+LO ; is LSB < special? +13443 921B CD E7 91 cmp IPAGE+LO ; MSB of current one == MSB of special +13444 921E 90 19 bcc INFPNX ; nope, not here +13445 9220 INFPYX: +13446 9220 A0 09 ldy #SGTSEG+1 ; point back to start block, LSB +13447 9222 B1 59 lda (INFODOS),Y ; get start block +13448 9224 0A asl A ; *2 to get start page +13449 9225 8D E7 91 sta IPAGE+LO ; save it +13450 9228 A5 81 lda ZPCM +13451 922A 38 sec ; doing sub +13452 922B ED E7 91 sbc IPAGE+LO ; get offset into special block +13453 922E 18 clc ; now add in offset +13454 922F 69 D0 adc #>SP_START ; get the start of special area +13455 9231 85 84 sta ZPCPNT+HI ; show ZPCPNTR +13456 9233 A9 00 lda #SP_BANK ; which bank +13457 9235 85 85 sta ZPCBNK ; okey +13458 9237 38 sec ; show it was here +13459 9238 60 rts +13460 9239 INFPNX: +13461 9239 18 clc ; show not here +13462 923A 60 rts ; g'day +13463 923B +13464 923B +13465 923B +13466 923B CHKPEXN0: +13467 +13468 923B GETBYT: +13469 923B A4 86 ldy MPCL +13470 923D 20 BA 92 jsr MFETCH ; go and get it +13471 9240 E6 86 inc MPCL ;POINT TO NEXT BYTE +13472 9242 D0 0B bne GETGOT ;IF NO CROSS WE ARE STILL VALID +13473 9244 E6 87 inc MPCM +13474 9246 D0 02 bne GET1 +13475 9248 E6 88 inc MPCH +13476 924A GET1: +13477 924A 48 pha ; save byte +13478 924B 20 B2 90 jsr VLDMPC +13479 924E 68 pla ; and get it back +13480 924F GETGOT: +13481 924F A8 tay ;SET FLAGS +13482 9250 60 rts ;RED SLIPPER TIME +13483 ; +13484 ; NEXTPC - Fetch the byte at the current ZPC, point to next byte and +13485 ; validate pointer +13486 ; +13487 9251 NEXTPC: +13488 9251 A4 80 ldy ZPCL ; get low pointer +13489 9253 20 A2 92 jsr ZFETCH ; fetch @ZPCPNT +13490 9256 E6 80 inc ZPCL +13491 9258 D0 0B bne NXTGOT +13492 925A E6 81 inc ZPCM +13493 925C D0 02 bne CRSZ1 +13494 925E E6 82 inc ZPCH +13495 9260 CRSZ1: +13496 9260 48 pha ; save opcode +13497 9261 20 DC 90 jsr VLDZPC +13498 9264 68 pla ; and get it back +13499 9265 NXTGOT: +13500 9265 A8 tay +13501 9266 60 rts +13502 +13503 ; +13504 ; STASHB - use SPC to save a byte in either aux or main mem +13505 ; +13506 9267 STASHB: +13507 9267 A4 91 ldy SPCBNK ; get the bank +13508 9269 30 09 bmi SB1 ; must be in upper RAM +13509 926B 99 04 C0 sta WRTBNK,Y ; set bank +13510 926E A0 00 ldy #0 ; can only do this with Y +13511 9270 91 8F sta (SPC),Y ; get the sucker +13512 9272 F0 10 beq SBEXI ; jump to end it +13513 ; + Tue Jun 13 1989 11:42 Page 201 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13514 ; this is in aux mem, >$E000 +13515 ; +13516 9274 SB1: +13517 9274 A4 90 ldy SPCH ; get high part +13518 9276 8C 80 92 sty SBMOD+2 ; and self mod my code +13519 9279 A4 8F ldy SPCL ; and get the low part +13520 927B 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13521 927E SBMOD: +13522 927E 99 00 D0 sta Z3BEGIN,Y ; store the little byte +13523 9281 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13524 9284 SBEXI: +13525 9284 8D 04 C0 sta WRTBNK+MAIN ; and write to main +13526 9287 60 rts +13527 ; +13528 ; FETCHB - fetch a byte from either main memory, aux memory, or upper +13529 ; Aux memory +13530 ; +13531 9288 FETCHB: +13532 9288 A4 8E ldy FPCBNK ; get the bank +13533 928A 30 04 bmi FB1 ; must be in upper RAM +13534 928C 20 D1 00 jsr ZERO_FB ; go to low end fetch +13535 928F 60 rts +13536 ; +13537 ; this is in aux mem, >$E000 +13538 ; +13539 9290 FB1: +13540 9290 A5 8D lda FPCH ; get which page +13541 9292 8D 9C 92 sta FBMOD+2 ; and show in operand +13542 9295 A4 8C ldy FPCL ; get which byte +13543 9297 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13544 929A B9 00 D0 FBMOD: lda Z3BEGIN,Y ; get the sucker +13545 929D 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13546 92A0 A8 tay ; set condition code +13547 92A1 60 rts +13548 ; +13549 ; ZFETCH - after checking for which bank (main, aux 1 or aux 2), go get +13550 ; the byte @ ZPCPNT, with the offset being in [Y] +13551 ; +13552 92A2 ZFETCH: +13553 92A2 A6 85 ldx ZPCBNK ; get the bank +13554 92A4 30 04 bmi ZFB1 ; must be in upper RAM +13555 92A6 20 DC 00 jsr ZERO_ZF ; go to low end fetch +13556 92A9 60 rts +13557 ; +13558 ; this is in aux mem, >$D000 +13559 ; +13560 92AA ZFB1: +13561 92AA A5 84 lda ZPNTH ; which page are we talking about +13562 92AC 8D B4 92 sta ZBMOD+2 ; show in the operand +13563 92AF 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13564 92B2 B9 00 D0 ZBMOD: lda Z3BEGIN,Y ; get the sucker +13565 92B5 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13566 92B8 AA tax ; set condition code +13567 92B9 60 rts +13568 ; +13569 ; MFETCH - after checking for which bank (main, aux 1 or aux 2), go get +13570 ; the byte @MPCPNT, with the offset being in [Y] +13571 ; +13572 92BA MFETCH: +13573 92BA A6 8B ldx MPCBNK ; get the bank +13574 92BC 30 04 bmi MB1 ; must be in upper RAM +13575 92BE 20 E5 00 jsr ZERO_MF ; go to low end fetch +13576 92C1 60 rts +13577 ; +13578 ; this is in aux mem, >$D000 +13579 ; +13580 92C2 MB1: +13581 92C2 A5 8A lda MPNTH ; which page are we talking about +13582 92C4 8D CC 92 sta MBMOD+2 ; show in the operand +13583 92C7 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13584 +13585 92CA B9 00 D0 MBMOD: lda Z3BEGIN,Y ; get the sucker +13586 +13587 92CD 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13588 92D0 AA tax ; set condition code + Tue Jun 13 1989 11:42 Page 202 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13589 92D1 60 rts +13590 +13591 +13592 92D2 END +13593 +13594 92D2 INCLUDE ZSTRING.ASM +13595 PAGE + Tue Jun 13 1989 11:42 Page 203 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13596 92D2 STTL "--- Z-STRING HANDLERS ---" +13597 +13598 ; ----------------------- +13599 ; POINT MPC TO ZSTRING IN [I], using SOFF +13600 ; ----------------------- +13601 +13602 92D2 SETSTR: +13603 92D2 A5 78 lda I+LO +13604 92D4 85 86 sta MPCL ; save in lo part +13605 92D6 A5 79 lda I+HI +13606 92D8 85 87 sta MPCM ; middle part +13607 92DA A9 00 lda #0 ; clear hi part +13608 92DC 85 88 sta MPCH ; okay, we did +13609 92DE 06 86 asl MPCL ; *2 +13610 92E0 26 87 rol MPCM +13611 92E2 26 88 rol MPCH +13612 92E4 06 86 asl MPCL ; *4 +13613 92E6 26 87 rol MPCM +13614 92E8 26 88 rol MPCH +13615 ; +13616 ; now add the offset +13617 ; +13618 92EA A5 86 lda MPCL ; carry clear from above +13619 92EC 65 60 adc SOFFL ; add lo part of offset +13620 92EE 85 86 sta MPCL ; save +13621 92F0 A5 87 lda MPCM +13622 92F2 65 5F adc SOFFM +13623 92F4 85 87 sta MPCM +13624 92F6 A5 88 lda MPCH +13625 92F8 65 5E adc SOFFH +13626 92FA 85 88 sta MPCH +13627 92FC 4C B2 90 jmp VLDMPC ; make MPCPNT to it +13628 +13629 +13630 92FF 60 ZSTEX: RTS +13631 +13632 ; ----------------------- +13633 ; PRINT Z-STRING AT [MPC] +13634 ; ----------------------- +13635 9300 PZSTR: +13636 9300 A2 00 ldx #0 +13637 9302 86 96 stx PSET ; ASSUME PERMANENT CHARSET +13638 9304 86 9A stx ZFLAG ; CLEAR BYTE FLAG +13639 9306 CA dex ; = $FF +13640 9307 86 97 stx TSET ; NO TEMPSET ACTIVE +13641 9309 PZTOP: +13642 9309 20 FC 93 jsr GETZCH ; GET A Z-CHAR +13643 930C B0 F1 bcs ZSTEX ; END OF STRING IF CARRY IS SET +13644 930E 85 98 sta ZCHAR ; ELSE SAVE CHAR HERE +13645 9310 AA tax ; SET FLAGS +13646 9311 F0 45 beq BLANK ; PRINT SPACE IF CHAR = 0 +13647 9313 C9 04 cmp #4 ; IS THIS AN F-WORD? +13648 9315 90 5F bcc DOFREQ ; APPARENTLY SO +13649 9317 C9 06 cmp #6 ; PERHAPS A SHIFT CODE? +13650 9319 90 41 bcc NEWSET ; YES, CHANGE CHARSETS +13651 931B 20 DE 93 jsr GETSET ; ELSE GET CHARSET +13652 931E AA tax ; SET FLAGS +13653 931F D0 14 bne SET1 ; SKIP IF NOT CHARSET #0 +13654 ; +13655 ; PRINT A LOWER-CASE CHAR (CHARSET #0) +13656 ; +13657 9321 A9 FA lda #$FA ; what to add to get offset into char table +13658 9323 TOASC: +13659 9323 8D 2A 93 sta TOASCM+1 ; modify code +13660 9326 A5 98 lda ZCHAR ; use char as offset +13661 9328 18 clc ; make char be an index +13662 9329 69 06 TOASCM: adc #6 ; we just did +13663 932B AA tax ; now use as index +13664 932C BD 8C 1F lda CHARSET,X ; go get that char in charset zero +13665 932F SHOVE: +13666 932F 20 F5 52 jsr COUT ; SHOW THE CHAR +13667 9332 4C 09 93 jmp PZTOP ; AND GRAB NEXT CHAR +13668 ; +13669 ; PRINT AN UPPER-CASE CHAR (CHARSET #1) +13670 ; + Tue Jun 13 1989 11:42 Page 204 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13671 9335 SET1: +13672 9335 C9 01 cmp #1 ; make sure it's set #1 +13673 9337 D0 04 bne SET2 ; else must be set #2 +13674 9339 A9 14 lda #20 ; skip into Charset 1 part of table +13675 933B D0 E6 bne TOASC ; fix just like the others +13676 ; +13677 ; PRINT FROM CHARSET #2 +13678 ; +13679 933D SET2: +13680 933D A5 98 lda ZCHAR ; retrieve the z-char +13681 933F C9 06 cmp #6 ; is it a special ascii char? +13682 9341 F0 04 beq DIRECT ; yes, so do it special +13683 9343 A9 2E lda #46 ; nothing special, just get offset +13684 9345 D0 DC bne TOASC ; and jump +13685 ; +13686 ; DECODE A "DIRECT" ASCII CHAR +13687 ; +13688 9347 DIRECT: +13689 9347 20 FC 93 jsr GETZCH ; FETCH NEXT Z-CHAR +13690 934A 0A asl A +13691 934B 0A asl A +13692 934C 0A asl A +13693 934D 0A asl A +13694 934E 0A asl A ; SHIFT INTO POSITION +13695 934F 85 98 sta ZCHAR ; AND SAVE HERE +13696 9351 20 FC 93 jsr GETZCH ; GRAB YET ANOTHER Z-CHAR +13697 9354 05 98 ora ZCHAR ; SUPERIMPOSE THE 2ND BYTE +13698 9356 D0 D7 bne SHOVE ; AND PRINT THE RESULT +13699 ; +13700 ; PRINT A SPACE +13701 ; +13702 9358 BLANK: +13703 9358 A9 20 lda #SPACE ; ASCII SPACE CHAR +13704 935A D0 D3 bne SHOVE +13705 +13706 ; CHANGE CHARSET +13707 +13708 935C 38 NEWSET: SEC ; CONVERT THE SHIFT CODE +13709 935D E9 03 SBC #3 ; TO 1 OR 2 +13710 935F A8 TAY +13711 9360 20 DE 93 JSR GETSET ; IS MODE TEMPORARY? +13712 9363 D0 05 BNE TOPERM ; YES, DO A PERMSHIFT +13713 9365 84 97 STY TSET ; ELSE JUST A TEMPSHIFT +13714 9367 4C 09 93 JMP PZTOP ; AND CONTINUE +13715 936A 84 96 TOPERM: STY PSET ; SET PERM CHARSET +13716 936C C5 96 CMP PSET ; SAME AS BEFORE? +13717 936E F0 99 BEQ PZTOP ; YES, CONTINUE +13718 9370 A9 00 LDA #0 +13719 9372 85 96 STA PSET ; ELSE RESET CHARSET +13720 9374 F0 93 BEQ PZTOP ; BEFORE LOOPING BACK +13721 +13722 ; PRINT AN F-WORD +13723 +13724 9376 38 DOFREQ: SEC +13725 9377 E9 01 SBC #1 ; ZERO-ALIGN THE CODE +13726 9379 0A ASL A ; AND MULTIPLY TIMES 64 +13727 937A 0A ASL A ; TO OBTAIN THE SEGMENT OFFSET +13728 937B 0A ASL A ; INTO THE F-WORDS TABLE +13729 937C 0A ASL A +13730 937D 0A ASL A +13731 937E 0A ASL A +13732 937F 85 99 STA OFFSET ; SAVE OFFSET FOR LATER +13733 9381 20 FC 93 JSR GETZCH ; NOW GET THE F-WORD POINTER +13734 9384 0A ASL A ; WORD-ALIGN IT +13735 9385 18 CLC ; AND +13736 9386 65 99 ADC OFFSET ; ADD THE SEGMENT OFFSET +13737 ; +13738 ; set up FPC to point to FWORDS table +13739 ; +13740 9388 A6 57 ldx FWORDS+ABANK +13741 938A 86 8E stx FPCBNK +13742 938C A6 56 ldx FWORDS+HI +13743 938E 86 8D stx FPCH +13744 9390 A6 55 ldx FWORDS+LO +13745 9392 86 8C stx FPCL + Tue Jun 13 1989 11:42 Page 205 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13746 9394 20 10 90 jsr ADDFPC ; add offset of the F-word +13747 9397 20 88 92 jsr FETCHB ; and get MSB of F-word +13748 939A 85 79 sta I+HI ; and save it +13749 939C 20 F0 8F jsr NEXTFPC ; and point to LSB +13750 939F 20 88 92 jsr FETCHB ; and get it +13751 93A2 85 78 sta I+LO ; and save it +13752 ; +13753 ; SAVE THE STATE OF CURRENT Z-STRING +13754 ; +13755 93A4 A5 88 LDA MPCH +13756 93A6 48 PHA +13757 93A7 A5 87 LDA MPCM +13758 93A9 48 PHA +13759 93AA A5 86 LDA MPCL +13760 93AC 48 PHA +13761 93AD A5 96 LDA PSET +13762 93AF 48 PHA +13763 93B0 A5 9A LDA ZFLAG +13764 93B2 48 PHA +13765 93B3 A5 9C LDA ZWORD+HI +13766 93B5 48 PHA +13767 93B6 A5 9B LDA ZWORD+LO +13768 93B8 48 PHA +13769 93B9 20 EA 93 JSR SETFWD ; PRINT THE Z-STRING +13770 93BC 20 00 93 JSR PZSTR ; IN [I] +13771 ; +13772 ; RESTORE OLD Z-STRING +13773 ; +13774 93BF 68 PLA +13775 93C0 85 9B STA ZWORD+LO +13776 93C2 68 PLA +13777 93C3 85 9C STA ZWORD+HI +13778 93C5 68 PLA +13779 93C6 85 9A STA ZFLAG +13780 93C8 68 PLA +13781 93C9 85 96 STA PSET +13782 93CB 68 PLA +13783 93CC 85 86 STA MPCL +13784 93CE 68 PLA +13785 93CF 85 87 STA MPCM +13786 93D1 68 PLA +13787 93D2 85 88 STA MPCH +13788 93D4 A2 FF LDX #$FF +13789 93D6 86 97 STX TSET ; DISABLE TEMP CHARSET +13790 93D8 20 B2 90 JSR VLDMPC +13791 93DB 4C 09 93 JMP PZTOP ; CONTINUE INNOCENTLY +13792 +13793 +13794 ; ---------------------- +13795 ; RETURN CURRENT CHARSET +13796 ; ---------------------- +13797 +13798 93DE A5 97 GETSET: LDA TSET +13799 93E0 10 03 BPL GS +13800 93E2 A5 96 LDA PSET +13801 93E4 60 RTS +13802 93E5 A0 FF GS: LDY #$FF +13803 93E7 84 97 STY TSET +13804 93E9 60 RTS +13805 +13806 +13807 ; ------------------------- +13808 ; POINT [I] AT FWORD STRING +13809 ; ------------------------- +13810 +13811 93EA A5 78 SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS +13812 93EC 0A ASL A +13813 93ED 85 86 STA MPCL +13814 93EF A5 79 LDA I+HI +13815 93F1 2A ROL A +13816 93F2 85 87 STA MPCM +13817 93F4 A9 00 LDA #0 +13818 93F6 2A ROL A +13819 93F7 85 88 STA MPCH +13820 93F9 4C B2 90 JMP VLDMPC + Tue Jun 13 1989 11:42 Page 206 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13821 +13822 +13823 ; ----------------- +13824 ; FETCH NEXT Z-CHAR +13825 ; ----------------- +13826 +13827 93FC A5 9A GETZCH: LDA ZFLAG ; WHICH BYTE IS THIS? +13828 93FE 10 02 BPL GTZ0 ; $FF = LAST +13829 9400 38 SEC ; SET CARRY TO INDICATE +13830 9401 60 RTS ; NO MORE CHARS +13831 9402 D0 13 GTZ0: BNE GETZ1 ; NOT FIRST CHAR, EITHER +13832 +13833 ; GET A Z-WORD INTO [ZWORD], RETURN 1ST CHAR IN TRIPLET +13834 +13835 9404 E6 9A INC ZFLAG ; UPDATE CHAR COUNT +13836 9406 20 3B 92 JSR GETBYT ; GET TRIPLET AT [MPC] +13837 9409 85 9C STA ZWORD+HI ; INTO [ZWORD] +13838 940B 20 3B 92 JSR GETBYT +13839 940E 85 9B STA ZWORD+LO +13840 9410 A5 9C LDA ZWORD+HI +13841 9412 4A LSR A +13842 9413 4A LSR A ; SHIFT 1ST CHAR INTO PLACE +13843 9414 4C 40 94 JMP GTEXIT ; AND RETURN IT +13844 9417 38 GETZ1: SEC +13845 9418 E9 01 SBC #1 +13846 941A D0 16 BNE GETZ2 ; LAST CHAR IN TRIPLET IF ZERO +13847 941C A9 02 LDA #2 ; ELSE +13848 941E 85 9A STA ZFLAG ; RESET CHAR INDEX +13849 9420 A5 9B LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET +13850 9422 85 78 STA I+LO ; MOVE HERE FOR SHIFTING +13851 9424 A5 9C LDA ZWORD+HI ; GET TOP HALF +13852 9426 06 78 ASL I+LO ; SHIFT THE TOP 3 BITS OF LOWER HALF +13853 9428 2A ROL A ; INTO THE BOTTOM OF THE TOP HALF +13854 9429 06 78 ASL I+LO +13855 942B 2A ROL A +13856 942C 06 78 ASL I+LO +13857 942E 2A ROL A +13858 942F 4C 40 94 JMP GTEXIT +13859 9432 A9 00 GETZ2: LDA #0 ; SET FLAG TO INDICATE +13860 9434 85 9A STA ZFLAG ; END OF TRIPLET +13861 9436 A5 9C LDA ZWORD+HI ; TEST TOP HALF OF TRIPLET +13862 9438 10 04 BPL GETZ3 ; CONTINUE IF NOT END OF STRING +13863 943A A9 FF LDA #$FF ; ELSE +13864 943C 85 9A STA ZFLAG ; INDICATE LAST TRIPLET IN STRING +13865 943E A5 9B GETZ3: LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET +13866 9440 29 1F GTEXIT: AND #%00011111 ; MASK OUT GARBAGE BITS +13867 9442 18 CLC +13868 9443 60 RTS +13869 +13870 +13871 ; --------------------------------- +13872 ; CONVERT [IN] TO Z-STRING IN [OUT] +13873 ; --------------------------------- +13874 9444 CONZST: +13875 9444 A9 05 lda #5 ; FILL OUTPUT BUFFER +13876 9446 A2 08 ldx #8 ; WITH PAD CHARS ($05) +13877 9448 CZSL: +13878 9448 9D C7 6C sta OUT,X +13879 944B CA dex +13880 944C 10 FA bpl CZSL +13881 +13882 944E A9 09 lda #9 ; INIT +13883 9450 85 9D sta CONCNT ; CHAR COUNT +13884 9452 A9 00 lda #0 ; CLEAR +13885 9454 85 9E sta CONIN ; SOURCE AND +13886 9456 85 9F sta CONOUT ; OUTPUT INDEXES +13887 9458 CONTOP: +13888 9458 A6 9E ldx CONIN ; fetch source index +13889 945A E6 9E inc CONIN ; and update +13890 945C BD BE 6C lda IN,X ; grab an ascii char +13891 945F 85 98 sta ZCHAR ; save it here +13892 9461 D0 04 bne NEXTZ ; continue if char was nz +13893 9463 A9 05 lda #5 ; else ship out +13894 9465 D0 27 bne CSHIP1 ; a pad char +13895 9467 NEXTZ: + Tue Jun 13 1989 11:42 Page 207 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13896 9467 20 93 94 jsr FINDCHAR ; find out where it tis +13897 946A F0 21 beq CSHIP ; no shift for charset zero +13898 946C 18 clc ; else do a temp-shift +13899 946D 69 03 adc #3 ; 4 = charset 1, 5 = charset 2 +13900 946F 20 C1 94 jsr CSTASH ; save the char in outbuf +13901 9472 C9 05 cmp #5 ; charset 2? +13902 9474 D0 17 bne CSHIP ; nope +13903 9476 E0 06 cpx #6 ; ascii escape? +13904 9478 D0 13 bne CSHIP ; nope +13905 ; +13906 ; Handle special Ascii escape sequence +13907 ; +13908 947A 8A txa ; get ASCII alert char (#6) +13909 947B 20 C1 94 jsr CSTASH ; shove it away +13910 ; +13911 ; do 1st half of "direct" +13912 ; +13913 947E A5 98 lda ZCHAR ; re-fetch char +13914 9480 4A lsr A ; get upper 2 bits in lower 2 bits +13915 9481 4A lsr A +13916 9482 4A lsr A +13917 9483 4A lsr A +13918 9484 4A lsr A +13919 9485 20 C1 94 jsr CSTASH +13920 ; +13921 ; SEND 2ND HALF OF "DIRECT" +13922 ; +13923 9488 A5 98 lda ZCHAR ; get char yet again +13924 948A 29 1F and #%00011111 ; and get lower 5 bits +13925 948C AA tax ; this is where it is expected +13926 ; +13927 ; SHIP Z-CHAR TO OUTPUT BUFFER +13928 ; +13929 948D CSHIP: +13930 948D 8A txa ; get char +13931 948E CSHIP1: +13932 948E 20 C1 94 jsr CSTASH ; put char away +13933 9491 D0 C5 bne CONTOP ; do again +13934 ; +13935 ; FINDCHAR - look through the charset table for the character. If found, +13936 ; figger out which shift it is. If not found, return charset 2, +13937 ; character #6. +13938 ; Enter: +13939 ; [A] = Char we are looking for +13940 ; Returns: +13941 ; [A] = Charset (0-2) +13942 ; [X] = Character # (6-31) +13943 ; +13944 9493 FINDCHAR: +13945 9493 A2 00 ldx #0 ; start at first char, first set +13946 9495 A0 4E ldy #78 ; there are 78 characters +13947 9497 FNDCL: +13948 9497 DD 8C 1F cmp CHARSET,X ; found it? +13949 949A F0 09 beq FNDCLX ; yes +13950 949C E8 inx ; next char +13951 949D 88 dey ; count char +13952 949E D0 F7 bne FNDCL ; go check next char +13953 ; +13954 ; not found in table, use ASCII escape sequence +13955 ; +13956 94A0 A9 02 lda #2 ; escape sequence is char set 2 +13957 94A2 A2 06 ldx #6 ; character 6 +13958 94A4 60 rts ; and done +13959 94A5 FNDCLX: +13960 94A5 8A txa ; put here for compares/action +13961 94A6 A0 00 ldy #0 ; this is char set 0 +13962 94A8 A2 FA ldx #$FA ; what to "subtract" to get +6 +13963 94AA C9 1A cmp #26 ; how we doin'? +13964 94AC 90 0A bcc FNDCHX ; all done +13965 94AE C8 iny ; char set 1 +13966 94AF A2 14 ldx #20 ; char set 1 offset +13967 94B1 C9 34 cmp #52 ; well? +13968 94B3 90 03 bcc FNDCHX ; must be char set 1 +13969 94B5 A2 2E ldx #46 ; for char set 2 setting up +13970 94B7 C8 iny ; must be char set 2 then + Tue Jun 13 1989 11:42 Page 208 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13971 94B8 FNDCHX: +13972 94B8 8E BD 94 stx FNDCHM+1 ; what to subtract to get offset +13973 94BB 38 sec ; doing subtract +13974 94BC E9 06 FNDCHM: sbc #6 ; make good offset +13975 94BE AA tax ; put here for return +13976 94BF 98 tya ; and here to set flag +13977 94C0 60 rts +13978 ; +13979 ; CSTASH - put the char in OUT. If we run out of room don't return, just +13980 ; jump to ZCRUSH as final destination +13981 ; [A] - char to be put away +13982 ; +13983 94C1 CSTASH: +13984 94C1 A4 9F ldy CONOUT ; fetch output index +13985 94C3 99 C7 6C sta OUT,Y ; send the shift char +13986 94C6 E6 9F inc CONOUT ; update index +13987 94C8 C6 9D dec CONCNT ; and char count +13988 94CA D0 05 bne CSTX ; plenty more room +13989 94CC 68 pla ; get rid of return spot +13990 94CD 68 pla ; fine +13991 94CE 4C D2 94 jmp ZCRUSH ; if out of room, crush 'em! +13992 94D1 CSTX: +13993 94D1 60 rts +13994 ; ---------------------- +13995 ; CRUSH Z-CHARS IN [OUT], mushing them into small 5 bit pieces +13996 ; ---------------------- +13997 94D2 ZCRUSH: +13998 94D2 AD C8 6C LDA OUT+1 ; GET 2ND Z-CHAR +13999 94D5 0A ASL A ; SHIFT BITS INTO POSITION +14000 94D6 0A ASL A +14001 94D7 0A ASL A +14002 94D8 0A ASL A +14003 94D9 2E C7 6C ROL OUT ; ALONG WITH 1ST Z-CHAR +14004 94DC 0A ASL A +14005 94DD 2E C7 6C ROL OUT +14006 94E0 0D C9 6C ORA OUT+2 ; SUPERIMPOSE 3RD Z-CHAR +14007 94E3 8D C8 6C STA OUT+1 +14008 94E6 AD CB 6C LDA OUT+4 ; GET 5TH Z-CHAR +14009 94E9 0A ASL A ; SHIFT BITS +14010 94EA 0A ASL A +14011 94EB 0A ASL A +14012 94EC 0A ASL A +14013 94ED 2E CA 6C ROL OUT+3 ; ALONG WITH 4TH Z-CHAR +14014 94F0 0A ASL A +14015 94F1 2E CA 6C ROL OUT+3 +14016 94F4 0D CC 6C ORA OUT+5 ; SUPERIMPOSE 6TH Z-CHAR +14017 94F7 AA TAX ; SAVE HERE +14018 94F8 AD CA 6C LDA OUT+3 ; GRAB 4TH Z-CHAR +14019 94FB 8D C9 6C STA OUT+2 ; MOVE CRUSHED Z-WORD +14020 94FE 8E CA 6C STX OUT+3 ; INTO PLACE +14021 9501 AD CE 6C LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) +14022 9504 0A ASL A ; SHIFT BITS +14023 9505 0A ASL A +14024 9506 0A ASL A +14025 9507 0A ASL A +14026 9508 2E CD 6C ROL OUT+6 ; ALONG WITH 7TH Z-CHAR +14027 950B 0A ASL A +14028 950C 2E CD 6C ROL OUT+6 +14029 950F 0D CF 6C ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR +14030 9512 8D CC 6C STA OUT+5 ; SAVE HERE +14031 9515 AD CD 6C LDA OUT+6 ; GRAB 7TH Z-CHAR +14032 9518 09 80 ORA #%10000000 ; SET HIGH BIT +14033 951A 8D CB 6C STA OUT+4 ; MOVE CRUSHED Z-WORD INTO PLACE +14034 951D 60 RTS +14035 +14036 951E END +14037 +14038 951E INCLUDE OBJECTS.ASM +14039 951E STTL "--- OBJECT & PROPERTY HANDLERS ---" +14040 PAGE + Tue Jun 13 1989 11:42 Page 209 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + +14041 +14042 ; ---------------------------------- +14043 ; GET ABSOLUTE ADDRESS OF OBJECT [A] +14044 ; ---------------------------------- +14045 ; ENTER: OBJECT IN A/X (LO/HI) +14046 ; EXIT: ADDRESS IN [FPC] +14047 951E OBJLOC: +14048 951E 86 79 STX I+HI ; SAVE MSB FOR SHIFTING +14049 9520 0A ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) +14050 9521 85 78 STA I+LO +14051 9523 26 79 ROL I+HI +14052 9525 A6 79 LDX I+HI +14053 9527 0A ASL A +14054 9528 26 79 ROL I+HI ; *4 +14055 952A 0A ASL A +14056 952B 26 79 ROL I+HI ; *8 +14057 952D 0A ASL A +14058 952E 26 79 ROL I+HI ; *16 +14059 9530 38 SEC +14060 9531 E5 78 SBC I+LO ; -(*2) +14061 9533 85 78 STA I+LO ; SO IS *14 TOTAL +14062 9535 A5 79 LDA I+HI +14063 9537 86 79 STX I+HI +14064 9539 E5 79 SBC I+HI +14065 953B 85 79 STA I+HI +14066 953D A5 78 LDA I+LO +14067 953F 18 CLC +14068 9540 69 70 ADC #112 ; ADD OBJECT TABLE OFFSET +14069 9542 90 02 BCC OBJ3 +14070 9544 E6 79 INC I+HI +14071 9546 OBJ3: +14072 9546 18 clc ; NEXT ADD THE relative ADDR +14073 9547 6D 0B 96 adc ZBEGIN+ZOBJEC+1 ; OF THE OBJECT TABLE +14074 954A 85 8C sta FPCL ; save lo byte +14075 954C A5 79 lda I+HI +14076 954E 6D 0A 96 adc ZBEGIN+ZOBJEC ; now work on page +14077 9551 20 A9 8F jsr SETPC ; now get page/bank +14078 9554 85 8D sta FPCH ; this is hi part +14079 9556 84 8E sty FPCBNK ; and this is the bank +14080 9558 60 rts +14081 ; ----------------------------- +14082 ; GET ADDRESS OF PROPERTY TABLE +14083 ; ----------------------------- +14084 ; EXIT: [FPC] HAS ABSOLUTE ADDR OF PROPERTY TABLE +14085 ; including OFFSET TO START OF PROP IDS +14086 9559 PROPB: +14087 9559 A5 63 lda ARG1+LO +14088 955B A6 64 ldx ARG1+HI ; get address +14089 955D 20 1E 95 jsr OBJLOC ; put table location into FPC +14090 9560 A9 0C lda #12 ; add 12 to get to beginning +14091 9562 20 10 90 jsr ADDFPC ; and add it to FPC +14092 9565 20 88 92 jsr FETCHB ; get MSB of P-TABLE Address +14093 9568 48 pha ; and save it for a moment +14094 9569 20 F0 8F jsr NEXTFPC ; to get LSB +14095 956C 20 88 92 jsr FETCHB ; get LSB of P-TABLE Address +14096 956F 85 8C sta FPCL ; and save lo part +14097 9571 68 pla ; get page back +14098 9572 20 A9 8F jsr SETPC ; and set up memory bank/page +14099 9575 85 8D sta FPCH ; save page +14100 9577 84 8E sty FPCBNK ; and bank +14101 9579 20 88 92 jsr FETCHB ; get length of short description +14102 957C 0A asl A ; WORD-ALIGN IT +14103 957D 20 10 90 jsr ADDFPC ; and add it to FPC +14104 9580 20 F0 8F jsr NEXTFPC ; POINT JUST PAST THE DESCRIPTION +14105 9583 60 rts +14106 +14107 +14108 ; ------------------- +14109 ; FETCH A PROPERTY ID +14110 ; ------------------- +14111 ; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +14112 ; +14113 9584 PROPN: +14114 9584 20 88 92 jsr FETCHB ; get the byte +14115 9587 29 3F and #%00111111 ; MASK OUT LENGTH BITS (EZIP) + Tue Jun 13 1989 11:42 Page 210 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + +14116 9589 60 rts +14117 +14118 ; ------------------------------- +14119 ; FETCH # BYTES IN PROPERTY VALUE +14120 ; ------------------------------- +14121 ; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +14122 ; +14123 958A PROPL: +14124 958A 20 88 92 jsr FETCHB ; CHECK LENGTH FLAGS +14125 958D AA tax ; save it +14126 958E 10 09 bpl SHORT ; OFF, SO 1 OR 2 BYTES +14127 9590 20 F0 8F jsr NEXTFPC +14128 9593 20 88 92 jsr FETCHB ; NEXT BYTE HAS LENGTH +14129 9596 29 3F and #%00111111 ; MASK OFF EXTRA BITS +14130 9598 60 rts +14131 9599 SHORT: +14132 9599 29 40 and #%01000000 ; BIT 6 +14133 959B F0 03 beq ONE +14134 959D A9 02 lda #2 ; BIT 6 = 1, LENGTH =2 +14135 959F 60 rts +14136 95A0 ONE: +14137 95A0 A9 01 lda #1 ; BIT 6 = 0, LENGTH =1 +14138 95A2 60 rts +14139 +14140 ; ---------------------- +14141 ; POINT TO NEXT PROPERTY +14142 ; ---------------------- +14143 ; ENTRY: LIKE "PROPB" EXIT (i.e. - in [FPC]) +14144 ; +14145 95A3 PROPNX: +14146 95A3 20 8A 95 jsr PROPL ; GET LENGTH OF CURRENT PROP +14147 95A6 A8 tay ; move one more for correct alignment +14148 95A7 C8 iny ; okay, done it +14149 95A8 98 tya ; thanks +14150 95A9 20 10 90 jsr ADDFPC ; add to [FPC] +14151 95AC 60 rts +14152 ; +14153 ; ---------------- +14154 ; GET OBJECT FLAGS +14155 ; ---------------- +14156 ; ENTRY: OBJECT # IN [ARG1], FLAG # IN [ARG2] +14157 ; EXIT: FLAG WORD IN [K], BIT ID IN [J], +14158 ; FLAG WORD ADDRESS IN [FPC] +14159 ; +14160 95AD FLAGSU: +14161 95AD A5 63 LDA ARG1+LO ; get table offset +14162 95AF A6 64 LDX ARG1+HI +14163 95B1 20 1E 95 JSR OBJLOC ; GET OBJECT ADDR IN [FPC] +14164 95B4 A5 65 LDA ARG2+LO ; LOOK AT FLAG ID +14165 95B6 C9 10 CMP #$10 ; FIRST SET OF FLAGS? +14166 95B8 90 14 BCC FLS1 ; YES, ADDR IN [FPC] IS CORRECT +14167 95BA E9 10 SBC #16 ; ELSE ZERO-ALIGN FLAG INDEX +14168 95BC AA TAX ; SAVE IT HERE +14169 95BD C9 10 CMP #$10 ; CHECK IF IN 2ND WORD +14170 95BF 90 07 BCC FLS ; YES, GO ALIGN FOR THAT +14171 95C1 E9 10 SBC #16 ; ELSE ALIGN TO 3RD WORD +14172 95C3 AA TAX +14173 95C4 A9 04 lda #4 ; 3rd Flag word +14174 95C6 D0 02 bne FLSx ; and add it in +14175 95C8 FLS: +14176 95C8 A9 02 lda #2 ; 2nd Flag word +14177 95CA FLSx: +14178 95CA 20 10 90 jsr ADDFPC +14179 95CD FLS0: +14180 95CD 8A TXA ; RESTORE INDEX +14181 95CE FLS1: +14182 95CE 85 7C STA K+LO ; SAVE FLAG ID HERE +14183 95D0 A2 01 LDX #1 ; INIT THE +14184 95D2 86 7A STX J+LO ; FLAG WORD TO +14185 95D4 CA DEX ; $0001 +14186 95D5 86 7B STX J+HI +14187 95D7 A9 0F LDA #15 ; SUBTRACT THE BIT POSITION +14188 95D9 38 SEC ; FROM 15 +14189 95DA E5 7C SBC K+LO ; TO GET THE SHIFT LOOP +14190 95DC AA TAX ; INDEX + Tue Jun 13 1989 11:42 Page 211 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + +14191 95DD F0 07 BEQ FLS2 ; EXIT NOW IF NO SHIFT NEEDED +14192 95DF 06 7A FLSL: ASL J+LO ; SHIFT THE BIT +14193 95E1 26 7B ROL J+HI ; INTO POSITION +14194 95E3 CA DEX +14195 95E4 D0 F9 BNE FLSL +14196 95E6 FLS2: +14197 95E6 20 88 92 jsr FETCHB ; MOVE THE FLAG WORD +14198 95E9 85 7D sta K+HI ; INTO [K] - FIRST THE MSB +14199 95EB 20 F0 8F jsr NEXTFPC ; and then get get LSB +14200 95EE 20 88 92 jsr FETCHB +14201 95F1 85 7C sta K+LO ; THEN THE LSB +14202 95F3 4C 56 90 jmp PREVFPC ; point back to flag word +14203 +14204 95F6 END +14205 +14206 +14207 95F6 BLKB ZBEGIN-$,0 +14208 9600 END + + + + Lines Assembled : 14208 Assembly Errors : 0 + + + \ No newline at end of file diff --git a/apple/yzip/rel.15/zbegin.asm b/apple/yzip/rel.15/zbegin.asm new file mode 100644 index 0000000..0f6ff06 --- /dev/null +++ b/apple/yzip/rel.15/zbegin.asm @@ -0,0 +1,100 @@ + STTL "--- START OF APPLE ][ INTERPRETER ---" + PAGE + + ORG INTR_BEGIN +; +; Set up for Double HiRes full screen graphics +; + lda PAGE2SW+OFF ; turn off page 2 + sta TEXTSW+OFF ; turn off text - turn on graphics + sta HIRESSW+ON ; turn on high resolution + sta MIXEDSW+OFF ; full screen graphics + sta COL80SW+ON ; turn on 80 column + sta IOUDIS+OFF ; turn ON (it too is backwards) Dhires switch + sta DHIRESW+OFF ; turn ON (it's backwards!) Dhires + + sta STORE80+ON ; turn on aux page display ability + lda BNK2SET ; read/write RAM, bank 2 + lda BNK2SET +; +; copy in progame from boot code +; + ldx #0 ; start at first letter +MVPRE: + lda BORG+3,X ; get letter + beq MVPREX ; all done + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + sta GAME,X ; save for asking about later + inx ; next letter + bne MVPRE ; do gen +MVPREX: + stx GAMEL ; save length of game name + lda #'.' ; get extension for names + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + inx ; next letter + lda #'D' ; for data segments + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + inx ; points to number + inx ; inclusive count for length + stx GAME1NML ; save length of name + stx GAME2NML ; save length of name + + lda #VERSID ; put in version number + sta ZBEGIN+ZINTWD+1 + + inc ZSP+LO ; INIT Z-STACK POINTERS + inc OLDZSP+LO ; TO "1" + inc SCREENF ; TURN DISPLAY ON + inc SCRIPT ; enable scripting + inc CRLF_CHECK ; do CR functino check + + lda WINTABLE+LO ; set WINDOW to point to window 0 + sta WINDOW+LO + lda WINTABLE+HI + sta WINDOW+HI ; okay, it does + + lda ARG1+LO ; using mouse? + beq ZBEGIN1 ; nope + ora #$78 ; point to correct screen holes + sta MSFIX0+1 + sta MSFIX1+1 ; and modify code to point to correct spot + sta MSFIX2+1 + lda ARG1+LO + ora #$F8 ; and one more + sta MSFIX2+1 +ZBEGIN1: + lda #$FF ; do a clear -1 to start off + sta ARG1+LO ; so arg 1 is this + jsr ZCLR ; doing it + + GET_PREFIX GPRE_PB ; get where we are to start + + lda D2SEG+HI ; start DSEGS at .D2 + sta DSEGS+HI + lda D2SEG+LO + sta DSEGS+LO + + lda #1 ; open game file .D2 please + jsr FETCH_FILE ; we did that + lda INFODOS ; are we on little dos? + beq ZBEGIN2 ; nope + jsr GET_SPECIAL ; do special preloading if so +ZBEGIN2: + lda D3SEG+HI ; this is cuz we be openin' .D3 + sta DSEGS+HI + lda D3SEG+LO + sta DSEGS+LO + lda #2 ; and just for giggles, do the + jsr FETCH_FILE ; same for game file .D3 + + jsr VLDZPC ; MAKE ZPC VALID + jsr NEXTPC ; skip over # of locals + + ; ... AND FALL INTO MAIN LOOP + + END + + diff --git a/apple/yzip/rel.15/zboot.asm b/apple/yzip/rel.15/zboot.asm new file mode 100644 index 0000000..c99e5d4 --- /dev/null +++ b/apple/yzip/rel.15/zboot.asm @@ -0,0 +1,261 @@ + PAGE + STTL "--- ZIP CODE BOOT PART ---" +ZBOOT: +; +; clear out ZERO page stuff +; + lda ARG2+LO ; get machine id! + sta ZBEGIN+ZINTWD ; save before it gets zeroed + + ldx #LASTWV-1 ; start at end of first part + lda #0 ; and clear to zero +ZEROL: + sta 0,X ; clear out zero page loc + dex ; next loc + bpl ZEROL ; and do next one + + ldx #ZEROPG ; now do other part +ZEROL1: + sta 0,X ; zero this one + inx ; point to next one + cpx #LASTZP ; find the last + bne ZEROL1 ; okay, so do it +; +; get game code from data and set up absolute pointers +; + lda ZBEGIN+ZVERS ; IS GAME A YZIP? + cmp #6 ; (X) + beq YESEZ ; YES, CONTINUE + +; *** ERROR #15 -- NOT AN EZIP GAME *** + lda #15 + ldy #0 + jmp ZERROR +YESEZ: + lda #%00111011 ; ENABLE SOUND, underline, MONOSPACING (X) + sta ZBEGIN+ZMODE + + lda #0 ; CLEAR HIGH BYTE + sta MOUSEF ; init mouse flag to no mouse + sta ZBEGIN+ZHWRD + sta ZBEGIN+ZVWRD + lda #MAXWIDTH ; SET SCREEN PARAMETERS + sta ZBEGIN+ZHWRD+1 + lda #MAXWIDTH/3 ; number of mono spaces on a line + sta ZBEGIN+ZSCRWD+1 + lda #MAXHEIGHT + sta ZBEGIN+ZVWRD+1 + lda #MAXHEIGHT/FONT_H + sta ZBEGIN+ZSCRWD ; number of lines of chars + lda #FONT_H ; height of font + sta ZBEGIN+ZFWRD + lda #3 ; width of font (2 spaces == 8 pixels) + sta ZBEGIN+ZFWRD+1 + lda #9 ; the color white is the foreground color + sta ZBEGIN+ZCLRWD+1 ; show Z game too + lda #2 ; black is the background color + sta ZBEGIN+ZCLRWD ; tell game about it +; +; just move global address to zero page for quick working +; + lda ZBEGIN+ZGLOBAL ; get page + sta GLOBAL+HI ; save which page + lda ZBEGIN+ZGLOBAL+1 ; LSB NEEDN'T CHANGE + sta GLOBAL+LO ; so just store it away +; +; figger absolute address for the fword table +; + lda ZBEGIN+ZFWORD ; get fword page number + jsr SETPC ; and get absolute address + sta FWORDS+HI ; show high addr of table + sty FWORDS+ABANK ; show which bank + lda ZBEGIN+ZFWORD+1 ; LSB NEEDN'T CHANGE + sta FWORDS+LO ; so just save it +; +; figger absolute address for the vocab table +; + lda ZBEGIN+ZVOCAB ; get fword page number + jsr SETPC ; and get absolute address + sta VOCAB+HI ; show high addr of table + sty VOCAB+ABANK ; show which bank + lda #0 ; this is always zero (get lo part from MPCL) + sta VOCAB+LO ; so just save it +; +; now do somethin' with the TCHAR table (maybe, if <> 0) +; + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + ora ZBEGIN+ZTCHAR+1 ; is it zero though? + bne TCH1 ; no, so copy it to somewhere useful + sta TCHARTBL ; not there, so zero first byte in table + beq TCHj ; jmp +TCH1: + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + jsr SETPC ; and now make absolute + sta FPCH ; Save in FPC + sty FPCBNK + lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + sta FPCL ; now move pointer to fetch spot + + lda #0 ; and set index + sta I ; thank you +TCHLP: + jsr FETCHB ; get the byte in [a] + ldx I ; get offset + inc I ; and point to next one + sta TCHARTBL,X ; save in lower memory, thank you + cmp #0 ; are we done yet? + beq TCHj ; NULL TERMINATED STRING + cmp #$FF ; $ff means all >128 chars are terminators + bne TCHLNEXT ; nope + lda #1 ; yes, + sta ALLFLG ; so set flag to say so +TCHLNEXT: + jsr NEXTFPC ; point to next one + jmp TCHLP ; and go get it +TCHj: + jsr DO_DSEGS ; set up disk segment pointers +; +; use mouse/joystick, see if either is connected +; + lda ZBEGIN+ZFLAGS+1 ; get game flags + and #FMOUS ; uses a mouse? + beq ZBEND ; nope, so don't ask + jsr MHOME ; clear & home +MSLOOP: + DLINE MMSG ; ask about Mouse/Joystick/Keyboard + lda #1 ; move to left + sta CHZ ; move to column 1 + jsr MBASCAL ; move cursor there! + lda #EOL.OR.$80 ; send out eol + jsr MCOUT ; bye + jsr MRDKEY ; get a key please + jsr MCOUT ; put key out there + and #$7F ; turn off hi bit + cmp #'M' ; mouse? + beq DO_MOUSE ; yup + cmp #'m' + beq DO_MOUSE + cmp #'J' ; Joystick? + beq DO_STICK ; yup + cmp #'j' + beq DO_STICK + cmp #'N' ; neither + beq DO_NEITHER ; yup + cmp #'n' + beq DO_NEITHER +MSLOOP1: + jsr MBELL ; complain + jmp MSLOOP ; and do again +DO_MOUSE: + jsr INST_MOUSE ; install mouse handlers + bcs MSLOOP1 ; problems, try again + bcc ZBEND ; continue +DO_STICK: + jsr INST_STICK ; install joystick handler + bcs MSLOOP1 ; try again + bcc ZBEND ; continue, please +DO_NEITHER: +ZBEND: +; +; now, set flags like I want them + lda #FMONO^FDISP^FCOLO + ldx MOUSEF ; doing mousey stuff? + beq ZBEND0 ; nope + ora #FMOUS ; then turn on that bit too +ZBEND0: + sta ZBEGIN+ZFLAGS+1 ; set game flags +; +; +; Multiply ZFOFF & ZSOFF * 8 to get actual offset +; + lda ZBEGIN+ZFOFF ; hi part + sta FOFFM ; this'll be the middle part + lda ZBEGIN+ZFOFF+1 ; lo part + asl A ; *2 + rol FOFFM + rol FOFFH + asl A ; *4 + rol FOFFM + rol FOFFH + asl A ; *8 + rol FOFFM + rol FOFFH + sta FOFFL ; lo part here too +; +; now do string offset +; + lda ZBEGIN+ZSOFF ; hi part + sta SOFFM ; this'll be the middle part + lda ZBEGIN+ZSOFF+1 ; lo part + asl A ; *2 + rol SOFFM + rol SOFFH + asl A ; *4 + rol SOFFM + rol SOFFH + asl A ; *8 + rol SOFFM + rol SOFFH + sta SOFFL ; lo part here too + + lda ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + sta ZPCM ; MSB + lda ZBEGIN+ZGO+1 ; AND LSB + asl A ; *2 + rol ZPCM + rol ZPCH + asl A ; *4 + rol ZPCM + rol ZPCH +; +; now add offset +; + clc ; doing adding + adc FOFFL ; add in lo part + sta ZPCL + lda ZPCM + adc FOFFM + sta ZPCM + lda ZPCH + adc FOFFH + sta ZPCH +; +; now, set up TBLPUR, FUNPRE, and FUNPUR +; + lda SEGTBL+SGTTBLE+1 ; get last page of table preload + asl A ; make 256K page + sta TBLPUR ; show last pre table + inc TBLPUR ; but we want first pure table address + inc TBLPUR ; so point to it + lda TBLPUR ; does table preload take up all preload? + cmp #PGBEGIN ; reach 1st paged page? + bcs ZBEND1 ; ayyup, no function preload + + lda SEGTBL+SGTFUNS+1 ; get first page of function preload + asl A ; make 256K page + sta FUNPRE ; show me + lda SEGTBL+SGTFUNE+1 ; last page of function preload + asl A ; make 256K page + sta FUNPUR ; show last pre function + inc FUNPUR ; but we want first pure function + inc FUNPUR ; now we point to it + + lda TBLPUR ; now figger out negative number to + sec ; add to function preload addres to + sbc FUNPRE ; get page offset in memory + sta FUNPGE ; set up offset +; +; and now to set up extension table pointer +; +ZBEND1: + lda ZBEGIN+ZEXTAB+1 ; LSB of table + sta MSTBL+LO ; stays the same + lda ZBEGIN+ZEXTAB ; MSB of table + jsr SETPC ; get me the memory addres + sty MSTBL+ABANK ; save bank + sta MSTBL+HI ; and page + + jsr INIT_CHARSET ; initialize the charset + jmp INITPAG ; set up paging system + + END diff --git a/apple/yzip/rel.15/zdos.asm b/apple/yzip/rel.15/zdos.asm new file mode 100644 index 0000000..40ddda8 --- /dev/null +++ b/apple/yzip/rel.15/zdos.asm @@ -0,0 +1,967 @@ + STTL "--- ZDOS (SEEKING, READING, WRITING) ---" + PAGE +; +; some ProDOS parameter blocks here +; +READ_PB: ; for READING files + db 4 ; 4 parameters +GMREF: db 0 ; refnum + dw IOBUFF ; read into io buffer + dw PAGELEN ; 512 byte buffer + dw 0 ; length actually read +OPEN_FILE: ; opening up the pure file + db 3 ; 3 parameters + dw GAME1NM ; name of pure file + dw GAME1FIO ; game file buffer + db 0 ; where refnum goes +PSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +SET_PB: + db 1 ; just one parameter + dw GAMEPL ; where to go to +; +; some messages +; +SWAPSAVE: db EOL, "Take out save disk and insert ", EOL +SWAPSAVEL EQU $-SWAPSAVE +NOSWAP: db "game disk." +NOSWAPL EQU $-NOSWAP +INS_MSG: db EOL,"Insert " +INS_MSGL EQU $-INS_MSG +SIDEMSG: db ", Side " +SIDEMSGL EQU $-SIDEMSG +DRIVE_MSG: db ", in Disk Drive " +DRIVE_MSGL EQU $-DRIVE_MSG + +RESEAT_MSG1: db EOL, "Having problems reading side #" +RESEAT_MSG1L EQU $-RESEAT_MSG1 +RESEAT_MSG2: db ".",EOL,"Please re-insert it.",EOL,EOL +RESEAT_MSG2L EQU $-RESEAT_MSG2 + IF CHECKSUM +RETRYING: db "RETRYING . . ." +RETRYINGL EQU $-RETRYING + ENDIF +; +; place to stash prefixes and names +; +GPRE_PB: ; game prefix spot + db 1 ; 1 parm + dw GAMEPL ; where to put prefix +GAMEL: db 0 +GAME: ds 15 ; longest name + +GAME1NM: +GAME1NML: + db 0 ; not sure how long +GAME1NAME: + BLKB 15,0 ; room for name +GAME1REF: db 0 ; save refnum here +GAME1NUM: db 0 ; number (0-3) of side + +GAME2NM: +GAME2NML: + db 0 ; not sure how long +GAME2NAME: + BLKB 15,0 ; room for name +GAME2REF: db 0 ; refnum for game file 2 +GAME2NUM: db 0 ; number (0-3) of side +GAMEPL: db 0 ; name of prefix for game file +GAMEP: ds 64-15 ; max len +; -------------------- +; READ A VIRTUAL PAGE +; -------------------- +; ENTRY: V-BLOCK TO READ IN [DBLOCK] +; BUFFER ADDRESS IN [DBUFF] +; DSKBNK SAYS WHERE TO PUT PAGE (AUX OR MAIN) +; EXIT: DATA AT [DBUFF] +; +RFLAG: ds 1 +RCHKS: ds 1 +GETDSK: + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now + + IF DEBUG + lda #0 + sta RFLAG ; show no retries + sta RCHKS ; and checksum for it + ENDIF + + jsr FINDSEG ; find the segment and point to it +GETDSKL: + SET_MARK PSEEK ; move to the block + bcs GDBAD ; just die then + jsr READ_DOS ; do the read, thank you + bcc GDEX ; okay, just fine + inc RFLAG + jsr RETRY ; try again + bcc GETDSKL ; try all over +GDEX: + lda READ_PB+RD_LENGTH+HI ; Get how much read in + cmp READ_PB+RD_BUFFLEN+HI ; same as we wanted? + beq GDEX1 ; yes + lda #23 + jmp ZERROR +GDEX1: + IF DEBUG + lda RFLAG ; see if we retried + beq GDEX3 ; nope + lda RCHKS ; did retry checksum? + bne GDEX2 + inc RCHKS ; now we have + ldy #0 ; save block + sty $B00 + clc +GDEXL: + lda IOBUFF,Y + sta $A00,Y + adc $B00 + sta $B00 + iny + bne GDEXL + beq GETDSKL +GDEX2: + ldy #0 + clc + sty RFLAG +GDEX2L: + lda IOBUFF,Y + adc RFLAG + sta RFLAG + iny + bne GDEX2L + lda RFLAG + cmp $B00 + beq GDEX3 + lda #24 + jmp ZERROR + ENDIF +GDEX3: + lda #>IOBUFF ; first 256 byte page + jsr COPY_DATA ; and copy from IOBUFF to DBUFF + inc DBUFF+HI ; point to next one + lda #>IOBUFF+1 ; next 256 byte page + jmp COPY_DATA ; and copy it over +GDBAD: + jmp DISK_FATAL ; just die then +RETRY: + IF CHECKSUM + DLINE RETRYING ; show me the way to go home + ENDIF + + dec RETRIES ; count this try + bmi GDBAD ; it's dead jim + beq RETRY0 ; ask for reset + cmp #1 ; down to last time? + bne RETRYX ; just try again + lda PSEEK+SM_FPOS+0 + pha + lda PSEEK+SM_FPOS+1 + pha + lda PSEEK+SM_FPOS+2 + pha + lda #0 ; seek to zero + sta PSEEK+SM_FPOS+0 ; save here for now + sta PSEEK+SM_FPOS+1 ; save here for now + sta PSEEK+SM_FPOS+2 ; save here for now + SET_MARK PSEEK ; move to the block + pla + sta PSEEK+SM_FPOS+2 + pla + sta PSEEK+SM_FPOS+1 + pla + sta PSEEK+SM_FPOS+0 + bcc RETRYX ; all done +RETRY0: + pha ; save disk error + jsr SWAP2INFOW ; go to window zero + DLINE RESEAT_MSG1 ; ask to move the disk around + lda GMREF ; get ref num + cmp GAME2REF ; game2? + bne RETRY1 ; nope + ldy GAME2NML ; get length + lda GAME2NM,Y ; and side # + bne RETRY2 ; and continue +RETRY1: + ldy GAME1NML ; get length + lda GAME1NM,Y ; and side # +RETRY2: + jsr CHAR ; send char out there + DLINE RESEAT_MSG2 ; and finish statement + pla ; get disk error back + jsr DISK_ERR ; tell the error + jsr SWAPBACK ; back to current window +RETRYX: + clc ; show goodness + rts ; and done +; +; this is the fatal error spot +; +DISK_FATAL: + jsr DISK_ERR ; print out problem +DRIVE_ERR: + lda #14 + jmp ZERROR ; DRIVE ACCESS ERROR +; +; this routine prints out the string associated with the error and +; returns with the carry set, like most routines do when there is +; an error. The error should be in [A]. +; +UNK_DISK: db "ProDOS error $" +UNK_DISKL EQU $-UNK_DISK + +DISK_ERR: + pha ; save [A] + jsr SWAP2INFOW ; point to information window + pla ; get it back + + ldx #ELISTL ; scan the error table +DSKE: + cmp ELIST,X ; is it this one + beq DSKE1 ; ayyup + dex ; now skip the address + dex ; of the description + dex ; point to next error number + bpl DSKE ; jump to start +; +; if we are here print out unknown error and it's value +; + pha ; save [A] + DLINE UNK_DISK ; show error + pla ; get [A] + jsr HEXNUM ; print [A] + jmp DSK_EXIT ; done +DSKE1: + inx ; point to string address + lda ELIST,X ; get lo part + sta L+LO ; save it + inx ; point to hi part + lda ELIST,X ; get hi part + tax ; save here + sta L+HI ; and here + ldy #0 ; for offset + lda (L),Y ; get length of string + tay ; save in y + inc L+LO ; point past length + lda L+LO ; get it + bne DSKPR ; for printing + inx ; wrapped +DSKPR: + txa ; hi part in a + ldx L+LO ; lo part in X + jsr DLINE ; print out message +DSK_EXIT: + jsr GETRET ; wait for RETURN + jsr SWAPBACK ; all done + sec ; show badness again + rts ; and be done with it +; +; HEXNUM - print out the HEX value of [A] at the current cursor +; location +; +HEXNUM: + pha + lsr A + lsr A + lsr A + lsr A + jsr NIB1 + pla +NIB1: + and #%00001111 + tay + lda HCHARS,Y + jsr CHAR ; print it out + rts +HCHARS: DB "0123456789ABCDEF" + +; ---------------------- +; WRITE [DBUFF] TO DISK +; ---------------------- +; ENTRY: File already open and positioned, ready to be written to +; from page in (DBUFF). Writes out 512bytes, starting @ DBUFF. +; EXIT: CARRY CLEAR IF OKAY, SET IF FAILED + +PUTDSK: + ldx DSKBNK ; get bank + ldy #0 ; clear Y + lda #>IOBUFF ; first buffer + jsr SAVE_DATA ; and copy from DBUFF to IOBUFF + + IF CHECKSUM == 1 + lda #>IOBUFF + jsr CKS_BLOCK + ENDIF + + jsr NEXT_DBUFF ; point to next buffer + ldx DSKBNK ; go get new DSKBNK + ldy #0 ; clear Y again + lda #>IOBUFF+1 ; top part + jsr SAVE_DATA ; copy to IOBUFF + + IF CHECKSUM == 1 + lda #>IOBUFF+1 + jsr CKS_BLOCK + ENDIF + + jsr NEXT_DBUFF ; count buffer + jmp WRITE_DOS ; and now write it +; --------------------- +; READ DBLOCK FROM DISK +; --------------------- +; CALLED BY RESTORE +; ENTER: with file already set up as it DBUFF +; L+LO == # of 256k blocks to read +; +GETRES: + lda L+LO ; get # of blocks + sta READ_PB+RD_BUFFLEN+HI + jsr READ_DOS + ldx #>PAGELEN ; get starting number of pages + stx READ_PB+RD_BUFFLEN+HI + bcc GTROK ; everything is fine + rts ; error if c == set +GTROK: + lda #>IOBUFF ; start at first block + sta L+HI ; we can use L+HI +GTRLOOP: + lda L+HI ; doing this block + + IF CHECKSUM == 1 + jsr CKS_BLOCK ; check check sum + ENDIF + + jsr COPY_DATA ; and copy from IOBUFF to DBUFF + jsr NEXT_DBUFF ; check for wrap + inc L+HI ; count this block + dec L+LO ; count this block + bne GTRLOOP ; do next one + rts ; all finished +; +; NEXT_DBUFF +; increment DBUFF to count the 2 pages done +; +NEXT_DBUFF: + inc DBUFF+HI ; point to next page + lda DBUFF+HI ; see where we are + cmp #>PRGLBL ; wrapping? + bne GTREX ; okay then + lda DSKBNK ; which bank we be in + bne GTR1 ; aux, so go to page 3 + inc DSKBNK ; point to aux + lda #Z2PAGE ; start of page 2 + bne GTREX ; so tell me which page +GTR1: + lda #P3BANK ; show page 3 bank + sta DSKBNK ; okay + lda #Z3PAGE ; page 3 of things +GTREX: + sta DBUFF+HI ; saved + rts ; all done +; +WRITE_DOS: + WRITE WRITE_SV ; write out save buffer + rts ; done +READ_DOS: + READ READ_PB ; read it + rts ; go home +; +; COPY_DATA - +; now move the data from iobuff to dbuff (in some bank) +; which part of IOBUFF is in [a] ($08 - $0B) +; +COPY_DATA: + sta SDLP3+2 ; self-modify code to get from IOBUFF + sta RDBNK+MAIN ; read from main + ldx DSKBNK ; get which bank it's going to + bmi CPD1 ; oh oh, third bank + sta WRTBNK,X ; and select that bank for writing + bpl CPD2 ; okay, bank selected +CPD1: + lda DBUFF+HI ; get from this zero page + sta ALTZP+AUX ; talk about aux mem + sta DBUFF+HI ; and save this in aux mem ZP +CPD2: + ldy #0 ; start at beginning + sty DBUFF+LO ; just to be sure +SDLP3: + lda IOBUFF,Y ; this becomes modified! + sta (DBUFF),Y ; to [DBUFF] + iny + bne SDLP3 + sta ALTZP+MAIN ; talk about main page again + sta WRTBNK+MAIN ; end up back at main + rts +; +; Segment table handling routines +; + +; +; FINDSEG - find the Virtual page in DBLOCK by searching through +; the SEGTBL. +; +DISKPAGE: ds 2 ; spot to put starting disk page +BIGPAGE: ds 2 ; DBLOCK/2 for 512 pages +FINDSEG: + lda DBLOCK+HI ; work with MSB first + lsr A ; /2 + sta BIGPAGE+HI + lda DBLOCK+LO ; now LSB + ror A ; /2 + sta BIGPAGE+LO + lda GAME1NUM ; get number for disk 1 + jsr SCANSEG ; scan through the current disk table + lda GAME1REF ; save refnum + bcc FNDSG1 ; found it, figger it out + lda GAME2NUM ; get number for disk 2 + jsr SCANSEG ; see if it is here + lda GAME2REF ; save refnum + bcc FNDSG1 ; ayyup + jsr SEGQUEST ; get correct disk/file with segment +FNDSG1: + sta PSEEK+SM_REFNUM ; for seeking + sta GMREF ; and for reading + lda (DSEGS),Y ; pick up MSB of disk page + sta DISKPAGE+HI ; save it + iny ; point to LSB + lda (DSEGS),Y ; get it + sta DISKPAGE+LO ; save it +; now point to Starting page again + dey + dey + dey + dey + lda BIGPAGE+LO ; LSB of desired page + sec ; doing subtract + sbc (DSEGS),Y ; get rid of LSB of starting page + sta PSEEK+SM_FPOS+1 ; save here for now + dey ; point to MSB of starting page + lda BIGPAGE+HI ; get DBLOCK MSB + sbc (DSEGS),Y ; get offset + sta PSEEK+SM_FPOS+2 ; save here temporarily + clc ; now add offset to starting disk page + lda DISKPAGE+LO ; get starting disk page + adc PSEEK+SM_FPOS+1 ; add inter-segment offset + sta PSEEK+SM_FPOS+1 ; save LSB + lda DISKPAGE+HI ; get MSB of segment disk page + adc PSEEK+SM_FPOS+2 ; add inter-segment offset + sta PSEEK+SM_FPOS+2 ; save MSB of disk page + asl PSEEK+SM_FPOS+1 ; *2 for 256Kb pages + rol PSEEK+SM_FPOS+2 ; okay, we did + lda DBLOCK+LO ; check to see which page in 512 we are + and #$01 ; if odd, then add one more + beq FNDEX ; all done then + inc PSEEK+SM_FPOS+1 ; one more page + bne FNDEX ; all done if no wrap + inc PSEEK+SM_FPOS+2 ; nother page +FNDEX: + rts ; done +; +; SCANSEG - look through the current segment table for the desired +; address found in BIGPAGE. Return with Y pointing to disk page +; and carry cleared if found. Otherwise, return carry set. +; [A] = which side number we are checking (0-n) +; +SCANSEG: + pha ; save which disk + asl A ; make word index + tax ; make it an index + lda DSKSEG+LO,X ; get LSB + sta DSEGS+LO + lda DSKSEG+HI,X + sta DSEGS+HI + ldy #SGTNSEG+1 ; point to segment count + lda (DSEGS),Y ; get it + tax ; use x as counter + pla ; get which side + tay ; is it side zero + bne SCANSG1 ; nope + ldy #SGTSEG+6 ; skip first entry, cuz they're preload + bne SCANNING ; okay ready to go +SCANSG1: + ldy #SGTSEG ; begin at beginning +SCANNING: + lda (DSEGS),Y ; get MSB of start + cmp BIGPAGE+HI ; check against block we want + beq SCAN1 ; might be okay + bcc SCAN2 ; PAGE > start seg, check end seg + iny ; LSB of start +SCAN0: + iny ; MSB of end + bcs NEXTSEG ; not this one +SCAN1: + iny ; point to LSB of start + lda (DSEGS),Y ; get LSB + cmp BIGPAGE+LO ; check against desired LSB + beq GOTSEG ; we found it + bcs SCAN0 ; DBLOCK LSB < then start LSB, not found + dey ; point back to MSB of start +SCAN2: + iny ; LSB of start + iny ; MSB of end + lda (DSEGS),Y ; get MSB of end + cmp BIGPAGE+HI ; check against DBLOCK MSB + bcc NEXTSEG ; end < DBLOCK, check next segment + bne GOTSEG1 ; end > DBLOCK, must be in this segment + iny ; point to end LSB + lda (DSEGS),Y ; get LSB + cmp BIGPAGE+LO ; how does it compare to desired LSB + bcs GOTSEG2 ; it's <= end, so it is here + dey ; point back to MSB +NEXTSEG: + iny ; point to LSB of end + iny ; MSB of disk page + iny ; LSB of disk page + iny ; MSB of next start page + dex ; count this segment + bne SCANNING ; check this segment + + sec ; show not on this disk + rts ; and done +GOTSEG: + iny ; MSB of end page +GOTSEG1: + iny ; LSB of end page +GOTSEG2: + iny ; MSB of disk offset + clc ; show we found it + rts ; all done +; +; SEGQUEST - find the correct disk/file with the desired page on +; it. Returns SCANSEG's stuff. +; +DISKCNTR: ds 1 ; disk count down +PAGENF: + db "Page not found in segment table: " +PAGENFL EQU $-PAGENF +SEGQUEST: + lda #1 ; start at first disk + sta DISKCNTR ; init counter +SEGQL: + lda DISKCNTR ; get disk + cmp SEGTBL+SGTDISKS+1 ; looked at all the disks? + bne SEGQL1 ; nope +; +; as a last resort, check disk 1, the boot disk +; + lda #0 ; set up DISKCNTR + sta DISKCNTR ; we did + jsr SCANSEG ; see if it is there + bcc SEGQ1 ; we found it + + DLINE PAGENF ; page not found + lda BIGPAGE+HI ; show MSB + jsr HEXNUM ; printed + lda BIGPAGE+LO ; and LSB + jsr HEXNUM ; we did + + lda #17 ; bad page + jmp ZERROR ; die a horrible death +SEGQL1: + lda DISKCNTR ; get which disk we be working on + jsr SCANSEG ; find out if it is here + bcc SEGQ1 ; it is, so open up file + inc DISKCNTR ; not in this disk + bne SEGQL ; and try again +; +; we have found the disk it is in, so ask for it if necessary +; +SEGQ1: + tya ; save the y pointer + pha ; it is saved + lda DISKCNTR ; get which disk we found it under + jsr FETCH_FILE ; go get the disk desired + pla ; get the Y reg back + tay ; and show it + lda GMREF ; get reference number again + rts ; all done +; +; FETCH_FILE: check to see if we can open GAMEFILE# (where # is in [A]) +; if not, ask for DISK#. +; +SAVENUM: db 0 ; spot to save ascii number +FETCH_FILE: + clc ; adding to make + adc #$30 ; it an ascii number + sta SAVENUM ; just save a minute + inc SAVENUM ; make name be one based + ldx GAME1NML ; get length of name + lda SAVENUM ; get name back + cmp #'3' ; are we looking for disk 1 or 2? + bcs FEFI1 ; disks 3 and up handled special +FEFI00: + cmp GAME1NM,X ; is it the current open one? + bne FEFI0 ; nope, so we need to open it + ldy GAME1REF ; get game 1 refnum + bne FEFIX ; all set, so point to it +FEFI0: + jsr DO_GAME1 ; handle it special + lda GAME1REF ; fetch refnum + jsr GET_PDATA ; now get the picture data + ldy GAME1REF ; refetch refnum + bne FEFIX ; so all done +FEFI1: + ldx GAME2NML ; get length of second name + cmp GAME2NM,X ; how bout second open file? + bne FEFI2 ; nope, so we need to open it + ldy GAME2REF ; it is second one, so show me + bne FEFIX ; it is open too +FEFI2: + lda GAME2REF ; get its refnum + beq FEFI20 ; nothing to close, thank you + sta CLOSE_PB+CL_REFNUM ; show close who to close + CLOSE CLOSE_PB ; close it up tight +FEFI20: + jsr OPEN_GAME2 ; open up GAME2 file + lda GAME2REF ; get refnum for this file + jsr GET_PDATA ; now get the picture data + ldy GAME2REF ; get ref back, please +FEFIX: + sty PSEEK+SM_REFNUM ; for seeking + sty GMREF ; and for reading + rts ; did it +; +; OPEN_GAME2 - open up the file that GAME2NM is pointing to, +; returning the REFNUM in [A], after storing in GAME2REF, +; and the 2 picture structures +; +OPEN_GAME2: + ldx GAME2NML ; get end of name + lda SAVENUM ; get new name + sta GAME2NM,X ; using second file + lda #>GAME2NM ; get lo byte + sta OPEN_FILE+OP_PATHNAME+HI + lda #GAME2FIO ; now set up file i/o buffer + sta OPEN_FILE+OP_FILEBUFF+HI + lda #0 if multi disk game + +SET_GAMEPRE: + jsr SWAP2INFOW ; point to info window + lda SWAPPED ; are we swapping disks? + beq SETGP ; nope, don't change game prefix + lda SAVENUM ; get which disk to put it + ldy GAMEPL ; get length of prefix + dey ; subtract 2 to point to prefix + dey ; number + sta GAMEP,Y ; set number for prefix +SETGP: + lda #>GAMEPL ; set up parm block + sta SET_PB+SP_PATHNAME+HI + lda #= side 3, must be disk drive 2 + bcs SEGTP02 ; fine, send that message out + lda #'1' ; ask for drive 1 then +SEGTP02: + jsr CHAR ; save which drive + lda #'.' ; finish sentence + jsr CHAR ; okay +SEGTP03: + jsr GETRET ; wait for + jmp SETGP0 ; try again +SETGP1: + jmp SWAPBACK ; pointing to disk +; +; DO_GAME1 - open up the special game 1 file and point to it +; +DO_GAME1: + ldy GAME1REF ; get the current game 1 ref num + beq DOG1 ; not currently open + pha ; save Name + sty CLOSE_PB+CL_REFNUM ; show close + CLOSE CLOSE_PB ; and close it + pla ; get name back +DOG1: + ldx GAME1NML ; get length of name + lda SAVENUM ; get new number + sta GAME1NM,X ; save name + pha ; save it for later use + lda #>GAME1NM ; get lo byte + sta OPEN_FILE+OP_PATHNAME+HI + lda #GAME1FIO ; now set up file i/o buffer + sta OPEN_FILE+OP_FILEBUFF+HI + lda # + jsr CHAR ; printed + dex ; count back one, as loop starts with inx + bne LSTVL ; go do next one +LSTVEX: + rts ; toots finis +; +; CHECKVOLS - set prefix to particular volume that is currently online +; +CHECKVOLS: + lda CHPTR+HI ; is it zero? + bne CHV1 ; if not, then get next volume + ONLINE ONLINE_PB ; get online volumes + bcc CHV0 ; okey dokey +CHVBX: + sec ; show badness + rts ; all done +CHV0: + lda #<(IOBUFF-16) ; get LSB (-16 cuz we start with add) + sta CHPTR+LO + lda #>IOBUFF ; and mSB + sta CHPTR+HI + lda #>SCRBUFF ; this is where we will work on it + sta SET_PB+SP_PATHNAME+HI + lda #SP_START ; where does it go? + sta L+HI ; L is pointer to there +GTS_RD: + lda #MAIN ; make sure we are in main + sta WRTBNK+MAIN + READ READ_PB ; go get 1Kb + bcc GTS_RD1 ; just fine + jsr RETRY ; try again + bcc GTS_RDL ; and do it again +GTS_RD1: + ldx #SP_BANK ; get bank that special is in + sta WRTBNK,X + lda #>IOBUFF ; get MSB of start + sta K+HI ; K is source + ldx #2 ; 2 blocks of 256 bytes each +GTS_CPL0: + ldy #0 ; indexer +GTS_CPL: + lda (K),y ; get it + sta (L),y ; store it + iny ; next + bne GTS_CPL ; gwon then + inc K+HI ; point to next block + inc L+HI ; for destination too + dex ; count block + bne GTS_CPL0 ; next block + dec J+LO ; count this 1Kb + bne GTS_RD ; go get next one + + sta WRTBNK+MAIN ; make sure we are in main +; +; now figger out last page +; + ldy #SGTSEG+1 ; get start segment LSB + lda (INFODOS),Y ; got it + clc ; doing add + adc #SP_SIZE ; add in size MSB + sta INFODOS_END+HI ; and save it + lda INFODOS_END+LO ; now, subtract one to make + bne GTS_END ; it inclusive + dec INFODOS_END+HI ; wrapped, so dec MSB +GTS_END: + dec INFODOS_END+LO ; make pointers inclusive + + rts ; done + + IF CHECKSUM == 1 +CKS_COUNT: db 0 +CKSB: db 0 +CKS_BLOCK: + pha + sta CKSMOD+2 + ldy #0 + lda CKSB +CKSLP: + clc +CKSMOD: adc IOBUFF,Y + iny + bne CKSLP + + sta CKSB + inc CKS_COUNT + pla + rts + + IF 0 + jsr HEXNUM + lda CKS_COUNT + cmp #$F + bne CKSCNT + lda #0 + sta CKS_COUNT + lda #EOL + bne CKSSEND +CKSCNT: + inc CKS_COUNT + lda #SPACE +CKSSEND: + jsr CHAR + jsr DISP_LINE + pla + rts + ENDIF + + ENDIF + + END diff --git a/apple/yzip/rel.15/zero.equ b/apple/yzip/rel.15/zero.equ new file mode 100644 index 0000000..f6f7c7f --- /dev/null +++ b/apple/yzip/rel.15/zero.equ @@ -0,0 +1,175 @@ + STTL "--- ZERO PAGE VARIABLES ---" + PAGE + +SCRCX EQU 0 ; CURSOR HORIZONTAL +SCRCY EQU SCRCX+1 ; CURSOR VERTICAL +SCRBTM EQU SCRCY+1 ; first line outside current window +MAXLINES EQU SCRBTM+1 ; maximum number of lines in window +LEFTMRG EQU MAXLINES+1 ; left edge + left margin in current window +WINDOW EQU LEFTMRG+1 ; (WORD) address of current window structure +LINE_X EQU WINDOW+2 ; (WORD) width of line counter +CC_OFF EQU LINE_X+2 ; save offset for char drawing +CLSLEFT EQU CC_OFF+1 ; screen limits for CLS code +CLSTOP EQU CLSLEFT+1 ; top of screen +CLSWIDTH EQU CLSTOP+1 ; # of columns +CLSHEIGHT EQU CLSWIDTH+1 ; # of lines +; +; some variables for all the screen positioning code +; +NY_DATA EQU CLSHEIGHT+1 ; place for GET/PUT_NYBBLE to use +CH_OFFSET EQU NY_DATA+1 ; offset into char data table +DATALOOP EQU CH_OFFSET+1 ; loop counter for byte works +BITOFF EQU DATALOOP+1 ; bit offset into screen byte +CH_DATA EQU BITOFF+1 ; actual char data being worked on +SCR_DATA EQU CH_DATA+1 ; screen byte being worked on +SH_LOOP EQU SCR_DATA+1 ; loop counter for bit shifting +SCROLLY EQU SH_LOOP+1 ; save spot for y pos when scrolling +RETRIES EQU SCROLLY+1 ; (BYTE) Machine ID +CHRMAX EQU RETRIES+1 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD +SCLLINES EQU CHRMAX+1 ; (BYTE) how many lines to scroll +FMTTBL EQU SCLLINES+1 ; (BYTE) flag to show formatted table output +STMASK EQU FMTTBL+1 ; (BYTE) Mask to use on first byte of CLS +ENDMASK EQU STMASK+1 ; (BYTE) Mask to use on last byte of CLS +CHPTR EQU ENDMASK+1 ; (WORD) pointer to char data +SCOFF EQU CHPTR ;(BYTE) Offset used by scroll +SCLDIR EQU CHPTR+1 ;(BYTE) Direction of scroll - >0 up, <0 down +DSEGS EQU CHPTR+2 ; (WORD) Pointer to current disk's segments +;WIDE_FLAG EQU SCOFF+1 ; (BYTE) <> 0 if 16 bytes in char data +;DSEGS EQU WIDE_FLAG+1 ; (WORD) Pointer to current disk's segments +LASTWV EQU DSEGS+2 ; last of the WINDOW variables + +ZEROPG EQU $50 ; FIRST FREE Z-PAGE LOCATION +; +; these are first, cuz ZBOOT inits them so we don't want to clear them +; at ZBEGIN warm start +; +GLOBAL EQU ZEROPG ; (Relative Addr.) GLOBAL VARIABLE POINTER +VOCAB EQU GLOBAL+2 ; (ADDRESS) Vocab table pointer +FWORDS EQU VOCAB+3 ; (ADDRESS) F-WORDS TABLE POINTER +MOUSEF EQU FWORDS+3 ; (BYTE) ==-1/1 if we have mouse/joystick +INFODOS EQU MOUSEF+1 ; (WORD) if <>0, then pointer to D2SEG +FUNOFF EQU INFODOS+2 ; (ADDRESS) Function Offset (ZFOFF*8) +FOFFH EQU FUNOFF ; (BYTE) Hi part +FOFFM EQU FUNOFF+1 ; (BYTE) Middle part +FOFFL EQU FUNOFF+2 ; (BYTE) Lo part +STROFF EQU FUNOFF+3 ; (ADDRESS) String Offset (ZSOFF*8) +SOFFH EQU STROFF ; (BYTE) Hi part +SOFFM EQU STROFF+1 ; (BYTE) Middle part +SOFFL EQU STROFF+2 ; (BYTE) Lo part +; +; Beginning of warm start zeroing +; +OPCODE EQU STROFF+3 ; (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 +ARG5 EQU OPCODE+10 ; (WORD) +ARG6 EQU OPCODE+12 ; (WORD) +ARG7 EQU OPCODE+14 ; (WORD) +ARG8 EQU OPCODE+16 ; (WORD) +ABYTE EQU OPCODE+18 ; (BYTE) X-OP ARGUMENT BYTE +BBYTE EQU OPCODE+19 ; (BYTE) XCALL ARG BYTE (EZIP) +ADEX EQU OPCODE+20 ; (BYTE) X-OP ARGUMENT INDEX +VALUE EQU OPCODE+21 ; (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 +L EQU VALUE+8 ; (WORD) GEN-PURPOSE REGISTER #4 +ZPC EQU VALUE+10 ; (3 BYTES) ZIP PROGRAM COUNTER +ZPCL EQU ZPC ; (BYTE) <8 BITS OF [ZPC] +ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] +ZPCH EQU ZPC+2 ; (BYTE) >BIT OF [ZPC] +ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE +ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +ZPNTH EQU ZPCPNT+1 ; (BYTE) +ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +MPC EQU ZPCPNT+3 ; (3 BYTES) MEMORY PROGRAM COUNTER +MPCL EQU MPC ; (BYTE) <8 BITS OF [MPC] +MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] +MPCH EQU MPC+2 ; (BYTE) >BIT OF [MPC] +MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE +MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +MPNTH EQU MPCPNT+1 ; (BYTE) +MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +FPC EQU MPCBNK+1 ; (3 Bytes) Fetch pointer +FPCL EQU FPC ; (BYTE) Low part +FPCH EQU FPCL+1 ; (BYTE) High Part +FPCBNK EQU FPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) +SPC EQU FPCBNK+1 ; (3 Bytes) Fetch pointer +SPCL EQU SPC ; (BYTE) Low part +SPCH EQU SPCL+1 ; (BYTE) High Part +SPCBNK EQU SPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + +; Z-STRING MANIPULATION VARIABLES + +LINLEN EQU SPCBNK+1 ; (BYTE) LENGTH OF CURRENT LINE +SOURCE EQU LINLEN+1 ; (BYTE) counter for read +WRDLEN EQU SOURCE+1 ; (BYTE) LENGTH OF CURRENT WORD +ESIZE EQU WRDLEN+1 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES +PSET EQU ESIZE+1 ; (BYTE) PERMANENT CHARSET +TSET EQU PSET+1 ; (BYTE) TEMPORARY CHARSET +ZCHAR EQU TSET+1 ; (BYTE) CURRENT Z-CHAR +OFFSET EQU ZCHAR+1 ; (BYTE) F-WORD TABLE OFFSET +ZFLAG EQU OFFSET+1 ; (BYTE) Z-WORD ACCESS FLAG +ZWORD EQU ZFLAG+1 ; (WORD) CURRENT Z-WORD +CONCNT EQU ZWORD+2 ; (BYTE) Z-STRING SOURCE COUNTER +CONIN EQU CONCNT+1 ; (BYTE) CONVERSION SOURCE INDEX +CONOUT EQU CONIN+1 ; (BYTE) CONVERSION DEST INDEX +DIRTBL EQU CONOUT+1 ; (WORD) CONTAINS TBLE TO STORE CHARS TO +XSIZE EQU DIRTBL+2 ; (WORD) SCREEN WIDTH FOR TESTS +RAND EQU XSIZE+2 ; (WORD) Random number offset +CURWIN EQU RAND+2 ; (BYTE) WHICH WINDOW TO WRITE IN +LENGTH EQU CURWIN+1 ; (WORD) CHAR POSITION ON THE SCREEN +CHRCNT EQU LENGTH+2 ; (BYTE) CHAR POSITION IN [LBUFF] +SCRIPT EQU CHRCNT+1 ; (BYTE) SCRIPT ENABLE FLAG +LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER +IOCHAR EQU LINCNT+1 ; (BYTE) CHARACTER BUFFER +COLORP EQU IOCHAR+1 ; (WORD) Pointer to current background color +ZSP EQU COLORP+2 ; (WORD) Z Stack +SCREENF EQU ZSP+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT +TABLEF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT +VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH +DBUFF EQU VOCEND+3 ; (WORD) RAM PG TO ACCESS (LSB = 0) +DSKBNK EQU DBUFF+2 ; (BYTE) MAIN/AUX bank +ALLFLG EQU DSKBNK+1 ; (BYTE) IF =1 ALL FCN KEYS (>127) ARE TCHARS +UNDFLG EQU ALLFLG+1 ; (BYTE) Underlining flag +INVFLG EQU UNDFLG+1 ; (BYTE) Inverse flag +MEMPAGE EQU INVFLG+1 ; (BYTE) Save spot for XPAGING stuff +CPY_COUNT EQU MEMPAGE+1 ; (BYTE) Number of bytes for copy line +TBLHEIGHT EQU CPY_COUNT+1 ;(BYTE) Number of lines in printing table +TBLWIDTH EQU TBLHEIGHT+1 ;(BYTE) Number of bytes per line +TBLCNT EQU TBLWIDTH+1 ;(BYTE) Counter for table printing +FONTFLG EQU TBLCNT+1 ;(BYTE) Which font (!=0 is width) +TBLPUR EQU FONTFLG+1 ;(BYTE) first pure table page +FUNPRE EQU TBLPUR+1 ;(BYTE) first preloaded function page +FUNPUR EQU FUNPRE+1 ;(BYTE) first pure function page +FUNPGE EQU FUNPUR+1 ;(BYTE) -number to get function preload page +DELAY_COUNTER EQU FUNPGE+1 ;(BYTE) counter for delay loop +; +; some char-to-screen variables +; +CHAR_D1 EQU DELAY_COUNTER+1 ; (BYTE) character data, part 1 +CHAR_D2 EQU CHAR_D1+1 ; (BYTE) char data, part 2 +CW EQU CHAR_D2+1 ; (BYTE) width of the character +CLKCTR EQU CW+1 ; (BYTE) counter for mouse clicking +MSX EQU CLKCTR+1 ; (BYTE) mouse cursor X +MSY EQU MSX+1 ; (BYTE) mouse cursor Y +CURRENT EQU MSY+1 ; (BYTE) current paging bufer +;CURSOR_OFF EQU CURRENT+1 ; (BYTE) ==1 if "don't show the blinking cursor" +MSTBL EQU CURRENT+1 ; (ADDRESS) pointer to extension table +LASTZP EQU MSTBL+3 ; just checking +; +; these routines are in non-swapped memory +; +ZERO_FB EQU LASTZP ; put fetch byte routine in at end of ZP +ZERO_ZF EQU ZERO_FB+11 ; and ZPCPNT fetch after that +ZERO_MF EQU ZERO_ZF+9 ; and MPCPNT fetch after that +SAVE_DATA EQU ZERO_MF+9 ; copy data from DBUFF to IOBUFF routine +; +; and just to check the end +; +ZEE_END EQU SAVE_DATA+17 ; should be == 100 + + END diff --git a/apple/yzip/rel.15/zip.equ b/apple/yzip/rel.15/zip.equ new file mode 100644 index 0000000..380f144 --- /dev/null +++ b/apple/yzip/rel.15/zip.equ @@ -0,0 +1,116 @@ + STTL "--- YZIP EQUATES ---" + PAGE + +VERSID EQU 15 ; VERSION OF INTERPRETER + ; See file "versions" for complete descriptions + +TRUE EQU $FF +FALSE EQU 0 + +; --------------------- +; Segment table equates +; --------------------- +SGTDISKS EQU 0 ; number of disks +SGTPAD EQU SGTDISKS+2 ; just some extra room +SGTCHKS1 EQU SGTPAD+16 ; Checksum for disk 1 (PRELOAD) +SGTPICOF1 EQU SGTCHKS1+2 ; N/A +SGTSEG1 EQU SGTPICOF1+2 ; # of segments +SGTGPOF1 EQU SGTSEG1+2 ; Global Picture Directory +SGTTBLS EQU SGTGPOF1+2 ; Start of table preload (should be 0) +SGTTBLE EQU SGTTBLS+2 ; Last page of table preload +SGTTBLX EQU SGTTBLE+2 ; N/A +SGTFUNS EQU SGTTBLX+2 ; First page of function preload +SGTFUNE EQU SGTFUNS+2 ; End page of function preload +SGTFUNX EQU SGTFUNE+2 ; N/A +SGTDSK EQU SGTFUNX+2 ; Actual start of disk segment tables + +SGTCHKS EQU 0 ; check sum for file +SGTPICOF EQU 2 ; picture data offset +SGTNSEG EQU 4 ; # of segments in this list +SGTGPOF EQU 6 ; Global Directory Offset +SGTSEG EQU 8 ; start of segments +; --------------------- +; Z-CODE HEADER OFFSETS +; --------------------- + +ZVERS EQU 0 ; VERSION BYTE +ZMODE EQU 1 ; MODE SELECT BYTE +ZID EQU 2 ; GAME ID WORD +ZENDLD EQU 4 ; # OF QUADWORDS ON SIDE 1 OF DISK +ZGO EQU 6 ; EXECUTION ADDRESS +ZVOCAB EQU 8 ; START OF VOCABULARY TABLE +ZOBJEC EQU 10 ; START OF OBJECT TABLE +ZGLOBAL EQU 12 ; START OF GLOBAL VARIABLE TABLE +ZPURBT EQU 14 ; START OF "PURE" Z-CODE +ZFLAGS EQU 16 ; FLAG WORD +ZSERIA EQU 18 ; 3-WORD 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 +ZINTWD EQU 30 ; INTERPRETER ID WORD (SUPPLIED BY EZIP) +ZSCRWD EQU 32 ; SCREEN PARAMETER WORD ( " " " ) +ZHWRD EQU 34 ; DISPLAY WIDTH IN PIXELS +ZVWRD EQU 36 ; DISPLAY HEIGHT IN PIXELS +ZFWRD EQU 38 ; FONT HEIGHT, FONT WIDTH +ZFOFF EQU 40 ; FUNCTION OFFSET +ZSOFF EQU 42 ; STRING OFFSET +ZCLRWD EQU 44 ; FORGROUND COLOR, BACKGROUND COLOR +ZTCHAR EQU 46 ; POINTER TO TBL OF TERMINATING CHARS +ZTWIDTH EQU 48 ; Running counter for table output char width +ZCRFUNC EQU 50 ; FUNCTION FOR CARRIAGE RETURNS +ZCHRSET EQU 52 ; POINTER TO CHAR SET TBL +ZEXTAB EQU 54 ; Points to extension table, if needed +; +; Extension table offsets +; +ZEXTLEN EQU 0 ; Length of extension table +ZMSLOCX EQU 2 ; x location of mouse +ZMSLOCY EQU 4 ; y location of mouse +ZMSETBL EQU 6 ; MOUSE TBL CHANGE WORD +ZMSEDIR EQU 8 ; DIRECTION MENU +ZMSEINV EQU 10 ; INVENTORY MENU +ZMSEVRB EQU 12 ; FREQUENT VERB MENU +ZMSEWRD EQU 14 ; FREQUENT WORD MENU +ZBUTTN EQU 16 ; BUTTON HANDLER +ZJOYST EQU 18 ; JOYSTICK HANDLER +ZBSTAT EQU 20 ; BUTTON STATUS +ZJSTAT EQU 22 ; JOYSTICK STATUS +; +; ZFLAGS values +; +FSCRI EQU $01 ; scripting? +FMONO EQU $02 ; mono spaced font? +FSTAT EQU $04 ; status line refresh? +FDISP EQU $08 ; uses DISPLAY operations? +FUNDO EQU $10 ; uses UNDO? +FMOUS EQU $20 ; uses mouse? +FCOLO EQU $40 ; uses color? +FMENU EQU $80 ; uses menus? +;--------------- +; Picture data +;--------------- +;=== DATA HEADER === +PHFID EQU 0 ; File ID +PHFLG EQU PHFID+1 ; Flags +PHHUFF EQU PHFLG+1 ; Pointer to Huffman data +PHNLD EQU PHHUFF+2 ; # entries in local directory +PHNGD EQU PHNLD+2 ; # entries in global directory +PHDSIZE EQU PHNGD+2 ; Local directory entry size +PHCHKS EQU PHDSIZE+2 ; File Checksum +PHFVERS EQU PHCHKS+2 ; File Version (N/A) +PHEXTRA EQU PHFVERS+2 ; Extra room for getting fatter +PHSIZE EQU 16 ; 16 bytes is header size +;=== DATA HEADER FLAGS === +PHFGD EQU $1 ; data has global directory +PHFHUFF EQU $2 ; Huffman encoded pictures +PHFHUFF1 EQU $4 ; All pictures use same Huff tree +PHFPAL EQU $8 ; No pallette information +;=== LOCAL DIRECTORY === +PLDID EQU 0 ; Picture ID +PLDWID EQU PLDID+2 ; Picture Width +PLDHGHT EQU PLDWID+1 ; Picture Height +PLDFLG EQU PLDHGHT+1 ; Flags +PLDPTR EQU PLDFLG+1 ; Pointer to picture data +PLDSIZE EQU PLDPTR+3 ; size of local directory entry + + END diff --git a/apple/yzip/rel.15/zsavres.asm b/apple/yzip/rel.15/zsavres.asm new file mode 100644 index 0000000..d6312fd --- /dev/null +++ b/apple/yzip/rel.15/zsavres.asm @@ -0,0 +1,726 @@ + + STTL "--- ZIP SAVE AND RESTORE ROUTINES ---" + PAGE +; ----------------------------- +; SET UP SAVE & RESTORE SCREENS +; ----------------------------- +SAVRES: + jsr ZCRLF ; CLEAR THE LINE BUFFER + lda #0 + sta SCRIPT ; DISABLE SCRIPTING + lda PAGE2SW+MAIN ; just do this for the heck of it + lda BNK2SET ; this stuff too + lda BNK2SET + + rts + +; ----------------------------- +; SAVE & RESTORE STRINGS +; ----------------------------- +YES: DB "YES" + DB EOL +YESL EQU $-YES +NO: DB "NO" + DB EOL +NOL EQU $-NO + +NAMEQ: db EOL + db "Insert save disk and enter " + db "full pathname of save file: " + db EOL + db "Hit '?' key to get a list of online volumes." + db EOL + db "Current pathname is:", + db EOL +NAMEQL EQU $-NAMEQ +SNDATA: ; show start of name and length +SNAMEL: db 0 ; place to save length of name +SAVENAME: ds 64+15 ; save plenty of room for max name + +DELQ: db EOL,"File exists, delete it (Yes/No)? " +DELQL EQU $-DELQ+1 ; include this following EOL +RETQ: db EOL,"Please hit [RETURN]",EOL +RETQL EQU $-RETQ +PREFIX_ERR: db EOL,"Name must have prefix, " + db "i.e.: /DISKNAME/FILENAME",EOL +PREFIX_ERRL EQU $-PREFIX_ERR + +MAX_SAVENAME EQU 45 ; max # of chars allowed in save name + +; ----------------------------- +; SAVE/RESTORE Parameter Blocks +; ----------------------------- +CREATE_PB: + db 7 ; 7 parameters + dw SNDATA ; pointer to name + db $C3 ; full access to file + db $06 ; BIN file type + dw 0 ; no aux data + db $01 ; standard file + dw 0 ; create date + dw 0 + ; creation time +SETEOF_PB: + db 2 ; 1 parameter + db 0 ; refnum + db 0,0,0 ; set to zero spot to clear it out +OPEN_SV: + db 3 ; 3 parameters + dw SNDATA ; name + dw GAME1FIO ; file buffer + db 0 ; ref num +CLOSE_PB: + db 1 ; only one parm + db 0 ; the refnum +WRITE_SV: + db 4 ; parm count + db 0 ; refnum + dw IOBUFF ; data is always here + dw 512 ; 1 page worth + dw 0 ; how many actually went + +; get the save file name. If user hits the ESC key, then abort the +; save by return with the carry set. +; +GET_SNAME: + jsr CLOSE_GAME ; close the game files + jsr SWAP2INFOW ; goto information window +GTSN0: + DLINE NAMEQ ; ask about name + lda SNAMEL ; is there a name yet? + beq GTSN00 ; nope + DLINE SAVENAME,SNAMEL ; show current name of file +GTSN00: + lda #0 ; clear line count + sta CLOSE_PB+CL_REFNUM ; clear this too + ldx SNAMEL ; get length + stx CHRCNT ; okay + ldy SNAMEL ; point to copy + dey ; one less +GCOPY: + lda SNAMEL,X ; get char + sta LBUFF,Y ; save it + dex ; point to previous one + dey ; previous pointer + bpl GCOPY ; copy until length byte +GNAME: + jsr GETKEY ; WAIT FOR A KEY + cmp #EOL ; IF [RETURN], + beq GOTNAME ; got the name + cmp #ESCAPE ; hit escape key? + sec ; just in case it does exit + bne GNM2 + jmp GNX ; all done then +GNM2: + cmp #BACKSPACE ; erasing things? + bne GNM1 ; nope + + ldx CHRCNT ; make sure there are chars there + bne GNMBP ; ayyup, do delete +GNMBAD: + jsr BEEP ; no room for delete + jmp GNAME ; okay +GNMBP: + dex ; point down one + stx CHRCNT ; count one down + lda LBUFF,X ; get char to delete + tax ; show in [X] + lda #BACKSPACE ; and doing a backspace + bne GNMSHOW ; okay, delete char on screen +GNM1: + cmp #'/' ; slash is the only good non-numeric char + beq GNMGOOD ; fine, use it + cmp #'.' ; well, maybe a . too + beq GNMGOOD ; fine, here it is + cmp #VOLCHAR ; does user want list of volumes? + bne GNM1x ; nope + + lda #0 ; clear out current name + sta CHRCNT ; okay, we did + jsr LISTVOLS ; show them + jmp GTSN0 ; start over, kind of +GNM1x: + cmp #'0' ; is it a number + bcc GNMBAD ; nope + cmp #'9'+1 ; well? + bcc GNMGOOD ; yup + cmp #'z'+1 ; make sure it is alpha numeric + bcs GNMBAD ; nope + cmp #'A' ; well? + bcc GNMBAD ; nope + cmp #'a' ; little char? + bcs GNMGOOD ; yup + cmp #'Z'+1 ; big char + bcs GNMBAD ; nope +GNMGOOD: + ldx CHRCNT ; get name index + cpx #MAX_SAVENAME ; just get so many characters + bcs GNMBAD ; beep at user + inc CHRCNT ; point to next char + sta LBUFF,X ; save name char +GNMSHOW: + jsr CHAR ; show character + jsr DISP_LINE ; make sure it is there + jmp GNAME ; go get next char +; +; got the name, so copy it to the SAVENAME buffer +; +GOTNAME: + lda CHRCNT ; did we get any? + beq GTNMERR ; nope + lda LBUFF ; make sure first name is a directory + cmp #'/' ; is it? + beq GTNM1 ; yup, probly okay then +GTNMERR: + lda #0 ; clear CHRCNT so name doesn't get + sta CHRCNT ; output again + DLINE PREFIX_ERR ; complain and die + sec ; show bad name + bcs GNX ; all done +GTNM1: + ldx #0 ; now check to make sure there are 2 + ldy #$FE ; use this as counter +GTNMCHK: + lda LBUFF,X ; get char + inx ; next char + cmp #'/' ; prefix deliminator? + bne GTNMCHK1 ; nope + iny ; count this one + beq GTNM2 ; we have 2 of them +GTNMCHK1: + cpx CHRCNT ; at end? + beq GTNMERR ; yes, and no 2 '/'s + bne GTNMCHK ; go check next char +GTNM2: + cpx CHRCNT ; make sure there are chars after prefix + beq GTNMERR ; nope, still an error + ldx CHRCNT ; get how many characters + stx SNAMEL ; save in length byte + dex ; points one too far +GNL: + lda LBUFF,X ; get the char + sta SAVENAME,X ; save the char + dex ; point to previous one + bpl GNL ; and go get it + clc ; show did just fine +GNX: + php ; save status + lda #0 ; and clear CHRCNT + sta CHRCNT ; okay + lda #EOL ; print EOL + jsr CHAR ; okay + jsr SWAPBACK ; change back to old window + plp ; get status back + rts ; all done +; +; open up a save file, by first trying to create it. If it already exists +; then make sure the player wants to delete the file, then get rid of it. +; Finally open the file. Return with carry set if user aborts the save. +; Store the ref number into the write parm block. +; +OPEN_SAVE: + CREATE CREATE_PB ; first try to create the file + bcc OPSV_OPEN ; created just fine, so open it +; +; can't create the file, check out why +; + cmp #$47 ; this means file already there + beq OPSV1 ; nope, not that + jmp DISK_ERR ; show badness +OPSV1: + DLINE DELQ ; ask about deleting this file + jsr GETYN ; get me the yes or no + bcc OPSV_OPEN ; so then delete it if yes + rts ; nope, so just quit +OPSV_OPEN: + OPEN OPEN_SV ; open the save file + bcc OPSV_OP1 ; okey, things worked just fine + jmp DISK_ERR ; complain about error +OPSV_OP1: + lda OPEN_SV+OP_REFNUM ; get the ref number + sta WRITE_SV+WR_REFNUM ; save the ref number + sta CLOSE_PB+CL_REFNUM ; to close parm too + sta SETEOF_PB+SE_REFNUM ; for cleansing file + SET_EOF SETEOF_PB ; clear out file + bcc OPSVEX ; no problems + jsr DISK_ERR ; complain +OPSVEX: + rts ; file has been opened, return +; +; OPEN_RES - open the save file +; +OPEN_RES: + OPEN OPEN_SV ; open it up + bcc OPR1 ; okay, it worked + rts ; okay, it didn't +OPR1: + lda OPEN_SV+OP_REFNUM ; get reference number + sta READ_PB+RD_REFNUM ; save for read + sta CLOSE_PB+CL_REFNUM ; and for close + rts +; +; CLOSE_SAVE - close up the save file if it is open, and +; restore open game files +; +CLOSE_SAVE: + lda CLOSE_PB+CL_REFNUM ; check if it opened + beq CLSVX ; okay, nothing + CLOSE CLOSE_PB ; close the save file +CLSVX: +; lda #1 ; flag is true +; sta SAVEDISK ; show we have a save disk in there +; jsr SET_GAMEPRE ; go get the last one used +; jsr FETCH_FILE ; this does it + ldx GAME1NML ; get length of current name + lda GAME1NM,X ; get the number of the file + sta SAVENUM ; we need this to look for prefix + sta SAVEDISK ; show taking out save disk, not game disk + jsr DO_GAME1 ; open up GAME1 file + lda D2SEG+HI ; set DSEGS to point to #2 + sta DSEGS+HI + lda D2SEG+LO + sta DSEGS+LO + ldx GAME2NML ; get length of current name + lda GAME2NM,X ; get the number of the file + sta SAVENUM ; we need this to look for prefix + jsr OPEN_GAME2 ; open up GAME2 file + ldy #0 ; open up GAME2 file, just for kicks + sty SAVEDISK ; show we have a save disk in there + sty CLOSE_PB+CL_REFNUM ; clear close + iny ; set for true + sty SCRIPT ; allow scripting again + rts ; DONE +; +; CLOSE_GAME - close the current game file(s) +; and set DSEGS to point to preload so it will reopen them +; +CLOSE_GAME: + lda #0 ; show no files are open + sta CLOSE_PB+CL_REFNUM ; 0 closes all files + sta GAME1REF ; zero out two game files too + sta GAME2REF ; and here is number 2 + sta PF_FID ; clear this too + CLOSE CLOSE_PB ; now all are closed + rts +; +; Get answer to Yes/No question. Return with C==0 for yes, and C==1 +; for a no. RETURN == Yes, ESCAPE == NO +; +GETYN: + jsr GETKEY ; get the key strok + cmp #'y' ; IF REPLY IS "Y" + beq ALLSET ; ACCEPT RESPONSES + cmp #'Y' ; get both y's + beq ALLSET + cmp #EOL ; EOL IS ALSO ACCEPTABLE + beq ALLSET + cmp #'n' ; IF REPLY IS "N" + beq NOTSAT ; return with carry set + cmp #'N' ; check both n's + beq NOTSAT + cmp #ESCAPE ; check for ESC key too + beq NOTSAT ; which means no + jsr BEEP ; ELSE BEEP + jmp GETYN ; INSIST ON Y OR N +NOTSAT: + DLINE NO ; PRINT "NO"/EOL + sec ; set the carry + rts ; and show it +ALLSET: + DLINE YES ; Print "YES"/EOL + clc ; clear the carry + rts +GETRET: + DLINE RETQ ; ask for return +GETRETL: + jsr GETKEY ; get a key + cmp #EOL ; return key? + bne GETRETL ; nope + jsr CHAR ; show the + rts + +; --------- +; SAVE GAME +; --------- +ZSAVE: + lda #'N' + ldx NARGS + beq OLDSAV ; NORMAL, COMPLETE SAVE + lda #'P' +OLDSAV: + sta TYPE + jsr SAVRES ; set up screen + jsr GET_SNAME ; get the name of the save file + bcs ZSEXIT ; don't wanna after all + jsr OPEN_SAVE ; open the file + bcs ZSEXIT ; don't really care to +; +; SAVE GAME PARAMETERS IN [BUFSAV] +; + lda ZBEGIN+ZID ; MOVE GAME ID + sta BUFSAV+0 ; INTO 1ST 2 BYTES + lda ZBEGIN+ZID+1 ; OF THE A + sta BUFSAV+1 + lda ZSP+LO ; MOVE [ZSP] + sta BUFSAV+2 + lda ZSP+HI + sta BUFSAV+3 + lda OLDZSP+LO + sta BUFSAV+4 + lda OLDZSP+HI ; MOVE [OLDZSP] + sta BUFSAV+5 + ldx #2 ; MOVE CONTENTS OF [ZPC] +ZSL1: lda ZPC,X ; TO BYTES 7-9 + sta BUFSAV+6,X ; OF [BUFSAV] + dex + bpl ZSL1 + lda TYPE + sta BUFSAV+9 ; NORMAL OR PARTIAL + cmp #'P' + bne ZSNONM ; NORMAL SAVE SO NO name TO SAVE + + lda ARG3+LO ; set up FPC to get save name + sta FPCL ; lo part is okay + lda ARG3+HI ; get page + jsr SETPC ; get memory addr + sta FPCH ; page number + sty FPCBNK ; and bank + jsr FETCHB ; get count + sta I ; and save it + jsr NEXTFPC ; point to next byte + lda #0 ; set up data offset + sta J ; did it +ZSL3: + jsr FETCHB ; get data byte + ldy J ; get offset + sta BUFSAV+10,Y ; save into buffer + jsr NEXTFPC ; point to next byte + inc J ; next byte + dec I ; count it + bne ZSL3 ; loop again +ZSNONM: +; +; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK +; + lda #MAIN ; in the main bank + sta DSKBNK ; thank you + lda #>LOCALS ; start at locals + sta DBUFF+HI ; POINT TO THE PAGE + jsr PUTDSK ; AND WRITE IT OUT + bcc ZSOK ; IF SUCCEEDED, WRITE STACK +ZSBAD: + jsr DISK_ERR ; print error message + SET_EOF SETEOF_PB ; clear out file, maybe +ZSEXIT: + jsr CLOSE_SAVE ; else get game file back + jmp RET0 ; AND FAIL +; +; IF A PARTIAL SAVE WRITE FROM ARG1 FOR ARG2 BYTES TO DISK +; (ROUNDED TO PGS) SKIPPING ZSTACK WRITE +; +ZSOK: + lda TYPE + cmp #'P' + bne ZSALL + lda ARG1+HI ; find where to start & how far to go + jsr SETPC ; get page in memory + pha ; save for minute + and #$01 ; check for odd page + beq ZSP1 ; nope, don't make one more page + inc ARG2+HI ; go get one more page +ZSP1: + pla ; get it back + and #$FE ; must be on block boundary + sta DBUFF+HI ; this is page + sty DSKBNK ; which bank + ldx ARG2+HI ; get MSB of count + lda ARG1+LO ; get lo offset + clc ; add + adc ARG2+LO ; lo count + bcc ZSPINC ; no extra page + inx ; wrapped extra page +ZSPINC: + bne SAVE2DISK ; go copy it now +; +; WRITE CONTENTS OF Z-STACK TO DISK +; +ZSALL: + lda #>ZSTKBL ; point to 1st page + sta DBUFF+HI + jsr PUTDSK ; write them, first one + bcs ZSBAD + jsr PUTDSK ; write them, second one + bcs ZSBAD +; +; WRITE ENTIRE GAME PRELOAD TO DISK +; + lda #>ZBEGIN ; POINT TO 1ST PAGE + sta DBUFF+HI ; OF PRELOAD + ldx ZBEGIN+ZPURBT ; GET # IMPURE PAGES +SAVE2DISK: + inx ; use for counting + stx I+LO + lsr I+LO ; /2 for 512byte pages + bcc ZSL2 ; no wrapping + inc I+LO ; wrapped once +ZSL2: + jsr PUTDSK ; this does the write + bcs ZSBAD + dec I+LO ; count one page + bne ZSL2 ; not done yet + + jsr CLOSE_SAVE ; prompt for game file + + IF CHECKSUM == 1 + lda CKS_COUNT + jsr HEXNUM + lda CKSB + jsr HEXNUM + lda #EOL + jsr CHAR + ENDIF + + lda #1 ; set to mark + ldx #0 + jmp PUTBYT ; SUCCESS + +; ------------ +; RESTORE GAME +; ------------ + +ZREST: + lda #'N' + ldx NARGS + beq OLDRES ; NORMAL, COMPLETE RESTORE + lda #'P' ; partial restore +OLDRES: + sta TYPE ; save which kind of restore +; +; SAVE LOCALS IN CASE OF ERROR +; + ldx #31 +LOCSAV: lda LOCALS,X ; COPY ALL LOCALS + sta LOCAL_SV,X ; to a save spot + dex + bpl LOCSAV + + jsr GET_SNAME ; get the name of the file + bcs ZRQUIT ; okay, don't do it + jsr OPEN_RES ; open the restore file + bcs ZRBAD ; can't do it + + lda TYPE ; PARTIAL SAVE DIFFERS STARTING HERE + cmp #'P' + bne ZRNRML + jmp ZPARTR ; just a partial restore +ZRNRML: + lda #MAIN + sta DSKBNK ; SET TO WRITE TO MAIN BANK + lda #>LOCALS + sta DBUFF+HI + lda #2 ; must read in two pages + sta L+LO + jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + bcs ZRBAD ; didn't work! + lda READ_PB+RD_LENGTH+HI ; see how much was read in + cmp #2 ; were 2 blocks read in? + bne ZRQUIT ; wrong kind of file for complete save + + lda BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID + cmp ZBEGIN+ZID ; MATCH THE CURRENT ID? + bne ZRQUIT ; WRONG DISK IF NOT + + lda BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE? + cmp ZBEGIN+ZID+1 + beq ZROK ; CONTINUE IF BOTH BYTES MATCH + bne ZRQUIT ; skip disk error message +; +; HANDLE RESTORE ERROR +; +ZRBAD: + jsr DISK_ERR ; print error message +ZRQUIT: + ldx #31 ; RESTORE ALL SAVED LOCALS +ZRL2: lda LOCAL_SV,X + sta LOCALS,X + dex + bpl ZRL2 +BADRES: + jsr CLOSE_SAVE ; PROMPT FOR GAME DISK + jmp RET0 ; PREDICATE FAILS +; +; CONTINUE RESTORE +; +ZROK: + lda ZBEGIN+ZFLAGS ; save both flag bytes + sta J+LO + lda ZBEGIN+ZFLAGS+1 + sta J+HI + + lda #>ZSTKBL ; retrieve old contents of + sta DBUFF+HI ; z-stack + lda #4 ; do 4 pages + sta L+LO ; tell GETRES how many pages + jsr GETRES ; get 4 pages of z-stack + bcc ZROKL1 + jmp DISK_FATAL ; if here, mix of good & bad so die +ZROKL1: + lda #>ZBEGIN ; get where we are + sta DBUFF+HI + lda ZBEGIN+ZPURBT ; get # pages to load + sta I+LO + inc I+LO ; go get last page if possible +LREST0: + lda I+LO ; how many pages left + beq LRESTj ; finis + sec ; doing subtract + sbc #4 ; doing it 4 blocks at a time + bcc LREST1 ; <4 blocks left so deal with it special + sta I+LO ; save remenants +LREST: + lda #4 ; assume at least 4 pages + sta L+LO ; this tells GETRES how many to read in + jsr GETRES ; fetch the remainder + bcc LREST0 + jmp DISK_FATAL +LREST1: + lda I+LO ; get how many left + sta L+LO ; and show it to GETRES + and #$1 ; is it odd? + beq LREST2 ; nope + inc L+LO ; read one more +LREST2: + jsr GETRES ; and finish it up +; +; RESTORE THE STATE OF THE SAVED GAME +; +LRESTj: + lda J+LO ; RESTORE THE STATE + sta ZBEGIN+ZFLAGS ; OF THE FLAG WORD + lda J+HI + sta ZBEGIN+ZFLAGS+1 + + lda BUFSAV+2 ; RESTORE THE [ZSP] + sta ZSP+LO + lda BUFSAV+3 + sta ZSP+HI + lda BUFSAV+4 + sta OLDZSP+LO + lda BUFSAV+5 ; AND THE [OLDZSP] + sta OLDZSP+HI + + ldx #2 ; RESTORE THE [ZPC] +ZRL4: lda BUFSAV+6,X + sta ZPC,X + dex + bpl ZRL4 + +ZROUT: jsr CLOSE_SAVE ; PROMPT FOR GAME DISK + jsr VLDZPC ; MAKE VALID (MUST DO AFTER GET DISK) + + IF CHECKSUM == 1 + lda CKS_COUNT + jsr HEXNUM + lda CKSB + jsr HEXNUM + lda #EOL + jsr CHAR + ENDIF + + lda #2 ; SET TO + ldx #0 + jmp PUTBYT ; SUCCESS + + + ; DO PARTIAL RESTORE GETTING 1ST PAGE + ; AND LAST PAGE BYTE ALIGNMENT CORRECT + ; WRITE LOCALS TO IOBUFF JUST TO LOOK AT NAME +ZPARTR: + lda #MAIN + sta DSKBNK + lda #>IOBUFF ; DON'T READ TO LOCALS YET (X) + sta DBUFF+HI + lda #2 ; just one block please + sta L+LO + jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + bcc ZRN2 ; worked just fine +ZPBAD: + jmp BADRES ; names don't match, die +ZRN2: + lda ARG3+LO ; set up FPC to get save name + sta FPCL ; lo part is okay + lda ARG3+HI ; get page + jsr SETPC ; get memory addr + sta FPCH ; page number + sty FPCBNK ; and bank + jsr FETCHB ; get count + sta I ; and save it + jsr NEXTFPC ; point to next byte + lda #IOBUFF ; get 1st page + sta DBUFF+HI ; getres should keep in iobuff + sta ZPARTMOD+2 ; and show where to get it from + lda #$01 ; is it odd + bit SPCH ; get page destination + beq ZPARTx ; nope + inc ZPARTMOD+2 ; then get second page worth +ZPARTx: + lda #2 ; just do one block + sta L+LO + jsr GETRES + bcc ZPART0 + jmp DISK_FATAL ; ALL MESSED UP, JUST QUIT +ZPART0: + ldy ARG1+LO ; START BYTE FIRST PAGE +ZPARTMOD: + lda IOBUFF,Y ; this gets modified with good page # + jsr STASHB + jsr NEXTSPC + jsr DECJ + bcs ZPART1 ; CARRY CLEAR IF $FFFF RESULT + jmp ZROUT +ZPART1: + inc ARG1+LO + bne ZPART0 + lda #>IOBUFF+1 ; this is second page address + cmp ZPARTMOD+2 ; is it second one already? + beq POK ; yes, so read in a new block + sta ZPARTMOD+2 ; then update it + bne ZPART0 ; and do it again +; +; THE OLD SAVE & RESTORE STILL HAVE OPCODES +; SO JUST PUT IN A PLACE FOR THEM HERE FOR NOW +; +OSAVE: +OREST: RTS + +ZISAVE: +ZIREST: JMP RET0 ; NOT IMPLEMENTED ON APPLE + END diff --git a/apple/yzip/rel.15/zstring.asm b/apple/yzip/rel.15/zstring.asm new file mode 100644 index 0000000..0d23bdb --- /dev/null +++ b/apple/yzip/rel.15/zstring.asm @@ -0,0 +1,443 @@ + PAGE + STTL "--- Z-STRING HANDLERS ---" + +; ----------------------- +; POINT MPC TO ZSTRING IN [I], using SOFF +; ----------------------- + +SETSTR: + lda I+LO + sta MPCL ; save in lo part + lda I+HI + sta MPCM ; middle part + lda #0 ; clear hi part + sta MPCH ; okay, we did + asl MPCL ; *2 + rol MPCM + rol MPCH + asl MPCL ; *4 + rol MPCM + rol MPCH +; +; now add the offset +; + lda MPCL ; carry clear from above + adc SOFFL ; add lo part of offset + sta MPCL ; save + lda MPCM + adc SOFFM + sta MPCM + lda MPCH + adc SOFFH + sta MPCH + jmp VLDMPC ; make MPCPNT to it + + +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 #$FA ; what to add to get offset into char table +TOASC: + sta TOASCM+1 ; modify code + lda ZCHAR ; use char as offset + clc ; make char be an index +TOASCM: adc #6 ; we just did + tax ; now use as index + lda CHARSET,X ; go get that char in charset zero +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 #20 ; skip into Charset 1 part of table + bne TOASC ; fix just like the others +; +; PRINT FROM CHARSET #2 +; +SET2: + lda ZCHAR ; retrieve the z-char + cmp #6 ; is it a special ascii char? + beq DIRECT ; yes, so do it special + lda #46 ; nothing special, just get offset + bne TOASC ; and jump +; +; 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 + bne 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 +; +; set up FPC to point to FWORDS table +; + ldx FWORDS+ABANK + stx FPCBNK + ldx FWORDS+HI + stx FPCH + ldx FWORDS+LO + stx FPCL + jsr ADDFPC ; add offset of the F-word + jsr FETCHB ; and get MSB of F-word + sta I+HI ; and save it + jsr NEXTFPC ; and point to LSB + jsr FETCHB ; and get it + sta I+LO ; and save it +; +; 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 SETFWD ; 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 + JSR VLDMPC + JMP PZTOP ; CONTINUE INNOCENTLY + + +; ---------------------- +; RETURN CURRENT CHARSET +; ---------------------- + +GETSET: LDA TSET + BPL GS + LDA PSET + RTS +GS: LDY #$FF + STY TSET + RTS + + +; ------------------------- +; POINT [I] AT FWORD STRING +; ------------------------- + +SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS + ASL A + STA MPCL + LDA I+HI + ROL A + STA MPCM + LDA #0 + ROL A + STA MPCH + JMP VLDMPC + + +; ----------------- +; 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 #5 ; FILL OUTPUT BUFFER + ldx #8 ; WITH PAD CHARS ($05) +CZSL: + sta OUT,X + dex + bpl CZSL + + lda #9 ; 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 CSHIP1 ; a pad char +NEXTZ: + jsr FINDCHAR ; find out where it tis + beq CSHIP ; no shift for charset zero + clc ; else do a temp-shift + adc #3 ; 4 = charset 1, 5 = charset 2 + jsr CSTASH ; save the char in outbuf + cmp #5 ; charset 2? + bne CSHIP ; nope + cpx #6 ; ascii escape? + bne CSHIP ; nope +; +; Handle special Ascii escape sequence +; + txa ; get ASCII alert char (#6) + jsr CSTASH ; shove it away +; +; do 1st half of "direct" +; + lda ZCHAR ; re-fetch char + lsr A ; get upper 2 bits in lower 2 bits + lsr A + lsr A + lsr A + lsr A + jsr CSTASH +; +; SEND 2ND HALF OF "DIRECT" +; + lda ZCHAR ; get char yet again + and #%00011111 ; and get lower 5 bits + tax ; this is where it is expected +; +; SHIP Z-CHAR TO OUTPUT BUFFER +; +CSHIP: + txa ; get char +CSHIP1: + jsr CSTASH ; put char away + bne CONTOP ; do again +; +; FINDCHAR - look through the charset table for the character. If found, +; figger out which shift it is. If not found, return charset 2, +; character #6. +; Enter: +; [A] = Char we are looking for +; Returns: +; [A] = Charset (0-2) +; [X] = Character # (6-31) +; +FINDCHAR: + ldx #0 ; start at first char, first set + ldy #78 ; there are 78 characters +FNDCL: + cmp CHARSET,X ; found it? + beq FNDCLX ; yes + inx ; next char + dey ; count char + bne FNDCL ; go check next char +; +; not found in table, use ASCII escape sequence +; + lda #2 ; escape sequence is char set 2 + ldx #6 ; character 6 + rts ; and done +FNDCLX: + txa ; put here for compares/action + ldy #0 ; this is char set 0 + ldx #$FA ; what to "subtract" to get +6 + cmp #26 ; how we doin'? + bcc FNDCHX ; all done + iny ; char set 1 + ldx #20 ; char set 1 offset + cmp #52 ; well? + bcc FNDCHX ; must be char set 1 + ldx #46 ; for char set 2 setting up + iny ; must be char set 2 then +FNDCHX: + stx FNDCHM+1 ; what to subtract to get offset + sec ; doing subtract +FNDCHM: sbc #6 ; make good offset + tax ; put here for return + tya ; and here to set flag + rts +; +; CSTASH - put the char in OUT. If we run out of room don't return, just +; jump to ZCRUSH as final destination +; [A] - char to be put away +; +CSTASH: + ldy CONOUT ; fetch output index + sta OUT,Y ; send the shift char + inc CONOUT ; update index + dec CONCNT ; and char count + bne CSTX ; plenty more room + pla ; get rid of return spot + pla ; fine + jmp ZCRUSH ; if out of room, crush 'em! +CSTX: + rts +; ---------------------- +; CRUSH Z-CHARS IN [OUT], mushing them into small 5 bit pieces +; ---------------------- +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 + STA OUT+2 ; MOVE CRUSHED Z-WORD + STX OUT+3 ; INTO PLACE + LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) + ASL A ; SHIFT BITS + ASL A + ASL A + ASL A + ROL OUT+6 ; ALONG WITH 7TH Z-CHAR + ASL A + ROL OUT+6 + ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR + STA OUT+5 ; SAVE HERE + LDA OUT+6 ; GRAB 7TH Z-CHAR + ORA #%10000000 ; SET HIGH BIT + STA OUT+4 ; MOVE CRUSHED Z-WORD INTO PLACE + RTS + + END + diff --git a/apple/yzip/rel.9/apple.equ b/apple/yzip/rel.9/apple.equ new file mode 100644 index 0000000..fb84363 --- /dev/null +++ b/apple/yzip/rel.9/apple.equ @@ -0,0 +1,298 @@ + STTL "--- APPLE ][ HARDWARE STUFF ---" + PAGE +; ------------------- +; APPLE II MEMORY MAP +; ------------------- +AUX EQU 1 ; offset to Auxillary mem switches +MAIN EQU 0 ; for main memory switches + +; +; some hardware spots +; +SCREEN EQU $2000 ; START OF Double HiRes SCREEN RAM + +PRGLBL EQU $BF00 ; ProDOS Globals page in main mem +PR_BITMAP EQU $BF58 ; ProDOS system bitmap +KVERSION EQU $BFFF ; ProDOS version (== $FF if InfoDOS) +INFODOS_ID EQU $FF + +IOADDR EQU $C000 ; start of I/O registers +PROADR EQU $D000 ; start of ProDOS + +LBUFF EQU $0200 ; LINE INPUT BUFFER +PIC1BUF EQU $0300-141 ; we can use line buffer for one picture buffer +SCRBUFF EQU LBUFF+$80 ; screen line buffer +BORG EQU $2000 ; ORIGIN OF .SYSTEM CODE +; +; some page 3 storage relocated stuff +; +PAGE3STUFF EQU $300 +MOUSER EQU PAGE3STUFF ; this is where mouse subroutine goes +COLORS EQU MOUSER+$12 +XPOSTBL EQU COLORS+$40 + +SV_PCL EQU $400 ; for scrolling data +SV_PCH EQU $600 + +IOBUFF EQU $0800 ; 1Kb DATA BUFFER BUFFER + +PAGING_MEM EQU IOBUFF+$400 ; Paging table stuff +NEXTPNT EQU PAGING_MEM +PREVPNT EQU NEXTPNT+$40 +VPAGEH EQU PREVPNT+$40 +VPAGEL EQU VPAGEH+$40 +PAGELEN EQU $200 ; length of paged read + +ZSTKBL EQU PAGING_MEM+$100 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) +ZSTKTL EQU ZSTKBL+$100 ; TOP, LO +ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI +ZSTKTH EQU ZSTKBL+$300 ; TOP, HI +; +; now define some file i/o buffers and such +; +GAME1FIO EQU ZSTKBL+$400 ; Game file I/O buffer +GAME2FIO EQU GAME1FIO+$400 ; Second game file i/o buffer +SEGTBL EQU GAME2FIO+$400 ; segment table for multi disks +PIC2BUF EQU SEGTBL+($400-140) ; picture buffer is 140 bytes long +TCHARTBL EQU SEGTBL+$400 ; 208 bytes for (possible) terminating +COPY_LINE EQU TCHARTBL+$50 ; copy line in screen memory +CPY_MOD1_SRC equ COPY_LINE+$2C ; special self-modifying places +CPY_MOD1_DST equ CPY_MOD1_SRC+3 +CPY_MOD2_SRC equ COPY_LINE+$50 +CPY_MOD2_DST equ CPY_MOD2_SRC+3 + +DSKSEG EQU TCHARTBL+$D0 ; spot to stash pointers for disk segments +D1SEG EQU DSKSEG ; where in SEGTBL for Disk 1 +D2SEG EQU D1SEG+2 +D3SEG EQU D2SEG+2 +D4SEG EQU D3SEG+2 +D5SEG EQU D4SEG+2 +D6SEG EQU D5SEG+2 +D7SEG EQU D6SEG+2 +D8SEG EQU D7SEG+2 +LOCAL_SV EQU TCHARTBL+$E0 ; to save locals before restore +LOCALS EQU TCHARTBL+$100 ; LOCAL VARIABLE STORAGE (30 BYTES) +BUFSAV EQU LOCALS+$20 ; TEMP SPACE FOR SAVE/RESTORE (80 BYTES) +SCR_LINE EQU LOCALS+$100 ; place to build displayed line +CHARSET EQU SCR_LINE+140 ; spot for charset to go +; +; now for some interpreter data +; +INTR_BEGIN EQU $4000 ; START OF Interpreter CODE in main +INTR_SIZE EQU (43*512) ; size of interpreter + +ZBEGIN EQU (INTR_BEGIN+INTR_SIZE) ; start of Z code +MMSIZE EQU PRGLBL-INTR_BEGIN ; free memory in main bank +Z1SIZE EQU >(PRGLBL-ZBEGIN) ; size of preload, part 1 +; +; this is in Bank 2, Main mem +; +; +; Picture directory goes in Bank 2, Aux mem +; +PIC_DIR EQU $D000 ; picture local directory +GBL_DIR EQU $DC00 ; global directory +; +; some special markers if we are using InfoDOS +; +SP_BANK EQU MAIN +SP_START EQU $D000 ; start of special area +SP_SIZE EQU ((($FE->SP_START)*256)/512) ; how many pages +;SP_SIZE EQU (((>SCREEN->SP_START)*256)/512) ; how many pages + +PB_BANK EQU AUX ; paging buffers in which bank +PBEGIN EQU $0800 ; start of paging buffers +NUMBUFS EQU >(SCREEN-PBEGIN) ; how many 256k paging buffers +;NUMBUFS EQU >($100-PBEGIN) ; how many 256k paging buffers + +P2PAGE EQU >(PRGLBL-ZBEGIN) ; first page of zcode in aux bank +Z2BEGIN EQU $4000 ; start of part 2 in aux mem + ; just after the dhires screen +Z2PAGE EQU >Z2BEGIN ; get me just the page address +Z2SIZE EQU >(PRGLBL-Z2BEGIN) ; size of preload, part 2 +P3PAGE EQU Z1SIZE+Z2SIZE ; first page in aux mem part 3 +Z3BEGIN EQU $D000 ; start of 3 part in aux mem +Z3PAGE EQU >Z3BEGIN ; get me page number too +Z3SIZE EQU <($FE-Z3PAGE) ; size of part 3, in pages + +; +; other numba's +; +PGBEGIN EQU (P3PAGE+Z3SIZE) ; first paged page +PRESIZE EQU (Z1SIZE+Z2SIZE+Z3SIZE) ; size of preload, # pages +SCRSZE EQU INTR_BEGIN-SCREEN ; size of Double HiRes screen (8k, each bank) +RAMDSK EQU (119*512) ; size of RAM disk in aux mem +RAMSAVE EQU $B500 ; save this much to cover HiRes screen in + ; aux and the rest of the preload, up to + ; PRGLBL ($bf00) +FREERAM EQU RAMDSK-RAMSAVE ; size of Free RAM after 'saving' + ; special AUX memory +DSKSZE EQU (512*273) ; size of ProDOS data disk file + +; --------- +; CONSTANTS +; --------- + +IIeID EQU 2 ; Apple ][e Yzip +IIcID EQU 9 ; ][c Yzip +IIgsID EQU 10 ; ][gs Yzip + +P3BANK EQU $FF ; show upper aux mem +LO EQU 0 +HI EQU 1 +ABANK EQU 2 ; for address variables + +OFF EQU 0 ; for toggling soft-switches +ON EQU 1 + +RETRY_COUNT EQU 3 ; how many retries before message + +TAB EQU $09 ; Tab char +EOS EQU $0B ; End of Sentence +EOL EQU $0D ; EOL CHAR +LF EQU $0A ; LINE FEED +SPACE EQU $20 ; SPACE CHAR +BACKSPACE EQU $08 ; BACKSPACE CHAR +ESCAPE EQU $1B ; ESCAPE Key +VOLCHAR EQU '?' ; Key to hit for ONLINE command +; +; Screen Defs +; +MAXWIDTH EQU 140 ; 560 / 4 = max "pixels" +REAL_MAXW EQU MAXWIDTH*4 +MAXHEIGHT EQU 192 ; 192 screen lines +FONT_W EQU 2 ; font width (for game, anyway) +FONT_H EQU 9 ; font height +MFONT_W EQU 3 ; mono spaced font width, to game +MONOFONT_W EQU MFONT_W*4 ; how wide the mono font really is + +SPACE_WIDTH EQU 8 ; default space width +BLINK_RATE EQU 3 ; tenths of seconds between blinks + +OUTER_DELAY EQU $1C ; outside delay loop counter +INNER_DELAY EQU 3 ; inner delay loop + +GS_OUTER_DELAY EQU $72 ; ][gs outside counter +GS_INNER_DELAY EQU 2 ; ][gs inside counter + +; ---------------------- +; BOOT ZERO PAGE EQUATES +; ---------------------- + +BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS +BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT + +START_NAME EQU $280 ; name upon boot is stored here +; ---------------- +; HARDWARE EQUATES +; ---------------- + +KBD EQU $C000 ; KEY STROBE +STORE80 EQU $C000 ; video aux mem switch +RDBNK EQU $C002 ; READ MAIN MEMORY (+MAIN, +AUX) +WRTBNK EQU $C004 ; WRITE MAIN 48K OF MEMORY (+MAIN, +AUX) +ALTZP EQU $C008 ; R/W MAIN (C009 = AUX) >MEM +COL80SW EQU $C00C ; 80 Column switch +ANYKEY EQU $C010 ; ANY KEY DOWN FLAG +VERTBLNK EQU $C019 ; Vertical Blanking Flag +IIGSVID EQU $C029 ; GS MEGA ][ video register +SPKR EQU $C030 ; SPEAKER FLAG (MAKE A NOISE) +IIGSSHD EQU $C035 ; ][GS shadowing reg +TEXTSW EQU $C050 ; Graphics Switch +MIXEDSW EQU $C052 ; Mixed Text/Graphics +PAGE2SW EQU $C054 ; Page select +HIRESSW EQU $C056 ; Select HiRes +DHIRESW EQU $C05E ; Double HiRes switch (backwards: +0 on +1 off) +IOUDIS EQU $C07E ; Double HiRes Switch enabler (same backass way) +BNK2SET EQU $C083 ;READ/READ READ RAM WRITE RAM BANK 2 +BNK1SET EQU $C08B ;READ/READ READ RAM WRITE RAM BANK 1 +RDROM EQU $C082 ; READ READ ROM NO WRITE +RDBNK1 EQU $C088 ; READ ram, bank 1 +RDBNK2 EQU $C080 ; Read ram, bank 2 + +; ----------------- +; MONITOR VARIABLES +; ----------------- + +CSW EQU $36 ; CHARACTER OUTPUT VECTOR (for scripting) +APKEY1 EQU $C061 ; open apple key flag +APKEY2 EQU $C062 ; closed apple key flag + +CURSW EQU 2 ; width of cursor +CURSH EQU 4 ; height of cursor +; ----------- +; MOUSE STUFF +; ----------- +MTABLE EQU $C412 ; Mouse ROM table +MSVECTOR EQU MOUSER+16 ; where vector is stored +MSMOVEF EQU MSVECTOR+2 ; Mouse moved flag +MSBTNF EQU MSMOVEF+1 ; Mouse button flag +; +; MOUSE screen holes +; +CLMPMINL EQU $478 ; lo part of clamping min +CLMPMINH EQU $578 ; hi part of " " +CLMPMAXL EQU $4F8 ; lo part of clamping max +CLMPMAXH EQU $5F8 ; hi part of " " +MOUSEXL EQU $478 ; lo part of mouse X +MOUSEXH EQU $578 ; hi part of mouse X +MOUSEYL EQU $4F8 ; lo part of mouse Y +MOUSEYH EQU $5F8 ; hi part of mouse Y +MOUSEST EQU $778 ; status byte +; +; some mouse constants +; +SGL_CLK EQU $81 ; single click char +DBL_CLK EQU $82 ; double click char +CLK_CNT EQU 6 ; counts between single and double click +; Subroutine offsets +SETM EQU 0 +SERVEM EQU 1 +READM EQU 2 +CLEARM EQU 3 +POSM EQU 4 +CLAMPM EQU 5 +HOMEM EQU 6 +INITM EQU 7 + +; -------------- +; PRODOS GLOBALS +; -------------- +PRODATE EQU $BF90 ; date and +PROTIME EQU $BF92 ; time +MACHID EQU $BF98 ; machine id + +; ---------------- +; MONITOR ROUTINES +; ---------------- +MPREAD EQU $FB1E ; Read for joystick control +MBASCAL EQU $FC22 ; CALC LINE BASE ADDRESS +MBELL EQU $FF3A ; MAKE A NOISE +RESET_VECTOR EQU $FFFC ; force warm reboot +MCLEOL EQU $FC9C ; CLEAR TO END OF LINE +MCLEOS EQU $FC42 ; CLEAR TO END OF SCREEN +MHOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR +MCOUT EQU $FDED ; CHAR OUTPUT +MCOUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN +MRDKEY EQU $FD0C ; READ KEY +MGETLN1 EQU $FD6F ; GET LINE +MWAIT EQU $FCA8 ; WASTE SO MUCH TIME +; +; Some /RAM spots +; +RAMVEC EQU $BF26 ; /RAM drive vector +OLDVEC EQU $77E ; spot to save the drive vector +UNSVEC EQU $BF16 ; "Uninstalled Device" vector +DEVCNT EQU $BF31 ; Device count +DEVNUM EQU $BF32 ; Device list + +; +; machine info spots +; +MACHID1 EQU $FBB3 ; first part +MACHID2 EQU $FBC0 ; second part +MACHCHK EQU $FE1F ; differentiate between ][e and gs + ; do sec, then jsr, and if still set, = ][e + END + + diff --git a/apple/yzip/rel.9/boot.asm b/apple/yzip/rel.9/boot.asm new file mode 100644 index 0000000..f105000 --- /dev/null +++ b/apple/yzip/rel.9/boot.asm @@ -0,0 +1,380 @@ + TITLE "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + + INCLUDE ZIP.EQU + INCLUDE ZERO.EQU + INCLUDE PRODOS.EQU + INCLUDE APPLE.EQU + INCLUDE MACROS.ASM + + STTL "--- APPLE ProDOS BOOT CODE ---" + PAGE + +CHZ EQU $24 ; CURSOR HORIZONTAL +EHZ EQU $57B ; CURSOR HORIZONTAL +CVT EQU $25 ; CURSOR VERTICAL + +; +; my own little error checking macro +; +ERRVAL .VAR 0 +; +; this macros checks for carry being set (ProDOS error) and if it is +; loads an error code in x and jumps to the error handler +ERRCHK .MACRO +ERRVAL .VAR ERRVAL+1 + bcc BOOT| + ldy #ERRVAL + jmp BOOT_ERROR +BOOT|: + .MACEND + + ORG BORG + jmp BOOT_BEGIN ; just jump to beginning +PROGNAME: + BLKB 9,0 ; 8 bytes for name + 1 for ending zero +BOOT_BEGIN: + lda RDROM ; swap in rom + sta TEXTSW+ON ; turn on text + sta COL80SW+OFF ; turn on 80 column + +; +; make sure we are on a ][c, or ][e+ +; + jsr MACHINE ; check it out, returns if good + lda ARG2+LO ; check machine + cmp #IIgsID ; 2gs? + bne ZBOOTGS ; nope + lda IIGSVID ; get current video setting + and #$1F ; turn off upper 3 bits + sta IIGSVID ; make sure double hires works + lda IIGSSHD ; get shadowing reg + and #$A0 ; turn on shadowing everywhere + sta IIGSSHD ; okay +ZBOOTGS: + jsr FIXRAM ; check and clear RAM disk + jsr DO_PREFIX ; go set my current prefix + + jsr MHOME ; clear and home + lda #9 ; CENTER DISPLAY + sta CVT + lda #8 + sta CHZ + sta EHZ + jsr MBASCAL ; move cursor there! + DLINE STRYM +; +; move down to lower left and print out version number +; + lda #21 + sta CVT + lda #1 + sta CHZ ; move to 1,20 + sta EHZ + jsr MBASCAL ; move cursor there! + DLINE VERMSG ; show me the version + lda #VERSID/10 ; get version + ora #$B0 ; make normal char for ][ + jsr MCOUT + lda #VERSID.MOD.10 + ora #$B0 ; make normal char for ][ + jsr MCOUT + + lda #$FF ; init invflg to normal + sta INVFLG ; okay + + lda #0 ; zero out bit map + ldx #$17 ; 17 bytes in ProDOS system bitmap +CLRPRD: + sta PR_BITMAP,X ; and zero out the memory + dex + bpl CLRPRD ; and zero entire bitmap + + lda #$C0 ; start out the bitmap with c0 at start + sta PR_BITMAP + lda #$01 ; and a 1 at the end + sta PR_BITMAP+$17 ; thankx +; +; now we need to load in the interpreter +; + OPEN INTR_OPEN ; open up interpreter file + ERRCHK + + lda INTR_OPEN+OP_REFNUM ; get refnum for intr file + sta READ_BLOCK+RD_REFNUM ; and save for read + sta CLOSE_BLOCK+CL_REFNUM ; close up interpreter file + + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now +RDINTR: + READ READ_BLOCK ; read in interpreter + bcc RDINTR1 ; it worked fine + dec RETRIES ; try again + bpl RDINTR ; fine + ERRCHK ; then just die +RDINTR1: + CLOSE CLOSE_BLOCK ; done with interpreter +; +; now read in first part of preload +; + ldx #0 ; start at first letter +MVPRE: + lda PROGNAME,X ; get letter + beq MVPREX ; all done + sta PRE_NAME,X ; save letter + inx ; next letter + bne MVPRE ; do gen +MVPREX: +; +; now add on ".d1" suffix for the preload +; + lda #'.' ; get '.' + sta PRE_NAME,X ; save it + inx ; next char + lda #'D' ; 'D' char + sta PRE_NAME,X ; save it + inx ; next char + lda #'1' ; preload is .1 + sta PRE_NAME,X ; saved + inx ; count the .1 + stx PRELOAD_NAME ; save length of name + + OPEN PRELOAD_OPEN ; so now open preload file + ERRCHK + + lda PRELOAD_OPEN+OP_REFNUM ; get refnum + sta READ_BLOCK+RD_REFNUM ; save refnum for read + sta PSEEK+SM_REFNUM ; and for moving around +; +; first, get the segment table +; + lda #>IOBUFF ; just read in size + sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + lda #4 ; read in first 1 Kb + sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + lda #0 ; get size in words + sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + + READ READ_BLOCK ; and read first block + ERRCHK +; +; now copy segtable to low mem +; + lda #>IOBUFF + sta J+HI + lda #(SEGTBL-2) + sta K+HI + lda #<(SEGTBL-2) + sta K+LO + + lda IOBUFF+1 ; get LSB + asl A ; *2, to pick up the carry + lda IOBUFF ; get how many words + rol A ; *2 for number of bytes + sta PSEEK+SM_FPOS+HI ; set page number + tax ; make it a counter + ldy #2 ; start at second byte, after length +CPSEGT: + lda (J),y ; get byte + sta (K),y ; save byte + iny ; next byte + bne CPSEGT ; go do it + inc J+HI + inc K+HI + ldy #0 ; restart at beginning of block + dex ; count page + bpl CPSEGT ; next page +; +; now, seek to page following seg table +; + inc PSEEK+SM_FPOS+HI ; next page + lda PSEEK+SM_FPOS+HI ; make sure it is an even 512 page + and #$01 ; is it odd? + beq BTSK0 ; nope, so we be okay + inc PSEEK+SM_FPOS+HI ; next page + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now +BTSK0: + SET_MARK PSEEK ; and point to beginning of game data + + lda #>ZBEGIN ; begining of game code + sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + lda #(Z1SIZE&$FE) ; get size + sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + lda #0 ; get size in words + sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + READ READ_BLOCK ; and read in part 1 of preload + bcc BTSK00 ; just fine + dec RETRIES ; try again + bpl BTSK0 ; fine + ERRCHK ; then just die +BTSK00: + lda #4 ; 4 pages per read + sta READ_BLOCK+RD_BUFFLEN+HI ; and lots + lda #>IOBUFF ; read into my io buffer + sta READ_BLOCK+RD_BUFFER+HI ; hi part of address + + IF Z1SIZE & 1 ; if odd, do something special + READ READ_BLOCK + ldy #0 ; copy second page +C2LOOP: + lda IOBUFF,Y + sta ZBEGIN+(Z1SIZE*$100)-$100,Y + iny + bne C2LOOP + lda #(>Z2BEGIN-1) ; don't need first block + sta MODOP+2 + bne RD10 ; skip that first read + ENDIF +AUXRDL: + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now +AUXRDL0: + READ READ_BLOCK ; and do the read + bcc RD10 + cmp #$4C ; this just means EOF already + beq BT12 ; otherwise, blech + dec RETRIES ; try again + bpl AUXRDL0 ; fine + ERRCHK ; then just die +RD10: + lda #>IOBUFF ; read into my io buffer + sta CLOOP+2 ; start at IOBUFF + lda #4 ; 4 copies + sta L ; okay +RD11: + ldy #0 ; start at zero, of course + lda MODOP+2 ; check where we are reading too + beq BT12 ; wrapped, so we had better be done + cmp #>PRGLBL ; done with aux mem, part 1? + bcc LOOPST ; nope + bne RD12 ; no need to change + lda #Z3PAGE ; restart at top of memory + sta MODOP+2 ; and do some self modifying code +RD12: + sta ALTZP+AUX ; turn on alt ZP + lda BNK2SET ; write to upper mem + lda BNK2SET ; write to upper mem +LOOPST: + sta WRTBNK+AUX ; always aux mem +CLOOP: + lda IOBUFF,Y ; get char +MODOP: sta Z2BEGIN,Y ; save + iny ; point to next one + bne CLOOP ; get next one + + lda RDROM ; swap back rom, just in case + lda RDROM ; swap back rom, just in case + sta ALTZP+MAIN ; and back to main page + sta WRTBNK+MAIN ; read into main bank + + inc MODOP+2 ; point to next page + inc CLOOP+2 ; point to next page + dec L ; next page + bne RD11 ; and get it + + jmp AUXRDL ; get next 1k +BT12: + lda READ_BLOCK+RD_REFNUM ; get refnum for + sta CLOSE_BLOCK+CL_REFNUM ; closing the file + CLOSE CLOSE_BLOCK ; okay, closed +; +; relocate the Zero Page routines +; + ldx #RLCLEN ; length of routine +RLOC: + lda FETCHBx,X ; get byte + sta ZERO_FB,X ; save byte + dex ; get next one + bpl RLOC ; thank you +; +; and now for the copying screen line sub +; + ldx #CPYLEN +CPYCPLP: + lda CPYx,X + sta COPY_LINE,X + dex + bpl CPYCPLP +; +; now relocate page 3 stuff +; + ldx #PAGE3RELL+1 ; get length of page 3 stuff +MSRCL: + lda PAGE3REL-1,X ; get byte + sta PAGE3STUFF-1,X ; save byte + dex ; count byte + bne MSRCL ; get next? + + jsr ZBOOT ; set up ZIP stuff + + JMP INTR_BEGIN ; jump to the interpreter + + INCLUDE ZBOOT.ASM ; ZBOOT subroutine + INCLUDE BREL.ASM ; relocated subroutines + INCLUDE BSUBS.ASM ; subs for e to use + + PAGE + STTL "--- BOOT DATA STRUCTURES ---" +INTR_OPEN: + DB 3 ; 3 parameters + DW INTR_NAME ; name of file + DW GAME1FIO ; file data buffer + DS 1 ; refnum goes here +CLOSE_BLOCK: + DB 1 ; 1 parameter + DS 2 ; room for ref num +PSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +PRELOAD_OPEN: + DB 3 + DW PRELOAD_NAME + DW GAME1FIO ; close interpreter first! + DS 1 ; refnum here +; +; start with interpreter data +; +READ_BLOCK: + DB 4 ; 4 parms + DB 0 ; refnum + DW INTR_BEGIN ; where to start the interpreter + DW INTR_SIZE ; and how big could it be + DW 0 ; actual length of interpreter +INTR_NAME: + DB INAME_LEN ; length of name +I_NAME: + DB "INFOCOM" ; interpreter name +INAME_LEN EQU $-I_NAME + +PRELOAD_NAME: + DB 0 ; length of name +PRE_NAME: + DS 20 ; spot for preload name +PRELEN EQU $-PRE_NAME + +DH_SAVE: ; to actual 'write' the data + DB 4 ; 4 parms for write + DB 0 ; refnum goes here + DW 0 ; just 'copy' junk + DW RAMSAVE ; to preserve this much mem in AUX + DW 0 ; how much is done + +STRYM: DB "The story is loading ..." +STRYML EQU $-STRYM +MMSG: DB EOL,"Enter the letter of the pointing",EOL + DB "device you will be using:",EOL + DB "J)oystick M)ouse N)either",EOL,EOL +MMSGL EQU $-MMSG +MSLT: DB EOL,"Enter the slot number in which the",EOL + db "mouse card is installed >" +MSLTL EQU $-MSLT +MSLTBAD: DB EOL,"Slot number must be between",EOL + db "ONE and SEVEN! Try again!",EOL +MSLTBADL EQU $-MSLTBAD +VERMSG: db EOL,"Version: " +VERMSGL equ $-VERMSG + END + diff --git a/apple/yzip/rel.9/boot.bin b/apple/yzip/rel.9/boot.bin new file mode 100644 index 0000000..b5192a7 Binary files /dev/null and b/apple/yzip/rel.9/boot.bin differ diff --git a/apple/yzip/rel.9/boot.lst b/apple/yzip/rel.9/boot.lst new file mode 100644 index 0000000..b488253 --- /dev/null +++ b/apple/yzip/rel.9/boot.lst @@ -0,0 +1,2730 @@ + Wed May 24 1989 15:00 Page 1 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT DATA STRUCTURES ---" + + + + + 2500 A.D. 6502 Macro Assembler - Version 4.01a + ------------------------------------------------ + + Input Filename : BOOT.asm + Output Filename : BOOT.obj + + + 1 0000 TITLE "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + 2 + 3 0000 INCLUDE ZIP.EQU + 4 0000 STTL "--- YZIP EQUATES ---" + 5 PAGE + Wed May 24 1989 15:00 Page 2 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- YZIP EQUATES ---" + + 6 + 7 0009 VERSID EQU 9 ; VERSION OF INTERPRETER + 8 ; See file "versions" for complete descriptions + 9 + 10 00FF TRUE EQU $FF + 11 0000 FALSE EQU 0 + 12 + 13 ; --------------------- + 14 ; Segment table equates + 15 ; --------------------- + 16 0000 SGTDISKS EQU 0 ; number of disks + 17 0002 SGTPAD EQU SGTDISKS+2 ; just some extra room + 18 0012 SGTCHKS1 EQU SGTPAD+16 ; Checksum for disk 1 (PRELOAD) + 19 0014 SGTPICOF1 EQU SGTCHKS1+2 ; N/A + 20 0016 SGTSEG1 EQU SGTPICOF1+2 ; # of segments + 21 0018 SGTGPOF1 EQU SGTSEG1+2 ; Global Picture Directory + 22 001A SGTTBLS EQU SGTGPOF1+2 ; Start of table preload (should be 0) + 23 001C SGTTBLE EQU SGTTBLS+2 ; Last page of table preload + 24 001E SGTTBLX EQU SGTTBLE+2 ; N/A + 25 0020 SGTFUNS EQU SGTTBLX+2 ; First page of function preload + 26 0022 SGTFUNE EQU SGTFUNS+2 ; End page of function preload + 27 0024 SGTFUNX EQU SGTFUNE+2 ; N/A + 28 0026 SGTDSK EQU SGTFUNX+2 ; Actual start of disk segment tables + 29 + 30 0000 SGTCHKS EQU 0 ; check sum for file + 31 0002 SGTPICOF EQU 2 ; picture data offset + 32 0004 SGTNSEG EQU 4 ; # of segments in this list + 33 0006 SGTGPOF EQU 6 ; Global Directory Offset + 34 0008 SGTSEG EQU 8 ; start of segments + 35 ; --------------------- + 36 ; Z-CODE HEADER OFFSETS + 37 ; --------------------- + 38 + 39 0000 ZVERS EQU 0 ; VERSION BYTE + 40 0001 ZMODE EQU 1 ; MODE SELECT BYTE + 41 0002 ZID EQU 2 ; GAME ID WORD + 42 0004 ZENDLD EQU 4 ; # OF QUADWORDS ON SIDE 1 OF DISK + 43 0006 ZGO EQU 6 ; EXECUTION ADDRESS + 44 0008 ZVOCAB EQU 8 ; START OF VOCABULARY TABLE + 45 000A ZOBJEC EQU 10 ; START OF OBJECT TABLE + 46 000C ZGLOBAL EQU 12 ; START OF GLOBAL VARIABLE TABLE + 47 000E ZPURBT EQU 14 ; START OF "PURE" Z-CODE + 48 0010 ZFLAGS EQU 16 ; FLAG WORD + 49 0012 ZSERIA EQU 18 ; 3-WORD SERIAL NUMBER + 50 0018 ZFWORD EQU 24 ; START OF FWORDS TABLE + 51 001A ZLENTH EQU 26 ; LENGTH OF Z-PROGRAM IN WORDS + 52 001C ZCHKSM EQU 28 ; Z-CODE CHECKSUM WORD + 53 001E ZINTWD EQU 30 ; INTERPRETER ID WORD (SUPPLIED BY EZIP) + 54 0020 ZSCRWD EQU 32 ; SCREEN PARAMETER WORD ( " " " ) + 55 0022 ZHWRD EQU 34 ; DISPLAY WIDTH IN PIXELS + 56 0024 ZVWRD EQU 36 ; DISPLAY HEIGHT IN PIXELS + 57 0026 ZFWRD EQU 38 ; FONT HEIGHT, FONT WIDTH + 58 0028 ZFOFF EQU 40 ; FUNCTION OFFSET + 59 002A ZSOFF EQU 42 ; STRING OFFSET + 60 002C ZCLRWD EQU 44 ; FORGROUND COLOR, BACKGROUND COLOR + 61 002E ZTCHAR EQU 46 ; POINTER TO TBL OF TERMINATING CHARS + 62 0030 ZTWIDTH EQU 48 ; Running counter for table output char width + Wed May 24 1989 15:00 Page 3 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- YZIP EQUATES ---" + + 63 0032 ZCRFUNC EQU 50 ; FUNCTION FOR CARRIAGE RETURNS + 64 0034 ZCHRSET EQU 52 ; POINTER TO CHAR SET TBL + 65 0036 ZEXTAB EQU 54 ; Points to extension table, if needed + 66 ; + 67 ; Extension table offsets + 68 ; + 69 0000 ZEXTLEN EQU 0 ; Length of extension table + 70 0002 ZMSLOCX EQU 2 ; x location of mouse + 71 0004 ZMSLOCY EQU 4 ; y location of mouse + 72 0006 ZMSETBL EQU 6 ; MOUSE TBL CHANGE WORD + 73 0008 ZMSEDIR EQU 8 ; DIRECTION MENU + 74 000A ZMSEINV EQU 10 ; INVENTORY MENU + 75 000C ZMSEVRB EQU 12 ; FREQUENT VERB MENU + 76 000E ZMSEWRD EQU 14 ; FREQUENT WORD MENU + 77 0010 ZBUTTN EQU 16 ; BUTTON HANDLER + 78 0012 ZJOYST EQU 18 ; JOYSTICK HANDLER + 79 0014 ZBSTAT EQU 20 ; BUTTON STATUS + 80 0016 ZJSTAT EQU 22 ; JOYSTICK STATUS + 81 ; + 82 ; ZFLAGS values + 83 ; + 84 0001 FSCRI EQU $01 ; scripting? + 85 0002 FMONO EQU $02 ; mono spaced font? + 86 0004 FSTAT EQU $04 ; status line refresh? + 87 0008 FDISP EQU $08 ; uses DISPLAY operations? + 88 0010 FUNDO EQU $10 ; uses UNDO? + 89 0020 FMOUS EQU $20 ; uses mouse? + 90 0040 FCOLO EQU $40 ; uses color? + 91 0080 FMENU EQU $80 ; uses menus? + 92 ;--------------- + 93 ; Picture data + 94 ;--------------- + 95 ;=== DATA HEADER === + 96 0000 PHFID EQU 0 ; File ID + 97 0001 PHFLG EQU PHFID+1 ; Flags + 98 0002 PHHUFF EQU PHFLG+1 ; Pointer to Huffman data + 99 0004 PHNLD EQU PHHUFF+2 ; # entries in local directory + 100 0006 PHNGD EQU PHNLD+2 ; # entries in global directory + 101 0008 PHDSIZE EQU PHNGD+2 ; Local directory entry size + 102 000A PHCHKS EQU PHDSIZE+2 ; File Checksum + 103 000C PHFVERS EQU PHCHKS+2 ; File Version (N/A) + 104 000E PHEXTRA EQU PHFVERS+2 ; Extra room for getting fatter + 105 0010 PHSIZE EQU 16 ; 16 bytes is header size + 106 ;=== DATA HEADER FLAGS === + 107 0001 PHFGD EQU $1 ; data has global directory + 108 0002 PHFHUFF EQU $2 ; Huffman encoded pictures + 109 0004 PHFHUFF1 EQU $4 ; All pictures use same Huff tree + 110 0008 PHFPAL EQU $8 ; No pallette information + 111 ;=== LOCAL DIRECTORY === + 112 0000 PLDID EQU 0 ; Picture ID + 113 0002 PLDWID EQU PLDID+2 ; Picture Width + 114 0003 PLDHGHT EQU PLDWID+1 ; Picture Height + 115 0004 PLDFLG EQU PLDHGHT+1 ; Flags + 116 0005 PLDPTR EQU PLDFLG+1 ; Pointer to picture data + 117 0008 PLDSIZE EQU PLDPTR+3 ; size of local directory entry + 118 + 119 0000 END + Wed May 24 1989 15:00 Page 4 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- YZIP EQUATES ---" + + 120 + 121 0000 INCLUDE ZERO.EQU + 122 0000 STTL "--- ZERO PAGE VARIABLES ---" + 123 PAGE + Wed May 24 1989 15:00 Page 5 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 124 + 125 0000 SCRCX EQU 0 ; CURSOR HORIZONTAL + 126 0001 SCRCY EQU SCRCX+1 ; CURSOR VERTICAL + 127 0002 SCRBTM EQU SCRCY+1 ; first line outside current window + 128 0003 MAXLINES EQU SCRBTM+1 ; maximum number of lines in window + 129 0004 LEFTMRG EQU MAXLINES+1 ; left edge + left margin in current window + 130 0005 WINDOW EQU LEFTMRG+1 ; (WORD) address of current window structure + 131 0007 LINE_X EQU WINDOW+2 ; (WORD) width of line counter + 132 0009 CC_OFF EQU LINE_X+2 ; save offset for char drawing + 133 000A CLSLEFT EQU CC_OFF+1 ; screen limits for CLS code + 134 000B CLSTOP EQU CLSLEFT+1 ; top of screen + 135 000C CLSWIDTH EQU CLSTOP+1 ; # of columns + 136 000D CLSHEIGHT EQU CLSWIDTH+1 ; # of lines + 137 ; + 138 ; some variables for all the screen positioning code + 139 ; + 140 000E NY_DATA EQU CLSHEIGHT+1 ; place for GET/PUT_NYBBLE to use + 141 000F CH_OFFSET EQU NY_DATA+1 ; offset into char data table + 142 0010 DATALOOP EQU CH_OFFSET+1 ; loop counter for byte works + 143 0011 BITOFF EQU DATALOOP+1 ; bit offset into screen byte + 144 0012 CH_DATA EQU BITOFF+1 ; actual char data being worked on + 145 0013 SCR_DATA EQU CH_DATA+1 ; screen byte being worked on + 146 0014 SH_LOOP EQU SCR_DATA+1 ; loop counter for bit shifting + 147 0015 SCROLLY EQU SH_LOOP+1 ; save spot for y pos when scrolling + 148 0016 RETRIES EQU SCROLLY+1 ; (BYTE) Machine ID + 149 0017 CHRMAX EQU RETRIES+1 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD + 150 0018 SCLLINES EQU CHRMAX+1 ; (BYTE) how many lines to scroll + 151 0019 FMTTBL EQU SCLLINES+1 ; (BYTE) flag to show formatted table output + 152 001A STMASK EQU FMTTBL+1 ; (BYTE) Mask to use on first byte of CLS + 153 001B ENDMASK EQU STMASK+1 ; (BYTE) Mask to use on last byte of CLS + 154 001C CHPTR EQU ENDMASK+1 ; (WORD) pointer to char data + 155 001C SCOFF EQU CHPTR ;(BYTE) Offset used by scroll + 156 001D SCLDIR EQU CHPTR+1 ;(BYTE) Direction of scroll - >0 up, <0 down + 157 001E DSEGS EQU CHPTR+2 ; (WORD) Pointer to current disk's segments + 158 ;WIDE_FLAG EQU SCOFF+1 ; (BYTE) <> 0 if 16 bytes in char data + 159 ;DSEGS EQU WIDE_FLAG+1 ; (WORD) Pointer to current disk's segments + 160 0020 LASTWV EQU DSEGS+2 ; last of the WINDOW variables + 161 + 162 0050 ZEROPG EQU $50 ; FIRST FREE Z-PAGE LOCATION + 163 ; + 164 ; these are first, cuz ZBOOT inits them so we don't want to clear them + 165 ; at ZBEGIN warm start + 166 ; + 167 0050 GLOBAL EQU ZEROPG ; (Relative Addr.) GLOBAL VARIABLE POINTER + 168 0052 VOCAB EQU GLOBAL+2 ; (ADDRESS) Vocab table pointer + 169 0055 FWORDS EQU VOCAB+3 ; (ADDRESS) F-WORDS TABLE POINTER + 170 0058 MOUSEF EQU FWORDS+3 ; (BYTE) ==-1/1 if we have mouse/joystick + 171 0059 INFODOS EQU MOUSEF+1 ; (WORD) if <>0, then pointer to D2SEG + 172 005B FUNOFF EQU INFODOS+2 ; (ADDRESS) Function Offset (ZFOFF*8) + 173 005B FOFFH EQU FUNOFF ; (BYTE) Hi part + 174 005C FOFFM EQU FUNOFF+1 ; (BYTE) Middle part + 175 005D FOFFL EQU FUNOFF+2 ; (BYTE) Lo part + 176 005E STROFF EQU FUNOFF+3 ; (ADDRESS) String Offset (ZSOFF*8) + 177 005E SOFFH EQU STROFF ; (BYTE) Hi part + 178 005F SOFFM EQU STROFF+1 ; (BYTE) Middle part + 179 0060 SOFFL EQU STROFF+2 ; (BYTE) Lo part + 180 ; + Wed May 24 1989 15:00 Page 6 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 181 ; Beginning of warm start zeroing + 182 ; + 183 0061 OPCODE EQU STROFF+3 ; (BYTE) CURRENT OPCODE + 184 0062 NARGS EQU OPCODE+1 ; (BYTE) # ARGUMENTS + 185 0063 ARG1 EQU OPCODE+2 ; (WORD) ARGUMENT #1 + 186 0065 ARG2 EQU OPCODE+4 ; (WORD) ARGUMENT #2 + 187 0067 ARG3 EQU OPCODE+6 ; (WORD) ARGUMENT #3 + 188 0069 ARG4 EQU OPCODE+8 ; (WORD) ARGUMENT #4 + 189 006B ARG5 EQU OPCODE+10 ; (WORD) + 190 006D ARG6 EQU OPCODE+12 ; (WORD) + 191 006F ARG7 EQU OPCODE+14 ; (WORD) + 192 0071 ARG8 EQU OPCODE+16 ; (WORD) + 193 0073 ABYTE EQU OPCODE+18 ; (BYTE) X-OP ARGUMENT BYTE + 194 0074 BBYTE EQU OPCODE+19 ; (BYTE) XCALL ARG BYTE (EZIP) + 195 0075 ADEX EQU OPCODE+20 ; (BYTE) X-OP ARGUMENT INDEX + 196 0076 VALUE EQU OPCODE+21 ; (WORD) VALUE RETURN REGISTER + 197 0078 I EQU VALUE+2 ; (WORD) GEN-PURPOSE REGISTER #1 + 198 007A J EQU VALUE+4 ; (WORD) GEN-PURPOSE REGISTER #2 + 199 007C K EQU VALUE+6 ; (WORD) GEN-PURPOSE REGISTER #3 + 200 007E L EQU VALUE+8 ; (WORD) GEN-PURPOSE REGISTER #4 + 201 0080 ZPC EQU VALUE+10 ; (3 BYTES) ZIP PROGRAM COUNTER + 202 0080 ZPCL EQU ZPC ; (BYTE) <8 BITS OF [ZPC] + 203 0081 ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] + 204 0082 ZPCH EQU ZPC+2 ; (BYTE) >BIT OF [ZPC] + 205 0083 ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE + 206 0083 ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 207 0084 ZPNTH EQU ZPCPNT+1 ; (BYTE) + 208 0085 ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 209 0086 MPC EQU ZPCPNT+3 ; (3 BYTES) MEMORY PROGRAM COUNTER + 210 0086 MPCL EQU MPC ; (BYTE) <8 BITS OF [MPC] + 211 0087 MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] + 212 0088 MPCH EQU MPC+2 ; (BYTE) >BIT OF [MPC] + 213 0089 MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE + 214 0089 MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 215 008A MPNTH EQU MPCPNT+1 ; (BYTE) + 216 008B MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 217 008C FPC EQU MPCBNK+1 ; (3 Bytes) Fetch pointer + 218 008C FPCL EQU FPC ; (BYTE) Low part + 219 008D FPCH EQU FPCL+1 ; (BYTE) High Part + 220 008E FPCBNK EQU FPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 221 008F SPC EQU FPCBNK+1 ; (3 Bytes) Fetch pointer + 222 008F SPCL EQU SPC ; (BYTE) Low part + 223 0090 SPCH EQU SPCL+1 ; (BYTE) High Part + 224 0091 SPCBNK EQU SPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 225 + 226 ; Z-STRING MANIPULATION VARIABLES + 227 + 228 0092 LINLEN EQU SPCBNK+1 ; (BYTE) LENGTH OF CURRENT LINE + 229 0093 SOURCE EQU LINLEN+1 ; (BYTE) counter for read + 230 0094 WRDLEN EQU SOURCE+1 ; (BYTE) LENGTH OF CURRENT WORD + 231 0095 ESIZE EQU WRDLEN+1 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES + 232 0096 PSET EQU ESIZE+1 ; (BYTE) PERMANENT CHARSET + 233 0097 TSET EQU PSET+1 ; (BYTE) TEMPORARY CHARSET + 234 0098 ZCHAR EQU TSET+1 ; (BYTE) CURRENT Z-CHAR + 235 0099 OFFSET EQU ZCHAR+1 ; (BYTE) F-WORD TABLE OFFSET + 236 009A ZFLAG EQU OFFSET+1 ; (BYTE) Z-WORD ACCESS FLAG + 237 009B ZWORD EQU ZFLAG+1 ; (WORD) CURRENT Z-WORD + Wed May 24 1989 15:00 Page 7 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 238 009D CONCNT EQU ZWORD+2 ; (BYTE) Z-STRING SOURCE COUNTER + 239 009E CONIN EQU CONCNT+1 ; (BYTE) CONVERSION SOURCE INDEX + 240 009F CONOUT EQU CONIN+1 ; (BYTE) CONVERSION DEST INDEX + 241 00A0 DIRTBL EQU CONOUT+1 ; (WORD) CONTAINS TBLE TO STORE CHARS TO + 242 00A2 XSIZE EQU DIRTBL+2 ; (WORD) SCREEN WIDTH FOR TESTS + 243 00A4 RAND EQU XSIZE+2 ; (WORD) Random number offset + 244 00A6 CURWIN EQU RAND+2 ; (BYTE) WHICH WINDOW TO WRITE IN + 245 00A7 LENGTH EQU CURWIN+1 ; (WORD) CHAR POSITION ON THE SCREEN + 246 00A9 CHRCNT EQU LENGTH+2 ; (BYTE) CHAR POSITION IN [LBUFF] + 247 00AA SCRIPT EQU CHRCNT+1 ; (BYTE) SCRIPT ENABLE FLAG + 248 00AB LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER + 249 00AC IOCHAR EQU LINCNT+1 ; (BYTE) CHARACTER BUFFER + 250 00AD COLORP EQU IOCHAR+1 ; (WORD) Pointer to current background color + 251 00AF ZSP EQU COLORP+2 ; (WORD) Z Stack + 252 00B1 SCREENF EQU ZSP+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT + 253 00B2 TABLEF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT + 254 00B3 VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH + 255 00B6 DBUFF EQU VOCEND+3 ; (WORD) RAM PG TO ACCESS (LSB = 0) + 256 00B8 DSKBNK EQU DBUFF+2 ; (BYTE) MAIN/AUX bank + 257 00B9 ALLFLG EQU DSKBNK+1 ; (BYTE) IF =1 ALL FCN KEYS (>127) ARE TCHARS + 258 00BA UNDFLG EQU ALLFLG+1 ; (BYTE) Underlining flag + 259 00BB INVFLG EQU UNDFLG+1 ; (BYTE) Inverse flag + 260 00BC MEMPAGE EQU INVFLG+1 ; (BYTE) Save spot for XPAGING stuff + 261 00BD CPY_COUNT EQU MEMPAGE+1 ; (BYTE) Number of bytes for copy line + 262 00BE TBLHEIGHT EQU CPY_COUNT+1 ;(BYTE) Number of lines in printing table + 263 00BF TBLWIDTH EQU TBLHEIGHT+1 ;(BYTE) Number of bytes per line + 264 00C0 TBLCNT EQU TBLWIDTH+1 ;(BYTE) Counter for table printing + 265 00C1 FONTFLG EQU TBLCNT+1 ;(BYTE) Which font (!=0 is width) + 266 00C2 TBLPUR EQU FONTFLG+1 ;(BYTE) first pure table page + 267 00C3 FUNPRE EQU TBLPUR+1 ;(BYTE) first preloaded function page + 268 00C4 FUNPUR EQU FUNPRE+1 ;(BYTE) first pure function page + 269 00C5 FUNPGE EQU FUNPUR+1 ;(BYTE) -number to get function preload page + 270 00C6 DELAY_COUNTER EQU FUNPGE+1 ;(BYTE) counter for delay loop + 271 ; + 272 ; some char-to-screen variables + 273 ; + 274 00C7 CHAR_D1 EQU DELAY_COUNTER+1 ; (BYTE) character data, part 1 + 275 00C8 CHAR_D2 EQU CHAR_D1+1 ; (BYTE) char data, part 2 + 276 00C9 CW EQU CHAR_D2+1 ; (BYTE) width of the character + 277 00CA CLKCTR EQU CW+1 ; (BYTE) counter for mouse clicking + 278 00CB MSX EQU CLKCTR+1 ; (BYTE) mouse cursor X + 279 00CC MSY EQU MSX+1 ; (BYTE) mouse cursor Y + 280 00CD CURRENT EQU MSY+1 ; (BYTE) current paging bufer + 281 ;CURSOR_OFF EQU CURRENT+1 ; (BYTE) ==1 if "don't show the blinking cursor" + 282 00CE MSTBL EQU CURRENT+1 ; (ADDRESS) pointer to extension table + 283 00D1 LASTZP EQU MSTBL+3 ; just checking + 284 ; + 285 ; these routines are in non-swapped memory + 286 ; + 287 00D1 ZERO_FB EQU LASTZP ; put fetch byte routine in at end of ZP + 288 00DC ZERO_ZF EQU ZERO_FB+11 ; and ZPCPNT fetch after that + 289 00E5 ZERO_MF EQU ZERO_ZF+9 ; and MPCPNT fetch after that + 290 00EE SAVE_DATA EQU ZERO_MF+9 ; copy data from DBUFF to IOBUFF routine + 291 ; + 292 ; and just to check the end + 293 ; + 294 00FF ZEE_END EQU SAVE_DATA+17 ; should be == 100 + Wed May 24 1989 15:00 Page 8 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZERO PAGE VARIABLES ---" + + 295 + 296 0000 END + 297 + 298 0000 INCLUDE PRODOS.EQU + 299 0000 STTL "--- ProDOS EQUATES ---" + 300 PAGE + Wed May 24 1989 15:00 Page 9 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ProDOS EQUATES ---" + + 301 + 302 ; + 303 ; some parameter structures + 304 ; + 305 0000 OPEN_PARM EQU 0 + 306 0000 OP_PCOUNT EQU OPEN_PARM ; must be 3 for open + 307 0001 OP_PATHNAME EQU OP_PCOUNT+1 ; address of pathname + 308 0003 OP_FILEBUFF EQU OP_PATHNAME+2 ; address of file data buffer + 309 0005 OP_REFNUM EQU OP_FILEBUFF+2 ; file reference number + 310 0006 OPEN_PSIZE EQU OP_REFNUM+1 ; size of parameter buffer + 311 + 312 0000 READ_PARM EQU 0 ; to read things + 313 0000 RD_PCOUNT EQU READ_PARM ; param count (=4) + 314 0001 RD_REFNUM EQU RD_PCOUNT+1 ; ref num of file + 315 0002 RD_BUFFER EQU RD_REFNUM+1 ; where to + 316 0004 RD_BUFFLEN EQU RD_BUFFER+2 ; length of buffer + 317 0006 RD_LENGTH EQU RD_BUFFLEN+2 ; actual length of read + 318 0008 READ_PSIZE EQU RD_LENGTH+2 ; length of parm block + 319 + 320 0000 CLOSE_PARM EQU 0 ; for closing file + 321 0000 CL_PCOUNT EQU CLOSE_PARM ; paramter count (=1) + 322 0001 CL_REFNUM EQU CL_PCOUNT+1 ; refnum of file to be closed + 323 0002 CLOSE_PSIZE EQU CL_REFNUM+1 ; this is the size, thank you + 324 + 325 0000 WRITE_PARM EQU 0 ; to write things + 326 0000 WR_PCOUNT EQU WRITE_PARM ; parm count (= 4) + 327 0001 WR_REFNUM EQU WR_PCOUNT+1 ; file refnum + 328 0002 WR_BUFFER EQU WR_REFNUM+1 ; data buffer address + 329 0004 WR_BUFFLEN EQU WR_BUFFER+2 ; data buffer length + 330 0006 WR_LENGTH EQU WR_BUFFLEN+2 ; actual length written + 331 0008 WRITE_PSIZE EQU WR_LENGTH+2 ; length of parm block + 332 + 333 0000 SETMARK_PARM EQU 0 + 334 0000 SM_PCOUNT EQU SETMARK_PARM ; parm count (=2) + 335 0001 SM_REFNUM EQU SM_PCOUNT+1 ; file refnum + 336 0002 SM_FPOS EQU SM_REFNUM+1 ; 3 byte file pos + 337 0005 SETMARK_PSIZE EQU SM_FPOS+3 ; length of parm block + 338 + 339 0000 SETPREFIX_PARM EQU 0 + 340 0000 SP_PCOUNT EQU SETPREFIX_PARM ; parm count (=1) + 341 0001 SP_PATHNAME EQU SP_PCOUNT+1 ; pointer to path name + 342 0003 SETPREFIX_PSIZE EQU SP_PATHNAME+2 ; length of block + 343 + 344 0000 SETEOF_PARM EQU 0 + 345 0000 SE_PCOUNT EQU SETEOF_PARM ; parm count (=2) + 346 0001 SE_REFNUM EQU SE_PCOUNT+1 ; reference number + 347 0002 SE_NEWEOF EQU SE_REFNUM+1 ; new EOF position + 348 0005 SETEOF_PSIZE EQU SE_NEWEOF+3 ; length of parm block + 349 + 350 0000 END + 351 + 352 0000 INCLUDE APPLE.EQU + 353 0000 STTL "--- APPLE ][ HARDWARE STUFF ---" + 354 PAGE + Wed May 24 1989 15:00 Page 10 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 355 ; ------------------- + 356 ; APPLE II MEMORY MAP + 357 ; ------------------- + 358 0001 AUX EQU 1 ; offset to Auxillary mem switches + 359 0000 MAIN EQU 0 ; for main memory switches + 360 + 361 ; + 362 ; some hardware spots + 363 ; + 364 2000 SCREEN EQU $2000 ; START OF Double HiRes SCREEN RAM + 365 + 366 BF00 PRGLBL EQU $BF00 ; ProDOS Globals page in main mem + 367 BF58 PR_BITMAP EQU $BF58 ; ProDOS system bitmap + 368 BFFF KVERSION EQU $BFFF ; ProDOS version (== $FF if InfoDOS) + 369 00FF INFODOS_ID EQU $FF + 370 + 371 C000 IOADDR EQU $C000 ; start of I/O registers + 372 D000 PROADR EQU $D000 ; start of ProDOS + 373 + 374 0200 LBUFF EQU $0200 ; LINE INPUT BUFFER + 375 0273 PIC1BUF EQU $0300-141 ; we can use line buffer for one picture buffer + 376 0280 SCRBUFF EQU LBUFF+$80 ; screen line buffer + 377 2000 BORG EQU $2000 ; ORIGIN OF .SYSTEM CODE + 378 ; + 379 ; some page 3 storage relocated stuff + 380 ; + 381 0300 PAGE3STUFF EQU $300 + 382 0300 MOUSER EQU PAGE3STUFF ; this is where mouse subroutine goes + 383 0312 COLORS EQU MOUSER+$12 + 384 0352 XPOSTBL EQU COLORS+$40 + 385 + 386 0400 SV_PCL EQU $400 ; for scrolling data + 387 0600 SV_PCH EQU $600 + 388 + 389 0800 IOBUFF EQU $0800 ; 1Kb DATA BUFFER BUFFER + 390 + 391 0C00 PAGING_MEM EQU IOBUFF+$400 ; Paging table stuff + 392 0C00 NEXTPNT EQU PAGING_MEM + 393 0C40 PREVPNT EQU NEXTPNT+$40 + 394 0C80 VPAGEH EQU PREVPNT+$40 + 395 0CC0 VPAGEL EQU VPAGEH+$40 + 396 0200 PAGELEN EQU $200 ; length of paged read + 397 + 398 0D00 ZSTKBL EQU PAGING_MEM+$100 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) + 399 0E00 ZSTKTL EQU ZSTKBL+$100 ; TOP, LO + 400 0F00 ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI + 401 1000 ZSTKTH EQU ZSTKBL+$300 ; TOP, HI + 402 ; + 403 ; now define some file i/o buffers and such + 404 ; + 405 1100 GAME1FIO EQU ZSTKBL+$400 ; Game file I/O buffer + 406 1500 GAME2FIO EQU GAME1FIO+$400 ; Second game file i/o buffer + 407 1900 SEGTBL EQU GAME2FIO+$400 ; segment table for multi disks + 408 1C74 PIC2BUF EQU SEGTBL+($400-140) ; picture buffer is 140 bytes long + 409 1D00 TCHARTBL EQU SEGTBL+$400 ; 208 bytes for (possible) terminating + 410 1D50 COPY_LINE EQU TCHARTBL+$50 ; copy line in screen memory + 411 1D7C CPY_MOD1_SRC equ COPY_LINE+$2C ; special self-modifying places + Wed May 24 1989 15:00 Page 11 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 412 1D7F CPY_MOD1_DST equ CPY_MOD1_SRC+3 + 413 1DA0 CPY_MOD2_SRC equ COPY_LINE+$50 + 414 1DA3 CPY_MOD2_DST equ CPY_MOD2_SRC+3 + 415 + 416 1DD0 DSKSEG EQU TCHARTBL+$D0 ; spot to stash pointers for disk segments + 417 1DD0 D1SEG EQU DSKSEG ; where in SEGTBL for Disk 1 + 418 1DD2 D2SEG EQU D1SEG+2 + 419 1DD4 D3SEG EQU D2SEG+2 + 420 1DD6 D4SEG EQU D3SEG+2 + 421 1DD8 D5SEG EQU D4SEG+2 + 422 1DDA D6SEG EQU D5SEG+2 + 423 1DDC D7SEG EQU D6SEG+2 + 424 1DDE D8SEG EQU D7SEG+2 + 425 1DE0 LOCAL_SV EQU TCHARTBL+$E0 ; to save locals before restore + 426 1E00 LOCALS EQU TCHARTBL+$100 ; LOCAL VARIABLE STORAGE (30 BYTES) + 427 1E20 BUFSAV EQU LOCALS+$20 ; TEMP SPACE FOR SAVE/RESTORE (80 BYTES) + 428 1F00 SCR_LINE EQU LOCALS+$100 ; place to build displayed line + 429 1F8C CHARSET EQU SCR_LINE+140 ; spot for charset to go + 430 ; + 431 ; now for some interpreter data + 432 ; + 433 4000 INTR_BEGIN EQU $4000 ; START OF Interpreter CODE in main + 434 5600 INTR_SIZE EQU (43*512) ; size of interpreter + 435 + 436 9600 ZBEGIN EQU (INTR_BEGIN+INTR_SIZE) ; start of Z code + 437 7F00 MMSIZE EQU PRGLBL-INTR_BEGIN ; free memory in main bank + 438 0029 Z1SIZE EQU >(PRGLBL-ZBEGIN) ; size of preload, part 1 + 439 ; + 440 ; this is in Bank 2, Main mem + 441 ; + 442 ; + 443 ; Picture directory goes in Bank 2, Aux mem + 444 ; + 445 D000 PIC_DIR EQU $D000 ; picture local directory + 446 DC00 GBL_DIR EQU $DC00 ; global directory + 447 ; + 448 ; some special markers if we are using InfoDOS + 449 ; + 450 0000 SP_BANK EQU MAIN + 451 D000 SP_START EQU $D000 ; start of special area + 452 0017 SP_SIZE EQU ((($FE->SP_START)*256)/512) ; how many pages + 453 ;SP_SIZE EQU (((>SCREEN->SP_START)*256)/512) ; how many pages + 454 + 455 0001 PB_BANK EQU AUX ; paging buffers in which bank + 456 0800 PBEGIN EQU $0800 ; start of paging buffers + 457 0018 NUMBUFS EQU >(SCREEN-PBEGIN) ; how many 256k paging buffers + 458 ;NUMBUFS EQU >($100-PBEGIN) ; how many 256k paging buffers + 459 + 460 0029 P2PAGE EQU >(PRGLBL-ZBEGIN) ; first page of zcode in aux bank + 461 4000 Z2BEGIN EQU $4000 ; start of part 2 in aux mem + 462 ; just after the dhires screen + 463 0040 Z2PAGE EQU >Z2BEGIN ; get me just the page address + 464 007F Z2SIZE EQU >(PRGLBL-Z2BEGIN) ; size of preload, part 2 + 465 00A8 P3PAGE EQU Z1SIZE+Z2SIZE ; first page in aux mem part 3 + 466 D000 Z3BEGIN EQU $D000 ; start of 3 part in aux mem + 467 00D0 Z3PAGE EQU >Z3BEGIN ; get me page number too + 468 002E Z3SIZE EQU <($FE-Z3PAGE) ; size of part 3, in pages + Wed May 24 1989 15:00 Page 12 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 469 + 470 ; + 471 ; other numba's + 472 ; + 473 00D6 PGBEGIN EQU (P3PAGE+Z3SIZE) ; first paged page + 474 00D6 PRESIZE EQU (Z1SIZE+Z2SIZE+Z3SIZE) ; size of preload, # pages + 475 2000 SCRSZE EQU INTR_BEGIN-SCREEN ; size of Double HiRes screen (8k, each bank) + 476 EE00 RAMDSK EQU (119*512) ; size of RAM disk in aux mem + 477 B500 RAMSAVE EQU $B500 ; save this much to cover HiRes screen in + 478 ; aux and the rest of the preload, up to + 479 ; PRGLBL ($bf00) + 480 3900 FREERAM EQU RAMDSK-RAMSAVE ; size of Free RAM after 'saving' + 481 ; special AUX memory + 482 2200 DSKSZE EQU (512*273) ; size of ProDOS data disk file + 483 + 484 ; --------- + 485 ; CONSTANTS + 486 ; --------- + 487 + 488 0002 IIeID EQU 2 ; Apple ][e Yzip + 489 0009 IIcID EQU 9 ; ][c Yzip + 490 000A IIgsID EQU 10 ; ][gs Yzip + 491 + 492 00FF P3BANK EQU $FF ; show upper aux mem + 493 0000 LO EQU 0 + 494 0001 HI EQU 1 + 495 0002 ABANK EQU 2 ; for address variables + 496 + 497 0000 OFF EQU 0 ; for toggling soft-switches + 498 0001 ON EQU 1 + 499 + 500 0003 RETRY_COUNT EQU 3 ; how many retries before message + 501 + 502 0009 TAB EQU $09 ; Tab char + 503 000B EOS EQU $0B ; End of Sentence + 504 000D EOL EQU $0D ; EOL CHAR + 505 000A LF EQU $0A ; LINE FEED + 506 0020 SPACE EQU $20 ; SPACE CHAR + 507 0008 BACKSPACE EQU $08 ; BACKSPACE CHAR + 508 001B ESCAPE EQU $1B ; ESCAPE Key + 509 003F VOLCHAR EQU '?' ; Key to hit for ONLINE command + 510 ; + 511 ; Screen Defs + 512 ; + 513 008C MAXWIDTH EQU 140 ; 560 / 4 = max "pixels" + 514 0230 REAL_MAXW EQU MAXWIDTH*4 + 515 00C0 MAXHEIGHT EQU 192 ; 192 screen lines + 516 0002 FONT_W EQU 2 ; font width (for game, anyway) + 517 0009 FONT_H EQU 9 ; font height + 518 0003 MFONT_W EQU 3 ; mono spaced font width, to game + 519 000C MONOFONT_W EQU MFONT_W*4 ; how wide the mono font really is + 520 + 521 0008 SPACE_WIDTH EQU 8 ; default space width + 522 0003 BLINK_RATE EQU 3 ; tenths of seconds between blinks + 523 + 524 001C OUTER_DELAY EQU $1C ; outside delay loop counter + 525 0003 INNER_DELAY EQU 3 ; inner delay loop + Wed May 24 1989 15:00 Page 13 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 526 + 527 0072 GS_OUTER_DELAY EQU $72 ; ][gs outside counter + 528 0002 GS_INNER_DELAY EQU 2 ; ][gs inside counter + 529 + 530 ; ---------------------- + 531 ; BOOT ZERO PAGE EQUATES + 532 ; ---------------------- + 533 + 534 0026 BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS + 535 002B BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT + 536 + 537 0280 START_NAME EQU $280 ; name upon boot is stored here + 538 ; ---------------- + 539 ; HARDWARE EQUATES + 540 ; ---------------- + 541 + 542 C000 KBD EQU $C000 ; KEY STROBE + 543 C000 STORE80 EQU $C000 ; video aux mem switch + 544 C002 RDBNK EQU $C002 ; READ MAIN MEMORY (+MAIN, +AUX) + 545 C004 WRTBNK EQU $C004 ; WRITE MAIN 48K OF MEMORY (+MAIN, +AUX) + 546 C008 ALTZP EQU $C008 ; R/W MAIN (C009 = AUX) >MEM + 547 C00C COL80SW EQU $C00C ; 80 Column switch + 548 C010 ANYKEY EQU $C010 ; ANY KEY DOWN FLAG + 549 C019 VERTBLNK EQU $C019 ; Vertical Blanking Flag + 550 C029 IIGSVID EQU $C029 ; GS MEGA ][ video register + 551 C030 SPKR EQU $C030 ; SPEAKER FLAG (MAKE A NOISE) + 552 C035 IIGSSHD EQU $C035 ; ][GS shadowing reg + 553 C050 TEXTSW EQU $C050 ; Graphics Switch + 554 C052 MIXEDSW EQU $C052 ; Mixed Text/Graphics + 555 C054 PAGE2SW EQU $C054 ; Page select + 556 C056 HIRESSW EQU $C056 ; Select HiRes + 557 C05E DHIRESW EQU $C05E ; Double HiRes switch (backwards: +0 on +1 off) + 558 C07E IOUDIS EQU $C07E ; Double HiRes Switch enabler (same backass way) + 559 C083 BNK2SET EQU $C083 ;READ/READ READ RAM WRITE RAM BANK 2 + 560 C08B BNK1SET EQU $C08B ;READ/READ READ RAM WRITE RAM BANK 1 + 561 C082 RDROM EQU $C082 ; READ READ ROM NO WRITE + 562 C088 RDBNK1 EQU $C088 ; READ ram, bank 1 + 563 C080 RDBNK2 EQU $C080 ; Read ram, bank 2 + 564 + 565 ; ----------------- + 566 ; MONITOR VARIABLES + 567 ; ----------------- + 568 + 569 0036 CSW EQU $36 ; CHARACTER OUTPUT VECTOR (for scripting) + 570 C061 APKEY1 EQU $C061 ; open apple key flag + 571 C062 APKEY2 EQU $C062 ; closed apple key flag + 572 + 573 0002 CURSW EQU 2 ; width of cursor + 574 0004 CURSH EQU 4 ; height of cursor + 575 ; ----------- + 576 ; MOUSE STUFF + 577 ; ----------- + 578 C412 MTABLE EQU $C412 ; Mouse ROM table + 579 0310 MSVECTOR EQU MOUSER+16 ; where vector is stored + 580 0312 MSMOVEF EQU MSVECTOR+2 ; Mouse moved flag + 581 0313 MSBTNF EQU MSMOVEF+1 ; Mouse button flag + 582 ; + Wed May 24 1989 15:00 Page 14 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 583 ; MOUSE screen holes + 584 ; + 585 0478 CLMPMINL EQU $478 ; lo part of clamping min + 586 0578 CLMPMINH EQU $578 ; hi part of " " + 587 04F8 CLMPMAXL EQU $4F8 ; lo part of clamping max + 588 05F8 CLMPMAXH EQU $5F8 ; hi part of " " + 589 0478 MOUSEXL EQU $478 ; lo part of mouse X + 590 0578 MOUSEXH EQU $578 ; hi part of mouse X + 591 04F8 MOUSEYL EQU $4F8 ; lo part of mouse Y + 592 05F8 MOUSEYH EQU $5F8 ; hi part of mouse Y + 593 0778 MOUSEST EQU $778 ; status byte + 594 ; + 595 ; some mouse constants + 596 ; + 597 0081 SGL_CLK EQU $81 ; single click char + 598 0082 DBL_CLK EQU $82 ; double click char + 599 0006 CLK_CNT EQU 6 ; counts between single and double click + 600 ; Subroutine offsets + 601 0000 SETM EQU 0 + 602 0001 SERVEM EQU 1 + 603 0002 READM EQU 2 + 604 0003 CLEARM EQU 3 + 605 0004 POSM EQU 4 + 606 0005 CLAMPM EQU 5 + 607 0006 HOMEM EQU 6 + 608 0007 INITM EQU 7 + 609 + 610 ; -------------- + 611 ; PRODOS GLOBALS + 612 ; -------------- + 613 BF90 PRODATE EQU $BF90 ; date and + 614 BF92 PROTIME EQU $BF92 ; time + 615 BF98 MACHID EQU $BF98 ; machine id + 616 + 617 ; ---------------- + 618 ; MONITOR ROUTINES + 619 ; ---------------- + 620 FB1E MPREAD EQU $FB1E ; Read for joystick control + 621 FC22 MBASCAL EQU $FC22 ; CALC LINE BASE ADDRESS + 622 FF3A MBELL EQU $FF3A ; MAKE A NOISE + 623 FFFC RESET_VECTOR EQU $FFFC ; force warm reboot + 624 FC9C MCLEOL EQU $FC9C ; CLEAR TO END OF LINE + 625 FC42 MCLEOS EQU $FC42 ; CLEAR TO END OF SCREEN + 626 FC58 MHOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR + 627 FDED MCOUT EQU $FDED ; CHAR OUTPUT + 628 FDF0 MCOUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN + 629 FD0C MRDKEY EQU $FD0C ; READ KEY + 630 FD6F MGETLN1 EQU $FD6F ; GET LINE + 631 FCA8 MWAIT EQU $FCA8 ; WASTE SO MUCH TIME + 632 ; + 633 ; Some /RAM spots + 634 ; + 635 BF26 RAMVEC EQU $BF26 ; /RAM drive vector + 636 077E OLDVEC EQU $77E ; spot to save the drive vector + 637 BF16 UNSVEC EQU $BF16 ; "Uninstalled Device" vector + 638 BF31 DEVCNT EQU $BF31 ; Device count + 639 BF32 DEVNUM EQU $BF32 ; Device list + Wed May 24 1989 15:00 Page 15 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ][ HARDWARE STUFF ---" + + 640 + 641 ; + 642 ; machine info spots + 643 ; + 644 FBB3 MACHID1 EQU $FBB3 ; first part + 645 FBC0 MACHID2 EQU $FBC0 ; second part + 646 FE1F MACHCHK EQU $FE1F ; differentiate between ][e and gs + 647 ; do sec, then jsr, and if still set, = ][e + 648 0000 END + 649 + 650 0000 INCLUDE MACROS.ASM + 651 0000 STTL "--- MACROS ---" + 652 PAGE + Wed May 24 1989 15:00 Page 16 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- MACROS ---" + + 653 + 654 ; + 655 ; MACROS for Apple ][ Yzip + 656 ; + 657 DLINE: .MACRO STRING,SLEN + 658 ldx #STRING ; get other part of string + 660 IFMA 2 ; check to see if length passed in + 661 ldy SLEN ; then just fetch it + 662 ELSE + 663 ldy #STRING|L ; get length of string + 664 ENDIF + 665 jsr DLINE ; print the string + 666 .MACEND + 667 ; + 668 ; ProDOS macros + 669 ; + 670 PRODOS: .MACRO CODE, PADDR + 671 jsr $BF00 ; ProDOS handler + 672 DB CODE ; ProDOS function code + 673 DW PADDR ; Function Parameter Block address + 674 .MACEND + 675 + 676 QUIT: .MACRO PBLOCK + 677 PRODOS $65, PBLOCK + 678 .MACEND + 679 + 680 READ_BLOCK: .MACRO PBLOCK + 681 PRODOS $80, PBLOCK + 682 .MACEND + 683 + 684 WRITE_BLOCK: .MACRO PBLOCK + 685 PRODOS $81, PBLOCK + 686 .MACEND + 687 + 688 GET_TIME: .MACRO PBLOCK + 689 PRODOS $82, PBLOCK + 690 .MACEND + 691 + 692 CREATE: .MACRO PBLOCK + 693 PRODOS $C0, PBLOCK + 694 .MACEND + 695 + 696 DESTROY: .MACRO PBLOCK + 697 PRODOS $C1, PBLOCK + 698 .MACEND + 699 + 700 RENAME: .MACRO PBLOCK + 701 PRODOS $C2, PBLOCK + 702 .MACEND + 703 + 704 SET_FILE_INFO: .MACRO PBLOCK + 705 PRODOS $C3, PBLOCK + 706 .MACEND + 707 + 708 GET_FILE_INFO: .MACRO PBLOCK + 709 PRODOS $C4, PBLOCK + Wed May 24 1989 15:00 Page 17 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- MACROS ---" + + 710 .MACEND + 711 + 712 ONLINE: .MACRO PBLOCK + 713 PRODOS $C5, PBLOCK + 714 .MACEND + 715 + 716 SET_PREFIX: .MACRO PBLOCK + 717 PRODOS $C6, PBLOCK + 718 .MACEND + 719 + 720 GET_PREFIX: .MACRO PBLOCK + 721 PRODOS $C7, PBLOCK + 722 .MACEND + 723 + 724 OPEN: .MACRO PBLOCK + 725 PRODOS $C8, PBLOCK + 726 .MACEND + 727 + 728 NEWLINE: .MACRO PBLOCK + 729 PRODOS $C9, PBLOCK + 730 .MACEND + 731 + 732 READ: .MACRO PBLOCK + 733 PRODOS $CA, PBLOCK + 734 .MACEND + 735 + 736 WRITE: .MACRO PBLOCK + 737 PRODOS $CB, PBLOCK + 738 .MACEND + 739 + 740 CLOSE: .MACRO PBLOCK + 741 PRODOS $CC, PBLOCK + 742 .MACEND + 743 + 744 FLUSH: .MACRO PBLOCK + 745 PRODOS $CD, PBLOCK + 746 .MACEND + 747 + 748 SET_MARK: .MACRO PBLOCK + 749 PRODOS $CE, PBLOCK + 750 .MACEND + 751 + 752 GET_MARK: .MACRO PBLOCK + 753 PRODOS $CF, PBLOCK + 754 .MACEND + 755 + 756 SET_EOF: .MACRO PBLOCK + 757 PRODOS $D0, PBLOCK + 758 .MACEND + 759 + 760 SET_BUF: .MACRO PBLOCK + 761 PRODOS $D1, PBLOCK + 762 .MACEND + 763 + 764 GET_BUF: .MACRO PBLOCK + 765 PRODOS $D2, PBLOCK + 766 .MACEND + Wed May 24 1989 15:00 Page 18 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- MACROS ---" + + 767 + 768 0000 END + 769 + 770 + 771 0000 STTL "--- APPLE ProDOS BOOT CODE ---" + 772 PAGE + Wed May 24 1989 15:00 Page 19 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 773 + 774 0024 CHZ EQU $24 ; CURSOR HORIZONTAL + 775 057B EHZ EQU $57B ; CURSOR HORIZONTAL + 776 0025 CVT EQU $25 ; CURSOR VERTICAL + 777 + 778 ; + 779 ; my own little error checking macro + 780 ; + 781 0000 ERRVAL .VAR 0 + 782 ; + 783 ; this macros checks for carry being set (ProDOS error) and if it is + 784 ; loads an error code in x and jumps to the error handler + 785 ERRCHK .MACRO + 786 ERRVAL .VAR ERRVAL+1 + 787 bcc BOOT| + 788 ldy #ERRVAL + 789 jmp BOOT_ERROR + 790 BOOT|: + 791 .MACEND + 792 + 793 2000 ORG BORG + 794 2000 4C 0C 20 jmp BOOT_BEGIN ; just jump to beginning + 795 2003 PROGNAME: + 796 2003 BLKB 9,0 ; 8 bytes for name + 1 for ending zero + 797 200C BOOT_BEGIN: + 798 200C AD 82 C0 lda RDROM ; swap in rom + 799 200F 8D 51 C0 sta TEXTSW+ON ; turn on text + 800 2012 8D 0C C0 sta COL80SW+OFF ; turn on 80 column + 801 + 802 ; + 803 ; make sure we are on a ][c, or ][e+ + 804 ; + 805 2015 20 AE 26 jsr MACHINE ; check it out, returns if good + 806 2018 A5 65 lda ARG2+LO ; check machine + 807 201A C9 0A cmp #IIgsID ; 2gs? + 808 201C D0 10 bne ZBOOTGS ; nope + 809 201E AD 29 C0 lda IIGSVID ; get current video setting + 810 2021 29 1F and #$1F ; turn off upper 3 bits + 811 2023 8D 29 C0 sta IIGSVID ; make sure double hires works + 812 2026 AD 35 C0 lda IIGSSHD ; get shadowing reg + 813 2029 29 A0 and #$A0 ; turn on shadowing everywhere + 814 202B 8D 35 C0 sta IIGSSHD ; okay + 815 202E ZBOOTGS: + 816 202E 20 5C 28 jsr FIXRAM ; check and clear RAM disk + 817 2031 20 6C 29 jsr DO_PREFIX ; go set my current prefix + 818 + 819 2034 20 58 FC jsr MHOME ; clear and home + 820 2037 A9 09 lda #9 ; CENTER DISPLAY + 821 2039 85 25 sta CVT + 822 203B A9 08 lda #8 + 823 203D 85 24 sta CHZ + 824 203F 8D 7B 05 sta EHZ + 825 2042 20 22 FC jsr MBASCAL ; move cursor there! + 826 2045 DLINE STRYM + 827 2045 A2 5C ldx #STRYM ; get other part of string + 829 [01] IFMA 2 ; check to see if length passed in + Wed May 24 1989 15:00 Page 20 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 830 ldy M ; then just fetch it + 831 [01] ELSE + 832 2049 A0 18 ldy #STRYML ; get length of string + 833 [00] ENDIF + 834 204B 20 D5 26 jsr DLINE ; print the string + 835 204E .MACEND + 836 ; + 837 ; move down to lower left and print out version number + 838 ; + 839 204E A9 15 lda #21 + 840 2050 85 25 sta CVT + 841 2052 A9 01 lda #1 + 842 2054 85 24 sta CHZ ; move to 1,20 + 843 2056 8D 7B 05 sta EHZ + 844 2059 20 22 FC jsr MBASCAL ; move cursor there! + 845 205C DLINE VERMSG ; show me the version + 846 205C A2 42 ldx #VERMSG ; get other part of string + 848 [01] IFMA 2 ; check to see if length passed in + 849 ldy ; then just fetch it + 850 [01] ELSE + 851 2060 A0 0A ldy #VERMSGL ; get length of string + 852 [00] ENDIF + 853 2062 20 D5 26 jsr DLINE ; print the string + 854 2065 .MACEND + 855 2065 A9 00 lda #VERSID/10 ; get version + 856 2067 09 B0 ora #$B0 ; make normal char for ][ + 857 2069 20 ED FD jsr MCOUT + 858 206C A9 09 lda #VERSID.MOD.10 + 859 206E 09 B0 ora #$B0 ; make normal char for ][ + 860 2070 20 ED FD jsr MCOUT + 861 + 862 2073 A9 FF lda #$FF ; init invflg to normal + 863 2075 85 BB sta INVFLG ; okay + 864 + 865 2077 A9 00 lda #0 ; zero out bit map + 866 2079 A2 17 ldx #$17 ; 17 bytes in ProDOS system bitmap + 867 207B CLRPRD: + 868 207B 9D 58 BF sta PR_BITMAP,X ; and zero out the memory + 869 207E CA dex + 870 207F 10 FA bpl CLRPRD ; and zero entire bitmap + 871 + 872 2081 A9 C0 lda #$C0 ; start out the bitmap with c0 at start + 873 2083 8D 58 BF sta PR_BITMAP + 874 2086 A9 01 lda #$01 ; and a 1 at the end + 875 2088 8D 6F BF sta PR_BITMAP+$17 ; thankx + 876 ; + 877 ; now we need to load in the interpreter + 878 ; + 879 208B OPEN INTR_OPEN ; open up interpreter file + 880 208B PRODOS $C8, INTR_OPEN + 881 208B 20 00 BF jsr $BF00 ; ProDOS handler + 882 208E C8 DB $C8 ; ProDOS function code + 883 208F 1B2A DW INTR_OPEN ; Function Parameter Block address + 884 2091 .MACEND + 885 2091 .MACEND + 886 2091 ERRCHK + Wed May 24 1989 15:00 Page 21 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 887 0001 ERRVAL .VAR ERRVAL+1 + 888 2091 90 05 bcc BOOT1 + 889 2093 A0 01 ldy #ERRVAL + 890 2095 4C AB 26 jmp BOOT_ERROR + 891 2098 BOOT1: + 892 2098 .MACEND + 893 + 894 2098 AD 20 2A lda INTR_OPEN+OP_REFNUM ; get refnum for intr file + 895 209B 8D 30 2A sta READ_BLOCK+RD_REFNUM ; and save for read + 896 209E 8D 22 2A sta CLOSE_BLOCK+CL_REFNUM ; close up interpreter file + 897 + 898 20A1 A9 03 lda #RETRY_COUNT ; set retry + 899 20A3 85 16 sta RETRIES ; just use this for now + 900 20A5 RDINTR: + 901 20A5 READ READ_BLOCK ; read in interpreter + 902 20A5 PRODOS $CA, READ_BLOCK + 903 20A5 20 00 BF jsr $BF00 ; ProDOS handler + 904 20A8 CA DB $CA ; ProDOS function code + 905 20A9 2F2A DW READ_BLOCK ; Function Parameter Block address + 906 20AB .MACEND + 907 20AB .MACEND + 908 20AB 90 0B bcc RDINTR1 ; it worked fine + 909 20AD C6 16 dec RETRIES ; try again + 910 20AF 10 F4 bpl RDINTR ; fine + 911 20B1 ERRCHK ; then just die + 912 0002 ERRVAL .VAR ERRVAL+1 + 913 20B1 90 05 bcc BOOT2 + 914 20B3 A0 02 ldy #ERRVAL + 915 20B5 4C AB 26 jmp BOOT_ERROR + 916 20B8 BOOT2: + 917 20B8 .MACEND + 918 20B8 RDINTR1: + 919 20B8 CLOSE CLOSE_BLOCK ; done with interpreter + 920 20B8 PRODOS $CC, CLOSE_BLOCK + 921 20B8 20 00 BF jsr $BF00 ; ProDOS handler + 922 20BB CC DB $CC ; ProDOS function code + 923 20BC 212A DW CLOSE_BLOCK ; Function Parameter Block address + 924 20BE .MACEND + 925 20BE .MACEND + 926 ; + 927 ; now read in first part of preload + 928 ; + 929 20BE A2 00 ldx #0 ; start at first letter + 930 20C0 MVPRE: + 931 20C0 BD 03 20 lda PROGNAME,X ; get letter + 932 20C3 F0 06 beq MVPREX ; all done + 933 20C5 9D 40 2A sta PRE_NAME,X ; save letter + 934 20C8 E8 inx ; next letter + 935 20C9 D0 F5 bne MVPRE ; do gen + 936 20CB MVPREX: + 937 ; + 938 ; now add on ".d1" suffix for the preload + 939 ; + 940 20CB A9 2E lda #'.' ; get '.' + 941 20CD 9D 40 2A sta PRE_NAME,X ; save it + 942 20D0 E8 inx ; next char + 943 20D1 A9 44 lda #'D' ; 'D' char + Wed May 24 1989 15:00 Page 22 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 944 20D3 9D 40 2A sta PRE_NAME,X ; save it + 945 20D6 E8 inx ; next char + 946 20D7 A9 31 lda #'1' ; preload is .1 + 947 20D9 9D 40 2A sta PRE_NAME,X ; saved + 948 20DC E8 inx ; count the .1 + 949 20DD 8E 3F 2A stx PRELOAD_NAME ; save length of name + 950 + 951 20E0 OPEN PRELOAD_OPEN ; so now open preload file + 952 20E0 PRODOS $C8, PRELOAD_OPEN + 953 20E0 20 00 BF jsr $BF00 ; ProDOS handler + 954 20E3 C8 DB $C8 ; ProDOS function code + 955 20E4 292A DW PRELOAD_OPEN ; Function Parameter Block address + 956 20E6 .MACEND + 957 20E6 .MACEND + 958 20E6 ERRCHK + 959 0003 ERRVAL .VAR ERRVAL+1 + 960 20E6 90 05 bcc BOOT3 + 961 20E8 A0 03 ldy #ERRVAL + 962 20EA 4C AB 26 jmp BOOT_ERROR + 963 20ED BOOT3: + 964 20ED .MACEND + 965 + 966 20ED AD 2E 2A lda PRELOAD_OPEN+OP_REFNUM ; get refnum + 967 20F0 8D 30 2A sta READ_BLOCK+RD_REFNUM ; save refnum for read + 968 20F3 8D 25 2A sta PSEEK+SM_REFNUM ; and for moving around + 969 ; + 970 ; first, get the segment table + 971 ; + 972 20F6 A9 08 lda #>IOBUFF ; just read in size + 973 20F8 8D 32 2A sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + 974 20FB A9 04 lda #4 ; read in first 1 Kb + 975 20FD 8D 34 2A sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + 976 2100 A9 00 lda #0 ; get size in words + 977 2102 8D 33 2A sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + 978 2105 + 979 2105 READ READ_BLOCK ; and read first block + 980 2105 PRODOS $CA, READ_BLOCK + 981 2105 20 00 BF jsr $BF00 ; ProDOS handler + 982 2108 CA DB $CA ; ProDOS function code + 983 2109 2F2A DW READ_BLOCK ; Function Parameter Block address + 984 210B .MACEND + 985 210B .MACEND + 986 210B ERRCHK + 987 0004 ERRVAL .VAR ERRVAL+1 + 988 210B 90 05 bcc BOOT4 + 989 210D A0 04 ldy #ERRVAL + 990 210F 4C AB 26 jmp BOOT_ERROR + 991 2112 BOOT4: + 992 2112 .MACEND + 993 ; + 994 ; now copy segtable to low mem + 995 ; + 996 2112 A9 08 lda #>IOBUFF + 997 2114 85 7B sta J+HI + 998 2116 A9 00 lda #(SEGTBL-2) + Wed May 24 1989 15:00 Page 23 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1001 211C 85 7D sta K+HI + 1002 211E A9 FE lda #<(SEGTBL-2) + 1003 2120 85 7C sta K+LO + 1004 + 1005 2122 AD 01 08 lda IOBUFF+1 ; get LSB + 1006 2125 0A asl A ; *2, to pick up the carry + 1007 2126 AD 00 08 lda IOBUFF ; get how many words + 1008 2129 2A rol A ; *2 for number of bytes + 1009 212A 8D 27 2A sta PSEEK+SM_FPOS+HI ; set page number + 1010 212D AA tax ; make it a counter + 1011 212E A0 02 ldy #2 ; start at second byte, after length + 1012 2130 CPSEGT: + 1013 2130 B1 7A lda (J),y ; get byte + 1014 2132 91 7C sta (K),y ; save byte + 1015 2134 C8 iny ; next byte + 1016 2135 D0 F9 bne CPSEGT ; go do it + 1017 2137 E6 7B inc J+HI + 1018 2139 E6 7D inc K+HI + 1019 213B A0 00 ldy #0 ; restart at beginning of block + 1020 213D CA dex ; count page + 1021 213E 10 F0 bpl CPSEGT ; next page + 1022 ; + 1023 ; now, seek to page following seg table + 1024 ; + 1025 2140 EE 27 2A inc PSEEK+SM_FPOS+HI ; next page + 1026 2143 AD 27 2A lda PSEEK+SM_FPOS+HI ; make sure it is an even 512 page + 1027 2146 29 01 and #$01 ; is it odd? + 1028 2148 F0 07 beq BTSK0 ; nope, so we be okay + 1029 214A EE 27 2A inc PSEEK+SM_FPOS+HI ; next page + 1030 214D A9 03 lda #RETRY_COUNT ; set retry + 1031 214F 85 16 sta RETRIES ; just use this for now + 1032 2151 BTSK0: + 1033 2151 SET_MARK PSEEK ; and point to beginning of game data + 1034 2151 PRODOS $CE, PSEEK + 1035 2151 20 00 BF jsr $BF00 ; ProDOS handler + 1036 2154 CE DB $CE ; ProDOS function code + 1037 2155 242A DW PSEEK ; Function Parameter Block address + 1038 2157 .MACEND + 1039 2157 .MACEND + 1040 + 1041 2157 A9 96 lda #>ZBEGIN ; begining of game code + 1042 2159 8D 32 2A sta READ_BLOCK+RD_BUFFER+HI ; and where to begin next read + 1043 215C A9 28 lda #(Z1SIZE&$FE) ; get size + 1044 215E 8D 34 2A sta READ_BLOCK+RD_BUFFLEN+HI ; to show how much to read + 1045 2161 A9 00 lda #0 ; get size in words + 1046 2163 8D 33 2A sta READ_BLOCK+RD_BUFFLEN+LO ; to show how much to read + 1047 2166 READ READ_BLOCK ; and read in part 1 of preload + 1048 2166 PRODOS $CA, READ_BLOCK + 1049 2166 20 00 BF jsr $BF00 ; ProDOS handler + 1050 2169 CA DB $CA ; ProDOS function code + 1051 216A 2F2A DW READ_BLOCK ; Function Parameter Block address + 1052 216C .MACEND + 1053 216C .MACEND + 1054 216C 90 0B bcc BTSK00 ; just fine + 1055 216E C6 16 dec RETRIES ; try again + 1056 2170 10 DF bpl BTSK0 ; fine + 1057 2172 ERRCHK ; then just die + Wed May 24 1989 15:00 Page 24 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1058 0005 ERRVAL .VAR ERRVAL+1 + 1059 2172 90 05 bcc BOOT5 + 1060 2174 A0 05 ldy #ERRVAL + 1061 2176 4C AB 26 jmp BOOT_ERROR + 1062 2179 BOOT5: + 1063 2179 .MACEND + 1064 2179 BTSK00: + 1065 2179 A9 04 lda #4 ; 4 pages per read + 1066 217B 8D 34 2A sta READ_BLOCK+RD_BUFFLEN+HI ; and lots + 1067 217E A9 08 lda #>IOBUFF ; read into my io buffer + 1068 2180 8D 32 2A sta READ_BLOCK+RD_BUFFER+HI ; hi part of address + 1069 + 1070 [01] IF Z1SIZE & 1 ; if odd, do something special + 1071 2183 READ READ_BLOCK + 1072 2183 PRODOS $CA, READ_BLOCK + 1073 2183 20 00 BF jsr $BF00 ; ProDOS handler + 1074 2186 CA DB $CA ; ProDOS function code + 1075 2187 2F2A DW READ_BLOCK ; Function Parameter Block address + 1076 2189 .MACEND + 1077 2189 .MACEND + 1078 2189 A0 00 ldy #0 ; copy second page + 1079 218B C2LOOP: + 1080 218B B9 00 08 lda IOBUFF,Y + 1081 218E 99 00 BE sta ZBEGIN+(Z1SIZE*$100)-$100,Y + 1082 2191 C8 iny + 1083 2192 D0 F7 bne C2LOOP + 1084 2194 A9 3F lda #(>Z2BEGIN-1) ; don't need first block + 1085 2196 8D E2 21 sta MODOP+2 + 1086 2199 D0 1B bne RD10 ; skip that first read + 1087 [00] ENDIF + 1088 219B AUXRDL: + 1089 219B A9 03 lda #RETRY_COUNT ; set retry + 1090 219D 85 16 sta RETRIES ; just use this for now + 1091 219F AUXRDL0: + 1092 219F READ READ_BLOCK ; and do the read + 1093 219F PRODOS $CA, READ_BLOCK + 1094 219F 20 00 BF jsr $BF00 ; ProDOS handler + 1095 21A2 CA DB $CA ; ProDOS function code + 1096 21A3 2F2A DW READ_BLOCK ; Function Parameter Block address + 1097 21A5 .MACEND + 1098 21A5 .MACEND + 1099 21A5 90 0F bcc RD10 + 1100 21A7 C9 4C cmp #$4C ; this just means EOF already + 1101 21A9 F0 54 beq BT12 ; otherwise, blech + 1102 21AB C6 16 dec RETRIES ; try again + 1103 21AD 10 F0 bpl AUXRDL0 ; fine + 1104 21AF ERRCHK ; then just die + 1105 0006 ERRVAL .VAR ERRVAL+1 + 1106 21AF 90 05 bcc BOOT6 + 1107 21B1 A0 06 ldy #ERRVAL + 1108 21B3 4C AB 26 jmp BOOT_ERROR + 1109 21B6 BOOT6: + 1110 21B6 .MACEND + 1111 21B6 RD10: + 1112 21B6 A9 08 lda #>IOBUFF ; read into my io buffer + 1113 21B8 8D DF 21 sta CLOOP+2 ; start at IOBUFF + 1114 21BB A9 04 lda #4 ; 4 copies + Wed May 24 1989 15:00 Page 25 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1115 21BD 85 7E sta L ; okay + 1116 21BF RD11: + 1117 21BF A0 00 ldy #0 ; start at zero, of course + 1118 21C1 AD E2 21 lda MODOP+2 ; check where we are reading too + 1119 21C4 F0 39 beq BT12 ; wrapped, so we had better be done + 1120 21C6 C9 BF cmp #>PRGLBL ; done with aux mem, part 1? + 1121 21C8 90 10 bcc LOOPST ; nope + 1122 21CA D0 05 bne RD12 ; no need to change + 1123 21CC A9 D0 lda #Z3PAGE ; restart at top of memory + 1124 21CE 8D E2 21 sta MODOP+2 ; and do some self modifying code + 1125 21D1 RD12: + 1126 21D1 8D 09 C0 sta ALTZP+AUX ; turn on alt ZP + 1127 21D4 AD 83 C0 lda BNK2SET ; write to upper mem + 1128 21D7 AD 83 C0 lda BNK2SET ; write to upper mem + 1129 21DA LOOPST: + 1130 21DA 8D 05 C0 sta WRTBNK+AUX ; always aux mem + 1131 21DD CLOOP: + 1132 21DD B9 00 08 lda IOBUFF,Y ; get char + 1133 21E0 99 00 40 MODOP: sta Z2BEGIN,Y ; save + 1134 21E3 C8 iny ; point to next one + 1135 21E4 D0 F7 bne CLOOP ; get next one + 1136 + 1137 21E6 AD 82 C0 lda RDROM ; swap back rom, just in case + 1138 21E9 AD 82 C0 lda RDROM ; swap back rom, just in case + 1139 21EC 8D 08 C0 sta ALTZP+MAIN ; and back to main page + 1140 21EF 8D 04 C0 sta WRTBNK+MAIN ; read into main bank + 1141 + 1142 21F2 EE E2 21 inc MODOP+2 ; point to next page + 1143 21F5 EE DF 21 inc CLOOP+2 ; point to next page + 1144 21F8 C6 7E dec L ; next page + 1145 21FA D0 C3 bne RD11 ; and get it + 1146 + 1147 21FC 4C 9B 21 jmp AUXRDL ; get next 1k + 1148 21FF BT12: + 1149 21FF AD 30 2A lda READ_BLOCK+RD_REFNUM ; get refnum for + 1150 2202 8D 22 2A sta CLOSE_BLOCK+CL_REFNUM ; closing the file + 1151 2205 CLOSE CLOSE_BLOCK ; okay, closed + 1152 2205 PRODOS $CC, CLOSE_BLOCK + 1153 2205 20 00 BF jsr $BF00 ; ProDOS handler + 1154 2208 CC DB $CC ; ProDOS function code + 1155 2209 212A DW CLOSE_BLOCK ; Function Parameter Block address + 1156 220B .MACEND + 1157 220B .MACEND + 1158 ; + 1159 ; relocate the Zero Page routines + 1160 ; + 1161 220B A2 2D ldx #RLCLEN ; length of routine + 1162 220D RLOC: + 1163 220D BD E2 23 lda FETCHBx,X ; get byte + 1164 2210 95 D1 sta ZERO_FB,X ; save byte + 1165 2212 CA dex ; get next one + 1166 2213 10 F8 bpl RLOC ; thank you + 1167 ; + 1168 ; and now for the copying screen line sub + 1169 ; + 1170 2215 A2 7C ldx #CPYLEN + 1171 2217 CPYCPLP: + Wed May 24 1989 15:00 Page 26 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1172 2217 BD 10 24 lda CPYx,X + 1173 221A 9D 50 1D sta COPY_LINE,X + 1174 221D CA dex + 1175 221E 10 F7 bpl CPYCPLP + 1176 ; + 1177 ; now relocate page 3 stuff + 1178 ; + 1179 2220 A2 DF ldx #PAGE3RELL+1 ; get length of page 3 stuff + 1180 2222 MSRCL: + 1181 2222 BD 8C 24 lda PAGE3REL-1,X ; get byte + 1182 2225 9D FF 02 sta PAGE3STUFF-1,X ; save byte + 1183 2228 CA dex ; count byte + 1184 2229 D0 F7 bne MSRCL ; get next? + 1185 + 1186 222B 20 31 22 jsr ZBOOT ; set up ZIP stuff + 1187 + 1188 222E 4C 00 40 JMP INTR_BEGIN ; jump to the interpreter + 1189 + 1190 2231 INCLUDE ZBOOT.ASM ; ZBOOT subroutine + 1191 PAGE + Wed May 24 1989 15:00 Page 27 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- APPLE ProDOS BOOT CODE ---" + + 1192 2231 STTL "--- ZIP CODE BOOT PART ---" + 1193 2231 ZBOOT: + 1194 ; + 1195 ; clear out ZERO page stuff + 1196 ; + 1197 2231 A5 65 lda ARG2+LO ; get machine id! + 1198 2233 8D 1E 96 sta ZBEGIN+ZINTWD ; save before it gets zeroed + 1199 + 1200 2236 A2 1F ldx #LASTWV-1 ; start at end of first part + 1201 2238 A9 00 lda #0 ; and clear to zero + 1202 223A ZEROL: + 1203 223A 95 00 sta 0,X ; clear out zero page loc + 1204 223C CA dex ; next loc + 1205 223D 10 FB bpl ZEROL ; and do next one + 1206 + 1207 223F A2 50 ldx #ZEROPG ; now do other part + 1208 2241 ZEROL1: + 1209 2241 95 00 sta 0,X ; zero this one + 1210 2243 E8 inx ; point to next one + 1211 2244 E0 D1 cpx #LASTZP ; find the last + 1212 2246 D0 F9 bne ZEROL1 ; okay, so do it + 1213 ; + 1214 ; get game code from data and set up absolute pointers + 1215 ; + 1216 2248 AD 00 96 lda ZBEGIN+ZVERS ; IS GAME A YZIP? + 1217 224B C9 06 cmp #6 ; (X) + 1218 224D F0 07 beq YESEZ ; YES, CONTINUE + 1219 + 1220 ; *** ERROR #15 -- NOT AN EZIP GAME *** + 1221 224F A9 0F lda #15 + 1222 2251 A0 00 ldy #0 + 1223 2253 4C 94 25 jmp ZERROR + 1224 2256 YESEZ: + 1225 2256 A9 3B lda #%00111011 ; ENABLE SOUND, underline, MONOSPACING (X) + 1226 2258 8D 01 96 sta ZBEGIN+ZMODE + 1227 + 1228 225B A9 00 lda #0 ; CLEAR HIGH BYTE + 1229 225D 85 58 sta MOUSEF ; init mouse flag to no mouse + 1230 225F 8D 22 96 sta ZBEGIN+ZHWRD + 1231 2262 8D 24 96 sta ZBEGIN+ZVWRD + 1232 2265 A9 8C lda #MAXWIDTH ; SET SCREEN PARAMETERS + 1233 2267 8D 23 96 sta ZBEGIN+ZHWRD+1 + 1234 226A A9 2E lda #MAXWIDTH/3 ; number of mono spaces on a line + 1235 226C 8D 21 96 sta ZBEGIN+ZSCRWD+1 + 1236 226F A9 C0 lda #MAXHEIGHT + 1237 2271 8D 25 96 sta ZBEGIN+ZVWRD+1 + 1238 2274 A9 15 lda #MAXHEIGHT/FONT_H + 1239 2276 8D 20 96 sta ZBEGIN+ZSCRWD ; number of lines of chars + 1240 2279 A9 09 lda #FONT_H ; height of font + 1241 227B 8D 26 96 sta ZBEGIN+ZFWRD + 1242 227E A9 03 lda #3 ; width of font (2 spaces == 8 pixels) + 1243 2280 8D 27 96 sta ZBEGIN+ZFWRD+1 + 1244 2283 A9 09 lda #9 ; the color white is the foreground color + 1245 2285 8D 2D 96 sta ZBEGIN+ZCLRWD+1 ; show Z game too + 1246 2288 A9 02 lda #2 ; black is the background color + 1247 228A 8D 2C 96 sta ZBEGIN+ZCLRWD ; tell game about it + 1248 ; + Wed May 24 1989 15:00 Page 28 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1249 ; just move global address to zero page for quick working + 1250 ; + 1251 228D AD 0C 96 lda ZBEGIN+ZGLOBAL ; get page + 1252 2290 85 51 sta GLOBAL+HI ; save which page + 1253 2292 AD 0D 96 lda ZBEGIN+ZGLOBAL+1 ; LSB NEEDN'T CHANGE + 1254 2295 85 50 sta GLOBAL+LO ; so just store it away + 1255 ; + 1256 ; figger absolute address for the fword table + 1257 ; + 1258 2297 AD 18 96 lda ZBEGIN+ZFWORD ; get fword page number + 1259 229A 20 ED 26 jsr SETPC ; and get absolute address + 1260 229D 85 56 sta FWORDS+HI ; show high addr of table + 1261 229F 84 57 sty FWORDS+ABANK ; show which bank + 1262 22A1 AD 19 96 lda ZBEGIN+ZFWORD+1 ; LSB NEEDN'T CHANGE + 1263 22A4 85 55 sta FWORDS+LO ; so just save it + 1264 ; + 1265 ; figger absolute address for the vocab table + 1266 ; + 1267 22A6 AD 08 96 lda ZBEGIN+ZVOCAB ; get fword page number + 1268 22A9 20 ED 26 jsr SETPC ; and get absolute address + 1269 22AC 85 53 sta VOCAB+HI ; show high addr of table + 1270 22AE 84 54 sty VOCAB+ABANK ; show which bank + 1271 22B0 A9 00 lda #0 ; this is always zero (get lo part from MPCL) + 1272 22B2 85 52 sta VOCAB+LO ; so just save it + 1273 ; + 1274 ; now do somethin' with the TCHAR table (maybe, if <> 0) + 1275 ; + 1276 22B4 AD 2E 96 lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + 1277 22B7 0D 2F 96 ora ZBEGIN+ZTCHAR+1 ; is it zero though? + 1278 22BA D0 05 bne TCH1 ; no, so copy it to somewhere useful + 1279 22BC 8D 00 1D sta TCHARTBL ; not there, so zero first byte in table + 1280 22BF F0 2F beq TCHj ; jmp + 1281 22C1 TCH1: + 1282 22C1 AD 2E 96 lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + 1283 22C4 20 ED 26 jsr SETPC ; and now make absolute + 1284 22C7 85 8D sta FPCH ; Save in FPC + 1285 22C9 84 8E sty FPCBNK + 1286 22CB AD 2F 96 lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + 1287 22CE 85 8C sta FPCL ; now move pointer to fetch spot + 1288 + 1289 22D0 A9 00 lda #0 ; and set index + 1290 22D2 85 78 sta I ; thank you + 1291 22D4 TCHLP: + 1292 22D4 20 14 27 jsr FETCHB ; get the byte in [a] + 1293 22D7 A6 78 ldx I ; get offset + 1294 22D9 E6 78 inc I ; and point to next one + 1295 22DB 9D 00 1D sta TCHARTBL,X ; save in lower memory, thank you + 1296 22DE C9 00 cmp #0 ; are we done yet? + 1297 22E0 F0 0E beq TCHj ; NULL TERMINATED STRING + 1298 22E2 C9 FF cmp #$FF ; $ff means all >128 chars are terminators + 1299 22E4 D0 04 bne TCHLNEXT ; nope + 1300 22E6 A9 01 lda #1 ; yes, + 1301 22E8 85 B9 sta ALLFLG ; so set flag to say so + 1302 22EA TCHLNEXT: + 1303 22EA 20 38 27 jsr NEXTFPC ; point to next one + 1304 22ED 4C D4 22 jmp TCHLP ; and go get it + 1305 22F0 TCHj: + Wed May 24 1989 15:00 Page 29 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1306 22F0 20 C6 28 jsr DO_DSEGS ; set up disk segment pointers + 1307 ; + 1308 ; use mouse/joystick, see if either is connected + 1309 ; + 1310 22F3 AD 11 96 lda ZBEGIN+ZFLAGS+1 ; get game flags + 1311 22F6 29 20 and #FMOUS ; uses a mouse? + 1312 22F8 F0 4C beq ZBEND ; nope, so don't ask + 1313 22FA 20 58 FC jsr MHOME ; clear & home + 1314 22FD MSLOOP: + 1315 22FD DLINE MMSG ; ask about Mouse/Joystick/Keyboard + 1316 22FD A2 74 ldx #MMSG ; get other part of string + 1318 [01] IFMA 2 ; check to see if length passed in + 1319 ldy ; then just fetch it + 1320 [01] ELSE + 1321 2301 A0 59 ldy #MMSGL ; get length of string + 1322 [00] ENDIF + 1323 2303 20 D5 26 jsr DLINE ; print the string + 1324 2306 .MACEND + 1325 2306 A9 01 lda #1 ; move to left + 1326 2308 85 24 sta CHZ ; move to column 1 + 1327 230A 20 22 FC jsr MBASCAL ; move cursor there! + 1328 230D A9 8D lda #EOL.OR.$80 ; send out eol + 1329 230F 20 ED FD jsr MCOUT ; bye + 1330 2312 20 0C FD jsr MRDKEY ; get a key please + 1331 2315 20 ED FD jsr MCOUT ; put key out there + 1332 2318 29 7F and #$7F ; turn off hi bit + 1333 231A C9 4D cmp #'M' ; mouse? + 1334 231C F0 1A beq DO_MOUSE ; yup + 1335 231E C9 6D cmp #'m' + 1336 2320 F0 16 beq DO_MOUSE + 1337 2322 C9 4A cmp #'J' ; Joystick? + 1338 2324 F0 19 beq DO_STICK ; yup + 1339 2326 C9 6A cmp #'j' + 1340 2328 F0 15 beq DO_STICK + 1341 232A C9 4E cmp #'N' ; neither + 1342 232C F0 18 beq DO_NEITHER ; yup + 1343 232E C9 6E cmp #'n' + 1344 2330 F0 14 beq DO_NEITHER + 1345 2332 MSLOOP1: + 1346 2332 20 3A FF jsr MBELL ; complain + 1347 2335 4C FD 22 jmp MSLOOP ; and do again + 1348 2338 DO_MOUSE: + 1349 2338 20 58 27 jsr INST_MOUSE ; install mouse handlers + 1350 233B B0 F5 bcs MSLOOP1 ; problems, try again + 1351 233D 90 07 bcc ZBEND ; continue + 1352 233F DO_STICK: + 1353 233F 20 E2 27 jsr INST_STICK ; install joystick handler + 1354 2342 B0 EE bcs MSLOOP1 ; try again + 1355 2344 90 00 bcc ZBEND ; continue, please + 1356 2346 DO_NEITHER: + 1357 2346 ZBEND: + 1358 ; + 1359 ; now, set flags like I want them + 1360 2346 A9 4A lda #FMONO^FDISP^FCOLO + 1361 2348 A6 58 ldx MOUSEF ; doing mousey stuff? + 1362 234A F0 02 beq ZBEND0 ; nope + Wed May 24 1989 15:00 Page 30 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1363 234C 09 20 ora #FMOUS ; then turn on that bit too + 1364 234E ZBEND0: + 1365 234E 8D 11 96 sta ZBEGIN+ZFLAGS+1 ; set game flags + 1366 ; + 1367 ; + 1368 ; Multiply ZFOFF & ZSOFF * 8 to get actual offset + 1369 ; + 1370 2351 AD 28 96 lda ZBEGIN+ZFOFF ; hi part + 1371 2354 85 5C sta FOFFM ; this'll be the middle part + 1372 2356 AD 29 96 lda ZBEGIN+ZFOFF+1 ; lo part + 1373 2359 0A asl A ; *2 + 1374 235A 26 5C rol FOFFM + 1375 235C 26 5B rol FOFFH + 1376 235E 0A asl A ; *4 + 1377 235F 26 5C rol FOFFM + 1378 2361 26 5B rol FOFFH + 1379 2363 0A asl A ; *8 + 1380 2364 26 5C rol FOFFM + 1381 2366 26 5B rol FOFFH + 1382 2368 85 5D sta FOFFL ; lo part here too + 1383 ; + 1384 ; now do string offset + 1385 ; + 1386 236A AD 2A 96 lda ZBEGIN+ZSOFF ; hi part + 1387 236D 85 5F sta SOFFM ; this'll be the middle part + 1388 236F AD 2B 96 lda ZBEGIN+ZSOFF+1 ; lo part + 1389 2372 0A asl A ; *2 + 1390 2373 26 5F rol SOFFM + 1391 2375 26 5E rol SOFFH + 1392 2377 0A asl A ; *4 + 1393 2378 26 5F rol SOFFM + 1394 237A 26 5E rol SOFFH + 1395 237C 0A asl A ; *8 + 1396 237D 26 5F rol SOFFM + 1397 237F 26 5E rol SOFFH + 1398 2381 85 60 sta SOFFL ; lo part here too + 1399 + 1400 2383 AD 06 96 lda ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + 1401 2386 85 81 sta ZPCM ; MSB + 1402 2388 AD 07 96 lda ZBEGIN+ZGO+1 ; AND LSB + 1403 238B 0A asl A ; *2 + 1404 238C 26 81 rol ZPCM + 1405 238E 26 82 rol ZPCH + 1406 2390 0A asl A ; *4 + 1407 2391 26 81 rol ZPCM + 1408 2393 26 82 rol ZPCH + 1409 ; + 1410 ; now add offset + 1411 ; + 1412 2395 18 clc ; doing adding + 1413 2396 65 5D adc FOFFL ; add in lo part + 1414 2398 85 80 sta ZPCL + 1415 239A A5 81 lda ZPCM + 1416 239C 65 5C adc FOFFM + 1417 239E 85 81 sta ZPCM + 1418 23A0 A5 82 lda ZPCH + 1419 23A2 65 5B adc FOFFH + Wed May 24 1989 15:00 Page 31 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- ZIP CODE BOOT PART ---" + + 1420 23A4 85 82 sta ZPCH + 1421 ; + 1422 ; now, set up TBLPUR, FUNPRE, and FUNPUR + 1423 ; + 1424 23A6 AD 1D 19 lda SEGTBL+SGTTBLE+1 ; get last page of table preload + 1425 23A9 0A asl A ; make 256K page + 1426 23AA 85 C2 sta TBLPUR ; show last pre table + 1427 23AC E6 C2 inc TBLPUR ; but we want first pure table address + 1428 23AE E6 C2 inc TBLPUR ; so point to it + 1429 23B0 A5 C2 lda TBLPUR ; does table preload take up all preload? + 1430 23B2 C9 D6 cmp #PGBEGIN ; reach 1st paged page? + 1431 23B4 B0 17 bcs ZBEND1 ; ayyup, no function preload + 1432 + 1433 23B6 AD 21 19 lda SEGTBL+SGTFUNS+1 ; get first page of function preload + 1434 23B9 0A asl A ; make 256K page + 1435 23BA 85 C3 sta FUNPRE ; show me + 1436 23BC AD 23 19 lda SEGTBL+SGTFUNE+1 ; last page of function preload + 1437 23BF 0A asl A ; make 256K page + 1438 23C0 85 C4 sta FUNPUR ; show last pre function + 1439 23C2 E6 C4 inc FUNPUR ; but we want first pure function + 1440 23C4 E6 C4 inc FUNPUR ; now we point to it + 1441 23C6 + 1442 23C6 A5 C2 lda TBLPUR ; now figger out negative number to + 1443 23C8 38 sec ; add to function preload addres to + 1444 23C9 E5 C3 sbc FUNPRE ; get page offset in memory + 1445 23CB 85 C5 sta FUNPGE ; set up offset + 1446 ; + 1447 ; and now to set up extension table pointer + 1448 ; + 1449 23CD ZBEND1: + 1450 23CD AD 37 96 lda ZBEGIN+ZEXTAB+1 ; LSB of table + 1451 23D0 85 CE sta MSTBL+LO ; stays the same + 1452 23D2 AD 36 96 lda ZBEGIN+ZEXTAB ; MSB of table + 1453 23D5 20 ED 26 jsr SETPC ; get me the memory addres + 1454 23D8 84 D0 sty MSTBL+ABANK ; save bank + 1455 23DA 85 CF sta MSTBL+HI ; and page + 1456 23DC + 1457 23DC 20 D7 29 jsr INIT_CHARSET ; initialize the charset + 1458 23DF 4C 34 29 jmp INITPAG ; set up paging system + 1459 + 1460 23E2 END + 1461 + 1462 23E2 INCLUDE BREL.ASM ; relocated subroutines + 1463 23E2 STTL "--- RELOCATED SUBROUTINES ---" + 1464 PAGE + Wed May 24 1989 15:00 Page 32 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1465 + 1466 ; + 1467 ; FETCHB - use FPC to get a byte in either aux or main mem + 1468 ; + 1469 23E2 FETCHBx: + 1470 23E2 99 02 C0 sta RDBNK,Y ; set bank, lower + 1471 23E5 A0 00 ldy #0 ; gotta use Y + 1472 23E7 B1 8C lda (FPC),Y ; so go get it + 1473 23E9 8D 02 C0 sta RDBNK ; go back to main bank + 1474 23EC 60 rts ; and return + 1475 ; + 1476 ; ZFETCH - fetch byte at (ZPCPNT),Y - offset from (ZPCPNT) + 1477 ; + 1478 23ED ZFETCHx: + 1479 23ED 9D 02 C0 sta RDBNK,X ; set lower bank + 1480 23F0 B1 83 lda (ZPCPNT),Y ; so go get it + 1481 23F2 8D 02 C0 sta RDBNK ; go back to main bank + 1482 23F5 60 rts ; bye + 1483 ; + 1484 ; MFETCH - fetch byte at (MPCPNT),Y - offset from (MPCPNT) + 1485 ; + 1486 23F6 MFETCHx: + 1487 23F6 9D 02 C0 sta RDBNK,X ; set bank + 1488 23F9 B1 89 lda (MPCPNT),Y ; so go get it + 1489 23FB 8D 02 C0 sta RDBNK ; go back to main bank + 1490 23FE 60 rts ; bye + 1491 ; + 1492 ; SAVE_DATA - copy data from [DBUFF] to IOBUFF + 1493 ; [Y] must == 0; [X] == DSKBNK; [A] == IOBUFF ($8 or $9) + 1494 ; + 1495 23FF 9D 02 C0 sta RDBNK,X ; and select that bank for reading + 1496 2402 85 F7 sta SAVE_DATA+9 ; show which part of iobuff + 1497 2404 SDAT1: + 1498 2404 B1 B6 lda (DBUFF),Y ; get me that byte + 1499 2406 SDAT2: + 1500 2406 99 00 08 sta IOBUFF,Y ; MODIFIED ABOVE + 1501 2409 C8 iny + 1502 240A D0 F8 bne SDAT1 + 1503 240C 8D 02 C0 sta RDBNK+MAIN ; and back to main + 1504 240F 60 rts + 1505 002D RLCLEN EQU $-FETCHBx-1 ; mark length + 1506 ; + 1507 ; COPY_LINE: + 1508 ; SPC - source pointer + 1509 ; FPC - destination pointer + 1510 ; SPCBNK - bank the above two are talking about + 1511 ; CPY_COUNT - end-start bytes to move + 1512 ; STMASK - mask to use on first byte (0 if none) + 1513 ; ENDMASK - mask to use for end byte (0 if none) + 1514 ; + 1515 ; MODIFIED CODE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + 1516 ; The definitions for CPY_MODs are HARD CODED in apple.equ - they MUST + 1517 ; match the definitions below for similar xCPY_MODs!!!!!!!! + 1518 ; DON'T CHANGE WITHOUT FIXING THOSE OFFSETS IN APPLE.EQU!!!!! + 1519 ; + 1520 2410 CPYx EQU * + 1521 2410 A6 91 ldx SPCBNK ; set up banks for first byte + Wed May 24 1989 15:00 Page 33 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1522 2412 BD 54 C0 lda PAGE2SW,X ; r/w which bank in display mem + 1523 2415 A0 00 ldy #0 ; use Y reg + 1524 2417 A5 1A lda STMASK ; get start mask + 1525 2419 F0 0E beq CPLOOP ; no start mask, start in middle of loop + 1526 241B 31 8C and (FPC),Y ; turn off changing bits, keep good bits + 1527 241D 91 8C sta (FPC),Y ; save it + 1528 241F A5 1A lda STMASK ; get changing bits + 1529 2421 49 FF eor #$FF ; turn on changing bits + 1530 2423 31 8F and (SPC),Y ; get SPC byte + 1531 2425 11 8C ora (FPC),Y ; turn them on in destination too + 1532 2427 91 8C sta (FPC),Y ; and destiny + 1533 2429 CPLOOP: + 1534 2429 A5 BD lda CPY_COUNT ; get count + 1535 242B 4A lsr A ; /2 for number in this bank + 1536 242C AA tax ; put in X for indexing + 1537 242D F0 15 beq CPLP2 ; then done! + 1538 242F CA dex ; zero base the number + 1539 2430 A5 1A lda STMASK ; special start? + 1540 2432 F0 07 beq CPL1 ; nope + 1541 2434 EE 7C 1D inc CPY_MOD1_SRC ; first one already done + 1542 2437 EE 7F 1D inc CPY_MOD1_DST ; point to next one + 1543 243A CA dex ; and count first one as done + 1544 243B CPL1: + 1545 243B BD 00 20 lda SCREEN,X ; get byte + 1546 243E 9D 00 20 sta SCREEN,X ; store byte + 1547 2441 CA dex ; count down + 1548 2442 10 F7 bpl CPL1 ; and do it all again + 1549 2444 CPLP2: + 1550 2444 A0 00 ldy #0 ; reset y + 1551 2446 A5 91 lda SPCBNK ; get current bank + 1552 2448 49 01 eor #1 ; toggle to point to the other one + 1553 244A AA tax + 1554 244B BD 54 C0 lda PAGE2SW,X + 1555 244E 8A txa ; which bank? + 1556 244F F0 07 beq CPLP21 ; we are now in main, things are fine + 1557 2451 EE A0 1D inc CPY_MOD2_SRC ; start one more if now in AUX + 1558 2454 EE A3 1D inc CPY_MOD2_DST + 1559 2457 CA dex ; and count as done + 1560 2458 CPLP21: + 1561 2458 A5 BD lda CPY_COUNT ; get count again + 1562 245A 4A lsr A ; /2 for bytes in this bank + 1563 245B AA tax ; put in X for counter + 1564 245C F0 0A beq CPDONE ; nothing here + 1565 245E CA dex ; zero base the number + 1566 245F CPL2: + 1567 245F BD 00 20 lda SCREEN,X ; get byte + 1568 2462 9D 00 20 sta SCREEN,X ; store byte + 1569 2465 CA dex ; count byte + 1570 2466 10 F7 bpl CPL2 ; and swing by again + 1571 2468 CPDONE: + 1572 2468 A5 1B lda ENDMASK ; do same mucking as when starting + 1573 246A F0 1D beq CPEXIT ; no mucking + 1574 246C 48 pha ; save endmask + 1575 246D A5 BD lda CPY_COUNT ; get how many bytes being copied + 1576 246F 4A lsr A ; /2 + 1577 2470 B0 07 bcs CPDONE1 ; if odd, then we are pointing to correct + 1578 2472 48 pha ; save a + Wed May 24 1989 15:00 Page 34 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1579 2473 A6 91 ldx SPCBNK ; get original bank + 1580 2475 BD 54 C0 lda PAGE2SW,X ; and point to it + 1581 2478 68 pla ; get it back + 1582 2479 CPDONE1: + 1583 2479 A8 tay ; get offset + 1584 247A 68 pla ; get end mask back + 1585 247B 49 FF eor #$FF ; turn on all off bits + 1586 247D 31 8C and (FPC),Y ; turn off changing bits + 1587 247F 91 8C sta (FPC),Y ; save it + 1588 2481 B1 8F lda (SPC),Y ; get source byte + 1589 2483 25 1B and ENDMASK ; turn on changing bits + 1590 2485 11 8C ora (FPC),Y ; turn them on in destination too + 1591 2487 91 8C sta (FPC),Y ; and destiny + 1592 2489 CPEXIT: + 1593 2489 AD 54 C0 lda PAGE2SW ; set back to main mem + 1594 248C 60 rts + 1595 007C CPYLEN EQU $-CPYx-1 + 1596 002C xCPY_MOD1 equ (CPL1-CPYx+1) + 1597 002F xCPY_MOD1_DST equ xCPY_MOD1+3 + 1598 0050 xCPY_MOD2 equ (CPL2-CPYx+1) + 1599 0053 xCPY_MOD2_DST equ xCPY_MOD2+3 + 1600 248D PAGE3REL: + 1601 ; + 1602 ; MOUSER - this vectors the call to the correct place + 1603 ; + 1604 248D MOUSERx: + 1605 248D 48 pha ; save A for a sec + 1606 248E BD 12 C4 MSX1: lda MTABLE,X ; get lo part of address + 1607 2491 8D 10 03 sta MSVECTOR+LO ; save lo part of address + 1608 2494 68 pla ; get A back + 1609 2495 EA nop + 1610 2496 A2 C4 MSX2: ldx #$C4 ; might be changed, depending on slot + 1611 2498 A0 40 MSX3: ldy #$40 ; hopefully, this doesn't + 1612 249A 6C 10 03 jmp (MSVECTOR) ; and away we go + 1613 000F MSRxLEN EQU $-MOUSERx-1 ; show how long this is + 1614 249D MSVECTORx: + 1615 249D ds 1 ; where lo part of vector goes + 1616 249E C4 MSX4: db $C4 ; slot where mouse is + 1617 0011 MSRLEN EQU $-MOUSERx-1 ; length or routine + 1618 ; + 1619 ; colors for screen lines + 1620 ; + 1621 RADIX H + 1622 249F COLORSx: + 1623 249F 00 00 00 00 db 00,00,00,00 ; black + 1624 24A3 08 11 22 44 db 08,11,22,44 ; magenta + 1625 24A7 44 08 11 22 db 44,08,11,22 ; brown + 1626 24AB 4C 19 33 66 db 4C,19,33,66 ; orange + 1627 24AF 22 44 08 11 db 22,44,08,11 ; dark green + 1628 24B3 2A 55 2A 55 db 2A,55,2A,55 ; gray 1 + 1629 24B7 66 4C 19 33 db 66,4C,19,33 ; green + 1630 24BB 6E 5D 3B 77 db 6E,5D,3B,77 ; yellow + 1631 24BF 11 22 44 08 db 11,22,44,08 ; dark blue + 1632 24C3 19 33 66 4C db 19,33,66,4C ; purple + 1633 24C7 55 2A 55 2A db 55,2A,55,2A ; gray 2 + 1634 24CB 5D 3B 77 6E db 5D,3B,77,6E ; pink + 1635 24CF 33 66 4C 19 db 33,66,4C,19 ; medium blue + Wed May 24 1989 15:00 Page 35 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1636 24D3 3B 77 6E 5D db 3B,77,6E,5D ; light blue + 1637 24D7 77 6E 5D 3B db 77,6E,5D,3B ; aqua + 1638 24DB 7F 7F 7F 7F db 7F,7F,7F,7F ; white + 1639 24DF XPOSTBLx: + 1640 24DF 00 DB 0 + 1641 24E0 00 01 01 02 02 DB 0,1,1,2,2,3,4 + 24E5 03 04 + 1642 24E7 04 05 05 06 06 DB 4,5,5,6,6,7,8 + 24EC 07 08 + 1643 24EE 08 09 09 0A 0A DB 8,9,9,0a,0a,0b,0c + 24F3 0B 0C + 1644 24F5 0C 0D 0D 0E 0E DB 0c,0d,0d,0e,0e,0f,10 + 24FA 0F 10 + 1645 24FC 10 11 11 12 12 DB 10,11,11,12,12,13,14 + 2501 13 14 + 1646 2503 14 15 15 16 16 DB 14,15,15,16,16,17,18 + 2508 17 18 + 1647 250A 18 19 19 1A 1A DB 18,19,19,1a,1a,1b,1c + 250F 1B 1C + 1648 2511 1C 1D 1D 1E 1E DB 1c,1d,1d,1e,1e,1f,20 + 2516 1F 20 + 1649 2518 20 21 21 22 22 DB 20,21,21,22,22,23,24 + 251D 23 24 + 1650 251F 24 25 25 26 26 DB 24,25,25,26,26,27,28 + 2524 27 28 + 1651 2526 28 29 29 2A 2A DB 28,29,29,2a,2a,2b,2c + 252B 2B 2C + 1652 252D 2C 2D 2D 2E 2E DB 2c,2d,2d,2e,2e,2f,30 + 2532 2F 30 + 1653 2534 30 31 31 32 32 DB 30,31,31,32,32,33,34 + 2539 33 34 + 1654 253B 34 35 35 36 36 DB 34,35,35,36,36,37,38 + 2540 37 38 + 1655 2542 38 39 39 3A 3A DB 38,39,39,3a,3a,3b,3c + 2547 3B 3C + 1656 2549 3C 3D 3D 3E 3E DB 3c,3d,3d,3e,3e,3f,40 + 254E 3F 40 + 1657 2550 40 41 41 42 42 DB 40,41,41,42,42,43,44 + 2555 43 44 + 1658 2557 44 45 45 46 46 DB 44,45,45,46,46,47,48 + 255C 47 48 + 1659 255E 48 49 49 4A 4A DB 48,49,49,4a,4a,4b,4c + 2563 4B 4C + 1660 2565 4C 4D 4D 4E 4E DB 4c,4d,4d,4e,4e,4f,50 + 256A 4F 50 + 1661 RADIX D + 1662 00DE PAGE3RELL EQU $-PAGE3REL-1 + 1663 256C END + 1664 + 1665 256C INCLUDE BSUBS.ASM ; subs for e to use + 1666 PAGE + Wed May 24 1989 15:00 Page 36 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- RELOCATED SUBROUTINES ---" + + 1667 256C STTL "--- BOOT CODE SUBROUTINES ---" + 1668 + 1669 256C 0D 0D ERRM: DB EOL,EOL + 1670 256E 49 6E 74 65 72 DB "Internal error " + 2573 6E 61 6C 20 65 + 2578 72 72 6F 72 20 + 1671 257D 30 30 ENUMB: DB "00" + 1672 257F 30 30 2E 20 20 DB "00. " + 1673 0018 ERRML EQU $-ERRM + 1674 2584 30 31 32 33 34 HCHARS: DB "0123456789ABCDEF" + 2589 35 36 37 38 39 + 258E 41 42 43 44 45 + 2593 46 + 1675 ; + 1676 ; ZERROR: print out error code in HexWord: [A][Y]. + 1677 ; + 1678 2594 ZERROR: + 1679 2594 48 pha ; save [A] + 1680 2595 98 tya ; and put y to a for figgering + 1681 2596 A0 03 ldy #3 ; CONVERT ERROR BYTE IN [A] + 1682 2598 ZERR0: + 1683 2598 48 pha + 1684 2599 29 0F and #%00001111 + 1685 259B AA tax + 1686 259C BD 84 25 lda HCHARS,X + 1687 259F 99 7D 25 sta ENUMB,Y + 1688 25A2 68 pla + 1689 25A3 4A LSR A + 1690 25A4 4A LSR A + 1691 25A5 4A lsr A + 1692 25A6 4A lsr A + 1693 25A7 AA tax + 1694 25A8 BD 84 25 lda HCHARS,X + 1695 25AB 88 dey + 1696 25AC 99 7D 25 sta ENUMB,Y + 1697 25AF F0 05 beq ZR1 ; done + 1698 25B1 + 1699 25B1 68 pla ; done with first number + 1700 25B2 88 dey ; and point one more down + 1701 25B3 4C 98 25 jmp ZERR0 ; so work on second number + 1702 25B6 ZR1: + 1703 25B6 A2 6C ldx #ERRM + 1705 25BA A0 18 ldy #ERRML + 1706 25BC 20 D5 26 jsr DLINE ; PRINT ERROR MESSAGE + 1707 25BF 20 01 26 jsr GETRET ; wait for + 1708 25C2 4C 19 26 jmp ZQUIT + 1709 + 1710 25C5 0D 50 6C 65 61 RETQ: db EOL,"Please insert new disk to boot." + 25CA 73 65 20 69 6E + 25CF 73 65 72 74 20 + 25D4 6E 65 77 20 64 + 25D9 69 73 6B 20 74 + 25DE 6F 20 62 6F 6F + 25E3 74 2E + 1711 25E5 0D 41 6E 64 20 db EOL, "And hit RETURN when ready.",EOL + 25EA 68 69 74 20 52 + Wed May 24 1989 15:00 Page 37 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 25EF 45 54 55 52 4E + 25F4 20 77 68 65 6E + 25F9 20 72 65 61 64 + 25FE 79 2E 0D + 1712 003C RETQL EQU $-RETQ + 1713 2601 GETRET: + 1714 2601 DLINE RETQ ; ask for return + 1715 2601 A2 C5 ldx #RETQ ; get other part of string + 1717 [01] IFMA 2 ; check to see if length passed in + 1718 ldy ; then just fetch it + 1719 [01] ELSE + 1720 2605 A0 3C ldy #RETQL ; get length of string + 1721 [00] ENDIF + 1722 2607 20 D5 26 jsr DLINE ; print the string + 1723 260A .MACEND + 1724 260A GETRETL: + 1725 260A AD 00 C0 lda KBD ; get a key + 1726 260D 10 FB bpl GETRETL ; no key + 1727 260F 29 7F and #$7f ; make a good key + 1728 2611 C9 0D cmp #EOL ; return key? + 1729 2613 D0 F5 bne GETRETL ; nope + 1730 2615 20 ED FD jsr MCOUT ; show the + 1731 2618 60 rts + 1732 2619 + 1733 + 1734 ; ---- + 1735 ; QUIT + 1736 ; ---- + 1737 + 1738 2619 ZQUIT: + 1739 2619 A5 59 lda INFODOS ; in dinky-dos? + 1740 261B F0 17 beq ZQUIT2 ; nope + 1741 261D A9 00 lda #0 ; clear power up byte + 1742 261F 8D F4 03 sta $3F4 ; make it do cold boot + 1743 2622 AD FD FF lda RESET_VECTOR+HI ; now, set up where to die to + 1744 2625 8D 33 26 sta ZQUITR1+2 + 1745 2628 AD FC FF lda RESET_VECTOR+LO + 1746 262B 8D 32 26 sta ZQUITR1+1 + 1747 262E AD 82 C0 lda RDROM ; get ROM back + 1748 2631 ZQUITR1: + 1749 2631 4C FC FF jmp RESET_VECTOR ; just reset things + 1750 ; + 1751 ; re-enable /RAM + 1752 ; + 1753 2634 ZQUIT2: + 1754 2634 AE 31 BF ldx DEVCNT ; put device in at end + 1755 2637 E8 inx ; point to one past end + 1756 2638 8E 31 BF stx DEVCNT ; show new count + 1757 263B A9 BF lda #$BF ; /RAM ID + 1758 263D 9D 32 BF sta DEVNUM,X ; save it + 1759 2640 AD 7F 07 lda OLDVEC+HI ; restore old vector + 1760 2643 8D 27 BF sta RAMVEC+HI + 1761 2646 AD 7E 07 lda OLDVEC+LO + 1762 2649 8D 26 BF sta RAMVEC+LO + 1763 ; + 1764 ; now format /RAM + Wed May 24 1989 15:00 Page 38 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1765 ; + 1766 264C A9 03 lda #3 ; stash into FORMAT parm block + 1767 264E 85 42 sta $42 ; it goes here, oddly enough + 1768 2650 A9 B0 lda #$B0 ; device id for /RAM + 1769 2652 85 43 sta $43 ; and here it goes + 1770 2654 A9 11 lda #>GAME1FIO ; IO buffer + 1771 2656 85 45 sta $45 ; this is where it goes + 1772 2658 A9 00 lda #ZBEGIN ; ADD OFFSET TO GET RAM PAGE + 1859 26F5 A0 00 ldy #MAIN ; in the main bank + 1860 26F7 F0 12 beq VFEXI ; BRA to fetch + 1861 26F9 VF2: + 1862 26F9 C9 D6 cmp #PGBEGIN ; is it paged? + 1863 26FB B0 12 bcs VFERR ; yes it be paged, so can't deal with it + 1864 26FD C9 A8 cmp #P3PAGE ; is it in Aux Mem, Part 2? + 1865 26FF B0 06 bcs VF3 ; yes, so subtract different amount + 1866 ; + 1867 ; this is in lower aux + 1868 ; + Wed May 24 1989 15:00 Page 40 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1869 2701 A9 17 lda #(Z2PAGE-Z1SIZE) ; subtract size from offset + 1870 2703 A0 01 ldy #AUX ; show aux mem + 1871 2705 D0 04 bne VFEXI ; jump to end + 1872 2707 VF3: + 1873 2707 A9 28 lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides + 1874 2709 A0 FF ldy #P3BANK ; show page 3 bank + 1875 270B VFEXI: + 1876 270B 18 clc ; get ready for addition + 1877 270C 65 BC adc MEMPAGE ; now get actual offset + 1878 270E 60 rts + 1879 270F VFERR: + 1880 ; + 1881 ; out of range + 1882 ; + 1883 270F A9 22 lda #$22 + 1884 2711 4C 94 25 jmp ZERROR + 1885 + 1886 ; + 1887 ; FETCHB - fetch a byte from either main memory, aux memory, or upper + 1888 ; Aux memory + 1889 ; + 1890 2714 FETCHB: + 1891 2714 A4 8E ldy FPCBNK ; get the bank + 1892 2716 30 03 bmi FB1 ; must be in upper RAM + 1893 2718 4C D1 00 jmp ZERO_FB ; go to low end fetch + 1894 ; + 1895 ; this is in aux mem, >$E000 + 1896 ; + 1897 271B FB1: + 1898 271B A5 8D lda FPCH ; get which page + 1899 271D 8D 2D 27 sta FBMOD+2 ; and show in operand + 1900 2720 A4 8C ldy FPCL ; get which byte + 1901 2722 8D 09 C0 sta ALTZP+AUX ; talk about aux mem + 1902 2725 AD 8B C0 lda BNK1SET ; set up read/write ram in upper mem + 1903 2728 AD 8B C0 lda BNK1SET ; set up read/write ram in upper mem + 1904 272B B9 00 D0 FBMOD: lda Z3BEGIN,Y ; get the sucker + 1905 272E 8D 08 C0 sta ALTZP+MAIN ; go back to main mem + 1906 2731 AE 82 C0 ldx RDROM ; now use ROM please + 1907 2734 AE 82 C0 ldx RDROM ; now use ROM please + 1908 2737 60 rts + 1909 ; + 1910 ; NEXTFPC - inc DPCL and check for wrapping round to next bank + 1911 ; + 1912 2738 NEXTFPC: + 1913 2738 E6 8C inc FPCL ; next lo byte + 1914 273A D0 1B bne NXFP_EXIT ; no change then + 1915 273C E6 8D inc FPCH ; next page + 1916 273E A5 8D lda FPCH ; and get it for checking + 1917 2740 C9 BF cmp #>PRGLBL ; have we reached end of line? + 1918 2742 D0 13 bne NXFP_EXIT ; we be okay + 1919 2744 A5 8E lda FPCBNK ; get bank + 1920 2746 D0 07 bne NXFP1 ; must skip over stuff in middle + 1921 2748 E6 8E inc FPCBNK ; so point to aux bank + 1922 274A A9 40 lda #Z2PAGE ; first page in aux + 1923 274C 85 8D sta FPCH ; and point to it + 1924 274E 60 rts ; toots finis + 1925 274F NXFP1: + Wed May 24 1989 15:00 Page 41 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1926 274F A9 D0 lda #Z3PAGE ; start of part 3 + 1927 2751 85 8D sta FPCH ; so show me + 1928 2753 A9 FF lda #P3BANK ; and point to this bank + 1929 2755 85 8E sta FPCBNK ; okey + 1930 2757 NXFP_EXIT: + 1931 2757 60 rts + 1932 ; + 1933 ; INST_MOUSE - install mouse handler IRQ + 1934 ; + 1935 0303 MFIX1 EQU (MSX1-MOUSERx)+PAGE3STUFF+2 + 1936 030A MFIX2 EQU (MSX2-MOUSERx)+PAGE3STUFF+1 + 1937 0311 MFIX3 EQU (MSX4-MOUSERx)+PAGE3STUFF + 1938 030C MFIX4 EQU (MSX3-MOUSERx)+PAGE3STUFF+1 + 1939 2758 INST_MOUSE: + 1940 2758 20 CA 27 jsr FINDMOUSE ; find which slot the mouse is in + 1941 275B 90 01 bcc INMS1 ; everything is fine + 1942 275D 60 rts ; can't find the mouse + 1943 275E INMS1: + 1944 275E 8D 03 03 sta MFIX1 + 1945 2761 8D 0A 03 sta MFIX2 + 1946 2764 8D 11 03 sta MFIX3 ; okay, everyone knows now + 1947 2767 29 0F and #$0f ; pick up low byte + 1948 2769 85 63 sta ARG1+LO ; save for program to pick up + 1949 276B 0A asl A ; shift slot number to upper nybble + 1950 276C 0A asl A + 1951 276D 0A asl A + 1952 276E 0A asl A + 1953 276F 8D 0C 03 sta MFIX4 ; and save here + 1954 ; + 1955 ; now init mouse, please + 1956 ; + 1957 2772 A2 07 ldx #INITM ; init first + 1958 2774 20 00 03 jsr MOUSER ; so do it + 1959 2777 A2 00 ldx #SETM ; setup mouse + 1960 2779 A9 01 lda #$01 ; transparent mode + 1961 277B 20 00 03 jsr MOUSER ; we do that + 1962 277E A2 03 ldx #CLEARM ; and clear mouse pos + 1963 2780 20 00 03 jsr MOUSER ; we did + 1964 ; + 1965 ; now set min and max for clamping. + 1966 ; 0 <= xpos <= 139 + 1967 ; 0 <= ypos <= 191 + 1968 ; + 1969 2783 A9 00 lda #0 ; zero out a few of the things + 1970 2785 8D 78 05 sta CLMPMINH ; hi part of min clamp + 1971 2788 8D 78 04 sta CLMPMINL ; lo part of min clamp + 1972 278B A9 89 lda #<137 ; max X + 1973 278D 8D F8 04 sta CLMPMAXL ; stash in lo part + 1974 2790 A9 00 lda #>137 ; max X + 1975 2792 8D F8 05 sta CLMPMAXH ; hi part of clamp + 1976 2795 A9 00 lda #0 ; show setting X clamp + 1977 2797 A2 05 ldx #CLAMPM ; do clamping + 1978 2799 20 00 03 jsr MOUSER ; okay, we did + 1979 279C A9 BD lda #<189 ; now for Y + 1980 279E 8D F8 04 sta CLMPMAXL ; saved in lo part + 1981 27A1 A9 00 lda #>189 ; now for Y + 1982 27A3 8D F8 05 sta CLMPMAXH ; saved in lo part + Wed May 24 1989 15:00 Page 42 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 1983 27A6 A9 01 lda #1 ; set y boundries + 1984 27A8 A2 05 ldx #CLAMPM ; okay, show which routine + 1985 27AA 20 00 03 jsr MOUSER ; and do it + 1986 + 1987 ; + 1988 ; initialize the mouse position + 1989 ; + 1990 27AD A9 00 lda #0 ; clear MSB + 1991 27AF 8D 78 05 sta MOUSEXH + 1992 27B2 8D F8 05 sta MOUSEYH + 1993 27B5 A9 C0 lda #MAXHEIGHT + 1994 27B7 8D F8 04 sta MOUSEYL + 1995 27BA A9 8C lda #MAXWIDTH + 1996 27BC 8D 78 04 sta MOUSEXL + 1997 + 1998 27BF A2 04 ldx #POSM + 1999 27C1 20 00 03 jsr MOUSER ; and move it + 2000 + 2001 ; cli ; enable interrupts now + 2002 27C4 A9 FF lda #$FF ; < 0 show mouse + 2003 27C6 85 58 sta MOUSEF ; so show it + 2004 27C8 18 clc ; show everything is fine + 2005 27C9 60 rts ; done + 2006 ; + 2007 ; FINDMOUSE - scan the slots for a mouse + 2008 ; + 2009 27CA FINDMOUSE: + 2010 27CA AD FB C1 lda $C1FB ; check for mouse ID == D6 + 2011 27CD C9 D6 cmp #$D6 ; mouse ID + 2012 27CF D0 05 bne FNDM1 ; not it + 2013 27D1 AD CC 27 lda FINDMOUSE+2 ; get slot + 2014 27D4 18 clc ; show okay-ness + 2015 27D5 60 rts ; and return + 2016 27D6 FNDM1: + 2017 27D6 EE CC 27 inc FINDMOUSE+2 ; point to next slot + 2018 27D9 AD CC 27 lda FINDMOUSE+2 ; reached last one yet? + 2019 27DC C9 C8 cmp #$C8 ; no slot eight + 2020 27DE 90 EA bcc FINDMOUSE ; go look again + 2021 27E0 38 sec ; show no mouse + 2022 27E1 60 rts + 2023 ; + 2024 ; INST_STICK - install the joystick handler + 2025 27E2 INST_STICK: + 2026 27E2 A9 01 lda #$1 ; > 0 show joystick + 2027 27E4 85 58 sta MOUSEF ; okay, we do + 2028 27E6 18 clc ; show it worked + 2029 27E7 60 rts + 2030 27E8 RAMINFO: + 2031 27E8 0A db 10 ; 10 parms + 2032 27E9 FA27 dw RAMNAME ; name + 2033 27EB ds 15 ; room for stuff + 2034 27FA RAMNAME: + 2035 27FA 05 db 5 ; length of name + 2036 27FB 2F 52 41 4D 2F db "/RAM/" ; name + 2037 2800 0D 54 68 69 73 RAMQ: db EOL,"This program disables /RAM and it",EOL + 2805 20 70 72 6F 67 + 280A 72 61 6D 20 64 + Wed May 24 1989 15:00 Page 43 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 280F 69 73 61 62 6C + 2814 65 73 20 2F 52 + 2819 41 4D 20 61 6E + 281E 64 20 69 74 0D + 2038 2823 69 73 20 6E 6F db "is not empty. Do you want to" + 2828 74 20 65 6D 70 + 282D 74 79 2E 20 20 + 2832 44 6F 20 79 6F + 2837 75 20 77 61 6E + 283C 74 20 74 6F + 2039 2840 0D 63 6F 6E 74 db EOL,"continue (Y destroys /RAM)?" + 2845 69 6E 75 65 20 + 284A 28 59 20 64 65 + 284F 73 74 72 6F 79 + 2854 73 20 2F 52 41 + 2859 4D 29 3F + 2040 005C RAMQL EQU $-RAMQ + 2041 285C FIXRAM: + 2042 285C GET_FILE_INFO RAMINFO ; get the volumn size + 2043 285C PRODOS $C4, RAMINFO + 2044 285C 20 00 BF jsr $BF00 ; ProDOS handler + 2045 285F C4 DB $C4 ; ProDOS function code + 2046 2860 E827 DW RAMINFO ; Function Parameter Block address + 2047 2862 .MACEND + 2048 2862 .MACEND + 2049 2862 B0 28 bcs FIXR1 ; problem, so we'll just disable it + 2050 + 2051 2864 AD F1 27 lda RAMINFO+9 ; get amount used + 2052 2867 D0 07 bne ASKUSER ; some files there complain + 2053 2869 AD F0 27 lda RAMINFO+8 ; get LSB of used + 2054 286C C9 09 cmp #9 ; if >= 9, must be being used + 2055 286E 90 1C bcc FIXR1 ; no problem, disable /RAM + 2056 2870 ASKUSER: + 2057 2870 20 58 FC jsr MHOME ; clear and home + 2058 2873 DLINE RAMQ ; ask about continuing + 2059 2873 A2 00 ldx #RAMQ ; get other part of string + 2061 [01] IFMA 2 ; check to see if length passed in + 2062 ldy ; then just fetch it + 2063 [01] ELSE + 2064 2877 A0 5C ldy #RAMQL ; get length of string + 2065 [00] ENDIF + 2066 2879 20 D5 26 jsr DLINE ; print the string + 2067 287C .MACEND + 2068 287C 20 0C FD jsr MRDKEY ; get answer + 2069 287F 29 7F and #$7F ; turn off hi bit + 2070 2881 C9 79 cmp #'y' ; check for yes + 2071 2883 F0 07 beq FIXR1 ; then continue + 2072 2885 C9 59 cmp #'Y' ; also, captital Y + 2073 2887 F0 03 beq FIXR1 ; okay again + 2074 2889 4C 19 26 jmp ZQUIT ; so die + 2075 288C FIXR1: + 2076 288C AD 26 BF lda RAMVEC+LO ; get current /RAM vector + 2077 288F 8D 7E 07 sta OLDVEC+LO ; save it for reinstalling + 2078 2892 AD 27 BF lda RAMVEC+HI + 2079 2895 8D 7F 07 sta OLDVEC+HI + 2080 2898 AD 16 BF lda UNSVEC+LO ; point /RAM vector to uninstalled device + Wed May 24 1989 15:00 Page 44 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2081 289B 8D 26 BF sta RAMVEC+LO + 2082 289E AD 17 BF lda UNSVEC+HI + 2083 28A1 8D 27 BF sta RAMVEC+HI + 2084 28A4 AE 31 BF ldx DEVCNT ; get how many devices + 2085 28A7 DEVLP: + 2086 28A7 BD 32 BF lda DEVNUM,X ; try to find /RAM device + 2087 28AA 29 70 and #$70 ; isolate slot + 2088 28AC C9 30 cmp #$30 ; look for slot 3 + 2089 28AE F0 04 beq GOTSLT ; got it + 2090 28B0 CA dex ; missed it + 2091 28B1 10 F4 bpl DEVLP ; try again + 2092 28B3 60 rts ; didn't find it (?) + 2093 28B4 GOTSLT: + 2094 28B4 BD 33 BF lda DEVNUM+1,X ; now move all down one + 2095 28B7 9D 32 BF sta DEVNUM,X ; down one + 2096 28BA EC 31 BF cpx DEVCNT ; done yet + 2097 28BD F0 03 beq FIXREX ; ayyup + 2098 28BF E8 inx ; point to next slot + 2099 28C0 D0 F2 bne GOTSLT ; continue on + 2100 28C2 FIXREX: + 2101 28C2 CE 31 BF dec DEVCNT ; one less device, thank you + 2102 28C5 60 rts ; all done + 2103 ; + 2104 ; DO_DSEGS - scan through the disk segment table and point to the + 2105 ; beginning of the segment list for each of the disks in the + 2106 ; file. + 2107 28C6 DO_DSEGS: + 2108 28C6 AD 01 19 lda SEGTBL+SGTDISKS+1 ; get # number disks + 2109 28C9 85 7A sta J ; save in counter + 2110 28CB C6 7A dec J ; we hand hold #1 + 2111 28CD A9 19 lda #>(SEGTBL+SGTCHKS1) ; start off at beginning + 2112 28CF 8D D1 1D sta D1SEG+HI ; here is first one + 2113 28D2 A9 12 lda #<(SEGTBL+SGTCHKS1); and here is LSB + 2114 28D4 8D D0 1D sta D1SEG+LO ; save it + 2115 28D7 AC 17 19 ldy SEGTBL+SGTSEG1+1 ; get number of segs in first disk + 2116 28DA A2 02 ldx #2 ; start at second one + 2117 28DC DODSL: + 2118 28DC BD CE 1D lda DSKSEG-2+LO,X ; get LSB of previous start + 2119 28DF 18 clc ; doing some adding + 2120 28E0 69 08 adc #SGTSEG ; point to start of segment list + 2121 28E2 9D D0 1D sta DSKSEG+LO,X ; save in working segment pointer + 2122 28E5 BD CF 1D lda DSKSEG-2+HI,X ; now work on MSB + 2123 28E8 69 00 adc #0 ; pick up possible carry + 2124 28EA 9D D1 1D sta DSKSEG+HI,X ; and save in new pointer + 2125 28ED ADDLOOP: + 2126 28ED 18 clc ; doing add + 2127 28EE A9 06 lda #6 ; size of segment entry + 2128 28F0 7D D0 1D adc DSKSEG+LO,X ; counting + 2129 28F3 9D D0 1D sta DSKSEG+LO,X ; counting + 2130 28F6 90 03 bcc ADDL1 ; no wrap + 2131 28F8 FE D1 1D inc DSKSEG+HI,X ; add one to hi + 2132 28FB ADDL1: + 2133 28FB 88 dey ; count segment + 2134 28FC D0 EF bne ADDLOOP ; okay, not done yet + 2135 28FE BD D0 1D lda DSKSEG+LO,X ; get pointer to #segs in this one + 2136 2901 85 1E sta DSEGS+LO ; save ptr + 2137 2903 BD D1 1D lda DSKSEG+HI,X ; get MSB + Wed May 24 1989 15:00 Page 45 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2138 2906 85 1F sta DSEGS+HI ; save ptr + 2139 2908 A0 05 ldy #SGTNSEG+1 ; just need LSB + 2140 290A B1 1E lda (DSEGS),Y ; get #segs in this segment + 2141 290C A8 tay ; save in counter Y + 2142 290D E8 inx + 2143 290E E8 inx ; point to new pointer loc + 2144 290F C6 7A dec J ; count this disk + 2145 2911 D0 C9 bne DODSL ; and do it again + 2146 ; + 2147 ; now, init DSEGS to point to beginnning again + 2148 ; + 2149 2913 AD D1 1D lda D1SEG+HI ; here is first one + 2150 2916 85 1F sta DSEGS+HI + 2151 2918 AD D0 1D lda D1SEG+LO ; save it + 2152 291B 85 1E sta DSEGS+LO + 2153 ; + 2154 ; check to see if we are using infoDOS, and set pointer to second + 2155 ; disk segment table if we are. + 2156 ; + 2157 291D AD FF BF lda KVERSION ; get "version" number + 2158 2920 C9 FF cmp #INFODOS_ID ; is in our DOS? + 2159 2922 D0 0B bne DODX ; nope, it ain't + 2160 2924 AD D3 1D lda D2SEG+HI ; then have infoDOS flag to point + 2161 2927 85 5A sta INFODOS+HI ; to the D2SEG, cuz that's what + 2162 2929 AD D2 1D lda D2SEG+LO ; we use to check all the ZPC's + 2163 292C 85 59 sta INFODOS+LO + 2164 292E 60 rts + 2165 292F DODX: + 2166 292F A9 00 lda #0 ; regular ProDOS + 2167 2931 85 59 sta INFODOS ; show nothing there! + 2168 2933 60 rts + 2169 + 2170 ; + 2171 ; INITPAG - init the paging buffers, thank you + 2172 ; + 2173 2934 INITPAG: + 2174 2934 A2 17 LDX #NUMBUFS-1 ;*** + 2175 2936 86 CD STX CURRENT ; make last one first one to be used + 2176 2938 C6 CD dec CURRENT ; using only even pages + 2177 293A A9 FF LDA #$FF + 2178 293C INILP: + 2179 293C 9D 80 0C STA VPAGEH,X + 2180 293F CA DEX + 2181 2940 10 FA BPL INILP + 2182 2942 A2 00 LDX #0 + 2183 2944 A0 02 LDY #2 ;*** + 2184 2946 INILP2: + 2185 2946 98 TYA + 2186 2947 9D 40 0C STA PREVPNT,X + 2187 294A E8 INX + 2188 294B E8 inx ;*** + 2189 294C C8 INY + 2190 294D C8 iny ;*** + 2191 294E E0 18 CPX #NUMBUFS + 2192 2950 90 F4 BCC INILP2 + 2193 2952 A9 00 LDA #00 + 2194 2954 CA DEX + Wed May 24 1989 15:00 Page 46 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2195 2955 CA dex ;*** + 2196 2956 9D 40 0C STA PREVPNT,X + 2197 2959 A2 00 LDX #0 ;*** + 2198 295B A0 FE LDY #$FE ;*** + 2199 295D A9 16 LDA #NUMBUFS-2 ;*** + 2200 295F INILP3: + 2201 295F 9D 00 0C STA NEXTPNT,X + 2202 2962 E8 INX + 2203 2963 E8 inx ;*** + 2204 2964 C8 iny ;*** + 2205 2965 C8 INY + 2206 2966 98 TYA + 2207 2967 E0 18 CPX #NUMBUFS + 2208 2969 90 F4 BCC INILP3 + 2209 296B 60 rts + 2210 + 2211 ; + 2212 ; DO_PREFIX - check out the program name at $280. If there is a prefix + 2213 ; in there, just set prefix to it, so my default prefix is just fine. + 2214 ; + 2215 296C DO_PREFIX: + 2216 296C AE 80 02 ldx START_NAME ; get length of name + 2217 296F DOPLOOP: + 2218 296F BD 80 02 lda START_NAME,x ; get char + 2219 2972 29 7F and #$7F ; make it real ASCII + 2220 2974 C9 2F cmp #'/' ; directory seperator? + 2221 2976 F0 04 beq DOPLX ; yup, found the prefix + 2222 2978 CA dex ; previous char + 2223 2979 D0 F4 bne DOPLOOP ; go do it + 2224 297B 60 rts ; prefix is just fine as it is + 2225 297C DOPLX: + 2226 297C 8E 80 02 stx START_NAME ; just reuse the name + 2227 297F SET_PREFIX START_PREFIX ; and go set it to this one + 2228 297F PRODOS $C6, START_PREFIX + 2229 297F 20 00 BF jsr $BF00 ; ProDOS handler + 2230 2982 C6 DB $C6 ; ProDOS function code + 2231 2983 8629 DW START_PREFIX ; Function Parameter Block address + 2232 2985 .MACEND + 2233 2985 .MACEND + 2234 2985 60 rts + 2235 2986 START_PREFIX: + 2236 2986 01 DB 1 ; just one parm + 2237 2987 8002 DW START_NAME ; use my start up name + 2238 ; + 2239 ; INIT_CHARSET - move the default charset into lower memory + 2240 ; + 2241 2989 ICHARS: + 2242 2989 61 62 63 64 65 db "abcdefghijklmnopqrstuvwxyz" ; CHARSET 1 + 298E 66 67 68 69 6A + 2993 6B 6C 6D 6E 6F + 2998 70 71 72 73 74 + 299D 75 76 77 78 79 + 29A2 7A + 2243 29A3 41 42 43 44 45 db "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; CHARSET 2 + 29A8 46 47 48 49 4A + 29AD 4B 4C 4D 4E 4F + 29B2 50 51 52 53 54 + Wed May 24 1989 15:00 Page 47 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 29B7 55 56 57 58 59 + 29BC 5A + 2244 29BD 00 0D 30 31 32 db 0,EOL,"0123456789.,!?_#'""/\-:()" ; CHARSET 3 + 29C2 33 34 35 36 37 + 29C7 38 39 2E 2C 21 + 29CC 3F 5F 23 27 22 + 29D1 2F 5C 2D 3A 28 + 29D6 29 + 2245 004D ICHARSL EQU $-ICHARS-1 + 2246 + 2247 29D7 INIT_CHARSET: + 2248 29D7 AD 34 96 lda ZBEGIN+ZCHRSET ; see if game has passed one + 2249 29DA 0D 35 96 ora ZBEGIN+ZCHRSET+1 ; well? + 2250 29DD D0 0C bne INITCHG ; yes, so use that one + 2251 29DF A2 4D ldx #ICHARSL + 2252 29E1 INITCL: + 2253 29E1 BD 89 29 lda ICHARS,X ; get char + 2254 29E4 9D 8C 1F sta CHARSET,X ; save char + 2255 29E7 CA dex ; next char + 2256 29E8 10 F7 bpl INITCL ; go get it + 2257 29EA 60 rts + 2258 29EB INITCHG: + 2259 29EB AD 34 96 lda ZBEGIN+ZCHRSET ; get game page + 2260 29EE 20 ED 26 jsr SETPC ; find out where in memory it be + 2261 29F1 85 8D sta FPCH ; save page + 2262 29F3 84 8E sty FPCBNK ; and save the bank + 2263 29F5 AD 35 96 lda ZBEGIN+ZCHRSET+1 ; get the LSB + 2264 29F8 85 8C sta FPCL ; just save it + 2265 29FA A9 4E lda #78 ; 78 characters are in it + 2266 29FC 85 7A sta J ; use J as counter + 2267 29FE A9 00 lda #0 ; set up index + 2268 2A00 85 7C sta K ; in K + 2269 2A02 INCGL: + 2270 2A02 20 14 27 jsr FETCHB ; go get the character + 2271 2A05 A6 7C ldx K ; this is index + 2272 2A07 9D 8C 1F sta CHARSET,X ; save game character + 2273 2A0A 20 38 27 jsr NEXTFPC ; point to next character + 2274 2A0D E6 7C inc K ; point to next storage byte + 2275 2A0F C6 7A dec J ; count character + 2276 2A11 D0 EF bne INCGL ; go get next char + 2277 + 2278 2A13 A9 0D lda #EOL ; make sure EOL is in list + 2279 2A15 A2 35 ldx #53 ; offset of 53 + 2280 2A17 9D 8C 1F sta CHARSET,X ; and away it goes + 2281 + 2282 2A1A 60 rts ; done + 2283 2A1B + 2284 2A1B END + 2285 + 2286 + 2287 PAGE + Wed May 24 1989 15:00 Page 48 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT CODE SUBROUTINES ---" + + 2288 2A1B STTL "--- BOOT DATA STRUCTURES ---" + 2289 2A1B INTR_OPEN: + 2290 2A1B 03 DB 3 ; 3 parameters + 2291 2A1C 372A DW INTR_NAME ; name of file + 2292 2A1E 0011 DW GAME1FIO ; file data buffer + 2293 2A20 DS 1 ; refnum goes here + 2294 2A21 CLOSE_BLOCK: + 2295 2A21 01 DB 1 ; 1 parameter + 2296 2A22 DS 2 ; room for ref num + 2297 2A24 PSEEK: + 2298 2A24 02 db 2 ; 2 pararmeters + 2299 2A25 00 db 0 ; refnum + 2300 2A26 00 00 00 db 0,0,0 ; 3 byte new file pos + 2301 2A29 PRELOAD_OPEN: + 2302 2A29 03 DB 3 + 2303 2A2A 3F2A DW PRELOAD_NAME + 2304 2A2C 0011 DW GAME1FIO ; close interpreter first! + 2305 2A2E DS 1 ; refnum here + 2306 ; + 2307 ; start with interpreter data + 2308 ; + 2309 2A2F READ_BLOCK: + 2310 2A2F 04 DB 4 ; 4 parms + 2311 2A30 00 DB 0 ; refnum + 2312 2A31 0040 DW INTR_BEGIN ; where to start the interpreter + 2313 2A33 0056 DW INTR_SIZE ; and how big could it be + 2314 2A35 0000 DW 0 ; actual length of interpreter + 2315 2A37 INTR_NAME: + 2316 2A37 07 DB INAME_LEN ; length of name + 2317 2A38 I_NAME: + 2318 2A38 49 4E 46 4F 43 DB "INFOCOM" ; interpreter name + 2A3D 4F 4D + 2319 0007 INAME_LEN EQU $-I_NAME + 2320 + 2321 2A3F PRELOAD_NAME: + 2322 2A3F 00 DB 0 ; length of name + 2323 2A40 PRE_NAME: + 2324 2A40 DS 20 ; spot for preload name + 2325 0014 PRELEN EQU $-PRE_NAME + 2326 2A54 + 2327 DH_SAVE: ; to actual 'write' the data + 2328 2A54 04 DB 4 ; 4 parms for write + 2329 2A55 00 DB 0 ; refnum goes here + 2330 2A56 0000 DW 0 ; just 'copy' junk + 2331 2A58 00B5 DW RAMSAVE ; to preserve this much mem in AUX + 2332 2A5A 0000 DW 0 ; how much is done + 2333 2A5C + 2334 2A5C 54 68 65 20 73 STRYM: DB "The story is loading ..." + 2A61 74 6F 72 79 20 + 2A66 69 73 20 6C 6F + 2A6B 61 64 69 6E 67 + 2A70 20 2E 2E 2E + 2335 0018 STRYML EQU $-STRYM + 2336 2A74 0D 45 6E 74 65 MMSG: DB EOL,"Enter the letter of the pointing",EOL + 2A79 72 20 74 68 65 + 2A7E 20 6C 65 74 74 + 2A83 65 72 20 6F 66 + Wed May 24 1989 15:00 Page 49 + + "APPLE YZIP (c)Infocom, Inc.. --- BOOT.SYSTEM" + "--- BOOT DATA STRUCTURES ---" + + 2A88 20 74 68 65 20 + 2A8D 70 6F 69 6E 74 + 2A92 69 6E 67 0D + 2337 2A96 64 65 76 69 63 DB "device you will be using:",EOL + 2A9B 65 20 79 6F 75 + 2AA0 20 77 69 6C 6C + 2AA5 20 62 65 20 75 + 2AAA 73 69 6E 67 3A + 2AAF 0D + 2338 2AB0 4A 29 6F 79 73 DB "J)oystick M)ouse N)either",EOL,EOL + 2AB5 74 69 63 6B 20 + 2ABA 20 4D 29 6F 75 + 2ABF 73 65 20 20 4E + 2AC4 29 65 69 74 68 + 2AC9 65 72 0D 0D + 2339 0059 MMSGL EQU $-MMSG + 2340 2ACD 0D 45 6E 74 65 MSLT: DB EOL,"Enter the slot number in which the",EOL + 2AD2 72 20 74 68 65 + 2AD7 20 73 6C 6F 74 + 2ADC 20 6E 75 6D 62 + 2AE1 65 72 20 69 6E + 2AE6 20 77 68 69 63 + 2AEB 68 20 74 68 65 + 2AF0 0D + 2341 2AF1 6D 6F 75 73 65 db "mouse card is installed >" + 2AF6 20 63 61 72 64 + 2AFB 20 69 73 20 69 + 2B00 6E 73 74 61 6C + 2B05 6C 65 64 20 3E + 2342 003D MSLTL EQU $-MSLT + 2343 2B0A 0D 53 6C 6F 74 MSLTBAD: DB EOL,"Slot number must be between",EOL + 2B0F 20 6E 75 6D 62 + 2B14 65 72 20 6D 75 + 2B19 73 74 20 62 65 + 2B1E 20 62 65 74 77 + 2B23 65 65 6E 0D + 2344 2B27 4F 4E 45 20 61 db "ONE and SEVEN! Try again!",EOL + 2B2C 6E 64 20 53 45 + 2B31 56 45 4E 21 20 + 2B36 20 54 72 79 20 + 2B3B 61 67 61 69 6E + 2B40 21 0D + 2345 0038 MSLTBADL EQU $-MSLTBAD + 2346 2B42 0D 56 65 72 73 VERMSG: db EOL,"Version: " + 2B47 69 6F 6E 3A 20 + 2347 000A VERMSGL equ $-VERMSG + 2348 2B4C END + + + + Lines Assembled : 2348 Assembly Errors : 0 + + + \ No newline at end of file diff --git a/apple/yzip/rel.9/brel.asm b/apple/yzip/rel.9/brel.asm new file mode 100644 index 0000000..37052c2 --- /dev/null +++ b/apple/yzip/rel.9/brel.asm @@ -0,0 +1,203 @@ + STTL "--- RELOCATED SUBROUTINES ---" + PAGE + +; +; FETCHB - use FPC to get a byte in either aux or main mem +; +FETCHBx: + sta RDBNK,Y ; set bank, lower + ldy #0 ; gotta use Y + lda (FPC),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; and return +; +; ZFETCH - fetch byte at (ZPCPNT),Y - offset from (ZPCPNT) +; +ZFETCHx: + sta RDBNK,X ; set lower bank + lda (ZPCPNT),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; bye +; +; MFETCH - fetch byte at (MPCPNT),Y - offset from (MPCPNT) +; +MFETCHx: + sta RDBNK,X ; set bank + lda (MPCPNT),Y ; so go get it + sta RDBNK ; go back to main bank + rts ; bye +; +; SAVE_DATA - copy data from [DBUFF] to IOBUFF +; [Y] must == 0; [X] == DSKBNK; [A] == IOBUFF ($8 or $9) +; + sta RDBNK,X ; and select that bank for reading + sta SAVE_DATA+9 ; show which part of iobuff +SDAT1: + lda (DBUFF),Y ; get me that byte +SDAT2: + sta IOBUFF,Y ; MODIFIED ABOVE + iny + bne SDAT1 + sta RDBNK+MAIN ; and back to main + rts +RLCLEN EQU $-FETCHBx-1 ; mark length +; +; COPY_LINE: +; SPC - source pointer +; FPC - destination pointer +; SPCBNK - bank the above two are talking about +; CPY_COUNT - end-start bytes to move +; STMASK - mask to use on first byte (0 if none) +; ENDMASK - mask to use for end byte (0 if none) +; +; MODIFIED CODE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +; The definitions for CPY_MODs are HARD CODED in apple.equ - they MUST +; match the definitions below for similar xCPY_MODs!!!!!!!! +; DON'T CHANGE WITHOUT FIXING THOSE OFFSETS IN APPLE.EQU!!!!! +; +CPYx EQU * + ldx SPCBNK ; set up banks for first byte + lda PAGE2SW,X ; r/w which bank in display mem + ldy #0 ; use Y reg + lda STMASK ; get start mask + beq CPLOOP ; no start mask, start in middle of loop + and (FPC),Y ; turn off changing bits, keep good bits + sta (FPC),Y ; save it + lda STMASK ; get changing bits + eor #$FF ; turn on changing bits + and (SPC),Y ; get SPC byte + ora (FPC),Y ; turn them on in destination too + sta (FPC),Y ; and destiny +CPLOOP: + lda CPY_COUNT ; get count + lsr A ; /2 for number in this bank + tax ; put in X for indexing + beq CPLP2 ; then done! + dex ; zero base the number + lda STMASK ; special start? + beq CPL1 ; nope + inc CPY_MOD1_SRC ; first one already done + inc CPY_MOD1_DST ; point to next one + dex ; and count first one as done +CPL1: + lda SCREEN,X ; get byte + sta SCREEN,X ; store byte + dex ; count down + bpl CPL1 ; and do it all again +CPLP2: + ldy #0 ; reset y + lda SPCBNK ; get current bank + eor #1 ; toggle to point to the other one + tax + lda PAGE2SW,X + txa ; which bank? + beq CPLP21 ; we are now in main, things are fine + inc CPY_MOD2_SRC ; start one more if now in AUX + inc CPY_MOD2_DST + dex ; and count as done +CPLP21: + lda CPY_COUNT ; get count again + lsr A ; /2 for bytes in this bank + tax ; put in X for counter + beq CPDONE ; nothing here + dex ; zero base the number +CPL2: + lda SCREEN,X ; get byte + sta SCREEN,X ; store byte + dex ; count byte + bpl CPL2 ; and swing by again +CPDONE: + lda ENDMASK ; do same mucking as when starting + beq CPEXIT ; no mucking + pha ; save endmask + lda CPY_COUNT ; get how many bytes being copied + lsr A ; /2 + bcs CPDONE1 ; if odd, then we are pointing to correct + pha ; save a + ldx SPCBNK ; get original bank + lda PAGE2SW,X ; and point to it + pla ; get it back +CPDONE1: + tay ; get offset + pla ; get end mask back + eor #$FF ; turn on all off bits + and (FPC),Y ; turn off changing bits + sta (FPC),Y ; save it + lda (SPC),Y ; get source byte + and ENDMASK ; turn on changing bits + ora (FPC),Y ; turn them on in destination too + sta (FPC),Y ; and destiny +CPEXIT: + lda PAGE2SW ; set back to main mem + rts +CPYLEN EQU $-CPYx-1 +xCPY_MOD1 equ (CPL1-CPYx+1) +xCPY_MOD1_DST equ xCPY_MOD1+3 +xCPY_MOD2 equ (CPL2-CPYx+1) +xCPY_MOD2_DST equ xCPY_MOD2+3 +PAGE3REL: +; +; MOUSER - this vectors the call to the correct place +; +MOUSERx: + pha ; save A for a sec +MSX1: lda MTABLE,X ; get lo part of address + sta MSVECTOR+LO ; save lo part of address + pla ; get A back + nop +MSX2: ldx #$C4 ; might be changed, depending on slot +MSX3: ldy #$40 ; hopefully, this doesn't + jmp (MSVECTOR) ; and away we go +MSRxLEN EQU $-MOUSERx-1 ; show how long this is +MSVECTORx: + ds 1 ; where lo part of vector goes +MSX4: db $C4 ; slot where mouse is +MSRLEN EQU $-MOUSERx-1 ; length or routine +; +; colors for screen lines +; + RADIX H +COLORSx: + db 00,00,00,00 ; black + db 08,11,22,44 ; magenta + db 44,08,11,22 ; brown + db 4C,19,33,66 ; orange + db 22,44,08,11 ; dark green + db 2A,55,2A,55 ; gray 1 + db 66,4C,19,33 ; green + db 6E,5D,3B,77 ; yellow + db 11,22,44,08 ; dark blue + db 19,33,66,4C ; purple + db 55,2A,55,2A ; gray 2 + db 5D,3B,77,6E ; pink + db 33,66,4C,19 ; medium blue + db 3B,77,6E,5D ; light blue + db 77,6E,5D,3B ; aqua + db 7F,7F,7F,7F ; white +XPOSTBLx: + DB 0 + DB 0,1,1,2,2,3,4 + DB 4,5,5,6,6,7,8 + DB 8,9,9,0a,0a,0b,0c + DB 0c,0d,0d,0e,0e,0f,10 + DB 10,11,11,12,12,13,14 + DB 14,15,15,16,16,17,18 + DB 18,19,19,1a,1a,1b,1c + DB 1c,1d,1d,1e,1e,1f,20 + DB 20,21,21,22,22,23,24 + DB 24,25,25,26,26,27,28 + DB 28,29,29,2a,2a,2b,2c + DB 2c,2d,2d,2e,2e,2f,30 + DB 30,31,31,32,32,33,34 + DB 34,35,35,36,36,37,38 + DB 38,39,39,3a,3a,3b,3c + DB 3c,3d,3d,3e,3e,3f,40 + DB 40,41,41,42,42,43,44 + DB 44,45,45,46,46,47,48 + DB 48,49,49,4a,4a,4b,4c + DB 4c,4d,4d,4e,4e,4f,50 + RADIX D +PAGE3RELL EQU $-PAGE3REL-1 + END + + diff --git a/apple/yzip/rel.9/bsubs.asm b/apple/yzip/rel.9/bsubs.asm new file mode 100644 index 0000000..8dd9d7e --- /dev/null +++ b/apple/yzip/rel.9/bsubs.asm @@ -0,0 +1,584 @@ + PAGE + STTL "--- BOOT CODE SUBROUTINES ---" + +ERRM: DB EOL,EOL + DB "Internal error " +ENUMB: DB "00" + DB "00. " +ERRML EQU $-ERRM +HCHARS: DB "0123456789ABCDEF" +; +; ZERROR: print out error code in HexWord: [A][Y]. +; +ZERROR: + pha ; save [A] + tya ; and put y to a for figgering + ldy #3 ; CONVERT ERROR BYTE IN [A] +ZERR0: + pha + and #%00001111 + tax + lda HCHARS,X + sta ENUMB,Y + pla + LSR A + LSR A + lsr A + lsr A + tax + lda HCHARS,X + dey + sta ENUMB,Y + beq ZR1 ; done + + pla ; done with first number + dey ; and point one more down + jmp ZERR0 ; so work on second number +ZR1: + ldx #ERRM + ldy #ERRML + jsr DLINE ; PRINT ERROR MESSAGE + jsr GETRET ; wait for + jmp ZQUIT + +RETQ: db EOL,"Please insert new disk to boot." + db EOL, "And hit RETURN when ready.",EOL +RETQL EQU $-RETQ +GETRET: + DLINE RETQ ; ask for return +GETRETL: + lda KBD ; get a key + bpl GETRETL ; no key + and #$7f ; make a good key + cmp #EOL ; return key? + bne GETRETL ; nope + jsr MCOUT ; show the + rts + + + ; ---- + ; QUIT + ; ---- + +ZQUIT: + lda INFODOS ; in dinky-dos? + beq ZQUIT2 ; nope + lda #0 ; clear power up byte + sta $3F4 ; make it do cold boot + lda RESET_VECTOR+HI ; now, set up where to die to + sta ZQUITR1+2 + lda RESET_VECTOR+LO + sta ZQUITR1+1 + lda RDROM ; get ROM back +ZQUITR1: + jmp RESET_VECTOR ; just reset things +; +; re-enable /RAM +; +ZQUIT2: + ldx DEVCNT ; put device in at end + inx ; point to one past end + stx DEVCNT ; show new count + lda #$BF ; /RAM ID + sta DEVNUM,X ; save it + lda OLDVEC+HI ; restore old vector + sta RAMVEC+HI + lda OLDVEC+LO + sta RAMVEC+LO +; +; now format /RAM +; + lda #3 ; stash into FORMAT parm block + sta $42 ; it goes here, oddly enough + lda #$B0 ; device id for /RAM + sta $43 ; and here it goes + lda #>GAME1FIO ; IO buffer + sta $45 ; this is where it goes + lda #ZBEGIN ; ADD OFFSET TO GET RAM PAGE + ldy #MAIN ; in the main bank + beq VFEXI ; BRA to fetch +VF2: + cmp #PGBEGIN ; is it paged? + bcs VFERR ; yes it be paged, so can't deal with it + cmp #P3PAGE ; is it in Aux Mem, Part 2? + bcs VF3 ; yes, so subtract different amount +; +; this is in lower aux +; + lda #(Z2PAGE-Z1SIZE) ; subtract size from offset + ldy #AUX ; show aux mem + bne VFEXI ; jump to end +VF3: + lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides + ldy #P3BANK ; show page 3 bank +VFEXI: + clc ; get ready for addition + adc MEMPAGE ; now get actual offset + rts +VFERR: +; +; out of range +; + lda #$22 + jmp ZERROR + +; +; FETCHB - fetch a byte from either main memory, aux memory, or upper +; Aux memory +; +FETCHB: + ldy FPCBNK ; get the bank + bmi FB1 ; must be in upper RAM + jmp ZERO_FB ; go to low end fetch +; +; this is in aux mem, >$E000 +; +FB1: + lda FPCH ; get which page + sta FBMOD+2 ; and show in operand + ldy FPCL ; get which byte + sta ALTZP+AUX ; talk about aux mem + lda BNK1SET ; set up read/write ram in upper mem + lda BNK1SET ; set up read/write ram in upper mem +FBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + ldx RDROM ; now use ROM please + ldx RDROM ; now use ROM please + rts +; +; NEXTFPC - inc DPCL and check for wrapping round to next bank +; +NEXTFPC: + inc FPCL ; next lo byte + bne NXFP_EXIT ; no change then + inc FPCH ; next page + lda FPCH ; and get it for checking + cmp #>PRGLBL ; have we reached end of line? + bne NXFP_EXIT ; we be okay + lda FPCBNK ; get bank + bne NXFP1 ; must skip over stuff in middle + inc FPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta FPCH ; and point to it + rts ; toots finis +NXFP1: + lda #Z3PAGE ; start of part 3 + sta FPCH ; so show me + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey +NXFP_EXIT: + rts +; +; INST_MOUSE - install mouse handler IRQ +; +MFIX1 EQU (MSX1-MOUSERx)+PAGE3STUFF+2 +MFIX2 EQU (MSX2-MOUSERx)+PAGE3STUFF+1 +MFIX3 EQU (MSX4-MOUSERx)+PAGE3STUFF +MFIX4 EQU (MSX3-MOUSERx)+PAGE3STUFF+1 +INST_MOUSE: + jsr FINDMOUSE ; find which slot the mouse is in + bcc INMS1 ; everything is fine + rts ; can't find the mouse +INMS1: + sta MFIX1 + sta MFIX2 + sta MFIX3 ; okay, everyone knows now + and #$0f ; pick up low byte + sta ARG1+LO ; save for program to pick up + asl A ; shift slot number to upper nybble + asl A + asl A + asl A + sta MFIX4 ; and save here +; +; now init mouse, please +; + ldx #INITM ; init first + jsr MOUSER ; so do it + ldx #SETM ; setup mouse + lda #$01 ; transparent mode + jsr MOUSER ; we do that + ldx #CLEARM ; and clear mouse pos + jsr MOUSER ; we did +; +; now set min and max for clamping. +; 0 <= xpos <= 139 +; 0 <= ypos <= 191 +; + lda #0 ; zero out a few of the things + sta CLMPMINH ; hi part of min clamp + sta CLMPMINL ; lo part of min clamp + lda #<137 ; max X + sta CLMPMAXL ; stash in lo part + lda #>137 ; max X + sta CLMPMAXH ; hi part of clamp + lda #0 ; show setting X clamp + ldx #CLAMPM ; do clamping + jsr MOUSER ; okay, we did + lda #<189 ; now for Y + sta CLMPMAXL ; saved in lo part + lda #>189 ; now for Y + sta CLMPMAXH ; saved in lo part + lda #1 ; set y boundries + ldx #CLAMPM ; okay, show which routine + jsr MOUSER ; and do it + +; +; initialize the mouse position +; + lda #0 ; clear MSB + sta MOUSEXH + sta MOUSEYH + lda #MAXHEIGHT + sta MOUSEYL + lda #MAXWIDTH + sta MOUSEXL + + ldx #POSM + jsr MOUSER ; and move it + +; cli ; enable interrupts now + lda #$FF ; < 0 show mouse + sta MOUSEF ; so show it + clc ; show everything is fine + rts ; done +; +; FINDMOUSE - scan the slots for a mouse +; +FINDMOUSE: + lda $C1FB ; check for mouse ID == D6 + cmp #$D6 ; mouse ID + bne FNDM1 ; not it + lda FINDMOUSE+2 ; get slot + clc ; show okay-ness + rts ; and return +FNDM1: + inc FINDMOUSE+2 ; point to next slot + lda FINDMOUSE+2 ; reached last one yet? + cmp #$C8 ; no slot eight + bcc FINDMOUSE ; go look again + sec ; show no mouse + rts +; +; INST_STICK - install the joystick handler +INST_STICK: + lda #$1 ; > 0 show joystick + sta MOUSEF ; okay, we do + clc ; show it worked + rts +RAMINFO: + db 10 ; 10 parms + dw RAMNAME ; name + ds 15 ; room for stuff +RAMNAME: + db 5 ; length of name + db "/RAM/" ; name +RAMQ: db EOL,"This program disables /RAM and it",EOL + db "is not empty. Do you want to" + db EOL,"continue (Y destroys /RAM)?" +RAMQL EQU $-RAMQ +FIXRAM: + GET_FILE_INFO RAMINFO ; get the volumn size + bcs FIXR1 ; problem, so we'll just disable it + + lda RAMINFO+9 ; get amount used + bne ASKUSER ; some files there complain + lda RAMINFO+8 ; get LSB of used + cmp #9 ; if >= 9, must be being used + bcc FIXR1 ; no problem, disable /RAM +ASKUSER: + jsr MHOME ; clear and home + DLINE RAMQ ; ask about continuing + jsr MRDKEY ; get answer + and #$7F ; turn off hi bit + cmp #'y' ; check for yes + beq FIXR1 ; then continue + cmp #'Y' ; also, captital Y + beq FIXR1 ; okay again + jmp ZQUIT ; so die +FIXR1: + lda RAMVEC+LO ; get current /RAM vector + sta OLDVEC+LO ; save it for reinstalling + lda RAMVEC+HI + sta OLDVEC+HI + lda UNSVEC+LO ; point /RAM vector to uninstalled device + sta RAMVEC+LO + lda UNSVEC+HI + sta RAMVEC+HI + ldx DEVCNT ; get how many devices +DEVLP: + lda DEVNUM,X ; try to find /RAM device + and #$70 ; isolate slot + cmp #$30 ; look for slot 3 + beq GOTSLT ; got it + dex ; missed it + bpl DEVLP ; try again + rts ; didn't find it (?) +GOTSLT: + lda DEVNUM+1,X ; now move all down one + sta DEVNUM,X ; down one + cpx DEVCNT ; done yet + beq FIXREX ; ayyup + inx ; point to next slot + bne GOTSLT ; continue on +FIXREX: + dec DEVCNT ; one less device, thank you + rts ; all done +; +; DO_DSEGS - scan through the disk segment table and point to the +; beginning of the segment list for each of the disks in the +; file. +DO_DSEGS: + lda SEGTBL+SGTDISKS+1 ; get # number disks + sta J ; save in counter + dec J ; we hand hold #1 + lda #>(SEGTBL+SGTCHKS1) ; start off at beginning + sta D1SEG+HI ; here is first one + lda #<(SEGTBL+SGTCHKS1); and here is LSB + sta D1SEG+LO ; save it + ldy SEGTBL+SGTSEG1+1 ; get number of segs in first disk + ldx #2 ; start at second one +DODSL: + lda DSKSEG-2+LO,X ; get LSB of previous start + clc ; doing some adding + adc #SGTSEG ; point to start of segment list + sta DSKSEG+LO,X ; save in working segment pointer + lda DSKSEG-2+HI,X ; now work on MSB + adc #0 ; pick up possible carry + sta DSKSEG+HI,X ; and save in new pointer +ADDLOOP: + clc ; doing add + lda #6 ; size of segment entry + adc DSKSEG+LO,X ; counting + sta DSKSEG+LO,X ; counting + bcc ADDL1 ; no wrap + inc DSKSEG+HI,X ; add one to hi +ADDL1: + dey ; count segment + bne ADDLOOP ; okay, not done yet + lda DSKSEG+LO,X ; get pointer to #segs in this one + sta DSEGS+LO ; save ptr + lda DSKSEG+HI,X ; get MSB + sta DSEGS+HI ; save ptr + ldy #SGTNSEG+1 ; just need LSB + lda (DSEGS),Y ; get #segs in this segment + tay ; save in counter Y + inx + inx ; point to new pointer loc + dec J ; count this disk + bne DODSL ; and do it again +; +; now, init DSEGS to point to beginnning again +; + lda D1SEG+HI ; here is first one + sta DSEGS+HI + lda D1SEG+LO ; save it + sta DSEGS+LO +; +; check to see if we are using infoDOS, and set pointer to second +; disk segment table if we are. +; + lda KVERSION ; get "version" number + cmp #INFODOS_ID ; is in our DOS? + bne DODX ; nope, it ain't + lda D2SEG+HI ; then have infoDOS flag to point + sta INFODOS+HI ; to the D2SEG, cuz that's what + lda D2SEG+LO ; we use to check all the ZPC's + sta INFODOS+LO + rts +DODX: + lda #0 ; regular ProDOS + sta INFODOS ; show nothing there! + rts + +; +; INITPAG - init the paging buffers, thank you +; +INITPAG: + LDX #NUMBUFS-1 ;*** + STX CURRENT ; make last one first one to be used + dec CURRENT ; using only even pages + LDA #$FF +INILP: + STA VPAGEH,X + DEX + BPL INILP + LDX #0 + LDY #2 ;*** +INILP2: + TYA + STA PREVPNT,X + INX + inx ;*** + INY + iny ;*** + CPX #NUMBUFS + BCC INILP2 + LDA #00 + DEX + dex ;*** + STA PREVPNT,X + LDX #0 ;*** + LDY #$FE ;*** + LDA #NUMBUFS-2 ;*** +INILP3: + STA NEXTPNT,X + INX + inx ;*** + iny ;*** + INY + TYA + CPX #NUMBUFS + BCC INILP3 + rts + +; +; DO_PREFIX - check out the program name at $280. If there is a prefix +; in there, just set prefix to it, so my default prefix is just fine. +; +DO_PREFIX: + ldx START_NAME ; get length of name +DOPLOOP: + lda START_NAME,x ; get char + and #$7F ; make it real ASCII + cmp #'/' ; directory seperator? + beq DOPLX ; yup, found the prefix + dex ; previous char + bne DOPLOOP ; go do it + rts ; prefix is just fine as it is +DOPLX: + stx START_NAME ; just reuse the name + SET_PREFIX START_PREFIX ; and go set it to this one + rts +START_PREFIX: + DB 1 ; just one parm + DW START_NAME ; use my start up name +; +; INIT_CHARSET - move the default charset into lower memory +; +ICHARS: + db "abcdefghijklmnopqrstuvwxyz" ; CHARSET 1 + db "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; CHARSET 2 + db 0,EOL,"0123456789.,!?_#'""/\-:()" ; CHARSET 3 +ICHARSL EQU $-ICHARS-1 + +INIT_CHARSET: + lda ZBEGIN+ZCHRSET ; see if game has passed one + ora ZBEGIN+ZCHRSET+1 ; well? + bne INITCHG ; yes, so use that one + ldx #ICHARSL +INITCL: + lda ICHARS,X ; get char + sta CHARSET,X ; save char + dex ; next char + bpl INITCL ; go get it + rts +INITCHG: + lda ZBEGIN+ZCHRSET ; get game page + jsr SETPC ; find out where in memory it be + sta FPCH ; save page + sty FPCBNK ; and save the bank + lda ZBEGIN+ZCHRSET+1 ; get the LSB + sta FPCL ; just save it + lda #78 ; 78 characters are in it + sta J ; use J as counter + lda #0 ; set up index + sta K ; in K +INCGL: + jsr FETCHB ; go get the character + ldx K ; this is index + sta CHARSET,X ; save game character + jsr NEXTFPC ; point to next character + inc K ; point to next storage byte + dec J ; count character + bne INCGL ; go get next char + + lda #EOL ; make sure EOL is in list + ldx #53 ; offset of 53 + sta CHARSET,X ; and away it goes + + rts ; done + + END + diff --git a/apple/yzip/rel.9/bugger.asm b/apple/yzip/rel.9/bugger.asm new file mode 100644 index 0000000..bde7b6e --- /dev/null +++ b/apple/yzip/rel.9/bugger.asm @@ -0,0 +1,257 @@ + PAGE + SBTTL "--- DEBUGGER: APPLE ---" + + ; -------------- + ; APPLE DEBUGGER + ; -------------- + + ; ENTRY: BREAKPOINT ID IN [A] + + ; SMALL DEBUGGER DBG1 (CONVERTS) DBG2 (JUST DISPLAYS) [A] + +DLCNT: DB 0 + +DBG1: + INC DLCNT + BNE DBG1m + PHA + JSR GETKEY + PLA +DBG1m: + PHA + LSR A + LSR A + LSR A + LSR A + JSR NIB1 + PLA + +NIB1: AND #%00001111 + TAY + LDA HCHARS,Y + JSR MCOUT + RTS + +DBG2: +; CMP #' ' +; BEQ DBG3 +; JSR MCOUT +; LDA #' ' +DBG3: JSR MCOUT + RTS + +HCHARS: DB "0123456789ABCDEF" + + END + +BLINE: DB "B: OP: PC: S: V: 1: 2: 3: 4: 5: 6: 7: 8: 9: " + DB EOL +BLINL EQU $-BLINE + +BUGLIN EQU LSTLNE + +DOBUG: LDX KBD ; WAS CTRL-S PRESSED? + CPX #$13 + BNE DO1 + RTS ; YES, SO LEAVE + +DO1: CMP #0 + BEQ BUGIT + RTS + + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + +BUGIT: LDX #2 ; INIT "CURSOR" + 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 BLINE,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 [ZSP] + LDA ZSP + JSR HEX + + LDX #29 ; CURSOR FOR [MPC] + LDA MPCH + JSR HEX + LDA MPCM + JSR HEX + LDA MPCL + JSR HEX + + LDX #38 + LDA BONE + JSR HEX + + LDX #43 + LDA BTWO + JSR HEX + + LDX #48 + LDA BTHREE + JSR HEX + + LDX #53 + LDA BFOUR + JSR HEX + + LDX #58 + LDA BFIVE + JSR HEX + + LDX #63 + LDA BSIX + JSR HEX + + LDX #68 + LDA BSEVEN + JSR HEX + + LDX #73 + LDA BEIGHT + JSR HEX + + LDX #78 + LDA BNINE + JSR HEX + +; TO SEND TO PRINTER IF WANTED +; LDA CSW+LO +; PHA +; LDA CSW+HI +; PHA +; LDA EH +; PHA +; LDA ALTCSW+LO +; STA CSW+LO +; LDA ALTCSW+HI +; STA CSW+HI +; +; LDA PSTAT +; BNE PPP +; +; LDA #$C1 +; STA CSW+HI +; LDA #$00 +; STA CSW+LO +; +; LDA #$89 +; JSR MCOUT +; LDA CSW+HI +; STA ALTCSW+HI +; LDA CSW+LO +; STA ALTCSW+LO +; LDA #$B8 +; JSR MCOUT +; LDA #$B0 +; JSR MCOUT +; LDA #$CE +; JSR MCOUT +; LDA #$8D +; JSR MCOUT + +PPP: LDX #2 +DBUG1: LDA BLINE,X ; PRINT DEBUGGER TEXT +; JSR MCOUT + JSR CHAR + INX + CPX #BLINL + BCC DBUG1 + +; PLA +; STA EH +; PLA +; STA CSW+HI +; PLA +; STA CSW+LO + +; BIT KBD +; BPL LETEX ; NO KEY PRESSED + + BIT ANYKEY ; CLEAR IT +BUGWAT: BIT KBD ; WAIT FOR A KEY + BPL BUGWAT + + LDA KBD + CMP #$8D + BNE LETEX + BRK + +LETEX: BIT ANYKEY ; CLEAR FOR NEXT ONE + 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 + ORA #%10000000 + STA BLINE,X + INX + RTS + +HCHARS: DB "0123456789ABCDEF" + +BONE: DB 0 +BTWO: DB 0 +BTHREE: DB 0 +BFOUR: DB 0 +BFIVE: DB 0 +BSIX: DB 0 +BSEVEN: DB 0 +BEIGHT: DB 0 +BNINE: DB 0 + + END + + \ No newline at end of file diff --git a/apple/yzip/rel.9/dispatch.asm b/apple/yzip/rel.9/dispatch.asm new file mode 100644 index 0000000..17f2bcc --- /dev/null +++ b/apple/yzip/rel.9/dispatch.asm @@ -0,0 +1,281 @@ + PAGE + STTL "--- OPCODE DISPATCH TABLES ---" + + + ; 0-OPS + +OPT0H: DB >ZRTRUE ;B0 + DB >ZRFALS ;B1 + DB >ZPRI ;B2 + DB >ZPRR ;B3 + DB >ZNOOP ;B4 + DB >OSAVE ;B5 + DB >OREST ;B6 + DB >ZSTART ;B7 + DB >ZRSTAK ;B8 + DB >ZCATCH ;B9 + DB >ZQUIT ;BA + DB >ZZCRLF ;BB + DB >ZUSL ;BC + DB >ZVER ;BD + DB >ZEXTOP ;BE + DB >ZORIG ;BF + +OPT0L: DB ZZERO ;80,90,A0 + DB >ZNEXT ;81 + DB >ZFIRST ;82 + DB >ZLOC ;83 + DB >ZPTSIZ ;84 + DB >ZINC ;85 + DB >ZDEC ;86 + DB >ZPRB ;87 + DB >ZCALL1 ;88 (EZIP) + DB >ZREMOV ;89 + DB >ZPRD ;8A + DB >ZRET ;8B + DB >ZJUMP ;8C + DB >ZPRINT ;8D + DB >ZVALUE ;8E + DB >ZICLL1 ;8F + +OPT1L: DB BADOP2 ;00 (UNDEFINED) + DB >ZEQUAL ;01 + DB >ZLESS ;02 + DB >ZGRTR ;03 + DB >ZDLESS ;04 + DB >ZIGRTR ;05 + DB >ZIN ;06 + DB >ZBTST ;07 + DB >ZBOR ;08 + DB >ZBAND ;09 + DB >ZFSETP ;0A + DB >ZFSET ;0B + DB >ZFCLR ;0C + DB >ZSET ;0D + DB >ZMOVE ;0E + DB >ZGET ;0F + DB >ZGETB ;10 + DB >ZGETP ;11 + DB >ZGETPT ;12 + DB >ZNEXTP ;13 + DB >ZADD ;14 + DB >ZSUB ;15 + DB >ZMUL ;16 + DB >ZDIV ;17 + DB >ZMOD ;18 + DB >ZCALL2 ;19 (EZIP) + DB >ZICLL2 ;1A + DB >ZCOLOR ;1B + DB >ZTHROW ;1C + DB >BADOP2 ;1D + DB >BADOP2 ;1E + DB >BADOP2 ;1F + +OPT2L: DB ZCALL ;E0 + DB >ZPUT ;E1 + DB >ZPUTB ;E2 + DB >ZPUTP ;E3 + DB >ZREAD ;E4 + DB >ZPRC ;E5 + DB >ZPRN ;E6 + DB >ZRAND ;E7 + DB >ZPUSH ;E8 + DB >ZPOP ;E9 + DB >ZSPLIT ;EA + DB >ZSCRN ;EB + + ; (EZIPS FROM HERE ON) + DB >ZXCALL ;EC + DB >ZCLR ;ED + DB >ZERASE ;EE + DB >ZCURST ;EF + DB >ZCURGT ;F0 + DB >ZLIGHT ;F1 + DB >ZBUFOUT ;F2 + DB >ZDIRT ;F3 + DB >ZDIRIN ;F4 (NOT IMPLEMENTED) + DB >ZSOUND ;F5 + DB >ZINPUT ;F6 + DB >ZINTBL ;F7 + DB >ZBCOM ;F8 + DB >ZICALL ;F9 + DB >ZIXCLL ;FA + DB >ZLEX ;FB + DB >ZWSTR ;FC + DB >ZCOPYT ;FD + DB >ZPRNTT ;FE + DB >ZASSND ;FF + +OPTXL: DB ZSAVE ;100 + DB >ZREST ;101 + DB >ZSHIFT ;102 + DB >ZASHFT ;103 + DB >ZFONT ;104 + DB >ZDISPL ;105 + DB >ZPICNF ;106 + DB >ZDCLR ;107 + DB >ZMARG ;108 + DB >ZISAVE ;109 + DB >ZIREST ;10A + DB >BADEXT ;10B - NOT USED + DB >BADEXT ;10C - NOT USED + DB >BADEXT ;10D - NOT USED + DB >BADEXT ;10E - NOT USED + DB >BADEXT ;10F - NOT USED + DB >ZWINPOS ;110 + DB >ZWINSIZE ;111 + DB >ZWINATTR ;112 + DB >ZWINGET ;113 + DB >ZSCROLL ;114 + DB >ZFSTACK ;115 + DB >ZMINFO ;116 + DB >ZMLIMIT ;117 + DB >ZXPUSH ;118 + DB >ZWINPUT ;119 + DB >ZPRINTF ;11A + DB >ZMENU ;11B + DB >ZPICSET ;11c + +EXTLEN EQU $-EXTOPH + +EXTOPL: DB + lda INFODOS ; in dinky-dos? + beq ZQUIT2 ; nope + lda #0 ; clear power up byte + sta $3F4 ; make it do cold boot + lda RESET_VECTOR+HI ; now, set up where to die to + sta ZQUITR1+2 + lda RESET_VECTOR+LO + sta ZQUITR1+1 + lda RDROM ; get ROM back +ZQUITR1: + jmp RESET_VECTOR ; just reset things +; +; re-enable /RAM +; +ZQUIT2: + ldx DEVCNT ; put device in at end + inx ; point to one past end + stx DEVCNT ; show new count + lda #$BF ; /RAM ID + sta DEVNUM,X ; save it + lda OLDVEC+HI ; restore old vector + sta RAMVEC+HI + lda OLDVEC+LO + sta RAMVEC+LO +; +; now format /RAM +; + lda #3 ; stash into FORMAT parm block + sta $42 ; it goes here, oddly enough + lda #$B0 ; device id for /RAM + sta $43 ; and here it goes + lda #>GAME1FIO ; IO buffer + sta $45 ; this is where it goes + lda #BOOTNAME + sta OPEN_FILE+OP_PATHNAME+HI + lda #'1' ; set disk name to disk #1 + sta SAVENUM ; show open_gamef + jsr OPEN_GAMEF ; okay + + lda OPEN_FILE+OP_REFNUM ; get ref num + sta BOOT_RD+RD_REFNUM ; save ref num + sta CLOSE_PB+CL_REFNUM + READ BOOT_RD ; read in boot system + bcc ZSTRTX ; okay, everything is fine + jmp DISK_FATAL ; die otherwise +ZSTRTX: + CLOSE CLOSE_PB ; and close it up + jmp BORG ; and go to it + + ; -------------------------------- + ; RETURN RANDOM BYTES IN [A] & [X] + ; -------------------------------- +RANDOM: + inc RAND+HI + dec RAND+LO + lda RAND+LO ; get LSB + adc RAND+HI ; add MSB + and #$7F ; don't let it go into $C0 page + sta RAND+HI ; new MSB + tay ; get random offset + lda (RAND),Y ; get random number + tax ; save in X + adc RAND+LO ; and go to another spot + and #$7F ; don't go above $80 + sta RAND+HI ; okay + tay ; more randomness + lda (RAND),Y ; and get it again + ora RAND+HI ; set more bits + rts + + + ; ------------------- + ; Z-PRINT A CHARACTER + ; ------------------- + ; ENTRY: ASCII CHAR IN [A] + ; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, + ; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN + ; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME + ; (DIROUT CHANGES 6/24/85) + +COUT: + sta IOCHAR ; HOLD IT A SEC + ldx TABLEF ; OUTPUT TO TABLE? + beq COUT1 ; NO + ldx FMTTBL ; formatted table? + bne COUT5 ; yes, so just do it normal + jmp TBLOUT ; just put into table +COUT1: + ldx SCREENF ; OUTPUT TO SCREEN? + bne COUT5 ; YES + ldx SCRIPTF ; OUTPUT TO PRINTER? + bne COUT5 ; YES + rts ; NO, SO DONE +COUT5: + lda IOCHAR ; RETRIEVE CHAR + bmi COUT2 ; highlight chars have no width +; +; this is an entry point for DLINE, so it doesn't check any of the above +; things. Enter with character in [A] +; +DIRECT_OUT: + cmp #EOL ; IF ASCII EOL, just handle it special + bne COUT0 + + jmp ZCRLF ; DO IT +COUT0: + bcs COUT02 ; not control character + cmp #EOS ; control-k (end of sentence)? + beq COUT01 ; yes, so put out 2 spaces + cmp #TAB ; tab char? + bne CEX ; ignore all other control chars +; +; this means do a couple of spaces +; + lda #SPACE ; do 3 spaces for start of line + jsr COUT ; a little recursion never hurt! + ldx CHRCNT ; back to beginning of line? + bne COUT01 ; nope +COUT010: + rts ; don't do any to start line +COUT01: + lda #SPACE ; 2 more spaces + jsr COUT + ldx CHRCNT ; back to zero? + beq COUT010 ; yes, so don't add to start of line + + lda #SPACE ; last one + jmp COUT ; finally +COUT02: + tax ; use char as index + lda FONTFLG ; get which font we be using + beq COUTF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne COUTF2 ; okay, now do add +COUTF1: + lda CHWID,X ; get width of char +COUTF2: + clc ; get ready for add + adc LENGTH+LO ; ADD LINE LENGTH COUNTER + sta LENGTH+LO ; update length + bcc COUT0C ; no wrap + inc LENGTH+HI ; okay, wrap then +COUT0C: + lda LENGTH+HI ; get MSB + cmp XSIZE+HI ; check MSB first + bcc COUT2 ; no need to check lsb + bne COUT00 ; XSIZE < LENGTH? + + lda LENGTH+LO ; check LSB + cmp XSIZE+LO ; END OF SCREEN LINE? + bcc COUT2 ; haven't reached the end if XSIZE > LENGTH +COUT00: + ldy WRPFLG ; are we wrapping + beq CEX ; no, so truncate + ldx CHRCNT ; get character count + lda IOCHAR ; get the character + sta LBUFF,X ; save current char in buffer + jmp FLUSH ; YES, FLUSH THE LINE +COUT2: + ldx CHRCNT ; GET LINE POINTER + lda IOCHAR ; get char back + sta LBUFF,X ; ADD CHAR TO BUFFER + inc CHRCNT ; and point to next CHRCNT +CEX: + rts + + ; --------------- + ; OUTPUT TO TABLE + ; --------------- +; +; this one just puts a char into the table +; +TBLOUT: + tax ; HOLD CHAR A SEC. +; +; figger out length of line in there +; + lda FONTFLG ; get which font we be using + beq TBLOUT1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne TBLOUT2 ; okay, now do add +TBLOUT1: + lda CHWID,X ; get width of char +TBLOUT2: + clc ; add width + adc ZBEGIN+ZTWIDTH+1 ; to current line width + sta ZBEGIN+ZTWIDTH+1 ; save current width + bcc TBLOUT3 ; no wrap + inc ZBEGIN+ZTWIDTH+0 ; wrap, then dammit +TBLOUT3: +; +; PUT BYTE IN TABLE AT CURRENT OFFSET +; + lda DIRITM+LO ; ADD IN OFFSET + clc + adc DIRTBL+LO + sta SPCL ; and make it lo part + lda DIRITM+HI + adc DIRTBL+HI + jsr SETPC ; set the PC + sta SPCH ; and this is high part + sty SPCBNK ; and the bank + txa ; PICK UP ASCII CHAR + jsr STASHB ; and save it +; +; SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER +; + inc DIRITM+LO ; INC OFFSET TO NEXT BYTE + bne TBLRTS + inc DIRITM+HI +TBLRTS: + rts +; +; PUT LBUFF IN TABLE AT CURRENT OFFSET +; +TBLRTN: + lda DIRITM+LO ; get where we are + clc + adc DIRTBL+LO ; ADD IN OFFSET + sta SPCL ; and make it lo part + sta FPCL ; save for later usage + lda DIRITM+HI ; get hi part + adc DIRTBL+HI + jsr SETPC ; set the PC + sta SPCH ; and this is high part + sta FPCH ; saving + sty SPCBNK ; and the bank + sty FPCBNK ; and here too + lda #0 ; start counter off at zero + sta J ; use J + sta K+HI ; this will be line length + sta K+LO ; both parts, please + jsr NEXTSPC ; point past the counter +TBLOOP: + ldy J ; get offset + lda LBUFF,Y ; get char + tax ; save char + bmi TBLP1 ; don't count hi light chars + cmp #SPACE ; see if less than a space + bcc TBLP1 ; no width if <$20 + tax ; use char as index + + lda FONTFLG ; get which font we be using + beq TBLF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne TBLF2 ; okay, now do add +TBLF1: + lda CHWID,X ; get width of char +TBLF2: + clc ; add width + adc K+LO ; to current line width + sta K+LO ; save current width + bcc TBLP1 ; no wrap + inc K+HI ; wrap, then dammit +TBLP1: + txa ; get char back + jsr STASHB ; and save it + jsr NEXTSPC ; next table entry + inc J ; point to next char + dec CHRCNT ; decrement counter + bne TBLOOP ; get next one +; +; now fill with necessary spaces +; + lda FONTFLG ; first, set up width to be added + beq TBLSPF1 ; must be variable width font + lda #MONOFONT_W ; get mono width + bne TBLSPF2 ; okay +TBLSPF1: + ldx #SPACE ; get space index + lda CHWID,X ; okay +TBLSPF2: + sta ARG8 ; use temporarily +TBLSP: + lda K+LO ; get how big line is + clc ; add in space + adc ARG8 ; pick up space width + sta K+LO ; saved + bcc TBLSP1 ; no wrap? + inc K+HI ; yes, wrapping +TBLSP1: + lda XSIZE+HI ; check against end + cmp K+HI ; compare against max width + bcc TBLSPX ; all done then + bne TBLSP2 ; no need to check if <> + lda XSIZE+LO ; check LSB + cmp K+LO ; well? + bcc TBLSPX ; all done then +TBLSP2: + lda #SPACE ; get it + jsr STASHB ; save it + jsr NEXTSPC ; point to next one + inc J ; count it + bne TBLSP ; and continue +TBLSPX: + lda #0 ; show end of table + sta LENGTH+LO ; clear out line length too + sta LENGTH+HI ; and hi part too + jsr STASHB ; marked with a zero + jsr FP2SP ; have SPC point to beginning + lda J ; get how many chars are there + jsr STASHB ; save at beginning of line + inc J ; count counter in offset + lda J ; get J back + clc ; add in where we were + adc DIRITM+LO ; okay with lo part + sta DIRITM+LO ; save it + lda DIRITM+HI ; and now the hi part + adc #0 ; pick up carry, maybe + sta DIRITM+HI ; and save it + rts + + ; ------------------- + ; FLUSH OUTPUT BUFFER + ; ------------------- + ; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: + lda #SPACE ; SPACE CHAR + stx OLDEND ; SAVE CURRENT END OF LINE +FL0: + cmp LBUFF,X ; FIND LAST SPACE CHAR + beq FL1 ; IN THE LINE + dex + bne FL0 ; IF NONE FOUND, + ldx CHRCNT ; FLUSH ENTIRE LINE + dex ; minus last one +FL1: + stx OLDLEN ; SAVE OLD LINE POS HERE + stx CHRCNT ; MAKE IT THE NEW LINE LENGTH + + lda TABLEF ; are we doing table I/O? + beq FL11 ; nope + jsr TBLRTN ; YES, DO IT + jmp FL12 ; so refill line +FL11: + jsr ZCRLF ; PRINT LINE UP TO LAST SPACE +; +; START NEW LINE WITH REMAINDER OF OLD +; +FL12: + ldx OLDLEN ; GET OLD LINE POS + ldy #0 ; START NEW LINE AT BEGINNING +FL2: + inx + cpx OLDEND ; CONTINUE IF + bcc FL3 ; INSIDE of end of line + beq FL3 ; or at end of line + sty CHRCNT + rts +FL3: + lda LBUFF,X ; GET CHAR FROM OLD LINE + cmp #SPACE ; don't move start spaces in either + beq FL4 ; fine, I won't + sta LBUFF,Y ; MOVE TO START OF NEW LINE + bmi FL4 ; don't count hi light chars + cmp #SPACE ; don't count control chars + bcc FL4 ; okay + txa ; save current x + pha ; saved + lda FONTFLG ; get which font we be using + beq FLSF1 ; must be variable width + lda #MONOFONT_W ; get width then of mono font + bne FLSF2 ; okay, now do add +FLSF1: + lda LBUFF,X ; get char back + tax ; make index + lda CHWID,X ; get width of char +FLSF2: + clc ; get ready for add + adc LENGTH+LO ; okay, now add char width + sta LENGTH+LO ; save new length + pla ; get old X back + tax ; okay + bcc FL4 ; no wrap + inc LENGTH+HI +FL4: + iny ; UPDATE # OF chars in NEW LINE + bne FL2 ; (ALWAYS) + + + ; --------------- + ; CARRIAGE RETURN + ; --------------- + +ZZCRLF: + ldx TABLEF ; OUTPUT TO TABLE? + beq ZCRLF ; NO +; +; if putting a into table, just add to line buffer and flush +; + lda #EOL ; get carriage return char + ldy CHRCNT ; add to lbuff + sta LBUFF,Y ; got it + inc CHRCNT ; now flush it + jsr TBLRTN ; YES, DO IT (TBL ONLY) + jmp ZCRLFX ; git out +ZCRLF: + ldx CHRCNT ; how far have we gone + lda #EOL ; get carriage return char + sta LBUFF,X ; END OF CURRENT LINE + inc CHRCNT ; UPDATE LINE LENGTH + jsr LINOUT ; DISPLAY LINE + +; +; now check about line count +; + lda #0 + sta CHRCNT ; AND RESET LINE COUNT + sta LENGTH+LO ; okay + sta LENGTH+HI ; okay + + jsr CHKFNC ; CHECK FOR CR FUNCTION (XZIP) + + lda SCREENF ; CHECK IF DISPLAYING TO SCREEN + beq ZCRLFX ; NO, GO HANDLE IF PRINTING + lda SCRLFLG ; is it a scrolling window? + beq ZCRLFX ; nope, so no more + inc LINCNT ; NEW LINE GOING OUT + + ldx LINCNT ; IS IT TIME TO + cpx MAXLINES ; PRINT "MORE" YET? + bcc ZCRLFX ; NO, CONTINUE + + lda #1 ; leave one line from last screen, and input line + sta LINCNT ; RESET LINE COUNTER + lda LEFTMRG ; SET LEFT MARGIN + sta SCRCX + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay +; +; print [MORE] out myself, to avoid re-entrancy problems +; + lda SCRIPTF ; make sure we don't script + pha + ldx #0 ; start with first char + stx SCRIPTF ; clear script flag + stx SCLLINES ; use this as a counter +MORELOOP: + lda MORE,X ; get char + sta IOCHAR ; save it + jsr DIRECT_OUT ; pump it out there + inc SCLLINES ; count char + ldx SCLLINES ; how many have we done + cpx #MOREL ; done? + bne MORELOOP ; nope + + jsr CLRBUF ; make sure it shows +WAIT: + jsr GETKEY ; wait for key please + lda #MOREL-1 ; how many backspaces + sta LENGTH ; just use this as counter +WM11: + ldx LENGTH ; which char? + lda MORE,X ; get char + tax ; put here for erase + lda #BACKSPACE ; erase char + jsr CHAR + dec LENGTH ; count it + bpl WM11 + pla ; get script flag back + sta SCRIPTF ; fine + lda LEFTMRG ; move back to left margin + sta SCRCX ; okay + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay +ZCRLFX: + lda #0 + sta CHRCNT ; AND RESET LINE COUNT + sta LENGTH+LO ; okay + sta LENGTH+HI + rts +LINOUT: + ldy CHRCNT ; IF BUFFER EMPTY, + beq LINEX ; DON'T PRINT ANYTHING + sty PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + lda SCREENF ; DISPLAY TO SCREEN? + beq LOUT1 ; NO, GO CHECK IF PRINT + ldx #0 ; SEND CONTENTS OF [LBUFF] +LOUT: + lda LBUFF,X ; TO SCREEN + jsr CHAR + inx + dey + bne LOUT + jsr DISP_LINE ; make sure line gets printed +LOUT1: JSR PPRINT ; PRINT [LBUFF] IF ENABLED +LINEX: + rts ; AND RETURN +; +; CHECK IF THERE IS A PENDING FUNCTION CALL ASSOCIATED WITH 'S +; +CHKFNC: + ldy #WINCRC+HI ; get function offset + lda (WINDOW),Y ; IF NULL IGNORE + dey ; point to lo part + ora (WINDOW),Y + beq CHKOUT + + lda CRLF_CHECK ; do we really want to do this? + beq CHKOUT ; nope + + lda (WINDOW),Y ; DECR COUNTER + sec + sbc #1 + sta (WINDOW),Y + iny + lda (WINDOW),Y ; work on hi part + sbc #0 ; pick up carry + sta (WINDOW),Y ; save it + dey + ora (WINDOW),Y ; if NULL NOW, CALL FCN + bne CHKOUT + + ldy #WINCRF+LO ; pointing to routine + lda (WINDOW),Y ; get lo part + sta J+LO ; and save in J + iny ; point to hi part + lda (WINDOW),Y ; got it + sta J+HI + jsr INTCLL ; DO FUNCTION CALL +CHKOUT: + rts + + + ; ---------------------- + ; UPDATE THE STATUS LINE + ; ---------------------- + ; NOT APPLICABLE IN EZIP. + +ZUSL: RTS + +; ------ +; BUFOUT +; ------ +; ENTER: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE +; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO +; +; shouldn't need this in YZIP ?! +; +ZBUFOUT: +; +; CLEAR OUTPUT BUFFER BEFORE DOING ANYTHING FANCY +; +CLRBUF: + jsr LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) + ldx #0 + stx CHRCNT + rts + + ; ------ + ; DIROUT + ; ------ + ; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT + ; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT + ; MULTIPLE DEVICE USAGE IS POSSIBLE. + +SAVEXSIZE: db 0,0 ; for formatted table saving + +ZDIRT: + jsr CLRBUF ; send out anything there now! + + ldx ARG1+LO + bmi DIRRES ; NEGATIVE VALUE, DESELECTING + dex + beq DIR1 ; 1 = SET OUTPUT TO SCREEN + dex + beq DIR2 ; 2 = SCRIPTING + dex + beq DIR3 ; 3 = TABLE + rts ; INVALID VALUE +DIRRES: + inx + beq DRES1 ; -1 = RESET TO SCREEN + inx + beq DRES2 + inx + beq DRES3 + rts ; INVALID VALUE, JUST LEAVE +DIR1: + jsr CLRBUF + lda #1 ; turn screen on + sta SCREENF + rts +DRES1: + jsr CLRBUF + lda #0 + sta SCREENF ; 0, TURN SCREEN OFF + rts +DIR2: + inx + stx SCRIPTF ; SET SCRIPT FLAG ON + lda ZBEGIN+ZFLAGS+1 ; SET GAME FLAG ALSO + ora #%00000001 + sta ZBEGIN+ZFLAGS+1 + lda PSTAT ; CHECK IF PRINTER ALREADY INIT'D + bne DIR2A + jsr PCHK ; NO, GO DO IT +DIR2A: + rts ; YES, READY TO LEAVE +DRES2: + stx SCRIPTF ; TURN PRINTER OFF + lda ZBEGIN+ZFLAGS+1 ; AND TURN OFF GAME FLAG TOO + and #%11111110 + sta ZBEGIN+ZFLAGS+1 + rts +DIR3: + stx SCREENF ; turn off screen + inx + stx TABLEF ; TURN TABLE OUTPUT FLAG ON + jmp START_TABLE ; and set things up +DRES3: + lda TABLEF ; IF OFF ALREADY + beq OUT3 ; LEAVE AS IS + + stx TABLEF ; TURN TBL OUTPUT OFF + inx ; turn screen back on + stx SCREENF ; screen back on + + lda #3 ; add three to make it wrap + clc ; ready for add + adc ZBEGIN+ZTWIDTH+1 ; do it + sta ZBEGIN+ZTWIDTH+1 + bcc DRESCC ; no wrap into MSB + inc ZBEGIN+ZTWIDTH +DRESCC: + lsr ZBEGIN+ZTWIDTH+0 ; /4 to get # of pixels + ror ZBEGIN+ZTWIDTH+1 + lsr ZBEGIN+ZTWIDTH+0 + ror ZBEGIN+ZTWIDTH+1 + + + lda FMTTBL ; did we do a formatted table? + bne DRESFT ; yes, so fix things +; +; now put count into table +; + lda DIRTBL+LO ; and put count into second byte of table + sta SPCL ; points to low par + lda DIRTBL+HI ; get page + jsr SETPC ; okay, page and bank + sta SPCH + sty SPCBNK + lda DIRITM+LO ; (2 LESS THAN [DIRITM]) + sec + sbc #2 + sta DIRITM+LO ; save this new count + bcs RESET0 + dec DIRITM+HI ; wrapped downwards +RESET0: + lda DIRITM+HI ; get hi part + jsr STASHB ; saved that count + jsr NEXTSPC ; and point to lo part + lda DIRITM+LO ; and get lo part + jsr STASHB ; and save it + rts ; done +DRESFT: + lda CHRCNT ; anything in buffer? + beq DRES31 ; nope + jsr TBLRTN ; then fill out last line +DRES31: + lda SAVEXSIZE+LO ; get old xsize back + sta XSIZE+LO ; restored + lda SAVEXSIZE+HI + sta XSIZE+HI + lda #0 ; reset this flag too + sta FMTTBL ; cleared +OUT3: + rts +; +; set things up for doing table output +; +START_TABLE: + + lda ARG2+HI ; SET UP TBL + sta DIRTBL+HI + lda ARG2+LO ; TO STORE CHARS IN + sta DIRTBL+LO + lda #2 + sta DIRITM+LO + lda #0 + sta DIRITM+HI + sta ZBEGIN+ZTWIDTH+1 ; clear width count + sta ZBEGIN+ZTWIDTH+0 +; +; check to see if we have formatted table +; + lda NARGS ; get # of arguments + cmp #3 ; if == 3, then we wrap it + beq DIR30 ; nope + rts ; all done other wise +DIR30: + stx FMTTBL ; set formatted table flag + lda XSIZE+LO ; save the current XSIZE + sta SAVEXSIZE+LO ; okay, did it + lda XSIZE+HI ; and MSB + sta SAVEXSIZE+HI ; okay + lda ARG3+LO ; this is the actual amount + ldx ARG3+HI ; get interesting arg + bmi DIRFT1 ; check for negative width + jsr SETWJ ; get the window offset + ldy #WINXSZ ; get its XSIZE + lda (J),Y ; got it + sta XSIZE+LO ; aren't we nice + bne DIR31 ; jump to end +DIRFT1: + eor #$FF ; turn to a positive number + sta XSIZE+LO ; save it + inc XSIZE+LO ; to make it right +DIR31: + lda #0 ; items starts at zero + sta DIRITM+LO ; okay + sta XSIZE+HI ; clear out highness + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + rts + + ; ------ + ; CURSET + ; ------ + ; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW + ; AND AT COLUMN (ARG2) in (optional) window ARG3 + +ZCURST: + jsr CLRBUF ; CLEAR OUT ANY NON DISPLAYED TEXT 1ST + lda ARG1+LO ; see if < 0 + cmp #$FF ; -1 == turn off cursor + bne ZCURS00 ; nope + lda #1 ; show cursor off + bne ZCURSTXX ; go do it and return +ZCURS00: + cmp #$FE ; -2 == turn cursor on + bne ZCURS0 ; nope, just deal with normally + lda #0 ; show cursor not off +ZCURSTXX: + sta CURSOR_OFF ; show current cursor state + rts +ZCURS0: + dec ARG1+LO ; zero base both args + dec ARG2+LO ; thanx + + lda NARGS ; check for id + cmp #3 ; if 3 args, then window ID specified + beq ZCURS1 ; not 3, so use current window + + lda CURWIN ; show current window being done + sta ARG3+LO ; thanx +ZCURS1: + lda ARG3+LO ; get window ID + jsr SETWJ ; put address into J + lda ARG1+LO ; GET LINE + ldy #WINHGHT ; check against height + cmp (J),Y ; too far? + bcc ZCURS3 ; no, so use it + lda (J),Y ; got max out + tay ; but one too far + dey ; all better now + tya ; back to A +ZCURS3: + clc ; get ready for add + ldy #WINTOP ; do y pos first + adc (J),Y ; add in top to get absolute value + ldy #WINY ; get y pos offset + sta (J),Y ; save here + lda ARG2+LO ; GET COLUMN + ldy #WINWID ; check against width + cmp (J),Y ; is it to for right (like Reagan?) + bcc ZCURS4 ; nope, must be dukakis + lda (J),Y ; get max + tay ; for going down one + dey ; done it + tya ; back to A for usefullness +ZCURS4: + ldy #WINLEFT ; get left edge to absolute it + adc (J),Y ; carry clear from above + ldy #WINX ; this is the x pos + sta (J),Y ; into the structure +; +; now check for current window again, move cursor anyway +; + jmp GET_CURSOR ; get cursor pos from WINDOW + + ; ------ + ; CURGET + ; ------ + +ZCURGT: + jsr CLRBUF ; flush the buffer + + jsr SAVE_CURSOR ; save the current position + + dec NARGS ; see how many arguments + beq ZCURG1 ; use main window + lda ARG2+LO ; get window id + bpl ZCURG2 ; and figger it out +ZCURG1: + lda CURWIN ; use current window +ZCURG2: + jsr SETWJ ; make J point to right place + + lda ARG1+HI ; get table address + jsr SETPC ; get real address in memory + sty SPCBNK ; set bank + sta SPCH ; and page + lda ARG1+LO ; get table offset + sta SPCL ; and save it + + lda #0 ; zero hi part of Y pos + jsr STASHB ; and save it + jsr NEXTSPC ; and point to next one + jsr FETCHCY ; Fetch Y pos + jsr STASHB ; and save it + jsr NEXTSPC +; +; now for the X pos + lda #0 ; zero top byte of x pos + jsr STASHB + jsr NEXTSPC + jsr FETCHCX ; and now the X pos, and return + jmp STASHB ; and stash it away + +; +; FETCHCY - get the relativized Y pos into [A] +; J points to window structure +FETCHCY: + ldy #WINY ; get Y pos of window's cursor + lda (J),Y ; got it + ldy #WINTOP ; need to de-absolute it + sec ; get ready for sub + sbc (J),Y ; get relative pos + tax ; for 1 basing it + inx ; 1 align it + txa ; and put for save + rts +; +; FETCHCX - get relativized X pos into [A] +; J points to window structure +FETCHCX: + ldy #WINX ; get X pos of cursor + lda (J),Y ; got it + ldy #WINLEFT ; relativize it + sec ; get ready for sub + sbc (J),Y ; subtract left edge + tax ; for incing + inx ; 1 ALIGN IT + txa + rts + + ; ----- + ; DIRIN + ; ----- + ; NOT YET IMPLEMENTED, BUT RESERVED + +ZDIRIN: RTS + +; +; SETWJ - set up J to point to window structure for window ID in [A] +; +SETWJ: + tay ; check for -3 (current window) + bpl SWJ1 ; nope, window ID here + lda CURWIN ; -3 means current window +SWJ1: + asl A ; shift to make word index + tay ; and now make index + lda WINTABLE,Y ; get lo part of window struct address + sta J+LO ; and save it + lda WINTABLE+1,Y ; here's the hi part + sta J+HI ; prove it + rts + + ; ----- + ; ERASE + ; ----- + +ZERASE: + lda ARG1+LO + cmp #1 + bne ZEROUT ; not clreol + + jsr CLRBUF + jmp CLREOL ; CLEAR TO END OF LINE +ZEROUT: + sta CLSWIDTH ; this many pixels wide + lda #FONT_H ; pixels of font_height + sta CLSHEIGHT + lda SCRCX ; start at current cursor pos + sta CLSLEFT + lda SCRCY + sta CLSTOP + jmp CLS ; and do it + +; ----- +; CLEAR the current window +; ----- +SAVEXY: dw 0 + +ZCLR: + jsr CLRBUF ; flush the current buffer + jsr SAVE_CURSOR ; save the cursor pos + + lda ARG1+LO ; CHECK WHAT TO DO + bpl CLRW ; a particular window + cmp #$FD ; -3 means current window + beq CLRW ; so just handle it regular + cmp #$FE ; clear with nothing social + beq CLRCLS ; just clear the screen +; +; UNSPLIT SCREEN & CLEAR IT +; + lda #0 ; just use SPLIT 0 + sta ARG1+LO ; as if called normally + jsr ZSPLIT ; do the split +; +; just clear the entire screen +; +CLRCLS: + lda #0 ; clear the entire screen + sta CLSLEFT ; from top left + sta CLSTOP + lda #MAXWIDTH ; to bottom right + sta CLSWIDTH + lda #MAXHEIGHT + sta CLSHEIGHT + + jsr CLS ; do the clear screen (no cursor movement) + lda ARG1+LO ; check for -2 + bmi ZCLRX ; it is, don't move cursor + bpl ZCLEARX ; move cursor +CLRW: + jsr SETWJ ; get me the window pointer + ldy #WINTOP ; step thro to get data + lda (J),Y ; TOP + sta CLSTOP ; save for clear + iny ; point to left + lda (J),Y ; get it + sta CLSLEFT ; tell CLS + iny ; now at WINHGHT + lda (J),Y ; got it + sta CLSHEIGHT ; save for clear + iny ; now at WINWID + lda (J),Y ; get height + sta CLSWIDTH ; saved + jsr CLS ; screen cleared +; +; now move the cursor to 1,1, if not == -2 +; +ZCLEARX: + lda ARG1+LO ; check arg + jsr SETWJ ; make sure J still points to window + ldy #WINTOP ; put at top left of window + lda (J),Y ; get top + ldy #WINY ; and make it the y pos + sta (J),Y ; of the cursor + ldy #WINLEFT ; and the left is + lda (J),Y ; the + clc ; add in the left margin + ldy #WINLM ; here's the left margin + adc (J),Y ; added it + ldy #WINX ; x pos of the + sta (J),Y ; cursor + lda #0 ; and clear out line count + ldy #WINLCNT ; line count + sta (J),Y ; okay + ldy #WINLLEN ; and length of current line + sta (J),Y ; okay + iny ; do hi + sta (J),Y ; okay +ZCLRX: + jmp GET_CURSOR ; restore the cursor pos for the current window + +; ------ +; PRINTT +; ------ +; PRINT A TABLE TO SCREEN, ARG1 = # OF BYTES +; ARG2 = WIDTH, ARG3 (DEF = 1) = HEIGHT + +OLDCHZ EQU I+LO ; EASIER TO READ +OLDEHZ EQU I+HI +OLDCVT EQU L+LO + +TBL_LEN DW 0 ; save for length + +ZPRNTT: +; +; make sure the buffer is empty, thanks +; + jsr CLRBUF + + lda ARG1+LO ; USE GETBYT AS TBL COULD + sta MPCL ; BE ANYWHERE + lda ARG1+HI + sta MPCM + lda #0 + sta MPCH + jsr VLDMPC + + lda ARG2+LO ; ONLY A BYTE AS MAX + beq PTTDUN ; QUIT NOW IF NULL + + sta TBLWIDTH ; width of the table + sta TBLCNT ; start counter off at width + dec NARGS ; count down to 1 (maybe) + lda NARGS + cmp #1 + beq NOHIGHT ; DEFAULT HEIGHT IS 1 + lda ARG3+LO ; get passed height +NOHIGHT: + sta TBLHEIGHT ; height of the table (at least 1) + lda SCRCX + sta OLDEHZ + sec ; subtract left margin to get how long line is + sbc LEFTMRG ; okay we did that + sta TBL_LEN+LO ; this is how big line is too + lda #0 ; clear MSB + asl TBL_LEN+LO ; *2 + rol A + asl TBL_LEN+LO ; *4 + rol A + sta TBL_LEN+HI ; save +PTTLP: + jsr GETBYT ; GET A BYTE + jsr COUT ; and send it out + + dec TBLCNT ; one more byte done + bne PTTLP + dec TBLHEIGHT ; IF DONE ALL LINES + beq PTTDUN ; LEAVE + + jsr CLRBUF ; so send out stuff that's there + + lda OLDEHZ ; get old x pos + sta SCRCX ; and restore it + lda #1 ; show cursor changed + sta CURSFLG ; okay + lda SCRCY ; point to next line + clc ; by adding in the font height + adc #FONT_H ; okay, goody + sta SCRCY ; and here we are + + lda TBL_LEN+HI ; reset length + sta LENGTH+HI ; hi part + lda TBL_LEN+LO ; lo part + sta LENGTH+LO ; just a lo + + lda TBLWIDTH ; RESET COUNT + sta TBLCNT ; thanx + bne PTTLP ; GO DO NEXT LINE +PTTDUN: + jsr CLRBUF ; send out last bit + rts +;-------------- +; ZPRINTF +;-------------- +; ZPRINTF - print a formatted table +; +ZPRINTF: + lda ARG1+LO ; USE GETBYT AS TBL COULD + sta MPCL ; BE ANYWHERE + lda ARG1+HI + sta MPCM + lda #0 + sta MPCH + jsr VLDMPC + + lda SCRCX ; save the X pos + sta OLDEHZ ; saved here +ZPFL1: + jsr GETBYT ; get the length byte + beq ZPFX ; no more if == 0 + sta TBLWIDTH ; keep track of it +ZPFL2: + jsr GETBYT ; now get the char byte + jsr CHAR ; and send it yt + dec TBLWIDTH ; any more? + bne ZPFL2 ; ayyup + + jsr DISP_LINE ; make sure line goes out + lda OLDEHZ ; reset a few things + sta SCRCX ; including x pos + lda #1 ; show cursor changed + sta CURSFLG ; okay + lda SCRCY ; point to next line + clc ; by adding in the font height + adc #FONT_H ; okay, goody + sta SCRCY ; and here we are + bne ZPFL1 ; and do it again +ZPFX: + rts +; ------------ +; SET NEW FONT +; ------------ + +; Font 4 is mono-spaced font. + +ZFONT: + jsr CLRBUF ; clear the buffer first + + dec NARGS ; did we get passed a window id? + bne ZFNTWID ; yup + lda #$FD ; -3 means current window + sta ARG2+LO ; make it the arg2 then +ZFNTWID: + lda ARG2+LO ; get window we are interested in + jsr SETWJ ; make [J] point to window struct + + lda ARG1+LO ; check for + cmp #1 ; font 1 + beq ZFNT1 ; or + cmp #4 ; font 4 (monospace) + bne ZFBAD ; nope, so die +; +; font 4 is the monospaced font +; + ldy #WINFSIZE ; point to width + lda #MFONT_W ; get game width + sta (J),Y ; store the width + lda #3 ; set font ID + bne ZFNTEX ; all done +ZFNT1: + ldy #WINFSIZE ; point to width + lda #FONT_W ; get game width + sta (J),Y ; store the width + lda #0 ; set font ID +ZFNTEX: + ldy #WINFONT ; set font + pha ; save font id + lda (J),Y ; get old font id + tax ; save old font id + pla ; get new one back + sta (J),Y ; save in structure + lda (WINDOW),Y ; get current window font + beq ZFNT0X ; set flag with zero + lda #MONOFONT_W ; get width of mono spaced font +ZFNT0X: + sta FONTFLG ; and set flag too + inx ; make it say correct font ID for game + txa ; put in A for put val + ldx #0 ; clear X + jmp PUTVAL ; and return it +ZFBAD: + jmp RET0 ; TELL IT DOESN'T WORK +; ------------------------------ +; FETCH A LINE OF INPUT FOR READ +; ------------------------------ +; ENTRY: Relative READ table address in RDTBL1 +; EXIT: # CHARS READ IN [A] +SV_SPC: ds 3 ; save SPC here for later usage + +INPUT: + jsr CLRBUF ; FLUSH [LBUFF] + ldy #0 ; RESET LINE COUNT + sty I+HI ; clear local variables + sty I+LO + sty J+HI + sty J+LO + sty BRKCHR ; init break char + sty LINCNT ; RESET LINE COUNT + sty PTR_COUNT ; we start by looking at pointer + sty CURSFLG ; make sure we don't change cursor +; +; check for new TCHARS table +; + lda ZBEGIN+ZTCHAR+1 ; so check lower byte for different tchars + cmp SVTCHAR+LO ; is it different? + bne IO_DOT ; ayyup, get new one + lda ZBEGIN+ZTCHAR ; get current TCHARS hi part + cmp SVTCHAR+HI ; is it the same as saved one? + + beq IOj ; yes, so don't muck with it +IO_DOT: + jsr DO_TCHARS ; new table, so copy it over +; +; now set up FPC +; +IOj: + lda RDTBL1+HI ; get page of table + jsr SETPC ; and get me the memory page and bank + sta FPCH ; save page + sty FPCBNK ; and bank + lda RDTBL1+LO ; and get offset + sta FPCL ; set up FPC/SPC + jsr FETCHB ; get length of line + tay ; for dec'ing + dey ; don't count the offset byte + dey ; and leave room for terminator + sty CHRMAX ; and save it + jsr NEXTFPC ; point to next byte + jsr FETCHB ; get current offset into buffer + sta CHARCNT ; save how many chars out there + jsr NEXTFPC ; point to beginning of data buffer +; +; now finish setting up saved SPC +; + ldx #2 +INSVCL: + lda FPC,X ; get byte to saved for use later on + sta SV_SPC,X ; it is saved here + dex + bpl INSVCL ; next! +; +; now copy current buffer into local buffer +; + lda CHARCNT ; make sure we have some + beq CPIOLX ; nope, none in there now + ldx #0 ; start at first char +CPIOL: + jsr FETCHB ; get a char + sta LBUFF,X ; save char + jsr NEXTFPC ; point to next one + inx ; next char + cpx CHARCNT ; got them all yet? + bne CPIOL ; nope +CPIOLX: + jsr CHKTME ; START TIME LIMIT +; +; this is the get-a-key-and-whack-on-it loop +; +INLOOP: + lda I+HI ; is there a time? + beq INPL1 ; nope + jsr TIMIN ; do timed input + bcc INPL2 ; got a char, process it + jmp LEXBAD ; timed out with nothing there! +INPL1: + jsr GETKEY ; let apple do the walking +INPL2: + jsr ISTCHR ; CHECK IF IT'S AN ACCEPTABLE TERMINATOR KEY + bcs NOTYET + + sta BRKCHR + cmp #EOL ; IF EOL PUT TO SCREEN + beq ENDLINx + jmp ENDIN ; ELSE JUST END +ENDLINx: + jmp ENDLIN ; can't reach with a branch +NOTYET: + ldy #$FF ; restart pointer device counter + sty PTR_COUNT ; and start again + tay ; check for functions keys that aren't + bmi CBAD ; terminators and feep if it is + cmp #EOL ; EOL? + beq ENDLIN ; LINE DONE IF SO + cmp ESCAPE ; don't allow escape char's thru + beq CBAD ; okay, I won't + + cmp #BACKSPACE ; BACKSPACE? + beq BACKUP ; SPECIAL HANDLING + cmp #ESCAPE ; ESCAPE char? + beq CBAD ; don't like it + + ldy CHARCNT ; where do we put char? + cpy CHRMAX ; are we filled up? + bcs CBAD ; boy, am i full + + pha ; save it + tax ; use as index + lda LENGTH+LO ; GET LINE LENGTH COUNTER + clc ; get ready for add + adc CHWID,X ; add width + tay ; save LSB in Y + ldx LENGTH+HI ; get high byte + bcc INP0C ; no wrap + inx ; okay, wrap then +INP0C: + pla ; get char back + cpx XSIZE+HI ; check MSB first + bcc NOIOWRAP ; no need to check lsb + cpy XSIZE+LO ; end of screen line? + bcs CBAD ; reached end, so just beep +NOIOWRAP: + stx LENGTH+HI ; save MSB + sty LENGTH+LO ; and LSB + ldx CHARCNT ; for putting in line buffer + sta LBUFF,X ; and save it in case we goto printer + jsr CHAR ; SEND TO SCREEN + jsr DISP_LINE ; show char + inc CHARCNT ; NEXT POSITION IN LINE + jmp INLOOP ; NO, GET ANOTHER CHAR +; +; HANDLE BACKSPACE +; +BACKUP: + ldx CHARCNT ; if == 2 then empty + beq CBAD ; JMP to beeping + dex ; get rid of char + stx CHARCNT ; saved + lda LBUFF,X ; get char we are interested in + tax ; put in x + + lda LENGTH+LO ; GET LINE LENGTH COUNTER + sec ; get ready for sub + sbc CHWID,X ; sub width + sta LENGTH+LO ; update length + bcs BCKP1 ; no wrap + dec LENGTH+HI ; okay, wrap then +BCKP1: + lda #BACKSPACE ; so do erasing backspace + jsr CHAR + jmp INLOOP +CBAD: + jsr BEEP ; ELSE SCREAM WITH PAIN + jmp INLOOP ; AND WAIT FOR SOMETHING BETTER +; +; HANDLE END OF LINE KEY +; +ENDLIN: + sta BRKCHR + lda #EOL ; get EOL char + jsr CHAR ; SEND EOL TO SCREEN + lda #0 ; and show 0 length of line out there + sta LENGTH+LO ; thanx + sta LENGTH+HI ; and msb + inc LINCNT ; take into account the at EOL +ENDIN: +; +; now save lbuff in table for posterity +; + lda SV_SPC+ABANK ; get bank first + sta SPCBNK ; saved + lda SV_SPC+HI + sta SPCH + lda SV_SPC+LO + sta SPCL + ldx #0 ; start with first char in buffer +ENDLOOP: + cpx CHARCNT ; done yet? + beq INP111 + lda LBUFF,X ; get char + cmp #'A' ; IF CHAR IS UPPERCASE ALPHA, + bcc LEX ; CONVERT TO LOWER CASE + cmp #'Z'+1 + bcs LEX + adc #$20 ; converting away +LEX: + jsr STASHB ; okay, stashing away + jsr NEXTSPC ; and point to next char in table + inx ; point to next char + bne ENDLOOP ; so get next one +INP111: + lda #00 ; to show end of line + jsr STASHB ; so put it in buffer +; +; now put in new line length +; + lda RDTBL1+HI ; get page of table + jsr SETPC ; and get me the memory page and bank + sta SPCH ; save page + sty SPCBNK ; and bank + lda RDTBL1+LO ; and get offset + sta SPCL + jsr NEXTSPC ; and point to char count + lda CHARCNT ; get character count + jsr STASHB ; and shove it away +LEXBAD: + ldy #0 ; clear out + sty PTR_COUNT ; pointer flag + rts ; Length is in [A] +; +; Copy over a new TCHARS table +; +DO_TCHARS: +; +; now do somethin' with the TCHAR table (maybe, if <> 0) +; + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + sta SVTCHAR+HI ; save it for checking + jsr SETPC ; and now make absolute + sta FPCH ; Save in FPC + sty FPCBNK + lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + sta SVTCHAR+LO ; and save for later check + sta FPCL ; now move pointer to fetch spot + + lda #0 ; and set index + sta I ; thank you + sta ALLFLG ; turn it off +TCHLP: + jsr FETCHB ; get the byte in [a] + jsr NEXTFPC ; point to next one + ldx I ; get offset + inc I ; and point to next one + sta TCHARTBL,X ; save in lower memory, thank you + cmp #0 ; are we done yet? + beq TCHj ; NULL TERMINATED STRING + cmp #$FF ; $ff means all >128 chars are terminators + bne TCHLNEXT ; nope + lda #1 ; yes, + sta ALLFLG ; so set flag to say so +TCHLNEXT: + bne TCHLP ; and go get it +TCHj: + rts + + ; ------------------------ + ; IS IT A TERMINATOR CHAR? + ; ------------------------ + +ISTCHR: + ldx TCHARTBL ; check for chars in TCHAR table + beq ISNOT ; nope + + ldx ALLFLG ; ARE ALL FCN KEYS (<127) TERMINATORS + beq ISCHK ; 0 = NO, GO CHECK LIST + tax ; check for minus + bmi ISFND ; YUP + bpl ISNOT +ISCHK: + ldy #0 +ISLP: + cmp TCHARTBL,Y ; IS CHAR WE HAVE A TCHAR? + beq ISFND ; YES + ldx TCHARTBL,Y ; NULL = END OF STRING + beq ISNOT + iny + bne ISLP ; SHOULD ALWAYS LOOP +ISNOT: + sec + rts ; NOT FOUND +ISFND: + clc + rts + + ; ----- + ; INPUT 1 char, no printing + ; ----- + +ZINPUT: + JSR CLRBUF + + ldy #0 + sty LINCNT + sty CHRCNT + sty I+HI ; init locals too + sty I+LO + sty J+HI + sty J+LO + sty PTR_COUNT ; always check the pointer + + DEC NARGS + BEQ ZINP3 ; NO TIME LIMIT + LDA ARG2+LO ; GET DELAY WANTED + STA I+HI + DEC NARGS + BEQ ZINP4 ; NO FCN + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI +ZINP4: + JSR TIMIN ; CALL timed input rotine + BCC ZINPRK ; send char on home + JMP RET0 ; time out without character +ZINP3: + jsr GETKEY ; ok, find which char was pressed + cmp #ESCAPE ; don't use escape char + bne ZINPRK ; fine + jsr BEEP ; complain + jmp ZINP3 ; do again +ZINPRK: + LDX #0 + JMP PUTBYT ; RETURN CHAR + + +INTCLL: + LDA I+HI ; SAVE VALUES FOR CALLING RTN + PHA + LDA I+LO + PHA + LDA J+HI + STA ARG1+HI ; pretend it's arg1 + PHA + LDA J+LO + STA ARG1+LO ; and this is the other half + PHA + + LDX #1 + STX NARGS ; 0 args for internal call + DEX + STX IRET ; make sure it returns here! + + LDA ZPCL ; a fake one to say we + PHA ; are an internal call + LDA ZPCM ; so save real one + PHA + LDA ZPCH + PHA + + LDA #0 ; return addr of zero is + STA ZPCH ; internal call! + STA ZPCM + STA ZPCL + + JSR DOCALL + + JMP MLOOP ; GO DO FCN +; +; RETURN FROM FCN WILL COME HERE +; +ZIRET: + PLA ; GET RID OF RTS FROM ZRET + PLA + + PLA ; get old zpc back + STA ZPCH + PLA + STA ZPCM + PLA + STA ZPCL + JSR VLDZPC ; and validate it + + PLA ; RESTORE FOR CALLING RTN + STA J+LO + PLA + STA J+HI + PLA + STA I+LO + PLA + STA I+HI + RTS ; GO BACK TO CALLER + +; INPUT: routine locals! +CHARCNT: DB 0 ; where into buffer goes char +SVCHAR: DB 0 ; where to save the char before printing + +IRET: DB 0 ; FLAG TELLS IF RETURNLESS CALL + +MTEMP: DB 00,00 ; temp spot for math routines +TYPE: DB 0 ; PARTIAL OR NORMAL (WHOLE) SAVE/RESTORE +ASSVLU: DB 0 ; how many args to this subroutine +BRKCHR: DB 0 ; READ BREAK CHAR +RDFLAG: DB 0 ; 0 - only read 1 - do lex on it +MORE: DB "[MORE]" +MOREL EQU $-MORE + END + + diff --git a/apple/yzip/rel.9/machine.asm b/apple/yzip/rel.9/machine.asm new file mode 100644 index 0000000..baa45fd --- /dev/null +++ b/apple/yzip/rel.9/machine.asm @@ -0,0 +1,946 @@ + STTL "--- MACHINE-DEPENDENT I/O: APPLE II ---" + PAGE +; ----------------------- +; DIRECT PRINT LINE [X/A] +; ----------------------- +; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB) +; STRING LENGTH IN [Y] +DLCNT: db 0 +DLOFF: db 0 +DLINE: + stx STRING+LO ; DROP STRING ADDRESS + sta STRING+HI ; INTO DUMMY BYTES + sty DLCNT ; COUNTER + jsr CLRBUF ; send out what's out + lda SCREENF ; save output flag + pha + ldx #1 ; INIT CHAR-FETCH INDEX + stx SCREENF ; make sure screen output is on + dex + stx CRLF_CHECK ; don't let swap happen + stx SCRIPT ; don't script any of my internal +DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE +STRING: DW $0000 ; DUMMY OPERAND BYTES + stx DLOFF ; save X + sta IOCHAR ; save here for DIRECT_OUT +DOUT1: jsr DIRECT_OUT ; send directly out there + ldx DLOFF ; get x back + inx + dec DLCNT ; LOOP TILL + bne DOUT ; OUT OF CHARS + jsr CLRBUF ; and force the chars out + ldx #1 ; allow scripting again + stx SCRIPT ; okay, we did + stx CRLF_CHECK ; and turn on check + pla ; get screen flag back + sta SCREENF ; bingo + rts ; done + +; SWAP2INFOW - save current state and swap to the information window, +; which is currently window zero +SWAPA1: ds 1 ; save for current ARG1 +SWAPCW: ds 1 ; save for current window +SWAPFLG: db 0 ; flag == 1 if we have already swapped +SWAP2INFOW: + lda SWAPFLG ; already swapped? + bne SWP2 ; ayyup + jsr CLRBUF ; clear out the buffer + jsr SAVE_CURSOR ; save current postion of cursor + lda ARG1+LO ; get current arg1 + sta SWAPA1 ; save it + lda CURWIN ; get current window + sta SWAPCW ; save it + lda #0 ; swap to window zero for messages + sta ARG1+LO ; okay + jsr ZSCRN ; and swap to it +SWP2: + inc SWAPFLG ; show we are in swap window +SWAPEX: + rts ; all done +; +; SWAPBACK - swap out of info window, and back to old window +; +SWAPBACK: + dec SWAPFLG ; are we finally leaving for good? + bne SWAPEX ; nope + lda SWAPCW ; and now for current window + sta ARG1+LO ; swap to it + jsr ZSCRN ; we did + lda SWAPA1 ; and get arg1 back + sta ARG1+LO ; we did + jmp GET_CURSOR ; and get cursor back + +; ----------------------- +; SEND [LBUFF] TO PRINTER +; ----------------------- +; ENTRY: LENTH OF LINE IN [PRLEN] + +PLEAV: RTS + +PPRINT: + lda SCRIPT ; SCRIPTING INTERNALLY ENABLED? + and SCRIPTF ; SCRIPTING ON? + and SCRIPTFLG ; Window allow scripting? + beq PLEAV ; NO, EXIT + lda CSW+LO ; SAVE NORMAL OUTPUT HOOK + pha + lda CSW+HI + pha + lda ALTCSW+LO ; LOAD SCRIPTING HOOK + sta CSW+LO + lda ALTCSW+HI + sta CSW+HI + lda RDROM ; put system ROM in for printer out + ldy #0 +PP5: + lda LBUFF,Y ;GET A CHAR TO SEND OUT + bmi PP6 ; don't do highlighting + ora #$80 ; make it apple happy + jsr MCOUT +PP6: + iny + dec PRLEN ;LINE COUNT + bne PP5 ;PRINT WHOLE LINE +; +; ALL DONE, RESET TO NORMAL AND LEAVE +; + lda BNK2SET ; write RAM, bank 1 + lda BNK2SET + pla + sta CSW+HI + pla + sta CSW+LO + rts + +PSTAT: DB 0 ;SET TO CLEAR WHEN BOOT, + ;I PUT IT HERE SO RESTART WON'T ALTER +ALTCSW: DB 0,0 ;(WORD) PRINTER COUT + + ; FIRST TIME USING PRINTER, INITIALIZE IT +SLOTM: DB EOL + DB "Printer Slot 1-7: " +SLOTML EQU $-SLOTM + +PCHK: + jsr SWAP2INFOW ; point to info window +PCHK1: + DLINE SLOTM + jsr GETKEY + cmp #'8' ;1-7 + bcs PCHK1 ;OOPS + cmp #'1' ; less than '1'? + bcc PCHK1 ; ayyup +PC2: + eor #$F0 ; make it a slot address + sta ALTCSW+HI + lda #EOL + jsr CHAR ;SEND >CR< TO SCREEN FOR NEATNESS + inc PSTAT ;SET TO ON + lda CSW+LO ;SAVE NORMAL OUTPUT HOOK + pha + lda CSW+HI + pha + lda ALTCSW+LO ;LOAD SCRIPTING HOOK + sta CSW+LO + lda ALTCSW+HI + sta CSW+HI + jsr INITPRT ; now, init it + + lda RDROM ; bring in system ROM + lda #$89 ; OUTPUT PRINTER SETUP SEQUENCE + jsr MCOUT ; START WITH COMMAND CHAR >CTRL-I< + lda #$B8 ; 8 (80 COL WIDE) + jsr MCOUT + lda #$B0 ; 0 + jsr MCOUT + lda #$CE ; N (LF AFTER CR) + jsr MCOUT + lda CSW+LO ; SAVE REAL PRINTER OUTPUT + sta ALTCSW+LO ; LOC. FOR NEXT TIME + lda CSW+HI + sta ALTCSW+HI + pla ; RESET NORMAL OUTPUT + sta CSW+HI + pla + sta CSW+LO + lda BNK2SET ; and bring back top RAM + lda BNK2SET ; okay + jmp SWAPBACK ; and back to the old window +INITPRT: + lda #0 ; jump to $Cn00 + sta CSW+LO ; make LSB == 0 + jmp (CSW) ; and goto it + + +SAVE_CURSOR: + lda SCRCY ; save the cursor pos + ldy #WINY ; get offset + sta (WINDOW),Y ; first y pos + iny ; now x pos + lda SCRCX ; got it + sta (WINDOW),Y ; saved it + ldy #WINLCNT ; reset line count too + lda LINCNT ; okay + sta (WINDOW),Y ; get it + rts + +GET_CURSOR: + ldy #WINY ; get cursor pos back + lda (WINDOW),Y ; got y pos + sta SCRCY ; saved + iny ; point to x pos + lda (WINDOW),Y ; got it + sta SCRCX ; make it better + sec ; subtract left margin to get how long line is + sbc LEFTMRG ; okay we did that + bcs GETCR1 ; make sure left margin is not > cur x pos + lda #0 ; otherwise, pretend length is zero +GETCR1: + sta LENGTH+LO ; this is how big line is too + lda #0 ; clear MSB + sta LENGTH+HI + asl LENGTH+LO ; *2 + rol LENGTH+HI + asl LENGTH+LO ; *4 + rol LENGTH+HI + + ldy #WINLCNT ; reset line count too + lda (WINDOW),Y ; get it + sta LINCNT ; okay + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay + rts + +; ------------ +; SPLIT SCREEN +; ------------ +; +; SPLIT SCREEN AT LINE [ARG1] putting screen 1 at top and screen +; 0 at bottom. +; DISABLE SPLIT IF [ARG1] = 0 +; +ZSPLIT: + jsr SAVE_CURSOR ; save the cursor pos +; +; first muck with window 1 +; + lda ARG1+LO ; get split arg back + sta WINDOW1+WINHGHT ; this becomes the height of window 1 + lda #0 ; put top of 1 to top of screen + sta WINDOW1+WINTOP ; okay, we did it + lda ARG1+LO ; get new height + ldx #$FF ; this is the counter + sec ; get ready for subs +ZSPLIT0: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZSPLIT0 ; still some lines + dex ; save input line + stx WINDOW1+WINLINES ; saved + + lda WINDOW1+WINY ; check cursor pos + cmp ARG1+LO ; against height + bcc ZSPL1 ; inside window, so save it +ZSPL0: + lda #0 ; reset to top left + sta WINDOW1+WINY ; y pos at top + sta WINDOW1+WINX ; x pos at left + sta WINDOW1+WINLLEN+LO ; line length + sta WINDOW1+WINLLEN+HI ; line length + sta WINDOW1+WINLCNT ; line counter +; +; now muck with window 0 +; +ZSPL1: + lda WINDOW0+WINTOP ; top of window 0 + sec ; doing sub + sbc ARG1+LO ; subtract out the new top + clc ; adding + adc WINDOW0+WINHGHT ; to get the new height +; bcc ZSPLIT1 ; okay, positive height +; lda #0 ; make height 0 +ZSPLIT1: + sta WINDOW0+WINHGHT ; and save new height + + ldx #$FF ; this is the counter + sec ; get ready for subs +ZSPLIT2: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZSPLIT2 ; still some lines + dex ; to save input line + stx WINDOW0+WINLINES ; saved + + lda ARG1+LO ; this is the new top + sta WINDOW0+WINTOP ; set in structure + cmp WINDOW0+WINY ; make sure cursor is still in window + beq ZSPL5 ; nope, at the top + bcc ZSPL5 ; or under it + sta WINDOW0+WINY ; put cursor at top + lda #0 ; left of new + sta WINDOW0+WINX ; window 0 + sta WINDOW0+WINLLEN+LO ; linelength + sta WINDOW0+WINLLEN+HI ; linelength + sta WINDOW0+WINLCNT ; line counter +ZSPL5: + jsr GET_CURSOR ; get the cursor pos back + + lda #0 ; now switch to window zero + sta ARG1+LO ; good bye + jmp ZSCRN ; making window 0 be current + +; ------ +; MARGIN +; ------ +; +; Set the margins for the window +; +; ARG1 - left margin +; ARG2 - right margin +; ARG3 - window ID (optional) +; +ZMARG: + jsr CLRBUF ; CLEAR LBUFF BEFORE RESETTING LINE MARGINS + jsr SAVE_CURSOR ; save current cursor pos + + lda NARGS ; see if window ID was passed + cmp #3 ; if ==3, then it's there + beq ZMRG1 ; okay, so use it + lda CURWIN ; get the current window + sta ARG3+LO ; and use as the default +ZMRG1: + lda ARG3+LO ; check what window + jsr SETWJ ; get window offset into J + lda ARG1+LO ; do left margin first + ldy #WINLM ; get offset + sta (J),Y ; save for window + iny ; point to right margin + lda ARG2+LO ; get right margin + sta (J),Y ; save right margin + ldy #WINWID ; get full width of window + lda (J),Y ; got it + sec ; subtract off the 2 margins + ldy #WINLM ; first the left margin + sbc (J),Y ; okay, gone + iny ; point to right margin + sbc (J),Y ; and take it off + ldy #WINXSZ ; set width of usable window + sta (J),Y ; see, here it is +; +; move cursor to left margin +; + ldy #WINLEFT ; get left edge + lda (J),Y ; got it + ldy #WINLM ; and add left margin + clc ; adding + adc (J),Y ; to get minimum X + ldy #WINX ; check to make sure X pos is okay + sta (J),Y ; then reset it +; +; now see if we changed the current window +; +ZMRGXP: + ldx ARG3+LO ; get the window + bmi ZMRG3 ; -3 means current window + cpx CURWIN ; check against the current window + bne ZMRGX ; nope, so we be done +ZMRG3: + sta LEFTMRG ; [A] already has left margin + ldy #WINXSZ ; get xsize to set + lda (WINDOW),Y ; got it + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + jsr GET_CURSOR ; restore the cursor pos +ZMRGX: + rts +; +; SOUND +; ----- +; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID +; (EZIP) + +ZSOUND: + ldx ARG1+LO ; GET SOUND WANTED + dex + beq BEEP + dex + bne ZSOEX ; INVALID + ldy #$FF ; DURATION ($C0 = .1 SEC) +BOOP: + lda #$10 ; TONE ($0C = 1 KHZ) + jsr WAIT10 + lda SPKR ; TOGGLE SPEAKER + dey + bne BOOP +ZSOEX: + rts + +BEEP: + lda RDROM + jsr MBELL ; just use system beep + lda BNK2SET ; back to bank 2 + lda BNK2SET ; back to bank 2 + rts +; +; just do the background color - foreground is always white/black +; +; +; ZIPCOLOR - maps ZIP colors to screen colors +; +ZCOLOR: + jsr CLRBUF ; print out what we have + + lda NARGS ; check if window was passed + cmp #3 ; was it? + beq ZCLR0 ; ayyup + lda CURWIN ; make it current window + sta ARG3+LO ; it is now +ZCLR0: + lda ARG3+LO ; get window ID + jsr SETWJ ; and put pointer into J + + ldx ARG2+LO ; get background color + beq ZCLR2 ; check fore ground color + bpl ZCLR01 ; not -1 + jsr GET_NYBBLE ; get me the color nybble here + jmp ZCLR11 ; and use as background color +ZCLR01: + dex ; check for default + bne ZCLR1 ; nope, find the color + ldx #1 ; use black as default back color +ZCLR1: + dex ; zero base the color + lda ZIPCOLOR,X ; get my color from the zip color +ZCLR11: + ldy #WINBGND ; get background offset + sta (J),Y ; saved color +; +; now do foreground color +; +ZCLR2: + ldx ARG1+LO ; get foreground color + beq ZCLREX ; no change + dex ; check for default + bne ZCLR3 ; nope, find the color + ldx #8 ; use white as default fore color +ZCLR3: + dex ; zero base the color + lda ZIPCOLOR,X ; get my color from the zip color + ldy #WINFORE ; foreground color offset + txa ; get into A for fun + sta (J),Y ; save in structure +ZCLREX: + rts + +; +; CHKTME RTN - CALLED BY INPUT & ZINPUT +; +CHKTME: + lda NARGS ; CHECK IF TIME LIMIT + cmp #2 + beq CHKT1 ; NO + lda ARG3+LO ; GET DELAY WANTED + sta I+HI + lda NARGS ; IS THERE A FCN? + cmp #4 + bne CHKT1 ; NO + lda ARG4+LO ; YES, SET IT + sta J+LO + lda ARG4+HI + sta J+HI +CHKT1: + rts ; just set things up, please + +WAIT10: + lda #2 ; do this twice (maybe) + sta DELAY_COUNTER ; put in counter +WAIT0: + lda RDROM ; get roms in + ldx #4 ; .04 SEC (time to do other stuff) +TIME1: lda #$30 ; .01 SEC + jsr MWAIT + dex + bne TIME1 + + lda BNK2SET ; get roms out + lda BNK2SET + + lda MOUSEF ; move mouse cursor? + beq WAIT1 ; nope + lda PTR_COUNT ; but do we really want to check it + bne WAIT1 ; nope + jmp MOVE_MC ; move cursor, if necessary +WAIT1: + dec DELAY_COUNTER ; count loop + bne WAIT0 ; go do again + rts +; +; tick the ol timer +; +TIMEK: + lda #BLINK_RATE ; how often to blink + sta CURCOUNT ; okay! +TIMEST: + lda I+LO ; don't reset if not zero + bne TIMELOOP ; so keep goin' then + lda I+HI + sta I+LO + jsr STCUR ; start the cursor +TIMELOOP: + jsr WAIT10 ; wait .10 secs + + jsr FKEYX ; Check for Keystroke + bmi TIME2 ; OK, HE'S THERE, CONTINUE + + dec CURCOUNT ; count down to toggle + bne TMCNT ; okay, no blink + jsr STCUR ; blink cursor + lda #BLINK_RATE ; once per second + sta CURCOUNT ; okay! +TMCNT: + dec I+LO ; 10TH'S OF SECONDS TO WAIT + beq TIMEOUT ; SOME TIME LEFT + + bne TIMELOOP ; so gwon back and try again! (JMP) +; +; THERE IS A TIME OUT, CHECK FOR A FCN +; +TIMEOUT: + jsr ERCUR ; after erasing cursor + lda J+HI ; IS THERE A FCN + beq TIMEBAD ; NO FCN, LEAVE WITH NOTHING +TIME3: + jsr INTCLL ; INTERNALLY CALL THE FCN + lda VALUE+LO ; CHECK RESULTS + beq TIMEST ; ELSE TRY AGAIN + bne TIMEBAD ; else die a horrible death! +TIME2: + jsr ERCUR ; after erasing cursor + clc ; GOT A KEY + rts +TIMEBAD: + sec + rts +; +; display the cursor in the current spot +; +CURSTATE: db $80 ; blinking cursor state +CURCOUNT: db 0 ; toggle counter + +STCUR: + lda CURSOR_OFF ; is the cursor off? + beq STCUR1 ; no + rts ; yes, so don't do nuthin' +STCUR1: + pha ; save a + lda INVFLG ; get current INVFLG + pha ; save it + lda #$80 ; make it all be ones + sta INVFLG ; and blink + + lda #SPACE ; space for cursor + sta SHOW_CURSOR ; show that we are doing cursor + jsr CHAR ; and print it out + jsr DISP_LINE ; send it out + + lda CURSTATE ; get current state + eor #$80 ; toggle it + sta CURSTATE ; save it + pla ; get invflg + sta INVFLG ; restored + lda #0 ; clear cursor flag + sta SHOW_CURSOR ; okay + + pla + rts +; +; just erase the cusor char, but leave cursor in its old place +; +ERCUR: + pha ; save a + lda CURSTATE ; get current state + bne ERCURX ; not on, leave alone + jsr STCUR ; 'start' it out +ERCURX: + pla ; retrieve [A] + rts +; +; timed key input loop +; +; carry set if timed out +; char in [A], if there is one! +TIMIN: + lda MOUSEF ; is there a mouse/joystick? + beq TIMIN1 ; nope + jsr MSCON ; turn on mouse cursor +TIMIN1: + jsr TIMEK ; check for keystroke + bcs TMBAD ; ELSE ABORT +TM1: + jsr PARSEKEY ; GET ASCII INTO [A] AND [IOCHAR] + bcs TIMIN1 ; c==1 means no good char +TMBAD: + ldx MOUSEF ; is there a mouse/joystick? + beq TIMIN2 ; nope + php ; save status + pha ; save (possible) char + jsr MSCOFF ; turn off mouse cursor + pla ; get char back + plp ; get return status +TIMIN2: + rts ; and away we go +; +; FKEYX - move the mouse cursor if any, then check for keystroke +; +FKEYX: + lda MOUSEF ; is there a mouse cursor? + beq KEYX ; nope + bmi KEYMOUSE ; handle mouse + jsr DO_STICK ; handle joystick + bpl KEYX ; go look for key still + bmi KEYBTN ; do button handling +KEYMOUSE: + jsr DO_MOUSE ; handle mouse stuff + bpl KEYX ; go look for key still +; +; button hit, so show pos in MSTBL +; +KEYBTN: + pha ; save status + lda MSTBL+LO + sta SPCL + lda MSTBL+HI + sta SPCH + lda MSTBL+ABANK + sta SPCBNK + lda #ZMSLOCX+1 ; point to LSB of mouse x + jsr ADDSPC ; add to point + lda MSX ; get X + clc ; center the hot spot + adc #CURSW/2 ; add 1/2 width + jsr STASHB ; and stuff it away + lda #2 ; 2 more to get to mouse y + jsr ADDSPC ; okay + lda MSY ; now show the world the y pos + clc ; and center vertically too + adc #CURSH/2 ; add 1/2 height + jsr STASHB ; and it is away + pla ; get status back + tay ; and set it again + rts ; otherwise, done +KEYX: + lda KBD ; check keyboard strobe + bpl KEYXX ; nothing + sta ANYKEY ; reset strobe +KEYXX: + rts +; +; MOVE_MC - move the mouse/joystick cursor, if necessary +; +MOVE_MC: + lda MOUSEF ; check which kind to move + bpl MOVE_MC1 ; move joystick cursor + jsr CHK_MOUSE ; move the mouse cursor + jmp MOVE_MC2 ; and print it +MOVE_MC1: + jsr MOVE_STICK ; okay, checked it out +MOVE_MC2 + lda MSMOVEF ; did it move? + beq MOVE_MCX ; nope + jmp MSCURS ; print it +MOVE_MCX: + rts ; done +; +; CHK_MOUSE - check the mouse position and button state, and flag any change +; +CHK_MOUSE: + lda PAGE2SW ; make sure we are pointing to main bank + + ldx #READM ; get me current cursor pos + jsr MOUSER ; turn off interrupts and set current pos + + lda BNK2SET ; make sure we are pointing to second bank + lda BNK2SET ; okay + +MSFIX0 lda MOUSEST ; get status byte + tay ; save for a sec + and #$20 ; moved since last time? + beq CHKM1 ; nope + sta MSMOVEF ; show movement +MSFIX1 lda MOUSEXL ; get mouse X pos + sta MSX ; save new one +MSFIX2 lda MOUSEYL ; and the y pos + sta MSY ; save for me +CHKM1: + tya ; get status back + and #$C0 ; is button down? + beq CHKMX ; nope + lda #$80 ; show down state +CHKMX: + jmp CHK_BTN ; check button state +; +; there is a mouse, so check it +; +DO_MOUSE: + jsr CHK_MOUSE ; check the mouse please +; FALL THROUGH TO BUTTON CLICKING HANDLER +; jmp DO_BUTTON ; handle button clicking +; +; DO_BUTTON - handle button clicking, working with the timer to +; check for double clicking or not +; +DO_BUTTON: + lda MSMOVEF ; check moved flag + beq DOM01 ; nope + jsr MSCURS ; move mouse cursor +DOM01: + lda #0 ; show no char + ldy MSBTNF ; check button flag + bpl DOBX ; none +; +; button strike, check for double click +; + sty JB_STATE ; show new state + ldy CLKCTR ; have we started click counter? + bpl DOB02 ; nope + ldy #1 ; this resets counter + sty CLKCTR ; reset it + lda #DBL_CLK ; show double click char + bne DOBEXIT ; and finis +DOB02: + ldy #-CLK_CNT ; set to double click timeout + sty CLKCTR ; okay + bmi DOBEXIT ;done +DOBX: + ldy CLKCTR ; click counter counting? + bpl DOBEXIT ; nope + inc CLKCTR ; count it then + bne DOBEXIT ; all done + ldy #1 ; reset counter + sty CLKCTR ; okay + lda #SGL_CLK ; set as char +DOBEXIT: + ldy #0 ; clear out flags + sty MSBTNF ; button flag + sty MSMOVEF ; moved flag + tay ; set flag to show any char + rts ; return char +; +; DO_STICK - handle the joystick 'interrupt' +; +DO_STICK: + jsr MOVE_STICK ; first move it + jmp DO_BUTTON ; now handle it +MOVE_STICK: + lda #0 ; get horizontal change + jsr READ_STICK ; puts value in Y + cpy #80 ; if < 80, then jump to the left + bcs DOST1 ; it is not + lda MSX ; make sure X is > 0 + beq DOST2 ; it is == 0, can't get smaller + sta MSMOVEF ; show movement + dec MSX ; move one to the left + dec MSX ; move two to the left + bne DOST2 ; now check vertical +DOST1: + cpy #180 ; if > 160, then move right + bcc DOST2 ; nope + lda MSX ; make sure X is in bounds + cmp #MAXWIDTH-4 ; don't go too far + bcs DOST2 ; already maxxed out + sty MSMOVEF ; show movement + inc MSX ; one step to the left + inc MSX ; and another one +DOST2: + lda #1 ; now check vertical + jsr READ_STICK ; ask the monitor + cpy #80 ; if < 80, move up + bcs DOST3 ; nope + lda MSY ; don't go negative + beq DOST4 ; already minned out + sta MSMOVEF ; show movement + dec MSY ; count down + dec MSY ; twice + bne DOST4 ; all done +DOST3: + cpy #180 ; check for downward motion + bcc DOST4 ; none + lda MSY ; check for maximum + cmp #MAXHEIGHT-3 ; don't go below water + bcs DOST4 ; gone, thanx + sty MSMOVEF ; show movement + inc MSY ; go further down + inc MSY ; twice as far for joystick +DOST4: + rts ; done +; +; READ_STICK - read the x or y value of the stick in mind. +; [A] == 0 or 1 - the "stick" you are interested in +; Also, check the button status. +; +JB_STATE db 0 ; last state of joystick button +READ_STICK: + pha ; save which stick we want + ldx #$E0 ; oh, pick something random +READST2: + jsr CHECK_JOYBTN ; check the joystick button + dex + bne READST2 + pla ; get x back + tax ; got it + lda RDROM ; bring ROM back + jsr MPREAD ; NOW do the read + lda BNK2SET ; back to RAM + lda BNK2SET ; back to RAM + rts +CHECK_JOYBTN: + lda MOUSEF ; check which kind to move + bpl DO_JBTN ; no joystick, check mouse + jmp CHK_MOUSE ; then do the mouse +DO_JBTN: + lda APKEY1 ; get joystick button +CHK_BTN: + bmi READST3 ; button down + sta JB_STATE ; show button went up +READST3: + eor JB_STATE ; toggle previous state + sta MSBTNF ; set button flag + rts +; ---------------------------- +; FETCH ASCII KEYCODE INTO [A] +; ---------------------------- +; EXIT: ASCII IN [A] & [IOCHAR] + +GETKEY: + lda #BLINK_RATE ; flag as wait for good key + sta CURCOUNT ; clear blinker + lda MOUSEF ; is there a mouse/joystick? + beq GTK0 ; nope + jsr MSCON ; turn on mouse cursor +GTK0: + lda #0 ; clear line counter + sta LINCNT ; okay, we did + txa ; SAVE [X] & [Y] + pha + tya + pha +GKEY0: + inc RAND+HI ; just whack on random number + dec RAND+LO ; and more + jsr FKEYX ; is there a key? + bmi GKEY01 ; got the key + + jsr WAIT10 ; wait .1 seconds, moving mouse cursor + + lda MOUSEF ; do we have a joystick/mouse? + beq GKEY02 ; nope + lda PTR_COUNT ; count down counter? + beq GKEY00 ; nope + dec PTR_COUNT ; count one wait cycle + bne GKEY02 ; don't check yet +GKEY00: + jsr CHECK_JOYBTN ; check the joystick button, just fur the heckuvit +GKEY02: + dec CURCOUNT ; down one + bne GKEY0 ; no toggle + jsr STCUR ; okay, toggle + lda #BLINK_RATE ; 1 per second + sta CURCOUNT ; okay + bne GKEY0 ; check for key +GKEY01: + pha ; save char + lda MOUSEF ; any mouse cursor? + beq GTK1 ; nope + jsr MSCOFF ; turn mouse cursor off +GTK1: + pla ; get char back + jsr ERCUR ; so erase cursor +CHKKEY: + jsr PARSEKEY ; how was the key? + bcs GKEY0 ;TRY AGAIN + sta IOCHAR ;HOLD ON TO IT + pla ; RESTORE + tay ; EVERYTHING + pla + tax + lda IOCHAR ; GET CHAR INTO [A] + rts ; AND RETURN IT + +; +; CHECK TO MAKE SURE KEY IS VALID, ONLY ACCEPT IT IF IT IS +; +PARSEKEY: + and #$7F ;SCREEN OUT SHIFTS +; +;CHECK FOR "ARROWS" & FUNCTION KEYS (X), CONVERT FOR USE (EZIP) +;ALSO : CHANGE <_>)@%^&*( TO ,-.0256789 - and 'mouse' clicks +; and other kinds of special chars +; +GK0: + ldx #ENDKEY ; GET LENGTH OF LIST +GK2: + cmp HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + beq GK3 ; FOUND IT + dex + bpl GK2 ; CHECK THEM ALL + bmi GK4 ; NOT FOUND, CONTINUE OTHER CHECKS +GK3: + lda WANT,X ; GET KEY TO USE INSTEAD + clc ; show niceness + rts ; done +GK4: + cmp #SPACE ; NO CTRL CHARS ACCEPTABLE + bcc BADKEY ; IF < SPACE, BAD + + cmp #'<' ; pick up numbers and most punctuation + bcc OK ; we did + + cmp #'z'+1 ;PICK OUT LETTERS NOW + bcs BADKEY ;IF > BAD + cmp #'a' + bcs OK ;IF > OK + cmp #'A' + bcc BADKEY + CMP #'Z'+1 + BCC OK ;IF < OK +BADKEY: + jsr BEEP ;BAD KEY, GIVE WARNING NOISE, gwon back + sec ; show badness + rts ; and done +OK: + cmp #'0' ; check for number keys + bcc OKj ; nope, < 0 + cmp #'9'+1 ; more than a nine? + bcs OKj ; ayyup +; +; here we check for the closed apple key being down too +; + ldx APKEY2 ; how about the closed apple key + bpl OKj ; not pressed, so use as number key +; +; transform number key into a function key +; + CLC ; get ready for add + ADC #84 ; transforms '1'-'9' to 133-141 + CMP #132 ; but '0' wants to be a 142! + BNE OKj ; but it's not it + CLC ; again, don't want carry + ADC #10 ; voila! +OKj: + clc ; show a wicked good character is about to arrive + rts ; toots finis + +HAVE: DB $0B,$0A,$08,$15,$7f,ESCAPE,$3C,$7C,$3F + DB $3C,$5F,$3E,$40,$25,$5E,$26,$01,$02, EOL +WANT: DB 129,130,131,132,08,ESCAPE,$3C,$7C,$3F + DB $2C,$2D,$2E,$32,$35,$36,$37,254,253, EOL +ENDKEY EQU $-WANT-1 + + END + + diff --git a/apple/yzip/rel.9/macros.asm b/apple/yzip/rel.9/macros.asm new file mode 100644 index 0000000..645c8b0 --- /dev/null +++ b/apple/yzip/rel.9/macros.asm @@ -0,0 +1,120 @@ + STTL "--- MACROS ---" + PAGE + +; +; MACROS for Apple ][ Yzip +; +DLINE: .MACRO STRING,SLEN + ldx #STRING ; get other part of string + IFMA 2 ; check to see if length passed in + ldy SLEN ; then just fetch it + ELSE + ldy #STRING|L ; get length of string + ENDIF + jsr DLINE ; print the string + .MACEND +; +; ProDOS macros +; +PRODOS: .MACRO CODE, PADDR + jsr $BF00 ; ProDOS handler + DB CODE ; ProDOS function code + DW PADDR ; Function Parameter Block address + .MACEND + +QUIT: .MACRO PBLOCK + PRODOS $65, PBLOCK + .MACEND + +READ_BLOCK: .MACRO PBLOCK + PRODOS $80, PBLOCK + .MACEND + +WRITE_BLOCK: .MACRO PBLOCK + PRODOS $81, PBLOCK + .MACEND + +GET_TIME: .MACRO PBLOCK + PRODOS $82, PBLOCK + .MACEND + +CREATE: .MACRO PBLOCK + PRODOS $C0, PBLOCK + .MACEND + +DESTROY: .MACRO PBLOCK + PRODOS $C1, PBLOCK + .MACEND + +RENAME: .MACRO PBLOCK + PRODOS $C2, PBLOCK + .MACEND + +SET_FILE_INFO: .MACRO PBLOCK + PRODOS $C3, PBLOCK + .MACEND + +GET_FILE_INFO: .MACRO PBLOCK + PRODOS $C4, PBLOCK + .MACEND + +ONLINE: .MACRO PBLOCK + PRODOS $C5, PBLOCK + .MACEND + +SET_PREFIX: .MACRO PBLOCK + PRODOS $C6, PBLOCK + .MACEND + +GET_PREFIX: .MACRO PBLOCK + PRODOS $C7, PBLOCK + .MACEND + +OPEN: .MACRO PBLOCK + PRODOS $C8, PBLOCK + .MACEND + +NEWLINE: .MACRO PBLOCK + PRODOS $C9, PBLOCK + .MACEND + +READ: .MACRO PBLOCK + PRODOS $CA, PBLOCK + .MACEND + +WRITE: .MACRO PBLOCK + PRODOS $CB, PBLOCK + .MACEND + +CLOSE: .MACRO PBLOCK + PRODOS $CC, PBLOCK + .MACEND + +FLUSH: .MACRO PBLOCK + PRODOS $CD, PBLOCK + .MACEND + +SET_MARK: .MACRO PBLOCK + PRODOS $CE, PBLOCK + .MACEND + +GET_MARK: .MACRO PBLOCK + PRODOS $CF, PBLOCK + .MACEND + +SET_EOF: .MACRO PBLOCK + PRODOS $D0, PBLOCK + .MACEND + +SET_BUF: .MACRO PBLOCK + PRODOS $D1, PBLOCK + .MACEND + +GET_BUF: .MACRO PBLOCK + PRODOS $D2, PBLOCK + .MACEND + + END + + \ No newline at end of file diff --git a/apple/yzip/rel.9/main.asm b/apple/yzip/rel.9/main.asm new file mode 100644 index 0000000..5d965d2 --- /dev/null +++ b/apple/yzip/rel.9/main.asm @@ -0,0 +1,328 @@ + STTL "--- MAIN LOOP ---" + PAGE + +MD_ADDR EQU ZBEGIN +MDEBUG EQU 1 + +MLOOP: + IF MDEBUG + lda MD_ADDR ; get interesting address + bne MLOOPx ; just fine, thank you + brk ; then die +MLOOPx: + ENDIF + + lda #0 + sta NARGS ; reset number of args + lda PAGE2SW+OFF ; just do this for the heck of it + lda BNK2SET + lda BNK2SET + sta STORE80+ON ; must always be on + + jsr NEXTPC ; get op code + sta OPCODE ; SAVE IT HERE + + IF MDEBUG +; +; special debugging code +; + ldy SPCSV + lda OPCODE + sta SAVEOP,Y + lda ZPCH + sta SAVEZH,Y + lda ZPCM + sta SAVEZM,Y + lda ZPCL + sta SAVEZL,Y + lda ZPCBNK + sta SAVEZB,Y + lda ZPCPNT+HI + sta SAVEZP,Y + ldy SPCSV + iny + tya + and #$0F + sta SPCSV + lda OPCODE + jmp MAINDB +SPCSV: db 0 + ORG $+15 + ORG $.SHR.4 + ORG $.SHL.4 +SAVEOP: ds 16 +SAVEZH: ds 16 +SAVEZM: ds 16 +SAVEZL: ds 16 +SAVEZB: ds 16 +SAVEZP: ds 16 +MAINDB: + ENDIF +; +; DECODE AN OPCODE +; + tay ; 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: CMP #236 ; XCALL? + BNE OPX5 + JMP OPXCLL ; YES, PROCESS SEPARATELY +OPX5: CMP #250 ; IXCALL + BNE OPX6 + JMP OPXCLL +OPX6: 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 + CMP #$C0 ; IS IT NEW OPCODE RANGE? + BCC ZEXTOP ; YES + JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + +DOXOP: AND #%00011111 ; ISOLATE ID BITS + TAY + LDA OPTXL,Y + STA GOX+1+LO + LDA OPTXH,Y + STA GOX+1+HI +GOX: JSR $FFFF ;DUMMY + JMP MLOOP + + ; HANDLE EXTENDED OPCODE RANGE OPS + +ZEXTOP: CMP #EXTLEN ; OUT OF RANGE? + BCS BADEXT + TAY ; OFFSET ALREADY CORRECT + LDA EXTOPL,Y + STA GOE+1+LO + LDA EXTOPH,Y + STA GOE+1+HI +GOE: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #1 -- ILLEGAL X-OP *** + +BADOPX: LDA #1 + JMP ZERROR + + ; *** ERROR #16 -- ILLEGAL EXTENDED RANGE X-OP *** + +BADEXT: LDA #16 + JMP ZERROR + + ; HANDLE AN XCALL OPCODE + +OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + STA ABYTE + JSR NEXTPC + STA BBYTE + LDA ABYTE ; ONE TO START WITH + LDX #0 + STX ADEX ; INIT ARGUMENT INDEX + BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP +XCALL1: LDA ABYTE ; GET ARG BYTE + ASL A ; SHIFT NEXT 2 BITS + ASL A ; INTO BITS 7 & 6 + STA ABYTE ; HOLD FOR LATER +XCALL2: AND #%11000000 ; MASK OUT GARBAGE + BNE XCALL3 + JSR GETLNG ; 00 = LONG IMMEDIATE + JMP XCNXT +XCALL3: CMP #%01000000 ; SHORT IMMED? + BNE XCALL4 ; NO, TRY ANOTHER + JSR GETSHT ; 01 = SHORT IMMED. + JMP XCNXT +XCALL4: CMP #%10000000 ; LAST TEST + BNE OPX4 ; 11 = NO MORE ARGS + JSR GETVAR ; 10 = VARIABLE +XCNXT: LDX ADEX + LDA VALUE+LO + STA ARG1+LO,X + LDA VALUE+HI + STA ARG1+HI,X + INC NARGS + INX + INX + STX ADEX + CPX #16 + BNE XCALL5 + JMP OPX4 ; DONE, GO DO IT +XCALL5: CPX #8 ; DONE 1ST MODE BYTE? + BNE XCALL1 ; NOT QUITE YET + LDA BBYTE ; SET UP FOR NEXT + STA ABYTE ; MODE BYTE + JMP XCALL2 ; GO DO IT + +; ------------- +; HANDLE A 0-OP +; ------------- + +OP0: CMP #190 ; IS IT EXTOP OP + BEQ EXTOP ; YES + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT0L,Y + STA GO0+1+LO + LDA OPT0H,Y + STA GO0+1+HI +GO0: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #2 -- ILLEGAL 0-OP *** + +BADOP0: LDA #2 + JMP ZERROR + + ; THIS OPCODE TELLS THAT NEXT OP IS PART OF THE + ; EXTENDED RANGE OF OPCODES, GET IT AND PROCESS IT + ; (THEY ARE ALL XOPS) + +EXTOP: JSR NEXTPC ; GO GET EXTENDED RANGE OP + STA OPCODE ; SAVE IT + JMP OPEXT ; AND HANDLE IT + + +; ------------- +; HANDLE A 1-OP +; ------------- + +OP1: + and #%00110000 ; ISOLATE ARGUMENT BITS + bne OP1A + jsr NEXTPC ; get next byte + tay + jmp OP1A1 +OP1A: and #%00100000 ; TEST AGAIN + bne OP1B +; +; 01 = SHORT IMMEDIATE +; +OP1A1: sta ARG1+HI + jsr NEXTPC + sta ARG1+LO + inc NARGS + jmp OP1EX1 +OP1B: JSR GETVAR ; 10 = VARIABLE +OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] +OP1EX1: LDA OPCODE + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT1L,Y + STA GO1+1+LO + LDA OPT1H,Y + STA GO1+1+HI +GO1: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** ERROR #3 -- ILLEGAL 1-OP *** + +BADOP1: LDA #3 + JMP ZERROR + + + +; ------------- +; HANDLE A 2-OP +; ------------- + +OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT + BNE OP2A +; +; 0 = SHORT IMMEDIATE +; + sta ARG1+HI + jsr NEXTPC + sta ARG1+LO + inc NARGS + jmp OP2B1 +OP2A: jsr GETVAR ; 1 = VARIABLE +OP2B: jsr V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] +OP2B1: lda OPCODE ; RESTORE OPCODE BYTE + and #%00100000 ; ISOLATE 2ND ARG BIT + bne OP2C + sta ARG2+HI + jsr NEXTPC + sta ARG2+LO + jmp OP2D1 +OP2C: jsr GETVAR ; 1 = VARIABLE +OP2D: lda VALUE+LO ; MOVE 2ND [VALUE] + sta ARG2+LO ; INTO [ARG2] + lda VALUE+HI + sta ARG2+HI +OP2D1: inc NARGS ; UPDATE ARGUMENT COUNT + + ; EXECUTE A 2-OP OR EXTENDED 2-OP + +OP2EX: LDA OPCODE + AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT2L,Y + STA GO2+1+LO + LDA OPT2H,Y + STA GO2+1+HI +GO2: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 + diff --git a/apple/yzip/rel.9/objects.asm b/apple/yzip/rel.9/objects.asm new file mode 100644 index 0000000..a7f6f78 --- /dev/null +++ b/apple/yzip/rel.9/objects.asm @@ -0,0 +1,167 @@ + STTL "--- OBJECT & PROPERTY HANDLERS ---" + PAGE + +; ---------------------------------- +; GET ABSOLUTE ADDRESS OF OBJECT [A] +; ---------------------------------- +; ENTER: OBJECT IN A/X (LO/HI) +; EXIT: ADDRESS IN [FPC] +OBJLOC: + STX I+HI ; SAVE MSB FOR SHIFTING + ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) + STA I+LO + ROL I+HI + LDX I+HI + ASL A + ROL I+HI ; *4 + ASL A + ROL I+HI ; *8 + ASL A + ROL I+HI ; *16 + SEC + SBC I+LO ; -(*2) + STA I+LO ; SO IS *14 TOTAL + LDA I+HI + STX I+HI + SBC I+HI + STA I+HI + LDA I+LO + CLC + ADC #112 ; ADD OBJECT TABLE OFFSET + BCC OBJ3 + INC I+HI +OBJ3: + clc ; NEXT ADD THE relative ADDR + adc ZBEGIN+ZOBJEC+1 ; OF THE OBJECT TABLE + sta FPCL ; save lo byte + lda I+HI + adc ZBEGIN+ZOBJEC ; now work on page + jsr SETPC ; now get page/bank + sta FPCH ; this is hi part + sty FPCBNK ; and this is the bank + rts +; ----------------------------- +; GET ADDRESS OF PROPERTY TABLE +; ----------------------------- +; EXIT: [FPC] HAS ABSOLUTE ADDR OF PROPERTY TABLE +; including OFFSET TO START OF PROP IDS +PROPB: + lda ARG1+LO + ldx ARG1+HI ; get address + jsr OBJLOC ; put table location into FPC + lda #12 ; add 12 to get to beginning + jsr ADDFPC ; and add it to FPC + jsr FETCHB ; get MSB of P-TABLE Address + pha ; and save it for a moment + jsr NEXTFPC ; to get LSB + jsr FETCHB ; get LSB of P-TABLE Address + sta FPCL ; and save lo part + pla ; get page back + jsr SETPC ; and set up memory bank/page + sta FPCH ; save page + sty FPCBNK ; and bank + jsr FETCHB ; get length of short description + asl A ; WORD-ALIGN IT + jsr ADDFPC ; and add it to FPC + jsr NEXTFPC ; POINT JUST PAST THE DESCRIPTION + rts + + +; ------------------- +; FETCH A PROPERTY ID +; ------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +; +PROPN: + jsr FETCHB ; get the byte + and #%00111111 ; MASK OUT LENGTH BITS (EZIP) + rts + +; ------------------------------- +; FETCH # BYTES IN PROPERTY VALUE +; ------------------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +; +PROPL: + jsr FETCHB ; CHECK LENGTH FLAGS + tax ; save it + bpl SHORT ; OFF, SO 1 OR 2 BYTES + jsr NEXTFPC + jsr FETCHB ; NEXT BYTE HAS LENGTH + and #%00111111 ; MASK OFF EXTRA BITS + rts +SHORT: + and #%01000000 ; BIT 6 + beq ONE + lda #2 ; BIT 6 = 1, LENGTH =2 + rts +ONE: + lda #1 ; BIT 6 = 0, LENGTH =1 + rts + +; ---------------------- +; POINT TO NEXT PROPERTY +; ---------------------- +; ENTRY: LIKE "PROPB" EXIT (i.e. - in [FPC]) +; +PROPNX: + jsr PROPL ; GET LENGTH OF CURRENT PROP + tay ; move one more for correct alignment + iny ; okay, done it + tya ; thanks + jsr ADDFPC ; add to [FPC] + rts +; +; ---------------- +; GET OBJECT FLAGS +; ---------------- +; ENTRY: OBJECT # IN [ARG1], FLAG # IN [ARG2] +; EXIT: FLAG WORD IN [K], BIT ID IN [J], +; FLAG WORD ADDRESS IN [FPC] +; +FLAGSU: + LDA ARG1+LO ; get table offset + LDX ARG1+HI + JSR OBJLOC ; GET OBJECT ADDR IN [FPC] + LDA ARG2+LO ; LOOK AT FLAG ID + CMP #$10 ; FIRST SET OF FLAGS? + BCC FLS1 ; YES, ADDR IN [FPC] IS CORRECT + SBC #16 ; ELSE ZERO-ALIGN FLAG INDEX + TAX ; SAVE IT HERE + CMP #$10 ; CHECK IF IN 2ND WORD + BCC FLS ; YES, GO ALIGN FOR THAT + SBC #16 ; ELSE ALIGN TO 3RD WORD + TAX + lda #4 ; 3rd Flag word + bne FLSx ; and add it in +FLS: + lda #2 ; 2nd Flag word +FLSx: + jsr ADDFPC +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: + jsr FETCHB ; MOVE THE FLAG WORD + sta K+HI ; INTO [K] - FIRST THE MSB + jsr NEXTFPC ; and then get get LSB + jsr FETCHB + sta K+LO ; THEN THE LSB + jmp PREVFPC ; point back to flag word + + END + \ No newline at end of file diff --git a/apple/yzip/rel.9/ops012.asm b/apple/yzip/rel.9/ops012.asm new file mode 100644 index 0000000..329d754 --- /dev/null +++ b/apple/yzip/rel.9/ops012.asm @@ -0,0 +1,1215 @@ + STTL "--- 0-OPS ---" + PAGE + + +; ----- +; 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: LDX #5 ;MOVE ZPC INTO MPC +ZPRI1: + LDA ZPC,X + STA MPC,X + DEX + BPL ZPRI1 ;NO NEED TO VALIDATE AS ZPC WAS VALID ANYWAY + JSR PZSTR ; PRINT THE Z-STRING AT [MPC] + LDX #5 ; COPY STATE OF [MPC] +ZPRI2: LDA MPC,X ; INTO [ZPC] + STA ZPC,X + DEX + BPL ZPRI2 + RTS + + +; ------ +; PRINTR +; ------ +; DO A "PRINTI," FOLLOWED BY "CRLF" AND "RTRUE" + +ZPRR: JSR ZPRI + JSR ZZCRLF + JMP ZRTRUE + + +; ------ +; RSTACK +; ------ +; "RETURN" WITH VALUE ON STACK + +ZRSTAK: JSR POPVAL ; GET VALUE INTO [X/A] + JMP ZRT1 ; AND GIVE IT TO "RETURN" + + +; ----- +; CATCH +; ----- + +ZCATCH: LDX OLDZSP+HI ; RETURN ZSTACK POINTER AS + LDA OLDZSP+LO ; ZRET WILL NEED IT + JMP PUTBYT + + +; --------- +; ORIGINAL? +; --------- + +; COPY PROTECTION DEVICE, RETURNS TRUE FOR NOW + +ZORIG: JMP PREDS + + + STTL "--- 1-OPS ---" + PAGE + + +; ----- +; 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC ; GET OBJECT ADDR INTO [FPC] + lda #8 ; POINT TO "NEXT" SLOT (EZIP) + jsr ADDFPC ; and point to it + jmp FIRST1 ; JMP to get it + +; ------ +; FIRST? +; ------ +; RETURN "FIRST" POINTER IN OBJECT [ARG1] ; +; FAIL IF LAST AND RETURN ZERO +; (EZIP ALTERATIONS) + +ZFIRST: + lda ARG1+LO + ldx ARG1+HI + jsr OBJLOC ; GET OBJECT ADDR INTO [FPC] + lda #10 ; point to "First" slot + jsr ADDFPC ; and add it +FIRST1: + jsr FETCHB ; and get it + pha ; save it + jsr NEXTFPC + jsr FETCHB ; and next one + tay ; now dance around a little; save LSB + pla ; get MSB back + tax ; and put to x + tya ; and put LSB back into [A] + jsr PUTBYT ; PASS IT TO VARIABLE + lda VALUE+LO ; EXAMINE THE VALUE JUST "PUT" + bne PFINE + lda VALUE+HI + beq PYUCK ; FAIL IF IT WAS ZERO +PFINE: + jmp PREDS ; ELSE REJOICE + +; --- +; LOC +; --- +; RETURN THE OBJECT CONTAINING OBJECT [ARG1] ; +; RETURN ZERO IF NONE +; (EZIP ALTERED) + +ZLOC: + lda ARG1+LO + ldx ARG1+HI + cpx #$20 ; don't let it get too high + bcc ZLOC1 ; fine + lda #22 ; too big object + jmp ZERROR ; and die +ZLOC1: + jsr OBJLOC ; GET ADDR OF OBJECT INTO [FPC] + lda #6 ; POINT TO "LOC" SLOT + jsr ADDFPC ; and make FPC point there + jsr FETCHB ; go get byte + pha ; save this please + jsr NEXTFPC ; and point to next one + jsr FETCHB ; and get it in [A] + tay ; save LSB + pla ; get MSB back + tax ; and put to [X] + tya ; and put LSB into a + jmp PUTBYT ; AND SHIP IT OUT + +; ------ +; PTSIZE +; ------ +; RETURN LENGTH OF PROP TABLE [ARG1] IN BYTES + +ZPTSIZ: + lda ARG1+HI ; MOVE ABS ADDR OF + jsr SETPC ; get bank/page + sta FPCH ; save page + sty FPCBNK ; and bank + lda ARG1+LO + sta FPCL ; and save lo part + jsr PREVFPC ; Decrement address while moving LSB +PTZ0: + jsr FETCHB ; get length of property + bmi PTZ2 ; BIT 7 = 1, LENGTH > 2 BYTES + and #%01000000 + beq PTZ1 ; BIT 6 = 0, LENGTH = 1 + lda #2 ; BIT 6 = 1, LENGTH = 2 + bne PTZ3 ; JMP +PTZ1: + lda #1 + bne PTZ3 ; JMP +PTZ2: + jsr FETCHB ; and get it + and #%00111111 ; ELSE PICK UP SIZE > 2 +PTZ3: + ldx #0 ; CLEAR FOR PUTBYT + jmp PUTBYT +; --- +; INC +; --- +; INCREMENT VARIABLE [ARG1] + +ZINC: LDA ARG1+LO + JSR VARGET ; FETCH VARIABLE INTO [VALUE] + INC VALUE+LO + BNE ZINC1 + INC VALUE+HI +ZINC1: JMP ZD0 + + +; --- +; DEC +; --- +; DECREMENT VARIABLE [ARG1] + +ZDEC: LDA ARG1+LO + JSR VARGET ; FETCH VAR INTO [VALUE] + LDA VALUE+LO + SEC + SBC #1 + STA VALUE+LO + LDA VALUE+HI + SBC #0 + STA VALUE+HI +ZD0: LDA ARG1+LO ; PUT RESULT BACK + JMP VARPUT ; INTO THE SAME VARIABLE + + +; ------ +; PRINTB +; ------ +; PRINT Z-STRING AT [ARG1] + +ZPRB: + lda ARG1+LO ; move arg1 to I + sta I+LO ; lo part + lda ARG1+HI ; and now for arg1 hi + sta I+HI ; okay + jsr SETWRD ; make [MPC] point to it + jmp PZSTR ; and print it + +; ------ +; REMOVE +; ------ +; MOVE OBJECT [ARG1] INTO PSEUDO-OBJECT #0 +; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO +; 2) MOVES AND COMPARES 2 BYTES) + +SAVEFPC: ds 3 ; spot to save the FPC +SAVEOBJ: ds 1 ; check for zero object + +ZREMOV: + lda ARG1+LO ; GET SOURCE OBJECT ADDR + ldx ARG1+HI + jsr OBJLOC ; INTO [FPC] +; +; now save this objects address in I,J +; + lda #6 ; point to the LOC slot + jsr ADDFPC ; thank you + lda FPCL ; COPY THE SOURCE ADDR + sta SAVEFPC+LO ; INTO [J] + lda FPCH ; FOR LATER REFERENCE + sta SAVEFPC+HI + lda FPCBNK + sta SAVEFPC+ABANK +; +; now go get object this one is in +; + jsr FETCHB ; get the data + sta K ; HOLD IT + jsr NEXTFPC ; get lo part + jsr FETCHB ; now get part + tay ; save it + ora K ; COMPARE BYTES + bne REMVj ; check for object + jmp REMVEX ; SCRAM IF NO OBJECT +REMVj: + tya ; get lo part + ldx K ; and hi part + jsr OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [FPC] + lda #11 ; POINT TO "FIRST" SLOT, LSB + jsr ADDFPC ; and point to it + jsr FETCHB ; and get it + pha ; save LSB + jsr PREVFPC ; point to MSB + jsr FETCHB ; A=LO, X=HI + tax ; put into x + pla ; get LSB back + cmp ARG1+LO ; IS THIS THE FIRST? + bne REMVC1 ; NO, KEEP SEARCHING + cpx ARG1+HI ; HM? + beq DO_REMOVE ; yes, so use it +REMVC1: + jsr OBJLOC ; get object + lda #9 ; GET "NEXT" slot address + jsr ADDFPC ; into FPC + jsr FETCHB ; get the byte + pha ; save LSB for later + jsr PREVFPC ; and this is the hi part + jsr FETCHB + sta SAVEOBJ ; save for later check + tax ; and put into x for (possible) check + pla ; get lo part back + tay ; save a minute + ora SAVEOBJ ; well, is it zero? + bne REMVC2 ; no, so check it + lda #21 ; so die + jmp ZERROR ; and croak +REMVC2: + tya ; put back into [A] + cmp ARG1+LO ; FOUND IT? + bne REMVC1 ; NO, KEEP TRYING + cpx ARG1+HI + bne REMVC1 +DO_REMOVE: +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; copied +; +; now get removed one's address for fetching +; + lda SAVEFPC+ABANK ; this is where bank is + sta FPCBNK ; so show it + lda SAVEFPC+HI ; and here's the hi/lo part + sta FPCH + lda SAVEFPC+LO + sta FPCL + lda #2 ; so get to source's "NEXT" slot + jsr ADDFPC ; point to next slot + jsr FETCHB ; get the hi byte + jsr STASHB ; and save it + jsr NEXTSPC ; point to next one + jsr NEXTFPC ; and from the source too + jsr FETCHB ; get lo byte + jsr STASHB ; and save it away +; +; now zero out SOURCE's loc and next spots +; + lda SAVEFPC+ABANK ; bank of source + sta SPCBNK + lda SAVEFPC+HI ; and addr of source LOC slot + sta SPCH + lda SAVEFPC+LO + sta SPCL +; +; zero out NEXT and LOC of source +; + lda #0 ; zero out 4 locations (LOC MSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (LOC LSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (NEXT MSB) + jsr STASHB + jsr NEXTSPC + + lda #0 ; zero out 4 locations (NEXT LSB) + jsr STASHB + jsr NEXTSPC +REMVEX: + RTS + + +; ------ +; PRINTD +; ------ +; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + +ZPRD: + lda ARG1+LO + ldx ARG1+HI ; (EZIP) + jsr OBJLOC ; GET ADDR OF OBJECT INTO [FPC] + lda #13 ; GET PROP TABLE POINTER (EZIP) + jsr ADDFPC ; and point to LSB + jsr FETCHB ; fetch LSB + pha ; SAVE IT HERE + jsr PREVFPC ; and now fetch MSB + jsr FETCHB ; thank you + sta I+HI ; AND MSB + pla ; get LSB back + sta I+LO ; STORE LSB + 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+LO ; RE-SYNC THE + STA ZSP+LO ; Z-STACK POINTER + LDA OLDZSP+HI + STA ZSP+HI + JSR POPVAL ; POP # LOCALS INTO [X/A] + STX I+HI ; SAVE HERE + JSR POPVAL ; now we need number of args + STA ASSVLU ; for ASSIGNED? + + LDX I+HI ; see how many 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 IRET + STA ZPCL + JSR POPVAL + STX OLDZSP+LO + STA OLDZSP+HI + + LDA ZPCL ; check for zero zpc + BNE RETj ; which means we are returning to + LDA ZPCM ; an internal call + BNE RETj ; rather than just a normal + LDA ZPCH ; return + BNE RETj ; but so far it isn't + + JSR A12VAL ; MOVE [ARG1] TO [VALUE] + JMP ZIRET ; so then do internal return +RETj: + JSR VLDZPC ; MAKE VALID + LDA IRET ; CHECK IF SHOULD RETURN A VALUE + BEQ RETYES ; (0 = RET, 1 = NO RETURN) + RTS ; NO, SO JUST GET OUT OF HERE +RETYES: + 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 (QUAD) 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 + + + + STTL "--- 2-OPS ---" + PAGE + + +; ----- +; 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 + + +; ----------------- +; SIGNED COMPARISON +; ----------------- +; ENTRY: VALUES IN [VALUE] AND [I] +; +; IS [VALUE] > [I] +; +COMPAR: + LDA I+HI + EOR VALUE+HI + BPL SCMP + LDA I+HI + CMP VALUE+HI + BCC PGOOD + JMP PREDF + +SCMP: LDA VALUE+HI + CMP I+HI + BNE SCEX + LDA VALUE+LO + CMP I+LO +SCEX: BCC PGOOD + JMP PREDF + + +; --- +; IN? +; --- +; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? +ZIN: + LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [FPC] + LDA #6 ; POINT TO "LOC" SLOT + jsr ADDFPC ; and point to it + jsr FETCHB ; well? + CMP ARG2+HI ; IS IT THERE? + BNE PBAD ; NO + jsr NEXTFPC ; point to lo part + jsr FETCHB ; and get it + CMP ARG2+LO + 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 + + ; FALL THROUGH ... + + +; --------------------- +; RETURN VALUE IN [X/A] +; --------------------- + +VEXIT: STX VALUE+LO + STA VALUE+HI + JMP PUTVAL + + +; ---- +; BAND +; ---- +; RETURN [ARG1] "AND" [ARG2] + +ZBAND: LDA ARG1+LO + AND ARG2+LO + TAX + LDA ARG1+HI + AND ARG2+HI + JMP VEXIT + + +; ----- +; FSET? +; ----- +; IS FLAG [ARG2] SET IN OBJECT [ARG1]? + +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 [FPC] +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; okay, done it + lda K+HI ; FIRST DO MSBS + ora J+HI + jsr STASHB + jsr NEXTSPC + lda K+LO ; THEN LSBS + ora J+LO + jsr STASHB + rts + + +; ------ +; FCLEAR +; ------ +; CLEAR FLAG [ARG2] IN OBJECT [ARG1] + +ZFCLR: + jsr FLAGSU ; GETS BITS INTO [J] & [K], ADDR IN [FPC] +; +; now, copy from FPC to SPC for stashing away +; + jsr FP2SP ; okey dokey + + lda J+HI ; FETCH MSB + eor #$FF ; COMPLEMENT IT + and K+HI ; RUB OUT FLAG + jsr STASHB ; and save it + jsr NEXTSPC ; point to lo part + lda J+LO ; SAME FOR LSB + eor #$FF + and K+LO + jsr STASHB ; and show it to the world + 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] +; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + +ZMOVE: + jsr ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS +; +; Make [ARG1] be first in [ARG2]'s chain. +; + lda ARG2+LO + ldx ARG2+HI ; Get parent's address + jsr OBJLOC ; into [FPC] + lda #10 ; point to FIRST slot + jsr ADDFPC ; okay + jsr FETCHB ; get old first one (MSB) + sta K+HI ; save it + jsr NEXTFPC ; point to next part + jsr FETCHB ; and get it + sta K+LO ; okay, saved + jsr FP2SP ; make FPC == SPC +; +; now make object [ARG1] be first in object [ARG2] +; SPC is currently pointing to LSB of [ARG2]'s FIRST slot +; + lda ARG1+LO ; stash away low part first + jsr STASHB ; stashed + jsr PREVSPC ; point to high part + lda ARG1+HI ; get hi part of source + jsr STASHB ; save it +; +; now point to object [ARG1] to update its slots +; + ldx ARG1+HI ; put hi part here + lda ARG1+LO ; and lo part here for OBJLOC + jsr OBJLOC ; get me the SOURCE of all confusion + lda #6 ; point to LOC slot + jsr ADDFPC ; and now FPC points there + jsr FP2SP ; now make it the STASH pointer +; +; update [ARG1]s LOC pointer to be [ARG2] +; SPC points to LOC slot +; + lda ARG2+HI ; get PARENT number + jsr STASHB ; and save it in LOC + jsr NEXTSPC ; and point to LSB of LOC + lda ARG2+LO ; got parent's lowness + jsr STASHB ; and saved it in ARG1 +; +; Move old FIRST object and make it [ARG1]s NEXT +; now SPC points to [ARG1]s NEXT slot +; + jsr NEXTSPC ; point to MSB of NEXT + lda K+HI ; get old FIRST one + jsr STASHB ; and save it + jsr NEXTSPC ; and point to LSB now + lda K+LO ; get LSB of this + jsr STASHB ; saved + 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 + LDA #0 + 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 + ADC #0 ; PICK UP CARRY FROM MPCM + STA MPCH ; TO GET TOP BIT + JMP VLDMPC + + +; ---- +; GETP +; ---- +; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 + +ZGETP: + jsr PROPB ; set up FPC +GETP1: + jsr PROPN ; GET ID OF PROP TBL + cmp ARG2+LO ; Compare PROP ID + beq GETP3 ; FOUND IT + bcc GETP2 ; NOT THERE + jsr PROPNX ; GET NEXT PROP, ALIGN [FPC] TO IT + jmp GETP1 ; TRY AGAIN WITH NEXT PROP +; +; PROPERTY NOT THERE, GET DEFAULT +; +GETP2: + lda ARG2+LO ; GET PROPERTY # + sec ; ZERO-ALIGN IT + sbc #1 + asl A ; WORD-ALIGN IT + clc ; add in table start + adc ZBEGIN+ZOBJEC+1 ; add lo part + sta FPCL ; save for fetch + lda ZBEGIN+ZOBJEC ; now get hi part + adc #0 ; pick up carry, if any + jsr SETPC ; get memory spot for this page + sta FPCH ; page and + sty FPCBNK ; bank + jsr FETCHB ; GET MSB OF PROPERTY + sta VALUE+HI + jsr NEXTFPC + jsr FETCHB ; DO SAME WITH LSB + sta VALUE+LO + jmp PUTVAL ; RETURN DEFAULT IN [VALUE] +GETP3: + jsr PROPL ; GET LENGTH OF PROP INTO [A] + tax ; save [A] + jsr NEXTFPC ; MAKE [FPC] POINT TO 1ST BYTE OF PROP + cpx #1 ; IF LENGTH =1 + beq GETPB ; GET A BYTE PROPERTY + cpx #2 ; IF LENGTH = 2 + beq GETPW ; GET A WORD PROPERTY + + ; *** ERROR #7: PROPERTY LENGTH *** + + LDA #7 + JMP ZERROR +; +; GET A 1-BYTE PROPERTY +; +GETPB: + jsr FETCHB ; GET LSB INTO [A] + sta VALUE+LO ; STORE LSB + lda #0 ; CLEAR MSB + sta VALUE+HI ; and zero it + beq ETPEX +; +; GET A 2-BYTE PROPERTY +; +GETPW: + jsr FETCHB ; GET MSB + sta VALUE+HI ; store MSB + jsr NEXTFPC ; POINT TO LSB + jsr FETCHB ; GET IT INTO [A] + sta VALUE+LO ; AND MSB +ETPEX: + jmp PUTVAL + +; ----- +; GETPT +; ----- +; RETURN POINTER TO PROP TABLE [ARG2] +; IN OBJECT [ARG1] + +ZGETPT: + lda ARG1+LO + ldx ARG1+HI ; (EZIP) + jsr OBJLOC ; put location into [FPC] + lda #12 ; get offset table pointer + jsr ADDFPC ; and point to it + jsr FETCHB ; get MSB of table pointer + pha ; save page + jsr NEXTFPC ; point to LSB + jsr FETCHB ; and get it + sta FPCL ; and save it + pla ; get page address back + jsr SETPC ; and absolutize it + sta FPCH ; and save page + sty FPCBNK ; and bank + jsr FETCHB ; GET LENGTH OF SHORT DESC + asl A ; WORD-ALIGN IT + tay ; now point to just past it + iny ; thank you + tya ; for adding + jsr ADDFPC ; and POINT JUST PAST THE DESCRIPTION +GETPT1: + jsr PROPN ; get prop ID + cmp ARG2+LO ; CHECK ID + beq GETPT2 + bcs DDD ; .GE. so check some more + jmp DORET ; BEYOND IT, SO NOT THERE +DDD: + jsr PROPNX ; point to next one + jmp GETPT1 ; next please +GETPT2: + jsr PROPL ; get the length of this property + jsr NEXTFPC ; INC TO POINT AT PROPERTY VALUE (EZIP) +; +; now subtract absolute address to get relative address for returning +; what a pain in the neck +; + lda FPCBNK ; check which bank we are in + beq GETPB0 ; in main bank, it's easier +; +; if in AUX bank, then we must subtract beginning of AUX mem, then +; add in size of MAIN bank +; + lda FPCH ; get page + cmp #>Z3BEGIN ; in part 2 of aux? + bcs GETPB3 ; ayyup + sec ; and subtract + sbc #>Z2BEGIN ; first page in aux + clc ; now add in how many pages in main + adc #P2PAGE ; now we have relative start + bne GETP15 ; JUMP to putval +GETPB3: + sec ; and subtract + sbc #>Z3BEGIN ; first page in aux, part 2 + clc ; now add in how many pages in main + adc #P3PAGE ; now we have relative start + bne GETP15 ; jump to putval +GETPB0: + lda FPCH ; get page in main mem + sec ; and then subtract + sbc #>ZBEGIN ; start of main mem +GETP15: + sta VALUE+HI ; save hi part for returning + lda FPCL ; and just save lo part + sta VALUE+LO ; okay? + jmp PUTVAL ; AND RETURN +DORET: + jmp RET0 ; ELSE RETURN A ZERO + + +; ----- +; NEXTP +; ----- +; RETURN INDEX # OF PROP FOLLOWING PROP [ARG2] IN OBJECT [AR +; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO + +ZNEXTP: + JSR PROPB ; ALIGN [FPC] AT PROPERTY TBL'S 1ST ENTRY + 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 (EZIP) + JMP NXTP1 +NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +NXTP3: JSR PROPN ; GET THE PROPERTY # + LDX #0 ; FOR PUTBYT (EZIP) + 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 + + +; ----- +; THROW +; ----- + +ZTHROW: + lda ARG2+LO ; check to see if we are ready to do return + cmp OLDZSP+LO + bne ZTHLOOP ; nope, keep unwinding the stack + lda ARG2+HI + cmp OLDZSP+HI ; have we found the right frame yet? + beq ZTHDO ; yes +ZTHLOOP: + jsr ZRET ; do another return + jmp ZTHROW ; and try again +ZTHDO: + lda ARG2+LO ; SET ZSTACK POINTER + sta OLDZSP+LO ; UP FOR ZRET + lda ARG2+HI + sta OLDZSP+HI + jmp ZRET + + END diff --git a/apple/yzip/rel.9/opsx.asm b/apple/yzip/rel.9/opsx.asm new file mode 100644 index 0000000..774df57 --- /dev/null +++ b/apple/yzip/rel.9/opsx.asm @@ -0,0 +1,903 @@ + PAGE + STTL "--- X-OPS ---" + + + ; ------ + ; EQUAL? + ; ------ + ; IS [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? + +ZEQUAL: + DEC NARGS ; DOUBLE-CHECK # ARGS + 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!) + + +; ---------------------------- +; ICALL,ICALL1, ICALL2, IXCALL +; ---------------------------- + +ZICALL: +ZICLL1: +ZICLL2: +ZIXCLL: LDA #1 ; SET FLAG FOR RETURNLESS CALL + STA IRET + BNE IENTR ; JMP OVER NORMAL SETTING + + +; ------------------- +; XCALL, CALL1, CALL2 +; ------------------- + +ZXCALL: ; DROP THROUGH +ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +ZCALL2: + +; ---- +; CALL +; ---- +; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +; ([ARG5]-[ARG8] FOR XCALL (EZIP)) + +ZCALL: LDA #0 + STA IRET ; SET FLAG TO RETURN SOMETHING +IENTR: LDA ARG1+LO + ORA ARG1+HI ; IS CALL ADDRESS ZERO? + BNE DOCALL ; NO, CONTINUE + LDA IRET ; any ret value? + BEQ Ij ; yes, so return a zero + + RTS ; otherwise, just end +Ij: + LDX #0 + JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER + LDA OLDZSP+HI + JSR PUSHXA + LDA ZPCL ; AND LSB OF [ZPC] + LDX IRET ; AND RETURN FLAG + 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 + ASL ARG1+LO ; MULTIPLY [ARG1] + ROL ARG1+HI ; (BY 2) + ROL A ; >BIT INTO [A] + ASL ARG1+LO ; BY 4 (EZIP) + ROL ARG1+HI + ROL A + STA ZPCH ; NEW >BIT OF [ZPC] + LDA ARG1+HI ; GET NEW 0, just ignore! + ORA ARG3+LO + BEQ INTNF ; SAY NOT FOUND + + LDA NARGS ; IS THERE A RECORD SPEC? + CMP #4 + BEQ SET4 +SETDEF: LDA #130 ; NO, SET DEFAULT + STA ARG4+LO + +SET4: LDA ARG4+LO + BEQ SETDEF ; GO BACK AND GET VALUE + LDA #0 ; COMPARE BYTE OR WORD? + ASL ARG4+LO + ROL A ; PICK UP INDICATOR + LSR ARG4+LO ; CLEAR FROM RECORD LENGTH + STA TYPE ; BYTE (0) OR WORD (1) + LDA TYPE ; SET FLAG + BNE SETTBL + LDA ARG1+LO ; IF ONLY BYTE, MOVE IT + STA ARG1+HI ; TO FIRST BYTE CHECKED +SETTBL: + LDA ARG2+LO ; PICK UP TBL ADDR + STA MPCL + LDA ARG2+HI + STA MPCM + LDA #0 + STA MPCH ; ONLY A WORD ADDR, SO IN 1ST 64K + JSR VLDMPC + +INTLP: LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + JSR GETBYT ; GET 1ST BYTE + CMP ARG1+HI ; DOES IT = THE VALUE LOOKING FOR? + BNE INTNXT ; NO + LDA TYPE + BEQ INTFND ; ONLY COMPARING A BYTE SO FOUND! + JSR GETBYT + CMP ARG1+LO + BEQ INTFND ; YES, FOUND IT +INTNXT: + LDA VWCUR+0 ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC ARG4+LO ; ENTRY + STA MPCL + BCC INEXT0 + + LDA VWCUR+1 ; PICK UP CARRY + ADC #0 + STA MPCM + LDA VWCUR+2 + ADC #0 + STA MPCH + JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE + +INEXT0: DEC ARG3+LO ; CHECKED ALL ENTRIES? + BNE INTLP + LDA ARG3+HI + BEQ INTNF + DEC ARG3+HI + BNE INTLP + +INTNF: + LDA #0 ; 0 = NOT FOUND + STA VALUE+LO + STA VALUE+HI + JSR PUTVAL + JMP PREDF ; FAILED! + +INTFND: + LDA VWCUR+LO + STA VALUE+LO ; AND SET TO RETURN THE VALUE + LDA VWCUR+HI + STA VALUE+HI + JSR PUTVAL ; SEND IT BACK + JMP PREDS ; AND SCREEM SUCCESS + +; ---- +; BCOM +; ---- +; COMPLEMENT [ARG1] + +ZBCOM: LDA ARG1+LO + EOR #$FF + STA VALUE+LO + LDA ARG1+HI + EOR #$FF + STA VALUE+HI + JMP PUTVAL + + +; ----- +; COPYT +; ----- + +ZCOPYT: + LDA ARG2+LO ; CHECK OUT WHAT'S TO BE DONE + ORA ARG2+HI + BNE ZC0 + JMP CASE1 ; ZERO LENGTH BYTES OF SOURCE +ZC0: + LDA ARG3+HI + CMP #$7F + BCC CASE2 + JMP CASE3 ; FORWARD COPY + + ; CASE2 - CHECK IF FORWARD OR BACKWARD COPY + +CASE2: LDA ARG1+HI ; IF SRC < DEST + CMP ARG2+HI + BCC CHK2 + BEQ ZC1 + JMP FRWRD ; NO +ZC1: LDA ARG1+LO + CMP ARG2+LO + BEQ CHK2 + BCS FRWRD ; NO +CHK2: LDA ARG1+LO ; AND SRC + LENGTH > DEST + CLC + ADC ARG3+LO + STA I+LO + LDA ARG1+HI + ADC ARG3+HI + CMP ARG2+HI + BCC FRWRD ; NO + BNE BKWRD ; YES + LDA I+LO + CMP ARG2+LO + BEQ FRWRD ; DEBUG, IF EQUAL REALLY LESS + BCS BKWRD ; OVERLAPS SO DO BACKWARD COPY + + ; ELSE FALL THROUGH TO FORWARD COPY + +FRWRD: LDA #0 ; USE GETBYT CAUSE MAY BE + STA MPCH ; BEYOND MAIN MEMORY + LDA ARG1+HI + STA MPCM + LDA ARG1+LO + STA MPCL + JSR VLDMPC ; AND ALIGN TO CORRECT PAGE + LDA ARG2+LO + STA SPCL + LDA ARG2+HI + jsr SETPC ; get memory spot + sta SPCH ; high part + sty SPCBNK ; and the bank part + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI +FRLP: + jsr DECJ + bcc FRDUN ; CARRY CLEAR ON $FFFF + jsr GETBYT + jsr STASHB ; and save it + jsr NEXTSPC ; and point to next one + jmp FRLP +FRDUN: + rts + + +BKWRD: + LDA ARG3+LO ; DECR 1ST TO GET CORRECT OFFSET + STA J+LO + LDA ARG3+HI + STA J+HI + JSR DECJ + LDA ARG1+LO ; SET TO END OF SOURCE & DEST. + CLC + ADC J+LO + sta FPCL ; set up fetch pointer + LDA ARG1+HI + ADC J+HI + jsr SETPC ; and get mem locations + sta FPCH + sty FPCBNK + LDA ARG2+LO + CLC + ADC J+LO + sta SPCL ; and now set up stash pointer + LDA ARG2+HI + ADC J+HI + jsr SETPC ; and get me page/bank + sta SPCH + sty SPCBNK +BKLP: + jsr FETCHB ; get byte + jsr STASHB ; and save it + jsr PREVFPC ; going backwards + jsr PREVSPC ; and here too + jsr DECJ ; RETURNS CARRY CLEAR ON $FFFF + bcs BKLP +BKDUN: + RTS + + ; ZERO LENGTH # OF BYTES OF SOURCE + +CASE1: LDA ARG1+LO + STA SPCL ; set stash pointer + LDA ARG1+HI + jsr SETPC ; get page/bank + sta SPCH + sty SPCBNK + LDA ARG3+LO ; SET UP COUNTER + STA J+LO + LDA ARG3+HI + STA J+HI +C1LP: + jsr DECJ ; CARRY CLEAR WHEN J = $FFFF + bcc C1DUN + lda #0 + jsr STASHB ; and zero it + jsr NEXTSPC ; and point to next one + jmp C1LP +C1DUN: + rts + + ; 2'S COMPLEMENT LENGTH (XOR + 1) THEN DO FORWARD COPY + +CASE3: + LDA ARG3+LO + EOR #$FF + STA ARG3+LO + LDA ARG3+HI + EOR #$FF + STA ARG3+HI + INC ARG3+LO + BNE GOFRWD + INC ARG3+HI +GOFRWD: JMP FRWRD + + +; --------- +; ASSIGNED? +; --------- + + +ZASSND: + LDA ARG1+LO ; COMPARE TO # OF OPTIONALS FROM LAST CALL + CMP ASSVLU + BCC DOYES ; IF LESS OR EQUAL, WAS ASSIGNED + BEQ DOYES + JMP PREDF +DOYES: + JMP PREDS + + +; ------------- +; LOGICAL SHIFT +; ------------- +; SHIFT ARG1, ARG2 BITS (LEFT IF ARG2 IS POS. RIGHT IF NEG.) + +ZSHIFT: LDA ARG1+LO ; SET UP FOR SHIFT + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCS SRIGHT + + ; SHIFT LEFT + + TAY ; COUNT +SLP1: ASL VALUE+LO + ROL VALUE+HI + DEY + BNE SLP1 + JMP PUTVAL ; AND RETURN THE VALUE + +SRIGHT: EOR #$FF ; COMPLEMENT + TAY +SLP2: LSR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL SLP2 + JMP PUTVAL + + +; ---------------- +; ARITHMETIC SHIFT +; ---------------- +; PROPAGATING SIGN BIT ON RIGHT SHIFT + +ZASHFT: LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCC ZSHIFT ; SAME AS LOGICAL SHIFT + LDX ARG1+LO ; SET UP FOR SHIFT + STX VALUE+LO + LDX ARG1+HI + STX VALUE+HI + + EOR #$FF ; COMPLEMENT COUNT + TAY +ASLP2: LDA ARG1+HI + ASL A ; GET SIGN BIT + ROR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL ASLP2 + JMP PUTVAL + +; -------- +; XPUSH +; -------- +ZXPUSH: + lda ARG2+LO ; get me the address of the LTABLE + sta FPCL ; for munging with + lda ARG2+HI ; this is page + jsr SETPC ; get me actual page/bank + sta FPCH ; set page + sty FPCBNK ; and bank + + jsr FETCHB ; this is hi part of counter + sta J+HI ; save it + jsr NEXTFPC ; point to lo part + jsr FETCHB ; get it + sta J+LO ; thanx + ora J+HI ; check for zero elements left + bne ZXP0 ; yes, there is room at the inn + + jmp PREDF ; no room here! +ZXP0: + jsr FP2SP ; set up to stash back in beginning of LTABLE + lda J+HI ; now the MSB + sta K+HI ; and saved it + lda J+LO ; save this + sta K+LO ; save it +; +; now count this one and stash it into the table +; + bne ZXP1 ; nope, dec okay + dec J+HI ; decrement MSB +ZXP1: + dec J+LO ; and the LSB + lda J+LO ; LSB first + jsr STASHB ; saved it + jsr PREVSPC ; point to MSB + lda J+HI ; get it + jsr STASHB ; saved it +; +; finally, we can save the arg into the stack +; + asl K+LO ; make a word offset (*2) + rol K+HI ; pick up carry maybe + lda K+LO ; add in arg offset + clc ; adding + adc ARG2+LO ; figger offset + sta SPCL ; this goes here for stashing + lda K+HI ; now page + adc ARG2+HI ; add in start of table + jsr SETPC ; get me memory page + sta SPCH ; page + sty SPCBNK ; and bank + + lda ARG1+HI ; push MSB + jsr STASHB ; saved + jsr NEXTSPC ; point to next one + lda ARG1+LO ; and now LSB + jsr STASHB ; into the stack + jmp PREDS ; show we worked good +;--------- +; ZFSTACK +;--------- +ZFSTACK: + dec NARGS ; how many args there? + bne ZFS1 ; flush ARG2 stack +; +; pop from system stack +; + lda ARG1+LO ; just add number to system counter + clc ; adding + adc ZSP+LO ; added + sta ZSP+LO ; and saved + lda ARG1+HI ; get hi part + adc ZSP+HI ; add in hi part + sta ZSP+HI ; save hi part + rts +ZFS1: + lda ARG2+LO ; get LTABLE we are interested in + sta FPCL ; set up FPC first + lda ARG2+HI ; and page + jsr SETPC ; tell me where + sta FPCH ; save me where + sty FPCBNK ; FPC all set + jsr FP2SP ; have SPC point to stack too + + jsr FETCHB ; get MSB of counter + sta J+HI ; save MSB + jsr NEXTFPC ; point to LSB + jsr FETCHB ; get LSB + sta J+LO ; save LSB + + lda J+LO ; get LSB back + clc ; get ready for add + adc ARG1+LO ; add how many to get rid off + sta J+LO ; save new counter + lda J+HI ; get MSB + adc ARG1+HI ; add MSB + + jsr STASHB ; save Msb of new counter + jsr NEXTSPC ; point to LSB + lda J+LO ; get lsb + jsr STASHB ; okay, reset the counter + rts + +; +; no mouse stuff yet +; +ZMINFO: +ZMLIMIT: + rts +ZMENU: + jmp PREDF ; no menu stuff either + + END diff --git a/apple/yzip/rel.9/pic.asm b/apple/yzip/rel.9/pic.asm new file mode 100644 index 0000000..09d616f --- /dev/null +++ b/apple/yzip/rel.9/pic.asm @@ -0,0 +1,826 @@ + STTL "--- Picture Op Codes ---" + PAGE +PFILE_RD: ; for READING files + db 4 ; 4 parameters + db 0 ; refnum + dw IOBUFF ; read into io buffer + dw $400 ; 1Kb buffer + dw 0 ; length actually read +PFSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +PICCNT: dw 0 ; counter of the entries +PF_REFNUM: db 0 ; place to store refnum +PF_FID: db $FF ; File ID of local directory data +P_IDX: db 0 +P_BCNT: db 0 +P_LOFF: db 0 +GBL_FLAG: db 0 ; found global directory? +PIC_FLAG: db 0 ; found pictures? +PF_NAME: db 0 ; name we are looking at + db 0 ; name we found + +PICINFO: + ds PLDSIZE ; get room for picture data + +TRANSCLR: DB 0 ; transparent color +UNKPIC: + + db EOL,"Unknown Picture #" +UNKPICL EQU $-UNKPIC +ZDISPL: + jsr CLRBUF ; put out any and all text + + jsr GET_PICINF ; get the necessary data + bcc ZDSP1 ; everything just fine + + DLINE UNKPIC ; unknown picture number error + lda ARG1+HI ; get MSB + jsr HEXNUM ; print it + lda ARG1+LO ; and LSB + jsr HEXNUM + lda #$14 ; bad picture number error + jmp ZERROR ; and croak +ZDSP1: + jsr SAVE_CURSOR ; save the cursor + + lda #0 ; show no cursor change + sta CURSFLG ; start with none, anyway + + dec NARGS ; x,y pos passed? + beq ZDSP10 ; nope, just use as is + + lda ARG2+LO ; get passed y pos + beq ZDSP01 ; don't change + sta SCRCY ; change, then + dec SCRCY ; zero base it + ldy #WINTOP ; get top edge of window + lda (WINDOW),Y ; got it + clc ; get ready for add + adc SCRCY ; add the offset + sta SCRCY ; and make it Y pos + lda #1 ; show cursor change anyway + sta CURSFLG ; okay, we did +ZDSP01: + dec NARGS ; x pos passed? + beq ZDSP10 ; nope + + lda ARG3+LO ; get x pos + beq ZDSP10 ; if == 0, don't change + sta SCRCX ; set as passed + dec SCRCX ; zero base it + ldy #WINLEFT ; get left hand edge of window + lda (WINDOW),Y ; got it + clc ; get ready for add + adc SCRCX ; add the offset + sta SCRCX ; and make it X pos + lda #1 ; show cursor change anyway + sta CURSFLG ; okay, we did +ZDSP10: + lda SCRCX ; get current X + pha ; save it + clc ; adding + adc PICINFO+PLDWID ; add in pic width + sta SCRCX ; save here + pla ; get start X pos back + sta SCRCX ; restored +ZDSP101: + lda PICINFO+PLDFLG ; get flag byte + and #1 ; is there a transparent color? + bne ZDSP11 ; ayyup + lda #$FF ; make TRANSCLR be $FF + bne ZDSP12 ; okay +ZDSP11: + lda PICINFO+PLDFLG ; get hi byte of flag word + lsr A ; put in lower byte + lsr A ; put in lower byte + lsr A ; put in lower byte + lsr A ; put in lower byte +ZDSP12: + sta TRANSCLR ; save transparent color + + lda PICINFO+PLDPTR ; MSB of offset + sta PFSEEK+SM_FPOS+2 ; MSB of seek + lda PICINFO+PLDPTR+1 ; Middle + and #$FE ; seek only to 512byte boundary + sta PFSEEK+SM_FPOS+1 + + SET_MARK PFSEEK ; go to pic data + lda #>PIC1BUF ; set up pointers to decode buffers + sta J+HI + lda #PIC2BUF + sta K+HI + lda #IOBUFF ; now get data buffer address + sta L+HI + lda #4 ; 4 pages read in at once + sta P_BCNT ; okay + lda #3 ; 3 bytes of width data start it + clc ; doing add + adc PICINFO+PLDPTR+2 ; pick up LSB pointer + sta P_IDX ; start index + bcc ZDLPCC ; no wrap + inc L+HI ; start at second one + dec P_BCNT ; one less block +ZDLPCC: + lda PICINFO+PLDPTR+1 ; tells which block it is in + and #$01 ; pick up which 256 block + beq ZDLP0 ; start at first one + inc L+HI ; start at next one + dec P_BCNT ; one less block +ZDLP0: + lda #IOBUFF ; reset data buffer address + sta L+HI + lda #GBL_DIR ; start destination off here + jsr READ_IN_PDATA ; go get global directory, if any + sta GBL_FLAG ; indicate whether there is a global +GTPG1: + lda SAVENUM ; get which file is being opened + and #$0F ; just make it binary + cmp PF_FID ; same as the file we already have? + beq GETPGX ; yes, so don't bother + ldy #SGTPICOF ; point to picture offset + lda #>PIC_DIR ; start destination off here + jsr READ_IN_PDATA ; go get the data for local pictures + sta PIC_FLAG ; any picture data +GETPGX: + rts +; +; READ_IN_PDATA - check for desired data being in file, and skip to it if +; it is. Then, read it in in 1Kb chunks, stashing it away into the +; upper bank of the aux mem language card. +; Enter with: +; [A] = Destination page +; [Y] = Offset into Segment table +; +READ_IN_PDATA: + pha ; save destination page + lda (DSEGS),Y ; get MSB + sta PFSEEK+SM_FPOS+2 ; Byte 2 + iny ; point to LSB + ora (DSEGS),Y ; is there any pic data? + bne GTPD00 ; yes + pla ; get page back + lda #0 ; show not here + rts ; nope +GTPD00: + lda (DSEGS),Y ; get it for shifting + asl A ; *2 + sta PFSEEK+SM_FPOS+1 ; stash away + rol PFSEEK+SM_FPOS+2 ; pick up carry + lda #0 ; clear out MSB + sta PFILE_RD+RD_BUFFLEN+HI + sta PFSEEK+SM_FPOS ; and LSB of seeking + + lda PF_REFNUM ; get file ref number + sta PFILE_RD+RD_REFNUM ; and save it for reading and + sta PFSEEK+SM_REFNUM ; for seeking + + lda #RETRY_COUNT ; set retry + sta NY_DATA ; just use this for now +GTPDRD0: + SET_MARK PFSEEK ; and go to beginning + + lda #4 ; read in 4 256 blocks + sta PFILE_RD+RD_BUFFLEN+HI + READ PFILE_RD ; go get the next 4Kb worth + bcc GTPD1 ; fine + jsr RETRY ; well, do it again? + bcc GTPDRD0 ; yes +GTPD1: + pla ; get destination page back + cmp #>PIC_DIR ; if doing local directory, set up + bne GTPD2 ; picture count + ldx IOBUFF+PHNLD ; get number of pictures + stx PICCNT+HI ; save for count down too + ldx IOBUFF+PHNLD+1 ; and here is LSB + stx PICCNT+LO ; saving for counting + ldx IOBUFF+PHFID ; get file ID + stx PF_FID ; and save for later + ldx #(256/PLDSIZE) ; how many entries in 256 bytes + bne GTPD3 ; done +GTPD2: + ldx IOBUFF ; get MSB of how many + stx PICCNT+HI ; show me + ldx IOBUFF+1 ; get LSB of count + stx PICCNT+LO + ldx #(256/2) ; how many entries / 256 bytes +GTPD3: + stx GTPMOD+1 ; set up how big entry is + sta ALTZP+AUX ; use aux mem for most of this + sta K+HI ; MSB of destination + lda #0 ; clear a few things + sta J+LO ; J = source + sta K+LO ; K = destination + lda #4 ; 4 * (4*256) bytes max + sta PFILE_RD+RD_BUFFLEN+HI ; show the read too + sta P_IDX ; save here for counting +GTPDL: + ldy #0 ; start y + lda #>IOBUFF ; get where source is + sta J+HI ; MSB of source + lda #4 ; 4 blocks worth of 256 + sta P_BCNT ; used as counter + lda BNK1SET ; we be using bank 1 @$D000 + lda BNK1SET ; we be using bank 1 @$D000 +GTPDL1: + lda (J),Y ; get the data byte + sta (K),Y ; store in upper aux + iny ; point to the next one + bne GTPDL1 ; and go get it + + inc J+HI ; next block please + inc K+HI ; for destination too + lda PICCNT+LO ; how many entries? + sec ; doing sbc +GTPMOD: sbc #(256/PLDSIZE) ; how many entries in 256 bytes? + sta PICCNT+LO ; save result + bcs GTPDL2 ; no wrapping + dec PICCNT+HI ; wrap + bmi GTPDLX ; all done if we go negative +GTPDL2: + ora PICCNT+HI ; make sure both are not zero + beq GTPDLX ; if they are, then we are done + dec P_BCNT ; count this block + bne GTPDL1 ; go fetch next 256 bytes + sta ALTZP+MAIN ; swap back to main for read + + lda #RETRY_COUNT ; set retry + sta NY_DATA ; just use this for now +GTPDRD: + READ PFILE_RD ; go get the next 4Kb worth + bcc GTPDRDG ; fine + jsr RETRY ; well, do it again? + bcc GTPDRD ; yes +GTPDRDG: + sta ALTZP+AUX ; and back to aux for working + dec P_IDX ; max 4Kb worth of reading + bne GTPDL ; and read in more +GTPDLX: + sta ALTZP+MAIN ; back to main bank of mem + lda BNK2SET ; back to bank 2 + lda BNK2SET ; yes please + lda #1 ; show we found it + rts ; all done + +GTPFLAG: db 0 ; if 1 when opening next file, then + ; this is the next file, so unable to + ; find picture number +GET_PICINF: + lda #0 ; set flag for double check + sta GTPFLAG ; start at zero +GTPLOOP: + lda ARG1+LO ; check argument for zero + ora ARG1+HI ; is it zero? + bne GTPINDX ; jump to look at first block + clc ; found some pictures + rts ; if zero, just give count +GTPINDX: + ldy ARG1+LO ; get arg, as we are swapping + ldx ARG1+HI ; to aux mem + sta ALTZP+AUX ; look at AUX mem + lda BNK1SET ; bank 1 + lda BNK1SET ; bank 1 + lda PIC_DIR+PHNLD ; get # of entries + sta PICCNT+HI + lda PIC_DIR+PHNLD+1 ; it's in reverse order + sta PICCNT+LO + sty ARG1+LO ; use aux mem zero page + stx ARG1+HI ; for new arg1 + lda #>PIC_DIR ; start at beginning of block + sta MPNTH ; hi part + lda #GBL_DIR ; start at beginning of block + sta MPNTH ; hi part + lda #GE< 1 WORD, CONTINUE + BNE FWM1 + LDA VWLEN+1 + BNE FWM1 + LDA VWLEN+0 + CMP ESIZE + BCC FWFAIL +FWM1: + JMP FWLOOP ; AND TRY AGAIN + +FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD + STA VALUE+LO + LDA VWCUR+1 + STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY + RTS ; WORD VALUE RETURNABLE +FWFAIL: + LDA #0 ; NOT FOUND + STA VALUE+LO + STA VALUE+HI + RTS ; THEN RETURN WITH [VALUE] = 0 +; +; DO UNSORTED SEARCH ON VOCAB TBL IN MPC +; +UNSORTED: + LDA #$FF ; 2'S COMPLEMENT LENGTH + EOR NENTS+HI ; TO GET REAL LENGTH + STA NENTS+HI ; WAS NEGATIVE TO SIGNIFY + LDA #$FF ; UNSORTED VOCAB TBL + EOR NENTS+LO + STA NENTS+LO + INC NENTS+LO ; 2'S CMPL + BNE UNSRT0 + INC NENTS+HI +UNSRT0: + LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + + JSR GETBYT ; GET 1ST BYTE OF ENTRY + CMP OUT ; MATCH 1ST BYTE OF TARGET? + BNE FNEXT ; LESS + JSR GETBYT + CMP OUT+1 ; 2ND BYTE MATCHED? + BNE FNEXT + JSR GETBYT + CMP OUT+2 ; 3RD BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+3 ; 4TH BYTE + BNE FNEXT + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + +FNEXT: LDA VWCUR+LO ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC ESIZE ; ENTRY + STA MPCL + BCC FNEXT0 + + LDA VWCUR+HI ; PICK UP CARRY + ADC #0 + STA MPCM + LDA #0 + STA MPCH + JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE + +FNEXT0: DEC NENTS+LO ; CHECKED ALL ENTRIES? + BNE UNSRT0 + LDA NENTS+HI + BEQ FWFAIL ; GO INDICATE NO FIND + DEC NENTS+HI ; OR DO NEXT 256 ENTRIES + JMP UNSRT0 + + END + \ No newline at end of file diff --git a/apple/yzip/rel.9/screen.asm b/apple/yzip/rel.9/screen.asm new file mode 100644 index 0000000..3b6b22e --- /dev/null +++ b/apple/yzip/rel.9/screen.asm @@ -0,0 +1,948 @@ + STTL "--- APPLE ][ SCREEN STUFF ---" + PAGE + +; ----------------- +; PRINT CHAR IN [A] AT CV,CH +; ----------------- +; +; uses memory register [L] +; +SAVECY DB 0 ; spot to save current screen y pos +SAVECX DB 0 ; spot for x pos + +CHAR: + sta IOCHAR ; SAVE HERE + txa ; SAVE [X] AND [Y] + pha + tya + pha + + lda IOCHAR ; get it back + cmp #BACKSPACE ; is it backspace with erase? + bne CHCX ; nope + + jmp DO_BSPC ; so handle backspace +CHCX: + cmp #EOL ; is it ? + bne CHCONT ; just let dline handle it + + jmp DO_EOL ; handle +; +; so save some stuff and do all the necessary figgering +; +CHCONT: + ldx SCRCNT ; just stash character + sta SCRBUFF,X ; save it + inc SCRCNT ; and count it +CH_EXIT: + pla ; RESTORE [X] AND [Y] + tay + pla + tax + rts +; +; PUT_NYBBLE - put 4 bits to the screen at SCRCX, SCRCY (the lower 4 bits +; in [A]). +; +PUT_NYBBLE: + sta NY_DATA ; save [A] for mucking with + jsr SETPOS ; set up offsets using SCRCX + + lda #$8 ; start at first bit, left to right + sta DATALOOP ; and init the counter with it +PNY0: + ldx FPCBNK ; which bank + lda PAGE2SW,X ; select it + ldy #0 ; start with zero + lda (FPC),Y ; get it + sta SCR_DATA ; and save it +PNY1: + ldx BITOFF ; get which interesting bit we want + lda GT_BITS,X ; get bit + pha ; save bit pictures + lda DATALOOP ; see if we have done all 4 bits in this 'pixel' + beq PNY_EXIT ; toots finis + lsr DATALOOP ; point to next bit + bit NY_DATA ; is this bit set? + bne PNY_SET ; yes it is, so we will handle different +; +; Bit is clear, so clear appropriate one in the SCR_DATA byte +; + pla ; get bit picture back + eor #$FF ; turn bits all around + and SCR_DATA ; turn off bit in screen data + jmp PNY_NEXT ; and continue +PNY_SET: + pla ; get bit mask back + ora SCR_DATA ; turn on bit +PNY_NEXT: + sta SCR_DATA ; save result + inc BITOFF ; we're looking at next bit + lda BITOFF ; now check how we're doing + cmp #7 ; only doing bits 0-6 + bne PNY1 ; check next bit +; +; we've finished this byte in screen memory, point to next one +; + lda #0 ; start at zero'th bit + sta BITOFF ; thank you + lda SCR_DATA ; now stash this one in the screen + sta (FPC),Y ; y is still zero; still pointing to bank + jsr NEXT_SCR ; make SPC/FPC point to next spot + jmp PNY0 ; and continue on please +; +; all done, so make sure we stash anything out there +; +PNY_EXIT: + pla ; get bit mask back to fix stack + lda SCR_DATA ; put away the current data byte + sta (FPC),Y ; y is still zero; still pointing to bank + lda PAGE2SW+MAIN ; back to MAIN page 2 + rts +; +; NEXT_SCR - make FPC/SPC point to next screen byte +; +NEXT_SCR: +; +; if in main bank, when we go to aux bank, we need to look at the next +; byte in memory +; + lda FPCBNK ; get what bank we're talking to currently + bne NXS0 ; 0 = main bank, 1 = aux bank + inc SPCL ; point to next byte + inc FPCL ; and for fetching + lda #AUX ; and point to aux bank + bne NXS1 ; (BRANCH) and continue on +; +; if in aux bank, all we need to do is switch banks +; +NXS0: + lda #MAIN ; just make it main bank +NXS1: + sta SPCBNK ; for stashing and + sta FPCBNK ; fetching + rts +; +; GET_NYBBLE - get the 4 bits which represent the screen at position +; SCRCX, SCRCY; return nybble in low 4 bits of [A] +; +GT_BITS: db 1,2,4,8,$10,$20,$40 +GET_NYBBLE: + jsr SETPOS ; set up offsets using SCRCX + + lda #0 ; clear out my data spot + sta NY_DATA ; for mucking with + + lda #$10 ; setting bits 0-3, starting with shift + sta DATALOOP ; so init the setter +GNY0: + ldx FPCBNK ; which bank + lda PAGE2SW,X ; save which bank + ldy #0 ; zero y + lda (FPC),Y ; get byte + sta SCR_DATA ; and save it +GNY1: + lsr DATALOOP ; see if we have done all 4 bits in this 'pixel' + beq GNY_EXIT ; all done! + + ldx BITOFF ; get bit offset + lda GT_BITS,X ; get bit pattern +; +; now check appropriate bit in Screen Data +; + and SCR_DATA ; see if it is set + beq GNY3 ; no bit set here +; +; bit is set, so set it in my data nybble +; + lda DATALOOP ; get bit setter + ora NY_DATA ; and put it into my data byte + sta NY_DATA ; and save it +GNY3: + inc BITOFF ; we're looking at next bit + lda BITOFF ; now check how we're doing + cmp #7 ; only doing bits 0-6 + bne GNY1 ; check next bit +; +; we've finished this byte in screen memory, point to next one +; + lda #0 ; start at zero'th bit + sta BITOFF ; thank you + jsr NEXT_SCR ; point to next byte + jmp GNY0 ; and continue on please +GNY_EXIT: + lda PAGE2SW+MAIN ; back to main page 2 + lda NY_DATA ; get the nybble desired + rts +; +; SETPOS - get the byte offset and the bit offset from the table using +; SCRCX +; +; USES: SCRCX, SCRCY +; SETS: FPC - pointer to correct screen memory location +; BITOFF - bit offset to get to start of byte (N.B. this is left to +; right count, while in memory it is right to left!) +SETPOS: + lda SCRCX ; get the x pos + tax ; put where we can use it + lda XPOSTBL,X ; get byte # + sta FPCL ; okay, saved + lda XBITTBL,X ; get bitoffset + sta BITOFF ; where it wants it + + lda FPCL ; check for correct bank + and #$01 ; if odd, then must be main bank + bne STP11 ; okay, it be odd + lda #AUX ; aux bank + bne STP22 ; jump +STP11: + lda #MAIN ; main bank +STP22: + sta FPCBNK ; save it + lda FPCL ; get for fetch + lsr A ; /2 to get correct byte offset + ldx SCRCY ; get vertical pos + clc ; get ready for adding + adc BASEL,X ; add low part + sta FPCL ; save low part + lda BASEH,X ; get high part + sta FPCH ; save high part + rts ; done !? +; +; DO_EOL - if this is end of line, check if we are at end of window +; and if we are, and it is a scrollable window, scroll. Then move +; the cursor to the left margin of said window +; +DO_EOL: + jsr DISP_LINE ; make sure line gets out there + lda SCRCY ; get current vertical pos + clc ; add font height + adc #FONT_H ; thank you + pha ; save this position + adc #FONT_H ; make sure we have room for characters here + cmp SCRBTM ; so check against the bottom + beq SAVECV ; no scroll yet + bcs SCROLLCITY ; nope, can't use it +SAVECV: + pla ; get new CV + sta SCRCY ; and save it + bne DEL1 ; JUMP +SCROLLCITY: + pla ; get bad y pos + lda SCRLFLG ; is this a scrolling window? + beq DEL1 ; nope, just move to left edge + jsr SCROLL_UP ; and scroll window +DEL1: +; +; move cursor back to left margin +; + lda LEFTMRG ; get left margin + sta SCRCX ; and set itpositions + lda #1 ; show cursor changed (maybe) + sta CURSFLG ; okay + lda #0 ; clear length too + sta LENGTH+LO ; no more on line + sta LENGTH+HI ; no more on line + jmp CH_EXIT ; now finish it up +; +; DO_BSPC - do a backspace, by erasing char just before cursor to +; background color, and moving cursor back one space +; [X] == character to delete +; +SAVECHX: DW 0 + +DO_BSPC: + lda CHR_X+LO ; figger new CHR_X + sec ; subtract width + ldy FONTFLG ; get which font we be using + beq DOBSP0 ; must be variable width + sbc #MONOFONT_W ; get width then of mono font + jmp DOBSP1 ; okay, now do add +DOBSP0: + sbc CHWID,X ; get width of char to be erased +DOBSP1: + sta CHR_X+LO ; show new one + sta SAVECHX+LO ; save to restore later + lda CHR_X+HI ; and pick up carry + sbc #0 ; okay, did it + sta CHR_X+HI ; save it + sta SAVECHX+HI ; okay + ldy #SPACE ; get SPACE offset + lda FONTFLG ; monospaced font? + beq DOBSP2 ; nope + lda #MONOFONT_W ; make monospaced wide + bne DOBSP3 ; fine +DOBSP2: + lda CHWID,X ; get width of char +DOBSP3: + sta CHWID,Y ; set space to be this wide + sty SCRBUFF ; make space for erasing + lda #1 ; show one char + sta SCRCNT ; assume it used to be zero + jsr DISP_LINE ; put that space out + lda SAVECHX+LO ; restore old/new x pos + sta CHR_X+LO + lda SAVECHX+HI + sta CHR_X+HI + jsr GET_SCRCX ; update SCRCX please + + lda #SPACE_WIDTH ; restore width of space char + ldy #SPACE ; get offset + sta CHWID,Y ; okay + + jmp CH_EXIT ; done +; +; CLS - clear the window, using CLS parameters +; +CLS: + lda SCRCX ; save the current X,Y + sta SAVECX ; x + lda SCRCY + sta SAVECY ; saved + lda CLSTOP ; get top line + sta SCRCY ; and set up a y pos + + jsr SETMASK ; set up masks and ending point + + lda CPY_COUNT ; get count + sta SH_LOOP ; save count + lda CLSLEFT ; get left edge + sta SCRCX ; set up as X pos + ldy #WINBGND ; get background offset + lda (WINDOW),Y ; get background color + sta ARG8 ; save it here + lda CLSWIDTH ; how wide we be? + bne CLSOKAY ; not a zero width + lda #25 ; zero can't do zero width + jmp ZERROR ; so die +CLSOKAY: + cmp #3 ; if skinny, handle special + bcs L1L0 ; nope + sta ARG7 ; make this be the counter + lda CLSHEIGHT ; just use PUT/GET NYBBLE if only one wide + bne CLSOKAY1 ; not a zero height either + lda #25 ; bad error + jmp ZERROR +CLSOKAY1: + sta J ; save here +CLS1W: + lda ARG8 ; get color + jsr PUT_NYBBLE ; put it + inc SCRCX ; next x + dec ARG7 ; counter + bne CLS1W ; do next X + lda CLSLEFT ; get left edge again + sta SCRCX ; point to it + inc SCRCY ; next line + lda CLSWIDTH ; restore width count + sta ARG7 ; thanks + dec J ; count + bne CLS1W ; do it + beq CLSEXIT ; all done then +L1L0: + sta J ; use j as counter +L1L: + lda ARG8 ; a color please + jsr PUT_NYBBLE ; do first line easy + inc SCRCX ; next nybble + dec J ; done yet? + bne L1L ; nope + + lda CLSLEFT ; where is left column + sta SCRCX ; here! + jsr SETPOS ; get the address + jsr FP2SP ; SPC is source PC, now! + lda CLSHEIGHT ; how many lines are we clearing + bne CLSOKAY2 ; not a zero height either + lda #25 ; bad error + jmp ZERROR +CLSOKAY2: + sta J ; j is counter again + dec J ; already cleared one line + beq CLSEXIT ; only one line to do! +CLSLOOP: + lda SPCH ; now, modify COPY_LINE + sta CPY_MOD1_SRC+HI + sta CPY_MOD2_SRC+HI + lda SPCL + sta CPY_MOD1_SRC+LO + sta CPY_MOD2_SRC+LO + inc SCRCY ; clear this line + jsr SETPOS ; where am i? + lda FPCH ; now, modify COPY_LINE + sta CPY_MOD1_DST+HI + sta CPY_MOD2_DST+HI + lda FPCL + sta CPY_MOD1_DST+LO + sta CPY_MOD2_DST+LO + lda SH_LOOP ; get count + sta CPY_COUNT ; and save it + jsr COPY_LINE ; did the copy (i hope) + dec J ; count it + bne CLSLOOP ; next one please +CLSEXIT: + lda SAVECX ; get X,Y back + sta SCRCX ; got it + lda SAVECY ; now for y + sta SCRCY ; restored! + + rts +; +; SETMASK - figger out the start and end masks, as well as setting +; stuff to point to stopping address. Use CLSLEFT and CLSWIDTH +; +ST_BITS: db 0,1,3,7,$f,$1f,$3f +SETMASK: + lda CLSLEFT ; munge with SCRX + sta SCRCX ; okay + jsr SETPOS ; get me the bit offset of start + + ldx BITOFF ; now set up mask + lda ST_BITS,X ; get the bit pattern + sta STMASK ; save it + + lda CLSLEFT ; get left edge again + clc ; add width + adc CLSWIDTH ; to get where to stop + tax ; make index + stx SCRCX ; set cur pos + lda XPOSTBL,X ; get how many bytes + ldx CLSLEFT ; subtract from byte offset of start + sec ; subbing + sbc XPOSTBL,X + sta CPY_COUNT ; and save it + + jsr SETPOS ; so get its address + + ldx BITOFF ; get bit offset + lda ST_BITS,X ; get pattern + sta ENDMASK ; okay! + rts +; +; SCROLL_UP - roll the current window by FONT_H lines +; +SCROLL_UP: + lda #FONT_H ; show one line + sta SCLLINES ; done + sta SCLDIR ; show scroll up with positive number + ldy #WINTOP ; get top of screen + lda (WINDOW),Y ; got it + sta CLSTOP ; saved it + iny ; point to left edge + lda (WINDOW),Y ; get left edge + sta CLSLEFT ; save + iny ; this is now the height + lda (WINDOW),Y ; get window height + sta CLSHEIGHT ; show me + iny ; and now for the width + lda (WINDOW),Y ; get width + sta CLSWIDTH ; saved it + ; so fall thru + ; and do the scrolling +; FALLING THRU +; | +; \ / +; +; +; DO_SCROLL - scroll SCLLINES withing the window as defined by +; CLSLEFT,TOP,WIDTH, and HEIGHT +; +DO_SCROLL: + lda SCRCX ; save the current X,Y + sta SAVECX ; x + lda SCRCY + sta SAVECY ; saved + lda SCLLINES ; how many lines? + + ldx SCLDIR ; which direction? + bpl SC1 ; >0 means scroll up +; +; scroll down, so we are going to start at the bottom and copy downwards +; until we reach the top +; +; now modify code so we do adds to get destination line and subtracts +; to get new src line +; + ldy #$C6 ; 'dec' opcode + bne SC2 ; jump to modify +SC1: +; +; scroll up - start at top and copy upwards until we reach the bottom +; + ldy #$E6 ; 'inc' opcode + ldx SCLLINES ; get # of scrolling lines +SC2: + sty SCMOD1 ; make inc/dec + sty SCMOD2 ; either inc or dec + stx SCOFF ; save the offset between SRC and DST + + lda SCLDIR ; which direction? + bpl SC3 ; must be normal scroll +; +; if scrolling downwards, we need to start source at bottom-offset and +; end when the destination is at top+offset +; + lda CLSHEIGHT ; get # of lines in window + sec ; subbing + sbc SCOFF ; subtract offset to get source + clc ; adding + adc CLSTOP ; and get absolute position + tax ; put in X + dex ; for 0 offset it + lda CLSTOP ; now figger last line to copy + clc ; adding + adc CLSHEIGHT ; get me last line + tay ; for later storage + dey ; make 0 based + bne SC4 ; always jumps +SC3: +; +; if scrolling upwards, start src at top+offset and end when destination +; is at bottom-offset +; + lda CLSTOP ; get top + clc ; adding + adc SCOFF ; add in offset + tax ; for later on + ldy CLSTOP ; first destination is top of window +SC4: + stx SCRCY ; Starting Source + sty SCROLLY ; Starting Destination + + jsr SETMASK ; set the masks and horizontal endpoint + lda CPY_COUNT ; save for future generations + sta SH_LOOP ; save it + lda CLSHEIGHT ; how high + sta DATALOOP ; save as counter + sec ; for subbing + sbc SCOFF ; subtract scrolling amount + sta CLSHEIGHT ; this is how many lines to copy + lda SCRCY ; save Start Source + pha + lda CLSTOP ; start at Y pos + sta SCRCY + lda CLSLEFT ; and x pos + sta SCRCX ; thank you + lda PAGE2SW+MAIN ; make sure main memory page is in there +SCRL1: + jsr SETPOS ; set up line pointer + ldy SCRCY ; get top + cpy #120 ; 120 bytes per list + bcc SCRLY ; all set + tya ; for adding + clc + adc #8 + tay +SCRLY: + lda FPCH + sta SV_PCH,Y + lda FPCL + sta SV_PCL,Y + inc SCRCY ; next line please + dec DATALOOP + bne SCRL1 + + pla ; get StartSource back + sta SCRCY + lda FPCBNK ; init SPC bank too + sta SPCBNK ; fine, we did +SCROLLING: + ldy SCRCY ; get source Y for index + cpy #120 ; jump over junk + bcc SCLYY + tya + clc + adc #8 + tay +SCLYY: + lda SV_PCH,Y + sta SPCH + sta CPY_MOD1_SRC+HI + sta CPY_MOD2_SRC+HI + lda SV_PCL,Y + sta CPY_MOD1_SRC+LO + sta CPY_MOD2_SRC+LO + sta SPCL + + ldy SCROLLY ; get destination Y pos + cpy #120 ; jump over junk + bcc SCLYY1 + tya + clc + adc #8 + tay +SCLYY1: + lda SV_PCH,Y + sta FPCH + sta CPY_MOD1_DST+HI + sta CPY_MOD2_DST+HI + lda SV_PCL,Y + sta CPY_MOD1_DST+LO + sta CPY_MOD2_DST+LO + sta FPCL + + lda SH_LOOP ; get byte counter + sta CPY_COUNT ; show copy line + jsr COPY_LINE ; and do the copy +SCMOD1: inc SCRCY ; inc or dec to get next one +SCMOD2: inc SCROLLY ; inc/dec for next destination Y + dec CLSHEIGHT ; count down + bne SCROLLING ; nope + + ldx SCLDIR ; scroll up or down? + bpl SCLCLR1 ; clear a little different +; +; if scrolling down, clear from current Y+1 +; + lda SCRCY ; get current source + sta CLSTOP ; save in top spot + inc CLSTOP ; get inside window + jmp SCLCLR2 +SCLCLR1: + lda SCROLLY ; get last destination + sta CLSTOP ; and save it +SCLCLR2: + lda SCOFF ; and both clear this many lines + sta CLSHEIGHT ; okay? + + lda SAVECX ; now restore X and Y + sta SCRCX ; x + lda SAVECY ; and + sta SCRCY ; y + + jsr CLS ; WIDTH and LEFT should be okay still + + rts +; +; CLREOL - clear from current cursor position to end of line by +; using CLS after changing the window size +; +CLREOL: + lda SCRCX ; and make left be where cursor is + sta CLSLEFT + lda SCRCY ; and top be where Y is + sta CLSTOP + lda #FONT_H ; and bottom be bottom of char + sta CLSHEIGHT + ldy #WINWID ; get width + lda (WINDOW),Y ; got it + clc ; now adding + ldy #WINLEFT ; the left edge + adc (WINDOW),Y ; to get the right edge + sec ; subbing + sbc CLSLEFT ; and subtract left to get width + ldy #WINRM ; remove the size of the right margin + sbc (WINDOW),Y ; that too + sta CLSWIDTH ; okay? + jmp CLS ; now clear the screen +; +; COPY_SCRL - copy from SCR_LINE onto the screen. CH_OFFSET says how +; many bytes in SCR_LINE to copy. FPC is assumed to be pointing +; to start of screen bytes. BITTER has the original BITOFF from +; SETPOS. ENDBIT shows how many significant bits in last byte. +; +COPY_SCRL: + ldx SHOW_CURSOR ; are we showing the cursor (ugh) + beq COPYL2 ; nope + jmp DO_CURSOR ; then XOR cursor in +COPYL2: + ldy #WINBGND ; get background offset + lda (WINDOW),Y ; get current background color + beq COPY_SCRL1 ; if black, ignore this + jsr FIX_COLOR ; or in the color, please +; +; Alternate entry point for COPY_SCRL, used by picture drawing routine +; to avoid using background color and checking for cursor +; +COPY_SCRL1: + ldx FPCBNK ; set up bank + lda PAGE2SW,X ; set first bank + lda ENDBIT ; did we end evenly? + bne COPYL22 ; nope + inc CH_OFFSET ; make CH_OFFSET be a counter +COPYL22: + ldy #0 ; zero y + + lda CH_OFFSET ; if only one, then handle real special + bne COPYL21 ; nope + + ldx BITTER ; get starting bit offset + lda ST_BITS,X ; get starting bit mask + sta IOCHAR ; save it + ldx ENDBIT ; get ending bit offset + lda ST_BITS,X ; combine with ending mask bits + eor #$FF ; set for good ones + ora IOCHAR ; set up mask for bits + and (FPC),Y ; get me interesting bits + sta (FPC),Y ; save + lda IOCHAR ; get flag for data + eor #$FF ; flip to get good data +CPYSM1: and SCR_LINE ; pick up my bits + ora (FPC),Y ; and or in screen data + sta (FPC),Y ; and save it + jmp COPYLEX ; go away now +COPYL21: + lda CH_OFFSET ; get # of chars + lsr A ; /2 get number in this bank + adc #0 ; pick up carry for first one + sta DATALOOP ; and save it to work on + + ldx BITTER ; do we have a weird start? + beq DLL2 ; nope +; +; need to do the first one special +; + lda (FPC),Y ; get byte + and ST_BITS,X ; get masking bits + sta IOCHAR ; save for later + lda ST_BITS,X ; get masking bits again + eor #$FF ; get good bits +CPYSM2: and SCR_LINE ; get first data byte + ora IOCHAR ; pick up screen bits + sta (FPC),Y ; pointing + iny ; next byte + ldx #2 ; start at next one for this bank + dec DATALOOP ; kount as done +COPYLOOP: + beq CPYLP2 ; all done with this part of line +DLL2: +CPYSM3: lda SCR_LINE,X ; get data + sta (FPC),Y ; pointing + iny ; next byte + inx ; next one + inx ; next one + dec DATALOOP ; count as used + bpl COPYLOOP ; start loop again +CPYLP2: + ldy #0 ; reset Y + lda FPCBNK ; which bank were we at + eor #1 ; swap to other one + tax ; make it in x + lda PAGE2SW,X ; swap to write bank + txa ; check which one + beq CPYLP23 ; correct offset + iny ; fix offset if going from main to aux +CPYLP23: + ldx #1 ; start at second byte in screen line + lda CH_OFFSET ; get starting number + lsr A ; /2 to get how many for this bank + sta DATALOOP ; and show it +COPYLOOP2: + beq LINE_DONE ; all done with this part of line + +CPYSM4: lda SCR_LINE,X ; get data + sta (FPC),Y ; pointing + iny ; next byte + inx ; next one + inx ; next one + dec DATALOOP ; count as used + bpl COPYLOOP2 ; start loop again +LINE_DONE: +; +; do the last byte special +; + stx DATALOOP ; save pointer + lda ENDBIT ; get ending bit offset + beq COPYLEX ; all done if nothing funky + lsr CH_OFFSET ; get line offset + pha ; save [A] + bcs LINED1 ; if odd, point at right things + dec DATALOOP ; one less then + ldx FPCBNK ; get original bank + lda PAGE2SW,X ; switch to it + txa ; which bank did we do? + bne LINED1 ; no need to step back one + dey ; point one less here too +LINED1: + pla ; get ENDBIT back + tax ; make end bits be index + lda ST_BITS,X ; get end mask + sta IOCHAR ; save mask bits + eor #$FF ; toggle every bit + and (FPC),Y ; get the interesting bits in byte + sta (FPC),Y ; save it + ldx DATALOOP ; get data pointer +CPYSM5: lda SCR_LINE,X ; turn on my bits + and IOCHAR ; pick up my good bits + ora (FPC),Y ; bring everything together + sta (FPC),Y ; save the byte +COPYLEX: + lda PAGE2SW+MAIN ; back to main, thanks + rts + +FIX_COLOR: + inc CH_OFFSET ; just to make checking easier for now + + asl A ; *2 + asl A ; *4 to get correct offset + adc #COLORS ; get hi part + adc #0 ; pick up maybe carry + sta COLORP+HI ; save pointer + ldx #$11 ; ORA (),Y opcode + ldy #WINFORE ; check foreground color + lda (WINDOW),Y ; check what color + bne FIXC1 ; just leave white if not black + ldx #0 ; start at beginning +FIXMUNGEL: + lda SCR_LINE,X ; get byte + eor #$FF ; swap all the bits + sta SCR_LINE,X ; store back + inx ; count it + cpx CH_OFFSET ; done? + bcc FIXMUNGEL ; nope + ldx #$31 ; AND (),Y opcode +FIXC1: + stx FCLM ; self mod my code (again . . . sigh) + lda BITTER ; get starting offset + and #3 ; pick up wrap + tay ; make index + ldx #0 ; start at zero line +FIXLOOP: +FCM1: lda SCR_LINE,X ; get screen byte +FCLM: ora (COLORP),Y ; or with color byte +FCM2: sta SCR_LINE,X ; save it + iny ; next color byte + cpy #4 ; wrapped? + bne FIXLP1 ; nope + ldy #0 ; restart +FIXLP1: + inx ; next screen byte + cpx CH_OFFSET ; done yet? + bcc FIXLOOP ; nope + + dec CH_OFFSET ; fix counter + rts ; now we are done +; +; MSCURS - Erase the cursor from the old spot and write it in the +; new spot +; +MOLDX: db MAXWIDTH ; spot to save x,y of mouse +MOLDY: db MAXHEIGHT +MSCCNT: ds 1 +SVCURS: ds CURSW*CURSH ; save room +MSWCNT: db 1 +MSSTATE: db 0 ; 0 == off, 1 == on +MSCOLOR: db $f,7,7,7,7,7,7,7 +; +MSCURS: + lda #0 ; clear moved flag + sta MSMOVEF ; we did + jsr MSCOFF ; turn cursor off at current pos + jmp MSCON ; and turn it on in new spot + +; +; MSCOFF - mouse cursor off +; Copy info from saved spot back onto screen @ MOLDX, MOLDY +MSCOFF: + lda MSSTATE ; already off? + bne MSCOFF1 ; no + rts ; done then +MSCOFF1: + lda SCRCY ; save X,Y + sta SAVECY + lda SCRCX + sta SAVECX + lda MOLDX ; point to old X,Y + sta SCRCX + lda MOLDY + sta SCRCY + lda #0 ; start at beginning of saved area + sta MSCCNT ; save counter + lda #CURSW ; restore width + sta MSWCNT ; and counter +RENEWL: + lda SCRCY ; check bounds + cmp #MAXHEIGHT + bcs MSC1 ; all done +RENEWL0: + lda SCRCX + cmp #MAXWIDTH + bcs RENEWL1 ; might not be done + jsr GET_NYBBLE ; get screen nybble + ldx MSCCNT ; get counter +; eor MSCOLOR,X ; xor to turn off + eor #$0F ; turn white/black + jsr PUT_NYBBLE ; save nybble + inc MSCCNT ; point to next one + lda MSCCNT ; get counter + cmp #(CURSW*CURSH) ; done yet? + beq MSC1 ; yup + dec MSWCNT ; count down one width + beq RENEWL1 ; it is + inc SCRCX ; next x + bne RENEWL0 ; try again +RENEWL1: + lda MOLDX ; reset X + sta SCRCX + lda #CURSW ; restore width + sta MSWCNT ; and counter + inc SCRCY ; next y + bne RENEWL ; okay try some more +MSC1: + jmp MSCON4 ; done turning it off +; +; MSCON - turn mouse cursor on +; Copy white pixels into area specified by MSX, MSY +; +MSCON: + lda MSSTATE ; already on? + beq MSCON0 ; no + rts ; don't bother +MSCON0: + lda SCRCY ; save X,Y + sta SAVECY + lda SCRCX + sta SAVECX + + lda MSX ; get mouse x + sta SCRCX ; set mouse X + sta MOLDX ; save mouse x + lda MSY ; get mouse y + sta SCRCY ; set mouse Y + sta MOLDY ; and mouse Y + lda #0 ; start at beginning of saved area + sta MSCCNT ; save counter + lda #CURSW ; restore width + sta MSWCNT ; and counter +MSCON1: + lda SCRCY ; check bounds + cmp #MAXHEIGHT + bcs MSCON4 ; all done +MSCON2: + lda SCRCX + cmp #MAXWIDTH + bcs MSCON3 ; might not be done + jsr GET_NYBBLE ; save nybble + ldx MSCCNT ; get counter +; eor MSCOLOR,X ; get cursor color + eor #$0F ; turn white/black + jsr PUT_NYBBLE ; put nybble + inc MSCCNT ; point to next one + lda MSCCNT ; check ending + cmp #(CURSW*CURSH) ; done yet? + beq MSCON4 ; yup + dec MSWCNT ; count down one width + beq MSCON3 ; finished for line + inc SCRCX ; next x + bne MSCON2 ; try again +MSCON3: + lda MSX ; reset X + sta SCRCX + lda #CURSW ; restore width + sta MSWCNT ; and counter + inc SCRCY ; next y + bne MSCON1 ; okay try some more +MSCON4: + lda MSSTATE ; get current state + eor #$01 ; toggle it + sta MSSTATE ; bang + lda SAVECX ; restore X,Y + sta SCRCX + lda SAVECY + sta SCRCY + rts + + + END diff --git a/apple/yzip/rel.9/subs.asm b/apple/yzip/rel.9/subs.asm new file mode 100644 index 0000000..63703e7 --- /dev/null +++ b/apple/yzip/rel.9/subs.asm @@ -0,0 +1,376 @@ + STTL "--- OPCODE SUPPORT SUBROUTINES ---" + PAGE + +; ----------------------- +; 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 LOW = 16, + BCS GETVRG ; IT'S GLOBAL + +; HANDLE A LOCAL VARIABLE + +GETVRL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA LOCALS-2+LO,X ; GRAB LSB + STA VALUE+LO + LDA LOCALS-2+HI,X ; AND MSB + STA VALUE+HI + RTS +; +; HANDLE A GLOBAL VARIABLE +; +GETVRG: + jsr GVCALC ; GET ADDRESS OF GLOBAL INTO [FPC] + jsr FETCHB ; and get hi part + sta VALUE+HI + jsr NEXTFPC ; and point to next part + jsr FETCHB ; and go get it + sta VALUE+LO ; SAVE IT + rts ; AND WE'RE DONE + +; ---------------------------------- +; POP Z-STACK INTO [VALUE] AND [X/A] +; ---------------------------------- +; ZSTACK DOUBLED IN SIZE FOR EZIP +; SO THIS RTN ALL NEW + +POPVAL: LDA ZSP+LO ; IF ZSP+LO IS 0 + BNE POP1 + STA ZSP+HI ; MUST DEC. HI (HI = 0 OR 1 ONLY) +POP1: DEC ZSP+LO ; THEN DEC ZSP LO + BNE POP2 + ORA ZSP+HI ; LO + HI BOTH 0? + BEQ UNDER ; UNDERFLOW IF ZERO! +POP2: LDY ZSP+LO + LDA ZSP+HI + BEQ POP3 ; BOTTOM HALF OF ZSTACK + LDA ZSTKTL,Y ; GET VALUE FROM TOP HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKTH,Y + STA VALUE+HI + RTS + +POP3: LDA ZSTKBL,Y ; GET VALUE FROM BOTTOM HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKBH,Y + STA VALUE+HI + 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: PHA ; HOLD VALUE IN [A] A SEC. + LDY ZSP+LO + LDA ZSP+HI + BEQ PSHBOT ; ON BOTTOM HALF OF STACK + TXA + STA ZSTKTL,Y ; PUSH VALUE ONTO TOP HALF OF STACK + PLA + STA ZSTKTH,Y + JMP PSHUPD ; NOW UPDATE POINTER + +PSHBOT: TXA ; PLACE VALUE ON ZSTACK + STA ZSTKBL,Y + PLA + STA ZSTKBH,Y +PSHUPD: INC ZSP+LO ; UPDATE ZSTACK POINTER + BNE PSHEX + LDA ZSP+LO + ORA ZSP+HI + BNE OVER ; OVERFLOW IF $200 + INC ZSP+HI ; TO 1 +PSHEX: 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 + +; FLUSH TOP WORD OFF STACK +; AND REPLACE WITH [VALUE] + + LDA ZSP+LO ; IF ZSP+LO =0 + BNE VAR1 ; THEN HI =1 (GUARDED ELSEWHERE) + STA ZSP+HI ; DECREMENT HI (ONLY 0 OR 1) +VAR1: DEC ZSP+LO ; NOW DEC LOW BYTE + BNE PSHVAL + ORA ZSP+HI + BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + BNE PSHVAL + + ; RETURN A ZERO +RET0: + lda #0 + tax ; zero's all +; +; RETURN WORD IN [A], [X] (LO,HI) (EZIP EXPANDED TO A WORD) +; +PUTBYT: + STA VALUE+LO + STX 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 LOW = 16, + BCS PUTVLG ; IT'S GLOBAL +; +; PUT A LOCAL VARIABLE +; +PUTVLL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA VALUE+LO ; GRAB LSB + STA LOCALS-2+LO,X ; SAVE IN LOCAL TABLE + LDA VALUE+HI ; DO SAME TO + STA LOCALS-2+HI,X ; MSB + RTS +; +; RETURN A GLOBAL VARIABLE +; +PUTVLG: + JSR GVCALC ; put address in [FPC] + lda FPCBNK ; and move it to stash spot + sta SPCBNK + lda FPCH + sta SPCH + lda FPCL + sta SPCL + lda VALUE+HI ; GET MSB + jsr STASHB ; and save it + jsr NEXTSPC ; point to next byte + lda VALUE+LO ; NOW GET LSB + jsr STASHB ; and send it out + rts + +; ----------------------- +; CALC GLOBAL WORD OFFSET +; ----------------------- +; ENTRY: VAR-I BYTE (16-255) IN [A] +; EXIT: ABSOLUTE ADDRESS OF GLOBAL VAR IN [FPC] +GVCALC: + sec ; time for a subtract + 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 FPCL ; ADDRESS OF THE + lda I+HI ; DESIRED GLOBAL VARIABLE + adc GLOBAL+HI ; STORE ADDRESS BACK IN [FPC] + jsr SETPC ; now get memory page and bank + sta FPCH ; hi part + sty FPCBNK ; and bank +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 PREDB7 ; 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 +PREDB7: 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: LDA VALUE+LO ; SUBTRACT 2 FROM OFFSET + SEC ; IN [VALUE] + SBC #2 + TAX ;SAVE LO BYTE + LDA VALUE+HI + SBC #0 + STA I+LO ;MSB OF OFFSET = LSB OF [I] + LDY #0 ; CLEAR THE MSB + STY I+HI ; OF [I] + ASL A ; EXTEND THE SIGN OF OFFSET + ROL I+HI ; INTO MSB OF [I] + ASL A + ROL I+HI ; (EZIP) + asl A + rol I+HI ; (YZIP) ??!! + TXA ; GET LSB OF OFFSET + 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 PREDB6 + LDA I+LO ; ELSE CALC NEW UPPER BITS + CLC + ADC ZPCM + STA ZPCM + LDA I+HI + ADC ZPCH + AND #%00000111 + STA ZPCH + JMP VLDZPC ;MAKE VALID +PREDB6: + + ; FALL THROUGH ... + +; ---- +; NOOP +; ---- + +ZNOOP: RTS + + +; ---------------------- +; MOVE [ARG1] TO [VALUE] +; ---------------------- + +A12VAL: LDA ARG1+LO + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + RTS + + +; ----------------------------------- +; INDICATE STATUS LINE REFRESH NEEDED +; ----------------------------------- + +REFRSH: LDA ZBEGIN+ZFLAGS+1 ; PICK UP LOW BYTE OF FLAG WORD + ORA #%00000100 ; SET BIT 2 + STA ZBEGIN+ZFLAGS+1 ; AND PUT IT BACK + RTS + + +;DECJ RETURNS C=0 WHEN J=$FFFF + +DECJ: LDA J+LO + SEC + SBC #1 + STA J+LO + LDA J+HI + SBC #0 + STA J+HI + RTS + + END diff --git a/apple/yzip/rel.9/tables.asm b/apple/yzip/rel.9/tables.asm new file mode 100644 index 0000000..80220e9 --- /dev/null +++ b/apple/yzip/rel.9/tables.asm @@ -0,0 +1,329 @@ + STTL "--- ZIP DATA TABLES ---" + PAGE +CHADR_H: + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db >C20,>C21,>C22,>C23,>C24,>C25,>C26,>C27 + DB >C28,>C29,>C2A,>C2B,>C2C,>C2D,>C2E,>C2F + db >C30,>C31,>C32,>C33,>C34,>C35,>C36,>C37 + DB >C38,>C39,>C3A,>C3B,>C3C,>C3D,>C3E,>C3F + db >C40,>C41,>C42,>C43,>C44,>C45,>C46,>C47 + DB >C48,>C49,>C4A,>C4B,>C4C,>C4D,>C4E,>C4F + db >C50,>C51,>C52,>C53,>C54,>C55,>C56,>C57 + DB >C58,>C59,>C5A,>C5B,>C5C,>C5D,>C5E,>C5F + db >C60,>C61,>C62,>C63,>C64,>C65,>C66,>C67 + DB >C68,>C69,>C6A,>C6B,>C6C,>C6D,>C6E,>C6F + db >C70,>C71,>C72,>C73,>C74,>C75,>C76,>C77 + DB >C78,>C79,>C7A,>C7B,>C7C,>C7D,>C7E +CHADR_L: + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 8 +C3F DB 3f,80,71,c0,03,80,0e,00,0e,00,00,00,0e,00,00,00,00,00 ;? 10 +C40 DB 1f,f8,e0,0e,e3,e7,e6,77,e6,77,e3,bc,e0,00,1f,f8,00,00 ;@ 16 +C41 DB 3f,80,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;A 10 +C42 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,7f,80,00,00,00,00 ;B 10 +C43 DB 3f,80,71,c0,70,00,70,00,70,00,71,c0,3f,80,00,00,00,00 ;C 10 +C44 DB 7f,80,71,c0,71,c0,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;D 10 +C45 DB 7f,70,70,7f,70,70,7f,00,00 ;E 8 +C46 DB 7f,70,70,7e,70,70,70,00,00 ;F 8 +C47 DB 3f,80,71,c0,70,00,73,c0,71,c0,71,c0,3f,80,00,00,00,00 ;G 10 +C48 DB 71,c0,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;H 10 +C49 DB 70,70,70,70,70,70,70,00,00 ;I 4 +C4A DB 01,c0,01,c0,01,c0,01,c0,71,c0,71,c0,3f,80,00,00,00,00 ;J 10 +C4B DB 70,e0,71,c0,73,80,7f,00,73,80,71,c0,70,e0,00,00,00,00 ;K 11 +C4C DB 70,70,70,70,70,70,7f,00,00 ;L 8 +C4D DB 78,3c,7c,7c,7e,fc,77,dc,73,9c,70,1c,70,1c,00,00,00,00 ;M 14 +C4E DB 78,70,7c,70,7e,70,77,70,73,f0,71,f0,70,f0,00,00,00,00 ;N 12 +C4F DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;O 10 +C50 DB 7f,80,71,c0,71,c0,7f,80,70,00,70,00,70,00,00,00,00,00 ;P 10 +C51 DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,00,03,c0,00,00 ;Q 10 +C52 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,71,c0,00,00,00,00 ;R 10 +C53 DB 3f,80,71,c0,78,00,1f,00,03,c0,71,c0,3f,80,00,00,00,00 ;S 10 +C54 DB 7f,c0,0e,00,0e,00,0e,00,0e,00,0e,00,0e,00,00,00,00,00 ;T 10 +C55 DB 71,c0,71,c0,71,c0,71,c0,71,c0,71,c0,1f,00,00,00,00,00 ;U 10 +C56 DB 71,c0,71,c0,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;V 10 +C57 DB 71,c7,71,c7,71,c7,71,c7,71,c7,71,dc,7f,f8,00,00,00,00 ;W 16 +C58 DB 71,c0,71,c0,71,c0,1f,00,71,c0,71,c0,71,c0,00,00,00,00 ;X 10 +C59 DB 71,c0,71,c0,71,c0,3f,80,0e,00,0e,00,0e,00,00,00,00,00 ;Y 10 +C5A DB 7f,c0,01,c0,03,80,0e,00,38,00,70,00,7f,c0,00,00,00,00 ;Z 10 +C5B DB 7f,70,70,70,70,70,7f,00,00 ;[ 8 +C5C DB 70,00,38,00,1c,00,0e,00,07,00,03,80,01,c0,00,00,00,00 ;\ 10 +C5D DB 7f,07,07,07,07,07,7f,00,00 ;] 8 +C5E DB 00,00,0c,00,3f,00,e1,c0,00,00,00,00,00,00,00,00,00,00 ;^ 10 +C5F DB 00,00,00,00,00,00,00,ff,00 ;_ 8 +C60 DB 70,38,1c,00,00,00,00,00,00 ;` 6 +C61 DB 00,00,00,00,3f,80,01,c0,3f,c0,71,c0,3f,c0,00,00,00,00 ;a 10 +C62 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;b 10 +C63 DB 00,00,00,00,3f,80,71,c0,70,00,71,c0,3f,80,00,00,00,00 ;c 10 +C64 DB 01,c0,01,c0,3f,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;d 10 +C65 DB 00,00,00,00,3f,80,79,c0,7f,c0,70,00,3f,80,00,00,00,00 ;e 10 +C66 DB 0f,1c,7f,1c,1c,1c,1c,00,00 ;f 8 +C67 DB 00,00,00,00,3f,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;g 10 +C68 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;h 10 +C69 DB 70,00,70,70,70,70,70,00,00 ;i 5 +C6A DB 0e,00,0e,0e,0e,0e,0e,0e,7c ;j 8 +C6B DB 70,00,70,00,71,c0,73,80,7f,00,73,80,71,c0,00,00,00,00 ;k 10 +C6C DB 70,70,70,70,70,70,70,00,00 ;l 5 +C6D DB 00,00,00,00,7f,fc,73,9c,73,9c,73,9c,73,9c,00,00,00,00 ;m 14 +C6E DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;n 10 +C6F DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;o 10 +C70 DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,7f,80,70,00,70,00 ;p 10 +C71 DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,c0,01,c0,01,c0 ;q 10 +C72 DB 00,00,77,7c,70,70,70,00,00 ;r 8 +C73 DB 00,00,00,00,3f,00,70,00,1e,00,03,80,3f,00,00,00,00,00 ;s 9 +C74 DB 1c,1c,7f,1c,1c,1c,0f,00,00 ;t 8 +C75 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;u 10 +C76 DB 00,00,00,00,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;v 10 +C77 DB 00,00,00,00,73,9c,73,9c,73,9c,73,9c,7f,f8,00,00,00,00 ;w 14 +C78 DB 00,00,00,00,71,c0,71,c0,1f,00,71,c0,71,c0,00,00,00,00 ;x 10 +C79 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;y 10 +C7A DB 00,00,00,00,7f,c0,03,80,0e,00,38,00,7f,c0,00,00,00,00 ;z 10 +C7B DB 1f,38,38,f0,38,38,1f,00,00 ;} 8 +C7C DB 70,70,70,70,70,70,70,70,70 ;| 5 +C7D DB f8,1c,1c,0f,1c,1c,f8,00,00 ;} 8 +C7E DB 00,00,00,00,3c,e0,e7,80,00,00,00,00,00,00,00,00,00,00 ;~ 11 +; +; base addresses for the screen lines +; +BASEL: + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 00,00,00,00,00,00,00,00 + DB 80,80,80,80,80,80,80,80 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 28,28,28,28,28,28,28,28 + DB A8,A8,A8,A8,A8,A8,A8,A8 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 + DB 50,50,50,50,50,50,50,50 + DB D0,D0,D0,D0,D0,D0,D0,D0 +BASEH: + DB 20,24,28,2C,30,34,38,3C + DB 20,24,28,2C,30,34,38,3C + DB 21,25,29,2D,31,35,39,3D + DB 21,25,29,2D,31,35,39,3D + DB 22,26,2A,2E,32,36,3A,3E + DB 22,26,2A,2E,32,36,3A,3E + DB 23,27,2B,2F,33,37,3B,3F + DB 23,27,2B,2F,33,37,3B,3F + DB 20,24,28,2C,30,34,38,3C + DB 20,24,28,2C,30,34,38,3C + DB 21,25,29,2D,31,35,39,3D + DB 21,25,29,2D,31,35,39,3D + DB 22,26,2A,2E,32,36,3A,3E + DB 22,26,2A,2E,32,36,3A,3E + DB 23,27,2B,2F,33,37,3B,3F + DB 23,27,2B,2F,33,37,3B,3F + DB 20,24,28,2C,30,34,38,3C + DB 20,24,28,2C,30,34,38,3C + DB 21,25,29,2D,31,35,39,3D + DB 21,25,29,2D,31,35,39,3D + DB 22,26,2A,2E,32,36,3A,3E + DB 22,26,2A,2E,32,36,3A,3E + DB 23,27,2B,2F,33,37,3B,3F + DB 23,27,2B,2F,33,37,3B,3F +; +; this gives the bit offset for each one +; +XBITTBL: + DB 0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + DB 4,1,5,2,6,3,0 + RADIX D +ZIPCOLOR: db 0,1,6,7,$C,$B,$E,$F +APLCOLOR: db 2,3,$FF,$FF,$FF,$FF,4,5,$FF,$FF,$FF,7,$FF,$FF,8,9 +OLDZV: +; +; Variables that used to be in the zero page but got moved out +; +PSVFLG EQU OLDZV ; (BYTE) PRESERVE FLAG FOR LEX 0=DON'T 1=DO +VOCFLG EQU PSVFLG+1 ; (BYTE) WHICH VOC TBL, 0=NORMAL 1= ARG3 +DBLOCK EQU VOCFLG+1 ; (WORD) Z-BLOCK TO READ +QUOT EQU DBLOCK+2 ; (WORD) QUOTIENT FOR DIVISION +REMAIN EQU QUOT+2 ; (WORD) REMAINDER FOR DIVISION +QSIGN EQU REMAIN+2 ; (BYTE) SIGN OF QUOTIENT +RSIGN EQU QSIGN+1 ; (BYTE) SIGN OF REMAINDER +DIGITS EQU RSIGN+1 ; (BYTE) DIGIT COUNT FOR "PRINTN" +OLDLEN EQU DIGITS+1 ; (BYTE) OLD LINE LENGTH +OLDEND EQU OLDLEN+1 ; (BYTE) OLD LAST CHAR IN [LBUFF] +SPSTAT EQU OLDEND+1 ; (BYTE) SPLIT SCREEN STATUS FLAG +LFROM EQU SPSTAT+1 ; (WORD) "FROM" LINE ADDRESS +LTO EQU LFROM+2 ; (WORD) "TO" LINE ADDRESS +PRLEN EQU LTO+2 ; (BYTE) SCRIPT LINE LENGTH +GPOSIT EQU PRLEN+1 ; (BYTE) DEFAULT SAVE POSITION +GDRIVE EQU GPOSIT+1 ; (BYTE) DEFAULT SAVE DRIVE +TPOSIT EQU GDRIVE+1 ; (BYTE) TEMP SAVE POSITION +TDRIVE EQU TPOSIT+1 ; (BYTE) TEMP SAVE DRIVE +TSLOT EQU TDRIVE+1 ; (BYTE) TEMP SAVE SLOT +DRIVE EQU TSLOT+1 ; (BYTE) CURRENT DRIVE +SIDEFLG EQU DRIVE+1 ; (BYTE) which disk side are we on +SRHOLD EQU SIDEFLG+1 ; (WORD) <>0 if doing sequential random +SCRIPTF EQU SRHOLD+2 ; (BYTE) DIROUT FLAG FOR PRINTER OUTPUT +SCRIPTFLG EQU SCRIPTF+1 ; (BYTE) Does window allow scripting? +OLDZSP EQU SCRIPTFLG+1 ; (WORD) +CURSFLG EQU OLDZSP+2 ; (BYTE) 1==New cursor X for DLINE +DBLK EQU CURSFLG+1 ; (WORD) +RDTBL1 EQU DBLK+2 ; (WORD) READ TABLE 1 (Game Relative) +RDTBL2 EQU RDTBL1+2 ; (WORD) READ TABLE 2 +NENTS EQU RDTBL2+2 ; (WORD) # ENTRIES IN VOCAB TABLE +DIRITM EQU NENTS+2 ; (WORD) OFFSET IN OUTPUT TBL (DIRTBL) +DIRCNT EQU DIRITM+2 ; (WORD) COUNT OF CHARS IN TBL (DIRTBL) +SVTCHAR EQU DIRCNT+2 ; (WORD) Old TCHARS table address +VOCMPC EQU SVTCHAR+2 ; (3 BYTES) Save for vocabulary MPC +VCESVE EQU VOCMPC+3 ; (3 BYTES) Save for VOCEND +VWLSVE EQU VCESVE+3 ; (3 BYTES) Save for VOCLEN +DIDVTBL EQU VWLSVE+3 ; (BYTE) <>0 if we have done default table +IN EQU DIDVTBL+1 ; (9 BYTES) INPUT BUFFER +OUT EQU IN+9 ; (9 BYTES) OUTPUT BUFFER +CURSOR_OFF EQU OUT+9 ; (BYTE) ==1 if char cursor not to be on +CRLF_CHECK EQU CURSOR_OFF+1 ; (BYTE) ==1 to do CRLF function check +PTR_COUNT EQU CRLF_CHECK+1 ; (BYTE) ==0 if checking pointer movement +INFODOS_END EQU PTR_COUNT+1 ; (WORD) last segment of infodos special +OLDZVLEN EQU INFODOS_END-PSVFLG+2 ; this is how much to reserve + + BLKB OLDZVLEN,0 ; and zero it out + +; ------------------ +; ERROR MESSAGE STRINGS +; ------------------ +E27: db E27L + db "Disk I/O Error" +E27L EQU $-E27-1 +E2B: db E2BL + db "Disk write protected" +E2BL EQU $-E2B-1 +E40: db E40L + db "Bad Filename" +E40L EQU $-E40-1 +E44: db E44L + db "Path not found" +E44L: EQU $-E44-1 +E45: db E45L + db "Volume not found" +E45L EQU $-E45-1 +E46: db E46L + db "File Not Found" +E46L EQU $-E46-1 +E48: db E48L + db "Disk Full" +E48L EQU $-E48-1 +E49: db E49L + db "LaneDOS limit: 12 files/directory" +E49L EQU $-E49-1 +E4E: db E4EL + db "LaneDOS limit: No writes to TREE files" +E4EL EQU $-E4E-1 +E4C: db E4CL + db "Unexpected EOF" +E4CL EQU $-E4C-1 + +ELIST: db $27 + dw E27 + db $2B + dw E2B + db $40 + dw E40 + db $44 + dw E44 + db $45 + dw E45 + db $46 + dw E46 + db $48 + dw E48 + db $49 + dw E49 + db $4C + dw E4C + db $4E + dw E4E +ELISTL EQU $-ELIST-3 ; mark last error code + + END + diff --git a/apple/yzip/rel.9/verify.asm b/apple/yzip/rel.9/verify.asm new file mode 100644 index 0000000..b2cd98a --- /dev/null +++ b/apple/yzip/rel.9/verify.asm @@ -0,0 +1,252 @@ + STTL "--- VERIFY CODE ---" + PAGE + + ; ------ + ; VERIFY + ; ------ + ; VERIFY GAME CODE ON DISK +VERBAD: DB EOL,"The data segment of file is BAD!",EOL +VERBADL EQU $-VERBAD +VERPBAD: DB EOL,"The picture data of file is BAD!",EOL +VERPBADL EQU $-VERPBAD +ZVFLAG: db 0 ; set to indicate ugliness +STARTPOS EQU I+LO ; this is where to start block +ZVER: + jsr CLOSE_GAME ; make sure the game files are closed + ldy GAME2NML ; get length of name + lda GAME2NM,Y ; get last char + eor #$30 ; make normal number + tay ; -1 to make ready for FETCH_FILE + dey ; F_F incs first + tya ; to push onto stack + pha ; and save for restoring later + lda #0 ; clear a few counters + sta ZVFLAG ; ==0 - verify worked; !=0 - verify broke + lda SEGTBL+SGTDISKS+1 ; get how many disks are here + sta DISKCNTR ; this shows which disk we are working on + dec DISKCNTR ; start down by one +VERIFY_LOOP: + jsr VERIFY_DATA ; check data in this file + jsr VERIFY_PICD ; check (possible) picture data in this file + lda GMREF ; get reference number + sta CLOSE_PB+CL_REFNUM ; and show CLOSE + CLOSE CLOSE_PB ; and shut it up + dec DISKCNTR ; next please + bpl VERIFY_LOOP ; and check the next file +ZVERX: + lda #>PAGELEN ; reset read buffer length + sta READ_PB+RD_BUFFLEN+HI ; to be $100 + lda # 0, then it isn't + jsr SETUP_DISK0 ; move around to point to start of data +VERD1: + ldy #SGTPICOF ; find where picture data starts + lda (DSEGS),Y ; MSB + sta J+HI ; J is the page counter + iny ; point to LSB + ora (DSEGS),Y ; any picture file? + bne VERD01 ; yes, so mark end of data + lda #$FF ; set J to be a real big number + sta J+LO ; okay + sta J+HI ; and this one + bne VERD11 ; all done +VERD01: + lda (DSEGS),Y ; and here it is + asl A ; *2 to make 512 pages be 256 pages + sta J+LO ; this is where it ends up + rol J+HI ; move in carry to MSB + lda J+LO ; now, subtract any skipping + sec ; doing sub + sbc PSEEK+SM_FPOS+1 ; take away any skipped amount + sta J+LO ; and save it + lda J+HI ; pick up carry + sbc #0 ; we will + sta J+HI ; we did +VERD11: + jsr VERIFY_FILE ; now, actually do the work + bcc VERDX ; worked just fine + DLINE VERBAD ; puke, gag, argh +; +; This prints out which file is garfed +; +VER_FMSG: + lda DISKCNTR ; which file did we do? + cmp #2 ; 0,1 are in one place + bcs VERDB1 ; nope it isn't it + DLINE GAME1NAME,GAME1NML + jmp VERDB2 +VERDB1: + DLINE GAME2NAME,GAME2NML ; 2,3 are in another +VERDB2: + inc ZVFLAG ; show bad file + jsr GETRET ; just wait for +VERDX: + rts ; all done +; +; VERIFY_PICD - verify the picture data in a file. First check to see if +; there is any. If so, seek to it, set J==0 to show VERIFY_FILE to read +; til EOF, and print out bad picture data message if necessary. +; +VERIFY_PICD: + lda #$FF ; gonna zero bunch of stuff + sta J+HI ; and the counter + sta J+LO ; which means now goto EOF + ldy #SGTPICOF ; fetch the picture data offset + lda (DSEGS),Y ; get MSB + sta PSEEK+SM_FPOS+2 ; we are doing pages + iny ; pointing to LSB + ora (DSEGS),Y ; first, check for all zeros + bne VERP1 ; nope, some picture data is there + rts ; just gwon back if nothing here +VERP1: + lda (DSEGS),Y ; go get LSB + asl A ; *2 to get 256 byte pages + sta PSEEK+SM_FPOS+1 ; put away here + rol PSEEK+SM_FPOS+2 ; pick up carry + lda #PHSIZE ; skip over header of file + sta STARTPOS ; show offset in first block +VERP11: + SET_MARK PSEEK ; and move to picture data spot + jsr VERIFY_FILE ; read in the data + SET_MARK PSEEK ; get back to beginning of pic data + READ READ_PB ; read in a block worth + lda IOBUFF+PHCHKS ; get MSB of picture checksum + cmp L+HI ; same as what we got? + bne VERPB ; nope + lda IOBUFF+PHCHKS+1 ; get LSB of picture checksum + cmp L+LO ; same as mine? + beq VERPX ; yup, checked out fine +VERPB: + DLINE VERPBAD ; picture data bad + jmp VER_FMSG ; print out file name +VERPX: + rts ; tootis finis +; +; VERIFY_FILE - Files is already open and pointing to start of checksummed +; data. Works along til J == 0 or EOF, which ever comes first. Starts by +; dec'ing J, so if J starts as 0, effectively means goto EOF. +; +VERIFY_FILE: + lda #0 ; clear out checksum counter + sta L+HI ; MSB + sta L+LO ; LSB + sta READ_PB+RD_BUFFLEN+LO + lda #4 ; make read read $400 (1Kb) + sta READ_PB+RD_BUFFLEN+HI +VFLOOP: + lda #RETRY_COUNT ; and set up retry count + sta RETRIES + lda #IOBUFF ; reading all the data + sta K+HI ; into, using as pointer +VFLRD: + READ READ_PB ; read in 1Kb of data + bcc VERF0 ; just fine read + cmp #$4C ; EOF error? + beq VFCHECK ; yes, so wee bee done + cmp #$4D ; InfoDOS EOF error? + beq VFCHECK ; ayyup + jsr RETRY ; check about retrying + bcc VFLRD ; and do again +VERF0: + lda J+LO ; count the block to be read + bne VERF1 ; no wrapping + lda J+HI ; anything left? + beq VFCHECK ; nope, all done then + dec J+HI ; count one block +VERF1: + dec J+LO ; count block + ldy STARTPOS ; and begin +VERF2: + lda (K),Y ; get byte + clc ; doing add + adc L+LO ; add it in + sta L+LO ; save it + bcc VERF3 ; no wrap + inc L+HI ; yes ther is +VERF3: + iny ; next byte + bne VERF2 ; back to start of inner tloop + + lda #0 ; start at first byte + sta STARTPOS ; okay + inc K+HI ; point to next block + dec READ_PB+RD_LENGTH+HI ; count this one + beq VFLOOP ; go read some more + bne VERF0 ; go do next 256 byte block +VFCHECK: + ldy #SGTCHKS ; get check sum + lda L+HI ; start with MSB + cmp (DSEGS),Y ; well . . . ? + bne VFBAD ; nope, it is wrong + iny ; first byte is okay + lda L+LO ; so check LSB + cmp (DSEGS),Y ; well . . . ? + bne VFBAD ; die a slow ugly death + clc ; clear carry to show niceness + rts +VFBAD: + sec ; carry is set if bad + rts ; and return to your fate +; +; SETUP_DISK0 - this routine does some special processing to get the file +; pointer to the beginning of data for the preload file. It skips over +; segment table. +SETUP_DISK0: + READ READ_PB ; read in first block + lda IOBUFF ; MSB of segment table size (in words) + sta PSEEK+SM_FPOS+1 ; middle part of offset + lda IOBUFF+1 ; LSB of size + asl A ; *2 to pick up carry + rol PSEEK+SM_FPOS+1 ; rotate in carry + rol PSEEK+SM_FPOS+2 ; and once more + tay ; check for wrapping upwards + beq STD01 ; no wrap up then +STD00: + inc PSEEK+SM_FPOS+1 ; wee did + bne STD01 ; no more wrapping + inc PSEEK+SM_FPOS+2 ; yes there is +STD01: + lda PSEEK+SM_FPOS+1 ; make sure it is a 512 byte page + and #$1 ; even page? + bne STD00 ; inc again, please +STD0X: + SET_MARK PSEEK ; skip the segment table stuff + rts ; all done + + END diff --git a/apple/yzip/rel.9/versions b/apple/yzip/rel.9/versions new file mode 100644 index 0000000..fe962da --- /dev/null +++ b/apple/yzip/rel.9/versions @@ -0,0 +1,657 @@ +This is just a list of all the version changes for the Apple ][ YZIP + +; +; 1 - 7/29/88 New numbering scheme +; Faster text handling +; +; 2 - 8/17/88 Gargantu-Games handling +; Fixed Restart +; Handle COLOR -1 +; Handle transparent colors in pictures +; +; 3 - 8/24/88 Joystick/Mouse handling +; +; 4 - 8/30/88 Heavily debugged with/for ZORK0 +; +; 5 - 9/1/88 Fix cursor x,y in WINGET +; Make CLS work on REAL skinny windows +; +; 6 - 9/2/88 No status check on CLOSEs +; Only allow alphanumerics for save names +; +; 7 - 9/2/88 Don't clear strobe first, do it after getting key +; Add /RAM check to boot code - restore /RAM after QUIT +; +; 8 - 9/7/88 Flag day +; Changed WINGET/WINPUT to like GET/PUT +; Add in multi disk stuff +; +; 9 - 9/15/88 Preload is in SEGMENT table now +; Program name in BOOT.ASM +; Copy name to correct place in boot and interpreter +; New name of interpreter is now "INFOCOM" +; Add verify code too +; +;10 - 9/16/88 Keep running count of dirout char width in lo core +; Set up pure and pre pointers for tables and functions +; +;11 - 9/20/88 Don't forget to add one to x,y pos of window and cursor +; in WINGET +; Init vocab pointers for default vocab table and use them +; +;12 - 9/28/88 Zero zero page stuff in two passes - used to wipe out ProDOS zero page +; Data length in pic files is now 3 bytes + +; +;13 - 10/11/88 Picture files and Data files are one and the same now +; +;14 - October 24, 1988 +; Add volumn command to save/restore get name routine +; +;15 - November 8, 1988 +; Search on disk 1 in last resort (hints are probably there) +; Use mouse in passive mode +; +;16 - November 14, 1988 +; Make mouse stuff be passive, rather than interrupt driven +; +;17- November 15, 1988 +; Few more fixes 'n' stuff +; +;18-November 15, 1988 +; Clear ZTWIDTH when starting table output +; +;19-November 28, 1988 +; Fix up PUT_NYBBLE and GET_NYBBLE +; Reset DSEGS after closing save file +; Make FONTSIZE word be Width/Height +; Make Chars/line reflect mono spaced char width of 3 in lo core +; Change ZTWIDTH to be MSB/LSB, rather than LSB/MSB word +; Point to main bank in CHK_MOUSE +; Clamp mouse to 136,189, and don't do shift when getting pos +; Make CLK_CNT be negative, and set flag to show button state +; Set up point to MSTBL (extension table for mouse clicks) +; Put X,Y coordinates in MSTBL after click +; +;20-December 1, 1988 +; Don't use [A] in DO_MOUSE unless it is a character +; Clear LSB in seek pblock before doing seek +; No, really, DON'T use [A] in DO_MOUSE +; Make CLK_CNT be 8 +; Exit normally if double click +; Split mouse cursor routine into 2 pieces - off and on +; If can't find picture, try opening other file. If it isn't there +; then die with error #$14 +; Move XPOSTBL and COLORS to page 3 for some elbow room +; Save/restore refnum when opening new picture file +; +;21-December 2, 1988 +; Swap back to Bank 1 in pic.asm +; +;22-December 5, 1988 +; Save/restore DSEG in verify +; Dec saved filename for passing to Fetch_file in Verify +; Fix addition for getting to Picture data in Verify +; Check for files 0 & 1 names in different place than 2 & 3 (Verify) +; Add STARTPOS to verify +; Copy BITOFF to BITTER in picture stuff +; +;23-December 6, 1988 +; Get picture data checksum from the right place +; Init counter for picture data checksum to be $FF, not 0 +; Move "mouse" cursor for joystick too +; Do "mouse" cursor pos for button for joystick too +; Change movement thresholds for joystick to 120/135 +; Double movement rate for joystick +; Change boundaries check in stick movement to bcs, not beq +; Save/restore cursor position in DLINE +; Create SWAP2INFOW/SWAPBACK to go to/from info window +; and have DLINE & GETSNAME use them +; Have only one exit point in GETSNAME +; Make DLINE do a CLRBUF upon exitting +; Add EOL to end of DELQ +; Muck with a few messages in ZSAVRES +; Change GAMEPL to maximum (64-15) as can only be a list of directories +; Add "Unexpected EOF" error string +; +;24-December 8, 1988 +; Game data starts out on even (512 byte) page boundary +; +;25-December 13, 1988 +; Make pop's FETCHB store afterwards +; Make WINGET handle 0-15 words to get +; Change order of window parameters, to make user ones the first +; 16 available +; Don't SWAP to infowindow in DLINE, rather do it in routines that +; call DLINE +; Fix color green in COLORS table +; +;26-December 14, 1988 +; Change PBEGIN to $0200 +; Scan for mouse slot, rather than asking or assuming +; After finding it, save lo byte in arg1+lo to change interpreter +; screen holes for interesting stuff +; Save/restore printer slot before/after SWAPBACK call +; +;27-December 15, 1988 +; Put paging buffer start back to $0800, cuz screen holes in aux +; mem really screw things up +; Make only closed-apple key work as function key faker +; +;28-December 16, 1988 +; Need only 8 chars for name, as .SYSTEM adds 7 more, to max 15 +; Make ZQUIT read RDBNK2, not write +; +;29-December 19, 1988 +; Save disk number when saving refnum, so that we can scan the two +; disks currently inserted, then look at all the rest +; Pass starting offset for segment list, cuz segments for side 1 +; start a little weird, cuz preload is the first set of +; segments, then the list starts normally +; Don't forget to save refnum in all the right places +; +;30-December 20, 1988 +; Use BIT_BITS in both CHAR_LINE and picture stuff +; Take out retries - it just doesn't work +; Add check for save disk when asking about swapping disk +; Copy read buffer to local buffer before doing read +; +;31-December 22, 1988 +; Play with bounds for joystick movement a little further out +; Don't script input line +; Fix input with timeout, so that the key gets parsed correctly +; Only look at button zero for joystick +; Call FKEYX instead of KEYX in TIMEK +; Check all online volumes before asking for disk by name +; Fix length byte before you do +; Use CHPTR in volume checking routine +; Copy path name to SCRBUFF so we can prepend a '/' in checking volumes +; And don't forget to count it in the length byte +; Quit if no more volumes to check +; More changes to avoid errors in set_prefix, which really seem to gum +; up the works +; +;32-December 23, 1988 +; Don't clear interrupts before reading paddles +; +;33-January 3, 1989 +; Spell volume right in error message +; Save cursor a little earlier in zdispl +; Set/clear savedisk only in close_save +; +;34-January 4, 1989 +; Make sure carry is set before returning from DISK_ERR +; Have SET_GAMEPRE use SAVENUM +; Push current INVFLG instead of saving in variable in ST_CUR +; Check for mouse cursor in timed input please too +; Took GOTKEY out, cuz no-one used it any more +; Changed order in TIMIN for goodness sake +; +;35-January 5, 1989 +; Try for 512 byte paging buffers +; +;36-January 6, 1989 +; Fix up some more for 512 byte buffers +; Muck with paging scheme (oh oh) +; Make GETRES take from one to four blocks +; Make restore use 4 blocks when doing full restore +; +;37-January 9, 1989 +; Fix multiple block restore problems +; Don't destroy DOS return code in GETRES +; Clear CLOSE_PB refnum +; Make DOS routine be READ_DOS and WRITE_DOS +; Fix read so SIB's increment word start +; Make WAIT10 check for mouse/joystick cursor movement +; Use FKEYX for [MORE] so buttons can be used +; +;38-January 10, 1989 +; Mess with PCHK and other scripting stuff +; Use GETKEY for [MORE] +; Put in delay before calling PREAD to get joystick status +; +;39-January 11, 1989 +; Make mouse cursor be two colors +; Change WAIT10 to be a loop, not an MWAIT call +; Clear MSMOVEF flag in MSCURS +; Don't check GETKEY's return in MORE +; Joystick is > 0, mouse is < 0 +; Leave mouse status in [A] for CHK_MOUSE +; Add DELAY_COUNTER for WAIT10 +; +;40-January 12, 1989 +; Fix shift (asl -> rol) when getting position of picture T.O.C. +; Don't split Mouse moving/button +; Play with Delay counter, doubling it if on a GS +; Make sure interrupts are turned back on in CHK mouse +; Only turn on button flag in CHK mouse, never turn it off +; Add another delay loop inside WAIT10 +; Make INNER & OUTER constant counters, with special ones for GS +; +;41-January 13, 1989 +; Add printer init call to pchk +; Play with SCRIPT flag (which allows scripting) +; Turn on initially +; Turn off at start of save/restore +; Turn on at end of save/restore +; Add SCRIPTFLG, which says whether window allows scripting +; +;42-January 19, 1989 +; Change to always seek to 512byte block boundary for new DOS +; pic.asm +; +;43-January 20, 1989 +; Move copy line for $D000 down to lower memory +; Add INFODOS flag for conditional assembly for special dos +; Play with boot to get it to work with 512byte blocks +; Take out all ROM calls, cept printer stuff; default is now +; BNK1SET +; +;44-January 26, 1989 +; Change DESTROY to SETEOF for new InfoDOS. +; +;45-January 31, 1989 +; Make paging stuff goto Bank 2, not bank 1 +; Make picture stuff goto Bank 1 +; Add INFODOS flag +; Non-sequential page map +; If INFODOS==1, then 12Kb preload in $D0-$FF, main bank, bank 2 +; and check for it in xpaging +; Just loop if using InfoDOS upon quit +; +;46-February 1, 1989 +; Don't muck with interrupts cuz InfoDOS don't like it +; +;47-February 4, 1989 +; Fixed set_eof to delete file. +; Ignore error returns for set_eof, cuz InfoDOS doesn't like to +; SET_EOF on an empty file. +; Make boot.asm print out version too +; Change special load from Kb's to pages +; Do special load 1 page at a time, rather than 2 +; +;48-February 6, 1989 +; Change get_special counter to count 2 blocks, not 4 +; Fix SAVE/RESTORE to do 512 byte pages for InfoDOS +; All reads in restore must be 512 bytes minimum +; +;49-February 7, 1989 +; Make SAVE_DATA self-modification be absolute, not relative +; Put version number into lower left corner of boot screen +; Fix scroll to move cursor to last line before doing any work +; and have it count the lines in lincnt, but not +; against the scrolling lines +; +;50-February 10, 1989 +; Add no write to TREE files error +; Add set_prefix call to OPEN_GAMEF, before opening file the +; first time +; Start Set-PB off pointing to game boot prefix +; Init a few GS registers in boot +; Put SET_EOF error check back +; Jump to reset vector if in InfoDOS +; +;51-February 13, 1989 +; Swap ROM back in if reading joystick +; Do a SET_EOF if bad save +; Check button click for joystick in delay loop +; Swap in ROM for jump to reset_vector +; Make restart load INFOCOM.SYSTEM +; Swap in ROM at start of boot task +; Try to get click/double click for joystick to work +; Add JB_STATE to show changing state +; Only check bit 7 +; Set CLK_CNT to 3 +; Only one loop in read_stick +; Fix restore of SCRCX in disp_line (nothing passed in [A]) +; In displaying cursor, always set up CHR_X, but don't change +; SCRCX +; +;52-February 14, 1989 +; Set CURSFLG at start of input and zinput +; Change display_line to not update for just show_cursor +; Don't let GET_SCRCX change chr_x +; Use my toggle for mouse button up&down +; Put in more check for joystick button +; Add Cursor off/on on curset of -1/-2 +; Go to prefix that was there on a save +; Take it out of zdos and put in close_save +; Just ask to put back game disk, not particular disk +; Fix set_gamepre - getret does not return == +; +;53-February 15, 1989 +; Wrap correctly if picture data starts near 256 byte boundary +; Add DIRECT_OUT call to DLINE/COUT to skip over checks like +; formatted table output and scripting +; Fix CHECK_JYBTN to check mouse if there is a mouse +; +;54-February 16, 1989 +; Fix check for -1/-2 in CURSET +; +;55-February 16, 1989 +; Major changes to COPY_LINE +; Change (zzz),Y to zzz,X +; Take out one of the counters +; +;56-February 17, 1989 +; Don't do CRLF check if doing interpreter printing +; +;57-February 21, 1989 +; Don't set function preload if tables take up all preload +; +;58-February 25, 1989 +; Ignore LINCNT during call to ZSCROLL +; Jump to ZRQUIT, not ZRBAD, when no restore name given +; Get updated DSKBNK in PUTDSK +; Make mouse hotspot be in middle of cursor +; +;59-February 28, 1989 +; Add Global Directory Offset to segment table structure +; Fix transparent color skipping to New X pos +; Add "Version:" to boot screen +; Move cursor to left most column for M/J/N question +; Ask for particular Game disk side after taking out save disk +; +;60-March 1, 1989 +; Change CHZ to good spot in boot.asm +; Add Global dir offset to segment 1 structure too +; Move Scrcx for good color in picture drawing too +; Send out eol too to position cursor in boot +; Don't ask for particular disk side after save, cuz I can't be sure +; whether it is a one disk or multi disk game (i.e. on a +; 3.5" disk, I don't want to ask for a particular side). If +; users puts in wrong disk, I will then ask for a particular +; side). +; Add SWAPPED flag to show a multi disk game, which requires special +; detailed question +; Check for $4D error in verify, cuz InfoDOS returns it instead of +; $4C on EOF +; +;61-March 2, 1989 +; Add SET_PREFIX to boot code startup +; Don't check for pointer movement if a key has been hit, at least +; not for a while (PTR_COUNT) +; +;62-March 4, 1989 +; Clear PTR_COUNT at start of ZINPUT and end of INPUT +; +;63-March 6, 1989 +; Don't set CURSFLG in ZINPUT/INPUT, cuz cursor doesn't want to +; move in an aborted one +; Make cursor always end up at top right of picture +; Move PIC1BUFF so it doesn't tromp input buffer +; Make RESTART use FETCH_FILE to get correct disk before rebooting +; Make CLOSE_SAVE use DO_GAME1 to get GAME1 file +; +;64-March 7, 1989 +; Make INPUT explicitly clear CURSFLG +; CLOSE_GAME should call DO_GAME1 first +; And don't forget to set SAVEDISK flag still +; Use OPEN_GAMEF, not FETCH_FILE in restart +; Make mouse x,y be one based +; Make sure there is a prefix in the save name +; Add check for zero length save file name +; Fix COPY_LINE to do ENDMASK correctly +; Update COPY_LINE's source address every loop in CLS +; Have call to buffout fall thru to CLRBUF +; +;65-March 7, 1989 +; Increased interpreter size to 42 pages +; Add clrbuf call to zfont +; Make random go fetch a word from memory +; Take out RNUM, just use RAND +; Add in Global directory handling +; +;66-March 8, 1989 +; Fix special case in SCANSEG for side 1 (skip 6, not 14) +; Add UNDERF to disp_line, so underline flag gets reset correctly +; Make partial save/restore work better, including by always readin +; in 2 pages worth +; +;67-March 9, 1989 +; Change some messages for inserting disks +; Fix get_save_name so it doesn't double print name on prefix error +; Modify some messages in save/restore +; Don't let user wrap input line +; +;68-March 9, 1989 +; Move Special to Aux bank, and paging to main bank +; +;69-March 10, 1989 +; Make CLREOL show inclusive width +; +;70-March 13, 1989 +; Don't make mouse x/y be one based (why?) +; When *2 for segment table size in boot, use both LSB & MSB +; +;71-March 14, 1989 +; Add in global dir handlers +; pic.asm - add OPEN_NEW_PF, FIND_PIC_DISK, and an expanded +; FIND_GBL +; zdos.asm - look for picture data in all files, including 1 & 2 +; Try to make keyboard read a little more responsive +; Set flags word to Apple ][ stuff in zbegin +; Add retry to GET_SPECIAL and GETDSK and VERIFY +; +;72-March 15, 1989 +; Don't forget to send side # out for RESEAT message +; Add CHARSET stuff +; Take into account the margins in CLREOL +; Modify how big entry is in getting picture/global directory +; Handle Ctrl-K (end of sentence) and Ctrl-I (start of paragraph) in +; COUT +; Go back to using MWAIT in WAIT10 +; Had NEXTPICF check backwards +; +;73-March 16, 1989 +; Make ISTCHARS function key check use tax/bmi sequence - no CMP +; Save LOCALS first in ZREST:, in case of early error +; Change where we display disk error (after RESEAT msg). +; Don't forget to save/restore the disk error # +; Fix check for double picture lookup +; Save cursor before drawing picture/restore it after +; Make FIX_COLOR handle either black or white foreground +; +;74-March 16, 1989 +; Make [MORE] get printed out without call to DLINE +; Set/restore DSEGS upon call to get picture data, just +; to make sure it's right. Also, don't bother going to +; get the data if it is the stuff already in memory +; Try to get more random +; Make sure GET_SPECIAL get's from the start of .D2 +; and all LSB's are zero'd +; +;75-March 17, 1989 +; Make sure disk error gets saved/restored while in RETRY +; Just tell user where to put disk, rather than what to take out +; and then tell what disk to put in +; Add APLCOLOR table for winget on color +; +;76-March 21, 1989 +; Reset find_gbl counter upon finding a picture +; Don't look for another global directory if we already have one +; Make findpicdisk stop trouncing on its data, and check both +; the disks that are in there +; Make the disk findpicdisk asks for be zero relative +; Change CLREOL width again - just make it # of pixels to clear +; User lower 4 bits in Long Jump ZPC MSB, and shift over once more? +; Allow game to set line count +; Go get picture data even if file is already open, if it isn't the +; one currently in memory +; Don't add extra spaces to start of line for tab/eos chars +; +;77-March 22, 1989 +; 'nother day, 'nother version +; Turn screen on/off with table output off/on +; Swap returned fore/back colors in winget +; Set length to zero if x pos < left margin +; Probably ought to be fixed better, perhaps by not taking +; left margin into account in XSIZE, and starting length off +; at left margin on CRLF/wrap +; Implement ERASE n, where n > 1 +; Make sure picture file directory gets read in, even if the file +; is already open, if it is not the data in memory +; Clear LINCNT on every ZCRLF in ZSCROLL +; Don't take into account the left margin in CLREOL +; Count byte if special start/end in COPY_LINE +; +;78-March 23, 1989 +; Try once more . . . +; Fix verify so it counts down correctly, and count the block at +; start of add, not end +; Make take out save disk message wrap better +; Make sure EOL is in CHARSET table, even if a table is passed to +; me +; Fix MSB/LSB of piccnt in FIND_GBL +; Save File ID of local directory, for later checking +; Don't move in starting spaces in FLUSH +; Make sure SCREENF is on while in DLINE +; +;79-March 24, 1989 +; This is so much fun, I just wanted to do it again . . . +; Wrap TWIDTH up before /4 +; Don't set undo bit in flag word +; Don't script [MORE] +; +;80-March 27, 1989 +; 'nother week, 'nother interpreter (are we having fun yet?) +; Change CLICK_CNT to 4 +; Swap to infowindow before zerror +; Just check passed arguments for fitness in WINSIZE/WINPOS, not +; the results +; +;81-March 28, 1989 +; Make sure the clear operand in the window attributes command works +; correctly +; Change LINCNT check in ZCRLF to be bcc, not bne +; Make sure first read in full restore has 2 blocks, to maybe catch +; a define save +; Make sure ROM is NOT in there when doing a reset +; Add some retries to boot disk +; +;82-March 29, 1989 +; Add one to PURBT size on restore and make sure last read is an +; 512 page +; Use TBLRTN on formatted table in flush +; +;83-March 30, 1989 +; Put in some retries in boot reads +; Make sure winput puts LINCNT +; Update attributes if -3 passed to WINATTR too +; Do CLRBUF in DIROUT +; Just set SCRIPT to true, not inc it, in CLOSE_SAVE +; +;84-March 31, 1989 +; Fix verify's handling of disk 1, and don't bother to skip 64 bytes +; of lo core +; +;85-April 3, 1989 +; Munge power up valid byte before jump to RESET_VECTOR +; Set ZFLAGS word correctly +; Try to turn on more bits in hi byte of random number +; +;86-April 5, 1989 +; Don't save/restore DSEG/GMREF in verify - just let fetch_file do +; the work +; Clear PF_FID in CLOSE_GAME +; Try to make RESET_VECTOR work, but getting/storing RESET_VECTOR, +; loading in ROM, then jumping to vector +; +;87-April 6, 1989 +; On error in GTS, restart whole process +; Load length of Game 2 name before checking in fetch file +; +;88-April 10, 1989 +; Don't script SCROLL call +; XOR mouse cursor onto screen +; Don't update LENGTH in INPUT til we've made sure it fits +; Handle monospaced font in BACKSPACE +; Don't script special chars +; Don't die on bad call to picinf, just on disp pic +; +;89-April 11, 1989 +; Check for zero object in REMOVE +; Make sure soft switches are good in ZSAVE +; Make sure restore gets correct number of blocks if even multiple +; of 4 is saved +; Don't allow escape key +; Swap to info window on reseat message +; Try doing online call before checking volume name again +; +;90-April 12, 1989 +; Make sample filename for save be in uppercase, cuz Hollywood's a +; turkey +; +;91-April 13, 1989 +; One more for the gipper +; Don't bother printing the prefix on bad file verify message +; Print spaces to delete MORE, not CLREOL +; +;92-April 18, 1989 +; Add IPAGE to INFO_PAGE +; Clear [MORE] with backspaces +; +;93-April 19, 1989 +; If no bit in global directory, assume picture is on disk 1 +; +;94-April 20, 1989 +; Add more debugging code (save ZPC, ZPCPNT, and OPCODE) +; +;95-April 21, 1989 +; Add fatal error on clear of zero width/height (#25) screen +; +;96-April 22, 1989 +; Unwind the stack on a THROW +; +;97-April 26, 1989 +; Take out unscripting of control chars, so we get EOL +; +;98-April 27, 1989 +; Give back version number of pic file +; Move file pointer to beginning of file in verify, before calling +; SETUP_DISK0 +; Don't count skipped data on side 1, verify +; +;99-April 28, 1989 +; 'Nother new version, just cuz it's so much fun messing with +; Hollywood's pea brain +; Make sure bank 2 is still in after mouse call +; +;1-May 1, 1989 +; Shipped version +; +;2-May 2, 1989 +; HA! +; Do 5 retries, reseeking to zero and back before asking for reseat +; +;3-May 8, 1989 +; Let's pretend this is the shipped version +; Let's first retry the set prefix a few times before asking again +; +;4-May 11, 1989 +; Put in more debugging stuff for SHOGUN problems +; +;5-May 18, 1989 +; Take out ONLINE call in SET_PREFIX +; Make all PAGE2SW be READS!! not WRITES!! +; Make sure we leave off pointing to MAIN PAGE 2 always! +; Don't ever mess with STORE80 switch - ALWAYS ON +; +;6-May 19, 1989 +; Take out debugging stuff +; Make version number for pic files be swapped +; +;7-May 22, 1989 +; Put debugging code back in +; Make sure main bank is in there before starting scroll stuff +; Just scroll up X lines, don't bother with ZCRLF stuff +; +;8-May 23, 1989 +; Let's ship this version +; Move the SWAPBACK call on retry +; ORA char with $80 before shipping to printer +; Don't do clrbuf's at the start/end of PRINTT +; +;9-May 24, 1989 +; SHOGUN version, without PRINTT change +; diff --git a/apple/yzip/rel.9/windows.asm b/apple/yzip/rel.9/windows.asm new file mode 100644 index 0000000..67be2b6 --- /dev/null +++ b/apple/yzip/rel.9/windows.asm @@ -0,0 +1,769 @@ + + STTL "--- WINDOW OPERATIONS ---" + PAGE +; +; these are the data structures for all 8 WINDOW. They are identical and +; are just seperated cuz I use the addresses in the table that follows. +; All numbers are inclusive, absolute, and zero-based. +; +WINDSTRUCT EQU 0 +WINTOP EQU WINDSTRUCT ; first line of the window +WINLEFT EQU WINTOP+1 ; left edge of the window +WINHGHT EQU WINLEFT+1 ; height of the window +WINWID EQU WINHGHT+1 ; width of the window, in pixels +WINY EQU WINWID+1 ; y pos of cursor (pos, not relative) +WINX EQU WINY+1 ; x pos of cursor (remember, ABSOLUTE) +WINLM EQU WINX+1 ; left margin +WINRM EQU WINLM+1 ; right margin +WINCRF EQU WINRM+1 ; (WORD) function +WINCRC EQU WINCRF+2 ; (WORD) counter +WINHIGHL EQU WINCRC+2 ; highlight mode +WINFORE EQU WINHIGHL+1 ; foreground color (0=black-7=white) +WINBGND EQU WINFORE+1 ; background color (0=black-7=white) +WINFONT EQU WINBGND+1 ; window font (0=normal/4=monospaced) +WINFSIZE EQU WINFONT+1 ; (WORD) font Height/Width +WINATR EQU WINFSIZE+2 ; Window Attributes +WINLCNT EQU WINATR+1 ; current number of lines +; +; these are my interesting things +; +WINXSZ EQU WINLCNT+1 ; width of window, in pixels, using margin +WINLLEN EQU WINXSZ+1 ; length of current line +WINLINES EQU WINLLEN+2 ; max # of lines for window + +WINDOW0: + DB 0 ; WINTOP - first line of the window + DB 0 ; WINLEFT - left edge of the window + DB MAXHEIGHT ; WINHGHT - height of window + DB MAXWIDTH ; WINWID - width of window + DB 0 ; WINY - y pos of cursor (pos, not relative) + DB 0 ; WINX - x pos of cursor (remember, ABSOLUTE) + DB 0 ; WINLM - left margin + DB 0 ; WINRM - right margin + DW 0 ; WINCRF - function + DW 0 ; WINCRC - counter + DB 0 ; WINHIGHL - Highlights + DB $f ; WINFORE - foreground color default of white + DB 0 ; WINBGND - background color + DB 0 ; WINFONT - window font (0=normal/1=alternate) + DB 2,FONT_H ; WINFSIZE - Width/Height + DB $0f ; WINATR - all attributes on for window 0 + DB 0 ; WINLCNT - current number of lines + DB MAXWIDTH ; WINXSZ - width of window, in pixels, using margin + DB 0,0 ; WINLLEN - length of current line + DB (MAXHEIGHT/FONT_H)-1 ; WINLINES - max # of lines for window +; +; same start as window 0, but with 0 length +; +WINDOW1: + DB 0,0,0,MAXWIDTH,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,MAXWIDTH,0,0,0 +; +; the rest have no width/height/attributes (except buffering) +; +WINDOW2: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW3: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW4: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW5: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW6: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 +WINDOW7: + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + +WINTABLE: + DW WINDOW0,WINDOW1,WINDOW2,WINDOW3 + DW WINDOW4,WINDOW5,WINDOW6,WINDOW7 + PAGE + +; ------ +; SCREEN +; ------ +; Move to the screen specified, by updating CURWIN and the cursor +; X,Y pos (SCRX,SCRY). Also put address of that window's structure +; in WINDOW. Save a bunch of the old stuff in old window's structure then +; update the same bunch with the new window's stuff. +; +; ARG1 - new screen id: 0-7 +; +ZSCRN: + jsr CLRBUF ; EMPTY OUTPUT BUFFER BEFORE MOVING +; +; now, save a few things from the common variables +; + ldy #WINLLEN ; current line length + lda LENGTH+LO ; get current line length + sta (WINDOW),Y ; save for later referencing + iny ; point to msb + lda LENGTH+HI ; get MSB + sta (WINDOW),Y ; saved + jsr SAVE_CURSOR ; save the x,y pos of cursor + lda INVFLG ; get inverse flag + beq ZSCA1 ; not set + lda #1 ; set 1 bit + bne ZSCA2 ; set in window +ZSCA1: + lda UNDFLG ; how about underlining + beq ZSCA2 ; nope + lda #4 ; 4 == underlining +ZSCA2: + ldy #WINHIGHL ; set new highlight + sta (WINDOW),Y ; save current attributes +; +; now it is time to update for new screen +; + lda ARG1+LO ; get which window + sta CURWIN ; save window number + asl A ; shift to make word indes + tax ; swap to indexing reg + lda WINTABLE,X ; get the address of the new WINDOW + sta WINDOW+LO ; lo part comes first + lda WINTABLE+1,X ; so go get hi part + sta WINDOW+HI ; save the hi part of the address + + jsr GET_CURSOR ; restore the cursor pos + + ldy #WINXSZ ; get line length + lda (WINDOW),Y ; update zero page variable + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + ldy #WINLLEN ; get current line length + lda (WINDOW),Y ; from before + sta LENGTH+LO ; save for later checking + iny + lda (WINDOW),Y + sta LENGTH+HI + ldy #WINLCNT ; how many lines already out there + lda (WINDOW),Y ; has been already saved + sta LINCNT ; and save 'ere too + ldy #WINLINES ; how many lines in this + lda (WINDOW),Y ; window, anyway? + sta MAXLINES ; show for everyone to see + ldy #WINLEFT ; show left margin + lda (WINDOW),Y ; get left edge + ldy #WINLM ; left margin + clc ; adding + adc (WINDOW),Y ; to find new left margin + sta LEFTMRG ; set up left margin for ease of use + ldy #WINTOP ; get top of window + lda (WINDOW),Y ; got it + clc ; adding + ldy #WINHGHT ; add height + adc (WINDOW),Y ; did it + sta SCRBTM ; this is first line outside window + ldy #WINHIGHL ; get highlighting modes + lda (WINDOW),Y ; first for inverse video + and #1 ; check for inverse video + beq SCRINV ; nope + lda #$80 ; means inverse video +SCRINV: + sta INVFLG ; there it be + lda (WINDOW),Y ; point to underline flag + and #4 ; check for underlining + beq SCRUND ; nope + lda #$80 ; means underlining +SCRUND: + sta UNDFLG ; save for everyone + + ldy #WINATR ; get the current attributes + lda (WINDOW),Y ; gottem + jsr SET_ATTRIBUTES ; set the flags, thank you + ldy #WINFONT ; get the font + lda (WINDOW),Y ; thank you + beq SCRFNT0 ; is it font zero? + lda #MONOFONT_W ; must be mono font, set width +SCRFNT0: + sta FONTFLG ; mark normal font +ZSCREX: + rts +;-------------- +; ZWINPOS +;-------------- +; +; change the window ARG1's top left corner to the new position +; +; ARG1 - window id from 0-7 +; ARG2 - new top y pos +; ARG3 - new top x pos +; +ZWINPOS: + dec ARG2+LO ; make pos be zero based + dec ARG3+LO ; now they are! +; +; if moving current window, save current cursor pos +; +ZWPOS0: + jsr SAVE_CURSOR ; saving +; +; let's set up [J] to point to window we are talking about +; +ZWPOS1: + lda ARG1+LO ; get window ID + jsr SETWJ ; get J to point to it + + lda ARG2+LO ; first, check the top + cmp #MAXHEIGHT ; < max height? + bcc CKWA1 ; fine + lda #0 ; make it zero then + sta ARG2+LO ; it is now +CKWA1: + lda ARG3+LO ; now check left edge + cmp #MAXWIDTH ; howzit compare + bcc CKWA2 ; just fine + lda #0 ; this too + sta ARG3+LO ; it is now +CKWA2: +; +; make the cursor pos be relative, so we can change back to +; absolute using new window pos +; + ldy #WINY ; let's do y pos first + lda (J),Y ; get the old y pos + ldy #WINTOP ; and subtract the top to make + sec ; (getting ready) + sbc (J),Y ; the pos relative + clc ; now add in new top + adc ARG2+LO ; this will be new top + ldy #WINY ; get y offset again + sta (J),Y ; and save new absolute y pos + ldy #WINX ; now we be talking about x pos + lda (J),Y ; get old x pos + sec ; getting ready for sub + ldy #WINLEFT ; get rid of left ness + sbc (J),Y ; now it's relative + clc ; get ready to add in new left ness + adc ARG3+LO ; done + ldy #WINX ; get x offset again + sta (J),Y ; save in structure +; +; now we can change the top and left of the window +; + lda ARG2+LO ; this is top of window + ldy #WINTOP ; TOP offset + sta (J),Y ; save the new top + lda ARG3+LO ; here is the left edge + ldy #WINLEFT ; offset into struct + sta (J),Y ; saved ! +; +; we might have moved current window so update screen cursor and left margin +; + jsr GET_CURSOR ; restore cursor + ldy #WINLEFT ; get left edge + lda (WINDOW),Y ; okay + ldy #WINLM ; add in left margin + clc ; adding + adc (WINDOW),Y ; to find new left edge + sta LEFTMRG ; store for ease of use + ldy #WINXSZ ; get xsize + lda (J),Y ; okay + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI +ZWPOSX: + rts +;------------ +; ZWINSIZE +;------------ +; +; Change the size of window ARG1. If cursor is outside of window, +; move to it. +; +; ARG1 - window ID +; ARG2 - height +; ARG3 - width +; +; Uses [J]. +; +ZWINSIZE: +; +; first put SCRCX,CY into window structure, just in case +; + jsr SAVE_CURSOR ; saved +; +; now do everything +; + lda ARG1+LO ; get the window ID + jsr SETWJ ; and get window pointer + + lda ARG2+LO ; first, check the top + cmp #MAXHEIGHT ; < max height? + bcc CKWA11 ; fine + lda #MAXHEIGHT ; make better + sta ARG2+LO ; it is now +CKWA11: + lda ARG3+LO ; now check left edge + cmp #MAXWIDTH ; howzit compare + bcc CKWA21 ; just fine + lda #MAXWIDTH ; make it the max + sta ARG3+LO ; it is now +CKWA21: + lda ARG2+LO ; get new height + ldy #WINHGHT ; offset + sta (J),Y ; save new height + lda ARG3+LO ; get width + ldy #WINWID ; store width + sta (J),Y ; okay +; +; now we need to figger out new XSIZE, MAXLINES +; + ldy #WINWID ; store width + lda (J),Y ; get width + sec ; have width, subtract margins + ldy #WINRM ; first right margin + sbc (J),Y ; subtracted right margin + ldy #WINLM ; and now for the left margin + sbc (J),Y ; now we have new XSIZE + ldy #WINXSZ ; get offset + sta (J),Y ; save for later ref + lda ARG2+LO ; get new height + ldx #$FF ; this is the counter + sec ; get ready for subs +ZWSZ1: + inx ; count this line + sbc #FONT_H ; subtract off font height + bcs ZWSZ1 ; still some lines + dex ; to keep the input line on screen + txa ; get line count for storage + ldy #WINLINES ; this is how many lines are allowed + sta (J),Y ; saved +; +; check to make sure the cursor is still in the window +; + ldy #WINLM ; get left margin + clc ; for adding + adc (J),Y ; for figgering out right edge + ldy #WINLEFT ; add in left edge + adc (J),Y ; get right column by adding in left one + ldy #WINX ; check X pos + cmp (J),Y ; see if X is still inside? + beq ZWSZ2 ; must move to top left + bcc ZWSZ2 ; ditto if X >= margin + ldy #WINTOP ; get top to figger last line + lda (J),Y ; from the structure + ldy #WINHGHT ; and add in the height + clc ; getting ready for add + adc (J),Y ; to find first line outside of range + ldy #WINY ; now check y + cmp (J),Y ; now check y then + beq ZWSZ2 ; outside, move to top left + bcs ZWSZ3 ; inside so quit +; +; move the cursor to top left if outside of resized window +; +ZWSZ2: + ldy #WINTOP ; top line is here + lda (J),Y ; so get me it + ldy #WINY ; now we be doing y + sta (J),Y ; change Y + ldy #WINLEFT ; move X to left margin + lda (J),Y ; first get left edge + ldy #WINLM ; and add in left margin + clc ; (adding) + adc (J),Y ; to get left spot of cursor + ldy #WINX ; this is x offset + sta (J),Y ; so move X there +; +; now check to see if we mucked with current window +; +ZWSZ3: + lda ARG1+HI ; this is the id + bmi ZWSZ4 ; must be current window + cmp CURWIN ; is it current window? + bne ZWSZX ; nope, so done +ZWSZ4: + ldy #WINLINES ; get how many lines + lda (J),Y ; get number of lines + sta MAXLINES ; set global + ldy #WINXSZ ; get new XSIZE too + lda (J),Y ; get it + sta XSIZE+LO ; this is for quicky comparing + lda #0 ; clear MSB + sta XSIZE+HI + asl XSIZE+LO ; *2 + rol XSIZE+HI + asl XSIZE+LO ; *4 + rol XSIZE+HI + jsr GET_CURSOR ; fix the cursor pos +ZWSZX: + rts +; +;CHECK_WIN_ARGS +; check args to make sure they be okay +; +; ARG2 = top/height +; ARG3 = right/width +; +CHECK_WIN_ARGS: + rts + + ; ------ + ; HLIGHT + ; ------ + +ZLIGHT: + lda ARG1+LO ; get argument + cmp #$10 ; must be <= 8 + bcs ZLIEX ; nope it aint + ora #$80 ; turn on hi bit + jsr COUT ; send it out then +ZLIEX: + rts ; done +; +; actually set the highlight flags according to [A] +; +HLIGHT: +; +; TURN OFF ALL HIGHLIGHTS +; + and #$7F ; turn off high bit + bne ZL1 ; nope, must be something + sta UNDFLG ; and turn of underlining flag + sta INVFLG ; and inverse + rts ; all done +ZL1: + cmp #4 ; underlining + bne ZL_REV ; maybe its INVERSE? + + lda #$80 ; turn on UNDFLG + sta UNDFLG ; with an FF + rts ; done +ZL_REV: + cmp #1 ; INVERSE? + bne ZL_MONO ; maybe monospaced then + lda #$80 ; must be inverse video + sta INVFLG ; and put it in invflg + rts +ZL_MONO: + rts ; fuck it for now! +; +; ZWINATTER - change the scrolling/buffering/scripting/wrapping attributes +; of the window. +; +; ARG1 - window id +; ARG2 - interesting bits +; | buffering | scripting | scrolling | wrapping | +; ARG3 - operation - 0 MOVE +; 1 SET +; 2 CLEAR +; 3 COMPLEMENT +; +ZWINATTR: + lda NARGS ; see how many args + cmp #3 ; check for operation args + beq ZWAT1 ; yes, already there + lda #0 ; zero means MOVE + sta ARG3+LO ; so show it as default +ZWAT1: + lda ARG1+LO ; get window ID + jsr SETWJ ; put window address into [J] + + ldy #WINATR ; get attribute offset + lda (J),Y ; get current attribute + clc ; so we can just branch + + dec ARG3+LO ; decrement to find out what to do + bmi ZWMOVE ; do a move + beq ZWSET ; do a set + dec ARG3+LO ; check once more + beq ZWCLEAR ; clear set ones +; +; this is for the COMPLEMENT operations +; + eor ARG2+LO ; complement bits + bcc ZWAT2 ; done +ZWMOVE: +; +; move into the flag word +; + lda ARG2+LO ; get new flags + bcc ZWAT2 ; done +ZWSET: +; +; set turned on ones +; + ora ARG2+LO ; set'em up + bcc ZWAT2 ; done +ZWCLEAR: +; +; clear just the ones that are on +; + lda ARG2+LO ; get argument + eor #$FF ; turn on all the off ones + and (J),Y ; keep all the other ones +ZWAT2: + sta (J),Y ; and save it back +; +; now, if current window, set necessary flags +; + ldx ARG1+LO ; get window ID + bmi SET_ATTRIBUTES ; assume negative is current window + cpx CURWIN ; is this the current one? + bne ZWATX ; nope, so leave +SET_ATTRIBUTES: +; +; current window, so set flags accordingly +; + ldx #0 ; to turn off flag + ldy #1 ; to turn on flag + ror A ; get wrapping flag into carry + bcc ZWAT3 ; clear it + sty WRPFLG ; set wrapping on + bcs ZWAT33 ; okay +ZWAT3: + stx WRPFLG ; clear wrapping flag +ZWAT33: + ror A ; now check thes crolling flag + bcc ZWAT4 ; not set + sty SCRLFLG ; turn on scrolling flag + bcs ZWAT44 ; okay, next please +ZWAT4: + stx SCRLFLG ; turn off scrolling +ZWAT44: + ror A ; checking the scripting flag + bcc ZWAT5 ; not set + sty SCRIPTFLG ; allow scripting? yes + bcs ZWAT55 ; next flag +ZWAT5: + stx SCRIPTFLG ; allow scripting? no +ZWAT55: + ror A ; this checks the buffering flag + bcc ZWAT6 ; not set + sty BUFFLG ; turn on buffering + bcs ZWATX ; scram +ZWAT6: + stx BUFFLG ; turn off buffering +ZWATX: + rts +; +; ZWINGET - put the window stuff into a table +; +; ARG1 - Window id +; ARG2 - offset +; +ZWINGET: + jsr SAVE_CURSOR ; save x,y into structure + + lda ARG1+LO ; get window ID + jsr SETWJ ; set up window address + + lda ARG2+LO ; get where to start getting + asl A ; make word index + tax ; make index + lda ZWGTBL+LO,X ; get lo part of address + sta K+LO ; save for jumping + lda ZWGTBL+HI,X ; get hi part + sta K+HI ; saved + jsr ZWGVEC ; do the vectoring + stx VALUE+HI ; save hi part + sta VALUE+LO ; and the lo part + jmp PUTVAL ; and return it +ZWGVEC: + jmp (K) ; and goto it boys +ZWG0: + ldx #0 ; zero out high part + ldy #WINTOP ; get window y pos + lda (J),Y ; got it + tay ; need to inc it + iny ; to make it a one-based number + tya ; back to a + rts +ZWG1: + ldx #0 ; zero out high part + ldy #WINLEFT ; get window x pos + lda (J),Y ; got it + tay ; need to inc it + iny ; to make it a one-based number + tya ; back to a + rts +ZWG2: + ldx #0 ; zero out high part + ldy #WINHGHT ; get window height + lda (J),Y ; got it + rts +ZWG3: + ldx #0 ; zero out high part + ldy #WINWID ; window width + lda (J),Y ; got it + rts +ZWG4: + jsr FETCHCY ; get the current Y pos + ldx #0 ; zero out high part + rts +ZWG5: + jsr FETCHCX ; fetch the current X pos + ldx #0 ; zero out high part + rts +ZWG6: + ldx #0 ; zero out high part + ldy #WINLM ; left margin + lda (J),Y ; got it + rts +ZWG7: + ldx #0 ; zero out high part + ldy #WINRM ; right margin + lda (J),Y ; got it + rts +ZWG8: + ldy #WINCRF+HI ; function + lda (J),Y ; got it, lo part + tax ; save hi part + dey ; point to lo part + lda (J),Y ; got lo part + rts +ZWG9: + ldy #WINCRC+HI ; count + lda (J),Y ; got it, hi part + tax ; save it + dey ; now to lo part + lda (J),Y ; got it + rts +ZWG10: + ldy #WINHIGHL ; get high light mode + lda (J),Y ; got it + ldx #0 ; zero out high part + rts +ZWG11: + ldy #WINBGND ; and background + lda (J),Y ; got it + tay ; make index + lda APLCOLOR,Y ; get apl->zip color + tax ; save for return + ldy #WINFORE ; get foreground + lda (J),Y ; got it + tay ; save it + lda APLCOLOR,Y ; get apl->zip color + rts +ZWG12: + ldy #WINFONT ; now for font id + lda (J),Y ; got it + ldx #0 ; zero out high part + rts +ZWG13: + ldy #WINFSIZE+1 ; font size (width) + lda (J),Y ; got it + tax ; save it + dey ; font size (height) + lda (J),Y ; got it + rts +ZWG14: + ldx #0 ; zero out high part + ldy #WINATR ; attributes + lda (J),Y ; got it + rts ; got them! +ZWG15: + ldx #0 ; only 1 byte worth + ldy #WINLCNT ; offset + lda (J),Y ; get more counter + rts +; +; jump table for figgering out where to start filling +; +ZWGTBL: + DW ZWG0,ZWG1,ZWG2,ZWG3,ZWG4,ZWG5,ZWG6,ZWG7 + DW ZWG8,ZWG9,ZWG10,ZWG11,ZWG12,ZWG13,ZWG14,ZWG15 +; +; ZSCROLL - scroll the specified window up or down +; +; ARG1 - window ID +; ARG2 - lines to scroll; <0 scrolls down +; +ZSCROLL: + jsr SAVE_CURSOR ; save where cursor is + + lda #0 ; don't script scroll + sta SCRIPT ; fine, we won't now + + lda ARG1+LO ; get which window + jsr SETWJ ; set up pointer + dec NARGS ; see what we have for lines + bne ZSCR1 ; a passed arg + lda #1 ; 1 line is default + sta ARG2+LO ; so say so +ZSCR1: + ldy #WINTOP ; get me window limits + lda (J),Y ; first top + sta CLSTOP ; save for usage + iny ; now left + lda (J),Y ; okay, get for this window + sta CLSLEFT ; save left + iny ; now it's width + lda (J),Y ; got the window height + sta CLSHEIGHT ; this is it + iny ; this is height + lda (J),Y ; get window's height + sta CLSWIDTH ; save + lda ARG2+HI ; is it negative? + sta SCLDIR ; show direction of scroll + bpl ZSCRL1 ; nope + ldx ARG2+LO ; get how many lines + eor #$FF ; make pos + tax ; put in X for inc + inx ; and make right + bne ZSCRLEX ; done +ZSCRL1: + ldx ARG2+LO ; get how many lines +ZSCRLEX: + stx SCLLINES ; save for routine + jsr DO_SCROLL ; and do the scroll +ZSCRLEX1: + lda #1 ; allow scripting + sta SCRIPT ; we do + jmp GET_CURSOR ; restore the cursor, thank you +; +; ZWINPUT - put some information into window structure. Just CRF/CRC +; is legit now. +; +; ARG1 - window ID +; ARG2 - Word to be saved +; ARG3 - offset of value +; +ZWINPUT: + jsr SAVE_CURSOR ; save the cursor pos + lda ARG1+LO ; get window ID + jsr SETWJ ; have J point to structure + + lda ARG2+LO ; get first value in table + cmp #8 ; 8 = function + beq ZWIPCRF ; so save that + cmp #9 ; this is counter + beq ZWIPCRC ; so set counter + cmp #15 ; LINCNT? + beq ZIPLCT ; then set it too + rts ; just die then +ZIPLCT: + ldy #WINLCNT ; point to line count + bne ZWINPUT2 ; and stash it away +ZWIPCRF: + ldy #WINCRF+1 ; point to window's CR function + bne ZWINPUT1 ; and put it +ZWIPCRC: + ldy #WINCRC+1 ; point to window's CR counter +ZWINPUT1: + lda ARG3+HI ; now get hi part + sta (J),Y ; saved! + dey ; point to lo part +ZWINPUT2: + lda ARG3+LO ; start with lo part + sta (J),Y ; save lo part +ZWIPLCT: + jmp GET_CURSOR ; restore cursor/lincnt + + END diff --git a/apple/yzip/rel.9/xpaging.asm b/apple/yzip/rel.9/xpaging.asm new file mode 100644 index 0000000..ebce363 --- /dev/null +++ b/apple/yzip/rel.9/xpaging.asm @@ -0,0 +1,681 @@ + STTL "--- MEMORY PAGING ROUTINES ---" + PAGE + +; ------------------------- +; POINT [MPC] TO V-ADDR [I] +; ------------------------- + +SETWRD: LDA I+LO + STA MPCL + LDA I+HI + STA MPCM + LDA #0 + STA MPCH ; ZERO TOP BIT + JMP VLDMPC + +; +WANTED: DB 00,00 +; +NEXT: DB 00 +NSUBA: DB 00 +PSUBA: DB 00 +; +YTEMP: DB 00 +ATEMP: DB 00 +NSUBY: DB 00 +; +; set [A](page), [Y](bank) to point to memory page where page in [A] is +; +SETPC: + sta MEMPAGE ; save it for later addition + cmp #P2PAGE ; IS IT A PAGE IN MAIN + bcs VF2 ; No, it might be in aux mem + + lda #>ZBEGIN ; ADD OFFSET TO GET RAM PAGE + ldy #MAIN ; in the main bank + beq VFEXI ; BRA to fetch +VF2: + cmp #PGBEGIN ; is it paged? + bcs VFERR ; yes it be paged, so can't deal with it + cmp #P3PAGE ; is it in Aux Mem, Part 2? + bcs VF3 ; yes, so subtract different amount +; +; this is in lower aux +; + lda #(Z2PAGE-Z1SIZE) ; subtract size from offset + ldy #AUX ; show aux mem + bne VFEXI ; jump to end +VF3: + lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides + ldy #P3BANK ; show page 3 bank +VFEXI: + clc ; get ready for addition + adc MEMPAGE ; now get actual offset + rts +VFERR: +; +; out of range +; + lda #18 + jmp ZERROR +; +; NEXTSPC - inc SPCL and check for wrapping round to next bank +; +NEXTSPC: + inc SPCL ; next lo byte + bne NXSP_EXIT ; no change then + inc SPCH ; next page + lda SPCH ; so get page + cmp #>PRGLBL ; have we reached end of line? + bne NXSP_EXIT ; we be okay + lda SPCBNK ; get bank + bne NXSP1 ; must go to Part 3 + inc SPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta SPCH ; and point to it + rts ; and all done +NXSP1: + lda #Z3PAGE ; get start of page 3 + sta SPCH ; and point there + lda #P3BANK ; and point to this bank + sta SPCBNK ; okey +NXSP_EXIT: + rts +; +; NEXTFPC - inc DPCL and check for wrapping round to next bank +; +NEXTFPC: + inc FPCL ; next lo byte + bne NXFP_EXIT ; no change then + inc FPCH ; next page + lda FPCH ; and get it for checking + cmp #>PRGLBL ; have we reached end of line? + bne NXFP_EXIT ; we be okay + lda FPCBNK ; get bank + bne NXFP1 ; must skip over stuff in middle + inc FPCBNK ; so point to aux bank + lda #Z2PAGE ; first page in aux + sta FPCH ; and point to it + rts ; toots finis +NXFP1: + lda #Z3PAGE ; start of part 3 + sta FPCH ; so show me + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey +NXFP_EXIT: + rts +; +; ADDFPC - add amount in [A] to current FPC and check for bank wrap +; +ADDFPC: + clc ; get ready for add + adc FPCL ; add lo part + sta FPCL ; and save it + bcc AFPX ; all done if no page wrap + inc FPCH ; point to next page + lda FPCH ; get it for compare + cmp #>PRGLBL ; at end of line in main bank? + bne AFPX ; nope, all done then + lda FPCBNK ; get bank + beq AFP1 ; it is main, so we be ok + lda #Z3PAGE ; must go to part 3 if in aux mem + sta FPCH ; thanx + lda #P3BANK ; and point to this bank + sta FPCBNK ; okey + rts ; done +AFP1: + inc FPCBNK ; point to aux + lda #Z2PAGE ; get start in aux + sta FPCH ; and save it +AFPX: + rts +; +; ADDSPC - add amount in [A] to current SPC and check for bank wrap +; +ADDSPC: + clc ; get ready for add + adc SPCL ; add lo part + sta SPCL ; and save it + bcc ASPX ; all done if no page wrap + inc SPCH ; point to next page + lda SPCH ; get it for compare + cmp #>PRGLBL ; at end of line in main bank? + bne ASPX ; nope, all done then + lda SPCBNK ; get bank + beq ASP1 ; it is main, so we be ok + lda #Z3PAGE ; must go to part 3 if in aux mem + sta SPCH ; thanx + lda #P3BANK ; and point to this bank + sta SPCBNK ; okey + rts ; done +ASP1: + inc SPCBNK ; point to aux + lda #Z2PAGE ; get start in aux + sta SPCH ; and save it +ASPX: + rts +; +; PREVFPC - DEC FPCL and check for wrapping round to next bank +; +PREVFPC: + lda FPCL ; get lo part + bne PFPC2 ; it's not zero, so no wrapping + lda FPCH ; get current page + cmp #Z2PAGE ; have we reached beginning of page 2? + beq PFPC1 ; wrap to first bank + cmp #Z3PAGE ; beginning of part 3? + beq PFPC3 ; ayyup + dec FPCH ; point to previous page + bne PFPC2 ; okay +PFPC1: + lda FPCBNK ; get bank + beq VF1ERR ; oops, can't go backwards from main bank + lda #MAIN ; so point to main bank + beq PFPC4 ; and store it away +PFPC3: + lda #AUX ; and point to this bank +PFPC4: + sta FPCBNK ; okey + lda #(>PRGLBL)-1 ; get me last page in part 2 + sta FPCH ; and show me +PFPC2: + dec FPCL ; and point to previous byte + rts +VF1ERR: +; +; out of range +; + lda #19 + jmp ZERROR +; +; PREVSPC - DEC SPCL and check for wrapping round to main bank +; +PREVSPC: + lda SPCL ; get lo part + bne PSPC2 ; it's not zero, so no wrapping + lda SPCH ; get current page + cmp #Z2PAGE ; have we reached beginning of page 2? + beq PSPC1 ; wrap to first bank + cmp #Z3PAGE ; down past page 3? + beq PSPC3 ; sure is + dec SPCH ; point to previous page + bne PSPC2 ; okay +PSPC1: + lda SPCBNK ; get bank + beq VF1ERR ; oops, can't go backwards from main bank + lda #MAIN ; so point to main bank + beq PSPC4 ; so save it +PSPC3: + lda #AUX ; and point to this bank +PSPC4: + sta FPCBNK ; okey + lda #>PRGLBL-1 ; get me last page in low part + sta SPCH ; and show me +PSPC2: + dec SPCL ; and point to previous byte + rts +; +; FP2SP - copy the 3 parts of FPC to SPC +; +FP2SP: + lda FPCBNK + sta SPCBNK + lda FPCH + sta SPCH + lda FPCL + sta SPCL + rts + +; MAKE [MPCPNT],[MPCBNK] POINT TO +; THE RAM PAGE AND BANK THAT HOLDS +; THE V-PAGE MPCH,M +; +VLDMPC: + lda MPCH ; check hi part + bne VLD3 ; NOT IN FIRST V-64K, so must be paged + lda MPCM ; check to see if it is paged + jsr CHECKPRE ; is it preloaded? + bcs VLD3 ; no, so it be paged + jsr SETPC ; so put page/bank into A/Y + sty MPCBNK + sta MPCPNT+HI +NOMUCK: + rts +; +; must be paged, so check for it or read it in +; +VLD3: + lda MPCH + ldy MPCM + jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + clc + adc #>PBEGIN + sta MPCPNT+HI + ldy #PB_BANK ; paging buffers are in aux mem + sty MPCBNK +; +; TEST FOR MUCK +; + lda MUCKFLG + beq NOMUCK + bne VLDZPC ;MAY HAVE MUCKED ZPC SO GO FIX +; +; SAME IDEA AS VLDMPC +; +VLDZPC: + lda INFODOS ; check first for InfoDOS page + beq VLDZ1 ; none + jsr INFO_PAGE ; well, is it? + bcc VLDZ1 ; nope + rts ; all set otherwise +VLDZ1: + lda ZPCH + bne VLDZ3 ;NOT IN FIRST V-64K, so must be paged + lda ZPCM ; check to see if it is paged + jsr CHECKPRE ; is it preloaded? + bcs VLDZ3 ; no, so it must be paged + jsr SETPC ; point to correct bank and page + sty ZPCBNK ; set bank + sta ZPCPNT+HI ; and MSB of pointer +NOZMUCK: + rts +VLDZ3: ;MUST BE PAGED + lda ZPCH + ldy ZPCM + jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + clc + adc #>PBEGIN + sta ZPCPNT+HI + ldy #PB_BANK + sty ZPCBNK +; +; TEST MUCKING +; + lda MUCKFLG + beq NOZMUCK + jmp VLDMPC ;MAY HAVE MUCKED MPC SO GO FIX + + +; FIND V-PAGE A,Y IF IT IS IN MEM +; AND RETURN WITH LINKED LIST +; PROPERLY MAINTAINED +; IF V-PAGE A,Y NOT IN MEM +; GET FROM DISK AND PUT IN RIGHT +; PLACE + +MUCKFLG: DB 00 ;00 IF PAGING BUFFERS NOT MUCKED + +PAGE: + sta WANTED+HI + sty WANTED+LO + ldx #0 + stx MUCKFLG ; CLEAR MUCK FLAG + jsr WHERE + bcc TOUGH ; PAGE IS RESIDENT IN PAGING SPACE +; +; PAGE MUST BE BROUGHT IN FROM DISK +; + ldx CURRENT ;GET BUFFER TO PUT PAGE INTO + lda NEXTPNT,X ;BY LOOKING AT NEXT POINTER + sta CURRENT ;MAKE IT THE CURRENT BUFFER + tax + lda WANTED+HI ;LET BUFFER MAP KNOW + sta VPAGEH,X ;WHICH PAGE + lda WANTED+LO ;IS GOING TO + and #$FE ; make address be even + sta VPAGEL,X ;BE THERE +;*** +; point to the next page too +; + ora #1 ; add one to point to next 256 byte page + pha ; save it + txa ; get pointer + tay ; into y + iny ; point to next buffer + pla ; get second buffer back + sta VPAGEL,Y ; so point to it + lda VPAGEH,X ; get MSB + sta VPAGEH,Y ; and save it +; +; A = WANTED+HI +; Y = WANTED+LO +; X = BUFFER +; + lda WANTED+LO + and #$FE ; clear low bit to make it even + tay ; want it in y +;*** + lda WANTED+HI + ldx CURRENT + jsr GETVPAGE ; PUT V-PAGE A,Y INTO PAGING BUFFER X +;*** + dec MUCKFLG ; INDICATE A MUCKING + bne PAGEXIT ; and return current buffer +TOUGH: + and #$FE ; make even page, please + sta NEXT + cmp CURRENT ; GETS REALY SCREWED IF CURRENT==NEXT + beq PAGEXIT ; DO NOT CHANGE POINTERS IF IT DOES +; +; Y=NEXT(CURRENT) +; DO THE RIGHT THING TO THE POINTERS +; +; ldy CURRENT +; lda NEXTPNT,Y +; sta NSUBCUR + lda NEXT + jsr DETATCH + ldy CURRENT + lda NEXT + jsr INSERT + lda NEXT + sta CURRENT +PAGEXIT: +;*** perhaps add one to point to correct buffer + lda WANTED+LO ; get LSB + and #$01 ; pick up even/odd bit + clc ; doing add + adc CURRENT ; point to correct buffer + rts + +GETVPAGE: + sta DBLOCK+HI + sty DBLOCK+LO + txa ; get which paging buffer + clc + adc #>PBEGIN ; and set up abs addr + sta DBUFF+HI ; thank you, that's much better + ldx #PB_BANK + stx DSKBNK + jmp GETDSK + +; INSERT A AFTER Y +; A.next = Y.next +; Y.next = A +; A.previous = Y +; [Y.next].previous = A +INSERT: + tax + lda NEXTPNT,Y ; Y.next + sta NEXTPNT,X ; A.next = Y.next + pha ; save Y.next for later + txa + sta NEXTPNT,Y ; Y.next = A + tya + sta PREVPNT,X ; A.prev = Y + pla ; get Y.next back + tay ; [Y.next].previous + txa + sta PREVPNT,Y ; [Y.next].previous = A + rts + + IF 0 +; +; old one, which puts A AFTER! Y +; +; PREV(A)=Y +; PREV(NEXT(Y))=A +; NEXT(A)=NEXT(Y) +; NEXT(Y)=A + + sta ATEMP + sty YTEMP + tax + tya + sta PREVPNT,X + + lda NEXTPNT,Y + sta NSUBY + txa + ldx NSUBY + sta PREVPNT,X + + txa + ldx ATEMP + sta NEXTPNT,X + + lda ATEMP + sta NEXTPNT,Y + rts + ENDIF + +; DETATCH BUFFER >A< +; NEXT(PREV(A))=NEXT(A) +; PREV(NEXT(A))=PREV(A) + +DETATCH: + tax + lda NEXTPNT,X + tay ; Y == A.next + lda PREVPNT,X ; get A.previous + tax ; X == A.previous + tya ; get A.next + sta NEXTPNT,X ; [A.previous].next = A.next + txa ; get A.previous + sta PREVPNT,Y ; [A.next].previous = A.previous + rts + + +; RETURN BUFFER OF PAGE [WANTED] +; IN >A< ELSE SEC (Y=WANTED+LO) + +WHERE: LDX #NUMBUFS-1 +WHLOOP: + LDA WANTED+HI + CMP VPAGEH,X ;>SAME + BEQ WHGOT +WHNOGOT: + DEX + BPL WHLOOP + SEC + RTS +WHGOT: + TYA + CMP VPAGEL,X + BNE WHNOGOT + TXA + CLC + RTS +; +; CHECKPRE - check to see if page in [A] is in preloaded +; +CHECKPRE: + cmp TBLPUR ; check against PURE tables + bcc CHKPEXY ; must be preloaded then +CHKP1: + cmp FUNPRE ; is it in function preload? + bcc CHKPEXN ; preloaded function > desired, not preloaded + cmp FUNPUR ; how bout at end? + bcs CHKPEXN ; it is not preloaded +CHKP3: + clc ; doing add + adc FUNPGE ; get me memory page for function +CHKPEXY: + clc ; show it is preloaded + rts ; then we got it +CHKPEXN: + sec ; show it ain't here + rts +; +; INFO_PAGE - is it one of the special preloaded pages for infoDOS? If it +; is, then set up ZPCPNTR to point to it, and set carry. Otherwise, +; clear carry to show it ain't. +IPAGE: ds 2 +INFO_PAGE: + lda ZPCH ; get 2 parts + sta IPAGE+HI + lda ZPCM + sta IPAGE+LO + lsr IPAGE+HI ; /2 to get 512 block + ror IPAGE+LO + ldy #SGTSEG ; point to first segment, MSB + lda (INFODOS),Y ; howzit look? + iny ; point to LSB + cmp IPAGE+HI + bcc INFP1 ; might be interesting + bne INFPNX ; not here, < than minimum + lda (INFODOS),Y ; how bout LSB + cmp IPAGE+LO + beq INFPYX ; found it + bcs INFPNX ; nope, < than minimum again +; +; here, it's at least > than minimum +; +INFP1: +; iny ; point at end block, MSB + lda INFODOS_END+HI ; howz end segment look + cmp IPAGE+HI + bcc INFPNX ; nope, > than maximum of special + bne INFPYX ; yup, < than maximum of special +; iny ; LSB of last one + lda INFODOS_END+LO ; is LSB < special? + cmp IPAGE+LO ; MSB of current one == MSB of special + bcc INFPNX ; nope, not here +INFPYX: + ldy #SGTSEG+1 ; point back to start block, LSB + lda (INFODOS),Y ; get start block + asl A ; *2 to get start page + sta IPAGE+LO ; save it + lda ZPCM + sec ; doing sub + sbc IPAGE+LO ; get offset into special block + clc ; now add in offset + adc #>SP_START ; get the start of special area + sta ZPCPNT+HI ; show ZPCPNTR + lda #SP_BANK ; which bank + sta ZPCBNK ; okey + sec ; show it was here + rts +INFPNX: + clc ; show not here + rts ; g'day + + + +CHKPEXN0: + +GETBYT: + ldy MPCL + jsr MFETCH ; go and get it + inc MPCL ;POINT TO NEXT BYTE + bne GETGOT ;IF NO CROSS WE ARE STILL VALID + inc MPCM + bne GET1 + inc MPCH +GET1: + pha ; save byte + jsr VLDMPC + pla ; and get it back +GETGOT: + tay ;SET FLAGS + rts ;RED SLIPPER TIME +; +; NEXTPC - Fetch the byte at the current ZPC, point to next byte and +; validate pointer +; +NEXTPC: + ldy ZPCL ; get low pointer + jsr ZFETCH ; fetch @ZPCPNT + inc ZPCL + bne NXTGOT + inc ZPCM + bne CRSZ1 + inc ZPCH +CRSZ1: + pha ; save opcode + jsr VLDZPC + pla ; and get it back +NXTGOT: + tay + rts + +; +; STASHB - use SPC to save a byte in either aux or main mem +; +STASHB: + ldy SPCBNK ; get the bank + bmi SB1 ; must be in upper RAM + sta WRTBNK,Y ; set bank + ldy #0 ; can only do this with Y + sta (SPC),Y ; get the sucker + beq SBEXI ; jump to end it +; +; this is in aux mem, >$E000 +; +SB1: + ldy SPCH ; get high part + sty SBMOD+2 ; and self mod my code + ldy SPCL ; and get the low part + sta ALTZP+AUX ; talk about aux mem +SBMOD: + sta Z3BEGIN,Y ; store the little byte + sta ALTZP+MAIN ; go back to main mem +SBEXI: + sta WRTBNK+MAIN ; and write to main + rts +; +; FETCHB - fetch a byte from either main memory, aux memory, or upper +; Aux memory +; +FETCHB: + ldy FPCBNK ; get the bank + bmi FB1 ; must be in upper RAM + jsr ZERO_FB ; go to low end fetch + rts +; +; this is in aux mem, >$E000 +; +FB1: + lda FPCH ; get which page + sta FBMOD+2 ; and show in operand + ldy FPCL ; get which byte + sta ALTZP+AUX ; talk about aux mem +FBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + tay ; set condition code + rts +; +; ZFETCH - after checking for which bank (main, aux 1 or aux 2), go get +; the byte @ ZPCPNT, with the offset being in [Y] +; +ZFETCH: + ldx ZPCBNK ; get the bank + bmi ZFB1 ; must be in upper RAM + jsr ZERO_ZF ; go to low end fetch + rts +; +; this is in aux mem, >$D000 +; +ZFB1: + lda ZPNTH ; which page are we talking about + sta ZBMOD+2 ; show in the operand + sta ALTZP+AUX ; talk about aux mem +ZBMOD: lda Z3BEGIN,Y ; get the sucker + sta ALTZP+MAIN ; go back to main mem + tax ; set condition code + rts +; +; MFETCH - after checking for which bank (main, aux 1 or aux 2), go get +; the byte @MPCPNT, with the offset being in [Y] +; +MFETCH: + ldx MPCBNK ; get the bank + bmi MB1 ; must be in upper RAM + jsr ZERO_MF ; go to low end fetch + rts +; +; this is in aux mem, >$D000 +; +MB1: + lda MPNTH ; which page are we talking about + sta MBMOD+2 ; show in the operand + sta ALTZP+AUX ; talk about aux mem + +MBMOD: lda Z3BEGIN,Y ; get the sucker + + sta ALTZP+MAIN ; go back to main mem + tax ; set condition code + rts + + + END diff --git a/apple/yzip/rel.9/yzip.asm b/apple/yzip/rel.9/yzip.asm new file mode 100644 index 0000000..40cef6e --- /dev/null +++ b/apple/yzip/rel.9/yzip.asm @@ -0,0 +1,86 @@ + ; -------------------------- + ; YZIP + ; Z-CODE INTERPRETER PROGRAM + ; FOR APPLE ][e/][c/][gs + ; -------------------------- + + ; INFOCOM, INC. + ; 125 CAMBRIDGEPARK DRIVE + ; CAMBRIDGE, MA 02140 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + + PL 50000 ; PAGE LENGTH OF PRINTER + +DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER (1 = YES) +CHECKSUM EQU 0 ; == 1 for generating save/restore checksum + + ; ----------- + ; 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 -- IMPURE CODE TOO LARGE (BM 1/20/86) + ; 14 -- DRIVE ACCESS + ; 15 -- NOT AN EZIP GAME + ; 16 -- ILLEGAL EXTENDED RANGE X-OP + ; 17 -- BAD VIRTUAL PAGE + ; 18 -- SETPC NOT PRELOADED + ; 19 -- PREVIOUS (SPC/FPC) NOT POSSIBLE + ; 20 -- PICTURE NOT FOUND + ; 21 -- ZERO OBJECT TO BE REMOVED + ; 22 -- OBJECT TOO BIG (ZLOC) + ; 23 -- Bad read: Read != Asked for + ; 24 -- Bad read: Retry 1 != Retry 2 + ; 25 -- Clear of zero height/width window + + TITLE "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + INCLUDE ZIP.EQU + INCLUDE ZERO.EQU + INCLUDE PRODOS.EQU + INCLUDE APPLE.EQU + INCLUDE MACROS.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + INCLUDE ZBEGIN.ASM + INCLUDE MAIN.ASM + INCLUDE SUBS.ASM + INCLUDE DISPATCH.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + INCLUDE ZDOS.ASM + INCLUDE MACHINE.ASM + INCLUDE IO.ASM + INCLUDE VERIFY.ASM + INCLUDE SCREEN.ASM + INCLUDE TABLES.ASM + INCLUDE WINDOWS.ASM + INCLUDE DLINE.ASM + INCLUDE PIC.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + INCLUDE OPS012.ASM + INCLUDE OPSX.ASM + INCLUDE READ.ASM + INCLUDE ZSAVRES.ASM + + TITLE "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + INCLUDE XPAGING.ASM + INCLUDE ZSTRING.ASM + INCLUDE OBJECTS.ASM + + BLKB ZBEGIN-$,0 + END + diff --git a/apple/yzip/rel.9/yzip.bin b/apple/yzip/rel.9/yzip.bin new file mode 100644 index 0000000..e69bbe6 Binary files /dev/null and b/apple/yzip/rel.9/yzip.bin differ diff --git a/apple/yzip/rel.9/yzip.lst b/apple/yzip/rel.9/yzip.lst new file mode 100644 index 0000000..c579869 --- /dev/null +++ b/apple/yzip/rel.9/yzip.lst @@ -0,0 +1,15774 @@ + Wed May 24 1989 15:00 Page 1 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + + + + + 2500 A.D. 6502 Macro Assembler - Version 4.01a + ------------------------------------------------ + + Input Filename : YZIP.asm + Output Filename : YZIP.obj + + + 1 ; -------------------------- + 2 ; YZIP + 3 ; Z-CODE INTERPRETER PROGRAM + 4 ; FOR APPLE ][e/][c/][gs + 5 ; -------------------------- + 6 + 7 ; INFOCOM, INC. + 8 ; 125 CAMBRIDGEPARK DRIVE + 9 ; CAMBRIDGE, MA 02140 + 10 + 11 ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + 12 + 13 PL 50000 ; PAGE LENGTH OF PRINTER + 14 + 15 0000 DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER (1 = YES) + 16 0000 CHECKSUM EQU 0 ; == 1 for generating save/restore checksum + 17 + 18 ; ----------- + 19 ; ERROR CODES + 20 ; ----------- + 21 + 22 ; 00 -- INSUFFICIENT RAM + 23 ; 01 -- ILLEGAL X-OP + 24 ; 02 -- ILLEGAL 0-OP + 25 ; 03 -- ILLEGAL 1-OP + 26 ; 04 -- ILLEGAL 2-OP + 27 ; 05 -- Z-STACK UNDERFLOW + 28 ; 06 -- Z-STACK OVERFLOW + 29 ; 07 -- ILLEGAL PROPERTY LENGTH (GETP) + 30 ; 08 -- DIVISION BY ZERO + 31 ; 09 -- ILLEGAL ARGUMENT COUNT (EQUAL?) + 32 ; 10 -- ILLEGAL PROPERTY ID (PUTP) + 33 ; 11 -- ILLEGAL PROPERTY LENGTH (PUTP) + 34 ; 12 -- DISK ADDRESS OUT OF RANGE + 35 ; 13 -- IMPURE CODE TOO LARGE (BM 1/20/86) + 36 ; 14 -- DRIVE ACCESS + 37 ; 15 -- NOT AN EZIP GAME + 38 ; 16 -- ILLEGAL EXTENDED RANGE X-OP + 39 ; 17 -- BAD VIRTUAL PAGE + 40 ; 18 -- SETPC NOT PRELOADED + 41 ; 19 -- PREVIOUS (SPC/FPC) NOT POSSIBLE + 42 ; 20 -- PICTURE NOT FOUND + 43 ; 21 -- ZERO OBJECT TO BE REMOVED + 44 ; 22 -- OBJECT TOO BIG (ZLOC) + 45 ; 23 -- Bad read: Read != Asked for + 46 ; 24 -- Bad read: Retry 1 != Retry 2 + 47 ; 25 -- Clear of zero height/width window + 48 0000 + 49 0000 TITLE "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + 50 0000 INCLUDE ZIP.EQU + 51 0000 STTL "--- YZIP EQUATES ---" + 52 PAGE + Wed May 24 1989 15:00 Page 2 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- YZIP EQUATES ---" + + 53 + 54 0009 VERSID EQU 9 ; VERSION OF INTERPRETER + 55 ; See file "versions" for complete descriptions + 56 + 57 00FF TRUE EQU $FF + 58 0000 FALSE EQU 0 + 59 + 60 ; --------------------- + 61 ; Segment table equates + 62 ; --------------------- + 63 0000 SGTDISKS EQU 0 ; number of disks + 64 0002 SGTPAD EQU SGTDISKS+2 ; just some extra room + 65 0012 SGTCHKS1 EQU SGTPAD+16 ; Checksum for disk 1 (PRELOAD) + 66 0014 SGTPICOF1 EQU SGTCHKS1+2 ; N/A + 67 0016 SGTSEG1 EQU SGTPICOF1+2 ; # of segments + 68 0018 SGTGPOF1 EQU SGTSEG1+2 ; Global Picture Directory + 69 001A SGTTBLS EQU SGTGPOF1+2 ; Start of table preload (should be 0) + 70 001C SGTTBLE EQU SGTTBLS+2 ; Last page of table preload + 71 001E SGTTBLX EQU SGTTBLE+2 ; N/A + 72 0020 SGTFUNS EQU SGTTBLX+2 ; First page of function preload + 73 0022 SGTFUNE EQU SGTFUNS+2 ; End page of function preload + 74 0024 SGTFUNX EQU SGTFUNE+2 ; N/A + 75 0026 SGTDSK EQU SGTFUNX+2 ; Actual start of disk segment tables + 76 + 77 0000 SGTCHKS EQU 0 ; check sum for file + 78 0002 SGTPICOF EQU 2 ; picture data offset + 79 0004 SGTNSEG EQU 4 ; # of segments in this list + 80 0006 SGTGPOF EQU 6 ; Global Directory Offset + 81 0008 SGTSEG EQU 8 ; start of segments + 82 ; --------------------- + 83 ; Z-CODE HEADER OFFSETS + 84 ; --------------------- + 85 + 86 0000 ZVERS EQU 0 ; VERSION BYTE + 87 0001 ZMODE EQU 1 ; MODE SELECT BYTE + 88 0002 ZID EQU 2 ; GAME ID WORD + 89 0004 ZENDLD EQU 4 ; # OF QUADWORDS ON SIDE 1 OF DISK + 90 0006 ZGO EQU 6 ; EXECUTION ADDRESS + 91 0008 ZVOCAB EQU 8 ; START OF VOCABULARY TABLE + 92 000A ZOBJEC EQU 10 ; START OF OBJECT TABLE + 93 000C ZGLOBAL EQU 12 ; START OF GLOBAL VARIABLE TABLE + 94 000E ZPURBT EQU 14 ; START OF "PURE" Z-CODE + 95 0010 ZFLAGS EQU 16 ; FLAG WORD + 96 0012 ZSERIA EQU 18 ; 3-WORD SERIAL NUMBER + 97 0018 ZFWORD EQU 24 ; START OF FWORDS TABLE + 98 001A ZLENTH EQU 26 ; LENGTH OF Z-PROGRAM IN WORDS + 99 001C ZCHKSM EQU 28 ; Z-CODE CHECKSUM WORD + 100 001E ZINTWD EQU 30 ; INTERPRETER ID WORD (SUPPLIED BY EZIP) + 101 0020 ZSCRWD EQU 32 ; SCREEN PARAMETER WORD ( " " " ) + 102 0022 ZHWRD EQU 34 ; DISPLAY WIDTH IN PIXELS + 103 0024 ZVWRD EQU 36 ; DISPLAY HEIGHT IN PIXELS + 104 0026 ZFWRD EQU 38 ; FONT HEIGHT, FONT WIDTH + 105 0028 ZFOFF EQU 40 ; FUNCTION OFFSET + 106 002A ZSOFF EQU 42 ; STRING OFFSET + 107 002C ZCLRWD EQU 44 ; FORGROUND COLOR, BACKGROUND COLOR + 108 002E ZTCHAR EQU 46 ; POINTER TO TBL OF TERMINATING CHARS + 109 0030 ZTWIDTH EQU 48 ; Running counter for table output char width + 110 0032 ZCRFUNC EQU 50 ; FUNCTION FOR CARRIAGE RETURNS + 111 0034 ZCHRSET EQU 52 ; POINTER TO CHAR SET TBL + 112 0036 ZEXTAB EQU 54 ; Points to extension table, if needed + 113 ; + 114 ; Extension table offsets + 115 ; + 116 0000 ZEXTLEN EQU 0 ; Length of extension table + 117 0002 ZMSLOCX EQU 2 ; x location of mouse + 118 0004 ZMSLOCY EQU 4 ; y location of mouse + 119 0006 ZMSETBL EQU 6 ; MOUSE TBL CHANGE WORD + 120 0008 ZMSEDIR EQU 8 ; DIRECTION MENU + 121 000A ZMSEINV EQU 10 ; INVENTORY MENU + 122 000C ZMSEVRB EQU 12 ; FREQUENT VERB MENU + 123 000E ZMSEWRD EQU 14 ; FREQUENT WORD MENU + 124 0010 ZBUTTN EQU 16 ; BUTTON HANDLER + 125 0012 ZJOYST EQU 18 ; JOYSTICK HANDLER + 126 0014 ZBSTAT EQU 20 ; BUTTON STATUS + 127 0016 ZJSTAT EQU 22 ; JOYSTICK STATUS + Wed May 24 1989 15:00 Page 3 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- YZIP EQUATES ---" + + 128 ; + 129 ; ZFLAGS values + 130 ; + 131 0001 FSCRI EQU $01 ; scripting? + 132 0002 FMONO EQU $02 ; mono spaced font? + 133 0004 FSTAT EQU $04 ; status line refresh? + 134 0008 FDISP EQU $08 ; uses DISPLAY operations? + 135 0010 FUNDO EQU $10 ; uses UNDO? + 136 0020 FMOUS EQU $20 ; uses mouse? + 137 0040 FCOLO EQU $40 ; uses color? + 138 0080 FMENU EQU $80 ; uses menus? + 139 ;--------------- + 140 ; Picture data + 141 ;--------------- + 142 ;=== DATA HEADER === + 143 0000 PHFID EQU 0 ; File ID + 144 0001 PHFLG EQU PHFID+1 ; Flags + 145 0002 PHHUFF EQU PHFLG+1 ; Pointer to Huffman data + 146 0004 PHNLD EQU PHHUFF+2 ; # entries in local directory + 147 0006 PHNGD EQU PHNLD+2 ; # entries in global directory + 148 0008 PHDSIZE EQU PHNGD+2 ; Local directory entry size + 149 000A PHCHKS EQU PHDSIZE+2 ; File Checksum + 150 000C PHFVERS EQU PHCHKS+2 ; File Version (N/A) + 151 000E PHEXTRA EQU PHFVERS+2 ; Extra room for getting fatter + 152 0010 PHSIZE EQU 16 ; 16 bytes is header size + 153 ;=== DATA HEADER FLAGS === + 154 0001 PHFGD EQU $1 ; data has global directory + 155 0002 PHFHUFF EQU $2 ; Huffman encoded pictures + 156 0004 PHFHUFF1 EQU $4 ; All pictures use same Huff tree + 157 0008 PHFPAL EQU $8 ; No pallette information + 158 ;=== LOCAL DIRECTORY === + 159 0000 PLDID EQU 0 ; Picture ID + 160 0002 PLDWID EQU PLDID+2 ; Picture Width + 161 0003 PLDHGHT EQU PLDWID+1 ; Picture Height + 162 0004 PLDFLG EQU PLDHGHT+1 ; Flags + 163 0005 PLDPTR EQU PLDFLG+1 ; Pointer to picture data + 164 0008 PLDSIZE EQU PLDPTR+3 ; size of local directory entry + 165 + 166 0000 END + 167 + 168 0000 INCLUDE ZERO.EQU + 169 0000 STTL "--- ZERO PAGE VARIABLES ---" + 170 PAGE + Wed May 24 1989 15:00 Page 4 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ZERO PAGE VARIABLES ---" + + 171 + 172 0000 SCRCX EQU 0 ; CURSOR HORIZONTAL + 173 0001 SCRCY EQU SCRCX+1 ; CURSOR VERTICAL + 174 0002 SCRBTM EQU SCRCY+1 ; first line outside current window + 175 0003 MAXLINES EQU SCRBTM+1 ; maximum number of lines in window + 176 0004 LEFTMRG EQU MAXLINES+1 ; left edge + left margin in current window + 177 0005 WINDOW EQU LEFTMRG+1 ; (WORD) address of current window structure + 178 0007 LINE_X EQU WINDOW+2 ; (WORD) width of line counter + 179 0009 CC_OFF EQU LINE_X+2 ; save offset for char drawing + 180 000A CLSLEFT EQU CC_OFF+1 ; screen limits for CLS code + 181 000B CLSTOP EQU CLSLEFT+1 ; top of screen + 182 000C CLSWIDTH EQU CLSTOP+1 ; # of columns + 183 000D CLSHEIGHT EQU CLSWIDTH+1 ; # of lines + 184 ; + 185 ; some variables for all the screen positioning code + 186 ; + 187 000E NY_DATA EQU CLSHEIGHT+1 ; place for GET/PUT_NYBBLE to use + 188 000F CH_OFFSET EQU NY_DATA+1 ; offset into char data table + 189 0010 DATALOOP EQU CH_OFFSET+1 ; loop counter for byte works + 190 0011 BITOFF EQU DATALOOP+1 ; bit offset into screen byte + 191 0012 CH_DATA EQU BITOFF+1 ; actual char data being worked on + 192 0013 SCR_DATA EQU CH_DATA+1 ; screen byte being worked on + 193 0014 SH_LOOP EQU SCR_DATA+1 ; loop counter for bit shifting + 194 0015 SCROLLY EQU SH_LOOP+1 ; save spot for y pos when scrolling + 195 0016 RETRIES EQU SCROLLY+1 ; (BYTE) Machine ID + 196 0017 CHRMAX EQU RETRIES+1 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD + 197 0018 SCLLINES EQU CHRMAX+1 ; (BYTE) how many lines to scroll + 198 0019 FMTTBL EQU SCLLINES+1 ; (BYTE) flag to show formatted table output + 199 001A STMASK EQU FMTTBL+1 ; (BYTE) Mask to use on first byte of CLS + 200 001B ENDMASK EQU STMASK+1 ; (BYTE) Mask to use on last byte of CLS + 201 001C CHPTR EQU ENDMASK+1 ; (WORD) pointer to char data + 202 001C SCOFF EQU CHPTR ;(BYTE) Offset used by scroll + 203 001D SCLDIR EQU CHPTR+1 ;(BYTE) Direction of scroll - >0 up, <0 down + 204 001E DSEGS EQU CHPTR+2 ; (WORD) Pointer to current disk's segments + 205 ;WIDE_FLAG EQU SCOFF+1 ; (BYTE) <> 0 if 16 bytes in char data + 206 ;DSEGS EQU WIDE_FLAG+1 ; (WORD) Pointer to current disk's segments + 207 0020 LASTWV EQU DSEGS+2 ; last of the WINDOW variables + 208 + 209 0050 ZEROPG EQU $50 ; FIRST FREE Z-PAGE LOCATION + 210 ; + 211 ; these are first, cuz ZBOOT inits them so we don't want to clear them + 212 ; at ZBEGIN warm start + 213 ; + 214 0050 GLOBAL EQU ZEROPG ; (Relative Addr.) GLOBAL VARIABLE POINTER + 215 0052 VOCAB EQU GLOBAL+2 ; (ADDRESS) Vocab table pointer + 216 0055 FWORDS EQU VOCAB+3 ; (ADDRESS) F-WORDS TABLE POINTER + 217 0058 MOUSEF EQU FWORDS+3 ; (BYTE) ==-1/1 if we have mouse/joystick + 218 0059 INFODOS EQU MOUSEF+1 ; (WORD) if <>0, then pointer to D2SEG + 219 005B FUNOFF EQU INFODOS+2 ; (ADDRESS) Function Offset (ZFOFF*8) + 220 005B FOFFH EQU FUNOFF ; (BYTE) Hi part + 221 005C FOFFM EQU FUNOFF+1 ; (BYTE) Middle part + 222 005D FOFFL EQU FUNOFF+2 ; (BYTE) Lo part + 223 005E STROFF EQU FUNOFF+3 ; (ADDRESS) String Offset (ZSOFF*8) + 224 005E SOFFH EQU STROFF ; (BYTE) Hi part + 225 005F SOFFM EQU STROFF+1 ; (BYTE) Middle part + 226 0060 SOFFL EQU STROFF+2 ; (BYTE) Lo part + 227 ; + 228 ; Beginning of warm start zeroing + 229 ; + 230 0061 OPCODE EQU STROFF+3 ; (BYTE) CURRENT OPCODE + 231 0062 NARGS EQU OPCODE+1 ; (BYTE) # ARGUMENTS + 232 0063 ARG1 EQU OPCODE+2 ; (WORD) ARGUMENT #1 + 233 0065 ARG2 EQU OPCODE+4 ; (WORD) ARGUMENT #2 + 234 0067 ARG3 EQU OPCODE+6 ; (WORD) ARGUMENT #3 + 235 0069 ARG4 EQU OPCODE+8 ; (WORD) ARGUMENT #4 + 236 006B ARG5 EQU OPCODE+10 ; (WORD) + 237 006D ARG6 EQU OPCODE+12 ; (WORD) + 238 006F ARG7 EQU OPCODE+14 ; (WORD) + 239 0071 ARG8 EQU OPCODE+16 ; (WORD) + 240 0073 ABYTE EQU OPCODE+18 ; (BYTE) X-OP ARGUMENT BYTE + 241 0074 BBYTE EQU OPCODE+19 ; (BYTE) XCALL ARG BYTE (EZIP) + 242 0075 ADEX EQU OPCODE+20 ; (BYTE) X-OP ARGUMENT INDEX + 243 0076 VALUE EQU OPCODE+21 ; (WORD) VALUE RETURN REGISTER + 244 0078 I EQU VALUE+2 ; (WORD) GEN-PURPOSE REGISTER #1 + 245 007A J EQU VALUE+4 ; (WORD) GEN-PURPOSE REGISTER #2 + Wed May 24 1989 15:00 Page 5 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ZERO PAGE VARIABLES ---" + + 246 007C K EQU VALUE+6 ; (WORD) GEN-PURPOSE REGISTER #3 + 247 007E L EQU VALUE+8 ; (WORD) GEN-PURPOSE REGISTER #4 + 248 0080 ZPC EQU VALUE+10 ; (3 BYTES) ZIP PROGRAM COUNTER + 249 0080 ZPCL EQU ZPC ; (BYTE) <8 BITS OF [ZPC] + 250 0081 ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] + 251 0082 ZPCH EQU ZPC+2 ; (BYTE) >BIT OF [ZPC] + 252 0083 ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE + 253 0083 ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 254 0084 ZPNTH EQU ZPCPNT+1 ; (BYTE) + 255 0085 ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 256 0086 MPC EQU ZPCPNT+3 ; (3 BYTES) MEMORY PROGRAM COUNTER + 257 0086 MPCL EQU MPC ; (BYTE) <8 BITS OF [MPC] + 258 0087 MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] + 259 0088 MPCH EQU MPC+2 ; (BYTE) >BIT OF [MPC] + 260 0089 MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE + 261 0089 MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) + 262 008A MPNTH EQU MPCPNT+1 ; (BYTE) + 263 008B MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY + 264 008C FPC EQU MPCBNK+1 ; (3 Bytes) Fetch pointer + 265 008C FPCL EQU FPC ; (BYTE) Low part + 266 008D FPCH EQU FPCL+1 ; (BYTE) High Part + 267 008E FPCBNK EQU FPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 268 008F SPC EQU FPCBNK+1 ; (3 Bytes) Fetch pointer + 269 008F SPCL EQU SPC ; (BYTE) Low part + 270 0090 SPCH EQU SPCL+1 ; (BYTE) High Part + 271 0091 SPCBNK EQU SPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + 272 + 273 ; Z-STRING MANIPULATION VARIABLES + 274 + 275 0092 LINLEN EQU SPCBNK+1 ; (BYTE) LENGTH OF CURRENT LINE + 276 0093 SOURCE EQU LINLEN+1 ; (BYTE) counter for read + 277 0094 WRDLEN EQU SOURCE+1 ; (BYTE) LENGTH OF CURRENT WORD + 278 0095 ESIZE EQU WRDLEN+1 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES + 279 0096 PSET EQU ESIZE+1 ; (BYTE) PERMANENT CHARSET + 280 0097 TSET EQU PSET+1 ; (BYTE) TEMPORARY CHARSET + 281 0098 ZCHAR EQU TSET+1 ; (BYTE) CURRENT Z-CHAR + 282 0099 OFFSET EQU ZCHAR+1 ; (BYTE) F-WORD TABLE OFFSET + 283 009A ZFLAG EQU OFFSET+1 ; (BYTE) Z-WORD ACCESS FLAG + 284 009B ZWORD EQU ZFLAG+1 ; (WORD) CURRENT Z-WORD + 285 009D CONCNT EQU ZWORD+2 ; (BYTE) Z-STRING SOURCE COUNTER + 286 009E CONIN EQU CONCNT+1 ; (BYTE) CONVERSION SOURCE INDEX + 287 009F CONOUT EQU CONIN+1 ; (BYTE) CONVERSION DEST INDEX + 288 00A0 DIRTBL EQU CONOUT+1 ; (WORD) CONTAINS TBLE TO STORE CHARS TO + 289 00A2 XSIZE EQU DIRTBL+2 ; (WORD) SCREEN WIDTH FOR TESTS + 290 00A4 RAND EQU XSIZE+2 ; (WORD) Random number offset + 291 00A6 CURWIN EQU RAND+2 ; (BYTE) WHICH WINDOW TO WRITE IN + 292 00A7 LENGTH EQU CURWIN+1 ; (WORD) CHAR POSITION ON THE SCREEN + 293 00A9 CHRCNT EQU LENGTH+2 ; (BYTE) CHAR POSITION IN [LBUFF] + 294 00AA SCRIPT EQU CHRCNT+1 ; (BYTE) SCRIPT ENABLE FLAG + 295 00AB LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER + 296 00AC IOCHAR EQU LINCNT+1 ; (BYTE) CHARACTER BUFFER + 297 00AD COLORP EQU IOCHAR+1 ; (WORD) Pointer to current background color + 298 00AF ZSP EQU COLORP+2 ; (WORD) Z Stack + 299 00B1 SCREENF EQU ZSP+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT + 300 00B2 TABLEF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT + 301 00B3 VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH + 302 00B6 DBUFF EQU VOCEND+3 ; (WORD) RAM PG TO ACCESS (LSB = 0) + 303 00B8 DSKBNK EQU DBUFF+2 ; (BYTE) MAIN/AUX bank + 304 00B9 ALLFLG EQU DSKBNK+1 ; (BYTE) IF =1 ALL FCN KEYS (>127) ARE TCHARS + 305 00BA UNDFLG EQU ALLFLG+1 ; (BYTE) Underlining flag + 306 00BB INVFLG EQU UNDFLG+1 ; (BYTE) Inverse flag + 307 00BC MEMPAGE EQU INVFLG+1 ; (BYTE) Save spot for XPAGING stuff + 308 00BD CPY_COUNT EQU MEMPAGE+1 ; (BYTE) Number of bytes for copy line + 309 00BE TBLHEIGHT EQU CPY_COUNT+1 ;(BYTE) Number of lines in printing table + 310 00BF TBLWIDTH EQU TBLHEIGHT+1 ;(BYTE) Number of bytes per line + 311 00C0 TBLCNT EQU TBLWIDTH+1 ;(BYTE) Counter for table printing + 312 00C1 FONTFLG EQU TBLCNT+1 ;(BYTE) Which font (!=0 is width) + 313 00C2 TBLPUR EQU FONTFLG+1 ;(BYTE) first pure table page + 314 00C3 FUNPRE EQU TBLPUR+1 ;(BYTE) first preloaded function page + 315 00C4 FUNPUR EQU FUNPRE+1 ;(BYTE) first pure function page + 316 00C5 FUNPGE EQU FUNPUR+1 ;(BYTE) -number to get function preload page + 317 00C6 DELAY_COUNTER EQU FUNPGE+1 ;(BYTE) counter for delay loop + 318 ; + 319 ; some char-to-screen variables + 320 ; + Wed May 24 1989 15:00 Page 6 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ZERO PAGE VARIABLES ---" + + 321 00C7 CHAR_D1 EQU DELAY_COUNTER+1 ; (BYTE) character data, part 1 + 322 00C8 CHAR_D2 EQU CHAR_D1+1 ; (BYTE) char data, part 2 + 323 00C9 CW EQU CHAR_D2+1 ; (BYTE) width of the character + 324 00CA CLKCTR EQU CW+1 ; (BYTE) counter for mouse clicking + 325 00CB MSX EQU CLKCTR+1 ; (BYTE) mouse cursor X + 326 00CC MSY EQU MSX+1 ; (BYTE) mouse cursor Y + 327 00CD CURRENT EQU MSY+1 ; (BYTE) current paging bufer + 328 ;CURSOR_OFF EQU CURRENT+1 ; (BYTE) ==1 if "don't show the blinking cursor" + 329 00CE MSTBL EQU CURRENT+1 ; (ADDRESS) pointer to extension table + 330 00D1 LASTZP EQU MSTBL+3 ; just checking + 331 ; + 332 ; these routines are in non-swapped memory + 333 ; + 334 00D1 ZERO_FB EQU LASTZP ; put fetch byte routine in at end of ZP + 335 00DC ZERO_ZF EQU ZERO_FB+11 ; and ZPCPNT fetch after that + 336 00E5 ZERO_MF EQU ZERO_ZF+9 ; and MPCPNT fetch after that + 337 00EE SAVE_DATA EQU ZERO_MF+9 ; copy data from DBUFF to IOBUFF routine + 338 ; + 339 ; and just to check the end + 340 ; + 341 00FF ZEE_END EQU SAVE_DATA+17 ; should be == 100 + 342 + 343 0000 END + 344 + 345 0000 INCLUDE PRODOS.EQU + 346 0000 STTL "--- ProDOS EQUATES ---" + 347 PAGE + Wed May 24 1989 15:00 Page 7 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- ProDOS EQUATES ---" + + 348 + 349 ; + 350 ; some parameter structures + 351 ; + 352 0000 OPEN_PARM EQU 0 + 353 0000 OP_PCOUNT EQU OPEN_PARM ; must be 3 for open + 354 0001 OP_PATHNAME EQU OP_PCOUNT+1 ; address of pathname + 355 0003 OP_FILEBUFF EQU OP_PATHNAME+2 ; address of file data buffer + 356 0005 OP_REFNUM EQU OP_FILEBUFF+2 ; file reference number + 357 0006 OPEN_PSIZE EQU OP_REFNUM+1 ; size of parameter buffer + 358 + 359 0000 READ_PARM EQU 0 ; to read things + 360 0000 RD_PCOUNT EQU READ_PARM ; param count (=4) + 361 0001 RD_REFNUM EQU RD_PCOUNT+1 ; ref num of file + 362 0002 RD_BUFFER EQU RD_REFNUM+1 ; where to + 363 0004 RD_BUFFLEN EQU RD_BUFFER+2 ; length of buffer + 364 0006 RD_LENGTH EQU RD_BUFFLEN+2 ; actual length of read + 365 0008 READ_PSIZE EQU RD_LENGTH+2 ; length of parm block + 366 + 367 0000 CLOSE_PARM EQU 0 ; for closing file + 368 0000 CL_PCOUNT EQU CLOSE_PARM ; paramter count (=1) + 369 0001 CL_REFNUM EQU CL_PCOUNT+1 ; refnum of file to be closed + 370 0002 CLOSE_PSIZE EQU CL_REFNUM+1 ; this is the size, thank you + 371 + 372 0000 WRITE_PARM EQU 0 ; to write things + 373 0000 WR_PCOUNT EQU WRITE_PARM ; parm count (= 4) + 374 0001 WR_REFNUM EQU WR_PCOUNT+1 ; file refnum + 375 0002 WR_BUFFER EQU WR_REFNUM+1 ; data buffer address + 376 0004 WR_BUFFLEN EQU WR_BUFFER+2 ; data buffer length + 377 0006 WR_LENGTH EQU WR_BUFFLEN+2 ; actual length written + 378 0008 WRITE_PSIZE EQU WR_LENGTH+2 ; length of parm block + 379 + 380 0000 SETMARK_PARM EQU 0 + 381 0000 SM_PCOUNT EQU SETMARK_PARM ; parm count (=2) + 382 0001 SM_REFNUM EQU SM_PCOUNT+1 ; file refnum + 383 0002 SM_FPOS EQU SM_REFNUM+1 ; 3 byte file pos + 384 0005 SETMARK_PSIZE EQU SM_FPOS+3 ; length of parm block + 385 + 386 0000 SETPREFIX_PARM EQU 0 + 387 0000 SP_PCOUNT EQU SETPREFIX_PARM ; parm count (=1) + 388 0001 SP_PATHNAME EQU SP_PCOUNT+1 ; pointer to path name + 389 0003 SETPREFIX_PSIZE EQU SP_PATHNAME+2 ; length of block + 390 + 391 0000 SETEOF_PARM EQU 0 + 392 0000 SE_PCOUNT EQU SETEOF_PARM ; parm count (=2) + 393 0001 SE_REFNUM EQU SE_PCOUNT+1 ; reference number + 394 0002 SE_NEWEOF EQU SE_REFNUM+1 ; new EOF position + 395 0005 SETEOF_PSIZE EQU SE_NEWEOF+3 ; length of parm block + 396 + 397 0000 END + 398 + 399 0000 INCLUDE APPLE.EQU + 400 0000 STTL "--- APPLE ][ HARDWARE STUFF ---" + 401 PAGE + Wed May 24 1989 15:00 Page 8 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 402 ; ------------------- + 403 ; APPLE II MEMORY MAP + 404 ; ------------------- + 405 0001 AUX EQU 1 ; offset to Auxillary mem switches + 406 0000 MAIN EQU 0 ; for main memory switches + 407 + 408 ; + 409 ; some hardware spots + 410 ; + 411 2000 SCREEN EQU $2000 ; START OF Double HiRes SCREEN RAM + 412 + 413 BF00 PRGLBL EQU $BF00 ; ProDOS Globals page in main mem + 414 BF58 PR_BITMAP EQU $BF58 ; ProDOS system bitmap + 415 BFFF KVERSION EQU $BFFF ; ProDOS version (== $FF if InfoDOS) + 416 00FF INFODOS_ID EQU $FF + 417 + 418 C000 IOADDR EQU $C000 ; start of I/O registers + 419 D000 PROADR EQU $D000 ; start of ProDOS + 420 + 421 0200 LBUFF EQU $0200 ; LINE INPUT BUFFER + 422 0273 PIC1BUF EQU $0300-141 ; we can use line buffer for one picture buffer + 423 0280 SCRBUFF EQU LBUFF+$80 ; screen line buffer + 424 2000 BORG EQU $2000 ; ORIGIN OF .SYSTEM CODE + 425 ; + 426 ; some page 3 storage relocated stuff + 427 ; + 428 0300 PAGE3STUFF EQU $300 + 429 0300 MOUSER EQU PAGE3STUFF ; this is where mouse subroutine goes + 430 0312 COLORS EQU MOUSER+$12 + 431 0352 XPOSTBL EQU COLORS+$40 + 432 + 433 0400 SV_PCL EQU $400 ; for scrolling data + 434 0600 SV_PCH EQU $600 + 435 + 436 0800 IOBUFF EQU $0800 ; 1Kb DATA BUFFER BUFFER + 437 + 438 0C00 PAGING_MEM EQU IOBUFF+$400 ; Paging table stuff + 439 0C00 NEXTPNT EQU PAGING_MEM + 440 0C40 PREVPNT EQU NEXTPNT+$40 + 441 0C80 VPAGEH EQU PREVPNT+$40 + 442 0CC0 VPAGEL EQU VPAGEH+$40 + 443 0200 PAGELEN EQU $200 ; length of paged read + 444 + 445 0D00 ZSTKBL EQU PAGING_MEM+$100 ; Z-STACK BOTTOM,LO (1K STACK FOR EZIP) + 446 0E00 ZSTKTL EQU ZSTKBL+$100 ; TOP, LO + 447 0F00 ZSTKBH EQU ZSTKBL+$200 ; BOTTOM, HI + 448 1000 ZSTKTH EQU ZSTKBL+$300 ; TOP, HI + 449 ; + 450 ; now define some file i/o buffers and such + 451 ; + 452 1100 GAME1FIO EQU ZSTKBL+$400 ; Game file I/O buffer + 453 1500 GAME2FIO EQU GAME1FIO+$400 ; Second game file i/o buffer + 454 1900 SEGTBL EQU GAME2FIO+$400 ; segment table for multi disks + 455 1C74 PIC2BUF EQU SEGTBL+($400-140) ; picture buffer is 140 bytes long + 456 1D00 TCHARTBL EQU SEGTBL+$400 ; 208 bytes for (possible) terminating + 457 1D50 COPY_LINE EQU TCHARTBL+$50 ; copy line in screen memory + 458 1D7C CPY_MOD1_SRC equ COPY_LINE+$2C ; special self-modifying places + 459 1D7F CPY_MOD1_DST equ CPY_MOD1_SRC+3 + 460 1DA0 CPY_MOD2_SRC equ COPY_LINE+$50 + 461 1DA3 CPY_MOD2_DST equ CPY_MOD2_SRC+3 + 462 + 463 1DD0 DSKSEG EQU TCHARTBL+$D0 ; spot to stash pointers for disk segments + 464 1DD0 D1SEG EQU DSKSEG ; where in SEGTBL for Disk 1 + 465 1DD2 D2SEG EQU D1SEG+2 + 466 1DD4 D3SEG EQU D2SEG+2 + 467 1DD6 D4SEG EQU D3SEG+2 + 468 1DD8 D5SEG EQU D4SEG+2 + 469 1DDA D6SEG EQU D5SEG+2 + 470 1DDC D7SEG EQU D6SEG+2 + 471 1DDE D8SEG EQU D7SEG+2 + 472 1DE0 LOCAL_SV EQU TCHARTBL+$E0 ; to save locals before restore + 473 1E00 LOCALS EQU TCHARTBL+$100 ; LOCAL VARIABLE STORAGE (30 BYTES) + 474 1E20 BUFSAV EQU LOCALS+$20 ; TEMP SPACE FOR SAVE/RESTORE (80 BYTES) + 475 1F00 SCR_LINE EQU LOCALS+$100 ; place to build displayed line + 476 1F8C CHARSET EQU SCR_LINE+140 ; spot for charset to go + Wed May 24 1989 15:00 Page 9 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 477 ; + 478 ; now for some interpreter data + 479 ; + 480 4000 INTR_BEGIN EQU $4000 ; START OF Interpreter CODE in main + 481 5600 INTR_SIZE EQU (43*512) ; size of interpreter + 482 + 483 9600 ZBEGIN EQU (INTR_BEGIN+INTR_SIZE) ; start of Z code + 484 7F00 MMSIZE EQU PRGLBL-INTR_BEGIN ; free memory in main bank + 485 0029 Z1SIZE EQU >(PRGLBL-ZBEGIN) ; size of preload, part 1 + 486 ; + 487 ; this is in Bank 2, Main mem + 488 ; + 489 ; + 490 ; Picture directory goes in Bank 2, Aux mem + 491 ; + 492 D000 PIC_DIR EQU $D000 ; picture local directory + 493 DC00 GBL_DIR EQU $DC00 ; global directory + 494 ; + 495 ; some special markers if we are using InfoDOS + 496 ; + 497 0000 SP_BANK EQU MAIN + 498 D000 SP_START EQU $D000 ; start of special area + 499 0017 SP_SIZE EQU ((($FE->SP_START)*256)/512) ; how many pages + 500 ;SP_SIZE EQU (((>SCREEN->SP_START)*256)/512) ; how many pages + 501 + 502 0001 PB_BANK EQU AUX ; paging buffers in which bank + 503 0800 PBEGIN EQU $0800 ; start of paging buffers + 504 0018 NUMBUFS EQU >(SCREEN-PBEGIN) ; how many 256k paging buffers + 505 ;NUMBUFS EQU >($100-PBEGIN) ; how many 256k paging buffers + 506 + 507 0029 P2PAGE EQU >(PRGLBL-ZBEGIN) ; first page of zcode in aux bank + 508 4000 Z2BEGIN EQU $4000 ; start of part 2 in aux mem + 509 ; just after the dhires screen + 510 0040 Z2PAGE EQU >Z2BEGIN ; get me just the page address + 511 007F Z2SIZE EQU >(PRGLBL-Z2BEGIN) ; size of preload, part 2 + 512 00A8 P3PAGE EQU Z1SIZE+Z2SIZE ; first page in aux mem part 3 + 513 D000 Z3BEGIN EQU $D000 ; start of 3 part in aux mem + 514 00D0 Z3PAGE EQU >Z3BEGIN ; get me page number too + 515 002E Z3SIZE EQU <($FE-Z3PAGE) ; size of part 3, in pages + 516 + 517 ; + 518 ; other numba's + 519 ; + 520 00D6 PGBEGIN EQU (P3PAGE+Z3SIZE) ; first paged page + 521 00D6 PRESIZE EQU (Z1SIZE+Z2SIZE+Z3SIZE) ; size of preload, # pages + 522 2000 SCRSZE EQU INTR_BEGIN-SCREEN ; size of Double HiRes screen (8k, each bank) + 523 EE00 RAMDSK EQU (119*512) ; size of RAM disk in aux mem + 524 B500 RAMSAVE EQU $B500 ; save this much to cover HiRes screen in + 525 ; aux and the rest of the preload, up to + 526 ; PRGLBL ($bf00) + 527 3900 FREERAM EQU RAMDSK-RAMSAVE ; size of Free RAM after 'saving' + 528 ; special AUX memory + 529 2200 DSKSZE EQU (512*273) ; size of ProDOS data disk file + 530 + 531 ; --------- + 532 ; CONSTANTS + 533 ; --------- + 534 + 535 0002 IIeID EQU 2 ; Apple ][e Yzip + 536 0009 IIcID EQU 9 ; ][c Yzip + 537 000A IIgsID EQU 10 ; ][gs Yzip + 538 + 539 00FF P3BANK EQU $FF ; show upper aux mem + 540 0000 LO EQU 0 + 541 0001 HI EQU 1 + 542 0002 ABANK EQU 2 ; for address variables + 543 + 544 0000 OFF EQU 0 ; for toggling soft-switches + 545 0001 ON EQU 1 + 546 + 547 0003 RETRY_COUNT EQU 3 ; how many retries before message + 548 + 549 0009 TAB EQU $09 ; Tab char + 550 000B EOS EQU $0B ; End of Sentence + 551 000D EOL EQU $0D ; EOL CHAR + Wed May 24 1989 15:00 Page 10 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 552 000A LF EQU $0A ; LINE FEED + 553 0020 SPACE EQU $20 ; SPACE CHAR + 554 0008 BACKSPACE EQU $08 ; BACKSPACE CHAR + 555 001B ESCAPE EQU $1B ; ESCAPE Key + 556 003F VOLCHAR EQU '?' ; Key to hit for ONLINE command + 557 ; + 558 ; Screen Defs + 559 ; + 560 008C MAXWIDTH EQU 140 ; 560 / 4 = max "pixels" + 561 0230 REAL_MAXW EQU MAXWIDTH*4 + 562 00C0 MAXHEIGHT EQU 192 ; 192 screen lines + 563 0002 FONT_W EQU 2 ; font width (for game, anyway) + 564 0009 FONT_H EQU 9 ; font height + 565 0003 MFONT_W EQU 3 ; mono spaced font width, to game + 566 000C MONOFONT_W EQU MFONT_W*4 ; how wide the mono font really is + 567 + 568 0008 SPACE_WIDTH EQU 8 ; default space width + 569 0003 BLINK_RATE EQU 3 ; tenths of seconds between blinks + 570 + 571 001C OUTER_DELAY EQU $1C ; outside delay loop counter + 572 0003 INNER_DELAY EQU 3 ; inner delay loop + 573 + 574 0072 GS_OUTER_DELAY EQU $72 ; ][gs outside counter + 575 0002 GS_INNER_DELAY EQU 2 ; ][gs inside counter + 576 + 577 ; ---------------------- + 578 ; BOOT ZERO PAGE EQUATES + 579 ; ---------------------- + 580 + 581 0026 BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS + 582 002B BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT + 583 + 584 0280 START_NAME EQU $280 ; name upon boot is stored here + 585 ; ---------------- + 586 ; HARDWARE EQUATES + 587 ; ---------------- + 588 + 589 C000 KBD EQU $C000 ; KEY STROBE + 590 C000 STORE80 EQU $C000 ; video aux mem switch + 591 C002 RDBNK EQU $C002 ; READ MAIN MEMORY (+MAIN, +AUX) + 592 C004 WRTBNK EQU $C004 ; WRITE MAIN 48K OF MEMORY (+MAIN, +AUX) + 593 C008 ALTZP EQU $C008 ; R/W MAIN (C009 = AUX) >MEM + 594 C00C COL80SW EQU $C00C ; 80 Column switch + 595 C010 ANYKEY EQU $C010 ; ANY KEY DOWN FLAG + 596 C019 VERTBLNK EQU $C019 ; Vertical Blanking Flag + 597 C029 IIGSVID EQU $C029 ; GS MEGA ][ video register + 598 C030 SPKR EQU $C030 ; SPEAKER FLAG (MAKE A NOISE) + 599 C035 IIGSSHD EQU $C035 ; ][GS shadowing reg + 600 C050 TEXTSW EQU $C050 ; Graphics Switch + 601 C052 MIXEDSW EQU $C052 ; Mixed Text/Graphics + 602 C054 PAGE2SW EQU $C054 ; Page select + 603 C056 HIRESSW EQU $C056 ; Select HiRes + 604 C05E DHIRESW EQU $C05E ; Double HiRes switch (backwards: +0 on +1 off) + 605 C07E IOUDIS EQU $C07E ; Double HiRes Switch enabler (same backass way) + 606 C083 BNK2SET EQU $C083 ;READ/READ READ RAM WRITE RAM BANK 2 + 607 C08B BNK1SET EQU $C08B ;READ/READ READ RAM WRITE RAM BANK 1 + 608 C082 RDROM EQU $C082 ; READ READ ROM NO WRITE + 609 C088 RDBNK1 EQU $C088 ; READ ram, bank 1 + 610 C080 RDBNK2 EQU $C080 ; Read ram, bank 2 + 611 + 612 ; ----------------- + 613 ; MONITOR VARIABLES + 614 ; ----------------- + 615 + 616 0036 CSW EQU $36 ; CHARACTER OUTPUT VECTOR (for scripting) + 617 C061 APKEY1 EQU $C061 ; open apple key flag + 618 C062 APKEY2 EQU $C062 ; closed apple key flag + 619 + 620 0002 CURSW EQU 2 ; width of cursor + 621 0004 CURSH EQU 4 ; height of cursor + 622 ; ----------- + 623 ; MOUSE STUFF + 624 ; ----------- + 625 C412 MTABLE EQU $C412 ; Mouse ROM table + 626 0310 MSVECTOR EQU MOUSER+16 ; where vector is stored + Wed May 24 1989 15:00 Page 11 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- APPLE ][ HARDWARE STUFF ---" + + 627 0312 MSMOVEF EQU MSVECTOR+2 ; Mouse moved flag + 628 0313 MSBTNF EQU MSMOVEF+1 ; Mouse button flag + 629 ; + 630 ; MOUSE screen holes + 631 ; + 632 0478 CLMPMINL EQU $478 ; lo part of clamping min + 633 0578 CLMPMINH EQU $578 ; hi part of " " + 634 04F8 CLMPMAXL EQU $4F8 ; lo part of clamping max + 635 05F8 CLMPMAXH EQU $5F8 ; hi part of " " + 636 0478 MOUSEXL EQU $478 ; lo part of mouse X + 637 0578 MOUSEXH EQU $578 ; hi part of mouse X + 638 04F8 MOUSEYL EQU $4F8 ; lo part of mouse Y + 639 05F8 MOUSEYH EQU $5F8 ; hi part of mouse Y + 640 0778 MOUSEST EQU $778 ; status byte + 641 ; + 642 ; some mouse constants + 643 ; + 644 0081 SGL_CLK EQU $81 ; single click char + 645 0082 DBL_CLK EQU $82 ; double click char + 646 0006 CLK_CNT EQU 6 ; counts between single and double click + 647 ; Subroutine offsets + 648 0000 SETM EQU 0 + 649 0001 SERVEM EQU 1 + 650 0002 READM EQU 2 + 651 0003 CLEARM EQU 3 + 652 0004 POSM EQU 4 + 653 0005 CLAMPM EQU 5 + 654 0006 HOMEM EQU 6 + 655 0007 INITM EQU 7 + 656 + 657 ; -------------- + 658 ; PRODOS GLOBALS + 659 ; -------------- + 660 BF90 PRODATE EQU $BF90 ; date and + 661 BF92 PROTIME EQU $BF92 ; time + 662 BF98 MACHID EQU $BF98 ; machine id + 663 + 664 ; ---------------- + 665 ; MONITOR ROUTINES + 666 ; ---------------- + 667 FB1E MPREAD EQU $FB1E ; Read for joystick control + 668 FC22 MBASCAL EQU $FC22 ; CALC LINE BASE ADDRESS + 669 FF3A MBELL EQU $FF3A ; MAKE A NOISE + 670 FFFC RESET_VECTOR EQU $FFFC ; force warm reboot + 671 FC9C MCLEOL EQU $FC9C ; CLEAR TO END OF LINE + 672 FC42 MCLEOS EQU $FC42 ; CLEAR TO END OF SCREEN + 673 FC58 MHOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR + 674 FDED MCOUT EQU $FDED ; CHAR OUTPUT + 675 FDF0 MCOUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN + 676 FD0C MRDKEY EQU $FD0C ; READ KEY + 677 FD6F MGETLN1 EQU $FD6F ; GET LINE + 678 FCA8 MWAIT EQU $FCA8 ; WASTE SO MUCH TIME + 679 ; + 680 ; Some /RAM spots + 681 ; + 682 BF26 RAMVEC EQU $BF26 ; /RAM drive vector + 683 077E OLDVEC EQU $77E ; spot to save the drive vector + 684 BF16 UNSVEC EQU $BF16 ; "Uninstalled Device" vector + 685 BF31 DEVCNT EQU $BF31 ; Device count + 686 BF32 DEVNUM EQU $BF32 ; Device list + 687 + 688 ; + 689 ; machine info spots + 690 ; + 691 FBB3 MACHID1 EQU $FBB3 ; first part + 692 FBC0 MACHID2 EQU $FBC0 ; second part + 693 FE1F MACHCHK EQU $FE1F ; differentiate between ][e and gs + 694 ; do sec, then jsr, and if still set, = ][e + 695 0000 END + 696 + 697 0000 INCLUDE MACROS.ASM + 698 0000 STTL "--- MACROS ---" + 699 PAGE + Wed May 24 1989 15:00 Page 12 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- MACROS ---" + + 700 + 701 ; + 702 ; MACROS for Apple ][ Yzip + 703 ; + 704 DLINE: .MACRO STRING,SLEN + 705 ldx #STRING ; get other part of string + 707 IFMA 2 ; check to see if length passed in + 708 ldy SLEN ; then just fetch it + 709 ELSE + 710 ldy #STRING|L ; get length of string + 711 ENDIF + 712 jsr DLINE ; print the string + 713 .MACEND + 714 ; + 715 ; ProDOS macros + 716 ; + 717 PRODOS: .MACRO CODE, PADDR + 718 jsr $BF00 ; ProDOS handler + 719 DB CODE ; ProDOS function code + 720 DW PADDR ; Function Parameter Block address + 721 .MACEND + 722 + 723 QUIT: .MACRO PBLOCK + 724 PRODOS $65, PBLOCK + 725 .MACEND + 726 + 727 READ_BLOCK: .MACRO PBLOCK + 728 PRODOS $80, PBLOCK + 729 .MACEND + 730 + 731 WRITE_BLOCK: .MACRO PBLOCK + 732 PRODOS $81, PBLOCK + 733 .MACEND + 734 + 735 GET_TIME: .MACRO PBLOCK + 736 PRODOS $82, PBLOCK + 737 .MACEND + 738 + 739 CREATE: .MACRO PBLOCK + 740 PRODOS $C0, PBLOCK + 741 .MACEND + 742 + 743 DESTROY: .MACRO PBLOCK + 744 PRODOS $C1, PBLOCK + 745 .MACEND + 746 + 747 RENAME: .MACRO PBLOCK + 748 PRODOS $C2, PBLOCK + 749 .MACEND + 750 + 751 SET_FILE_INFO: .MACRO PBLOCK + 752 PRODOS $C3, PBLOCK + 753 .MACEND + 754 + 755 GET_FILE_INFO: .MACRO PBLOCK + 756 PRODOS $C4, PBLOCK + 757 .MACEND + 758 + 759 ONLINE: .MACRO PBLOCK + 760 PRODOS $C5, PBLOCK + 761 .MACEND + 762 + 763 SET_PREFIX: .MACRO PBLOCK + 764 PRODOS $C6, PBLOCK + 765 .MACEND + 766 + 767 GET_PREFIX: .MACRO PBLOCK + 768 PRODOS $C7, PBLOCK + 769 .MACEND + 770 + 771 OPEN: .MACRO PBLOCK + 772 PRODOS $C8, PBLOCK + 773 .MACEND + 774 + Wed May 24 1989 15:00 Page 13 + + "APPLE YZIP (c)Infocom, Inc. --- EQUATES AND SUCH" + "--- MACROS ---" + + 775 NEWLINE: .MACRO PBLOCK + 776 PRODOS $C9, PBLOCK + 777 .MACEND + 778 + 779 READ: .MACRO PBLOCK + 780 PRODOS $CA, PBLOCK + 781 .MACEND + 782 + 783 WRITE: .MACRO PBLOCK + 784 PRODOS $CB, PBLOCK + 785 .MACEND + 786 + 787 CLOSE: .MACRO PBLOCK + 788 PRODOS $CC, PBLOCK + 789 .MACEND + 790 + 791 FLUSH: .MACRO PBLOCK + 792 PRODOS $CD, PBLOCK + 793 .MACEND + 794 + 795 SET_MARK: .MACRO PBLOCK + 796 PRODOS $CE, PBLOCK + 797 .MACEND + 798 + 799 GET_MARK: .MACRO PBLOCK + 800 PRODOS $CF, PBLOCK + 801 .MACEND + 802 + 803 SET_EOF: .MACRO PBLOCK + 804 PRODOS $D0, PBLOCK + 805 .MACEND + 806 + 807 SET_BUF: .MACRO PBLOCK + 808 PRODOS $D1, PBLOCK + 809 .MACEND + 810 + 811 GET_BUF: .MACRO PBLOCK + 812 PRODOS $D2, PBLOCK + 813 .MACEND + 814 + 815 0000 END + 816 + 817 + 818 0000 TITLE "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + 819 0000 INCLUDE ZBEGIN.ASM + 820 0000 STTL "--- START OF APPLE ][ INTERPRETER ---" + 821 PAGE + Wed May 24 1989 15:00 Page 14 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- START OF APPLE ][ INTERPRETER ---" + + 822 + 823 4000 ORG INTR_BEGIN + 824 ; + 825 ; Set up for Double HiRes full screen graphics + 826 ; + 827 4000 AD 54 C0 lda PAGE2SW+OFF ; turn off page 2 + 828 4003 8D 50 C0 sta TEXTSW+OFF ; turn off text - turn on graphics + 829 4006 8D 57 C0 sta HIRESSW+ON ; turn on high resolution + 830 4009 8D 52 C0 sta MIXEDSW+OFF ; full screen graphics + 831 400C 8D 0D C0 sta COL80SW+ON ; turn on 80 column + 832 400F 8D 7E C0 sta IOUDIS+OFF ; turn ON (it too is backwards) Dhires switch + 833 4012 8D 5E C0 sta DHIRESW+OFF ; turn ON (it's backwards!) Dhires + 834 + 835 4015 8D 01 C0 sta STORE80+ON ; turn on aux page display ability + 836 4018 AD 83 C0 lda BNK2SET ; read/write RAM, bank 2 + 837 401B AD 83 C0 lda BNK2SET + 838 ; + 839 ; copy in progame from boot code + 840 ; + 841 401E A2 00 ldx #0 ; start at first letter + 842 4020 MVPRE: + 843 4020 BD 03 20 lda BORG+3,X ; get letter + 844 4023 F0 0C beq MVPREX ; all done + 845 4025 9D 78 46 sta GAME1NAME,X ; save letter + 846 4028 9D 8A 46 sta GAME2NAME,X ; save letter + 847 402B 9D 68 46 sta GAME,X ; save for asking about later + 848 402E E8 inx ; next letter + 849 402F D0 EF bne MVPRE ; do gen + 850 4031 MVPREX: + 851 4031 8E 67 46 stx GAMEL ; save length of game name + 852 4034 A9 2E lda #'.' ; get extension for names + 853 4036 9D 78 46 sta GAME1NAME,X ; save letter + 854 4039 9D 8A 46 sta GAME2NAME,X ; save letter + 855 403C E8 inx ; next letter + 856 403D A9 44 lda #'D' ; for data segments + 857 403F 9D 78 46 sta GAME1NAME,X ; save letter + 858 4042 9D 8A 46 sta GAME2NAME,X ; save letter + 859 4045 E8 inx ; points to number + 860 4046 E8 inx ; inclusive count for length + 861 4047 8E 77 46 stx GAME1NML ; save length of name + 862 404A 8E 89 46 stx GAME2NML ; save length of name + 863 + 864 404D A9 09 lda #VERSID ; put in version number + 865 404F 8D 1F 96 sta ZBEGIN+ZINTWD+1 + 866 + 867 4052 E6 AF inc ZSP+LO ; INIT Z-STACK POINTERS + 868 4054 EE 75 6C inc OLDZSP+LO ; TO "1" + 869 4057 E6 B1 inc SCREENF ; TURN DISPLAY ON + 870 4059 E6 AA inc SCRIPT ; enable scripting + 871 405B EE A3 6C inc CRLF_CHECK ; do CR functino check + 872 + 873 405E AD 47 6E lda WINTABLE+LO ; set WINDOW to point to window 0 + 874 4061 85 05 sta WINDOW+LO + 875 4063 AD 48 6E lda WINTABLE+HI + 876 4066 85 06 sta WINDOW+HI ; okay, it does + 877 + 878 4068 A5 63 lda ARG1+LO ; using mouse? + 879 406A F0 12 beq ZBEGIN1 ; nope + 880 406C 09 78 ora #$78 ; point to correct screen holes + 881 406E 8D 50 50 sta MSFIX0+1 + 882 4071 8D 5B 50 sta MSFIX1+1 ; and modify code to point to correct spot + 883 4074 8D 60 50 sta MSFIX2+1 + 884 4077 A5 63 lda ARG1+LO + 885 4079 09 F8 ora #$F8 ; and one more + 886 407B 8D 60 50 sta MSFIX2+1 + 887 407E ZBEGIN1: + 888 407E A9 FF lda #$FF ; do a clear -1 to start off + 889 4080 85 63 sta ARG1+LO ; so arg 1 is this + 890 4082 20 A8 57 jsr ZCLR ; doing it + 891 + 892 4085 GET_PREFIX GPRE_PB ; get where we are to start + 893 4085 PRODOS $C7, GPRE_PB + 894 4085 20 00 BF jsr $BF00 ; ProDOS handler + 895 4088 C7 DB $C7 ; ProDOS function code + 896 4089 6446 DW GPRE_PB ; Function Parameter Block address + Wed May 24 1989 15:00 Page 15 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- START OF APPLE ][ INTERPRETER ---" + + 897 408B .MACEND + 898 408B .MACEND + 899 + 900 408B AD D3 1D lda D2SEG+HI ; start DSEGS at .D2 + 901 408E 85 1F sta DSEGS+HI + 902 4090 AD D2 1D lda D2SEG+LO + 903 4093 85 1E sta DSEGS+LO + 904 + 905 4095 A9 01 lda #1 ; open game file .D2 please + 906 4097 20 C6 49 jsr FETCH_FILE ; we did that + 907 409A A5 59 lda INFODOS ; are we on little dos? + 908 409C F0 03 beq ZBEGIN2 ; nope + 909 409E 20 F1 4B jsr GET_SPECIAL ; do special preloading if so + 910 40A1 ZBEGIN2: + 911 40A1 AD D5 1D lda D3SEG+HI ; this is cuz we be openin' .D3 + 912 40A4 85 1F sta DSEGS+HI + 913 40A6 AD D4 1D lda D3SEG+LO + 914 40A9 85 1E sta DSEGS+LO + 915 40AB A9 02 lda #2 ; and just for giggles, do the + 916 40AD 20 C6 49 jsr FETCH_FILE ; same for game file .D3 + 917 + 918 40B0 20 AA 90 jsr VLDZPC ; MAKE ZPC VALID + 919 40B3 20 1F 92 jsr NEXTPC ; skip over # of locals + 920 + 921 ; ... AND FALL INTO MAIN LOOP + 922 + 923 40B6 END + 924 + 925 40B6 INCLUDE MAIN.ASM + 926 40B6 STTL "--- MAIN LOOP ---" + 927 PAGE + Wed May 24 1989 15:00 Page 16 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 928 + 929 9600 MD_ADDR EQU ZBEGIN + 930 0001 MDEBUG EQU 1 + 931 + 932 40B6 MLOOP: + 933 [01] IF MDEBUG + 934 40B6 AD 00 96 lda MD_ADDR ; get interesting address + 935 40B9 D0 01 bne MLOOPx ; just fine, thank you + 936 40BB 00 brk ; then die + 937 40BC MLOOPx: + 938 [00] ENDIF + 939 + 940 40BC A9 00 lda #0 + 941 40BE 85 62 sta NARGS ; reset number of args + 942 40C0 AD 54 C0 lda PAGE2SW+OFF ; just do this for the heck of it + 943 40C3 AD 83 C0 lda BNK2SET + 944 40C6 AD 83 C0 lda BNK2SET + 945 40C9 8D 01 C0 sta STORE80+ON ; must always be on + 946 + 947 40CC 20 1F 92 jsr NEXTPC ; get op code + 948 40CF 85 61 sta OPCODE ; SAVE IT HERE + 949 + 950 [01] IF MDEBUG + 951 ; + 952 ; special debugging code + 953 ; + 954 40D1 AC 01 41 ldy SPCSV + 955 40D4 A5 61 lda OPCODE + 956 40D6 99 10 41 sta SAVEOP,Y + 957 40D9 A5 82 lda ZPCH + 958 40DB 99 20 41 sta SAVEZH,Y + 959 40DE A5 81 lda ZPCM + 960 40E0 99 30 41 sta SAVEZM,Y + 961 40E3 A5 80 lda ZPCL + 962 40E5 99 40 41 sta SAVEZL,Y + 963 40E8 A5 85 lda ZPCBNK + 964 40EA 99 50 41 sta SAVEZB,Y + 965 40ED A5 84 lda ZPCPNT+HI + 966 40EF 99 60 41 sta SAVEZP,Y + 967 40F2 AC 01 41 ldy SPCSV + 968 40F5 C8 iny + 969 40F6 98 tya + 970 40F7 29 0F and #$0F + 971 40F9 8D 01 41 sta SPCSV + 972 40FC A5 61 lda OPCODE + 973 40FE 4C 70 41 jmp MAINDB + 974 4101 00 SPCSV: db 0 + 975 4111 ORG $+15 + 976 0411 ORG $.SHR.4 + 977 4110 ORG $.SHL.4 + 978 4110 SAVEOP: ds 16 + 979 4120 SAVEZH: ds 16 + 980 4130 SAVEZM: ds 16 + 981 4140 SAVEZL: ds 16 + 982 4150 SAVEZB: ds 16 + 983 4160 SAVEZP: ds 16 + 984 4170 MAINDB: + 985 [00] ENDIF + 986 ; + 987 ; DECODE AN OPCODE + 988 ; + 989 4170 A8 tay ; set flags + 990 4171 30 03 bmi DC0 ; IF POSITIVE, + 991 4173 4C CD 42 jmp OP2 ; IT'S A 2-OP + 992 4176 C9 B0 DC0: cmp #$B0 + 993 4178 B0 03 bcs DC1 + 994 417A 4C 90 42 jmp OP1 ; OR MAYBE A 1-OP + 995 417D C9 C0 DC1: cmp #$C0 + 996 417F B0 03 bcs OPEXT + 997 4181 4C 6A 42 jmp OP0 ; PERHAPS A 0-OP + 998 + 999 ; -------------- + 1000 ; HANDLE AN X-OP + 1001 ; -------------- + 1002 + Wed May 24 1989 15:00 Page 17 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1003 4184 C9 EC OPEXT: CMP #236 ; XCALL? + 1004 4186 D0 03 BNE OPX5 + 1005 4188 4C 15 42 JMP OPXCLL ; YES, PROCESS SEPARATELY + 1006 418B C9 FA OPX5: CMP #250 ; IXCALL + 1007 418D D0 03 BNE OPX6 + 1008 418F 4C 15 42 JMP OPXCLL + 1009 4192 20 1F 92 OPX6: JSR NEXTPC ; GRAB THE ARGUMENT ID BYTE + 1010 4195 85 73 STA ABYTE ; HOLD IT HERE + 1011 4197 A2 00 LDX #0 + 1012 4199 86 75 STX ADEX ; INIT ARGUMENT INDEX + 1013 419B F0 06 BEQ OPX1 ; JUMP TO TOP OF LOOP + 1014 419D A5 73 OPX0: LDA ABYTE ; GET ARG BYTE + 1015 419F 0A ASL A ; SHIFT NEXT 2 ARG BITS + 1016 41A0 0A ASL A ; INTO BITS 7 & 6 + 1017 41A1 85 73 STA ABYTE ; HOLD FOR LATER + 1018 41A3 29 C0 OPX1: AND #%11000000 ; MASK OUT GARBAGE BITS + 1019 41A5 D0 06 BNE OPX2 + 1020 41A7 20 2B 43 JSR GETLNG ; 00 = LONG IMMEDIATE + 1021 41AA 4C BE 41 JMP OPXNXT + 1022 41AD C9 40 OPX2: CMP #%01000000 ; IS IT A SHORT IMMEDIATE? + 1023 41AF D0 06 BNE OPX3 ; NO, KEEP GUESSING + 1024 41B1 20 27 43 JSR GETSHT ; 01 = SHORT IMMEDIATE + 1025 41B4 4C BE 41 JMP OPXNXT + 1026 41B7 C9 80 OPX3: CMP #%10000000 ; LAST TEST + 1027 41B9 D0 17 BNE OPX4 ; 11 = NO MORE ARGUMENTS + 1028 41BB 20 3F 43 JSR GETVAR ; 10 = VARIABLE + 1029 41BE A6 75 OPXNXT: LDX ADEX ; RETRIEVE ARGUMENT INDEX + 1030 41C0 A5 76 LDA VALUE+LO ; GRAB LSB OF VALUE + 1031 41C2 95 63 STA ARG1+LO,X ; STORE IN ARGUMENT TABLE + 1032 41C4 A5 77 LDA VALUE+HI ; GRAB MSB OF VALUE + 1033 41C6 95 64 STA ARG1+HI,X ; STORE THAT, TOO + 1034 41C8 E6 62 INC NARGS ; UPDATE ARGUMENT COUNTER + 1035 41CA E8 INX + 1036 41CB E8 INX + 1037 41CC 86 75 STX ADEX ; UPDATE INDEX + 1038 41CE E0 08 CPX #8 ; DONE 4 ARGUMENTS YET? + 1039 41D0 90 CB BCC OPX0 ; NO, GET SOME MORE + 1040 + 1041 ; ALL X-OP ARGUMENTS READY + 1042 + 1043 41D2 A5 61 OPX4: LDA OPCODE ; IS THIS + 1044 41D4 C9 E0 CMP #$E0 ; AN EXTENDED 2-OP? + 1045 41D6 B0 07 BCS DOXOP ; NO, IT'S A REAL X-OP + 1046 41D8 C9 C0 CMP #$C0 ; IS IT NEW OPCODE RANGE? + 1047 41DA 90 18 BCC ZEXTOP ; YES + 1048 41DC 4C 00 43 JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + 1049 + 1050 41DF 29 1F DOXOP: AND #%00011111 ; ISOLATE ID BITS + 1051 41E1 A8 TAY + 1052 41E2 B9 74 45 LDA OPTXL,Y + 1053 41E5 8D EF 41 STA GOX+1+LO + 1054 41E8 B9 54 45 LDA OPTXH,Y + 1055 41EB 8D F0 41 STA GOX+1+HI + 1056 41EE 20 FF FF GOX: JSR $FFFF ;DUMMY + 1057 41F1 4C B6 40 JMP MLOOP + 1058 + 1059 ; HANDLE EXTENDED OPCODE RANGE OPS + 1060 + 1061 41F4 C9 1D ZEXTOP: CMP #EXTLEN ; OUT OF RANGE? + 1062 41F6 B0 18 BCS BADEXT + 1063 41F8 A8 TAY ; OFFSET ALREADY CORRECT + 1064 41F9 B9 B1 45 LDA EXTOPL,Y + 1065 41FC 8D 06 42 STA GOE+1+LO + 1066 41FF B9 94 45 LDA EXTOPH,Y + 1067 4202 8D 07 42 STA GOE+1+HI + 1068 4205 20 FF FF GOE: JSR $FFFF ;DUMMY + 1069 4208 4C B6 40 JMP MLOOP + 1070 + 1071 ; *** ERROR #1 -- ILLEGAL X-OP *** + 1072 + 1073 420B A9 01 BADOPX: LDA #1 + 1074 420D 4C 0A 52 JMP ZERROR + 1075 + 1076 ; *** ERROR #16 -- ILLEGAL EXTENDED RANGE X-OP *** + 1077 + Wed May 24 1989 15:00 Page 18 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1078 4210 A9 10 BADEXT: LDA #16 + 1079 4212 4C 0A 52 JMP ZERROR + 1080 + 1081 ; HANDLE AN XCALL OPCODE + 1082 + 1083 4215 20 1F 92 OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + 1084 4218 85 73 STA ABYTE + 1085 421A 20 1F 92 JSR NEXTPC + 1086 421D 85 74 STA BBYTE + 1087 421F A5 73 LDA ABYTE ; ONE TO START WITH + 1088 4221 A2 00 LDX #0 + 1089 4223 86 75 STX ADEX ; INIT ARGUMENT INDEX + 1090 4225 F0 06 BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP + 1091 4227 A5 73 XCALL1: LDA ABYTE ; GET ARG BYTE + 1092 4229 0A ASL A ; SHIFT NEXT 2 BITS + 1093 422A 0A ASL A ; INTO BITS 7 & 6 + 1094 422B 85 73 STA ABYTE ; HOLD FOR LATER + 1095 422D 29 C0 XCALL2: AND #%11000000 ; MASK OUT GARBAGE + 1096 422F D0 06 BNE XCALL3 + 1097 4231 20 2B 43 JSR GETLNG ; 00 = LONG IMMEDIATE + 1098 4234 4C 48 42 JMP XCNXT + 1099 4237 C9 40 XCALL3: CMP #%01000000 ; SHORT IMMED? + 1100 4239 D0 06 BNE XCALL4 ; NO, TRY ANOTHER + 1101 423B 20 27 43 JSR GETSHT ; 01 = SHORT IMMED. + 1102 423E 4C 48 42 JMP XCNXT + 1103 4241 C9 80 XCALL4: CMP #%10000000 ; LAST TEST + 1104 4243 D0 8D BNE OPX4 ; 11 = NO MORE ARGS + 1105 4245 20 3F 43 JSR GETVAR ; 10 = VARIABLE + 1106 4248 A6 75 XCNXT: LDX ADEX + 1107 424A A5 76 LDA VALUE+LO + 1108 424C 95 63 STA ARG1+LO,X + 1109 424E A5 77 LDA VALUE+HI + 1110 4250 95 64 STA ARG1+HI,X + 1111 4252 E6 62 INC NARGS + 1112 4254 E8 INX + 1113 4255 E8 INX + 1114 4256 86 75 STX ADEX + 1115 4258 E0 10 CPX #16 + 1116 425A D0 03 BNE XCALL5 + 1117 425C 4C D2 41 JMP OPX4 ; DONE, GO DO IT + 1118 425F E0 08 XCALL5: CPX #8 ; DONE 1ST MODE BYTE? + 1119 4261 D0 C4 BNE XCALL1 ; NOT QUITE YET + 1120 4263 A5 74 LDA BBYTE ; SET UP FOR NEXT + 1121 4265 85 73 STA ABYTE ; MODE BYTE + 1122 4267 4C 2D 42 JMP XCALL2 ; GO DO IT + 1123 + 1124 ; ------------- + 1125 ; HANDLE A 0-OP + 1126 ; ------------- + 1127 + 1128 426A C9 BE OP0: CMP #190 ; IS IT EXTOP OP + 1129 426C F0 1A BEQ EXTOP ; YES + 1130 426E 29 0F AND #%00001111 ; ISOLATE 0-OP ID BITS + 1131 4270 A8 TAY + 1132 4271 B9 E4 44 LDA OPT0L,Y + 1133 4274 8D 7E 42 STA GO0+1+LO + 1134 4277 B9 D4 44 LDA OPT0H,Y + 1135 427A 8D 7F 42 STA GO0+1+HI + 1136 427D 20 FF FF GO0: JSR $FFFF ;DUMMY + 1137 4280 4C B6 40 JMP MLOOP + 1138 + 1139 ; *** ERROR #2 -- ILLEGAL 0-OP *** + 1140 + 1141 4283 A9 02 BADOP0: LDA #2 + 1142 4285 4C 0A 52 JMP ZERROR + 1143 + 1144 ; THIS OPCODE TELLS THAT NEXT OP IS PART OF THE + 1145 ; EXTENDED RANGE OF OPCODES, GET IT AND PROCESS IT + 1146 ; (THEY ARE ALL XOPS) + 1147 + 1148 4288 20 1F 92 EXTOP: JSR NEXTPC ; GO GET EXTENDED RANGE OP + 1149 428B 85 61 STA OPCODE ; SAVE IT + 1150 428D 4C 84 41 JMP OPEXT ; AND HANDLE IT + 1151 + 1152 + Wed May 24 1989 15:00 Page 19 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1153 ; ------------- + 1154 ; HANDLE A 1-OP + 1155 ; ------------- + 1156 + 1157 4290 OP1: + 1158 4290 29 30 and #%00110000 ; ISOLATE ARGUMENT BITS + 1159 4292 D0 07 bne OP1A + 1160 4294 20 1F 92 jsr NEXTPC ; get next byte + 1161 4297 A8 tay + 1162 4298 4C 9F 42 jmp OP1A1 + 1163 429B 29 20 OP1A: and #%00100000 ; TEST AGAIN + 1164 429D D0 0C bne OP1B + 1165 ; + 1166 ; 01 = SHORT IMMEDIATE + 1167 ; + 1168 429F 85 64 OP1A1: sta ARG1+HI + 1169 42A1 20 1F 92 jsr NEXTPC + 1170 42A4 85 63 sta ARG1+LO + 1171 42A6 E6 62 inc NARGS + 1172 42A8 4C B1 42 jmp OP1EX1 + 1173 42AB 20 3F 43 OP1B: JSR GETVAR ; 10 = VARIABLE + 1174 42AE 20 1C 43 OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] + 1175 42B1 A5 61 OP1EX1: LDA OPCODE + 1176 42B3 29 0F AND #%00001111 ; ISOLATE 0-OP ID BITS + 1177 42B5 A8 TAY + 1178 42B6 B9 04 45 LDA OPT1L,Y + 1179 42B9 8D C3 42 STA GO1+1+LO + 1180 42BC B9 F4 44 LDA OPT1H,Y + 1181 42BF 8D C4 42 STA GO1+1+HI + 1182 42C2 20 FF FF GO1: JSR $FFFF ;DUMMY + 1183 42C5 4C B6 40 JMP MLOOP + 1184 + 1185 ; *** ERROR #3 -- ILLEGAL 1-OP *** + 1186 + 1187 42C8 A9 03 BADOP1: LDA #3 + 1188 42CA 4C 0A 52 JMP ZERROR + 1189 + 1190 + 1191 + 1192 ; ------------- + 1193 ; HANDLE A 2-OP + 1194 ; ------------- + 1195 + 1196 42CD 29 40 OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT + 1197 42CF D0 0C BNE OP2A + 1198 ; + 1199 ; 0 = SHORT IMMEDIATE + 1200 ; + 1201 42D1 85 64 sta ARG1+HI + 1202 42D3 20 1F 92 jsr NEXTPC + 1203 42D6 85 63 sta ARG1+LO + 1204 42D8 E6 62 inc NARGS + 1205 42DA 4C E3 42 jmp OP2B1 + 1206 42DD 20 3F 43 OP2A: jsr GETVAR ; 1 = VARIABLE + 1207 42E0 20 1C 43 OP2B: jsr V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] + 1208 42E3 A5 61 OP2B1: lda OPCODE ; RESTORE OPCODE BYTE + 1209 42E5 29 20 and #%00100000 ; ISOLATE 2ND ARG BIT + 1210 42E7 D0 0A bne OP2C + 1211 42E9 85 66 sta ARG2+HI + 1212 42EB 20 1F 92 jsr NEXTPC + 1213 42EE 85 65 sta ARG2+LO + 1214 42F0 4C FE 42 jmp OP2D1 + 1215 42F3 20 3F 43 OP2C: jsr GETVAR ; 1 = VARIABLE + 1216 42F6 A5 76 OP2D: lda VALUE+LO ; MOVE 2ND [VALUE] + 1217 42F8 85 65 sta ARG2+LO ; INTO [ARG2] + 1218 42FA A5 77 lda VALUE+HI + 1219 42FC 85 66 sta ARG2+HI + 1220 42FE E6 62 OP2D1: inc NARGS ; UPDATE ARGUMENT COUNT + 1221 + 1222 ; EXECUTE A 2-OP OR EXTENDED 2-OP + 1223 + 1224 4300 A5 61 OP2EX: LDA OPCODE + 1225 4302 29 1F AND #%00011111 ; ISOLATE 0-OP ID BITS + 1226 4304 A8 TAY + 1227 4305 B9 34 45 LDA OPT2L,Y + Wed May 24 1989 15:00 Page 20 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- MAIN LOOP ---" + + 1228 4308 8D 12 43 STA GO2+1+LO + 1229 430B B9 14 45 LDA OPT2H,Y + 1230 430E 8D 13 43 STA GO2+1+HI + 1231 4311 20 FF FF GO2: JSR $FFFF ;DUMMY + 1232 4314 4C B6 40 JMP MLOOP + 1233 + 1234 ; *** ERROR #4 -- ILLEGAL 2-OP **** + 1235 + 1236 4317 A9 04 BADOP2: LDA #4 + 1237 4319 4C 0A 52 JMP ZERROR + 1238 + 1239 + 1240 + 1241 ; -------------------------------------- + 1242 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] + 1243 ; -------------------------------------- + 1244 + 1245 431C A5 76 V2A1: LDA VALUE+LO + 1246 431E 85 63 STA ARG1+LO + 1247 4320 A5 77 LDA VALUE+HI + 1248 4322 85 64 STA ARG1+HI + 1249 4324 E6 62 INC NARGS + 1250 4326 60 RTS + 1251 + 1252 4327 END + 1253 + 1254 4327 INCLUDE SUBS.ASM + 1255 4327 STTL "--- OPCODE SUPPORT SUBROUTINES ---" + 1256 PAGE + Wed May 24 1989 15:00 Page 21 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1257 + 1258 ; ----------------------- + 1259 ; FETCH A SHORT IMMEDIATE + 1260 ; ----------------------- + 1261 + 1262 4327 A9 00 GETSHT: LDA #0 ; MSB IS ZERO + 1263 4329 F0 03 BEQ GETV ; FETCH LSB FROM Z-CODE + 1264 + 1265 + 1266 ; ---------------------- + 1267 ; FETCH A LONG IMMEDIATE + 1268 ; ---------------------- + 1269 + 1270 432B 20 1F 92 GETLNG: JSR NEXTPC ; GRAB MSB + 1271 432E 85 77 GETV: STA VALUE+HI + 1272 4330 20 1F 92 JSR NEXTPC ; GRAB LSB + 1273 4333 85 76 STA VALUE+LO + 1274 4335 60 RTS + 1275 + 1276 + 1277 ; ---------------- + 1278 ; FETCH A VARIABLE + 1279 ; ---------------- + 1280 ; FROM INSIDE AN OPCODE (VARIABLE ID IN [A]) + 1281 + 1282 4336 AA VARGET: TAX ; IF NON-ZERO, + 1283 4337 D0 0B BNE GETVR1 ; ACCESS A VARIABLE + 1284 4339 20 66 43 JSR POPVAL ; ELSE PULL VAR OFF Z-STACK + 1285 433C 4C 97 43 JMP PSHVAL ; WITHOUT ALTERING STACK + 1286 + 1287 ; FROM THE MAIN LOOP (VARIABLE ID IN Z-CODE) + 1288 + 1289 433F 20 1F 92 GETVAR: JSR NEXTPC ; GRAB VAR-TYPE BYTE + 1290 4342 F0 22 BEQ POPVAL ; VALUE IS ON Z-STACK + 1291 + 1292 ; IS VARIABLE LOCAL OR GLOBAL? + 1293 + 1294 4344 C9 10 GETVR1: CMP #$10 ; IF LOW = 16, + 1295 4346 B0 0D BCS GETVRG ; IT'S GLOBAL + 1296 + 1297 ; HANDLE A LOCAL VARIABLE + 1298 + 1299 4348 0A GETVRL: ASL A ; WORD INDEX + 1300 4349 AA TAX ; INTO THE [LOCALS] TABLE + 1301 434A BD FE 1D LDA LOCALS-2+LO,X ; GRAB LSB + 1302 434D 85 76 STA VALUE+LO + 1303 434F BD FF 1D LDA LOCALS-2+HI,X ; AND MSB + 1304 4352 85 77 STA VALUE+HI + 1305 4354 60 RTS + 1306 ; + 1307 ; HANDLE A GLOBAL VARIABLE + 1308 ; + 1309 4355 GETVRG: + 1310 4355 20 14 44 jsr GVCALC ; GET ADDRESS OF GLOBAL INTO [FPC] + 1311 4358 20 56 92 jsr FETCHB ; and get hi part + 1312 435B 85 77 sta VALUE+HI + 1313 435D 20 BE 8F jsr NEXTFPC ; and point to next part + 1314 4360 20 56 92 jsr FETCHB ; and go get it + 1315 4363 85 76 sta VALUE+LO ; SAVE IT + 1316 4365 60 rts ; AND WE'RE DONE + 1317 + 1318 ; ---------------------------------- + 1319 ; POP Z-STACK INTO [VALUE] AND [X/A] + 1320 ; ---------------------------------- + 1321 ; ZSTACK DOUBLED IN SIZE FOR EZIP + 1322 ; SO THIS RTN ALL NEW + 1323 + 1324 4366 A5 AF POPVAL: LDA ZSP+LO ; IF ZSP+LO IS 0 + 1325 4368 D0 02 BNE POP1 + 1326 436A 85 B0 STA ZSP+HI ; MUST DEC. HI (HI = 0 OR 1 ONLY) + 1327 436C C6 AF POP1: DEC ZSP+LO ; THEN DEC ZSP LO + 1328 436E D0 04 BNE POP2 + 1329 4370 05 B0 ORA ZSP+HI ; LO + HI BOTH 0? + 1330 4372 F0 1E BEQ UNDER ; UNDERFLOW IF ZERO! + 1331 4374 A4 AF POP2: LDY ZSP+LO + Wed May 24 1989 15:00 Page 22 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1332 4376 A5 B0 LDA ZSP+HI + 1333 4378 F0 0C BEQ POP3 ; BOTTOM HALF OF ZSTACK + 1334 437A B9 00 0E LDA ZSTKTL,Y ; GET VALUE FROM TOP HALF + 1335 437D 85 76 STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + 1336 437F AA TAX + 1337 4380 B9 00 10 LDA ZSTKTH,Y + 1338 4383 85 77 STA VALUE+HI + 1339 4385 60 RTS + 1340 + 1341 4386 B9 00 0D POP3: LDA ZSTKBL,Y ; GET VALUE FROM BOTTOM HALF + 1342 4389 85 76 STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + 1343 438B AA TAX + 1344 438C B9 00 0F LDA ZSTKBH,Y + 1345 438F 85 77 STA VALUE+HI + 1346 4391 60 RTS + 1347 + 1348 ; *** ERROR #5 -- Z-STACK UNDERFLOW *** + 1349 4392 A9 05 UNDER: LDA #5 + 1350 4394 4C 0A 52 JMP ZERROR + 1351 + 1352 ; ----------------------- + 1353 ; PUSH [VALUE] TO Z-STACK + 1354 ; ----------------------- + 1355 + 1356 4397 A6 76 PSHVAL: LDX VALUE+LO + 1357 4399 A5 77 LDA VALUE+HI + 1358 + 1359 ; --------------------- + 1360 ; PUSH [X/A] TO Z-STACK + 1361 ; --------------------- + 1362 + 1363 439B 48 PUSHXA: PHA ; HOLD VALUE IN [A] A SEC. + 1364 439C A4 AF LDY ZSP+LO + 1365 439E A5 B0 LDA ZSP+HI + 1366 43A0 F0 0B BEQ PSHBOT ; ON BOTTOM HALF OF STACK + 1367 43A2 8A TXA + 1368 43A3 99 00 0E STA ZSTKTL,Y ; PUSH VALUE ONTO TOP HALF OF STACK + 1369 43A6 68 PLA + 1370 43A7 99 00 10 STA ZSTKTH,Y + 1371 43AA 4C B5 43 JMP PSHUPD ; NOW UPDATE POINTER + 1372 + 1373 43AD 8A PSHBOT: TXA ; PLACE VALUE ON ZSTACK + 1374 43AE 99 00 0D STA ZSTKBL,Y + 1375 43B1 68 PLA + 1376 43B2 99 00 0F STA ZSTKBH,Y + 1377 43B5 E6 AF PSHUPD: INC ZSP+LO ; UPDATE ZSTACK POINTER + 1378 43B7 D0 08 BNE PSHEX + 1379 43B9 A5 AF LDA ZSP+LO + 1380 43BB 05 B0 ORA ZSP+HI + 1381 43BD D0 03 BNE OVER ; OVERFLOW IF $200 + 1382 43BF E6 B0 INC ZSP+HI ; TO 1 + 1383 43C1 60 PSHEX: RTS + 1384 + 1385 ; *** ERROR #6 -- Z-STACK OVERFLOW *** + 1386 43C2 A9 06 OVER: LDA #6 + 1387 43C4 4C 0A 52 JMP ZERROR + 1388 + 1389 + 1390 ; -------------- + 1391 ; RETURN A VALUE + 1392 ; -------------- + 1393 ; FROM WITHIN AN OPCODE (VARIABLE ID IN [A]) + 1394 + 1395 43C7 AA VARPUT: TAX ; IF ZERO, + 1396 43C8 D0 1C BNE PUTVR1 + 1397 + 1398 ; FLUSH TOP WORD OFF STACK + 1399 ; AND REPLACE WITH [VALUE] + 1400 + 1401 43CA A5 AF LDA ZSP+LO ; IF ZSP+LO =0 + 1402 43CC D0 02 BNE VAR1 ; THEN HI =1 (GUARDED ELSEWHERE) + 1403 43CE 85 B0 STA ZSP+HI ; DECREMENT HI (ONLY 0 OR 1) + 1404 43D0 C6 AF VAR1: DEC ZSP+LO ; NOW DEC LOW BYTE + 1405 43D2 D0 C3 BNE PSHVAL + 1406 43D4 05 B0 ORA ZSP+HI + Wed May 24 1989 15:00 Page 23 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1407 43D6 F0 BA BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + 1408 43D8 D0 BD BNE PSHVAL + 1409 + 1410 ; RETURN A ZERO + 1411 43DA RET0: + 1412 43DA A9 00 lda #0 + 1413 43DC AA tax ; zero's all + 1414 ; + 1415 ; RETURN WORD IN [A], [X] (LO,HI) (EZIP EXPANDED TO A WORD) + 1416 ; + 1417 43DD PUTBYT: + 1418 43DD 85 76 STA VALUE+LO + 1419 43DF 86 77 STX VALUE+HI ; CLEAR MSB + 1420 ; + 1421 ; RETURN [VALUE] + 1422 ; + 1423 43E1 20 1F 92 PUTVAL: JSR NEXTPC ; GET VARIABLE ID BYTE + 1424 43E4 F0 B1 BEQ PSHVAL ; [VALUE] GOES TO Z-STACK + 1425 ; + 1426 ; LOCAL OR GLOBAL VARIABLE? + 1427 ; + 1428 43E6 C9 10 PUTVR1: CMP #$10 ; IF LOW = 16, + 1429 43E8 B0 0D BCS PUTVLG ; IT'S GLOBAL + 1430 ; + 1431 ; PUT A LOCAL VARIABLE + 1432 ; + 1433 43EA 0A PUTVLL: ASL A ; WORD INDEX + 1434 43EB AA TAX ; INTO THE [LOCALS] TABLE + 1435 43EC A5 76 LDA VALUE+LO ; GRAB LSB + 1436 43EE 9D FE 1D STA LOCALS-2+LO,X ; SAVE IN LOCAL TABLE + 1437 43F1 A5 77 LDA VALUE+HI ; DO SAME TO + 1438 43F3 9D FF 1D STA LOCALS-2+HI,X ; MSB + 1439 43F6 60 RTS + 1440 ; + 1441 ; RETURN A GLOBAL VARIABLE + 1442 ; + 1443 43F7 PUTVLG: + 1444 43F7 20 14 44 JSR GVCALC ; put address in [FPC] + 1445 43FA A5 8E lda FPCBNK ; and move it to stash spot + 1446 43FC 85 91 sta SPCBNK + 1447 43FE A5 8D lda FPCH + 1448 4400 85 90 sta SPCH + 1449 4402 A5 8C lda FPCL + 1450 4404 85 8F sta SPCL + 1451 4406 A5 77 lda VALUE+HI ; GET MSB + 1452 4408 20 35 92 jsr STASHB ; and save it + 1453 440B 20 9E 8F jsr NEXTSPC ; point to next byte + 1454 440E A5 76 lda VALUE+LO ; NOW GET LSB + 1455 4410 20 35 92 jsr STASHB ; and send it out + 1456 4413 60 rts + 1457 + 1458 ; ----------------------- + 1459 ; CALC GLOBAL WORD OFFSET + 1460 ; ----------------------- + 1461 ; ENTRY: VAR-I BYTE (16-255) IN [A] + 1462 ; EXIT: ABSOLUTE ADDRESS OF GLOBAL VAR IN [FPC] + 1463 4414 GVCALC: + 1464 4414 38 sec ; time for a subtract + 1465 4415 E9 10 sbc #$10 ; FORM A ZERO-ALIGNED INDEX + 1466 4417 A0 00 ldy #0 ; MAKE SURE MSB OF OFFSET AND [Y] + 1467 4419 84 79 sty I+HI ; ARE CLEARED + 1468 441B 0A asl A ; MULTIPLY OFFSET BY 2 + 1469 441C 26 79 rol I+HI ; TO WORD-ALIGN IT + 1470 441E 18 clc ; ADD OFFSET TO ADDR OF GLOBAL TABLE + 1471 441F 65 50 adc GLOBAL+LO ; TO FORM THE ABSOLUTE + 1472 4421 85 8C sta FPCL ; ADDRESS OF THE + 1473 4423 A5 79 lda I+HI ; DESIRED GLOBAL VARIABLE + 1474 4425 65 51 adc GLOBAL+HI ; STORE ADDRESS BACK IN [FPC] + 1475 4427 20 77 8F jsr SETPC ; now get memory page and bank + 1476 442A 85 8D sta FPCH ; hi part + 1477 442C 84 8E sty FPCBNK ; and bank + 1478 442E WCEX: + 1479 442E 60 rts + 1480 + 1481 + Wed May 24 1989 15:00 Page 24 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1482 ; --------------- + 1483 ; PREDICATE FAILS + 1484 ; --------------- + 1485 + 1486 442F 20 1F 92 PREDF: JSR NEXTPC ; GET 1ST BRANCH BYTE + 1487 4432 10 0C BPL PREDB ; DO BRANCH IF BIT 7 OFF + 1488 + 1489 + 1490 ; ----------------------- + 1491 ; IGNORE PREDICATE BRANCH + 1492 ; ----------------------- + 1493 ; ENTRY: 1ST BRANCH BYTE IN [A] + 1494 + 1495 4434 29 40 PREDNB: AND #%01000000 ; TEST BIT 6 + 1496 4436 D0 F6 BNE WCEX ; SHORT BRANCH IF SET + 1497 4438 4C 1F 92 JMP NEXTPC ; ELSE SKIP OVER 2ND BRANCH BYTE + 1498 + 1499 + 1500 ; ------------------ + 1501 ; PREDICATE SUCCEEDS + 1502 ; ------------------ + 1503 + 1504 443B 20 1F 92 PREDS: JSR NEXTPC ; GET 1ST BRANCH BYTE + 1505 443E 10 F4 BPL PREDNB ; DON'T BRANCH IF BIT 7 CLEAR + 1506 + 1507 + 1508 ; -------------------------- + 1509 ; PERFORM A PREDICATE BRANCH + 1510 ; -------------------------- + 1511 ; ENTRY: 1ST PRED BYTE IN [A] + 1512 + 1513 4440 AA PREDB: TAX ; SAVE HERE + 1514 4441 29 40 AND #%01000000 ; LONG OR SHORT BRANCH? + 1515 4443 F0 0B BEQ PREDLB ; LONG IF BIT 6 IS CLEAR + 1516 + 1517 ; HANDLE A SHORT BRANCH + 1518 + 1519 4445 8A TXA ; RESTORE PRED BYTE + 1520 4446 29 3F AND #%00111111 ; FORM SHORT OFFSET + 1521 4448 85 76 STA VALUE+LO ; USE AS LSB OF BRANCH OFFSET + 1522 444A A9 00 LDA #0 + 1523 444C 85 77 STA VALUE+HI ; MSB OF OFFSET IS ZERO + 1524 444E F0 17 BEQ PREDB7 ; DO THE BRANCH + 1525 + 1526 ; HANDLE A LONG BRANCH + 1527 + 1528 4450 8A PREDLB: TXA ; RESTORE 1ST PRED BYTE + 1529 4451 29 3F AND #%00111111 ; FORM MSB OF OFFSET + 1530 4453 AA TAX ; SAVE HERE FOR REFERENCE + 1531 4454 29 20 AND #%00100000 ; CHECK SIGN OF 14-BIT VALUE + 1532 4456 F0 04 BEQ DOB2 ; POSITIVE IF ZERO, SO USE [X] + 1533 4458 8A TXA ; ELSE RESTORE BYTE + 1534 4459 09 E0 ORA #%11100000 ; EXTEND THE SIGN BIT + 1535 445B AA TAX ; BACK HERE FOR STORAGE + 1536 445C 86 77 DOB2: STX VALUE+HI + 1537 445E 20 1F 92 JSR NEXTPC ; FETCH LSB OF 14-BIT OFFSET + 1538 4461 85 76 STA VALUE+LO + 1539 + 1540 ; BRANCH TO Z-ADDRESS IN [VALUE] + 1541 + 1542 4463 A5 77 PREDB1: LDA VALUE+HI ; CHECK MSB OF OFFSET + 1543 4465 D0 0E BNE PREDB3 ; DO BRANCH IF NZ + 1544 4467 A5 76 PREDB7: LDA VALUE+LO ; IF LSB IS NON-ZERO, + 1545 4469 D0 03 BNE PREDB2 ; MAKE SURE IT ISN'T 1 + 1546 446B 4C 61 79 JMP ZRFALS ; ELSE DO AN "RFALSE" + 1547 446E C9 01 PREDB2: CMP #1 ; IF OFFSET = 1 + 1548 4470 D0 03 BNE PREDB3 + 1549 4472 4C 56 79 JMP ZRTRUE ; DO AN "RTRUE" + 1550 + 1551 ; ENTRY POINT FOR "JUMP" + 1552 + 1553 4475 A5 76 PREDB3: LDA VALUE+LO ; SUBTRACT 2 FROM OFFSET + 1554 4477 38 SEC ; IN [VALUE] + 1555 4478 E9 02 SBC #2 + 1556 447A AA TAX ;SAVE LO BYTE + Wed May 24 1989 15:00 Page 25 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1557 447B A5 77 LDA VALUE+HI + 1558 447D E9 00 SBC #0 + 1559 447F 85 78 STA I+LO ;MSB OF OFFSET = LSB OF [I] + 1560 4481 A0 00 LDY #0 ; CLEAR THE MSB + 1561 4483 84 79 STY I+HI ; OF [I] + 1562 4485 0A ASL A ; EXTEND THE SIGN OF OFFSET + 1563 4486 26 79 ROL I+HI ; INTO MSB OF [I] + 1564 4488 0A ASL A + 1565 4489 26 79 ROL I+HI ; (EZIP) + 1566 448B 0A asl A + 1567 448C 26 79 rol I+HI ; (YZIP) ??!! + 1568 448E 8A TXA ; GET LSB OF OFFSET + 1569 448F 65 80 ADC ZPCL ; ADD LOW 8 BITS OF ZPC + 1570 4491 90 06 BCC PREDB5 ; IF OVERFLOWED, + 1571 4493 E6 78 INC I+LO ; UPDATE UPPER 9 BITS + 1572 4495 D0 02 BNE PREDB5 + 1573 4497 E6 79 INC I+HI + 1574 4499 85 80 PREDB5: STA ZPCL ; UPDATE ZPC + 1575 449B A5 78 LDA I+LO ; IF UPPER 9 BITS ARE ZERO, + 1576 449D 05 79 ORA I+HI ; NO NEED TO CHANGE PAGES + 1577 449F F0 12 BEQ PREDB6 + 1578 44A1 A5 78 LDA I+LO ; ELSE CALC NEW UPPER BITS + 1579 44A3 18 CLC + 1580 44A4 65 81 ADC ZPCM + 1581 44A6 85 81 STA ZPCM + 1582 44A8 A5 79 LDA I+HI + 1583 44AA 65 82 ADC ZPCH + 1584 44AC 29 07 AND #%00000111 + 1585 44AE 85 82 STA ZPCH + 1586 44B0 4C AA 90 JMP VLDZPC ;MAKE VALID + 1587 44B3 PREDB6: + 1588 + 1589 ; FALL THROUGH ... + 1590 + 1591 ; ---- + 1592 ; NOOP + 1593 ; ---- + 1594 + 1595 44B3 60 ZNOOP: RTS + 1596 + 1597 + 1598 ; ---------------------- + 1599 ; MOVE [ARG1] TO [VALUE] + 1600 ; ---------------------- + 1601 + 1602 44B4 A5 63 A12VAL: LDA ARG1+LO + 1603 44B6 85 76 STA VALUE+LO + 1604 44B8 A5 64 LDA ARG1+HI + 1605 44BA 85 77 STA VALUE+HI + 1606 44BC 60 RTS + 1607 + 1608 + 1609 ; ----------------------------------- + 1610 ; INDICATE STATUS LINE REFRESH NEEDED + 1611 ; ----------------------------------- + 1612 + 1613 44BD AD 11 96 REFRSH: LDA ZBEGIN+ZFLAGS+1 ; PICK UP LOW BYTE OF FLAG WORD + 1614 44C0 09 04 ORA #%00000100 ; SET BIT 2 + 1615 44C2 8D 11 96 STA ZBEGIN+ZFLAGS+1 ; AND PUT IT BACK + 1616 44C5 60 RTS + 1617 + 1618 + 1619 ;DECJ RETURNS C=0 WHEN J=$FFFF + 1620 + 1621 44C6 A5 7A DECJ: LDA J+LO + 1622 44C8 38 SEC + 1623 44C9 E9 01 SBC #1 + 1624 44CB 85 7A STA J+LO + 1625 44CD A5 7B LDA J+HI + 1626 44CF E9 00 SBC #0 + 1627 44D1 85 7B STA J+HI + 1628 44D3 60 RTS + 1629 + 1630 44D4 END + 1631 + Wed May 24 1989 15:00 Page 26 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1632 44D4 INCLUDE DISPATCH.ASM + 1633 PAGE + Wed May 24 1989 15:00 Page 27 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE SUPPORT SUBROUTINES ---" + + 1634 44D4 STTL "--- OPCODE DISPATCH TABLES ---" + 1635 + 1636 + 1637 ; 0-OPS + 1638 + 1639 44D4 79 OPT0H: DB >ZRTRUE ;B0 + 1640 44D5 79 DB >ZRFALS ;B1 + 1641 44D6 79 DB >ZPRI ;B2 + 1642 44D7 79 DB >ZPRR ;B3 + 1643 44D8 44 DB >ZNOOP ;B4 + 1644 44D9 8F DB >OSAVE ;B5 + 1645 44DA 8F DB >OREST ;B6 + 1646 44DB 52 DB >ZSTART ;B7 + 1647 44DC 79 DB >ZRSTAK ;B8 + 1648 44DD 79 DB >ZCATCH ;B9 + 1649 44DE 52 DB >ZQUIT ;BA + 1650 44DF 54 DB >ZZCRLF ;BB + 1651 44E0 55 DB >ZUSL ;BC + 1652 44E1 5B DB >ZVER ;BD + 1653 44E2 41 DB >ZEXTOP ;BE + 1654 44E3 79 DB >ZORIG ;BF + 1655 + 1656 44E4 56 OPT0L: DB ZZERO ;80,90,A0 + 1676 44F5 79 DB >ZNEXT ;81 + 1677 44F6 79 DB >ZFIRST ;82 + 1678 44F7 79 DB >ZLOC ;83 + 1679 44F8 79 DB >ZPTSIZ ;84 + 1680 44F9 7A DB >ZINC ;85 + 1681 44FA 7A DB >ZDEC ;86 + 1682 44FB 7A DB >ZPRB ;87 + 1683 44FC 7F DB >ZCALL1 ;88 (EZIP) + 1684 44FD 7A DB >ZREMOV ;89 + 1685 44FE 7B DB >ZPRD ;8A + 1686 44FF 7B DB >ZRET ;8B + 1687 4500 7B DB >ZJUMP ;8C + 1688 4501 7B DB >ZPRINT ;8D + 1689 4502 7B DB >ZVALUE ;8E + 1690 4503 7F DB >ZICLL1 ;8F + 1691 + 1692 4504 96 OPT1L: DB BADOP2 ;00 (UNDEFINED) + 1712 4515 7F DB >ZEQUAL ;01 + 1713 4516 7B DB >ZLESS ;02 + 1714 4517 7B DB >ZGRTR ;03 + 1715 4518 7B DB >ZDLESS ;04 + 1716 4519 7B DB >ZIGRTR ;05 + 1717 451A 7C DB >ZIN ;06 + 1718 451B 7C DB >ZBTST ;07 + 1719 451C 7C DB >ZBOR ;08 + 1720 451D 7C DB >ZBAND ;09 + 1721 451E 7C DB >ZFSETP ;0A + 1722 451F 7C DB >ZFSET ;0B + 1723 4520 7C DB >ZFCLR ;0C + 1724 4521 7C DB >ZSET ;0D + 1725 4522 7C DB >ZMOVE ;0E + 1726 4523 7D DB >ZGET ;0F + 1727 4524 7D DB >ZGETB ;10 + 1728 4525 7D DB >ZGETP ;11 + 1729 4526 7D DB >ZGETPT ;12 + 1730 4527 7E DB >ZNEXTP ;13 + 1731 4528 7E DB >ZADD ;14 + 1732 4529 7E DB >ZSUB ;15 + 1733 452A 7E DB >ZMUL ;16 + 1734 452B 7E DB >ZDIV ;17 + 1735 452C 7E DB >ZMOD ;18 + 1736 452D 7F DB >ZCALL2 ;19 (EZIP) + 1737 452E 7F DB >ZICLL2 ;1A + 1738 452F 4E DB >ZCOLOR ;1B + 1739 4530 7F DB >ZTHROW ;1C + 1740 4531 43 DB >BADOP2 ;1D + 1741 4532 43 DB >BADOP2 ;1E + 1742 4533 43 DB >BADOP2 ;1F + 1743 + 1744 4534 17 OPT2L: DB ZCALL ;E0 + 1780 4555 80 DB >ZPUT ;E1 + 1781 4556 80 DB >ZPUTB ;E2 + 1782 4557 80 DB >ZPUTP ;E3 + 1783 4558 85 DB >ZREAD ;E4 + Wed May 24 1989 15:00 Page 29 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE DISPATCH TABLES ---" + + 1784 4559 81 DB >ZPRC ;E5 + 1785 455A 81 DB >ZPRN ;E6 + 1786 455B 81 DB >ZRAND ;E7 + 1787 455C 81 DB >ZPUSH ;E8 + 1788 455D 82 DB >ZPOP ;E9 + 1789 455E 4D DB >ZSPLIT ;EA + 1790 455F 6E DB >ZSCRN ;EB + 1791 + 1792 ; (EZIPS FROM HERE ON) + 1793 4560 7F DB >ZXCALL ;EC + 1794 4561 57 DB >ZCLR ;ED + 1795 4562 57 DB >ZERASE ;EE + 1796 4563 56 DB >ZCURST ;EF + 1797 4564 57 DB >ZCURGT ;F0 + 1798 4565 70 DB >ZLIGHT ;F1 + 1799 4566 55 DB >ZBUFOUT ;F2 + 1800 4567 55 DB >ZDIRT ;F3 + 1801 4568 57 DB >ZDIRIN ;F4 (NOT IMPLEMENTED) + 1802 4569 4E DB >ZSOUND ;F5 + 1803 456A 5A DB >ZINPUT ;F6 + 1804 456B 82 DB >ZINTBL ;F7 + 1805 456C 83 DB >ZBCOM ;F8 + 1806 456D 7F DB >ZICALL ;F9 + 1807 456E 7F DB >ZIXCLL ;FA + 1808 456F 86 DB >ZLEX ;FB + 1809 4570 86 DB >ZWSTR ;FC + 1810 4571 83 DB >ZCOPYT ;FD + 1811 4572 58 DB >ZPRNTT ;FE + 1812 4573 84 DB >ZASSND ;FF + 1813 + 1814 4574 B2 OPTXL: DB ZSAVE ;100 + 1851 4595 8D DB >ZREST ;101 + 1852 4596 84 DB >ZSHIFT ;102 + 1853 4597 84 DB >ZASHFT ;103 + 1854 4598 58 DB >ZFONT ;104 + 1855 4599 73 DB >ZDISPL ;105 + 1856 459A 78 DB >ZPICNF ;106 + 1857 459B 79 DB >ZDCLR ;107 + 1858 459C 4E DB >ZMARG ;108 + Wed May 24 1989 15:00 Page 30 + + "APPLE YZIP (c)Infocom, Inc.. --- INIT & MAINLINE" + "--- OPCODE DISPATCH TABLES ---" + + 1859 459D 8F DB >ZISAVE ;109 + 1860 459E 8F DB >ZIREST ;10A + 1861 459F 42 DB >BADEXT ;10B - NOT USED + 1862 45A0 42 DB >BADEXT ;10C - NOT USED + 1863 45A1 42 DB >BADEXT ;10D - NOT USED + 1864 45A2 42 DB >BADEXT ;10E - NOT USED + 1865 45A3 42 DB >BADEXT ;10F - NOT USED + 1866 45A4 6E DB >ZWINPOS ;110 + 1867 45A5 6F DB >ZWINSIZE ;111 + 1868 45A6 70 DB >ZWINATTR ;112 + 1869 45A7 70 DB >ZWINGET ;113 + 1870 45A8 71 DB >ZSCROLL ;114 + 1871 45A9 84 DB >ZFSTACK ;115 + 1872 45AA 84 DB >ZMINFO ;116 + 1873 45AB 84 DB >ZMLIMIT ;117 + 1874 45AC 84 DB >ZXPUSH ;118 + 1875 45AD 71 DB >ZWINPUT ;119 + 1876 45AE 58 DB >ZPRINTF ;11A + 1877 45AF 85 DB >ZMENU ;11B + 1878 45B0 79 DB >ZPICSET ;11c + 1879 + 1880 001D EXTLEN EQU $-EXTOPH + 1881 + 1882 45B1 EF EXTOPL: DB IOBUFF ; first 256 byte page + 2065 46FA 20 5D 48 jsr COPY_DATA ; and copy from IOBUFF to DBUFF + 2066 46FD E6 B7 inc DBUFF+HI ; point to next one + 2067 46FF A9 09 lda #>IOBUFF+1 ; next 256 byte page + 2068 4701 4C 5D 48 jmp COPY_DATA ; and copy it over + 2069 4704 GDBAD: + 2070 4704 4C 74 47 jmp DISK_FATAL ; just die then + 2071 4707 RETRY: + 2072 [01] IF CHECKSUM + 2073 DLINE RETRYING ; show me the way to go home + 2074 [00] ENDIF + 2075 + 2076 4707 C6 16 dec RETRIES ; count this try + 2077 4709 30 F9 bmi GDBAD ; it's dead jim + 2078 470B F0 2F beq RETRY0 ; ask for reset + 2079 470D C9 01 cmp #1 ; down to last time? + 2080 470F D0 61 bne RETRYX ; just try again + 2081 4711 AD DE 45 lda PSEEK+SM_FPOS+0 + 2082 4714 48 pha + 2083 4715 AD DF 45 lda PSEEK+SM_FPOS+1 + 2084 4718 48 pha + 2085 4719 AD E0 45 lda PSEEK+SM_FPOS+2 + 2086 471C 48 pha + 2087 471D A9 00 lda #0 ; seek to zero + 2088 471F 8D DE 45 sta PSEEK+SM_FPOS+0 ; save here for now + 2089 4722 8D DF 45 sta PSEEK+SM_FPOS+1 ; save here for now + 2090 4725 8D E0 45 sta PSEEK+SM_FPOS+2 ; save here for now + 2091 4728 SET_MARK PSEEK ; move to the block + 2092 4728 PRODOS $CE, PSEEK + 2093 4728 20 00 BF jsr $BF00 ; ProDOS handler + 2094 472B CE DB $CE ; ProDOS function code + 2095 472C DC45 DW PSEEK ; Function Parameter Block address + 2096 472E .MACEND + 2097 472E .MACEND + 2098 472E 68 pla + 2099 472F 8D E0 45 sta PSEEK+SM_FPOS+2 + 2100 4732 68 pla + 2101 4733 8D DF 45 sta PSEEK+SM_FPOS+1 + 2102 4736 68 pla + 2103 4737 8D DE 45 sta PSEEK+SM_FPOS+0 + 2104 473A 90 36 bcc RETRYX ; all done + 2105 473C RETRY0: + 2106 473C 48 pha ; save disk error + 2107 473D 20 A9 4C jsr SWAP2INFOW ; go to window zero + 2108 4740 DLINE RESEAT_MSG1 ; ask to move the disk around + 2109 4740 A2 2D ldx #RESEAT_MSG1 ; get other part of string + 2111 [01] IFMA 2 ; check to see if length passed in + 2112 ldy ; then just fetch it + 2113 [01] ELSE + 2114 4744 A0 1F ldy #RESEAT_MSG1L ; get length of string + 2115 [00] ENDIF + 2116 4746 20 6B 4C jsr DLINE ; print the string + 2117 4749 .MACEND + 2118 4749 AD CF 45 lda GMREF ; get ref num + 2119 474C CD 99 46 cmp GAME2REF ; game2? + 2120 474F D0 08 bne RETRY1 ; nope + 2121 4751 AC 89 46 ldy GAME2NML ; get length + Wed May 24 1989 15:00 Page 34 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2122 4754 B9 89 46 lda GAME2NM,Y ; and side # + 2123 4757 D0 06 bne RETRY2 ; and continue + 2124 4759 RETRY1: + 2125 4759 AC 77 46 ldy GAME1NML ; get length + 2126 475C B9 77 46 lda GAME1NM,Y ; and side # + 2127 475F RETRY2: + 2128 475F 20 7D 5D jsr CHAR ; send char out there + 2129 4762 DLINE RESEAT_MSG2 ; and finish statement + 2130 4762 A2 4C ldx #RESEAT_MSG2 ; get other part of string + 2132 [01] IFMA 2 ; check to see if length passed in + 2133 ldy ; then just fetch it + 2134 [01] ELSE + 2135 4766 A0 18 ldy #RESEAT_MSG2L ; get length of string + 2136 [00] ENDIF + 2137 4768 20 6B 4C jsr DLINE ; print the string + 2138 476B .MACEND + 2139 476B 68 pla ; get disk error back + 2140 476C 20 8A 47 jsr DISK_ERR ; tell the error + 2141 476F 20 C9 4C jsr SWAPBACK ; back to current window + 2142 4772 RETRYX: + 2143 4772 18 clc ; show goodness + 2144 4773 60 rts ; and done + 2145 ; + 2146 ; this is the fatal error spot + 2147 ; + 2148 4774 DISK_FATAL: + 2149 4774 20 8A 47 jsr DISK_ERR ; print out problem + 2150 4777 DRIVE_ERR: + 2151 4777 A9 0E lda #14 + 2152 4779 4C 0A 52 jmp ZERROR ; DRIVE ACCESS ERROR + 2153 ; + 2154 ; this routine prints out the string associated with the error and + 2155 ; returns with the carry set, like most routines do when there is + 2156 ; an error. The error should be in [A]. + 2157 ; + 2158 477C 50 72 6F 44 4F UNK_DISK: db "ProDOS error $" + 4781 53 20 65 72 72 + 4786 6F 72 20 24 + 2159 000E UNK_DISKL EQU $-UNK_DISK + 2160 + 2161 478A DISK_ERR: + 2162 478A 48 pha ; save [A] + 2163 478B 20 A9 4C jsr SWAP2INFOW ; point to information window + 2164 478E 68 pla ; get it back + 2165 + 2166 478F A2 1B ldx #ELISTL ; scan the error table + 2167 4791 DSKE: + 2168 4791 DD 69 6D cmp ELIST,X ; is it this one + 2169 4794 F0 16 beq DSKE1 ; ayyup + 2170 4796 CA dex ; now skip the address + 2171 4797 CA dex ; of the description + 2172 4798 CA dex ; point to next error number + 2173 4799 10 F6 bpl DSKE ; jump to start + 2174 ; + 2175 ; if we are here print out unknown error and it's value + 2176 ; + 2177 479B 48 pha ; save [A] + 2178 479C DLINE UNK_DISK ; show error + 2179 479C A2 7C ldx #UNK_DISK ; get other part of string + 2181 [01] IFMA 2 ; check to see if length passed in + 2182 ldy ; then just fetch it + 2183 [01] ELSE + 2184 47A0 A0 0E ldy #UNK_DISKL ; get length of string + 2185 [00] ENDIF + 2186 47A2 20 6B 4C jsr DLINE ; print the string + 2187 47A5 .MACEND + 2188 47A5 68 pla ; get [A] + 2189 47A6 20 D3 47 jsr HEXNUM ; print [A] + 2190 47A9 4C CB 47 jmp DSK_EXIT ; done + 2191 47AC DSKE1: + 2192 47AC E8 inx ; point to string address + 2193 47AD BD 69 6D lda ELIST,X ; get lo part + 2194 47B0 85 7E sta L+LO ; save it + Wed May 24 1989 15:00 Page 35 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2195 47B2 E8 inx ; point to hi part + 2196 47B3 BD 69 6D lda ELIST,X ; get hi part + 2197 47B6 AA tax ; save here + 2198 47B7 85 7F sta L+HI ; and here + 2199 47B9 A0 00 ldy #0 ; for offset + 2200 47BB B1 7E lda (L),Y ; get length of string + 2201 47BD A8 tay ; save in y + 2202 47BE E6 7E inc L+LO ; point past length + 2203 47C0 A5 7E lda L+LO ; get it + 2204 47C2 D0 01 bne DSKPR ; for printing + 2205 47C4 E8 inx ; wrapped + 2206 47C5 DSKPR: + 2207 47C5 8A txa ; hi part in a + 2208 47C6 A6 7E ldx L+LO ; lo part in X + 2209 47C8 20 6B 4C jsr DLINE ; print out message + 2210 47CB DSK_EXIT: + 2211 47CB 20 DB 8C jsr GETRET ; wait for RETURN + 2212 47CE 20 C9 4C jsr SWAPBACK ; all done + 2213 47D1 38 sec ; show badness again + 2214 47D2 60 rts ; and be done with it + 2215 ; + 2216 ; HEXNUM - print out the HEX value of [A] at the current cursor + 2217 ; location + 2218 ; + 2219 47D3 HEXNUM: + 2220 47D3 48 pha + 2221 47D4 4A lsr A + 2222 47D5 4A lsr A + 2223 47D6 4A lsr A + 2224 47D7 4A lsr A + 2225 47D8 20 DC 47 jsr NIB1 + 2226 47DB 68 pla + 2227 47DC NIB1: + 2228 47DC 29 0F and #%00001111 + 2229 47DE A8 tay + 2230 47DF B9 E6 47 lda HCHARS,Y + 2231 47E2 20 7D 5D jsr CHAR ; print it out + 2232 47E5 60 rts + 2233 47E6 30 31 32 33 34 HCHARS: DB "0123456789ABCDEF" + 47EB 35 36 37 38 39 + 47F0 41 42 43 44 45 + 47F5 46 + 2234 + 2235 ; ---------------------- + 2236 ; WRITE [DBUFF] TO DISK + 2237 ; ---------------------- + 2238 ; ENTRY: File already open and positioned, ready to be written to + 2239 ; from page in (DBUFF). Writes out 512bytes, starting @ DBUFF. + 2240 ; EXIT: CARRY CLEAR IF OKAY, SET IF FAILED + 2241 + 2242 47F6 PUTDSK: + 2243 47F6 A6 B8 ldx DSKBNK ; get bank + 2244 47F8 A0 00 ldy #0 ; clear Y + 2245 47FA A9 08 lda #>IOBUFF ; first buffer + 2246 47FC 20 EE 00 jsr SAVE_DATA ; and copy from DBUFF to IOBUFF + 2247 + 2248 [01] IF CHECKSUM == 1 + 2249 lda #>IOBUFF + 2250 jsr CKS_BLOCK + 2251 [00] ENDIF + 2252 + 2253 47FF 20 34 48 jsr NEXT_DBUFF ; point to next buffer + 2254 4802 A6 B8 ldx DSKBNK ; go get new DSKBNK + 2255 4804 A0 00 ldy #0 ; clear Y again + 2256 4806 A9 09 lda #>IOBUFF+1 ; top part + 2257 4808 20 EE 00 jsr SAVE_DATA ; copy to IOBUFF + 2258 + 2259 [01] IF CHECKSUM == 1 + 2260 lda #>IOBUFF+1 + 2261 jsr CKS_BLOCK + 2262 [00] ENDIF + 2263 + 2264 480B 20 34 48 jsr NEXT_DBUFF ; count buffer + 2265 480E 4C 4F 48 jmp WRITE_DOS ; and now write it + 2266 ; --------------------- + Wed May 24 1989 15:00 Page 36 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2267 ; READ DBLOCK FROM DISK + 2268 ; --------------------- + 2269 ; CALLED BY RESTORE + 2270 ; ENTER: with file already set up as it DBUFF + 2271 ; L+LO == # of 256k blocks to read + 2272 ; + 2273 4811 GETRES: + 2274 4811 A5 7E lda L+LO ; get # of blocks + 2275 4813 8D D3 45 sta READ_PB+RD_BUFFLEN+HI + 2276 4816 20 56 48 jsr READ_DOS + 2277 4819 A2 02 ldx #>PAGELEN ; get starting number of pages + 2278 481B 8E D3 45 stx READ_PB+RD_BUFFLEN+HI + 2279 481E 90 01 bcc GTROK ; everything is fine + 2280 4820 60 rts ; error if c == set + 2281 4821 GTROK: + 2282 4821 A9 08 lda #>IOBUFF ; start at first block + 2283 4823 85 7F sta L+HI ; we can use L+HI + 2284 4825 GTRLOOP: + 2285 4825 A5 7F lda L+HI ; doing this block + 2286 + 2287 [01] IF CHECKSUM == 1 + 2288 jsr CKS_BLOCK ; check check sum + 2289 [00] ENDIF + 2290 + 2291 4827 20 5D 48 jsr COPY_DATA ; and copy from IOBUFF to DBUFF + 2292 482A 20 34 48 jsr NEXT_DBUFF ; check for wrap + 2293 482D E6 7F inc L+HI ; count this block + 2294 482F C6 7E dec L+LO ; count this block + 2295 4831 D0 F2 bne GTRLOOP ; do next one + 2296 4833 60 rts ; all finished + 2297 ; + 2298 ; NEXT_DBUFF + 2299 ; increment DBUFF to count the 2 pages done + 2300 ; + 2301 4834 NEXT_DBUFF: + 2302 4834 E6 B7 inc DBUFF+HI ; point to next page + 2303 4836 A5 B7 lda DBUFF+HI ; see where we are + 2304 4838 C9 BF cmp #>PRGLBL ; wrapping? + 2305 483A D0 10 bne GTREX ; okay then + 2306 483C A5 B8 lda DSKBNK ; which bank we be in + 2307 483E D0 06 bne GTR1 ; aux, so go to page 3 + 2308 4840 E6 B8 inc DSKBNK ; point to aux + 2309 4842 A9 40 lda #Z2PAGE ; start of page 2 + 2310 4844 D0 06 bne GTREX ; so tell me which page + 2311 4846 GTR1: + 2312 4846 A9 FF lda #P3BANK ; show page 3 bank + 2313 4848 85 B8 sta DSKBNK ; okay + 2314 484A A9 D0 lda #Z3PAGE ; page 3 of things + 2315 484C GTREX: + 2316 484C 85 B7 sta DBUFF+HI ; saved + 2317 484E 60 rts ; all done + 2318 ; + 2319 484F WRITE_DOS: + 2320 484F WRITE WRITE_SV ; write out save buffer + 2321 484F PRODOS $CB, WRITE_SV + 2322 484F 20 00 BF jsr $BF00 ; ProDOS handler + 2323 4852 CB DB $CB ; ProDOS function code + 2324 4853 088B DW WRITE_SV ; Function Parameter Block address + 2325 4855 .MACEND + 2326 4855 .MACEND + 2327 4855 60 rts ; done + 2328 4856 READ_DOS: + 2329 4856 READ READ_PB ; read it + 2330 4856 PRODOS $CA, READ_PB + 2331 4856 20 00 BF jsr $BF00 ; ProDOS handler + 2332 4859 CA DB $CA ; ProDOS function code + 2333 485A CE45 DW READ_PB ; Function Parameter Block address + 2334 485C .MACEND + 2335 485C .MACEND + 2336 485C 60 rts ; go home + 2337 ; + 2338 ; COPY_DATA - + 2339 ; now move the data from iobuff to dbuff (in some bank) + 2340 ; which part of IOBUFF is in [a] ($08 - $0B) + 2341 ; + Wed May 24 1989 15:00 Page 37 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2342 485D COPY_DATA: + 2343 485D 8D 79 48 sta SDLP3+2 ; self-modify code to get from IOBUFF + 2344 4860 8D 02 C0 sta RDBNK+MAIN ; read from main + 2345 4863 A6 B8 ldx DSKBNK ; get which bank it's going to + 2346 4865 30 05 bmi CPD1 ; oh oh, third bank + 2347 4867 9D 04 C0 sta WRTBNK,X ; and select that bank for writing + 2348 486A 10 07 bpl CPD2 ; okay, bank selected + 2349 486C CPD1: + 2350 486C A5 B7 lda DBUFF+HI ; get from this zero page + 2351 486E 8D 09 C0 sta ALTZP+AUX ; talk about aux mem + 2352 4871 85 B7 sta DBUFF+HI ; and save this in aux mem ZP + 2353 4873 CPD2: + 2354 4873 A0 00 ldy #0 ; start at beginning + 2355 4875 84 B6 sty DBUFF+LO ; just to be sure + 2356 4877 SDLP3: + 2357 4877 B9 00 08 lda IOBUFF,Y ; this becomes modified! + 2358 487A 91 B6 sta (DBUFF),Y ; to [DBUFF] + 2359 487C C8 iny + 2360 487D D0 F8 bne SDLP3 + 2361 487F 8D 08 C0 sta ALTZP+MAIN ; talk about main page again + 2362 4882 8D 04 C0 sta WRTBNK+MAIN ; end up back at main + 2363 4885 60 rts + 2364 ; + 2365 ; Segment table handling routines + 2366 ; + 2367 + 2368 ; + 2369 ; FINDSEG - find the Virtual page in DBLOCK by searching through + 2370 ; the SEGTBL. + 2371 ; + 2372 4886 DISKPAGE: ds 2 ; spot to put starting disk page + 2373 4888 BIGPAGE: ds 2 ; DBLOCK/2 for 512 pages + 2374 488A FINDSEG: + 2375 488A AD 5A 6C lda DBLOCK+HI ; work with MSB first + 2376 488D 4A lsr A ; /2 + 2377 488E 8D 89 48 sta BIGPAGE+HI + 2378 4891 AD 59 6C lda DBLOCK+LO ; now LSB + 2379 4894 6A ror A ; /2 + 2380 4895 8D 88 48 sta BIGPAGE+LO + 2381 4898 AD 88 46 lda GAME1NUM ; get number for disk 1 + 2382 489B 20 01 49 jsr SCANSEG ; scan through the current disk table + 2383 489E AD 87 46 lda GAME1REF ; save refnum + 2384 48A1 90 0E bcc FNDSG1 ; found it, figger it out + 2385 48A3 AD 9A 46 lda GAME2NUM ; get number for disk 2 + 2386 48A6 20 01 49 jsr SCANSEG ; see if it is here + 2387 48A9 AD 99 46 lda GAME2REF ; save refnum + 2388 48AC 90 03 bcc FNDSG1 ; ayyup + 2389 48AE 20 79 49 jsr SEGQUEST ; get correct disk/file with segment + 2390 48B1 FNDSG1: + 2391 48B1 8D DD 45 sta PSEEK+SM_REFNUM ; for seeking + 2392 48B4 8D CF 45 sta GMREF ; and for reading + 2393 48B7 B1 1E lda (DSEGS),Y ; pick up MSB of disk page + 2394 48B9 8D 87 48 sta DISKPAGE+HI ; save it + 2395 48BC C8 iny ; point to LSB + 2396 48BD B1 1E lda (DSEGS),Y ; get it + 2397 48BF 8D 86 48 sta DISKPAGE+LO ; save it + 2398 ; now point to Starting page again + 2399 48C2 88 dey + 2400 48C3 88 dey + 2401 48C4 88 dey + 2402 48C5 88 dey + 2403 48C6 AD 88 48 lda BIGPAGE+LO ; LSB of desired page + 2404 48C9 38 sec ; doing subtract + 2405 48CA F1 1E sbc (DSEGS),Y ; get rid of LSB of starting page + 2406 48CC 8D DF 45 sta PSEEK+SM_FPOS+1 ; save here for now + 2407 48CF 88 dey ; point to MSB of starting page + 2408 48D0 AD 89 48 lda BIGPAGE+HI ; get DBLOCK MSB + 2409 48D3 F1 1E sbc (DSEGS),Y ; get offset + 2410 48D5 8D E0 45 sta PSEEK+SM_FPOS+2 ; save here temporarily + 2411 48D8 18 clc ; now add offset to starting disk page + 2412 48D9 AD 86 48 lda DISKPAGE+LO ; get starting disk page + 2413 48DC 6D DF 45 adc PSEEK+SM_FPOS+1 ; add inter-segment offset + 2414 48DF 8D DF 45 sta PSEEK+SM_FPOS+1 ; save LSB + 2415 48E2 AD 87 48 lda DISKPAGE+HI ; get MSB of segment disk page + 2416 48E5 6D E0 45 adc PSEEK+SM_FPOS+2 ; add inter-segment offset + Wed May 24 1989 15:00 Page 38 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2417 48E8 8D E0 45 sta PSEEK+SM_FPOS+2 ; save MSB of disk page + 2418 48EB 0E DF 45 asl PSEEK+SM_FPOS+1 ; *2 for 256Kb pages + 2419 48EE 2E E0 45 rol PSEEK+SM_FPOS+2 ; okay, we did + 2420 48F1 AD 59 6C lda DBLOCK+LO ; check to see which page in 512 we are + 2421 48F4 29 01 and #$01 ; if odd, then add one more + 2422 48F6 F0 08 beq FNDEX ; all done then + 2423 48F8 EE DF 45 inc PSEEK+SM_FPOS+1 ; one more page + 2424 48FB D0 03 bne FNDEX ; all done if no wrap + 2425 48FD EE E0 45 inc PSEEK+SM_FPOS+2 ; nother page + 2426 4900 FNDEX: + 2427 4900 60 rts ; done + 2428 ; + 2429 ; SCANSEG - look through the current segment table for the desired + 2430 ; address found in BIGPAGE. Return with Y pointing to disk page + 2431 ; and carry cleared if found. Otherwise, return carry set. + 2432 ; [A] = which side number we are checking (0-n) + 2433 ; + 2434 4901 SCANSEG: + 2435 4901 48 pha ; save which disk + 2436 4902 0A asl A ; make word index + 2437 4903 AA tax ; make it an index + 2438 4904 BD D0 1D lda DSKSEG+LO,X ; get LSB + 2439 4907 85 1E sta DSEGS+LO + 2440 4909 BD D1 1D lda DSKSEG+HI,X + 2441 490C 85 1F sta DSEGS+HI + 2442 490E A0 05 ldy #SGTNSEG+1 ; point to segment count + 2443 4910 B1 1E lda (DSEGS),Y ; get it + 2444 4912 AA tax ; use x as counter + 2445 4913 68 pla ; get which side + 2446 4914 A8 tay ; is it side zero + 2447 4915 D0 04 bne SCANSG1 ; nope + 2448 4917 A0 0E ldy #SGTSEG+6 ; skip first entry, cuz they're preload + 2449 4919 D0 02 bne SCANNING ; okay ready to go + 2450 491B SCANSG1: + 2451 491B A0 08 ldy #SGTSEG ; begin at beginning + 2452 491D SCANNING: + 2453 491D B1 1E lda (DSEGS),Y ; get MSB of start + 2454 491F CD 89 48 cmp BIGPAGE+HI ; check against block we want + 2455 4922 F0 06 beq SCAN1 ; might be okay + 2456 4924 90 0F bcc SCAN2 ; PAGE > start seg, check end seg + 2457 4926 C8 iny ; LSB of start + 2458 4927 SCAN0: + 2459 4927 C8 iny ; MSB of end + 2460 4928 B0 1F bcs NEXTSEG ; not this one + 2461 492A SCAN1: + 2462 492A C8 iny ; point to LSB of start + 2463 492B B1 1E lda (DSEGS),Y ; get LSB + 2464 492D CD 88 48 cmp BIGPAGE+LO ; check against desired LSB + 2465 4930 F0 20 beq GOTSEG ; we found it + 2466 4932 B0 F3 bcs SCAN0 ; DBLOCK LSB < then start LSB, not found + 2467 4934 88 dey ; point back to MSB of start + 2468 4935 SCAN2: + 2469 4935 C8 iny ; LSB of start + 2470 4936 C8 iny ; MSB of end + 2471 4937 B1 1E lda (DSEGS),Y ; get MSB of end + 2472 4939 CD 89 48 cmp BIGPAGE+HI ; check against DBLOCK MSB + 2473 493C 90 0B bcc NEXTSEG ; end < DBLOCK, check next segment + 2474 493E D0 13 bne GOTSEG1 ; end > DBLOCK, must be in this segment + 2475 4940 C8 iny ; point to end LSB + 2476 4941 B1 1E lda (DSEGS),Y ; get LSB + 2477 4943 CD 88 48 cmp BIGPAGE+LO ; how does it compare to desired LSB + 2478 4946 B0 0C bcs GOTSEG2 ; it's <= end, so it is here + 2479 4948 88 dey ; point back to MSB + 2480 4949 NEXTSEG: + 2481 4949 C8 iny ; point to LSB of end + 2482 494A C8 iny ; MSB of disk page + 2483 494B C8 iny ; LSB of disk page + 2484 494C C8 iny ; MSB of next start page + 2485 494D CA dex ; count this segment + 2486 494E D0 CD bne SCANNING ; check this segment + 2487 + 2488 4950 38 sec ; show not on this disk + 2489 4951 60 rts ; and done + 2490 4952 GOTSEG: + 2491 4952 C8 iny ; MSB of end page + Wed May 24 1989 15:00 Page 39 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2492 4953 GOTSEG1: + 2493 4953 C8 iny ; LSB of end page + 2494 4954 GOTSEG2: + 2495 4954 C8 iny ; MSB of disk offset + 2496 4955 18 clc ; show we found it + 2497 4956 60 rts ; all done + 2498 ; + 2499 ; SEGQUEST - find the correct disk/file with the desired page on + 2500 ; it. Returns SCANSEG's stuff. + 2501 ; + 2502 4957 DISKCNTR: ds 1 ; disk count down + 2503 4958 PAGENF: + 2504 4958 50 61 67 65 20 db "Page not found in segment table: " + 495D 6E 6F 74 20 66 + 4962 6F 75 6E 64 20 + 4967 69 6E 20 73 65 + 496C 67 6D 65 6E 74 + 4971 20 74 61 62 6C + 4976 65 3A 20 + 2505 0021 PAGENFL EQU $-PAGENF + 2506 4979 SEGQUEST: + 2507 4979 A9 01 lda #1 ; start at first disk + 2508 497B 8D 57 49 sta DISKCNTR ; init counter + 2509 497E SEGQL: + 2510 497E AD 57 49 lda DISKCNTR ; get disk + 2511 4981 CD 01 19 cmp SEGTBL+SGTDISKS+1 ; looked at all the disks? + 2512 4984 D0 24 bne SEGQL1 ; nope + 2513 ; + 2514 ; as a last resort, check disk 1, the boot disk + 2515 ; + 2516 4986 A9 00 lda #0 ; set up DISKCNTR + 2517 4988 8D 57 49 sta DISKCNTR ; we did + 2518 498B 20 01 49 jsr SCANSEG ; see if it is there + 2519 498E 90 27 bcc SEGQ1 ; we found it + 2520 + 2521 4990 DLINE PAGENF ; page not found + 2522 4990 A2 58 ldx #PAGENF ; get other part of string + 2524 [01] IFMA 2 ; check to see if length passed in + 2525 ldy ; then just fetch it + 2526 [01] ELSE + 2527 4994 A0 21 ldy #PAGENFL ; get length of string + 2528 [00] ENDIF + 2529 4996 20 6B 4C jsr DLINE ; print the string + 2530 4999 .MACEND + 2531 4999 AD 89 48 lda BIGPAGE+HI ; show MSB + 2532 499C 20 D3 47 jsr HEXNUM ; printed + 2533 499F AD 88 48 lda BIGPAGE+LO ; and LSB + 2534 49A2 20 D3 47 jsr HEXNUM ; we did + 2535 + 2536 49A5 A9 11 lda #17 ; bad page + 2537 49A7 4C 0A 52 jmp ZERROR ; die a horrible death + 2538 49AA SEGQL1: + 2539 49AA AD 57 49 lda DISKCNTR ; get which disk we be working on + 2540 49AD 20 01 49 jsr SCANSEG ; find out if it is here + 2541 49B0 90 05 bcc SEGQ1 ; it is, so open up file + 2542 49B2 EE 57 49 inc DISKCNTR ; not in this disk + 2543 49B5 D0 C7 bne SEGQL ; and try again + 2544 ; + 2545 ; we have found the disk it is in, so ask for it if necessary + 2546 ; + 2547 49B7 SEGQ1: + 2548 49B7 98 tya ; save the y pointer + 2549 49B8 48 pha ; it is saved + 2550 49B9 AD 57 49 lda DISKCNTR ; get which disk we found it under + 2551 49BC 20 C6 49 jsr FETCH_FILE ; go get the disk desired + 2552 49BF 68 pla ; get the Y reg back + 2553 49C0 A8 tay ; and show it + 2554 49C1 AD CF 45 lda GMREF ; get reference number again + 2555 49C4 60 rts ; all done + 2556 ; + 2557 ; FETCH_FILE: check to see if we can open GAMEFILE# (where # is in [A]) + 2558 ; if not, ask for DISK#. + 2559 ; + 2560 49C5 00 SAVENUM: db 0 ; spot to save ascii number + Wed May 24 1989 15:00 Page 40 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2561 49C6 FETCH_FILE: + 2562 49C6 18 clc ; adding to make + 2563 49C7 69 30 adc #$30 ; it an ascii number + 2564 49C9 8D C5 49 sta SAVENUM ; just save a minute + 2565 49CC EE C5 49 inc SAVENUM ; make name be one based + 2566 49CF AE 77 46 ldx GAME1NML ; get length of name + 2567 49D2 AD C5 49 lda SAVENUM ; get name back + 2568 49D5 C9 33 cmp #'3' ; are we looking for disk 1 or 2? + 2569 49D7 B0 18 bcs FEFI1 ; disks 3 and up handled special + 2570 49D9 FEFI00: + 2571 49D9 DD 77 46 cmp GAME1NM,X ; is it the current open one? + 2572 49DC D0 05 bne FEFI0 ; nope, so we need to open it + 2573 49DE AC 87 46 ldy GAME1REF ; get game 1 refnum + 2574 49E1 D0 35 bne FEFIX ; all set, so point to it + 2575 49E3 FEFI0: + 2576 49E3 20 E1 4A jsr DO_GAME1 ; handle it special + 2577 49E6 AD 87 46 lda GAME1REF ; fetch refnum + 2578 49E9 20 1B 76 jsr GET_PDATA ; now get the picture data + 2579 49EC AC 87 46 ldy GAME1REF ; refetch refnum + 2580 49EF D0 27 bne FEFIX ; so all done + 2581 49F1 FEFI1: + 2582 49F1 AE 89 46 ldx GAME2NML ; get length of second name + 2583 49F4 DD 89 46 cmp GAME2NM,X ; how bout second open file? + 2584 49F7 D0 05 bne FEFI2 ; nope, so we need to open it + 2585 49F9 AC 99 46 ldy GAME2REF ; it is second one, so show me + 2586 49FC D0 1A bne FEFIX ; it is open too + 2587 49FE FEFI2: + 2588 49FE AD 99 46 lda GAME2REF ; get its refnum + 2589 4A01 F0 09 beq FEFI20 ; nothing to close, thank you + 2590 4A03 8D 07 8B sta CLOSE_PB+CL_REFNUM ; show close who to close + 2591 4A06 CLOSE CLOSE_PB ; close it up tight + 2592 4A06 PRODOS $CC, CLOSE_PB + 2593 4A06 20 00 BF jsr $BF00 ; ProDOS handler + 2594 4A09 CC DB $CC ; ProDOS function code + 2595 4A0A 068B DW CLOSE_PB ; Function Parameter Block address + 2596 4A0C .MACEND + 2597 4A0C .MACEND + 2598 4A0C FEFI20: + 2599 4A0C 20 1F 4A jsr OPEN_GAME2 ; open up GAME2 file + 2600 4A0F AD 99 46 lda GAME2REF ; get refnum for this file + 2601 4A12 20 1B 76 jsr GET_PDATA ; now get the picture data + 2602 4A15 AC 99 46 ldy GAME2REF ; get ref back, please + 2603 4A18 FEFIX: + 2604 4A18 8C DD 45 sty PSEEK+SM_REFNUM ; for seeking + 2605 4A1B 8C CF 45 sty GMREF ; and for reading + 2606 4A1E 60 rts ; did it + 2607 ; + 2608 ; OPEN_GAME2 - open up the file that GAME2NM is pointing to, + 2609 ; returning the REFNUM in [A], after storing in GAME2REF, + 2610 ; and the 2 picture structures + 2611 ; + 2612 4A1F OPEN_GAME2: + 2613 4A1F AE 89 46 ldx GAME2NML ; get end of name + 2614 4A22 AD C5 49 lda SAVENUM ; get new name + 2615 4A25 9D 89 46 sta GAME2NM,X ; using second file + 2616 4A28 A9 46 lda #>GAME2NM ; get lo byte + 2617 4A2A 8D D8 45 sta OPEN_FILE+OP_PATHNAME+HI + 2618 4A2D A9 89 lda #GAME2FIO ; now set up file i/o buffer + 2621 4A34 8D DA 45 sta OPEN_FILE+OP_FILEBUFF+HI + 2622 4A37 A9 00 lda #0 if multi disk game + 2638 + 2639 4A56 SET_GAMEPRE: + 2640 4A56 20 A9 4C jsr SWAP2INFOW ; point to info window + 2641 4A59 AD 55 4A lda SWAPPED ; are we swapping disks? + 2642 4A5C F0 0B beq SETGP ; nope, don't change game prefix + 2643 4A5E AD C5 49 lda SAVENUM ; get which disk to put it + 2644 4A61 AC 9B 46 ldy GAMEPL ; get length of prefix + 2645 4A64 88 dey ; subtract 2 to point to prefix + 2646 4A65 88 dey ; number + 2647 4A66 99 9C 46 sta GAMEP,Y ; set number for prefix + 2648 4A69 SETGP: + 2649 4A69 A9 46 lda #>GAMEPL ; set up parm block + 2650 4A6B 8D E3 45 sta SET_PB+SP_PATHNAME+HI + 2651 4A6E A9 9B lda #SWAPSAVE ; get other part of string + 2670 [01] IFMA 2 ; check to see if length passed in + 2671 ldy ; then just fetch it + 2672 [01] ELSE + 2673 4A84 A0 20 ldy #SWAPSAVEL ; get length of string + 2674 [00] ENDIF + 2675 4A86 20 6B 4C jsr DLINE ; print the string + 2676 4A89 .MACEND + 2677 4A89 AD 55 4A lda SWAPPED ; should we ask for specific disk? + 2678 4A8C D0 15 bne SEGTP01 ; yes, so ask for it + 2679 4A8E DLINE NOSWAP ; no, so just get game disk + 2680 4A8E A2 04 ldx #NOSWAP ; get other part of string + 2682 [01] IFMA 2 ; check to see if length passed in + 2683 ldy ; then just fetch it + 2684 [01] ELSE + 2685 4A92 A0 0A ldy #NOSWAPL ; get length of string + 2686 [00] ENDIF + 2687 4A94 20 6B 4C jsr DLINE ; print the string + 2688 4A97 .MACEND + 2689 4A97 4C D8 4A jmp SEGTP03 ; and continue + 2690 4A9A SEGTP00: + 2691 4A9A DLINE INS_MSG ; ask for game disk + 2692 4A9A A2 0E ldx #INS_MSG ; get other part of string + 2694 [01] IFMA 2 ; check to see if length passed in + 2695 ldy ; then just fetch it + 2696 [01] ELSE + 2697 4A9E A0 08 ldy #INS_MSGL ; get length of string + 2698 [00] ENDIF + 2699 4AA0 20 6B 4C jsr DLINE ; print the string + 2700 4AA3 .MACEND + 2701 4AA3 SEGTP01: + 2702 4AA3 DLINE GAME, GAMEL ; this is the name of the game + 2703 4AA3 A2 68 ldx #GAME ; get other part of string + 2705 [01] IFMA 2 ; check to see if length passed in + 2706 4AA7 AC 67 46 ldy GAMEL ; then just fetch it + 2707 [01] ELSE + 2708 ldy #GAMEL ; get length of string + 2709 [00] ENDIF + 2710 4AAA 20 6B 4C jsr DLINE ; print the string + Wed May 24 1989 15:00 Page 42 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2711 4AAD .MACEND + 2712 4AAD DLINE SIDEMSG ; part 2 of message + 2713 4AAD A2 16 ldx #SIDEMSG ; get other part of string + 2715 [01] IFMA 2 ; check to see if length passed in + 2716 ldy ; then just fetch it + 2717 [01] ELSE + 2718 4AB1 A0 07 ldy #SIDEMSGL ; get length of string + 2719 [00] ENDIF + 2720 4AB3 20 6B 4C jsr DLINE ; print the string + 2721 4AB6 .MACEND + 2722 4AB6 AD C5 49 lda SAVENUM ; get which disk to put it + 2723 4AB9 20 7D 5D jsr CHAR ; print it out + 2724 4ABC DLINE DRIVE_MSG ; tell about drive + 2725 4ABC A2 1D ldx #DRIVE_MSG ; get other part of string + 2727 [01] IFMA 2 ; check to see if length passed in + 2728 ldy ; then just fetch it + 2729 [01] ELSE + 2730 4AC0 A0 10 ldy #DRIVE_MSGL ; get length of string + 2731 [00] ENDIF + 2732 4AC2 20 6B 4C jsr DLINE ; print the string + 2733 4AC5 .MACEND + 2734 4AC5 A9 32 lda #'2' ; assume it's drive 2 + 2735 4AC7 AE C5 49 ldx SAVENUM ; get which disk we want + 2736 4ACA E0 33 cpx #'3' ; >= side 3, must be disk drive 2 + 2737 4ACC B0 02 bcs SEGTP02 ; fine, send that message out + 2738 4ACE A9 31 lda #'1' ; ask for drive 1 then + 2739 4AD0 SEGTP02: + 2740 4AD0 20 7D 5D jsr CHAR ; save which drive + 2741 4AD3 A9 2E lda #'.' ; finish sentence + 2742 4AD5 20 7D 5D jsr CHAR ; okay + 2743 4AD8 SEGTP03: + 2744 4AD8 20 DB 8C jsr GETRET ; wait for + 2745 4ADB 4C 73 4A jmp SETGP0 ; try again + 2746 4ADE SETGP1: + 2747 4ADE 4C C9 4C jmp SWAPBACK ; pointing to disk + 2748 ; + 2749 ; DO_GAME1 - open up the special game 1 file and point to it + 2750 ; + 2751 4AE1 DO_GAME1: + 2752 4AE1 AC 87 46 ldy GAME1REF ; get the current game 1 ref num + 2753 4AE4 F0 0B beq DOG1 ; not currently open + 2754 4AE6 48 pha ; save Name + 2755 4AE7 8C 07 8B sty CLOSE_PB+CL_REFNUM ; show close + 2756 4AEA CLOSE CLOSE_PB ; and close it + 2757 4AEA PRODOS $CC, CLOSE_PB + 2758 4AEA 20 00 BF jsr $BF00 ; ProDOS handler + 2759 4AED CC DB $CC ; ProDOS function code + 2760 4AEE 068B DW CLOSE_PB ; Function Parameter Block address + 2761 4AF0 .MACEND + 2762 4AF0 .MACEND + 2763 4AF0 68 pla ; get name back + 2764 4AF1 DOG1: + 2765 4AF1 AE 77 46 ldx GAME1NML ; get length of name + 2766 4AF4 AD C5 49 lda SAVENUM ; get new number + 2767 4AF7 9D 77 46 sta GAME1NM,X ; save name + 2768 4AFA 48 pha ; save it for later use + 2769 4AFB A9 46 lda #>GAME1NM ; get lo byte + 2770 4AFD 8D D8 45 sta OPEN_FILE+OP_PATHNAME+HI + 2771 4B00 A9 77 lda #GAME1FIO ; now set up file i/o buffer + 2774 4B07 8D DA 45 sta OPEN_FILE+OP_FILEBUFF+HI + 2775 4B0A A9 00 lda #LSTVM ; get other part of string + 2832 [01] IFMA 2 ; check to see if length passed in + 2833 ldy ; then just fetch it + 2834 [01] ELSE + 2835 4B61 A0 0B ldy #LSTVML ; get length of string + 2836 [00] ENDIF + 2837 4B63 20 6B 4C jsr DLINE ; print the string + 2838 4B66 .MACEND + 2839 + 2840 4B66 ONLINE ONLINE_PB + 2841 4B66 PRODOS $C5, ONLINE_PB + 2842 4B66 20 00 BF jsr $BF00 ; ProDOS handler + 2843 4B69 C5 DB $C5 ; ProDOS function code + 2844 4B6A 4E4B DW ONLINE_PB ; Function Parameter Block address + 2845 4B6C .MACEND + 2846 4B6C .MACEND + 2847 4B6C 90 05 bcc LSTV1 ; worked fine + 2848 4B6E 20 8A 47 jsr DISK_ERR ; complain if we had an error + 2849 4B71 B0 31 bcs LSTVEX ; all done + 2850 4B73 LSTV1: + 2851 4B73 A9 00 lda #0 ; start at byte zero + 2852 4B75 48 pha ; saved on stack + 2853 4B76 LSTVL: + 2854 4B76 68 pla ; get index + 2855 4B77 AA tax ; make it an index + 2856 4B78 BD 00 08 lda IOBUFF,X ; get drive/length byte + 2857 4B7B F0 27 beq LSTVEX ; all done if == 0 + 2858 4B7D 29 0F and #$0F ; just care about length + Wed May 24 1989 15:00 Page 44 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZDOS (SEEKING, READING, WRITING) ---" + + 2859 4B7F A8 tay ; save in [Y] for now + 2860 4B80 8A txa ; into [A] for addition + 2861 4B81 18 clc ; doing add + 2862 4B82 69 10 adc #16 ; point to next entry + 2863 4B84 48 pha ; save for later reference + 2864 4B85 98 tya ; check for zero length + 2865 4B86 F0 EE beq LSTVL ; nothing here but an error + 2866 4B88 A9 2F lda #'/' ; start with / to be better + 2867 4B8A 20 7D 5D jsr CHAR ; and it is out there + 2868 4B8D LSTVCL: + 2869 4B8D E8 inx ; point to next char + 2870 4B8E BD 00 08 lda IOBUFF,X ; get char + 2871 4B91 20 7D 5D jsr CHAR ; print it out + 2872 4B94 88 dey ; count char + 2873 4B95 D0 F6 bne LSTVCL ; go get next char + 2874 4B97 A9 2F lda #'/' ; end with '/' to show volume status + 2875 4B99 20 7D 5D jsr CHAR ; and awaaaaay we go + 2876 4B9C A9 0D lda #EOL ; do a + 2877 4B9E 20 7D 5D jsr CHAR ; printed + 2878 4BA1 CA dex ; count back one, as loop starts with inx + 2879 4BA2 D0 D2 bne LSTVL ; go do next one + 2880 4BA4 LSTVEX: + 2881 4BA4 60 rts ; toots finis + 2882 ; + 2883 ; CHECKVOLS - set prefix to particular volume that is currently online + 2884 ; + 2885 4BA5 CHECKVOLS: + 2886 4BA5 A5 1D lda CHPTR+HI ; is it zero? + 2887 4BA7 D0 1C bne CHV1 ; if not, then get next volume + 2888 4BA9 ONLINE ONLINE_PB ; get online volumes + 2889 4BA9 PRODOS $C5, ONLINE_PB + 2890 4BA9 20 00 BF jsr $BF00 ; ProDOS handler + 2891 4BAC C5 DB $C5 ; ProDOS function code + 2892 4BAD 4E4B DW ONLINE_PB ; Function Parameter Block address + 2893 4BAF .MACEND + 2894 4BAF .MACEND + 2895 4BAF 90 02 bcc CHV0 ; okey dokey + 2896 4BB1 CHVBX: + 2897 4BB1 38 sec ; show badness + 2898 4BB2 60 rts ; all done + 2899 4BB3 CHV0: + 2900 4BB3 A9 F0 lda #<(IOBUFF-16) ; get LSB (-16 cuz we start with add) + 2901 4BB5 85 1C sta CHPTR+LO + 2902 4BB7 A9 08 lda #>IOBUFF ; and mSB + 2903 4BB9 85 1D sta CHPTR+HI + 2904 4BBB A9 02 lda #>SCRBUFF ; this is where we will work on it + 2905 4BBD 8D E3 45 sta SET_PB+SP_PATHNAME+HI + 2906 4BC0 A9 80 lda #SP_START ; where does it go? + 2965 4C15 85 7F sta L+HI ; L is pointer to there + 2966 4C17 GTS_RD: + 2967 4C17 A9 00 lda #MAIN ; make sure we are in main + 2968 4C19 8D 04 C0 sta WRTBNK+MAIN + 2969 4C1C READ READ_PB ; go get 1Kb + 2970 4C1C PRODOS $CA, READ_PB + 2971 4C1C 20 00 BF jsr $BF00 ; ProDOS handler + 2972 4C1F CA DB $CA ; ProDOS function code + 2973 4C20 CE45 DW READ_PB ; Function Parameter Block address + 2974 4C22 .MACEND + 2975 4C22 .MACEND + 2976 4C22 90 05 bcc GTS_RD1 ; just fine + 2977 4C24 20 07 47 jsr RETRY ; try again + 2978 4C27 90 CC bcc GTS_RDL ; and do it again + 2979 4C29 GTS_RD1: + 2980 4C29 A2 00 ldx #SP_BANK ; get bank that special is in + 2981 4C2B 9D 04 C0 sta WRTBNK,X + 2982 4C2E A9 08 lda #>IOBUFF ; get MSB of start + 2983 4C30 85 7D sta K+HI ; K is source + 2984 4C32 A2 02 ldx #2 ; 2 blocks of 256 bytes each + 2985 4C34 GTS_CPL0: + 2986 4C34 A0 00 ldy #0 ; indexer + 2987 4C36 GTS_CPL: + 2988 4C36 B1 7C lda (K),y ; get it + 2989 4C38 91 7E sta (L),y ; store it + 2990 4C3A C8 iny ; next + 2991 4C3B D0 F9 bne GTS_CPL ; gwon then + 2992 4C3D E6 7D inc K+HI ; point to next block + 2993 4C3F E6 7F inc L+HI ; for destination too + 2994 4C41 CA dex ; count block + 2995 4C42 D0 F0 bne GTS_CPL0 ; next block + 2996 4C44 C6 7A dec J+LO ; count this 1Kb + 2997 4C46 D0 CF bne GTS_RD ; go get next one + 2998 4C48 + 2999 4C48 8D 04 C0 sta WRTBNK+MAIN ; make sure we are in main + 3000 ; + 3001 ; now figger out last page + 3002 ; + 3003 4C4B A0 09 ldy #SGTSEG+1 ; get start segment LSB + 3004 4C4D B1 59 lda (INFODOS),Y ; got it + 3005 4C4F 18 clc ; doing add + 3006 4C50 69 17 adc #SP_SIZE ; add in size MSB + 3011 4C5A 8D A6 6C sta INFODOS_END+HI ; and save it + 3012 4C5D AD A5 6C lda INFODOS_END+LO ; now, subtract one to make + 3013 4C60 D0 03 bne GTS_END ; it inclusive + 3014 4C62 CE A6 6C dec INFODOS_END+HI ; wrapped, so dec MSB + 3015 4C65 GTS_END: + 3016 4C65 CE A5 6C dec INFODOS_END+LO ; make pointers inclusive + 3017 + 3018 4C68 60 rts ; done + 3019 + 3020 [01] IF CHECKSUM == 1 + 3021 CKS_COUNT: db 0 + 3022 CKSB: db 0 + 3023 CKS_BLOCK: + 3024 pha + 3025 sta CKSMOD+2 + 3026 ldy #0 + 3027 lda CKSB + 3028 CKSLP: + 3029 clc + 3030 CKSMOD: adc IOBUFF,Y + 3031 iny + 3032 bne CKSLP + 3033 + 3034 sta CKSB + 3035 inc CKS_COUNT + 3036 pla + 3037 rts + 3038 + 3039 [02] IF 0 + 3040 jsr HEXNUM + 3041 lda CKS_COUNT + 3042 cmp #$F + 3043 bne CKSCNT + 3044 lda #0 + 3045 sta CKS_COUNT + 3046 lda #EOL + 3047 bne CKSSEND + 3048 CKSCNT: + 3049 inc CKS_COUNT + 3050 lda #SPACE + 3051 CKSSEND: + 3052 jsr CHAR + 3053 jsr DISP_LINE + 3054 pla + 3055 rts + 3056 [01] ENDIF + 3057 + 3058 [00] ENDIF + 3059 + 3060 4C69 END + 3061 + 3062 4C69 INCLUDE MACHINE.ASM + 3063 4C69 STTL "--- MACHINE-DEPENDENT I/O: APPLE II ---" + 3064 PAGE + Wed May 24 1989 15:00 Page 47 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3065 ; ----------------------- + 3066 ; DIRECT PRINT LINE [X/A] + 3067 ; ----------------------- + 3068 ; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB) + 3069 ; STRING LENGTH IN [Y] + 3070 4C69 00 DLCNT: db 0 + 3071 4C6A 00 DLOFF: db 0 + 3072 4C6B DLINE: + 3073 4C6B 8E 85 4C stx STRING+LO ; DROP STRING ADDRESS + 3074 4C6E 8D 86 4C sta STRING+HI ; INTO DUMMY BYTES + 3075 4C71 8C 69 4C sty DLCNT ; COUNTER + 3076 4C74 20 AD 55 jsr CLRBUF ; send out what's out + 3077 4C77 A5 B1 lda SCREENF ; save output flag + 3078 4C79 48 pha + 3079 4C7A A2 01 ldx #1 ; INIT CHAR-FETCH INDEX + 3080 4C7C 86 B1 stx SCREENF ; make sure screen output is on + 3081 4C7E CA dex + 3082 4C7F 8E A3 6C stx CRLF_CHECK ; don't let swap happen + 3083 4C82 86 AA stx SCRIPT ; don't script any of my internal + 3084 4C84 BD DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE + 3085 4C85 0000 STRING: DW $0000 ; DUMMY OPERAND BYTES + 3086 4C87 8E 6A 4C stx DLOFF ; save X + 3087 4C8A 85 AC sta IOCHAR ; save here for DIRECT_OUT + 3088 4C8C 20 21 53 DOUT1: jsr DIRECT_OUT ; send directly out there + 3089 4C8F AE 6A 4C ldx DLOFF ; get x back + 3090 4C92 E8 inx + 3091 4C93 CE 69 4C dec DLCNT ; LOOP TILL + 3092 4C96 D0 EC bne DOUT ; OUT OF CHARS + 3093 4C98 20 AD 55 jsr CLRBUF ; and force the chars out + 3094 4C9B A2 01 ldx #1 ; allow scripting again + 3095 4C9D 86 AA stx SCRIPT ; okay, we did + 3096 4C9F 8E A3 6C stx CRLF_CHECK ; and turn on check + 3097 4CA2 68 pla ; get screen flag back + 3098 4CA3 85 B1 sta SCREENF ; bingo + 3099 4CA5 60 rts ; done + 3100 + 3101 ; SWAP2INFOW - save current state and swap to the information window, + 3102 ; which is currently window zero + 3103 4CA6 SWAPA1: ds 1 ; save for current ARG1 + 3104 4CA7 SWAPCW: ds 1 ; save for current window + 3105 4CA8 00 SWAPFLG: db 0 ; flag == 1 if we have already swapped + 3106 4CA9 SWAP2INFOW: + 3107 4CA9 AD A8 4C lda SWAPFLG ; already swapped? + 3108 4CAC D0 17 bne SWP2 ; ayyup + 3109 4CAE 20 AD 55 jsr CLRBUF ; clear out the buffer + 3110 4CB1 20 9F 4D jsr SAVE_CURSOR ; save current postion of cursor + 3111 4CB4 A5 63 lda ARG1+LO ; get current arg1 + 3112 4CB6 8D A6 4C sta SWAPA1 ; save it + 3113 4CB9 A5 A6 lda CURWIN ; get current window + 3114 4CBB 8D A7 4C sta SWAPCW ; save it + 3115 4CBE A9 00 lda #0 ; swap to window zero for messages + 3116 4CC0 85 63 sta ARG1+LO ; okay + 3117 4CC2 20 57 6E jsr ZSCRN ; and swap to it + 3118 4CC5 SWP2: + 3119 4CC5 EE A8 4C inc SWAPFLG ; show we are in swap window + 3120 4CC8 SWAPEX: + 3121 4CC8 60 rts ; all done + 3122 ; + 3123 ; SWAPBACK - swap out of info window, and back to old window + 3124 ; + 3125 4CC9 SWAPBACK: + 3126 4CC9 CE A8 4C dec SWAPFLG ; are we finally leaving for good? + 3127 4CCC D0 FA bne SWAPEX ; nope + 3128 4CCE AD A7 4C lda SWAPCW ; and now for current window + 3129 4CD1 85 63 sta ARG1+LO ; swap to it + 3130 4CD3 20 57 6E jsr ZSCRN ; we did + 3131 4CD6 AD A6 4C lda SWAPA1 ; and get arg1 back + 3132 4CD9 85 63 sta ARG1+LO ; we did + 3133 4CDB 4C B1 4D jmp GET_CURSOR ; and get cursor back + 3134 + 3135 ; ----------------------- + 3136 ; SEND [LBUFF] TO PRINTER + 3137 ; ----------------------- + 3138 ; ENTRY: LENTH OF LINE IN [PRLEN] + 3139 + Wed May 24 1989 15:00 Page 48 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3140 4CDE 60 PLEAV: RTS + 3141 + 3142 4CDF PPRINT: + 3143 4CDF A5 AA lda SCRIPT ; SCRIPTING INTERNALLY ENABLED? + 3144 4CE1 2D 73 6C and SCRIPTF ; SCRIPTING ON? + 3145 4CE4 2D 74 6C and SCRIPTFLG ; Window allow scripting? + 3146 4CE7 F0 F5 beq PLEAV ; NO, EXIT + 3147 4CE9 A5 36 lda CSW+LO ; SAVE NORMAL OUTPUT HOOK + 3148 4CEB 48 pha + 3149 4CEC A5 37 lda CSW+HI + 3150 4CEE 48 pha + 3151 4CEF AD 1C 4D lda ALTCSW+LO ; LOAD SCRIPTING HOOK + 3152 4CF2 85 36 sta CSW+LO + 3153 4CF4 AD 1D 4D lda ALTCSW+HI + 3154 4CF7 85 37 sta CSW+HI + 3155 4CF9 AD 82 C0 lda RDROM ; put system ROM in for printer out + 3156 4CFC A0 00 ldy #0 + 3157 4CFE PP5: + 3158 4CFE B9 00 02 lda LBUFF,Y ;GET A CHAR TO SEND OUT + 3159 4D01 30 05 bmi PP6 ; don't do highlighting + 3160 4D03 09 80 ora #$80 ; make it apple happy + 3161 4D05 20 ED FD jsr MCOUT + 3162 4D08 PP6: + 3163 4D08 C8 iny + 3164 4D09 CE 69 6C dec PRLEN ;LINE COUNT + 3165 4D0C D0 F0 bne PP5 ;PRINT WHOLE LINE + 3166 ; + 3167 ; ALL DONE, RESET TO NORMAL AND LEAVE + 3168 ; + 3169 4D0E AD 83 C0 lda BNK2SET ; write RAM, bank 1 + 3170 4D11 AD 83 C0 lda BNK2SET + 3171 4D14 68 pla + 3172 4D15 85 37 sta CSW+HI + 3173 4D17 68 pla + 3174 4D18 85 36 sta CSW+LO + 3175 4D1A 60 rts + 3176 + 3177 4D1B 00 PSTAT: DB 0 ;SET TO CLEAR WHEN BOOT, + 3178 ;I PUT IT HERE SO RESTART WON'T ALTER + 3179 4D1C 00 00 ALTCSW: DB 0,0 ;(WORD) PRINTER COUT + 3180 + 3181 ; FIRST TIME USING PRINTER, INITIALIZE IT + 3182 4D1E 0D SLOTM: DB EOL + 3183 4D1F 50 72 69 6E 74 DB "Printer Slot 1-7: " + 4D24 65 72 20 53 6C + 4D29 6F 74 20 31 2D + 4D2E 37 3A 20 + 3184 0013 SLOTML EQU $-SLOTM + 3185 + 3186 4D31 PCHK: + 3187 4D31 20 A9 4C jsr SWAP2INFOW ; point to info window + 3188 4D34 PCHK1: + 3189 4D34 DLINE SLOTM + 3190 4D34 A2 1E ldx #SLOTM ; get other part of string + 3192 [01] IFMA 2 ; check to see if length passed in + 3193 ldy M ; then just fetch it + 3194 [01] ELSE + 3195 4D38 A0 13 ldy #SLOTML ; get length of string + 3196 [00] ENDIF + 3197 4D3A 20 6B 4C jsr DLINE ; print the string + 3198 4D3D .MACEND + 3199 4D3D 20 31 51 jsr GETKEY + 3200 4D40 C9 38 cmp #'8' ;1-7 + 3201 4D42 B0 F0 bcs PCHK1 ;OOPS + 3202 4D44 C9 31 cmp #'1' ; less than '1'? + 3203 4D46 90 EC bcc PCHK1 ; ayyup + 3204 4D48 PC2: + 3205 4D48 49 F0 eor #$F0 ; make it a slot address + 3206 4D4A 8D 1D 4D sta ALTCSW+HI + 3207 4D4D A9 0D lda #EOL + 3208 4D4F 20 7D 5D jsr CHAR ;SEND >CR< TO SCREEN FOR NEATNESS + 3209 4D52 EE 1B 4D inc PSTAT ;SET TO ON + 3210 4D55 A5 36 lda CSW+LO ;SAVE NORMAL OUTPUT HOOK + 3211 4D57 48 pha + Wed May 24 1989 15:00 Page 49 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3212 4D58 A5 37 lda CSW+HI + 3213 4D5A 48 pha + 3214 4D5B AD 1C 4D lda ALTCSW+LO ;LOAD SCRIPTING HOOK + 3215 4D5E 85 36 sta CSW+LO + 3216 4D60 AD 1D 4D lda ALTCSW+HI + 3217 4D63 85 37 sta CSW+HI + 3218 4D65 20 98 4D jsr INITPRT ; now, init it + 3219 + 3220 4D68 AD 82 C0 lda RDROM ; bring in system ROM + 3221 4D6B A9 89 lda #$89 ; OUTPUT PRINTER SETUP SEQUENCE + 3222 4D6D 20 ED FD jsr MCOUT ; START WITH COMMAND CHAR >CTRL-I< + 3223 4D70 A9 B8 lda #$B8 ; 8 (80 COL WIDE) + 3224 4D72 20 ED FD jsr MCOUT + 3225 4D75 A9 B0 lda #$B0 ; 0 + 3226 4D77 20 ED FD jsr MCOUT + 3227 4D7A A9 CE lda #$CE ; N (LF AFTER CR) + 3228 4D7C 20 ED FD jsr MCOUT + 3229 4D7F A5 36 lda CSW+LO ; SAVE REAL PRINTER OUTPUT + 3230 4D81 8D 1C 4D sta ALTCSW+LO ; LOC. FOR NEXT TIME + 3231 4D84 A5 37 lda CSW+HI + 3232 4D86 8D 1D 4D sta ALTCSW+HI + 3233 4D89 68 pla ; RESET NORMAL OUTPUT + 3234 4D8A 85 37 sta CSW+HI + 3235 4D8C 68 pla + 3236 4D8D 85 36 sta CSW+LO + 3237 4D8F AD 83 C0 lda BNK2SET ; and bring back top RAM + 3238 4D92 AD 83 C0 lda BNK2SET ; okay + 3239 4D95 4C C9 4C jmp SWAPBACK ; and back to the old window + 3240 4D98 INITPRT: + 3241 4D98 A9 00 lda #0 ; jump to $Cn00 + 3242 4D9A 85 36 sta CSW+LO ; make LSB == 0 + 3243 4D9C 6C 36 00 jmp (CSW) ; and goto it + 3244 + 3245 + 3246 4D9F SAVE_CURSOR: + 3247 4D9F A5 01 lda SCRCY ; save the cursor pos + 3248 4DA1 A0 04 ldy #WINY ; get offset + 3249 4DA3 91 05 sta (WINDOW),Y ; first y pos + 3250 4DA5 C8 iny ; now x pos + 3251 4DA6 A5 00 lda SCRCX ; got it + 3252 4DA8 91 05 sta (WINDOW),Y ; saved it + 3253 4DAA A0 13 ldy #WINLCNT ; reset line count too + 3254 4DAC A5 AB lda LINCNT ; okay + 3255 4DAE 91 05 sta (WINDOW),Y ; get it + 3256 4DB0 60 rts + 3257 + 3258 4DB1 GET_CURSOR: + 3259 4DB1 A0 04 ldy #WINY ; get cursor pos back + 3260 4DB3 B1 05 lda (WINDOW),Y ; got y pos + 3261 4DB5 85 01 sta SCRCY ; saved + 3262 4DB7 C8 iny ; point to x pos + 3263 4DB8 B1 05 lda (WINDOW),Y ; got it + 3264 4DBA 85 00 sta SCRCX ; make it better + 3265 4DBC 38 sec ; subtract left margin to get how long line is + 3266 4DBD E5 04 sbc LEFTMRG ; okay we did that + 3267 4DBF B0 02 bcs GETCR1 ; make sure left margin is not > cur x pos + 3268 4DC1 A9 00 lda #0 ; otherwise, pretend length is zero + 3269 4DC3 GETCR1: + 3270 4DC3 85 A7 sta LENGTH+LO ; this is how big line is too + 3271 4DC5 A9 00 lda #0 ; clear MSB + 3272 4DC7 85 A8 sta LENGTH+HI + 3273 4DC9 06 A7 asl LENGTH+LO ; *2 + 3274 4DCB 26 A8 rol LENGTH+HI + 3275 4DCD 06 A7 asl LENGTH+LO ; *4 + 3276 4DCF 26 A8 rol LENGTH+HI + 3277 4DD1 + 3278 4DD1 A0 13 ldy #WINLCNT ; reset line count too + 3279 4DD3 B1 05 lda (WINDOW),Y ; get it + 3280 4DD5 85 AB sta LINCNT ; okay + 3281 4DD7 A9 01 lda #1 ; show cursor changed (maybe) + 3282 4DD9 8D 77 6C sta CURSFLG ; okay + 3283 4DDC 60 rts + 3284 + 3285 ; ------------ + 3286 ; SPLIT SCREEN + Wed May 24 1989 15:00 Page 50 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3287 ; ------------ + 3288 ; + 3289 ; SPLIT SCREEN AT LINE [ARG1] putting screen 1 at top and screen + 3290 ; 0 at bottom. + 3291 ; DISABLE SPLIT IF [ARG1] = 0 + 3292 ; + 3293 4DDD ZSPLIT: + 3294 4DDD 20 9F 4D jsr SAVE_CURSOR ; save the cursor pos + 3295 ; + 3296 ; first muck with window 1 + 3297 ; + 3298 4DE0 A5 63 lda ARG1+LO ; get split arg back + 3299 4DE2 8D A1 6D sta WINDOW1+WINHGHT ; this becomes the height of window 1 + 3300 4DE5 A9 00 lda #0 ; put top of 1 to top of screen + 3301 4DE7 8D 9F 6D sta WINDOW1+WINTOP ; okay, we did it + 3302 4DEA A5 63 lda ARG1+LO ; get new height + 3303 4DEC A2 FF ldx #$FF ; this is the counter + 3304 4DEE 38 sec ; get ready for subs + 3305 4DEF ZSPLIT0: + 3306 4DEF E8 inx ; count this line + 3307 4DF0 E9 09 sbc #FONT_H ; subtract off font height + 3308 4DF2 B0 FB bcs ZSPLIT0 ; still some lines + 3309 4DF4 CA dex ; save input line + 3310 4DF5 8E B6 6D stx WINDOW1+WINLINES ; saved + 3311 + 3312 4DF8 AD A3 6D lda WINDOW1+WINY ; check cursor pos + 3313 4DFB C5 63 cmp ARG1+LO ; against height + 3314 4DFD 90 11 bcc ZSPL1 ; inside window, so save it + 3315 4DFF ZSPL0: + 3316 4DFF A9 00 lda #0 ; reset to top left + 3317 4E01 8D A3 6D sta WINDOW1+WINY ; y pos at top + 3318 4E04 8D A4 6D sta WINDOW1+WINX ; x pos at left + 3319 4E07 8D B4 6D sta WINDOW1+WINLLEN+LO ; line length + 3320 4E0A 8D B5 6D sta WINDOW1+WINLLEN+HI ; line length + 3321 4E0D 8D B2 6D sta WINDOW1+WINLCNT ; line counter + 3322 ; + 3323 ; now muck with window 0 + 3324 ; + 3325 4E10 ZSPL1: + 3326 4E10 AD 87 6D lda WINDOW0+WINTOP ; top of window 0 + 3327 4E13 38 sec ; doing sub + 3328 4E14 E5 63 sbc ARG1+LO ; subtract out the new top + 3329 4E16 18 clc ; adding + 3330 4E17 6D 89 6D adc WINDOW0+WINHGHT ; to get the new height + 3331 ; bcc ZSPLIT1 ; okay, positive height + 3332 ; lda #0 ; make height 0 + 3333 4E1A ZSPLIT1: + 3334 4E1A 8D 89 6D sta WINDOW0+WINHGHT ; and save new height + 3335 4E1D + 3336 4E1D A2 FF ldx #$FF ; this is the counter + 3337 4E1F 38 sec ; get ready for subs + 3338 4E20 ZSPLIT2: + 3339 4E20 E8 inx ; count this line + 3340 4E21 E9 09 sbc #FONT_H ; subtract off font height + 3341 4E23 B0 FB bcs ZSPLIT2 ; still some lines + 3342 4E25 CA dex ; to save input line + 3343 4E26 8E 9E 6D stx WINDOW0+WINLINES ; saved + 3344 + 3345 4E29 A5 63 lda ARG1+LO ; this is the new top + 3346 4E2B 8D 87 6D sta WINDOW0+WINTOP ; set in structure + 3347 4E2E CD 8B 6D cmp WINDOW0+WINY ; make sure cursor is still in window + 3348 4E31 F0 13 beq ZSPL5 ; nope, at the top + 3349 4E33 90 11 bcc ZSPL5 ; or under it + 3350 4E35 8D 8B 6D sta WINDOW0+WINY ; put cursor at top + 3351 4E38 A9 00 lda #0 ; left of new + 3352 4E3A 8D 8C 6D sta WINDOW0+WINX ; window 0 + 3353 4E3D 8D 9C 6D sta WINDOW0+WINLLEN+LO ; linelength + 3354 4E40 8D 9D 6D sta WINDOW0+WINLLEN+HI ; linelength + 3355 4E43 8D 9A 6D sta WINDOW0+WINLCNT ; line counter + 3356 4E46 ZSPL5: + 3357 4E46 20 B1 4D jsr GET_CURSOR ; get the cursor pos back + 3358 + 3359 4E49 A9 00 lda #0 ; now switch to window zero + 3360 4E4B 85 63 sta ARG1+LO ; good bye + 3361 4E4D 4C 57 6E jmp ZSCRN ; making window 0 be current + Wed May 24 1989 15:00 Page 51 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3362 + 3363 ; ------ + 3364 ; MARGIN + 3365 ; ------ + 3366 ; + 3367 ; Set the margins for the window + 3368 ; + 3369 ; ARG1 - left margin + 3370 ; ARG2 - right margin + 3371 ; ARG3 - window ID (optional) + 3372 ; + 3373 4E50 ZMARG: + 3374 4E50 20 AD 55 jsr CLRBUF ; CLEAR LBUFF BEFORE RESETTING LINE MARGINS + 3375 4E53 20 9F 4D jsr SAVE_CURSOR ; save current cursor pos + 3376 4E56 + 3377 4E56 A5 62 lda NARGS ; see if window ID was passed + 3378 4E58 C9 03 cmp #3 ; if ==3, then it's there + 3379 4E5A F0 04 beq ZMRG1 ; okay, so use it + 3380 4E5C A5 A6 lda CURWIN ; get the current window + 3381 4E5E 85 67 sta ARG3+LO ; and use as the default + 3382 4E60 ZMRG1: + 3383 4E60 A5 67 lda ARG3+LO ; check what window + 3384 4E62 20 77 57 jsr SETWJ ; get window offset into J + 3385 4E65 A5 63 lda ARG1+LO ; do left margin first + 3386 4E67 A0 06 ldy #WINLM ; get offset + 3387 4E69 91 7A sta (J),Y ; save for window + 3388 4E6B C8 iny ; point to right margin + 3389 4E6C A5 65 lda ARG2+LO ; get right margin + 3390 4E6E 91 7A sta (J),Y ; save right margin + 3391 4E70 A0 03 ldy #WINWID ; get full width of window + 3392 4E72 B1 7A lda (J),Y ; got it + 3393 4E74 38 sec ; subtract off the 2 margins + 3394 4E75 A0 06 ldy #WINLM ; first the left margin + 3395 4E77 F1 7A sbc (J),Y ; okay, gone + 3396 4E79 C8 iny ; point to right margin + 3397 4E7A F1 7A sbc (J),Y ; and take it off + 3398 4E7C A0 14 ldy #WINXSZ ; set width of usable window + 3399 4E7E 91 7A sta (J),Y ; see, here it is + 3400 ; + 3401 ; move cursor to left margin + 3402 ; + 3403 4E80 A0 01 ldy #WINLEFT ; get left edge + 3404 4E82 B1 7A lda (J),Y ; got it + 3405 4E84 A0 06 ldy #WINLM ; and add left margin + 3406 4E86 18 clc ; adding + 3407 4E87 71 7A adc (J),Y ; to get minimum X + 3408 4E89 A0 05 ldy #WINX ; check to make sure X pos is okay + 3409 4E8B 91 7A sta (J),Y ; then reset it + 3410 ; + 3411 ; now see if we changed the current window + 3412 ; + 3413 4E8D ZMRGXP: + 3414 4E8D A6 67 ldx ARG3+LO ; get the window + 3415 4E8F 30 04 bmi ZMRG3 ; -3 means current window + 3416 4E91 E4 A6 cpx CURWIN ; check against the current window + 3417 4E93 D0 17 bne ZMRGX ; nope, so we be done + 3418 4E95 ZMRG3: + 3419 4E95 85 04 sta LEFTMRG ; [A] already has left margin + 3420 4E97 A0 14 ldy #WINXSZ ; get xsize to set + 3421 4E99 B1 05 lda (WINDOW),Y ; got it + 3422 4E9B 85 A2 sta XSIZE+LO ; this is for quicky comparing + 3423 4E9D A9 00 lda #0 ; clear MSB + 3424 4E9F 85 A3 sta XSIZE+HI + 3425 4EA1 06 A2 asl XSIZE+LO ; *2 + 3426 4EA3 26 A3 rol XSIZE+HI + 3427 4EA5 06 A2 asl XSIZE+LO ; *4 + 3428 4EA7 26 A3 rol XSIZE+HI + 3429 4EA9 20 B1 4D jsr GET_CURSOR ; restore the cursor pos + 3430 4EAC ZMRGX: + 3431 4EAC 60 rts + 3432 ; + 3433 ; SOUND + 3434 ; ----- + 3435 ; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID + 3436 ; (EZIP) + Wed May 24 1989 15:00 Page 52 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3437 + 3438 4EAD ZSOUND: + 3439 4EAD A6 63 ldx ARG1+LO ; GET SOUND WANTED + 3440 4EAF CA dex + 3441 4EB0 F0 11 beq BEEP + 3442 4EB2 CA dex + 3443 4EB3 D0 0D bne ZSOEX ; INVALID + 3444 4EB5 A0 FF ldy #$FF ; DURATION ($C0 = .1 SEC) + 3445 4EB7 BOOP: + 3446 4EB7 A9 10 lda #$10 ; TONE ($0C = 1 KHZ) + 3447 4EB9 20 27 4F jsr WAIT10 + 3448 4EBC AD 30 C0 lda SPKR ; TOGGLE SPEAKER + 3449 4EBF 88 dey + 3450 4EC0 D0 F5 bne BOOP + 3451 4EC2 ZSOEX: + 3452 4EC2 60 rts + 3453 + 3454 4EC3 BEEP: + 3455 4EC3 AD 82 C0 lda RDROM + 3456 4EC6 20 3A FF jsr MBELL ; just use system beep + 3457 4EC9 AD 83 C0 lda BNK2SET ; back to bank 2 + 3458 4ECC AD 83 C0 lda BNK2SET ; back to bank 2 + 3459 4ECF 60 rts + 3460 ; + 3461 ; just do the background color - foreground is always white/black + 3462 ; + 3463 ; + 3464 ; ZIPCOLOR - maps ZIP colors to screen colors + 3465 ; + 3466 4ED0 ZCOLOR: + 3467 4ED0 20 AD 55 jsr CLRBUF ; print out what we have + 3468 + 3469 4ED3 A5 62 lda NARGS ; check if window was passed + 3470 4ED5 C9 03 cmp #3 ; was it? + 3471 4ED7 F0 04 beq ZCLR0 ; ayyup + 3472 4ED9 A5 A6 lda CURWIN ; make it current window + 3473 4EDB 85 67 sta ARG3+LO ; it is now + 3474 4EDD ZCLR0: + 3475 4EDD A5 67 lda ARG3+LO ; get window ID + 3476 4EDF 20 77 57 jsr SETWJ ; and put pointer into J + 3477 + 3478 4EE2 A6 65 ldx ARG2+LO ; get background color + 3479 4EE4 F0 15 beq ZCLR2 ; check fore ground color + 3480 4EE6 10 06 bpl ZCLR01 ; not -1 + 3481 4EE8 20 0B 5E jsr GET_NYBBLE ; get me the color nybble here + 3482 4EEB 4C F7 4E jmp ZCLR11 ; and use as background color + 3483 4EEE ZCLR01: + 3484 4EEE CA dex ; check for default + 3485 4EEF D0 02 bne ZCLR1 ; nope, find the color + 3486 4EF1 A2 01 ldx #1 ; use black as default back color + 3487 4EF3 ZCLR1: + 3488 4EF3 CA dex ; zero base the color + 3489 4EF4 BD 3F 6C lda ZIPCOLOR,X ; get my color from the zip color + 3490 4EF7 ZCLR11: + 3491 4EF7 A0 0E ldy #WINBGND ; get background offset + 3492 4EF9 91 7A sta (J),Y ; saved color + 3493 ; + 3494 ; now do foreground color + 3495 ; + 3496 4EFB ZCLR2: + 3497 4EFB A6 63 ldx ARG1+LO ; get foreground color + 3498 4EFD F0 0E beq ZCLREX ; no change + 3499 4EFF CA dex ; check for default + 3500 4F00 D0 02 bne ZCLR3 ; nope, find the color + 3501 4F02 A2 08 ldx #8 ; use white as default fore color + 3502 4F04 ZCLR3: + 3503 4F04 CA dex ; zero base the color + 3504 4F05 BD 3F 6C lda ZIPCOLOR,X ; get my color from the zip color + 3505 4F08 A0 0D ldy #WINFORE ; foreground color offset + 3506 4F0A 8A txa ; get into A for fun + 3507 4F0B 91 7A sta (J),Y ; save in structure + 3508 4F0D ZCLREX: + 3509 4F0D 60 rts + 3510 + 3511 ; + Wed May 24 1989 15:00 Page 53 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3512 ; CHKTME RTN - CALLED BY INPUT & ZINPUT + 3513 ; + 3514 4F0E CHKTME: + 3515 4F0E A5 62 lda NARGS ; CHECK IF TIME LIMIT + 3516 4F10 C9 02 cmp #2 + 3517 4F12 F0 12 beq CHKT1 ; NO + 3518 4F14 A5 67 lda ARG3+LO ; GET DELAY WANTED + 3519 4F16 85 79 sta I+HI + 3520 4F18 A5 62 lda NARGS ; IS THERE A FCN? + 3521 4F1A C9 04 cmp #4 + 3522 4F1C D0 08 bne CHKT1 ; NO + 3523 4F1E A5 69 lda ARG4+LO ; YES, SET IT + 3524 4F20 85 7A sta J+LO + 3525 4F22 A5 6A lda ARG4+HI + 3526 4F24 85 7B sta J+HI + 3527 4F26 CHKT1: + 3528 4F26 60 rts ; just set things up, please + 3529 + 3530 4F27 WAIT10: + 3531 4F27 A9 02 lda #2 ; do this twice (maybe) + 3532 4F29 85 C6 sta DELAY_COUNTER ; put in counter + 3533 4F2B WAIT0: + 3534 4F2B AD 82 C0 lda RDROM ; get roms in + 3535 4F2E A2 04 ldx #4 ; .04 SEC (time to do other stuff) + 3536 4F30 A9 30 TIME1: lda #$30 ; .01 SEC + 3537 4F32 20 A8 FC jsr MWAIT + 3538 4F35 CA dex + 3539 4F36 D0 F8 bne TIME1 + 3540 + 3541 4F38 AD 83 C0 lda BNK2SET ; get roms out + 3542 4F3B AD 83 C0 lda BNK2SET + 3543 + 3544 4F3E A5 58 lda MOUSEF ; move mouse cursor? + 3545 4F40 F0 08 beq WAIT1 ; nope + 3546 4F42 AD A4 6C lda PTR_COUNT ; but do we really want to check it + 3547 4F45 D0 03 bne WAIT1 ; nope + 3548 4F47 4C 2B 50 jmp MOVE_MC ; move cursor, if necessary + 3549 4F4A WAIT1: + 3550 4F4A C6 C6 dec DELAY_COUNTER ; count loop + 3551 4F4C D0 DD bne WAIT0 ; go do again + 3552 4F4E 60 rts + 3553 ; + 3554 ; tick the ol timer + 3555 ; + 3556 4F4F TIMEK: + 3557 4F4F A9 03 lda #BLINK_RATE ; how often to blink + 3558 4F51 8D 92 4F sta CURCOUNT ; okay! + 3559 4F54 TIMEST: + 3560 4F54 A5 78 lda I+LO ; don't reset if not zero + 3561 4F56 D0 07 bne TIMELOOP ; so keep goin' then + 3562 4F58 A5 79 lda I+HI + 3563 4F5A 85 78 sta I+LO + 3564 4F5C 20 93 4F jsr STCUR ; start the cursor + 3565 4F5F TIMELOOP: + 3566 4F5F 20 27 4F jsr WAIT10 ; wait .10 secs + 3567 + 3568 4F62 20 E6 4F jsr FKEYX ; Check for Keystroke + 3569 4F65 30 23 bmi TIME2 ; OK, HE'S THERE, CONTINUE + 3570 + 3571 4F67 CE 92 4F dec CURCOUNT ; count down to toggle + 3572 4F6A D0 08 bne TMCNT ; okay, no blink + 3573 4F6C 20 93 4F jsr STCUR ; blink cursor + 3574 4F6F A9 03 lda #BLINK_RATE ; once per second + 3575 4F71 8D 92 4F sta CURCOUNT ; okay! + 3576 4F74 TMCNT: + 3577 4F74 C6 78 dec I+LO ; 10TH'S OF SECONDS TO WAIT + 3578 4F76 F0 02 beq TIMEOUT ; SOME TIME LEFT + 3579 + 3580 4F78 D0 E5 bne TIMELOOP ; so gwon back and try again! (JMP) + 3581 ; + 3582 ; THERE IS A TIME OUT, CHECK FOR A FCN + 3583 ; + 3584 4F7A TIMEOUT: + 3585 4F7A 20 BE 4F jsr ERCUR ; after erasing cursor + 3586 4F7D A5 7B lda J+HI ; IS THERE A FCN + Wed May 24 1989 15:00 Page 54 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3587 4F7F F0 0E beq TIMEBAD ; NO FCN, LEAVE WITH NOTHING + 3588 4F81 TIME3: + 3589 4F81 20 13 5B jsr INTCLL ; INTERNALLY CALL THE FCN + 3590 4F84 A5 76 lda VALUE+LO ; CHECK RESULTS + 3591 4F86 F0 CC beq TIMEST ; ELSE TRY AGAIN + 3592 4F88 D0 05 bne TIMEBAD ; else die a horrible death! + 3593 4F8A TIME2: + 3594 4F8A 20 BE 4F jsr ERCUR ; after erasing cursor + 3595 4F8D 18 clc ; GOT A KEY + 3596 4F8E 60 rts + 3597 4F8F TIMEBAD: + 3598 4F8F 38 sec + 3599 4F90 60 rts + 3600 ; + 3601 ; display the cursor in the current spot + 3602 ; + 3603 4F91 80 CURSTATE: db $80 ; blinking cursor state + 3604 4F92 00 CURCOUNT: db 0 ; toggle counter + 3605 + 3606 4F93 STCUR: + 3607 4F93 AD A2 6C lda CURSOR_OFF ; is the cursor off? + 3608 4F96 F0 01 beq STCUR1 ; no + 3609 4F98 60 rts ; yes, so don't do nuthin' + 3610 4F99 STCUR1: + 3611 4F99 48 pha ; save a + 3612 4F9A A5 BB lda INVFLG ; get current INVFLG + 3613 4F9C 48 pha ; save it + 3614 4F9D A9 80 lda #$80 ; make it all be ones + 3615 4F9F 85 BB sta INVFLG ; and blink + 3616 + 3617 4FA1 A9 20 lda #SPACE ; space for cursor + 3618 4FA3 8D DE 71 sta SHOW_CURSOR ; show that we are doing cursor + 3619 4FA6 20 7D 5D jsr CHAR ; and print it out + 3620 4FA9 20 EC 71 jsr DISP_LINE ; send it out + 3621 + 3622 4FAC AD 91 4F lda CURSTATE ; get current state + 3623 4FAF 49 80 eor #$80 ; toggle it + 3624 4FB1 8D 91 4F sta CURSTATE ; save it + 3625 4FB4 68 pla ; get invflg + 3626 4FB5 85 BB sta INVFLG ; restored + 3627 4FB7 A9 00 lda #0 ; clear cursor flag + 3628 4FB9 8D DE 71 sta SHOW_CURSOR ; okay + 3629 4FBC + 3630 4FBC 68 pla + 3631 4FBD 60 rts + 3632 ; + 3633 ; just erase the cusor char, but leave cursor in its old place + 3634 ; + 3635 4FBE ERCUR: + 3636 4FBE 48 pha ; save a + 3637 4FBF AD 91 4F lda CURSTATE ; get current state + 3638 4FC2 D0 03 bne ERCURX ; not on, leave alone + 3639 4FC4 20 93 4F jsr STCUR ; 'start' it out + 3640 4FC7 ERCURX: + 3641 4FC7 68 pla ; retrieve [A] + 3642 4FC8 60 rts + 3643 ; + 3644 ; timed key input loop + 3645 ; + 3646 ; carry set if timed out + 3647 ; char in [A], if there is one! + 3648 4FC9 TIMIN: + 3649 4FC9 A5 58 lda MOUSEF ; is there a mouse/joystick? + 3650 4FCB F0 03 beq TIMIN1 ; nope + 3651 4FCD 20 B5 62 jsr MSCON ; turn on mouse cursor + 3652 4FD0 TIMIN1: + 3653 4FD0 20 4F 4F jsr TIMEK ; check for keystroke + 3654 4FD3 B0 05 bcs TMBAD ; ELSE ABORT + 3655 4FD5 TM1: + 3656 4FD5 20 8B 51 jsr PARSEKEY ; GET ASCII INTO [A] AND [IOCHAR] + 3657 4FD8 B0 F6 bcs TIMIN1 ; c==1 means no good char + 3658 4FDA TMBAD: + 3659 4FDA A6 58 ldx MOUSEF ; is there a mouse/joystick? + 3660 4FDC F0 07 beq TIMIN2 ; nope + 3661 4FDE 08 php ; save status + Wed May 24 1989 15:00 Page 55 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3662 4FDF 48 pha ; save (possible) char + 3663 4FE0 20 56 62 jsr MSCOFF ; turn off mouse cursor + 3664 4FE3 68 pla ; get char back + 3665 4FE4 28 plp ; get return status + 3666 4FE5 TIMIN2: + 3667 4FE5 60 rts ; and away we go + 3668 ; + 3669 ; FKEYX - move the mouse cursor if any, then check for keystroke + 3670 ; + 3671 4FE6 FKEYX: + 3672 4FE6 A5 58 lda MOUSEF ; is there a mouse cursor? + 3673 4FE8 F0 38 beq KEYX ; nope + 3674 4FEA 30 07 bmi KEYMOUSE ; handle mouse + 3675 4FEC 20 AD 50 jsr DO_STICK ; handle joystick + 3676 4FEF 10 31 bpl KEYX ; go look for key still + 3677 4FF1 30 05 bmi KEYBTN ; do button handling + 3678 4FF3 KEYMOUSE: + 3679 4FF3 20 6E 50 jsr DO_MOUSE ; handle mouse stuff + 3680 4FF6 10 2A bpl KEYX ; go look for key still + 3681 ; + 3682 ; button hit, so show pos in MSTBL + 3683 ; + 3684 4FF8 KEYBTN: + 3685 4FF8 48 pha ; save status + 3686 4FF9 A5 CE lda MSTBL+LO + 3687 4FFB 85 8F sta SPCL + 3688 4FFD A5 CF lda MSTBL+HI + 3689 4FFF 85 90 sta SPCH + 3690 5001 A5 D0 lda MSTBL+ABANK + 3691 5003 85 91 sta SPCBNK + 3692 5005 A9 03 lda #ZMSLOCX+1 ; point to LSB of mouse x + 3693 5007 20 01 90 jsr ADDSPC ; add to point + 3694 500A A5 CB lda MSX ; get X + 3695 500C 18 clc ; center the hot spot + 3696 500D 69 01 adc #CURSW/2 ; add 1/2 width + 3697 500F 20 35 92 jsr STASHB ; and stuff it away + 3698 5012 A9 02 lda #2 ; 2 more to get to mouse y + 3699 5014 20 01 90 jsr ADDSPC ; okay + 3700 5017 A5 CC lda MSY ; now show the world the y pos + 3701 5019 18 clc ; and center vertically too + 3702 501A 69 02 adc #CURSH/2 ; add 1/2 height + 3703 501C 20 35 92 jsr STASHB ; and it is away + 3704 501F 68 pla ; get status back + 3705 5020 A8 tay ; and set it again + 3706 5021 60 rts ; otherwise, done + 3707 5022 KEYX: + 3708 5022 AD 00 C0 lda KBD ; check keyboard strobe + 3709 5025 10 03 bpl KEYXX ; nothing + 3710 5027 8D 10 C0 sta ANYKEY ; reset strobe + 3711 502A KEYXX: + 3712 502A 60 rts + 3713 ; + 3714 ; MOVE_MC - move the mouse/joystick cursor, if necessary + 3715 ; + 3716 502B MOVE_MC: + 3717 502B A5 58 lda MOUSEF ; check which kind to move + 3718 502D 10 06 bpl MOVE_MC1 ; move joystick cursor + 3719 502F 20 41 50 jsr CHK_MOUSE ; move the mouse cursor + 3720 5032 4C 38 50 jmp MOVE_MC2 ; and print it + 3721 5035 MOVE_MC1: + 3722 5035 20 B3 50 jsr MOVE_STICK ; okay, checked it out + 3723 5038 MOVE_MC2 + 3724 5038 AD 12 03 lda MSMOVEF ; did it move? + 3725 503B F0 03 beq MOVE_MCX ; nope + 3726 503D 4C 4B 62 jmp MSCURS ; print it + 3727 5040 MOVE_MCX: + 3728 5040 60 rts ; done + 3729 ; + 3730 ; CHK_MOUSE - check the mouse position and button state, and flag any change + 3731 ; + 3732 5041 CHK_MOUSE: + 3733 5041 AD 54 C0 lda PAGE2SW ; make sure we are pointing to main bank + 3734 + 3735 5044 A2 02 ldx #READM ; get me current cursor pos + 3736 5046 20 00 03 jsr MOUSER ; turn off interrupts and set current pos + Wed May 24 1989 15:00 Page 56 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3737 + 3738 5049 AD 83 C0 lda BNK2SET ; make sure we are pointing to second bank + 3739 504C AD 83 C0 lda BNK2SET ; okay + 3740 + 3741 504F AD 78 07 MSFIX0 lda MOUSEST ; get status byte + 3742 5052 A8 tay ; save for a sec + 3743 5053 29 20 and #$20 ; moved since last time? + 3744 5055 F0 0D beq CHKM1 ; nope + 3745 5057 8D 12 03 sta MSMOVEF ; show movement + 3746 505A AD 78 04 MSFIX1 lda MOUSEXL ; get mouse X pos + 3747 505D 85 CB sta MSX ; save new one + 3748 505F AD F8 04 MSFIX2 lda MOUSEYL ; and the y pos + 3749 5062 85 CC sta MSY ; save for me + 3750 5064 CHKM1: + 3751 5064 98 tya ; get status back + 3752 5065 29 C0 and #$C0 ; is button down? + 3753 5067 F0 02 beq CHKMX ; nope + 3754 5069 A9 80 lda #$80 ; show down state + 3755 506B CHKMX: + 3756 506B 4C 25 51 jmp CHK_BTN ; check button state + 3757 ; + 3758 ; there is a mouse, so check it + 3759 ; + 3760 506E DO_MOUSE: + 3761 506E 20 41 50 jsr CHK_MOUSE ; check the mouse please + 3762 ; FALL THROUGH TO BUTTON CLICKING HANDLER + 3763 ; jmp DO_BUTTON ; handle button clicking + 3764 ; + 3765 ; DO_BUTTON - handle button clicking, working with the timer to + 3766 ; check for double clicking or not + 3767 ; + 3768 5071 DO_BUTTON: + 3769 5071 AD 12 03 lda MSMOVEF ; check moved flag + 3770 5074 F0 03 beq DOM01 ; nope + 3771 5076 20 4B 62 jsr MSCURS ; move mouse cursor + 3772 5079 DOM01: + 3773 5079 A9 00 lda #0 ; show no char + 3774 507B AC 13 03 ldy MSBTNF ; check button flag + 3775 507E 10 15 bpl DOBX ; none + 3776 ; + 3777 ; button strike, check for double click + 3778 ; + 3779 5080 8C 02 51 sty JB_STATE ; show new state + 3780 5083 A4 CA ldy CLKCTR ; have we started click counter? + 3781 5085 10 08 bpl DOB02 ; nope + 3782 5087 A0 01 ldy #1 ; this resets counter + 3783 5089 84 CA sty CLKCTR ; reset it + 3784 508B A9 82 lda #DBL_CLK ; show double click char + 3785 508D D0 14 bne DOBEXIT ; and finis + 3786 508F DOB02: + 3787 508F A0 FA ldy #-CLK_CNT ; set to double click timeout + 3788 5091 84 CA sty CLKCTR ; okay + 3789 5093 30 0E bmi DOBEXIT ;done + 3790 5095 DOBX: + 3791 5095 A4 CA ldy CLKCTR ; click counter counting? + 3792 5097 10 0A bpl DOBEXIT ; nope + 3793 5099 E6 CA inc CLKCTR ; count it then + 3794 509B D0 06 bne DOBEXIT ; all done + 3795 509D A0 01 ldy #1 ; reset counter + 3796 509F 84 CA sty CLKCTR ; okay + 3797 50A1 A9 81 lda #SGL_CLK ; set as char + 3798 50A3 DOBEXIT: + 3799 50A3 A0 00 ldy #0 ; clear out flags + 3800 50A5 8C 13 03 sty MSBTNF ; button flag + 3801 50A8 8C 12 03 sty MSMOVEF ; moved flag + 3802 50AB A8 tay ; set flag to show any char + 3803 50AC 60 rts ; return char + 3804 ; + 3805 ; DO_STICK - handle the joystick 'interrupt' + 3806 ; + 3807 50AD DO_STICK: + 3808 50AD 20 B3 50 jsr MOVE_STICK ; first move it + 3809 50B0 4C 71 50 jmp DO_BUTTON ; now handle it + 3810 50B3 MOVE_STICK: + 3811 50B3 A9 00 lda #0 ; get horizontal change + Wed May 24 1989 15:00 Page 57 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3812 50B5 20 03 51 jsr READ_STICK ; puts value in Y + 3813 50B8 C0 50 cpy #80 ; if < 80, then jump to the left + 3814 50BA B0 0D bcs DOST1 ; it is not + 3815 50BC A5 CB lda MSX ; make sure X is > 0 + 3816 50BE F0 1A beq DOST2 ; it is == 0, can't get smaller + 3817 50C0 8D 12 03 sta MSMOVEF ; show movement + 3818 50C3 C6 CB dec MSX ; move one to the left + 3819 50C5 C6 CB dec MSX ; move two to the left + 3820 50C7 D0 11 bne DOST2 ; now check vertical + 3821 50C9 DOST1: + 3822 50C9 C0 B4 cpy #180 ; if > 160, then move right + 3823 50CB 90 0D bcc DOST2 ; nope + 3824 50CD A5 CB lda MSX ; make sure X is in bounds + 3825 50CF C9 88 cmp #MAXWIDTH-4 ; don't go too far + 3826 50D1 B0 07 bcs DOST2 ; already maxxed out + 3827 50D3 8C 12 03 sty MSMOVEF ; show movement + 3828 50D6 E6 CB inc MSX ; one step to the left + 3829 50D8 E6 CB inc MSX ; and another one + 3830 50DA DOST2: + 3831 50DA A9 01 lda #1 ; now check vertical + 3832 50DC 20 03 51 jsr READ_STICK ; ask the monitor + 3833 50DF C0 50 cpy #80 ; if < 80, move up + 3834 50E1 B0 0D bcs DOST3 ; nope + 3835 50E3 A5 CC lda MSY ; don't go negative + 3836 50E5 F0 1A beq DOST4 ; already minned out + 3837 50E7 8D 12 03 sta MSMOVEF ; show movement + 3838 50EA C6 CC dec MSY ; count down + 3839 50EC C6 CC dec MSY ; twice + 3840 50EE D0 11 bne DOST4 ; all done + 3841 50F0 DOST3: + 3842 50F0 C0 B4 cpy #180 ; check for downward motion + 3843 50F2 90 0D bcc DOST4 ; none + 3844 50F4 A5 CC lda MSY ; check for maximum + 3845 50F6 C9 BD cmp #MAXHEIGHT-3 ; don't go below water + 3846 50F8 B0 07 bcs DOST4 ; gone, thanx + 3847 50FA 8C 12 03 sty MSMOVEF ; show movement + 3848 50FD E6 CC inc MSY ; go further down + 3849 50FF E6 CC inc MSY ; twice as far for joystick + 3850 5101 DOST4: + 3851 5101 60 rts ; done + 3852 ; + 3853 ; READ_STICK - read the x or y value of the stick in mind. + 3854 ; [A] == 0 or 1 - the "stick" you are interested in + 3855 ; Also, check the button status. + 3856 ; + 3857 5102 00 JB_STATE db 0 ; last state of joystick button + 3858 5103 READ_STICK: + 3859 5103 48 pha ; save which stick we want + 3860 5104 A2 E0 ldx #$E0 ; oh, pick something random + 3861 5106 READST2: + 3862 5106 20 1B 51 jsr CHECK_JOYBTN ; check the joystick button + 3863 5109 CA dex + 3864 510A D0 FA bne READST2 + 3865 510C 68 pla ; get x back + 3866 510D AA tax ; got it + 3867 510E AD 82 C0 lda RDROM ; bring ROM back + 3868 5111 20 1E FB jsr MPREAD ; NOW do the read + 3869 5114 AD 83 C0 lda BNK2SET ; back to RAM + 3870 5117 AD 83 C0 lda BNK2SET ; back to RAM + 3871 511A 60 rts + 3872 511B CHECK_JOYBTN: + 3873 511B A5 58 lda MOUSEF ; check which kind to move + 3874 511D 10 03 bpl DO_JBTN ; no joystick, check mouse + 3875 511F 4C 41 50 jmp CHK_MOUSE ; then do the mouse + 3876 5122 DO_JBTN: + 3877 5122 AD 61 C0 lda APKEY1 ; get joystick button + 3878 5125 CHK_BTN: + 3879 5125 30 03 bmi READST3 ; button down + 3880 5127 8D 02 51 sta JB_STATE ; show button went up + 3881 512A READST3: + 3882 512A 4D 02 51 eor JB_STATE ; toggle previous state + 3883 512D 8D 13 03 sta MSBTNF ; set button flag + 3884 5130 60 rts + 3885 ; ---------------------------- + 3886 ; FETCH ASCII KEYCODE INTO [A] + Wed May 24 1989 15:00 Page 58 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3887 ; ---------------------------- + 3888 ; EXIT: ASCII IN [A] & [IOCHAR] + 3889 + 3890 5131 GETKEY: + 3891 5131 A9 03 lda #BLINK_RATE ; flag as wait for good key + 3892 5133 8D 92 4F sta CURCOUNT ; clear blinker + 3893 5136 A5 58 lda MOUSEF ; is there a mouse/joystick? + 3894 5138 F0 03 beq GTK0 ; nope + 3895 513A 20 B5 62 jsr MSCON ; turn on mouse cursor + 3896 513D GTK0: + 3897 513D A9 00 lda #0 ; clear line counter + 3898 513F 85 AB sta LINCNT ; okay, we did + 3899 5141 8A txa ; SAVE [X] & [Y] + 3900 5142 48 pha + 3901 5143 98 tya + 3902 5144 48 pha + 3903 5145 GKEY0: + 3904 5145 E6 A5 inc RAND+HI ; just whack on random number + 3905 5147 C6 A4 dec RAND+LO ; and more + 3906 5149 20 E6 4F jsr FKEYX ; is there a key? + 3907 514C 30 23 bmi GKEY01 ; got the key + 3908 + 3909 514E 20 27 4F jsr WAIT10 ; wait .1 seconds, moving mouse cursor + 3910 + 3911 5151 A5 58 lda MOUSEF ; do we have a joystick/mouse? + 3912 5153 F0 0D beq GKEY02 ; nope + 3913 5155 AD A4 6C lda PTR_COUNT ; count down counter? + 3914 5158 F0 05 beq GKEY00 ; nope + 3915 515A CE A4 6C dec PTR_COUNT ; count one wait cycle + 3916 515D D0 03 bne GKEY02 ; don't check yet + 3917 515F GKEY00: + 3918 515F 20 1B 51 jsr CHECK_JOYBTN ; check the joystick button, just fur the heckuvit + 3919 5162 GKEY02: + 3920 5162 CE 92 4F dec CURCOUNT ; down one + 3921 5165 D0 DE bne GKEY0 ; no toggle + 3922 5167 20 93 4F jsr STCUR ; okay, toggle + 3923 516A A9 03 lda #BLINK_RATE ; 1 per second + 3924 516C 8D 92 4F sta CURCOUNT ; okay + 3925 516F D0 D4 bne GKEY0 ; check for key + 3926 5171 GKEY01: + 3927 5171 48 pha ; save char + 3928 5172 A5 58 lda MOUSEF ; any mouse cursor? + 3929 5174 F0 03 beq GTK1 ; nope + 3930 5176 20 56 62 jsr MSCOFF ; turn mouse cursor off + 3931 5179 GTK1: + 3932 5179 68 pla ; get char back + 3933 517A 20 BE 4F jsr ERCUR ; so erase cursor + 3934 517D CHKKEY: + 3935 517D 20 8B 51 jsr PARSEKEY ; how was the key? + 3936 5180 B0 C3 bcs GKEY0 ;TRY AGAIN + 3937 5182 85 AC sta IOCHAR ;HOLD ON TO IT + 3938 5184 68 pla ; RESTORE + 3939 5185 A8 tay ; EVERYTHING + 3940 5186 68 pla + 3941 5187 AA tax + 3942 5188 A5 AC lda IOCHAR ; GET CHAR INTO [A] + 3943 518A 60 rts ; AND RETURN IT + 3944 + 3945 ; + 3946 ; CHECK TO MAKE SURE KEY IS VALID, ONLY ACCEPT IT IF IT IS + 3947 ; + 3948 518B PARSEKEY: + 3949 518B 29 7F and #$7F ;SCREEN OUT SHIFTS + 3950 ; + 3951 ;CHECK FOR "ARROWS" & FUNCTION KEYS (X), CONVERT FOR USE (EZIP) + 3952 ;ALSO : CHANGE <_>)@%^&*( TO ,-.0256789 - and 'mouse' clicks + 3953 ; and other kinds of special chars + 3954 ; + 3955 518D GK0: + 3956 518D A2 12 ldx #ENDKEY ; GET LENGTH OF LIST + 3957 518F GK2: + 3958 518F DD D4 51 cmp HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + 3959 5192 F0 05 beq GK3 ; FOUND IT + 3960 5194 CA dex + 3961 5195 10 F8 bpl GK2 ; CHECK THEM ALL + Wed May 24 1989 15:00 Page 59 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + 3962 5197 30 05 bmi GK4 ; NOT FOUND, CONTINUE OTHER CHECKS + 3963 5199 GK3: + 3964 5199 BD E7 51 lda WANT,X ; GET KEY TO USE INSTEAD + 3965 519C 18 clc ; show niceness + 3966 519D 60 rts ; done + 3967 519E GK4: + 3968 519E C9 20 cmp #SPACE ; NO CTRL CHARS ACCEPTABLE + 3969 51A0 90 14 bcc BADKEY ; IF < SPACE, BAD + 3970 + 3971 51A2 C9 3C cmp #'<' ; pick up numbers and most punctuation + 3972 51A4 90 15 bcc OK ; we did + 3973 + 3974 51A6 C9 7B cmp #'z'+1 ;PICK OUT LETTERS NOW + 3975 51A8 B0 0C bcs BADKEY ;IF > BAD + 3976 51AA C9 61 cmp #'a' + 3977 51AC B0 0D bcs OK ;IF > OK + 3978 51AE C9 41 cmp #'A' + 3979 51B0 90 04 bcc BADKEY + 3980 51B2 C9 5B CMP #'Z'+1 + 3981 51B4 90 05 BCC OK ;IF < OK + 3982 51B6 BADKEY: + 3983 51B6 20 C3 4E jsr BEEP ;BAD KEY, GIVE WARNING NOISE, gwon back + 3984 51B9 38 sec ; show badness + 3985 51BA 60 rts ; and done + 3986 51BB OK: + 3987 51BB C9 30 cmp #'0' ; check for number keys + 3988 51BD 90 13 bcc OKj ; nope, < 0 + 3989 51BF C9 3A cmp #'9'+1 ; more than a nine? + 3990 51C1 B0 0F bcs OKj ; ayyup + 3991 ; + 3992 ; here we check for the closed apple key being down too + 3993 ; + 3994 51C3 AE 62 C0 ldx APKEY2 ; how about the closed apple key + 3995 51C6 10 0A bpl OKj ; not pressed, so use as number key + 3996 ; + 3997 ; transform number key into a function key + 3998 ; + 3999 51C8 18 CLC ; get ready for add + 4000 51C9 69 54 ADC #84 ; transforms '1'-'9' to 133-141 + 4001 51CB C9 84 CMP #132 ; but '0' wants to be a 142! + 4002 51CD D0 03 BNE OKj ; but it's not it + 4003 51CF 18 CLC ; again, don't want carry + 4004 51D0 69 0A ADC #10 ; voila! + 4005 51D2 OKj: + 4006 51D2 18 clc ; show a wicked good character is about to arrive + 4007 51D3 60 rts ; toots finis + 4008 + 4009 51D4 0B 0A 08 15 7F HAVE: DB $0B,$0A,$08,$15,$7f,ESCAPE,$3C,$7C,$3F + 51D9 1B 3C 7C 3F + 4010 51DD 3C 5F 3E 40 25 DB $3C,$5F,$3E,$40,$25,$5E,$26,$01,$02, EOL + 51E2 5E 26 01 02 0D + 4011 51E7 81 82 83 84 08 WANT: DB 129,130,131,132,08,ESCAPE,$3C,$7C,$3F + 51EC 1B 3C 7C 3F + 4012 51F0 2C 2D 2E 32 35 DB $2C,$2D,$2E,$32,$35,$36,$37,254,253, EOL + 51F5 36 37 FE FD 0D + 4013 0012 ENDKEY EQU $-WANT-1 + 4014 + 4015 51FA END + 4016 + 4017 51FA INCLUDE IO.ASM + 4018 51FA STTL "--- GAME I/O: APPLE II ---" + 4019 PAGE + Wed May 24 1989 15:00 Page 60 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4020 + 4021 ; -------------- + 4022 ; INTERNAL ERROR + 4023 ; -------------- + 4024 ; ENTRY: ERROR CODE IN [A] + 4025 ; EXIT: HA! + 4026 + 4027 51FA 0D 49 6E 74 65 ERRM: DB EOL,"Internal error " + 51FF 72 6E 61 6C 20 + 5204 65 72 72 6F 72 + 5209 20 + 4028 0010 ERRML EQU $-ERRM + 4029 + 4030 520A ZERROR: + 4031 520A 48 pha ; save err number + 4032 520B 20 A9 4C jsr SWAP2INFOW ; go to the info window (window 0)` + 4033 520E DLINE ERRM ; print message + 4034 520E A2 FA ldx #ERRM ; get other part of string + 4036 [01] IFMA 2 ; check to see if length passed in + 4037 ldy ; then just fetch it + 4038 [01] ELSE + 4039 5212 A0 10 ldy #ERRML ; get length of string + 4040 [00] ENDIF + 4041 5214 20 6B 4C jsr DLINE ; print the string + 4042 5217 .MACEND + 4043 5217 68 pla ; get error number + 4044 5218 20 D3 47 jsr HEXNUM ; print error number + 4045 521B 4C 21 52 jmp ZQUIT1 ; and die + 4046 + 4047 + 4048 ; ---- + 4049 ; QUIT + 4050 ; ---- + 4051 + 4052 521E 20 DF 54 ZQUIT: JSR ZCRLF ; FLUSH BUFFER + 4053 5221 ZQUIT1: + 4054 5221 DLINE ENDM ; print ending message + 4055 5221 A2 8C ldx #ENDM ; get other part of string + 4057 [01] IFMA 2 ; check to see if length passed in + 4058 ldy ; then just fetch it + 4059 [01] ELSE + 4060 5225 A0 10 ldy #ENDML ; get length of string + 4061 [00] ENDIF + 4062 5227 20 6B 4C jsr DLINE ; print the string + 4063 522A .MACEND + 4064 522A 20 DB 8C jsr GETRET ; wait for + 4065 522D A5 59 lda INFODOS ; in dinky-dos? + 4066 522F F0 17 beq ZQUIT2 ; nope + 4067 5231 A9 00 lda #0 ; clear power up byte + 4068 5233 8D F4 03 sta $3F4 ; make it do cold boot + 4069 5236 AD FD FF lda RESET_VECTOR+HI ; now, set up where to die to + 4070 5239 8D 47 52 sta ZQUITR1+2 + 4071 523C AD FC FF lda RESET_VECTOR+LO + 4072 523F 8D 46 52 sta ZQUITR1+1 + 4073 5242 AD 82 C0 lda RDROM ; get ROM back + 4074 5245 ZQUITR1: + 4075 5245 4C FC FF jmp RESET_VECTOR ; just reset things + 4076 ; + 4077 ; re-enable /RAM + 4078 ; + 4079 5248 ZQUIT2: + 4080 5248 AE 31 BF ldx DEVCNT ; put device in at end + 4081 524B E8 inx ; point to one past end + 4082 524C 8E 31 BF stx DEVCNT ; show new count + 4083 524F A9 BF lda #$BF ; /RAM ID + 4084 5251 9D 32 BF sta DEVNUM,X ; save it + 4085 5254 AD 7F 07 lda OLDVEC+HI ; restore old vector + 4086 5257 8D 27 BF sta RAMVEC+HI + 4087 525A AD 7E 07 lda OLDVEC+LO + 4088 525D 8D 26 BF sta RAMVEC+LO + 4089 ; + 4090 ; now format /RAM + 4091 ; + Wed May 24 1989 15:00 Page 61 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4092 5260 A9 03 lda #3 ; stash into FORMAT parm block + 4093 5262 85 42 sta $42 ; it goes here, oddly enough + 4094 5264 A9 B0 lda #$B0 ; device id for /RAM + 4095 5266 85 43 sta $43 ; and here it goes + 4096 5268 A9 11 lda #>GAME1FIO ; IO buffer + 4097 526A 85 45 sta $45 ; this is where it goes + 4098 526C A9 00 lda #BOOTNAME + 4142 52C2 8D D8 45 sta OPEN_FILE+OP_PATHNAME+HI + 4143 52C5 A9 31 lda #'1' ; set disk name to disk #1 + 4144 52C7 8D C5 49 sta SAVENUM ; show open_gamef + 4145 52CA 20 22 4B jsr OPEN_GAMEF ; okay + 4146 + 4147 52CD AD DB 45 lda OPEN_FILE+OP_REFNUM ; get ref num + 4148 52D0 8D 9D 52 sta BOOT_RD+RD_REFNUM ; save ref num + 4149 52D3 8D 07 8B sta CLOSE_PB+CL_REFNUM + 4150 52D6 READ BOOT_RD ; read in boot system + 4151 52D6 PRODOS $CA, BOOT_RD + 4152 52D6 20 00 BF jsr $BF00 ; ProDOS handler + 4153 52D9 CA DB $CA ; ProDOS function code + 4154 52DA 9C52 DW BOOT_RD ; Function Parameter Block address + 4155 52DC .MACEND + 4156 52DC .MACEND + 4157 52DC 90 03 bcc ZSTRTX ; okay, everything is fine + 4158 52DE 4C 74 47 jmp DISK_FATAL ; die otherwise + 4159 52E1 ZSTRTX: + 4160 52E1 CLOSE CLOSE_PB ; and close it up + Wed May 24 1989 15:00 Page 62 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4161 52E1 PRODOS $CC, CLOSE_PB + 4162 52E1 20 00 BF jsr $BF00 ; ProDOS handler + 4163 52E4 CC DB $CC ; ProDOS function code + 4164 52E5 068B DW CLOSE_PB ; Function Parameter Block address + 4165 52E7 .MACEND + 4166 52E7 .MACEND + 4167 52E7 4C 00 20 jmp BORG ; and go to it + 4168 52EA + 4169 ; -------------------------------- + 4170 ; RETURN RANDOM BYTES IN [A] & [X] + 4171 ; -------------------------------- + 4172 52EA RANDOM: + 4173 52EA E6 A5 inc RAND+HI + 4174 52EC C6 A4 dec RAND+LO + 4175 52EE A5 A4 lda RAND+LO ; get LSB + 4176 52F0 65 A5 adc RAND+HI ; add MSB + 4177 52F2 29 7F and #$7F ; don't let it go into $C0 page + 4178 52F4 85 A5 sta RAND+HI ; new MSB + 4179 52F6 A8 tay ; get random offset + 4180 52F7 B1 A4 lda (RAND),Y ; get random number + 4181 52F9 AA tax ; save in X + 4182 52FA 65 A4 adc RAND+LO ; and go to another spot + 4183 52FC 29 7F and #$7F ; don't go above $80 + 4184 52FE 85 A5 sta RAND+HI ; okay + 4185 5300 A8 tay ; more randomness + 4186 5301 B1 A4 lda (RAND),Y ; and get it again + 4187 5303 05 A5 ora RAND+HI ; set more bits + 4188 5305 60 rts + 4189 + 4190 + 4191 ; ------------------- + 4192 ; Z-PRINT A CHARACTER + 4193 ; ------------------- + 4194 ; ENTRY: ASCII CHAR IN [A] + 4195 ; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, + 4196 ; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN + 4197 ; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME + 4198 ; (DIROUT CHANGES 6/24/85) + 4199 + 4200 5306 COUT: + 4201 5306 85 AC sta IOCHAR ; HOLD IT A SEC + 4202 5308 A6 B2 ldx TABLEF ; OUTPUT TO TABLE? + 4203 530A F0 07 beq COUT1 ; NO + 4204 530C A6 19 ldx FMTTBL ; formatted table? + 4205 530E D0 0D bne COUT5 ; yes, so just do it normal + 4206 5310 4C 86 53 jmp TBLOUT ; just put into table + 4207 5313 COUT1: + 4208 5313 A6 B1 ldx SCREENF ; OUTPUT TO SCREEN? + 4209 5315 D0 06 bne COUT5 ; YES + 4210 5317 AE 73 6C ldx SCRIPTF ; OUTPUT TO PRINTER? + 4211 531A D0 01 bne COUT5 ; YES + 4212 531C 60 rts ; NO, SO DONE + 4213 531D COUT5: + 4214 531D A5 AC lda IOCHAR ; RETRIEVE CHAR + 4215 531F 30 5B bmi COUT2 ; highlight chars have no width + 4216 ; + 4217 ; this is an entry point for DLINE, so it doesn't check any of the above + 4218 ; things. Enter with character in [A] + 4219 ; + 4220 5321 DIRECT_OUT: + 4221 5321 C9 0D cmp #EOL ; IF ASCII EOL, just handle it special + 4222 5323 D0 03 bne COUT0 + 4223 + 4224 5325 4C DF 54 jmp ZCRLF ; DO IT + 4225 5328 COUT0: + 4226 5328 B0 20 bcs COUT02 ; not control character + 4227 532A C9 0B cmp #EOS ; control-k (end of sentence)? + 4228 532C F0 0E beq COUT01 ; yes, so put out 2 spaces + 4229 532E C9 09 cmp #TAB ; tab char? + 4230 5330 D0 53 bne CEX ; ignore all other control chars + 4231 ; + 4232 ; this means do a couple of spaces + 4233 ; + 4234 5332 A9 20 lda #SPACE ; do 3 spaces for start of line + 4235 5334 20 06 53 jsr COUT ; a little recursion never hurt! + Wed May 24 1989 15:00 Page 63 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4236 5337 A6 A9 ldx CHRCNT ; back to beginning of line? + 4237 5339 D0 01 bne COUT01 ; nope + 4238 533B COUT010: + 4239 533B 60 rts ; don't do any to start line + 4240 533C COUT01: + 4241 533C A9 20 lda #SPACE ; 2 more spaces + 4242 533E 20 06 53 jsr COUT + 4243 5341 A6 A9 ldx CHRCNT ; back to zero? + 4244 5343 F0 F6 beq COUT010 ; yes, so don't add to start of line + 4245 + 4246 5345 A9 20 lda #SPACE ; last one + 4247 5347 4C 06 53 jmp COUT ; finally + 4248 534A COUT02: + 4249 534A AA tax ; use char as index + 4250 534B A5 C1 lda FONTFLG ; get which font we be using + 4251 534D F0 04 beq COUTF1 ; must be variable width + 4252 534F A9 0C lda #MONOFONT_W ; get width then of mono font + 4253 5351 D0 03 bne COUTF2 ; okay, now do add + 4254 5353 COUTF1: + 4255 5353 BD 25 64 lda CHWID,X ; get width of char + 4256 5356 COUTF2: + 4257 5356 18 clc ; get ready for add + 4258 5357 65 A7 adc LENGTH+LO ; ADD LINE LENGTH COUNTER + 4259 5359 85 A7 sta LENGTH+LO ; update length + 4260 535B 90 02 bcc COUT0C ; no wrap + 4261 535D E6 A8 inc LENGTH+HI ; okay, wrap then + 4262 535F COUT0C: + 4263 535F A5 A8 lda LENGTH+HI ; get MSB + 4264 5361 C5 A3 cmp XSIZE+HI ; check MSB first + 4265 5363 90 17 bcc COUT2 ; no need to check lsb + 4266 5365 D0 06 bne COUT00 ; XSIZE < LENGTH? + 4267 5367 + 4268 5367 A5 A7 lda LENGTH+LO ; check LSB + 4269 5369 C5 A2 cmp XSIZE+LO ; END OF SCREEN LINE? + 4270 536B 90 0F bcc COUT2 ; haven't reached the end if XSIZE > LENGTH + 4271 536D COUT00: + 4272 536D AC D6 71 ldy WRPFLG ; are we wrapping + 4273 5370 F0 13 beq CEX ; no, so truncate + 4274 5372 A6 A9 ldx CHRCNT ; get character count + 4275 5374 A5 AC lda IOCHAR ; get the character + 4276 5376 9D 00 02 sta LBUFF,X ; save current char in buffer + 4277 5379 4C 6B 54 jmp FLUSH ; YES, FLUSH THE LINE + 4278 537C COUT2: + 4279 537C A6 A9 ldx CHRCNT ; GET LINE POINTER + 4280 537E A5 AC lda IOCHAR ; get char back + 4281 5380 9D 00 02 sta LBUFF,X ; ADD CHAR TO BUFFER + 4282 5383 E6 A9 inc CHRCNT ; and point to next CHRCNT + 4283 5385 CEX: + 4284 5385 60 rts + 4285 5386 + 4286 ; --------------- + 4287 ; OUTPUT TO TABLE + 4288 ; --------------- + 4289 ; + 4290 ; this one just puts a char into the table + 4291 ; + 4292 5386 TBLOUT: + 4293 5386 AA tax ; HOLD CHAR A SEC. + 4294 ; + 4295 ; figger out length of line in there + 4296 ; + 4297 5387 A5 C1 lda FONTFLG ; get which font we be using + 4298 5389 F0 04 beq TBLOUT1 ; must be variable width + 4299 538B A9 0C lda #MONOFONT_W ; get width then of mono font + 4300 538D D0 03 bne TBLOUT2 ; okay, now do add + 4301 538F TBLOUT1: + 4302 538F BD 25 64 lda CHWID,X ; get width of char + 4303 5392 TBLOUT2: + 4304 5392 18 clc ; add width + 4305 5393 6D 31 96 adc ZBEGIN+ZTWIDTH+1 ; to current line width + 4306 5396 8D 31 96 sta ZBEGIN+ZTWIDTH+1 ; save current width + 4307 5399 90 03 bcc TBLOUT3 ; no wrap + 4308 539B EE 30 96 inc ZBEGIN+ZTWIDTH+0 ; wrap, then dammit + 4309 539E TBLOUT3: + 4310 ; + Wed May 24 1989 15:00 Page 64 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4311 ; PUT BYTE IN TABLE AT CURRENT OFFSET + 4312 ; + 4313 539E AD 80 6C lda DIRITM+LO ; ADD IN OFFSET + 4314 53A1 18 clc + 4315 53A2 65 A0 adc DIRTBL+LO + 4316 53A4 85 8F sta SPCL ; and make it lo part + 4317 53A6 AD 81 6C lda DIRITM+HI + 4318 53A9 65 A1 adc DIRTBL+HI + 4319 53AB 20 77 8F jsr SETPC ; set the PC + 4320 53AE 85 90 sta SPCH ; and this is high part + 4321 53B0 84 91 sty SPCBNK ; and the bank + 4322 53B2 8A txa ; PICK UP ASCII CHAR + 4323 53B3 20 35 92 jsr STASHB ; and save it + 4324 ; + 4325 ; SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER + 4326 ; + 4327 53B6 EE 80 6C inc DIRITM+LO ; INC OFFSET TO NEXT BYTE + 4328 53B9 D0 03 bne TBLRTS + 4329 53BB EE 81 6C inc DIRITM+HI + 4330 53BE TBLRTS: + 4331 53BE 60 rts + 4332 ; + 4333 ; PUT LBUFF IN TABLE AT CURRENT OFFSET + 4334 ; + 4335 53BF TBLRTN: + 4336 53BF AD 80 6C lda DIRITM+LO ; get where we are + 4337 53C2 18 clc + 4338 53C3 65 A0 adc DIRTBL+LO ; ADD IN OFFSET + 4339 53C5 85 8F sta SPCL ; and make it lo part + 4340 53C7 85 8C sta FPCL ; save for later usage + 4341 53C9 AD 81 6C lda DIRITM+HI ; get hi part + 4342 53CC 65 A1 adc DIRTBL+HI + 4343 53CE 20 77 8F jsr SETPC ; set the PC + 4344 53D1 85 90 sta SPCH ; and this is high part + 4345 53D3 85 8D sta FPCH ; saving + 4346 53D5 84 91 sty SPCBNK ; and the bank + 4347 53D7 84 8E sty FPCBNK ; and here too + 4348 53D9 A9 00 lda #0 ; start counter off at zero + 4349 53DB 85 7A sta J ; use J + 4350 53DD 85 7D sta K+HI ; this will be line length + 4351 53DF 85 7C sta K+LO ; both parts, please + 4352 53E1 20 9E 8F jsr NEXTSPC ; point past the counter + 4353 53E4 TBLOOP: + 4354 53E4 A4 7A ldy J ; get offset + 4355 53E6 B9 00 02 lda LBUFF,Y ; get char + 4356 53E9 AA tax ; save char + 4357 53EA 30 19 bmi TBLP1 ; don't count hi light chars + 4358 53EC C9 20 cmp #SPACE ; see if less than a space + 4359 53EE 90 15 bcc TBLP1 ; no width if <$20 + 4360 53F0 AA tax ; use char as index + 4361 + 4362 53F1 A5 C1 lda FONTFLG ; get which font we be using + 4363 53F3 F0 04 beq TBLF1 ; must be variable width + 4364 53F5 A9 0C lda #MONOFONT_W ; get width then of mono font + 4365 53F7 D0 03 bne TBLF2 ; okay, now do add + 4366 53F9 TBLF1: + 4367 53F9 BD 25 64 lda CHWID,X ; get width of char + 4368 53FC TBLF2: + 4369 53FC 18 clc ; add width + 4370 53FD 65 7C adc K+LO ; to current line width + 4371 53FF 85 7C sta K+LO ; save current width + 4372 5401 90 02 bcc TBLP1 ; no wrap + 4373 5403 E6 7D inc K+HI ; wrap, then dammit + 4374 5405 TBLP1: + 4375 5405 8A txa ; get char back + 4376 5406 20 35 92 jsr STASHB ; and save it + 4377 5409 20 9E 8F jsr NEXTSPC ; next table entry + 4378 540C E6 7A inc J ; point to next char + 4379 540E C6 A9 dec CHRCNT ; decrement counter + 4380 5410 D0 D2 bne TBLOOP ; get next one + 4381 ; + 4382 ; now fill with necessary spaces + 4383 ; + 4384 5412 A5 C1 lda FONTFLG ; first, set up width to be added + 4385 5414 F0 04 beq TBLSPF1 ; must be variable width font + Wed May 24 1989 15:00 Page 65 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4386 5416 A9 0C lda #MONOFONT_W ; get mono width + 4387 5418 D0 05 bne TBLSPF2 ; okay + 4388 541A TBLSPF1: + 4389 541A A2 20 ldx #SPACE ; get space index + 4390 541C BD 25 64 lda CHWID,X ; okay + 4391 541F TBLSPF2: + 4392 541F 85 71 sta ARG8 ; use temporarily + 4393 5421 TBLSP: + 4394 5421 A5 7C lda K+LO ; get how big line is + 4395 5423 18 clc ; add in space + 4396 5424 65 71 adc ARG8 ; pick up space width + 4397 5426 85 7C sta K+LO ; saved + 4398 5428 90 02 bcc TBLSP1 ; no wrap? + 4399 542A E6 7D inc K+HI ; yes, wrapping + 4400 542C TBLSP1: + 4401 542C A5 A3 lda XSIZE+HI ; check against end + 4402 542E C5 7D cmp K+HI ; compare against max width + 4403 5430 90 14 bcc TBLSPX ; all done then + 4404 5432 D0 06 bne TBLSP2 ; no need to check if <> + 4405 5434 A5 A2 lda XSIZE+LO ; check LSB + 4406 5436 C5 7C cmp K+LO ; well? + 4407 5438 90 0C bcc TBLSPX ; all done then + 4408 543A TBLSP2: + 4409 543A A9 20 lda #SPACE ; get it + 4410 543C 20 35 92 jsr STASHB ; save it + 4411 543F 20 9E 8F jsr NEXTSPC ; point to next one + 4412 5442 E6 7A inc J ; count it + 4413 5444 D0 DB bne TBLSP ; and continue + 4414 5446 TBLSPX: + 4415 5446 A9 00 lda #0 ; show end of table + 4416 5448 85 A7 sta LENGTH+LO ; clear out line length too + 4417 544A 85 A8 sta LENGTH+HI ; and hi part too + 4418 544C 20 35 92 jsr STASHB ; marked with a zero + 4419 544F 20 73 90 jsr FP2SP ; have SPC point to beginning + 4420 5452 A5 7A lda J ; get how many chars are there + 4421 5454 20 35 92 jsr STASHB ; save at beginning of line + 4422 5457 E6 7A inc J ; count counter in offset + 4423 5459 A5 7A lda J ; get J back + 4424 545B 18 clc ; add in where we were + 4425 545C 6D 80 6C adc DIRITM+LO ; okay with lo part + 4426 545F 8D 80 6C sta DIRITM+LO ; save it + 4427 5462 AD 81 6C lda DIRITM+HI ; and now the hi part + 4428 5465 69 00 adc #0 ; pick up carry, maybe + 4429 5467 8D 81 6C sta DIRITM+HI ; and save it + 4430 546A 60 rts + 4431 + 4432 ; ------------------- + 4433 ; FLUSH OUTPUT BUFFER + 4434 ; ------------------- + 4435 ; ENTRY: LENGTH OF BUFFER IN [X] + 4436 + 4437 546B FLUSH: + 4438 546B A9 20 lda #SPACE ; SPACE CHAR + 4439 546D 8E 63 6C stx OLDEND ; SAVE CURRENT END OF LINE + 4440 5470 FL0: + 4441 5470 DD 00 02 cmp LBUFF,X ; FIND LAST SPACE CHAR + 4442 5473 F0 06 beq FL1 ; IN THE LINE + 4443 5475 CA dex + 4444 5476 D0 F8 bne FL0 ; IF NONE FOUND, + 4445 5478 A6 A9 ldx CHRCNT ; FLUSH ENTIRE LINE + 4446 547A CA dex ; minus last one + 4447 547B FL1: + 4448 547B 8E 62 6C stx OLDLEN ; SAVE OLD LINE POS HERE + 4449 547E 86 A9 stx CHRCNT ; MAKE IT THE NEW LINE LENGTH + 4450 5480 + 4451 5480 A5 B2 lda TABLEF ; are we doing table I/O? + 4452 5482 F0 06 beq FL11 ; nope + 4453 5484 20 BF 53 jsr TBLRTN ; YES, DO IT + 4454 5487 4C 8D 54 jmp FL12 ; so refill line + 4455 548A FL11: + 4456 548A 20 DF 54 jsr ZCRLF ; PRINT LINE UP TO LAST SPACE + 4457 ; + 4458 ; START NEW LINE WITH REMAINDER OF OLD + 4459 ; + 4460 548D FL12: + Wed May 24 1989 15:00 Page 66 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4461 548D AE 62 6C ldx OLDLEN ; GET OLD LINE POS + 4462 5490 A0 00 ldy #0 ; START NEW LINE AT BEGINNING + 4463 5492 FL2: + 4464 5492 E8 inx + 4465 5493 EC 63 6C cpx OLDEND ; CONTINUE IF + 4466 5496 90 05 bcc FL3 ; INSIDE of end of line + 4467 5498 F0 03 beq FL3 ; or at end of line + 4468 549A 84 A9 sty CHRCNT + 4469 549C 60 rts + 4470 549D FL3: + 4471 549D BD 00 02 lda LBUFF,X ; GET CHAR FROM OLD LINE + 4472 54A0 C9 20 cmp #SPACE ; don't move start spaces in either + 4473 54A2 F0 25 beq FL4 ; fine, I won't + 4474 54A4 99 00 02 sta LBUFF,Y ; MOVE TO START OF NEW LINE + 4475 54A7 30 20 bmi FL4 ; don't count hi light chars + 4476 54A9 C9 20 cmp #SPACE ; don't count control chars + 4477 54AB 90 1C bcc FL4 ; okay + 4478 54AD 8A txa ; save current x + 4479 54AE 48 pha ; saved + 4480 54AF A5 C1 lda FONTFLG ; get which font we be using + 4481 54B1 F0 04 beq FLSF1 ; must be variable width + 4482 54B3 A9 0C lda #MONOFONT_W ; get width then of mono font + 4483 54B5 D0 07 bne FLSF2 ; okay, now do add + 4484 54B7 FLSF1: + 4485 54B7 BD 00 02 lda LBUFF,X ; get char back + 4486 54BA AA tax ; make index + 4487 54BB BD 25 64 lda CHWID,X ; get width of char + 4488 54BE FLSF2: + 4489 54BE 18 clc ; get ready for add + 4490 54BF 65 A7 adc LENGTH+LO ; okay, now add char width + 4491 54C1 85 A7 sta LENGTH+LO ; save new length + 4492 54C3 68 pla ; get old X back + 4493 54C4 AA tax ; okay + 4494 54C5 90 02 bcc FL4 ; no wrap + 4495 54C7 E6 A8 inc LENGTH+HI + 4496 54C9 FL4: + 4497 54C9 C8 iny ; UPDATE # OF chars in NEW LINE + 4498 54CA D0 C6 bne FL2 ; (ALWAYS) + 4499 + 4500 + 4501 ; --------------- + 4502 ; CARRIAGE RETURN + 4503 ; --------------- + 4504 + 4505 54CC ZZCRLF: + 4506 54CC A6 B2 ldx TABLEF ; OUTPUT TO TABLE? + 4507 54CE F0 0F beq ZCRLF ; NO + 4508 ; + 4509 ; if putting a into table, just add to line buffer and flush + 4510 ; + 4511 54D0 A9 0D lda #EOL ; get carriage return char + 4512 54D2 A4 A9 ldy CHRCNT ; add to lbuff + 4513 54D4 99 00 02 sta LBUFF,Y ; got it + 4514 54D7 E6 A9 inc CHRCNT ; now flush it + 4515 54D9 20 BF 53 jsr TBLRTN ; YES, DO IT (TBL ONLY) + 4516 54DC 4C 55 55 jmp ZCRLFX ; git out + 4517 54DF ZCRLF: + 4518 54DF A6 A9 ldx CHRCNT ; how far have we gone + 4519 54E1 A9 0D lda #EOL ; get carriage return char + 4520 54E3 9D 00 02 sta LBUFF,X ; END OF CURRENT LINE + 4521 54E6 E6 A9 inc CHRCNT ; UPDATE LINE LENGTH + 4522 54E8 20 5E 55 jsr LINOUT ; DISPLAY LINE + 4523 + 4524 ; + 4525 ; now check about line count + 4526 ; + 4527 54EB A9 00 lda #0 + 4528 54ED 85 A9 sta CHRCNT ; AND RESET LINE COUNT + 4529 54EF 85 A7 sta LENGTH+LO ; okay + 4530 54F1 85 A8 sta LENGTH+HI ; okay + 4531 + 4532 54F3 20 7C 55 jsr CHKFNC ; CHECK FOR CR FUNCTION (XZIP) + 4533 + 4534 54F6 A5 B1 lda SCREENF ; CHECK IF DISPLAYING TO SCREEN + 4535 54F8 F0 5B beq ZCRLFX ; NO, GO HANDLE IF PRINTING + Wed May 24 1989 15:00 Page 67 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4536 54FA AD D7 71 lda SCRLFLG ; is it a scrolling window? + 4537 54FD F0 56 beq ZCRLFX ; nope, so no more + 4538 54FF E6 AB inc LINCNT ; NEW LINE GOING OUT + 4539 + 4540 5501 A6 AB ldx LINCNT ; IS IT TIME TO + 4541 5503 E4 03 cpx MAXLINES ; PRINT "MORE" YET? + 4542 5505 90 4E bcc ZCRLFX ; NO, CONTINUE + 4543 + 4544 5507 A9 01 lda #1 ; leave one line from last screen, and input line + 4545 5509 85 AB sta LINCNT ; RESET LINE COUNTER + 4546 550B A5 04 lda LEFTMRG ; SET LEFT MARGIN + 4547 550D 85 00 sta SCRCX + 4548 550F A9 01 lda #1 ; show cursor changed (maybe) + 4549 5511 8D 77 6C sta CURSFLG ; okay + 4550 ; + 4551 ; print [MORE] out myself, to avoid re-entrancy problems + 4552 ; + 4553 5514 AD 73 6C lda SCRIPTF ; make sure we don't script + 4554 5517 48 pha + 4555 5518 A2 00 ldx #0 ; start with first char + 4556 551A 8E 73 6C stx SCRIPTF ; clear script flag + 4557 551D 86 18 stx SCLLINES ; use this as a counter + 4558 551F MORELOOP: + 4559 551F BD 66 5B lda MORE,X ; get char + 4560 5522 85 AC sta IOCHAR ; save it + 4561 5524 20 21 53 jsr DIRECT_OUT ; pump it out there + 4562 5527 E6 18 inc SCLLINES ; count char + 4563 5529 A6 18 ldx SCLLINES ; how many have we done + 4564 552B E0 06 cpx #MOREL ; done? + 4565 552D D0 F0 bne MORELOOP ; nope + 4566 + 4567 552F 20 AD 55 jsr CLRBUF ; make sure it shows + 4568 5532 WAIT: + 4569 5532 20 31 51 jsr GETKEY ; wait for key please + 4570 5535 A9 05 lda #MOREL-1 ; how many backspaces + 4571 5537 85 A7 sta LENGTH ; just use this as counter + 4572 5539 WM11: + 4573 5539 A6 A7 ldx LENGTH ; which char? + 4574 553B BD 66 5B lda MORE,X ; get char + 4575 553E AA tax ; put here for erase + 4576 553F A9 08 lda #BACKSPACE ; erase char + 4577 5541 20 7D 5D jsr CHAR + 4578 5544 C6 A7 dec LENGTH ; count it + 4579 5546 10 F1 bpl WM11 + 4580 5548 68 pla ; get script flag back + 4581 5549 8D 73 6C sta SCRIPTF ; fine + 4582 554C A5 04 lda LEFTMRG ; move back to left margin + 4583 554E 85 00 sta SCRCX ; okay + 4584 5550 A9 01 lda #1 ; show cursor changed (maybe) + 4585 5552 8D 77 6C sta CURSFLG ; okay + 4586 5555 ZCRLFX: + 4587 5555 A9 00 lda #0 + 4588 5557 85 A9 sta CHRCNT ; AND RESET LINE COUNT + 4589 5559 85 A7 sta LENGTH+LO ; okay + 4590 555B 85 A8 sta LENGTH+HI + 4591 555D 60 rts + 4592 555E LINOUT: + 4593 555E A4 A9 ldy CHRCNT ; IF BUFFER EMPTY, + 4594 5560 F0 19 beq LINEX ; DON'T PRINT ANYTHING + 4595 5562 8C 69 6C sty PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + 4596 5565 A5 B1 lda SCREENF ; DISPLAY TO SCREEN? + 4597 5567 F0 0F beq LOUT1 ; NO, GO CHECK IF PRINT + 4598 5569 A2 00 ldx #0 ; SEND CONTENTS OF [LBUFF] + 4599 556B LOUT: + 4600 556B BD 00 02 lda LBUFF,X ; TO SCREEN + 4601 556E 20 7D 5D jsr CHAR + 4602 5571 E8 inx + 4603 5572 88 dey + 4604 5573 D0 F6 bne LOUT + 4605 5575 20 EC 71 jsr DISP_LINE ; make sure line gets printed + 4606 5578 20 DF 4C LOUT1: JSR PPRINT ; PRINT [LBUFF] IF ENABLED + 4607 557B LINEX: + 4608 557B 60 rts ; AND RETURN + 4609 ; + 4610 ; CHECK IF THERE IS A PENDING FUNCTION CALL ASSOCIATED WITH 'S + Wed May 24 1989 15:00 Page 68 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4611 ; + 4612 557C CHKFNC: + 4613 557C A0 0B ldy #WINCRC+HI ; get function offset + 4614 557E B1 05 lda (WINDOW),Y ; IF NULL IGNORE + 4615 5580 88 dey ; point to lo part + 4616 5581 11 05 ora (WINDOW),Y + 4617 5583 F0 26 beq CHKOUT + 4618 + 4619 5585 AD A3 6C lda CRLF_CHECK ; do we really want to do this? + 4620 5588 F0 21 beq CHKOUT ; nope + 4621 + 4622 558A B1 05 lda (WINDOW),Y ; DECR COUNTER + 4623 558C 38 sec + 4624 558D E9 01 sbc #1 + 4625 558F 91 05 sta (WINDOW),Y + 4626 5591 C8 iny + 4627 5592 B1 05 lda (WINDOW),Y ; work on hi part + 4628 5594 E9 00 sbc #0 ; pick up carry + 4629 5596 91 05 sta (WINDOW),Y ; save it + 4630 5598 88 dey + 4631 5599 11 05 ora (WINDOW),Y ; if NULL NOW, CALL FCN + 4632 559B D0 0E bne CHKOUT + 4633 + 4634 559D A0 08 ldy #WINCRF+LO ; pointing to routine + 4635 559F B1 05 lda (WINDOW),Y ; get lo part + 4636 55A1 85 7A sta J+LO ; and save in J + 4637 55A3 C8 iny ; point to hi part + 4638 55A4 B1 05 lda (WINDOW),Y ; got it + 4639 55A6 85 7B sta J+HI + 4640 55A8 20 13 5B jsr INTCLL ; DO FUNCTION CALL + 4641 55AB CHKOUT: + 4642 55AB 60 rts + 4643 + 4644 + 4645 ; ---------------------- + 4646 ; UPDATE THE STATUS LINE + 4647 ; ---------------------- + 4648 ; NOT APPLICABLE IN EZIP. + 4649 + 4650 55AC 60 ZUSL: RTS + 4651 + 4652 ; ------ + 4653 ; BUFOUT + 4654 ; ------ + 4655 ; ENTER: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE + 4656 ; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO + 4657 ; + 4658 ; shouldn't need this in YZIP ?! + 4659 ; + 4660 55AD ZBUFOUT: + 4661 ; + 4662 ; CLEAR OUTPUT BUFFER BEFORE DOING ANYTHING FANCY + 4663 ; + 4664 55AD CLRBUF: + 4665 55AD 20 5E 55 jsr LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) + 4666 55B0 A2 00 ldx #0 + 4667 55B2 86 A9 stx CHRCNT + 4668 55B4 60 rts + 4669 + 4670 ; ------ + 4671 ; DIROUT + 4672 ; ------ + 4673 ; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT + 4674 ; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT + 4675 ; MULTIPLE DEVICE USAGE IS POSSIBLE. + 4676 + 4677 55B5 00 00 SAVEXSIZE: db 0,0 ; for formatted table saving + 4678 + 4679 55B7 ZDIRT: + 4680 55B7 20 AD 55 jsr CLRBUF ; send out anything there now! + 4681 + 4682 55BA A6 63 ldx ARG1+LO + 4683 55BC 30 0A bmi DIRRES ; NEGATIVE VALUE, DESELECTING + 4684 55BE CA dex + 4685 55BF F0 11 beq DIR1 ; 1 = SET OUTPUT TO SCREEN + Wed May 24 1989 15:00 Page 69 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4686 55C1 CA dex + 4687 55C2 F0 1E beq DIR2 ; 2 = SCRIPTING + 4688 55C4 CA dex + 4689 55C5 F0 3C beq DIR3 ; 3 = TABLE + 4690 55C7 60 rts ; INVALID VALUE + 4691 55C8 DIRRES: + 4692 55C8 E8 inx + 4693 55C9 F0 0F beq DRES1 ; -1 = RESET TO SCREEN + 4694 55CB E8 inx + 4695 55CC F0 29 beq DRES2 + 4696 55CE E8 inx + 4697 55CF F0 3A beq DRES3 + 4698 55D1 60 rts ; INVALID VALUE, JUST LEAVE + 4699 55D2 DIR1: + 4700 55D2 20 AD 55 jsr CLRBUF + 4701 55D5 A9 01 lda #1 ; turn screen on + 4702 55D7 85 B1 sta SCREENF + 4703 55D9 60 rts + 4704 55DA DRES1: + 4705 55DA 20 AD 55 jsr CLRBUF + 4706 55DD A9 00 lda #0 + 4707 55DF 85 B1 sta SCREENF ; 0, TURN SCREEN OFF + 4708 55E1 60 rts + 4709 55E2 DIR2: + 4710 55E2 E8 inx + 4711 55E3 8E 73 6C stx SCRIPTF ; SET SCRIPT FLAG ON + 4712 55E6 AD 11 96 lda ZBEGIN+ZFLAGS+1 ; SET GAME FLAG ALSO + 4713 55E9 09 01 ora #%00000001 + 4714 55EB 8D 11 96 sta ZBEGIN+ZFLAGS+1 + 4715 55EE AD 1B 4D lda PSTAT ; CHECK IF PRINTER ALREADY INIT'D + 4716 55F1 D0 03 bne DIR2A + 4717 55F3 20 31 4D jsr PCHK ; NO, GO DO IT + 4718 55F6 DIR2A: + 4719 55F6 60 rts ; YES, READY TO LEAVE + 4720 55F7 DRES2: + 4721 55F7 8E 73 6C stx SCRIPTF ; TURN PRINTER OFF + 4722 55FA AD 11 96 lda ZBEGIN+ZFLAGS+1 ; AND TURN OFF GAME FLAG TOO + 4723 55FD 29 FE and #%11111110 + 4724 55FF 8D 11 96 sta ZBEGIN+ZFLAGS+1 + 4725 5602 60 rts + 4726 5603 DIR3: + 4727 5603 86 B1 stx SCREENF ; turn off screen + 4728 5605 E8 inx + 4729 5606 86 B2 stx TABLEF ; TURN TABLE OUTPUT FLAG ON + 4730 5608 4C 73 56 jmp START_TABLE ; and set things up + 4731 560B DRES3: + 4732 560B A5 B2 lda TABLEF ; IF OFF ALREADY + 4733 560D F0 63 beq OUT3 ; LEAVE AS IS + 4734 + 4735 560F 86 B2 stx TABLEF ; TURN TBL OUTPUT OFF + 4736 5611 E8 inx ; turn screen back on + 4737 5612 86 B1 stx SCREENF ; screen back on + 4738 + 4739 5614 A9 03 lda #3 ; add three to make it wrap + 4740 5616 18 clc ; ready for add + 4741 5617 6D 31 96 adc ZBEGIN+ZTWIDTH+1 ; do it + 4742 561A 8D 31 96 sta ZBEGIN+ZTWIDTH+1 + 4743 561D 90 03 bcc DRESCC ; no wrap into MSB + 4744 561F EE 30 96 inc ZBEGIN+ZTWIDTH + 4745 5622 DRESCC: + 4746 5622 4E 30 96 lsr ZBEGIN+ZTWIDTH+0 ; /4 to get # of pixels + 4747 5625 6E 31 96 ror ZBEGIN+ZTWIDTH+1 + 4748 5628 4E 30 96 lsr ZBEGIN+ZTWIDTH+0 + 4749 562B 6E 31 96 ror ZBEGIN+ZTWIDTH+1 + 4750 + 4751 + 4752 562E A5 19 lda FMTTBL ; did we do a formatted table? + 4753 5630 D0 2B bne DRESFT ; yes, so fix things + 4754 ; + 4755 ; now put count into table + 4756 ; + 4757 5632 A5 A0 lda DIRTBL+LO ; and put count into second byte of table + 4758 5634 85 8F sta SPCL ; points to low par + 4759 5636 A5 A1 lda DIRTBL+HI ; get page + 4760 5638 20 77 8F jsr SETPC ; okay, page and bank + Wed May 24 1989 15:00 Page 70 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4761 563B 85 90 sta SPCH + 4762 563D 84 91 sty SPCBNK + 4763 563F AD 80 6C lda DIRITM+LO ; (2 LESS THAN [DIRITM]) + 4764 5642 38 sec + 4765 5643 E9 02 sbc #2 + 4766 5645 8D 80 6C sta DIRITM+LO ; save this new count + 4767 5648 B0 03 bcs RESET0 + 4768 564A CE 81 6C dec DIRITM+HI ; wrapped downwards + 4769 564D RESET0: + 4770 564D AD 81 6C lda DIRITM+HI ; get hi part + 4771 5650 20 35 92 jsr STASHB ; saved that count + 4772 5653 20 9E 8F jsr NEXTSPC ; and point to lo part + 4773 5656 AD 80 6C lda DIRITM+LO ; and get lo part + 4774 5659 20 35 92 jsr STASHB ; and save it + 4775 565C 60 rts ; done + 4776 565D DRESFT: + 4777 565D A5 A9 lda CHRCNT ; anything in buffer? + 4778 565F F0 03 beq DRES31 ; nope + 4779 5661 20 BF 53 jsr TBLRTN ; then fill out last line + 4780 5664 DRES31: + 4781 5664 AD B5 55 lda SAVEXSIZE+LO ; get old xsize back + 4782 5667 85 A2 sta XSIZE+LO ; restored + 4783 5669 AD B6 55 lda SAVEXSIZE+HI + 4784 566C 85 A3 sta XSIZE+HI + 4785 566E A9 00 lda #0 ; reset this flag too + 4786 5670 85 19 sta FMTTBL ; cleared + 4787 5672 OUT3: + 4788 5672 60 rts + 4789 ; + 4790 ; set things up for doing table output + 4791 ; + 4792 5673 START_TABLE: + 4793 + 4794 5673 A5 66 lda ARG2+HI ; SET UP TBL + 4795 5675 85 A1 sta DIRTBL+HI + 4796 5677 A5 65 lda ARG2+LO ; TO STORE CHARS IN + 4797 5679 85 A0 sta DIRTBL+LO + 4798 567B A9 02 lda #2 + 4799 567D 8D 80 6C sta DIRITM+LO + 4800 5680 A9 00 lda #0 + 4801 5682 8D 81 6C sta DIRITM+HI + 4802 5685 8D 31 96 sta ZBEGIN+ZTWIDTH+1 ; clear width count + 4803 5688 8D 30 96 sta ZBEGIN+ZTWIDTH+0 + 4804 ; + 4805 ; check to see if we have formatted table + 4806 ; + 4807 568B A5 62 lda NARGS ; get # of arguments + 4808 568D C9 03 cmp #3 ; if == 3, then we wrap it + 4809 568F F0 01 beq DIR30 ; nope + 4810 5691 60 rts ; all done other wise + 4811 5692 DIR30: + 4812 5692 86 19 stx FMTTBL ; set formatted table flag + 4813 5694 A5 A2 lda XSIZE+LO ; save the current XSIZE + 4814 5696 8D B5 55 sta SAVEXSIZE+LO ; okay, did it + 4815 5699 A5 A3 lda XSIZE+HI ; and MSB + 4816 569B 8D B6 55 sta SAVEXSIZE+HI ; okay + 4817 569E A5 67 lda ARG3+LO ; this is the actual amount + 4818 56A0 A6 68 ldx ARG3+HI ; get interesting arg + 4819 56A2 30 0B bmi DIRFT1 ; check for negative width + 4820 56A4 20 77 57 jsr SETWJ ; get the window offset + 4821 56A7 A0 14 ldy #WINXSZ ; get its XSIZE + 4822 56A9 B1 7A lda (J),Y ; got it + 4823 56AB 85 A2 sta XSIZE+LO ; aren't we nice + 4824 56AD D0 06 bne DIR31 ; jump to end + 4825 56AF DIRFT1: + 4826 56AF 49 FF eor #$FF ; turn to a positive number + 4827 56B1 85 A2 sta XSIZE+LO ; save it + 4828 56B3 E6 A2 inc XSIZE+LO ; to make it right + 4829 56B5 DIR31: + 4830 56B5 A9 00 lda #0 ; items starts at zero + 4831 56B7 8D 80 6C sta DIRITM+LO ; okay + 4832 56BA 85 A3 sta XSIZE+HI ; clear out highness + 4833 56BC 06 A2 asl XSIZE+LO ; *2 + 4834 56BE 26 A3 rol XSIZE+HI + 4835 56C0 06 A2 asl XSIZE+LO ; *4 + Wed May 24 1989 15:00 Page 71 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4836 56C2 26 A3 rol XSIZE+HI + 4837 56C4 60 rts + 4838 + 4839 ; ------ + 4840 ; CURSET + 4841 ; ------ + 4842 ; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW + 4843 ; AND AT COLUMN (ARG2) in (optional) window ARG3 + 4844 + 4845 56C5 ZCURST: + 4846 56C5 20 AD 55 jsr CLRBUF ; CLEAR OUT ANY NON DISPLAYED TEXT 1ST + 4847 56C8 A5 63 lda ARG1+LO ; see if < 0 + 4848 56CA C9 FF cmp #$FF ; -1 == turn off cursor + 4849 56CC D0 04 bne ZCURS00 ; nope + 4850 56CE A9 01 lda #1 ; show cursor off + 4851 56D0 D0 06 bne ZCURSTXX ; go do it and return + 4852 56D2 ZCURS00: + 4853 56D2 C9 FE cmp #$FE ; -2 == turn cursor on + 4854 56D4 D0 06 bne ZCURS0 ; nope, just deal with normally + 4855 56D6 A9 00 lda #0 ; show cursor not off + 4856 56D8 ZCURSTXX: + 4857 56D8 8D A2 6C sta CURSOR_OFF ; show current cursor state + 4858 56DB 60 rts + 4859 56DC ZCURS0: + 4860 56DC C6 63 dec ARG1+LO ; zero base both args + 4861 56DE C6 65 dec ARG2+LO ; thanx + 4862 56E0 + 4863 56E0 A5 62 lda NARGS ; check for id + 4864 56E2 C9 03 cmp #3 ; if 3 args, then window ID specified + 4865 56E4 F0 04 beq ZCURS1 ; not 3, so use current window + 4866 + 4867 56E6 A5 A6 lda CURWIN ; show current window being done + 4868 56E8 85 67 sta ARG3+LO ; thanx + 4869 56EA ZCURS1: + 4870 56EA A5 67 lda ARG3+LO ; get window ID + 4871 56EC 20 77 57 jsr SETWJ ; put address into J + 4872 56EF A5 63 lda ARG1+LO ; GET LINE + 4873 56F1 A0 02 ldy #WINHGHT ; check against height + 4874 56F3 D1 7A cmp (J),Y ; too far? + 4875 56F5 90 05 bcc ZCURS3 ; no, so use it + 4876 56F7 B1 7A lda (J),Y ; got max out + 4877 56F9 A8 tay ; but one too far + 4878 56FA 88 dey ; all better now + 4879 56FB 98 tya ; back to A + 4880 56FC ZCURS3: + 4881 56FC 18 clc ; get ready for add + 4882 56FD A0 00 ldy #WINTOP ; do y pos first + 4883 56FF 71 7A adc (J),Y ; add in top to get absolute value + 4884 5701 A0 04 ldy #WINY ; get y pos offset + 4885 5703 91 7A sta (J),Y ; save here + 4886 5705 A5 65 lda ARG2+LO ; GET COLUMN + 4887 5707 A0 03 ldy #WINWID ; check against width + 4888 5709 D1 7A cmp (J),Y ; is it to for right (like Reagan?) + 4889 570B 90 05 bcc ZCURS4 ; nope, must be dukakis + 4890 570D B1 7A lda (J),Y ; get max + 4891 570F A8 tay ; for going down one + 4892 5710 88 dey ; done it + 4893 5711 98 tya ; back to A for usefullness + 4894 5712 ZCURS4: + 4895 5712 A0 01 ldy #WINLEFT ; get left edge to absolute it + 4896 5714 71 7A adc (J),Y ; carry clear from above + 4897 5716 A0 05 ldy #WINX ; this is the x pos + 4898 5718 91 7A sta (J),Y ; into the structure + 4899 ; + 4900 ; now check for current window again, move cursor anyway + 4901 ; + 4902 571A 4C B1 4D jmp GET_CURSOR ; get cursor pos from WINDOW + 4903 + 4904 ; ------ + 4905 ; CURGET + 4906 ; ------ + 4907 + 4908 571D ZCURGT: + 4909 571D 20 AD 55 jsr CLRBUF ; flush the buffer + 4910 + Wed May 24 1989 15:00 Page 72 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4911 5720 20 9F 4D jsr SAVE_CURSOR ; save the current position + 4912 + 4913 5723 C6 62 dec NARGS ; see how many arguments + 4914 5725 F0 04 beq ZCURG1 ; use main window + 4915 5727 A5 65 lda ARG2+LO ; get window id + 4916 5729 10 02 bpl ZCURG2 ; and figger it out + 4917 572B ZCURG1: + 4918 572B A5 A6 lda CURWIN ; use current window + 4919 572D ZCURG2: + 4920 572D 20 77 57 jsr SETWJ ; make J point to right place + 4921 + 4922 5730 A5 64 lda ARG1+HI ; get table address + 4923 5732 20 77 8F jsr SETPC ; get real address in memory + 4924 5735 84 91 sty SPCBNK ; set bank + 4925 5737 85 90 sta SPCH ; and page + 4926 5739 A5 63 lda ARG1+LO ; get table offset + 4927 573B 85 8F sta SPCL ; and save it + 4928 + 4929 573D A9 00 lda #0 ; zero hi part of Y pos + 4930 573F 20 35 92 jsr STASHB ; and save it + 4931 5742 20 9E 8F jsr NEXTSPC ; and point to next one + 4932 5745 20 5C 57 jsr FETCHCY ; Fetch Y pos + 4933 5748 20 35 92 jsr STASHB ; and save it + 4934 574B 20 9E 8F jsr NEXTSPC + 4935 ; + 4936 ; now for the X pos + 4937 574E A9 00 lda #0 ; zero top byte of x pos + 4938 5750 20 35 92 jsr STASHB + 4939 5753 20 9E 8F jsr NEXTSPC + 4940 5756 20 69 57 jsr FETCHCX ; and now the X pos, and return + 4941 5759 4C 35 92 jmp STASHB ; and stash it away + 4942 + 4943 ; + 4944 ; FETCHCY - get the relativized Y pos into [A] + 4945 ; J points to window structure + 4946 575C FETCHCY: + 4947 575C A0 04 ldy #WINY ; get Y pos of window's cursor + 4948 575E B1 7A lda (J),Y ; got it + 4949 5760 A0 00 ldy #WINTOP ; need to de-absolute it + 4950 5762 38 sec ; get ready for sub + 4951 5763 F1 7A sbc (J),Y ; get relative pos + 4952 5765 AA tax ; for 1 basing it + 4953 5766 E8 inx ; 1 align it + 4954 5767 8A txa ; and put for save + 4955 5768 60 rts + 4956 ; + 4957 ; FETCHCX - get relativized X pos into [A] + 4958 ; J points to window structure + 4959 5769 FETCHCX: + 4960 5769 A0 05 ldy #WINX ; get X pos of cursor + 4961 576B B1 7A lda (J),Y ; got it + 4962 576D A0 01 ldy #WINLEFT ; relativize it + 4963 576F 38 sec ; get ready for sub + 4964 5770 F1 7A sbc (J),Y ; subtract left edge + 4965 5772 AA tax ; for incing + 4966 5773 E8 inx ; 1 ALIGN IT + 4967 5774 8A txa + 4968 5775 60 rts + 4969 + 4970 ; ----- + 4971 ; DIRIN + 4972 ; ----- + 4973 ; NOT YET IMPLEMENTED, BUT RESERVED + 4974 + 4975 5776 60 ZDIRIN: RTS + 4976 + 4977 ; + 4978 ; SETWJ - set up J to point to window structure for window ID in [A] + 4979 ; + 4980 5777 SETWJ: + 4981 5777 A8 tay ; check for -3 (current window) + 4982 5778 10 02 bpl SWJ1 ; nope, window ID here + 4983 577A A5 A6 lda CURWIN ; -3 means current window + 4984 577C SWJ1: + 4985 577C 0A asl A ; shift to make word index + Wed May 24 1989 15:00 Page 73 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 4986 577D A8 tay ; and now make index + 4987 577E B9 47 6E lda WINTABLE,Y ; get lo part of window struct address + 4988 5781 85 7A sta J+LO ; and save it + 4989 5783 B9 48 6E lda WINTABLE+1,Y ; here's the hi part + 4990 5786 85 7B sta J+HI ; prove it + 4991 5788 60 rts + 4992 + 4993 ; ----- + 4994 ; ERASE + 4995 ; ----- + 4996 + 4997 5789 ZERASE: + 4998 5789 A5 63 lda ARG1+LO + 4999 578B C9 01 cmp #1 + 5000 578D D0 06 bne ZEROUT ; not clreol + 5001 + 5002 578F 20 AD 55 jsr CLRBUF + 5003 5792 4C FD 60 jmp CLREOL ; CLEAR TO END OF LINE + 5004 5795 ZEROUT: + 5005 5795 85 0C sta CLSWIDTH ; this many pixels wide + 5006 5797 A9 09 lda #FONT_H ; pixels of font_height + 5007 5799 85 0D sta CLSHEIGHT + 5008 579B A5 00 lda SCRCX ; start at current cursor pos + 5009 579D 85 0A sta CLSLEFT + 5010 579F A5 01 lda SCRCY + 5011 57A1 85 0B sta CLSTOP + 5012 57A3 4C 00 5F jmp CLS ; and do it + 5013 + 5014 ; ----- + 5015 ; CLEAR the current window + 5016 ; ----- + 5017 57A6 0000 SAVEXY: dw 0 + 5018 + 5019 57A8 ZCLR: + 5020 57A8 20 AD 55 jsr CLRBUF ; flush the current buffer + 5021 57AB 20 9F 4D jsr SAVE_CURSOR ; save the cursor pos + 5022 + 5023 57AE A5 63 lda ARG1+LO ; CHECK WHAT TO DO + 5024 57B0 10 26 bpl CLRW ; a particular window + 5025 57B2 C9 FD cmp #$FD ; -3 means current window + 5026 57B4 F0 22 beq CLRW ; so just handle it regular + 5027 57B6 C9 FE cmp #$FE ; clear with nothing social + 5028 57B8 F0 07 beq CLRCLS ; just clear the screen + 5029 ; + 5030 ; UNSPLIT SCREEN & CLEAR IT + 5031 ; + 5032 57BA A9 00 lda #0 ; just use SPLIT 0 + 5033 57BC 85 63 sta ARG1+LO ; as if called normally + 5034 57BE 20 DD 4D jsr ZSPLIT ; do the split + 5035 ; + 5036 ; just clear the entire screen + 5037 ; + 5038 57C1 CLRCLS: + 5039 57C1 A9 00 lda #0 ; clear the entire screen + 5040 57C3 85 0A sta CLSLEFT ; from top left + 5041 57C5 85 0B sta CLSTOP + 5042 57C7 A9 8C lda #MAXWIDTH ; to bottom right + 5043 57C9 85 0C sta CLSWIDTH + 5044 57CB A9 C0 lda #MAXHEIGHT + 5045 57CD 85 0D sta CLSHEIGHT + 5046 + 5047 57CF 20 00 5F jsr CLS ; do the clear screen (no cursor movement) + 5048 57D2 A5 63 lda ARG1+LO ; check for -2 + 5049 57D4 30 44 bmi ZCLRX ; it is, don't move cursor + 5050 57D6 10 1B bpl ZCLEARX ; move cursor + 5051 57D8 CLRW: + 5052 57D8 20 77 57 jsr SETWJ ; get me the window pointer + 5053 57DB A0 00 ldy #WINTOP ; step thro to get data + 5054 57DD B1 7A lda (J),Y ; TOP + 5055 57DF 85 0B sta CLSTOP ; save for clear + 5056 57E1 C8 iny ; point to left + 5057 57E2 B1 7A lda (J),Y ; get it + 5058 57E4 85 0A sta CLSLEFT ; tell CLS + 5059 57E6 C8 iny ; now at WINHGHT + 5060 57E7 B1 7A lda (J),Y ; got it + Wed May 24 1989 15:00 Page 74 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5061 57E9 85 0D sta CLSHEIGHT ; save for clear + 5062 57EB C8 iny ; now at WINWID + 5063 57EC B1 7A lda (J),Y ; get height + 5064 57EE 85 0C sta CLSWIDTH ; saved + 5065 57F0 20 00 5F jsr CLS ; screen cleared + 5066 ; + 5067 ; now move the cursor to 1,1, if not == -2 + 5068 ; + 5069 57F3 ZCLEARX: + 5070 57F3 A5 63 lda ARG1+LO ; check arg + 5071 57F5 20 77 57 jsr SETWJ ; make sure J still points to window + 5072 57F8 A0 00 ldy #WINTOP ; put at top left of window + 5073 57FA B1 7A lda (J),Y ; get top + 5074 57FC A0 04 ldy #WINY ; and make it the y pos + 5075 57FE 91 7A sta (J),Y ; of the cursor + 5076 5800 A0 01 ldy #WINLEFT ; and the left is + 5077 5802 B1 7A lda (J),Y ; the + 5078 5804 18 clc ; add in the left margin + 5079 5805 A0 06 ldy #WINLM ; here's the left margin + 5080 5807 71 7A adc (J),Y ; added it + 5081 5809 A0 05 ldy #WINX ; x pos of the + 5082 580B 91 7A sta (J),Y ; cursor + 5083 580D A9 00 lda #0 ; and clear out line count + 5084 580F A0 13 ldy #WINLCNT ; line count + 5085 5811 91 7A sta (J),Y ; okay + 5086 5813 A0 15 ldy #WINLLEN ; and length of current line + 5087 5815 91 7A sta (J),Y ; okay + 5088 5817 C8 iny ; do hi + 5089 5818 91 7A sta (J),Y ; okay + 5090 581A ZCLRX: + 5091 581A 4C B1 4D jmp GET_CURSOR ; restore the cursor pos for the current window + 5092 + 5093 ; ------ + 5094 ; PRINTT + 5095 ; ------ + 5096 ; PRINT A TABLE TO SCREEN, ARG1 = # OF BYTES + 5097 ; ARG2 = WIDTH, ARG3 (DEF = 1) = HEIGHT + 5098 + 5099 0078 OLDCHZ EQU I+LO ; EASIER TO READ + 5100 0079 OLDEHZ EQU I+HI + 5101 007E OLDCVT EQU L+LO + 5102 + 5103 581D 0000 TBL_LEN DW 0 ; save for length + 5104 + 5105 581F ZPRNTT: + 5106 ; + 5107 ; make sure the buffer is empty, thanks + 5108 ; + 5109 581F 20 AD 55 jsr CLRBUF + 5110 + 5111 5822 A5 63 lda ARG1+LO ; USE GETBYT AS TBL COULD + 5112 5824 85 86 sta MPCL ; BE ANYWHERE + 5113 5826 A5 64 lda ARG1+HI + 5114 5828 85 87 sta MPCM + 5115 582A A9 00 lda #0 + 5116 582C 85 88 sta MPCH + 5117 582E 20 80 90 jsr VLDMPC + 5118 + 5119 5831 A5 65 lda ARG2+LO ; ONLY A BYTE AS MAX + 5120 5833 F0 58 beq PTTDUN ; QUIT NOW IF NULL + 5121 + 5122 5835 85 BF sta TBLWIDTH ; width of the table + 5123 5837 85 C0 sta TBLCNT ; start counter off at width + 5124 5839 C6 62 dec NARGS ; count down to 1 (maybe) + 5125 583B A5 62 lda NARGS + 5126 583D C9 01 cmp #1 + 5127 583F F0 02 beq NOHIGHT ; DEFAULT HEIGHT IS 1 + 5128 5841 A5 67 lda ARG3+LO ; get passed height + 5129 5843 NOHIGHT: + 5130 5843 85 BE sta TBLHEIGHT ; height of the table (at least 1) + 5131 5845 A5 00 lda SCRCX + 5132 5847 85 79 sta OLDEHZ + 5133 5849 38 sec ; subtract left margin to get how long line is + 5134 584A E5 04 sbc LEFTMRG ; okay we did that + 5135 584C 8D 1D 58 sta TBL_LEN+LO ; this is how big line is too + Wed May 24 1989 15:00 Page 75 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5136 584F A9 00 lda #0 ; clear MSB + 5137 5851 0E 1D 58 asl TBL_LEN+LO ; *2 + 5138 5854 2A rol A + 5139 5855 0E 1D 58 asl TBL_LEN+LO ; *4 + 5140 5858 2A rol A + 5141 5859 8D 1E 58 sta TBL_LEN+HI ; save + 5142 585C PTTLP: + 5143 585C 20 09 92 jsr GETBYT ; GET A BYTE + 5144 585F 20 06 53 jsr COUT ; and send it out + 5145 + 5146 5862 C6 C0 dec TBLCNT ; one more byte done + 5147 5864 D0 F6 bne PTTLP + 5148 5866 C6 BE dec TBLHEIGHT ; IF DONE ALL LINES + 5149 5868 F0 23 beq PTTDUN ; LEAVE + 5150 + 5151 586A 20 AD 55 jsr CLRBUF ; so send out stuff that's there + 5152 + 5153 586D A5 79 lda OLDEHZ ; get old x pos + 5154 586F 85 00 sta SCRCX ; and restore it + 5155 5871 A9 01 lda #1 ; show cursor changed + 5156 5873 8D 77 6C sta CURSFLG ; okay + 5157 5876 A5 01 lda SCRCY ; point to next line + 5158 5878 18 clc ; by adding in the font height + 5159 5879 69 09 adc #FONT_H ; okay, goody + 5160 587B 85 01 sta SCRCY ; and here we are + 5161 + 5162 587D AD 1E 58 lda TBL_LEN+HI ; reset length + 5163 5880 85 A8 sta LENGTH+HI ; hi part + 5164 5882 AD 1D 58 lda TBL_LEN+LO ; lo part + 5165 5885 85 A7 sta LENGTH+LO ; just a lo + 5166 + 5167 5887 A5 BF lda TBLWIDTH ; RESET COUNT + 5168 5889 85 C0 sta TBLCNT ; thanx + 5169 588B D0 CF bne PTTLP ; GO DO NEXT LINE + 5170 588D PTTDUN: + 5171 588D 20 AD 55 jsr CLRBUF ; send out last bit + 5172 5890 60 rts + 5173 ;-------------- + 5174 ; ZPRINTF + 5175 ;-------------- + 5176 ; ZPRINTF - print a formatted table + 5177 ; + 5178 5891 ZPRINTF: + 5179 5891 A5 63 lda ARG1+LO ; USE GETBYT AS TBL COULD + 5180 5893 85 86 sta MPCL ; BE ANYWHERE + 5181 5895 A5 64 lda ARG1+HI + 5182 5897 85 87 sta MPCM + 5183 5899 A9 00 lda #0 + 5184 589B 85 88 sta MPCH + 5185 589D 20 80 90 jsr VLDMPC + 5186 + 5187 58A0 A5 00 lda SCRCX ; save the X pos + 5188 58A2 85 79 sta OLDEHZ ; saved here + 5189 58A4 ZPFL1: + 5190 58A4 20 09 92 jsr GETBYT ; get the length byte + 5191 58A7 F0 21 beq ZPFX ; no more if == 0 + 5192 58A9 85 BF sta TBLWIDTH ; keep track of it + 5193 58AB ZPFL2: + 5194 58AB 20 09 92 jsr GETBYT ; now get the char byte + 5195 58AE 20 7D 5D jsr CHAR ; and send it yt + 5196 58B1 C6 BF dec TBLWIDTH ; any more? + 5197 58B3 D0 F6 bne ZPFL2 ; ayyup + 5198 + 5199 58B5 20 EC 71 jsr DISP_LINE ; make sure line goes out + 5200 58B8 A5 79 lda OLDEHZ ; reset a few things + 5201 58BA 85 00 sta SCRCX ; including x pos + 5202 58BC A9 01 lda #1 ; show cursor changed + 5203 58BE 8D 77 6C sta CURSFLG ; okay + 5204 58C1 A5 01 lda SCRCY ; point to next line + 5205 58C3 18 clc ; by adding in the font height + 5206 58C4 69 09 adc #FONT_H ; okay, goody + 5207 58C6 85 01 sta SCRCY ; and here we are + 5208 58C8 D0 DA bne ZPFL1 ; and do it again + 5209 58CA ZPFX: + 5210 58CA 60 rts + Wed May 24 1989 15:00 Page 76 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5211 ; ------------ + 5212 ; SET NEW FONT + 5213 ; ------------ + 5214 + 5215 ; Font 4 is mono-spaced font. + 5216 + 5217 58CB ZFONT: + 5218 58CB 20 AD 55 jsr CLRBUF ; clear the buffer first + 5219 + 5220 58CE C6 62 dec NARGS ; did we get passed a window id? + 5221 58D0 D0 04 bne ZFNTWID ; yup + 5222 58D2 A9 FD lda #$FD ; -3 means current window + 5223 58D4 85 65 sta ARG2+LO ; make it the arg2 then + 5224 58D6 ZFNTWID: + 5225 58D6 A5 65 lda ARG2+LO ; get window we are interested in + 5226 58D8 20 77 57 jsr SETWJ ; make [J] point to window struct + 5227 + 5228 58DB A5 63 lda ARG1+LO ; check for + 5229 58DD C9 01 cmp #1 ; font 1 + 5230 58DF F0 0E beq ZFNT1 ; or + 5231 58E1 C9 04 cmp #4 ; font 4 (monospace) + 5232 58E3 D0 2A bne ZFBAD ; nope, so die + 5233 ; + 5234 ; font 4 is the monospaced font + 5235 ; + 5236 58E5 A0 10 ldy #WINFSIZE ; point to width + 5237 58E7 A9 03 lda #MFONT_W ; get game width + 5238 58E9 91 7A sta (J),Y ; store the width + 5239 58EB A9 03 lda #3 ; set font ID + 5240 58ED D0 08 bne ZFNTEX ; all done + 5241 58EF ZFNT1: + 5242 58EF A0 10 ldy #WINFSIZE ; point to width + 5243 58F1 A9 02 lda #FONT_W ; get game width + 5244 58F3 91 7A sta (J),Y ; store the width + 5245 58F5 A9 00 lda #0 ; set font ID + 5246 58F7 ZFNTEX: + 5247 58F7 A0 0F ldy #WINFONT ; set font + 5248 58F9 48 pha ; save font id + 5249 58FA B1 7A lda (J),Y ; get old font id + 5250 58FC AA tax ; save old font id + 5251 58FD 68 pla ; get new one back + 5252 58FE 91 7A sta (J),Y ; save in structure + 5253 5900 B1 05 lda (WINDOW),Y ; get current window font + 5254 5902 F0 02 beq ZFNT0X ; set flag with zero + 5255 5904 A9 0C lda #MONOFONT_W ; get width of mono spaced font + 5256 5906 ZFNT0X: + 5257 5906 85 C1 sta FONTFLG ; and set flag too + 5258 5908 E8 inx ; make it say correct font ID for game + 5259 5909 8A txa ; put in A for put val + 5260 590A A2 00 ldx #0 ; clear X + 5261 590C 4C E1 43 jmp PUTVAL ; and return it + 5262 590F ZFBAD: + 5263 590F 4C DA 43 jmp RET0 ; TELL IT DOESN'T WORK + 5264 ; ------------------------------ + 5265 ; FETCH A LINE OF INPUT FOR READ + 5266 ; ------------------------------ + 5267 ; ENTRY: Relative READ table address in RDTBL1 + 5268 ; EXIT: # CHARS READ IN [A] + 5269 5912 SV_SPC: ds 3 ; save SPC here for later usage + 5270 + 5271 5915 INPUT: + 5272 5915 20 AD 55 jsr CLRBUF ; FLUSH [LBUFF] + 5273 5918 A0 00 ldy #0 ; RESET LINE COUNT + 5274 591A 84 79 sty I+HI ; clear local variables + 5275 591C 84 78 sty I+LO + 5276 591E 84 7B sty J+HI + 5277 5920 84 7A sty J+LO + 5278 5922 8C 64 5B sty BRKCHR ; init break char + 5279 5925 84 AB sty LINCNT ; RESET LINE COUNT + 5280 5927 8C A4 6C sty PTR_COUNT ; we start by looking at pointer + 5281 592A 8C 77 6C sty CURSFLG ; make sure we don't change cursor + 5282 ; + 5283 ; check for new TCHARS table + 5284 ; + 5285 592D AD 2F 96 lda ZBEGIN+ZTCHAR+1 ; so check lower byte for different tchars + Wed May 24 1989 15:00 Page 77 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5286 5930 CD 84 6C cmp SVTCHAR+LO ; is it different? + 5287 5933 D0 08 bne IO_DOT ; ayyup, get new one + 5288 5935 AD 2E 96 lda ZBEGIN+ZTCHAR ; get current TCHARS hi part + 5289 5938 CD 85 6C cmp SVTCHAR+HI ; is it the same as saved one? + 5290 + 5291 593B F0 03 beq IOj ; yes, so don't muck with it + 5292 593D IO_DOT: + 5293 593D 20 79 5A jsr DO_TCHARS ; new table, so copy it over + 5294 ; + 5295 ; now set up FPC + 5296 ; + 5297 5940 IOj: + 5298 5940 AD 7B 6C lda RDTBL1+HI ; get page of table + 5299 5943 20 77 8F jsr SETPC ; and get me the memory page and bank + 5300 5946 85 8D sta FPCH ; save page + 5301 5948 84 8E sty FPCBNK ; and bank + 5302 594A AD 7A 6C lda RDTBL1+LO ; and get offset + 5303 594D 85 8C sta FPCL ; set up FPC/SPC + 5304 594F 20 56 92 jsr FETCHB ; get length of line + 5305 5952 A8 tay ; for dec'ing + 5306 5953 88 dey ; don't count the offset byte + 5307 5954 88 dey ; and leave room for terminator + 5308 5955 84 17 sty CHRMAX ; and save it + 5309 5957 20 BE 8F jsr NEXTFPC ; point to next byte + 5310 595A 20 56 92 jsr FETCHB ; get current offset into buffer + 5311 595D 8D 5D 5B sta CHARCNT ; save how many chars out there + 5312 5960 20 BE 8F jsr NEXTFPC ; point to beginning of data buffer + 5313 ; + 5314 ; now finish setting up saved SPC + 5315 ; + 5316 5963 A2 02 ldx #2 + 5317 5965 INSVCL: + 5318 5965 B5 8C lda FPC,X ; get byte to saved for use later on + 5319 5967 9D 12 59 sta SV_SPC,X ; it is saved here + 5320 596A CA dex + 5321 596B 10 F8 bpl INSVCL ; next! + 5322 ; + 5323 ; now copy current buffer into local buffer + 5324 ; + 5325 596D AD 5D 5B lda CHARCNT ; make sure we have some + 5326 5970 F0 11 beq CPIOLX ; nope, none in there now + 5327 5972 A2 00 ldx #0 ; start at first char + 5328 5974 CPIOL: + 5329 5974 20 56 92 jsr FETCHB ; get a char + 5330 5977 9D 00 02 sta LBUFF,X ; save char + 5331 597A 20 BE 8F jsr NEXTFPC ; point to next one + 5332 597D E8 inx ; next char + 5333 597E EC 5D 5B cpx CHARCNT ; got them all yet? + 5334 5981 D0 F1 bne CPIOL ; nope + 5335 5983 CPIOLX: + 5336 5983 20 0E 4F jsr CHKTME ; START TIME LIMIT + 5337 ; + 5338 ; this is the get-a-key-and-whack-on-it loop + 5339 ; + 5340 5986 INLOOP: + 5341 5986 A5 79 lda I+HI ; is there a time? + 5342 5988 F0 08 beq INPL1 ; nope + 5343 598A 20 C9 4F jsr TIMIN ; do timed input + 5344 598D 90 06 bcc INPL2 ; got a char, process it + 5345 598F 4C 73 5A jmp LEXBAD ; timed out with nothing there! + 5346 5992 INPL1: + 5347 5992 20 31 51 jsr GETKEY ; let apple do the walking + 5348 5995 INPL2: + 5349 5995 20 B0 5A jsr ISTCHR ; CHECK IF IT'S AN ACCEPTABLE TERMINATOR KEY + 5350 5998 B0 0D bcs NOTYET + 5351 + 5352 599A 8D 64 5B sta BRKCHR + 5353 599D C9 0D cmp #EOL ; IF EOL PUT TO SCREEN + 5354 599F F0 03 beq ENDLINx + 5355 59A1 4C 2A 5A jmp ENDIN ; ELSE JUST END + 5356 59A4 ENDLINx: + 5357 59A4 4C 1A 5A jmp ENDLIN ; can't reach with a branch + 5358 59A7 NOTYET: + 5359 59A7 A0 FF ldy #$FF ; restart pointer device counter + 5360 59A9 8C A4 6C sty PTR_COUNT ; and start again + Wed May 24 1989 15:00 Page 78 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5361 59AC A8 tay ; check for functions keys that aren't + 5362 59AD 30 65 bmi CBAD ; terminators and feep if it is + 5363 59AF C9 0D cmp #EOL ; EOL? + 5364 59B1 F0 67 beq ENDLIN ; LINE DONE IF SO + 5365 59B3 C5 1B cmp ESCAPE ; don't allow escape char's thru + 5366 59B5 F0 5D beq CBAD ; okay, I won't + 5367 + 5368 59B7 C9 08 cmp #BACKSPACE ; BACKSPACE? + 5369 59B9 F0 38 beq BACKUP ; SPECIAL HANDLING + 5370 59BB C9 1B cmp #ESCAPE ; ESCAPE char? + 5371 59BD F0 55 beq CBAD ; don't like it + 5372 + 5373 59BF AC 5D 5B ldy CHARCNT ; where do we put char? + 5374 59C2 C4 17 cpy CHRMAX ; are we filled up? + 5375 59C4 B0 4E bcs CBAD ; boy, am i full + 5376 + 5377 59C6 48 pha ; save it + 5378 59C7 AA tax ; use as index + 5379 59C8 A5 A7 lda LENGTH+LO ; GET LINE LENGTH COUNTER + 5380 59CA 18 clc ; get ready for add + 5381 59CB 7D 25 64 adc CHWID,X ; add width + 5382 59CE A8 tay ; save LSB in Y + 5383 59CF A6 A8 ldx LENGTH+HI ; get high byte + 5384 59D1 90 01 bcc INP0C ; no wrap + 5385 59D3 E8 inx ; okay, wrap then + 5386 59D4 INP0C: + 5387 59D4 68 pla ; get char back + 5388 59D5 E4 A3 cpx XSIZE+HI ; check MSB first + 5389 59D7 90 04 bcc NOIOWRAP ; no need to check lsb + 5390 59D9 C4 A2 cpy XSIZE+LO ; end of screen line? + 5391 59DB B0 37 bcs CBAD ; reached end, so just beep + 5392 59DD NOIOWRAP: + 5393 59DD 86 A8 stx LENGTH+HI ; save MSB + 5394 59DF 84 A7 sty LENGTH+LO ; and LSB + 5395 59E1 AE 5D 5B ldx CHARCNT ; for putting in line buffer + 5396 59E4 9D 00 02 sta LBUFF,X ; and save it in case we goto printer + 5397 59E7 20 7D 5D jsr CHAR ; SEND TO SCREEN + 5398 59EA 20 EC 71 jsr DISP_LINE ; show char + 5399 59ED EE 5D 5B inc CHARCNT ; NEXT POSITION IN LINE + 5400 59F0 4C 86 59 jmp INLOOP ; NO, GET ANOTHER CHAR + 5401 ; + 5402 ; HANDLE BACKSPACE + 5403 ; + 5404 59F3 BACKUP: + 5405 59F3 AE 5D 5B ldx CHARCNT ; if == 2 then empty + 5406 59F6 F0 1C beq CBAD ; JMP to beeping + 5407 59F8 CA dex ; get rid of char + 5408 59F9 8E 5D 5B stx CHARCNT ; saved + 5409 59FC BD 00 02 lda LBUFF,X ; get char we are interested in + 5410 59FF AA tax ; put in x + 5411 + 5412 5A00 A5 A7 lda LENGTH+LO ; GET LINE LENGTH COUNTER + 5413 5A02 38 sec ; get ready for sub + 5414 5A03 FD 25 64 sbc CHWID,X ; sub width + 5415 5A06 85 A7 sta LENGTH+LO ; update length + 5416 5A08 B0 02 bcs BCKP1 ; no wrap + 5417 5A0A C6 A8 dec LENGTH+HI ; okay, wrap then + 5418 5A0C BCKP1: + 5419 5A0C A9 08 lda #BACKSPACE ; so do erasing backspace + 5420 5A0E 20 7D 5D jsr CHAR + 5421 5A11 4C 86 59 jmp INLOOP + 5422 5A14 CBAD: + 5423 5A14 20 C3 4E jsr BEEP ; ELSE SCREAM WITH PAIN + 5424 5A17 4C 86 59 jmp INLOOP ; AND WAIT FOR SOMETHING BETTER + 5425 ; + 5426 ; HANDLE END OF LINE KEY + 5427 ; + 5428 5A1A ENDLIN: + 5429 5A1A 8D 64 5B sta BRKCHR + 5430 5A1D A9 0D lda #EOL ; get EOL char + 5431 5A1F 20 7D 5D jsr CHAR ; SEND EOL TO SCREEN + 5432 5A22 A9 00 lda #0 ; and show 0 length of line out there + 5433 5A24 85 A7 sta LENGTH+LO ; thanx + 5434 5A26 85 A8 sta LENGTH+HI ; and msb + 5435 5A28 E6 AB inc LINCNT ; take into account the at EOL + Wed May 24 1989 15:00 Page 79 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5436 5A2A ENDIN: + 5437 ; + 5438 ; now save lbuff in table for posterity + 5439 ; + 5440 5A2A AD 14 59 lda SV_SPC+ABANK ; get bank first + 5441 5A2D 85 91 sta SPCBNK ; saved + 5442 5A2F AD 13 59 lda SV_SPC+HI + 5443 5A32 85 90 sta SPCH + 5444 5A34 AD 12 59 lda SV_SPC+LO + 5445 5A37 85 8F sta SPCL + 5446 5A39 A2 00 ldx #0 ; start with first char in buffer + 5447 5A3B ENDLOOP: + 5448 5A3B EC 5D 5B cpx CHARCNT ; done yet? + 5449 5A3E F0 16 beq INP111 + 5450 5A40 BD 00 02 lda LBUFF,X ; get char + 5451 5A43 C9 41 cmp #'A' ; IF CHAR IS UPPERCASE ALPHA, + 5452 5A45 90 06 bcc LEX ; CONVERT TO LOWER CASE + 5453 5A47 C9 5B cmp #'Z'+1 + 5454 5A49 B0 02 bcs LEX + 5455 5A4B 69 20 adc #$20 ; converting away + 5456 5A4D LEX: + 5457 5A4D 20 35 92 jsr STASHB ; okay, stashing away + 5458 5A50 20 9E 8F jsr NEXTSPC ; and point to next char in table + 5459 5A53 E8 inx ; point to next char + 5460 5A54 D0 E5 bne ENDLOOP ; so get next one + 5461 5A56 INP111: + 5462 5A56 A9 00 lda #00 ; to show end of line + 5463 5A58 20 35 92 jsr STASHB ; so put it in buffer + 5464 ; + 5465 ; now put in new line length + 5466 ; + 5467 5A5B AD 7B 6C lda RDTBL1+HI ; get page of table + 5468 5A5E 20 77 8F jsr SETPC ; and get me the memory page and bank + 5469 5A61 85 90 sta SPCH ; save page + 5470 5A63 84 91 sty SPCBNK ; and bank + 5471 5A65 AD 7A 6C lda RDTBL1+LO ; and get offset + 5472 5A68 85 8F sta SPCL + 5473 5A6A 20 9E 8F jsr NEXTSPC ; and point to char count + 5474 5A6D AD 5D 5B lda CHARCNT ; get character count + 5475 5A70 20 35 92 jsr STASHB ; and shove it away + 5476 5A73 LEXBAD: + 5477 5A73 A0 00 ldy #0 ; clear out + 5478 5A75 8C A4 6C sty PTR_COUNT ; pointer flag + 5479 5A78 60 rts ; Length is in [A] + 5480 ; + 5481 ; Copy over a new TCHARS table + 5482 ; + 5483 5A79 DO_TCHARS: + 5484 ; + 5485 ; now do somethin' with the TCHAR table (maybe, if <> 0) + 5486 ; + 5487 5A79 AD 2E 96 lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + 5488 5A7C 8D 85 6C sta SVTCHAR+HI ; save it for checking + 5489 5A7F 20 77 8F jsr SETPC ; and now make absolute + 5490 5A82 85 8D sta FPCH ; Save in FPC + 5491 5A84 84 8E sty FPCBNK + 5492 5A86 AD 2F 96 lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + 5493 5A89 8D 84 6C sta SVTCHAR+LO ; and save for later check + 5494 5A8C 85 8C sta FPCL ; now move pointer to fetch spot + 5495 + 5496 5A8E A9 00 lda #0 ; and set index + 5497 5A90 85 78 sta I ; thank you + 5498 5A92 85 B9 sta ALLFLG ; turn it off + 5499 5A94 TCHLP: + 5500 5A94 20 56 92 jsr FETCHB ; get the byte in [a] + 5501 5A97 20 BE 8F jsr NEXTFPC ; point to next one + 5502 5A9A A6 78 ldx I ; get offset + 5503 5A9C E6 78 inc I ; and point to next one + 5504 5A9E 9D 00 1D sta TCHARTBL,X ; save in lower memory, thank you + 5505 5AA1 C9 00 cmp #0 ; are we done yet? + 5506 5AA3 F0 0A beq TCHj ; NULL TERMINATED STRING + 5507 5AA5 C9 FF cmp #$FF ; $ff means all >128 chars are terminators + 5508 5AA7 D0 04 bne TCHLNEXT ; nope + 5509 5AA9 A9 01 lda #1 ; yes, + 5510 5AAB 85 B9 sta ALLFLG ; so set flag to say so + Wed May 24 1989 15:00 Page 80 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5511 5AAD TCHLNEXT: + 5512 5AAD D0 E5 bne TCHLP ; and go get it + 5513 5AAF TCHj: + 5514 5AAF 60 rts + 5515 + 5516 ; ------------------------ + 5517 ; IS IT A TERMINATOR CHAR? + 5518 ; ------------------------ + 5519 + 5520 5AB0 ISTCHR: + 5521 5AB0 AE 00 1D ldx TCHARTBL ; check for chars in TCHAR table + 5522 5AB3 F0 18 beq ISNOT ; nope + 5523 + 5524 5AB5 A6 B9 ldx ALLFLG ; ARE ALL FCN KEYS (<127) TERMINATORS + 5525 5AB7 F0 05 beq ISCHK ; 0 = NO, GO CHECK LIST + 5526 5AB9 AA tax ; check for minus + 5527 5ABA 30 13 bmi ISFND ; YUP + 5528 5ABC 10 0F bpl ISNOT + 5529 5ABE ISCHK: + 5530 5ABE A0 00 ldy #0 + 5531 5AC0 ISLP: + 5532 5AC0 D9 00 1D cmp TCHARTBL,Y ; IS CHAR WE HAVE A TCHAR? + 5533 5AC3 F0 0A beq ISFND ; YES + 5534 5AC5 BE 00 1D ldx TCHARTBL,Y ; NULL = END OF STRING + 5535 5AC8 F0 03 beq ISNOT + 5536 5ACA C8 iny + 5537 5ACB D0 F3 bne ISLP ; SHOULD ALWAYS LOOP + 5538 5ACD ISNOT: + 5539 5ACD 38 sec + 5540 5ACE 60 rts ; NOT FOUND + 5541 5ACF ISFND: + 5542 5ACF 18 clc + 5543 5AD0 60 rts + 5544 + 5545 ; ----- + 5546 ; INPUT 1 char, no printing + 5547 ; ----- + 5548 + 5549 5AD1 ZINPUT: + 5550 5AD1 20 AD 55 JSR CLRBUF + 5551 + 5552 5AD4 A0 00 ldy #0 + 5553 5AD6 84 AB sty LINCNT + 5554 5AD8 84 A9 sty CHRCNT + 5555 5ADA 84 79 sty I+HI ; init locals too + 5556 5ADC 84 78 sty I+LO + 5557 5ADE 84 7B sty J+HI + 5558 5AE0 84 7A sty J+LO + 5559 5AE2 8C A4 6C sty PTR_COUNT ; always check the pointer + 5560 5AE5 + 5561 5AE5 C6 62 DEC NARGS + 5562 5AE7 F0 18 BEQ ZINP3 ; NO TIME LIMIT + 5563 5AE9 A5 65 LDA ARG2+LO ; GET DELAY WANTED + 5564 5AEB 85 79 STA I+HI + 5565 5AED C6 62 DEC NARGS + 5566 5AEF F0 08 BEQ ZINP4 ; NO FCN + 5567 5AF1 A5 67 LDA ARG3+LO + 5568 5AF3 85 7A STA J+LO + 5569 5AF5 A5 68 LDA ARG3+HI + 5570 5AF7 85 7B STA J+HI + 5571 5AF9 ZINP4: + 5572 5AF9 20 C9 4F JSR TIMIN ; CALL timed input rotine + 5573 5AFC 90 10 BCC ZINPRK ; send char on home + 5574 5AFE 4C DA 43 JMP RET0 ; time out without character + 5575 5B01 ZINP3: + 5576 5B01 20 31 51 jsr GETKEY ; ok, find which char was pressed + 5577 5B04 C9 1B cmp #ESCAPE ; don't use escape char + 5578 5B06 D0 06 bne ZINPRK ; fine + 5579 5B08 20 C3 4E jsr BEEP ; complain + 5580 5B0B 4C 01 5B jmp ZINP3 ; do again + 5581 5B0E ZINPRK: + 5582 5B0E A2 00 LDX #0 + 5583 5B10 4C DD 43 JMP PUTBYT ; RETURN CHAR + 5584 + 5585 + Wed May 24 1989 15:00 Page 81 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- GAME I/O: APPLE II ---" + + 5586 5B13 INTCLL: + 5587 5B13 A5 79 LDA I+HI ; SAVE VALUES FOR CALLING RTN + 5588 5B15 48 PHA + 5589 5B16 A5 78 LDA I+LO + 5590 5B18 48 PHA + 5591 5B19 A5 7B LDA J+HI + 5592 5B1B 85 64 STA ARG1+HI ; pretend it's arg1 + 5593 5B1D 48 PHA + 5594 5B1E A5 7A LDA J+LO + 5595 5B20 85 63 STA ARG1+LO ; and this is the other half + 5596 5B22 48 PHA + 5597 + 5598 5B23 A2 01 LDX #1 + 5599 5B25 86 62 STX NARGS ; 0 args for internal call + 5600 5B27 CA DEX + 5601 5B28 8E 5F 5B STX IRET ; make sure it returns here! + 5602 5B2B + 5603 5B2B A5 80 LDA ZPCL ; a fake one to say we + 5604 5B2D 48 PHA ; are an internal call + 5605 5B2E A5 81 LDA ZPCM ; so save real one + 5606 5B30 48 PHA + 5607 5B31 A5 82 LDA ZPCH + 5608 5B33 48 PHA + 5609 + 5610 5B34 A9 00 LDA #0 ; return addr of zero is + 5611 5B36 85 82 STA ZPCH ; internal call! + 5612 5B38 85 81 STA ZPCM + 5613 5B3A 85 80 STA ZPCL + 5614 + 5615 5B3C 20 C8 7F JSR DOCALL + 5616 + 5617 5B3F 4C B6 40 JMP MLOOP ; GO DO FCN + 5618 ; + 5619 ; RETURN FROM FCN WILL COME HERE + 5620 ; + 5621 5B42 ZIRET: + 5622 5B42 68 PLA ; GET RID OF RTS FROM ZRET + 5623 5B43 68 PLA + 5624 + 5625 5B44 68 PLA ; get old zpc back + 5626 5B45 85 82 STA ZPCH + 5627 5B47 68 PLA + 5628 5B48 85 81 STA ZPCM + 5629 5B4A 68 PLA + 5630 5B4B 85 80 STA ZPCL + 5631 5B4D 20 AA 90 JSR VLDZPC ; and validate it + 5632 + 5633 5B50 68 PLA ; RESTORE FOR CALLING RTN + 5634 5B51 85 7A STA J+LO + 5635 5B53 68 PLA + 5636 5B54 85 7B STA J+HI + 5637 5B56 68 PLA + 5638 5B57 85 78 STA I+LO + 5639 5B59 68 PLA + 5640 5B5A 85 79 STA I+HI + 5641 5B5C 60 RTS ; GO BACK TO CALLER + 5642 + 5643 ; INPUT: routine locals! + 5644 5B5D 00 CHARCNT: DB 0 ; where into buffer goes char + 5645 5B5E 00 SVCHAR: DB 0 ; where to save the char before printing + 5646 + 5647 5B5F 00 IRET: DB 0 ; FLAG TELLS IF RETURNLESS CALL + 5648 + 5649 5B60 00 00 MTEMP: DB 00,00 ; temp spot for math routines + 5650 5B62 00 TYPE: DB 0 ; PARTIAL OR NORMAL (WHOLE) SAVE/RESTORE + 5651 5B63 00 ASSVLU: DB 0 ; how many args to this subroutine + 5652 5B64 00 BRKCHR: DB 0 ; READ BREAK CHAR + 5653 5B65 00 RDFLAG: DB 0 ; 0 - only read 1 - do lex on it + 5654 5B66 5B 4D 4F 52 45 MORE: DB "[MORE]" + 5B6B 5D + 5655 0006 MOREL EQU $-MORE + 5656 5B6C END + 5657 + 5658 5B6C INCLUDE VERIFY.ASM + 5659 5B6C STTL "--- VERIFY CODE ---" + Wed May 24 1989 15:00 Page 82 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5660 PAGE + Wed May 24 1989 15:00 Page 83 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5661 + 5662 ; ------ + 5663 ; VERIFY + 5664 ; ------ + 5665 ; VERIFY GAME CODE ON DISK + 5666 5B6C 0D 54 68 65 20 VERBAD: DB EOL,"The data segment of file is BAD!",EOL + 5B71 64 61 74 61 20 + 5B76 73 65 67 6D 65 + 5B7B 6E 74 20 6F 66 + 5B80 20 66 69 6C 65 + 5B85 20 69 73 20 42 + 5B8A 41 44 21 0D + 5667 0022 VERBADL EQU $-VERBAD + 5668 5B8E 0D 54 68 65 20 VERPBAD: DB EOL,"The picture data of file is BAD!",EOL + 5B93 70 69 63 74 75 + 5B98 72 65 20 64 61 + 5B9D 74 61 20 6F 66 + 5BA2 20 66 69 6C 65 + 5BA7 20 69 73 20 42 + 5BAC 41 44 21 0D + 5669 0022 VERPBADL EQU $-VERPBAD + 5670 5BB0 00 ZVFLAG: db 0 ; set to indicate ugliness + 5671 0078 STARTPOS EQU I+LO ; this is where to start block + 5672 5BB1 ZVER: + 5673 5BB1 20 8F 8C jsr CLOSE_GAME ; make sure the game files are closed + 5674 5BB4 AC 89 46 ldy GAME2NML ; get length of name + 5675 5BB7 B9 89 46 lda GAME2NM,Y ; get last char + 5676 5BBA 49 30 eor #$30 ; make normal number + 5677 5BBC A8 tay ; -1 to make ready for FETCH_FILE + 5678 5BBD 88 dey ; F_F incs first + 5679 5BBE 98 tya ; to push onto stack + 5680 5BBF 48 pha ; and save for restoring later + 5681 5BC0 A9 00 lda #0 ; clear a few counters + 5682 5BC2 8D B0 5B sta ZVFLAG ; ==0 - verify worked; !=0 - verify broke + 5683 5BC5 AD 01 19 lda SEGTBL+SGTDISKS+1 ; get how many disks are here + 5684 5BC8 8D 57 49 sta DISKCNTR ; this shows which disk we are working on + 5685 5BCB CE 57 49 dec DISKCNTR ; start down by one + 5686 5BCE VERIFY_LOOP: + 5687 5BCE 20 06 5C jsr VERIFY_DATA ; check data in this file + 5688 5BD1 20 91 5C jsr VERIFY_PICD ; check (possible) picture data in this file + 5689 5BD4 AD CF 45 lda GMREF ; get reference number + 5690 5BD7 8D 07 8B sta CLOSE_PB+CL_REFNUM ; and show CLOSE + 5691 5BDA CLOSE CLOSE_PB ; and shut it up + 5692 5BDA PRODOS $CC, CLOSE_PB + 5693 5BDA 20 00 BF jsr $BF00 ; ProDOS handler + 5694 5BDD CC DB $CC ; ProDOS function code + 5695 5BDE 068B DW CLOSE_PB ; Function Parameter Block address + 5696 5BE0 .MACEND + 5697 5BE0 .MACEND + 5698 5BE0 CE 57 49 dec DISKCNTR ; next please + 5699 5BE3 10 E9 bpl VERIFY_LOOP ; and check the next file + 5700 5BE5 ZVERX: + 5701 5BE5 A9 02 lda #>PAGELEN ; reset read buffer length + 5702 5BE7 8D D3 45 sta READ_PB+RD_BUFFLEN+HI ; to be $100 + 5703 5BEA A9 00 lda # 0, then it isn't + 5745 5C33 20 4C 5D jsr SETUP_DISK0 ; move around to point to start of data + 5746 5C36 VERD1: + 5747 5C36 A0 02 ldy #SGTPICOF ; find where picture data starts + 5748 5C38 B1 1E lda (DSEGS),Y ; MSB + 5749 5C3A 85 7B sta J+HI ; J is the page counter + 5750 5C3C C8 iny ; point to LSB + 5751 5C3D 11 1E ora (DSEGS),Y ; any picture file? + 5752 5C3F D0 08 bne VERD01 ; yes, so mark end of data + 5753 5C41 A9 FF lda #$FF ; set J to be a real big number + 5754 5C43 85 7A sta J+LO ; okay + 5755 5C45 85 7B sta J+HI ; and this one + 5756 5C47 D0 15 bne VERD11 ; all done + 5757 5C49 VERD01: + 5758 5C49 B1 1E lda (DSEGS),Y ; and here it is + 5759 5C4B 0A asl A ; *2 to make 512 pages be 256 pages + 5760 5C4C 85 7A sta J+LO ; this is where it ends up + 5761 5C4E 26 7B rol J+HI ; move in carry to MSB + 5762 5C50 A5 7A lda J+LO ; now, subtract any skipping + 5763 5C52 38 sec ; doing sub + 5764 5C53 ED DF 45 sbc PSEEK+SM_FPOS+1 ; take away any skipped amount + 5765 5C56 85 7A sta J+LO ; and save it + 5766 5C58 A5 7B lda J+HI ; pick up carry + 5767 5C5A E9 00 sbc #0 ; we will + 5768 5C5C 85 7B sta J+HI ; we did + 5769 5C5E VERD11: + 5770 5C5E 20 E1 5C jsr VERIFY_FILE ; now, actually do the work + 5771 5C61 90 2D bcc VERDX ; worked just fine + 5772 5C63 DLINE VERBAD ; puke, gag, argh + 5773 5C63 A2 6C ldx #VERBAD ; get other part of string + 5775 [01] IFMA 2 ; check to see if length passed in + 5776 ldy ; then just fetch it + 5777 [01] ELSE + 5778 5C67 A0 22 ldy #VERBADL ; get length of string + 5779 [00] ENDIF + 5780 5C69 20 6B 4C jsr DLINE ; print the string + 5781 5C6C .MACEND + 5782 ; + 5783 ; This prints out which file is garfed + 5784 ; + 5785 5C6C VER_FMSG: + 5786 5C6C AD 57 49 lda DISKCNTR ; which file did we do? + 5787 5C6F C9 02 cmp #2 ; 0,1 are in one place + 5788 5C71 B0 0D bcs VERDB1 ; nope it isn't it + 5789 5C73 DLINE GAME1NAME,GAME1NML + 5790 5C73 A2 78 ldx #GAME1NAME ; get other part of string + 5792 [01] IFMA 2 ; check to see if length passed in + 5793 5C77 AC 77 46 ldy GAME1NML ; then just fetch it + 5794 [01] ELSE + 5795 ldy #GAME1NAMEL ; get length of string + 5796 [00] ENDIF + 5797 5C7A 20 6B 4C jsr DLINE ; print the string + 5798 5C7D .MACEND + Wed May 24 1989 15:00 Page 85 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5799 5C7D 4C 8A 5C jmp VERDB2 + 5800 5C80 VERDB1: + 5801 5C80 DLINE GAME2NAME,GAME2NML ; 2,3 are in another + 5802 5C80 A2 8A ldx #GAME2NAME ; get other part of string + 5804 [01] IFMA 2 ; check to see if length passed in + 5805 5C84 AC 89 46 ldy GAME2NML ; then just fetch it + 5806 [01] ELSE + 5807 ldy #GAME2NAMEL ; get length of string + 5808 [00] ENDIF + 5809 5C87 20 6B 4C jsr DLINE ; print the string + 5810 5C8A .MACEND + 5811 5C8A VERDB2: + 5812 5C8A EE B0 5B inc ZVFLAG ; show bad file + 5813 5C8D 20 DB 8C jsr GETRET ; just wait for + 5814 5C90 VERDX: + 5815 5C90 60 rts ; all done + 5816 ; + 5817 ; VERIFY_PICD - verify the picture data in a file. First check to see if + 5818 ; there is any. If so, seek to it, set J==0 to show VERIFY_FILE to read + 5819 ; til EOF, and print out bad picture data message if necessary. + 5820 ; + 5821 5C91 VERIFY_PICD: + 5822 5C91 A9 FF lda #$FF ; gonna zero bunch of stuff + 5823 5C93 85 7B sta J+HI ; and the counter + 5824 5C95 85 7A sta J+LO ; which means now goto EOF + 5825 5C97 A0 02 ldy #SGTPICOF ; fetch the picture data offset + 5826 5C99 B1 1E lda (DSEGS),Y ; get MSB + 5827 5C9B 8D E0 45 sta PSEEK+SM_FPOS+2 ; we are doing pages + 5828 5C9E C8 iny ; pointing to LSB + 5829 5C9F 11 1E ora (DSEGS),Y ; first, check for all zeros + 5830 5CA1 D0 01 bne VERP1 ; nope, some picture data is there + 5831 5CA3 60 rts ; just gwon back if nothing here + 5832 5CA4 VERP1: + 5833 5CA4 B1 1E lda (DSEGS),Y ; go get LSB + 5834 5CA6 0A asl A ; *2 to get 256 byte pages + 5835 5CA7 8D DF 45 sta PSEEK+SM_FPOS+1 ; put away here + 5836 5CAA 2E E0 45 rol PSEEK+SM_FPOS+2 ; pick up carry + 5837 5CAD A9 10 lda #PHSIZE ; skip over header of file + 5838 5CAF 85 78 sta STARTPOS ; show offset in first block + 5839 5CB1 VERP11: + 5840 5CB1 SET_MARK PSEEK ; and move to picture data spot + 5841 5CB1 PRODOS $CE, PSEEK + 5842 5CB1 20 00 BF jsr $BF00 ; ProDOS handler + 5843 5CB4 CE DB $CE ; ProDOS function code + 5844 5CB5 DC45 DW PSEEK ; Function Parameter Block address + 5845 5CB7 .MACEND + 5846 5CB7 .MACEND + 5847 5CB7 20 E1 5C jsr VERIFY_FILE ; read in the data + 5848 5CBA SET_MARK PSEEK ; get back to beginning of pic data + 5849 5CBA PRODOS $CE, PSEEK + 5850 5CBA 20 00 BF jsr $BF00 ; ProDOS handler + 5851 5CBD CE DB $CE ; ProDOS function code + 5852 5CBE DC45 DW PSEEK ; Function Parameter Block address + 5853 5CC0 .MACEND + 5854 5CC0 .MACEND + 5855 5CC0 READ READ_PB ; read in a block worth + 5856 5CC0 PRODOS $CA, READ_PB + 5857 5CC0 20 00 BF jsr $BF00 ; ProDOS handler + 5858 5CC3 CA DB $CA ; ProDOS function code + 5859 5CC4 CE45 DW READ_PB ; Function Parameter Block address + 5860 5CC6 .MACEND + 5861 5CC6 .MACEND + 5862 5CC6 AD 0A 08 lda IOBUFF+PHCHKS ; get MSB of picture checksum + 5863 5CC9 C5 7F cmp L+HI ; same as what we got? + 5864 5CCB D0 07 bne VERPB ; nope + 5865 5CCD AD 0B 08 lda IOBUFF+PHCHKS+1 ; get LSB of picture checksum + 5866 5CD0 C5 7E cmp L+LO ; same as mine? + 5867 5CD2 F0 0C beq VERPX ; yup, checked out fine + 5868 5CD4 VERPB: + 5869 5CD4 DLINE VERPBAD ; picture data bad + 5870 5CD4 A2 8E ldx #VERPBAD ; get other part of string + 5872 [01] IFMA 2 ; check to see if length passed in + 5873 ldy ; then just fetch it + Wed May 24 1989 15:00 Page 86 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5874 [01] ELSE + 5875 5CD8 A0 22 ldy #VERPBADL ; get length of string + 5876 [00] ENDIF + 5877 5CDA 20 6B 4C jsr DLINE ; print the string + 5878 5CDD .MACEND + 5879 5CDD 4C 6C 5C jmp VER_FMSG ; print out file name + 5880 5CE0 VERPX: + 5881 5CE0 60 rts ; tootis finis + 5882 ; + 5883 ; VERIFY_FILE - Files is already open and pointing to start of checksummed + 5884 ; data. Works along til J == 0 or EOF, which ever comes first. Starts by + 5885 ; dec'ing J, so if J starts as 0, effectively means goto EOF. + 5886 ; + 5887 5CE1 VERIFY_FILE: + 5888 5CE1 A9 00 lda #0 ; clear out checksum counter + 5889 5CE3 85 7F sta L+HI ; MSB + 5890 5CE5 85 7E sta L+LO ; LSB + 5891 5CE7 8D D2 45 sta READ_PB+RD_BUFFLEN+LO + 5892 5CEA A9 04 lda #4 ; make read read $400 (1Kb) + 5893 5CEC 8D D3 45 sta READ_PB+RD_BUFFLEN+HI + 5894 5CEF VFLOOP: + 5895 5CEF A9 03 lda #RETRY_COUNT ; and set up retry count + 5896 5CF1 85 16 sta RETRIES + 5897 5CF3 A9 00 lda #IOBUFF ; reading all the data + 5900 5CF9 85 7D sta K+HI ; into, using as pointer + 5901 5CFB VFLRD: + 5902 5CFB READ READ_PB ; read in 1Kb of data + 5903 5CFB PRODOS $CA, READ_PB + 5904 5CFB 20 00 BF jsr $BF00 ; ProDOS handler + 5905 5CFE CA DB $CA ; ProDOS function code + 5906 5CFF CE45 DW READ_PB ; Function Parameter Block address + 5907 5D01 .MACEND + 5908 5D01 .MACEND + 5909 5D01 90 0D bcc VERF0 ; just fine read + 5910 5D03 C9 4C cmp #$4C ; EOF error? + 5911 5D05 F0 32 beq VFCHECK ; yes, so wee bee done + 5912 5D07 C9 4D cmp #$4D ; InfoDOS EOF error? + 5913 5D09 F0 2E beq VFCHECK ; ayyup + 5914 5D0B 20 07 47 jsr RETRY ; check about retrying + 5915 5D0E 90 EB bcc VFLRD ; and do again + 5916 5D10 VERF0: + 5917 5D10 A5 7A lda J+LO ; count the block to be read + 5918 5D12 D0 06 bne VERF1 ; no wrapping + 5919 5D14 A5 7B lda J+HI ; anything left? + 5920 5D16 F0 21 beq VFCHECK ; nope, all done then + 5921 5D18 C6 7B dec J+HI ; count one block + 5922 5D1A VERF1: + 5923 5D1A C6 7A dec J+LO ; count block + 5924 5D1C A4 78 ldy STARTPOS ; and begin + 5925 5D1E VERF2: + 5926 5D1E B1 7C lda (K),Y ; get byte + 5927 5D20 18 clc ; doing add + 5928 5D21 65 7E adc L+LO ; add it in + 5929 5D23 85 7E sta L+LO ; save it + 5930 5D25 90 02 bcc VERF3 ; no wrap + 5931 5D27 E6 7F inc L+HI ; yes ther is + 5932 5D29 VERF3: + 5933 5D29 C8 iny ; next byte + 5934 5D2A D0 F2 bne VERF2 ; back to start of inner tloop + 5935 + 5936 5D2C A9 00 lda #0 ; start at first byte + 5937 5D2E 85 78 sta STARTPOS ; okay + 5938 5D30 E6 7D inc K+HI ; point to next block + 5939 5D32 CE D5 45 dec READ_PB+RD_LENGTH+HI ; count this one + 5940 5D35 F0 B8 beq VFLOOP ; go read some more + 5941 5D37 D0 D7 bne VERF0 ; go do next 256 byte block + 5942 5D39 VFCHECK: + 5943 5D39 A0 00 ldy #SGTCHKS ; get check sum + 5944 5D3B A5 7F lda L+HI ; start with MSB + 5945 5D3D D1 1E cmp (DSEGS),Y ; well . . . ? + 5946 5D3F D0 09 bne VFBAD ; nope, it is wrong + 5947 5D41 C8 iny ; first byte is okay + 5948 5D42 A5 7E lda L+LO ; so check LSB + Wed May 24 1989 15:00 Page 87 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- VERIFY CODE ---" + + 5949 5D44 D1 1E cmp (DSEGS),Y ; well . . . ? + 5950 5D46 D0 02 bne VFBAD ; die a slow ugly death + 5951 5D48 18 clc ; clear carry to show niceness + 5952 5D49 60 rts + 5953 5D4A VFBAD: + 5954 5D4A 38 sec ; carry is set if bad + 5955 5D4B 60 rts ; and return to your fate + 5956 ; + 5957 ; SETUP_DISK0 - this routine does some special processing to get the file + 5958 ; pointer to the beginning of data for the preload file. It skips over + 5959 ; segment table. + 5960 5D4C SETUP_DISK0: + 5961 5D4C READ READ_PB ; read in first block + 5962 5D4C PRODOS $CA, READ_PB + 5963 5D4C 20 00 BF jsr $BF00 ; ProDOS handler + 5964 5D4F CA DB $CA ; ProDOS function code + 5965 5D50 CE45 DW READ_PB ; Function Parameter Block address + 5966 5D52 .MACEND + 5967 5D52 .MACEND + 5968 5D52 AD 00 08 lda IOBUFF ; MSB of segment table size (in words) + 5969 5D55 8D DF 45 sta PSEEK+SM_FPOS+1 ; middle part of offset + 5970 5D58 AD 01 08 lda IOBUFF+1 ; LSB of size + 5971 5D5B 0A asl A ; *2 to pick up carry + 5972 5D5C 2E DF 45 rol PSEEK+SM_FPOS+1 ; rotate in carry + 5973 5D5F 2E E0 45 rol PSEEK+SM_FPOS+2 ; and once more + 5974 5D62 A8 tay ; check for wrapping upwards + 5975 5D63 F0 08 beq STD01 ; no wrap up then + 5976 5D65 STD00: + 5977 5D65 EE DF 45 inc PSEEK+SM_FPOS+1 ; wee did + 5978 5D68 D0 03 bne STD01 ; no more wrapping + 5979 5D6A EE E0 45 inc PSEEK+SM_FPOS+2 ; yes there is + 5980 5D6D STD01: + 5981 5D6D AD DF 45 lda PSEEK+SM_FPOS+1 ; make sure it is a 512 byte page + 5982 5D70 29 01 and #$1 ; even page? + 5983 5D72 D0 F1 bne STD00 ; inc again, please + 5984 5D74 STD0X: + 5985 5D74 SET_MARK PSEEK ; skip the segment table stuff + 5986 5D74 PRODOS $CE, PSEEK + 5987 5D74 20 00 BF jsr $BF00 ; ProDOS handler + 5988 5D77 CE DB $CE ; ProDOS function code + 5989 5D78 DC45 DW PSEEK ; Function Parameter Block address + 5990 5D7A .MACEND + 5991 5D7A .MACEND + 5992 5D7A 60 rts ; all done + 5993 + 5994 5D7B END + 5995 + 5996 5D7B INCLUDE SCREEN.ASM + 5997 5D7B STTL "--- APPLE ][ SCREEN STUFF ---" + 5998 PAGE + Wed May 24 1989 15:00 Page 88 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 5999 + 6000 ; ----------------- + 6001 ; PRINT CHAR IN [A] AT CV,CH + 6002 ; ----------------- + 6003 ; + 6004 ; uses memory register [L] + 6005 ; + 6006 5D7B 00 SAVECY DB 0 ; spot to save current screen y pos + 6007 5D7C 00 SAVECX DB 0 ; spot for x pos + 6008 + 6009 5D7D CHAR: + 6010 5D7D 85 AC sta IOCHAR ; SAVE HERE + 6011 5D7F 8A txa ; SAVE [X] AND [Y] + 6012 5D80 48 pha + 6013 5D81 98 tya + 6014 5D82 48 pha + 6015 5D83 + 6016 5D83 A5 AC lda IOCHAR ; get it back + 6017 5D85 C9 08 cmp #BACKSPACE ; is it backspace with erase? + 6018 5D87 D0 03 bne CHCX ; nope + 6019 + 6020 5D89 4C AB 5E jmp DO_BSPC ; so handle backspace + 6021 5D8C CHCX: + 6022 5D8C C9 0D cmp #EOL ; is it ? + 6023 5D8E D0 03 bne CHCONT ; just let dline handle it + 6024 5D90 + 6025 5D90 4C 78 5E jmp DO_EOL ; handle + 6026 ; + 6027 ; so save some stuff and do all the necessary figgering + 6028 ; + 6029 5D93 CHCONT: + 6030 5D93 AE DF 71 ldx SCRCNT ; just stash character + 6031 5D96 9D 80 02 sta SCRBUFF,X ; save it + 6032 5D99 EE DF 71 inc SCRCNT ; and count it + 6033 5D9C CH_EXIT: + 6034 5D9C 68 pla ; RESTORE [X] AND [Y] + 6035 5D9D A8 tay + 6036 5D9E 68 pla + 6037 5D9F AA tax + 6038 5DA0 60 rts + 6039 ; + 6040 ; PUT_NYBBLE - put 4 bits to the screen at SCRCX, SCRCY (the lower 4 bits + 6041 ; in [A]). + 6042 ; + 6043 5DA1 PUT_NYBBLE: + 6044 5DA1 85 0E sta NY_DATA ; save [A] for mucking with + 6045 5DA3 20 4C 5E jsr SETPOS ; set up offsets using SCRCX + 6046 + 6047 5DA6 A9 08 lda #$8 ; start at first bit, left to right + 6048 5DA8 85 10 sta DATALOOP ; and init the counter with it + 6049 5DAA PNY0: + 6050 5DAA A6 8E ldx FPCBNK ; which bank + 6051 5DAC BD 54 C0 lda PAGE2SW,X ; select it + 6052 5DAF A0 00 ldy #0 ; start with zero + 6053 5DB1 B1 8C lda (FPC),Y ; get it + 6054 5DB3 85 13 sta SCR_DATA ; and save it + 6055 5DB5 PNY1: + 6056 5DB5 A6 11 ldx BITOFF ; get which interesting bit we want + 6057 5DB7 BD 04 5E lda GT_BITS,X ; get bit + 6058 5DBA 48 pha ; save bit pictures + 6059 5DBB A5 10 lda DATALOOP ; see if we have done all 4 bits in this 'pixel' + 6060 5DBD F0 29 beq PNY_EXIT ; toots finis + 6061 5DBF 46 10 lsr DATALOOP ; point to next bit + 6062 5DC1 24 0E bit NY_DATA ; is this bit set? + 6063 5DC3 D0 08 bne PNY_SET ; yes it is, so we will handle different + 6064 ; + 6065 ; Bit is clear, so clear appropriate one in the SCR_DATA byte + 6066 ; + 6067 5DC5 68 pla ; get bit picture back + 6068 5DC6 49 FF eor #$FF ; turn bits all around + 6069 5DC8 25 13 and SCR_DATA ; turn off bit in screen data + 6070 5DCA 4C D0 5D jmp PNY_NEXT ; and continue + 6071 5DCD PNY_SET: + 6072 5DCD 68 pla ; get bit mask back + 6073 5DCE 05 13 ora SCR_DATA ; turn on bit + Wed May 24 1989 15:00 Page 89 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6074 5DD0 PNY_NEXT: + 6075 5DD0 85 13 sta SCR_DATA ; save result + 6076 5DD2 E6 11 inc BITOFF ; we're looking at next bit + 6077 5DD4 A5 11 lda BITOFF ; now check how we're doing + 6078 5DD6 C9 07 cmp #7 ; only doing bits 0-6 + 6079 5DD8 D0 DB bne PNY1 ; check next bit + 6080 ; + 6081 ; we've finished this byte in screen memory, point to next one + 6082 ; + 6083 5DDA A9 00 lda #0 ; start at zero'th bit + 6084 5DDC 85 11 sta BITOFF ; thank you + 6085 5DDE A5 13 lda SCR_DATA ; now stash this one in the screen + 6086 5DE0 91 8C sta (FPC),Y ; y is still zero; still pointing to bank + 6087 5DE2 20 F1 5D jsr NEXT_SCR ; make SPC/FPC point to next spot + 6088 5DE5 4C AA 5D jmp PNY0 ; and continue on please + 6089 ; + 6090 ; all done, so make sure we stash anything out there + 6091 ; + 6092 5DE8 PNY_EXIT: + 6093 5DE8 68 pla ; get bit mask back to fix stack + 6094 5DE9 A5 13 lda SCR_DATA ; put away the current data byte + 6095 5DEB 91 8C sta (FPC),Y ; y is still zero; still pointing to bank + 6096 5DED AD 54 C0 lda PAGE2SW+MAIN ; back to MAIN page 2 + 6097 5DF0 60 rts + 6098 ; + 6099 ; NEXT_SCR - make FPC/SPC point to next screen byte + 6100 ; + 6101 5DF1 NEXT_SCR: + 6102 ; + 6103 ; if in main bank, when we go to aux bank, we need to look at the next + 6104 ; byte in memory + 6105 ; + 6106 5DF1 A5 8E lda FPCBNK ; get what bank we're talking to currently + 6107 5DF3 D0 08 bne NXS0 ; 0 = main bank, 1 = aux bank + 6108 5DF5 E6 8F inc SPCL ; point to next byte + 6109 5DF7 E6 8C inc FPCL ; and for fetching + 6110 5DF9 A9 01 lda #AUX ; and point to aux bank + 6111 5DFB D0 02 bne NXS1 ; (BRANCH) and continue on + 6112 ; + 6113 ; if in aux bank, all we need to do is switch banks + 6114 ; + 6115 5DFD NXS0: + 6116 5DFD A9 00 lda #MAIN ; just make it main bank + 6117 5DFF NXS1: + 6118 5DFF 85 91 sta SPCBNK ; for stashing and + 6119 5E01 85 8E sta FPCBNK ; fetching + 6120 5E03 60 rts + 6121 ; + 6122 ; GET_NYBBLE - get the 4 bits which represent the screen at position + 6123 ; SCRCX, SCRCY; return nybble in low 4 bits of [A] + 6124 ; + 6125 5E04 01 02 04 08 10 GT_BITS: db 1,2,4,8,$10,$20,$40 + 5E09 20 40 + 6126 5E0B GET_NYBBLE: + 6127 5E0B 20 4C 5E jsr SETPOS ; set up offsets using SCRCX + 6128 + 6129 5E0E A9 00 lda #0 ; clear out my data spot + 6130 5E10 85 0E sta NY_DATA ; for mucking with + 6131 + 6132 5E12 A9 10 lda #$10 ; setting bits 0-3, starting with shift + 6133 5E14 85 10 sta DATALOOP ; so init the setter + 6134 5E16 GNY0: + 6135 5E16 A6 8E ldx FPCBNK ; which bank + 6136 5E18 BD 54 C0 lda PAGE2SW,X ; save which bank + 6137 5E1B A0 00 ldy #0 ; zero y + 6138 5E1D B1 8C lda (FPC),Y ; get byte + 6139 5E1F 85 13 sta SCR_DATA ; and save it + 6140 5E21 GNY1: + 6141 5E21 46 10 lsr DATALOOP ; see if we have done all 4 bits in this 'pixel' + 6142 5E23 F0 21 beq GNY_EXIT ; all done! + 6143 + 6144 5E25 A6 11 ldx BITOFF ; get bit offset + 6145 5E27 BD 04 5E lda GT_BITS,X ; get bit pattern + 6146 ; + 6147 ; now check appropriate bit in Screen Data + Wed May 24 1989 15:00 Page 90 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6148 ; + 6149 5E2A 25 13 and SCR_DATA ; see if it is set + 6150 5E2C F0 06 beq GNY3 ; no bit set here + 6151 ; + 6152 ; bit is set, so set it in my data nybble + 6153 ; + 6154 5E2E A5 10 lda DATALOOP ; get bit setter + 6155 5E30 05 0E ora NY_DATA ; and put it into my data byte + 6156 5E32 85 0E sta NY_DATA ; and save it + 6157 5E34 GNY3: + 6158 5E34 E6 11 inc BITOFF ; we're looking at next bit + 6159 5E36 A5 11 lda BITOFF ; now check how we're doing + 6160 5E38 C9 07 cmp #7 ; only doing bits 0-6 + 6161 5E3A D0 E5 bne GNY1 ; check next bit + 6162 ; + 6163 ; we've finished this byte in screen memory, point to next one + 6164 ; + 6165 5E3C A9 00 lda #0 ; start at zero'th bit + 6166 5E3E 85 11 sta BITOFF ; thank you + 6167 5E40 20 F1 5D jsr NEXT_SCR ; point to next byte + 6168 5E43 4C 16 5E jmp GNY0 ; and continue on please + 6169 5E46 GNY_EXIT: + 6170 5E46 AD 54 C0 lda PAGE2SW+MAIN ; back to main page 2 + 6171 5E49 A5 0E lda NY_DATA ; get the nybble desired + 6172 5E4B 60 rts + 6173 ; + 6174 ; SETPOS - get the byte offset and the bit offset from the table using + 6175 ; SCRCX + 6176 ; + 6177 ; USES: SCRCX, SCRCY + 6178 ; SETS: FPC - pointer to correct screen memory location + 6179 ; BITOFF - bit offset to get to start of byte (N.B. this is left to + 6180 ; right count, while in memory it is right to left!) + 6181 5E4C SETPOS: + 6182 5E4C A5 00 lda SCRCX ; get the x pos + 6183 5E4E AA tax ; put where we can use it + 6184 5E4F BD 52 03 lda XPOSTBL,X ; get byte # + 6185 5E52 85 8C sta FPCL ; okay, saved + 6186 5E54 BD B2 6B lda XBITTBL,X ; get bitoffset + 6187 5E57 85 11 sta BITOFF ; where it wants it + 6188 + 6189 5E59 A5 8C lda FPCL ; check for correct bank + 6190 5E5B 29 01 and #$01 ; if odd, then must be main bank + 6191 5E5D D0 04 bne STP11 ; okay, it be odd + 6192 5E5F A9 01 lda #AUX ; aux bank + 6193 5E61 D0 02 bne STP22 ; jump + 6194 5E63 STP11: + 6195 5E63 A9 00 lda #MAIN ; main bank + 6196 5E65 STP22: + 6197 5E65 85 8E sta FPCBNK ; save it + 6198 5E67 A5 8C lda FPCL ; get for fetch + 6199 5E69 4A lsr A ; /2 to get correct byte offset + 6200 5E6A A6 01 ldx SCRCY ; get vertical pos + 6201 5E6C 18 clc ; get ready for adding + 6202 5E6D 7D 32 6A adc BASEL,X ; add low part + 6203 5E70 85 8C sta FPCL ; save low part + 6204 5E72 BD F2 6A lda BASEH,X ; get high part + 6205 5E75 85 8D sta FPCH ; save high part + 6206 5E77 60 rts ; done !? + 6207 ; + 6208 ; DO_EOL - if this is end of line, check if we are at end of window + 6209 ; and if we are, and it is a scrollable window, scroll. Then move + 6210 ; the cursor to the left margin of said window + 6211 ; + 6212 5E78 DO_EOL: + 6213 5E78 20 EC 71 jsr DISP_LINE ; make sure line gets out there + 6214 5E7B A5 01 lda SCRCY ; get current vertical pos + 6215 5E7D 18 clc ; add font height + 6216 5E7E 69 09 adc #FONT_H ; thank you + 6217 5E80 48 pha ; save this position + 6218 5E81 69 09 adc #FONT_H ; make sure we have room for characters here + 6219 5E83 C5 02 cmp SCRBTM ; so check against the bottom + 6220 5E85 F0 02 beq SAVECV ; no scroll yet + 6221 5E87 B0 05 bcs SCROLLCITY ; nope, can't use it + 6222 5E89 SAVECV: + Wed May 24 1989 15:00 Page 91 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6223 5E89 68 pla ; get new CV + 6224 5E8A 85 01 sta SCRCY ; and save it + 6225 5E8C D0 09 bne DEL1 ; JUMP + 6226 5E8E SCROLLCITY: + 6227 5E8E 68 pla ; get bad y pos + 6228 5E8F AD D7 71 lda SCRLFLG ; is this a scrolling window? + 6229 5E92 F0 03 beq DEL1 ; nope, just move to left edge + 6230 5E94 20 E8 5F jsr SCROLL_UP ; and scroll window + 6231 5E97 DEL1: + 6232 ; + 6233 ; move cursor back to left margin + 6234 ; + 6235 5E97 A5 04 lda LEFTMRG ; get left margin + 6236 5E99 85 00 sta SCRCX ; and set itpositions + 6237 5E9B A9 01 lda #1 ; show cursor changed (maybe) + 6238 5E9D 8D 77 6C sta CURSFLG ; okay + 6239 5EA0 A9 00 lda #0 ; clear length too + 6240 5EA2 85 A7 sta LENGTH+LO ; no more on line + 6241 5EA4 85 A8 sta LENGTH+HI ; no more on line + 6242 5EA6 4C 9C 5D jmp CH_EXIT ; now finish it up + 6243 ; + 6244 ; DO_BSPC - do a backspace, by erasing char just before cursor to + 6245 ; background color, and moving cursor back one space + 6246 ; [X] == character to delete + 6247 ; + 6248 5EA9 0000 SAVECHX: DW 0 + 6249 + 6250 5EAB DO_BSPC: + 6251 5EAB AD D3 71 lda CHR_X+LO ; figger new CHR_X + 6252 5EAE 38 sec ; subtract width + 6253 5EAF A4 C1 ldy FONTFLG ; get which font we be using + 6254 5EB1 F0 05 beq DOBSP0 ; must be variable width + 6255 5EB3 E9 0C sbc #MONOFONT_W ; get width then of mono font + 6256 5EB5 4C BB 5E jmp DOBSP1 ; okay, now do add + 6257 5EB8 DOBSP0: + 6258 5EB8 FD 25 64 sbc CHWID,X ; get width of char to be erased + 6259 5EBB DOBSP1: + 6260 5EBB 8D D3 71 sta CHR_X+LO ; show new one + 6261 5EBE 8D A9 5E sta SAVECHX+LO ; save to restore later + 6262 5EC1 AD D4 71 lda CHR_X+HI ; and pick up carry + 6263 5EC4 E9 00 sbc #0 ; okay, did it + 6264 5EC6 8D D4 71 sta CHR_X+HI ; save it + 6265 5EC9 8D AA 5E sta SAVECHX+HI ; okay + 6266 5ECC A0 20 ldy #SPACE ; get SPACE offset + 6267 5ECE A5 C1 lda FONTFLG ; monospaced font? + 6268 5ED0 F0 04 beq DOBSP2 ; nope + 6269 5ED2 A9 0C lda #MONOFONT_W ; make monospaced wide + 6270 5ED4 D0 03 bne DOBSP3 ; fine + 6271 5ED6 DOBSP2: + 6272 5ED6 BD 25 64 lda CHWID,X ; get width of char + 6273 5ED9 DOBSP3: + 6274 5ED9 99 25 64 sta CHWID,Y ; set space to be this wide + 6275 5EDC 8C 80 02 sty SCRBUFF ; make space for erasing + 6276 5EDF A9 01 lda #1 ; show one char + 6277 5EE1 8D DF 71 sta SCRCNT ; assume it used to be zero + 6278 5EE4 20 EC 71 jsr DISP_LINE ; put that space out + 6279 5EE7 AD A9 5E lda SAVECHX+LO ; restore old/new x pos + 6280 5EEA 8D D3 71 sta CHR_X+LO + 6281 5EED AD AA 5E lda SAVECHX+HI + 6282 5EF0 8D D4 71 sta CHR_X+HI + 6283 5EF3 20 85 73 jsr GET_SCRCX ; update SCRCX please + 6284 + 6285 5EF6 A9 08 lda #SPACE_WIDTH ; restore width of space char + 6286 5EF8 A0 20 ldy #SPACE ; get offset + 6287 5EFA 99 25 64 sta CHWID,Y ; okay + 6288 + 6289 5EFD 4C 9C 5D jmp CH_EXIT ; done + 6290 ; + 6291 ; CLS - clear the window, using CLS parameters + 6292 ; + 6293 5F00 CLS: + 6294 5F00 A5 00 lda SCRCX ; save the current X,Y + 6295 5F02 8D 7C 5D sta SAVECX ; x + 6296 5F05 A5 01 lda SCRCY + 6297 5F07 8D 7B 5D sta SAVECY ; saved + Wed May 24 1989 15:00 Page 92 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6298 5F0A A5 0B lda CLSTOP ; get top line + 6299 5F0C 85 01 sta SCRCY ; and set up a y pos + 6300 + 6301 5F0E 20 BC 5F jsr SETMASK ; set up masks and ending point + 6302 + 6303 5F11 A5 BD lda CPY_COUNT ; get count + 6304 5F13 85 14 sta SH_LOOP ; save count + 6305 5F15 A5 0A lda CLSLEFT ; get left edge + 6306 5F17 85 00 sta SCRCX ; set up as X pos + 6307 5F19 A0 0E ldy #WINBGND ; get background offset + 6308 5F1B B1 05 lda (WINDOW),Y ; get background color + 6309 5F1D 85 71 sta ARG8 ; save it here + 6310 5F1F A5 0C lda CLSWIDTH ; how wide we be? + 6311 5F21 D0 05 bne CLSOKAY ; not a zero width + 6312 5F23 A9 19 lda #25 ; zero can't do zero width + 6313 5F25 4C 0A 52 jmp ZERROR ; so die + 6314 5F28 CLSOKAY: + 6315 5F28 C9 03 cmp #3 ; if skinny, handle special + 6316 5F2A B0 28 bcs L1L0 ; nope + 6317 5F2C 85 6F sta ARG7 ; make this be the counter + 6318 5F2E A5 0D lda CLSHEIGHT ; just use PUT/GET NYBBLE if only one wide + 6319 5F30 D0 05 bne CLSOKAY1 ; not a zero height either + 6320 5F32 A9 19 lda #25 ; bad error + 6321 5F34 4C 0A 52 jmp ZERROR + 6322 5F37 CLSOKAY1: + 6323 5F37 85 7A sta J ; save here + 6324 5F39 CLS1W: + 6325 5F39 A5 71 lda ARG8 ; get color + 6326 5F3B 20 A1 5D jsr PUT_NYBBLE ; put it + 6327 5F3E E6 00 inc SCRCX ; next x + 6328 5F40 C6 6F dec ARG7 ; counter + 6329 5F42 D0 F5 bne CLS1W ; do next X + 6330 5F44 A5 0A lda CLSLEFT ; get left edge again + 6331 5F46 85 00 sta SCRCX ; point to it + 6332 5F48 E6 01 inc SCRCY ; next line + 6333 5F4A A5 0C lda CLSWIDTH ; restore width count + 6334 5F4C 85 6F sta ARG7 ; thanks + 6335 5F4E C6 7A dec J ; count + 6336 5F50 D0 E7 bne CLS1W ; do it + 6337 5F52 F0 56 beq CLSEXIT ; all done then + 6338 5F54 L1L0: + 6339 5F54 85 7A sta J ; use j as counter + 6340 5F56 L1L: + 6341 5F56 A5 71 lda ARG8 ; a color please + 6342 5F58 20 A1 5D jsr PUT_NYBBLE ; do first line easy + 6343 5F5B E6 00 inc SCRCX ; next nybble + 6344 5F5D C6 7A dec J ; done yet? + 6345 5F5F D0 F5 bne L1L ; nope + 6346 + 6347 5F61 A5 0A lda CLSLEFT ; where is left column + 6348 5F63 85 00 sta SCRCX ; here! + 6349 5F65 20 4C 5E jsr SETPOS ; get the address + 6350 5F68 20 73 90 jsr FP2SP ; SPC is source PC, now! + 6351 5F6B A5 0D lda CLSHEIGHT ; how many lines are we clearing + 6352 5F6D D0 05 bne CLSOKAY2 ; not a zero height either + 6353 5F6F A9 19 lda #25 ; bad error + 6354 5F71 4C 0A 52 jmp ZERROR + 6355 5F74 CLSOKAY2: + 6356 5F74 85 7A sta J ; j is counter again + 6357 5F76 C6 7A dec J ; already cleared one line + 6358 5F78 F0 30 beq CLSEXIT ; only one line to do! + 6359 5F7A CLSLOOP: + 6360 5F7A A5 90 lda SPCH ; now, modify COPY_LINE + 6361 5F7C 8D 7D 1D sta CPY_MOD1_SRC+HI + 6362 5F7F 8D A1 1D sta CPY_MOD2_SRC+HI + 6363 5F82 A5 8F lda SPCL + 6364 5F84 8D 7C 1D sta CPY_MOD1_SRC+LO + 6365 5F87 8D A0 1D sta CPY_MOD2_SRC+LO + 6366 5F8A E6 01 inc SCRCY ; clear this line + 6367 5F8C 20 4C 5E jsr SETPOS ; where am i? + 6368 5F8F A5 8D lda FPCH ; now, modify COPY_LINE + 6369 5F91 8D 80 1D sta CPY_MOD1_DST+HI + 6370 5F94 8D A4 1D sta CPY_MOD2_DST+HI + 6371 5F97 A5 8C lda FPCL + 6372 5F99 8D 7F 1D sta CPY_MOD1_DST+LO + Wed May 24 1989 15:00 Page 93 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6373 5F9C 8D A3 1D sta CPY_MOD2_DST+LO + 6374 5F9F A5 14 lda SH_LOOP ; get count + 6375 5FA1 85 BD sta CPY_COUNT ; and save it + 6376 5FA3 20 50 1D jsr COPY_LINE ; did the copy (i hope) + 6377 5FA6 C6 7A dec J ; count it + 6378 5FA8 D0 D0 bne CLSLOOP ; next one please + 6379 5FAA CLSEXIT: + 6380 5FAA AD 7C 5D lda SAVECX ; get X,Y back + 6381 5FAD 85 00 sta SCRCX ; got it + 6382 5FAF AD 7B 5D lda SAVECY ; now for y + 6383 5FB2 85 01 sta SCRCY ; restored! + 6384 + 6385 5FB4 60 rts + 6386 ; + 6387 ; SETMASK - figger out the start and end masks, as well as setting + 6388 ; stuff to point to stopping address. Use CLSLEFT and CLSWIDTH + 6389 ; + 6390 5FB5 00 01 03 07 0F ST_BITS: db 0,1,3,7,$f,$1f,$3f + 5FBA 1F 3F + 6391 5FBC SETMASK: + 6392 5FBC A5 0A lda CLSLEFT ; munge with SCRX + 6393 5FBE 85 00 sta SCRCX ; okay + 6394 5FC0 20 4C 5E jsr SETPOS ; get me the bit offset of start + 6395 + 6396 5FC3 A6 11 ldx BITOFF ; now set up mask + 6397 5FC5 BD B5 5F lda ST_BITS,X ; get the bit pattern + 6398 5FC8 85 1A sta STMASK ; save it + 6399 + 6400 5FCA A5 0A lda CLSLEFT ; get left edge again + 6401 5FCC 18 clc ; add width + 6402 5FCD 65 0C adc CLSWIDTH ; to get where to stop + 6403 5FCF AA tax ; make index + 6404 5FD0 86 00 stx SCRCX ; set cur pos + 6405 5FD2 BD 52 03 lda XPOSTBL,X ; get how many bytes + 6406 5FD5 A6 0A ldx CLSLEFT ; subtract from byte offset of start + 6407 5FD7 38 sec ; subbing + 6408 5FD8 FD 52 03 sbc XPOSTBL,X + 6409 5FDB 85 BD sta CPY_COUNT ; and save it + 6410 + 6411 5FDD 20 4C 5E jsr SETPOS ; so get its address + 6412 + 6413 5FE0 A6 11 ldx BITOFF ; get bit offset + 6414 5FE2 BD B5 5F lda ST_BITS,X ; get pattern + 6415 5FE5 85 1B sta ENDMASK ; okay! + 6416 5FE7 60 rts + 6417 ; + 6418 ; SCROLL_UP - roll the current window by FONT_H lines + 6419 ; + 6420 5FE8 SCROLL_UP: + 6421 5FE8 A9 09 lda #FONT_H ; show one line + 6422 5FEA 85 18 sta SCLLINES ; done + 6423 5FEC 85 1D sta SCLDIR ; show scroll up with positive number + 6424 5FEE A0 00 ldy #WINTOP ; get top of screen + 6425 5FF0 B1 05 lda (WINDOW),Y ; got it + 6426 5FF2 85 0B sta CLSTOP ; saved it + 6427 5FF4 C8 iny ; point to left edge + 6428 5FF5 B1 05 lda (WINDOW),Y ; get left edge + 6429 5FF7 85 0A sta CLSLEFT ; save + 6430 5FF9 C8 iny ; this is now the height + 6431 5FFA B1 05 lda (WINDOW),Y ; get window height + 6432 5FFC 85 0D sta CLSHEIGHT ; show me + 6433 5FFE C8 iny ; and now for the width + 6434 5FFF B1 05 lda (WINDOW),Y ; get width + 6435 6001 85 0C sta CLSWIDTH ; saved it + 6436 ; so fall thru + 6437 ; and do the scrolling + 6438 ; FALLING THRU + 6439 ; | + 6440 ; \ / + 6441 ; + 6442 ; + 6443 ; DO_SCROLL - scroll SCLLINES withing the window as defined by + 6444 ; CLSLEFT,TOP,WIDTH, and HEIGHT + 6445 ; + 6446 6003 DO_SCROLL: + Wed May 24 1989 15:00 Page 94 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6447 6003 A5 00 lda SCRCX ; save the current X,Y + 6448 6005 8D 7C 5D sta SAVECX ; x + 6449 6008 A5 01 lda SCRCY + 6450 600A 8D 7B 5D sta SAVECY ; saved + 6451 600D A5 18 lda SCLLINES ; how many lines? + 6452 + 6453 600F A6 1D ldx SCLDIR ; which direction? + 6454 6011 10 04 bpl SC1 ; >0 means scroll up + 6455 ; + 6456 ; scroll down, so we are going to start at the bottom and copy downwards + 6457 ; until we reach the top + 6458 ; + 6459 ; now modify code so we do adds to get destination line and subtracts + 6460 ; to get new src line + 6461 ; + 6462 6013 A0 C6 ldy #$C6 ; 'dec' opcode + 6463 6015 D0 04 bne SC2 ; jump to modify + 6464 6017 SC1: + 6465 ; + 6466 ; scroll up - start at top and copy upwards until we reach the bottom + 6467 ; + 6468 6017 A0 E6 ldy #$E6 ; 'inc' opcode + 6469 6019 A6 18 ldx SCLLINES ; get # of scrolling lines + 6470 601B SC2: + 6471 601B 8C D2 60 sty SCMOD1 ; make inc/dec + 6472 601E 8C D4 60 sty SCMOD2 ; either inc or dec + 6473 6021 86 1C stx SCOFF ; save the offset between SRC and DST + 6474 + 6475 6023 A5 1D lda SCLDIR ; which direction? + 6476 6025 10 13 bpl SC3 ; must be normal scroll + 6477 ; + 6478 ; if scrolling downwards, we need to start source at bottom-offset and + 6479 ; end when the destination is at top+offset + 6480 ; + 6481 6027 A5 0D lda CLSHEIGHT ; get # of lines in window + 6482 6029 38 sec ; subbing + 6483 602A E5 1C sbc SCOFF ; subtract offset to get source + 6484 602C 18 clc ; adding + 6485 602D 65 0B adc CLSTOP ; and get absolute position + 6486 602F AA tax ; put in X + 6487 6030 CA dex ; for 0 offset it + 6488 6031 A5 0B lda CLSTOP ; now figger last line to copy + 6489 6033 18 clc ; adding + 6490 6034 65 0D adc CLSHEIGHT ; get me last line + 6491 6036 A8 tay ; for later storage + 6492 6037 88 dey ; make 0 based + 6493 6038 D0 08 bne SC4 ; always jumps + 6494 603A SC3: + 6495 ; + 6496 ; if scrolling upwards, start src at top+offset and end when destination + 6497 ; is at bottom-offset + 6498 ; + 6499 603A A5 0B lda CLSTOP ; get top + 6500 603C 18 clc ; adding + 6501 603D 65 1C adc SCOFF ; add in offset + 6502 603F AA tax ; for later on + 6503 6040 A4 0B ldy CLSTOP ; first destination is top of window + 6504 6042 SC4: + 6505 6042 86 01 stx SCRCY ; Starting Source + 6506 6044 84 15 sty SCROLLY ; Starting Destination + 6507 + 6508 6046 20 BC 5F jsr SETMASK ; set the masks and horizontal endpoint + 6509 6049 A5 BD lda CPY_COUNT ; save for future generations + 6510 604B 85 14 sta SH_LOOP ; save it + 6511 604D A5 0D lda CLSHEIGHT ; how high + 6512 604F 85 10 sta DATALOOP ; save as counter + 6513 6051 38 sec ; for subbing + 6514 6052 E5 1C sbc SCOFF ; subtract scrolling amount + 6515 6054 85 0D sta CLSHEIGHT ; this is how many lines to copy + 6516 6056 A5 01 lda SCRCY ; save Start Source + 6517 6058 48 pha + 6518 6059 A5 0B lda CLSTOP ; start at Y pos + 6519 605B 85 01 sta SCRCY + 6520 605D A5 0A lda CLSLEFT ; and x pos + 6521 605F 85 00 sta SCRCX ; thank you + Wed May 24 1989 15:00 Page 95 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6522 6061 AD 54 C0 lda PAGE2SW+MAIN ; make sure main memory page is in there + 6523 6064 SCRL1: + 6524 6064 20 4C 5E jsr SETPOS ; set up line pointer + 6525 6067 A4 01 ldy SCRCY ; get top + 6526 6069 C0 78 cpy #120 ; 120 bytes per list + 6527 606B 90 05 bcc SCRLY ; all set + 6528 606D 98 tya ; for adding + 6529 606E 18 clc + 6530 606F 69 08 adc #8 + 6531 6071 A8 tay + 6532 6072 SCRLY: + 6533 6072 A5 8D lda FPCH + 6534 6074 99 00 06 sta SV_PCH,Y + 6535 6077 A5 8C lda FPCL + 6536 6079 99 00 04 sta SV_PCL,Y + 6537 607C E6 01 inc SCRCY ; next line please + 6538 607E C6 10 dec DATALOOP + 6539 6080 D0 E2 bne SCRL1 + 6540 + 6541 6082 68 pla ; get StartSource back + 6542 6083 85 01 sta SCRCY + 6543 6085 A5 8E lda FPCBNK ; init SPC bank too + 6544 6087 85 91 sta SPCBNK ; fine, we did + 6545 6089 SCROLLING: + 6546 6089 A4 01 ldy SCRCY ; get source Y for index + 6547 608B C0 78 cpy #120 ; jump over junk + 6548 608D 90 05 bcc SCLYY + 6549 608F 98 tya + 6550 6090 18 clc + 6551 6091 69 08 adc #8 + 6552 6093 A8 tay + 6553 6094 SCLYY: + 6554 6094 B9 00 06 lda SV_PCH,Y + 6555 6097 85 90 sta SPCH + 6556 6099 8D 7D 1D sta CPY_MOD1_SRC+HI + 6557 609C 8D A1 1D sta CPY_MOD2_SRC+HI + 6558 609F B9 00 04 lda SV_PCL,Y + 6559 60A2 8D 7C 1D sta CPY_MOD1_SRC+LO + 6560 60A5 8D A0 1D sta CPY_MOD2_SRC+LO + 6561 60A8 85 8F sta SPCL + 6562 + 6563 60AA A4 15 ldy SCROLLY ; get destination Y pos + 6564 60AC C0 78 cpy #120 ; jump over junk + 6565 60AE 90 05 bcc SCLYY1 + 6566 60B0 98 tya + 6567 60B1 18 clc + 6568 60B2 69 08 adc #8 + 6569 60B4 A8 tay + 6570 60B5 SCLYY1: + 6571 60B5 B9 00 06 lda SV_PCH,Y + 6572 60B8 85 8D sta FPCH + 6573 60BA 8D 80 1D sta CPY_MOD1_DST+HI + 6574 60BD 8D A4 1D sta CPY_MOD2_DST+HI + 6575 60C0 B9 00 04 lda SV_PCL,Y + 6576 60C3 8D 7F 1D sta CPY_MOD1_DST+LO + 6577 60C6 8D A3 1D sta CPY_MOD2_DST+LO + 6578 60C9 85 8C sta FPCL + 6579 + 6580 60CB A5 14 lda SH_LOOP ; get byte counter + 6581 60CD 85 BD sta CPY_COUNT ; show copy line + 6582 60CF 20 50 1D jsr COPY_LINE ; and do the copy + 6583 60D2 E6 01 SCMOD1: inc SCRCY ; inc or dec to get next one + 6584 60D4 E6 15 SCMOD2: inc SCROLLY ; inc/dec for next destination Y + 6585 60D6 C6 0D dec CLSHEIGHT ; count down + 6586 60D8 D0 AF bne SCROLLING ; nope + 6587 + 6588 60DA A6 1D ldx SCLDIR ; scroll up or down? + 6589 60DC 10 09 bpl SCLCLR1 ; clear a little different + 6590 ; + 6591 ; if scrolling down, clear from current Y+1 + 6592 ; + 6593 60DE A5 01 lda SCRCY ; get current source + 6594 60E0 85 0B sta CLSTOP ; save in top spot + 6595 60E2 E6 0B inc CLSTOP ; get inside window + 6596 60E4 4C EB 60 jmp SCLCLR2 + Wed May 24 1989 15:00 Page 96 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6597 60E7 SCLCLR1: + 6598 60E7 A5 15 lda SCROLLY ; get last destination + 6599 60E9 85 0B sta CLSTOP ; and save it + 6600 60EB SCLCLR2: + 6601 60EB A5 1C lda SCOFF ; and both clear this many lines + 6602 60ED 85 0D sta CLSHEIGHT ; okay? + 6603 + 6604 60EF AD 7C 5D lda SAVECX ; now restore X and Y + 6605 60F2 85 00 sta SCRCX ; x + 6606 60F4 AD 7B 5D lda SAVECY ; and + 6607 60F7 85 01 sta SCRCY ; y + 6608 + 6609 60F9 20 00 5F jsr CLS ; WIDTH and LEFT should be okay still + 6610 + 6611 60FC 60 rts + 6612 ; + 6613 ; CLREOL - clear from current cursor position to end of line by + 6614 ; using CLS after changing the window size + 6615 ; + 6616 60FD CLREOL: + 6617 60FD A5 00 lda SCRCX ; and make left be where cursor is + 6618 60FF 85 0A sta CLSLEFT + 6619 6101 A5 01 lda SCRCY ; and top be where Y is + 6620 6103 85 0B sta CLSTOP + 6621 6105 A9 09 lda #FONT_H ; and bottom be bottom of char + 6622 6107 85 0D sta CLSHEIGHT + 6623 6109 A0 03 ldy #WINWID ; get width + 6624 610B B1 05 lda (WINDOW),Y ; got it + 6625 610D 18 clc ; now adding + 6626 610E A0 01 ldy #WINLEFT ; the left edge + 6627 6110 71 05 adc (WINDOW),Y ; to get the right edge + 6628 6112 38 sec ; subbing + 6629 6113 E5 0A sbc CLSLEFT ; and subtract left to get width + 6630 6115 A0 07 ldy #WINRM ; remove the size of the right margin + 6631 6117 F1 05 sbc (WINDOW),Y ; that too + 6632 6119 85 0C sta CLSWIDTH ; okay? + 6633 611B 4C 00 5F jmp CLS ; now clear the screen + 6634 ; + 6635 ; COPY_SCRL - copy from SCR_LINE onto the screen. CH_OFFSET says how + 6636 ; many bytes in SCR_LINE to copy. FPC is assumed to be pointing + 6637 ; to start of screen bytes. BITTER has the original BITOFF from + 6638 ; SETPOS. ENDBIT shows how many significant bits in last byte. + 6639 ; + 6640 611E COPY_SCRL: + 6641 611E AE DE 71 ldx SHOW_CURSOR ; are we showing the cursor (ugh) + 6642 6121 F0 03 beq COPYL2 ; nope + 6643 6123 4C 9D 73 jmp DO_CURSOR ; then XOR cursor in + 6644 6126 COPYL2: + 6645 6126 A0 0E ldy #WINBGND ; get background offset + 6646 6128 B1 05 lda (WINDOW),Y ; get current background color + 6647 612A F0 03 beq COPY_SCRL1 ; if black, ignore this + 6648 612C 20 ED 61 jsr FIX_COLOR ; or in the color, please + 6649 ; + 6650 ; Alternate entry point for COPY_SCRL, used by picture drawing routine + 6651 ; to avoid using background color and checking for cursor + 6652 ; + 6653 612F COPY_SCRL1: + 6654 612F A6 8E ldx FPCBNK ; set up bank + 6655 6131 BD 54 C0 lda PAGE2SW,X ; set first bank + 6656 6134 AD D5 71 lda ENDBIT ; did we end evenly? + 6657 6137 D0 02 bne COPYL22 ; nope + 6658 6139 E6 0F inc CH_OFFSET ; make CH_OFFSET be a counter + 6659 613B COPYL22: + 6660 613B A0 00 ldy #0 ; zero y + 6661 + 6662 613D A5 0F lda CH_OFFSET ; if only one, then handle real special + 6663 613F D0 24 bne COPYL21 ; nope + 6664 + 6665 6141 AE DC 71 ldx BITTER ; get starting bit offset + 6666 6144 BD B5 5F lda ST_BITS,X ; get starting bit mask + 6667 6147 85 AC sta IOCHAR ; save it + 6668 6149 AE D5 71 ldx ENDBIT ; get ending bit offset + 6669 614C BD B5 5F lda ST_BITS,X ; combine with ending mask bits + 6670 614F 49 FF eor #$FF ; set for good ones + 6671 6151 05 AC ora IOCHAR ; set up mask for bits + Wed May 24 1989 15:00 Page 97 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6672 6153 31 8C and (FPC),Y ; get me interesting bits + 6673 6155 91 8C sta (FPC),Y ; save + 6674 6157 A5 AC lda IOCHAR ; get flag for data + 6675 6159 49 FF eor #$FF ; flip to get good data + 6676 615B 2D 00 1F CPYSM1: and SCR_LINE ; pick up my bits + 6677 615E 11 8C ora (FPC),Y ; and or in screen data + 6678 6160 91 8C sta (FPC),Y ; and save it + 6679 6162 4C E9 61 jmp COPYLEX ; go away now + 6680 6165 COPYL21: + 6681 6165 A5 0F lda CH_OFFSET ; get # of chars + 6682 6167 4A lsr A ; /2 get number in this bank + 6683 6168 69 00 adc #0 ; pick up carry for first one + 6684 616A 85 10 sta DATALOOP ; and save it to work on + 6685 + 6686 616C AE DC 71 ldx BITTER ; do we have a weird start? + 6687 616F F0 1A beq DLL2 ; nope + 6688 ; + 6689 ; need to do the first one special + 6690 ; + 6691 6171 B1 8C lda (FPC),Y ; get byte + 6692 6173 3D B5 5F and ST_BITS,X ; get masking bits + 6693 6176 85 AC sta IOCHAR ; save for later + 6694 6178 BD B5 5F lda ST_BITS,X ; get masking bits again + 6695 617B 49 FF eor #$FF ; get good bits + 6696 617D 2D 00 1F CPYSM2: and SCR_LINE ; get first data byte + 6697 6180 05 AC ora IOCHAR ; pick up screen bits + 6698 6182 91 8C sta (FPC),Y ; pointing + 6699 6184 C8 iny ; next byte + 6700 6185 A2 02 ldx #2 ; start at next one for this bank + 6701 6187 C6 10 dec DATALOOP ; kount as done + 6702 6189 COPYLOOP: + 6703 6189 F0 0C beq CPYLP2 ; all done with this part of line + 6704 618B DLL2: + 6705 618B BD 00 1F CPYSM3: lda SCR_LINE,X ; get data + 6706 618E 91 8C sta (FPC),Y ; pointing + 6707 6190 C8 iny ; next byte + 6708 6191 E8 inx ; next one + 6709 6192 E8 inx ; next one + 6710 6193 C6 10 dec DATALOOP ; count as used + 6711 6195 10 F2 bpl COPYLOOP ; start loop again + 6712 6197 CPYLP2: + 6713 6197 A0 00 ldy #0 ; reset Y + 6714 6199 A5 8E lda FPCBNK ; which bank were we at + 6715 619B 49 01 eor #1 ; swap to other one + 6716 619D AA tax ; make it in x + 6717 619E BD 54 C0 lda PAGE2SW,X ; swap to write bank + 6718 61A1 8A txa ; check which one + 6719 61A2 F0 01 beq CPYLP23 ; correct offset + 6720 61A4 C8 iny ; fix offset if going from main to aux + 6721 61A5 CPYLP23: + 6722 61A5 A2 01 ldx #1 ; start at second byte in screen line + 6723 61A7 A5 0F lda CH_OFFSET ; get starting number + 6724 61A9 4A lsr A ; /2 to get how many for this bank + 6725 61AA 85 10 sta DATALOOP ; and show it + 6726 61AC COPYLOOP2: + 6727 61AC F0 0C beq LINE_DONE ; all done with this part of line + 6728 + 6729 61AE BD 00 1F CPYSM4: lda SCR_LINE,X ; get data + 6730 61B1 91 8C sta (FPC),Y ; pointing + 6731 61B3 C8 iny ; next byte + 6732 61B4 E8 inx ; next one + 6733 61B5 E8 inx ; next one + 6734 61B6 C6 10 dec DATALOOP ; count as used + 6735 61B8 10 F2 bpl COPYLOOP2 ; start loop again + 6736 61BA LINE_DONE: + 6737 ; + 6738 ; do the last byte special + 6739 ; + 6740 61BA 86 10 stx DATALOOP ; save pointer + 6741 61BC AD D5 71 lda ENDBIT ; get ending bit offset + 6742 61BF F0 28 beq COPYLEX ; all done if nothing funky + 6743 61C1 46 0F lsr CH_OFFSET ; get line offset + 6744 61C3 48 pha ; save [A] + 6745 61C4 B0 0B bcs LINED1 ; if odd, point at right things + 6746 61C6 C6 10 dec DATALOOP ; one less then + Wed May 24 1989 15:00 Page 98 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6747 61C8 A6 8E ldx FPCBNK ; get original bank + 6748 61CA BD 54 C0 lda PAGE2SW,X ; switch to it + 6749 61CD 8A txa ; which bank did we do? + 6750 61CE D0 01 bne LINED1 ; no need to step back one + 6751 61D0 88 dey ; point one less here too + 6752 61D1 LINED1: + 6753 61D1 68 pla ; get ENDBIT back + 6754 61D2 AA tax ; make end bits be index + 6755 61D3 BD B5 5F lda ST_BITS,X ; get end mask + 6756 61D6 85 AC sta IOCHAR ; save mask bits + 6757 61D8 49 FF eor #$FF ; toggle every bit + 6758 61DA 31 8C and (FPC),Y ; get the interesting bits in byte + 6759 61DC 91 8C sta (FPC),Y ; save it + 6760 61DE A6 10 ldx DATALOOP ; get data pointer + 6761 61E0 BD 00 1F CPYSM5: lda SCR_LINE,X ; turn on my bits + 6762 61E3 25 AC and IOCHAR ; pick up my good bits + 6763 61E5 11 8C ora (FPC),Y ; bring everything together + 6764 61E7 91 8C sta (FPC),Y ; save the byte + 6765 61E9 COPYLEX: + 6766 61E9 AD 54 C0 lda PAGE2SW+MAIN ; back to main, thanks + 6767 61EC 60 rts + 6768 + 6769 61ED FIX_COLOR: + 6770 61ED E6 0F inc CH_OFFSET ; just to make checking easier for now + 6771 + 6772 61EF 0A asl A ; *2 + 6773 61F0 0A asl A ; *4 to get correct offset + 6774 61F1 69 12 adc #COLORS ; get hi part + 6777 61F7 69 00 adc #0 ; pick up maybe carry + 6778 61F9 85 AE sta COLORP+HI ; save pointer + 6779 61FB A2 11 ldx #$11 ; ORA (),Y opcode + 6780 61FD A0 0D ldy #WINFORE ; check foreground color + 6781 61FF B1 05 lda (WINDOW),Y ; check what color + 6782 6201 D0 11 bne FIXC1 ; just leave white if not black + 6783 6203 A2 00 ldx #0 ; start at beginning + 6784 6205 FIXMUNGEL: + 6785 6205 BD 00 1F lda SCR_LINE,X ; get byte + 6786 6208 49 FF eor #$FF ; swap all the bits + 6787 620A 9D 00 1F sta SCR_LINE,X ; store back + 6788 620D E8 inx ; count it + 6789 620E E4 0F cpx CH_OFFSET ; done? + 6790 6210 90 F3 bcc FIXMUNGEL ; nope + 6791 6212 A2 31 ldx #$31 ; AND (),Y opcode + 6792 6214 FIXC1: + 6793 6214 8E 22 62 stx FCLM ; self mod my code (again . . . sigh) + 6794 6217 AD DC 71 lda BITTER ; get starting offset + 6795 621A 29 03 and #3 ; pick up wrap + 6796 621C A8 tay ; make index + 6797 621D A2 00 ldx #0 ; start at zero line + 6798 621F FIXLOOP: + 6799 621F BD 00 1F FCM1: lda SCR_LINE,X ; get screen byte + 6800 6222 11 AD FCLM: ora (COLORP),Y ; or with color byte + 6801 6224 9D 00 1F FCM2: sta SCR_LINE,X ; save it + 6802 6227 C8 iny ; next color byte + 6803 6228 C0 04 cpy #4 ; wrapped? + 6804 622A D0 02 bne FIXLP1 ; nope + 6805 622C A0 00 ldy #0 ; restart + 6806 622E FIXLP1: + 6807 622E E8 inx ; next screen byte + 6808 622F E4 0F cpx CH_OFFSET ; done yet? + 6809 6231 90 EC bcc FIXLOOP ; nope + 6810 6233 + 6811 6233 C6 0F dec CH_OFFSET ; fix counter + 6812 6235 60 rts ; now we are done + 6813 ; + 6814 ; MSCURS - Erase the cursor from the old spot and write it in the + 6815 ; new spot + 6816 ; + 6817 6236 8C MOLDX: db MAXWIDTH ; spot to save x,y of mouse + 6818 6237 C0 MOLDY: db MAXHEIGHT + 6819 6238 MSCCNT: ds 1 + 6820 6239 SVCURS: ds CURSW*CURSH ; save room + 6821 6241 01 MSWCNT: db 1 + Wed May 24 1989 15:00 Page 99 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6822 6242 00 MSSTATE: db 0 ; 0 == off, 1 == on + 6823 6243 0F 07 07 07 07 MSCOLOR: db $f,7,7,7,7,7,7,7 + 6248 07 07 07 + 6824 ; + 6825 624B MSCURS: + 6826 624B A9 00 lda #0 ; clear moved flag + 6827 624D 8D 12 03 sta MSMOVEF ; we did + 6828 6250 20 56 62 jsr MSCOFF ; turn cursor off at current pos + 6829 6253 4C B5 62 jmp MSCON ; and turn it on in new spot + 6830 + 6831 ; + 6832 ; MSCOFF - mouse cursor off + 6833 ; Copy info from saved spot back onto screen @ MOLDX, MOLDY + 6834 6256 MSCOFF: + 6835 6256 AD 42 62 lda MSSTATE ; already off? + 6836 6259 D0 01 bne MSCOFF1 ; no + 6837 625B 60 rts ; done then + 6838 625C MSCOFF1: + 6839 625C A5 01 lda SCRCY ; save X,Y + 6840 625E 8D 7B 5D sta SAVECY + 6841 6261 A5 00 lda SCRCX + 6842 6263 8D 7C 5D sta SAVECX + 6843 6266 AD 36 62 lda MOLDX ; point to old X,Y + 6844 6269 85 00 sta SCRCX + 6845 626B AD 37 62 lda MOLDY + 6846 626E 85 01 sta SCRCY + 6847 6270 A9 00 lda #0 ; start at beginning of saved area + 6848 6272 8D 38 62 sta MSCCNT ; save counter + 6849 6275 A9 02 lda #CURSW ; restore width + 6850 6277 8D 41 62 sta MSWCNT ; and counter + 6851 627A RENEWL: + 6852 627A A5 01 lda SCRCY ; check bounds + 6853 627C C9 C0 cmp #MAXHEIGHT + 6854 627E B0 32 bcs MSC1 ; all done + 6855 6280 RENEWL0: + 6856 6280 A5 00 lda SCRCX + 6857 6282 C9 8C cmp #MAXWIDTH + 6858 6284 B0 1E bcs RENEWL1 ; might not be done + 6859 6286 20 0B 5E jsr GET_NYBBLE ; get screen nybble + 6860 6289 AE 38 62 ldx MSCCNT ; get counter + 6861 ; eor MSCOLOR,X ; xor to turn off + 6862 628C 49 0F eor #$0F ; turn white/black + 6863 628E 20 A1 5D jsr PUT_NYBBLE ; save nybble + 6864 6291 EE 38 62 inc MSCCNT ; point to next one + 6865 6294 AD 38 62 lda MSCCNT ; get counter + 6866 6297 C9 08 cmp #(CURSW*CURSH) ; done yet? + 6867 6299 F0 17 beq MSC1 ; yup + 6868 629B CE 41 62 dec MSWCNT ; count down one width + 6869 629E F0 04 beq RENEWL1 ; it is + 6870 62A0 E6 00 inc SCRCX ; next x + 6871 62A2 D0 DC bne RENEWL0 ; try again + 6872 62A4 RENEWL1: + 6873 62A4 AD 36 62 lda MOLDX ; reset X + 6874 62A7 85 00 sta SCRCX + 6875 62A9 A9 02 lda #CURSW ; restore width + 6876 62AB 8D 41 62 sta MSWCNT ; and counter + 6877 62AE E6 01 inc SCRCY ; next y + 6878 62B0 D0 C8 bne RENEWL ; okay try some more + 6879 62B2 MSC1: + 6880 62B2 4C 14 63 jmp MSCON4 ; done turning it off + 6881 ; + 6882 ; MSCON - turn mouse cursor on + 6883 ; Copy white pixels into area specified by MSX, MSY + 6884 ; + 6885 62B5 MSCON: + 6886 62B5 AD 42 62 lda MSSTATE ; already on? + 6887 62B8 F0 01 beq MSCON0 ; no + 6888 62BA 60 rts ; don't bother + 6889 62BB MSCON0: + 6890 62BB A5 01 lda SCRCY ; save X,Y + 6891 62BD 8D 7B 5D sta SAVECY + 6892 62C0 A5 00 lda SCRCX + 6893 62C2 8D 7C 5D sta SAVECX + 6894 + 6895 62C5 A5 CB lda MSX ; get mouse x + Wed May 24 1989 15:00 Page 100 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- APPLE ][ SCREEN STUFF ---" + + 6896 62C7 85 00 sta SCRCX ; set mouse X + 6897 62C9 8D 36 62 sta MOLDX ; save mouse x + 6898 62CC A5 CC lda MSY ; get mouse y + 6899 62CE 85 01 sta SCRCY ; set mouse Y + 6900 62D0 8D 37 62 sta MOLDY ; and mouse Y + 6901 62D3 A9 00 lda #0 ; start at beginning of saved area + 6902 62D5 8D 38 62 sta MSCCNT ; save counter + 6903 62D8 A9 02 lda #CURSW ; restore width + 6904 62DA 8D 41 62 sta MSWCNT ; and counter + 6905 62DD MSCON1: + 6906 62DD A5 01 lda SCRCY ; check bounds + 6907 62DF C9 C0 cmp #MAXHEIGHT + 6908 62E1 B0 31 bcs MSCON4 ; all done + 6909 62E3 MSCON2: + 6910 62E3 A5 00 lda SCRCX + 6911 62E5 C9 8C cmp #MAXWIDTH + 6912 62E7 B0 1E bcs MSCON3 ; might not be done + 6913 62E9 20 0B 5E jsr GET_NYBBLE ; save nybble + 6914 62EC AE 38 62 ldx MSCCNT ; get counter + 6915 ; eor MSCOLOR,X ; get cursor color + 6916 62EF 49 0F eor #$0F ; turn white/black + 6917 62F1 20 A1 5D jsr PUT_NYBBLE ; put nybble + 6918 62F4 EE 38 62 inc MSCCNT ; point to next one + 6919 62F7 AD 38 62 lda MSCCNT ; check ending + 6920 62FA C9 08 cmp #(CURSW*CURSH) ; done yet? + 6921 62FC F0 16 beq MSCON4 ; yup + 6922 62FE CE 41 62 dec MSWCNT ; count down one width + 6923 6301 F0 04 beq MSCON3 ; finished for line + 6924 6303 E6 00 inc SCRCX ; next x + 6925 6305 D0 DC bne MSCON2 ; try again + 6926 6307 MSCON3: + 6927 6307 A5 CB lda MSX ; reset X + 6928 6309 85 00 sta SCRCX + 6929 630B A9 02 lda #CURSW ; restore width + 6930 630D 8D 41 62 sta MSWCNT ; and counter + 6931 6310 E6 01 inc SCRCY ; next y + 6932 6312 D0 C9 bne MSCON1 ; okay try some more + 6933 6314 MSCON4: + 6934 6314 AD 42 62 lda MSSTATE ; get current state + 6935 6317 49 01 eor #$01 ; toggle it + 6936 6319 8D 42 62 sta MSSTATE ; bang + 6937 631C AD 7C 5D lda SAVECX ; restore X,Y + 6938 631F 85 00 sta SCRCX + 6939 6321 AD 7B 5D lda SAVECY + 6940 6324 85 01 sta SCRCY + 6941 6326 60 rts + 6942 6327 + 6943 + 6944 6327 END + 6945 + 6946 6327 INCLUDE TABLES.ASM + 6947 6327 STTL "--- ZIP DATA TABLES ---" + 6948 PAGE + Wed May 24 1989 15:00 Page 101 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6949 6327 CHADR_H: + 6950 6327 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 632C 00 00 00 00 00 + 6331 00 00 00 00 00 + 6336 00 + 6951 6337 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 633C 00 00 00 00 00 + 6341 00 00 00 00 00 + 6346 00 + 6952 6347 64 64 64 64 64 db >C20,>C21,>C22,>C23,>C24,>C25,>C26,>C27 + 634C 64 65 65 + 6953 634F 65 65 65 65 65 DB >C28,>C29,>C2A,>C2B,>C2C,>C2D,>C2E,>C2F + 6354 65 65 65 + 6954 6357 65 65 65 65 65 db >C30,>C31,>C32,>C33,>C34,>C35,>C36,>C37 + 635C 65 65 65 + 6955 635F 65 66 66 66 66 DB >C38,>C39,>C3A,>C3B,>C3C,>C3D,>C3E,>C3F + 6364 66 66 66 + 6956 6367 66 66 66 66 66 db >C40,>C41,>C42,>C43,>C44,>C45,>C46,>C47 + 636C 66 66 66 + 6957 636F 66 66 66 67 67 DB >C48,>C49,>C4A,>C4B,>C4C,>C4D,>C4E,>C4F + 6374 67 67 67 + 6958 6377 67 67 67 67 67 db >C50,>C51,>C52,>C53,>C54,>C55,>C56,>C57 + 637C 67 67 67 + 6959 637F 67 67 68 68 68 DB >C58,>C59,>C5A,>C5B,>C5C,>C5D,>C5E,>C5F + 6384 68 68 68 + 6960 6387 68 68 68 68 68 db >C60,>C61,>C62,>C63,>C64,>C65,>C66,>C67 + 638C 68 68 68 + 6961 638F 68 68 68 69 69 DB >C68,>C69,>C6A,>C6B,>C6C,>C6D,>C6E,>C6F + 6394 69 69 69 + 6962 6397 69 69 69 69 69 db >C70,>C71,>C72,>C73,>C74,>C75,>C76,>C77 + 639C 69 69 69 + 6963 639F 69 69 69 6A 6A DB >C78,>C79,>C7A,>C7B,>C7C,>C7D,>C7E + 63A4 6A 6A + 6964 63A6 CHADR_L: + 6965 63A6 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 63AB 00 00 00 00 00 + 63B0 00 00 00 00 00 + 63B5 00 + 6966 63B6 00 00 00 00 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 63BB 00 00 00 00 00 + 63C0 00 00 00 00 00 + 63C5 00 + 6967 63C6 A4 B6 BF D1 E3 db 8 + 6647 70 00 00 00 + 7022 664B 3F 80 71 C0 03 C3F DB 3f,80,71,c0,03,80,0e,00,0e,00,00,00,0e,00,00,00,00,00 ;? 10 + 6650 80 0E 00 0E 00 + 6655 00 00 0E 00 00 + 665A 00 00 00 + 7023 665D 1F F8 E0 0E E3 C40 DB 1f,f8,e0,0e,e3,e7,e6,77,e6,77,e3,bc,e0,00,1f,f8,00,00 ;@ 16 + 6662 E7 E6 77 E6 77 + 6667 E3 BC E0 00 1F + 666C F8 00 00 + 7024 666F 3F 80 71 C0 71 C41 DB 3f,80,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;A 10 + 6674 C0 7F C0 71 C0 + 6679 71 C0 71 C0 00 + 667E 00 00 00 + 7025 6681 7F 80 71 C0 71 C42 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,7f,80,00,00,00,00 ;B 10 + 6686 C0 7F 00 71 C0 + 668B 71 C0 7F 80 00 + 6690 00 00 00 + 7026 6693 3F 80 71 C0 70 C43 DB 3f,80,71,c0,70,00,70,00,70,00,71,c0,3f,80,00,00,00,00 ;C 10 + 6698 00 70 00 70 00 + 669D 71 C0 3F 80 00 + 66A2 00 00 00 + 7027 66A5 7F 80 71 C0 71 C44 DB 7f,80,71,c0,71,c0,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;D 10 + 66AA C0 71 C0 71 C0 + 66AF 71 C0 7F 80 00 + 66B4 00 00 00 + 7028 66B7 7F 70 70 7F 70 C45 DB 7f,70,70,7f,70,70,7f,00,00 ;E 8 + 66BC 70 7F 00 00 + 7029 66C0 7F 70 70 7E 70 C46 DB 7f,70,70,7e,70,70,70,00,00 ;F 8 + 66C5 70 70 00 00 + 7030 66C9 3F 80 71 C0 70 C47 DB 3f,80,71,c0,70,00,73,c0,71,c0,71,c0,3f,80,00,00,00,00 ;G 10 + 66CE 00 73 C0 71 C0 + Wed May 24 1989 15:00 Page 104 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 66D3 71 C0 3F 80 00 + 66D8 00 00 00 + 7031 66DB 71 C0 71 C0 71 C48 DB 71,c0,71,c0,71,c0,7f,c0,71,c0,71,c0,71,c0,00,00,00,00 ;H 10 + 66E0 C0 7F C0 71 C0 + 66E5 71 C0 71 C0 00 + 66EA 00 00 00 + 7032 66ED 70 70 70 70 70 C49 DB 70,70,70,70,70,70,70,00,00 ;I 4 + 66F2 70 70 00 00 + 7033 66F6 01 C0 01 C0 01 C4A DB 01,c0,01,c0,01,c0,01,c0,71,c0,71,c0,3f,80,00,00,00,00 ;J 10 + 66FB C0 01 C0 71 C0 + 6700 71 C0 3F 80 00 + 6705 00 00 00 + 7034 6708 70 E0 71 C0 73 C4B DB 70,e0,71,c0,73,80,7f,00,73,80,71,c0,70,e0,00,00,00,00 ;K 11 + 670D 80 7F 00 73 80 + 6712 71 C0 70 E0 00 + 6717 00 00 00 + 7035 671A 70 70 70 70 70 C4C DB 70,70,70,70,70,70,7f,00,00 ;L 8 + 671F 70 7F 00 00 + 7036 6723 78 3C 7C 7C 7E C4D DB 78,3c,7c,7c,7e,fc,77,dc,73,9c,70,1c,70,1c,00,00,00,00 ;M 14 + 6728 FC 77 DC 73 9C + 672D 70 1C 70 1C 00 + 6732 00 00 00 + 7037 6735 78 70 7C 70 7E C4E DB 78,70,7c,70,7e,70,77,70,73,f0,71,f0,70,f0,00,00,00,00 ;N 12 + 673A 70 77 70 73 F0 + 673F 71 F0 70 F0 00 + 6744 00 00 00 + 7038 6747 3F 80 71 C0 71 C4F DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;O 10 + 674C C0 71 C0 71 C0 + 6751 71 C0 3F 80 00 + 6756 00 00 00 + 7039 6759 7F 80 71 C0 71 C50 DB 7f,80,71,c0,71,c0,7f,80,70,00,70,00,70,00,00,00,00,00 ;P 10 + 675E C0 7F 80 70 00 + 6763 70 00 70 00 00 + 6768 00 00 00 + 7040 676B 3F 80 71 C0 71 C51 DB 3f,80,71,c0,71,c0,71,c0,71,c0,71,c0,3f,00,03,c0,00,00 ;Q 10 + 6770 C0 71 C0 71 C0 + 6775 71 C0 3F 00 03 + 677A C0 00 00 + 7041 677D 7F 80 71 C0 71 C52 DB 7f,80,71,c0,71,c0,7f,00,71,c0,71,c0,71,c0,00,00,00,00 ;R 10 + 6782 C0 7F 00 71 C0 + 6787 71 C0 71 C0 00 + 678C 00 00 00 + 7042 678F 3F 80 71 C0 78 C53 DB 3f,80,71,c0,78,00,1f,00,03,c0,71,c0,3f,80,00,00,00,00 ;S 10 + 6794 00 1F 00 03 C0 + 6799 71 C0 3F 80 00 + 679E 00 00 00 + 7043 67A1 7F C0 0E 00 0E C54 DB 7f,c0,0e,00,0e,00,0e,00,0e,00,0e,00,0e,00,00,00,00,00 ;T 10 + 67A6 00 0E 00 0E 00 + 67AB 0E 00 0E 00 00 + 67B0 00 00 00 + 7044 67B3 71 C0 71 C0 71 C55 DB 71,c0,71,c0,71,c0,71,c0,71,c0,71,c0,1f,00,00,00,00,00 ;U 10 + 67B8 C0 71 C0 71 C0 + 67BD 71 C0 1F 00 00 + 67C2 00 00 00 + 7045 67C5 71 C0 71 C0 71 C56 DB 71,c0,71,c0,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;V 10 + 67CA C0 71 C0 73 80 + 67CF 77 00 7E 00 00 + 67D4 00 00 00 + 7046 67D7 71 C7 71 C7 71 C57 DB 71,c7,71,c7,71,c7,71,c7,71,c7,71,dc,7f,f8,00,00,00,00 ;W 16 + 67DC C7 71 C7 71 C7 + 67E1 71 DC 7F F8 00 + 67E6 00 00 00 + 7047 67E9 71 C0 71 C0 71 C58 DB 71,c0,71,c0,71,c0,1f,00,71,c0,71,c0,71,c0,00,00,00,00 ;X 10 + 67EE C0 1F 00 71 C0 + 67F3 71 C0 71 C0 00 + 67F8 00 00 00 + 7048 67FB 71 C0 71 C0 71 C59 DB 71,c0,71,c0,71,c0,3f,80,0e,00,0e,00,0e,00,00,00,00,00 ;Y 10 + 6800 C0 3F 80 0E 00 + 6805 0E 00 0E 00 00 + 680A 00 00 00 + 7049 680D 7F C0 01 C0 03 C5A DB 7f,c0,01,c0,03,80,0e,00,38,00,70,00,7f,c0,00,00,00,00 ;Z 10 + 6812 80 0E 00 38 00 + 6817 70 00 7F C0 00 + 681C 00 00 00 + 7050 681F 7F 70 70 70 70 C5B DB 7f,70,70,70,70,70,7f,00,00 ;[ 8 + Wed May 24 1989 15:00 Page 105 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6824 70 7F 00 00 + 7051 6828 70 00 38 00 1C C5C DB 70,00,38,00,1c,00,0e,00,07,00,03,80,01,c0,00,00,00,00 ;\ 10 + 682D 00 0E 00 07 00 + 6832 03 80 01 C0 00 + 6837 00 00 00 + 7052 683A 7F 07 07 07 07 C5D DB 7f,07,07,07,07,07,7f,00,00 ;] 8 + 683F 07 7F 00 00 + 7053 6843 00 00 0C 00 3F C5E DB 00,00,0c,00,3f,00,e1,c0,00,00,00,00,00,00,00,00,00,00 ;^ 10 + 6848 00 E1 C0 00 00 + 684D 00 00 00 00 00 + 6852 00 00 00 + 7054 6855 00 00 00 00 00 C5F DB 00,00,00,00,00,00,00,ff,00 ;_ 8 + 685A 00 00 FF 00 + 7055 685E 70 38 1C 00 00 C60 DB 70,38,1c,00,00,00,00,00,00 ;` 6 + 6863 00 00 00 00 + 7056 6867 00 00 00 00 3F C61 DB 00,00,00,00,3f,80,01,c0,3f,c0,71,c0,3f,c0,00,00,00,00 ;a 10 + 686C 80 01 C0 3F C0 + 6871 71 C0 3F C0 00 + 6876 00 00 00 + 7057 6879 70 00 70 00 7F C62 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,7f,80,00,00,00,00 ;b 10 + 687E 80 71 C0 71 C0 + 6883 71 C0 7F 80 00 + 6888 00 00 00 + 7058 688B 00 00 00 00 3F C63 DB 00,00,00,00,3f,80,71,c0,70,00,71,c0,3f,80,00,00,00,00 ;c 10 + 6890 80 71 C0 70 00 + 6895 71 C0 3F 80 00 + 689A 00 00 00 + 7059 689D 01 C0 01 C0 3F C64 DB 01,c0,01,c0,3f,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;d 10 + 68A2 C0 71 C0 71 C0 + 68A7 71 C0 3F C0 00 + 68AC 00 00 00 + 7060 68AF 00 00 00 00 3F C65 DB 00,00,00,00,3f,80,79,c0,7f,c0,70,00,3f,80,00,00,00,00 ;e 10 + 68B4 80 79 C0 7F C0 + 68B9 70 00 3F 80 00 + 68BE 00 00 00 + 7061 68C1 0F 1C 7F 1C 1C C66 DB 0f,1c,7f,1c,1c,1c,1c,00,00 ;f 8 + 68C6 1C 1C 00 00 + 7062 68CA 00 00 00 00 3F C67 DB 00,00,00,00,3f,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;g 10 + 68CF C0 71 C0 71 C0 + 68D4 71 C0 3F C0 01 + 68D9 C0 3F 80 + 7063 68DC 70 00 70 00 7F C68 DB 70,00,70,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;h 10 + 68E1 80 71 C0 71 C0 + 68E6 71 C0 71 C0 00 + 68EB 00 00 00 + 7064 68EE 70 00 70 70 70 C69 DB 70,00,70,70,70,70,70,00,00 ;i 5 + 68F3 70 70 00 00 + 7065 68F7 0E 00 0E 0E 0E C6A DB 0e,00,0e,0e,0e,0e,0e,0e,7c ;j 8 + 68FC 0E 0E 0E 7C + 7066 6900 70 00 70 00 71 C6B DB 70,00,70,00,71,c0,73,80,7f,00,73,80,71,c0,00,00,00,00 ;k 10 + 6905 C0 73 80 7F 00 + 690A 73 80 71 C0 00 + 690F 00 00 00 + 7067 6912 70 70 70 70 70 C6C DB 70,70,70,70,70,70,70,00,00 ;l 5 + 6917 70 70 00 00 + 7068 691B 00 00 00 00 7F C6D DB 00,00,00,00,7f,fc,73,9c,73,9c,73,9c,73,9c,00,00,00,00 ;m 14 + 6920 FC 73 9C 73 9C + 6925 73 9C 73 9C 00 + 692A 00 00 00 + 7069 692D 00 00 00 00 7F C6E DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,71,c0,00,00,00,00 ;n 10 + 6932 80 71 C0 71 C0 + 6937 71 C0 71 C0 00 + 693C 00 00 00 + 7070 693F 00 00 00 00 3F C6F DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,80,00,00,00,00 ;o 10 + 6944 80 71 C0 71 C0 + 6949 71 C0 3F 80 00 + 694E 00 00 00 + 7071 6951 00 00 00 00 7F C70 DB 00,00,00,00,7f,80,71,c0,71,c0,71,c0,7f,80,70,00,70,00 ;p 10 + 6956 80 71 C0 71 C0 + 695B 71 C0 7F 80 70 + 6960 00 70 00 + 7072 6963 00 00 00 00 3F C71 DB 00,00,00,00,3f,80,71,c0,71,c0,71,c0,3f,c0,01,c0,01,c0 ;q 10 + 6968 80 71 C0 71 C0 + 696D 71 C0 3F C0 01 + 6972 C0 01 C0 + Wed May 24 1989 15:00 Page 106 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 7073 6975 00 00 77 7C 70 C72 DB 00,00,77,7c,70,70,70,00,00 ;r 8 + 697A 70 70 00 00 + 7074 697E 00 00 00 00 3F C73 DB 00,00,00,00,3f,00,70,00,1e,00,03,80,3f,00,00,00,00,00 ;s 9 + 6983 00 70 00 1E 00 + 6988 03 80 3F 00 00 + 698D 00 00 00 + 7075 6990 1C 1C 7F 1C 1C C74 DB 1c,1c,7f,1c,1c,1c,0f,00,00 ;t 8 + 6995 1C 0F 00 00 + 7076 6999 00 00 00 00 71 C75 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,00,00,00,00 ;u 10 + 699E C0 71 C0 71 C0 + 69A3 71 C0 3F C0 00 + 69A8 00 00 00 + 7077 69AB 00 00 00 00 71 C76 DB 00,00,00,00,71,c0,71,c0,73,80,77,00,7e,00,00,00,00,00 ;v 10 + 69B0 C0 71 C0 73 80 + 69B5 77 00 7E 00 00 + 69BA 00 00 00 + 7078 69BD 00 00 00 00 73 C77 DB 00,00,00,00,73,9c,73,9c,73,9c,73,9c,7f,f8,00,00,00,00 ;w 14 + 69C2 9C 73 9C 73 9C + 69C7 73 9C 7F F8 00 + 69CC 00 00 00 + 7079 69CF 00 00 00 00 71 C78 DB 00,00,00,00,71,c0,71,c0,1f,00,71,c0,71,c0,00,00,00,00 ;x 10 + 69D4 C0 71 C0 1F 00 + 69D9 71 C0 71 C0 00 + 69DE 00 00 00 + 7080 69E1 00 00 00 00 71 C79 DB 00,00,00,00,71,c0,71,c0,71,c0,71,c0,3f,c0,01,c0,3f,80 ;y 10 + 69E6 C0 71 C0 71 C0 + 69EB 71 C0 3F C0 01 + 69F0 C0 3F 80 + 7081 69F3 00 00 00 00 7F C7A DB 00,00,00,00,7f,c0,03,80,0e,00,38,00,7f,c0,00,00,00,00 ;z 10 + 69F8 C0 03 80 0E 00 + 69FD 38 00 7F C0 00 + 6A02 00 00 00 + 7082 6A05 1F 38 38 F0 38 C7B DB 1f,38,38,f0,38,38,1f,00,00 ;} 8 + 6A0A 38 1F 00 00 + 7083 6A0E 70 70 70 70 70 C7C DB 70,70,70,70,70,70,70,70,70 ;| 5 + 6A13 70 70 70 70 + 7084 6A17 F8 1C 1C 0F 1C C7D DB f8,1c,1c,0f,1c,1c,f8,00,00 ;} 8 + 6A1C 1C F8 00 00 + 7085 6A20 00 00 00 00 3C C7E DB 00,00,00,00,3c,e0,e7,80,00,00,00,00,00,00,00,00,00,00 ;~ 11 + 6A25 E0 E7 80 00 00 + 6A2A 00 00 00 00 00 + 6A2F 00 00 00 + 7086 ; + 7087 ; base addresses for the screen lines + 7088 ; + 7089 6A32 BASEL: + 7090 6A32 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A37 00 00 00 + 7091 6A3A 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A3F 80 80 80 + 7092 6A42 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A47 00 00 00 + 7093 6A4A 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A4F 80 80 80 + 7094 6A52 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A57 00 00 00 + 7095 6A5A 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A5F 80 80 80 + 7096 6A62 00 00 00 00 00 DB 00,00,00,00,00,00,00,00 + 6A67 00 00 00 + 7097 6A6A 80 80 80 80 80 DB 80,80,80,80,80,80,80,80 + 6A6F 80 80 80 + 7098 6A72 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + 6A77 28 28 28 + 7099 6A7A A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6A7F A8 A8 A8 + 7100 6A82 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + 6A87 28 28 28 + 7101 6A8A A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6A8F A8 A8 A8 + 7102 6A92 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + 6A97 28 28 28 + 7103 6A9A A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6A9F A8 A8 A8 + 7104 6AA2 28 28 28 28 28 DB 28,28,28,28,28,28,28,28 + Wed May 24 1989 15:00 Page 107 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6AA7 28 28 28 + 7105 6AAA A8 A8 A8 A8 A8 DB A8,A8,A8,A8,A8,A8,A8,A8 + 6AAF A8 A8 A8 + 7106 6AB2 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6AB7 50 50 50 + 7107 6ABA D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6ABF D0 D0 D0 + 7108 6AC2 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6AC7 50 50 50 + 7109 6ACA D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6ACF D0 D0 D0 + 7110 6AD2 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6AD7 50 50 50 + 7111 6ADA D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6ADF D0 D0 D0 + 7112 6AE2 50 50 50 50 50 DB 50,50,50,50,50,50,50,50 + 6AE7 50 50 50 + 7113 6AEA D0 D0 D0 D0 D0 DB D0,D0,D0,D0,D0,D0,D0,D0 + 6AEF D0 D0 D0 + 7114 6AF2 BASEH: + 7115 6AF2 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6AF7 34 38 3C + 7116 6AFA 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6AFF 34 38 3C + 7117 6B02 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B07 35 39 3D + 7118 6B0A 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B0F 35 39 3D + 7119 6B12 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B17 36 3A 3E + 7120 6B1A 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B1F 36 3A 3E + 7121 6B22 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B27 37 3B 3F + 7122 6B2A 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B2F 37 3B 3F + 7123 6B32 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B37 34 38 3C + 7124 6B3A 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B3F 34 38 3C + 7125 6B42 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B47 35 39 3D + 7126 6B4A 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B4F 35 39 3D + 7127 6B52 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B57 36 3A 3E + 7128 6B5A 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B5F 36 3A 3E + 7129 6B62 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B67 37 3B 3F + 7130 6B6A 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6B6F 37 3B 3F + 7131 6B72 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B77 34 38 3C + 7132 6B7A 20 24 28 2C 30 DB 20,24,28,2C,30,34,38,3C + 6B7F 34 38 3C + 7133 6B82 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B87 35 39 3D + 7134 6B8A 21 25 29 2D 31 DB 21,25,29,2D,31,35,39,3D + 6B8F 35 39 3D + 7135 6B92 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B97 36 3A 3E + 7136 6B9A 22 26 2A 2E 32 DB 22,26,2A,2E,32,36,3A,3E + 6B9F 36 3A 3E + 7137 6BA2 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6BA7 37 3B 3F + 7138 6BAA 23 27 2B 2F 33 DB 23,27,2B,2F,33,37,3B,3F + 6BAF 37 3B 3F + 7139 ; + 7140 ; this gives the bit offset for each one + 7141 ; + 7142 6BB2 XBITTBL: + 7143 6BB2 00 DB 0 + 7144 6BB3 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BB8 03 00 + Wed May 24 1989 15:00 Page 108 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 7145 6BBA 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BBF 03 00 + 7146 6BC1 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BC6 03 00 + 7147 6BC8 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BCD 03 00 + 7148 6BCF 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BD4 03 00 + 7149 6BD6 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BDB 03 00 + 7150 6BDD 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BE2 03 00 + 7151 6BE4 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BE9 03 00 + 7152 6BEB 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BF0 03 00 + 7153 6BF2 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BF7 03 00 + 7154 6BF9 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6BFE 03 00 + 7155 6C00 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C05 03 00 + 7156 6C07 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C0C 03 00 + 7157 6C0E 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C13 03 00 + 7158 6C15 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C1A 03 00 + 7159 6C1C 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C21 03 00 + 7160 6C23 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C28 03 00 + 7161 6C2A 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C2F 03 00 + 7162 6C31 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C36 03 00 + 7163 6C38 04 01 05 02 06 DB 4,1,5,2,6,3,0 + 6C3D 03 00 + 7164 RADIX D + 7165 6C3F 00 01 06 07 0C ZIPCOLOR: db 0,1,6,7,$C,$B,$E,$F + 6C44 0B 0E 0F + 7166 6C47 02 03 FF FF FF APLCOLOR: db 2,3,$FF,$FF,$FF,$FF,4,5,$FF,$FF,$FF,7,$FF,$FF,8,9 + 6C4C FF 04 05 FF FF + 6C51 FF 07 FF FF 08 + 6C56 09 + 7167 6C57 OLDZV: + 7168 ; + 7169 ; Variables that used to be in the zero page but got moved out + 7170 ; + 7171 6C57 PSVFLG EQU OLDZV ; (BYTE) PRESERVE FLAG FOR LEX 0=DON'T 1=DO + 7172 6C58 VOCFLG EQU PSVFLG+1 ; (BYTE) WHICH VOC TBL, 0=NORMAL 1= ARG3 + 7173 6C59 DBLOCK EQU VOCFLG+1 ; (WORD) Z-BLOCK TO READ + 7174 6C5B QUOT EQU DBLOCK+2 ; (WORD) QUOTIENT FOR DIVISION + 7175 6C5D REMAIN EQU QUOT+2 ; (WORD) REMAINDER FOR DIVISION + 7176 6C5F QSIGN EQU REMAIN+2 ; (BYTE) SIGN OF QUOTIENT + 7177 6C60 RSIGN EQU QSIGN+1 ; (BYTE) SIGN OF REMAINDER + 7178 6C61 DIGITS EQU RSIGN+1 ; (BYTE) DIGIT COUNT FOR "PRINTN" + 7179 6C62 OLDLEN EQU DIGITS+1 ; (BYTE) OLD LINE LENGTH + 7180 6C63 OLDEND EQU OLDLEN+1 ; (BYTE) OLD LAST CHAR IN [LBUFF] + 7181 6C64 SPSTAT EQU OLDEND+1 ; (BYTE) SPLIT SCREEN STATUS FLAG + 7182 6C65 LFROM EQU SPSTAT+1 ; (WORD) "FROM" LINE ADDRESS + 7183 6C67 LTO EQU LFROM+2 ; (WORD) "TO" LINE ADDRESS + 7184 6C69 PRLEN EQU LTO+2 ; (BYTE) SCRIPT LINE LENGTH + 7185 6C6A GPOSIT EQU PRLEN+1 ; (BYTE) DEFAULT SAVE POSITION + 7186 6C6B GDRIVE EQU GPOSIT+1 ; (BYTE) DEFAULT SAVE DRIVE + 7187 6C6C TPOSIT EQU GDRIVE+1 ; (BYTE) TEMP SAVE POSITION + 7188 6C6D TDRIVE EQU TPOSIT+1 ; (BYTE) TEMP SAVE DRIVE + 7189 6C6E TSLOT EQU TDRIVE+1 ; (BYTE) TEMP SAVE SLOT + 7190 6C6F DRIVE EQU TSLOT+1 ; (BYTE) CURRENT DRIVE + 7191 6C70 SIDEFLG EQU DRIVE+1 ; (BYTE) which disk side are we on + 7192 6C71 SRHOLD EQU SIDEFLG+1 ; (WORD) <>0 if doing sequential random + 7193 6C73 SCRIPTF EQU SRHOLD+2 ; (BYTE) DIROUT FLAG FOR PRINTER OUTPUT + 7194 6C74 SCRIPTFLG EQU SCRIPTF+1 ; (BYTE) Does window allow scripting? + 7195 6C75 OLDZSP EQU SCRIPTFLG+1 ; (WORD) + 7196 6C77 CURSFLG EQU OLDZSP+2 ; (BYTE) 1==New cursor X for DLINE + Wed May 24 1989 15:00 Page 109 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 7197 6C78 DBLK EQU CURSFLG+1 ; (WORD) + 7198 6C7A RDTBL1 EQU DBLK+2 ; (WORD) READ TABLE 1 (Game Relative) + 7199 6C7C RDTBL2 EQU RDTBL1+2 ; (WORD) READ TABLE 2 + 7200 6C7E NENTS EQU RDTBL2+2 ; (WORD) # ENTRIES IN VOCAB TABLE + 7201 6C80 DIRITM EQU NENTS+2 ; (WORD) OFFSET IN OUTPUT TBL (DIRTBL) + 7202 6C82 DIRCNT EQU DIRITM+2 ; (WORD) COUNT OF CHARS IN TBL (DIRTBL) + 7203 6C84 SVTCHAR EQU DIRCNT+2 ; (WORD) Old TCHARS table address + 7204 6C86 VOCMPC EQU SVTCHAR+2 ; (3 BYTES) Save for vocabulary MPC + 7205 6C89 VCESVE EQU VOCMPC+3 ; (3 BYTES) Save for VOCEND + 7206 6C8C VWLSVE EQU VCESVE+3 ; (3 BYTES) Save for VOCLEN + 7207 6C8F DIDVTBL EQU VWLSVE+3 ; (BYTE) <>0 if we have done default table + 7208 6C90 IN EQU DIDVTBL+1 ; (9 BYTES) INPUT BUFFER + 7209 6C99 OUT EQU IN+9 ; (9 BYTES) OUTPUT BUFFER + 7210 6CA2 CURSOR_OFF EQU OUT+9 ; (BYTE) ==1 if char cursor not to be on + 7211 6CA3 CRLF_CHECK EQU CURSOR_OFF+1 ; (BYTE) ==1 to do CRLF function check + 7212 6CA4 PTR_COUNT EQU CRLF_CHECK+1 ; (BYTE) ==0 if checking pointer movement + 7213 6CA5 INFODOS_END EQU PTR_COUNT+1 ; (WORD) last segment of infodos special + 7214 0050 OLDZVLEN EQU INFODOS_END-PSVFLG+2 ; this is how much to reserve + 7215 + 7216 6C57 BLKB OLDZVLEN,0 ; and zero it out + 7217 + 7218 ; ------------------ + 7219 ; ERROR MESSAGE STRINGS + 7220 ; ------------------ + 7221 6CA7 0E E27: db E27L + 7222 6CA8 44 69 73 6B 20 db "Disk I/O Error" + 6CAD 49 2F 4F 20 45 + 6CB2 72 72 6F 72 + 7223 000E E27L EQU $-E27-1 + 7224 6CB6 14 E2B: db E2BL + 7225 6CB7 44 69 73 6B 20 db "Disk write protected" + 6CBC 77 72 69 74 65 + 6CC1 20 70 72 6F 74 + 6CC6 65 63 74 65 64 + 7226 0014 E2BL EQU $-E2B-1 + 7227 6CCB 0C E40: db E40L + 7228 6CCC 42 61 64 20 46 db "Bad Filename" + 6CD1 69 6C 65 6E 61 + 6CD6 6D 65 + 7229 000C E40L EQU $-E40-1 + 7230 6CD8 0E E44: db E44L + 7231 6CD9 50 61 74 68 20 db "Path not found" + 6CDE 6E 6F 74 20 66 + 6CE3 6F 75 6E 64 + 7232 000E E44L: EQU $-E44-1 + 7233 6CE7 10 E45: db E45L + 7234 6CE8 56 6F 6C 75 6D db "Volume not found" + 6CED 65 20 6E 6F 74 + 6CF2 20 66 6F 75 6E + 6CF7 64 + 7235 0010 E45L EQU $-E45-1 + 7236 6CF8 0E E46: db E46L + 7237 6CF9 46 69 6C 65 20 db "File Not Found" + 6CFE 4E 6F 74 20 46 + 6D03 6F 75 6E 64 + 7238 000E E46L EQU $-E46-1 + 7239 6D07 09 E48: db E48L + 7240 6D08 44 69 73 6B 20 db "Disk Full" + 6D0D 46 75 6C 6C + 7241 0009 E48L EQU $-E48-1 + 7242 6D11 21 E49: db E49L + 7243 6D12 4C 61 6E 65 44 db "LaneDOS limit: 12 files/directory" + 6D17 4F 53 20 6C 69 + 6D1C 6D 69 74 3A 20 + 6D21 31 32 20 66 69 + 6D26 6C 65 73 2F 64 + 6D2B 69 72 65 63 74 + 6D30 6F 72 79 + 7244 0021 E49L EQU $-E49-1 + 7245 6D33 26 E4E: db E4EL + 7246 6D34 4C 61 6E 65 44 db "LaneDOS limit: No writes to TREE files" + 6D39 4F 53 20 6C 69 + 6D3E 6D 69 74 3A 20 + 6D43 4E 6F 20 77 72 + 6D48 69 74 65 73 20 + Wed May 24 1989 15:00 Page 110 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- ZIP DATA TABLES ---" + + 6D4D 74 6F 20 54 52 + 6D52 45 45 20 66 69 + 6D57 6C 65 73 + 7247 0026 E4EL EQU $-E4E-1 + 7248 6D5A 0E E4C: db E4CL + 7249 6D5B 55 6E 65 78 70 db "Unexpected EOF" + 6D60 65 63 74 65 64 + 6D65 20 45 4F 46 + 7250 000E E4CL EQU $-E4C-1 + 7251 + 7252 6D69 27 ELIST: db $27 + 7253 6D6A A76C dw E27 + 7254 6D6C 2B db $2B + 7255 6D6D B66C dw E2B + 7256 6D6F 40 db $40 + 7257 6D70 CB6C dw E40 + 7258 6D72 44 db $44 + 7259 6D73 D86C dw E44 + 7260 6D75 45 db $45 + 7261 6D76 E76C dw E45 + 7262 6D78 46 db $46 + 7263 6D79 F86C dw E46 + 7264 6D7B 48 db $48 + 7265 6D7C 076D dw E48 + 7266 6D7E 49 db $49 + 7267 6D7F 116D dw E49 + 7268 6D81 4C db $4C + 7269 6D82 5A6D dw E4C + 7270 6D84 4E db $4E + 7271 6D85 336D dw E4E + 7272 001B ELISTL EQU $-ELIST-3 ; mark last error code + 7273 + 7274 6D87 END + 7275 + 7276 6D87 INCLUDE WINDOWS.ASM + 7277 + 7278 6D87 STTL "--- WINDOW OPERATIONS ---" + 7279 PAGE + Wed May 24 1989 15:00 Page 111 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7280 ; + 7281 ; these are the data structures for all 8 WINDOW. They are identical and + 7282 ; are just seperated cuz I use the addresses in the table that follows. + 7283 ; All numbers are inclusive, absolute, and zero-based. + 7284 ; + 7285 0000 WINDSTRUCT EQU 0 + 7286 0000 WINTOP EQU WINDSTRUCT ; first line of the window + 7287 0001 WINLEFT EQU WINTOP+1 ; left edge of the window + 7288 0002 WINHGHT EQU WINLEFT+1 ; height of the window + 7289 0003 WINWID EQU WINHGHT+1 ; width of the window, in pixels + 7290 0004 WINY EQU WINWID+1 ; y pos of cursor (pos, not relative) + 7291 0005 WINX EQU WINY+1 ; x pos of cursor (remember, ABSOLUTE) + 7292 0006 WINLM EQU WINX+1 ; left margin + 7293 0007 WINRM EQU WINLM+1 ; right margin + 7294 0008 WINCRF EQU WINRM+1 ; (WORD) function + 7295 000A WINCRC EQU WINCRF+2 ; (WORD) counter + 7296 000C WINHIGHL EQU WINCRC+2 ; highlight mode + 7297 000D WINFORE EQU WINHIGHL+1 ; foreground color (0=black-7=white) + 7298 000E WINBGND EQU WINFORE+1 ; background color (0=black-7=white) + 7299 000F WINFONT EQU WINBGND+1 ; window font (0=normal/4=monospaced) + 7300 0010 WINFSIZE EQU WINFONT+1 ; (WORD) font Height/Width + 7301 0012 WINATR EQU WINFSIZE+2 ; Window Attributes + 7302 0013 WINLCNT EQU WINATR+1 ; current number of lines + 7303 ; + 7304 ; these are my interesting things + 7305 ; + 7306 0014 WINXSZ EQU WINLCNT+1 ; width of window, in pixels, using margin + 7307 0015 WINLLEN EQU WINXSZ+1 ; length of current line + 7308 0017 WINLINES EQU WINLLEN+2 ; max # of lines for window + 7309 + 7310 6D87 WINDOW0: + 7311 6D87 00 DB 0 ; WINTOP - first line of the window + 7312 6D88 00 DB 0 ; WINLEFT - left edge of the window + 7313 6D89 C0 DB MAXHEIGHT ; WINHGHT - height of window + 7314 6D8A 8C DB MAXWIDTH ; WINWID - width of window + 7315 6D8B 00 DB 0 ; WINY - y pos of cursor (pos, not relative) + 7316 6D8C 00 DB 0 ; WINX - x pos of cursor (remember, ABSOLUTE) + 7317 6D8D 00 DB 0 ; WINLM - left margin + 7318 6D8E 00 DB 0 ; WINRM - right margin + 7319 6D8F 0000 DW 0 ; WINCRF - function + 7320 6D91 0000 DW 0 ; WINCRC - counter + 7321 6D93 00 DB 0 ; WINHIGHL - Highlights + 7322 6D94 0F DB $f ; WINFORE - foreground color default of white + 7323 6D95 00 DB 0 ; WINBGND - background color + 7324 6D96 00 DB 0 ; WINFONT - window font (0=normal/1=alternate) + 7325 6D97 02 09 DB 2,FONT_H ; WINFSIZE - Width/Height + 7326 6D99 0F DB $0f ; WINATR - all attributes on for window 0 + 7327 6D9A 00 DB 0 ; WINLCNT - current number of lines + 7328 6D9B 8C DB MAXWIDTH ; WINXSZ - width of window, in pixels, using margin + 7329 6D9C 00 00 DB 0,0 ; WINLLEN - length of current line + 7330 6D9E 14 DB (MAXHEIGHT/FONT_H)-1 ; WINLINES - max # of lines for window + 7331 ; + 7332 ; same start as window 0, but with 0 length + 7333 ; + 7334 6D9F WINDOW1: + 7335 6D9F 00 00 00 8C 00 DB 0,0,0,MAXWIDTH,0,0,0,0,0,0,0,0,0 + 6DA4 00 00 00 00 00 + 6DA9 00 00 00 + 7336 6DAC 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,MAXWIDTH,0,0,0 + 6DB1 08 00 8C 00 00 + 6DB6 00 + 7337 ; + 7338 ; the rest have no width/height/attributes (except buffering) + 7339 ; + 7340 6DB7 WINDOW2: + 7341 6DB7 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6DBC 00 00 00 00 00 + 6DC1 00 00 00 + 7342 6DC4 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6DC9 08 00 00 00 00 + 6DCE 00 + 7343 6DCF WINDOW3: + 7344 6DCF 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6DD4 00 00 00 00 00 + 6DD9 00 00 00 + Wed May 24 1989 15:00 Page 112 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7345 6DDC 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6DE1 08 00 00 00 00 + 6DE6 00 + 7346 6DE7 WINDOW4: + 7347 6DE7 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6DEC 00 00 00 00 00 + 6DF1 00 00 00 + 7348 6DF4 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6DF9 08 00 00 00 00 + 6DFE 00 + 7349 6DFF WINDOW5: + 7350 6DFF 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6E04 00 00 00 00 00 + 6E09 00 00 00 + 7351 6E0C 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6E11 08 00 00 00 00 + 6E16 00 + 7352 6E17 WINDOW6: + 7353 6E17 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6E1C 00 00 00 00 00 + 6E21 00 00 00 + 7354 6E24 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6E29 08 00 00 00 00 + 6E2E 00 + 7355 6E2F WINDOW7: + 7356 6E2F 00 00 00 00 00 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + 6E34 00 00 00 00 00 + 6E39 00 00 00 + 7357 6E3C 0F 00 00 02 09 DB $F,0,0,2,FONT_H,$08,0,0,0,0,0 + 6E41 08 00 00 00 00 + 6E46 00 + 7358 + 7359 6E47 WINTABLE: + 7360 6E47 876D 9F6D B76D DW WINDOW0,WINDOW1,WINDOW2,WINDOW3 + 6E4D CF6D + 7361 6E4F E76D FF6D 176E DW WINDOW4,WINDOW5,WINDOW6,WINDOW7 + 6E55 2F6E + 7362 PAGE + Wed May 24 1989 15:00 Page 113 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7363 + 7364 ; ------ + 7365 ; SCREEN + 7366 ; ------ + 7367 ; Move to the screen specified, by updating CURWIN and the cursor + 7368 ; X,Y pos (SCRX,SCRY). Also put address of that window's structure + 7369 ; in WINDOW. Save a bunch of the old stuff in old window's structure then + 7370 ; update the same bunch with the new window's stuff. + 7371 ; + 7372 ; ARG1 - new screen id: 0-7 + 7373 ; + 7374 6E57 ZSCRN: + 7375 6E57 20 AD 55 jsr CLRBUF ; EMPTY OUTPUT BUFFER BEFORE MOVING + 7376 ; + 7377 ; now, save a few things from the common variables + 7378 ; + 7379 6E5A A0 15 ldy #WINLLEN ; current line length + 7380 6E5C A5 A7 lda LENGTH+LO ; get current line length + 7381 6E5E 91 05 sta (WINDOW),Y ; save for later referencing + 7382 6E60 C8 iny ; point to msb + 7383 6E61 A5 A8 lda LENGTH+HI ; get MSB + 7384 6E63 91 05 sta (WINDOW),Y ; saved + 7385 6E65 20 9F 4D jsr SAVE_CURSOR ; save the x,y pos of cursor + 7386 6E68 A5 BB lda INVFLG ; get inverse flag + 7387 6E6A F0 04 beq ZSCA1 ; not set + 7388 6E6C A9 01 lda #1 ; set 1 bit + 7389 6E6E D0 06 bne ZSCA2 ; set in window + 7390 6E70 ZSCA1: + 7391 6E70 A5 BA lda UNDFLG ; how about underlining + 7392 6E72 F0 02 beq ZSCA2 ; nope + 7393 6E74 A9 04 lda #4 ; 4 == underlining + 7394 6E76 ZSCA2: + 7395 6E76 A0 0C ldy #WINHIGHL ; set new highlight + 7396 6E78 91 05 sta (WINDOW),Y ; save current attributes + 7397 ; + 7398 ; now it is time to update for new screen + 7399 ; + 7400 6E7A A5 63 lda ARG1+LO ; get which window + 7401 6E7C 85 A6 sta CURWIN ; save window number + 7402 6E7E 0A asl A ; shift to make word indes + 7403 6E7F AA tax ; swap to indexing reg + 7404 6E80 BD 47 6E lda WINTABLE,X ; get the address of the new WINDOW + 7405 6E83 85 05 sta WINDOW+LO ; lo part comes first + 7406 6E85 BD 48 6E lda WINTABLE+1,X ; so go get hi part + 7407 6E88 85 06 sta WINDOW+HI ; save the hi part of the address + 7408 + 7409 6E8A 20 B1 4D jsr GET_CURSOR ; restore the cursor pos + 7410 + 7411 6E8D A0 14 ldy #WINXSZ ; get line length + 7412 6E8F B1 05 lda (WINDOW),Y ; update zero page variable + 7413 6E91 85 A2 sta XSIZE+LO ; this is for quicky comparing + 7414 6E93 A9 00 lda #0 ; clear MSB + 7415 6E95 85 A3 sta XSIZE+HI + 7416 6E97 06 A2 asl XSIZE+LO ; *2 + 7417 6E99 26 A3 rol XSIZE+HI + 7418 6E9B 06 A2 asl XSIZE+LO ; *4 + 7419 6E9D 26 A3 rol XSIZE+HI + 7420 6E9F A0 15 ldy #WINLLEN ; get current line length + 7421 6EA1 B1 05 lda (WINDOW),Y ; from before + 7422 6EA3 85 A7 sta LENGTH+LO ; save for later checking + 7423 6EA5 C8 iny + 7424 6EA6 B1 05 lda (WINDOW),Y + 7425 6EA8 85 A8 sta LENGTH+HI + 7426 6EAA A0 13 ldy #WINLCNT ; how many lines already out there + 7427 6EAC B1 05 lda (WINDOW),Y ; has been already saved + 7428 6EAE 85 AB sta LINCNT ; and save 'ere too + 7429 6EB0 A0 17 ldy #WINLINES ; how many lines in this + 7430 6EB2 B1 05 lda (WINDOW),Y ; window, anyway? + 7431 6EB4 85 03 sta MAXLINES ; show for everyone to see + 7432 6EB6 A0 01 ldy #WINLEFT ; show left margin + 7433 6EB8 B1 05 lda (WINDOW),Y ; get left edge + 7434 6EBA A0 06 ldy #WINLM ; left margin + 7435 6EBC 18 clc ; adding + 7436 6EBD 71 05 adc (WINDOW),Y ; to find new left margin + 7437 6EBF 85 04 sta LEFTMRG ; set up left margin for ease of use + Wed May 24 1989 15:00 Page 114 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7438 6EC1 A0 00 ldy #WINTOP ; get top of window + 7439 6EC3 B1 05 lda (WINDOW),Y ; got it + 7440 6EC5 18 clc ; adding + 7441 6EC6 A0 02 ldy #WINHGHT ; add height + 7442 6EC8 71 05 adc (WINDOW),Y ; did it + 7443 6ECA 85 02 sta SCRBTM ; this is first line outside window + 7444 6ECC A0 0C ldy #WINHIGHL ; get highlighting modes + 7445 6ECE B1 05 lda (WINDOW),Y ; first for inverse video + 7446 6ED0 29 01 and #1 ; check for inverse video + 7447 6ED2 F0 02 beq SCRINV ; nope + 7448 6ED4 A9 80 lda #$80 ; means inverse video + 7449 6ED6 SCRINV: + 7450 6ED6 85 BB sta INVFLG ; there it be + 7451 6ED8 B1 05 lda (WINDOW),Y ; point to underline flag + 7452 6EDA 29 04 and #4 ; check for underlining + 7453 6EDC F0 02 beq SCRUND ; nope + 7454 6EDE A9 80 lda #$80 ; means underlining + 7455 6EE0 SCRUND: + 7456 6EE0 85 BA sta UNDFLG ; save for everyone + 7457 + 7458 6EE2 A0 12 ldy #WINATR ; get the current attributes + 7459 6EE4 B1 05 lda (WINDOW),Y ; gottem + 7460 6EE6 20 68 70 jsr SET_ATTRIBUTES ; set the flags, thank you + 7461 6EE9 A0 0F ldy #WINFONT ; get the font + 7462 6EEB B1 05 lda (WINDOW),Y ; thank you + 7463 6EED F0 02 beq SCRFNT0 ; is it font zero? + 7464 6EEF A9 0C lda #MONOFONT_W ; must be mono font, set width + 7465 6EF1 SCRFNT0: + 7466 6EF1 85 C1 sta FONTFLG ; mark normal font + 7467 6EF3 ZSCREX: + 7468 6EF3 60 rts + 7469 ;-------------- + 7470 ; ZWINPOS + 7471 ;-------------- + 7472 ; + 7473 ; change the window ARG1's top left corner to the new position + 7474 ; + 7475 ; ARG1 - window id from 0-7 + 7476 ; ARG2 - new top y pos + 7477 ; ARG3 - new top x pos + 7478 ; + 7479 6EF4 ZWINPOS: + 7480 6EF4 C6 65 dec ARG2+LO ; make pos be zero based + 7481 6EF6 C6 67 dec ARG3+LO ; now they are! + 7482 ; + 7483 ; if moving current window, save current cursor pos + 7484 ; + 7485 6EF8 ZWPOS0: + 7486 6EF8 20 9F 4D jsr SAVE_CURSOR ; saving + 7487 ; + 7488 ; let's set up [J] to point to window we are talking about + 7489 ; + 7490 6EFB ZWPOS1: + 7491 6EFB A5 63 lda ARG1+LO ; get window ID + 7492 6EFD 20 77 57 jsr SETWJ ; get J to point to it + 7493 + 7494 6F00 A5 65 lda ARG2+LO ; first, check the top + 7495 6F02 C9 C0 cmp #MAXHEIGHT ; < max height? + 7496 6F04 90 04 bcc CKWA1 ; fine + 7497 6F06 A9 00 lda #0 ; make it zero then + 7498 6F08 85 65 sta ARG2+LO ; it is now + 7499 6F0A CKWA1: + 7500 6F0A A5 67 lda ARG3+LO ; now check left edge + 7501 6F0C C9 8C cmp #MAXWIDTH ; howzit compare + 7502 6F0E 90 04 bcc CKWA2 ; just fine + 7503 6F10 A9 00 lda #0 ; this too + 7504 6F12 85 67 sta ARG3+LO ; it is now + 7505 6F14 CKWA2: + 7506 ; + 7507 ; make the cursor pos be relative, so we can change back to + 7508 ; absolute using new window pos + 7509 ; + 7510 6F14 A0 04 ldy #WINY ; let's do y pos first + 7511 6F16 B1 7A lda (J),Y ; get the old y pos + 7512 6F18 A0 00 ldy #WINTOP ; and subtract the top to make + Wed May 24 1989 15:00 Page 115 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7513 6F1A 38 sec ; (getting ready) + 7514 6F1B F1 7A sbc (J),Y ; the pos relative + 7515 6F1D 18 clc ; now add in new top + 7516 6F1E 65 65 adc ARG2+LO ; this will be new top + 7517 6F20 A0 04 ldy #WINY ; get y offset again + 7518 6F22 91 7A sta (J),Y ; and save new absolute y pos + 7519 6F24 A0 05 ldy #WINX ; now we be talking about x pos + 7520 6F26 B1 7A lda (J),Y ; get old x pos + 7521 6F28 38 sec ; getting ready for sub + 7522 6F29 A0 01 ldy #WINLEFT ; get rid of left ness + 7523 6F2B F1 7A sbc (J),Y ; now it's relative + 7524 6F2D 18 clc ; get ready to add in new left ness + 7525 6F2E 65 67 adc ARG3+LO ; done + 7526 6F30 A0 05 ldy #WINX ; get x offset again + 7527 6F32 91 7A sta (J),Y ; save in structure + 7528 ; + 7529 ; now we can change the top and left of the window + 7530 ; + 7531 6F34 A5 65 lda ARG2+LO ; this is top of window + 7532 6F36 A0 00 ldy #WINTOP ; TOP offset + 7533 6F38 91 7A sta (J),Y ; save the new top + 7534 6F3A A5 67 lda ARG3+LO ; here is the left edge + 7535 6F3C A0 01 ldy #WINLEFT ; offset into struct + 7536 6F3E 91 7A sta (J),Y ; saved ! + 7537 ; + 7538 ; we might have moved current window so update screen cursor and left margin + 7539 ; + 7540 6F40 20 B1 4D jsr GET_CURSOR ; restore cursor + 7541 6F43 A0 01 ldy #WINLEFT ; get left edge + 7542 6F45 B1 05 lda (WINDOW),Y ; okay + 7543 6F47 A0 06 ldy #WINLM ; add in left margin + 7544 6F49 18 clc ; adding + 7545 6F4A 71 05 adc (WINDOW),Y ; to find new left edge + 7546 6F4C 85 04 sta LEFTMRG ; store for ease of use + 7547 6F4E A0 14 ldy #WINXSZ ; get xsize + 7548 6F50 B1 7A lda (J),Y ; okay + 7549 6F52 85 A2 sta XSIZE+LO ; this is for quicky comparing + 7550 6F54 A9 00 lda #0 ; clear MSB + 7551 6F56 85 A3 sta XSIZE+HI + 7552 6F58 06 A2 asl XSIZE+LO ; *2 + 7553 6F5A 26 A3 rol XSIZE+HI + 7554 6F5C 06 A2 asl XSIZE+LO ; *4 + 7555 6F5E 26 A3 rol XSIZE+HI + 7556 6F60 ZWPOSX: + 7557 6F60 60 rts + 7558 ;------------ + 7559 ; ZWINSIZE + 7560 ;------------ + 7561 ; + 7562 ; Change the size of window ARG1. If cursor is outside of window, + 7563 ; move to it. + 7564 ; + 7565 ; ARG1 - window ID + 7566 ; ARG2 - height + 7567 ; ARG3 - width + 7568 ; + 7569 ; Uses [J]. + 7570 ; + 7571 6F61 ZWINSIZE: + 7572 ; + 7573 ; first put SCRCX,CY into window structure, just in case + 7574 ; + 7575 6F61 20 9F 4D jsr SAVE_CURSOR ; saved + 7576 ; + 7577 ; now do everything + 7578 ; + 7579 6F64 A5 63 lda ARG1+LO ; get the window ID + 7580 6F66 20 77 57 jsr SETWJ ; and get window pointer + 7581 + 7582 6F69 A5 65 lda ARG2+LO ; first, check the top + 7583 6F6B C9 C0 cmp #MAXHEIGHT ; < max height? + 7584 6F6D 90 04 bcc CKWA11 ; fine + 7585 6F6F A9 C0 lda #MAXHEIGHT ; make better + 7586 6F71 85 65 sta ARG2+LO ; it is now + 7587 6F73 CKWA11: + Wed May 24 1989 15:00 Page 116 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7588 6F73 A5 67 lda ARG3+LO ; now check left edge + 7589 6F75 C9 8C cmp #MAXWIDTH ; howzit compare + 7590 6F77 90 04 bcc CKWA21 ; just fine + 7591 6F79 A9 8C lda #MAXWIDTH ; make it the max + 7592 6F7B 85 67 sta ARG3+LO ; it is now + 7593 6F7D CKWA21: + 7594 6F7D A5 65 lda ARG2+LO ; get new height + 7595 6F7F A0 02 ldy #WINHGHT ; offset + 7596 6F81 91 7A sta (J),Y ; save new height + 7597 6F83 A5 67 lda ARG3+LO ; get width + 7598 6F85 A0 03 ldy #WINWID ; store width + 7599 6F87 91 7A sta (J),Y ; okay + 7600 ; + 7601 ; now we need to figger out new XSIZE, MAXLINES + 7602 ; + 7603 6F89 A0 03 ldy #WINWID ; store width + 7604 6F8B B1 7A lda (J),Y ; get width + 7605 6F8D 38 sec ; have width, subtract margins + 7606 6F8E A0 07 ldy #WINRM ; first right margin + 7607 6F90 F1 7A sbc (J),Y ; subtracted right margin + 7608 6F92 A0 06 ldy #WINLM ; and now for the left margin + 7609 6F94 F1 7A sbc (J),Y ; now we have new XSIZE + 7610 6F96 A0 14 ldy #WINXSZ ; get offset + 7611 6F98 91 7A sta (J),Y ; save for later ref + 7612 6F9A A5 65 lda ARG2+LO ; get new height + 7613 6F9C A2 FF ldx #$FF ; this is the counter + 7614 6F9E 38 sec ; get ready for subs + 7615 6F9F ZWSZ1: + 7616 6F9F E8 inx ; count this line + 7617 6FA0 E9 09 sbc #FONT_H ; subtract off font height + 7618 6FA2 B0 FB bcs ZWSZ1 ; still some lines + 7619 6FA4 CA dex ; to keep the input line on screen + 7620 6FA5 8A txa ; get line count for storage + 7621 6FA6 A0 17 ldy #WINLINES ; this is how many lines are allowed + 7622 6FA8 91 7A sta (J),Y ; saved + 7623 ; + 7624 ; check to make sure the cursor is still in the window + 7625 ; + 7626 6FAA A0 06 ldy #WINLM ; get left margin + 7627 6FAC 18 clc ; for adding + 7628 6FAD 71 7A adc (J),Y ; for figgering out right edge + 7629 6FAF A0 01 ldy #WINLEFT ; add in left edge + 7630 6FB1 71 7A adc (J),Y ; get right column by adding in left one + 7631 6FB3 A0 05 ldy #WINX ; check X pos + 7632 6FB5 D1 7A cmp (J),Y ; see if X is still inside? + 7633 6FB7 F0 13 beq ZWSZ2 ; must move to top left + 7634 6FB9 90 11 bcc ZWSZ2 ; ditto if X >= margin + 7635 6FBB A0 00 ldy #WINTOP ; get top to figger last line + 7636 6FBD B1 7A lda (J),Y ; from the structure + 7637 6FBF A0 02 ldy #WINHGHT ; and add in the height + 7638 6FC1 18 clc ; getting ready for add + 7639 6FC2 71 7A adc (J),Y ; to find first line outside of range + 7640 6FC4 A0 04 ldy #WINY ; now check y + 7641 6FC6 D1 7A cmp (J),Y ; now check y then + 7642 6FC8 F0 02 beq ZWSZ2 ; outside, move to top left + 7643 6FCA B0 15 bcs ZWSZ3 ; inside so quit + 7644 ; + 7645 ; move the cursor to top left if outside of resized window + 7646 ; + 7647 6FCC ZWSZ2: + 7648 6FCC A0 00 ldy #WINTOP ; top line is here + 7649 6FCE B1 7A lda (J),Y ; so get me it + 7650 6FD0 A0 04 ldy #WINY ; now we be doing y + 7651 6FD2 91 7A sta (J),Y ; change Y + 7652 6FD4 A0 01 ldy #WINLEFT ; move X to left margin + 7653 6FD6 B1 7A lda (J),Y ; first get left edge + 7654 6FD8 A0 06 ldy #WINLM ; and add in left margin + 7655 6FDA 18 clc ; (adding) + 7656 6FDB 71 7A adc (J),Y ; to get left spot of cursor + 7657 6FDD A0 05 ldy #WINX ; this is x offset + 7658 6FDF 91 7A sta (J),Y ; so move X there + 7659 ; + 7660 ; now check to see if we mucked with current window + 7661 ; + 7662 6FE1 ZWSZ3: + Wed May 24 1989 15:00 Page 117 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7663 6FE1 A5 64 lda ARG1+HI ; this is the id + 7664 6FE3 30 04 bmi ZWSZ4 ; must be current window + 7665 6FE5 C5 A6 cmp CURWIN ; is it current window? + 7666 6FE7 D0 1B bne ZWSZX ; nope, so done + 7667 6FE9 ZWSZ4: + 7668 6FE9 A0 17 ldy #WINLINES ; get how many lines + 7669 6FEB B1 7A lda (J),Y ; get number of lines + 7670 6FED 85 03 sta MAXLINES ; set global + 7671 6FEF A0 14 ldy #WINXSZ ; get new XSIZE too + 7672 6FF1 B1 7A lda (J),Y ; get it + 7673 6FF3 85 A2 sta XSIZE+LO ; this is for quicky comparing + 7674 6FF5 A9 00 lda #0 ; clear MSB + 7675 6FF7 85 A3 sta XSIZE+HI + 7676 6FF9 06 A2 asl XSIZE+LO ; *2 + 7677 6FFB 26 A3 rol XSIZE+HI + 7678 6FFD 06 A2 asl XSIZE+LO ; *4 + 7679 6FFF 26 A3 rol XSIZE+HI + 7680 7001 20 B1 4D jsr GET_CURSOR ; fix the cursor pos + 7681 7004 ZWSZX: + 7682 7004 60 rts + 7683 ; + 7684 ;CHECK_WIN_ARGS + 7685 ; check args to make sure they be okay + 7686 ; + 7687 ; ARG2 = top/height + 7688 ; ARG3 = right/width + 7689 ; + 7690 7005 CHECK_WIN_ARGS: + 7691 7005 60 rts + 7692 + 7693 ; ------ + 7694 ; HLIGHT + 7695 ; ------ + 7696 + 7697 7006 ZLIGHT: + 7698 7006 A5 63 lda ARG1+LO ; get argument + 7699 7008 C9 10 cmp #$10 ; must be <= 8 + 7700 700A B0 05 bcs ZLIEX ; nope it aint + 7701 700C 09 80 ora #$80 ; turn on hi bit + 7702 700E 20 06 53 jsr COUT ; send it out then + 7703 7011 ZLIEX: + 7704 7011 60 rts ; done + 7705 ; + 7706 ; actually set the highlight flags according to [A] + 7707 ; + 7708 7012 HLIGHT: + 7709 ; + 7710 ; TURN OFF ALL HIGHLIGHTS + 7711 ; + 7712 7012 29 7F and #$7F ; turn off high bit + 7713 7014 D0 05 bne ZL1 ; nope, must be something + 7714 7016 85 BA sta UNDFLG ; and turn of underlining flag + 7715 7018 85 BB sta INVFLG ; and inverse + 7716 701A 60 rts ; all done + 7717 701B ZL1: + 7718 701B C9 04 cmp #4 ; underlining + 7719 701D D0 05 bne ZL_REV ; maybe its INVERSE? + 7720 + 7721 701F A9 80 lda #$80 ; turn on UNDFLG + 7722 7021 85 BA sta UNDFLG ; with an FF + 7723 7023 60 rts ; done + 7724 7024 ZL_REV: + 7725 7024 C9 01 cmp #1 ; INVERSE? + 7726 7026 D0 05 bne ZL_MONO ; maybe monospaced then + 7727 7028 A9 80 lda #$80 ; must be inverse video + 7728 702A 85 BB sta INVFLG ; and put it in invflg + 7729 702C 60 rts + 7730 702D ZL_MONO: + 7731 702D 60 rts ; fuck it for now! + 7732 ; + 7733 ; ZWINATTER - change the scrolling/buffering/scripting/wrapping attributes + 7734 ; of the window. + 7735 ; + 7736 ; ARG1 - window id + 7737 ; ARG2 - interesting bits + Wed May 24 1989 15:00 Page 118 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7738 ; | buffering | scripting | scrolling | wrapping | + 7739 ; ARG3 - operation - 0 MOVE + 7740 ; 1 SET + 7741 ; 2 CLEAR + 7742 ; 3 COMPLEMENT + 7743 ; + 7744 702E ZWINATTR: + 7745 702E A5 62 lda NARGS ; see how many args + 7746 7030 C9 03 cmp #3 ; check for operation args + 7747 7032 F0 04 beq ZWAT1 ; yes, already there + 7748 7034 A9 00 lda #0 ; zero means MOVE + 7749 7036 85 67 sta ARG3+LO ; so show it as default + 7750 7038 ZWAT1: + 7751 7038 A5 63 lda ARG1+LO ; get window ID + 7752 703A 20 77 57 jsr SETWJ ; put window address into [J] + 7753 + 7754 703D A0 12 ldy #WINATR ; get attribute offset + 7755 703F B1 7A lda (J),Y ; get current attribute + 7756 7041 18 clc ; so we can just branch + 7757 + 7758 7042 C6 67 dec ARG3+LO ; decrement to find out what to do + 7759 7044 30 0A bmi ZWMOVE ; do a move + 7760 7046 F0 0C beq ZWSET ; do a set + 7761 7048 C6 67 dec ARG3+LO ; check once more + 7762 704A F0 0C beq ZWCLEAR ; clear set ones + 7763 ; + 7764 ; this is for the COMPLEMENT operations + 7765 ; + 7766 704C 45 65 eor ARG2+LO ; complement bits + 7767 704E 90 0E bcc ZWAT2 ; done + 7768 7050 ZWMOVE: + 7769 ; + 7770 ; move into the flag word + 7771 ; + 7772 7050 A5 65 lda ARG2+LO ; get new flags + 7773 7052 90 0A bcc ZWAT2 ; done + 7774 7054 ZWSET: + 7775 ; + 7776 ; set turned on ones + 7777 ; + 7778 7054 05 65 ora ARG2+LO ; set'em up + 7779 7056 90 06 bcc ZWAT2 ; done + 7780 7058 ZWCLEAR: + 7781 ; + 7782 ; clear just the ones that are on + 7783 ; + 7784 7058 A5 65 lda ARG2+LO ; get argument + 7785 705A 49 FF eor #$FF ; turn on all the off ones + 7786 705C 31 7A and (J),Y ; keep all the other ones + 7787 705E ZWAT2: + 7788 705E 91 7A sta (J),Y ; and save it back + 7789 ; + 7790 ; now, if current window, set necessary flags + 7791 ; + 7792 7060 A6 63 ldx ARG1+LO ; get window ID + 7793 7062 30 04 bmi SET_ATTRIBUTES ; assume negative is current window + 7794 7064 E4 A6 cpx CURWIN ; is this the current one? + 7795 7066 D0 30 bne ZWATX ; nope, so leave + 7796 7068 SET_ATTRIBUTES: + 7797 ; + 7798 ; current window, so set flags accordingly + 7799 ; + 7800 7068 A2 00 ldx #0 ; to turn off flag + 7801 706A A0 01 ldy #1 ; to turn on flag + 7802 706C 6A ror A ; get wrapping flag into carry + 7803 706D 90 05 bcc ZWAT3 ; clear it + 7804 706F 8C D6 71 sty WRPFLG ; set wrapping on + 7805 7072 B0 03 bcs ZWAT33 ; okay + 7806 7074 ZWAT3: + 7807 7074 8E D6 71 stx WRPFLG ; clear wrapping flag + 7808 7077 ZWAT33: + 7809 7077 6A ror A ; now check thes crolling flag + 7810 7078 90 05 bcc ZWAT4 ; not set + 7811 707A 8C D7 71 sty SCRLFLG ; turn on scrolling flag + 7812 707D B0 03 bcs ZWAT44 ; okay, next please + Wed May 24 1989 15:00 Page 119 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7813 707F ZWAT4: + 7814 707F 8E D7 71 stx SCRLFLG ; turn off scrolling + 7815 7082 ZWAT44: + 7816 7082 6A ror A ; checking the scripting flag + 7817 7083 90 05 bcc ZWAT5 ; not set + 7818 7085 8C 74 6C sty SCRIPTFLG ; allow scripting? yes + 7819 7088 B0 03 bcs ZWAT55 ; next flag + 7820 708A ZWAT5: + 7821 708A 8E 74 6C stx SCRIPTFLG ; allow scripting? no + 7822 708D ZWAT55: + 7823 708D 6A ror A ; this checks the buffering flag + 7824 708E 90 05 bcc ZWAT6 ; not set + 7825 7090 8C D8 71 sty BUFFLG ; turn on buffering + 7826 7093 B0 03 bcs ZWATX ; scram + 7827 7095 ZWAT6: + 7828 7095 8E D8 71 stx BUFFLG ; turn off buffering + 7829 7098 ZWATX: + 7830 7098 60 rts + 7831 ; + 7832 ; ZWINGET - put the window stuff into a table + 7833 ; + 7834 ; ARG1 - Window id + 7835 ; ARG2 - offset + 7836 ; + 7837 7099 ZWINGET: + 7838 7099 20 9F 4D jsr SAVE_CURSOR ; save x,y into structure + 7839 + 7840 709C A5 63 lda ARG1+LO ; get window ID + 7841 709E 20 77 57 jsr SETWJ ; set up window address + 7842 + 7843 70A1 A5 65 lda ARG2+LO ; get where to start getting + 7844 70A3 0A asl A ; make word index + 7845 70A4 AA tax ; make index + 7846 70A5 BD 41 71 lda ZWGTBL+LO,X ; get lo part of address + 7847 70A8 85 7C sta K+LO ; save for jumping + 7848 70AA BD 42 71 lda ZWGTBL+HI,X ; get hi part + 7849 70AD 85 7D sta K+HI ; saved + 7850 70AF 20 B9 70 jsr ZWGVEC ; do the vectoring + 7851 70B2 86 77 stx VALUE+HI ; save hi part + 7852 70B4 85 76 sta VALUE+LO ; and the lo part + 7853 70B6 4C E1 43 jmp PUTVAL ; and return it + 7854 70B9 ZWGVEC: + 7855 70B9 6C 7C 00 jmp (K) ; and goto it boys + 7856 70BC ZWG0: + 7857 70BC A2 00 ldx #0 ; zero out high part + 7858 70BE A0 00 ldy #WINTOP ; get window y pos + 7859 70C0 B1 7A lda (J),Y ; got it + 7860 70C2 A8 tay ; need to inc it + 7861 70C3 C8 iny ; to make it a one-based number + 7862 70C4 98 tya ; back to a + 7863 70C5 60 rts + 7864 70C6 ZWG1: + 7865 70C6 A2 00 ldx #0 ; zero out high part + 7866 70C8 A0 01 ldy #WINLEFT ; get window x pos + 7867 70CA B1 7A lda (J),Y ; got it + 7868 70CC A8 tay ; need to inc it + 7869 70CD C8 iny ; to make it a one-based number + 7870 70CE 98 tya ; back to a + 7871 70CF 60 rts + 7872 70D0 ZWG2: + 7873 70D0 A2 00 ldx #0 ; zero out high part + 7874 70D2 A0 02 ldy #WINHGHT ; get window height + 7875 70D4 B1 7A lda (J),Y ; got it + 7876 70D6 60 rts + 7877 70D7 ZWG3: + 7878 70D7 A2 00 ldx #0 ; zero out high part + 7879 70D9 A0 03 ldy #WINWID ; window width + 7880 70DB B1 7A lda (J),Y ; got it + 7881 70DD 60 rts + 7882 70DE ZWG4: + 7883 70DE 20 5C 57 jsr FETCHCY ; get the current Y pos + 7884 70E1 A2 00 ldx #0 ; zero out high part + 7885 70E3 60 rts + 7886 70E4 ZWG5: + 7887 70E4 20 69 57 jsr FETCHCX ; fetch the current X pos + Wed May 24 1989 15:00 Page 120 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7888 70E7 A2 00 ldx #0 ; zero out high part + 7889 70E9 60 rts + 7890 70EA ZWG6: + 7891 70EA A2 00 ldx #0 ; zero out high part + 7892 70EC A0 06 ldy #WINLM ; left margin + 7893 70EE B1 7A lda (J),Y ; got it + 7894 70F0 60 rts + 7895 70F1 ZWG7: + 7896 70F1 A2 00 ldx #0 ; zero out high part + 7897 70F3 A0 07 ldy #WINRM ; right margin + 7898 70F5 B1 7A lda (J),Y ; got it + 7899 70F7 60 rts + 7900 70F8 ZWG8: + 7901 70F8 A0 09 ldy #WINCRF+HI ; function + 7902 70FA B1 7A lda (J),Y ; got it, lo part + 7903 70FC AA tax ; save hi part + 7904 70FD 88 dey ; point to lo part + 7905 70FE B1 7A lda (J),Y ; got lo part + 7906 7100 60 rts + 7907 7101 ZWG9: + 7908 7101 A0 0B ldy #WINCRC+HI ; count + 7909 7103 B1 7A lda (J),Y ; got it, hi part + 7910 7105 AA tax ; save it + 7911 7106 88 dey ; now to lo part + 7912 7107 B1 7A lda (J),Y ; got it + 7913 7109 60 rts + 7914 710A ZWG10: + 7915 710A A0 0C ldy #WINHIGHL ; get high light mode + 7916 710C B1 7A lda (J),Y ; got it + 7917 710E A2 00 ldx #0 ; zero out high part + 7918 7110 60 rts + 7919 7111 ZWG11: + 7920 7111 A0 0E ldy #WINBGND ; and background + 7921 7113 B1 7A lda (J),Y ; got it + 7922 7115 A8 tay ; make index + 7923 7116 B9 47 6C lda APLCOLOR,Y ; get apl->zip color + 7924 7119 AA tax ; save for return + 7925 711A A0 0D ldy #WINFORE ; get foreground + 7926 711C B1 7A lda (J),Y ; got it + 7927 711E A8 tay ; save it + 7928 711F B9 47 6C lda APLCOLOR,Y ; get apl->zip color + 7929 7122 60 rts + 7930 7123 ZWG12: + 7931 7123 A0 0F ldy #WINFONT ; now for font id + 7932 7125 B1 7A lda (J),Y ; got it + 7933 7127 A2 00 ldx #0 ; zero out high part + 7934 7129 60 rts + 7935 712A ZWG13: + 7936 712A A0 11 ldy #WINFSIZE+1 ; font size (width) + 7937 712C B1 7A lda (J),Y ; got it + 7938 712E AA tax ; save it + 7939 712F 88 dey ; font size (height) + 7940 7130 B1 7A lda (J),Y ; got it + 7941 7132 60 rts + 7942 7133 ZWG14: + 7943 7133 A2 00 ldx #0 ; zero out high part + 7944 7135 A0 12 ldy #WINATR ; attributes + 7945 7137 B1 7A lda (J),Y ; got it + 7946 7139 60 rts ; got them! + 7947 713A ZWG15: + 7948 713A A2 00 ldx #0 ; only 1 byte worth + 7949 713C A0 13 ldy #WINLCNT ; offset + 7950 713E B1 7A lda (J),Y ; get more counter + 7951 7140 60 rts + 7952 ; + 7953 ; jump table for figgering out where to start filling + 7954 ; + 7955 7141 ZWGTBL: + 7956 7141 BC70 C670 D070 DW ZWG0,ZWG1,ZWG2,ZWG3,ZWG4,ZWG5,ZWG6,ZWG7 + 7147 D770 DE70 E470 + 714D EA70 F170 + 7957 7151 F870 0171 0A71 DW ZWG8,ZWG9,ZWG10,ZWG11,ZWG12,ZWG13,ZWG14,ZWG15 + 7157 1171 2371 2A71 + 715D 3371 3A71 + 7958 ; + Wed May 24 1989 15:00 Page 121 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 7959 ; ZSCROLL - scroll the specified window up or down + 7960 ; + 7961 ; ARG1 - window ID + 7962 ; ARG2 - lines to scroll; <0 scrolls down + 7963 ; + 7964 7161 ZSCROLL: + 7965 7161 20 9F 4D jsr SAVE_CURSOR ; save where cursor is + 7966 + 7967 7164 A9 00 lda #0 ; don't script scroll + 7968 7166 85 AA sta SCRIPT ; fine, we won't now + 7969 + 7970 7168 A5 63 lda ARG1+LO ; get which window + 7971 716A 20 77 57 jsr SETWJ ; set up pointer + 7972 716D C6 62 dec NARGS ; see what we have for lines + 7973 716F D0 04 bne ZSCR1 ; a passed arg + 7974 7171 A9 01 lda #1 ; 1 line is default + 7975 7173 85 65 sta ARG2+LO ; so say so + 7976 7175 ZSCR1: + 7977 7175 A0 00 ldy #WINTOP ; get me window limits + 7978 7177 B1 7A lda (J),Y ; first top + 7979 7179 85 0B sta CLSTOP ; save for usage + 7980 717B C8 iny ; now left + 7981 717C B1 7A lda (J),Y ; okay, get for this window + 7982 717E 85 0A sta CLSLEFT ; save left + 7983 7180 C8 iny ; now it's width + 7984 7181 B1 7A lda (J),Y ; got the window height + 7985 7183 85 0D sta CLSHEIGHT ; this is it + 7986 7185 C8 iny ; this is height + 7987 7186 B1 7A lda (J),Y ; get window's height + 7988 7188 85 0C sta CLSWIDTH ; save + 7989 718A A5 66 lda ARG2+HI ; is it negative? + 7990 718C 85 1D sta SCLDIR ; show direction of scroll + 7991 718E 10 08 bpl ZSCRL1 ; nope + 7992 7190 A6 65 ldx ARG2+LO ; get how many lines + 7993 7192 49 FF eor #$FF ; make pos + 7994 7194 AA tax ; put in X for inc + 7995 7195 E8 inx ; and make right + 7996 7196 D0 02 bne ZSCRLEX ; done + 7997 7198 ZSCRL1: + 7998 7198 A6 65 ldx ARG2+LO ; get how many lines + 7999 719A ZSCRLEX: + 8000 719A 86 18 stx SCLLINES ; save for routine + 8001 719C 20 03 60 jsr DO_SCROLL ; and do the scroll + 8002 719F ZSCRLEX1: + 8003 719F A9 01 lda #1 ; allow scripting + 8004 71A1 85 AA sta SCRIPT ; we do + 8005 71A3 4C B1 4D jmp GET_CURSOR ; restore the cursor, thank you + 8006 ; + 8007 ; ZWINPUT - put some information into window structure. Just CRF/CRC + 8008 ; is legit now. + 8009 ; + 8010 ; ARG1 - window ID + 8011 ; ARG2 - Word to be saved + 8012 ; ARG3 - offset of value + 8013 ; + 8014 71A6 ZWINPUT: + 8015 71A6 20 9F 4D jsr SAVE_CURSOR ; save the cursor pos + 8016 71A9 A5 63 lda ARG1+LO ; get window ID + 8017 71AB 20 77 57 jsr SETWJ ; have J point to structure + 8018 + 8019 71AE A5 65 lda ARG2+LO ; get first value in table + 8020 71B0 C9 08 cmp #8 ; 8 = function + 8021 71B2 F0 0D beq ZWIPCRF ; so save that + 8022 71B4 C9 09 cmp #9 ; this is counter + 8023 71B6 F0 0D beq ZWIPCRC ; so set counter + 8024 71B8 C9 0F cmp #15 ; LINCNT? + 8025 71BA F0 01 beq ZIPLCT ; then set it too + 8026 71BC 60 rts ; just die then + 8027 71BD ZIPLCT: + 8028 71BD A0 13 ldy #WINLCNT ; point to line count + 8029 71BF D0 0B bne ZWINPUT2 ; and stash it away + 8030 71C1 ZWIPCRF: + 8031 71C1 A0 09 ldy #WINCRF+1 ; point to window's CR function + 8032 71C3 D0 02 bne ZWINPUT1 ; and put it + 8033 71C5 ZWIPCRC: + Wed May 24 1989 15:00 Page 122 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- WINDOW OPERATIONS ---" + + 8034 71C5 A0 0B ldy #WINCRC+1 ; point to window's CR counter + 8035 71C7 ZWINPUT1: + 8036 71C7 A5 68 lda ARG3+HI ; now get hi part + 8037 71C9 91 7A sta (J),Y ; saved! + 8038 71CB 88 dey ; point to lo part + 8039 71CC ZWINPUT2: + 8040 71CC A5 67 lda ARG3+LO ; start with lo part + 8041 71CE 91 7A sta (J),Y ; save lo part + 8042 71D0 ZWIPLCT: + 8043 71D0 4C B1 4D jmp GET_CURSOR ; restore cursor/lincnt + 8044 71D3 + 8045 71D3 END + 8046 + 8047 71D3 INCLUDE DLINE.ASM + 8048 71D3 STTL "--- Display line Routine ---" + 8049 PAGE + Wed May 24 1989 15:00 Page 123 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8050 ; + 8051 ; some aux mem zero page stuff + 8052 ; + 8053 71D3 DLVARS: + 8054 71D3 CHR_X EQU DLVARS ; (WORD) X pos for char (0-559) + 8055 71D5 ENDBIT EQU CHR_X+2 ; (BYTE) ending bit offset + 8056 71D6 WRPFLG EQU ENDBIT+1 ; wrapping flag + 8057 71D7 SCRLFLG EQU WRPFLG+1 ; scrolling flag + 8058 71D8 BUFFLG EQU SCRLFLG+1 ; buffering flag + 8059 71D9 SAVEX EQU BUFFLG+1 ; (BYTE) save original X + 8060 71DA CHR_Y EQU SAVEX+1 ; (BYTE) Working cursor Y pos + 8061 71DB LINECHAR EQU CHR_Y+1 ; (BYTE) working char counter + 8062 71DC BITTER EQU LINECHAR+1 ; (BYTE) bit twiddler counter + 8063 71DD INCFLG EQU BITTER+1 ; (BYTE) ==1 if NEXT_SCR needed after setpos + 8064 71DE SHOW_CURSOR EQU INCFLG+1 ; (BYTE) flag as to whether we are doing cursor + 8065 71DF SCRCNT EQU SHOW_CURSOR+1 ; (BYTE) screen buffer offset + 8066 71E0 SV_UND EQU SCRCNT+1 ; (BYTE) spot to save underline flag + 8067 71E1 SV_INV EQU SV_UND+1 ; (BYTE) save starting INVFLG + 8068 71E2 UNDERF EQU SV_INV+1 ; (BYTE) underline flag used internally + 8069 71E3 LINE_HEIGHT EQU UNDERF+1 ; (BYTE) counter for height + 8070 0011 DLVARSL EQU LINE_HEIGHT-CHR_X+1 + 8071 + 8072 71D3 BLKB DLVARSL,0 + 8073 + 8074 71E4 07 06 05 04 03 BIT_BITS: DB 7,6,5,4,3,2,1,0 ; number significant bits in last byte + 71E9 02 01 00 + 8075 + 8076 71EC DISP_LINE: + 8077 71EC AD DF 71 lda SCRCNT ; make sure there are characters + 8078 71EF D0 01 bne DPL1 ; ayyup + 8079 71F1 60 rts ; no chars, don't do anything + 8080 71F2 DPL1: + 8081 71F2 A9 00 lda #0 ; start at zero + 8082 71F4 85 09 sta CC_OFF ; which byte to use + 8083 71F6 8D DD 71 sta INCFLG ; and clear out inc'er flag + 8084 71F9 + 8085 71F9 A9 08 lda #FONT_H-1 ; do for height of char + 8086 71FB 8D E3 71 sta LINE_HEIGHT ; height counter + 8087 + 8088 71FE A4 01 ldy SCRCY ; and starting y + 8089 7200 8C DA 71 sty CHR_Y ; saved + 8090 7203 A4 00 ldy SCRCX ; save x to + 8091 7205 8C D9 71 sty SAVEX ; save it + 8092 7208 A5 BB lda INVFLG ; get current state + 8093 720A 8D E1 71 sta SV_INV ; and save it + 8094 720D A5 BA lda UNDFLG ; get current underline state + 8095 720F 8D E0 71 sta SV_UND ; and save it too + 8096 + 8097 7212 AD 77 6C lda CURSFLG ; changed x pos? + 8098 7215 F0 12 beq DPL2 ; no new figgering + 8099 7217 A2 00 ldx #0 + 8100 7219 8E D4 71 stx CHR_X+HI ; clear out msb + 8101 + 8102 721C A5 00 lda SCRCX ; get new cursor x pos + 8103 721E 0A asl A ; *2 + 8104 721F 2E D4 71 rol CHR_X+HI + 8105 7222 0A asl A ; *4 + 8106 7223 8D D3 71 sta CHR_X+LO + 8107 7226 2E D4 71 rol CHR_X+HI + 8108 7229 DPL2: + 8109 7229 AD D3 71 lda CHR_X+LO + 8110 722C 85 00 sta SCRCX + 8111 722E 29 03 and #3 ; pick up 2 bits rolling out + 8112 7230 8D DC 71 sta BITTER ; what to add + 8113 7233 AD D4 71 lda CHR_X+HI + 8114 7236 4A lsr A ; /2 + 8115 7237 66 00 ror SCRCX + 8116 7239 4A lsr A ; /4 + 8117 723A 66 00 ror SCRCX + 8118 723C 20 4C 5E jsr SETPOS ; set up pointers + 8119 + 8120 723F AD DC 71 lda BITTER ; get extra + 8121 7242 18 clc ; add in + 8122 7243 65 11 adc BITOFF ; normal bit offset + 8123 7245 8D DC 71 sta BITTER ; and make it new one + Wed May 24 1989 15:00 Page 124 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8124 7248 C9 07 cmp #7 ; but can't be greater than 6 + 8125 724A 90 08 bcc DO_LINE ; okay, it's not + 8126 724C 8D DD 71 sta INCFLG ; show needing NEXT_SCR call + 8127 724F E9 07 sbc #7 ; so shrink it + 8128 7251 8D DC 71 sta BITTER ; save it + 8129 7254 DO_LINE: + 8130 7254 20 4C 5E jsr SETPOS ; set up pointers + 8131 7257 AD DD 71 lda INCFLG ; do we need to go one more? + 8132 725A F0 03 beq DOL1 ; nope + 8133 725C 20 F1 5D jsr NEXT_SCR ; and point to next screen byte + 8134 725F DOL1: + 8135 725F AE DC 71 ldx BITTER ; get bit off set + 8136 7262 86 11 stx BITOFF ; and save here + 8137 7264 A9 00 lda #0 ; init a few things + 8138 7266 85 13 sta SCR_DATA ; init screen data byte + 8139 7268 8D DB 71 sta LINECHAR ; which character on the line + 8140 726B 85 0F sta CH_OFFSET ; which byte in line on screen + 8141 726D 85 07 sta LINE_X+LO ; X pos of line + 8142 726F 85 08 sta LINE_X+HI ; part 2 + 8143 7271 8D E2 71 sta UNDERF ; make sure this be zero + 8144 + 8145 7274 AD E1 71 lda SV_INV ; get starting INV state + 8146 7277 85 BB sta INVFLG ; okay! + 8147 7279 AD E0 71 lda SV_UND ; get starting UNDERLINE state + 8148 727C 85 BA sta UNDFLG ; and restart it + 8149 + 8150 727E C6 0F dec CH_OFFSET ; inclusive count + 8151 7280 A6 11 ldx BITOFF ; make bitoff be a count + 8152 7282 BD E4 71 lda BIT_BITS,X ; get count + 8153 7285 AA tax ; x is bit counter + 8154 7286 CHARL: + 8155 7286 AC DB 71 ldy LINECHAR ; get the char + 8156 7289 CC DF 71 cpy SCRCNT ; done with line? + 8157 728C D0 03 bne CHARL1 ; nope + 8158 728E 4C 32 73 jmp COPYL ; okay, move onto screen + 8159 7291 CHARL1: + 8160 7291 EE DB 71 inc LINECHAR ; point to next one + 8161 7294 B9 80 02 lda SCRBUFF,Y ; got it + 8162 7297 10 06 bpl CHARL3 ; not a highlight char + 8163 + 8164 7299 20 12 70 jsr HLIGHT ; so check it out + 8165 729C 4C 86 72 jmp CHARL ; done + 8166 729F CHARL3: + 8167 729F C9 20 cmp #SPACE ; is it a highlight char? + 8168 72A1 90 E3 bcc CHARL ; ignore this one then + 8169 72A3 CHARL2: + 8170 72A3 A8 tay ; use as index + 8171 72A4 B9 27 63 lda CHADR_H,Y ; get high part of address + 8172 72A7 85 1D sta CHPTR+HI ; point to it + 8173 72A9 B9 A6 63 lda CHADR_L,Y ; get lo part + 8174 72AC 85 1C sta CHPTR+LO ; save it + 8175 72AE B9 25 64 lda CHWID,Y ; get how wide the char is + 8176 72B1 85 C9 sta CW ; save it + 8177 72B3 A5 09 lda CC_OFF ; to get data + 8178 72B5 A4 C9 ldy CW ; see how wide the char is + 8179 72B7 C0 0A cpy #10 ; if <= 8, only one byte of info + 8180 72B9 90 01 bcc CHRLCW ; it is, so skip shift + 8181 72BB 0A asl A ; *2 for bigger chars + 8182 72BC CHRLCW: + 8183 72BC A8 tay ; get the index + 8184 72BD B1 1C lda (CHPTR),Y ; get first byte + 8185 72BF 85 C7 sta CHAR_D1 ; part one + 8186 72C1 C8 iny ; point to next part + 8187 72C2 B1 1C lda (CHPTR),Y ; get second byte + 8188 72C4 85 C8 sta CHAR_D2 ; and save it + 8189 72C6 A5 C9 lda CW ; get width back + 8190 72C8 C9 0A cmp #10 ; if <= 8 zero byte 2 of char data + 8191 72CA B0 04 bcs CHRLCW1 ; nope + 8192 72CC A9 00 lda #0 ; clear out byte 2 + 8193 72CE 85 C8 sta CHAR_D2 ; okay + 8194 72D0 CHRLCW1: + 8195 72D0 A5 C1 lda FONTFLG ; is this monospacing? + 8196 72D2 F0 28 beq CHRLFX ; nope + 8197 ; + 8198 ; if monospacing, see if it char is < mono width, and try to split + Wed May 24 1989 15:00 Page 125 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8199 ; the difference if so + 8200 ; + 8201 72D4 C5 C9 cmp CW ; check against current width + 8202 72D6 B0 12 bcs CHRLF0 ; CW < monowidth, so center + 8203 ; + 8204 ; too big, so take a little off front end too + 8205 ; + 8206 72D8 A5 C9 lda CW ; get current width + 8207 72DA 38 sec ; get ready for subbing + 8208 72DB E9 0C sbc #MONOFONT_W ; take away mono width + 8209 72DD 4A lsr A ; /2 to get front half + 8210 72DE A8 tay ; use as counter + 8211 72DF F0 17 beq CHRLF1 ; nothing to do + 8212 72E1 CHRLFX1: + 8213 72E1 06 C8 asl CHAR_D2 ; step to the left + 8214 72E3 26 C7 rol CHAR_D1 ; pick up char + 8215 72E5 88 dey ; count one + 8216 72E6 D0 F9 bne CHRLFX1 ; do next one + 8217 72E8 F0 0E beq CHRLF1 ; all done + 8218 72EA CHRLF0: + 8219 72EA 38 sec ; do sub + 8220 72EB E5 C9 sbc CW ; subtract CW + 8221 72ED 4A lsr A ; /2 to get front part + 8222 72EE A8 tay ; put in counter + 8223 72EF F0 07 beq CHRLF1 ; no need to do anything + 8224 72F1 CHRLFL: + 8225 72F1 46 C7 lsr CHAR_D1 ; shift to right + 8226 72F3 66 C8 ror CHAR_D2 ; this part too + 8227 72F5 88 dey ; count shift + 8228 72F6 D0 F9 bne CHRLFL ; not done shifting yet + 8229 72F8 CHRLF1: + 8230 72F8 A9 0C lda #MONOFONT_W ; get mono font width + 8231 72FA 85 C9 sta CW ; chop at mono width + 8232 72FC CHRLFX: + 8233 72FC AD E3 71 lda LINE_HEIGHT ; if == 0, then pick up underlining + 8234 72FF D0 05 bne CHRL3 ; nope + 8235 + 8236 7301 A5 BA lda UNDFLG ; get underlining flag + 8237 7303 8D E2 71 sta UNDERF ; and mark for later + 8238 7306 CHRL3: + 8239 7306 A5 13 lda SCR_DATA ; get starting data + 8240 7308 DATAL: + 8241 7308 26 C8 rol CHAR_D2 ; it's a step to the left + 8242 730A 26 C7 rol CHAR_D1 ; nother one + 8243 730C 6A ror A ; and put into screen byte + 8244 730D 45 BB eor INVFLG ; pick up inversing + 8245 730F 0D E2 71 ora UNDERF ; pick up underline flag + 8246 7312 E6 07 inc LINE_X+LO ; next X pos too + 8247 7314 D0 02 bne DATAL0 ; no wrap + 8248 7316 E6 08 inc LINE_X+HI ; wrapped + 8249 7318 DATAL0: + 8250 7318 CA dex ; next bit pos + 8251 7319 D0 0C bne DATAL1 ; nope + 8252 ; + 8253 ; save the byte and point to next byte + 8254 ; + 8255 731B STCH: + 8256 731B 4A lsr A ; put in lower 7 bits + 8257 731C E6 0F inc CH_OFFSET ; point to next one + 8258 731E A4 0F ldy CH_OFFSET ; get current offset + 8259 7320 99 00 1F sta SCR_LINE,Y ; save in line + 8260 7323 A2 07 ldx #7 ; and start bitoff at 7 + 8261 7325 A9 00 lda #0 ; clear a few locals + 8262 7327 DATAL1: + 8263 7327 C6 C9 dec CW ; well? + 8264 7329 30 1F bmi COPYL1 ; all done, start copying + 8265 732B D0 DB bne DATAL ; nope + 8266 732D 85 13 sta SCR_DATA ; save current screen byte stuff here + 8267 732F 4C 86 72 jmp CHARL ; do next char + 8268 7332 COPYL: + 8269 7332 A5 07 lda LINE_X+LO ; see if we have any at all + 8270 7334 05 08 ora LINE_X+HI ; well, did we go anywhere? + 8271 7336 F0 21 beq LINE_EXIT ; then quit + 8272 7338 BD E4 71 lda BIT_BITS,X ; get number of significant bits + 8273 733B 8D D5 71 sta ENDBIT ; save this one + Wed May 24 1989 15:00 Page 126 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8274 733E E0 07 cpx #7 ; has it been renewed? + 8275 7340 F0 08 beq COPYL1 ; no last byte + 8276 7342 A5 13 lda SCR_DATA ; get screen data + 8277 7344 COPYSH: + 8278 7344 4A lsr A ; put down low, please + 8279 7345 CA dex ; one more + 8280 7346 D0 FC bne COPYSH ; and do it again + 8281 7348 F0 D1 beq STCH ; now save this char + 8282 734A COPYL1: + 8283 734A 20 1E 61 jsr COPY_SCRL ; copy SCR_LINE to screen + 8284 734D LED2: + 8285 734D E6 01 inc SCRCY ; point to next line + 8286 734F CE E3 71 dec LINE_HEIGHT ; count this line + 8287 7352 30 05 bmi LINE_EXIT ; all done! + 8288 + 8289 7354 E6 09 inc CC_OFF ; point to next byte + 8290 7356 4C 54 72 jmp DO_LINE ; and do next line + 8291 7359 LINE_EXIT: + 8292 7359 AE D9 71 ldx SAVEX ; get x back + 8293 735C 86 00 stx SCRCX ; restore it + 8294 + 8295 735E AD DE 71 lda SHOW_CURSOR ; are we just doing cursor? + 8296 7361 D0 14 bne DLXX ; yes, don't change char pos + 8297 + 8298 7363 18 clc ; add in length of this line + 8299 7364 A5 07 lda LINE_X+LO ; get length of line + 8300 7366 6D D3 71 adc CHR_X+LO ; add to start pos + 8301 7369 8D D3 71 sta CHR_X+LO ; save it + 8302 736C A5 08 lda LINE_X+HI ; and the MSB + 8303 736E 6D D4 71 adc CHR_X+HI ; okay + 8304 7371 8D D4 71 sta CHR_X+HI ; save for a rainy day + 8305 7374 20 85 73 jsr GET_SCRCX ; set SCRCX back up + 8306 7377 DLXX: + 8307 7377 AD DA 71 lda CHR_Y ; restore the + 8308 737A 85 01 sta SCRCY ; y pos + 8309 737C A9 00 lda #0 ; clear out counter + 8310 737E 8D DF 71 sta SCRCNT ; okay + 8311 7381 8D 77 6C sta CURSFLG ; reset this flag too + 8312 7384 60 rts + 8313 + 8314 7385 GET_SCRCX: + 8315 7385 AD D3 71 lda CHR_X+LO ; pick this back up + 8316 7388 85 00 sta SCRCX + 8317 738A AD D4 71 lda CHR_X+HI ; /2 + 8318 738D 4A lsr A ; pick up remainder + 8319 738E 66 00 ror SCRCX ; /4 + 8320 7390 4A lsr A ; pick up remainder + 8321 7391 66 00 ror SCRCX ; got it + 8322 7393 AD D3 71 lda CHR_X+LO ; any remainder? + 8323 7396 29 03 and #3 ; well? + 8324 7398 F0 DD beq DLXX ; nope + 8325 739A E6 00 inc SCRCX ; point to next pos + 8326 739C 60 rts + 8327 + 8328 ; + 8329 ; DO_CURSOR - read in the screen byte, XOR cursor data, store it + 8330 ; + 8331 739D DO_CURSOR: + 8332 739D A0 00 ldy #0 ; and zero y + 8333 739F 84 10 sty DATALOOP ; init this counter + 8334 73A1 DOCLOOP: + 8335 + 8336 73A1 A0 00 ldy #0 ; must use Y + 8337 73A3 A6 8E ldx FPCBNK ; what bank + 8338 73A5 BD 54 C0 lda PAGE2SW,X ; select it + 8339 73A8 B1 8C lda (FPC),Y ; okay, get byte + 8340 73AA A6 10 ldx DATALOOP ; get offset + 8341 73AC 5D 00 1F eor SCR_LINE,X ; get data + 8342 73AF 91 8C sta (FPC),Y ; save data + 8343 73B1 20 F1 5D jsr NEXT_SCR ; point to next screen byte + 8344 73B4 E6 10 inc DATALOOP ; point to next char + 8345 73B6 C6 0F dec CH_OFFSET ; count one char + 8346 73B8 10 E7 bpl DOCLOOP ; all done with this line? + 8347 73BA AD 54 C0 lda PAGE2SW+MAIN ; make sure we are point to MAIN + 8348 73BD 60 rts + Wed May 24 1989 15:00 Page 127 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Display line Routine ---" + + 8349 + 8350 73BE END + 8351 + 8352 73BE INCLUDE PIC.ASM + 8353 73BE STTL "--- Picture Op Codes ---" + 8354 PAGE + Wed May 24 1989 15:00 Page 128 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8355 PFILE_RD: ; for READING files + 8356 73BE 04 db 4 ; 4 parameters + 8357 73BF 00 db 0 ; refnum + 8358 73C0 0008 dw IOBUFF ; read into io buffer + 8359 73C2 0004 dw $400 ; 1Kb buffer + 8360 73C4 0000 dw 0 ; length actually read + 8361 73C6 PFSEEK: + 8362 73C6 02 db 2 ; 2 pararmeters + 8363 73C7 00 db 0 ; refnum + 8364 73C8 00 00 00 db 0,0,0 ; 3 byte new file pos + 8365 73CB 0000 PICCNT: dw 0 ; counter of the entries + 8366 73CD 00 PF_REFNUM: db 0 ; place to store refnum + 8367 73CE FF PF_FID: db $FF ; File ID of local directory data + 8368 73CF 00 P_IDX: db 0 + 8369 73D0 00 P_BCNT: db 0 + 8370 73D1 00 P_LOFF: db 0 + 8371 73D2 00 GBL_FLAG: db 0 ; found global directory? + 8372 73D3 00 PIC_FLAG: db 0 ; found pictures? + 8373 73D4 00 PF_NAME: db 0 ; name we are looking at + 8374 73D5 00 db 0 ; name we found + 8375 + 8376 73D6 PICINFO: + 8377 73D6 ds PLDSIZE ; get room for picture data + 8378 + 8379 73DE 00 TRANSCLR: DB 0 ; transparent color + 8380 73DF UNKPIC: + 8381 + 8382 73DF 0D 55 6E 6B 6E db EOL,"Unknown Picture #" + 73E4 6F 77 6E 20 50 + 73E9 69 63 74 75 72 + 73EE 65 20 23 + 8383 0012 UNKPICL EQU $-UNKPIC + 8384 73F1 ZDISPL: + 8385 73F1 20 AD 55 jsr CLRBUF ; put out any and all text + 8386 + 8387 73F4 20 48 77 jsr GET_PICINF ; get the necessary data + 8388 73F7 90 18 bcc ZDSP1 ; everything just fine + 8389 + 8390 73F9 DLINE UNKPIC ; unknown picture number error + 8391 73F9 A2 DF ldx #UNKPIC ; get other part of string + 8393 [01] IFMA 2 ; check to see if length passed in + 8394 ldy ; then just fetch it + 8395 [01] ELSE + 8396 73FD A0 12 ldy #UNKPICL ; get length of string + 8397 [00] ENDIF + 8398 73FF 20 6B 4C jsr DLINE ; print the string + 8399 7402 .MACEND + 8400 7402 A5 64 lda ARG1+HI ; get MSB + 8401 7404 20 D3 47 jsr HEXNUM ; print it + 8402 7407 A5 63 lda ARG1+LO ; and LSB + 8403 7409 20 D3 47 jsr HEXNUM + 8404 740C A9 14 lda #$14 ; bad picture number error + 8405 740E 4C 0A 52 jmp ZERROR ; and croak + 8406 7411 ZDSP1: + 8407 7411 20 9F 4D jsr SAVE_CURSOR ; save the cursor + 8408 + 8409 7414 A9 00 lda #0 ; show no cursor change + 8410 7416 8D 77 6C sta CURSFLG ; start with none, anyway + 8411 + 8412 7419 C6 62 dec NARGS ; x,y pos passed? + 8413 741B F0 30 beq ZDSP10 ; nope, just use as is + 8414 + 8415 741D A5 65 lda ARG2+LO ; get passed y pos + 8416 741F F0 12 beq ZDSP01 ; don't change + 8417 7421 85 01 sta SCRCY ; change, then + 8418 7423 C6 01 dec SCRCY ; zero base it + 8419 7425 A0 00 ldy #WINTOP ; get top edge of window + 8420 7427 B1 05 lda (WINDOW),Y ; got it + 8421 7429 18 clc ; get ready for add + 8422 742A 65 01 adc SCRCY ; add the offset + 8423 742C 85 01 sta SCRCY ; and make it Y pos + 8424 742E A9 01 lda #1 ; show cursor change anyway + 8425 7430 8D 77 6C sta CURSFLG ; okay, we did + 8426 7433 ZDSP01: + Wed May 24 1989 15:00 Page 129 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8427 7433 C6 62 dec NARGS ; x pos passed? + 8428 7435 F0 16 beq ZDSP10 ; nope + 8429 + 8430 7437 A5 67 lda ARG3+LO ; get x pos + 8431 7439 F0 12 beq ZDSP10 ; if == 0, don't change + 8432 743B 85 00 sta SCRCX ; set as passed + 8433 743D C6 00 dec SCRCX ; zero base it + 8434 743F A0 01 ldy #WINLEFT ; get left hand edge of window + 8435 7441 B1 05 lda (WINDOW),Y ; got it + 8436 7443 18 clc ; get ready for add + 8437 7444 65 00 adc SCRCX ; add the offset + 8438 7446 85 00 sta SCRCX ; and make it X pos + 8439 7448 A9 01 lda #1 ; show cursor change anyway + 8440 744A 8D 77 6C sta CURSFLG ; okay, we did + 8441 744D ZDSP10: + 8442 744D A5 00 lda SCRCX ; get current X + 8443 744F 48 pha ; save it + 8444 7450 18 clc ; adding + 8445 7451 6D D8 73 adc PICINFO+PLDWID ; add in pic width + 8446 7454 85 00 sta SCRCX ; save here + 8447 7456 68 pla ; get start X pos back + 8448 7457 85 00 sta SCRCX ; restored + 8449 7459 ZDSP101: + 8450 7459 AD DA 73 lda PICINFO+PLDFLG ; get flag byte + 8451 745C 29 01 and #1 ; is there a transparent color? + 8452 745E D0 04 bne ZDSP11 ; ayyup + 8453 7460 A9 FF lda #$FF ; make TRANSCLR be $FF + 8454 7462 D0 07 bne ZDSP12 ; okay + 8455 7464 ZDSP11: + 8456 7464 AD DA 73 lda PICINFO+PLDFLG ; get hi byte of flag word + 8457 7467 4A lsr A ; put in lower byte + 8458 7468 4A lsr A ; put in lower byte + 8459 7469 4A lsr A ; put in lower byte + 8460 746A 4A lsr A ; put in lower byte + 8461 746B ZDSP12: + 8462 746B 8D DE 73 sta TRANSCLR ; save transparent color + 8463 + 8464 746E AD DB 73 lda PICINFO+PLDPTR ; MSB of offset + 8465 7471 8D CA 73 sta PFSEEK+SM_FPOS+2 ; MSB of seek + 8466 7474 AD DC 73 lda PICINFO+PLDPTR+1 ; Middle + 8467 7477 29 FE and #$FE ; seek only to 512byte boundary + 8468 7479 8D C9 73 sta PFSEEK+SM_FPOS+1 + 8469 + 8470 747C SET_MARK PFSEEK ; go to pic data + 8471 747C PRODOS $CE, PFSEEK + 8472 747C 20 00 BF jsr $BF00 ; ProDOS handler + 8473 747F CE DB $CE ; ProDOS function code + 8474 7480 C673 DW PFSEEK ; Function Parameter Block address + 8475 7482 .MACEND + 8476 7482 .MACEND + 8477 7482 A9 02 lda #>PIC1BUF ; set up pointers to decode buffers + 8478 7484 85 7B sta J+HI + 8479 7486 A9 73 lda #PIC2BUF + 8482 748C 85 7D sta K+HI + 8483 748E A9 74 lda #IOBUFF ; now get data buffer address + 8495 74A2 85 7F sta L+HI + 8496 74A4 A9 04 lda #4 ; 4 pages read in at once + 8497 74A6 8D D0 73 sta P_BCNT ; okay + 8498 74A9 A9 03 lda #3 ; 3 bytes of width data start it + 8499 74AB 18 clc ; doing add + 8500 74AC 6D DD 73 adc PICINFO+PLDPTR+2 ; pick up LSB pointer + 8501 74AF 8D CF 73 sta P_IDX ; start index + Wed May 24 1989 15:00 Page 130 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8502 74B2 90 05 bcc ZDLPCC ; no wrap + 8503 74B4 E6 7F inc L+HI ; start at second one + 8504 74B6 CE D0 73 dec P_BCNT ; one less block + 8505 74B9 ZDLPCC: + 8506 74B9 AD DC 73 lda PICINFO+PLDPTR+1 ; tells which block it is in + 8507 74BC 29 01 and #$01 ; pick up which 256 block + 8508 74BE F0 05 beq ZDLP0 ; start at first one + 8509 74C0 E6 7F inc L+HI ; start at next one + 8510 74C2 CE D0 73 dec P_BCNT ; one less block + 8511 74C5 ZDLP0: + 8512 74C5 A9 00 lda #IOBUFF ; reset data buffer address + 8707 75FC 85 7F sta L+HI + 8708 75FE A9 00 lda #GBL_DIR ; start destination off here + 8765 764A 20 65 76 jsr READ_IN_PDATA ; go get global directory, if any + 8766 764D 8D D2 73 sta GBL_FLAG ; indicate whether there is a global + 8767 7650 GTPG1: + 8768 7650 AD C5 49 lda SAVENUM ; get which file is being opened + 8769 7653 29 0F and #$0F ; just make it binary + 8770 7655 CD CE 73 cmp PF_FID ; same as the file we already have? + 8771 7658 F0 0A beq GETPGX ; yes, so don't bother + 8772 765A A0 02 ldy #SGTPICOF ; point to picture offset + 8773 765C A9 D0 lda #>PIC_DIR ; start destination off here + 8774 765E 20 65 76 jsr READ_IN_PDATA ; go get the data for local pictures + 8775 7661 8D D3 73 sta PIC_FLAG ; any picture data + 8776 7664 GETPGX: + 8777 7664 60 rts + 8778 ; + 8779 ; READ_IN_PDATA - check for desired data being in file, and skip to it if + 8780 ; it is. Then, read it in in 1Kb chunks, stashing it away into the + 8781 ; upper bank of the aux mem language card. + 8782 ; Enter with: + 8783 ; [A] = Destination page + 8784 ; [Y] = Offset into Segment table + 8785 ; + 8786 7665 READ_IN_PDATA: + 8787 7665 48 pha ; save destination page + 8788 7666 B1 1E lda (DSEGS),Y ; get MSB + 8789 7668 8D CA 73 sta PFSEEK+SM_FPOS+2 ; Byte 2 + 8790 766B C8 iny ; point to LSB + 8791 766C 11 1E ora (DSEGS),Y ; is there any pic data? + 8792 766E D0 04 bne GTPD00 ; yes + 8793 7670 68 pla ; get page back + 8794 7671 A9 00 lda #0 ; show not here + 8795 7673 60 rts ; nope + 8796 7674 GTPD00: + 8797 7674 B1 1E lda (DSEGS),Y ; get it for shifting + 8798 7676 0A asl A ; *2 + 8799 7677 8D C9 73 sta PFSEEK+SM_FPOS+1 ; stash away + 8800 767A 2E CA 73 rol PFSEEK+SM_FPOS+2 ; pick up carry + 8801 767D A9 00 lda #0 ; clear out MSB + Wed May 24 1989 15:00 Page 134 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8802 767F 8D C3 73 sta PFILE_RD+RD_BUFFLEN+HI + 8803 7682 8D C8 73 sta PFSEEK+SM_FPOS ; and LSB of seeking + 8804 + 8805 7685 AD CD 73 lda PF_REFNUM ; get file ref number + 8806 7688 8D BF 73 sta PFILE_RD+RD_REFNUM ; and save it for reading and + 8807 768B 8D C7 73 sta PFSEEK+SM_REFNUM ; for seeking + 8808 + 8809 768E A9 03 lda #RETRY_COUNT ; set retry + 8810 7690 85 0E sta NY_DATA ; just use this for now + 8811 7692 GTPDRD0: + 8812 7692 SET_MARK PFSEEK ; and go to beginning + 8813 7692 PRODOS $CE, PFSEEK + 8814 7692 20 00 BF jsr $BF00 ; ProDOS handler + 8815 7695 CE DB $CE ; ProDOS function code + 8816 7696 C673 DW PFSEEK ; Function Parameter Block address + 8817 7698 .MACEND + 8818 7698 .MACEND + 8819 + 8820 7698 A9 04 lda #4 ; read in 4 256 blocks + 8821 769A 8D C3 73 sta PFILE_RD+RD_BUFFLEN+HI + 8822 769D READ PFILE_RD ; go get the next 4Kb worth + 8823 769D PRODOS $CA, PFILE_RD + 8824 769D 20 00 BF jsr $BF00 ; ProDOS handler + 8825 76A0 CA DB $CA ; ProDOS function code + 8826 76A1 BE73 DW PFILE_RD ; Function Parameter Block address + 8827 76A3 .MACEND + 8828 76A3 .MACEND + 8829 76A3 90 05 bcc GTPD1 ; fine + 8830 76A5 20 07 47 jsr RETRY ; well, do it again? + 8831 76A8 90 E8 bcc GTPDRD0 ; yes + 8832 76AA GTPD1: + 8833 76AA 68 pla ; get destination page back + 8834 76AB C9 D0 cmp #>PIC_DIR ; if doing local directory, set up + 8835 76AD D0 16 bne GTPD2 ; picture count + 8836 76AF AE 04 08 ldx IOBUFF+PHNLD ; get number of pictures + 8837 76B2 8E CC 73 stx PICCNT+HI ; save for count down too + 8838 76B5 AE 05 08 ldx IOBUFF+PHNLD+1 ; and here is LSB + 8839 76B8 8E CB 73 stx PICCNT+LO ; saving for counting + 8840 76BB AE 00 08 ldx IOBUFF+PHFID ; get file ID + 8841 76BE 8E CE 73 stx PF_FID ; and save for later + 8842 76C1 A2 20 ldx #(256/PLDSIZE) ; how many entries in 256 bytes + 8843 76C3 D0 0E bne GTPD3 ; done + 8844 76C5 GTPD2: + 8845 76C5 AE 00 08 ldx IOBUFF ; get MSB of how many + 8846 76C8 8E CC 73 stx PICCNT+HI ; show me + 8847 76CB AE 01 08 ldx IOBUFF+1 ; get LSB of count + 8848 76CE 8E CB 73 stx PICCNT+LO + 8849 76D1 A2 80 ldx #(256/2) ; how many entries / 256 bytes + 8850 76D3 GTPD3: + 8851 76D3 8E 0A 77 stx GTPMOD+1 ; set up how big entry is + 8852 76D6 8D 09 C0 sta ALTZP+AUX ; use aux mem for most of this + 8853 76D9 85 7D sta K+HI ; MSB of destination + 8854 76DB A9 00 lda #0 ; clear a few things + 8855 76DD 85 7A sta J+LO ; J = source + 8856 76DF 85 7C sta K+LO ; K = destination + 8857 76E1 A9 04 lda #4 ; 4 * (4*256) bytes max + 8858 76E3 8D C3 73 sta PFILE_RD+RD_BUFFLEN+HI ; show the read too + 8859 76E6 8D CF 73 sta P_IDX ; save here for counting + 8860 76E9 GTPDL: + 8861 76E9 A0 00 ldy #0 ; start y + 8862 76EB A9 08 lda #>IOBUFF ; get where source is + 8863 76ED 85 7B sta J+HI ; MSB of source + 8864 76EF A9 04 lda #4 ; 4 blocks worth of 256 + 8865 76F1 8D D0 73 sta P_BCNT ; used as counter + 8866 76F4 AD 8B C0 lda BNK1SET ; we be using bank 1 @$D000 + 8867 76F7 AD 8B C0 lda BNK1SET ; we be using bank 1 @$D000 + 8868 76FA GTPDL1: + 8869 76FA B1 7A lda (J),Y ; get the data byte + 8870 76FC 91 7C sta (K),Y ; store in upper aux + 8871 76FE C8 iny ; point to the next one + 8872 76FF D0 F9 bne GTPDL1 ; and go get it + 8873 7701 + 8874 7701 E6 7B inc J+HI ; next block please + 8875 7703 E6 7D inc K+HI ; for destination too + 8876 7705 AD CB 73 lda PICCNT+LO ; how many entries? + Wed May 24 1989 15:00 Page 135 + + "APPLE YZIP (c)Infocom, Inc.. --- MACHINE DEPENDENT SHELL" + "--- Picture Op Codes ---" + + 8877 7708 38 sec ; doing sbc + 8878 7709 E9 20 GTPMOD: sbc #(256/PLDSIZE) ; how many entries in 256 bytes? + 8879 770B 8D CB 73 sta PICCNT+LO ; save result + 8880 770E B0 05 bcs GTPDL2 ; no wrapping + 8881 7710 CE CC 73 dec PICCNT+HI ; wrap + 8882 7713 30 26 bmi GTPDLX ; all done if we go negative + 8883 7715 GTPDL2: + 8884 7715 0D CC 73 ora PICCNT+HI ; make sure both are not zero + 8885 7718 F0 21 beq GTPDLX ; if they are, then we are done + 8886 771A CE D0 73 dec P_BCNT ; count this block + 8887 771D D0 DB bne GTPDL1 ; go fetch next 256 bytes + 8888 771F 8D 08 C0 sta ALTZP+MAIN ; swap back to main for read + 8889 + 8890 7722 A9 03 lda #RETRY_COUNT ; set retry + 8891 7724 85 0E sta NY_DATA ; just use this for now + 8892 7726 GTPDRD: + 8893 7726 READ PFILE_RD ; go get the next 4Kb worth + 8894 7726 PRODOS $CA, PFILE_RD + 8895 7726 20 00 BF jsr $BF00 ; ProDOS handler + 8896 7729 CA DB $CA ; ProDOS function code + 8897 772A BE73 DW PFILE_RD ; Function Parameter Block address + 8898 772C .MACEND + 8899 772C .MACEND + 8900 772C 90 05 bcc GTPDRDG ; fine + 8901 772E 20 07 47 jsr RETRY ; well, do it again? + 8902 7731 90 F3 bcc GTPDRD ; yes + 8903 7733 GTPDRDG: + 8904 7733 8D 09 C0 sta ALTZP+AUX ; and back to aux for working + 8905 7736 CE CF 73 dec P_IDX ; max 4Kb worth of reading + 8906 7739 D0 AE bne GTPDL ; and read in more + 8907 773B GTPDLX: + 8908 773B 8D 08 C0 sta ALTZP+MAIN ; back to main bank of mem + 8909 773E AD 83 C0 lda BNK2SET ; back to bank 2 + 8910 7741 AD 83 C0 lda BNK2SET ; yes please + 8911 7744 A9 01 lda #1 ; show we found it + 8912 7746 60 rts ; all done + 8913 + 8914 7747 00 GTPFLAG: db 0 ; if 1 when opening next file, then + 8915 ; this is the next file, so unable to + 8916 ; find picture number + 8917 7748 GET_PICINF: + 8918 7748 A9 00 lda #0 ; set flag for double check + 8919 774A 8D 47 77 sta GTPFLAG ; start at zero + 8920 774D GTPLOOP: + 8921 774D A5 63 lda ARG1+LO ; check argument for zero + 8922 774F 05 64 ora ARG1+HI ; is it zero? + 8923 7751 D0 02 bne GTPINDX ; jump to look at first block + 8924 7753 18 clc ; found some pictures + 8925 7754 60 rts ; if zero, just give count + 8926 7755 GTPINDX: + 8927 7755 A4 63 ldy ARG1+LO ; get arg, as we are swapping + 8928 7757 A6 64 ldx ARG1+HI ; to aux mem + 8929 7759 8D 09 C0 sta ALTZP+AUX ; look at AUX mem + 8930 775C AD 8B C0 lda BNK1SET ; bank 1 + 8931 775F AD 8B C0 lda BNK1SET ; bank 1 + 8932 7762 AD 04 D0 lda PIC_DIR+PHNLD ; get # of entries + 8933 7765 8D CC 73 sta PICCNT+HI + 8934 7768 AD 05 D0 lda PIC_DIR+PHNLD+1 ; it's in reverse order + 8935 776B 8D CB 73 sta PICCNT+LO + 8936 776E 84 63 sty ARG1+LO ; use aux mem zero page + 8937 7770 86 64 stx ARG1+HI ; for new arg1 + 8938 7772 A9 D0 lda #>PIC_DIR ; start at beginning of block + 8939 7774 85 8A sta MPNTH ; hi part + 8940 7776 A9 00 lda #GBL_DIR ; start at beginning of block + 9029 780B 85 8A sta MPNTH ; hi part + 9030 780D A9 00 lda # 2 BYTES + 9413 7A11 29 40 and #%01000000 + 9414 7A13 F0 04 beq PTZ1 ; BIT 6 = 0, LENGTH = 1 + 9415 7A15 A9 02 lda #2 ; BIT 6 = 1, LENGTH = 2 + 9416 7A17 D0 09 bne PTZ3 ; JMP + 9417 7A19 PTZ1: + 9418 7A19 A9 01 lda #1 + 9419 7A1B D0 05 bne PTZ3 ; JMP + 9420 7A1D PTZ2: + 9421 7A1D 20 56 92 jsr FETCHB ; and get it + 9422 7A20 29 3F and #%00111111 ; ELSE PICK UP SIZE > 2 + 9423 7A22 PTZ3: + 9424 7A22 A2 00 ldx #0 ; CLEAR FOR PUTBYT + 9425 7A24 4C DD 43 jmp PUTBYT + 9426 ; --- + 9427 ; INC + 9428 ; --- + 9429 ; INCREMENT VARIABLE [ARG1] + 9430 + 9431 7A27 A5 63 ZINC: LDA ARG1+LO + 9432 7A29 20 36 43 JSR VARGET ; FETCH VARIABLE INTO [VALUE] + 9433 7A2C E6 76 INC VALUE+LO + 9434 7A2E D0 02 BNE ZINC1 + 9435 7A30 E6 77 INC VALUE+HI + 9436 7A32 4C 47 7A ZINC1: JMP ZD0 + 9437 + 9438 + 9439 ; --- + 9440 ; DEC + 9441 ; --- + 9442 ; DECREMENT VARIABLE [ARG1] + 9443 + 9444 7A35 A5 63 ZDEC: LDA ARG1+LO + 9445 7A37 20 36 43 JSR VARGET ; FETCH VAR INTO [VALUE] + 9446 7A3A A5 76 LDA VALUE+LO + 9447 7A3C 38 SEC + 9448 7A3D E9 01 SBC #1 + 9449 7A3F 85 76 STA VALUE+LO + 9450 7A41 A5 77 LDA VALUE+HI + 9451 7A43 E9 00 SBC #0 + 9452 7A45 85 77 STA VALUE+HI + 9453 7A47 A5 63 ZD0: LDA ARG1+LO ; PUT RESULT BACK + 9454 7A49 4C C7 43 JMP VARPUT ; INTO THE SAME VARIABLE + 9455 + 9456 + 9457 ; ------ + 9458 ; PRINTB + 9459 ; ------ + 9460 ; PRINT Z-STRING AT [ARG1] + 9461 + Wed May 24 1989 15:00 Page 144 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9462 7A4C ZPRB: + 9463 7A4C A5 63 lda ARG1+LO ; move arg1 to I + 9464 7A4E 85 78 sta I+LO ; lo part + 9465 7A50 A5 64 lda ARG1+HI ; and now for arg1 hi + 9466 7A52 85 79 sta I+HI ; okay + 9467 7A54 20 60 8F jsr SETWRD ; make [MPC] point to it + 9468 7A57 4C CE 92 jmp PZSTR ; and print it + 9469 + 9470 ; ------ + 9471 ; REMOVE + 9472 ; ------ + 9473 ; MOVE OBJECT [ARG1] INTO PSEUDO-OBJECT #0 + 9474 ; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO + 9475 ; 2) MOVES AND COMPARES 2 BYTES) + 9476 + 9477 7A5A SAVEFPC: ds 3 ; spot to save the FPC + 9478 7A5D SAVEOBJ: ds 1 ; check for zero object + 9479 + 9480 7A5E ZREMOV: + 9481 7A5E A5 63 lda ARG1+LO ; GET SOURCE OBJECT ADDR + 9482 7A60 A6 64 ldx ARG1+HI + 9483 7A62 20 EC 94 jsr OBJLOC ; INTO [FPC] + 9484 ; + 9485 ; now save this objects address in I,J + 9486 ; + 9487 7A65 A9 06 lda #6 ; point to the LOC slot + 9488 7A67 20 DE 8F jsr ADDFPC ; thank you + 9489 7A6A A5 8C lda FPCL ; COPY THE SOURCE ADDR + 9490 7A6C 8D 5A 7A sta SAVEFPC+LO ; INTO [J] + 9491 7A6F A5 8D lda FPCH ; FOR LATER REFERENCE + 9492 7A71 8D 5B 7A sta SAVEFPC+HI + 9493 7A74 A5 8E lda FPCBNK + 9494 7A76 8D 5C 7A sta SAVEFPC+ABANK + 9495 ; + 9496 ; now go get object this one is in + 9497 ; + 9498 7A79 20 56 92 jsr FETCHB ; get the data + 9499 7A7C 85 7C sta K ; HOLD IT + 9500 7A7E 20 BE 8F jsr NEXTFPC ; get lo part + 9501 7A81 20 56 92 jsr FETCHB ; now get part + 9502 7A84 A8 tay ; save it + 9503 7A85 05 7C ora K ; COMPARE BYTES + 9504 7A87 D0 03 bne REMVj ; check for object + 9505 7A89 4C 2E 7B jmp REMVEX ; SCRAM IF NO OBJECT + 9506 7A8C REMVj: + 9507 7A8C 98 tya ; get lo part + 9508 7A8D A6 7C ldx K ; and hi part + 9509 7A8F 20 EC 94 jsr OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [FPC] + 9510 7A92 A9 0B lda #11 ; POINT TO "FIRST" SLOT, LSB + 9511 7A94 20 DE 8F jsr ADDFPC ; and point to it + 9512 7A97 20 56 92 jsr FETCHB ; and get it + 9513 7A9A 48 pha ; save LSB + 9514 7A9B 20 24 90 jsr PREVFPC ; point to MSB + 9515 7A9E 20 56 92 jsr FETCHB ; A=LO, X=HI + 9516 7AA1 AA tax ; put into x + 9517 7AA2 68 pla ; get LSB back + 9518 7AA3 C5 63 cmp ARG1+LO ; IS THIS THE FIRST? + 9519 7AA5 D0 04 bne REMVC1 ; NO, KEEP SEARCHING + 9520 7AA7 E4 64 cpx ARG1+HI ; HM? + 9521 7AA9 F0 2B beq DO_REMOVE ; yes, so use it + 9522 7AAB REMVC1: + 9523 7AAB 20 EC 94 jsr OBJLOC ; get object + 9524 7AAE A9 09 lda #9 ; GET "NEXT" slot address + 9525 7AB0 20 DE 8F jsr ADDFPC ; into FPC + 9526 7AB3 20 56 92 jsr FETCHB ; get the byte + 9527 7AB6 48 pha ; save LSB for later + 9528 7AB7 20 24 90 jsr PREVFPC ; and this is the hi part + 9529 7ABA 20 56 92 jsr FETCHB + 9530 7ABD 8D 5D 7A sta SAVEOBJ ; save for later check + 9531 7AC0 AA tax ; and put into x for (possible) check + 9532 7AC1 68 pla ; get lo part back + 9533 7AC2 A8 tay ; save a minute + 9534 7AC3 0D 5D 7A ora SAVEOBJ ; well, is it zero? + 9535 7AC6 D0 05 bne REMVC2 ; no, so check it + 9536 7AC8 A9 15 lda #21 ; so die + Wed May 24 1989 15:00 Page 145 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9537 7ACA 4C 0A 52 jmp ZERROR ; and croak + 9538 7ACD REMVC2: + 9539 7ACD 98 tya ; put back into [A] + 9540 7ACE C5 63 cmp ARG1+LO ; FOUND IT? + 9541 7AD0 D0 D9 bne REMVC1 ; NO, KEEP TRYING + 9542 7AD2 E4 64 cpx ARG1+HI + 9543 7AD4 D0 D5 bne REMVC1 + 9544 7AD6 DO_REMOVE: + 9545 ; + 9546 ; now, copy from FPC to SPC for stashing away + 9547 ; + 9548 7AD6 20 73 90 jsr FP2SP ; copied + 9549 ; + 9550 ; now get removed one's address for fetching + 9551 ; + 9552 7AD9 AD 5C 7A lda SAVEFPC+ABANK ; this is where bank is + 9553 7ADC 85 8E sta FPCBNK ; so show it + 9554 7ADE AD 5B 7A lda SAVEFPC+HI ; and here's the hi/lo part + 9555 7AE1 85 8D sta FPCH + 9556 7AE3 AD 5A 7A lda SAVEFPC+LO + 9557 7AE6 85 8C sta FPCL + 9558 7AE8 A9 02 lda #2 ; so get to source's "NEXT" slot + 9559 7AEA 20 DE 8F jsr ADDFPC ; point to next slot + 9560 7AED 20 56 92 jsr FETCHB ; get the hi byte + 9561 7AF0 20 35 92 jsr STASHB ; and save it + 9562 7AF3 20 9E 8F jsr NEXTSPC ; point to next one + 9563 7AF6 20 BE 8F jsr NEXTFPC ; and from the source too + 9564 7AF9 20 56 92 jsr FETCHB ; get lo byte + 9565 7AFC 20 35 92 jsr STASHB ; and save it away + 9566 ; + 9567 ; now zero out SOURCE's loc and next spots + 9568 ; + 9569 7AFF AD 5C 7A lda SAVEFPC+ABANK ; bank of source + 9570 7B02 85 91 sta SPCBNK + 9571 7B04 AD 5B 7A lda SAVEFPC+HI ; and addr of source LOC slot + 9572 7B07 85 90 sta SPCH + 9573 7B09 AD 5A 7A lda SAVEFPC+LO + 9574 7B0C 85 8F sta SPCL + 9575 ; + 9576 ; zero out NEXT and LOC of source + 9577 ; + 9578 7B0E A9 00 lda #0 ; zero out 4 locations (LOC MSB) + 9579 7B10 20 35 92 jsr STASHB + 9580 7B13 20 9E 8F jsr NEXTSPC + 9581 7B16 + 9582 7B16 A9 00 lda #0 ; zero out 4 locations (LOC LSB) + 9583 7B18 20 35 92 jsr STASHB + 9584 7B1B 20 9E 8F jsr NEXTSPC + 9585 7B1E + 9586 7B1E A9 00 lda #0 ; zero out 4 locations (NEXT MSB) + 9587 7B20 20 35 92 jsr STASHB + 9588 7B23 20 9E 8F jsr NEXTSPC + 9589 7B26 + 9590 7B26 A9 00 lda #0 ; zero out 4 locations (NEXT LSB) + 9591 7B28 20 35 92 jsr STASHB + 9592 7B2B 20 9E 8F jsr NEXTSPC + 9593 7B2E REMVEX: + 9594 7B2E 60 RTS + 9595 + 9596 + 9597 ; ------ + 9598 ; PRINTD + 9599 ; ------ + 9600 ; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + 9601 + 9602 7B2F ZPRD: + 9603 7B2F A5 63 lda ARG1+LO + 9604 7B31 A6 64 ldx ARG1+HI ; (EZIP) + 9605 7B33 20 EC 94 jsr OBJLOC ; GET ADDR OF OBJECT INTO [FPC] + 9606 7B36 A9 0D lda #13 ; GET PROP TABLE POINTER (EZIP) + 9607 7B38 20 DE 8F jsr ADDFPC ; and point to LSB + 9608 7B3B 20 56 92 jsr FETCHB ; fetch LSB + 9609 7B3E 48 pha ; SAVE IT HERE + 9610 7B3F 20 24 90 jsr PREVFPC ; and now fetch MSB + 9611 7B42 20 56 92 jsr FETCHB ; thank you + Wed May 24 1989 15:00 Page 146 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9612 7B45 85 79 sta I+HI ; AND MSB + 9613 7B47 68 pla ; get LSB back + 9614 7B48 85 78 sta I+LO ; STORE LSB + 9615 7B4A E6 78 inc I+LO ; POINT PAST THE + 9616 7B4C D0 02 bne PDC0 ; LENGTH BYTE + 9617 7B4E E6 79 inc I+HI + 9618 7B50 20 60 8F PDC0: jsr SETWRD ; CALC Z-STRING ADDR + 9619 7B53 4C CE 92 jmp PZSTR ; AND PRINT IT + 9620 + 9621 + 9622 ; ------ + 9623 ; RETURN + 9624 ; ------ + 9625 ; RETURN FROM "CALL" WITH VALUE [ARG1] + 9626 + 9627 7B56 ZRET: + 9628 7B56 AD 75 6C LDA OLDZSP+LO ; RE-SYNC THE + 9629 7B59 85 AF STA ZSP+LO ; Z-STACK POINTER + 9630 7B5B AD 76 6C LDA OLDZSP+HI + 9631 7B5E 85 B0 STA ZSP+HI + 9632 7B60 20 66 43 JSR POPVAL ; POP # LOCALS INTO [X/A] + 9633 7B63 86 79 STX I+HI ; SAVE HERE + 9634 7B65 20 66 43 JSR POPVAL ; now we need number of args + 9635 7B68 8D 63 5B STA ASSVLU ; for ASSIGNED? + 9636 + 9637 7B6B A6 79 LDX I+HI ; see how many locals + 9638 7B6D F0 19 BEQ RET2 ; SKIP IF NOT + 9639 + 9640 ; RESTORE PUSHED LOCALS + 9641 + 9642 7B6F CA DEX ; ZERO-ALIGN + 9643 7B70 8A TXA ; AND + 9644 7B71 0A ASL A ; WORD-ALIGN # LOCALS + 9645 7B72 85 78 STA I+LO ; FOR USE AS A STORAGE INDEX + 9646 7B74 20 66 43 RET1: JSR POPVAL ; POP A LOCAL INTO [X/A] + 9647 7B77 A4 78 LDY I+LO ; RETRIEVE STORAGE INDEX + 9648 7B79 99 01 1E STA LOCALS+HI,Y ; STORE MSB OF LOCAL + 9649 7B7C 8A TXA ; MOVE LSB + 9650 7B7D 99 00 1E STA LOCALS+LO,Y ; AND STORE THAT TOO + 9651 7B80 C6 78 DEC I+LO + 9652 7B82 C6 78 DEC I+LO ; UPDATE STORAGE INDEX + 9653 7B84 C6 79 DEC I+HI ; AND LOCALS COUNT + 9654 7B86 D0 EC BNE RET1 ; POP TILL NO MORE LOCALS + 9655 + 9656 ; RESTORE OTHER VARIABLES + 9657 + 9658 7B88 RET2: + 9659 7B88 20 66 43 JSR POPVAL ; POP [ZPCH] AND [ZPCM] + 9660 7B8B 86 81 STX ZPCM + 9661 7B8D 85 82 STA ZPCH + 9662 7B8F 20 66 43 JSR POPVAL ; POP AND RESTORE + 9663 7B92 8E 5F 5B STX IRET + 9664 7B95 85 80 STA ZPCL + 9665 7B97 20 66 43 JSR POPVAL + 9666 7B9A 8E 75 6C STX OLDZSP+LO + 9667 7B9D 8D 76 6C STA OLDZSP+HI + 9668 + 9669 7BA0 A5 80 LDA ZPCL ; check for zero zpc + 9670 7BA2 D0 0E BNE RETj ; which means we are returning to + 9671 7BA4 A5 81 LDA ZPCM ; an internal call + 9672 7BA6 D0 0A BNE RETj ; rather than just a normal + 9673 7BA8 A5 82 LDA ZPCH ; return + 9674 7BAA D0 06 BNE RETj ; but so far it isn't + 9675 + 9676 7BAC 20 B4 44 JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9677 7BAF 4C 42 5B JMP ZIRET ; so then do internal return + 9678 7BB2 RETj: + 9679 7BB2 20 AA 90 JSR VLDZPC ; MAKE VALID + 9680 7BB5 AD 5F 5B LDA IRET ; CHECK IF SHOULD RETURN A VALUE + 9681 7BB8 F0 01 BEQ RETYES ; (0 = RET, 1 = NO RETURN) + 9682 7BBA 60 RTS ; NO, SO JUST GET OUT OF HERE + 9683 7BBB RETYES: + 9684 7BBB 20 B4 44 JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9685 7BBE 4C E1 43 JMP PUTVAL ; AND RETURN IT + 9686 + Wed May 24 1989 15:00 Page 147 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 1-OPS ---" + + 9687 + 9688 ; ---- + 9689 ; JUMP + 9690 ; ---- + 9691 ; JUMP TO Z-LOCATION IN [ARG1] + 9692 + 9693 7BC1 20 B4 44 ZJUMP: JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9694 7BC4 4C 75 44 JMP PREDB3 ; A BRANCH THAT ALWAYS SUCCEEDS + 9695 + 9696 + 9697 ; ----- + 9698 ; PRINT + 9699 ; ----- + 9700 ; PRINT Z-STRING AT WORD (QUAD) POINTER [ARG1] + 9701 + 9702 7BC7 ZPRINT: + 9703 7BC7 A5 63 LDA ARG1+LO + 9704 7BC9 85 78 STA I+LO + 9705 7BCB A5 64 LDA ARG1+HI + 9706 7BCD 85 79 STA I+HI + 9707 7BCF 20 A0 92 JSR SETSTR ; CALC STRING ADDRESS + 9708 7BD2 4C CE 92 JMP PZSTR ; AND PRINT IT + 9709 + 9710 + 9711 ; ----- + 9712 ; VALUE + 9713 ; ----- + 9714 ; RETURN VALUE OF VARIABLE [ARG1] + 9715 + 9716 7BD5 ZVALUE: + 9717 7BD5 A5 63 LDA ARG1+LO + 9718 7BD7 20 36 43 JSR VARGET ; GET THE VALUE + 9719 7BDA 4C E1 43 JMP PUTVAL ; EASY ENOUGH + 9720 + 9721 + 9722 + 9723 7BDD STTL "--- 2-OPS ---" + 9724 PAGE + Wed May 24 1989 15:00 Page 148 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9725 + 9726 + 9727 ; ----- + 9728 ; LESS? + 9729 ; ----- + 9730 ; [ARG1] < [ARG2]? + 9731 + 9732 7BDD ZLESS: + 9733 7BDD 20 B4 44 JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 9734 7BE0 4C E6 7B JMP DLS0 ; MOVE [ARG2] TO [I] & COMPARE + 9735 + 9736 + 9737 ; ------ + 9738 ; DLESS? + 9739 ; ------ + 9740 ; DECREMENT [ARG1] ; SUCCEED IF < [ARG2] + 9741 + 9742 7BE3 ZDLESS: + 9743 7BE3 20 35 7A JSR ZDEC ; MOVES ([ARG1]-1) TO [VALUE] + 9744 7BE6 A5 65 DLS0: LDA ARG2+LO ; MOVE [ARG2] TO [I] + 9745 7BE8 85 78 STA I+LO + 9746 7BEA A5 66 LDA ARG2+HI + 9747 7BEC 85 79 STA I+HI + 9748 7BEE 4C 0F 7C JMP COMPAR ; COMPARE & RETURN + 9749 + 9750 + 9751 ; ----- + 9752 ; GRTR? + 9753 ; ----- + 9754 ; [ARG1] < [ARG2]? + 9755 + 9756 7BF1 A5 63 ZGRTR: LDA ARG1+LO ; MOVE [ARG1] TO [I] + 9757 7BF3 85 78 STA I+LO + 9758 7BF5 A5 64 LDA ARG1+HI + 9759 7BF7 85 79 STA I+HI + 9760 7BF9 4C 07 7C JMP A2VAL ; MOVE [ARG2] TO [VALUE] & COMPARE + 9761 + 9762 + 9763 ; ------ + 9764 ; IGRTR? + 9765 ; ------ + 9766 ; INCREMENT [ARG1] ; SUCCEED IF GREATER THAN [ARG2] + 9767 + 9768 7BFC 20 27 7A ZIGRTR: JSR ZINC ; GET ([ARG1]+1) INTO [VALUE] + 9769 7BFF A5 76 LDA VALUE+LO ; MOVE [VALUE] TO [I] + 9770 7C01 85 78 STA I+LO + 9771 7C03 A5 77 LDA VALUE+HI + 9772 7C05 85 79 STA I+HI + 9773 7C07 A5 65 A2VAL: LDA ARG2+LO ; MOVE [ARG2] TO [VALUE] + 9774 7C09 85 76 STA VALUE+LO + 9775 7C0B A5 66 LDA ARG2+HI + 9776 7C0D 85 77 STA VALUE+HI + 9777 + 9778 + 9779 ; ----------------- + 9780 ; SIGNED COMPARISON + 9781 ; ----------------- + 9782 ; ENTRY: VALUES IN [VALUE] AND [I] + 9783 ; + 9784 ; IS [VALUE] > [I] + 9785 ; + 9786 7C0F COMPAR: + 9787 7C0F A5 79 LDA I+HI + 9788 7C11 45 77 EOR VALUE+HI + 9789 7C13 10 09 BPL SCMP + 9790 7C15 A5 79 LDA I+HI + 9791 7C17 C5 77 CMP VALUE+HI + 9792 7C19 90 42 BCC PGOOD + 9793 7C1B 4C 2F 44 JMP PREDF + 9794 + 9795 7C1E A5 77 SCMP: LDA VALUE+HI + 9796 7C20 C5 79 CMP I+HI + 9797 7C22 D0 04 BNE SCEX + 9798 7C24 A5 76 LDA VALUE+LO + 9799 7C26 C5 78 CMP I+LO + Wed May 24 1989 15:00 Page 149 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9800 7C28 90 33 SCEX: BCC PGOOD + 9801 7C2A 4C 2F 44 JMP PREDF + 9802 + 9803 + 9804 ; --- + 9805 ; IN? + 9806 ; --- + 9807 ; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? + 9808 7C2D ZIN: + 9809 7C2D A5 63 LDA ARG1+LO + 9810 7C2F A6 64 LDX ARG1+HI + 9811 7C31 20 EC 94 JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [FPC] + 9812 7C34 A9 06 LDA #6 ; POINT TO "LOC" SLOT + 9813 7C36 20 DE 8F jsr ADDFPC ; and point to it + 9814 7C39 20 56 92 jsr FETCHB ; well? + 9815 7C3C C5 66 CMP ARG2+HI ; IS IT THERE? + 9816 7C3E D0 0A BNE PBAD ; NO + 9817 7C40 20 BE 8F jsr NEXTFPC ; point to lo part + 9818 7C43 20 56 92 jsr FETCHB ; and get it + 9819 7C46 C5 65 CMP ARG2+LO + 9820 7C48 F0 13 BEQ PGOOD ; YES, SUCCEED + 9821 7C4A 4C 2F 44 PBAD: JMP PREDF ; TOO BAD, CHUM ... + 9822 + 9823 + 9824 ; ---- + 9825 ; BTST + 9826 ; ---- + 9827 ; IS EVERY "ON" BIT IN [ARG1] + 9828 ; ALSO "ON" IN [ARG2]? + 9829 + 9830 7C4D A5 65 ZBTST: LDA ARG2+LO ; FIRST CHECK LSBS + 9831 7C4F 25 63 AND ARG1+LO + 9832 7C51 C5 65 CMP ARG2+LO ; LSBS MATCH? + 9833 7C53 D0 F5 BNE PBAD ; NO, EXIT NOW + 9834 7C55 A5 66 LDA ARG2+HI ; ELSE CHECK MSBS + 9835 7C57 25 64 AND ARG1+HI + 9836 7C59 C5 66 CMP ARG2+HI ; MATCHED? + 9837 7C5B D0 ED BNE PBAD ; SORRY ... + 9838 7C5D PGOOD: + 9839 7C5D 4C 3B 44 JMP PREDS + 9840 + 9841 + 9842 ; --- + 9843 ; BOR + 9844 ; --- + 9845 ; RETURN [ARG1] "OR" [ARG2] + 9846 + 9847 7C60 A5 63 ZBOR: LDA ARG1+LO + 9848 7C62 05 65 ORA ARG2+LO + 9849 7C64 AA TAX + 9850 7C65 A5 64 LDA ARG1+HI + 9851 7C67 05 66 ORA ARG2+HI + 9852 + 9853 ; FALL THROUGH ... + 9854 + 9855 + 9856 ; --------------------- + 9857 ; RETURN VALUE IN [X/A] + 9858 ; --------------------- + 9859 + 9860 7C69 86 76 VEXIT: STX VALUE+LO + 9861 7C6B 85 77 STA VALUE+HI + 9862 7C6D 4C E1 43 JMP PUTVAL + 9863 + 9864 + 9865 ; ---- + 9866 ; BAND + 9867 ; ---- + 9868 ; RETURN [ARG1] "AND" [ARG2] + 9869 + 9870 7C70 A5 63 ZBAND: LDA ARG1+LO + 9871 7C72 25 65 AND ARG2+LO + 9872 7C74 AA TAX + 9873 7C75 A5 64 LDA ARG1+HI + 9874 7C77 25 66 AND ARG2+HI + Wed May 24 1989 15:00 Page 150 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9875 7C79 4C 69 7C JMP VEXIT + 9876 + 9877 + 9878 ; ----- + 9879 ; FSET? + 9880 ; ----- + 9881 ; IS FLAG [ARG2] SET IN OBJECT [ARG1]? + 9882 + 9883 7C7C 20 7B 95 ZFSETP: JSR FLAGSU ; GET BITS INTO [K] AND [J] + 9884 7C7F A5 7D LDA K+HI ; DO MSBS + 9885 7C81 25 7B AND J+HI + 9886 7C83 85 7D STA K+HI + 9887 7C85 A5 7C LDA K+LO ; DO LSBS + 9888 7C87 25 7A AND J+LO + 9889 7C89 05 7D ORA K+HI ; ANY BITS ON? + 9890 7C8B D0 D0 BNE PGOOD ; TARGET BIT MUST BE ON + 9891 7C8D 4C 2F 44 JMP PREDF + 9892 + 9893 + 9894 ; ---- + 9895 ; FSET + 9896 ; ---- + 9897 ; SET FLAG [ARG2] IN OBJECT [ARG1] + 9898 + 9899 7C90 ZFSET: + 9900 7C90 20 7B 95 JSR FLAGSU ; GET BITS INTO [K] & [J], ADDR IN [FPC] + 9901 ; + 9902 ; now, copy from FPC to SPC for stashing away + 9903 ; + 9904 7C93 20 73 90 jsr FP2SP ; okay, done it + 9905 7C96 A5 7D lda K+HI ; FIRST DO MSBS + 9906 7C98 05 7B ora J+HI + 9907 7C9A 20 35 92 jsr STASHB + 9908 7C9D 20 9E 8F jsr NEXTSPC + 9909 7CA0 A5 7C lda K+LO ; THEN LSBS + 9910 7CA2 05 7A ora J+LO + 9911 7CA4 20 35 92 jsr STASHB + 9912 7CA7 60 rts + 9913 + 9914 + 9915 ; ------ + 9916 ; FCLEAR + 9917 ; ------ + 9918 ; CLEAR FLAG [ARG2] IN OBJECT [ARG1] + 9919 + 9920 7CA8 ZFCLR: + 9921 7CA8 20 7B 95 jsr FLAGSU ; GETS BITS INTO [J] & [K], ADDR IN [FPC] + 9922 ; + 9923 ; now, copy from FPC to SPC for stashing away + 9924 ; + 9925 7CAB 20 73 90 jsr FP2SP ; okey dokey + 9926 + 9927 7CAE A5 7B lda J+HI ; FETCH MSB + 9928 7CB0 49 FF eor #$FF ; COMPLEMENT IT + 9929 7CB2 25 7D and K+HI ; RUB OUT FLAG + 9930 7CB4 20 35 92 jsr STASHB ; and save it + 9931 7CB7 20 9E 8F jsr NEXTSPC ; point to lo part + 9932 7CBA A5 7A lda J+LO ; SAME FOR LSB + 9933 7CBC 49 FF eor #$FF + 9934 7CBE 25 7C and K+LO + 9935 7CC0 20 35 92 jsr STASHB ; and show it to the world + 9936 7CC3 60 rts + 9937 + 9938 + 9939 ; --- + 9940 ; SET + 9941 ; --- + 9942 ; SET VARIABLE [ARG1] EQUAL TO [ARG2] + 9943 + 9944 7CC4 A5 65 ZSET: LDA ARG2+LO ; MOVE THE VALUE + 9945 7CC6 85 76 STA VALUE+LO ; INTO [VALUE] + 9946 7CC8 A5 66 LDA ARG2+HI + 9947 7CCA 85 77 STA VALUE+HI + 9948 7CCC A5 63 LDA ARG1+LO ; GET VARIABLE ID + 9949 7CCE 4C C7 43 JMP VARPUT ; AND CHANGE THE VARIABLE + Wed May 24 1989 15:00 Page 151 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + + 9950 + 9951 + 9952 ; ---- + 9953 ; MOVE + 9954 ; ---- + 9955 ; MOVE OBJECT [ARG1] INTO OBJECT [ARG2] + 9956 ; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + 9957 + 9958 7CD1 ZMOVE: + 9959 7CD1 20 5E 7A jsr ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS + 9960 ; + 9961 ; Make [ARG1] be first in [ARG2]'s chain. + 9962 ; + 9963 7CD4 A5 65 lda ARG2+LO + 9964 7CD6 A6 66 ldx ARG2+HI ; Get parent's address + 9965 7CD8 20 EC 94 jsr OBJLOC ; into [FPC] + 9966 7CDB A9 0A lda #10 ; point to FIRST slot + 9967 7CDD 20 DE 8F jsr ADDFPC ; okay + 9968 7CE0 20 56 92 jsr FETCHB ; get old first one (MSB) + 9969 7CE3 85 7D sta K+HI ; save it + 9970 7CE5 20 BE 8F jsr NEXTFPC ; point to next part + 9971 7CE8 20 56 92 jsr FETCHB ; and get it + 9972 7CEB 85 7C sta K+LO ; okay, saved + 9973 7CED 20 73 90 jsr FP2SP ; make FPC == SPC + 9974 ; + 9975 ; now make object [ARG1] be first in object [ARG2] + 9976 ; SPC is currently pointing to LSB of [ARG2]'s FIRST slot + 9977 ; + 9978 7CF0 A5 63 lda ARG1+LO ; stash away low part first + 9979 7CF2 20 35 92 jsr STASHB ; stashed + 9980 7CF5 20 4E 90 jsr PREVSPC ; point to high part + 9981 7CF8 A5 64 lda ARG1+HI ; get hi part of source + 9982 7CFA 20 35 92 jsr STASHB ; save it + 9983 ; + 9984 ; now point to object [ARG1] to update its slots + 9985 ; + 9986 7CFD A6 64 ldx ARG1+HI ; put hi part here + 9987 7CFF A5 63 lda ARG1+LO ; and lo part here for OBJLOC + 9988 7D01 20 EC 94 jsr OBJLOC ; get me the SOURCE of all confusion + 9989 7D04 A9 06 lda #6 ; point to LOC slot + 9990 7D06 20 DE 8F jsr ADDFPC ; and now FPC points there + 9991 7D09 20 73 90 jsr FP2SP ; now make it the STASH pointer + 9992 ; + 9993 ; update [ARG1]s LOC pointer to be [ARG2] + 9994 ; SPC points to LOC slot + 9995 ; + 9996 7D0C A5 66 lda ARG2+HI ; get PARENT number + 9997 7D0E 20 35 92 jsr STASHB ; and save it in LOC + 9998 7D11 20 9E 8F jsr NEXTSPC ; and point to LSB of LOC + 9999 7D14 A5 65 lda ARG2+LO ; got parent's lowness +10000 7D16 20 35 92 jsr STASHB ; and saved it in ARG1 +10001 ; +10002 ; Move old FIRST object and make it [ARG1]s NEXT +10003 ; now SPC points to [ARG1]s NEXT slot +10004 ; +10005 7D19 20 9E 8F jsr NEXTSPC ; point to MSB of NEXT +10006 7D1C A5 7D lda K+HI ; get old FIRST one +10007 7D1E 20 35 92 jsr STASHB ; and save it +10008 7D21 20 9E 8F jsr NEXTSPC ; and point to LSB now +10009 7D24 A5 7C lda K+LO ; get LSB of this +10010 7D26 20 35 92 jsr STASHB ; saved +10011 7D29 60 rts +10012 +10013 ; --- +10014 ; GET +10015 ; --- +10016 ; RETURN ITEM [ARG2] IN WORD-TABLE [ARG1] +10017 +10018 7D2A ZGET: +10019 7D2A 20 41 7D JSR WCALC ; CALC ADDRESS +10020 7D2D 20 09 92 JSR GETBYT ; GET 1ST BYTE (MSB) +10021 7D30 85 77 DOGET: STA VALUE+HI ; SAVE MSB +10022 7D32 20 09 92 JSR GETBYT ; GET LSB +10023 7D35 85 76 STA VALUE+LO ; SAVE AND +10024 7D37 4C E1 43 jmp PUTVAL ; HAND IT OVER + Wed May 24 1989 15:00 Page 152 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10025 +10026 +10027 ; ---- +10028 ; GETB +10029 ; ---- +10030 ; RETURN ITEM [ARG2] IN BYTE-TABLE AT [ARG1] +10031 +10032 7D3A ZGETB: +10033 7D3A 20 45 7D JSR BCALC +10034 7D3D A9 00 LDA #0 +10035 7D3F F0 EF BEQ DOGET ; [A] = 0, SO CLEAR MSB OF [VALUE] +10036 +10037 +10038 ; -------------------- +10039 ; CALC TABLE ADDRESSES +10040 ; -------------------- +10041 ; WORD-ALIGNED ENTRY +10042 +10043 7D41 WCALC: +10044 7D41 06 65 ASL ARG2+LO ; WORD-ALIGN FOR +10045 7D43 26 66 ROL ARG2+HI ; WORD ACCESS +10046 ; +10047 ; BYTE-ALIGNED ENTRY +10048 ; +10049 7D45 BCALC: +10050 7D45 A5 65 LDA ARG2+LO ; ADD BASE ADDR OF TABLE +10051 7D47 18 CLC ; TO ITEM +10052 7D48 65 63 ADC ARG1+LO ; INDEX +10053 7D4A 85 86 STA MPCL +10054 7D4C A5 66 LDA ARG2+HI ; SAME FOR MSBS +10055 7D4E 65 64 ADC ARG1+HI +10056 7D50 85 87 STA MPCM +10057 7D52 A9 00 LDA #0 +10058 7D54 69 00 ADC #0 ; PICK UP CARRY FROM MPCM +10059 7D56 85 88 STA MPCH ; TO GET TOP BIT +10060 7D58 4C 80 90 JMP VLDMPC +10061 +10062 +10063 ; ---- +10064 ; GETP +10065 ; ---- +10066 ; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +10067 ; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 +10068 +10069 7D5B ZGETP: +10070 7D5B 20 27 95 jsr PROPB ; set up FPC +10071 7D5E GETP1: +10072 7D5E 20 52 95 jsr PROPN ; GET ID OF PROP TBL +10073 7D61 C5 65 cmp ARG2+LO ; Compare PROP ID +10074 7D63 F0 30 beq GETP3 ; FOUND IT +10075 7D65 90 06 bcc GETP2 ; NOT THERE +10076 7D67 20 71 95 jsr PROPNX ; GET NEXT PROP, ALIGN [FPC] TO IT +10077 7D6A 4C 5E 7D jmp GETP1 ; TRY AGAIN WITH NEXT PROP +10078 ; +10079 ; PROPERTY NOT THERE, GET DEFAULT +10080 ; +10081 7D6D GETP2: +10082 7D6D A5 65 lda ARG2+LO ; GET PROPERTY # +10083 7D6F 38 sec ; ZERO-ALIGN IT +10084 7D70 E9 01 sbc #1 +10085 7D72 0A asl A ; WORD-ALIGN IT +10086 7D73 18 clc ; add in table start +10087 7D74 6D 0B 96 adc ZBEGIN+ZOBJEC+1 ; add lo part +10088 7D77 85 8C sta FPCL ; save for fetch +10089 7D79 AD 0A 96 lda ZBEGIN+ZOBJEC ; now get hi part +10090 7D7C 69 00 adc #0 ; pick up carry, if any +10091 7D7E 20 77 8F jsr SETPC ; get memory spot for this page +10092 7D81 85 8D sta FPCH ; page and +10093 7D83 84 8E sty FPCBNK ; bank +10094 7D85 20 56 92 jsr FETCHB ; GET MSB OF PROPERTY +10095 7D88 85 77 sta VALUE+HI +10096 7D8A 20 BE 8F jsr NEXTFPC +10097 7D8D 20 56 92 jsr FETCHB ; DO SAME WITH LSB +10098 7D90 85 76 sta VALUE+LO +10099 7D92 4C E1 43 jmp PUTVAL ; RETURN DEFAULT IN [VALUE] + Wed May 24 1989 15:00 Page 153 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10100 7D95 GETP3: +10101 7D95 20 58 95 jsr PROPL ; GET LENGTH OF PROP INTO [A] +10102 7D98 AA tax ; save [A] +10103 7D99 20 BE 8F jsr NEXTFPC ; MAKE [FPC] POINT TO 1ST BYTE OF PROP +10104 7D9C E0 01 cpx #1 ; IF LENGTH =1 +10105 7D9E F0 09 beq GETPB ; GET A BYTE PROPERTY +10106 7DA0 E0 02 cpx #2 ; IF LENGTH = 2 +10107 7DA2 F0 10 beq GETPW ; GET A WORD PROPERTY +10108 +10109 ; *** ERROR #7: PROPERTY LENGTH *** +10110 +10111 7DA4 A9 07 LDA #7 +10112 7DA6 4C 0A 52 JMP ZERROR +10113 ; +10114 ; GET A 1-BYTE PROPERTY +10115 ; +10116 7DA9 GETPB: +10117 7DA9 20 56 92 jsr FETCHB ; GET LSB INTO [A] +10118 7DAC 85 76 sta VALUE+LO ; STORE LSB +10119 7DAE A9 00 lda #0 ; CLEAR MSB +10120 7DB0 85 77 sta VALUE+HI ; and zero it +10121 7DB2 F0 0D beq ETPEX +10122 ; +10123 ; GET A 2-BYTE PROPERTY +10124 ; +10125 7DB4 GETPW: +10126 7DB4 20 56 92 jsr FETCHB ; GET MSB +10127 7DB7 85 77 sta VALUE+HI ; store MSB +10128 7DB9 20 BE 8F jsr NEXTFPC ; POINT TO LSB +10129 7DBC 20 56 92 jsr FETCHB ; GET IT INTO [A] +10130 7DBF 85 76 sta VALUE+LO ; AND MSB +10131 7DC1 ETPEX: +10132 7DC1 4C E1 43 jmp PUTVAL +10133 +10134 ; ----- +10135 ; GETPT +10136 ; ----- +10137 ; RETURN POINTER TO PROP TABLE [ARG2] +10138 ; IN OBJECT [ARG1] +10139 +10140 7DC4 ZGETPT: +10141 7DC4 A5 63 lda ARG1+LO +10142 7DC6 A6 64 ldx ARG1+HI ; (EZIP) +10143 7DC8 20 EC 94 jsr OBJLOC ; put location into [FPC] +10144 7DCB A9 0C lda #12 ; get offset table pointer +10145 7DCD 20 DE 8F jsr ADDFPC ; and point to it +10146 7DD0 20 56 92 jsr FETCHB ; get MSB of table pointer +10147 7DD3 48 pha ; save page +10148 7DD4 20 BE 8F jsr NEXTFPC ; point to LSB +10149 7DD7 20 56 92 jsr FETCHB ; and get it +10150 7DDA 85 8C sta FPCL ; and save it +10151 7DDC 68 pla ; get page address back +10152 7DDD 20 77 8F jsr SETPC ; and absolutize it +10153 7DE0 85 8D sta FPCH ; and save page +10154 7DE2 84 8E sty FPCBNK ; and bank +10155 7DE4 20 56 92 jsr FETCHB ; GET LENGTH OF SHORT DESC +10156 7DE7 0A asl A ; WORD-ALIGN IT +10157 7DE8 A8 tay ; now point to just past it +10158 7DE9 C8 iny ; thank you +10159 7DEA 98 tya ; for adding +10160 7DEB 20 DE 8F jsr ADDFPC ; and POINT JUST PAST THE DESCRIPTION +10161 7DEE GETPT1: +10162 7DEE 20 52 95 jsr PROPN ; get prop ID +10163 7DF1 C5 65 cmp ARG2+LO ; CHECK ID +10164 7DF3 F0 0B beq GETPT2 +10165 7DF5 B0 03 bcs DDD ; .GE. so check some more +10166 7DF7 4C 2E 7E jmp DORET ; BEYOND IT, SO NOT THERE +10167 7DFA DDD: +10168 7DFA 20 71 95 jsr PROPNX ; point to next one +10169 7DFD 4C EE 7D jmp GETPT1 ; next please +10170 7E00 GETPT2: +10171 7E00 20 58 95 jsr PROPL ; get the length of this property +10172 7E03 20 BE 8F jsr NEXTFPC ; INC TO POINT AT PROPERTY VALUE (EZIP) +10173 ; +10174 ; now subtract absolute address to get relative address for returning + Wed May 24 1989 15:00 Page 154 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10175 ; what a pain in the neck +10176 ; +10177 7E06 A5 8E lda FPCBNK ; check which bank we are in +10178 7E08 F0 16 beq GETPB0 ; in main bank, it's easier +10179 ; +10180 ; if in AUX bank, then we must subtract beginning of AUX mem, then +10181 ; add in size of MAIN bank +10182 ; +10183 7E0A A5 8D lda FPCH ; get page +10184 7E0C C9 D0 cmp #>Z3BEGIN ; in part 2 of aux? +10185 7E0E B0 08 bcs GETPB3 ; ayyup +10186 7E10 38 sec ; and subtract +10187 7E11 E9 40 sbc #>Z2BEGIN ; first page in aux +10188 7E13 18 clc ; now add in how many pages in main +10189 7E14 69 29 adc #P2PAGE ; now we have relative start +10190 7E16 D0 0D bne GETP15 ; JUMP to putval +10191 7E18 GETPB3: +10192 7E18 38 sec ; and subtract +10193 7E19 E9 D0 sbc #>Z3BEGIN ; first page in aux, part 2 +10194 7E1B 18 clc ; now add in how many pages in main +10195 7E1C 69 A8 adc #P3PAGE ; now we have relative start +10196 7E1E D0 05 bne GETP15 ; jump to putval +10197 7E20 GETPB0: +10198 7E20 A5 8D lda FPCH ; get page in main mem +10199 7E22 38 sec ; and then subtract +10200 7E23 E9 96 sbc #>ZBEGIN ; start of main mem +10201 7E25 GETP15: +10202 7E25 85 77 sta VALUE+HI ; save hi part for returning +10203 7E27 A5 8C lda FPCL ; and just save lo part +10204 7E29 85 76 sta VALUE+LO ; okay? +10205 7E2B 4C E1 43 jmp PUTVAL ; AND RETURN +10206 7E2E DORET: +10207 7E2E 4C DA 43 jmp RET0 ; ELSE RETURN A ZERO +10208 +10209 +10210 ; ----- +10211 ; NEXTP +10212 ; ----- +10213 ; RETURN INDEX # OF PROP FOLLOWING PROP [ARG2] IN OBJECT [AR +10214 ; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO +10215 +10216 7E31 ZNEXTP: +10217 7E31 20 27 95 JSR PROPB ; ALIGN [FPC] AT PROPERTY TBL'S 1ST ENTRY +10218 7E34 A5 65 LDA ARG2+LO ; IF [ARG2]=0 +10219 7E36 F0 12 BEQ NXTP3 ; RETURN "FIRST" SLOT +10220 7E38 NXTP1: +10221 7E38 20 52 95 JSR PROPN ; FETCH PROPERTY # +10222 7E3B C5 65 CMP ARG2+LO ; COMPARE TO TARGET # +10223 7E3D F0 08 BEQ NXTP2 ; FOUND IT! +10224 7E3F 90 ED BCC DORET ; LAST PROP, SO RETURN ZERO +10225 7E41 20 71 95 JSR PROPNX ; ELSE TRY NEXT PROPERTY (EZIP) +10226 7E44 4C 38 7E JMP NXTP1 +10227 7E47 20 71 95 NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +10228 7E4A 20 52 95 NXTP3: JSR PROPN ; GET THE PROPERTY # +10229 7E4D A2 00 LDX #0 ; FOR PUTBYT (EZIP) +10230 7E4F 4C DD 43 JMP PUTBYT ; AND RETURN IT +10231 +10232 +10233 ; --- +10234 ; ADD +10235 ; --- +10236 ; RETURN [ARG1] + [ARG2] +10237 +10238 7E52 A5 63 ZADD: LDA ARG1+LO ; ADD LSBS +10239 7E54 18 CLC +10240 7E55 65 65 ADC ARG2+LO +10241 7E57 AA TAX ; SAVE LSB HERE +10242 7E58 A5 64 LDA ARG1+HI ; ADD MSBS +10243 7E5A 65 66 ADC ARG2+HI +10244 7E5C 4C 69 7C JMP VEXIT +10245 +10246 +10247 ; --- +10248 ; SUB +10249 ; --- + Wed May 24 1989 15:00 Page 155 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10250 ; RETURN [ARG1] - [ARG2] +10251 +10252 7E5F A5 63 ZSUB: LDA ARG1+LO ; SUBTRACT LSBS +10253 7E61 38 SEC +10254 7E62 E5 65 SBC ARG2+LO +10255 7E64 AA TAX ; SAVE LSB HERE +10256 7E65 A5 64 LDA ARG1+HI ; SUBTRACT MSBS +10257 7E67 E5 66 SBC ARG2+HI +10258 7E69 4C 69 7C JMP VEXIT ; EXIT WITH [X]=LSB, [A]=MSB +10259 +10260 +10261 ; --- +10262 ; MUL +10263 ; --- +10264 ; RETURN [ARG1] * [ARG2] +10265 +10266 7E6C 20 52 7F ZMUL: JSR MINIT ; INIT THINGS +10267 7E6F 6E 61 5B ZMLOOP: ROR MTEMP+HI +10268 7E72 6E 60 5B ROR MTEMP+LO +10269 7E75 66 66 ROR ARG2+HI +10270 7E77 66 65 ROR ARG2+LO +10271 7E79 90 11 BCC ZMNEXT +10272 7E7B A5 63 LDA ARG1+LO +10273 7E7D 18 CLC +10274 7E7E 6D 60 5B ADC MTEMP+LO +10275 7E81 8D 60 5B STA MTEMP+LO +10276 7E84 A5 64 LDA ARG1+HI +10277 7E86 6D 61 5B ADC MTEMP+HI +10278 7E89 8D 61 5B STA MTEMP+HI +10279 7E8C CA ZMNEXT: DEX +10280 7E8D 10 E0 BPL ZMLOOP +10281 7E8F A6 65 LDX ARG2+LO ; PUT LSB OF PRODUCT +10282 7E91 A5 66 LDA ARG2+HI ; AND MSB +10283 7E93 4C 69 7C JMP VEXIT ; WHERE "VEXIT" EXPECTS THEM +10284 +10285 +10286 ; --- +10287 ; DIV +10288 ; --- +10289 ; RETURN QUOTIENT OF [ARG1] / [ARG2] +10290 +10291 7E96 20 AE 7E ZDIV: JSR DIVIDE +10292 7E99 AE 5B 6C LDX QUOT+LO +10293 7E9C AD 5C 6C LDA QUOT+HI +10294 7E9F 4C 69 7C JMP VEXIT +10295 +10296 +10297 ; --- +10298 ; MOD +10299 ; --- +10300 ; RETURN REMAINDER OF [ARG1] / [ARG2] +10301 +10302 7EA2 20 AE 7E ZMOD: JSR DIVIDE +10303 7EA5 AE 5D 6C LDX REMAIN+LO ; FETCH THE REMAINDER +10304 7EA8 AD 5E 6C LDA REMAIN+HI ; IN [REMAIN] +10305 7EAB 4C 69 7C JMP VEXIT ; AND RETURN IT +10306 +10307 +10308 ; --------------- +10309 ; SIGNED DIVISION +10310 ; --------------- +10311 ; ENTRY: DIVIDEND IN [ARG1], DIVISOR IN [ARG2] +10312 ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] +10313 +10314 7EAE DIVIDE: +10315 7EAE A5 64 LDA ARG1+HI ; SIGN OF REMAINDER +10316 7EB0 8D 60 6C STA RSIGN ; IS THE SIGN OF THE DIVIDEND +10317 7EB3 45 66 EOR ARG2+HI ; SIGN OF QUOTIENT IS POSITIVE +10318 7EB5 8D 5F 6C STA QSIGN ; IF SIGNS OF TERMS ARE THE SAME +10319 7EB8 A5 63 LDA ARG1+LO ; MOVE [ARG1] TO [QUOT] +10320 7EBA 8D 5B 6C STA QUOT+LO +10321 7EBD A5 64 LDA ARG1+HI +10322 7EBF 8D 5C 6C STA QUOT+HI ; IF DIVIDEND IS POSITIVE +10323 7EC2 10 03 BPL ABSDIV ; MOVE DIVISOR +10324 7EC4 20 F8 7E JSR ABQUOT ; ELSE CALC ABS(DIVIDEND) FIRST + Wed May 24 1989 15:00 Page 156 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10325 7EC7 A5 65 ABSDIV: LDA ARG2+LO +10326 7EC9 8D 5D 6C STA REMAIN+LO +10327 7ECC A5 66 LDA ARG2+HI +10328 7ECE 8D 5E 6C STA REMAIN+HI ; IF REMAINDER IS POSITIVE +10329 7ED1 10 03 BPL GODIV ; WE'RE READY TO DIVIDE +10330 7ED3 20 E6 7E JSR ABREM ; ELSE CALC ABS(DIVISOR) +10331 7ED6 20 0A 7F GODIV: JSR UDIV ; DO UNSIGNED DIVIDE +10332 7ED9 AD 5F 6C LDA QSIGN ; SHOULD QUOTIENT BE FLIPPED? +10333 7EDC 10 03 BPL RFLIP ; NO, TEST REMAINDER +10334 7EDE 20 F8 7E JSR ABQUOT ; ELSE GET ABSOLUTE VALUE +10335 7EE1 AD 60 6C RFLIP: LDA RSIGN ; SHOULD EMAINDER BE FLIPPED? +10336 7EE4 10 11 BPL DIVEX ; NO, WE'RE DONE +10337 +10338 ; ELSE FALL THROUGH ... +10339 +10340 +10341 ; ---------------- +10342 ; CALC ABS(REMAIN) +10343 ; ---------------- +10344 +10345 7EE6 A9 00 ABREM: LDA #0 +10346 7EE8 38 SEC +10347 7EE9 ED 5D 6C SBC REMAIN+LO +10348 7EEC 8D 5D 6C STA REMAIN+LO +10349 7EEF A9 00 LDA #0 +10350 7EF1 ED 5E 6C SBC REMAIN+HI +10351 7EF4 8D 5E 6C STA REMAIN+HI +10352 7EF7 60 DIVEX: RTS +10353 +10354 +10355 ; -------------- +10356 ; CALC ABS(QUOT) +10357 ; -------------- +10358 +10359 7EF8 A9 00 ABQUOT: LDA #0 +10360 7EFA 38 SEC +10361 7EFB ED 5B 6C SBC QUOT+LO +10362 7EFE 8D 5B 6C STA QUOT+LO +10363 7F01 A9 00 LDA #0 +10364 7F03 ED 5C 6C SBC QUOT+HI +10365 7F06 8D 5C 6C STA QUOT+HI +10366 7F09 60 RTS +10367 +10368 +10369 ; ----------------- +10370 ; UNSIGNED DIVISION +10371 ; ----------------- +10372 ; ENTRY: DIVIDEND IN [QUOT], DIVISOR IN [REMAIN] +10373 ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] +10374 +10375 7F0A UDIV: +10376 7F0A AD 5D 6C LDA REMAIN+LO ; CHECK [REMAIN] +10377 7F0D 0D 5E 6C ORA REMAIN+HI ; BEFORE PROCEEDING +10378 7F10 F0 3B BEQ DIVERR ; CAN'T DIVIDE BY ZERO! +10379 7F12 20 52 7F JSR MINIT ; SET IT ALL UP +10380 7F15 2E 5B 6C UDLOOP: ROL QUOT+LO +10381 7F18 2E 5C 6C ROL QUOT+HI +10382 7F1B 2E 60 5B ROL MTEMP+LO +10383 7F1E 2E 61 5B ROL MTEMP+HI +10384 7F21 AD 60 5B LDA MTEMP+LO +10385 7F24 38 SEC +10386 7F25 ED 5D 6C SBC REMAIN+LO +10387 7F28 A8 TAY ; SAVE HERE +10388 7F29 AD 61 5B LDA MTEMP+HI +10389 7F2C ED 5E 6C SBC REMAIN+HI +10390 7F2F 90 06 BCC UDNEXT +10391 7F31 8C 60 5B STY MTEMP+LO +10392 7F34 8D 61 5B STA MTEMP+HI +10393 7F37 CA UDNEXT: DEX +10394 7F38 D0 DB BNE UDLOOP +10395 7F3A 2E 5B 6C ROL QUOT+LO ; SHIFT LAST CARRY FOR QUOTIENT +10396 7F3D 2E 5C 6C ROL QUOT+HI +10397 7F40 AD 60 5B LDA MTEMP+LO ; MOVE REMAINDER +10398 7F43 8D 5D 6C STA REMAIN+LO ; INTO [REMAIN] +10399 7F46 AD 61 5B LDA MTEMP+HI + Wed May 24 1989 15:00 Page 157 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10400 7F49 8D 5E 6C STA REMAIN+HI +10401 7F4C 60 RTS +10402 +10403 ; *** ERROR #8: DIVISION BY ZERO *** +10404 +10405 7F4D A9 08 DIVERR: LDA #8 +10406 7F4F 4C 0A 52 JMP ZERROR +10407 +10408 +10409 ; --------- +10410 ; MATH INIT +10411 ; --------- +10412 +10413 7F52 A2 10 MINIT: LDX #16 ; INIT LOOPING INDEX +10414 7F54 A9 00 LDA #0 +10415 7F56 8D 60 5B STA MTEMP+LO ; CLEAR TEMP +10416 7F59 8D 61 5B STA MTEMP+HI ; REGISTER +10417 7F5C 18 CLC ; AND CARRY +10418 7F5D 60 RTS +10419 +10420 +10421 ; ----- +10422 ; THROW +10423 ; ----- +10424 +10425 7F5E ZTHROW: +10426 7F5E A5 65 lda ARG2+LO ; check to see if we are ready to do return +10427 7F60 CD 75 6C cmp OLDZSP+LO +10428 7F63 D0 07 bne ZTHLOOP ; nope, keep unwinding the stack +10429 7F65 A5 66 lda ARG2+HI +10430 7F67 CD 76 6C cmp OLDZSP+HI ; have we found the right frame yet? +10431 7F6A F0 06 beq ZTHDO ; yes +10432 7F6C ZTHLOOP: +10433 7F6C 20 56 7B jsr ZRET ; do another return +10434 7F6F 4C 5E 7F jmp ZTHROW ; and try again +10435 7F72 ZTHDO: +10436 7F72 A5 65 lda ARG2+LO ; SET ZSTACK POINTER +10437 7F74 8D 75 6C sta OLDZSP+LO ; UP FOR ZRET +10438 7F77 A5 66 lda ARG2+HI +10439 7F79 8D 76 6C sta OLDZSP+HI +10440 7F7C 4C 56 7B jmp ZRET +10441 +10442 7F7F END +10443 +10444 7F7F INCLUDE OPSX.ASM +10445 PAGE + Wed May 24 1989 15:00 Page 158 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- 2-OPS ---" + +10446 7F7F STTL "--- X-OPS ---" +10447 +10448 +10449 ; ------ +10450 ; EQUAL? +10451 ; ------ +10452 ; IS [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? +10453 +10454 7F7F ZEQUAL: +10455 7F7F C6 62 DEC NARGS ; DOUBLE-CHECK # ARGS +10456 7F81 A5 63 LDA ARG1+LO ; FETCH LSB +10457 7F83 A6 64 LDX ARG1+HI ; AND MSB OF [ARG1] +10458 7F85 C5 65 CMP ARG2+LO ; TEST LSB OF [ARG2] +10459 7F87 D0 04 BNE TRY2 ; NO GOOD, LOOK FOR ANOTHER ARG +10460 7F89 E4 66 CPX ARG2+HI ; ELSE TRY MSB OF [ARG2] +10461 7F8B F0 18 BEQ EQOK ; MATCHED! +10462 7F8D C6 62 TRY2: DEC NARGS ; OUT OF ARGS YET? +10463 7F8F F0 17 BEQ EQBAD ; YES, WE FAILED +10464 7F91 C5 67 CMP ARG3+LO ; TRY LSB OF [ARG3] +10465 7F93 D0 04 BNE TRY3 ; NO GOOD, LOOK FOR ANOTHER ARG +10466 7F95 E4 68 CPX ARG3+HI ; HOW ABOUT MSB OF [ARG3]? +10467 7F97 F0 0C BEQ EQOK ; YAY! +10468 7F99 C6 62 TRY3: DEC NARGS ; OUT OF ARGS YET? +10469 7F9B F0 0B BEQ EQBAD ; IF NOT ... +10470 7F9D C5 69 CMP ARG4+LO ; TRY [ARG4] +10471 7F9F D0 07 BNE EQBAD ; SORRY, CHUM +10472 7FA1 E4 6A CPX ARG4+HI ; MSB MATCHED? +10473 7FA3 D0 03 BNE EQBAD ; TOO BAD +10474 +10475 7FA5 4C 3B 44 EQOK: JMP PREDS ; FINALLY MATCHED! +10476 +10477 7FA8 4C 2F 44 EQBAD: JMP PREDF ; FAILURE (SNIFF!) +10478 +10479 +10480 ; ---------------------------- +10481 ; ICALL,ICALL1, ICALL2, IXCALL +10482 ; ---------------------------- +10483 +10484 7FAB ZICALL: +10485 7FAB ZICLL1: +10486 7FAB ZICLL2: +10487 7FAB A9 01 ZIXCLL: LDA #1 ; SET FLAG FOR RETURNLESS CALL +10488 7FAD 8D 5F 5B STA IRET +10489 7FB0 D0 05 BNE IENTR ; JMP OVER NORMAL SETTING +10490 +10491 +10492 ; ------------------- +10493 ; XCALL, CALL1, CALL2 +10494 ; ------------------- +10495 +10496 ZXCALL: ; DROP THROUGH +10497 ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +10498 7FB2 ZCALL2: +10499 +10500 ; ---- +10501 ; CALL +10502 ; ---- +10503 ; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +10504 ; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +10505 ; ([ARG5]-[ARG8] FOR XCALL (EZIP)) +10506 +10507 7FB2 A9 00 ZCALL: LDA #0 +10508 7FB4 8D 5F 5B STA IRET ; SET FLAG TO RETURN SOMETHING +10509 7FB7 A5 63 IENTR: LDA ARG1+LO +10510 7FB9 05 64 ORA ARG1+HI ; IS CALL ADDRESS ZERO? +10511 7FBB D0 0B BNE DOCALL ; NO, CONTINUE +10512 7FBD AD 5F 5B LDA IRET ; any ret value? +10513 7FC0 F0 01 BEQ Ij ; yes, so return a zero +10514 +10515 7FC2 60 RTS ; otherwise, just end +10516 7FC3 Ij: +10517 7FC3 A2 00 LDX #0 +10518 7FC5 4C DD 43 JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +10519 7FC8 AE 75 6C DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER +10520 7FCB AD 76 6C LDA OLDZSP+HI + Wed May 24 1989 15:00 Page 159 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +10521 7FCE 20 9B 43 JSR PUSHXA +10522 7FD1 A5 80 LDA ZPCL ; AND LSB OF [ZPC] +10523 7FD3 AE 5F 5B LDX IRET ; AND RETURN FLAG +10524 7FD6 20 9B 43 JSR PUSHXA ; ON THE Z-STACK +10525 7FD9 A6 81 LDX ZPCM ; SAVE MIDDLE 8 BITS +10526 7FDB A5 82 LDA ZPCH ; AND TOP BIT OF [ZPC] +10527 7FDD 20 9B 43 JSR PUSHXA ; AS WELL +10528 +10529 ; FORM 16-BIT ADDRESS FROM [ARG1] +10530 +10531 7FE0 A9 00 LDA #0 +10532 7FE2 06 63 ASL ARG1+LO ; MULTIPLY [ARG1] +10533 7FE4 26 64 ROL ARG1+HI ; (BY 2) +10534 7FE6 2A ROL A ; >BIT INTO [A] +10535 7FE7 06 63 ASL ARG1+LO ; BY 4 (EZIP) +10536 7FE9 26 64 ROL ARG1+HI +10537 7FEB 2A ROL A +10538 7FEC 85 82 STA ZPCH ; NEW >BIT OF [ZPC] +10539 7FEE A5 64 LDA ARG1+HI ; GET NEW 0, just ignore! +10930 8269 05 67 ORA ARG3+LO +10931 826B F0 79 BEQ INTNF ; SAY NOT FOUND +10932 +10933 826D A5 62 LDA NARGS ; IS THERE A RECORD SPEC? +10934 826F C9 04 CMP #4 +10935 8271 F0 04 BEQ SET4 +10936 8273 A9 82 SETDEF: LDA #130 ; NO, SET DEFAULT +10937 8275 85 69 STA ARG4+LO +10938 +10939 8277 A5 69 SET4: LDA ARG4+LO +10940 8279 F0 F8 BEQ SETDEF ; GO BACK AND GET VALUE +10941 827B A9 00 LDA #0 ; COMPARE BYTE OR WORD? +10942 827D 06 69 ASL ARG4+LO +10943 827F 2A ROL A ; PICK UP INDICATOR +10944 8280 46 69 LSR ARG4+LO ; CLEAR FROM RECORD LENGTH +10945 8282 8D 62 5B STA TYPE ; BYTE (0) OR WORD (1) +10946 8285 AD 62 5B LDA TYPE ; SET FLAG +10947 8288 D0 04 BNE SETTBL +10948 828A A5 63 LDA ARG1+LO ; IF ONLY BYTE, MOVE IT +10949 828C 85 64 STA ARG1+HI ; TO FIRST BYTE CHECKED +10950 828E SETTBL: +10951 828E A5 65 LDA ARG2+LO ; PICK UP TBL ADDR +10952 8290 85 86 STA MPCL +10953 8292 A5 66 LDA ARG2+HI +10954 8294 85 87 STA MPCM +10955 8296 A9 00 LDA #0 +10956 8298 85 88 STA MPCH ; ONLY A WORD ADDR, SO IN 1ST 64K +10957 829A 20 80 90 JSR VLDMPC +10958 +10959 829D A5 86 INTLP: LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS +10960 829F 8D 7B 00 STA VWCUR+0 +10961 82A2 A5 87 LDA MPCM +10962 82A4 8D 7C 00 STA VWCUR+1 +10963 82A7 A5 88 LDA MPCH +10964 82A9 8D 7D 00 STA VWCUR+2 +10965 82AC 20 09 92 JSR GETBYT ; GET 1ST BYTE +10966 82AF C5 64 CMP ARG1+HI ; DOES IT = THE VALUE LOOKING FOR? +10967 82B1 D0 0C BNE INTNXT ; NO +10968 82B3 AD 62 5B LDA TYPE +10969 82B6 F0 3A BEQ INTFND ; ONLY COMPARING A BYTE SO FOUND! +10970 82B8 20 09 92 JSR GETBYT + Wed May 24 1989 15:00 Page 165 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +10971 82BB C5 63 CMP ARG1+LO +10972 82BD F0 33 BEQ INTFND ; YES, FOUND IT +10973 82BF INTNXT: +10974 82BF AD 7B 00 LDA VWCUR+0 ; TO MOVE UP, JUST ADD +10975 82C2 18 CLC ; OFFSET FROM START OF THIS +10976 82C3 65 69 ADC ARG4+LO ; ENTRY +10977 82C5 85 86 STA MPCL +10978 82C7 90 11 BCC INEXT0 +10979 +10980 82C9 AD 7C 00 LDA VWCUR+1 ; PICK UP CARRY +10981 82CC 69 00 ADC #0 +10982 82CE 85 87 STA MPCM +10983 82D0 AD 7D 00 LDA VWCUR+2 +10984 82D3 69 00 ADC #0 +10985 82D5 85 88 STA MPCH +10986 82D7 20 80 90 JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE +10987 +10988 82DA C6 67 INEXT0: DEC ARG3+LO ; CHECKED ALL ENTRIES? +10989 82DC D0 BF BNE INTLP +10990 82DE A5 68 LDA ARG3+HI +10991 82E0 F0 04 BEQ INTNF +10992 82E2 C6 68 DEC ARG3+HI +10993 82E4 D0 B7 BNE INTLP +10994 +10995 82E6 INTNF: +10996 82E6 A9 00 LDA #0 ; 0 = NOT FOUND +10997 82E8 85 76 STA VALUE+LO +10998 82EA 85 77 STA VALUE+HI +10999 82EC 20 E1 43 JSR PUTVAL +11000 82EF 4C 2F 44 JMP PREDF ; FAILED! +11001 +11002 82F2 INTFND: +11003 82F2 AD 7B 00 LDA VWCUR+LO +11004 82F5 85 76 STA VALUE+LO ; AND SET TO RETURN THE VALUE +11005 82F7 AD 7C 00 LDA VWCUR+HI +11006 82FA 85 77 STA VALUE+HI +11007 82FC 20 E1 43 JSR PUTVAL ; SEND IT BACK +11008 82FF 4C 3B 44 JMP PREDS ; AND SCREEM SUCCESS +11009 +11010 ; ---- +11011 ; BCOM +11012 ; ---- +11013 ; COMPLEMENT [ARG1] +11014 +11015 8302 A5 63 ZBCOM: LDA ARG1+LO +11016 8304 49 FF EOR #$FF +11017 8306 85 76 STA VALUE+LO +11018 8308 A5 64 LDA ARG1+HI +11019 830A 49 FF EOR #$FF +11020 830C 85 77 STA VALUE+HI +11021 830E 4C E1 43 JMP PUTVAL +11022 +11023 +11024 ; ----- +11025 ; COPYT +11026 ; ----- +11027 +11028 8311 ZCOPYT: +11029 8311 A5 65 LDA ARG2+LO ; CHECK OUT WHAT'S TO BE DONE +11030 8313 05 66 ORA ARG2+HI +11031 8315 D0 03 BNE ZC0 +11032 8317 4C C6 83 JMP CASE1 ; ZERO LENGTH BYTES OF SOURCE +11033 831A ZC0: +11034 831A A5 68 LDA ARG3+HI +11035 831C C9 7F CMP #$7F +11036 831E 90 03 BCC CASE2 +11037 8320 4C EC 83 JMP CASE3 ; FORWARD COPY +11038 +11039 ; CASE2 - CHECK IF FORWARD OR BACKWARD COPY +11040 +11041 8323 A5 64 CASE2: LDA ARG1+HI ; IF SRC < DEST +11042 8325 C5 66 CMP ARG2+HI +11043 8327 90 0D BCC CHK2 +11044 8329 F0 03 BEQ ZC1 +11045 832B 4C 4F 83 JMP FRWRD ; NO + Wed May 24 1989 15:00 Page 166 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11046 832E A5 63 ZC1: LDA ARG1+LO +11047 8330 C5 65 CMP ARG2+LO +11048 8332 F0 02 BEQ CHK2 +11049 8334 B0 19 BCS FRWRD ; NO +11050 8336 A5 63 CHK2: LDA ARG1+LO ; AND SRC + LENGTH > DEST +11051 8338 18 CLC +11052 8339 65 67 ADC ARG3+LO +11053 833B 85 78 STA I+LO +11054 833D A5 64 LDA ARG1+HI +11055 833F 65 68 ADC ARG3+HI +11056 8341 C5 66 CMP ARG2+HI +11057 8343 90 0A BCC FRWRD ; NO +11058 8345 D0 3E BNE BKWRD ; YES +11059 8347 A5 78 LDA I+LO +11060 8349 C5 65 CMP ARG2+LO +11061 834B F0 02 BEQ FRWRD ; DEBUG, IF EQUAL REALLY LESS +11062 834D B0 36 BCS BKWRD ; OVERLAPS SO DO BACKWARD COPY +11063 +11064 ; ELSE FALL THROUGH TO FORWARD COPY +11065 +11066 834F A9 00 FRWRD: LDA #0 ; USE GETBYT CAUSE MAY BE +11067 8351 85 88 STA MPCH ; BEYOND MAIN MEMORY +11068 8353 A5 64 LDA ARG1+HI +11069 8355 85 87 STA MPCM +11070 8357 A5 63 LDA ARG1+LO +11071 8359 85 86 STA MPCL +11072 835B 20 80 90 JSR VLDMPC ; AND ALIGN TO CORRECT PAGE +11073 835E A5 65 LDA ARG2+LO +11074 8360 85 8F STA SPCL +11075 8362 A5 66 LDA ARG2+HI +11076 8364 20 77 8F jsr SETPC ; get memory spot +11077 8367 85 90 sta SPCH ; high part +11078 8369 84 91 sty SPCBNK ; and the bank part +11079 836B A5 67 LDA ARG3+LO +11080 836D 85 7A STA J+LO +11081 836F A5 68 LDA ARG3+HI +11082 8371 85 7B STA J+HI +11083 8373 FRLP: +11084 8373 20 C6 44 jsr DECJ +11085 8376 90 0C bcc FRDUN ; CARRY CLEAR ON $FFFF +11086 8378 20 09 92 jsr GETBYT +11087 837B 20 35 92 jsr STASHB ; and save it +11088 837E 20 9E 8F jsr NEXTSPC ; and point to next one +11089 8381 4C 73 83 jmp FRLP +11090 8384 FRDUN: +11091 8384 60 rts +11092 +11093 +11094 8385 BKWRD: +11095 8385 A5 67 LDA ARG3+LO ; DECR 1ST TO GET CORRECT OFFSET +11096 8387 85 7A STA J+LO +11097 8389 A5 68 LDA ARG3+HI +11098 838B 85 7B STA J+HI +11099 838D 20 C6 44 JSR DECJ +11100 8390 A5 63 LDA ARG1+LO ; SET TO END OF SOURCE & DEST. +11101 8392 18 CLC +11102 8393 65 7A ADC J+LO +11103 8395 85 8C sta FPCL ; set up fetch pointer +11104 8397 A5 64 LDA ARG1+HI +11105 8399 65 7B ADC J+HI +11106 839B 20 77 8F jsr SETPC ; and get mem locations +11107 839E 85 8D sta FPCH +11108 83A0 84 8E sty FPCBNK +11109 83A2 A5 65 LDA ARG2+LO +11110 83A4 18 CLC +11111 83A5 65 7A ADC J+LO +11112 83A7 85 8F sta SPCL ; and now set up stash pointer +11113 83A9 A5 66 LDA ARG2+HI +11114 83AB 65 7B ADC J+HI +11115 83AD 20 77 8F jsr SETPC ; and get me page/bank +11116 83B0 85 90 sta SPCH +11117 83B2 84 91 sty SPCBNK +11118 83B4 BKLP: +11119 83B4 20 56 92 jsr FETCHB ; get byte +11120 83B7 20 35 92 jsr STASHB ; and save it + Wed May 24 1989 15:00 Page 167 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11121 83BA 20 24 90 jsr PREVFPC ; going backwards +11122 83BD 20 4E 90 jsr PREVSPC ; and here too +11123 83C0 20 C6 44 jsr DECJ ; RETURNS CARRY CLEAR ON $FFFF +11124 83C3 B0 EF bcs BKLP +11125 83C5 BKDUN: +11126 83C5 60 RTS +11127 +11128 ; ZERO LENGTH # OF BYTES OF SOURCE +11129 +11130 83C6 A5 63 CASE1: LDA ARG1+LO +11131 83C8 85 8F STA SPCL ; set stash pointer +11132 83CA A5 64 LDA ARG1+HI +11133 83CC 20 77 8F jsr SETPC ; get page/bank +11134 83CF 85 90 sta SPCH +11135 83D1 84 91 sty SPCBNK +11136 83D3 A5 67 LDA ARG3+LO ; SET UP COUNTER +11137 83D5 85 7A STA J+LO +11138 83D7 A5 68 LDA ARG3+HI +11139 83D9 85 7B STA J+HI +11140 83DB C1LP: +11141 83DB 20 C6 44 jsr DECJ ; CARRY CLEAR WHEN J = $FFFF +11142 83DE 90 0B bcc C1DUN +11143 83E0 A9 00 lda #0 +11144 83E2 20 35 92 jsr STASHB ; and zero it +11145 83E5 20 9E 8F jsr NEXTSPC ; and point to next one +11146 83E8 4C DB 83 jmp C1LP +11147 83EB C1DUN: +11148 83EB 60 rts +11149 +11150 ; 2'S COMPLEMENT LENGTH (XOR + 1) THEN DO FORWARD COPY +11151 +11152 83EC CASE3: +11153 83EC A5 67 LDA ARG3+LO +11154 83EE 49 FF EOR #$FF +11155 83F0 85 67 STA ARG3+LO +11156 83F2 A5 68 LDA ARG3+HI +11157 83F4 49 FF EOR #$FF +11158 83F6 85 68 STA ARG3+HI +11159 83F8 E6 67 INC ARG3+LO +11160 83FA D0 02 BNE GOFRWD +11161 83FC E6 68 INC ARG3+HI +11162 83FE 4C 4F 83 GOFRWD: JMP FRWRD +11163 +11164 +11165 ; --------- +11166 ; ASSIGNED? +11167 ; --------- +11168 +11169 +11170 8401 ZASSND: +11171 8401 A5 63 LDA ARG1+LO ; COMPARE TO # OF OPTIONALS FROM LAST CALL +11172 8403 CD 63 5B CMP ASSVLU +11173 8406 90 05 BCC DOYES ; IF LESS OR EQUAL, WAS ASSIGNED +11174 8408 F0 03 BEQ DOYES +11175 840A 4C 2F 44 JMP PREDF +11176 840D DOYES: +11177 840D 4C 3B 44 JMP PREDS +11178 +11179 +11180 ; ------------- +11181 ; LOGICAL SHIFT +11182 ; ------------- +11183 ; SHIFT ARG1, ARG2 BITS (LEFT IF ARG2 IS POS. RIGHT IF NEG.) +11184 +11185 8410 A5 63 ZSHIFT: LDA ARG1+LO ; SET UP FOR SHIFT +11186 8412 85 76 STA VALUE+LO +11187 8414 A5 64 LDA ARG1+HI +11188 8416 85 77 STA VALUE+HI +11189 8418 A5 65 LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT +11190 841A C9 80 CMP #$80 +11191 841C B0 0B BCS SRIGHT +11192 +11193 ; SHIFT LEFT +11194 +11195 841E A8 TAY ; COUNT + Wed May 24 1989 15:00 Page 168 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11196 841F 06 76 SLP1: ASL VALUE+LO +11197 8421 26 77 ROL VALUE+HI +11198 8423 88 DEY +11199 8424 D0 F9 BNE SLP1 +11200 8426 4C E1 43 JMP PUTVAL ; AND RETURN THE VALUE +11201 +11202 8429 49 FF SRIGHT: EOR #$FF ; COMPLEMENT +11203 842B A8 TAY +11204 842C 46 77 SLP2: LSR VALUE+HI ; SHIFT +11205 842E 66 76 ROR VALUE+LO +11206 8430 88 DEY +11207 8431 10 F9 BPL SLP2 +11208 8433 4C E1 43 JMP PUTVAL +11209 +11210 +11211 ; ---------------- +11212 ; ARITHMETIC SHIFT +11213 ; ---------------- +11214 ; PROPAGATING SIGN BIT ON RIGHT SHIFT +11215 +11216 8436 A5 65 ZASHFT: LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT +11217 8438 C9 80 CMP #$80 +11218 843A 90 D4 BCC ZSHIFT ; SAME AS LOGICAL SHIFT +11219 843C A6 63 LDX ARG1+LO ; SET UP FOR SHIFT +11220 843E 86 76 STX VALUE+LO +11221 8440 A6 64 LDX ARG1+HI +11222 8442 86 77 STX VALUE+HI +11223 +11224 8444 49 FF EOR #$FF ; COMPLEMENT COUNT +11225 8446 A8 TAY +11226 8447 A5 64 ASLP2: LDA ARG1+HI +11227 8449 0A ASL A ; GET SIGN BIT +11228 844A 66 77 ROR VALUE+HI ; SHIFT +11229 844C 66 76 ROR VALUE+LO +11230 844E 88 DEY +11231 844F 10 F6 BPL ASLP2 +11232 8451 4C E1 43 JMP PUTVAL +11233 8454 +11234 ; -------- +11235 ; XPUSH +11236 ; -------- +11237 8454 ZXPUSH: +11238 8454 A5 65 lda ARG2+LO ; get me the address of the LTABLE +11239 8456 85 8C sta FPCL ; for munging with +11240 8458 A5 66 lda ARG2+HI ; this is page +11241 845A 20 77 8F jsr SETPC ; get me actual page/bank +11242 845D 85 8D sta FPCH ; set page +11243 845F 84 8E sty FPCBNK ; and bank +11244 +11245 8461 20 56 92 jsr FETCHB ; this is hi part of counter +11246 8464 85 7B sta J+HI ; save it +11247 8466 20 BE 8F jsr NEXTFPC ; point to lo part +11248 8469 20 56 92 jsr FETCHB ; get it +11249 846C 85 7A sta J+LO ; thanx +11250 846E 05 7B ora J+HI ; check for zero elements left +11251 8470 D0 03 bne ZXP0 ; yes, there is room at the inn +11252 +11253 8472 4C 2F 44 jmp PREDF ; no room here! +11254 8475 ZXP0: +11255 8475 20 73 90 jsr FP2SP ; set up to stash back in beginning of LTABLE +11256 8478 A5 7B lda J+HI ; now the MSB +11257 847A 85 7D sta K+HI ; and saved it +11258 847C A5 7A lda J+LO ; save this +11259 847E 85 7C sta K+LO ; save it +11260 ; +11261 ; now count this one and stash it into the table +11262 ; +11263 8480 D0 02 bne ZXP1 ; nope, dec okay +11264 8482 C6 7B dec J+HI ; decrement MSB +11265 8484 ZXP1: +11266 8484 C6 7A dec J+LO ; and the LSB +11267 8486 A5 7A lda J+LO ; LSB first +11268 8488 20 35 92 jsr STASHB ; saved it +11269 848B 20 4E 90 jsr PREVSPC ; point to MSB +11270 848E A5 7B lda J+HI ; get it + Wed May 24 1989 15:00 Page 169 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11271 8490 20 35 92 jsr STASHB ; saved it +11272 ; +11273 ; finally, we can save the arg into the stack +11274 ; +11275 8493 06 7C asl K+LO ; make a word offset (*2) +11276 8495 26 7D rol K+HI ; pick up carry maybe +11277 8497 A5 7C lda K+LO ; add in arg offset +11278 8499 18 clc ; adding +11279 849A 65 65 adc ARG2+LO ; figger offset +11280 849C 85 8F sta SPCL ; this goes here for stashing +11281 849E A5 7D lda K+HI ; now page +11282 84A0 65 66 adc ARG2+HI ; add in start of table +11283 84A2 20 77 8F jsr SETPC ; get me memory page +11284 84A5 85 90 sta SPCH ; page +11285 84A7 84 91 sty SPCBNK ; and bank +11286 +11287 84A9 A5 64 lda ARG1+HI ; push MSB +11288 84AB 20 35 92 jsr STASHB ; saved +11289 84AE 20 9E 8F jsr NEXTSPC ; point to next one +11290 84B1 A5 63 lda ARG1+LO ; and now LSB +11291 84B3 20 35 92 jsr STASHB ; into the stack +11292 84B6 4C 3B 44 jmp PREDS ; show we worked good +11293 ;--------- +11294 ; ZFSTACK +11295 ;--------- +11296 84B9 ZFSTACK: +11297 84B9 C6 62 dec NARGS ; how many args there? +11298 84BB D0 0E bne ZFS1 ; flush ARG2 stack +11299 ; +11300 ; pop from system stack +11301 ; +11302 84BD A5 63 lda ARG1+LO ; just add number to system counter +11303 84BF 18 clc ; adding +11304 84C0 65 AF adc ZSP+LO ; added +11305 84C2 85 AF sta ZSP+LO ; and saved +11306 84C4 A5 64 lda ARG1+HI ; get hi part +11307 84C6 65 B0 adc ZSP+HI ; add in hi part +11308 84C8 85 B0 sta ZSP+HI ; save hi part +11309 84CA 60 rts +11310 84CB ZFS1: +11311 84CB A5 65 lda ARG2+LO ; get LTABLE we are interested in +11312 84CD 85 8C sta FPCL ; set up FPC first +11313 84CF A5 66 lda ARG2+HI ; and page +11314 84D1 20 77 8F jsr SETPC ; tell me where +11315 84D4 85 8D sta FPCH ; save me where +11316 84D6 84 8E sty FPCBNK ; FPC all set +11317 84D8 20 73 90 jsr FP2SP ; have SPC point to stack too +11318 +11319 84DB 20 56 92 jsr FETCHB ; get MSB of counter +11320 84DE 85 7B sta J+HI ; save MSB +11321 84E0 20 BE 8F jsr NEXTFPC ; point to LSB +11322 84E3 20 56 92 jsr FETCHB ; get LSB +11323 84E6 85 7A sta J+LO ; save LSB +11324 84E8 +11325 84E8 A5 7A lda J+LO ; get LSB back +11326 84EA 18 clc ; get ready for add +11327 84EB 65 63 adc ARG1+LO ; add how many to get rid off +11328 84ED 85 7A sta J+LO ; save new counter +11329 84EF A5 7B lda J+HI ; get MSB +11330 84F1 65 64 adc ARG1+HI ; add MSB +11331 +11332 84F3 20 35 92 jsr STASHB ; save Msb of new counter +11333 84F6 20 9E 8F jsr NEXTSPC ; point to LSB +11334 84F9 A5 7A lda J+LO ; get lsb +11335 84FB 20 35 92 jsr STASHB ; okay, reset the counter +11336 84FE 60 rts +11337 +11338 ; +11339 ; no mouse stuff yet +11340 ; +11341 84FF ZMINFO: +11342 84FF ZMLIMIT: +11343 84FF 60 rts +11344 8500 ZMENU: +11345 8500 4C 2F 44 jmp PREDF ; no menu stuff either + Wed May 24 1989 15:00 Page 170 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- X-OPS ---" + +11346 +11347 8503 END +11348 +11349 8503 INCLUDE READ.ASM +11350 8503 STTL "--- READ HANDLER ---" +11351 PAGE + Wed May 24 1989 15:00 Page 171 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11352 ; ---- +11353 ; READ +11354 ; ---- +11355 ; READ LINE INTO TABLE [ARG1] ; PARSE INTO TABLE [ARG2] (IF ARG2 IS THERE) +11356 +11357 8503 00 MAXWORDS DB 0 ; maximum number of words in table +11358 8504 00 WORDCNT DB 0 ; how many words read so far +11359 8505 00 WORDSTART DB 0 ; table offset of word +11360 8506 SAVESPC DS 3 ; SPC that points to Word Count +11361 +11362 8509 ZREAD: +11363 8509 A5 64 lda ARG1+HI ; MAKE THE TABLE ADDRESSES +11364 850B 8D 7B 6C sta RDTBL1+HI ; AND PLACE IT HERE TO USE +11365 850E A5 63 lda ARG1+LO +11366 8510 8D 7A 6C sta RDTBL1+LO ; LSBS NEED NOT CHANGE +11367 +11368 8513 A9 00 lda #0 ; TURN OFF FLAGS +11369 8515 8D 57 6C sta PSVFLG ; FOR ZLEX +11370 8518 8D 58 6C sta VOCFLG +11371 +11372 851B A6 62 ldx NARGS +11373 851D CA dex ; IF 2ND TBL ADDR 0 OR NOT THERE +11374 851E F0 14 beq ONLYRD ; JUST READ IN DON'T DO CONVERSION (X) +11375 8520 A2 00 ldx #0 ; JIC +11376 8522 A5 66 lda ARG2+HI +11377 8524 05 65 ora ARG2+LO +11378 8526 F0 0C beq ONLYRD +11379 +11380 8528 A5 66 lda ARG2+HI +11381 852A 8D 7D 6C sta RDTBL2+HI +11382 852D A5 65 lda ARG2+LO +11383 852F 8D 7C 6C sta RDTBL2+LO +11384 +11385 8532 A2 01 ldx #1 ; 1 = DO IT ALL (X) +11386 8534 ONLYRD: +11387 8534 8E 65 5B stx RDFLAG ; CHECK AGAIN AFTER READ IN WHAT TO DO +11388 8537 20 15 59 jsr INPUT ; READ LINE; RETURN LENGTH IN [RDTBL1],1 +11389 +11390 853A AD 65 5B lda RDFLAG ; FLAG (X) +11391 853D F0 03 beq RDEX ; IF INPUT ONLY, LEAVE NOW +11392 853F 20 4F 85 jsr DOREST +11393 8542 RDEX: +11394 8542 A9 F0 lda #$F0 ; RETURN NOW ONLY WANTED READ PART +11395 8544 8D 65 5B sta RDFLAG +11396 8547 AD 64 5B lda BRKCHR ; GET BREAK CHAR +11397 854A A2 00 ldx #0 +11398 854C 4C DD 43 jmp PUTBYT ; RETURN IT +11399 ; +11400 ; IF TIMEOUT, [A]=0 SO WILL QUIT W/NO RESULTS +11401 ; +11402 854F DOREST: +11403 854F AD 7D 6C lda RDTBL2+HI ; get max number of words +11404 8552 20 77 8F jsr SETPC ; tell me memory and bank +11405 8555 85 8D sta FPCH ; save page +11406 8557 84 8E sty FPCBNK ; and bank +11407 8559 AD 7C 6C lda RDTBL2+LO ; and for LSB +11408 855C 85 8C sta FPCL ; it is same +11409 855E 20 56 92 jsr FETCHB ; get max # of words in table +11410 8561 F0 04 beq RDERR ; (5/14/85 - FORCE # WORDS TO +11411 8563 C9 3B cmp #59 ; BE BETWEEN 1 AND 59) +11412 8565 90 02 bcc RD0 +11413 8567 RDERR: +11414 8567 A9 3A lda #58 ; (5/16/86 - MAKE IT 58, 59 LOST) +11415 8569 RD0: +11416 8569 8D 03 85 sta MAXWORDS ; save max words +11417 856C A9 00 lda #0 ; start at 0 words +11418 856E 8D 04 85 sta WORDCNT ; save it +11419 8571 85 94 sta WRDLEN ; INIT # CHARS IN WORD COUNTER +11420 8573 A9 02 lda #2 +11421 8575 85 93 sta SOURCE ; INIT SOURCE TABLE PNTR +11422 ; +11423 ; now futz with destination table a little +11424 ; +11425 8577 20 BE 8F jsr NEXTFPC ; now we point to # words read +11426 857A A5 8E lda FPCBNK ; and save this pointer + Wed May 24 1989 15:00 Page 172 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11427 857C 8D 06 85 sta SAVESPC ; for stashing at the end +11428 857F A5 8D lda FPCH +11429 8581 8D 07 85 sta SAVESPC+1 +11430 8584 A5 8C lda FPCL +11431 8586 8D 08 85 sta SAVESPC+2 +11432 +11433 8589 A9 04 lda #4 ; offset to end of first entry +11434 858B 20 DE 8F jsr ADDFPC ; and point to end of first entry +11435 858E 20 73 90 jsr FP2SP ; now put RDTBL2 into stash pointer +11436 ; +11437 ; now get source table +11438 ; +11439 8591 AD 7B 6C lda RDTBL1+HI ; get page +11440 8594 20 77 8F jsr SETPC ; and tell me what mem page and bank +11441 8597 85 8D sta FPCH ; set up fetch counter +11442 8599 84 8E sty FPCBNK ; and bank +11443 859B AD 7A 6C lda RDTBL1+LO ; and lo stays the same +11444 859E 85 8C sta FPCL ; and save it +11445 85A0 20 BE 8F jsr NEXTFPC ; get # of chars in buffer +11446 85A3 20 56 92 jsr FETCHB ; and tell me about it +11447 85A6 85 92 sta LINLEN ; SAVE # CHARS IN LINE +11448 85A8 20 BE 8F jsr NEXTFPC ; now point to first char in line +11449 ; +11450 ; MAIN LOOP STARTS HERE +11451 ; +11452 85AB READL: +11453 85AB AD 03 85 lda MAXWORDS ; how we doin'? +11454 85AE CD 04 85 cmp WORDCNT ; see if we have maxxed out +11455 85B1 90 06 bcc RLEX ; all done, thank you +11456 +11457 85B3 A5 92 lda LINLEN +11458 85B5 05 94 ora WRDLEN ; OUT OF CHARS AND WORDS? +11459 85B7 D0 16 bne RL2 ; NOT YET +11460 85B9 RLEX: +11461 85B9 AD 06 85 lda SAVESPC ; now set SPC to point to # words +11462 85BC 85 91 sta SPCBNK ; read byte, as saved at the beginning +11463 85BE AD 07 85 lda SAVESPC+1 +11464 85C1 85 90 sta SPCH +11465 85C3 AD 08 85 lda SAVESPC+2 +11466 85C6 85 8F sta SPCL +11467 85C8 AD 04 85 lda WORDCNT ; get word count +11468 85CB 20 35 92 jsr STASHB ; and save it +11469 85CE 60 rts +11470 85CF RL2: +11471 85CF A5 94 lda WRDLEN ; GET WORD LENGTH +11472 85D1 C9 09 cmp #9 ; 9 CHARS DONE? (EZIP) +11473 85D3 90 03 bcc RL3 ; NO, KEEP GOING +11474 85D5 20 06 87 jsr FLUSHW ; ELSE FLUSH REMAINDER OF WORD +11475 85D8 RL3: +11476 85D8 A5 94 lda WRDLEN ; GET WORD LENGTH AGAIN +11477 85DA D0 24 bne READL2 ; CONTINUE IF NOT FIRST CHAR +11478 ; +11479 ; START A NEW WORD +11480 ; +11481 85DC A2 08 ldx #8 ; CLEAR Z-WORD INPUT BUFFER +11482 85DE 9D 90 6C RLL: sta IN,X ; [A] = 0 +11483 85E1 CA dex +11484 85E2 10 FA bpl RLL +11485 +11486 85E4 A5 93 lda SOURCE ; STORE THE START POS OF THE WORD +11487 85E6 8D 05 85 sta WORDSTART ; and save it for later +11488 85E9 20 56 92 jsr FETCHB ; GET A CHAR FROM SOURCE BUFFER +11489 85EC 20 37 87 jsr SIB ; IS IT A SELF-INSERTING BREAK? +11490 85EF B0 2C bcs DOSIB ; YES IF CARRY WAS SET +11491 85F1 20 2B 87 jsr NORM ; IS IT A "NORMAL" BREAK? +11492 85F4 90 0A bcc READL2 ; NO, CONTINUE +11493 85F6 E6 93 inc SOURCE ; ELSE FLUSH THE STRANDED BREAK +11494 85F8 20 BE 8F jsr NEXTFPC ; and point to next char +11495 85FB C6 92 dec LINLEN ; UPDATE # CHARS LEFT IN LINE +11496 85FD 4C AB 85 jmp READL ; AND LOOP +11497 8600 READL2: +11498 8600 A5 92 lda LINLEN ; OUT OF CHARS YET? +11499 8602 F0 25 beq READL3 ; LOOKS THAT WAY +11500 8604 20 56 92 jsr FETCHB ; Grab the char +11501 8607 20 26 87 jsr BREAK ; IS IT A BREAK? + Wed May 24 1989 15:00 Page 173 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11502 860A B0 1D bcs READL3 ; YES IF CARRY WAS SET +11503 860C A6 94 ldx WRDLEN ; ELSE STORE THE CHAR +11504 860E 9D 90 6C sta IN,X ; INTO THE INPUT BUFFER +11505 8611 C6 92 dec LINLEN ; ONE LESS CHAR IN LINE +11506 8613 E6 94 inc WRDLEN ; ONE MORE IN WORD +11507 8615 E6 93 inc SOURCE ; and update next source +11508 8617 20 BE 8F jsr NEXTFPC ; POINT TO NEXT CHAR IN SOURCE +11509 861A 4C AB 85 jmp READL ; AND LOOP BACK +11510 ; +11511 ; handle self-inserting breaks +11512 861D DOSIB: +11513 861D 8D 90 6C sta IN ; put the break into 1st word slot +11514 8620 C6 92 dec LINLEN ; one less char in line +11515 8622 E6 94 inc WRDLEN ; one more in word buffer +11516 8624 E6 93 inc SOURCE ; and update next source +11517 8626 20 BE 8F jsr NEXTFPC ; point to next source char +11518 8629 READL3: +11519 8629 A5 94 lda WRDLEN ; ANY CHARS IN WORD YET? +11520 862B D0 03 bne READL31 ; yup, so deal with word +11521 862D 4C AB 85 jmp READL ; then go get next word +11522 8630 READL31: +11523 8630 20 12 94 jsr CONZST ; CONVERT ASCII IN [IN] TO Z-STRING +11524 8633 20 67 87 jsr FINDW ; AND LOOK IT UP IN VOCABULARY +11525 +11526 8636 AD 05 85 lda WORDSTART ; get where it starts +11527 8639 20 35 92 jsr STASHB ; and save it +11528 863C 20 4E 90 jsr PREVSPC ; step backwards to point to length +11529 863F A5 94 lda WRDLEN ; and get length +11530 8641 20 35 92 jsr STASHB ; and save it away +11531 8644 20 4E 90 jsr PREVSPC ; and backwards to LSB of offset +11532 8647 A2 06 ldx #6 ; offset to point to end of next entry +11533 +11534 8649 EE 04 85 inc WORDCNT ; increment # words read +11535 +11536 864C AD 57 6C lda PSVFLG ; IF SHOULD PRESERVE WHAT'S IN +11537 864F F0 06 beq READL4 +11538 8651 A5 77 lda VALUE+HI ; RDTBL2 AND NOT FOUND (VALUE = 0) +11539 8653 05 76 ora VALUE+LO +11540 8655 F0 0F beq READL5 ; JUST SKIP OVER +11541 8657 READL4: +11542 8657 A5 76 lda VALUE+LO ; GET LSB OF VOCAB ENTRY ADDRESS +11543 8659 20 35 92 jsr STASHB ; and stash it away +11544 865C 20 4E 90 jsr PREVSPC ; point to MSB part +11545 865F A5 77 lda VALUE+HI ; ALSO STORE MSB IN 2ND SLOT +11546 8661 20 35 92 jsr STASHB ; and send it out +11547 8664 A2 07 ldx #7 ; offset to point to end of next entry +11548 8666 READL5: +11549 8666 A9 00 lda #0 +11550 8668 85 94 sta WRDLEN ; CLEAR # CHARS IN WORD +11551 866A 8A txa ; get offset +11552 866B 20 01 90 jsr ADDSPC ; and point to end of next entry +11553 866E 4C AB 85 jmp READL ; AND LOOP BACK +11554 +11555 ; --- +11556 ; LEX +11557 ; --- +11558 ; DO PARSE OF TBL1 INTO TBL2 (2ND HALF OF READ) +11559 +11560 8671 ZLEX: +11561 8671 A5 64 LDA ARG1+HI ; MAKE THE TABLE ADDRESSES +11562 8673 8D 7B 6C STA RDTBL1+HI ; AND PLACE IT HERE TO USE +11563 8676 A5 63 LDA ARG1+LO +11564 8678 8D 7A 6C STA RDTBL1+LO ; LSBS NEED NOT CHANGE +11565 +11566 867B A5 66 LDA ARG2+HI +11567 867D 8D 7D 6C STA RDTBL2+HI +11568 8680 A5 65 LDA ARG2+LO +11569 8682 8D 7C 6C STA RDTBL2+LO +11570 +11571 8685 C6 62 DEC NARGS +11572 8687 C6 62 DEC NARGS +11573 8689 F0 13 BEQ NORMLEX ; USE NORMAL VOCAB TBL +11574 +11575 868B A9 01 LDA #1 ; USE ARG3 VOCAB TBL +11576 868D 8D 58 6C STA VOCFLG + Wed May 24 1989 15:00 Page 174 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11577 8690 A9 00 LDA #0 +11578 8692 C6 62 DEC NARGS +11579 8694 F0 02 BEQ NOSAVE ; ZERO UNFOUND WORDS +11580 8696 A9 01 LDA #1 ; PRESERVE UNFOUND WORD SLOT FLAG +11581 8698 8D 57 6C NOSAVE: STA PSVFLG +11582 869B 4C A6 86 JMP DOLEX +11583 +11584 869E A9 00 NORMLEX: LDA #0 +11585 86A0 8D 58 6C STA VOCFLG ; USE NORMAL VOCAB TBL +11586 86A3 8D 57 6C STA PSVFLG ; AND WILL BE NO PRESERVING +11587 +11588 86A6 4C 4F 85 DOLEX: JMP DOREST ; GO DO LEXICAL CONVERSION AND JUST RETURN +11589 +11590 +11591 ; ----- +11592 ; ZWSTR +11593 ; ----- +11594 ; CONVERT A WORD TO A ZWORD, PLACE IN ARG4 TBL +11595 86A9 ZWSTR: +11596 86A9 A5 64 lda ARG1+HI ; Make ARG1 be the FPC +11597 86AB 20 77 8F jsr SETPC ; so get absolute mem bank/page +11598 86AE 84 8E sty FPCBNK ; save bank and +11599 86B0 85 8D sta FPCH ; page +11600 86B2 A5 63 lda ARG1+LO +11601 86B4 85 8C sta FPCL ; LSBS NEED NOT CHANGE +11602 ; +11603 ; (IGNORE WORD LENGTH CAUSE CHECK FOR BREAK CHAR (9 CHAR MAX)) +11604 ; +11605 86B6 A5 67 lda ARG3+LO ; ADD OFFSET INTO INBUF +11606 86B8 20 DE 8F jsr ADDFPC ; add it to the FPC +11607 +11608 86BB A5 6A lda ARG4+HI ; now fix the SPC too +11609 86BD 20 77 8F jsr SETPC ; get me bank and page +11610 86C0 84 91 sty SPCBNK ; save bank +11611 86C2 85 90 sta SPCH ; save page +11612 86C4 A5 69 lda ARG4+LO +11613 86C6 85 8F sta SPCL ; LSB doesn't change +11614 ; +11615 ; START A NEW WORD +11616 ; +11617 86C8 A9 09 lda #9 +11618 86CA 85 92 sta LINLEN ; 1 WORD'S WORTH +11619 86CC A9 00 lda #0 +11620 86CE 85 94 sta WRDLEN +11621 +11622 86D0 A2 08 ldx #8 ; CLEAR Z-WORD INPUT BUFFER +11623 86D2 9D 90 6C WSTR1: sta IN,X ; [A] = 0 +11624 86D5 CA dex +11625 86D6 10 FA bpl WSTR1 +11626 ; +11627 ; THIS LOOP READS FROM INBUF TIL BREAK OR 9 CHARS READ +11628 ; +11629 86D8 WSTR2: +11630 86D8 20 56 92 jsr FETCHB ; grab the next char +11631 86DB 20 26 87 jsr BREAK ; IS IT A BREAK? +11632 86DE B0 0E bcs WSTR3 ; YES IF CARRY WAS SET +11633 86E0 A6 94 ldx WRDLEN ; ELSE STORE THE CHAR +11634 86E2 9D 90 6C sta IN,X ; INTO THE INPUT BUFFER +11635 86E5 E6 94 inc WRDLEN ; ONE MORE CHAR IN WORD +11636 86E7 C6 92 dec LINLEN ; ONE LESS IN LINE +11637 86E9 20 BE 8F jsr NEXTFPC ; point to next char +11638 86EC D0 EA bne WSTR2 ; AND LOOP BACK TIL DONE +11639 86EE WSTR3: +11640 86EE A5 94 lda WRDLEN ; ANY CHARS IN WORD YET? +11641 86F0 F0 13 beq WOOPS ; APPARENTLY NOT, OOPS +11642 86F2 20 12 94 jsr CONZST ; CONVERT ASCII IN [IN] TO Z-STRING +11643 +11644 86F5 A2 00 ldx #0 ; MOVE FROM [OUT] TO RDTBL2 +11645 86F7 BD 99 6C WSTR4: lda OUT,X +11646 86FA 20 35 92 jsr STASHB ; and stash it into ZWORD table +11647 86FD 20 9E 8F jsr NEXTSPC ; and point to next byte +11648 8700 E8 inx +11649 8701 E0 06 cpx #6 ; max 6 word table +11650 8703 D0 F2 bne WSTR4 ; not done yet +11651 8705 WOOPS: + Wed May 24 1989 15:00 Page 175 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11652 8705 60 rts +11653 +11654 ; ---------- +11655 ; FLUSH WORD +11656 ; ---------- +11657 +11658 8706 FLUSHW: +11659 8706 A5 92 lda LINLEN ; ANY CHARS LEFT IN LINE? +11660 8708 F0 14 beq FLEX ; NO, SCRAM +11661 870A 20 56 92 jsr FETCHB ; GRAB A CHAR +11662 870D 20 26 87 jsr BREAK ; IS IT A BREAK? +11663 8710 B0 0C bcs FLEX ; EXIT IF SO +11664 8712 C6 92 dec LINLEN ; ELSE UPDATE CHAR COUNT +11665 8714 E6 94 inc WRDLEN ; AND WORD-CHAR COUNT +11666 8716 E6 93 inc SOURCE ; AND CHAR POINTER +11667 8718 20 BE 8F jsr NEXTFPC ; and FPC pointer too +11668 871B 4C 06 87 jmp FLUSHW ; AND LOOP BACK (ALWAYS) +11669 871E FLEX: +11670 871E 60 rts +11671 +11672 +11673 ; --------------------------------- +11674 ; IS CHAR IN [A] ANY TYPE OF BREAK? +11675 ; --------------------------------- +11676 ; ------------------ +11677 ; NORMAL BREAK CHARS +11678 ; ------------------ +11679 +11680 871F 21 3F 2C 2E BRKTBL: DB '!?,.' ; IN ORDER OF +11681 8723 0D DB $0D ; ASCII ENDING FREQUENCY +11682 8724 20 DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED +11683 8725 00 DB 0 ; ZERO ADDED FOR ZWSTR (X) +11684 0007 NBRKS EQU $-BRKTBL ; # NORMAL BREAKS +11685 +11686 8726 20 37 87 BREAK: JSR SIB ; CHECK FOR A SIB FIRST +11687 8729 B0 3A BCS FBRK ; EXIT NOW IF MATCHED +11688 +11689 ; ELSE FALL THROUGH ... +11690 +11691 +11692 ; -------------------------------- +11693 ; IS CHAR IN [A] A "NORMAL" BREAK? +11694 ; -------------------------------- +11695 +11696 872B A2 06 NORM: LDX #NBRKS-1 ; NUMBER OF "NORMAL" BREAKS +11697 872D DD 1F 87 NBL: CMP BRKTBL,X ; MATCHED? +11698 8730 F0 33 BEQ FBRK ; YES, EXIT +11699 8732 CA DEX +11700 8733 10 F8 BPL NBL ; NO, KEEP LOOKING +11701 8735 18 CLC ; NO MATCH, CLEAR CARRY +11702 8736 60 RTS ; AND RETURN +11703 +11704 +11705 ; --------------------- +11706 ; IS CHAR IN [A] A SIB? +11707 ; --------------------- +11708 +11709 8737 85 AC SIB: STA IOCHAR ; SAVE TEST CHAR +11710 8739 A5 54 lda VOCAB+ABANK ; get bank +11711 873B 85 8B sta MPCBNK ; and save it +11712 873D A5 53 lda VOCAB+HI ; and hi part +11713 873F 85 8A sta MPCPNT+HI ; and save it +11714 8741 AD 08 96 lda ZBEGIN+ZVOCAB+0 ; GET 1ST BYTE IN VOCAB TABLE +11715 8744 AC 09 96 LDY ZBEGIN+ZVOCAB+1 +11716 8747 85 87 STA MPCM +11717 8749 84 86 STY MPCL +11718 874B A9 00 LDA #0 +11719 874D 85 88 STA MPCH ; now everything is set up +11720 874F 20 09 92 JSR GETBYT ; HAS # SIBS +11721 8752 85 7A STA J ; USE AS AN INDEX +11722 8754 20 09 92 SBL: JSR GETBYT ; GET NEXT SIB +11723 8757 C5 AC CMP IOCHAR ; MATCHED? +11724 8759 F0 08 BEQ FBRK0 ; YES, REPORT IT +11725 875B C6 7A DEC J +11726 875D D0 F5 BNE SBL ; ELSE KEEP LOOPING + Wed May 24 1989 15:00 Page 176 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11727 875F A5 AC LDA IOCHAR +11728 8761 18 CLC ; NO MATCH, SO +11729 8762 60 RTS ; EXIT WITH CARRY CLEAR +11730 8763 A5 AC FBRK0: LDA IOCHAR +11731 8765 38 FBRK: SEC ; EXIT WITH CARRY SET +11732 8766 60 RTS ; IF MATCHED WITH A BREAK CHAR +11733 +11734 +11735 ; ----------------- +11736 ; VOCABULARY SEARCH +11737 ; ----------------- +11738 ; ENTRY: 6-BYTE TARGET Z-WORD IN [OUT] +11739 ; EXIT: VIRTUAL ENTRY ADDRESS IN [VALUE] IF FOUND ; +11740 ; OTHERWISE [VALUE] = 0 +11741 +11742 0078 VWLEN EQU I ; ********** +11743 007B VWCUR EQU J+HI +11744 +11745 8767 FINDW: +11746 8767 AD 58 6C lda VOCFLG ; USE WHAT VOCAB TBL? +11747 876A F0 07 beq FWL2 ; NORMAL +11748 876C A5 68 lda ARG3+HI ; IF ALTERNATE VOCTBL +11749 876E A4 67 ldy ARG3+LO ; IT'S ADDR IS IN ARG3 +11750 8770 4C 9A 87 jmp FWL3 +11751 8773 FWL2: +11752 8773 AD 8F 6C lda DIDVTBL ; have we done default vocab table? +11753 8776 F0 17 beq FWLNEW ; nope, so do it the first time +11754 8778 A2 02 ldx #2 ; restore pointers +11755 877A FWRSTL: +11756 877A BD 86 6C lda VOCMPC,X ; get it +11757 877D 95 86 sta MPC,X ; save it +11758 877F BD 89 6C lda VCESVE,X ; save VOCEND too +11759 8782 95 B3 sta VOCEND,X ; okay, we have +11760 8784 BD 8C 6C lda VWLSVE,X ; and starting length +11761 8787 95 78 sta VWLEN,X ; we have +11762 8789 CA dex ; count +11763 878A 10 EE bpl FWRSTL ; okay, next one +11764 878C 4C 70 88 jmp FWLOOP ; and go do it +11765 878F FWLNEW: +11766 878F A9 FF lda #$FF ; show we are doing default table +11767 8791 8D 8F 6C sta DIDVTBL ; we shall +11768 +11769 8794 AD 08 96 lda ZBEGIN+ZVOCAB ; GET VIRTUAL ADDR OF VOCAB TBL +11770 8797 AC 09 96 ldy ZBEGIN+ZVOCAB+1 +11771 879A FWL3: +11772 879A 85 87 STA MPCM +11773 879C 84 86 STY MPCL +11774 879E A9 00 LDA #0 +11775 87A0 85 88 STA MPCH +11776 87A2 20 80 90 JSR VLDMPC ; SET TO NEW PAGE +11777 87A5 20 09 92 JSR GETBYT ; GET # SIBS +11778 87A8 18 CLC +11779 87A9 65 86 ADC MPCL ; GET ACTUAL BASE ADDR OF VOCAB ENTRIES +11780 87AB 85 86 STA MPCL +11781 87AD 90 02 BCC FWL0 +11782 87AF E6 87 INC MPCM +11783 87B1 20 80 90 FWL0: JSR VLDMPC ; SET TO NEW PAGE +11784 87B4 20 09 92 JSR GETBYT ; GET # BYTES PER ENTRY (AND MOVE TO NEXT BYTE) +11785 87B7 85 95 STA ESIZE ; SAVE IT HERE +11786 87B9 85 78 STA VWLEN+0 ; AND HERE +11787 87BB A9 00 LDA #0 ; CLEAR REST OF COUNTER +11788 87BD 85 79 STA VWLEN+1 +11789 87BF 85 7A STA VWLEN+2 +11790 +11791 87C1 20 09 92 JSR GETBYT ; GET # OF ENTRIES IN TBL (MSB) +11792 87C4 8D 7F 6C STA NENTS+HI ; AND STUFF IT IN [NENTS] +11793 87C7 20 09 92 JSR GETBYT ; DON'T FORGET THE LSB! +11794 87CA 8D 7E 6C STA NENTS+LO +11795 87CD AD 7F 6C LDA NENTS+HI +11796 87D0 10 03 BPL SORTED +11797 87D2 4C 29 89 JMP UNSORTED ; VOCAB LIST IS UNSORTED, HANDLE DIFFERENTLY +11798 87D5 SORTED: +11799 87D5 A9 00 LDA #0 ; FIND SIZE OF VAOCAB TBL +11800 87D7 85 B3 STA VOCEND ; TO LOCATE THE END OF IT +11801 87D9 85 B4 STA VOCEND+1 + Wed May 24 1989 15:00 Page 177 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11802 87DB 85 B5 STA VOCEND+2 +11803 87DD A6 95 LDX ESIZE +11804 87DF FWL1: +11805 87DF 18 CLC +11806 87E0 A5 B3 LDA VOCEND ; (# OF ENTRIES) * (ENTRY SIZE) +11807 87E2 6D 7E 6C ADC NENTS+LO +11808 87E5 85 B3 STA VOCEND +11809 87E7 A5 B4 LDA VOCEND+1 +11810 87E9 6D 7F 6C ADC NENTS+HI +11811 87EC 85 B4 STA VOCEND+1 +11812 87EE 90 02 bcc FWL11 +11813 87F0 E6 B5 inc VOCEND+2 +11814 87F2 FWL11: +11815 87F2 CA DEX +11816 87F3 D0 EA BNE FWL1 +11817 +11818 87F5 18 CLC +11819 87F6 A5 B3 LDA VOCEND ; AND ADD LENGTH TO START OF TBL +11820 87F8 65 86 ADC MPCL ; TO GET END OF TBL +11821 87FA 85 B3 STA VOCEND +11822 87FC A5 B4 LDA VOCEND+1 +11823 87FE 65 87 ADC MPCM +11824 8800 85 B4 STA VOCEND+1 +11825 8802 A5 B5 LDA VOCEND+2 +11826 8804 65 88 ADC MPCH +11827 8806 85 B5 STA VOCEND+2 ; TO SAVE FOR TESTING IF PAST END +11828 +11829 8808 A5 B3 LDA VOCEND ; SUBTRACT [ESIZE] SO THAT +11830 880A 38 SEC ; [VOCEND] POINTS TO REAL LAST ENTRY +11831 880B E5 95 SBC ESIZE +11832 880D 85 B3 STA VOCEND +11833 880F A5 B4 LDA VOCEND+1 +11834 8811 E9 00 SBC #0 +11835 8813 85 B4 STA VOCEND+1 +11836 ; +11837 ; BEGIN THE SEARCH! [MPC] NOW POINTS TO 1ST ENTRY +11838 ; +11839 8815 4E 7F 6C LSR NENTS+HI ; 2 ALIGN # OF ENTRIES +11840 8818 6E 7E 6C ROR NENTS+LO ; 2 point to middle of table +11841 881B 06 78 FWCALC: ASL VWLEN+0 ; CALCULATE INITIAL OFFSET FOR SEARCH +11842 881D 26 79 ROL VWLEN+1 +11843 881F 26 7A ROL VWLEN+2 +11844 8821 4E 7F 6C LSR NENTS+HI +11845 8824 6E 7E 6C ROR NENTS+LO +11846 8827 D0 F2 BNE FWCALC +11847 +11848 8829 18 CLC ; ADD 1ST OFFSET INTO START OF VOCABULARL +11849 882A A5 86 LDA MPCL ; WHICH IS CURRENTLY IN MPC +11850 882C 65 78 ADC VWLEN+0 +11851 882E 85 86 STA MPCL +11852 8830 A5 87 LDA MPCM +11853 8832 65 79 ADC VWLEN+1 +11854 8834 85 87 STA MPCM +11855 8836 A5 88 LDA MPCH +11856 8838 65 7A ADC VWLEN+2 +11857 883A 85 88 STA MPCH +11858 +11859 883C 38 SEC ; AVOID FENCE-POST BUG FOR +11860 883D A5 86 LDA MPCL ; EXACT-POWER-OF-2 TBL (DUNCAN) +11861 883F E5 95 SBC ESIZE +11862 8841 85 86 STA MPCL +11863 8843 B0 0F BCS FWSAVE +11864 8845 A5 87 LDA MPCM +11865 8847 38 SEC +11866 8848 E9 01 SBC #1 +11867 884A 85 87 STA MPCM +11868 884C B0 06 BCS FWSAVE +11869 884E A5 88 LDA MPCH +11870 8850 E9 00 SBC #0 +11871 8852 85 88 STA MPCH +11872 8854 FWSAVE: +11873 8854 AD 8F 6C lda DIDVTBL ; are we installing default table? +11874 8857 10 17 bpl FWLOOP ; already have? +11875 8859 A2 02 ldx #2 ; save MPC +11876 885B 8E 8F 6C stx DIDVTBL ; show we have saved it + Wed May 24 1989 15:00 Page 178 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11877 885E FWSVL: +11878 885E B5 86 lda MPC,X ; get it +11879 8860 9D 86 6C sta VOCMPC,X ; save it +11880 8863 B5 B3 lda VOCEND,X ; save VOCEND too +11881 8865 9D 89 6C sta VCESVE,X ; okay, we have +11882 8868 B5 78 lda VWLEN,X ; and starting length +11883 886A 9D 8C 6C sta VWLSVE,X ; we have +11884 886D CA dex ; count +11885 886E 10 EE bpl FWSVL ; okay, next one +11886 8870 FWLOOP: +11887 8870 46 7A lsr VWLEN+2 ; SET FOR NEXT OFFSET, +11888 8872 66 79 ror VWLEN+1 ; WHICH IS HALF THIS ONE +11889 8874 66 78 ror VWLEN+0 +11890 +11891 8876 A5 86 lda MPCL ; HOLD START ADDR, MPC WILL BE A MESS +11892 8878 85 7B sta VWCUR+0 +11893 887A A5 87 lda MPCM +11894 887C 85 7C sta VWCUR+1 +11895 887E A5 88 lda MPCH +11896 8880 85 7D sta VWCUR+2 +11897 +11898 8882 20 80 90 jsr VLDMPC ; SET TO NEW PAGE +11899 8885 20 09 92 jsr GETBYT ; GET 1ST BYTE OF ENTRY +11900 8888 CD 99 6C cmp OUT ; MATCH 1ST BYTE OF TARGET? +11901 888B 90 34 bcc WNEXT ; LESS +11902 888D D0 66 bne FWPREV ; GREATER +11903 888F 20 09 92 jsr GETBYT +11904 8892 CD 9A 6C cmp OUT+1 ; 2ND BYTE MATCHED? +11905 8895 90 2A bcc WNEXT +11906 8897 D0 5C bne FWPREV ; NOPE +11907 8899 20 09 92 jsr GETBYT +11908 889C CD 9B 6C cmp OUT+2 ; 3RD BYTE? +11909 889F 90 20 bcc WNEXT +11910 88A1 D0 52 bne FWPREV ; SORRY ... +11911 88A3 20 09 92 jsr GETBYT +11912 88A6 CD 9C 6C cmp OUT+3 ; 4TH BYTE +11913 88A9 90 16 bcc WNEXT +11914 88AB D0 48 BNE FWPREV +11915 88AD 20 09 92 JSR GETBYT +11916 88B0 CD 9D 6C CMP OUT+4 ; 5TH BYTE? +11917 88B3 90 0C BCC WNEXT +11918 88B5 D0 3E BNE FWPREV ; SORRY ... +11919 88B7 20 09 92 JSR GETBYT +11920 88BA CD 9E 6C CMP OUT+5 ; LAST BYTE? +11921 88BD F0 5A BEQ FWSUCC ; FOUND IT! +11922 88BF B0 34 BCS FWPREV ; ELSE BACK UP ... +11923 88C1 WNEXT: +11924 88C1 A5 7B LDA VWCUR+0 ; TO MOVE UP, JUST ADD +11925 88C3 18 CLC ; OFFSET FROM START OF THIS +11926 88C4 65 78 ADC VWLEN+0 ; ENTRY +11927 88C6 85 86 STA MPCL +11928 88C8 A5 7C LDA VWCUR+1 +11929 88CA 65 79 ADC VWLEN+1 +11930 88CC B0 18 BCS WNXT2 ; SAVES CODE (?) +11931 +11932 88CE 85 87 STA MPCM +11933 88D0 A9 00 LDA #0 +11934 88D2 85 88 STA MPCH +11935 88D4 WNXT0: +11936 88D4 A5 87 LDA MPCM ; GONE PAST END? +11937 88D6 C5 B4 CMP VOCEND+1 +11938 88D8 F0 04 BEQ WNXT1 ; MAYBE +11939 88DA B0 0A BCS WNXT2 ; YES +11940 88DC 90 2A BCC FWMORE ; NO +11941 88DE WNXT1: +11942 88DE A5 86 LDA MPCL +11943 88E0 C5 B3 CMP VOCEND +11944 88E2 90 24 BCC FWMORE ; NO +11945 88E4 F0 22 BEQ FWMORE ; NO, EQUAL +11946 88E6 WNXT2: +11947 88E6 A5 B3 LDA VOCEND ; YES, SO POINT TO END OF TBL +11948 88E8 85 86 STA MPCL +11949 88EA A5 B4 LDA VOCEND+1 +11950 88EC 85 87 STA MPCM +11951 88EE A5 B5 LDA VOCEND+2 + Wed May 24 1989 15:00 Page 179 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +11952 88F0 85 88 STA MPCH +11953 88F2 4C 08 89 JMP FWMORE +11954 88F5 FWPREV: +11955 88F5 A5 7B LDA VWCUR+0 ; TO MOVE DOWN, JUST SUBTRACT +11956 88F7 38 SEC ; OFFSET FROM START OF THIS +11957 88F8 E5 78 SBC VWLEN+0 ; ENTRY +11958 88FA 85 86 STA MPCL +11959 88FC A5 7C LDA VWCUR+1 +11960 88FE E5 79 SBC VWLEN+1 +11961 8900 85 87 STA MPCM +11962 8902 A5 7D LDA VWCUR+2 +11963 8904 E5 7A SBC VWLEN+2 +11964 8906 85 88 STA MPCH +11965 8908 FWMORE: +11966 8908 A5 7A LDA VWLEN+2 ; IF OFFSET >GE< 1 WORD, CONTINUE +11967 890A D0 0A BNE FWM1 +11968 890C A5 79 LDA VWLEN+1 +11969 890E D0 06 BNE FWM1 +11970 8910 A5 78 LDA VWLEN+0 +11971 8912 C5 95 CMP ESIZE +11972 8914 90 0C BCC FWFAIL +11973 8916 FWM1: +11974 8916 4C 70 88 JMP FWLOOP ; AND TRY AGAIN +11975 +11976 8919 A5 7B FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD +11977 891B 85 76 STA VALUE+LO +11978 891D A5 7C LDA VWCUR+1 +11979 891F 85 77 STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY +11980 8921 60 RTS ; WORD VALUE RETURNABLE +11981 8922 FWFAIL: +11982 8922 A9 00 LDA #0 ; NOT FOUND +11983 8924 85 76 STA VALUE+LO +11984 8926 85 77 STA VALUE+HI +11985 8928 60 RTS ; THEN RETURN WITH [VALUE] = 0 +11986 ; +11987 ; DO UNSORTED SEARCH ON VOCAB TBL IN MPC +11988 ; +11989 8929 UNSORTED: +11990 8929 A9 FF LDA #$FF ; 2'S COMPLEMENT LENGTH +11991 892B 4D 7F 6C EOR NENTS+HI ; TO GET REAL LENGTH +11992 892E 8D 7F 6C STA NENTS+HI ; WAS NEGATIVE TO SIGNIFY +11993 8931 A9 FF LDA #$FF ; UNSORTED VOCAB TBL +11994 8933 4D 7E 6C EOR NENTS+LO +11995 8936 8D 7E 6C STA NENTS+LO +11996 8939 EE 7E 6C INC NENTS+LO ; 2'S CMPL +11997 893C D0 03 BNE UNSRT0 +11998 893E EE 7F 6C INC NENTS+HI +11999 8941 UNSRT0: +12000 8941 A5 86 LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS +12001 8943 85 7B STA VWCUR+0 +12002 8945 A5 87 LDA MPCM +12003 8947 85 7C STA VWCUR+1 +12004 8949 A5 88 LDA MPCH +12005 894B 85 7D STA VWCUR+2 +12006 +12007 894D 20 09 92 JSR GETBYT ; GET 1ST BYTE OF ENTRY +12008 8950 CD 99 6C CMP OUT ; MATCH 1ST BYTE OF TARGET? +12009 8953 D0 28 BNE FNEXT ; LESS +12010 8955 20 09 92 JSR GETBYT +12011 8958 CD 9A 6C CMP OUT+1 ; 2ND BYTE MATCHED? +12012 895B D0 20 BNE FNEXT +12013 895D 20 09 92 JSR GETBYT +12014 8960 CD 9B 6C CMP OUT+2 ; 3RD BYTE? +12015 8963 D0 18 BNE FNEXT +12016 8965 20 09 92 JSR GETBYT +12017 8968 CD 9C 6C CMP OUT+3 ; 4TH BYTE +12018 896B D0 10 BNE FNEXT +12019 896D 20 09 92 JSR GETBYT +12020 8970 CD 9D 6C CMP OUT+4 ; 5TH BYTE? +12021 8973 D0 08 BNE FNEXT +12022 8975 20 09 92 JSR GETBYT +12023 8978 CD 9E 6C CMP OUT+5 ; LAST BYTE? +12024 897B F0 9C BEQ FWSUCC ; FOUND IT! +12025 +12026 897D A5 7B FNEXT: LDA VWCUR+LO ; TO MOVE UP, JUST ADD + Wed May 24 1989 15:00 Page 180 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- READ HANDLER ---" + +12027 897F 18 CLC ; OFFSET FROM START OF THIS +12028 8980 65 95 ADC ESIZE ; ENTRY +12029 8982 85 86 STA MPCL +12030 8984 90 0D BCC FNEXT0 +12031 +12032 8986 A5 7C LDA VWCUR+HI ; PICK UP CARRY +12033 8988 69 00 ADC #0 +12034 898A 85 87 STA MPCM +12035 898C A9 00 LDA #0 +12036 898E 85 88 STA MPCH +12037 8990 20 80 90 JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE +12038 +12039 8993 CE 7E 6C FNEXT0: DEC NENTS+LO ; CHECKED ALL ENTRIES? +12040 8996 D0 A9 BNE UNSRT0 +12041 8998 AD 7F 6C LDA NENTS+HI +12042 899B F0 85 BEQ FWFAIL ; GO INDICATE NO FIND +12043 899D CE 7F 6C DEC NENTS+HI ; OR DO NEXT 256 ENTRIES +12044 89A0 4C 41 89 JMP UNSRT0 +12045 +12046 89A3 END +12047 +12048 89A3 INCLUDE ZSAVRES.ASM +12049 +12050 89A3 STTL "--- ZIP SAVE AND RESTORE ROUTINES ---" +12051 PAGE + Wed May 24 1989 15:00 Page 181 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12052 ; ----------------------------- +12053 ; SET UP SAVE & RESTORE SCREENS +12054 ; ----------------------------- +12055 89A3 SAVRES: +12056 89A3 20 DF 54 jsr ZCRLF ; CLEAR THE LINE BUFFER +12057 89A6 A9 00 lda #0 +12058 89A8 85 AA sta SCRIPT ; DISABLE SCRIPTING +12059 89AA AD 54 C0 lda PAGE2SW+MAIN ; just do this for the heck of it +12060 89AD AD 83 C0 lda BNK2SET ; this stuff too +12061 89B0 AD 83 C0 lda BNK2SET +12062 +12063 89B3 60 rts +12064 +12065 ; ----------------------------- +12066 ; SAVE & RESTORE STRINGS +12067 ; ----------------------------- +12068 89B4 59 45 53 YES: DB "YES" +12069 89B7 0D DB EOL +12070 0004 YESL EQU $-YES +12071 89B8 4E 4F NO: DB "NO" +12072 89BA 0D DB EOL +12073 0003 NOL EQU $-NO +12074 +12075 89BB 0D NAMEQ: db EOL +12076 89BC 49 6E 73 65 72 db "Insert save disk and enter " + 89C1 74 20 73 61 76 + 89C6 65 20 64 69 73 + 89CB 6B 20 61 6E 64 + 89D0 20 65 6E 74 65 + 89D5 72 20 +12077 89D7 66 75 6C 6C 20 db "full pathname of save file: " + 89DC 70 61 74 68 6E + 89E1 61 6D 65 20 6F + 89E6 66 20 73 61 76 + 89EB 65 20 66 69 6C + 89F0 65 3A 20 +12078 89F3 0D db EOL +12079 89F4 48 69 74 20 27 db "Hit '?' key to get a list of online volumes." + 89F9 3F 27 20 6B 65 + 89FE 79 20 74 6F 20 + 8A03 67 65 74 20 61 + 8A08 20 6C 69 73 74 + 8A0D 20 6F 66 20 6F + 8A12 6E 6C 69 6E 65 + 8A17 20 76 6F 6C 75 + 8A1C 6D 65 73 2E +12080 8A20 0D db EOL +12081 8A21 43 75 72 72 65 db "Current pathname is:", + 8A26 6E 74 20 70 61 + 8A2B 74 68 6E 61 6D + 8A30 65 20 69 73 3A + 8A35 00 +12082 8A36 0D db EOL +12083 007C NAMEQL EQU $-NAMEQ +12084 SNDATA: ; show start of name and length +12085 8A37 00 SNAMEL: db 0 ; place to save length of name +12086 8A38 SAVENAME: ds 64+15 ; save plenty of room for max name +12087 +12088 8A87 0D 46 69 6C 65 DELQ: db EOL,"File exists, delete it (Yes/No)? " + 8A8C 20 65 78 69 73 + 8A91 74 73 2C 20 64 + 8A96 65 6C 65 74 65 + 8A9B 20 69 74 20 28 + 8AA0 59 65 73 2F 4E + 8AA5 6F 29 3F 20 +12089 0023 DELQL EQU $-DELQ+1 ; include this following EOL +12090 8AA9 0D 50 6C 65 61 RETQ: db EOL,"Please hit [RETURN]",EOL + 8AAE 73 65 20 68 69 + 8AB3 74 20 5B 52 45 + 8AB8 54 55 52 4E 5D + 8ABD 0D +12091 0015 RETQL EQU $-RETQ +12092 8ABE 0D 4E 61 6D 65 PREFIX_ERR: db EOL,"Name must have prefix, " + 8AC3 20 6D 75 73 74 + 8AC8 20 68 61 76 65 + Wed May 24 1989 15:00 Page 182 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + + 8ACD 20 70 72 65 66 + 8AD2 69 78 2C 20 +12093 8AD6 69 2E 65 2E 3A db "i.e.: /DISKNAME/FILENAME",EOL + 8ADB 20 2F 44 49 53 + 8AE0 4B 4E 41 4D 45 + 8AE5 2F 46 49 4C 45 + 8AEA 4E 41 4D 45 0D +12094 0031 PREFIX_ERRL EQU $-PREFIX_ERR +12095 ; ----------------------------- +12096 ; SAVE/RESTORE Parameter Blocks +12097 ; ----------------------------- +12098 8AEF CREATE_PB: +12099 8AEF 07 db 7 ; 7 parameters +12100 8AF0 378A dw SNDATA ; pointer to name +12101 8AF2 C3 db $C3 ; full access to file +12102 8AF3 06 db $06 ; BIN file type +12103 8AF4 0000 dw 0 ; no aux data +12104 8AF6 01 db $01 ; standard file +12105 8AF7 0000 dw 0 ; create date +12106 8AF9 0000 dw 0 +12107 ; creation time +12108 8AFB SETEOF_PB: +12109 8AFB 02 db 2 ; 1 parameter +12110 8AFC 00 db 0 ; refnum +12111 8AFD 00 00 00 db 0,0,0 ; set to zero spot to clear it out +12112 8B00 OPEN_SV: +12113 8B00 03 db 3 ; 3 parameters +12114 8B01 378A dw SNDATA ; name +12115 8B03 0011 dw GAME1FIO ; file buffer +12116 8B05 00 db 0 ; ref num +12117 8B06 CLOSE_PB: +12118 8B06 01 db 1 ; only one parm +12119 8B07 00 db 0 ; the refnum +12120 8B08 WRITE_SV: +12121 8B08 04 db 4 ; parm count +12122 8B09 00 db 0 ; refnum +12123 8B0A 0008 dw IOBUFF ; data is always here +12124 8B0C 0002 dw 512 ; 1 page worth +12125 8B0E 0000 dw 0 ; how many actually went +12126 +12127 ; get the save file name. If user hits the ESC key, then abort the +12128 ; save by return with the carry set. +12129 ; +12130 8B10 GET_SNAME: +12131 8B10 20 8F 8C jsr CLOSE_GAME ; close the game files +12132 8B13 20 A9 4C jsr SWAP2INFOW ; goto information window +12133 8B16 GTSN0: +12134 8B16 DLINE NAMEQ ; ask about name +12135 8B16 A2 BB ldx #NAMEQ ; get other part of string +12137 [01] IFMA 2 ; check to see if length passed in +12138 ldy ; then just fetch it +12139 [01] ELSE +12140 8B1A A0 7C ldy #NAMEQL ; get length of string +12141 [00] ENDIF +12142 8B1C 20 6B 4C jsr DLINE ; print the string +12143 8B1F .MACEND +12144 8B1F AD 37 8A lda SNAMEL ; is there a name yet? +12145 8B22 F0 0A beq GTSN00 ; nope +12146 8B24 DLINE SAVENAME,SNAMEL ; show current name of file +12147 8B24 A2 38 ldx #SAVENAME ; get other part of string +12149 [01] IFMA 2 ; check to see if length passed in +12150 8B28 AC 37 8A ldy SNAMEL ; then just fetch it +12151 [01] ELSE +12152 ldy #SAVENAMEL ; get length of string +12153 [00] ENDIF +12154 8B2B 20 6B 4C jsr DLINE ; print the string +12155 8B2E .MACEND +12156 8B2E GTSN00: +12157 8B2E A9 00 lda #0 ; clear line count +12158 8B30 8D 07 8B sta CLOSE_PB+CL_REFNUM ; clear this too +12159 8B33 AE 37 8A ldx SNAMEL ; get length +12160 8B36 86 A9 stx CHRCNT ; okay +12161 8B38 AC 37 8A ldy SNAMEL ; point to copy + Wed May 24 1989 15:00 Page 183 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12162 8B3B 88 dey ; one less +12163 8B3C GCOPY: +12164 8B3C BD 37 8A lda SNAMEL,X ; get char +12165 8B3F 99 00 02 sta LBUFF,Y ; save it +12166 8B42 CA dex ; point to previous one +12167 8B43 88 dey ; previous pointer +12168 8B44 10 F6 bpl GCOPY ; copy until length byte +12169 8B46 GNAME: +12170 8B46 20 31 51 jsr GETKEY ; WAIT FOR A KEY +12171 8B49 C9 0D cmp #EOL ; IF [RETURN], +12172 8B4B F0 5F beq GOTNAME ; got the name +12173 8B4D C9 1B cmp #ESCAPE ; hit escape key? +12174 8B4F 38 sec ; just in case it does exit +12175 8B50 D0 03 bne GNM2 +12176 8B52 4C F0 8B jmp GNX ; all done then +12177 8B55 GNM2: +12178 8B55 C9 08 cmp #BACKSPACE ; erasing things? +12179 8B57 D0 15 bne GNM1 ; nope +12180 +12181 8B59 A6 A9 ldx CHRCNT ; make sure there are chars there +12182 8B5B D0 06 bne GNMBP ; ayyup, do delete +12183 8B5D GNMBAD: +12184 8B5D 20 C3 4E jsr BEEP ; no room for delete +12185 8B60 4C 46 8B jmp GNAME ; okay +12186 8B63 GNMBP: +12187 8B63 CA dex ; point down one +12188 8B64 86 A9 stx CHRCNT ; count one down +12189 8B66 BD 00 02 lda LBUFF,X ; get char to delete +12190 8B69 AA tax ; show in [X] +12191 8B6A A9 08 lda #BACKSPACE ; and doing a backspace +12192 8B6C D0 35 bne GNMSHOW ; okay, delete char on screen +12193 8B6E GNM1: +12194 8B6E C9 2F cmp #'/' ; slash is the only good non-numeric char +12195 8B70 F0 2A beq GNMGOOD ; fine, use it +12196 8B72 C9 2E cmp #'.' ; well, maybe a . too +12197 8B74 F0 26 beq GNMGOOD ; fine, here it is +12198 8B76 C9 3F cmp #VOLCHAR ; does user want list of volumes? +12199 8B78 D0 0A bne GNM1x ; nope +12200 +12201 8B7A A9 00 lda #0 ; clear out current name +12202 8B7C 85 A9 sta CHRCNT ; okay, we did +12203 8B7E 20 5D 4B jsr LISTVOLS ; show them +12204 8B81 4C 16 8B jmp GTSN0 ; start over, kind of +12205 8B84 GNM1x: +12206 8B84 C9 30 cmp #'0' ; is it a number +12207 8B86 90 D5 bcc GNMBAD ; nope +12208 8B88 C9 3A cmp #'9'+1 ; well? +12209 8B8A 90 10 bcc GNMGOOD ; yup +12210 8B8C C9 7B cmp #'z'+1 ; make sure it is alpha numeric +12211 8B8E B0 CD bcs GNMBAD ; nope +12212 8B90 C9 41 cmp #'A' ; well? +12213 8B92 90 C9 bcc GNMBAD ; nope +12214 8B94 C9 61 cmp #'a' ; little char? +12215 8B96 B0 04 bcs GNMGOOD ; yup +12216 8B98 C9 5B cmp #'Z'+1 ; big char +12217 8B9A B0 C1 bcs GNMBAD ; nope +12218 8B9C GNMGOOD: +12219 8B9C A6 A9 ldx CHRCNT ; get name index +12220 8B9E E6 A9 inc CHRCNT ; point to next char +12221 8BA0 9D 00 02 sta LBUFF,X ; save name char +12222 8BA3 GNMSHOW: +12223 8BA3 20 7D 5D jsr CHAR ; show character +12224 8BA6 20 EC 71 jsr DISP_LINE ; make sure it is there +12225 8BA9 4C 46 8B jmp GNAME ; go get next char +12226 ; +12227 ; got the name, so copy it to the SAVENAME buffer +12228 ; +12229 8BAC GOTNAME: +12230 8BAC A5 A9 lda CHRCNT ; did we get any? +12231 8BAE F0 07 beq GTNMERR ; nope +12232 8BB0 AD 00 02 lda LBUFF ; make sure first name is a directory +12233 8BB3 C9 2F cmp #'/' ; is it? +12234 8BB5 F0 10 beq GTNM1 ; yup, probly okay then +12235 8BB7 GTNMERR: +12236 8BB7 A9 00 lda #0 ; clear CHRCNT so name doesn't get + Wed May 24 1989 15:00 Page 184 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12237 8BB9 85 A9 sta CHRCNT ; output again +12238 8BBB DLINE PREFIX_ERR ; complain and die +12239 8BBB A2 BE ldx #PREFIX_ERR ; get other part of string +12241 [01] IFMA 2 ; check to see if length passed in +12242 ldy ; then just fetch it +12243 [01] ELSE +12244 8BBF A0 31 ldy #PREFIX_ERRL ; get length of string +12245 [00] ENDIF +12246 8BC1 20 6B 4C jsr DLINE ; print the string +12247 8BC4 .MACEND +12248 8BC4 38 sec ; show bad name +12249 8BC5 B0 29 bcs GNX ; all done +12250 8BC7 GTNM1: +12251 8BC7 A2 00 ldx #0 ; now check to make sure there are 2 +12252 8BC9 A0 FE ldy #$FE ; use this as counter +12253 8BCB GTNMCHK: +12254 8BCB BD 00 02 lda LBUFF,X ; get char +12255 8BCE E8 inx ; next char +12256 8BCF C9 2F cmp #'/' ; prefix deliminator? +12257 8BD1 D0 03 bne GTNMCHK1 ; nope +12258 8BD3 C8 iny ; count this one +12259 8BD4 F0 06 beq GTNM2 ; we have 2 of them +12260 8BD6 GTNMCHK1: +12261 8BD6 E4 A9 cpx CHRCNT ; at end? +12262 8BD8 F0 DD beq GTNMERR ; yes, and no 2 '/'s +12263 8BDA D0 EF bne GTNMCHK ; go check next char +12264 8BDC GTNM2: +12265 8BDC E4 A9 cpx CHRCNT ; make sure there are chars after prefix +12266 8BDE F0 D7 beq GTNMERR ; nope, still an error +12267 8BE0 A6 A9 ldx CHRCNT ; get how many characters +12268 8BE2 8E 37 8A stx SNAMEL ; save in length byte +12269 8BE5 CA dex ; points one too far +12270 8BE6 GNL: +12271 8BE6 BD 00 02 lda LBUFF,X ; get the char +12272 8BE9 9D 38 8A sta SAVENAME,X ; save the char +12273 8BEC CA dex ; point to previous one +12274 8BED 10 F7 bpl GNL ; and go get it +12275 8BEF 18 clc ; show did just fine +12276 8BF0 GNX: +12277 8BF0 08 php ; save status +12278 8BF1 A9 00 lda #0 ; and clear CHRCNT +12279 8BF3 85 A9 sta CHRCNT ; okay +12280 8BF5 A9 0D lda #EOL ; print EOL +12281 8BF7 20 7D 5D jsr CHAR ; okay +12282 8BFA 20 C9 4C jsr SWAPBACK ; change back to old window +12283 8BFD 28 plp ; get status back +12284 8BFE 60 rts ; all done +12285 ; +12286 ; open up a save file, by first trying to create it. If it already exists +12287 ; then make sure the player wants to delete the file, then get rid of it. +12288 ; Finally open the file. Return with carry set if user aborts the save. +12289 ; Store the ref number into the write parm block. +12290 ; +12291 8BFF OPEN_SAVE: +12292 8BFF CREATE CREATE_PB ; first try to create the file +12293 8BFF PRODOS $C0, CREATE_PB +12294 8BFF 20 00 BF jsr $BF00 ; ProDOS handler +12295 8C02 C0 DB $C0 ; ProDOS function code +12296 8C03 EF8A DW CREATE_PB ; Function Parameter Block address +12297 8C05 .MACEND +12298 8C05 .MACEND +12299 8C05 90 16 bcc OPSV_OPEN ; created just fine, so open it +12300 ; +12301 ; can't create the file, check out why +12302 ; +12303 8C07 C9 47 cmp #$47 ; this means file already there +12304 8C09 F0 03 beq OPSV1 ; nope, not that +12305 8C0B 4C 8A 47 jmp DISK_ERR ; show badness +12306 8C0E OPSV1: +12307 8C0E DLINE DELQ ; ask about deleting this file +12308 8C0E A2 87 ldx #DELQ ; get other part of string +12310 [01] IFMA 2 ; check to see if length passed in +12311 ldy ; then just fetch it + Wed May 24 1989 15:00 Page 185 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12312 [01] ELSE +12313 8C12 A0 23 ldy #DELQL ; get length of string +12314 [00] ENDIF +12315 8C14 20 6B 4C jsr DLINE ; print the string +12316 8C17 .MACEND +12317 8C17 20 A4 8C jsr GETYN ; get me the yes or no +12318 8C1A 90 01 bcc OPSV_OPEN ; so then delete it if yes +12319 8C1C 60 rts ; nope, so just quit +12320 8C1D OPSV_OPEN: +12321 8C1D OPEN OPEN_SV ; open the save file +12322 8C1D PRODOS $C8, OPEN_SV +12323 8C1D 20 00 BF jsr $BF00 ; ProDOS handler +12324 8C20 C8 DB $C8 ; ProDOS function code +12325 8C21 008B DW OPEN_SV ; Function Parameter Block address +12326 8C23 .MACEND +12327 8C23 .MACEND +12328 8C23 90 03 bcc OPSV_OP1 ; okey, things worked just fine +12329 8C25 4C 8A 47 jmp DISK_ERR ; complain about error +12330 8C28 OPSV_OP1: +12331 8C28 AD 05 8B lda OPEN_SV+OP_REFNUM ; get the ref number +12332 8C2B 8D 09 8B sta WRITE_SV+WR_REFNUM ; save the ref number +12333 8C2E 8D 07 8B sta CLOSE_PB+CL_REFNUM ; to close parm too +12334 8C31 8D FC 8A sta SETEOF_PB+SE_REFNUM ; for cleansing file +12335 8C34 SET_EOF SETEOF_PB ; clear out file +12336 8C34 PRODOS $D0, SETEOF_PB +12337 8C34 20 00 BF jsr $BF00 ; ProDOS handler +12338 8C37 D0 DB $D0 ; ProDOS function code +12339 8C38 FB8A DW SETEOF_PB ; Function Parameter Block address +12340 8C3A .MACEND +12341 8C3A .MACEND +12342 8C3A 90 03 bcc OPSVEX ; no problems +12343 8C3C 20 8A 47 jsr DISK_ERR ; complain +12344 8C3F OPSVEX: +12345 8C3F 60 rts ; file has been opened, return +12346 ; +12347 ; OPEN_RES - open the save file +12348 ; +12349 8C40 OPEN_RES: +12350 8C40 OPEN OPEN_SV ; open it up +12351 8C40 PRODOS $C8, OPEN_SV +12352 8C40 20 00 BF jsr $BF00 ; ProDOS handler +12353 8C43 C8 DB $C8 ; ProDOS function code +12354 8C44 008B DW OPEN_SV ; Function Parameter Block address +12355 8C46 .MACEND +12356 8C46 .MACEND +12357 8C46 90 01 bcc OPR1 ; okay, it worked +12358 8C48 60 rts ; okay, it didn't +12359 8C49 OPR1: +12360 8C49 AD 05 8B lda OPEN_SV+OP_REFNUM ; get reference number +12361 8C4C 8D CF 45 sta READ_PB+RD_REFNUM ; save for read +12362 8C4F 8D 07 8B sta CLOSE_PB+CL_REFNUM ; and for close +12363 8C52 60 rts +12364 ; +12365 ; CLOSE_SAVE - close up the save file if it is open, and +12366 ; restore open game files +12367 ; +12368 8C53 CLOSE_SAVE: +12369 8C53 AD 07 8B lda CLOSE_PB+CL_REFNUM ; check if it opened +12370 8C56 F0 06 beq CLSVX ; okay, nothing +12371 8C58 CLOSE CLOSE_PB ; close the save file +12372 8C58 PRODOS $CC, CLOSE_PB +12373 8C58 20 00 BF jsr $BF00 ; ProDOS handler +12374 8C5B CC DB $CC ; ProDOS function code +12375 8C5C 068B DW CLOSE_PB ; Function Parameter Block address +12376 8C5E .MACEND +12377 8C5E .MACEND +12378 8C5E CLSVX: +12379 ; lda #1 ; flag is true +12380 ; sta SAVEDISK ; show we have a save disk in there +12381 ; jsr SET_GAMEPRE ; go get the last one used +12382 ; jsr FETCH_FILE ; this does it +12383 8C5E AE 77 46 ldx GAME1NML ; get length of current name +12384 8C61 BD 77 46 lda GAME1NM,X ; get the number of the file +12385 8C64 8D C5 49 sta SAVENUM ; we need this to look for prefix +12386 8C67 8D 54 4A sta SAVEDISK ; show taking out save disk, not game disk + Wed May 24 1989 15:00 Page 186 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12387 8C6A 20 E1 4A jsr DO_GAME1 ; open up GAME1 file +12388 8C6D AD D3 1D lda D2SEG+HI ; set DSEGS to point to #2 +12389 8C70 85 1F sta DSEGS+HI +12390 8C72 AD D2 1D lda D2SEG+LO +12391 8C75 85 1E sta DSEGS+LO +12392 8C77 AE 89 46 ldx GAME2NML ; get length of current name +12393 8C7A BD 89 46 lda GAME2NM,X ; get the number of the file +12394 8C7D 8D C5 49 sta SAVENUM ; we need this to look for prefix +12395 8C80 20 1F 4A jsr OPEN_GAME2 ; open up GAME2 file +12396 8C83 A0 00 ldy #0 ; open up GAME2 file, just for kicks +12397 8C85 8C 54 4A sty SAVEDISK ; show we have a save disk in there +12398 8C88 8C 07 8B sty CLOSE_PB+CL_REFNUM ; clear close +12399 8C8B C8 iny ; set for true +12400 8C8C 84 AA sty SCRIPT ; allow scripting again +12401 8C8E 60 rts ; DONE +12402 ; +12403 ; CLOSE_GAME - close the current game file(s) +12404 ; and set DSEGS to point to preload so it will reopen them +12405 ; +12406 8C8F CLOSE_GAME: +12407 8C8F A9 00 lda #0 ; show no files are open +12408 8C91 8D 07 8B sta CLOSE_PB+CL_REFNUM ; 0 closes all files +12409 8C94 8D 87 46 sta GAME1REF ; zero out two game files too +12410 8C97 8D 99 46 sta GAME2REF ; and here is number 2 +12411 8C9A 8D CE 73 sta PF_FID ; clear this too +12412 8C9D CLOSE CLOSE_PB ; now all are closed +12413 8C9D PRODOS $CC, CLOSE_PB +12414 8C9D 20 00 BF jsr $BF00 ; ProDOS handler +12415 8CA0 CC DB $CC ; ProDOS function code +12416 8CA1 068B DW CLOSE_PB ; Function Parameter Block address +12417 8CA3 .MACEND +12418 8CA3 .MACEND +12419 8CA3 60 rts +12420 ; +12421 ; Get answer to Yes/No question. Return with C==0 for yes, and C==1 +12422 ; for a no. RETURN == Yes, ESCAPE == NO +12423 ; +12424 8CA4 GETYN: +12425 8CA4 20 31 51 jsr GETKEY ; get the key strok +12426 8CA7 C9 79 cmp #'y' ; IF REPLY IS "Y" +12427 8CA9 F0 25 beq ALLSET ; ACCEPT RESPONSES +12428 8CAB C9 59 cmp #'Y' ; get both y's +12429 8CAD F0 21 beq ALLSET +12430 8CAF C9 0D cmp #EOL ; EOL IS ALSO ACCEPTABLE +12431 8CB1 F0 1D beq ALLSET +12432 8CB3 C9 6E cmp #'n' ; IF REPLY IS "N" +12433 8CB5 F0 0E beq NOTSAT ; return with carry set +12434 8CB7 C9 4E cmp #'N' ; check both n's +12435 8CB9 F0 0A beq NOTSAT +12436 8CBB C9 1B cmp #ESCAPE ; check for ESC key too +12437 8CBD F0 06 beq NOTSAT ; which means no +12438 8CBF 20 C3 4E jsr BEEP ; ELSE BEEP +12439 8CC2 4C A4 8C jmp GETYN ; INSIST ON Y OR N +12440 8CC5 NOTSAT: +12441 8CC5 DLINE NO ; PRINT "NO"/EOL +12442 8CC5 A2 B8 ldx #NO ; get other part of string +12444 [01] IFMA 2 ; check to see if length passed in +12445 ldy ; then just fetch it +12446 [01] ELSE +12447 8CC9 A0 03 ldy #NOL ; get length of string +12448 [00] ENDIF +12449 8CCB 20 6B 4C jsr DLINE ; print the string +12450 8CCE .MACEND +12451 8CCE 38 sec ; set the carry +12452 8CCF 60 rts ; and show it +12453 8CD0 ALLSET: +12454 8CD0 DLINE YES ; Print "YES"/EOL +12455 8CD0 A2 B4 ldx #YES ; get other part of string +12457 [01] IFMA 2 ; check to see if length passed in +12458 ldy ; then just fetch it +12459 [01] ELSE +12460 8CD4 A0 04 ldy #YESL ; get length of string +12461 [00] ENDIF + Wed May 24 1989 15:00 Page 187 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12462 8CD6 20 6B 4C jsr DLINE ; print the string +12463 8CD9 .MACEND +12464 8CD9 18 clc ; clear the carry +12465 8CDA 60 rts +12466 8CDB GETRET: +12467 8CDB DLINE RETQ ; ask for return +12468 8CDB A2 A9 ldx #RETQ ; get other part of string +12470 [01] IFMA 2 ; check to see if length passed in +12471 ldy ; then just fetch it +12472 [01] ELSE +12473 8CDF A0 15 ldy #RETQL ; get length of string +12474 [00] ENDIF +12475 8CE1 20 6B 4C jsr DLINE ; print the string +12476 8CE4 .MACEND +12477 8CE4 GETRETL: +12478 8CE4 20 31 51 jsr GETKEY ; get a key +12479 8CE7 C9 0D cmp #EOL ; return key? +12480 8CE9 D0 F9 bne GETRETL ; nope +12481 8CEB 20 7D 5D jsr CHAR ; show the +12482 8CEE 60 rts +12483 8CEF +12484 ; --------- +12485 ; SAVE GAME +12486 ; --------- +12487 8CEF ZSAVE: +12488 8CEF A9 4E lda #'N' +12489 8CF1 A6 62 ldx NARGS +12490 8CF3 F0 02 beq OLDSAV ; NORMAL, COMPLETE SAVE +12491 8CF5 A9 50 lda #'P' +12492 8CF7 OLDSAV: +12493 8CF7 8D 62 5B sta TYPE +12494 8CFA 20 A3 89 jsr SAVRES ; set up screen +12495 8CFD 20 10 8B jsr GET_SNAME ; get the name of the save file +12496 8D00 B0 7B bcs ZSEXIT ; don't wanna after all +12497 8D02 20 FF 8B jsr OPEN_SAVE ; open the file +12498 8D05 B0 76 bcs ZSEXIT ; don't really care to +12499 ; +12500 ; SAVE GAME PARAMETERS IN [BUFSAV] +12501 ; +12502 8D07 AD 02 96 lda ZBEGIN+ZID ; MOVE GAME ID +12503 8D0A 8D 20 1E sta BUFSAV+0 ; INTO 1ST 2 BYTES +12504 8D0D AD 03 96 lda ZBEGIN+ZID+1 ; OF THE A +12505 8D10 8D 21 1E sta BUFSAV+1 +12506 8D13 A5 AF lda ZSP+LO ; MOVE [ZSP] +12507 8D15 8D 22 1E sta BUFSAV+2 +12508 8D18 A5 B0 lda ZSP+HI +12509 8D1A 8D 23 1E sta BUFSAV+3 +12510 8D1D AD 75 6C lda OLDZSP+LO +12511 8D20 8D 24 1E sta BUFSAV+4 +12512 8D23 AD 76 6C lda OLDZSP+HI ; MOVE [OLDZSP] +12513 8D26 8D 25 1E sta BUFSAV+5 +12514 8D29 A2 02 ldx #2 ; MOVE CONTENTS OF [ZPC] +12515 8D2B B5 80 ZSL1: lda ZPC,X ; TO BYTES 7-9 +12516 8D2D 9D 26 1E sta BUFSAV+6,X ; OF [BUFSAV] +12517 8D30 CA dex +12518 8D31 10 F8 bpl ZSL1 +12519 8D33 AD 62 5B lda TYPE +12520 8D36 8D 29 1E sta BUFSAV+9 ; NORMAL OR PARTIAL +12521 8D39 C9 50 cmp #'P' +12522 8D3B D0 2A bne ZSNONM ; NORMAL SAVE SO NO name TO SAVE +12523 +12524 8D3D A5 67 lda ARG3+LO ; set up FPC to get save name +12525 8D3F 85 8C sta FPCL ; lo part is okay +12526 8D41 A5 68 lda ARG3+HI ; get page +12527 8D43 20 77 8F jsr SETPC ; get memory addr +12528 8D46 85 8D sta FPCH ; page number +12529 8D48 84 8E sty FPCBNK ; and bank +12530 8D4A 20 56 92 jsr FETCHB ; get count +12531 8D4D 85 78 sta I ; and save it +12532 8D4F 20 BE 8F jsr NEXTFPC ; point to next byte +12533 8D52 A9 00 lda #0 ; set up data offset +12534 8D54 85 7A sta J ; did it +12535 8D56 ZSL3: +12536 8D56 20 56 92 jsr FETCHB ; get data byte + Wed May 24 1989 15:00 Page 188 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12537 8D59 A4 7A ldy J ; get offset +12538 8D5B 99 2A 1E sta BUFSAV+10,Y ; save into buffer +12539 8D5E 20 BE 8F jsr NEXTFPC ; point to next byte +12540 8D61 E6 7A inc J ; next byte +12541 8D63 C6 78 dec I ; count it +12542 8D65 D0 EF bne ZSL3 ; loop again +12543 8D67 ZSNONM: +12544 ; +12545 ; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK +12546 ; +12547 8D67 A9 00 lda #MAIN ; in the main bank +12548 8D69 85 B8 sta DSKBNK ; thank you +12549 8D6B A9 1E lda #>LOCALS ; start at locals +12550 8D6D 85 B7 sta DBUFF+HI ; POINT TO THE PAGE +12551 8D6F 20 F6 47 jsr PUTDSK ; AND WRITE IT OUT +12552 8D72 90 0F bcc ZSOK ; IF SUCCEEDED, WRITE STACK +12553 8D74 ZSBAD: +12554 8D74 20 8A 47 jsr DISK_ERR ; print error message +12555 8D77 SET_EOF SETEOF_PB ; clear out file, maybe +12556 8D77 PRODOS $D0, SETEOF_PB +12557 8D77 20 00 BF jsr $BF00 ; ProDOS handler +12558 8D7A D0 DB $D0 ; ProDOS function code +12559 8D7B FB8A DW SETEOF_PB ; Function Parameter Block address +12560 8D7D .MACEND +12561 8D7D .MACEND +12562 8D7D ZSEXIT: +12563 8D7D 20 53 8C jsr CLOSE_SAVE ; else get game file back +12564 8D80 4C DA 43 jmp RET0 ; AND FAIL +12565 ; +12566 ; IF A PARTIAL SAVE WRITE FROM ARG1 FOR ARG2 BYTES TO DISK +12567 ; (ROUNDED TO PGS) SKIPPING ZSTACK WRITE +12568 ; +12569 8D83 ZSOK: +12570 8D83 AD 62 5B lda TYPE +12571 8D86 C9 50 cmp #'P' +12572 8D88 D0 1F bne ZSALL +12573 8D8A A5 64 lda ARG1+HI ; find where to start & how far to go +12574 8D8C 20 77 8F jsr SETPC ; get page in memory +12575 8D8F 48 pha ; save for minute +12576 8D90 29 01 and #$01 ; check for odd page +12577 8D92 F0 02 beq ZSP1 ; nope, don't make one more page +12578 8D94 E6 66 inc ARG2+HI ; go get one more page +12579 8D96 ZSP1: +12580 8D96 68 pla ; get it back +12581 8D97 29 FE and #$FE ; must be on block boundary +12582 8D99 85 B7 sta DBUFF+HI ; this is page +12583 8D9B 84 B8 sty DSKBNK ; which bank +12584 8D9D A6 66 ldx ARG2+HI ; get MSB of count +12585 8D9F A5 63 lda ARG1+LO ; get lo offset +12586 8DA1 18 clc ; add +12587 8DA2 65 65 adc ARG2+LO ; lo count +12588 8DA4 90 01 bcc ZSPINC ; no extra page +12589 8DA6 E8 inx ; wrapped extra page +12590 8DA7 ZSPINC: +12591 8DA7 D0 15 bne SAVE2DISK ; go copy it now +12592 ; +12593 ; WRITE CONTENTS OF Z-STACK TO DISK +12594 ; +12595 8DA9 ZSALL: +12596 8DA9 A9 0D lda #>ZSTKBL ; point to 1st page +12597 8DAB 85 B7 sta DBUFF+HI +12598 8DAD 20 F6 47 jsr PUTDSK ; write them, first one +12599 8DB0 B0 C2 bcs ZSBAD +12600 8DB2 20 F6 47 jsr PUTDSK ; write them, second one +12601 8DB5 B0 BD bcs ZSBAD +12602 ; +12603 ; WRITE ENTIRE GAME PRELOAD TO DISK +12604 ; +12605 8DB7 A9 96 lda #>ZBEGIN ; POINT TO 1ST PAGE +12606 8DB9 85 B7 sta DBUFF+HI ; OF PRELOAD +12607 8DBB AE 0E 96 ldx ZBEGIN+ZPURBT ; GET # IMPURE PAGES +12608 8DBE SAVE2DISK: +12609 8DBE E8 inx ; use for counting +12610 8DBF 86 78 stx I+LO +12611 8DC1 46 78 lsr I+LO ; /2 for 512byte pages + Wed May 24 1989 15:00 Page 189 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12612 8DC3 90 02 bcc ZSL2 ; no wrapping +12613 8DC5 E6 78 inc I+LO ; wrapped once +12614 8DC7 ZSL2: +12615 8DC7 20 F6 47 jsr PUTDSK ; this does the write +12616 8DCA B0 A8 bcs ZSBAD +12617 8DCC C6 78 dec I+LO ; count one page +12618 8DCE D0 F7 bne ZSL2 ; not done yet +12619 +12620 8DD0 20 53 8C jsr CLOSE_SAVE ; prompt for game file +12621 +12622 [01] IF CHECKSUM == 1 +12623 lda CKS_COUNT +12624 jsr HEXNUM +12625 lda CKSB +12626 jsr HEXNUM +12627 lda #EOL +12628 jsr CHAR +12629 [00] ENDIF +12630 +12631 8DD3 A9 01 lda #1 ; set to mark +12632 8DD5 A2 00 ldx #0 +12633 8DD7 4C DD 43 jmp PUTBYT ; SUCCESS +12634 +12635 ; ------------ +12636 ; RESTORE GAME +12637 ; ------------ +12638 +12639 8DDA ZREST: +12640 8DDA A9 4E lda #'N' +12641 8DDC A6 62 ldx NARGS +12642 8DDE F0 02 beq OLDRES ; NORMAL, COMPLETE RESTORE +12643 8DE0 A9 50 lda #'P' ; partial restore +12644 8DE2 OLDRES: +12645 8DE2 8D 62 5B sta TYPE ; save which kind of restore +12646 ; +12647 ; SAVE LOCALS IN CASE OF ERROR +12648 ; +12649 8DE5 A2 1F ldx #31 +12650 8DE7 BD 00 1E LOCSAV: lda LOCALS,X ; COPY ALL LOCALS +12651 8DEA 9D E0 1D sta LOCAL_SV,X ; to a save spot +12652 8DED CA dex +12653 8DEE 10 F7 bpl LOCSAV +12654 +12655 8DF0 20 10 8B jsr GET_SNAME ; get the name of the file +12656 8DF3 B0 3C bcs ZRQUIT ; okay, don't do it +12657 8DF5 20 40 8C jsr OPEN_RES ; open the restore file +12658 8DF8 B0 34 bcs ZRBAD ; can't do it +12659 +12660 8DFA AD 62 5B lda TYPE ; PARTIAL SAVE DIFFERS STARTING HERE +12661 8DFD C9 50 cmp #'P' +12662 8DFF D0 03 bne ZRNRML +12663 8E01 4C C2 8E jmp ZPARTR ; just a partial restore +12664 8E04 ZRNRML: +12665 8E04 A9 00 lda #MAIN +12666 8E06 85 B8 sta DSKBNK ; SET TO WRITE TO MAIN BANK +12667 8E08 A9 1E lda #>LOCALS +12668 8E0A 85 B7 sta DBUFF+HI +12669 8E0C A9 02 lda #2 ; must read in two pages +12670 8E0E 85 7E sta L+LO +12671 8E10 20 11 48 jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD +12672 8E13 B0 19 bcs ZRBAD ; didn't work! +12673 8E15 AD D5 45 lda READ_PB+RD_LENGTH+HI ; see how much was read in +12674 8E18 C9 02 cmp #2 ; were 2 blocks read in? +12675 8E1A D0 15 bne ZRQUIT ; wrong kind of file for complete save +12676 +12677 8E1C AD 20 1E lda BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID +12678 8E1F CD 02 96 cmp ZBEGIN+ZID ; MATCH THE CURRENT ID? +12679 8E22 D0 0D bne ZRQUIT ; WRONG DISK IF NOT +12680 +12681 8E24 AD 21 1E lda BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE? +12682 8E27 CD 03 96 cmp ZBEGIN+ZID+1 +12683 8E2A F0 16 beq ZROK ; CONTINUE IF BOTH BYTES MATCH +12684 8E2C D0 03 bne ZRQUIT ; skip disk error message +12685 ; +12686 ; HANDLE RESTORE ERROR + Wed May 24 1989 15:00 Page 190 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12687 ; +12688 8E2E ZRBAD: +12689 8E2E 20 8A 47 jsr DISK_ERR ; print error message +12690 8E31 ZRQUIT: +12691 8E31 A2 1F ldx #31 ; RESTORE ALL SAVED LOCALS +12692 8E33 BD E0 1D ZRL2: lda LOCAL_SV,X +12693 8E36 9D 00 1E sta LOCALS,X +12694 8E39 CA dex +12695 8E3A 10 F7 bpl ZRL2 +12696 8E3C BADRES: +12697 8E3C 20 53 8C jsr CLOSE_SAVE ; PROMPT FOR GAME DISK +12698 8E3F 4C DA 43 jmp RET0 ; PREDICATE FAILS +12699 ; +12700 ; CONTINUE RESTORE +12701 ; +12702 8E42 ZROK: +12703 8E42 AD 10 96 lda ZBEGIN+ZFLAGS ; save both flag bytes +12704 8E45 85 7A sta J+LO +12705 8E47 AD 11 96 lda ZBEGIN+ZFLAGS+1 +12706 8E4A 85 7B sta J+HI +12707 +12708 8E4C A9 0D lda #>ZSTKBL ; retrieve old contents of +12709 8E4E 85 B7 sta DBUFF+HI ; z-stack +12710 8E50 A9 04 lda #4 ; do 4 pages +12711 8E52 85 7E sta L+LO ; tell GETRES how many pages +12712 8E54 20 11 48 jsr GETRES ; get 4 pages of z-stack +12713 8E57 90 03 bcc ZROKL1 +12714 8E59 4C 74 47 jmp DISK_FATAL ; if here, mix of good & bad so die +12715 8E5C ZROKL1: +12716 8E5C A9 96 lda #>ZBEGIN ; get where we are +12717 8E5E 85 B7 sta DBUFF+HI +12718 8E60 AD 0E 96 lda ZBEGIN+ZPURBT ; get # pages to load +12719 8E63 85 78 sta I+LO +12720 8E65 E6 78 inc I+LO ; go get last page if possible +12721 8E67 LREST0: +12722 8E67 A5 78 lda I+LO ; how many pages left +12723 8E69 F0 20 beq LRESTj ; finis +12724 8E6B 38 sec ; doing subtract +12725 8E6C E9 04 sbc #4 ; doing it 4 blocks at a time +12726 8E6E 90 0E bcc LREST1 ; <4 blocks left so deal with it special +12727 8E70 85 78 sta I+LO ; save remenants +12728 8E72 LREST: +12729 8E72 A9 04 lda #4 ; assume at least 4 pages +12730 8E74 85 7E sta L+LO ; this tells GETRES how many to read in +12731 8E76 20 11 48 jsr GETRES ; fetch the remainder +12732 8E79 90 EC bcc LREST0 +12733 8E7B 4C 74 47 jmp DISK_FATAL +12734 8E7E LREST1: +12735 8E7E A5 78 lda I+LO ; get how many left +12736 8E80 85 7E sta L+LO ; and show it to GETRES +12737 8E82 29 01 and #$1 ; is it odd? +12738 8E84 F0 02 beq LREST2 ; nope +12739 8E86 E6 7E inc L+LO ; read one more +12740 8E88 LREST2: +12741 8E88 20 11 48 jsr GETRES ; and finish it up +12742 ; +12743 ; RESTORE THE STATE OF THE SAVED GAME +12744 ; +12745 8E8B LRESTj: +12746 8E8B A5 7A lda J+LO ; RESTORE THE STATE +12747 8E8D 8D 10 96 sta ZBEGIN+ZFLAGS ; OF THE FLAG WORD +12748 8E90 A5 7B lda J+HI +12749 8E92 8D 11 96 sta ZBEGIN+ZFLAGS+1 +12750 +12751 8E95 AD 22 1E lda BUFSAV+2 ; RESTORE THE [ZSP] +12752 8E98 85 AF sta ZSP+LO +12753 8E9A AD 23 1E lda BUFSAV+3 +12754 8E9D 85 B0 sta ZSP+HI +12755 8E9F AD 24 1E lda BUFSAV+4 +12756 8EA2 8D 75 6C sta OLDZSP+LO +12757 8EA5 AD 25 1E lda BUFSAV+5 ; AND THE [OLDZSP] +12758 8EA8 8D 76 6C sta OLDZSP+HI +12759 +12760 8EAB A2 02 ldx #2 ; RESTORE THE [ZPC] +12761 8EAD BD 26 1E ZRL4: lda BUFSAV+6,X + Wed May 24 1989 15:00 Page 191 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12762 8EB0 95 80 sta ZPC,X +12763 8EB2 CA dex +12764 8EB3 10 F8 bpl ZRL4 +12765 +12766 8EB5 20 53 8C ZROUT: jsr CLOSE_SAVE ; PROMPT FOR GAME DISK +12767 8EB8 20 AA 90 jsr VLDZPC ; MAKE VALID (MUST DO AFTER GET DISK) +12768 +12769 [01] IF CHECKSUM == 1 +12770 lda CKS_COUNT +12771 jsr HEXNUM +12772 lda CKSB +12773 jsr HEXNUM +12774 lda #EOL +12775 jsr CHAR +12776 [00] ENDIF +12777 +12778 8EBB A9 02 lda #2 ; SET TO +12779 8EBD A2 00 ldx #0 +12780 8EBF 4C DD 43 jmp PUTBYT ; SUCCESS +12781 +12782 +12783 ; DO PARTIAL RESTORE GETTING 1ST PAGE +12784 ; AND LAST PAGE BYTE ALIGNMENT CORRECT +12785 ; WRITE LOCALS TO IOBUFF JUST TO LOOK AT NAME +12786 8EC2 ZPARTR: +12787 8EC2 A9 00 lda #MAIN +12788 8EC4 85 B8 sta DSKBNK +12789 8EC6 A9 08 lda #>IOBUFF ; DON'T READ TO LOCALS YET (X) +12790 8EC8 85 B7 sta DBUFF+HI +12791 8ECA A9 02 lda #2 ; just one block please +12792 8ECC 85 7E sta L+LO +12793 8ECE 20 11 48 jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD +12794 8ED1 90 03 bcc ZRN2 ; worked just fine +12795 8ED3 ZPBAD: +12796 8ED3 4C 3C 8E jmp BADRES ; names don't match, die +12797 8ED6 ZRN2: +12798 8ED6 A5 67 lda ARG3+LO ; set up FPC to get save name +12799 8ED8 85 8C sta FPCL ; lo part is okay +12800 8EDA A5 68 lda ARG3+HI ; get page +12801 8EDC 20 77 8F jsr SETPC ; get memory addr +12802 8EDF 85 8D sta FPCH ; page number +12803 8EE1 84 8E sty FPCBNK ; and bank +12804 8EE3 20 56 92 jsr FETCHB ; get count +12805 8EE6 85 78 sta I ; and save it +12806 8EE8 20 BE 8F jsr NEXTFPC ; point to next byte +12807 8EEB A9 20 lda #IOBUFF ; get 1st page +12836 8F1F 85 B7 sta DBUFF+HI ; getres should keep in iobuff + Wed May 24 1989 15:00 Page 192 + + "APPLE YZIP (c)Infocom, Inc.. --- OPCODE EXECUTORS" + "--- ZIP SAVE AND RESTORE ROUTINES ---" + +12837 8F21 8D 3D 8F sta ZPARTMOD+2 ; and show where to get it from +12838 8F24 A9 01 lda #$01 ; is it odd +12839 8F26 24 90 bit SPCH ; get page destination +12840 8F28 F0 03 beq ZPARTx ; nope +12841 8F2A EE 3D 8F inc ZPARTMOD+2 ; then get second page worth +12842 8F2D ZPARTx: +12843 8F2D A9 02 lda #2 ; just do one block +12844 8F2F 85 7E sta L+LO +12845 8F31 20 11 48 jsr GETRES +12846 8F34 90 03 bcc ZPART0 +12847 8F36 4C 74 47 jmp DISK_FATAL ; ALL MESSED UP, JUST QUIT +12848 8F39 ZPART0: +12849 8F39 A4 63 ldy ARG1+LO ; START BYTE FIRST PAGE +12850 8F3B ZPARTMOD: +12851 8F3B B9 00 08 lda IOBUFF,Y ; this gets modified with good page # +12852 8F3E 20 35 92 jsr STASHB +12853 8F41 20 9E 8F jsr NEXTSPC +12854 8F44 20 C6 44 jsr DECJ +12855 8F47 B0 03 bcs ZPART1 ; CARRY CLEAR IF $FFFF RESULT +12856 8F49 4C B5 8E jmp ZROUT +12857 8F4C ZPART1: +12858 8F4C E6 63 inc ARG1+LO +12859 8F4E D0 E9 bne ZPART0 +12860 8F50 A9 09 lda #>IOBUFF+1 ; this is second page address +12861 8F52 CD 3D 8F cmp ZPARTMOD+2 ; is it second one already? +12862 8F55 F0 C6 beq POK ; yes, so read in a new block +12863 8F57 8D 3D 8F sta ZPARTMOD+2 ; then update it +12864 8F5A D0 DD bne ZPART0 ; and do it again +12865 ; +12866 ; THE OLD SAVE & RESTORE STILL HAVE OPCODES +12867 ; SO JUST PUT IN A PLACE FOR THEM HERE FOR NOW +12868 ; +12869 8F5C OSAVE: +12870 8F5C 60 OREST: RTS +12871 +12872 8F5D ZISAVE: +12873 8F5D 4C DA 43 ZIREST: JMP RET0 ; NOT IMPLEMENTED ON APPLE +12874 8F60 END +12875 +12876 +12877 8F60 TITLE "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" +12878 8F60 INCLUDE XPAGING.ASM +12879 8F60 STTL "--- MEMORY PAGING ROUTINES ---" +12880 PAGE + Wed May 24 1989 15:00 Page 193 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +12881 +12882 ; ------------------------- +12883 ; POINT [MPC] TO V-ADDR [I] +12884 ; ------------------------- +12885 +12886 8F60 A5 78 SETWRD: LDA I+LO +12887 8F62 85 86 STA MPCL +12888 8F64 A5 79 LDA I+HI +12889 8F66 85 87 STA MPCM +12890 8F68 A9 00 LDA #0 +12891 8F6A 85 88 STA MPCH ; ZERO TOP BIT +12892 8F6C 4C 80 90 JMP VLDMPC +12893 +12894 ; +12895 8F6F 00 00 WANTED: DB 00,00 +12896 ; +12897 8F71 00 NEXT: DB 00 +12898 8F72 00 NSUBA: DB 00 +12899 8F73 00 PSUBA: DB 00 +12900 ; +12901 8F74 00 YTEMP: DB 00 +12902 8F75 00 ATEMP: DB 00 +12903 8F76 00 NSUBY: DB 00 +12904 ; +12905 ; set [A](page), [Y](bank) to point to memory page where page in [A] is +12906 ; +12907 8F77 SETPC: +12908 8F77 85 BC sta MEMPAGE ; save it for later addition +12909 8F79 C9 29 cmp #P2PAGE ; IS IT A PAGE IN MAIN +12910 8F7B B0 06 bcs VF2 ; No, it might be in aux mem +12911 +12912 8F7D A9 96 lda #>ZBEGIN ; ADD OFFSET TO GET RAM PAGE +12913 8F7F A0 00 ldy #MAIN ; in the main bank +12914 8F81 F0 12 beq VFEXI ; BRA to fetch +12915 8F83 VF2: +12916 8F83 C9 D6 cmp #PGBEGIN ; is it paged? +12917 8F85 B0 12 bcs VFERR ; yes it be paged, so can't deal with it +12918 8F87 C9 A8 cmp #P3PAGE ; is it in Aux Mem, Part 2? +12919 8F89 B0 06 bcs VF3 ; yes, so subtract different amount +12920 ; +12921 ; this is in lower aux +12922 ; +12923 8F8B A9 17 lda #(Z2PAGE-Z1SIZE) ; subtract size from offset +12924 8F8D A0 01 ldy #AUX ; show aux mem +12925 8F8F D0 04 bne VFEXI ; jump to end +12926 8F91 VF3: +12927 8F91 A9 28 lda #(Z3PAGE-(Z1SIZE+Z2SIZE)) ; subtract out first 2 sides +12928 8F93 A0 FF ldy #P3BANK ; show page 3 bank +12929 8F95 VFEXI: +12930 8F95 18 clc ; get ready for addition +12931 8F96 65 BC adc MEMPAGE ; now get actual offset +12932 8F98 60 rts +12933 8F99 VFERR: +12934 ; +12935 ; out of range +12936 ; +12937 8F99 A9 12 lda #18 +12938 8F9B 4C 0A 52 jmp ZERROR +12939 ; +12940 ; NEXTSPC - inc SPCL and check for wrapping round to next bank +12941 ; +12942 8F9E NEXTSPC: +12943 8F9E E6 8F inc SPCL ; next lo byte +12944 8FA0 D0 1B bne NXSP_EXIT ; no change then +12945 8FA2 E6 90 inc SPCH ; next page +12946 8FA4 A5 90 lda SPCH ; so get page +12947 8FA6 C9 BF cmp #>PRGLBL ; have we reached end of line? +12948 8FA8 D0 13 bne NXSP_EXIT ; we be okay +12949 8FAA A5 91 lda SPCBNK ; get bank +12950 8FAC D0 07 bne NXSP1 ; must go to Part 3 +12951 8FAE E6 91 inc SPCBNK ; so point to aux bank +12952 8FB0 A9 40 lda #Z2PAGE ; first page in aux +12953 8FB2 85 90 sta SPCH ; and point to it +12954 8FB4 60 rts ; and all done +12955 8FB5 NXSP1: + Wed May 24 1989 15:00 Page 194 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +12956 8FB5 A9 D0 lda #Z3PAGE ; get start of page 3 +12957 8FB7 85 90 sta SPCH ; and point there +12958 8FB9 A9 FF lda #P3BANK ; and point to this bank +12959 8FBB 85 91 sta SPCBNK ; okey +12960 8FBD NXSP_EXIT: +12961 8FBD 60 rts +12962 ; +12963 ; NEXTFPC - inc DPCL and check for wrapping round to next bank +12964 ; +12965 8FBE NEXTFPC: +12966 8FBE E6 8C inc FPCL ; next lo byte +12967 8FC0 D0 1B bne NXFP_EXIT ; no change then +12968 8FC2 E6 8D inc FPCH ; next page +12969 8FC4 A5 8D lda FPCH ; and get it for checking +12970 8FC6 C9 BF cmp #>PRGLBL ; have we reached end of line? +12971 8FC8 D0 13 bne NXFP_EXIT ; we be okay +12972 8FCA A5 8E lda FPCBNK ; get bank +12973 8FCC D0 07 bne NXFP1 ; must skip over stuff in middle +12974 8FCE E6 8E inc FPCBNK ; so point to aux bank +12975 8FD0 A9 40 lda #Z2PAGE ; first page in aux +12976 8FD2 85 8D sta FPCH ; and point to it +12977 8FD4 60 rts ; toots finis +12978 8FD5 NXFP1: +12979 8FD5 A9 D0 lda #Z3PAGE ; start of part 3 +12980 8FD7 85 8D sta FPCH ; so show me +12981 8FD9 A9 FF lda #P3BANK ; and point to this bank +12982 8FDB 85 8E sta FPCBNK ; okey +12983 8FDD NXFP_EXIT: +12984 8FDD 60 rts +12985 ; +12986 ; ADDFPC - add amount in [A] to current FPC and check for bank wrap +12987 ; +12988 8FDE ADDFPC: +12989 8FDE 18 clc ; get ready for add +12990 8FDF 65 8C adc FPCL ; add lo part +12991 8FE1 85 8C sta FPCL ; and save it +12992 8FE3 90 1B bcc AFPX ; all done if no page wrap +12993 8FE5 E6 8D inc FPCH ; point to next page +12994 8FE7 A5 8D lda FPCH ; get it for compare +12995 8FE9 C9 BF cmp #>PRGLBL ; at end of line in main bank? +12996 8FEB D0 13 bne AFPX ; nope, all done then +12997 8FED A5 8E lda FPCBNK ; get bank +12998 8FEF F0 09 beq AFP1 ; it is main, so we be ok +12999 8FF1 A9 D0 lda #Z3PAGE ; must go to part 3 if in aux mem +13000 8FF3 85 8D sta FPCH ; thanx +13001 8FF5 A9 FF lda #P3BANK ; and point to this bank +13002 8FF7 85 8E sta FPCBNK ; okey +13003 8FF9 60 rts ; done +13004 8FFA AFP1: +13005 8FFA E6 8E inc FPCBNK ; point to aux +13006 8FFC A9 40 lda #Z2PAGE ; get start in aux +13007 8FFE 85 8D sta FPCH ; and save it +13008 9000 AFPX: +13009 9000 60 rts +13010 ; +13011 ; ADDSPC - add amount in [A] to current SPC and check for bank wrap +13012 ; +13013 9001 ADDSPC: +13014 9001 18 clc ; get ready for add +13015 9002 65 8F adc SPCL ; add lo part +13016 9004 85 8F sta SPCL ; and save it +13017 9006 90 1B bcc ASPX ; all done if no page wrap +13018 9008 E6 90 inc SPCH ; point to next page +13019 900A A5 90 lda SPCH ; get it for compare +13020 900C C9 BF cmp #>PRGLBL ; at end of line in main bank? +13021 900E D0 13 bne ASPX ; nope, all done then +13022 9010 A5 91 lda SPCBNK ; get bank +13023 9012 F0 09 beq ASP1 ; it is main, so we be ok +13024 9014 A9 D0 lda #Z3PAGE ; must go to part 3 if in aux mem +13025 9016 85 90 sta SPCH ; thanx +13026 9018 A9 FF lda #P3BANK ; and point to this bank +13027 901A 85 91 sta SPCBNK ; okey +13028 901C 60 rts ; done +13029 901D ASP1: +13030 901D E6 91 inc SPCBNK ; point to aux + Wed May 24 1989 15:00 Page 195 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13031 901F A9 40 lda #Z2PAGE ; get start in aux +13032 9021 85 90 sta SPCH ; and save it +13033 9023 ASPX: +13034 9023 60 rts +13035 ; +13036 ; PREVFPC - DEC FPCL and check for wrapping round to next bank +13037 ; +13038 9024 PREVFPC: +13039 9024 A5 8C lda FPCL ; get lo part +13040 9026 D0 1E bne PFPC2 ; it's not zero, so no wrapping +13041 9028 A5 8D lda FPCH ; get current page +13042 902A C9 40 cmp #Z2PAGE ; have we reached beginning of page 2? +13043 902C F0 08 beq PFPC1 ; wrap to first bank +13044 902E C9 D0 cmp #Z3PAGE ; beginning of part 3? +13045 9030 F0 0C beq PFPC3 ; ayyup +13046 9032 C6 8D dec FPCH ; point to previous page +13047 9034 D0 10 bne PFPC2 ; okay +13048 9036 PFPC1: +13049 9036 A5 8E lda FPCBNK ; get bank +13050 9038 F0 0F beq VF1ERR ; oops, can't go backwards from main bank +13051 903A A9 00 lda #MAIN ; so point to main bank +13052 903C F0 02 beq PFPC4 ; and store it away +13053 903E PFPC3: +13054 903E A9 01 lda #AUX ; and point to this bank +13055 9040 PFPC4: +13056 9040 85 8E sta FPCBNK ; okey +13057 9042 A9 BE lda #(>PRGLBL)-1 ; get me last page in part 2 +13058 9044 85 8D sta FPCH ; and show me +13059 9046 PFPC2: +13060 9046 C6 8C dec FPCL ; and point to previous byte +13061 9048 60 rts +13062 9049 VF1ERR: +13063 ; +13064 ; out of range +13065 ; +13066 9049 A9 13 lda #19 +13067 904B 4C 0A 52 jmp ZERROR +13068 ; +13069 ; PREVSPC - DEC SPCL and check for wrapping round to main bank +13070 ; +13071 904E PREVSPC: +13072 904E A5 8F lda SPCL ; get lo part +13073 9050 D0 1E bne PSPC2 ; it's not zero, so no wrapping +13074 9052 A5 90 lda SPCH ; get current page +13075 9054 C9 40 cmp #Z2PAGE ; have we reached beginning of page 2? +13076 9056 F0 08 beq PSPC1 ; wrap to first bank +13077 9058 C9 D0 cmp #Z3PAGE ; down past page 3? +13078 905A F0 0C beq PSPC3 ; sure is +13079 905C C6 90 dec SPCH ; point to previous page +13080 905E D0 10 bne PSPC2 ; okay +13081 9060 PSPC1: +13082 9060 A5 91 lda SPCBNK ; get bank +13083 9062 F0 E5 beq VF1ERR ; oops, can't go backwards from main bank +13084 9064 A9 00 lda #MAIN ; so point to main bank +13085 9066 F0 02 beq PSPC4 ; so save it +13086 9068 PSPC3: +13087 9068 A9 01 lda #AUX ; and point to this bank +13088 906A PSPC4: +13089 906A 85 8E sta FPCBNK ; okey +13090 906C A9 BE lda #>PRGLBL-1 ; get me last page in low part +13091 906E 85 90 sta SPCH ; and show me +13092 9070 PSPC2: +13093 9070 C6 8F dec SPCL ; and point to previous byte +13094 9072 60 rts +13095 ; +13096 ; FP2SP - copy the 3 parts of FPC to SPC +13097 ; +13098 9073 FP2SP: +13099 9073 A5 8E lda FPCBNK +13100 9075 85 91 sta SPCBNK +13101 9077 A5 8D lda FPCH +13102 9079 85 90 sta SPCH +13103 907B A5 8C lda FPCL +13104 907D 85 8F sta SPCL +13105 907F 60 rts + Wed May 24 1989 15:00 Page 196 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13106 9080 +13107 ; MAKE [MPCPNT],[MPCBNK] POINT TO +13108 ; THE RAM PAGE AND BANK THAT HOLDS +13109 ; THE V-PAGE MPCH,M +13110 ; +13111 9080 VLDMPC: +13112 9080 A5 88 lda MPCH ; check hi part +13113 9082 D0 0F bne VLD3 ; NOT IN FIRST V-64K, so must be paged +13114 9084 A5 87 lda MPCM ; check to see if it is paged +13115 9086 20 A2 91 jsr CHECKPRE ; is it preloaded? +13116 9089 B0 08 bcs VLD3 ; no, so it be paged +13117 908B 20 77 8F jsr SETPC ; so put page/bank into A/Y +13118 908E 84 8B sty MPCBNK +13119 9090 85 8A sta MPCPNT+HI +13120 9092 NOMUCK: +13121 9092 60 rts +13122 ; +13123 ; must be paged, so check for it or read it in +13124 ; +13125 9093 VLD3: +13126 9093 A5 88 lda MPCH +13127 9095 A4 87 ldy MPCM +13128 9097 20 E0 90 jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y +13129 909A 18 clc +13130 909B 69 08 adc #>PBEGIN +13131 909D 85 8A sta MPCPNT+HI +13132 909F A0 01 ldy #PB_BANK ; paging buffers are in aux mem +13133 90A1 84 8B sty MPCBNK +13134 ; +13135 ; TEST FOR MUCK +13136 ; +13137 90A3 AD DF 90 lda MUCKFLG +13138 90A6 F0 EA beq NOMUCK +13139 90A8 D0 00 bne VLDZPC ;MAY HAVE MUCKED ZPC SO GO FIX +13140 ; +13141 ; SAME IDEA AS VLDMPC +13142 ; +13143 90AA VLDZPC: +13144 90AA A5 59 lda INFODOS ; check first for InfoDOS page +13145 90AC F0 06 beq VLDZ1 ; none +13146 90AE 20 B7 91 jsr INFO_PAGE ; well, is it? +13147 90B1 90 01 bcc VLDZ1 ; nope +13148 90B3 60 rts ; all set otherwise +13149 90B4 VLDZ1: +13150 90B4 A5 82 lda ZPCH +13151 90B6 D0 0F bne VLDZ3 ;NOT IN FIRST V-64K, so must be paged +13152 90B8 A5 81 lda ZPCM ; check to see if it is paged +13153 90BA 20 A2 91 jsr CHECKPRE ; is it preloaded? +13154 90BD B0 08 bcs VLDZ3 ; no, so it must be paged +13155 90BF 20 77 8F jsr SETPC ; point to correct bank and page +13156 90C2 84 85 sty ZPCBNK ; set bank +13157 90C4 85 84 sta ZPCPNT+HI ; and MSB of pointer +13158 90C6 NOZMUCK: +13159 90C6 60 rts +13160 VLDZ3: ;MUST BE PAGED +13161 90C7 A5 82 lda ZPCH +13162 90C9 A4 81 ldy ZPCM +13163 90CB 20 E0 90 jsr PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y +13164 90CE 18 clc +13165 90CF 69 08 adc #>PBEGIN +13166 90D1 85 84 sta ZPCPNT+HI +13167 90D3 A0 01 ldy #PB_BANK +13168 90D5 84 85 sty ZPCBNK +13169 ; +13170 ; TEST MUCKING +13171 ; +13172 90D7 AD DF 90 lda MUCKFLG +13173 90DA F0 EA beq NOZMUCK +13174 90DC 4C 80 90 jmp VLDMPC ;MAY HAVE MUCKED MPC SO GO FIX +13175 +13176 +13177 ; FIND V-PAGE A,Y IF IT IS IN MEM +13178 ; AND RETURN WITH LINKED LIST +13179 ; PROPERLY MAINTAINED +13180 ; IF V-PAGE A,Y NOT IN MEM + Wed May 24 1989 15:00 Page 197 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13181 ; GET FROM DISK AND PUT IN RIGHT +13182 ; PLACE +13183 +13184 90DF 00 MUCKFLG: DB 00 ;00 IF PAGING BUFFERS NOT MUCKED +13185 +13186 90E0 PAGE: +13187 90E0 8D 70 8F sta WANTED+HI +13188 90E3 8C 6F 8F sty WANTED+LO +13189 90E6 A2 00 ldx #0 +13190 90E8 8E DF 90 stx MUCKFLG ; CLEAR MUCK FLAG +13191 90EB 20 8A 91 jsr WHERE +13192 90EE 90 39 bcc TOUGH ; PAGE IS RESIDENT IN PAGING SPACE +13193 ; +13194 ; PAGE MUST BE BROUGHT IN FROM DISK +13195 ; +13196 90F0 A6 CD ldx CURRENT ;GET BUFFER TO PUT PAGE INTO +13197 90F2 BD 00 0C lda NEXTPNT,X ;BY LOOKING AT NEXT POINTER +13198 90F5 85 CD sta CURRENT ;MAKE IT THE CURRENT BUFFER +13199 90F7 AA tax +13200 90F8 AD 70 8F lda WANTED+HI ;LET BUFFER MAP KNOW +13201 90FB 9D 80 0C sta VPAGEH,X ;WHICH PAGE +13202 90FE AD 6F 8F lda WANTED+LO ;IS GOING TO +13203 9101 29 FE and #$FE ; make address be even +13204 9103 9D C0 0C sta VPAGEL,X ;BE THERE +13205 ;*** +13206 ; point to the next page too +13207 ; +13208 9106 09 01 ora #1 ; add one to point to next 256 byte page +13209 9108 48 pha ; save it +13210 9109 8A txa ; get pointer +13211 910A A8 tay ; into y +13212 910B C8 iny ; point to next buffer +13213 910C 68 pla ; get second buffer back +13214 910D 99 C0 0C sta VPAGEL,Y ; so point to it +13215 9110 BD 80 0C lda VPAGEH,X ; get MSB +13216 9113 99 80 0C sta VPAGEH,Y ; and save it +13217 ; +13218 ; A = WANTED+HI +13219 ; Y = WANTED+LO +13220 ; X = BUFFER +13221 ; +13222 9116 AD 6F 8F lda WANTED+LO +13223 9119 29 FE and #$FE ; clear low bit to make it even +13224 911B A8 tay ; want it in y +13225 ;*** +13226 911C AD 70 8F lda WANTED+HI +13227 911F A6 CD ldx CURRENT +13228 9121 20 4E 91 jsr GETVPAGE ; PUT V-PAGE A,Y INTO PAGING BUFFER X +13229 ;*** +13230 9124 CE DF 90 dec MUCKFLG ; INDICATE A MUCKING +13231 9127 D0 1C bne PAGEXIT ; and return current buffer +13232 9129 TOUGH: +13233 9129 29 FE and #$FE ; make even page, please +13234 912B 8D 71 8F sta NEXT +13235 912E C5 CD cmp CURRENT ; GETS REALY SCREWED IF CURRENT==NEXT +13236 9130 F0 13 beq PAGEXIT ; DO NOT CHANGE POINTERS IF IT DOES +13237 ; +13238 ; Y=NEXT(CURRENT) +13239 ; DO THE RIGHT THING TO THE POINTERS +13240 ; +13241 ; ldy CURRENT +13242 ; lda NEXTPNT,Y +13243 ; sta NSUBCUR +13244 9132 AD 71 8F lda NEXT +13245 9135 20 78 91 jsr DETATCH +13246 9138 A4 CD ldy CURRENT +13247 913A AD 71 8F lda NEXT +13248 913D 20 61 91 jsr INSERT +13249 9140 AD 71 8F lda NEXT +13250 9143 85 CD sta CURRENT +13251 9145 PAGEXIT: +13252 ;*** perhaps add one to point to correct buffer +13253 9145 AD 6F 8F lda WANTED+LO ; get LSB +13254 9148 29 01 and #$01 ; pick up even/odd bit +13255 914A 18 clc ; doing add + Wed May 24 1989 15:00 Page 198 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13256 914B 65 CD adc CURRENT ; point to correct buffer +13257 914D 60 rts +13258 +13259 914E GETVPAGE: +13260 914E 8D 5A 6C sta DBLOCK+HI +13261 9151 8C 59 6C sty DBLOCK+LO +13262 9154 8A txa ; get which paging buffer +13263 9155 18 clc +13264 9156 69 08 adc #>PBEGIN ; and set up abs addr +13265 9158 85 B7 sta DBUFF+HI ; thank you, that's much better +13266 915A A2 01 ldx #PB_BANK +13267 915C 86 B8 stx DSKBNK +13268 915E 4C CF 46 jmp GETDSK +13269 +13270 ; INSERT A AFTER Y +13271 ; A.next = Y.next +13272 ; Y.next = A +13273 ; A.previous = Y +13274 ; [Y.next].previous = A +13275 9161 INSERT: +13276 9161 AA tax +13277 9162 B9 00 0C lda NEXTPNT,Y ; Y.next +13278 9165 9D 00 0C sta NEXTPNT,X ; A.next = Y.next +13279 9168 48 pha ; save Y.next for later +13280 9169 8A txa +13281 916A 99 00 0C sta NEXTPNT,Y ; Y.next = A +13282 916D 98 tya +13283 916E 9D 40 0C sta PREVPNT,X ; A.prev = Y +13284 9171 68 pla ; get Y.next back +13285 9172 A8 tay ; [Y.next].previous +13286 9173 8A txa +13287 9174 99 40 0C sta PREVPNT,Y ; [Y.next].previous = A +13288 9177 60 rts +13289 +13290 [01] IF 0 +13291 ; +13292 ; old one, which puts A AFTER! Y +13293 ; +13294 ; PREV(A)=Y +13295 ; PREV(NEXT(Y))=A +13296 ; NEXT(A)=NEXT(Y) +13297 ; NEXT(Y)=A +13298 +13299 sta ATEMP +13300 sty YTEMP +13301 tax +13302 tya +13303 sta PREVPNT,X +13304 +13305 lda NEXTPNT,Y +13306 sta NSUBY +13307 txa +13308 ldx NSUBY +13309 sta PREVPNT,X +13310 +13311 txa +13312 ldx ATEMP +13313 sta NEXTPNT,X +13314 +13315 lda ATEMP +13316 sta NEXTPNT,Y +13317 rts +13318 [00] ENDIF +13319 +13320 ; DETATCH BUFFER >A< +13321 ; NEXT(PREV(A))=NEXT(A) +13322 ; PREV(NEXT(A))=PREV(A) +13323 +13324 9178 DETATCH: +13325 9178 AA tax +13326 9179 BD 00 0C lda NEXTPNT,X +13327 917C A8 tay ; Y == A.next +13328 917D BD 40 0C lda PREVPNT,X ; get A.previous +13329 9180 AA tax ; X == A.previous +13330 9181 98 tya ; get A.next + Wed May 24 1989 15:00 Page 199 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13331 9182 9D 00 0C sta NEXTPNT,X ; [A.previous].next = A.next +13332 9185 8A txa ; get A.previous +13333 9186 99 40 0C sta PREVPNT,Y ; [A.next].previous = A.previous +13334 9189 60 rts +13335 +13336 +13337 ; RETURN BUFFER OF PAGE [WANTED] +13338 ; IN >A< ELSE SEC (Y=WANTED+LO) +13339 +13340 918A A2 17 WHERE: LDX #NUMBUFS-1 +13341 918C WHLOOP: +13342 918C AD 70 8F LDA WANTED+HI +13343 918F DD 80 0C CMP VPAGEH,X ;>SAME +13344 9192 F0 05 BEQ WHGOT +13345 9194 WHNOGOT: +13346 9194 CA DEX +13347 9195 10 F5 BPL WHLOOP +13348 9197 38 SEC +13349 9198 60 RTS +13350 9199 WHGOT: +13351 9199 98 TYA +13352 919A DD C0 0C CMP VPAGEL,X +13353 919D D0 F5 BNE WHNOGOT +13354 919F 8A TXA +13355 91A0 18 CLC +13356 91A1 60 RTS +13357 ; +13358 ; CHECKPRE - check to see if page in [A] is in preloaded +13359 ; +13360 91A2 CHECKPRE: +13361 91A2 C5 C2 cmp TBLPUR ; check against PURE tables +13362 91A4 90 0B bcc CHKPEXY ; must be preloaded then +13363 91A6 CHKP1: +13364 91A6 C5 C3 cmp FUNPRE ; is it in function preload? +13365 91A8 90 09 bcc CHKPEXN ; preloaded function > desired, not preloaded +13366 91AA C5 C4 cmp FUNPUR ; how bout at end? +13367 91AC B0 05 bcs CHKPEXN ; it is not preloaded +13368 91AE CHKP3: +13369 91AE 18 clc ; doing add +13370 91AF 65 C5 adc FUNPGE ; get me memory page for function +13371 91B1 CHKPEXY: +13372 91B1 18 clc ; show it is preloaded +13373 91B2 60 rts ; then we got it +13374 91B3 CHKPEXN: +13375 91B3 38 sec ; show it ain't here +13376 91B4 60 rts +13377 ; +13378 ; INFO_PAGE - is it one of the special preloaded pages for infoDOS? If it +13379 ; is, then set up ZPCPNTR to point to it, and set carry. Otherwise, +13380 ; clear carry to show it ain't. +13381 91B5 IPAGE: ds 2 +13382 91B7 INFO_PAGE: +13383 91B7 A5 82 lda ZPCH ; get 2 parts +13384 91B9 8D B6 91 sta IPAGE+HI +13385 91BC A5 81 lda ZPCM +13386 91BE 8D B5 91 sta IPAGE+LO +13387 91C1 4E B6 91 lsr IPAGE+HI ; /2 to get 512 block +13388 91C4 6E B5 91 ror IPAGE+LO +13389 91C7 A0 08 ldy #SGTSEG ; point to first segment, MSB +13390 91C9 B1 59 lda (INFODOS),Y ; howzit look? +13391 91CB C8 iny ; point to LSB +13392 91CC CD B6 91 cmp IPAGE+HI +13393 91CF 90 0B bcc INFP1 ; might be interesting +13394 91D1 D0 34 bne INFPNX ; not here, < than minimum +13395 91D3 B1 59 lda (INFODOS),Y ; how bout LSB +13396 91D5 CD B5 91 cmp IPAGE+LO +13397 91D8 F0 14 beq INFPYX ; found it +13398 91DA B0 2B bcs INFPNX ; nope, < than minimum again +13399 ; +13400 ; here, it's at least > than minimum +13401 ; +13402 91DC INFP1: +13403 ; iny ; point at end block, MSB +13404 91DC AD A6 6C lda INFODOS_END+HI ; howz end segment look +13405 91DF CD B6 91 cmp IPAGE+HI + Wed May 24 1989 15:00 Page 200 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13406 91E2 90 23 bcc INFPNX ; nope, > than maximum of special +13407 91E4 D0 08 bne INFPYX ; yup, < than maximum of special +13408 ; iny ; LSB of last one +13409 91E6 AD A5 6C lda INFODOS_END+LO ; is LSB < special? +13410 91E9 CD B5 91 cmp IPAGE+LO ; MSB of current one == MSB of special +13411 91EC 90 19 bcc INFPNX ; nope, not here +13412 91EE INFPYX: +13413 91EE A0 09 ldy #SGTSEG+1 ; point back to start block, LSB +13414 91F0 B1 59 lda (INFODOS),Y ; get start block +13415 91F2 0A asl A ; *2 to get start page +13416 91F3 8D B5 91 sta IPAGE+LO ; save it +13417 91F6 A5 81 lda ZPCM +13418 91F8 38 sec ; doing sub +13419 91F9 ED B5 91 sbc IPAGE+LO ; get offset into special block +13420 91FC 18 clc ; now add in offset +13421 91FD 69 D0 adc #>SP_START ; get the start of special area +13422 91FF 85 84 sta ZPCPNT+HI ; show ZPCPNTR +13423 9201 A9 00 lda #SP_BANK ; which bank +13424 9203 85 85 sta ZPCBNK ; okey +13425 9205 38 sec ; show it was here +13426 9206 60 rts +13427 9207 INFPNX: +13428 9207 18 clc ; show not here +13429 9208 60 rts ; g'day +13430 9209 +13431 9209 +13432 9209 +13433 9209 CHKPEXN0: +13434 +13435 9209 GETBYT: +13436 9209 A4 86 ldy MPCL +13437 920B 20 88 92 jsr MFETCH ; go and get it +13438 920E E6 86 inc MPCL ;POINT TO NEXT BYTE +13439 9210 D0 0B bne GETGOT ;IF NO CROSS WE ARE STILL VALID +13440 9212 E6 87 inc MPCM +13441 9214 D0 02 bne GET1 +13442 9216 E6 88 inc MPCH +13443 9218 GET1: +13444 9218 48 pha ; save byte +13445 9219 20 80 90 jsr VLDMPC +13446 921C 68 pla ; and get it back +13447 921D GETGOT: +13448 921D A8 tay ;SET FLAGS +13449 921E 60 rts ;RED SLIPPER TIME +13450 ; +13451 ; NEXTPC - Fetch the byte at the current ZPC, point to next byte and +13452 ; validate pointer +13453 ; +13454 921F NEXTPC: +13455 921F A4 80 ldy ZPCL ; get low pointer +13456 9221 20 70 92 jsr ZFETCH ; fetch @ZPCPNT +13457 9224 E6 80 inc ZPCL +13458 9226 D0 0B bne NXTGOT +13459 9228 E6 81 inc ZPCM +13460 922A D0 02 bne CRSZ1 +13461 922C E6 82 inc ZPCH +13462 922E CRSZ1: +13463 922E 48 pha ; save opcode +13464 922F 20 AA 90 jsr VLDZPC +13465 9232 68 pla ; and get it back +13466 9233 NXTGOT: +13467 9233 A8 tay +13468 9234 60 rts +13469 +13470 ; +13471 ; STASHB - use SPC to save a byte in either aux or main mem +13472 ; +13473 9235 STASHB: +13474 9235 A4 91 ldy SPCBNK ; get the bank +13475 9237 30 09 bmi SB1 ; must be in upper RAM +13476 9239 99 04 C0 sta WRTBNK,Y ; set bank +13477 923C A0 00 ldy #0 ; can only do this with Y +13478 923E 91 8F sta (SPC),Y ; get the sucker +13479 9240 F0 10 beq SBEXI ; jump to end it +13480 ; + Wed May 24 1989 15:00 Page 201 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13481 ; this is in aux mem, >$E000 +13482 ; +13483 9242 SB1: +13484 9242 A4 90 ldy SPCH ; get high part +13485 9244 8C 4E 92 sty SBMOD+2 ; and self mod my code +13486 9247 A4 8F ldy SPCL ; and get the low part +13487 9249 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13488 924C SBMOD: +13489 924C 99 00 D0 sta Z3BEGIN,Y ; store the little byte +13490 924F 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13491 9252 SBEXI: +13492 9252 8D 04 C0 sta WRTBNK+MAIN ; and write to main +13493 9255 60 rts +13494 ; +13495 ; FETCHB - fetch a byte from either main memory, aux memory, or upper +13496 ; Aux memory +13497 ; +13498 9256 FETCHB: +13499 9256 A4 8E ldy FPCBNK ; get the bank +13500 9258 30 04 bmi FB1 ; must be in upper RAM +13501 925A 20 D1 00 jsr ZERO_FB ; go to low end fetch +13502 925D 60 rts +13503 ; +13504 ; this is in aux mem, >$E000 +13505 ; +13506 925E FB1: +13507 925E A5 8D lda FPCH ; get which page +13508 9260 8D 6A 92 sta FBMOD+2 ; and show in operand +13509 9263 A4 8C ldy FPCL ; get which byte +13510 9265 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13511 9268 B9 00 D0 FBMOD: lda Z3BEGIN,Y ; get the sucker +13512 926B 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13513 926E A8 tay ; set condition code +13514 926F 60 rts +13515 ; +13516 ; ZFETCH - after checking for which bank (main, aux 1 or aux 2), go get +13517 ; the byte @ ZPCPNT, with the offset being in [Y] +13518 ; +13519 9270 ZFETCH: +13520 9270 A6 85 ldx ZPCBNK ; get the bank +13521 9272 30 04 bmi ZFB1 ; must be in upper RAM +13522 9274 20 DC 00 jsr ZERO_ZF ; go to low end fetch +13523 9277 60 rts +13524 ; +13525 ; this is in aux mem, >$D000 +13526 ; +13527 9278 ZFB1: +13528 9278 A5 84 lda ZPNTH ; which page are we talking about +13529 927A 8D 82 92 sta ZBMOD+2 ; show in the operand +13530 927D 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13531 9280 B9 00 D0 ZBMOD: lda Z3BEGIN,Y ; get the sucker +13532 9283 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13533 9286 AA tax ; set condition code +13534 9287 60 rts +13535 ; +13536 ; MFETCH - after checking for which bank (main, aux 1 or aux 2), go get +13537 ; the byte @MPCPNT, with the offset being in [Y] +13538 ; +13539 9288 MFETCH: +13540 9288 A6 8B ldx MPCBNK ; get the bank +13541 928A 30 04 bmi MB1 ; must be in upper RAM +13542 928C 20 E5 00 jsr ZERO_MF ; go to low end fetch +13543 928F 60 rts +13544 ; +13545 ; this is in aux mem, >$D000 +13546 ; +13547 9290 MB1: +13548 9290 A5 8A lda MPNTH ; which page are we talking about +13549 9292 8D 9A 92 sta MBMOD+2 ; show in the operand +13550 9295 8D 09 C0 sta ALTZP+AUX ; talk about aux mem +13551 +13552 9298 B9 00 D0 MBMOD: lda Z3BEGIN,Y ; get the sucker +13553 +13554 929B 8D 08 C0 sta ALTZP+MAIN ; go back to main mem +13555 929E AA tax ; set condition code + Wed May 24 1989 15:00 Page 202 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13556 929F 60 rts +13557 +13558 +13559 92A0 END +13560 +13561 92A0 INCLUDE ZSTRING.ASM +13562 PAGE + Wed May 24 1989 15:00 Page 203 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- MEMORY PAGING ROUTINES ---" + +13563 92A0 STTL "--- Z-STRING HANDLERS ---" +13564 +13565 ; ----------------------- +13566 ; POINT MPC TO ZSTRING IN [I], using SOFF +13567 ; ----------------------- +13568 +13569 92A0 SETSTR: +13570 92A0 A5 78 lda I+LO +13571 92A2 85 86 sta MPCL ; save in lo part +13572 92A4 A5 79 lda I+HI +13573 92A6 85 87 sta MPCM ; middle part +13574 92A8 A9 00 lda #0 ; clear hi part +13575 92AA 85 88 sta MPCH ; okay, we did +13576 92AC 06 86 asl MPCL ; *2 +13577 92AE 26 87 rol MPCM +13578 92B0 26 88 rol MPCH +13579 92B2 06 86 asl MPCL ; *4 +13580 92B4 26 87 rol MPCM +13581 92B6 26 88 rol MPCH +13582 ; +13583 ; now add the offset +13584 ; +13585 92B8 A5 86 lda MPCL ; carry clear from above +13586 92BA 65 60 adc SOFFL ; add lo part of offset +13587 92BC 85 86 sta MPCL ; save +13588 92BE A5 87 lda MPCM +13589 92C0 65 5F adc SOFFM +13590 92C2 85 87 sta MPCM +13591 92C4 A5 88 lda MPCH +13592 92C6 65 5E adc SOFFH +13593 92C8 85 88 sta MPCH +13594 92CA 4C 80 90 jmp VLDMPC ; make MPCPNT to it +13595 +13596 +13597 92CD 60 ZSTEX: RTS +13598 +13599 ; ----------------------- +13600 ; PRINT Z-STRING AT [MPC] +13601 ; ----------------------- +13602 92CE PZSTR: +13603 92CE A2 00 ldx #0 +13604 92D0 86 96 stx PSET ; ASSUME PERMANENT CHARSET +13605 92D2 86 9A stx ZFLAG ; CLEAR BYTE FLAG +13606 92D4 CA dex ; = $FF +13607 92D5 86 97 stx TSET ; NO TEMPSET ACTIVE +13608 92D7 PZTOP: +13609 92D7 20 CA 93 jsr GETZCH ; GET A Z-CHAR +13610 92DA B0 F1 bcs ZSTEX ; END OF STRING IF CARRY IS SET +13611 92DC 85 98 sta ZCHAR ; ELSE SAVE CHAR HERE +13612 92DE AA tax ; SET FLAGS +13613 92DF F0 45 beq BLANK ; PRINT SPACE IF CHAR = 0 +13614 92E1 C9 04 cmp #4 ; IS THIS AN F-WORD? +13615 92E3 90 5F bcc DOFREQ ; APPARENTLY SO +13616 92E5 C9 06 cmp #6 ; PERHAPS A SHIFT CODE? +13617 92E7 90 41 bcc NEWSET ; YES, CHANGE CHARSETS +13618 92E9 20 AC 93 jsr GETSET ; ELSE GET CHARSET +13619 92EC AA tax ; SET FLAGS +13620 92ED D0 14 bne SET1 ; SKIP IF NOT CHARSET #0 +13621 ; +13622 ; PRINT A LOWER-CASE CHAR (CHARSET #0) +13623 ; +13624 92EF A9 FA lda #$FA ; what to add to get offset into char table +13625 92F1 TOASC: +13626 92F1 8D F8 92 sta TOASCM+1 ; modify code +13627 92F4 A5 98 lda ZCHAR ; use char as offset +13628 92F6 18 clc ; make char be an index +13629 92F7 69 06 TOASCM: adc #6 ; we just did +13630 92F9 AA tax ; now use as index +13631 92FA BD 8C 1F lda CHARSET,X ; go get that char in charset zero +13632 92FD SHOVE: +13633 92FD 20 06 53 jsr COUT ; SHOW THE CHAR +13634 9300 4C D7 92 jmp PZTOP ; AND GRAB NEXT CHAR +13635 ; +13636 ; PRINT AN UPPER-CASE CHAR (CHARSET #1) +13637 ; + Wed May 24 1989 15:00 Page 204 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13638 9303 SET1: +13639 9303 C9 01 cmp #1 ; make sure it's set #1 +13640 9305 D0 04 bne SET2 ; else must be set #2 +13641 9307 A9 14 lda #20 ; skip into Charset 1 part of table +13642 9309 D0 E6 bne TOASC ; fix just like the others +13643 ; +13644 ; PRINT FROM CHARSET #2 +13645 ; +13646 930B SET2: +13647 930B A5 98 lda ZCHAR ; retrieve the z-char +13648 930D C9 06 cmp #6 ; is it a special ascii char? +13649 930F F0 04 beq DIRECT ; yes, so do it special +13650 9311 A9 2E lda #46 ; nothing special, just get offset +13651 9313 D0 DC bne TOASC ; and jump +13652 ; +13653 ; DECODE A "DIRECT" ASCII CHAR +13654 ; +13655 9315 DIRECT: +13656 9315 20 CA 93 jsr GETZCH ; FETCH NEXT Z-CHAR +13657 9318 0A asl A +13658 9319 0A asl A +13659 931A 0A asl A +13660 931B 0A asl A +13661 931C 0A asl A ; SHIFT INTO POSITION +13662 931D 85 98 sta ZCHAR ; AND SAVE HERE +13663 931F 20 CA 93 jsr GETZCH ; GRAB YET ANOTHER Z-CHAR +13664 9322 05 98 ora ZCHAR ; SUPERIMPOSE THE 2ND BYTE +13665 9324 D0 D7 bne SHOVE ; AND PRINT THE RESULT +13666 ; +13667 ; PRINT A SPACE +13668 ; +13669 9326 BLANK: +13670 9326 A9 20 lda #SPACE ; ASCII SPACE CHAR +13671 9328 D0 D3 bne SHOVE +13672 +13673 ; CHANGE CHARSET +13674 +13675 932A 38 NEWSET: SEC ; CONVERT THE SHIFT CODE +13676 932B E9 03 SBC #3 ; TO 1 OR 2 +13677 932D A8 TAY +13678 932E 20 AC 93 JSR GETSET ; IS MODE TEMPORARY? +13679 9331 D0 05 BNE TOPERM ; YES, DO A PERMSHIFT +13680 9333 84 97 STY TSET ; ELSE JUST A TEMPSHIFT +13681 9335 4C D7 92 JMP PZTOP ; AND CONTINUE +13682 9338 84 96 TOPERM: STY PSET ; SET PERM CHARSET +13683 933A C5 96 CMP PSET ; SAME AS BEFORE? +13684 933C F0 99 BEQ PZTOP ; YES, CONTINUE +13685 933E A9 00 LDA #0 +13686 9340 85 96 STA PSET ; ELSE RESET CHARSET +13687 9342 F0 93 BEQ PZTOP ; BEFORE LOOPING BACK +13688 +13689 ; PRINT AN F-WORD +13690 +13691 9344 38 DOFREQ: SEC +13692 9345 E9 01 SBC #1 ; ZERO-ALIGN THE CODE +13693 9347 0A ASL A ; AND MULTIPLY TIMES 64 +13694 9348 0A ASL A ; TO OBTAIN THE SEGMENT OFFSET +13695 9349 0A ASL A ; INTO THE F-WORDS TABLE +13696 934A 0A ASL A +13697 934B 0A ASL A +13698 934C 0A ASL A +13699 934D 85 99 STA OFFSET ; SAVE OFFSET FOR LATER +13700 934F 20 CA 93 JSR GETZCH ; NOW GET THE F-WORD POINTER +13701 9352 0A ASL A ; WORD-ALIGN IT +13702 9353 18 CLC ; AND +13703 9354 65 99 ADC OFFSET ; ADD THE SEGMENT OFFSET +13704 ; +13705 ; set up FPC to point to FWORDS table +13706 ; +13707 9356 A6 57 ldx FWORDS+ABANK +13708 9358 86 8E stx FPCBNK +13709 935A A6 56 ldx FWORDS+HI +13710 935C 86 8D stx FPCH +13711 935E A6 55 ldx FWORDS+LO +13712 9360 86 8C stx FPCL + Wed May 24 1989 15:00 Page 205 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13713 9362 20 DE 8F jsr ADDFPC ; add offset of the F-word +13714 9365 20 56 92 jsr FETCHB ; and get MSB of F-word +13715 9368 85 79 sta I+HI ; and save it +13716 936A 20 BE 8F jsr NEXTFPC ; and point to LSB +13717 936D 20 56 92 jsr FETCHB ; and get it +13718 9370 85 78 sta I+LO ; and save it +13719 ; +13720 ; SAVE THE STATE OF CURRENT Z-STRING +13721 ; +13722 9372 A5 88 LDA MPCH +13723 9374 48 PHA +13724 9375 A5 87 LDA MPCM +13725 9377 48 PHA +13726 9378 A5 86 LDA MPCL +13727 937A 48 PHA +13728 937B A5 96 LDA PSET +13729 937D 48 PHA +13730 937E A5 9A LDA ZFLAG +13731 9380 48 PHA +13732 9381 A5 9C LDA ZWORD+HI +13733 9383 48 PHA +13734 9384 A5 9B LDA ZWORD+LO +13735 9386 48 PHA +13736 9387 20 B8 93 JSR SETFWD ; PRINT THE Z-STRING +13737 938A 20 CE 92 JSR PZSTR ; IN [I] +13738 ; +13739 ; RESTORE OLD Z-STRING +13740 ; +13741 938D 68 PLA +13742 938E 85 9B STA ZWORD+LO +13743 9390 68 PLA +13744 9391 85 9C STA ZWORD+HI +13745 9393 68 PLA +13746 9394 85 9A STA ZFLAG +13747 9396 68 PLA +13748 9397 85 96 STA PSET +13749 9399 68 PLA +13750 939A 85 86 STA MPCL +13751 939C 68 PLA +13752 939D 85 87 STA MPCM +13753 939F 68 PLA +13754 93A0 85 88 STA MPCH +13755 93A2 A2 FF LDX #$FF +13756 93A4 86 97 STX TSET ; DISABLE TEMP CHARSET +13757 93A6 20 80 90 JSR VLDMPC +13758 93A9 4C D7 92 JMP PZTOP ; CONTINUE INNOCENTLY +13759 +13760 +13761 ; ---------------------- +13762 ; RETURN CURRENT CHARSET +13763 ; ---------------------- +13764 +13765 93AC A5 97 GETSET: LDA TSET +13766 93AE 10 03 BPL GS +13767 93B0 A5 96 LDA PSET +13768 93B2 60 RTS +13769 93B3 A0 FF GS: LDY #$FF +13770 93B5 84 97 STY TSET +13771 93B7 60 RTS +13772 +13773 +13774 ; ------------------------- +13775 ; POINT [I] AT FWORD STRING +13776 ; ------------------------- +13777 +13778 93B8 A5 78 SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS +13779 93BA 0A ASL A +13780 93BB 85 86 STA MPCL +13781 93BD A5 79 LDA I+HI +13782 93BF 2A ROL A +13783 93C0 85 87 STA MPCM +13784 93C2 A9 00 LDA #0 +13785 93C4 2A ROL A +13786 93C5 85 88 STA MPCH +13787 93C7 4C 80 90 JMP VLDMPC + Wed May 24 1989 15:00 Page 206 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13788 +13789 +13790 ; ----------------- +13791 ; FETCH NEXT Z-CHAR +13792 ; ----------------- +13793 +13794 93CA A5 9A GETZCH: LDA ZFLAG ; WHICH BYTE IS THIS? +13795 93CC 10 02 BPL GTZ0 ; $FF = LAST +13796 93CE 38 SEC ; SET CARRY TO INDICATE +13797 93CF 60 RTS ; NO MORE CHARS +13798 93D0 D0 13 GTZ0: BNE GETZ1 ; NOT FIRST CHAR, EITHER +13799 +13800 ; GET A Z-WORD INTO [ZWORD], RETURN 1ST CHAR IN TRIPLET +13801 +13802 93D2 E6 9A INC ZFLAG ; UPDATE CHAR COUNT +13803 93D4 20 09 92 JSR GETBYT ; GET TRIPLET AT [MPC] +13804 93D7 85 9C STA ZWORD+HI ; INTO [ZWORD] +13805 93D9 20 09 92 JSR GETBYT +13806 93DC 85 9B STA ZWORD+LO +13807 93DE A5 9C LDA ZWORD+HI +13808 93E0 4A LSR A +13809 93E1 4A LSR A ; SHIFT 1ST CHAR INTO PLACE +13810 93E2 4C 0E 94 JMP GTEXIT ; AND RETURN IT +13811 93E5 38 GETZ1: SEC +13812 93E6 E9 01 SBC #1 +13813 93E8 D0 16 BNE GETZ2 ; LAST CHAR IN TRIPLET IF ZERO +13814 93EA A9 02 LDA #2 ; ELSE +13815 93EC 85 9A STA ZFLAG ; RESET CHAR INDEX +13816 93EE A5 9B LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET +13817 93F0 85 78 STA I+LO ; MOVE HERE FOR SHIFTING +13818 93F2 A5 9C LDA ZWORD+HI ; GET TOP HALF +13819 93F4 06 78 ASL I+LO ; SHIFT THE TOP 3 BITS OF LOWER HALF +13820 93F6 2A ROL A ; INTO THE BOTTOM OF THE TOP HALF +13821 93F7 06 78 ASL I+LO +13822 93F9 2A ROL A +13823 93FA 06 78 ASL I+LO +13824 93FC 2A ROL A +13825 93FD 4C 0E 94 JMP GTEXIT +13826 9400 A9 00 GETZ2: LDA #0 ; SET FLAG TO INDICATE +13827 9402 85 9A STA ZFLAG ; END OF TRIPLET +13828 9404 A5 9C LDA ZWORD+HI ; TEST TOP HALF OF TRIPLET +13829 9406 10 04 BPL GETZ3 ; CONTINUE IF NOT END OF STRING +13830 9408 A9 FF LDA #$FF ; ELSE +13831 940A 85 9A STA ZFLAG ; INDICATE LAST TRIPLET IN STRING +13832 940C A5 9B GETZ3: LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET +13833 940E 29 1F GTEXIT: AND #%00011111 ; MASK OUT GARBAGE BITS +13834 9410 18 CLC +13835 9411 60 RTS +13836 +13837 +13838 ; --------------------------------- +13839 ; CONVERT [IN] TO Z-STRING IN [OUT] +13840 ; --------------------------------- +13841 9412 CONZST: +13842 9412 A9 05 lda #5 ; FILL OUTPUT BUFFER +13843 9414 A2 08 ldx #8 ; WITH PAD CHARS ($05) +13844 9416 CZSL: +13845 9416 9D 99 6C sta OUT,X +13846 9419 CA dex +13847 941A 10 FA bpl CZSL +13848 +13849 941C A9 09 lda #9 ; INIT +13850 941E 85 9D sta CONCNT ; CHAR COUNT +13851 9420 A9 00 lda #0 ; CLEAR +13852 9422 85 9E sta CONIN ; SOURCE AND +13853 9424 85 9F sta CONOUT ; OUTPUT INDEXES +13854 9426 CONTOP: +13855 9426 A6 9E ldx CONIN ; fetch source index +13856 9428 E6 9E inc CONIN ; and update +13857 942A BD 90 6C lda IN,X ; grab an ascii char +13858 942D 85 98 sta ZCHAR ; save it here +13859 942F D0 04 bne NEXTZ ; continue if char was nz +13860 9431 A9 05 lda #5 ; else ship out +13861 9433 D0 27 bne CSHIP1 ; a pad char +13862 9435 NEXTZ: + Wed May 24 1989 15:00 Page 207 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13863 9435 20 61 94 jsr FINDCHAR ; find out where it tis +13864 9438 F0 21 beq CSHIP ; no shift for charset zero +13865 943A 18 clc ; else do a temp-shift +13866 943B 69 03 adc #3 ; 4 = charset 1, 5 = charset 2 +13867 943D 20 8F 94 jsr CSTASH ; save the char in outbuf +13868 9440 C9 05 cmp #5 ; charset 2? +13869 9442 D0 17 bne CSHIP ; nope +13870 9444 E0 06 cpx #6 ; ascii escape? +13871 9446 D0 13 bne CSHIP ; nope +13872 ; +13873 ; Handle special Ascii escape sequence +13874 ; +13875 9448 8A txa ; get ASCII alert char (#6) +13876 9449 20 8F 94 jsr CSTASH ; shove it away +13877 ; +13878 ; do 1st half of "direct" +13879 ; +13880 944C A5 98 lda ZCHAR ; re-fetch char +13881 944E 4A lsr A ; get upper 2 bits in lower 2 bits +13882 944F 4A lsr A +13883 9450 4A lsr A +13884 9451 4A lsr A +13885 9452 4A lsr A +13886 9453 20 8F 94 jsr CSTASH +13887 ; +13888 ; SEND 2ND HALF OF "DIRECT" +13889 ; +13890 9456 A5 98 lda ZCHAR ; get char yet again +13891 9458 29 1F and #%00011111 ; and get lower 5 bits +13892 945A AA tax ; this is where it is expected +13893 ; +13894 ; SHIP Z-CHAR TO OUTPUT BUFFER +13895 ; +13896 945B CSHIP: +13897 945B 8A txa ; get char +13898 945C CSHIP1: +13899 945C 20 8F 94 jsr CSTASH ; put char away +13900 945F D0 C5 bne CONTOP ; do again +13901 ; +13902 ; FINDCHAR - look through the charset table for the character. If found, +13903 ; figger out which shift it is. If not found, return charset 2, +13904 ; character #6. +13905 ; Enter: +13906 ; [A] = Char we are looking for +13907 ; Returns: +13908 ; [A] = Charset (0-2) +13909 ; [X] = Character # (6-31) +13910 ; +13911 9461 FINDCHAR: +13912 9461 A2 00 ldx #0 ; start at first char, first set +13913 9463 A0 4E ldy #78 ; there are 78 characters +13914 9465 FNDCL: +13915 9465 DD 8C 1F cmp CHARSET,X ; found it? +13916 9468 F0 09 beq FNDCLX ; yes +13917 946A E8 inx ; next char +13918 946B 88 dey ; count char +13919 946C D0 F7 bne FNDCL ; go check next char +13920 ; +13921 ; not found in table, use ASCII escape sequence +13922 ; +13923 946E A9 02 lda #2 ; escape sequence is char set 2 +13924 9470 A2 06 ldx #6 ; character 6 +13925 9472 60 rts ; and done +13926 9473 FNDCLX: +13927 9473 8A txa ; put here for compares/action +13928 9474 A0 00 ldy #0 ; this is char set 0 +13929 9476 A2 FA ldx #$FA ; what to "subtract" to get +6 +13930 9478 C9 1A cmp #26 ; how we doin'? +13931 947A 90 0A bcc FNDCHX ; all done +13932 947C C8 iny ; char set 1 +13933 947D A2 14 ldx #20 ; char set 1 offset +13934 947F C9 34 cmp #52 ; well? +13935 9481 90 03 bcc FNDCHX ; must be char set 1 +13936 9483 A2 2E ldx #46 ; for char set 2 setting up +13937 9485 C8 iny ; must be char set 2 then + Wed May 24 1989 15:00 Page 208 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- Z-STRING HANDLERS ---" + +13938 9486 FNDCHX: +13939 9486 8E 8B 94 stx FNDCHM+1 ; what to subtract to get offset +13940 9489 38 sec ; doing subtract +13941 948A E9 06 FNDCHM: sbc #6 ; make good offset +13942 948C AA tax ; put here for return +13943 948D 98 tya ; and here to set flag +13944 948E 60 rts +13945 ; +13946 ; CSTASH - put the char in OUT. If we run out of room don't return, just +13947 ; jump to ZCRUSH as final destination +13948 ; [A] - char to be put away +13949 ; +13950 948F CSTASH: +13951 948F A4 9F ldy CONOUT ; fetch output index +13952 9491 99 99 6C sta OUT,Y ; send the shift char +13953 9494 E6 9F inc CONOUT ; update index +13954 9496 C6 9D dec CONCNT ; and char count +13955 9498 D0 05 bne CSTX ; plenty more room +13956 949A 68 pla ; get rid of return spot +13957 949B 68 pla ; fine +13958 949C 4C A0 94 jmp ZCRUSH ; if out of room, crush 'em! +13959 949F CSTX: +13960 949F 60 rts +13961 ; ---------------------- +13962 ; CRUSH Z-CHARS IN [OUT], mushing them into small 5 bit pieces +13963 ; ---------------------- +13964 94A0 ZCRUSH: +13965 94A0 AD 9A 6C LDA OUT+1 ; GET 2ND Z-CHAR +13966 94A3 0A ASL A ; SHIFT BITS INTO POSITION +13967 94A4 0A ASL A +13968 94A5 0A ASL A +13969 94A6 0A ASL A +13970 94A7 2E 99 6C ROL OUT ; ALONG WITH 1ST Z-CHAR +13971 94AA 0A ASL A +13972 94AB 2E 99 6C ROL OUT +13973 94AE 0D 9B 6C ORA OUT+2 ; SUPERIMPOSE 3RD Z-CHAR +13974 94B1 8D 9A 6C STA OUT+1 +13975 94B4 AD 9D 6C LDA OUT+4 ; GET 5TH Z-CHAR +13976 94B7 0A ASL A ; SHIFT BITS +13977 94B8 0A ASL A +13978 94B9 0A ASL A +13979 94BA 0A ASL A +13980 94BB 2E 9C 6C ROL OUT+3 ; ALONG WITH 4TH Z-CHAR +13981 94BE 0A ASL A +13982 94BF 2E 9C 6C ROL OUT+3 +13983 94C2 0D 9E 6C ORA OUT+5 ; SUPERIMPOSE 6TH Z-CHAR +13984 94C5 AA TAX ; SAVE HERE +13985 94C6 AD 9C 6C LDA OUT+3 ; GRAB 4TH Z-CHAR +13986 94C9 8D 9B 6C STA OUT+2 ; MOVE CRUSHED Z-WORD +13987 94CC 8E 9C 6C STX OUT+3 ; INTO PLACE +13988 94CF AD A0 6C LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) +13989 94D2 0A ASL A ; SHIFT BITS +13990 94D3 0A ASL A +13991 94D4 0A ASL A +13992 94D5 0A ASL A +13993 94D6 2E 9F 6C ROL OUT+6 ; ALONG WITH 7TH Z-CHAR +13994 94D9 0A ASL A +13995 94DA 2E 9F 6C ROL OUT+6 +13996 94DD 0D A1 6C ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR +13997 94E0 8D 9E 6C STA OUT+5 ; SAVE HERE +13998 94E3 AD 9F 6C LDA OUT+6 ; GRAB 7TH Z-CHAR +13999 94E6 09 80 ORA #%10000000 ; SET HIGH BIT +14000 94E8 8D 9D 6C STA OUT+4 ; MOVE CRUSHED Z-WORD INTO PLACE +14001 94EB 60 RTS +14002 +14003 94EC END +14004 +14005 94EC INCLUDE OBJECTS.ASM +14006 94EC STTL "--- OBJECT & PROPERTY HANDLERS ---" +14007 PAGE + Wed May 24 1989 15:00 Page 209 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + +14008 +14009 ; ---------------------------------- +14010 ; GET ABSOLUTE ADDRESS OF OBJECT [A] +14011 ; ---------------------------------- +14012 ; ENTER: OBJECT IN A/X (LO/HI) +14013 ; EXIT: ADDRESS IN [FPC] +14014 94EC OBJLOC: +14015 94EC 86 79 STX I+HI ; SAVE MSB FOR SHIFTING +14016 94EE 0A ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) +14017 94EF 85 78 STA I+LO +14018 94F1 26 79 ROL I+HI +14019 94F3 A6 79 LDX I+HI +14020 94F5 0A ASL A +14021 94F6 26 79 ROL I+HI ; *4 +14022 94F8 0A ASL A +14023 94F9 26 79 ROL I+HI ; *8 +14024 94FB 0A ASL A +14025 94FC 26 79 ROL I+HI ; *16 +14026 94FE 38 SEC +14027 94FF E5 78 SBC I+LO ; -(*2) +14028 9501 85 78 STA I+LO ; SO IS *14 TOTAL +14029 9503 A5 79 LDA I+HI +14030 9505 86 79 STX I+HI +14031 9507 E5 79 SBC I+HI +14032 9509 85 79 STA I+HI +14033 950B A5 78 LDA I+LO +14034 950D 18 CLC +14035 950E 69 70 ADC #112 ; ADD OBJECT TABLE OFFSET +14036 9510 90 02 BCC OBJ3 +14037 9512 E6 79 INC I+HI +14038 9514 OBJ3: +14039 9514 18 clc ; NEXT ADD THE relative ADDR +14040 9515 6D 0B 96 adc ZBEGIN+ZOBJEC+1 ; OF THE OBJECT TABLE +14041 9518 85 8C sta FPCL ; save lo byte +14042 951A A5 79 lda I+HI +14043 951C 6D 0A 96 adc ZBEGIN+ZOBJEC ; now work on page +14044 951F 20 77 8F jsr SETPC ; now get page/bank +14045 9522 85 8D sta FPCH ; this is hi part +14046 9524 84 8E sty FPCBNK ; and this is the bank +14047 9526 60 rts +14048 ; ----------------------------- +14049 ; GET ADDRESS OF PROPERTY TABLE +14050 ; ----------------------------- +14051 ; EXIT: [FPC] HAS ABSOLUTE ADDR OF PROPERTY TABLE +14052 ; including OFFSET TO START OF PROP IDS +14053 9527 PROPB: +14054 9527 A5 63 lda ARG1+LO +14055 9529 A6 64 ldx ARG1+HI ; get address +14056 952B 20 EC 94 jsr OBJLOC ; put table location into FPC +14057 952E A9 0C lda #12 ; add 12 to get to beginning +14058 9530 20 DE 8F jsr ADDFPC ; and add it to FPC +14059 9533 20 56 92 jsr FETCHB ; get MSB of P-TABLE Address +14060 9536 48 pha ; and save it for a moment +14061 9537 20 BE 8F jsr NEXTFPC ; to get LSB +14062 953A 20 56 92 jsr FETCHB ; get LSB of P-TABLE Address +14063 953D 85 8C sta FPCL ; and save lo part +14064 953F 68 pla ; get page back +14065 9540 20 77 8F jsr SETPC ; and set up memory bank/page +14066 9543 85 8D sta FPCH ; save page +14067 9545 84 8E sty FPCBNK ; and bank +14068 9547 20 56 92 jsr FETCHB ; get length of short description +14069 954A 0A asl A ; WORD-ALIGN IT +14070 954B 20 DE 8F jsr ADDFPC ; and add it to FPC +14071 954E 20 BE 8F jsr NEXTFPC ; POINT JUST PAST THE DESCRIPTION +14072 9551 60 rts +14073 +14074 +14075 ; ------------------- +14076 ; FETCH A PROPERTY ID +14077 ; ------------------- +14078 ; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +14079 ; +14080 9552 PROPN: +14081 9552 20 56 92 jsr FETCHB ; get the byte +14082 9555 29 3F and #%00111111 ; MASK OUT LENGTH BITS (EZIP) + Wed May 24 1989 15:00 Page 210 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + +14083 9557 60 rts +14084 +14085 ; ------------------------------- +14086 ; FETCH # BYTES IN PROPERTY VALUE +14087 ; ------------------------------- +14088 ; ENTRY: LIKE "PROPB" EXIT (i.e. - address in FPC) +14089 ; +14090 9558 PROPL: +14091 9558 20 56 92 jsr FETCHB ; CHECK LENGTH FLAGS +14092 955B AA tax ; save it +14093 955C 10 09 bpl SHORT ; OFF, SO 1 OR 2 BYTES +14094 955E 20 BE 8F jsr NEXTFPC +14095 9561 20 56 92 jsr FETCHB ; NEXT BYTE HAS LENGTH +14096 9564 29 3F and #%00111111 ; MASK OFF EXTRA BITS +14097 9566 60 rts +14098 9567 SHORT: +14099 9567 29 40 and #%01000000 ; BIT 6 +14100 9569 F0 03 beq ONE +14101 956B A9 02 lda #2 ; BIT 6 = 1, LENGTH =2 +14102 956D 60 rts +14103 956E ONE: +14104 956E A9 01 lda #1 ; BIT 6 = 0, LENGTH =1 +14105 9570 60 rts +14106 +14107 ; ---------------------- +14108 ; POINT TO NEXT PROPERTY +14109 ; ---------------------- +14110 ; ENTRY: LIKE "PROPB" EXIT (i.e. - in [FPC]) +14111 ; +14112 9571 PROPNX: +14113 9571 20 58 95 jsr PROPL ; GET LENGTH OF CURRENT PROP +14114 9574 A8 tay ; move one more for correct alignment +14115 9575 C8 iny ; okay, done it +14116 9576 98 tya ; thanks +14117 9577 20 DE 8F jsr ADDFPC ; add to [FPC] +14118 957A 60 rts +14119 ; +14120 ; ---------------- +14121 ; GET OBJECT FLAGS +14122 ; ---------------- +14123 ; ENTRY: OBJECT # IN [ARG1], FLAG # IN [ARG2] +14124 ; EXIT: FLAG WORD IN [K], BIT ID IN [J], +14125 ; FLAG WORD ADDRESS IN [FPC] +14126 ; +14127 957B FLAGSU: +14128 957B A5 63 LDA ARG1+LO ; get table offset +14129 957D A6 64 LDX ARG1+HI +14130 957F 20 EC 94 JSR OBJLOC ; GET OBJECT ADDR IN [FPC] +14131 9582 A5 65 LDA ARG2+LO ; LOOK AT FLAG ID +14132 9584 C9 10 CMP #$10 ; FIRST SET OF FLAGS? +14133 9586 90 14 BCC FLS1 ; YES, ADDR IN [FPC] IS CORRECT +14134 9588 E9 10 SBC #16 ; ELSE ZERO-ALIGN FLAG INDEX +14135 958A AA TAX ; SAVE IT HERE +14136 958B C9 10 CMP #$10 ; CHECK IF IN 2ND WORD +14137 958D 90 07 BCC FLS ; YES, GO ALIGN FOR THAT +14138 958F E9 10 SBC #16 ; ELSE ALIGN TO 3RD WORD +14139 9591 AA TAX +14140 9592 A9 04 lda #4 ; 3rd Flag word +14141 9594 D0 02 bne FLSx ; and add it in +14142 9596 FLS: +14143 9596 A9 02 lda #2 ; 2nd Flag word +14144 9598 FLSx: +14145 9598 20 DE 8F jsr ADDFPC +14146 959B FLS0: +14147 959B 8A TXA ; RESTORE INDEX +14148 959C FLS1: +14149 959C 85 7C STA K+LO ; SAVE FLAG ID HERE +14150 959E A2 01 LDX #1 ; INIT THE +14151 95A0 86 7A STX J+LO ; FLAG WORD TO +14152 95A2 CA DEX ; $0001 +14153 95A3 86 7B STX J+HI +14154 95A5 A9 0F LDA #15 ; SUBTRACT THE BIT POSITION +14155 95A7 38 SEC ; FROM 15 +14156 95A8 E5 7C SBC K+LO ; TO GET THE SHIFT LOOP +14157 95AA AA TAX ; INDEX + Wed May 24 1989 15:00 Page 211 + + "APPLE YZIP (c)Infocom, Inc.. --- OP SUPPORT & MEMORY MANAGEMENT" + "--- OBJECT & PROPERTY HANDLERS ---" + +14158 95AB F0 07 BEQ FLS2 ; EXIT NOW IF NO SHIFT NEEDED +14159 95AD 06 7A FLSL: ASL J+LO ; SHIFT THE BIT +14160 95AF 26 7B ROL J+HI ; INTO POSITION +14161 95B1 CA DEX +14162 95B2 D0 F9 BNE FLSL +14163 95B4 FLS2: +14164 95B4 20 56 92 jsr FETCHB ; MOVE THE FLAG WORD +14165 95B7 85 7D sta K+HI ; INTO [K] - FIRST THE MSB +14166 95B9 20 BE 8F jsr NEXTFPC ; and then get get LSB +14167 95BC 20 56 92 jsr FETCHB +14168 95BF 85 7C sta K+LO ; THEN THE LSB +14169 95C1 4C 24 90 jmp PREVFPC ; point back to flag word +14170 +14171 95C4 END +14172 +14173 +14174 95C4 BLKB ZBEGIN-$,0 +14175 9600 END + + + + Lines Assembled : 14175 Assembly Errors : 0 + + + \ No newline at end of file diff --git a/apple/yzip/rel.9/zbegin.asm b/apple/yzip/rel.9/zbegin.asm new file mode 100644 index 0000000..0f6ff06 --- /dev/null +++ b/apple/yzip/rel.9/zbegin.asm @@ -0,0 +1,100 @@ + STTL "--- START OF APPLE ][ INTERPRETER ---" + PAGE + + ORG INTR_BEGIN +; +; Set up for Double HiRes full screen graphics +; + lda PAGE2SW+OFF ; turn off page 2 + sta TEXTSW+OFF ; turn off text - turn on graphics + sta HIRESSW+ON ; turn on high resolution + sta MIXEDSW+OFF ; full screen graphics + sta COL80SW+ON ; turn on 80 column + sta IOUDIS+OFF ; turn ON (it too is backwards) Dhires switch + sta DHIRESW+OFF ; turn ON (it's backwards!) Dhires + + sta STORE80+ON ; turn on aux page display ability + lda BNK2SET ; read/write RAM, bank 2 + lda BNK2SET +; +; copy in progame from boot code +; + ldx #0 ; start at first letter +MVPRE: + lda BORG+3,X ; get letter + beq MVPREX ; all done + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + sta GAME,X ; save for asking about later + inx ; next letter + bne MVPRE ; do gen +MVPREX: + stx GAMEL ; save length of game name + lda #'.' ; get extension for names + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + inx ; next letter + lda #'D' ; for data segments + sta GAME1NAME,X ; save letter + sta GAME2NAME,X ; save letter + inx ; points to number + inx ; inclusive count for length + stx GAME1NML ; save length of name + stx GAME2NML ; save length of name + + lda #VERSID ; put in version number + sta ZBEGIN+ZINTWD+1 + + inc ZSP+LO ; INIT Z-STACK POINTERS + inc OLDZSP+LO ; TO "1" + inc SCREENF ; TURN DISPLAY ON + inc SCRIPT ; enable scripting + inc CRLF_CHECK ; do CR functino check + + lda WINTABLE+LO ; set WINDOW to point to window 0 + sta WINDOW+LO + lda WINTABLE+HI + sta WINDOW+HI ; okay, it does + + lda ARG1+LO ; using mouse? + beq ZBEGIN1 ; nope + ora #$78 ; point to correct screen holes + sta MSFIX0+1 + sta MSFIX1+1 ; and modify code to point to correct spot + sta MSFIX2+1 + lda ARG1+LO + ora #$F8 ; and one more + sta MSFIX2+1 +ZBEGIN1: + lda #$FF ; do a clear -1 to start off + sta ARG1+LO ; so arg 1 is this + jsr ZCLR ; doing it + + GET_PREFIX GPRE_PB ; get where we are to start + + lda D2SEG+HI ; start DSEGS at .D2 + sta DSEGS+HI + lda D2SEG+LO + sta DSEGS+LO + + lda #1 ; open game file .D2 please + jsr FETCH_FILE ; we did that + lda INFODOS ; are we on little dos? + beq ZBEGIN2 ; nope + jsr GET_SPECIAL ; do special preloading if so +ZBEGIN2: + lda D3SEG+HI ; this is cuz we be openin' .D3 + sta DSEGS+HI + lda D3SEG+LO + sta DSEGS+LO + lda #2 ; and just for giggles, do the + jsr FETCH_FILE ; same for game file .D3 + + jsr VLDZPC ; MAKE ZPC VALID + jsr NEXTPC ; skip over # of locals + + ; ... AND FALL INTO MAIN LOOP + + END + + diff --git a/apple/yzip/rel.9/zboot.asm b/apple/yzip/rel.9/zboot.asm new file mode 100644 index 0000000..c99e5d4 --- /dev/null +++ b/apple/yzip/rel.9/zboot.asm @@ -0,0 +1,261 @@ + PAGE + STTL "--- ZIP CODE BOOT PART ---" +ZBOOT: +; +; clear out ZERO page stuff +; + lda ARG2+LO ; get machine id! + sta ZBEGIN+ZINTWD ; save before it gets zeroed + + ldx #LASTWV-1 ; start at end of first part + lda #0 ; and clear to zero +ZEROL: + sta 0,X ; clear out zero page loc + dex ; next loc + bpl ZEROL ; and do next one + + ldx #ZEROPG ; now do other part +ZEROL1: + sta 0,X ; zero this one + inx ; point to next one + cpx #LASTZP ; find the last + bne ZEROL1 ; okay, so do it +; +; get game code from data and set up absolute pointers +; + lda ZBEGIN+ZVERS ; IS GAME A YZIP? + cmp #6 ; (X) + beq YESEZ ; YES, CONTINUE + +; *** ERROR #15 -- NOT AN EZIP GAME *** + lda #15 + ldy #0 + jmp ZERROR +YESEZ: + lda #%00111011 ; ENABLE SOUND, underline, MONOSPACING (X) + sta ZBEGIN+ZMODE + + lda #0 ; CLEAR HIGH BYTE + sta MOUSEF ; init mouse flag to no mouse + sta ZBEGIN+ZHWRD + sta ZBEGIN+ZVWRD + lda #MAXWIDTH ; SET SCREEN PARAMETERS + sta ZBEGIN+ZHWRD+1 + lda #MAXWIDTH/3 ; number of mono spaces on a line + sta ZBEGIN+ZSCRWD+1 + lda #MAXHEIGHT + sta ZBEGIN+ZVWRD+1 + lda #MAXHEIGHT/FONT_H + sta ZBEGIN+ZSCRWD ; number of lines of chars + lda #FONT_H ; height of font + sta ZBEGIN+ZFWRD + lda #3 ; width of font (2 spaces == 8 pixels) + sta ZBEGIN+ZFWRD+1 + lda #9 ; the color white is the foreground color + sta ZBEGIN+ZCLRWD+1 ; show Z game too + lda #2 ; black is the background color + sta ZBEGIN+ZCLRWD ; tell game about it +; +; just move global address to zero page for quick working +; + lda ZBEGIN+ZGLOBAL ; get page + sta GLOBAL+HI ; save which page + lda ZBEGIN+ZGLOBAL+1 ; LSB NEEDN'T CHANGE + sta GLOBAL+LO ; so just store it away +; +; figger absolute address for the fword table +; + lda ZBEGIN+ZFWORD ; get fword page number + jsr SETPC ; and get absolute address + sta FWORDS+HI ; show high addr of table + sty FWORDS+ABANK ; show which bank + lda ZBEGIN+ZFWORD+1 ; LSB NEEDN'T CHANGE + sta FWORDS+LO ; so just save it +; +; figger absolute address for the vocab table +; + lda ZBEGIN+ZVOCAB ; get fword page number + jsr SETPC ; and get absolute address + sta VOCAB+HI ; show high addr of table + sty VOCAB+ABANK ; show which bank + lda #0 ; this is always zero (get lo part from MPCL) + sta VOCAB+LO ; so just save it +; +; now do somethin' with the TCHAR table (maybe, if <> 0) +; + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + ora ZBEGIN+ZTCHAR+1 ; is it zero though? + bne TCH1 ; no, so copy it to somewhere useful + sta TCHARTBL ; not there, so zero first byte in table + beq TCHj ; jmp +TCH1: + lda ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + jsr SETPC ; and now make absolute + sta FPCH ; Save in FPC + sty FPCBNK + lda ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + sta FPCL ; now move pointer to fetch spot + + lda #0 ; and set index + sta I ; thank you +TCHLP: + jsr FETCHB ; get the byte in [a] + ldx I ; get offset + inc I ; and point to next one + sta TCHARTBL,X ; save in lower memory, thank you + cmp #0 ; are we done yet? + beq TCHj ; NULL TERMINATED STRING + cmp #$FF ; $ff means all >128 chars are terminators + bne TCHLNEXT ; nope + lda #1 ; yes, + sta ALLFLG ; so set flag to say so +TCHLNEXT: + jsr NEXTFPC ; point to next one + jmp TCHLP ; and go get it +TCHj: + jsr DO_DSEGS ; set up disk segment pointers +; +; use mouse/joystick, see if either is connected +; + lda ZBEGIN+ZFLAGS+1 ; get game flags + and #FMOUS ; uses a mouse? + beq ZBEND ; nope, so don't ask + jsr MHOME ; clear & home +MSLOOP: + DLINE MMSG ; ask about Mouse/Joystick/Keyboard + lda #1 ; move to left + sta CHZ ; move to column 1 + jsr MBASCAL ; move cursor there! + lda #EOL.OR.$80 ; send out eol + jsr MCOUT ; bye + jsr MRDKEY ; get a key please + jsr MCOUT ; put key out there + and #$7F ; turn off hi bit + cmp #'M' ; mouse? + beq DO_MOUSE ; yup + cmp #'m' + beq DO_MOUSE + cmp #'J' ; Joystick? + beq DO_STICK ; yup + cmp #'j' + beq DO_STICK + cmp #'N' ; neither + beq DO_NEITHER ; yup + cmp #'n' + beq DO_NEITHER +MSLOOP1: + jsr MBELL ; complain + jmp MSLOOP ; and do again +DO_MOUSE: + jsr INST_MOUSE ; install mouse handlers + bcs MSLOOP1 ; problems, try again + bcc ZBEND ; continue +DO_STICK: + jsr INST_STICK ; install joystick handler + bcs MSLOOP1 ; try again + bcc ZBEND ; continue, please +DO_NEITHER: +ZBEND: +; +; now, set flags like I want them + lda #FMONO^FDISP^FCOLO + ldx MOUSEF ; doing mousey stuff? + beq ZBEND0 ; nope + ora #FMOUS ; then turn on that bit too +ZBEND0: + sta ZBEGIN+ZFLAGS+1 ; set game flags +; +; +; Multiply ZFOFF & ZSOFF * 8 to get actual offset +; + lda ZBEGIN+ZFOFF ; hi part + sta FOFFM ; this'll be the middle part + lda ZBEGIN+ZFOFF+1 ; lo part + asl A ; *2 + rol FOFFM + rol FOFFH + asl A ; *4 + rol FOFFM + rol FOFFH + asl A ; *8 + rol FOFFM + rol FOFFH + sta FOFFL ; lo part here too +; +; now do string offset +; + lda ZBEGIN+ZSOFF ; hi part + sta SOFFM ; this'll be the middle part + lda ZBEGIN+ZSOFF+1 ; lo part + asl A ; *2 + rol SOFFM + rol SOFFH + asl A ; *4 + rol SOFFM + rol SOFFH + asl A ; *8 + rol SOFFM + rol SOFFH + sta SOFFL ; lo part here too + + lda ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + sta ZPCM ; MSB + lda ZBEGIN+ZGO+1 ; AND LSB + asl A ; *2 + rol ZPCM + rol ZPCH + asl A ; *4 + rol ZPCM + rol ZPCH +; +; now add offset +; + clc ; doing adding + adc FOFFL ; add in lo part + sta ZPCL + lda ZPCM + adc FOFFM + sta ZPCM + lda ZPCH + adc FOFFH + sta ZPCH +; +; now, set up TBLPUR, FUNPRE, and FUNPUR +; + lda SEGTBL+SGTTBLE+1 ; get last page of table preload + asl A ; make 256K page + sta TBLPUR ; show last pre table + inc TBLPUR ; but we want first pure table address + inc TBLPUR ; so point to it + lda TBLPUR ; does table preload take up all preload? + cmp #PGBEGIN ; reach 1st paged page? + bcs ZBEND1 ; ayyup, no function preload + + lda SEGTBL+SGTFUNS+1 ; get first page of function preload + asl A ; make 256K page + sta FUNPRE ; show me + lda SEGTBL+SGTFUNE+1 ; last page of function preload + asl A ; make 256K page + sta FUNPUR ; show last pre function + inc FUNPUR ; but we want first pure function + inc FUNPUR ; now we point to it + + lda TBLPUR ; now figger out negative number to + sec ; add to function preload addres to + sbc FUNPRE ; get page offset in memory + sta FUNPGE ; set up offset +; +; and now to set up extension table pointer +; +ZBEND1: + lda ZBEGIN+ZEXTAB+1 ; LSB of table + sta MSTBL+LO ; stays the same + lda ZBEGIN+ZEXTAB ; MSB of table + jsr SETPC ; get me the memory addres + sty MSTBL+ABANK ; save bank + sta MSTBL+HI ; and page + + jsr INIT_CHARSET ; initialize the charset + jmp INITPAG ; set up paging system + + END diff --git a/apple/yzip/rel.9/zdos.asm b/apple/yzip/rel.9/zdos.asm new file mode 100644 index 0000000..40ddda8 --- /dev/null +++ b/apple/yzip/rel.9/zdos.asm @@ -0,0 +1,967 @@ + STTL "--- ZDOS (SEEKING, READING, WRITING) ---" + PAGE +; +; some ProDOS parameter blocks here +; +READ_PB: ; for READING files + db 4 ; 4 parameters +GMREF: db 0 ; refnum + dw IOBUFF ; read into io buffer + dw PAGELEN ; 512 byte buffer + dw 0 ; length actually read +OPEN_FILE: ; opening up the pure file + db 3 ; 3 parameters + dw GAME1NM ; name of pure file + dw GAME1FIO ; game file buffer + db 0 ; where refnum goes +PSEEK: + db 2 ; 2 pararmeters + db 0 ; refnum + db 0,0,0 ; 3 byte new file pos +SET_PB: + db 1 ; just one parameter + dw GAMEPL ; where to go to +; +; some messages +; +SWAPSAVE: db EOL, "Take out save disk and insert ", EOL +SWAPSAVEL EQU $-SWAPSAVE +NOSWAP: db "game disk." +NOSWAPL EQU $-NOSWAP +INS_MSG: db EOL,"Insert " +INS_MSGL EQU $-INS_MSG +SIDEMSG: db ", Side " +SIDEMSGL EQU $-SIDEMSG +DRIVE_MSG: db ", in Disk Drive " +DRIVE_MSGL EQU $-DRIVE_MSG + +RESEAT_MSG1: db EOL, "Having problems reading side #" +RESEAT_MSG1L EQU $-RESEAT_MSG1 +RESEAT_MSG2: db ".",EOL,"Please re-insert it.",EOL,EOL +RESEAT_MSG2L EQU $-RESEAT_MSG2 + IF CHECKSUM +RETRYING: db "RETRYING . . ." +RETRYINGL EQU $-RETRYING + ENDIF +; +; place to stash prefixes and names +; +GPRE_PB: ; game prefix spot + db 1 ; 1 parm + dw GAMEPL ; where to put prefix +GAMEL: db 0 +GAME: ds 15 ; longest name + +GAME1NM: +GAME1NML: + db 0 ; not sure how long +GAME1NAME: + BLKB 15,0 ; room for name +GAME1REF: db 0 ; save refnum here +GAME1NUM: db 0 ; number (0-3) of side + +GAME2NM: +GAME2NML: + db 0 ; not sure how long +GAME2NAME: + BLKB 15,0 ; room for name +GAME2REF: db 0 ; refnum for game file 2 +GAME2NUM: db 0 ; number (0-3) of side +GAMEPL: db 0 ; name of prefix for game file +GAMEP: ds 64-15 ; max len +; -------------------- +; READ A VIRTUAL PAGE +; -------------------- +; ENTRY: V-BLOCK TO READ IN [DBLOCK] +; BUFFER ADDRESS IN [DBUFF] +; DSKBNK SAYS WHERE TO PUT PAGE (AUX OR MAIN) +; EXIT: DATA AT [DBUFF] +; +RFLAG: ds 1 +RCHKS: ds 1 +GETDSK: + lda #RETRY_COUNT ; set retry + sta RETRIES ; just use this for now + + IF DEBUG + lda #0 + sta RFLAG ; show no retries + sta RCHKS ; and checksum for it + ENDIF + + jsr FINDSEG ; find the segment and point to it +GETDSKL: + SET_MARK PSEEK ; move to the block + bcs GDBAD ; just die then + jsr READ_DOS ; do the read, thank you + bcc GDEX ; okay, just fine + inc RFLAG + jsr RETRY ; try again + bcc GETDSKL ; try all over +GDEX: + lda READ_PB+RD_LENGTH+HI ; Get how much read in + cmp READ_PB+RD_BUFFLEN+HI ; same as we wanted? + beq GDEX1 ; yes + lda #23 + jmp ZERROR +GDEX1: + IF DEBUG + lda RFLAG ; see if we retried + beq GDEX3 ; nope + lda RCHKS ; did retry checksum? + bne GDEX2 + inc RCHKS ; now we have + ldy #0 ; save block + sty $B00 + clc +GDEXL: + lda IOBUFF,Y + sta $A00,Y + adc $B00 + sta $B00 + iny + bne GDEXL + beq GETDSKL +GDEX2: + ldy #0 + clc + sty RFLAG +GDEX2L: + lda IOBUFF,Y + adc RFLAG + sta RFLAG + iny + bne GDEX2L + lda RFLAG + cmp $B00 + beq GDEX3 + lda #24 + jmp ZERROR + ENDIF +GDEX3: + lda #>IOBUFF ; first 256 byte page + jsr COPY_DATA ; and copy from IOBUFF to DBUFF + inc DBUFF+HI ; point to next one + lda #>IOBUFF+1 ; next 256 byte page + jmp COPY_DATA ; and copy it over +GDBAD: + jmp DISK_FATAL ; just die then +RETRY: + IF CHECKSUM + DLINE RETRYING ; show me the way to go home + ENDIF + + dec RETRIES ; count this try + bmi GDBAD ; it's dead jim + beq RETRY0 ; ask for reset + cmp #1 ; down to last time? + bne RETRYX ; just try again + lda PSEEK+SM_FPOS+0 + pha + lda PSEEK+SM_FPOS+1 + pha + lda PSEEK+SM_FPOS+2 + pha + lda #0 ; seek to zero + sta PSEEK+SM_FPOS+0 ; save here for now + sta PSEEK+SM_FPOS+1 ; save here for now + sta PSEEK+SM_FPOS+2 ; save here for now + SET_MARK PSEEK ; move to the block + pla + sta PSEEK+SM_FPOS+2 + pla + sta PSEEK+SM_FPOS+1 + pla + sta PSEEK+SM_FPOS+0 + bcc RETRYX ; all done +RETRY0: + pha ; save disk error + jsr SWAP2INFOW ; go to window zero + DLINE RESEAT_MSG1 ; ask to move the disk around + lda GMREF ; get ref num + cmp GAME2REF ; game2? + bne RETRY1 ; nope + ldy GAME2NML ; get length + lda GAME2NM,Y ; and side # + bne RETRY2 ; and continue +RETRY1: + ldy GAME1NML ; get length + lda GAME1NM,Y ; and side # +RETRY2: + jsr CHAR ; send char out there + DLINE RESEAT_MSG2 ; and finish statement + pla ; get disk error back + jsr DISK_ERR ; tell the error + jsr SWAPBACK ; back to current window +RETRYX: + clc ; show goodness + rts ; and done +; +; this is the fatal error spot +; +DISK_FATAL: + jsr DISK_ERR ; print out problem +DRIVE_ERR: + lda #14 + jmp ZERROR ; DRIVE ACCESS ERROR +; +; this routine prints out the string associated with the error and +; returns with the carry set, like most routines do when there is +; an error. The error should be in [A]. +; +UNK_DISK: db "ProDOS error $" +UNK_DISKL EQU $-UNK_DISK + +DISK_ERR: + pha ; save [A] + jsr SWAP2INFOW ; point to information window + pla ; get it back + + ldx #ELISTL ; scan the error table +DSKE: + cmp ELIST,X ; is it this one + beq DSKE1 ; ayyup + dex ; now skip the address + dex ; of the description + dex ; point to next error number + bpl DSKE ; jump to start +; +; if we are here print out unknown error and it's value +; + pha ; save [A] + DLINE UNK_DISK ; show error + pla ; get [A] + jsr HEXNUM ; print [A] + jmp DSK_EXIT ; done +DSKE1: + inx ; point to string address + lda ELIST,X ; get lo part + sta L+LO ; save it + inx ; point to hi part + lda ELIST,X ; get hi part + tax ; save here + sta L+HI ; and here + ldy #0 ; for offset + lda (L),Y ; get length of string + tay ; save in y + inc L+LO ; point past length + lda L+LO ; get it + bne DSKPR ; for printing + inx ; wrapped +DSKPR: + txa ; hi part in a + ldx L+LO ; lo part in X + jsr DLINE ; print out message +DSK_EXIT: + jsr GETRET ; wait for RETURN + jsr SWAPBACK ; all done + sec ; show badness again + rts ; and be done with it +; +; HEXNUM - print out the HEX value of [A] at the current cursor +; location +; +HEXNUM: + pha + lsr A + lsr A + lsr A + lsr A + jsr NIB1 + pla +NIB1: + and #%00001111 + tay + lda HCHARS,Y + jsr CHAR ; print it out + rts +HCHARS: DB "0123456789ABCDEF" + +; ---------------------- +; WRITE [DBUFF] TO DISK +; ---------------------- +; ENTRY: File already open and positioned, ready to be written to +; from page in (DBUFF). Writes out 512bytes, starting @ DBUFF. +; EXIT: CARRY CLEAR IF OKAY, SET IF FAILED + +PUTDSK: + ldx DSKBNK ; get bank + ldy #0 ; clear Y + lda #>IOBUFF ; first buffer + jsr SAVE_DATA ; and copy from DBUFF to IOBUFF + + IF CHECKSUM == 1 + lda #>IOBUFF + jsr CKS_BLOCK + ENDIF + + jsr NEXT_DBUFF ; point to next buffer + ldx DSKBNK ; go get new DSKBNK + ldy #0 ; clear Y again + lda #>IOBUFF+1 ; top part + jsr SAVE_DATA ; copy to IOBUFF + + IF CHECKSUM == 1 + lda #>IOBUFF+1 + jsr CKS_BLOCK + ENDIF + + jsr NEXT_DBUFF ; count buffer + jmp WRITE_DOS ; and now write it +; --------------------- +; READ DBLOCK FROM DISK +; --------------------- +; CALLED BY RESTORE +; ENTER: with file already set up as it DBUFF +; L+LO == # of 256k blocks to read +; +GETRES: + lda L+LO ; get # of blocks + sta READ_PB+RD_BUFFLEN+HI + jsr READ_DOS + ldx #>PAGELEN ; get starting number of pages + stx READ_PB+RD_BUFFLEN+HI + bcc GTROK ; everything is fine + rts ; error if c == set +GTROK: + lda #>IOBUFF ; start at first block + sta L+HI ; we can use L+HI +GTRLOOP: + lda L+HI ; doing this block + + IF CHECKSUM == 1 + jsr CKS_BLOCK ; check check sum + ENDIF + + jsr COPY_DATA ; and copy from IOBUFF to DBUFF + jsr NEXT_DBUFF ; check for wrap + inc L+HI ; count this block + dec L+LO ; count this block + bne GTRLOOP ; do next one + rts ; all finished +; +; NEXT_DBUFF +; increment DBUFF to count the 2 pages done +; +NEXT_DBUFF: + inc DBUFF+HI ; point to next page + lda DBUFF+HI ; see where we are + cmp #>PRGLBL ; wrapping? + bne GTREX ; okay then + lda DSKBNK ; which bank we be in + bne GTR1 ; aux, so go to page 3 + inc DSKBNK ; point to aux + lda #Z2PAGE ; start of page 2 + bne GTREX ; so tell me which page +GTR1: + lda #P3BANK ; show page 3 bank + sta DSKBNK ; okay + lda #Z3PAGE ; page 3 of things +GTREX: + sta DBUFF+HI ; saved + rts ; all done +; +WRITE_DOS: + WRITE WRITE_SV ; write out save buffer + rts ; done +READ_DOS: + READ READ_PB ; read it + rts ; go home +; +; COPY_DATA - +; now move the data from iobuff to dbuff (in some bank) +; which part of IOBUFF is in [a] ($08 - $0B) +; +COPY_DATA: + sta SDLP3+2 ; self-modify code to get from IOBUFF + sta RDBNK+MAIN ; read from main + ldx DSKBNK ; get which bank it's going to + bmi CPD1 ; oh oh, third bank + sta WRTBNK,X ; and select that bank for writing + bpl CPD2 ; okay, bank selected +CPD1: + lda DBUFF+HI ; get from this zero page + sta ALTZP+AUX ; talk about aux mem + sta DBUFF+HI ; and save this in aux mem ZP +CPD2: + ldy #0 ; start at beginning + sty DBUFF+LO ; just to be sure +SDLP3: + lda IOBUFF,Y ; this becomes modified! + sta (DBUFF),Y ; to [DBUFF] + iny + bne SDLP3 + sta ALTZP+MAIN ; talk about main page again + sta WRTBNK+MAIN ; end up back at main + rts +; +; Segment table handling routines +; + +; +; FINDSEG - find the Virtual page in DBLOCK by searching through +; the SEGTBL. +; +DISKPAGE: ds 2 ; spot to put starting disk page +BIGPAGE: ds 2 ; DBLOCK/2 for 512 pages +FINDSEG: + lda DBLOCK+HI ; work with MSB first + lsr A ; /2 + sta BIGPAGE+HI + lda DBLOCK+LO ; now LSB + ror A ; /2 + sta BIGPAGE+LO + lda GAME1NUM ; get number for disk 1 + jsr SCANSEG ; scan through the current disk table + lda GAME1REF ; save refnum + bcc FNDSG1 ; found it, figger it out + lda GAME2NUM ; get number for disk 2 + jsr SCANSEG ; see if it is here + lda GAME2REF ; save refnum + bcc FNDSG1 ; ayyup + jsr SEGQUEST ; get correct disk/file with segment +FNDSG1: + sta PSEEK+SM_REFNUM ; for seeking + sta GMREF ; and for reading + lda (DSEGS),Y ; pick up MSB of disk page + sta DISKPAGE+HI ; save it + iny ; point to LSB + lda (DSEGS),Y ; get it + sta DISKPAGE+LO ; save it +; now point to Starting page again + dey + dey + dey + dey + lda BIGPAGE+LO ; LSB of desired page + sec ; doing subtract + sbc (DSEGS),Y ; get rid of LSB of starting page + sta PSEEK+SM_FPOS+1 ; save here for now + dey ; point to MSB of starting page + lda BIGPAGE+HI ; get DBLOCK MSB + sbc (DSEGS),Y ; get offset + sta PSEEK+SM_FPOS+2 ; save here temporarily + clc ; now add offset to starting disk page + lda DISKPAGE+LO ; get starting disk page + adc PSEEK+SM_FPOS+1 ; add inter-segment offset + sta PSEEK+SM_FPOS+1 ; save LSB + lda DISKPAGE+HI ; get MSB of segment disk page + adc PSEEK+SM_FPOS+2 ; add inter-segment offset + sta PSEEK+SM_FPOS+2 ; save MSB of disk page + asl PSEEK+SM_FPOS+1 ; *2 for 256Kb pages + rol PSEEK+SM_FPOS+2 ; okay, we did + lda DBLOCK+LO ; check to see which page in 512 we are + and #$01 ; if odd, then add one more + beq FNDEX ; all done then + inc PSEEK+SM_FPOS+1 ; one more page + bne FNDEX ; all done if no wrap + inc PSEEK+SM_FPOS+2 ; nother page +FNDEX: + rts ; done +; +; SCANSEG - look through the current segment table for the desired +; address found in BIGPAGE. Return with Y pointing to disk page +; and carry cleared if found. Otherwise, return carry set. +; [A] = which side number we are checking (0-n) +; +SCANSEG: + pha ; save which disk + asl A ; make word index + tax ; make it an index + lda DSKSEG+LO,X ; get LSB + sta DSEGS+LO + lda DSKSEG+HI,X + sta DSEGS+HI + ldy #SGTNSEG+1 ; point to segment count + lda (DSEGS),Y ; get it + tax ; use x as counter + pla ; get which side + tay ; is it side zero + bne SCANSG1 ; nope + ldy #SGTSEG+6 ; skip first entry, cuz they're preload + bne SCANNING ; okay ready to go +SCANSG1: + ldy #SGTSEG ; begin at beginning +SCANNING: + lda (DSEGS),Y ; get MSB of start + cmp BIGPAGE+HI ; check against block we want + beq SCAN1 ; might be okay + bcc SCAN2 ; PAGE > start seg, check end seg + iny ; LSB of start +SCAN0: + iny ; MSB of end + bcs NEXTSEG ; not this one +SCAN1: + iny ; point to LSB of start + lda (DSEGS),Y ; get LSB + cmp BIGPAGE+LO ; check against desired LSB + beq GOTSEG ; we found it + bcs SCAN0 ; DBLOCK LSB < then start LSB, not found + dey ; point back to MSB of start +SCAN2: + iny ; LSB of start + iny ; MSB of end + lda (DSEGS),Y ; get MSB of end + cmp BIGPAGE+HI ; check against DBLOCK MSB + bcc NEXTSEG ; end < DBLOCK, check next segment + bne GOTSEG1 ; end > DBLOCK, must be in this segment + iny ; point to end LSB + lda (DSEGS),Y ; get LSB + cmp BIGPAGE+LO ; how does it compare to desired LSB + bcs GOTSEG2 ; it's <= end, so it is here + dey ; point back to MSB +NEXTSEG: + iny ; point to LSB of end + iny ; MSB of disk page + iny ; LSB of disk page + iny ; MSB of next start page + dex ; count this segment + bne SCANNING ; check this segment + + sec ; show not on this disk + rts ; and done +GOTSEG: + iny ; MSB of end page +GOTSEG1: + iny ; LSB of end page +GOTSEG2: + iny ; MSB of disk offset + clc ; show we found it + rts ; all done +; +; SEGQUEST - find the correct disk/file with the desired page on +; it. Returns SCANSEG's stuff. +; +DISKCNTR: ds 1 ; disk count down +PAGENF: + db "Page not found in segment table: " +PAGENFL EQU $-PAGENF +SEGQUEST: + lda #1 ; start at first disk + sta DISKCNTR ; init counter +SEGQL: + lda DISKCNTR ; get disk + cmp SEGTBL+SGTDISKS+1 ; looked at all the disks? + bne SEGQL1 ; nope +; +; as a last resort, check disk 1, the boot disk +; + lda #0 ; set up DISKCNTR + sta DISKCNTR ; we did + jsr SCANSEG ; see if it is there + bcc SEGQ1 ; we found it + + DLINE PAGENF ; page not found + lda BIGPAGE+HI ; show MSB + jsr HEXNUM ; printed + lda BIGPAGE+LO ; and LSB + jsr HEXNUM ; we did + + lda #17 ; bad page + jmp ZERROR ; die a horrible death +SEGQL1: + lda DISKCNTR ; get which disk we be working on + jsr SCANSEG ; find out if it is here + bcc SEGQ1 ; it is, so open up file + inc DISKCNTR ; not in this disk + bne SEGQL ; and try again +; +; we have found the disk it is in, so ask for it if necessary +; +SEGQ1: + tya ; save the y pointer + pha ; it is saved + lda DISKCNTR ; get which disk we found it under + jsr FETCH_FILE ; go get the disk desired + pla ; get the Y reg back + tay ; and show it + lda GMREF ; get reference number again + rts ; all done +; +; FETCH_FILE: check to see if we can open GAMEFILE# (where # is in [A]) +; if not, ask for DISK#. +; +SAVENUM: db 0 ; spot to save ascii number +FETCH_FILE: + clc ; adding to make + adc #$30 ; it an ascii number + sta SAVENUM ; just save a minute + inc SAVENUM ; make name be one based + ldx GAME1NML ; get length of name + lda SAVENUM ; get name back + cmp #'3' ; are we looking for disk 1 or 2? + bcs FEFI1 ; disks 3 and up handled special +FEFI00: + cmp GAME1NM,X ; is it the current open one? + bne FEFI0 ; nope, so we need to open it + ldy GAME1REF ; get game 1 refnum + bne FEFIX ; all set, so point to it +FEFI0: + jsr DO_GAME1 ; handle it special + lda GAME1REF ; fetch refnum + jsr GET_PDATA ; now get the picture data + ldy GAME1REF ; refetch refnum + bne FEFIX ; so all done +FEFI1: + ldx GAME2NML ; get length of second name + cmp GAME2NM,X ; how bout second open file? + bne FEFI2 ; nope, so we need to open it + ldy GAME2REF ; it is second one, so show me + bne FEFIX ; it is open too +FEFI2: + lda GAME2REF ; get its refnum + beq FEFI20 ; nothing to close, thank you + sta CLOSE_PB+CL_REFNUM ; show close who to close + CLOSE CLOSE_PB ; close it up tight +FEFI20: + jsr OPEN_GAME2 ; open up GAME2 file + lda GAME2REF ; get refnum for this file + jsr GET_PDATA ; now get the picture data + ldy GAME2REF ; get ref back, please +FEFIX: + sty PSEEK+SM_REFNUM ; for seeking + sty GMREF ; and for reading + rts ; did it +; +; OPEN_GAME2 - open up the file that GAME2NM is pointing to, +; returning the REFNUM in [A], after storing in GAME2REF, +; and the 2 picture structures +; +OPEN_GAME2: + ldx GAME2NML ; get end of name + lda SAVENUM ; get new name + sta GAME2NM,X ; using second file + lda #>GAME2NM ; get lo byte + sta OPEN_FILE+OP_PATHNAME+HI + lda #GAME2FIO ; now set up file i/o buffer + sta OPEN_FILE+OP_FILEBUFF+HI + lda #0 if multi disk game + +SET_GAMEPRE: + jsr SWAP2INFOW ; point to info window + lda SWAPPED ; are we swapping disks? + beq SETGP ; nope, don't change game prefix + lda SAVENUM ; get which disk to put it + ldy GAMEPL ; get length of prefix + dey ; subtract 2 to point to prefix + dey ; number + sta GAMEP,Y ; set number for prefix +SETGP: + lda #>GAMEPL ; set up parm block + sta SET_PB+SP_PATHNAME+HI + lda #= side 3, must be disk drive 2 + bcs SEGTP02 ; fine, send that message out + lda #'1' ; ask for drive 1 then +SEGTP02: + jsr CHAR ; save which drive + lda #'.' ; finish sentence + jsr CHAR ; okay +SEGTP03: + jsr GETRET ; wait for + jmp SETGP0 ; try again +SETGP1: + jmp SWAPBACK ; pointing to disk +; +; DO_GAME1 - open up the special game 1 file and point to it +; +DO_GAME1: + ldy GAME1REF ; get the current game 1 ref num + beq DOG1 ; not currently open + pha ; save Name + sty CLOSE_PB+CL_REFNUM ; show close + CLOSE CLOSE_PB ; and close it + pla ; get name back +DOG1: + ldx GAME1NML ; get length of name + lda SAVENUM ; get new number + sta GAME1NM,X ; save name + pha ; save it for later use + lda #>GAME1NM ; get lo byte + sta OPEN_FILE+OP_PATHNAME+HI + lda #GAME1FIO ; now set up file i/o buffer + sta OPEN_FILE+OP_FILEBUFF+HI + lda # + jsr CHAR ; printed + dex ; count back one, as loop starts with inx + bne LSTVL ; go do next one +LSTVEX: + rts ; toots finis +; +; CHECKVOLS - set prefix to particular volume that is currently online +; +CHECKVOLS: + lda CHPTR+HI ; is it zero? + bne CHV1 ; if not, then get next volume + ONLINE ONLINE_PB ; get online volumes + bcc CHV0 ; okey dokey +CHVBX: + sec ; show badness + rts ; all done +CHV0: + lda #<(IOBUFF-16) ; get LSB (-16 cuz we start with add) + sta CHPTR+LO + lda #>IOBUFF ; and mSB + sta CHPTR+HI + lda #>SCRBUFF ; this is where we will work on it + sta SET_PB+SP_PATHNAME+HI + lda #SP_START ; where does it go? + sta L+HI ; L is pointer to there +GTS_RD: + lda #MAIN ; make sure we are in main + sta WRTBNK+MAIN + READ READ_PB ; go get 1Kb + bcc GTS_RD1 ; just fine + jsr RETRY ; try again + bcc GTS_RDL ; and do it again +GTS_RD1: + ldx #SP_BANK ; get bank that special is in + sta WRTBNK,X + lda #>IOBUFF ; get MSB of start + sta K+HI ; K is source + ldx #2 ; 2 blocks of 256 bytes each +GTS_CPL0: + ldy #0 ; indexer +GTS_CPL: + lda (K),y ; get it + sta (L),y ; store it + iny ; next + bne GTS_CPL ; gwon then + inc K+HI ; point to next block + inc L+HI ; for destination too + dex ; count block + bne GTS_CPL0 ; next block + dec J+LO ; count this 1Kb + bne GTS_RD ; go get next one + + sta WRTBNK+MAIN ; make sure we are in main +; +; now figger out last page +; + ldy #SGTSEG+1 ; get start segment LSB + lda (INFODOS),Y ; got it + clc ; doing add + adc #SP_SIZE ; add in size MSB + sta INFODOS_END+HI ; and save it + lda INFODOS_END+LO ; now, subtract one to make + bne GTS_END ; it inclusive + dec INFODOS_END+HI ; wrapped, so dec MSB +GTS_END: + dec INFODOS_END+LO ; make pointers inclusive + + rts ; done + + IF CHECKSUM == 1 +CKS_COUNT: db 0 +CKSB: db 0 +CKS_BLOCK: + pha + sta CKSMOD+2 + ldy #0 + lda CKSB +CKSLP: + clc +CKSMOD: adc IOBUFF,Y + iny + bne CKSLP + + sta CKSB + inc CKS_COUNT + pla + rts + + IF 0 + jsr HEXNUM + lda CKS_COUNT + cmp #$F + bne CKSCNT + lda #0 + sta CKS_COUNT + lda #EOL + bne CKSSEND +CKSCNT: + inc CKS_COUNT + lda #SPACE +CKSSEND: + jsr CHAR + jsr DISP_LINE + pla + rts + ENDIF + + ENDIF + + END diff --git a/apple/yzip/rel.9/zero.equ b/apple/yzip/rel.9/zero.equ new file mode 100644 index 0000000..f6f7c7f --- /dev/null +++ b/apple/yzip/rel.9/zero.equ @@ -0,0 +1,175 @@ + STTL "--- ZERO PAGE VARIABLES ---" + PAGE + +SCRCX EQU 0 ; CURSOR HORIZONTAL +SCRCY EQU SCRCX+1 ; CURSOR VERTICAL +SCRBTM EQU SCRCY+1 ; first line outside current window +MAXLINES EQU SCRBTM+1 ; maximum number of lines in window +LEFTMRG EQU MAXLINES+1 ; left edge + left margin in current window +WINDOW EQU LEFTMRG+1 ; (WORD) address of current window structure +LINE_X EQU WINDOW+2 ; (WORD) width of line counter +CC_OFF EQU LINE_X+2 ; save offset for char drawing +CLSLEFT EQU CC_OFF+1 ; screen limits for CLS code +CLSTOP EQU CLSLEFT+1 ; top of screen +CLSWIDTH EQU CLSTOP+1 ; # of columns +CLSHEIGHT EQU CLSWIDTH+1 ; # of lines +; +; some variables for all the screen positioning code +; +NY_DATA EQU CLSHEIGHT+1 ; place for GET/PUT_NYBBLE to use +CH_OFFSET EQU NY_DATA+1 ; offset into char data table +DATALOOP EQU CH_OFFSET+1 ; loop counter for byte works +BITOFF EQU DATALOOP+1 ; bit offset into screen byte +CH_DATA EQU BITOFF+1 ; actual char data being worked on +SCR_DATA EQU CH_DATA+1 ; screen byte being worked on +SH_LOOP EQU SCR_DATA+1 ; loop counter for bit shifting +SCROLLY EQU SH_LOOP+1 ; save spot for y pos when scrolling +RETRIES EQU SCROLLY+1 ; (BYTE) Machine ID +CHRMAX EQU RETRIES+1 ; (BYTE) # CHARS CAN INPUT FROM KEYBOARD +SCLLINES EQU CHRMAX+1 ; (BYTE) how many lines to scroll +FMTTBL EQU SCLLINES+1 ; (BYTE) flag to show formatted table output +STMASK EQU FMTTBL+1 ; (BYTE) Mask to use on first byte of CLS +ENDMASK EQU STMASK+1 ; (BYTE) Mask to use on last byte of CLS +CHPTR EQU ENDMASK+1 ; (WORD) pointer to char data +SCOFF EQU CHPTR ;(BYTE) Offset used by scroll +SCLDIR EQU CHPTR+1 ;(BYTE) Direction of scroll - >0 up, <0 down +DSEGS EQU CHPTR+2 ; (WORD) Pointer to current disk's segments +;WIDE_FLAG EQU SCOFF+1 ; (BYTE) <> 0 if 16 bytes in char data +;DSEGS EQU WIDE_FLAG+1 ; (WORD) Pointer to current disk's segments +LASTWV EQU DSEGS+2 ; last of the WINDOW variables + +ZEROPG EQU $50 ; FIRST FREE Z-PAGE LOCATION +; +; these are first, cuz ZBOOT inits them so we don't want to clear them +; at ZBEGIN warm start +; +GLOBAL EQU ZEROPG ; (Relative Addr.) GLOBAL VARIABLE POINTER +VOCAB EQU GLOBAL+2 ; (ADDRESS) Vocab table pointer +FWORDS EQU VOCAB+3 ; (ADDRESS) F-WORDS TABLE POINTER +MOUSEF EQU FWORDS+3 ; (BYTE) ==-1/1 if we have mouse/joystick +INFODOS EQU MOUSEF+1 ; (WORD) if <>0, then pointer to D2SEG +FUNOFF EQU INFODOS+2 ; (ADDRESS) Function Offset (ZFOFF*8) +FOFFH EQU FUNOFF ; (BYTE) Hi part +FOFFM EQU FUNOFF+1 ; (BYTE) Middle part +FOFFL EQU FUNOFF+2 ; (BYTE) Lo part +STROFF EQU FUNOFF+3 ; (ADDRESS) String Offset (ZSOFF*8) +SOFFH EQU STROFF ; (BYTE) Hi part +SOFFM EQU STROFF+1 ; (BYTE) Middle part +SOFFL EQU STROFF+2 ; (BYTE) Lo part +; +; Beginning of warm start zeroing +; +OPCODE EQU STROFF+3 ; (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 +ARG5 EQU OPCODE+10 ; (WORD) +ARG6 EQU OPCODE+12 ; (WORD) +ARG7 EQU OPCODE+14 ; (WORD) +ARG8 EQU OPCODE+16 ; (WORD) +ABYTE EQU OPCODE+18 ; (BYTE) X-OP ARGUMENT BYTE +BBYTE EQU OPCODE+19 ; (BYTE) XCALL ARG BYTE (EZIP) +ADEX EQU OPCODE+20 ; (BYTE) X-OP ARGUMENT INDEX +VALUE EQU OPCODE+21 ; (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 +L EQU VALUE+8 ; (WORD) GEN-PURPOSE REGISTER #4 +ZPC EQU VALUE+10 ; (3 BYTES) ZIP PROGRAM COUNTER +ZPCL EQU ZPC ; (BYTE) <8 BITS OF [ZPC] +ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] +ZPCH EQU ZPC+2 ; (BYTE) >BIT OF [ZPC] +ZPCPNT EQU ZPC+3 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE +ZPNTL EQU ZPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +ZPNTH EQU ZPCPNT+1 ; (BYTE) +ZPCBNK EQU ZPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +MPC EQU ZPCPNT+3 ; (3 BYTES) MEMORY PROGRAM COUNTER +MPCL EQU MPC ; (BYTE) <8 BITS OF [MPC] +MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] +MPCH EQU MPC+2 ; (BYTE) >BIT OF [MPC] +MPCPNT EQU MPC+3 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE +MPNTL EQU MPCPNT ; FIRST 2 BYTES = SAME AS FOR ZIP (EZIP) +MPNTH EQU MPCPNT+1 ; (BYTE) +MPCBNK EQU MPCPNT+2 ; (BYTE) INDICATES AUXILIARY MEMORY +FPC EQU MPCBNK+1 ; (3 Bytes) Fetch pointer +FPCL EQU FPC ; (BYTE) Low part +FPCH EQU FPCL+1 ; (BYTE) High Part +FPCBNK EQU FPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) +SPC EQU FPCBNK+1 ; (3 Bytes) Fetch pointer +SPCL EQU SPC ; (BYTE) Low part +SPCH EQU SPCL+1 ; (BYTE) High Part +SPCBNK EQU SPCH+1 ; (BYTE) Bank part (0-Main, 1-Aux) + +; Z-STRING MANIPULATION VARIABLES + +LINLEN EQU SPCBNK+1 ; (BYTE) LENGTH OF CURRENT LINE +SOURCE EQU LINLEN+1 ; (BYTE) counter for read +WRDLEN EQU SOURCE+1 ; (BYTE) LENGTH OF CURRENT WORD +ESIZE EQU WRDLEN+1 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES +PSET EQU ESIZE+1 ; (BYTE) PERMANENT CHARSET +TSET EQU PSET+1 ; (BYTE) TEMPORARY CHARSET +ZCHAR EQU TSET+1 ; (BYTE) CURRENT Z-CHAR +OFFSET EQU ZCHAR+1 ; (BYTE) F-WORD TABLE OFFSET +ZFLAG EQU OFFSET+1 ; (BYTE) Z-WORD ACCESS FLAG +ZWORD EQU ZFLAG+1 ; (WORD) CURRENT Z-WORD +CONCNT EQU ZWORD+2 ; (BYTE) Z-STRING SOURCE COUNTER +CONIN EQU CONCNT+1 ; (BYTE) CONVERSION SOURCE INDEX +CONOUT EQU CONIN+1 ; (BYTE) CONVERSION DEST INDEX +DIRTBL EQU CONOUT+1 ; (WORD) CONTAINS TBLE TO STORE CHARS TO +XSIZE EQU DIRTBL+2 ; (WORD) SCREEN WIDTH FOR TESTS +RAND EQU XSIZE+2 ; (WORD) Random number offset +CURWIN EQU RAND+2 ; (BYTE) WHICH WINDOW TO WRITE IN +LENGTH EQU CURWIN+1 ; (WORD) CHAR POSITION ON THE SCREEN +CHRCNT EQU LENGTH+2 ; (BYTE) CHAR POSITION IN [LBUFF] +SCRIPT EQU CHRCNT+1 ; (BYTE) SCRIPT ENABLE FLAG +LINCNT EQU SCRIPT+1 ; (BYTE) LINE COUNTER +IOCHAR EQU LINCNT+1 ; (BYTE) CHARACTER BUFFER +COLORP EQU IOCHAR+1 ; (WORD) Pointer to current background color +ZSP EQU COLORP+2 ; (WORD) Z Stack +SCREENF EQU ZSP+2 ; (BYTE) DIROUT FLAG FOR SCREEN OUTPUT +TABLEF EQU SCREENF+1 ; (BYTE) DIROUT FLAG FOR TABLE OUTPUT +VOCEND EQU TABLEF+1 ; (3 BYTES) HOLDS MPC IN VOCAB SEARCH +DBUFF EQU VOCEND+3 ; (WORD) RAM PG TO ACCESS (LSB = 0) +DSKBNK EQU DBUFF+2 ; (BYTE) MAIN/AUX bank +ALLFLG EQU DSKBNK+1 ; (BYTE) IF =1 ALL FCN KEYS (>127) ARE TCHARS +UNDFLG EQU ALLFLG+1 ; (BYTE) Underlining flag +INVFLG EQU UNDFLG+1 ; (BYTE) Inverse flag +MEMPAGE EQU INVFLG+1 ; (BYTE) Save spot for XPAGING stuff +CPY_COUNT EQU MEMPAGE+1 ; (BYTE) Number of bytes for copy line +TBLHEIGHT EQU CPY_COUNT+1 ;(BYTE) Number of lines in printing table +TBLWIDTH EQU TBLHEIGHT+1 ;(BYTE) Number of bytes per line +TBLCNT EQU TBLWIDTH+1 ;(BYTE) Counter for table printing +FONTFLG EQU TBLCNT+1 ;(BYTE) Which font (!=0 is width) +TBLPUR EQU FONTFLG+1 ;(BYTE) first pure table page +FUNPRE EQU TBLPUR+1 ;(BYTE) first preloaded function page +FUNPUR EQU FUNPRE+1 ;(BYTE) first pure function page +FUNPGE EQU FUNPUR+1 ;(BYTE) -number to get function preload page +DELAY_COUNTER EQU FUNPGE+1 ;(BYTE) counter for delay loop +; +; some char-to-screen variables +; +CHAR_D1 EQU DELAY_COUNTER+1 ; (BYTE) character data, part 1 +CHAR_D2 EQU CHAR_D1+1 ; (BYTE) char data, part 2 +CW EQU CHAR_D2+1 ; (BYTE) width of the character +CLKCTR EQU CW+1 ; (BYTE) counter for mouse clicking +MSX EQU CLKCTR+1 ; (BYTE) mouse cursor X +MSY EQU MSX+1 ; (BYTE) mouse cursor Y +CURRENT EQU MSY+1 ; (BYTE) current paging bufer +;CURSOR_OFF EQU CURRENT+1 ; (BYTE) ==1 if "don't show the blinking cursor" +MSTBL EQU CURRENT+1 ; (ADDRESS) pointer to extension table +LASTZP EQU MSTBL+3 ; just checking +; +; these routines are in non-swapped memory +; +ZERO_FB EQU LASTZP ; put fetch byte routine in at end of ZP +ZERO_ZF EQU ZERO_FB+11 ; and ZPCPNT fetch after that +ZERO_MF EQU ZERO_ZF+9 ; and MPCPNT fetch after that +SAVE_DATA EQU ZERO_MF+9 ; copy data from DBUFF to IOBUFF routine +; +; and just to check the end +; +ZEE_END EQU SAVE_DATA+17 ; should be == 100 + + END diff --git a/apple/yzip/rel.9/zip.equ b/apple/yzip/rel.9/zip.equ new file mode 100644 index 0000000..ec5d39b --- /dev/null +++ b/apple/yzip/rel.9/zip.equ @@ -0,0 +1,116 @@ + STTL "--- YZIP EQUATES ---" + PAGE + +VERSID EQU 9 ; VERSION OF INTERPRETER + ; See file "versions" for complete descriptions + +TRUE EQU $FF +FALSE EQU 0 + +; --------------------- +; Segment table equates +; --------------------- +SGTDISKS EQU 0 ; number of disks +SGTPAD EQU SGTDISKS+2 ; just some extra room +SGTCHKS1 EQU SGTPAD+16 ; Checksum for disk 1 (PRELOAD) +SGTPICOF1 EQU SGTCHKS1+2 ; N/A +SGTSEG1 EQU SGTPICOF1+2 ; # of segments +SGTGPOF1 EQU SGTSEG1+2 ; Global Picture Directory +SGTTBLS EQU SGTGPOF1+2 ; Start of table preload (should be 0) +SGTTBLE EQU SGTTBLS+2 ; Last page of table preload +SGTTBLX EQU SGTTBLE+2 ; N/A +SGTFUNS EQU SGTTBLX+2 ; First page of function preload +SGTFUNE EQU SGTFUNS+2 ; End page of function preload +SGTFUNX EQU SGTFUNE+2 ; N/A +SGTDSK EQU SGTFUNX+2 ; Actual start of disk segment tables + +SGTCHKS EQU 0 ; check sum for file +SGTPICOF EQU 2 ; picture data offset +SGTNSEG EQU 4 ; # of segments in this list +SGTGPOF EQU 6 ; Global Directory Offset +SGTSEG EQU 8 ; start of segments +; --------------------- +; Z-CODE HEADER OFFSETS +; --------------------- + +ZVERS EQU 0 ; VERSION BYTE +ZMODE EQU 1 ; MODE SELECT BYTE +ZID EQU 2 ; GAME ID WORD +ZENDLD EQU 4 ; # OF QUADWORDS ON SIDE 1 OF DISK +ZGO EQU 6 ; EXECUTION ADDRESS +ZVOCAB EQU 8 ; START OF VOCABULARY TABLE +ZOBJEC EQU 10 ; START OF OBJECT TABLE +ZGLOBAL EQU 12 ; START OF GLOBAL VARIABLE TABLE +ZPURBT EQU 14 ; START OF "PURE" Z-CODE +ZFLAGS EQU 16 ; FLAG WORD +ZSERIA EQU 18 ; 3-WORD 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 +ZINTWD EQU 30 ; INTERPRETER ID WORD (SUPPLIED BY EZIP) +ZSCRWD EQU 32 ; SCREEN PARAMETER WORD ( " " " ) +ZHWRD EQU 34 ; DISPLAY WIDTH IN PIXELS +ZVWRD EQU 36 ; DISPLAY HEIGHT IN PIXELS +ZFWRD EQU 38 ; FONT HEIGHT, FONT WIDTH +ZFOFF EQU 40 ; FUNCTION OFFSET +ZSOFF EQU 42 ; STRING OFFSET +ZCLRWD EQU 44 ; FORGROUND COLOR, BACKGROUND COLOR +ZTCHAR EQU 46 ; POINTER TO TBL OF TERMINATING CHARS +ZTWIDTH EQU 48 ; Running counter for table output char width +ZCRFUNC EQU 50 ; FUNCTION FOR CARRIAGE RETURNS +ZCHRSET EQU 52 ; POINTER TO CHAR SET TBL +ZEXTAB EQU 54 ; Points to extension table, if needed +; +; Extension table offsets +; +ZEXTLEN EQU 0 ; Length of extension table +ZMSLOCX EQU 2 ; x location of mouse +ZMSLOCY EQU 4 ; y location of mouse +ZMSETBL EQU 6 ; MOUSE TBL CHANGE WORD +ZMSEDIR EQU 8 ; DIRECTION MENU +ZMSEINV EQU 10 ; INVENTORY MENU +ZMSEVRB EQU 12 ; FREQUENT VERB MENU +ZMSEWRD EQU 14 ; FREQUENT WORD MENU +ZBUTTN EQU 16 ; BUTTON HANDLER +ZJOYST EQU 18 ; JOYSTICK HANDLER +ZBSTAT EQU 20 ; BUTTON STATUS +ZJSTAT EQU 22 ; JOYSTICK STATUS +; +; ZFLAGS values +; +FSCRI EQU $01 ; scripting? +FMONO EQU $02 ; mono spaced font? +FSTAT EQU $04 ; status line refresh? +FDISP EQU $08 ; uses DISPLAY operations? +FUNDO EQU $10 ; uses UNDO? +FMOUS EQU $20 ; uses mouse? +FCOLO EQU $40 ; uses color? +FMENU EQU $80 ; uses menus? +;--------------- +; Picture data +;--------------- +;=== DATA HEADER === +PHFID EQU 0 ; File ID +PHFLG EQU PHFID+1 ; Flags +PHHUFF EQU PHFLG+1 ; Pointer to Huffman data +PHNLD EQU PHHUFF+2 ; # entries in local directory +PHNGD EQU PHNLD+2 ; # entries in global directory +PHDSIZE EQU PHNGD+2 ; Local directory entry size +PHCHKS EQU PHDSIZE+2 ; File Checksum +PHFVERS EQU PHCHKS+2 ; File Version (N/A) +PHEXTRA EQU PHFVERS+2 ; Extra room for getting fatter +PHSIZE EQU 16 ; 16 bytes is header size +;=== DATA HEADER FLAGS === +PHFGD EQU $1 ; data has global directory +PHFHUFF EQU $2 ; Huffman encoded pictures +PHFHUFF1 EQU $4 ; All pictures use same Huff tree +PHFPAL EQU $8 ; No pallette information +;=== LOCAL DIRECTORY === +PLDID EQU 0 ; Picture ID +PLDWID EQU PLDID+2 ; Picture Width +PLDHGHT EQU PLDWID+1 ; Picture Height +PLDFLG EQU PLDHGHT+1 ; Flags +PLDPTR EQU PLDFLG+1 ; Pointer to picture data +PLDSIZE EQU PLDPTR+3 ; size of local directory entry + + END diff --git a/apple/yzip/rel.9/zsavres.asm b/apple/yzip/rel.9/zsavres.asm new file mode 100644 index 0000000..f82ce0c --- /dev/null +++ b/apple/yzip/rel.9/zsavres.asm @@ -0,0 +1,721 @@ + + STTL "--- ZIP SAVE AND RESTORE ROUTINES ---" + PAGE +; ----------------------------- +; SET UP SAVE & RESTORE SCREENS +; ----------------------------- +SAVRES: + jsr ZCRLF ; CLEAR THE LINE BUFFER + lda #0 + sta SCRIPT ; DISABLE SCRIPTING + lda PAGE2SW+MAIN ; just do this for the heck of it + lda BNK2SET ; this stuff too + lda BNK2SET + + rts + +; ----------------------------- +; SAVE & RESTORE STRINGS +; ----------------------------- +YES: DB "YES" + DB EOL +YESL EQU $-YES +NO: DB "NO" + DB EOL +NOL EQU $-NO + +NAMEQ: db EOL + db "Insert save disk and enter " + db "full pathname of save file: " + db EOL + db "Hit '?' key to get a list of online volumes." + db EOL + db "Current pathname is:", + db EOL +NAMEQL EQU $-NAMEQ +SNDATA: ; show start of name and length +SNAMEL: db 0 ; place to save length of name +SAVENAME: ds 64+15 ; save plenty of room for max name + +DELQ: db EOL,"File exists, delete it (Yes/No)? " +DELQL EQU $-DELQ+1 ; include this following EOL +RETQ: db EOL,"Please hit [RETURN]",EOL +RETQL EQU $-RETQ +PREFIX_ERR: db EOL,"Name must have prefix, " + db "i.e.: /DISKNAME/FILENAME",EOL +PREFIX_ERRL EQU $-PREFIX_ERR +; ----------------------------- +; SAVE/RESTORE Parameter Blocks +; ----------------------------- +CREATE_PB: + db 7 ; 7 parameters + dw SNDATA ; pointer to name + db $C3 ; full access to file + db $06 ; BIN file type + dw 0 ; no aux data + db $01 ; standard file + dw 0 ; create date + dw 0 + ; creation time +SETEOF_PB: + db 2 ; 1 parameter + db 0 ; refnum + db 0,0,0 ; set to zero spot to clear it out +OPEN_SV: + db 3 ; 3 parameters + dw SNDATA ; name + dw GAME1FIO ; file buffer + db 0 ; ref num +CLOSE_PB: + db 1 ; only one parm + db 0 ; the refnum +WRITE_SV: + db 4 ; parm count + db 0 ; refnum + dw IOBUFF ; data is always here + dw 512 ; 1 page worth + dw 0 ; how many actually went + +; get the save file name. If user hits the ESC key, then abort the +; save by return with the carry set. +; +GET_SNAME: + jsr CLOSE_GAME ; close the game files + jsr SWAP2INFOW ; goto information window +GTSN0: + DLINE NAMEQ ; ask about name + lda SNAMEL ; is there a name yet? + beq GTSN00 ; nope + DLINE SAVENAME,SNAMEL ; show current name of file +GTSN00: + lda #0 ; clear line count + sta CLOSE_PB+CL_REFNUM ; clear this too + ldx SNAMEL ; get length + stx CHRCNT ; okay + ldy SNAMEL ; point to copy + dey ; one less +GCOPY: + lda SNAMEL,X ; get char + sta LBUFF,Y ; save it + dex ; point to previous one + dey ; previous pointer + bpl GCOPY ; copy until length byte +GNAME: + jsr GETKEY ; WAIT FOR A KEY + cmp #EOL ; IF [RETURN], + beq GOTNAME ; got the name + cmp #ESCAPE ; hit escape key? + sec ; just in case it does exit + bne GNM2 + jmp GNX ; all done then +GNM2: + cmp #BACKSPACE ; erasing things? + bne GNM1 ; nope + + ldx CHRCNT ; make sure there are chars there + bne GNMBP ; ayyup, do delete +GNMBAD: + jsr BEEP ; no room for delete + jmp GNAME ; okay +GNMBP: + dex ; point down one + stx CHRCNT ; count one down + lda LBUFF,X ; get char to delete + tax ; show in [X] + lda #BACKSPACE ; and doing a backspace + bne GNMSHOW ; okay, delete char on screen +GNM1: + cmp #'/' ; slash is the only good non-numeric char + beq GNMGOOD ; fine, use it + cmp #'.' ; well, maybe a . too + beq GNMGOOD ; fine, here it is + cmp #VOLCHAR ; does user want list of volumes? + bne GNM1x ; nope + + lda #0 ; clear out current name + sta CHRCNT ; okay, we did + jsr LISTVOLS ; show them + jmp GTSN0 ; start over, kind of +GNM1x: + cmp #'0' ; is it a number + bcc GNMBAD ; nope + cmp #'9'+1 ; well? + bcc GNMGOOD ; yup + cmp #'z'+1 ; make sure it is alpha numeric + bcs GNMBAD ; nope + cmp #'A' ; well? + bcc GNMBAD ; nope + cmp #'a' ; little char? + bcs GNMGOOD ; yup + cmp #'Z'+1 ; big char + bcs GNMBAD ; nope +GNMGOOD: + ldx CHRCNT ; get name index + inc CHRCNT ; point to next char + sta LBUFF,X ; save name char +GNMSHOW: + jsr CHAR ; show character + jsr DISP_LINE ; make sure it is there + jmp GNAME ; go get next char +; +; got the name, so copy it to the SAVENAME buffer +; +GOTNAME: + lda CHRCNT ; did we get any? + beq GTNMERR ; nope + lda LBUFF ; make sure first name is a directory + cmp #'/' ; is it? + beq GTNM1 ; yup, probly okay then +GTNMERR: + lda #0 ; clear CHRCNT so name doesn't get + sta CHRCNT ; output again + DLINE PREFIX_ERR ; complain and die + sec ; show bad name + bcs GNX ; all done +GTNM1: + ldx #0 ; now check to make sure there are 2 + ldy #$FE ; use this as counter +GTNMCHK: + lda LBUFF,X ; get char + inx ; next char + cmp #'/' ; prefix deliminator? + bne GTNMCHK1 ; nope + iny ; count this one + beq GTNM2 ; we have 2 of them +GTNMCHK1: + cpx CHRCNT ; at end? + beq GTNMERR ; yes, and no 2 '/'s + bne GTNMCHK ; go check next char +GTNM2: + cpx CHRCNT ; make sure there are chars after prefix + beq GTNMERR ; nope, still an error + ldx CHRCNT ; get how many characters + stx SNAMEL ; save in length byte + dex ; points one too far +GNL: + lda LBUFF,X ; get the char + sta SAVENAME,X ; save the char + dex ; point to previous one + bpl GNL ; and go get it + clc ; show did just fine +GNX: + php ; save status + lda #0 ; and clear CHRCNT + sta CHRCNT ; okay + lda #EOL ; print EOL + jsr CHAR ; okay + jsr SWAPBACK ; change back to old window + plp ; get status back + rts ; all done +; +; open up a save file, by first trying to create it. If it already exists +; then make sure the player wants to delete the file, then get rid of it. +; Finally open the file. Return with carry set if user aborts the save. +; Store the ref number into the write parm block. +; +OPEN_SAVE: + CREATE CREATE_PB ; first try to create the file + bcc OPSV_OPEN ; created just fine, so open it +; +; can't create the file, check out why +; + cmp #$47 ; this means file already there + beq OPSV1 ; nope, not that + jmp DISK_ERR ; show badness +OPSV1: + DLINE DELQ ; ask about deleting this file + jsr GETYN ; get me the yes or no + bcc OPSV_OPEN ; so then delete it if yes + rts ; nope, so just quit +OPSV_OPEN: + OPEN OPEN_SV ; open the save file + bcc OPSV_OP1 ; okey, things worked just fine + jmp DISK_ERR ; complain about error +OPSV_OP1: + lda OPEN_SV+OP_REFNUM ; get the ref number + sta WRITE_SV+WR_REFNUM ; save the ref number + sta CLOSE_PB+CL_REFNUM ; to close parm too + sta SETEOF_PB+SE_REFNUM ; for cleansing file + SET_EOF SETEOF_PB ; clear out file + bcc OPSVEX ; no problems + jsr DISK_ERR ; complain +OPSVEX: + rts ; file has been opened, return +; +; OPEN_RES - open the save file +; +OPEN_RES: + OPEN OPEN_SV ; open it up + bcc OPR1 ; okay, it worked + rts ; okay, it didn't +OPR1: + lda OPEN_SV+OP_REFNUM ; get reference number + sta READ_PB+RD_REFNUM ; save for read + sta CLOSE_PB+CL_REFNUM ; and for close + rts +; +; CLOSE_SAVE - close up the save file if it is open, and +; restore open game files +; +CLOSE_SAVE: + lda CLOSE_PB+CL_REFNUM ; check if it opened + beq CLSVX ; okay, nothing + CLOSE CLOSE_PB ; close the save file +CLSVX: +; lda #1 ; flag is true +; sta SAVEDISK ; show we have a save disk in there +; jsr SET_GAMEPRE ; go get the last one used +; jsr FETCH_FILE ; this does it + ldx GAME1NML ; get length of current name + lda GAME1NM,X ; get the number of the file + sta SAVENUM ; we need this to look for prefix + sta SAVEDISK ; show taking out save disk, not game disk + jsr DO_GAME1 ; open up GAME1 file + lda D2SEG+HI ; set DSEGS to point to #2 + sta DSEGS+HI + lda D2SEG+LO + sta DSEGS+LO + ldx GAME2NML ; get length of current name + lda GAME2NM,X ; get the number of the file + sta SAVENUM ; we need this to look for prefix + jsr OPEN_GAME2 ; open up GAME2 file + ldy #0 ; open up GAME2 file, just for kicks + sty SAVEDISK ; show we have a save disk in there + sty CLOSE_PB+CL_REFNUM ; clear close + iny ; set for true + sty SCRIPT ; allow scripting again + rts ; DONE +; +; CLOSE_GAME - close the current game file(s) +; and set DSEGS to point to preload so it will reopen them +; +CLOSE_GAME: + lda #0 ; show no files are open + sta CLOSE_PB+CL_REFNUM ; 0 closes all files + sta GAME1REF ; zero out two game files too + sta GAME2REF ; and here is number 2 + sta PF_FID ; clear this too + CLOSE CLOSE_PB ; now all are closed + rts +; +; Get answer to Yes/No question. Return with C==0 for yes, and C==1 +; for a no. RETURN == Yes, ESCAPE == NO +; +GETYN: + jsr GETKEY ; get the key strok + cmp #'y' ; IF REPLY IS "Y" + beq ALLSET ; ACCEPT RESPONSES + cmp #'Y' ; get both y's + beq ALLSET + cmp #EOL ; EOL IS ALSO ACCEPTABLE + beq ALLSET + cmp #'n' ; IF REPLY IS "N" + beq NOTSAT ; return with carry set + cmp #'N' ; check both n's + beq NOTSAT + cmp #ESCAPE ; check for ESC key too + beq NOTSAT ; which means no + jsr BEEP ; ELSE BEEP + jmp GETYN ; INSIST ON Y OR N +NOTSAT: + DLINE NO ; PRINT "NO"/EOL + sec ; set the carry + rts ; and show it +ALLSET: + DLINE YES ; Print "YES"/EOL + clc ; clear the carry + rts +GETRET: + DLINE RETQ ; ask for return +GETRETL: + jsr GETKEY ; get a key + cmp #EOL ; return key? + bne GETRETL ; nope + jsr CHAR ; show the + rts + +; --------- +; SAVE GAME +; --------- +ZSAVE: + lda #'N' + ldx NARGS + beq OLDSAV ; NORMAL, COMPLETE SAVE + lda #'P' +OLDSAV: + sta TYPE + jsr SAVRES ; set up screen + jsr GET_SNAME ; get the name of the save file + bcs ZSEXIT ; don't wanna after all + jsr OPEN_SAVE ; open the file + bcs ZSEXIT ; don't really care to +; +; SAVE GAME PARAMETERS IN [BUFSAV] +; + lda ZBEGIN+ZID ; MOVE GAME ID + sta BUFSAV+0 ; INTO 1ST 2 BYTES + lda ZBEGIN+ZID+1 ; OF THE A + sta BUFSAV+1 + lda ZSP+LO ; MOVE [ZSP] + sta BUFSAV+2 + lda ZSP+HI + sta BUFSAV+3 + lda OLDZSP+LO + sta BUFSAV+4 + lda OLDZSP+HI ; MOVE [OLDZSP] + sta BUFSAV+5 + ldx #2 ; MOVE CONTENTS OF [ZPC] +ZSL1: lda ZPC,X ; TO BYTES 7-9 + sta BUFSAV+6,X ; OF [BUFSAV] + dex + bpl ZSL1 + lda TYPE + sta BUFSAV+9 ; NORMAL OR PARTIAL + cmp #'P' + bne ZSNONM ; NORMAL SAVE SO NO name TO SAVE + + lda ARG3+LO ; set up FPC to get save name + sta FPCL ; lo part is okay + lda ARG3+HI ; get page + jsr SETPC ; get memory addr + sta FPCH ; page number + sty FPCBNK ; and bank + jsr FETCHB ; get count + sta I ; and save it + jsr NEXTFPC ; point to next byte + lda #0 ; set up data offset + sta J ; did it +ZSL3: + jsr FETCHB ; get data byte + ldy J ; get offset + sta BUFSAV+10,Y ; save into buffer + jsr NEXTFPC ; point to next byte + inc J ; next byte + dec I ; count it + bne ZSL3 ; loop again +ZSNONM: +; +; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK +; + lda #MAIN ; in the main bank + sta DSKBNK ; thank you + lda #>LOCALS ; start at locals + sta DBUFF+HI ; POINT TO THE PAGE + jsr PUTDSK ; AND WRITE IT OUT + bcc ZSOK ; IF SUCCEEDED, WRITE STACK +ZSBAD: + jsr DISK_ERR ; print error message + SET_EOF SETEOF_PB ; clear out file, maybe +ZSEXIT: + jsr CLOSE_SAVE ; else get game file back + jmp RET0 ; AND FAIL +; +; IF A PARTIAL SAVE WRITE FROM ARG1 FOR ARG2 BYTES TO DISK +; (ROUNDED TO PGS) SKIPPING ZSTACK WRITE +; +ZSOK: + lda TYPE + cmp #'P' + bne ZSALL + lda ARG1+HI ; find where to start & how far to go + jsr SETPC ; get page in memory + pha ; save for minute + and #$01 ; check for odd page + beq ZSP1 ; nope, don't make one more page + inc ARG2+HI ; go get one more page +ZSP1: + pla ; get it back + and #$FE ; must be on block boundary + sta DBUFF+HI ; this is page + sty DSKBNK ; which bank + ldx ARG2+HI ; get MSB of count + lda ARG1+LO ; get lo offset + clc ; add + adc ARG2+LO ; lo count + bcc ZSPINC ; no extra page + inx ; wrapped extra page +ZSPINC: + bne SAVE2DISK ; go copy it now +; +; WRITE CONTENTS OF Z-STACK TO DISK +; +ZSALL: + lda #>ZSTKBL ; point to 1st page + sta DBUFF+HI + jsr PUTDSK ; write them, first one + bcs ZSBAD + jsr PUTDSK ; write them, second one + bcs ZSBAD +; +; WRITE ENTIRE GAME PRELOAD TO DISK +; + lda #>ZBEGIN ; POINT TO 1ST PAGE + sta DBUFF+HI ; OF PRELOAD + ldx ZBEGIN+ZPURBT ; GET # IMPURE PAGES +SAVE2DISK: + inx ; use for counting + stx I+LO + lsr I+LO ; /2 for 512byte pages + bcc ZSL2 ; no wrapping + inc I+LO ; wrapped once +ZSL2: + jsr PUTDSK ; this does the write + bcs ZSBAD + dec I+LO ; count one page + bne ZSL2 ; not done yet + + jsr CLOSE_SAVE ; prompt for game file + + IF CHECKSUM == 1 + lda CKS_COUNT + jsr HEXNUM + lda CKSB + jsr HEXNUM + lda #EOL + jsr CHAR + ENDIF + + lda #1 ; set to mark + ldx #0 + jmp PUTBYT ; SUCCESS + +; ------------ +; RESTORE GAME +; ------------ + +ZREST: + lda #'N' + ldx NARGS + beq OLDRES ; NORMAL, COMPLETE RESTORE + lda #'P' ; partial restore +OLDRES: + sta TYPE ; save which kind of restore +; +; SAVE LOCALS IN CASE OF ERROR +; + ldx #31 +LOCSAV: lda LOCALS,X ; COPY ALL LOCALS + sta LOCAL_SV,X ; to a save spot + dex + bpl LOCSAV + + jsr GET_SNAME ; get the name of the file + bcs ZRQUIT ; okay, don't do it + jsr OPEN_RES ; open the restore file + bcs ZRBAD ; can't do it + + lda TYPE ; PARTIAL SAVE DIFFERS STARTING HERE + cmp #'P' + bne ZRNRML + jmp ZPARTR ; just a partial restore +ZRNRML: + lda #MAIN + sta DSKBNK ; SET TO WRITE TO MAIN BANK + lda #>LOCALS + sta DBUFF+HI + lda #2 ; must read in two pages + sta L+LO + jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + bcs ZRBAD ; didn't work! + lda READ_PB+RD_LENGTH+HI ; see how much was read in + cmp #2 ; were 2 blocks read in? + bne ZRQUIT ; wrong kind of file for complete save + + lda BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID + cmp ZBEGIN+ZID ; MATCH THE CURRENT ID? + bne ZRQUIT ; WRONG DISK IF NOT + + lda BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE? + cmp ZBEGIN+ZID+1 + beq ZROK ; CONTINUE IF BOTH BYTES MATCH + bne ZRQUIT ; skip disk error message +; +; HANDLE RESTORE ERROR +; +ZRBAD: + jsr DISK_ERR ; print error message +ZRQUIT: + ldx #31 ; RESTORE ALL SAVED LOCALS +ZRL2: lda LOCAL_SV,X + sta LOCALS,X + dex + bpl ZRL2 +BADRES: + jsr CLOSE_SAVE ; PROMPT FOR GAME DISK + jmp RET0 ; PREDICATE FAILS +; +; CONTINUE RESTORE +; +ZROK: + lda ZBEGIN+ZFLAGS ; save both flag bytes + sta J+LO + lda ZBEGIN+ZFLAGS+1 + sta J+HI + + lda #>ZSTKBL ; retrieve old contents of + sta DBUFF+HI ; z-stack + lda #4 ; do 4 pages + sta L+LO ; tell GETRES how many pages + jsr GETRES ; get 4 pages of z-stack + bcc ZROKL1 + jmp DISK_FATAL ; if here, mix of good & bad so die +ZROKL1: + lda #>ZBEGIN ; get where we are + sta DBUFF+HI + lda ZBEGIN+ZPURBT ; get # pages to load + sta I+LO + inc I+LO ; go get last page if possible +LREST0: + lda I+LO ; how many pages left + beq LRESTj ; finis + sec ; doing subtract + sbc #4 ; doing it 4 blocks at a time + bcc LREST1 ; <4 blocks left so deal with it special + sta I+LO ; save remenants +LREST: + lda #4 ; assume at least 4 pages + sta L+LO ; this tells GETRES how many to read in + jsr GETRES ; fetch the remainder + bcc LREST0 + jmp DISK_FATAL +LREST1: + lda I+LO ; get how many left + sta L+LO ; and show it to GETRES + and #$1 ; is it odd? + beq LREST2 ; nope + inc L+LO ; read one more +LREST2: + jsr GETRES ; and finish it up +; +; RESTORE THE STATE OF THE SAVED GAME +; +LRESTj: + lda J+LO ; RESTORE THE STATE + sta ZBEGIN+ZFLAGS ; OF THE FLAG WORD + lda J+HI + sta ZBEGIN+ZFLAGS+1 + + lda BUFSAV+2 ; RESTORE THE [ZSP] + sta ZSP+LO + lda BUFSAV+3 + sta ZSP+HI + lda BUFSAV+4 + sta OLDZSP+LO + lda BUFSAV+5 ; AND THE [OLDZSP] + sta OLDZSP+HI + + ldx #2 ; RESTORE THE [ZPC] +ZRL4: lda BUFSAV+6,X + sta ZPC,X + dex + bpl ZRL4 + +ZROUT: jsr CLOSE_SAVE ; PROMPT FOR GAME DISK + jsr VLDZPC ; MAKE VALID (MUST DO AFTER GET DISK) + + IF CHECKSUM == 1 + lda CKS_COUNT + jsr HEXNUM + lda CKSB + jsr HEXNUM + lda #EOL + jsr CHAR + ENDIF + + lda #2 ; SET TO + ldx #0 + jmp PUTBYT ; SUCCESS + + + ; DO PARTIAL RESTORE GETTING 1ST PAGE + ; AND LAST PAGE BYTE ALIGNMENT CORRECT + ; WRITE LOCALS TO IOBUFF JUST TO LOOK AT NAME +ZPARTR: + lda #MAIN + sta DSKBNK + lda #>IOBUFF ; DON'T READ TO LOCALS YET (X) + sta DBUFF+HI + lda #2 ; just one block please + sta L+LO + jsr GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + bcc ZRN2 ; worked just fine +ZPBAD: + jmp BADRES ; names don't match, die +ZRN2: + lda ARG3+LO ; set up FPC to get save name + sta FPCL ; lo part is okay + lda ARG3+HI ; get page + jsr SETPC ; get memory addr + sta FPCH ; page number + sty FPCBNK ; and bank + jsr FETCHB ; get count + sta I ; and save it + jsr NEXTFPC ; point to next byte + lda #IOBUFF ; get 1st page + sta DBUFF+HI ; getres should keep in iobuff + sta ZPARTMOD+2 ; and show where to get it from + lda #$01 ; is it odd + bit SPCH ; get page destination + beq ZPARTx ; nope + inc ZPARTMOD+2 ; then get second page worth +ZPARTx: + lda #2 ; just do one block + sta L+LO + jsr GETRES + bcc ZPART0 + jmp DISK_FATAL ; ALL MESSED UP, JUST QUIT +ZPART0: + ldy ARG1+LO ; START BYTE FIRST PAGE +ZPARTMOD: + lda IOBUFF,Y ; this gets modified with good page # + jsr STASHB + jsr NEXTSPC + jsr DECJ + bcs ZPART1 ; CARRY CLEAR IF $FFFF RESULT + jmp ZROUT +ZPART1: + inc ARG1+LO + bne ZPART0 + lda #>IOBUFF+1 ; this is second page address + cmp ZPARTMOD+2 ; is it second one already? + beq POK ; yes, so read in a new block + sta ZPARTMOD+2 ; then update it + bne ZPART0 ; and do it again +; +; THE OLD SAVE & RESTORE STILL HAVE OPCODES +; SO JUST PUT IN A PLACE FOR THEM HERE FOR NOW +; +OSAVE: +OREST: RTS + +ZISAVE: +ZIREST: JMP RET0 ; NOT IMPLEMENTED ON APPLE + END diff --git a/apple/yzip/rel.9/zstring.asm b/apple/yzip/rel.9/zstring.asm new file mode 100644 index 0000000..0d23bdb --- /dev/null +++ b/apple/yzip/rel.9/zstring.asm @@ -0,0 +1,443 @@ + PAGE + STTL "--- Z-STRING HANDLERS ---" + +; ----------------------- +; POINT MPC TO ZSTRING IN [I], using SOFF +; ----------------------- + +SETSTR: + lda I+LO + sta MPCL ; save in lo part + lda I+HI + sta MPCM ; middle part + lda #0 ; clear hi part + sta MPCH ; okay, we did + asl MPCL ; *2 + rol MPCM + rol MPCH + asl MPCL ; *4 + rol MPCM + rol MPCH +; +; now add the offset +; + lda MPCL ; carry clear from above + adc SOFFL ; add lo part of offset + sta MPCL ; save + lda MPCM + adc SOFFM + sta MPCM + lda MPCH + adc SOFFH + sta MPCH + jmp VLDMPC ; make MPCPNT to it + + +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 #$FA ; what to add to get offset into char table +TOASC: + sta TOASCM+1 ; modify code + lda ZCHAR ; use char as offset + clc ; make char be an index +TOASCM: adc #6 ; we just did + tax ; now use as index + lda CHARSET,X ; go get that char in charset zero +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 #20 ; skip into Charset 1 part of table + bne TOASC ; fix just like the others +; +; PRINT FROM CHARSET #2 +; +SET2: + lda ZCHAR ; retrieve the z-char + cmp #6 ; is it a special ascii char? + beq DIRECT ; yes, so do it special + lda #46 ; nothing special, just get offset + bne TOASC ; and jump +; +; 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 + bne 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 +; +; set up FPC to point to FWORDS table +; + ldx FWORDS+ABANK + stx FPCBNK + ldx FWORDS+HI + stx FPCH + ldx FWORDS+LO + stx FPCL + jsr ADDFPC ; add offset of the F-word + jsr FETCHB ; and get MSB of F-word + sta I+HI ; and save it + jsr NEXTFPC ; and point to LSB + jsr FETCHB ; and get it + sta I+LO ; and save it +; +; 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 SETFWD ; 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 + JSR VLDMPC + JMP PZTOP ; CONTINUE INNOCENTLY + + +; ---------------------- +; RETURN CURRENT CHARSET +; ---------------------- + +GETSET: LDA TSET + BPL GS + LDA PSET + RTS +GS: LDY #$FF + STY TSET + RTS + + +; ------------------------- +; POINT [I] AT FWORD STRING +; ------------------------- + +SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS + ASL A + STA MPCL + LDA I+HI + ROL A + STA MPCM + LDA #0 + ROL A + STA MPCH + JMP VLDMPC + + +; ----------------- +; 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 #5 ; FILL OUTPUT BUFFER + ldx #8 ; WITH PAD CHARS ($05) +CZSL: + sta OUT,X + dex + bpl CZSL + + lda #9 ; 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 CSHIP1 ; a pad char +NEXTZ: + jsr FINDCHAR ; find out where it tis + beq CSHIP ; no shift for charset zero + clc ; else do a temp-shift + adc #3 ; 4 = charset 1, 5 = charset 2 + jsr CSTASH ; save the char in outbuf + cmp #5 ; charset 2? + bne CSHIP ; nope + cpx #6 ; ascii escape? + bne CSHIP ; nope +; +; Handle special Ascii escape sequence +; + txa ; get ASCII alert char (#6) + jsr CSTASH ; shove it away +; +; do 1st half of "direct" +; + lda ZCHAR ; re-fetch char + lsr A ; get upper 2 bits in lower 2 bits + lsr A + lsr A + lsr A + lsr A + jsr CSTASH +; +; SEND 2ND HALF OF "DIRECT" +; + lda ZCHAR ; get char yet again + and #%00011111 ; and get lower 5 bits + tax ; this is where it is expected +; +; SHIP Z-CHAR TO OUTPUT BUFFER +; +CSHIP: + txa ; get char +CSHIP1: + jsr CSTASH ; put char away + bne CONTOP ; do again +; +; FINDCHAR - look through the charset table for the character. If found, +; figger out which shift it is. If not found, return charset 2, +; character #6. +; Enter: +; [A] = Char we are looking for +; Returns: +; [A] = Charset (0-2) +; [X] = Character # (6-31) +; +FINDCHAR: + ldx #0 ; start at first char, first set + ldy #78 ; there are 78 characters +FNDCL: + cmp CHARSET,X ; found it? + beq FNDCLX ; yes + inx ; next char + dey ; count char + bne FNDCL ; go check next char +; +; not found in table, use ASCII escape sequence +; + lda #2 ; escape sequence is char set 2 + ldx #6 ; character 6 + rts ; and done +FNDCLX: + txa ; put here for compares/action + ldy #0 ; this is char set 0 + ldx #$FA ; what to "subtract" to get +6 + cmp #26 ; how we doin'? + bcc FNDCHX ; all done + iny ; char set 1 + ldx #20 ; char set 1 offset + cmp #52 ; well? + bcc FNDCHX ; must be char set 1 + ldx #46 ; for char set 2 setting up + iny ; must be char set 2 then +FNDCHX: + stx FNDCHM+1 ; what to subtract to get offset + sec ; doing subtract +FNDCHM: sbc #6 ; make good offset + tax ; put here for return + tya ; and here to set flag + rts +; +; CSTASH - put the char in OUT. If we run out of room don't return, just +; jump to ZCRUSH as final destination +; [A] - char to be put away +; +CSTASH: + ldy CONOUT ; fetch output index + sta OUT,Y ; send the shift char + inc CONOUT ; update index + dec CONCNT ; and char count + bne CSTX ; plenty more room + pla ; get rid of return spot + pla ; fine + jmp ZCRUSH ; if out of room, crush 'em! +CSTX: + rts +; ---------------------- +; CRUSH Z-CHARS IN [OUT], mushing them into small 5 bit pieces +; ---------------------- +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 + STA OUT+2 ; MOVE CRUSHED Z-WORD + STX OUT+3 ; INTO PLACE + LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) + ASL A ; SHIFT BITS + ASL A + ASL A + ASL A + ROL OUT+6 ; ALONG WITH 7TH Z-CHAR + ASL A + ROL OUT+6 + ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR + STA OUT+5 ; SAVE HERE + LDA OUT+6 ; GRAB 7TH Z-CHAR + ORA #%10000000 ; SET HIGH BIT + STA OUT+4 ; MOVE CRUSHED Z-WORD INTO PLACE + RTS + + END + diff --git a/apple/zip/bugger.asm b/apple/zip/bugger.asm new file mode 100644 index 0000000..ac19e9c --- /dev/null +++ b/apple/zip/bugger.asm @@ -0,0 +1,205 @@ + PAGE + SBTTL "--- DEBUGGER: CBM64 ---" + + ; -------------- + ; APPLE DEBUGGER + ; -------------- + + ; ENTRY: BREAKPOINT ID IN [A] + +BLINE: DB "B: OP: PC: S: V: 1: 2: 3: 4: 5: 6: " + DB EOL +BLINL EQU $-BLINE + +DOBUG: LDX KBD ; WAS CTRL-S PRESSED? + CPX #$13 + BNE BUGIT + RTS ; YES, SO LEAVE + + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP ; ON THE FLY CHANGE SPACE + NOP + +BUGIT: LDX #2 ; INIT "CURSOR" + 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 BLINE,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 [ZSP] + LDA ZSP + JSR HEX + + LDX #29 ; CURSOR FOR [MPC] + LDA MPCH + JSR HEX + LDA MPCM + JSR HEX + LDA MPCL + JSR HEX + + LDX #38 + LDA BONE + JSR HEX + + LDX #43 + LDA BTWO + JSR HEX + + LDX #48 + LDA BTHREE + JSR HEX + + LDX #53 + LDA BFOUR + JSR HEX + + LDX #58 + LDA BFIVE + JSR HEX + + LDX #63 + LDA BSIX + JSR HEX + + +; LDA CSW+LO +; PHA +; LDA CSW+HI +; PHA +; LDA EH +; PHA +; LDA ALTCSW+LO +; STA CSW+LO +; LDA ALTCSW+HI +; STA CSW+HI +; +; LDA PSTAT +; BNE PPP +; +; LDA #$C1 +; STA CSW+HI +; LDA #$00 +; STA CSW+LO +; +; LDA #$89 +; JSR MCOUT +; LDA CSW+HI +; STA ALTCSW+HI +; LDA CSW+LO +; STA ALTCSW+LO +; LDA #$B8 +; JSR MCOUT +; LDA #$B0 +; JSR MCOUT +; LDA #$CE +; JSR MCOUT +; LDA #$8D +; JSR MCOUT + +PPP: LDX #0 +DBG1: LDA BLINE,X ; PRINT DEBUGGER TEXT +; JSR MCOUT + JSR CHAR + INX + CPX #BLINL + BCC DBG1 + +; PLA +; STA EH +; PLA +; STA CSW+HI +; PLA +; STA CSW+LO + + BIT KBD + BPL LETEX ; NO KEY PRESSED + + BIT ANYKEY ; CLEAR IT +BUGWAT: BIT KBD + BPL BUGWAT + + LDA KBD + CMP #$8D + BNE LETEX + BRK + +LETEX: BIT ANYKEY ; CLEAR FOR NEXT ONE + 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 + ORA #%10000000 + STA BLINE,X + INX + RTS + +HCHARS: DB "0123456789ABCDEF" + +BONE: DB 0 +BTWO: DB 0 +BTHREE: DB 0 +BFOUR: DB 0 +BFIVE: DB 0 +BSIX: DB 0 + + END + diff --git a/apple/zip/cold.k b/apple/zip/cold.k new file mode 100644 index 0000000..9eb4d7d --- /dev/null +++ b/apple/zip/cold.k @@ -0,0 +1,111 @@ + PAGE + SBTTL "--- MACHINE COLDSTART: APPLE II ---" + + ; --------- + ; COLDSTART + ; --------- + +COL80: DB 0 ; 80-COLUMN FLAG +SIG: DB 0 ; IIc FLAG +STRYSL: DB 0 ; BOOT SLOT +STRYDR: DB 0 ; BOOT DRIVE + +P80: DB "80-COLUMN DISPLAY? (Y/N) >" +P80L EQU $-P80 + + ; FINISH LOADING THE ZIP + +COLD: LDA BSLOT ; SET UP + STA DCBSLT ; CURRENT AND + STA DCBPSL ; PREVIOUS SLOT IDS + + LDA #HIGH COUT1 ; SET SCREEN OUTPUT + STA CSW+HI ; IN CASE OF PR#6 + LDA #LOW COUT1 ; WHICH SETS ALL IN & OUTPUT + STA CSW+LO ; TO PR #6 + + LDX #0 + STX DCBSEC ; START WITH SECTOR 0 + STX DBUFF+LO ; CLEAR LSB OF [DBUFF] + INX ; = 1 + STX DCBTRK ; START WITH TRACK 1 + STX DCBDRV ; SET UP CURRENT + STX DCBPDR ; AND PREVIOUS DRIVE ID + + LDA #$18 ; START LOAD AT $1800 + STA DBUFF+HI + + LDA #17 ; LOAD ALL OF + STA I+LO ; TRACK 1 +COLD0: JSR GETRES ; GO THRU ZDOS + DEC I+LO ; DONE LOADING? + BNE COLD0 ; NO, SO LOOP BACK + + LDA #$FF ;SET TO NORMAL DISPLAY + STA INVFLG + + ; DETERMINE SCREEN CONFIGURATION + + LDA $FBB3 ; CHECK ID BYTE + STA SIG ; SAVE MACHINE ID FOR LATER + CMP #$06 ; IS IT A IIE OR IIC? + BNE DO40 ; NO, SO DO 40-COL + LDA $FBC0 ; IS IT A IIE OR! A IIC + BNE COLD1 ; IIE + STA SIG ; 0 = IIC +COLD1: LDA $C017 ; IS TOP BIT SET? + BMI DO40 ; YES, NO 80-COLUMN CARD + + ; MAKE SURE PLAYER WANTS 80-COLUMN DISPLAY + + JSR CLS ;CLEAR SCREEN 1ST + LDA #10 ;CENTER DISPLAY + STA CV + LDA #5 + STA CH + JSR BASCAL ;FORCE IT + LDX #LOW P80 + LDA #HIGH P80 + LDY #P80L + JSR DLINE ; PRINT 80-COL PROMPT + +GET80: JSR RDKEY + CMP #$EE ; "n" + BEQ DO40 + CMP #$CE ; "N" + BEQ DO40 + CMP #$F9 ; "y" + BEQ DO80 + CMP #$D9 ; "Y" + BEQ DO80 +; CMP #$8D ; EOL? (COMMENTED OUT TO FORCE Y/N Le) +; BEQ DO80 + JSR BOOP + JMP GET80 + + ; SET [COL80] "TRUE" FOR 80-COLUMN + +DO80: JSR $C300 ; INIT 80 COL (PR#3) + + LDA #$FF + BNE SETCOL + + ; SET [COL80] "FALSE" FOR 40-COLUMN + +DO40: LDA #0 + +SETCOL: STA COL80 + + ; --------------- + ; WARMSTART ENTRY + ; --------------- + +WARM: LDA DCBPSL ;SAVE STORY DRIVE AND SLOT + LDX DCBPDR ;IN CASE CHANGED BY "SAVE" + STA STRYSL + STX STRYDR + + JSR CLS + + END + diff --git a/apple/zip/dispatch.asm b/apple/zip/dispatch.asm new file mode 100644 index 0000000..1cf14cc --- /dev/null +++ b/apple/zip/dispatch.asm @@ -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 + diff --git a/apple/zip/eq.g b/apple/zip/eq.g new file mode 100644 index 0000000..504da7b --- /dev/null +++ b/apple/zip/eq.g @@ -0,0 +1,160 @@ + PAGE + SBTTL "--- MEMORY ORGANIZATION ---" + +TRUE EQU $FF +FALSE EQU 0 +LO EQU 0 +HI EQU 1 + + ; SEE "HARDEQ.ASM" FOR APPLE II 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 ---" + +ZEROPG EQU $80 ; FIRST FREE Z-PAGE LOCATION + +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 ; (3 BYTES) ABS POINTER TO CURRENT Z-PAGE +ZPNTL EQU ZPCPNT +ZPNTM EQU ZPCPNT+1 +ZPNTH EQU ZPCPNT+2 + +MPC EQU ZPC+7 ; (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 ; (3 BYTES) ABS POINTER TO CURRENT M-PAGE +MPNTL EQU MPCPNT +MPNTM EQU MPCPNT+1 +MPNTH EQU MPCPNT+2 + +GLOBAL EQU MPC+7 ;LRU+16 ; (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+7 ; (BYTE) SCRIPT LINE LENGTH + +DBLOCK EQU IOCHAR+8 ; (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 +;GSLOT EQU DBLOCK+8 ; (BYTE) DEFAULT SAVE SLOT +TPOSIT EQU DBLOCK+8 ; (BYTE) TEMP SAVE POSITION +TDRIVE EQU DBLOCK+9 ; (BYTE) TEMP SAVE DRIVE +TSLOT EQU DBLOCK+10 ; (BYTE) TEMP SAVE SLOT +DRIVE EQU DBLOCK+11 ; (BYTE) CURRENT DRIVE + +;BLINK EQU DBLOCK+12 ; (WORD) CURSOR BLINK TIMER +;CSHAPE EQU BLINK+2 ; (BYTE) CURRENT CURSOR SHAPE +XSIZE EQU DBLOCK+12 ; (BYTE) SCREEN WIDTH FOR TESTS +RAND1 EQU XSIZE+1 ; (BYTE) +RAND2 EQU XSIZE+2 ; (BYTE) RANDOM # +SPLITF EQU XSIZE+3 ; (BYTE) WHICH WINDOW TO WRITE IN +ZPURE EQU XSIZE+4 ; (WORD) 1ST VIRTUAL PAGE OF "PURE" Z-CODE +HOLD EQU XSIZE+6 ; (WORD) USED BY GETBUF (PAGING) + +PR1 EQU HOLD+2 ; (WORD) PAGING REGISTERS +PR2 EQU PR1+2 ; (WORD) +PR3 EQU PR1+4 ; (WORD) + + ; PLACE SOME VARIABLES IN PAGE 2, NOT ENOUGH ROOM ON PG0 + +LRU EQU $280 ;MPC+6 ; (WORD) EARLIEST TIMESTAMP +ZCODE EQU LRU+2 ; (WORD) 1ST ABSOLUTE PAGE OF PRELOAD +PAGE0 EQU LRU+4 ; (WORD) 1ST PAGE OF ACTUAL SWAPPING SPACE +PMAX EQU LRU+6 ; (WORD) MAXIMUM # OF SWAPPING PAGES +ZPAGE EQU LRU+8 ; (WORD) CURRENT SWAPPING PAGE +TARGET EQU LRU+10 ; (WORD) TARGET PAGE FOR SWAPPING +STAMP EQU LRU+12 ; (WORD) CURRENT TIMESTAMP +SWAP EQU LRU+14 ; (WORD) EARLIEST BUFFER +TSTVAL EQU LRU+16 ; (BYTE) VALUE TO TEST FOR MEMORY EXISTENCE + ; CAN'T USE PG0 CAUSE SWAP TO AUX MEMORY. +PG2SIZ EQU 17 ; SIZE OF VARIABLE MEMORY IN PG 2 (ABOVE) + + END + diff --git a/apple/zip/eq.l b/apple/zip/eq.l new file mode 100644 index 0000000..179296d --- /dev/null +++ b/apple/zip/eq.l @@ -0,0 +1,142 @@ + PAGE + SBTTL "--- MEMORY ORGANIZATION ---" + +TRUE EQU $FF +FALSE EQU 0 +LO EQU 0 +HI EQU 1 + + ; SEE "HARDEQ.ASM" FOR APPLE II 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 ---" + +ZEROPG EQU $80 ; FIRST FREE Z-PAGE LOCATION + +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+7 ; (BYTE) SCRIPT LINE LENGTH + +DBLOCK EQU IOCHAR+8 ; (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 +;GSLOT EQU DBLOCK+8 ; (BYTE) DEFAULT SAVE SLOT +TPOSIT EQU DBLOCK+8 ; (BYTE) TEMP SAVE POSITION +TDRIVE EQU DBLOCK+9 ; (BYTE) TEMP SAVE DRIVE +TSLOT EQU DBLOCK+10 ; (BYTE) TEMP SAVE SLOT +DRIVE EQU DBLOCK+11 ; (BYTE) CURRENT DRIVE + +XSIZE EQU DBLOCK+12 ; (BYTE) SCREEN WIDTH FOR TESTS +RAND1 EQU XSIZE+1 ; (BYTE) +RAND2 EQU XSIZE+2 ; (BYTE) RANDOM # +SPLITF EQU XSIZE+5 ; (BYTE) WHICH WINDOW TO WRITE IN + + END + diff --git a/apple/zip/hardeq.g b/apple/zip/hardeq.g new file mode 100644 index 0000000..981b47e --- /dev/null +++ b/apple/zip/hardeq.g @@ -0,0 +1,147 @@ + PAGE + SBTTL "--- HARDWARE EQUATES: APPLE II ---" + + ; ------------------- + ; APPLE II MEMORY MAP + ; ------------------- + +LBUFF EQU $0200 ; LINE INPUT BUFFER (80 BYTES) +SCREEN EQU $0400 ; START OF SCREEN RAM +ZIP EQU $0800 ; START OF EXECUTABLE ZIP CODE + +IOBUFF EQU ZIP+$2400 ; PAGING BUFFER (ASSUME 9K ZIP) +BUFFA EQU IOBUFF+$0100 ; SECTOR DECODE BUFFER, LOWER HALF +BUFFB EQU BUFFA+$0100 ; SECTOR DECODE BUFFER, UPPER HALF + +PTABL EQU BUFFB+$0100 ; PAGE TBL IS 1K, 512 WORD ENTRIES + ; PAGING TABLE, LSBS +;PTABH EQU PTABL+$0100 ; PAGING TABLE, MSBS +LRUMAP EQU PTABL+$0400 ; TIMESTAMP TABLE + +ZSTAKL EQU LRUMAP+$0400 ; Z-STACK LSBS +ZSTAKH EQU ZSTAKL+$0100 ; Z-STACK MSBS +LOCALS EQU ZSTAKH+$0100 ; LOCAL VARIABLE STORAGE (30 BYTES) +BUFSAV EQU LOCALS+$20 ; AUXILIARY INPUT BUFFER (80 BYTES) + +ZBEGIN EQU LOCALS+$0100 ; START OF Z-PRELOAD + + ; --------- + ; CONSTANTS + ; --------- + +ARROW EQU $08 ; LEFT ARROW (BACKSPACE) +EOL EQU $0D ; EOL CHAR +LF EQU $0A ; LINE FEED +SPACE EQU $20 ; SPACE CHAR +BACKSP EQU $7F ; BACKSPACE + +READ EQU $00 ; "READ" COMMAND +WRITE EQU $01 ; "WRITE" COMMAND + +TOP EQU 1 ; NORMAL TOP EXCLUDING STATUS LINE +BOTM EQU 24 ; BOTTOM SCREEN LINE + +ZTRKF EQU 3 ; FIRST TRACK GAME IS ON +ZTRKL EQU 36 ; ANYTHING FROM HERE UP IS ILLEGAL + +II EQU $38 ; ID BYTE @ FBB3 +IIPLUS EQU $EA ; ID BYTE @ FBB3 +IIC EQU $06 ; ID BYTE @ FBB3 +IIE EQU $EA ; ID BYTE @ FBC0 +III EQU $8A ; ID BYTE @ FB1E + +B48GET EQU $D000 ; ADDR OF GETBYT FROM 48K AUX MEM +B48ADD EQU $D003 + + ; ---------------------- + ; BOOT ZERO PAGE EQUATES + ; ---------------------- + +BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS +BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT +BSECT EQU $3D ; (BYTE) BOOT SECTOR TO READ + + ; ---------------- + ; HARDWARE EQUATES + ; ---------------- + +KBD EQU $C000 ; KEY STROBE +ANYKEY EQU $C010 ; ANY KEY DOWN FLAG +TXTSET EQU $C051 ; SWITCH FOR TEXT MODE +MIXCLR EQU $C052 ; SWITCH FOR MIX MODE CLEAR +LOWSCR EQU $C054 ; SWITCH FOR PAGE 1 SELECT + + ; ------------------------ + ; IDOS INTERFACE VARIABLES + ; ------------------------ + +DCBSLT EQU $60 ; (BYTE) TARGET SLOT ID +DCBPSL EQU DCBSLT+1 ; (BYTE) PREVIOUSLY ACCESSED SLOT +DCBDRV EQU DCBSLT+2 ; (BYTE) TARGET DRIVE ID +DCBPDR EQU DCBSLT+3 ; (BYTE) PREVIOUSLY ACCESSED DRIVE +DCBSEC EQU DCBSLT+4 ; (BYTE) TARGET SECTOR +DCBTRK EQU DCBSLT+5 ; (BYTE) TARGET TRACK +DCBERR EQU DCBSLT+6 ; (BYTE) DRIVE ERROR CODE +DCBCMD EQU DCBSLT+7 ; (BYTE) DISK COMMAND ID +DCBBFL EQU DCBSLT+8 ; (BYTE) LO POINTER TO DATA BUFFER +DCBBFH EQU DCBSLT+9 ; (BYTE) HI POINTER TO DATA BUFFER +DRVFLG EQU DCBSLT+10 ; (BYTE) CURRENT DRIVE +SLTMP3 EQU DCBSLT+11 ; (BYTE) TRACK-SEEK SLOT +TTRK EQU DCBSLT+12 ; (BYTE) TARGET TRACK +DTMP3 EQU DCBSLT+13 ; (BYTE) WORK BYTE +DTMP4 EQU DCBSLT+14 ; (BYTE) SLOT ID * 16 +HDRCHK EQU DCBSLT+15 ; (BYTE) CHECKSUM FOUND +HDRSEC EQU DCBSLT+16 ; (BYTE) SECTOR FOUND +HDRTRK EQU DCBSLT+17 ; (BYTE) TRACK FOUND +HDRVOL EQU DCBSLT+18 ; (BYTE) VOLUME FOUND +DCNT EQU DCBSLT+19 ; (BYTE) MOTOR TIME COUNT +DTMP2 EQU DCBSLT+20 ; (BYTE) TEMP + + ; --------------------- + ; DISK HARDWARE EQUATES + ; --------------------- + +PH0OFF EQU $C080 ; STEP MOTOR POSITION #0 +DRVOFF EQU $C088 ; DRIVE MOTOR OFF +DRVON EQU $C089 ; DRIVE MOTOR ON +DRV0EN EQU $C08A ; ENGAGE DRIVE #1 +DRV1EN EQU $C08B ; ENGAGE DRIVE #2 +Q6L EQU $C08C ; READ DATA LATCH +Q6H EQU $C08D ; WRITE DATA LATCH +Q7L EQU $C08E ; SET READ MODE +Q7H EQU $C08F ; SET WRITE MODE + + ; ----------------- + ; MONITOR VARIABLES + ; ----------------- + +WLEFT EQU $20 ; LEFT MARGIN (0) +WWIDTH EQU $21 ; RIGHT MARGIN (40 OR 80) +WTOP EQU $22 ; TOP LINE (0-23) +WBOTM EQU $23 ; BOTTOM LINE (1-24) +CH EQU $24 ; CURSOR HORIZONTAL +CV EQU $25 ; CURSOR VERTICAL +BASL EQU $28 ; SCREEN LINE +INVFLG EQU $32 ; CHAR OUTPUT MASK ($FF=NORM, $3F=INVERSE) +PROMPT EQU $33 ; PROMPT CHARACTER (SET TO >) +CSW EQU $36 ; CHARACTER OUTPUT VECTOR +RNUM1 EQU $4E ; RANDOM #'S GENERATED BY +RNUM2 EQU $4F ; MONITOR GETKEY +EH EQU $057B ; CURSOR HORIZONTAL (IIE/C) + + ; ---------------- + ; MONITOR ROUTINES + ; ---------------- + +BASCAL EQU $FC22 ; CALC LINE BASE ADDRESS +BELL EQU $FF3A ; MAKE A NOISE +CLEOL EQU $FC9C ; CLEAR TO END OF LINE +CLEOS EQU $FC42 ; CLEAR TO END OF SCREEN +HOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR +MCOUT EQU $FDED ; CHAR OUTPUT +COUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN +RDKEY EQU $FD0C ; READ KEY +GETLN1 EQU $FD6F ; GET LINE + + END + diff --git a/apple/zip/hardeq.h b/apple/zip/hardeq.h new file mode 100644 index 0000000..24fa9f7 --- /dev/null +++ b/apple/zip/hardeq.h @@ -0,0 +1,138 @@ + PAGE + SBTTL "--- HARDWARE EQUATES: APPLE II ---" + + ; ------------------- + ; APPLE II MEMORY MAP + ; ------------------- + +LBUFF EQU $0200 ; LINE INPUT BUFFER (80 BYTES) +SCREEN EQU $0400 ; START OF SCREEN RAM +LSTLNE EQU $07D0 ; LAST LINE OF SCREEN RAM +ZIP EQU $0800 ; START OF EXECUTABLE ZIP CODE + +IOBUFF EQU ZIP+$2100 ; PAGING BUFFER (ASSUME 8K+ ZIP) +BUFFA EQU IOBUFF+$0100 ; SECTOR DECODE BUFFER, LOWER HALF +BUFFB EQU BUFFA+$0100 ; SECTOR DECODE BUFFER, UPPER HALF + +PTABL EQU BUFFB+$0100 ; PAGING TABLE, LSBS +PTABH EQU PTABL+$0100 ; PAGING TABLE, MSBS +LRUMAP EQU PTABH+$0100 ; TIMESTAMP TABLE + +ZSTAKL EQU LRUMAP+$0100 ; Z-STACK LSBS +ZSTAKH EQU ZSTAKL+$0100 ; Z-STACK MSBS +LOCALS EQU ZSTAKH+$0100 ; LOCAL VARIABLE STORAGE (30 BYTES) +BUFSAV EQU LOCALS+$20 ; AUXILIARY INPUT BUFFER (80 BYTES) + +ZBEGIN EQU LOCALS+$0100 ; START OF Z-PRELOAD + + ; --------- + ; CONSTANTS + ; --------- + +ARROW EQU $08 ; LEFT ARROW (BACKSPACE) +EOL EQU $0D ; EOL CHAR +LF EQU $0A ; LINE FEED +SPACE EQU $20 ; SPACE CHAR +BACKSP EQU $7F ; BACKSPACE + +READ EQU $00 ; "READ" COMMAND +WRITE EQU $01 ; "WRITE" COMMAND + +TOP EQU 1 ; NORMAL TOP EXCLUDING STATUS LINE +BOTM EQU 24 ; BOTTOM SCREEN LINE + +ZTRKF EQU 2 ; FIRST TRACK GAME IS ON +ZTRKL EQU 36 ; ANYTHING FROM HERE UP IS ILLEGAL + + ; ---------------------- + ; BOOT ZERO PAGE EQUATES + ; ---------------------- + +BADDR EQU $26 ; (WORD) ROM BOOT ADDRESS +BSLOT EQU $2B ; (BYTE) ROM BOOT SLOT +BSECT EQU $3D ; (BYTE) BOOT SECTOR TO READ + + ; ---------------- + ; HARDWARE EQUATES + ; ---------------- + +KBD EQU $C000 ; KEY STROBE +ANYKEY EQU $C010 ; ANY KEY DOWN FLAG +TXTSET EQU $C051 ; SWITCH FOR TEXT MODE +MIXCLR EQU $C052 ; SWITCH FOR MIX MODE CLEAR +LOWSCR EQU $C054 ; SWITCH FOR PAGE 1 SELECT + + ; ------------------------ + ; IDOS INTERFACE VARIABLES + ; ------------------------ + +DCBSLT EQU $60 ; (BYTE) TARGET SLOT ID +DCBPSL EQU DCBSLT+1 ; (BYTE) PREVIOUSLY ACCESSED SLOT +DCBDRV EQU DCBSLT+2 ; (BYTE) TARGET DRIVE ID +DCBPDR EQU DCBSLT+3 ; (BYTE) PREVIOUSLY ACCESSED DRIVE +DCBSEC EQU DCBSLT+4 ; (BYTE) TARGET SECTOR +DCBTRK EQU DCBSLT+5 ; (BYTE) TARGET TRACK +DCBERR EQU DCBSLT+6 ; (BYTE) DRIVE ERROR CODE +DCBCMD EQU DCBSLT+7 ; (BYTE) DISK COMMAND ID +DCBBFL EQU DCBSLT+8 ; (BYTE) LO POINTER TO DATA BUFFER +DCBBFH EQU DCBSLT+9 ; (BYTE) HI POINTER TO DATA BUFFER +DRVFLG EQU DCBSLT+10 ; (BYTE) CURRENT DRIVE +SLTMP3 EQU DCBSLT+11 ; (BYTE) TRACK-SEEK SLOT +TTRK EQU DCBSLT+12 ; (BYTE) TARGET TRACK +DTMP3 EQU DCBSLT+13 ; (BYTE) WORK BYTE +DTMP4 EQU DCBSLT+14 ; (BYTE) SLOT ID * 16 +HDRCHK EQU DCBSLT+15 ; (BYTE) CHECKSUM FOUND +HDRSEC EQU DCBSLT+16 ; (BYTE) SECTOR FOUND +HDRTRK EQU DCBSLT+17 ; (BYTE) TRACK FOUND +HDRVOL EQU DCBSLT+18 ; (BYTE) VOLUME FOUND +DCNT EQU DCBSLT+19 ; (BYTE) MOTOR TIME COUNT +DTMP2 EQU DCBSLT+20 ; (BYTE) TEMP + + ; --------------------- + ; DISK HARDWARE EQUATES + ; --------------------- + +PH0OFF EQU $C080 ; STEP MOTOR POSITION #0 +DRVOFF EQU $C088 ; DRIVE MOTOR OFF +DRVON EQU $C089 ; DRIVE MOTOR ON +DRV0EN EQU $C08A ; ENGAGE DRIVE #1 +DRV1EN EQU $C08B ; ENGAGE DRIVE #2 +Q6L EQU $C08C ; READ DATA LATCH +Q6H EQU $C08D ; WRITE DATA LATCH +Q7L EQU $C08E ; SET READ MODE +Q7H EQU $C08F ; SET WRITE MODE + + ; ----------------- + ; MONITOR VARIABLES + ; ----------------- + +WLEFT EQU $20 ; LEFT MARGIN (0) +WWIDTH EQU $21 ; RIGHT MARGIN (40 OR 80) +WTOP EQU $22 ; TOP LINE (0-23) +WBOTM EQU $23 ; BOTTOM LINE (1-24) +CH EQU $24 ; CURSOR HORIZONTAL +CV EQU $25 ; CURSOR VERTICAL +BASL EQU $28 ; SCREEN LINE +INVFLG EQU $32 ; CHAR OUTPUT MASK ($FF=NORM, $3F=INVERSE) +PROMPT EQU $33 ; PROMPT CHARACTER (SET TO >) +CSW EQU $36 ; CHARACTER OUTPUT VECTOR +RNUM1 EQU $4E ; RANDOM #'S GENERATED BY +RNUM2 EQU $4F ; MONITOR GETKEY +EH EQU $057B ; CURSOR HORIZONTAL (IIE/C) + + ; ---------------- + ; MONITOR ROUTINES + ; ---------------- + +BASCAL EQU $FC22 ; CALC LINE BASE ADDRESS +BELL EQU $FF3A ; MAKE A NOISE +CLEOL EQU $FC9C ; CLEAR TO END OF LINE +CLEOS EQU $FC42 ; CLEAR TO END OF SCREEN +HOME EQU $FC58 ; CLEAR SCREEN/HOME CURSOR +MCOUT EQU $FDED ; CHAR OUTPUT +COUT1 EQU $FDF0 ; CHAR OUTPUT TO SCREEN +RDKEY EQU $FD0C ; READ KEY +GETLN1 EQU $FD6F ; GET LINE + + END + diff --git a/apple/zip/io.g b/apple/zip/io.g new file mode 100644 index 0000000..15ea13d --- /dev/null +++ b/apple/zip/io.g @@ -0,0 +1,601 @@ + PAGE + SBTTL "--- GAME I/O: APPLE II ---" + + ; -------------- + ; INTERNAL ERROR + ; -------------- + + ; ENTRY: ERROR CODE IN [A] + ; EXIT: HA! + +ERRM: DB "Internal error " +ENUMB: DB "00." +ERRML EQU $-ERRM + +ZERROR: CLD + LDY #1 ; CONVERT ERROR BYTE IN [A] +ZERR0: LDX #0 ; TO ASCII AT "ENUMB" +ZERR1: CMP #10 + BCC ZERR2 + SBC #10 + INX + BNE ZERR1 +ZERR2: ORA #'0' + STA ENUMB,Y + TXA + DEY + BPL ZERR0 + + LDX #LOW ERRM + LDA #HIGH ERRM + LDY #ERRML + JSR DLINE ; PRINT ERROR MESSAGE + + ; FALL THROUGH ... + + ; ---- + ; QUIT + ; ---- + +ZQUIT: JSR ZCRLF ; FLUSH BUFFER + + LDX #LOW ENDM + LDA #HIGH ENDM + LDY #ENDML + JSR DLINE ; "END OF STORY" + +FREEZE: JMP FREEZE ; AND STOP + +ENDM: DB "End of story." + DB EOL +ENDML EQU $-ENDM + + ; ------- + ; RESTART + ; ------- + +ZSTART: LDX #0 + STX WTOP ;RESET FULL SCREEN FOR CLEAR + LDA ZBEGIN+ZSCRIP+1 ; PRINTING? + AND #%00000001 + BEQ STEX ; NO + DEX ; = $FF + STX PSTAT ; MARK SO WILL CONTINUE TO PRINT + +STEX: JMP WARM ;AND DO WARMSTART + + ; -------------------- + ; PRINT VERSION NUMBER + ; -------------------- + +VERS: DB "Apple II Version G" + DB EOL +VERSL EQU $-VERS + +VERNUM: JSR ZCRLF ; FLUSH BUFFER + + LDX #LOW VERS + LDA #HIGH VERS + LDY #VERSL + JMP DLINE ; PRINT ID AND RETURN + + ; -------------------------- + ; RETURN TOP RAM PAGE IN [A] + ; -------------------------- + +MEMTOP: LDA $FBB3 ; CHECK MACHING IDENTIFICATION + CMP #II + BNE MEM2 + JMP TOP48 ; IT'S A II, USE 48K TOP +MEM2: CMP #IIPLUS + BEQ MEM0 ; GO CHECK IF II+ OR III + CMP #IIC + BEQ MEM3 + JMP TOP48 ; IF NOT A STANDARD, GIVE IT 48K ONLY +MEM3: LDA $FBC0 + BNE MEM4 + JMP TOP128 ; IT'S A IIC, USE 128K TOP +MEM4: CMP #IIE + BEQ MEM1 ; GO CHECK AMT OF MEMORY IIE HAS + JMP TOP48 ; NOT STANDARD, USE 48K TOP + +MEM0: LDA $FB1E + CMP #III + BNE MEM5 + JMP TOP48 ; IT'S A III, USE 48K TOP + + ; OK, IT'S A II+, CHECK IF 48 OR 64 K OF MEMORY AVAILABLE + +MEM5: LDA #0 + STA TSTVAL + LDA BNK1RW ; SET TO R/W BANK 1 RAM + LDA BNK1RW +MEMLP1: LDY #0 + LDA TSTVAL +MEMLP2: STA $D000,Y ; WRITE A PG OF TSTVAL TO + INY ; $D000 RAM + BNE MEMLP2 + +MEMLP3: LDA $D000,Y + CMP TSTVAL + BNE NO64 ; NO COMPARE, THE MEMORY ISN'T THERE + INY + BNE MEMLP3 ; CHECK WHOLE PAGE + + INC TSTVAL + BNE MEMLP1 ; CHECK WITH 0 -> FF + + LDA ROMRAM ; RESET TO ROM + LDA ROMRAM + +TOP64: LDA #0 + LDY #$FF + RTS ; SEND BACK VALUE FOR 64K + +NO64: LDA ROMRAM ; RESET TO ROM + LDA ROMRAM + JMP TOP48 ; GO SET TO 48K ROP + + ; IT'S A IIE, CHECK IF 64 OR 128 K OF AVAILABLE MEMORY + +MEM1: LDA #0 ; START @ 0 + STA TSTVAL + LDA BNK1RW ; SETY TO BANK 1 RAM + LDA BNK1RW + +MEMLP4: LDY #0 + LDA TSTVAL +MEMLP5: STA $D000,Y ; WRITE [TSTVAL] TO + INY ; HIGH MAIN MEMORY + BNE MEMLP5 + + INC TSTVAL + LDA TSTVAL + STA ALTZPS ; SET TO AUX MEMORY + +MEMLP6: STA $D000,Y ; WRITE NEXT VALUE + INY ; TO AUX MEM + BNE MEMLP6 + + STA ALTZPC ; SET TO MAIN MEM + DEC TSTVAL ; RESET TO [TSTVAL] WRITTEN TO MAIN + +MEMLP7: LDA $D000,Y ; CHECK IF WHAT WRITTEN + CMP TSTVAL ; 1ST TO MAIN MEM D000 PG + BNE NO128 ; IS STILL THERE + INY + BNE MEMLP7 + + INC TSTVAL + STA ALTZPS ; & SET TO AUX MEM + +MEMLP8: LDA $D000,Y ; & SEE IF WHAT WROTE + CMP TSTVAL ; TO AUX MEM IS STILL THERE + BNE NO128 + INY + BNE MEMLP8 + + STA ALTZPC ; RESET TO MAIN MEM + LDA TSTVAL ; LAST THING WAS INC'D + BNE MEMLP4 ; GO TRY W/ NEXT SET OF VALUES, DO 0,1 -> FF,0 + + LDA ROMRAM ; RESET TO ROM + LDA ROMRAM + +TOP128: ; MOVE RTN TO READ FROM 48K AUX MEM + ; TO HIGH MEM SO IT CAN BE USED + + LDA BNK1RW ; SET BANK 1 TO RECEIVE + LDA BNK1RW + LDY #B48LNG +MOVRTN: LDA B48,Y + STA $D000,Y + DEY + BPL MOVRTN + LDA ROMRAM ; RESET ROM + LDA ROMRAM + JMP TOPEX ; SKIP OVER THE RTN MOVED + +B48: STA RAMRDS ; SET READ 48K AUX + LDA $FF00,Y ; PICK UP CHAR (FAKE ADDR) + STA RAMRDC ; SET BACK TO MAIN 48K RAM + RTS +B48LNG EQU $-B48 + +TOPEX: LDA #1 ; $1FA IS TOP USABLE BUFFER NUMBER + LDY #$FB + RTS + +NO128: STA ALTZPC ; RESET TO MAIN MEMORY + LDA ROMRAM ; RESET TO ROM + LDA ROMRAM + JMP TOP64 ; GO SET TO 64K + +TOP48: LDA #0 + LDY #$C0 + RTS + + + ; -------------------------------- + ; RETURN RANDOM BYTES IN [A] & [X] + ; -------------------------------- + +RANDOM: INC RNUM1 + DEC RNUM2 + LDA RNUM1 ;GENERATED BY MONITOR GETBYT + ADC RAND1 + TAX + LDA RNUM2 + SBC RAND2 + STA RAND1 + STX RAND2 + RTS + + ; ------------------- + ; Z-PRINT A CHARACTER + ; ------------------- + + ; ENTRY: ASCII CHAR IN [A] + +COUT: CMP #$0D ; IF ASCII EOL, + BEQ ZCRLF ; DO IT! + CMP #SPACE ; IGNORE ALL OTHER + BCC CEX ; CONTROLS + + LDX LENGTH ; GET LINE POINTER + STA LBUFF,X ; ADD CHAR TO BUFFER + CPX XSIZE ; END OF LINE? + BCS FLUSH ; YES, FLUSH THE LINE + INC LENGTH ; ELSE UPDATE POINTER + +CEX: RTS + + ; ------------------- + ; FLUSH OUTPUT BUFFER + ; ------------------- + + ; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: LDA #SPACE + +FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR + BEQ FL1 ; IN THE LINE + DEX + BNE FL0 ; IF NONE FOUND, + LDX XSIZE ; FLUSH ENTIRE LINE + +FL1: STX OLDLEN ; SAVE OLD LINE POS HERE + STX LENGTH ; MAKE IT THE NEW LINE LENGTH + + JSR ZCRLF ; PRINT LINE UP TO LAST SPACE + + ; START NEW LINE WITH REMAINDER OF OLD + + LDX OLDLEN ; GET OLD LINE POS + LDY #0 ; START NEW LINE AT BEGINNING +FL2: INX + CPX XSIZE ; CONTINUE IF + BCC FL3 ; INSIDE OR + BEQ FL3 ; AT END OF LINE + STY LENGTH ; ELSE SET NEW LINE LENGTH + RTS + +FL3: LDA LBUFF,X ; GET CHAR FROM OLD LINE + STA LBUFF,Y ; MOVE TO START OF NEW LINE + INY ; UPDATE LENGTH OF NEW LINE + BNE FL2 ; (ALWAYS) + + ; --------------- + ; CARRIAGE RETURN + ; --------------- + +ZCRLF: LDA SPLITF ; AT SPLIT SCREEN + BNE ZCRLF0 ; YES + + INC LINCNT ; NEW LINE GOING OUT +ZCRLF0: LDX LENGTH ; INSTALL EOL + LDA #$8D ; (MUST! BE $8D FOR PRINTER Le 5/8/85) + STA LBUFF,X ; AT END OF CURRENT LINE + INC LENGTH ; UPDATE LINE LENGTH + LDX LINCNT ; IS IT TIME TO + INX ; (A LINE FOR "MORE") + CPX WBOTM ; PRINT "MORE" YET? + BCC CR1 ; NO, CONTINUE + + ; SCREEN FULL; PRINT "MORE" + + JSR ZUSL ; UPDATE STATUS LINE + + LDX WTOP + INX + STX LINCNT ; RESET LINE COUNTER + + BIT ANYKEY ; CLEAR STROBE SO GET CLEAN READING + + LDA #HIGH MORE + LDX #LOW MORE + LDY #MOREL + JSR DLINE + +WAIT: BIT KBD + BPL WAIT + BIT ANYKEY ;CLEAR STROBE SO THIS KEY WILL BE DISCOUNTED + + LDA #0 + STA CH + STA EH + JSR CLEOL ;CLEAR TO EOL + + LDX LENGTH + BEQ LINEX ; SKIP IF EMPTY + +CR1: + +LINOUT: LDY LENGTH ; IF BUFFER EMPTY, + BEQ LINEX ; DON'T PRINT ANYTHING + STY PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + + LDX #0 ; SEND CONTENTS OF [LBUFF] +LOUT: LDA LBUFF,X ; TO SCREEN + JSR CHAR + INX + DEY + BNE LOUT + + JSR PPRINT ; PRINT [LBUFF] IF ENABLED + LDA #0 ; RESET LINE LENGTH + STA LENGTH ; TO ZERO + +LINEX: RTS ; AND RETURN + +MORE: DB "[MORE]" +MOREL EQU $-MORE + + ; ---------------------- + ; UPDATE THE STATUS LINE + ; ---------------------- + +ZUSL: JSR LINOUT ;CLEAR LAST LINE TO SCREEN + + LDA EH ;SAVE CURRENT CURSOR POSITION + PHA + LDA CH + PHA + LDA CV + PHA + + LDA LENGTH ; SAVE ALL + PHA ; STRING-PRINTING + LDA MPCH ; VARIABLES + PHA + LDA MPCM + PHA + LDA MPCL + PHA + LDA TSET + PHA + LDA PSET + PHA + LDA ZWORD+HI + PHA + LDA ZWORD+LO + PHA + LDA ZFLAG + PHA + LDA DIGITS + PHA + LDA WTOP + PHA + + LDX XSIZE +USL0: LDA LBUFF,X ; MOVE CONTENTS OF [LBUFF] + STA BUFSAV,X ; TO [BUFSAV] + LDA #SPACE ; CLEAR + STA LBUFF,X ; [LBUFF] WITH SPACES + DEX + BPL USL0 + + LDA #0 + STA LENGTH ; RESET LINE LENGTH + STA SCRIPT ; DISABLE SCRIPTING + STA WTOP ; SET WINDOW TO INCLUDE STATUS LINE + + STA CH ;HOME THE CURSOR + STA EH + STA CV + JSR BASCAL + + LDA #$3F ;AND SET INVERSE VIDEO + STA INVFLG + + ; PRINT ROOM DESCRIPTION + + LDA #16 ; GLOBAL VAR #16 (ROOM ID) + JSR GETVRG ; GET IT INTO [VALUE] + LDA VALUE+LO + JSR PRNTDC ; PRINT SHORT ROOM DESCRIPTION + + LDA COL80 ;GET 80 COL FLAG + BEQ USL3 ;NOT 80 COL + LDA #60 ;THIS IS WHERE TO PRINT SCORE/TIME + BNE USL4 ;(ALWAYS) +USL3: LDA #23 ;OLD MIDDLE OF SCREEN +USL4: STA LENGTH + + LDA #SPACE ; TRUNCATE LONG DESCS + JSR COUT ; WITH A SPACE + + LDA #17 ; GLOBAL VAR #17 (SCORE/HOURS) + JSR GETVRG ; GET IT INTO [VALUE] + + LDA TIMEFL ; GET MODE FLAG + BNE DOTIME ; USE TIME MODE IF NON-ZERO + + ; PRINT "SCORE" + + LDA #'S' + JSR COUT + LDA #'c' + JSR COUT + LDA #'o' + JSR COUT + LDA #'r' + JSR COUT + LDA #'e' + JSR COUT + LDA #':' + JSR COUT + LDA #SPACE + JSR COUT + + LDA VALUE+LO ; MOVE SCORE VALUE + STA QUOT+LO ; INTO [QUOT] + LDA VALUE+HI ; FOR PRINTING + STA QUOT+HI + JSR NUMBER ; PRINT SCORE VALUE IN DECIMAL + + LDA #'/' ; PRINT A SLASH + BNE MOVMIN ; BRANCH ALWAYS + + ; PRINT "TIME" + +DOTIME: LDA #'T' + JSR COUT + LDA #'i' + JSR COUT + LDA #'m' + JSR COUT + LDA #'e' + JSR COUT + LDA #':' + JSR COUT + LDA #SPACE + JSR COUT + + LDA VALUE+LO ; 00 IS REALLY 24 + BNE DT0 + LDA #24 +DT0: CMP #13 ; IS HOURS > 12, + BCC DT1 + SBC #12 ; CONVERT TO 1-12 +DT1: STA QUOT+LO ; MOVE FOR PRINTING + LDA #0 + STA QUOT+HI ; CLEAR MSB + JSR NUMBER + + LDA #':' ; COLON + +MOVMIN: JSR COUT ; PRINT SLASH OR COLON + + LDA #18 ; GLOBAL VAR #18 (MOVES/MINUTES) + JSR GETVRG ; GET IT INTO [VALUE] + LDA VALUE+LO ; MOVE TO [QUOT] + STA QUOT+LO ; FOR EVENTUAL PRINTING + LDA VALUE+HI + STA QUOT+HI + + LDA TIMEFL ; WHICH MODE? + BNE DOMINS ; TIME IF NZ + + ; PRINT NUMBER OF MOVES + + JSR NUMBER ; SHOW # MOVES + JMP STATEX ; ALL DONE + + ; PRINT MINUTES + +DOMINS: LDA VALUE+LO ; CHECK MINUTES + CMP #10 ; IF MORE THAN TEN + BCS DOM0 ; CONTINUE + + LDA #'0' ; ELSE PRINT A + JSR COUT ; PADDING "0" FIRST + +DOM0: JSR NUMBER ; SHOW MINUTES + + LDA #SPACE + JSR COUT ; SEPARATE THINGS + + LDA #17 ; CHECK "HOURS" AGAIN + JSR GETVRG + LDA VALUE+LO + CMP #12 ; PAST NOON? + BCS DOPM ; YES, PRINT "PM" + + LDA #'a' ; ELSE PRINT "AM" + BNE DOXM ; BRANCH ALWAYS + +DOPM: LDA #'p' + +DOXM: JSR COUT + LDA #'m' + JSR COUT + + ; STATUS LINE READY + +STATEX: LDX #0 +STX0: LDA LBUFF,X ; GET A CHAR FROM [LBUFF] + JSR CHAR ; SEND TO SCREEN + INX ; LOOP TILL + CPX LENGTH ; ALL CHARS SENT + BCC STX0 + +STX1: CPX WWIDTH ; REAL END OF LINE + BCS STX2 + LDA #$A0 ; FILL REST OF LINE WITH BLANKS + JSR MCOUT + INX + BNE STX1 ; MAX 80 SO IT'S A JUMP + +STX2: LDA #$0FF ;AND CLEAR OFF INVERSE + STA INVFLG + + LDX XSIZE ; RESTORE OLD [LBUFF] +STX3: LDA BUFSAV,X + STA LBUFF,X + DEX + BPL STX3 + + PLA ; RESTORE ALL + STA WTOP ; SAVED VARIABLES + PLA + STA DIGITS + PLA + STA ZFLAG + PLA + STA ZWORD+LO + PLA + STA ZWORD+HI + PLA + STA PSET + PLA + STA TSET + PLA + STA MPCL + PLA + STA MPCM + PLA + STA MPCH + PLA + STA LENGTH + + PLA ;RESTORE CURSOR POSITION + STA CV + PLA + STA CH + PLA + STA EH ;** IIe'S CH + JSR BASCAL + + LDX #$FF + STX SCRIPT ; RE-ENABLE SCRIPTING + INX ; = 0 + STX MPCFLG ; INVALIDATE [MPC] + RTS + + +STRYM DB "The story is loading ..." +STRYML EQU $-STRYM + + END + diff --git a/apple/zip/io.l b/apple/zip/io.l new file mode 100644 index 0000000..6e5487e --- /dev/null +++ b/apple/zip/io.l @@ -0,0 +1,479 @@ + PAGE + SBTTL "--- GAME I/O: APPLE II ---" + + ; -------------- + ; INTERNAL ERROR + ; -------------- + + ; ENTRY: ERROR CODE IN [A] + ; EXIT: HA! + +ERRM: DB "Internal error " +ENUMB: DB "00." +ERRML EQU $-ERRM + +ZERROR: CLD + LDY #1 ; CONVERT ERROR BYTE IN [A] +ZERR0: LDX #0 ; TO ASCII AT "ENUMB" +ZERR1: CMP #10 + BCC ZERR2 + SBC #10 + INX + BNE ZERR1 +ZERR2: ORA #'0' + STA ENUMB,Y + TXA + DEY + BPL ZERR0 + + LDX #LOW ERRM + LDA #HIGH ERRM + LDY #ERRML + JSR DLINE ; PRINT ERROR MESSAGE + + ; FALL THROUGH ... + + ; ---- + ; QUIT + ; ---- + +ZQUIT: JSR ZCRLF ; FLUSH BUFFER + + LDX #LOW ENDM + LDA #HIGH ENDM + LDY #ENDML + JSR DLINE ; "END OF STORY" + +FREEZE: JMP FREEZE ; AND STOP + +ENDM: DB "End of session." + DB EOL +ENDML EQU $-ENDM + + ; ------- + ; RESTART + ; ------- + +ZSTART: LDX #0 + STX WTOP ;RESET FULL SCREEN FOR CLEAR + LDA ZBEGIN+ZSCRIP+1 ; PRINTING? + AND #%00000001 + BEQ STEX ; NO + DEX ; = $FF + STX PSTAT ; MARK SO WILL CONTINUE TO PRINT + +STEX: JMP WARM ;AND DO WARMSTART + + ; -------------------- + ; PRINT VERSION NUMBER + ; -------------------- + +VERS: DB "Apple II Version L" + DB EOL +VERSL EQU $-VERS + +VERNUM: JSR ZCRLF ; FLUSH BUFFER + + LDX #LOW VERS + LDA #HIGH VERS + LDY #VERSL + JMP DLINE ; PRINT ID AND RETURN + + ; -------------------------- + ; RETURN TOP RAM PAGE IN [A] + ; -------------------------- + +MEMTOP: LDA #$BF ; FOR NOW, ASSUME 48K + RTS + + ; -------------------------------- + ; RETURN RANDOM BYTES IN [A] & [X] + ; -------------------------------- + +RANDOM: INC RNUM1 + DEC RNUM2 + LDA RNUM1 ;GENERATED BY MONITOR GETBYT + ADC RAND1 + TAX + LDA RNUM2 + SBC RAND2 + STA RAND1 + STX RAND2 + RTS + + ; ------------------- + ; Z-PRINT A CHARACTER + ; ------------------- + + ; ENTRY: ASCII CHAR IN [A] + +COUT: CMP #$0D ; IF ASCII EOL, + BEQ ZCRLF ; DO IT! + CMP #SPACE ; IGNORE ALL OTHER + BCC CEX ; CONTROLS + + LDX LENGTH ; GET LINE POINTER + STA LBUFF,X ; ADD CHAR TO BUFFER + CPX XSIZE ; END OF LINE? + BCS FLUSH ; YES, FLUSH THE LINE + INC LENGTH ; ELSE UPDATE POINTER + +CEX: RTS + + ; ------------------- + ; FLUSH OUTPUT BUFFER + ; ------------------- + + ; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: LDA #SPACE + +FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR + BEQ FL1 ; IN THE LINE + DEX + BNE FL0 ; IF NONE FOUND, + LDX XSIZE ; FLUSH ENTIRE LINE + +FL1: STX OLDLEN ; SAVE OLD LINE POS HERE + STX LENGTH ; MAKE IT THE NEW LINE LENGTH + + JSR ZCRLF ; PRINT LINE UP TO LAST SPACE + + ; START NEW LINE WITH REMAINDER OF OLD + + LDX OLDLEN ; GET OLD LINE POS + LDY #0 ; START NEW LINE AT BEGINNING +FL2: INX + CPX XSIZE ; CONTINUE IF + BCC FL3 ; INSIDE OR + BEQ FL3 ; AT END OF LINE + STY LENGTH ; ELSE SET NEW LINE LENGTH + RTS + +FL3: LDA LBUFF,X ; GET CHAR FROM OLD LINE + STA LBUFF,Y ; MOVE TO START OF NEW LINE + INY ; UPDATE LENGTH OF NEW LINE + BNE FL2 ; (ALWAYS) + + ; --------------- + ; CARRIAGE RETURN + ; --------------- + +ZCRLF: LDA SPLITF ; AT SPLIT SCREEN + BNE ZCRLF0 ; YES + + INC LINCNT ; NEW LINE GOING OUT +ZCRLF0: LDX LENGTH ; INSTALL EOL + LDA #$8D ; (MUST! BE $8D FOR PRINTER Le 5/8/85) + STA LBUFF,X ; AT END OF CURRENT LINE + INC LENGTH ; UPDATE LINE LENGTH + LDX LINCNT ; IS IT TIME TO + INX ; (A LINE FOR "MORE") + CPX WBOTM ; PRINT "MORE" YET? + BCC CR1 ; NO, CONTINUE + + ; SCREEN FULL; PRINT "MORE" + + JSR ZUSL ; UPDATE STATUS LINE + + LDX WTOP + INX + STX LINCNT ; RESET LINE COUNTER + + BIT ANYKEY ; CLEAR STROBE SO GET CLEAN READING + + LDA #HIGH MORE + LDX #LOW MORE + LDY #MOREL + JSR DLINE + +WAIT: BIT KBD + BPL WAIT + BIT ANYKEY ;CLEAR STROBE SO THIS KEY WILL BE DISCOUNTED + + LDA #0 + STA CH + STA EH + JSR CLEOL ;CLEAR TO EOL + + LDX LENGTH + BEQ LINEX ; SKIP IF EMPTY + +CR1: + +LINOUT: LDY LENGTH ; IF BUFFER EMPTY, + BEQ LINEX ; DON'T PRINT ANYTHING + STY PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + + LDX #0 ; SEND CONTENTS OF [LBUFF] +LOUT: LDA LBUFF,X ; TO SCREEN + JSR CHAR + INX + DEY + BNE LOUT + + JSR PPRINT ; PRINT [LBUFF] IF ENABLED + LDA #0 ; RESET LINE LENGTH + STA LENGTH ; TO ZERO + +LINEX: RTS ; AND RETURN + +MORE: DB "[MORE]" +MOREL EQU $-MORE + + ; ---------------------- + ; UPDATE THE STATUS LINE + ; ---------------------- + +ZUSL: JSR LINOUT ;CLEAR LAST LINE TO SCREEN + + LDA EH ;SAVE CURRENT CURSOR POSITION + PHA + LDA CH + PHA + LDA CV + PHA + + LDA LENGTH ; SAVE ALL + PHA ; STRING-PRINTING + LDA MPCH ; VARIABLES + PHA + LDA MPCM + PHA + LDA MPCL + PHA + LDA TSET + PHA + LDA PSET + PHA + LDA ZWORD+HI + PHA + LDA ZWORD+LO + PHA + LDA ZFLAG + PHA + LDA DIGITS + PHA + LDA WTOP + PHA + + LDX XSIZE +USL0: LDA LBUFF,X ; MOVE CONTENTS OF [LBUFF] + STA BUFSAV,X ; TO [BUFSAV] + LDA #SPACE ; CLEAR + STA LBUFF,X ; [LBUFF] WITH SPACES + DEX + BPL USL0 + + LDA #0 + STA LENGTH ; RESET LINE LENGTH + STA SCRIPT ; DISABLE SCRIPTING + STA WTOP ; SET WINDOW TO INCLUDE STATUS LINE + + STA CH ;HOME THE CURSOR + STA EH + STA CV + JSR BASCAL + + LDA #$3F ;AND SET INVERSE VIDEO + STA INVFLG + + ; PRINT ROOM DESCRIPTION + + LDA #16 ; GLOBAL VAR #16 (ROOM ID) + JSR GETVRG ; GET IT INTO [VALUE] + LDA VALUE+LO + JSR PRNTDC ; PRINT SHORT ROOM DESCRIPTION + + LDA COL80 ;GET 80 COL FLAG + BEQ USL3 ;NOT 80 COL + LDA #60 ;THIS IS WHERE TO PRINT SCORE/TIME + BNE USL4 ;(ALWAYS) +USL3: LDA #23 ;OLD MIDDLE OF SCREEN +USL4: STA LENGTH + + LDA #SPACE ; TRUNCATE LONG DESCS + JSR COUT ; WITH A SPACE + + LDA #17 ; GLOBAL VAR #17 (SCORE/HOURS) + JSR GETVRG ; GET IT INTO [VALUE] + + LDA TIMEFL ; GET MODE FLAG + BNE DOTIME ; USE TIME MODE IF NON-ZERO + + ; PRINT "SCORE" + + LDA #'S' + JSR COUT + LDA #'c' + JSR COUT + LDA #'o' + JSR COUT + LDA #'r' + JSR COUT + LDA #'e' + JSR COUT + LDA #':' + JSR COUT + LDA #SPACE + JSR COUT + + LDA VALUE+LO ; MOVE SCORE VALUE + STA QUOT+LO ; INTO [QUOT] + LDA VALUE+HI ; FOR PRINTING + STA QUOT+HI + JSR NUMBER ; PRINT SCORE VALUE IN DECIMAL + + LDA #'/' ; PRINT A SLASH + BNE MOVMIN ; BRANCH ALWAYS + + ; PRINT "TIME" + +DOTIME: LDA #'T' + JSR COUT + LDA #'i' + JSR COUT + LDA #'m' + JSR COUT + LDA #'e' + JSR COUT + LDA #':' + JSR COUT + LDA #SPACE + JSR COUT + + LDA VALUE+LO ; 00 IS REALLY 24 + BNE DT0 + LDA #24 +DT0: CMP #13 ; IS HOURS > 12, + BCC DT1 + SBC #12 ; CONVERT TO 1-12 +DT1: STA QUOT+LO ; MOVE FOR PRINTING + LDA #0 + STA QUOT+HI ; CLEAR MSB + JSR NUMBER + + LDA #':' ; COLON + +MOVMIN: JSR COUT ; PRINT SLASH OR COLON + + LDA #18 ; GLOBAL VAR #18 (MOVES/MINUTES) + JSR GETVRG ; GET IT INTO [VALUE] + LDA VALUE+LO ; MOVE TO [QUOT] + STA QUOT+LO ; FOR EVENTUAL PRINTING + LDA VALUE+HI + STA QUOT+HI + + LDA TIMEFL ; WHICH MODE? + BNE DOMINS ; TIME IF NZ + + ; PRINT NUMBER OF MOVES + + JSR NUMBER ; SHOW # MOVES + JMP STATEX ; ALL DONE + + ; PRINT MINUTES + +DOMINS: LDA VALUE+LO ; CHECK MINUTES + CMP #10 ; IF MORE THAN TEN + BCS DOM0 ; CONTINUE + + LDA #'0' ; ELSE PRINT A + JSR COUT ; PADDING "0" FIRST + +DOM0: JSR NUMBER ; SHOW MINUTES + + LDA #SPACE + JSR COUT ; SEPARATE THINGS + + LDA #17 ; CHECK "HOURS" AGAIN + JSR GETVRG + LDA VALUE+LO + CMP #12 ; PAST NOON? + BCS DOPM ; YES, PRINT "PM" + + LDA #'a' ; ELSE PRINT "AM" + BNE DOXM ; BRANCH ALWAYS + +DOPM: LDA #'p' + +DOXM: JSR COUT + LDA #'m' + JSR COUT + + ; STATUS LINE READY + +STATEX: LDX #0 +STX0: LDA LBUFF,X ; GET A CHAR FROM [LBUFF] + JSR CHAR ; SEND TO SCREEN + INX ; LOOP TILL + CPX LENGTH ; ALL CHARS SENT + BCC STX0 + +STX1: CPX WWIDTH ; REAL END OF LINE + BCS STX2 + LDA #$A0 ; FILL REST OF LINE WITH BLANKS + JSR MCOUT + INX + BNE STX1 ; MAX 80 SO IT'S A JUMP + +STX2: LDA #$0FF ;AND CLEAR OFF INVERSE + STA INVFLG + + LDX XSIZE ; RESTORE OLD [LBUFF] +STX3: LDA BUFSAV,X + STA LBUFF,X + DEX + BPL STX3 + + PLA ; RESTORE ALL + STA WTOP ; SAVED VARIABLES + PLA + STA DIGITS + PLA + STA ZFLAG + PLA + STA ZWORD+LO + PLA + STA ZWORD+HI + PLA + STA PSET + PLA + STA TSET + PLA + STA MPCL + PLA + STA MPCM + PLA + STA MPCH + PLA + STA LENGTH + + PLA ;RESTORE CURSOR POSITION + STA CV + PLA + STA CH + PLA + STA EH + LDX COL80 + BEQ STX4 ; 40 COL + + ; BASCAL SEEMS TO USE CH EXCLUSIVELY ON IIe, EVEN THOUGH + ; NEEDS EH FOR MOST USE IF 80 COLUMN. SO SET CH FOR BASCAL. + ; IIc DOESN'T CARE WHAT YOU DO. + + STA CH ; FOR IIe (VERSION J, 11/7/85) +STX4: JSR BASCAL + + LDX #$FF + STX SCRIPT ; RE-ENABLE SCRIPTING + INX ; = 0 + STX MPCFLG ; INVALIDATE [MPC] + RTS + + +STRYM DB "The story is loading ..." +STRYML EQU $-STRYM + + END + diff --git a/apple/zip/machine.g b/apple/zip/machine.g new file mode 100644 index 0000000..75243f6 --- /dev/null +++ b/apple/zip/machine.g @@ -0,0 +1,829 @@ + PAGE + SBTTL "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + ; ---------------------------- + ; FETCH ASCII KEYCODE INTO [A] + ; ---------------------------- + + ; EXIT: ASCII IN [A] & [IOCHAR] + +GETKEY: CLD + TXA ; SAVE [X] & [Y] + PHA + TYA + PHA + +GKEY0: LDA COL80 ; ** THIS IS A TEMPORARY, CHEATER'S ** + BEQ GKEY1 ; ** PATCH THAT MUST BE MADE INTO ** + LDA EH ; ** A SENSIBLE SOLUTION AT THE ** + STA CH ; ** FIRST OPORTUNITY ** + +GKEY1: JSR RDKEY ; GET A CHAR + + ;CHECK TO MAKE SURE KEY IS VALID, ONLY ACCEPT IT IF IT IS + + AND #$7F ;SCREEN OUT SHIFTS + CMP #EOL ;CHECK FOR GOOD (BAD) CHAR + BNE GK1 + JMP OK +GK1: CMP #BACKSP + BNE GK2 + JMP OK +GK2: CMP #ARROW + BNE GK3 + JMP OK +GK3: CMP #SPACE ;NO CTRL CHARS WANTED + BCC BADKEY ;IF < SPACE, BAD + CMP #$2B ;CLEAR OUT UNWANTED KEYS + BEQ BADKEY + + CMP #$3C ;CHANGE <_>)@%^&*( TO ,-.0256789 + BNE B ;EXCHANGE THESE TO ELIMINATE + LDA #$2C ;UNWANTED VALUES + BNE OK ;JMP +B: CMP #$5F + BNE C + LDA #$2D + BNE OK ;JMP +C: CMP #$3E + BNE D + LDA #$2E + BNE OK ;JMP +D: CMP #$29 + BNE E + LDA #$30 + BNE OK ;JMP +E: CMP #$40 + BNE F + LDA #$32 + BNE OK ;JMP +F: CMP #$25 + BNE G + LDA #$35 + BNE OK ;JMP +G: CMP #$5E + BNE H + LDA #$36 + BNE OK ;JMP +H: CMP #$26 + BNE L + LDA #$37 + BNE OK ;JMP +L: CMP #$2A + BNE M + LDA #$38 + BNE OK ;JMP +M: CMP #$28 + BNE N + LDA #$39 + BNE OK ;JMP + +N: CMP #$3C + BCC OK + CMP #$3F + BEQ OK + +MASK0: CMP #'z'+1 ;PICK OUT LETTERS NOW + BCS BADKEY ;IF > BAD + CMP #'a' + BCS OK ;IF > OK + CMP #'A' + BCC BADKEY + CMP #'Z'+1 + BCC OK ;IF < OK + +BADKEY: JSR BOOP ;BAD KEY, GIVE WARNING NOISE + JMP GKEY0 ;TRY AGAIN + +OK: STA IOCHAR ;HOLD ON TO IT + + ADC RNUM1 ;FUTZ WITH RANDOM + STA RNUM1 + EOR RNUM2 + STA RNUM2 + + 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 + + LDA IOCHAR + CMP #$60 + BCC CHAR1 ;LESS THAN a + CMP #$80 + BCS CHAR1 ;GREATER THAN z + LDX COL80 + BNE CHAR1 ;ONLY CONVERT IF 40 COLUMN + AND #%11011111 ;STRIP LOWER CASE BIT + +CHAR1: ORA #%10000000 ;SET BIT 7 SO WILL BE NORMAL IF WANTED + JSR MCOUT + + PLA ; RESTORE [X] AND [Y] + TAY + PLA + TAX + RTS + + ; --------------------- + ; FETCH A LINE OF INPUT + ; --------------------- + + ; ENTRY: ABS ADDR OF READ BUFFER IN [ARG1] + ; EXIT: # CHARS READ IN [A] + +INPUT: JSR LINOUT ; FLUSH [LBUFF] + + LDY WTOP + STY LINCNT ; RESET LINE COUNT + INC LINCNT ; 1 FOR THIS LINE + LDY #0 ; AND CHAR 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 + CMP #ARROW ; LEFT ARROW (BACKSPACE)? + BEQ BACKUP + + 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 + CMP #ARROW ; BACKSPACE + BEQ BACKUP + JSR BOOP ; ELSE COMPLAIN + JMP NOMORE ; AND INSIST + + ; HANDLE BACKSPACE + +BACKUP: DEY ; BACK UP THE POINTER + BMI BBAD + LDA #$08 ;BACKSP STRANGE SO DO 082008 + JSR CHAR + LDA #$20 + JSR CHAR + LDA #$08 + BNE SHOWIT ;JMP + +BBAD: JSR BOOP ; ELSE SCREAM WITH PAIN + LDY #0 ; RESET POINTER + BEQ INLOOP ; AND WAIT FOR SOMETHING BETTER + + ; HANDLE END OF LINE + +ENDLIN: LDA #$8D ; (MUST BE $8D FOR PRINTER Le 5/8/85) + 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] + +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 + + LDX COL80 + BNE LEX3 ; 80 COL. + CMP #40 + BCC LEX3 + INC LINCNT ; USED 2 LINES + +LEX3: 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] + +PLEAV: RTS + +PPRINT: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? + BEQ PLEAV ; NO, SCRAM IMMEDIATELY + + LDA ZBEGIN+ZSCRIP+1 ; CHECK SCRIPT FLAG + AND #%00000001 ; SCRIPTING ON? + BEQ PLEAV ; NO, EXIT + + LDA CSW+LO ;SAVE NORMAL OUTPUT HOOK + PHA + LDA CSW+HI + PHA + + LDA CH ;SAVE CURRENT CURSOR POSITION + PHA + LDA EH ; IF 80 COL + PHA + + LDA ALTCSW+LO ;LOAD SCRIPTING HOOK + STA CSW+LO + LDA ALTCSW+HI + STA CSW+HI + + LDA #0 + STA CH + STA EH + +PP4: LDY #0 +PP5: LDA LBUFF,Y ;GET A CHAR TO SEND OUT + JSR MCOUT + INY + DEC PRLEN ;LINE COUNT + BNE PP5 ;PRINT WHOLE LINE + + ;ALL DONE, RESET TO NORMAL AND LEAVE + + PLA ;RETRIEVE CURRENT CURSOR POSITION + STA EH + PLA + STA CH + PLA + STA CSW+HI + PLA + STA CSW+LO + +PEX: RTS + + +SLOTM: DB EOL + DB "Printer Slot 1-7: " +SLOTML EQU $-SLOTM + +PSTAT: DB 0 ;SET TO CLEAR WHEN BOOT, + ;I PUT IT HERE SO RESTART WON'T ALTER +ALTCSW: DB 0,0 ;(WORD) PRINTER COUT + + ; ------------ + ; PRINTER INIT + ; ------------ + +PCHK: LDX #LOW SLOTM ;ASK WHICH SLOT PRINTER IS IN + LDA #HIGH SLOTM + LDY #SLOTML + JSR DLINE + + LDA #0 ;ACTUALLY SLOT 1 + JSR DODEF ;DISPLAY IT AS DEFAULT + + JSR GETKEY + CMP #EOL + BEQ PC2 ;USE DEFAULT + SEC + SBC #"0" + CMP #8 ;1-7 + BCS PCHK ;OOPS + BCC PC3 ;SKIP AROUND DEFAULT +PC2: LDA #1 ;WHICH IS 1 +PC3: CLC + ADC #$C0 + STA ALTCSW+HI + + JSR PISSER ;SEND TO SCREEN FOR NEATNESS + + INC PSTAT ;SET TO ON + + LDA CSW+LO ;SAVE NORMAL OUTPUT HOOK + PHA + LDA CSW+HI + PHA + LDA ALTCSW+LO ;LOAD SCRIPTING HOOK + STA CSW+LO + LDA ALTCSW+HI + STA CSW+HI + +PP0: LDA #$89 ; OUTPUT PRINTER SETUP SEQUENCE + JSR MCOUT ; START WITH COMMAND CHAR + LDA #$B8 ; 8 (80 COL WIDE) + JSR MCOUT + LDA #$B0 ; 0 + JSR MCOUT + LDA #$CE ; N (LF AFTER CR) + JSR MCOUT + + LDA CSW+LO ; SAVE REAL PRINTER OUTPUT + STA ALTCSW+LO ; LOC. FOR NEXT TIME + LDA CSW+HI + STA ALTCSW+HI + + PLA ; RESET NORMAL OUTPUT + STA CSW+HI + PLA + STA CSW+LO + + ; PRINTER SETUP ON THE IIc COPIES THE ROM INTERRUPT VECTOR + ; FROM $FFFE IN ROM TO BOTH MAIN & AUX. RAM PAGES @ $FFFE + ; THOSE PAGES ARE BEING USED TO CONTAIN A PAGE OF GAME + ; CODE. THE FOLLOWING RTN CAUSES THE NEXT USE OF THOSE + ; PAGES TO READ THEM IN NEW FROM THE DISK SO THAT THE VALUES + ; WILL ALL BE CORRECT. (6/14/85 Le) + + LDA #HIGH PTABL ; SET TBL SO CAN + STA I+HI ; ACCESS ALL OF IT + LDA #LOW PTABL + STA I+LO + + LDA #$EE ; THIS IS ID OF MAIN RAM PG $FF + SEC + SBC PAGE0 ; GET OFFSET OF PAGE IN PTABL + ASL A ; WORD ALIGNED TBL + CLC + ADC I+LO ; ALIGN AT THAT PAGE IN THE TABLE + STA I+LO + BCC PC4 + INC I+HI ; PICK UP CARRY +PC4: LDA #$FF + LDY #0 + STA (I),Y ; ERASE PAGE @ $FF + INY ; AS IF NOT THERE + STA (I),Y + LDA #$F8 ; LOW BYTE OF OFFSET TO + CLC ; AUX. MEMORY PAGE $FF + ADC I+LO + STA I+LO + LDA I+HI + ADC #1 ; ADD CARRY AND HIGH BYTE OFFSET + STA I+HI + + LDA #$FF ; AND ERASE PAGE + STA (I),Y ; IN AUX. MEM LOCATION TOO + DEY + STA (I),Y + + LDA #0 + STA ZPCFLG ; INVALIDATE ZPNT + STA MPCFLG ; AND MPNT TO FORCE NEW READ + RTS + + + ; ------------ + ; SPLIT SCREEN + ; ------------ + + ; SPLIT SCREEN AT LINE [ARG1] + ; DISABLE SPLIT IF [ARG1] = 0 + ; IGNORE IF SPLIT ALREADY ENABLED OR [ARG1] >= 20 + +ZSPLIT: LDA ZBEGIN+ZMODE + AND #%00100000 ;CHECK IF ENABLED + BEQ ZSPOUT ;NOT, LEAVE + + LDA ARG1+LO ;GET # OF LINES FOR SCREEN + BEQ NORL ;IF 0 THEN RESTORE SCREEN + LDX SPSTAT ;CHECK IF ALREADY ENABLED + BNE ZSPOUT ;IT IS + CMP #20 ;IS SPLIT REALLY = WHOLE SCREEN + BCS ZSPOUT ;YES, IGNORE + + PHA + CLC + ADC #1 ;ONE LINE ADDITIONAL TO SIZE GIVEN + ;TO MAKE UP FOR STATUS LINE + STA WBOTM ;TEMPORARILY FOR TOP SCREEN CLEAR + STA SPSTAT ;NON ZERO = SCREEN IS SPLIT + JSR HOME ;CLEAR FROM TOP TO BOTTOM (OF TOP SCREEN) + LDA #$18 ;RESTORE BOTTOM FOR SCROLL + STA WBOTM + PLA ;GET @ OF LINES AGAIN + CLC + ADC #1 ;ADD 1 + STA WTOP ;MAKE THAT THE TOP OF THE SECOND SCREEN + LDA #1 + STA CH + STA EH + LDA #$16 + STA CV ;RESTORE CURSOR AFTER HOME CALL + JMP PISSER ; TO MAKE CV WORK +ZSPOUT: RTS + +NORL: ;RESTORE SCREEN TO FULL SCREEN MODE + + LDA #1 ;PUT CURSOR AT TOP OF SCREEN + STA WTOP ;RESTORE FULL SCREEN ALIGNMENT + LDA #0 + STA LINCNT + STA SPSTAT ;FLAG NOT SPLIT + RTS + + ; ------ + ; SCREEN + ; ------ + + ; GO TO TOP WINDOW (TOP OF SCREEN) IF [A] = 1 + ; GO TO BOTTOM OF SCREEN IF [A] = 0 + ; IGNORE IF SPLIT NOT ENABLED OR [A] <> 0 OR 1 + + ; FLAG SPLITF WILL BE SET FOR OUTPUT TO DETERMINE + ; IF AND WHICH WINDOW TO DISPLAY TO + ; (0=BOTTOM 1=TOP) + + +ZSCRN: LDA ZBEGIN+ZMODE + AND #%00100000 ;CHECK IF ENABLED + BEQ ZSPOUT ;NOT, LEAVE + + LDA SPSTAT ;CHECK IF SCREEN IS SPLIT + BEQ ZSPOUT ;NO, SO JUST LEAVE + LDA ARG1+LO ;CHECK WHICH WINDOW + BNE SCRN1 ;TOP SCREEN + + STA SPLITF ;SET FLAG TO SPLIT SCREEN (0) + LDA #01 ;PUT CURSOR AT BOTTOM OF SCREEN + STA CH + STA EH + LDA #$16 + STA CV + BNE SCRNP ;JMP TO RTN +SCRN1: CMP #01 + BNE ZSPOUT ;INVALID SCREEN ID + STA SPLITF ;SET FLAG TO UNSCROLLING SCREEN (1) + + LDA #0 + STA CH + STA EH + STA CV ;ALIGN AT TOP OF SCREEN +SCRNP: JMP PISSER ;CALL RTN TO SET CURSOR (+ LEAVE) + + + ; --------- + ; RAZZ USER + ; --------- + +BOOP EQU BELL ;MONITOR BELL + + ; ------------ + ; CLEAR SCREEN + ; ------------ + +CLS EQU HOME ;CLEAR & HOME CURSOR + +PISSER: LDA COL80 ;SEND APPROPRIATE TO SCREEN + BEQ PISS ;IF = 0 THEN 40 COL. + LDA #$0D + BNE PIS ;JMP +PISS LDA #$8D +PIS JMP MCOUT + + +GETBUF: LDA ZPAGE+HI ; DIVIDE BY 2, WORD ALIGNED + LSR A + STA HOLD+HI + LDA ZPAGE+LO + ROR A + CLC + ADC PAGE0+LO ; ADD TO PAGING START FOR + STA HOLD+LO ; ACTUAL BUFFER IN MEMORY TO USE + LDA HOLD+HI + ADC PAGE0+HI + AND #%00000001 + BNE GETAUX ; PAGE BUFFER IS IN AUX. MEMORY + + LDA HOLD+LO + CMP #$C0 + BCS GETHI ; PAGE BUFFER IS IN HIGH MAIN MEMORY + + STA DBUFF+HI ; SET PAGE TO READ TO + JSR GETDSK ; AND READ PAGE IN + RTS + +GETHI: PHA ; SAVE DESTINATION BUFFER + LDA #HIGH IOBUFF ; FAKE GETDSK INTO NOT MOVING + STA DBUFF+HI ; THE PAGE ANYWHERE + JSR GETDSK + PLA ; NOW GET DESTINATION OF PAGE + BCS GETBEX ; OOPS + JSR HIMOV ; AND MOVE IT THERE + CLC ; CLEAR CARRY FOR OK +GETBEX: RTS + +GETAUX: LDA #HIGH IOBUFF ; FAKE GETDSK INTO NOT MOVING + STA DBUFF+HI ; THE PAGE ANYWHERE + JSR GETDSK + LDA HOLD+LO ; NOW GET DESTINATION OF PAGE + BCS GETBEX ; OOPS + JSR MOVBUF ; AND MOVE IT THERE + CLC ; CLEAR CARRY FOR OK + RTS + +ALIGN: RTS + +ALIGNM: RTS + + ; ------------------------- + ; SOFT SWITCHES FOR AUX RAM + ; ------------------------- + +BNK1RD EQU $C088 ; ALLOWS READ OF BANK1 RAM (MAIN/AUX) +BNK2RD EQU $C080 ; ALLOWS READ OF BANK2 RAM + +BNK1RW EQU $C08B ; 2 READS ENABLES R/W TO BANK 1 +BNK2RW EQU $C083 ; 2 + +RAMRDS EQU $C003 ; ALLOWS READ OF 48K AUX MEM +RAMRDC EQU $C002 ; SETS FOR READ OF MAIN 48K BANK + +RAMWRTS EQU $C005 ; SET WRITE TO AUX MEM +RAMWRTC EQU $C004 ; MAIN MEM + +ALTZPS EQU $C009 ; SETS FOR R/W OF AUX MEM + ; PAGES 0, 1, $D000-$FFFF +ALTZPC EQU $C008 ; SETS FOR MAIN. + +ROMRAM EQU $C089 ; READ ROM, WRITE RAM, BANK1 + ; REQUIRES 2 READS + + ; ************** + ; + ; TO USE 63K OF ALTERNATE RAM IN THE IIE OR IIC, VIEW + ; THE MEMORY AS A NUMBER OF BUFFERS. + ; EACH BUFFER IS ONE PAGE AND COINCIDES WITH ONE RAM PAGE. + ; (80 COL. USES $400 - $7FF FOR VIDEO DISPLAY) + + ; ** THE BUFFER (NN) IS NOT NESSISARILY RAM (NNXX) ** + + ; BUFFER NUMBER RAM PAGE + ; ------------- -------- + ; MAIN + ; + ; C0 -> EE : D1 -> FF BANK 1 + ; EF -> FE : D0 -> DF BANK 2 + ; + ; AUXILIARY + ; + ; FF -> 00 : 00 -> 01 + ; 01 -> BA : 02 -> 03, 08 -> BF + ; BB -> EA : DO -> FF BANK 1 + ; EB -> FA : DO -> DF BANK 2 + + ; AS THIS INTERPRETER IS IN MAIN RAM 48K, RTNS TO HANDLE + ; READING FROM 48K AUX MEMORY MUST BE IN HIGH MEM + ; THOSE RTNS ARE PLACED AT $D000 IN COLDSTART + + ; ----- + ; HIBYT + ; ----- + + ; GET BYTE FROM HIGH MAIN MEMORY BUFFER + ; EXIT BYTE IN ALL ELSE UNCHANGED + +HIBYT: SEI + CMP #$EF + BCC BNK1 + + SBC #$1F ; CONVERT TO BANK2 ADDR + STA B2ADD+1+HI ; PLACE IT IN CODE + LDA BNK2RD ; READ BANK 2 + LDA BNK2RD +B2ADD: LDA $FF00,Y ; GET CHAR FROM BANK 2 + LDX ROMRAM ; RESET TO ROM + LDX ROMRAM + CLI + RTS + +BNK1: ADC #$11 ; CONVERT TO BANK1 ADDR + STA B1ADD+1+HI + LDA BNK1RD + LDA BNK1RD +B1ADD: LDA $FF00,Y ; (FAKE ADDR) + LDX ROMRAM ; RESET TO ROM + LDX ROMRAM + CLI + RTS + + ; ----- + ; HIMOV + ; ----- + + ; TRANSFER [IOBUFF] CONTENTS TO HIGH MAIN MEMORY BLOCK IN [A] + +HIMOV: SEI + CMP #$EF + BCC MBNK1 + + SBC #$1F ; SET TO WRITE TO BANK 2 + STA M2ADD+1+HI + LDA BNK2RW + LDA BNK2RW + JMP HIMOV0 + +MBNK1: ADC #$11 ; CONVERT TO BANK 1 ADDR + STA M2ADD+1+HI + LDA BNK1RW + LDA BNK1RW + +HIMOV0: LDY #0 +HIMLP: LDA IOBUFF,Y ; READ FROM LOW MEMORY BUFFER +M2ADD: STA $FF00,Y ; WRITE TO HIGH PAGE + INY + BNE HIMLP + + LDA ROMRAM ; RESET TO ROM + LDA ROMRAM + CLI + RTS + + + ; ------ + ; BUFBYT + ; ------ + + ; GET BYT FROM AUX MEM BUFFER + ; EXIT BYTE IN ALL ELSE UNCHANGED + +BUFBYT: SEI ; COULD BE BAD IF AN INTERUPT OCCURED + CMP #$FF ; FF,0 = 0,1 + BEQ BSKP1 + TAX + BEQ BSKP1 ; TO PAGE 0 OR 1 BLOCK + + CMP #$BB + BCC BUF48 ; TO 48K BLOCK + + CMP #$EB + BCC BSKP2 ; TO BANK1 + + ; TO BANK 2 + SBC #$1B ; C=1 ADJUST TO RAM LOC. + STA BADD+1+HI ; SET DUMMY ADDR TO CORRECT ONE + + LDA BNK2RD + LDA BNK2RD +B1GET: STA ALTZPS ; SET TO AUX MEM +BADD: LDA $FF00,Y ; FAKE ADDR (WILL BE SET APPROPRIATELY) + LDX ROMRAM ; RESET WHEN DONE TO ROM + LDX ROMRAM + STA ALTZPC + CLI + RTS + + ; TO BANK 1 AUX MEM +BSKP2: ADC #$14 ; C=0 ADJUST TO RAM LOC. (+14, +1 LATER) + LDX BNK1RD ; SET FOR BANK 1 + LDX BNK1RD + + ; TO PAGE 0 OR 1 AUX MEM +BSKP1: CLC + ADC #1 + STA BADD+1+HI ; SET DUMMY ADDR + + JMP B1GET ; GO DO MOVE + + ; TO 48K AUX MEMORY + +BUF48: CLC + ADC #1 + CMP #4 ; IF PG 2 OR 3, OK + BCC BSKP0 + CLC + ADC #4 ; ELSE SKIP OVER 4 VIDEO PAGES +BSKP0: LDX BNK1RW ; SET TO R/W TO MAIN BANK1 + LDX BNK1RW + STA B48ADD+1+HI + JSR B48GET ; RTN IS @ $D000 MAIN HIGH MEM + LDX ROMRAM ; RESET TO ROM + LDX ROMRAM + CLI + RTS + +;---------------------------------------------------------------- +; THIS IS RTN AT $D000 SO CAN READ FROM AUX MEM +; +;B48GET:STA RAMRDS ; SET READ 48K AUX +;B48ADD:LDA $FF00,Y ; PICK UP CHAR (FAKE ADDR) +; STA RAMRDC ; SET BACK TO MAIN 48K RAM +; RTS +; +;----------------------------------------------------------------- + + ; ------ + ; MOVBUF + ; ------ + + ; TRANSFERS THE DATA AT (IOBUFF) INTO THE AUX MEMORY BLOCK + +MOVBUF: SEI + CMP #$FF ; FF,0 = 0,1 + BEQ MBSKP1 + TAX + BEQ MBSKP1 ; TO PAGE 0 OR 1 BLOCK + + CMP #$BB + BCC MOV48 ; TO 48K BLOCK + + CMP #$EB + BCC MBSKP2 ; TO BANK1 + + ; TO BANK 2 + SBC #$1B ; CARRY=1 ADJUST TO RAM LOC. + LDY BNK2RW ; SET TO WRITE TO BANK 2 + LDY BNK2RW + JMP MBSKP3 ; GO DO MOVE + + ; TO BANK 1 AUX MEM +MBSKP2: ADC #$14 ; CARRY=0 ADJUST TO RAM LOC. (+14, +1 LATER) + LDX BNK1RW + LDX BNK1RW + + ; TO PAGE 0 OR 1 AUX MEM +MBSKP1: CLC + ADC #1 +MBSKP3: STA MOVADD+1+HI ; SET DUMMY ADDR TO CORRECT ONE +MOV1: STA ALTZPS ; SET TO AUX MEMORY + + LDY #0 ; INIT INDEX +MOVLP: LDA IOBUFF,Y ; GET A CHAR FROM WHERE STORING IT +MOVADD: STA $FF00,Y ; AND PLACE IT IN REAL ADDR (FAKE ADDR) + INY + BNE MOVLP + STA ALTZPC ; AND RESET MEMORY WHEN DONE + LDY ROMRAM + LDY ROMRAM + CLI + RTS + + ; TO 48K AUX MEMORY + +MOV48: CLC + ADC #1 + CMP #4 ; IF PG 2 OR 3, OK + BCC MSKP0 + CLC + ADC #4 ; ELSE SKIP OVER 4 VIDEO PAGES +MSKP0: STA M48ADD+1+HI + STA RAMWRTS ; SET TO WRITE TO 48K AUX. + + LDY #0 ; INIT INDEX +MLP: LDA IOBUFF,Y ; READ FROM MAIN RAM BUFFER +M48ADD: STA $FF00,Y ; TO AUX RAM PAGE (FAKE ADDR) + INY + BNE MLP + + STA RAMWRTC + CLI + RTS + + END + diff --git a/apple/zip/machine.l b/apple/zip/machine.l new file mode 100644 index 0000000..caf73c7 --- /dev/null +++ b/apple/zip/machine.l @@ -0,0 +1,492 @@ + + PAGE + SBTTL "--- MACHINE-DEPENDENT I/O: APPLE II ---" + + ; ---------------------------- + ; FETCH ASCII KEYCODE INTO [A] + ; ---------------------------- + + ; EXIT: ASCII IN [A] & [IOCHAR] + +GETKEY: CLD + TXA ; SAVE [X] & [Y] + PHA + TYA + PHA + +GKEY0: JSR RDKEY ;GET A CHAR + + ;CHECK TO MAKE SURE KEY IS VALID, ONLY ACCEPT IT IF IT IS + + AND #$7F ;SCREEN OUT SHIFTS + CMP #EOL ;CHECK FOR GOOD (BAD) CHAR + BNE GK0 + JMP OK +GK0: CMP #BACKSP + BNE GK5 + JMP OK +GK5: CMP #ARROW + BNE GK1 + JMP OK + + ; CHECK FOR "ARROWS", CONVERT FOR USE (EZIP) + ; ALSO : CHANGE <_>)@%^&*( TO ,-.0256789 + +GK1: LDX #ENDKEY ; GET LENGTH OF LIST +GK2: CMP HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + BEQ GK3 ; FOUND IT + DEX + BPL GK2 ; CHECK THEM ALL + BMI GK4 ; NOT FOUND, CONTINUE OTHER CHECKS +GK3: LDA WANT,X ; GET KEY TO USE INSTEAD + BNE OK ; JMP + +GK4: CMP #SPACE ; NO CTRL CHARS ACCEPTABLE + BCC BADKEY ; IF < SPACE, BAD + CMP #$2B + BEQ BADKEY + + CMP #$3C + BCC OK + CMP #$3F + BEQ OK + +MASK0: CMP #'z'+1 ;PICK OUT LETTERS NOW + BCS BADKEY ;IF > BAD + CMP #'a' + BCS OK ;IF > OK + CMP #'A' + BCC BADKEY + CMP #'Z'+1 + BCC OK ;IF < OK + +BADKEY: JSR BOOP ;BAD KEY, GIVE WARNING NOISE + JMP GKEY0 ;TRY AGAIN + +OK: STA IOCHAR ;HOLD ON TO IT + + ADC RNUM1 ;FUTZ WITH RANDOM + STA RNUM1 + EOR RNUM2 + STA RNUM2 + + PLA ; RESTORE + TAY ; EVERYTHING + PLA + TAX + LDA IOCHAR ; GET CHAR INTO [A] + RTS ; AND RETURN IT + +HAVE: DB $3C,$5F,$3E,$29,$40,$25,$5E,$26,$2A,$28 +WANT: DB $2C,$2D,$2E,$30,$32,$35,$36,$37,$38,$39 +ENDKEY EQU $-WANT-1 + + + ; ----------------- + ; PRINT CHAR IN [A] + ; ----------------- + +CHAR: STA IOCHAR ; SAVE HERE + TXA ; SAVE [X] AND [Y] + PHA + TYA + PHA + + LDA IOCHAR + CMP #$61 ; (L) + BCC CHAR1 ;LESS THAN a + CMP #$7B ; (L) + BCS CHAR1 ;GREATER THAN z + LDX COL80 + BNE CHAR1 ;ONLY CONVERT IF 40 COLUMN + AND #%11011111 ;STRIP LOWER CASE BIT + +CHAR1: ORA #%10000000 ;SET BIT 7 SO WILL BE NORMAL IF WANTED + JSR MCOUT + + PLA ; RESTORE [X] AND [Y] + TAY + PLA + TAX + RTS + + ; --------------------- + ; FETCH A LINE OF INPUT + ; --------------------- + + ; ENTRY: ABS ADDR OF READ BUFFER IN [ARG1] + ; EXIT: # CHARS READ IN [A] + +INPUT: JSR LINOUT ; FLUSH [LBUFF] + + LDY WTOP + STY LINCNT ; RESET LINE COUNT + INC LINCNT ; 1 FOR THIS LINE + LDY #0 ; AND CHAR 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 + CMP #ARROW ; LEFT ARROW (BACKSPACE)? + BEQ BACKUP + + 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 + CMP #ARROW ; BACKSPACE + BEQ BACKUP + JSR BOOP ; ELSE COMPLAIN + JMP NOMORE ; AND INSIST + + ; HANDLE BACKSPACE + +BACKUP: DEY ; BACK UP THE POINTER + BMI BBAD + LDA #$08 ;BACKSP STRANGE SO DO 082008 + JSR CHAR + LDA #$20 + JSR CHAR + LDA #$08 + BNE SHOWIT ;JMP + +BBAD: JSR BOOP ; ELSE SCREAM WITH PAIN + LDY #0 ; RESET POINTER + BEQ INLOOP ; AND WAIT FOR SOMETHING BETTER + + ; HANDLE END OF LINE + +ENDLIN: LDA #$8D ; (MUST BE $8D FOR PRINTER Le 5/8/85) + 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] + +LEX1: CMP #'A' ; IF CHAR IS ALPHA, + BCC LEX2 ; CONVERT TO LOWER CASE + CMP #'Z'+1 + BCS LEX2 + ADC #$20 + +LEX2: AND #$7F ; HIGH BIT OFF + STA (ARG1),Y ; MOVE CHAR TO INPUT BUFFER AT [ARG1] + DEY ; LOOP TILL + BNE LEX0 ; ALL CHARS MOVED + + JSR PPRINT ; SCRIPT [LBUFF] IF ENABLED + + LDA LINLEN ; RESTORE # CHARS + + LDX COL80 + BNE LEX3 ; 80 COL. + CMP #40 + BCC LEX3 + INC LINCNT ; USED 2 LINES + +LEX3: 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] + +PLEAV: RTS + +PPRINT: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? + BEQ PLEAV ; NO, SCRAM IMMEDIATELY + + LDA ZBEGIN+ZSCRIP+1 ; CHECK SCRIPT FLAG + AND #%00000001 ; SCRIPTING ON? + BEQ PLEAV ; NO, EXIT + + LDA CSW+LO ;SAVE NORMAL OUTPUT HOOK + PHA + LDA CSW+HI + PHA + + LDA CH ;SAVE CURRENT CURSOR POSITION + PHA + LDA EH ; IF 80 COL + PHA + + LDA ALTCSW+LO ;LOAD SCRIPTING HOOK + STA CSW+LO + LDA ALTCSW+HI + STA CSW+HI + + LDA #0 + STA CH + STA EH + + IF 0 + + ;PRINTER INIT SEQUENCE FROM OLD ZIP (I DON'T KNOW) + + LDA PSTAT ;CHECK PRINTER STATUS + CMP #1 + BNE PP4 ;OPEN, ONLY DO ONCE + + INC PSTAT ;SET TO DONE + +PP0: LDA #$89 ;OUTPUT PRINTER SETUP SEQUENCE + JSR MCOUT ; + LDA CSW+HI + STA ALTCSW+HI + LDA CSW+LO + STA ALTCSW+LO + + ; (SETTING BYTE $779 REMOVED - UNNECCESARY COMPLICATION) + ; (HANDLED BY THE ^I 80N Le 5/8/85) + + LDA #$B8 ; 8 (80 COL WIDE) + JSR MCOUT + LDA #$B0 ; 0 + JSR MCOUT + LDA #$CE ; N (LF AFTER CR) + JSR MCOUT + LDA #$8D ; (GUY AT APPLE SAID THIS A GOOD IDEA) + JSR MCOUT + + ENDIF + +PP4: LDY #0 +PP5: LDA LBUFF,Y ;GET A CHAR TO SEND OUT + JSR MCOUT + INY + DEC PRLEN ;LINE COUNT + BNE PP5 ;PRINT WHOLE LINE + + ;ALL DONE, RESET TO NORMAL AND LEAVE + + PLA ;RETRIEVE CURRENT CURSOR POSITION + STA EH + PLA + STA CH + PLA + STA CSW+HI + PLA + STA CSW+LO + +PEX: RTS + + +SLOTM: DB EOL + DB "Printer Slot 1-7: " +SLOTML EQU $-SLOTM + +PSTAT: DB 0 ;SET TO CLEAR WHEN BOOT, + ;I PUT IT HERE SO RESTART WON'T ALTER +ALTCSW: DB 0,0 ;(WORD) PRINTER COUT + + ; ------------ + ; PRINTER INIT + ; ------------ + +PCHK: LDX #LOW SLOTM ;ASK WHICH SLOT PRINTER IS IN + LDA #HIGH SLOTM + LDY #SLOTML + JSR DLINE + + LDA #0 ;ACTUALLY SLOT 1 + JSR DODEF ;DISPLAY IT AS DEFAULT + + JSR GETKEY + CMP #EOL + BEQ PC2 ;USE DEFAULT + SEC + SBC #"0" + CMP #8 ;1-7 + BCS PCHK ;OOPS + BCC PC3 ;SKIP AROUND DEFAULT +PC2: LDA #1 ;WHICH IS 1 +PC3: CLC + ADC #$C0 + STA ALTCSW+HI + + JSR PISSER ;SEND TO SCREEN FOR NEATNESS + + INC PSTAT ;SET TO ON + + LDA CSW+LO ;SAVE NORMAL OUTPUT HOOK + PHA + LDA CSW+HI + PHA + LDA ALTCSW+LO ;LOAD SCRIPTING HOOK + STA CSW+LO + LDA ALTCSW+HI + STA CSW+HI + +PP0: LDA #$89 ; OUTPUT PRINTER SETUP SEQUENCE + JSR MCOUT ; START WITH COMMAND CHAR + LDA #$B8 ; 8 (80 COL WIDE) + JSR MCOUT + LDA #$B0 ; 0 + JSR MCOUT + LDA #$CE ; N (LF AFTER CR) + JSR MCOUT + + LDA CSW+LO ; SAVE REAL PRINTER OUTPUT + STA ALTCSW+LO ; LOC. FOR NEXT TIME + LDA CSW+HI + STA ALTCSW+HI + + PLA ; RESET NORMAL OUTPUT + STA CSW+HI + PLA + STA CSW+LO + + RTS + + + ; ------------ + ; SPLIT SCREEN + ; ------------ + + ; SPLIT SCREEN AT LINE [ARG1] + ; DISABLE SPLIT IF [ARG1] = 0 + ; IGNORE IF SPLIT ALREADY ENABLED OR [ARG1] >= 20 + +ZSPLIT: LDA ZBEGIN+ZMODE + AND #%00100000 ;CHECK IF ENABLED + BEQ ZSPOUT ;NOT, LEAVE + + LDA ARG1+LO ;GET # OF LINES FOR SCREEN + BEQ NORL ;IF 0 THEN RESTORE SCREEN + LDX SPSTAT ;CHECK IF ALREADY ENABLED + BNE ZSPOUT ;IT IS + CMP #20 ;IS SPLIT REALLY = WHOLE SCREEN + BCS ZSPOUT ;YES, IGNORE + + PHA + CLC + ADC #1 ;ONE LINE ADDITIONAL TO SIZE GIVEN + ;TO MAKE UP FOR STATUS LINE + STA WBOTM ;TEMPORARILY FOR TOP SCREEN CLEAR + STA SPSTAT ;NON ZERO = SCREEN IS SPLIT + JSR HOME ;CLEAR FROM TOP TO BOTTOM (OF TOP SCREEN) + LDA #$18 ;RESTORE BOTTOM FOR SCROLL + STA WBOTM + PLA ;GET @ OF LINES AGAIN + CLC + ADC #1 ;ADD 1 + STA WTOP ;MAKE THAT THE TOP OF THE SECOND SCREEN + LDA #1 + STA CH + STA EH + LDA #$16 + STA CV ;RESTORE CURSOR AFTER HOME CALL + JMP PISSER ; TO MAKE CV WORK +ZSPOUT: RTS + +NORL: ;RESTORE SCREEN TO FULL SCREEN MODE + + LDA #1 ;PUT CURSOR AT TOP OF SCREEN + STA WTOP ;RESTORE FULL SCREEN ALIGNMENT + LDA #0 + STA LINCNT + STA SPSTAT ;FLAG NOT SPLIT + RTS + + ; ------ + ; SCREEN + ; ------ + + ; GO TO TOP WINDOW (TOP OF SCREEN) IF [A] = 1 + ; GO TO BOTTOM OF SCREEN IF [A] = 0 + ; IGNORE IF SPLIT NOT ENABLED OR [A] <> 0 OR 1 + + ; FLAG SPLITF WILL BE SET FOR OUTPUT TO DETERMINE + ; IF AND WHICH WINDOW TO DISPLAY TO + ; (0=BOTTOM 1=TOP) + + +ZSCRN: LDA ZBEGIN+ZMODE + AND #%00100000 ;CHECK IF ENABLED + BEQ ZSPOUT ;NOT, LEAVE + + LDA SPSTAT ;CHECK IF SCREEN IS SPLIT + BEQ ZSPOUT ;NO, SO JUST LEAVE + LDA ARG1+LO ;CHECK WHICH WINDOW + BNE SCRN1 ;TOP SCREEN + + STA SPLITF ;SET FLAG TO SPLIT SCREEN (0) + LDA #01 ;PUT CURSOR AT BOTTOM OF SCREEN + STA CH + STA EH + LDA #$16 + STA CV + BNE SCRNP ;JMP TO RTN +SCRN1: CMP #01 + BNE ZSPOUT ;INVALID SCREEN ID + STA SPLITF ;SET FLAG TO UNSCROLLING SCREEN (1) + + LDA #0 + STA CH + STA EH + STA CV ;ALIGN AT TOP OF SCREEN +SCRNP: JMP PISSER ;CALL RTN TO SET CURSOR (+ LEAVE) + + + ; --------- + ; RAZZ USER + ; --------- + +BOOP EQU BELL ;MONITOR BELL + + ; ------------ + ; CLEAR SCREEN + ; ------------ + +CLS EQU HOME ;CLEAR & HOME CURSOR + +PISSER: LDA COL80 ;SEND APPROPRIATE TO SCREEN + BEQ PISS ;IF = 0 THEN 40 COL. + LDA #$0D + BNE PIS ;JMP +PISS LDA #$8D +PIS JMP MCOUT + + END + diff --git a/apple/zip/main.l b/apple/zip/main.l new file mode 100644 index 0000000..73c682b --- /dev/null +++ b/apple/zip/main.l @@ -0,0 +1,221 @@ + PAGE + SBTTL "--- MAIN LOOP ---" + +MLOOP: ; FIRST CHECK IF SCRIPTING WANTED + ; AND IF SO IS PRINTER ON? + + LDA PSTAT ; CHECK IF PRINTER + BNE DLOOP ; ALREADY ON + LDA ZBEGIN+ZSCRIP+1 ; CHECK SCRIPT FLAG + AND #%00000001 + BEQ DLOOP ; SCRIPT NOT ON + + JSR PCHK ; GO INIT PRINTER + +DLOOP: LDA #0 + STA NARGS ; RESET # ARGUMENTS + JSR NEXTPC ; GET NEXT INSTRUCTION INTO [A] + STA OPCODE ; SAVE IT HERE + + 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 #$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 + diff --git a/apple/zip/npaging.h b/apple/zip/npaging.h new file mode 100644 index 0000000..4ab1522 --- /dev/null +++ b/apple/zip/npaging.h @@ -0,0 +1,276 @@ + 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 DKERR ; 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 EARLY2 ; 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 *** + +DKERR: 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 + + ; ------ + ; EARLY2 + ; ------ + + ; 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 + LDY SAVEY + RTS ; [SWAP] HAS INDEX TO EARLIEST BUFFER + + ; ------------------------- + ; 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 + + \ No newline at end of file diff --git a/apple/zip/objects.asm b/apple/zip/objects.asm new file mode 100644 index 0000000..63a9585 --- /dev/null +++ b/apple/zip/objects.asm @@ -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 + diff --git a/apple/zip/ops0.h b/apple/zip/ops0.h new file mode 100644 index 0000000..e81b64d --- /dev/null +++ b/apple/zip/ops0.h @@ -0,0 +1,175 @@ + 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 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 + + IF 0 + + LDA #K+HI ; PATCH THE "GETBYT" ROUTINE + STA PATCH ; TO USE [K+HI]=0 INSTEAD OF [ZPURE] + +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 ; MIDDLE BYTE + CMP I+HI + BNE VSUM + + LDA MPCH ; AND HIGH BIT + CMP K+LO + BNE VSUM + + LDA #ZPURE ; UNPATCH "GETBYT" + STA PATCH + + ENDIF + + + LDA #0 ; START AT BEGINNING + STA DBLOCK+LO + STA DBLOCK+HI + JMP READIN ; READ FIRST BLOCK IN + +VSUM: LDA MPCL ; IF 0, NEED ANOTHER PAGE + BNE VSUM2 +READIN: LDA #HIGH IOBUFF ; FAKE GETDSK OUT SO + STA DBUFF+HI ; IT DOESN'T MOVE BUFFER + JSR GETDSK ; GO READ A PAGE + +VSUM2: LDY MPCL ; GET THIS BYTE + LDA IOBUFF,Y + INC MPCL ; SET FOR NEXT BYTE + BNE VSUM3 + INC MPCM + BNE VSUM3 + INC MPCH + +VSUM3: 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 ; MIDDLE BYTE + CMP I+HI + BNE VSUM + + LDA MPCH ; AND HIGH BIT + CMP K+LO + BNE VSUM + + 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 diff --git a/apple/zip/ops1.asm b/apple/zip/ops1.asm new file mode 100644 index 0000000..7cdd795 --- /dev/null +++ b/apple/zip/ops1.asm @@ -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 + diff --git a/apple/zip/ops2.asm b/apple/zip/ops2.asm new file mode 100644 index 0000000..7d3be0a --- /dev/null +++ b/apple/zip/ops2.asm @@ -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 + diff --git a/apple/zip/opsx.asm b/apple/zip/opsx.asm new file mode 100644 index 0000000..35fccc4 --- /dev/null +++ b/apple/zip/opsx.asm @@ -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 + + \ No newline at end of file diff --git a/apple/zip/paging.asm b/apple/zip/paging.asm new file mode 100644 index 0000000..1599d94 --- /dev/null +++ b/apple/zip/paging.asm @@ -0,0 +1,197 @@ + PAGE + SBTTL "--- PAGING ROUTINES ---" + + ; ------------------------- + ; FETCH NEXT BYTE OF Z-CODE + ; ------------------------- + + ; EXIT: BYTE AT [ZPC] IN [A] & [Y], FLAGS SET + +NEXTPC: LDA ZPCFLG ; HAS PAGE CHANGED? + BEQ NEWZ ; APPARENTLY SO + +NPC: LDY ZPCL + LDA (ZPCPNT),Y ; GRAB A Z-BYTE + + INC ZPCL + BNE NXTX + + LDY #0 + STY ZPCFLG + + INC ZPCM ; POINT [ZPC] TO NEXT PAGE + BNE NXTX + INC ZPCH + +NXTX: TAY ; SET FLAGS + RTS + + ; -------------- + ; SWITCH Z-PAGES + ; -------------- + +NEWZ: LDA ZPCM ; GET LSB OF TARGET INTO [A] + LDY ZPCH ; AND MSB INTO [Y] + BNE NZ0 ; SWAP IF MSB <> 0 + + CMP ZPURE ; IS PAGE IN PRELOAD? + BCS NZ0 ; NO, SWAP IT IN + + ADC ZCODE ; ELSE CALC ABSOLUTE PAGE + BNE NZ1 ; AND GIVE IT TO [ZPCPNT] + +NZ0: LDX #0 + STX MPCFLG ; INVALIDATE [MPC] + JSR PAGE ; LOCATE PAGE [A/Y] IN SWAPPING SPACE + +NZ1: STA ZPCPNT+HI ; AND UPDATE MSB OF POINTER + LDX #$FF + STX ZPCFLG ; VALIDATE [ZPC] + INX ; (= 0) CLEAR LSB + STX ZPCPNT+LO ; OF [ZPCPNT] + BEQ NPC ; GET THE BYTE + + ; ------------------------------- + ; GET NEXT BYTE OF VIRTUAL MEMORY + ; ------------------------------- + + ; EXIT: BYTE AT [MPC] IN [A] & [Y], FLAGS SET + +GETBYT: LDA MPCFLG ; [MPC] VALID? + BEQ NEWM ; NO, SWITCH PAGES + +GTB: LDY MPCL ; GRAB NEXT BYTE + LDA (MPCPNT),Y + + INC MPCL ; END OF THIS PAGE? + BNE NXMX ; NO, CONTINUE + + LDY #0 ; ELSE INVALIDATE + STY MPCFLG ; [MPC] + + INC MPCM ; POINT [MPC] TO + BNE NXMX ; NEXT PAGE + INC MPCH + +NXMX: TAY ; SET FLAGS + RTS + + ; -------------- + ; SWITCH M-PAGES + ; -------------- + +NEWM: LDA MPCM ; GET LSB AND + LDY MPCH ; MSB OF TARGET PAGE + BNE NM0 ; SWAP IF MSB <> 0 + +PATCH EQU $+1 ; PATCH POINT FOR "VERIFY" + + CMP ZPURE ; TARGET IN PRELOAD? + BCS NM0 ; NO, SWAP IT IN + + ADC ZCODE ; ELSE MAKE IT ABSOLUTE + BNE NM1 ; AND GIVE TO [MPCPNT] + +NM0: LDX #0 + STX ZPCFLG ; INVALIDATE [ZPC] + JSR PAGE ; GET PAGE OF TARGET BLOCK IN [A/Y] + +NM1: STA MPCPNT+HI ; SET MSB OF POINTER + LDX #$FF + STX MPCFLG ; [MPC] IS NOW VALID + INX ; CLEAR LSB + STX MPCPNT+LO ; OF [MPCPNT] + BEQ GTB + + ; ------------------------------- + ; LOCATE A PAGE OF VIRTUAL MEMORY + ; ------------------------------- + + ; ENTRY: TARGET PAGE IN [A/Y] (LSB/MSB) + ; EXIT: ABSOLUTE PAGE ADDRESS IN [A] + +PAGE: STA TARGET+LO ; SAVE THE + STY TARGET+HI ; TARGET PAGE FOR REFERENCE + + LDX #0 ; INIT INDEX + STX ZPAGE ; KEEP A RUNNING TALLY + +PG1: CMP PTABL,X ; SEARCH FOR LSB IN [A] + BEQ PG3 ; IF FOUND, CHECK MSB + +PG2: INC ZPAGE ; UPDATE TALLY + INX + CPX PMAX ; OUT OF PAGING SPACE? + BCC PG1 ; NO, KEEP LOOKING + BCS SWAP ; ELSE PAGE MUST BE SWAPPED IN + +PG3: TYA ; GET MSB OF TARGET + CMP PTABH,X ; MATCHED? + BEQ PFOUND ; YES, PAGE IS IN [ZPAGE] + LDA TARGET+LO ; ELSE RESTORE LSB OF TARGET + JMP PG2 ; AND RESUME SEARCH + + ; SWAP IN TARGET PAGE IN [TARGET] + +SWAP: LDX LRU ; SPLICE THE + LDA TARGET+LO ; TARGET PAGE + STA PTABL,X ; INTO THE PAGING TABLES + STA DBLOCK+LO ; AND GIVE IT TO ZDOS + + LDA TARGET+HI ; SAME FOR MSB + STA PTABH,X + STA DBLOCK+HI + + TXA + STA ZPAGE ; SAVE FOR "PFOUND" + CLC + ADC PAGE0 ; MAKE IT ABSOLUTE + STA DBUFF+HI ; GIVE PAGE ADDRESS TO ZDOS + + JSR GETDSK ; GET BLOCK INTO SWAPPING SPACE + BCS DSKERR ; ERROR IF CARRY SET + + INC LRU ; UPDATE PAGE POINTER + LDA LRU + CMP PMAX ; TOP OF PAGING SPACE? + BCC PFOUND ; NO, EXIT + LDA #0 + STA LRU ; ELSE RESET POINTER + +PFOUND: LDA ZPAGE ; GET SWAPPING PAGE INDEX + CLC + ADC PAGE0 ; MAKE IT ABSOLUTE + RTS ; AND RETURN IT IN [A] + + ; *** ERROR #14: DRIVE ACCESS *** + +DSKERR: LDA #14 + JMP ZERROR + + ; ------------------------- + ; 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 + + \ No newline at end of file diff --git a/apple/zip/read.h b/apple/zip/read.h new file mode 100644 index 0000000..1f3dd4b --- /dev/null +++ b/apple/zip/read.h @@ -0,0 +1,311 @@ + 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 RDERR ; (5/14/85 - FORCE # WORDS TO + CMP #60 ; BE BETWEEN 1 AND 59 + BCC RD0 ; LESS, OK +RDERR: LDA #59 + STA (ARG2),Y ; Le) +RD0: INY ; (Y = 1) POINT TO "# WORDS READ" SLOT + CMP (ARG2),Y ; TOO MANY WORDS? + BCC RLEX ; EXIT IF SO (BM 5/2/85) + +; BCS RL1 + + ; *** ERROR #13: PARSER OVERFLOW *** + +; LDA #13 +; JMP ZERROR + +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 + diff --git a/apple/zip/rwts.asm b/apple/zip/rwts.asm new file mode 100644 index 0000000..c15b380 --- /dev/null +++ b/apple/zip/rwts.asm @@ -0,0 +1,922 @@ + PAGE + SBTTL "--- BOOT CODE & RWTS: APPLE II ---" + + ; --------- + ; BOOT CODE + ; --------- + + ; LOADS ALL OF TRACK 0 INTO RAM AT $800 TO $1800, + ; THEN JUMPS THROUGH [COLD] + + ORG ZIP + + DB $01 ; MAGICAL MYSTERY BYTE + + ; BOOT BEGINS HERE + +BOOT: LDA BADDR+HI ; CHECK MSB OF BOOT ADDRESS + CMP #$09 ; 1ST ENTRY INTO BOOT? + BNE BT0 ; NO, CONTINUE + + ; CALC ADDRESS OF ROM SECTOR READ ROUTINE + + LDA BSLOT ; GET SLOT ID * 16 + STA DCBSLT ; MAKE IT THE DEFAULT TARGET + STA DCBPSL ; AND THE "OLD" SLOT + LSR A ; DIVIDE BY 16 + LSR A + LSR A + LSR A + ORA #%11000000 ; MAKE IT $C0nn + STA I+HI ; USE AS MSB OF ADDRESS + LDA #$5C ; LSB IS ALWAYS $5C + STA I+LO + + LDA #1 + STA DCBSEC + +BT0: LDX DCBSEC + INC DCBSEC + CPX #$10 + BCS BT1 + LDA ILEAVE,X + STA BSECT + LDX BSLOT + JMP (I) + +BT1: JSR INIT + JMP COLD ; LOAD REMAINDER OF ZIP + + ; --------------------- + ; SECTOR INTERLEAVE MAP + ; --------------------- + + ; USED BY "BOOT" AND "RWTS" + ; MUST BE IN 1ST PAGE! + +ILEAVE: DB $00,$04,$08,$0C,$01,$05,$09,$0D + DB $02,$06,$0A,$0E,$03,$07,$0B,$0F + + ; INFOCOM'S VERSION OF APPLE RWTS (READ/WRITE TRACK/SECTOR) + + ; HACKED BY ANDREW KALUZNIACKI + ; FROM THE DOS RWTS ON APPLE DOS 3.3 + + ; ------------ + ; SPACE FILLER + ; ------------ + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00 + + ; ------------------------------- + ; MAIN ENTRY INTO INFO-DOS (IDOS) + ; ------------------------------- + + ; [DCBSEC] SECTOR (0-15), SET BY CALLER + ; [DCBTRK] TRACK (0-34), SET BY CALLER + ; [DCBDRV] DRIVE (1 OR 2), SET BY CALLER [BOOT DEFAULT] + ; [DCBSLT] SLOT*16, SET BY CALLER [BOOT DEFAULT] + ; [DCBPSL] SLOT*16 OF LAST USED SLOT, SET BY BOOT + ; [DCBPDR] LAST DRIVE USED (1 OR 2), SET BY BOOT + ; [DCBCMD] STORAGE FOR COMMAND SENT IN AT CALL TO IDOS + ; [DCBERR] IDOS ERROR CODE + ; [DCBBFL] DISK BUFFER ADDRESS (LSB) [BOOT = IOBUFF] + ; [DCBBFH] DISK BUFFER ADDRESS (MSB) [BOOT = IOBUFF] + + ; =1 WRITES DISK BUFFER + ; =0 READS DISK BUFFER + + ; [IOBUFF] = 256-BYTE BUFFER FOR DISK I/O + ; (OPTIONAL IF [DCBBFL/DCBBFH] ARE SET) + + ; [BUFFA] ONE PAGE BUFFER + ; [BUFFB] $56 BYTE BUFFER + + ; CARRY CLEAR ON RETURN IF NO ERROR + ; IF CARRY SET, ERROR CODE IS IN [DERR]: + + ; $10 = WRITE PROTECTED + ; $40 = DRIVE ERROR + ; $80 = READ ERROR + + ; *** WARNING *** + + ; IDOS MUST START ON A PAGE BOUNDARY. + ; CHANGE ANY CODE BETWEEN [IDOS] AND [INIT] AT YOUR OWN RISK. + ; YOU HAVE BEEN WARNED. + +IDOS: NOP + NOP + NOP ; DON'T ASK, AND DON'T CHANGE + PHP ; SAVE STATUS OF [I] + SEI ; DISABLE INTERUPTS + JSR DOS ; DO IT (GO TO MAIN ROUTINE) + BCS DOSERR ; ERROR OCCURED IF C=1 + PLP ; RESTORE [I] + CLC ; SET "NO ERROR" + RTS ; RETURN FROM CALL +DOSERR: PLP ; RESTORE [I] + SEC ; INDICATE ERROR + RTS ; EXIT + + ; PRE-NIBBLIZE [IOBUFF] BEFORE WRITING + +PRENIB: LDX #0 + LDY #2 +PREN0: DEY + LDA (DCBBFL),Y + LSR A + ROL BUFFB,X + LSR A + ROL BUFFB,X + STA BUFFA,Y + INX + CPX #$56 + BCC PREN0 + + LDX #0 + TYA + BNE PREN0 + + LDX #$55 ; CLEAR BITS 7 AND 6 +PREN1: LDA BUFFB,X ; OF TOP NIBBLE BUFFER + AND #%00111111 + STA BUFFB,X + DEX + BPL PREN1 + RTS + + ; ------------ + ; WRITE SECTOR + ; ------------ + + ; WRITES PRENIBBLIZED DATA AT [BUFFA/BUFFB] TO DISK + + ; ENTRY: SLOT*16 IN [X] + ; EXIT: CARRY SET IF ERROR + +WRTDTA: STX DTMP4 ; SAVE SLOT ID HERE + STX SLTMP2 + + SEC ; SET CARRY FOR POSSIBLE ERROR + LDA Q6H,X ; CHECK FOR WRITE-PROTECT + LDA Q7L,X + BMI WRT5 ; EXIT W/CARRY SET IF PROTECTED + + LDA BUFFB ; SAVE 1ST BYTE OF 2NDARY BUFFER + STA DTMP3 ; FOR LATER + + LDA #$FF ; ESTABLISH AUTOSYNC BYTE + + STA Q7H,X ; SET DRIVE TO WRITE MODE + ORA Q6L,X ; WAIT FOR HARDWARE TO SETTLE + PHA + PLA + NOP + + LDY #4 ; WRITE 5 AUTOSYNC BYTES +WRT1: PHA + PLA + JSR WRBYT2 ; USING 40 uS DELAY + DEY + BNE WRT1 + + LDA #$D5 ; WRITE DATA FIELD PROLOGUE: + JSR WRBYT1 ; $D5-$AA-$AD + LDA #$AA + JSR WRBYT1 + LDA #$AD + JSR WRBYT1 + + TYA ; A BRIEF DELAY + + LDY #$56 ; INIT LOOP INDEX + BNE WRT3 ; BRANCH ALWAYS + + ; WRITE [BUFFB] TO DISK + +WRT2: LDA BUFFB,Y ; GET A BYTE FROM [BUFFB] + +WRT3: EOR BUFFB-1,Y + TAX ; USE IT AS AN INDEX + LDA WRTTBL,X ; INTO THE TRANSLATE TABLE + LDX DTMP4 ; RESTORE SLOT ID + STA Q6H,X ; AND WRITE THE TRANSLATED BYTE + LDA Q6L,X + DEY ; LOOP TILL + BNE WRT2 ; EMPTY + + ; WRITE [BUFFA] TO DISK + + LDA DTMP3 ; RESTORE "LOST" [BUFFB] BYTE + NOP ; WAIT JUST A MOMENT ... + +WRT4: EOR BUFFA,Y ; GET A BYTE FROM [BUFFA] + TAX ; USE IT AS AN INDEX + LDA WRTTBL,X ; INTO THE TRANSLATE TABLE + LDX SLTMP2 ; RESTORE SLOT ID + STA Q6H,X ; AND WRITE THE TRANSLATED BYTE + LDA Q6L,X + LDA BUFFA,Y ; GET NEXT BYTE FROM BUFFER + INY ; AND LOOP TILL + BNE WRT4 ; ALL OF [BUFFA] IS WRITTEN + + TAX + LDA WRTTBL,X + LDX DTMP4 ; RESTORE SLOT ID + JSR WRBYT3 ; AND WRITE THE LAST [BUFFA] BYTE + + LDA #$DE ; WRITE DATA FIELD EPILOGUE: + JSR WRBYT1 ; $DE-$AA-$EB + LDA #$AA + JSR WRBYT1 + LDA #$EB + JSR WRBYT1 + + LDA #$FF ; WRITE GAP 3 + JSR WRBYT1 + + LDA Q7L,X ; SET DRIVE TO READ MODE + +WRT5: LDA Q6L,X + RTS + + ; ---------------------------- + ; WRITE A BYTE (TIME-CRITICAL) + ; ---------------------------- + + ; ENTRY: BYTE TO WRITE IN [A] + ; SLOT*16 IN [X] + +WRBYT1: CLC ; PROLOGUE, EPILOGUE AND GAP 3 TIMING +WRBYT2: PHA ; ENTRY FOR GAP 2 TIMING + PLA +WRBYT3: STA Q6H,X + ORA Q6L,X + RTS + + ; CONVERT RAW DATA TO BINARY IN [IOBUFF] + +POSTNB: LDY #0 +PST0: LDX #$56 +PST1: DEX + BMI PST0 + LDA BUFFA,Y + LSR BUFFB,X + ROL A + LSR BUFFB,X + ROL A + STA (DCBBFL),Y + INY + CPY DTMP3 + BNE PST1 + RTS + + ; ----------- + ; READ SECTOR + ; ----------- + + ; READ RAW SECTOR DATA TO [BUFFA/BUFFB] + + ; ENTRY: SLOT*16 IN [X] + ; EXIT: CARRY SET IF ERROR, ELSE 342 RAW BYTES IN [BUFFA/BUFFB] + +RDSECT: LDY #$20 +RDS1: DEY ; RETURN AN ERROR IF + BEQ RDBAD ; NO $D5 FOUND AFTER 32 TRIES + + ; FETCH & VALIDATE PROLOGUE ($D5-$AA-$AD) + +RDS2: LDA Q6L,X ; GET A BYTE + BPL RDS2 + +RDS3: EOR #$D5 ; WAS IT $D5? + BNE RDS1 ; NO, KEEP LOOKING + + NOP ; ELSE WAIT A MOMENT ... + +RDS4: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDS4 + CMP #$AA ; WAS IT $AA? + BNE RDS3 ; CHECK FOR $D5 AGAIN IF NOT + + LDY #$56 ; ELSE INIT DATA-READ INDEX + +RDS5: LDA Q6L,X ; GET A BYTE + BPL RDS5 + CMP #$AD ; WAS IT $AD? + BNE RDS3 ; CHECK FOR $D5 IF NOT + + ; READ RAW DATA INTO [BUFFB] + + LDA #0 ; CLEAR [A], DELAY ... + +RDS6: DEY + STY DTMP3 ; SAVE INDEX HERE + +RDS7: LDY Q6L,X ; GET A DATA BYTE + BPL RDS7 + EOR RDTBL-$96,Y ; TRANSLATE IT + LDY DTMP3 ; RESTORE INDEX + STA BUFFB,Y ; STORE BYTE IN [BUFFB] + BNE RDS6 ; CONTINUE TILL [BUFFB] FULL + + ; READ RAW DATA INTO [BUFFA] + +RDS8: STY DTMP3 ; RE-INIT INDEX TO ZERO + +RDS9: LDY Q6L,X ; GET A DATA BYTE + BPL RDS9 + EOR RDTBL-$96,Y ; TRANSLATE IT + LDY DTMP3 ; RESTORE INDEX + STA BUFFA,Y ; SAVE BYTE IN [BUFFA] + INY + BNE RDS8 ; LOOP TILL [BUFFA] IS FULL + + ; FETCH & VALIDATE CHECKSUM + +RDS10: LDY Q6L,X ; GET THE NEXT BYTE + BPL RDS10 + CMP RDTBL-$96,Y ; TRANSLATE IT + BNE RDBAD ; ERROR IF CHECKSUM BAD + + ; FETCH & VALIDATE EPILOGUE ($DE-$AA-$EB) + +RDS11: LDA Q6L,X ; GET A BYTE + BPL RDS11 + CMP #$DE ; IS IT $DE? + BNE RDBAD ; ERROR IF NOT + + NOP ; WAIT ... + +RDS12: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDS12 + CMP #$AA ; IS IT $AA? + BEQ RDOK ; DATA OKAY IF SO + +RDBAD: SEC ; ELSE SET CARRY FOR ERROR + RTS ; AND SCRAM + + ; --------------------- + ; READ AN ADDRESS FIELD + ; --------------------- + + ; ENTRY: SLOT*16 IN [X] + ; EXIT: CARRY SET IF ERROR + +RDADDR: LDY #$FC ; INIT TIMEOUT COUNTER + STY DTMP3 + +RDA1: INY + BNE RDA2 + INC DTMP3 ; ERROR IF + BEQ RDBAD ; CAN'T FIND ADDRESS HEADER + + ; FETCH THE ADDRESS FIELD PROLOGUE ($D5-$AA-$96) + +RDA2: LDA Q6L,X ; GRAB A BYTE + BPL RDA2 + +RDA3: CMP #$D5 ; WAS IT $D5? + BNE RDA1 ; NO, KEEP SEARCHING + + NOP ; ELSE WAIT A FEW MICROSECONDS ... + +RDA4: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDA4 + CMP #$AA ; WAS IT $AA? + BNE RDA3 ; NO, CHECK IF $D5 + + LDY #3 ; ELSE INIT DATA-FETCH INDEX + +RDA5: LDA Q6L,X ; GET A BYTE + BPL RDA5 + CMP #$96 ; WAS IT $96? + BNE RDA3 ; NO, CHECK FOR $D5 + + ; FETCH THE 4 BYTES OF ADDRESS DATA + + LDA #0 ; INIT CHECKSUM BYTE + +RDA6: STA DTMP4 ; UPDATE CHECKSUM + +RDA7: LDA Q6L,X ; GET A BYTE + BPL RDA7 + ROL A ; SHIFT IT + STA DTMP3 ; AND SAVE 1ST PART HERE + +RDA8: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDA8 + AND DTMP3 ; SUPER 1ST PART OF BYTE + STA HDRCHK,Y ; STORE IN RESULT TABLE + EOR DTMP4 ; COMPUTE CHECKSUM + DEY ; GOT 4 BYTES YET? + BPL RDA6 ; NO, LOOP BACK + + TAY ; LOOK AT CHECKSUM BYTE + BNE RDBAD ; ERROR IF NON-ZERO + + ; FETCH & VALIDATE EPILOGUE ($DE-$AA, IGNORE $EB) + +RDA9: LDA Q6L,X ; GET A BYTE + BPL RDA9 + CMP #$DE ; WAS IT $DE? + BNE RDBAD ; ERROR IF NOT + + NOP ; ELSE WAIT A MOMENT ... + +RDA10: LDA Q6L,X ; GET ONE MORE BYTE + BPL RDA10 + CMP #$AA ; WAS IT $AA + BNE RDBAD ; ERROR IF NOT + +RDOK: CLC ; ELSE CLEAR CARRY FOR SUCCESS + RTS ; AND RETURN + + ; --------------------- + ; MOVE ARM TO TRACK [A] + ; --------------------- + + ; ENTRY: SLOT*16 IN [X] + ; TARGET TRACK IN [A] + ; CURRENT TRACK IN [CTRACK] + +SEEK: STX SLTMP3 ; SAVE SLOT ID + STA TTRK ; AND TARGET TRACK + CMP CTRACK ; TARGET SAME AS CURRENT? + BEQ SEEKEX ; EXIT NOW IF SO + + LDA #0 ; INIT + STA DTMP3 ; INDEX + +SK1: LDA CTRACK ; GET CURRENT TRACK + STA DTMP4 ; SAVE IT HERE + SEC + SBC TTRK ; GET TRACK DIFFERENCE + BEQ SK6 + BCS SK2 + EOR #%11111111 + INC CTRACK + BCC SK3 + +SK2: ADC #$FE + DEC CTRACK + +SK3: CMP DTMP3 + BCC SK4 + LDA DTMP3 + +SK4: CMP #$0C + BCS SK5 + TAY + +SK5: SEC + JSR SEEK0 + LDA DELTB1,Y + JSR ARMDEL + LDA DTMP4 + CLC + JSR SEEK1 + LDA DELTB2,Y + JSR ARMDEL + INC DTMP3 + BNE SK1 + +SK6: JSR ARMDEL + CLC + +SEEK0: LDA CTRACK + +SEEK1: AND #%00000011 + ROL A + ORA SLTMP3 + TAX + LDA PH0OFF,X ; MOVE THE ARM + LDX SLTMP3 + +SEEKEX: RTS + + ; ------------------ + ; ARM MOVEMENT DELAY + ; ------------------ + + ; NOTE: THIS ROUTINE MUST BEGIN ON A PAGE BOUNDARY! + + ; ENTRY: 100uS DELAY INTERVAL IN [A] + ; MOTOR TIME COUNT IN [MTIME] + +ARMDEL: LDX #$11 +ARM1: DEX + BNE ARM1 + INC DCNT + BNE ARM2 + INC DTMP2 +ARM2: SEC + SBC #1 + BNE ARMDEL + RTS + + ; ------------------------- + ; ARM MOVEMENT DELAY TABLES + ; ------------------------- + +DELTB1: DB $01,$30,$28,$24,$20,$1E,$1D,$1C + DB $1C,$1C,$1C,$1C + +DELTB2: DB $70,$2C,$26,$22,$1F,$1E,$1D,$1C + DB $1C,$1C,$1C,$1C + + ; --------------------- + ; WRITE TRANSLATE TABLE + ; --------------------- + +WRTTBL: DB $96,$97,$9A,$9B,$9D,$9E,$9F,$A6 + DB $A7,$AB,$AC,$AD,$AE,$AF,$B2,$B3 + DB $B4,$B5,$B6,$B7,$B9,$BA,$BB,$BC + DB $BD,$BE,$BF,$CB,$CD,$CE,$CF,$D3 + DB $D6,$D7,$D9,$DA,$DB,$DC,$DD,$DE + DB $DF,$E5,$E6,$E7,$E9,$EA,$EB,$EC + DB $ED,$EE,$EF,$F2,$F3,$F4,$F5,$F6 + DB $F7,$F9,$FA,$FB,$FC,$FD,$FE,$FF + + ; -------------------- + ; READ TRANSLATE TABLE + ; -------------------- + +RDTBL: DB $00,$01,$98,$99,$02,$03,$9C,$04 + DB $05,$06,$A0,$A1,$A2,$A3,$A4,$A5 + DB $07,$08,$A8,$A9,$AA,$09,$0A,$0B + DB $0C,$0D,$B0,$B1,$0E,$0F,$10,$11 + DB $12,$13,$B8,$14,$15,$16,$17,$18 + DB $19,$1A,$C0,$C1,$C2,$C3,$C4,$C5 + DB $C6,$C7,$C8,$C9,$CA,$1B,$CC,$1C + DB $1D,$1E,$D0,$D1,$D2,$1F,$D4,$D5 + DB $20,$21,$D8,$22,$23,$24,$25,$26 + DB $27,$28,$E0,$E1,$E2,$E3,$E4,$29 + DB $2A,$2B,$E8,$2C,$2D,$2E,$2F,$30 + DB $31,$32,$F0,$F1,$33,$34,$35,$36 + DB $37,$38,$F8,$39,$3A,$3B,$3C,$3D + DB $3E,$3F + + ; --------------- + ; MAIN RWTS ENTRY + ; --------------- + + ; ENTRY: [A]=0 FOR READ, [A]=1 FOR WRITE + ; [SLOT] = TARGET SLOT + ; [DRIVE] = TARGET DRIVE + ; [TRACK] = TARGET TRACK + ; [SECTOR] = TARGET SECTOR + ; EXIT: CARRY CLEAR IF OKAY + + ; COMMENTS - LINDE + + ; ACTUAL VARIABLES ARE: + ; [DCBSLT] = SLOT + ; [DCBTRK] = TRACK + ; [DCBSEC] = SECTOR + ; [[DCBDRV] = DRIVE + + ; FOR TRK, SEC, DRV 1 = 1 (DRIVE 1, SET DCBDRV TO 1) + ; FOR SLT - MULTIPLY SLOT BY 16 (SLOT 6, SET DCBSLT TO $60) + +DOS: STA DCBCMD ; SAVE COMMAND + LDA #2 ; ALLOW 2 + STA NRECAL ; RECALS + ASL A ; AND 4 + STA NSEEK ; SEEKS + + LDX DCBSLT ; GET REQUESTED SLOT ID + CPX DCBPSL ; SAME AS LAST SLOT? + BEQ SAMESL ; YES, CONTINUE + LDX DCBPSL + + ; WAIT FOR OLD DRIVE TO TURN OFF, UPDATE SLOT ID + + LDA Q7L,X ; SET OLD SLOT TO READ MODE +RW1: LDY #8 ; INIT COUNTER + LDA Q6L,X +RW2: CMP Q6L,X + BNE RW1 + DEY + BNE RW2 + + LDX DCBSLT ; GET NEW SLOT ID INTO [X] + STX DCBPSL ; MAKE IT THE "OLD" SLOT + + ; CURRENT SLOT ID IN [X] + +SAMESL: LDA Q7L,X ; GET DRIVE INTO READ MODE + LDA Q6L,X ; READ WITH DELAYS + LDY #8 ; TO SEE IF DRIVE IS SPINNING +RW4: LDA Q6L,X + PHA + PLA + PHA + PLA + STX SLTMP1 ; SAVE SLOT HERE + CMP Q6L,X + BNE RW5 + DEY + BNE RW4 + +RW5: PHP ; SAVE TEST RESULT ON STACK + LDA DRVON,X ; TURN ON MOTOR + + LDA #$D8 ; REFRESH + STA DTMP2 ; MOTOR TIME CONSTANT + + ; CHECK DRIVE ID + + LDA DCBDRV + CMP DCBPDR ; HAS DRIVE CHANGED? + BEQ RW7 ; NO, CONTINUE + + STA DCBPDR ; ELSE MAKE NEW DRIVE "OLD" + PLP ; SET ZERO FLAG + LDY #0 ; OF TEST RESULT + PHP ; AND PUSH IT BACK ON STACK + +RW7: ROR A ; CHECK DRIVE ID + BCC RW8 ; CARRY WILL BE CLEAR IF DRIVE = 2 + LDA DRV0EN,X ; ELSE SELECT DRIVE #1 + BCS RW9 ; BRANCH ALWAYS + +RW8: LDA DRV1EN,X ; SELECT DRIVE #2 + +RW9: ROR DRVFLG ; HIGH BIT = 1 FOR DRIVE 1, 0 FOR 2 + + PLP ; CHECK TEST RESULTS + PHP + BNE RW11 ; BRANCH IF DRIVE WAS ON + + LDY #7 ; WAIT FOR CAP DISCHARGE +RW10: JSR ARMDEL + DEY + BNE RW10 + + LDX SLTMP1 ; RESTORE SLOT ID + + ; SEEK THE TARGET TRACK + +RW11: LDA DCBTRK ; GET TARGET TRACK + JSR MYSEEK + + PLP ; WAS DRIVE ON? + BNE RW14 ; YES, CONTINUE + + ; WAIT FOR DRIVE TO COME UP TO SPEED + + LDY DTMP2 + BPL RW14 + +RW12: LDY #$12 ; WAIT FOR DRIVE TO +RW13: DEY ; COME UP TO SPEED + BNE RW13 + INC DCNT + BNE RW12 + INC DTMP2 + BNE RW12 + + ; DECODE DISK COMMAND + +RW14: LDA DCBCMD ; GET COMMAND + ROR A ; CARRY = 0 IF "READ" + PHP ; SAVE READ/WRITE STATUS + ; AND MAINTAIN STACK + BCC GETADR ; BRANCH IF "READ" + JSR PRENIB + + ; FETCH AN ADDRESS FIELD + +GETADR: LDA #48 + STA DTMP1 ; INIT RETRY COUNT + +GTA0: LDX SLTMP1 ; RESTORE SLOT ID + JSR RDADDR ; GET AN ADDRESS FIELD + BCC RRIGHT ; CONTINUE IF SUCCESSFUL + +GTA1: DEC DTMP1 ; ELSE UPDATE RETRY COUNT + BPL GTA0 ; AND TRY AGAIN + + ; RECALIBRATE THE ARM + +GTA2: LDA CTRACK ; SAVE THE + PHA ; CURRENT TRACK ID + + LDA #$60 + JSR SETTRK + DEC NRECAL ; UPDATE RECAL COUNT + BEQ DRVERR ; ERROR IF EMPTY + LDA #4 ; RESET + STA NSEEK ; SEEK COUNT + LDA #0 ; CALIBRATE THE ARM + JSR MYSEEK ; TO TRACK #0 + PLA ; RESTORE CURRENT TRACK + +GTA3: JSR MYSEEK ; GO TO IT + JMP GETADR ; AND TRY AGAIN + + ; ADDRESS FIELD FOUND + +RRIGHT: LDY HDRTRK + CPY CTRACK ; ON THE RIGHT TRACK? + BEQ RTTRAK ; YES, CONTINUE + + LDA CTRACK + PHA + TYA + JSR SETTRK + PLA + DEC NSEEK + BNE GTA3 + BEQ GTA2 ; ELSE RECALIBRATE + + ; HANDLE A DRIVE ERROR + +DRVERR: PLA ; CLEAN UP STACK + LDA #$40 ; $40 = DRIVE ERROR +EREXT: PLP ; CLEAN UP STATUS REGISTER + JMP DERROR + + ; CHECK FOR PROPER SECTOR (VOLUME CHECK OMITTED) + +RTTRAK: LDY DCBSEC + LDA ILEAVE,Y ; GET INTERLEAVE BYTE + CMP HDRSEC ; MATCHED FOUND SECTOR? + BNE GTA1 ; NO, TRY AGAIN + + ; SECTOR FOUND! + + PLP ; WILL THIS BE READ OR WRITE? + BCS DWRITE ; DO "WRITE" IF CARRY SET + + ; READ A SECTOR + + JSR RDSECT ; DO THE READ + + BCC GTA3A ; OK + CLC ; RESET FOR NEXT TIME THRU + PHP ; AND PUSH FOR NEXT TIME THRU + BCC GTA1 ; JMP, ERROR OCCURRED + +; CHANGED TO ABOVE 4 LINES 6/11/85, CARRY MUST BE CLEARED SO READS +; PHP ; SAVE STATUS +; BCS GTA1 ; ERROR IF CARRY WAS SET +; PLP ; ELSE DUMP STATUS + +GTA3A: LDX #$00 + STX DTMP3 + JSR POSTNB + + LDX SLTMP1 ; RESTORE SLOT ID + +DONE: LDA #0 ; 0 = NO ERRORS + CLC ; CARRY CLEAR FOR SUCCESS + BCC EXIT + + ; ERROR EXIT + +DERROR: SEC ; CARRY SET FOR ERROR + + ; GENERAL EXIT + +EXIT: STA DCBERR ; SAVE ERROR CODE HERE + LDA DRVOFF,X ; STOP THE DRIVE + + RTS ; BYE! + + ; WRITE A SECTOR + +DWRITE: JSR WRTDTA + BCC DONE ; ALL'S WELL IF CARRY CLEAR + LDA #$10 ; ELSE GET ERROR CODE INTO [A] + BNE DERROR ; AND DO AN ERROR EXIT + + ; --------------------- + ; SET UP FOR TRACK SEEK + ; --------------------- + +MYSEEK: ASL A ; TRACK*2 (PHASE OF DISK CARE) + JSR DOSEEK + LSR CTRACK ; CURRENT TRACK/2 + RTS + + ; -------------- + ; EXECUTE A SEEK + ; -------------- + + ; PAGE BOUNDARY SHOULD BEGIN HERE! + +DOSEEK: STA TTRK + JSR XTOY + LDA DR1TBL,Y + BIT DRVFLG + BMI DSE1 + LDA DR2TBL,Y +DSE1: STA CTRACK + LDA TTRK + BIT DRVFLG + BMI DSE2 + STA DR2TBL,Y + BPL DSE3 +DSE2: STA DR1TBL,Y +DSE3: JMP SEEK + + ; -------------------- + ; GET SLOT ID INTO [Y] + ; -------------------- + +XTOY: TXA + LSR A + LSR A + LSR A + LSR A + TAY + RTS + + ; ------------ + ; SET TRACK ID + ; ------------ + +SETTRK: PHA + LDA DCBDRV + ROR A + ROR DRVFLG + JSR XTOY + PLA + ASL A + BIT DRVFLG + BMI STT1 + STA DR2TBL,Y + BPL STT2 +STT1: STA DR1TBL,Y +STT2: RTS + + ; ----------- + ; IDOS TABLES + ; ----------- + +DR1TBL: DB $00,$00,$00,$00 ; (8 BYTES) + DB $00,$00,$00,$00 + +CTRACK EQU DR1TBL ; CURRENT TRACK + +DR2TBL: DB $00,$00,$00,$00 ; (8 BYTES) + DB $00,$00,$00,$00 + +NSEEK: DB $00 ; SEEK COUNT +DTMP1: DB $00 ; RETRY COUNT +SLTMP1: DB $00 ; SLOT ID +SLTMP2: DB $00 +NRECAL: DB $00 ; RECALIBRATE COUNT + + ; ---------------------- + ; MACHINE INITIALIZATION + ; ---------------------- + +INIT: LDA TXTSET ; SET TEXT MODE + LDA MIXCLR ; SET NO MIX + LDA LOWSCR ; SET PAGE 1 + + LDA #HIGH IOBUFF ; POINT [DCBBFL/H] TO [IOBUFF] + STA DCBBFH + LDA #LOW IOBUFF + STA DCBBFL + + LDA #1 + STA DCBDRV ; SET DRIVE = 1 + STA DCBPDR + + RTS + + END + diff --git a/apple/zip/rwts.k b/apple/zip/rwts.k new file mode 100644 index 0000000..45ef09b --- /dev/null +++ b/apple/zip/rwts.k @@ -0,0 +1,922 @@ + PAGE + SBTTL "--- BOOT CODE & RWTS: APPLE II ---" + + ; --------- + ; BOOT CODE + ; --------- + + ; LOADS ALL OF TRACK 0 INTO RAM AT $800 TO $1800, + ; THEN JUMPS THROUGH [COLD] + + ORG ZIP + + DB $01 ; MAGICAL MYSTERY BYTE + + ; BOOT BEGINS HERE + +BOOT: LDA BADDR+HI ; CHECK MSB OF BOOT ADDRESS + CMP #$09 ; 1ST ENTRY INTO BOOT? + BNE BT0 ; NO, CONTINUE + + ; CALC ADDRESS OF ROM SECTOR READ ROUTINE + + LDA BSLOT ; GET SLOT ID * 16 + STA DCBSLT ; MAKE IT THE DEFAULT TARGET + STA DCBPSL ; AND THE "OLD" SLOT + LSR A ; DIVIDE BY 16 + LSR A + LSR A + LSR A + ORA #%11000000 ; MAKE IT $C0nn + STA I+HI ; USE AS MSB OF ADDRESS + LDA #$5C ; LSB IS ALWAYS $5C + STA I+LO + + LDA #1 + STA DCBSEC + +BT0: LDX DCBSEC + INC DCBSEC + CPX #$10 + BCS BT1 + LDA ILEAVE,X + STA BSECT + LDX BSLOT + JMP (I) + +BT1: JSR INIT + JMP COLD ; LOAD REMAINDER OF ZIP + + ; --------------------- + ; SECTOR INTERLEAVE MAP + ; --------------------- + + ; USED BY "BOOT" AND "RWTS" + ; MUST BE IN 1ST PAGE! + +ILEAVE: DB $00,$04,$08,$0C,$01,$05,$09,$0D + DB $02,$06,$0A,$0E,$03,$07,$0B,$0F + + ; INFOCOM'S VERSION OF APPLE RWTS (READ/WRITE TRACK/SECTOR) + + ; HACKED BY ANDREW KALUZNIACKI + ; FROM THE DOS RWTS ON APPLE DOS 3.3 + + ; ------------ + ; SPACE FILLER + ; ------------ + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00 + + ; ------------------------------- + ; MAIN ENTRY INTO INFO-DOS (IDOS) + ; ------------------------------- + + ; [DCBSEC] SECTOR (0-15), SET BY CALLER + ; [DCBTRK] TRACK (0-34), SET BY CALLER + ; [DCBDRV] DRIVE (1 OR 2), SET BY CALLER [BOOT DEFAULT] + ; [DCBSLT] SLOT*16, SET BY CALLER [BOOT DEFAULT] + ; [DCBPSL] SLOT*16 OF LAST USED SLOT, SET BY BOOT + ; [DCBPDR] LAST DRIVE USED (1 OR 2), SET BY BOOT + ; [DCBCMD] STORAGE FOR COMMAND SENT IN AT CALL TO IDOS + ; [DCBERR] IDOS ERROR CODE + ; [DCBBFL] DISK BUFFER ADDRESS (LSB) [BOOT = IOBUFF] + ; [DCBBFH] DISK BUFFER ADDRESS (MSB) [BOOT = IOBUFF] + + ; =1 WRITES DISK BUFFER + ; =0 READS DISK BUFFER + + ; [IOBUFF] = 256-BYTE BUFFER FOR DISK I/O + ; (OPTIONAL IF [DCBBFL/DCBBFH] ARE SET) + + ; [BUFFA] ONE PAGE BUFFER + ; [BUFFB] $56 BYTE BUFFER + + ; CARRY CLEAR ON RETURN IF NO ERROR + ; IF CARRY SET, ERROR CODE IS IN [DERR]: + + ; $10 = WRITE PROTECTED + ; $40 = DRIVE ERROR + ; $80 = READ ERROR + + ; *** WARNING *** + + ; IDOS MUST START ON A PAGE BOUNDARY. + ; CHANGE ANY CODE BETWEEN [IDOS] AND [INIT] AT YOUR OWN RISK. + ; YOU HAVE BEEN WARNED. + +IDOS: NOP + NOP + NOP ; DON'T ASK, AND DON'T CHANGE + PHP ; SAVE STATUS OF [I] + SEI ; DISABLE INTERUPTS + JSR DOS ; DO IT (GO TO MAIN ROUTINE) + BCS DOSERR ; ERROR OCCURED IF C=1 + PLP ; RESTORE [I] + CLC ; SET "NO ERROR" + RTS ; RETURN FROM CALL +DOSERR: PLP ; RESTORE [I] + SEC ; INDICATE ERROR + RTS ; EXIT + + ; PRE-NIBBLIZE [IOBUFF] BEFORE WRITING + +PRENIB: LDX #0 + LDY #2 +PREN0: DEY + LDA (DCBBFL),Y + LSR A + ROL BUFFB,X + LSR A + ROL BUFFB,X + STA BUFFA,Y + INX + CPX #$56 + BCC PREN0 + + LDX #0 + TYA + BNE PREN0 + + LDX #$55 ; CLEAR BITS 7 AND 6 +PREN1: LDA BUFFB,X ; OF TOP NIBBLE BUFFER + AND #%00111111 + STA BUFFB,X + DEX + BPL PREN1 + RTS + + ; ------------ + ; WRITE SECTOR + ; ------------ + + ; WRITES PRENIBBLIZED DATA AT [BUFFA/BUFFB] TO DISK + + ; ENTRY: SLOT*16 IN [X] + ; EXIT: CARRY SET IF ERROR + +WRTDTA: STX DTMP4 ; SAVE SLOT ID HERE + STX SLTMP2 + + SEC ; SET CARRY FOR POSSIBLE ERROR + LDA Q6H,X ; CHECK FOR WRITE-PROTECT + LDA Q7L,X + BMI WRT5 ; EXIT W/CARRY SET IF PROTECTED + + LDA BUFFB ; SAVE 1ST BYTE OF 2NDARY BUFFER + STA DTMP3 ; FOR LATER + + LDA #$FF ; ESTABLISH AUTOSYNC BYTE + + STA Q7H,X ; SET DRIVE TO WRITE MODE + ORA Q6L,X ; WAIT FOR HARDWARE TO SETTLE + PHA + PLA + NOP + + LDY #4 ; WRITE 5 AUTOSYNC BYTES +WRT1: PHA + PLA + JSR WRBYT2 ; USING 40 uS DELAY + DEY + BNE WRT1 + + LDA #$D5 ; WRITE DATA FIELD PROLOGUE: + JSR WRBYT1 ; $D5-$AA-$AD + LDA #$AA + JSR WRBYT1 + LDA #$AD + JSR WRBYT1 + + TYA ; A BRIEF DELAY + + LDY #$56 ; INIT LOOP INDEX + BNE WRT3 ; BRANCH ALWAYS + + ; WRITE [BUFFB] TO DISK + +WRT2: LDA BUFFB,Y ; GET A BYTE FROM [BUFFB] + +WRT3: EOR BUFFB-1,Y + TAX ; USE IT AS AN INDEX + LDA WRTTBL,X ; INTO THE TRANSLATE TABLE + LDX DTMP4 ; RESTORE SLOT ID + STA Q6H,X ; AND WRITE THE TRANSLATED BYTE + LDA Q6L,X + DEY ; LOOP TILL + BNE WRT2 ; EMPTY + + ; WRITE [BUFFA] TO DISK + + LDA DTMP3 ; RESTORE "LOST" [BUFFB] BYTE + NOP ; WAIT JUST A MOMENT ... + +WRT4: EOR BUFFA,Y ; GET A BYTE FROM [BUFFA] + TAX ; USE IT AS AN INDEX + LDA WRTTBL,X ; INTO THE TRANSLATE TABLE + LDX SLTMP2 ; RESTORE SLOT ID + STA Q6H,X ; AND WRITE THE TRANSLATED BYTE + LDA Q6L,X + LDA BUFFA,Y ; GET NEXT BYTE FROM BUFFER + INY ; AND LOOP TILL + BNE WRT4 ; ALL OF [BUFFA] IS WRITTEN + + TAX + LDA WRTTBL,X + LDX DTMP4 ; RESTORE SLOT ID + JSR WRBYT3 ; AND WRITE THE LAST [BUFFA] BYTE + + LDA #$DE ; WRITE DATA FIELD EPILOGUE: + JSR WRBYT1 ; $DE-$AA-$EB + LDA #$AA + JSR WRBYT1 + LDA #$EB + JSR WRBYT1 + + LDA #$FF ; WRITE GAP 3 + JSR WRBYT1 + + LDA Q7L,X ; SET DRIVE TO READ MODE + +WRT5: LDA Q6L,X + RTS + + ; ---------------------------- + ; WRITE A BYTE (TIME-CRITICAL) + ; ---------------------------- + + ; ENTRY: BYTE TO WRITE IN [A] + ; SLOT*16 IN [X] + +WRBYT1: CLC ; PROLOGUE, EPILOGUE AND GAP 3 TIMING +WRBYT2: PHA ; ENTRY FOR GAP 2 TIMING + PLA +WRBYT3: STA Q6H,X + ORA Q6L,X + RTS + + ; CONVERT RAW DATA TO BINARY IN [IOBUFF] + +POSTNB: LDY #0 +PST0: LDX #$56 +PST1: DEX + BMI PST0 + LDA BUFFA,Y + LSR BUFFB,X + ROL A + LSR BUFFB,X + ROL A + STA (DCBBFL),Y + INY + CPY DTMP3 + BNE PST1 + RTS + + ; ----------- + ; READ SECTOR + ; ----------- + + ; READ RAW SECTOR DATA TO [BUFFA/BUFFB] + + ; ENTRY: SLOT*16 IN [X] + ; EXIT: CARRY SET IF ERROR, ELSE 342 RAW BYTES IN [BUFFA/BUFFB] + +RDSECT: LDY #$20 +RDS1: DEY ; RETURN AN ERROR IF + BEQ RDBAD ; NO $D5 FOUND AFTER 32 TRIES + + ; FETCH & VALIDATE PROLOGUE ($D5-$AA-$AD) + +RDS2: LDA Q6L,X ; GET A BYTE + BPL RDS2 + +RDS3: EOR #$D5 ; WAS IT $D5? + BNE RDS1 ; NO, KEEP LOOKING + + NOP ; ELSE WAIT A MOMENT ... + +RDS4: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDS4 + CMP #$AA ; WAS IT $AA? + BNE RDS3 ; CHECK FOR $D5 AGAIN IF NOT + + LDY #$56 ; ELSE INIT DATA-READ INDEX + +RDS5: LDA Q6L,X ; GET A BYTE + BPL RDS5 + CMP #$AD ; WAS IT $AD? + BNE RDS3 ; CHECK FOR $D5 IF NOT + + ; READ RAW DATA INTO [BUFFB] + + LDA #0 ; CLEAR [A], DELAY ... + +RDS6: DEY + STY DTMP3 ; SAVE INDEX HERE + +RDS7: LDY Q6L,X ; GET A DATA BYTE + BPL RDS7 + EOR RDTBL-$96,Y ; TRANSLATE IT + LDY DTMP3 ; RESTORE INDEX + STA BUFFB,Y ; STORE BYTE IN [BUFFB] + BNE RDS6 ; CONTINUE TILL [BUFFB] FULL + + ; READ RAW DATA INTO [BUFFA] + +RDS8: STY DTMP3 ; RE-INIT INDEX TO ZERO + +RDS9: LDY Q6L,X ; GET A DATA BYTE + BPL RDS9 + EOR RDTBL-$96,Y ; TRANSLATE IT + LDY DTMP3 ; RESTORE INDEX + STA BUFFA,Y ; SAVE BYTE IN [BUFFA] + INY + BNE RDS8 ; LOOP TILL [BUFFA] IS FULL + + ; FETCH & VALIDATE CHECKSUM + +RDS10: LDY Q6L,X ; GET THE NEXT BYTE + BPL RDS10 + CMP RDTBL-$96,Y ; TRANSLATE IT + BNE RDBAD ; ERROR IF CHECKSUM BAD + + ; FETCH & VALIDATE EPILOGUE ($DE-$AA-$EB) + +RDS11: LDA Q6L,X ; GET A BYTE + BPL RDS11 + CMP #$DE ; IS IT $DE? + BNE RDBAD ; ERROR IF NOT + + NOP ; WAIT ... + +RDS12: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDS12 + CMP #$AA ; IS IT $AA? + BEQ RDOK ; DATA OKAY IF SO + +RDBAD: SEC ; ELSE SET CARRY FOR ERROR + RTS ; AND SCRAM + + ; --------------------- + ; READ AN ADDRESS FIELD + ; --------------------- + + ; ENTRY: SLOT*16 IN [X] + ; EXIT: CARRY SET IF ERROR + +RDADDR: LDY #$FC ; INIT TIMEOUT COUNTER + STY DTMP3 + +RDA1: INY + BNE RDA2 + INC DTMP3 ; ERROR IF + BEQ RDBAD ; CAN'T FIND ADDRESS HEADER + + ; FETCH THE ADDRESS FIELD PROLOGUE ($D5-$AA-$96) + +RDA2: LDA Q6L,X ; GRAB A BYTE + BPL RDA2 + +RDA3: CMP #$D5 ; WAS IT $D5? + BNE RDA1 ; NO, KEEP SEARCHING + + NOP ; ELSE WAIT A FEW MICROSECONDS ... + +RDA4: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDA4 + CMP #$AA ; WAS IT $AA? + BNE RDA3 ; NO, CHECK IF $D5 + + LDY #3 ; ELSE INIT DATA-FETCH INDEX + +RDA5: LDA Q6L,X ; GET A BYTE + BPL RDA5 + CMP #$96 ; WAS IT $96? + BNE RDA3 ; NO, CHECK FOR $D5 + + ; FETCH THE 4 BYTES OF ADDRESS DATA + + LDA #0 ; INIT CHECKSUM BYTE + +RDA6: STA DTMP4 ; UPDATE CHECKSUM + +RDA7: LDA Q6L,X ; GET A BYTE + BPL RDA7 + ROL A ; SHIFT IT + STA DTMP3 ; AND SAVE 1ST PART HERE + +RDA8: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDA8 + AND DTMP3 ; SUPER 1ST PART OF BYTE + STA HDRCHK,Y ; STORE IN RESULT TABLE + EOR DTMP4 ; COMPUTE CHECKSUM + DEY ; GOT 4 BYTES YET? + BPL RDA6 ; NO, LOOP BACK + + TAY ; LOOK AT CHECKSUM BYTE + BNE RDBAD ; ERROR IF NON-ZERO + + ; FETCH & VALIDATE EPILOGUE ($DE-$AA, IGNORE $EB) + +RDA9: LDA Q6L,X ; GET A BYTE + BPL RDA9 + CMP #$DE ; WAS IT $DE? + BNE RDBAD ; ERROR IF NOT + + NOP ; ELSE WAIT A MOMENT ... + +RDA10: LDA Q6L,X ; GET ONE MORE BYTE + BPL RDA10 + CMP #$AA ; WAS IT $AA + BNE RDBAD ; ERROR IF NOT + +RDOK: CLC ; ELSE CLEAR CARRY FOR SUCCESS + RTS ; AND RETURN + + ; --------------------- + ; MOVE ARM TO TRACK [A] + ; --------------------- + + ; ENTRY: SLOT*16 IN [X] + ; TARGET TRACK IN [A] + ; CURRENT TRACK IN [CTRACK] + +SEEK: STX SLTMP3 ; SAVE SLOT ID + STA TTRK ; AND TARGET TRACK + CMP CTRACK ; TARGET SAME AS CURRENT? + BEQ SEEKEX ; EXIT NOW IF SO + + LDA #0 ; INIT + STA DTMP3 ; INDEX + +SK1: LDA CTRACK ; GET CURRENT TRACK + STA DTMP4 ; SAVE IT HERE + SEC + SBC TTRK ; GET TRACK DIFFERENCE + BEQ SK6 + BCS SK2 + EOR #%11111111 + INC CTRACK + BCC SK3 + +SK2: ADC #$FE + DEC CTRACK + +SK3: CMP DTMP3 + BCC SK4 + LDA DTMP3 + +SK4: CMP #$0C + BCS SK5 + TAY + +SK5: SEC + JSR SEEK0 + LDA DELTB1,Y + JSR ARMDEL + LDA DTMP4 + CLC + JSR SEEK1 + LDA DELTB2,Y + JSR ARMDEL + INC DTMP3 + BNE SK1 + +SK6: JSR ARMDEL + CLC + +SEEK0: LDA CTRACK + +SEEK1: AND #%00000011 + ROL A + ORA SLTMP3 + TAX + LDA PH0OFF,X ; MOVE THE ARM + LDX SLTMP3 + +SEEKEX: RTS + + ; ------------------ + ; ARM MOVEMENT DELAY + ; ------------------ + + ; NOTE: THIS ROUTINE MUST BEGIN ON A PAGE BOUNDARY! + + ; ENTRY: 100uS DELAY INTERVAL IN [A] + ; MOTOR TIME COUNT IN [MTIME] + +ARMDEL: LDX #$11 +ARM1: DEX + BNE ARM1 + INC DCNT + BNE ARM2 + INC DTMP2 +ARM2: SEC + SBC #1 + BNE ARMDEL + RTS + + ; ------------------------- + ; ARM MOVEMENT DELAY TABLES + ; ------------------------- + +DELTB1: DB $01,$30,$28,$24,$20,$1E,$1D,$1C + DB $1C,$1C,$1C,$1C + +DELTB2: DB $70,$2C,$26,$22,$1F,$1E,$1D,$1C + DB $1C,$1C,$1C,$1C + + ; --------------------- + ; WRITE TRANSLATE TABLE + ; --------------------- + +WRTTBL: DB $96,$97,$9A,$9B,$9D,$9E,$9F,$A6 + DB $A7,$AB,$AC,$AD,$AE,$AF,$B2,$B3 + DB $B4,$B5,$B6,$B7,$B9,$BA,$BB,$BC + DB $BD,$BE,$BF,$CB,$CD,$CE,$CF,$D3 + DB $D6,$D7,$D9,$DA,$DB,$DC,$DD,$DE + DB $DF,$E5,$E6,$E7,$E9,$EA,$EB,$EC + DB $ED,$EE,$EF,$F2,$F3,$F4,$F5,$F6 + DB $F7,$F9,$FA,$FB,$FC,$FD,$FE,$FF + + ; -------------------- + ; READ TRANSLATE TABLE + ; -------------------- + +RDTBL: DB $00,$01,$98,$99,$02,$03,$9C,$04 + DB $05,$06,$A0,$A1,$A2,$A3,$A4,$A5 + DB $07,$08,$A8,$A9,$AA,$09,$0A,$0B + DB $0C,$0D,$B0,$B1,$0E,$0F,$10,$11 + DB $12,$13,$B8,$14,$15,$16,$17,$18 + DB $19,$1A,$C0,$C1,$C2,$C3,$C4,$C5 + DB $C6,$C7,$C8,$C9,$CA,$1B,$CC,$1C + DB $1D,$1E,$D0,$D1,$D2,$1F,$D4,$D5 + DB $20,$21,$D8,$22,$23,$24,$25,$26 + DB $27,$28,$E0,$E1,$E2,$E3,$E4,$29 + DB $2A,$2B,$E8,$2C,$2D,$2E,$2F,$30 + DB $31,$32,$F0,$F1,$33,$34,$35,$36 + DB $37,$38,$F8,$39,$3A,$3B,$3C,$3D + DB $3E,$3F + + ; --------------- + ; MAIN RWTS ENTRY + ; --------------- + + ; ENTRY: [A]=0 FOR READ, [A]=1 FOR WRITE + ; [SLOT] = TARGET SLOT + ; [DRIVE] = TARGET DRIVE + ; [TRACK] = TARGET TRACK + ; [SECTOR] = TARGET SECTOR + ; EXIT: CARRY CLEAR IF OKAY + + ; COMMENTS - LINDE + + ; ACTUAL VARIABLES ARE: + ; [DCBSLT] = SLOT + ; [DCBTRK] = TRACK + ; [DCBSEC] = SECTOR + ; [[DCBDRV] = DRIVE + + ; FOR TRK, SEC, DRV 1 = 1 (DRIVE 1, SET DCBDRV TO 1) + ; FOR SLT - MULTIPLY SLOT BY 16 (SLOT 6, SET DCBSLT TO $60) + +DOS: STA DCBCMD ; SAVE COMMAND + LDA #2 ; ALLOW 2 + STA NRECAL ; RECALS + ASL A ; AND 4 + STA NSEEK ; SEEKS + + LDX DCBSLT ; GET REQUESTED SLOT ID + CPX DCBPSL ; SAME AS LAST SLOT? + BEQ SAMESL ; YES, CONTINUE + LDX DCBPSL + + ; WAIT FOR OLD DRIVE TO TURN OFF, UPDATE SLOT ID + + LDA Q7L,X ; SET OLD SLOT TO READ MODE +RW1: LDY #8 ; INIT COUNTER + LDA Q6L,X +RW2: CMP Q6L,X + BNE RW1 + DEY + BNE RW2 + + LDX DCBSLT ; GET NEW SLOT ID INTO [X] + STX DCBPSL ; MAKE IT THE "OLD" SLOT + + ; CURRENT SLOT ID IN [X] + +SAMESL: LDA Q7L,X ; GET DRIVE INTO READ MODE + LDA Q6L,X ; READ WITH DELAYS + LDY #8 ; TO SEE IF DRIVE IS SPINNING +RW4: LDA Q6L,X + PHA + PLA + PHA + PLA + STX SLTMP1 ; SAVE SLOT HERE + CMP Q6L,X + BNE RW5 + DEY + BNE RW4 + +RW5: PHP ; SAVE TEST RESULT ON STACK + LDA DRVON,X ; TURN ON MOTOR + + LDA #$D8 ; REFRESH + STA DTMP2 ; MOTOR TIME CONSTANT + + ; CHECK DRIVE ID + + LDA DCBDRV + CMP DCBPDR ; HAS DRIVE CHANGED? + BEQ RW7 ; NO, CONTINUE + + STA DCBPDR ; ELSE MAKE NEW DRIVE "OLD" + PLP ; SET ZERO FLAG + LDY #0 ; OF TEST RESULT + PHP ; AND PUSH IT BACK ON STACK + +RW7: ROR A ; CHECK DRIVE ID + BCC RW8 ; CARRY WILL BE CLEAR IF DRIVE = 2 + LDA DRV0EN,X ; ELSE SELECT DRIVE #1 + BCS RW9 ; BRANCH ALWAYS + +RW8: LDA DRV1EN,X ; SELECT DRIVE #2 + +RW9: ROR DRVFLG ; HIGH BIT = 1 FOR DRIVE 1, 0 FOR 2 + + PLP ; CHECK TEST RESULTS + PHP + BNE RW11 ; BRANCH IF DRIVE WAS ON + + LDY #7 ; WAIT FOR CAP DISCHARGE +RW10: JSR ARMDEL + DEY + BNE RW10 + + LDX SLTMP1 ; RESTORE SLOT ID + + ; SEEK THE TARGET TRACK + +RW11: LDA DCBTRK ; GET TARGET TRACK + JSR MYSEEK + + PLP ; WAS DRIVE ON? + BNE RW14 ; YES, CONTINUE + + ; WAIT FOR DRIVE TO COME UP TO SPEED + + LDY DTMP2 + BPL RW14 + +RW12: LDY #$12 ; WAIT FOR DRIVE TO +RW13: DEY ; COME UP TO SPEED + BNE RW13 + INC DCNT + BNE RW12 + INC DTMP2 + BNE RW12 + + ; DECODE DISK COMMAND + +RW14: LDA DCBCMD ; GET COMMAND + ROR A ; CARRY = 0 IF "READ" + PHP ; SAVE READ/WRITE STATUS + ; AND MAINTAIN STACK + BCC GETADR ; BRANCH IF "READ" + JSR PRENIB + + ; FETCH AN ADDRESS FIELD + +GETADR: LDA #48 + STA DTMP1 ; INIT RETRY COUNT + +GTA0: LDX SLTMP1 ; RESTORE SLOT ID + JSR RDADDR ; GET AN ADDRESS FIELD + BCC RRIGHT ; CONTINUE IF SUCCESSFUL + +GTA1: DEC DTMP1 ; ELSE UPDATE RETRY COUNT + BPL GTA0 ; AND TRY AGAIN + + ; RECALIBRATE THE ARM + +GTA2: LDA CTRACK ; SAVE THE + PHA ; CURRENT TRACK ID + + LDA #$60 + JSR SETTRK + DEC NRECAL ; UPDATE RECAL COUNT + BEQ DRVERR ; ERROR IF EMPTY + LDA #4 ; RESET + STA NSEEK ; SEEK COUNT + LDA #0 ; CALIBRATE THE ARM + JSR MYSEEK ; TO TRACK #0 + PLA ; RESTORE CURRENT TRACK + +GTA3: JSR MYSEEK ; GO TO IT + JMP GETADR ; AND TRY AGAIN + + ; ADDRESS FIELD FOUND + +RRIGHT: LDY HDRTRK + CPY CTRACK ; ON THE RIGHT TRACK? + BEQ RTTRAK ; YES, CONTINUE + + LDA CTRACK + PHA + TYA + JSR SETTRK + PLA + DEC NSEEK + BNE GTA3 + BEQ GTA2 ; ELSE RECALIBRATE + + ; HANDLE A DRIVE ERROR + +DRVERR: PLA ; CLEAN UP STACK + LDA #$40 ; $40 = DRIVE ERROR +EREXT: PLP ; CLEAN UP STATUS REGISTER + JMP DERROR + + ; CHECK FOR PROPER SECTOR (VOLUME CHECK OMITTED) + +RTTRAK: LDY DCBSEC + LDA ILEAVE,Y ; GET INTERLEAVE BYTE + CMP HDRSEC ; MATCHED FOUND SECTOR? + BNE GTA1 ; NO, TRY AGAIN + + ; SECTOR FOUND! + + PLP ; WILL THIS BE READ OR WRITE? + BCS DWRITE ; DO "WRITE" IF CARRY SET + + ; READ A SECTOR + + JSR RDSECT ; DO THE READ + + BCC GTA3A ; OK + CLC ; RESET FOR NEXT TIME THRU + PHP ; AND PUSH FOR NEXT TIME THRU + BCC GTA1 ; JMP, ERROR OCCURRED + +; CHANGED TO ABOVE 4 LINES 1/14/86, CARRY MUST BE CLEARED SO READS +; PHP ; SAVE STATUS +; BCS GTA1 ; ERROR IF CARRY WAS SET +; PLP ; ELSE DUMP STATUS + +GTA3A: LDX #$00 + STX DTMP3 + JSR POSTNB + + LDX SLTMP1 ; RESTORE SLOT ID + +DONE: LDA #0 ; 0 = NO ERRORS + CLC ; CARRY CLEAR FOR SUCCESS + BCC EXIT + + ; ERROR EXIT + +DERROR: SEC ; CARRY SET FOR ERROR + + ; GENERAL EXIT + +EXIT: STA DCBERR ; SAVE ERROR CODE HERE + LDA DRVOFF,X ; STOP THE DRIVE + + RTS ; BYE! + + ; WRITE A SECTOR + +DWRITE: JSR WRTDTA + BCC DONE ; ALL'S WELL IF CARRY CLEAR + LDA #$10 ; ELSE GET ERROR CODE INTO [A] + BNE DERROR ; AND DO AN ERROR EXIT + + ; --------------------- + ; SET UP FOR TRACK SEEK + ; --------------------- + +MYSEEK: ASL A ; TRACK*2 (PHASE OF DISK CARE) + JSR DOSEEK + LSR CTRACK ; CURRENT TRACK/2 + RTS + + ; -------------- + ; EXECUTE A SEEK + ; -------------- + + ; PAGE BOUNDARY SHOULD BEGIN HERE! + +DOSEEK: STA TTRK + JSR XTOY + LDA DR1TBL,Y + BIT DRVFLG + BMI DSE1 + LDA DR2TBL,Y +DSE1: STA CTRACK + LDA TTRK + BIT DRVFLG + BMI DSE2 + STA DR2TBL,Y + BPL DSE3 +DSE2: STA DR1TBL,Y +DSE3: JMP SEEK + + ; -------------------- + ; GET SLOT ID INTO [Y] + ; -------------------- + +XTOY: TXA + LSR A + LSR A + LSR A + LSR A + TAY + RTS + + ; ------------ + ; SET TRACK ID + ; ------------ + +SETTRK: PHA + LDA DCBDRV + ROR A + ROR DRVFLG + JSR XTOY + PLA + ASL A + BIT DRVFLG + BMI STT1 + STA DR2TBL,Y + BPL STT2 +STT1: STA DR1TBL,Y +STT2: RTS + + ; ----------- + ; IDOS TABLES + ; ----------- + +DR1TBL: DB $00,$00,$00,$00 ; (8 BYTES) + DB $00,$00,$00,$00 + +CTRACK EQU DR1TBL ; CURRENT TRACK + +DR2TBL: DB $00,$00,$00,$00 ; (8 BYTES) + DB $00,$00,$00,$00 + +NSEEK: DB $00 ; SEEK COUNT +DTMP1: DB $00 ; RETRY COUNT +SLTMP1: DB $00 ; SLOT ID +SLTMP2: DB $00 +NRECAL: DB $00 ; RECALIBRATE COUNT + + ; ---------------------- + ; MACHINE INITIALIZATION + ; ---------------------- + +INIT: LDA TXTSET ; SET TEXT MODE + LDA MIXCLR ; SET NO MIX + LDA LOWSCR ; SET PAGE 1 + + LDA #HIGH IOBUFF ; POINT [DCBBFL/H] TO [IOBUFF] + STA DCBBFH + LDA #LOW IOBUFF + STA DCBBFL + + LDA #1 + STA DCBDRV ; SET DRIVE = 1 + STA DCBPDR + + RTS + + END + diff --git a/apple/zip/rwts.l b/apple/zip/rwts.l new file mode 100644 index 0000000..d60f4cf --- /dev/null +++ b/apple/zip/rwts.l @@ -0,0 +1,928 @@ + PAGE + SBTTL "--- BOOT CODE & RWTS: APPLE II ---" + + ; --------- + ; BOOT CODE + ; --------- + + ; LOADS ALL OF TRACK 0 INTO RAM AT $800 TO $1800, + ; THEN JUMPS THROUGH [COLD] + + ORG ZIP + + DB $01 ; MAGICAL MYSTERY BYTE + + ; BOOT BEGINS HERE + +BOOT: LDA BADDR+HI ; CHECK MSB OF BOOT ADDRESS + CMP #$09 ; 1ST ENTRY INTO BOOT? + BNE BT0 ; NO, CONTINUE + + ; CALC ADDRESS OF ROM SECTOR READ ROUTINE + + LDA BSLOT ; GET SLOT ID * 16 + STA DCBSLT ; MAKE IT THE DEFAULT TARGET + STA DCBPSL ; AND THE "OLD" SLOT + LSR A ; DIVIDE BY 16 + LSR A + LSR A + LSR A + ORA #%11000000 ; MAKE IT $C0nn + STA I+HI ; USE AS MSB OF ADDRESS + LDA #$5C ; LSB IS ALWAYS $5C + STA I+LO + + LDA #1 + STA DCBSEC + +BT0: LDX DCBSEC + INC DCBSEC + CPX #$10 + BCS BT1 + LDA ILEAVE,X + STA BSECT + LDX BSLOT + JMP (I) + +BT1: JSR INIT + JMP COLD ; LOAD REMAINDER OF ZIP + + ; --------------------- + ; SECTOR INTERLEAVE MAP + ; --------------------- + + ; USED BY "BOOT" AND "RWTS" + ; MUST BE IN 1ST PAGE! + +ILEAVE: DB $00,$04,$08,$0C,$01,$05,$09,$0D + DB $02,$06,$0A,$0E,$03,$07,$0B,$0F + + ; INFOCOM'S VERSION OF APPLE RWTS (READ/WRITE TRACK/SECTOR) + + ; HACKED BY ANDREW KALUZNIACKI + ; FROM THE DOS RWTS ON APPLE DOS 3.3 + + ; ------------ + ; SPACE FILLER + ; ------------ + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00 + + ; ------------------------------- + ; MAIN ENTRY INTO INFO-DOS (IDOS) + ; ------------------------------- + + ; [DCBSEC] SECTOR (0-15), SET BY CALLER + ; [DCBTRK] TRACK (0-34), SET BY CALLER + ; [DCBDRV] DRIVE (1 OR 2), SET BY CALLER [BOOT DEFAULT] + ; [DCBSLT] SLOT*16, SET BY CALLER [BOOT DEFAULT] + ; [DCBPSL] SLOT*16 OF LAST USED SLOT, SET BY BOOT + ; [DCBPDR] LAST DRIVE USED (1 OR 2), SET BY BOOT + ; [DCBCMD] STORAGE FOR COMMAND SENT IN AT CALL TO IDOS + ; [DCBERR] IDOS ERROR CODE + ; [DCBBFL] DISK BUFFER ADDRESS (LSB) [BOOT = IOBUFF] + ; [DCBBFH] DISK BUFFER ADDRESS (MSB) [BOOT = IOBUFF] + + ; =1 WRITES DISK BUFFER + ; =0 READS DISK BUFFER + + ; [IOBUFF] = 256-BYTE BUFFER FOR DISK I/O + ; (OPTIONAL IF [DCBBFL/DCBBFH] ARE SET) + + ; [BUFFA] ONE PAGE BUFFER + ; [BUFFB] $56 BYTE BUFFER + + ; CARRY CLEAR ON RETURN IF NO ERROR + ; IF CARRY SET, ERROR CODE IS IN [DERR]: + + ; $10 = WRITE PROTECTED + ; $40 = DRIVE ERROR + ; $80 = READ ERROR + + ; *** WARNING *** + + ; IDOS MUST START ON A PAGE BOUNDARY. + ; CHANGE ANY CODE BETWEEN [IDOS] AND [INIT] AT YOUR OWN RISK. + ; YOU HAVE BEEN WARNED. + +IDOS: NOP + NOP + NOP ; DON'T ASK, AND DON'T CHANGE + PHP ; SAVE STATUS OF [I] + SEI ; DISABLE INTERUPTS + JSR DOS ; DO IT (GO TO MAIN ROUTINE) + BCS DOSERR ; ERROR OCCURED IF C=1 + PLP ; RESTORE [I] + CLC ; SET "NO ERROR" + RTS ; RETURN FROM CALL +DOSERR: PLP ; RESTORE [I] + SEC ; INDICATE ERROR + RTS ; EXIT + + ; PRE-NIBBLIZE [IOBUFF] BEFORE WRITING + +PRENIB: LDX #0 + LDY #2 +PREN0: DEY + LDA (DCBBFL),Y + LSR A + ROL BUFFB,X + LSR A + ROL BUFFB,X + STA BUFFA,Y + INX + CPX #$56 + BCC PREN0 + + LDX #0 + TYA + BNE PREN0 + + LDX #$55 ; CLEAR BITS 7 AND 6 +PREN1: LDA BUFFB,X ; OF TOP NIBBLE BUFFER + AND #%00111111 + STA BUFFB,X + DEX + BPL PREN1 + RTS + + ; ------------ + ; WRITE SECTOR + ; ------------ + + ; WRITES PRENIBBLIZED DATA AT [BUFFA/BUFFB] TO DISK + + ; ENTRY: SLOT*16 IN [X] + ; EXIT: CARRY SET IF ERROR + +WRTDTA: STX DTMP4 ; SAVE SLOT ID HERE + STX SLTMP2 + + SEC ; SET CARRY FOR POSSIBLE ERROR + LDA Q6H,X ; CHECK FOR WRITE-PROTECT + LDA Q7L,X + BMI WRT5 ; EXIT W/CARRY SET IF PROTECTED + + LDA BUFFB ; SAVE 1ST BYTE OF 2NDARY BUFFER + STA DTMP3 ; FOR LATER + + LDA #$FF ; ESTABLISH AUTOSYNC BYTE + + STA Q7H,X ; SET DRIVE TO WRITE MODE + ORA Q6L,X ; WAIT FOR HARDWARE TO SETTLE + PHA + PLA + NOP + + LDY #4 ; WRITE 5 AUTOSYNC BYTES +WRT1: PHA + PLA + JSR WRBYT2 ; USING 40 uS DELAY + DEY + BNE WRT1 + + LDA #$D5 ; WRITE DATA FIELD PROLOGUE: + JSR WRBYT1 ; $D5-$AA-$AD + LDA #$AA + JSR WRBYT1 + LDA #$AD + JSR WRBYT1 + + TYA ; A BRIEF DELAY + + LDY #$56 ; INIT LOOP INDEX + BNE WRT3 ; BRANCH ALWAYS + + ; WRITE [BUFFB] TO DISK + +WRT2: LDA BUFFB,Y ; GET A BYTE FROM [BUFFB] + +WRT3: EOR BUFFB-1,Y + TAX ; USE IT AS AN INDEX + LDA WRTTBL,X ; INTO THE TRANSLATE TABLE + LDX DTMP4 ; RESTORE SLOT ID + STA Q6H,X ; AND WRITE THE TRANSLATED BYTE + LDA Q6L,X + DEY ; LOOP TILL + BNE WRT2 ; EMPTY + + ; WRITE [BUFFA] TO DISK + + LDA DTMP3 ; RESTORE "LOST" [BUFFB] BYTE + NOP ; WAIT JUST A MOMENT ... + +WRT4: EOR BUFFA,Y ; GET A BYTE FROM [BUFFA] + TAX ; USE IT AS AN INDEX + LDA WRTTBL,X ; INTO THE TRANSLATE TABLE + LDX SLTMP2 ; RESTORE SLOT ID + STA Q6H,X ; AND WRITE THE TRANSLATED BYTE + LDA Q6L,X + LDA BUFFA,Y ; GET NEXT BYTE FROM BUFFER + INY ; AND LOOP TILL + BNE WRT4 ; ALL OF [BUFFA] IS WRITTEN + + TAX + LDA WRTTBL,X + LDX DTMP4 ; RESTORE SLOT ID + JSR WRBYT3 ; AND WRITE THE LAST [BUFFA] BYTE + + LDA #$DE ; WRITE DATA FIELD EPILOGUE: + JSR WRBYT1 ; $DE-$AA-$EB + LDA #$AA + JSR WRBYT1 + LDA #$EB + JSR WRBYT1 + + LDA #$FF ; WRITE GAP 3 + JSR WRBYT1 + + LDA Q7L,X ; SET DRIVE TO READ MODE + +WRT5: LDA Q6L,X + RTS + + ; ---------------------------- + ; WRITE A BYTE (TIME-CRITICAL) + ; ---------------------------- + + ; ENTRY: BYTE TO WRITE IN [A] + ; SLOT*16 IN [X] + +WRBYT1: CLC ; PROLOGUE, EPILOGUE AND GAP 3 TIMING +WRBYT2: PHA ; ENTRY FOR GAP 2 TIMING + PLA +WRBYT3: STA Q6H,X + ORA Q6L,X + RTS + + ; ----------- + ; READ SECTOR + ; ----------- + + ; READ RAW SECTOR DATA TO [BUFFA/BUFFB] + + ; ENTRY: SLOT*16 IN [X] + ; EXIT: CARRY SET IF ERROR, ELSE 342 RAW BYTES IN [BUFFA/BUFFB] + +RDSECT: LDY #$20 +RDS1: DEY ; RETURN AN ERROR IF + BEQ RDBAD ; NO $D5 FOUND AFTER 32 TRIES + + ; FETCH & VALIDATE PROLOGUE ($D5-$AA-$AD) + +RDS2: LDA Q6L,X ; GET A BYTE + BPL RDS2 + +RDS3: EOR #$D5 ; WAS IT $D5? + BNE RDS1 ; NO, KEEP LOOKING + + NOP ; ELSE WAIT A MOMENT ... + +RDS4: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDS4 + CMP #$AA ; WAS IT $AA? + BNE RDS3 ; CHECK FOR $D5 AGAIN IF NOT + + LDY #$56 ; ELSE INIT DATA-READ INDEX + +RDS5: LDA Q6L,X ; GET A BYTE + BPL RDS5 + CMP #$AD ; WAS IT $AD? + BNE RDS3 ; CHECK FOR $D5 IF NOT + + ; READ RAW DATA INTO [BUFFB] + + LDA #0 ; CLEAR [A], DELAY ... + +RDS6: DEY + STY DTMP3 ; SAVE INDEX HERE + +RDS7: LDY Q6L,X ; GET A DATA BYTE + BPL RDS7 + EOR RDTBL-$96,Y ; TRANSLATE IT + LDY DTMP3 ; RESTORE INDEX + STA BUFFB,Y ; STORE BYTE IN [BUFFB] + BNE RDS6 ; CONTINUE TILL [BUFFB] FULL + + ; READ RAW DATA INTO [BUFFA] + +RDS8: STY DTMP3 ; RE-INIT INDEX TO ZERO + +RDS9: LDY Q6L,X ; GET A DATA BYTE + BPL RDS9 + EOR RDTBL-$96,Y ; TRANSLATE IT + LDY DTMP3 ; RESTORE INDEX + STA BUFFA,Y ; SAVE BYTE IN [BUFFA] + INY + BNE RDS8 ; LOOP TILL [BUFFA] IS FULL + + ; FETCH & VALIDATE CHECKSUM + +RDS10: LDY Q6L,X ; GET THE NEXT BYTE + BPL RDS10 + CMP RDTBL-$96,Y ; TRANSLATE IT + BNE RDBAD ; ERROR IF CHECKSUM BAD + + ; FETCH & VALIDATE EPILOGUE ($DE-$AA-$EB) + +RDS11: LDA Q6L,X ; GET A BYTE + BPL RDS11 + CMP #$DE ; IS IT $DE? + BNE RDBAD ; ERROR IF NOT + + NOP ; WAIT ... + +RDS12: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDS12 + CMP #$AA ; IS IT $AA? + BEQ RDOK ; DATA OKAY IF SO + +RDBAD: SEC ; ELSE SET CARRY FOR ERROR + RTS ; AND SCRAM + + ; --------------------- + ; READ AN ADDRESS FIELD + ; --------------------- + + ; ENTRY: SLOT*16 IN [X] + ; EXIT: CARRY SET IF ERROR + +RDADDR: LDY #$FC ; INIT TIMEOUT COUNTER + STY DTMP3 + +RDA1: INY + BNE RDA2 + INC DTMP3 ; ERROR IF + BEQ RDBAD ; CAN'T FIND ADDRESS HEADER + + ; FETCH THE ADDRESS FIELD PROLOGUE ($D5-$AA-$96) + +RDA2: LDA Q6L,X ; GRAB A BYTE + BPL RDA2 + +RDA3: CMP #$D5 ; WAS IT $D5? + BNE RDA1 ; NO, KEEP SEARCHING + + NOP ; ELSE WAIT A FEW MICROSECONDS ... + +RDA4: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDA4 + CMP #$AA ; WAS IT $AA? + BNE RDA3 ; NO, CHECK IF $D5 + + LDY #3 ; ELSE INIT DATA-FETCH INDEX + +RDA5: LDA Q6L,X ; GET A BYTE + BPL RDA5 + CMP #$96 ; WAS IT $96? + BNE RDA3 ; NO, CHECK FOR $D5 + + ; FETCH THE 4 BYTES OF ADDRESS DATA + + LDA #0 ; INIT CHECKSUM BYTE + +RDA6: STA DTMP4 ; UPDATE CHECKSUM + +RDA7: LDA Q6L,X ; GET A BYTE + BPL RDA7 + ROL A ; SHIFT IT + STA DTMP3 ; AND SAVE 1ST PART HERE + +RDA8: LDA Q6L,X ; GET ANOTHER BYTE + BPL RDA8 + AND DTMP3 ; SUPER 1ST PART OF BYTE + STA HDRCHK,Y ; STORE IN RESULT TABLE + EOR DTMP4 ; COMPUTE CHECKSUM + DEY ; GOT 4 BYTES YET? + BPL RDA6 ; NO, LOOP BACK + + TAY ; LOOK AT CHECKSUM BYTE + BNE RDBAD ; ERROR IF NON-ZERO + + ; FETCH & VALIDATE EPILOGUE ($DE-$AA, IGNORE $EB) + +RDA9: LDA Q6L,X ; GET A BYTE + BPL RDA9 + CMP #$DE ; WAS IT $DE? + BNE RDBAD ; ERROR IF NOT + + NOP ; ELSE WAIT A MOMENT ... + +RDA10: LDA Q6L,X ; GET ONE MORE BYTE + BPL RDA10 + CMP #$AA ; WAS IT $AA + BNE RDBAD ; ERROR IF NOT + +RDOK: CLC ; ELSE CLEAR CARRY FOR SUCCESS + RTS ; AND RETURN + + ; --------------------- + ; MOVE ARM TO TRACK [A] + ; --------------------- + + ; ENTRY: SLOT*16 IN [X] + ; TARGET TRACK IN [A] + ; CURRENT TRACK IN [CTRACK] + +SEEK: STX SLTMP3 ; SAVE SLOT ID + STA TTRK ; AND TARGET TRACK + CMP CTRACK ; TARGET SAME AS CURRENT? + BEQ SEEKEX ; EXIT NOW IF SO + + LDA #0 ; INIT + STA DTMP3 ; INDEX + +SK1: LDA CTRACK ; GET CURRENT TRACK + STA DTMP4 ; SAVE IT HERE + SEC + SBC TTRK ; GET TRACK DIFFERENCE + BEQ SK6 + BCS SK2 + EOR #%11111111 + INC CTRACK + BCC SK3 + +SK2: ADC #$FE + DEC CTRACK + +SK3: CMP DTMP3 + BCC SK4 + LDA DTMP3 + +SK4: CMP #$0C + BCS SK5 + TAY + +SK5: SEC + JSR SEEK0 + LDA DELTB1,Y + JSR ARMDEL + LDA DTMP4 + CLC + JSR SEEK1 + LDA DELTB2,Y + JSR ARMDEL + INC DTMP3 + BNE SK1 + +SK6: JSR ARMDEL + CLC + +SEEK0: LDA CTRACK + +SEEK1: AND #%00000011 + ROL A + ORA SLTMP3 + TAX + LDA PH0OFF,X ; MOVE THE ARM + LDX SLTMP3 + +SEEKEX: RTS + + ; -------------- + ; EXECUTE A SEEK + ; -------------- + + ; PAGE BOUNDARY SHOULD BEGIN HERE! + + DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + +DOSEEK: STA TTRK + JSR XTOY + LDA DR1TBL,Y + BIT DRVFLG + BMI DSE1 + LDA DR2TBL,Y +DSE1: STA CTRACK + LDA TTRK + BIT DRVFLG + BMI DSE2 + STA DR2TBL,Y + BPL DSE3 +DSE2: STA DR1TBL,Y +DSE3: JMP SEEK + + ; ------------------------- + ; ARM MOVEMENT DELAY TABLES + ; ------------------------- + +DELTB1: DB $01,$30,$28,$24,$20,$1E,$1D,$1C + DB $1C,$1C,$1C,$1C + +DELTB2: DB $70,$2C,$26,$22,$1F,$1E,$1D,$1C + DB $1C,$1C,$1C,$1C + + ; --------------------- + ; WRITE TRANSLATE TABLE + ; --------------------- + +WRTTBL: DB $96,$97,$9A,$9B,$9D,$9E,$9F,$A6 + DB $A7,$AB,$AC,$AD,$AE,$AF,$B2,$B3 + DB $B4,$B5,$B6,$B7,$B9,$BA,$BB,$BC + DB $BD,$BE,$BF,$CB,$CD,$CE,$CF,$D3 + DB $D6,$D7,$D9,$DA,$DB,$DC,$DD,$DE + DB $DF,$E5,$E6,$E7,$E9,$EA,$EB,$EC + DB $ED,$EE,$EF,$F2,$F3,$F4,$F5,$F6 + DB $F7,$F9,$FA,$FB,$FC,$FD,$FE,$FF + + ; -------------------- + ; READ TRANSLATE TABLE + ; -------------------- + +RDTBL: DB $00,$01,$98,$99,$02,$03,$9C,$04 + DB $05,$06,$A0,$A1,$A2,$A3,$A4,$A5 + DB $07,$08,$A8,$A9,$AA,$09,$0A,$0B + DB $0C,$0D,$B0,$B1,$0E,$0F,$10,$11 + DB $12,$13,$B8,$14,$15,$16,$17,$18 + DB $19,$1A,$C0,$C1,$C2,$C3,$C4,$C5 + DB $C6,$C7,$C8,$C9,$CA,$1B,$CC,$1C + DB $1D,$1E,$D0,$D1,$D2,$1F,$D4,$D5 + DB $20,$21,$D8,$22,$23,$24,$25,$26 + DB $27,$28,$E0,$E1,$E2,$E3,$E4,$29 + DB $2A,$2B,$E8,$2C,$2D,$2E,$2F,$30 + DB $31,$32,$F0,$F1,$33,$34,$35,$36 + DB $37,$38,$F8,$39,$3A,$3B,$3C,$3D + DB $3E,$3F + + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; FILLER FOR ALIGNMENT + DB 0,0,0,0,0,0,0,0,0,0,0 + + ; ------------------ + ; ARM MOVEMENT DELAY + ; ------------------ + + ; NOTE: THIS ROUTINE MUST BEGIN ON A PAGE BOUNDARY! + + ; ENTRY: 100uS DELAY INTERVAL IN [A] + ; MOTOR TIME COUNT IN [MTIME] + +ARMDEL: LDX #$11 +ARM1: DEX + BNE ARM1 + INC DCNT + BNE ARM2 + INC DTMP2 +ARM2: SEC + SBC #1 + BNE ARMDEL + RTS + + ; --------------- + ; MAIN RWTS ENTRY + ; --------------- + + ; ENTRY: [A]=0 FOR READ, [A]=1 FOR WRITE + ; [SLOT] = TARGET SLOT + ; [DRIVE] = TARGET DRIVE + ; [TRACK] = TARGET TRACK + ; [SECTOR] = TARGET SECTOR + ; EXIT: CARRY CLEAR IF OKAY + + ; COMMENTS - LINDE + + ; ACTUAL VARIABLES ARE: + ; [DCBSLT] = SLOT + ; [DCBTRK] = TRACK + ; [DCBSEC] = SECTOR + ; [[DCBDRV] = DRIVE + + ; FOR TRK, SEC, DRV 1 = 1 (DRIVE 1, SET DCBDRV TO 1) + ; FOR SLT - MULTIPLY SLOT BY 16 (SLOT 6, SET DCBSLT TO $60) + +DOS: STA DCBCMD ; SAVE COMMAND + LDA #2 ; ALLOW 2 + STA NRECAL ; RECALS + ASL A ; AND 4 + STA NSEEK ; SEEKS + + LDX DCBSLT ; GET REQUESTED SLOT ID + CPX DCBPSL ; SAME AS LAST SLOT? + BEQ SAMESL ; YES, CONTINUE + LDX DCBPSL + + ; WAIT FOR OLD DRIVE TO TURN OFF, UPDATE SLOT ID + + LDA Q7L,X ; SET OLD SLOT TO READ MODE +RW1: LDY #8 ; INIT COUNTER + LDA Q6L,X +RW2: CMP Q6L,X + BNE RW1 + DEY + BNE RW2 + + LDX DCBSLT ; GET NEW SLOT ID INTO [X] + STX DCBPSL ; MAKE IT THE "OLD" SLOT + + ; CURRENT SLOT ID IN [X] + +SAMESL: LDA Q7L,X ; GET DRIVE INTO READ MODE + LDA Q6L,X ; READ WITH DELAYS + LDY #8 ; TO SEE IF DRIVE IS SPINNING +RW4: LDA Q6L,X + PHA + PLA + PHA + PLA + STX SLTMP1 ; SAVE SLOT HERE + CMP Q6L,X + BNE RW5 + DEY + BNE RW4 + +RW5: PHP ; SAVE TEST RESULT ON STACK + LDA DRVON,X ; TURN ON MOTOR + + LDA #$D8 ; REFRESH + STA DTMP2 ; MOTOR TIME CONSTANT + + ; CHECK DRIVE ID + + LDA DCBDRV + CMP DCBPDR ; HAS DRIVE CHANGED? + BEQ RW7 ; NO, CONTINUE + + STA DCBPDR ; ELSE MAKE NEW DRIVE "OLD" + PLP ; SET ZERO FLAG + LDY #0 ; OF TEST RESULT + PHP ; AND PUSH IT BACK ON STACK + +RW7: ROR A ; CHECK DRIVE ID + BCC RW8 ; CARRY WILL BE CLEAR IF DRIVE = 2 + LDA DRV0EN,X ; ELSE SELECT DRIVE #1 + BCS RW9 ; BRANCH ALWAYS + +RW8: LDA DRV1EN,X ; SELECT DRIVE #2 + +RW9: ROR DRVFLG ; HIGH BIT = 1 FOR DRIVE 1, 0 FOR 2 + + PLP ; CHECK TEST RESULTS + PHP + BNE RW11 ; BRANCH IF DRIVE WAS ON + + LDY #7 ; WAIT FOR CAP DISCHARGE +RW10: JSR ARMDEL + DEY + BNE RW10 + + LDX SLTMP1 ; RESTORE SLOT ID + + ; SEEK THE TARGET TRACK + +RW11: LDA DCBTRK ; GET TARGET TRACK + JSR MYSEEK + + PLP ; WAS DRIVE ON? + BNE RW14 ; YES, CONTINUE + + ; WAIT FOR DRIVE TO COME UP TO SPEED + + LDY DTMP2 + BPL RW14 + +RW12: LDY #$12 ; WAIT FOR DRIVE TO +RW13: DEY ; COME UP TO SPEED + BNE RW13 + INC DCNT + BNE RW12 + INC DTMP2 + BNE RW12 + + ; DECODE DISK COMMAND + +RW14: LDA DCBCMD ; GET COMMAND + ROR A ; CARRY = 0 IF "READ" + PHP ; SAVE READ/WRITE STATUS + ; AND MAINTAIN STACK + BCC GETADR ; BRANCH IF "READ" + JSR PRENIB + + ; FETCH AN ADDRESS FIELD + +GETADR: LDA #48 + STA DTMP1 ; INIT RETRY COUNT + +GTA0: LDX SLTMP1 ; RESTORE SLOT ID + JSR RDADDR ; GET AN ADDRESS FIELD + BCC RRIGHT ; CONTINUE IF SUCCESSFUL + +GTA1: DEC DTMP1 ; ELSE UPDATE RETRY COUNT + BPL GTA0 ; AND TRY AGAIN + + ; RECALIBRATE THE ARM + +GTA2: LDA CTRACK ; SAVE THE + PHA ; CURRENT TRACK ID + + LDA #$60 + JSR SETTRK + DEC NRECAL ; UPDATE RECAL COUNT + BEQ DRVERR ; ERROR IF EMPTY + LDA #4 ; RESET + STA NSEEK ; SEEK COUNT + LDA #0 ; CALIBRATE THE ARM + JSR MYSEEK ; TO TRACK #0 + PLA ; RESTORE CURRENT TRACK + +GTA3: JSR MYSEEK ; GO TO IT + JMP GETADR ; AND TRY AGAIN + + ; ADDRESS FIELD FOUND + +RRIGHT: LDY HDRTRK + CPY CTRACK ; ON THE RIGHT TRACK? + BEQ RTTRAK ; YES, CONTINUE + + LDA CTRACK + PHA + TYA + JSR SETTRK + PLA + DEC NSEEK + BNE GTA3 + BEQ GTA2 ; ELSE RECALIBRATE + + ; HANDLE A DRIVE ERROR + +DRVERR: PLA ; CLEAN UP STACK + LDA #$40 ; $40 = DRIVE ERROR +EREXT: PLP ; CLEAN UP STATUS REGISTER + JMP DERROR + + ; CHECK FOR PROPER SECTOR (VOLUME CHECK OMITTED) + +RTTRAK: LDY DCBSEC + LDA ILEAVE,Y ; GET INTERLEAVE BYTE + CMP HDRSEC ; MATCHED FOUND SECTOR? + BNE GTA1 ; NO, TRY AGAIN + + ; SECTOR FOUND! + + PLP ; WILL THIS BE READ OR WRITE? + BCS DWRITE ; DO "WRITE" IF CARRY SET + + ; READ A SECTOR + + JSR RDSECT ; DO THE READ + + BCC GTA3A ; OK + CLC ; RESET FOR NEXT TIME THRU + PHP ; AND PUSH FOR NEXT TIME THRU + BCC GTA1 ; JMP, ERROR OCCURRED + +; CHANGED TO ABOVE 4 LINES 1/14/86, CARRY MUST BE CLEARED SO READS +; PHP ; SAVE STATUS +; BCS GTA1 ; ERROR IF CARRY WAS SET +; PLP ; ELSE DUMP STATUS + +GTA3A: LDX #$00 + STX DTMP3 + JSR POSTNB + + LDX SLTMP1 ; RESTORE SLOT ID + +DONE: LDA #0 ; 0 = NO ERRORS + CLC ; CARRY CLEAR FOR SUCCESS + BCC EXIT + + ; ERROR EXIT + +DERROR: SEC ; CARRY SET FOR ERROR + + ; GENERAL EXIT + +EXIT: STA DCBERR ; SAVE ERROR CODE HERE + LDA DRVOFF,X ; STOP THE DRIVE + + RTS ; BYE! + + ; WRITE A SECTOR + +DWRITE: JSR WRTDTA + BCC DONE ; ALL'S WELL IF CARRY CLEAR + LDA #$10 ; ELSE GET ERROR CODE INTO [A] + BNE DERROR ; AND DO AN ERROR EXIT + + ; --------------------- + ; SET UP FOR TRACK SEEK + ; --------------------- + +MYSEEK: ASL A ; TRACK*2 (PHASE OF DISK CARE) + JSR DOSEEK + LSR CTRACK ; CURRENT TRACK/2 + RTS + + ; -------------------- + ; GET SLOT ID INTO [Y] + ; -------------------- + +XTOY: TXA + LSR A + LSR A + LSR A + LSR A + TAY + RTS + + ; ------------ + ; SET TRACK ID + ; ------------ + +SETTRK: PHA + LDA DCBDRV + ROR A + ROR DRVFLG + JSR XTOY + PLA + ASL A + BIT DRVFLG + BMI STT1 + STA DR2TBL,Y + BPL STT2 +STT1: STA DR1TBL,Y +STT2: RTS + + + ; CONVERT RAW DATA TO BINARY IN [IOBUFF] + +POSTNB: LDY #0 +PST0: LDX #$56 +PST1: DEX + BMI PST0 + LDA BUFFA,Y + LSR BUFFB,X + ROL A + LSR BUFFB,X + ROL A + STA (DCBBFL),Y + INY + CPY DTMP3 + BNE PST1 + RTS + + ; ----------- + ; IDOS TABLES + ; ----------- + +DR1TBL: DB $00,$00,$00,$00 ; (8 BYTES) + DB $00,$00,$00,$00 + +CTRACK EQU DR1TBL ; CURRENT TRACK + +DR2TBL: DB $00,$00,$00,$00 ; (8 BYTES) + DB $00,$00,$00,$00 + +NSEEK: DB $00 ; SEEK COUNT +DTMP1: DB $00 ; RETRY COUNT +SLTMP1: DB $00 ; SLOT ID +SLTMP2: DB $00 +NRECAL: DB $00 ; RECALIBRATE COUNT + + ; ---------------------- + ; MACHINE INITIALIZATION + ; ---------------------- + +INIT: LDA TXTSET ; SET TEXT MODE + LDA MIXCLR ; SET NO MIX + LDA LOWSCR ; SET PAGE 1 + + LDA #HIGH IOBUFF ; POINT [DCBBFL/H] TO [IOBUFF] + STA DCBBFH + LDA #LOW IOBUFF + STA DCBBFL + + LDA #1 + STA DCBDRV ; SET DRIVE = 1 + STA DCBPDR + + RTS + + END + diff --git a/apple/zip/subs.asm b/apple/zip/subs.asm new file mode 100644 index 0000000..b2fec65 --- /dev/null +++ b/apple/zip/subs.asm @@ -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 + diff --git a/apple/zip/warm.asm b/apple/zip/warm.asm new file mode 100644 index 0000000..dc2bd01 --- /dev/null +++ b/apple/zip/warm.asm @@ -0,0 +1,154 @@ + PAGE + SBTTL "--- WARMSTART ROUTINE ---" + + ; ------------- + ; ZIP WARMSTART + ; ------------- + +WARM1: LDA #10 ;CENTER DISPLAY + STA CV + LDA COL80 + BNE W1 ;80 COL + LDA #8 ;40 COL + STA CH + BNE W2 ;JMP +W1: LDA #27 + STA CH + STA EH +W2: JSR BASCAL + + LDA #HIGH STRYM ;DISP. "THE STORY IS LOADING..." + LDX #LOW STRYM + LDY #STRYML + JSR DLINE + + 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 SCRIPT ; ENABLE SCRIPTING + 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 #1 ; EXCLUDE STATUS LINE FROM REGULAR DISPLAY + STA WTOP + STA LINCNT ; FIX FOR 1ST SCREEN + + LDX WWIDTH ; SET XSIZE TO 1 LESS + DEX + STX XSIZE + + LDA PSTAT ; CHECK IF RESTART & WAS PRINTING + BPL EX2 ; NOPE + LDA ZBEGIN+ZSCRIP+1 ; MAKE IT KEEP PRINTING + ORA #%00000001 + STA ZBEGIN+ZSCRIP+1 + LDA #2 ; RESET PSTAT FOR NEXT TIME + STA PSTAT + +EX2: JSR CLS ; CLEAR SCREEN ... + + ; ... AND FALL INTO MAIN LOOP + + END + diff --git a/apple/zip/warm.g b/apple/zip/warm.g new file mode 100644 index 0000000..3d871d9 --- /dev/null +++ b/apple/zip/warm.g @@ -0,0 +1,202 @@ + PAGE + SBTTL "--- WARMSTART ROUTINE ---" + + ; ------------- + ; ZIP WARMSTART + ; ------------- + +WARM1: LDA #10 ;CENTER DISPLAY + STA CV + LDA COL80 + BNE W1 ;80 COL + LDA #8 ;40 COL + STA CH + BNE W2 ;JMP +W1: LDA #27 + STA CH + STA EH +W2: JSR BASCAL + + LDA #HIGH STRYM ;DISP. "THE STORY IS LOADING..." + LDX #LOW STRYM + LDY #STRYML + JSR DLINE + + LDA #0 ; CLEAR ALL Z-PAGE VARIABLES + LDX #ZEROPG +ST0: STA 0,X + INX + BNE ST0 + + LDX #PG2SIZ +ST3: STA LRU,X ; CLEAR ALL VARIABLES IN PG 2 + DEX + BPL ST3 + +; LDA #0 ; INIT THE PAGING TABLE +; TAX ; = 0 + + LDX #4 ; 4 TIMES THRU = 1K + LDY #0 + LDA #HIGH PTABL + STA I+HI + LDA #LOW PTABL + STA I+LO + + LDA #$FF ; INIT THE PAGING TBL +ST1: STA (I),Y + INY + BNE ST1 + INC I+HI ; NEXT PAGE IN BLOCK + DEX + BNE ST1 + + ; CLEAR THE TIMESTAMP MAP + + LDA #HIGH LRUMAP + STA I+HI + LDA #LOW LRUMAP + STA I+LO + LDX #4 ; = 1K + LDY #0 + TYA ; = 0 +ST2: STA (I),Y + INY + BNE ST2 + INC I+HI + DEX + BNE ST2 + + INC ZSP ; INIT Z-STACK POINTERS + INC OLDZSP ; TO "1" + INC SCRIPT ; ENABLE SCRIPTING + INC STAMP+LO ; 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 + 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+LO ; 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+LO + +; 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 +; + + JSR MEMTOP ; RETURN TOP RAM PG IN [A/Y] + PHA + TYA + SEC + SBC PAGE0+LO + STA PMAX+LO + BEQ CKHIGH ; LESS OR =, CHECK HIGH BYTE + BCC CKHIGH + + PLA + SBC PAGE0+HI + BCC NORAM ; IF HIGH BYTE IS LESS, NOT ENOUGH MEMORY + BCS SETNP ; A-OK + +CKHIGH: PLA + SBC PAGE0+HI + BEQ NORAM ; LO BYTE NOT ENOUGH, IF NOTHING HERE... + BCS SETNP ; OK + + ; *** ERROR #0 -- INSUFFICIENT RAM *** + +NORAM: LDA #0 + JMP ZERROR + +SETNP: STA PMAX+HI ; FINISH SETTING # SWAPPING PAGES + ASL PMAX+LO ; WORD ALIGN VALUE, + ROL PMAX+HI ; ALWAYS USED THAT WAY IN PAGING + + 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 #1 ; EXCLUDE STATUS LINE FROM REGULAR DISPLAY + STA WTOP + STA LINCNT ; FIX FOR 1ST SCREEN + + LDX WWIDTH ; SET XSIZE TO 1 LESS + DEX + STX XSIZE + + LDA PSTAT ; CHECK IF RESTART & WAS PRINTING + BPL EX2 ; NOPE + LDA ZBEGIN+ZSCRIP+1 ; MAKE IT KEEP PRINTING + ORA #%00000001 + STA ZBEGIN+ZSCRIP+1 + LDA #2 ; RESET PSTAT FOR NEXT TIME + STA PSTAT + +EX2: JSR CLS ; CLEAR SCREEN ... + + ; ... AND FALL INTO MAIN LOOP + + END + diff --git a/apple/zip/zdos.h b/apple/zip/zdos.h new file mode 100644 index 0000000..5b008a8 --- /dev/null +++ b/apple/zip/zdos.h @@ -0,0 +1,675 @@ + PAGE + SBTTL "--- Z-DOS: APPLE II ---" + + ; -------------------- + ; READ A VIRTUAL BLOCK + ; -------------------- + + ; ENTRY: V-BLOCK TO READ IN [DBLOCK] + ; BUFFER ADDRESS IN [DBUFF] + ; EXIT: DATA IN [DBUFF] + +GETDSK: LDA DBLOCK+LO ; GET LSB OF BLOCK ID + AND #%00001111 ; MASK OFF TOP NIBBLE + STA DCBSEC ; TO FORM DCBSEC ID (0-15) + + LDA DBLOCK+HI ; GET MSB OF BLOCK ID + AND #%00001111 ; THROW AWAY TOP NIBBLE + ASL A ; AND SHIFT BOTTOM TO TOP + ASL A + ASL A + ASL A + STA DCBTRK ; SAVE HERE FOR A MOMENT + + LDA DBLOCK+LO ; GET LSB + AND #%11110000 ; SCREEN OUT BOTTOM NIBBLE + LSR A ; MOVE TOP TO BOTTOM + LSR A + LSR A + LSR A + ORA DCBTRK ; SUPERIMPOSE TOP OF MSB + CLC ; Z-BLOCKS START ON + CLD + ADC #03 ; FIRST TRACK + CMP #ZTRKL ; ANYTHING ABOVE TRACK 35 + BCS TRKERR + + STA DCBTRK ; THIS IS THE TRACK ID + + ; "RESTORE" ENTRY (W/[DCBSEC/TRK] PRESET) + +GETRES: LDA #0 ; 0 = "READ SECTOR" + JSR DOS + BCS DSKER ; FATAL ERROR IF CARRY SET + + LDY #0 ; MOVE DATA +GDSK1: LDA IOBUFF,Y ; IN [IOBUFF] + STA (DBUFF),Y ; TO [DBUFF] + INY + BNE GDSK1 + + INC DBLOCK+LO ; POINT TO NEXT + BNE NXTSEC ; VIRTUAL BLOCK + INC DBLOCK+HI + + ; POINT TO NEXT SECTOR + +NXTSEC: INC DCBSEC ; UPDATE SECTOR + LDA DCBSEC ; CHECK IT + AND #%00001111 ; DID IT OVERFLOW? + BNE SECTOK ; NO, ALL'S WELL + + LDX DCBTRK ; ELSE UPDATE + INX ; TRACK ID + CPX #ZTRKL ; IF > 35, + BCS WRTERR ; SCRAM W/CARRY SET + STX DCBTRK ; ELSE SAVE NEW TRACK + +SECTOK: STA DCBSEC ; AND SECTOR + INC DBUFF+HI ; POINT TO NEXT RAM PAGE + CLC ; CLEAR CARRY FOR SUCCESS (WRITE ONLY) + RTS + + ; ---------------------- + ; WRITE [DBLOCK] TO DISK + ; ---------------------- + + ; ENTRY: TRACK,SECTOR,DRIVE,SLOT ALL SET ALREADY + ; PAGE TO WRITE IN (DBUFF) + ; EXIT: CARRY CLEAR IF OKAY, SET IF FAILED + +PUTDSK: LDY #0 ; MOVE DATA AT [DBUFF] +PDSK0: LDA (DBUFF),Y ; TO [IOBUFF] + STA IOBUFF,Y ; FOR WRITING + INY + BNE PDSK0 + + LDA #1 ; 1 = "WRITE SECTOR" + JSR DOS ; DO IT! + BCC NXTSEC ; OKAY IF CARRY CLEAR +WRTERR: RTS ; ELSE EXIT WITH CARRY SET + + ; *** ERROR #12: DISK ADDRESS RANGE *** + +TRKERR: LDA #12 + JMP ZERROR + + ; *** ERROR #14: DRIVE ACCESS *** + +DSKER: LDA #14 + JMP ZERROR + + ; ----------------------------- + ; SET UP SAVE & RESTORE SCREENS + ; ----------------------------- + +SAVRES: JSR ZCRLF ; CLEAR THE LINE BUFFER + LDA #0 ; USE FULL SCREEN ! + STA WTOP + JSR HOME ; AND THE SCREEN + + LDA #0 + STA SCRIPT ; DISABLE SCRIPTING + STA CH ;HOME CURSOR + STA EH ;(80 COL) + STA CV + JMP PISSER ;TO ACTUALLY MOVE CURSOR + + ; ----------------- + ; 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 0-7 + 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 0-7" +POSITL EQU $-POSIT + +WDRIV: DB EOL + DB "Drive 1 or 2" +WDRIVL EQU $-WDRIV + +SLOT: DB EOL + DB "Slot 1-7" +SLOTL EQU $-SLOT + +GSLOT: DB 5 ;START W/ DEFAULT SLOT 6 (YES 5 IS 6) + +MIND: DB EOL + DB EOL + DB "Position " +MPOS: DB "*; Drive #" +MDRI: DB "*; Slot " +MSLT: DB "*." + DB EOL + DB "Are you sure? (Y/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 (0-7)" + + ; GET GAME SAVE POSITION + + LDX GPOSIT ; SHOW THE CURRENT + DEX ; ALIGN TO DISPLAY + TXA ; CORRECTLY W/ DODEF + JSR DODEF ; DEFAULT POSITION + +GETPOS: JSR GETKEY ; WAIT FOR A KEY + CMP #EOL ; IF [RETURN], + BEQ POSSET ; USE DEFAULT + SEC + SBC #'0' ; ELSE CONVERT ASCII TO BINARY + CMP #8 ; IF BELOW "8" + 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 #'0' ; CONVERT TO ASCII "0"-"7" + 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 + + ;IF IIC SLOT IS 6 OTHERWISE ASK + + LDA SIG ; CHECK IF IIc + BNE PREIIC ; IS NOT A IIC SO ASK WHICH SLOT + + LDA #5 ; SLOT 6 + BNE SETSLT ; JMP + +PREIIC: LDX #LOW SLOT + LDA #HIGH SLOT + LDY #SLOTL + JSR DLINE ; "SLOT 1-7" + + ; GET DRIVE SLOT + + LDA GSLOT ; SHOW THE CURRENT + + JSR DODEF ; DEFAULT SLOT + +GETSLT: JSR GETKEY ; WAIT FOR A KEY + CMP #EOL ; IF [RETURN], + BEQ SLTSET ; USE DEFAULT + SEC + SBC #'1' ; ELSE CONVERT ASCII TO BINARY + CMP #7 ; IF "7" OR BELOW + BCC SETSLT ; MAKE IT THE NEW DEFAULT +BADSLT: JSR BOOP ; ELSE RAZZ + JMP GETSLT ; AND TRY AGAIN +SLTSET: LDA GSLOT ; USE DEFAULT + +SETSLT: STA TSLOT ; USE KEYPRESS + CLC + ADC #'1' ; CONVERT TO ASCII "1"-"7" + STA MSLT ; STORE IN TEMP STRING + LDX SIG ; AND IF NOT IIC + BEQ DBLCHK + JSR CHAR ; DISPLAY IT + +DBLCHK: LDX #LOW MIND ; SHOW TEMPORARY SETTINGS + LDA #HIGH MIND + LDY #MINDL + JSR DLINE + + ; VALIDATE RESPONSES + +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 DCBDRV ; AND SET [DRIVE] ACCORDINGLY + INC DCBDRV ; 1-ALIGN THE DRIVE ID + + LDX TSLOT ; MAKE TEMP DRIVE SLOT +; STX GSLOT ; DEFAULT + INX ; 1-ALIGN + TXA + ASL A ; * 16 FOR # RWTS NEEDS + ASL A + ASL A + ASL A + STA DCBSLT ; AND SET SLOT ACCORDINGLY + + LDA TPOSIT ; MAKE THE TEMP POSITION +; STA GPOSIT ; THE DEFAULT POSITION + + ; CALC TRACK & SECTOR OF GAME POSITION + ; 64 SECTORS PER SAVE (AS PER OLD ZIP) + ; SO 4 TRACKS AT 16 SECTORS EACH + + ASL A ; *2 + ASL A ; POSITION * 4 + STA DCBTRK ; GIVES THE TRACK + LDA #0 + STA DCBSEC ; SECTOR ALWAYS 0 TO START + + LDX #LOW INSM + LDA #HIGH INSM + LDY #INSML + JSR DLINE ; "INSERT SAVE DISK IN DRIVE X." + + ; FALL THROUGH ... + + ; --------------------- + ; "PRESS RETURN" PROMPT + ; --------------------- + +RETURN: LDX #LOW RTN + LDA #HIGH RTN + LDY #RTNL + JSR DLINE ; SHOW PROMPT + + ; ENTRY FOR QUIT/RESTART + +GETRET: JSR GETKEY ; WAIT FOR [RETURN] + CMP #EOL + BEQ GTRT1 + JSR BOOP ; ACCEPT NO + JMP GETRET ; SUBSTITUTES! + +GTRT1: RTS + +RTN: DB EOL + DB "Press [RETURN] to continue." + DB EOL + DB ">" +RTNL EQU $-RTN + + ; -------------------- + ; PROMPT FOR GAME DISK + ; -------------------- + +GAME: DB EOL + DB "Insert the STORY disk into Drive #1." +GAMEL EQU $-GAME + +SIDE2: LDA DCBDRV ; HOLD LAST DRIVE USED + PHA + LDA STRYDR ; MAKE SURE WE'RE ON + LDX STRYSL ; THE BOOT DRIVE + STA DCBDRV + STX DCBSLT + + PLA ; DID THEY USE DR.2 + CMP #2 + BEQ SIDEX ; YES, DON'T PROMPT + +SIDEL: LDX #LOW GAME + LDA #HIGH GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + + ; COMPARE 2ND PAGE OF INTERPRETER WITH + ; CORRESPONDING SECTOR ON DISK TO + ; VERIFY THAT STORY DISK WAS RE-INSERTED + + LDX #1 ; READ IN TRK 0, SEC 1 + STX DCBSEC ; (PART OF INTERPRETER) + DEX + STX DCBTRK + + TXA ; [0] - READ SECTOR + JSR DOS + BCC CHK1 + JMP DSKER ; OOPS + +CHK1: LDA #HIGH IOBUFF + STA I+HI + LDA #LOW IOBUFF + STA I+LO + LDX #HIGH ZIP + INX ; 2ND PAGE WANTED + STX J+HI + LDA #LOW ZIP + STA J+LO + + LDY #0 ; COMPARE PAGE ON DISK +CHK2: LDA (I),Y ; WITH ONE IN MEMORY + CMP (J),Y + BNE SIDEL ; NO MATCH + INY + BNE CHK2 ; WHEN EQUAL MATCHED OK + +SIDEX: 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: LDA WTOP ; SAVE CURRENT SCREEN TOP + PHA + JSR SAVRES ; SET UP SCREEN + + LDX #LOW SAV + LDA #HIGH SAV + LDY #SAVL + JSR DLINE ; "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 + PLA ; GET CURRENT SCREEN TOP + STA WTOP + 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 + LDA TDRIVE ; OK, SUCCESSFUL, SO + STA GDRIVE ; SAVE PARAMS FOR + LDA TSLOT ; NEXT TIME + STA GSLOT + LDA TPOSIT + STA GPOSIT + + PLA ; GET CURRENT SCREEN TOP + STA WTOP + 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: LDA WTOP ;SAVE CURRENT SCREEN TOP + PHA + JSR SAVRES + + LDX #LOW RES + LDA #HIGH RES + LDY #RESL + JSR DLINE ; "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 GETRES ; 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 + PLA ; RETRIEVE CURRENT SCREEN TOP + STA WTOP + 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 GETRES ; GET 1ST BLOCK OF Z-STACK + BCS WRONG + JSR GETRES ; AND 2ND BLOCK + BCS WRONG + + LDA ZCODE + STA DBUFF+HI + JSR GETRES ; 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 GETRES ; 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 + LDA TDRIVE ; OK, SUCCESSFUL, SO + STA GDRIVE ; SAVE PARAMS FOR + LDA TSLOT ; NEXT TIME + STA GSLOT + LDA TPOSIT + STA GPOSIT + + PLA ; RETRIEVE CURRENT SCREEN TOP + STA WTOP + JSR CLS + JMP PREDS ; PREDICATE SUCCEEDS + + END + diff --git a/apple/zip/zip.l b/apple/zip/zip.l new file mode 100644 index 0000000..17bbd65 --- /dev/null +++ b/apple/zip/zip.l @@ -0,0 +1,84 @@ + TITLE "ZIP/6502 INFOCOM, INC. --- EQUATES" + + ; -------------------------- + ; ZIP/6502 2.0 + ; Z-CODE INTERPRETER PROGRAM + ; FOR APPLE II+/IIE/IIC + ; -------------------------- + + ; INFOCOM, INC. + ; 55 WHEELER STREET + ; CAMBRIDGE, MA 02136 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + + ; CHANGES: + ; + ; VERSION J - FIXED CURSOR ALIGNMENT W/ 80 COL + ; (CH MUST BE SET FOR BASCAL) + ; VERSION K - WILL BOOT WITH PR#6 (1/6/86 Le) + ; ALSO, R/W FLAG SET CORRECTLY IN RWTS + ; VERSION L - FIXED PARAMS IN CHAR RTN SO _ & | WOULD PRINT + +DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER +NEWPR EQU 1 ; ASSEMBLY FLAG FOR PRINT RTN + + ; ----------- + ; 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 (NO LONGER EXISTS 5.2.85 Le) + ; 14 -- DRIVE ACCESS + + INCLUD EQ.ASM + + TITLE "ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT SHELL" + INCLUD HARDEQ.ASM + + INCLUD RWTS.ASM + + INCLUD ZDOS.ASM + INCLUD MACHINE.ASM + INCLUD IO.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 NPAGING.ASM + INCLUD ZSTRING.ASM + INCLUD OBJECTS.ASM + + IF DEBUG + INCLUD BUGGER.ASM + ENDIF + + TITLE "ZIP/6502 INFOCOM, INC." + END + diff --git a/apple/zip/zpaging.asm b/apple/zip/zpaging.asm new file mode 100644 index 0000000..33cec9f --- /dev/null +++ b/apple/zip/zpaging.asm @@ -0,0 +1,568 @@ + PAGE + SBTTL "--- TIME-STAMP PAGING ROUTINE ---" + + ; ------------------------- + ; FETCH NEXT BYTE OF Z-CODE + ; ------------------------- + + ; EXIT: BYTE AT [ZPC] IN [A] & [Y]; FLAGS SET + ; EXPANDED TO USE ALL AVAILABLE MEMORY + ; ASSUMPTION: PAGING STARTS IN LOW MAIN MEMORY + +NEXTPC: LDA ZPCFLG ; IS [ZPCPNT] VALID? + BEQ NPC0 ; NO, GO GET NEW Z-PAGE + + ;SAME PAGE + + LDA ZPNTH ; CHECK ABS ADDR TO SEE IF AUX OR MAIN RAM + BEQ NPC4 ; MAIN + LDA ZPNTM ; SET UP FOR AUX READ + LDY ZPCL ; ABS PAGE AND BYTE OFFSET + JMP NPC2 + + ; Z-PAGE HAS CHANGED! + +NPC0: LDA ZPCM ; GET TOP + LDY ZPCH ; 9 BITS OF [ZPC] + + CPY ZPURE+HI ; CHECK IF BELOW PAGING + BCC NPC3 ; YES + BEQ NPC1 ; MAYBE, CHECK LOW + BCS NPCPG ; ABOVE, PAGE IT IN +NPC1: CMP ZPURE+LO + BCC NPC3 ; BELOW +NPCPG: LDX #0 ; INVALIDATE MPC FLAG + STX MPCFLG + JSR PAGE ; ABOVE, GET PAGE INTO Y/A + + STA ZPNTM ; SAVE POINTER + STY ZPNTH + LDY #$FF ; VALIDATE [ZPCPNT] + STY ZPCFLG + INY ; = 0 + STY ZPNTL ; 1ST BYTE ON A NEW PAGE + LDY ZPNTH ; IF CLEAR + BEQ NPC4 ; PAGE IS IN MAIN MEMORY + LDY ZPCL ; GET BYTE WANTED NOW FROM AUX MEM +NPC2: JSR BUFBYT ; GET [Y] BYTE IN BUFFER [A] INTO [A] + JMP NPC5 ; GOT IT + +NPC3: CLC ; MAKE PAGE ABSOLUTE + ADC ZCODE ; BY ADDING IT TO START OF GAME SPACE + STA ZPNTM ; SAVE HERE FOR USE + LDX #$FF + STX ZPCFLG ; VALIDATE [ZPCPNT] + INX ; = 0 + STX ZPNTL ; CLEAR LSB OF POINTER + STX ZPNTH ; AND MSB, MAIN MEMORY + +; JSR ALIGN ; GET ABS ADDR. (Y/A = ZPCH/ZPCM) +; BCS NPC2 ; AUX MEM. + + ; ELSE DROP THRU TO MAIN MEM RTN + +NPC4: LDY ZPCL ; FETCH PAGE INDEX + LDA ZPNTM ; CHECK IF LOW OR HIGH MEMORY + CMP #$C0 + BCC NPC7 ; LOW + JSR HIBYT ; HIGH + JMP NPC5 +NPC7: LDA (ZPCPNT),Y ; GET Z-BYTE (FROM MAIN MEMORY) + +NPC5: INC ZPCL ; END OF PAGE YET? + BNE NPC6 ; NO, EXIT + + LDY #0 + STY ZPCFLG ; ELSE INVALIDATE [ZPCPNT] + + INC ZPCM ; POINT [ZPC] TO + BNE NPC6 ; THE NEXT + INC ZPCH ; Z-PAGE + +NPC6: TAY ; SET FLAGS + RTS ; AND RETURN + + ; ------------------------------- + ; GET NEXT BYTE OF VIRTUAL MEMORY + ; ------------------------------- + + ; EXIT: BYTE AT [MPC] IN [A] & [Y]; FLAGS SET + ; (ALL DIFFERENT FOR EXPANDED MEMORY USE - TAKEN FROM EZIP) + +GETBYT: LDA MPCFLG ; IS [ZPCPNT] VALID? + BEQ GTBT0 ; NO, GO GET NEW Z-PAGE + + LDA MPNTH ; CHECK IF AUX OR MAIN RAM + BEQ GTBT4 ; MAIN + LDA MPNTM ; SET UP FOR AUX READ + LDY MPCL + JMP GTBT2 + + ; Z-PAGE HAS CHANGED! + +GTBT0: LDA MPCM ; GET TOP + LDY MPCH ; 9 BITS OF [MPC] + +PATCH1: EQU $+1 ; PATCH POINT FOR "VERIFY" + + CPY ZPURE+HI ; CHECK IF BELOW PAGING + BCC GTBT3 ; YES + BEQ GTBT1 ; MAYBE, CHECK LOW + BCS GETPG ; ABOVE, PAGE IT IN + +PATCH2: EQU $+1 ; PATCH POINT FOR "VERIFY" + +GTBT1 CMP ZPURE+LO + BCC GTBT3 ; BELOW +GETPG: LDX #0 + STX ZPCFLG + JSR PAGE ; ABOVE, GET PAGE INTO Y/A + + STA MPNTM ; SAVE POINTER + STY MPNTH + LDY #$FF ; VALIDATE [MPCPNT] + STY MPCFLG + INY ; = 0 + STY MPNTL ; 1ST BYTE ON A NEW PAGE + LDY MPNTH ; IF CLEAR + BEQ GTBT4 ; PAGE IS IN MAIN MEMORY + LDY MPCL ; BYTE WE WANT +GTBT2: JSR BUFBYT ; GET [Y] BYTE IN BUFFER [A] INTO [A] + JMP GTBT5 ; GOT IT + +GTBT3: CLC ; MAKE PAGE ABSOLUTE + ADC ZCODE ; BY ADDING IT TO START OF GAME SPACE + STA MPNTM ; SAVE HERE FOR USE + LDX #$FF + STX MPCFLG ; VALIDATE [MPCPNT] + INX ; = 0 + STX MPNTL ; CLEAR LSB OF POINTER + STX MPNTH ; MARK AS MAIN MEMORY + +; JSR ALIGNM ; GET ABS ADDR. (Y/A = ZPCH/ZPCM) +; BCS GTBT2 ; AUX MEM. + + ; ELSE DROP THRU TO MAIN MEM RTN + +GTBT4: LDY MPCL ; FETCH PAGE INDEX + LDA MPNTM ; CHECK IF LOW OR HIGH MEM + CMP #$C0 + BCC GTBT7 ; LOW + JSR HIBYT ; HIGH + JMP GTBT5 +GTBT7: LDA (MPCPNT),Y ; GET Z-BYTE (FROM MAIN MEMORY) + +GTBT5: INC MPCL ; END OF PAGE YET? + BNE GTBT6 ; NO, EXIT + + LDY #0 + STY MPCFLG ; ELSE INVALIDATE [MPCPNT] + + INC MPCM ; POINT [MPC] TO + BNE GTBT6 ; THE NEXT + INC MPCH ; Z-PAGE + +GTBT6: 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] + ; DIFF FOR EXPANDED MEMORY USE + +PAGE: STA TARGET+LO ; SAVE THE + STY TARGET+HI ; TARGET Z-PAGE HERE + + ; IS THIS Z-PAGE ALREADY PAGED IN? + + LDA PMAX+LO + STA ZPAGE+LO ; MOVE PMAX IN FOR COUNT + STA PR1+LO + LDA PMAX+HI + STA ZPAGE+HI + STA PR1+HI + + LDA PR1+LO ; ADD TO PAGTBL ADDR +; SEC ; PMAX ACTUALLY 1 GREATER THAN MAX +; SBC #2 ; SO COME DOWN TO REAL LAST ENTRY +; BCS PG13 +; DEC PR1+HI +PG13: CLC + ADC #LOW PTABL + STA PR1+LO + LDA PR1+HI + ADC #HIGH PTABL + STA PR1+HI ; SO PR1 = TOP OF PGING SPACE + +; LDX #HI + LDY #0 + +PG1: LDA TARGET+LO ; CHECK IF TARGET PAGE + CMP (PR1),Y ; ALREADY IN RESIDENCE + BNE PG2 ; NO + LDA TARGET+HI ; CHECK HIGH BYTE + INY + CMP (PR1),Y + BEQ PG4 ; ALREADY THERE + DEY ; RESET FOR NEXT COMPARE +PG2: LDA PR1+LO ; MOVE DOWN TO NEXT ENTRY + SEC + SBC #2 + STA PR1+LO + BCS PG3 + DEC PR1+HI +PG3: LDA ZPAGE+LO ; DECREMENT COUNTER + SEC + SBC #2 + STA ZPAGE+LO + BEQ PG12 + BCS PG1 ; NOT DONE YET +PG12: DEC ZPAGE+HI + BPL PG1 ; KEEP LOOKING + + +; 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 ; MSB +; BEQ PG5 ; 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 + + JSR EARLY ; GET EARLIEST PAGE + LDA SWAP+LO ; INTO [SWAP] + STA ZPAGE+LO ; SAVE FOR LATER + CLC + ADC #LOW PTABL ; ALIGN AT EARLIEST BUFFER + STA PR1+LO + LDA SWAP+HI + STA ZPAGE+HI + ADC #HIGH PTABL + STA PR1+HI + LDY #LO ; PLACE PAGE IN BUFFER + LDA TARGET+LO + STA (PR1),Y + STA DBLOCK+LO ; AND GIVE IT TO ZDOS + LDY #HI + LDA TARGET+HI + STA (PR1),Y + STA DBLOCK+HI + +; 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 #%00000011 ; USE ONLY BIT 0 (& 1 - EZIP) +; STA PTABH,X +; STA DBLOCK+HI + + JSR GETBUF ; GET BUFFER FROM DISK INTO CORRECT PAGE + BCC PG4 ; OK + JMP DKERR ; OOPS + + ; UPDATE THE TIMESTAMP + +PG4: LDA ZPAGE+LO ; ADD BUFFER INDEX TO LRUMAP + CLC + ADC #LOW LRUMAP + STA PR1+LO + LDA ZPAGE+HI + ADC #HIGH LRUMAP + STA PR1+HI + LDY #LO ; CHECK IF SAME AS + LDA (PR1),Y ; CURRENT STAMP + CMP STAMP+LO + BNE PG5 ; NO, GO GET THIS PG A NEW STAMP + LDY #HI + LDA (PR1),Y + CMP STAMP+HI + BEQ PG11 ; YES, EXIT + +PG5: INC STAMP+LO ; UPDATE STAMP + BNE PG10 ; CONTINUE IF NO OVERFLOW + LDA STAMP+HI + BNE PG6 ; HANDLE OVERFLOW + INC STAMP+HI ; SET FOR 2ND 256 STAMPS + JMP PG10 ; (512 IN ALL) + +;PG5: 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 + +PG6: JSR EARLY2 ; GET EARLIEST STAMP INTO [LRU] + + LDA #LOW LRUMAP ; SET PR2 TO LRUMAP SO + STA PR2+LO ; CAN HANDLE WHOLE 1K EASILY + LDA #HIGH LRUMAP + STA PR2+HI +; LDX #HI + +PG7: LDY #0 ; LOW BYTE + LDA (PR2),Y + INY ; HIGH BYTE + ORA (PR2),Y + BEQ PG8 ; SKIP IT IF ALREADY ZERO + DEY ; RESET + + LDA (PR2),Y ; ELSE SUBTRACT OFF + SEC + SBC LRU+LO ; THE EARLIEST TIMESTAMP + STA (PR2),Y ; AND REPLACE THE STAMP + INY ; HI BYTE + LDA (PR2),Y ; (AND THE HIGH BYTE) + SBC LRU+HI + STA (PR2),Y + DEY ; RESET FOR NEXT ENTRY +PG8: CLC ; INC PR2 TO NEXT ENTRY + LDA PR2+LO + ADC #2 + STA PR2+LO + BCC PG9 + INC PR2+HI +PG9: LDA PR2+HI ; GET OFFSET TO WHERE WE ARE + SEC + SBC #HIGH LRUMAP + CMP PMAX+HI ; HAVE WE CHECKED ALL THE ENTRIES? + BCC PG7 ; NO, KEEP LOOKING + LDA PR2+LO ; CHECK LOW BYTE + SBC #LOW LRUMAP + CMP PMAX+LO + BCC PG7 ; LESS, KEEP LOOKING + +; LDX #0 ; INIT INDEX +;PG9: 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 PG9 ; LOOP TILL ALL STAMPS FIXED + + LDA LRU+HI ; TURN BACK THE CLOCK + EOR #$FF ; TO REFLECT NEW + STA LRU+HI ; STAMP READING + LDA LRU+LO + EOR #$FF + STA LRU+LO + INC LRU+LO + +; LDA #0 ; TURN BACK THE CLOCK +; SEC ; TO REFLECT NEW +; SBC LRU ; STAMP READING +; STA STAMP + +PG10: LDY #LO ; STAMP TARGET PAGE + LDA STAMP+LO ; WITH NEW STAMP + STA (PR1),Y ; [PR1] STILL SET AT PROPER LOCATION + LDY #HI + LDA STAMP+HI + STA (PR1),Y + +;PG7: LDA STAMP ; FETCH STAMP +; STA LRUMAP,Y ; STAMP TARGET PAGE WITH IT + +PG11: LSR ZPAGE+HI ; DIVIDE BY 2 + ROR ZPAGE+LO ; WORD ALIGNED + LDA ZPAGE+LO ; GET ABS.PAGE + CLC + ADC PAGE0+LO ; (PAGE # + 1ST PG) + PHA + LDA ZPAGE+HI + ADC PAGE0+HI ; PICK UP CARRY + TAY + PLA + RTS ; Y/A (HI/LO) = PAGE TO USE + +;PG8: LDA ZPAGE ; GET ABS. PAGE (EZIP) +; CLC +; ADC PAGE0 ; (PAGE # + 1ST PAGE) +; LDY #1 ; MARK IT AUX MEMORY +; RTS ; AND RETURN IT IN [A] AND [Y] + + ; *** ERROR #14: DRIVE ACCESS *** + +DKERR: LDA #14 + JMP ZERROR + + ; ------------------------- + ; LOCATE EARLIEST TIMESTAMP + ; ------------------------- + + ; EXIT: [LRU] - EARLIEST TIMESTAMP + ; [SWAP] = WORD ALIGNED INDEX TO EARLIEST BUFFER + +EARLY: LDA #LOW LRUMAP ; SET PR3 & PR2 TO LRUMAP + STA PR3+LO + CLC + ADC #2 ; MOVE PR2 TO NEXT ENTRY + STA PR2+LO + LDA #HIGH LRUMAP + STA PR3+HI + ADC #0 ; PICK UP CARRY IF ANY + STA PR2+HI + + LDY #1 ; Y TO HIGH + +EAR0: LDA (PR3),Y ; CHECK IF PR2 LOCATION + CMP (PR2),Y ; IS EARLIER THAN PR3 + BCC EAR1 ; NO + BNE EAR3 ; GREATER + DEY + LDA (PR3),Y ; EQUAL, CHECK LOW BYTE + CMP (PR2),Y + INY ; RESET FOR NEXT ENTRY + BCC EAR1 ; NO, NOT EARLIER + +EAR3: LDA PR2+LO ; YES, PICK UP EARLIER + STA PR3+LO + LDA PR2+HI + STA PR3+HI + +EAR1: CLC ; INC PR2 TO NEXT ENTRY + LDA PR2+LO + ADC #2 + STA PR2+LO + BCC EAR2 + INC PR2+HI +EAR2: LDA PR2+HI ; GET OFFSET TO WHERE WE ARE + SEC + SBC #HIGH LRUMAP + CMP PMAX+HI ; HAVE WE CHECKED ALL THE ENTRIES? + BCC EAR0 ; NO, KEEP LOOKING + LDA PR2+LO ; CHECK LOW BYTE + SBC #LOW LRUMAP + CMP PMAX+LO + BCC EAR0 ; LESS, KEEP LOOKING + + LDA PR3+LO ; GET INDEX OF PG TO USE + SEC + SBC #LOW LRUMAP + STA SWAP+LO ; SAVE IT IN SWAP FOR LATER + LDA PR3+HI + SBC #HIGH LRUMAP + STA SWAP+HI + LDA (PR3),Y ; GET LRU # TO USE + STA LRU+HI + DEY + LDA (PR3),Y + STA LRU+LO + RTS + + ; THIS IS FOR OVERFLOW, IGNORES 0 ENTRIES + +EARLY2: LDA #LOW LRUMAP ; SET PR3 & PR2 TO LRUMAP + STA PR3+LO + CLC + ADC #2 ; MOVE PR2 TO NEXT ENTRY + STA PR2+LO + LDA #HIGH LRUMAP + STA PR3+HI + ADC #0 ; PICK UP CARRY IF ANY + STA PR2+HI + +EAR20: LDY #0 + LDA (PR3),Y ; CHECK IF PR2 LOCATION + INY + ORA (PR3),Y ; IS VALUE 0 + BEQ EAR23 ; YES, SO PICK THE OTHER + + LDA (PR3),Y + CMP (PR2),Y ; IS EARLIER THAN PR3 + BCC EAR21 ; NO + BNE EAR23 ; GREATER + DEY + LDA (PR3),Y ; EQUAL, CHECK LOW BYTE + CMP (PR2),Y + BCC EAR21 ; NO, NOT EARLIER + INY + +EAR23: LDA (PR2),Y ; MAKE SURE PR2 ISN'T 0 + DEY + ORA (PR2),Y + BEQ EAR21 ; DON'T USE 0 ENTRY + + LDA PR2+LO ; PR2 EARLIER, PICK IT UP + STA PR3+LO + LDA PR2+HI + STA PR3+HI + +EAR21: CLC ; INC PR2 TO NEXT ENTRY + LDA PR2+LO + ADC #2 + STA PR2+LO + BCC EAR22 + INC PR2+HI +EAR22: LDA PR2+HI ; GET OFFSET TO WHERE WE ARE + SEC + SBC #HIGH LRUMAP + CMP PMAX+HI ; HAVE WE CHECKED ALL THE ENTRIES? + BCC EAR20 ; NO, KEEP LOOKING + LDA PR2+LO ; CHECK LOW BYTE + SBC #LOW LRUMAP + CMP PMAX+LO + BCC EAR20 ; LESS, KEEP LOOKING + + LDA PR3+LO ; GET INDEX OF PG TO USE + SEC + SBC #LOW LRUMAP + STA SWAP+LO ; SAVE IT IN SWAP FOR LATER + LDA PR3+HI + SBC #HIGH LRUMAP + STA SWAP+HI + LDY #1 + LDA (PR3),Y ; GET LRU # TO USE + STA LRU+HI + DEY + LDA (PR3),Y + STA LRU+LO + 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 + + \ No newline at end of file diff --git a/apple/zip/zstring.asm b/apple/zip/zstring.asm new file mode 100644 index 0000000..6045eb9 --- /dev/null +++ b/apple/zip/zstring.asm @@ -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 + diff --git a/atari/atari-d.zip b/atari/atari-d.zip new file mode 100644 index 0000000..aff20e2 Binary files /dev/null and b/atari/atari-d.zip differ diff --git a/atari/atari-grip.bin b/atari/atari-grip.bin new file mode 100644 index 0000000..c73f0cc Binary files /dev/null and b/atari/atari-grip.bin differ diff --git a/atari/atari-grip.prn b/atari/atari-grip.prn new file mode 100644 index 0000000..09e8461 --- /dev/null +++ b/atari/atari-grip.prn @@ -0,0 +1,6289 @@ + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 1 + + + + 0000 ; ---------------------------- + 0000 ; GRIP/6502 1.0 + 0000 ; G-CODE INTERPRETER PROGRAM + 0000 ; FOR ATARI 400/800/1200/XL + 0000 ; ---------------------------- + + 0000 ; INFOCOM, INC. + 0000 ; 55 WHEELER STREET + 0000 ; CAMBRIDGE, MA 02138 + + 0000 ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + + 0000 ; ------------------------- + 0000 ; MEMORY ALLOCATION EQUATES + 0000 ; ------------------------- + + 0000 ; THESE MUST BE DEFINED FOR EACH MACHINE + + ;ZSTART EQU $80 ; FIRST FREE ZERO-PAGE LOCATION + + ;*** + ;ZSTART EQU $7E ; FIRST FREE ZERO-PAGE LOCATION + ;*** + + ;*** + 006B ZSTART EQU $6B ; FIRST FREE ZERO-PAGE LOCATION + ;*** + + 00FF ZEND EQU $FF ; LAST FREE ZERO-PAGE LOCATION + 0400 MSTART EQU $0400 ; FIRST FREE RAM LOCATION + + 0000 DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER + + 0000 ; ----------- + 0000 ; ERROR CODES + 0000 ; ----------- + + 0000 ; 00 -- GAME PRELOAD TOO BIG + 0000 ; 01 -- IMAGE PRELOAD TOO BIG + 0000 ; 02 -- UNDEFINED X-OP + 0000 ; 03 -- UNDEFINED 0-OP + 0000 ; 04 -- UNDEFINED 1-OP + 0000 ; 05 -- UNDEFINED 2-OP + 0000 ; 06 -- G-STACK UNDERFLOW + 0000 ; 07 -- G-STACK OVERFLOW + 0000 ; 08 -- DIVISION BY ZERO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 2 + + + 0000 ; 09 -- PURITY VIOLATION (PUT/PUTB/ITER) + 0000 ; 0A -- DISK ADDRESS RANGE + 0000 ; 0B -- DISK ACCESS + 0000 ; 0C -- NO CALL ADDRESS + 0000 ; 0D -- UNDEFINED SOUND + 0000 ; 0E -- PURITY VIOLATION (SETI/SWAPI) + + 0000 ; ---------------- + 0000 ; BATCH PROCESSING + 0000 ; ---------------- + + INCLUD EQ.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 3 +--- SOFTWARE EQUATES --- + + + 0000 ; ------------------- + 0000 ; MEMORY ORGANIZATION + 0000 ; ------------------- + + 0400 BUFFER EQU MSTART ; 256-BYTE DISK BUFFER + 0500 GSTAKL EQU MSTART+$100 ; G-STACK LSBS + 0600 GSTAKH EQU MSTART+$200 ; G-STACK MSBS + 0700 MEMMAP EQU MSTART+$300 ; ABSOLUTE MEMORY MAP + 0800 PAGMAP EQU MSTART+$400 ; PAGING BUFFER MAP (128 BYTES) + 0880 LRUMAP EQU MSTART+$480 ; LRU MAP (128 BYTES) + 0900 VLOWS EQU MSTART+$500 ; LSB PLOT TABLE (192 BYTES) + 09C0 VHIGHS EQU VLOWS+$C0 ; MSB PLOT TABLE (192 BYTES) + 0A80 LOCALS EQU VLOWS+$180 ; LOCAL VARIABLE STORAGE (32 BYTES) + 0AA0 CARGS EQU LOCALS+$20 ; CALL ARGUMENT STORAGE (32 BYTES) + 0AC0 CTYPES EQU CARGS+$20 ; CALL ARGUMENT LIST (16 BYTES) + 0B00 GRIP EQU MSTART+$700 ; BEGINNING OF GRIP CODE + 2300 GBEGIN EQU GRIP+$1800 ; START OF PRELOAD + + 0000 ; ----------------- + 0000 ; PROGRAM CONSTANTS + 0000 ; ----------------- + + 0000 FALSE EQU 0 + 00FF TRUE EQU $FF + 0000 LO EQU 0 + 0001 HI EQU 1 + 0042 INTRP EQU 'B' ; INTERPRETER VERSION # + + 0000 ; --------------------- + 0000 ; G-CODE HEADER OFFSETS + 0000 ; --------------------- + + 0000 GVERS EQU 0 ; (BYTE) G-MACHINE VERSION ("1") + 0001 GMODE EQU 1 ; (BYTE) MODE BYTE + 0002 GID EQU 2 ; (WORD) GAME ID + 0004 GEND EQU 4 ; (WORD) END OF G-PRELOAD + 0006 GSTART EQU 6 ; (WORD) EXECUTION START ADDRESS + 0008 GPUR EQU 8 ; (WORD) START OF PURE G-CODE + 000A GGLOB EQU 10 ; (WORD) START OF GLOBAL VARIABLE TABLE + 000C GSER EQU 12 ; (6 BYTES) ASCII SERIAL NUMBER + 0012 GLEN EQU 18 ; (WORD) LENGTH OF G-PROGRAM IN BYTES + 0014 GCHECK EQU 20 ; (WORD) G-CODE CHECKSUM + 0016 IVERS EQU 22 ; (WORD) INTERPRETER VERSION + + 0000 ; --------------------- + 0000 ; I-FILE HEADER OFFSETS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 4 +--- SOFTWARE EQUATES --- + + 0000 ; --------------------- + + 0000 ILEN EQU 0 ; (WORD) I-FILE LENGTH IN BYTES + 0002 IEND EQU 2 ; (WORD) END OF I-FILE PRELOAD + 0004 ICHECK EQU 4 ; (WORD) I-FILE CHECKSUM WORD + 0006 IBLKS EQU 6 ; (BYTE) # BLOCKSETS IN FILE + 0007 IICONS EQU 7 ; (BYTE) # ICONS IN FILE + + 0000 ; ------------------- + 0000 ; ZERO-PAGE VARIABLES + 0000 ; ------------------- + + 006B OPCODE EQU ZSTART ; (BYTE) CURRENT OPCODE + 006C NARGS EQU OPCODE+1 ; (BYTE) CURRENT # ARGUMENTS + 006D ARG1 EQU OPCODE+2 ; (WORD) ARGUMENT 1 REGISTER + 006F ARG2 EQU OPCODE+4 ; (WORD) ARGUMENT 2 REGISTER + 0071 ARG3 EQU OPCODE+6 ; (WORD) ARGUMENT 3 REGISTER + 0073 ARG4 EQU OPCODE+8 ; (WORD) ARGUMENT 4 REGISTER + 0075 ABYTE EQU OPCODE+10 ; (BYTE) X-OP ARGUMENT BYTE + 0076 ADEX EQU OPCODE+11 ; (BYTE) X-OP ARGUMENT INDEX + 0077 ADEX2 EQU OPCODE+12 ; (BYTE) "CALL" ARG-BYTE INDEX + + 0078 VALUE EQU OPCODE+13 ; (WORD) VALUE RETURN REGISTER + 007A I EQU VALUE+2 ; (WORD) GENERAL INDEX REGISTER #1 + 007C J EQU VALUE+4 ; (WORD) GENERAL INDEX REGISTER #2 + 007E K EQU VALUE+6 ; (WORD) " " " #3 + + 0080 GPC EQU VALUE+8 ; (WORD) G-CODE PROGRAM COUNTER + 0080 GPCL EQU GPC ; (BYTE) LSB OF GPC + 0081 GPCH EQU GPC+1 ; (BYTE) MSB OF GPC + + ;*** + 0082 GPC0: EQU GPC+2 ; (BYTE) BIT 0 OF BYTE IS BIT 0 OF GPC + ;*** + + 0083 GPCFLG EQU GPC+3 ; (BYTE) GPC VALIDITY FLAG + 0084 GPOINT EQU GPC+4 ; (WORD) ABSOLUTE G-MEMORY POINTER + + 0086 VPC EQU GPC+6 ; (WORD) VIRTUAL MEMORY POINTER + 0086 VPCL EQU VPC ; (BYTE) LSB OF VPC + 0087 VPCH EQU VPC+1 ; (BYTE) MSB OF VPC + + ;*** + 0088 VPC0 EQU VPC+2 ; (BYTE) LEAST SIG BIT OF VPC + ;*** + + 0089 VPCFLG EQU VPC+3 ; (BYTE) VPC VALIDITY FLAG + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 5 +--- SOFTWARE EQUATES --- + + 008A VPOINT EQU VPC+4 ; (WORD) ABSOLUTE V-MEMORY POINTER + 008C VPCSAV EQU VPC+6 ; (WORD) [VPC] SAVE REGISTER + + 008E GSP EQU VPC+8 ; (BYTE) G-STACK POINTER + 008F OLDGSP EQU GSP+1 ; (BYTE) OLD G-STACK POINTER + + 0090 GCODE EQU GSP+2 ; (BYTE) ABS 1ST PAGE OF G-PRELOAD + 0091 ICODE EQU GCODE+1 ; (WORD) ABS START ADDR OF I-PRELOAD + + 0093 GPURE EQU GCODE+3 ; (BYTE) 1ST V-PAGE OF "PURE" G-CODE + 0094 ISTART EQU GPURE+1 ; (BYTE) 1ST V-PAGE OF I-FILE + 0095 IPURE EQU GPURE+2 ; (BYTE) 1ST V-PAGE OF "PURE" I-FILE + + 0096 PAGE0 EQU GPURE+3 ; (BYTE) ABS 1ST PAGE OF PAGING SPACE + 0097 PMAX EQU PAGE0+1 ; (BYTE) MAXIMUM # SWAPPING PAGES + 0098 STAMP EQU PAGE0+2 ; (BYTE) LRU TIMESTAMP + 0099 LRU EQU PAGE0+3 ; (BYTE) EARLIEST TIMESTAMP + 009A SWAP EQU PAGE0+4 ; (BYTE) LRU SWAPPING PAGE + 009B TARGET EQU PAGE0+5 ; (BYTE) TARGET BUFFER ADDRESS + + 009C GLOBAL EQU PAGE0+6 ; (WORD) ABSOLUTE GLOBAL TABLE ADDR + 009E BTAB EQU GLOBAL+2 ; (WORD) ABSOLUTE BLOCKSET TABLE ADDR + 00A0 ITAB EQU GLOBAL+4 ; (WORD) ABSOLUTE ICON TABLE ADDR + 00A2 NBLOKS EQU GLOBAL+6 ; (BYTE) # BLOCKSETS IN I-FILE + 00A3 NICONS EQU GLOBAL+7 ; (BYTE) # ICONS IN I-FILE + + 00A4 QUOT EQU GLOBAL+8 ; (WORD) QUOTIENT REGISTER + 00A6 REMAIN EQU QUOT+2 ; (WORD) REMAINDER REGISTER + 00A8 MTEMP EQU QUOT+4 ; (WORD) TEMP MATH REGISTER + 00AA QSIGN EQU QUOT+6 ; (BYTE) SIGN OF QUOTIENT + 00AB RSIGN EQU QUOT+7 ; (BYTE) SIGN OF REMAINDER + 00AC MUSHFT EQU QUOT+8 ; (BYTE) MULTIPLY TEMP FOR BLOCKS + 00AD MUL EQU QUOT+9 ; (BYTE) DITTO + 00AE MUH EQU QUOT+10 ; (BYTE) DITTO + + 00AF IADR1 EQU QUOT+11 ; (WORD) ABS ADDR OF ICON #1 + + ;*** + 00B1 IADR10 EQU IADR1+2 ; (BYTE) SAME IDEA AS VPC0 + ;*** + + 00B2 IADR2 EQU IADR1+3 ; (WORD) ABS ADDR OF ICON #2 + + ;*** + 00B4 IADR20 EQU IADR1+5 ; (BYTE) SAME IDEA AS VPC0 + ;*** + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 6 +--- SOFTWARE EQUATES --- + + 00B5 IX1 EQU IADR1+6 ; (BYTE) X-SIZE OF ICON #1 + 00B6 IX2 EQU IADR1+7 ; (BYTE) X-SIZE OF ICON #2 + 00B7 IY1 EQU IADR1+8 ; (BYTE) Y-SIZE OF ICON #1 + 00B8 IY2 EQU IADR1+9 ; (BYTE) Y-SIZE OF ICON #2 + 00B9 XDEX1 EQU IADR1+10 ; (BYTE) X-INDEX #1 + 00BA XDEX2 EQU IADR1+11 ; (BYTE) X-INDEX #2 + 00BB YDEX1 EQU IADR1+12 ; (BYTE) Y-INDEX #1 + 00BC YDEX2 EQU IADR1+13 ; (BYTE) Y-INDEX #2 + 00BD ITERS EQU IADR1+14 ; (BYTE) # ICON ITERATIONS + 00BE ITICN EQU IADR1+15 ; (BYTE) COUNTER FOR ITERATE ROUTINE + 00BF ITPNT EQU IADR1+16 ; (BYTE) COUTNER FOR ITERATE ROUTINE + 00C0 XPOS EQU IADR1+17 ; (WORD) ICON X-POSITION + 00C2 YPOS EQU IADR1+19 ; (WORD) ICON Y-POSITION + 00C4 TOPCUT EQU IADR1+21 ; (BYTE) TEMP FOR AMOUNT TO CUT OFF TOP IN SET + 0000 ; UP ROUTINE OF SHOWI + 00C5 SIDCUT EQU IADR1+22 ; (BYTE) SAME AS TOPCUT FOR SIDE + 00C6 IXSKIP EQU IADR1+23 ; (BYTE) AMOUNT TO ADD TO IADR1 TO GET NEXT + 0000 ; BLOCK AT NEXT ROW + 00C7 MDXCUT EQU IADR1+24 ; (BYTE) IF YOU DON'T UNDERSTAND, OH WELL. + + ;MDYCUT EQU IADR1+25 ; (BYTE) NOT SHURE THIS IS USED IN FINAL + + 00C9 WINDX1 EQU IADR1+26 ; (BYTE) LEFT CLIP VALUE + 00CA WINDY1 EQU WINDX1+1 ; (BYTE) RIGHT CLIP VALUE + 00CB WINDX2 EQU WINDX1+2 ; (BYTE) TOP CLIP VALUE + 00CC WINDY2 EQU WINDX1+3 ; (BYTE) BOTTOM CLIP VALUE + 00CD WINDH EQU WINDX1+4 ; (BYTE) HEIGHT OF WINDOW (WINDY2-WINDY1) + 00CE WINDW EQU WINDX1+5 ; (BYTE) WIDTH OF WINDOW (WINDX2-WINDX1) + + 00CF BSET EQU WINDX1+6 ; (BYTE) CURRENT BLOCKSET ID + 00D0 BSADR EQU BSET+1 ; (WORD) ABS ADDR OF CURRENT BLOCKSET + 00D2 BSIZE EQU BSET+3 ; (BYTE) # BLOCKS IN CURRENT BLOCKSET + 00D3 BLOCK EQU BSET+4 ; (8 BYTES) IMAGE BLOCK BUFFER + 00DB MASK EQU BSET+12 ; (8 BYTES) IMAGE MASK BUFFER + 00E3 MSKFLG EQU BSET+20 ; (BYTE) FLAG FOR MASKING 00=DISABLED + 00E4 TOX EQU BSET+21 ; (BYTE) X-SAVE FOR "DUMP" + 00E5 XPSAV EQU BSET+22 ; (WORD) X-POSITION SAVE + 00E7 XCURS EQU BSET+24 ; (BYTE) GAME CURSOR X-POS + 00E8 YCURS EQU BSET+25 ; (BYTE) GAME CURSOR Y-POS + 00E9 NEGATE EQU BSET+26 ; (BYTE) BLOCK NEGATE FLAG + 00EA BLKLEN EQU BSET+27 ; (BYTE) # BYTES PER BLOCK + + 00EB DBLOCK EQU BSET+28 ; (BYTE) G-CODE BLOCK TO ACCESS + 00EC DBTOP EQU DBLOCK+1 ; (BYTE) MSB HOLDER FOR "GETDSK" + 00ED DBUFF EQU DBLOCK+2 ; (WORD) DISK BUFFER PAGE POINTER + 00EF SECTOR EQU DBLOCK+4 ; (WORD) SECTOR ADDRESS + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 7 +--- SOFTWARE EQUATES --- + + ;*** + 00F1 DCNT EQU DBLOCK+6 ; (BYTE) COUNTER FOR GROS + ;*** + + 00F2 LINE EQU DBLOCK+7 ; (WORD) TEXT LINE ADDRESS + 00F4 LEN EQU LINE+2 ; (BYTE) TEXT LINE LENGTH + 00F5 CURSOR EQU LINE+3 ; (BYTE) TEXT CURSOR POSITION (0-39) + 00F6 CHKSUM EQU LINE+4 ; (WORD) HOLDS IMAGE CHECKSUM FOR VERIFY + END + INCLUD HARDEQ.ASM ; M + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 8 +--- HARDWARE EQUATES: ATARI --- + + + A100 SCREEN EQU $A100 ; START OF SCREEN RAM + + 0000 ; ---------------------- + 0000 ; ATARI HARDWARE EQUATES + 0000 ; ---------------------- + + 0000 ; ZER0-PAGE + + 0009 BOOT EQU $09 ; BOOT FLAG + 000A DOSVEC EQU $0A ; DOS START VECTOR + 000C DOSINI EQU $0C ; DOS INIT VECTOR + 0010 POKMSK EQU $10 ; FOR BREAK KEY DISABLE + 0011 BRKKEY EQU $11 ; BREAK KEY FLAG + 0014 RTCLOK EQU $14 ; JIFFY CLOCK + 0041 SOUNDR EQU $41 ; NOISY I/O FLAG + 004D ATRACT EQU $4D ; ATTRACT MODE FLAG + 0054 ROWCRS EQU $54 ; OS CURSOR ROW + 0055 COLCRS EQU $55 ; OS CURSOR COLUMN + 0058 SAVMSC EQU $58 ; OS SCREEN ADDRESS + 006A RAMTOP EQU $6A ; OS TOP OF RAM + 00D4 FR0 EQU $D4 ; FP REGISTER #0 + 00E0 FR1 EQU $E0 ; FP REGISTER #1 + 00F2 CIX EQU $F2 ; FP INDEX + 00F3 INBUFF EQU $F3 ; ASCII BUFFER POINTER + + 0000 ; PAGES 2-5 + + 022F SDMCTL EQU $022F ; DMA CONTROL + 0230 SDLSTL EQU $0230 ; DISPLAY LIST ADDRESS + 0244 COLDST EQU $0244 ; COLDSTART FLAG + 0278 STICK0 EQU $0278 ; JOYSTICK #0 + 0279 STICK1 EQU $0279 ; JOYSTICK #1 + 0284 STRIG0 EQU $0284 ; JOYSTICK #0 TRIGGER + 0285 STRIG1 EQU $0285 ; JOYSTICK #1 TRIGGER + 02C5 COLOR1 EQU $02C5 ; GRAPHICS FOREGROUND COLOR + 02C6 COLOR2 EQU $02C6 ; BACKGROUND COLOR + 02E4 RAMSIZ EQU $02E4 ; AMOUNT OF RAM IN SYSTEM + 02F0 CRSINH EQU $02F0 ; OS CURSOR INHIBIT + 02FC CH EQU $02FC ; KEYBOARD READ FLAG + 0301 DUNIT EQU $0301 ; DRIVE # + 0302 DCOMND EQU $0302 ; DISK COMMAND + 0303 DSTATS EQU $0303 ; DISK I/O STATUS + 0304 DBUFLO EQU $0304 ; DISK BUFFER ADDR (LSB) + 0305 DBUFHI EQU $0305 ; DISK BUFFER ADDR (MSB) + 030A DAUX1 EQU $030A ; SECTOR ADDR (LSB) + 030B DAUX2 EQU $030B ; SECTOR ADDR (MSB) + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 9 +--- HARDWARE EQUATES: ATARI --- + + 0342 ICCOM EQU $0342 ; IOCB #0 COMMAND + 0344 ICBADR EQU $0344 ; IOCB #0 BUFFER ADDR + 0348 ICBLEN EQU $0348 ; IOCB #0 LENGTH + 034A ICAUX1 EQU $034A ; IOCB #0 AUX BYTE #1 + 034B ICAUX2 EQU $034B ; IOCB #0 AUX BYTE #2 + 03A0 TEXT EQU $03A0 ; TEXT BUFFER + 0580 LBUFF EQU $0580 ; ASCII OUTPUT BUFFER + + 0000 ; GTIA, POKEY, ANTIC + + D01F CONSOL EQU $D01F ; CONSOLE KEY REGISTER + D200 AUDF1 EQU $D200 ; AUDIO CH1 FREQ + D201 AUDC1 EQU $D201 ; AUDIO CH1 CTRL + D202 AUDF2 EQU $D202 ; AUDIO CH2 FREQ + D203 AUDC2 EQU $D203 ; AUDIO CH2 CTRL + D204 AUDF3 EQU $D204 ; AUDIO CH3 FREQ + D205 AUDC3 EQU $D205 ; AUDIO CH3 CTRL + D206 AUDF4 EQU $D206 ; AUDIO CH4 FREQ + D207 AUDC4 EQU $D207 ; AUDIO CH4 CTRL + D208 AUDCTL EQU $D208 ; AUDIO CONTROL + D20A RANDOM EQU $D20A ; RANDOM BYTE + D20E IRQEN EQU $D20E ; IRQ ENABLE + D20F SKCTL EQU $D20F ; SERIAL PORT CONTROL + D301 PORTB EQU $D301 ; PORT B (XL ROM SWITCH) + D400 DMACTL EQU $D400 ; DMA CONTROL + + 0000 ; OS ROM + + D8E6 FASC EQU $D8E6 ; FP TO ASCII + D9AA IFP EQU $D9AA ; INTEGER TO FP + D9D2 FPI EQU $D9D2 ; FP TO INTEGER + DA44 ZFR0 EQU $DA44 ; CLEAR FR0 + DA46 ZFR1 EQU $DA46 ; CLEAR FR1 + DA60 FSUB EQU $DA60 ; FP SUBTRACT + DA66 FADD EQU $DA66 ; FP ADD + DADB FMUL EQU $DADB ; FP MULTIPLY + DB28 FDIV EQU $DB28 ; FP DIVIDE + DDB6 FMOVE EQU $DDB6 ; MOVE FR0 TO FR1 + E453 DSKINV EQU $E453 ; SIO DISK ACCESS + E456 CIOV EQU $E456 ; CIO VECTOR + E465 SIOINV EQU $E465 ; SIO INIT (FOR SOUND) + E477 COLDSV EQU $E477 ; COLDSTART VECTOR + + END + INCLUD COLD.ASM ; M + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 10 +--- MACHINE COLDSTART: ATARI --- + + + 0B00 ORG GRIP + + 0B00 ; ----------------- + 0B00 ; ATARI BOOT HEADER + 0B00 ; ----------------- + + 0B00 00 DB 0 ; FLAG BYTE (IGNORED) + 0B01 35 DB 53 ; LOAD ALL OF TRACKS 0, 1 AND 2 + 0B02 000B DW GRIP ; WHERE TO LOAD THE SECTORS + 0B04 0E0B DW DUMMY ; POINT TO INIT SUBROUTINE + + 0B06 ; -------------- + 0B06 ; BOOT COLDSTART + 0B06 ; -------------- + + 0B06 A9EB LDA #LOW COLD ; POINT [DOSVEC] TO + 0B08 850A STA DOSVEC+LO ; THE COLDSTART ROUTINE + 0B0A A90B LDA #HIGH COLD + 0B0C 850B STA DOSVEC+HI + + 0B0E A9FF DUMMY: LDA #$FF ; DISABLE BASIC ROM + 0B10 8D01D3 STA PORTB ; IN XL-SERIES MACHINES + 0B13 18 CLC ; SUCCESS FLAG + 0B14 60 RTS + + 0B15 ; ------------- + 0B15 ; DISPLAY LISTS + 0B15 ; ------------- + + 0B15 ; LIST 1: SCREEN W/STATUS LINE + + 0B15 707060 DL1: DB $70,$70,$60 ; 23 BLANK LINES + 0B18 42 DB $42 ; TEXT LINE W/LMS + 0B19 A003 DW TEXT ; ADDRESS OF TEXT LINE + 0B1B 02 DB $02 ; A SECOND LINE OF TEXT + 0B1C 01 DB $01 ; JUMP INSTRUCTION + 0B1D 340B DW DL2A ; INTO DL2 + + 0B1F ; LIST 2: SCREEN W/O STATUS LINE (NORMAL) + + 0B1F 707070 DL2: DB $70,$70,$70 ; 24 BLANK LINES + 0B22 4F DB $4F ; 1 SCAN LINE W/LMS + 0B23 00A1 DW SCREEN ; ADDRESS OF SCREEN RAM + 0B25 0F0F0F0F DB $0F,$0F,$0F,$0F ; 7 MORE + 0B29 0F0F0F DB $0F,$0F,$0F ; SCAN LINES (0) + 0B2C 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (2) + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 11 +--- MACHINE COLDSTART: ATARI --- + + + 0B34 4F DL2A: DB $4F ; 1 SCAN LINE W/LMS + 0B35 80A3 DW SCREEN+640 ; ADDRESS OF 8TH SCAN LINE + 0B37 0F0F0F0F DB $0F,$0F,$0F,$0F ; 7 MORE + 0B3B 0F0F0F DB $0F,$0F,$0F ; SCAN LINES (1) + + 0B3E 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (3) + 0B46 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (4) + 0B4E 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (5) + 0B56 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (6) + 0B5E 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (7) + 0B66 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (8) + 0B6E 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (9) + 0B76 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (10) + 0B7E 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (11) + + 0B86 4F DB $4F ; 1 SCAN LINE W/LMS + 0B87 00B0 DW SCREEN+3840 ; ADDRESS OF 96TH SCAN LINE + 0B89 0F0F0F0F DB $0F,$0F,$0F,$0F ; 7 MORE + 0B8D 0F0F0F DB $0F,$0F,$0F ; SCAN LINES (12) + + 0B90 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (13) + 0B98 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (14) + 0BA0 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (15) + 0BA8 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (16) + 0BB0 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (17) + 0BB8 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (18) + 0BC0 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (19) + 0BC8 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (20) + 0BD0 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (21) + 0BD8 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (22) + 0BE0 0F0F0F0F DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (23) + + 0BE8 41 DB $41 ; JUMP ON VERTICAL BLANK + 0BE9 1F0B DLTOP: DW DL2 ; TO TOP OF D-LIST 2 + + 0BEB ; --------- + 0BEB ; COLDSTART + 0BEB ; --------- + + 0BEB D8 COLD: CLD + 0BEC A2FF LDX #$FF ; RESET THE + 0BEE 9A TXS ; HARDWARE STACK + 0BEF 8EFC02 STX CH ; AND KEYBOARD REGISTER + 0BF2 8E01D3 STX PORTB ; REMOVE BASIC ROM IN XL-SERIES MACHINES + 0BF5 E8 INX ; = 0 + 0BF6 8E00D4 STX DMACTL ; SHUT OFF + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 12 +--- MACHINE COLDSTART: ATARI --- + + 0BF9 8E2F02 STX SDMCTL ; ANTIC + 0BFC 8EC602 STX COLOR2 ; BLACK BACKGROUND + 0BFF 8E4402 STX COLDST ; COLDSTART OKAY + 0C02 8E08D2 STX AUDCTL ; CLEAR SOUND + 0C05 8641 STX SOUNDR ; PREVENT I/O BEEPS + 0C07 E8 INX ; = 1 + 0C08 8609 STX BOOT ; BOOT SUCCESSFUL + + 0C0A A903 LDA #3 + 0C0C 8D0FD2 STA SKCTL ; RESET SOUND + + 0C0F A970 LDA #$70 + 0C11 8510 STA POKMSK ; DISABLE + 0C13 8D0ED2 STA IRQEN ; THE BREAK KEY + + 0C16 A90E LDA #14 ; WHITE + 0C18 8DC502 STA COLOR1 ; GRAPHICS + + 0C1B ; SET UP THE PLOT TABLES + + 0C1B A900 LDA #LOW SCREEN ; ADDRESS OF SCAN LINE 0 + 0C1D 8D0009 STA VLOWS ; HARD-WIRE THE 1ST POSITION + 0C20 857A STA I+LO ; ALSO INIT INDEX + + 0C22 A9A1 LDA #HIGH SCREEN ; SAME FOR MSBS + 0C24 8DC009 STA VHIGHS + 0C27 857B STA I+HI + + 0C29 A201 LDX #1 ; START AT LINE 1 + 0C2B A57A PTCALC: LDA I+LO + 0C2D 18 CLC + 0C2E 6928 ADC #40 + 0C30 857A STA I+LO + 0C32 9D0009 STA VLOWS,X + 0C35 A57B LDA I+HI + 0C37 6900 ADC #0 + 0C39 857B STA I+HI + 0C3B 9DC009 STA VHIGHS,X + 0C3E E8 INX + 0C3F E0C0 CPX #192 + 0C41 D0E8 BNE PTCALC + + 0C43 A97F LDA #$7F + 0C45 856D STA ARG1+LO + 0C47 856E STA ARG1+HI + 0C49 201F1C JSR GCLEAR ; CLEAR SCREEN TO BLACK + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 13 +--- MACHINE COLDSTART: ATARI --- + + 0C4C IF DEBUG + 0C4C JSR BUGNIT ; SET UP DEBUGGER + 0C4C ELSE + 0C4C A91F LDA #LOW DL2 ; ELSE USE FULL-SCREEN + 0C4E 8D3002 STA SDLSTL+LO + 0C51 8DE90B STA DLTOP+LO + 0C54 A90B LDA #HIGH DL2 + 0C56 8D3102 STA SDLSTL+HI + 0C59 8DEA0B STA DLTOP+HI + 0C5C ENDIF + + 0C5C A922 LDA #$22 + 0C5E 8D2F02 STA SDMCTL ; RESTORE ANTIC + + 0C61 ; FALL THROUGH TO WARMSTART ... + + END + INCLUD WARM.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 14 +--- WARMSTART ROUTINE --- + + + 0C61 ; --------- + 0C61 ; WARMSTART + 0C61 ; --------- + + 0C61 A900 WARM: LDA #0 ; CLEAR ALL Z-PAGE VARIABLES + 0C63 A26B LDX #ZSTART + 0C65 9500 CLRZ: STA 0,X + 0C67 E8 INX + ; CPX #ZEND ; NOT NEEDED FOR ATARI + 0C68 D0FB BNE CLRZ + + 0C6A ; CLEAR THE MEMORY, LRU & SWAPPING MAPS + + 0C6A AA TAX ; = 0 + 0C6B 9D0007 CLRT: STA MEMMAP,X + 0C6E 9D0008 STA PAGMAP,X + 0C71 E8 INX + 0C72 D0F7 BNE CLRT + + 0C74 E68E INC GSP ; INIT G-STACK POINTERS + 0C76 E68F INC OLDGSP ; TO 1 + 0C78 E698 INC STAMP ; 1ST TIMESTAMP IS 1 + + 0C7A A928 LDA #40 ; SET DEFAULT CLIPPING PARAMETERS + 0C7C 85CB STA WINDX2 + 0C7E 85CE STA WINDW ; DEFAULT WINDOW WIDTH + 0C80 A918 LDA #24 + 0C82 85CC STA WINDY2 + 0C84 85CD STA WINDH ; DEFAULT WINDOW HEIGHT + + 0C86 ; FETCH 1ST BLOCK OF G-PRELOAD + + 0C86 A923 LDA #HIGH GBEGIN + 0C88 8590 STA GCODE ; 1ST PAGE OF G-PRELOAD + 0C8A 85EE STA DBUFF+HI ; LSB OF [DBUFF] IS ALWAYS ZERO + 0C8C C694 DEC ISTART ; (= $FF) FORCE LOAD FROM G-FILE + 0C8E 202722 JSR GETDSK ; GRAB G-BLOCK #0 (G-PRELOAD HEADER) + + 0C91 ; EXTRACT DATA FROM G-PRELOAD HEADER + + 0C91 AE0423 LDX GBEGIN+GEND ; END OF PRELOAD (MSB) + 0C94 E8 INX ; MAKE IT AT LEAST 1 + 0C95 8693 STX GPURE ; 1ST VIRTUAL PAGE OF "PURE" G-CODE + + 0C97 8A TXA + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 15 +--- WARMSTART ROUTINE --- + + ;*** + 0C98 0A ASL A ; * 2 FOR 512 BYTE PAGES + 0C99 B012 BCS NOGRAM ; IT WOULD BE BAD IF CARRY WERE SET + ;*** + + ; CLC + + 0C9B 6590 ADC GCODE ; ABSOLUTE END OF G-PRELOAD + 0C9D 8592 STA ICODE+HI ; IS ABSOLUTE START OF I-PRELOAD + + 0C9F A942 LDA #INTRP ; SET INTERPRETER VERSION + 0CA1 8D1623 STA GBEGIN+IVERS ; FOR GAME + + 0CA4 20FD1C JSR MEMTOP ; GET TOP FREE PAGE INTO [A] + 0CA7 C592 CMP ICODE+HI ; ENOUGH ROOM FOR G-PRELOAD? + 0CA9 F002 BEQ NOGRAM + 0CAB B005 BCS GETLEN ; ONLY IF [MEMTOP] >= [ICODE] + + 0CAD ; *** ERROR #0: GAME PRELOAD TOO BIG *** + + 0CAD A900 NOGRAM: LDA #0 + 0CAF 4C5F1C JMP GERROR + + 0CB2 ; CALC VIRTUAL ADDRESS OF I-FILE + + 0CB2 AE1223 GETLEN: LDX GBEGIN+GLEN ; MSB OF G-CODE LENGTH + 0CB5 E8 INX + 0CB6 8694 STX ISTART ; 1ST VIRTUAL PAGE OF I-FILE + + 0CB8 ; FETCH THE REST OF THE G-PRELOAD + + 0CB8 A5EB GPGET: LDA DBLOCK + 0CBA C593 CMP GPURE + 0CBC B006 BCS IHEAD + 0CBE 202722 JSR GETDSK + 0CC1 4CB80C JMP GPGET + + 0CC4 ; NOW GET THE I-FILE HEADER + + 0CC4 A594 IHEAD: LDA ISTART ; POINT TO 1ST BLOCK + 0CC6 85EB STA DBLOCK ; OF IMAGE FILE + 0CC8 A592 LDA ICODE+HI ; TELL GROS + 0CCA 85EE STA DBUFF+HI ; WHERE TO PUT IT + 0CCC 202722 JSR GETDSK ; AND GET IT! + + 0CCF ; EXTRACT DATA FROM I-FILE HEADER + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 16 +--- WARMSTART ROUTINE --- + + 0CCF A002 LDY #IEND ; "END OF I-PRELOAD" POINTER (MSB) + 0CD1 B191 LDA (ICODE),Y + 0CD3 AA TAX ; COPY IT HERE + 0CD4 E8 INX ; POINT TO NEXT PAGE + + 0CD5 8A TXA + 0CD6 18 CLC + 0CD7 6594 ADC ISTART ; ADD 1ST V-PAGE OF I-FILE + 0CD9 8595 STA IPURE ; TO GET V-PAGE OF "PURE" I-CODE + + 0CDB 8A TXA + + ;*** + 0CDC 0A ASL A ; * 2 FOR 512 BYTE PAGES + 0CDD B00E BCS ITOBIG ; AGAIN IT WOULD BE BAD IF CARRY WERE SET + ;*** + + ; CLC + + 0CDF 6592 ADC ICODE+HI ; ADD BASE ADDR OF I-PRELOAD + 0CE1 8596 STA PAGE0 ; TO GET BASE PAGE OF SWAPPING SPACE + + 0CE3 20FD1C JSR MEMTOP ; GET TOP FREE PAGE INTO [A] AGAIN + 0CE6 38 SEC + 0CE7 E596 SBC PAGE0 ; CALC # PAGES IN SWAPPING SPACE + 0CE9 C910 CMP #16 ; MUST HAVE AT LEAST 2K + 0CEB B005 BCS ENOUGH ; OF SWAPPING SPACE + + 0CED ; *** ERROR #1: IMAGE PRELOAD TOO BIG *** + + 0CED A901 ITOBIG: LDA #1 + 0CEF 4C5F1C JMP GERROR + + 0CF2 AA ENOUGH: TAX ; CHECK SIZE OF PAGING SPACE + 0CF3 1002 BPL NOUGH ; MUST BE NO LARGER + 0CF5 A97E LDA #$7E ; THAN 32K! + + ;*** + 0CF7 4A NOUGH: LSR A ; DIVIDE !RAM! PAGES/2 TO GET #/BUFFERS + + 0CF8 **** + + 0CF8 8597 STA PMAX ; ESTABLISH # SWAPPING PAGES + + 0CFA ; GRAB THE REST OF THE I-PRELOAD + + 0CFA A5EB GETIP: LDA DBLOCK + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 17 +--- WARMSTART ROUTINE --- + + 0CFC C595 CMP IPURE + 0CFE B006 BCS GCALC + 0D00 202722 JSR GETDSK + 0D03 4CFA0C JMP GETIP + + 0D06 ; 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 + + ;*** + + 0D06 ;----------------------------------------------------------- + 0D06 ; [GGLOB] IS A VIRTUAL WORD POINTER TO THE GLOBAL TABLE + 0D06 ; MAKE [GLOBAL] A !RAM! ABSOLUTE POINTER TO THE GLOBAL TABLE + 0D06 ; + 0D06 ; WE MULTIPLY [GGLOB]*2 TO MAKE IT A BYTE POINTER AND ADD + 0D06 ; TO THE BEGINING ADDRESS OF PRELOAD. + 0D06 ;------------------------------------------------------------ + 0D06 AD0B23 GCALC: LDA GBEGIN+GGLOB+1 ; MAKE IT A BYTE POINTER WITH A * 2 + 0D09 0A ASL A + 0D0A 859C STA GLOBAL+LO + 0D0C AD0A23 LDA GBEGIN+GGLOB + 0D0F 2A ROL A + 0D10 18 CLC ; I THINK THE CARRY WOULD BE CLEAR ANYWAY + 0D11 6590 ADC GCODE + 0D13 859D STA GLOBAL+HI + ;*** + + + 0D15 ; G-VAR #16 = # BLOCKSETS IN I-FILE + + 0D15 A006 LDY #IBLKS ; GET # BLOCKSETS IN I-FILE + 0D17 B191 LDA (ICODE),Y + 0D19 85A2 STA NBLOKS ; SAVE HERE + + 0D1B 8578 STA VALUE+LO ; MSB IS ALREADY CLEARED + 0D1D A910 LDA #16 + 0D1F 207F0F JSR PUTVLG + + 0D22 ; G-VAR #18 = # ICONS IN I-FILE + + 0D22 A007 LDY #IICONS ; GET # ICONS IN I-FILE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 18 +--- WARMSTART ROUTINE --- + + 0D24 B191 LDA (ICODE),Y ; FROM THE I-FILE HEADER + 0D26 85A3 STA NICONS ; SAVE HERE + + 0D28 8578 STA VALUE+LO ; MSB ALREADY CLEARED + 0D2A A912 LDA #18 + 0D2C 207F0F JSR PUTVLG + + 0D2F ; [BTAB] = ABSOLUTE BLOCKSET TABLE ADDR + + 0D2F A592 LDA ICODE+HI ; BLOCKSET TABLE BEGINS + 0D31 859F STA BTAB+HI ; 8 BYTES AFTER THE START + 0D33 A908 LDA #8 ; OF THE I-FILE + 0D35 859E STA BTAB+LO + + 0D37 ; G-VAR #17 = V-WORD OF BLOCKSET TABLE + ;*** + 0D37 4A LSR A ; /2 FOR 4-WORD OFFSET + ;*** + + 0D38 8578 STA VALUE+LO ; SAME 8-BYTE OFFSET AS [BTAB] + 0D3A A594 LDA ISTART ; 1ST VIRTUAL PAGE # OF I-FILE + 0D3C 8579 STA VALUE+HI + 0D3E A911 LDA #17 + 0D40 207F0F JSR PUTVLG + + 0D43 ; G-VAR #19 = VIRTUAL WORD ADDRESS OF ICON TABLE + + 0D43 A5A2 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 + + 0D45 18 CLC ; ADD THE V-WORD ADDR OF THE B-TABLE + 0D46 6578 ADC VALUE+LO ; TO GET V-WORD ADDR OF I-TABLE + 0D48 8578 STA VALUE+LO ; INTO [VALUE] + + ; LDA MTEMP+HI + ;*** + 0D4A A900 LDA #00 + ;*** + + 0D4C 6579 ADC VALUE+HI + 0D4E 8579 STA VALUE+HI + + 0D50 A913 LDA #19 + 0D52 207F0F JSR PUTVLG + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 19 +--- WARMSTART ROUTINE --- + + + 0D55 ; PREPARE FOR TABLE PATCHING + + ;*** + 0D55 A5A2 LDA NBLOKS ; * 2 FOR LENGTH IN BYTES INSTED OF WORDS + 0D57 0A ASL A + 0D58 85A8 STA MTEMP+LO + 0D5A 26A9 ROL MTEMP+HI + ;*** + + + 0D5C A59E LDA BTAB+LO ; MAKE [I] POINT TO + 0D5E 857A STA I+LO ; START OF B-TABLE + 0D60 18 CLC ; WHILE WE'RE AT IT, + 0D61 65A8 ADC MTEMP+LO ; ADD SIZE OF B-TABLE + 0D63 85A0 STA ITAB+LO ; TO GET ABS START ADDR OF I-TABLE + 0D65 857C STA J+LO ; INTO [ITAB] AND [J] + + 0D67 A59F LDA BTAB+HI ; DON'T FORGET MSBS! + 0D69 857B STA I+HI + 0D6B 65A9 ADC MTEMP+HI + 0D6D 85A1 STA ITAB+HI + 0D6F 857D STA J+HI + + 0D71 ; PATCH THE BLOCKSET TABLE + ;*** + 0D71 ;SHOULD WORK AS IS + ;*** + + 0D71 A5A2 LDA NBLOKS ; GET # BLOCKSETS + 0D73 85AA STA QSIGN ; SAVE HERE FOR INDEXING + 0D75 A000 LDY #0 ; [I] HAS START OF B-TABLE + 0D77 B17A PATB: LDA (I),Y ; GET MSB OF A B-POINTER + 0D79 18 CLC + 0D7A 6594 ADC ISTART ; ADD ITS VIRTUAL OFFSET + 0D7C 917A STA (I),Y + + 0D7E C8 INY ; NO NEED TO TOUCH LSB + 0D7F C8 INY ; SO SKIP OVER IT + 0D80 D002 BNE PATB1 ; CONTINUE UNTIL PAGE BOUNDARY HIT + 0D82 E67B INC I+HI ; IF HIT, POINT TO NEXT PAGE + + 0D84 C6AA PATB1: DEC QSIGN ; DECREMENT # BLOCKSETS + 0D86 D0EF BNE PATB ; KEEP PATCHING TILL NONE LEFT + + 0D88 ; PATCH THE ICON TABLE + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 20 +--- WARMSTART ROUTINE --- + + 0D88 A5A3 LDA NICONS ; GET # ICONS + 0D8A 85AA STA QSIGN ; FOR INDEXING + 0D8C A000 LDY #0 ; [J] HAS START OF I-TABLE + 0D8E B17C PATI: LDA (J),Y ; GET MSB OF I-POINTER + 0D90 18 CLC + 0D91 6594 ADC ISTART ; ADD ITS VIRTUAL OFFSET + 0D93 917C STA (J),Y + + 0D95 C8 INY ; SKIP OVER LSB + 0D96 C8 INY + 0D97 D002 BNE PATI1 + 0D99 E67D INC J+HI + + 0D9B C6AA PATI1: DEC QSIGN ; DECREMENT # ICONS + 0D9D D0EF BNE PATI ; KEEP PATCHING TILL NONE LEFT + + 0D9F ; INIT THE VIRTUAL MEMORY MAP + + 0D9F A200 LDX #0 ; 1ST VIRTUAL PAGE + 0DA1 A490 LDY GCODE ; 1ST ABSOLUTE PAGE OF G-PRELOAD + 0DA3 98 MINIT0: TYA + 0DA4 9D0007 STA MEMMAP,X + 0DA7 C8 INY ; NEXT ABSOLUTE PAGE + ;*** + 0DA8 C8 INY ; SKIP 2 RAM PAGES FOR EVERY VIRTUAL PAGE + ;*** + 0DA9 E8 INX ; NEXT VIRTUAL PAGE + 0DAA E493 CPX GPURE ; END OF PRELOAD? + 0DAC 90F5 BCC MINIT0 ; NO, KEEP FILLING + + 0DAE A694 LDX ISTART ; 1ST VIRTUAL PAGE OF I-CODE + 0DB0 A492 LDY ICODE+HI ; 1ST ABSOLUTE PAGE OF I-PRELOAD + 0DB2 98 MINIT1: TYA + 0DB3 9D0007 STA MEMMAP,X + 0DB6 C8 INY ; NEXT ABSOLUTE PAGE + ;*** + 0DB7 C8 INY ; SKIP 2 RAM FOR EVERY 1 VIRTUAL + ;*** + 0DB8 E8 INX ; NEXT VIRTUAL PAGE + 0DB9 E495 CPX IPURE ; END OF I-PRELOAD? + 0DBB 90F5 BCC MINIT1 + + 0DBD ; ESTABLISH START ADDRESS OF G-PROGRAM + + 0DBD AD0623 LDA GBEGIN+GSTART ; MSB + 0DC0 8581 STA GPCH + 0DC2 AD0723 LDA GBEGIN+GSTART+1 ; LSB + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION PAGE 21 +--- WARMSTART ROUTINE --- + + 0DC5 8580 STA GPCL + + ;*** + 0DC7 A901 LDA #$01 ; START OF GAME IS ALWAYS ON THE ODD BYTE + 0DC9 8582 STA GPC0 ; OF THE [GSTART] WORD + 0DCB A900 LDA #$00 + 0DCD 8583 STA GPCFLG + ;*** + + 0DCF ; FALL THROUGH TO MAIN LOOP ... + + END + + INCLUD MAIN.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 22 +--- MAIN LOOP --- + + + 0DCF A2FF MLOOP: LDX #$FF ; RESET THE + 0DD1 9A TXS ; HARDWARE STACK + 0DD2 E8 INX ; = 0 + 0DD3 866C STX NARGS ; CLEAR # ARGS + 0DD5 20D21A JSR NEXTPC ; GET Z-BYTE INTO [A] + 0DD8 856B STA OPCODE ; FLAGS ARE SET + + 0DDA IF DEBUG + 0DDA LDA #0 ; BREAKPOINT #0 + 0DDA JSR DOBUG + 0DDA LDA OPCODE + 0DDA ENDIF + + 0DDA ; DECODE AN OPCODE + + 0DDA AA TAX ; SET FLAGS + 0DDB 3003 BMI DC0 ; IF POSITIVE, + 0DDD 4CA20E JMP OP2 ; IT'S A 2-OP + + 0DE0 C9E0 DC0: CMP #$E0 ; IS IT "CALL"? + 0DE2 D003 BNE DC1 + 0DE4 4CF712 JMP GCALL + + 0DE7 C9B0 DC1: CMP #$B0 + 0DE9 B003 BCS DC2 + 0DEB 4C730E JMP OP1 ; OR MAYBE A 1-OP + + 0DEE C9C0 DC2: CMP #$C0 + 0DF0 B003 BCS OPEXT + 0DF2 4C640E JMP OP0 ; PERHAPS A 0-OP + + 0DF5 ; -------------- + 0DF5 ; HANDLE AN X-OP + 0DF5 ; -------------- + + 0DF5 20D21A OPEXT: JSR NEXTPC ; GRAB ARGUMENT BYTE + 0DF8 8575 STA ABYTE ; HOLD IT HERE + + 0DFA A200 LDX #0 + 0DFC 8676 STX ADEX ; INIT LOOP INDEX + 0DFE F006 BEQ OPX1 ; JUMP INTO LOOP + + 0E00 A575 TOPX: LDA ABYTE ; GET ARG BYTE + 0E02 0A ASL A ; SHIFT NEXT 2 ARG BITS + 0E03 0A ASL A ; INTO BITS 7 & 6 + 0E04 8575 STA ABYTE ; HOLD FOR LATER + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 23 +--- MAIN LOOP --- + + + 0E06 29C0 OPX1: AND #%11000000 ; MASK OUT GARBAGE BITS + 0E08 D006 BNE OPX2 + 0E0A 20EE0E JSR GETLNG ; 00 = LONG IMMEDIATE + 0E0D 4C210E JMP OPXNXT + + 0E10 C940 OPX2: CMP #%01000000 ; IS IT A SHORT IMMEDIATE? + 0E12 D006 BNE OPX3 ; NO, KEEP GUESSING + 0E14 20EA0E JSR GETSHT ; 01 = SHORT IMMEDIATE + 0E17 4C210E JMP OPXNXT + + 0E1A C980 OPX3: CMP #%10000000 ; LAST TEST + 0E1C D017 BNE OPX4 ; 11 = NO MORE ARGUMENTS + 0E1E 20020F JSR GETVAR ; 10 = VARIABLE + + 0E21 A676 OPXNXT: LDX ADEX ; ARGUMENT INDEX + 0E23 A578 LDA VALUE+LO ; GRAB LSB OF VALUE + 0E25 956D STA ARG1+LO,X ; STORE IN ARGUMENT TABLE + 0E27 A579 LDA VALUE+HI ; GRAB MSB OF VALUE + 0E29 956E STA ARG1+HI,X ; STORE THAT, TOO + + 0E2B E66C INC NARGS ; UPDATE ARGUMENT COUNTER + + 0E2D E8 INX + 0E2E E8 INX + 0E2F 8676 STX ADEX ; UPDATE INDEX + 0E31 E008 CPX #8 ; DONE 4 ARGUMENTS YET? + 0E33 90CB BCC TOPX ; NO, GET SOME MORE + + 0E35 ; ALL X-OP ARGUMENTS READY + + 0E35 A56B OPX4: LDA OPCODE ; IS THIS + 0E37 C9E0 CMP #$E0 ; AN EXTENDED 2-OP? + 0E39 B003 BCS DOXOP ; NO, IT'S A REAL X-OP + 0E3B 4CCB0E JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + + 0E3E A261 DOXOP: LDX #LOW OPTX ; GET ADDR OF X-OP TABLE + 0E40 A010 LDY #HIGH OPTX ; INTO [X/Y] + 0E42 291F AND #%00011111 ; ISOLATE OP ID BITS + 0E44 C911 CMP #NOPSX ; IS IT A LEGAL X-OP? + 0E46 9005 BCC DODIS ; YUP; TIME TO DISPATCH IT + + 0E48 ; *** ERROR #2: UNDEFINED X-OP *** + + 0E48 A902 LDA #2 + 0E4A 4C5F1C JMP GERROR + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 24 +--- MAIN LOOP --- + + 0E4D ; --------------- + 0E4D ; OPCODE DISPATCH + 0E4D ; --------------- + + 0E4D ; ENTRY: MASKED OPCODE INDEX IN [A] + 0E4D ; OP-TABLE ADDR IN X/Y (LSB/MSB) + + 0E4D 867A DODIS: STX I+LO ; SAVE TABLE ADDRESS + 0E4F 847B STY I+HI ; IN A POINTER + + 0E51 0A ASL A ; WORD-ALIGN THE OP INDEX + 0E52 A8 TAY + 0E53 B17A LDA (I),Y ; GET LSB OF DISPATCH ADDRESS + 0E55 8D5F0E STA GO+LO ; INSTALL AS JSR OPERAND + 0E58 C8 INY + 0E59 B17A LDA (I),Y ; SAME WITH MSB + 0E5B 8D600E STA GO+HI + + 0E5E 20 DB $20 ; 6502 "JSR" OPCODE + 0E5F 0000 GO: DW $0000 ; DUMMY OPERAND BYTES + + 0E61 4CCF0D JMP MLOOP ; GO BACK FOR ANOTHER OPCODE + + 0E64 ; ------------- + 0E64 ; HANDLE A 0-OP + 0E64 ; ------------- + + 0E64 A21B OP0: LDX #LOW OPT0 ; GET ADDR OF 0-OP TABLE + 0E66 A010 LDY #HIGH OPT0 ; INTO [X/Y] + 0E68 290F AND #%00001111 ; ISOLATE OP ID BITS + 0E6A C908 CMP #NOPS0 ; OUT OF RANGE? + 0E6C 90DF BCC DODIS ; NO, DISPATCH + + 0E6E ; *** ERROR #3: UNDEFINED 0-OP *** + + 0E6E A903 LDA #3 + 0E70 4C5F1C JMP GERROR + + 0E73 ; ------------- + 0E73 ; HANDLE A 1-OP + 0E73 ; ------------- + + 0E73 2930 OP1: AND #%00110000 ; ISOLATE ARGUMENT BITS + 0E75 D006 BNE OP1A + 0E77 20EE0E JSR GETLNG ; 00 = LONG IMMEDIATE + 0E7A 4C8E0E JMP OP1EX + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 25 +--- MAIN LOOP --- + + 0E7D C910 OP1A: CMP #%00010000 ; TEST AGAIN + 0E7F D006 BNE OP1B + 0E81 20EA0E JSR GETSHT ; 01 = SHORT IMMEDIATE + 0E84 4C8E0E JMP OP1EX + + 0E87 C920 OP1B: CMP #%00100000 ; ONE MORE TEST + 0E89 D012 BNE BADOP1 ; UNDEFINED STATE! + 0E8B 20020F JSR GETVAR ; 10 = VARIABLE + + 0E8E 20DF0E OP1EX: JSR V2A1 ; VALUE TO [ARG1], UPDATE COUNT + 0E91 A22B LDX #LOW OPT1 ; LSB OF DISPATCH TABLE + 0E93 A010 LDY #HIGH OPT1 ; MSB + 0E95 A56B LDA OPCODE ; RESTORE OPCODE + 0E97 290F AND #%00001111 ; ISOLATE OP ID BITS + 0E99 C909 CMP #NOPS1 ; IF WITHIN RANGE, + 0E9B 90B0 BCC DODIS ; EXECUTE THE 1-OP + + 0E9D ; *** ERROR #4: UNDEFINED 1-OP *** + + 0E9D A904 BADOP1: LDA #4 + 0E9F 4C5F1C JMP GERROR + + 0EA2 ; ------------- + 0EA2 ; HANDLE A 2-OP + 0EA2 ; ------------- + + 0EA2 2940 OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT + 0EA4 D006 BNE OP2A + 0EA6 20EA0E JSR GETSHT ; 0 = SHORT IMMEDIATE + 0EA9 4CAF0E JMP OP2B + 0EAC 20020F OP2A: JSR GETVAR ; 1 = VARIABLE + 0EAF 20DF0E OP2B: JSR V2A1 ; VALUE TO [ARG1], UPDATE COUNT + + 0EB2 A56B LDA OPCODE ; RESTORE OPCODE BYTE + 0EB4 2920 AND #%00100000 ; ISOLATE 2ND ARG BIT + 0EB6 D006 BNE OP2C + 0EB8 20EA0E JSR GETSHT ; 0 = SHORT IMMEDIATE + 0EBB 4CC10E JMP OP2D + 0EBE 20020F OP2C: JSR GETVAR ; 1 = VARIABLE + 0EC1 A578 OP2D: LDA VALUE+LO ; MOVE VALUE TO [ARG2] + 0EC3 856F STA ARG2+LO + 0EC5 A579 LDA VALUE+HI + 0EC7 8570 STA ARG2+HI + 0EC9 E66C INC NARGS ; UPDATE COUNT + + 0ECB ; ENTRY FOR EXTENDED 2-OPS + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 26 +--- MAIN LOOP --- + + 0ECB A23D OP2EX: LDX #LOW OPT2 ; LSB OF DISPATCH TABLE + 0ECD A010 LDY #HIGH OPT2 ; MSB + 0ECF A56B LDA OPCODE ; RESTORE OPCODE BYTE + 0ED1 291F AND #%00011111 ; ISOLATE OP ID BITS + 0ED3 C912 CMP #NOPS2 + 0ED5 B003 BCS BADOP2 ; ERROR IF OUT OF RANGE + 0ED7 4C4D0E JMP DODIS ; ELSE DISPATCH + + 0EDA ; *** ERROR #5: UNDEFINED 2-OP **** + + 0EDA A905 BADOP2: LDA #5 + 0EDC 4C5F1C JMP GERROR + + 0EDF ; -------------------------------------- + 0EDF ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] + 0EDF ; -------------------------------------- + + 0EDF A578 V2A1: LDA VALUE+LO + 0EE1 856D STA ARG1+LO + 0EE3 A579 LDA VALUE+HI + 0EE5 856E STA ARG1+HI + 0EE7 E66C INC NARGS + 0EE9 60 RTS + + END + INCLUD SUBS.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 27 +--- OPCODE SUPPORT SUBROUTINES --- + + + 0EEA ; ----------------------- + 0EEA ; FETCH A SHORT IMMEDIATE + 0EEA ; ----------------------- + + 0EEA A900 GETSHT: LDA #0 ; CLEAR MSB OF [VALUE] + 0EEC F003 BEQ GLG ; AND GRAB LSB + + 0EEE ; ---------------------- + 0EEE ; FETCH A LONG IMMEDIATE + 0EEE ; ---------------------- + + 0EEE 20D21A GETLNG: JSR NEXTPC ; GRAB MSB + + 0EF1 8579 GLG: STA VALUE+HI ; STORE IT + 0EF3 20D21A JSR NEXTPC ; GRAB LSB + 0EF6 8578 STA VALUE+LO ; STORE THAT TOO + 0EF8 60 RTS + + 0EF9 ; ---------------- + 0EF9 ; FETCH A VARIABLE + 0EF9 ; ---------------- + + 0EF9 ; FROM WITHIN AN OPCODE (VARIABLE ID IN [A]) + + 0EF9 AA VARGET: TAX ; IF NON-ZERO, + 0EFA D00B BNE GETVR1 ; ACCESS A VARIABLE + + 0EFC 20280F JSR POPVAL ; ELSE PULL VAR OFF Z-STACK + 0EFF 4C3E0F JMP PSHVAL ; WITHOUT ALTERING STACK + + 0F02 ; FROM THE MAIN LOOP (ID BYTE IN Z-CODE) + + 0F02 20D21A GETVAR: JSR NEXTPC ; GRAB VAR-TYPE BYTE + 0F05 F021 BEQ POPVAL ; VALUE IS ON Z-STACK + + 0F07 ; IS VARIABLE LOCAL OR GLOBAL? + + 0F07 C910 GETVR1: CMP #$10 ; IF >= 16, + 0F09 B010 BCS GETVRG ; IT'S GLOBAL + + 0F0B ; HANDLE A LOCAL VARIABLE + + 0F0B 38 GETVRL: SEC + 0F0C E901 SBC #1 ; FORM A ZERO-ALIGNED + 0F0E 0A ASL A ; WORD INDEX + 0F0F AA TAX ; INTO THE [LOCALS] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 28 +--- OPCODE SUPPORT SUBROUTINES --- + + + 0F10 BD800A LDA LOCALS+LO,X ; GRAB LSB + 0F13 8578 STA VALUE+LO + 0F15 BD810A LDA LOCALS+HI,X ; AND MSB + 0F18 8579 STA VALUE+HI + 0F1A 60 RTS + + 0F1B ; HANDLE A GLOBAL VARIABLE + + 0F1B 208C0F GETVRG: JSR GVCALC ; GET ADDRESS OF GLOBAL INTO [I] + 0F1E B17A LDA (I),Y ; MSB OF GLOBAL ([Y] = 0) + 0F20 8579 STA VALUE+HI + 0F22 C8 INY ; = 1 + 0F23 B17A LDA (I),Y ; LSB OF GLOBAL + 0F25 8578 STA VALUE+LO ; SAVE IT + 0F27 60 RTS ; AND WE'RE DONE + + 0F28 ; ---------------------------------- + 0F28 ; POP G-STACK INTO [VALUE] AND [X/A] + 0F28 ; ---------------------------------- + + 0F28 C68E POPVAL: DEC GSP + 0F2A F00D BEQ UNDER ; UNDERFLOW IF ZERO! + + 0F2C A48E LDY GSP ; READ STACK POINTER + 0F2E BE0005 LDX GSTAKL,Y ; GRAB LSB OF STACK VALUE + 0F31 8678 STX VALUE+LO ; GIVE TO [VALUE] + 0F33 B90006 LDA GSTAKH,Y ; ALSO GRAB MSB + 0F36 8579 STA VALUE+HI ; A SIMILAR FATE + 0F38 60 RTS + + 0F39 ; *** ERROR #6: G-STACK UNDERFLOW *** + + 0F39 A906 UNDER: LDA #6 + 0F3B 4C5F1C JMP GERROR + + 0F3E ; ----------------------- + 0F3E ; PUSH [VALUE] TO G-STACK + 0F3E ; ----------------------- + + 0F3E A678 PSHVAL: LDX VALUE+LO + 0F40 A579 LDA VALUE+HI + + 0F42 ; FALL THROUGH ... + + 0F42 ; --------------------- + 0F42 ; PUSH [X/A] TO G-STACK + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 29 +--- OPCODE SUPPORT SUBROUTINES --- + + 0F42 ; --------------------- + + 0F42 A48E PSHXA: LDY GSP + 0F44 990006 STA GSTAKH,Y + 0F47 8A TXA + 0F48 990005 STA GSTAKL,Y + + 0F4B E68E INC GSP + 0F4D F001 BEQ OVER ; OVERFLOW IF ZEROED! + 0F4F 60 RTS + + 0F50 ; *** ERROR #7: G-STACK OVERFLOW *** + + 0F50 A907 OVER: LDA #7 + 0F52 4C5F1C JMP GERROR + + 0F55 ; -------------- + 0F55 ; RETURN A VALUE + 0F55 ; -------------- + + 0F55 ; FROM WITHIN AN OPCODE (VARIABLE ID IN [A]) + + 0F55 AA VARPUT: TAX ; IF ZERO, + 0F56 D013 BNE PUTVR1 + + 0F58 C68E DEC GSP ; FLUSH TOP WORD OFF STACK + 0F5A D0E2 BNE PSHVAL ; AND REPLACE WITH [VALUE] + 0F5C F0DB BEQ UNDER ; ERROR IF ZSP BECAME ZERO! + + 0F5E ; RETURN A ZERO + + 0F5E A900 RET0: LDA #0 + + 0F60 ; RETURN BYTE IN [A] + + 0F60 8578 PUTBYT: STA VALUE+LO + 0F62 A900 LDA #0 + 0F64 8579 STA VALUE+HI ; CLEAR MSB + + 0F66 ; RETURN [VALUE]; VARIABLE ID IN NEXT Z-BYTE + + 0F66 20D21A PUTVAL: JSR NEXTPC ; GET VAR-TYPE BYTE + 0F69 F0D3 BEQ PSHVAL ; VALUE GOES TO STACK IF ZERO + + 0F6B ; LOCAL OR GLOBAL VARIABLE? + + 0F6B C910 PUTVR1: CMP #$10 ; IF >= 16, + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 30 +--- OPCODE SUPPORT SUBROUTINES --- + + 0F6D B010 BCS PUTVLG ; IT'S GLOBAL + + 0F6F ; PUT A LOCAL VARIABLE + + 0F6F 38 PUTVLL: SEC + 0F70 E901 SBC #1 ; FORM A ZERO-ALIGNED + 0F72 0A ASL A ; WORD INDEX + 0F73 AA TAX ; INTO [LOCALS] + + 0F74 A578 LDA VALUE+LO ; GRAB LSB + 0F76 9D800A STA LOCALS+LO,X ; SAVE IN LOCAL TABLE + 0F79 A579 LDA VALUE+HI ; DO SAME TO + 0F7B 9D810A STA LOCALS+HI,X ; MSB + 0F7E 60 RTS + + 0F7F ; PUT A GLOBAL VARIABLE + + 0F7F 208C0F PUTVLG: JSR GVCALC ; GET ADDR OF GLOBAL INTO [I] + 0F82 A579 LDA VALUE+HI ; GET MSB + 0F84 917A STA (I),Y ; STORE AS 1ST BYTE ([Y] = 0) + 0F86 C8 INY ; [Y] = 1 + 0F87 A578 LDA VALUE+LO ; NOW GET LSB + 0F89 917A STA (I),Y ; STORE AS 2ND BYTE + 0F8B 60 RTS + + 0F8C ; ----------------------- + 0F8C ; CALC GLOBAL WORD OFFSET + 0F8C ; ----------------------- + + 0F8C ; ENTRY: VAR-ID BYTE (16-255) IN [A] + 0F8C ; EXIT: ADDRESS OF GLOBAL VAR IN [VAL] + 0F8C ; [Y] = 0 FOR INDEXING + + 0F8C 38 GVCALC: SEC + 0F8D E910 SBC #$10 ; FORM A ZERO-ALIGNED INDEX + 0F8F A000 LDY #0 ; MAKE SURE MSB OF OFFSET AND [Y] + 0F91 847B STY I+HI ; ARE CLEARED + + 0F93 0A ASL A ; MULTIPLY OFFSET BY 2 + 0F94 267B ROL I+HI ; TO WORD-ALIGN IT + + 0F96 18 CLC ; TO ADDRESS OF GLOBAL TABLE + 0F97 659C ADC GLOBAL+LO ; TO FORM THE ABSOLUTE + 0F99 857A STA I+LO ; ADDRESS OF THE + 0F9B A57B LDA I+HI ; DESIRED GLOBAL VARIABLE + 0F9D 659D ADC GLOBAL+HI ; STORE ADDRESS BACK IN [I] + 0F9F 857B STA I+HI ; AS A POINTER + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 31 +--- OPCODE SUPPORT SUBROUTINES --- + + + 0FA1 60 WCEX: RTS + + 0FA2 ; --------------- + 0FA2 ; PREDICATE FAILS + 0FA2 ; --------------- + + 0FA2 20D21A PREDF: JSR NEXTPC ; GET 1ST BRANCH BYTE + 0FA5 100C BPL PREDB ; BRANCH IF BIT 7 CLEAR + + 0FA7 ; ----------------------- + 0FA7 ; IGNORE PREDICATE BRANCH + 0FA7 ; ----------------------- + + 0FA7 ; ENTRY: 1ST BRANCH BYTE IN [A] + + 0FA7 2940 PREDNB: AND #%01000000 ; TEST BIT 6 + 0FA9 D0F6 BNE WCEX ; SHORT BRANCH IF SET + 0FAB 4CD21A JMP NEXTPC ; ELSE SKIP OVER 2ND BRANCH BYTE + + 0FAE ; ------------------ + 0FAE ; PREDICATE SUCCEEDS + 0FAE ; ------------------ + + 0FAE 20D21A PREDS: JSR NEXTPC ; GET 1ST BRANCH BYTE + 0FB1 10F4 BPL PREDNB ; DON'T BRANCH IF BIT 7 CLEAR + + 0FB3 ; -------------------------- + 0FB3 ; PERFORM A PREDICATE BRANCH + 0FB3 ; -------------------------- + + 0FB3 ; ENTRY: 1ST PRED BYTE IN [A] + + 0FB3 AA PREDB: TAX ; COPY FOR LATER + 0FB4 2940 AND #%01000000 ; LONG OR SHORT BRANCH? + 0FB6 F00B BEQ PREDLB ; LONG IF BIT 6 IS CLEAR + + 0FB8 ; HANDLE A SHORT BRANCH + + 0FB8 8A TXA ; RESTORE PRED BYTE + 0FB9 293F AND #%00111111 ; FORM SHORT OFFSET + 0FBB 8578 STA VALUE+LO ; USE AS LSB OF BRANCH OFFSET + 0FBD A900 LDA #0 + 0FBF 8579 STA VALUE+HI ; MSB OF OFFSET IS ZERO + 0FC1 F013 BEQ PREDB1 ; DO THE BRANCH + + 0FC3 ; HANDLE A LONG BRANCH + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 32 +--- OPCODE SUPPORT SUBROUTINES --- + + + 0FC3 8A PREDLB: TXA ; RESTORE 1ST PRED BYTE + 0FC4 293F AND #%00111111 ; FORM MSB OF OFFSET + 0FC6 AA TAX ; SAVE HERE FOR REFERENCE + + 0FC7 2920 AND #%00100000 ; CHECK SIGN OF 14-BIT VALUE + 0FC9 F004 BEQ DOB2 ; POSITIVE IF ZERO, USE [X] FOR MSB + + 0FCB 8A TXA ; ELSE RESTORE BYTE + 0FCC 09E0 ORA #%11100000 ; EXTEND SIGN BIT + 0FCE AA TAX ; BACK HERE FOR STORAGE + + 0FCF 8679 DOB2: STX VALUE+HI + 0FD1 20D21A JSR NEXTPC ; FETCH LSB OF 14-BIT OFFSET + 0FD4 8578 STA VALUE+LO + + 0FD6 ; BRANCH TO Z-ADDRESS IN [VALUE] + + 0FD6 A579 PREDB1: LDA VALUE+HI ; CHECK MSB OF OFFSET + 0FD8 D00E BNE PREDB3 ; DO BRANCH IF NZ + 0FDA A578 LDA VALUE+LO ; IF LSB IS NON-ZERO, + 0FDC D003 BNE PREDB2 ; MAKE SURE IT ISN'T 1 + 0FDE 4C8E10 JMP GRFALS ; ELSE DO AN "RFALSE" IF [VALUE] = 0 + + 0FE1 C901 PREDB2: CMP #1 ; IF OFFSET = 1 + 0FE3 D003 BNE PREDB3 + 0FE5 4C8310 JMP GRTRUE ; DO AN "RTRUE" + + 0FE8 ; ENTRY POINT FOR "JUMP" + + 0FE8 200610 PREDB3: JSR DECVAL ; CALC [VALUE]-2 + 0FEB 200610 JSR DECVAL + ;*** + 0FEE A579 LDA VALUE+HI + 0FF0 A678 LDX VALUE+LO + 0FF2 20D918 JSR ADDGPC + + 0FF5 A579 LDA VALUE+HI ; EXTEND SIGN + 0FF7 2980 AND #$80 + 0FF9 18 CLC + 0FFA 6581 ADC GPCH + 0FFC 8581 STA GPCH + ;*** + + + ; LDA VALUE+LO ; GET LSB OF OFFSET + ; CLC + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 33 +--- OPCODE SUPPORT SUBROUTINES --- + + ; 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 + + 0FFE ; FALL THROUGH ... + + 0FFE ; ---- + 0FFE ; NOOP + 0FFE ; ---- + + 0FFE 60 GNOOP: RTS + + 0FFF ; ----------------- + 0FFF ; INCREMENT [VALUE] + 0FFF ; ----------------- + + 0FFF E678 INCVAL: INC VALUE+LO + 1001 D002 BNE IVX + 1003 E679 INC VALUE+HI + 1005 60 IVX: RTS + + 1006 ; ----------------- + 1006 ; DECREMENT [VALUE] + 1006 ; ----------------- + + 1006 A578 DECVAL: LDA VALUE+LO + 1008 38 SEC + 1009 E901 SBC #1 + 100B 8578 STA VALUE+LO + 100D B002 BCS DVX + 100F C679 DEC VALUE+HI + 1011 60 DVX: RTS + + 1012 ; ---------------------- + 1012 ; MOVE [ARG1] TO [VALUE] + 1012 ; ---------------------- + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 34 +--- OPCODE SUPPORT SUBROUTINES --- + + 1012 A56D A12VAL: LDA ARG1+LO + 1014 8578 STA VALUE+LO + 1016 A56E LDA ARG1+HI + 1018 8579 STA VALUE+HI + 101A 60 RTS + + END + INCLUD DISPATCH.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 35 +--- OPCODE DISPATCH TABLES --- + + + 101B ; ------------------- + 101B ; 0-OP DISPATCH TABLE + 101B ; ------------------- + + 101B FE0F OPT0: DW GNOOP ; 0 + 101D 8310 DW GRTRUE ; 1 + 101F 8E10 DW GRFALS ; 2 + 1021 9210 DW GRSTAK ; 3 + 1023 280F DW GFSTAK ; 4 + 1025 7A1C DW GQUIT ; 5 + 1027 AE0F DW GCOPYP ; 6 + 1029 461E DW GVERP ; 7 + + 0008 NOPS0 EQU 8 ; # VALID 0-OPS + + 102B ; ------------------- + 102B ; 1-OP DISPATCH TABLE + 102B ; ------------------- + + 102B 9810 OPT1: DW GPUSH ; 0 + 102D 9F10 DW GPOP ; 1 + 102F A510 DW GVALUE ; 2 + 1031 AD10 DW GINC ; 3 + 1033 B810 DW GDEC ; 4 + 1035 C510 DW GZEROP ; 5 + 1037 D110 DW GBNOT ; 6 + 1039 DD10 DW GJUMP ; 7 + 103B E310 DW GRET ; 8 + + 0009 NOPS1 EQU 9 ; # VALID 1-OPS + + 103D ; ------------------- + 103D ; 2-OP DISPATCH TABLE + 103D ; ------------------- + + 103D DA0E OPT2: DW BADOP2 ; 0, UNDEFINED + 103F 2511 DW GADD ; 1 + 1041 3211 DW GSUB ; 2 + 1043 3F11 DW GMUL ; 3 + 1045 6311 DW GDIV ; 4 + 1047 6D11 DW GMOD ; 5 + 1049 0312 DW GBAND ; 6 + 104B 0F12 DW GBIOR ; 7 + 104D 1B12 DW GBXOR ; 8 + 104F 2712 DW GBITSP ; 9 + 1051 3912 DW GEQP ; 10 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP PAGE 36 +--- OPCODE DISPATCH TABLES --- + + 1053 6512 DW GLESSP ; 11 + 1055 6B12 DW GDLESP ; 12 + 1057 7912 DW GGRTRP ; 13 + 1059 8412 DW GIGRTP ; 14 + 105B B412 DW GSET ; 15 + 105D C112 DW GGET ; 16 + 105F D512 DW GGETB ; 17 + + 0012 NOPS2 EQU 18 ; # VALID 2-OPS + + 1061 ; ------------------- + 1061 ; X-OP DISPATCH TABLE + 1061 ; ------------------- + + 1061 F712 OPTX: DW GCALL ; 0 + 1063 F113 DW GPUT ; 1 + 1065 FC13 DW GPUTB ; 2 + 1067 241D DW GINPUT ; 3 + 1069 BD14 DW GSHOWI ; 4 + 106B 8816 DW GSETI ; 5 + 106D BC16 DW GSWAPI ; 6 + 106F 251E DW GSOUND ; 7 + 1071 3F14 DW GRAND ; 8 + 1073 1F1C DW GCLEAR ; 9 + 1075 B714 DW GSHOWN ; 10 + 1077 1C17 DW GWIND ; 11 + 1079 6114 DW GITER ; 12 + 107B B414 DW GLOAD ; 13 + 107D B114 DW GDUMP ; 14 + 107F D01F DW GREST ; 15 + 1081 6D20 DW GSAVE ; 16 + + 0011 NOPSX EQU 17 ; # VALID X-OPS + + END + + INCLUD OPS0.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 37 +--- 0-OPS --- + + + 1083 ; ----- + 1083 ; RTRUE + 1083 ; ----- + + 1083 ; SIMULATE "RETURN 1" + + 1083 A201 GRTRUE: LDX #1 + + 1085 A900 GRT1: LDA #0 + + 1087 866D GRT2: STX ARG1+LO + 1089 856E STA ARG1+HI + 108B 4CE310 JMP GRET + + 108E ; ------ + 108E ; RFALSE + 108E ; ------ + + 108E ; SIMULATE "RETURN 0" + + 108E A200 GRFALS: LDX #0 + 1090 F0F3 BEQ GRT1 + + 1092 ; ------ + 1092 ; RSTACK + 1092 ; ------ + + 1092 ; "RETURN" WITH VALUE ON STACK + + 1092 20280F GRSTAK: JSR POPVAL ; GET VALUE INTO [X/A] + 1095 4C8710 JMP GRT2 + + 1098 ; ------ + 1098 ; FSTACK + 1098 ; ------ + + 1098 ; FLUSH TOP VALUE OFF G-STACK + + 0F28 GFSTAK EQU POPVAL + + END + INCLUD OPS1.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 38 +--- 1-OPS --- + + + 1098 ; ---- + 1098 ; PUSH + 1098 ; ---- + + 1098 ; PUSH [ARG1] ONTO G-STACK + + 1098 A66D GPUSH: LDX ARG1+LO + 109A A56E LDA ARG1+HI + 109C 4C420F JMP PSHXA + + 109F ; --- + 109F ; POP + 109F ; --- + + 109F ; POP Z-STACK INTO VARIABLE [ARG1] + + 109F 20280F GPOP: JSR POPVAL + 10A2 4CC010 JMP DOPUT + + 10A5 ; ----- + 10A5 ; VALUE + 10A5 ; ----- + + 10A5 ; RETURN VALUE OF VARIABLE [ARG1] + + 10A5 A56D GVALUE: LDA ARG1+LO ; GET VARIABLE ID + 10A7 20F90E JSR VARGET ; PUT VALUE INTO [VALUE] + 10AA 4C660F JMP PUTVAL + + 10AD ; --- + 10AD ; INC + 10AD ; --- + + 10AD ; INCREMENT VARIABLE [ARG1] + + 10AD A56D GINC: LDA ARG1+LO + 10AF 20F90E JSR VARGET + 10B2 20FF0F JSR INCVAL + 10B5 4CC010 JMP DOPUT + + 10B8 ; --- + 10B8 ; DEC + 10B8 ; --- + + 10B8 ; DECREMENT VARIABLE [ARG1] + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 39 +--- 1-OPS --- + + 10B8 A56D GDEC: LDA ARG1+LO + 10BA 20F90E JSR VARGET + 10BD 200610 JSR DECVAL + + 10C0 A56D DOPUT: LDA ARG1+LO + 10C2 4C550F JMP VARPUT + + 10C5 ; ----- + 10C5 ; ZERO? + 10C5 ; ----- + + 10C5 ; [ARG1] = 0 ? + + 10C5 A56D GZEROP: LDA ARG1+LO + 10C7 056E ORA ARG1+HI + 10C9 F003 BEQ PYES + 10CB 4CA20F JMP PREDF + + 10CE 4CAE0F PYES: JMP PREDS + + 10D1 ; ---- + 10D1 ; BNOT + 10D1 ; ---- + + 10D1 ; COMPLEMENT [ARG1] + + 10D1 A56D GBNOT: LDA ARG1+LO + 10D3 49FF EOR #$FF + 10D5 AA TAX + 10D6 A56E LDA ARG1+HI + 10D8 49FF EOR #$FF + 10DA 4C1E11 JMP VEXIT + + 10DD ; ---- + 10DD ; JUMP + 10DD ; ---- + + 10DD ; JUMP TO G-ADDRESS [ARG1] + + 10DD 201210 GJUMP: JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 10E0 4CE80F JMP PREDB3 ; A BRANCH THAT ALWAYS SUCCEEDS + + 10E3 ; ------ + 10E3 ; RETURN + 10E3 ; ------ + + 10E3 ; RETURN FROM "CALL" WITH VALUE [ARG1] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 40 +--- 1-OPS --- + + + 10E3 A58F GRET: LDA OLDGSP + 10E5 858E STA GSP ; SYNC THE G-STACK + + 10E7 20280F JSR POPVAL ; POP # LOCALS INTO [X] + 10EA 8A TXA ; ANY LOCALS? + 10EB F018 BEQ RET2 ; NO, SKIP + + 10ED ; RESTORE ALL PUSHED LOCALS + + 10ED 0A ASL A ; WORD-ALIGN # LOCALS + 10EE 8576 STA ADEX ; USE FOR INDEXING + 10F0 C676 DEC ADEX ; ZERO-ALIGN THE INDEX + + 10F2 20280F RET1: JSR POPVAL ; POP LOCAL INTO [X/A] AND [VALUE] + 10F5 A676 LDX ADEX ; GET INDEX + 10F7 9D800A STA LOCALS,X ; STORE MSB IN TABLE + 10FA CA DEX + 10FB A578 LDA VALUE+LO ; SAME FOR LSB + 10FD 9D800A STA LOCALS,X + 1100 CA DEX + 1101 8676 STX ADEX ; SAVE INDEX + 1103 10ED BPL RET1 ; LOOP TILL EMPTY + + 1105 ; RESTORE GPC + + 1105 20280F RET2: JSR POPVAL ; RESTORE [GPC] + + ;*** + 1108 8682 STX GPC0 ; DON'T FORGET THAT 17TH BIT + 110A 20280F JSR POPVAL + ;*** + + 110D 8680 STX GPCL + 110F 8581 STA GPCH + 1111 A900 LDA #0 + 1113 8583 STA GPCFLG ; PC HAS CHANGED + + 1115 20280F JSR POPVAL + 1118 868F STX OLDGSP ; RESTORE OLD GSP + + 111A A66D LDX ARG1+LO + 111C A56E LDA ARG1+HI + + 111E ; FALL THROUGH TO ... + + 111E ; ----------------- + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 41 +--- 1-OPS --- + + 111E ; VALUE RETURN EXIT + 111E ; ----------------- + + 111E ; ENTRY: VALUE IN [X/A] (LSB/MSB) + + 111E 8678 VEXIT: STX VALUE+LO + 1120 8579 STA VALUE+HI + 1122 4C660F JMP PUTVAL + + END + INCLUD OPS2.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 42 +--- 2-OPS --- + + + 1125 ; --- + 1125 ; ADD + 1125 ; --- + + 1125 ; RETURN [ARG1] + [ARG2] + + 1125 A56D GADD: LDA ARG1+LO + 1127 18 CLC + 1128 656F ADC ARG2+LO + 112A AA TAX + 112B A56E LDA ARG1+HI + 112D 6570 ADC ARG2+HI + 112F 4C1E11 JMP VEXIT + + 1132 ; --- + 1132 ; SUB + 1132 ; --- + + 1132 ; RETURN [ARG1] - [ARG2] + + 1132 A56D GSUB: LDA ARG1+LO + 1134 38 SEC + 1135 E56F SBC ARG2+LO + 1137 AA TAX + 1138 A56E LDA ARG1+HI + 113A E570 SBC ARG2+HI + 113C 4C1E11 JMP VEXIT + + 113F ; --- + 113F ; MUL + 113F ; --- + + 113F ; RETURN [ARG1] * [ARG2] + + 113F 20F911 GMUL: JSR MINIT ; INIT LOOP AND TEMPS + + 1142 66A9 GMLOOP: ROR MTEMP+HI + 1144 66A8 ROR MTEMP+LO + 1146 6670 ROR ARG2+HI + 1148 666F ROR ARG2+LO + 114A 900D BCC GMNEXT + + 114C A56D LDA ARG1+LO + 114E 18 CLC + 114F 65A8 ADC MTEMP+LO + 1151 85A8 STA MTEMP+LO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 43 +--- 2-OPS --- + + 1153 A56E LDA ARG1+HI + 1155 65A9 ADC MTEMP+HI + 1157 85A9 STA MTEMP+HI + + 1159 CA GMNEXT: DEX + 115A 10E6 BPL GMLOOP + + 115C A66F LDX ARG2+LO ; [ARG2] CONTAINS PRODUCT + 115E A570 LDA ARG2+HI + 1160 4C1E11 JMP VEXIT + + 1163 ; --- + 1163 ; DIV + 1163 ; --- + + 1163 ; RETURN QUOTIENT OF [ARG1] / [ARG2] + + 1163 207711 GDIV: JSR DIVIDE + 1166 A6A4 LDX QUOT+LO + 1168 A5A5 LDA QUOT+HI + 116A 4C1E11 JMP VEXIT + + 116D ; --- + 116D ; MOD + 116D ; --- + + 116D ; RETURN REMAINDER OF [ARG1] / [ARG2] + + 116D 207711 GMOD: JSR DIVIDE + 1170 A6A6 LDX REMAIN+LO + 1172 A5A7 LDA REMAIN+HI + 1174 4C1E11 JMP VEXIT + + 1177 ; --------------- + 1177 ; SIGNED DIVISION + 1177 ; --------------- + + 1177 ; ENTRY: DIVIDEND IN [ARG1], DIVISOR IN [ARG2] + 1177 ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] + + 1177 A56E DIVIDE: LDA ARG1+HI ; SIGN OF THE DIVIDEND + 1179 85AB STA RSIGN ; IS SIGN OF REMAINDER + 117B 4570 EOR ARG2+HI ; SIGN OF QUOTIENT IS POSITIVE + 117D 85AA STA QSIGN ; IF SIGNS OF TERMS ARE THE SAME + + 117F A56D LDA ARG1+LO ; MOVE [ARG1] TO [QUOT] + 1181 85A4 STA QUOT+LO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 44 +--- 2-OPS --- + + 1183 A56E LDA ARG1+HI ; IS DIVIDEND POSITIVE? + 1185 85A5 STA QUOT+HI + 1187 1003 BPL ABSDIV ; YES, CONTINUE + 1189 20B511 JSR ABQUOT ; ELSE CALC ABSOLUTE VALUE + + 118C A56F ABSDIV: LDA ARG2+LO ; MOVE [ARG2] TO [REMAIN] + 118E 85A6 STA REMAIN+LO + 1190 A570 LDA ARG2+HI ; IS DIVISOR POSITIVE? + 1192 85A7 STA REMAIN+HI + 1194 1003 BPL GODIV ; IF NOT, + 1196 20A711 JSR ABREM ; CALC ABSOLUTE VALUE + + 1199 20C311 GODIV: JSR UDIV ; UNSIGNED DIVIDE + + 119C A5AA LDA QSIGN ; SHOULD QUOTIENT BE FLIPPED? + 119E 1003 BPL RFLIP ; NO, CHECK REMAINDER + 11A0 20B511 JSR ABQUOT ; ELSE FLIP QUOTIENT + + 11A3 A5AB RFLIP: LDA RSIGN ; FLIP REMAINDER? + 11A5 100D BPL DIVEX ; NO, SCRAM + + 11A7 ; OR FALL THROUGH ... + + 11A7 ; ---------------- + 11A7 ; CALC ABS(REMAIN) + 11A7 ; ---------------- + + 11A7 A900 ABREM: LDA #0 + 11A9 38 SEC + 11AA E5A6 SBC REMAIN+LO + 11AC 85A6 STA REMAIN+LO + 11AE A900 LDA #0 + 11B0 E5A7 SBC REMAIN+HI + 11B2 85A7 STA REMAIN+HI + + 11B4 60 DIVEX: RTS + + 11B5 ; -------------- + 11B5 ; CALC ABS(QUOT) + 11B5 ; -------------- + + 11B5 A900 ABQUOT: LDA #0 + 11B7 38 SEC + 11B8 E5A4 SBC QUOT+LO + 11BA 85A4 STA QUOT+LO + 11BC A900 LDA #0 + 11BE E5A5 SBC QUOT+HI + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 45 +--- 2-OPS --- + + 11C0 85A5 STA QUOT+HI + 11C2 60 RTS + + 11C3 ; ----------------- + 11C3 ; UNSIGNED DIVISION + 11C3 ; ----------------- + + 11C3 ; ENTRY: DIVIDEND IN [QUOT], DIVISOR IN [REMAIN] + 11C3 ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] + + 11C3 A5A6 UDIV: LDA REMAIN+LO + 11C5 05A7 ORA REMAIN+HI + 11C7 F02B BEQ DIVERR ; CAN'T DIVIDE BY ZERO! + + 11C9 20F911 JSR MINIT ; INIT LOOP & TEMP REGISTER + + 11CC 26A4 UDLOOP: ROL QUOT+LO + 11CE 26A5 ROL QUOT+HI + 11D0 26A8 ROL MTEMP+LO + 11D2 26A9 ROL MTEMP+HI + + 11D4 A5A8 LDA MTEMP+LO + 11D6 38 SEC + 11D7 E5A6 SBC REMAIN+LO + 11D9 A8 TAY + 11DA A5A9 LDA MTEMP+HI + 11DC E5A7 SBC REMAIN+HI + 11DE 9004 BCC UDNEXT + 11E0 84A8 STY MTEMP+LO + 11E2 85A9 STA MTEMP+HI + + 11E4 CA UDNEXT: DEX + 11E5 D0E5 BNE UDLOOP + + 11E7 26A4 ROL QUOT+LO ; SHIFT LAST CARRY + 11E9 26A5 ROL QUOT+HI ; INTO QUOTIENT + + 11EB A5A8 LDA MTEMP+LO ; MOVE REMAINDER + 11ED 85A6 STA REMAIN+LO ; INTO [REMAIN] + 11EF A5A9 LDA MTEMP+HI + 11F1 85A7 STA REMAIN+HI + 11F3 60 RTS + + 11F4 ; *** ERROR #8: DIVISION BY ZERO *** + + 11F4 A908 DIVERR: LDA #8 + 11F6 4C5F1C JMP GERROR + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 46 +--- 2-OPS --- + + + 11F9 ; --------- + 11F9 ; MATH INIT + 11F9 ; --------- + + 11F9 A210 MINIT: LDX #16 ; INIT BIT LOOP INDEX + 11FB A900 LDA #0 ; CLEAR TEMP MATH REGISTER + 11FD 85A8 STA MTEMP+LO + 11FF 85A9 STA MTEMP+HI + 1201 18 CLC ; CLEAR FOR LOOPING + 1202 60 RTS + + 1203 ; ---- + 1203 ; BAND + 1203 ; ---- + + 1203 ; RETURN [ARG1] "AND" [ARG2] + + 1203 A56D GBAND: LDA ARG1+LO + 1205 256F AND ARG2+LO + 1207 AA TAX + 1208 A56E LDA ARG1+HI + 120A 2570 AND ARG2+HI + 120C 4C1E11 JMP VEXIT + + 120F ; ---- + 120F ; BIOR + 120F ; ---- + + 120F ; RETURN [ARG1] "OR" [ARG2] + + 120F A56D GBIOR: LDA ARG1+LO + 1211 056F ORA ARG2+LO + 1213 AA TAX + 1214 A56E LDA ARG1+HI + 1216 0570 ORA ARG2+HI + 1218 4C1E11 JMP VEXIT + + 121B ; ---- + 121B ; BXOR + 121B ; ---- + + 121B ; RETURN [ARG1] "XOR" [ARG2] + + 121B A56D GBXOR: LDA ARG1+LO + 121D 456F EOR ARG2+LO + 121F AA TAX + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 47 +--- 2-OPS --- + + 1220 A56E LDA ARG1+HI + 1222 4570 EOR ARG2+HI + 1224 4C1E11 JMP VEXIT + + 1227 ; ----- + 1227 ; BITS? + 1227 ; ----- + + 1227 ; IS EVERY "ON" BIT IN [ARG1] ALSO "ON" IN [ARG2]? + + 1227 A56F GBITSP: LDA ARG2+LO + 1229 256D AND ARG1+LO + 122B C56F CMP ARG2+LO + 122D D033 BNE PBAD + 122F A570 LDA ARG2+HI + 1231 256E AND ARG1+HI + 1233 C570 CMP ARG2+HI + 1235 D02B BNE PBAD + 1237 F026 BEQ PGOOD + + 1239 ; ------ + 1239 ; EQUAL? + 1239 ; ------ + + 1239 ; DOES [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? + + 1239 C66C GEQP: DEC NARGS ; ZERO-ALIGN ARGUMENT COUNT + 123B A66D LDX ARG1+LO ; FETCH LSB AND + 123D A56E LDA ARG1+HI ; MSB OF [ARG1] + + 123F E46F CPX ARG2+LO ; LSB OF [ARG2] MATCHED? + 1241 D004 BNE EQP1 ; NO, TRY NEXT ARG + 1243 C570 CMP ARG2+HI ; MSBS MATCH? + 1245 F018 BEQ PGOOD ; HOORAY! + + 1247 C66C EQP1: DEC NARGS ; OUT OF ARGS YET? + 1249 F017 BEQ PBAD ; IF SO, SCRAM + + 124B E471 CPX ARG3+LO ; ELSE CHECK [ARG3] + 124D D004 BNE EQP2 + 124F C572 CMP ARG3+HI + 1251 F00C BEQ PGOOD + + 1253 C66C EQP2: DEC NARGS ; ANOTHER ARG? + 1255 F00B BEQ PBAD ; NO, EXIT + + 1257 E473 CPX ARG4+LO ; ELSE CHECK [ARG4] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 48 +--- 2-OPS --- + + 1259 D007 BNE PBAD + 125B C574 CMP ARG4+HI + 125D D003 BNE PBAD + + 125F 4CAE0F PGOOD: JMP PREDS + + 1262 4CA20F PBAD: JMP PREDF + + 1265 ; ----- + 1265 ; LESS? + 1265 ; ----- + + 1265 ; IS [ARG1] < [ARG2]? + + 1265 201210 GLESSP: JSR A12VAL ; MOVE [ARG1] INTO [VALUE] + 1268 4C6E12 JMP DLS0 + + 126B ; ------ + 126B ; DLESS? + 126B ; ------ + + 126B ; DECREMENT [ARG1]; SUCCEED IF < [ARG2] + + 126B 20B810 GDLESP: JSR GDEC + + 126E A56F DLS0: LDA ARG2+LO ; MOVE [ARG2] + 1270 857A STA I+LO ; INTO [I] + 1272 A570 LDA ARG2+HI + 1274 857B STA I+HI + + 1276 4C9712 JMP COMPAR ; [ARG1]-1 IS ALREADY IN [VALUE] + + 1279 ; ----- + 1279 ; GRTR? + 1279 ; ----- + + 1279 ; IS [ARG1] > [ARG2]? + + 1279 A56D GGRTRP: LDA ARG1+LO ; MOVE [ARG1] + 127B 857A STA I+LO ; INTO [I] + 127D A56E LDA ARG1+HI + 127F 857B STA I+HI + 1281 4C8F12 JMP A2VAL + + 1284 ; ------ + 1284 ; IGRTR? + 1284 ; ------ + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 49 +--- 2-OPS --- + + + 1284 ; INCREMENT [ARG1]; SUCCEED IF > [ARG2] + + 1284 20AD10 GIGRTP: JSR GINC + + 1287 A578 LDA VALUE+LO ; MOVE [ARG1]-1 + 1289 857A STA I+LO ; INTO [I] + 128B A579 LDA VALUE+HI + 128D 857B STA I+HI + + 128F A56F A2VAL: LDA ARG2+LO ; MOVE [ARG2] + 1291 8578 STA VALUE+LO ; INTO [VALUE] + 1293 A570 LDA ARG2+HI + 1295 8579 STA VALUE+HI + + 1297 209E12 COMPAR: JSR SCOMP ; SIGNED COMPARE + 129A 90C3 BCC PGOOD + 129C B0C4 BCS PBAD + + 129E ; ------------------------------- + 129E ; SIGNED COMPARE OF [VALUE] & [I] + 129E ; ------------------------------- + + 129E A57B SCOMP: LDA I+HI + 12A0 4579 EOR VALUE+HI + 12A2 1005 BPL SCMP + 12A4 A57B LDA I+HI + 12A6 C579 CMP VALUE+HI + 12A8 60 RTS + + 12A9 A579 SCMP: LDA VALUE+HI + 12AB C57B CMP I+HI + 12AD D004 BNE SCEX + 12AF A578 LDA VALUE+LO + 12B1 C57A CMP I+LO + 12B3 60 SCEX: RTS + + 12B4 ; --- + 12B4 ; SET + 12B4 ; --- + + 12B4 ; SET VARIABLE [ARG1] EQUAL TO [ARG2] + + 12B4 A56F GSET: LDA ARG2+LO ; MOVE [ARG2] + 12B6 8578 STA VALUE ; INTO [VALUE] + 12B8 A570 LDA ARG2+HI + 12BA 8579 STA VALUE+HI + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 50 +--- 2-OPS --- + + + 12BC A56D LDA ARG1+LO ; GET VARIABLE ID + 12BE 4C550F JMP VARPUT ; AND SET THE VALUE + + 12C1 ; --- + 12C1 ; GET + 12C1 ; --- + + 12C1 ; RETURN ITEM [ARG2] IN WORD-TABLE [ARG1] + + 12C1 20E512 GGET: JSR CALCW ; V-ADDR OF WORD IN [VPC] + ;*** + 12C4 A900 LDA #00 + 12C6 8588 STA VPC0 + ;*** + 12C8 20251B JSR GETBYT ; GET MSB OF VALUE + 12CB 8579 DOGET: STA VALUE+HI + 12CD 20251B JSR GETBYT ; AND LSB + 12D0 8578 STA VALUE+LO + 12D2 4C660F JMP PUTVAL + + 12D5 ; ---- + 12D5 ; GETB + 12D5 ; ---- + + 12D5 ; RETURN ITEM [ARG2] IN BYTE-TABLE [ARG1] + + 12D5 20DC12 GGETB: JSR CALCB ; V-ADDR OF BYTE IN [VPC] + 12D8 A900 LDA #0 ; MSB WILL BE ZERO + 12DA F0EF BEQ DOGET + + 12DC ; -------------------- + 12DC ; CALC TABLE ADDRESSES + 12DC ; -------------------- + + ;CALCW: ASL ARG2+LO ; WORD-ALIGN TABLE INDEX + ; ROL ARG2+HI + ; + + ;*** + 12DC 4670 CALCB: LSR ARG2+HI ; BYTE-ALIGN TABLE INDEX + 12DE 666F ROR ARG2+LO + 12E0 A900 LDA #00 + 12E2 2A ROL A ; PUT CARRY IN A + 12E3 8588 STA VPC0 + ;*** + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 51 +--- 2-OPS --- + + ;CALCB: LDA ARG2+LO ; CALC LSB OF V-ADDRESS + + ;*** + 12E5 A56F CALCW: LDA ARG2+LO ; CALC LSB OF V-ADDRESS + 12E7 18 CLC + 12E8 656D ADC ARG1+LO + 12EA 8586 STA VPCL + 12EC A570 LDA ARG2+HI ; ALSO CALC MSB + 12EE 656E ADC ARG1+HI + 12F0 8587 STA VPCH + + 12F2 A900 LDA #0 + 12F4 8589 STA VPCFLG ; INVALIDATE [VPC] + 12F6 60 RTS + + END + INCLUD OPSX.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 52 +--- X-OPS --- + + + 12F7 ; ---- + 12F7 ; CALL + 12F7 ; ---- + + 12F7 ; ENTRY: [NARGS] = 0 + + 12F7 A20F GCALL: LDX #15 ; FILL THE ARG-TYPE LIST + 12F9 A9C0 LDA #%11000000 ; WITH "NO MORE ARGS" BYTES + 12FB 9DC00A GCL: STA CTYPES,X + 12FE CA DEX + 12FF 10FA BPL GCL + + 1301 A904 LDA #4 + 1303 8576 STA ADEX ; INIT BYTE INDEX + 1305 8577 STA ADEX2 ; AND ARG BYTE COUNTER + + 1307 20D21A GCL0: JSR NEXTPC ; GRAB AN ARGUMENT BYTE + 130A 8575 STA ABYTE ; SAVE IT HERE + 130C 4C1513 JMP GCL2 ; SKIP OVER 1ST SHIFT + + 130F A575 GCL1: LDA ABYTE + 1311 0A ASL A + 1312 0A ASL A + 1313 8575 STA ABYTE + + 1315 29C0 GCL2: AND #%11000000 ; MASK GARBAGE + 1317 C9C0 CMP #%11000000 ; LAST ARGUMENT? + 1319 F013 BEQ GCL3 ; YES, TIME TO DECODE ARGS + + 131B A66C LDX NARGS ; ELSE ADD THIS ARGUMENT + 131D 9DC00A STA CTYPES,X ; TO THE ARG-TYPE LIST + 1320 E66C INC NARGS ; UPDATE # ARGUMENTS + + 1322 C676 DEC ADEX ; THIS ARG BYTE EMPTY? + 1324 D0E9 BNE GCL1 ; NO, GET NEXT ARG + + 1326 A904 LDA #4 ; ELSE RESET + 1328 8576 STA ADEX ; ARGUMENT INDEX + 132A C677 DEC ADEX2 ; DONE 4 ARG BYTES? + 132C D0D9 BNE GCL0 ; NO, GET ANOTHER + + 132E ; [CTYPES] HAS LIST OF ARG TYPES + 132E ; [NARGS] HAS # ARGUMENTS + + 132E A900 GCL3: LDA #0 ; RESET THE + 1330 8576 STA ADEX ; ARGUMENT INDEX + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 53 +--- X-OPS --- + + 1332 8577 STA ADEX2 ; AND STORAGE INDEX + + 1334 A56C LDA NARGS ; CONTINUE ONLY IF + 1336 D005 BNE GCL4 ; [NARGS] <> 0 + + 1338 ; *** ERROR #12: NO CALL ADDRESS *** + + 1338 A90C LDA #12 + 133A 4C5F1C JMP GERROR + + 133D A676 GCL4: LDX ADEX ; GET ARG INDEX + 133F E46C CPX NARGS ; OUT OF ARGS YET? + 1341 F02C BEQ GCL8 ; YES IF [X] = [NARGS] + + 1343 E676 INC ADEX ; ELSE UPDATE THE INDEX + 1345 BDC00A LDA CTYPES,X ; GET A TYPE BYTE + 1348 D006 BNE GCL5 + 134A 20EE0E JSR GETLNG ; 00 = LONG IMMEDIATE + 134D 4C5D13 JMP GCL7 + + 1350 C940 GCL5: CMP #%01000000 + 1352 D006 BNE GCL6 + 1354 20EA0E JSR GETSHT ; 01 = SHORT IMMEDIATE + 1357 4C5D13 JMP GCL7 + + 135A 20020F GCL6: JSR GETVAR ; ELSE GET VARIABLE + + 135D ; ARGUMENT IS NOW IN [VALUE] + + 135D A677 GCL7: LDX ADEX2 ; GET STORAGE INDEX + 135F A578 LDA VALUE+LO ; MOVE LSB OF VALUE + 1361 9DA00A STA CARGS,X ; INTO [CARGS] + 1364 A579 LDA VALUE+HI ; ALSO MOVE + 1366 9DA10A STA CARGS+1,X ; MSB + + 1369 E8 INX + 136A E8 INX ; UPDATE THE + 136B 8677 STX ADEX2 ; STORAGE INDEX + 136D D0CE BNE GCL4 ; LOOP BACK FOR ANOTHER ARGUMENT + + 136F ; ARGUMENTS IN [CARGS], # ARGUMENTS IN [NARGS] + + 136F ADA00A GCL8: LDA CARGS+LO ; IS CALL ADDRESS + 1372 0DA10A ORA CARGS+HI ; ZERO? + 1375 D003 BNE DOCALL ; NO, CONTINUE + + 1377 4C600F JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 54 +--- X-OPS --- + + + 137A A68F DOCALL: LDX OLDGSP ; SAVE [OLDGSP] + 137C 8A TXA + 137D 20420F JSR PSHXA + + 1380 A680 LDX GPCL ; AND [GPC] + 1382 A581 LDA GPCH + 1384 20420F JSR PSHXA + + ;*** + 1387 A682 LDX GPC0 + 1389 20420F JSR PSHXA + ;*** + + + 138C ADA00A LDA CARGS+LO ; RESET [GPC] + 138F 8580 STA GPCL + 1391 ADA10A LDA CARGS+HI + 1394 8581 STA GPCH + 1396 A900 LDA #0 + + ;*** + 1398 8582 STA GPC0 ; ALL FUNCTIONS START ON WORD BOUNDRIES + ;*** + + 139A 8583 STA GPCFLG ; AND ANNOUNCE CHANGE + + 139C 20D21A JSR NEXTPC ; GET # LOCALS IN FUNCTION + 139F 8576 STA ADEX ; SAVE HERE FOR REFERENCE + 13A1 8577 STA ADEX2 ; AND HERE FOR COUNTING + 13A3 F027 BEQ CALL2 ; IF ZERO, JUMP AHEAD + + 13A5 A900 LDA #0 + 13A7 857C STA J+LO ; INIT LOOP INDEX + + 13A9 A47C CALL1: LDY J+LO + 13AB BE800A LDX LOCALS,Y ; GET LSB OF LOCAL INTO [X] + 13AE B9810A LDA LOCALS+1,Y ; GET MSB INTO [A] + 13B1 20420F JSR PSHXA ; PUSH [X/A] + + 13B4 20D21A JSR NEXTPC ; GET MSB OF NEW LOCAL + 13B7 A47C LDY J+LO + 13B9 99810A STA LOCALS+1,Y ; MOVE MSB TO [LOCALS] + + 13BC 20D21A JSR NEXTPC ; GET LSB OF NEW LOCAL + 13BF A47C LDY J+LO + 13C1 99800A STA LOCALS,Y ; STORE LSB + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 55 +--- X-OPS --- + + + 13C4 C8 INY + 13C5 C8 INY + 13C6 847C STY J+LO ; UPDATE STORAGE INDEX + + 13C8 C677 DEC ADEX2 ; ANY MORE LOCALS? + 13CA D0DD BNE CALL1 ; YES, LOOP BACK + + 13CC C66C CALL2: DEC NARGS ; ANY ARGS LEFT? + 13CE F014 BEQ CALL4 ; NO, SCRAM NOW + + 13D0 ; PASS UP TO 15 [CARGS] TO [LOCALS] + + 13D0 A200 LDX #0 ; INIT LOOP INDEX + + 13D2 BDA20A CALL3: LDA CARGS+2,X ; GET LSB OF ARGUMENT + 13D5 9D800A STA LOCALS,X ; ASSIGN TO A LOCAL + 13D8 BDA30A LDA CARGS+3,X ; SAME FOR + 13DB 9D810A STA LOCALS+1,X ; MSB + + 13DE E8 INX ; POINT TO THE + 13DF E8 INX ; NEXT ENTRIES + + 13E0 C66C DEC NARGS ; OUT OF ARGS YET? + 13E2 D0EE BNE CALL3 ; NO, KEEP LOOPING + + 13E4 ; PUSH # LOCALS + + 13E4 A676 CALL4: LDX ADEX ; # LOCALS KEPT HERE + 13E6 8A TXA + 13E7 20420F JSR PSHXA + + 13EA A58E LDA GSP ; REMEMBER WHERE WE ARE + 13EC 858F STA OLDGSP + + 13EE 4CCF0D JMP MLOOP ; BACK TO MAIN LOOP + + 13F1 ; --- + 13F1 ; PUT + 13F1 ; --- + + 13F1 ; SET ITEM [ARG2] IN WORD-TABLE [ARG1] EQUAL TO [ARG3] + + ;GPUT: ASL ARG2+LO ; WORD-ALIGN + ; ROL ARG2+HI ; [ARG2] + ; JSR PCALC + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 56 +--- X-OPS --- + + ;*** + 13F1 18 GPUT: CLC + + + 13F2 200914 JSR PCALC ; GET ADDRESS INTO [I] + ;*** + + + 13F5 A572 LDA ARG3+HI + 13F7 917A STA (I),Y ; [Y] = 0 + 13F9 C8 INY + 13FA D008 BNE PUTLSB ; BRANCH ALWAYS + + 13FC ; ---- + 13FC ; PUTB + 13FC ; ---- + + 13FC ; SET ITEM [ARG2] IN BYTE-TABLE [ARG1] EQUAL TO [ARG3] + + ;GPUTB: JSR PCALC + + ;*** + 13FC 18 GPUTB: CLC + + 13FD 4670 LSR ARG2+HI ; DIVIDE BY TWO TO ADJUST FOR BYTE POINTING + 13FF 666F ROR ARG2+LO ; LEAVE BIT 0 IN CARRY FOR PCALC + 1401 200914 JSR PCALC + ;*** + + 1404 A571 PUTLSB: LDA ARG3+LO + 1406 917A STA (I),Y + 1408 60 RTS + + 1409 ; ------------------ + 1409 ; CALC "PUT" ADDRESS + 1409 ; ------------------ + + 1409 A000 PCALC: LDY #0 ; FOR INDEXING + + ;*** + 140B 9001 BCC PCALC1 ; TAKE CARE OF CARRY FROM GPUTB + 140D C8 INY + ;*** + 140E A56F PCALC1: LDA ARG2+LO ; ADD ITEM OFFSET + 1410 18 CLC ; TO TABLE ADDRESS + 1411 656D ADC ARG1+LO ; FIRST LSB + 1413 857A STA I+LO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 57 +--- X-OPS --- + + + 1415 A570 LDA ARG2+HI ; THEN MSB + 1417 656E ADC ARG1+HI + + 1419 C593 ICENT: CMP GPURE ; IS CODE IN G-PRELOAD? (ENTRY FOR ICALC) + 141B 9014 BCC USEGP ; YES, OK TO CHANGE + + 141D C594 CMP ISTART ; IS IT BELOW THE I-FILE? + 141F 9019 BCC PURERR ; CAN'T CHANGE PURE CODE! + + 1421 C595 CMP IPURE ; IS IT ABOVE THE I-PRELOAD? + 1423 B015 BCS PURERR ; YES, UNCHANGEABLE! + + 1425 ; POINT TO BYTE IN I-PRELOAD + + 1425 38 SEC + 1426 E594 SBC ISTART ; STRIP OF V-OFFSET + + ;*** + 1428 067A ASL I+LO ; *2 + 142A 2A ROL A + 142B **** + + 142B 18 CLC + 142C 6592 ADC ICODE+HI ; MAKE IT ABSOLUTE + 142E 857B STA I+HI + + ;*** + 1430 60 PCALC2: RTS + + ;*** + + ; RTS + + 1431 ; POINT TO BYTE IN G-PRELOAD + ;*** + 1431 067A USEGP: ASL I+LO ; * 2 FOR 512 BYTE PAGES + 1433 2A ROL A + ;*** + 1434 18 CLC + 1435 6590 ADC GCODE ; CALC ABSOLUTE ADDR + 1437 857B STA I+HI ; IN G-PRELOAD + 1439 60 RTS + + 143A ; *** ERROR #9: PURITY VIOLATION *** + + 143A A909 PURERR: LDA #9 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 58 +--- X-OPS --- + + 143C 4C5F1C JMP GERROR + + 143F ; ------ + 143F ; RANDOM + 143F ; ------ + + 143F ; RETURN A RANDOM VALUE BETWEEN 1 AND [ARG1] + + 143F A56D GRAND: LDA ARG1+LO ; MAKE [ARG1] + 1441 856F STA ARG2+LO ; A DIVISOR + 1443 A56E LDA ARG1+HI + 1445 8570 STA ARG2+HI + + 1447 200A1D JSR DORAND ; GET RANDOM BYTES + 144A 866D STX ARG1+LO ; INTO [A] & [X] + 144C 297F AND #%01111111 ; MAKE IT A POSITIVE + 144E 856E STA ARG1+HI ; DIVIDEND + + 1450 207711 JSR DIVIDE ; SIGNED DIVISION + + 1453 A5A6 LDA REMAIN+LO ; GRAB THE REMAINDER + 1455 8578 STA VALUE+LO + 1457 A5A7 LDA REMAIN+HI + 1459 8579 STA VALUE+HI + + 145B 20FF0F JSR INCVAL ; INCREMENT IT + 145E 4C660F JMP PUTVAL ; AND RETURN THE RESULT + + + 1461 ;------------------------------------- + 1461 ; GITER: INITIALIZE ITERATION TABLE AT + 1461 ; WORD-ADDRESS ARG1 + 1461 ;------------------------------------- + + 1461 A900 GITER: LDA #00 ; SET ARG4=0 FOR ICALC + 1463 8573 STA ARG4+LO + 1465 8574 STA ARG4+HI + + 1467 A56E LDA ARG1+HI ; MOVE ARG1 TO ARG3 + 1469 8572 STA ARG3+HI + 146B A56D LDA ARG1+LO + 146D 8571 STA ARG3+LO + 146F 208918 JSR ICALC ; THIS WILL ALSO CHECK PURITY VIOLATIONS + + 1472 B17A LDA (I),Y ; GET NUMBER OF ENTRIES IN TABLE + 1474 85BE STA ITICN + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 59 +--- X-OPS --- + + 1476 C8 INY + 1477 98 TYA ; INIT ICOUNT Y=1 A=1 + 1478 917A STA (I),Y + + 147A E673 INC ARG4+LO ; POINT TO FIRST WORD OF FIRST ENTRY + + 147C 208918 GITER1: JSR ICALC + 147F B17A LDA (I),Y ; HIGH BYTE OF ICON ADDRESS + 1481 48 PHA ; SAVE + 1482 C8 INY ; =1 + 1483 B17A LDA (I),Y ; LOWBYTE OF ADDRESS + 1485 AA TAX + 1486 68 PLA + 1487 20361A JSR GETI ; GET ICON INFORMATION + + 148A A900 LDA #0 + 148C A006 LDY #6 + 148E 917A STA (I),Y ; SET NEGATE FOR POSITIVE DISPLAY + 1490 C8 INY ; =7 + 1491 A901 LDA #1 + 1493 917A STA (I),Y ; SET FIRST ITERATION=1 + + 1495 C8 INY ; =8 + 1496 A5CF LDA BSET + 1498 917A STA (I),Y ; SAVE BSET + 149A C8 INY ; =9 + 149B A5BD LDA ITERS + 149D 917A STA (I),Y ; SAVE # OF ITERS + + 149F C8 INY ; =10 + 14A0 A5B5 LDA IX1 + 14A2 917A STA (I),Y ; SAVE ICON WIDTH + 14A4 C8 INY ; =11 + 14A5 A5B7 LDA IY1 + 14A7 917A STA (I),Y ; SAVE ICON HEIGHTH + + 14A9 207D18 JSR NXTENT + 14AC C6BE DEC ITICN + 14AE D0CC BNE GITER1 + 14B0 60 RTS + + + 14B1 ;------------------------ + 14B1 ; GDUMP : NOT IMPLIMENTED + 14B1 ; RETURN 0 + 14B1 ;------------------------ + 14B1 4C5E0F GDUMP: JMP RET0 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 60 +--- X-OPS --- + + + 14B4 ;------------------------- + 14B4 ; GLOAD : NOT IMPLIMENTED + 14B4 ; RETURN 0 + 14B4 ;------------------------ + 14B4 4C5E0F GLOAD: JMP RET0 + + END + INCLUD IO.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 61 +--- I/O ROUTINES --- + + + 14B7 ; ----- + 14B7 ; SHOWN + 14B7 ; ----- + + 14B7 ; DISPLAY NEGATIVE ICON [ARG3] AT X=[ARG1], Y=[ARG2] + 14B7 ; IF [ARG4] IS GIVEN IT POINTS TO THE MASK TO BE USED + + + 14B7 A9FF GSHOWN: LDA #$FF + 14B9 85E9 STA NEGATE ; SET NEGATE FLAG + 14BB D004 BNE SHOWI ; AND DO A "SHOWI" + + 14BD ; ----- + 14BD ; SHOWI + 14BD ; ----- + + 14BD ; DISPLAY ICON [ARG3] AT X=[ARG1], Y=[ARG2] + 14BD ; IF [ARG4] IS GIVEN IT POINTS TO THE MASK TO BE USED + + 14BD A900 GSHOWI: LDA #0 + 14BF 85E9 STA NEGATE ; DISABLE NEGATE + + 14C1 ; ****************NEW ROUTINE******************** + 14C1 A900 SHOWI: LDA #0 + 14C3 85E3 STA MSKFLG ; DISABLE MASKING UNTIL FURTHER NOTICE + 14C5 A56C LDA NARGS + 14C7 C903 CMP #3 + 14C9 F019 BEQ NOMASK ; DO THE NORMAL THING + + 14CB A673 LDX ARG4+LO ; GET MASK INFO + 14CD A574 LDA ARG4+HI + 14CF 201B1A JSR ISU ; THIS ENTRY INTO [ISETUP] WILL PUT + 14D2 ; THE DATA FOR ICON [ARG4] INTO + 14D2 ; IX2,IY2,IADR2 ETC. + 14D2 ; AND RETURN WITH DATA FROM ICON [ARG3] + 14D2 ; IN IX1,IY1 ETC. + 14D2 ; * NOTE IT WILL NOT DETECT DIFFERENT * + 14D2 ; * BLOCKSETS IT USES THE BSET FROM * + 14D2 ; * [ARG3] * + 14D2 A5B5 LDA IX1 + 14D4 C5B6 CMP IX2 ; IF THE WIDTH AND HEIGHT ARE NOT + 14D6 D02E BNE DRAWEX ; DO NOTHING + 14D8 A5B7 LDA IY1 + 14DA C5B8 CMP IY2 + 14DC D028 BNE DRAWEX + 14DE A9FF LDA #$FF ; SET MASK FLAG + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 62 +--- I/O ROUTINES --- + + 14E0 85E3 STA MSKFLG + 14E2 D007 BNE ITENT ; GOTO RIGHT PLACE + + 14E4 A671 NOMASK: LDX ARG3+LO ; SET UP + 14E6 A572 LDA ARG3+HI ; BSET, ITERS, IX1, IY1, IADR1+LO, IADR1+HI + 14E8 20361A JSR GETI + + 14EB A900 ITENT: LDA #0 + 14ED 85C4 STA TOPCUT ; ZERO THIS + 14EF 85AE STA MUH ; THIS TOO + 14F1 85C5 STA SIDCUT ; AND THIS + + ; STA MDYCUT ; AND THIS + + 14F3 85C7 STA MDXCUT ; AND THIS + + + 14F5 A66F LDX ARG2+LO ; ICON Y1 POS LO + 14F7 A570 LDA ARG2+HI + 14F9 F01B BEQ DRAWI1 ; ICON STARTS ON WINDOW PAGE (YPOS= 00 XX) + + 14FB C9FF CMP #$FF + 14FD D007 BNE DRAWEX ; ICON WILL NOT BE DISPLAYED + + 14FF ;STARTS ON PAGE BEFORE WINDOW PAGE + + 14FF 8A TXA ; PUT LO YPOS IN + 1500 49FF EOR #$FF ; C=1 FROM CMP #$FF + 1502 65CA ADC WINDY1 ; FIND DISTANCE FROM ICON Y1-> WINDOW Y1 + 1504 9017 BCC DRAWI2 + 1506 ; FALL THRU DISTANCE > MAX SIZE OF 255 + + 1506 60 DRAWEX: RTS ; GENERAL PURPOUS EXIT FROM DRAW ICON + + 1507 A5CC DRAWI3: LDA WINDY2 ; * [WINDY2] IS ONE GREATER THAN LAST * + 1509 38 SEC ; * LINE OF WINDOW TO DISPLAY * + 150A E56F SBC ARG2+LO ; * IF THIS MAKES A DIFFERANCE TAKE * + 150C 90F8 BCC DRAWEX ; AMOUNT TO CUT FROM ROWS DISPLAYED + 150E C5B7 CMP IY1 ; * THE SEC MIGHT FIX * + 1510 B00D BCS DRAWI4 + 1512 85B7 STA IY1 ; EXIT WHEN ICON STARTS BELOW WINDOW + 1514 9009 BCC DRAWI4 + + 1516 ; THE ABOVE SECTION OCCURS IF THE ICON STARTS INDSIDE THE WINDOW + 1516 ; AND FINDS THE NUMBER ROWS TO DRAW + + 1516 38 DRAWI1: SEC ; ICON ON ZERO PAGE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 63 +--- I/O ROUTINES --- + + 1517 A5CA LDA WINDY1 + 1519 E56F SBC ARG2+LO ; FIND (WINDY1-ICONY1) + 151B 90EA BCC DRAWI3 ; IF NEGATIVE ICON STARTS AFTER WINDOW Y1 + 151D 85C4 DRAWI2: STA TOPCUT ; OTHERWISE CUT THIS AMOUNT FROM TOP OF ICON + + 151F A5B7 DRAWI4: LDA IY1 ; HEIGHT OF ICON + 1521 38 SEC + 1522 E5C4 SBC TOPCUT ; DO CUT + 1524 F0E0 BEQ DRAWEX + 1526 90DE BCC DRAWEX ; NO ICON LEFT TO DRAW. GOOD BYE + + 1528 85BB STA YDEX1 ; *** NEED TO USE OTHER NAME???? *** + 152A E5CD SBC WINDH ; *(+-1) SET IN WINDSET (HEIGHT OF WINDOW) + 152C 9004 BCC DRAWI5 ; ICON SMALLER THAN WINDOW (DISPLAY ALL) + + 152E A5CD LDA WINDH ; DISPLAY A WINDOWS WORTH OF ICON + 1530 85BB STA YDEX1 + + + 1532 ; MULTIPLY TOPCUT AND ICON WIDTH, ADD TO ICON POINTER TO POINT + 1532 ; AT FIRST DISPLAYED ROW BLOCK + + 1532 A5C4 DRAWI5: LDA TOPCUT ; * NOT NEEDED IF NOT CHANGED LATER * + 1534 85AC STA MUSHFT ; * JUST USE TOPCUT * + + 1536 18 CLC + 1537 656F ADC ARG2+LO ; CHANGE STARY YPOS OF ICON TO REFLECT + 1539 85C2 STA YPOS+LO ; TOPCUT + + 153B A007 LDY #7 ; SHIFT COUNTER + 153D A6B5 LDX IX1 ; WIDTH COEFICIANT + 153F CA DEX ; LESS ONE SO ADC C=0 SAME AS ADC C=1 + 1540 8A DRAWI6: TXA ; GET IX1 BACK IN FOR ADD + 1541 46AC LSR MUSHFT ; SHIFT BIT 0 INTO + 1543 9004 BCC DRAWI7 ; C=0 SAME AS ADDING 0 + 1545 65AE ADC MUH + 1547 85AE STA MUH ; ADD IXA TO TOTAL + 1549 66AE DRAWI7: ROR MUH ; MUTIPLY BY 2 + 154B 66AD ROR MUL + 154D 88 DEY + 154E 10F0 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 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 64 +--- I/O ROUTINES --- + + ; ADC MUH + ; STA IADR1+HI + + ;*** + 1550 A5AE LDA MUH + 1552 A6AD LDX MUL + 1554 202F19 JSR ADDIA1 + + 1557 A5E3 LDA MSKFLG ; IF MASK ENABLED + 1559 F005 BEQ NOMSK1 + 155B A5AE LDA MUH ; X IS STILL MUL + 155D 200619 JSR ADDIA2 + ;*** + + 1560 ; COMPUTE THE DISPLAYED WIDTH AND THE IXSKIP + + 1560 A5B5 NOMSK1: LDA IX1 ; KLUDGE + 1562 85C7 STA MDXCUT + + 1564 A66D LDX ARG1+LO ; ICON X CORDINATE + 1566 A56E LDA ARG1+HI + 1568 F01B BEQ DRAWI8 ; ICON STARTS ON WINDOW PAGE (XPOS= 00 XX) + + 156A C9FF CMP #$FF + 156C D007 BNE DRAWE2 ; ICON WILL NOT BE DISPLAYED + + 156E ; STARTS ON PAGE BEFORE WINDOW PAGE + + 156E 8A TXA ; PUT LO XPOS IN + 156F 49FF EOR #$FF ; C=1 FROM CMP #$FF + 1571 65C9 ADC WINDX1 ; FIND DISTANCE FROM ICON X1-> WINDOW X1 + 1573 9017 BCC DRAWI9 + 1575 ; FALL THRU DISTANCE > MAX ICON SIZE OF 255 + + 1575 60 DRAWE2: RTS ; AN EXIT FROM DRAW ICON + + 1576 A5CB DRAWIA: LDA WINDX2 ; ICON STARTS INSIDE WINDOW + 1578 38 SEC + 1579 E56D SBC ARG1+LO ; CHECK IF ICON STARTS TO RIGHT OF WINDOW + 157B 90F8 BCC DRAWE2 ; FOR LATER + 157D C5B5 CMP IX1 + 157F B00D BCS DRAWIB + 1581 85B5 STA IX1 ; STARTS TO RIGHT DON T BOTHER + 1583 9009 BCC DRAWIB + + 1585 A5C9 DRAWI8: LDA WINDX1 ; ICON STARTS ON ZERO PAGE + 1587 38 SEC + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 65 +--- I/O ROUTINES --- + + 1588 E56D SBC ARG1+LO ; FIND (WINDX2-ICONX1) + 158A 90EA BCC DRAWIA ; IF NEGATIVE ICON STARTS AFTER WINDOW X1 + 158C 85C5 DRAWI9: STA SIDCUT ; OTHERWISE CUT THIS FROF LEFT OF ICON + + 158E A5B5 DRAWIB: LDA IX1 ; WIDTH OF ICON + 1590 38 SEC + 1591 E5C5 SBC SIDCUT ; DO CUT + 1593 F0E0 BEQ DRAWE2 + 1595 90DE BCC DRAWE2 ; NO ICON TO DRAW BYE BYE + + 1597 85B9 STA XDEX1 + 1599 E5CE SBC WINDW ; IF ICON SMALLER THAN WINDOW DISPLAY ALL + 159B 9004 BCC DRAWIC + + 159D A5CE LDA WINDW ; OTHERWISE DISPLAY WINDOW WIDTH OF ICON + 159F 85B9 STA XDEX1 + + ;DRAWIC: LDA IADR1+LO + ; CLC + ; ADC SIDCUT + ; STA IADR1+LO + ; BCC DRAWID + ; INC IADR1+HI + + ;*** + 15A1 A900 DRAWIC: LDA #00 + 15A3 A6C5 LDX SIDCUT + 15A5 202F19 JSR ADDIA1 + ;*** + 15A8 A5E3 LDA MSKFLG ; IS MASK ENABLED + 15AA F005 BEQ DRAWID + 15AC A900 LDA #00 ; X IS STILL SIDCUT + 15AE 200619 JSR ADDIA2 + + + 15B1 A5C7 DRAWID: LDA MDXCUT + 15B3 38 SEC + 15B4 E5B9 SBC XDEX1 + 15B6 85C6 STA IXSKIP + + 15B8 A5B9 LDA XDEX1 + 15BA 85B5 STA IX1 ; SET THE COUNTER REFRESH VALUE + + 15BC A56D LDA ARG1+LO + 15BE 18 CLC + 15BF 65C5 ADC SIDCUT + 15C1 85C0 STA XPOS+LO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 66 +--- I/O ROUTINES --- + + 15C3 85E5 STA XPSAV+LO + + 15C5 ;************************************** + + 15C5 A5CF LDA BSET ; GET REQUIRED BLOCK SET INTO RAM + 15C7 204919 JSR GETBS + + 15CA A5E3 LDA MSKFLG ; IF ENABLED GO DO THE MASK THING + 15CC D042 BNE DOMASK + + 15CE ; DRAW THE ICON ITERATION AT [IADR1] + + 15CE A5AF DRAW: LDA IADR1+LO ; POINT [VPC] TO NEXT ICON BYTE + 15D0 8586 STA VPCL + 15D2 A5B0 LDA IADR1+HI + 15D4 8587 STA VPCH + ;*** + 15D6 A5B1 LDA IADR10 + 15D8 8588 STA VPC0 + ;*** + + + 15DA A900 LDA #0 + 15DC 8589 STA VPCFLG ; INVALIDATE [VPC] + + 15DE 20251B JSR GETBYT ; GET BLOCK ID INTO [A] + + 15E1 20C019 JSR GETBLK ; GET BLOCK [A] INTO [BLOCK] + 15E4 A6C0 LDX XPOS+LO ; GET SCREEN COORDINATES + 15E6 A5C2 LDA YPOS+LO ; INTO [X] AND [A] + 15E8 20D21D JSR DUMP ; DUMP [BLOCK] AT X=[X], Y=[A] + + 15EB C6B9 DEC XDEX1 ; DEC INDEX OF DISPLAYED WIDTH + 15ED F008 BEQ CLPRI2 ; OUT OF COLUMNS: DO NEXT ROW + + 15EF E6C0 INC XPOS+LO ; INCREMENT X CORDINATE + + ;*** + 15F1 202019 JSR INCIA1 + ;*** + 15F4 4CCE15 JMP DRAW + + + 15F7 A5B5 CLPRI2: LDA IX1 ; REFRESH + 15F9 85B9 STA XDEX1 ; X-COUNT + + 15FB A5E5 LDA XPSAV+LO ; RESET X-POS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 67 +--- I/O ROUTINES --- + + 15FD 85C0 STA XPOS+LO + ;*** + 15FF A900 LDA #0 + 1601 A6C6 LDX IXSKIP + 1603 202F19 JSR ADDIA1 + 1606 202019 JSR INCIA1 + ;*** + + 1609 E6C2 INC YPOS+LO ; INCREMENT + 160B C6BB DEC YDEX1 ; OUT OF Y'S YET? + 160D D0BF BNE DRAW ; NO, KEEP DUMPING + 160F 60 RTS ; TILL EMPTY + + + + + 1610 ; DRAW THE ICON ITERATION AT [IADR1] WITH MASK AT [IADR2] + + 1610 A5B2 DOMASK: LDA IADR2+LO ; POINT [VPC] TO NEXT MASK BYTE + 1612 8586 STA VPCL + 1614 A5B3 LDA IADR2+HI + 1616 8587 STA VPCH + 1618 A5B4 LDA IADR20 + 161A 8588 STA VPC0 + + 161C A5E9 LDA NEGATE ; SAVE NEGATE STATUS + 161E 48 PHA + + 161F A900 LDA #00 + 1621 8589 STA VPCFLG ; INVAL FLAG + 1623 85E9 STA NEGATE ; NEVER NEGATE THE MASK + + 1625 20251B JSR GETBYT ; GET MASK BLOCK + 1628 20C019 JSR GETBLK ; GET MASK INTO [BLOCK] + 162B 207E16 JSR B2MASK ; COPY [BLOCK] INTO [MASK] + + + 162E A5AF LDA IADR1+LO ; POINT [VPC] TO NEXT ICON BYTE + 1630 8586 STA VPCL + 1632 A5B0 LDA IADR1+HI + 1634 8587 STA VPCH + 1636 A5B1 LDA IADR10 + 1638 8588 STA VPC0 + + 163A 68 PLA ; RESTORE THE NEGATE + 163B 85E9 STA NEGATE + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 68 +--- I/O ROUTINES --- + + 163D A900 LDA #0 + 163F 8589 STA VPCFLG ; INVALIDATE [VPC] + + 1641 20251B JSR GETBYT ; GET BLOCK ID INTO [A] + + 1644 20C019 JSR GETBLK ; GET BLOCK [A] INTO [BLOCK] + 1647 A6C0 LDX XPOS+LO ; GET SCREEN COORDINATES + 1649 A5C2 LDA YPOS+LO ; INTO [X] AND [A] + 164B 20F51D JSR DMPMSK ; DRAW [BLOCK] AGAINST [MASK] AT X=[X], Y=[A] + + 164E C6B9 DEC XDEX1 ; DEC INDEX OF DISPLAYED WIDTH + 1650 F00B BEQ CLPRIA ; OUT OF COLUMNS: DO NEXT ROW + + 1652 E6C0 INC XPOS+LO ; INCREMENT X CORDINATE + + ;*** + 1654 202019 JSR INCIA1 + 1657 20F718 JSR INCIA2 + ;*** + 165A 4C1016 JMP DOMASK + + + 165D A5B5 CLPRIA: LDA IX1 ; REFRESH + 165F 85B9 STA XDEX1 ; X-COUNT + + 1661 A5E5 LDA XPSAV+LO ; RESET X-POS + 1663 85C0 STA XPOS+LO + ;*** + 1665 A900 LDA #0 + 1667 A6C6 LDX IXSKIP + 1669 202F19 JSR ADDIA1 + 166C 202019 JSR INCIA1 + 166F A900 LDA #0 + 1671 200619 JSR ADDIA2 + 1674 20F718 JSR INCIA2 + ;*** + + 1677 E6C2 INC YPOS+LO ; INCREMENT + 1679 C6BB DEC YDEX1 ; OUT OF Y'S YET? + 167B D093 BNE DOMASK ; NO, KEEP DUMPING + 167D 60 RTS ; TILL EMPTY + + 167E ; ------ + 167E ; B2MASK + 167E ; ------ + 167E A207 B2MASK: LDX #7 + 1680 B5D3 B2MLP: LDA BLOCK,X + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 69 +--- I/O ROUTINES --- + + 1682 95DB STA MASK,X + 1684 CA DEX + 1685 10F9 BPL B2MLP + 1687 60 RTS + + 1688 ; ---- + 1688 ; SETI + 1688 ; ---- + + 1688 ; COPY ICON [ARG3] INTO ICON [ARG4] WITH + 1688 ; TOP LEFT CORNER AT X=[ARG1], Y=[ARG2]; + 1688 ; RETURN ZERO IF RANGE ERROR, ONE IF OKAY + + 1688 20101A GSETI: JSR ISETUP ; GET STATS OF SOURCE & DEST + 168B 20921A JSR DOFIT ; WILL SOURCE FIT IN DEST? + 168E 9003 BCC SI0 ; CARRY CLEAR IF OKAY + 1690 4C5E0F JMP RET0 ; ELSE RETURN A ZERO + + 1693 ; [IADR2] HAS ABS ADDR OF SUB-ICON + 1693 ; [VPC] POINTS TO 1ST BYTE OF SOURCE ICON + + 1693 A900 SI0: LDA #0 + 1695 857A STA I+LO ; INIT X-ROW POINTER + + 1697 20251B SI1: JSR GETBYT ; GET A BYTE FROM SOURCE + 169A A47A LDY I+LO + 169C 91B2 STA (IADR2),Y ; STORE IN DEST + + 169E E67A INC I+LO ; UPDATE ROW POINTER + + 16A0 C6B9 DEC XDEX1 ; OUT OF SOURCE X'S YET? + 16A2 D0F3 BNE SI1 ; NO, MOVE ANOTHER BYTE + 16A4 A5B5 LDA IX1 ; ELSE REFRESH + 16A6 85B9 STA XDEX1 ; X-COUNT + + 16A8 A5B6 LDA IX2 ; GET X-SIZE OF DEST + 16AA 18 CLC + 16AB 65B2 ADC IADR2+LO ; ADD TO BASE ADDR OF SUB-ICON + 16AD 85B2 STA IADR2+LO ; TO GET ADDR OF NEXT SUB-ROW + 16AF 9002 BCC SI3 + 16B1 E6B3 INC IADR2+HI + + 16B3 C6BB SI3: DEC YDEX1 ; OUT OF Y'S YET? + 16B5 D0DC BNE SI0 ; RESET X-INDEX AND LOOP TILL EMPTY + + 16B7 A901 LDA #1 + 16B9 4C600F JMP PUTBYT ; RETURN A 1 FOR SUCCESS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 70 +--- I/O ROUTINES --- + + + 16BC ; ----- + 16BC ; SWAPI + 16BC ; ----- + + 16BC ; SAME AS "SETI" EXCEPT ICON [ARG4] SUB-DATA IS COPIED + 16BC ; BACK INTO ICON [ARG3] + + 16BC 20101A GSWAPI: JSR ISETUP + 16BF A5B0 LDA IADR1+HI ; MAKE SURE SOURCE ICON + 16C1 C595 CMP IPURE ; IS IN I-PRELOAD + 16C3 9005 BCC GSW0 ; ERROR IF NOT + + 16C5 ; *** ERROR #14: PURITY VIOLATION (SETI/SWAPI) *** + + 16C5 A90E PRERR2: LDA #14 + 16C7 4C5F1C JMP GERROR + + 16CA 20921A GSW0: JSR DOFIT ; WILL SOURCE FIT IN DEST? + 16CD 9003 BCC GSW1 ; CARRY CLEAR IF OKAY + 16CF 4C5E0F JMP RET0 ; ELSE RETURN A ZERO + + 16D2 A5B0 GSW1: LDA IADR1+HI ; MAKE [IADR1] ABSOLUTE + 16D4 38 SEC + 16D5 E594 SBC ISTART ; STRIP OFF VIRTUAL OFFSET + ;*** + 16D7 46B1 LSR IADR10 + 16D9 26AF ROL IADR1+LO + 16DB 2A ROL A + ;*** + 16DC 18 CLC + 16DD 6592 ADC ICODE+HI ; ADD BASE ADDR OF I-PRELOAD + 16DF 85B0 STA IADR1+HI ; LSB NEEDN'T CHANGE + + 16E1 A900 GSW2: LDA #0 ; INIT ROW INDEX + 16E3 857A STA I+LO + + 16E5 A47A GSW3: LDY I+LO ; GET ROW INDEX + 16E7 B1AF LDA (IADR1),Y ; GET BYTE FROM SOURCE ICON + 16E9 857B STA I+HI ; SAVE IT HERE + 16EB B1B2 LDA (IADR2),Y ; GET BYTE FROM DEST ICON + 16ED 91AF STA (IADR1),Y ; MOVE IT TO SOURCE ICON + 16EF A57B LDA I+HI ; RETRIEVE SOURCE BYTE + 16F1 91B2 STA (IADR2),Y ; AND MOVE IT TO DEST ICON + + 16F3 E67A INC I+LO ; UPDATE ROW INDEX + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 71 +--- I/O ROUTINES --- + + 16F5 C6B9 DEC XDEX1 ; OUT OF X'S YET? + 16F7 D0EC BNE GSW3 ; NO, KEEP LOOPING + 16F9 A5B5 LDA IX1 ; ELSE REFRESH X-COUNT + 16FB 85B9 STA XDEX1 + + 16FD A5B6 LDA IX2 ; ADD X-SIZE OF DEST + 16FF 18 CLC ; TO BASE ADDR OF SUB-ICON + 1700 65B2 ADC IADR2+LO ; TO GET ADDR OF NEXT ROW + 1702 85B2 STA IADR2+LO + 1704 9002 BCC GSW4 + 1706 E6B3 INC IADR2+HI + + 1708 A5B5 GSW4: LDA IX1 ; ADD X-SIZE OF SOURCE + 170A 18 CLC ; TO BASE ADDR OF SOURCE + 170B 65AF ADC IADR1+LO ; TO GET ADDR OF NEXT ROW + 170D 85AF STA IADR1+LO + 170F 9002 BCC GSW5 + 1711 E6B0 INC IADR1+HI + + 1713 C6BB GSW5: DEC YDEX1 ; OUT OF Y'S YET? + 1715 D0CA BNE GSW2 ; RESET ROW INDEX & LOOP TILL EMPTY + + 1717 A901 LDA #1 + 1719 4C600F JMP PUTBYT ; RETURN A 1 FOR SUCCESS + + 171C ; ------ + 171C ; WINDOW + 171C ; ------ + + 006D X1 EQU ARG1 + 006F Y1 EQU ARG2 + 0071 X2 EQU ARG3 + 0073 Y2 EQU ARG4 + + 171C A006 GWIND: LDY #6 ; SET INDEX TO DO ALL ARGS + + 171E A200 WILP: LDX #0 ; TO ZERO ARGS LATER + 1720 B96E00 LDA X1+HI,Y ; TEST IF - OR >255 + 1723 F009 BEQ WISK1 ; IF 0 DONT ADJUST GOTO NEXT ARG + 1725 1004 BPL WISK2 ; IF PLUS ADJUST TO 255 + 1727 966D STX X1+LO,Y ; CLIP FROM NEGATIVE TO ZERO + 1729 3003 BMI WISK1 ; BRANCH + 172B CA WISK2: DEX ; [X] = 255 + 172C 966D STX X1+LO,Y ; IF > 255 CLIP TO 255 + 172E 88 WISK1: DEY + 172F 88 DEY ; 2 DEYS FOR NEXT ARG (WORD) + 1730 10EC BPL WILP ; DO Y2-X1 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 72 +--- I/O ROUTINES --- + + + 1732 A227 LDX #39 ; MAXIMUM X-VALUE + 1734 A017 LDY #23 ; MAXIMUM Y-VALUE + + 1736 A56D LDA X1+LO ; CLIP X1 + 1738 C928 CMP #40 + 173A 9002 BCC WISK3 + 173C 866D STX X1+LO + + 173E A571 WISK3: LDA X2+LO ; CLIP X2 + 1740 C928 CMP #40 + 1742 9002 BCC WISK4 + 1744 8671 STX X2+LO + + 1746 A56F WISK4: LDA Y1+LO ; CLIP Y1 + 1748 C918 CMP #24 + 174A 9002 BCC WISK5 + 174C 846F STY Y1+LO + + 174E A573 WISK5: LDA Y2+LO ; CLIP Y2 + 1750 C918 CMP #24 + 1752 9002 BCC WISK6 + 1754 8473 STY Y2+LO + + 1756 ; SWITCH IF NEEDED + + 1756 A66D WISK6: LDX X1+LO + 1758 A471 LDY X2+LO + + 175A E471 CPX X2+LO ; IS X1 > X2? + 175C B006 BCS WISK7 ; BRANCH YES + 175E 86C9 STX WINDX1 ; SET X1 = X1 + 1760 84CB STY WINDX2 ; SET X2 = X2 + 1762 9004 BCC WISK8 ; BRANCH + + 1764 86CB WISK7: STX WINDX2 ; SWAP + 1766 84C9 STY WINDX1 ; X1 AND X2 + + 1768 A66F WISK8: LDX Y1+LO ; GET Y1 AND + 176A A473 LDY Y2+LO ; Y2 + + 176C E473 CPX Y2+LO ; IS Y1 > Y2? + 176E B006 BCS WISK9 ; BRANCH YES + 1770 86CA STX WINDY1 ; SET Y1 = Y1 + 1772 84CC STY WINDY2 ; SET Y2 = Y2 + 1774 9004 BCC WISKA ; BRANCH + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 73 +--- I/O ROUTINES --- + + 1776 86CC WISK9: STX WINDY2 ; SWAP + 1778 84CA STY WINDY1 ; Y1 AND Y2 + + 177A E6CB WISKA: INC WINDX2 ; THIS IS SO A BCC WILL WORK ON CLIP + 177C E6CC INC WINDY2 ; SAME + + 177E A5CC LDA WINDY2 ; COMPUTE HEIGHT + 1780 38 SEC + 1781 E5CA SBC WINDY1 + 1783 85CD STA WINDH + + 1785 A5CB LDA WINDX2 ; COMPUTE WIDTH + 1787 E5C9 SBC WINDX1 ; C=1 FROM ABOVE + 1789 85CE STA WINDW + 178B 60 RTS + + 178C 84AC MULXY STY MUSHFT + 178E A007 LDY #7 + 1790 A900 LDA #0 + 1792 85AE STA MUH + 1794 8A TXA ; TEST 0 + 1795 F012 BEQ MU0 + 1797 CA DEX + 1798 8A MULP1: TXA + 1799 46AC LSR MUSHFT + 179B 9004 BCC MUSK1 + 179D 65AE ADC MUH + 179F 85AE STA MUH + 17A1 66AE MUSK1: ROR MUH + 17A3 66AD ROR MUL + 17A5 88 DEY + 17A6 10F0 BPL MULP1 + 17A8 60 RTS + 17A9 85AD MU0: STA MUL + 17AB 60 RTS + + END + INCLUD ITERS.ASM + + 17AC ;-------------------------------------------- + 17AC ; ITERATIONS + 17AC ; EXECUTE THE ITERATION TABLE AT [ARG2] + 17AC ; TEST FOR INPUT AFTER EACH ENTRY IS DONE AND + 17AC ; ------------------------------------------- + + 17AC A570 ITRATE: LDA ARG2+HI + 17AE 8572 STA ARG3+HI ; POINT ARG3 AT TABLE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 74 +--- ITERATION STUFF --- + + 17B0 A56F LDA ARG2+LO + 17B2 8571 STA ARG3+LO + + 17B4 A900 LDA #00 ; SET OFFSET INTO TABLE=0 + 17B6 8574 STA ARG4+HI + 17B8 8573 STA ARG4+LO + 17BA 208918 JSR ICALC ; POINT [I] AT TABLE + + 17BD B17A LDA (I),Y ; NUMBER OF ENTRIES + 17BF 85BE STA ITICN + 17C1 C8 INY + 17C2 B17A LDA (I),Y ; ENTRY TO START WITH + 17C4 85BF STA ITPNT ; (NORMALLY ENTRY 1) + + 17C6 E673 INC ARG4+LO ; POINT AT FISRT WORD IN FIRST ENTRY + + 17C8 A201 LDX #1 + 17CA E4BF ITLP2: CPX ITPNT ; SKIP ENTRIES 1 TO ITPNT + 17CC F006 BEQ ITLOOP + 17CE 207D18 JSR NXTENT + 17D1 E8 INX + 17D2 D0F6 BNE ITLP2 ; BRA + + 17D4 208918 ITLOOP: JSR ICALC ; SET (I) CORECTLY + + 17D7 B17A LDA (I),Y ; POINT IADR1 AT "HEADER" + 17D9 85B0 STA IADR1+HI + 17DB 84B1 STY IADR10 + 17DD C8 INY + 17DE B17A LDA (I),Y + 17E0 85AF STA IADR1+LO + + 17E2 A007 LDY #7 ; CURRENT ITERATION + 17E4 B17A LDA (I),Y + 17E6 48 PHA ; SAVE + 17E7 AA TAX + 17E8 E8 INX ; TAKE CARE OF SETING FOR NEXT ITERATION + + 17E9 A009 LDY #9 ; NUMBER OF ITERATIONS + 17EB D17A CMP (I),Y + 17ED D002 BNE ITSKP2 + 17EF A201 LDX #1 ; RESTET TO FIRST ITERATION + 17F1 8A ITSKP2: TXA + 17F2 A007 LDY #7 + 17F4 917A STA (I),Y ; NEXT ITERATION + + 17F6 C8 INY ;=8 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 75 +--- ITERATION STUFF --- + + 17F7 B17A LDA (I),Y ; BSET + 17F9 85CF STA BSET + + 17FB A00A LDY #10 ; WIDTH + 17FD B17A LDA (I),Y + 17FF 85B5 STA IX1 + 1801 AA TAX + 1802 C8 INY + 1803 B17A LDA (I),Y ; HEIGHT + 1805 85B7 STA IY1 + 1807 A8 TAY + 1808 208C17 JSR MULXY ; FIND WIDTH*HEIGHT + + 180B 68 PLA ; RESTORE CURRENT ITERATION + 180C A8 TAY + 180D 88 ITLP3: DEY ; ZERO ALIGN FIRST TIME THRU/ THEN JUST DEX + 180E F00A BEQ ITSKP3 + 1810 A5AE LDA MUH ; ADD LENGTH OF ICON (WIDTH*HEIGTH) + 1812 A6AD LDX MUL + 1814 202F19 JSR ADDIA1 + 1817 4C0D18 JMP ITLP3 + + 181A 98 ITSKP3: TYA ;=0 + 181B A204 LDX #4 + 181D 202F19 JSR ADDIA1 ; SKIP 4 HEADER BYTES + + 1820 A002 LDY #2 ; =2 + 1822 B17A LDA (I),Y ; ICON XPOS + 1824 856E STA ARG1+HI + 1826 C8 INY ; =3 + 1827 B17A LDA (I),Y + 1829 856D STA ARG1+LO + 182B C8 INY ; =4 + 182C B17A LDA (I),Y ; ICON YPOS + 182E 8570 STA ARG2+HI + 1830 C8 INY ; =5 + 1831 B17A LDA (I),Y + 1833 856F STA ARG2+LO + 1835 C8 INY ; =6 + 1836 B17A LDA (I),Y ; NEGATE + 1838 85E9 ITSKP4: STA NEGATE + + 183A A900 LDA #00 + 183C 85E3 STA MSKFLG ; DISABLE MASKING + + 183E 20EB14 JSR ITENT ; ENTER DRAW ROUTINE + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 76 +--- ITERATION STUFF --- + + 1841 207D18 JSR NXTENT ; POINT ARG4 AT NEXT ENTRY + + 1844 A6BF LDX ITPNT ; ARE WE DONE YET? + 1846 E4BE CPX ITICN + 1848 F023 BEQ ITEXI ; YES WE ARE DONE + + 184A E6BF INC ITPNT ; OTHERWISE POINT TO NEXT ENTRY + + 184C A579 LDA VALUE+HI ; IF INPUT WAS CALLED WITH A NEG INT + 184E 3007 BMI NONSNS ; DO NOT LOOK FOR INPUT + + 1850 205D1D JSR SENSE ; DO WE HAVE AN INPUT + 1853 C98F CMP #%10001111 + 1855 D003 BNE ITSKP5 ; GO HANDLE AN INPUT + 1857 4CD417 NONSNS: JMP ITLOOP ; OTHERWISE DO NEXT ENTRY + + 185A 48 ITSKP5: PHA ; SAVE INPUT + 185B A900 LDA #00 + 185D 8574 STA ARG4+HI + 185F 8573 STA ARG4+LO ; POINT AT TABLE HEADER + 1861 208918 JSR ICALC + 1864 C8 INY ; =1 + 1865 A5BF LDA ITPNT ; SAVE STATUS OF HOW FAR WE GOT IN DOING + 1867 917A STA (I),Y ; THE TABLE + + 1869 68 PLA ; RESTORE SENSE + 186A 4C600F JMP PUTBYT ; RETURN SENSE + + 186D A900 ITEXI: LDA #00 + 186F 8574 STA ARG4+HI + 1871 8573 STA ARG4+LO + 1873 208918 JSR ICALC ; POINT TO TABLE HEADER + 1876 C8 INY ; =1 + 1877 98 TYA + 1878 917A STA (I),Y + 187A 4C351D JMP NOIT + + + + 187D ;----------------------------- + 187D ; SKIP 6 WORDS (1 TABLE ENTRY) + 187D ;----------------------------- + + 187D A906 NXTENT: LDA #6 ; ADD 6 TO ARG4 + 187F 18 CLC + 1880 6573 ADC ARG4+LO + 1882 8573 STA ARG4+LO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 77 +--- ITERATION STUFF --- + + 1884 9002 BCC NEXI + 1886 E674 INC ARG4+HI + 1888 60 NEXI: RTS + + 1889 ;----------------------------------------------------------- + 1889 ; ICALC POINTS [I] AT THE RAM ADDRESS OF THE TABLE,OFFSET OF + 1889 ; ARG3,ARG4 + 1889 ; AND GENERATES A PURITY ERROR IF [I] POINTS AT PURE CODE. + 1889 ; + 1889 ; EXITS: =0 + 1889 ;------------------------------------------------------------ + + 1889 A000 ICALC: LDY #00 + 188B A573 LDA ARG4+LO + 188D 18 CLC + 188E 6571 ADC ARG3+LO + 1890 857A STA I+LO + 1892 A574 LDA ARG4+HI + 1894 6572 ADC ARG3+HI + 1896 4C1914 JMP ICENT ;ENTRY IN PCALC + + + END + INCLUD IOSUBS.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 78 +--- I/O SUPPORT ROUTINES --- + + + 1899 ;----------------------------------------- + 1899 ; INCRIMENT [VPC]+HI,[VPC]+LO,[VPC0] + 1899 ;----------------------------------------- + + 1899 A588 INCVPC: LDA VPC0 ; EFFECTIVLY ADD 1 + 189B 4901 EOR #$01 ; WITH EOR + 189D 8588 STA VPC0 + 189F D008 BNE VPEX1 + + 18A1 8589 STA VPCFLG ; INVALIDATE FLAG + + 18A3 E686 INC VPC+LO + 18A5 D002 BNE VPEX1 + 18A7 E687 INC VPC+HI + 18A9 60 VPEX1: RTS + + 18AA ;---------------------------- + 18AA ; ADD A,X TO [VPC]+HI,+LO,0 + 18AA ;---------------------------- + + 18AA 867C ADDVPC: STX J+LO ; SAVE + 18AC 4A LSR A ; SHIFT SO AS TO ALIGN WITH 8,8,1 BIT PATTERN + 18AD ; IN [VPC] + 18AD 857D STA J+HI + 18AF 667C ROR J+LO ; SHIFT LOW PART + 18B1 9004 BCC AVISK + 18B3 209918 JSR INCVPC ; IF CARRY SET ADD 1 TO [VPC] + 18B6 18 CLC + 18B7 A586 AVISK: LDA VPC+LO + 18B9 657C ADC J+LO + 18BB 8586 STA VPC+LO + 18BD A587 LDA VPC+HI + 18BF 657D ADC J+HI + 18C1 8587 STA VPC+HI + + 18C3 A900 LDA #00 ; INVALIDATE FLAG + 18C5 8589 STA VPCFLG + + 18C7 60 RTS + + + 18C8 ;----------------------------------------- + 18C8 ; INCRIMENT [GPC]+HI,[GPC]+LO,[GPC0] + 18C8 ;----------------------------------------- + + 18C8 A582 INCGPC: LDA GPC0 ; EFFECTIVLY ADD 1 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 79 +--- I/O SUPPORT ROUTINES --- + + 18CA 4901 EOR #$01 ; WITH EOR + 18CC 8582 STA GPC0 + 18CE D008 BNE GPEX1 + + 18D0 8583 STA GPCFLG ; INVALIDATE FLAG + + 18D2 E680 INC GPC+LO + 18D4 D002 BNE GPEX1 + 18D6 E681 INC GPC+HI + 18D8 60 GPEX1: RTS + + 18D9 ;---------------------------- + 18D9 ; ADD A,X TO [GPC]+HI,+LO,0 + 18D9 ;---------------------------- + + 18D9 867C ADDGPC: STX J+LO ; SAVE + 18DB 4A LSR A ; SHIFT SO AS TO ALIGN WITH 8,8,1 BIT PATTERN + 18DC ; IN [GPC] + 18DC 857D STA J+HI + 18DE 667C ROR J+LO ; SHIFT LOW PART + 18E0 9004 BCC AGISK + 18E2 20C818 JSR INCGPC ; IF CARRY SET ADD 1 TO [GPC] + 18E5 18 CLC + 18E6 A580 AGISK: LDA GPC+LO + 18E8 657C ADC J+LO + 18EA 8580 STA GPC+LO + 18EC A581 LDA GPC+HI + 18EE 657D ADC J+HI + 18F0 8581 STA GPC+HI + + 18F2 A900 LDA #00 ; INVALIDATE FLAG + 18F4 8583 STA GPCFLG + + 18F6 60 RTS + + 18F7 ;----------------------------------------- + 18F7 ; INCRIMENT [IADR2]+HI,[IADR2]+LO,[IADR20] + 18F7 ;----------------------------------------- + + 18F7 A5B4 INCIA2: LDA IADR20 ; EFFECTIVLY ADD 1 + 18F9 4901 EOR #$01 ; WITH EOR + 18FB 85B4 STA IADR20 + 18FD D006 BNE INEX2 + 18FF E6B2 INC IADR2+LO + 1901 D002 BNE INEX2 + 1903 E6B3 INC IADR2+HI + 1905 60 INEX2: RTS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 80 +--- I/O SUPPORT ROUTINES --- + + + 1906 ;---------------------------- + 1906 ; ADD A,X TO [IADR2]+HI,+LO,0 + 1906 ;---------------------------- + + 1906 867C ADDIA2: STX J+LO ; SAVE + 1908 4A LSR A ; SHIFT SO AS TO ALIGN WITH 8,8,1 BIT PATTERN + 1909 ; IN [IADR2] + 1909 857D STA J+HI + 190B 667C ROR J+LO ; SHIFT LOW PART + 190D 9004 BCC ADIS2 + 190F 20F718 JSR INCIA2 ; IF CARRY SET ADD 1 TO [IADR1] + 1912 18 CLC + 1913 A5B2 ADIS2: LDA IADR2+LO + 1915 657C ADC J+LO + 1917 85B2 STA IADR2+LO + 1919 A5B3 LDA IADR2+HI + 191B 657D ADC J+HI + 191D 85B3 STA IADR2+HI + 191F 60 RTS + + 1920 ;----------------------------------------- + 1920 ; INCRIMENT [IADR1]+HI,[IADR1]+LO,[IADR10] + 1920 ;----------------------------------------- + + 1920 A5B1 INCIA1: LDA IADR10 ; EFFECTIVLY ADD 1 + 1922 4901 EOR #$01 ; WITH EOR + 1924 85B1 STA IADR10 + 1926 D006 BNE INEX1 + 1928 E6AF INC IADR1+LO + 192A D002 BNE INEX1 + 192C E6B0 INC IADR1+HI + 192E 60 INEX1: RTS + + 192F ;---------------------------- + 192F ; ADD A,X TO [IADR1]+HI,+LO,0 + 192F ;---------------------------- + + 192F 867C ADDIA1: STX J+LO ; SAVE + 1931 4A LSR A ; SHIFT SO AS TO ALIGN WITH 8,8,1 BIT PATTERN + 1932 ; IN [IADR1] + 1932 857D STA J+HI + 1934 667C ROR J+LO ; SHIFT LOW PART + 1936 9004 BCC ADISK + 1938 202019 JSR INCIA1 ; IF CARRY SET ADD 1 TO [IADR1] + 193B 18 CLC + 193C A5AF ADISK: LDA IADR1+LO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 81 +--- I/O SUPPORT ROUTINES --- + + 193E 657C ADC J+LO + 1940 85AF STA IADR1+LO + 1942 A5B0 LDA IADR1+HI + 1944 657D ADC J+HI + 1946 85B0 STA IADR1+HI + 1948 60 RTS + 1949 ; ---------------- + 1949 ; GET BLOCKSET [A] + 1949 ; ---------------- + + 1949 ; ENTRY: BLOCKSET ID # (1-255) IN [A] + 1949 ; EXIT: VIRTUAL BASE ADDR OF BLOCKSET DATA IN [BSADR] + 1949 ; # BLOCKS IN [BSIZE] + 1949 ; BLOCKSET DATA PAGED INTO RAM + + 1949 A000 GETBS: LDY #0 + 194B 8489 STY VPCFLG ; INVALIDATE [VPC] + 194D 847B STY I+HI ; CLEAR MSB OF INDEX + 194F 84AD STY MUL ; AND MULTIPLICATION + 1951 84AE STY MUH ; REGISTERS + + 1953 38 SEC + 1954 E901 SBC #1 ; ZERO-ALIGN AND + 1956 0A ASL A ; WORD-ALIGN THE + 1957 267B ROL I+HI ; BLOCKSET INDEX (ALSO CLEARS CARRY) + + 1959 659E ADC BTAB+LO ; ADD BASE ADDRESS OF + 195B 857A STA I+LO ; BLOCKSET TABLE + 195D A57B LDA I+HI ; TO GET ABS ADDR OF POINTER + 195F 659F ADC BTAB+HI ; INTO [I] + 1961 857B STA I+HI + + 1963 B17A LDA (I),Y ; GET MSB OF POINTER ([Y] = 0) + 1965 8587 STA VPCH + 1967 C8 INY ; ALSO GET LSB + 1968 B17A LDA (I),Y ; SO THAT [VPC] POINTS TO + 196A 8586 STA VPCL ; V-ADDR OF BLOCKSET FILE + + ;*** + 196C A900 LDA #00 + 196E 8588 STA VPC0 + ;*** + 1970 20251B JSR GETBYT + 1973 85EA STA BLKLEN ; SAVE # BYTES PER BLOCK + + 1975 20251B JSR GETBYT ; 2ND BYTE HAS # BLOCKS + 1978 85D2 STA BSIZE ; SAVE HERE FOR REFERENCE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 82 +--- I/O SUPPORT ROUTINES --- + + 197A 85AC STA MUSHFT ; AND HERE FOR MULTIPLY + + 197C A586 LDA VPCL ; MOVE V-ADDR OF BLOCKSET DATA + 197E 85D0 STA BSADR+LO ; INTO [BSADR] + 1980 A587 LDA VPCH + 1982 85D1 STA BSADR+HI + + 1984 C595 CMP IPURE ; IS THIS SET IN I-PRELOAD? + 1986 9037 BCC GBLX ; EXIT NOW IF SO + + 1988 ; LOAD THE ENTIRE BLOCKSET AT [VPC] INTO PAGING RAM + + 1988 A007 LDY #7 ; INIT BIT-LOOP INDEX + 198A A6EA LDX BLKLEN ; GET BLOCK LENGTH + 198C CA DEX ; ZERO-ALIGN + 198D 8A GBL1: TXA ; MULTIPLY BY + 198E 46AC LSR MUSHFT ; # BLOCKS IN BLOCKSET + 1990 9004 BCC GBL2 ; TO GET SIZE + 1992 65AE ADC MUH ; OF BLOCKSET + 1994 85AE STA MUH ; IN [MUL/H] + 1996 66AE GBL2: ROR MUH + 1998 66AD ROR MUL + 199A 88 DEY + 199B 10F0 BPL GBL1 + + ;*** + 199D 46AE LSR MUH + 199F 66AD ROR MUL + ;*** + + 19A1 A586 LDA VPCL ; ADD LSB OF BLOCKSET START ADDRESS + 19A3 18 CLC ; TO LSB OF + 19A4 65AD ADC MUL ; BLOCKSET SIZE IN [MUL/H] + 19A6 9002 BCC GBL3 ; CONTINUE IF NO PAGE OVERFLOW + 19A8 E6AE INC MUH ; ELSE FORCE EXTRA PAGE LOAD + + 19AA A5AE GBL3: LDA MUH ; IF [MUH] = 0, + 19AC F011 BEQ GBLX ; NO MORE PAGES ARE NEEDED + + 19AE E687 GBL4: INC VPCH ; ELSE POINT TO NEXT PAGE + 19B0 A900 LDA #0 + 19B2 8589 STA VPCFLG ; INVALIDATE [VPC] + 19B4 20251B JSR GETBYT ; GET A BYTE (FORCE PAGE LOAD) + 19B7 C6AE DEC MUH ; LOADED ALL BLOCKSET PAGES YET? + 19B9 D0F3 BNE GBL4 ; LOOP TILL EMPTY + + 19BB A900 LDA #0 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 83 +--- I/O SUPPORT ROUTINES --- + + 19BD 8589 STA VPCFLG ; INVALIDATE [VPC] + + 19BF 60 GBLX: RTS + + 19C0 ; --------------------------------- + 19C0 ; GET BLOCK [A] IN CURRENT BLOCKSET + 19C0 ; --------------------------------- + + 19C0 ; ENTRY: BLOCK ID # (0-255) IN [A] + 19C0 ; EXIT: BLOCK DATA IN [BLOCK] + + 19C0 85AC GETBLK: STA MUSHFT ; SAVE BLOCK ID + + 19C2 A900 LDA #0 + 19C4 8589 STA VPCFLG ; INVALIDATE [VPC] + 19C6 85AD STA MUL ; CLEAR LSB AND + 19C8 85AE STA MUH ; MSB OF OFFSET + + 19CA A007 LDY #7 ; INIT BIT-SHIFT INDEX + + 19CC A6EA LDX BLKLEN ; GET LENGTH OF BLOCKS + 19CE CA DEX ; ZERO-ALIGN + 19CF 867A STX I+LO ; SAVE FOR LATER LOOPING + 19D1 8A MULP: TXA + 19D2 46AC LSR MUSHFT + 19D4 9004 BCC MUSK + 19D6 65AE ADC MUH + 19D8 85AE STA MUH + 19DA 66AE MUSK: ROR MUH + 19DC 66AD ROR MUL + 19DE 88 DEY + 19DF 10F0 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 + + ;*** + 19E1 A5D0 MUEND: LDA BSADR+LO ; PUT WORD POINTER TO START OF BLOCKSET + 19E3 8586 STA VPCL ; IN VPCH,L + 19E5 A5D1 LDA BSADR+HI + 19E7 8587 STA VPCH + 19E9 A900 LDA #00 ; ZERO BOTTEM BIT + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 84 +--- I/O SUPPORT ROUTINES --- + + 19EB 8588 STA VPC0 + + 19ED A5AE LDA MUH ; ADD OFFSET TO BLOCK TO VPC + 19EF A6AD LDX MUL + 19F1 20AA18 JSR ADDVPC + ;*** + + 19F4 20251B GBLL: JSR GETBYT ; GET A BYTE + 19F7 A67A LDX I+LO + 19F9 95D3 STA BLOCK,X ; STORE BYTE IN [BLOCK] + 19FB C67A DEC I+LO + 19FD CA DEX ; LOOP TILL + 19FE 10F4 BPL GBLL ; ALL BYTES DONE + + 1A00 ; NEGATE [BLOCK] IF [NEGATE] IS TRUE + + 1A00 A5E9 LDA NEGATE + 1A02 F00B BEQ BLOCKX + + 1A04 A207 LDX #7 ; NEGATE [BLOCK] + 1A06 B5D3 GBLLL: LDA BLOCK,X + 1A08 49FF EOR #$FF + 1A0A 95D3 STA BLOCK,X + 1A0C CA DEX + 1A0D 10F7 BPL GBLLL + + 1A0F 60 BLOCKX: RTS + + 1A10 ; ------------------------ + 1A10 ; SETUP FOR SETI AND SWAPI + 1A10 ; ------------------------ + + 1A10 A673 ISETUP: LDX ARG4+LO ; GET ADDR OF DESTINATION ICON + 1A12 A574 LDA ARG4+HI + 1A14 C595 CMP IPURE ; IS DEST IN I-PRELOAD? + 1A16 9003 BCC ISU ; CONTINUE IF SO + + 1A18 4CC516 JMP PRERR2 ; ELSE PURITY VIOLATION! + + 1A1B ;---------------------- + 1A1B ; ENTRY FOR MASK SET UP + 1A1B ;---------------------- + + 1A1B 20361A ISU: JSR GETI ; FETCH STATS OF DEST ICON + + 1A1E A5B5 LDA IX1 ; COPY DEST ICON STATS + 1A20 85B6 STA IX2 ; INTO AUXILIARY REGISTERS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 85 +--- I/O SUPPORT ROUTINES --- + + 1A22 A5B7 LDA IY1 + 1A24 85B8 STA IY2 + + 1A26 A5B1 LDA IADR10 + 1A28 85B4 STA IADR20 + 1A2A A5AF LDA IADR1+LO + 1A2C 85B2 STA IADR2+LO + 1A2E A5B0 LDA IADR1+HI + 1A30 85B3 STA IADR2+HI + + 1A32 A671 LDX ARG3+LO ; NOW GET SOURCE ICON STATS + 1A34 A572 LDA ARG3+HI + + 1A36 ; FALL THROUGH TO ... + + 1A36 ; -------- + 1A36 ; GET ICON + 1A36 ; -------- + + 1A36 ; ENTRY: V-ADDR OF ICON FILE IN [X/A] + 1A36 ; EXIT: ICON DATA V-ADDR IN [IADR1] + 1A36 ; X-SIZE IN [IX1] & [XDEX1] + 1A36 ; Y-SIZE IN [IY1] & [YDEX1] + 1A36 ; ASSIGNED BLOCKSET IN [BSET] + + 1A36 8686 GETI: STX VPCL + 1A38 8587 STA VPCH + 1A3A A900 LDA #0 + ;*** + 1A3C 8588 STA VPC0 + ;*** + 1A3E 8589 STA VPCFLG ; INVALIDATE [VPC] + + 1A40 20251B JSR GETBYT ; 1ST BYTE HAS + 1A43 85CF STA BSET ; ASSIGNED BLOCKSET + + 1A45 20251B JSR GETBYT ; 2ND BYTE HAS + 1A48 85BD STA ITERS ; # ITERATIONS + + 1A4A 20251B JSR GETBYT ; 3RD BYTE HAS + 1A4D 85B5 STA IX1 ; X-SIZE + + 1A4F 20251B JSR GETBYT ; 4TH BYTE HAS + 1A52 85B7 STA IY1 ; Y-SIZE + 1A54 857C STA J+LO ; SAVE HERE FOR LATER + + 1A56 A586 LDA VPCL ; SAVE BASE V-ADDR + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 86 +--- I/O SUPPORT ROUTINES --- + + 1A58 85AF STA IADR1+LO ; IN [IADR] + 1A5A A587 LDA VPCH + 1A5C 85B0 STA IADR1+HI + 1A5E A588 LDA VPC0 + 1A60 85B1 STA IADR10 + + + 1A62 C595 CMP IPURE ; IS THIS ICON PRELOADED? + + 1A64 9023 BCC NEWXY ; YES, SCRAM NOW + + + 1A66 ; MAKE SURE ICON DATA IS PAGED INTO RAM + + 1A66 A586 LDA VPCL ; GET CURRENT PAGE POINTER + 1A68 18 CLC + 1A69 65B5 ADC IX1 ; ADD X-OFFSET + 1A6B B008 BCS ILD1 ; GET NEW PAGE IF BOUNDARY CROSSED + + 1A6D C67C ILD0: DEC J+LO ; OUT OF X-LINES YET? + 1A6F F014 BEQ ILD2 ; YES, ICON IS ALL LOADED + 1A71 65B5 ADC IX1 ; ELSE ADD ANOTHER X-LINE + 1A73 90F8 BCC ILD0 ; LOOP BACK IF SAME PAGE + + 1A75 857D ILD1: STA J+HI ; SAVE NEW PAGE POINTER + 1A77 E687 INC VPCH ; POINT TO NEXT PAGE + 1A79 A900 LDA #0 + 1A7B 8589 STA VPCFLG ; INVALIDATE [VPC] + 1A7D 20251B JSR GETBYT ; TO FORCE PAGE LOAD + 1A80 A57D LDA J+HI ; RESTORE POINTER + 1A82 18 CLC ; CLEAR CARRY FOR NEW LOOP + 1A83 90E8 BCC ILD0 ; BRANCH ALWAYS + + 1A85 A900 ILD2: LDA #0 + 1A87 8589 STA VPCFLG ; INVALIDATE [VPC] + + 1A89 ; FALL THROUGH ... + + + 1A89 ; ------------------------- + 1A89 ; REFRESH [XDEX1] & [YDEX1] + 1A89 ; ------------------------- + + 1A89 A5B5 NEWXY: LDA IX1 + 1A8B 85B9 STA XDEX1 + 1A8D A5B7 LDA IY1 + 1A8F 85BB STA YDEX1 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 87 +--- I/O SUPPORT ROUTINES --- + + 1A91 60 RTS + + 1A92 ; ----------------------------- + 1A92 ; WILL SOURCE ICON FIT IN DEST? + 1A92 ; ----------------------------- + + 1A92 ; ENTRY: SOURCE STATS IN [1] REGISTERS, DEST IN [2] + 1A92 ; EXIT: CARRY CLEAR IF FIT OKAY, ELSE CARRY SET + 1A92 ; [IADR2] HAS ABSOLUTE ADDRESS OF SUB-ICON + + 1A92 A56D DOFIT: LDA ARG1+LO ; GET X-POSITION + 1A94 18 CLC + 1A95 65B5 ADC IX1 ; ADD X-SIZE OF SOURCE + 1A97 C5B6 CMP IX2 ; COMPARE TO SIZE OF DEST + 1A99 9002 BCC FIT ; OKAY IF LESS + 1A9B D034 BNE FITEX ; OR EQUAL; ELSE EXIT W/CARRY SET + + 1A9D A56F FIT: LDA ARG2+LO ; GET Y-POSITION + 1A9F A8 TAY ; SAVE HERE FOR INDEXING BELOW + 1AA0 18 CLC + 1AA1 65B7 ADC IY1 ; ADD SIZE OF SOURCE + 1AA3 C5B8 CMP IY2 ; COMPARE TO SIZE OF DEST + 1AA5 9002 BCC FIT0 ; OKAY IS LESS + 1AA7 D028 BNE FITEX ; SO IS EQUAL; ELSE EXIT W/CARRY SET + + 1AA9 ; MAKE [IADR2] POINT TO ADDR OF SUB-ICON + + 1AA9 A56D FIT0: LDA ARG1+LO ; IF X-POS OF SUB-ICON IS 0, + 1AAB F011 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 + ;*** + 1AAD A900 LDA #0 + 1AAF A66D LDX ARG1+LO + 1AB1 200619 JSR ADDIA2 + 1AB4 4CBE1A 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 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS PAGE 88 +--- I/O SUPPORT ROUTINES --- + + ; STA IADR2+LO + ; BCC FIT3 + ; INC IADR2+HI + ;*** + 1AB7 A900 FIT2: LDA #0 + 1AB9 A6B6 LDX IX2 + 1ABB 200619 JSR ADDIA2 + ;*** + + 1ABE 88 FIT3: DEY ; OUT OF Y-COORDS YET? + 1ABF 10F6 BPL FIT2 ; NO, KEEP ADDING + + 1AC1 A5B3 LDA IADR2+HI ; MAKE SUB-ICON ADDR ABSOLUTE + 1AC3 38 SEC ; BY STRIPPING OFF THE + 1AC4 E594 SBC ISTART ; V-OFFSET + + ;*** + 1AC6 46B4 LSR IADR20 + 1AC8 26B2 ROL IADR2+LO + 1ACA 2A ROL A + ;*** + 1ACB 18 CLC ; AND ADDING THE ABS ADDR + 1ACC 6592 ADC ICODE+HI ; OF THE + 1ACE 85B3 STA IADR2+HI ; I-PRELOAD (LSB NEEDN'T CHANGE) + 1AD0 18 CLC ; CLEAR CARRY FOR SUCCESS + + 1AD1 60 FITEX: RTS + + END + + INCLUD PAGING.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MEMORY MANAGEMENT PAGE 89 +--- PAGING ROUTINES --- + + + 1AD2 ; ----------------------- + 1AD2 ; GET NEXT BYTE OF G-CODE + 1AD2 ; ----------------------- + + 1AD2 ; EXIT: BYTE IN [A] & [Y], FLAGS SET + + 1AD2 A583 NEXTPC: LDA GPCFLG ; IS [GPOINT] VALID? + 1AD4 D025 BNE NPC2 ; YES, CONTINUE + + 1AD6 A681 LDX GPCH ; GET TARGET V-PAGE + 1AD8 BD0007 LDA MEMMAP,X ; IS IT ALREADY RESIDENT? + 1ADB F00A BEQ NPC0 ; NO, PAGE IT IN + 1ADD C596 CMP PAGE0 ; IS IT IN PRELOAD? + 1ADF 900E BCC NPC1 ; YES, CONTINUE + + 1AE1 ; HANDLE A RESIDENT "PURE" PAGE + + 1AE1 20A01B JSR UPTIME ; UPDATE STAMP + 1AE4 4CEF1A JMP NPC1 ; CONTINUE W/PAGE ADDR IN [A] + + 1AE7 ; FETCH A NON-RESIDENT "PURE" PAGE + + 1AE7 8589 NPC0: STA VPCFLG ; ([A]=0) INVALIDATE [VPC] + 1AE9 20781B JSR PAGE ; GET ABS PAGE OF V-BLOCK [X] IN [A] + 1AEC 4CD21A JMP NEXTPC + ;THIS JUMP SHOULD NOT BE NEEDED BUT SEEMS TO HELP + + + 1AEF ; [A] HAS ABS ADDR OF TARGET PAGE (FIRST RAM PAGE OF TWO PAGES) + + 1AEF 8585 NPC1: STA GPOINT+HI ; FORM MSB OF G-POINTER + 1AF1 A580 LDA GPCL ; IF BIT 7 SET + 1AF3 1002 BPL NPC1A + 1AF5 E685 INC GPOINT+HI ; POINT [GPOINT] AT NEXT RAM PAGE + 1AF7 A9FF NPC1A: LDA #$FF + 1AF9 8583 STA GPCFLG ; VALIDATE [GPC] + + 1AFB ; [GPOINT] HAS POINTER TO ABS PAGE ADDR + + 1AFB ; PUT BITS 0 THRU 7 OF GPC INTO + + 1AFB A582 NPC2: LDA GPC0 ; PUT BIT 0 INTO + 1AFD 4A LSR A + 1AFE A580 LDA GPCL ; GET BITS 1-8 + 1B00 2A ROL A ; DON'T WORRY ABOUT BIT 8 + 1B01 A8 TAY + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MEMORY MANAGEMENT PAGE 90 +--- PAGING ROUTINES --- + + + 1B02 B184 LDA (GPOINT),Y ; GET A G-BYTE + + 1B04 ; INCREMENT [GPC] + 1B04 ; IF CROSSING A !RAM! PAGE ADJUST [GPOINT] + 1B04 ; IF CROSSING A V-PAGE INVALIDATE FLAG + + 1B04 48 PHA ; SAVE THE BYTE + + 1B05 A582 LDA GPC0 ; EFFECTIVLY ADD 1 + 1B07 4901 EOR #$01 + 1B09 8582 STA GPC0 + 1B0B D015 BNE NPC3 ; BRANCH NO CARRY + + 1B0D E680 INC GPCL + 1B0F F00B BEQ NPC4 ; BRANCH CROSSED V-PAGE + + 1B11 A580 LDA GPCL ; TEST FOR CROSS !RAM! PAGE + 1B13 297F AND #$7F + 1B15 D00B BNE NPC3 ; BRANCH NO CROSS + + 1B17 E685 INC GPOINT+HI ; ADJUST RAM POINTER + 1B19 4C221B JMP NPC3 + + 1B1C E681 NPC4: INC GPCH ; CROSS V-PAGE + 1B1E A900 LDA #00 + 1B20 8583 STA GPCFLG ; INVALIDATE FLAG + + 1B22 68 NPC3: PLA ; RESTORE BYTE + 1B23 A8 TAY ; SET FLAGS + 1B24 60 RTS + + 1B25 ; ---------------------------- + 1B25 ; GET A BYTE OF VIRTUAL MEMORY + 1B25 ; ---------------------------- + + 1B25 ; EXIT: SAME AS "NEXTPC" + + 1B25 A589 GETBYT: LDA VPCFLG ; [VPC] VALID? + 1B27 D025 BNE GTBT2 ; YES, CONTINUE + + 1B29 A687 LDX VPCH ; GET TARGET V-PAGE + 1B2B BD0007 LDA MEMMAP,X ; ALREADY IN RAM? + 1B2E F00A BEQ GTBT0 ; NO, PAGE IT IN + 1B30 C596 CMP PAGE0 ; IS IT PRELOADED? + 1B32 900E BCC GTBT1 ; YES, CONTINUE + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MEMORY MANAGEMENT PAGE 91 +--- PAGING ROUTINES --- + + 1B34 ; HANDLE A RESIDENT PAGE + + 1B34 20A01B JSR UPTIME ; STAMP PAGE & UPDATE STAMP + 1B37 4C421B JMP GTBT1 ; CONTINUE W/BUFFER ADDR IN [A] + + 1B3A ; HANDLE A NON-RESIDENT PAGE + + 1B3A 8583 GTBT0: STA GPCFLG ; ([A]=0) INVALIDATE [GPC] + 1B3C 20781B JSR PAGE ; GET ABS PAGE OF V-BLOCK [X] INTO [A] + 1B3F 4C251B JMP GETBYT + ;THIS JMP SHOULD NOT BE NEEDED BUT SEEMS TO HELP + + + 1B42 ; [A] HAS ABS PAGE # OF TARGET PAGE + + 1B42 858B GTBT1: STA VPOINT+HI ; SET MSB OF POINTER + 1B44 A586 LDA VPCL ; IF BIT 7 SET + 1B46 1002 BPL GTBT1A + 1B48 E68B INC VPOINT+HI ; POINT AT NEXT RAM PAGE + 1B4A A9FF GTBT1A: LDA #$FF + 1B4C 8589 STA VPCFLG ; VALIDATE [VPC] + + 1B4E ; [VPOINT] POINTS TO ABS ADDR OF TARGET V-PAGE + + 1B4E ; PUT BITS 0 THRU 7 OF GPC INTO + + 1B4E A588 GTBT2: LDA VPC0 ; PUT BIT 0 INTO + 1B50 4A LSR A + 1B51 A586 LDA VPCL ; GET BITS 1-8 + 1B53 2A ROL A ; DON'T WORRY ABOUT BIT 8 + 1B54 A8 TAY + + 1B55 B18A LDA (VPOINT),Y ; GET A V-BYTE + + 1B57 ; INCREMENT [VPC] + 1B57 ; IF CROSSING A !RAM! PAGE ADJUST [GPOINT] + 1B57 ; IF CROSSING A V-PAGE INVALIDATE FLAG + + 1B57 48 PHA ; SAVE THE BYTE + + 1B58 A588 LDA VPC0 ; EFFECTIVLY ADD 1 + 1B5A 4901 EOR #$01 + 1B5C 8588 STA VPC0 + 1B5E D015 BNE GTBT3 ; BRANCH NO CARRY + + 1B60 E686 INC VPCL + 1B62 F00B BEQ GTBT4 ; BRANCH CROSSED V-PAGE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MEMORY MANAGEMENT PAGE 92 +--- PAGING ROUTINES --- + + + 1B64 A586 LDA VPCL ; TEST FOR CROSS !RAM! PAGE + 1B66 297F AND #$7F + 1B68 D00B BNE GTBT3 ; BRANCH NO CROSS + + 1B6A E68B INC VPOINT+HI ; ADJUST RAM POINTER + 1B6C 4C751B JMP GTBT3 + + 1B6F E687 GTBT4: INC VPCH ; CROSS V-PAGE + 1B71 A900 LDA #00 + 1B73 8589 STA VPCFLG ; INVALIDATE FLAG + + 1B75 68 GTBT3: PLA ; RESTORE BYTE + 1B76 A8 TAY ; SET FLAGS + 1B77 60 RTS + + 1B78 ; ------------------------------- + 1B78 ; LOCATE A PAGE OF VIRTUAL MEMORY + 1B78 ; ------------------------------- + + 1B78 ;----------------------------------------------------------------- + 1B78 ; A VIRTUAL PAGE IS 512 BYTES OF VIRTUAL MEMORY. + 1B78 ; WHEN PAGED INTO MACHINE RAM IT MUST OCCUPY TWO CONSECUTIVE + 1B78 ; 256 BYTE !RAM! PAGES. + 1B78 ; + 1B78 ; [PAGMAP],BUFFER RETURN THE V-PAGE IN THAT BUFFFER + 1B78 ; (A BUFFER IS TWO CONSECUTIVE RAM PAGES) + 1B78 ; [MEMMAP],VPAGE RETURNS RAM PAGE LOWER HALF OF VPAGE IS IN + 1B78 ; + 1B78 ; [PAGE0] - RAM PAGE WHERE BUFFER(0) STARTS + 1B78 ;----------------------------------------------------------------- + + 1B78 ; ENTRY: V-BLOCK TO SEARCH FOR IN [X] + 1B78 ; EXIT: ABSOLUTE PAGE ADDRESS IN [A] + + 1B78 86EB PAGE: STX DBLOCK ; GIVE TARGET V-PAGE TO GROS + + 1B7A ; DE-ALLOCATE THE EARLIEST V-PAGE + + 1B7A 20D61B PGE1: JSR EARLY ; GET INDEX OF EARLIEST BUFFER INTO [SWAP] + + 1B7D A49A LDY SWAP + 1B7F BE0008 LDX PAGMAP,Y ; GET V-PAGE OF EARLIEST BUFFER + 1B82 F005 BEQ PGE2 ; 0 = NO PAGE IN BUFFER + 1B84 A900 LDA #0 + 1B86 9D0007 STA MEMMAP,X ; ZERO THE [MEMMAP] ENTRY + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MEMORY MANAGEMENT PAGE 93 +--- PAGING ROUTINES --- + + 1B89 ; SPLICE THE TARGET PAGE INTO THE BUFFER MAP + + 1B89 A5EB PGE2: LDA DBLOCK ; TARGET V-PAGE + 1B8B 990008 STA PAGMAP,Y ; ADD IT TO BUFFER MAP + 1B8E AA TAX ; USE LATER FOR INDEX INTO [MEMMAP] + + 1B8F 98 TYA ; CALC THE ABSOLUTE ADDRESS + 1B90 0A ASL A ; * 2 FOR 512 BYTE VPAGES + 1B91 18 CLC ; OF THE + 1B92 6596 ADC PAGE0 ; CORRESPONDING BUFFER + 1B94 9D0007 STA MEMMAP,X ; TELL [MEMMAP] WHERE TO FIND THE PAGE + 1B97 85EE STA DBUFF+HI ; TELL GROS WHERE THE BUFFER IS + + 1B99 859B STA TARGET ; SAVE HERE + 1B9B 202722 JSR GETDSK ; GET PAGE [DBLOCK] INTO [DBUFF] + 1B9E A59B LDA TARGET ; RESTORE BUFFER PAGE + + 1BA0 ; FALL THROUGH ... + + 1BA0 ; ---------------- + 1BA0 ; UPDATE TIMESTAMP + 1BA0 ; ---------------- + + 1BA0 ; ENTRY: ABS BUFFER PAGE OF V-BLOCK + + 1BA0 859B UPTIME: STA TARGET ; SAVE FOR LATER + 1BA2 38 SEC ; FORM A ZERO-ALIGNED + 1BA3 E596 SBC PAGE0 ; INDEX + ;*** + 1BA5 4A LSR A ; / 2 FOR 512 BYTE PAGES + ;*** + 1BA6 A8 TAY ; INTO [LRUMAP] + 1BA7 B98008 LDA LRUMAP,Y ; CHECK THIS PAGE'S STAMP + 1BAA C598 CMP STAMP ; SAME AS CURRENT STAMP? + 1BAC F025 BEQ UT3 ; EXIT NOW IF SO + + 1BAE E698 INC STAMP ; ELSE UPDATE STAMP + 1BB0 D01C BNE UT2 ; CONTINUE IF NO OVERFLOW + + 1BB2 ; HANDLE STAMP OVERFLOW + + 1BB2 20EF1B JSR EARLY2 ; GET EARLIEST STAMP INTO [LRU] + 1BB5 A200 LDX #0 ; INIT INDEX + 1BB7 BD8008 UT0: LDA LRUMAP,X ; ELSE GET A STAMP READING + 1BBA F006 BEQ UT1 ; EXIT IF ZERO + 1BBC 38 SEC ; SUBTRACT OFF + 1BBD E599 SBC LRU ; EARLIEST STAMP READING + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MEMORY MANAGEMENT PAGE 94 +--- PAGING ROUTINES --- + + 1BBF 9D8008 STA LRUMAP,X ; REPLACE IN MAP + 1BC2 E8 UT1: INX + 1BC3 E497 CPX PMAX ; LOOP TILL + 1BC5 90F0 BCC UT0 ; ALL STAMPS FIXED + + 1BC7 A900 LDA #0 ; TURN BACK + 1BC9 38 SEC ; THE CLOCK + 1BCA E599 SBC LRU ; TO REFLECT STAMP FUDGING + 1BCC 8598 STA STAMP + + 1BCE A598 UT2: LDA STAMP ; STAMP BUFFER [Y] + 1BD0 998008 STA LRUMAP,Y ; WITH THE NEW STAMP + + 1BD3 A59B UT3: LDA TARGET ; RESTORE BUFFER ADDR + 1BD5 60 RTS + + 1BD6 ; -------------------------------- + 1BD6 ; LOCATE EARLIEST ACTIVE TIMESTAMP + 1BD6 ; -------------------------------- + + 1BD6 ; EXIT: [LRU] = EARLIEST TIMESTAMP + 1BD6 ; [SWAP] = INDEX TO EARLIEST BUFFER + + 1BD6 A200 EARLY: LDX #0 ; INIT INDEX + 1BD8 869A STX SWAP + 1BDA AD8008 LDA LRUMAP ; GET TIMESTAMP OF BUFFER #0 + 1BDD E8 INX ; START COMPARE WITH BUFFER #1 + + 1BDE DD8008 EAR0: CMP LRUMAP,X ; IS THIS STAMP EARLIER THAN [A]? + 1BE1 9005 BCC EAR1 ; IF STILL SMALLER, TRY NEXT STAMP + + 1BE3 BD8008 LDA LRUMAP,X ; ELSE CHANGE EARLIEST ENTRY + 1BE6 869A STX SWAP ; AND UPDATE BUFFER INDEX + + 1BE8 E8 EAR1: INX + 1BE9 E497 CPX PMAX ; OUT OF BUFFERS? + 1BEB 90F1 BCC EAR0 ; LOOP TILL EMPTY + 1BED 60 RTS ; [SWAP] HAS INDEX TO EARLIEST BUFFER + + 1BEE ; THIS IS FOR OVERFLOW, IGNORES 0 ENTRIES + + 1BEE 00 SAVEY: DB 0 + + 1BEF A200 EARLY2: LDX #0 ; INIT INDEX + 1BF1 869A STX SWAP + 1BF3 8CEE1B STY SAVEY + 1BF6 BD8008 EAR23: LDA LRUMAP,X ; GET TIMESTAMP OF BUFFER #0 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MEMORY MANAGEMENT PAGE 95 +--- PAGING ROUTINES --- + + 1BF9 C900 CMP #0 ; DON'T USE A ZERO VALUE + 1BFB D007 BNE EAR22 ; OK, NOT 0 + 1BFD E8 INX + 1BFE E497 CPX PMAX ; OUT OF BUFFERS? + 1C00 90F4 BCC EAR23 ; NO, KEEP LOOKING + 1C02 B013 BCS EAR24 ; YUP, SO WILL HAVE TO USE 0 + + 1C04 E8 EAR22: INX ; START COMPARE WITH NEXT BUFFER + + 1C05 DD8008 EAR20: CMP LRUMAP,X ; IS THIS STAMP EARLIER THAN [A]? + 1C08 9008 BCC EAR21 ; IF STILL SMALLER, TRY NEXT STAMP + + 1C0A BC8008 LDY LRUMAP,X + 1C0D F003 BEQ EAR21 + 1C0F 98 TYA + 1C10 869A STX SWAP + + 1C12 E8 EAR21: INX + 1C13 E497 CPX PMAX ; OUT OF BUFFERS? + 1C15 90EE BCC EAR20 ; LOOP TILL EMPTY + + 1C17 8599 EAR24: STA LRU ; [A] HAS EARLIEST STAMP + ; CMP #2 ; DON'T MAKE IT 0 + ; BCC EAR25 + 1C19 C699 DEC LRU ; MAKE SO END RESULT NOT 0 + 1C1B ACEE1B EAR25: LDY SAVEY + 1C1E 60 RTS ; [SWAP] HAS INDEX TO EARLIEST BUFFER + END + + INCLUD MACHINE.ASM ; M + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 96 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + + 1C1F ; ------------ + 1C1F ; CLEAR SCREEN + 1C1F ; ------------ + + 1C1F ; CLEAR SCREEN TO WHITE IF [ARG1] NEGATIVE + 1C1F ; CLEAR SCREEN TO BLACK IF [ARG1] POSITIVE + + 1C1F A900 GCLEAR: LDA #LOW SCREEN ; MAKE [I] POINT TO + 1C21 857A STA I+LO ; THE 1ST BYTE OF + 1C23 A9A1 LDA #HIGH SCREEN ; SCREEN RAM + 1C25 857B STA I+HI + + 1C27 A21E LDX #30 ; # PAGES TO CLEAR + 1C29 A000 LDY #0 ; INIT LOOP INDEX + + 1C2B A56E LDA ARG1+HI ; IF [ARG1] + 1C2D 3004 BMI GCLSN ; NEGATIVE CLEAR TO WHITE + 1C2F A900 LDA #00 + 1C31 F002 BEQ GCLS ; CLEAR SCREEN TO BLACK + 1C33 A9FF GCLSN: LDA #$FF ; ELSE CLEAR TO WHITE + 1C35 917A GCLS: STA (I),Y + 1C37 C8 INY + 1C38 D0FB BNE GCLS + 1C3A E67B INC I+HI + 1C3C CA DEX + 1C3D D0F6 BNE GCLS + 1C3F 60 RTS + + 1C40 ; ------------------------ + 1C40 ; TEXT (ATARI SCREEN CODE) + 1C40 ; ------------------------ + + 1C40 296E7465 ERRM: DB 41,110,116,101,114,110,97,108,0 ; INTERNAL + 1C49 2572726F DB 37,114,114,111,114,0,3,0 ; ERROR # + 0011 ERRML EQU $-ERRM + + 1C51 252E2400 ENDM: DB 37,46,36,0,47,38,0 ; END OF + 1C58 33253333 DB 51,37,51,51,41,47,46 ; SESSION + 000E ENDML EQU $-ENDM + + 1C5F ; ----- + 1C5F ; ERROR + 1C5F ; ----- + + 1C5F ; ENTRY: ERROR CODE IN [A] + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 97 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + 1C5F 8500 GERROR: STA $00 ; SAVE ERROR CODE + 1C61 20A61C JSR STATUS ; SET UP STATUS LINE + + 1C64 A240 LDX #LOW ERRM ; GET LSB + 1C66 A91C LDA #HIGH ERRM ; AND MSB OF TEXT ADDRESS + 1C68 A011 LDY #ERRML ; AND ITS LENGTH + 1C6A 20E51C JSR PRINT ; PRINT "INTERNAL ERROR #" + + 1C6D A500 LDA $00 ; RETRIEVE ERROR CODE + 1C6F 20CE1C JSR HEX ; DISPLAY IT IN HEX + 1C72 A900 LDA #0 + 1C74 20DD1C JSR CHAR ; PRINT A SPACE + 1C77 4C811C JMP GOVER ; AND PRINT "GAME OVER" + + 1C7A ; ---- + 1C7A ; QUIT + 1C7A ; ---- + + 1C7A 20A61C GQUIT: JSR STATUS ; SET UP MESSAGE LINE + 1C7D A90D LDA #13 + 1C7F 85F5 STA CURSOR ; CENTER TEXT + + 1C81 A251 GOVER: LDX #LOW ENDM ; LSB AND + 1C83 A91C LDA #HIGH ENDM ; MSB OF TEXT ADDRESS + 1C85 A00E LDY #ENDML ; LENGTH + 1C87 20E51C JSR PRINT ; PRINT "GAME OVER" + + 1C8A AD1FD0 HOLD: LDA CONSOL ; WAIT FOR CONSOLE KEYPRESS + 1C8D C907 CMP #7 + 1C8F F0F9 BEQ HOLD + 1C91 AD1FD0 LETGO: LDA CONSOL ; WAIT FOR KEY RELEASE + 1C94 C907 CMP #7 + 1C96 D0F9 BNE LETGO + + 1C98 4CEB0B JMP COLD ; AND DO A COLDSTART + + 1C9B ; ----------------- + 1C9B ; CLEAR STATUS LINE + 1C9B ; ----------------- + + 1C9B A24F NEWLIN: LDX #79 + 1C9D A900 LDA #0 + 1C9F 9DA003 NEWL0: STA TEXT,X + 1CA2 CA DEX + 1CA3 10FA BPL NEWL0 + 1CA5 60 RTS + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 98 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + 1CA6 ; ------------------ + 1CA6 ; SET UP STATUS LINE + 1CA6 ; ------------------ + + 1CA6 ; FOR ERRORS & DEBUGGER + + 1CA6 209B1C STATUS: JSR NEWLIN + + 1CA9 A900 LDA #0 + 1CAB 85F5 STA CURSOR + + 1CAD A215 LDX #LOW DL1 ; TELL THE D-LIST WHERE + 1CAF A90B LDA #HIGH DL1 ; TO START ITSELF + 1CB1 8EE90B STX DLTOP+LO + 1CB4 8DEA0B STA DLTOP+HI + 1CB7 8E3002 STX SDLSTL+LO ; ALSO TELL ANTIC + 1CBA 8D3102 STA SDLSTL+HI ; WHERE TO FIND OUR LIST + 1CBD 60 RTS + + 1CBE ; ---------------- + 1CBE ; PRINT [A] IN HEX + 1CBE ; ---------------- + + 1CBE ; HEX CHARS IN ATARI SCREEN CODE + + 1CBE 10111213 HCHARS: DB 16,17,18,19,20,21,22,23,24,25 ; 0-9 + 1CC8 21222324 DB 33,34,35,36,37,38 ; A-F + + 1CCE 48 HEX: PHA ; SAVE HERE + 1CCF 4A LSR A ; SHIFT TOP NIBBLE + 1CD0 4A LSR A ; INTO POSITION + 1CD1 4A LSR A + 1CD2 4A LSR A + 1CD3 20D71C JSR NIBBLE ; AND PRINT IT + 1CD6 68 PLA ; RETRIEVE BYTE + + 1CD7 290F NIBBLE: AND #%00001111 ; ISOLATE BITS 3-0 + 1CD9 AA TAX + 1CDA BDBE1C LDA HCHARS,X + + 1CDD ; FALL THROUGH ... + + 1CDD ; ----------------- + 1CDD ; PRINT CHAR IN [A] + 1CDD ; ----------------- + + 1CDD A6F5 CHAR: LDX CURSOR + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 99 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + 1CDF 9DA003 STA TEXT,X + 1CE2 E6F5 INC CURSOR + 1CE4 60 RTS + + 1CE5 ; ---------- + 1CE5 ; PRINT TEXT + 1CE5 ; ---------- + + 1CE5 ; ENTRY: TEXT ADDRESS IN [X/A] (LSB/MSB) + 1CE5 ; TEXT LENGTH IN [Y] + + 1CE5 86F2 PRINT: STX LINE+LO ; LSB OF ADDRESS + 1CE7 85F3 STA LINE+HI ; MSB OF ADDRESS + 1CE9 84F4 STY LEN ; LENGTH + + 1CEB A000 LDY #0 + 1CED A6F5 LDX CURSOR + 1CEF B1F2 PR0: LDA (LINE),Y + 1CF1 9DA003 STA TEXT,X + 1CF4 E8 INX + 1CF5 C8 INY + 1CF6 C6F4 DEC LEN + 1CF8 D0F5 BNE PR0 + 1CFA 86F5 STX CURSOR + 1CFC 60 RTS + + 1CFD ; ------ + 1CFD ; MEMTOP + 1CFD ; ------ + + 1CFD ; EXIT: [A]=$A0 IF 48K, ELSE [A]=0 + + 1CFD A900 MEMTOP: LDA #0 ; CLEAR $A000 + 1CFF 8D00A0 STA $A000 + 1D02 AE00A0 LDX $A000 ; CHECK THE VALUE + 1D05 D002 BNE EMPTY ; RETURN [A]=0 IF NON-ZERO + 1D07 A9A0 LDA #$A0 ; ELSE RETURN $A0 + 1D09 60 EMPTY: RTS + + 1D0A ; ------ + 1D0A ; RANDOM + 1D0A ; ------ + + 1D0A ; EXIT: RANDOM 16-BIT WORD IN [X/A] + + 1D0A AD0AD2 DORAND: LDA RANDOM + 1D0D EA NOP ; A PAUSE ... + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 100 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + 1D0E AE0AD2 LDX RANDOM + 1D11 60 RTS + + 1D12 ; ------------ + 1D12 ; SIMPLE DELAY + 1D12 ; ------------ + + 1D12 ; ENTRY: NEGATIVE JIFFY COUNT IN [VALUE] + + 1D12 A900 DELAY: LDA #0 ; WAIT A JIFFY + 1D14 8514 STA RTCLOK + 1D16 A514 DEL1: LDA RTCLOK + 1D18 F0FC BEQ DEL1 + + 1D1A E678 INC VALUE+LO + 1D1C D0F4 BNE DELAY + 1D1E E679 INC VALUE+HI + 1D20 D0F0 BNE DELAY + + 1D22 F019 BEQ MOVED ; GET A VALUE AND RETURN + + 1D24 ; ----- + 1D24 ; INPUT + 1D24 ; ----- + + 1D24 A56D GINPUT: LDA ARG1+LO ; MOVE [ARG1] INTO [VALUE] + 1D26 8578 STA VALUE+LO + 1D28 A56E LDA ARG1+HI + 1D2A 8579 STA VALUE+HI + + 1D2C A56C LDA NARGS ; IF THERE ARE 2 ARGS THEN DO THE TABLE + 1D2E C901 CMP #1 ; ITERATIONS + 1D30 F003 BEQ NOIT + 1D32 4CAC17 JMP ITRATE ; YES VIRGINIA, A JUMP + + 1D35 A579 NOIT: LDA VALUE+HI + 1D37 30D9 BMI DELAY ; DO A SIMPLE DELAY + + 1D39 0578 ORA VALUE+LO ; IF NON-ZERO, + 1D3B D006 BNE TICK ; ENTER SENSE LOOP + + 1D3D 205D1D MOVED: JSR SENSE ; ELSE READ JUST ONCE + 1D40 4C600F MOVED2: JMP PUTBYT ; ELSE RETURN [A] + + 1D43 ; INPUT SENSE LOOP + + 1D43 205D1D TICK: JSR SENSE ; GET READING INTO [A] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 101 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + 1D46 C98F CMP #%10001111 ; ANY INPUT? + 1D48 D0F6 BNE MOVED2 ; YES, RETURN IT + + 1D4A A900 LDA #0 ; ELSE WAIT 1 JIFFY + 1D4C 8514 STA RTCLOK + 1D4E A514 TICK1: LDA RTCLOK + 1D50 F0FC BEQ TICK1 + + 1D52 200610 JSR DECVAL ; DECREMENT COUNT + 1D55 A578 LDA VALUE+LO + 1D57 0579 ORA VALUE+HI ; ZERO YET? + 1D59 D0E8 BNE TICK ; NO, LOOP BACK + + 1D5B F0E0 BEQ MOVED ; RETURN + + 1D5D ; ------------------------- + 1D5D ; CHECK KEYBOARD & JOYSTICK + 1D5D ; ------------------------- + + 1D5D ; EXIT: INPUT STATUS IN [A] + + 1D5D A900 SENSE: LDA #0 + 1D5F 854D STA ATRACT ; KILL ATTRACT MODE + + 1D61 ADFC02 LDA CH ; READ THE KEYBOARD REGISTER + 1D64 C9FF CMP #$FF ; KEY PRESSED YET? + 1D66 F01B BEQ STICK ; IF NOT, CHECK STICK + + 1D68 A8 TAY ; ELSE SAVE KEYCODE HERE + 1D69 A2FF LDX #$FF ; RESET THE + 1D6B 8EFC02 STX CH ; KEYBOARD REGISTER + 1D6E 29C0 AND #%11000000 ; SHIFT OR CTRL CHAR? + 1D70 D011 BNE STICK ; IGNORE IF SO + + 1D72 B9921D LDA ATASCI,Y ; GET ATASCII CODE INTO [A] + + 1D75 C961 CMP #'a' ; CONVERT TO + 1D77 9007 BCC KEXIT ; UPPER CASE ALPHA + 1D79 C97B CMP #'z'+1 ; IF NECESSARY + 1D7B B003 BCS KEXIT + 1D7D 38 SEC + 1D7E E920 SBC #$20 + + 1D80 297F KEXIT: AND #%01111111 ; MAKE SURE IT'S POSITIVE + 1D82 60 RTS + + 1D83 ; CHECK THE JOYSTICK + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 102 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + + 1D83 AD7802 STICK: LDA STICK0 + 1D86 290F AND #%00001111 ; MASK GARBAGE + 1D88 AE8402 LDX STRIG0 ; ALSO CHECK TRIGGER + 1D8B D002 BNE STIKEX ; EXIT IF NOT PRESSED + 1D8D 0910 ORA #%00010000 ; ELSE SET BIT 4 + + 1D8F 0980 STIKEX: ORA #%10000000 ; NEGATIVE FOR STICK READING + 1D91 60 RTS ; RETURN WITH CODE IN [A] + + 1D92 ; ------------------------ + 1D92 ; ATASCII CONVERSION TABLE + 1D92 ; ------------------------ + + 1D92 6C6A3B8A ATASCI: DB $6C,$6A,$3B,$8A,$8B,$6B,$2B,$2A + 1D9A 6F807075 DB $6F,$80,$70,$75,$9B,$69,$2D,$3D + 1DA2 7680638C DB $76,$80,$63,$8C,$8D,$62,$78,$7A + 1DAA 34803336 DB $34,$80,$33,$36,$1B,$35,$32,$31 + 1DB2 2C202E6E DB $2C,$20,$2E,$6E,$80,$6D,$2F,$81 + 1DBA 72806579 DB $72,$80,$65,$79,$7F,$74,$77,$71 + 1DC2 39803037 DB $39,$80,$30,$37,$7E,$38,$3C,$3E + 1DCA 66686480 DB $66,$68,$64,$80,$82,$67,$73,$61 + + 1DD2 ; -------------------- + 1DD2 ; DUMP BLOCK TO SCREEN + 1DD2 ; -------------------- + + 1DD2 ; ENTRY: BLOCK TO DUMP IN [BLOCK] (TOP BYTE IN [BLOCK+7]) + 1DD2 ; X-COORDINATE IN [X], Y-COORDINATE IN [A] + + 1DD2 86E4 DUMP: STX TOX ; SAVE X-COORDINATE + 1DD4 0A ASL A ; MULTIPLY Y-COORD BY 8 + 1DD5 0A ASL A ; TO GET MODE LINE (0-191) + 1DD6 0A ASL A + 1DD7 A8 TAY ; USE AS INDEX + + 1DD8 A207 LDX #7 ; INIT BLOCK-FETCHING INDEX + + 1DDA B90009 DUMP0: LDA VLOWS,Y ; GET LSB OF LINE ADDR + 1DDD 18 CLC + 1DDE 65E4 ADC TOX ; ADD X-POS + 1DE0 8DEE1D STA TOADR+LO ; TO GET LSB OF SCREEN ADDR + 1DE3 B9C009 LDA VHIGHS,Y ; GET MSB OF LINE ADDR + 1DE6 6900 ADC #0 + 1DE8 8DEF1D STA TOADR+HI ; FORM MSB OF SCREEN ADDR + + 1DEB B5D3 LDA BLOCK,X ; GET BLOCK DATA + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 103 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + + 1DED 8D DB $8D ; 6502 "STA nnnn" INSTRUCTION + 1DEE 0000 TOADR: DW $0000 ; SCREEN RAM ADDRESS + + 1DF0 C8 INY ; NEXT SCAN LINE + 1DF1 CA DEX ; DONE 8 BYTES YET? + 1DF2 10E6 BPL DUMP0 ; NO, FETCH MORE + 1DF4 60 RTS + + 1DF5 ; ----------------------------------------------- + 1DF5 ; DUMP BLOCK TO SCREEN WITH MASK + 1DF5 ; + 1DF5 ; IF THE MASK BIT IS 1 THEN THE SCREEN SHOWS THRU + 1DF5 ; IF THE MASK BIT IS 0 THEN THE ICON IS DISPLAYED + 1DF5 ; ----------------------------------------------- + + 1DF5 ; ENTRY: BLOCK TO DUMP IN [BLOCK] (TOP BYTE IN [BLOCK+7]) + 1DF5 ; MASK IN [MASK] + 1DF5 ; X-COORDINATE IN [X], Y-COORDINATE IN [A] + + 1DF5 86E4 DMPMSK: STX TOX ; SAVE X-COORDINATE + 1DF7 0A ASL A ; MULTIPLY Y-COORD BY 8 + 1DF8 0A ASL A ; TO GET MODE LINE (0-191) + 1DF9 0A ASL A + 1DFA A8 TAY ; USE AS INDEX + + 1DFB A207 LDX #7 ; INIT BLOCK-FETCHING INDEX + + 1DFD B90009 DMSK0: LDA VLOWS,Y ; GET LSB OF LINE ADDR + 1E00 18 CLC + 1E01 65E4 ADC TOX ; ADD X-POS + 1E03 8D151E STA TOADR2+LO+1 ; TO GET LSB OF SCREEN ADDR + 1E06 8D1E1E STA TOADR3+LO+1 + 1E09 B9C009 LDA VHIGHS,Y ; GET MSB OF LINE ADDR + 1E0C 6900 ADC #0 + 1E0E 8D161E STA TOADR2+HI+1 ; FORM MSB OF SCREEN ADDR + 1E11 8D1F1E STA TOADR3+HI+1 + + 1E14 ADFFFF TOADR2: LDA $FFFF ; DUMMY GET SCREEN BYTE + 1E17 55D3 EOR BLOCK,X + 1E19 35DB AND MASK,X + 1E1B 55D3 EOR BLOCK,X + 1E1D 8DFFFF TOADR3: STA $FFFF ; DUMMY PUT BACK ON SCREEN + + 1E20 C8 INY ; NEXT SCAN LINE + 1E21 CA DEX ; DONE 8 BYTES YET? + 1E22 10D9 BPL DMSK0 ; NO, FETCH MORE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 104 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + 1E24 60 RTS + + 1E25 ; ----- + 1E25 ; SOUND + 1E25 ; ----- + + 1E25 ; PLAY SOUND [ARG1] (1-127) + + 1E25 A56D GSOUND: LDA ARG1+LO + 1E27 3018 BMI SNDERR ; RANGE ERROR! + 1E29 C905 CMP #SOUNDS+1 + 1E2B B014 BCS SNDERR ; SOUND NOT DEFINED + + 1E2D 38 SEC + 1E2E E901 SBC #1 ; ZERO-ALIGN + 1E30 0A ASL A ; AND WORD-ALIGN + 1E31 AA TAX ; THE SOUND ID INDEX + 1E32 BD561F LDA STABLE+LO,X ; GET LSB OF EXECUTION ADDR + 1E35 8D3F1E STA PLAY+LO + 1E38 BD571F LDA STABLE+HI,X ; AND MSB + 1E3B 8D401E STA PLAY+HI + + 1E3E 4C DB $4C ; 6502 "JMP" INSTRUCTION + 1E3F 0000 PLAY: DW $0000 ; SOUND JUMP VECTOR + + 1E41 ; *** ERROR #13: UNDEFINED SOUND *** + + 1E41 A90D SNDERR: LDA #13 + 1E43 4C5F1C JMP GERROR + + 1E46 ; ----- + 1E46 ; COPY? + 1E46 ; ----- + + 1E46 ; IS THIS A LEGAL COPY OF THE DISK? + + 0FAE GCOPYP EQU PREDS + + 1E46 ; ------- + 1E46 ; VERIFY? + 1E46 ; ------- + + 1E46 ; ARE THE GAME AND IMAGE FILES INTACT? + 1E46 ; NOTE: THIS DOES NOT OBSERVE EXTRA BIT LOW + 1E46 ; BUT USES EXTRA BIT HIGH! Le + + 1E46 A900 GVERP: LDA #0 ; CLEAR + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 105 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + 1E48 857C STA J+LO ; ACCUM FOR CHECKSUM + 1E4A 857D STA J+HI + 1E4C 857E STA K+LO + 1E4E 85EB STA DBLOCK ; START AT 1ST GAME SECTOR + 1E50 8587 STA VPCH ; START @ BYTE 0064 + 1E52 8588 STA VPC0 ; USE AS HIGH BIT + 1E54 A940 LDA #64 ; 64 W/LOW BIT IN VPC0 + 1E56 8586 STA VPCL + + 1E58 AD1223 LDA GBEGIN+GLEN ; SET BYTE LENGTH + 1E5B 857B STA I+HI ; FOR GAME CHECK + 1E5D AD1323 LDA GBEGIN+GLEN+1 ; (LENGTH IN WORDS - + 1E60 0A ASL A ; SO MULTIPLY BY 2 + 1E61 857A STA I+LO ; TO GET BYTES + 1E63 267B ROL I+HI + 1E65 267E ROL K+LO + 1E67 4C6E1E JMP READIN ; READ 1ST PAGE IN + + 1E6A A586 VSUM: LDA VPCL ; NEW PAGE? + 1E6C D018 BNE VSUM2 ; NO, CONTINUE + 1E6E A200 READIN: LDX #0 ; SET UP FOR GETDSK + 1E70 86EC STX DBTOP + 1E72 86F1 STX DCNT + 1E74 E8 INX + 1E75 8E0103 STX DUNIT + + 1E78 A952 LDA #$52 ; "READ" + 1E7A 8D0203 STA DCOMND + 1E7D A904 LDA #HIGH BUFFER ; NO MOVE + 1E7F 85EE STA DBUFF+HI + 1E81 A5EB LDA DBLOCK + 1E83 205222 JSR GETGME + + 1E86 A486 VSUM2: LDY VPCL ; GET THIS BYTE + 1E88 B90004 LDA BUFFER,Y + 1E8B E686 INC VPCL ; SET FOR NEXT BYTE + 1E8D D006 BNE VSUM3 + 1E8F E687 INC VPCH + 1E91 D002 BNE VSUM3 + 1E93 E688 INC VPC0 + + 1E95 18 VSUM3: CLC + 1E96 657C ADC J+LO ; ADD IT TO ACCUM + 1E98 857C STA J+LO + 1E9A 9002 BCC VSUM0 + 1E9C E67D INC J+HI + 1E9E A586 VSUM0: LDA VPCL ; CHECK IF ALL BYTES DONE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 106 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + 1EA0 C57A CMP I+LO + 1EA2 D0C6 BNE VSUM + 1EA4 A587 LDA VPCH + 1EA6 C57B CMP I+HI + 1EA8 D0C0 BNE VSUM + 1EAA A588 LDA VPC0 + 1EAC C57E CMP K+LO + 1EAE D0BA BNE VSUM ; AS WORD ALIGNED SIZE + + 1EB0 AD1423 LDA GBEGIN+GCHECK + 1EB3 C57D CMP J+HI + 1EB5 F003 BEQ VSUM4 + 1EB7 4C531F JMP BADVER ; OOPS + 1EBA AD1523 VSUM4: LDA GBEGIN+GCHECK+1 + 1EBD C57C CMP J+LO + 1EBF F003 BEQ IFILE + 1EC1 4C531F JMP BADVER + + 1EC4 ; GAME FILE OK, CHECK IMAGE FILE + + 1EC4 A900 IFILE: LDA #0 + 1EC6 857E STA K+LO + 1EC8 A591 LDA ICODE+LO ; FIND VIRTUAL IBEGIN + 1ECA 857C STA J+LO + 1ECC A592 LDA ICODE+HI + 1ECE 857D STA J+HI + 1ED0 A000 LDY #ILEN ; OFFSET TO LENGTH + 1ED2 B17C LDA (J),Y + 1ED4 857B STA I+HI ; SET I TO LENGTH + 1ED6 C8 INY + 1ED7 B17C LDA (J),Y + 1ED9 0A ASL A ; *2 AS WORD VALUE + 1EDA 857A STA I+LO + 1EDC 267B ROL I+HI + 1EDE 267E ROL K+LO + + 1EE0 A004 LDY #ICHECK ; GET CHECKSUM + 1EE2 B17C LDA (J),Y ; WHILE IT'S EASY + 1EE4 85F7 STA CHKSUM+HI ; SAVE IT HERE + 1EE6 C8 INY + 1EE7 B17C LDA (J),Y + 1EE9 85F6 STA CHKSUM+LO + + 1EEB A900 LDA #0 ; CLEAR FOR IMAGE FILE + 1EED 857C STA J+LO + 1EEF 857D STA J+HI + 1EF1 8587 STA VPCH + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 107 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + 1EF3 8588 STA VPC0 + 1EF5 85EB STA DBLOCK ; SET TO START OF IMAGE SECTORS. + 1EF7 A908 LDA #8 + 1EF9 8586 STA VPCL ; HEADER OF IMAGE FILE + 1EFB 4C021F JMP IRDIN + + 1EFE A586 ISUM: LDA VPCL ; NEW PAGE? + 1F00 D018 BNE ISUM2 ; NO, CONTINUE + 1F02 A200 IRDIN: LDX #0 ; SET UP FOR GETDSK + 1F04 86EC STX DBTOP + 1F06 86F1 STX DCNT + 1F08 E8 INX + 1F09 8E0103 STX DUNIT + + 1F0C A952 LDA #$52 ; "READ" + 1F0E 8D0203 STA DCOMND + 1F11 A904 LDA #HIGH BUFFER ; NO MOVE + 1F13 85EE STA DBUFF+HI + 1F15 A5EB LDA DBLOCK + 1F17 204122 JSR GETIMG + + 1F1A A486 ISUM2: LDY VPCL ; GET THIS BYTE + 1F1C B90004 LDA BUFFER,Y + 1F1F E686 INC VPCL ; SET FOR NEXT BYTE + 1F21 D006 BNE ISUM3 + 1F23 E687 INC VPCH + 1F25 D002 BNE ISUM3 + 1F27 E688 INC VPC0 + + 1F29 18 ISUM3: CLC + 1F2A 657C ADC J+LO ; ADD IT TO ACCUM + 1F2C 857C STA J+LO + 1F2E 9002 BCC ISUM0 + 1F30 E67D INC J+HI + 1F32 A586 ISUM0: LDA VPCL ; CHECK IF ALL BYTES DONE + 1F34 C57A CMP I+LO + 1F36 D0C6 BNE ISUM + 1F38 A587 LDA VPCH + 1F3A C57B CMP I+HI + 1F3C D0C0 BNE ISUM + 1F3E A588 LDA VPC0 + 1F40 C57E CMP K+LO + 1F42 D0BA BNE ISUM ; AS WORD ALIGNED SIZE + + 1F44 A5F6 LDA CHKSUM+LO ; COMPARE TO SAVED CHECKSUM + 1F46 C57C CMP J+LO + 1F48 D009 BNE BADVER + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 108 +--- MACHINE-DEPENDENT ROUTINES: ATARI --- + + 1F4A A5F7 LDA CHKSUM+HI + 1F4C C57D CMP J+HI + 1F4E D003 BNE BADVER + + 1F50 4CAE0F JMP PREDS ; SUCCESS! + + 1F53 4CA20F BADVER: JMP PREDF + + END + INCLUD SOUND.ASM ; M + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 109 +GAME-DEPENDENT SOUND LIBRARY (ATARI FOOBLITSKY) + + + 1F56 ; ---------------------------- + 1F56 ; GAME-DEPENDENT SOUND LIBRARY + 1F56 ; ---------------------------- + + 1F56 5E1F STABLE: DW SND1 + 1F58 661F DW SND2 + 1F5A 7C1F DW SND3 + 1F5C A61F DW SND4 + + 0004 SOUNDS EQU 4 ; # SOUNDS IN LIBRARY + + 1F5E ; ---------------- + 1F5E ; SOUND #1: "BOOP" + 1F5E ; ---------------- + + 1F5E A296 SND1: LDX #150 ; FREQUENCY + 1F60 A9FC LDA #252 ; DURATION (4 JIFFIES) + 1F62 A0AE LDY #$AE ; FULL VOLUME, NO DISTORTION + 1F64 D006 BNE NOISE + + 1F66 ; ----------------- + 1F66 ; SOUND #2: "CLICK" + 1F66 ; ----------------- + + 1F66 A219 SND2: LDX #25 ; FREQUENCY + 1F68 A9FF LDA #255 ; DURATION (1 JIFFY) + 1F6A A0AE LDY #$AE ; FULL VOLUME, NO DISTORTION + + 1F6C ; FALL THROUGH ... + + 1F6C 8E00D2 NOISE: STX AUDF1 + 1F6F 8C01D2 STY AUDC1 + 1F72 8514 STA RTCLOK ; START TIMER + + 1F74 A514 S1L: LDA RTCLOK + 1F76 D0FC BNE S1L + 1F78 8D01D2 STA AUDC1 ; STOP SOUND + 1F7B 60 RTS + + 1F7C ; ---------------- + 1F7C ; SOUND #3: "TING" + 1F7C ; ---------------- + + 1F7C A90A SND3: LDA #10 ; FREQUENCY + 1F7E 8D00D2 STA AUDF1 + 1F81 A9AE LDA #$AE ; FULL, PURE TONE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 110 +GAME-DEPENDENT SOUND LIBRARY (ATARI FOOBLITSKY) + + 1F83 8D01D2 STA AUDC1 + + 1F86 A9FB LDA #251 ; 5-JIFFY SUSTAIN + 1F88 8514 STA RTCLOK + 1F8A A514 S3L1: LDA RTCLOK + 1F8C D0FC BNE S3L1 + + 1F8E ; DECAY TO ZERO VOLUME + + 1F8E A20E LDX #$0E ; VOLUME INDEX + 1F90 8A S3L2: TXA + 1F91 09A0 ORA #$A0 ; SUPERIMPOSE DISTORTION (PURE) + 1F93 8D01D2 STA AUDC1 + + 1F96 A9FC LDA #252 ; WAIT 4 JIFFIES ON EACH LEVEL + 1F98 8514 STA RTCLOK + 1F9A A514 S3L3: LDA RTCLOK + 1F9C D0FC BNE S3L3 + + 1F9E CA DEX + 1F9F CA DEX ; LOOP BACK TILL + 1FA0 D0EE BNE S3L2 ; NO MORE VOLUME + 1FA2 8E01D2 STX AUDC1 ; STOP TONE + 1FA5 60 RTS + + 1FA6 ; ---------------- + 1FA6 ; SOUND #4: "RAZZ" + 1FA6 ; ---------------- + + 1FA6 A964 SND4: LDA #100 ; FREQUENCY + 1FA8 8D00D2 STA AUDF1 + 1FAB A92E LDA #$2E ; LOUD, DISTORTED TONE + 1FAD 8D01D2 STA AUDC1 + + 1FB0 A9FB LDA #251 ; 5-JIFFY SUSTAIN + 1FB2 8514 STA RTCLOK + 1FB4 A514 S4L1: LDA RTCLOK + 1FB6 D0FC BNE S4L1 + + 1FB8 ; DECAY TO ZERO VOLUME + + 1FB8 A20E LDX #$0E ; VOLUME INDEX + 1FBA 8A S4L2: TXA + 1FBB 0920 ORA #$20 ; SUPERIMPOSE DISTORTION + 1FBD 8D01D2 STA AUDC1 + + 1FC0 A9FC LDA #252 ; WAIT 4 JIFFIES ON EACH LEVEL + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 111 +GAME-DEPENDENT SOUND LIBRARY (ATARI FOOBLITSKY) + + 1FC2 8514 STA RTCLOK + 1FC4 A514 S4L3: LDA RTCLOK + 1FC6 D0FC BNE S4L3 + + 1FC8 CA DEX + 1FC9 CA DEX ; LOOP BACK TILL + 1FCA D0EE BNE S4L2 ; NO MORE VOLUME + 1FCC 8E01D2 STX AUDC1 ; STOP TONE + 1FCF 60 RTS + + END + INCLUD SAVE.ASM ; M + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 112 +--- SAVE/RESTORE --- + + + 1FD0 ; -------- + 1FD0 ; GRESTORE + 1FD0 ; -------- + + 1FD0 20C821 GREST: JSR SRINIT ; INIT SCREEN, GET CR + + 1FD3 A900 LDA #0 + 1FD5 8583 STA GPCFLG ; INVALIDATE [GPC] + 1FD7 8589 STA VPCFLG ; AND [VPC] + + 1FD9 A936 LDA #54 + 1FDB 85F5 STA CURSOR ; CENTER TEXT + 1FDD A292 LDX #LOW RSTG + 1FDF A921 LDA #HIGH RSTG + 1FE1 A00E LDY #RSTGL + 1FE3 20E51C JSR PRINT ; "RESTORING ..." + + 1FE6 200721 JSR READ ; READ 1ST BLOCK INTO [BUFFER] + 1FE9 B07F BCS BADRD ; SCRAM IF ERROR + + 1FEB AD0004 LDA BUFFER ; CHECK MSB + 1FEE CD0223 CMP GBEGIN+GID ; OF GAME ID + 1FF1 D077 BNE BADRD ; SCRAM IF NO MATCH + 1FF3 AD0104 LDA BUFFER+1 ; SAME FOR LSB + 1FF6 CD0323 CMP GBEGIN+GID+1 + 1FF9 D06F BNE BADRD + + 1FFB AD0704 LDA BUFFER+7 ; ALSO COMPARE SIZE SAVED + 1FFE C596 CMP PAGE0 ; TO CURRENT SIZE + 2000 D068 BNE BADRD ; EXIT IF BAD + + 2002 AD0204 RST0: LDA BUFFER+2 + 2005 858E STA GSP ; RESTORE [GSP] + 2007 AD0304 LDA BUFFER+3 + 200A 858F STA OLDGSP ; [OLDGSP] + 200C AD0404 LDA BUFFER+4 + 200F 8580 STA GPCL ; [GPCL] + 2011 AD0504 LDA BUFFER+5 + 2014 8581 STA GPCH ; [GPCH] + 2016 AD0504 LDA BUFFER+5 + 2019 8581 STA GPCH ; [GPCH] + 201B AD0604 LDA BUFFER+6 + 201E 8582 STA GPC0 ; [GPC0] + + 2020 A200 LDX #0 + 2022 8683 STX GPCFLG ; INVALIDATE [GPC] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 113 +--- SAVE/RESTORE --- + + 2024 8689 STX VPCFLG ; AND [VPC] + 2026 E8 INX ; = 1 + 2027 8698 STX STAMP ; RESET TIMESTAMP (?) + + 2029 A24F LDX #79 ; RESTORE [LOCALS], [CARGS], [CTYPES] + 202B BD0804 RST1: LDA BUFFER+8,X + 202E 9D800A STA LOCALS,X + 2031 CA DEX + 2032 10F7 BPL RST1 + + 2034 200721 JSR READ ; RESTORE [GSTAKL] + 2037 B031 BCS BADRD + 2039 200721 JSR READ ; AND [GSTAKH] + 203C B02C BCS BADRD + + 203E A900 LDA #LOW GBEGIN ; POINT [DBUFLO/HI] + 2040 8D0403 STA DBUFLO ; TO PRELOAD + 2043 A923 LDA #HIGH GBEGIN + 2045 8D0503 STA DBUFHI + + 2048 200721 RST2: JSR READ ; READ A BLOCK + 204B B01D BCS BADRD ; EXIT IF ERROR + 204D AD0503 LDA DBUFHI ; END OF PRELOAD YET? + 2050 C596 CMP PAGE0 + 2052 D0F4 BNE RST2 ; NO, KEEP READING + + 2054 209B1C JSR NEWLIN ; CLEAR STATUS LINE + 2057 A90E LDA #14 + 2059 85F5 STA CURSOR ; CENTER TEXT + 205B A2BA LDX #LOW GRD + 205D A921 LDA #HIGH GRD + 205F A00E LDY #GRDL + 2061 20E51C JSR PRINT ; "GAME RESTORED" + + 2064 200222 JSR GETGD ; "INSERT GAME DISK, PRESS START" + 2067 4CAE0F JMP PREDS ; SUCCEEDS + + 206A 4CED20 BADRD: JMP SRERR ; ELSE FAILS + + 206D ; ----- + 206D ; GSAVE + 206D ; ----- + + 206D 20C821 GSAVE: JSR SRINIT ; INIT SCREEN, GET CR + + 2070 A935 LDA #53 + 2072 85F5 STA CURSOR ; CENTER TEXT + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 114 +--- SAVE/RESTORE --- + + 2074 A282 LDX #LOW SVG + 2076 A921 LDA #HIGH SVG + 2078 A010 LDY #SVGL + 207A 20E51C JSR PRINT ; "SAVING GAME ..." + + 207D AD0223 LDA GBEGIN+GID ; SAVE 1ST + 2080 8D0004 STA BUFFER ; AND + 2083 AD0323 LDA GBEGIN+GID+1 ; 2ND BYTES OF + 2086 8D0104 STA BUFFER+1 ; GAME ID WORD + + 2089 A58E LDA GSP + 208B 8D0204 STA BUFFER+2 ; SAVE [GSP] + 208E A58F LDA OLDGSP + 2090 8D0304 STA BUFFER+3 ; SAVE [OLDGSP] + + 2093 A580 LDA GPCL ; SAVE [GPC] + 2095 8D0404 STA BUFFER+4 + 2098 A581 LDA GPCH + 209A 8D0504 STA BUFFER+5 + 209D A582 LDA GPC0 + 209F 8D0604 STA BUFFER+6 + + 20A2 A596 LDA PAGE0 ; SAVE SIZE OF PRELOADS + 20A4 8D0704 STA BUFFER+7 + + 20A7 A24F LDX #79 ; SAVE [LOCALS], [CARGS] & [CTYPES] + 20A9 BD800A SV0: LDA LOCALS,X + 20AC 9D0804 STA BUFFER+8,X + 20AF CA DEX + 20B0 10F7 BPL SV0 + + 20B2 200321 JSR WRITE ; WRITE [BUFFER] BLOCK + 20B5 B036 BCS SRERR + 20B7 200321 JSR WRITE ; WRITE [GSTAKL] + 20BA B031 BCS SRERR + 20BC 200321 JSR WRITE ; WRITE [GSTAKH] + 20BF B02C BCS SRERR + + 20C1 A900 LDA #LOW GBEGIN ; POINT TO START OF PRELOADS + 20C3 8D0403 STA DBUFLO + 20C6 A923 LDA #HIGH GBEGIN + 20C8 8D0503 STA DBUFHI + + 20CB 200321 SV1: JSR WRITE ; WRITE BLOCK + 20CE B01D BCS SRERR ; SCRAM IF ERROR + 20D0 AD0503 LDA DBUFHI ; WRITTEN ALL OF + 20D3 C596 CMP PAGE0 ; PRELOAD(S)? + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 115 +--- SAVE/RESTORE --- + + 20D5 D0F4 BNE SV1 ; NO, WRITE SOME MORE + + 20D7 209B1C JSR NEWLIN ; CLEAR STATUS LINE + 20DA A90E LDA #14 + 20DC 85F5 STA CURSOR ; CENTER TEXT + 20DE A2AC LDX #LOW SCOM + 20E0 A921 LDA #HIGH SCOM + 20E2 A00E LDY #SCOML + 20E4 20E51C JSR PRINT ; "SAVE COMPLETE" + + 20E7 200222 JSR GETGD ; "INSERT GAME DISK" + 20EA 4CAE0F JMP PREDS ; PREDICATE SUCCEEDS + + 20ED ; ------------------ + 20ED ; SAVE/RESTORE ERROR + 20ED ; ------------------ + + 20ED 209B1C SRERR: JSR NEWLIN ; CLEAR STATUS LINE + + 20F0 A90F LDA #15 + 20F2 85F5 STA CURSOR ; CENTER TEXT + + 20F4 A2A0 LDX #LOW DXX + 20F6 A921 LDA #HIGH DXX + 20F8 A00C LDY #DXXL + 20FA 20E51C JSR PRINT ; "DISK ERROR!" + + 20FD 200222 JSR GETGD ; "INSERT GAME DISK, PRESS START" + 2100 4CA20F JMP PREDF ; PREDICATE FAILED + + 2103 ; ------------------- + 2103 ; WRITE BLOCK TO DISK + 2103 ; ------------------- + + 2103 A957 WRITE: LDA #$57 ; SIO "WRITE" COMMAND + 2105 D002 BNE DDISK + + 2107 ; -------------------- + 2107 ; READ BLOCK FROM DISK + 2107 ; -------------------- + + 2107 A952 READ: LDA #$52 ; SIO "READ" COMMAND + + 2109 8D0203 DDISK: STA DCOMND ; SET READ/WRITE MODE + + 210C A901 LDA #1 ; ALWAYS USE + 210E 8D0103 STA DUNIT ; DRIVE #1 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 116 +--- SAVE/RESTORE --- + + + 2111 2053E4 JSR DSKINV ; ACCESS 1ST HALF + 2114 AD0303 LDA DSTATS + 2117 3010 BMI BADISK ; EXIT IF ERROR + + 2119 202B21 JSR NEXTSC ; SET UP NEXT ACCESS + + 211C 2053E4 JSR DSKINV ; ACCESS 2ND HALF + 211F AD0303 LDA DSTATS + 2122 3005 BMI BADISK ; EXIT IF ERROR + + 2124 202B21 JSR NEXTSC ; SET UP NEXT ACCESS + 2127 18 CLC ; CARRY CLEAR = OKAY + 2128 60 RTS + + 2129 38 BADISK: SEC ; CARRY SET = BAD I/O + 212A 60 RTS + + 212B ; --------------------------- + 212B ; POINT TO NEXT SECTOR/BUFFER + 212B ; --------------------------- + + 212B EE0A03 NEXTSC: INC DAUX1 ; LSB OF SECTOR ID + 212E D003 BNE NXC + 2130 EE0B03 INC DAUX2 ; MSB + + 2133 AD0403 NXC: LDA DBUFLO ; POINT TO 2ND HALF + 2136 D8 CLD ; OF BUFFER + 2137 18 CLC + 2138 6980 ADC #$80 + 213A 8D0403 STA DBUFLO + 213D AD0503 LDA DBUFHI + 2140 6900 ADC #0 + 2142 8D0503 STA DBUFHI + 2145 60 RTS + + 2146 ; -------------------- + 2146 ; SAVE & RESTORE TEXT + 2146 ; IN ATARI SCREEN CODE + 2146 ; -------------------- + + 2146 ; INSERT SAVE DISK, PRESS START + + 2146 296E7365 SAVEM: DB 41,110,115,101,114,116,0 + 214D 33213625 DB 51,33,54,37,0 + 2152 6469736B DB 100,105,115,107,12,0 + 2158 70726573 DB 112,114,101,115,115,0 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 117 +--- SAVE/RESTORE --- + + 215E B3B4A1B2 DB 179,180,161,178,180,0 + 001E SAVEML EQU $-SAVEM + + 2164 ; INSERT GAME DISK, PRESS START + + 2164 296E7365 RESTM: DB 41,110,115,101,114,116,0 + 216B 27212D25 DB 39,33,45,37,0 + 2170 6469736B DB 100,105,115,107,12,0 + 2176 70726573 DB 112,114,101,115,115,0 + 217C B3B4A1B2 DB 179,180,161,178,180,0 + 001E RESTML EQU $-RESTM + + 2182 ; SAVING GAME ... + + 2182 33617669 SVG: DB 51,97,118,105,110,103,0 + 2189 67616D65 DB 103,97,109,101,0,14,14,14,0 + 0010 SVGL EQU $-SVG + + 2192 ; RESTORING ... + + 2192 32657374 RSTG: DB 50,101,115,116,111,114,105,110,103,0,14,14,14,0 + 000E RSTGL EQU $-RSTG + + 21A0 ; DISK ERROR! + + 21A0 2429332B DXX: DB 36,41,51,43,0,37,50,50,47,50,1,0 + 000C DXXL EQU $-DXX + + 21AC ; SAVE COMPLETE + + 21AC 33213625 SCOM: DB 51,33,54,37,0,35,47,45,48,44,37,52,37,0 + 000E SCOML EQU $-SCOM + + 21BA ; GAME RESTORED + + 21BA 27212D25 GRD: DB 39,33,45,37,0,50,37,51,52,47,50,37,36,0 + 000E GRDL EQU $-GRD + + 21C8 ; ------------------------ + 21C8 ; INIT SAVE/RESTORE SCREEN + 21C8 ; ------------------------ + + 21C8 20A61C SRINIT: JSR STATUS ; SET UP STATUS LINE + + 21CB A903 LDA #3 + 21CD 8541 STA SOUNDR ; ENABLE NOISY I/O + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 118 +--- SAVE/RESTORE --- + + 21CF A906 LDA #6 + 21D1 85F5 STA CURSOR ; CENTER TEXT + + 21D3 A246 LDX #LOW SAVEM + 21D5 A921 LDA #HIGH SAVEM + 21D7 A01E LDY #SAVEML + 21D9 20E51C JSR PRINT ; "INSERT SAVE DISK ..." + + 21DC A901 LDA #1 ; POINT [DAUX1/2] TO SECTOR 1 + 21DE 8D0A03 STA DAUX1 + 21E1 A900 LDA #0 + 21E3 8D0B03 STA DAUX2 + + 21E6 A900 LDA #LOW BUFFER ; AND TO [BUFFER] + 21E8 8D0403 STA DBUFLO + 21EB A904 LDA #HIGH BUFFER + 21ED 8D0503 STA DBUFHI + + 21F0 ; FALL THROUGH ... + + 21F0 ; ----------------- + 21F0 ; WAIT FOR "START" + 21F0 ; ----------------- + + 21F0 207C1F GETST: JSR SND3 ; "TING" + + 21F3 AD1FD0 GST0: LDA CONSOL + 21F6 C906 CMP #6 + 21F8 D0F9 BNE GST0 + 21FA AD1FD0 GST1: LDA CONSOL + 21FD C907 CMP #7 + 21FF D0F9 BNE GST1 + 2201 60 RTS + + 2202 ; -------------------- + 2202 ; PROMPT FOR GAME DISK + 2202 ; -------------------- + + 2202 A92E GETGD: LDA #46 + 2204 85F5 STA CURSOR ; CENTER LINE + + 2206 A264 LDX #LOW RESTM + 2208 A921 LDA #HIGH RESTM + 220A A01E LDY #RESTML + 220C 20E51C JSR PRINT ; "INSERT GAME DISK ..." + + 220F 20F021 JSR GETST ; GET START KEY + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 119 +--- SAVE/RESTORE --- + + + 2212 A21F LDX #LOW DL2 ; SWITCH BACK TO + 2214 A90B LDA #HIGH DL2 ; FULL-SCREEN DLIST + 2216 8EE90B STX DLTOP+LO + 2219 8DEA0B STA DLTOP+HI + 221C 8E3002 STX SDLSTL+LO + 221F 8D3102 STA SDLSTL+HI + + 2222 A900 LDA #0 + 2224 8541 STA SOUNDR ; DISABLE NOISY I/O + 2226 60 RTS + + END + INCLUD GROS.ASM ; M + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 120 +--- GRIP OPERATING SYSTEM: ATARI --- + + + 0037 GAME EQU 3*18+1 ; 1ST G-CODE BLOCK (55; TRACK 3, SECTOR 1) + 00FD IMAGE EQU 14*18+1 ; 1ST I-FILE BLOCK (253; TRACK 14, SECTOR 1) + 0480 BUFTOP EQU BUFFER+$80 ; TOP HALF OF [BUFFER] + + 2227 ;-------------------------------------------------- + 2227 ; FETCH VIRTUAL PAGE [DBLOCK] AND PUT AT RAM PAGES + 2227 ; [DBUFF],[DBUFF]+1. + 2227 ; ON EXIT POINT [DBLOCK] AT NEXT V-PAGE AND POINT + 2227 ; [DBUFF] TO NEXT RAM PAGE + 2227 ;-------------------------------------------------- + + 2227 ; ---------------- + 2227 ; GET A DISK BLOCK + 2227 ; ---------------- + + 2227 A200 GETDSK: LDX #0 + 2229 86EC STX DBTOP ; CLEAR MSB OF BLOCK INDEX + 222B E8 INX ; = 1 + 222C 8E0103 STX DUNIT ; ALWAYS USE DRIVE #1 + 222F 86F1 STX DCNT ; COUNTER FOR LOOP TO GET (2) 256 BYTE PAGES + + + 2231 A952 LDA #$52 ; SIO "READ" COMMAND + 2233 8D0203 STA DCOMND + + 2236 ; CALC WHICH DISK SECTORS TO GET + + 2236 A5EB LDA DBLOCK ; GET THE VIRTUAL PAGE INDEX + 2238 C594 CMP ISTART ; IT IS BELOW THE IMAGE FILE? + 223A 9013 BCC GETGAM ; IF SO, IT'S IN THE GAME FILE + + 223C ; GET BLOCK [A] FROM THE IMAGE FILE + + 223C E594 SBC ISTART ; ZERO-ALIGN THE BLOCK INDEX + 223E 0A ASL A ; * 2 FOR ATARI 128-BYTE SECTORS + 223F 26EC ROL DBTOP ; BUILD MSB + + 2241 ; ENTRY POINT FOR VERIFY + + 2241 0A GETIMG: ASL A ; * 2 AGAIN FOR 512 BYTE PAGES + 2242 26EC ROL DBTOP + 2244 18 CLC + 2245 69FD ADC #LOW IMAGE ; ADD THE PHYSICAL I-FILE OFFSET + 2247 AA TAX ; SAVE LSB HERE + + 2248 A5EC LDA DBTOP ; DO MSB + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 121 +--- GRIP OPERATING SYSTEM: ATARI --- + + 224A 6900 ADC #HIGH IMAGE + 224C 4C5B22 JMP DODSK + + 224F ; GET BLOCK [A] FROM THE GAME FILE + + 224F 0A GETGAM: ASL A ; * 2 FOR 128-BYTE SECTORS + 2250 26EC ROL DBTOP + + 2252 ; ENTRY POINT FOR VERIFY + + 2252 0A GETGME: ASL A ; * 2 AGAIN FOR 512 BYTE PAGES + 2253 18 CLC + 2254 6937 ADC #LOW GAME ; ADD THE PHYSICAL G-FILE OFFSET + 2256 AA TAX ; SAVE LSB HERE + + 2257 A5EC LDA DBTOP ; TAKE CARE OF MSB + 2259 6900 ADC #HIGH GAME + + 225B ; VALIDATE SECTOR ADDRESS IN [X/A] (LSB/MSB) + 225B ; MUST BE NO HIGHER THAN 717 ($02CD) + + 225B C902 DODSK: CMP #$02 ; MSB OUT OF RANGE? + 225D 900B BCC ROK ; OK IF MSB < 2 + 225F F005 BEQ T717 ; CHECK LSB IF MSB = 2 + + 2261 ; *** ERROR #10: DISK ADDRESS RANGE *** + + 2261 A90A RANGE: LDA #10 + 2263 4C5F1C JMP GERROR + + 2266 E0CE T717: CPX #$CE ; MSB WAS 2; IS LSB > $CD? + 2268 B0F7 BCS RANGE ; RANGE ERROR IF SO + + 226A 86EF ROK: STX SECTOR+LO + 226C 85F0 STA SECTOR+HI + + 226E A5EF DSKLP1: LDA SECTOR+LO + 2270 8D0A03 STA DAUX1 ; LSB OF SECTOR ADDRESS + 2273 A5F0 LDA SECTOR+HI + 2275 8D0B03 STA DAUX2 ; MSB OF SECTOR ADDRESS + + 2278 A900 LDA #LOW BUFFER + 227A 8D0403 STA DBUFLO + 227D A904 LDA #HIGH BUFFER + 227F 8D0503 STA DBUFHI + + 2282 ; FETCH DISK BLOCK INTO [BUFFER] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 122 +--- GRIP OPERATING SYSTEM: ATARI --- + + + 2282 2053E4 JSR DSKINV ; GET 1ST HALF OF BLOCK + 2285 AD0303 LDA DSTATS ; IF STATUS IS NEGATIVE, + 2288 3040 BMI DERR ; SOMETHING WENT WRONG + + 228A A980 LDA #LOW BUFTOP ; POINT TO + 228C 8D0403 STA DBUFLO ; TOP HALF-PAGE + 228F A904 LDA #HIGH BUFTOP ; OF [BUFFER] + 2291 8D0503 STA DBUFHI + + 2294 E6EF INC SECTOR+LO ; ALSO POINT + 2296 D002 BNE DODSK1 ; TO THE + 2298 E6F0 INC SECTOR+HI ; NEXT SECTOR + + 229A A5EF DODSK1: LDA SECTOR+LO + 229C 8D0A03 STA DAUX1 + 229F A5F0 LDA SECTOR+HI + 22A1 8D0B03 STA DAUX2 + + 22A4 2053E4 JSR DSKINV ; GET 2ND HALF OF BLOCK + 22A7 AD0303 LDA DSTATS ; ERROR IF + 22AA 301E BMI DERR ; [DSTATS] RETURNED NEGATIVE + + 22AC ; MOVE [BUFFER] TO PAGE [DBUFF] + + 22AC A000 LDY #0 + 22AE 84ED STY DBUFF+LO ; MAKE SURE LSB IS ZEROED! + 22B0 B90004 MOVEB: LDA BUFFER,Y + 22B3 91ED STA (DBUFF),Y + 22B5 C8 INY + 22B6 D0F8 BNE MOVEB + + 22B8 E6EE INC DBUFF+HI ; POINT TO NEXT RAM PAGE + 22BA C6F1 DEC DCNT + 22BC 3009 BMI DSKP1 + + 22BE E6EF INC SECTOR+LO + 22C0 D002 BNE DSKP0 + 22C2 E6F0 INC SECTOR+HI + 22C4 4C6E22 DSKP0: JMP DSKLP1 + + + 22C7 E6EB DSKP1: INC DBLOCK ; POINT TO NEXT VIRTUAL PAGE + 22C9 60 RTS + + 22CA ; *** ERROR #11: DISK ACCESS *** + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT PAGE 123 +--- GRIP OPERATING SYSTEM: ATARI --- + + 22CA A90B DERR: LDA #11 + 22CC 4C5F1C JMP GERROR + + END + + 22CF IF DEBUG + 22CF INCLUD BUGGER.ASM + 22CF ENDIF + + 0000 END + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- SYMBOL TABLE PAGE 124 +---- SYMBOL TABLE ---- + + 142B BSADR 00D0 DECVAL 1006 DSKP1 22C7 GBITSP 1227 + 0CF8 BSET 00CF DEL1 1D16 DSTATS 0303 GBL1 198D + 0CF8 BSIZE 00D2 DELAY 1D12 DUMMY 0B0E GBL2 1996 + 142B BTAB 009E DERR 22CA DUMP 1DD2 GBL3 19AA +A12VAL 1012 BUFFER 0400 DIVERR 11F4 DUMP0 1DDA GBL4 19AE +A2VAL 128F BUFTOP 0480 DIVEX 11B4 DUNIT 0301 GBLL 19F4 +ABQUOT 11B5 CALCB 12DC DIVIDE 1177 DVX 1011 GBLLL 1A06 +ABREM 11A7 CALCW 12E5 DL1 0B15 DXX 21A0 GBLX 19BF +ABSDIV 118C CALL1 13A9 DL2 0B1F DXXL 000C GBNOT 10D1 +ABYTE 0075 CALL2 13CC DL2A 0B34 EAR0 1BDE GBXOR 121B +ADDGPC 18D9 CALL3 13D2 DLS0 126E EAR1 1BE8 GCALC 0D06 +ADDIA1 192F CALL4 13E4 DLTOP 0BE9 EAR20 1C05 GCALL 12F7 +ADDIA2 1906 CARGS 0AA0 DMACTL D400 EAR21 1C12 GCHECK 0014 +ADDVPC 18AA CH 02FC DMPMSK 1DF5 EAR22 1C04 GCL 12FB +ADEX 0076 CHAR 1CDD DMSK0 1DFD EAR23 1BF6 GCL0 1307 +ADEX2 0077 CHKSUM 00F6 DOB2 0FCF EAR24 1C17 GCL1 130F +ADIS2 1913 CIOV E456 DOCALL 137A EAR25 1C1B GCL2 1315 +ADISK 193C CIX 00F2 DODIS 0E4D EARLY 1BD6 GCL3 132E +AGISK 18E6 CLPRI2 15F7 DODSK 225B EARLY2 1BEF GCL4 133D +ARG1 006D CLPRIA 165D DODSK1 229A EMPTY 1D09 GCL5 1350 +ARG2 006F CLRT 0C6B DOFIT 1A92 ENDM 1C51 GCL6 135A +ARG3 0071 CLRZ 0C65 DOGET 12CB ENDML 000E GCL7 135D +ARG4 0073 COLCRS 0055 DOMASK 1610 ENOUGH 0CF2 GCL8 136F +ATASCI 1D92 COLD 0BEB DOPUT 10C0 EQP1 1247 GCLEAR 1C1F +ATRACT 004D COLDST 0244 DORAND 1D0A EQP2 1253 GCLS 1C35 +AUDC1 D201 COLDSV E477 DOSINI 000C ERRM 1C40 GCLSN 1C33 +AUDC2 D203 COLOR1 02C5 DOSVEC 000A ERRML 0011 GCODE 0090 +AUDC3 D205 COLOR2 02C6 DOXOP 0E3E FADD DA66 GCOPYP 0FAE +AUDC4 D207 COMPAR 1297 DRAW 15CE FALSE 0000 GDEC 10B8 +AUDCTL D208 CONSOL D01F DRAWE2 1575 FASC D8E6 GDIV 1163 +AUDF1 D200 CRSINH 02F0 DRAWEX 1506 FDIV DB28 GDLESP 126B +AUDF2 D202 CTYPES 0AC0 DRAWI1 1516 FIT 1A9D GDUMP 14B1 +AUDF3 D204 CURSOR 00F5 DRAWI2 151D FIT0 1AA9 GEND 0004 +AUDF4 D206 DAUX1 030A DRAWI3 1507 FIT2 1AB7 GEQP 1239 +AVISK 18B7 DAUX2 030B DRAWI4 151F FIT3 1ABE GERROR 1C5F +B2MASK 167E DBLOCK 00EB DRAWI5 1532 FITEX 1AD1 GETBLK 19C0 +B2MLP 1680 DBTOP 00EC DRAWI6 1540 FMOVE DDB6 GETBS 1949 +BADISK 2129 DBUFF 00ED DRAWI7 1549 FMUL DADB GETBYT 1B25 +BADOP1 0E9D DBUFHI 0305 DRAWI8 1585 FPI D9D2 GETDSK 2227 +BADOP2 0EDA DBUFLO 0304 DRAWI9 158C FR0 00D4 GETGAM 224F +BADRD 206A DC0 0DE0 DRAWIA 1576 FR1 00E0 GETGD 2202 +BADVER 1F53 DC1 0DE7 DRAWIB 158E FSUB DA60 GETGME 2252 +BLKLEN 00EA DC2 0DEE DRAWIC 15A1 GADD 1125 GETI 1A36 +BLOCK 00D3 DCNT 00F1 DRAWID 15B1 GAME 0037 GETIMG 2241 +BLOCKX 1A0F DCOMND 0302 DSKINV E453 GBAND 1203 GETIP 0CFA +BOOT 0009 DDISK 2109 DSKLP1 226E GBEGIN 2300 GETLEN 0CB2 +BRKKEY 0011 DEBUG 0000 DSKP0 22C4 GBIOR 120F GETLNG 0EEE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- SYMBOL TABLE PAGE 125 +---- SYMBOL TABLE ---- + +GETSHT 0EEA GRAND 143F HOLD 1C8A ITERS 00BD MUH 00AE +GETST 21F0 GRD 21BA I 007A ITEXI 186D MUL 00AD +GETVAR 0F02 GRDL 000E IADR1 00AF ITICN 00BE MULP 19D1 +GETVR1 0F07 GREST 1FD0 IADR10 00B1 ITLOOP 17D4 MULP1 1798 +GETVRG 0F1B GRET 10E3 IADR2 00B2 ITLP2 17CA MULXY 178C +GETVRL 0F0B GRFALS 108E IADR20 00B4 ITLP3 180D MUSHFT 00AC +GFSTAK 0F28 GRIP 0B00 IBLKS 0006 ITOBIG 0CED MUSK 19DA +GGET 12C1 GRSTAK 1092 ICALC 1889 ITPNT 00BF MUSK1 17A1 +GGETB 12D5 GRT1 1085 ICAUX1 034A ITRATE 17AC NARGS 006C +GGLOB 000A GRT2 1087 ICAUX2 034B ITSKP2 17F1 NBLOKS 00A2 +GGRTRP 1279 GRTRUE 1083 ICBADR 0344 ITSKP3 181A NEGATE 00E9 +GID 0002 GSAVE 206D ICBLEN 0348 ITSKP4 1838 NEWL0 1C9F +GIGRTP 1284 GSER 000C ICCOM 0342 ITSKP5 185A NEWLIN 1C9B +GINC 10AD GSET 12B4 ICENT 1419 IVERS 0016 NEWXY 1A89 +GINPUT 1D24 GSETI 1688 ICHECK 0004 IVX 1005 NEXI 1888 +GITER 1461 GSHOWI 14BD ICODE 0091 IX1 00B5 NEXTPC 1AD2 +GITER1 147C GSHOWN 14B7 IEND 0002 IX2 00B6 NEXTSC 212B +GJUMP 10DD GSOUND 1E25 IFILE 1EC4 IXSKIP 00C6 NIBBLE 1CD7 +GLEN 0012 GSP 008E IFP D9AA IY1 00B7 NICONS 00A3 +GLESSP 1265 GST0 21F3 IHEAD 0CC4 IY2 00B8 NOGRAM 0CAD +GLG 0EF1 GST1 21FA IICONS 0007 J 007C NOISE 1F6C +GLOAD 14B4 GSTAKH 0600 ILD0 1A6D K 007E NOIT 1D35 +GLOBAL 009C GSTAKL 0500 ILD1 1A75 KEXIT 1D80 NOMASK 14E4 +GMLOOP 1142 GSTART 0006 ILD2 1A85 LBUFF 0580 NOMSK1 1560 +GMNEXT 1159 GSUB 1132 ILEN 0000 LEN 00F4 NONSNS 1857 +GMOD 116D GSW0 16CA IMAGE 00FD LETGO 1C91 NOPS0 0008 +GMODE 0001 GSW1 16D2 INBUFF 00F3 LINE 00F2 NOPS1 0009 +GMUL 113F GSW2 16E1 INCGPC 18C8 LO 0000 NOPS2 0012 +GNOOP 0FFE GSW3 16E5 INCIA1 1920 LOCALS 0A80 NOPSX 0011 +GO 0E5F GSW4 1708 INCIA2 18F7 LRU 0099 NOUGH 0CF7 +GODIV 1199 GSW5 1713 INCVAL 0FFF LRUMAP 0880 NPC0 1AE7 +GOVER 1C81 GSWAPI 16BC INCVPC 1899 MASK 00DB NPC1 1AEF +GPC 0080 GTBT0 1B3A INEX1 192E MDXCUT 00C7 NPC1A 1AF7 +GPC0 0082 GTBT1 1B42 INEX2 1905 MEMMAP 0700 NPC2 1AFB +GPCFLG 0083 GTBT1A 1B4A INTRP 0042 MEMTOP 1CFD NPC3 1B22 +GPCH 0081 GTBT2 1B4E IPURE 0095 MINIT 11F9 NPC4 1B1C +GPCL 0080 GTBT3 1B75 IRDIN 1F02 MINIT0 0DA3 NXC 2133 +GPEX1 18D8 GTBT4 1B6F IRQEN D20E MINIT1 0DB2 NXTENT 187D +GPGET 0CB8 GVALUE 10A5 ISETUP 1A10 MLOOP 0DCF OLDGSP 008F +GPOINT 0084 GVCALC 0F8C ISTART 0094 MOVEB 22B0 OP0 0E64 +GPOP 109F GVERP 1E46 ISU 1A1B MOVED 1D3D OP1 0E73 +GPUR 0008 GVERS 0000 ISUM 1EFE MOVED2 1D40 OP1A 0E7D +GPURE 0093 GWIND 171C ISUM0 1F32 MSKFLG 00E3 OP1B 0E87 +GPUSH 1098 GZEROP 10C5 ISUM2 1F1A MSTART 0400 OP1EX 0E8E +GPUT 13F1 HCHARS 1CBE ISUM3 1F29 MTEMP 00A8 OP2 0EA2 +GPUTB 13FC HEX 1CCE ITAB 00A0 MU0 17A9 OP2A 0EAC +GQUIT 1C7A HI 0001 ITENT 14EB MUEND 19E1 OP2B 0EAF + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +GRIP/6502 INFOCOM COMPANY PRIVATE --- SYMBOL TABLE PAGE 126 +---- SYMBOL TABLE ---- + +OP2C 0EBE PREDS 0FAE S4L1 1FB4 SV0 20A9 VSUM 1E6A +OP2D 0EC1 PRERR2 16C5 S4L2 1FBA SV1 20CB VSUM0 1E9E +OP2EX 0ECB PRINT 1CE5 S4L3 1FC4 SVG 2182 VSUM2 1E86 +OPCODE 006B PSHVAL 0F3E SAVEM 2146 SVGL 0010 VSUM3 1E95 +OPEXT 0DF5 PSHXA 0F42 SAVEML 001E SWAP 009A VSUM4 1EBA +OPT0 101B PTCALC 0C2B SAVEY 1BEE T717 2266 WARM 0C61 +OPT1 102B PURERR 143A SAVMSC 0058 TARGET 009B WCEX 0FA1 +OPT2 103D PUTBYT 0F60 SCEX 12B3 TEXT 03A0 WILP 171E +OPTX 1061 PUTLSB 1404 SCMP 12A9 TICK 1D43 WINDH 00CD +OPX1 0E06 PUTVAL 0F66 SCOM 21AC TICK1 1D4E WINDW 00CE +OPX2 0E10 PUTVLG 0F7F SCOML 000E TOADR 1DEE WINDX1 00C9 +OPX3 0E1A PUTVLL 0F6F SCOMP 129E TOADR2 1E14 WINDX2 00CB +OPX4 0E35 PUTVR1 0F6B SCREEN A100 TOADR3 1E1D WINDY1 00CA +OPXNXT 0E21 PYES 10CE SDLSTL 0230 TOPCUT 00C4 WINDY2 00CC +OVER 0F50 QSIGN 00AA SDMCTL 022F TOPX 0E00 WISK1 172E +PAGE 1B78 QUOT 00A4 SECTOR 00EF TOX 00E4 WISK2 172B +PAGE0 0096 RAMSIZ 02E4 SENSE 1D5D TRUE 00FF WISK3 173E +PAGMAP 0800 RAMTOP 006A SHOWI 14C1 UDIV 11C3 WISK4 1746 +PATB 0D77 RANDOM D20A SI0 1693 UDLOOP 11CC WISK5 174E +PATB1 0D84 RANGE 2261 SI1 1697 UDNEXT 11E4 WISK6 1756 +PATI 0D8E READ 2107 SI3 16B3 UNDER 0F39 WISK7 1764 +PATI1 0D9B READIN 1E6E SIDCUT 00C5 UPTIME 1BA0 WISK8 1768 +PBAD 1262 REMAIN 00A6 SIOINV E465 USEGP 1431 WISK9 1776 +PCALC 1409 RESTM 2164 SKCTL D20F UT0 1BB7 WISKA 177A +PCALC1 140E RESTML 001E SND1 1F5E UT1 1BC2 WRITE 2103 +PCALC2 1430 RET0 0F5E SND2 1F66 UT2 1BCE X1 006D +PGE1 1B7A RET1 10F2 SND3 1F7C UT3 1BD3 X2 0071 +PGE2 1B89 RET2 1105 SND4 1FA6 V2A1 0EDF XCURS 00E7 +PGOOD 125F RFLIP 11A3 SNDERR 1E41 VALUE 0078 XDEX1 00B9 +PLAY 1E3F ROK 226A SOUNDR 0041 VARGET 0EF9 XDEX2 00BA +PMAX 0097 ROWCRS 0054 SOUNDS 0004 VARPUT 0F55 XPOS 00C0 +POKMSK 0010 RSIGN 00AB SRERR 20ED VEXIT 111E XPSAV 00E5 +POPVAL 0F28 RST0 2002 SRINIT 21C8 VHIGHS 09C0 Y1 006F +PORTB D301 RST1 202B STABLE 1F56 VLOWS 0900 Y2 0073 +PR0 1CEF RST2 2048 STAMP 0098 VPC 0086 YCURS 00E8 +PREDB 0FB3 RSTG 2192 STATUS 1CA6 VPC0 0088 YDEX1 00BB +PREDB1 0FD6 RSTGL 000E STICK 1D83 VPCFLG 0089 YDEX2 00BC +PREDB2 0FE1 RTCLOK 0014 STICK0 0278 VPCH 0087 YPOS 00C2 +PREDB3 0FE8 S1L 1F74 STICK1 0279 VPCL 0086 ZEND 00FF +PREDF 0FA2 S3L1 1F8A STIKEX 1D8F VPCSAV 008C ZFR0 DA44 +PREDLB 0FC3 S3L2 1F90 STRIG0 0284 VPEX1 18A9 ZFR1 DA46 +PREDNB 0FA7 S3L3 1F9A STRIG1 0285 VPOINT 008A ZSTART 006B + +***** NO ERRORS DETECTED ***** diff --git a/atari/atarizip-d.asm b/atari/atarizip-d.asm new file mode 100644 index 0000000..0821942 --- /dev/null +++ b/atari/atarizip-d.asm @@ -0,0 +1,6359 @@ + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- EQUATES PAGE 1 + + + + 0000 ; -------------------------- + 0000 ; ZIP/6502 2.0 + 0000 ; Z-CODE INTERPRETER PROGRAM + 0000 ; FOR ATARI 400/800/1200/XL + 0000 ; -------------------------- + + 0000 ; INFOCOM, INC. + 0000 ; 55 WHEELER STREET + 0000 ; CAMBRIDGE, MA 02136 + + 0000 ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + + 0080 ZEROPG EQU $80 ; 1ST FREE Z-PAGE LOCATION + + 0000 DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER + + 0000 ; ----------- + 0000 ; ERROR CODES + 0000 ; ----------- + + 0000 ; 00 -- INSUFFICIENT RAM + 0000 ; 01 -- ILLEGAL X-OP + 0000 ; 02 -- ILLEGAL 0-OP + 0000 ; 03 -- ILLEGAL 1-OP + 0000 ; 04 -- ILLEGAL 2-OP + 0000 ; 05 -- Z-STACK UNDERFLOW + 0000 ; 06 -- Z-STACK OVERFLOW + 0000 ; 07 -- ILLEGAL PROPERTY LENGTH (GETP) + 0000 ; 08 -- DIVISION BY ZERO + 0000 ; 09 -- ILLEGAL ARGUMENT COUNT (EQUAL?) + 0000 ; 10 -- ILLEGAL PROPERTY ID (PUTP) + 0000 ; 11 -- ILLEGAL PROPERTY LENGTH (PUTP) + 0000 ; 12 -- DISK ADDRESS OUT OF RANGE + 0000 ; 13 -- PARSER OVERFLOW + 0000 ; 14 -- DRIVE ACCESS + + INCLUD EQ.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- EQUATES PAGE 2 +--- MEMORY ORGANIZATION --- + + + 00FF TRUE EQU $FF + 0000 FALSE EQU 0 + 0000 LO EQU 0 + 0001 HI EQU 1 + + 0000 ; SEE "HARDEQ.ASM" FOR ATARI MEMORY MAP + + 0000 ; --------------------- + 0000 ; Z-CODE HEADER OFFSETS + 0000 ; --------------------- + + 0000 ZVERS EQU 0 ; VERSION BYTE + 0001 ZMODE EQU 1 ; MODE SELECT BYTE + 0002 ZID EQU 2 ; GAME ID WORD + 0004 ZENDLD EQU 4 ; START OF NON-PRELOADED Z-CODE + 0006 ZGO EQU 6 ; EXECUTION ADDRESS + 0008 ZVOCAB EQU 8 ; START OF VOCABULARY TABLE + 000A ZOBJEC EQU 10 ; START OF OBJECT TABLE + 000C ZGLOBA EQU 12 ; START OF GLOBAL VARIABLE TABLE + 000E ZPURBT EQU 14 ; START OF "PURE" Z-CODE + 0010 ZSCRIP EQU 16 ; FLAG WORD + 0012 ZSERIA EQU 18 ; 3-WORD ASCII SERIAL NUMBER + 0018 ZFWORD EQU 24 ; START OF FWORDS TABLE + 001A ZLENTH EQU 26 ; LENGTH OF Z-PROGRAM IN WORDS + 001C ZCHKSM EQU 28 ; Z-CODE CHECKSUM WORD + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- EQUATES PAGE 3 +--- ZIP Z-PAGE VARIABLES --- + + + 0080 OPCODE EQU ZEROPG ; (BYTE) CURRENT OPCODE + 0081 NARGS EQU OPCODE+1 ; (BYTE) # ARGUMENTS + 0082 ARG1 EQU OPCODE+2 ; (WORD) ARGUMENT #1 + 0084 ARG2 EQU OPCODE+4 ; (WORD) ARGUMENT #2 + 0086 ARG3 EQU OPCODE+6 ; (WORD) ARGUMENT #3 + 0088 ARG4 EQU OPCODE+8 ; (WORD) ARGUMENT #4 + 008A ABYTE EQU OPCODE+10 ; (BYTE) X-OP ARGUMENT BYTE + 008B ADEX EQU OPCODE+11 ; (BYTE) X-OP ARGUMENT INDEX + + 008C VALUE EQU OPCODE+12 ; (WORD) VALUE RETURN REGISTER + 008E I EQU VALUE+2 ; (WORD) GEN-PURPOSE REGISTER #1 + 0090 J EQU VALUE+4 ; (WORD) GEN-PURPOSE REGISTER #2 + 0092 K EQU VALUE+6 ; (WORD) GEN-PURPOSE REGISTER #3 + + 0094 ZSP EQU VALUE+8 ; (BYTE) Z-STACK POINTER + 0095 OLDZSP EQU ZSP+1 ; (BYTE) OLD Z-STACK POINTER + + 0096 ZPC EQU ZSP+2 ; (3 BYTES) ZIP PROGRAM COUNTER + 0096 ZPCL EQU ZPC ; (BYTE) LOW 8 BITS OF [ZPC] + 0097 ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC] + 0098 ZPCH EQU ZPC+2 ; (BYTE) HIGH BIT OF [ZPC] + 0099 ZPCFLG EQU ZPC+3 ; (BYTE) FLAG: "TRUE" IF [ZPCPNT] VALID + 009A ZPCPNT EQU ZPC+4 ; (WORD) ABS POINTER TO CURRENT Z-PAGE + + 009C MPC EQU ZPC+6 ; (3 BYTES) MEMORY PROGRAM COUNTER + 009C MPCL EQU MPC ; (BYTE) LOW 8 BITS OF [MPC] + 009D MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC] + 009E MPCH EQU MPC+2 ; (BYTE) HIGH BIT OF [MPC] + 009F MPCFLG EQU MPC+3 ; (BYTE) FLAG: "TRUE" IF [MPCPNT] VALID + 00A0 MPCPNT EQU MPC+4 ; (WORD) ABS POINTER TO CURRENT M-PAGE + + 00A2 LRU EQU MPC+6 ; (BYTE) EARLIEST TIMESTAMP + 00A3 ZCODE EQU LRU+1 ; (BYTE) 1ST ABSOLUTE PAGE OF PRELOAD + 00A4 ZPURE EQU LRU+2 ; (BYTE) 1ST VIRTUAL PAGE OF "PURE" Z-CODE + 00A5 PAGE0 EQU LRU+3 ; (BYTE) 1ST PAGE OF ACTUAL SWAPPING SPACE + 00A6 PMAX EQU LRU+4 ; (BYTE) MAXIMUM # OF SWAPPING PAGES + 00A7 ZPAGE EQU LRU+5 ; (BYTE) CURRENT SWAPPING PAGE + 00A8 TARGET EQU LRU+6 ; (WORD) TARGET PAGE FOR SWAPPING + 00AA STAMP EQU LRU+8 ; (BYTE) CURRENT TIMESTAMP + 00AB SWAP EQU LRU+9 ; (BYTE) EARLIEST BUFFER + + 00AC GLOBAL EQU LRU+10 ; (WORD) GLOBAL VARIABLE POINTER + 00AE VOCAB EQU GLOBAL+2 ; (WORD) VOCAB TABLE POINTER + 00B0 FWORDS EQU GLOBAL+4 ; (WORD) F-WORDS TABLE POINTER + 00B2 OBJTAB EQU GLOBAL+6 ; (WORD) OBJECT TABLE POINTER + + 0000 ; Z-STRING MANIPULATION VARIABLES + + 00B4 IN EQU GLOBAL+8 ; (6 BYTES) INPUT BUFFER + 00BA OUT EQU IN+6 ; (6 BYTES) OUTPUT BUFFER + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- EQUATES PAGE 4 +--- ZIP Z-PAGE VARIABLES --- + + + 00C0 SOURCE EQU OUT+6 ; (BYTE) SOURCE BUFFER POINTER + 00C1 RESULT EQU SOURCE+1 ; (BYTE) RESULT TABLE POINTER + 00C2 LINLEN EQU SOURCE+2 ; (BYTE) LENGTH OF CURRENT LINE + 00C3 WRDLEN EQU SOURCE+3 ; (BYTE) LENGTH OF CURRENT WORD + 00C4 ENTRY EQU SOURCE+4 ; (WORD) ADDR OF CURRENT RESULT ENTRY + 00C6 NENTS EQU SOURCE+6 ; (WORD) # ENTRIES IN VOCAB TABLE + 00C8 ESIZE EQU SOURCE+8 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES + 00C9 PSET EQU SOURCE+9 ; (BYTE) PERMANENT CHARSET + 00CA TSET EQU SOURCE+10 ; (BYTE) TEMPORARY CHARSET + 00CB ZCHAR EQU SOURCE+11 ; (BYTE) CURRENT Z-CHAR + 00CC OFFSET EQU SOURCE+12 ; (BYTE) F-WORD TABLE OFFSET + 00CD ZFLAG EQU SOURCE+13 ; (BYTE) Z-WORD ACCESS FLAG + 00CE ZWORD EQU SOURCE+14 ; (WORD) CURRENT Z-WORD + 00D0 CONCNT EQU SOURCE+16 ; (BYTE) Z-STRING SOURCE COUNTER + 00D1 CONIN EQU SOURCE+17 ; (BYTE) CONVERSION SOURCE INDEX + 00D2 CONOUT EQU SOURCE+18 ; (BYTE) CONVERSION DEST INDEX + + 00D3 QUOT EQU SOURCE+19 ; (WORD) QUOTIENT FOR DIVISION + 00D5 REMAIN EQU QUOT+2 ; (WORD) REMAINDER FOR DIVISION + 00D7 MTEMP EQU QUOT+4 ; (WORD) MATH TEMPORARY REGISTER + 00D9 QSIGN EQU QUOT+6 ; (BYTE) SIGN OF QUOTIENT + 00DA RSIGN EQU QUOT+7 ; (BYTE) SIGN OF REMAINDER + 00DB DIGITS EQU QUOT+8 ; (BYTE) DIGIT COUNT FOR "PRINTN" + + 00DC TIMEFL EQU QUOT+9 ; (BYTE) "TRUE" IF TIME MODE + 00DD LENGTH EQU TIMEFL+1 ; (BYTE) LENGTH OF LINE IN [LINBUF] + 00DE OLDLEN EQU TIMEFL+2 ; (BYTE) OLD LINE LENGTH + 00DF SCRIPT EQU TIMEFL+3 ; (BYTE) SCRIPT ENABLE FLAG + 00E0 LINCNT EQU TIMEFL+4 ; (BYTE) LINE COUNTER + 00E1 LMAX EQU TIMEFL+5 ; (BYTE) MAX # LINES/SCREEN + + 00E2 IOCHAR EQU TIMEFL+6 ; (BYTE) CHARACTER BUFFER + 00E3 SLINE EQU IOCHAR+1 ; (BYTE) BORDERLINE FOR SPLIT + 00E4 SPSTAT EQU IOCHAR+2 ; (BYTE) SPLIT SCREEN STATUS FLAG + 00E5 LFROM EQU IOCHAR+3 ; (WORD) "FROM" LINE ADDRESS + 00E7 LTO EQU IOCHAR+5 ; (WORD) "TO" LINE ADDRESS + 00E9 PSTAT EQU IOCHAR+7 ; (BYTE) PRINTER STATUS FLAG + 00EA PRLEN EQU IOCHAR+8 ; (BYTE) SCRIPT LINE LENGTH + + 00EB DBLOCK EQU IOCHAR+9 ; (WORD) Z-BLOCK TO READ + 00ED DBUFF EQU DBLOCK+2 ; (WORD) RAM PAGE TO ACCESS (LSB = 0) + 00EF SECTOR EQU DBLOCK+4 ; (WORD) TARGET SECTOR + 00F1 GPOSIT EQU DBLOCK+6 ; (BYTE) DEFAULT SAVE POSITION + 00F2 GDRIVE EQU DBLOCK+7 ; (BYTE) DEFAULT SAVE DRIVE + 00F3 TPOSIT EQU DBLOCK+8 ; (BYTE) TEMP SAVE POSITION + 00F4 TDRIVE EQU DBLOCK+9 ; (BYTE) TEMP SAVE DRIVE + 00F5 DRIVE EQU DBLOCK+10 ; (BYTE) CURRENT DRIVE + + 00F6 BLINK EQU DBLOCK+11 ; (WORD) CURSOR BLINK TIMER + 00F8 CSHAPE EQU BLINK+2 ; (BYTE) CURRENT CURSOR SHAPE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- EQUATES PAGE 5 +--- ZIP Z-PAGE VARIABLES --- + + + END + + INCLUD HARDEQ.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 6 +--- HARDWARE EQUATES: ATARI --- + + + 0000 ; ---------------- + 0000 ; ATARI MEMORY MAP + 0000 ; ---------------- + + 0400 IOBUFF EQU $0400 ; DISK I/O BUFFER + 0480 BUFTOP EQU $0480 ; TOP HALF OF I/O BUFFER + 0500 ZSTAKL EQU $0500 ; Z-STACK LSBS + 0600 ZSTAKH EQU $0600 ; Z-STACK MSBS + 0700 PTABL EQU $0700 ; PAGING TABLE LSBS + 0800 PTABH EQU $0800 ; PAGING TABLE MSBS + 0900 LRUMAP EQU $0900 ; TIMESTAMP MAP + 0A00 LOCALS EQU $0A00 ; LOCAL VARIABLE STORAGE (30 BYTES) + 0A20 BUFSAV EQU $0A20 ; AUXILIARY INPUT BUFFER (80 BYTES) + 0A80 LBUFF EQU $0A80 ; MAIN INPUT BUFFER (80 BYTES) + + 0800 PLMRAM EQU $0800 ; START OF PLAYER/MISSILE RAM + 0B00 MISSL EQU $0B00 ; START OF MISSILE RAM (CURSOR) + + 0C00 ZIP EQU $0C00 ; START OF ZIP CODE + 2600 ZBEGIN EQU $2600 ; START OF Z-CODE (ASSUME 6.5K ZIP) + + BC20 OLDLST EQU $BC20 ; CIO DEFAULT DL ADDR + BC40 SCREEN EQU $BC40 ; START OF SCREEN RAM + + 0000 ; --------- + 0000 ; CONSTANTS + 0000 ; --------- + + 0027 XSIZE EQU 39 ; WIDTH OF SCREEN IN CHARACTERS (-1) + 0017 YSIZE EQU 23 ; HEIGHT OF SCREEN IN LINES (-1) + + 009B EOL EQU $9B ; EOL CHAR + 0020 SPACE EQU $20 ; SPACE CHAR + 007E BACKSP EQU 126 ; BACKSPACE + + 0000 ; --------- + 0000 ; ZER0-PAGE + 0000 ; --------- + + 0009 BOOT EQU $09 ; BOOT FLAG + 000A DOSVEC EQU $0A ; DOS START VECTOR + 0010 POKMSK EQU $10 ; FOR BREAK KEY DISABLE + 0014 RTCLOK EQU $14 ; JIFFY CLOCK + 0052 LMARGN EQU $52 ; LEFT MARGIN + 0054 ROWCRS EQU $54 ; OS CURSOR ROW + 0055 COLCRS EQU $55 ; OS CURSOR COLUMN + + 0000 ; --------- + 0000 ; PAGES 2-3 + 0000 ; --------- + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 7 +--- HARDWARE EQUATES: ATARI --- + + + 022F SDMCTL EQU $022F ; DMA CONTROL + 0230 SDLSTL EQU $0230 ; DISPLAY LIST ADDRESS + 0244 COLDST EQU $0244 ; COLDSTART FLAG + 026F GPRIOR EQU $026F ; GRAPHICS PRIORITY + 02B2 LOGMAP EQU $02B2 ; LOGICAL LINE MAP (3 BYTES) + 02B6 INVFLG EQU $02B6 ; INVERSE TEXT FLAG + 02C5 COLOR1 EQU $02C5 ; TEXT COLOR + 02C8 COLOR4 EQU $02C8 ; BORDER COLOR + 02F0 CRSINH EQU $02F0 ; OS CURSOR INHIBIT + 02FC CH EQU $02FC ; KEYBOARD READ FLAG + 0301 DUNIT EQU $0301 ; DRIVE # + 0302 DCOMND EQU $0302 ; DISK COMMAND + 0303 DSTATS EQU $0303 ; DISK I/O STATUS + 0304 DBUFLO EQU $0304 ; DISK BUFFER ADDR (LSB) + 0305 DBUFHI EQU $0305 ; DISK BUFFER ADDR (MSB) + 030A DAUX1 EQU $030A ; SECTOR ADDR (LSB) + 030B DAUX2 EQU $030B ; SECTOR ADDR (MSB) + 0342 ICCOM EQU $0342 ; IOCB #0 COMMAND + 0344 ICBADR EQU $0344 ; IOCB #0 BUFFER ADDR + 0348 ICBLEN EQU $0348 ; IOCB #0 LENGTH + 034A ICAUX1 EQU $034A ; IOCB #0 AUX BYTE #1 + 034B ICAUX2 EQU $034B ; IOCB #0 AUX BYTE #2 + + 0000 ; ------------------ + 0000 ; GTIA, POKEY, ANTIC + 0000 ; ------------------ + + D000 HPOSP0 EQU $D000 ; PLAYER #0 H-POS + D004 HPOSM0 EQU $D004 ; MISSILE #0 H-POS + D00C SIZEM EQU $D00C ; MISSILE SIZES + D01D GRACTL EQU $D01D ; P/M GRAPHICS CONTROL + D01F CONSOL EQU $D01F ; CONSOLE KEY REGISTER + D200 AUDF1 EQU $D200 ; AUDIO CH1 FREQ + D201 AUDC1 EQU $D201 ; AUDIO CH1 CTRL + D208 AUDCTL EQU $D208 ; AUDIO CONTROL + D20A MRAND EQU $D20A ; RANDOM BYTE + D20E IRQEN EQU $D20E ; IRQ ENABLE + D20F SKCTL EQU $D20F ; SERIAL PORT CONTROL + D301 PORTB EQU $D301 ; PORT B (XL ROM SWITCH) + D400 DMACTL EQU $D400 ; DMA CONTROL + D407 PMBASE EQU $D407 ; PMG RAM BASE ADDR + + 0000 ; ------ + 0000 ; OS ROM + 0000 ; ------ + + E453 DSKINV EQU $E453 ; SIO DISK ACCESS + E456 CIOV EQU $E456 ; CIO VECTOR + + END + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 8 +--- HARDWARE EQUATES: ATARI --- + + INCLUD COLD.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 9 +--- MACHINE COLDSTART: ATARI --- + + + 0C00 ORG ZIP + + 0C00 ; ----------------- + 0C00 ; ATARI BOOT HEADER + 0C00 ; ----------------- + + 0C00 00 DB 0 ; FLAG BYTE (IGNORED) + 0C01 38 DB 56 ; LOAD 7K OF CODE + 0C02 000C DW ZIP ; WHERE TO LOAD THE SECTORS + 0C04 0E0C DW DUMMY ; POINT TO INIT SUBROUTINE + + 0C06 ; -------------- + 0C06 ; BOOT COLDSTART + 0C06 ; -------------- + + 0C06 A94F LDA #LOW COLD ; POINT [DOSVEC] TO + 0C08 850A STA DOSVEC+LO ; THE COLDSTART ROUTINE + 0C0A A90C LDA #HIGH COLD + 0C0C 850B STA DOSVEC+HI + + 0C0E A9FF DUMMY: LDA #$FF ; DISABLE BASIC ROM + 0C10 8D01D3 STA PORTB ; IN XL-SERIES MACHINES + 0C13 18 CLC ; SUCCESS FLAG + 0C14 60 RTS + + 0C15 ; ------------------- + 0C15 ; CUSTOM DISPLAY LIST + 0C15 ; ------------------- + + 0C15 707050 DLIST: DB $70,$70,$50 ; 22 BLANK LINES + 0C18 42 DB $42 ; 1 TEXT LINE W/LMS + 0C19 40BC DW SCREEN ; ADDR OF SCREEN RAM + 0C1B 10 DB $10 ; 2 BLANK LINES + 0C1C 02020202 DB $02,$02,$02,$02,$02,$02,$02 ; 7 TEXT LINES + 0C23 02020202 DB $02,$02,$02,$02,$02,$02,$02,$02 ; 8 TEXT LINES + 0C2B 02020202 DB $02,$02,$02,$02,$02,$02,$02,$02 ; 8 TEXT LINES + 0C33 41 DB $41 ; JVB + 0C34 150C DW DLIST ; ADDR OF D-LIST + + 0C36 54686520 SLD: DB "The story is loading ..." + 0C4E 9B DB EOL + 0019 SLDL EQU $-SLD + + 0C4F ; --------- + 0C4F ; COLDSTART + 0C4F ; --------- + + 0C4F D8 COLD: CLD + 0C50 A2FF LDX #$FF ; RESET THE + 0C52 9A TXS ; HARDWARE STACK + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 10 +--- MACHINE COLDSTART: ATARI --- + + 0C53 8EFC02 STX CH ; AND KEYBOARD REGISTER + 0C56 8E01D3 STX PORTB ; REMOVE BASIC ROM IN XL MACHINES + 0C59 E8 INX ; = 0 + 0C5A 8E4402 STX COLDST ; COLDSTART OKAY + 0C5D 8E08D2 STX AUDCTL ; CLEAR SOUND + 0C60 8652 STX LMARGN ; NO LEFT MARGIN + 0C62 86DF STX SCRIPT ; DISABLE SCRIPTING + 0C64 8ED81F STX SFLAG ; DISABLE PREVIOS SCRIPT (BM 5/14/85) + 0C67 E8 INX ; = 1 + 0C68 8609 STX BOOT ; BOOT SUCCESSFUL + 0C6A 8E6F02 STX GPRIOR ; MAXIMUM PMG PRIORITY + 0C6D 8EF002 STX CRSINH ; INHIBIT OS CURSOR + + 0C70 A903 LDA #3 + 0C72 8D0FD2 STA SKCTL ; RESET SOUND + 0C75 8D1DD0 STA GRACTL ; ENABLE PLAYERS & MISSILES + + 0C78 A970 LDA #$70 + 0C7A 8510 STA POKMSK ; DISABLE + 0C7C 8D0ED2 STA IRQEN ; THE BREAK KEY + + 0C7F A90C LDA #12 ; WHITE + 0C81 8DC502 STA COLOR1 ; TEXT + 0C84 A994 LDA #148 + 0C86 8DC802 STA COLOR4 ; BLUE BORDER + + 0C89 A211 LDX #$11 ; CLEAR ALL PMG REGISTERS + 0C8B A900 LDA #0 + 0C8D 9D00D0 PMG0: STA HPOSP0,X + 0C90 CA DEX + 0C91 10FA BPL PMG0 + + 0C93 AA TAX ; [X] & [A] = 0 + 0C94 9D000B PMG1: STA MISSL,X ; CLEAR CURSOR RAM + 0C97 E8 INX + 0C98 D0FA BNE PMG1 + + 0C9A A901 LDA #1 ; DOUBLE-WIDTH FOR + 0C9C 8D0CD0 STA SIZEM ; MISSILE #0 + 0C9F A908 LDA #HIGH PLMRAM ; POINT TO LOCATION + 0CA1 8D07D4 STA PMBASE ; OF PMG RAM + + 0CA4 A915 LDA #LOW DLIST ; ENABLE + 0CA6 8D3002 STA SDLSTL+LO ; CUSTOM + 0CA9 A90C LDA #HIGH DLIST ; DISPLAY + 0CAB 8D3102 STA SDLSTL+HI ; LIST + + 0CAE ; FALL THROUGH ... + + 0CAE ; --------------- + 0CAE ; WARMSTART ENTRY + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT INIT PAGE 11 +--- MACHINE COLDSTART: ATARI --- + + 0CAE ; --------------- + + 0CAE 20D320 WARM: JSR CLS ; CLEAR SCREEN + + 0CB1 A908 LDA #8 ; POSITION CURSOR + 0CB3 8555 STA COLCRS+LO ; AT (8,0) + 0CB5 A900 LDA #0 + 0CB7 8554 STA ROWCRS + + 0CB9 A236 LDX #LOW SLD + 0CBB A90C LDA #HIGH SLD + 0CBD A019 LDY #SLDL + 0CBF 20A823 JSR SROOM ; "THE STORY IS LOADING ..." + + 0CC2 A93E LDA #%00111110 ; ENABLE 1-LINE PMG, STANDARD FIELD + 0CC4 8D2F02 STA SDMCTL ; RESTORE ANTIC + + 0CC7 ; FALL THROUGH TO ZIP WARMSTART ... + + END + + INCLUD WARM.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 12 +--- WARMSTART ROUTINE --- + + + 0CC7 ; ------------- + 0CC7 ; ZIP WARMSTART + 0CC7 ; ------------- + + 0CC7 A900 WARM1: LDA #0 ; CLEAR ALL Z-PAGE VARIABLES + 0CC9 A280 LDX #ZEROPG + 0CCB 9500 ST0: STA 0,X + 0CCD E8 INX + ; CPX #ZPGTOP ; NOT NEEDED FOR ATARI + 0CCE D0FB BNE ST0 + + 0CD0 ; INIT THE PAGING TABLE + + 0CD0 AA TAX ; = 0 + 0CD1 A9FF LDA #$FF + 0CD3 9D0007 ST1: STA PTABL,X + 0CD6 9D0008 STA PTABH,X + 0CD9 E8 INX + 0CDA D0F7 BNE ST1 + + 0CDC ; CLEAR THE TIMESTAMP MAP + + 0CDC 8A TXA ; = 0 + 0CDD 9D0009 ST2: STA LRUMAP,X + 0CE0 E8 INX + 0CE1 D0FA BNE ST2 + + 0CE3 E694 INC ZSP ; INIT Z-STACK POINTERS + 0CE5 E695 INC OLDZSP ; TO "1" + 0CE7 E6AA INC STAMP ; INIT TIMESTAMP + + 0CE9 ; GRAB THE FIRST BLOCK OF PRELOAD + + 0CE9 A926 LDA #HIGH ZBEGIN ; MSB OF PRELOAD START ADDRESS + 0CEB 85A3 STA ZCODE ; FREEZE IT HERE + 0CED 85EE STA DBUFF+HI ; LSB IS ALWAYS ZERO + 0CEF C6A4 DEC ZPURE ; (ATARI ONLY) FORCE FETCH FROM PRELOAD + 0CF1 203325 JSR GETDSK ; [DBLOCK] SET TO Z-BLOCK 0 + + 0CF4 ; EXTRACT GAME DATA FROM Z-CODE HEADER + + 0CF4 AE0426 LDX ZBEGIN+ZENDLD ; MSB OF ENDLOAD POINTER + 0CF7 E8 INX ; ADD 1 TO GET + 0CF8 86A4 STX ZPURE ; 1ST "PURE" PAGE OF Z-CODE + + 0CFA 8A TXA ; ADD START PAGE OF PRELOAD + 0CFB 18 CLC ; TO CALC ABSOLUTE START ADDRESS + 0CFC 65A3 ADC ZCODE ; OF PAGING SPACE + 0CFE 85A5 STA PAGE0 + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 13 +--- WARMSTART ROUTINE --- + + 0D00 206A1C JSR MEMTOP ; RETURNS TOP RAM PAGE IN [A] + 0D03 38 SEC + 0D04 E5A5 SBC PAGE0 ; SUBTRACT ADDRESS OF PAGING SPACE + 0D06 F002 BEQ NORAM + 0D08 B005 BCS SETNP ; ERROR IF NOT ENOUGH RAM + + 0D0A ; *** ERROR #0 -- INSUFFICIENT RAM *** + + 0D0A A900 NORAM: LDA #0 + 0D0C 4CF91B JMP ZERROR + + 0D0F 85A6 SETNP: STA PMAX ; SET # SWAPPING PAGES + + 0D11 AD0126 LDA ZBEGIN+ZMODE + 0D14 0920 ORA #%00100000 ; ENABLE SPLIT-SCREEN + 0D16 8D0126 STA ZBEGIN+ZMODE + + 0D19 2902 AND #%00000010 ; ISOLATE STATUS-FORMAT BIT + 0D1B 85DC STA TIMEFL ; 0=SCORE, NZ=TIME + + 0D1D AD0C26 LDA ZBEGIN+ZGLOBA ; GET MSB OF GLOBAL TABLE ADDR + 0D20 18 CLC ; CONVERT TO + 0D21 65A3 ADC ZCODE ; ABSOLUTE ADDRESS + 0D23 85AD STA GLOBAL+HI + 0D25 AD0D26 LDA ZBEGIN+ZGLOBA+1 ; LSB NEEDN'T CHANGE + 0D28 85AC STA GLOBAL+LO + + 0D2A AD1826 LDA ZBEGIN+ZFWORD ; DO SAME FOR FWORDS TABLE + 0D2D 18 CLC + 0D2E 65A3 ADC ZCODE + 0D30 85B1 STA FWORDS+HI + 0D32 AD1926 LDA ZBEGIN+ZFWORD+1 ; NO CHANGE FOR LSB + 0D35 85B0 STA FWORDS+LO + + 0D37 AD0826 LDA ZBEGIN+ZVOCAB ; NOW DO VOCABULARY TABLE + 0D3A 18 CLC + 0D3B 65A3 ADC ZCODE + 0D3D 85AF STA VOCAB+HI + 0D3F AD0926 LDA ZBEGIN+ZVOCAB+1 ; LSB SAME + 0D42 85AE STA VOCAB+LO + + 0D44 AD0A26 LDA ZBEGIN+ZOBJEC ; NOT TO MENTION + 0D47 18 CLC ; THE OBJECT TABLE + 0D48 65A3 ADC ZCODE + 0D4A 85B3 STA OBJTAB+HI + 0D4C AD0B26 LDA ZBEGIN+ZOBJEC+1 ; LSB SAME + 0D4F 85B2 STA OBJTAB+LO + + 0D51 ; FETCH THE REST OF THE PRELOAD + + 0D51 A5EB LDPRE: LDA DBLOCK+LO ; CHECK CURRENT BLOCK # + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 14 +--- WARMSTART ROUTINE --- + + 0D53 C5A4 CMP ZPURE ; LOADED LAST PRELOAD PAGE YET? + 0D55 B006 BCS WARMEX ; YES, TIME TO PLAY! + 0D57 203325 JSR GETDSK ; ELSE GRAB NEXT Z-BLOCK + 0D5A 4C510D JMP LDPRE + + 0D5D AD0626 WARMEX: LDA ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + 0D60 8597 STA ZPCM ; MSB + 0D62 AD0726 LDA ZBEGIN+ZGO+1 ; AND LSB + 0D65 8596 STA ZPCL ; HIGH BIT ALREADY ZEROED + + 0D67 A915 LDA #21 + 0D69 85E1 STA LMAX ; PREVENT WEIRDNESS + + 0D6B 207F23 JSR SIDE2 ; REQUEST SIDE 2 OF DISK + 0D6E 20D320 JSR CLS ; CLEAR SCREEN + + 0D71 A9FF LDA #$FF + 0D73 85DF STA SCRIPT ; ENABLE SCRIPTING + + 0D75 AD1126 LDA ZBEGIN+ZSCRIP+1 ; SET SCRIPT FLAG + 0D78 0DD81F ORA SFLAG ; TO PREVIOUS SETTING + 0D7B 8D1126 STA ZBEGIN+ZSCRIP+1 ; (BM 5/14/85) + + 0D7E ; ... AND FALL INTO MAIN LOOP + + END + INCLUD MAIN.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 15 +--- MAIN LOOP --- + + + 0D7E A900 MLOOP: LDA #0 + 0D80 8581 STA NARGS ; RESET # ARGUMENTS + 0D82 201918 JSR NEXTPC ; GET NEXT INSTRUCTION INTO [A] + 0D85 8580 STA OPCODE ; SAVE IT HERE + + 0D87 IF DEBUG + 0D87 LDA SECTOR+LO + 0D87 STA MBYTE + 0D87 LDA #0 ; BREAKPOINT #0 + 0D87 JSR DOBUG + 0D87 LDA OPCODE + 0D87 ENDIF + + 0D87 ; DECODE AN OPCODE + + 0D87 AA TAX ; SET FLAGS + 0D88 3003 BMI DC0 ; IF POSITIVE, + 0D8A 4C480E JMP OP2 ; IT'S A 2-OP + + 0D8D C9B0 DC0: CMP #$B0 + 0D8F B003 BCS DC1 + 0D91 4C190E JMP OP1 ; OR MAYBE A 1-OP + + 0D94 C9C0 DC1: CMP #$C0 + 0D96 B003 BCS OPEXT + 0D98 4C0A0E JMP OP0 ; PERHAPS A 0-OP + + 0D9B ; -------------- + 0D9B ; HANDLE AN X-OP + 0D9B ; -------------- + + 0D9B 201918 OPEXT: JSR NEXTPC ; GRAB THE ARGUMENT ID BYTE + 0D9E 858A STA ABYTE ; HOLD IT HERE + + 0DA0 A200 LDX #0 + 0DA2 868B STX ADEX ; INIT ARGUMENT INDEX + 0DA4 F006 BEQ OPX1 ; JUMP TO TOP OF LOOP + + 0DA6 A58A OPX0: LDA ABYTE ; GET ARG BYTE + 0DA8 0A ASL A ; SHIFT NEXT 2 ARG BITS + 0DA9 0A ASL A ; INTO BITS 7 & 6 + 0DAA 858A STA ABYTE ; HOLD FOR LATER + + 0DAC 29C0 OPX1: AND #%11000000 ; MASK OUT GARBAGE BITS + 0DAE D006 BNE OPX2 + 0DB0 20940E JSR GETLNG ; 00 = LONG IMMEDIATE + 0DB3 4CC70D JMP OPXNXT + + 0DB6 C940 OPX2: CMP #%01000000 ; IS IT A SHORT IMMEDIATE? + 0DB8 D006 BNE OPX3 ; NO, KEEP GUESSING + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 16 +--- MAIN LOOP --- + + 0DBA 20900E JSR GETSHT ; 01 = SHORT IMMEDIATE + 0DBD 4CC70D JMP OPXNXT + + 0DC0 C980 OPX3: CMP #%10000000 ; LAST TEST + 0DC2 D017 BNE OPX4 ; 11 = NO MORE ARGUMENTS + 0DC4 20A80E JSR GETVAR ; 10 = VARIABLE + + 0DC7 A68B OPXNXT: LDX ADEX ; RETRIEVE ARGUMENT INDEX + 0DC9 A58C LDA VALUE+LO ; GRAB LSB OF VALUE + 0DCB 9582 STA ARG1+LO,X ; STORE IN ARGUMENT TABLE + 0DCD A58D LDA VALUE+HI ; GRAB MSB OF VALUE + 0DCF 9583 STA ARG1+HI,X ; STORE THAT, TOO + + 0DD1 E681 INC NARGS ; UPDATE ARGUMENT COUNTER + + 0DD3 E8 INX + 0DD4 E8 INX + 0DD5 868B STX ADEX ; UPDATE INDEX + 0DD7 E008 CPX #8 ; DONE 4 ARGUMENTS YET? + 0DD9 90CB BCC OPX0 ; NO, GET SOME MORE + + 0DDB ; ALL X-OP ARGUMENTS READY + + 0DDB A580 OPX4: LDA OPCODE ; IS THIS + 0DDD C9E0 CMP #$E0 ; AN EXTENDED 2-OP? + 0DDF B003 BCS DOXOP ; NO, IT'S A REAL X-OP + 0DE1 4C710E JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + + 0DE4 A252 DOXOP: LDX #LOW OPTX ; GET ADDR OF X-OP TABLE + 0DE6 A010 LDY #HIGH OPTX ; INTO [X/Y] + 0DE8 291F AND #%00011111 ; ISOLATE OP ID BITS + 0DEA C90C CMP #NOPSX ; IS IT A LEGAL X-OP? + 0DEC 9005 BCC DODIS ; YUP; TIME TO DISPATCH IT + + 0DEE ; *** ERROR #1 -- ILLEGAL X-OP *** + + 0DEE A901 LDA #1 + 0DF0 4CF91B JMP ZERROR + + 0DF3 ; --------------- + 0DF3 ; OPCODE DISPATCH + 0DF3 ; --------------- + + 0DF3 ; ENTRY: MASKED OPCODE INDEX IN [A] + 0DF3 ; OP-TABLE ADDR IN X/Y (LSB/MSB) + + 0DF3 868E DODIS: STX I+LO ; SAVE TABLE ADDRESS + 0DF5 848F STY I+HI ; IN A POINTER + + 0DF7 0A ASL A ; WORD-ALIGN THE OP INDEX + 0DF8 A8 TAY + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 17 +--- MAIN LOOP --- + + 0DF9 B18E LDA (I),Y ; GET LSB OF DISPATCH ADDRESS + 0DFB 8D050E STA GO+LO ; INSTALL AS JSR OPERAND + 0DFE C8 INY + 0DFF B18E LDA (I),Y ; SAME WITH MSB + 0E01 8D060E STA GO+HI + + 0E04 20 DB $20 ; 6502 "JSR" OPCODE + 0E05 0000 GO: DW $0000 ; DUMMY OPERAND BYTES + + 0E07 4C7E0D JMP MLOOP ; GO BACK FOR ANOTHER OPCODE + + 0E0A ; ------------- + 0E0A ; HANDLE A 0-OP + 0E0A ; ------------- + + 0E0A A2E4 OP0: LDX #LOW OPT0 ; GET 0-OP TABLE ADDR + 0E0C A00F LDY #HIGH OPT0 ; INTO [X/Y] + 0E0E 290F AND #%00001111 ; ISOLATE 0-OP ID BITS + 0E10 C90E CMP #NOPS0 ; OUT OF RANGE? + 0E12 90DF BCC DODIS ; NO, DISPATCH IT + + 0E14 ; *** ERROR #2 -- ILLEGAL 0-OP *** + + 0E14 A902 LDA #2 + 0E16 4CF91B JMP ZERROR + + 0E19 ; ------------- + 0E19 ; HANDLE A 1-OP + 0E19 ; ------------- + + 0E19 2930 OP1: AND #%00110000 ; ISOLATE ARGUMENT BITS + 0E1B D006 BNE OP1A + 0E1D 20940E JSR GETLNG ; 00 = LONG IMMEDIATE + 0E20 4C340E JMP OP1EX + + 0E23 C910 OP1A: CMP #%00010000 ; TEST AGAIN + 0E25 D006 BNE OP1B + 0E27 20900E JSR GETSHT ; 01 = SHORT IMMEDIATE + 0E2A 4C340E JMP OP1EX + + 0E2D C920 OP1B: CMP #%00100000 ; ONE MORE TEST + 0E2F D012 BNE BADOP1 ; UNDEFINED STATE! + 0E31 20A80E JSR GETVAR ; 10 = VARIABLE + + 0E34 20850E OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] + 0E37 A200 LDX #LOW OPT1 ; GET ADDR OF 1-OP TABLE + 0E39 A010 LDY #HIGH OPT1 ; INTO [X/Y] + 0E3B A580 LDA OPCODE ; RESTORE OPCODE + 0E3D 290F AND #%00001111 ; ISOLATE OP ID BITS + 0E3F C910 CMP #NOPS1 ; IF WITHIN RANGE, + 0E41 90B0 BCC DODIS ; EXECUTE THE 1-OP + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 18 +--- MAIN LOOP --- + + + 0E43 ; *** ERROR #3 -- ILLEGAL 1-OP *** + + 0E43 A903 BADOP1: LDA #3 + 0E45 4CF91B JMP ZERROR + + 0E48 ; ------------- + 0E48 ; HANDLE A 2-OP + 0E48 ; ------------- + + 0E48 2940 OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT + 0E4A D006 BNE OP2A + 0E4C 20900E JSR GETSHT ; 0 = SHORT IMMEDIATE + 0E4F 4C550E JMP OP2B + 0E52 20A80E OP2A: JSR GETVAR ; 1 = VARIABLE + 0E55 20850E OP2B: JSR V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] + + 0E58 A580 LDA OPCODE ; RESTORE OPCODE BYTE + 0E5A 2920 AND #%00100000 ; ISOLATE 2ND ARG BIT + 0E5C D006 BNE OP2C + 0E5E 20900E JSR GETSHT ; 0 = SHORT IMMEDIATE + 0E61 4C670E JMP OP2D + 0E64 20A80E OP2C: JSR GETVAR ; 1 = VARIABLE + 0E67 A58C OP2D: LDA VALUE+LO ; MOVE 2ND [VALUE] + 0E69 8584 STA ARG2+LO ; INTO [ARG2] + 0E6B A58D LDA VALUE+HI + 0E6D 8585 STA ARG2+HI + 0E6F E681 INC NARGS ; UPDATE ARGUMENT COUNT + + 0E71 ; EXECUTE A 2-OP OR EXTENDED 2-OP + + 0E71 A220 OP2EX: LDX #LOW OPT2 ; LSB OF DISPATCH TABLE + 0E73 A010 LDY #HIGH OPT2 ; MSB + 0E75 A580 LDA OPCODE ; RESTORE OPCODE BYTE + 0E77 291F AND #%00011111 ; ISOLATE OP ID BITS + 0E79 C919 CMP #NOPS2 + 0E7B B003 BCS BADOP2 ; ERROR IF OUT OF RANGE + 0E7D 4CF30D JMP DODIS ; ELSE DISPATCH + + 0E80 ; *** ERROR #4 -- ILLEGAL 2-OP **** + + 0E80 A904 BADOP2: LDA #4 + 0E82 4CF91B JMP ZERROR + + 0E85 ; -------------------------------------- + 0E85 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] + 0E85 ; -------------------------------------- + + 0E85 A58C V2A1: LDA VALUE+LO + 0E87 8582 STA ARG1+LO + 0E89 A58D LDA VALUE+HI + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 19 +--- MAIN LOOP --- + + 0E8B 8583 STA ARG1+HI + 0E8D E681 INC NARGS + 0E8F 60 RTS + + END + INCLUD SUBS.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 20 +--- OPCODE SUPPORT SUBROUTINES --- + + + 0E90 ; ----------------------- + 0E90 ; FETCH A SHORT IMMEDIATE + 0E90 ; ----------------------- + + 0E90 A900 GETSHT: LDA #0 ; MSB IS ZERO + 0E92 F003 BEQ GETV ; FETCH LSB FROM Z-CODE + + 0E94 ; ---------------------- + 0E94 ; FETCH A LONG IMMEDIATE + 0E94 ; ---------------------- + + 0E94 201918 GETLNG: JSR NEXTPC ; GRAB MSB + + 0E97 858D GETV: STA VALUE+HI + 0E99 201918 JSR NEXTPC ; GRAB LSB + 0E9C 858C STA VALUE+LO + 0E9E 60 RTS + + 0E9F ; ---------------- + 0E9F ; FETCH A VARIABLE + 0E9F ; ---------------- + + 0E9F ; FROM INSIDE AN OPCODE (VARIABLE ID IN [A]) + + 0E9F AA VARGET: TAX ; IF NON-ZERO, + 0EA0 D00B BNE GETVR1 ; ACCESS A VARIABLE + + 0EA2 20CE0E JSR POPVAL ; ELSE PULL VAR OFF Z-STACK + 0EA5 4CE40E JMP PSHVAL ; WITHOUT ALTERING STACK + + 0EA8 ; FROM THE MAIN LOOP (VARIABLE ID IN Z-CODE) + + 0EA8 201918 GETVAR: JSR NEXTPC ; GRAB VAR-TYPE BYTE + 0EAB F021 BEQ POPVAL ; VALUE IS ON Z-STACK + + 0EAD ; IS VARIABLE LOCAL OR GLOBAL? + + 0EAD C910 GETVR1: CMP #$10 ; IF >= 16, + 0EAF B010 BCS GETVRG ; IT'S GLOBAL + + 0EB1 ; HANDLE A LOCAL VARIABLE + + 0EB1 38 GETVRL: SEC + 0EB2 E901 SBC #1 ; FORM A ZERO-ALIGNED + 0EB4 0A ASL A ; WORD INDEX + 0EB5 AA TAX ; INTO THE [LOCALS] TABLE + + 0EB6 BD000A LDA LOCALS+LO,X ; GRAB LSB + 0EB9 858C STA VALUE+LO + 0EBB BD010A LDA LOCALS+HI,X ; AND MSB + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 21 +--- OPCODE SUPPORT SUBROUTINES --- + + 0EBE 858D STA VALUE+HI + 0EC0 60 RTS + + 0EC1 ; HANDLE A GLOBAL VARIABLE + + 0EC1 20320F GETVRG: JSR GVCALC ; GET ADDRESS OF GLOBAL INTO [I] + 0EC4 B18E LDA (I),Y ; MSB OF GLOBAL ([Y] = 0) + 0EC6 858D STA VALUE+HI + 0EC8 C8 INY ; = 1 + 0EC9 B18E LDA (I),Y ; LSB OF GLOBAL + 0ECB 858C STA VALUE+LO ; SAVE IT + 0ECD 60 RTS ; AND WE'RE DONE + + 0ECE ; ---------------------------------- + 0ECE ; POP Z-STACK INTO [VALUE] AND [X/A] + 0ECE ; ---------------------------------- + + 0ECE C694 POPVAL: DEC ZSP + 0ED0 F00D BEQ UNDER ; UNDERFLOW IF ZERO! + + 0ED2 A494 LDY ZSP ; READ STACK POINTER + 0ED4 BE0005 LDX ZSTAKL,Y ; GRAB LSB OF STACK VALUE + 0ED7 868C STX VALUE+LO ; GIVE TO [VALUE] + 0ED9 B90006 LDA ZSTAKH,Y ; ALSO GRAB MSB + 0EDC 858D STA VALUE+HI ; A SIMILAR FATE + 0EDE 60 RTS + + 0EDF ; *** ERROR #5 -- Z-STACK UNDERFLOW *** + + 0EDF A905 UNDER: LDA #5 + 0EE1 4CF91B JMP ZERROR + + 0EE4 ; ----------------------- + 0EE4 ; PUSH [VALUE] TO Z-STACK + 0EE4 ; ----------------------- + + 0EE4 A68C PSHVAL: LDX VALUE+LO + 0EE6 A58D LDA VALUE+HI + + 0EE8 ; --------------------- + 0EE8 ; PUSH [X/A] TO Z-STACK + 0EE8 ; --------------------- + + 0EE8 A494 PUSHXA: LDY ZSP ; READ STACK POINTER + 0EEA 990006 STA ZSTAKH,Y ; PUSH MSB IN [A] + 0EED 8A TXA + 0EEE 990005 STA ZSTAKL,Y ; AND LSB IN [X] + + 0EF1 E694 INC ZSP ; UPDATE Z-STACK POINTER + 0EF3 F001 BEQ OVER ; OVERFLOW IF ZEROED! + 0EF5 60 RTS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 22 +--- OPCODE SUPPORT SUBROUTINES --- + + + 0EF6 ; *** ERROR #6 -- Z-STACK OVERFLOW *** + + 0EF6 A906 OVER: LDA #6 + 0EF8 4CF91B JMP ZERROR + + 0EFB ; -------------- + 0EFB ; RETURN A VALUE + 0EFB ; -------------- + + 0EFB ; FROM WITHIN AN OPCODE (VARIABLE ID IN [A]) + + 0EFB AA VARPUT: TAX ; IF ZERO, + 0EFC D013 BNE PUTVR1 + + 0EFE C694 DEC ZSP ; FLUSH TOP WORD OFF STACK + 0F00 D0E2 BNE PSHVAL ; AND REPLACE WITH [VALUE] + 0F02 F0DB BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + + 0F04 ; RETURN A ZERO + + 0F04 A900 RET0: LDA #0 + + 0F06 ; RETURN BYTE IN [A] + + 0F06 858C PUTBYT: STA VALUE+LO + 0F08 A900 LDA #0 + 0F0A 858D STA VALUE+HI ; CLEAR MSB + + 0F0C ; RETURN [VALUE] + + 0F0C 201918 PUTVAL: JSR NEXTPC ; GET VARIABLE ID BYTE + 0F0F F0D3 BEQ PSHVAL ; [VALUE] GOES TO Z-STACK + + 0F11 ; LOCAL OR GLOBAL VARIABLE? + + 0F11 C910 PUTVR1: CMP #$10 ; IF >= 16, + 0F13 B010 BCS PUTVLG ; IT'S GLOBAL + + 0F15 ; PUT A LOCAL VARIABLE + + 0F15 38 PUTVLL: SEC + 0F16 E901 SBC #1 ; FORM A ZERO-ALIGNED + 0F18 0A ASL A ; WORD INDEX + 0F19 AA TAX ; INTO THE [LOCALS] TABLE + + 0F1A A58C LDA VALUE+LO ; GRAB LSB + 0F1C 9D000A STA LOCALS+LO,X ; SAVE IN LOCAL TABLE + 0F1F A58D LDA VALUE+HI ; DO SAME TO + 0F21 9D010A STA LOCALS+HI,X ; MSB + 0F24 60 RTS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 23 +--- OPCODE SUPPORT SUBROUTINES --- + + + 0F25 ; RETURN A GLOBAL VARIABLE + + 0F25 20320F PUTVLG: JSR GVCALC + 0F28 A58D LDA VALUE+HI ; GET MSB + 0F2A 918E STA (I),Y ; STORE AS 1ST BYTE ([Y] = 0) + 0F2C C8 INY ; = 1 + 0F2D A58C LDA VALUE+LO ; NOW GET LSB + 0F2F 918E STA (I),Y ; STORE AS 2ND BYTE + 0F31 60 RTS + + 0F32 ; ----------------------- + 0F32 ; CALC GLOBAL WORD OFFSET + 0F32 ; ----------------------- + + 0F32 ; ENTRY: VAR-ID BYTE (16-255) IN [A] + 0F32 ; EXIT: ABSOLUTE ADDRESS OF GLOBAL VAR IN [I] + 0F32 ; [Y] = 0 FOR INDEXING + + 0F32 38 GVCALC: SEC + 0F33 E910 SBC #$10 ; FORM A ZERO-ALIGNED INDEX + 0F35 A000 LDY #0 ; MAKE SURE MSB OF OFFSET AND [Y] + 0F37 848F STY I+HI ; ARE CLEARED + + 0F39 0A ASL A ; MULTIPLY OFFSET BY 2 + 0F3A 268F ROL I+HI ; TO WORD-ALIGN IT + + 0F3C 18 CLC ; ADD OFFSET TO ADDR OF GLOBAL TABLE + 0F3D 65AC ADC GLOBAL+LO ; TO FORM THE ABSOLUTE + 0F3F 858E STA I+LO ; ADDRESS OF THE + 0F41 A58F LDA I+HI ; DESIRED GLOBAL VARIABLE + 0F43 65AD ADC GLOBAL+HI ; STORE ADDRESS BACK IN [VAL] + 0F45 858F STA I+HI ; AS A POINTER + + 0F47 60 WCEX: RTS + + 0F48 ; --------------- + 0F48 ; PREDICATE FAILS + 0F48 ; --------------- + + 0F48 201918 PREDF: JSR NEXTPC ; GET 1ST BRANCH BYTE + 0F4B 100C BPL PREDB ; DO BRANCH IF BIT 7 OFF + + 0F4D ; ----------------------- + 0F4D ; IGNORE PREDICATE BRANCH + 0F4D ; ----------------------- + + 0F4D ; ENTRY: 1ST BRANCH BYTE IN [A] + + 0F4D 2940 PREDNB: AND #%01000000 ; TEST BIT 6 + 0F4F D0F6 BNE WCEX ; SHORT BRANCH IF SET + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 24 +--- OPCODE SUPPORT SUBROUTINES --- + + 0F51 4C1918 JMP NEXTPC ; ELSE SKIP OVER 2ND BRANCH BYTE + + 0F54 ; ------------------ + 0F54 ; PREDICATE SUCCEEDS + 0F54 ; ------------------ + + 0F54 201918 PREDS: JSR NEXTPC ; GET 1ST BRANCH BYTE + 0F57 10F4 BPL PREDNB ; DON'T BRANCH IF BIT 7 CLEAR + + 0F59 ; -------------------------- + 0F59 ; PERFORM A PREDICATE BRANCH + 0F59 ; -------------------------- + + 0F59 ; ENTRY: 1ST PRED BYTE IN [A] + + 0F59 AA PREDB: TAX ; SAVE HERE + 0F5A 2940 AND #%01000000 ; LONG OR SHORT BRANCH? + 0F5C F00B BEQ PREDLB ; LONG IF BIT 6 IS CLEAR + + 0F5E ; HANDLE A SHORT BRANCH + + 0F5E 8A TXA ; RESTORE PRED BYTE + 0F5F 293F AND #%00111111 ; FORM SHORT OFFSET + 0F61 858C STA VALUE+LO ; USE AS LSB OF BRANCH OFFSET + 0F63 A900 LDA #0 + 0F65 858D STA VALUE+HI ; MSB OF OFFSET IS ZERO + 0F67 F013 BEQ PREDB1 ; DO THE BRANCH + + 0F69 ; HANDLE A LONG BRANCH + + 0F69 8A PREDLB: TXA ; RESTORE 1ST PRED BYTE + 0F6A 293F AND #%00111111 ; FORM MSB OF OFFSET + + 0F6C AA TAX ; SAVE HERE FOR REFERENCE + + 0F6D 2920 AND #%00100000 ; CHECK SIGN OF 14-BIT VALUE + 0F6F F004 BEQ DOB2 ; POSITIVE IF ZERO, SO USE [X] + + 0F71 8A TXA ; ELSE RESTORE BYTE + 0F72 09E0 ORA #%11100000 ; EXTEND THE SIGN BIT + 0F74 AA TAX ; BACK HERE FOR STORAGE + + 0F75 868D DOB2: STX VALUE+HI + 0F77 201918 JSR NEXTPC ; FETCH LSB OF 14-BIT OFFSET + 0F7A 858C STA VALUE+LO + + 0F7C ; BRANCH TO Z-ADDRESS IN [VALUE] + + 0F7C A58D PREDB1: LDA VALUE+HI ; CHECK MSB OF OFFSET + 0F7E D00E BNE PREDB3 ; DO BRANCH IF NZ + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 25 +--- OPCODE SUPPORT SUBROUTINES --- + + 0F80 A58C LDA VALUE+LO ; IF LSB IS NON-ZERO, + 0F82 D003 BNE PREDB2 ; MAKE SURE IT ISN'T 1 + 0F84 4C7510 JMP ZRFALS ; ELSE DO AN "RFALSE" + + 0F87 C901 PREDB2: CMP #1 ; IF OFFSET = 1 + 0F89 D003 BNE PREDB3 + 0F8B 4C6A10 JMP ZRTRUE ; DO AN "RTRUE" + + 0F8E ; ENTRY POINT FOR "JUMP" + + 0F8E 20C80F PREDB3: JSR DECVAL ; SUBTRACT 2 FROM THE OFFSET + 0F91 20C80F JSR DECVAL ; IN [VALUE] + + 0F94 A900 LDA #0 ; CLEAR THE MSB + 0F96 858F STA I+HI ; OF [I] + + 0F98 A58D LDA VALUE+HI ; MAKE MSB OF OFFSET + 0F9A 858E STA I+LO ; THE LSB OF [I] + 0F9C 0A ASL A ; EXTEND THE SIGN OF OFFSET + 0F9D 268F ROL I+HI ; INTO MSB OF [I] + + 0F9F A58C LDA VALUE+LO ; GET LSB OF OFFSET + 0FA1 18 CLC + 0FA2 6596 ADC ZPCL ; ADD LOW 8 BITS OF ZPC + 0FA4 9006 BCC PREDB5 ; IF OVERFLOWED, + + 0FA6 E68E INC I+LO ; UPDATE UPPER 9 BITS + 0FA8 D002 BNE PREDB5 + 0FAA E68F INC I+HI + + 0FAC 8596 PREDB5: STA ZPCL ; UPDATE ZPC + + 0FAE A58E LDA I+LO ; IF UPPER 9 BITS ARE ZERO, + 0FB0 058F ORA I+HI ; NO NEED TO CHANGE PAGES + 0FB2 F013 BEQ ZNOOP + + 0FB4 A58E LDA I+LO ; ELSE CALC NEW UPPER BITS + 0FB6 18 CLC + 0FB7 6597 ADC ZPCM + 0FB9 8597 STA ZPCM + + 0FBB A58F LDA I+HI + 0FBD 6598 ADC ZPCH + 0FBF 2901 AND #%00000001 ; USE ONLY BIT 0 + 0FC1 8598 STA ZPCH + + 0FC3 A900 LDA #0 + 0FC5 8599 STA ZPCFLG ; [ZPC] NO LONGER VALID + + 0FC7 ; FALL THROUGH ... + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 26 +--- OPCODE SUPPORT SUBROUTINES --- + + 0FC7 ; ---- + 0FC7 ; NOOP + 0FC7 ; ---- + + 0FC7 60 ZNOOP: RTS + + 0FC8 ; ----------------- + 0FC8 ; DECREMENT [VALUE] + 0FC8 ; ----------------- + + 0FC8 A58C DECVAL: LDA VALUE+LO + 0FCA 38 SEC + 0FCB E901 SBC #1 + 0FCD 858C STA VALUE+LO + 0FCF B002 BCS DVX + 0FD1 C68D DEC VALUE+HI + 0FD3 60 DVX: RTS + + 0FD4 ; ----------------- + 0FD4 ; INCREMENT [VALUE] + 0FD4 ; ----------------- + + 0FD4 E68C INCVAL: INC VALUE+LO + 0FD6 D002 BNE IVX + 0FD8 E68D INC VALUE+HI + 0FDA 60 IVX: RTS + + 0FDB ; ---------------------- + 0FDB ; MOVE [ARG1] TO [VALUE] + 0FDB ; ---------------------- + + 0FDB A582 A12VAL: LDA ARG1+LO + 0FDD 858C STA VALUE+LO + 0FDF A583 LDA ARG1+HI + 0FE1 858D STA VALUE+HI + 0FE3 60 RTS + + END + INCLUD DISPATCH.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 27 +--- OPCODE DISPATCH TABLES --- + + + 0FE4 ; 0-OPS + + 0FE4 6A10 OPT0: DW ZRTRUE ; 0 + 0FE6 7510 DW ZRFALS ; 1 + 0FE8 7910 DW ZPRI ; 2 + 0FEA 9610 DW ZPRR ; 3 + 0FEC C70F DW ZNOOP ; 4 + 0FEE DF23 DW ZSAVE ; 5 + 0FF0 7F24 DW ZREST ; 6 + 0FF2 3E1C DW ZSTART ; 7 + 0FF4 9F10 DW ZRSTAK ; 8 + 0FF6 CE0E DW POPVAL ; 9 + 0FF8 1F1C DW ZQUIT ; 10 + 0FFA C71C DW ZCRLF ; 11 + 0FFC 201D DW ZUSL ; 12 + 0FFE A510 DW ZVER ; 13 + + 000E NOPS0 EQU 14 ; NUMBER OF 0-OPS + + 1000 ; 1-OPS + + 1000 2711 OPT1: DW ZZERO ; 0 + 1002 3011 DW ZNEXT ; 1 + 1004 3911 DW ZFIRST ; 2 + 1006 4C11 DW ZLOC ; 3 + 1008 5811 DW ZPTSIZ ; 4 + 100A 7511 DW ZINC ; 5 + 100C 8011 DW ZDEC ; 6 + 100E 8D11 DW ZPRB ; 7 + 1010 430E DW BADOP1 ; 8 (UNDEFINED) + 1012 9B11 DW ZREMOV ; 9 + 1014 DD11 DW ZPRD ; 10 + 1016 FA11 DW ZRET ; 11 + 1018 3712 DW ZJUMP ; 12 + 101A 3D12 DW ZPRINT ; 13 + 101C 4B12 DW ZVALUE ; 14 + 101E 5312 DW ZBCOM ; 15 + + 0010 NOPS1 EQU 16 ; NUMBER OF 1-OPS + + 1020 ; 2-OPS + + 1020 800E OPT2: DW BADOP2 ; 0 (UNDEFINED) + 1022 0115 DW ZEQUAL ; 1 + 1024 6312 DW ZLESS ; 2 + 1026 7712 DW ZGRTR ; 3 + 1028 6912 DW ZDLESS ; 4 + 102A 8212 DW ZIGRTR ; 5 + 102C B212 DW ZIN ; 6 + 102E C212 DW ZBTST ; 7 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE PAGE 28 +--- OPCODE DISPATCH TABLES --- + + 1030 D512 DW ZBOR ; 8 + 1032 E112 DW ZBAND ; 9 + 1034 ED12 DW ZFSETP ; 10 + 1036 0113 DW ZFSET ; 11 + 1038 1413 DW ZFCLR ; 12 + 103A 2B13 DW ZSET ; 13 + 103C 3813 DW ZMOVE ; 14 + 103E 6213 DW ZGET ; 15 + 1040 7213 DW ZGETB ; 16 + 1042 8F13 DW ZGETP ; 17 + 1044 D713 DW ZGETPT ; 18 + 1046 0414 DW ZNEXTP ; 19 + 1048 2314 DW ZADD ; 20 + 104A 3014 DW ZSUB ; 21 + 104C 3D14 DW ZMUL ; 22 + 104E 6114 DW ZDIV ; 23 + 1050 6B14 DW ZMOD ; 24 + + 0019 NOPS2 EQU 25 ; NUMBER OF 2-OPS + + 1052 ; X-OPS + + 1052 3415 OPTX: DW ZCALL ; 0 + 1054 C715 DW ZPUT ; 1 + 1056 D515 DW ZPUTB ; 2 + 1058 F015 DW ZPUTP ; 3 + 105A 9C16 DW ZREAD ; 4 + 105C 2116 DW ZPRC ; 5 + 105E 2616 DW ZPRN ; 6 + 1060 6B16 DW ZRAND ; 7 + 1062 8D16 DW ZPUSH ; 8 + 1064 9416 DW ZPOP ; 9 + 1066 4920 DW ZSPLIT ; 10 + 1068 8E20 DW ZSCRN ; 11 + + 000C NOPSX EQU 12 ; NUMBER OF X-OPS + + END + + INCLUD OPS0.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 29 +--- 0-OPS --- + + + 106A ; ----- + 106A ; RTRUE + 106A ; ----- + + 106A ; SIMULATE A "RETURN 1" + + 106A A201 ZRTRUE: LDX #1 + + 106C A900 ZRT0: LDA #0 + + 106E 8682 ZRT1: STX ARG1+LO ; GIVE TO + 1070 8583 STA ARG1+HI ; [ARG1] + 1072 4CFA11 JMP ZRET ; AND DO THE RETURN + + 1075 ; ------ + 1075 ; RFALSE + 1075 ; ------ + + 1075 ; SIMULATE A "RETURN 0" + + 1075 A200 ZRFALS: LDX #0 + 1077 F0F3 BEQ ZRT0 + + 1079 ; ------ + 1079 ; PRINTI + 1079 ; ------ + + 1079 ; PRINT Z-STRING FOLLOWING THE OPCODE + + 1079 A598 ZPRI: LDA ZPCH ; MOVE [ZPC] INTO [MPC] + 107B 859E STA MPCH + 107D A597 LDA ZPCM + 107F 859D STA MPCM + 1081 A596 LDA ZPCL + 1083 859C STA MPCL + + 1085 A900 LDA #0 + 1087 859F STA MPCFLG ; [MPC] NO LONGER VALID + + 1089 204219 JSR PZSTR ; PRINT THE Z-STRING AT [MPC] + + 108C A205 LDX #5 ; COPY STATE OF [MPC] + 108E B59C PRIL: LDA MPC,X ; INTO [ZPC] + 1090 9596 STA ZPC,X + 1092 CA DEX + 1093 10F9 BPL PRIL + 1095 60 RTS + + 1096 ; ------ + 1096 ; PRINTR + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 30 +--- 0-OPS --- + + 1096 ; ------ + + 1096 ; DO A "PRINTI," FOLLOWED BY "CRLF" AND "RTRUE" + + 1096 207910 ZPRR: JSR ZPRI + 1099 20C71C JSR ZCRLF + 109C 4C6A10 JMP ZRTRUE + + 109F ; ------ + 109F ; RSTACK + 109F ; ------ + + 109F ; "RETURN" WITH VALUE ON STACK + + 109F 20CE0E ZRSTAK: JSR POPVAL ; GET VALUE INTO [X/A] + 10A2 4C6E10 JMP ZRT1 ; AND GIVE IT TO "RETURN" + + 10A5 ; ------ + 10A5 ; VERIFY + 10A5 ; ------ + + 10A5 ; VERIFY GAME CODE ON DISK + + 10A5 205B1C ZVER: JSR VERNUM ; DISPLAY VERSION NUMBER, GET SIDE 1 + + 10A8 A203 LDX #3 + 10AA A900 LDA #0 + 10AC 9590 ZVR: STA J+LO,X ; CLEAR [J], [K] + 10AE 959C STA MPC,X ; [MPC] AND [MPCFLG] + 10B0 CA DEX + 10B1 10F9 BPL ZVR + + 10B3 A940 LDA #64 ; POINT [MPC] TO Z-ADDRESS $00040 + 10B5 859C STA MPCL ; 1ST 64 BYTES AREN'T CHECKED + + 10B7 A993 LDA #K+HI ; PATCH THE "GETBYT" ROUTINE + 10B9 8D5A18 STA PATCH ; TO USE [K+HI]=0 INSTEAD OF [ZPURE] + + 10BC AD0426 LDA ZBEGIN+ZENDLD ; GET LAST BYTE OF ENDLOAD + 10BF 858F STA I+HI ; FIRST MSB + 10C1 AD0526 LDA ZBEGIN+ZENDLD+1 + 10C4 858E STA I+LO ; THEN LSB + + 10C6 ; CHECKSUM THE PRELOAD (SIDE 1) + + 10C6 204F18 VSUM: JSR GETBYT ; GET A Z-BYTE INTO [A] + 10C9 18 CLC + 10CA 6590 ADC J+LO ; ADD IT TO SUM + 10CC 8590 STA J+LO ; IN [J] + 10CE 9002 BCC VSUM0 + 10D0 E691 INC J+HI + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 31 +--- 0-OPS --- + + + 10D2 A59C VSUM0: LDA MPCL ; END OF Z-CODE YET? + 10D4 C58E CMP I+LO ; CHECK LSB + 10D6 D0EE BNE VSUM + + 10D8 A59D LDA MPCM ; AND MIDDLE BYTE + 10DA C58F CMP I+HI ; (HIGH BIT NEEDN'T BE CHECKED) + 10DC D0E8 BNE VSUM + + 10DE ; CHECKSUM "PURE" CODE (SIDE 2) + + 10DE 207F23 JSR SIDE2 ; PROMPT FOR SIDE 2 + + 10E1 AD1A26 LDA ZBEGIN+ZLENTH ; GET MSB + 10E4 858F STA I+HI ; AND + 10E6 AD1B26 LDA ZBEGIN+ZLENTH+1 ; LSB OF Z-CODE LENGTH IN BYTES + 10E9 0A ASL A ; MULTIPLY BY + 10EA 858E STA I+LO ; TWO + 10EC 268F ROL I+HI ; TO GET # BYTES + 10EE 2692 ROL K+LO ; IN GAME + + 10F0 204F18 VSUM2: JSR GETBYT ; GET A Z-BYTE INTO [A] + 10F3 18 CLC + 10F4 6590 ADC J+LO ; ADD IT TO SUM + 10F6 8590 STA J+LO ; IN [J] + 10F8 9002 BCC VSUM3 + 10FA E691 INC J+HI + + 10FC A59C VSUM3: LDA MPCL ; END OF Z-CODE YET? + 10FE C58E CMP I+LO ; CHECK LSB + 1100 D0EE BNE VSUM2 + + 1102 A59D LDA MPCM ; MIDDLE BYTE + 1104 C58F CMP I+HI + 1106 D0E8 BNE VSUM2 + + 1108 A59E LDA MPCH ; AND HIGH BIT + 110A C592 CMP K+LO + 110C D0E2 BNE VSUM2 + + 110E A9A4 LDA #ZPURE ; UNPATCH "GETBYT" + 1110 8D5A18 STA PATCH + + 1113 AD1D26 LDA ZBEGIN+ZCHKSM+1 ; GET LSB OF CHECKSUM + 1116 C590 CMP J+LO ; DOES IT MATCH? + 1118 D00A BNE BADVER ; NO, PREDICATE FAILS + + 111A AD1C26 LDA ZBEGIN+ZCHKSM ; ELSE CHECK MSB + 111D C591 CMP J+HI ; LOOK GOOD? + 111F D003 BNE BADVER ; IF MATCHED, + 1121 4C540F JMP PREDS ; GAME IS OKAY + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 32 +--- 0-OPS --- + + + 1124 4C480F BADVER: JMP PREDF + + END + INCLUD OPS1.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 33 +--- 1-OPS --- + + + 1127 ; ----- + 1127 ; ZERO? + 1127 ; ----- + + 1127 ; [ARG1] = 0? + + 1127 A582 ZZERO: LDA ARG1+LO + 1129 0583 ORA ARG1+HI + 112B F01C BEQ PFINE + + 112D 4C480F PYUCK: JMP PREDF + + 1130 ; ----- + 1130 ; NEXT? + 1130 ; ----- + + 1130 ; RETURN "NEXT" POINTER IN OBJECT [ARG1]; + 1130 ; FAIL IF LAST AND RETURN ZERO + + 1130 A582 ZNEXT: LDA ARG1+LO + 1132 204D1B JSR OBJLOC ; GET OBJECT ADDR INTO [I] + 1135 A005 LDY #5 ; POINT TO "NEXT" SLOT + 1137 D007 BNE FIRST1 + + 1139 ; ------ + 1139 ; FIRST? + 1139 ; ------ + + 1139 ; RETURN "FIRST" POINTER IN OBJECT [ARG1]; + 1139 ; FAIL IF LAST AND RETURN ZERO + + 1139 A582 ZFIRST: LDA ARG1+LO + 113B 204D1B JSR OBJLOC ; GET OBJECT ADDR INTO [I] + 113E A006 LDY #6 ; POINT TO "FIRST" SLOT + + 1140 B18E FIRST1: LDA (I),Y ; GET CONTENTS OF SLOT + 1142 20060F JSR PUTBYT ; PASS IT TO VARIABLE + + 1145 A58C LDA VALUE+LO ; EXAMINE THE VALUE JUST "PUT" + 1147 F0E4 BEQ PYUCK ; FAIL IF IT WAS ZERO + + 1149 4C540F PFINE: JMP PREDS ; ELSE REJOICE + + 114C ; --- + 114C ; LOC + 114C ; --- + + 114C ; RETURN THE OBJECT CONTAINING OBJECT [ARG1]; + 114C ; RETURN ZERO IF NONE + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 34 +--- 1-OPS --- + + 114C A582 ZLOC: LDA ARG1+LO + 114E 204D1B JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + 1151 A004 LDY #4 ; POINT TO "LOC" SLOT + 1153 B18E LDA (I),Y ; GET THE BYTE + 1155 4C060F JMP PUTBYT ; AND SHIP IT OUT + + 1158 ; ------ + 1158 ; PTSIZE + 1158 ; ------ + + 1158 ; RETURN LENGTH OF PROP TABLE [ARG1] IN BYTES + + 1158 A583 ZPTSIZ: LDA ARG1+HI ; MOVE ABS ADDR OF + 115A 18 CLC ; THE PROP TABLE + 115B 65A3 ADC ZCODE ; INTO [I] + 115D 858F STA I+HI + + 115F A582 LDA ARG1+LO ; DECREMENT THE + 1161 38 SEC ; ADDRESS + 1162 E901 SBC #1 ; WHILE MOVING LSB + 1164 858E STA I+LO + 1166 B002 BCS PTZ0 + 1168 C68F DEC I+HI + + 116A A000 PTZ0: LDY #0 ; GET THE LENGTH + 116C 20971B JSR PROPL ; OF PROPERTY AT [I] INTO [A] + + 116F 18 CLC + 1170 6901 ADC #1 ; INCREMENT RESULT + 1172 4C060F JMP PUTBYT ; AND RETURN IT + + 1175 ; --- + 1175 ; INC + 1175 ; --- + + 1175 ; INCREMENT VARIABLE [ARG1] + + 1175 A582 ZINC: LDA ARG1+LO + 1177 209F0E JSR VARGET ; FETCH VARIABLE INTO [VALUE] + 117A 20D40F JSR INCVAL ; INCREMENT IT + 117D 4C8811 JMP ZD0 + + 1180 ; --- + 1180 ; DEC + 1180 ; --- + + 1180 ; DECREMENT VARIABLE [ARG1] + + 1180 A582 ZDEC: LDA ARG1+LO + 1182 209F0E JSR VARGET ; FETCH VAR INTO [VALUE] + 1185 20C80F JSR DECVAL ; DECREMENT IT + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 35 +--- 1-OPS --- + + + 1188 A582 ZD0: LDA ARG1+LO ; PUT RESULT BACK + 118A 4CFB0E JMP VARPUT ; INTO THE SAME VARIABLE + + 118D ; ------ + 118D ; PRINTB + 118D ; ------ + + 118D ; PRINT Z-STRING AT [ARG1] + + 118D A582 ZPRB: LDA ARG1+LO + 118F 858E STA I+LO + 1191 A583 LDA ARG1+HI + 1193 858F STA I+HI + + 1195 201619 JSR SETWRD ; MOVE Z-ADDR TO [MPC] + 1198 4C4219 JMP PZSTR ; AND PRINT + + 119B ; ------ + 119B ; REMOVE + 119B ; ------ + + 119B ; MOVE OBJECT [ARG1] INTO PSEUDO-OBJECT #0 + + 119B A582 ZREMOV: LDA ARG1+LO ; GET SOURCE OBJECT ADDR + 119D 204D1B JSR OBJLOC ; INTO [I] + + 11A0 A58E LDA I+LO ; COPY THE SOURCE ADDR + 11A2 8590 STA J+LO ; INTO [J] + 11A4 A58F LDA I+HI ; FOR LATER REFERENCE + 11A6 8591 STA J+HI + + 11A8 A004 LDY #4 ; POINT TO "LOC" SLOT + 11AA B18E LDA (I),Y ; GET THE DATA + 11AC F02E BEQ REMVEX ; SCRAM IF NO OBJECT + + 11AE 204D1B JSR OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [I] + 11B1 A006 LDY #6 ; POINT TO "FIRST" SLOT + 11B3 B18E LDA (I),Y ; GRAB DATA + 11B5 C582 CMP ARG1+LO ; IS THIS THE FIRST? + 11B7 D009 BNE REMVC1 ; NO, KEEP SEARCHING + + 11B9 A005 LDY #5 ; ELSE COPY SOURCE'S "NEXT" SLOT + 11BB B190 LDA (J),Y + 11BD C8 INY ; INTO DEST'S "FIRST" SLOT ([Y] = 6) + 11BE 918E STA (I),Y + 11C0 D011 BNE REMVC2 ; BRANCH ALWAYS + + 11C2 204D1B REMVC1: JSR OBJLOC + 11C5 A005 LDY #5 ; GET "NEXT" + 11C7 B18E LDA (I),Y + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 36 +--- 1-OPS --- + + 11C9 C582 CMP ARG1+LO ; FOUND IT? + 11CB D0F5 BNE REMVC1 ; NO, KEEP TRYING + + 11CD A005 LDY #5 ; WHEN FOUND + 11CF B190 LDA (J),Y ; MOVE "NEXT" SLOT OF SOURCE + 11D1 918E STA (I),Y ; TO "NEXT" SLOT OF DEST + + 11D3 A900 REMVC2: LDA #0 + 11D5 A004 LDY #4 ; CLEAR "LOC" + 11D7 9190 STA (J),Y + 11D9 C8 INY ; AND "NEXT" SLOTS ([Y] = 5) + 11DA 9190 STA (J),Y ; OF SOURCE OBJECT + + 11DC 60 REMVEX: RTS + + 11DD ; ------ + 11DD ; PRINTD + 11DD ; ------ + + 11DD ; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + + 11DD A582 ZPRD: LDA ARG1+LO + + 11DF ; ENTRY POINT FOR "USL" + + 11DF 204D1B PRNTDC: JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + 11E2 A007 LDY #7 ; GET PROP TABLE POINTER + 11E4 B18E LDA (I),Y ; FETCH MSB + 11E6 AA TAX ; SAVE IT HERE + 11E7 C8 INY + 11E8 B18E LDA (I),Y ; FETCH LSB + 11EA 858E STA I+LO ; STORE LSB + 11EC 868F STX I+HI ; AND MSB + + 11EE E68E INC I+LO ; POINT PAST THE + 11F0 D002 BNE PDC0 ; LENGTH BYTE + 11F2 E68F INC I+HI + + 11F4 201619 PDC0: JSR SETWRD ; CALC Z-STRING ADDR + 11F7 4C4219 JMP PZSTR ; AND PRINT IT + + 11FA ; ------ + 11FA ; RETURN + 11FA ; ------ + + 11FA ; RETURN FROM "CALL" WITH VALUE [ARG1] + + 11FA A595 ZRET: LDA OLDZSP ; RE-SYNC THE + 11FC 8594 STA ZSP ; Z-STACK POINTER + + 11FE 20CE0E JSR POPVAL ; POP # LOCALS INTO [X/A] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 37 +--- 1-OPS --- + + 1201 868F STX I+HI ; SAVE HERE + 1203 8A TXA ; SET FLAGS; ANY LOCALS? + 1204 F019 BEQ RET2 ; SKIP IF NOT + + 1206 ; RESTORE PUSHED LOCALS + + 1206 CA DEX ; ZERO-ALIGN + 1207 8A TXA ; AND + 1208 0A ASL A ; WORD-ALIGN # LOCALS + 1209 858E STA I+LO ; FOR USE AS A STORAGE INDEX + + 120B 20CE0E RET1: JSR POPVAL ; POP A LOCAL INTO [X/A] + + 120E A48E LDY I+LO ; RETRIEVE STORAGE INDEX + 1210 99010A STA LOCALS+HI,Y ; STORE MSB OF LOCAL + 1213 8A TXA ; MOVE LSB + 1214 99000A STA LOCALS+LO,Y ; AND STORE THAT TOO + + 1217 C68E DEC I+LO + 1219 C68E DEC I+LO ; UPDATE STORAGE INDEX + + 121B C68F DEC I+HI ; AND LOCALS COUNT + 121D D0EC BNE RET1 ; POP TILL NO MORE LOCALS + + 121F ; RESTORE OTHER VARIABLES + + 121F 20CE0E RET2: JSR POPVAL ; POP [ZPCH] AND [ZPCM] + 1222 8697 STX ZPCM + 1224 8598 STA ZPCH + + 1226 20CE0E JSR POPVAL ; POP AND RESTORE + 1229 8695 STX OLDZSP + 122B 8596 STA ZPCL + + 122D A900 LDA #0 + 122F 8599 STA ZPCFLG ; ZPC CHANGED! + + 1231 20DB0F JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 1234 4C0C0F JMP PUTVAL ; AND RETURN IT + + 1237 ; ---- + 1237 ; JUMP + 1237 ; ---- + + 1237 ; JUMP TO Z-LOCATION IN [ARG1] + + 1237 20DB0F ZJUMP: JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 123A 4C8E0F JMP PREDB3 ; A BRANCH THAT ALWAYS SUCCEEDS + + 123D ; ----- + 123D ; PRINT + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 38 +--- 1-OPS --- + + 123D ; ----- + + 123D ; PRINT Z-STRING AT WORD POINTER [ARG1] + + 123D A582 ZPRINT: LDA ARG1+LO + 123F 858E STA I+LO + 1241 A583 LDA ARG1+HI + 1243 858F STA I+HI + + 1245 203019 JSR SETSTR ; CALC STRING ADDRESS + 1248 4C4219 JMP PZSTR ; AND PRINT IT + + 124B ; ----- + 124B ; VALUE + 124B ; ----- + + 124B ; RETURN VALUE OF VARIABLE [ARG1] + + 124B A582 ZVALUE: LDA ARG1+LO + 124D 209F0E JSR VARGET ; GET THE VALUE + 1250 4C0C0F JMP PUTVAL ; EASY ENOUGH + + 1253 ; ---- + 1253 ; BCOM + 1253 ; ---- + + 1253 ; COMPLEMENT [ARG1] + + 1253 A582 ZBCOM: LDA ARG1+LO + 1255 49FF EOR #$FF + 1257 AA TAX + 1258 A583 LDA ARG1+HI + 125A 49FF EOR #$FF + + 125C ; FALL THROUGH ... + + 125C ; --------------------- + 125C ; RETURN VALUE IN [X/A] + 125C ; --------------------- + + 125C 868C VEXIT: STX VALUE+LO + 125E 858D STA VALUE+HI + 1260 4C0C0F JMP PUTVAL + + END + INCLUD OPS2.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 39 +--- 2-OPS --- + + + 1263 ; ----- + 1263 ; LESS? + 1263 ; ----- + + 1263 ; [ARG1] < [ARG2]? + + 1263 20DB0F ZLESS: JSR A12VAL ; MOVE [ARG1] TO [VALUE] + 1266 4C6C12 JMP DLS0 ; MOVE [ARG2] TO [I] & COMPARE + + 1269 ; ------ + 1269 ; DLESS? + 1269 ; ------ + + 1269 ; DECREMENT [ARG1]; SUCCEED IF < [ARG2] + + 1269 208011 ZDLESS: JSR ZDEC ; MOVES ([ARG1]-1) TO [VALUE] + + 126C A584 DLS0: LDA ARG2+LO ; MOVE [ARG2] TO [I] + 126E 858E STA I+LO + 1270 A585 LDA ARG2+HI + 1272 858F STA I+HI + + 1274 4C9512 JMP COMPAR ; COMPARE & RETURN + + 1277 ; ----- + 1277 ; GRTR? + 1277 ; ----- + + 1277 ; [ARG1] > [ARG2]? + + 1277 A582 ZGRTR: LDA ARG1+LO ; MOVE [ARG1] TO [I] + 1279 858E STA I+LO + 127B A583 LDA ARG1+HI + 127D 858F STA I+HI + + 127F 4C8D12 JMP A2VAL ; MOVE [ARG2] TO [VALUE] & COMPARE + + 1282 ; ------ + 1282 ; IGRTR? + 1282 ; ------ + + 1282 ; INCREMENT [ARG1]; SUCCEED IF GREATER THAN [ARG2] + + 1282 207511 ZIGRTR: JSR ZINC ; GET ([ARG1]+1) INTO [VALUE] + + 1285 A58C LDA VALUE+LO ; MOVE [VALUE] TO [I] + 1287 858E STA I+LO + 1289 A58D LDA VALUE+HI + 128B 858F STA I+HI + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 40 +--- 2-OPS --- + + 128D A584 A2VAL: LDA ARG2+LO ; MOVE [ARG2] TO [VALUE] + 128F 858C STA VALUE+LO + 1291 A585 LDA ARG2+HI + 1293 858D STA VALUE+HI + + 1295 209C12 COMPAR: JSR SCOMP ; COMPARE [VALUE] AND [I] + 1298 9038 BCC PGOOD + 129A B023 BCS PBAD + + 129C ; ----------------- + 129C ; SIGNED COMPARISON + 129C ; ----------------- + + 129C ; ENTRY: VALUES IN [VALUE] AND [I] + + 129C A58F SCOMP: LDA I+HI + 129E 458D EOR VALUE+HI + 12A0 1005 BPL SCMP + 12A2 A58F LDA I+HI + 12A4 C58D CMP VALUE+HI + 12A6 60 RTS + + 12A7 A58D SCMP: LDA VALUE+HI + 12A9 C58F CMP I+HI + 12AB D004 BNE SCEX + 12AD A58C LDA VALUE+LO + 12AF C58E CMP I+LO + 12B1 60 SCEX: RTS + + 12B2 ; --- + 12B2 ; IN? + 12B2 ; --- + + 12B2 ; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? + + 12B2 A582 ZIN: LDA ARG1+LO + 12B4 204D1B JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [I] + + 12B7 A004 LDY #4 ; POINT TO "LOC" SLOT + 12B9 B18E LDA (I),Y ; GET DATA + 12BB C584 CMP ARG2+LO ; IS IT THERE? + 12BD F013 BEQ PGOOD ; YES, SUCCEED + + 12BF 4C480F PBAD: JMP PREDF ; TOO BAD, CHUM ... + + 12C2 ; ---- + 12C2 ; BTST + 12C2 ; ---- + + 12C2 ; IS EVERY "ON" BIT IN [ARG1] + 12C2 ; ALSO "ON" IN [ARG2]? + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 41 +--- 2-OPS --- + + + 12C2 A584 ZBTST: LDA ARG2+LO ; FIRST CHECK LSBS + 12C4 2582 AND ARG1+LO + 12C6 C584 CMP ARG2+LO ; LSBS MATCH? + 12C8 D0F5 BNE PBAD ; NO, EXIT NOW + + 12CA A585 LDA ARG2+HI ; ELSE CHECK MSBS + 12CC 2583 AND ARG1+HI + 12CE C585 CMP ARG2+HI ; MATCHED? + 12D0 D0ED BNE PBAD ; SORRY ... + + 12D2 4C540F PGOOD: JMP PREDS + + 12D5 ; --- + 12D5 ; BOR + 12D5 ; --- + + 12D5 ; RETURN [ARG1] "OR" [ARG2] + + 12D5 A582 ZBOR: LDA ARG1+LO + 12D7 0584 ORA ARG2+LO + 12D9 AA TAX + 12DA A583 LDA ARG1+HI + 12DC 0585 ORA ARG2+HI + 12DE 4C5C12 JMP VEXIT + + 12E1 ; ---- + 12E1 ; BAND + 12E1 ; ---- + + 12E1 ; RETURN [ARG1] "AND" [ARG2] + + 12E1 A582 ZBAND: LDA ARG1+LO + 12E3 2584 AND ARG2+LO + 12E5 AA TAX + 12E6 A583 LDA ARG1+HI + 12E8 2585 AND ARG2+HI + 12EA 4C5C12 JMP VEXIT + + 12ED ; ----- + 12ED ; FSET? + 12ED ; ----- + + 12ED ; IS FLAG [ARG1] SET IN OBJECT [ARG2]? + + 12ED 20A91B ZFSETP: JSR FLAGSU ; GET BITS INTO [K] AND [J] + 12F0 A593 LDA K+HI ; DO MSBS + 12F2 2591 AND J+HI + 12F4 8593 STA K+HI + + 12F6 A592 LDA K+LO ; DO LSBS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 42 +--- 2-OPS --- + + 12F8 2590 AND J+LO + + 12FA 0593 ORA K+HI ; ANY BITS ON? + 12FC D0D4 BNE PGOOD ; TARGET BIT MUST BE ON + 12FE 4C480F JMP PREDF + + 1301 ; ---- + 1301 ; FSET + 1301 ; ---- + + 1301 ; SET FLAG [ARG2] IN OBJECT [ARG1] + + 1301 20A91B ZFSET: JSR FLAGSU ; GET BITS INTO [K] & [J], ADDR IN [I] + + 1304 A000 LDY #0 + 1306 A593 LDA K+HI ; FIRST DO MSBS + 1308 0591 ORA J+HI + 130A 918E STA (I),Y + + 130C C8 INY + 130D A592 LDA K+LO ; THEN LSBS + 130F 0590 ORA J+LO + 1311 918E STA (I),Y + 1313 60 RTS + + 1314 ; ------ + 1314 ; FCLEAR + 1314 ; ------ + + 1314 ; CLEAR FLAG [ARG2] IN OBJECT [ARG1] + + 1314 20A91B ZFCLR: JSR FLAGSU ; GETS BITS INTO [J] & [K], ADDR IN [I] + + 1317 A000 LDY #0 + 1319 A591 LDA J+HI ; FETCH MSB + 131B 49FF EOR #$FF ; COMPLEMENT IT + 131D 2593 AND K+HI ; RUB OUT FLAG + 131F 918E STA (I),Y + + 1321 C8 INY + 1322 A590 LDA J+LO ; SAME FOR LSB + 1324 49FF EOR #$FF + 1326 2592 AND K+LO + 1328 918E STA (I),Y + 132A 60 RTS + + 132B ; --- + 132B ; SET + 132B ; --- + + 132B ; SET VARIABLE [ARG1] EQUAL TO [ARG2] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 43 +--- 2-OPS --- + + + 132B A584 ZSET: LDA ARG2+LO ; MOVE THE VALUE + 132D 858C STA VALUE+LO ; INTO [VALUE] + 132F A585 LDA ARG2+HI + 1331 858D STA VALUE+HI + + 1333 A582 LDA ARG1+LO ; GET VARIABLE ID + 1335 4CFB0E JMP VARPUT ; AND CHANGE THE VARIABLE + + 1338 ; ---- + 1338 ; MOVE + 1338 ; ---- + + 1338 ; MOVE OBJECT [ARG1] INTO OBJECT [ARG2] + + 1338 209B11 ZMOVE: JSR ZREMOV ; REMOVE FIRST + + 133B A582 LDA ARG1+LO + 133D 204D1B JSR OBJLOC ; GET SOURCE OBJECT ADDR INTO [I] + + 1340 A58E LDA I+LO ; COPY SOURCE ADDRESS + 1342 8590 STA J+LO ; INTO [J] + 1344 A58F LDA I+HI + 1346 8591 STA J+HI + + 1348 A584 LDA ARG2+LO ; GET DEST OBJECT ID + 134A A004 LDY #4 ; POINT TO "LOC" SLOT OF SOURCE + 134C 918E STA (I),Y ; AND MOVE IT IN + + 134E 204D1B JSR OBJLOC ; GET ADDR OF DEST OBJECT INTO [I] + + 1351 A006 LDY #6 ; POINT TO "FIRST" SLOT + 1353 B18E LDA (I),Y ; GET "FIRST" OF DEST + 1355 AA TAX ; SAVE HERE FOR A MOMENT + + 1356 A582 LDA ARG1+LO ; GET SOURCE OBJECT ID + 1358 918E STA (I),Y ; MAKE IT "FIRST" OF DEST + + 135A 8A TXA ; RESTORE "FIRST" OF DEST + 135B F004 BEQ ZMVEX ; SCRAM IF ZERO + + 135D A005 LDY #5 ; MAKE "FIRST" OF DEST + 135F 9190 STA (J),Y ; THE "NEXT" OF SOURCE + + 1361 60 ZMVEX: RTS + + 1362 ; --- + 1362 ; GET + 1362 ; --- + + 1362 ; RETURN ITEM [ARG2] IN WORD-TABLE [ARG1] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 44 +--- 2-OPS --- + + + 1362 207713 ZGET: JSR WCALC ; CALC ADDRESS + 1365 204F18 JSR GETBYT ; GET 1ST BYTE (MSB) + + 1368 858D DOGET: STA VALUE+HI ; SAVE MSB + 136A 204F18 JSR GETBYT ; GET LSB + 136D 858C STA VALUE+LO ; SAVE AND + 136F 4C0C0F JMP PUTVAL ; HAND IT OVER + + 1372 ; ---- + 1372 ; GETB + 1372 ; ---- + + 1372 ; RETURN ITEM [ARG2] IN BYTE-TABLE AT [ARG1] + + 1372 207B13 ZGETB: JSR BCALC + 1375 F0F1 BEQ DOGET ; [A] = 0, SO CLEAR MSB OF [VALUE] + + 1377 ; -------------------- + 1377 ; CALC TABLE ADDRESSES + 1377 ; -------------------- + + 1377 ; WORD-ALIGNED ENTRY + + 1377 0684 WCALC: ASL ARG2+LO ; WORD-ALIGN FOR + 1379 2685 ROL ARG2+HI ; WORD ACCESS + + 137B ; BYTE-ALIGNED ENTRY + + 137B A584 BCALC: LDA ARG2+LO ; ADD BASE ADDR OF TABLE + 137D 18 CLC ; TO ITEM + 137E 6582 ADC ARG1+LO ; INDEX + 1380 859C STA MPCL + + 1382 A585 LDA ARG2+HI ; SAME FOR MSBS + 1384 6583 ADC ARG1+HI + 1386 859D STA MPCM + + 1388 A900 LDA #0 + 138A 859E STA MPCH ; CLEAR TOP BIT + 138C 859F STA MPCFLG ; & INVALIDATE [MPC] + 138E 60 RTS + + 138F ; ---- + 138F ; GETP + 138F ; ---- + + 138F ; RETURN PROPERTY [ARG2] OF OBJECT [ARG1]; + 138F ; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 + + 138F 20761B ZGETP: JSR PROPB + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 45 +--- 2-OPS --- + + + 1392 20921B GETP1: JSR PROPN + 1395 C584 CMP ARG2+LO + 1397 F01B BEQ GETP3 + 1399 9006 BCC GETP2 + + 139B 209F1B JSR PROPNX + 139E 4C9213 JMP GETP1 ; TRY AGAIN WITH NEXT PROP + + 13A1 A584 GETP2: LDA ARG2+LO ; GET PROPERTY # + 13A3 38 SEC ; ZERO-ALIGN IT + 13A4 E901 SBC #1 + 13A6 0A ASL A ; WORD-ALIGN IT + 13A7 A8 TAY ; USE AS AN INDEX + 13A8 B1B2 LDA (OBJTAB),Y ; GET MSB OF PROPERTY + 13AA 858D STA VALUE+HI + 13AC C8 INY + 13AD B1B2 LDA (OBJTAB),Y ; DO SAME WITH LSB + 13AF 858C STA VALUE+LO + 13B1 4C0C0F JMP PUTVAL ; RETURN DEFAULT IN [VALUE] + + 13B4 20971B GETP3: JSR PROPL + 13B7 C8 INY ; MAKE [Y] POINT TO 1ST BYTE OF PROP + 13B8 AA TAX ; (SET FLAGS) IF LENGTH IN [A] = 0 + 13B9 F009 BEQ GETPB ; GET A BYTE PROPERTY + 13BB C901 CMP #1 ; IF LENGTH = 1 + 13BD F00B BEQ GETPW ; GET A WORD PROPERTY + + 13BF ; *** ERROR #7: PROPERTY LENGTH *** + + 13BF A907 LDA #7 + 13C1 4CF91B JMP ZERROR + + 13C4 ; GET A 1-BYTE PROPERTY + + 13C4 B18E GETPB: LDA (I),Y ; GET LSB INTO [A] + 13C6 A200 LDX #0 ; CLEAR MSB IN [X] + 13C8 F006 BEQ ETPEX + + 13CA ; GET A 2-BYTE PROPERTY + + 13CA B18E GETPW: LDA (I),Y ; GET MSB + 13CC AA TAX ; INTO [X] + 13CD C8 INY ; POINT TO LSB + 13CE B18E LDA (I),Y ; GET IT INTO [A] + + 13D0 858C ETPEX: STA VALUE+LO ; STORE LSB + 13D2 868D STX VALUE+HI ; AND MSB + 13D4 4C0C0F JMP PUTVAL + + 13D7 ; ----- + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 46 +--- 2-OPS --- + + 13D7 ; GETPT + 13D7 ; ----- + + 13D7 ; RETURN POINTER TO PROP TABLE [ARG2] + 13D7 ; IN OBJECT [ARG1] + + 13D7 20761B ZGETPT: JSR PROPB + + 13DA 20921B GETPT1: JSR PROPN ; RETURNS OFFSET IN [Y] + 13DD C584 CMP ARG2+LO + 13DF F008 BEQ GETPT2 + 13E1 901E BCC DORET + 13E3 209F1B JSR PROPNX ; TRY NEXT PROPERTY + 13E6 4CDA13 JMP GETPT1 + + 13E9 E68E GETPT2: INC I+LO + 13EB D002 BNE GETPT3 + 13ED E68F INC I+HI + + 13EF 98 GETPT3: TYA ; FETCH OFFSET + 13F0 18 CLC + 13F1 658E ADC I+LO ; ADD LSB OF TABLE ADDRESS + 13F3 858C STA VALUE+LO + + 13F5 A58F LDA I+HI ; AND MSB + 13F7 6900 ADC #0 + 13F9 38 SEC ; STRIP OFF + 13FA E5A3 SBC ZCODE ; RELATIVE POINTER + 13FC 858D STA VALUE+HI + 13FE 4C0C0F JMP PUTVAL ; AND RETURN + + 1401 4C040F DORET: JMP RET0 ; ELSE RETURN A ZERO + + 1404 ; ----- + 1404 ; NEXTP + 1404 ; ----- + + 1404 ; RETURN INDEX # OF PROP FOLLOWING PROP [ARG2] IN OBJECT [ARG1]; + 1404 ; RETURN ZERO IF LAST; RETURN FIRST IF [ARG2]=0; ERROR IF NONE + + 1404 20761B ZNEXTP: JSR PROPB + 1407 A584 LDA ARG2+LO ; IF [ARG2]=0 + 1409 F012 BEQ NXTP3 ; RETURN "FIRST" SLOT + + 140B 20921B NXTP1: JSR PROPN ; FETCH PROPERTY # + 140E C584 CMP ARG2+LO ; COMPARE TO TARGET # + 1410 F008 BEQ NXTP2 ; FOUND IT! + 1412 90ED BCC DORET ; LAST PROP, SO RETURN ZERO + 1414 209F1B JSR PROPNX ; ELSE TRY NEXT PROPERTY + 1417 4C0B14 JMP NXTP1 + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 47 +--- 2-OPS --- + + 141A 209F1B NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY + + 141D 20921B NXTP3: JSR PROPN ; GET THE PROPERTY # + 1420 4C060F JMP PUTBYT ; AND RETURN IT + + 1423 ; --- + 1423 ; ADD + 1423 ; --- + + 1423 ; RETURN [ARG1] + [ARG2] + + 1423 A582 ZADD: LDA ARG1+LO ; ADD LSBS + 1425 18 CLC + 1426 6584 ADC ARG2+LO + 1428 AA TAX ; SAVE LSB HERE + 1429 A583 LDA ARG1+HI ; ADD MSBS + 142B 6585 ADC ARG2+HI + 142D 4C5C12 JMP VEXIT + + 1430 ; --- + 1430 ; SUB + 1430 ; --- + + 1430 ; RETURN [ARG1] - [ARG2] + + 1430 A582 ZSUB: LDA ARG1+LO ; SUBTRACT LSBS + 1432 38 SEC + 1433 E584 SBC ARG2+LO + 1435 AA TAX ; SAVE LSB HERE + 1436 A583 LDA ARG1+HI ; SUBTRACT MSBS + 1438 E585 SBC ARG2+HI + 143A 4C5C12 JMP VEXIT ; EXIT WITH [X]=LSB, [A]=MSB + + 143D ; --- + 143D ; MUL + 143D ; --- + + 143D ; RETURN [ARG1] * [ARG2] + + 143D 20F714 ZMUL: JSR MINIT ; INIT THINGS + + 1440 66D8 ZMLOOP: ROR MTEMP+HI + 1442 66D7 ROR MTEMP+LO + 1444 6685 ROR ARG2+HI + 1446 6684 ROR ARG2+LO + 1448 900D BCC ZMNEXT + + 144A A582 LDA ARG1+LO + 144C 18 CLC + 144D 65D7 ADC MTEMP+LO + 144F 85D7 STA MTEMP+LO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 48 +--- 2-OPS --- + + 1451 A583 LDA ARG1+HI + 1453 65D8 ADC MTEMP+HI + 1455 85D8 STA MTEMP+HI + + 1457 CA ZMNEXT: DEX + 1458 10E6 BPL ZMLOOP + + 145A A684 LDX ARG2+LO ; PUT LSB OF PRODUCT + 145C A585 LDA ARG2+HI ; AND MSB + 145E 4C5C12 JMP VEXIT ; WHERE "VEXIT" EXPECTS THEM + + 1461 ; --- + 1461 ; DIV + 1461 ; --- + + 1461 ; RETURN QUOTIENT OF [ARG1] / [ARG2] + + 1461 207514 ZDIV: JSR DIVIDE + 1464 A6D3 LDX QUOT+LO + 1466 A5D4 LDA QUOT+HI + 1468 4C5C12 JMP VEXIT + + 146B ; --- + 146B ; MOD + 146B ; --- + + 146B ; RETURN REMAINDER OF [ARG1] / [ARG2] + + 146B 207514 ZMOD: JSR DIVIDE + 146E A6D5 LDX REMAIN+LO ; FETCH THE REMAINDER + 1470 A5D6 LDA REMAIN+HI ; IN [REMAIN] + 1472 4C5C12 JMP VEXIT ; AND RETURN IT + + 1475 ; --------------- + 1475 ; SIGNED DIVISION + 1475 ; --------------- + + 1475 ; ENTRY: DIVIDEND IN [ARG1], DIVISOR IN [ARG2] + 1475 ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] + + 1475 A583 DIVIDE: LDA ARG1+HI ; SIGN OF REMAINDER + 1477 85DA STA RSIGN ; IS THE SIGN OF THE DIVIDEND + 1479 4585 EOR ARG2+HI ; SIGN OF QUOTIENT IS POSITIVE + 147B 85D9 STA QSIGN ; IF SIGNS OF TERMS ARE THE SAME + + 147D A582 LDA ARG1+LO ; MOVE [ARG1] TO [QUOT] + 147F 85D3 STA QUOT+LO + 1481 A583 LDA ARG1+HI + 1483 85D4 STA QUOT+HI ; IF DIVIDEND IS POSITIVE + 1485 1003 BPL ABSDIV ; MOVE DIVISOR + 1487 20B314 JSR ABQUOT ; ELSE CALC ABS(DIVIDEND) FIRST + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 49 +--- 2-OPS --- + + + 148A A584 ABSDIV: LDA ARG2+LO + 148C 85D5 STA REMAIN+LO + 148E A585 LDA ARG2+HI + 1490 85D6 STA REMAIN+HI ; IF REMAINDER IS POSITIVE + 1492 1003 BPL GODIV ; WE'RE READY TO DIVIDE + 1494 20A514 JSR ABREM ; ELSE CALC ABS(DIVISOR) + + 1497 20C114 GODIV: JSR UDIV ; DO UNSIGNED DIVIDE + + 149A A5D9 LDA QSIGN ; SHOULD QUOTIENT BE FLIPPED? + 149C 1003 BPL RFLIP ; NO, TEST REMAINDER + 149E 20B314 JSR ABQUOT ; ELSE GET ABSOLUTE VALUE + + 14A1 A5DA RFLIP: LDA RSIGN ; SHOULD EMAINDER BE FLIPPED? + 14A3 100D BPL DIVEX ; NO, WE'RE DONE + + 14A5 ; ELSE FALL THROUGH ... + + 14A5 ; ---------------- + 14A5 ; CALC ABS(REMAIN) + 14A5 ; ---------------- + + 14A5 A900 ABREM: LDA #0 + 14A7 38 SEC + 14A8 E5D5 SBC REMAIN+LO + 14AA 85D5 STA REMAIN+LO + 14AC A900 LDA #0 + 14AE E5D6 SBC REMAIN+HI + 14B0 85D6 STA REMAIN+HI + + 14B2 60 DIVEX: RTS + + 14B3 ; -------------- + 14B3 ; CALC ABS(QUOT) + 14B3 ; -------------- + + 14B3 A900 ABQUOT: LDA #0 + 14B5 38 SEC + 14B6 E5D3 SBC QUOT+LO + 14B8 85D3 STA QUOT+LO + 14BA A900 LDA #0 + 14BC E5D4 SBC QUOT+HI + 14BE 85D4 STA QUOT+HI + 14C0 60 RTS + + 14C1 ; ----------------- + 14C1 ; UNSIGNED DIVISION + 14C1 ; ----------------- + + 14C1 ; ENTRY: DIVIDEND IN [QUOT], DIVISOR IN [REMAIN] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 50 +--- 2-OPS --- + + 14C1 ; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN] + + 14C1 A5D5 UDIV: LDA REMAIN+LO ; CHECK [REMAIN] + 14C3 05D6 ORA REMAIN+HI ; BEFORE PROCEEDING + 14C5 F02B BEQ DIVERR ; CAN'T DIVIDE BY ZERO! + + 14C7 20F714 JSR MINIT ; SET IT ALL UP + + 14CA 26D3 UDLOOP: ROL QUOT+LO + 14CC 26D4 ROL QUOT+HI + 14CE 26D7 ROL MTEMP+LO + 14D0 26D8 ROL MTEMP+HI + + 14D2 A5D7 LDA MTEMP+LO + 14D4 38 SEC + 14D5 E5D5 SBC REMAIN+LO + 14D7 A8 TAY ; SAVE HERE + 14D8 A5D8 LDA MTEMP+HI + 14DA E5D6 SBC REMAIN+HI + 14DC 9004 BCC UDNEXT + 14DE 84D7 STY MTEMP+LO + 14E0 85D8 STA MTEMP+HI + + 14E2 CA UDNEXT: DEX + 14E3 D0E5 BNE UDLOOP + + 14E5 26D3 ROL QUOT+LO ; SHIFT LAST CARRY FOR QUOTIENT + 14E7 26D4 ROL QUOT+HI + + 14E9 A5D7 LDA MTEMP+LO ; MOVE REMAINDER + 14EB 85D5 STA REMAIN+LO ; INTO [REMAIN] + 14ED A5D8 LDA MTEMP+HI + 14EF 85D6 STA REMAIN+HI + 14F1 60 RTS + + 14F2 ; *** ERROR #8: DIVISION BY ZERO *** + + 14F2 A908 DIVERR: LDA #8 + 14F4 4CF91B JMP ZERROR + + 14F7 ; --------- + 14F7 ; MATH INIT + 14F7 ; --------- + + 14F7 A210 MINIT: LDX #16 ; INIT LOOPING INDEX + 14F9 A900 LDA #0 + 14FB 85D7 STA MTEMP+LO ; CLEAR TEMP + 14FD 85D8 STA MTEMP+HI ; REGISTER + 14FF 18 CLC ; AND CARRY + 1500 60 RTS + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 51 +--- 2-OPS --- + + END + INCLUD OPSX.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 52 +--- X-OPS --- + + + 1501 ; ------ + 1501 ; EQUAL? + 1501 ; ------ + + 1501 ; IS [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? + + 1501 C681 ZEQUAL: DEC NARGS ; DOUBLE-CHECK # ARGS + 1503 D005 BNE DOEQ ; MUST BE AT LEAST TWO, OR ... + + 1505 ; *** ERROR #9: NOT ENOUGH "EQUAL?" ARGS *** + + 1505 A909 LDA #9 + 1507 4CF91B JMP ZERROR + + 150A A582 DOEQ: LDA ARG1+LO ; FETCH LSB + 150C A683 LDX ARG1+HI ; AND MSB OF [ARG1] + + 150E C584 CMP ARG2+LO ; TEST LSB OF [ARG2] + 1510 D004 BNE TRY2 ; NO GOOD, LOOK FOR ANOTHER ARG + 1512 E485 CPX ARG2+HI ; ELSE TRY MSB OF [ARG2] + 1514 F018 BEQ EQOK ; MATCHED! + + 1516 C681 TRY2: DEC NARGS ; OUT OF ARGS YET? + 1518 F017 BEQ EQBAD ; YES, WE FAILED + + 151A C586 CMP ARG3+LO ; TRY LSB OF [ARG3] + 151C D004 BNE TRY3 ; NO GOOD, LOOK FOR ANOTHER ARG + 151E E487 CPX ARG3+HI ; HOW ABOUT MSB OF [ARG3]? + 1520 F00C BEQ EQOK ; YAY! + + 1522 C681 TRY3: DEC NARGS ; OUT OF ARGS YET? + 1524 F00B BEQ EQBAD ; IF NOT ... + + 1526 C588 CMP ARG4+LO ; TRY [ARG4] + 1528 D007 BNE EQBAD ; SORRY, CHUM + 152A E489 CPX ARG4+HI ; MSB MATCHED? + 152C D003 BNE EQBAD ; TOO BAD + + 152E 4C540F EQOK: JMP PREDS ; FINALLY MATCHED! + + 1531 4C480F EQBAD: JMP PREDF ; FAILURE (SNIFF!) + + 1534 ; ---- + 1534 ; CALL + 1534 ; ---- + + 1534 ; BRANCH TO FUNCTION AT ([ARG1]*2), PASSING + 1534 ; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] + + 1534 A582 ZCALL: LDA ARG1+LO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 53 +--- X-OPS --- + + 1536 0583 ORA ARG1+HI ; IS CALL ADDRESS ZERO? + 1538 D003 BNE DOCALL ; NO, CONTINUE + + 153A 4C060F JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] + + 153D A695 DOCALL: LDX OLDZSP ; SAVE OLD STACK POINTER + 153F A596 LDA ZPCL ; AND LSB OF [ZPC] + 1541 20E80E JSR PUSHXA ; ON THE Z-STACK + + 1544 A697 LDX ZPCM ; SAVE MIDDLE 8 BITS + 1546 A598 LDA ZPCH ; AND TOP BIT OF [ZPC] + 1548 20E80E JSR PUSHXA ; AS WELL + + 154B ; FORM 16-BIT ADDRESS FROM [ARG1] + + 154B A900 LDA #0 ; CLEAR HIGH BIT FOR ROTATE + 154D 8599 STA ZPCFLG ; AND INVALIDATE [ZPC] + + 154F 0682 ASL ARG1+LO ; MULTIPLY [ARG1] + 1551 2683 ROL ARG1+HI ; BY TWO + 1553 2A ROL A ; HIGH BIT INTO [A] + 1554 8598 STA ZPCH ; NEW HIGH BIT OF [ZPC] + + 1556 A583 LDA ARG1+HI ; GET NEW LOW BYTES + 1558 8597 STA ZPCM + 155A A582 LDA ARG1+LO + 155C 8596 STA ZPCL + + 155E 201918 JSR NEXTPC ; FETCH # LOCALS TO PASS + 1561 8590 STA J+LO ; SAVE HERE FOR COUNTING + 1563 8591 STA J+HI ; AND HERE FOR LATER REFERENCE + 1565 F02B BEQ ZCALL2 ; SKIP IF NO LOCALS + + 1567 A900 LDA #0 + 1569 858E STA I+LO ; ELSE INIT STORAGE INDEX + + 156B A48E ZCALL1: LDY I+LO + 156D BE000A LDX LOCALS+LO,Y ; GET LSB OF LOCAL INTO [X] + 1570 B9010A LDA LOCALS+HI,Y ; AND MSB INTO [A] + 1573 848E STY I+LO ; SAVE THE INDEX + 1575 20E80E JSR PUSHXA ; PUSH LOCAL IN [X/A] ONTO Z-STACK + + 1578 201918 JSR NEXTPC ; GET MSB OF NEW LOCAL + 157B 858F STA I+HI ; SAVE IT HERE + 157D 201918 JSR NEXTPC ; NOW GET LSB + + 1580 A48E LDY I+LO ; RESTORE INDEX + 1582 99000A STA LOCALS+LO,Y ; STORE LSB INTO [LOCALS] + 1585 A58F LDA I+HI ; RETRIEVE MSB + 1587 99010A STA LOCALS+HI,Y ; STORE IT INTO [LOCALS] + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 54 +--- X-OPS --- + + 158A C8 INY + 158B C8 INY ; UPDATE + 158C 848E STY I+LO ; THE STORAGE INDEX + + 158E C690 DEC J+LO ; ANY MORE LOCALS? + 1590 D0D9 BNE ZCALL1 ; YES, KEEP LOOPING + + 1592 ; MOVE UP TO 3 ARGUMENTS TO [LOCALS] + + 1592 C681 ZCALL2: DEC NARGS ; EXTRA ARGS IN THIS CALL? + 1594 F026 BEQ ZCALL3 ; NO, CONTINUE + + 1596 A584 LDA ARG2+LO ; MOVE [ARG2] TO LOCAL #1 + 1598 8D000A STA LOCALS+LO + 159B A585 LDA ARG2+HI + 159D 8D010A STA LOCALS+HI + + 15A0 C681 DEC NARGS ; ANY LEFT? + 15A2 F018 BEQ ZCALL3 ; NO, SCRAM + + 15A4 A586 LDA ARG3+LO ; MOVE [ARG3] TO LOCAL #2 + 15A6 8D020A STA LOCALS+LO+2 + 15A9 A587 LDA ARG3+HI + 15AB 8D030A STA LOCALS+HI+2 + + 15AE C681 DEC NARGS ; ANY LEFT? + 15B0 F00A BEQ ZCALL3 ; NO, EXUENT + + 15B2 A588 LDA ARG4+LO ; MOVE [ARG4] TO LOCAL #3 + 15B4 8D040A STA LOCALS+LO+4 + 15B7 A589 LDA ARG4+HI + 15B9 8D050A STA LOCALS+HI+4 + + 15BC A691 ZCALL3: LDX J+HI ; RETRIEVE # LOCALS + 15BE 8A TXA ; DUPE FOR NO GOOD REASON + 15BF 20E80E JSR PUSHXA ; PUSH # LOCALS ONTO Z-STACK + + 15C2 A594 LDA ZSP ; REMEMBER WHERE + 15C4 8595 STA OLDZSP ; WE CAME FROM + + 15C6 60 RTS ; WHEW! + + 15C7 ; --- + 15C7 ; PUT + 15C7 ; --- + + 15C7 ; SET ITEM [ARG2] IN WORD-TABLE [ARG1] EQUAL TO [ARG3] + + 15C7 0684 ZPUT: ASL ARG2+LO ; WORD-ALIGN [ARG2] + 15C9 2685 ROL ARG2+HI + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 55 +--- X-OPS --- + + 15CB 20DD15 JSR PCALC ; GET ITEM ADDR INTO [I] + 15CE A587 LDA ARG3+HI ; STORE MSB OF [ARG3] + 15D0 918E STA (I),Y ; INTO MSB OF TABLE POSITION + 15D2 C8 INY ; POINT TO LSB + 15D3 D003 BNE PUTLSB ; BRANCH ALWAYS + + 15D5 ; ---- + 15D5 ; PUTB + 15D5 ; ---- + + 15D5 ; SET ITEM [ARG2] IN BYTE-TABLE [ARG1] EQUAL TO [ARG3] + + 15D5 20DD15 ZPUTB: JSR PCALC + + 15D8 ; ENTRY FOR "PUT" + + 15D8 A586 PUTLSB: LDA ARG3+LO ; GET LSB OF [ARG3] + 15DA 918E STA (I),Y ; STORE IN TABLE AT [Y] + 15DC 60 RTS + + 15DD ; --------------------------- + 15DD ; CALC ITEM ADDRESS FOR "PUT" + 15DD ; --------------------------- + + 15DD A584 PCALC: LDA ARG2+LO ; ADD ITEM OFFSET IN [ARG2] + 15DF 18 CLC ; TO TABLE ADDR IN [ARG1] + 15E0 6582 ADC ARG1+LO ; TO FORM A POINTER + 15E2 858E STA I+LO ; IN [I] + + 15E4 A585 LDA ARG2+HI ; SAME FOR MSB + 15E6 6583 ADC ARG1+HI + 15E8 18 CLC + 15E9 65A3 ADC ZCODE ; MAKE IT ABSOLUTE + 15EB 858F STA I+HI + + 15ED A000 LDY #0 ; ZERO FOR INDEXING + 15EF 60 RTS + + 15F0 ; ---- + 15F0 ; PUTP + 15F0 ; ---- + + 15F0 ; SET PROPERTY [ARG2] IN OBJECT [ARG1] EQUAL TO [ARG3] + + 15F0 20761B ZPUTP: JSR PROPB + + 15F3 20921B PUTP1: JSR PROPN + 15F6 C584 CMP ARG2+LO + 15F8 F008 BEQ PUTP2 + 15FA 901B BCC PNERR ; ERROR IF LOWER + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 56 +--- X-OPS --- + + 15FC 209F1B JSR PROPNX ; TRY NEXT PROPERTY + 15FF 4CF315 JMP PUTP1 + + 1602 20971B PUTP2: JSR PROPL + 1605 C8 INY ; MAKE [Y] POINT TO 1ST PROPERTY BYTE + 1606 AA TAX ; (SET FLAGS) IF LENGTH IN [A] = 0 + 1607 F009 BEQ PUTP3 ; PUT A BYTE + 1609 C901 CMP #1 ; PUT A WORD IF [A] = 1 + 160B D00F BNE PLERR ; ELSE LENGTH IS BAD + + 160D A587 LDA ARG3+HI ; GET MSB OF PROPERTY + 160F 918E STA (I),Y ; AND STORE IN OBJECT + 1611 C8 INY ; POINT TO LSB SLOT + + 1612 A586 PUTP3: LDA ARG3+LO ; FETCH LSB + 1614 918E STA (I),Y ; AND STORE IN OBJECT + 1616 60 RTS + + 1617 ; *** ERROR #10: BAD PROPERTY NUMBER *** + + 1617 A90A PNERR: LDA #10 + 1619 4CF91B JMP ZERROR + + 161C ; *** ERROR #11: PUTP PROPERTY LENGTH *** + + 161C A90B PLERR: LDA #11 + 161E 4CF91B JMP ZERROR + + 1621 ; ------ + 1621 ; PRINTC + 1621 ; ------ + + 1621 ; PRINT CHAR WITH ASCII VALUE IN [ARG1] + + 1621 A582 ZPRC: LDA ARG1+LO ; GRAB THE CHAR + 1623 4C891C JMP COUT ; AND SHIP IT OUT + + 1626 ; ------ + 1626 ; PRINTN + 1626 ; ------ + + 1626 ; PRINT VALUE OF [ARG1] AS A SIGNED INTEGER + + 1626 A582 ZPRN: LDA ARG1+LO ; MOVE [ARG1] TO [QUOT] + 1628 85D3 STA QUOT+LO + 162A A583 LDA ARG1+HI + 162C 85D4 STA QUOT+HI + + 162E ; PRINT [QUOT] + + 162E A5D4 NUMBER: LDA QUOT+HI ; IF VALUE IS POSITIVE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 57 +--- X-OPS --- + + 1630 1008 BPL DIGCNT ; CONTINUE + + 1632 A92D LDA #$2D ; ELSE START WITH A MINUS SIGN + 1634 20891C JSR COUT + + 1637 20B314 JSR ABQUOT ; AND CALC ABS([QUOT]) + + 163A ; COUNT # OF DECIMAL DIGITS + + 163A A900 DIGCNT: LDA #0 ; RESET + 163C 85DB STA DIGITS ; DIGIT INDEX + + 163E A5D3 DGC: LDA QUOT+LO ; IS QUOTIENT + 1640 05D4 ORA QUOT+HI ; ZERO YET? + 1642 F012 BEQ PRNTN3 ; YES, READY TO PRINT + + 1644 A90A LDA #10 ; ELSE DIVIDE [QUOT] + 1646 85D5 STA REMAIN+LO ; BY 10 (LSB) + 1648 A900 LDA #0 + 164A 85D6 STA REMAIN+HI ; 10 (MSB) + + 164C 20C114 JSR UDIV ; UNSIGNED DIVIDE + + 164F A5D5 LDA REMAIN+LO ; FETCH LSB OF REMAINDER (THE DIGIT) + 1651 48 PHA ; SAVE IT ON STACK + 1652 E6DB INC DIGITS ; UPDATE DIGIT COUNT + 1654 D0E8 BNE DGC ; LOOP TILL QUOTIENT=0 + + 1656 A5DB PRNTN3: LDA DIGITS ; IF DIGIT COUNT IS NZ + 1658 D005 BNE PRNTN4 ; CONTINUE + + 165A A930 LDA #'0' ; ELSE PRINT "0" + 165C 4C891C JMP COUT ; AND RETURN + + 165F 68 PRNTN4: PLA ; PULL A DIGIT OFF THE STACK + 1660 18 CLC + 1661 6930 ADC #'0' ; CONVERT TO ASCII + 1663 20891C JSR COUT ; AND PRINT IT + 1666 C6DB DEC DIGITS ; OUT OF DIGITS YET? + 1668 D0F5 BNE PRNTN4 ; NO, KEEP LOOPING + 166A 60 RTS + + 166B ; ------ + 166B ; RANDOM + 166B ; ------ + + 166B ; RETURN A RANDOM VALUE BETWEEN 0 AND [ARG1] + + 166B A582 ZRAND: LDA ARG1+LO ; MAKE [ARG1] THE DIVISOR + 166D 8584 STA ARG2+LO + 166F A583 LDA ARG1+HI + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 58 +--- X-OPS --- + + 1671 8585 STA ARG2+HI + + 1673 20811C JSR RANDOM ; GET RANDOM BYTES INTO [A] AND [X] + 1676 8682 STX ARG1+LO ; MAKE THEM THE DIVIDEND + 1678 297F AND #$7F ; MAKE SURE MSB IS POSITIVE + 167A 8583 STA ARG1+HI + + 167C 207514 JSR DIVIDE ; SIGNED DIVIDE, [ARG1] / [ARG2] + + 167F A5D5 LDA REMAIN+LO ; MOVE REMAINDER + 1681 858C STA VALUE+LO ; INTO [VALUE] + 1683 A5D6 LDA REMAIN+HI + 1685 858D STA VALUE+HI + + 1687 20D40F JSR INCVAL ; INCREMENT [VALUE] + 168A 4C0C0F JMP PUTVAL ; AND RETURN RESULT + + 168D ; ---- + 168D ; PUSH + 168D ; ---- + + 168D ; PUSH [ARG1] ONTO THE Z-STACK + + 168D A682 ZPUSH: LDX ARG1+LO + 168F A583 LDA ARG1+HI + 1691 4CE80E JMP PUSHXA + + 1694 ; --- + 1694 ; POP + 1694 ; --- + + 1694 ; POP WORD OFF Z-STACK, STORE IN VARIABLE [ARG1] + + 1694 20CE0E ZPOP: JSR POPVAL ; VALUE INTO [VALUE] + 1697 A582 LDA ARG1+LO ; GET VARIABLE ID + 1699 4CFB0E JMP VARPUT ; AND CHANGE THE VARIABLE + + END + INCLUD READ.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 59 +--- READ HANDLER --- + + + 169C ; ---- + 169C ; READ + 169C ; ---- + + 169C ; READ LINE INTO TABLE [ARG1]; PARSE INTO TABLE [ARG2] + + 169C 20201D ZREAD: JSR ZUSL ; UPDATE THE STATUS LINE + + 169F A583 LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + 16A1 18 CLC ; ABSOLUTE + 16A2 65A3 ADC ZCODE ; LSBS NEED NOT CHANGE + 16A4 8583 STA ARG1+HI + + 16A6 A585 LDA ARG2+HI + 16A8 18 CLC + 16A9 65A3 ADC ZCODE + 16AB 8585 STA ARG2+HI + + 16AD 205B1F JSR INPUT ; READ LINE; RETURN LENGTH IN [A] + 16B0 85C2 STA LINLEN ; SAVE # CHARS IN LINE + + 16B2 A900 LDA #0 + 16B4 85C3 STA WRDLEN ; INIT # CHARS IN WORD COUNTER + + 16B6 A001 LDY #1 ; POINT TO "# WORDS READ" SLOT + 16B8 9184 STA (ARG2),Y ; AND CLEAR IT ([A] = 0) + + 16BA 84C0 STY SOURCE ; INIT SOURCE TABLE PNTR ([Y] = 1) + 16BC C8 INY ; = 2 + 16BD 84C1 STY RESULT ; AND RESULT TABLE POINTER + + 16BF ; MAIN LOOP STARTS HERE + + 16BF A000 READL: LDY #0 ; POINT TO "MAX # WORDS" SLOT + 16C1 B184 LDA (ARG2),Y ; AND READ IT + + 16C3 F004 BEQ RLERR ; IF ENTRY IS ZERO, PATCH IT (BM 5/14/85) + 16C5 C93C CMP #60 ; IF ENTRY <= 59, + 16C7 9004 BCC RL0 ; CONTINUE + + 16C9 A93B RLERR: LDA #59 ; FORCE # TOKENS + 16CB 9184 STA (ARG2),Y ; TO BE 59 + + 16CD C8 RL0: INY ; (Y = 1) POINT TO "# WORDS READ" SLOT + 16CE D184 CMP (ARG2),Y ; TOO MANY WORDS? + 16D0 9006 BCC RLEX ; EXIT IF SO (BM 5/1/85) + + 16D2 A5C2 RL1: LDA LINLEN + 16D4 05C3 ORA WRDLEN ; OUT OF CHARS AND WORDS? + 16D6 D001 BNE RL2 ; NOT YET + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 60 +--- READ HANDLER --- + + + 16D8 60 RLEX: RTS ; ELSE EXIT + + 16D9 A5C3 RL2: LDA WRDLEN ; GET WORD LENGTH + 16DB C906 CMP #6 ; 6 CHARS DONE? + 16DD 9003 BCC RL3 ; NO, KEEP GOING + 16DF 207017 JSR FLUSHW ; ELSE FLUSH REMAINDER OF WORD + + 16E2 A5C3 RL3: LDA WRDLEN ; GET WORD LENGTH AGAIN + 16E4 D024 BNE READL2 ; CONTINUE IF NOT FIRST CHAR + + 16E6 ; START A NEW WORD + + 16E6 A205 LDX #5 ; CLEAR Z-WORD INPUT BUFFER + 16E8 95B4 RLL: STA IN,X ; [A] = 0 + 16EA CA DEX + 16EB 10FB BPL RLL + + 16ED 206217 JSR EFIND ; GET BASE ADDRESS INTO [ENTRY] + 16F0 A5C0 LDA SOURCE ; STORE THE START POS OF THE WORD + 16F2 A003 LDY #3 ; INTO THE "WORD START" SLOT + 16F4 91C4 STA (ENTRY),Y ; OF THE RESULT TABLE + + 16F6 A8 TAY + 16F7 B182 LDA (ARG1),Y ; GET A CHAR FROM SOURCE BUFFER + 16F9 209D17 JSR SIB ; IS IT A SELF-INSERTING BREAK? + 16FC B026 BCS DOSIB ; YES IF CARRY WAS SET + + 16FE 208B17 JSR NORM ; IS IT A "NORMAL" BREAK? + 1701 9007 BCC READL2 ; NO, CONTINUE + + 1703 E6C0 INC SOURCE ; ELSE FLUSH THE STRANDED BREAK + 1705 C6C2 DEC LINLEN ; UPDATE # CHARS LEFT IN LINE + 1707 4CBF16 JMP READL ; AND LOOP + + 170A A5C2 READL2: LDA LINLEN ; OUT OF CHARS YET? + 170C F01E BEQ READL3 ; LOOKS THAT WAY + + 170E A4C0 LDY SOURCE + 1710 B182 LDA (ARG1),Y ; ELSE GRAB NEXT CHAR + 1712 208617 JSR BREAK ; IS IT A BREAK? + 1715 B015 BCS READL3 ; YES IF CARRY WAS SET + + 1717 A6C3 LDX WRDLEN ; ELSE STORE THE CHAR + 1719 95B4 STA IN,X ; INTO THE INPUT BUFFER + + 171B C6C2 DEC LINLEN ; ONE LESS CHAR IN LINE + 171D E6C3 INC WRDLEN ; ONE MORE IN WORD + 171F E6C0 INC SOURCE ; POINT TO NEXT CHAR IN SOURCE + 1721 4CBF16 JMP READL ; AND LOOP BACK + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 61 +--- READ HANDLER --- + + 1724 85B4 DOSIB: STA IN ; PUT THE BREAK INTO 1ST WORD SLOT + 1726 C6C2 DEC LINLEN ; ONE LESS CHAR IN LINE + 1728 E6C3 INC WRDLEN ; ONE MORE IN WORD BUFFER + 172A E6C0 INC SOURCE ; POINT TO NEXT SOURCE CHAR + + 172C A5C3 READL3: LDA WRDLEN ; ANY CHARS IN WORD YET? + 172E F08F BEQ READL ; APPARENTLY NOT, SO LOOP BACK + + 1730 206217 JSR EFIND ; GET ENTRY ADDR INTO [ENTRY] + 1733 A5C3 LDA WRDLEN ; GET ACTUAL LNGTH OF WORD + 1735 A002 LDY #2 ; STORE IT IN "WORD LENGTH" SLOT + 1737 91C4 STA (ENTRY),Y ; OF THE CURRENT ENTRY + + 1739 205E1A JSR CONZST ; CONVERT ASCII IN [IN] TO Z-STRING + 173C 20AF17 JSR FINDW ; AND LOOK IT UP IN VOCABULARY + + 173F A001 LDY #1 + 1741 B184 LDA (ARG2),Y ; FETCH THE # WORDS READ + 1743 18 CLC + 1744 6901 ADC #1 ; INCREMENT IT + 1746 9184 STA (ARG2),Y ; AND UPDATE + + 1748 206217 JSR EFIND ; MAKE [ENTRY] POINT TO ENTRY + + 174B A000 LDY #0 + 174D 84C3 STY WRDLEN ; CLEAR # CHARS IN WORD + 174F A58D LDA VALUE+HI ; GET MSB OF VOCAB ENTRY ADDRESS + 1751 91C4 STA (ENTRY),Y ; AND STORE IN 1ST SLOT OF ENTRY + 1753 C8 INY + 1754 A58C LDA VALUE+LO ; ALSO STORE LSB IN 2ND SLOT + 1756 91C4 STA (ENTRY),Y + + 1758 A5C1 LDA RESULT ; UPDATE THE + 175A 18 CLC ; RESULT TABLE POINTER + 175B 6904 ADC #4 ; SO IT POINTS TO THE + 175D 85C1 STA RESULT ; NEXT ENTRY + + 175F 4CBF16 JMP READL ; AND LOOP BACK + + 1762 ; ----------------------------------- + 1762 ; FIND BASE ADDR OF RESULT ENTRY SLOT + 1762 ; ----------------------------------- + + 1762 A584 EFIND: LDA ARG2+LO ; LSB OF RESULT TABLE BASE + 1764 18 CLC + 1765 65C1 ADC RESULT ; AND CURRENT POINTER + 1767 85C4 STA ENTRY+LO ; SAVE IN [ENTRY] + 1769 A585 LDA ARG2+HI ; ALSO ADD MSB + 176B 6900 ADC #0 + 176D 85C5 STA ENTRY+HI + 176F 60 RTS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 62 +--- READ HANDLER --- + + + 1770 ; ---------- + 1770 ; FLUSH WORD + 1770 ; ---------- + + 1770 A5C2 FLUSHW: LDA LINLEN ; ANY CHARS LEFT IN LINE? + 1772 F011 BEQ FLEX ; NO, SCRAM + + 1774 A4C0 LDY SOURCE ; GET CURRENT CHAR POINTER + 1776 B182 LDA (ARG1),Y ; AND GRAB A CHAR + 1778 208617 JSR BREAK ; IS IT A BREAK? + 177B B008 BCS FLEX ; EXIT IF SO + 177D C6C2 DEC LINLEN ; ELSE UPDATE CHAR COUNT + 177F E6C3 INC WRDLEN ; AND WORD-CHAR COUNT + 1781 E6C0 INC SOURCE ; AND CHAR POINTER + 1783 D0EB BNE FLUSHW ; AND LOOP BACK (ALWAYS) + + 1785 60 FLEX: RTS + + 1786 ; --------------------------------- + 1786 ; IS CHAR IN [A] ANY TYPE OF BREAK? + 1786 ; --------------------------------- + + 1786 209D17 BREAK: JSR SIB ; CHECK FOR A SIB FIRST + 1789 B022 BCS FBRK ; EXIT NOW IF MATCHED + + 178B ; ELSE FALL THROUGH ... + + 178B ; -------------------------------- + 178B ; IS CHAR IN [A] A "NORMAL" BREAK? + 178B ; -------------------------------- + + 178B A205 NORM: LDX #NBRKS-1 ; NUMBER OF "NORMAL" BREAKS + 178D DD9717 NBL: CMP BRKTBL,X ; MATCHED? + 1790 F01B BEQ FBRK ; YES, EXIT + 1792 CA DEX + 1793 10F8 BPL NBL ; NO, KEEP LOOKING + 1795 18 CLC ; NO MATCH, CLEAR CARRY + 1796 60 RTS ; AND RETURN + + 1797 ; ------------------ + 1797 ; NORMAL BREAK CHARS + 1797 ; ------------------ + + 1797 213F2C2E BRKTBL: DB "!?,." ; IN ORDER OF + 179B 0D DB $0D ; ASCENDING FREQUENCY + 179C 20 DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED + + 0006 NBRKS EQU $-BRKTBL ; # NORMAL BREAKS + + 179D ; --------------------- + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 63 +--- READ HANDLER --- + + 179D ; IS CHAR IN [A] A SIB? + 179D ; --------------------- + + 179D AA SIB: TAX ; SAVE TEST CHAR + 179E A000 LDY #0 ; 1ST BYTE IN VOCAB TABLE + 17A0 B1AE LDA (VOCAB),Y ; HAS # SIBS + 17A2 A8 TAY ; USE AS AN INDEX + 17A3 8A TXA ; RESTORE TEST CHAR + 17A4 D1AE SBL: CMP (VOCAB),Y ; MATCHED? + 17A6 F005 BEQ FBRK ; YES, REPORT IT + 17A8 88 DEY + 17A9 D0F9 BNE SBL ; ELSE KEEP LOOPING + 17AB 18 CLC ; NO MATCH, SO + 17AC 60 RTS ; EXIT WITH CARRY CLEAR + + 17AD 38 FBRK: SEC ; EXIT WITH CARRY SET + 17AE 60 RTS ; IF MATCHED WITH A BREAK CHAR + + 17AF ; ----------------- + 17AF ; VOCABULARY SEARCH + 17AF ; ----------------- + + 17AF ; ENTRY: 4-BYTE TARGET Z-WORD IN [OUT] + 17AF ; EXIT: ABS ENTRY ADDRESS IN [VALUE] IF FOUND; + 17AF ; OTHERWISE [VALUE] = 0 + + 17AF A000 FINDW: LDY #0 ; GET # SIBS + 17B1 B1AE LDA (VOCAB),Y ; IN VOCAB TABLE + 17B3 18 CLC ; INCREMENT IT + 17B4 6901 ADC #1 ; FOR PROPER ALIGNMENT + 17B6 65AE ADC VOCAB+LO ; NOW ADD THE BASE ADDR OF THE TABLE + 17B8 858C STA VALUE+LO ; TO GET THE ACTUAL BASE ADDR + 17BA A5AF LDA VOCAB+HI ; OF THE VOCAB ENTRIES + 17BC 6900 ADC #0 ; WHICH IS SAVED + 17BE 858D STA VALUE+HI ; IN [VALUE] + + 17C0 B18C LDA (VALUE),Y ; GET # BYTES PER ENTRY ([Y] = 0) + 17C2 85C8 STA ESIZE ; SAVE IT HERE + + 17C4 20D40F JSR INCVAL ; POINT TO NEXT BYTE + 17C7 B18C LDA (VALUE),Y ; GET # ENTRIES IN TABLE (MSB) + 17C9 85C7 STA NENTS+HI ; AND STUFF IT IN [NENTS] + + 17CB 20D40F JSR INCVAL ; NEXT BYTE + 17CE B18C LDA (VALUE),Y ; DON'T FORGET THE LSB! + 17D0 85C6 STA NENTS+LO + + 17D2 20D40F JSR INCVAL ; [VALUE] NOW POINTS TO 1ST ENTRY + + 17D5 ; BEGIN THE SEARCH! + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS PAGE 64 +--- READ HANDLER --- + + 17D5 A000 FWL1: LDY #0 + 17D7 B18C LDA (VALUE),Y ; GET 1ST BYTE OF ENTRY + 17D9 C5BA CMP OUT ; MATCHED 1ST BYTE OF TARGET? + 17DB D015 BNE WNEXT ; NO, SKIP TO NEXT WORD + + 17DD C8 INY + 17DE B18C LDA (VALUE),Y + 17E0 C5BB CMP OUT+1 ; 2ND BYTE MATCHED? + 17E2 D00E BNE WNEXT ; NOPE + + 17E4 C8 INY + 17E5 B18C LDA (VALUE),Y + 17E7 C5BC CMP OUT+2 ; 3RD BYTE? + 17E9 D007 BNE WNEXT ; SORRY ... + + 17EB C8 INY + 17EC B18C LDA (VALUE),Y + 17EE C5BD CMP OUT+3 ; LAST BYTE + 17F0 F01F BEQ FWSUCC ; FOUND IT! + + 17F2 A5C8 WNEXT: LDA ESIZE ; GET ENTRY SIZE + 17F4 18 CLC ; AND ADD IT TO ENTRY ADDRESS + 17F5 658C ADC VALUE+LO ; TO MAKE [VALUE] + 17F7 858C STA VALUE+LO ; POINT TO THE NEXT ENTRY + 17F9 9002 BCC WNX + 17FB E68D INC VALUE+HI + + 17FD A5C6 WNX: LDA NENTS+LO ; DECREMENT THE + 17FF 38 SEC ; ENTRY COUNTER + 1800 E901 SBC #1 + 1802 85C6 STA NENTS+LO + 1804 B002 BCS WNX1 + 1806 C6C7 DEC NENTS+HI + + 1808 05C7 WNX1: ORA NENTS+HI ; KEEP SEARCHING + 180A D0C9 BNE FWL1 ; UNTIL COUNT IS ZERO + + 180C 858C STA VALUE+LO + 180E 858D STA VALUE+HI + 1810 60 RTS ; THEN RETURN WITH [VALUE] = 0 + + 1811 ; ENTRY MATCHED! + + 1811 A58D FWSUCC: LDA VALUE+HI ; CONVERT ABSOLUTE ENTRY ADDRESS + 1813 38 SEC ; IN [VALUE] + 1814 E5A3 SBC ZCODE ; TO RELATIVE Z-ADDRESS + 1816 858D STA VALUE+HI ; LSB NEEDN'T CHANGE + 1818 60 RTS + + END + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 65 +--- READ HANDLER --- + + INCLUD PAGING.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 66 +--- TIME-STAMP PAGING ROUTINE --- + + + 1819 ; ------------------------- + 1819 ; FETCH NEXT BYTE OF Z-CODE + 1819 ; ------------------------- + + 1819 ; EXIT: BYTE AT [ZPC] IN [A] & [Y]; FLAGS SET + + 1819 A599 NEXTPC: LDA ZPCFLG ; IS [ZPCPNT] VALID? + 181B D01E BNE NPC2 ; YES, GET THE BYTE + + 181D ; Z-PAGE HAS CHANGED! + + 181D A597 LDA ZPCM ; GET TOP + 181F A498 LDY ZPCH ; 9 BITS OF [ZPC] + 1821 D008 BNE NPC0 ; SWAP PAGE IF TOP BIT IS SET + + 1823 C5A4 CMP ZPURE ; IS THIS PAGE PRELOADED? + 1825 B004 BCS NPC0 ; NO, SWAP IT IN + + 1827 65A3 ADC ZCODE ; ELSE MAKE IT ABSOLUTE + 1829 D007 BNE NPC1 ; AND GIVE IT TO [ZPCPNT] + + 182B A200 NPC0: LDX #0 + 182D 869F STX MPCFLG ; INVALIDATE [MPC] + 182F 208518 JSR PAGE ; AND GET ABS PAGE ADDR INTO [A] + + 1832 859B NPC1: STA ZPCPNT+HI ; SET ABS PAGE ADDRESS + 1834 A2FF LDX #$FF + 1836 8699 STX ZPCFLG ; VALIDATE [ZPCPNT] + 1838 E8 INX ; = 0 + 1839 869A STX ZPCPNT+LO ; CLEAR LSB OF POINTER + + 183B A496 NPC2: LDY ZPCL ; FETCH PAGE INDEX + 183D B19A LDA (ZPCPNT),Y ; GET Z-BYTE + + 183F E696 INC ZPCL ; END OF PAGE YET? + 1841 D00A BNE NPC3 ; NO, EXIT + + 1843 A000 LDY #0 + 1845 8499 STY ZPCFLG ; ELSE INVALIDATE [ZPCPNT] + + 1847 E697 INC ZPCM ; POINT [ZPC] TO + 1849 D002 BNE NPC3 ; THE NEXT + 184B E698 INC ZPCH ; Z-PAGE + + 184D A8 NPC3: TAY ; SET FLAGS + 184E 60 RTS ; AND RETURN + + 184F ; ------------------------------- + 184F ; GET NEXT BYTE OF VIRTUAL MEMORY + 184F ; ------------------------------- + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 67 +--- TIME-STAMP PAGING ROUTINE --- + + + 184F ; EXIT: BYTE AT [MPC] IN [A] & [Y]; FLAGS SET + + 184F A59F GETBYT: LDA MPCFLG ; IS [MPCPNT] VALID? + 1851 D01E BNE GTBT2 ; YES, GET THE BYTE + + 1853 ; Z-PAGE HAS CHANGED! + + 1853 A59D LDA MPCM ; GET TOP + 1855 A49E LDY MPCH ; 9 BITS OF [MPC] + 1857 D008 BNE GTBT0 ; SWAP PAGE IF TOP BIT IS SET + + 185A PATCH EQU $+1 ; PATCH POINT FOR "VERIFY" + + 1859 C5A4 CMP ZPURE ; IS THIS PAGE PRELOADED? + 185B B004 BCS GTBT0 ; NO, SWAP IT IN + + 185D 65A3 ADC ZCODE ; ELSE MAKE IT ABSOLUTE + 185F D007 BNE GTBT1 ; AND GIVE IT TO [MPCPNT] + + 1861 A200 GTBT0: LDX #0 + 1863 8699 STX ZPCFLG ; INVALIDATE [ZPC] + 1865 208518 JSR PAGE ; AND GET ABS PAGE ADDR INTO [A] + + 1868 85A1 GTBT1: STA MPCPNT+HI ; SET ABS PAGE ADDRESS + 186A A2FF LDX #$FF + 186C 869F STX MPCFLG ; VALIDATE [MPCPNT] + 186E E8 INX ; = 0 + 186F 86A0 STX MPCPNT+LO ; CLEAR LSB OF POINTER + + 1871 A49C GTBT2: LDY MPCL ; FETCH PAGE INDEX + 1873 B1A0 LDA (MPCPNT),Y ; GET Z-BYTE + + 1875 E69C INC MPCL ; END OF PAGE YET? + 1877 D00A BNE GTBT3 ; NO, EXIT + + 1879 A000 LDY #0 + 187B 849F STY MPCFLG ; ELSE INVALIDATE [MPCPNT] + + 187D E69D INC MPCM ; POINT [MPC] TO + 187F D002 BNE GTBT3 ; THE NEXT + 1881 E69E INC MPCH ; Z-PAGE + + 1883 A8 GTBT3: TAY ; SET FLAGS + 1884 60 RTS ; AND RETURN + + 1885 ; ------------------------ + 1885 ; LOCATE A SWAPABLE Z-PAGE + 1885 ; ------------------------ + + 1885 ; ENTRY: TARGET Z-PAGE IN [A/Y] (9 BITS) + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 68 +--- TIME-STAMP PAGING ROUTINE --- + + 1885 ; EXIT: ABSOLUTE PAGE IN [A] + + 1885 85A8 PAGE: STA TARGET+LO ; SAVE THE + 1887 84A9 STY TARGET+HI ; TARGET Z-PAGE HERE + + 1889 ; IS THIS Z-PAGE ALREADY PAGED IN? + + 1889 A200 LDX #0 + 188B 86A7 STX ZPAGE ; START AT BUFFER #0 + + 188D DD0007 PG1: CMP PTABL,X ; LSB MATCHED? + 1890 D008 BNE PG2 ; NO, TRY NEXT BUFFER + 1892 98 TYA ; ELSE CHECK + 1893 DD0008 CMP PTABH,X ; TOP BIT + 1896 F02B BEQ PG4 ; MATCHED! BUFFER IN [ZPAGE] + 1898 A5A8 LDA TARGET+LO ; ELSE RESTORE LSB + 189A E6A7 PG2: INC ZPAGE ; UPDATE TALLY + 189C E8 INX + 189D E4A6 CPX PMAX ; OUT OF BUFFERS YET? + 189F 90EC BCC PG1 ; NO, KEEP SEARCHING + + 18A1 ; SWAP IN THE TARGET PAGE + + 18A1 20FC18 PG3: JSR EARLY ; GET EARLIEST PAGE + 18A4 A6AB LDX SWAP ; INTO [SWAP] & [X] + 18A6 86A7 STX ZPAGE ; SAVE FOR LATER + + 18A8 A5A8 LDA TARGET+LO ; ASSIGN THE TARGET PAGE + 18AA 9D0007 STA PTABL,X ; TO THE EARLIEST BUFFER + 18AD 85EB STA DBLOCK+LO ; ALSO GIVE IT TO ZDOS + + 18AF A5A9 LDA TARGET+HI ; SAME FOR TOP BIT + 18B1 2901 AND #%00000001 ; USE ONLY BIT 0 + 18B3 9D0008 STA PTABH,X + 18B6 85EC STA DBLOCK+HI + + 18B8 8A TXA + 18B9 18 CLC + 18BA 65A5 ADC PAGE0 ; CALC ABS ADDR OF BUFFER + 18BC 85EE STA DBUFF+HI ; GIVE IT TO ZDOS + + 18BE 203325 JSR GETDSK ; SWAP IN THE NEW PAGE + 18C1 B034 BCS DSKERR ; ERROR IF CARRY SET + + 18C3 ; UPDATE THE TIMESTAMP + + 18C3 A4A7 PG4: LDY ZPAGE ; GET THE BUFFER INDEX + 18C5 B90009 LDA LRUMAP,Y ; GET THIS BUFFER'S STAMP + 18C8 C5AA CMP STAMP ; SAME AS CURRENT STAMP? + 18CA F025 BEQ PG8 ; YES, EXIT + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 69 +--- TIME-STAMP PAGING ROUTINE --- + + 18CC E6AA INC STAMP ; UPDATE STAMP + 18CE D01C BNE PG7 ; CONTINUE IF NO OVERFLOW + + 18D0 ; HANDLE STAMP OVERFLOW + + 18D0 20FC18 JSR EARLY ; GET EARLIEST STAMP INTO [LRU] + + 18D3 A200 LDX #0 ; INIT INDEX + 18D5 BD0009 PG5: LDA LRUMAP,X ; GET A STAMP READING + 18D8 F006 BEQ PG6 ; EXIT IF ALREADY ZERO + 18DA 38 SEC ; ELSE SUBTRACT OFF + 18DB E5A2 SBC LRU ; THE EARLIEST TIMESTAMP + 18DD 9D0009 STA LRUMAP,X ; AND REPLACE THE STAMP + 18E0 E8 PG6: INX + 18E1 E4A6 CPX PMAX ; END OF SWAPPING SPACE? + 18E3 90F0 BCC PG5 ; LOOP TILL ALL STAMPS FIXED + + 18E5 A900 LDA #0 ; TURN BACK THE CLOCK + 18E7 38 SEC ; TO REFLECT NEW + 18E8 E5A2 SBC LRU ; STAMP READING + 18EA 85AA STA STAMP + + 18EC A5AA PG7: LDA STAMP ; FETCH STAMP + 18EE 990009 STA LRUMAP,Y ; STAMP TARGET PAGE WITH IT + + 18F1 A5A7 PG8: LDA ZPAGE ; GET BUFFER INDEX + 18F3 18 CLC ; MAKE IT + 18F4 65A5 ADC PAGE0 ; ABSOLUTE + 18F6 60 RTS ; AND RETURN IT IN [A] + + 18F7 ; *** ERROR #14: DRIVE ACCESS *** + + 18F7 A90E DSKERR: LDA #14 + 18F9 4CF91B JMP ZERROR + + 18FC ; ------------------------- + 18FC ; LOCATE EARLIEST TIMESTAMP + 18FC ; ------------------------- + + 18FC ; EXIT: [LRU] - EARLIEST TIMESTAMP + 18FC ; [SWAP] = INDEX TO EARLIEST BUFFER + + 18FC A200 EARLY: LDX #0 ; INIT INDEX + 18FE 86AB STX SWAP ; AND [SWAP] + 1900 AD0009 LDA LRUMAP ; GET STAMP OF BUFFER #0 + 1903 E8 INX ; START COMPARE WITH BUFFER #1 + 1904 DD0009 EAR0: CMP LRUMAP,X ; IS THIS STAMP EARLIER THAN [A]? + 1907 9005 BCC EAR1 ; NO, TRY NEXT STAMP + 1909 BD0009 LDA LRUMAP,X ; ELSE FETCH EARLIER ENTRY + 190C 86AB STX SWAP ; AND REMEMBER WHERE WE FOUND IT + 190E E8 EAR1: INX ; POINT TO NEXT STAMP + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 70 +--- TIME-STAMP PAGING ROUTINE --- + + 190F E4A6 CPX PMAX ; OUT OF STAMPS YET? + 1911 90F1 BCC EAR0 ; LOOP TILL EMPTY + + 1913 85A2 STA LRU ; SAVE EARLIEST STAMP HERE + 1915 60 RTS + + 1916 ; ------------------------- + 1916 ; POINT [MPC] TO V-ADDR [I] + 1916 ; ------------------------- + + 1916 A58E SETWRD: LDA I+LO + 1918 859C STA MPCL + 191A A58F LDA I+HI + 191C 859D STA MPCM + + 191E A900 LDA #0 + 1920 859E STA MPCH ; ZERO TOP BIT + 1922 859F STA MPCFLG ; INVALIDATE [MPC] + 1924 60 RTS + + 1925 ; ---------------------------- + 1925 ; GET Z-WORD AT [MPC] INTO [I] + 1925 ; ---------------------------- + + 1925 204F18 GETWRD: JSR GETBYT + 1928 858F STA I+HI + 192A 204F18 JSR GETBYT + 192D 858E STA I+LO + 192F 60 RTS + + END + INCLUD ZSTRING.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 71 +--- Z-STRING HANDLERS --- + + + 1930 ; ----------------------- + 1930 ; POINT TO ZSTRING IN [I] + 1930 ; ----------------------- + + 1930 A58E SETSTR: LDA I+LO ; WORD-ALIGN THE ADDRESS + 1932 0A ASL A + 1933 859C STA MPCL + 1935 A58F LDA I+HI + 1937 2A ROL A + 1938 859D STA MPCM + 193A A900 LDA #0 + 193C 859F STA MPCFLG ; [MPC] IS CHANGING! + 193E 2A ROL A + 193F 859E STA MPCH + + 1941 60 ZSTEX: RTS + + 1942 ; ----------------------- + 1942 ; PRINT Z-STRING AT [MPC] + 1942 ; ----------------------- + + 1942 A200 PZSTR: LDX #0 + 1944 86C9 STX PSET ; ASSUME PERMANENT CHARSET + 1946 86CD STX ZFLAG ; CLEAR BYTE FLAG + 1948 CA DEX ; = $FF + 1949 86CA STX TSET ; NO TEMPSET ACTIVE + + 194B 20161A PZTOP: JSR GETZCH ; GET A Z-CHAR + 194E B0F1 BCS ZSTEX ; END OF STRING IF CARRY IS SET + + 1950 85CB STA ZCHAR ; ELSE SAVE CHAR HERE + 1952 AA TAX ; SET FLAGS + 1953 F041 BEQ BLANK ; PRINT SPACE IF CHAR = 0 + + 1955 C904 CMP #4 ; IS THIS AN F-WORD? + 1957 905B BCC DOFREQ ; APPARENTLY SO + + 1959 C906 CMP #6 ; PERHAPS A SHIFT CODE? + 195B 903D BCC NEWSET ; YES, CHANGE CHARSETS + + 195D 200A1A JSR GETSET ; ELSE GET CHARSET + 1960 AA TAX ; SET FLAGS + 1961 D00B BNE SET1 ; SKIP IF NOT CHARSET #0 + + 1963 ; PRINT A LOWER-CASE CHAR (CHARSET #0) + + 1963 A95B LDA #$61-6 ; ASCII "a" MINUS Z-OFFSET + + 1965 18 TOASC: CLC + 1966 65CB ADC ZCHAR ; ADD Z-CHAR INDEX + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 72 +--- Z-STRING HANDLERS --- + + + 1968 20891C SHOVE: JSR COUT ; SHOW THE CHAR + 196B 4C4B19 JMP PZTOP ; AND GRAB NEXT CHAR + + 196E ; PRINT AN UPPER-CASE CHAR (CHARSET #1) + + 196E C901 SET1: CMP #1 ; MAKE SURE IT'S SET #1 + 1970 D004 BNE SET2 ; ELSE MUST BE SET #2 + + 1972 A93B LDA #$41-6 ; ASCII "A" MINUS Z-OFFSET + 1974 D0EF BNE TOASC ; SAME AS SET #0 + + 1976 ; PRINT FROM CHARSET #2 + + 1976 A5CB SET2: LDA ZCHAR ; RETRIEVE THE Z-CHAR + 1978 38 SEC + 1979 E906 SBC #6 ; ZERO-ALIGN IT + 197B F007 BEQ DIRECT ; IF ZERO, IT'S A "DIRECT" ASCII + + 197D AA TAX ; OTHERWISE USE CODE AS AN INDEX + 197E BD331B LDA CHRTBL,X ; INTO THE CHARSET TABLE + 1981 4C6819 JMP SHOVE ; AND PRINT THE CHAR + + 1984 ; DECODE A "DIRECT" ASCII CHAR + + 1984 20161A DIRECT: JSR GETZCH ; FETCH NEXT Z-CHAR + 1987 0A ASL A + 1988 0A ASL A + 1989 0A ASL A + 198A 0A ASL A + 198B 0A ASL A ; SHIFT INTO POSITION + 198C 85CB STA ZCHAR ; AND SAVE HERE + 198E 20161A JSR GETZCH ; GRAB YET ANOTHER Z-CHAR + 1991 05CB ORA ZCHAR ; SUPERIMPOSE THE 2ND BYTE + 1993 4C6819 JMP SHOVE ; AND PRINT THE RESULT + + 1996 ; PRINT A SPACE + + 1996 A920 BLANK: LDA #SPACE ; ASCII SPACE CHAR + 1998 D0CE BNE SHOVE + + 199A ; CHANGE CHARSET + + 199A 38 NEWSET: SEC ; CONVERT THE SHIFT CODE + 199B E903 SBC #3 ; TO 1 OR 2 + 199D A8 TAY + 199E 200A1A JSR GETSET ; IS MODE TEMPORARY? + 19A1 D005 BNE TOPERM ; YES, DO A PERMSHIFT + 19A3 84CA STY TSET ; ELSE JUST A TEMPSHIFT + 19A5 4C4B19 JMP PZTOP ; AND CONTINUE + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 73 +--- Z-STRING HANDLERS --- + + 19A8 84C9 TOPERM: STY PSET ; SET PERM CHARSET + 19AA C5C9 CMP PSET ; SAME AS BEFORE? + 19AC F09D BEQ PZTOP ; YES, CONTINUE + 19AE A900 LDA #0 + 19B0 85C9 STA PSET ; ELSE RESET CHARSET + 19B2 F097 BEQ PZTOP ; BEFORE LOOPING BACK + + 19B4 ; PRINT AN F-WORD + + 19B4 38 DOFREQ: SEC + 19B5 E901 SBC #1 ; ZERO-ALIGN THE CODE + 19B7 0A ASL A ; AND MULTIPLY TIMES 64 + 19B8 0A ASL A ; TO OBTAIN THE SEGMENT OFFSET + 19B9 0A ASL A ; INTO THE F-WORDS TABLE + 19BA 0A ASL A + 19BB 0A ASL A + 19BC 0A ASL A + 19BD 85CC STA OFFSET ; SAVE OFFSET FOR LATER + + 19BF 20161A JSR GETZCH ; NOW GET THE F-WORD POINTER + 19C2 0A ASL A ; WORD-ALIGN IT + 19C3 18 CLC ; AND + 19C4 65CC ADC OFFSET ; ADD THE SEGMENT OFFSET + 19C6 A8 TAY ; TO GET THE OFFSET OF THE F-WORD + 19C7 B1B0 LDA (FWORDS),Y ; FROM THE START OF THE F-WORDS TABLE + 19C9 858F STA I+HI ; SAVE MSB OF F-WORD ADDRESS + 19CB C8 INY + 19CC B1B0 LDA (FWORDS),Y ; ALSO SAVE LSB + 19CE 858E STA I+LO ; Z-ADDRESS OF F-WORD IS IN [I] + + 19D0 ; SAVE THE STATE OF CURRENT Z-STRING + + 19D0 A59E LDA MPCH + 19D2 48 PHA + 19D3 A59D LDA MPCM + 19D5 48 PHA + 19D6 A59C LDA MPCL + 19D8 48 PHA + 19D9 A5C9 LDA PSET + 19DB 48 PHA + 19DC A5CD LDA ZFLAG + 19DE 48 PHA + 19DF A5CF LDA ZWORD+HI + 19E1 48 PHA + 19E2 A5CE LDA ZWORD+LO + 19E4 48 PHA + + 19E5 203019 JSR SETSTR ; PRINT THE Z-STRING + 19E8 204219 JSR PZSTR ; IN [I] + + 19EB ; RESTORE OLD Z-STRING + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 74 +--- Z-STRING HANDLERS --- + + + 19EB 68 PLA + 19EC 85CE STA ZWORD+LO + 19EE 68 PLA + 19EF 85CF STA ZWORD+HI + 19F1 68 PLA + 19F2 85CD STA ZFLAG + 19F4 68 PLA + 19F5 85C9 STA PSET + 19F7 68 PLA + 19F8 859C STA MPCL + 19FA 68 PLA + 19FB 859D STA MPCM + 19FD 68 PLA + 19FE 859E STA MPCH + + 1A00 A2FF LDX #$FF + 1A02 86CA STX TSET ; DISABLE TEMP CHARSET + 1A04 E8 INX ; = 0 + 1A05 869F STX MPCFLG ; [MPC] HAS CHANGED + 1A07 4C4B19 JMP PZTOP ; CONTINUE INNOCENTLY + + 1A0A ; ---------------------- + 1A0A ; RETURN CURRENT CHARSET + 1A0A ; ---------------------- + + 1A0A A5CA GETSET: LDA TSET + 1A0C 1003 BPL GS + 1A0E A5C9 LDA PSET + 1A10 60 RTS + + 1A11 A0FF GS: LDY #$FF + 1A13 84CA STY TSET + 1A15 60 RTS + + 1A16 ; ----------------- + 1A16 ; FETCH NEXT Z-CHAR + 1A16 ; ----------------- + + 1A16 A5CD GETZCH: LDA ZFLAG ; WHICH BYTE IS THIS? + 1A18 1002 BPL GTZ0 ; $FF = LAST + 1A1A 38 SEC ; SET CARRY TO INDICATE + 1A1B 60 RTS ; NO MORE CHARS + + 1A1C D013 GTZ0: BNE GETZ1 ; NOT FIRST CHAR, EITHER + + 1A1E ; GET A Z-WORD INTO [ZWORD], RETURN 1ST CHAR IN TRIPLET + + 1A1E E6CD INC ZFLAG ; UPDATE CHAR COUNT + + 1A20 204F18 JSR GETBYT ; GET TRIPLET AT [MPC] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 75 +--- Z-STRING HANDLERS --- + + 1A23 85CF STA ZWORD+HI ; INTO [ZWORD] + 1A25 204F18 JSR GETBYT + 1A28 85CE STA ZWORD+LO + + 1A2A A5CF LDA ZWORD+HI + 1A2C 4A LSR A + 1A2D 4A LSR A ; SHIFT 1ST CHAR INTO PLACE + 1A2E 4C5A1A JMP GTEXIT ; AND RETURN IT + + 1A31 38 GETZ1: SEC + 1A32 E901 SBC #1 + 1A34 D016 BNE GETZ2 ; LAST CHAR IN TRIPLET IF ZERO + 1A36 A902 LDA #2 ; ELSE + 1A38 85CD STA ZFLAG ; RESET CHAR INDEX + + 1A3A A5CE LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET + 1A3C 858E STA I+LO ; MOVE HERE FOR SHIFTING + 1A3E A5CF LDA ZWORD+HI ; GET TOP HALF + + 1A40 068E ASL I+LO ; SHIFT THE TOP 3 BITS OF LOWER HALF + 1A42 2A ROL A ; INTO THE BOTTOM OF THE TOP HALF + 1A43 068E ASL I+LO + 1A45 2A ROL A + 1A46 068E ASL I+LO + 1A48 2A ROL A + 1A49 4C5A1A JMP GTEXIT + + 1A4C A900 GETZ2: LDA #0 ; SET FLAG TO INDICATE + 1A4E 85CD STA ZFLAG ; END OF TRIPLET + + 1A50 A5CF LDA ZWORD+HI ; TEST TOP HALF OF TRIPLET + 1A52 1004 BPL GETZ3 ; CONTINUE IF NOT END OF STRING + 1A54 A9FF LDA #$FF ; ELSE + 1A56 85CD STA ZFLAG ; INDICATE LAST TRIPLET IN STRING + + 1A58 A5CE GETZ3: LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET + + 1A5A 291F GTEXIT: AND #%00011111 ; MASK OUT GARBAGE BITS + 1A5C 18 CLC + 1A5D 60 RTS + + 1A5E ; --------------------------------- + 1A5E ; CONVERT [IN] TO Z-STRING IN [OUT] + 1A5E ; --------------------------------- + + 1A5E A905 CONZST: LDA #$05 ; FILL OUTPUT BUFFER + 1A60 AA TAX ; WITH PAD CHARS ($05) + 1A61 95BA CZSL: STA OUT,X + 1A63 CA DEX + 1A64 10FB BPL CZSL + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 76 +--- Z-STRING HANDLERS --- + + 1A66 A906 LDA #6 ; INIT + 1A68 85D0 STA CONCNT ; CHAR COUNT + + 1A6A A900 LDA #0 ; CLEAR + 1A6C 85D1 STA CONIN ; SOURCE AND + 1A6E 85D2 STA CONOUT ; OUTPUT INDEXES + + 1A70 A6D1 CONTOP: LDX CONIN ; FETCH SOURCE INDEX + 1A72 E6D1 INC CONIN ; AND UPDATE + 1A74 B5B4 LDA IN,X ; GRAB AN ASCII CHAR + 1A76 85CB STA ZCHAR ; SAVE IT HERE + 1A78 D004 BNE NEXTZ ; CONTINUE IF CHAR WAS NZ + + 1A7A A905 LDA #5 ; ELSE SHIP OUT + 1A7C D02C BNE CSHIP ; A PAD CHAR + + 1A7E A5CB NEXTZ: LDA ZCHAR + 1A80 20F41A JSR SAYSET ; WHICH CHARSET TO USE? + 1A83 F020 BEQ CSET0 ; LOWER-CASE IF ZERO + + 1A85 18 CLC ; ELSE DO A TEMP-SHIFT + 1A86 6903 ADC #3 ; 4 = CHARSET 1, 5 = CHARSET 2 + 1A88 A6D2 LDX CONOUT ; FETCH OUTPUT INDEX + 1A8A 95BA STA OUT,X ; SEND THE SHIFT CHAR + + 1A8C E6D2 INC CONOUT ; UPDATE INDEX + 1A8E C6D0 DEC CONCNT ; AND CHAR COUNT + 1A90 D003 BNE CTEST ; IF OUT OF CHARS + 1A92 4C0D1B JMP ZCRUSH ; CRUSH 'EM! + + 1A95 A5CB CTEST: LDA ZCHAR ; TEST CHAR AGAIN + 1A97 20F41A JSR SAYSET + 1A9A C902 CMP #2 + 1A9C F019 BEQ CSET2 ; CHARSET #2 + + 1A9E ; HANDLE CHARSET #1 (UPPER CASE ALPHA) + + 1A9E A5CB LDA ZCHAR + 1AA0 38 SEC + 1AA1 E93B SBC #$41-6 ; CONVERT TO Z-CHAR + 1AA3 1005 BPL CSHIP ; AND SEND TO OUTPUT + + 1AA5 ; HANDLE CHARSET #0 (LOWER CASE ALPHA) + + 1AA5 A5CB CSET0: LDA ZCHAR + 1AA7 38 SEC + 1AA8 E95B SBC #$61-6 ; CONVERT TO Z-CHAR + + 1AAA ; SHIP Z-CHAR TO OUTPUT BUFFER + + 1AAA A6D2 CSHIP: LDX CONOUT ; FETCH OUTPUT INDEX + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 77 +--- Z-STRING HANDLERS --- + + 1AAC 95BA STA OUT,X + + 1AAE E6D2 INC CONOUT ; UPDATE INDEX + 1AB0 C6D0 DEC CONCNT ; DONE 6 CHARS YET? + 1AB2 D0BC BNE CONTOP ; NO, LOOP BACK + 1AB4 4C0D1B JMP ZCRUSH ; ELSE CRUSH + + 1AB7 ; HANDLE CHARSET #2 (MISCELLANEOUS) + + 1AB7 A5CB CSET2: LDA ZCHAR ; GRAB CHAR + 1AB9 20E41A JSR CTABLE ; IS IT IN CHARSET #3 TABLE? + 1ABC D0EC BNE CSHIP ; YES, SEND IT TO OUTPUT + + 1ABE ; SEND A "DIRECT" ASCII CHAR + + 1ABE A906 LDA #6 ; ASCII ALERT! + 1AC0 A6D2 LDX CONOUT + 1AC2 95BA STA OUT,X + + 1AC4 E6D2 INC CONOUT ; UPDATE INDEX + 1AC6 C6D0 DEC CONCNT ; AND CHAR COUNT + 1AC8 F043 BEQ ZCRUSH ; BUFFER FULL! + + 1ACA ; SEND 1ST HALF OF "DIRECT" + + 1ACA A5CB LDA ZCHAR + 1ACC 4A LSR A + 1ACD 4A LSR A + 1ACE 4A LSR A + 1ACF 4A LSR A + 1AD0 4A LSR A + 1AD1 2903 AND #%00000011 ; MASK GARBAGE + 1AD3 A6D2 LDX CONOUT + 1AD5 95BA STA OUT,X + + 1AD7 E6D2 INC CONOUT + 1AD9 C6D0 DEC CONCNT + 1ADB F030 BEQ ZCRUSH ; BUFFER FULL! + + 1ADD ; SEND 2ND HALF OF "DIRECT" + + 1ADD A5CB LDA ZCHAR ; GET CHAR YET AGAIN + 1ADF 291F AND #%00011111 ; MASK JUNK + 1AE1 4CAA1A JMP CSHIP ; AND SHIP IT OUT + + 1AE4 ; --------------------- + 1AE4 ; IS [A] IN CHARSET #3? + 1AE4 ; --------------------- + + 1AE4 ; EXIT: [A] = CHAR CODE IF FOUND, Z-FLAG CLEARED + 1AE4 ; Z-FLAG SET IF NOT FOUND + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 78 +--- Z-STRING HANDLERS --- + + + 1AE4 A219 CTABLE: LDX #25 + 1AE6 DD331B CNL: CMP CHRTBL,X + 1AE9 F004 BEQ CNOK + 1AEB CA DEX + 1AEC D0F8 BNE CNL + 1AEE 60 RTS ; Z-FLAG SET IF NO MATCH + + 1AEF 8A CNOK: TXA ; CHAR CODE IS INDEX + 1AF0 18 CLC + 1AF1 6906 ADC #6 ; PLUS 6 + 1AF3 60 RTS + + 1AF4 ; ----------------------------- + 1AF4 ; RETURN CHARSET OF CHAR IN [A] + 1AF4 ; ----------------------------- + + 1AF4 C961 SAYSET: CMP #'a' + 1AF6 9007 BCC SAY1 + 1AF8 C97B CMP #'z'+1 + 1AFA B003 BCS SAY1 + 1AFC A900 LDA #0 ; IT'S CHARSET #0 + 1AFE 60 RTS + + 1AFF C941 SAY1: CMP #'A' + 1B01 9007 BCC SAY2 + 1B03 C95B CMP #'Z'+1 + 1B05 B003 BCS SAY2 + 1B07 A901 LDA #1 ; IT'S CHARSET #1 + 1B09 60 RTS + + 1B0A A902 SAY2: LDA #2 ; IT'S CHARSET #2 + 1B0C 60 RTS + + 1B0D ; ---------------------- + 1B0D ; CRUSH Z-CHARS IN [OUT] + 1B0D ; ---------------------- + + 1B0D A5BB ZCRUSH: LDA OUT+1 ; GET 2ND Z-CHAR + 1B0F 0A ASL A ; SHIFT BITS INTO POSITION + 1B10 0A ASL A + 1B11 0A ASL A + 1B12 0A ASL A + 1B13 26BA ROL OUT ; ALONG WITH 1ST Z-CHAR + 1B15 0A ASL A + 1B16 26BA ROL OUT + 1B18 05BC ORA OUT+2 ; SUPERIMPOSE 3RD Z-CHAR + 1B1A 85BB STA OUT+1 + + 1B1C A5BE LDA OUT+4 ; GET 5TH Z-CHAR + 1B1E 0A ASL A ; SHIFT BITS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 79 +--- Z-STRING HANDLERS --- + + 1B1F 0A ASL A + 1B20 0A ASL A + 1B21 0A ASL A + 1B22 26BD ROL OUT+3 ; ALONG WITH 4TH Z-CHAR + 1B24 0A ASL A + 1B25 26BD ROL OUT+3 + 1B27 05BF ORA OUT+5 ; SUPERIMPOSE 6TH Z-CHAR + 1B29 AA TAX ; SAVE HERE + 1B2A A5BD LDA OUT+3 ; GRAB 4TH Z-CHAR + 1B2C 0980 ORA #%10000000 ; SET HIGH BIT + 1B2E 85BC STA OUT+2 ; MOVE CRUSHED Z-WORD + 1B30 86BD STX OUT+3 ; INTO PLACE + 1B32 60 RTS + + 1B33 ; ----------------------- + 1B33 ; CHARSET #2 DECODE TABLE + 1B33 ; ----------------------- + + 1B33 00 CHRTBL: DB 0 ; DUMMY BYTE FOR "DIRECT" + 1B34 0D DB $0D ; EOL + 1B35 30313233 DB "0123456789.,!?_#" + 1B45 27 DB $27 ; SINGLE QUOTE + 1B46 22 DB $22 ; DOUBLE QUOTE + 1B47 2F5C2D3A DB "/\-:()" + + END + INCLUD OBJECTS.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 80 +--- OBJECT & PROPERTY HANDLERS --- + + + 1B4D ; ---------------------------------- + 1B4D ; GET ABSOLUTE ADDRESS OF OBJECT [A] + 1B4D ; ---------------------------------- + + 1B4D ; EXIT: ADDRESS IN [I] + + 1B4D 858E OBJLOC: STA I+LO ; SAVE LSB FOR ADDING + + 1B4F A200 LDX #0 ; CLEAR MSB + 1B51 868F STX I+HI ; FOR SHIFTING + + 1B53 0A ASL A ; MULTIPLY BY 8 + 1B54 268F ROL I+HI + 1B56 0A ASL A + 1B57 268F ROL I+HI + 1B59 0A ASL A + 1B5A 268F ROL I+HI + + 1B5C 18 CLC ; ADD TO ITSELF + 1B5D 658E ADC I+LO ; TO GET TIMES 9 + 1B5F 9002 BCC OBJ1 + 1B61 E68F INC I+HI + + 1B63 18 OBJ1: CLC + 1B64 6935 ADC #53 ; NOW ADD 53 + 1B66 9002 BCC OBJ2 ; (THE OBJECT TABLE OFFSET) + 1B68 E68F INC I+HI + + 1B6A 18 OBJ2: CLC ; NEXT ADD THE ABS ADDR + 1B6B 65B2 ADC OBJTAB+LO ; OF THE OBJECT TABLE + 1B6D 858E STA I+LO + + 1B6F A58F LDA I+HI + 1B71 65B3 ADC OBJTAB+HI + 1B73 858F STA I+HI + 1B75 60 RTS + + 1B76 ; ----------------------------- + 1B76 ; GET ADDRESS OF PROPERTY TABLE + 1B76 ; ----------------------------- + + 1B76 ; EXIT: [I] HAS ABSOLUTE ADDR OF PROPERTY TABLE + 1B76 ; [Y] HAS OFFSET TO START OF PROP IDS + + 1B76 A582 PROPB: LDA ARG1+LO + 1B78 204D1B JSR OBJLOC + 1B7B A007 LDY #7 + 1B7D B18E LDA (I),Y ; GET MSB OF P-TABLE ADDRESS + 1B7F 18 CLC + 1B80 65A3 ADC ZCODE ; MAKE IT ABSOLUTE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 81 +--- OBJECT & PROPERTY HANDLERS --- + + 1B82 AA TAX ; AND SAVE HERE + 1B83 C8 INY + 1B84 B18E LDA (I),Y ; NOW GET LSB + 1B86 858E STA I+LO + 1B88 868F STX I+HI ; [I] NOW POINTS TO PROP TABLE + + 1B8A A000 LDY #0 + 1B8C B18E LDA (I),Y ; GET LENGTH OF SHORT DESC + 1B8E 0A ASL A ; WORD-ALIGN IT + 1B8F A8 TAY ; EXPECTED HERE + 1B90 C8 INY ; POINT JUST PAST THE DESCRIPTION + 1B91 60 RTS + + 1B92 ; ------------------- + 1B92 ; FETCH A PROPERTY ID + 1B92 ; ------------------- + + 1B92 ; ENTRY: LIKE "PROPB" EXIT + + 1B92 B18E PROPN: LDA (I),Y + 1B94 291F AND #%00011111 ; MASK OUT LENGTH BITS + 1B96 60 RTS + + 1B97 ; ------------------------------- + 1B97 ; FETCH # BYTES IN PROPERTY VALUE + 1B97 ; ------------------------------- + + 1B97 ; ENTRY: LIKE "PROPB" EXIT + + 1B97 B18E PROPL: LDA (I),Y + 1B99 4A LSR A ; LENGTH IS IN + 1B9A 4A LSR A ; BITS 7-5 + 1B9B 4A LSR A ; SO SHIFT INTO PLACE + 1B9C 4A LSR A + 1B9D 4A LSR A + 1B9E 60 RTS + + 1B9F ; ---------------------- + 1B9F ; POINT TO NEXT PROPERTY + 1B9F ; ---------------------- + + 1B9F ; ENTRY: LIKE "PROPB" EXIT + + 1B9F 20971B PROPNX: JSR PROPL ; GET LENGTH OF CURRENT PROP + 1BA2 AA TAX ; SAVE HERE + + 1BA3 C8 PPX: INY ; LOOP UNTIL + 1BA4 CA DEX ; [Y] POINTS TO + 1BA5 10FC BPL PPX ; START OF NEXT PROP + 1BA7 C8 INY ; CORRECT ALIGNMENT + 1BA8 60 RTS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 82 +--- OBJECT & PROPERTY HANDLERS --- + + + 1BA9 ; ---------------- + 1BA9 ; GET OBJECT FLAGS + 1BA9 ; ---------------- + + 1BA9 ; ENTRY: OBJECT # IN [ARG1], FLAG # IN [ARG2] + 1BA9 ; EXIT: FLAG WORD IN [K], BIT ID IN [J], + 1BA9 ; FLAG WORD ADDRESS IN [I] + + 1BA9 A582 FLAGSU: LDA ARG1+LO + 1BAB 204D1B JSR OBJLOC ; GET OBJECT ADDR IN [I] + + 1BAE A584 LDA ARG2+LO ; LOOK AT FLAG ID + 1BB0 C910 CMP #$10 ; FIRST SET OF FLAGS? + 1BB2 900F BCC FLS1 ; YES, ADDR IN [I] IS CORRECT + + 1BB4 E910 SBC #16 ; ELSE ZERO-ALIGN FLAG INDEX + 1BB6 AA TAX ; SAVE IT HERE + + 1BB7 A58E LDA I+LO ; ADD 2 TO ADDRESS IN [I] + 1BB9 18 CLC ; TO POINT TO ADDRESS OF + 1BBA 6902 ADC #2 ; 2ND FLAG WORD + 1BBC 858E STA I+LO + 1BBE 9002 BCC FLS0 + 1BC0 E68F INC I+HI + + 1BC2 8A FLS0: TXA ; RESTORE INDEX + + 1BC3 8592 FLS1: STA K+LO ; SAVE FLAG ID HERE + + 1BC5 A201 LDX #1 ; INIT THE + 1BC7 8690 STX J+LO ; FLAG WORD TO + 1BC9 CA DEX ; $0001 + 1BCA 8691 STX J+HI + + 1BCC A90F LDA #15 ; SUBTRACT THE BIT POSITION + 1BCE 38 SEC ; FROM 15 + 1BCF E592 SBC K+LO ; TO GET THE SHIFT LOOP + 1BD1 AA TAX ; INDEX + 1BD2 F007 BEQ FLS2 ; EXIT NOW IF NO SHIFT NEEDED + + 1BD4 0690 FLSL: ASL J+LO ; SHIFT THE BIT + 1BD6 2691 ROL J+HI ; INTO POSITION + 1BD8 CA DEX + 1BD9 D0F9 BNE FLSL + + 1BDB A000 FLS2: LDY #0 ; MOVE THE FLAG WORD + 1BDD B18E LDA (I),Y ; INTO [J] + 1BDF 8593 STA K+HI ; FIRST THE MSB + 1BE1 C8 INY + 1BE2 B18E LDA (I),Y + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT PAGE 83 +--- OBJECT & PROPERTY HANDLERS --- + + 1BE4 8592 STA K+LO ; THEN THE LSB + 1BE6 60 RTS + + END + + INCLUD IO.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 84 +--- GAME I/O: ATARI --- + + + 1BE7 ; -------------- + 1BE7 ; INTERNAL ERROR + 1BE7 ; -------------- + + 1BE7 ; ENTRY: ERROR CODE IN [A] + + 1BE7 496E7465 ERRM: DB "Internal error " + 1BF6 30302E ENUMB: DB "00." + 0012 ERRML EQU $-ERRM + + 1BF9 A001 ZERROR: LDY #1 ; CONVERT ERROR BYTE IN [A] + + 1BFB A200 ZERR0: LDX #0 ; TO ASCII AT "ENUMB" + 1BFD C90A ZERR1: CMP #10 + 1BFF 9005 BCC ZERR2 + 1C01 E90A SBC #10 + 1C03 E8 INX + 1C04 D0F7 BNE ZERR1 + + 1C06 0930 ZERR2: ORA #'0' + 1C08 99F61B STA ENUMB,Y + 1C0B 8A TXA + 1C0C 88 DEY + 1C0D 10EC BPL ZERR0 + + 1C0F 20C71C JSR ZCRLF ; CLEAR LINE BUFFER + + 1C12 A900 LDA #0 + 1C14 85DF STA SCRIPT ; DISABLE SCRIPTING + + 1C16 A2E7 LDX #LOW ERRM + 1C18 A91B LDA #HIGH ERRM + 1C1A A012 LDY #ERRML + 1C1C 20C21F JSR DLINE + + 1C1F ; FALL THROUGH ... + + 1C1F ; ---- + 1C1F ; QUIT + 1C1F ; ---- + + 1C1F 20C71C ZQUIT: JSR ZCRLF + + 1C22 A231 LDX #LOW TORES + 1C24 A91C LDA #HIGH TORES + 1C26 A00D LDY #TORESL + 1C28 20C21F JSR DLINE ; "END OF STORY" + + 1C2B 20C71C JSR ZCRLF + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 85 +--- GAME I/O: ATARI --- + + 1C2E 4C2E1C FREEZE: JMP FREEZE + + 1C31 456E6420 TORES: DB "End of story." + 000D TORESL EQU $-TORES + + 1C3E ; ------- + 1C3E ; RESTART + 1C3E ; ------- + + 1C3E 207B23 ZSTART: JSR SIDE1 ; PROMPT FOR SIDE 1 + + 1C41 AD1126 LDA ZBEGIN+ZSCRIP+1 ; SAVE THE STATE OF + 1C44 2901 AND #%00000001 ; THE SCRIPT FLAG + 1C46 8DD81F STA SFLAG ; (BM 5/14/85) + + 1C49 4CAE0C JMP WARM ; AND DO A WARMSTART + + 1C4C ; -------------------- + 1C4C ; PRINT VERSION NUMBER + 1C4C ; -------------------- + + 1C4C 41746172 VERS: DB "Atari Version D" + 000F VERSL EQU $-VERS + + 1C5B 20C71C VERNUM: JSR ZCRLF ; FLUSH BUFFER + + 1C5E A24C LDX #LOW VERS + 1C60 A91C LDA #HIGH VERS + 1C62 A00F LDY #VERSL + 1C64 20C21F JSR DLINE ; "VERSION X" + + 1C67 4C7B23 JMP SIDE1 ; GET SIDE 1 & RETURN + + 1C6A ; -------------------------- + 1C6A ; RETURN TOP RAM PAGE IN [A] + 1C6A ; -------------------------- + + 1C6A A200 MEMTOP: LDX #0 + 1C6C 8E00B0 STX $B000 ; CLEAR THIS CELL + 1C6F AD00B0 LDA $B000 ; TEST IT + 1C72 D00B BNE NOT48K ; NOT 48K IF NZ + 1C74 CE00B0 DEC $B000 ; SET TO $FF + 1C77 AD00B0 LDA $B000 ; TEST AGAIN + 1C7A 1003 BPL NOT48K ; NOT 48K IF POSITIVE + 1C7C A9BB LDA #$BB ; ELSE RETURN 48K + 1C7E 60 RTS + + 1C7F 8A NOT48K: TXA ; RETURN 0 IN [A] + 1C80 60 RTS + + 1C81 ; -------------------------------- + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 86 +--- GAME I/O: ATARI --- + + 1C81 ; RETURN RANDOM BYTES IN [A] & [X] + 1C81 ; -------------------------------- + + 1C81 AD0AD2 RANDOM: LDA MRAND + 1C84 EA NOP + 1C85 AE0AD2 LDX MRAND + 1C88 60 RTS + + 1C89 ; ------------------- + 1C89 ; Z-PRINT A CHARACTER + 1C89 ; ------------------- + + 1C89 ; ENTRY: ASCII CHAR IN [A] + + 1C89 C90D COUT: CMP #$0D ; IF ASCII EOL, + 1C8B F03A BEQ ZCRLF ; DO IT! + 1C8D C920 CMP #SPACE ; IGNORE ALL OTHER + 1C8F 900B BCC CEX ; CONTROLS + + 1C91 A6DD LDX LENGTH ; ELSE GET LINE POINTER + 1C93 9D800A STA LBUFF,X ; ADD CHAR TO BUFFER + 1C96 E027 CPX #XSIZE ; END OF LINE? + 1C98 B003 BCS FLUSH ; YES, FLUSH THE LINE + 1C9A E6DD INC LENGTH ; ELSE UPDATE POINTER + + 1C9C 60 CEX: RTS + + 1C9D ; ------------------- + 1C9D ; FLUSH OUTPUT BUFFER + 1C9D ; ------------------- + + 1C9D ; ENTRY: LENGTH OF BUFFER IN [X] + + 1C9D A920 FLUSH: LDA #SPACE + + 1C9F DD800A FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR + 1CA2 F005 BEQ FL1 ; IN THE LINE + 1CA4 CA DEX + 1CA5 D0F8 BNE FL0 ; IF NONE FOUND, + 1CA7 A227 LDX #XSIZE ; FLUSH ENTIRE LINE + + 1CA9 86DE FL1: STX OLDLEN ; SAVE OLD LINE POS HERE + 1CAB 86DD STX LENGTH ; MAKE IT THE NEW LINE LENGTH + + 1CAD 20C71C JSR ZCRLF ; PRINT LINE UP TO LAST SPACE + + 1CB0 ; START NEW LINE WITH REMAINDER OF OLD + + 1CB0 A6DE LDX OLDLEN ; GET OLD LINE POS + 1CB2 A000 LDY #0 ; START NEW LINE AT BEGINNING + 1CB4 E8 FL2: INX + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 87 +--- GAME I/O: ATARI --- + + 1CB5 E027 CPX #XSIZE ; CONTINUE IF + 1CB7 9005 BCC FL3 ; INSIDE OR + 1CB9 F003 BEQ FL3 ; AT END OF LINE + 1CBB 84DD STY LENGTH ; ELSE SET NEW LINE LENGTH + 1CBD 60 RTS + + 1CBE BD800A FL3: LDA LBUFF,X ; GET CHAR FROM OLD LINE + 1CC1 99800A STA LBUFF,Y ; MOVE TO START OF NEW LINE + 1CC4 C8 INY ; UPDATE LENGTH OF NEW LINE + 1CC5 D0ED BNE FL2 + + 1CC7 ; --------------- + 1CC7 ; CARRIAGE RETURN + 1CC7 ; --------------- + + 1CC7 E6E0 ZCRLF: INC LINCNT ; NEW LINE GOING OUT + 1CC9 A5E0 LDA LINCNT ; IS IT TIME TO + 1CCB C5E1 CMP LMAX ; PRINT "MORE" YET? + 1CCD 9028 BCC CR1 ; NO, CONTINUE + + 1CCF ; SCREEN FULL; PRINT "MORE" + + 1CCF 20201D JSR ZUSL ; UPDATE STATUS LINE + + 1CD2 A900 LDA #0 + 1CD4 85E0 STA LINCNT ; RESET LINE COUNTER + + 1CD6 A205 LDX #5 ; POKE "[MORE]" INTO BOTTOM LEFT CORNER + 1CD8 BD1A1D ZCRMP: LDA MORE,X + 1CDB 9DD8BF STA SCREEN+920,X + 1CDE CA DEX + 1CDF 10F7 BPL ZCRMP + + 1CE1 A9FF LDA #$FF ; WAIT FOR ANY KEY + 1CE3 8DFC02 STA CH + 1CE6 ADFC02 ZCR0: LDA CH + 1CE9 C9FF CMP #$FF + 1CEB F0F9 BEQ ZCR0 + + 1CED A205 LDX #5 ; ERASE "[MORE]" + 1CEF A900 LDA #0 + 1CF1 9DD8BF ZCRME: STA SCREEN+920,X + 1CF4 CA DEX + 1CF5 10FA BPL ZCRME + + 1CF7 A6DD CR1: LDX LENGTH + 1CF9 A99B LDA #EOL ; INSTALL EOL AT + 1CFB 9D800A STA LBUFF,X ; END OF CURRENT LINE + 1CFE E6DD INC LENGTH ; UPDATE LINE LENGTH + + 1D00 A4DD LINOUT: LDY LENGTH ; IF BUFFER EMPTY, + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 88 +--- GAME I/O: ATARI --- + + 1D02 F015 BEQ LINEX ; DON'T PRINT ANYTHING + 1D04 84EA STY PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + + 1D06 A200 LDX #0 ; SEND CONTENTS OF [LBUFF] + 1D08 BD800A LOUT: LDA LBUFF,X ; TO SCREEN + 1D0B 20EB1E JSR CHAR + 1D0E E8 INX + 1D0F 88 DEY + 1D10 D0F6 BNE LOUT + + 1D12 20D91F JSR PPRINT ; PRINT [LBUFF] IF ENABLED + 1D15 A900 LDA #0 ; RESET LINE LENGTH + 1D17 85DD STA LENGTH ; TO ZERO + + 1D19 60 LINEX: RTS ; AND RETURN + + 1D1A BB MORE: DB 59+128 ; INVERSE "[MORE]" + 1D1B AD DB 45+128 ; IN ATARI SCREEN CODE + 1D1C AF DB 47+128 + 1D1D B2 DB 50+128 + 1D1E A5 DB 37+128 + 1D1F BD DB 61+128 + + 1D20 ; ---------------------- + 1D20 ; UPDATE THE STATUS LINE + 1D20 ; ---------------------- + + 1D20 A555 ZUSL: LDA COLCRS+LO ; SAVE THE + 1D22 48 PHA ; CURRENT + 1D23 A554 LDA ROWCRS ; CURSOR + 1D25 48 PHA ; POSITION + + 1D26 A5DD LDA LENGTH ; SAVE ALL + 1D28 48 PHA ; STRING-PRINTING + 1D29 A59E LDA MPCH ; VARIABLES + 1D2B 48 PHA + 1D2C A59D LDA MPCM + 1D2E 48 PHA + 1D2F A59C LDA MPCL + 1D31 48 PHA + 1D32 A5CA LDA TSET + 1D34 48 PHA + 1D35 A5C9 LDA PSET + 1D37 48 PHA + 1D38 A5CF LDA ZWORD+HI + 1D3A 48 PHA + 1D3B A5CE LDA ZWORD+LO + 1D3D 48 PHA + 1D3E A5CD LDA ZFLAG + 1D40 48 PHA + 1D41 A5DB LDA DIGITS + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 89 +--- GAME I/O: ATARI --- + + 1D43 48 PHA + + 1D44 A227 LDX #XSIZE + 1D46 BD800A USL0: LDA LBUFF,X ; MOVE CONTENTS OF [LBUFF] + 1D49 9D200A STA BUFSAV,X ; TO [BUFSAV] + 1D4C A920 LDA #SPACE ; CLEAR + 1D4E 9D800A STA LBUFF,X ; [LBUFF] WITH SPACES + 1D51 CA DEX + 1D52 10F2 BPL USL0 + + 1D54 A900 LDA #0 + 1D56 85DD STA LENGTH ; RESET LINE LENGTH + 1D58 85DF STA SCRIPT ; DISABLE SCRIPTING + 1D5A 8555 STA COLCRS+LO ; HOME THE + 1D5C 8554 STA ROWCRS ; CURSOR + + 1D5E ; PRINT ROOM DESCRIPTION + + 1D5E A910 LDA #16 ; GLOBAL VAR #16 (ROOM ID) + 1D60 20C10E JSR GETVRG ; GET IT INTO [VALUE] + 1D63 A58C LDA VALUE+LO + 1D65 20DF11 JSR PRNTDC ; PRINT SHORT ROOM DESCRIPTION + + 1D68 A917 LDA #23 ; MOVE LINE INDEX UP + 1D6A 85DD STA LENGTH ; TO TIME/SCORE POSITION + + 1D6C A920 LDA #SPACE ; TRUNCATE LONG DESCS + 1D6E 20891C JSR COUT ; WITH A SPACE + + 1D71 A911 LDA #17 ; GLOBAL VAR #17 (SCORE/HOURS) + 1D73 20C10E JSR GETVRG ; GET IT INTO [VALUE] + + 1D76 A5DC LDA TIMEFL ; GET MODE FLAG + 1D78 D032 BNE DOTIME ; USE TIME MODE IF NON-ZERO + + 1D7A ; PRINT "SCORE" + + 1D7A A953 LDA #'S' + 1D7C 20891C JSR COUT + 1D7F A963 LDA #'c' + 1D81 20891C JSR COUT + 1D84 A96F LDA #'o' + 1D86 20891C JSR COUT + 1D89 A972 LDA #'r' + 1D8B 20891C JSR COUT + 1D8E A965 LDA #'e' + 1D90 20891C JSR COUT + 1D93 A93A LDA #':' + 1D95 20891C JSR COUT + 1D98 A920 LDA #SPACE + 1D9A 20891C JSR COUT + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 90 +--- GAME I/O: ATARI --- + + + 1D9D A58C LDA VALUE+LO ; MOVE SCORE VALUE + 1D9F 85D3 STA QUOT+LO ; INTO [QUOT] + 1DA1 A58D LDA VALUE+HI ; FOR PRINTING + 1DA3 85D4 STA QUOT+HI + 1DA5 202E16 JSR NUMBER ; PRINT SCORE VALUE IN DECIMAL + + 1DA8 A92F LDA #'/' ; PRINT A SLASH + 1DAA D035 BNE MOVMIN ; BRANCH ALWAYS + + 1DAC ; PRINT "TIME" + + 1DAC A954 DOTIME: LDA #'T' + 1DAE 20891C JSR COUT + 1DB1 A969 LDA #'i' + 1DB3 20891C JSR COUT + 1DB6 A96D LDA #'m' + 1DB8 20891C JSR COUT + 1DBB A965 LDA #'e' + 1DBD 20891C JSR COUT + 1DC0 A93A LDA #':' + 1DC2 20891C JSR COUT + 1DC5 A920 LDA #SPACE + 1DC7 20891C JSR COUT + + 1DCA A58C LDA VALUE+LO ; 00 IS REALLY 24 + 1DCC D002 BNE DT0 + 1DCE A918 LDA #24 + 1DD0 C90D DT0: CMP #13 ; IS HOURS > 12, + 1DD2 9002 BCC DT1 + 1DD4 E90C SBC #12 ; CONVERT TO 1-12 + 1DD6 85D3 DT1: STA QUOT+LO ; MOVE FOR PRINTING + 1DD8 A900 LDA #0 + 1DDA 85D4 STA QUOT+HI ; CLEAR MSB + 1DDC 202E16 JSR NUMBER + + 1DDF A93A LDA #':' ; COLON + + 1DE1 20891C MOVMIN: JSR COUT ; PRINT SLASH OR COLON + + 1DE4 A912 LDA #18 ; GLOBAL VAR #18 (MOVES/MINUTES) + 1DE6 20C10E JSR GETVRG ; GET IT INTO [VALUE] + 1DE9 A58C LDA VALUE+LO ; MOVE TO [QUOT] + 1DEB 85D3 STA QUOT+LO ; FOR EVENTUAL PRINTING + 1DED A58D LDA VALUE+HI + 1DEF 85D4 STA QUOT+HI + + 1DF1 A5DC LDA TIMEFL ; WHICH MODE? + 1DF3 D006 BNE DOMINS ; TIME IF NZ + + 1DF5 ; PRINT NUMBER OF MOVES + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 91 +--- GAME I/O: ATARI --- + + + 1DF5 202E16 JSR NUMBER ; SHOW # MOVES + 1DF8 4C271E JMP STATEX ; ALL DONE + + 1DFB ; PRINT MINUTES + + 1DFB A58C DOMINS: LDA VALUE+LO ; CHECK MINUTES + 1DFD C90A CMP #10 ; IF MORE THAN TEN + 1DFF B005 BCS DOM0 ; CONTINUE + + 1E01 A930 LDA #'0' ; ELSE PRINT A + 1E03 20891C JSR COUT ; PADDING "0" FIRST + + 1E06 202E16 DOM0: JSR NUMBER ; SHOW MINUTES + + 1E09 A920 LDA #SPACE + 1E0B 20891C JSR COUT ; SEPARATE THINGS + + 1E0E A911 LDA #17 ; CHECK "HOURS" AGAIN + 1E10 20C10E JSR GETVRG + 1E13 A58C LDA VALUE+LO + 1E15 C90C CMP #12 ; PAST NOON? + 1E17 B004 BCS DOPM ; YES, PRINT "PM" + + 1E19 A961 LDA #'a' ; ELSE PRINT "AM" + 1E1B D002 BNE DOXM ; BRANCH ALWAYS + + 1E1D A970 DOPM: LDA #'p' + + 1E1F 20891C DOXM: JSR COUT + 1E22 A96D LDA #'m' + 1E24 20891C JSR COUT + + 1E27 ; STATUS LINE READY + + 1E27 A227 STATEX: LDX #XSIZE + 1E29 A980 LDA #$80 ; CLEAR THE + 1E2B 9D40BC STX0: STA SCREEN,X ; STATUS LINE! + 1E2E CA DEX + 1E2F D0FA BNE STX0 + 1E31 BD800A STX1: LDA LBUFF,X ; GET A CHAR FROM [LBUFF] + 1E34 0980 ORA #%10000000 ; CONVERT TO INVERSE VIDEO + 1E36 20EB1E JSR CHAR ; SEND TO SCREEN + 1E39 E8 INX ; LOOP TILL + 1E3A E4DD CPX LENGTH ; ALL CHARS SENT + 1E3C 90F3 BCC STX1 + + 1E3E A227 LDX #XSIZE ; RESTORE OLD [LBUFF] + 1E40 BD200A STX2: LDA BUFSAV,X + 1E43 9D800A STA LBUFF,X + 1E46 CA DEX + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 92 +--- GAME I/O: ATARI --- + + 1E47 10F7 BPL STX2 + + 1E49 68 PLA ; RESTORE ALL + 1E4A 85DB STA DIGITS ; SAVED VARIABLES + 1E4C 68 PLA + 1E4D 85CD STA ZFLAG + 1E4F 68 PLA + 1E50 85CE STA ZWORD+LO + 1E52 68 PLA + 1E53 85CF STA ZWORD+HI + 1E55 68 PLA + 1E56 85C9 STA PSET + 1E58 68 PLA + 1E59 85CA STA TSET + 1E5B 68 PLA + 1E5C 859C STA MPCL + 1E5E 68 PLA + 1E5F 859D STA MPCM + 1E61 68 PLA + 1E62 859E STA MPCH + 1E64 68 PLA + 1E65 85DD STA LENGTH + + 1E67 68 PLA ; RESTORE THE + 1E68 8554 STA ROWCRS ; CURSOR POSITION + 1E6A 68 PLA + 1E6B 8555 STA COLCRS+LO + + 1E6D A2FF LDX #$FF + 1E6F 86DF STX SCRIPT ; RE-ENABLE SCRIPTING + 1E71 E8 INX ; = 0 + 1E72 869F STX MPCFLG ; INVALIDATE [MPC] + 1E74 4CB120 JMP NEWLOG ; RESET THE LINE MAP & RETURN + + END + INCLUD MACHINE.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 93 +--- MACHINE-DEPENDENT I/O: ATARI --- + + + 1E77 ; ---------------------------- + 1E77 ; FETCH ASCII KEYCODE INTO [A] + 1E77 ; ---------------------------- + + 1E77 ; EXIT: ASCII IN [A] & [IOCHAR] + + 1E77 20BD20 BADKEY: JSR BOOP + 1E7A 4C821E JMP GKEY0 + + 1E7D D8 GETKEY: CLD + 1E7E 8A TXA ; SAVE [X] & [Y] + 1E7F 48 PHA + 1E80 98 TYA + 1E81 48 PHA + + 1E82 A900 GKEY0: LDA #0 + 1E84 85F6 STA BLINK+LO ; LENGTHEN BLINK DELAY + 1E86 85F7 STA BLINK+HI ; TO MAXIMUM + + 1E88 A555 LDA COLCRS+LO ; CALC CURSOR X-POS + 1E8A 0A ASL A + 1E8B 0A ASL A + 1E8C 18 CLC + 1E8D 6930 ADC #48 + 1E8F 8D04D0 STA HPOSM0 + + 1E92 A554 LDA ROWCRS ; CALC CURSOR Y-POS + 1E94 0A ASL A + 1E95 0A ASL A + 1E96 0A ASL A + 1E97 18 CLC + 1E98 6927 ADC #39 + 1E9A A8 TAY ; MOVE HERE FOR DRAWING + + 1E9B A903 LDA #%00000011 ; FORCE CURSOR "ON" + 1E9D 85F8 STA CSHAPE + 1E9F 99000B STA MISSL,Y ; AND DRAW IT + + 1EA2 AEFC02 GKEY1: LDX CH ; CHECK HARDWARE FOR A KEYPRESS + + 1EA5 E6F6 INC BLINK+LO + 1EA7 D011 BNE NOBLIN + 1EA9 E6F7 INC BLINK+HI + 1EAB D00D BNE NOBLIN + + 1EAD A980 LDA #$80 + 1EAF 85F7 STA BLINK+HI ; RESET BLINK TIMER + + 1EB1 A5F8 LDA CSHAPE + 1EB3 4903 EOR #%00000011 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 94 +--- MACHINE-DEPENDENT I/O: ATARI --- + + 1EB5 85F8 STA CSHAPE ; FLIP CURSOR SHAPE + 1EB7 99000B STA MISSL,Y ; DRAW CURSOR INTO MISSILE RAM + + 1EBA E0FF NOBLIN: CPX #$FF ; KEY PRESSED? + 1EBC F0E4 BEQ GKEY1 ; NO, KEEP SCANNING + + 1EBE A9FF LDA #$FF + 1EC0 8DFC02 STA CH ; RESET KEY HARDWARE + + 1EC3 8A TXA + 1EC4 30B1 BMI BADKEY ; REJECT CTRL KEYS + + 1EC6 BD2621 LDA ATASCI,X ; GET CODE INTO [A] + 1EC9 C99B CMP #EOL ; WAS IT EOL? + 1ECB F003 BEQ CLICK ; OKAY IF SO + 1ECD AA TAX ; ANY OTHER NEGATIVE CODE + 1ECE 30A7 BMI BADKEY ; IS ILLEGAL + + 1ED0 ; ERASE CURSOR, "CLICK" THE SPEAKER + + 1ED0 85E2 CLICK: STA IOCHAR ; SAVE KEYCODE + 1ED2 A900 LDA #0 + 1ED4 99000B STA MISSL,Y ; ERASE CURSOR + + 1ED7 A080 LDY #$80 + 1ED9 8C1FD0 CLK0: STY CONSOL + 1EDC A208 LDX #8 + 1EDE CA CLK1: DEX + 1EDF D0FD BNE CLK1 + 1EE1 88 DEY + 1EE2 D0F5 BNE CLK0 + + 1EE4 68 PLA ; RESTORE + 1EE5 A8 TAY ; EVERYTHING + 1EE6 68 PLA + 1EE7 AA TAX + 1EE8 A5E2 LDA IOCHAR ; GET CHAR INTO [A] + 1EEA 60 RTS ; AND RETURN IT + + 1EEB ; ----------------- + 1EEB ; PRINT CHAR IN [A] + 1EEB ; ----------------- + + 1EEB 85E2 CHAR: STA IOCHAR ; SAVE HERE + 1EED 8A TXA ; SAVE [X] AND [Y] + 1EEE 48 PHA + 1EEF 98 TYA + 1EF0 48 PHA + + 1EF1 A454 LDY ROWCRS ; Y-POS INTO [Y] + 1EF3 A655 LDX COLCRS+LO ; X-POS INTO [X] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 95 +--- MACHINE-DEPENDENT I/O: ATARI --- + + + 1EF5 A5E2 LDA IOCHAR ; RESTORE CHAR + 1EF7 C99B CMP #EOL ; IS IT EOL? + 1EF9 F056 BEQ OUTEOL ; YES, SPECIAL HANDLING + 1EFB C90D CMP #$0D ; ALSO CHECK FOR + 1EFD F052 BEQ OUTEOL ; ASCII EOL + + 1EFF ; HANDLE A NON-EOL CHAR + + 1EFF C016 CPY #YSIZE-1 ; ON LAST SCREEN LINE? + 1F01 9037 BCC NOSCRL ; NO, NO SCROLL NEEDED + 1F03 E027 CPX #XSIZE ; LAST CHAR ON LINE? + 1F05 9033 BCC NOSCRL ; NO, DON'T SCROLL + + 1F07 ; SCROLL THE SCREEN + + 1F07 88 DOSCRL: DEY ; PUSH CURSOR UP ONE LINE + 1F08 8454 STY ROWCRS + + 1F0A A6E3 LDX SLINE ; GET CURRENT SCROLL LINE + + 1F0C E017 SRL0: CPX #YSIZE + 1F0E F020 BEQ SRL2 ; SCROLL DONE + + 1F10 BDF620 LDA LOLINE,X ; GET ADDR OF DEST LINE + 1F13 85E7 STA LTO+LO ; INTO [LTO] + 1F15 BD0E21 LDA HILINE,X + 1F18 85E8 STA LTO+HI + + 1F1A E8 INX + 1F1B BDF620 LDA LOLINE,X ; GET ADDR OF SOURCE LINE + 1F1E 85E5 STA LFROM+LO ; INTO [LFROM] + 1F20 BD0E21 LDA HILINE,X + 1F23 85E6 STA LFROM+HI + + 1F25 A027 LDY #XSIZE + 1F27 B1E5 SRL1: LDA (LFROM),Y ; MOVE SOURCE LINE + 1F29 91E7 STA (LTO),Y ; TO DEST LINE + 1F2B 88 DEY + 1F2C 10F9 BPL SRL1 + + 1F2E 30DC BMI SRL0 ; LOOP TILL [X] = YSIZE + + 1F30 A227 SRL2: LDX #XSIZE + 1F32 A900 LDA #0 + 1F34 9DD8BF SRL3: STA SCREEN+920,X ; CLEAR LAST LINE + 1F37 CA DEX ; OF SCREEN RAM + 1F38 10FA BPL SRL3 + + 1F3A A5E2 NOSCRL: LDA IOCHAR ; RESTORE CHAR + 1F3C A20B LDX #$0B ; CIO "PUT CHAR" + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 96 +--- MACHINE-DEPENDENT I/O: ATARI --- + + 1F3E 8E4203 STX ICCOM ; COMMAND + 1F41 A200 LDX #0 ; IOCB #0 (E:) + 1F43 8E4803 STX ICBLEN+LO ; ZERO THE + 1F46 8E4903 STX ICBLEN+HI ; BUFFER LENGTH + 1F49 2056E4 JSR CIOV ; SEND IT OUT! + + 1F4C 68 PLA ; RESTORE [X] AND [Y] + 1F4D A8 TAY + 1F4E 68 PLA + 1F4F AA TAX + 1F50 60 RTS + + 1F51 ; HANDLE EOL + + 1F51 A99B OUTEOL: LDA #$9B ; MAKE SURE [IOCHAR] + 1F53 85E2 STA IOCHAR ; IS AN ATASCII EOL + 1F55 C016 CPY #YSIZE-1 ; LAST SCREEN LINE? + 1F57 90E1 BCC NOSCRL ; NO, DON'T SCROLL + 1F59 B0AC BCS DOSCRL ; ELSE SCROLL + + 1F5B ; --------------------- + 1F5B ; FETCH A LINE OF INPUT + 1F5B ; --------------------- + + 1F5B ; ENTRY: ABS ADDR OF READ BUFFER IN [ARG1] + 1F5B ; EXIT: # CHARS READ IN [A] + + 1F5B 20001D INPUT: JSR LINOUT ; FLUSH [LBUFF] + + 1F5E A0FF LDY #$FF + 1F60 8CFC02 STY CH ; CLEAR KEYBOARD + 1F63 C8 INY ; = 0 + 1F64 84E0 STY LINCNT ; RESET LINE COUNT + + 1F66 207D1E INLOOP: JSR GETKEY ; GET ASCII INTO [A] AND [IOCHAR] + + 1F69 C99B CMP #EOL ; EOL? + 1F6B F02A BEQ ENDLIN ; LINE DONE IF SO + 1F6D C97E CMP #BACKSP ; BACKSPACE? + 1F6F F01C BEQ BACKUP ; SPECIAL HANDLING + + 1F71 99800A STA LBUFF,Y ; ELSE ADD CHAR TO INPUT BUFFER + 1F74 C8 INY ; NEXT POSITION IN LINE + + 1F75 20EB1E SHOWIT: JSR CHAR ; SEND TO SCREEN + + 1F78 C04D CPY #77 ; 2 SCREEN LINES FULL? + 1F7A 90EA BCC INLOOP ; NO, GET ANOTHER CHAR + + 1F7C ; HANDLE LINE OVERFLOW + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 97 +--- MACHINE-DEPENDENT I/O: ATARI --- + + 1F7C 207D1E NOMORE: JSR GETKEY + 1F7F C99B CMP #EOL ; IF EOL, + 1F81 F014 BEQ ENDLIN ; WRAP UP THE LINE + 1F83 C97E CMP #BACKSP ; BACKSPACE + 1F85 F006 BEQ BACKUP ; IS OKAY TOO + 1F87 20BD20 JSR BOOP ; ELSE COMPLAIN + 1F8A 4C7C1F JMP NOMORE ; AND INSIST + + 1F8D ; HANDLE BACKSPACE + + 1F8D 88 BACKUP: DEY ; BACK UP THE POINTER + 1F8E 10E5 BPL SHOWIT ; SEND BS IF NOT START OF LINE + 1F90 20BD20 JSR BOOP ; ELSE SCREAM WITH PAIN + 1F93 A000 LDY #0 ; RESET POINTER + 1F95 F0CF BEQ INLOOP ; AND WAIT FOR SOMETHING BETTER + + 1F97 ; HANDLE END OF LINE + + 1F97 99800A ENDLIN: STA LBUFF,Y ; SHIP EOL TO BUFFER + 1F9A C8 INY ; UPDATE INDEX + 1F9B 84C2 STY LINLEN ; SAVE HERE FOR "READ" + 1F9D 84EA STY PRLEN ; AND HERE FOR "PPRINT" + + 1F9F 20EB1E JSR CHAR ; AND SEND EOL TO SCREEN + + 1FA2 ; MOVE [LBUFF] TO [ARG1] W/LC CONVERSION + + 1FA2 B97F0A LEX0: LDA LBUFF-1,Y ; GET A CHAR FROM [LBUFF] + + 1FA5 C99B CMP #EOL ; ATASCII EOL? + 1FA7 D004 BNE LEX1 ; IF SO, + 1FA9 A90D LDA #$0D ; CONVERT TO ASCII + 1FAB D00A BNE LEX2 + + 1FAD C941 LEX1: CMP #'A' ; IF CHAR IS ALPHA, + 1FAF 9006 BCC LEX2 ; CONVERT TO LOWER CASE + 1FB1 C95B CMP #'Z'+1 + 1FB3 B002 BCS LEX2 + 1FB5 6920 ADC #$20 + + 1FB7 9182 LEX2: STA (ARG1),Y ; MOVE CHAR TO INPUT BUFFER AT [ARG1] + 1FB9 88 DEY ; LOOP TILL + 1FBA 10E6 BPL LEX0 ; ALL CHARS MOVED + + 1FBC 20D91F JSR PPRINT ; SCRIPT [LBUFF] IF ENABLED + + 1FBF A5C2 LDA LINLEN ; RESTORE # CHARS + 1FC1 60 RTS ; INTO [A] + + 1FC2 ; ----------------------- + 1FC2 ; DIRECT PRINT LINE [X/A] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 98 +--- MACHINE-DEPENDENT I/O: ATARI --- + + 1FC2 ; ----------------------- + + 1FC2 ; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB) + 1FC2 ; STRING LENGTH IN [Y] + + 1FC2 8ECB1F DLINE: STX STRING+LO ; DROP STRING ADDRESS + 1FC5 8DCC1F STA STRING+HI ; INTO DUMMY BYTES + + 1FC8 A200 LDX #0 ; INIT CHAR-FETCH INDEX + + 1FCA BD DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE + 1FCB 0000 STRING: DW $0000 ; DUMMY OPERAND BYTES + 1FCD 20EB1E JSR CHAR + 1FD0 E8 INX + 1FD1 88 DEY ; LOOP TILL + 1FD2 D0F6 BNE DOUT ; OUT OF CHARS + + 1FD4 60 RTS + + 1FD5 ; ----------------------- + 1FD5 ; SEND [LBUFF] TO PRINTER + 1FD5 ; ----------------------- + + 1FD5 ; ENTRY: LENTH OF LINE IN [PRLEN] + + 1FD5 503A PNAME: DB "P:" ; FILENAME FOR PRINTER + 1FD7 9B DB EOL + + 1FD8 00 SFLAG: DB 0 ; PREVIOUS SCRIPTING STATE + + 1FD9 A5DF PPRINT: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? + 1FDB F06B BEQ PEX ; NO, SCRAM IMMEDIATELY + + 1FDD AD1126 LDA ZBEGIN+ZSCRIP+1 ; CHECK SCRIPT FLAG + 1FE0 2901 AND #%00000001 ; SCRIPTING ON? + 1FE2 F064 BEQ PEX ; NO, EXIT + + 1FE4 A5E9 LDA PSTAT ; CHECK PRINTER STATUS + 1FE6 3060 BMI PEX ; CAN'T OPEN IF NEGATIVE + 1FE8 D02F BNE PP1 ; ALREADY OPEN, SCRIPT THE LINE + + 1FEA ; OPEN THE PRINTER FOR OUTPUT + + 1FEA 203E20 JSR CLOSEP ; CLOSE IOCB #1 FIRST FOR SAFETY + + 1FED A210 LDX #$10 ; IOCB #1 (P:) + 1FEF A9D5 LDA #LOW PNAME ; POINT + 1FF1 9D4403 STA ICBADR+LO,X ; TO + 1FF4 A91F LDA #HIGH PNAME ; P: + 1FF6 9D4503 STA ICBADR+HI,X ; FILENAME + 1FF9 A903 LDA #$03 ; CIO "OPEN" + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 99 +--- MACHINE-DEPENDENT I/O: ATARI --- + + 1FFB 9D4203 STA ICCOM,X ; COMMAND + 1FFE A908 LDA #$08 ; SET CHANNEL + 2000 9D4A03 STA ICAUX1,X ; FOR WRITE-ONLY + 2003 A900 LDA #0 + 2005 9D4B03 STA ICAUX2,X ; ZERO THIS BYTE + 2008 2056E4 JSR CIOV ; OPEN IT! + 200B 98 TYA ; STATUS CODE IN [Y] + 200C 302C BMI BADP ; ERROR IF NEGATIVE + + 200E A970 LDA #$70 + 2010 8510 STA POKMSK + 2012 8D0ED2 STA IRQEN ; DISABLE BREAK KEY + + 2015 A901 LDA #1 ; SET [PSTAT] + 2017 85E9 STA PSTAT ; TO INDICATE "PRINTER READY" + + 2019 ; PRINT [LBUFF] + + 2019 A210 PP1: LDX #$10 ; IOCB #1 (P:) + 201B A980 LDA #LOW LBUFF ; TELL CIO + 201D 9D4403 STA ICBADR+LO,X ; WHERE + 2020 A90A LDA #HIGH LBUFF ; [LBUFF] + 2022 9D4503 STA ICBADR+HI,X ; IS HIDING + 2025 A5EA LDA PRLEN ; # CHARS TO PRINT + 2027 9D4803 STA ICBLEN+LO,X + 202A A900 LDA #0 ; CLEAR THE + 202C 9D4903 STA ICBLEN+HI,X ; MSB OF LINE LENGTH + 202F A90B LDA #$0B ; CIO "PUT BUFFER" COMMAND (BM 4/9/85) + 2031 9D4203 STA ICCOM,X ; COMMAND + 2034 2056E4 JSR CIOV + 2037 98 TYA + 2038 100E BPL PEX ; EXIT IF NO ERROR + + 203A ; HANDLE PRINTER ERROR + + 203A A9FF BADP: LDA #$FF ; SET PRINTER STATUS + 203C 85E9 STA PSTAT ; TO "CAN'T OPEN" + + 203E ; CLOSE PRINTER CHANNEL (IOCB #1) + + 203E A210 CLOSEP: LDX #$10 ; IOCB #1 (P:) + 2040 A90C LDA #$0C ; CIO "CLOSE" + 2042 9D4203 STA ICCOM,X ; COMMAND + 2045 2056E4 JSR CIOV ; CLOSE THE CHANNEL + + 2048 60 PEX: RTS + + 2049 ; ------------ + 2049 ; SPLIT SCREEN + 2049 ; ------------ + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 100 +--- MACHINE-DEPENDENT I/O: ATARI --- + + 2049 ; SPLIT SCREEN AT LINE [ARG1] + 2049 ; DISABLE SPLIT IF [ARG1] = 0 + 2049 ; IGNORE IF SPLIT ALREADY ENABLED OR [ARG1] >= 20 + + 2049 A682 ZSPLIT: LDX ARG1+LO ; IF [ARG1] = 0, + 204B F02F BEQ OFFSPL ; TURN OFF SPLIT SCREEN + + 204D A5E4 LDA SPSTAT ; SPLIT ALREADY ENABLED? + 204F D02A BNE SPLEX ; IGNORE REQUEST IF SO + + 2051 E014 CPX #20 ; IF [ARG1] >= 20, + 2053 B026 BCS SPLEX ; IGNORE + + 2055 E8 INX + 2056 86E3 STX SLINE ; ELSE SET NEW SPLIT LINE + 2058 86E4 STX SPSTAT ; SET "SPLIT ENABLED" FLAG + + 205A BDF620 SPL0: LDA LOLINE,X ; MAKE [LFROM] POINT TO + 205D 85E5 STA LFROM+LO ; LINE [X] IN WINDOW + 205F BD0E21 LDA HILINE,X + 2062 85E6 STA LFROM+HI + + 2064 A027 LDY #XSIZE ; CLEAR LINE [X] + 2066 A900 LDA #0 + 2068 91E5 SPL1: STA (LFROM),Y + 206A 88 DEY + 206B 10FB BPL SPL1 + + 206D CA DEX ; DONE ALL LINES? + 206E D0EA BNE SPL0 ; LOOP TILL WINDOW CLEARED + 2070 86E0 STX LINCNT ; RESET LINE COUNT TO ZERO + + 2072 A916 SPCALC: LDA #YSIZE-1 ; CALCULATE # LINES TO SCROLL + 2074 38 SEC ; BEFORE "MORE" APPEARS: + 2075 E5E3 SBC SLINE ; LMAX = YSIZE-SLINE-1 + 2077 85E1 STA LMAX + 2079 C6E1 DEC LMAX + + 207B 60 SPLEX: RTS + + 207C ; -------------------- + 207C ; DISABLE SPLIT SCREEN + 207C ; -------------------- + + 207C 20A720 OFFSPL: JSR TOBOT1 ; SET CURSOR TO BOTTOM + + 207F A201 SPLOFF: LDX #1 + 2081 86E3 STX SLINE ; SPLIT AT LINE 1 + 2083 CA DEX ; = 0 + 2084 86E4 STX SPSTAT ; TURN OFF STATUS FLAG + 2086 86E0 STX LINCNT ; RESET LINE COUNT + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 101 +--- MACHINE-DEPENDENT I/O: ATARI --- + + 2088 A915 LDA #21 + 208A 85E1 STA LMAX ; SET MAXIMUM LINE SCROLL + 208C D023 BNE NEWLOG ; RESET LINE MAP & RETURN + + 208E ; ------ + 208E ; SCREEN + 208E ; ------ + + 208E ; GO TO TOP WINDOW IF [A] = 0 + 208E ; GO TO BOTTOM IF [A] = 1 + 208E ; IGNORE IF SPLIT NOT ENABLED OR [A] <> 0 OR 1 + + 208E A5E4 ZSCRN: LDA SPSTAT ; IF SPLIT NOT ENABLED, + 2090 F0E9 BEQ SPLEX ; IGNORE REQUEST + + 2092 A582 LDA ARG1+LO ; IF [ARG1] = 0, + 2094 0583 ORA ARG1+HI + 2096 F00C BEQ TOBOT0 ; GO TO BOTTOM WINDOW + 2098 C901 CMP #1 ; IF [ARG1] <> 1, + 209A D0DF BNE SPLEX ; IGNORE THE REQUEST + + 209C ; SET TO TOP WINDOW + + 209C A015 TOTOP: LDY #21 ; TEMPORARILY RESET + 209E 84E1 STY LMAX ; [LMAX] TO KILL "MORE" + 20A0 A001 LDY #1 ; Y-POS = 1 + 20A2 D005 BNE DOSCRN + + 20A4 ; SET TO BOTTOM WINDOW + + 20A4 207220 TOBOT0: JSR SPCALC ; RE-CALC [LMAX] + + 20A7 A017 TOBOT1: LDY #23 ; Y-POS = 23 + + 20A9 8454 DOSCRN: STY ROWCRS ; Y-POS = [Y] + 20AB A900 LDA #0 ; X-POS = 0 + 20AD 8555 STA COLCRS+LO + 20AF 85E0 STA LINCNT ; RESET LINE COUNT + + 20B1 ; FALL THROUGH ... + + 20B1 ; ---------------------- + 20B1 ; RESET LOGICAL LINE MAP + 20B1 ; ---------------------- + + 20B1 A9FF NEWLOG: LDA #$FF + 20B3 8DB202 STA LOGMAP + 20B6 8DB302 STA LOGMAP+1 + 20B9 8DB402 STA LOGMAP+2 + 20BC 60 RTS + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 102 +--- MACHINE-DEPENDENT I/O: ATARI --- + + 20BD ; --------- + 20BD ; RAZZ USER + 20BD ; --------- + + 20BD A9C8 BOOP: LDA #200 ; SET + 20BF 8D00D2 STA AUDF1 ; FREQUENCY + 20C2 A9AA LDA #$AA ; PURE TONE, VOLUME #10 + 20C4 8D01D2 STA AUDC1 + 20C7 A9FC LDA #252 ; 4 JIFFY DELAY + 20C9 8514 STA RTCLOK + 20CB A514 BOOP0: LDA RTCLOK + 20CD D0FC BNE BOOP0 + 20CF 8D01D2 STA AUDC1 ; SHUT OFF SOUND + 20D2 60 RTS + + 20D3 ; ------------ + 20D3 ; CLEAR SCREEN + 20D3 ; ------------ + + 20D3 A940 CLS: LDA #LOW SCREEN + 20D5 858E STA I+LO + 20D7 A9BC LDA #HIGH SCREEN ; POINT [I] TO + 20D9 858F STA I+HI ; SCREEN RAM + + 20DB A900 LDA #0 + 20DD 85DD STA LENGTH ; RESET LINE LENGTH + 20DF A8 TAY + 20E0 A204 LDX #4 ; CLEAR 4 PAGES + 20E2 918E CLS0: STA (I),Y ; FOR SCREEN + 20E4 C8 INY + 20E5 D0FB BNE CLS0 + 20E7 E68F INC I+HI ; POINT TO NEXT PAGE + 20E9 CA DEX ; 4 PAGES DONE? + 20EA D0F6 BNE CLS0 ; LOOP TILL EMPTY + + 20EC A001 LDY #1 ; SET Y-POS TO 1 + 20EE 8454 STY ROWCRS + 20F0 88 DEY ; X-POS TO 0 + 20F1 8455 STY COLCRS+LO + 20F3 4C7F20 JMP SPLOFF ; DISABLE SPLIT-SCREEN & RETURN + + 20F6 ; ------------------- + 20F6 ; LINE ADDRESS TABLES + 20F6 ; ------------------- + + 20F6 406890B8 LOLINE: DB $40,$68,$90,$B8,$E0,$08,$30,$58 + 20FE 80A8D0F8 DB $80,$A8,$D0,$F8,$20,$48,$70,$98 + 2106 C0E81038 DB $C0,$E8,$10,$38,$60,$88,$B0,$D8 + + 210E BCBCBCBC HILINE: DB $BC,$BC,$BC,$BC,$BC,$BD,$BD,$BD + 2116 BDBDBDBD DB $BD,$BD,$BD,$BD,$BE,$BE,$BE,$BE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 103 +--- MACHINE-DEPENDENT I/O: ATARI --- + + 211E BEBEBFBF DB $BE,$BE,$BF,$BF,$BF,$BF,$BF,$BF + + 2126 ; ------------------------ + 2126 ; ATASCII CONVERSION TABLE + 2126 ; ------------------------ + + 2126 6C6A3BFF ATASCI: DB $6C,$6A,$3B,$FF,$FF,$6B,$FF,$FF ; UNSHIFTED + 212E 6FFF7075 DB $6F,$FF,$70,$75,$9B,$69,$2D,$FF + 2136 76FF63FF DB $76,$FF,$63,$FF,$FF,$62,$78,$7A + 213E 34FF3336 DB $34,$FF,$33,$36,$FF,$35,$32,$31 + 2146 2C202E6E DB $2C,$20,$2E,$6E,$FF,$6D,$2F,$FF + 214E 72FF6579 DB $72,$FF,$65,$79,$FF,$74,$77,$71 + 2156 39FF3037 DB $39,$FF,$30,$37,$7E,$38,$FF,$FF + 215E 666864FF DB $66,$68,$64,$FF,$FF,$67,$73,$61 + + 2166 4C4A3AFF DB $4C,$4A,$3A,$FF,$FF,$4B,$FF,$FF ; SHIFTED + 216E 4FFF5055 DB $4F,$FF,$50,$55,$9B,$49,$2D,$FF + 2176 56FF43FF DB $56,$FF,$43,$FF,$FF,$42,$58,$5A + 217E 24FF2336 DB $24,$FF,$23,$36,$FF,$35,$22,$21 + 2186 2C202E4E DB $2C,$20,$2E,$4E,$FF,$4D,$3F,$FF + 218E 52FF4559 DB $52,$FF,$45,$59,$FF,$54,$57,$51 + 2196 39FF3027 DB $39,$FF,$30,$27,$7E,$38,$FF,$FF + 219E 464844FF DB $46,$48,$44,$FF,$FF,$47,$53,$41 + + END + INCLUD ZDOS.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 104 +--- Z-DOS: ATARI --- + + + 21A6 ; ----------------------------- + 21A6 ; SET UP SAVE & RESTORE SCREENS + 21A6 ; ----------------------------- + + 21A6 20C71C SAVRES: JSR ZCRLF ; CLEAR THE LINE BUFFER + 21A9 20D320 JSR CLS ; AND THE SCREEN + + 21AC A900 LDA #0 + 21AE 85DF STA SCRIPT ; DISABLE SCRIPTING + 21B0 8555 STA COLCRS+LO ; HOME CURSOR + 21B2 8554 STA ROWCRS + 21B4 60 RTS + + 21B5 ; ----------------- + 21B5 ; DISPLAY A DEFAULT + 21B5 ; ----------------- + + 21B5 ; ENTRY: DEFAULT (1-8) IN [A] + + 21B5 20284465 DEFAL: DB " (Default is " + 21C2 2A29203E DEFNUM: DB "*) >" + 0011 DEFALL EQU $-DEFAL + + 21C6 18 DODEF: CLC + 21C7 6931 ADC #'1' ; CONVERT TO ASCII 1-9 + 21C9 8DC221 STA DEFNUM ; INSERT IN STRING + + 21CC A2B5 LDX #LOW DEFAL + 21CE A921 LDA #HIGH DEFAL + 21D0 A011 LDY #DEFALL + 21D2 4CC21F JMP DLINE ; PRINT THE STRING + + 21D5 ; ----------------------------- + 21D5 ; GET SAVE & RESTORE PARAMETERS + 21D5 ; ----------------------------- + + 21D5 9B POSIT: DB EOL + 21D6 506F7369 DB "Position 1-5" + 000D POSITL EQU $-POSIT + + 21E2 9B WDRIV: DB EOL + 21E3 44726976 DB "Drive 1 or 2" + 000D WDRIVL EQU $-WDRIV + + 21EF 9B MIND: DB EOL + 21F0 9B DB EOL + 21F1 506F7369 DB "Position " + 21FA 2A3B2044 MPOS: DB "*; Drive #" + 2204 2A2E MDRI: DB "*." + 2206 9B DB EOL + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 105 +--- Z-DOS: ATARI --- + + 2207 41726520 DB "Are you sure? (Y or N) >" + 0030 MINDL EQU $-MIND + + 221F 9B INSM: DB EOL + 2220 496E7365 DB "Insert SAVE disk into Drive #" + 223D 2A2E SAVDRI: DB "*." + 0020 INSML EQU $-INSM + + 223F 594553 YES: DB "YES" + 2242 9B DB EOL + 0004 YESL EQU $-YES + + 2243 4E4F NO: DB "NO" + 2245 9B DB EOL + 0003 NOL EQU $-NO + + 2246 A2D5 PARAMS: LDX #LOW POSIT + 2248 A921 LDA #HIGH POSIT + 224A A00D LDY #POSITL + 224C 20C21F JSR DLINE ; "POSITION (1-5)" + + 224F ; GET GAME SAVE POSITION + + 224F A5F1 LDA GPOSIT ; SHOW THE CURRENT + 2251 20C621 JSR DODEF ; DEFAULT POSITION + + 2254 207D1E GETPOS: JSR GETKEY ; WAIT FOR A KEY + 2257 C99B CMP #EOL ; IF [RETURN], + 2259 F00D BEQ POSSET ; USE DEFAULT + 225B 38 SEC + 225C E931 SBC #'1' ; ELSE CONVERT ASCII TO BINARY + 225E C905 CMP #5 ; IF BELOW "5" + 2260 9008 BCC SETPOS ; MAKE IT THE NEW DEFAULT + 2262 20BD20 JSR BOOP ; ELSE RAZZ + 2265 4C5422 JMP GETPOS ; AND TRY AGAIN + + 2268 A5F1 POSSET: LDA GPOSIT ; USE DEFAULT + + 226A 85F3 SETPOS: STA TPOSIT ; USE KEYPRESS + 226C 18 CLC + 226D 6931 ADC #'1' ; CONVERT TO ASCII "1"-"5" + 226F 8DFA21 STA MPOS ; STORE IN TEMP STRING + 2272 8DD923 STA SVPOS + 2275 8D7924 STA RSPOS + 2278 20EB1E JSR CHAR ; AND DISPLAY IT + + 227B ; GET DRIVE ID + + 227B A2E2 LDX #LOW WDRIV + 227D A921 LDA #HIGH WDRIV + 227F A00D LDY #WDRIVL + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 106 +--- Z-DOS: ATARI --- + + 2281 20C21F JSR DLINE ; "DRIVE 1 OR 2" + + 2284 A5F2 LDA GDRIVE ; SHOW DEFAULT + 2286 20C621 JSR DODEF + + 2289 207D1E GETDRV: JSR GETKEY ; GET A KEYPRESS + 228C C99B CMP #EOL ; IF [RETURN], + 228E F00D BEQ DRVSET ; USE DEFAULT + 2290 38 SEC + 2291 E931 SBC #'1' ; CONVERT TO BINARY 0 OR 1 + 2293 C902 CMP #2 ; IF WITHIN RANGE, + 2295 9008 BCC SETDRV ; SET NEW DEFAULT + 2297 20BD20 JSR BOOP + 229A 4C8922 JMP GETDRV ; ELSE TRY AGAIN + + 229D A5F2 DRVSET: LDA GDRIVE ; USE DEFAULT + + 229F 85F4 SETDRV: STA TDRIVE ; USE [A] + 22A1 18 CLC + 22A2 6931 ADC #'1' ; CONVERT TO ASCII 1 OR 2 + 22A4 8D3D22 STA SAVDRI ; STORE IN DRIVE STRING + 22A7 8D0422 STA MDRI ; AND IN TEMP STRING + 22AA 20EB1E JSR CHAR ; AND SHOW NEW SETTING + + 22AD A2EF LDX #LOW MIND ; SHOW TEMPORARY SETTINGS + 22AF A921 LDA #HIGH MIND + 22B1 A030 LDY #MINDL + 22B3 20C21F JSR DLINE + + 22B6 ; VALIDATE RESPONSES + + 22B6 A9FF LDA #$FF + 22B8 8DFC02 STA CH + 22BB 207D1E GETYES: JSR GETKEY + 22BE C979 CMP #'y' ; IF REPLY IS "Y" + 22C0 F022 BEQ ALLSET ; ACCEPT RESPONSES + 22C2 C959 CMP #'Y' + 22C4 F01E BEQ ALLSET + 22C6 C99B CMP #EOL ; EOL IS ALSO ACCEPTABLE + 22C8 F01A BEQ ALLSET + + 22CA C96E CMP #'n' ; IF REPLY IS "N" + 22CC F00A BEQ NOTSAT ; RESTATE PARAMETERS + 22CE C94E CMP #'N' + 22D0 F006 BEQ NOTSAT + + 22D2 20BD20 JSR BOOP ; ELSE BOOP + 22D5 4CBB22 JMP GETYES ; INSIST ON Y OR N + + 22D8 A243 NOTSAT: LDX #LOW NO + 22DA A922 LDA #HIGH NO + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 107 +--- Z-DOS: ATARI --- + + 22DC A003 LDY #NOL + 22DE 20C21F JSR DLINE ; PRINT "NO"/EOL + 22E1 4C4622 JMP PARAMS ; AND TRY AGAIN + + 22E4 A23F ALLSET: LDX #LOW YES + 22E6 A922 LDA #HIGH YES + 22E8 A004 LDY #YESL + 22EA 20C21F JSR DLINE ; PRINT "YES"/EOL + + 22ED A5F4 LDA TDRIVE ; MAKE THE TEMPORARY DRIVE + 22EF 85F2 STA GDRIVE ; THE DEFAULT DRIVE + 22F1 85F5 STA DRIVE ; AND SET [DRIVE] ACCORDINGLY + + 22F3 E6F5 INC DRIVE ; 1-ALIGN THE DRIVE ID + + 22F5 A6F3 LDX TPOSIT ; MAKE THE TEMP POSITION + 22F7 86F1 STX GPOSIT ; THE DEFAULT POSITION + + 22F9 ; CALC TRACK & SECTOR OF GAME POSITION + + 22F9 BD2925 LDA OFFLOS,X ; INDEX INTO THE OFFSET TABLES + 22FC 85EF STA SECTOR+LO ; SET [SECTOR] = 1ST SECTOR + 22FE BD2E25 LDA OFFHIS,X ; IN REQUESTED SAVE POSITION + 2301 85F0 STA SECTOR+HI + + 2303 A21F LDX #LOW INSM + 2305 A922 LDA #HIGH INSM + 2307 A020 LDY #INSML + 2309 20C21F JSR DLINE ; "INSERT SAVE DISK IN DRIVE X." + + 230C ; FALL THROUGH ... + + 230C ; --------------------- + 230C ; "PRESS RETURN" PROMPT + 230C ; --------------------- + + 230C 20C71C RETURN: JSR ZCRLF + 230F A233 LDX #LOW RTN + 2311 A923 LDA #HIGH RTN + 2313 A01B LDY #RTNL + 2315 20C21F JSR DLINE ; SHOW PROMPT + + 2318 20C71C JSR ZCRLF + 231B A93E LDA #'>' + 231D 20EB1E JSR CHAR + + 2320 ; ENTRY FOR QUIT/RESTART + + 2320 A9FF GETRET: LDA #$FF + 2322 8DFC02 STA CH + 2325 207D1E GTRT0: JSR GETKEY ; WAIT FOR [RETURN] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 108 +--- Z-DOS: ATARI --- + + 2328 C99B CMP #EOL + 232A F006 BEQ GTRT1 + 232C 20BD20 JSR BOOP ; ACCEPT NO + 232F 4C2523 JMP GTRT0 ; SUBSTITUTES! + + 2332 60 GTRT1: RTS + + 2333 50726573 RTN: DB "Press [RETURN] to continue." + 001B RTNL EQU $-RTN + + 234E ; -------------------- + 234E ; PROMPT FOR GAME DISK + 234E ; -------------------- + + 234E 496E7365 GAME: DB "Insert Side " + 235A 32206F66 DSIDE: DB "2 of the STORY disk into" + 0024 GAMEL EQU $-GAME + + 2372 44726976 GAME2: DB "Drive #1." + 0009 GAME2L EQU $-GAME2 + + 237B A931 SIDE1: LDA #'1' ; ASK FOR SIDE 1 + 237D D002 BNE DOSIDE + + 237F A932 SIDE2: LDA #'2' ; ASK FOR SIDE 2 + + 2381 8D5A23 DOSIDE: STA DSIDE + + 2384 A901 LDA #1 ; MAKE SURE WE'RE ON + 2386 85F5 STA DRIVE ; THE BOOT DRIVE + + 2388 20C71C JSR ZCRLF + 238B A24E LDX #LOW GAME + 238D A923 LDA #HIGH GAME + 238F A024 LDY #GAMEL + 2391 20C21F JSR DLINE ; "INSERT STORY DISK" + + 2394 20C71C JSR ZCRLF + 2397 A272 LDX #LOW GAME2 + 2399 A923 LDA #HIGH GAME2 + 239B A009 LDY #GAME2L + 239D 20C21F JSR DLINE ; "DRIVE #1" + + 23A0 200C23 JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + + 23A3 A9FF LDA #$FF ; ENABLE + 23A5 85DF STA SCRIPT ; SCRIPTING + 23A7 60 RTS + + 23A8 ; ------------------------- + 23A8 ; SET UP PHONEY STATUS LINE + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 109 +--- Z-DOS: ATARI --- + + 23A8 ; ------------------------- + + 23A8 ; ENTRY: TEXT SET UP FOR "DLINE" + + 23A8 20C21F SROOM: JSR DLINE ; PRINT LINE IN [X/Y/A] + + 23AB A227 LDX #39 ; INVERT & BLACKEN TOP LINE + 23AD BD40BC SRLP: LDA SCREEN,X + 23B0 0980 ORA #%10000000 + 23B2 9D40BC STA SCREEN,X + 23B5 CA DEX + 23B6 10F5 BPL SRLP + 23B8 60 RTS + + 23B9 ; --------- + 23B9 ; SAVE GAME + 23B9 ; --------- + + 23B9 53617665 SAV: DB "Save Position" + 23C6 9B DB EOL + 000E SAVL EQU $-SAV + + 23C7 9B SVING: DB EOL + 23C8 9B DB EOL + 23C9 53617669 DB "Saving position " + 23D9 2A202E2E SVPOS: DB "* ..." + 23DE 9B DB EOL + 0018 SVINGL EQU $-SVING + + 23DF 20A621 ZSAVE: JSR SAVRES ; SET UP SCREEN + + 23E2 A2B9 LDX #LOW SAV + 23E4 A923 LDA #HIGH SAV + 23E6 A00E LDY #SAVL + 23E8 20A823 JSR SROOM ; "SAVE POSITION" + + 23EB 204622 JSR PARAMS ; GET PARAMETERS + + 23EE A2C7 LDX #LOW SVING + 23F0 A923 LDA #HIGH SVING + 23F2 A018 LDY #SVINGL + 23F4 20C21F JSR DLINE ; "SAVING POSITION X ..." + + 23F7 ; SAVE GAME PARAMETERS IN [BUFSAV] + + 23F7 AD0226 LDA ZBEGIN+ZID ; MOVE GAME ID + 23FA 8D200A STA BUFSAV+0 ; INTO 1ST 2 BYTES + 23FD AD0326 LDA ZBEGIN+ZID+1 ; OF THE AUX LINE BUFFER + 2400 8D210A STA BUFSAV+1 + + 2403 A594 LDA ZSP ; MOVE [ZSP] + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 110 +--- Z-DOS: ATARI --- + + 2405 8D220A STA BUFSAV+2 ; TO 3RD BYTE + 2408 A595 LDA OLDZSP ; MOVE [OLDZSP] + 240A 8D230A STA BUFSAV+3 ; TO 4TH + + 240D A202 LDX #2 ; MOVE CONTENTS OF [ZPC] + 240F B596 ZPCSAV: LDA ZPC,X ; TO BYTES 5-7 + 2411 9D240A STA BUFSAV+4,X ; OF [BUFSAV] + 2414 CA DEX + 2415 10F8 BPL ZPCSAV + + 2417 ; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK + + 2417 A90A LDA #HIGH LOCALS + 2419 85EE STA DBUFF+HI ; POINT TO THE PAGE + 241B 208125 JSR PUTDSK ; AND WRITE IT OUT + 241E 9009 BCC WSTACK ; IF SUCCEEDED, WRITE STACK + + 2420 207F23 BADSAV: JSR SIDE2 ; ELSE REQUEST STORY DISK + 2423 20D320 JSR CLS + 2426 4C480F JMP PREDF ; AND FAIL + + 2429 ; WRITE CONTENTS OF Z-STACK TO DISK + + 2429 A905 WSTACK: LDA #HIGH ZSTAKL ; POINT TO 1ST PAGE + 242B 85EE STA DBUFF+HI + 242D 208125 JSR PUTDSK ; WRITE 1ST AND + 2430 B0EE BCS BADSAV + 2432 208125 JSR PUTDSK ; 2ND PAGE OF Z-STACK + 2435 B0E9 BCS BADSAV + + 2437 ; WRITE ENTIRE GAME PRELOAD TO DISK + + 2437 A5A3 LDA ZCODE ; POINT TO 1ST PAGE + 2439 85EE STA DBUFF+HI ; OF PRELOAD + + 243B AE0E26 LDX ZBEGIN+ZPURBT ; GET # IMPURE PAGES + 243E E8 INX ; USE FOR INDEXING + 243F 868E STX I+LO + + 2441 208125 LSAVE: JSR PUTDSK + 2444 B0DA BCS BADSAV + 2446 C68E DEC I+LO + 2448 D0F7 BNE LSAVE + + 244A 207F23 JSR SIDE2 ; PROMPT FOR GAME DISK + 244D 20D320 JSR CLS + 2450 4C540F JMP PREDS ; ELSE PREDICATE SUCCEEDS + + 2453 ; ------------ + 2453 ; RESTORE GAME + 2453 ; ------------ + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 111 +--- Z-DOS: ATARI --- + + + 2453 52657374 RES: DB "Restore Position" + 2463 9B DB EOL + 0011 RESL EQU $-RES + + 2464 9B RSING: DB EOL + 2465 9B DB EOL + 2466 52657374 DB "Restoring position " + 2479 2A202E2E RSPOS: DB "* ..." + 247E 9B DB EOL + 001B RSINGL EQU $-RSING + + 247F 20A621 ZREST: JSR SAVRES + + 2482 A253 LDX #LOW RES + 2484 A924 LDA #HIGH RES + 2486 A011 LDY #RESL + 2488 20A823 JSR SROOM ; "RESTORE POSITION" + + 248B 204622 JSR PARAMS ; GET PARAMETERS + + 248E A264 LDX #LOW RSING + 2490 A924 LDA #HIGH RSING + 2492 A01B LDY #RSINGL + 2494 20C21F JSR DLINE ; "RESTORING POSITION X ..." + + 2497 ; SAVE LOCALS IN CASE OF ERROR + + 2497 A21F LDX #31 + 2499 BD000A LOCSAV: LDA LOCALS,X ; COPY ALL LOCALS + 249C 9D0001 STA $0100,X ; TO BOTTOM OF MACHINE STACK + 249F CA DEX + 24A0 10F7 BPL LOCSAV + + 24A2 A90A LDA #HIGH LOCALS + 24A4 85EE STA DBUFF+HI + 24A6 206E25 JSR RDISK ; RETRIEVE 1ST BLOCK OF PRELOAD + 24A9 B010 BCS WRONG ; BAD DISK READ IF CARRY CLEAR + + 24AB AD200A LDA BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID + 24AE CD0226 CMP ZBEGIN+ZID ; MATCH THE CURRENT ID? + 24B1 D008 BNE WRONG ; WRONG DISK IF NOT + + 24B3 AD210A LDA BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE? + 24B6 CD0326 CMP ZBEGIN+ZID+1 + 24B9 F014 BEQ RIGHT ; CONTINUE IF BOTH BYTES MATCH + + 24BB ; HANDLE RESTORE ERROR + + 24BB A21F WRONG: LDX #31 ; RESTORE ALL SAVED LOCALS + 24BD BD0001 WR0: LDA $0100,X + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 112 +--- Z-DOS: ATARI --- + + 24C0 9D000A STA LOCALS,X + 24C3 CA DEX + 24C4 10F7 BPL WR0 + + 24C6 207F23 JSR SIDE2 ; PROMPT FOR GAME DISK + 24C9 20D320 JSR CLS + 24CC 4C480F JMP PREDF ; PREDICATE FAILS + + 24CF ; CONTINUE RESTORE + + 24CF AD1026 RIGHT: LDA ZBEGIN+ZSCRIP ; SAVE BOTH FLAG BYTES + 24D2 858E STA I+LO + 24D4 AD1126 LDA ZBEGIN+ZSCRIP+1 + 24D7 858F STA I+HI + + 24D9 A905 LDA #HIGH ZSTAKL ; RETRIEVE OLD CONTENTS OF + 24DB 85EE STA DBUFF+HI ; Z-STACK + 24DD 206E25 JSR RDISK ; GET 1ST BLOCK OF Z-STACK + 24E0 B0D9 BCS WRONG + 24E2 206E25 JSR RDISK ; AND 2ND BLOCK + 24E5 B0D4 BCS WRONG + + 24E7 A5A3 LDA ZCODE + 24E9 85EE STA DBUFF+HI + 24EB 206E25 JSR RDISK ; GET 1ST BLOCK OF PRELOAD + 24EE B0CB BCS WRONG + + 24F0 A58E LDA I+LO ; RESTORE THE STATE + 24F2 8D1026 STA ZBEGIN+ZSCRIP ; OF THE FLAG WORD + 24F5 A58F LDA I+HI + 24F7 8D1126 STA ZBEGIN+ZSCRIP+1 + + 24FA AD0E26 LDA ZBEGIN+ZPURBT ; GET # PAGES TO LOAD + 24FD 858E STA I+LO + + 24FF 206E25 LREST: JSR RDISK ; FETCH THE REMAINDER + 2502 B0B7 BCS WRONG + 2504 C68E DEC I+LO ; OF THE PRELOAD + 2506 D0F7 BNE LREST + + 2508 ; RESTORE THE STATE OF THE SAVED GAME + + 2508 AD220A LDA BUFSAV+2 ; RESTORE THE [ZSP] + 250B 8594 STA ZSP + 250D AD230A LDA BUFSAV+3 ; AND THE [OLDZSP] + 2510 8595 STA OLDZSP + + 2512 A202 LDX #2 ; RESTORE THE [ZPC] + 2514 BD240A RESZPC: LDA BUFSAV+4,X + 2517 9596 STA ZPC,X + 2519 CA DEX + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 113 +--- Z-DOS: ATARI --- + + 251A 10F8 BPL RESZPC + + 251C A900 LDA #0 + 251E 8599 STA ZPCFLG ; INVALIDATE [ZPC] + + 2520 207F23 JSR SIDE2 ; PROMPT FOR GAME DISK + 2523 20D320 JSR CLS + 2526 4C540F JMP PREDS ; PREDICATE SUCCEEDS + + 2529 ; -------------------------- + 2529 ; SAVE/RESTORE OFFSET TABLES + 2529 ; -------------------------- + + 2529 ; 144 SECTORS (18K) PER SAVE POSITION + + 2529 01 OFFLOS: DB LOW 1 + 252A 91 DB LOW 145 + 252B 21 DB LOW 289 + 252C B1 DB LOW 433 + 252D 41 DB LOW 577 + + 252E 00 OFFHIS: DB HIGH 1 + 252F 00 DB HIGH 145 + 2530 01 DB HIGH 289 + 2531 01 DB HIGH 433 + 2532 02 DB HIGH 577 + + END + INCLUD DISK.ASM + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 114 +--- DISK ACCESS: ATARI --- + + + 2533 ; -------------------- + 2533 ; READ A VIRTUAL BLOCK + 2533 ; -------------------- + + 2533 ; ENTRY: TARGET V-BLOCK IN [DBLOCK] + 2533 ; TARGET RAM PAGE IN [DBUFF] + 2533 ; EXIT: CARRY CLEAR IF OKAY, SET IF NOT + + 2533 D8 GETDSK: CLD + 2534 A901 LDA #1 ; V-BLOCKS ALWAYS COME + 2536 85F5 STA DRIVE ; FROM DRIVE #1 + + 2538 ; CALCULATE SECTOR OF [DBLOCK] + + 2538 A6EB LDX DBLOCK+LO ; COPY LSB OF [DBLOCK] + 253A 86EF STX SECTOR+LO ; INTO [SECTOR] + + 253C A5EC LDA DBLOCK+HI + 253E 2901 AND #%00000001 ; MASK ALL BUT BIT 1 + 2540 85F0 STA SECTOR+HI + 2542 D015 BNE INPURE ; BLOCK IS PURE IF MSB <> 0 + + 2544 E4A4 CPX ZPURE ; ELSE CHECK LSB + 2546 B011 BCS INPURE ; PURE IF >= [ZPURE] + + 2548 ; HANDLE A PRELOAD BLOCK + + 2548 06EF ASL SECTOR+LO ; MULTIPLY BY 2 + 254A 26F0 ROL SECTOR+HI ; FOR ATARI 128-BYTE SECTORS + + 254C A5EF LDA SECTOR+LO + 254E 18 CLC + 254F 6949 ADC #73 ; ADD DISK PRELOAD OFFSET + 2551 85EF STA SECTOR+LO + 2553 9019 BCC RDISK + 2555 E6F0 INC SECTOR+HI + 2557 D015 BNE RDISK ; AND READ THE SECTOR + + 2559 ; HANDLE A PURE BLOCK + + 2559 A5EF INPURE: LDA SECTOR+LO + 255B 38 SEC ; STRIP OFF THE + 255C E5A4 SBC ZPURE ; VIRTUAL PRELOAD OFFSET + 255E 85EF STA SECTOR+LO + 2560 B002 BCS INP0 + 2562 C6F0 DEC SECTOR+HI + + 2564 06EF INP0: ASL SECTOR+LO ; MULTIPLY BY 2 + 2566 26F0 ROL SECTOR+HI ; FOR ATARI 128-BYTE SECTORS + + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 115 +--- DISK ACCESS: ATARI --- + + 2568 E6EF INC SECTOR+LO ; DISK "PURE" OFFSET IS 1 + 256A D002 BNE RDISK + 256C E6F0 INC SECTOR+HI + + 256E ; FALL THROUGH ... + + 256E ; ----------------- + 256E ; READ A DISK BLOCK + 256E ; ----------------- + + 256E ; ENTRY: TARGET SECTOR IN [SECTOR] + 256E ; TARGET DRIVE IN [DRIVE] + 256E ; PAGE TO READ IN [DBUFF] + 256E ; EXIT: CARRY CLEAR IF OKAY, SET IF NOT + + 256E A952 RDISK: LDA #$52 ; "READ" COMMAND + 2570 20A225 JSR DODISK ; GET DATA INTO [IOBUFF] + 2573 B02C BCS IOERR ; SOMETHING WRONG IF CARRY SET + + 2575 A000 LDY #0 ; MOVE DATA IN [IOBUFF] + 2577 B90004 RDSK0: LDA IOBUFF,Y ; TO [DBUFF] + 257A 91ED STA (DBUFF),Y + 257C C8 INY + 257D D0F8 BNE RDSK0 + + 257F F011 BEQ SNEXT ; UPDATE & RETURN + + 2581 ; ------------------ + 2581 ; WRITE A DISK BLOCK + 2581 ; ------------------ + + 2581 ; ENTRY: TARGET SECTOR IN [SECTOR] + 2581 ; TARGET DRIVE IN [DRIVE] + 2581 ; PAGE TO WRITE IN [DBUFF] + 2581 ; EXIT: CARRY CLEAR IF OKAY, SET IF NOT + + 2581 A000 PUTDSK: LDY #0 ; MOVE THE PAGE + 2583 B1ED PDSK0: LDA (DBUFF),Y ; AT [DBUFF] + 2585 990004 STA IOBUFF,Y ; INTO [IOBUFF] + 2588 C8 INY + 2589 D0F8 BNE PDSK0 + + 258B A957 LDA #$57 ; "WRITE" COMMAND + 258D 20A225 JSR DODISK + 2590 B00F BCS IOERR ; SOMETHING WRONG IF CARRY SET + + 2592 E6EE SNEXT: INC DBUFF+HI ; POINT TO NEXT RAM PAGE + + 2594 E6EB INC DBLOCK+LO ; NEXT V-PAGE + 2596 D002 BNE SNX0 + 2598 E6EC INC DBLOCK+HI + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 116 +--- DISK ACCESS: ATARI --- + + + 259A E6EF SNX0: INC SECTOR+LO ; AND NEXT SECTOR + 259C D002 BNE SNX1 + 259E E6F0 INC SECTOR+HI + + 25A0 18 SNX1: CLC ; CLEAR CARRY FOR SUCCESS + + 25A1 60 IOERR: RTS ; ELSE RETURN WITH CARRY SET + + 25A2 ; --------------- + 25A2 ; ACCESS THE DISK + 25A2 ; --------------- + + 25A2 ; ENTRY: [A] = $52 TO READ, $57 TO WRITE + 25A2 ; [DRIVE] = TARGET DRIVE (1 OR 2) + 25A2 ; [SECTOR] = TARGET SECTOR + 25A2 ; EXIT: CARRY CLEAR IF OKAY, SET IF NOT + + 25A2 8D0203 DODISK: STA DCOMND ; SET READ/WRITE COMMAND + + 25A5 A5F5 LDA DRIVE ; SPECIFY + 25A7 8D0103 STA DUNIT ; WHICH DRIVE TO USE + + 25AA ; CHECK VALIDITY OF SECTOR RANGE + + 25AA A6EF LDX SECTOR+LO ; GET LSB AND + 25AC A5F0 LDA SECTOR+HI ; MSB OF TARGET SECTOR + 25AE C902 CMP #$02 ; MSB WITHIN RANGE? + 25B0 9006 BCC RANOK ; OKAY IF < 2 + 25B2 D042 BNE RANERR ; RANGE ERROR IF > 2 + 25B4 E0D0 CPX #$D0 ; IF MSB WAS $02, IS LSB < $CF? + 25B6 B03E BCS RANERR ; ERROR IF NOT + + 25B8 8E0A03 RANOK: STX DAUX1 ; TELL SIO + 25BB 8D0B03 STA DAUX2 ; WHICH SECTOR TO USE + + 25BE A900 LDA #LOW IOBUFF ; POINT TO + 25C0 8D0403 STA DBUFLO ; THE BOTTOM HALF + 25C3 A904 LDA #HIGH IOBUFF ; OF [IOBUFF] + 25C5 8D0503 STA DBUFHI + + 25C8 2053E4 JSR DSKINV ; ACCESS 1ST HALF OF [IOBUFF] + 25CB AD0303 LDA DSTATS ; CHECK STATUS + 25CE 3024 BMI DERR ; ERROR IF NEGATIVE + + 25D0 E6EF INC SECTOR+LO ; POINT TO NEXT SECTOR + 25D2 D002 BNE DDSK0 + 25D4 E6F0 INC SECTOR+HI + + 25D6 A5EF DDSK0: LDA SECTOR+LO ; UPDATE [DAUX1/2] + 25D8 8D0A03 STA DAUX1 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT PAGE 117 +--- DISK ACCESS: ATARI --- + + 25DB A5F0 LDA SECTOR+HI + 25DD 8D0B03 STA DAUX2 + + 25E0 A980 LDA #LOW BUFTOP ; POINT TO TOP HALF + 25E2 8D0403 STA DBUFLO ; OF [IOBUFF] + 25E5 A904 LDA #HIGH BUFTOP + 25E7 8D0503 STA DBUFHI + + 25EA 2053E4 JSR DSKINV ; ACCESS TOP HALF OF [IOBUFF] + 25ED AD0303 LDA DSTATS ; CHECK STATUS + 25F0 3002 BMI DERR ; ERROR IF NEGATIVE + 25F2 18 CLC ; CLEAR CARRY FOR NO ERRORS + 25F3 60 RTS + + 25F4 38 DERR: SEC ; OR SET IT IF ERROR + 25F5 60 RTS + + 25F6 ; *** ERROR #12: DISK ADDRESS OUT OF RANGE *** + + 25F6 A90C RANERR: LDA #12 + 25F8 4CF91B JMP ZERROR + + END + + 25FB IF DEBUG + 25FB INCLUD BUGGER.ASM + 25FB ENDIF + + 0000 END + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. PAGE 118 +---- SYMBOL TABLE ---- + +A12VAL 0FDB COLOR4 02C8 DOFREQ 19B4 FLS1 1BC3 GTBT0 1861 +A2VAL 128D COMPAR 1295 DOGET 1368 FLS2 1BDB GTBT1 1868 +ABQUOT 14B3 CONCNT 00D0 DOM0 1E06 FLSL 1BD4 GTBT2 1871 +ABREM 14A5 CONIN 00D1 DOMINS 1DFB FLUSH 1C9D GTBT3 1883 +ABSDIV 148A CONOUT 00D2 DOPM 1E1D FLUSHW 1770 GTEXIT 1A5A +ABYTE 008A CONSOL D01F DORET 1401 FREEZE 1C2E GTRT0 2325 +ADEX 008B CONTOP 1A70 DOSCRL 1F07 FWL1 17D5 GTRT1 2332 +ALLSET 22E4 CONZST 1A5E DOSCRN 20A9 FWORDS 00B0 GTZ0 1A1C +ARG1 0082 COUT 1C89 DOSIB 1724 FWSUCC 1811 GVCALC 0F32 +ARG2 0084 CR1 1CF7 DOSIDE 2381 GAME 234E HI 0001 +ARG3 0086 CRSINH 02F0 DOSVEC 000A GAME2 2372 HILINE 210E +ARG4 0088 CSET0 1AA5 DOTIME 1DAC GAME2L 0009 HPOSM0 D004 +ATASCI 2126 CSET2 1AB7 DOUT 1FCA GAMEL 0024 HPOSP0 D000 +AUDC1 D201 CSHAPE 00F8 DOXM 1E1F GDRIVE 00F2 I 008E +AUDCTL D208 CSHIP 1AAA DOXOP 0DE4 GETBYT 184F ICAUX1 034A +AUDF1 D200 CTABLE 1AE4 DRIVE 00F5 GETDRV 2289 ICAUX2 034B +BACKSP 007E CTEST 1A95 DRVSET 229D GETDSK 2533 ICBADR 0344 +BACKUP 1F8D CZSL 1A61 DSIDE 235A GETKEY 1E7D ICBLEN 0348 +BADKEY 1E77 DAUX1 030A DSKERR 18F7 GETLNG 0E94 ICCOM 0342 +BADOP1 0E43 DAUX2 030B DSKINV E453 GETP1 1392 IN 00B4 +BADOP2 0E80 DBLOCK 00EB DSTATS 0303 GETP2 13A1 INCVAL 0FD4 +BADP 203A DBUFF 00ED DT0 1DD0 GETP3 13B4 INLOOP 1F66 +BADSAV 2420 DBUFHI 0305 DT1 1DD6 GETPB 13C4 INP0 2564 +BADVER 1124 DBUFLO 0304 DUMMY 0C0E GETPOS 2254 INPURE 2559 +BCALC 137B DC0 0D8D DUNIT 0301 GETPT1 13DA INPUT 1F5B +BLANK 1996 DC1 0D94 DVX 0FD3 GETPT2 13E9 INSM 221F +BLINK 00F6 DCOMND 0302 EAR0 1904 GETPT3 13EF INSML 0020 +BOOP 20BD DDSK0 25D6 EAR1 190E GETPW 13CA INVFLG 02B6 +BOOP0 20CB DEBUG 0000 EARLY 18FC GETRET 2320 IOBUFF 0400 +BOOT 0009 DECVAL 0FC8 EFIND 1762 GETSET 1A0A IOCHAR 00E2 +BREAK 1786 DEFAL 21B5 ENDLIN 1F97 GETSHT 0E90 IOERR 25A1 +BRKTBL 1797 DEFALL 0011 ENTRY 00C4 GETV 0E97 IRQEN D20E +BUFSAV 0A20 DEFNUM 21C2 ENUMB 1BF6 GETVAR 0EA8 IVX 0FDA +BUFTOP 0480 DERR 25F4 EOL 009B GETVR1 0EAD J 0090 +CEX 1C9C DGC 163E EQBAD 1531 GETVRG 0EC1 K 0092 +CH 02FC DIGCNT 163A EQOK 152E GETVRL 0EB1 LBUFF 0A80 +CHAR 1EEB DIGITS 00DB ERRM 1BE7 GETWRD 1925 LDPRE 0D51 +CHRTBL 1B33 DIRECT 1984 ERRML 0012 GETYES 22BB LENGTH 00DD +CIOV E456 DIVERR 14F2 ESIZE 00C8 GETZ1 1A31 LEX0 1FA2 +CLICK 1ED0 DIVEX 14B2 ETPEX 13D0 GETZ2 1A4C LEX1 1FAD +CLK0 1ED9 DIVIDE 1475 FALSE 0000 GETZ3 1A58 LEX2 1FB7 +CLK1 1EDE DLINE 1FC2 FBRK 17AD GETZCH 1A16 LFROM 00E5 +CLOSEP 203E DLIST 0C15 FINDW 17AF GKEY0 1E82 LINCNT 00E0 +CLS 20D3 DLS0 126C FIRST1 1140 GKEY1 1EA2 LINEX 1D19 +CLS0 20E2 DMACTL D400 FL0 1C9F GLOBAL 00AC LINLEN 00C2 +CNL 1AE6 DOB2 0F75 FL1 1CA9 GO 0E05 LINOUT 1D00 +CNOK 1AEF DOCALL 153D FL2 1CB4 GODIV 1497 LMARGN 0052 +COLCRS 0055 DODEF 21C6 FL3 1CBE GPOSIT 00F1 LMAX 00E1 +COLD 0C4F DODIS 0DF3 FLAGSU 1BA9 GPRIOR 026F LO 0000 +COLDST 0244 DODISK 25A2 FLEX 1785 GRACTL D01D LOCALS 0A00 +COLOR1 02C5 DOEQ 150A FLS0 1BC2 GS 1A11 LOCSAV 2499 + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. PAGE 119 +---- SYMBOL TABLE ---- + +LOGMAP 02B2 NUMBER 162E PG1 188D PUTBYT 0F06 RTNL 001B +LOLINE 20F6 NXTP1 140B PG2 189A PUTDSK 2581 SAV 23B9 +LOUT 1D08 NXTP2 141A PG3 18A1 PUTLSB 15D8 SAVDRI 223D +LREST 24FF NXTP3 141D PG4 18C3 PUTP1 15F3 SAVL 000E +LRU 00A2 OBJ1 1B63 PG5 18D5 PUTP2 1602 SAVRES 21A6 +LRUMAP 0900 OBJ2 1B6A PG6 18E0 PUTP3 1612 SAY1 1AFF +LSAVE 2441 OBJLOC 1B4D PG7 18EC PUTVAL 0F0C SAY2 1B0A +LTO 00E7 OBJTAB 00B2 PG8 18F1 PUTVLG 0F25 SAYSET 1AF4 +MDRI 2204 OFFHIS 252E PGOOD 12D2 PUTVLL 0F15 SBL 17A4 +MEMTOP 1C6A OFFLOS 2529 PLERR 161C PUTVR1 0F11 SCEX 12B1 +MIND 21EF OFFSET 00CC PLMRAM 0800 PYUCK 112D SCMP 12A7 +MINDL 0030 OFFSPL 207C PMAX 00A6 PZSTR 1942 SCOMP 129C +MINIT 14F7 OLDLEN 00DE PMBASE D407 PZTOP 194B SCREEN BC40 +MISSL 0B00 OLDLST BC20 PMG0 0C8D QSIGN 00D9 SCRIPT 00DF +MLOOP 0D7E OLDZSP 0095 PMG1 0C94 QUOT 00D3 SDLSTL 0230 +MORE 1D1A OP0 0E0A PNAME 1FD5 RANDOM 1C81 SDMCTL 022F +MOVMIN 1DE1 OP1 0E19 PNERR 1617 RANERR 25F6 SECTOR 00EF +MPC 009C OP1A 0E23 POKMSK 0010 RANOK 25B8 SET1 196E +MPCFLG 009F OP1B 0E2D POPVAL 0ECE RDISK 256E SET2 1976 +MPCH 009E OP1EX 0E34 PORTB D301 RDSK0 2577 SETDRV 229F +MPCL 009C OP2 0E48 POSIT 21D5 READL 16BF SETNP 0D0F +MPCM 009D OP2A 0E52 POSITL 000D READL2 170A SETPOS 226A +MPCPNT 00A0 OP2B 0E55 POSSET 2268 READL3 172C SETSTR 1930 +MPOS 21FA OP2C 0E64 PP1 2019 REMAIN 00D5 SETWRD 1916 +MRAND D20A OP2D 0E67 PPRINT 1FD9 REMVC1 11C2 SFLAG 1FD8 +MTEMP 00D7 OP2EX 0E71 PPX 1BA3 REMVC2 11D3 SHOVE 1968 +NARGS 0081 OPCODE 0080 PREDB 0F59 REMVEX 11DC SHOWIT 1F75 +NBL 178D OPEXT 0D9B PREDB1 0F7C RES 2453 SIB 179D +NBRKS 0006 OPT0 0FE4 PREDB2 0F87 RESL 0011 SIDE1 237B +NENTS 00C6 OPT1 1000 PREDB3 0F8E RESULT 00C1 SIDE2 237F +NEWLOG 20B1 OPT2 1020 PREDB5 0FAC RESZPC 2514 SIZEM D00C +NEWSET 199A OPTX 1052 PREDF 0F48 RET0 0F04 SKCTL D20F +NEXTPC 1819 OPX0 0DA6 PREDLB 0F69 RET1 120B SLD 0C36 +NEXTZ 1A7E OPX1 0DAC PREDNB 0F4D RET2 121F SLDL 0019 +NO 2243 OPX2 0DB6 PREDS 0F54 RETURN 230C SLINE 00E3 +NOBLIN 1EBA OPX3 0DC0 PRIL 108E RFLIP 14A1 SNEXT 2592 +NOL 0003 OPX4 0DDB PRLEN 00EA RIGHT 24CF SNX0 259A +NOMORE 1F7C OPXNXT 0DC7 PRNTDC 11DF RL0 16CD SNX1 25A0 +NOPS0 000E OUT 00BA PRNTN3 1656 RL1 16D2 SOURCE 00C0 +NOPS1 0010 OUTEOL 1F51 PRNTN4 165F RL2 16D9 SPACE 0020 +NOPS2 0019 OVER 0EF6 PROPB 1B76 RL3 16E2 SPCALC 2072 +NOPSX 000C PAGE 1885 PROPL 1B97 RLERR 16C9 SPL0 205A +NORAM 0D0A PAGE0 00A5 PROPN 1B92 RLEX 16D8 SPL1 2068 +NORM 178B PARAMS 2246 PROPNX 1B9F RLL 16E8 SPLEX 207B +NOSCRL 1F3A PATCH 185A PSET 00C9 ROWCRS 0054 SPLOFF 207F +NOT48K 1C7F PBAD 12BF PSHVAL 0EE4 RSIGN 00DA SPSTAT 00E4 +NOTSAT 22D8 PCALC 15DD PSTAT 00E9 RSING 2464 SRL0 1F0C +NPC0 182B PDC0 11F4 PTABH 0800 RSINGL 001B SRL1 1F27 +NPC1 1832 PDSK0 2583 PTABL 0700 RSPOS 2479 SRL2 1F30 +NPC2 183B PEX 2048 PTZ0 116A RTCLOK 0014 SRL3 1F34 +NPC3 184D PFINE 1149 PUSHXA 0EE8 RTN 2333 SRLP 23AD + + +AVOCET SYSTEMS 6502 CROSS-ASSEMBLER - VERSION 2.01C + +ZIP/6502 INFOCOM, INC. PAGE 120 +---- SYMBOL TABLE ---- + +SROOM 23A8 VARPUT 0EFB ZCALL3 15BC ZIP 0C00 ZPUTB 15D5 +ST0 0CCB VERNUM 1C5B ZCHAR 00CB ZJUMP 1237 ZPUTP 15F0 +ST1 0CD3 VERS 1C4C ZCHKSM 001C ZLENTH 001A ZQUIT 1C1F +ST2 0CDD VERSL 000F ZCODE 00A3 ZLESS 1263 ZRAND 166B +STAMP 00AA VEXIT 125C ZCR0 1CE6 ZLOC 114C ZREAD 169C +STATEX 1E27 VOCAB 00AE ZCRLF 1CC7 ZMLOOP 1440 ZREMOV 119B +STRING 1FCB VSUM 10C6 ZCRME 1CF1 ZMNEXT 1457 ZREST 247F +STX0 1E2B VSUM0 10D2 ZCRMP 1CD8 ZMOD 146B ZRET 11FA +STX1 1E31 VSUM2 10F0 ZCRUSH 1B0D ZMODE 0001 ZRFALS 1075 +STX2 1E40 VSUM3 10FC ZD0 1188 ZMOVE 1338 ZRSTAK 109F +SVING 23C7 WARM 0CAE ZDEC 1180 ZMUL 143D ZRT0 106C +SVINGL 0018 WARM1 0CC7 ZDIV 1461 ZMVEX 1361 ZRT1 106E +SVPOS 23D9 WARMEX 0D5D ZDLESS 1269 ZNEXT 1130 ZRTRUE 106A +SWAP 00AB WCALC 1377 ZENDLD 0004 ZNEXTP 1404 ZSAVE 23DF +TARGET 00A8 WCEX 0F47 ZEQUAL 1501 ZNOOP 0FC7 ZSCRIP 0010 +TDRIVE 00F4 WDRIV 21E2 ZEROPG 0080 ZOBJEC 000A ZSCRN 208E +TIMEFL 00DC WDRIVL 000D ZERR0 1BFB ZPAGE 00A7 ZSERIA 0012 +TOASC 1965 WNEXT 17F2 ZERR1 1BFD ZPC 0096 ZSET 132B +TOBOT0 20A4 WNX 17FD ZERR2 1C06 ZPCFLG 0099 ZSP 0094 +TOBOT1 20A7 WNX1 1808 ZERROR 1BF9 ZPCH 0098 ZSPLIT 2049 +TOPERM 19A8 WR0 24BD ZFCLR 1314 ZPCL 0096 ZSTAKH 0600 +TORES 1C31 WRDLEN 00C3 ZFIRST 1139 ZPCM 0097 ZSTAKL 0500 +TORESL 000D WRONG 24BB ZFLAG 00CD ZPCPNT 009A ZSTART 1C3E +TOTOP 209C WSTACK 2429 ZFSET 1301 ZPCSAV 240F ZSTEX 1941 +TPOSIT 00F3 XSIZE 0027 ZFSETP 12ED ZPOP 1694 ZSUB 1430 +TRUE 00FF YES 223F ZFWORD 0018 ZPRB 118D ZUSL 1D20 +TRY2 1516 YESL 0004 ZGET 1362 ZPRC 1621 ZVALUE 124B +TRY3 1522 YSIZE 0017 ZGETB 1372 ZPRD 11DD ZVER 10A5 +TSET 00CA ZADD 1423 ZGETP 138F ZPRI 1079 ZVERS 0000 +UDIV 14C1 ZBAND 12E1 ZGETPT 13D7 ZPRINT 123D ZVOCAB 0008 +UDLOOP 14CA ZBCOM 1253 ZGLOBA 000C ZPRN 1626 ZVR 10AC +UDNEXT 14E2 ZBEGIN 2600 ZGO 0006 ZPRR 1096 ZWORD 00CE +UNDER 0EDF ZBOR 12D5 ZGRTR 1277 ZPTSIZ 1158 ZZERO 1127 +USL0 1D46 ZBTST 12C2 ZID 0002 ZPURBT 000E +V2A1 0E85 ZCALL 1534 ZIGRTR 1282 ZPURE 00A4 +VALUE 008C ZCALL1 156B ZIN 12B2 ZPUSH 168D +VARGET 0E9F ZCALL2 1592 ZINC 1175 ZPUT 15C7 + +***** NO ERRORS DETECTED ***** diff --git a/atari/bugger.dip b/atari/bugger.dip new file mode 100644 index 0000000..c10e33f --- /dev/null +++ b/atari/bugger.dip @@ -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 + diff --git a/atari/bugger.src b/atari/bugger.src new file mode 100644 index 0000000..a333413 --- /dev/null +++ b/atari/bugger.src @@ -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 + diff --git a/atari/cold.dip b/atari/cold.dip new file mode 100644 index 0000000..3b7578e --- /dev/null +++ b/atari/cold.dip @@ -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 + diff --git a/atari/cold.src b/atari/cold.src new file mode 100644 index 0000000..b575bf0 --- /dev/null +++ b/atari/cold.src @@ -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 + diff --git a/atari/disk.src b/atari/disk.src new file mode 100644 index 0000000..c61c41c --- /dev/null +++ b/atari/disk.src @@ -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 + diff --git a/atari/dispatch.dip b/atari/dispatch.dip new file mode 100644 index 0000000..db3dd7e --- /dev/null +++ b/atari/dispatch.dip @@ -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 + diff --git a/atari/dispatch.src b/atari/dispatch.src new file mode 100644 index 0000000..1cf14cc --- /dev/null +++ b/atari/dispatch.src @@ -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 + diff --git a/atari/eq.dip b/atari/eq.dip new file mode 100644 index 0000000..55058e5 --- /dev/null +++ b/atari/eq.dip @@ -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 + diff --git a/atari/eq.src b/atari/eq.src new file mode 100644 index 0000000..5c6b2bd --- /dev/null +++ b/atari/eq.src @@ -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 + diff --git a/atari/grip.dip b/atari/grip.dip new file mode 100644 index 0000000..ad07699 --- /dev/null +++ b/atari/grip.dip @@ -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 + diff --git a/atari/gros.dip b/atari/gros.dip new file mode 100644 index 0000000..e8bb7cf --- /dev/null +++ b/atari/gros.dip @@ -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 + diff --git a/atari/hardeq.dip b/atari/hardeq.dip new file mode 100644 index 0000000..98a5911 --- /dev/null +++ b/atari/hardeq.dip @@ -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 + diff --git a/atari/hardeq.src b/atari/hardeq.src new file mode 100644 index 0000000..8458326 --- /dev/null +++ b/atari/hardeq.src @@ -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 + diff --git a/atari/io.dip b/atari/io.dip new file mode 100644 index 0000000..9e008de --- /dev/null +++ b/atari/io.dip @@ -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 + 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 FOR ADD + LSR MUSHFT ; SHIFT BIT 0 INTO + 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 + 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 + diff --git a/atari/iosubs.dip b/atari/iosubs.dip new file mode 100644 index 0000000..181987e --- /dev/null +++ b/atari/iosubs.dip @@ -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 + 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 + 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 + 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 + 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 + diff --git a/atari/iters.dip b/atari/iters.dip new file mode 100644 index 0000000..eb540f3 --- /dev/null +++ b/atari/iters.dip @@ -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: =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 + diff --git a/atari/machine.dip b/atari/machine.dip new file mode 100644 index 0000000..214a4d3 --- /dev/null +++ b/atari/machine.dip @@ -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 + diff --git a/atari/machine.src b/atari/machine.src new file mode 100644 index 0000000..df7a118 --- /dev/null +++ b/atari/machine.src @@ -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 + diff --git a/atari/main.dip b/atari/main.dip new file mode 100644 index 0000000..32e444f --- /dev/null +++ b/atari/main.dip @@ -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 + diff --git a/atari/main.src b/atari/main.src new file mode 100644 index 0000000..7d82652 --- /dev/null +++ b/atari/main.src @@ -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 + diff --git a/atari/objects.src b/atari/objects.src new file mode 100644 index 0000000..63a9585 --- /dev/null +++ b/atari/objects.src @@ -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 + diff --git a/atari/ops0.dip b/atari/ops0.dip new file mode 100644 index 0000000..9eea58a --- /dev/null +++ b/atari/ops0.dip @@ -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 + diff --git a/atari/ops0.src b/atari/ops0.src new file mode 100644 index 0000000..fcfe4b0 --- /dev/null +++ b/atari/ops0.src @@ -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 + diff --git a/atari/ops1.dip b/atari/ops1.dip new file mode 100644 index 0000000..d36d552 --- /dev/null +++ b/atari/ops1.dip @@ -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 + diff --git a/atari/ops1.src b/atari/ops1.src new file mode 100644 index 0000000..7cdd795 --- /dev/null +++ b/atari/ops1.src @@ -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 + diff --git a/atari/ops2.dip b/atari/ops2.dip new file mode 100644 index 0000000..6277f75 --- /dev/null +++ b/atari/ops2.dip @@ -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 + diff --git a/atari/ops2.src b/atari/ops2.src new file mode 100644 index 0000000..7d3be0a --- /dev/null +++ b/atari/ops2.src @@ -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 + diff --git a/atari/opsx.dip b/atari/opsx.dip new file mode 100644 index 0000000..1ef3dae --- /dev/null +++ b/atari/opsx.dip @@ -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 + diff --git a/atari/opsx.src b/atari/opsx.src new file mode 100644 index 0000000..35fccc4 --- /dev/null +++ b/atari/opsx.src @@ -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 + + \ No newline at end of file diff --git a/atari/paging.dip b/atari/paging.dip new file mode 100644 index 0000000..3904e43 --- /dev/null +++ b/atari/paging.dip @@ -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 + +NPC2: LDA GPC0 ; PUT BIT 0 INTO + 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 + +GTBT2: LDA VPC0 ; PUT BIT 0 INTO + 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 + diff --git a/atari/paging.src b/atari/paging.src new file mode 100644 index 0000000..2de85ae --- /dev/null +++ b/atari/paging.src @@ -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 + + \ No newline at end of file diff --git a/atari/read.src b/atari/read.src new file mode 100644 index 0000000..5365ed6 --- /dev/null +++ b/atari/read.src @@ -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 + diff --git a/atari/save.dip b/atari/save.dip new file mode 100644 index 0000000..54ec3eb --- /dev/null +++ b/atari/save.dip @@ -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 + diff --git a/atari/sound.dip b/atari/sound.dip new file mode 100644 index 0000000..b0d70bb --- /dev/null +++ b/atari/sound.dip @@ -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 + diff --git a/atari/subs.dip b/atari/subs.dip new file mode 100644 index 0000000..9aac64e --- /dev/null +++ b/atari/subs.dip @@ -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 + diff --git a/atari/subs.src b/atari/subs.src new file mode 100644 index 0000000..b2fec65 --- /dev/null +++ b/atari/subs.src @@ -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 + diff --git a/atari/warm.dip b/atari/warm.dip new file mode 100644 index 0000000..7e55153 --- /dev/null +++ b/atari/warm.dip @@ -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 + diff --git a/atari/warm.src b/atari/warm.src new file mode 100644 index 0000000..0af8507 --- /dev/null +++ b/atari/warm.src @@ -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 + diff --git a/atari/zdos.src b/atari/zdos.src new file mode 100644 index 0000000..9f1e344 --- /dev/null +++ b/atari/zdos.src @@ -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 + diff --git a/atari/zip.src b/atari/zip.src new file mode 100644 index 0000000..fc9cb81 --- /dev/null +++ b/atari/zip.src @@ -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 + diff --git a/atari/zstring.src b/atari/zstring.src new file mode 100644 index 0000000..6045eb9 --- /dev/null +++ b/atari/zstring.src @@ -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 + diff --git a/basic/lptset.bas b/basic/lptset.bas new file mode 100644 index 0000000..4edd554 Binary files /dev/null and b/basic/lptset.bas differ diff --git a/basic/nsend.bas b/basic/nsend.bas new file mode 100644 index 0000000..bcddee3 Binary files /dev/null and b/basic/nsend.bas differ diff --git a/basic/send-ap.bas b/basic/send-ap.bas new file mode 100644 index 0000000..6dcef3f Binary files /dev/null and b/basic/send-ap.bas differ diff --git a/basic/send.bas b/basic/send.bas new file mode 100644 index 0000000..cd9942e Binary files /dev/null and b/basic/send.bas differ diff --git a/basic/test.bas b/basic/test.bas new file mode 100644 index 0000000..9a02e29 Binary files /dev/null and b/basic/test.bas differ diff --git a/basic/tftp.bas b/basic/tftp.bas new file mode 100644 index 0000000..6cc927e Binary files /dev/null and b/basic/tftp.bas differ diff --git a/basic/tom.bas b/basic/tom.bas new file mode 100644 index 0000000..3342c1d Binary files /dev/null and b/basic/tom.bas differ diff --git a/basic/tsend.bas b/basic/tsend.bas new file mode 100644 index 0000000..bb46824 Binary files /dev/null and b/basic/tsend.bas differ diff --git a/basic/xzip.bin b/basic/xzip.bin new file mode 100644 index 0000000..91b624f Binary files /dev/null and b/basic/xzip.bin differ diff --git a/c-128/ezip/_read.me b/c-128/ezip/_read.me new file mode 100644 index 0000000..40595f1 --- /dev/null +++ b/c-128/ezip/_read.me @@ -0,0 +1,18 @@ + +******* Directory Update and Source File Archive Record ****** + + Date of Last Change Version Letter Who Made the Change + ___________________ _____________ ____________________ + +1) 5/5/86 A (EZIP) Le +2) 12/10/86 B (regular EZIP) Le +2a) 12/10/86 B (CBD-EZIP) Le + (note: only 3 files are different for CBD-EZIP - the version of Ezip that + can be used with Lzip on the same disk with one game split for the + Lzip : Ezip-128.CBD, Hardeq.CBD, Xpaging.CBD. Only those 3 files are + included for the CBD version - MAKE SURE TO ALWAYS CHANGE BOTH SOURCES + AND PROGRAM VERSIONS NOT ONLY THE REGULAR VERSION!) + (NOTE: CBD EZIP scrapped when Lzip scrapped (1/87) kept here jic) +3) 11/13/87 E (both) JDA + This one is both CBD and normal (it uses preload + information in the game) diff --git a/c-128/ezip/boot.asm b/c-128/ezip/boot.asm new file mode 100644 index 0000000..9bc6940 --- /dev/null +++ b/c-128/ezip/boot.asm @@ -0,0 +1,443 @@ + PL 58 ; PAGE LENGTH OF PRINTER + +DEBUG EQU $00 ; 0 = NO, 1 = YES +ZEROPG EQU $03 +ZPGTOP EQU $8F +COLD1 EQU $1200 ; WHERE TO ENTER THE REST OF THE CODE + + INCLUDE EQ.ASM + INCLUDE HARDEQ.ASM + + PAGE + STTL "--- MACHINE AUTOBOOT: CBM64 ---" + + ; ------------------ + ; THE VERY BEGINNING + ; ------------------ + + ORG EZIP + + ; 'CBM' IS AUTOBOOT RECOGNITION CODE + ; $00,$0C = TELLS AUTOBOOT TO READ REST IN STARTING AT $C00 + ; $00,$02 = READ IN 2 PAGES, $00 = NO DISK CODE, $00 = NO FILE NAME + + DB 'C','B','M' + DB $00,$0C,$00,$02,$00,$00 + + LDA COLMODE ; 1ST MAKE SURE IN 40 COLUMN MODE + CMP #$80 ; TO DISPLAY 80 COL MONITOR NEEDED MSG + BNE OK40 + JSR SWAPPER ; INTO 40 COL MODE +OK40: LDA #$0B ; DARK GRAY + STA EXTCOL ; BORDER + STA BGCOLO ; BACKGRND + STA FRCOLO ; FORGRND COLOR REG + + LDY #>COLRAM + STY I+HI + LDY #BI0 ; "I0:" + LDA #BI0L ; LENGTH OF FILENAME + JSR RSETNAM + + JMP ROPEN ; OPEN THE DISK (CARRY CLEAR IF OK) + + ; -------------------------- + ; OPEN DIRECT ACCESS CHANNEL + ; -------------------------- + +BPOUND: DB "#" +BPNDL EQU $-BPOUND + +BAOPEN: LDA #0 +; STA SPENA ; SHUT OFF CURSOR DMA + + JSR BACLOSE ; CLOSE FIRST + + LDA #2 ; D/A CHANNEL ID + TAY ; SECONDARY ID + LDX DRIVE + JSR RSETLFS + + LDX #BPOUND ; "#" + LDA #BPNDL + JSR RSETNAM + + JMP ROPEN ; OPEN CHANNEL (CARRY CLEAR IF OK) + + ; ------------------- + ; CLOSE CURRENT DRIVE + ; ------------------- + +BDCLOSE: LDA #15 ; CLOSE COMMAND CHANNEL + JSR RCLOSE + + ; FALL THROUGH ... + + ; --------------------- + ; CLOSE THE D/A CHANNEL + ; --------------------- + +BACLOSE: LDA #2 ; AND THE + JMP RCLOSE ; DATA CHANNEL + + ; ---------------- + ; DIVIDE [A] BY 10 + ; ---------------- + + ; EXIT: QUOTIENT IN [X], REMAINDER IN [A] + +BDIV10: LDX #0 ; START WITH ZERO QUOTIENT + +BD10L: CMP #10 ; IF DIVISOR < 10, + BCC BD10EX ; WE'RE DONE + SBC #10 ; ELSE SUBTRACT ANOTHER 10 + INX ; UPDATE QUOTIENT + BNE BD10L ; BRANCH ALWAYS + +BD10EX: RTS + + ; --------------- + ; SEND Ux COMMAND + ; --------------- + + ; ENTRY: ASCII "1" OR "2" IN [A] + +BCOMLIN: DB "U" +BDCOMM: DB "*" + DB ":2,0," +BDTRAK: DB "***," +BDSECT: DB "***" + DB EOL +BCMLL EQU $-BCOMLIN + +BSENDU: STA BDCOMM ; INSERT COMMAND ("1" OR "2") IN STRING + + ; CONVERT [TRACK] AND [SECTOR] TO ASCII IN [COMLIN] + + LDA TRACK + LDY #2 +BTCON: JSR BDIV10 ; DIVIDE BY 10 + ORA #'0' ; CONVERT TO ASCII + STA BDTRAK,Y ; STORE INTO STRING + TXA ; GET QUOTIENT INTO [A] + DEY ; ZERO-FILL USUSED BYTES + BPL BTCON + + LDA SECTOR ; SAME FOR SECTOR ID + LDY #2 +BSCON: JSR BDIV10 + ORA #'0' + STA BDSECT,Y + TXA + DEY + BPL BSCON + + ; SEND COMMAND + + JSR RCLRCHN + LDX #15 ; OUTPUT TO THE + JSR RCHKOUT ; COMMAND CHANNEL + BCS BUEX ; EXIT W/CARRY SET IF ERROR + + LDY #0 +BSCM0: LDA BCOMLIN,Y ; SEND THE COMMAND LINE + JSR RCHROUT ; TO THE DRIVE CHANNEL + INY ; A BYTE AT A TIME + CPY #BCMLL + BCC BSCM0 + CLC ; SUCCESS! +BUEX: RTS + + ; ---------------------- + ; SET THE BUFFER POINTER + ; ---------------------- + +BBPLINE: DB "B-P:2,0" + DB EOL +BBPLL EQU $-BBPLINE + +BSETBP: JSR RCLRCHN + LDX #15 ; OUTPUT TO + JSR RCHKOUT ; COMMAND CHANNEL + BCS BBEX ; CARRY SET IF ERROR + + LDY #0 +BSBPL: LDA BBPLINE,Y + JSR RCHROUT + INY + CPY #BBPLL + BCC BSBPL + CLC +BBEX: RTS + + ; ------------------------------ + ; READ/WRITE A BLOCK TO [IOBUFF] + ; ------------------------------ + + ; ENTRY: [TRACK] = TRACK # (1-35) + ; [SECTOR] = SECTOR # (0-15) + ; [DRIVE] = DRIVE ID (8 OR 9) + ; CARRY CLEAR TO READ, CARRY SET TO WRITE + +BDISK: BCS BDWRITE ; WRITE IF CARRY SET + + ; READ A DISK BLOCK + + JSR BAOPEN ; OPEN THE ACCESS CHANNEL + BCS BBADISK + + LDA #'1' ; SEND A "U1" COMMAND + JSR BSENDU + BCS BBADISK ; CARRY SET IF ERROR + + JSR BSETBP ; SET THE BUFFER POINTER + BCS BBADISK ; CARRY SET IF ERROR + + JSR RCLRCHN + LDX #2 ; INPUT FROM + JSR RCHKIN ; DATA CHANNEL + BCS BBADISK + + LDY #0 +BREAD1: JSR RCHRIN ; GET A BYTE + STA IOBUFF,Y ; MOVE TO I/O BUFFER + INY + BNE BREAD1 ; DO 256 BYTES + + BEQ BSHUTD ; THEN EXIT + + ; WRITE A BLOCK + +BDWRITE: JSR BAOPEN ; OPEN THE ACCESS CHANNEL + BCS BBADISK + + JSR BSETBP ; SET THE BUFFER POINTER + BCS BBADISK ; CARRY SET IF ERROR + + JSR RCLRCHN + LDX #2 ; OUTPUT TO + JSR RCHKOUT ; DATA CHANNEL + BCS BBADISK ; CARRY SET IF ERROR + + LDY #0 +BWRITE1: LDA IOBUFF,Y ; SEND CONTENTS OF [IOBUFF] + JSR RCHROUT ; TO THE DRIVE + INY + BNE BWRITE1 ; WRITE 256 BYTES + + LDA #'2' ; ISSUE A "U2" COMMAND + JSR BSENDU + BCS BBADISK ; CARRY SET IF ERROR + +BSHUTD: JSR RREADST + AND #%10000011 + BNE BBADISK + + JSR RCLRCHN + CLC ; CARRY CLEAR FOR SUCCESS + RTS + +BBADISK: JSR RCLRCHN + SEC + RTS ; OR SET IF ERROR + + + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00 + + ; MARKER + + END diff --git a/c-128/ezip/boot.cbd b/c-128/ezip/boot.cbd new file mode 100644 index 0000000..27e4260 --- /dev/null +++ b/c-128/ezip/boot.cbd @@ -0,0 +1,435 @@ + PAGE + SBTTL "--- MACHINE AUTOBOOT: CBM64 ---" + + ; ------------------ + ; THE VERY BEGINNING + ; ------------------ + + ORG EZIP + + ; 'CBM' IS AUTOBOOT RECOGNITION CODE + ; $00,$0C = TELLS AUTOBOOT TO READ REST IN STARTING AT $C00 + ; $00,$02 = READ IN 2 PAGES, $00 = NO DISK CODE, $00 = NO FILE NAME + + DB 'C','B','M' + DB $00,$0C,$00,$02,$00,$00 + + LDA COLMODE ; 1ST MAKE SURE IN 40 COLUMN MODE + CMP #$80 ; TO DISPLAY 80 COL MONITOR NEEDED MSG + BNE OK40 + JSR SWAPPER ; INTO 40 COL MODE +OK40: LDA #$0B ; DARK GRAY + STA EXTCOL ; BORDER + STA BGCOLO ; BACKGRND + STA FRCOLO ; FORGRND COLOR REG + + LDY #HIGH COLRAM + STY I+HI + LDY #LOW COLRAM + STY I+LO + + LDY #0 ; SET COLOR RAM TO + LDX #4 +CLR40: STA (I),Y ; DARK GRAY + INY + BNE CLR40 + INC I+HI + DEX + BNE CLR40 ; ALL 4 PAGES + + LDX #0 + LDY #7 +NEEDLP: LDA #$0F ; LIGHT GRAY CHARS FOR MSG + STA $DB48,Y ; SET THOSE BYTES IN COLOR RAM + LDA NEED,X ; SHOW MSG - PLACE DIRECTLY ON SCREEN + STA $748,Y ; LINE 20, COLUMN 8 + INY + INX + CPX #NEEDL + BCC NEEDLP + + JSR SWAPPER ; SET TO 80 COL DISPLAY + + +BOOT0: LDA #%00000101 ; 4K SHARED RAM, LOW ($00-$10) + STA RCR + LDA #%01001110 ; SYS ROM, IO, TO BANK 1 + STA CR ; THIS IS TO LOAD EZIP INTO BANK 1 + ; DO IT HERE SO IN JUMP TIME IT WILL + ; TAKE EFFECT (NOT IMMEDIATE) + + JMP COLD ; THIS PAGE WILL BECOME IOBUFF + ; SO THIS JUMP WILL GET THINGS STARTED + ; AND GET US OUT OF HERE AS THIS BOOT + ; STUFF WILL DISSAPEAR + +NEED: DB 56,48,32,03,15,12,21,13,14,32,13,15,14,09,20,15,18,32 + DB 18,05,17,21,09,18,05,04 ; "80 COLUMN MONITOR REQUIRED" +NEEDL EQU $-NEED + + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + + + ; --------- + ; COLDSTART + ; --------- + + ; THERE IS NOT ENOUGH ROOM IN BANK0 FOR THE PRELOAD AS WE CAN'T START + ; BEFORE $1C00 OR USE PAST $BFFF DUE TO THE KERNAL USE OF MEMORY + ; SO: THIS RTN WILL LOAD THE ACTUAL INTERPRETER INTO BANK1 AND BANK1 + ; WILL BE USED AS THE MAIN BANK WITH BANK0 BEING USED AS THE SECOND, + ; AUXILIARY BANK. IN ORDER TO USE BANK0 AND THE KERNAL THE FIRST 4K + ; OF MEMORY IS BEING SET ASIDE AS COMMON MEMORY, TREATED AS BANK0 + ; SPACE BUT ABLE TO READ/WRITE TO BOTH BANKS. AT $400 IN THIS COMMON + ; RAM WILL RESIDE THE RTNS TO READ/WRITE TO EITHER BANK AND TO SWITCH + ; TO BANK0 FOR KERNAL USE AND BACK AGAIN. AS SOON AS THE INTERPRETER + ; HAS BEEN LOADED BANK1 WILL BE SET TO ALL RAM, THE START OF THE + ; INTERPRETER WILL BE JUMPED TO AND THE AREA THIS CODE IS IN WILL + ; BE USED AS BUFFER SPACE. + + +COLD: LDA #8 ; TURN DRIVE ON + JSR BDOPEN + + LDA #1 ; SET TO READ IN COMMON CODE 1ST + STA TRACK + LDA #3 ; IT STARTS ON SECTOR 3 + STA SECTOR ; AFTER ALL THIS LOADING SHIT + LDA #4 + STA DBUFF+HI ; LOAD IT AT $400 + LDA #0 + STA DBUFF+LO + + JSR GETONE ; GET 2 SECTORS OF CODE + JSR GETONE ; COMMON TO BOTH BANKS + + LDA #$12 ; THEN MOVE IN THE REST + STA DBUFF+HI ; OF EZIP INTO BANK1 + +BIGLOOP: JSR GETONE + LDA DBUFF+HI + CMP #MAINSTRT ; THIS IS END OF EZIP, START OF GAME + BNE BIGLOOP + + ; INITIALIZE THE SOUND SYSTEM (WHILE STILL ACCESSIBLE) + + LDX #$1C ; CLEAR + LDA #0 ; ALL +CLD0: STA FRELO1,X ; SID REGISTERS + DEX + BPL CLD0 + + LDA #2 ; SET VOICE #1 + STA PWLO1 ; PULSE WIDTH + LDA #8 ; FOR A + STA PWHI1 ; 50% DUTY CYCLE + + LDA #%10000000 ; DISABLE OUTPUT + STA SIGVOL ; FROM VOICE #3 + + LDA #$EE + STA FRELO3 ; SET VOICE #3 TO + STA FREHI3 ; AN AMUSING FREQUENCY + + LDA #%10000000 ; SPECIFY NOISY WAVEFORM + STA VCREG3 ; FOR RANDOMNESS + + LDA #%01111111 + STA CR ; SET FOR NORMAL USE NOW + JMP COLD1 ; AND GO START THE THING FOR REAL + + +GETONE: CLC + JSR BDISK + BCS DKERR ; OOPS + + LDY #0 +LOOP: LDA IOBUFF,Y + STA (DBUFF),Y + INY + BNE LOOP + + INC SECTOR ; NEXT SECTOR SO READY + LDY TRACK ; AS VARIABLE # OF SECTORS + LDA SECTOR ; PER TRACK, CHECK AGAINST + CMP TRKTAB,Y ; TBL WITH SIZE PER TRACK + BCC SECOK + INC TRACK + LDA #0 + STA SECTOR + +SECOK: INC DBUFF+HI + RTS + + ; DON'T BOTHER SKIPPING SECTOR 0 ON TRK 18 & 20 + ; AS DON'T ACCESS THOSE TRACKS IN THIS CODE + +TRKTAB: DB 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21 + DB 19,19,19,19,19,19,19 + DB 18,18,18,18,18,18 + DB 17,17,17,17,17 + + ; *** ERROR #14: DRIVE ACCESS *** + +DKERR: LDY #DRVML ; AS IT'S THE START, TELL THEM WHAT'S WRONG +DKERR1: LDA DRVMSG,X + JSR RCHROUT + INX + DEY + BNE DKERR1 + JMP $ ; HANG AS WOULD REBOOT WITH SAME PROBLEM + + +DRVMSG: DB "DRIVE ACCESS ERROR" + DB EOL +DRVML EQU $-DRVMSG + + + PAGE + SBTTL "--- DISK ACCESS FOR BOOT: C-128 ---" + + ; NOTE: THIS IS SAME AS OTHER DISK ACCESS CODE + ; BUT IS LOCATED SO BOOT CODE CAN USE IT TO READ + ; INTERPRETER OFF THE DISK AND LOCATE IT CORRECTLY + + ; -------------- + ; OPEN DRIVE [A] + ; -------------- + + ; ENTRY: DISK ID (8 OR 9 BINARY) IN [A] + +BI0: DB "I0" +BI0L EQU $-BI0 + +BDOPEN: STA DRIVE ; SAVE DRIVE ID HERE + JSR BDCLOSE ; CLOSE COMMAND & DATA CHANNELS + + LDA #15 ; LOGICAL FILE # + TAY ; SECONDARY ADDRESS + LDX DRIVE ; DEVICE # (8 OR 9) + JSR RSETLFS ; SET UP LOGICAL FILE + + LDX #LOW BI0 ; POINT TO FILENAME + LDY #HIGH BI0 ; "I0:" + LDA #BI0L ; LENGTH OF FILENAME + JSR RSETNAM + + JMP ROPEN ; OPEN THE DISK (CARRY CLEAR IF OK) + + ; -------------------------- + ; OPEN DIRECT ACCESS CHANNEL + ; -------------------------- + +BPOUND: DB "#" +BPNDL EQU $-BPOUND + +BAOPEN: LDA #0 +; STA SPENA ; SHUT OFF CURSOR DMA + + JSR BACLOSE ; CLOSE FIRST + + LDA #2 ; D/A CHANNEL ID + TAY ; SECONDARY ID + LDX DRIVE + JSR RSETLFS + + LDX #LOW BPOUND ; POINT TO FILENAME + LDY #HIGH BPOUND ; "#" + LDA #BPNDL + JSR RSETNAM + + JMP ROPEN ; OPEN CHANNEL (CARRY CLEAR IF OK) + + ; ------------------- + ; CLOSE CURRENT DRIVE + ; ------------------- + +BDCLOSE: LDA #15 ; CLOSE COMMAND CHANNEL + JSR RCLOSE + + ; FALL THROUGH ... + + ; --------------------- + ; CLOSE THE D/A CHANNEL + ; --------------------- + +BACLOSE: LDA #2 ; AND THE + JMP RCLOSE ; DATA CHANNEL + + ; ---------------- + ; DIVIDE [A] BY 10 + ; ---------------- + + ; EXIT: QUOTIENT IN [X], REMAINDER IN [A] + +BDIV10: LDX #0 ; START WITH ZERO QUOTIENT + +BD10L: CMP #10 ; IF DIVISOR < 10, + BCC BD10EX ; WE'RE DONE + SBC #10 ; ELSE SUBTRACT ANOTHER 10 + INX ; UPDATE QUOTIENT + BNE BD10L ; BRANCH ALWAYS + +BD10EX: RTS + + ; --------------- + ; SEND Ux COMMAND + ; --------------- + + ; ENTRY: ASCII "1" OR "2" IN [A] + +BCOMLIN: DB "U" +BDCOMM: DB "*" + DB ":2,0," +BDTRAK: DB "***," +BDSECT: DB "***" + DB EOL +BCMLL EQU $-BCOMLIN + +BSENDU: STA BDCOMM ; INSERT COMMAND ("1" OR "2") IN STRING + + ; CONVERT [TRACK] AND [SECTOR] TO ASCII IN [COMLIN] + + LDA TRACK + LDY #2 +BTCON: JSR BDIV10 ; DIVIDE BY 10 + ORA #'0' ; CONVERT TO ASCII + STA BDTRAK,Y ; STORE INTO STRING + TXA ; GET QUOTIENT INTO [A] + DEY ; ZERO-FILL USUSED BYTES + BPL BTCON + + LDA SECTOR ; SAME FOR SECTOR ID + LDY #2 +BSCON: JSR BDIV10 + ORA #'0' + STA BDSECT,Y + TXA + DEY + BPL BSCON + + ; SEND COMMAND + + JSR RCLRCHN + LDX #15 ; OUTPUT TO THE + JSR RCHKOUT ; COMMAND CHANNEL + BCS BUEX ; EXIT W/CARRY SET IF ERROR + + LDY #0 +BSCM0: LDA BCOMLIN,Y ; SEND THE COMMAND LINE + JSR RCHROUT ; TO THE DRIVE CHANNEL + INY ; A BYTE AT A TIME + CPY #BCMLL + BCC BSCM0 + CLC ; SUCCESS! +BUEX: RTS + + ; ---------------------- + ; SET THE BUFFER POINTER + ; ---------------------- + +BBPLINE: DB "B-P:2,0" + DB EOL +BBPLL EQU $-BBPLINE + +BSETBP: JSR RCLRCHN + LDX #15 ; OUTPUT TO + JSR RCHKOUT ; COMMAND CHANNEL + BCS BBEX ; CARRY SET IF ERROR + + LDY #0 +BSBPL: LDA BBPLINE,Y + JSR RCHROUT + INY + CPY #BBPLL + BCC BSBPL + CLC +BBEX: RTS + + ; ------------------------------ + ; READ/WRITE A BLOCK TO [IOBUFF] + ; ------------------------------ + + ; ENTRY: [TRACK] = TRACK # (1-35) + ; [SECTOR] = SECTOR # (0-15) + ; [DRIVE] = DRIVE ID (8 OR 9) + ; CARRY CLEAR TO READ, CARRY SET TO WRITE + +BDISK: BCS BDWRITE ; WRITE IF CARRY SET + + ; READ A DISK BLOCK + + JSR BAOPEN ; OPEN THE ACCESS CHANNEL + BCS BBADISK + + LDA #'1' ; SEND A "U1" COMMAND + JSR BSENDU + BCS BBADISK ; CARRY SET IF ERROR + + JSR BSETBP ; SET THE BUFFER POINTER + BCS BBADISK ; CARRY SET IF ERROR + + JSR RCLRCHN + LDX #2 ; INPUT FROM + JSR RCHKIN ; DATA CHANNEL + BCS BBADISK + + LDY #0 +BREAD1: JSR RCHRIN ; GET A BYTE + STA IOBUFF,Y ; MOVE TO I/O BUFFER + INY + BNE BREAD1 ; DO 256 BYTES + + BEQ BSHUTD ; THEN EXIT + + ; WRITE A BLOCK + +BDWRITE: JSR BAOPEN ; OPEN THE ACCESS CHANNEL + BCS BBADISK + + JSR BSETBP ; SET THE BUFFER POINTER + BCS BBADISK ; CARRY SET IF ERROR + + JSR RCLRCHN + LDX #2 ; OUTPUT TO + JSR RCHKOUT ; DATA CHANNEL + BCS BBADISK ; CARRY SET IF ERROR + + LDY #0 +BWRITE1: LDA IOBUFF,Y ; SEND CONTENTS OF [IOBUFF] + JSR RCHROUT ; TO THE DRIVE + INY + BNE BWRITE1 ; WRITE 256 BYTES + + LDA #'2' ; ISSUE A "U2" COMMAND + JSR BSENDU + BCS BBADISK ; CARRY SET IF ERROR + +BSHUTD: JSR RREADST + AND #%10000011 + BNE BBADISK + + JSR RCLRCHN + CLC ; CARRY CLEAR FOR SUCCESS + RTS + +BBADISK: JSR RCLRCHN + SEC + RTS ; OR SET IF ERROR + + + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00,00 + + ; MARKER + + END diff --git a/c-128/ezip/bugger.asm b/c-128/ezip/bugger.asm new file mode 100644 index 0000000..eaddc09 --- /dev/null +++ b/c-128/ezip/bugger.asm @@ -0,0 +1,221 @@ + PAGE + STTL "--- DEBUGGER: EZIP C128 ---" + + ; -------------- + ; C128 DEBUGGER + ; -------------- + + ; ENTRY: BREAKPOINT ID IN [A] + +BLINE: DB "B: OP: PC: S: V: 1: 2: 3: 4: 5: 6: 7: 8: 9: " + DB EOL +BLINL EQU $-BLINE + + +DOBUG: ;RTS + + STA DHOLD + +; LDA SHFLAG +; AND #%00000100 ; CTRL KEY PRESSED? +; BEQ TEST2 ; CONTINUE IF NOT +; RTS ; AND EXIT + +TEST2: ;LDA DHOLD + ;CMP #0 + ;BEQ BUGIT + ;RTS + + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + +BUGIT: +; SEC +; JSR PLOT ; GET GAME POSITION +; STX OLDX +; STY OLDY +; LDX #23 +; LDY #0 +; CLC +; JSR PLOT ; AND SET DUBUG ONE + + LDA DHOLD + LDX #2 ; INIT "CURSOR" + 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 BLINE,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 [ZSP] + LDA ZSP + JSR HEX + + LDX #29 ; CURSOR FOR [MPC] + LDA MPCH + JSR HEX + LDA MPCM + JSR HEX + LDA MPCL + JSR HEX + + LDX #38 + LDA WBOTM +; LDA BONE + JSR HEX + + LDX #43 + LDA WTOP +; LDA BTWO + JSR HEX + + LDX #48 + LDA TOP +; LDA BTHREE + JSR HEX + + LDX #53 + LDA BFOUR + JSR HEX + + LDX #58 + LDA BFIVE + JSR HEX + + LDX #63 + LDA BSIX + JSR HEX + + LDX #68 + LDA BSEVEN + JSR HEX + + LDX #73 + LDA BEIGHT + JSR HEX + + LDX #78 + LDA BNINE + JSR HEX + +PPP: LDX #0 +DBG1: LDA BLINE,X ; PRINT DEBUGGER TEXT + JSR CHROUT + INX + CPX #BLINL + BCC DBG1 + + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + + LDA #0 + STA NDX ; CLEAR +; JSR GETIN +; CMP #0 +; BEQ WOK ; IF NO KEY, CONTINUE +WAITT: JSR GETIN ; NOW WAIT FOR ANOTHER KEY + CMP #0 + BEQ WAITT + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP +WOK: NOP + + CMP #'Q' + BNE LLETEX + BRK + +LLETEX: +; LDX OLDX +; LDY OLDY +; CLC +; JSR PLOT ; NOW BACK TO OUR REGULARLY SCHEDULED PROGRAM + 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 BLINE,X + INX + RTS + +HCHARS: DB "0123456789ABCDEF" + +BONE: DB 0 +BTWO: DB 0 +BTHREE: DB 0 +BFOUR: DB 0 +BFIVE: DB 0 +BSIX: DB 0 +BSEVEN: DB 0 +BEIGHT: DB 0 +BNINE: DB 0 +DHOLD: DB 0 + + END + diff --git a/c-128/ezip/cold.asm b/c-128/ezip/cold.asm new file mode 100644 index 0000000..668df6b --- /dev/null +++ b/c-128/ezip/cold.asm @@ -0,0 +1,57 @@ + PAGE + STTL "--- MACHINE COLDSTART: CBM128 ---" + + ORG $1200 + + ; --------- + ; COLDSTART + ; --------- + +COLD1: LDA #%00001110 ; SET UP CONFIGURATIONS FOR + STA BANK0 ; PROPER USE OF MEMORY + LDA #%01111111 ; SAVING TO BE USED AS NEEDED + STA BANK1 + + LDA #$0E + JSR CHROUT ; USE UPPER/LOWER CHARS + LDA #$80 ; PROHIBIT FURTHER + STA MODE ; CHARSET CHANGES + + LDA #0 + JSR SETMSG ; DISABLE KERNAL MESSAGES + JSR CLALL ; CLOSE EVERYTHING + + JMP WARM1 + + ; --------------- + ; WARMSTART ENTRY + ; --------------- + +SLOAD: DB "The story is loading ..." + DB EOL +SLOADL EQU $-SLOAD + +WARM1: CLD + LDX #$FF + TXS ; RESET MACHINE STACK + + LDA #CLS ; CLEAR SCREEN, ETC. + JSR CHROUT + + LDY #28 ; POSITION "STORY LOADING" MESSAGE + LDX #11 ; AT (8,11) + CLC + JSR PLOT + + LDX #SLOAD + LDY #SLOADL + JSR DLINE ; "THE STORY IS LOADING ..." + + LDA #8 ; MAKE BOOT DRIVE + JSR DOPEN ; AND OPEN IT + + ; FALL THROUGH TO ZIP WARMSTART AT "WARM2" + + END + diff --git a/c-128/ezip/disk.asm b/c-128/ezip/disk.asm new file mode 100644 index 0000000..e78fc73 --- /dev/null +++ b/c-128/ezip/disk.asm @@ -0,0 +1,224 @@ + PAGE + STTL "--- DISK ACCESS: CBM64 ---" + + ; -------------- + ; OPEN DRIVE [A] + ; -------------- + + ; ENTRY: DISK ID (8 OR 9 BINARY) IN [A] + +DOPEN: STA DRIVE ; SAVE DRIVE ID HERE + JSR DCLOSE ; CLOSE COMMAND & DATA CHANNELS + + LDA #15 ; LOGICAL FILE # + TAY ; SECONDARY ADDRESS + LDX DRIVE ; DEVICE # (8 OR 9) + JSR SETLFS ; SET UP LOGICAL FILE + + LDX #I0 ; "I0:" + LDA #I0L ; LENGTH OF FILENAME + JSR SETNAM + + JMP OPEN ; OPEN THE DISK (CARRY CLEAR IF OK) + + ; -------------------------- + ; OPEN DIRECT ACCESS CHANNEL + ; -------------------------- + +AOPEN: LDA #0 +; STA SPENA ; SHUT OFF CURSOR DMA + + JSR ACLOSE ; CLOSE FIRST + + LDA #2 ; D/A CHANNEL ID + TAY ; SECONDARY ID + LDX DRIVE + JSR SETLFS + + LDX #POUND ; "#" + LDA #POUNDL + JSR SETNAM + + JMP OPEN ; OPEN CHANNEL (CARRY CLEAR IF OK) + + ; ------------------- + ; CLOSE CURRENT DRIVE + ; ------------------- + +DCLOSE: LDA #15 ; CLOSE COMMAND CHANNEL + JSR CLOSE + + ; FALL THROUGH ... + + ; --------------------- + ; CLOSE THE D/A CHANNEL + ; --------------------- + +ACLOSE: LDA #2 ; AND THE + JMP CLOSE ; DATA CHANNEL + + ; ---------------- + ; DIVIDE [A] BY 10 + ; ---------------- + + ; EXIT: QUOTIENT IN [X], REMAINDER IN [A] + +DIV10: LDX #0 ; START WITH ZERO QUOTIENT + +D10L: CMP #10 ; IF DIVISOR < 10, + BCC D10EX ; WE'RE DONE + SBC #10 ; ELSE SUBTRACT ANOTHER 10 + INX ; UPDATE QUOTIENT + BNE D10L ; BRANCH ALWAYS + +D10EX: RTS + + ; --------------- + ; SEND Ux COMMAND + ; --------------- + + ; ENTRY: ASCII "1" OR "2" IN [A] + +COMLIN: DB "U" +DCOMM: DB "*" + DB ":2,0," +DTRAK: DB "***," +DSECT: DB "***" + DB EOL +CMLL EQU $-COMLIN + +SENDU: STA DCOMM ; INSERT COMMAND ("1" OR "2") IN STRING + + ; CONVERT [TRACK] AND [SECTOR] TO ASCII IN [COMLIN] + + LDA TRACK + LDY #2 +TCON: JSR DIV10 ; DIVIDE BY 10 + ORA #'0' ; CONVERT TO ASCII + STA DTRAK,Y ; STORE INTO STRING + TXA ; GET QUOTIENT INTO [A] + DEY ; ZERO-FILL USUSED BYTES + BPL TCON + + LDA SECTOR ; SAME FOR SECTOR ID + LDY #2 +SCON: JSR DIV10 + ORA #'0' + STA DSECT,Y + TXA + DEY + BPL SCON + + ; SEND COMMAND + + JSR CLRCHN + LDX #15 ; OUTPUT TO THE + JSR CHKOUT ; COMMAND CHANNEL + BCS UEX ; EXIT W/CARRY SET IF ERROR + + LDY #0 +SCM0: LDA COMLIN,Y ; SEND THE COMMAND LINE + JSR CHROUT ; TO THE DRIVE CHANNEL + INY ; A BYTE AT A TIME + CPY #CMLL + BCC SCM0 + CLC ; SUCCESS! +UEX: RTS + + ; ---------------------- + ; SET THE BUFFER POINTER + ; ---------------------- + +BPLINE: DB "B-P:2,0" + DB EOL +BPLL EQU $-BPLINE + +SETBP: JSR CLRCHN + LDX #15 ; OUTPUT TO + JSR CHKOUT ; COMMAND CHANNEL + BCS BEX ; CARRY SET IF ERROR + + LDY #0 +SBPL: LDA BPLINE,Y + JSR CHROUT + INY + CPY #BPLL + BCC SBPL + CLC +BEX: RTS + + ; ------------------------------ + ; READ/WRITE A BLOCK TO [IOBUFF] + ; ------------------------------ + + ; ENTRY: [TRACK] = TRACK # (1-35) + ; [SECTOR] = SECTOR # (0-15) + ; [DRIVE] = DRIVE ID (8 OR 9) + ; CARRY CLEAR TO READ, CARRY SET TO WRITE + +DISK: BCS DWRITE ; WRITE IF CARRY SET + + ; READ A DISK BLOCK + + JSR AOPEN ; OPEN THE ACCESS CHANNEL + BCS BADISK + + LDA #'1' ; SEND A "U1" COMMAND + JSR SENDU + BCS BADISK ; CARRY SET IF ERROR + + JSR SETBP ; SET THE BUFFER POINTER + BCS BADISK ; CARRY SET IF ERROR + + JSR CLRCHN + LDX #2 ; INPUT FROM + JSR CHKIN ; DATA CHANNEL + BCS BADISK + + LDY #0 +READ1: JSR CHRIN ; GET A BYTE + STA IOBUFF,Y ; MOVE TO I/O BUFFER + INY + BNE READ1 ; DO 256 BYTES + + BEQ SHUTD ; THEN EXIT + + ; WRITE A BLOCK + +DWRITE: JSR AOPEN ; OPEN THE ACCESS CHANNEL + BCS BADISK + + JSR SETBP ; SET THE BUFFER POINTER + BCS BADISK ; CARRY SET IF ERROR + + JSR CLRCHN + LDX #2 ; OUTPUT TO + JSR CHKOUT ; DATA CHANNEL + BCS BADISK ; CARRY SET IF ERROR + + LDY #0 +WRITE1: LDA IOBUFF,Y ; SEND CONTENTS OF [IOBUFF] + JSR CHROUT ; TO THE DRIVE + INY + BNE WRITE1 ; WRITE 256 BYTES + + LDA #'2' ; ISSUE A "U2" COMMAND + JSR SENDU + BCS BADISK ; CARRY SET IF ERROR + +SHUTD: JSR READST + AND #%10000011 + BNE BADISK + + JSR CLRCHN + CLC ; CARRY CLEAR FOR SUCCESS + RTS + +BADISK: JSR CLRCHN + SEC + RTS ; OR SET IF ERROR + + END + diff --git a/c-128/ezip/dispatch.asm b/c-128/ezip/dispatch.asm new file mode 100644 index 0000000..04570a2 --- /dev/null +++ b/c-128/ezip/dispatch.asm @@ -0,0 +1,217 @@ + PAGE + STTL "--- OPCODE DISPATCH TABLES ---" + + + ; 0-OPS + +OPT0H: DB >ZRTRUE ;0 + DB >ZRFALS ;1 + DB >ZPRI ;2 + DB >ZPRR ;3 + DB >ZNOOP ;4 + DB >ZSAVE ;5 + DB >ZREST ;6 + DB >ZSTART ;7 + DB >ZRSTAK ;8 + DB >POPVAL ;9 + DB >ZQUIT ;10 + DB >ZCRLF ;11 + DB >ZUSL ;12 + DB >ZVER ;13 + DB >BADOP0 ;14 + DB >BADOP0 ;15 + +OPT0L: DB ZZERO ;0 + DB >ZNEXT ;1 + DB >ZFIRST ;2 + DB >ZLOC ;3 + DB >ZPTSIZ ;4 + DB >ZINC ;5 + DB >ZDEC ;6 + DB >ZPRB ;7 + DB >ZCALL1 ;8 (EZIP) + DB >ZREMOV ;9 + DB >ZPRD ;10 + DB >ZRET ;11 + DB >ZJUMP ;12 + DB >ZPRINT ;13 + DB >ZVALUE ;14 + DB >ZBCOM ;15 + +OPT1L: DB BADOP2 ;0 (UNDEFINED) + DB >ZEQUAL ;1 + DB >ZLESS ;2 + DB >ZGRTR ;3 + DB >ZDLESS ;4 + DB >ZIGRTR ;5 + DB >ZIN ;6 + DB >ZBTST ;7 + DB >ZBOR ;8 + DB >ZBAND ;9 + DB >ZFSETP ;10 + DB >ZFSET ;11 + DB >ZFCLR ;12 + DB >ZSET ;13 + DB >ZMOVE ;14 + DB >ZGET ;15 + DB >ZGETB ;16 + DB >ZGETP ;17 + DB >ZGETPT ;18 + DB >ZNEXTP ;19 + DB >ZADD ;20 + DB >ZSUB ;21 + DB >ZMUL ;22 + DB >ZDIV ;23 + DB >ZMOD ;24 + DB >ZCALL2 ;25 (EZIP) + DB >BADOP2 ;26 + DB >BADOP2 ;27 + DB >BADOP2 ;28 + DB >BADOP2 ;29 + DB >BADOP2 ;30 + DB >BADOP2 ;31 + +OPT2L: DB ZCALL ;0 + DB >ZPUT ;1 + DB >ZPUTB ;2 + DB >ZPUTP ;3 + DB >ZREAD ;4 + DB >ZPRC ;5 + DB >ZPRN ;6 + DB >ZRAND ;7 + DB >ZPUSH ;8 + DB >ZPOP ;9 + DB >ZSPLIT ;10 + DB >ZSCRN ;11 + + ; (EZIPS FROM HERE ON) + DB >ZXCALL ;12 + DB >ZCLR ;13 + DB >ZERASE ;14 + DB >ZCURST ;15 + DB >ZCURGT ;16 (NOT IMPLEMENTED) + DB >ZLIGHT ;17 + DB >ZBUFOUT ;18 + DB >ZDIRT ;19 + DB >ZDIRIN ;20 (NOT IMPLEMENTED) + DB >ZSOUND ;21 + DB >ZINPUT ;22 + DB >ZINTBL ;23 + DB >BADOPX ;24 + DB >BADOPX ;25 + DB >BADOPX ;26 + DB >BADOPX ;27 + DB >BADOPX ;28 + DB >BADOPX ;29 + DB >BADOPX ;30 + DB >BADOPX ;31 + +OPTXL: DB ERRM + LDY #ERRML + JSR DLINE ; PRINT ERROR MESSAGE + + ; FALL THROUGH + + +; ---- +; QUIT +; ---- + +ZQUIT: JSR ZCRLF ; FLUSH BUFFER + + LDA TOP ; AND IF ENTER HERE + STA WTOP ; SCROLL ONLY WHAT SHOULD + + LDX #ENDM + LDY #ENDML + JSR DLINE ; "END OF STORY" + JMP DOWARM + + +; ------- +; RESTART +; ------- + +ZSTART: JSR ZCRLF ; FLUSH BUFFER + + LDA TOP ; AND IF ENTER HERE + STA WTOP ; SCROLL ONLY WHAT SHOULD + + LDX #RSTRT + LDY #RSTRTL + JSR DLINE + + +DOWARM: JSR GETRET + LDX #0 + STX WTOP ; RESET FULL SCREEN FOR CLEAR +REX: JSR SIDE1 ; NEED SIDE 1 AGAIN + JMP WARM1 ; AND DO WARMSTART + +ENDM: DB "End of session." + DB EOL +RSTRT: DB "Press [RETURN] to restart." + DB EOL +ENDML EQU $-ENDM +RSTRTL EQU $-RSTRT + + +; -------------------------- +; RETURN TOP RAM PAGE IN [A] +; -------------------------- + +MEMTOP: LDA #$FB ; FOR NOW, ASSUME LAST "BUFFER" + RTS ; OF AUX MEMORY + + +; ------------------- +; Z-PRINT A CHARACTER +; ------------------- +; ENTRY: ASCII CHAR IN [A] +; +; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, +; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN +; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME +; (DIROUT CHANGES 6/24/85) + +COUT: STA IOCHAR ; HOLD IT A SEC + LDX TABLEF ; OUTPUT TO TABLE? + BEQ COUT4 ; NO + JMP TBLRTN ; YES, DO IT (TBL ONLY 4.7.86) +COUT4: LDX SCREENF ; OUTPUT TO SCREEN? + BNE COUT5 ; YES + LDX SCRIPTF ; OUTPUT TO PRINTER? + BNE COUT5 ; YES + RTS ; NO, SO DONE +COUT5: LDA IOCHAR ; RETRIEVE CHAR + LDX BUFFLG ; UNBUFFERED OUTPUT? + BNE UNBUFR ; YES, PLACE ON SCREEN IMMED. + CMP #EOL ; IF ASCII EOL, + BNE COUT0 + JMP ZCRLF ; DO IT +COUT0: CMP #SPACE ; IGNORE ALL OTHER + BCC CEX ; CONTROLS + +COUT3: LDX CHRCNT ; GET LINE POINTER + STA LBUFF,X ; ADD CHAR TO BUFFER + LDY LENGTH ; GET LINE LENGTH COUNTER + CPY XSIZE ; END OF SCREEN LINE? + BCC COUT2 + JMP FLUSH ; YES, FLUSH THE LINE +COUT2: INC LENGTH ; ELSE UPDATE + INC CHRCNT +CEX: RTS + + +; -------------------------- +; DIRECT, UNBUFFERED DISPLAY +; -------------------------- + +UNBUFR: STA IOCHAR ; HOLD IN CASE NEED TO PRINT + CMP #SPACE ; IGNORE CONTROLS + BCC UNBEX + + SEC + JSR PLOT + CPY #80 ; CHECK IF BEYOND SCREEN + BCS UNBEX ; YES, LEAVE + LDA SPLITF ; CHECK WHICH WINDOW + BEQ UNBBOT ; BOTTOM WINDOW + + CPX TOP ; CHECK IF WITHIN WINDOW + BCS UNBEX ; NO, JUST LEAVE + BCC UNBDIS ; YES, GO DISPLAY + +UNBBOT: CPX TOP + BCC UNBEX ; NOT WITHIN WINDOW, LEAVE + +UNBDIS: LDA SCREENF ; DISPLAY TO SCREEN? + BEQ UNBPRN ; NO, CHECK IF PRINTING + LDA IOCHAR + JSR LETTER ; DO VOODOO AND DISPLAY + +UNBPRN: LDA SPLITF ; SPLIT (NON-TEXT) SCREEN + BNE UNBEX ; DON'T PRINT + + ;SEND CHAR TO PRINTER + + LDA #1 ; SET FOR PRINT RTN + STA PRLEN + LDA IOCHAR + STA LBUFF + JSR PPRINT ; AND GO ATTEMPT IT + LDA #0 ; MAKE SURE NO LEFTOVER + STA PRLEN +UNBEX: RTS + + +; --------------- +; OUTPUT TO TABLE +; --------------- + +TBLRTN: TAX ; HOLD CHAR A SEC. + + ;PUT BYTE IN TABLE AT CURRENT OFFSET + + LDA DIRITM+LO ; ADD IN OFFSET + CLC + ADC DIRTBL+LO + STA I+LO + LDA DIRITM+HI + ADC DIRTBL+HI + STA I+HI + LDY #0 + TXA ; PICK UP ASCII CHAR + STA (I),Y ; STORE IT IN TBL @ BYTE ALIGNED @ + +;SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER + + INC DIRITM+LO ; INC OFFSET TO NEXT BYTE + BNE TBLRTS + INC DIRITM+HI +TBLRTS: RTS + + +; ------------------- +; FLUSH OUTPUT BUFFER +; ------------------- +; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: LDA #SPACE ; SPACE + STX OLDEND ; SAVE CURRENT END OF LINE +FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR + BEQ FL1 ; IN THE LINE + DEX + BNE FL0 ; IF NONE FOUND, + LDX XSIZE ; FLUSH ENTIRE LINE +FL1: STX OLDLEN ; SAVE OLD LINE POS HERE + STX CHRCNT ; MAKE IT THE NEW LINE LENGTH + JSR ZCRLF ; PRINT LINE UP TO LAST SPACE + +; START NEW LINE WITH REMAINDER OF OLD + + LDX OLDLEN ; GET OLD LINE POS + LDY #0 ; START NEW LINE AT BEGINNING +FL2: INX + CPX OLDEND ; CONTINUE IF + BCC FL3 ; INSIDE OR + BEQ FL3 ; AT END OF LINE + STY LENGTH ; ELSE SET NEW LINE LENGTH + STY CHRCNT + RTS +FL3: LDA LBUFF,X ; GET CHAR FROM OLD LINE + STA LBUFF,Y ; MOVE TO START OF NEW LINE + INY ; UPDATE LENGTH OF NEW LINE + BNE FL2 ; (ALWAYS) + + +; --------------- +; CARRIAGE RETURN +; --------------- + +ZCRLF: LDX CHRCNT + LDA #EOL ; INSTALL EOL AT + STA LBUFF,X ; END OF CURRENT LINE + INC CHRCNT ; UPDATE LINE LENGTH + LDA SCREENF ; CHECK IF DISPLAYING TO SCREEN + BEQ ZCRLFX ; NO, GO HANDLE IF PRINTING + LDA SPLITF ; AT SPLIT SCREEN + BNE ZCRLF0 ; YES + INC LINCNT ; NEW LINE GOING OUT +ZCRLF0: LDX LINCNT ; IS IT TIME TO + INX ; (A LINE FOR "MORE") + CPX WBOTM ; PRINT "MORE" YET? + BCC ZCRLFX ; NO, CONTINUE + BEQ ZCRLFX ; also no continue + LDA WTOP + STA LINCNT ; RESET LINE COUNTER + INC LINCNT ; LEAVE 1 LINE ON SCREEN + + SEC + JSR PLOT ; GET CURSOR POSITION + STY OLDX + STX OLDY + + LDX WBOTM ;#23p + LDY #0 + CLC + JSR PLOT ; BOTTOM LEFT OF SCREEN + + LDA #146 ; IF GET HERE INVERSE + JSR CHROUT ; SHOULD BE OFF SO TURN OFF + + LDX #MORE + LDY #MOREL + JSR DLINE ; PRINT MORE DIRECTLY + + LDA #0 + STA NDX ; CLEAR INPUT QUEUE + +ZCR0: JSR GETIN ; GET ANY KEYPRESS + TAX + BEQ ZCR0 + + LDX WBOTM ;#23 + LDY #0 + CLC + JSR PLOT ; RESTORE CURSOR + + LDX #MCLR + LDY #MOREL + JSR DLINE ; RUB OUT "MORE" + + LDY OLDX + LDX OLDY + CLC + JSR PLOT ; RESTORE CURSOR + +ZCRLFX: JSR LINOUT ; DISPLAY LINE + LDA #0 + STA LENGTH ; AND RESET LINE COUNT + STA CHRCNT + RTS + +LINOUT: LDY CHRCNT ; IF BUFFER EMPTY, + BEQ LINEX ; DON'T PRINT ANYTHING + STY PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + LDA SCREENF ; DISPLAY TO SCREEN? + BEQ LOUT1 ; NO, GO CHECK IF PRINT + + LDA WTOP + PHA + + LDA SPLITF + BNE LOUT2 ; NON SCROLLING SCREEN + LDA TOP + STA WTOP + +LOUT2: LDX #0 ; SEND CONTENTS OF [LBUFF] +LOUT: LDA LBUFF,X ; TO SCREEN + JSR CHAR + INX + DEY + BNE LOUT + + PLA ; RESET FOR FULL SCREEN ACCESS + STA WTOP + +LOUT1: LDA SPLITF ; DON'T PRINT IF SPLIT (NON-TEXT) SCREEN (EZIP) + BNE LINEX + JSR PPRINT ; PRINT [LBUFF] IF ENABLED +LINEX: RTS ; AND RETURN + + +; ---------------------- +; UPDATE THE STATUS LINE +; ---------------------- +; NOT APPLICABLE IN EZIP. +ZUSL: RTS + + +; ------ +; BUFOUT +; ------ +; INPUT: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE +; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO + +ZBUFOUT: LDX ARG1+LO + BNE ZBUF1 ; SET TO BUFFERED OUTPUT + JSR LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) + + LDX #0 + STX CHRCNT + INX + STX BUFFLG ; SET FUTURE OUTPUT TO BE UNBUFFERED + RTS +ZBUF1: DEX + BNE ZBUFEX ; INVALID + STX BUFFLG ; SET TO BUFFERED +ZBUFEX: RTS + + +; ------ +; DIROUT +; ------ +; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT +; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT +; MULTIPLE DEVICE USAGE IS POSSIBLE. + +ZDIRT: LDX ARG1+LO + BMI DIRRES ; NEGATIVE VALUE, DESELECTING + DEX + BEQ DIR1 ; 1 = SET OUTPUT TO SCREEN + DEX + BEQ DIR2 ; 2 = SCRIPTING + DEX + BEQ DIR3 ; 3 = TABLE + DEX + BEQ DIR4 ; 4 = RECORDING DEVICE (NOT IMPLEMENTED) +DIR4: RTS ; INVALID VALUE +DIRRES: INX + BEQ DRES1 ; -1 = RESET TO SCREEN + INX + BEQ DRES2 + INX + BEQ DRES3 + INX + BEQ DRES4 +DRES4: RTS ; INVALID VALUE, JUST LEAVE + +DIR1: INX ; 1, TURN SCREEN OUTPUT ON + STX SCREENF + RTS + +DRES1: STX SCREENF ; 0, TURN SCREEN OFF + RTS + +DIR2: INX + STX SCRIPTF ; SET SCRIPT FLAG ON + LDA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO + ORA #%00000001 + STA ZBEGIN+ZSCRIP+1 + RTS ; YES, READY TO LEAVE + +DRES2: STX SCRIPTF ; TURN PRINTER OFF + LDA ZBEGIN+ZSCRIP+1 ; AND TURN OFF GAME FLAG TOO + AND #%11111110 + STA ZBEGIN+ZSCRIP+1 + RTS + +DIR3: INX + STX TABLEF ; TURN TABLE OUTPUT FLAG ON + LDA ARG2+HI ; SET UP TBL + CLC + ADC ZCODE + LDX ARG2+LO ; TO STORE CHARS IN + STX DIRTBL+LO + STA DIRTBL+HI + LDA #2 + STA DIRITM+LO + LDA #0 + STA DIRITM+HI + RTS + +DRES3: LDA TABLEF ; IF ALREADY OFF + BEQ DROUT ; LEAVE AS IS + + STX TABLEF ; TURN TBL OUTPUT OFF + LDA DIRITM+LO ; MARK END OF CHARS IN TBL + CLC ; WITH A NULL CHAR + ADC DIRTBL+LO + STA I+LO + LDA DIRITM+HI + ADC DIRTBL+HI + STA I+HI ; ALIGNED AT EOL + LDA #0 + TAY + STA (I),Y ; PLACE 0 IN TBL + LDY #1 ; GET CHAR COUNT + LDA DIRITM+LO ; (2 LESS THAN [DIRITM]) + SEC + SBC #2 + STA (DIRTBL),Y + BCS RESET0 + DEC DIRITM+HI +RESET0: LDA DIRITM+HI + DEY + STA (DIRTBL),Y ; STORE CHAR COUNT IN TBL + LDA #0 ; CLEAR COUNT FOR NEXT TIME + STA DIRFLG ; SET OUTPUT TO SCREEN +DROUT: RTS + + +; ------ +; CURSET +; ------ +; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW +; AND AT COLUMN (ARG2) + +ZCURST: LDA ZBEGIN+ZMODE + AND #%00010000 + BEQ ZCUREX ; NOT ENABLED + LDA SPLITF + BEQ ZCUREX ; OOPS, IN SCROLLING TOP + LDA BUFFLG + BEQ ZCUREX ; OOPS, UNBUFFERED + + LDX ARG1+LO ; GET LINE + DEX ; ZERO ALIGN IT + LDY ARG2+LO ; GET COLUMN + DEY ; ZERO ALIGN IT + CLC + JSR PLOT ; MOVE THE CURSOR +ZCUREX: RTS + + +; -------------- +; CURGET & DIRIN +; -------------- +; NOT YET IMPLEMENTED, BUT RESERVED + +ZCURGT: +ZDIRIN: RTS + + +; ------ +; HLIGHT +; ------ + +ZLIGHT: LDA ZBEGIN+ZMODE ; CHECK IF ENABLED + AND #%00001010 + BEQ ZLEX ; NOPE + + LDX ARG1+LO ; GET CHOICE OF MODE + BNE ZL1 + + LDA #146 ; REVERSE OFF + JSR HLIGHT + LDA #130 ; UNDERLINE OFF + JMP HLIGHT +ZLEX: RTS + +ZL1: CPX #1 ; INVERSE? + BNE ZL2 + + LDA #$12 ; INVERSE + JMP HLIGHT + +ZL2: CPX #4 ; UNDERLINE? + BNE ZLEX ; NO OTHER ON C128 + + LDA #$02 ; UNDERLINE + +HLIGHT: STA IOCHAR ; HOLD COMMAND CHAR + LDA SCREENF ; IF NOT PRINTING TO + BNE DOLIGHT ; SCREEN OR PRINTER, SKIP THIS + LDA SCRIPTF + BNE DOLIGHT + RTS +DOLIGHT: LDA IOCHAR + LDX BUFFLG + BEQ BUFFD + JMP CHROUT ; UNBUFFERED, CHANGE IMMEDIATELY + +BUFFD: LDX CHRCNT ; BUFFERED, PLACE + STA LBUFF,X ; DISPLAY BUFFER + INC CHRCNT ; INC CHRCNT BUT NOT! LINE LENGTH + RTS + + +; ----- +; ERASE +; ----- + +ZERASE: LDA ZBEGIN+ZMODE ; ENABLED? + AND #%00010000 + BEQ ZEROUT ; NO + LDA ARG1+LO + CMP #1 + BNE ZEROUT ; INVALID + + SEC ; CLEAR TO END OF LINE + JSR PLOT + STX OLDX + STY OLDY + +ZERLP: INY + CPY #80 + BCS ZERDUN + LDA #SPACE + JSR CHROUT + JMP ZERLP + +ZERDUN: LDX OLDX ; RESET CURSOR + LDY OLDY + CLC + JSR PLOT + +ZEROUT: RTS + + +; ----- +; CLEAR +; ----- + +ZCLR: LDA ZBEGIN+ZMODE + AND #%00000001 + BEQ ZEROUT ; NOT ENABLED + LDA ARG1+LO ; CHECK WHAT TO DO + BEQ CLR0 ; BOTTOM SCREEN + CMP #1 + BEQ CLR1 ; TOP SCREEN + CMP #$FF + BNE ZEROUT ; INVALID + +; UNSPLIT SCREEN & CLEAR IT + + JSR NORL ; RESET TO FULL + LDA #CLS ; & CLEAR IT + JSR CHROUT + RTS + +CLR0: LDA WTOP ; KEEP + PHA + LDA TOP ; SET COUNT + STA LINCNT ; FOR "MORE" + STA WTOP ; AND PROPER WINDOW TOP + LDA #CLS ; CLEAR & HOME + JSR CHROUT + PLA + STA WTOP + LDX WBOTM ;#$17 ; SET CURSOR @ + LDY #0 ; BOTTOM OF SCREEN + CLC + JMP PLOT +CLR1: LDA WBOTM + PHA + + LDY #0 ; TOP OF SCREEN + STY WTOP + LDX TOP + STX WBOTM ; MAKE BOTTOM OF TOP SCREEN + LDA #CLS + JSR CHROUT + + PLA ; RESET TOP & BOTTOM + STA WBOTM + CLC + JMP PLOT + + +; ----- +; INPUT +; ----- + +ZINPUT: LDA ARG1+LO + CMP #1 ; KEYBOARD? + BEQ ZINP7 + JMP RET0 ; NO, INVALID + +ZINP7: LDA WTOP ; RESET LINE COUNT + STA LINCNT + LDA #0 + STA LENGTH ; SET LINE COUNT TO 0 + STA CHRCNT + STA NDX ; CLEAR INPUT QUEUE + + DEC NARGS + BNE ZINP8 + JMP ZINP3 ; NO TIME LIMIT + +ZINP8: LDA ARG2+LO ; GET DELAY WANTED + STA I+HI + LDA #0 ; SET FCN IF IS ONE + STA J+HI + STA J+LO + DEC NARGS + BEQ ZINP4 ; NO FCN + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI + +ZINP4: SEC + JSR PLOT + STX OLDX + STY OLDY + + LDA #$E4 ; TURN CURSOR ON + STA ULINE + JSR CHROUT + + LDX OLDX + LDY OLDY + CLC + JSR PLOT + + LDX #0 + STX BLINK+LO ; RESET THE BLINK COUNTER + STX BLINK+HI ; FOR A LONG DELAY + +ZINP0: LDA I+HI + STA I+LO ; RESET EA TIME THRU + +ZINP1: LDA #249 ; = 7, TIME COUNTS UP + STA TIME +ZINP2: LDA TIME + BNE ZINP2 + + JSR GETIN ; GET A KEY + CMP #0 + BEQ ZINP6 ; NO KEY YET + JSR GOTKEY + JMP ZINP5 ; [A] NOW HAS PROPER CODE + +ZINP6: INC BLINK+LO ; TIME TO BLINK YET? + BNE NOBLNK ; NOT TILL BOTH BLINK TIMERS + INC BLINK+HI ; ARE ZERO + BNE NOBLNK + + LDA ULINE + AND #$C4 ; MAKE _ OR BLANK, SO "BLINKS" + JSR CHROUT + + LDX OLDX + LDY OLDY + CLC + JSR PLOT + +NOBLNK: DEC I+LO + BNE ZINP1 ; SOME TIME LEFT, TRY AGAIN + +; TIME OUT, CHECK IF THERE IS A FCN TO CALL + + LDA J+LO ; FCN IN J IF THERE IS ONE + ORA J+HI + BEQ ZINPEX ; NO FCN, SEND 0 FOR FAILED + JSR INTCLL ; INTERNAL CALL + LDA VALUE+LO ; GET RESULTS + BNE ZINPEX ; ABORT + BEQ ZINP0 ; TRY AGAIN + +ZINP3: JSR GETKEY ; OK, FIND WHICH CHAR WAS PRESSED + +ZINP5: CMP #BACKSP ; GAME EXPECTS ASCII BS + BNE ZINP9 + LDA #$08 ; WHICH IS $08 +ZINP9: LDX #0 + JMP PUTBYT ; RETURN CHAR + +ZINPEX: JMP RET0 ; OOPS + + +INTCLL: LDA #>ZIRET ; SET ZRETURN TO RETURN HERE + STA PATCHI+HI + LDA #PUTVAL ; REPAIR ZRETURN + STA PATCHI+HI + LDA # TO , . + +MASK: LDX #ENDKEY ; GET LENGTH OF LIST +MASK0: CMP HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + BEQ MASK1 ; FOUND IT + DEX + BPL MASK0 ; CHECK THEM ALL + BMI MASK2 ; NOT FOUND, CONTINUE OTHER CHECKS +MASK1: LDA WANT,X ; GET KEY TO USE INSTEAD + BNE TICK ; JMP + +MASK2: AND #%01111111 ; SCREEN OUT SHIFTS + + CMP #EOL ; EOL? + BEQ TICK + CMP #BACKSP + BEQ TICK + CMP #SPACE ; ANYTHING ELSE < "SPACE" + BCC BADKEY ; IS BAD + + LDX #BLISTL ; IGNORE OBSTINATE NON ALLOWED KEYS +BADL: CMP BADLIST,X + BEQ BADKEY + DEX + BNE BADL + + CMP #'z'+1 ; PASS L-C ALPHA + BCS BADKEY + CMP #'a' + BCS TICK + + CMP #'Z'+1 ; PASS U-C ALPHA + BCC TICK ; AND OTHER ASCII CHARS + +BADKEY: JSR BOOP ; REJECT BAD KEYPRESS + JMP GETKEY ; AND TRY AGAIN + +TICK: STA IOCHAR ; HOLD ON TO IT + LDA #SPACE + JSR CHROUT ; ERASE CURSOR + LDX OLDX + LDY OLDY + CLC + JSR PLOT + + ADC RNUM1 ; FUTZ WITH RANDOM + STA RNUM1 + EOR RNUM2 + STA RNUM2 + LDA IOCHAR ; GET CHAR INTO [A] + RTS ; AND RETURN IT + +HAVE: DB '<','>',$11,$1D,$91,$5E,$9D +WANT: DB ',','.',13,07,14,14,11 +ENDKEY EQU $-WANT-1 + +BADLIST: DB '%','&','=','@' +BLISTL EQU $-BADLIST-1 + + ; ------------------------- + ; OUTPUT AN ASCII CHARACTER + ; ------------------------- + +LETTER: CMP #'a' ; LOWER-CASE? + BCC LET0 ; NO, CONTINUE + CMP #'z'+1 + BCS LETEX ; CTRL CHARS + AND #%01011111 ; ELSE MASK FOR LOWER-CASE + JMP CHROUT + +LET0: CMP #'A' ; UPPER-CASE? + BCC LETEX + CMP #'Z'+1 + BCS LETEX + ORA #%00100000 ; MAKE UPPER +LETEX: JMP CHROUT + + + ; ----------------- + ; PRINT CHAR IN [A] + ; ----------------- + +CHAR: STA IOCHAR ; SAVE HERE + TXA ; SAVE [X] AND [Y] + PHA + TYA + PHA + +NOSCRL: LDA IOCHAR ; RESTORE CHAR + CMP #$22 + BNE NOQUOT + JSR LETTER ; QUOTE MARKS SCREW + LDA #0 ; UP SYSTEM, SO + STA QUOTMOD ; TURN OFF QUOTE MODE FLAG + JMP CHDUN + +NOQUOT: JSR LETTER ; OFF TO THE SCREEN! +CHDUN: PLA ; RESTORE [X] AND [Y] + TAY + PLA + TAX + RTS + + + ; --------------------- + ; FETCH A LINE OF INPUT + ; --------------------- + + ; ENTRY: ABS ADDR OF READ BUFFER IN [ARG1] + ; EXIT: # CHARS READ IN [A] + +INPUT: JSR LINOUT ; FLUSH [LBUFF] + LDA #0 ; RESET LINE COUNT + STA LENGTH + STA CHRCNT + LDY TOP + STY LINCNT ; RESET LINE COUNT + STA NDX ; CLEAR INPUT QUEUE + + DEC NARGS ; CHECK IF TIME LIMIT (EZIP) + DEC NARGS + BEQ INP2 ; NO + LDA ARG3+LO ; GET DELAY WANTED + STA I+HI + LDA #0 + STA J+HI + STA J+LO + DEC NARGS ; IS THERE A FCN? + BEQ INP4 ; NO + LDA ARG4+LO ; YES, SET IT + STA J+LO + LDA ARG4+HI + STA J+HI + +INP4: LDA I+HI + STA I+LO ; RESET EA TIME THRU + +INP0: LDA #249 ; = 7, TIME COUNTS UP + STA TIME +INP1: LDA TIME + BNE INP1 + + JSR GETIN + CMP #0 + BEQ INP6 ; NO KEY YET + JSR GOTKEY ; OK, GO DO THE VOODOO + LDY #0 + STY CHARCNT + JMP INLP1 ; [A] NOW HAS PROPER CODE + +INP6: DEC I+LO + BNE INP0 ; SOME TIME LEFT, TRY AGAIN + + ; TIME OUT, CHECK IF THERE IS A FCN TO CALL + + LDA J+LO ; IS THERE A FCN + ORA J+HI + BNE INP3 + JMP LEXBAD ; NO FCN, LEAVE WITH NOTHING + +INP3: JSR INTCLL ; INTERNALLY CALL THE FCN + LDA VALUE+LO ; CHECK RESULTS + BEQ INP4 ; ELSE TRY AGAIN (END EZIP) + JMP LEXBAD ; ELSE ABORT + +INP2: LDY #0 ; AND CHAR COUNT + STY CHARCNT + +INLOOP: JSR GETKEY ; GET ASCII INTO [A] AND [IOCHAR] +INLP1: CMP #14 + BEQ CBAD ; CLEAR OFF ARROWS (EZIP) + CMP #11 + BEQ CBAD + CMP #7 + BEQ CBAD + CMP #EOL ; EOL? + BEQ ENDLIN ; LINE DONE IF SO + CMP #BACKSP ; BACKSPACE? + BEQ BACKUP ; SPECIAL HANDLING + + LDY CHARCNT + STA LBUFF,Y ; ELSE ADD CHAR TO INPUT BUFFER + INC CHARCNT ; NEXT POSITION IN LINE +SHOWIT: JSR CHAR ; SEND TO SCREEN + LDY CHARCNT + CPY #77 ; ALL THE CHARS ALLOWED? + 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 BEEP ; ELSE COMPLAIN + JMP NOMORE ; AND INSIST + + ; HANDLE BACKSPACE + +BACKUP: DEC CHARCNT ; BACK UP THE POINTER + BPL SHOWIT ; JMP + LDY #0 ; RESET POINTER + STY CHARCNT +CBAD: JSR BEEP ; ELSE SCREAM WITH PAIN + JMP INLOOP ; AND WAIT FOR SOMETHING BETTER + + ; HANDLE END OF LINE + +ENDLIN: LDY CHARCNT + STA LBUFF,Y ; SHIP EOL TO BUFFER + INY ; UPDATE INDEX + STY LINLEN ; SAVE HERE FOR "READ" + STY PRLEN ; AND HERE FOR "PPRINT" + + LDX TOP ; SET TOP SO SCROLLS CORRECTLY + STX WTOP + JSR CHAR ; AND SEND EOL TO SCREEN + LDX #0 + STX WTOP ; AND SET BACK TO EASY USE + + ; MOVE [LBUFF] TO [ARG1] W/LC CONVERSION + +LEX0: LDA LBUFF-1,Y ; GET A CHAR FROM [LBUFF] + CMP #'A' ; IF CHAR IS ALPHA, + BCC LEX2 ; CONVERT TO LOWER CASE + CMP #'Z'+1 + BCS LEX2 + ADC #$20 +LEX2: STA (RDTBL1),Y ; MOVE CHAR TO INPUT BUFFER AT [ARG1] + DEY ; LOOP TILL + BNE LEX0 ; ALL CHARS MOVED + JSR PPRINT ; SCRIPT [LBUFF] IF ENABLED + LDA LINLEN ; RESTORE # CHARS + RTS ; INTO [A] +LEXBAD: LDA #0 ; TIME OUT OCCURRED (EZIP) + RTS ; ZERO CHARS OBTAINED + +CHARCNT: DB 0 + +; ----------------------- +; 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 + STY J ; COUNTER + + LDA TOP ; RETAIN STATUS LINE(S) + STA WTOP + + LDX #0 ; INIT CHAR-FETCH INDEX +DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE +STRING: DW $0000 ; DUMMY OPERAND BYTES + JSR CHAR + INX + DEC J ; LOOP TILL + BNE DOUT ; OUT OF CHARS + + LDA #0 + STA WTOP + + RTS + + + ; ----------------------- + ; SEND [LBUFF] TO PRINTER + ; ----------------------- + + ; ENTRY: LENTH OF LINE IN [PRLEN] + ; NOW WITH IMPROVED ERROR PROTECTION! (BM 11/24/84) + +PPRINT: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? + BEQ PEX ; NO, SCRAM IMMEDIATELY + + LDA ZBEGIN+ZSCRIP+1 ; CHECK SCRIPT FLAG + AND #%00000001 ; SCRIPTING ON? + BEQ PP3 ; NO, CHECK FOR "UNSCRIPT" + + LDA PSTAT ; CHECK PRINTER STATUS + BMI PEX ; CAN'T OPEN IF NEGATIVE + BNE PP1 ; ALREADY OPEN, SCRIPT THE LINE + + ; OPEN THE PRINTER FOR OUTPUT + +PP0: LDX #1 + STX PSTAT ; SET STATUS TO "PRINTER OPENED" (1) + + LDA #4 ; LOGICAL FILE #4 + TAX ; DEVICE #4 + LDY #7 ; ALLOW UPPER/LOWER CASE + JSR SETLFS ; SET UP LOGICAL FILE + LDA #0 + JSR SETNAM ; NO FILENAME REQUIRED + JSR OPEN ; OPEN THE CHANNEL + BCC PP1 ; OPEN OKAY IF CARRY CLEAR + +PPERR: LDA #$FF ; ELSE SET PRINTER STATUS + STA PSTAT ; TO "CAN'T OPEN" + BNE PP5 ; AND SIMULATE AN "UNSCRIPT" + +PP1: LDX #4 ; SET PRINTER CHANNEL + JSR CHKOUT ; TO "OUTPUT" + BCS PPERR ; ERROR IF CARRY SET + + LDY #0 ; INIT INDEX +PP2: LDA LBUFF,Y + CMP #$0D + BEQ PP6 + AND #%01111111 + CMP #$20 + BCC PP4 ; NO CONTROLS +PP6: JSR LETTER + BCS PPERR ; ERROR IF CARRY SET +PP4: INY + DEC PRLEN + BNE PP2 + BEQ PEX ; RESET & RETURN + + ; CHECK FOR "UNSCRIPT" + +PP3: LDA PSTAT ; CHECK PRINTER STATUS + BEQ PEX ; EXIT IF PRINTER WAS OFF + BMI PEX ; OR UNOPENABLE + +PCLOSE: LDA #0 ; RESET PRINTER STATUS FLAG + STA PSTAT ; TO "CLOSED" + + ; ENTRY FOR PRINTER ERROR + +PP5: LDA #4 + JSR CLOSE ; CLOSE THE PRINTER CHANNEL +PEX: JMP CLRCHN + +PSTAT: DB 0 ; HERE SO RESTART WON'T ALTER + + + ; ------------ + ; SPLIT SCREEN + ; ------------ + + ; SPLIT SCREEN AT LINE [ARG1] + ; DISABLE SPLIT IF [ARG1] = 0 + ; IGNORE IF SPLIT ALREADY ENABLED OR [ARG1] >= 23 + + ; ON C-128, I AM USING KERNAL RTNS TO ACCESS SCREEN MEMORY + ; AS SCREEN MEMORY IS IN ITS OWN WORLD. IN ORDER NOT TO + ; SCROLL THE TOP WINDOW WHEN SCREEN IS SPLIT, THE C-128 + ; TOP OF SCREEN INDICATOR MUST BE USED, BUT: NO ACCESS IS + ; ALLOWED ABOVE THAT INDICATOR. THAT INDICATOR (WTOP) WILL + ; THEREFORE BE SET ONLY WHEN SCROLLING MIGHT OCCUR, LEAVING + ; [WTOP] SET TO #0 OTHERWISE. THE SPLIT LINE IS KEPT TRACK + ; OF IN [TOP]. + +ZSPLIT: LDA ZBEGIN+ZMODE + AND #%00100000 ;CHECK IF ENABLED (EZIP) + BEQ ZSPOUT ;NOT, LEAVE + LDA ARG1+LO ;GET # OF LINES FOR SCREEN + BEQ NORL ;IF 0 THEN RESTORE SCREEN + CMP #24 ;IS SPLIT REALLY = WHOLE SCREEN + BCS ZSPOUT ;YES, IGNORE + + CMP TOP ; IF SCREEN 1 SHRINKING + BCS ZSLVIT ; SET LINCNT - (TOP - [A]) + PHA ; HOLD IT + SEC + SBC TOP + ADC LINCNT + STA LINCNT + PLA + +ZSLVIT: STA TOP ; SET THE TOP OF THE SECOND SCREEN + STA SPSTAT ; NON ZERO = SCREEN IS SPLIT + CMP LINCNT ; IS SCROLLING SCREEN NOW MORE THAN LINCNT? + BCC ZSPL3 ; NO + STA LINCNT ; YES, RESET LINCNT +ZSPL3: LDX WBOTM + LDY LENGTH ; get where y used to be #0 + CLC + JSR PLOT ; RESTORE CURSOR AFTER HOME CALL +ZSPOUT: + RTS + +NORL: ;RESTORE SCREEN TO FULL SCREEN MODE + + LDA #0 ; PUT CURSOR AT TOP OF SCREEN + STA WTOP ; RESTORE FULL SCREEN ALIGNMENT + STA TOP ; JIC + STA LINCNT + STA SPSTAT ; FLAG NOT SPLIT + RTS + + +; ------ +; SCREEN +; ------ +; GO TO TOP WINDOW (TOP OF SCREEN) IF [A] = 1 +; GO TO BOTTOM OF SCREEN IF [A] = 0 +; IGNORE IF SPLIT NOT ENABLED OR [A] <> 0 OR 1 +; FLAG SPLITF WILL BE SET FOR OUTPUT TO DETERMINE +; IF AND WHICH WINDOW TO DISPLAY TO +; (0=BOTTOM 1=TOP) + +SAVEX: DB 23 ; save spot for current cursor pos +SAVEY: DB 0 + +ZSCRN: LDA ZBEGIN+ZMODE + AND #%00000001 ; CHECK IF ENABLED (EZIP) + BEQ ZSPOUT ; NOT, LEAVE + LDA SPSTAT ; CHECK IF SCREEN IS SPLIT + BEQ ZSPOUT ; NO, SO JUST LEAVE + + LDA ARG1+LO ; CHECK WHICH WINDOW + BNE SCRN1 ; TOP SCREEN + LDA #$FF ; SCROLLING SCREEN SO + STA SCRIPT ; ALLOW SCRIPTING + + LDA #23 ; recreate bottom of screen + STA WBOTM ; and save it + LDA #0 + STA SPLITF ; SET FLAG TO SPLIT SCREEN (0) +; TAY ; PUT CURSOR AT BOTTOM OF SCREEN +; LDX WBOTM + + LDY SAVEY ; get where it used to be + LDX SAVEX ; get where it used to be + + JMP SCRNP ; JMP TO HIGH CRLOW RTN + +SCRN1: CMP #01 + BNE ZSPOUT ; INVALID SCREEN ID + + STA SPLITF ; SET FLAG TO UNSCROLLING SCREEN (1) + + SEC + JSR PLOT ; get where cursor currently resides + STY SAVEY ; save the y, + STX SAVEX ; x spots + + LDA TOP ; make bottom of screen the top of +; SEC ; scrolling screen - 1 +; SBC #1 ; to get bottom of screen +; STA WBOTM ; and save it +; LDA #2 ;DBG + STA WBOTM ;DBG + LDA #0 ; TOP, NON SCROLLING SCREEN + STA WTOP ; (C-128 WON'T GO BEYOND WTOP) + STA SCRIPT ; SET SCRIPTNG OFF, NOT ALLOWED THIS SCREEN + TAY + TAX ; ALIGN AT TOP OF SCREEN +SCRNP: + CLC + JMP PLOT ; SET CURSOR (+ LEAVE) + + + ; ----- + ; SOUND + ; ----- + ; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID + ; (EZIP) + +ZSOUND: LDA ZBEGIN+ZMODE + AND #%00100000 + BEQ ZSOEX ; NOT ENABLED + LDX ARG1+LO ; GET SOUND WANTED + DEX + BNE ZSO1 + JMP BEEP +ZSO1: DEX + BNE ZSOEX ; INVALID + JMP BOOP ; DOWN IN COMMON MEMORY + +ZSOEX: RTS + + + END + diff --git a/c-128/ezip/main.asm b/c-128/ezip/main.asm new file mode 100644 index 0000000..98b3b17 --- /dev/null +++ b/c-128/ezip/main.asm @@ -0,0 +1,257 @@ + PAGE + STTL "--- MAIN LOOP ---" + +MLOOP: LDA #0 + STA NARGS ; RESET # ARGUMENTS + JSR NEXTPC + STA OPCODE ; SAVE IT HERE + + IF DEBUG + LDA VALUE+HI + STA BONE + LDA VALUE+LO + STA BTWO + LDA #0 ; BREAKPOINT #0 + JSR DOBUG + LDA OPCODE + TAY + ENDIF + + ; DECODE AN OPCODE + + 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: CMP #236 ; XCALL? + BEQ OPXCLL ; YES, PROCESS SEPARATELY + 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: AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPTXL,Y + STA GOX+1+LO + LDA OPTXH,Y + STA GOX+1+HI +GOX: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #1 -- ILLEGAL X-OP *** + +BADOPX: LDA #1 + JMP ZERROR + + ; HANDLE AN XCALL OPCODE + +OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + STA ABYTE + JSR NEXTPC + STA BBYTE + LDA ABYTE ; ONE TO START WITH + LDX #0 + STX ADEX ; INIT ARGUMENT INDEX + BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP +XCALL1: LDA ABYTE ; GET ARG BYTE + ASL A ; SHIFT NEXT 2 BITS + ASL A ; INTO BITS 7 & 6 + STA ABYTE ; HOLD FOR LATER +XCALL2: AND #%11000000 ; MASK OUT GARBAGE + BNE XCALL3 + JSR GETLNG ; 00 = LONG IMMEDIATE + JMP XCNXT +XCALL3: CMP #%01000000 ; SHORT IMMED? + BNE XCALL4 ; NO, TRY ANOTHER + JSR GETSHT ; 01 = SHORT IMMED. + JMP XCNXT +XCALL4: CMP #%10000000 ; LAST TEST + BNE OPX4 ; 11 = NO MORE ARGS + JSR GETVAR ; 10 = VARIABLE +XCNXT: LDX ADEX + LDA VALUE+LO + STA ARG1+LO,X + LDA VALUE+HI + STA ARG1+HI,X + INC NARGS + INX + INX + STX ADEX + CPX #16 + BEQ OPX4 ; DONE, GO DO IT + CPX #8 ; DONE 1ST MODE BYTE? + BNE XCALL1 ; NOT QUITE YET + LDA BBYTE ; SET UP FOR NEXT + STA ABYTE ; MODE BYTE + JMP XCALL2 ; GO DO IT + + + +; ------------- +; HANDLE A 0-OP +; ------------- + +OP0: AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT0L,Y + STA GO0+1+LO + LDA OPT0H,Y + STA GO0+1+HI +GO0: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #2 -- ILLEGAL 0-OP *** + +BADOP0: LDA #2 + JMP ZERROR + + + +; ------------- +; HANDLE A 1-OP +; ------------- + +OP1: AND #%00110000 ; ISOLATE ARGUMENT BITS + BNE OP1A + + ;JSR GETLNG ; 00 = LONG IMMEDIATE + + JSR NEXTPC + JMP OP1A1 +OP1A: AND #%00100000 ; TEST AGAIN + BNE OP1B + + ;JSR GETSHT ; 01 = SHORT IMMEDIATE + +OP1A1: STA ARG1+HI + JSR NEXTPC + STA ARG1+LO + INC NARGS + JMP OP1EX1 +OP1B: JSR GETVAR ; 10 = VARIABLE +OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] +OP1EX1: LDA OPCODE + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT1L,Y + STA GO1+1+LO + LDA OPT1H,Y + STA GO1+1+HI +GO1: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 + + STA ARG1+HI + JSR NEXTPC + STA ARG1+LO + INC NARGS + JMP OP2B1 +OP2A: JSR GETVAR ; 1 = VARIABLE +OP2B: JSR V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] +OP2B1: LDA OPCODE ; RESTORE OPCODE BYTE + AND #%00100000 ; ISOLATE 2ND ARG BIT + BNE OP2C + + ;JSR GETSHT ; 0 = SHORT IMMEDIATE + + STA ARG2+HI + JSR NEXTPC + STA ARG2+LO + JMP OP2D1 +OP2C: JSR GETVAR ; 1 = VARIABLE +OP2D: LDA VALUE+LO ; MOVE 2ND [VALUE] + STA ARG2+LO ; INTO [ARG2] + LDA VALUE+HI + STA ARG2+HI +OP2D1: INC NARGS ; UPDATE ARGUMENT COUNT + + ; EXECUTE A 2-OP OR EXTENDED 2-OP + +OP2EX: LDA OPCODE + AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT2L,Y + STA GO2+1+LO + LDA OPT2H,Y + STA GO2+1+HI +GO2: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 diff --git a/c-128/ezip/memory.asm b/c-128/ezip/memory.asm new file mode 100644 index 0000000..2629c0b --- /dev/null +++ b/c-128/ezip/memory.asm @@ -0,0 +1,336 @@ + PAGE + STTL "--- COMMODORE 128 MEMORY ACCESS RTNS ---" + + + ORG SHARED + + ; THIS CODE MUST BE ACCESSIBLE FROM BOTH BANK0 AND BANK1 + ; THEREFORE IT WILL BE IN THE "SHARED" SECTION OF MEMORY + + ; ------ + ; GETBYT + ; ------ + +GETBYT: LDY MPCBNK ;SELECT CURRENT BANK + LDA BANK0,Y ;ENABLE READ + STA CR + LDY MPCL + LDA (MPCPNT),Y ;GET THE BYTE + LDX BANK1 ;KILL (FOR SAFTY) + STX CR + INC MPCL ;POINT TO NEXT BYTE + BNE GETGOT ;IF NO CROSS WE ARE STILL VALID + JSR CRSMPC +GETGOT: TAY ;SET FLAGS + RTS ;RED SLIPPER TIME + + + ; ------ + ; NEXTPC + ; ------ + + ; LIKE GETBYT + +NEXTPC: LDY ZPCBNK + LDA BANK0,Y + STA CR + LDY ZPCL + LDA (ZPCPNT),Y + LDX BANK1 ;KILL + STX CR + INC ZPCL + BNE NXTGOT + JSR CRSZPC +NXTGOT: TAY + RTS + + + ; ----------- + ; READ SECTOR + ; ----------- + + ; NOW HAVE TRACK & SECTOR, READ THE DISK + +GETRES: CLC ; CARRY CLEAR = "READ BLOCK" + JSR DISK ; GO DO IT! + BCC GOT + RTS + ;JMP DSKERR ; ERROR IF CARRY SET + +GOT: LDY DSKBNK ; SET TO PROPER BANK + LDA BANK0,Y + STA CR + + LDY #0 ; MOVE CONTENTS OF [IOBUFF] +GDKL: LDA IOBUFF,Y ; TO THE + STA (DBUFF),Y ; TARGET PAGE IN [DBUFF] + INY + BNE GDKL + + LDA BANK1 ; RESET TO MAIN BANK + STA CR + + INC DBUFF+HI ; POINT TO NEXT PAGE + LDA DBUFF+HI + CMP #MAINEND+1 ; PAST LAST MAIN RAM PAGE ? + BCC GDEX ; NO + LDA #AUXSTART ; RESET DBUFF TO FIRST AUX PAGE + STA DBUFF+HI + LDA #AUX ; SET DSKBNK TO AUX + STA DSKBNK +GDEX: JMP NXTDBL ; POINT TO NEXT DBLOCK, SECTOR & TRACK + + + ; ------------- + ; KERNAL ACCESS + ; ------------- + + ; THESE RTNS WILL SWITCH TO BANK0 WHERE THE KERNAL + ; CAN BE ACCESSED, CALL THE WANTED RTN AND THEN + ; SWITCH BACK TO BANK1 TO RESUME WITH EZIP + +CHKIN: PHA ; SAVE [A] IN CASE IS NEEDED + LDA BANK0 ; SET TO BANK0 WHERE CAN ACCESS KERNAL + STA CR + PLA + JSR RCHKIN ; AND CALL KERNAL RTN + PHA + LDA BANK1 ; THEN SET BACK TO MAIN BANK + STA CR + PLA + RTS + +CHKOUT: PHA + LDA BANK0 + STA CR + PLA + JSR RCHKOUT + PHA + LDA BANK1 + STA CR + PLA + RTS + +CHRIN: PHA + LDA BANK0 + STA CR + PLA + JSR RCHRIN + PHA + LDA BANK1 + STA CR + PLA + RTS + +CHROUT: PHA + LDA BANK0 + STA CR + PLA + JSR RCHROUT + PHA + LDA BANK1 + STA CR + PLA + RTS + +CLALL: PHA + LDA BANK0 + STA CR + PLA + JSR RCLALL + PHA + LDA BANK1 + STA CR + PLA + RTS + +CLOSE: PHA + LDA BANK0 + STA CR + PLA + JSR RCLOSE + PHA + LDA BANK1 + STA CR + PLA + RTS + +CLRCHN: PHA + LDA BANK0 + STA CR + PLA + JSR RCLRCHN + PHA + LDA BANK1 + STA CR + PLA + RTS + +GETIN: PHA + LDA BANK0 + STA CR + PLA + JSR RGETIN + PHA + LDA BANK1 + STA CR + PLA + RTS + +OPEN: PHA + LDA BANK0 + STA CR + PLA + JSR ROPEN + PHA + LDA BANK1 + STA CR + PLA + RTS + +PLOT: PHA + LDA BANK0 + STA CR + PLA + JSR RPLOT + PHA + LDA BANK1 + STA CR + PLA + RTS + +READST: PHA + LDA BANK0 + STA CR + PLA + JSR RREADST + PHA + LDA BANK1 + STA CR + PLA + RTS + +SCNKEY: PHA + LDA BANK0 + STA CR + PLA + JSR RSCNKEY + PHA + LDA BANK1 + STA CR + PLA + RTS + +SETLFS: PHA + LDA BANK0 + STA CR + PLA + JSR RSETLFS + PHA + LDA BANK1 + STA CR + PLA + RTS + +SETMSG: PHA + LDA BANK0 + STA CR + PLA + JSR RSETMSG + PHA + LDA BANK1 + STA CR + PLA + RTS + +SETNAM: PHA + LDA BANK0 + STA CR + PLA + JSR RSETNAM + PHA + LDA BANK1 + STA CR + PLA + RTS + + ; THE TWO FILE NAMES CALLED WITH SETNAM, THEY NEED + ; TO BE ACCESSIBLE FROM BANK0 FOR THE CALL + +I0: DB "I0" +I0L EQU $-I0 + +POUND: DB "#" +POUNDL EQU $-POUND + + +; -------------------------------- +; RETURN RANDOM BYTES IN [A] & [X] +; -------------------------------- + +RANDOM: LDA BANK0 + STA CR + INC RAND ; RANDOM FROM APPLE (11/4/86 LD) + DEC RASTER + LDA RAND + ADC RNUM1 + TAX + LDA RASTER + SBC RNUM2 + STA RNUM1 + STX RNUM2 + LDY BANK1 + STY CR + RTS + +RNUM1: DB 0 +RNUM2: DB 0 + + +BOOP: LDA BANK0 + STA CR + + LDA #96 ; FREQ LSB + STA FRELO1 + LDA #22 ; MSB + STA FREHI1 + LDA #$F2 + STA TIME + JMP SOUND + +BEEP: LDA BANK0 + STA CR + + LDA #60 ; FREQ LSB + STA FRELO1 + LDA #50 ; MSB + STA FREHI1 + LDA #$FC + STA TIME + +SOUND: LDA #%11110000 + STA SUREL1 ; FULL SUSTAIN + LDA #%10001111 + STA SIGVOL ; FULL VOLUME + LDA #%01000001 + STA VCREG1 ; START PULSE + +RAZZ: LDA TIME + BNE RAZZ + + STA VCREG1 ; STOP PULSE + LDA #%10000000 + STA SIGVOL ; VOLUME OFF + + LDA BANK1 ; RESET SYSTEM + STA CR + RTS + + + DB 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + DB 00,00,00,00,00,00,00,00 + + ; FILL OUT THE SECTOR NICE NICE SO IT'S ALL ALIGNED HAPPY + + + END diff --git a/c-128/ezip/objects.asm b/c-128/ezip/objects.asm new file mode 100644 index 0000000..e4e4de8 --- /dev/null +++ b/c-128/ezip/objects.asm @@ -0,0 +1,198 @@ + PAGE + STTL "--- OBJECT & PROPERTY HANDLERS ---" + + +; ******************************************** +; AN ASSUMPTION HAS BEEN MADE WITH EZIP OBJECT +; HANDLING. THAT IS THAT ALL THIS STUFF IS +; BEFORE PURBOT AND IS IN MAIN MEMORY +; AND THEREFORE DIRECT ACCESSING IS JUST FINE +; LINDE +; ******************************************** +; ---------------------------------- +; GET ABSOLUTE ADDRESS OF OBJECT [A] +; ---------------------------------- +; ENTER: OBJECT IN A/X (LO/HI) +; EXIT: ADDRESS IN [I] +; (EZIP VERSION) + +OBJLOC: STX I+HI ; SAVE MSB FOR SHIFTING + ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) + STA I+LO + ROL I+HI + LDX I+HI + ASL A + ROL I+HI ; *4 + ASL A + ROL I+HI ; *8 + ASL A + ROL I+HI ; *16 + SEC + SBC I+LO ; -(*2) + STA I+LO ; SO IS *14 TOTAL + LDA I+HI + STX I+HI + SBC I+HI + STA I+HI + LDA I+LO + CLC + ADC #112 ; ADD OBJECT TABLE OFFSET + BCC OBJ3 + INC I+HI +OBJ3: 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC + LDY #12 ; (EZIP) + 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 #%00111111 ; MASK OUT LENGTH BITS (EZIP) + RTS + + +; ------------------------------- +; FETCH # BYTES IN PROPERTY VALUE +; ------------------------------- +; ENTRY: LIKE "PROPB" EXIT +; (EZIP) + +PROPL: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + RTS + +SHORT: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE + LDA #2 ; BIT 6 = 1, LENGTH =2 + RTS +ONE: LDA #1 ; BIT 6 = 0, LENGTH =1 + RTS + + +; ---------------------- +; POINT TO NEXT PROPERTY +; ---------------------- +; ENTRY: LIKE "PROPB" EXIT + +PROPNX: JSR PROPL ; GET LENGTH OF CURRENT PROP + TAX ; SAVE HERE +PPX: INY ; LOOP UNTIL + BNE PPY + INC I+LO + BNE PPY + INC I+HI +PPY: DEX ; [Y] POINTS TO + BNE PPX ; START OF NEXT PROP + INY ; CORRECT ALIGNMENT + RTS + + +; ----------------------------------------- +; CALL PROPNX, THEN ALIGN [I] AT THAT ENTRY +; ----------------------------------------- +; EXIT: [I] IS ALIGNED AT CURRENT PROPERTY +; [Y] IS ZEROED +; (EZIP) + +NEXTPI: JSR PROPNX ; GET ALIGNMENT OF NEXT PROPERTY INTO [Y] + TYA ; ADD OFFSET TO NEXT PROP + CLC ; TO [I] SO I POINTS DIRECTLY + ADC I+LO ; AT IT + STA I+LO + BCC NXTPI1 + INC I+HI ; ADD IN CARRY +NXTPI1: LDY #0 ; CLEAR [Y] AS IT IS USED AS AN INDEX + 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 ; (EZIP) + LDX ARG1+HI + 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 + CMP #$10 ; CHECK IF IN 2ND WORD + BCC FLS ; YES, GO ALIGN FOR THAT + SBC #16 ; ELSE ALIGN TO 3RD WORD + TAX + LDA I+LO + CLC + ADC #4 ; 3RD FLAG WORD + STA I+LO + BCC FLS0 + INC I+HI + JMP FLS0 ; (END EZIP CHGS) +FLS: 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 diff --git a/c-128/ezip/ops012.asm b/c-128/ezip/ops012.asm new file mode 100644 index 0000000..0995f46 --- /dev/null +++ b/c-128/ezip/ops012.asm @@ -0,0 +1,1177 @@ + PAGE + STTL "--- 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: LDX #5 ;MOVE ZPC INTO MPC +ZPRI1: + LDA ZPC,X + STA MPC,X + DEX + BPL ZPRI1 ;NO NEED TO VALIDATE AS ZPC WAS VALID ANYWAY + JSR PZSTR ; PRINT THE Z-STRING AT [MPC] + LDX #5 ; COPY STATE OF [MPC] +ZPRI2: LDA MPC,X ; INTO [ZPC] + STA ZPC,X + DEX + BPL ZPRI2 + 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: LDA TOP ; SET SO MSG'S DON'T SCROLL + STA WTOP ; OVER STATUS LINES + + JSR ZCRLF ; DISPLAY VERSION NUMBER, GET SIDE 1 + LDX #3 + LDA #0 +ZVR: STA K+LO,X ; CLEAR [K], [L] + 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 ZBEGIN+ZLENTH ; GET MSB + STA I+HI ; AND + LDA ZBEGIN+ZLENTH+1 ; LSB OF Z-CODE LENGTH IN BYTES + ASL A ; MULTIPLY BY + ROL I+HI ; FOUR + ROL K+LO + ASL A + STA I+LO + ROL I+HI ; TO GET # BYTES + ROL K+LO ; IN GAME + LDA #0 ; START AT BEGINNING + STA DBLOCK+LO + STA DBLOCK+HI + JMP READIN ; READ FIRST BLOCK IN + +VSUM: LDA MPCL ; NEW PAGE? + BNE VSUM2 ; NO, CONTINUE +READIN: LDA #>IOBUFF ; FAKE READ OUT SO + STA DBUFF+HI ; IT DOESN'T MOVE BUFFER + LDA #MAIN + STA DSKBNK ; SET FOR MAIN BANK + JSR GETDSK ; GO READ A PAGE + BCC VSUM2 + JMP DSKERR ; BAD DISK!!!!! + +VSUM2: LDY MPCL ; GET THIS BYTE + LDA IOBUFF,Y + INC MPCL ; SET FOR NEXT BYTE + BNE VSUM3 + INC MPCM + BNE VSUM3 + INC MPCH +VSUM3: CLC + ADC L+LO ; ADD IT TO SUM + STA L+LO ; IN [J] + BCC VSUM1 + INC L+HI +VSUM1: LDA MPCL ; END OF Z-CODE YET? + CMP I+LO ; CHECK LSB + BNE VSUM + LDA MPCM ; MIDDLE BYTE + CMP I+HI + BNE VSUM + LDA MPCH ; AND HIGH BIT + CMP K+LO + BNE VSUM + + LDA #0 ; RESET SCREEN ROLL + STA WTOP ; TO INDIVIDUAL CONTROL + + LDA ZBEGIN+ZCHKSM+1 ; GET LSB OF CHECKSUM + CMP L+LO ; DOES IT MATCH? + BNE BADVER ; NO, PREDICATE FAILS + LDA ZBEGIN+ZCHKSM ; ELSE CHECK MSB + CMP L+HI ; LOOK GOOD? + BNE BADVER ; IF MATCHED, + JMP PREDS ; GAME IS OKAY +BADVER: brk + JMP PREDF + + + + PAGE + STTL "--- 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC ; GET OBJECT ADDR INTO [I] + LDY #8 ; POINT TO "NEXT" SLOT (EZIP) + BNE FIRST1 ; JMP + + +; ------ +; FIRST? +; ------ +; RETURN "FIRST" POINTER IN OBJECT [ARG1] ; +; FAIL IF LAST AND RETURN ZERO +; (EZIP ALTERATIONS) + +ZFIRST: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET OBJECT ADDR INTO [I] + LDY #10 ; POINT TO "FIRST" SLOT +FIRST1: LDA (I),Y ; GET CONTENTS OF SLOT + TAX + INY + LDA (I),Y ; INTO A,X + JSR PUTBYT ; PASS IT TO VARIABLE + LDA VALUE+LO ; EXAMINE THE VALUE JUST "PUT" + BNE PFINE + LDA VALUE+HI + BEQ PYUCK ; FAIL IF IT WAS ZERO +PFINE: JMP PREDS ; ELSE REJOICE + + +; --- +; LOC +; --- +; RETURN THE OBJECT CONTAINING OBJECT [ARG1] ; +; RETURN ZERO IF NONE +; (EZIP ALTERED) + +ZLOC: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + LDY #6 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET THE WORD + TAX + INY + LDA (I),Y + 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 + LDA (I),Y ; OF PROPERTY AT [I] INTO [A] + BMI PTZ2 ; BIT 7 = 1, LENGTH LOW 2 BYTES + AND #%01000000 + BEQ PTZ1 ; BIT 6 = 0, LENGTH = 1 + LDA #2 ; BIT 6 = 1, LENGTH = 2 + BNE PTZ3 ; JMP +PTZ1: LDA #1 + BNE PTZ3 ; JMP +PTZ2: AND #%00111111 ; SIZE > 2 +PTZ3: LDX #0 ; CLEAR FOR PUTBYT + JMP PUTBYT + + +; --- +; INC +; --- +; INCREMENT VARIABLE [ARG1] + +ZINC: LDA ARG1+LO + JSR VARGET ; FETCH VARIABLE INTO [VALUE] + INC VALUE+LO + BNE ZINC1 + INC VALUE+HI +ZINC1: JMP ZD0 + + +; --- +; DEC +; --- +; DECREMENT VARIABLE [ARG1] + +ZDEC: LDA ARG1+LO + JSR VARGET ; FETCH VAR INTO [VALUE] + LDA VALUE+LO + SEC + SBC #1 + STA VALUE+LO + LDA VALUE+HI + SBC #0 + STA VALUE+HI +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 +; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO +; 2) MOVES AND COMPARES 2 BYTES) + +ZREMOV: LDA ARG1+LO ; GET SOURCE OBJECT ADDR + LDX ARG1+HI + 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 #7 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET THE DATA + STA K ; HOLD IT + DEY + LDA (I),Y + TAX ; X = HI + LDA K ; A = LO + ORA (I),Y ; COMPARE BYTES + BEQ REMVEX ; SCRAM IF NO OBJECT + LDA K ; PICK UP, DESTROYED BY ORA + JSR OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [I] + LDY #10 ; POINT TO "FIRST" SLOT + LDA (I),Y ; GRAB DATA + TAX + INY + LDA (I),Y ; A=LO, X=HI + CMP ARG1+LO ; IS THIS THE FIRST? + BNE REMVC1 ; NO, KEEP SEARCHING + CPX ARG1+HI ; HM? + BNE REMVC1 + LDY #8 ; ELSE COPY SOURCE'S "NEXT" SLOT + LDA (J),Y + INY ; INTO DEST'S "FIRST" SLOT ([Y] = 10) + INY + STA (I),Y + DEY ; BACK UP TO GET HIGH BYTE + LDA (J),Y + INY + INY + STA (I),Y + BNE REMVC2 ; BRANCH ALWAYS +REMVC1: JSR OBJLOC + LDY #8 ; GET "NEXT" + LDA (I),Y + TAX + INY + LDA (I),Y + CMP ARG1+LO ; FOUND IT? + BNE REMVC1 ; NO, KEEP TRYING + CPX ARG1+HI + BNE REMVC1 + LDY #8 ; WHEN FOUND + LDA (J),Y ; MOVE "NEXT" SLOT OF SOURCE (THIS OBJECT) + STA (I),Y ; TO "NEXT" SLOT OF DEST + ;(OBJECT THAT REFERENCED THIS ONE) + INY + LDA (J),Y + STA (I),Y +REMVC2: LDA #0 + LDY #6 ; CLEAR "LOC" + STA (J),Y + INY + STA (J),Y + INY ; AND "NEXT" SLOTS ([Y] = 5) + STA (J),Y ; OF SOURCE OBJECT (ARG1) + INY + STA (J),Y +REMVEX: RTS + + +; ------ +; PRINTD +; ------ +; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + +ZPRD: LDA ARG1+LO + LDX ARG1+HI ; (EZIP) + + ; ENTRY POINT FOR "USL" + +PRNTDC: JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + LDY #12 ; GET PROP TABLE POINTER (EZIP) + 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+LO ; RE-SYNC THE + STA ZSP+LO ; Z-STACK POINTER + LDA OLDZSP+HI + STA ZSP+HI + 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 + + ;EZIP STX OLDZSP + + STA ZPCL + JSR POPVAL + STX OLDZSP+LO + STA OLDZSP+HI + JSR VLDZPC ;MAKE VALID + JSR A12VAL ; MOVE [ARG1] TO [VALUE] +PATCHI EQU $+1 ; FOR ZINPUT RTN (IF A FCN CALL) (EZIP) + 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 (QUAD) 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 + + + + PAGE + STTL "--- 2-OPS ---" + + +; ----- +; LESS? +; ----- +; [ARG1] HIGH [ARG2]? + +ZLESS: JSR A12VAL ; MOVE [ARG1] TO [VALUE] + JMP DLS0 ; MOVE [ARG2] TO [I] & COMPARE + + +; ------ +; DLESS? +; ------ +; DECREMENT [ARG1] ; SUCCEED IF HIGH [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] LOW [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 + + +; ----------------- +; SIGNED COMPARISON +; ----------------- +; ENTRY: VALUES IN [VALUE] AND [I] + +COMPAR: LDA I+HI + EOR VALUE+HI + BPL SCMP + LDA I+HI + CMP VALUE+HI + BCC PGOOD + JMP PREDF + +SCMP: LDA VALUE+HI + CMP I+HI + BNE SCEX + LDA VALUE+LO + CMP I+LO +SCEX: BCC PGOOD + JMP PREDF + + +; --- +; IN? +; --- +; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? + +ZIN: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [I] + LDY #6 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET DATA + CMP ARG2+HI ; IS IT THERE? + BNE PBAD ; NO + INY + LDA (I),Y + CMP ARG2+LO + 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 [ARG2] SET IN OBJECT [ARG1]? + +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] +; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + +ZMOVE: JSR ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS + + ; NOW, IF IT IS ANYWHERE + + LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET SOURCE OBJECT ADDR INTO [I] + LDA I+LO ; COPY SOURCE (ARG1) ADDRESS + STA J+LO ; INTO [J] + LDA I+HI + STA J+HI + LDA ARG2+HI ; GET DEST OBJECT ID + LDY #6 ; POINT TO "LOC" SLOT OF SOURCE + STA (I),Y ; AND MOVE IT IN + TAX ; (MOVE ARG2 INTO PARENT SLOT OF ARG1) + LDA ARG2+LO + INY + STA (I),Y ; X/A (HI/LO) SET FOR OBJLOC + JSR OBJLOC ; GET ADDR OF DEST OBJECT INTO [I] (GET PARENT) + + ; NOW SWAP IN NEW VALUE + + LDY #10 ; POINT TO "FIRST" SLOT + LDA (I),Y ; OF PARENT (ARG2) + STA K+HI ; SAVE HERE FOR A MOMENT + LDA ARG1+HI ; GET SOURCE OBJECT ID + STA (I),Y ; MAKE IT "FIRST" OF PARENT + INY + LDA (I),Y + TAX + LDA ARG1+LO + STA (I),Y + TXA + ORA K+HI ; CHECK OLD "FIRST" OF DEST/PARENT + BEQ ZMVEX ; SCRAM IF ZERO + TXA ; GET LO BYTE AGAIN + LDY #9 ; MAKE OLD "FIRST" OF PARENT + STA (J),Y ; THE "NEXT" (SIBLING) OF THIS OBJECT (ARG1) + DEY ; I.E. ADD THIS ONE AT THE TOP OF LIST + LDA K+HI ; & GET HIGH BYTE + STA (J),Y +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 + LDA #0 + 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 + ADC #0 ; PICK UP CARRY FROM MPCM + STA MPCH ; TO GET TOP BIT + JMP VLDMPC + + +; ---- +; GETP +; ---- +; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 + +ZGETP: JSR PROPB +GETP1: JSR PROPN ; GET ADDR OF PROP TBL + CMP ARG2+LO ; GET PROP ID + BEQ GETP3 ; FOUND IT + BCC GETP2 ; NOT THERE + JSR NEXTPI ; GET NEXT PROP, ALIGN [I] TO IT (EZIP) + JMP GETP1 ; TRY AGAIN WITH NEXT PROP + + ; PROPERTY NOT THERE, GET DEFAULT + +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 ; GET LENGTH OF PROP INTO [A] + INY ; MAKE [Y] POINT TO 1ST BYTE OF PROP + CMP #1 ; IF LENGTH =1 + BEQ GETPB ; GET A BYTE PROPERTY + CMP #2 ; IF LENGTH = 2 + 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 + + IF 0 + +; ----- +; GETPT +; ----- +; RETURN POINTER TO PROP TABLE [ARG2] +; IN OBJECT [ARG1] + +ZGETPT: JSR PROPB ; GET ADDR OF PROP TBL +GETPT1: JSR PROPN ; RETURNS OFFSET IN [Y] + CMP ARG2+LO ; CHECK ID + BEQ GETPT2 + BCC DORET ; BEYOND IT, SO NOT THERE + JSR NEXTPI ; GET NEXT PROPERTY, ALIGN [I] TO IT (EZIP) + JMP GETPT1 +GETPT2: JSR PROPL ; ALIGN Y @ LAST SIZE BYTE (EZIP) + INY ; INC TO POINT AT PROPERTY VALUE (EZIP) + +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 + + ENDIF + +; ----- +; GETPT +; ----- +; RETURN POINTER TO PROP TABLE [ARG2] +; IN OBJECT [ARG1] + +ZGETPT: LDA ARG1+LO + LDX ARG1+HI ; (EZIP) + JSR OBJLOC + LDY #12 ; (EZIP) + 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 + +GETPT1: LDA (I),Y + AND #%00111111 ; MASK OUT LENGTH BITS (EZIP) + + CMP ARG2+LO ; CHECK ID + BEQ GETPT2 + BCS DDD + JMP DORET ; BEYOND IT, SO NOT THERE + +DDD: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT0 ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + JMP AAA + +SHORT0: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE0 + LDA #2 ; BIT 6 = 1, LENGTH =2 + JMP AAA +ONE0: LDA #1 ; BIT 6 = 0, LENGTH =1 + +AAA: TAX ; SAVE HERE +PPPX: INY ; LOOP UNTIL + BNE PPPY + INC I+HI +PPPY: DEX ; [Y] POINTS TO + BNE PPPX ; START OF NEXT PROP + INY ; CORRECT ALIGNMENT + TYA ; ADD OFFSET TO NEXT PROP + CLC ; TO [I] SO I POINTS DIRECTLY + ADC I+LO ; AT IT + STA I+LO + BCC CCCC1 + INC I+HI ; ADD IN CARRY +CCCC1: LDY #0 ; CLEAR [Y] AS IT IS USED AS AN INDEX + + JMP GETPT1 + +GETPT2: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT1 ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + JMP BBB + +SHORT1: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE1 + LDA #2 ; BIT 6 = 1, LENGTH =2 + JMP BBB +ONE1: LDA #1 ; BIT 6 = 0, LENGTH =1 + +BBB: INY ; INC TO POINT AT PROPERTY VALUE (EZIP) +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 [AR +; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO + +ZNEXTP: JSR PROPB ; ALIGN [I] AT PROPERTY TBL'S 1ST ENTRY + 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 NEXTPI ; ELSE TRY NEXT PROPERTY (EZIP) + JMP NXTP1 +NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +NXTP3: JSR PROPN ; GET THE PROPERTY # + LDX #0 ; FOR PUTBYT (EZIP) + 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 diff --git a/c-128/ezip/opsx.asm b/c-128/ezip/opsx.asm new file mode 100644 index 0000000..2dd1a06 --- /dev/null +++ b/c-128/ezip/opsx.asm @@ -0,0 +1,443 @@ + PAGE + STTL "--- 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!) + + +; ------------------- +; XCALL, CALL1, CALL2 +; ------------------- + +ZXCALL: ; DROP THROUGH +ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +ZCALL2: + + +; ---- +; CALL +; ---- +; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +; ([ARG5]-[ARG8] FOR XCALL (EZIP)) + +ZCALL: LDA ARG1+LO + ORA ARG1+HI ; IS CALL ADDRESS ZERO? + BNE DOCALL ; NO, CONTINUE + LDX #0 + JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER + LDA OLDZSP+HI + JSR PUSHXA + LDA ZPCL ; AND LSB OF [ZPC] + JSR PUSHXA ; ON THE Z-STACK ([X] NOT USED HERE - EZIP) + 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 + ASL ARG1+LO ; MULTIPLY [ARG1] + ROL ARG1+HI ; (BY 2) + ROL A ; HIGH BIT INTO [A] + STA ZPCH ; NEW HIGH BIT OF [ZPC] + ASL ARG1+LO ; BY 4 (EZIP) + ROL ARG1+HI + ROL ZPCH + LDA ARG1+HI ; GET NEW LOW BYTES + STA ZPCM + LDA ARG1+LO + STA ZPCL + JSR VLDZPC + JSR NEXTPC ; FETCH # LOCALS TO PASS + STA J+LO ; SAVE HERE FOR COUNTING + STA J+HI ; AND HERE FOR LATER REFERENCE + BEQ ZCLL2 ; SKIP IF NO LOCALS + LDA #0 + STA I+LO ; ELSE INIT STORAGE INDEX +ZCLL1: LDY I+LO + LDX LOCALS+LO,Y ; GET LSB OF LOCAL INTO [X] + LDA LOCALS+HI,Y ; AND MSB INTO [A] + 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 ZCLL1 ; YES, KEEP LOOPING + + ; MOVE UP TO 3 ARGUMENTS TO [LOCALS] ( 7 FOR XCALL (EZIP)) + +ZCLL2: 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 + DEC NARGS ; MORE (THAT MEANS IT'S AN XCALL) + BEQ ZCALL3 ; NO, JUST A CALL + LDA ARG5+LO ; MOVE [ARG5] TO LOCAL #4 + STA LOCALS+LO+6 + LDA ARG5+HI + STA LOCALS+HI+6 + DEC NARGS ; MORE? + BEQ ZCALL3 ; NO + LDA ARG6+LO ; MOVE [ARG6] TO LOCAL #5 + STA LOCALS+LO+8 + LDA ARG6+HI + STA LOCALS+HI+8 + DEC NARGS ; MORE? + BEQ ZCALL3 ; NO + LDA ARG7+LO ; MOVE [ARG7] TO LOCAL #6 + STA LOCALS+LO+10 + LDA ARG7+HI + STA LOCALS+HI+10 + DEC NARGS ; MORE? + BEQ ZCALL3 ; NO + LDA ARG8+LO ; MOVE [ARG8] TO LOCAL #7 + STA LOCALS+LO+12 + LDA ARG8+HI + STA LOCALS+HI+12 +ZCALL3: LDX J+HI ; RETRIEVE # LOCALS + TXA ; DUPE FOR NO GOOD REASON + JSR PUSHXA ; PUSH # LOCALS ONTO Z-STACK + LDA ZSP+HI ; REMEMBER WHERE + STA OLDZSP+HI ; WE CAME FROM + LDA ZSP+LO + STA OLDZSP+LO + 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 ; GET PROP TBL ADDR + +PUTP1: JSR PROPN ; GET ID + CMP ARG2+LO + BEQ PUTP2 + BCC PNERR ; ERROR IF LOWER + JSR NEXTPI ; TRY NEXT PROPERTY, ALIGN [I] AT IT (EZIP) + JMP PUTP1 +PUTP2: JSR PROPL ; GET PROPERTY LENGTH INTO [A] + INY ; MAKE [Y] POINT TO 1ST PROPERTY BYTE + CMP #1 ; IF LENGTH = 1 + BEQ PUTP3 ; PUT A BYTE + CMP #2 ; PUT A WORD IF [A] = 2 + 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 DB II 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 DB II + 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 ; IF VALUE IS ZERO + ORA ARG1+HI + BNE ZRAND1 + STA SRHOLD+LO ; RETURN TO RANDOM RANDOM + STA SRHOLD+HI ; CLEAR INDICATOR + JMP RET0 ; AND RETURN THRU HERE SO ALIGNED +ZRAND1: LDA SRHOLD+LO ; ARE WE NONRAMDOM INCREMENTING? (EZIP) + ORA SRHOLD+HI + BNE ZRAND3 ; YUP + LDA ARG1+HI + BPL ZRAND2 ; GENERATE A RANDOM # + EOR #$FF ; SET UP TO INCREMENT FROM 1 THRU INT + STA SRHOLD+HI ; GET ABSOLUTE + LDA ARG1+LO + EOR #$FF + STA SRHOLD+LO + INC SRHOLD+LO + LDA #0 ; W/ NO RAMDOMNESS + STA RAND1+LO + STA RAND1+HI + BEQ ZRAND3 ; JMP (END EZIP) +ZRAND2: 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 + CLC + ADC #1 ; ADD 1 + STA VALUE+LO ; INTO [VALUE] + LDA REMAIN+HI + ADC #0 + STA VALUE+HI + JMP PUTVAL ; AND RETURN RESULT + + ; NON RANDOM INCREMENTING + +ZRAND3: LDA SRHOLD+HI ; RESET TOP OF COUNT IF NECESSARY + CMP ARG1+HI ; SO ALWAYS W/IN RANGE OF CALL + BCC ZRAND7 + BNE ZRAND6 + LDA ARG1+LO + CMP SRHOLD+LO + BCS ZRAND7 + +ZRAND6: LDA ARG1+HI ; NEW LOWER, SO SUBSTITUTE + STA SRHOLD+HI + LDA ARG1+LO + STA SRHOLD+LO + +ZRAND7: LDA RAND1+HI ; (EZIP) + CMP SRHOLD+HI + BCC ZRAND4 + LDA RAND1+LO + CMP SRHOLD+LO + BCC ZRAND4 + BEQ ZRAND4 + LDA #1 ; WENT THRU ALL + STA RAND1+LO ; START AGAIN + LDA #0 + STA RAND1+HI +ZRAND4: LDA RAND1+LO + STA VALUE+LO + LDA RAND1+HI + STA VALUE+HI + INC RAND1+LO ; FOR NEXT TIME + BNE ZRAND5 + INC RAND1+HI +ZRAND5: JMP PUTVAL ; (END EZIP) + + +; ---- +; 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 + + +; ------ +; INTBL? +; ------ + +ZINTBL: LDA ARG2+LO ; PICK UP TBL ADDR + STA MPCL + LDA ARG2+HI + STA MPCM + LDA #0 + STA MPCH ; ONLY A WORD ADDR, SO IN 1ST 64K + JSR VLDMPC +INTLP: JSR GETBYT ; GET A WORD ENTRY FROM TBL + STA I+HI + JSR GETBYT + CMP ARG1+LO ; DOES IT = THE VALUE LOOKING FOR? + BNE INTNXT ; NO + LDA I+HI + CMP ARG1+HI + BEQ INTFND ; YES, FOUND IT +INTNXT: DEC ARG3+LO + BNE INTLP + LDA ARG3+HI + BEQ INTNF ; NOT FOUND + DEC ARG3+HI + JMP INTLP ; GO DO SOME MORE +INTFND: SEC + LDA MPCL + SBC #2 + STA MPCL + BCS INTEX + DEC MPCM ; ONCE AGAIN, RETURNING WORD SO 64K LIMIT +INTEX: STA VALUE+LO ; AND SET TO RETURN THE VALUE + LDA MPCM + STA VALUE+HI + JSR PUTVAL ; SEND IT BACK + JMP PREDS ; AND SCREEM SUCCESS +INTNF: LDA #0 ; 0 = NOT FOUND + STA VALUE+LO + STA VALUE+HI + JSR PUTVAL + JMP PREDF ; FAILED! + + END diff --git a/c-128/ezip/read.asm b/c-128/ezip/read.asm new file mode 100644 index 0000000..fcb9ec9 --- /dev/null +++ b/c-128/ezip/read.asm @@ -0,0 +1,453 @@ + PAGE + STTL "--- READ HANDLER ---" + + +; ---- +; READ +; ---- +; READ LINE INTO TABLE [ARG1] ; PARSE INTO TABLE [ARG2] + +ZREAD: ;JSR ZUSL ; UPDATE THE STATUS LINE (NOT IN EZIP) + LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + CLC ; ABSOLUTE + ADC ZCODE + STA RDTBL1+HI ; AND PLACE IT HERE TO USE + LDA ARG1+LO + STA RDTBL1+LO ; LSBS NEED NOT CHANGE + LDA ARG2+HI + CLC + ADC ZCODE + STA RDTBL2+HI + LDA ARG2+LO + STA RDTBL2+LO + + LDY #0 ; GET SIZE OF INPUT BUFFER + LDA (RDTBL1),Y + CMP #79 ; IF OVER 78, CUT DOWN TO 78 + BCC LEAVIT ; LEAVE IT AS IT IS, IT IS LESS + LDA #78 +LEAVIT: STA CHRMAX ; SET COUNTER FOR INPUT + JSR INPUT ; READ LINE; RETURN LENGTH IN [A] + + ; IF TIMEOUT, [A]=0 SO WILL QUIT W/NO RESULTS + + STA LINLEN ; SAVE # CHARS IN LINE + LDA #0 + STA WRDLEN ; INIT # CHARS IN WORD COUNTER + LDY #1 ; POINT TO "# WORDS READ" SLOT + STA (RDTBL2),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 (RDTBL2),Y ; AND READ IT + BEQ RDERR ; (5/14/85 - FORCE # WORDS TO + CMP #60 ; BE BETWEEN 1 AND 59 + BCC RD0 +RDERR: LDA #59 + STA (RDTBL2),Y ; Le) +RD0: INY ; (Y = 1) POINT TO "# WORDS READ" SLOT + CMP (RDTBL2),Y ; TOO MANY WORDS? + BCC RLEX ; YES, SO LEAVE, IGNORING THE REST + +; BCS RL1 ; CHANGED 5.2.85 IN ZIP & EZIP +; ; *** ERROR #13: PARSER OVERFLOW *** +; +; LDA #13 +; JMP ZERROR + +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 #9 ; 9 CHARS DONE? (EZIP) + 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 #8 ; 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 (RDTBL1),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 (RDTBL1),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 DB II IN [IN] TO Z-STRING + JSR FINDW ; AND LOOK IT UP IN VOCABULARY + LDY #1 + LDA (RDTBL2),Y ; FETCH THE # WORDS READ + CLC + ADC #1 ; INCREMENT IT + STA (RDTBL2),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 RDTBL2+LO ; LSB OF RESULT TABLE BASE + CLC + ADC RESULT ; AND CURRENT POINTER + STA ENTRY+LO ; SAVE IN [ENTRY] + LDA RDTBL2+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 (RDTBL1),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? +; --------------------------------- +; ------------------ +; NORMAL BREAK CHARS +; ------------------ + +BRKTBL: DB '!?,.' ; IN ORDER OF + DB $0D ; DB ENDING FREQUENCY + DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED +NBRKS EQU $-BRKTBL ; # NORMAL BREAKS + +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 + + +; --------------------- +; IS CHAR IN [A] A SIB? +; --------------------- + +SIB: STA IOCHAR ; SAVE TEST CHAR + LDA ZBEGIN+ZVOCAB ; GET 1ST BYTE IN VOCAB TABLE + LDY ZBEGIN+ZVOCAB+1 + STA MPCM + STY MPCL + LDA #0 + STA MPCH + JSR VLDMPC ; GET CORRECT PAGE + JSR GETBYT ; HAS # SIBS + STA J ; USE AS AN INDEX +SBL: JSR GETBYT ; GET NEXT SIB + CMP IOCHAR ; MATCHED? + BEQ FBRK0 ; YES, REPORT IT + DEC J + BNE SBL ; ELSE KEEP LOOPING + LDA IOCHAR + CLC ; NO MATCH, SO + RTS ; EXIT WITH CARRY CLEAR +FBRK0: LDA IOCHAR +FBRK: SEC ; EXIT WITH CARRY SET + RTS ; IF MATCHED WITH A BREAK CHAR + + +; ----------------- +; VOCABULARY SEARCH +; ----------------- +; ENTRY: 6-BYTE TARGET Z-WORD IN [OUT] +; EXIT: VIRTUAL ENTRY ADDRESS IN [VALUE] IF FOUND ; +; OTHERWISE [VALUE] = 0 + +VWLEN EQU I +VWCUR EQU J+HI + +FINDW: LDA ZBEGIN+ZVOCAB ; GET VIRTUAL ADDR OF VOCAB TBL + LDY ZBEGIN+ZVOCAB+1 + STA MPCM + STY MPCL + LDA #0 + STA MPCH + JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # SIBS + CLC + ADC MPCL ; GET ACTUAL BASE ADDR OF VOCAB ENTRIES + STA MPCL + BCC FWL0 + INC MPCM +FWL0: JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # BYTES PER ENTRY (AND MOVE TO NEXT BYTE) + STA ESIZE ; SAVE IT HERE + STA VWLEN+0 ; AND HERE + LDA #0 ; CLEAR REST OF COUNTER + STA VWLEN+1 + STA VWLEN+2 + + JSR GETBYT ;GET # OF ENTRIES IN TBL (MSB) + STA NENTS+HI ; AND STUFF IT IN [NENTS] + JSR GETBYT ; DON'T FORGET THE LSB! + STA NENTS+LO + LDA #0 ; FIND SIZE OF VAOCAB TBL + STA VOCEND ; TO LOCATE THE END OF IT + STA VOCEND+1 + STA VOCEND+2 + LDX ESIZE + +FWL1: CLC + LDA VOCEND ; (# OF ENTRIES) * (ENTRY SIZE) + ADC NENTS+LO + STA VOCEND + LDA VOCEND+1 + ADC NENTS+HI + STA VOCEND+1 + LDA VOCEND+2 + ADC #0 ; PICK UP CARRY + STA VOCEND+2 + DEX + BNE FWL1 + + CLC + LDA VOCEND ; AND ADD LENGTH TO START OF TBL + ADC MPCL ; TO GET END OF TBL + STA VOCEND + LDA VOCEND+1 + ADC MPCM + STA VOCEND+1 + LDA VOCEND+2 + ADC MPCH + STA VOCEND+2 ; TO SAVE FOR TESTING IF PAST END + + LDA VOCEND ; SUBTRACT [ESIZE] SO THAT + SEC ; [VOCEND] POINTS TO REAL LAST ENTRY + SBC ESIZE + STA VOCEND + LDA VOCEND+1 + SBC #0 + STA VOCEND+1 + +; NOP +; NOP +; NOP +; NOP +; NOP +; NOP + + ; BEGIN THE SEARCH! [MPC] NOW POINTS TO 1ST ENTRY + + LSR NENTS+HI ; 2 ALIGN # OF ENTRIES + ROR NENTS+LO +FWCALC: ASL VWLEN+0 ; CALCULATE INITIAL OFFSET FOR SEARCH + ROL VWLEN+1 + ROL VWLEN+2 + LSR NENTS+HI + ROR NENTS+LO + BNE FWCALC + +; LDA NENTS+HI +; BNE FWCALC ; DOUBLE-CHECK + + CLC ; ADD 1ST OFFSET INTO START OF VOCABULARL + LDA MPCL ; WHICH IS CURRENTLY IN MPC + ADC VWLEN+0 + STA MPCL + LDA MPCM + ADC VWLEN+1 + STA MPCM + LDA MPCH + ADC VWLEN+2 + STA MPCH + + SEC ; AVOID FENCE-POST BUG FOR + LDA MPCL ; EXACT-POWER-OF-2 TBL (DUNCAN) + SBC ESIZE + STA MPCL + BCS FWLOOP + LDA MPCM + SEC + SBC #1 + STA MPCM + BCS FWLOOP + LDA MPCH + SBC #0 + STA MPCH + +FWLOOP: LSR VWLEN+2 ; SET FOR NEXT OFFSET, + ROR VWLEN+1 ; WHICH IS HALF THIS ONE + ROR VWLEN+0 + + LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + + JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET 1ST BYTE OF ENTRY + + CMP OUT ; MATCH 1ST BYTE OF TARGET? + BCC WNEXT ; LESS + BNE FWPREV ; GREATER + JSR GETBYT + CMP OUT+1 ; 2ND BYTE MATCHED? + BCC WNEXT + BNE FWPREV ; NOPE + JSR GETBYT + CMP OUT+2 ; 3RD BYTE? + BCC WNEXT + BNE FWPREV ; SORRY ... + JSR GETBYT + CMP OUT+3 ; 4TH BYTE + BCC WNEXT + BNE FWPREV + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BCC WNEXT + BNE FWPREV ; SORRY ... + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + BCS FWPREV ; ELSE BACK UP ... + +WNEXT: LDA VWCUR+0 ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + ADC VWLEN+1 + + BCS WNXT2 ; SAVES CODE (?) + + STA MPCM + + LDA #0 + STA MPCH + +; LDA VWCUR+2 +; ADC VWLEN+2 +; STA MPCH + +; LDA MPCH +; CMP VOCEND+2 ; GONE PAST END? +; BEQ WNXT0 ; MAYBE +; BCS WNXT2 ; YES +; BCC FWMORE ; NO +WNXT0: LDA MPCM + CMP VOCEND+1 + BEQ WNXT1 ; MAYBE + BCS WNXT2 ; YES + BCC FWMORE ; NO +WNXT1: LDA MPCL + CMP VOCEND + BCC FWMORE ; NO + BEQ FWMORE ; NO, EQUAL +WNXT2: LDA VOCEND ; YES, SO POINT TO END OF TBL + STA MPCL + LDA VOCEND+1 + STA MPCM + LDA VOCEND+2 + STA MPCH + JMP FWMORE + +FWPREV: LDA VWCUR+0 ; TO MOVE DOWN, JUST SUBTRACT + SEC ; OFFSET FROM START OF THIS + SBC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + SBC VWLEN+1 + STA MPCM + LDA VWCUR+2 + SBC VWLEN+2 + STA MPCH + +FWMORE: LDA VWLEN+2 ; IF OFFSET HIGH GELOW 1 WORD, CONTINUE + BNE FWM1 + LDA VWLEN+1 + BNE FWM1 + LDA VWLEN+0 + CMP ESIZE + BCC FWFAIL +FWM1: JMP FWLOOP ; AND TRY AGAIN + +FWFAIL: LDA #0 ; NOT FOUND + STA VALUE+LO + STA VALUE+HI + RTS ; THEN RETURN WITH [VALUE] = 0 + +FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD + STA VALUE+LO + LDA VWCUR+1 + STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY + RTS ; WORD VALUE RETURNABLE + + END diff --git a/c-128/ezip/subs.asm b/c-128/ezip/subs.asm new file mode 100644 index 0000000..cc96aa3 --- /dev/null +++ b/c-128/ezip/subs.asm @@ -0,0 +1,351 @@ + PAGE + STTL "--- 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 LOW = 16, + BCS GETVRG ; IT'S GLOBAL + +; HANDLE A LOCAL VARIABLE + +GETVRL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA LOCALS-2+LO,X ; GRAB LSB + STA VALUE+LO + LDA LOCALS-2+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] +; ---------------------------------- +; ZSTACK DOUBLED IN SIZE FOR EZIP +; SO THIS RTN ALL NEW + +POPVAL: LDA ZSP+LO ; IF ZSP+LO IS 0 + BNE POP1 + STA ZSP+HI ; MUST DEC. HI (HI = 0 OR 1 ONLY) +POP1: DEC ZSP+LO ; THEN DEC ZSP LO + BNE POP2 + ORA ZSP+HI ; LO + HI BOTH 0? + BEQ UNDER ; UNDERFLOW IF ZERO! +POP2: LDY ZSP+LO + LDA ZSP+HI + BEQ POP3 ; BOTTOM HALF OF ZSTACK + LDA ZSTKTL,Y ; GET VALUE FROM TOP HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKTH,Y + STA VALUE+HI + RTS + +POP3: LDA ZSTKBL,Y ; GET VALUE FROM BOTTOM HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKBH,Y + STA VALUE+HI + 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: ;STX VALUE+LO ; KLUDGE 4.7.86 Le + ;STA VALUE+HI + + PHA ; HOLD VALUE IN [A] A SEC. + LDY ZSP+LO + LDA ZSP+HI + BEQ PSHBOT ; ON BOTTOM HALF OF STACK + TXA ; **** + STA ZSTKTL,Y ; PUSH VALUE ONTO TOP HALF OF STACK + PLA + STA ZSTKTH,Y + JMP PSHUPD ; NOW UPDATE POINTER + +PSHBOT: TXA ; PLACE VALUE ON ZSTACK + STA ZSTKBL,Y + PLA + STA ZSTKBH,Y +PSHUPD: INC ZSP+LO ; UPDATE ZSTACK POINTER + BNE PSHEX + LDA ZSP+LO + ORA ZSP+HI + BNE OVER ; OVERFLOW IF $200 + INC ZSP+HI ; TO 1 +PSHEX: 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 + +; FLUSH TOP WORD OFF STACK +; AND REPLACE WITH [VALUE] + + LDA ZSP+LO ; IF ZSP+LO =0 + BNE VAR1 ; THEN HI =1 (GUARDED ELSEWHERE) + STA ZSP+HI ; DECREMENT HI (ONLY 0 OR 1) +VAR1: DEC ZSP+LO ; NOW DEC LOW BYTE + BNE PSHVAL + ORA ZSP+HI + BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + BNE PSHVAL ; JMP + + ; RETURN A ZERO +RET0: LDA #0 + LDX #0 + + ; RETURN WORD IN [A], [X] (LO,HI) (EZIP EXPANDED TO A WORD) +PUTBYT: STA VALUE+LO + STX 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: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA VALUE+LO ; GRAB LSB + STA LOCALS-2+LO,X ; SAVE IN LOCAL TABLE + LDA VALUE+HI ; DO SAME TO + STA LOCALS-2+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 PREDB7 ; 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 +PREDB7: 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: LDA VALUE+LO ; SUBTRACT 2 FROM OFFSET + SEC ; IN [VALUE] + SBC #2 + TAX ;SAVE LO BYTE + LDA VALUE+HI + SBC #0 + STA I+LO ;MSB OF OFFSET = LSB OF [I] + LDY #0 ; CLEAR THE MSB + STY I+HI ; OF [I] + ASL A ; EXTEND THE SIGN OF OFFSET + ROL I+HI ; INTO MSB OF [I] + ASL A + ROL I+HI ; (EZIP) + TXA ; GET LSB OF OFFSET + 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 PREDB6 + LDA I+LO ; ELSE CALC NEW UPPER BITS + CLC + ADC ZPCM + STA ZPCM + LDA I+HI + ADC ZPCH + AND #%00000011 ; USE ONLY BIT 0 (& 1 - EZIP) + STA ZPCH + JMP VLDZPC ;MAKE VALID +PREDB6: + + ; FALL THROUGH ... + +; ---- +; NOOP +; ---- + +ZNOOP: RTS + + +; ---------------------- +; MOVE [ARG1] TO [VALUE] +; ---------------------- + +A12VAL: LDA ARG1+LO + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + RTS + + +; ----------------------------------- +; INDICATE STATUS LINE REFRESH NEEDED +; ----------------------------------- + +REFRSH: LDA ZBEGIN+ZSCRIP+1 ; PICK UP LOW BYTE OF FLAG WORD + ORA #%00000100 ; SET BIT 2 + STA ZBEGIN+ZSCRIP+1 ; AND PUT IT BACK + RTS + + END diff --git a/c-128/ezip/warm.asm b/c-128/ezip/warm.asm new file mode 100644 index 0000000..0f94744 --- /dev/null +++ b/c-128/ezip/warm.asm @@ -0,0 +1,181 @@ + PAGE + STTL "--- WARMSTART ROUTINE ---" + + ; ------------- + ; ZIP WARMSTART + ; ------------- + +WARM2: LDA #0 ; CLEAR ALL Z-PAGE VARIABLES + LDX #ZEROPG +ST0: STA 0,X + INX + CPX #ZPGTOP + BCC ST0 + + INC ZSP+LO ; INIT Z-STACK POINTERS + INC OLDZSP+LO ; TO "1" + INC SCRIPT ; ENABLE SCRIPTING + INC SCREENF ; TURN DISPLAY ON + INC SIDEFLG ; SET SIDE 1 + + LDA #%00001110 ; DO IT AGAIN AS JUST + STA BANK0 ; WIPED IT OUT + LDA #%01111111 + STA BANK1 + + ; GRAB THE FIRST BLOCK OF PRELOAD + + LDA #>ZBEGIN ; MSB OF PRELOAD START ADDRESS + STA ZCODE ; FREEZE IT HERE + STA DBUFF+HI ; LSB IS ALWAYS ZERO + LDA #MAIN + STA DSKBNK ;SET TO MAIN BANK + JSR GETDSK ; [DBLOCK] SET TO Z-BLOCK 0 + BCC CHKGAM + JMP DSKERR ; BAD DISK READ + + ; EXTRACT GAME DATA FROM Z-CODE HEADER + +CHKGAM: LDA ZBEGIN+ZVERS ; (EZIP) IS GAME AN EZIP? + CMP #4 + BEQ YESEZ ; YES, CONTINUE + +; *** ERROR #16 -- NOT AN EZIP GAME *** + LDA #16 + JMP ZERROR + +; *** ERROR #0 -- INSUFFICIENT RAM *** +NORAM: LDX #5 + LDY #0 + CLC + JSR PLOT + LDA #0 + JMP ZERROR + +YESEZ: LDX ZBEGIN+ZENDLD ; MSB OF ENDLOAD POINTER + INX ; ADD 1 TO GET + STX ZPURE ; 1ST "PURE" PAGE OF Z-CODE + LDA ZBEGIN+ZMODE ; ENABLE SPLIT-SCREEN, + ORA #%00111011 ; INVERSE, CURSOR CONTROL, + STA ZBEGIN+ZMODE ; SOUND (EZIP) + LDA #EZIPID ; SET INTERPRETER ID + STA ZBEGIN+ZINTWD + LDA #VERSID + STA ZBEGIN+ZINTWD+1 + LDA #$18 ; AND SCREEN PARAMETERS + STA ZBEGIN+ZSCRWD + LDA #80 + STA ZBEGIN+ZSCRWD+1 + 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+ZOBJEC ; NOT TO MENTION + CLC ; THE OBJECT TABLE + ADC ZCODE + STA OBJTAB+HI + LDA ZBEGIN+ZOBJEC+1 ; LSB SAME + STA OBJTAB+LO + + ; FIND SIZE AND NUMBER OF SAVES + + LDA ZBEGIN+ZPURBT ; SIZE OF IMPURE + CMP #$A0 ; MAXIMUM IMPURE IS $A000 (36K) + BCC SIZE0 ; OKAY, CONTINUE + + LDA #13 + JMP ZERROR ; ELSE ERROR #13 (IMPURE TOO BIG) + +SIZE0: + CLC + ADC #6 ; PLUS ZSTACK &... + STA SAVSIZ ; HOW MANY PAGES PER SAVE + + LDX #0 + STX NUMSAV +SIZE1: INC NUMSAV ; INC NUMSAVE WITH EACH + CLC ; POSSIBLE SAVE + ADC SAVSIZ + BCC SIZE1 +SIZE2: INC NUMSAV ; TOTAL SIZE IS 170K, ($298) + CLC + ADC SAVSIZ ; SO DO LOOP FOR 1ST & 2ND $100 + BCC SIZE2 +SIZE3: CMP #$98 + BCS SIZE4 ; BEYOND TOTAL DISK SIZE + INC NUMSAV + CLC + ADC SAVSIZ + BCC SIZE3 + +SIZE4: LDA NUMSAV + CMP #9 + BCC SIZEj + + LDA #9 ; easier to print a 9! +SIZEj: + CLC + ADC #'0' + STA POSTOP ; SET POSITION MSG + + LDY #21 ; POSITION MESSAGE + LDX #14 + CLC + JSR PLOT + + LDX #TMSG + LDY #TMSGL + JSR DLINE + + JMP ENDTST + +TMSG: DB "(Please be patient, this takes a while)" + DB EOL +TMSGL EQU $-TMSG + +ENDTST: + LDY #00 ; (CBD) POSITION FOR SIDE2 MESSAGE + LDX #20 ; (CBD) + CLC ; (CBD) + JSR PLOT ; (CBD) + + JSR INITPAG + LDA #CLS ; GET RID OF "LOADING" MSG + JSR CHROUT + + LDA ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + STA ZPCM ; MSB + LDA ZBEGIN+ZGO+1 ; AND LSB + STA ZPCL ; HIGH BIT ALREADY ZEROED + JSR VLDZPC ; MAKE ZPC VALID + + LDX WWIDTH + STX XSIZE + + LDA PSTAT ; CHECK IF RESTART & WERE PRINTING + CMP #1 + BNE EX2 ; NO + STA SCRIPTF ; YES, TURN SCRIPT FLAG ON + ORA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO + STA ZBEGIN+ZSCRIP+1 + +EX2: LDA #CLS ; CLEAR SCREEN ... + JSR CHROUT + + LDY #0 + LDX #23 ; start cursor off at bottom of + CLC + JSR PLOT ; screen + + ; ... AND FALL INTO MAIN LOOP + + END diff --git a/c-128/ezip/xpaging.asm b/c-128/ezip/xpaging.asm new file mode 100644 index 0000000..3cf434d --- /dev/null +++ b/c-128/ezip/xpaging.asm @@ -0,0 +1,407 @@ + PAGE + STTL "--- TIME-STAMP PAGING ROUTINE ---" + + +; ------------------------- +; POINT [MPC] TO V-ADDR [I] +; ------------------------- + +SETWRD: LDA I+LO + STA MPCL + LDA I+HI + STA MPCM + LDA #0 + STA MPCH ; ZERO TOP BIT + JMP VLDMPC + + +; THE FIRST 86K (SIDE1) MUST +; BE RAM RESIDENT (344=$158 PAGES) +; +; PAGES V$0 TO ($FE-VBEGIN) ARE IN MAIN (BANK1) +; PAGES ($FE-VBEGIN) TO V$158 ARE IN AUX (BANK0) +; PAGENG BUFFERS ARE IN HIGH AUX +; +DSKBNK: DB 00 +; +WANTED: DB 00,00 +; +CURRENT: DB 00 +NEXT: DB 00 +NSUBA: DB 00 +PSUBA: DB 00 +NSUBCUR: DB 00 +; +YTEMP: DB 00 +ATEMP: DB 00 +NSUBY: DB 00 +; +; +; GET SIDE 1 LOADS ALL CODE FROM +; DISK SIDE 1 INTO ITS CORRECT +; PLACE + +; THE FIRST VPAGE MUST ALREADY BE +; RESIDENT AT [ZBEGIN] + +GETSIDE1: LDA ZBEGIN+ZLENTH+1 ;GET LENGTH OF GAME (QUADS) + STA J+LO + LDA ZBEGIN+ZLENTH+0 + LDY #5 +SLP: LSR A ;CONVERT QUADS TO PAGES WITH /64 + ROR J+LO + DEY + BPL SLP + STA J+HI + +; [J] HAS # PAGES IN GAME ROUNDED +; DOWN, BUT PAGE 0 IS IN ALREADY +; SO WE NEED ONLY LOAD [J] MORE +; PAGES OR FILL MEM WITH SIDE 1 +; IF THE GAME IS LARGER THAN SIDE 1 + +; FILL MAIN AND AUX +; # GETRES ASSUMED TO BE POINTING +; # AT V-PAGE 1 AND RAM PAGE ZBEGIN+1 +; # ALSO, GETRES SHOULD ROLL INTO +; # AUX RAM WHEN INCMNTING DBUFF + +FLP: JSR DECJ ; C=0 IF [J] GOES HIGH 0 + BCC FIN + JSR GETDSK ; (CBD) + BCC FLP0 + JMP DSKERR ; OH SHIT + +FLP0: LDA DSKBNK ; IS IT FILLING AUX ? + CMP #AUX + BNE FLP ; JMP + +FLP1: LDA DBUFF+HI + CMP #PBEGIN ;FILLED TO PAGING BUFFERS YET? + BNE FLP ;NO, NOT YET + + LDA #CLS + JSR CHROUT ; CLEAR THE SCREEN FOR NEATNESS + LDA SIDEFLG ; IF NOT ON SIDE 2 YET + CMP #2 + BEQ FIN + LDX #2 + LDY #0 + CLC ; make sure you set it + JSR PLOT + JMP SIDE2 ; GO ASK FOR IT NOW +FIN: RTS + +;DECJ RETURNS C=0 WHEN J=$FFFF + +DECJ: LDA J+LO + SEC + SBC #1 + STA J+LO + LDA J+HI + SBC #0 + STA J+HI + RTS + + +; MAKE [MPCPNT],[MPCBNK] POINT TO +; THE RAM PAGE AND BANK THAT HOLDS +; THE V-PAGE MPCH,M +; +VLDMPC: LDA MPCH + BNE VLD1 ;NOT IN FIRST V-64K + LDA MPCM + CMP #VAUX ;IS IT A PAGE IN MAIN + BCS VLD2 ;NO, IT IS IN AUX + ADC #>ZBEGIN ;ADD OFFSET TO GET RAM PAGE +VLD0: LDY #MAIN + JMP VLDEXI ;JMP + +VLD1: CMP #1 ;BETWEEN 64K AND 128K ? + BNE VLD3 ;NO, ABOVE 128K + + LDA MPCM + CMP #ZBEGIN ;ADD OFFSET TO GET RAM PAGE +VLDZ0: LDY #MAIN + JMP VLDZEXI ;JMP + +VLDZ1: CMP #1 ;BETWEEN 64K AND 128K ? + BNE VLDZ3 ;NO, ABOVE 128K + LDA ZPCM + CMP #(DBLOCK) + ; FROM DISK & PUT IN PAGING BUFFER [X] (MUST BE MADE ABSOLUTE) + +GETVPAGE: STA DBLOCK+HI + STY DBLOCK+LO + TXA ; OFFSET INTO CORRECT RAM PAGE + CLC + ADC #PBEGIN ; MAKE ABSOLUTE + STA DBUFF+HI + LDX #AUX ; SET FLAG + STX DSKBNK + JSR GETDSK + BCC T2 + JMP DSKERR ; COULDN'T READ DISK + + +; PREV(A)=Y +; PREV(NEXT(Y))=A +; NEXT(A)=NEXT(Y) +; NEXT(Y)=A + + ; INSERT A BEFORE Y + +INSERT: STA ATEMP + STY YTEMP + TAX + TYA + STA PREVPNT,X + + LDA NEXTPNT,Y + STA NSUBY + TXA + LDX NSUBY + STA PREVPNT,X + + TXA + LDX ATEMP + STA NEXTPNT,X + + LDA ATEMP + STA NEXTPNT,Y + RTS + + +; DETATCH BUFFER HIGH ALOW +; NEXT(PREV(A))=NEXT(A) +; PREV(NEXT(A))=PREV(A) + +DETATCH: TAX + LDA NEXTPNT,X + STA NSUBA + LDA PREVPNT,X + STA PSUBA + TAX + LDA NSUBA + STA NEXTPNT,X + LDA PSUBA + LDX NSUBA + STA PREVPNT,X + RTS + + +; RETURN BUFFER OF PAGE [WANTED] +; IN [A] ELSE SEC (Y=WANTED+LO) +; (CHECKING FOR PAGED BUFFER ALREADY RESIDENT) + +WHERE: LDX #NUMBUFS-1 +WHLOOP: + LDA WANTED+HI + CMP VPAGEH,X ;HIGH SAME + BEQ WHGOT +WHNOGOT: + DEX + BPL WHLOOP + SEC + RTS +WHGOT: + TYA + CMP VPAGEL,X + BNE WHNOGOT + TXA + CLC + RTS + + + ; SETS UP PAGING SYSTEM - CALLED FROM WARM (?, COLD ?) + +INITPAG: LDX #NUMBUFS-1 + STX CURRENT + LDA #$FF +INILP: + STA VPAGEH,X + DEX + BPL INILP + LDX #0 + LDY #1 +INILP2: + TYA + STA PREVPNT,X + INX + INY + CPX #NUMBUFS + BCC INILP2 + LDA #00 + DEX + STA PREVPNT,X + LDX #0 + LDY #$FF + LDA #NUMBUFS-1 +INILP3: + STA NEXTPNT,X + INX + INY + TYA + CPX #NUMBUFS + BCC INILP3 + + JMP GETSIDE1 + +; TAKE CARE OF CROSSING A PAGE + +CRSMPC: + PHA + INC MPCM + BNE CRS1 + INC MPCH +CRS1: JSR VLDMPC + PLA + RTS + +;SAME AS CRSMPC + +CRSZPC: + PHA + INC ZPCM + BNE CRSZ1 + INC ZPCH +CRSZ1: JSR VLDZPC + PLA + RTS + + PAGE + + END diff --git a/c-128/ezip/xpaging.cbd b/c-128/ezip/xpaging.cbd new file mode 100644 index 0000000..c649366 --- /dev/null +++ b/c-128/ezip/xpaging.cbd @@ -0,0 +1,406 @@ + PAGE + SBTTL "--- TIME-STAMP PAGING ROUTINE ---" + + +; ------------------------- +; POINT [MPC] TO V-ADDR [I] +; ------------------------- + +SETWRD: LDA I+LO + STA MPCL + LDA I+HI + STA MPCM + LDA #0 + STA MPCH ; ZERO TOP BIT + JMP VLDMPC + + +; THE FIRST 86K (SIDE1) MUST +; BE RAM RESIDENT (344=$158 PAGES) +; +; PAGES V$0 TO ($FE-VBEGIN) ARE IN MAIN (BANK1) +; PAGES ($FE-VBEGIN) TO V$158 ARE IN AUX (BANK0) +; PAGENG BUFFERS ARE IN HIGH AUX +; +DSKBNK: DB 00 +; +WANTED: DB 00,00 +; +CURRENT: DB 00 +NEXT: DB 00 +NSUBA: DB 00 +PSUBA: DB 00 +NSUBCUR: DB 00 +; +YTEMP: DB 00 +ATEMP: DB 00 +NSUBY: DB 00 +; +; +; GET SIDE 1 LOADS ALL CODE FROM +; DISK SIDE 1 INTO ITS CORRECT +; PLACE + +; THE FIRST VPAGE MUST ALREADY BE +; RESIDENT AT [ZBEGIN] + +GETSIDE1: LDA ZBEGIN+ZLENTH+1 ;GET LENGTH OF GAME (QUADS) + STA J+LO + LDA ZBEGIN+ZLENTH+0 + LDY #5 +SLP: LSR A ;CONVERT QUADS TO PAGES WITH /64 + ROR J+LO + DEY + BPL SLP + STA J+HI + +; [J] HAS # PAGES IN GAME ROUNDED +; DOWN, BUT PAGE 0 IS IN ALREADY +; SO WE NEED ONLY LOAD [J] MORE +; PAGES OR FILL MEM WITH SIDE 1 +; IF THE GAME IS LARGER THAN SIDE 1 + +; FILL MAIN AND AUX +; # GETRES ASSUMED TO BE POINTING +; # AT V-PAGE 1 AND RAM PAGE ZBEGIN+1 +; # ALSO, GETRES SHOULD ROLL INTO +; # AUX RAM WHEN INCMNTING DBUFF + +FLP: JSR DECJ ; C=0 IF [J] GOES HIGH 0 + BCC FIN + JSR GETDSK ; (CBD) + BCC FLP0 + JMP DSKERR ; OH SHIT + +FLP0: LDA DSKBNK ; IS IT FILLING AUX ? + CMP #AUX + BNE FLP ; JMP + +FLP1: LDA DBUFF+HI + CMP #PBEGIN ;FILLED TO PAGING BUFFERS YET? + BNE FLP ;NO, NOT YET + + LDA #CLS + JSR CHROUT ; CLEAR THE SCREEN FOR NEATNESS + LDA SIDEFLG ; IF NOT ON SIDE 2 YET + CMP #2 + BEQ FIN + LDX #2 + LDY #0 + JSR PLOT + JMP SIDE2 ; GO ASK FOR IT NOW +FIN: RTS + +;DECJ RETURNS C=0 WHEN J=$FFFF + +DECJ: LDA J+LO + SEC + SBC #1 + STA J+LO + LDA J+HI + SBC #0 + STA J+HI + RTS + + +; MAKE [MPCPNT],[MPCBNK] POINT TO +; THE RAM PAGE AND BANK THAT HOLDS +; THE V-PAGE MPCH,M +; +VLDMPC: LDA MPCH + BNE VLD1 ;NOT IN FIRST V-64K + LDA MPCM + CMP #VAUX ;IS IT A PAGE IN MAIN + BCS VLD2 ;NO, IT IS IN AUX + ADC #HIGH ZBEGIN ;ADD OFFSET TO GET RAM PAGE +VLD0: LDY #MAIN + JMP VLDEXI ;JMP + +VLD1: CMP #1 ;BETWEEN 64K AND 128K ? + BNE VLD3 ;NO, ABOVE 128K + + LDA MPCM + CMP #LOW PRESIZ ; CBD + BCS VLD3 ;PAGED + +VLD2: SEC + SBC #VAUX-AUXSTART ;FIX TO OFFST INTO AUX RAM + LDY #AUX + +VLDEXI: STY MPCBNK + STA MPCPNT+HI +NOMUCK: RTS + +VLD3: ;MUST BE PAGED + LDA MPCH + LDY MPCM + JSR PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + CLC + ADC #PBEGIN + STA MPCPNT+HI + LDY #AUX + STY MPCBNK + + ;TEST FOR MUCK + + LDA MUCKFLG + BEQ NOMUCK + JMP VLDZPC ;MAY HAVE MUCKED ZPC SO GO FIX + + ;SAME IDEA AS VLDMPC + +VLDZPC: LDA ZPCH + BNE VLDZ1 ;NOT IN FIRST V-64K + LDA ZPCM + CMP #VAUX ;IS IT A PAGE IN MAIN + BCS VLDZ2 ;NO, IT IS IN AUX + ADC #HIGH ZBEGIN ;ADD OFFSET TO GET RAM PAGE +VLDZ0: LDY #MAIN + JMP VLDZEXI ;JMP + +VLDZ1: CMP #1 ;BETWEEN 64K AND 128K ? + BNE VLDZ3 ;NO, ABOVE 128K + LDA ZPCM + CMP #LOW PRESIZ ; CBD + BCS VLDZ3 ;PAGED +VLDZ2: SEC + SBC #VAUX-AUXSTART + LDY #AUX + +VLDZEXI: STY ZPCBNK + STA ZPCPNT+HI +NOZMUCK: RTS + +VLDZ3: ;MUST BE PAGED + LDA ZPCH + LDY ZPCM + JSR PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y + CLC + ADC #PBEGIN + STA ZPCPNT+HI + LDY #AUX + STY ZPCBNK + + ;TEST MUCKING + + LDA MUCKFLG + BEQ NOZMUCK + JMP VLDMPC ;MAY HAVE MUCKED MPC SO GO FIX + + +; FIND V-PAGE A,Y IF IT IS IN MEM +; AND RETURN WITH LINKED LIST +; PROPERLY MAINTAINED +; IF V-PAGE A,Y NOT IN MEM +; GET FROM DISK AND PUT IN RIGHT +; PLACE + +MUCKFLG: DB 00 ; 00 IF PAGING BUFFERS NOT MUCKED + + +PAGE: STA WANTED+HI + STY WANTED+LO + + ; CLEAR MUCK FLAG + + LDX #0 + STX MUCKFLG + + JSR WHERE + BCC TOUGH ;PAGE IS RESIDENT IN PAGENG SPACE + + ; PAGE MUST BE BROUGHT IN FROM DISK + + LDX CURRENT ;GET BUFFER TO PUT PAGE INTO + LDA NEXTPNT,X ;BY LOOKING AT NEXT POINTER + STA CURRENT ;MAKE IT THE CURRENT BUFFER + TAX + LDA WANTED+HI ;LET BUFFER MAP KNOW + STA VPAGEH,X ;WHICH PAGE + LDA WANTED+LO ;IS GOING TO + STA VPAGEL,X ;BE THERE + TAY + TXA + PHA ;SAVE BUFFER + LDA WANTED+HI + + ; Y = WANTED+LO + ; X = BUFFER + + JSR GETVPAGE ;PUT V-PAGE A,Y INTO PAGENG BUFFER X + + ;INDICATE A MUCKING + + DEC MUCKFLG + PLA ;RESTOR BUFFER NUMBER + RTS + + ; THIS IS WHERE THINGS GET WEIRD + +TOUGH: STA NEXT + CMP CURRENT ;GETS REALY FUCKED IF CURRENT=NEXT + BNE T1 + RTS ;DO NOT CHANGE POINTERS IF IT DOES, ALL IS WELL + +; Y=NEXT(CURRENT) +; DO THE RIGHT THING TO THE POINTERS +; ASK LIM TO EXPLAIN ,HA HA. + +T1: LDY CURRENT + LDA NEXTPNT,Y + STA NSUBCUR + LDA NEXT + JSR DETATCH + LDY CURRENT + LDA NEXT + JSR INSERT + LDA NEXT + STA CURRENT +T2: RTS + + ; GET A PAGE IN BANK 1, PREPAGED + + ; TEMPORARY NOTE: GET A PAGED PAGE [A,Y] >(DBLOCK) + ; FROM DISK & PUT IN PAGING BUFFER [X] (MUST BE MADE ABSOLUTE) + +GETVPAGE: STA DBLOCK+HI + STY DBLOCK+LO + TXA ; OFFSET INTO CORRECT RAM PAGE + CLC + ADC #PBEGIN ; MAKE ABSOLUTE + STA DBUFF+HI + LDX #AUX ; SET FLAG + STX DSKBNK + JSR GETDSK + BCC T2 + JMP DSKERR ; COULDN'T READ DISK + + +; PREV(A)=Y +; PREV(NEXT(Y))=A +; NEXT(A)=NEXT(Y) +; NEXT(Y)=A + + ; INSERT A BEFORE Y + +INSERT: STA ATEMP + STY YTEMP + TAX + TYA + STA PREVPNT,X + + LDA NEXTPNT,Y + STA NSUBY + TXA + LDX NSUBY + STA PREVPNT,X + + TXA + LDX ATEMP + STA NEXTPNT,X + + LDA ATEMP + STA NEXTPNT,Y + RTS + + +; DETATCH BUFFER HIGH ALOW +; NEXT(PREV(A))=NEXT(A) +; PREV(NEXT(A))=PREV(A) + +DETATCH: TAX + LDA NEXTPNT,X + STA NSUBA + LDA PREVPNT,X + STA PSUBA + TAX + LDA NSUBA + STA NEXTPNT,X + LDA PSUBA + LDX NSUBA + STA PREVPNT,X + RTS + + +; RETURN BUFFER OF PAGE [WANTED] +; IN [A] ELSE SEC (Y=WANTED+LO) +; (CHECKING FOR PAGED BUFFER ALREADY RESIDENT) + +WHERE: LDX #NUMBUFS-1 +WHLOOP: + LDA WANTED+HI + CMP VPAGEH,X ;HIGH SAME + BEQ WHGOT +WHNOGOT: + DEX + BPL WHLOOP + SEC + RTS +WHGOT: + TYA + CMP VPAGEL,X + BNE WHNOGOT + TXA + CLC + RTS + + + ; SETS UP PAGING SYSTEM - CALLED FROM WARM (?, COLD ?) + +INITPAG: LDX #NUMBUFS-1 + STX CURRENT + LDA #$FF +INILP: + STA VPAGEH,X + DEX + BPL INILP + LDX #0 + LDY #1 +INILP2: + TYA + STA PREVPNT,X + INX + INY + CPX #NUMBUFS + BCC INILP2 + LDA #00 + DEX + STA PREVPNT,X + LDX #0 + LDY #$FF + LDA #NUMBUFS-1 +INILP3: + STA NEXTPNT,X + INX + INY + TYA + CPX #NUMBUFS + BCC INILP3 + + JMP GETSIDE1 + +; TAKE CARE OF CROSSING A PAGE + +CRSMPC: + PHA + INC MPCM + BNE CRS1 + INC MPCH +CRS1: JSR VLDMPC + PLA + RTS + +;SAME AS CRSMPC + +CRSZPC: + PHA + INC ZPCM + BNE CRSZ1 + INC ZPCH +CRSZ1: JSR VLDZPC + PLA + RTS + + PAGE + + END diff --git a/c-128/ezip/zdos.asm b/c-128/ezip/zdos.asm new file mode 100644 index 0000000..c1d9352 --- /dev/null +++ b/c-128/ezip/zdos.asm @@ -0,0 +1,681 @@ + PAGE + STTL "--- Z-DOS: CBM64 ---" + + + ; --------------------- + ; GET Z-BLOCK FROM DISK + ; --------------------- + + ; ENTRY: Z-BLOCK # IN [BLOCK] + ; TARGET PAGE IN [DBUFF+HI] + + ; NOTE: USING VARIABLE SECTORS PER TRACK TO GET 170K ON DISK + +GETDSK: LDA #8 + STA DRIVE ; GAME ALWAYS PLAYS FROM DRIVE #8 + + LDA DBLOCK+HI + CMP #>PSIDE1 + BCC GETSD1 ; OK, SIDE1 + BNE SID2 + LDA DBLOCK+LO + CMP #PSIDE1 + TAX + PLA + LDY #1 ; SIDE 2 STARTS ON TRACK 1 + JSR SETTS ; SET TRACK & SECTOR + JMP GETRES ; AND GO READ + +GETSD1: LDA SIDEFLG ; ARE WE ON SIDE 1 + CMP #1 + BEQ SID1 + JSR SIDE1 + +SID1: LDA DBLOCK+LO + LDX DBLOCK+HI + LDY #3 ; SIDE 1 STARTS ON TRACK 3 + JSR SETTS ; GO GET TRACK & SECTOR + JMP GETRES ; AND GO READ THE DISK + + + ; SET TRACK & SECTOR FROM A,X DBLOCK (A=LO) Y = STARTING TRACK + +SETTS: STY TRACK + DEY + +TRKLP: CMP TRKTBL,Y ; CHECK IF REMAINDER LESS + BCS DOIT ; THAN 1 TRACK + CPX #0 + BEQ TRKDUN ; YES + +DOIT: SEC ; SUBTRACT ANOTHER TRACKS WORTH + SBC TRKTBL,Y ; FROM THE SECTORS PER TRACK TABLE + BCS TRK1 + DEX ; BORROWED +TRK1: INC TRACK + INY ; NEXT TRACK IN TABLE + BNE TRKLP ; JMP + +TRKDUN: STA SECTOR + LDA TRACK + CMP #18 ; IF ON TRACK 18, SKIP OVER 1ST SECTOR + BNE TRKOVR + INC SECTOR +TRKOVR: RTS + + +TRKTBL: DB 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21 + DB 18,19,19,19,19,19,19 + DB 18,18,18,18,18,18 + DB 17,17,17,17,17 + + ; *** ERROR #12: DISK ADDRESS OUT OF RANGE *** + +TRKERR: LDA #12 + JMP ZERROR + + ; *** ERROR #14: DRIVE ACCESS *** + +DSKERR: LDA #14 + JMP ZERROR + + + + ; -------------------- + ; PUT [DBLOCK] TO DISK + ; -------------------- + + ; ENTRY: [DBLOCK] & [DRIVE] ASSIGNED + ; PAGE TO WRITE IN [DBUFF] + + ; NOTE: AS THIS ONLY WRITES FROM MAIN BANK (BANK1) + ; CAN HAVE UP HERE + +PUTDSK: LDY #0 ; MOVE PAGE AT [DBUFF] +PTKL: LDA (DBUFF),Y ; INTO + STA IOBUFF,Y ; [IOBUFF] FOR I/O + INY + BNE PTKL + + SEC ; CARRY SET = "WRITE BLOCK" + JSR DISK + BCS WRTERR ; CARRY SET IF ERROR + + INC DBUFF+HI ; NEXT MEMORY PAGE + +NXTDBL: INC DBLOCK+LO ; POINT TO NEXT VIRTUAL PAGE + BNE DBLOK + INC DBLOCK+HI +DBLOK: INC SECTOR ; NEXT SECTOR + LDY TRACK ; CHECK IF NEXT TRACK + DEY + LDA SECTOR + CMP TRKTBL,Y + BCC SECTOK + INC TRACK ; YES, RESET + LDA #0 + STA SECTOR + LDA TRACK + CMP #18 + BNE SECTOK + INC SECTOR ; SKIP 1ST SECTOR TRACK 18 (DIRECTORY) +SECTOK: CLC + +WRTERR: RTS + + + ; -------------------- + ; PROMPT FOR GAME DISK + ; -------------------- + + ; EZIP USES BOTH SIDES OF DISK + +GAME: DB EOL + DB "Insert Side " +DSIDE: DB "* of the STORY disk into Drive #8." ; (CBD) + DB EOL +GAMEL EQU $-GAME +SD: DB "INFOCOM-S" ; (CBD) + +SIDE1: LDA #'1' ; ASK FOR SIDE 1 + STA DSIDE + LDA #1 ; SET FOR SUCCESS + STA SIDEFLG +SL1: LDX #GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + LDX #0 ; READ DIRECTORY + STX SECTOR ; (CBD) MUST BE "INFOCOM-S1" + LDX #$12 ; (CBD) + STX TRACK + + LDA #8 ; MAKE SURE WE'RE ON + STA DRIVE ; THE GAME DRIVE + JSR DOPEN + + CLC ; CARRY CLEAR = "READ BLOCK" + JSR DISK ; GO DO IT! + BCC SL3 + JMP DSKERR ; ERROR IF CARRY SET + +SL3: LDY #$99 ; (CBD) OFFSET IN DIRECTORY SECTOR + LDX #9 ; (CBD) + LDA #"1" ; (CBD) + BNE SL8 ; (CBD) +SL7: LDA SD,X ; (CBD) "INFOCOM-S1" +SL8: CMP IOBUFF,Y ; (CBD) DIR ENTRY CORRECT? + BNE SL1 ; (CBD) NO, GO ASK AGAIN + DEY ; (CBD) + DEX ; (CBD) + BPL SL7 ; (CBD) + BMI ASK2 ; (CBD) JUMP, GOOD + + +SIDE2: LDA #'2' ; ASK FOR SIDE 2 + STA DSIDE + LDA #2 + STA SIDEFLG ; SET FOR SUCCESS + LDA DRIVE ; GET LAST DRIVE USED + PHA ; HOLD IT A SEC + LDA #8 ; MAKE SURE WE'RE ON + STA DRIVE ; THE BOOT DRIVE + JSR DOPEN + PLA ; IF SAVED/RESTORED + CMP #9 ; TO DRIVE 2, DON'T ASK + BEQ ASK2 ; NOTE: THIS IS OK W/ VERIFY CAUSE ASKS + ; FOR SIDE 1 FIRST, RESETTING DRIVE TO 1 + +SL2: LDX #GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + + LDX #0 ; READ DIRECTORY + STX SECTOR ; (CBD) MUST BE "INFOCOM-S2" + LDX #$12 + STX TRACK + CLC + JSR DISK + BCC SL4 + JMP SL2 ; BAD READ, GO ASK AGAIN + +SL4: LDY #$99 ; (CBD) OFFSET IN DIRECTORY SECTOR + LDX #9 ; (CBD) + LDA #"2" ; (CBD) + BNE SL6 ; (CBD) +SL5: LDA SD,X ; (CBD) +SL6: CMP IOBUFF,Y ; (CBD) DIR ENTRY CORRECT? + BNE SL2 ; NO, GO ASK AGAIN + DEY + DEX + BPL SL5 + +ASK2: LDA #$FF ; RE-ENABLE + STA SCRIPT ; SCRIPTING + RTS + + + ; ----------------------------- + ; SET UP SAVE & RESTORE SCREENS + ; ----------------------------- + +SAVRES: JSR ZCRLF ; CLEAR THE BUFFER + LDX #0 + STX SCRIPT ; DISABLE SCRIPTING + LDA TOP ; SET TO REFILL SCREEN + STA LINCNT + RTS +; LDA #CLS +; JMP CHROUT ; HOME CURSOR & RETURN + + ; ----------------- + ; DISPLAY A DEFAULT + ; ----------------- + + ; ENTRY: DEFAULT (0-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 #DEFAL + LDY #DEFALL + JMP DLINE ; PRINT THE STRING + + + ; ----------------------------- + ; GET SAVE & RESTORE PARAMETERS + ; ----------------------------- + +POSIT: DB EOL + DB "Position 1-" +POSTOP: DB "*" +POSITL EQU $-POSIT + +WDRIV: DB EOL + DB "Drive 8 or 9" +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 #POSIT + LDY #POSITL + JSR DLINE ; "POSITION (1-5)" + + ; GET GAME POSITION + +CHANGE: 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 NUMSAV ; IF BELOW "6" + 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 LETTER ; AND DISPLAY IT + + ; GET DRIVE ID + + LDX #WDRIV + LDY #WDRIVL + JSR DLINE ; "DRIVE 8 OR 9" + + LDA GDRIVE ; SHOW DEFAULT + CLC ; CONVERT 0 OR 1 + ADC #7 ; TO 7 OR 8 + JSR DODEF ; SO DEFAULT WILL BE CORRECT + +GETDRV: JSR GETKEY ; GET A KEYPRESS + CMP #EOL ; IF [RETURN], + BEQ DRVSET ; USE DEFAULT + SEC + SBC #'8' ; 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 #'8' ; CONVERT TO ASCII 8 OR 9 + STA SAVDRI ; STORE IN DRIVE STRING + STA MDRI ; AND IN TEMP STRING + JSR LETTER ; AND SHOW NEW SETTING + + LDX #MIND + LDY #MINDL + JSR DLINE + +GETYES: JSR GETKEY + CMP #'Y' ; IF REPLY IS "Y" + BEQ ALLSET ; ACCEPT RESPONSES + CMP #'y' + BEQ ALLSET + + CMP #'N' ; IF REPLY IS N, + BEQ RETRY ; DO A RETRY + CMP #'n' + BEQ RETRY + + JSR BOOP ; INSIST ON Y/RETURN + JMP GETYES ; OR N + +RETRY: LDX #NO + LDY #NOL + JSR DLINE + JMP PARAMS ; AND TRY AGAIN + +ALLSET: LDX #YES + LDY #YESL + JSR DLINE + + ; CALC START POSITION OF SAVE + + LDA #0 ; SET FOR POSITION 1 + STA DBLOCK+LO + STA DBLOCK+HI + + LDX TPOSIT ; GET # OF SAVES IN TO MOVE + BEQ FINDTS +CALC: CLC ; AND FIND WHAT SECTOR TO START WITH + ADC SAVSIZ + BCC CALC1 + INC DBLOCK+HI +CALC1: DEX + BNE CALC + STA DBLOCK+LO ; IN THE FORM OF DBLOCKS + +FINDTS: LDA DBLOCK+LO + LDX DBLOCK+HI + LDY #1 + JSR SETTS ; GET TRACK & SECTOR + +SREADY: LDX #INSM + LDY #INSML + JSR DLINE ; "INSERT SAVE DISK IN DRIVE X." + JSR RETURN ; "PRESS [RETURN] TO CONTINUE." + +TRYOPN: LDA TDRIVE ; TRY TO OPEN SPECIFIED DRIVE + CLC + ADC #8 + JSR DOPEN ; THE DEFAULT DRIVE + RTS ; CARRY SET IF ERROR + + ; --------------------- + ; "PRESS RETURN" PROMPT + ; --------------------- + +RETURN: LDX #RTN + LDY #RTNL + JSR DLINE ; SHOW PROMPT + + ; ENTRY FOR QUIT/RESTART + +GETRET: JSR GETIN ; WAIT FOR [RETURN] + CMP #0 + BEQ GETRET ; GET A CHAR 1ST + AND #%01111111 ; CLEAR SHIFT + CMP #EOL + BEQ RETEX + JSR BOOP ; ACCEPT NO + JMP GETRET ; SUBSTITUTES! + +RETEX: RTS + +RTN: DB EOL + DB "Press [RETURN] to continue." + DB EOL,EOL +RTNL EQU $-RTN + + + ; --------- + ; SAVE GAME + ; --------- + +SAV: DB "Save Position" + DB EOL +SAVL EQU $-SAV + +SVING: DB EOL + DB "Saving position " +SVPOS: DB "* ..." + DB EOL +SVINGL EQU $-SVING + +ZSAVE: JSR SAVRES ; SET UP SCREEN + + LDX #SAV + LDY #SAVL + JSR DLINE ; "SAVE POSITION" + + JSR PARAMS ; GET PARAMETERS + BCC DOSAVE ; ERROR IF CARRY SET + +BADSAV: JSR SIDE2 ; PROMPT FOR GAME DISK + JMP RET0 ; AND FAIL + +DOSAVE: LDX #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+LO ; MOVE [ZSP] + STA BUFSAV+2 + LDA ZSP+HI + STA BUFSAV+3 + LDA OLDZSP+LO + STA BUFSAV+4 + LDA OLDZSP+HI ; MOVE [OLDZSP] + STA BUFSAV+5 + + LDX #2 ; MOVE CONTENTS OF [ZPC] +ZPCSAV: LDA ZPC,X ; TO BYTES 5-7 + STA BUFSAV+6,X ; OF [BUFSAV] + DEX + BPL ZPCSAV + + ; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK + + LDA #>LOCALS + STA DBUFF+HI ; POINT TO THE PAGE + JSR PUTDSK ; AND WRITE IT OUT + BCS BADSAV ; CATCH WRITE ERROR HERE + + ; WRITE CONTENTS OF Z-STACK TO DISK + +ZSOK: LDA #>ZSTKBL ; POINT TO 1ST PAGE + STA DBUFF+HI + LDA #4 ; DO ALL 4 PAGES + STA L ; SET COUNTER +ZSOKLP: JSR PUTDSK ; WRITE THEM + BCS BADSAV + DEC L + BNE ZSOKLP + + ; 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 + LDA TDRIVE ; IF SAVE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TPOSIT + STA GPOSIT + LDA #1 ; SET TO MARK + LDX #0 + JMP PUTBYT ; SUCCESS + + + ; ------------ + ; RESTORE GAME + ; ------------ + +RES: DB "Restore Position" + DB EOL +RESL EQU $-RES + +RSING: DB EOL + DB "Restoring position " +RSPOS: DB "* ..." + DB EOL +RSINGL EQU $-RSING + +ZREST: JSR SAVRES + + LDX #RES + LDY #RESL + JSR DLINE ; "RESTORE POSITION" + + JSR PARAMS ; GET PARAMETERS + BCS BADRES ; ERROR IF CARRY SET + + LDX #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 #MAIN + STA DSKBNK ; SET TO WRITE TO MAIN BANK + LDA #>LOCALS + STA DBUFF+HI + JSR GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + BCS BADRES + + 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 INCORRECT SAVE DISK + +WRONG: LDX #31 ; RESTORE ALL SAVED LOCALS +WR0: LDA $0100,X + STA LOCALS,X + DEX + BPL WR0 + +BADRES: JSR SIDE2 ; PROMPT FOR GAME DISK + JMP RET0 ; AND FAIL + + ; CONTINUE RESTORE + +RIGHT: LDA ZBEGIN+ZSCRIP ; SAVE BOTH FLAG BYTES + STA I+LO + LDA ZBEGIN+ZSCRIP+1 + STA I+HI + + LDA #>ZSTKBL ; RETRIEVE OLD CONTENTS OF + STA DBUFF+HI ; Z-STACK + LDA #4 ; DO 4 PAGES + STA L ; SET COUNTER +ZROKLP: JSR GETRES ; GET 4 PAGES OF Z-STACK + BCC ZROKL1 + JMP DSKERR ; IF HERE, MIX OF GOOD & BAD SO DIE + +ZROKL1: DEC L + BNE ZROKLP + + LDA ZCODE + STA DBUFF+HI + JSR GETRES ; GET 1ST BLOCK OF PRELOAD + BCC ZROKL2 + JMP DSKERR + +ZROKL2: 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 GETRES ; FETCH THE REMAINDER + BCC LREST0 + JMP DSKERR + +LREST0: DEC I+LO ; OF THE PRELOAD + BNE LREST + + ; RESTORE THE STATE OF THE SAVED GAME + + LDA BUFSAV+2 ; RESTORE THE [ZSP] + STA ZSP+LO + LDA BUFSAV+3 + STA ZSP+HI + LDA BUFSAV+4 + STA OLDZSP+LO + LDA BUFSAV+5 ; AND THE [OLDZSP] + STA OLDZSP+HI + + LDX #2 ; RESTORE THE [ZPC] +RESZPC: LDA BUFSAV+6,X + STA ZPC,X + DEX + BPL RESZPC + + JSR SIDE2 ; PROMPT FOR GAME DISK + JSR VLDZPC ; MAKE VALID (12-2-86) + + LDA TDRIVE ; IF RESTORE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TPOSIT ; NEXT TIME + STA GPOSIT + LDA #2 ; SET TO + LDX #0 + JMP PUTBYT ; SUCCESS + + END + diff --git a/c-128/ezip/zdos.cbd b/c-128/ezip/zdos.cbd new file mode 100644 index 0000000..4d4793a --- /dev/null +++ b/c-128/ezip/zdos.cbd @@ -0,0 +1,691 @@ + PAGE + SBTTL "--- Z-DOS: CBM64 ---" + + + ; --------------------- + ; GET Z-BLOCK FROM DISK + ; --------------------- + + ; ENTRY: Z-BLOCK # IN [BLOCK] + ; TARGET PAGE IN [DBUFF+HI] + + ; NOTE: USING VARIABLE SECTORS PER TRACK TO GET 170K ON DISK + +GETDSK: LDA #8 + STA DRIVE ; GAME ALWAYS PLAYS FROM DRIVE #8 + + LDA DBLOCK+HI + CMP #HIGH PSIDE1 + BCC GETSD1 ; OK, SIDE1 + BNE SID2 + LDA DBLOCK+LO + CMP #LOW PSIDE1 + BCC GETSD1 + +SID2: LDA SIDEFLG ; ON SIDE 2? + CMP #2 + BEQ GETSD2 ; YES + JSR SIDE2 ; NO, ASK FOR IT + +GETSD2: LDA DBLOCK+LO + SEC ; SIDE 2, SO SUBTRACT SIDE 1 + SBC #LOW PSIDE1 ; AMOUNT SO GET ACCURATE + PHA ; CALCULATION OF TRACK & SECTOR + LDA DBLOCK+HI + SBC #HIGH PSIDE1 + TAX + PLA + LDY #1 ; SIDE 2 STARTS ON TRACK 1 + JSR SETTS ; SET TRACK & SECTOR + JMP GETRES ; AND GO READ + +GETSD1: LDA SIDEFLG ; ARE WE ON SIDE 1 + CMP #1 + BEQ SID1 + JSR SIDE1 + +SID1: LDA DBLOCK+LO + LDX DBLOCK+HI + LDY #3 ; SIDE 1 STARTS ON TRACK 3 + JSR SETTS ; GO GET TRACK & SECTOR + JMP GETRES ; AND GO READ THE DISK + + + ; SET TRACK & SECTOR FROM A,X DBLOCK (A=LO) Y = STARTING TRACK + +SETTS: STY TRACK + DEY + +TRKLP: CMP TRKTBL,Y ; CHECK IF REMAINDER LESS + BCS DOIT ; THAN 1 TRACK + CPX #0 + BEQ TRKDUN ; YES + +DOIT: SEC ; SUBTRACT ANOTHER TRACKS WORTH + SBC TRKTBL,Y ; FROM THE SECTORS PER TRACK TABLE + BCS TRK1 + DEX ; BORROWED +TRK1: INC TRACK + INY ; NEXT TRACK IN TABLE + BNE TRKLP ; JMP + +TRKDUN: STA SECTOR + LDA TRACK + CMP #20 ; TRK 20, SECT 0 IS FAST CODE, SKIP OVER + BNE NOT20 + INC SECTOR ; NO HARM IN FALLING THRU +NOT20: CMP #18 ; IF ON TRACK 18, SKIP OVER 1ST SECTOR + BNE TRKOVR + INC SECTOR + +TRKOVR: RTS + + ; FIRST SECTOR, TRK 20 IS USED BY LZIP FOR FAST CODE + ; MUST SKIP IT FOR CBD EZIP (LSD 1/12/87) + +TRKTBL: DB 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21 + DB 18,19,18,19,19,19,19 + DB 18,18,18,18,18,18 + DB 17,17,17,17,17 + + ; *** ERROR #12: DISK ADDRESS OUT OF RANGE *** + +TRKERR: LDA #12 + JMP ZERROR + + ; *** ERROR #14: DRIVE ACCESS *** + +DSKERR: LDA #14 + JMP ZERROR + + + ; -------------------- + ; PUT [DBLOCK] TO DISK + ; -------------------- + + ; ENTRY: [DBLOCK] & [DRIVE] ASSIGNED + ; PAGE TO WRITE IN [DBUFF] + + ; NOTE: AS THIS ONLY WRITES FROM MAIN BANK (BANK1) + ; CAN HAVE UP HERE + +PUTDSK: LDY #0 ; MOVE PAGE AT [DBUFF] +PTKL: LDA (DBUFF),Y ; INTO + STA IOBUFF,Y ; [IOBUFF] FOR I/O + INY + BNE PTKL + + SEC ; CARRY SET = "WRITE BLOCK" + JSR DISK + BCS WRTERR ; CARRY SET IF ERROR + + INC DBUFF+HI ; NEXT MEMORY PAGE + +NXTDBL: INC DBLOCK+LO ; POINT TO NEXT VIRTUAL PAGE + BNE DBLOK + INC DBLOCK+HI +DBLOK: INC SECTOR ; NEXT SECTOR + LDY TRACK ; CHECK IF NEXT TRACK + DEY + LDA SECTOR + CMP TRKTBL,Y + BCC SECTOK + INC TRACK ; YES, RESET + LDA #0 + STA SECTOR + LDA TRACK + CMP #18 ; IF ON TRACK 18, SKIP OVER 1ST SECTOR (0) + BNE NOT18 ; (DISK DIRECTORY) + INC SECTOR +NOT18: CMP #20 ; TRK 20, SECT 0 ALSO (FAST CODE) + BNE SECTOK + INC SECTOR +SECTOK: CLC +WRTERR: RTS + + + ; -------------------- + ; PROMPT FOR GAME DISK + ; -------------------- + + ; EZIP USES BOTH SIDES OF DISK + +GAME: DB EOL + DB "Insert Side " +DSIDE: DB "* of the STORY disk into Drive #8." ; (CBD) + DB EOL +GAMEL EQU $-GAME +SD: DB "INFOCOM-S" ; (CBD) + +SIDE1: LDA #'1' ; ASK FOR SIDE 1 + STA DSIDE + LDA #1 ; SET FOR SUCCESS + STA SIDEFLG +SL1: LDX #LOW GAME + LDA #HIGH GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + LDX #0 ; READ DIRECTORY + STX SECTOR ; (CBD) MUST BE "INFOCOM-S1" + LDX #$12 ; (CBD) + STX TRACK + + LDA #8 ; MAKE SURE WE'RE ON + STA DRIVE ; THE GAME DRIVE + JSR DOPEN + + CLC ; CARRY CLEAR = "READ BLOCK" + JSR DISK ; GO DO IT! + BCC SL3 + JMP DSKERR ; ERROR IF CARRY SET + +SL3: LDY #$99 ; (CBD) OFFSET IN DIRECTORY SECTOR + LDX #9 ; (CBD) + LDA #"1" ; (CBD) + BNE SL8 ; (CBD) +SL7: LDA SD,X ; (CBD) "INFOCOM-S1" +SL8: CMP IOBUFF,Y ; (CBD) DIR ENTRY CORRECT? + BNE SL1 ; (CBD) NO, GO ASK AGAIN + DEY ; (CBD) + DEX ; (CBD) + BPL SL7 ; (CBD) + BMI ASK2 ; (CBD) JUMP, GOOD + + +SIDE2: LDA #'2' ; ASK FOR SIDE 2 + STA DSIDE + LDA #2 + STA SIDEFLG ; SET FOR SUCCESS + LDA DRIVE ; GET LAST DRIVE USED + PHA ; HOLD IT A SEC + LDA #8 ; MAKE SURE WE'RE ON + STA DRIVE ; THE BOOT DRIVE + JSR DOPEN + PLA ; IF SAVED/RESTORED + CMP #9 ; TO DRIVE 2, DON'T ASK + BEQ ASK2 ; NOTE: THIS IS OK W/ VERIFY CAUSE ASKS + ; FOR SIDE 1 FIRST, RESETTING DRIVE TO 1 + +SL2: LDX #LOW GAME + LDA #HIGH GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + + LDX #0 ; READ DIRECTORY + STX SECTOR ; (CBD) MUST BE "INFOCOM-S2" + LDX #$12 + STX TRACK + CLC + JSR DISK + BCC SL4 + JMP SL2 ; BAD READ, GO ASK AGAIN + +SL4: LDY #$99 ; (CBD) OFFSET IN DIRECTORY SECTOR + LDX #9 ; (CBD) + LDA #"2" ; (CBD) + BNE SL6 ; (CBD) +SL5: LDA SD,X ; (CBD) +SL6: CMP IOBUFF,Y ; (CBD) DIR ENTRY CORRECT? + BNE SL2 ; NO, GO ASK AGAIN + DEY + DEX + BPL SL5 + +ASK2: LDA #$FF ; RE-ENABLE + STA SCRIPT ; SCRIPTING + RTS + + + ; ----------------------------- + ; SET UP SAVE & RESTORE SCREENS + ; ----------------------------- + +SAVRES: JSR ZCRLF ; CLEAR THE BUFFER + LDX #0 + STX SCRIPT ; DISABLE SCRIPTING + LDA TOP ; SET TO REFILL SCREEN + STA LINCNT + RTS + + ; ----------------- + ; DISPLAY A DEFAULT + ; ----------------- + + ; ENTRY: DEFAULT (0-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-" +POSTOP: DB "*" +POSITL EQU $-POSIT + +WDRIV: DB EOL + DB "Drive 8 or 9" +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 POSITION + +CHANGE: 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 NUMSAV ; IF BELOW "6" + 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 LETTER ; AND DISPLAY IT + + ; GET DRIVE ID + + LDX #LOW WDRIV + LDA #HIGH WDRIV + LDY #WDRIVL + JSR DLINE ; "DRIVE 8 OR 9" + + LDA GDRIVE ; SHOW DEFAULT + CLC ; CONVERT 0 OR 1 + ADC #7 ; TO 7 OR 8 + JSR DODEF ; SO DEFAULT WILL BE CORRECT + +GETDRV: JSR GETKEY ; GET A KEYPRESS + CMP #EOL ; IF [RETURN], + BEQ DRVSET ; USE DEFAULT + SEC + SBC #'8' ; 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 #'8' ; CONVERT TO ASCII 8 OR 9 + STA SAVDRI ; STORE IN DRIVE STRING + STA MDRI ; AND IN TEMP STRING + JSR LETTER ; AND SHOW NEW SETTING + + LDX #LOW MIND ; SHOW TEMPORARY SETTINGS + LDA #HIGH MIND + LDY #MINDL + JSR DLINE + +GETYES: JSR GETKEY + CMP #'Y' ; IF REPLY IS "Y" + BEQ ALLSET ; ACCEPT RESPONSES + CMP #'y' + BEQ ALLSET + + CMP #'N' ; IF REPLY IS N, + BEQ RETRY ; DO A RETRY + CMP #'n' + BEQ RETRY + + JSR BOOP ; INSIST ON Y/RETURN + JMP GETYES ; OR N + +RETRY: LDX #LOW NO ; ELSE PRINT "NO" + LDA #HIGH NO + LDY #NOL + JSR DLINE + JMP PARAMS ; AND TRY AGAIN + +ALLSET: LDX #LOW YES ; PRINT "YES" + LDA #HIGH YES + LDY #YESL + JSR DLINE + + ; CALC START POSITION OF SAVE + + LDA #0 ; SET FOR POSITION 1 + STA DBLOCK+LO + STA DBLOCK+HI + + LDX TPOSIT ; GET # OF SAVES IN TO MOVE + BEQ FINDTS +CALC: CLC ; AND FIND WHAT SECTOR TO START WITH + ADC SAVSIZ + BCC CALC1 + INC DBLOCK+HI +CALC1: DEX + BNE CALC + STA DBLOCK+LO ; IN THE FORM OF DBLOCKS + +FINDTS: LDA DBLOCK+LO + LDX DBLOCK+HI + LDY #1 + JSR SETTS ; GET TRACK & SECTOR + +SREADY: LDX #LOW INSM + LDA #HIGH INSM + LDY #INSML + JSR DLINE ; "INSERT SAVE DISK IN DRIVE X." + JSR RETURN ; "PRESS [RETURN] TO CONTINUE." + +TRYOPN: LDA TDRIVE ; TRY TO OPEN SPECIFIED DRIVE + CLC + ADC #8 + JSR DOPEN ; THE DEFAULT DRIVE + RTS ; CARRY SET IF ERROR + + ; --------------------- + ; "PRESS RETURN" PROMPT + ; --------------------- + +RETURN: LDX #LOW RTN + LDA #HIGH RTN + LDY #RTNL + JSR DLINE ; SHOW PROMPT + + ; ENTRY FOR QUIT/RESTART + +GETRET: JSR GETIN ; WAIT FOR [RETURN] + CMP #0 + BEQ GETRET ; GET A CHAR 1ST + AND #%01111111 ; CLEAR SHIFT + CMP #EOL + BEQ RETEX + JSR BOOP ; ACCEPT NO + JMP GETRET ; SUBSTITUTES! + +RETEX: RTS + +RTN: DB EOL + DB "Press [RETURN] to continue." + DB EOL,EOL +RTNL EQU $-RTN + + + ; --------- + ; SAVE GAME + ; --------- + +SAV: DB "Save Position" + DB EOL +SAVL EQU $-SAV + +SVING: 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 DLINE ; "SAVE POSITION" + + JSR PARAMS ; GET PARAMETERS + BCC DOSAVE ; ERROR IF CARRY SET + +BADSAV: JSR SIDE2 ; PROMPT FOR GAME DISK + JMP RET0 ; AND FAIL + +DOSAVE: 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+LO ; MOVE [ZSP] + STA BUFSAV+2 + LDA ZSP+HI + STA BUFSAV+3 + LDA OLDZSP+LO + STA BUFSAV+4 + LDA OLDZSP+HI ; MOVE [OLDZSP] + STA BUFSAV+5 + + LDX #2 ; MOVE CONTENTS OF [ZPC] +ZPCSAV: LDA ZPC,X ; TO BYTES 5-7 + STA BUFSAV+6,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 + BCS BADSAV ; CATCH WRITE ERROR HERE + + ; WRITE CONTENTS OF Z-STACK TO DISK + +ZSOK: LDA #HIGH ZSTKBL ; POINT TO 1ST PAGE + STA DBUFF+HI + LDA #4 ; DO ALL 4 PAGES + STA L ; SET COUNTER +ZSOKLP: JSR PUTDSK ; WRITE THEM + BCS BADSAV + DEC L + BNE ZSOKLP + + ; 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 + LDA TDRIVE ; IF SAVE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TPOSIT + STA GPOSIT + LDA #1 ; SET TO MARK + LDX #0 + JMP PUTBYT ; SUCCESS + + + ; ------------ + ; RESTORE GAME + ; ------------ + +RES: DB "Restore Position" + DB EOL +RESL EQU $-RES + +RSING: DB EOL + DB "Restoring position " +RSPOS: DB "* ..." + DB EOL +RSINGL EQU $-RSING + +ZREST: JSR SAVRES + + LDX #LOW RES + LDA #HIGH RES + LDY #RESL + JSR DLINE ; "RESTORE POSITION" + + JSR PARAMS ; GET PARAMETERS + BCS BADRES ; ERROR IF CARRY SET + + 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 #MAIN + STA DSKBNK ; SET TO WRITE TO MAIN BANK + LDA #HIGH LOCALS + STA DBUFF+HI + JSR GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + BCS BADRES + + 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 INCORRECT SAVE DISK + +WRONG: LDX #31 ; RESTORE ALL SAVED LOCALS +WR0: LDA $0100,X + STA LOCALS,X + DEX + BPL WR0 + +BADRES: JSR SIDE2 ; PROMPT FOR GAME DISK + JMP RET0 ; AND FAIL + + ; CONTINUE RESTORE + +RIGHT: LDA ZBEGIN+ZSCRIP ; SAVE BOTH FLAG BYTES + STA I+LO + LDA ZBEGIN+ZSCRIP+1 + STA I+HI + + LDA #HIGH ZSTKBL ; RETRIEVE OLD CONTENTS OF + STA DBUFF+HI ; Z-STACK + LDA #4 ; DO 4 PAGES + STA L ; SET COUNTER +ZROKLP: JSR GETRES ; GET 4 PAGES OF Z-STACK + BCC ZROKL1 + JMP DSKERR ; IF HERE, MIX OF GOOD & BAD SO DIE + +ZROKL1: DEC L + BNE ZROKLP + + LDA ZCODE + STA DBUFF+HI + JSR GETRES ; GET 1ST BLOCK OF PRELOAD + BCC ZROKL2 + JMP DSKERR + +ZROKL2: 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 GETRES ; FETCH THE REMAINDER + BCC LREST0 + JMP DSKERR + +LREST0: DEC I+LO ; OF THE PRELOAD + BNE LREST + + ; RESTORE THE STATE OF THE SAVED GAME + + LDA BUFSAV+2 ; RESTORE THE [ZSP] + STA ZSP+LO + LDA BUFSAV+3 + STA ZSP+HI + LDA BUFSAV+4 + STA OLDZSP+LO + LDA BUFSAV+5 ; AND THE [OLDZSP] + STA OLDZSP+HI + + LDX #2 ; RESTORE THE [ZPC] +RESZPC: LDA BUFSAV+6,X + STA ZPC,X + DEX + BPL RESZPC + + LDA #$18 ; SET SCREEN PARAMETERS + STA ZBEGIN+ZSCRWD ; AS MAY BE C64 SAVE + LDA #80 + STA ZBEGIN+ZSCRWD+1 + + JSR SIDE2 ; PROMPT FOR GAME DISK + JSR VLDZPC ; MAKE VALID (12-2-86) + + LDA TDRIVE ; IF RESTORE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TPOSIT ; NEXT TIME + STA GPOSIT + LDA #2 ; SET TO + LDX #0 + JMP PUTBYT ; SUCCESS + + END + diff --git a/c-128/ezip/zstring.asm b/c-128/ezip/zstring.asm new file mode 100644 index 0000000..7362670 --- /dev/null +++ b/c-128/ezip/zstring.asm @@ -0,0 +1,435 @@ + PAGE + STTL "--- 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 + ROL A + STA MPCH + ASL MPCL ; QUAD-ALIGN ADDRESS!(EZIP) + ROL MPCM + ROL MPCH + JMP VLDMPC +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 ; DB II "a" MINUS Z-OFFSET +TODB: 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 ; DB II "A" MINUS Z-OFFSET + BNE TODB ; 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" DB II + TAX ; OTHERWISE USE CODE AS AN INDEX + LDA CHRTBL,X ; INTO THE CHARSET TABLE + JMP SHOVE ; AND PRINT THE CHAR + + ; DECODE A "DIRECT" DB II 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 ; DB II 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 SETFWD ; 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 + JSR VLDMPC + JMP PZTOP ; CONTINUE INNOCENTLY + + +; ---------------------- +; RETURN CURRENT CHARSET +; ---------------------- + +GETSET: LDA TSET + BPL GS + LDA PSET + RTS +GS: LDY #$FF + STY TSET + RTS + + +; ------------------------- +; POINT [I] AT FWORD STRING +; ------------------------- + +SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS + ASL A + STA MPCL + LDA I+HI + ROL A + STA MPCM + LDA #0 + ROL A + STA MPCH + JMP VLDMPC + + +; ----------------- +; 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 + LDX #$08 ; WITH PAD CHARS ($05) +CZSL: STA OUT,X + DEX + BPL CZSL + LDA #9 ; 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 DB II 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 9 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" DB II CHAR + + LDA #6 ; DB II 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 + STA OUT+2 ; MOVE CRUSHED Z-WORD + STX OUT+3 ; INTO PLACE + LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) + ASL A ; SHIFT BITS + ASL A + ASL A + ASL A + ROL OUT+6 ; ALONG WITH 7TH Z-CHAR + ASL A + ROL OUT+6 + ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR + STA OUT+5 ; SAVE HERE + LDA OUT+6 ; GRAB 7TH Z-CHAR + ORA #%10000000 ; SET HIGH BIT + STA OUT+4 ; MOVE CRUSHED Z-WORD 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 + diff --git a/c-128/split/spl.c b/c-128/split/spl.c new file mode 100644 index 0000000..7249dd4 --- /dev/null +++ b/c-128/split/spl.c @@ -0,0 +1,156 @@ +#include +#include + +#define BLKSIZE 512 +#define FMSIZE 64 + +char in_fname[FMSIZE], out_fname[FMSIZE]; /* used by all so make global */ + + +/********/ +/* main */ +/********/ + +main(argc, argv) +int argc; +char *argv[]; + { + FILE *in_fp, *out_fp, *fopen(); + long maxsize, length1, length2, addr1, addr2, addr3; + int i; + + if (argc < 5) + { + fprintf(stderr, "\nusage: spl <2nd start addr>.\n"); + exit(1); + } + + if ((in_fp = fopen(argv[1], "rb")) == NULL) + { + fprintf(stderr, "\nError opening <%s>\n", argv[1]); + exit(2); + } + + sscanf(argv[2], "%ld", &addr1); + sscanf(argv[3], "%ld", &addr2); + sscanf(argv[4], "%ld", &addr3); + + if (addr1 > addr2 || addr1 > addr3 || addr2 > addr3) + { + fprintf(stderr, "\nIllegal addresses, must be addr1 < addr2 < addr3.\n"); + exit(3); + } + + length1 = addr2 - addr1; + length2 = addr3 - addr2; + + for (i = 0; in_fname[i] = argv[1][i]; ++i) /* strip off type */ + if (in_fname[i] == '.') + break; + in_fname[i] = 0; + + sprintf(out_fname, "%s.bin", in_fname); + printf("Creating <%s>\n", out_fname); + + if ((out_fp = fopen(out_fname, "wb")) == NULL) + { + fprintf(stderr, "\nError opening <%s>\n", out_fname); + exit(4); + } + + copy (in_fp, out_fp, length1); + skip (in_fp, length2); + copyrest (in_fp, out_fp); + + fclose(out_fp); + fclose(in_fp); + printf("Ok, all done.\n"); + exit(0); + } + + +/********/ +/* copy */ +/********/ + +copy(in_fp, out_fp, maxsize) +FILE *in_fp, *out_fp; +long maxsize; +{ + long cursize; + int bytes, i; + char buffer[BLKSIZE]; + + cursize = 0; + + do + { + if ((maxsize - cursize) <= (long) BLKSIZE) + bytes = (int) (maxsize - cursize); + else + bytes = BLKSIZE; + + if ((i = fread(buffer, 1, bytes, in_fp)) == 0) + { + fprintf(stderr, "\nError reading file <%s>\n", in_fname); + exit(6); + } + + if (fwrite(buffer, 1, i, out_fp) != i) + { + fprintf(stderr, "\nError writing file <%s>\n", out_fname); + exit(5); + } + } + while ((cursize += (long) i) < maxsize); /* can't be greater than */ +} + + +/********/ +/* skip */ +/********/ + +skip (in_fp, length2) +FILE *in_fp; +long length2; +{ + long i; + + for (i = 0; i < length2; ++i) + if (fgetc (in_fp) == EOF) + { + fprintf(stderr, "\nError, file <%s> not as large as discard length.\n", in_fname); + exit(7); + } +} + + +/************/ +/* copyrest */ +/************/ + +copyrest(in_fp, out_fp) +FILE *in_fp, *out_fp; +{ + int bytes, i; + char buffer[BLKSIZE]; + + bytes = BLKSIZE; + + while (feof(in_fp) == 0) /* not eof */ + { + + if ((i = fread(buffer, 1, bytes, in_fp)) == 0) + { + fprintf(stderr, "\nError reading file <%s>\n", in_fname); + exit(6); + } + + if (fwrite(buffer, 1, i, out_fp) != i) + { + fprintf(stderr, "\nError writing file <%s>\n", out_fname); + exit(5); + } + } +} + \ No newline at end of file diff --git a/c-128/split/spl.exe b/c-128/split/spl.exe new file mode 100644 index 0000000..b756d9f Binary files /dev/null and b/c-128/split/spl.exe differ diff --git a/c-128/tftp/asm.bat b/c-128/tftp/asm.bat new file mode 100644 index 0000000..fd3f1e1 --- /dev/null +++ b/c-128/tftp/asm.bat @@ -0,0 +1,10 @@ +ECHO OFF +ECHO THIS BATCH FILE ASSEMBLES TFTP.ASM +ECHO IF NO ERRORS, TFTP.TSK WILL BE CREATED + +\6502\2500AD_X\X6502 TFTP -ED +\6502\2500AD_X\LINK -Q -C TFTP -X +basica baud + lda #baudlen ; and length + jsr SETNAM ; so send it + + lda RIDBS ; where does it now start + sta INDEX ; where do i start + + jsr OPEN ; and so open it + + jmp CLRCHN ; done +; +; get a byte from the comm buffer +; +getbyt: + tya + pha ; save y + txa + pha ; and save x +waiting: + ldx #3 ; set channel + jsr CHKIN ; for input + ldy RIDBS ; get where we are + cpy RIDBE ; get where it ends + beq waiting ; nothing yet + + lda RIBUFF,Y ; get char + inc RIDBS ; point to first one + sta INCHAR ; save it + + pla ; get a back + tax ; and make it x + pla ; and then just + tay ; get y back + lda INCHAR ; put char in a + rts ; and give it +; +; acknowledge a good block +; +doack: + lda #ACK ; get ack char +; fall through to send +putcom: + sta INCHAR ; save it + ldx #3 + jsr CHKOUT ; get ready for output + lda #CMND ; sending back command + jsr CHROUT ; and bye + lda INCHAR ; get command going + jsr CHROUT ; and bye + jmp CLRCHN ; clear and leave +; +; get a tftp data frame +; +frame: +getcom: +; i'm just going to ignore this here first byte and just look for +; either a data or eof command +; jsr getbyt ; get byte from comm +; cmp #CMND ; getting command? +; bne getcom ; better, or i'll ignore it + jsr getbyt ; what kind of command? + cmp #DATACMND ; is this some more data? + beq dodata ; yup, so start getting it + cmp #EOF ; end of file? + bne getcom ; if not, just ignore it + sec ; carry set + rts ; means EOF +; +; frame better start with: $01, $00, $FE, $FF +; +dodata: + jsr getbyt ; see what's up + cmp #$01 ; first + bne rerror ; receive error + jsr getbyt + bne rerror ; must be $00 + jsr getbyt + cmp #$FE ; looking for an FE + bne rerror + jsr getbyt + cmp #$FF ; and now an FF + bne rerror +; +; okay, now we can get the 256 byte data block and +; do the checksumming +; + ldx #0 + stx CHECKSUM+LO ; reset the checksum + stx CHECKSUM+HI +comloop: + jsr getbyt ; get a byte + sta IOBUFF,X ; save it + clc ; get ready for add + adc CHECKSUM+LO ; low byte + sta CHECKSUM+LO ; and save it + bcc cl0 + inc CHECKSUM+HI ; went to next one +cl0: + inx ; point to next char + bne comloop ; and get next one +; +; check check sum +; + jsr getbyt ; get MSB of check sum + cmp CHECKSUM+HI ; and compare with mine + bne rerror ; nope + jsr getbyt ; get LSB of check sum + cmp CHECKSUM+LO ; and compare with min + bne rerror ; nope + clc ; carry clear + rts ; show's its good +; +; nak a bad block here +; +rerror: + lda #NAK ; get nak cmnd + jsr putcom ; and send it out + jmp frame ; and start anew + + \ No newline at end of file diff --git a/c-128/tftp/disk.asm b/c-128/tftp/disk.asm new file mode 100644 index 0000000..70b1c4f --- /dev/null +++ b/c-128/tftp/disk.asm @@ -0,0 +1,188 @@ +; +; disk stuff +; + ; --------------- + ; SEND U2 (write) COMMAND + ; --------------- + +COMLIN: DB "U2:2,0," +DTRAK: DB "***," +DSECT: DB "***" + DB EOL +CMLL EQU $-COMLIN + +SENDU: + ; CONVERT [TRACK] AND [SECTOR] TO ASCII IN [COMLIN] + + LDA TRACK + LDY #2 +TCON: JSR DIV10 ; DIVIDE BY 10 + ORA #'0' ; CONVERT TO ASCII + STA DTRAK,Y ; STORE INTO STRING + TXA ; GET QUOTIENT INTO [A] + DEY ; ZERO-FILL USUSED BYTES + BPL TCON + + LDA SECTOR ; SAME FOR SECTOR ID + LDY #2 +SCON: JSR DIV10 + ORA #'0' + STA DSECT,Y + TXA + DEY + BPL SCON + + ; SEND COMMAND + + JSR CLRCHN + LDX #15 ; OUTPUT TO THE + JSR CHKOUT ; COMMAND CHANNEL + BCS UEX ; EXIT W/CARRY SET IF ERROR + + LDY #0 +SCM0: LDA COMLIN,Y ; SEND THE COMMAND LINE + JSR CHROUT ; TO THE DRIVE CHANNEL + INY ; A BYTE AT A TIME + CPY #CMLL + BCC SCM0 + CLC ; SUCCESS! +UEX: RTS + + ; -------------------------- + ; OPEN DIRECT ACCESS CHANNEL + ; -------------------------- + +POUND: db "#" +POUNDL equ $-POUND + +AOPEN: + LDA #2 ; D/A CHANNEL ID + JSR CLOSE ; close it first + + TAY ; SECONDARY ID + LDX #8 ; always on drive 8 + JSR SETLFS + + LDX #POUND ; "#" + LDA #POUNDL ; to let disk pick buffer + JSR SETNAM + + JMP OPEN ; OPEN CHANNEL (CARRY CLEAR IF OK) + + ; ---------------------- + ; SET THE BUFFER POINTER + ; ---------------------- + +BPLINE: DB "B-P:2,0" + DB EOL +BPLL EQU $-BPLINE + +SETBP: JSR CLRCHN + LDX #15 ; OUTPUT TO + JSR CHKOUT ; COMMAND CHANNEL + BCS BEX ; CARRY SET IF ERROR + + LDY #0 +SBPL: LDA BPLINE,Y + JSR CHROUT + INY + CPY #BPLL + BCC SBPL + CLC +BEX: RTS + + + ; -------------- + ; OPEN DRIVE [A] + ; -------------- + + ; ENTRY: DISK ID (8 OR 9 BINARY) IN [A] + +I0: db "I0:" +I0L equ $-I0 + +dopen: + LDA #15 ; LOGICAL FILE # + TAY ; SECONDARY ADDRESS + LDX #8 ; DEVICE #8 + JSR SETLFS ; SET UP LOGICAL FILE + + LDX #I0 ; "I0:" + LDA #I0L ; LENGTH OF FILENAME + JSR SETNAM + + JMP OPEN ; OPEN THE DISK (CARRY CLEAR IF OK) + + ; WRITE A BLOCK + +dwrite: + JSR AOPEN ; OPEN THE ACCESS CHANNEL + BCS BADISK + + JSR SETBP ; SET THE BUFFER POINTER + BCS BADISK ; CARRY SET IF ERROR + + JSR CLRCHN + LDX #2 ; OUTPUT TO + JSR CHKOUT ; DATA CHANNEL + BCS BADISK ; CARRY SET IF ERROR + + LDY #0 +WRITE1: LDA IOBUFF,Y ; SEND CONTENTS OF [IOBUFF] + JSR CHROUT ; TO THE DRIVE + INY + BNE WRITE1 ; WRITE 256 BYTES + + JSR SENDU + BCS BADISK ; CARRY SET IF ERROR + +SHUTD: JSR READST + AND #%10000011 + BNE BADISK + + JSR CLRCHN + CLC ; CARRY CLEAR FOR SUCCESS + RTS + +BADISK: JSR CLRCHN + SEC + RTS ; OR SET IF ERROR +; +; nxtts - get the next track and sector +; +nxtts: + INC SECTOR ; NEXT SECTOR + LDY TRACK ; CHECK IF NEXT TRACK + DEY + LDA SECTOR + CMP TRKTBL,Y + BCC SECTOK + INC TRACK ; YES, RESET + LDA #0 + STA SECTOR + LDA TRACK + CMP #18 + BNE DNOT18 + INC SECTOR ; SKIP 1ST SECTOR TRACK 18 (DIRECTORY) + BNE SECTOK +DNOT18: ; check for sector 20 + CMP #20 ; for fast code stuff + BNE SECTOK + INC SECTOR ; so skip over sector 0 +SECTOK: + RTS +; +; this table shows the last usable sector on the track + 1 +; i.e. 21 means there are sectors 0-20 on the track +; +TRKTBL: DB 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21 + DB 19,19,19,19,19,19,19 + DB 18,18,18,18,18,18 + DB 17,17,17,17,17 + + + + + \ No newline at end of file diff --git a/c-128/tftp/eq.asm b/c-128/tftp/eq.asm new file mode 100644 index 0000000..8288d38 --- /dev/null +++ b/c-128/tftp/eq.asm @@ -0,0 +1,50 @@ + PAGE + STTL "--- MEMORY ORGANIZATION ---" + +TRUE EQU $FF +FALSE EQU 0 +LO EQU 0 +HI EQU 1 + + ; --------- + ; CONSTANTS + ; --------- + +EOL EQU $0D ; EOL CHAR +SPACE EQU $20 ; SPACE CHAR +BACKSP EQU $14 ; BACKSPACE +LF EQU $0A ; LINE FEED +CLS EQU $93 ; CLEAR SCREEN, HOME CURSOR +ESCAPE EQU $1B ; ESCAPE KEY + +; +; tftp constants +; +CMND EQU $7E ; command for tftp +DATACMND EQU $00 ; data following +EOF EQU $04 ; end of file +ACK EQU $02 ; acknowledge good block +NAK EQU $05 ; bad block here + + ; FONT 1 & 2 OFFSETS + +FONT1T EQU 32 ; TRACK & SECTOR TO FIND +FONT1S EQU 0 ; FONT FILES ON +FONT2T EQU 33 +FONT2S EQU 0 + +C128T EQU 1 ; C128 interpreter start track +C128S EQU 0 ; and sector +C64T EQU 20 ; C64 interpreter start track +C64S EQU 0 ; and sector +LSIDE1T EQU 3 ; side 1 start track for LZIP games +LSIDE1S EQU 0 ; and sector +SIDE1T EQU 5 ; side 1 start track +SIDE1S EQU 0 ; and sector +SIDE2T EQU 1 ; side 2 start track +SIDE2S EQU 0 ; and sector +FASTT EQU 20 ; fastcode, side 2, start track +FASTS EQU 0 ; and sector + + END + \ No newline at end of file diff --git a/c-128/tftp/format.asm b/c-128/tftp/format.asm new file mode 100644 index 0000000..51ab08f --- /dev/null +++ b/c-128/tftp/format.asm @@ -0,0 +1,104 @@ +; +; format a disk please +; +fmtmsg: + DB CLS,EOL,EOL," ",RVSON + DB YELLOW,"Format Commodore game disk",RVSOFF + DB EOL,EOL,LRED,"Please select which side you wish to format:",EOL + DB " 1 - format side 1 (NAME: 'INFOCOM-S1')",EOL + DB " 2 - format side 2 (NAME: 'INFOCOM-S2')",EOL + DB " X - Done Formatting",EOL,LGREEN +fmtlen EQU $-fmtmsg + +fcmd DB "N0:INFOCOM-S" ; formatting command +fside DB '*' ; store actual side here + DB ",XX" +fcmdl equ $-fcmd + +insmsg: db EOL,EOL,"Give me the disk to be MUNGED, please!" + db EOL, "Hit any key to CHOMP it, or ",RED,"",LGREEN, + db " to begin anew" +inslen equ $-insmsg + +waitmsg: db DYELLOW,EOL,EOL,"Now hit any key to continue . . ." +waitlen equ $-waitmsg + +workmsg: db CYAN,EOL,EOL,"Give me a moment while I format the disk . . ." +worklen equ $-workmsg + +formatter: + MSG fmt ; print out prompt +floop: + jsr GETIN + tay + beq floop ; wait for command + + cmp #'1' ; do side 1 + bne fk1 + + sta fside ; save in string + jmp dofmt +fk1: + cmp #'2' ; do side 2? + bne fk2 + + sta fside ; yes, so show it + jmp dofmt +fk2: + cmp #'X' ; done? + bne floop ; unknown command, so try again + jmp begin ; go back to start +; +; do the actual formatting of disk, please +; +dofmt: + MSG ins ; ask for disk +dfloop: + jsr GETIN + tay + beq dfloop ; no key yet + cmp #ESCAPE ; check for get me outta here + bne dfl1 ; nope + jmp begin ; begin again +dfl1: + MSG work ; show we are working + + lda #$0f ; logical number 15 + ldx #$08 ; drive 8 + ldy #$0f ; secondary address 15 + jsr SETLFS ; and setit + bcs error ; problems with drive + + lda #fcmdl ; length of command + ldx #fcmd ; and MSG of command address + jsr SETNAM ; and send it out + bcs error ; problems with drive + + jsr OPEN ; open things up + bcs error ; problems with drive + + lda #$0f ; and now close it + jsr CLOSE ; thank you + bcs error ; problems with drive +wait: + MSG wait ; now wait for key +wloop: + jsr GETIN + tay + beq wloop + + jmp formatter + +; +; just complain about error +; +errmsg: db "Problems with disk and/or drive",EOL + db "Please check things out and try again!!" +errlen equ $-errmsg + +error: + MSG err ; complain about error + + jmp wait + \ No newline at end of file diff --git a/c-128/tftp/hardeq.asm b/c-128/tftp/hardeq.asm new file mode 100644 index 0000000..69e056b --- /dev/null +++ b/c-128/tftp/hardeq.asm @@ -0,0 +1,158 @@ + PAGE + STTL "--- HARDWARE EQUATES: CBM128 ---" + + + ; --------- + ; Zero page stuff + ; --------- + +IOBUFF EQU $B00 ; Disk IO buffer + +SECTOR EQU 3 ; (BYTE) TARGET SECTOR +TRACK EQU SECTOR+1 ; (BYTE) TARGET TRACK +TEMP EQU TRACK+1 ; (BYTE) Temp variable +BLNUM EQU TEMP+1 ; (3 BYTES) place to count blocks (in ascii) +INDEX EQU BLNUM+3 ; index into rs-232 buffer +INCHAR EQU INDEX+1 ; incoming character +CHECKSUM EQU INCHAR+1 ; whole word for checksum please +XSAVE EQU CHECKSUM+2 ; where to save x,y +YSAVE EQU XSAVE+1 ; for whatever reason +QUOT EQU YSAVE+1 ; for divide word by 10 +DIVWORD EQU QUOT+1 ; (WORD) what we are dividing + + ; ----------------- + ; MONITOR VARIABLES + ; ----------------- + +WLEFT EQU $E6 ; LEFT MARGIN (0) +WWIDTH EQU $E7 ; RIGHT MARGIN (40 OR 80) +WTOP EQU $E5 ; TOP LINE (0-23) +WBOTM EQU $E4 ; BOTTOM LINE (1-24) +LINES EQU $ED ; # LINES ON SCREEN +COLMODE EQU $D7 ; WHAT COLUMN MODE ARE WE IN (40/80) +QUOTMOD EQU $F4 ; QUOTES SENT TO SCREEN TURN ON STRANGE + ; MODE, THIS FLAG SET TO 0 SHOULD + ; TURN THAT MODE OFF + + ; --------- + ; ZERO-PAGE + ; --------- + +D6510 EQU $00 ; 6510 DATA DIRECTION REGISTER +R6510 EQU $01 ; 6510 I/O PORT +FAST EQU $02 ; FAST-READ AVAILABLE FLAG +STKEY EQU $91 ; STOP KEY FLAG +MSGFLG EQU $9D ; KERNAL MESSAGE CONTROL FLAG +TIME EQU $A2 ; SYSTEM JIFFY TIMER +BLNSW EQU $CC ; CURSOR BLINK SWITCH +NDX EQU $D0 ; # CHARS IN KEYBOARD BUFFER +SFDX EQU $D4 ; CURRENT KEY PRESSED +LSTX EQU $D5 ; LAST KEY PRESSED +TBLX EQU $EB ; CURRENT CURSOR ROW +PNTR EQU $EC ; CURSOR COLUMN IN LOGICAL LINE +RVS EQU $F3 ; REVERSE CHARACTER FLAG +KEYTAB EQU $F5 ; KEYBOARD DECODE TABLE VECTOR +MODE EQU $F7 ; CHARSET MODE SWITCH + +FDATA EQU $FB ; FAST-READ DATA BUFFER +FINDEX EQU $FC ; FAST-READ BUFFER INDEX +FASTEN EQU $FD ; FAST-READ ENABLED FLAG + + ; ----------- + ; PAGES 2 & 3 + ; ----------- + +LBUFF EQU $0200 ; 89-BYTE LINE BUFFER +KEYD EQU $0277 ; KEYBOARD QUEUE +RPTFLG EQU $028A ; KEY REPEAT FLAG +SHFLAG EQU $028D ; SHIFT KEY FLAG +KEYLOG EQU $028F ; VECTOR TO KEY-TABLE SETUP ROUTINE +CINV EQU $0314 ; SYSTEM 60HZ IRQ VECTOR +CBINV EQU $0316 ; BRK INSTRUCTION VECTOR +NMINV EQU $0318 ; NMI INTERRUPT VECTOR + + ;-------- + ; other pages + ;---------- +RIDBE EQU $0A18 ; RS-232 end of buffer +RIDBS EQU $0A19 ; RS-232 start of buffer +RIBUFF EQU $0C00 ; RS-232 receive buffer + + ; ----- + ; COLOR + ; ----- + +COLRAM EQU $D800 ; COLOR RAM +EXTCOL EQU $D020 ; BORDER COLOR +BGCOLO EQU $D021 ; BACKGRND COLOR +FRCOLO EQU $F1 ; FOREGRND COLOR REG + +WHITE EQU $03 +RED EQU $1C +LGREEN EQU $99 +CYAN EQU $9F +LRED EQU $96 +YELLOW EQU $9E +BLUE EQU $1F +DYELLOW EQU $95 +DCYAN EQU $97 + +RVSON EQU $12 ; reverse video on/off +RVSOFF EQU $92 +UNDON EQU $03 ; underline on/off +UNDOFF EQU $82 +BLKON EQU $0F ; blink on/off +BLKOFF EQU $8F + + + ; -------------- + ; MEMORY CONTROL + ; -------------- + +LCRA EQU $FF01 +LCRB EQU $FF02 + +CR EQU $FF00 ; MAIN CONFIGURATION REGISTER +PCRA EQU $D501 +PCRB EQU $D502 +MCR EQU $D505 ; MODE CONFIG REG (6502/128) +RCR EQU $D506 ; RAM CONFIG REG (SHARED/WHERE) +FASTER EQU $D030 ; BIT 0 - 1 = 2 MHz speed + + ; ------------------- + ; KERNAL JUMP VECTORS + ; ------------------- + +FASTIO EQU $FF47 ; FAST DATA I/O +CHKIN EQU $FFC6 ; OPEN CHANNEL FOR INPUT +CHKOUT EQU $FFC9 ; OPEN CHANNEL FOR OUTPUT +CHRIN EQU $FFCF ; INPUT CHARACTER FROM CHANNEL +CHROUT EQU $FFD2 ; OUTPUT CHARACTER TO CHANNEL +CINT EQU $FF81 ; INIT SCREEN EDITOR +CLALL EQU $FFE7 ; CLOSE ALL CHANNELS & FILES +CLOSE EQU $FFC3 ; CLOSE A FILE +CLRCHN EQU $FFCC ; CLEAR CHANNEL +GETIN EQU $FFE4 ; GET CHAR FROM KEYBOARD QUEUE +IOINIT EQU $FF84 ; INIT I/O +OPEN EQU $FFC0 ; OPEN A FILE +PLOT EQU $FFF0 ; READ/SET CURSOR POSITION +RAMTAS EQU $FF87 ; INIT RAM +READST EQU $FFB7 ; READ I/O STATUS +SCNKEY EQU $FF9F ; SCAN KEYBOARD +SETLFS EQU $FFBA ; SET FILE ATTRIBUTES +SETMSG EQU $FF90 ; SET KERNAL MESSAGES +SETNAM EQU $FFBD ; SET FILENAME +SWAPPER EQU $FF5F ; SWAP TO ALTERNATE DISPLAY DEVICE +RESET EQU $FFFC ; do a reset + +MSG .MACRO XMSG ; to print out a message + + LDX #XMSG|msg ; and the MSB + LDY #XMSG|len ; and the length of the message + JSR DLINE ; now print out the whole thing + .ENDM + + END + + \ No newline at end of file diff --git a/c-128/tftp/main.asm b/c-128/tftp/main.asm new file mode 100644 index 0000000..b32c031 --- /dev/null +++ b/c-128/tftp/main.asm @@ -0,0 +1,104 @@ +; +; this does receiving and writing +; +doingmsg: db EOL,EOL,"Waiting for transfer . . . .",EOL,EOL + db CYAN,"Blocks Received: " +doinglen equ $-doingmsg + +donemsg: db EOL,EOL,RVSON,DYELLOW,"Finished with transfer.",EOL,EOL + db EOL," Hit any key to continue . . . ", +donelen equ $-donemsg + +doit: + lda #'0' ; init ascii counter + sta BLNUM + sta BLNUM+1 + sta BLNUM+2 + + jsr copen ; open comm port + jsr dopen ; open disk drive + MSG doing + + sec ; now get where cursor is for + jsr PLOT ; blocks count display + stx XSAVE ; and save it + sty YSAVE +xloop: +; jsr chkkey ; see if user wants to abort +; bcs done ; then quit now + jsr frame ; get transmit frame + bcc writeit + jmp done ; cs if EOF +writeit: + jsr dwrite ; write out block + jsr nxtts ; get next track and sector + jsr doack ; send back ack + jsr blocks ; inc and display blocks done + jmp xloop ; and continue +; +; all done with transfer, so show it and leave +; +done: + jsr doack ; finished with this transfer + jsr CLRCHN ; clear things up + + MSG done ; and show world we are done +donel: + jsr GETIN + tay + beq donel ; wait for user to be happy + + jmp begin ; and start all over + +blocks: + ldx XSAVE ; get where to put it + ldy YSAVE + clc + jsr PLOT ; and put it there + + ldx #2 ; inc chars counting +countl: + inc BLNUM,x ; inc it + lda BLNUM,x ; get it for check + cmp #'9'+1 ; if <= '9' all set + bcc printit ; so print all chars + lda #'0' ; reset this one to zero + sta BLNUM,x ; and then go check next one + dex + bpl countl ; check next one +printit: + lda BLNUM ; now put it out there + cmp #'0' ; don't print leading zero + beq next1 ; so don't do it + jsr CHROUT +next1: + lda BLNUM+1 ; one by one, by hand for speed + cmp #'0' ; don't print leading zeros + bne pj ; okay, so print it + ldx BLNUM ; gotta check first one too, + cpx #'0' ; and if it is zero then don't print + beq pj1 ; any of these +pj: + jsr CHROUT ; not leading zero, so print +pj1: + lda BLNUM+2 ; and now the last one + jsr CHROUT + + rts + +; +; see if user has hit abort (ESCAPE KEY) to get out +; +chkkey: + jsr CLALL + jsr GETIN + cmp #ESCAPE ; is it the escape key? + bne notdone + + sec ; set to show found + rts +notdone: + clc ; clear to show not found + rts + + \ No newline at end of file diff --git a/c-128/tftp/send.bas b/c-128/tftp/send.bas new file mode 100644 index 0000000..1e3b0d3 Binary files /dev/null and b/c-128/tftp/send.bas differ diff --git a/c-128/tftp/subs.asm b/c-128/tftp/subs.asm new file mode 100644 index 0000000..ff9fd58 --- /dev/null +++ b/c-128/tftp/subs.asm @@ -0,0 +1,201 @@ +; +; print out prompt message and set up start track and sector for each one +; +gc128msg: db CLS,EOL,EOL," ",RVSON + db YELLOW,"Put C128 Xzip Interpreter onto Side 1",EOL +gc128len equ $-gc128msg + +getc128: ; get c128 xzip interpreter + MSG gc128 + + lda #C128T ; start track + sta TRACK + lda #C128S ; start sector + sta SECTOR + jmp ready ; now see if user is ready + +gc64msg: db CLS,EOL,EOL," ",RVSON + db YELLOW,"Put C64 Xzip Interpreter onto Side 1" +gc64len equ $-gc64msg + +getc64: ; go get c64 xzip interpreter + MSG gc64 + lda #C64T ; c64 interpreter start track + sta TRACK + lda #C64S ; and start sector + sta SECTOR + jmp ready ; now do it + +gs1lmsg: db CLS,EOL,EOL," ",RVSON + db YELLOW,"Put LZIP story preload onto side 1 of disk",EOL + db EOL,LRED,"REMEMBER:",EOL + db " Combined C64/C128 split @" + db YELLOW,"44800",EOL + db LRED," Commodore C128 split @" + db DCYAN,"88064",EOL +gs1llen equ $-gs1lmsg + +gets1l: ; get side 1 of the story + MSG gs1l + + lda #LSIDE1T ; start story at track + sta TRACK + lda #LSIDE1S ; sector + sta SECTOR + + jmp ready ; now do it + +gs1msg: db CLS,EOL,EOL," ",RVSON + db YELLOW,"Put story preload onto side 1 of disk",EOL + db EOL,LRED,"REMEMBER:",EOL + db " Combined C64/C128 split @" + db YELLOW,"44800",EOL + db LRED," Commodore C128 split @" + db DCYAN,"88064",EOL +gs1len equ $-gs1msg + +gets1: ; get side 1 of the story + MSG gs1 + + lda #SIDE1T ; start story at track + sta TRACK + lda #SIDE1S ; sector + sta SECTOR + + jmp ready ; now do it + +gs2msg: db CLS,EOL,EOL," ",RVSON + db YELLOW,"Put story PURLOAD onto side 2 of disk",EOL + db EOL,LRED,"REMEMBER:",EOL + db " Combined C64/C128 split @" + db YELLOW,"44800",EOL + db LRED," Commodore C128 split @" + db DCYAN,"88064",EOL +gs2len equ $-gs2msg + +gets2: ; get side 2 of story + MSG gs2 + + lda #SIDE2T ; side 2 starts at track + sta TRACK + lda #SIDE2S ; sector + sta SECTOR + + jmp ready ; now get ready + +gf1msg: db CLS,EOL,EOL," ",RVSON + db YELLOW,"Put C128 Font 1 onto side 1" +gf1len equ $-gf1msg + +getf1: ; get font 1 + MSG gf1 + + lda #FONT1T ; font track + sta TRACK + lda #FONT1S ; and sector + sta SECTOR + + jmp ready ; so do it already + +gf2msg: db CLS,EOL,EOL," ",RVSON + db YELLOW,"Put C128 Font 2 onto side 1" +gf2len equ $-gf2msg + +getf2: ; get font 2 + MSG gf2 + + lda #FONT2T ; font 2 track + sta TRACK + lda #FONT2S ; font 2 sector + sta SECTOR + + jmp ready ; and wing it + +gfcmsg: db CLS,EOL,EOL," ",RVSON + db YELLOW,"Put Commodore 64 FASTCODE onto side 2" +gfclen equ $-gfcmsg + +getfc: ; get the c64 fastcode + MSG gfc + + lda #FASTT ; fast code start track + sta TRACK + lda #FASTS ; and sector + sta SECTOR + + jmp ready ; and do it + +rdymsg: db EOL,EOL,LGREEN,"Insert Disk to be copied onto and then" + db " hit any key to begin transfer or the",EOL + db RED," ", LGREEN, "key to escape and start all over!" +rdylen equ $-rdymsg + +ready: + MSG rdy + +rloop: + jsr GETIN + tay + beq rloop ; wait for user + + cmp #ESCAPE ; check of X-scape + beq rexit + + jsr doit ; do the transfer +rexit: + jmp begin ; begin again + +; ----------------------- +; 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 + STY TEMP ; COUNTER + + LDX #0 ; INIT CHAR-FETCH INDEX +DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE +STRING: DW $0000 ; DUMMY OPERAND BYTES + JSR CHAR + INX + DEC TEMP ; LOOP TILL + BNE DOUT ; OUT OF CHARS + RTS + +CHAR: CMP #'a' ; LOWER-CASE? + BCC LET0 ; NO, CONTINUE + CMP #'z'+1 + BCS LETEX ; CTRL CHARS + AND #%01011111 ; ELSE MASK FOR LOWER-CASE + BNE LETEX +LET0: + CMP #'A' ; UPPER-CASE? + BCC LETEX + CMP #'Z'+1 + BCS LETEX + ORA #%00100000 ; MAKE UPPER +LETEX: + JSR CHROUT ; goodbye, cruel char + RTS + ; ---------------- + ; DIVIDE [A] BY 10 + ; ---------------- + + ; EXIT: QUOTIENT IN [X], REMAINDER IN [A] + +DIV10: LDX #0 ; START WITH ZERO QUOTIENT + +D10L: CMP #10 ; IF DIVISOR < 10, + BCC D10EX ; WE'RE DONE + SBC #10 ; ELSE SUBTRACT ANOTHER 10 + INX ; UPDATE QUOTIENT + BNE D10L ; BRANCH ALWAYS + +D10EX: RTS + end + + + \ No newline at end of file diff --git a/c-128/tftp/tftp.asm b/c-128/tftp/tftp.asm new file mode 100644 index 0000000..b04e3a3 --- /dev/null +++ b/c-128/tftp/tftp.asm @@ -0,0 +1,117 @@ + PAGE + STTL "--- MACHINE COLDSTART: CBM64 ---" + + INCLUDE EQ.ASM + INCLUDE HARDEQ.ASM + + ORG $4000 +TFTP: + LDA #%00001110 ; SET UP CONFIGURATION + STA CR + + LDA #%00001001 ; 80 Column display + ; Fast disk i/o + ; 8502 processor + STA MCR ; and save it + + LDA #$01 ; set fast mode! + STA FASTER ; + + LDA #$0E + JSR CHROUT ; USE UPPER/LOWER CHARS + + LDA #0 + JSR SETMSG ; DISABLE KERNAL MESSAGES + + CLD + LDX #$FF + TXS + +; JSR CLALL ; CLOSE EVERYTHING + + JMP begin + + ; --------------- + ; WARMSTART ENTRY + ; --------------- + +tftp1msg: + DB RVSON,YELLOW + DB CLS,"Commodore C128 TFTP Rev 1.0 == 2400 BAUD ==",EOL,EOL,LRED + DB "Please select TFTP option from list below:",EOL + DB " F - Format Disk",EOL,EOL + DB " 8 - C128 XZIP Interpreter",EOL + DB " 4 - C64 XZIP Interpreter",EOL,EOL +tftp1len equ $-tftp1msg +tftp2msg: + DB " 1 - Story Side 1",EOL + DB " 2 - Story Side 2", EOL,EOL + DB " L - LZIP Story Side 1",EOL,EOL + DB " A - C128 Font 1 (on Side 1)",EOL + DB " B - C128 Font 2 (on Side 1)",EOL,EOL + DB " C - C64 FastCode (on Side 2)",EOL,EOL + DB " X - Exit and return to BASIC",EOL +tftp2len EQU $-tftp2msg + +; +; this is where all the commands return to when all done +; +begin: + MSG tftp1 + MSG tftp2 +GLOOP: + JSR GETIN + TAY + BEQ GLOOP ; wait for command key + + CMP #'F' ; format disk + bne ck1 + jmp formatter +ck1: + cmp #'8' ; get c128 xzip interpreter + bne ck2 + jmp getc128 +ck2: + cmp #'4' ; get c64 xzip interpreter + bne ck3 + jmp getc64 +ck3: + cmp #'1' ; get story, side 1 + bne ck4 + jmp gets1 +ck4: + cmp #'2' ; get story, side 2 + bne ck5 + jmp gets2 +ck5: + cmp #'A' ; get c128 font 1 + bne ck6 + jmp getf1 +ck6: + cmp #'B' ; get c128 font 2 + bne ck7 + jmp getf2 +ck7: + cmp #'C' ; get c64 fast code + bne ck8 + jmp getfc +ck8: + cmp #'X' ; all done + bne ck9 + jmp (RESET) ; so quit then +ck9: + cmp #'L' ; put on lzip side one + bne ck10 + jmp gets1l +ck10: + jmp GLOOP ; just wait some more + + INCLUDE FORMAT.ASM + INCLUDE SUBS.ASM + INCLUDE DISK.ASM + INCLUDE COMM.ASM + INCLUDE MAIN.ASM + + END + + \ No newline at end of file diff --git a/c-128/xzip/_read.me b/c-128/xzip/_read.me new file mode 100644 index 0000000..c5cde48 --- /dev/null +++ b/c-128/xzip/_read.me @@ -0,0 +1,9 @@ + +******* Directory Update and Source File Archive Record ****** + + Date of Last Change Version Letter Who Made the Change + ___________________ _____________ ____________________ + +1) 3/13/87 A (XZIP) Le +2) 9/18/87 A (XZIP) JDA +3) 11/13/87 E (XZIP) JDA diff --git a/c-128/xzip/bas.cmd b/c-128/xzip/bas.cmd new file mode 100644 index 0000000..2d0d717 --- /dev/null +++ b/c-128/xzip/bas.cmd @@ -0,0 +1,5 @@ +load"send" +run +g + + \ No newline at end of file diff --git a/c-128/xzip/boot.asm b/c-128/xzip/boot.asm new file mode 100644 index 0000000..4287c09 --- /dev/null +++ b/c-128/xzip/boot.asm @@ -0,0 +1,460 @@ + PL 58 ; PAGE LENGTH OF PRINTER + +DEBUG EQU $0 ; 0 = NO, 1 = YES +ZEROPG EQU $03 +ZPGTOP EQU $8F +COLD1 EQU $1200 ; WHERE TO ENTER THE REST OF THE CODE + + INCLUDE EQ.ASM + INCLUDE HARDEQ.ASM + + PAGE + STTL "--- MACHINE AUTOBOOT: CBM64 ---" + + ; ------------------ + ; THE VERY BEGINNING + ; ------------------ + + ORG EZIP + + ; 'CBM' IS AUTOBOOT RECOGNITION CODE + ; $00,$0C = TELLS AUTOBOOT TO READ REST IN STARTING AT $C00 + ; $00,$02 = READ IN 2 PAGES, $00 = NO DISK CODE, $00 = NO FILE NAME + + DB 'C','B','M' + DB $00,$0C,$00,$02,$00,$00 + + LDA COLMODE ; 1ST MAKE SURE IN 40 COLUMN MODE + CMP #$80 ; TO DISPLAY 80 COL MONITOR NEEDED MSG + BNE OK40 + JSR SWAPPER ; INTO 40 COL MODE +OK40: LDA #$0B ; DARK GRAY + STA EXTCOL ; BORDER + STA BGCOLO ; BACKGRND + STA FRCOLO ; FORGRND COLOR REG + LDY #>COLRAM + STY I+HI + LDY #BI0 ; "I0:" + LDA #BI0L ; LENGTH OF FILENAME + JSR RSETNAM + + JMP ROPEN ; OPEN THE DISK (CARRY CLEAR IF OK) + + ; -------------------------- + ; OPEN DIRECT ACCESS CHANNEL + ; -------------------------- + +BPOUND: DB "#" +BPNDL EQU $-BPOUND + +BAOPEN: LDA #0 +; STA SPENA ; SHUT OFF CURSOR DMA + + JSR BACLOSE ; CLOSE FIRST + + LDA #2 ; D/A CHANNEL ID + TAY ; SECONDARY ID + LDX DRIVE + JSR RSETLFS + + LDX #BPOUND ; "#" + LDA #BPNDL + JSR RSETNAM + + JMP ROPEN ; OPEN CHANNEL (CARRY CLEAR IF OK) + + ; ------------------- + ; CLOSE CURRENT DRIVE + ; ------------------- + +BDCLOSE: LDA #15 ; CLOSE COMMAND CHANNEL + JSR RCLOSE + + ; FALL THROUGH ... + + ; --------------------- + ; CLOSE THE D/A CHANNEL + ; --------------------- + +BACLOSE: LDA #2 ; AND THE + JMP RCLOSE ; DATA CHANNEL + + ; ---------------- + ; DIVIDE [A] BY 10 + ; ---------------- + + ; EXIT: QUOTIENT IN [X], REMAINDER IN [A] + +BDIV10: LDX #0 ; START WITH ZERO QUOTIENT + +BD10L: CMP #10 ; IF DIVISOR < 10, + BCC BD10EX ; WE'RE DONE + SBC #10 ; ELSE SUBTRACT ANOTHER 10 + INX ; UPDATE QUOTIENT + BNE BD10L ; BRANCH ALWAYS + +BD10EX: RTS + + ; --------------- + ; SEND Ux COMMAND + ; --------------- + + ; ENTRY: ASCII "1" OR "2" IN [A] + +BCOMLIN: DB "U" +BDCOMM: DB "*" + DB ":2,0," +BDTRAK: DB "***," +BDSECT: DB "***" + DB EOL +BCMLL EQU $-BCOMLIN + +BSENDU: STA BDCOMM ; INSERT COMMAND ("1" OR "2") IN STRING + + ; CONVERT [TRACK] AND [SECTOR] TO ASCII IN [COMLIN] + + LDA TRACK + LDY #2 +BTCON: JSR BDIV10 ; DIVIDE BY 10 + ORA #'0' ; CONVERT TO ASCII + STA BDTRAK,Y ; STORE INTO STRING + TXA ; GET QUOTIENT INTO [A] + DEY ; ZERO-FILL USUSED BYTES + BPL BTCON + + LDA SECTOR ; SAME FOR SECTOR ID + LDY #2 +BSCON: JSR BDIV10 + ORA #'0' + STA BDSECT,Y + TXA + DEY + BPL BSCON + + ; SEND COMMAND + + JSR RCLRCHN + LDX #15 ; OUTPUT TO THE + JSR RCHKOUT ; COMMAND CHANNEL + BCS BUEX ; EXIT W/CARRY SET IF ERROR + + LDY #0 +BSCM0: LDA BCOMLIN,Y ; SEND THE COMMAND LINE + JSR RCHROUT ; TO THE DRIVE CHANNEL + INY ; A BYTE AT A TIME + CPY #BCMLL + BCC BSCM0 + CLC ; SUCCESS! +BUEX: RTS + + ; ---------------------- + ; SET THE BUFFER POINTER + ; ---------------------- + +BBPLINE: DB "B-P:2,0" + DB EOL +BBPLL EQU $-BBPLINE + +BSETBP: JSR RCLRCHN + LDX #15 ; OUTPUT TO + JSR RCHKOUT ; COMMAND CHANNEL + BCS BBEX ; CARRY SET IF ERROR + + LDY #0 +BSBPL: LDA BBPLINE,Y + JSR RCHROUT + INY + CPY #BBPLL + BCC BSBPL + CLC +BBEX: RTS + + ; ------------------------------ + ; READ/WRITE A BLOCK TO [IOBUFF] + ; ------------------------------ + + ; ENTRY: [TRACK] = TRACK # (1-35) + ; [SECTOR] = SECTOR # (0-15) + ; [DRIVE] = DRIVE ID (8 OR 9) + ; CARRY CLEAR TO READ, CARRY SET TO WRITE + +BDISK: BCS BDWRITE ; WRITE IF CARRY SET + + ; READ A DISK BLOCK + + JSR BAOPEN ; OPEN THE ACCESS CHANNEL + BCS BBADISK + + LDA #'1' ; SEND A "U1" COMMAND + JSR BSENDU + BCS BBADISK ; CARRY SET IF ERROR + + JSR BSETBP ; SET THE BUFFER POINTER + BCS BBADISK ; CARRY SET IF ERROR + + JSR RCLRCHN + LDX #2 ; INPUT FROM + JSR RCHKIN ; DATA CHANNEL + BCS BBADISK + + LDY #0 +BREAD1: JSR RCHRIN ; GET A BYTE + STA IOBUFF,Y ; MOVE TO I/O BUFFER + INY + BNE BREAD1 ; DO 256 BYTES + + BEQ BSHUTD ; THEN EXIT + + ; WRITE A BLOCK + +BDWRITE: JSR BAOPEN ; OPEN THE ACCESS CHANNEL + BCS BBADISK + + JSR BSETBP ; SET THE BUFFER POINTER + BCS BBADISK ; CARRY SET IF ERROR + + JSR RCLRCHN + LDX #2 ; OUTPUT TO + JSR RCHKOUT ; DATA CHANNEL + BCS BBADISK ; CARRY SET IF ERROR + + LDY #0 +BWRITE1: LDA IOBUFF,Y ; SEND CONTENTS OF [IOBUFF] + JSR RCHROUT ; TO THE DRIVE + INY + BNE BWRITE1 ; WRITE 256 BYTES + + LDA #'2' ; ISSUE A "U2" COMMAND + JSR BSENDU + BCS BBADISK ; CARRY SET IF ERROR + +BSHUTD: JSR RREADST + AND #%10000011 + BNE BBADISK + + JSR RCLRCHN + CLC ; CARRY CLEAR FOR SUCCESS + RTS + +BBADISK: JSR RCLRCHN + SEC + RTS ; OR SET IF ERROR + + + ORG $DFF ; just to fill out the sector with + ; 'ff's, curtesy of the assembler! + DB $AA + + ; MARKER + + END + \ No newline at end of file diff --git a/c-128/xzip/bugger.asm b/c-128/xzip/bugger.asm new file mode 100644 index 0000000..f6f16c3 --- /dev/null +++ b/c-128/xzip/bugger.asm @@ -0,0 +1,284 @@ + PAGE + SBTTL "--- DEBUGGER: C128 ---" + + ; -------------- + ; C128 DEBUGGER + ; -------------- + + ; ENTRY: BREAKPOINT ID IN [A] + + ; SMALL DEBUGGER DBG1 (CONVERTS) DBG2 (JUST DISPLAYS) [A] + ; DISPLAYS ON LINE 24, col 75/76 + +dbgsvx: db 00 +dbgsvy: db 00 + +dbx: db 55 +dby: db 4 + +DBG1: STA HLDA + TYA + PHA + TXA + PHA + + LDA HLDA + PHA + LSR A + LSR A + LSR A + LSR A + JSR NIB1 + PLA + JSR NIB1 + + PLA + TAX + PLA + TAY + + RTS + +NIB1: AND #%00001111 + TAY + LDA HCHARS,Y + JMP CHROUT + +dbgsetc: + sec + jsr PLOT + stx dbgsvx + sty dbgsvy + ldx dby + ldy dbx + clc + jsr PLOT + rts + +dbgrstc: + sec + jsr PLOT + sty dbx + stx dby + clc + adc dbx + cmp #75 + bcc dchj1 + ldx dby + inx + cpx #24 + bne dchj + ldx #4 +dchj: + stx dby + lda #55 +dchj1: + sta dbx + ldx dbgsvx + ldy dbgsvy + clc + jsr PLOT + rts + + IF 0 +DBG2: STA HLDA + TYA + PHA + TXA + PHA + LDA HLDA + CMP #' ' + BEQ DBG3 + LDX HLDX ; PLACE ON 40 COL SCREEN + STA LINE18,X + INC HLDX + LDA #' ' +DBG3: LDX HLDX ; PLACE ON 40 COL SCREEN + STA LINE18,X + INC HLDX + PLA + TAX + PLA + TAY + LDA HLDA + RTS + ENDIF + +HCHARS: DB "0123456789ABCDEF" +HLDA: DB 0 +HLDX: DB 0 +HLDY: DB 0 +;LINE18 EQU $6D0 ; LINE 18 BYTE ADDR IN 40 COL SCREEN + + END + +BLINE: DB "B: OP: PC: S: V: 1: 2: 3: 4: 5: 6: " + DB EOL +BLINL EQU $-BLINE + + +DOBUG: STA DHOLD + NOP ; ON THE FLY CHANGE SPACE + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + +BUGIT: + LDX #2 ; INIT "CURSOR" + 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 BLINE,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 [ZSP] + LDA ZSP + JSR HEX + + LDX #29 ; CURSOR FOR [MPC] + LDA MPCH + JSR HEX + LDA MPCM + JSR HEX + LDA MPCL + JSR HEX + + LDX #38 + LDA DHOLD + JSR HEX + + LDX #43 + LDA BTWO + JSR HEX + + LDX #48 + LDA BTHREE + JSR HEX + + LDX #53 + LDA BFOUR + JSR HEX + + LDX #58 + LDA BFIVE + JSR HEX + + LDX #63 + LDA BSIX + JSR HEX + +PPP: LDX #0 +DBG1: LDA BLINE,X ; PRINT DEBUGGER TEXT + JSR CHROUT + INX + CPX #BLINL + BCC DBG1 + + LDA #0 + STA NDX ; CLEAR +WAITT: JSR GETIN ; NOW WAIT FOR ANOTHER KEY + CMP #0 + BEQ WAITT +WOK: NOP + + CMP #'Q' + BNE LLETEX + BRK + +LLETEX: +; LDX OLDX +; LDY OLDY +; CLC +; JSR PLOT ; NOW BACK TO OUR REGULARLY SCHEDULED PROGRAM + LDA DHOLD + 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 BLINE,X + INX + RTS + +HCHARS: DB "0123456789ABCDEF" + +BONE: DB 0 +BTWO: DB 0 +BTHREE: DB 0 +BFOUR: DB 0 +BFIVE: DB 0 +BSIX: DB 0 +DHOLD: DB 0 + + + END + + \ No newline at end of file diff --git a/c-128/xzip/bugger.new b/c-128/xzip/bugger.new new file mode 100644 index 0000000..468e52a --- /dev/null +++ b/c-128/xzip/bugger.new @@ -0,0 +1,46 @@ + PAGE + SBTTL "--- DEBUGGER: C128 ---" + + ; -------------- + ; C128 DEBUGGER + ; -------------- + + ; ENTRY: BREAKPOINT ID IN [A] + + ; SMALL DEBUGGER DBG1 (CONVERTS) DBG2 (JUST DISPLAYS) [A] + ; DISPLAYS ON LINE 24, col 75/76 + +DBG1: STA HLDA + TYA + PHA + TXA + PHA + + LDA HLDA + PHA + LSR A + LSR A + LSR A + LSR A + JSR NIB1 + PLA + JSR NIB1 + + PLA + TAX + PLA + TAY + + RTS + +NIB1: AND #%00001111 + TAY + LDA HCHARS,Y + JMP CHROUT + +HCHARS: DB "0123456789abcdef" +HLDA: DB 0 + + END + + \ No newline at end of file diff --git a/c-128/xzip/c128 b/c-128/xzip/c128 new file mode 100644 index 0000000..2e0dfd1 --- /dev/null +++ b/c-128/xzip/c128 @@ -0,0 +1,29 @@ +C128 Requirements for: + +Alternate character sets: + +The first character must be 32 (GOFF must be 32 or greater). +The number of characters can therefore only be up to 96 (GCOUNT must be 96 +or less). +The GSIZE must be 8 x 8. Any other configuration is unmanagable. + +Two alternate character sets are possible. They must be created as two +separate file, both of which will be loaded into character memory at the +start of the game. Neither set can be expected to be displayed while the +output is in inverse mode. Any inverse of a char you wish must be explicitly +included in the character sets. + + + +There is no capability for picture files. + + + +COLOR is possible. All the colors mentioned in the spec may be used for both +the foreground and the background, however, while all the colors may appear +on the screen together at once as the foreground, only 1 color at a time may +be the background color. Changing the background color will cause the entire +screen background to change to that color. + + + \ No newline at end of file diff --git a/c-128/xzip/cold.asm b/c-128/xzip/cold.asm new file mode 100644 index 0000000..e1ea5b2 --- /dev/null +++ b/c-128/xzip/cold.asm @@ -0,0 +1,70 @@ + PAGE + STTL "--- MACHINE COLDSTART: CBM64 ---" + + ORG $1200 + + ; --------- + ; COLDSTART + ; --------- + + ; BANK CONFIGURING IS LIKE THIS: + ; BIT 0 $D000 - $DFFF 1 = RAM 0 = IO + ; BIT 1 $4000 - $7FFF 1 = RAM 0 = SYSTEM ROM + ; BIT 2 & 3 $8000 - $BFFF 11 = RAM 00 = SYSTEM ROM + ; BITS 4 & 5 $C000 - $FFFF 11 = RAM 00 = SYSTEM ROM + ; BIT 6 RAM BANK 0 = BANK0 1 = BANK1 + ; BIT 7 UNUSED, WILL BE FOR BANKS 2 & 3 + +COLD1: LDA #%00001110 ; SET UP CONFIGURATIONS FOR + STA BANK0 ; PROPER USE OF MEMORY + LDA #%01111111 ; SAVING TO BE USED AS NEEDED + STA BANK1 + LDA #%00111110 + STA BANK2 ; RAM FROM $C000 - $FFFF IN BANK0 + + LDA #$0E + JSR CHROUT ; USE UPPER/LOWER CHARS + LDA #$80 ; PROHIBIT FURTHER + STA MODE ; CHARSET CHANGES + + JSR CLALL ; CLOSE EVERYTHING + JSR MEMCHK ; check for ram expansion + + JMP WARM1 + + ; --------------- + ; WARMSTART ENTRY + ; --------------- + +SLOAD: DB "The story is loading ..." + DB EOL +SLOADL EQU $-SLOAD + +WARM1: CLD + LDX #$FF + TXS ; RESET MACHINE STACK + + LDA #CLS ; CLEAR SCREEN, ETC. + JSR CHROUT + + LDA #1 ; SET FONT TO 1 SO + STA FONT ; CHARS WILL BE DISPLAYED + + LDY #28 ; POSITION "STORY LOADING" MESSAGE + LDX #11 ; AT (8,11) + CLC + JSR PLOT + + LDX #SLOAD + LDY #SLOADL + JSR DLINE ; "THE STORY IS LOADING ..." + + LDA #8 ; MAKE BOOT DRIVE + JSR DOPEN ; AND OPEN IT + + JMP WARM2 ; JMP OVER TEXT STRINGS + + END + + \ No newline at end of file diff --git a/c-128/xzip/disk.asm b/c-128/xzip/disk.asm new file mode 100644 index 0000000..4e03d91 --- /dev/null +++ b/c-128/xzip/disk.asm @@ -0,0 +1,278 @@ + PAGE + STTL "--- DISK ACCESS: CBM64 ---" + + ; -------------- + ; OPEN DRIVE [A] + ; -------------- + + ; ENTRY: DISK ID (8 OR 9 BINARY) IN [A] + +DOPEN: STA DRIVE ; SAVE DRIVE ID HERE + JSR DCLOSE ; CLOSE COMMAND & DATA CHANNELS + + LDA #15 ; LOGICAL FILE # + TAY ; SECONDARY ADDRESS + LDX DRIVE ; DEVICE # (8 OR 9) + JSR SETLFS ; SET UP LOGICAL FILE + + LDX #I0 ; "I0:" + LDA #I0L ; LENGTH OF FILENAME + JSR SETNAM + + JMP OPEN ; OPEN THE DISK (CARRY CLEAR IF OK) + + ; -------------------------- + ; OPEN DIRECT ACCESS CHANNEL + ; -------------------------- + +AOPEN: +; LDA #0 +; STA SPENA ; SHUT OFF CURSOR DMA + + JSR ACLOSE ; CLOSE FIRST + + LDA #2 ; D/A CHANNEL ID + TAY ; SECONDARY ID + LDX DRIVE + JSR SETLFS + + LDX #POUND ; "#" + LDA #POUNDL + JSR SETNAM + + JMP OPEN ; OPEN CHANNEL (CARRY CLEAR IF OK) + + ; ------------------- + ; CLOSE CURRENT DRIVE + ; ------------------- + +DCLOSE: LDA #15 ; CLOSE COMMAND CHANNEL + JSR CLOSE + + ; FALL THROUGH ... + + ; --------------------- + ; CLOSE THE D/A CHANNEL + ; --------------------- + +ACLOSE: LDA #2 ; AND THE + JMP CLOSE ; DATA CHANNEL + + ; ---------------- + ; DIVIDE [A] BY 10 + ; ---------------- + + ; EXIT: QUOTIENT IN [X], REMAINDER IN [A] + +DIV10: LDX #0 ; START WITH ZERO QUOTIENT + +D10L: CMP #10 ; IF DIVISOR < 10, + BCC D10EX ; WE'RE DONE + SBC #10 ; ELSE SUBTRACT ANOTHER 10 + INX ; UPDATE QUOTIENT + BNE D10L ; BRANCH ALWAYS + +D10EX: RTS + + ; --------------- + ; SEND Ux COMMAND + ; --------------- + + ; ENTRY: ASCII "1" OR "2" IN [A] + +COMLIN: DB "U" +DCOMM: DB "*" + DB ":2,0," +DTRAK: DB "***," +DSECT: DB "***" + DB EOL +CMLL EQU $-COMLIN + +SENDU: STA DCOMM ; INSERT COMMAND ("1" OR "2") IN STRING + + ; CONVERT [TRACK] AND [SECTOR] TO ASCII IN [COMLIN] + + LDA TRACK + LDY #2 +TCON: JSR DIV10 ; DIVIDE BY 10 + ORA #'0' ; CONVERT TO ASCII + STA DTRAK,Y ; STORE INTO STRING + TXA ; GET QUOTIENT INTO [A] + DEY ; ZERO-FILL USUSED BYTES + BPL TCON + + LDA SECTOR ; SAME FOR SECTOR ID + LDY #2 +SCON: JSR DIV10 + ORA #'0' + STA DSECT,Y + TXA + DEY + BPL SCON + + ; SEND COMMAND + + JSR CLRCHN + LDX #15 ; OUTPUT TO THE + JSR CHKOUT ; COMMAND CHANNEL + BCS UEX ; EXIT W/CARRY SET IF ERROR + + LDY #0 +SCM0: LDA COMLIN,Y ; SEND THE COMMAND LINE + JSR CHROUT ; TO THE DRIVE CHANNEL + INY ; A BYTE AT A TIME + CPY #CMLL + BCC SCM0 + CLC ; SUCCESS! +UEX: RTS + + ; ---------------------- + ; SET THE BUFFER POINTER + ; ---------------------- + +BPLINE: DB "B-P:2,0" + DB EOL +BPLL EQU $-BPLINE + +SETBP: JSR CLRCHN + LDX #15 ; OUTPUT TO + JSR CHKOUT ; COMMAND CHANNEL + BCS BEX ; CARRY SET IF ERROR + + LDY #0 +SBPL: LDA BPLINE,Y + JSR CHROUT + INY + CPY #BPLL + BCC SBPL + CLC +BEX: RTS + + ; ------------------------------ + ; READ/WRITE A BLOCK TO [IOBUFF] + ; ------------------------------ + + ; ENTRY: [TRACK] = TRACK # (1-35) + ; [SECTOR] = SECTOR # (0-15) + ; [DRIVE] = DRIVE ID (8 OR 9) + ; CARRY CLEAR TO READ, CARRY SET TO WRITE + +DISK: BCS DWRITE ; WRITE IF CARRY SET + + ; READ A DISK BLOCK + + JSR AOPEN ; OPEN THE ACCESS CHANNEL + BCS BADISK + + LDA #'1' ; SEND A "U1" COMMAND + JSR SENDU + BCS BADISK ; CARRY SET IF ERROR + + JSR SETBP ; SET THE BUFFER POINTER + BCS BADISK ; CARRY SET IF ERROR + + JSR CLRCHN + LDX #2 ; INPUT FROM + JSR CHKIN ; DATA CHANNEL + BCS BADISK + + LDY #0 +READ1: JSR CHRIN ; GET A BYTE + STA IOBUFF,Y ; MOVE TO I/O BUFFER + INY + BNE READ1 ; DO 256 BYTES + + BEQ SHUTD ; THEN EXIT + + ; WRITE A BLOCK + +DWRITE: JSR AOPEN ; OPEN THE ACCESS CHANNEL + BCS BADISK + + JSR SETBP ; SET THE BUFFER POINTER + BCS BADISK ; CARRY SET IF ERROR + + JSR CLRCHN + LDX #2 ; OUTPUT TO + JSR CHKOUT ; DATA CHANNEL + BCS BADISK ; CARRY SET IF ERROR + + LDY #0 +WRITE1: LDA IOBUFF,Y ; SEND CONTENTS OF [IOBUFF] + JSR CHROUT ; TO THE DRIVE + INY + BNE WRITE1 ; WRITE 256 BYTES + + LDA #'2' ; ISSUE A "U2" COMMAND + JSR SENDU + BCS BADISK ; CARRY SET IF ERROR + + JSR TALKTO + BCS COMPLAIN ; tell about error then +SHUTD: + JSR CLRCHN + CLC + RTS ; CARRY CLEAR FOR SUCCESS +COMPLAIN: + JSR CLRCHN + LDX #TALKBUF + LDY TALKLEN + JSR DLINE +BADISK: + JSR CLRCHN + SEC + RTS ; OR SET IF ERROR +; +; ask the disk how things are going +; +TALKTO: + LDA SAVDRI ; get save drive + LDX #15 + JSR TALK + + JSR LISTEN + CMP #'0' ; IS FIRST BYTE A ZERO? + BEQ TALKG + BCC TALKG ; waiting for 0-9! + CMP #'9'+1 + BCS TALKG ; don't know what it is saying + + JSR LISTEN + JSR LISTEN + + LDY #1 +LLOOP: + JSR LISTEN + CMP #',' + BEQ TALKEX + STA TALKBUF,Y + INY + CPY #30 + BNE LLOOP +TALKEX: + LDA #EOL + STA TALKBUF,Y + INY + STA TALKBUF,Y + STY TALKLEN + JSR UNTALK + SEC + RTS +TALKG: + JSR UNTALK + CLC + RTS + +TALKBUF: DB EOL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +TALKLEN: DB 0 + + END + + + + + \ No newline at end of file diff --git a/c-128/xzip/dispatch.asm b/c-128/xzip/dispatch.asm new file mode 100644 index 0000000..3fd5029 --- /dev/null +++ b/c-128/xzip/dispatch.asm @@ -0,0 +1,245 @@ + PAGE + STTL "--- OPCODE DISPATCH TABLES ---" + + + ; 0-OPS + +OPT0H: DB >ZRTRUE ;B0 + DB >ZRFALS ;B1 + DB >ZPRI ;B2 + DB >ZPRR ;B3 + DB >ZNOOP ;B4 + DB >OSAVE ;B5 + DB >OREST ;B6 + DB >ZSTART ;B7 + DB >ZRSTAK ;B8 + DB >ZCATCH ;B9 + DB >ZQUIT ;BA + DB >ZZCRLF ;BB + DB >ZUSL ;BC + DB >ZVER ;BD + DB >ZEXTOP ;BE + DB >ZORIG ;BF + +OPT0L: DB ZZERO ;80,90,A0 + DB >ZNEXT ;81 + DB >ZFIRST ;82 + DB >ZLOC ;83 + DB >ZPTSIZ ;84 + DB >ZINC ;85 + DB >ZDEC ;86 + DB >ZPRB ;87 + DB >ZCALL1 ;88 (EZIP) + DB >ZREMOV ;89 + DB >ZPRD ;8A + DB >ZRET ;8B + DB >ZJUMP ;8C + DB >ZPRINT ;8D + DB >ZVALUE ;8E + DB >ZICLL1 ;8F + +OPT1L: DB BADOP2 ;00 (UNDEFINED) + DB >ZEQUAL ;01 + DB >ZLESS ;02 + DB >ZGRTR ;03 + DB >ZDLESS ;04 + DB >ZIGRTR ;05 + DB >ZIN ;06 + DB >ZBTST ;07 + DB >ZBOR ;08 + DB >ZBAND ;09 + DB >ZFSETP ;0A + DB >ZFSET ;0B + DB >ZFCLR ;0C + DB >ZSET ;0D + DB >ZMOVE ;0E + DB >ZGET ;0F + DB >ZGETB ;10 + DB >ZGETP ;11 + DB >ZGETPT ;12 + DB >ZNEXTP ;13 + DB >ZADD ;14 + DB >ZSUB ;15 + DB >ZMUL ;16 + DB >ZDIV ;17 + DB >ZMOD ;18 + DB >ZCALL2 ;19 (EZIP) + DB >ZICLL2 ;1A + DB >ZCOLOR ;1B + DB >ZTHROW ;1C + DB >BADOP2 ;1D + DB >BADOP2 ;1E + DB >BADOP2 ;1F + +OPT2L: DB ZCALL ;E0 + DB >ZPUT ;E1 + DB >ZPUTB ;E2 + DB >ZPUTP ;E3 + DB >ZREAD ;E4 + DB >ZPRC ;E5 + DB >ZPRN ;E6 + DB >ZRAND ;E7 + DB >ZPUSH ;E8 + DB >ZPOP ;E9 + DB >ZSPLIT ;EA + DB >ZSCRN ;EB + + ; (EZIPS FROM HERE ON) + DB >ZXCALL ;EC + DB >ZCLR ;ED + DB >ZERASE ;EE + DB >ZCURST ;EF + DB >ZCURGT ;F0 (NOT IMPLEMENTED) + DB >ZLIGHT ;F1 + DB >ZBUFOUT ;F2 + DB >ZDIRT ;F3 + DB >ZDIRIN ;F4 (NOT IMPLEMENTED) + DB >ZSOUND ;F5 + DB >ZINPUT ;F6 + DB >ZINTBL ;F7 + DB >ZBCOM ;F8 + DB >ZICALL ;F9 + DB >ZIXCLL ;FA + DB >ZLEX ;FB + DB >ZWSTR ;FC + DB >ZCOPYT ;FD + DB >ZPRNTT ;FE + DB >ZASSND ;FF + +OPTXL: DB ZSAVE ;100 + DB >ZREST ;101 + DB >ZSHIFT ;102 + DB >ZASHFT ;103 + DB >ZFONT ;104 + DB >ZDISPL ;105 + DB >ZPICNF ;106 + DB >ZDCLR ;107 + DB >ZMARG ;108 + DB >ZISAVE ;109 + DB >ZIREST ;10A + +EXTLEN EQU $-EXTOPH + +EXTOPL: DB C128 COMMAND +XWRITE EQU $90 ; C128 -> RAM COMMAND + +XFLAGS EQU $DF00 ; THE PAGE THE FLAGS ARE ON +XFER EQU 1 ; (BYTE) WRITE TO THIS TO DO TRANSFER +XBUFF EQU 2 ; (WORD) ADDR OF TRANSFER BUFFER IN MAIN MEMORY +XRAM EQU 4 ; (WORD) ADDR OF BUFFER IN XPANSION RAM (XRAM) +XBANK EQU 6 ; (BYTE) WHICH BANK OF XPANSION RAM +XSIZ EQU 7 ; (WORD) SIZE OF TRANSFER IN BYTES +XINT EQU 9 ; (BYTE) SET FOR NO INTERRUPTS DURING TRANSFERS +XINCR EQU 10 ; (BYTE) SET FOR POINTERS TO INCREMENT + + ; -------------- + ; MEMORY CONTROL + ; -------------- + +LCRA EQU $FF01 +LCRB EQU $FF02 + +CR EQU $FF00 ; MAIN CONFIGURATION REGISTER +PCRA EQU $D501 +PCRB EQU $D502 +MCR EQU $D505 ; MODE CONFIG REG (6502/128) +RCR EQU $D506 ; RAM CONFIG REG (SHARED/WHERE) +FASTER EQU $D030 ; BIT 0 - 1 = 2 MHz speed + ; 0 = 1 MHz speed + + ; --- + ; SID + ; --- + + ; VOICE #1 REGISTERS + +FRELO1 EQU $D400 ; FREQ +FREHI1 EQU $D401 ; FREQ HIGH BIT +PWLO1 EQU $D402 ; PULSE WIDTH +PWHI1 EQU $D403 ; PULSE WIDTH HIGH NIBBLE +VCREG1 EQU $D404 ; CONTROL +ATDCY1 EQU $D405 ; ATTACK/DECAY +SUREL1 EQU $D406 ; SUSTAIN/RELEASE + + + ; VOICE #2 REGISTERS + +FRELO2 EQU $D407 ; FREQ +FREHI2 EQU $D408 ; FREQ HIGH BIT +PWLO2 EQU $D409 ; PULSE WIDTH +PWHI2 EQU $D40A ; PULSE WIDTH HIGH NIBBLE +VCREG2 EQU $D40B ; CONTROL +ATDCY2 EQU $D40C ; ATTACK/DECAY +SUREL2 EQU $D40D ; SUSTAIN/RELEASE + + ; VOICE #3 REGISTERS + +FRELO3 EQU $D40E ; FREQ +FREHI3 EQU $D40F ; FREQ HIGH BIT +PWLO3 EQU $D410 ; PULSE WIDTH +PWHI3 EQU $D411 ; PULSE WIDTH HIGH NIBBLE +VCREG3 EQU $D412 ; VOICE CONTROL +ATDCY3 EQU $D413 ; ATTACK/DECAY +SUREL3 EQU $D414 ; SUSTAIN/RELEASE + + ; MISCELLANEOUS REGISTERS + +CUTLO EQU $D415 ; FILTER CUTOFF, LOW BITS +CUTHI EQU $D416 ; FILTER CUTOFF, HIGH BYTE +RESON EQU $D417 ; RESONANCE CONTROL +SIGVOL EQU $D418 ; VOLUME/FILTER CONTROL +RAND EQU $D41B ; RANDOM NUMBER +CI2PRA EQU $DD00 ; DATA PORT A + + ; ------------------- + ; KERNAL JUMP VECTORS + ; ------------------- + +RFASTIO EQU $FF47 ; FAST DATA I/O +RCHKIN EQU $FFC6 ; OPEN CHANNEL FOR INPUT +RCHKOUT EQU $FFC9 ; OPEN CHANNEL FOR OUTPUT +RCHRIN EQU $FFCF ; INPUT CHARACTER FROM CHANNEL +RCHROUT EQU $FFD2 ; OUTPUT CHARACTER TO CHANNEL +RCINT EQU $FF81 ; INIT SCREEN EDITOR +RCLALL EQU $FFE7 ; CLOSE ALL CHANNELS & FILES +RCLOSE EQU $FFC3 ; CLOSE A FILE +RCLRCHN EQU $FFCC ; CLEAR CHANNEL +RGETIN EQU $FFE4 ; GET CHAR FROM KEYBOARD QUEUE +RIOINIT EQU $FF84 ; INIT I/O +ROPEN EQU $FFC0 ; OPEN A FILE +RPLOT EQU $FFF0 ; READ/SET CURSOR POSITION +RRAMTAS EQU $FF87 ; INIT RAM +RREADST EQU $FFB7 ; READ I/O STATUS +RSCNKEY EQU $FF9F ; SCAN KEYBOARD +RSETMSG EQU $FF90 ; SET KERNAL MESSAGES +RSETLFS EQU $FFBA ; SET FILE ATTRIBUTES +RSETNAM EQU $FFBD ; SET FILENAME +SWAPPER EQU $FF5F ; SWAP TO ALTERNATE DISPLAY DEVICE +RSETFCN EQU $FF65 ; ASSIGN STRING VALUES TO FCN KEYS + ; (AS WE WANT THEM) +RTKSA EQU $FF96 ; set secondary addr for talk +RUNTLK EQU $FFAB ; untalk to disk +RLISTEN EQU $FFB1 ; listen to disk +RTALK EQU $FFB4 ; tell disk to start talking + + END + + \ No newline at end of file diff --git a/c-128/xzip/io.asm b/c-128/xzip/io.asm new file mode 100644 index 0000000..c23deff --- /dev/null +++ b/c-128/xzip/io.asm @@ -0,0 +1,1484 @@ +; PAGE + STTL "--- GAME I/O: C128 ---" + +; -------------- +; INTERNAL ERROR +; -------------- +; ENTRY: ERROR CODE IN [A] +; EXIT: HA! + +ERRM: DB "Internal error " +ENUMB: DB "00. " +ERRML EQU $-ERRM + +ZERROR: LDY #1 ; CONVERT ERROR BYTE IN [A] +ZERR0: LDX #0 ; TO ASCII AT "ENUMB" +ZERR1: CMP #10 + BCC ZERR2 + SBC #10 + INX + BNE ZERR1 +ZERR2: ORA #'0' + STA ENUMB,Y + TXA + DEY + BPL ZERR0 + + LDA TOP + STA WTOP ; SCROLL NOT + + JSR ZCRLF ; CLEAR BUFFER + LDX #ERRM + LDY #ERRML + JSR DLINE ; PRINT ERROR MESSAGE + + ; FALL THROUGH + + +; ---- +; QUIT +; ---- + +ZQUIT: JSR ZCRLF ; FLUSH BUFFER + + LDA TOP ; AND IF ENTER HERE + STA WTOP ; SCROLL ONLY WHAT SHOULD + + LDX #ENDM + LDY #ENDML + JSR DLINE ; "END OF STORY" +FREEZE: JMP FREEZE + + +; ------- +; RESTART +; ------- + +ZSTART: JSR ZCRLF ; FLUSH BUFFER + + LDA TOP ; AND IF ENTER HERE + STA WTOP ; SCROLL ONLY WHAT SHOULD + + LDX #RSTRT + LDY #RSTRTL + JSR DLINE + + +DOWARM: JSR GETRET + LDX #0 + STX WTOP ; RESET FULL SCREEN FOR CLEAR +REX: JSR SIDE1 ; NEED SIDE 1 AGAIN + JMP WARM1 ; AND DO WARMSTART + +ENDM: DB "End of session." + DB EOL +ENDML EQU $-ENDM +RSTRT: DB "Press [RETURN] to restart." + DB EOL +RSTRTL EQU $-RSTRT + + +; -------------------------- +; RETURN TOP RAM PAGE IN [A] +; -------------------------- + +MEMTOP: LDA #$FB ; FOR NOW, ASSUME LAST "BUFFER" + RTS ; OF AUX MEMORY + + +; ------------------- +; Z-PRINT A CHARACTER +; ------------------- +; ENTRY: ASCII CHAR IN [A] +; +; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, +; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN +; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME +; (DIROUT CHANGES 6/24/85) + +COUT: STA IOCHAR ; HOLD IT A SEC + LDX TABLEF ; OUTPUT TO TABLE? + BEQ COUT4 ; NO + JMP TBLRTN ; YES, DO IT (TBL ONLY 4.7.86) +COUT4: LDX SCREENF ; OUTPUT TO SCREEN? + BNE COUT5 ; YES + LDX SCRIPTF ; OUTPUT TO PRINTER? + BNE COUT5 ; YES + RTS ; NO, SO DONE +COUT5: LDA IOCHAR ; RETRIEVE CHAR + LDX BUFFLG ; UNBUFFERED OUTPUT? + BNE UNBUFR ; YES, PLACE ON SCREEN IMMED. + CMP #EOL ; IF ASCII EOL, + BNE COUT3 + JMP ZCRLF ; DO IT +COUT3: + LDX CHRCNT ; GET LINE POINTER + STA LBUFF,X ; ADD CHAR TO BUFFER + INC CHRCNT + LDY SPLITF ; don't wrap if we are in SC 1 + BNE CEX ; okay, I won't + INC LENGTH ; ELSE UPDATE + LDY LENGTH ; GET LINE LENGTH COUNTER + CPY XSIZE ; END OF SCREEN LINE? + BNE CEX + JMP FLUSH ; YES, FLUSH THE LINE +CEX: RTS + + +; -------------------------- +; DIRECT, UNBUFFERED DISPLAY +; -------------------------- + +UNBUFR: STA IOCHAR ; HOLD IN CASE NEED TO PRINT + SEC + JSR PLOT + CPY #80 ; CHECK IF BEYOND SCREEN + BCS UNBEX ; YES, LEAVE + LDA SPLITF ; CHECK WHICH WINDOW + BEQ UNBBOT ; BOTTOM WINDOW + + CPX TOP ; CHECK IF WITHIN WINDOW + BCS UNBEX ; NO, JUST LEAVE + BCC UNBDIS ; YES, GO DISPLAY + +UNBBOT: CPX TOP + BCC UNBEX ; NOT WITHIN WINDOW, LEAVE + +UNBDIS: LDA SCREENF ; DISPLAY TO SCREEN? + BEQ UNBPRN ; NO, CHECK IF PRINTING + +UNBD: LDA IOCHAR + JSR CHAR ; DO VOODOO AND DISPLAY + +UNBPRN: LDA SPLITF ; SPLIT (NON-TEXT) SCREEN + BNE UNBEX ; DON'T PRINT + + ;SEND CHAR TO PRINTER + + LDA #1 ; SET FOR PRINT RTN + STA PRLEN + LDA IOCHAR + STA LBUFF + JSR PPRINT ; AND GO ATTEMPT IT + LDA #0 ; MAKE SURE NO LEFTOVER + STA PRLEN +UNBEX: RTS + + +; --------------- +; OUTPUT TO TABLE +; --------------- + +TBLRTN: TAX ; HOLD CHAR A SEC. + + ;PUT BYTE IN TABLE AT CURRENT OFFSET + + LDA DIRITM+LO ; ADD IN OFFSET + CLC + ADC DIRTBL+LO + STA I+LO + LDA DIRITM+HI + ADC DIRTBL+HI + STA I+HI + LDY #0 + TXA ; PICK UP ASCII CHAR + STA (I),Y ; STORE IT IN TBL @ BYTE ALIGNED @ + +;SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER + + INC DIRITM+LO ; INC OFFSET TO NEXT BYTE + BNE TBLRTS + INC DIRITM+HI +TBLRTS: RTS + + +; ------------------- +; FLUSH OUTPUT BUFFER +; ------------------- +; ENTRY: LENGTH OF BUFFER IN [X] + +FLUSH: + LDA #SPACE ; SPACE + STX OLDEND ; SAVE CURRENT END OF LINE +FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR + BEQ FL1 ; IN THE LINE + DEX + BNE FL0 ; IF NONE FOUND, + LDX XSIZE ; FLUSH ENTIRE LINE +FL1: STX OLDLEN ; SAVE OLD LINE POS HERE + STX CHRCNT ; MAKE IT THE NEW LINE LENGTH + JSR ZCRLF ; PRINT LINE UP TO LAST SPACE + +; START NEW LINE WITH REMAINDER OF OLD + + LDX OLDLEN ; GET OLD LINE POS + LDY #0 ; START NEW LINE AT BEGINNING +FL2: INX + CPX OLDEND ; CONTINUE IF + BCC FL3 ; INSIDE OR + BEQ FL3 ; AT END OF LINE + STY LENGTH ; ELSE SET NEW LINE LENGTH + STY CHRCNT + RTS +FL3: LDA LBUFF,X ; GET CHAR FROM OLD LINE + STA LBUFF,Y ; MOVE TO START OF NEW LINE + INY ; UPDATE LENGTH OF NEW LINE + BNE FL2 ; (ALWAYS) + + +; --------------- +; CARRIAGE RETURN +; --------------- + +ZZCRLF: + LDX TABLEF ; OUTPUT TO TBL? + BEQ ZCRLF ; NO + LDA #EOL ; INSTALL EOL + JMP TBLRTN ; YES, DO IT (TBL ONLY) +ZCRLF: + LDA #EOL ; INSTALL EOL + LDX CHRCNT + STA LBUFF,X ; END OF CURRENT LINE + INC CHRCNT ; UPDATE LINE LENGTH + LDA SCREENF ; CHECK IF DISPLAYING TO SCREEN + BEQ ZCRLFX ; NO, GO HANDLE IF PRINTING + LDA SPLITF ; AT SPLIT SCREEN + BNE ZCRLFX ; YES + INC LINCNT ; NEW LINE GOING OUT +ZCRLF0: LDX LINCNT ; IS IT TIME TO + CPX WBOTM ; PRINT "MORE" YET? + BCC ZCRLFX ; NO, CONTINUE + BEQ ZCRLFX ; NO, CONTINUE + LDA TOP + STA LINCNT ; RESET LINE COUNTER + + INC LINCNT ; LEAVE 1 LINE ON SCREEN + INC LINCNT ; and leave last line from previous screen + + SEC + JSR PLOT ; GET CURSOR POSITION + STY OLDX + STX OLDY + + LDX WBOTM ;#23 + LDY ZBEGIN+ZLMRG+1 ; SET LEFT MARGIN + CLC + JSR PLOT ; BOTTOM LEFT OF SCREEN + + LDA #146 ; IF GET HERE INVERSE + JSR CHROUT ; SHOULD BE OFF SO TURN OFF + + LDX #MORE + LDY #MOREL + JSR DLINE ; PRINT MORE DIRECTLY + + LDA #0 + STA NDX ; CLEAR INPUT QUEUE + +ZCR0: JSR GETIN ; GET ANY KEYPRESS + TAX + BEQ ZCR0 + + LDX WBOTM ;#23 + LDY ZBEGIN+ZLMRG+1 + CLC + JSR PLOT ; RESTORE CURSOR + + LDX #MCLR + LDY #MOREL + JSR DLINE ; RUB OUT "MORE" + + LDY OLDX + LDX OLDY + CLC + JSR PLOT ; RESTORE CURSOR + +ZCRLFX: JSR LINOUT ; DISPLAY LINE + JSR CHKFNC ; CHECK FOR [CR] FUNCTION (XZIP) + LDA #0 + STA LENGTH ; AND RESET LINE COUNT + STA CHRCNT ; new line, new chars, + RTS + +LINOUT: LDY CHRCNT ; IF BUFFER EMPTY, + BEQ LINEX ; DON'T PRINT ANYTHING + STY PRLEN ; SAVE LENGTH HERE FOR "PPRINT" + LDA SCREENF ; DISPLAY TO SCREEN? + BEQ LOUT1 ; NO, GO CHECK IF PRINT + + LDA WTOP + PHA + + LDA SPLITF + BNE LOUT2 ; NON SCROLLING SCREEN + + LDA TOP + STA WTOP + +LOUT2: LDY CHRCNT ; how many to send + LDX #0 ; where to start sending +LOUT: LDA LBUFF,X ; TO SCREEN + JSR CHAR + INX + DEY + BNE LOUT + + PLA ; RESET FOR FULL SCREEN ACCESS + STA WTOP + +LOUT1: LDA SPLITF + BNE LINEX ; NON SCROLLING SCREEN + JSR PPRINT ; PRINT [LBUFF] IF ENABLED +LINEX: + RTS ; AND RETURN + +; +; CHECK IF THERE IS A PENDING FUNCTION CALL ASSOCIATED WITH 'S +; + +CHKFNC: LDA ZBEGIN+ZCRCNT+0 ; IF NULL IGNORE + ORA ZBEGIN+ZCRCNT+1 + BEQ CHKDUN + + LDA ZBEGIN+ZCRCNT+1 ; DECR COUNTER + SEC + SBC #1 + STA ZBEGIN+ZCRCNT+1 + LDA ZBEGIN+ZCRCNT+0 + SBC #0 + STA ZBEGIN+ZCRCNT+0 + LDA ZBEGIN+ZCRCNT+1 ; IF NULL NOW, CALL FCN + ORA ZBEGIN+ZCRCNT+0 + BNE CHKDUN + + LDA ZBEGIN+ZCRFUNC+1 ; SET UP FUNCTION + STA J+LO + LDA ZBEGIN+ZCRFUNC+0 + STA J+HI + JSR INTCLL ; DO FUNCTION CALL +CHKDUN: RTS + +; ---------------------- +; UPDATE THE STATUS LINE +; ---------------------- +; NOT APPLICABLE IN EZIP. +ZUSL: RTS + + +; ------ +; VERIFY +; ------ +; VERIFY GAME CODE ON DISK + +ZVER: LDA TOP ; SET SO MSG'S DON'T SCROLL + STA WTOP ; OVER STATUS LINES + + JSR ZCRLF ; DISPLAY VERSION NUMBER, GET SIDE 1 + LDX #3 + LDA #0 +ZVR: STA K+LO,X ; CLEAR [K], [L] + 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 ZBEGIN+ZLENTH ; GET MSB + STA I+HI ; AND + LDA ZBEGIN+ZLENTH+1 ; LSB OF Z-CODE LENGTH IN BYTES + ASL A ; MULTIPLY BY + ROL I+HI ; FOUR + ROL K+LO + ASL A + STA I+LO + ROL I+HI ; TO GET # BYTES + ROL K+LO ; IN GAME + LDA #0 ; START AT BEGINNING + STA DBLOCK+LO + STA DBLOCK+HI + JMP READIN ; READ FIRST BLOCK IN + +VSUM: LDA MPCL ; NEW PAGE? + BNE VSUM2 ; NO, CONTINUE +READIN: LDA #>IOBUFF ; FAKE READ OUT SO + STA DBUFF+HI ; IT DOESN'T MOVE BUFFER + LDA #MAIN + STA DSKBNK ; SET FOR MAIN BANK + JSR GETDSK ; GO READ A PAGE + BCC VSUM2 + JMP DSKERR ; BAD DISK!!!!! + +VSUM2: LDY MPCL ; GET THIS BYTE + LDA IOBUFF,Y + INC MPCL ; SET FOR NEXT BYTE + BNE VSUM3 + INC MPCM + BNE VSUM3 + INC MPCH +VSUM3: CLC + ADC L+LO ; ADD IT TO SUM + STA L+LO ; IN [J] + BCC VSUM1 + INC L+HI +VSUM1: LDA MPCL ; END OF Z-CODE YET? + CMP I+LO ; CHECK LSB + BNE VSUM + LDA MPCM ; MIDDLE BYTE + CMP I+HI + BNE VSUM + LDA MPCH ; AND HIGH BIT + CMP K+LO + BNE VSUM + + LDA #0 ; RESET SCREEN ROLL + STA WTOP ; TO INDIVIDUAL CONTROL + + LDA ZBEGIN+ZCHKSM+1 ; GET LSB OF CHECKSUM + CMP L+LO ; DOES IT MATCH? + BNE BADVER ; NO, PREDICATE FAILS + LDA ZBEGIN+ZCHKSM ; ELSE CHECK MSB + CMP L+HI ; LOOK GOOD? + BNE BADVER ; IF MATCHED, + JMP PREDS ; GAME IS OKAY +BADVER: + JMP PREDF + + +; ------ +; BUFOUT +; ------ +; ENTER: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE +; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO + +ZBUFOUT: LDX ARG1+LO + BNE ZBUF1 ; SET TO BUFFERED OUTPUT + JSR CLRBUF ; CLEAR OUTPUT BUFFER + LDX #1 + STX BUFFLG ; SET FUTURE OUTPUT TO BE UNBUFFERED + RTS +ZBUF1: DEX + BNE ZBUFEX ; INVALID + STX BUFFLG ; SET TO BUFFERED +ZBUFEX: RTS + + + ; CLEAR OUTPUT BUFFER BEFORE DOING ANY FANCY DISPLAY + +CLRBUF: JSR LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) + LDX #0 + STX CHRCNT + RTS + + +; ------ +; DIROUT +; ------ +; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT +; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT +; MULTIPLE DEVICE USAGE IS POSSIBLE. + +ZDIRT: LDX ARG1+LO + BMI DIRRES ; NEGATIVE VALUE, DESELECTING + DEX + BEQ DIR1 ; 1 = SET OUTPUT TO SCREEN + DEX + BEQ DIR2 ; 2 = SCRIPTING + DEX + BEQ DIR3 ; 3 = TABLE + DEX + BEQ DIR4 ; 4 = RECORDING DEVICE (NOT IMPLEMENTED) +DIR4: RTS ; INVALID VALUE +DIRRES: INX + BEQ DRES1 ; -1 = RESET TO SCREEN + INX + BEQ DRES2 + INX + BEQ DRES3 + INX + BEQ DRES4 +DRES4: RTS ; INVALID VALUE, JUST LEAVE + +DIR1: INX ; 1, TURN SCREEN OUTPUT ON + STX SCREENF + RTS + +DRES1: +; JSR CLRBUF ; don't do this (eh?) + STX SCREENF ; 0, TURN SCREEN OFF + RTS + +DIR2: INX + STX SCRIPTF ; SET SCRIPT FLAG ON + LDA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO + ORA #%00000001 + STA ZBEGIN+ZSCRIP+1 + RTS ; YES, READY TO LEAVE + +DRES2: STX SCRIPTF ; TURN PRINTER OFF + LDA ZBEGIN+ZSCRIP+1 ; AND TURN OFF GAME FLAG TOO + AND #%11111110 + STA ZBEGIN+ZSCRIP+1 + RTS + +DIR3: INX + STX TABLEF ; TURN TABLE OUTPUT FLAG ON + + LDA ARG2+HI ; SET UP TBL + CLC + ADC ZCODE + LDX ARG2+LO ; TO STORE CHARS IN + STX DIRTBL+LO + STA DIRTBL+HI + LDA #2 + STA DIRITM+LO + LDA #0 + STA DIRITM+HI + RTS + +DRES3: LDA TABLEF ; IF ALREADY OFF + BEQ DROUT ; LEAVE AS IS + + STX TABLEF ; TURN TBL OUTPUT OFF + LDA DIRITM+LO ; MARK END OF CHARS IN TBL + CLC ; WITH A NULL CHAR + ADC DIRTBL+LO + STA I+LO + LDA DIRITM+HI + ADC DIRTBL+HI + STA I+HI ; ALIGNED AT EOL + LDA #0 + TAY + STA (I),Y ; PLACE 0 IN TBL + LDY #1 ; GET CHAR COUNT + LDA DIRITM+LO ; (2 LESS THAN [DIRITM]) + SEC + SBC #2 + STA (DIRTBL),Y + BCS RESET0 + DEC DIRITM+HI +RESET0: LDA DIRITM+HI + DEY + STA (DIRTBL),Y ; STORE CHAR COUNT IN TBL + LDA #0 ; CLEAR COUNT FOR NEXT TIME + STA DIRFLG ; SET OUTPUT TO SCREEN +DROUT: RTS + + +; ------ +; CURSET +; ------ +; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW +; AND AT COLUMN (ARG2) + +ZCURST: + JSR CLRBUF + + LDX ARG1+LO ; GET LINE + DEX ; ZERO ALIGN IT + LDY ARG2+LO ; GET COLUMN + DEY ; ZERO ALIGN IT + CLC + JMP PLOT ; MOVE THE CURSOR + + +; ------ +; CURGET +; ------ + +ZCURGT: LDA ARG1+LO + STA I+LO + LDA ARG1+HI + CLC + ADC ZCODE ; ABSOLUTE + STA I+HI + SEC + JSR PLOT + INX + INY ; 1 ALIGN + + TYA ; NOW SLIP CURSOR POSITION + LDY #3 ; INTO PLACE TO RETURN IT + STA (I),Y + DEY + LDA #0 + STA (I),Y + DEY + TXA + STA (I),Y + DEY + LDA #0 + STA (I),Y + RTS + + +; ----- +; DIRIN +; ----- +; NOT YET IMPLEMENTED, BUT RESERVED + +ZDIRIN: RTS + + +; ------ +; HIGHLIGHT +; ------ + +ZLIGHT: LDX ARG1+LO ; GET CHOICE OF MODE + BNE ZL1 + + LDA #0 ; turn off inversed + STA RVFLAG ; voila + + LDA #146 ; REVERSE OFF + JSR HLIGHT + LDA #130 ; UNDERLINE OFF + JMP HLIGHT +ZLOUT: RTS + +ZL1: CPX #1 ; INVERSE? + BNE ZL2 + + LDA #$12 ; INVERSE + STA RVFLAG ; mark as inversed + JMP HLIGHT + +ZL2: CPX #4 ; UNDERLINE? + BNE ZLOUT ; NO OTHER ON C128 + + LDA #$02 ; UNDERLINE + +HLIGHT: STA IOCHAR ; HOLD COMMAND CHAR + LDA TABLEF ; IF IN TBL MODE + BNE DOTBL ; PUT CHAR TO TBL + LDA SCREENF ; IF NOT PRINTING TO + BNE DOLIGHT ; SCREEN OR PRINTER, SKIP THIS + LDA SCRIPTF + BNE DOLIGHT + RTS + +DOLIGHT: + LDA IOCHAR + JSR ADDBUF ; add the unprinting char to buffer + RTS + +DOTBL: LDA IOCHAR + JMP TBLRTN + + + +; ----- +; ERASE +; ----- + +ZERASE: LDA ARG1+LO + CMP #1 + BNE ZEROUT ; INVALID + + JSR CLRBUF + SEC ; CLEAR TO END OF LINE + JSR PLOT + STX OLDX + STY OLDY + +ZERLP: INY + CPY #80 + BCS ZERDUN + LDA #SPACE + JSR CHROUT + JMP ZERLP + +ZERDUN: LDX OLDX ; RESET CURSOR + LDY OLDY + CLC + JSR PLOT + +ZEROUT: RTS + + +; ----- +; CLEAR +; ----- + +ZCLR: JSR CLRBUF + SEC ; READ CURRENT POSITION + JSR PLOT + STY OLDY + STX OLDX + + LDA ARG1+LO ; CHECK WHAT TO DO + BEQ CLR0 ; BOTTOM SCREEN + CMP #1 + BEQ CLR1 ; TOP SCREEN + CMP #$FF + BNE ZEROUT ; INVALID + + ; UNSPLIT SCREEN & CLEAR IT + + JSR NORL ; RESET TO FULL + LDA #CLS ; & CLEAR IT + JSR CHROUT + RTS + +CLR0: LDA WTOP ; KEEP + PHA + LDA TOP ; SET COUNT + STA LINCNT ; FOR "MORE" + STA WTOP ; AND PROPER WINDOW TOP + LDA #CLS ; CLEAR & HOME + JSR CHROUT + PLA + STA WTOP + LDX #0 + JMP SETOLD + +CLR1: LDA WBOTM + PHA + + LDY #0 ; TOP OF SCREEN + STY WTOP + LDX TOP + STX WBOTM ; MAKE BOTTOM OF TOP SCREEN + LDA #CLS + JSR CHROUT + + PLA ; RESET TOP & BOTTOM + STA WBOTM + + LDX #1 ; SET SO NEXT TIME INTO WINDOW TOP LEFTS +SETOLD: LDA #0 + STA OLD0Y,X + STA OLD0X,X + + CPX SPLITF ; IF IN WINDOW JUST CLEARED + BEQ CLROUT ; LEAVE CURSOR TOP LEFT + + LDX OLDX ; OTHERWISE SET CURSOR + LDY OLDY ; BACK WHERE IT WAS + CLC + JMP PLOT +CLROUT: RTS + + +; ------ +; PRINTT +; ------ + + ; PRINT A TABLE TO SCREEN, ARG1 = # OF BYTES + ; ARG2 = WIDTH, ARG3 (DEF = 1) = HEIGHT + +ZPRNTT: LDA ARG1+LO ; USE GETBYT AS TBL COULD + STA MPCL ; BE ANYWHERE + LDA ARG1+HI + STA MPCM + LDA #0 + STA MPCH + JSR VLDMPC + LDA ARG2+LO ; ONLY A BYTE AS MAX + CMP #0 + BEQ PTTDUN ; QUIT NOW IF NULL + + STA J+HI ; SCREEN WIDTH IS 80 + STA J+LO + DEC NARGS + LDA NARGS + CMP #1 + BEQ NOHIGHT ; DEFAULT HEIGHT IS 1 + LDA ARG3+LO ; & SCREEN LENGTH MAX IS 25 +NOHIGHT: STA K+LO + LDA SPLITF ; don't clear in window 0 + BEQ PTTj ; cuz we are wrapping +; +; 5/6/87 jdarnold -- flush the buffer to send out anything that is +; ready to go + JSR CLRBUF +PTTj: + SEC ; GET CURSOR POS & SAVE + JSR PLOT + STX OLDX + STY OLDY +PTTLP: JSR GETBYT ; GET A BYTE + JSR COUT ; use cout to do wrapping if necessary +; JSR UNBUFR ; AND PUT IT TO SCREEN + DEC J+LO + BNE PTTLP +PASTX: DEC K+LO ; IF DONE ALL LINES + BEQ PTTDUN ; LEAVE + INC OLDX ; TO NEXT LINE + LDY OLDY + LDX OLDX + CLC + JSR PLOT ; PLACE CURSOR ON NEXT LINE + LDA J+HI ; RESET COUNT + STA J+LO + JMP PTTLP ; GO DO NEXT LINE +PTTDUN: RTS + + + ; ------------ + ; SET NEW FONT + ; ------------ + +ZFONT: + LDA ARG1+LO ; CHECK WHICH FONT +; +; need to check CURRENT font, not font for this window +; + LDX SPLITF ; get old font + CMP FONT,X + BEQ ZFRET ; don't bother changing if the same + + JSR CHFONT ; go change it + BCS ZFBAD ; but we had problems! +ZFRET: + LDX SPLITF ; get old font + LDA FONT,X ; for returning + PHA + LDA ARG1+LO + STA FONT,X ; REMEMBER NEW FONT FOR NEXT TIME + PLA + LDX #0 + JMP PUTVAL ; RETURN PREVIOUS FONT +ZFBAD: + JMP RET0 ; TELL IT DOESN'T WORK +; +; change to the font located in [A] +; Set the carry if there are any problems +; +CHFONT: + CMP #4 + BEQ CFONT4 + CMP #3 + BEQ CFONT3 + CMP #1 + BEQ CFONT1 + JMP CFBAD ; NO OTHER OPTIONS AVAILABLE + + ; MAY BE A PROBLEM WITH SETTING SPACE CHAR TO SOMETHING ELSE + ; AS ALL SPACES MAY BECOME THAT CHAR WHEN SWITCH TO GRAPHICS + ; MODE, BUT THAT SHOULD NOT HAPPEN CAUSE CLEAR WITH UP/LOW + ; SPACE AND THAT IS WHAT IS ON SCREEN SO IF DON'T TRY TO USE + ; NORMAL CHARS (INCL CLEAR) WHILE SET UP FOR FONT3 & FONT4 + ; SHOULD BE NO PROBLEM + +CFONT1: + LDA RVFLAG ; was inverse on? + BEQ FNT1 ; nope + + LDA #$12 ; we must turn it back on + JMP FNT1a ; and change font +FNT1: + LDA #$92 ; turn inverse off +FNT1a: + JSR ADDBUF ; make inverse state correct + LDA #$0E ; SET UPPER/LOWER CHAR SET ON + JMP FOUT +CFONT3: + LDA F3FLG ; CHECK IF FONT3 HAS BEEN LOADED IN + BNE CFBAD ; NO, WAS NOT ON DISK, RET FAIL + + ; FONT 3 IS IN PLACE OF NORMAL UPPER/GRAPHICS CHAR SET + LDA #$92 ; turn off reverse video + JSR ADDBUF + LDA #$8E ; SET UPPER/GRAPHICS SET + JMP FOUT +CFONT4: + LDA F4FLG ; CHECK FOR FONT 4 + BNE CFBAD + + ; FONT 4 IS IN PLACE OF INVERSE UPPER/GRAPHICS SET + LDA #$8E ; upper/graphics set + JSR ADDBUF + LDA #$12 ; turn on inverse +FOUT: + JSR ADDBUF ; add font switch to output +CFRET: + CLC ; going just fine + RTS +CFBAD: + SEC ; sorry, but problems! + RTS +; +; 6/3/87 jdarnold -- add Non-printable chars to output buffer +; +ADDBUF: + LDX BUFFLG ; is it unbuffered? + BEQ ADB1 ; no, it is bufferin' + JMP CHAR ; send it out +ADB1: + LDX CHRCNT ; BUFFERED, PLACE + STA LBUFF,X ; DISPLAY BUFFER + INX ; INC CHRCNT + STX CHRCNT ; and save it + CPX #50 ; flush after 80 chars, please + BCC ADBR + JSR CLRBUF ; so get rid of it, please +ADBR: + RTS + + + ; --------------------- + ; FETCH A LINE OF INPUT + ; --------------------- + +; +; 5/11/87 jdarnold -- major change of this input routine; here's how it goes +; start cursor and time +; check for key +; if no key, check for cursor blink and time out +; if key, display it, and do blink and time out check +; + ; ENTRY: ABS ADDR OF READ BUFFER IN [ARG1] + ; EXIT: # CHARS READ IN [A] + +INPUT: JSR CLRBUF ; FLUSH [LBUFF] + + LDA #0 ; RESET LINE COUNT + STA BRKCHR + STA I+HI ; clear local variables + STA I+LO + STA J+HI + STA J+LO + STA NDX ; CLEAR INPUT QUEUE + + LDY #0 ; GET length stuff + LDA (RDTBL1),Y ; get maximum size of buffer + CMP #79 ; IF OVER 78, CUT DOWN TO 78 + BCC STORIT ; LEAVE IT AS IT IS, IT IS LESS + LDA #78 +STORIT: + STA CHRMAX ; and save it + + LDY #1 + LDA (RDTBL1),Y ; get current offset into buffer + TAX ; get so we can inc it + INX ; and not + INX ; count the 2 info-bytes + STX CHARCNT ; save how many chars out there + + LDY TOP + STY LINCNT ; RESET LINE COUNT + JSR STCUR ; start the cursor + + LDA NARGS ; CHECK IF TIME LIMIT (EZIP) + CMP #2 + BEQ INP0 ; NO + + LDA ARG3+LO ; GET DELAY WANTED + STA I+HI + LDA NARGS ; IS THERE A FCN? + CMP #4 + BNE INP4 ; NO + LDA ARG4+LO ; YES, SET IT + STA J+LO + LDA ARG4+HI + STA J+HI + +INP4: LDA I+HI + STA I+LO ; RESET EA TIME THRU +INP0: + LDA #250 ; = 7, TIME COUNTS UP + STA TIME +INP1: + JSR GETIN ; do we have a key? + CMP #0 ; 1 is yes + BNE INPJ1 +INP15: + JSR TOGCUR ; toggle the cursor? + LDA TIME ; how's the time? + BNE INP1 ; still time left + + JMP INP6 ; .1 sec, check for timeout + +INP6: LDA I+LO ; check for i/o timer + BEQ INP0 ; no timer, just continue waiting + + DEC I+LO + BNE INP0 ; SOME TIME LEFT, TRY AGAIN + + ; TIME OUT, CHECK IF THERE IS A FCN TO CALL + + JSR OFFCUR ; turn off cursor, if necessary + + LDA J+LO ; IS THERE A FCN + ORA J+HI + BNE INP3 + JMP ENDIN ; NO FCN, LEAVE WITH NOTHING + +INP3: JSR INTCLL ; INTERNALLY CALL THE FCN + LDA VALUE+LO ; CHECK RESULTS + BEQ INPCNT ; return == 0, so continue + JMP ENDIN ; != 0, so ABORT! + +INPCNT: + LDA LINCNT ; see if anything got printed out + CMP TOP ; if ==, then nothing new + BEQ INPCNTj ; nope + + JSR FLUSHRD ; send out input so far typed +INPCNTj: + JSR STCUR ; turn cursor back on + JMP INP4 ; and start timer over +INPJ1: + JSR GOTKEY ; OK, GO DO THE VOODOO + CMP #0 ; if == 0, not a good key + BNE INPJ2 + JMP AGAIN ; don't use the bad key +INPJ2: + JSR ISTCHR ; CHECK IF IT'S AN ACCEPTABLE TERMINATOR KEY + BCS NOTYET + + STA BRKCHR ; save for later + + JSR OFFCUR ; make sure the cursor is off + + LDA BRKCHR + CMP #EOL + BEQ ENDLIN ; PUT EOL TO SCREEN + JMP ENDIN ; ELSE JUST END +NOTYET: + TAY ; check for function keys + BMI CBAD ; beep for > 127 keys if not terminators + CMP #EOL ; EOL? + BEQ ENDLIN ; LINE DONE IF SO + CMP #BACKSP ; BACKSPACE? + BEQ BACKUP ; SPECIAL HANDLING + + LDY CHARCNT ; where do we put char? + CPY CHRMAX ; are we filled up? + BCS CBAD ; boy, am i full + CMP #$80 ; DON'T SHOW FCN KEYS + BCS NOSHOW +SHOWIT: + STA IOCHAR ; save it + JSR CHAR ; SEND TO SCREEN + LDA IOCHAR ; get it back +NOSHOW: + CMP #'A' ; IF CHAR IS UPPERCASE ALPHA, + BCC LEX ; CONVERT TO LOWER CASE + CMP #'Z'+1 + BCS LEX + ADC #$20 ; converting away +LEX: + LDY CHARCNT ; where does next char go + STA (RDTBL1),Y ; ADD CHAR TO INPUT BUFFER + INC CHARCNT ; NEXT POSITION IN LINE +AGAIN: + JSR STCUR ; start the cursor again + JMP INP15 ; go back to main loop +; +; HANDLE BACKSPACE +; +BACKUP: + STA BRKCHR ; save it + LDA CHARCNT ; if == 2, then buffer is empty + CMP #2 ; and if not, then we still have room + BEQ CBAD ; JMP to beeping + DEC CHARCNT ; get rid of it + LDA BRKCHR ; go get BS + JSR CHAR ; show + JMP AGAIN ; try another one + +CBAD: JSR BEEP ; ELSE SCREAM WITH PAIN + JMP AGAIN ; and start anew +; +; HANDLE END OF LINE +; +ENDLIN: + STA BRKCHR ; save the break char + JSR OFFCUR ; make sure the cursor is off + + LDA BRKCHR ; get break char back + LDX TOP ; SET TOP SO SCROLLS CORRECTLY + STX WTOP + JSR CHAR ; AND SEND EOL TO SCREEN + INC LINCNT ; count eol out there + LDX #0 + STX WTOP ; AND SET BACK TO EASY USE +; +; now, build lbuff so we can send it to the printer if necessary +; but only build it if it is necessary, really! +; + LDA SCRIPT ; find out if we are scripting + BEQ ENDIN ; i guess not + LDA ZBEGIN+ZSCRIP+1 ; check for printing + AND #$01 ; check bit flag + BEQ ENDIN ; no printing, continue on + + LDY CHARCNT ; start at end of buffer + LDA #EOL ; and put in there + STA (RDTBL1),Y + + LDX CHARCNT ; fill in backwards + DEX + STX LINLEN ; say how many chars for printing + DEX ; we don't need to count info-bytes here +SLOOP: + LDA (RDTBL1),Y ; get char + STA LBUFF,X ; store char + DEY ; point to next get place + DEX ; point to next lbuff place + BPL SLOOP ; go to some more +SDONE: + JSR CLEARP ; CLEAR OFF FCN KEYS BEFORE PRINTING + JSR PPRINT ; SCRIPT [LBUFF] IF ENABLED +ENDIN: + LDY CHARCNT ; how many chars in buffer + LDA #00 ; show 0 end of line + STA (RDTBL1),Y + DEY ; DON'T INCLUDE info-bytes + DEY ; in the char count + TYA + LDY #1 + STA (RDTBL1),Y ; tell caller how many good chars there +LEXBAD: RTS ; INTO [A] + +STCUR: ; turn cursor on and start count + SEC + JSR PLOT ; get where we are + STX OLDX ; save old x + STY OLDY ; and the old y + + LDA #$E4 ; TURN CURSOR ON + STA ULINE + JSR CHROUT + + LDX OLDX ; now move back to original place + LDY OLDY + CLC ; move back to + JSR PLOT ; where we were + + LDX #0 + STX BLINK+LO ; RESET THE BLINK COUNTER + STX BLINK+HI ; FOR A LONG DELAY + + RTS + +TOGCUR: ; blink cursor when necessary + INC BLINK+LO ; TIME TO BLINK YET? + BNE TOGNO ; NOT TILL LOWER is ZERO + INC BLINK+HI + LDA BLINK+HI ; and upper is 8 + CMP #8 + BNE TOGNO + + LDA #0 ; reset uppper one + STA BLINK+HI + + LDA ULINE + EOR #$C4 ; MAKE _ OR BLANK, SO "BLINKS" + STA ULINE + JSR CHROUT + + LDX OLDX + LDY OLDY + CLC + JSR PLOT + +TOGNO: + RTS ; goodbye cruel world + +OFFCUR: ; just plain turn the cursor off! + LDA #SPACE ; erase with a space + JSR CHROUT ; and then erase it + LDX OLDX + LDY OLDY + CLC + JSR PLOT ; put cursor back there +NOOFF: + RTS + +; +; send out the input chars type in so far +; +FLUSHRD: + ldy #1 ; start at 1 to skip junk in front +FRLOOP: + iny ; next char? + cpy CHARCNT ; see if we are full + beq FREND ; nope, still some more + lda (RDTBL1),Y ; get the char + jsr CHAR ; and send it out + jmp FRLOOP +FREND: + lda TOP + sta LINCNT + rts + +CHARCNT: DB 0 + + ; ------------------------ + ; IS IT A TERMINATOR CHAR? + ; ------------------------ + +ISTCHR: + PHA + LDA TCHARS+HI + ORA TCHARS+LO + BEQ ISDUN ; no tchars table + + PLA + LDX ALLFLG ; ARE ALL FCN KEYS (<127) TERMINATORS + BEQ ISCHK ; 0 = NO, GO CHECK LIST + CMP #$80 ; YES, SO CHECK IF PAST 127 + BCS ISFND ; YUP + BCC ISNOT + +ISCHK: + LDY #0 +ISLP: + CMP (TCHARS),Y ; IS CHAR WE HAVE A TCHAR? + BEQ ISFND ; YES + + PHA + LDA (TCHARS),Y ; NULL = END OF STRING + BEQ ISDUN + PLA + INY + BNE ISLP ; SHOULD ALWAYS LOOP + +ISDUN: PLA ; RETRIEVE CHAR +ISNOT: SEC + RTS ; NOT FOUND + +;**** +;**** IF FOUND DO YOU WANT IT IN BUFFER? CHECK WITH AND W/OUT, HOW CHANGES +;**** + +ISFND: + CLC + RTS + + + ; ------------------------ + ; CLEAR LBUFF FOR PRINTING + ; ------------------------ + +CLEARP: LDY #0 + LDX #0 +CLRLP: LDA LBUFF,Y + CMP #$80 + BCS CLSKIP ; DON'T PRINT FCN KEYS + CMP #00 ; (X) EOL BECOMES 00 IN XZIP + BNE CLRLP0 + LDA #$0D ; PRINTER NEEDS $0D +CLRLP0: STA LBUFF,X + INX +CLSKIP: INY + CPY LINLEN + BNE CLRLP ; CHECK ALL CHARS + STX PRLEN ; X = NEW LENGTH FOR PRINT + RTS + + +; ----- +; INPUT +; ----- + +ZINPUT: LDA ARG1+LO + CMP #1 ; KEYBOARD? + BEQ ZINP7 + JMP RET0 ; NO, INVALID + +ZINP7: LDA WTOP ; RESET LINE COUNT + STA LINCNT +; +; first, flush anything that is ready to print +; + JSR CLRBUF + + LDA #0 + STA NDX ; CLEAR INPUT QUEUE + + DEC NARGS + BNE ZINP8 + JMP ZINP3 ; NO TIME LIMIT + +ZINP8: LDA ARG2+LO ; GET DELAY WANTED + STA I+HI + LDA #0 ; SET FCN IF IS ONE + STA J+HI + STA J+LO + DEC NARGS + BEQ ZINP4 ; NO FCN + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI +ZINP4: + JSR STCUR ; turn cursor on +ZINP0: + LDA I+HI + STA I+LO ; RESET EA TIME THRU +ZINP1: + LDA #250 ; = 7, TIME COUNTS UP + STA TIME +ZINP2: + JSR GETIN ; GET A KEY + CMP #0 + BNE ZINP25 ; we must have one then + + JSR TOGCUR ; see if it is blink time + + LDA TIME ; is it .1 second yet + BNE ZINP2 ; no, loop again + JMP ZINP6 ; timeout + +ZINP25: + JSR GOTKEY + CMP #0 ; 0 means bad key + BEQ ZINP6 + + JMP ZINP5 ; [A] NOW HAS PROPER CODE +ZINP6: + DEC I+LO + BNE ZINP1 ; SOME TIME LEFT, TRY AGAIN + +; TIME OUT, CHECK IF THERE IS A FCN TO CALL + + JSR OFFCUR ; make sure the cursor is off + LDA J+LO ; FCN IN J IF THERE IS ONE + ORA J+HI + BEQ ZINPEX ; NO FCN, SEND 0 FOR FAILED + LDA J+LO ; FCN IN J IF THERE IS ONE + ORA J+HI + JSR INTCLL ; INTERNAL CALL + LDA VALUE+LO ; GET RESULTS + BNE ZINPEX ; ABORT + JSR STCUR ; put cursor back on + BEQ ZINP0 ; TRY AGAIN +ZINP3: + JSR GETKEY ; OK, GO WAIT FOR A KEY +ZINP5: + STA I+LO ; save char + JSR OFFCUR ; make sure the cursor is off, please + LDA I+LO ; go back and get the char + CMP #BACKSP ; GAME EXPECTS ASCII BS + BNE ZINP9 + LDA #$08 ; WHICH IS $08 +ZINP9: LDX #0 + JMP PUTBYT ; RETURN CHAR + +ZINPEX: JMP RET0 ; OOPS + + +INTCLL: + LDA I+HI ; SAVE VALUES FOR CALLING RTN + PHA + LDA J+HI + STA ARG1+HI ; pretend it's arg1 for zcall + PHA + LDA J+LO + STA ARG1+LO ; and here's the low part + PHA + LDX #1 + STX NARGS + DEX + STX IRET ; make sure it returns back here! + + LDA ZPCL ; now, save this zpc, and put back + PHA + STX ZPCL ; a 0 one to show return to internal + LDA ZPCM ; call + PHA + STX ZPCM + LDA ZPCH + PHA + STX ZPCH + + JSR DOCALL + + JMP MLOOP ; GO DO FCN + + ; RETURN FROM FCN WILL COME HERE + +ZIRET: + PLA ; GET RID OF RTS FROM ZRET + PLA + + PLA ; now get real ZPC + STA ZPCH + PLA + STA ZPCM + PLA + STA ZPCL + JSR VLDZPC + + PLA ; RESTORE FOR CALLING RTN + STA J+LO + PLA + STA J+HI + PLA + STA I+HI + RTS ; GO BACK TO CALLER + + + +IN: DB 00,00,00,00,00,00,00,00,00 +OUT: DB 00,00,00,00,00,00,00,00,00 + +QUOT: DB 00,00 ; RDTBL1+4 ; (WORD) QUOTIENT FOR DIVISION +REMAIN: DB 00,00 ; QUOT+2 ; (WORD) REMAINDER FOR DIVISION +MTEMP: DB 00,00 ; REMAIN+2 ; (WORD) MATH TEMPORARY REGISTER +RDFLAG: DB 00 ; TEMP FLAG FOR READ TO USE +QSIGN: DB 00 ; MTEMP+2 ; (BYTE) SIGN OF QUOTIENT +RSIGN: DB 00 ; QSIGN+1 ; (BYTE) SIGN OF REMAINDER +DIGITS: DB 00 ; RSIGN+1 ; (BYTE) DIGIT COUNT FOR "PRINTN" +BLINK: DB 00,00 ; (WORD) COUNT CYCLE BETWEEN CURSOR BLINKS +ULINE: DB 00 ; (BYTE) UNDERLINE VALUE FOR CURSOR + +IRET: DB 0 ; FLAG TELLS IF RETURNLESS CALL +OLD0Y: DB 0 ; HOLDS WHERE CURSOR WAS WHEN LEFT +OLD1Y: DB 0 ; A WINDOW SO CAN RETURN THERE +OLD0X: DB 0 ; WHEN REENTER THE WINDOW +OLD1X: DB 0 ; (MUST BE IN THIS ORDER!!) + +OLDX: DB 0 ; HOLD X & Y TEMPORARILY +OLDY: DB 0 +OLDWL: DB 0 +OLDWD: DB 0 + +TYPE: DB 0 ; PARTIAL OR NORMAL (WHOLE) SAVE/RESTORE +ASSVLU: DB 0 +BRKCHR: DB 0 ; READ BREAK CHAR +F3FLG: DB 0 ; 0 = FONT 3 IN CHAR RAM 1 = NO FONT 3 +F4FLG: DB 0 ; " " " " " +FONT: DB 1,1 ; KEEP TRACK OF CURRENT FONT FOR CHANGES +STRT: DB 0 ; HIGH BYTE OF START ADDR FOR CHAR 48 +STRT96: DB 0 ; AND FOR CHAR 64 +GCHAR: DB 0 ; FONTS +GEND: DB 0 ; FONTS +ALLFLG: DB 0 ; 1 = ALL CHARS OVER $80 ARE TERMINATORS +PSVFLG: DB 0 ; FOR READ, PRESERVE TBL CONTENTS? +VOCFLG: DB 0 ; FOR READ, WHICH VOCAB TBL TO USE +RVFLAG: DB 0 ; is the normal font inverse? (0=FALSE) + +SRHOLD: DB 0,0 ; random spot holder flag + +XEXIST: DB 0 ; is there expansion ram? +RESFLG: DB 0 ; have we already loaded it? + +ISRBANK: DB 0 ; bank for any internal save/restore stuff +ISRPAGE: DB 0 ; page " " " +ISRFLAG: DB 0 ; to show we are internally saving/restoring +ISAVED: DB 0 ; have we done internal save? + +SAVSIZ: DB 0 ; (BYTE) # OF SECTORS PER SAVE +NUMSAV: DB 0 ; (BYTE) # SAVES OF THIS GAME POSSIBLE + +MORE: DB "[MORE]" +MOREL EQU $-MORE +MCLR: DB " " + +SLOTM: DB EOL + DB "Printer Slot 1-7: " +SLOTML EQU $-SLOTM + +STRYM: DB "The story is loading ..." +STRYML EQU $-STRYM + + END + \ No newline at end of file diff --git a/c-128/xzip/machine.asm b/c-128/xzip/machine.asm new file mode 100644 index 0000000..b8638a0 --- /dev/null +++ b/c-128/xzip/machine.asm @@ -0,0 +1,729 @@ + PAGE + STTL "--- MACHINE-DEPENDENT I/O: CBM64 ---" + + ; ---------------------------- + ; FETCH ASCII KEYCODE INTO [A] + ; ---------------------------- + + ; EXIT: ASCII IN [A] & [IOCHAR] +GETKEY: + JSR STCUR ; start the cursor please +GK1: + JSR GETIN ; do we have a key? + CMP #0 ; 1 is yes + BNE GK2 + + JSR TOGCUR ; toggle the cursor? + JMP GK1 ; check again! +GK2: + STA IOCHAR ; save the char + JSR OFFCUR ; turn off cursor, if necessary + + ; CONVERT & MASK KEYCODE IN [A] + LDA IOCHAR + + JSR GOTKEY ; parse the ol key + CMP #0 ; 0 RETURN MEANS BAD KEY + BEQ GK1 ; no goodnik key, try again! + + RTS ; AND RETURN IT +; +; parse the key, returning it in (A), with 0 = bad key +; +GOTKEY: + CMP #'0' ; check for numbers + BCC GOTK1 ; nope, let it go + CMP #'9'+1 ; how about more than nine? + BCS GOTK1 ; ayyup +; +; must be a number, see if it was the numeric keypad +; + LDY SFDX ; get keyboard coordinate + CPY #$41 ; check against lowest keypad coord + BCC NCHK ; it was normal number +; +; pretend these ones are functions keys +; + CLC ; get ready for translate + ADC #97 ; keypads range from 145-154 +NCHK: + JMP GOTDNE ; no need for further checking +GOTK1: + CMP #'A' ; CONVERT UNSHIFTED ALPHA + BCC GKA ; TO ASCII LOWER CASE + CMP #'Z'+1 + BCS GKA + ADC #$20 + JMP GOTDNE +GKA: + CMP #133 ; LET FCN KEYS THRU, ALREADY CORRECT + BCC MASK + CMP #141 + BCC GOTDNE + CMP #143 + BEQ GOTDNE +; +; CHECK FOR "ARROWS", CONVERT FOR USE (EZIP) +; ALSO : CHANGE < > TO , . +; +MASK: LDX #ENDKEY ; GET LENGTH OF LIST +MASK0: CMP HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS + BEQ MASK1 ; FOUND IT + DEX + BPL MASK0 ; CHECK THEM ALL + BMI MASK3 ; NOT FOUND, CONTINUE OTHER CHECKS +MASK1: LDA WANT,X ; GET KEY TO USE INSTEAD + BNE GOTDNE ; JMP +MASK3: + AND #%01111111 ; SCREEN OUT SHIFTS + CMP #EOL ; EOL? + BEQ GOTDNE + CMP #BACKSP + BEQ GOTDNE + CMP #SPACE ; ANYTHING ELSE < "SPACE" + BCC BADKEY ; IS BAD + + LDX #BLISTL ; IGNORE OBSTINATE NON ALLOWED KEYS +BADL: CMP BADLIST,X + BEQ BADKEY + DEX + BNE BADL +GKCMP1: + CMP #'Z'+1 ; PASS U-C ALPHA + BCC GOTDNE ; AND OTHER ASCII CHARS + +BADKEY: JSR BOOP ; REJECT BAD KEYPRESS + LDA #0 ; O MEANS BAD KEYPRESS +GOTDNE: + STA IOCHAR ; save char + ADC RNUM1 ; FUTZ WITH RANDOM + STA RNUM1 + EOR RNUM2 + STA RNUM2 + LDA IOCHAR ; go get it back + + RTS + + ; ARROW AND FUNCTION KEYS FOR XZIP ARE: + ; FOUR ARROW KEYS (BOTH SETS MATCH) PLUS EXTRA UP ARROW KEY + ; FUNCTION KEYS ARE F1 - F8, F9 = ESC, F10 = TAB, F11 = HELP + ; F12 = LINE FEED + ; Also, numberic keypad 0-9 turns into 145-154 + ; +HAVE: DB '<','>',$91,$11,$9D,$1D,$5E + DB $1B,$09,$0A +WANT: DB ',','.',129,130,131,132,129 + DB 141,142,144 +ENDKEY EQU $-WANT-1 + +BADLIST: DB '%','&','=','@' +BLISTL EQU $-BADLIST-1 + + ; ------------------------- + ; OUTPUT AN ASCII CHARACTER + ; ------------------------- + +LETTER: CMP #'a' ; LOWER-CASE? + BCC LET0 ; NO, CONTINUE + CMP #'z'+1 + BCS LETEX ; CTRL CHARS + AND #%01011111 ; ELSE MASK FOR LOWER-CASE + JMP CHROUT + +LET0: CMP #'A' ; UPPER-CASE? + BCC LETEX + CMP #'Z'+1 + BCS LETEX + ORA #%00100000 ; MAKE UPPER +LETEX: + STA IOCHAR ; just in case we need it + JSR CHROUT ; goodbye, cruel char + RTS + +FONTFLAG: DB 0 ; 0 = font1/1 = not font 1, for current + ; output character + + ; ----------------- + ; PRINT CHAR IN [A] + ; ----------------- + +CHAR: STA IOCHAR ; SAVE HERE + TXA + PHA ; SAVE [X] AND [Y] + TYA + PHA + + LDA IOCHAR ; RESTORE CHAR + CMP #$0E ; change to font 1? + BNE CH1 ; nope + + LDX #0 ; set font1 flag showing font 1 + STX FONTFLAG ; 0 = font 1 + BEQ CH2 +CH1: + CMP #$8E ; font 3/4 ? + BNE CH2 ; nope + + LDX #1 + STX FONTFLAG ; 1 = not font 1 +CH2: + CMP #$22 + BNE NOQUOT + + JSR LETTER ; QUOTE MARKS SCREW + LDA #0 ; UP SYSTEM, SO + STA QUOTMOD ; TURN OFF QUOTE MODE FLAG + BEQ CHDUN + +NOQUOT: LDX FONTFLAG ; IF FONT 3 OR 4 DO DIRECT CHROUT + BNE NOLETR ; LETTER CONVERTS CHARS + + JSR LETTER ; OFF TO THE SCREEN! +CHDUN: + LDA IOCHAR ; go get char + CMP #EOL ; did we just send a ? + BNE LETJ ; nope, continue +; +; move cursor back to left margin +; + SEC + JSR PLOT ; first, get where cursor is + LDY ZBEGIN+ZLMRG+1 ; set left margin + CLC ; and then send the + JSR PLOT ; cursor back there + LDA #0 ; and then show no more chars in [LBUFF] + STA CHRCNT ; none more + LDA RVFLAG ; is rvideo on? + BEQ LETJ ; nope + LDA #$12 ; turn it back on + JSR CHROUT ; okay +LETJ: + PLA + TAY ; RESTORE [X] AND [Y] + PLA + TAX + RTS +NOLETR: + JSR CHROUT + JMP CHDUN + + +; ----------------------- +; 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 + STY MTEMP ; COUNTER + + LDA TOP ; RETAIN STATUS LINE(S) + STA WTOP + + LDX #0 ; INIT CHAR-FETCH INDEX +DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE +STRING: DW $0000 ; DUMMY OPERAND BYTES + JSR CHAR + INX + DEC MTEMP ; LOOP TILL + BNE DOUT ; OUT OF CHARS + + LDA #0 + STA WTOP + + RTS + + + ; ----------------------- + ; SEND [LBUFF] TO PRINTER + ; ----------------------- + + ; ENTRY: LENTH OF LINE IN [PRLEN] + ; NOW WITH IMPROVED ERROR PROTECTION! (BM 11/24/84) + +PPRINT: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? + BEQ PEX ; NO, SCRAM IMMEDIATELY + + LDA ZBEGIN+ZSCRIP+1 ; CHECK SCRIPT FLAG + AND #%00000001 ; SCRIPTING ON? + BEQ PP3 ; NO, CHECK FOR "UNSCRIPT" + + LDA PSTAT ; CHECK PRINTER STATUS + BMI PEX ; CAN'T OPEN IF NEGATIVE + BNE PP1 ; ALREADY OPEN, SCRIPT THE LINE + + ; OPEN THE PRINTER FOR OUTPUT + +PP0: LDX #1 + STX PSTAT ; SET STATUS TO "PRINTER OPENED" (1) + + LDA #4 ; LOGICAL FILE #4 + TAX ; DEVICE #4 + LDY #7 ; ALLOW UPPER/LOWER CASE + JSR SETLFS ; SET UP LOGICAL FILE + LDA #0 + JSR SETNAM ; NO FILENAME REQUIRED + JSR OPEN ; OPEN THE CHANNEL + BCC PP1 ; OPEN OKAY IF CARRY CLEAR +PPERR: + LDA #$FF ; ELSE SET PRINTER STATUS + STA PSTAT ; TO "CAN'T OPEN" + BNE PP5 ; AND SIMULATE AN "UNSCRIPT" +PP1: + LDX #4 ; SET PRINTER CHANNEL + JSR CHKOUT ; TO "OUTPUT" + BCS PPERR ; ERROR IF CARRY SET + + LDY #0 ; INIT INDEX +PP2: LDA LBUFF,Y + CMP #$0D + BEQ PP6 + AND #%01111111 + CMP #$20 + BCC PP4 ; NO CONTROLS +PP6: JSR LETTER + BCS PPERR ; ERROR IF CARRY SET +PP4: INY + DEC PRLEN + BNE PP2 + BEQ PEX ; RESET & RETURN + + ; CHECK FOR "UNSCRIPT" + +PP3: LDA PSTAT ; CHECK PRINTER STATUS + BEQ PEX ; EXIT IF PRINTER WAS OFF + BMI PEX ; OR UNOPENABLE + +PCLOSE: LDA #0 ; RESET PRINTER STATUS FLAG + STA PSTAT ; TO "CLOSED" + + ; ENTRY FOR PRINTER ERROR + +PP5: LDA #4 + JSR CLOSE ; CLOSE THE PRINTER CHANNEL +PEX: JMP CLRCHN + +PSTAT: DB 0 ; HERE SO RESTART WON'T ALTER + + + ; ------------ + ; SPLIT SCREEN + ; ------------ + + ; SPLIT SCREEN AT LINE [ARG1] + ; DISABLE SPLIT IF [ARG1] = 0 + ; IGNORE IF SPLIT ALREADY ENABLED OR [ARG1] >= 23 + + ; ON C-128, I AM USING KERNAL RTNS TO ACCESS SCREEN MEMORY + ; AS SCREEN MEMORY IS IN ITS OWN WORLD. IN ORDER NOT TO + ; SCROLL THE TOP WINDOW WHEN SCREEN IS SPLIT, THE C-128 + ; TOP OF SCREEN INDICATOR MUST BE USED, BUT: NO ACCESS IS + ; ALLOWED ABOVE THAT INDICATOR. THAT INDICATOR (WTOP) WILL + ; THEREFORE BE SET ONLY WHEN SCROLLING MIGHT OCCUR, LEAVING + ; [WTOP] SET TO #0 OTHERWISE. THE SPLIT LINE IS KEPT TRACK + ; OF IN [TOP]. + +ZSPLIT: LDA TOP ; HOLD A SEC + STA I + LDA ARG1+LO ; GET # OF LINES FOR SCREEN + BEQ NORL ; IF 0 THEN RESTORE SCREEN + CMP #24 ; IS SPLIT REALLY = WHOLE SCREEN + BCS ZSPOUT ; YES, IGNORE + + CMP TOP ; IF SCREEN 1 SHRINKING + BCS ZSLVIT ; SET LINCNT - (TOP - [A]) + PHA ; HOLD IT + SEC + SBC TOP + ADC LINCNT + STA LINCNT + PLA + +ZSLVIT: STA TOP ; SET THE TOP OF THE SECOND SCREEN + STA SPSTAT ; NON ZERO = SCREEN IS SPLIT + CMP LINCNT ; IS SCROLLING SCREEN NOW MORE THAN LINCNT? + BCC ZSPL3 ; NO + STA LINCNT ; YES, RESET LINCNT +ZSPL3: LDA #0 ; ALIGN TOP CURSOR FOR NEW SPLIT + STA OLD1Y + STA OLD1X + + SEC + JSR PLOT ; FIND WHERE WE ARE NOW + CPX I + BCC ZSPL5 ; TOP SCREEN, GO TO 0,0 + CPX TOP ; STAYING W/IN BOTTOM SCREEN + BCS ZSPOUT ; YUP + + LDX TOP ; WERE IN TOP, NOW IN BOTTOM SCREEN + LDY ZBEGIN+ZLMRG+1 ; SO GO TO TOP LEFT OF IT + CLC + JMP PLOT + +ZSPL5: LDX #0 + LDY #0 + CLC + JMP PLOT + +NORL: ;RESTORE SCREEN TO FULL SCREEN MODE + + LDA #0 ; PUT CURSOR AT TOP OF SCREEN + STA WTOP ; RESTORE FULL SCREEN ALIGNMENT + STA TOP ; JIC + STA LINCNT + STA SPSTAT ; FLAG NOT SPLIT +ZSPOUT: RTS + + +; ------ +; SCREEN +; ------ +; GO TO TOP WINDOW (TOP OF SCREEN) IF [ARG1] = 1 +; GO TO BOTTOM OF SCREEN IF [ARG1] = 0 +; IGNORE IF SPLIT NOT ENABLED OR [ARG1] <> 0 OR 1 +; FLAG SPLITF WILL BE SET FOR OUTPUT TO DETERMINE +; IF AND WHICH WINDOW TO DISPLAY TO +; (0=BOTTOM 1=TOP) + +ZSCRN: + LDA SPSTAT ; CHECK IF SCREEN IS SPLIT + BEQ ZSPOUT ; NO, SO JUST LEAVE + JSR CLRBUF ; EMPTY OUTPUT BUFFER BEFORE MOVING + SEC ; GET CURSOR LOC + JSR PLOT + TXA + LDX SPLITF ; SAVE CURSOR OF SCREEN NOW IN +SCRSAV: STA OLD0X,X + TYA + STA OLD0Y,X + + LDA ARG1+LO ; CHECK WHICH WINDOW + BNE SCRN1 ; TOP SCREEN + +SCRN0: LDA #$FF ; SCROLLING SCREEN SO + STA SCRIPT ; ALLOW SCRIPTING + LDA OLDWD ; RESET MARGINS + STA XSIZE + LDA #0 + STA SPLITF ; SET FLAG TO BOTTOM SCREEN (0) + JMP SCRNP ; JMP TO RTN + +SCRN1: CMP #01 + BNE ZSPOUT ; INVALID SCREEN ID + STA SPLITF ; SET FLAG TO UNSCROLLING SCREEN (1) + LDA XSIZE ; SAVE MARGINS + STA OLDWD + + LDA #0 + STA SCRIPT ; SET SCRIPTNG OFF, NOT ALLOWED THIS SCREEN + LDA #79 + STA XSIZE ; SET FOR TOP SCREEN USING WHOLE WIDTH +SCRNP: + LDX SPLITF ; WHICH SCREEN + LDA FONT,X ; get screens font + CMP #1 ; to font 1? + BNE SCF1 ; nope + LDX FONTFLAG ; 1 means we weren't in font 1 before + BEQ SCF2 ; here we don't need to change it + BNE SCF3 ; so we need to change it +SCF1: + LDX FONTFLAG ; 0 means we are already in font 1 + BNE SCF2 ; so don't change a thing +SCF3: + JSR CHFONT ; and change to it +SCF2: + LDX SPLITF ; WHICH SCREEN + LDA OLD0Y,X ; SET CURSOR TO WHERE IT WAS IN THAT WINDOW + TAY + LDA OLD0X,X + TAX + CLC + JMP PLOT ; SET CURSOR (+ LEAVE) + + + ; ------ + ; MARGIN + ; ------ + +ZMARG: JSR CLRBUF ; CLEAR LBUFF BEFORE RESETTING LINE MARGINS + LDA ARG2+LO ; SET RIGHT MARGIN + STA ZBEGIN+ZRMRG+1 + LDA ARG1+LO + STA ZBEGIN+ZLMRG+1 + LDA #79 ; FULL WIDTH + SEC + SBC ARG2+LO ; SUBTRACT BOTH MARGINS + SBC ARG1+LO ; TO GET NEW WIDTH + STA XSIZE + STA OLDWD ; JIC + + SEC + JSR PLOT + LDY ARG1+LO ; SET CURSOR AT NEW LEFT MARGIN + CLC + JMP PLOT + + + ; ----- + ; SOUND + ; ----- + ; ARG1 = BOOP (2) BEEP (1) ALL OTHERS INVALID + ; (EZIP) + +ZSOUND: LDX ARG1+LO ; GET SOUND WANTED + DEX + BNE ZSO1 + JMP BEEP +ZSO1: DEX + BNE ZSOEX ; INVALID + JMP BOOP ; DOWN IN COMMON MEMORY + +ZSOEX: RTS + + + ; ----- + ; COLOR + ; ----- + ; ARG1 IS FOREGROUND, ARG2 BACKGROUND + ; TRANSLATES GAME COLOR CODE TO MACHINE CODE + ; ONLY AVAILABLE IF USER ASKED FOR COLOR + ; (MONOCHROME MONITOR POSSIBLE) + +ZCOLOR: ; SET BACKGROUND COLOR IN REGISTER 26 BITS 3-0 OF 80 COL CHIP + LDA ZBEGIN+ZMODE + AND #$01 + BEQ ZCNO ; WE'RE NOT ON + + JSR CLRBUF ; MAKE SURE ANYTHING WAITING IS DISPLAYED + + LDX ARG2+LO ; GO SET BACKGROUND COLOR + BEQ ZFORE ; BACK SET TO NO CHANGE, CHECK FORE + LDA BAKCOL,X + JSR COLOR ; RTN IN SHARED MEMORY +ZFORE: LDX ARG1+LO ; AND FOREGROUND COLOR + BEQ ZCNO ; NO CHANGE + LDA FORCOL,X + JSR ADDBUF ; add unprinting char to buffer +ZCNO: RTS + +FORCOL: DB 00,$9F,$90,$1C,$1E,$9E,$1F,$81,$97,$05 +BAKCOL: DB 0,0,0,8,4,$0D,2,$0A,6,$0F + + +ZDISPL: +ZDCLR: RTS +ZPICNF: JMP PREDF ; SET AS BAD + + +;********SET A FLAG SO RESTARTS DON'T DO THIS +;******** + ; ALLOWS FOR 2 FONTS, 3 & 4, THAT ARE LOCATED AT TRACK 32, SECTOR 0 + ; AND TRACK 33, SECTOR 0 AND HAVE A MAX LENGTH OF 4 SECTORS (1K) + ; AFTER READING IN THE 4 SECTORS A CHECK IS MADE TO SEE IF THERE + ; IS A FONT FILE THERE, IF NOT A FLAG IS SET SO THAT THE FONT OPCODE + ; RETURNS A FAIL IF THE GAME TRIES TO USE THAT FONT + ; A CHECK IS ALSO MADE TO MAKE SURE THAT CHARACTERS WITH A VALUE LESS + ; THAN 32 ARE NOT USED AND THAT ALL CHARS ARE 8*8 IN SIZE. (GOFF + ; LESS THAN 32, OR GSIZE IS NOT 8*8) THE ZIP + ; WILL HALT WITH ERROR CODE 17 IF EITHER OF THESE OCCUR. OTHERWISE + ; THE CHAR DEFINITIONS ARE LOADED INTO THE 80 COL CHIP CHARACTER + ; DEFINITION RAM. THE SETUP THERE IS 8 BYTES OF CHAR DEFINITION + ; FOLLOWED BY 8 BYTES OF NULLS. ALSO CHARS ARE LOADED IN AS SUCH: + ; CHAR ASCII VALUE ADDRESS IN CHAR DEF RAM + ; @ - <- $40 - $5F $3000 - $31FF + ; SPACE - ? $20 - $3F $3200 - $33FF + ; A - Z $61 - $7A $3410 - $35xx + ; THIS IS FOR UPPER/LOWER CHARS, INVERSE STARTS AT $3800 + ; AND UPPER/GRAPHICS DEFS ARE AT $2000, THIS SECTION AT $2000 IS + ; WHAT IS BEING USED FOR THE 2 ALTERNATE CHAR SETS. + ; @ = 3C 66 6E 6E 60 62 3C 00 00 00 00 00 00 00 00 00 + +LDFNTS: + LDA RESFLG ; is this a restart? + BEQ LDFj ; nope, so check it out + + JMP DONE ; okay, so done it +LDFj: + LDA #FONT3T ; FONT 1 TRACK + STA TRACK + LDA #FONT3S ; AND ITS FIRST SECTOR + STA SECTOR + + LDA #$20 + STA STRT + LDA #$24 + STA STRT96 + JSR MOVFNT + BCC FONT4 + LDA #1 ; SET SO WON'T USE FONT 3 + STA F3FLG + + ; FALL THRU TO DO FONT4 ALSO + +FONT4: LDA #FONT4T ; FONT 1 TRACK + STA TRACK + LDA #FONT4S ; AND ITS FIRST SECTOR + STA SECTOR + LDA #$28 + STA STRT + LDA #$2C + STA STRT96 + JSR MOVFNT + BCC F4EX + LDA #1 ; SET SO WON'T USE FONT 3 + STA F4FLG ; FLAG STARTS = 0 + +F4EX: LDX #>ZBEGIN ; RESET POINTERS TO LOAD + INX ; IN REST OF GAME NOW + STX DBUFF+HI ; STARTING WITH 2ND PAGE + LDX #00 ; (1ST ALREADY IN) + STX DBLOCK+HI + INX + STX DBLOCK+LO + LDA #MAIN + STA DSKBNK ; JIC + RTS + + + ; READ FONT FILE IN AT ZBEGIN + 1 + ; AND MOVE ITS CONTENTS INTO 80 COL CHAR DEFINITION RAM + +MOVFNT: LDX #>ZBEGIN ; READ FONT FILE IN AT PAGE AFTER ZBEGIN + INX ; AS 1ST PAGE OF GAME ALREADY IN + STX DBUFF+HI + STX I+HI ; SET FOR COPY + LDX #0 ; PAGE ALIGNED! + STX I+LO + LDA #MAIN + STA DSKBNK + LDA #4 ; 4 PAGES LONG + STA L +F1LP: JSR GETRES + BCC F1OK + JMP DSKERR ; BAD READ +F1OK: DEC L + BNE F1LP + + LDY #5 +ISFILE: LDA (I),Y ; CHECK IF THERE IS A FONT FILE + BNE CHKFLE ; IF <> 0, then must be something there + DEY + BPL ISFILE + SEC ; NO FONT FILE PRESENT + RTS ; SET SO THAT DON'T TRY TO USE THAT FONT + +CHKFLE: LDY #GOFF + LDA (I),Y ; CHECK HIGH BYTE SB. 0 + BNE BADGR + INY + LDA (I),Y + CMP #32 + BCC BADGR + STA GCHAR ; SET STARTING CHAR + LDY #GSIZE + LDA (I),Y + CMP #8 + BNE BADGR ; CHAR SIZE MUST BE 8*8 + INY + LDA (I),Y ; OR I DON'T KNOW THE ALIGNMENT TO USE + CMP #8 + BEQ GOODGR + + ; *** ERROR #17: ALTERNATE CHAR SET FILE NOT USABLE *** + +BADGR: LDA #17 + JMP ZERROR + + + ; OK, THIS ALTERNATE CHARACTER SET CAN BE USED ON THE C128 + ; SO LOAD IT INTO THE 80-COL CHIP CHAR DEFINITION RAM + +GOODGR: LDY #GCOUNT ; CHAR MAX IS 96, SKIP ANY MORE THAN THIS + LDA (I),Y + BNE SETMAX + INY + LDA (I),Y + CMP #97 + BCC GOK +SETMAX: LDA #96 +GOK: CLC + ADC GCHAR + STA GEND ; SET JUST BEYOND LAST CHAR TO DO + + LDA #CSTART ; SET I TO WHERE CHAR DEFS START + STA I+LO ; (JUST SET CAUSE PAGE STARTED AT 0) + + LDA GCHAR + LDX #0 + STX J+HI + LDY #4 +GLP: ASL A ; MULTIPLY START CHAR BY 16 TO GET OFFSET + ROL J+HI ; INTO 80-COL CHAR RAM + DEY + BNE GLP + STA J+LO + LDA STRT ; ADD IN START OF CHAR RAM + CLC + ADC J+HI + STA J+HI + + LDA GCHAR ; IF STARTING IN 64 - 95 RANGE + CMP #$40 ; MUST BRING IT DOWN TO WHERE + BCC BIGLP ; IT BELONGS AT $2000 + CMP #$60 ; (MULTIPLIES IN AT $2300 RANGE) + BCS BIGLP + LDA J+HI + SEC + SBC #3 + STA J+HI + +BIGLP: LDA #8 + STA K +SMLOOP: LDY #0 ;GET ADDR & VALUE + LDA (I),Y + LDX J+HI + LDY J+LO + JSR WRTCHR ; AND WRITE IT OUT + + INC J+LO + BNE INCI + INC J+HI +INCI: INC I+LO + BNE CHKCNT + INC I+HI +CHKCNT: DEC K + BNE SMLOOP + LDA #8 ; SKIP 8 NULL BYTES OF CHAR DEFINITION + CLC ; IN 80 COL CHAR DEF RAM + ADC J+LO + STA J+LO + BCC NXTCHR ; ON TO NEXT CHAR + INC J+HI + +NXTCHR: INC GCHAR ; NEXT CHAR TO DO + LDA GCHAR + CMP GEND ; DONE THEM ALL? + BCS DONE ; NOPE + + CMP #$40 ; 64 AND 96 ARE BORDER CHARACTERS + BNE CHK60 + LDA STRT ; 64 - 95 LOAD IN AT $2000 + STA J+HI + LDA #0 + STA J+LO + BEQ BIGLP ; JMP +CHK60: CMP #$60 ; 96 - 127 LOAD IN AT $2400 + BNE BIGLP + LDA STRT96 + STA J+HI + LDA #0 + STA J+LO + BEQ BIGLP ; JMP + +DONE: CLC ; TELL CALLING RTN THE FONT IS LOADED + RTS + + END + + \ No newline at end of file diff --git a/c-128/xzip/main.asm b/c-128/xzip/main.asm new file mode 100644 index 0000000..accad08 --- /dev/null +++ b/c-128/xzip/main.asm @@ -0,0 +1,308 @@ + PAGE + STTL "--- MAIN LOOP ---" + +MLOOP: LDA #0 + STA NARGS ; RESET # ARGUMENTS + + JSR NEXTPC + STA OPCODE ; SAVE IT HERE + + IF 0 + JSR DBG1 +; LDA #'*' +; JSR DBG2 + LDA OPCODE + TAY + ENDIF + + IF 0 + LDA #0 ; BREAKPOINT #0 + JSR DOBUG + LDA OPCODE + TAY + ENDIF + + + ; DECODE AN OPCODE + + 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: CMP #236 ; XCALL? + BNE OPX5 + JMP OPXCLL ; YES, PROCESS SEPARATELY +OPX5: CMP #250 ; IXCALL + BNE OPX6 + JMP OPXCLL +OPX6: 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 + CMP #$C0 ; IS IT NEW OPCODE RANGE? + BCC ZEXTOP ; YES + JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP + +DOXOP: AND #%00011111 ; ISOLATE ID BITS + TAY + LDA OPTXL,Y + STA GOX+1+LO + LDA OPTXH,Y + STA GOX+1+HI +GOX: JSR $FFFF ;DUMMY + JMP MLOOP + + ; HANDLE EXTENDED OPCODE RANGE OPS + +ZEXTOP: CMP #EXTLEN ; OUT OF RANGE? + BCS BADEXT + TAY ; OFFSET ALREADY CORRECT + LDA EXTOPL,Y + STA GOE+1+LO + LDA EXTOPH,Y + STA GOE+1+HI +GOE: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #1 -- ILLEGAL X-OP *** + +BADOPX: LDA #1 + JMP ZERROR + + ; *** ERROR #16 -- ILLEGAL EXTENDED RANGE X-OP *** + +BADEXT: LDA #16 + JMP ZERROR + + ; HANDLE AN XCALL OPCODE + +OPXCLL: JSR NEXTPC ; GET 2 MODE BYTES + STA ABYTE + JSR NEXTPC + STA BBYTE + LDA ABYTE ; ONE TO START WITH + LDX #0 + STX ADEX ; INIT ARGUMENT INDEX + BEQ XCALL2 ; ALWAYS JUMP TO TOP OF LOOP +XCALL1: LDA ABYTE ; GET ARG BYTE + ASL A ; SHIFT NEXT 2 BITS + ASL A ; INTO BITS 7 & 6 + STA ABYTE ; HOLD FOR LATER +XCALL2: AND #%11000000 ; MASK OUT GARBAGE + BNE XCALL3 + JSR GETLNG ; 00 = LONG IMMEDIATE + JMP XCNXT +XCALL3: CMP #%01000000 ; SHORT IMMED? + BNE XCALL4 ; NO, TRY ANOTHER + JSR GETSHT ; 01 = SHORT IMMED. + JMP XCNXT +XCALL4: CMP #%10000000 ; LAST TEST + BNE OPX4 ; 11 = NO MORE ARGS + JSR GETVAR ; 10 = VARIABLE +XCNXT: LDX ADEX + LDA VALUE+LO + STA ARG1+LO,X + LDA VALUE+HI + STA ARG1+HI,X + INC NARGS + INX + INX + STX ADEX + CPX #16 + BNE XCALL5 + JMP OPX4 ; DONE, GO DO IT +XCALL5: CPX #8 ; DONE 1ST MODE BYTE? + BNE XCALL1 ; NOT QUITE YET + LDA BBYTE ; SET UP FOR NEXT + STA ABYTE ; MODE BYTE + JMP XCALL2 ; GO DO IT + + + +; ------------- +; HANDLE A 0-OP +; ------------- + +OP0: CMP #190 ; IS IT EXTOP OP + BEQ EXTOP ; YES + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT0L,Y + STA GO0+1+LO + LDA OPT0H,Y + STA GO0+1+HI +GO0: JSR $FFFF ;DUMMY + JMP MLOOP + + ; *** ERROR #2 -- ILLEGAL 0-OP *** + +BADOP0: LDA #2 + JMP ZERROR + + ; THIS OPCODE TELLS THAT NEXT OP IS PART OF THE + ; EXTENDED RANGE OF OPCODES, GET IT AND PROCESS IT + ; (THEY ARE ALL XOPS) + +EXTOP: JSR NEXTPC ; GO GET EXTENDED RANGE OP + STA OPCODE ; SAVE IT + + IF 0 + JSR DBG1 + LDA #'!' + JSR DBG2 + LDA OPCODE + TAY + ENDIF + + JMP OPEXT ; AND HANDLE IT + + +; ------------- +; HANDLE A 1-OP +; ------------- + +OP1: AND #%00110000 ; ISOLATE ARGUMENT BITS + BNE OP1A + + ;JSR GETLNG ; 00 = LONG IMMEDIATE + + JSR NEXTPC + JMP OP1A1 +OP1A: AND #%00100000 ; TEST AGAIN + BNE OP1B + + ;JSR GETSHT ; 01 = SHORT IMMEDIATE + +OP1A1: STA ARG1+HI + JSR NEXTPC + STA ARG1+LO + INC NARGS + JMP OP1EX1 +OP1B: JSR GETVAR ; 10 = VARIABLE +OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS] +OP1EX1: LDA OPCODE + AND #%00001111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT1L,Y + STA GO1+1+LO + LDA OPT1H,Y + STA GO1+1+HI +GO1: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 + + STA ARG1+HI + JSR NEXTPC + STA ARG1+LO + INC NARGS + JMP OP2B1 +OP2A: JSR GETVAR ; 1 = VARIABLE +OP2B: JSR V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS] +OP2B1: LDA OPCODE ; RESTORE OPCODE BYTE + AND #%00100000 ; ISOLATE 2ND ARG BIT + BNE OP2C + + ;JSR GETSHT ; 0 = SHORT IMMEDIATE + + STA ARG2+HI + + JSR NEXTPC + STA ARG2+LO + JMP OP2D1 +OP2C: JSR GETVAR ; 1 = VARIABLE +OP2D: LDA VALUE+LO ; MOVE 2ND [VALUE] + STA ARG2+LO ; INTO [ARG2] + LDA VALUE+HI + STA ARG2+HI +OP2D1: INC NARGS ; UPDATE ARGUMENT COUNT + + ; EXECUTE A 2-OP OR EXTENDED 2-OP + +OP2EX: LDA OPCODE + AND #%00011111 ; ISOLATE 0-OP ID BITS + TAY + LDA OPT2L,Y + STA GO2+1+LO + LDA OPT2H,Y + STA GO2+1+HI +GO2: JSR $FFFF ;DUMMY + JMP MLOOP + +; *** 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 + \ No newline at end of file diff --git a/c-128/xzip/memory.asm b/c-128/xzip/memory.asm new file mode 100644 index 0000000..bb41291 --- /dev/null +++ b/c-128/xzip/memory.asm @@ -0,0 +1,344 @@ + PAGE + STTL "--- COMMODORE 128 MEMORY ACCESS RTNS ---" + + + ORG SHARED + + ; THIS CODE MUST BE ACCESSIBLE FROM BOTH BANK0 AND BANK1 + ; THEREFORE IT WILL BE IN THE "SHARED" SECTION OF MEMORY + + ; ------ + ; GETBYT + ; ------ + +GETBYT: LDX MPCBNK ;SELECT CURRENT BANK + LDA BANK2,X ;ENABLE READ + STA CR + LDY MPCL + LDA (MPCPNT),Y ;GET THE BYTE + LDX BANK1 ;KILL (FOR SAFTY) + STX CR + INC MPCL ;POINT TO NEXT BYTE + BNE GETGOT ;IF NO CROSS WE ARE STILL VALID + JSR CRSMPC +GETGOT: TAY ;SET FLAGS + RTS ;RED SLIPPER TIME + + + ; ------ + ; NEXTPC + ; ------ + + ; LIKE GETBYT + +NEXTPC: LDX ZPCBNK + LDA BANK2,X + STA CR + LDY ZPCL + LDA (ZPCPNT),Y + LDX BANK1 ;KILL + STX CR + INC ZPCL + BNE NXTGOT + JSR CRSZPC +NXTGOT: TAY + RTS + + + ; ----------- + ; READ SECTOR + ; ----------- + + ; NOW HAVE TRACK & SECTOR, READ THE DISK + +GETRES: CLC ; CARRY CLEAR = "READ BLOCK" + JSR DISK ; GO DO IT! + +GOT: LDX DSKBNK ; SET TO PROPER BANK + LDA BANK2,X + STA CR + + LDY #0 ; MOVE CONTENTS OF [IOBUFF] +GDKL: LDA IOBUFF,Y ; TO THE + STA (DBUFF),Y ; TARGET PAGE IN [DBUFF] + INY + BNE GDKL + + LDA BANK1 ; RESET TO MAIN BANK + STA CR + + INC DBUFF+HI ; POINT TO NEXT PAGE + LDA DBUFF+HI + CMP #MAINEND+1 ; PAST LAST MAIN RAM PAGE ? + BCC GDEX ; NO + LDA #AUXSTART ; RESET DBUFF TO FIRST AUX PAGE + STA DBUFF+HI + LDA #AUX ; SET DSKBNK TO AUX + STA DSKBNK +GDEX: JMP NXTDBL ; POINT TO NEXT DBLOCK, SECTOR & TRACK + + + ; ------------- + ; KERNAL ACCESS + ; ------------- + + ; THESE RTNS WILL SWITCH TO BANK0 WHERE THE KERNAL + ; CAN BE ACCESSED, CALL THE WANTED RTN AND THEN + ; SWITCH BACK TO BANK1 TO RESUME WITH EZIP + +CHKIN: JSR KSETUP ; SET TO BANK 0 + JSR RCHKIN ; AND CALL KERNAL RTN + JMP MEMOUT ; THEN SET BACK TO MAIN BANK + +CHKOUT: JSR KSETUP + JSR RCHKOUT + JMP MEMOUT + +CHRIN: JSR KSETUP + JSR RCHRIN + JMP MEMOUT + +CHROUT: JSR KSETUP + JSR RCHROUT + JMP MEMOUT + +CLALL: JSR KSETUP + JSR RCLALL + JMP MEMOUT + +CLOSE: JSR KSETUP + JSR RCLOSE + JMP MEMOUT + +CLRCHN: JSR KSETUP + JSR RCLRCHN + JMP MEMOUT + +GETIN: JSR KSETUP + JSR RGETIN + JMP MEMOUT + +OPEN: JSR KSETUP + JSR ROPEN + JMP MEMOUT + +PLOT: JSR KSETUP + JSR RPLOT + JMP MEMOUT + +SETLFS: JSR KSETUP + JSR RSETLFS + JMP MEMOUT + +SETNAM: JSR KSETUP + JSR RSETNAM + JMP MEMOUT + +SETFCN: JSR KSETUP + JSR RSETFCN + JMP MEMOUT + +LISTEN: JSR KSETUP + JSR RLISTEN + JMP MEMOUT + +; +; open talk channel to disk +; [a] = device number +; [x] = seconday number +TALK: JSR KSETUP + TXA + PHA + JSR RTALK + PLA + JSR RTKSA + JMP MEMOUT + +UNTALK: JSR KSETUP + JSR RUNTLK + JMP MEMOUT + +KSETUP: PHA ; SAVE [A] IN CASE IS NEEDED + LDA BANK0 ; SET TO BANK0 WHERE CAN ACCESS KERNAL + STA CR + PLA + RTS + +MEMOUT: PHA + LDA BANK1 + STA CR + PLA + RTS + +;; +;; this is the 'get at expansion memory' code, cuz it has to be +;; slow, and must get at the i/o space too +;; +;; [X] - expansion ram bank +;; [Y] - expansion ram page +;; [A] - XREAD or XWRITE +;; +;; Data is in IOBUFF +;; +EXIO: + JSR KSETUP ; get i/o rom here + + STX XFLAGS+XBANK ; BANK CURRENTLY WRITING TO + + LDX #0 + STX FASTER ; make it go slow + STX XFLAGS+XRAM+LO + STX XFLAGS+XINT ; NO INTERRUPTS + STX XFLAGS+XINCR ; INCREMENT ADDR POINTERS + STX XFLAGS+XSIZ+LO ; AMOUNT TO WRITE IS 1 PG + + INX ; now make a 1 + STX XFLAGS+XSIZ+HI + + LDX #>IOBUFF + STX XFLAGS+XBUFF+HI + LDX # and LOW < + 3) SBTTL should become STTL except that the error created has no + impact on the code results and if you get an error the SBTTL + errors provide an excellent way of finding which source file the + errors are in because the 2500AD does not provide that info like + the Avocet does. +Also after using the crossassembler the linker must be used and if you have +any gaps in your code you must use SPL.EXE to remove the $FF's the linker +forces in to fill in the space to create a continuous file. + \ No newline at end of file diff --git a/c-128/xzip/objects.asm b/c-128/xzip/objects.asm new file mode 100644 index 0000000..8aff7ca --- /dev/null +++ b/c-128/xzip/objects.asm @@ -0,0 +1,200 @@ + PAGE + STTL "--- OBJECT & PROPERTY HANDLERS ---" + + +; ******************************************** +; AN ASSUMPTION HAS BEEN MADE WITH EZIP OBJECT +; HANDLING. THAT IS THAT ALL THIS STUFF IS +; BEFORE PURBOT AND IS IN MAIN MEMORY +; AND THEREFORE DIRECT ACCESSING IS JUST FINE +; LINDE +; ******************************************** +; ---------------------------------- +; GET ABSOLUTE ADDRESS OF OBJECT [A] +; ---------------------------------- +; ENTER: OBJECT IN A/X (LO/HI) +; EXIT: ADDRESS IN [I] +; (EZIP VERSION) + +OBJLOC: STX I+HI ; SAVE MSB FOR SHIFTING + ASL A ; MULTIPLY BY LENGTH OF AN ENTRY (14) + STA I+LO + ROL I+HI + LDX I+HI + ASL A + ROL I+HI ; *4 + ASL A + ROL I+HI ; *8 + ASL A + ROL I+HI ; *16 + SEC + SBC I+LO ; -(*2) + STA I+LO ; SO IS *14 TOTAL + LDA I+HI + STX I+HI + SBC I+HI + STA I+HI + LDA I+LO + CLC + ADC #112 ; ADD OBJECT TABLE OFFSET + BCC OBJ3 + INC I+HI +OBJ3: + 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC + LDY #12 ; (EZIP) + 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 #%00111111 ; MASK OUT LENGTH BITS (EZIP) + RTS + + +; ------------------------------- +; FETCH # BYTES IN PROPERTY VALUE +; ------------------------------- +; ENTRY: LIKE "PROPB" EXIT +; (EZIP) + +PROPL: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + RTS + +SHORT: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE + LDA #2 ; BIT 6 = 1, LENGTH =2 + RTS +ONE: LDA #1 ; BIT 6 = 0, LENGTH =1 + RTS + + +; ---------------------- +; POINT TO NEXT PROPERTY +; ---------------------- +; ENTRY: LIKE "PROPB" EXIT + +PROPNX: JSR PROPL ; GET LENGTH OF CURRENT PROP + TAX ; SAVE HERE +PPX: INY ; LOOP UNTIL + BNE PPY + INC I+LO + BNE PPY + INC I+HI +PPY: DEX ; [Y] POINTS TO + BNE PPX ; START OF NEXT PROP + INY ; CORRECT ALIGNMENT + RTS + + +; ----------------------------------------- +; CALL PROPNX, THEN ALIGN [I] AT THAT ENTRY +; ----------------------------------------- +; EXIT: [I] IS ALIGNED AT CURRENT PROPERTY +; [Y] IS ZEROED +; (EZIP) + +NEXTPI: JSR PROPNX ; GET ALIGNMENT OF NEXT PROPERTY INTO [Y] + TYA ; ADD OFFSET TO NEXT PROP + CLC ; TO [I] SO I POINTS DIRECTLY + ADC I+LO ; AT IT + STA I+LO + BCC NXTPI1 + INC I+HI ; ADD IN CARRY +NXTPI1: LDY #0 ; CLEAR [Y] AS IT IS USED AS AN INDEX + 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 ; (EZIP) + LDX ARG1+HI + 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 + CMP #$10 ; CHECK IF IN 2ND WORD + BCC FLS ; YES, GO ALIGN FOR THAT + SBC #16 ; ELSE ALIGN TO 3RD WORD + TAX + LDA I+LO + CLC + ADC #4 ; 3RD FLAG WORD + STA I+LO + BCC FLS0 + INC I+HI + JMP FLS0 ; (END EZIP CHGS) +FLS: 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 + \ No newline at end of file diff --git a/c-128/xzip/ops012.asm b/c-128/xzip/ops012.asm new file mode 100644 index 0000000..34f2af8 --- /dev/null +++ b/c-128/xzip/ops012.asm @@ -0,0 +1,1102 @@ + PAGE + STTL "--- 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: LDX #5 ;MOVE ZPC INTO MPC +ZPRI1: + LDA ZPC,X + STA MPC,X + DEX + BPL ZPRI1 ;NO NEED TO VALIDATE AS ZPC WAS VALID ANYWAY + JSR PZSTR ; PRINT THE Z-STRING AT [MPC] + LDX #5 ; COPY STATE OF [MPC] +ZPRI2: LDA MPC,X ; INTO [ZPC] + STA ZPC,X + DEX + BPL ZPRI2 + RTS + + +; ------ +; PRINTR +; ------ +; DO A "PRINTI," FOLLOWED BY "CRLF" AND "RTRUE" + +ZPRR: JSR ZPRI + JSR ZZCRLF + JMP ZRTRUE + + +; ------ +; RSTACK +; ------ +; "RETURN" WITH VALUE ON STACK + +ZRSTAK: JSR POPVAL ; GET VALUE INTO [X/A] + JMP ZRT1 ; AND GIVE IT TO "RETURN" + + +; ----- +; CATCH +; ----- + +ZCATCH: LDX OLDZSP+HI ; RETURN ZSTACK POINTER AS + LDA OLDZSP+LO ; ZRET WILL NEED IT + JMP PUTBYT + + +; --------- +; ORIGINAL? +; --------- + +; COPY PROTECTION DEVICE, RETURNS TRUE FOR NOW + +ZORIG: JMP PREDS + + + PAGE + STTL "--- 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 + LDX ARG1+HI ; (EZIP) + JSR OBJLOC ; GET OBJECT ADDR INTO [I] + LDY #8 ; POINT TO "NEXT" SLOT (EZIP) + BNE FIRST1 ; JMP + + +; ------ +; FIRST? +; ------ +; RETURN "FIRST" POINTER IN OBJECT [ARG1] ; +; FAIL IF LAST AND RETURN ZERO +; (EZIP ALTERATIONS) + +ZFIRST: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET OBJECT ADDR INTO [I] + LDY #10 ; POINT TO "FIRST" SLOT +FIRST1: LDA (I),Y ; GET CONTENTS OF SLOT + TAX + INY + LDA (I),Y ; INTO A,X + JSR PUTBYT ; PASS IT TO VARIABLE + LDA VALUE+LO ; EXAMINE THE VALUE JUST "PUT" + BNE PFINE + LDA VALUE+HI + BEQ PYUCK ; FAIL IF IT WAS ZERO +PFINE: JMP PREDS ; ELSE REJOICE + + +; --- +; LOC +; --- +; RETURN THE OBJECT CONTAINING OBJECT [ARG1] ; +; RETURN ZERO IF NONE +; (EZIP ALTERED) + +ZLOC: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + LDY #6 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET THE WORD + TAX + INY + LDA (I),Y + 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 + LDA (I),Y ; OF PROPERTY AT [I] INTO [A] + BMI PTZ2 ; BIT 7 = 1, LENGTH > 2 BYTES + AND #%01000000 + BEQ PTZ1 ; BIT 6 = 0, LENGTH = 1 + LDA #2 ; BIT 6 = 1, LENGTH = 2 + BNE PTZ3 ; JMP +PTZ1: LDA #1 + BNE PTZ3 ; JMP +PTZ2: AND #%00111111 ; ELSE PICK UP SIZE > 2 +PTZ3: LDX #0 ; CLEAR FOR PUTBYT + JMP PUTBYT + + +; --- +; INC +; --- +; INCREMENT VARIABLE [ARG1] + +ZINC: LDA ARG1+LO + JSR VARGET ; FETCH VARIABLE INTO [VALUE] + INC VALUE+LO + BNE ZINC1 + INC VALUE+HI +ZINC1: JMP ZD0 + + +; --- +; DEC +; --- +; DECREMENT VARIABLE [ARG1] + +ZDEC: LDA ARG1+LO + JSR VARGET ; FETCH VAR INTO [VALUE] + LDA VALUE+LO + SEC + SBC #1 + STA VALUE+LO + LDA VALUE+HI + SBC #0 + STA VALUE+HI +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 +; (EZIP CHANGES - 1) OBJLOC NEEDS HI & LO +; 2) MOVES AND COMPARES 2 BYTES) + +ZREMOV: LDA ARG1+LO ; GET SOURCE OBJECT ADDR + LDX ARG1+HI + 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 #7 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET THE DATA + STA K ; HOLD IT + DEY + LDA (I),Y + TAX ; X = HI + LDA K ; A = LO + ORA (I),Y ; COMPARE BYTES + BEQ REMVEX ; SCRAM IF NO OBJECT + LDA K ; PICK UP, DESTROYED BY ORA + JSR OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [I] + LDY #10 ; POINT TO "FIRST" SLOT + LDA (I),Y ; GRAB DATA + TAX + INY + LDA (I),Y ; A=LO, X=HI + CMP ARG1+LO ; IS THIS THE FIRST? + BNE REMVC1 ; NO, KEEP SEARCHING + CPX ARG1+HI ; HM? + BNE REMVC1 + LDY #8 ; ELSE COPY SOURCE'S "NEXT" SLOT + LDA (J),Y + INY ; INTO DEST'S "FIRST" SLOT ([Y] = 10) + INY + STA (I),Y + DEY ; BACK UP TO GET >BYTE + LDA (J),Y + INY + INY + STA (I),Y + BNE REMVC2 ; BRANCH ALWAYS +REMVC1: JSR OBJLOC + LDY #8 ; GET "NEXT" + LDA (I),Y + TAX + INY + LDA (I),Y + CMP ARG1+LO ; FOUND IT? + BNE REMVC1 ; NO, KEEP TRYING + CPX ARG1+HI + BNE REMVC1 + LDY #8 ; WHEN FOUND + LDA (J),Y ; MOVE "NEXT" SLOT OF SOURCE (THIS OBJECT) + STA (I),Y ; TO "NEXT" SLOT OF DEST + ;(OBJECT THAT REFERENCED THIS ONE) + INY + LDA (J),Y + STA (I),Y +REMVC2: LDA #0 + LDY #6 ; CLEAR "LOC" + STA (J),Y + INY + STA (J),Y + INY ; AND "NEXT" SLOTS ([Y] = 5) + STA (J),Y ; OF SOURCE OBJECT (ARG1) + INY + STA (J),Y +REMVEX: RTS + + +; ------ +; PRINTD +; ------ +; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + +ZPRD: LDA ARG1+LO + LDX ARG1+HI ; (EZIP) + + ; ENTRY POINT FOR "USL" + +PRNTDC: JSR OBJLOC ; GET ADDR OF OBJECT INTO [I] + LDY #12 ; GET PROP TABLE POINTER (EZIP) + 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+LO ; RE-SYNC THE + STA ZSP+LO ; Z-STACK POINTER + LDA OLDZSP+HI + STA ZSP+HI + JSR POPVAL ; POP # LOCALS INTO [X/A] + STX I+HI ; SAVE HERE + JSR POPVAL ; save how many args for ASSIGNED? + STA ASSVLU ; get how many here + + LDX I+HI ; and get # back + 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 IRET + STA ZPCL + JSR POPVAL + STX OLDZSP+LO + STA OLDZSP+HI + + LDA ZPCL ; check for zero zpc + BNE RETj ; which means we are returning to + LDA ZPCM ; an internal call + BNE RETj ; rather than just a normal + LDA ZPCH ; return + BNE RETj ; but so far it isn't + + JSR A12VAL ; MOVE [ARG1] TO [VALUE] + JMP ZIRET ; so then do internal return +RETj: + JSR VLDZPC ; MAKE VALID + LDA IRET ; CHECK IF SHOULD RETURN A VALUE + BEQ RETYES ; (0 = RET, 1 = NO RETURN) + RTS ; NO, SO JUST GET OUT OF HERE + +RETYES: 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 (QUAD) 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 + + + + PAGE + STTL "--- 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 + + +; ----------------- +; SIGNED COMPARISON +; ----------------- +; ENTRY: VALUES IN [VALUE] AND [I] + +COMPAR: LDA I+HI + EOR VALUE+HI + BPL SCMP + LDA I+HI + CMP VALUE+HI + BCC PGOOD + JMP PREDF + +SCMP: LDA VALUE+HI + CMP I+HI + BNE SCEX + LDA VALUE+LO + CMP I+LO +SCEX: BCC PGOOD + JMP PREDF + + +; --- +; IN? +; --- +; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]? + +ZIN: LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [I] + LDY #6 ; POINT TO "LOC" SLOT + LDA (I),Y ; GET DATA + CMP ARG2+HI ; IS IT THERE? + BNE PBAD ; NO + INY + LDA (I),Y + CMP ARG2+LO + 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 + + ; FALL THROUGH ... + + +; --------------------- +; RETURN VALUE IN [X/A] +; --------------------- + +VEXIT: STX VALUE+LO + STA VALUE+HI + JMP PUTVAL + + +; ---- +; BAND +; ---- +; RETURN [ARG1] "AND" [ARG2] + +ZBAND: LDA ARG1+LO + AND ARG2+LO + TAX + LDA ARG1+HI + AND ARG2+HI + JMP VEXIT + + +; ----- +; FSET? +; ----- +; IS FLAG [ARG2] SET IN OBJECT [ARG1]? + +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] +; (EZIP - EXPANDED FROM BYTE OBJECTS TO WORD OBJECTS) + +ZMOVE: JSR ZREMOV ; REMOVE FIRST - CUT ARG1 OUT OF WHERE IT IS + + ; NOW, IF IT IS ANYWHERE + + LDA ARG1+LO + LDX ARG1+HI + JSR OBJLOC ; GET SOURCE OBJECT ADDR INTO [I] + LDA I+LO ; COPY SOURCE (ARG1) ADDRESS + STA J+LO ; INTO [J] + LDA I+HI + STA J+HI + LDA ARG2+HI ; GET DEST OBJECT ID + LDY #6 ; POINT TO "LOC" SLOT OF SOURCE + STA (I),Y ; AND MOVE IT IN + TAX ; (MOVE ARG2 INTO PARENT SLOT OF ARG1) + LDA ARG2+LO + INY + STA (I),Y ; X/A (HI/LO) SET FOR OBJLOC + JSR OBJLOC ; GET ADDR OF DEST OBJECT INTO [I] (GET PARENT) + + ; NOW SWAP IN NEW VALUE + + LDY #10 ; POINT TO "FIRST" SLOT + LDA (I),Y ; OF PARENT (ARG2) + STA K+HI ; SAVE HERE FOR A MOMENT + LDA ARG1+HI ; GET SOURCE OBJECT ID + STA (I),Y ; MAKE IT "FIRST" OF PARENT + INY + LDA (I),Y + TAX + LDA ARG1+LO + STA (I),Y + TXA + ORA K+HI ; CHECK OLD "FIRST" OF DEST/PARENT + BEQ ZMVEX ; SCRAM IF ZERO + TXA ; GET LO BYTE AGAIN + LDY #9 ; MAKE OLD "FIRST" OF PARENT + STA (J),Y ; THE "NEXT" (SIBLING) OF THIS OBJECT (ARG1) + DEY ; I.E. ADD THIS ONE AT THE TOP OF LIST + LDA K+HI ; & GET >BYTE + STA (J),Y +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 + LDA #0 + 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 + ADC #0 ; PICK UP CARRY FROM MPCM + STA MPCH ; TO GET TOP BIT + JMP VLDMPC + + +; ---- +; GETP +; ---- +; RETURN PROPERTY [ARG2] OF OBJECT [ARG1] ; +; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0 + +ZGETP: + + JSR PROPB +GETP1: JSR PROPN ; GET ADDR OF PROP TBL + CMP ARG2+LO ; GET PROP ID + BEQ GETP3 ; FOUND IT + BCC GETP2 ; NOT THERE + JSR NEXTPI ; GET NEXT PROP, ALIGN [I] TO IT (EZIP) + JMP GETP1 ; TRY AGAIN WITH NEXT PROP + + ; PROPERTY NOT THERE, GET DEFAULT + +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 ; GET LENGTH OF PROP INTO [A] + INY ; MAKE [Y] POINT TO 1ST BYTE OF PROP + CMP #1 ; IF LENGTH =1 + BEQ GETPB ; GET A BYTE PROPERTY + CMP #2 ; IF LENGTH = 2 + 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: LDA ARG1+LO + LDX ARG1+HI ; (EZIP) + JSR OBJLOC + LDY #12 ; (EZIP) + 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 + +GETPT1: LDA (I),Y + AND #%00111111 ; MASK OUT LENGTH BITS (EZIP) + + CMP ARG2+LO ; CHECK ID + BEQ GETPT2 + BCS DDD + JMP DORET ; BEYOND IT, SO NOT THERE + +DDD: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT0 ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + JMP AAA + +SHORT0: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE0 + LDA #2 ; BIT 6 = 1, LENGTH =2 + JMP AAA +ONE0: LDA #1 ; BIT 6 = 0, LENGTH =1 + +AAA: TAX ; SAVE HERE +PPPX: INY ; LOOP UNTIL + BNE PPPY + INC I+HI +PPPY: DEX ; [Y] POINTS TO + BNE PPPX ; START OF NEXT PROP + INY ; CORRECT ALIGNMENT + TYA ; ADD OFFSET TO NEXT PROP + CLC ; TO [I] SO I POINTS DIRECTLY + ADC I+LO ; AT IT + STA I+LO + BCC CCCC1 + INC I+HI ; ADD IN CARRY +CCCC1: LDY #0 ; CLEAR [Y] AS IT IS USED AS AN INDEX + + JMP GETPT1 + +GETPT2: LDA (I),Y ; CHECK LENGTH FLAGS + AND #%10000000 ; TEST BIT 7 + BEQ SHORT1 ; OFF, SO 1 OR 2 BYTES + INY + LDA (I),Y ; NEXT BYTE HAS LENGTH + AND #%00111111 ; MASK OFF EXTRA BITS + JMP BBB + +SHORT1: LDA (I),Y ; PICK UP BYTE AGAIN + AND #%01000000 ; BIT 6 + BEQ ONE1 + LDA #2 ; BIT 6 = 1, LENGTH =2 + JMP BBB +ONE1: LDA #1 ; BIT 6 = 0, LENGTH =1 + +BBB: INY ; INC TO POINT AT PROPERTY VALUE (EZIP) + +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 [AR +; RETURN ZERO IF LAST ; RETURN FIRST IF [ARG2]=0; ERROR IF NO + +ZNEXTP: JSR PROPB ; ALIGN [I] AT PROPERTY TBL'S 1ST ENTRY + 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 NEXTPI ; ELSE TRY NEXT PROPERTY (EZIP) + JMP NXTP1 +NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY +NXTP3: JSR PROPN ; GET THE PROPERTY # + LDX #0 ; FOR PUTBYT (EZIP) + 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 + + +; ----- +; THROW +; ----- + +ZTHROW: LDA ARG2+LO ; SET ZSTACK POINTER + STA OLDZSP+LO ; UP FOR ZRET + LDA ARG2+HI + STA OLDZSP+HI + JMP ZRET + + END + \ No newline at end of file diff --git a/c-128/xzip/opsx.asm b/c-128/xzip/opsx.asm new file mode 100644 index 0000000..2418873 --- /dev/null +++ b/c-128/xzip/opsx.asm @@ -0,0 +1,733 @@ + PAGE + STTL "--- 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!) + + +; ---------------------------- +; ICALL,ICALL1, ICALL2, IXCALL +; ---------------------------- + +ZICALL: +ZICLL1: +ZICLL2: +ZIXCLL: LDA #1 ; SET FLAG FOR RETURNLESS CALL + STA IRET + BNE IENTR ; JMP OVER NORMAL SETTING + + +; ------------------- +; XCALL, CALL1, CALL2 +; ------------------- + +ZXCALL: ; DROP THROUGH +ZCALL1: ; CALL RTN HANDLES ALL 4 KINDS +ZCALL2: + + +; ---- +; CALL +; ---- +; BRANCH TO FUNCTION AT ([ARG1]*4), PASSING +; OPTIONAL PARAMETERS IN [ARG2]-[ARG4] +; ([ARG5]-[ARG8] FOR XCALL (EZIP)) + +ZCALL: LDA #0 + STA IRET ; SET FLAG TO RETURN SOMETHING +IENTR: LDA ARG1+LO + ORA ARG1+HI ; IS CALL ADDRESS ZERO? + BNE DOCALL ; NO, CONTINUE + + LDA IRET + BEQ Ij ; if no ret value, and no + RTS ; routine, the just end +Ij: + LDX #0 + JMP PUTBYT ; ELSE RETURN THE ZERO IN [A] +DOCALL: LDX OLDZSP+LO ; SAVE OLD STACK POINTER + LDA OLDZSP+HI + JSR PUSHXA + LDA ZPCL ; AND LSB OF [ZPC] + LDX IRET ; AND RETURN FLAG + 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 + ASL ARG1+LO ; MULTIPLY [ARG1] + ROL ARG1+HI ; (BY 2) + ROL A ; >BIT INTO [A] + STA ZPCH ; NEW >BIT OF [ZPC] + ASL ARG1+LO ; BY 4 (EZIP) + ROL ARG1+HI + ROL ZPCH + LDA ARG1+HI ; GET NEW DEST + CLC + ADC ARG3+LO + STA I+LO + LDA ARG1+HI + ADC ARG3+HI + CMP ARG2+HI + BCC FRWRD ; NO + BNE BKWRD ; YES + LDA I+LO + CMP ARG2+LO + BEQ FRWRD ; DEBUG, IF EQUAL REALLY LESS + BCS BKWRD ; OVERLAPS SO DO BACKWARD COPY + + ; ELSE FALL THROUGH TO FORWARD COPY + +FRWRD: LDA #0 ; USE GETBYT CAUSE MAY BE + STA MPCH ; BEYOND MAIN MEMORY + LDA ARG1+HI + STA MPCM + LDA ARG1+LO + STA MPCL + JSR VLDMPC ; AND ALIGN TO CORRECT PAGE + LDA ARG2+LO + STA I+LO + LDA ARG2+HI + CLC + ADC ZCODE ; MAKE ABSOLUTE + STA I+HI + LDA ARG3+LO + STA J+LO + LDA ARG3+HI + STA J+HI + +FRLP: JSR DECJ + BCC FRDUN ; CARRY CLEAR ON $FFFF + JSR GETBYT + LDY #0 + STA (I),Y + + INC I+LO + BNE FRLP + INC I+HI + JMP FRLP + +FRDUN: RTS + + +BKWRD: + LDA ARG3+LO ; DECR 1ST TO GET CORRECT OFFSET + STA J+LO + LDA ARG3+HI + STA J+HI + JSR DECJ + LDA ARG1+LO ; SET TO END OF SOURCE & DEST. + CLC + ADC J+LO + STA I+LO + LDA ARG1+HI + ADC J+HI + CLC + ADC ZCODE ; ABSOLUTE + STA I+HI + LDA ARG2+LO + CLC + ADC J+LO + STA K+LO + LDA ARG2+HI + ADC J+HI + CLC + ADC ZCODE + STA K+HI +BKLP: LDY #0 + LDA (I),Y + STA (K),Y + LDA I+LO ; DECR >BYTE AFTER X00 BYTE MOVED + BNE BKL0 + DEC I+HI +BKL0: DEC I+LO + LDA K+LO + BNE BKL1 + DEC K+HI +BKL1: DEC K+LO + JSR DECJ ; RETURNS CARRY CLEAR ON $FFFF + BCS BKLP +BKDUN: RTS + + ; ZERO LENGTH # OF BYTES OF SOURCE + +CASE1: LDA ARG1+LO + STA I+LO + LDA ARG1+HI + CLC + ADC ZCODE ; ABSOLUTE + STA I+HI + LDA ARG3+LO ; SET UP COUNTER + STA J+LO + LDA ARG3+HI + STA J+HI + LDY #0 +C1LP: JSR DECJ ; CARRY CLEAR WHEN J = $FFFF + BCC C1DUN + LDA #0 + STA (I),Y + INY + BNE C1LP + INC I+HI ; NEXT PAGE + JMP C1LP +C1DUN: RTS + + ; 2'S COMPLEMENT LENGTH (XOR + 1) THEN DO FORWARD COPY + +CASE3: LDA ARG3+LO + EOR #$FF + STA ARG3+LO + LDA ARG3+HI + EOR #$FF + STA ARG3+HI + INC ARG3+LO + BNE GOFRWD + INC ARG3+HI +GOFRWD: JMP FRWRD + + +; --------- +; ASSIGNED? +; --------- + + +ZASSND: LDA ARG1+LO ; COMPARE TO # OF OPTIONALS FROM LAST CALL + CMP ASSVLU + BCC DOYES ; IF LESS OR EQUAL, WAS ASSIGNED + BEQ DOYES + JMP PREDF +DOYES: JMP PREDS + + +; ------------- +; LOGICAL SHIFT +; ------------- +; SHIFT ARG1, ARG2 BITS (LEFT IF ARG2 IS POS. RIGHT IF NEG.) + +ZSHIFT: LDA ARG1+LO ; SET UP FOR SHIFT + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCS SRIGHT + + ; SHIFT LEFT + + TAY ; COUNT +SLP1: ASL VALUE+LO + ROL VALUE+HI + DEY + BNE SLP1 + JMP PUTVAL ; AND RETURN THE VALUE + +SRIGHT: EOR #$FF ; COMPLEMENT + TAY +SLP2: LSR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL SLP2 + JMP PUTVAL + + +; ---------------- +; ARITHMETIC SHIFT +; ---------------- +; PROPAGATING SIGN BIT ON RIGHT SHIFT + +ZASHFT: LDA ARG2+LO ; IF NEGATIVE, SHIFT RIGHT + CMP #$80 + BCC ZSHIFT ; SAME AS LOGICAL SHIFT + LDX ARG1+LO ; SET UP FOR SHIFT + STX VALUE+LO + LDX ARG1+HI + STX VALUE+HI + + EOR #$FF ; COMPLEMENT COUNT + TAY +ASLP2: LDA ARG1+HI + ASL A ; GET SIGN BIT + ROR VALUE+HI ; SHIFT + ROR VALUE+LO + DEY + BPL ASLP2 + JMP PUTVAL + + END + \ No newline at end of file diff --git a/c-128/xzip/read.asm b/c-128/xzip/read.asm new file mode 100644 index 0000000..87e180d --- /dev/null +++ b/c-128/xzip/read.asm @@ -0,0 +1,645 @@ + PAGE + STTL "--- READ HANDLER ---" + + +; ---- +; READ +; ---- +; READ LINE INTO TABLE [ARG1] ; PARSE INTO TABLE [ARG2] (IF ARG2 IS THERE) + +ZREAD: LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + CLC ; ABSOLUTE + ADC ZCODE + STA RDTBL1+HI ; AND PLACE IT HERE TO USE + LDA ARG1+LO + STA RDTBL1+LO ; LSBS NEED NOT CHANGE + + LDA #0 ; TURN OFF FLAGS + STA PSVFLG ; FOR ZLEX + STA VOCFLG + + LDX NARGS + DEX ; IF 2ND TBL ADDR 0 OR NOT THERE + BEQ ONLYRD ; JUST READ IN DON'T DO CONVERSION (X) + LDX #0 ; JIC + LDA ARG2+HI + ORA ARG2+LO + BEQ ONLYRD + + LDA ARG2+HI + CLC + ADC ZCODE + STA RDTBL2+HI + LDA ARG2+LO + STA RDTBL2+LO + LDX #1 ; 1 = DO IT ALL (X) + +ONLYRD: STX RDFLAG ; CHECK AGAIN AFTER READ IN WHAT TO DO + JSR INPUT ; READ LINE; RETURN LENGTH IN [RDTBL1],1 + LDA RDFLAG ; FLAG (X) + BEQ RDEX ; IF INPUT ONLY, LEAVE NOW + JSR DOREST + + ; RETURN NOW ONLY WANTED READ PART +RDEX: + LDA BRKCHR ; GET BREAK CHAR + LDX #0 + JMP PUTBYT ; RETURN IT + + ; IF TIMEOUT, [A]=0 SO WILL QUIT W/NO RESULTS + +DOREST: LDY #1 + LDA (RDTBL1),Y ; GET # OF CHARS IN INBUF + STA LINLEN ; SAVE # CHARS IN LINE + LDA #0 + STA WRDLEN ; INIT # CHARS IN WORD COUNTER + STA (RDTBL2),Y ; CLEAR "# WORDS READ" SLOT ([A] = 0) +NOCLR: INY ; = 2 + STY SOURCE ; INIT SOURCE TABLE PNTR + STY RESULT ; AND RESULT TABLE POINTER + + ; MAIN LOOP STARTS HERE + +READL: LDY #0 ; POINT TO "MAX # WORDS" SLOT + LDA (RDTBL2),Y ; AND READ IT + BEQ RDERR ; (5/14/85 - FORCE # WORDS TO + CMP #59 ; BE BETWEEN 1 AND 59) + BCC RD0 +RDERR: LDA #58 ; (5/16/86 - MAKE IT 58, 59 LOST) + STA (RDTBL2),Y ; Le) +RD0: INY ; (Y = 1) POINT TO "# WORDS READ" SLOT + CMP (RDTBL2),Y ; TOO MANY WORDS? + BCC RLEX ; YES, SO LEAVE, IGNORING THE REST + +; BCS RL1 ; CHANGED 5.2.85 IN ZIP & EZIP +; ; *** ERROR #13: PARSER OVERF<*** +; +; LDA #13 +; JMP ZERROR + +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 #9 ; 9 CHARS DONE? (EZIP) + 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 #8 ; 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 (RDTBL1),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 (RDTBL1),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 (RDTBL2),Y ; FETCH THE # WORDS READ + CLC + ADC #1 ; INCREMENT IT + STA (RDTBL2),Y ; AND UPDATE + LDY #0 + STY WRDLEN ; CLEAR # CHARS IN WORD + + LDA PSVFLG ; IF SHOULD PRESERVE WHAT'S IN + BEQ READL4 + LDA VALUE+HI ; RDTBL2 AND NOT FOUND (VALUE = 0) + ORA VALUE+LO + BEQ READL5 ; JUST SKIP OVER + +READL4: 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 + +READL5: LDA RESULT ; UPDATE THE + CLC ; RESULT TABLE POINTER + ADC #4 ; SO IT POINTS TO THE + STA RESULT ; NEXT ENTRY + JMP READL ; AND LOOP BACK + + +; --- +; LEX +; --- +; DO PARSE OF TBL1 INTO TBL2 (2ND HALF OF READ) + +ZLEX: LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + CLC ; ABSOLUTE + ADC ZCODE + STA RDTBL1+HI ; AND PLACE IT HERE TO USE + LDA ARG1+LO + STA RDTBL1+LO ; LSBS NEED NOT CHANGE + + LDA ARG2+HI + CLC + ADC ZCODE + STA RDTBL2+HI + LDA ARG2+LO + STA RDTBL2+LO + + DEC NARGS + DEC NARGS + BEQ NORMLEX ; USE NORMAL VOCAB TBL + + LDA #1 ; USE ARG3 VOCAB TBL + STA VOCFLG + LDA #0 + DEC NARGS + BEQ NOSAVE ; ZERO UNFOUND WORDS + LDA #1 ; PRESERVE UNFOUND WORD SLOT FLAG +NOSAVE: STA PSVFLG + JMP DOLEX + +NORMLEX: LDA #0 + STA VOCFLG ; USE NORMAL VOCAB TBL + STA PSVFLG ; AND WILL BE NO PRESERVING + +DOLEX: JMP DOREST ; GO DO LEXICAL CONVERSION AND JUST RETURN + + +; ----- +; ZWSTR +; ----- +; CONVERT A WORD TO A ZWORD, PLACE IN ARG4 TBL + +ZWSTR: LDA ARG1+HI ; MAKE THE TABLE ADDRESSES + CLC ; ABSOLUTE + ADC ZCODE + STA RDTBL1+HI ; AND PLACE IT HERE TO USE + LDA ARG1+LO + STA RDTBL1+LO ; LSBS NEED NOT CHANGE + + ; (IGNORE WORD LENGTH CAUSE CHECK FOR BREAK CHAR (9 CHAR MAX)) + + LDA ARG3+LO ; ADD OFFSET INTO INBUF + CLC ; AS NOT SURE OF OFFSET SIZE + ADC RDTBL1+LO ; MAKE SO CAN BE ANY SIZE + STA RDTBL1+LO + LDA ARG3+HI + ADC RDTBL1+HI + STA RDTBL1+HI + + LDA ARG4+HI ; AND MAKE RECIPIENT ADDR ABSOLUTE + CLC + ADC ZCODE + STA RDTBL2+HI + LDA ARG4+LO + STA RDTBL2+LO + + ; START A NEW WORD + + LDA #9 + STA LINLEN ; 1 WORD'S WORTH + LDA #0 + STA WRDLEN + LDX #8 ; CLEAR Z-WORD INPUT BUFFER +WSTR1: STA IN,X ; [A] = 0 + DEX + BPL WSTR1 + + ; THIS LOOP READS FROM INBUF TIL BREAK OR 9 CHARS READ + +WSTR2: LDY WRDLEN ; SOURCE OFFSET SAME AS WRDLEN + LDA (RDTBL1),Y ; ELSE GRAB NEXT CHAR + JSR BREAK ; IS IT A BREAK? + BCS WSTR3 ; YES IF CARRY WAS SET + + LDY WRDLEN ; SOURCE OFFSET SAME AS WRDLEN + LDA (RDTBL1),Y ; ELSE GRAB NEXT CHAR + + LDX WRDLEN ; ELSE STORE THE CHAR + STA IN,X ; INTO THE INPUT BUFFER + INC WRDLEN ; ONE MORE CHAR IN WORD + DEC LINLEN ; ONE LESS IN LINE + BNE WSTR2 ; AND LOOP BACK TIL DONE + +WSTR3: LDA WRDLEN ; ANY CHARS IN WORD YET? + BEQ WOOPS ; APPARENTLY NOT, OOPS + JSR CONZST ; CONVERT ASCII IN [IN] TO Z-STRING + + LDY #5 ; MOVE FROM [OUT] TO RDTBL2 +WSTR4: LDA OUT,Y ; (RDTBL2 HAS DIFF USE HERE FROM IN ZREAD) + STA (RDTBL2),Y + DEY + BPL WSTR4 +WOOPS: RTS + + +; ----------------------------------- +; FIND BASE ADDR OF RESULT ENTRY SLOT +; ----------------------------------- + +EFIND: LDA RDTBL2+LO ; LSB OF RESULT TABLE BASE + CLC + ADC RESULT ; AND CURRENT POINTER + STA ENTRY+LO ; SAVE IN [ENTRY] + LDA RDTBL2+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 (RDTBL1),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? +; --------------------------------- +; ------------------ +; NORMAL BREAK CHARS +; ------------------ + +BRKTBL: DB '!?,.' ; IN ORDER OF + DB $0D ; ASCII ENDING FREQUENCY + DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED + DB 0 ; ZERO ADDED FOR ZWSTR (X) +NBRKS EQU $-BRKTBL ; # NORMAL BREAKS + +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 + + +; --------------------- +; IS CHAR IN [A] A SIB? +; --------------------- + +SIB: STA IOCHAR ; SAVE TEST CHAR + LDA ZBEGIN+ZVOCAB ; GET 1ST BYTE IN VOCAB TABLE + LDY ZBEGIN+ZVOCAB+1 + STA MPCM + STY MPCL + LDA #0 + STA MPCH + JSR VLDMPC ; GET CORRECT PAGE + JSR GETBYT ; HAS # SIBS + STA J ; USE AS AN INDEX +SBL: JSR GETBYT ; GET NEXT SIB + CMP IOCHAR ; MATCHED? + BEQ FBRK0 ; YES, REPORT IT + DEC J + BNE SBL ; ELSE KEEP LOOPING + LDA IOCHAR + CLC ; NO MATCH, SO + RTS ; EXIT WITH CARRY CLEAR +FBRK0: LDA IOCHAR +FBRK: SEC ; EXIT WITH CARRY SET + RTS ; IF MATCHED WITH A BREAK CHAR + + +; ----------------- +; VOCABULARY SEARCH +; ----------------- +; ENTRY: 6-BYTE TARGET Z-WORD IN [OUT] +; EXIT: VIRTUAL ENTRY ADDRESS IN [VALUE] IF FOUND ; +; OTHERWISE [VALUE] = 0 + +VWLEN EQU I ; ********** +VWCUR EQU J+HI + +FINDW: LDA VOCFLG ; USE WHAT VOCAB TBL? + BEQ FWL2 ; NORMAL + LDA ARG3+HI ; IF ALTERNATE VOCTBL + LDY ARG3+LO ; IT'S ADDR IS IN ARG3 + JMP FWL3 + +FWL2: LDA ZBEGIN+ZVOCAB ; GET VIRTUAL ADDR OF VOCAB TBL + LDY ZBEGIN+ZVOCAB+1 +FWL3: STA MPCM + STY MPCL + LDA #0 + STA MPCH + JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # SIBS + CLC + ADC MPCL ; GET ACTUAL BASE ADDR OF VOCAB ENTRIES + STA MPCL + BCC FWL0 + INC MPCM +FWL0: JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET # BYTES PER ENTRY (AND MOVE TO NEXT BYTE) + STA ESIZE ; SAVE IT HERE + STA VWLEN+0 ; AND HERE + LDA #0 ; CLEAR REST OF COUNTER + STA VWLEN+1 + STA VWLEN+2 + + JSR GETBYT ; GET # OF ENTRIES IN TBL (MSB) + STA NENTS+HI ; AND STUFF IT IN [NENTS] + JSR GETBYT ; DON'T FORGET THE LSB! + STA NENTS+LO + LDA NENTS+HI + BPL SORTED + JMP UNSORTED ; VOCAB LIST IS UNSORTED, HANDLE DIFFERENTLY + +SORTED: LDA #0 ; FIND SIZE OF VAOCAB TBL + STA VOCEND ; TO LOCATE THE END OF IT + STA VOCEND+1 + STA VOCEND+2 + LDX ESIZE + +FWL1: CLC + LDA VOCEND ; (# OF ENTRIES) * (ENTRY SIZE) + ADC NENTS+LO + STA VOCEND + LDA VOCEND+1 + ADC NENTS+HI + STA VOCEND+1 + LDA VOCEND+2 + ADC #0 ; PICK UP CARRY + STA VOCEND+2 + DEX + BNE FWL1 + + CLC + LDA VOCEND ; AND ADD LENGTH TO START OF TBL + ADC MPCL ; TO GET END OF TBL + STA VOCEND + LDA VOCEND+1 + ADC MPCM + STA VOCEND+1 + LDA VOCEND+2 + ADC MPCH + STA VOCEND+2 ; TO SAVE FOR TESTING IF PAST END + + LDA VOCEND ; SUBTRACT [ESIZE] SO THAT + SEC ; [VOCEND] POINTS TO REAL LAST ENTRY + SBC ESIZE + STA VOCEND + LDA VOCEND+1 + SBC #0 + STA VOCEND+1 + + ; BEGIN THE SEARCH! [MPC] NOW POINTS TO 1ST ENTRY + + LSR NENTS+HI ; 2 ALIGN # OF ENTRIES + ROR NENTS+LO +FWCALC: ASL VWLEN+0 ; CALCULATE INITIAL OFFSET FOR SEARCH + ROL VWLEN+1 + ROL VWLEN+2 + LSR NENTS+HI + ROR NENTS+LO + BNE FWCALC + +; LDA NENTS+HI +; BNE FWCALC ; DOUBLE-CHECK + + CLC ; ADD 1ST OFFSET INTO START OF VOCABULARL + LDA MPCL ; WHICH IS CURRENTLY IN MPC + ADC VWLEN+0 + STA MPCL + LDA MPCM + ADC VWLEN+1 + STA MPCM + LDA MPCH + ADC VWLEN+2 + STA MPCH + + SEC ; AVOID FENCE-POST BUG FOR + LDA MPCL ; EXACT-POWER-OF-2 TBL (DUNCAN) + SBC ESIZE + STA MPCL + BCS FWLOOP + LDA MPCM + SEC + SBC #1 + STA MPCM + BCS FWLOOP + LDA MPCH + SBC #0 + STA MPCH + +FWLOOP: LSR VWLEN+2 ; SET FOR NEXT OFFSET, + ROR VWLEN+1 ; WHICH IS HALF THIS ONE + ROR VWLEN+0 + + LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + + JSR VLDMPC ; SET TO NEW PAGE + JSR GETBYT ; GET 1ST BYTE OF ENTRY + + CMP OUT ; MATCH 1ST BYTE OF TARGET? + BCC WNEXT ; LESS + BNE FWPREV ; GREATER + JSR GETBYT + CMP OUT+1 ; 2ND BYTE MATCHED? + BCC WNEXT + BNE FWPREV ; NOPE + JSR GETBYT + CMP OUT+2 ; 3RD BYTE? + BCC WNEXT + BNE FWPREV ; SORRY ... + JSR GETBYT + CMP OUT+3 ; 4TH BYTE + BCC WNEXT + BNE FWPREV + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BCC WNEXT + BNE FWPREV ; SORRY ... + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + BCS FWPREV ; ELSE BACK UP ... + +WNEXT: LDA VWCUR+0 ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + ADC VWLEN+1 + + BCS WNXT2 ; SAVES CODE (?) + + STA MPCM + + LDA #0 + STA MPCH + +WNXT0: LDA MPCM ; GONE PAST END? + CMP VOCEND+1 + BEQ WNXT1 ; MAYBE + BCS WNXT2 ; YES + BCC FWMORE ; NO +WNXT1: LDA MPCL + CMP VOCEND + BCC FWMORE ; NO + BEQ FWMORE ; NO, EQUAL +WNXT2: LDA VOCEND ; YES, SO POINT TO END OF TBL + STA MPCL + LDA VOCEND+1 + STA MPCM + LDA VOCEND+2 + STA MPCH + JMP FWMORE + +FWPREV: LDA VWCUR+0 ; TO MOVE DOWN, JUST SUBTRACT + SEC ; OFFSET FROM START OF THIS + SBC VWLEN+0 ; ENTRY + STA MPCL + LDA VWCUR+1 + SBC VWLEN+1 + STA MPCM + LDA VWCUR+2 + SBC VWLEN+2 + STA MPCH + +FWMORE: LDA VWLEN+2 ; IF OFFSET >GE< 1 WORD, CONTINUE + BNE FWM1 + LDA VWLEN+1 + BNE FWM1 + LDA VWLEN+0 + CMP ESIZE + BCC FWFAIL +FWM1: JMP FWLOOP ; AND TRY AGAIN + +FWFAIL: LDA #0 ; NOT FOUND + STA VALUE+LO + STA VALUE+HI + RTS ; THEN RETURN WITH [VALUE] = 0 + +FWSUCC: LDA VWCUR+0 ; ENTRY MATCHED! RETRIEVE START OF WORD + STA VALUE+LO + LDA VWCUR+1 + STA VALUE+HI ; MUST BE 64K LIMIT AS ONLY + RTS ; WORD VALUE RETURNABLE + + +UNSORTED: ; DO UNSORTED SEARCH ON VOCAB TBL IN MPC + LDA #$FF ; 2'S COMPLEMENT LENGTH + EOR NENTS+HI ; TO GET REAL LENGTH + STA NENTS+HI ; WAS NEGATIVE TO SIGNIFY + LDA #$FF ; UNSORTED VOCAB TBL + EOR NENTS+LO + STA NENTS+LO + INC NENTS+LO ; 2'S CMPL + BNE UNSRT0 + INC NENTS+HI + +UNSRT0: LDA MPCL ; HOLD START ADDR, MPC WILL BE A MESS + STA VWCUR+0 + LDA MPCM + STA VWCUR+1 + LDA MPCH + STA VWCUR+2 + + JSR GETBYT ; GET 1ST BYTE OF ENTRY + CMP OUT ; MATCH 1ST BYTE OF TARGET? + BNE FNEXT ; LESS + JSR GETBYT + CMP OUT+1 ; 2ND BYTE MATCHED? + BNE FNEXT + JSR GETBYT + CMP OUT+2 ; 3RD BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+3 ; 4TH BYTE + BNE FNEXT + JSR GETBYT + CMP OUT+4 ; 5TH BYTE? + BNE FNEXT + JSR GETBYT + CMP OUT+5 ; LAST BYTE? + BEQ FWSUCC ; FOUND IT! + +FNEXT: LDA VWCUR+LO ; TO MOVE UP, JUST ADD + CLC ; OFFSET FROM START OF THIS + ADC ESIZE ; ENTRY + STA MPCL + BCC FNEXT0 + + LDA VWCUR+HI ; PICK UP CARRY + ADC #0 + STA MPCM + LDA #0 + STA MPCH + JSR VLDMPC ; CROSSED PAGE SO RE-VALIDATE + +FNEXT0: DEC NENTS+LO ; CHECKED ALL ENTRIES? + BNE UNSRT0 + LDA NENTS+HI + BEQ FWFAIL ; GO INDICATE NO FIND + DEC NENTS+HI ; OR DO NEXT 256 ENTRIES + JMP UNSRT0 + + END + \ No newline at end of file diff --git a/c-128/xzip/send.bas b/c-128/xzip/send.bas new file mode 100644 index 0000000..2b17340 Binary files /dev/null and b/c-128/xzip/send.bas differ diff --git a/c-128/xzip/subs.asm b/c-128/xzip/subs.asm new file mode 100644 index 0000000..2fdae29 --- /dev/null +++ b/c-128/xzip/subs.asm @@ -0,0 +1,350 @@ + PAGE + STTL "--- 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 LOW = 16, + BCS GETVRG ; IT'S GLOBAL + +; HANDLE A LOCAL VARIABLE + +GETVRL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA LOCALS-2+LO,X ; GRAB LSB + STA VALUE+LO + LDA LOCALS-2+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] +; ---------------------------------- +; ZSTACK DOUBLED IN SIZE FOR EZIP +; SO THIS RTN ALL NEW + +POPVAL: LDA ZSP+LO ; IF ZSP+LO IS 0 + BNE POP1 + STA ZSP+HI ; MUST DEC. HI (HI = 0 OR 1 ONLY) +POP1: DEC ZSP+LO ; THEN DEC ZSP LO + BNE POP2 + ORA ZSP+HI ; LO + HI BOTH 0? + BEQ UNDER ; UNDERFLOW IF ZERO! +POP2: LDY ZSP+LO + LDA ZSP+HI + BEQ POP3 ; BOTTOM HALF OF ZSTACK + LDA ZSTKTL,Y ; GET VALUE FROM TOP HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKTH,Y + STA VALUE+HI + RTS + +POP3: LDA ZSTKBL,Y ; GET VALUE FROM BOTTOM HALF + STA VALUE+LO ; OF ZSTACK INTO VALUE & A,X + TAX + LDA ZSTKBH,Y + STA VALUE+HI + 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: PHA ; HOLD VALUE IN [A] A SEC. + LDY ZSP+LO + LDA ZSP+HI + BEQ PSHBOT ; ON BOTTOM HALF OF STACK + TXA + STA ZSTKTL,Y ; PUSH VALUE ONTO TOP HALF OF STACK + PLA + STA ZSTKTH,Y + JMP PSHUPD ; NOW UPDATE POINTER + +PSHBOT: TXA ; PLACE VALUE ON ZSTACK + STA ZSTKBL,Y + PLA + STA ZSTKBH,Y +PSHUPD: INC ZSP+LO ; UPDATE ZSTACK POINTER + BNE PSHEX + LDA ZSP+LO + ORA ZSP+HI + BNE OVER ; OVERFLOW IF $200 + INC ZSP+HI ; TO 1 +PSHEX: 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 + +; FLUSH TOP WORD OFF STACK +; AND REPLACE WITH [VALUE] + + LDA ZSP+LO ; IF ZSP+LO =0 + BNE VAR1 ; THEN HI =1 (GUARDED ELSEWHERE) + STA ZSP+HI ; DECREMENT HI (ONLY 0 OR 1) +VAR1: DEC ZSP+LO ; NOW DEC LOW BYTE + BNE PSHVAL + ORA ZSP+HI + BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO! + BNE PSHVAL + + ; RETURN A ZERO +RET0: LDA #0 + LDX #0 + + ; RETURN WORD IN [A], [X] (LO,HI) (EZIP EXPANDED TO A WORD) +PUTBYT: STA VALUE+LO + ; LDA #0 + STX 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 LOW = 16, + BCS PUTVLG ; IT'S GLOBAL + + ; PUT A LOCAL VARIABLE +PUTVLL: ASL A ; WORD INDEX + TAX ; INTO THE [LOCALS] TABLE + LDA VALUE+LO ; GRAB LSB + STA LOCALS-2+LO,X ; SAVE IN LOCAL TABLE + LDA VALUE+HI ; DO SAME TO + STA LOCALS-2+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 PREDB7 ; 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 +PREDB7: 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: LDA VALUE+LO ; SUBTRACT 2 FROM OFFSET + SEC ; IN [VALUE] + SBC #2 + TAX ;SAVE LO BYTE + LDA VALUE+HI + SBC #0 + STA I+LO ;MSB OF OFFSET = LSB OF [I] + LDY #0 ; CLEAR THE MSB + STY I+HI ; OF [I] + ASL A ; EXTEND THE SIGN OF OFFSET + ROL I+HI ; INTO MSB OF [I] + ASL A + ROL I+HI ; (EZIP) + TXA ; GET LSB OF OFFSET + 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 PREDB6 + LDA I+LO ; ELSE CALC NEW UPPER BITS + CLC + ADC ZPCM + STA ZPCM + LDA I+HI + ADC ZPCH + AND #%00000011 ; USE ONLY BIT 0 (& 1 - EZIP) + STA ZPCH + JMP VLDZPC ;MAKE VALID +PREDB6: + + ; FALL THROUGH ... + +; ---- +; NOOP +; ---- + +ZNOOP: RTS + + +; ---------------------- +; MOVE [ARG1] TO [VALUE] +; ---------------------- + +A12VAL: LDA ARG1+LO + STA VALUE+LO + LDA ARG1+HI + STA VALUE+HI + RTS + + +; ----------------------------------- +; INDICATE STATUS LINE REFRESH NEEDED +; ----------------------------------- + +REFRSH: LDA ZBEGIN+ZSCRIP+1 ; PICK UP LOW BYTE OF FLAG WORD + ORA #%00000100 ; SET BIT 2 + STA ZBEGIN+ZSCRIP+1 ; AND PUT IT BACK + RTS + + END + \ No newline at end of file diff --git a/c-128/xzip/warm.asm b/c-128/xzip/warm.asm new file mode 100644 index 0000000..93ce644 --- /dev/null +++ b/c-128/xzip/warm.asm @@ -0,0 +1,269 @@ + PAGE + STTL "--- WARMSTART ROUTINE ---" + + ; ------------- + ; ZIP WARMSTART + ; ------------- + +TMSG: DB "(Please be patient, this takes a while)" + DB EOL +TMSGL EQU $-TMSG + +CMSG: DB EOL,EOL + DB "Do you want color? " +CMSGL EQU $-CMSG + + ; SET FCN KEYS SO THAT THEY = WHAT XZIP WANTS (MAKE RUN/STOP BEEP) +FCNKEY: DB 0,133,134,135,136,137,138,139,140,7,143 + + +WARM2: LDA #0 ; CLEAR ALL Z-PAGE VARIABLES + LDX #ZEROPG +ST0: STA 0,X + INX + CPX #ZPGTOP + BCC ST0 + + STA CSFLAG ; clear ^S flag + + INC ZSP+LO ; INIT Z-STACK POINTERS + INC OLDZSP+LO ; TO "1" + INC SCRIPT ; ENABLE SCRIPTING + INC SCREENF ; TURN DISPLAY ON + INC SIDEFLG ; SET SIDE 1 + + LDA #%00001110 ; DO IT AGAIN AS JUST + STA BANK0 ; WIPED IT OUT + LDA #%01111111 + STA BANK1 + LDA #%00111110 + STA BANK2 + + ; GRAB THE FIRST BLOCK OF PRELOAD + + LDA #>ZBEGIN ; MSB OF PRELOAD START ADDRESS + STA ZCODE ; FREEZE IT HERE + STA DBUFF+HI ; LSB IS ALWAYS ZERO + LDA #MAIN + STA DSKBNK ; SET TO MAIN BANK + LDA #1 ; Set ZPURE to 100 to fake + STA ZPURE+HI ; GETDSK out this first time through + JSR GETDSK ; [DBLOCK] SET TO Z-BLOCK 0 + BCC CHKGAM + JMP DSKERR ; BAD DISK READ + + ; EXTRACT GAME DATA FROM Z-CODE HEADER + +CHKGAM: LDA ZBEGIN+ZVERS ; (XZIP) IS GAME AN XZIP? + CMP #5 ; 5 means xzip + BEQ YESEZ ; YES, CONTINUE + +; *** ERROR #16 -- NOT AN EZIP GAME *** + LDA #16 + JMP ZERROR +YESEZ: + LDA ZBEGIN+ZENDLD ; MSB OF ENDLOAD POINTER + STA ZPURE+HI ; GOT TO FIGURE OUT FIRST PAGE + LDA ZBEGIN+ZENDLD+1 ; of data on side 2 + STA ZPURE+LO ; ok? + + LSR ZPURE+HI ; SO WE NEED TO /64 TO GET IT + ROR ZPURE+LO ; SO DO 6 SHITS + LSR ZPURE+HI + ROR ZPURE+LO + LSR ZPURE+HI + ROR ZPURE+LO + LSR ZPURE+HI + ROR ZPURE+LO + LSR ZPURE+HI + ROR ZPURE+LO + LSR ZPURE+HI ; NOW IT CONTAINS FIRST PAGE ON + ROR ZPURE+LO ; SIDE 2 OF THE DISK + + LDA #%00111000 ; WITH UNDERLINE, MONOSPACE AND + STA ZBEGIN+ZMODE ; SOUND + + LDA #XZIPID ; SET INTERPRETER ID + STA ZBEGIN+ZINTWD + LDA #VERSID + STA ZBEGIN+ZINTWD+1 + LDA #0 ; CLEAR TOP BYTE + STA ZBEGIN+ZHWRD + STA ZBEGIN+ZVWRD + LDA #79 ; SET SCREEN PARAMETERS + STA ZBEGIN+ZHWRD+1 + LDA #24 + STA ZBEGIN+ZVWRD+1 + LDA #1 ; EACH "PIXEL" IS 1*1 + STA ZBEGIN+ZFWRD + STA ZBEGIN+ZFWRD+1 + LDA #24 ; AND SCREEN PARAMETERS + STA ZBEGIN+ZSCRWD + LDA #79 + STA ZBEGIN+ZSCRWD+1 + LDA #2 ; DEFAULT COLORS + STA ZBEGIN+ZCLRWD ; CYAN ON BLACK + LDA #8 + STA ZBEGIN+ZCLRWD+1 + + 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+ZOBJEC ; NOT TO MENTION + CLC ; THE OBJECT TABLE + ADC ZCODE + STA OBJTAB+HI + LDA ZBEGIN+ZOBJEC+1 ; LSB SAME + STA OBJTAB+LO + + LDA ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + ORA ZBEGIN+ZTCHAR+1 ; is it zero though? + BEQ INICLL + + LDA ZBEGIN+ZTCHAR ; DO SAME FOR TCHARS TABLE + CLC + ADC ZCODE + STA TCHARS+HI + LDA ZBEGIN+ZTCHAR+1 ; NO CHANGE FOR LSB + STA TCHARS+LO + + ; FIND SIZE AND NUMBER OF SAVES + +INICLL: + LDA ZBEGIN+ZPURBT ; SIZE OF IMPURE + CMP #$A0 ; MAXIMUM IMPURE IS $A000 (36K) + BCC SIZE0 ; OKAY, CONTINUE + + LDA #13 + JMP ZERROR ; ELSE ERROR #13 (IMPURE TOO BIG) + +SIZE0: ADC #6 ; PLUS ZSTACK &... + STA SAVSIZ ; HOW MANY PAGES PER SAVE + + LDX #0 + STX NUMSAV +SIZE1: INC NUMSAV ; INC NUMSAVE WITH EACH + CLC ; POSSIBLE SAVE + ADC SAVSIZ + BCC SIZE1 +SIZE2: INC NUMSAV ; TOTAL SIZE IS 170K - 1, ($297) + CLC + ADC SAVSIZ ; SO DO LOOP FOR 1ST & 2ND $100 + BCC SIZE2 +SIZE3: CMP #$97 + BCS SIZE4 ; BEYOND TOTAL DISK SIZE + INC NUMSAV + CLC + ADC SAVSIZ + BCC SIZE3 +SIZE4: + LDA NUMSAV + CMP #9 + BCC SZj + LDA #9 ; just make it 9 for ease +SZj: + CLC + ADC #'0' + STA POSTOP ; SET POSITION MSG + + LDY #21 ; POSITION MESSAGE + LDX #14 + CLC + JSR PLOT + + LDX #TMSG + LDY #TMSGL + JSR DLINE + + JSR LDFNTS ; LOAD IN ALT CHAR SETS + JSR INITPAG ; INIT PAGING AND LOAD IN GAME + + LDA #CLS ; GET RID OF "LOADING" MSG + JSR CHROUT + + LDA TCHARS+HI + ORA TCHARS+LO + BEQ TCHj ; no tchars table + + LDY #$FF ; CHECK IF $FF IS IN TCHARS TBL +TCHLP: INY + LDA (TCHARS),Y + BEQ TCHj ; NULL TERMINATED STRING + CMP #$FF + BNE TCHLP + LDA #1 + STA ALLFLG ; YES, SET ALL FCN KEYS (>127) TO TERMINATORS +TCHj: + LDX #CMSG + LDY #CMSGL + JSR DLINE + JSR GETYES + BCS OVERC ; NO, NO COLOR PLEASE +CON: + LDA ZBEGIN+ZMODE + ORA #%00000001 + STA ZBEGIN+ZMODE +OVERC: + LDA ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE + STA ZPCM ; MSB + LDA ZBEGIN+ZGO+1 ; AND LSB + STA ZPCL ; HIGH BIT ALREADY ZEROED + JSR VLDZPC ; MAKE ZPC VALID + + LDX WWIDTH + STX XSIZE + STX OLDWD ; JIC + + ; SET THE FUNCTION KEYS (1-9 AND HELP IS 10) TO RETURN XZIP VALUE + ; INSTEAD OF THE STRINGS FROM BASIC (HELP, RUN, DLOAD...) + + LDA #1 + STA I ; START WITH FCN KEY 1 + +LOOP: LDA #FCNKEY + ADC #0 ; PICK UP CARRY IF THERE + STA $FB + LDA #1 ; AND BASIC BANK REPRESENTATION + STA $FC ; USE BANK 1 AS THIS XZIP IS IN BANK 1 + + LDA #$FA + LDX I ; FCN KEY # + LDY #$01 ; # OF CHARS IN STRING + JSR SETFCN ; AND CALL FCN THAT RESETS FCN KEY RETURN + + INC I + LDA I + CMP #11 + BNE LOOP ; USE 9 FCN KEYS, MAKE RUN/STOP JUST BEEP + + LDA PSTAT ; CHECK IF RESTART & WERE PRINTING + CMP #1 + BNE EX2 ; NO + STA SCRIPTF ; YES, TURN SCRIPT FLAG ON + ORA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO + STA ZBEGIN+ZSCRIP+1 + +EX2: LDA #CLS ; CLEAR SCREEN ... + JSR CHROUT + + ; ... AND FALL INTO MAIN LOOP + + END + \ No newline at end of file diff --git a/c-128/xzip/x.bat b/c-128/xzip/x.bat new file mode 100644 index 0000000..2f981b6 --- /dev/null +++ b/c-128/xzip/x.bat @@ -0,0 +1,18 @@ +ECHO OFF +ECHO THIS BATCH FILE ASSEMBLES XZIP.ASM +ECHO ERRORS ONLY WILL BE IN XZIP.LST +ECHO IF NO ERRORS, XZIP.BIN WILL BE CREATED + +\6502\2500AD_X\X6502 BOOT -ED +\6502\2500AD_X\LINK -Q -C BOOT -X +\6502\2500AD_X\X6502 XZIP -ED +\6502\2500AD_X\LINK -Q -C XZIP -X +\6502\SPLIT\SPL XZIP.TSK 1024 1536 4608 +COPY BOOT.TSK/B+XZIP.BIN/B XZIP.FIN +DEL XZIP.BIN +REN XZIP.FIN XZIP.BIN + +BASICA LMSG + LDY #LMSGL + JSR DLINE + +FILL: JSR DECJ ; C=0 IF [J] GOES LT 0 + BCC FILLED + + LDA #'*' ; show slow progress + JSR CHROUT + + LDA #>IOBUFF + STA DBUFF+HI ; FAKE GETDSK OUT + JSR GETDSK + BCC FILL0 + JMP DSKERR ; OH SHIT +FILLED: + LDA L+LO ; see if we can fit i-save + CMP XEXIST ; if another bank is there, use it + BCS NOISAVE ; nope, no room + LDA XEXIST ; get save bank + STA ISRBANK ; save it + DEC XEXIST ; mark this one as unavailable +NOISAVE: + LDA #1 + STA RESFLG ; SET RESTART FLAG ON FOR XRAM LOAD + RTS + +FILL0: LDY I+HI ; PAGE + LDX L+LO ; BANK + LDA #XWRITE ; show we want to write + JSR EXIO ; and go get it + + INC I+HI ; NEXT PAGE + BNE FILL + INC L+LO ; NEXT BANK + JMP FILL + +LMSG: DB EOL,EOL,"Side 2 being loaded into expansion ram" + DB EOL,EOL,"This will take about 5 minutes." + DB EOL +LMSGL EQU $-LMSG + + +;DECJ RETURNS C=0 WHEN J=$FFFF + +DECJ: LDA J+LO + SEC + SBC #1 + STA J+LO + LDA J+HI + SBC #0 + STA J+HI + RTS + + +; MAKE [MPCPNT],[MPCBNK] POINT TO +; THE RAM PAGE AND BANK THAT HOLDS +; THE V-PAGE MPCH,M +; +VLDMPC: LDA MPCH + BNE VLD1 ;NOT IN FIRST V-64K + LDA MPCM + CMP #VAUX ;IS IT A PAGE IN MAIN + BCS VLD2 ;NO, IT IS IN AUX + + ADC #>ZBEGIN ;ADD OFFSET TO GET RAM PAGE + LDY #MAIN + JMP VLDEXI ;JMP +VLD1: + CMP #1 ;BETWEEN 64K AND 128K ? + BNE VLD3 ;NO, ABOVE 128K + + LDA MPCM + CMP #ZBEGIN ;ADD OFFSET TO GET RAM PAGE +VLDZ0: LDY #MAIN + JMP VLDZEXI ;JMP + +VLDZ1: CMP #1 ;BETWEEN 64K AND 128K ? + BNE VLDZ3 ;NO, ABOVE 128K + LDA ZPCM + CMP #(DBLOCK) + ; FROM DISK & PUT IN PAGING BUFFER [X] (MUST BE MADE ABSOLUTE) + +GETVPAGE: + STA DBLOCK+HI + STY DBLOCK+LO + TXA ; OFFSET INTO CORRECT RAM PAGE + CLC + ADC #PBEGIN ; MAKE ABSOLUTE + STA DBUFF+HI + LDX #AUX ; SET FLAG + STX DSKBNK + + LDA XEXIST ; IF XRAM EXISTS, IT'S ALL IN THERE + BNE GETXPAGE ; SO GET IT FROM THERE + + JSR GETDSK + BCC T2 + JMP DSKERR ; COULDN'T READ DISK +GETXPAGE: + LDA DBLOCK+LO + SEC ; SIDE 2, SO SUBTRACT OFF PRELOAD + SBC #PRELOAD ; PICK UP CARRY + TAX + PLA ; [Y] = LOW, [X] = HIGH + TAY + + LDA #XREAD ; to read the info + JSR EXIO ; and go get, boys + + JMP GOT + +; PREV(A)=Y +; PREV(NEXT(Y))=A +; NEXT(A)=NEXT(Y) +; NEXT(Y)=A + + ; INSERT A BEFORE Y + +INSERT: STA ATEMP + STY YTEMP + TAX + TYA + STA PREVPNT,X + + LDA NEXTPNT,Y + STA NSUBY + TXA + LDX NSUBY + STA PREVPNT,X + + TXA + LDX ATEMP + STA NEXTPNT,X + + LDA ATEMP + STA NEXTPNT,Y + RTS + + +; DETATCH BUFFER [A] +; NEXT(PREV(A))=NEXT(A) +; PREV(NEXT(A))=PREV(A) + +DETATCH: TAX + LDA NEXTPNT,X + STA NSUBA + LDA PREVPNT,X + STA PSUBA + TAX + LDA NSUBA + STA NEXTPNT,X + LDA PSUBA + LDX NSUBA + STA PREVPNT,X + RTS + + +; RETURN BUFFER OF PAGE [WANTED] +; IN [A] ELSE SEC (Y=WANTED+LO) +; (CHECKING FOR PAGED BUFFER ALREADY RESIDENT) + +WHERE: LDX #NUMBUFS-1 +WHLOOP: + LDA WANTED+HI + CMP VPAGEH,X ;HIGH SAME + BEQ WHGOT +WHNOGOT: + DEX + BPL WHLOOP + SEC + RTS +WHGOT: + TYA + CMP VPAGEL,X + BNE WHNOGOT + TXA + CLC + RTS + + + ; SETS UP PAGING SYSTEM - CALLED FROM WARM (?, COLD ?) + +INITPAG: LDX #NUMBUFS-1 + STX CURRENT + LDA #$FF +INILP: + STA VPAGEH,X + DEX + BPL INILP + LDX #0 + LDY #1 +INILP2: + TYA + STA PREVPNT,X + INX + INY + CPX #NUMBUFS + BCC INILP2 + LDA #00 + DEX + STA PREVPNT,X + LDX #0 + LDY #$FF + LDA #NUMBUFS-1 +INILP3: + STA NEXTPNT,X + INX + INY + TYA + CPX #NUMBUFS + BCC INILP3 + + JMP GETSIDE1 + +; TAKE CARE OF CROSSING A PAGE + +CRSMPC: + PHA + INC MPCM + BNE CRS1 + INC MPCH +CRS1: JSR VLDMPC + PLA + RTS + +;SAME AS CRSMPC + +CRSZPC: + PHA + INC ZPCM + BNE CRSZ1 + INC ZPCH +CRSZ1: JSR VLDZPC + PLA + RTS + +;; +;; THIS IS RAM EXPANSION STUFF +;; + ; CHECK IF THERE IS EXPANSION RAM ON THIS MACHINE + ; while your at it, count how many banks there are! +MEMCHK: + LDA #0 + STA XEXIST ; SET TO NO + +MEMLOOP: + LDX XEXIST ; BANK # + LDA #$55 ; FIRST CHECK IF MACHINE HAS XRAM + JSR CHKX + BCS MEMXNO + INC XEXIST ; point to next one + LDA XEXIST ; get it + AND #$08 ; only bits 0-2 are significant + BEQ MEMLOOP +MEMXNO: + LDA XEXIST ; see if any there + CMP #3 ; is it at least 3 banks worth? + BCC NOEX ; nope, no (or not enough) expansion ram + DEC XEXIST ; point to last one + RTS ; and end it +NOEX: + LDA #0 ; so make sure it is zero + STA XEXIST ; so we don't use it + RTS ; so long, and thanks for the fish + + ; CHECK FOR THE PRESENCE OF EXPANSION RAM + ; SET ALL THE FLAGS WRITE & SEE IF READ BACK WHAT WROTE + +CHKX: STX L+LO ; SAVE BANK TO TEST FOR THIS TIME + STA IOCHAR ; HOLD FOR CMP + LDY #$E0 ; only check 32 chars +CLOOP1: STA IOBUFF,Y + INY + BNE CLOOP1 + + LDA #XWRITE ; write to expansion + LDX L+LO ; this bank + LDY #0 ; and always just do page 0 + JSR EXIO ; and go to it + + LDA #0 ; CLEAR IOBUFF BEFORE READ + LDY #$E0 ; SO SURE IT GETS DONE +CLOOP2: STA IOBUFF,Y + INY + BNE CLOOP2 + + LDA #XREAD ; now see if it is there + LDX L+LO + LDY #0 + JSR EXIO + + LDA IOCHAR ; SEE IF READ BACK RIGHT THING + LDY #$E0 +CLOOP3: CMP IOBUFF,Y + BNE CNOX + INY + BNE CLOOP3 + CLC + RTS +CNOX: SEC ; NOT THERE + RTS + +; +; DOISAVE - write stuff to ex-mem save bank +; +DOISAVE: + LDY #0 ; MOVE PAGE AT [DBUFF] +DOIC: LDA (DBUFF),Y ; INTO + STA IOBUFF,Y ; [IOBUFF] FOR I/O + INY + BNE DOIC + + LDX ISRBANK ; get bank and + LDY ISRPAGE ; page + LDA #XWRITE ; show writing it + JSR EXIO ; and do it + + INC ISRPAGE ; show next page + INC DBUFF+HI ; point to next page + RTS ; goodbye, sweet maiden + +; +; DOIRES - get save stuff from ex-mem save bank +; +DOIRES: + LDX ISRBANK ; get bank and + LDY ISRPAGE ; page + LDA #XREAD ; show we want to read + JSR EXIO ; and do it + + LDY #0 ; MOVE PAGE AT [IOBUFF] +DOIRC: + LDA IOBUFF,Y ; TO + STA (DBUFF),Y ; DBUFF + INY + BNE DOIRC + + INC ISRPAGE ; show next page + INC DBUFF+HI ; and next mem loc + RTS ; goodbye, sweet maiden + + PAGE + + END + \ No newline at end of file diff --git a/c-128/xzip/xzip.asm b/c-128/xzip/xzip.asm new file mode 100644 index 0000000..95d9ed2 --- /dev/null +++ b/c-128/xzip/xzip.asm @@ -0,0 +1,130 @@ + + TITLE "EZIP/6502-C INFOCOM, INC. --- EQUATES" + + ; -------------------------- + ; XZIP/6502 VERSION A + ; Z-CODE INTERPRETER PROGRAM + ; FOR COMMODORE 128 + ; -------------------------- + + ; INFOCOM, INC. + ; 125 CAMBRIDGEPARK DRIVE + ; CAMBRIDGE, MA 02140 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + + LLCHAR ? + PL 58 ; PAGE LENGTH OF PRINTER + +ZEROPG EQU $03 ; START OF FREE Z-PAGE RAM +ZPGTOP EQU $8F ; END OF FREE Z-PAGE RAM + +DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER (1=YES,0=NO) + + ; ----------- + ; 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 -- PRELOAD/IMPURE TOO LARGE + ; 14 -- DRIVE ACCESS + ; 15 -- Z-STACK DESTROYED + ; 16 -- NOT AN EZIP GAME + ; 17 -- BAD FONT FOUND + + ; NOTE: DISK ACCESS IS SET SO THAT SIDE 1 STARTS ON TRACK 3 + ; SIDE 2 ON TRACK 1 AND SAVES STARTING ON TRACK 1. THIS IS IN + ; THE CODE IN ZDOS.ASM (APPEARS NOWHERE ELSE 3/18/86 LE) + +VERSID EQU 'K' ; VERSION OF INTERPRETER +; +; A - Initial Released Version +; +; B - Combined c64/c128 version +; Mostly, just remember to skip Tr20, Sect0 because of FASTCODE +; +; C - jdarnold 10/5/87 +; Fix some scrolling problems in CRLF +; +; D - jdarnold 10/7/87 +; Don't allow function keys unless they are terminators +; +; E - jdarnold 10/14/87 +; Don't clear the screen before asking for SIDE X of disk +; +; F - jdarnold 11/17/87 +; Make SCR width == HWRD (i.e. both 79) +; Don't do wrapping in Screen 1 +; Save X Pos as LENGTH in CurSet +; If reverse video and a goes out, then turn it back on +; (as the C128 turns it off after a ) +; Don't update LENGTH counter if in Window 1 +; +; G - jdarnold 12/1/87 +; Make for maximum of 9 saves, thank you +; +; H - jdarnold 12/14/87 +; Don't clear buff if in window 0 in PRNTT +; Call COUT instead of unbuffered output in PRNTT +; Don't clear buff when turning off screen +; +; I - jdarnold 2/17/88 +; Make sure we have at least 3 expansion RAM banks in MEMCHK +; +; J - jdarnold 2/24/88 +; Don't let XEXIST get greater than 8 +; +; K - jdarnold 3/1/88 +; Make SRHOLD be a word, not a byte +; + INCLUDE EQ.ASM + + TITLE "XZIP/6502-C128 INFOCOM, INC. --- MACHINE DEPENDENT INIT" + INCLUDE HARDEQ.ASM + INCLUDE MEMORY.ASM + INCLUDE COLD.ASM + + TITLE "XZIP/6502-C128 INFOCOM, INC. --- INIT & MAINLINE" + INCLUDE WARM.ASM + INCLUDE MAIN.ASM + INCLUDE SUBS.ASM + INCLUDE DISPATCH.ASM + + TITLE "XZIP/6502-C128 INFOCOM, INC. --- OPCODE EXECUTORS" + INCLUDE OPS012.ASM + INCLUDE OPSX.ASM + INCLUDE READ.ASM + + TITLE "XZIP/6502-C128 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT" + INCLUDE XPAGING.ASM + INCLUDE ZSTRING.ASM + INCLUDE OBJECTS.ASM + + TITLE "XZIP/6502-C128 INFOCOM, INC. --- MACHINE DEPENDENT I/O" + + INCLUDE IO.ASM + INCLUDE MACHINE.ASM + INCLUDE ZDOS.ASM + INCLUDE DISK.ASM + + IF DEBUG + INCLUDE BUGGER.ASM + ENDIF + + STTL "END ADDR OF INTERPRETER" + + END + + \ No newline at end of file diff --git a/c-128/xzip/zdos.asm b/c-128/xzip/zdos.asm new file mode 100644 index 0000000..bbe6da4 --- /dev/null +++ b/c-128/xzip/zdos.asm @@ -0,0 +1,1059 @@ + PAGE + STTL "--- Z-DOS: CBM64 ---" + + + ; --------------------- + ; GET Z-BLOCK FROM DISK + ; --------------------- + + ; ENTRY: Z-BLOCK # IN [BLOCK] + ; TARGET PAGE IN [DBUFF+HI] + + ; NOTE: USING VARIABLE SECTORS PER TRACK TO GET 170K ON DISK + +GETDSK: LDA #8 + STA DRIVE ; GAME ALWAYS PLAYS FROM DRIVE #8 + + LDA DBLOCK+HI + CMP ZPURE+HI ; check for on side 1 + BCC GETSD1 ; OK, SIDE1 + BNE SID2 + LDA DBLOCK+LO + CMP ZPURE+LO + BCC GETSD1 + +SID2: LDA SIDEFLG ; ON SIDE 2? + CMP #2 + BEQ GETSD2 ; YES + JSR SIDE2 ; NO, ASK FOR IT + +GETSD2: LDA DBLOCK+LO + SEC ; SIDE 2, SO SUBTRACT SIDE 1 + SBC ZPURE+LO ; AMOUNT SO GET ACCURATE + PHA ; CALCULATION OF TRACK & SECTOR + LDA DBLOCK+HI + SBC ZPURE+HI + TAX + PLA + LDY #1 ; SIDE 2 STARTS ON TRACK 1 + JSR SETTS ; SET TRACK & SECTOR + JMP GETRES ; AND GO READ + +GETSD1: LDA SIDEFLG ; ARE WE ON SIDE 1 + CMP #1 + BEQ SID1 + JSR SIDE1 + +SID1: LDA DBLOCK+LO + LDX DBLOCK+HI + LDY #5 ; SIDE 1 STARTS ON TRACK 5 (XZIP) + JSR SETTS ; GO GET TRACK & SECTOR + JMP GETRES ; AND GO READ THE DISK + + + ; SET TRACK & SECTOR FROM A,X DBLOCK (A=LO) Y = STARTING TRACK + +SETTS: STY TRACK + DEY + +TRKLP: CMP TRKTBL,Y ; CHECK IF REMAINDER LESS + BCS DOIT ; THAN 1 TRACK + CPX #0 + BEQ TRKDUN ; YES + +DOIT: SEC ; SUBTRACT ANOTHER TRACKS WORTH + SBC TRKTBL,Y ; FROM THE SECTORS PER TRACK TABLE + BCS TRK1 + DEX ; BORROWED +TRK1: INC TRACK + INY ; NEXT TRACK IN TABLE + BNE TRKLP ; JMP + +TRKDUN: STA SECTOR + LDA TRACK + CMP #18 ; IF ON TRACK 18, SKIP OVER 1ST SECTOR + BNE NOT18 + INC SECTOR + BNE TRKOVR +NOT18: ; check for sector 20 + CMP #20 ; for fast code stuff + BNE TRKOVR + INC SECTOR ; so skip over sector 0 +TRKOVR: + RTS + +; +; skip over Track 20, Sector 0 in case of fast code +; +TRKTBL: DB 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21 + DB 18,19,18,19,19,19,19 + DB 18,18,18,18,18,18 + DB 17,17,17,17,17 + + ; *** ERROR #12: DISK ADDRESS OUT OF RANGE *** + +TRKERR: LDA #12 + JMP ZERROR + + ; *** ERROR #14: DRIVE ACCESS *** + +DSKERR: LDA #14 + JMP ZERROR + + + + ; -------------------- + ; PUT [DBLOCK] TO DISK + ; -------------------- + + ; ENTRY: [DBLOCK] & [DRIVE] ASSIGNED + ; PAGE TO WRITE IN [DBUFF] + + ; NOTE: AS THIS ONLY WRITES FROM MAIN BANK (BANK1) + ; CAN HAVE UP HERE + +PUTDSK: LDY #0 ; MOVE PAGE AT [DBUFF] +PTKL: LDA (DBUFF),Y ; INTO + STA IOBUFF,Y ; [IOBUFF] FOR I/O + INY + BNE PTKL + + SEC ; CARRY SET = "WRITE BLOCK" + JSR DISK + BCS WRTERR ; CARRY SET IF ERROR + + INC DBUFF+HI ; NEXT MEMORY PAGE + +NXTDBL: INC DBLOCK+LO ; POINT TO NEXT VIRTUAL PAGE + BNE DBLOK + INC DBLOCK+HI +DBLOK: INC SECTOR ; NEXT SECTOR + LDY TRACK ; CHECK IF NEXT TRACK + DEY + LDA SECTOR + CMP TRKTBL,Y + BCC SECTOK + INC TRACK ; YES, RESET + LDA #0 + STA SECTOR + LDA TRACK + CMP #18 + BNE DNOT18 + INC SECTOR ; SKIP 1ST SECTOR TRACK 18 (DIRECTORY) + BNE SECTOK +DNOT18: ; check for sector 20 + CMP #20 ; for fast code stuff + BNE SECTOK + INC SECTOR ; so skip over sector 0 +SECTOK: CLC + +WRTERR: RTS + + + ; -------------------- + ; PROMPT FOR GAME DISK + ; -------------------- + + ; EZIP USES BOTH SIDES OF DISK + +GAME: DB EOL + DB "Insert Side " +DSIDE: DB "* of the STORY disk into Drive #8." ; (CBD) + DB EOL +GAMEL EQU $-GAME +SD: DB "INFOCOM-S" ; (CBD) + +SIDE1: LDA #'1' ; ASK FOR SIDE 1 + STA DSIDE + LDA #1 ; SET FOR SUCCESS + STA SIDEFLG +SL1: LDX #GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + LDX #0 ; READ DIRECTORY + STX SECTOR ; (CBD) MUST BE "INFOCOM-S1" + LDX #$12 ; (CBD) + STX TRACK + + LDA #8 ; MAKE SURE WE'RE ON + STA DRIVE ; THE GAME DRIVE + JSR DOPEN + + CLC ; CARRY CLEAR = "READ BLOCK" + JSR DISK ; GO DO IT! + BCC SL3 + JMP DSKERR ; ERROR IF CARRY SET + +SL3: LDY #$99 ; (CBD) OFFSET IN DIRECTORY SECTOR + LDX #9 ; (CBD) + LDA #"1" ; (CBD) + BNE SL8 ; (CBD) +SL7: LDA SD,X ; (CBD) "INFOCOM-S1" +SL8: CMP IOBUFF,Y ; (CBD) DIR ENTRY CORRECT? + BNE SL1 ; (CBD) NO, GO ASK AGAIN + DEY ; (CBD) + DEX ; (CBD) + BPL SL7 ; (CBD) + BMI ASK2 ; (CBD) JUMP, GOOD + + +SIDE2: + LDA SIDEFLG ; see if we are on side 2 + CMP #2 ; well? + BNE SD2 ; nope + JMP ASK2 ; done then +SD2: + LDA #'2' ; ASK FOR SIDE 2 + STA DSIDE + LDA #2 + STA SIDEFLG ; SET FOR SUCCESS + LDA DRIVE ; GET LAST DRIVE USED + PHA ; HOLD IT A SEC + LDA #8 ; MAKE SURE WE'RE ON + STA DRIVE ; THE BOOT DRIVE + JSR DOPEN + PLA ; IF SAVED/RESTORED + CMP #9 ; TO DRIVE 2, DON'T ASK + BEQ ASK2 ; NOTE: THIS IS OK W/ VERIFY CAUSE ASKS + ; FOR SIDE 1 FIRST, RESETTING DRIVE TO 1 + +SL2: LDX #GAME + LDY #GAMEL + JSR DLINE ; "INSERT STORY DISK" + JSR RETURN ; "PRESS [RETURN] TO CONTINUE:" + + LDX #0 ; READ DIRECTORY + STX SECTOR ; (CBD) MUST BE "INFOCOM-S2" + LDX #$12 + STX TRACK + CLC + JSR DISK + BCC SL4 + JMP SL2 ; BAD READ, GO ASK AGAIN + +SL4: LDY #$99 ; (CBD) OFFSET IN DIRECTORY SECTOR + LDX #9 ; (CBD) + LDA #"2" ; (CBD) + BNE SL6 ; (CBD) +SL5: LDA SD,X ; (CBD) +SL6: CMP IOBUFF,Y ; (CBD) DIR ENTRY CORRECT? + BNE SL2 ; NO, GO ASK AGAIN + DEY + DEX + BPL SL5 + +ASK2: LDA #$FF ; RE-ENABLE + STA SCRIPT ; SCRIPTING + RTS + + + ; ----------------------------- + ; SET UP SAVE & RESTORE SCREENS + ; ----------------------------- + +SAVRES: JSR ZCRLF ; CLEAR THE BUFFER + LDX #0 + STX SCRIPT ; DISABLE SCRIPTING + LDA TOP ; SET TO REFILL SCREEN + STA LINCNT + RTS + + ; ----------------- + ; DISPLAY A DEFAULT + ; ----------------- + + ; ENTRY: DEFAULT (0-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 #DEFAL + LDY #DEFALL + JMP DLINE ; PRINT THE STRING + + + ; ----------------------------- + ; GET SAVE & RESTORE PARAMETERS + ; ----------------------------- + +POSIT: DB EOL + DB "Position 1-" +POSTOP: DB "*" +POSITL EQU $-POSIT + +WDRIV: DB EOL + DB "Drive 8 or 9" +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 #POSIT + LDY #POSITL + JSR DLINE ; "POSITION (1-5)" + + ; GET GAME POSITION + +CHANGE: 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 NUMSAV ; IF BELOW "6" + 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 LETTER ; AND DISPLAY IT + + ; GET DRIVE ID + + LDX #WDRIV + LDY #WDRIVL + JSR DLINE ; "DRIVE 8 OR 9" + + LDA GDRIVE ; SHOW DEFAULT + CLC ; CONVERT 0 OR 1 + ADC #7 ; TO 7 OR 8 + JSR DODEF ; SO DEFAULT WILL BE CORRECT + +GETDRV: JSR GETKEY ; GET A KEYPRESS + CMP #EOL ; IF [RETURN], + BEQ DRVSET ; USE DEFAULT + SEC + SBC #'8' ; 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 #'8' ; CONVERT TO ASCII 8 OR 9 + STA SAVDRI ; STORE IN DRIVE STRING + STA MDRI ; AND IN TEMP STRING + JSR LETTER ; AND SHOW NEW SETTING + + LDX #MIND + LDY #MINDL + JSR DLINE + + JSR GETYES + BCC ALLSET ; YES + RTS ; carry set, means it didn't work + + ; GET DISK AND MAKE SURE IT'S ACCESSIBLE + +ALLSET: LDX #INSM + LDY #INSML + JSR DLINE ; "INSERT SAVE DISK IN DRIVE X." + JSR RETURN ; "PRESS [RETURN] TO CONTINUE." + +TRYOPN: + LDA #$FF ; show bad side + STA SIDEFLG + LDA TDRIVE ; TRY TO OPEN SPECIFIED DRIVE + CLC + ADC #8 + JSR DOPEN ; THE DEFAULT DRIVE + RTS ; CARRY SET IF ERROR + + ; ------ + ; GETYES + ; ------ + + ; CALLED BY PARAMS AND WARM + +GETYES: JSR GETKEY + + CMP #'Y' ; IF REPLY IS "Y" + BEQ YUP ; ACCEPT RESPONSES + CMP #'y' + BEQ YUP + + CMP #'N' ; IF REPLY IS N, + BEQ RETRY ; DO A RETRY + CMP #'n' + BEQ RETRY + + JSR BOOP ; INSIST ON Y/RETURN + JMP GETYES ; OR N + +RETRY: LDX #NO + LDY #NOL + JSR DLINE + SEC + RTS + +YUP: LDX #YES + LDY #YESL + JSR DLINE + CLC + RTS + + + ; -------------------------------- + ; SET START SECTOR OF SAVE/RESTORE + ; -------------------------------- + + ; THERE IS A BIT OF INFORMATION ON THE LAST SECTOR OF SAVE DISKS - + ; THE WORD "INFOSAVES " AND THE SIZE OF A SAVE TO USE IN THE + ; CALCULATION OF THE STARTING LOCATION OF EACH OF THE SAVES ON + ; THAT DISK, THIS IS USED FOR PARTIAL RESTORES, BECAUSE PARTIAL + ; SAVES MAY BE RESTORED INTO A DIFFERENT GAME AND THAT GAME MAY + ; ALLOW A DIFFERENT NUMBER OF SAVES. IN ORDER TO FIND THE START OF + ; THE PARTIAL RESTORE THE SIZE OF SAVES ON THE SAVE DISK IS TAKEN + ; FROM THE DISK AND USED FOR A PARTIAL RESTORE. IN ORDER THAT PART + ; OF THOSE RESTORES ARE NOT OVERWRITTEN WITH DIFFERENT ALIGNMENT + ; ONLY BLANK DISKS OR DISKS WITH THE SAME SAVE SIZE MAY BE USED + ; FOR NEW SAVES. BLANK DISKS ARE MARKED WITH THE INFOSAVES INFO + ; ON FIRST USE + + +SAVSTRT: JSR CHKINF ; CHECK IF DISK OK + BCS SBLANK ; BLANK MEANS NEW DISK + + LDX #INFML ; GET OFFSET OF SIZE BYTE + LDA IOBUFF,X ; AND PICK IT UP FROM BUFFER + CMP SAVSIZ + BEQ SIZOK ; SAME SIZE, JUST USE DISK + + ;ASK IF WANT TO USE, WILL OVERWRITE ANYTHING ON DISK + +REUSE: LDX #STILL + LDY #STILLL + JSR DLINE + JSR GETYES + BCC SBLANK ; YES + RTS ; NO, RET CARRY SET + +SBLANK: LDA #LASTT + STA TRACK + LDA #LASTS + STA SECTOR + LDX #INFML-1 ; MOVE IN "INFOSAVES " +BLOOP: LDA INFM,X + STA IOBUFF,X + DEX + BPL BLOOP + LDA SAVSIZ + LDX #INFML + STA IOBUFF,X + + SEC ; WRITE INFO SECTOR TO DISK + JSR DISK + BCS RET ; CARRY SET IF ERROR + +SIZOK: LDA SAVSIZ + JSR SETSTRT ; SET STARTING SECTOR FOR THIS SAVE + CLC +RET: RTS + + + ; NUMBER OF SECTORS REQUIRED FOR SAVE IN [A] + ; FINDS STARTING TRACK & SECTOR FOR CURRENT POSITION + +SETSTRT: STA IOCHAR ; BORROW THIS SPACE + LDA #0 ; SET FOR POSITION 1 + STA DBLOCK+LO + STA DBLOCK+HI + + LDX TPOSIT ; GET # OF SAVES IN TO MOVE + BEQ FINDTS +CALC: CLC ; AND FIND WHAT SECTOR TO START WITH + ADC IOCHAR ; MAY BE GAME SIZE OR PARTIAL RESTORE SIZE + BCC CALC1 + INC DBLOCK+HI +CALC1: DEX + BNE CALC + STA DBLOCK+LO ; IN THE FORM OF DBLOCKS + +FINDTS: LDA DBLOCK+LO + LDX DBLOCK+HI + LDY #1 + JSR SETTS ; GET TRACK & SECTOR + RTS + + + ; THIS RTN LOOKS FOR "INFOSAVES " ON (ASSUMED) SAVE DISK + ; IF NOT THERE RTNS BAD - NO SAVES ON DISK + ; IF THERE SETS UP TRACK & SECTOR FOR THE RESTORE + ; USES SAVE SIZE ON DISK, FULL OR PARTIAL SAVE SHOULD BE CORRECT + ; SIZE + +RESSTRT: JSR CHKINF ; CHECK IF DISK OK + BCC SETRES ; IF NO "INFOSAVES " NO SAVES ON THIS DISK + RTS ; RET WITH CARRY SET + +SETRES: LDX #INFML ; GET OFFSET OF SIZE BYTE + LDA IOBUFF,X ; AND PICK IT UP FROM BUFFER + JSR SETSTRT + CLC + RTS + + + ; THIS RTN LOOKS AT THE LAST SECTOR OF (ASSUMED) SAVE DISK + ; AND RTNS WHETHER "INFOSAVES " IS ON IT (C = 0) OR NOT (C = 1) + +CHKINF: LDA #LASTT + STA TRACK + LDA #LASTS + STA SECTOR + LDA #>IOBUFF ; READ LAST SECTOR ON SAVE DISK + STA DBUFF+HI + JSR GETRES + LDX #INFML-1 ; CHECK FOR "INFOSAVES" +CHKLP: LDA IOBUFF,X + CMP INFM,X + BNE NOTINF + DEX + BPL CHKLP + CLC + RTS +NOTINF: SEC + RTS + +INFM: DB "INFOSAVES " +INFML EQU $-INFM + +STILL: DB EOL + DB "USING THIS DISK WILL DESTROY PREVIOUS SAVES ON THIS DISK." + DB EOL + DB "DO YOU STILL WISH TO USE THIS DISK? (Y/N) " +STILLL EQU $-STILL + + + ; --------------------- + ; "PRESS RETURN" PROMPT + ; --------------------- + +RETURN: LDX #RTN + LDY #RTNL + JSR DLINE ; SHOW PROMPT + + ; ENTRY FOR QUIT/RESTART + +GETRET: JSR GETIN ; WAIT FOR [RETURN] + CMP #0 + BEQ GETRET ; GET A CHAR 1ST + AND #%01111111 ; CLEAR SHIFT + CMP #EOL + BEQ RETEX + JSR BOOP ; ACCEPT NO + JMP GETRET ; SUBSTITUTES! + +RETEX: RTS + +RTN: DB EOL + DB "Press [RETURN] to continue." + DB EOL,EOL +RTNL EQU $-RTN + + + ; --------- + ; SAVE GAME + ; --------- + +SAV: DB "Save Position" + DB EOL +SAVL EQU $-SAV + +SVING: DB EOL + DB "Saving position " +SVPOS: DB "* ..." + DB EOL +SVINGL EQU $-SVING + + +ZSAVE: LDA #'N' + LDX NARGS + BEQ OLDSAV ; NORMAL, COMPLETE SAVE + LDA #'P' +OLDSAV: STA TYPE + + JSR SAVRES ; SET UP SCREEN + LDX #SAV + LDY #SAVL + JSR DLINE ; "SAVE POSITION" + + JSR PARAMS ; GET PARAMETERS + BCC DOSAVE ; ERROR IF CARRY SET +BADSAV: + JSR SIDE2 ; PROMPT FOR GAME DISK + JMP RET0 ; AND FAIL + +DOSAVE: LDX #SVING + LDY #SVINGL + JSR DLINE ; "SAVING POSITION X ..." + + JSR SAVSTRT ; READ/MAKE DIRECTORY FOR PARTIAL SAV/RES'S + BCS BADSAV ; OOPS + + JSR SAVGUTS ; do all the work here + + JSR SIDE2 ; PROMPT FOR GAME DISK + LDA TDRIVE ; IF SAVE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TPOSIT + STA GPOSIT + LDA #1 ; SET TO MARK + LDX #0 + JMP PUTBYT ; SUCCESS + +SAVGUTS: + ; 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+LO ; MOVE [ZSP] + STA BUFSAV+2 + LDA ZSP+HI + STA BUFSAV+3 + LDA OLDZSP+LO + STA BUFSAV+4 + LDA OLDZSP+HI ; MOVE [OLDZSP] + STA BUFSAV+5 + + LDX #2 ; MOVE CONTENTS OF [ZPC] +ZPCSAV: LDA ZPC,X ; TO BYTES 5-7 + STA BUFSAV+6,X ; OF [BUFSAV] + DEX + BPL ZPCSAV + + LDA TYPE + STA BUFSAV+9 ; NORMAL OR PARTIAL + CMP #'P' + BNE ZSNONM ; NORMAL SAVE SO NO name TO SAVE + LDY #0 + LDA (ARG3),Y + TAY ; MOVE NAME TO BUFSAV +ZSL3: LDA (ARG3),Y + STA BUFSAV+10,Y + DEY + BPL ZSL3 ; INCLUDE LENGTH BYTE + + ; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK + +ZSNONM: LDA #>LOCALS + STA DBUFF+HI ; POINT TO THE PAGE + + LDA ISRFLAG ; is it an i-save to ex-mem? + BEQ ZSNOj ; nope + + JSR DOISAVE ; this does it + BNE ZSNOj1 ; always returns <> 0 +ZSNOj: + JSR PUTDSK ; AND WRITE IT OUT + BCS BADSAV ; CATCH WRITE ERROR HERE +ZSNOj1: + ; IF A PARTIAL SAVE WRITE FROM ARG1 FOR ARG2 BYTES TO DISK + ; (ROUNDED TO PGS) SKIPPING ZSTACK WRITE + + LDA TYPE + CMP #'P' + BNE ZSALL + LDA ARG1+HI ; FIND WHERE TO START & HOW FAR TO GO + CLC + ADC ZCODE ; MAKE IT ABSOLUTE + STA DBUFF+HI + LDX ARG2+HI + INX ; TO GET WHOLE OF LAST PG + STX I+LO + JMP LSAVE ; JMP + + ; WRITE CONTENTS OF Z-STACK TO DISK + +ZSALL: LDA #>ZSTKBL ; POINT TO 1ST PAGE + STA DBUFF+HI + LDA #4 ; DO ALL 4 PAGES + STA L ; SET COUNTER +ZSOKLP: + LDA ISRFLAG ; is it an i-save to ex-mem? + BEQ ZSOKj ; nope + + JSR DOISAVE ; this does it + BNE ZSOK ; always returns <> 0 +ZSOKj: + JSR PUTDSK ; WRITE THEM + BCC ZSOK + JMP BADSAV ; OOPS +ZSOK: DEC L + BNE ZSOKLP + + ; 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: + LDA ISRFLAG ; is it an i-save to ex-mem? + BEQ LSVj ; nope + + JSR DOISAVE ; this does it + BNE DECCNT ; always returns <> 0 +LSVj: + JSR PUTDSK + BCC DECCNT + JMP BADSAV +DECCNT: DEC I+LO + BNE LSAVE + RTS ; done with it + + ; ------------ + ; RESTORE GAME + ; ------------ + +RES: DB "Restore Position" + DB EOL +RESL EQU $-RES + +RSING: DB EOL + DB "Restoring position " +RSPOS: DB "* ..." + DB EOL +RSINGL EQU $-RSING + + +ZREST: LDA #'N' + LDX NARGS + BEQ OLDRES ; NORMAL, COMPLETE RESTORE + LDA #'P' +OLDRES: STA TYPE + + JSR SAVRES + LDX #RES + LDY #RESL + JSR DLINE ; "RESTORE POSITION" + + JSR PARAMS ; GET PARAMETERS + BCS BADRES ; ERROR IF CARRY SET + + LDX #RSING + LDY #RSINGL + JSR DLINE ; "RESTORING POSITION X ..." + + JSR RESSTRT ; READ/MAKE DIRECTORY FOR PARTIAL SAV/RES'S + BCS BADRES ; OOPS + + JSR RESGUTS ; do all the real work + + JSR SIDE2 ; PROMPT FOR GAME DISK + LDA TDRIVE ; IF RESTORE SUCCESSFUL + STA GDRIVE ; SAVE PARAMS FOR + LDA TPOSIT ; NEXT TIME + STA GPOSIT + LDA #2 ; SET TO + LDX #0 + JMP PUTBYT ; SUCCESS + +; +; RESGUTS - major grunt work for saving is done here +; +RESGUTS: + LDA TYPE ; PARTIAL SAVE DIFFERS STARTING HERE + CMP #'P' + BNE ZRNRML + JMP ZPARTR + + ; SAVE LOCALS IN CASE OF ERROR + +ZRNRML: LDX #31 +LOCSAV: LDA LOCALS,X ; COPY ALL LOCALS + STA $0100,X ; TO BOTTOM OF MACHINE STACK + DEX + BPL LOCSAV + + LDA #MAIN + STA DSKBNK ; SET TO WRITE TO MAIN BANK + LDA #>LOCALS + STA DBUFF+HI + + LDA ISRFLAG ; internal restore? + BEQ GRj ; nope + + JSR DOIRES ; do the work + BNE GRj1 ; always branch +GRj: + JSR GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + BCS WRONG +GRj1: + 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 INCORRECT SAVE DISK + +WRONG: LDX #31 ; RESTORE ALL SAVED LOCALS +WR0: LDA $0100,X + STA LOCALS,X + DEX + BPL WR0 + +BADRES: JSR SIDE2 ; PROMPT FOR GAME DISK + JMP RET0 ; AND FAIL + + ; CONTINUE RESTORE + +RIGHT: + LDA ZBEGIN+ZSCRIP ; SAVE BOTH FLAG BYTES + STA I+LO + LDA ZBEGIN+ZSCRIP+1 + STA I+HI + + LDA #>ZSTKBL ; RETRIEVE OLD CONTENTS OF + STA DBUFF+HI ; Z-STACK + LDA #4 ; DO 4 PAGES + STA L ; SET COUNTER +ZROKLP: + LDA ISRFLAG ; are we doing i-restore + BEQ ZROKj ; nope + JSR DOIRES ; so do i-restore + BNE ZROKL1 ; always returns <>0 +ZROKj: + JSR GETRES ; GET 4 PAGES OF Z-STACK + BCC ZROKL1 + JMP DSKERR ; IF HERE, MIX OF GOOD & BAD SO DIE + +ZROKL1: DEC L + BNE ZROKLP + + LDA ZCODE + STA DBUFF+HI + + LDA ISRFLAG ; are we doing i-restore + BEQ ZROKLj ; nope + JSR DOIRES ; so do i-restore + BNE ZROKL2 ; always returns <>0 +ZROKLj: + JSR GETRES ; GET 1ST BLOCK OF PRELOAD + BCC ZROKL2 + JMP DSKERR +ZROKL2: + 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: + LDA ISRFLAG ; are we doing i-restore + BEQ LRESTj ; nope + JSR DOIRES ; so do i-restore + BNE LREST0 ; always returns <>0 +LRESTj: + JSR GETRES ; FETCH THE REMAINDER + BCC LREST0 + JMP DSKERR +LREST0: + DEC I+LO ; OF THE PRELOAD + BNE LREST + + ; RESTORE THE STATE OF THE SAVED GAME + + LDA BUFSAV+2 ; RESTORE THE [ZSP] + STA ZSP+LO + LDA BUFSAV+3 + STA ZSP+HI + LDA BUFSAV+4 + STA OLDZSP+LO + LDA BUFSAV+5 ; AND THE [OLDZSP] + STA OLDZSP+HI + + LDX #2 ; RESTORE THE [ZPC] +RESZPC: LDA BUFSAV+6,X + STA ZPC,X + DEX + BPL RESZPC + +ZROUT: + JSR VLDZPC ; MAKE VALID (12-2-86) + RTS + + ; DO PARTIAL RESTORE GETTING 1ST PAGE + ; AND LAST PAGE BYTE ALIGNMENT CORRECT + +ZPARTR: ; WRITE LOCALS TO IOBUFF JUST TO LOOK AT NAME + + LDA #MAIN + STA DSKBNK + LDA #>IOBUFF ; DON'T READ TO LOCALS YET (X) + STA DBUFF+HI + JSR GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD + BCS ZPBAD ; BAD DISK READ IF CARRY CLEAR + + LDY #0 ; ADD ALL OFFSETS TOGETHER TO + LDA (ARG3),Y ; COMPARE PARTIAL NAME (LENGTH) + TAY ; COUNTER + CLC + ADC #IOBUFF ; GET 1ST PAGE + STA DBUFF+HI ; GETRES SHOULD KEEP IN IOBUFF + JSR GETRES + BCC POK + JMP DSKERR ; ALL MESSED UP, JUST QUIT + +POK: LDY ARG1+LO ; START BYTE FIRST PAGE +ZPART0: LDA IOBUFF,Y + STA (I),Y + JSR DECJ + BCC ZROUT ; CARRY CLEAR IF $FFFF RESULT + INY + BNE ZPART0 + + LDA #>IOBUFF ; GET SUBSEQUENT PAGES + STA DBUFF+HI ; GETRES SHOULD KEEP IN IOBUFF + JSR GETRES + BCC POK2 + JMP DSKERR +POK2: LDY #0 + JMP ZPART0 + +ZPBAD: JMP BADRES ; NAMES DON'T MATCH, DIE + + ; THE OLD SAVE & RESTORE STILL HAVE OPCODES + ; SO JUST PUT IN A PLACE FOR THEM HERE FOR NOW + +OSAVE: +OREST: RTS + +ZISAVE: + LDA ISRBANK ; can we do it? + BNE ZIS1 ; no i-saving here + + LDA #$FF ; SET TO + LDX #$FF + JMP PUTBYT ; FAILURE FOREVER +ZIS1: + STA ISRFLAG ; show we are i-saving + LDA #'N' ; make a full save + STA TYPE ; and show savguts + LDA #0 ; start ISRBANK, Page 0 + STA ISRPAGE ; show it to DOISAVE + + JSR SAVGUTS ; save the world + + LDY #0 ; turn off i-saving + STY ISRFLAG ; turned off + INY ; and show we done it + STY ISAVED ; for restore to check + LDA #1 ; SET TO + LDX #0 + JMP PUTBYT ; SUCCESS + +ZIREST: + LDA ISRBANK ; can we do it? + BEQ ZIR0 ; no i-restoring here + LDA ISAVED ; if either are zero then + BEQ ZIR0 ; none can be done + + STA ISRFLAG ; show we are i-saving + LDA #'N' ; make a full save + STA TYPE ; and show savguts + LDA #0 ; start ISRBANK, Page 0 + STA ISRPAGE ; show it to DOIREST + + JSR RESGUTS ; save the world + + LDA #0 ; turn off i-saving + STA ISRFLAG ; turned off + LDA #2 ; SET TO + LDX #0 + JMP PUTBYT ; SUCCESS +ZIR0: + JMP RET0 ; DIDN'T WORK + + END + + \ No newline at end of file diff --git a/c-128/xzip/zstring.asm b/c-128/xzip/zstring.asm new file mode 100644 index 0000000..dfc7c24 --- /dev/null +++ b/c-128/xzip/zstring.asm @@ -0,0 +1,438 @@ + PAGE + STTL "--- 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 + ROL A + STA MPCH + ASL MPCL ; QUAD-ALIGN ADDRESS!(EZIP) + ROL MPCM + ROL MPCH + JMP VLDMPC +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" DB II + TAX ; OTHERWISE USE CODE AS AN INDEX + LDA CHRTBL,X ; INTO THE CHARSET TABLE + JMP SHOVE ; AND PRINT THE CHAR + + ; DECODE A "DIRECT" DB II 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 ; DB II 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 SETFWD ; 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 + JSR VLDMPC + JMP PZTOP ; CONTINUE INNOCENTLY + + +; ---------------------- +; RETURN CURRENT CHARSET +; ---------------------- + +GETSET: LDA TSET + BPL GS + LDA PSET + RTS +GS: LDY #$FF + STY TSET + RTS + + +; ------------------------- +; POINT [I] AT FWORD STRING +; ------------------------- + +SETFWD: LDA I+LO ; WORD-ALIGN THE ADDRESS + ASL A + STA MPCL + LDA I+HI + ROL A + STA MPCM + LDA #0 + ROL A + STA MPCH + JMP VLDMPC + + +; ----------------- +; 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 + LDX #$08 ; WITH PAD CHARS ($05) +CZSL: STA OUT,X + DEX + BPL CZSL + LDA #9 ; 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 DB II 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 9 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" DB II CHAR + + LDA #6 ; DB II 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 + STA OUT+2 ; MOVE CRUSHED Z-WORD + STX OUT+3 ; INTO PLACE + LDA OUT+7 ; GET 8TH Z-CHAR (EZIP) + ASL A ; SHIFT BITS + ASL A + ASL A + ASL A + ROL OUT+6 ; ALONG WITH 7TH Z-CHAR + ASL A + ROL OUT+6 + ORA OUT+8 ; SUPERIMPOSE 9TH Z-CHAR + STA OUT+5 ; SAVE HERE + LDA OUT+6 ; GRAB 7TH Z-CHAR + ORA #%10000000 ; SET HIGH BIT + STA OUT+4 ; MOVE CRUSHED Z-WORD 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 + + \ No newline at end of file diff --git a/colorcomputer/boot.src b/colorcomputer/boot.src new file mode 100644 index 0000000..b2f2278 --- /dev/null +++ b/colorcomputer/boot.src @@ -0,0 +1,390 @@ + + ;------------------------------------------ + ; NEW ZIP LOADER + ; RESIDES ON TRACK 34 OF CO-CO DISK + ; AND IS LOADED BY CO-CO WITH 'DOS' COMMAND + ;------------------------------------------ + + +PIA0 EQU $FF00 +KEYBUF EQU $0152 +CASFLG EQU $011A +DEBVAL EQU $011B + +DEVNUM EQU $6F +BS EQU $08 +SPACE EQU $20 + +IRQVEC EQU $10C +RDYTMR EQU $985 +DCDRV EQU $EB +DRGRAM EQU $986 +DCTRK EQU $EC +DSKREG EQU $FF40 +DCSTA EQU $F0 +DCOPC EQU $EA +DR0TRK EQU $97E +FDCREG EQU $FF48 +ZERO EQU $8A +DSEC EQU $ED +DNMIVC EQU $983 +DCBPT EQU $EE +NMIFLG EQU $982 +SKP2 EQU $8C + +DCB EQU $EA + + +RVEC3 EQU $0167 +CR EQU $0D +VIDRAM EQU $0400 +CURPOS EQU $88 + + ; EQUATES + +BUG EQU 0 +ZSTART EQU $1100 +ZEND EQU $3000+BUG + + + + + ORG $2600 + + + DB "OS" ; REQUIRED BY DOS + +MOVE: LDX #00 ; SET UP TO MOVE BOOT CODE OUT OF WAY OF ZIP +MOVLP: LDD HERE,X + STD THERE,X + LEAX 2,X + CMPX #$800 + BLO MOVLP + JMP RUN + +HERE: EQU $ + + ORG $5000 + +THERE: EQU $ + +RUN: LDX #DIRQSV ;SET VECTOR + STX IRQVEC+1 + LDA #$7E ;JMP OP + STA IRQVEC + + + LDD #$0001 + STD TRACK + LDD #ZSTART + STD BUFFER +LOOP: LDX #DCB + LDD #$0200 + STD ,X + LDD TRACK + STD 2,X + INCB + CMPB #19 + BLO DOBUFF + LDB #1 + INCA +DOBUFF: STD TRACK + LDD BUFFER + STD 4,X + INCA + STD BUFFER + LBSR MYCON + TST 6,X + BNE ERROR + CMPD #ZEND + BLO LOOP + JMP ZSTART + + ;ERROR HANDLER + +ERRM: DB $0D + DB "DISK ERRROR!" + DB $0D +ERRML: EQU $-ERRM + +ERROR: LDX #ERRM + LDB #ERRML +ELOOP: LDA ,X+ + LBSR MYCHR + DECB + BNE ELOOP +FREEZ: BRA FREEZ + +TRACK: DB $00,$00 +BUFFER: DB $00,$00 + +ZZZ: EQU $ + + +;----------------------------------------------------------------------------- +; ROM- ROUTINES + + + ; IRQ HANDLER NEEDED FOR RDYTMR + +DIRQSV: LDA PIA0+3 + BPL DRTI + LDA PIA0+2 + LDA RDYTMR + BEQ DRTI + DECA + STA RDYTMR + BNE DRTI + LDA DRGRAM + ANDA #$B0 + STA DRGRAM + STA DSKREG +DRTI: RTI + + +;POLCAT + + + + +LA7D1: LDX ZERO +LA7D3: LEAX -1,X + BNE LA7D3 + RTS + +;------------------------ +; COPY OF CHROUT FROM ROM +;------------------------ + +; +MYCHR: JSR RVEC3 ;HOOK INTO RAM THE BOOK SAYS (BUT WHY I ASK) + PSHS B + LDB DEVNUM + INCB + PULS B + BMI LA2BF + BNE LA30A +;SEND TO CASSETTE NOT NEEDED + +LA2BF: RTS + +LA30A: PSHS A,B,X + LDX CURPOS + CMPA #BS + BNE LA31D + CMPX #VIDRAM + BEQ LA35D + LDA #$60 + STA ,-X + BRA LA344 +LA31D: CMPA #CR + BNE LA32F + LDX CURPOS +LA323: LDA #$60 + STA ,X+ + TFR X,D + BITB #$1F + BNE LA323 + BRA LA344 +LA32F: CMPA #SPACE + BLO LA35D + TSTA + BMI LA342 + CMPA #$40 + BLO LA340 + CMPA #$60 + BLO LA342 + ANDA #$DF +LA340: EORA #$40 +LA342: STA ,X+ +LA344: STX CURPOS + CMPX #VIDRAM+511 + BLS LA35D + LDX #VIDRAM + +LA34E: LDD 32,X + STD ,X++ + CMPX #VIDRAM+$1E0 + BLO LA34E + LDB #$60 + BSR LA92D +LA35D: PULS A,B,X,PC + +LA92D: STX CURPOS +LA92F: STB ,X+ + CMPX #VIDRAM+511 + BLS LA92F + RTS + +;---------------------------------- +;COPY OF DISK CODE FROM ROM SOURCES +;---------------------------------- + + +MYCON: PSHS U,Y,X,D ;AT $D75F IN LISTING + LDA #5 + PSHS A +LD672: CLR RDYTMR + LDB DCDRV + LDX #LD7AA + LDA DRGRAM + ANDA #$A8 + ORA B,X + ORA #$20 + LDB DCTRK + CMPB #22 + BLO LD68B + ORA #$10 +LD68B: TFR A,B + ORA #8 + STA DRGRAM + STA DSKREG + BITB #8 + BNE LD69F + JSR LA7D1 + JSR LA7D1 +LD69F: BSR LD6DE + BNE LD6AD + CLR DCSTA + LDX #LD7A2 + LDB DCOPC + ASLB + JSR [B,X] +LD6AD: PULS A + LDB DCSTA + BEQ LD6BE + DECA + BEQ LD6BE + PSHS A + BSR LD6C5 + BNE LD6AD + BRA LD672 +LD6BE: LDA #120 + STA RDYTMR + PULS PC,U,Y,X,D + +LD6C5: LDX #DR0TRK + LDB DCDRV + CLR B,X + LDA #3 + STA FDCREG + EXG A,A + EXG A,A + BSR LD6DE + BSR LD6FD + ANDA #$10 + STA DCSTA +LD6DD: RTS + +LD6DE: LDX ZERO +LD6E0: LEAX -1,X + BEQ LD6EC + LDA FDCREG + BITA #1 + BNE LD6E0 + RTS +LD6EC: LDA #$D0 + STA FDCREG + EXG A,A + EXG A,A + LDA FDCREG + LDA #$80 + STA DCSTA + RTS + +LD6FD: LDX #8750 +LD700: LEAX -1,X + BNE LD700 + RTS + +LD705: LDA #$80 + DB SKP2 +LD708: LDA #$A0 + PSHS A + LDX #DR0TRK + LDB DCDRV + ABX + LDB ,X + STB FDCREG+1 + CMPB DCTRK + BEQ LD739 + LDA DCTRK + STA FDCREG+3 + STA ,X + LDA #$17 + STA FDCREG + EXG A,A + EXG A,A + BSR LD6DE + BNE LD737 + BSR LD6FD + ANDA #$18 + BEQ LD739 + STA DCSTA +LD737: PULS PC,A + +LD739: LDA DSEC + STA FDCREG+2 + LDX #LD798 + STX DNMIVC + LDX DCBPT + LDA FDCREG + LDA DRGRAM + ORA #$80 + PULS B + LDY ZERO + LDU #FDCREG + COM NMIFLG + ORCC #$50 + STB FDCREG + EXG A,A + EXG A,A + CMPB #$80 + BEQ LD782 + + LDB #2 +LD768: BITB ,U + BNE LD778 + LEAY -1,Y + BNE LD768 +LD770: CLR NMIFLG + ANDCC #$AF + JMP LD6EC + + +;WRITE A SECTOR + +LD778: LDB ,X+ + STB FDCREG+3 + STA DSKREG + BRA LD778 + +LD782: LDB #2 +LD784: BITB ,U + BNE LD78E + LEAY -1,Y + BNE LD784 + BRA LD770 + +LD78E: LDB FDCREG+3 + STB ,X+ + STA DSKREG + BRA LD78E + +LD798: ANDCC #$AF + LDA FDCREG + ANDA #$7C + STA DCSTA + RTS + +LD7A2: DW LD6C5 + DW LD6DD + DW LD705 + DW LD708 + +LD7AA: DB 1 + DB 2 + DB 4 + DB $40 + + END diff --git a/colorcomputer/bugger.src b/colorcomputer/bugger.src new file mode 100644 index 0000000..d557946 --- /dev/null +++ b/colorcomputer/bugger.src @@ -0,0 +1,124 @@ + PAGE + SBTTL "--- DEBUGGER ---" + + ; -------- + ; DEBUGGER + ; -------- + + ; ENTRY: BREAKPOINT # IN [B] + +DOBUG: LDX #SCREEN+64 ; BEGINNING OF LINE + LDA #'B' ; "BUG:" + STA ,X+ + LDA #'P' + STA ,X+ + JSR COLON + + STB ,X+ ; SHOW BREAKPOINT ID + JSR BUGSP ; SPACE + + LDA OPCODE + BPL P2OP ; 2-OP IF POSITIVE + CMPA #176 + BLO P1OP ; 1-OP + CMPA #192 + BLO POP0 ; 0-OP + CMPA #224 + BLO POPE ; EXTENDED 2-OP + + LDA #'X' ; OR X-OP + BRA POPC + +P2OP: LDA #'2' + BRA POPC + +P1OP: LDA #'1' + BRA POPC + +POP0: LDA #'0' + BRA POPC + +POPE: LDA #'E' + +POPC: STA ,X+ ; PRINT OP-TYPE + + LDA #'-' ; "-OP:" + STA ,X+ + LDA #'O' + STA ,X+ + LDA #'P' + STA ,X+ + BSR COLON + + LDA OPCODE ; SHOW OPCODE + BSR INHEX + BSR BUGSP + + LDA #'P' ; "PC:" + STA ,X+ + LDA #'C' + STA ,X+ + BSR COLON + + TST ZPCH ; IF ZPCH <> 0 + BEQ DOBZ ; PRINT "0" + LDA #'1' ; ELSE PRINT "1" + BRA TOPPC + +DOBZ: LDA #'0' +TOPPC: STA ,X+ + + LDA ZPCM ; PRINT ZPCM & L + BSR INHEX + LDA ZPCL + BSR INHEX + BSR BUGSP + + ; INVERT THE DEBUG LINE + + LDX #SCREEN+96 +BUGL2: LDA ,-X + ANDA #%10111111 ; CLEAR BIT 6 + STA ,X + CMPX #SCREEN+64 + BHI BUGL2 + RTS + + ; ------------- + ; PRINT A COLON + ; ------------- + +COLON: LDA #':' + BRA POOP + + ; ------------- + ; PRINT A SPACE + ; ------------- + +BUGSP: LDA #$20 + BRA POOP + + ; ---------------- + ; PRINT [A] IN HEX + ; ---------------- + +INHEX: TFR A,B + LSRA ; SHIFT HIGH NIBBLE INTO PLACE + LSRA + LSRA + LSRA + + BSR TOASC ; CONVERT HIGH NIBBLE & SHOW + TFR B,A + +TOASC: ANDA #%00001111 + CMPA #10 ; CONVERT LOW NIBBLE & SHOW + BLO IH1 + ADDA #7 +IH1: ADDA #$30 + +POOP: STA ,X+ + RTS + + END + diff --git a/colorcomputer/coco.zip b/colorcomputer/coco.zip new file mode 100644 index 0000000..cc4cb75 --- /dev/null +++ b/colorcomputer/coco.zip @@ -0,0 +1,308 @@ +:101100004F1F8B1A50B6FF0384FEB7FF03B7FFDFF4 +:1011100010CE0AFE7E1F7310CE0AFE8E00006F8076 +:101120008C005E25F98E0E0086FFA7808C100025AE +:10113000F9CC2500DD48BD2167B625044C970B8B03 +:1011400025970EC6FED00E2304C10824044FBD1FF0 +:10115000A9D70C8E0E003A3A9F0FB625018A08B720 +:1011600025018402974EFC2506DD12FC250CC325C3 +:1011700000DD1FFC2518C32500DD23FC2508C32541 +:1011800000DD21960B973DBD21670A3D26F9CE0D66 +:10119000FEDF25BD1F1A035CBD1D920A570A570FBB +:1011A00001BD1A559700102A00A481B0256F81C097 +:1011B000255BBD1A55973F0F402006963F4848973C +:1011C0003F84C02605BD128E201081402605BD1229 +:1011D00086200781802619BD12A5D6408E00023ACE +:1011E000DC3DED840C010C400C409640810825CB81 +:1011F000D600C1E01025007CC41FC10C2505860166 +:10120000BD1FA98E13FF583AAD947E11988E13918D +:10121000D600C40FC10E25EE8602BD1FA98430265C +:1012200005BD128E201581102605BD1286200C8169 +:101230002027058603BD1FA9BD12A5DC3DDD020CDC +:10124000018E13ADD600C40FC11024E720B884402E +:101250002605BD12862003BD12A5DC3DDD020C0172 +:10126000960084202605BD12862003BD12A5DC3D14 +:10127000DD040C018E13CDD600C41FC1191025FF4B +:10128000858604BD1FA9BD1A55973E0F3D39BD1A6D +:10129000553402BD1A55973E3502973D394D260B00 +:1012A000BD130A205ABD1A554D275F8110240D4ADF +:1012B000488E10001F893AEC84DD3D3980109E1F56 +:1012C0001F893A20F14D261D370611830DFE224954 +:1012D000202D4F973E0F3D9E3D3410BD1A553510C1 +:1012E0009F3D4D271A8110240D4A481F898E1000FA +:1012F0003ADC3DED843980109E1F1F893A20F1DCD5 +:101300003D360611830C00250C393706DD3D11836F +:101310000DFE220539860520028606BD1FA9BD1ACD +:10132000554D2A0E84402603BD1A5539BD1A554D18 +:101330002AF285402708843F973E0F3D2013843FC3 +:10134000852027028AE03402BD1A55973E35029760 +:101350003DDC3D102700C8830001102700B9830041 +:1013600001DD3D973C5F4859D73B963E1CFE9913E3 +:1013700024060C3C26020C3B9713DC3B2712963CC0 +:101380001CFE99129712963B9911840197110F1622 +:10139000391417141F14221440143F21AE22601F69 +:1013A0006B1447130A1FC22037207B144F149C1460 +:1013B000A514AE14CC14DC14EE1506151212331558 +:1013C0001C155C1570159F15A915B315BB12811757 +:1013D000E015C415CE15D815E116041614162116FD +:1013E0002C1634164516531663166C169216A5164F +:1013F000B816FC172017401749174F176E177318A8 +:1014000008187618881896193318CC18D1190C19A1 +:1014100026192B143F143FC6014FDD027E15705F65 +:1014200020F796119718DC12DD190F1DBD1B1F96B2 +:10143000189711DC19DD12961D9716DC1BDD143987 +:101440008DE0BD203720D0BD130ADD027E1570BDB2 +:101450001FEBFC251ADD044F5FDD02DD06DD3D08D4 +:1014600005090409078640973EBD1ACE8606B71ABD +:10147000A9BD1A8B5F9903970324020C02DC191093 +:10148000930426ED9618910726E7860BB71AA9FC58 +:10149000251C1093021027FE937E131EDC021027DA +:1014A000FE8A7E131E9603BD1D69C605200796039E +:1014B000BD1D69C6069E3DA685973E34020F3DBD03 +:1014C00012D735024D1027FE557E132C9603BD1DF5 +:1014D000699E3DA604973E0F3D7E12D7DC02C325D0 +:1014E00000830001DD3D5FBD1D234C7E12D39603BA +:1014F000BD129DDC3DC30001DD3D34069603BD12E7 +:10150000C53506DD3D399603BD129DDC3D830001E6 +:1015100020E6DC02DD3DBD1ACE7E1B1F9603BD1DFD +:10152000699E3DA60427343410BD1D699E3DA60664 +:101530009103260C35103410A6059E3DA7062015F4 +:10154000BD1D699E3DA605910326F535103410A6F4 +:10155000059E3DA70535106F046F05399603BD1D27 +:10156000699E3DEC07C30001DD3DBD1ACE7E1B1F09 +:10157000DE25BD130AD73B270E8E1000583ABD1347 +:101580000AED830A3B26F7BD130ADD11BD130AD706 +:1015900013BD130ADD250F16DC02DD3D7E12D7DCFC +:1015A00002830001DD3D7E135EDC02DD3DBD1B10CC +:1015B0007E1B1F9603BD129D7E12D7DC024353DDB6 +:1015C0003D7E12D7DC02DD3DDC04DD3B201EDC026B +:1015D000DD3BDC04DD3D2014BD1506DC04DD3B20D5 +:1015E0000BBD14EEDC3DDD3BDC04DD3D8D0525212E +:1015F0007E131E963B983D2A05963B913D39DC3D76 +:1016000010933B399603BD1D699E3D9605A10426A6 +:10161000DF7E132CDC049402D40310930427F22001 +:10162000CFDC029A04DA05DD3D7E12D7DC02940499 +:10163000D40520F3BD1D3BDC3B9441973BD442DAFB +:101640003B26CE20ABBD1D3B9E3DDC3B9A41DA42A2 +:10165000ED8439BD1D3B9E3DDC414353943BD43C5E +:10166000ED8439DC04DD3D96037E12C5BD151C9664 +:1016700003BD1D699E3D34109605A704BD1D699EDE +:101680003DA606973B9603A7063510963B2702A773 +:10169000053908050904DC04D302DD3DBD1ACEBDC1 +:1016A0001AC17E12D7DC02D304DD3DBD1ACEBD1AAD +:1016B0008B973E0F3D7E12D7BD1D06BD1D1B9105AC +:1016C00027182505BD1D3020F2FC250AC325001F63 +:1016D00001D6055A583AEC84201DBD1D235C4D27C8 +:1016E00010810127058607BD1FA99E3D3AEC842085 +:1016F000069E3D3AE6844FDD3D7E12D7BD1D06BDF8 +:101700001D1B910527091025FBC8BD1D3020F00CBD +:101710003E26020C3D4FD33D832500DD3D7E12D792 +:10172000BD1D0696052713BD1D1B91052709102514 +:10173000FBA0BD1D3020F0BD1D30BD1D1B7E12D392 +:10174000DC02D304DD3D7E12D7DC02930420F58E4B +:1017500000114F5FDD4506450646060406052406D2 +:10176000DC02D345DD45301F26ECDC0420D68D0994 +:101770007E12D78D04DC3B20CBDC02DD3DDC04DDBA +:101780003B963D9744983B97430D3D2A028D190D9A +:101790003B2A028D0C8D180D432A028D0B0D442A15 +:1017A000064F5F933BDD3B394F5F933DDD3D39DCB9 +:1017B0003B27288E00104F5FDD45093E093D094655 +:1017C0000945DC45933B2505DD454320014F301F8E +:1017D00026E8093E093DDC45DD3B398608BD1FA9E9 +:1017E0000A0126058609BD1FA9DC021093042715EE +:1017F0000A01270E109306270C0A012705109308EB +:1018000027037E131E7E132CDC0226037E1744DC86 +:1018100025BD1301D613BD1301DC11BD13014F0803 +:10182000030902499711DC02DD120F16BD1A559704 +:101830003F9740271E8E1000EC843410BD1301BD6D +:101840001A553402BD1A551F8935023510ED810A2B +:101850003F26E50A012717DC04FD10000A01270EC8 +:10186000DC06FD10020A012705DC08FD1004D64045 +:10187000BD1301DF253908050904DC04D302C325A3 +:10188000001F01DC06ED8439DC04D302C325001FF0 +:10189000019607A78439BD1D06BD1D1B9105270CA8 +:1018A0002405860ABD1FA9BD1D3020EDBD1D235C8A +:1018B0004D271181012705860BBD1FA99E3D3ADCEE +:1018C00006ED843996079E3D3AA7843996037E1F1C +:1018D000F3DC02DD3DDC3D2A08862DBD1FF3BD177C +:1018E000A80F41DC3D2710CC000ADD3BBD17AF96A9 +:1018F0003C34020C4120EC9641270C35028B30BD64 +:101900001FF30A4126F53986307E1FF3DC02DD3BEA +:10191000DC56C3330BDD56847FDD3DBD1781DC3BD8 +:10192000C300017E1744DC027E1301BD130A960337 +:101930007E12C5BD207BDC02C32500DD02DC04C3B2 +:101940002500DD04BD1E3997410F429E046F0186BC +:101950000197394C97389E04A680A1842405860DF2 +:10196000BD1FA9DC41260139964281062503BD1918 +:10197000EE964226245FDD2CDD2EDD30D6389E0427 +:101980003AD639E7039E02A685BD1A102529BD1A4D +:101990000924060C390A4120BD96412722D6399EDA +:1019A00002A685BD1A052517D6428E002CA7850AEA +:1019B000410C420C39209F972C0A410C420C39965D +:1019C000422793D6389E043A9642A70296413402A3 +:1019D000BD1C11BD1A20350297419E046C01D638FA +:1019E0003ACB04D738DC3BED840F427E1956964142 +:1019F0002712D6399E02A6858D0B25080A410C4276 +:101A00000C3920EA398D0925158E1A4FC605200597 +:101A10009E21E6805AA18527055A2AF95F39533954 +:101A20009E21E6803AA6809742EC81DD3BEC841053 +:101A300093322607EC02109334270DD6423ADC3B52 +:101A4000830001DD3B26E6393089DB009F3B3921ED +:101A50003F2C2E0D200D162714D6139E143AA68463 +:101A60000C1326080F160C1226020C1139DC114D2E +:101A70002604D10B2507BD1AD70F1D2004CB251F27 +:101A80009897140F1586FF971620CE0D1D2714D694 +:101A90001A9E1B3AA6840C1A26080F1D0C19260242 +:101AA0000C1839DC184D2604D10B2507BD1AD70FA9 +:101AB000162004CB251F98971B0F1C86FF971D200F +:101AC000CE8DC834028DC4973E3502973D39DC3D3A +:101AD000DD190F180F1D390F0D8E0E0010A3812771 +:101AE0002A0C0D9C0F25F5DD4A960A970D9B0E9743 +:101AF000480F498E0E00D60A3A3ADC4AED84BD21E1 +:101B0000670C0A960A910C25020F0A960D9B0E3956 +:101B10004F083E093D499718DC3DDD190F1D390F6F +:101B2000280F2986FF9727BD1BD925F2974127410A +:101B3000810425578106253DBD1BCD4D2609865BB9 +:101B40009B41BD1FF320E081012604863B20F1D696 +:101B500041C00627078E1CECA68520E6BD1BD94890 +:101B6000484848489741BD1BD9974296419A422020 +:101B7000D1862020CD80031F898D522604D72720AF +:101B8000A6D728912827A00F28209C4AC6403DD7D9 +:101B90003ABD1BD91F8958DB3A9E233AEC84DD3DC0 +:101BA000961834029628D6299E19109E2A3436BDDE +:101BB0001B10BD1B1F3536109F2A9F19D729972848 +:101BC0003502971886FF97270F1D7E1B2796272A19 +:101BD00003962839C6FFD7273996292A0253392672 +:101BE0000F0C29BD1AC1DC3DDD2A4444841F5F3936 +:101BF0004A261486029729DC2A4456962A444456DB +:101C00005454541F9820E50F29DC2A2AF603292072 +:101C1000F2CC0505DD32DD34DD364C97410F3B0F4C +:101C20003DD63D0C3D8E002CA685974226048605A8 +:101C300020259642BD1CB24D27118B03D63B8E004A +:101C400032A7850C3B0A41102700849642BD1CB286 +:101C50004A2A139642805BD63B8E0032A7850C3B06 +:101C60000A41276B20BB26069642803B20E996421C +:101C7000BD1CA026E28606D63B8E0032A7850C3B13 +:101C80000A41274B964244444444448403D63B8E45 +:101C90000032A7850C3B0A4127359642841F20B7A6 +:101CA0008E1CECC619A18527045A26F9391F988B7A +:101CB000063981612506817B24024F398141250740 +:101CC000815B24038601394D27042B02860239DC0F +:101CD0003258585858495849DA34DD32DC355858AA +:101CE0005858495849DA378A80DD3439000D303187 +:101CF00032333435363738392E2C213F5F232722B3 +:101D00002F5C2D3A28299603BD1D699E3DEC07C323 +:101D10002500DD3D1F01E684585C399E3D3AA684CE +:101D2000841F399E3D3AA684464646464684073976 +:101D30008DF1973B5C0A3B2AFB5C399603BD1D691C +:101D400096058110250880109E3D30029F3D973CEE +:101D5000CC0001DD41C60FD03C2707084209415A9B +:101D600020F79E3DEC84DD3B39C6093DC30035F3C9 +:101D7000250AC32500DD3D39975DB6FF038A01B70B +:101D8000FFDEB7FF031CAF965D398DECAD9FA00061 +:101D900027FA975D1A50B6FF0384FEB7FF03B7FF1B +:101DA000DF965D398DD2AD9FA00220E6BD1F492090 +:101DB0000434748DC3108E0600109F588680975A85 +:101DC000AD9FA0000C560D5B2721109E58313F108F +:101DD0009F58260D108E0180109F58D65AC880D764 +:101DE0005A9E88E684C47FDA5AE7844D27D20D5B79 +:101DF0002704C47FE784810D271881082714816197 +:101E00002508817B24A680202008815B249E8120D8 +:101E1000259A9753BD1F30C60586FEB7FF208D114A +:101E20008602B7FF208D0A5A26EF357496537E1D21 +:101E3000928E0019301F26FC39BD20710F520F6F92 +:101E40009E02E680C002D751D75B5FBD1DB1810DF8 +:101E5000273281082725814125028B20A7855C96A2 +:101E6000538D4CD1512404C13D25E0BD1DB1810DE0 +:101E7000271281082705BD1F4920F05A2AE15FBDBE +:101E80001F4920C7A7858D275CD7510D5C2719B640 +:101E900025118401271286FE976FD651BD1D78A6A5 +:101EA00080AD9FA0025A26F70F6F96517E1D929724 +:101EB000530F6F34340C56109E88810D273F108CC1 +:101EC00005FF252B108E05DF109F888E0440108E95 +:101ED0000420C61FA685A7A55A2AF91F12308820FC +:101EE0008C060025ED8660A7A0108C060025F896CC +:101EF00053816125028020BD1DA4353439108C0525 +:101F0000E025EC20BFD64F8E1020D7515FA685BDAF +:101F10001EAF5CD15125F67E1E8B86608E0400A715 +:101F2000808C060025F9CC0420DD880F520F4F3934 +:101F3000B6FF0184F7B7FF01B6FF0384F7B7FF03CD +:101F4000B6FF238A08B7FF233934168DE3C60A8605 +:101F5000FEB7FF208D0D8602B7FF208D065A26EFB3 +:101F60003516398E01F4301F26FC39BD20370F5C41 +:101F7000BD22EF0F5CBD1F1ACC04C8DD888E1F8800 +:101F8000C610BD1F0A7E11174C4F4144494E4720D1 +:101F900047414D45202E2E2E0D494E5445524E415F +:101FA0004C204552524F5220233402BD20378E1F01 +:101FB00098C611BD1F0A3502973E0F3DBD18D5BD0D +:101FC00020668E1FD2C60FBD1F0A7FFF40BD1D7841 +:101FD00020FE454E44204F462053455353494F4E13 +:101FE0000D56455253494F4E20410D8E1FE0C60BF2 +:101FF0007E1F0A8E1020D64F810D273B8120250899 +:10200000A785C11F24030C4F398620A18527055AB7 +:1020100026F9C61FD750D74FBD20370C50D650C118 +:102020001F2301398E1020A685D64FA7850C4F207F +:10203000EA5B6D6F72655D0C529652810E25278D9D +:102040003ADC88DD3F8E2031C606BD23840F5BBDA0 +:102050001DB1DC3FDD888620C606BD1DA45A26FAC8 +:10206000DC3FDD880F52D64F8E1020860DA7850CE1 +:102070004F0D4F2705BD1F050F4F39964FD6299E8F +:1020800088109E2A34369618D6519E19109E2734F1 +:1020900036108E10408E1020C620A684E780A7A0A0 +:1020A0008C104025F58E04008620A7808C04202506 +:1020B000F90F4F0F5CCC0400DD888610BD129D9691 +:1020C0003EBD155E8617974F8611BD129D0D4E269B +:1020D00007BD18D5862F2013963E26028618810C40 +:1020E0002F04800C973EBD18D5863ABD1FF386128B +:1020F000BD129D0D4E272E963E810A24058630BDC9 +:102100001FF3BD18D58620BD1FF38611BD129D9605 +:102110003E810C2404864120028650BD1FF3864D6B +:10212000BD1FF32003BD18D5BD20668D2B108E106A +:10213000408E1020A6A0A7808C104025F7353610C1 +:102140009F279F19D75197183536109F2A9F88D7F8 +:1021500029974F035C0F1D398E0400A68484BFA706 +:10216000808C042025F539DC3D9E3B3416DC4AC3C7 +:102170000025108301212503C30024DD3DCC00127E +:10218000DD3BBD17AF963ED63C2603C6124ADD4C5A +:10219000BD22110C4B26020C4A35169F3BDD3D3902 +:1021A000BD2037BD1F1ACC0400DD880F5C398DF0CF +:1021B0008E2396C606BD2384BD23018E1040FC25C8 +:1021C00002ED81DC25ED81EF819611A780DC12ED17 +:1021D00084CC1000DD488D26CC0C00DD488D1F8D91 +:1021E0001DCC2500DD48B6250E4C973D8D100A3DCF +:1021F00026FA7E22D8860C2002860EBD1FA98E0BE1 +:1022000000109E48ECA1ED818C0C0025F786032080 +:10221000028602BD1D78BEC006D647ED84DC4C8127 +:102220002324D2C11324CEED02CC0B00ED04AD9FCC +:10223000C004BD1D92A606854026214D26BB8E0BEF +:1022400000109E48EC81EDA18C0C0025F70C48DCB9 +:102250004C5CC1132503C6014CDD4C3935062034D6 +:10226000BD21A08E238DC609BD2384BD23018E1000 +:10227000009F48EC8134068C101E25F7BD2211FC0E +:10228000104010B3250227118E101E3506ED838CE9 +:10229000100022F78D477E131E32E81EFC2510DD4C +:1022A0003BCC0C00DD48BD2211BD2211CC2500DD48 +:1022B00048BD2211B6250E973DBD22110A3D26F9D3 +:1022C0008E1042EC81DD25EE81A6809711EC84DD35 +:1022D000120F16DC3BFD25108D037E132C0F478E4D +:1022E00023BAC61EBD2384BD22EF035C7E1F1A8E57 +:1022F00023D8C61AD75BBD1F0ABD1DB1860D7E1F30 +:10230000F38E23F2C614BD2384BD21589655BD23F8 +:1023100078BD1D8A810D270B803081052507BD1FE3 +:102320004920EE965597558B30BD1DA4860DBD1DD9 +:10233000A49655C6063DD74CC601D74D8E2406C679 +:102340000DBD238496548D30BD1D8A810D270B80D1 +:102350003081022507BD1F4920EE965497549747B8 +:102360008B30B723B7BD1DA4860DBD1DA48E239C45 +:10237000C61EBD23847E22EF8B30B7241E8E24130D +:10238000C60ED75BA680BD1DA45A26F83952455308 +:10239000544F52494E47534156494E470D494E53AB +:1023A0004552542053415645204449534B20494EF1 +:1023B00020445249564520302C0D0D494E5345526C +:1023C000542047414D45204449534B20494E204419 +:1023D0005249564520302C0D505245535320414E02 +:1023E00059204B455920544F20434F4E54494E5588 +:1023F000450D2047414D450D0D504F534954494F10 +:102400004E20302D342044524956452030204F5222 +:102410002031202844454641554C54203D20302948 +:042420003A454E44A7 +:0000000000 diff --git a/colorcomputer/cocoref.doc b/colorcomputer/cocoref.doc new file mode 100644 index 0000000..d77cd85 --- /dev/null +++ b/colorcomputer/cocoref.doc @@ -0,0 +1,225 @@ +Interactive Fiction Reference Card for the TRS-80 COLOR COMPUTER 2 + + +I. What You Need + +Required + +- TRS-80 Color Computer 2 +- 64K bytes of RAM +- One TRS-80 Color Disk Drive + +Optional + +- One or more blank, formatted disks (for SAVEs) +- An 80-column line printer and serial printer cable (for SCRIPTing) +- A second Color Disk Drive (for convenience with SAVEs) + + +II. Loading The Disk + +1. Turn on the power to your disk drive(s) and Color Computer. + +2. Insert the master story disk into drive #0, with the oval-shaped cutout + going in first and the label facing to the right. + +3. Under BASIC's "OK" prompt, type: + + RUN "GAME" + + After a few seconds, the following prompt will appear: + + LOADING GAME ... + + The program automatically loads and runs in about 15 seconds. + +4. If nothing appears on your TV screen or monitor, or if you receive an + error message, something is wrong. Refer to the Troubleshooting + section for help. + + +III. Talking To The Game + +Whenever you see a prompt (>), the story is waiting for your command. +You may type up to two full lines of text at a time. If you make +an error, use the back-arrow key to erase it. Press the ENTER key when +you are finished typing. The story will respond and the prompt will reappear. + +A clicking sound has been added to the keys to make typing easier. Use the +volume control on your TV set or monitor to change the sound of the clicks. +Certain keys (such as the up- and down-arrows, CLEAR and BREAK) have been +disabled. You will hear a "boop" sound if you accidently touch one of these +keys. You will also hear the "boop" if you try to type more than two lines +of text at a time, or if you try to backspace past the beginning of a line. + +If a description will not fit on the screen all at once, [MORE] will +appear in the bottom left corner. Press the space bar (or any other key) +after reading the screen to view the rest of the description. + + +IV. The Status Line + +At the top of your screen, you will see a status line. The line is updated +after every move to indicate your current location in the story. Depending +on the story, the status line may also provide other information: + +Score + +In stories that keep a score, such as the ZORK underground adventure trilogy, +the right side of the status line will look something like this: + + 245/920 + +The number on the left is your score. The other number tells you how many +moves you have made. In the example above, you have earned 245 points in +920 moves. + +Time + +In stories that keep track of time, such as the mystery thriller DEADLINE, the +right side of the status line will look something like this: + + 9:22 AM + +This indicates the current time in the story. + + +V. Saving a Story Position + +WARNING: Disks used for SAVE and RESTORE are maintained in a special +format and should not be used for any other purpose. Files of any other +kind stored on the disk will be erased by the SAVE command. + +You need a blank, formatted disk to SAVE your position in the story. You +may SAVE up to five different positions on a blank disk and RESTORE them in +any order. Each SAVE position is assigned a number from 0 to 4. You must +specify a position number each time you use the SAVE command, and +you overwrite any position previously SAVEd with that number. You must use +a different number for each position that you want to SAVE. + +To save your current position, type the word SAVE at the prompt (>). After +pressing the ENTER key, the screen will clear and you'll see the following: + + SAVING GAME + POSITION 0-4 (DEFAULT = 0): + +1. Type a number from 0 to 4 to tell the story which SAVE position on the + disk should be used, or simply press ENTER to use the default position. + You will see the message: + + DRIVE 0 or 1 (DEFAULT = 0): + +2. Select the drive that will contain the SAVE disk, or press ENTER to use + the default setting. You will now see: + + INSERT SAVE DISK IN DRIVE 0 (or 1), + PRESS ANY KEY TO CONTINUE + +3. Insert your SAVE disk into the indicated drive and press a key. + The disk will spin for a few moments. You will then be asked to + + INSERT GAME DISK IN DRIVE 0, + PRESS ANY KEY TO CONTINUE + +4. Make sure the master story disk is inserted in drive #0 and press a key. + If all is well, you'll get the message: + + Ok. + + If you receive an error message, or the game responds with + + Failed. + + consult the Troubleshooting section. + + +VI. Restoring a Saved Position + +To restore a previously saved story position, type RESTORE at the prompt +(>). Then follow steps 1 through 4 above for SAVE. + + +VII. SCRIPTing + +If you have an 80-column TRS-80 Line Printer (or any equivalent printer that +connects to the serial port on the back of the Color Computer), you may make a +transcript as you go along. + +1. Connect the printer to the serial port on the back of your Color + Computer. + +2. Turn on the printer and set it on-line. + +3. Load the master disk and start the story as previously described. + +4. To start the transcript at any time, type SCRIPT. + +5. To stop the transcript, type UNSCRIPT. + +6. SCRIPT and UNSCRIPT may be used as often as desired for as long as the + printer is left on-line. + + +VIII. Initializing SAVE Disks + +Blank disks must be formatted before they can be used to SAVE games. Use the +standard Disk Extended BASIC command DSKINI to format your disks. Refer to +the TRS-80 Color Computer Disk System Owner's Manual and Programming Guide for +more information. + + +IX. Troubleshooting + +A. If the program refuses to load properly, if SAVE/RESTORE fails, or if you + receive an error message, check each of the following points. + +1. Make sure your Color Computer and disk drive(s) are connected + properly and everything is turned on. + +2. Make sure the disk is inserted correctly into the drive slot, + and the drive door is closed. + +3. Inspect the master disk and SAVE disk(s) carefully for visible damage. + +4. Make sure each disk is in the proper drive. The master disk can only + be run from drive #0. For SAVE/RESTORE, make sure that you have typed + the correct drive number for the storage disk, and that you have replaced + the master disk in drive #0 before proceeding with the story. + +5. When saving a story position, make sure the write-protect notch on the + edge of the SAVE disk is not covered. Also make certain the storage disk + has been formatted properly. As a last resort, try a different storage + disk. + +B. If you receive an error message, turn off your Color Computer and reload + the story following the instructions in Section II. The problem may be + only momentary. If trouble persists, try the following procedure. + + After reloading the master disk and receiving the intial prompt (>), + type $VERIFY. The disk will spin for about a minute, and a message + similar to one of the following will appear: + + a. DISK CORRECT. This indicates that the story data on the disk is + intact. This may indicate a problem with your hardware (probably + the disk drive). It is also possible that the story program + contains a bug. If you suspect a bug, call the Infocom Technical + Hotline. + + b. INTERNAL ERROR. This response indicates either + hardware trouble or disk damage. Repeat the $VERIFY procedure + several times. Also try the procedure on another Color Computer + system (such as your dealer's). If you ever get the message DISK + CORRECT, the problem is probably in your hardware. + + If you repeatedly get an error message on more than one computer, + the disk is probably damaged. Please send the master disk ONLY to + Infocom for testing. + + +TRS-80 is a registered trademark of Tandy Corporation. +DEADLINE is a trademark and ZORK is a registered trademark of Infocom, Inc. + +(Logo) INFOCOM + +Infocom, Inc., 55 Wheeler Street, Cambridge, MA 02138 + diff --git a/colorcomputer/cocozip.asm b/colorcomputer/cocozip.asm new file mode 100644 index 0000000..1788e67 Binary files /dev/null and b/colorcomputer/cocozip.asm differ diff --git a/colorcomputer/cocozip.src b/colorcomputer/cocozip.src new file mode 100644 index 0000000..6f7d238 --- /dev/null +++ b/colorcomputer/cocozip.src @@ -0,0 +1,69 @@ + TITLE "ZIP/6809-C INFOCOM, INC. --- INITIALIZATION" + + ; ------------------------------- + ; ZIP/6809 VERSION C + ; Z-CODE INTERPRETER PROGRAM + ; FOR 64K TRS-80 COLOR COMPUTER 2 + ; ------------------------------- + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + +MSTART EQU $0A00 ; START OF FREE PROGRAM RAM + +DEBUG EQU 0 ; ASSEMBLY FLAG + + ; ----------- + ; 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 + ; 15 -- Z-STACK DESTROYED + ; 16 -- ZIP NOT FULLY LOADED + + + INCLUD EQ.ASM + INCLUD WARM.ASM + + TITLE "ZIP/6809-B INFOCOM, INC. --- MAINLINE" + INCLUD MAIN.ASM + INCLUD SUBS.ASM + INCLUD DISPATCH.ASM + + TITLE "ZIP/6809-B INFOCOM, INC. --- OPCODE EXECUTORS" + INCLUD OPS0.ASM + INCLUD OPS1.ASM + INCLUD OPS2.ASM + INCLUD OPSX.ASM + INCLUD READ.ASM + + TITLE "ZIP/6809-B INFOCOM, INC. --- OPCODE SUPPORT" + INCLUD PAGING.ASM + INCLUD ZSTRING.ASM + INCLUD OBJECTS.ASM + + TITLE "ZIP/6809-B INFOCOM, INC. --- COCO MACHINE DEPENDENT" + INCLUD IO.ASM + INCLUD SCREEN.ASM + INCLUD DISK.ASM + + TITLE "ZIP/6809-B INFOCOM, INC." + IF DEBUG + INCLUD BUGGER.ASM + ENDIF + + END + diff --git a/colorcomputer/disk.src b/colorcomputer/disk.src new file mode 100644 index 0000000..fd8aac2 --- /dev/null +++ b/colorcomputer/disk.src @@ -0,0 +1,450 @@ + PAGE + SBTTL "--- DISK I/O ---" + +DSKCON EQU $C004 ; CONTAINS DISK ACCESS VECTOR +DCB EQU $EA ; ADDRESS OF DCB +MOTOR EQU $FF40 ; DRIVE MOTOR ON/OFF SWITCH +BLOCK1 EQU 37 ; 1ST Z-CODE BLOCK (TRACK 2, SECTOR 1) + + ; ------------------------ + ; READ A Z-BLOCK FROM DISK + ; ------------------------ + + ; ENTRY: DRIVE # (0 OR 1) IN [DRIVE] + ; BLOCK # IN [DBLOCK] + ; BUFFER ADDRESS IN [DBUFF] + +GETDSK: LDD TEMP ; SAVE [TEMP] AND + LDX VAL ; [VAL] FOR DIVISION + PSHS X,D + + ; CONVERT BLOCK # TO SECTOR/TRACK + + LDD DBLOCK ; FETCH BLOCK # + ADDD #BLOCK1 ; ADD DISK OFFSET + CMPD #16*18+1 ; IF BELOW TRACK 16 + BLO TRAKZ ; CONTINUE + ADDD #36 ; ELSE SKIP OVER TRACKS 16 & 17 +TRAKZ: STD TEMP ; USE AS DIVIDEND + LDD #18 + STD VAL ; DIVIDE BY 18 (# SECTORS PER TRACK) + JSR UDIV ; UNSIGNED DIVIDE + LDA TEMP+1 ; [TEMP] HAS QUOTIENT (TRACK #) + LDB VAL+1 ; [VAL] HAS REMAINDER (SECTOR #) + BNE NXTSEC ; IF REMAINDER WAS ZERO, + LDB #18 ; CHANGE IT TO 18 + DECA ; AND PATCH TRACK # +NXTSEC: STD TRACK + JSR DREAD ; ACCESS THE DISK + INC DBLOCK+1 ; POINT TO NEXT Z-BLOCK + BNE REND + INC DBLOCK +REND: PULS X,D ; RESTORE VARIABLES + STX VAL + STD TEMP + RTS + + ; ----------------- + ; SAVE/RESTORE INIT + ; ----------------- + +SAVRES: JSR ZCRLF ; FLUSH OUTPUT BUFFER + JSR CLS + LDD #SCREEN + STD CURSOR ; MOVE CURSOR TO STATUS LINE + CLR SCRIPT ; DISABLE SCRIPTING + RTS + + ; --------- + ; SAVE GAME + ; --------- + +ZSAVE: BSR SAVRES ; INIT THINGS + LDX #SAV + LDB #SAVL + JSR DLINE ; "SAVE POSITION" + + JSR PARAMS ; GET POSITION AND DRIVE + + LDX #SING + LDB #SINGL + JSR DLINE ; "SAVING" + JSR TIONP ; "POSITION X ..." + + LDX #BUFSAV ; POINT TO AUX BUFFER + LDD ZCODE+ZID ; GET GAME ID CODE + STD ,X++ ; SAVE IN BUFFER + LDD OZSTAK ; OLD STACK POINTER + STD ,X++ + STU ,X++ ; AND CURRENT STACK POINTER + LDA ZPCH ; HI BYTE OF ZPC + STA ,X+ + LDD ZPCM ; LOW ZPC BYTES + STD ,X + + LDD #LOCALS + STD DBUFF + BSR DWRITE ; WRITE LOCAL/BUFFER PAGE + + LDD #ZSTACK ; SAVE CONTENTS + STD DBUFF ; OF Z-STACK (2 PAGES) + BSR DWRITE ; FIRST HALF + BSR DWRITE ; 2ND HALF + + ; SAVE GAME PRELOAD + + LDD #ZCODE ; START OF PRELOAD + STD DBUFF + LDA ZCODE+ZPURBT ; SIZE OF PRELOAD (MSB, # PAGES) + INCA ; ROUND UP + STA TEMP ; USE [TEMP] AS INDEX + +LSAVE: BSR DWRITE ; SAVE A PAGE + DEC TEMP ; SAVED ENTIRE PRELOAD YET? + BNE LSAVE ; NO, KEEP SAVING + JMP RESUME + + ; *** ERROR #12: DISK ADDRESS RANGE *** + +DSKERR: LDA #12 + BRA DSKEX + + ; *** ERROR #14: DISK ACCESS *** + +DERR2: LDA #14 +DSKEX: JSR ZERROR + + ; ------------ + ; ACCESS DRIVE + ; ------------ + + ; ENTRY: [DBUFF] HOLDS BUFFER ADDRESS + ; [TRACK] HOLDS TRACK, SECTOR ADDRESS + ; [DRIVE] HOLDS DRIVE # + +DWRITE: LDX #IOBUFF ; POINT TO DISK I/O BUFFER + LDY DBUFF ; AND RAM PAGE TO BE WRITTEN +DRLOOP: LDD ,Y++ ; GRAB A WORD OUT OF RAM + STD ,X++ ; MOVE IT INTO THE BUFFER + CMPX #IOBUFF+$100 ; BUFFER FILLED YET? + BLO DRLOOP ; NO, KEEP MOVING + LDA #3 ; "WRITE SECTOR" COMMAND + BRA DIO + +DREAD: LDA #2 ; "READ SECTOR" COMMAND + +DIO: JSR ROMIN ; ENABLE ROMS [TAKEN OUT BY ASK 5/15/85] + + LDX #DCB ; GET ADDR OF DCB + LDB DRIVE ; DRIVE # (0 OR 1) + STD ,X ; PASS TO [DSKCON] + LDD TRACK ; TRACK & SECTOR ADDRESSES + CMPA #35 + BHS DSKERR ; NO TRACKS HIGHER THAN 34 + CMPB #19 + BHS DSKERR ; OR SECTORS HIGHER THAN 18 + STD 2,X ; PASS IT + LDD #IOBUFF ; BUFFER ADDRESS + STD 4,X + + ; ACCESS THE DRIVE + + JSR MYCON ; (NOT ANY MORE-->) LET OS DO THE DIRTY WORK + + JSR ROMOUT ; THEN TURN ROMS OFF AGAIN [ASK 5/15/85] + + ; CHECK FOR ACCESS ERRORS + + LDA 6,X ; GET STATUS BYTE + BITA #%01000000 ; WRITE-PROTECT ERROR? + BNE WPERR ; YES, GO REPORT IT + TSTA ; ANY OTHER ERRORS? + BNE DERR2 ; ERROR IF ANY BIT SET + + LDX #IOBUFF ; MOVE CONTENTS OF I/O BUFFER + LDY DBUFF ; TO DESIRED RAM ADDRESS +QLOOP: LDD ,X++ + STD ,Y++ + CMPX #IOBUFF+$100 + BLO QLOOP + + INC DBUFF ; POINT TO NEXT PAGE OF RAM + LDD TRACK ; AND NEXT SECTOR + INCB + CMPB #19 + BLO DIOEX + LDB #1 + INCA +DIOEX: STD TRACK + RTS + + ; ------------------- + ; WRITE-PROTECT ERROR + ; ------------------- + +WPERR: PULS D ; PULL RETURN ADDRESS OFF STACK + BRA ERRWP ; PROMPT FOR GAME DISK + + ; ------------ + ; RESTORE GAME + ; ------------ + +ZREST: JSR SAVRES + + LDX #RES + LDB #RESL + JSR DLINE ; "RESTORE POSITION" + + JSR PARAMS + + LDX #RING + LDB #RINGL + JSR DLINE ; "RESTORING" + JSR TIONP ; "POSITION X ..." + + ; SAVE LOCALS ON MACHINE STACK + ; IN CASE OF ERROR + + LDX #LOCALS ; POINT TO LOCALS STORAGE + STX DBUFF ; POINT TO 1ST PAGE TO RESTORE +LOCLP: LDD ,X++ ; GRAB A LOCAL + PSHS D ; AND PUSH IT + CMPX #LOCALS+30 ; SAVED 15 LOCALS YET? + BLO LOCLP ; NO, KEEP PUSHING + + JSR DREAD ; RETRIEVE LOCALS/BUFFER PAGE + + LDD BUFSAV ; READ SAVED GAME ID + CMPD ZCODE+ZID ; IF IT MATCHES CURRENT GAME ID, + BEQ VERSOK ; PROCEED WITH THE RESTORE + + ; WRONG SAVE DISK, ABORT RESTORE + + LDX #LOCALS+30 ; RESTORE PUSHED LOCALS +RESLP: PULS D + STD ,--X + CMPX #LOCALS + BHI RESLP +ERRWP: BSR TOBOOT ; PROMPT FOR GAME DISK + JMP PREDF ; PREDICATE FAILS + +VERSOK: LEAS +30,S ; POP OLD LOCALS OFF STACK + LDD ZCODE+ZSCRIP + STD VAL ; SAVE FLAGS + + LDD #ZSTACK ; RETRIEVE + STD DBUFF ; CONTENTS OF Z-STACK + JSR DREAD + JSR DREAD + +DOREST: LDD #ZCODE ; NOW RETRIEVE + STD DBUFF ; 1ST PAGE OF PRELOAD + JSR DREAD + + LDA ZCODE+ZPURBT ; DETERMINE # PAGES + STA TEMP ; TO RETRIEVE + +LREST: JSR DREAD ; FETCH REMAINDER OF PRELOAD + DEC TEMP + BNE LREST + + ; RESTORE STATE OF SAVED GAME + + LDX #BUFSAV+2 ; POINT TO SAVED VARIABLES + LDD ,X++ + STD OZSTAK ; RESTORE OLD STACK POINTERS + LDU ,X++ + LDA ,X+ + STA ZPCH ; HIGH BYTE OF ZPC + LDD ,X ; LOW BYTES OF ZPC + STD ZPCM + CLR ZPCFLG ; PC HAS CHANGED! + + LDD VAL ; RESTORE FLAGS + STD ZCODE+ZSCRIP + + ; RESUME GAME AFTER SAVE OR RESTORE + +RESUME: BSR TOBOOT ; PROMPT FOR GAME DISK + JMP PREDS ; PREDICATE SUCCEEDS + +TOBOOT: CLR DRIVE ; BACK TO BOOT DRIVE + LDX #GAME + LDB #GAMEL + JSR DLINE ; "INSERT STORY DISK IN DRIVE 0," + JSR ENTER ; "PRESS TO CONTINUE" + COM SCRIPT ; RE-ENABLE SCRIPTING + JMP CLS ; CLEAR SCREEN AND RETURN + + ; --------------------------- + ; "PRESS TO CONTINUE" + ; --------------------------- + +ENTER: LDX #PRESS + LDB #PRESSL + STB CFLAG ; ENABLE CURSOR + JSR LINE ; "PRESS TO CONTINUE" + JSR GETKEY ; GET A KEY + CLR CFLAG ; DISABLE CURSOR + LDA #EOL + JMP COUT ; DO EOL AND RETURN + + ; -------------------------------- + ; PROMPT SEQUENCE FOR SAVE/RESTORE + ; -------------------------------- + +PARAMS: LDX #POSIT + LDB #POSITL + JSR DLINE ; "GAME ... POSITION 1-7 " + JSR INVERT ; FLIP STATUS LINE + + LDA #TRUE + STA CFLAG ; ENABLE CURSOR + + ; GET POSITION + + LDA GPOSIT ; GET DEFAULT POSITION + INCA ; 1-ALIGN IT + JSR DODEF + +GETPOS: JSR GETKEY + CMPA #EOL + BEQ SETPOS + SUBA #$31 ; CONVERT "1-7" TO 0-6 + CMPA #7 ; IF LOWER THAN "7" + BLO POSSET ; SET NEW POSITION + JSR BOOP ; ELSE RAZZ + BRA GETPOS ; AND TRY AGAIN + +SETPOS: LDA GPOSIT ; USE DEFAULT +POSSET: STA GPOSIT ; TEMP DEFAULT + ADDA #$31 ; CONVERT TO ASCII + STA PDO ; HERE TOO + JSR OUTCHR ; AND SHOW CHOICE + + ; GET DRIVE # + + LDX #WDRIV + LDB #WDRIVL + JSR DLINE ; "DRIVE 0 OR 1 " + + LDA GDRIVE + BSR DODEF ; SHOW DEFAULT + +GETDRV: JSR GETKEY + CMPA #EOL + BEQ DRVSET + SUBA #$30 ; CONVERT TO ASCII + CMPA #2 + BLO SETDRV + JSR BOOP + BRA GETDRV ; DRIVE # NO GOOD + +DRVSET: LDA GDRIVE +SETDRV: STA DRIVE ; NEW DEFAULT + ADDA #$30 ; CONVERT TO ASCII + STA GAMDRI ; FOR PROMPT + JSR OUTCHR ; SHOW CHOICE + + LDA GPOSIT ; MAKE IT THE NEW DEFAULT + LDB #5 ; CALC BLOCK OFFSET (5 TRACKS/GAME) + MUL + STB TRACK ; TRACK ADDRESS + LDB #1 ; START ON SECTOR 1 + STB TRACK+1 ; SECTOR ADDRESS + + LDX #INSERM + LDB #INSERML + JSR DLINE ; "INSERT SAVE DISK IN DRIVE X," + JMP ENTER ; ETC. + + ; ------------ + ; SHOW DEFAULT + ; ------------ + +DODEF: ADDA #$30 ; CONVERT # TO ASCII + STA DEFNUM ; INSERT IN STRING + LDX #DEFALT + LDB #DEFALL + STB CFLAG ; ENABLE CURSOR + + ; FALL THROUGH TO ... + + ; -------------------- + ; DIRECT SCREEN OUTPUT + ; -------------------- + + ; ENTRY: SAME AS "LINE" ROUTINE + +DLINE: LDA ,X+ + JSR OUTCHR + DECB + BNE DLINE + RTS + + ; ---------------------- + ; PRINT "POSITION X ..." + ; ---------------------- + +TIONP: LDX #PTION + LDB #PTIONL + BRA DLINE + + ; --------------------- + ; TEXT FOR SAVE/RESTORE + ; --------------------- + +RES: DB "RESTORE" +RESL EQU $-RES + +SAV: DB "SAVE" +SAVL EQU $-SAV + +INSERM: DB EOL + DB EOL + DB "INSERT SAVE DISK IN DRIVE " +GAMDRI: DB "0." + DB EOL +INSERML EQU $-INSERM + +GAME: DB EOL + DB "INSERT STORY DISK IN DRIVE 0." + DB EOL +GAMEL EQU $-GAME + +PRESS: DB "PRESS TO CONTINUE." + DB EOL + DB ">" +PRESSL EQU $-PRESS + +POSIT: DB " POSITION" + DB EOL + DB EOL + DB "POSITION 1-7 " +POSITL EQU $-POSIT + +WDRIV: DB EOL + DB "DRIVE 0 OR 1 " +WDRIVL EQU $-WDRIV + +DEFALT: DB "(DEFAULT IS " +DEFNUM: DB "0) >" +DEFALL EQU $-DEFALT + +SING: DB EOL + DB "SAVING" +SINGL EQU $-SING + +RING: DB EOL + DB "RESTORING" +RINGL EQU $-RING + +PTION: DB " POSITION " +PDO: DB "1 ..." + DB EOL +PTIONL EQU $-PTION + +ENDTST: DB "END" + + END + diff --git a/colorcomputer/dispatch.src b/colorcomputer/dispatch.src new file mode 100644 index 0000000..a56870a --- /dev/null +++ b/colorcomputer/dispatch.src @@ -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 POPSTK ; 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 + diff --git a/colorcomputer/ioprims.src b/colorcomputer/ioprims.src new file mode 100644 index 0000000..30766fb --- /dev/null +++ b/colorcomputer/ioprims.src @@ -0,0 +1,859 @@ + PAGE + SBTTL "--- OS EQUATES ---" + +SCREEN EQU $400 ; START OF SCREEN RAM +ENDSCR EQU $600 ; END OF SCREEN RAM +POLCAT EQU $A000 ; KEYCODE FETCH VECTOR +CHROUT EQU $A002 ; PRINT CHAR TO DEVICE +DEVNUM EQU $6F ; $00 = SCREEN, $FE = PRINTER +CURSOR EQU $88 ; ABSOLUTE CURSOR ADDRESS +INT60 EQU $FF03 ; 60HZ INTERRUPT CONTROL +ROMON EQU $FFDE ; ROM ENABLE +ROMOFF EQU $FFDF ; ROM DISABLE +MEMTOP EQU $FE ; TOP PAGE OF AVAILABLE RAM + +EOL EQU $0D ; END-OF-LINE CHARACTER +BS EQU $08 ; BACKSPACE CHARACTER +SPACE EQU $20 ; SPACE CHARACTER +CDURAT EQU 5 ; DURATION OF KEYCLICKS +CFREQ EQU 25 ; FREQUENCY OF KEYCLICKS +BDURAT EQU 10 ; DURATION OF RAZZ +BFREQ EQU 500 ; FREQUENCY OF RAZZ +FLASH EQU $180 ; CURSOR BLINK FREQUENCY + + PAGE + SBTTL "I/O PRIMITIVES" + + ; ------------------ + ; ENABLE ROM FOR I/O + ; ------------------ + +; NO LONGER NEEDED IN 0S9 VERSION [ASK 5/17/85]**************************** +ROMIN: STA IHOLD ; SAVE [A] + LDA INT60 ; ENABLE 60HZ INTERRUPT + ORA #%00000001 + STA ROMON + STA INT60 + ANDCC #%10101111 ; INTERRUPTS ON + LDA IHOLD ; RESTORE [A] + RTS + + ; ------------------ + ; ACCESS OS KEY-READ + ; ------------------ + +;CATPOL: BSR ROMIN +;CPL: JSR MYCAT ; TO NON-ROM ROUTINE OF POLCAT +; BEQ CPL + +CATPOL: JSR MYCAT + BEQ CATPOL + RTS + + ; ---------------------- + ; DISABLE ROM FOR PAGING + ; ---------------------- + +ROMOUT: STA IHOLD ; SAVE [A] +; ORCC #%01010000 ; DISABLE INTERUPTS +; LDA INT60 +; ANDA #%11111110 ; DISABLE 60HZ INTERRUPT +; STA INT60 + STA ROMOFF ; AND ROM + LDA IHOLD ; RESTORE [A] + RTS + + ; -------------------- + ; ACCESS OS CHAR-PRINT + ; -------------------- + +;OUTCHR: BSR ROMIN +; JSR MYCHR ;CHROUT COPIED +; BRA ROMOUT + +OUTCHR: JMP MYCHR + + ; ----------------- + ; READ A SINGLE KEY + ; ----------------- + + ; EXIT: KEYCODE IN [A] + +BADKEY: JSR BOOP ; RAZZ + BRA WINK ; AND TRY AGAIN + +GETKEY: PSHS U,X,Y,B ; SAVE THESE + +; BSR ROMIN ;[ASK 5/15/85] + +WINK: LDY #FLASH*4 + STY CYCLE ; LONG DELAY + LDA #%10000000 + STA BLINK ; INIT CURSOR MASK +GK: JSR MYCAT ; (POLCAT COPIED) LET OS DO THE WORK + INC RAND1 ; GENERATE RANDOMNESS + BNE GKZ + INC RAND2 +GKZ: TST CFLAG ; BLINK CURSOR? + BEQ NOBLIN ; NOT IF [CFLAG]=0 + LDY CYCLE + LEAY -1,Y + STY CYCLE ; TIME TO BLINK? + BNE KTEST ; NOT YET + LDY #FLASH ; ELSE RESET BLINK TIMER + STY CYCLE + LDB BLINK + EORB #%10000000 ; FLIP CURSOR MASK + STB BLINK +KTEST: LDX CURSOR + LDB ,X + ANDB #%01111111 + ORB BLINK + STB ,X +NOBLIN: TSTA + BEQ GK ; 0 = NO KEY YET + TST CFLAG + BEQ QKEY + ANDB #%01111111 ; CLEAR CURSOR + STB ,X + + ; SCREEN KEYCODE IN [A] + +QKEY: CMPA #EOL ; "ENTER" IS FINE + BEQ CLICK + CMPA #BS ; SO IS "LEFT ARROW" + BEQ CLICK + + CMPA #$61 ; LOWER-CASE ALPHA? + BLO PKICK ; NO, CHECK FOR OTHERS + CMPA #$7B ; NOTHING ABOVE "z" IS LEGAL + BHS BADKEY + SUBA #$20 ; CONVERT TO UPPER-CASE ALPHA + BRA CLICK + +PKICK: CMPA #$5B ; NOTHING BETWEEN "Z" AND "a" + BHS BADKEY ; IS LEGAL + CMPA #$20 ; NOTHING BELOW "SPACE" + BLO BADKEY ; IS LEGAL EITHER + + ; "CLICK" SOUND FOR KEYS + +CLICK: STA IOCHAR ; SAVE KEY HERE + JSR AINIT ; ENABLE SOUND + LDB #CDURAT +TICK: LDA #%11111110 + STA $FF20 + BSR CDELAY + LDA #%00000010 + STA $FF20 + BSR CDELAY + DECB + BNE TICK + PULS U,X,Y,B ; RESTORE THINGS + LDA IOCHAR ; RETRIEVE THE KEYPRESS + RTS + +; JMP ROMOUT ; AND SWITCH OUT THE ROMS [ASK 5/15/85] + + ; DELAY FOR KEYCLICK + +CDELAY: LDX #CFREQ +CDEL: LEAX -1,X + BNE CDEL + RTS + + ; ------------------- + ; READ A LINE OF TEXT + ; ------------------- + + ; ENTRY: [ARG1] HAS ADDRESS OF CHAR BUFFER + ; LENGTH OF BUFFER IN 1ST BYTE + ; EXIT: # CHARS READ IN [A] + +INPUT: JSR LINOUT ; FLUSH OUTPUT BUFFER + CLR LINCNT ; RESET LINE COUNTER + CLR DEVNUM ; POINT TO SCREEN + LDX ARG1 ; GET ADDRESS OF INPUT BUFFER + LDB ,X+ ; GET MAX # CHARS + SUBB #2 ; LEAVE A MARGIN FOR ERROR + STB BINDEX ; SAVE MAX # CHARS + STB CFLAG ; ENABLE CURSOR + + CLRB ; RESET INDEX +INLOOP: JSR GETKEY ; KEY IN [A] AND [IOCHAR] + CMPA #EOL ; IF EOL, + BEQ ENDLIN ; LINE IS DONE + CMPA #BS ; IF BACKSPACE, + BEQ GOBACK ; TAKE CARE OF IT + + CMPA #$41 ; IF LOWER THAN ASCII "A," + BLO SENDCH ; SEND THE CHARACTER + ADDA #$20 ; ELSE CONVERT TO LOWER-CASE + +SENDCH: STA B,X ; SEND CHAR TO BUFFER + INCB ; UPDATE INDEX +TOSCR: LDA IOCHAR ; RETRIEVE KEY CHAR + BSR CHAR ; ECHO CHAR TO SCREEN + CMPB BINDEX ; BUFFER FILLED? + BHS NOMORE ; YES -- INSIST ON BS OR EOL + CMPB #61 ; 2 SCREEN LINES FILLED? + BLO INLOOP ; NO, KEEP GOING + + ; LINE FULL; INSIST ON EOL OR BACKSPACE + +NOMORE: JSR GETKEY ; GET NEXT KEY + CMPA #EOL ; IF EOL, + BEQ ENDLIN ; WE'RE FINE + CMPA #BS ; BACKSPACE + BEQ GOBACK ; IS OKAY TOO + JSR BOOP + BRA NOMORE ; ELSE PERSIST + + ; HANDLE BACKSPACE + +GOBACK: DECB ; BACK UP CHAR COUNT + BPL TOSCR ; SEND TO SCREEN IF NO UNDERFLOW + CLRB ; ELSE RESET COUNT + JSR BOOP ; RAZZ + BRA INLOOP ; AND TRY AGAIN + + ; HANDLE EOL + +ENDLIN: STA B,X ; PUT EOL IN BUFFER + BSR CHAR ; AND ON SCREEN + INCB ; UPDATE CHAR COUNT + STB BINDEX ; SAVE IT HERE + + ; FALL THROUGH TO ... + + ; --------------------- + ; SCRIPT A LINE OF TEXT + ; --------------------- + + ; ENTRY: ADDRESS OF TEXT IN [X] + ; LENGTH OF LINE IN [BINDEX] + +TOPRIN: TST SCRIPT ; SCRIPTING ENABLED? + BEQ INPEX ; NO, EXIT IMMEDIATELY + LDA ZCODE+ZSCRIP+1 ; GET FLAGS BYTE + ANDA #1 ; BIT 0 SET? + BEQ INPEX ; NO, IGNORE THE FOLLOWING + LDA #$FE ; ELSE + STA DEVNUM ; POINT TO PRINTER + LDB BINDEX ; START AT 1ST BUFFER CHAR + +; JSR ROMIN + +SCROUT: LDA ,X+ ; GRAB A CHAR FROM BUFFER + JSR MYCHR + DECB + BNE SCROUT +INPEX: CLR DEVNUM ; POINT BACK TO SCREEN + LDA BINDEX ; RETRIEVE # CHARS IN LINE + RTS + +SFLAG DB 0 ; FLAG TO SAVE SCRIPT STATE + +; JMP ROMOUT ; MAKE SURE ROM IS GONE [ASK 5/15/85] + + ; ------------------- + ; PRINT A SINGLE CHAR + ; ------------------- + + ; ENTRY: ASCII CODE IN [A] + +CHAR: STA IOCHAR ; SAVE CHAR HERE + CLR DEVNUM ; ALWAYS TO SCREEN + PSHS X,Y,B ; SAVE THESE + INC RAND1 ; RANDOMNESS + LDY CURSOR ; GET ADDRESS OF CURSOR + CMPA #EOL ; EOL? + BEQ OUTEOL ; HANDLE IT + CMPY #ENDSCR-1 ; LAST CHAR ON SCREEN? + BLO NOSCRL ; NO SCROLL NECESSARY + + ; SCROLL SCREEN, RETAINING STATUS LINE + +DOSCRL: LDY #ENDSCR-33 ; LAST POSITION IN LINE 14 + STY CURSOR ; MOVE CURSOR + LDX #SCREEN+64 ; [X] POINTS TO "SOURCE" LINE + LDY #SCREEN+32 ; [Y] POINTS TO "DEST" LINE + +SCRL1: LDB #31 ; INIT LINE INDEX + +SCRL2: LDA B,X ; GET CHAR FROM SOURCE LINE + STA B,Y ; MOVE TO DESTINATION LINE + DECB ; CONTINUE TILL + BPL SCRL2 ; ENTIRE LINE IS MOVED + + TFR X,Y ; SOURCE IS NOW DEST + LEAX 32,X ; ADD 32 TO SOURCE ADDRESS + CMPX #ENDSCR ; END OF SCREEN YET? + BLO SCRL1 ; NO, KEEP MOVING + + LDA #$60 ; SPACE CHAR +SCRL3: STA ,Y+ + CMPY #ENDSCR + BLO SCRL3 + +NOSCRL: LDA IOCHAR ; RESTORE CHAR + + ; LOWER-CASE OPTION + +; TST LCASE ; LOWER-CASE CAPABILITY? +; BNE GOCHR ; YES, SEND CHAR AS-IS + + CMPA #$61 ; LESS THAN "a"? + BLO GOCHR ; YES, USE AS-IS + SUBA #$20 ; ELSE CONVERT TO UPPER CASE +GOCHR: JSR OUTCHR ; OFF TO THE SCREEN! + PULS X,Y,B ; RESTORE + RTS + + ; EOL SCROLL? + +OUTEOL: CMPY #ENDSCR-32 ; ON LAST SCREEN LINE? + BLO NOSCRL ; NO, HANDLE NORMALLY + BRA DOSCRL ; ELSE MOVE CURSOR UP! + + ; -------------------------- + ; PRINT CONTENTS OF [BUFFER] + ; -------------------------- + +BUFOUT: LDB CHRPNT ; # CHARS IN BUFFER + LDX #BUFFER ; BUFFER ADDRESS + + ; FALL THROUGH TO ... + + ; ------------- + ; PRINT MESSAGE + ; ------------- + + ; ENTRY: ADDRESS OF ASCII MESSAGE IN [X] + ; LENGTH OF MESSAGE IN [B] + +LINE: STB BINDEX ; SAVE LENGTH + CLRB ; INIT INDEX + +LN: LDA B,X ; GET A CHAR + JSR CHAR + INCB + CMPB BINDEX + BLO LN + JMP TOPRIN ; HANDLE SCRIPTING + + ; ---------------- + ; CLEAR THE SCREEN + ; ---------------- + +CLS: LDA #$60 ; SPACE CHARS + LDX #SCREEN +CLS0: STA ,X+ + CMPX #ENDSCR + BLO CLS0 + LDD #SCREEN+32 + STD CURSOR ; CURSOR AT LINE 1 + CLR LINCNT ; RESET LINE COUNTER + CLR CHRPNT ; AND CHAR INDEX + RTS + + ; -------------- + ; SOUND HANDLERS + ; -------------- + +AINIT: LDA $FF01 ; ENABLE SOUND + ANDA #%11110111 + STA $FF01 + LDA $FF03 + ANDA #%11110111 + STA $FF03 + LDA $FF23 + ORA #%00001000 + STA $FF23 + RTS + + ; DO THE RAZZ + +BOOP: PSHS X,D + BSR AINIT + LDB #BDURAT ; GET DURATION +BOOP1: LDA #%11111110 ; CREST OF WAVE + STA $FF20 ; SEND TO DAC + BSR DELAY ; WAIT ... + LDA #%00000010 + STA $FF20 ; TROUGH + BSR DELAY ; WAIT AGAIN + DECB ; ELSE NEXT DURATION + BNE BOOP1 + PULS X,D + RTS + + ; TIME DELAY + +DELAY: LDX #BFREQ ; INIT FREQUENCY +DELOOP: LEAX -1,X + BNE DELOOP + RTS + +;----------------------------------------------------------------------------- + + ; THESE ROM ROUTINES ARE TAKEN FROM THE BASIC UNRAVELED BOOKS + ; + ; THEY ARE HERE FOR THE OS9 VERSION REQUIREMENT OF NO ROM CALLS + ; + ; [ASK 5/15/85] + +; ROM- ROUTINES + +;POLCAT + + +PIA0 EQU $FF00 +PIA1 EQU $FF20 +DA EQU $FF20 + +LPTPOS EQU $9C +LPTWID EQU $9B +LPTBTD EQU $95 +LPTLND EQU $97 + +KEYBUF EQU $0152 +CASFLG EQU $011A +DEBVAL EQU $011B + + +RDYTMR EQU $985 +DCDRV EQU $EB +DRGRAM EQU $986 +DCTRK EQU $EC +DSKREG EQU $FF40 +DCSTA EQU $F0 +DCOPC EQU $EA +DR0TRK EQU $97E +FDCREG EQU $FF48 +ZERO EQU $8A +DSEC EQU $ED +DNMIVC EQU $983 +DCBPT EQU $EE +NMIFLG EQU $982 +SKP2 EQU $8C + + + ; IRQ HANDLER NEEDED FOR RDYTMR + +DIRQSV: LDA PIA0+3 + BPL DRTI + LDA PIA0+2 + LDA RDYTMR + BEQ DRTI + DECA + STA RDYTMR + BNE DRTI + LDA DRGRAM + ANDA #$B0 + STA DRGRAM + STA DSKREG +DRTI: RTI + + + +LA1AE: JMP LA7D3 + +MYCAT: PSHS U,X,B + LDU #PIA0 + LDX #KEYBUF + CLRA + DECA + PSHS X,A + STA 2,U +LA1D5: ROL 2,U + BCC LA220 + INC ,S + BSR LA239 + STA 1,S + EORA ,X + ANDA ,X + LDB 1,S + STB ,X+ + TSTA + BEQ LA1D5 + LDB 2,U + STB 2,S + + LDB #$F8 +LA1F1: ADDB #8 + LSRA + BCC LA1F1 + ADDB ,S + + BEQ LA244 + CMPB #26 + BHI LA246 + ORB #$40 + BSR LA22E + ORA CASFLG + BNE LA20B + ORB #$20 +LA20B: STB ,S + LDX DEBVAL + BSR LA1AE + LDB #$FF + BSR LA237 + INCA + BNE LA220 +LA21A: LDB 2,S + BSR LA237 + CMPA 1,S +LA220: PULS X,A + + BNE LA22B + CMPA #$12 + BNE LA22C + COM CASFLG +LA22B: CLRA +LA22C: PULS X,U,B,PC +LA22E: LDA #$7F + STA 2,U + LDA ,U + COMA + ANDA #$40 + RTS + +LA237: STB 2,U +LA239: LDA ,U + + ORA #$80 + TST 2,U + BMI LA243 + ORA #$C0 + +LA243: RTS + + +LA244: LDB #51 +LA246: LDX #CONTAB-$36 + CMPB #33 + BLO LA263 + LDX #CONTAB-$54 + CMPB #48 + BHS LA263 + BSR LA22E + CMPB #43 + BLS LA25C + EORA #$40 + +LA25C: TSTA + BNE LA20B + ADDB #$10 + BRA LA20B +LA263: ASLB + + BSR LA22E + BEQ LA269 + INCB +LA269: LDB B,X + BRA LA20B + +CONTAB: DB $5E,$5F + DB $A,$5B + DB $8,$15 + DB $9,$5D + DB $20,$20 + DB $30,$12 + + DB $D,$D + DB $C,$5C + DB $3,$3 + DB $40,$13 + +LA7D1: LDX ZERO +LA7D3: LEAX -1,X + BNE LA7D3 + RTS + +;------------------------ +; COPY OF CHROUT FROM ROM +;------------------------ + +RVEC3 EQU $0167 +CR EQU $0D +VIDRAM EQU $0400 +CURPOS EQU $88 + +; +;MYCHR: JSR RVEC3 ;HOOK INTO RAM THE BOOK SAYS (BUT WHY I ASK) + +MYCHR: PSHS B + LDB DEVNUM + INCB + PULS B + BMI LA2BF + BNE LA30A +;SEND TO CASSETTE NOT NEEDED + +;PRINTER CODE +LA2BF: PSHS CC,A,B,X + ORCC #$50 +LA2C3: LDB PIA1+2 + LSRB + BCS LA2C3 + BSR LA2FB + CLRB + BSR LA2FD + LDB #8 +LA2C8: PSHS B + CLRB + LSRA + ROLB + ASLB + BSR LA2FD + PULS B + DECB + BNE LA2C8 + BSR LA2FB + PULS CC,A + CMPA #CR ;#$0D + BEQ LA2ED + INC LPTPOS + LDB LPTPOS + CMPB LPTWID + BLO LA2F3 +LA2ED: CLR LPTPOS + BSR LA305 + BSR LA305 +LA2F3: LDB PIA1+2 + LSRB + BCS LA2F3 + PULS B,X,PC +LA2FB: LDB #2 +LA2FD: STB DA ;$FF20 + BSR LA302 +LA302: LDX LPTBTD + DB SKP2 +LA305: LDX LPTLND + JMP LA7D3 + + + +LA30A: PSHS A,B,X + LDX CURPOS + CMPA #BS + BNE LA31D + CMPX #VIDRAM + BEQ LA35D + LDA #$60 + STA ,-X + BRA LA344 +LA31D: CMPA #CR + BNE LA32F + LDX CURPOS +LA323: LDA #$60 + STA ,X+ + TFR X,D + BITB #$1F + BNE LA323 + BRA LA344 +LA32F: CMPA #SPACE + BLO LA35D + TSTA + BMI LA342 + CMPA #$40 + BLO LA340 + CMPA #$60 + BLO LA342 + ANDA #$DF +LA340: EORA #$40 +LA342: STA ,X+ +LA344: STX CURPOS + CMPX #VIDRAM+511 + BLS LA35D + LDX #VIDRAM + +LA34E: LDD 32,X + STD ,X++ + CMPX #VIDRAM+$1E0 + BLO LA34E + LDB #$60 + JSR LA92D +LA35D: PULS A,B,X,PC + +LA92D: STX CURPOS +LA92F: STB ,X+ + CMPX #VIDRAM+511 + BLS LA92F + RTS + +;---------------------------------- +;COPY OF DISK CODE FROM ROM SOURCES +;---------------------------------- + + +MYCON: PSHS U,Y,X,D ;AT $D75F IN LISTING + LDA #5 + PSHS A +LD672: CLR RDYTMR + LDB DCDRV + LDX #LD7AA + LDA DRGRAM + ANDA #$A8 + ORA B,X + ORA #$20 + LDB DCTRK + CMPB #22 + BLO LD68B + ORA #$10 +LD68B: TFR A,B + ORA #8 + STA DRGRAM + STA DSKREG + BITB #8 + BNE LD69F + JSR LA7D1 + JSR LA7D1 +LD69F: BSR LD6DE + BNE LD6AD + CLR DCSTA + LDX #LD7A2 + LDB DCOPC + ASLB + JSR [B,X] +LD6AD: PULS A + LDB DCSTA + BEQ LD6BE + DECA + BEQ LD6BE + PSHS A + BSR LD6C5 + BNE LD6AD + BRA LD672 +LD6BE: LDA #120 + STA RDYTMR + PULS PC,U,Y,X,D + +LD6C5: LDX #DR0TRK + LDB DCDRV + CLR B,X + LDA #3 + STA FDCREG + EXG A,A + EXG A,A + BSR LD6DE + BSR LD6FD + ANDA #$10 + STA DCSTA +LD6DD: RTS + +LD6DE: LDX ZERO +LD6E0: LEAX -1,X + BEQ LD6EC + LDA FDCREG + BITA #1 + BNE LD6E0 + RTS +LD6EC: LDA #$D0 + STA FDCREG + EXG A,A + EXG A,A + LDA FDCREG + LDA #$80 + STA DCSTA + RTS + +LD6FD: LDX #8750 +LD700: LEAX -1,X + BNE LD700 + RTS + +LD705: LDA #$80 + DB SKP2 +LD708: LDA #$A0 + PSHS A + LDX #DR0TRK + LDB DCDRV + ABX + LDB ,X + STB FDCREG+1 + CMPB DCTRK + BEQ LD739 + LDA DCTRK + STA FDCREG+3 + STA ,X + LDA #$17 + STA FDCREG + EXG A,A + EXG A,A + BSR LD6DE + BNE LD737 + BSR LD6FD + ANDA #$18 + BEQ LD739 + STA DCSTA +LD737: PULS PC,A + +LD739: LDA DSEC + STA FDCREG+2 + LDX #LD798 + STX DNMIVC + LDX DCBPT + LDA FDCREG + LDA DRGRAM + ORA #$80 + PULS B + LDY ZERO + LDU #FDCREG + COM NMIFLG + ORCC #$50 + STB FDCREG + EXG A,A + EXG A,A + CMPB #$80 + BEQ LD782 + + LDB #2 +LD768: BITB ,U + BNE LD778 + LEAY -1,Y + BNE LD768 +LD770: CLR NMIFLG + ANDCC #$AF + JMP LD6EC + + +;WRITE A SECTOR + +LD778: LDB ,X+ + STB FDCREG+3 + STA DSKREG + BRA LD778 + +LD782: LDB #2 +LD784: BITB ,U + BNE LD78E + LEAY -1,Y + BNE LD784 + BRA LD770 + +LD78E: LDB FDCREG+3 + STB ,X+ + STA DSKREG + BRA LD78E + +LD798: ANDCC #$AF + LDA FDCREG + ANDA #$7C + STA DCSTA + RTS + +LD7A2: DW LD6C5 + DW LD6DD + DW LD705 + DW LD708 + +LD7AA: DB 1 + DB 2 + DB 4 + DB $40 + + + END + diff --git a/colorcomputer/main.src b/colorcomputer/main.src new file mode 100644 index 0000000..f6d614e --- /dev/null +++ b/colorcomputer/main.src @@ -0,0 +1,172 @@ + PAGE + SBTTL "--- MAIN LOOP ---" + +MLOOP: JSR ROMOUT ; FOR SAFETY + DEC RAND2 ; RANDOMNESS + DEC RAND2 + + CLR ARGCNT ; RESET # ARGUMENTS + JSR NEXTPC ; GET NEXT Z-BYTE + STA OPCODE ; SAVE OPCODE + + IF DEBUG + LDB #'0' + JSR DOBUG + LDA OPCODE + ENDIF + + LBPL OP2 ; 2-OP IF POSITIVE + CMPA #176 + BLO OP1 ; IT'S A 1-OP + CMPA #192 + BLO OP0 ; IF NOT A 0-OP ... + + ; HANDLE AN X-OP + +OPEXT: JSR NEXTPC ; GET ARGUMENT BYTE + STA TEMP2 ; HOLD IT HERE + CLR TEMP2+1 ; INIT LOOP INDEX + BRA OPX1 + +OPX0: LDA TEMP2 ; GRAB ARG BYTE + ASLA ; SHIFT TO BITS 7 & 6 + ASLA + STA TEMP2 ; SAVE RESULT + +OPX1: ANDA #%11000000 ; MASK OUT GARBAGE + BNE OPX2 + JSR GETLNG ; 00 = LONG IMMEDIATE + BRA OPXNXT + +OPX2: CMPA #%01000000 + BNE OPX3 + JSR GETSHT ; 01 = SHORT IMMEDIATE + BRA OPXNXT + +OPX3: CMPA #%10000000 + BNE OPX4 ; 11 = NO MORE VARIABLES + JSR GETVAR ; 10 = VARIABLE + +OPXNXT: LDB TEMP2+1 ; GET INDEX + LDX #ARG1 ; BASE ADDR OF ARGS + ABX ; ADD OFFSET IN B + LDD TEMP ; GRAB THE ARGUMENT'S VALUE + STD ,X ; AND SAVE IT + INC ARGCNT ; KEEP TRACK + INC TEMP2+1 ; UPDATE + INC TEMP2+1 ; ARGUMENT INDEX + LDA TEMP2+1 ; DONE 4 ARGS YET? + CMPA #8 + BLO OPX0 ; NO, KEEP GRABBING + + ; DISPATCH THE X-OP + +OPX4: LDB OPCODE ; RETRIEVE THE OPCODE + CMPB #224 ; IS IT AN EXTENDED 2-OP? + LBLO OP2EX ; YES, HANDLE LIKE A 2-OP + ANDB #%00011111 ; ELSE ISOLATE OP BITS + CMPB #NOPSX ; COMPARE TO LEGAL # OF X-OPS + BLO DISPX ; CONTINUE IF OKAY + + ; *** ERROR #1 -- ILLEGAL X-OP *** + + LDA #1 + JSR ZERROR + +DISPX: LDX #OPTX ; X-OP DISPATCH TABLE +DODIS: ASLB ; FORM A WORD-OFFSET INTO IT + ABX ; ADD THE OFFSET + + IF DEBUG + PSHS X + LDB #'1' + JSR DOBUG + PULS X + ENDIF + + JSR [,X] ; HANDLE THE OPCODE + JMP MLOOP ; AND GO BACK FOR ANOTHER + + ; HANDLE A 0-OP + +OP0: LDX #OPT0 ; 0-OP DISPATCH TABLE + LDB OPCODE ; FETCH OPCODE + ANDB #%00001111 ; ISOLATE OP BITS + CMPB #NOPS0 ; OPCODE OUT OF RANGE? + BLO DODIS ; NO, GO DISPATCH IT + + ; *** ERROR #2 -- ILLEGAL 0-OP *** + + LDA #2 + JSR ZERROR + + ; HANDLE A 1-OP + +OP1: ANDA #%00110000 ; ISOLATE ARG BITS + BNE OP1A + JSR GETLNG ; 00 = LONG IMMEDIATE + BRA OP1EX + +OP1A: CMPA #%00010000 + BNE OP1B + JSR GETSHT ; 01 = SHORT IMMEDIATE + BRA OP1EX + +OP1B: CMPA #%00100000 + BEQ OP1C + + ; *** ERROR #3 -- ILLEGAL 1-OP *** + +BADOP1: LDA #3 + JSR ZERROR + +OP1C: JSR GETVAR ; 10 = VARIABLE + +OP1EX: LDD TEMP + STD ARG1 ; GRAB THE ARGUMENT + INC ARGCNT ; ONE ARGUMENT + LDX #OPT1 ; ADDR OF 1-OP DISPATCH TABLE + LDB OPCODE ; RESTORE OPCODE + ANDB #%00001111 ; ISOLATE OP BITS + CMPB #NOPS1 ; IF OPCODE OUT OF RANGE, + BHS BADOP1 ; REPORT IT + BRA DODIS ; ELSE DISPATCH THE 1-OP + + ; HANDLE A 2-OP + +OP2: ANDA #%01000000 ; ISOLATE 1ST ARG BIT + BNE OP2A + JSR GETSHT ; 0 = SHORT IMMEDIATE + BRA OP2B + +OP2A: JSR GETVAR ; 1 = VARIABLE + +OP2B: LDD TEMP ; GRAB VALUE + STD ARG1 ; SAVE IN ARG1 + INC ARGCNT + + LDA OPCODE ; RESTORE OPCODE + ANDA #%00100000 ; ISOLATE 2ND ARG BIT + BNE OP2C + JSR GETSHT ; 0 = SHORT IMMEDIATE + BRA OP2D + +OP2C: JSR GETVAR ; 1 = VARIABLE + +OP2D: LDD TEMP ; GRAB 2ND VALUE + STD ARG2 ; STORE AS ARG2 + INC ARGCNT + +OP2EX: LDX #OPT2 ; ADDR OF 2-OP DISPATCH TABLE + LDB OPCODE ; RESTORE YET AGAIN + ANDB #%00011111 ; ISOLATE OP BITS + CMPB #NOPS2 ; OPCODE IN RANGE? + LBLO DODIS ; YES, GO DISPATCH IT + + ; *** ERROR #4 -- ILLEGAL 2-OP *** + +BADOP2: LDA #4 + JSR ZERROR + + END + diff --git a/colorcomputer/mainsubs.src b/colorcomputer/mainsubs.src new file mode 100644 index 0000000..0716eb7 --- /dev/null +++ b/colorcomputer/mainsubs.src @@ -0,0 +1,241 @@ + PAGE + SBTTL "--- MAIN LOOP SUPPORT ---" + + ; ----------------------- + ; FETCH A SHORT IMMEDIATE + ; ----------------------- + +GETSHT: JSR NEXTPC ; NEXT Z-BYTE IS + STA TEMP+1 ; THE LSB OF ARGUMENT + CLR TEMP ; MSB IS ZERO + RTS + + ; ---------------------- + ; FETCH A LONG IMMEDIATE + ; ---------------------- + +GETLNG: JSR NEXTPC ; NEXT Z-BYTE IS MSB + PSHS A ; SAVE ON STACK + JSR NEXTPC ; NOW GRAB LSB + STA TEMP+1 ; STORE IT + PULS A ; RETRIEVE MSB + STA TEMP ; AND STORE IT + RTS + + ; ---------------- + ; FETCH A VARIABLE + ; ---------------- + + ; GET WITHIN AN OPCODE + +VARGET: TSTA ; IF NON-ZERO, + BNE GETVR1 ; ACCESS A VARIABLE + JSR POPSTK ; ELSE TAKE VAR OFF STACK + BRA PSHSTK ; WITHOUT ALTERING STACK + +GETVAR: JSR NEXTPC ; GRAB VAR-TYPE BYTE + TSTA ; IF ZERO, + BEQ POPSTK ; VALUE IS ON STACK + + ; IS VARIABLE LOCAL OR GLOBAL? + +GETVR1: CMPA #16 + BHS GETVRG ; IT'S GLOBAL + + ; HANDLE A LOCAL VARIABLE + +GETVRL: DECA ; FORM A ZERO-ALIGNED INDEX + ASLA ; WORD INDEX + LDX #LOCALS ; INTO LOCAL VAR TABLE + TFR A,B ; MOVE AND +GTVX: ABX ; ADD INDEXING OFFSET + LDD ,X ; FETCH VALUE + STD TEMP ; AND RETURN IT + RTS + + ; HANDLE A GLOBAL VARIABLE + +GETVRG: SUBA #16 ; ZERO-ALIGN + LDX GLOBAL ; BASE OF GLOBAL VAR TABLE + TFR A,B ; CONVERT TO WORD-ALIGNED INDEX + ABX ; BY ADDING OFFSET TWICE (CLEVER, EH?) + BRA GTVX ; 2ND ADD ABOVE + + ; -------------- + ; RETURN A VALUE + ; -------------- + + ; RETURN FROM WITHIN OPCODE + +VARPUT: TSTA ; IF NON-ZERO + BNE PUTVR1 ; ACCESS A VARIABLE + PULU D ; ELSE FLUSH TOP ITEM OFF STACK + CMPU #TOPSTA + BHI UNDER ; WATCH FOR UNDERFLOW! + BRA PSHSTK ; AND PUSH [TEMP] ONTO STACK + + ; RETURN A ZERO + +RET0: CLRA ; CLEAR MSB + + ; RETURN BYTE IN [A] + +PUTBYT: STA TEMP+1 ; USE [A] AS LSB + CLR TEMP ; ZERO MSB + + ; RETURN VALUE IN [TEMP] + +PUTVAL: LDX TEMP ; GET VALUE IN [TEMP] + PSHS X ; AND HOLD ON TO IT + JSR NEXTPC ; GET VAR-TYPE BYTE + PULS X ; RETRIEVE VALUE + STX TEMP ; PUT IT BACK IN [TEMP] + TSTA ; IF TYPE-BYTE IS ZERO, + BEQ PSHSTK ; VALUE GOES TO THE STACK + + ; LOCAL OR GLOBAL? + +PUTVR1: CMPA #16 + BHS PUTVLG ; IT'S GLOBAL + + ; HANDLE A LOCAL VARIABLE + +PUTVLL: DECA + ASLA + TFR A,B + LDX #LOCALS ; INTO LOCAL VARIABLE TABLE +PTVX: ABX + LDD TEMP + STD ,X + RTS + + ; HANDLE A GLOBAL VARIABLE + +PUTVLG: SUBA #16 ; ZERO-ALIGN + LDX GLOBAL ; BASE OF GLOBAL VAR TABLE + TFR A,B ; FORM WORD-ALIGNED INDEX + ABX ; BY ADDING OFFSET TO BASE + BRA PTVX ; TWICE + + ; -------------------- + ; PUSH [TEMP] TO STACK + ; -------------------- + +PSHSTK: LDD TEMP + + ; PUSH [D] TO STACK + +PSHDZ: PSHU D + CMPU #ZSTACK + BLO OVER + RTS + + ; ------------------------- + ; POP STACK, SAVE IN [TEMP] + ; ------------------------- + +POPSTK: PULU D ; PULL A WORD + STD TEMP ; SAVE IT IN [TEMP] + CMPU #TOPSTA + BHI UNDER + RTS + + ; *** ERROR #5 -- Z-STACK UNDERFLOW *** + +UNDER: LDA #5 + JMP ZERROR + + ; *** ERROR #6 -- Z-STACK OVERFLOW *** + +OVER: LDA #6 + JMP ZERROR + + ; --------------- + ; PREDICATE FAILS + ; --------------- + +PREDF: JSR NEXTPC ; GET 1ST BRANCH BYTE + TSTA ; IF BIT 7 ISN'T SET, + BPL PREDB ; DO THE BRANCH + +PREDNB: ANDA #%01000000 ; ELSE TEST BIT 6 + BNE PNBX ; ALL DONE IF SET + JSR NEXTPC ; ELSE SKIP OVER 2ND BRANCH BYTE +PNBX: RTS ; BEFORE LEAVING + + ; ------------------ + ; PREDICATE SUCCEEDS + ; ------------------ + +PREDS: JSR NEXTPC + TSTA ; IF BIT 7 IS SET, + BPL PREDNB ; BRANCH ON PREDICATE FAILURE + + ; ---------------- + ; PERFORM A BRANCH + ; ---------------- + +PREDB: BITA #%01000000 ; LONG OR SHORT BRANCH? + BEQ PREDLB ; LONG IF BIT 6 IS OFF + ANDA #%00111111 ; ELSE FORM SHORT OFFSET + STA TEMP+1 ; USE AS LSB OF BRANCH OFFSET + CLR TEMP ; ZERO MSB OF OFFSET + BRA PREDB1 ; AND DO THE BRANCH + + ; HANDLE A LONG BRANCH + +PREDLB: ANDA #%00111111 ; FORM MSB OF OFFSET + BITA #%00100000 ; CHECK SIGN OF 14-BIT VALUE + BEQ DOB2 ; IT'S POSITIVE + ORA #%11100000 ; ELSE EXTEND SIGN BITS +DOB2: PSHS A ; SAVE MSB OF BRANCH + JSR NEXTPC ; GRAB NEXT Z-BYTE + STA TEMP+1 ; USE AS LSB OF BRANCH + PULS A + STA TEMP ; RETRIEVE MSB + + ; BRANCH TO Z-ADDRESS IN [TEMP] + +PREDB1: LDD TEMP ; IF OFFSET IS ZERO, + LBEQ ZRFALS ; DO AN "RFALSE" + SUBD #1 ; IF OFFSET IS ONE, + LBEQ ZRTRUE ; DO AN "RTRUE" + +PREDB3: SUBD #1 ; D = OFFSET-2 + STD TEMP ; SAVE NEW OFFSET + + ; USE [VAL] TO HOLD TOP 9 BITS OF OFFSET + + STA VAL+1 + CLRB + ASLA ; EXTEND THE SIGN BIT + ROLB ; SHIFT CARRY TO BIT 0 OF [B] + STB VAL ; SAVE AS UPPER BYTE OF OFFSET + + LDA TEMP+1 ; GET LOW BYTE OF OFFSET + ANDCC #%11111110 ; CLEAR CARRY + ADCA ZPCL ; ADD LOW BYTE OF CURRENT ZPC + BCC PDB0 ; IF OVERFLOWED, + + INC VAL+1 ; UPDATE + BNE PDB0 ; UPPER + INC VAL ; 9 BITS + +PDB0: STA ZPCL ; LOW-BYTES CALCED + + LDD VAL ; IF 9 UPPER BITS ARE ZERO, + BEQ PDB1 ; NO NEED TO CHANGE PAGES + + LDA VAL+1 ; ELSE ADD MIDDLE BYTES + ANDCC #%11111110 ; CLEAR CARRY + ADCA ZPCM + STA ZPCM + LDA VAL ; NOW ADD THE TOP BITS + ADCA ZPCH ; USING PREVIOUS CARRY + ANDA #%00000001 ; ISOLATE BIT 0 + STA ZPCH + CLR ZPCFLG ; CHANGED PAGES +PDB1: RTS + + END + diff --git a/colorcomputer/objects.src b/colorcomputer/objects.src new file mode 100644 index 0000000..2c0bdc2 --- /dev/null +++ b/colorcomputer/objects.src @@ -0,0 +1,77 @@ + PAGE + SBTTL "--- OBJECT & PROPERTY HANDLERS ---" + +PROPB: LDA ARG1+1 + JSR OBJLOC + LDX TEMP + LDD 7,X + ADDD #ZCODE + STD TEMP ; EXPECTED HERE + TFR D,X + LDB ,X ; GET FIRST BYTE (LENGTH OF DESC) + ASLB ; WORD-ALIGN IT + INCB ; AND POINT JUST PAST IT + RTS + +PROPN: LDX TEMP + ABX + LDA ,X + ANDA #%00011111 + RTS + +PROPL: LDX TEMP + ABX + LDA ,X + RORA + RORA + RORA + RORA + RORA + ANDA #%00000111 + RTS + +PROPNX: BSR PROPL + STA VAL +PPX: INCB + DEC VAL + BPL PPX + INCB + RTS + +FLAGSU: LDA ARG1+1 + JSR OBJLOC + LDA ARG2+1 + CMPA #16 + BLO FLGSU1 + SUBA #16 + LDX TEMP + LEAX 2,X + STX TEMP + +FLGSU1: STA VAL+1 + LDD #1 + STD MASK + LDB #15 + SUBB VAL+1 + +FLGSU2: BEQ FLGSU3 + ASL MASK+1 + ROL MASK + DECB + BRA FLGSU2 + +FLGSU3: LDX TEMP + LDD ,X + STD VAL + RTS + +OBJLOC: LDB #9 ; NUMBER IN [A] TIMES 9 + MUL + ADDD #53 ; PLUS 53 + ADDD ZCODE+ZOBJEC ; Z-ADDRESS OF OBJECT TABLE + ADDD #ZCODE ; FORM ABSOLUTE ADDRESS + STD TEMP + RTS + + END + diff --git a/colorcomputer/ops0.src b/colorcomputer/ops0.src new file mode 100644 index 0000000..86718a3 --- /dev/null +++ b/colorcomputer/ops0.src @@ -0,0 +1,131 @@ + PAGE + SBTTL "--- 0-OPS ---" + + ; ----- + ; RTRUE + ; ----- + + ; Simulate a RETURN 1 + +ZRTRUE: LDB #1 + +ZRT: CLRA + STD ARG1 ; SAVE VALUE HERE + JMP ZRET + + ; ------ + ; RFALSE + ; ------ + + ; Simulate a RETURN 0 + +ZRFALS: CLRB + BRA ZRT + + ; ------ + ; PRINTI + ; ------ + + ; Print the Z-string immediately following the opcode + +ZPRI: LDA ZPCH ; MOVE ZPC INTO MPC + STA MPCH + LDD ZPCM + STD MPCM + CLR MPCFLG ; ZERO MPC FLAG + + JSR PZSTR ; PRINT THE STRING AT [MPC] + + LDA MPCH ; UPDATE ZPC FROM MPC + STA ZPCH + LDD MPCM + STD ZPCM + LDA MPCFLG ; ALSO UPDATE FLAG + STA ZPCFLG + LDD MPCPNT ; AND PAGE POINTER + STD ZPCPNT + + ; FALL THROUGH TO ... + + ; ---- + ; NOOP + ; ---- + +ZNOOP: RTS + + ; ------ + ; PRINTR + ; ------ + + ; Execute a PRINTI, followed by CRLF and RTRUE + +ZPRR: BSR ZPRI + JSR ZCRLF + BRA ZRTRUE + + ; ------ + ; RSTACK + ; ------ + + ; Execute a RETURN, with CALL value on top of the stack + +ZRSTAK: JSR POPSTK + STD ARG1 ; TOS WAS LEFT IN [D] + JMP ZRET + + ; ------ + ; VERIFY + ; ------ + + ; Verify the game code + +ZVER: JSR VERNUM ; DISPLAY ZIP VERSION CODE + LDD ZCODE+ZLENTH ; GET LENGTH OF Z-CODE + STD ARG2 ; IN WORDS + + ; CLEAR VARIABLES + + CLRA + CLRB + STD ARG1 + STD ARG3 ; BIT 17 OF Z-CODE LENGTH + STD TEMP ; BYTE COUNT + + ; CONVERT Z-CODE LENGTH TO BYTES + + ASL ARG2+1 ; BOTTOM 8 BITS + ROL ARG2 ; MIDDLE 8 BITS + ROL ARG3+1 ; 17TH BIT OF LENGTH + + LDA #$40 ; 1ST 64 BYTES + STA TEMP+1 ; ARE NOT CHECKED + JSR SETWRD ; [TEMP] POINTS TO FIRST BYTE + + LDA #ARG3 ; PATCH [GETBYT] ROUTINE + STA PATCH ; SO PRELOAD WILL BE READ FROM DISK + +VSUM: JSR GETBYT ; GET A BYTE + CLRB ; CLEAR CARRY + ADCA ARG1+1 ; ADD TO SUM + STA ARG1+1 + BCC VSUM0 + INC ARG1 + +VSUM0: LDD MPCM ; END OF GAME YET? + CMPD ARG2 + BNE VSUM + + LDA MPCH ; ALSO CHECK TOP BIT + CMPA ARG3+1 + BNE VSUM + + LDA #ZPURE + STA PATCH ; UNPATCH [GETBYT] + + LDD ZCODE+ZCHKSM ; GET CHECKSUM + CMPD ARG1 ; SAME AS CALCULATED? + LBEQ PREDS ; YES, PREDICATE SUCCEEDS + JMP PREDF ; ELSE FAILURE ... + + END + diff --git a/colorcomputer/ops1.src b/colorcomputer/ops1.src new file mode 100644 index 0000000..8ad5c90 --- /dev/null +++ b/colorcomputer/ops1.src @@ -0,0 +1,274 @@ + PAGE + SBTTL "--- 1-OPS ---" + + ; ----- + ; ZERO? + ; ----- + + ; Is arg1 equal to zero? [PRED] + +ZZERO: LDD ARG1 + LBEQ PREDS + JMP PREDF + + ; ----- + ; NEXT? + ; ----- + + ; Return the NEXT pointer in object "arg1"; fail if + ; none left, and return zero [VALUE][PRED] + +ZNEXT: LDA ARG1+1 + JSR OBJLOC + LDB #5 ; SAME AS FIRST? + BRA FIRST1 + + ; ------ + ; FIRST? + ; ------ + + ; Return the FIRST pointer in object "arg1"; fail if + ; none, and return zero [VALUE][PRED] + +ZFIRST: LDA ARG1+1 + JSR OBJLOC + LDB #6 + +FIRST1: LDX TEMP + LDA B,X ; FETCH SLOT + STA TEMP+1 ; SAVE HERE + PSHS A ; AND ON STACK + CLR TEMP ; ZERO MSB + JSR PUTVAL + PULS A + TSTA + LBEQ PREDF ; FAILURE + JMP PREDS ; OR SUCCESS + + ; --- + ; LOC + ; --- + + ; Return the object containing object "arg1"; zero if none [VALUE] + +ZLOC: LDA ARG1+1 + JSR OBJLOC + LDX TEMP + LDA 4,X + STA TEMP+1 + CLR TEMP + JMP PUTVAL + + ; ------ + ; PTSIZE + ; ------ + + ; Return length of prop table "arg1" in bytes [VALUE] + +ZPTSIZ: LDD ARG1 + ADDD #ZCODE + SUBD #1 + STD TEMP + CLRB + JSR PROPL + INCA + JMP PUTBYT + + ; --- + ; INC + ; --- + + ; Increment arg1 [VALUE] + +ZINC: LDA ARG1+1 + JSR VARGET + LDD TEMP + ADDD #1 +ZINC1: STD TEMP + PSHS D + LDA ARG1+1 + JSR VARPUT + PULS D + STD TEMP + RTS + + ; --- + ; DEC + ; --- + + ; Decrement arg1 [VALUE] + +ZDEC: LDA ARG1+1 + JSR VARGET + LDD TEMP + SUBD #1 + BRA ZINC1 + + ; ------ + ; PRINTB + ; ------ + + ; PRINT the string pointed to by BYTE-pointer "arg1" + +ZPRB: LDD ARG1 + STD TEMP + JSR SETWRD + JMP PZSTR + + ; ------ + ; REMOVE + ; ------ + + ; Move object "arg1" to pseudo-object #0 + +ZREMOV: LDA ARG1+1 + JSR OBJLOC + LDX TEMP + LDA 4,X + BEQ REMVEX ; NO OBJECT + + PSHS X ; SAVE [TEMP] + + JSR OBJLOC + LDX TEMP + LDA 6,X + CMPA ARG1+1 + BNE REMVC1 + + PULS X ; RETRIEVE FORMER [TEMP] + PSHS X ; SAVE COPY ON STACK + + LDA 5,X ; OLD [TEMP] IS IN [X] + LDX TEMP + STA 6,X + + BRA REMVC2 + +REMVC1: JSR OBJLOC + LDX TEMP + LDA 5,X + CMPA ARG1+1 + BNE REMVC1 + + PULS X + PSHS X + + LDA 5,X + LDX TEMP + STA 5,X + +REMVC2: PULS X + CLR 4,X + CLR 5,X + +REMVEX: RTS + + ; ------ + ; PRINTD + ; ------ + + ; Print short description of object "arg1" + +ZPRD: LDA ARG1+1 + +PRNTDC: JSR OBJLOC + LDX TEMP + LDD 7,X + ADDD #1 ; INCREMENT + STD TEMP ; AND SAVE + JSR SETWRD + JMP PZSTR + + ; ------ + ; RETURN + ; ------ + + ; Return from a CALL with value "arg1" + +ZRET: LDU OZSTAK ; STAY IN SYNC! + JSR POPSTK ; POP # LOCALS + STB VAL ; SAVE COUNT HERE + + COMA ; COMPLEMENT [A] + CMPA VAL ; SHOULD BE OPPOSITE OF [B] + BNE RETERR ; IF NOT, STACK IS BAD (BM 11/24/84) + + TSTB ; CHECK # LOCALS + BEQ RET2 ; SKIP IF NO LOCALS + + ; RESTORE LOCAL VARIABLES + + LDX #LOCALS ; SET UP A POINTER + ASLB ; WORD-ALIGN THE INDEX + ABX ; [X] POINTS TO LAST LOCAL VAR + +RET1: JSR POPSTK ; POP A VALUE ([X] UNAFFECTED) + STD ,--X ; SAVE IN [LOCALS], UPDATE INDEX + DEC VAL + BNE RET1 ; LOOP TILL ALL LOCALS POPPED + + ; RESTORE OTHER VARIABLES + +RET2: JSR POPSTK + STD ZPCH ; RESTORE TOP 9 BITS OF ZPC + JSR POPSTK + STB ZPCL ; RESTORE LOWER 8 BITS OF ZPC + JSR POPSTK + STD OZSTAK ; AND OLD ZSP + CLR ZPCFLG ; PC NO LONGER VALID + + LDD ARG1 + STD TEMP ; PASS THE RETURN VALUE + JMP PUTVAL ; TO PUTVAL + + ; *** ERROR #15: Z-STACK DESTROYED *** + +RETERR: LDA #15 + JMP ZERROR + + ; ---- + ; JUMP + ; ---- + + ; Branch to location pointed to by 16-bit 2's-comp "arg1" + +ZJUMP: LDD ARG1 ; TREAT LIKE A BRANCH + SUBD #1 ; THAT ALWAYS SUCCEEDS + STD TEMP + JMP PREDB3 + + ; ----- + ; PRINT + ; ----- + + ; Print the z-string pointed to by WORD-pointer "arg1" + +ZPRINT: LDD ARG1 + STD TEMP ; TELL SETSTR + JSR SETSTR ; WHERE THE STRING RESIDES + JMP PZSTR ; AND PRINT IT + + ; ----- + ; VALUE + ; ----- + + ; Return value of arg1 [VALUE] + +ZVALUE: LDA ARG1+1 ; GRAB VARIABLE ID + JSR VARGET ; FETCH ITS VALUE + JMP PUTVAL ; AND RETURN IT + + ; ---- + ; BCOM + ; ---- + + ; Complement arg1 [VALUE] + +ZBCOM: LDD ARG1 ; GRAB ARGUMENT + COMA ; COMPLEMENT MSB + COMB ; AND LSB + STD TEMP ; AND PASS TO PUTVAL + JMP PUTVAL + + END + diff --git a/colorcomputer/ops2.src b/colorcomputer/ops2.src new file mode 100644 index 0000000..1e12605 --- /dev/null +++ b/colorcomputer/ops2.src @@ -0,0 +1,500 @@ + PAGE + SBTTL "--- 2-OPS ---" + + ; ----- + ; LESS? + ; ----- + + ; Is arg1 less than arg2? [PRED] + +ZLESS: LDD ARG1 + STD TEMP + LDD ARG2 + STD VAL + BRA CEXIT + + ; ----- + ; GRTR? + ; ----- + + ; Is arg1 greater than arg2? [PRED] + +ZGRTR: LDD ARG1 + STD VAL + LDD ARG2 + STD TEMP + BRA CEXIT + + ; ------ + ; DLESS? + ; ------ + + ; Decrement variable "arg1"; succeed if new value + ; is less than arg2 [PRED] + +ZDLESS: JSR ZDEC ; DECREMENT THE VARIABLE + LDD ARG2 + STD VAL + BRA CEXIT ; AND COMPARE + + ; ------ + ; IGRTR? + ; ------ + + ; Increment variable "arg1"; succeed if new value is + ; greater than arg2 [PRED] + +ZIGRTR: JSR ZINC ; INCREMENT THE VARIABLE + LDD TEMP + STD VAL + LDD ARG2 + STD TEMP + +CEXIT: BSR SCOMP + BLO POK +PBAD: JMP PREDF + + ; ----------------- + ; SIGNED COMPARISON + ; ----------------- + +SCOMP: LDA VAL ; ARE ARGUMENTS + EORA TEMP ; SIGNED THE SAME? + BPL SCMP ; YES, DO ORDINARY COMPARE + LDA VAL ; ELSE COMPARE + CMPA TEMP ; ONLY THE HIGH BYTES + RTS + +SCMP: LDD TEMP + CMPD VAL + RTS + + ; --- + ; IN? + ; --- + + ; Is object "arg1" contained in object "arg2?" [PRED] + +ZIN: LDA ARG1+1 + JSR OBJLOC + LDX TEMP + LDA ARG2+1 + CMPA 4,X + BNE PBAD +POK: JMP PREDS + + ; ---- + ; BTST + ; ---- + + ; Is every "on" bit in arg1 also "on" in arg2? [PRED] + +ZBTST: LDD ARG2 + ANDA ARG1 + ANDB ARG1+1 + CMPD ARG2 + BEQ POK + BRA PBAD + + ; --- + ; BOR + ; --- + + ; Return bitwise OR of arg1 and arg2 [VALUE] + +ZBOR: LDD ARG1 + ORA ARG2 + ORB ARG2+1 +ZB0: STD TEMP + JMP PUTVAL + + ; ---- + ; BAND + ; ---- + + ; Return bitwise AND of arg1 and arg2 [VALUE] + +ZBAND: LDD ARG1 + ANDA ARG2 + ANDB ARG2+1 + BRA ZB0 + + ; ----- + ; FSET? + ; ----- + + ; Is flag "arg2" set in object "arg1?" [PRED] + +ZFSETP: JSR FLAGSU ; GET BIT + LDD VAL + ANDA MASK + STA VAL + ANDB MASK+1 + ORB VAL + BNE POK ; BIT IS ON + BRA PBAD + + ; ---- + ; FSET + ; ---- + + ; Set flag "arg2" in object "arg1" + +ZFSET: JSR FLAGSU + LDX TEMP ; ADDRESS OF FLAGS + LDD VAL ; GRAB FLAGS + ORA MASK ; SUPERIMPOSE THE + ORB MASK+1 ; MASKING PATTERN + STD ,X ; AND REPLACE FLAG + RTS + + ; ------ + ; FCLEAR + ; ------ + + ; Clear flag "arg2" in object "arg1" + +ZFCLR: JSR FLAGSU + LDX TEMP ; ADDRESS OF OBJECT + LDD MASK ; GRAB THE MASK + COMA ; COMPLEMENT IT + COMB + ANDA VAL ; SUPERIMPOSE FLAGS + ANDB VAL+1 ; TO MASK OUT TARGET + STD ,X ; REPLACE THE FLAGS + RTS + + ; --- + ; SET + ; --- + + ; Set variable "arg1" equal to value "arg2" + +ZSET: LDD ARG2 + STD TEMP + LDA ARG1+1 + JMP VARPUT + + ; ---- + ; MOVE + ; ---- + + ; Put object "arg1" into object "arg2" + +ZMOVE: JSR ZREMOV ; REMOVE OBJECT FIRST + LDA ARG1+1 + JSR OBJLOC ; GET ADDRESS OF OBJECT + LDX TEMP ; PUT ADDRESS IN X + PSHS X ; SAVE IT HERE TOO + LDA ARG2+1 + STA 4,X + + JSR OBJLOC + LDX TEMP + LDA 6,X + STA VAL ; HOLD HERE FOR A MOMENT + LDA ARG1+1 + STA 6,X + PULS X ; RESTORE OLD [TEMP] + LDA VAL + BEQ ZMVEX + STA 5,X +ZMVEX: RTS + + ; --- + ; GET + ; --- + + ; Return value of item "arg2" in WORD-table at "arg1" [VALUE] + +ZGET: ASL ARG2+1 + ROL ARG2 ; WORD-ALIGN ARG2 + LDD ARG2 + ADDD ARG1 ; ADD OFFSET TO TABLE ADDRESS + STD TEMP + JSR SETWRD + JSR GETWRD + JMP PUTVAL + + ; ---- + ; GETB + ; ---- + + ; Return value of item "arg2" in BYTE-table at "arg1" [VALUE] + +ZGETB: LDD ARG1 + ADDD ARG2 + STD TEMP + JSR SETWRD + JSR GETBYT + STA TEMP+1 + CLR TEMP + JMP PUTVAL + + ; ---- + ; GETP + ; ---- + + ; Return prop "arg2" of object "arg1"; if specified prop + ; doesn't exist, return prop'th element of default object [VALUE] + +ZGETP: JSR PROPB ; GET POINTER TO PROPS +GETP1: JSR PROPN + CMPA ARG2+1 + BEQ GETP2 + BLO GETP3 + + JSR PROPNX + BRA GETP1 ; TRY AGAIN WITH NEXT PROP + +GETP3: LDD ZCODE+ZOBJEC ; Z-ADDR OF OBJECT TABLE + ADDD #ZCODE ; FORM THE ABSOLUTE ADDRESS + TFR D,X ; USE AS AN INDEX + LDB ARG2+1 ; GET PROPERTY # + DECB + ASLB + ABX ; ADD TO TABLE ADDRESS + LDD ,X ; FETCH THE PROPERTY + BRA ETPEX ; AND PASS IT ON + +GETP2: JSR PROPL + INCB ; SOMETHING SHOULD BE IN B! + TSTA ; AND IN A! + BEQ GETP2A + CMPA #1 + BEQ GETP2B + + ; *** ERROR #7: PROPERTY LENGTH *** + + LDA #7 + JSR ZERROR + +GETP2B: LDX TEMP + ABX + LDD ,X + BRA ETPEX + +GETP2A: LDX TEMP + ABX + LDB ,X + CLRA +ETPEX: STD TEMP + JMP PUTVAL + + ; ----- + ; GETPT + ; ----- + + ; Return a POINTER to prop table "arg2" in object "arg1" [VALUE] + +ZGETPT: JSR PROPB +GETPT1: JSR PROPN + CMPA ARG2+1 + BEQ GETPT2 + LBLO RET0 + JSR PROPNX ; TRY NEXT ENTRY + BRA GETPT1 + +GETPT2: INC TEMP+1 + BNE GPT + INC TEMP +GPT: CLRA ; ADD OFFSET IN [B] + ADDD TEMP + SUBD #ZCODE ; CHANGE TO RELATIVE POINTER + STD TEMP + JMP PUTVAL + + ; ----- + ; NEXTP + ; ----- + + ; Return prop index number of the prop following prop "arg2" + ; in object "arg1"; return zero if last property; return + ; 1st prop # if arg2=0; error if no prop "arg2" in "arg1" [VALUE] + +ZNEXTP: JSR PROPB + LDA ARG2+1 + BEQ NXTP2 + +NXTP1: JSR PROPN + CMPA ARG2+1 + BEQ NXTP3 + LBCS RET0 + JSR PROPNX ; TRY NEXT ENTRY + BRA NXTP1 + +NXTP3: JSR PROPNX + +NXTP2: JSR PROPN + JMP PUTBYT + + ; --- + ; ADD + ; --- + + ; Return (arg1+arg2) [VALUE] + +ZADD: LDD ARG1 + ADDD ARG2 +MATH: STD TEMP + JMP PUTVAL + + ; --- + ; SUB + ; --- + + ; Return (arg1-arg2) [VALUE] + +ZSUB: LDD ARG1 + SUBD ARG2 + BRA MATH + + ; --- + ; MUL + ; --- + + ; Return (arg1*arg2) [VALUE] + +ZMUL: LDX #17 ; INIT LOOP INDEX + CLRA ; CLEAR THE + CLRB ; CARRY + STD MTEMP ; AND TEMP REGISTER + +ZMLOOP: ROR MTEMP + ROR MTEMP+1 + ROR ARG2 ; SHIFT A BIT + ROR ARG2+1 ; INTO POSITION + BCC ZMNEXT ; NO ADDITION IF BIT CLEAR + + LDD ARG1 + ADDD MTEMP + STD MTEMP + +ZMNEXT: LEAX -1,X ; ALL BITS EXAMINED? + BNE ZMLOOP ; NO, KEEP SHIFTING + + LDD ARG2 ; ELSE GRAB PRODUCT + BRA MATH ; AND RETURN + + ; --------- + ; DIV & MOD + ; --------- + + ; DIV: Return quotient of int(arg1/arg2) [VALUE] + ; MOD: Return remainder of int(arg1/arg2) [VALUE] + +ZDIV: BSR DVINIT + JMP PUTVAL ; AND SHIP OUT [TEMP] + +ZMOD: BSR DVINIT + LDD VAL ; RETURN THE + BRA MATH ; REMAINDER IN [VAL] + + ; ----------- + ; DIVIDE INIT + ; ----------- + +DVINIT: LDD ARG1 + STD TEMP + LDD ARG2 + STD VAL + + ; FALL THROUGH ... + + ; --------------- + ; SIGNED DIVISION + ; --------------- + + ; ENTRY: DIVIDEND IN [TEMP], DIVISOR IN [VAL] + ; EXIT: QUOTIENT IN [TEMP], REMAINDER IN [VAL] + +DIVIDE: LDA TEMP ; SIGN OF REMAINDER + STA SREM ; IS ALWAYS SIGN OF DIVIDEND + EORA VAL ; SIGN OF QUOTIENT IS POSITIVE + STA SQUOT ; IF SIGNS OF TERMS ARE THE SAME + + TST TEMP ; IF DIVIDEND IS NEGATIVE, + BPL TABS ; CALC ABSOLUTE VALUE + BSR ABTEMP + +TABS: TST VAL ; IF DIVISOR IS NEGATIVE, + BPL DOUDIV ; DO THE SAME + BSR ABSVAL + +DOUDIV: BSR UDIV ; UNSIGNED DIVIDE + + TST SQUOT + BPL RFLIP + BSR ABTEMP + +RFLIP: TST SREM + BPL DIVEX + + ; FALL THROUGH ... + + ; ------------- + ; CALC ABS(VAL) + ; ------------- + +ABSVAL: CLRA + CLRB + SUBD VAL + STD VAL + +DIVEX: RTS + + ; -------------- + ; CALC ABS(TEMP) + ; -------------- + +ABTEMP: CLRA + CLRB + SUBD TEMP + STD TEMP + RTS + + ; ----------------- + ; UNSIGNED DIVISION + ; ----------------- + + ; ENTRY: DIVIDEND IN [TEMP], DIVISOR IN [VAL] + ; EXIT: QUOTIENT IN [TEMP], REMAINDER IN [VAL] + +UDIV: LDD VAL + BEQ DIVERR ; CAN'T DIVIDE BY ZERO! + + LDX #16 ; INIT LOOP INDEX + CLRA ; CLEAR THE + CLRB ; CARRY + STD MTEMP ; AND HI-DIVIDEND REGISTER + +UDLOOP: ROL TEMP+1 + ROL TEMP + ROL MTEMP+1 + ROL MTEMP + + LDD MTEMP ; IS DIVIDEND < DIVISOR? + SUBD VAL + BCS UDNEXT ; YES, CLEAR THE CARRY AND LOOP + STD MTEMP ; ELSE UPDATE DIVIDEND + COMA ; SET THE CARRY + BRA DECX ; AND LOOP + +UDNEXT: CLRA ; CLEAR CARRY + +DECX: LEAX -1,X + BNE UDLOOP + + ROL TEMP+1 ; SHIFT LAST CARRY INTO PLACE + ROL TEMP + LDD MTEMP ; MOVE REMAINDER INTO + STD VAL ; ITS RIGHTFUL PLACE + RTS + + ; *** ERROR #8: DIVISION *** + +DIVERR: LDA #8 + JSR ZERROR + + END + diff --git a/colorcomputer/opsx.src b/colorcomputer/opsx.src new file mode 100644 index 0000000..85056c3 --- /dev/null +++ b/colorcomputer/opsx.src @@ -0,0 +1,286 @@ + PAGE + SBTTL "--- X-OPS ---" + + ; ------ + ; EQUAL? + ; ------ + +ZEQUAL: DEC ARGCNT + BNE DOEQ + + ; *** ERROR #9: NOT ENOUGH "EQUAL?" ARGS *** + + LDA #9 + JSR ZERROR + +DOEQ: LDD ARG1 + CMPD ARG2 + BEQ EQOK + DEC ARGCNT + BEQ EQBAD + + CMPD ARG3 + BEQ EQOK + DEC ARGCNT + BEQ EQBAD + + CMPD ARG4 + BEQ EQOK +EQBAD: JMP PREDF + +EQOK: JMP PREDS + + ; ---- + ; CALL + ; ---- + + ; Branch to function pointed to by [arg1 * 2], passing + ; the optional parameters "arg2" thru "arg4" [VALUE] + +ZCALL: LDD ARG1 ; DID FUNCTION = 0? + BNE DOCALL ; NO, CONTINUE + JMP MATH ; ELSE RETURN A ZERO + +DOCALL: LDD OZSTAK ; ZSP FROM PREVIOUS ZCALL + JSR PSHDZ + LDB ZPCL ; LOW 8 BITS OF ZPC + JSR PSHDZ ; SAVE TO Z-STACK + LDD ZPCH ; PUSH H & M PC + JSR PSHDZ + + ; MULTIPLY ARG1 BY 2; FORM 17-BIT ADDR + + CLRA + ASL ARG1+1 ; BOTTOM 8 BITS + ROL ARG1 ; MIDDLE 8 + ROLA ; TOP BIT + STA ZPCH + LDD ARG1 + STD ZPCM + CLR ZPCFLG ; [ZPC] HAS CHANGED ... + + JSR NEXTPC ; FETCH # NEW LOCALS + STA TEMP2 ; SAVE IT HERE FOR INDEXING + STA TEMP2+1 ; AND HERE FOR REFERENCE + BEQ ZCALL2 ; NO LOCALS IN THIS FUNCTION + + ; SAVE OLD LOCALS, REPLACE WITH NEW + + LDX #LOCALS ; INIT POINTER +ZCALL1: LDD ,X ; GRAB AN OLD LOCAL + PSHS X ; SAVE THE POINTER + JSR PSHDZ ; PUSH OLD LOCAL TO Z-STACK + JSR NEXTPC ; GET MSB OF NEW LOCAL + PSHS A ; SAVE HERE + JSR NEXTPC ; NOW GET LSB + TFR A,B ; POSITION IT PROPERLY + PULS A ; RETRIEVE MSB + PULS X ; THIS IS WHERE IT GOES + STD ,X++ ; STORE NEW LOCAL, UPDATE POINTER + DEC TEMP2 ; ANY MORE OLD LOCALS? + BNE ZCALL1 ; KEEP LOOPING TILL DONE + +ZCALL2: DEC ARGCNT ; EXTRA ARGUMENTS IN THIS CALL? + BEQ ZCALL4 ; NO ARGS TO PASS + + ; MOVE UP TO 3 ARGS TO LOCAL STORAGE + +ZCALL3: LDD ARG2 + STD LOCALS + DEC ARGCNT + BEQ ZCALL4 + LDD ARG3 + STD LOCALS+2 + DEC ARGCNT + BEQ ZCALL4 + LDD ARG4 + STD LOCALS+4 + +ZCALL4: LDB TEMP2+1 ; REMEMBER # LOCALS SAVED + TFR B,A ; COPY INTO [A] + COMA ; COMPLEMENT FOR ERROR CHECK (BM 11/24/84) + JSR PSHDZ ; AND RETURN + STU OZSTAK ; "THE WAY WE WERE ..." + RTS + + ; --- + ; PUT + ; --- + + ; Set item "arg2" in WORD-table "arg1" equal to "arg3" + +ZPUT: ASL ARG2+1 ; WORD-ALIGN + ROL ARG2 ; ARG2 + LDD ARG2 + ADDD ARG1 ; ADD Z-ADDR OF TABLE + ADDD #ZCODE ; FORM ABSOLUTE ADDRESS + TFR D,X ; FOR USE AS AN INDEX + LDD ARG3 + STD ,X + RTS + + ; ---- + ; PUTB + ; ---- + + ; Set item "arg2" in BYTE-table "arg1" equal to "arg3" + +ZPUTB: LDD ARG2 + ADDD ARG1 + ADDD #ZCODE + TFR D,X + LDA ARG3+1 + STA ,X + RTS + + ; ---- + ; PUTP + ; ---- + + ; Set property "arg2" in object "arg1" equal to "arg3" + +ZPUTP: JSR PROPB +PUTP1: JSR PROPN + CMPA ARG2+1 + BEQ PUTP2 + BHS PTP + + ; *** ERROR #10: BAD PROPERTY NUMBER *** + + LDA #10 + JSR ZERROR ; ERROR #7 (BAD PROPERTY #) + +PTP: JSR PROPNX ; NEXT ITEM + BRA PUTP1 + +PUTP2: JSR PROPL + INCB + TSTA + BEQ PUTP2A + CMPA #1 + BEQ PTP1 + + ; *** ERROR #11: PROPERTY LENGTH *** + + LDA #11 + JSR ZERROR ; ERROR #8 (PROP TOO LONG) + +PTP1: LDX TEMP + ABX + LDD ARG3 + STD ,X + RTS + +PUTP2A: LDA ARG3+1 + LDX TEMP + ABX + STA ,X + RTS + + ; ------ + ; PRINTC + ; ------ + + ; Print the character with ASCII value "arg1" + +ZPRC: LDA ARG1+1 + JMP COUT + + ; ------ + ; PRINTN + ; ------ + + ; Print "arg1" as a signed integer + +ZPRN: LDD ARG1 + STD TEMP + + ; PRINT THE SIGNED VALUE IN [TEMP] + +NUMBER: LDD TEMP + BPL DIGCNT ; IF NUMBER IS NEGATIVE, + LDA #$2D ; START WITH A MINUS SIGN + JSR COUT + JSR ABTEMP ; GET ABS(TEMP) + + ; COUNT # OF DECIMAL DIGITS + +DIGCNT: CLR MASK ; RESET INDEX +DGC: LDD TEMP ; CHECK QUOTIENT + BEQ PRNTN3 ; SKIP IF ZERO + LDD #10 + STD VAL ; ELSE DIVIDE BY 10 + JSR UDIV ; UNSIGNED DIVIDE + LDA VAL+1 ; GET LSB OF REMAINDER + PSHS A ; SAVE ON STACK + INC MASK ; INCREMENT CHAR COUNT + BRA DGC ; LOOP TILL ARG1=0 + +PRNTN3: LDA MASK + BEQ PZERO ; PRINT AT LEAST A "0" +PRNTN4: PULS A ; GET A CHAR + ADDA #$30 ; CONVERT TO ASCII NUMBER + JSR COUT + DEC MASK ; OUT OF CHARS? + BNE PRNTN4 ; KEEP PRINTING TILL + RTS ; DONE + + ; PRINT A ZERO + +PZERO: LDA #$30 ; ASCII "0" + JMP COUT + + ; ------ + ; RANDOM + ; ------ + + ; Return a random value between zero and "arg1" [VALUE] + +ZRAND: LDD ARG1 ; USE [ARG1] + STD VAL ; AS THE DIVISOR + + LDD RAND1 ; GET A RANDOM # + ADDD #$AA55 ; DO WEIRD THINGS + STA RAND2 ; SAVE AS + STB RAND1 ; NEW SEED + ANDA #%01111111 ; MAKE POSITIVE + STD TEMP ; MAKE IT THE DIVIDEND + + JSR DIVIDE ; UNSIGNED DIVIDE! + LDD VAL ; GET REMAINDER + ADDD #1 ; AT LEAST 1 + JMP MATH + + ; ---- + ; PUSH + ; ---- + + ; Push "arg1" onto the Z-stack + +ZPUSH: LDD ARG1 + JMP PSHDZ + + ; --- + ; POP + ; --- + + ; Pop a word off Z-stack and store in variable "arg1" + +ZPOP: JSR POPSTK + LDA ARG1+1 ; GET VARIABLE ID + JMP VARPUT + + ; ----- + ; SPLIT + ; ----- + +ZSPLIT EQU ZNOOP + + ; ------ + ; SCREEN + ; ------ + +ZSCRN EQU ZNOOP + + END + diff --git a/colorcomputer/paging.src b/colorcomputer/paging.src new file mode 100644 index 0000000..36d5b47 --- /dev/null +++ b/colorcomputer/paging.src @@ -0,0 +1,212 @@ + PAGE + SBTTL "--- TIMESTAMP PAGING ROUTINES (BM 11/24/84) ---" + + ; -------------------- + ; FETCH A VIRTUAL WORD + ; -------------------- + +GETWRD: BSR GETBYT + STA TEMP + BSR GETBYT + STA TEMP+1 + RTS + + ; ----------------- + ; FETCH NEXT Z-BYTE + ; ----------------- + +NEXTPC: TST ZPCFLG ; IS [ZPCPNT] VALID? + BNE NPC2 ; YES, GET THE BYTE + + ; Z-PAGE HAS CHANGED! + + LDD ZPCH ; GET TOP 9 BITS OF [ZPC] + TSTA ; IS TOP BIT CLEAR? + BNE NPC0 ; NO, PAGE MUST BE SWAPPED + + CMPB ZPURE ; IS THIS PAGE PRELOADED? + BHS NPC0 ; NO, SWAP IT IN + + ADDB #HIGH ZCODE ; ELSE MAKE IT ABSOLUTE + BRA NPC1 ; AND CONTINUE + +NPC0: CLR MPCFLG ; INVALIDATE [MPC] FOR SAFETY + BSR PAGE ; RETURN BUFFER IN [B] + +NPC1: STB ZPCPNT ; SET MSB OF BUFFER ADDRESS + CLR ZPCPNT+1 ; CLEAR LSB + LDA #TRUE + STA ZPCFLG ; VALIDATE [ZPC] + +NPC2: LDB ZPCL ; GET BYTE INDEX + LDX ZPCPNT ; AND PAGE ADDRESS + ABX ; USE [ZPCL] AS OFFSET + LDA ,X ; AND FETCH THE BYTE + + INC ZPCL ; POINT TO NEXT BYTE + BNE NPC3 ; CONTINUE IF NO OVERFLOW + + CLR ZPCFLG ; ELSE INVALIDATE [ZPC] + INC ZPCM ; AND POINT + BNE NPC3 ; TO THE + INC ZPCH ; NEXT Z-PAGE + +NPC3: RTS ; RETURN BYTE IN [A] + + ; --------------------- + ; GET NEXT VIRTUAL BYTE + ; --------------------- + +GETBYT: TST MPCFLG ; IS [MPCPNT] VALID? + BNE GTBT2 ; YES, GET THE BYTE + + ; Z-PAGE HAS CHANGED! + + LDD MPCH ; GET TOP 9 BITS OF [MPC] + TSTA ; IS TOP BIT CLEAR? + BNE GTBT0 ; NO, PAGE MUST BE SWAPPED + +PATCH EQU $+1 ; PATCH POINT FOR "VERIFY" + + CMPB ZPURE ; IS THIS PAGE PRELOADED? + BHS GTBT0 ; NO, SWAP IT IN + + ADDB #HIGH ZCODE ; ELSE MAKE IT ABSOLUTE + BRA GTBT1 ; AND CONTINUE + +GTBT0: CLR ZPCFLG ; INVALIDATE [ZPC] FOR SAFETY + BSR PAGE ; RETURN BUFFER PAGE IN [B] + +GTBT1: STB MPCPNT ; SET MSB OF BUFFER ADDRESS + CLR MPCPNT+1 ; CLEAR LSB + LDA #TRUE + STA MPCFLG ; VALIDATE [MPC] + +GTBT2: LDB MPCL ; GET BYTE INDEX + LDX MPCPNT ; AND PAGE ADDRESS + ABX ; USE [MPCL] AS OFFSET + LDA ,X ; AND FETCH THE BYTE + + INC MPCL ; POINT TO NEXT BYTE + BNE GTBT3 ; CONTINUE IF NO OVERFLOW + + CLR MPCFLG ; ELSE INVALIDATE [MPC] + INC MPCM ; AND POINT + BNE GTBT3 ; TO THE + INC MPCH ; NEXT Z-PAGE + +GTBT3: RTS ; RETURN BYTE IN [A] + + ; ------------------------- + ; LOCATE A SWAPPABLE Z-PAGE + ; ------------------------- + + ; ENTRY: TARGET PAGE IN [D] (TOP 9 BITS) + ; EXIT: ABSOLUTE BUFFER PAGE IN [B] + +PAGE: STD DBLOCK ; SAVE TARGET PAGE HERE + CLR ZPAGE ; CLEAR INDEX + LDX #PTABLE ; START AT BOTOM OF TABLE +PG0: CMPD ,X++ ; FOUND IT? + BEQ PG1 ; YES! + INC ZPAGE ; ELSE COUNT NEXT PAGE + CMPX TABTOP ; ANY BUFFERS LEFT? + BLO PG0 ; NO, KEEP SEARCHING + + ; SWAP IN THE TARGET PAGE + + BSR EARLY ; FIND THE EARLIEST PAGE + LDB SWAP ; MOVE ITS INDEX + STB ZPAGE ; INTO [ZPAGE] + + ADDB PAGE0 ; CALC ABSOLUTE PAGE OF BUFFER + STB DBUFF ; TELL DISK WHERE TO PUT DATA + CLR DBUFF+1 ; CLEAR LSB + + LDX #PTABLE ; GET THE PAGING TABLE ADDRESS + LDB ZPAGE ; AND THE BUFFER OFFSET + ABX ; ADD THE OFFSET + ABX ; TWICE FOR WORD ALIGNMENT + LDD DBLOCK ; RETRIEVE PAGE ID + STD ,X ; SPLICE IT INTO THE TABLE + + JSR GETDSK ; MOVE BLOCK [DBLOCK] TO [DBUFF] + + ; UPDATE THE TIMESTAMP + +PG1: LDB ZPAGE ; GET BUFFER INDEX + LDX #LRUMAP ; CALC ADDRESS OF ENTRY + ABX ; IN TIMESTAMP MAP + LDA ,X ; GET BUFFER'S LAST STAMP + CMPA STAMP ; SAME AS CURRENT STAMP? + BEQ PG5 ; EXIT IF SO + + INC STAMP ; UPDATE [STAMP] + BNE PG4 ; IF STAMP OVERFLOWS ... + + ; HANDLE STAMP OVERFLOW + + BSR EARLY ; GET EARLIEST STAMP INTO [LRU] + + LDX #LRUMAP ; GET BASE ADDRESS OF STAMPS + CLRB ; INIT STAMP COUNTER +PG2: LDA ,X ; GET A STAMP + BEQ PG3 ; SKIP IF ALREADY ZERO + SUBA LRU ; ELSE SUBTRACT OFF EARLIEST STAMP + STA ,X ; AND REPLACE IT +PG3: LEAX +1,X ; INCREMENT BASE ADDRESS + INCB ; AND COUNTER + CMPB PMAX ; OUT OF PAGES YET? + BLO PG2 ; LOOP TILL DONE + + LDA #0 ; TURN BACK THE CLOCK + SUBA LRU ; ON [STAMP] + STA STAMP ; TO REFLECT TABLE FUDGING + + ; STAMP THE PAGE WITH CURRENT TIME + +PG4: LDX #LRUMAP + LDB ZPAGE + ABX + LDA STAMP + STA ,X + +PG5: LDB ZPAGE ; GET PAGE OFFSET + ADDB PAGE0 ; MAKE IT ABSOLUTE + RTS ; AND RETURN IT IN [B] + + ; ------------------------- + ; LOCATE EARLIEST TIMESTAMP + ; ------------------------- + + ; EXIT: [LRU] = EARLIEST STAMP READING + ; [SWAP] = INDEX TO EARLIEST BUFFER + +EARLY: CLR SWAP ; RESET [SWAP] + LDA LRUMAP ; FETCH 1ST READING FOR COMPARISONS + LDX #LRUMAP+1 ; POINT TO 2ND READING + LDB #1 ; INIT BUFFER INDEX +EAR0: CMPA ,X ; IS THIS STAMP EARLIER THAN [A]? + BLO EAR1 ; NO, TRY NEXT + LDA ,X ; ELSE MAKE THIS READING THE "NEW" LOWEST + STB SWAP ; AND REMEMBER WHERE WE FOUND IT +EAR1: LEAX +1,X ; UPDATE POINTER + INCB ; AND BUFFER INDEX + CMPB PMAX ; OUT OF BUFFERS YET? + BLO EAR0 ; LOOP TILL DONE + + STA LRU ; SAVE EARLIEST STAMP FOUND + RTS ; AND RETURN + + ; --------------------- + ; POINT [MPC] TO [TEMP] + ; --------------------- + +SETWRD: LDD TEMP + STD MPCM + CLR MPCH + CLR MPCFLG + RTS + + END + diff --git a/colorcomputer/read.me b/colorcomputer/read.me new file mode 100644 index 0000000..423b346 --- /dev/null +++ b/colorcomputer/read.me @@ -0,0 +1,13 @@ +******* Directory Update and Source File Archive Record ****** + + Date of Last Change Version Letter Who Made the Change + ___________________ _____________ ____________________ + +1) FIRST ARCHIVED 8/23/84 A PROF +2) VERSION C 6/12/85/ C A.S.K +3) +4) +5) +6) +7) +8) diff --git a/colorcomputer/read.src b/colorcomputer/read.src new file mode 100644 index 0000000..0bbf264 --- /dev/null +++ b/colorcomputer/read.src @@ -0,0 +1,212 @@ + PAGE + SBTTL "--- READ HANDLER ---" + +ZREAD: JSR ZUSL ; UPDATE STATUS LINE FIRST + + LDD ARG1 ; CALC ABSOLUTE ADDRESS + ADDD #ZCODE ; OF READ BUFFERS + STD ARG1 + LDD ARG2 + ADDD #ZCODE + STD ARG2 + + JSR INPUT ; READ LINE; RETURN LENGTH IN A + STA MASK ; # CHARS IN LINE + CLR MASK+1 ; # CHARS IN CURRENT WORD + + LDX ARG2 ; SET # OF WORDS READ + CLR 1,X ; TO ZERO + + LDA #1 ; = 1 + STA STABP ; INIT SOURCE TABLE POINTER + INCA ; = 2 + STA RTABP ; AND RESULT TABLE POINTER + +READL: LDX ARG2 + LDA ,X+ ; FETCH MAXIMUM # OF WORDS + CMPA ,X ; COMPARE TO # WORDS READ + BHS RL1 ; STILL ROOM + + ; *** ERROR #13 -- PARSER OVERFLOW *** + + LDA #13 + JSR ZERROR + +RL1: LDD MASK ; OUT OF CHARS & WORDS? + BNE RL2 ; NOT YET +RDEX: RTS ; ELSE SCRAM + +RL2: LDA MASK+1 ; GET CHAR COUNT + CMPA #6 ; 6 CHARS DONE? + BLO RL3 ; NOT YET + JSR FLUSHW ; ELSE FLUSH WORD + +RL3: LDA MASK+1 ; FIRST CHAR IN WORD? + BNE READL2 ; NOPE + + ; CLEAR OUT WORD BUFFER [ZSTBUI] + + CLRB ; [A] IS ALREADY ZERO + STD ZSTBUI + STD ZSTBUI+2 + STD ZSTBUI+4 + + LDB RTABP + LDX ARG2 + ABX + LDB STABP + STB 3,X ; STORE POSITION + + LDX ARG1 + LDA B,X ; GRAB A CHAR FROM SOURCE BUFFER + JSR SIBRKP ; IS IT A SIB? + BCS RSIBRK ; YES IF CARRY IS SET + JSR NBRKP ; IS IT A "NORMAL" BREAK CHAR? + BCC READL2 ; NO, KEEP SCANNING + INC STABP ; ELSE FLUSH STRANDED BREAK + DEC MASK ; UPDATE # OF CHARS IN LINE + BRA READL ; AND LOOP BACK + +READL2: LDA MASK ; OUT OF CHARS? + BEQ READL3 ; SURE ENOUGH + LDB STABP + LDX ARG1 + LDA B,X ; ELSE GRAB NEXT CHAR + JSR RBRKP ; IS IT A BREAK? + BCS READL3 ; YES IF CARRY SET + LDB MASK+1 ; ELSE POINT TO + LDX #ZSTBUI ; WORD BUFFER + STA B,X ; STORE CHAR IN BUFFER + DEC MASK ; ONE LESS CHAR IN LINE + INC MASK+1 ; ONE MORE IN RESULT + INC STABP ; POINT TO NEXT CHAR + BRA READL ; AND LOOP BACK + +RSIBRK: STA ZSTBUI ; STORE THE SIB + DEC MASK ; UPDATE LINE-CHAR COUNT + INC MASK+1 ; WORD-CHAR COUNT + INC STABP ; AND # CHARS IN WORD + +READL3: LDA MASK+1 ; ANY CHARS IN WORD? + BEQ READL ; APPARENTLY NOT + + LDB RTABP ; POINT TO + LDX ARG2 ; IN THIS ENTRY + ABX + LDA MASK+1 ; FETCH ACTUAL WORD LENGTH + STA 2,X ; AND STORE IN 3RD BYTE + + LDA MASK + PSHS A ; SAVE THIS + JSR CONZST ; CONVERT TO Z-STRING + JSR FINDW ; LOOK UP IN VOCABULARY + PULS A + STA MASK ; RESTORE + + LDX ARG2 + INC 1,X ; UPDATE # WORDS READ + LDB RTABP ; POINT [X] TO 1ST BYTE + ABX ; IN CURRENT ENTRY + ADDB #4 + STB RTABP ; POINT TO NEXT ENTRY + LDD VAL ; STORE [VAL] IN ENTRY + STD ,X + CLR MASK+1 ; RESET WORD-CHAR COUNT + JMP READL ; AND CONTINUE + + ; ---------- + ; FLUSH WORD + ; ---------- + +FLUSHW: LDA MASK + BEQ FLEX + LDB STABP + LDX ARG1 + LDA B,X + BSR RBRKP ; WORD BREAK? + BCS FLEX ; EXIT IF SO + DEC MASK + INC MASK+1 + INC STABP + BRA FLUSHW ; KEEP LOOPING +FLEX: RTS + + ; --------------- + ; BREAK CHAR SCAN + ; --------------- + +RBRKP: BSR SIBRKP ; FIRST CHECK FOR SIBS + BCS FBRK ; EXIT IF MATCHED + + ; FALL THROUGH TO ... + + ; ---------------------- + ; NORMAL BREAK CHAR SCAN + ; ---------------------- + +NBRKP: LDX #BRKTBL ; BASE OF BREAK CHAR TABLE + LDB #NBRKS-1 ; NUMBER OF NORMAL BREAK CHARS + BRA NBR1 + + ; ------------------------------ + ; SELF-INSERTING BREAK CHAR SCAN + ; ------------------------------ + +SIBRKP: LDX VOCAB ; BASE ADDRESS OF VOCAB TABLE + LDB ,X+ ; GET # SIB CHARS + DECB ; ZERO-ALIGN COUNT + +NBR1: CMPA B,X + BEQ FBRK ; MATCHED! + DECB + BPL NBR1 ; KEEP LOOPING + CLRB ; NO MATCH, CLEAR CARRY + RTS +FBRK: COMB ; SET CARRY TO FLAG MATCH + RTS + + ; ----------------- + ; VOCABULARY SEARCH + ; ----------------- + +FINDW: LDX VOCAB ; BASE ADDR OF VOCAB TABLE + LDB ,X+ ; GET # SIB BYTES + ABX ; AND SKIP OVER THEM + + LDA ,X+ ; # BYTES PER TABLE ENTRY + STA MASK+1 ; SAVE IT HERE + + LDD ,X++ ; # OF ENTRIES IN TABLE + STD VAL ; SAVE THAT TOO + +FWL1: LDD ,X ; CHECK FIRST Z-WORD + CMPD ZSTBUO + BNE WNEXT ; NO GOOD + LDD 2,X ; ELSE CHECK 2ND HALF + CMPD ZSTBUO+2 + BEQ FWSUCC ; MATCHED! + +WNEXT: LDB MASK+1 ; MOVE [X] UP TO + ABX ; NEXT TABLE ENTRY + LDD VAL + SUBD #1 + STD VAL ; OUT OF ENTRIES YET? + BNE FWL1 ; NO, KEEP LOOKING + RTS ; ELSE RETURN WITH [VAL]=0 + +FWSUCC: LEAX -ZCODE,X ; CONVERT TO Z-ADDRESS + STX VAL ; LEAVE RESULT IN [VAL] + RTS + + ; ------------------ + ; NORMAL BREAK CHARS + ; ------------------ + +BRKTBL: DB "!?,." + DB EOL + DB SPACE + +NBRKS EQU 6 ; # NORMAL BREAK CHARS + + END + diff --git a/colorcomputer/screen.src b/colorcomputer/screen.src new file mode 100644 index 0000000..461737a --- /dev/null +++ b/colorcomputer/screen.src @@ -0,0 +1,322 @@ + PAGE + SBTTL "--- SCREEN & PRINTER I/O ---" + + ; ------------ + ; RESTART GAME + ; ------------ + +ZSTART: JSR ZCRLF ; FLUSH OUTPUT BUFFER + CLR SCRIPT ; DISABLE SCRIPTING [ASK 5/28/85] +; JSR ENTER ; "PRESS ANY KEY TO CONTINUE"[ASK 5/28/85] + LDA ZCODE+ZSCRIP+1 + STA SFLAG + JMP LUKE ; SKIP SCRIPT DISABLE + ; FALL THROUGH TO ... + + ; --------- + ; COLDSTART + ; --------- + +COLD: CLR SCRIPT ; DISABLE SCRIPTING +LUKE: JSR CLS ; A CLEAN SLATE + LDD #SCREEN+228 ; POSITION + STD CURSOR ; CURSOR + LDX #LOADM + LDB #LOADML + JSR DLINE ; "LOADING GAME ..." + JMP START ; AND DO A WARMSTART + +LOADM: DB "THE STORY IS LOADING ..." +LOADML EQU $-LOADM + + ; ----- + ; ERROR + ; ----- + + ; ENTRY: ERROR CODE # IN [A] + +INTERR: DB EOL + DB "INTERNAL ERROR #" +IERRL EQU $-INTERR + +ZERROR: PSHS A ; SAVE CODE # + JSR ZCRLF ; FLUSH BUFFER + LDX #INTERR + LDB #IERRL + JSR LINE ; "INTERNAL ERROR #" + PULS A ; RETRIEVE CODE # + STA TEMP+1 + CLR TEMP + JSR NUMBER ; CONVERT ERROR CODE # + JSR CR1 ; AND SHOW IT + + ; FALL THROUGH TO ... + + ; ---- + ; QUIT + ; ---- + +ZQUIT: LDX #ENDSES + LDB #ENDSL + JSR LINE ; "END OF SESSION" + CLR MOTOR ; SHUT DOWN DRIVE MOTOR + +; JSR ROMIN ; MAKE SURE ROM'S ACTIVE [ASK 5/15/85] + +FREEZE: BRA FREEZE ; STOP DEAD + +ENDSES: DB "END OF SESSION" +VCODE: DB EOL ; SHARED EOL CHAR +ENDSL EQU $-ENDSES + + ; -------------------------- + ; DISPLAY ZIP VERSION NUMBER + ; -------------------------- + + DB "COCO 2 VERSION C" + DB EOL +VCODEL EQU $-VCODE + +VERNUM: LDX #VCODE + LDB #VCODEL + JMP LINE + + ; ----------------- + ; PRINT A CHARACTER + ; ----------------- + +COUT: LDX #BUFFER ; POINT TO I/O BUFFER + LDB CHRPNT ; GET LINE INDEX + CMPA #EOL ; IF THIS IS A CR, + BEQ ZCRLF ; HANDLE AS SUCH + CMPA #SPACE ; IGNORE OTHER CONTROLS + BLO COUT1 + + STA B,X ; SEND CHAR TO BUFFER + CMPB #31 ; END OF SCREEN LINE? + BHS FLUSH ; YES, SO FLUSH CURRENT BUFFER + INC CHRPNT ; ELSE UPDATE INDEX +COUT1: RTS ; AND LEAVE + + ; FLUSH CONTENTS OF [BUFFER] + +FLUSH: LDA #SPACE +FLUSH1: CMPA B,X ; FIND LAST SPACE CHAR + BEQ FLUSH2 ; IN CURRENT LINE + DECB + BNE FLUSH1 ; KEEP SCANNING + LDB #31 ; SEND ENTIRE LINE IF NONE FOUND + +FLUSH2: STB CPSAV ; SAVE + STB CHRPNT ; # CHARS IN LINE + JSR ZCRLF ; OUTPUT 1ST PART OF LINE + + ; START NEW LINE WITH REMAINDER OF OLD + +FLUSH3: INC CPSAV ; GET 1ST CHAR + LDB CPSAV ; OF REMAINDER + CMPB #31 ; END OF LINE YET? + BLS FLUSH4 ; NO, MOVE IT FORWARD + RTS ; ELSE WE'RE DONE HERE + +FLUSH4: LDX #BUFFER ; POINT TO BUFFER + LDA B,X ; GET OLD CHAR + LDB CHRPNT ; THIS WAS RESET BY CRLF + STA B,X ; MOVE TO START OF BUFFER + INC CHRPNT ; NEXT POSITION + BRA FLUSH3 ; KEEP MOVING + +MORES: DB "[more]" +MOREL EQU $-MORES + + ; --------------- + ; CARRIAGE RETURN + ; --------------- + +ZCRLF: INC LINCNT ; NEW LINE GOING OUT + LDA LINCNT + CMPA #13 ; 13 LINES SENT YET? + BLO CR1 ; NO, KEEP GOING + + BSR ZUSL ; UPDATE STATUS LINE + + LDD CURSOR ; GET CURSOR POSITION + STD TEMP2 ; AND SAVE IT + + LDX #MORES ; "[MORE]" + LDB #MOREL + JSR DLINE + + CLR CFLAG ; NO CURSOR! + JSR GETKEY ; GET A KEYPRESS + + LDD TEMP2 + STD CURSOR ; RESTORE CURSOR + + LDA #SPACE ; ERASE "MORE" MESSAGE + LDB #MOREL ; WITH SPACES +SPCS: JSR OUTCHR + DECB + BNE SPCS + + LDD TEMP2 + STD CURSOR ; RESTORE CURSOR AGAIN + CLR LINCNT ; RESET LINE COUNTER + +CR1: LDB CHRPNT + LDX #BUFFER + LDA #EOL ; INSTALL AN EOL + STA B,X ; AT END OF CURRENT LINE + INC CHRPNT ; ADD IT TO CHAR COUNT + +LINOUT: TST CHRPNT ; IF NO CHARS IN BUFFER + BEQ SCDONE ; DON'T PRINT ANYTHING +OUTPUT: JSR BUFOUT ; ELSE DISPLAY BUFFER + CLR CHRPNT ; RESET CHAR INDEX +SCDONE: RTS ; AND RETURN + + ; ------------------ + ; UPDATE STATUS LINE + ; ------------------ + +ZUSL: LDA CHRPNT ; SAVE ALL Z-STRING VARS + LDB STBYTF + LDX CURSOR + LDY ZSTWRD + PSHS X,Y,D + LDA MPCH ; HIGH BIT OF MPC + LDB BINDEX + LDX MPCM ; LOW BYTES OF MPC + LDY CSTEMP ; TEMP & PERM TOGETHER! + PSHS X,Y,D + + LDY #BUFSAV ; MOVE OUTPUT BUFFER + LDX #BUFFER ; TO TEMPORARY STORAGE + LDB #SPACE ; CLEAR [BUFFER] WITH SPACES +ZUSL1: LDA ,X + STB ,X+ + STA ,Y+ + CMPX #BUFFER+32 + BLO ZUSL1 + + LDX #SCREEN + LDA #$20 ; CLEAR OLD STATUS LINE +ZSL: STA ,X+ + CMPX #SCREEN+32 + BLO ZSL + + ; DISPLAY ROOM NAME + + CLR CHRPNT ; RESET CHAR INDEX + CLR SCRIPT ; DISABLE SCRIPTING + LDD #SCREEN ; HOME THE + STD CURSOR ; CURSOR + + LDA #$10 ; GLOBAL VAR #0 (ROOM #) + JSR VARGET + LDA TEMP+1 + JSR PRNTDC ; GET SHORT DESC INTO [BUFFER] + + LDA #22 ; ADVANCE BUFFER INDEX + STA CHRPNT ; INTO SCORING POSITION + LDA #SPACE ; PRINT A SPACE + JSR COUT ; TO SEPARATE THINGS (BM 12/6/84) + + LDA #$11 ; FETCH GLOBAL VARIABLE + JSR VARGET ; #1 (SCORE/HOURS) + TST TIMEFL ; TIME MODE? + BNE PTIME ; YES IF NZ + + ; PRINT SCORE + + JSR NUMBER ; PRINT THE VALUE + LDA #$2F ; ASCII SLASH + BRA MOVEP + + ; PRINT TIME (HOURS) + +PTIME: LDA TEMP+1 + BNE PTIME1 ; 00 IS REALLY 24 + LDA #24 +PTIME1: CMPA #12 + BLE PTIME2 ; IF HOURS IS GREATER THAN 12, + SUBA #12 ; CONVERT TO 12-HOUR TIME + STA TEMP+1 +PTIME2: JSR NUMBER ; SHOW HOURS VALUE + LDA #$3A ; ASCII COLON + +MOVEP: JSR COUT ; SEND COLON (OR SLASH) + LDA #$12 ; GLOBAL VAR #2 (MOVES/MINUTES) + JSR VARGET + TST TIMEFL ; TIME MODE? + BEQ PNUM ; NO, DO MOVES + + ; PRINT MINUTES + + LDA TEMP+1 + CMPA #10 ; IF LESS THAN 10 MINUTES, + BHS MOVEP1 + LDA #$30 ; ADD ASCII ZERO FOR PADDING + JSR COUT + +MOVEP1: JSR NUMBER ; SHOW MINUTES + + ; PRINT "AM/PM" + + LDA #SPACE ; SEPARATE TIMING + JSR COUT ; FROM "AM/PM" + LDA #$11 ; GLOBAL #1 AGAIN + JSR VARGET + LDA TEMP+1 + CMPA #12 ; PAST NOON? + BHS USEPM ; YES, IT'S PM + LDA #$41 ; "A" + BRA DOM +USEPM: LDA #$50 ; "P" +DOM: JSR COUT + LDA #$4D ; "M" + JSR COUT + BRA AHEAD ; DONE! + + ; PRINT # MOVES + +PNUM: JSR NUMBER ; SIMPLE, EH? + +AHEAD: JSR CR1 ; DUMP BUFFER + BSR INVERT ; INVERT STATUS LINE + + LDY #BUFSAV ; POINT TO "SAVE" BUFFER + LDX #BUFFER ; POINT TO OUTPUT BUFFER +USLEND: LDA ,Y+ + STA ,X+ ; RESTORE PREVIOUS CONTENTS + CMPX #BUFFER+32 + BLO USLEND + + PULS X,Y,D ; RESTORE EVERYTHING + STY CSTEMP + STX MPCM + STB BINDEX + STA MPCH + PULS X,Y,D + STY ZSTWRD + STX CURSOR + STB STBYTF + STA CHRPNT + COM SCRIPT ; RE-ENABLE SCRIPTING + CLR MPCFLG ; MPC NO LONGER VALID + RTS + + ; ------------------ + ; INVERT STATUS LINE + ; ------------------ + +INVERT: LDX #SCREEN +REVERS: LDA ,X + ANDA #%10111111 ; CLEAR BIT 6 (REVERSE VIDEO) + STA ,X+ + CMPX #SCREEN+32 + BLO REVERS + RTS + + END + diff --git a/colorcomputer/warm.src b/colorcomputer/warm.src new file mode 100644 index 0000000..8cff27b --- /dev/null +++ b/colorcomputer/warm.src @@ -0,0 +1,145 @@ + PAGE + SBTTL "--- WARMSTART ROUTINE ---" + + SETDP 0 + ORG ZIP ; START OF EXECUTABLE CODE + + CLRA ; USE PAGE ZERO + TFR A,DP ; AS THE DIRECT PAGE + +IRQVEC EQU $10C + + LDX #DIRQSV ;SET VECTOR + STX IRQVEC+1 + LDA #$7E ;JMP OP + STA IRQVEC + +; ORCC #%01010000 ; DISABLE INTERRUPTS +; LDA INT60 ; DISABLE +; ANDA #%11111110 ; THE 60HZ + STA INT60 ; INTERRUPT + STA ROMOFF ; AND THE ROMS + LDS #MSTACK ; GIVE THE STACK A NEW HOME + JMP COLD ; PERFORM ONE-TIME INITIALIZATION + + ; WARMSTART ENTRY + +START: LDS #MSTACK ; RESET MACHINE STACK + + + ; TEST TO SEE IF ZIP IS ALL LOADED + + LDX #3 +TSTEND: LDA ENDTST-1,X + CMPA ENDCMP-1,X + BNE ENDERR + LEAX -1,X + BNE TSTEND + BRA ENDOK +ENDERR: LDA #16 + JMP ZERROR; + +ENDCMP: DB "END" + + ; CLEAR ALL DIRECT-PAGE VARIABLES + +ENDOK: LDX #DSTART +ST0: CLR ,X+ + CMPX #ZPGTOP + BLO ST0 + + INC STAMP ; INIT TIMESTAMP TO 1 (BM 11/24/84) + + ; RESET THE PAGING TABLE + + LDX #PTABLE + LDA #$FF +ST1A: STA ,X+ + CMPX #PTABLE+$140 + BLO ST1A + + ; CLEAR THE TIMESTAMP MAP (BM 11/24/84) + + LDX #LRUMAP +ST1B: CLR ,X+ + CMPX #LRUMAP+$A0 + BLO ST1B + + ; GET THE FIRST SECTOR OF Z-CODE + + LDD #ZCODE ; POINT TO 1ST + STD DBUFF ; Z-CODE LOCATION + JSR GETDSK ; FETCH BLOCK #0 FROM DRIVE 0 + + ; EXTRACT GAME DATA FROM Z-CODE HEADER + + LDA ZCODE+ZENDLD ; GET MSB OF ENDLOAD POINTER + INCA ; ADD ONE TO GET + STA ZPURE ; 1ST PAGE IN "PURE" CODE + ADDA #HIGH ZCODE ; ADD BASE ADDRESS TO GET + STA PAGE0 ; 1ST PAGE OF SWAPPING SPACE + + LDB #MEMTOP ; TOP PAGE OF MEMORY + SUBB PAGE0 ; SUBTRACT ADDRESS OF PAGING BUFFER + BLS NORAM + CMPB #8 + BHS SETNP ; MUST HAVE AT LEAST 8 SWAPPING PAGES + + ; *** ERROR #0 -- INSUFFICIENT RAM *** + +NORAM: CLRA + JSR ZERROR + + ; [B] HAS # FREE SWAPPING PAGES + +SETNP: CMPB #$A0 ; MAKE SURE # PAGES + BLO SETA0 ; DOESN'T EXCEED + LDB #$A0 ; $A0 (BM 11/24/84) +SETA0: STB PMAX ; SET MAXIMUM # FREE PAGES + LDX #PTABLE ; ADD BASE ADDR OF P-TABLE + ABX ; TO PAGING LIMIT + ABX ; TWICE (FOR WORD-ALIGNMENT) + STX TABTOP ; TO GET ADDR OF HIGHEST TABLE ENTRY + + LDA ZCODE+ZMODE ; GET MODE BYTE + ORA #%00001000 ; SET THE "TANDY" ID BIT + STA ZCODE+ZMODE ; (WE DON'T WANT ANY DIRTY WORDS) + ANDA #%00000010 ; ISOLATE STAT-LINE FORMAT BIT + STA TIMEFL ; 0=SCORE/MOVES, NZ=HOURS/MINUTES + + LDD ZCODE+ZBEGIN ; GET START ADDRESS OF Z-CODE + STD ZPCM ; HIGH BITS AT ZPCH ALREADY CLEARED + + LDD ZCODE+ZGLOBA ; GET RELATIVE ADDR OF GLOBAL TABLE + ADDD #ZCODE ; CONVERT TO ABSOLUTE ADDRESS + STD GLOBAL + + LDD ZCODE+ZFWORD ; DO SAME FOR FWORDS TABLE + ADDD #ZCODE + STD FWORDS + + LDD ZCODE+ZVOCAB ; AND VOCABULARY TABLE + ADDD #ZCODE + STD VOCAB + + ; GRAB THE REST OF THE PRELOAD + + LDA ZPURE ; GET # PAGES IN PRELOAD + 1 + STA TEMP ; USE AS AN INDEX +LDPRE: JSR GETDSK ; GRAB THE BLOCK + DEC TEMP + BNE LDPRE ; KEEP READING TILL DONE + + LDU #TOPSTA ; INIT THE ZSP + STU OZSTAK ; REMEMBER ITS POSITION + + JSR CLS ; CLEAR THE SCREEN + COM SCRIPT ; ENABLE SCRIPTING + + LDA SFLAG ; SCRIPTING FLAG + STA ZCODE+ZSCRIP+1 + + ; FALL INTO MAIN LOOP + + END + diff --git a/colorcomputer/zequates.src b/colorcomputer/zequates.src new file mode 100644 index 0000000..c9c7db4 --- /dev/null +++ b/colorcomputer/zequates.src @@ -0,0 +1,122 @@ + PAGE + SBTTL "--- MEMORY ORGANIZATION ---" + +TRUE EQU $FF +FALSE EQU 0 + +DSTART EQU 0 ; START OF DIRECT-PAGE RAM + +MSTACK EQU MSTART+$FE ; TOP OF MACHINE STACK (254 BYTES) +IOBUFF EQU MSTART+$100 ; 256-BYTE DISK I/O BUFFER +ZSTACK EQU MSTART+$200 ; Z-STACK (255 WORDS) +ZSTAKL EQU 255 ; LENGTH OF Z-STACK IN WORDS +TOPSTA EQU (2*ZSTAKL)+ZSTACK ; TOP OF Z-STACK +PTABLE EQU MSTART+$400 ; PAGING TABLE ($140 BYTES/$A0 WORDS) +LRUMAP EQU MSTART+$550 ; TIMESTAMP MAP ($A0 BYTES) +LOCALS EQU MSTART+$600 ; LOCAL VARIABLE STORAGE (32 BYTES) +BUFFER EQU MSTART+$620 ; I/O LINE BUFFER (32 BYTES) +BUFSAV EQU MSTART+$640 ; I/O AUX BUFFER (32 BYTES) +ZIP EQU MSTART+$700 ; START OF EXECUTABLE CODE +ZCODE EQU ZIP+$1700 ; START OF Z-CODE (ASSUME 5.75K ZIP) + + ; 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 +ZBEGIN 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 D-PAGE VARIABLES ---" + +OPCODE EQU DSTART ; CURRENT OPCODE +ARGCNT EQU OPCODE+1 ; # ARGUMENTS +ARG1 EQU OPCODE+2 ; ARGUMENT #1 (WORD) +ARG2 EQU OPCODE+4 ; ARGUMENT #2 (WORD) +ARG3 EQU OPCODE+6 ; ARGUMENT #3 (WORD) +ARG4 EQU OPCODE+8 ; ARGUMENT #4 (WORD) + +LRU EQU OPCODE+10 ; (BYTE) LEAST RECENTLY USED PAGE INDEX +ZPURE EQU LRU+1 ; (BYTE) 1ST VIRTUAL PAGE OF PURE Z-CODE +PMAX EQU LRU+2 ; (BYTE) MAXIMUM # SWAPPING PAGES +ZPAGE EQU LRU+3 ; (BYTE) CURRENT SWAPPING PAGE +PAGE0 EQU LRU+4 ; (BYTE) 1ST ABS PAGE OF SWAPPING SPACE +TABTOP EQU LRU+5 ; (WORD) ADDRESS OF LAST P-TABLE ENTRY +STAMP EQU LRU+7 ; (BYTE) CURRENT TIMESTAMP (BM 11/24/84) +SWAP EQU LRU+8 ; (BYTE) EARLIEST BUFFER (BM 11/24/84) + +ZPCH EQU LRU+9 ; HIGHEST-ORDER BIT OF PC +ZPCM EQU ZPCH+1 ; MIDDLE 8 BITS OF PC +ZPCL EQU ZPCH+2 ; LOWER 8 BITS OF PC +ZPCPNT EQU ZPCH+3 ; POINTER TO ACTUAL PC PAGE (WORD) +ZPCFLG EQU ZPCH+5 ; FLAG: "TRUE" IF ZPCPNT VALID + +MPCH EQU ZPCH+7 ; HIGHEST-ORDER BIT OF MEM POINTER +MPCM EQU MPCH+1 ; MIDDLE 8 BITS OF MEM POINTER +MPCL EQU MPCH+2 ; LOW-ORDER 8 BITS OF MEMORY POINTER +MPCPNT EQU MPCH+3 ; ACTUAL POINTER TO MEMORY (WORD) +MPCFLG EQU MPCH+5 ; FLAG: "TRUE" IF MPCPNT VALID + +GLOBAL EQU MPCH+7 ; GLOBAL VARIABLE POINTER (WORD) +VOCAB EQU GLOBAL+2 ; VOCAB TABLE POINTER (WORD) +FWORDS EQU GLOBAL+4 ; FWORDS TABLE POINTER (WORD) + +OZSTAK EQU GLOBAL+6 ; ZSP SAVE REGISTER (FOR ZCALL) + +CSTEMP EQU OZSTAK+2 ; SET IF TEMP CHARSET IN EFFECT +CSPERM EQU CSTEMP+1 ; CURRENT PERM CHARSET +STBYTF EQU CSTEMP+2 ; 0=1ST, 1=2ND, 2=3RD, 0=LAST + +ZSTWRD EQU CSTEMP+3 ; WORD STORAGE (WORD) +ZSTBUI EQU ZSTWRD+2 ; Z-STRING INPUT BUFFER (6 BYTES) +ZSTBUO EQU ZSTWRD+8 ; Z-STRING OUTPUT BUFFER (6 BYTES) +RTABP EQU ZSTWRD+14 ; RESULT TABLE POINTER +STABP EQU ZSTWRD+15 ; SOURCE TABLE POINTER +PZSTFO EQU ZSTWRD+16 ; FWORD TABLE BLOCK OFFSET + +VAL EQU ZSTWRD+17 ; VALUE RETURN REGISTER (WORD) +TEMP EQU VAL+2 ; TEMPORARY REGISTER (WORD) +TEMP2 EQU VAL+4 ; ANOTHER TEMPORARY REGISTER (WORD) +MASK EQU VAL+6 ; BIT-MASK REGISTER (WORD) +SQUOT EQU VAL+8 ; SIGN OF QUOTIENT +SREM EQU VAL+9 ; SIGN OF REMAINDER +MTEMP EQU VAL+10 ; MATH TEMP REGISTER (WORD) + +DRIVE EQU VAL+12 ; DRIVE NUMBER +DBUFF EQU DRIVE+1 ; DISK I/O BUFFER POINTER (WORD) +DBLOCK EQU DRIVE+3 ; Z-BLOCK # (WORD) +TRACK EQU DRIVE+5 ; TRACK/SECTOR ADDRESS (WORD) + +TIMEFL EQU DRIVE+7 ; "TRUE" IF TIME MODE + +CHRPNT EQU TIMEFL+1 ; I/O BUFFER INDEX +CPSAV EQU CHRPNT+1 ; SAVE REGISTER FOR [CHRPNT] +BINDEX EQU CHRPNT+2 ; BUFFER DISPLAY INDEX +LINCNT EQU CHRPNT+3 ; # LINES DISPLAYED SINCE LAST USL +IOCHAR EQU CHRPNT+4 ; CURRENT I/O CHARACTER +GDRIVE EQU CHRPNT+5 ; GAME-SAVE DEFAULT DRIVE # +GPOSIT EQU CHRPNT+6 ; GAME-SAVE DEFAULT POSITION +RAND1 EQU CHRPNT+7 ; RANDOM NUMBER REGISTER +RAND2 EQU CHRPNT+8 ; DITTO +CYCLE EQU CHRPNT+9 ; TIMER FOR CURSOR BLINK (WORD) +BLINK EQU CHRPNT+11 ; MASK FOR CURSOR BLINK +CFLAG EQU CHRPNT+12 ; CURSOR ENABLE FLAG +SCRIPT EQU CHRPNT+13 ; SCRIPTING ENABLE FLAG +IHOLD EQU CHRPNT+14 ; INTERRUPT HOLD +TPOSIT EQU CHRPNT+15 ; TEMP GAME POSITION +TDRIVE EQU CHRPNT+16 ; TEMP GAME DRIVE + +ZPGTOP EQU CHRPNT+15 ; END OF DIRECT-PAGE VARIABLES + + END + diff --git a/colorcomputer/zstring.src b/colorcomputer/zstring.src new file mode 100644 index 0000000..e0c05dc --- /dev/null +++ b/colorcomputer/zstring.src @@ -0,0 +1,366 @@ + PAGE + SBTTL "--- Z-STRING HANDLERS ---" + + ; ----------------- + ; POINT TO Z-STRING + ; ----------------- + +SETSTR: CLRA + ASL TEMP+1 + ROL TEMP + ROLA + STA MPCH + LDD TEMP + STD MPCM + CLR MPCFLG +ZSTEX: RTS + + ; -------------- + ; PRINT Z-STRING + ; -------------- + +PZSTR: CLR CSPERM ; PERMANENT CHARSET + CLR STBYTF ; RESET STRING BYTE FLAG + LDA #$FF + STA CSTEMP ; NO TEMP CHARSET ACTIVE + +PZSTRL: JSR GETZCH ; GET A Z-CHARACTER + BCS ZSTEX ; END OF STRING IF CARRY SET + STA MASK ; SAVE CHAR HERE + BEQ PZSTRS ; O = SPACE CHAR + CMPA #4 ; IS THIS AN F-WORD? + BLO PZSTRF ; APPARENTLY SO + CMPA #6 ; SHIFT CHAR? + BLO PZSTRT ; YES, CHANGE CHARSET + + JSR GETMOD + TSTA ; IS THIS CHARSET 0? + BNE PZSTR1 ; NOPE + + ; PRINT LOWER-CASE CHAR (CHARSET 0) + + LDA #$61-6 ; ASCII "a" MINUS Z-OFFSET +PZSTP0: ADDA MASK ; ADD CHARACTER +PZSTP1: JSR COUT ; PRINT RESULT + BRA PZSTRL ; AND FETCH ANOTHER Z-CHAR + + ; CHARSET 1 OR 2? + +PZSTR1: CMPA #1 ; SET 1? + BNE PZSTR2 ; NOPE, IT'S SET 2 + + ; PRINT UPPER-CASE CHAR (CHARSET 1) + + LDA #$41-6 ; ASCII "A" MINUS Z-OFFSET + BRA PZSTP0 ; AND SO ON ... + + ; DECODE/PRINT CHARSET 2 + +PZSTR2: LDB MASK ; RETRIEVE Z-CHAR + SUBB #6 ; CONVERT TO ZERO-ALIGNED INDEX + BEQ PZSTRA ; IF ZERO, IT'S "DIRECT" ASCII + LDX #CHRTBL ; ELSE GET BASE OF DECODE TABLE + LDA B,X ; GET CHAR FROM TABLE + BRA PZSTP1 ; AND PRINT IT! + + ; DECODE/PRINT A "DIRECT" ASCII CHAR + +PZSTRA: JSR GETZCH ; GET NEXT Z-BYTE + ASLA ; SHIFT INTO POSITION + ASLA + ASLA + ASLA + ASLA + STA MASK ; SAVE MSB + JSR GETZCH ; FETCH LSB + STA MASK+1 ; SAVE THAT, TOO + LDA MASK ; GET MSB + ORA MASK+1 ; SUPERIMPOSE LSB + BRA PZSTP1 ; AND PRINT RESULT + + ; PRINT A SPACE + +PZSTRS: LDA #$20 + BRA PZSTP1 + + ; CHANGE CHARACTER SETS + +PZSTRT: SUBA #3 ; CONVERT TO 1 OR 2 + TFR A,B + BSR GETMOD + BNE PZSTRP ; NO, DO PERMANENT SHIFT + STB CSTEMP ; JUST A TEMP-SHIFT + BRA PZSTRL + +PZSTRP: STB CSPERM ; PERMANENT SHIFT + CMPA CSPERM ; NEW SET SAME AS OLD? + BEQ PZSTRL ; YES, EXIT + CLR CSPERM ; ELSE BACK TO SET 0 + BRA PZSTRL ; BEFORE FINISHING + + ; HANDLE AN F-WORD + +PZSTRF: DECA ; CONVERT TO 0-2 + LDB #64 ; TIMES 64 + MUL + STB PZSTFO ; SAVE FOR LATER + JSR GETZCH ; GET F-WORD INDEX + TFR A,B ; MOVE IT + ASLB ; FORM WORD-ALIGNED INDEX + ADDB PZSTFO ; ADD OFFSET + LDX FWORDS ; GET BASE ADDR OF FWORDS TABLE + ABX ; ADD THE OFFSET + LDD ,X ; GET THE FWORD POINTER + STD TEMP ; AND SAVE IT + + ; SAVE THE STATE OF CURRENT Z-PRINT + + LDA MPCH + PSHS A + LDA CSPERM + LDB STBYTF + LDX MPCM + LDY ZSTWRD + PSHS Y,X,B,A + + JSR SETSTR ; PRINT THE F-WORD + JSR PZSTR ; POINTED TO BY [TEMP] + + ; RESTORE THE OLD Z-STRING + + PULS Y,X,B,A + STY ZSTWRD + STX MPCM + STB STBYTF + STA CSPERM + PULS A + STA MPCH + + LDA #$FF + STA CSTEMP ; DISABLE TEMP CHARSET + CLR MPCFLG ; MPC HAS CHANGED! + JMP PZSTRL ; CONTINUE INNOCENTLY + + ; ---------------------- + ; RETURN CURRENT CHARSET + ; ---------------------- + +GETMOD: LDA CSTEMP + BPL GM + LDA CSPERM + RTS + +GM: LDB #$FF + STB CSTEMP + RTS + + ; --------------- + ; GET NEXT Z-CHAR + ; --------------- + +GETZCH: LDA STBYTF ; WHICH BYTE? + BPL GTZ0 + COMB ; SET CARRY + RTS ; TO INDICATE "NO MORE CHARS" + +GTZ0: BNE GETZH1 ; NOT FIRST CHAR + INC STBYTF + JSR GETWRD + LDD TEMP + STD ZSTWRD + LSRA + LSRA +GTEXIT: ANDA #%00011111 + CLRB ; CLEAR CARRY + RTS + +GETZH1: DECA + BNE GETZH2 ; MUST BE LAST CHAR + LDA #2 + STA STBYTF + LDD ZSTWRD + LSRA + RORB + LDA ZSTWRD + LSRA + LSRA + RORB + LSRB + LSRB + LSRB +GETZH3: TFR B,A ; EXPECTED HERE + BRA GTEXIT + +GETZH2: CLR STBYTF + LDD ZSTWRD + BPL GETZH3 + COM STBYTF ; INDICATE END OF STRING + BRA GETZH3 + + ; ------------------- + ; CONVERT TO Z-STRING + ; ------------------- + +CONZST: LDD #$0505 ; FILL OUTPUT BUFFER + STD ZSTBUO ; WITH PAD CHARS + STD ZSTBUO+2 + STD ZSTBUO+4 + + INCA ; = 6 + STA MASK ; INIT CHAR COUNT + + CLR VAL ; RESET OUTPUT AND + CLR TEMP ; INPUT INDEXES + +CNZSL1: LDB TEMP + INC TEMP + LDX #ZSTBUI ; POINT TO INPUT BUFFER + LDA B,X ; GRAB NEXT CHAR + STA MASK+1 ; SAVE IT HERE + BNE CNZSL2 ; IF CHAR WAS ZERO, + LDA #5 ; USE A Z-PAD + BRA CNZSLO + +CNZSL2: LDA MASK+1 + JSR ZCHRCS ; WHICH CHARSET TO USE? + TSTA + BEQ CNZSLC ; IF CHARSET 0, USE LOWER CASE + ADDA #3 + LDB VAL ; OUTPUT A TEMP SHIFT + LDX #ZSTBUO + STA B,X + INC VAL + DEC MASK + LBEQ CNZSLE + +CNZSLC: LDA MASK+1 + JSR ZCHRCS + DECA + BPL CNZSC1 ; NOT CHARSET 0! + LDA MASK+1 + SUBA #$61-6 ; ASCII "a" MINUS 6 + +CNZSLO: LDB VAL + LDX #ZSTBUO + STA B,X + INC VAL + DEC MASK + BEQ CNZSLE ; ALL FINISHED + BRA CNZSL1 ; ELSE LOOP BACK FOR MORE + +CNZSC1: BNE CNZSC3 ; MUST BE CHARSET 3 + LDA MASK+1 + SUBA #$41-6 ; ASCII "A" MINUS 6 + BRA CNZSLO + +CNZSC3: LDA MASK+1 + JSR CNZS2M ; IS IT IN TABLE? + BNE CNZSLO ; YES, OUTPUT THE CHAR + LDA #6 ; ELSE IT'S A "DIRECT" ASCII CHAR + LDB VAL + LDX #ZSTBUO + STA B,X ; SEND "DIRECT" TO OUTPUT + INC VAL + DEC MASK + BEQ CNZSLE ; NO MORE ROOM! + + ; CONVERT CHAR TO 2-BYTE DIRECT ASCII + + LDA MASK+1 + LSRA + LSRA + LSRA + LSRA + LSRA + ANDA #%00000011 + LDB VAL + LDX #ZSTBUO + STA B,X + INC VAL + DEC MASK + BEQ CNZSLE ; NO MORE ROOM! + LDA MASK+1 + ANDA #%00011111 ; FORM 2ND Z-BYTE + BRA CNZSLO ; AND OUTPUT IT + + ; ---------------------- + ; SEARCH CHARSET 3 TABLE + ; ---------------------- + +CNZS2M: LDX #CHRTBL + LDB #25 +CNLOOP: CMPA B,X + BEQ CNOK + DECB + BNE CNLOOP + RTS ; RETURN ZERO IN B IF NO MATCH + +CNOK: TFR B,A ; EXPECTED IN [A] + ADDA #6 ; CONVERT TO Z-CHAR + RTS + + ; ------------------------- + ; DETERMINE CHARSET OF CHAR + ; ------------------------- + +ZCHRCS: CMPA #$61 ; ASCII "a" + BLO ZCHR1 + CMPA #$7B ; ASCII "z"+1 + BHS ZCHR1 + CLRA ; IT'S CHARSET 0 + RTS + +ZCHR1: CMPA #$41 ; ASCII "A" + BLO ZCHR2 + CMPA #$5B ; ASCII "Z"+1 + BHS ZCHR2 + LDA #1 ; IT'S CHARSET 1 + RTS + +ZCHR2: TSTA + BEQ ZCHRX ; EXIT IF ZERO + BMI ZCHRX ; OR NEGATIVE + LDA #2 ; ELSE IT'S CHARSET 2 +ZCHRX: RTS + + ; --------------- + ; CRUSH 6 Z-CHARS + ; --------------- + +CNZSLE: LDD ZSTBUO ; HANDLE 1ST TRIPLET + ASLB + ASLB + ASLB + ASLB + ROLA + ASLB + ROLA + ORB ZSTBUO+2 + STD ZSTBUO + + LDD ZSTBUO+3 ; HANDLE 2ND TRIPLET + ASLB + ASLB + ASLB + ASLB + ROLA + ASLB + ROLA + ORB ZSTBUO+5 + ORA #%10000000 ; SET SIGN BIT OF LAST Z-BYTE + STD ZSTBUO+2 + RTS + + ; ---------------------- + ; CHARSET 2 DECODE TABLE + ; ---------------------- + +CHRTBL: DB 0 ; DUMMY BYTE + DB $0D ; CARRIAGE RETURN + DB "0123456789.,!?_#" + DB $27 ; SINGLE QUOTE + DB $22 ; DOUBLE QUOTE + DB "/\-:()" + + END + diff --git a/cpm80/read.me b/cpm80/read.me new file mode 100644 index 0000000..5aabdb8 --- /dev/null +++ b/cpm80/read.me @@ -0,0 +1,13 @@ +******* Directory Update and Source File Archive Record ****** + + Date of Last Change Version Letter Who Made the Change + ___________________ _____________ ____________________ + +1) NOV 6, 84 A Le +2) DEC 19, 84 B Le +3) FEB 5, 85 C Le +4) +5) +6) +7) +8) diff --git a/cpm80/zorkcpm.asm b/cpm80/zorkcpm.asm new file mode 100644 index 0000000..507a267 --- /dev/null +++ b/cpm80/zorkcpm.asm @@ -0,0 +1,4304 @@ +; ********************************************************************** +; * * +; * ZIP80 - CPM VERSION * +; * Z-CODE INTERPRETER PROGRAM * +; * FOR ZILOG Z80 MICROPROCESSOR * +; * COPYRIGHT 1984, INFOCOM, INC. * +; * COMPANY PRIVATE -- NOT FOR DISTRIBUTION * +; * * +; ********************************************************************** +; +; +; +; ********************************************************************** +; * * +; * REVISION HISTORY * +; * * +; * 7/27/84 RML * +; * 12/19/84 LS * +; * 2/5/85 LS (CLEAR RND FLG) * +; * * +; ********************************************************************** +; +; +; ************************************* +; * EQUATES * +; ************************************* +; +;-------------------------------------- +; SOME COMMON DEFINITIONS +;-------------------------------------- +; +FALSE EQU 00H ;STANDARD FALSE VALUE +TRUE EQU 0FFH ;STANDARD TRUE VALUE +; +;-------------------------------------- +; CPM EQUATES +;-------------------------------------- +; +WARM EQU 0000H ;WARM START IN BIOS +IOBYTE EQU 0003H ;I/O DEVICE BLOCK +CDISK EQU 0004H ;CURRENT DISK DRIVE +BDOS EQU 0005H ;CPM FUNCTION ENTRY POINT +LSTADR EQU 0006H ;LAST ADDRESS +CPMFCB EQU 005CH ;DEFAULT FILE CONTROL BLOCK +CPMBUF EQU 0080H ;DEFAULT FILE TRANSFER BUFFER +TPA EQU 0100H ;TRANSIENT PROGRAM AREA +; +; FILE CONTROL BLOCK OFFSETS +; +CPMDRV EQU CPMFCB+0 ;DRIVE +CPMFNB EQU CPMFCB+1 ;NAME STORAGE +CPMFEX EQU CPMFCB+9 ;EXTENTION +CPMCR EQU CPMFCB+32 ;CURRENT RECORD +CPMREC EQU CPMFCB+33 ;RECORD NUMBER FOR RANDOM ACCESS +; +; CPM FUNCTION EQUATES +; +CRESET EQU 0 ;SYSTEM RESET +CCI EQU 1 ;CHARACTER INPUT +CCO EQU 2 ;CHARACTER OUTPUT +CLO EQU 5 ;LIST OUTPUT +CDIO EQU 6 ;DIRECT I/O +CPSTNG EQU 9 ;PRINT STRING +CRCBUF EQU 10 ;READ CONSOLE BUFFER +CGCONS EQU 11 ;GET CONSOLE STATUS +CPMRDS EQU 13 ;RESET DISK SYSTEM +CPMSEL EQU 14 ;SELECT DISK +OPEN EQU 15 ;ACTIVATES EXISTING FILE FOR R/W OPERATIONS +CLOSE EQU 16 ;INACTIVATES OPEN FILE AND RECORDS NEW FCB IN DIRECTORY +DELETE EQU 19 ;REMOVE EXISTING FILE FROM THE DIRECTORY +RETCUR EQU 25 ;RETURN CURRENT DEFAULT DISK +; +;SEQUENTIAL OPERATIONS +READS EQU 20 ;READ THE NEXT 128-BYTE RECORD FROM AN OPEN FILE +WRITES EQU 21 ;WRITE A SEQUENTIAL 128-BYTE RECORD ONTO AN OPEN FILE +; +MAKEF EQU 22 ;CREATE AND OPEN A NEW FILE +CPMRCD EQU 25 ;RETURN CURRENT DISK +; +;RANDOM OPERATIONS +READR EQU 33 ;READ A SPECIFIED 128-BYTE RECORD FROM AN OPEN FILE +WRITER EQU 34 ;WRITE A 128-BYTE RECORD TO A SPECIFIED RECORD NUMBER +; IN AN OPEN FILE +; +;MISC. EQUATES +CPLMAX EQU 133 ;MAXIMUM CHARACTERS PER LINE +; +;-------------------------------------- +; APPLICATION EQUATES +;-------------------------------------- +; +MAXPGS EQU 64 ;MUST BE 64 FOR TRSN VERSIONS +ROOMG EQU 16 ;ROOM # (USED TO DISPLAY SHORT DESCRIPTION) +SCOREG EQU 17 ;SCORE +MOVESG EQU 18 ;NUMBER OF MOVES +ZSTAKL EQU 224 ;LENGTH OF THE ZSTACK IN WORDS +; +;ZCODE HEADER OFFSETS INIT VALUES +ZVERS EQU 0 ;VERSION BYTE +ZSWAP EQU 1 ;BIT FLAGS - SEE BELOW +ZID EQU 2 ;GAME ID WORD +ZENDLD EQU 4 ;START OF NON-PRELOADED ZCODE +ZSTART EQU 6 ;ZCODE 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" ZCODE +ZSCRIP EQU 16 ;WORD FLAG FOR CONTROLLING SCRIPT FEATURE +ZSERNM EQU 18 ;18 THROUGH 23 ARE ASCII SERIAL NUMBER, UNIQUE TO EACH COPY +ZFWORD EQU 24 ;TABLE OF COMMON WORDS +ZCKLEN EQU 26 ;LENGTH TO USE FOR CHECKSUM +ZCKSUM EQU 28 ;SUM OF ALL WORDS AFTER WORD 64 +; +;BIT FLAGS IN ZSWAP +ZSWAPF EQU 1 ;NOT USED +ZTIMEF EQU 2 ;IF SET, DISPLAY TIME IN STATUS LINE +ZSPLIT EQU 4 ;SET BY MAKDAT TO INDICATE SPLIT FILE +ZTANDY EQU 8 ;SET BY INTERPRETER TO DESIGNATE TANDY MACHINE +ZSTATB EQU 10H ;SET BY CPM CONSOLE PROGRAM, 1 IMPLIES NO STATUS LINE +;END OF COMMON EQUATES +; +LPDL EQU 400 ;200 LEVELS OF PUSH AND POP +; +; ************************************* +; * * +; * PROGRAM START * +; * * +; ************************************* +; + ORG 100H ;START OF THE TPA +START: + JP CPMSTR ;JUMP AROUND CONFIGURATION DATA +; +; ************************************* +; * CONFIGURATION DATA * +; ************************************* +; +CPMCPL: DB 79 ;CHARACTERS PER LINE +CPMLPP: DB 23 ;LINES PER PAGE EXCLUDING STATUS LINE +CPMFN: DB 'SUSPECT ' ;FILE PREFIX NAME (GAME DEPENDENT) +; PADDED AT THE END WITH BLANKS (' ') SO AS +; TO TOTAL 8 CHARACTERS +; +CPMCLF: DB 1 ;1 FOR LF AFTER CR ON CONSOLE +CPMLLF: DB 0 ;1 FOR LF AFTER CR ON LIST +CPMINV: DB 80H ;NUMBER ADDED TO CHARACTERS FOR INVERSE VIDEO + +;THE FOLLOWING STRINGS HAVE A COUNT FIELD FOLLOWED BY UP TO 32 CHARACTERS +ITRMST: + DB 6 ;INIT TERMINAL, CLEAR SCREEN, LOWER LEFT,SCROLL MODE + DB 1EH,1AH,1BH,'=',55,32 + DS 33-($-ITRMST) +RTRMST: DB 0 ;RESET TERMINAL + DS 33-($-RTRMST) +BSTLIN: DB 4 ;BEGIN STATUS LINE STRING + DB 1BH,'=',32,32 + DS 33-($-BSTLIN) +ESTLIN: DB 4 ;END STATUS LINE STRING + DB 1BH,'=',55,32 + DS 33-($-ESTLIN) +PSTUPS: DB 0 ;PRINTER SETUP STRING + DS 33-($-PSTUPS) +TWODSK: DB 0 ;SET TO 1 IF TWO DISKS ARE AVAILABLE +; + DS 200H-$ ;TO FIX THE ENTRY POINT REGUARDLESS OF +; VARIABLE LENGTH CONFIGURATION DATA +; +; ************************************* +; * CPM START * +; ************************************* +; +CPMSTR: ;LOCATION 200H + LD SP,PDL+LPDL ;INIT MACHINE STACK + JP BODY ;JUMP AROUND SUBROUTINE SECTION +; +; ************************************* +; * SUBROUTINES * +; ************************************* +; +ZER: JP RESTAR +; +MEMTOP: LD HL,(LSTADR) ;HL <= BDOS ENTRY VECTOR + LD A,L ; + CP 0FFH ; +; JP Z,MEMTP1 ;PREVIOUSLY COMMENTED OUT LINE (SCOTT) + LD L,0FFH ;SUBTRACT 1 BYTE + DEC H ; +MEMTP1: LD A,(ZCODEP+1) ;GET MSB OF LOW MEM STARTING POINTER + XOR H ; + AND 1 ; + RET NZ ; + DEC H ;WASTE 256 MORE IF NECESSARY + RET +; +;OPEN FILE +OPNDK1: LD (FILTYP),A ;SAVE FILETYPE + LD HL,CPMFCB ;XFER DRIVE NUMBER AND FILE NAME TO FCB + LD B,12 + CALL MOVIT + XOR A + LD (CPMCR),A ;SET CURRENT RECORD=0 (SEQUENTIAL FILE) + LD HL,0 + LD (CPMFCB+12),HL ;SET EXTENT "EX" AND S1=0 + LD (CPMFCB+14),HL ;SET S2 AND RECORD COUNT FOR EXTENT "EX"=0 + LD DE,CPMFCB ;^FCB + XOR A + LD (CPMFCB),A ;SELECT DEFAULT DRIVE + LD C,OPEN ;SELECT OPEN FUNCTION + CALL BDOS ;DO IT + INC A ;INCREMENT DIRECTORY CODE TO TEST FOR FILE NOT FOUND +; Z FLAG SET IF FILE NOT FOUND + RET NZ ;IF FILE EXISTS THEN RETURN WITH Z FLAG RESET A=0 +; ELSE +;TEST FOR TWO DISKS + LD A,(TWODSK) ;MULTIPLE DISKS? + OR A + RET Z ;NO ONLY 1, ZFLAG SET AND RETURN +; +;TWO DISKS + LD A,1 ;AUTO DISK SELECT DRIVE A + LD (CPMFCB),A ;SET UP THE PARAMETERS + XOR A + LD (CPMCR),A + LD HL,0 + LD (CPMFCB+12),HL + LD (CPMFCB+14),HL + LD DE,CPMFCB + LD C,OPEN ;TRY DRIVE 1 + CALL BDOS + INC A + RET NZ ;RETURN IF FOUND WITH ZFLAG RESET + LD A,2 ; ELSE AUTO DISK SELECT DRIVE B + LD (CPMFCB),A ;SET UP THE PARAMETERS + XOR A + LD (CPMCR),A + LD HL,0 + LD (CPMFCB+12),HL + LD (CPMFCB+14),HL + LD DE,CPMFCB + LD C,OPEN ;TRY DRIVE 2 + CALL BDOS + INC A + RET ;IF NOT FOUND, THEN Z WILL BE SET + + +PCSTR: LD A,(HL) ;PRINT STRING, GET COUNT +PCSTRL: INC HL ;POINT TO NEXT CHARACTER + OR A + RET Z ;DONE + PUSH AF + PUSH BC + PUSH DE + PUSH HL + LD E,(HL) + LD C,CDIO + CALL BDOS + POP HL + POP DE + POP BC + POP AF + DEC A + JP PCSTRL + +PCPST: LD A,(HL) ;PRINT PRINTER SETUP STRING, GET COUNT +PCPSTL: INC HL ;POINT TO NEXT CHARACTER + OR A + RET Z ;DONE + PUSH AF + PUSH BC + PUSH DE + PUSH HL + LD E,(HL) + LD C,CLO + CALL BDOS + POP HL + POP DE + POP BC + POP AF + DEC A + JP PCPSTL + +SETFIL: LD HL,FNDAT+1 ;APPEND TO THE FILE EXTENSION NAMES + CALL SETFL1 ;THE GAME NAME SUFFIX + LD HL,FNPRE+1 + CALL SETFL1 + LD HL,FNPUR+1 + CALL SETFL1 + LD HL,SRDFNM+1 +SETFL1: LD DE,CPMFN + LD B,8 + JP MOVIT + +FNDAT: DB 0,'........DAT' +FNPUR: DB 0,'........PUR' +FNPRE: DB 0,'........PRE' +SRDFNM: DB 0,'........SAV' + + +GETDSK: LD (DBUFP),HL + CALL LFILS ;OPEN ZORK/DAT FILE IF NOTHING OPEN + LD L,A + LD A,(FILTYP) + CP 3 ;DATA TYPE OF FILE? + LD A,L + JP Z,GETDK2 + LD HL,ZMEMT + CP (HL) + JP C,GETPRE ;MAKE SURE ZORK/PRE IS OPEN + SUB (HL) ;REAL OFFSET + CALL LFILD ;MAKE SURE ZORK/DAT IS OPEN + JP GETDK2 + +GETPRE: CALL LFILP ;GET ZORK/PRE +GETDK2: LD L,A + LD H,0 + ADD HL,HL + ADD HL,HL ;*4 FOR 128 BYTE BLOCKS + CALL GTDSK1 + CALL GTDSK1 + CALL GTDSK1 +GTDSK1: PUSH HL + LD (CPMREC),HL + XOR A + LD (CPMREC+2),A + LD DE,CPMFCB + LD C,READR ;READ RANDOM RECORD + CALL BDOS + OR A + CALL NZ,ZER + LD DE,CPMBUF + LD HL,(DBUFP) + LD B,128 + CALL MOVIT + LD (DBUFP),HL + POP HL + INC HL ;INCREMENT FOR NEXT TIME + RET + +MOVIT: LD A,(DE) ;TRANSFER (D) TO (H) COUNT IN B + LD (HL),A + INC HL + INC DE + DEC B + JP NZ,MOVIT + RET + +READBF: LD A,(CPMLPP) ;LINES PER PAGE + DEC A + LD (MORCNT),A + CALL FLSLIN ;FLUSH LINE + LD A,1 + LD (NOLPT),A ;TURN OFF LPT DURING READ + LD D,77 ;D CONTAINS MAX CHARS CAN READ + LD E,0 ;E CONTAINS CHAR COUNT + LD HL,(ARG1) ;READ A BUFFER + INC HL +READB1: CALL CIN ;GET A CHAR + CP 08H + JP Z,RDBFRO + CP 7FH + JP Z,RDBFRO + CP 0DH + JP Z,RDBFCR + CP 18 + JP Z,RDBFRT + CP 20H + JP C,READB1 + LD C,A + CALL COUT + LD A,C + CP 'A' + JP C,READB2 + CP 'Z'+1 + JP NC,READB2 + ADD A,'a'-'A' ;CONVERT TO LOWER CASE +READB2: LD (HL),A + INC HL + INC E + LD A,D + CP E + JP Z,RDBFFL + JP READB1 + +RDBFRO: LD A,E ;CHECK IF 1ST CHAR + CP 0 ;IF SO DON'T DELETE + JP Z,READB1 ;GO GET ANOTHER CHAR + DEC E + DEC HL + CALL COUTBS + JP READB1 + +COUTBS: LD C,08H + CALL COUT + LD C,20H + CALL COUT + LD C,08H ;DEVINE RUBOUT + JP COUT + +RDBFCR: PUSH HL + PUSH DE + XOR A + LD (NOLPT),A + LD HL,(ZCODEP) + LD DE,ZSCRIP+1 + ADD HL,DE + LD A,(HL) + AND 1 + JP Z,RDBFC2 ;NO LPT + POP DE + PUSH DE + LD A,E + OR A + JP Z,RDBFC2 ;NOTHING TYPED + LD HL,(ARG1) + INC HL +RDBFC3: LD A,(HL) + CP 'a' + JP C,RDBFC4 ;NOT LOWER CASE + SUB 'a'-'A' +RDBFC4: LD C,A + INC HL + CALL LPTO + DEC E + JP NZ,RDBFC3 +RDBFC2: POP DE + POP HL + LD A,D + CP E + JP Z,RDBFC1 + INC E + LD (HL),0DH +RDBFC1: CALL PCRLFD + LD A,E + RET + +RDBFRT: PUSH DE + PUSH HL + LD HL,(ARG1) + INC HL + CALL PCRLFD +RDBFR1: LD A,E + OR A + JP Z,RDBFR2 + LD C,(HL) + CALL COUT + DEC E + INC HL + JP RDBFR1 + +RDBFR2: POP HL + POP DE + JP READB1 + +RDBFFL: CALL CIN + CP 0DH ;ACCEPT + JP Z,RDBFCR + CP 08 ;OR + JP Z,RDBFRO + CP 7FH + JP Z,RDBFRO + PUSH DE + LD E,7 ;RING BELL, READ BUFFER FULL + LD C,CDIO + CALL BDOS + POP DE + JP RDBFFL ;AND LOOP TIL GET WHAT WE WANT + + +CIN: PUSH BC + PUSH DE + PUSH HL +CIN1: LD E,0FFH + LD C,CDIO ;READ DIRECT + CALL BDOS + OR A + JP Z,CIN2 ;NO CHARACTER YET + LD HL,RDFLG + LD (HL),0FFH ;NOT FIRST READ ANY MORE + POP HL + POP DE + POP BC + AND 7FH + RET + +CIN2: LD A,(RDFLG) + OR A + JP NZ,CIN1 ;NOT FIRST READ + CALL RND + JP CIN1 + +COUTD: LD HL,COUTDC ;INCREASE COUNT + INC (HL) + LD A,(CPMINV) ;INVERSE VIDEO ADDER + LD HL,STAFLG + AND (HL) ;ADD ONLY IF IN STATUS MODE + ADD A,C + LD E,A + LD C,CDIO + CALL BDOS + JP POPRET + +PCRLFD: PUSH BC + PUSH DE + PUSH HL + LD E,0DH + LD C,CDIO + CALL BDOS + LD A,(CPMCLF) + OR A + JP Z,PCRLD1 ;NO LINE FEED + LD E,0AH + LD C,CDIO + CALL BDOS +PCRLD1: LD C,0DH + CALL LPCHK + LD HL,MORCNT + DEC (HL) + CALL Z,MORE +POPRET: POP HL + POP DE + POP BC + RET + +LPCHK: PUSH BC + PUSH DE + PUSH HL + LD HL,(ZCODEP) + LD DE,ZSCRIP+1 + ADD HL,DE + LD A,(HL) + AND 1 + CALL NZ,LPTO + JP POPRET + +COUTCR: CALL LINOCR + JP CORET + +PCRLF: LD C,0DH +COUT: PUSH BC + PUSH DE + PUSH HL + LD A,C + CP 8 + JP Z,COUT1 + CP 1BH + JP Z,CLEARS + CP 12 + JP Z,CLEARS + CP 0DH + JP Z,COUTCR + CP 20H + JP C,CORET ;NON PRINTING +COUT1: LD A,(NOLPT) + OR A + JP NZ,COUTD + LD A,(NCHARS) + LD HL,CPMCPL + CP (HL) + CALL NC,LINOCR ;OUTPUT LINE IF FULL + LD A,(NCHARS) + INC A + LD (NCHARS),A + LD HL,(CHRPNT) + LD (HL),C + INC HL + LD (CHRPNT),HL +CORET: POP HL + POP DE + POP BC + RET + +FLSLIN: PUSH BC ;FLUSH LINE + LD A,(NCHARS) + OR A + JP Z,LINOTR ;NO CHARS + JP LINFUL ;PRINT ALL + +LINOUT: PUSH BC + LD A,(NCHARS) + OR A + JP Z,LINOTR ;NO CHARACTERS + DEC A + LD B,A + LD A,C + CP 0DH + JP Z,LINFUL + LD HL,(CHRPNT) ;FIND LAST SPACE + DEC HL +LINOT1: LD A,(HL) + CP 20H + JP Z,LINOT2 ;FOUND SPACE + DEC HL + DEC B + JP P,LINOT1 +LINFUL: LD HL,(CHRPNT) ;PRINT WHOLE LINE + LD A,(NCHARS) + LD B,A +LINOT2: PUSH BC + PUSH HL + LD HL,CHARS + LD A,B + OR A + JP Z,LINOT6 +LINOT3: PUSH BC + PUSH DE + PUSH HL + LD E,(HL) + LD C,CDIO + CALL BDOS + POP HL + PUSH HL + LD C,(HL) + CALL LPCHK + POP HL + POP DE + INC HL + POP BC + DEC B + JP NZ,LINOT3 +LINOT6: POP HL + INC HL + POP BC + LD A,(NCHARS) + SUB B + DEC A + JP P,LINOT7 + XOR A +; +LINOT7: LD (NCHARS),A ;CHARACTERS NOT YET PRINTED + JP Z,LINOT5 + LD DE,CHARS +LINOT4: LD A,(HL) + LD (DE),A + INC HL + INC DE + DEC B + JP NZ,LINOT4 +LINOT5: LD HL,CHARS + LD A,(NCHARS) + CALL HLOFF + LD (CHRPNT),HL +LINOTR: POP BC + RET + +LINOCR: CALL LINOUT + JP PCRLFD + +TMCHK: LD HL,(ZCODEP) ;RETURNS NON ZERO IF IN TIME DISPLAY MODE + LD DE,ZSWAP + ADD HL,DE + LD A,(HL) + AND ZTIMEF + RET + +CLEARS: + RET ;NOT YET IMPLEMENTED + +LPTO: LD A,(NOLPT) + OR A + RET NZ ;SOME ITEMS DON'T GO TO LPT + LD A,(PRFLG) + OR A + CALL Z,LPINIT + PUSH BC + PUSH DE + PUSH HL + LD E,C + PUSH BC + LD C,CLO ;LIST OUT + CALL BDOS + POP BC + LD A,C + CP 0DH + JP NZ,POPRET ;NOT CR + LD A,(CPMLLF) + OR A + JP Z,POPRET + LD E,0AH + LD C,CLO ;OUTPUT LF IF NEEDED + CALL BDOS + JP POPRET + +LPINIT: INC A + LD (PRFLG),A + PUSH HL + LD HL,PSTUPS + CALL PCPST ;PRINTER SETUP STRING + POP HL + RET + +WHOLIN: LD HL,BSTLIN + LD A,(HL) ;DO WE HAVE A STATUS LINE? + OR A + RET Z ;NO, RETURN + LD A,(CSPERM) ;SAVE DATA CLOBERED BY PRNTDC + LD H,A + LD A,(STBYTF) + LD L,A + PUSH HL + LD HL,(ZSTWRD) + PUSH HL + LD HL,(MPCL) + PUSH HL + LD HL,(MPCH) + PUSH HL + LD HL,BSTLIN + CALL PCSTR ;POSITON TO TOP OF SCREEN + XOR A + LD (COUTDC),A ;BEGINNING OF LINE + LD A,1 + LD (NOLPT),A + LD A,0FFH + LD (STAFLG),A ;STATUS LINE FLAG (ANDED WITH CPMINV ADDER) + CALL TMCHK + JP NZ,WHOLT + CALL WHOLN1 ;COMMON TIME/ROOM PRINTING + LD HL,WHOMSG ;PRINT 'SCORE' + CALL POSPST ;POSITION THEN PRINT + LD A,SCOREG + CALL VARGET + CALL PRNTNC + LD C,'/' + CALL COUT + LD A,MOVESG + CALL VARGET + CALL PRNTNC +WHOLN2: LD A,(CPMCPL) + LD B,A + CALL CHRPOS ;BLANK REST OF LINE + LD HL,ESTLIN + CALL PCSTR ;POSITION BACK TO LOWER LEFT + XOR A + LD (NOLPT),A + LD (STAFLG),A + LD (MPCFLG),A ;RESTORE STRING VALUES + POP HL + LD A,L + LD (MPCH),A + POP HL + LD (MPCL),HL + POP HL + LD (ZSTWRD),HL + POP HL + LD A,H + LD (CSPERM),A + LD A,L + LD (STBYTF),A + CALL GETMOD + RET + + +WHOLN1: LD C,' ' ;PRINT A ' ' + CALL COUT + LD A,ROOMG ;GET THE CURRENT ROOM NO. + CALL VARGET + LD A,L + JP PRNTDC ;PRINT THE SHORT DESCRIPTION +; +; PRINT THE TIME (HOURS) +WHOLT: CALL WHOLN1 + LD HL,WHOTMS ;PRINT '.......TIME' MESSAGE + CALL POSPST + LD A,SCOREG ;GET HOURS IN MILITARY TIME (24 HR CLOCK) + CALL VARGET + LD A,L ;A <= HOURS + PUSH AF ;SAVE HOURS + OR A ;HOURS=0? + JP NZ,WHOLT0 ; NO. + LD L,12 ; YES. 0 HRS IS REALLY 12 HOURS + JP WHOLT1 +; +WHOLT0: CP 13 ;COMPARE HOURS (24 HR CLOCK) WITH 13 + JP C,WHOLT1 ; IF < 13 THEN PRINT HOURS + SUB 12 ; ELSE A <= A-12 + LD L,A ; L <= ADJUSTED TIME (12 HR CLOCK) +WHOLT1: CALL PRNTNC ;PRINT THE HOURS + LD C,':' ;PRINT ':' + CALL COUT +; +; PRINT TIME (MINUTES) + LD A,MOVESG ;GET THE MINUTES + CALL VARGET ;A <= MINUTES + CALL PNTTIM ;PRINT THE MINUTES + LD C,' ' ;PRINT A ' ' + CALL COUT +; +; PRINT 'AM/PM' + LD C,'a' + POP AF ;RESTORE HOURS + CP 24 ;24 HOURS IS AM + JP Z,WHOLT2 + CP 12 ;< 12 HOURS IS AM + JP C,WHOLT2 + LD C,'p' ;ELSE IT'S PM +WHOLT2: CALL COUT ;PRINT 'A/P' + LD C,'m' + CALL COUT ;PRINT 'M' + JP WHOLN2 +; +CHRPOS: LD A,(COUTDC) ;SPACE UNTILE COUTDC=(B) + CP B + RET NC + PUSH BC + LD C,20H + CALL COUT + POP BC + JP CHRPOS + +POSPST: LD A,(CPMCPL) + CP 39 ;VERY SHORT + JP C,POSPS1 ;DON'T PRINT WORDS + SUB 16 + PUSH HL + LD B,A + CALL CHRPOS ;SPACE OVER + POP HL + LD B,(HL) +POSPS2: INC HL + LD C,(HL) + CALL COUT + DEC B + JP NZ,POSPS2 + RET + +POSPS1: SUB 8 ;MOVE OVER 8 FROM EDGE + LD B,A + JP CHRPOS + +WHOMSG: DB 7,'Score:',20H + +WHOTMS: DB 6,'Time:',20H + +MORMSG: DB '-------------More-------------',0 +LMORE EQU $-MORMSG + +MORE: LD A,(CPMLPP) + OR A + RET Z ;NO MORE LINE IF 0 + DEC A + LD (HL),A + CALL WHOLIN ;SHOW STATUS + LD A,1 + LD (NOLPT),A ;DON'T SCRIPT MORE MESSAGE + LD HL,MORMSG + CALL MSGOUT + CALL CIN + LD E,0DH + LD C,CDIO ;CR WITHOUT LF + CALL BDOS + LD B,LMORE +MORE1: PUSH BC + LD E,20H + LD C,CDIO + CALL BDOS + POP BC + DEC B + JP NZ,MORE1 + LD E,0DH + LD C,CDIO + CALL BDOS + XOR A + LD (NOLPT),A + RET ;NOW AT BEGINNING OF CLEAR LINE + +PNTTIM: LD DE,10 + CALL HLGEDE + LD C,'0' + CALL NC,COUT + JP PRNTNC + +;ZZZZZZZZZZZZZZZZZZZZZZZZZZZ +QUIT: LD DE,CPMFCB + LD C,CLOSE + CALL BDOS + LD HL,RTRMST + CALL PCSTR + LD C,CRESET + CALL BDOS + JP QUIT + +RESTAR: + LD DE,CPMFCB + LD C,CLOSE + CALL BDOS + LD HL,RTRMST + CALL PCSTR + JP START + +SAVE: + XOR A + LD (FILTYP),A + LD DE,CPMFCB ;CLOSE CURRENT FCB + LD C,CLOSE ;SO FILE IS PROTECTED + CALL BDOS + CALL SRGFNM ;GET SAVE NAME (SWAP DISKS) + LD DE,CPMFCB ;DELETE ANY PREVIOUS FILE + LD C,DELETE ;BY THIS NAME + CALL BDOS + LD DE,CPMFCB ;CREATE NEW SAVE FILE + LD C,MAKEF + CALL BDOS + INC A + JP Z,SFAIL ;DID NOT OPEN + LD HL,(ZCODEP) + LD BC,ZVERS + ADD HL,BC + LD A,(HL) ;STORE VERSION NUMBER + LD (CPMBUF),A + LD HL,(ZSTAKP) + LD (CPMBUF+1),HL + LD HL,CPMBUF+3 + LD DE,SRND + LD BC,SRNDC ;TO MAKE EXTERNALS WORK + LD B,C + CALL MOVIT + LD DE,CPMFCB + LD C,WRITES + CALL BDOS + OR A + JP NZ,SFAIL ;WRITE OUT INITIAL STUFF + LD C,0+(((ZSTAKL*2)+127)/128) + LD DE,ZSTACK ;NEXT WRITE OUT STACK +SAVEA: LD B,128 + LD HL,CPMBUF + CALL MOVIT + PUSH BC + PUSH DE + LD DE,CPMFCB + LD C,WRITES ;WRITE SEQ. RECORD + CALL BDOS + OR A + JP NZ,SRFAIL + POP DE + POP BC + DEC C + JP NZ,SAVEA ;ALL ZSTACK RECORDS DONE? + LD HL,(ZCODEP) + LD DE,ZPURBT + ADD HL,DE + LD C,(HL) ;COUNT OF PAGES + LD HL,(ZCODEP) + EX DE,HL ;WHERE TO START FROM + LD B,2 ;128 BYTE RECORDS +SAVE1: PUSH BC + LD HL,CPMBUF + LD B,128 + CALL MOVIT ;GET NEXT RECORD TO TRANSFER + PUSH DE + LD DE,CPMFCB + LD C,WRITES ;WRITE IT SEQ. TO DISK + CALL BDOS + POP DE + POP BC + OR A + JP NZ,SFAIL ;WRITE ERROR + DEC B + JP NZ,SAVE1 ;GO DO 2ND HALF OF PAGE + LD B,2 ;RESET FOR 2 RECORDS PER PAGE + DEC C + JP P,SAVE1 ;NEXT PAGE +SRCLOS: LD DE,CPMFCB + LD C,CLOSE ;DONE, CLOSE SAVE FILE + CALL BDOS + CALL SRSWPD ;TELL PLAYER SWAP GAME DISK BACK IN + LD C,CPMRCD ;GET CURRENT DEFAULT DRIVE + CALL BDOS + PUSH AF ;HOLD IT A SEC + LD C,CPMRDS ;RESET SYSTEM FOR NEW DISK + CALL BDOS + POP AF ;RETRIEVE + LD E,A ;AND RESET CORRECT DEFAULT + LD C,CPMSEL ;(DESTROYED BY RESET SYSTEM) + CALL BDOS + CALL PCRLF + XOR A + LD (ZPCFLG),A + JP PREDS + + + +SFAIL: LD DE,CPMFCB + LD C,CLOSE + CALL BDOS + LD DE,CPMFCB + LD C,DELETE + CALL BDOS + JP SFAIL1 + +SRFAIL: LD DE,CPMFCB + LD C,CLOSE + CALL BDOS +SFAIL1: CALL SRSWPD + LD C,CPMRCD ;RETURN CURRENT DEFAULT DISK + CALL BDOS + PUSH AF + LD C,CPMRDS + CALL BDOS + POP AF + LD E,A + LD C,CPMSEL ;RESELECT DEFAULT + CALL BDOS + XOR A + LD (ZPCFLG),A + JP PREDF + +SRGFNM: LD HL,SRMSG1 + CALL MSGOUT + + LD B,8 + LD HL,SRDFNM+1 ;FILENAME + CALL SRGFNA ;DISPLAY CHARS TILL HIT BLANKS + LD HL,SRMSG3 + CALL MSGOUT + LD B,3 + LD HL,SRDFNM+9 + CALL SRGFNA + LD HL,SRMSG2 + CALL MSGOUT + LD HL,0 + LD (CPMFCB+12),HL ;CLEAR EX,S1 + LD (CPMFCB+14),HL ; S2,RC + XOR A + LD (CPMCR),A ; CR + LD DE,CPMBUF + LD A,14 + LD (DE),A + LD C,CRCBUF ;READ CONSOLE BUFFER + CALL BDOS + CALL PCRLFD + LD C,CPMRCD ;RETURN CURRENT DISK + CALL BDOS + PUSH AF + LD C,CPMRDS ;RESET SYSTEM + CALL BDOS + POP AF + LD E,A + LD C,CPMSEL ;RESELECT DEFAULT + CALL BDOS + LD A,(CPMBUF+1) + OR A + JP Z,SRGDFN ;USE DEFAULT, SKIP THIS NEXT PART + LD B,11 + LD HL,SRDFNM + INC HL ;SKIP OVER DRIVE, LEAVE AS WAS SO PLAYER + ;NEED ONLY SPECIFY IT ONCE +SRGFM1: LD (HL),20H + INC HL + DEC B + JP NZ,SRGFM1 ;FILL WITH BLANK FILE NAME + LD B,A ;SAVE COUNT OF CHARACTERS + LD HL,CPMBUF+2 ;BEG OF FILE NAME + LD DE,SRDFNM+1 ;STORAGE FOR FILE NAME + CP 3 + JP C,SRGFN2 ;NO DRIVE SPEC + LD A,(CPMBUF+3) + CP ':' ;DRIVE SPEC? + JP NZ,SRGFN2 ;NONE THIS TIME + DEC B + DEC B + LD A,(HL) + AND 0FH ;DRIVE NUMBER + LD (SRDFNM),A + INC HL + INC HL ;POINTER PAST DRIVE SPEC +SRGFN2: DEC B + JP M,SRGDFN ;FILE NAME NOW DEFAULT + LD A,(HL) + CALL UPPER + INC HL + CP '.' + JP Z,SRGFN3 ;EXTENTION + LD (DE),A + INC DE + JP SRGFN2 + +SRGFNA: LD A,(HL) + CP ' ' + JP Z,SRGFNB + LD C,A + PUSH BC + PUSH DE + PUSH HL + LD E,(HL) + LD C,CDIO + CALL BDOS + POP HL + PUSH HL + CALL MSGCRC ;SEND LF IF NECESSARY + POP HL + POP DE + POP BC + CALL LPCHK +SRGFNB: INC HL + DEC B + JP NZ,SRGFNA + RET + +UPPER: CP 'a' + RET C + CP 'z'+1 + RET NC + SUB 'a'-'A' + RET + +SRGFN3: LD DE,SRDFNM+9 + LD A,B + AND 3 ;MAX OF 3 CHARACTERS + LD B,A + JP SRGFN2 + +SRGDFN: LD DE,SRDFNM ;DEFAULT FILE NAME + LD HL,CPMFCB + LD B,12 + JP MOVIT + +SRSWPD: LD HL,LFILDG +MSGRES: CALL MSGOUT ;MESSAGE THEN RESPONSE + CALL CIN ;WAIT FOR CHARACTER + LD HL,CRMSG + JP MSGOUT + +CRMSG: DB 0DH,0 + +LFILDG: DB 'Load Game Disk if it was removed.',0DH + DB 'Type to continue >',0 +LFILDM: DB 'Load Disk 2, type to continue >',0 +LFILPM: DB 'Load Disk 1, type to continue >',0 +LFILGM: DB 'Load Game Disk, type to continue >',0 + +SRMSG1: DB 'Load SAVE disk then enter file name.',0DH + DB '(default file name is ',0 + +SRMSG2: DB ').',0DH + DB 'Type to continue > ',0 + +SRMSG3: DB '.',0 + +MSGOUT: LD C,(HL) + LD A,(HL) + OR A + RET Z + PUSH BC + PUSH DE + PUSH HL + LD E,(HL) + LD C,CDIO + CALL BDOS + POP HL + PUSH HL + CALL MSGCRC + POP HL + POP DE + POP BC + CALL LPCHK + INC HL + JP MSGOUT + +MSGCRC: LD A,(CPMCLF) + OR A + RET Z ;NO LF AFTER CR + LD A,(HL) + CP 0DH + RET NZ ;NOT CR + LD E,0AH ;PRINT A LF + LD C,CDIO + CALL BDOS + RET + + +RESTOR: XOR A + LD (FILTYP),A + LD DE,CPMFCB + LD C,CLOSE + CALL BDOS + CALL SRGFNM + LD DE,CPMFCB + LD C,OPEN + CALL BDOS + INC A + JP Z,SRFAIL + LD DE,CPMFCB + LD C,READS + CALL BDOS + OR A + JP NZ,SRFAIL + LD HL,(ZCODEP) + LD DE,ZVERS + ADD HL,DE + LD A,(CPMBUF) + CP (HL) + JP NZ,SRFAIL ;VERSIONS DIFFER + LD HL,(CPMBUF+1) + LD (ZSTAKP),HL ;STACK POINTER + LD DE,CPMBUF+3 + LD HL,SRND + LD BC,SRNDC ;TO MAKE EXTERNALS WORK + LD B,C + CALL MOVIT ;RESTORE RANDOM DATA + LD C,0+(((ZSTAKL*2)-1)/128) ;ONE TOO FEW + LD HL,ZSTACK ;NEXT WRITE OUT STACK +RESTA: PUSH BC + PUSH HL + LD DE,CPMFCB + LD C,READS + CALL BDOS + POP HL + POP BC + OR A + JP NZ,SRFAIL + LD DE,CPMBUF + LD B,128 + CALL MOVIT + DEC C + JP NZ,RESTA + PUSH HL ;READ LAST BLOCK + LD DE,CPMFCB + LD C,READS + CALL BDOS + POP HL + OR A + JP NZ,SRFAIL + LD DE,CPMBUF + LD B,0+((ZSTAKL*2)-((((ZSTAKL*2)-1)/128)*128)) + CALL MOVIT + LD HL,(ZCODEP) + LD DE,ZSCRIP+1 + ADD HL,DE + LD (SCPLOC),HL ;LOCATION OF SCRIPT FLAG + LD A,(HL) + AND 1 ;ISOLATE SCRIPT BIT + LD (SCPVAL),A ;AND SAVE + LD HL,(ZCODEP) + LD DE,ZPURBT + ADD HL,DE + LD C,(HL) + LD HL,(ZCODEP) ;POINTER TO BEGINNING OF DATA + LD B,2 ;128 BYTE RECORDS +REST1: PUSH BC + PUSH HL + LD DE,CPMFCB + LD C,READS + CALL BDOS + POP HL + POP BC + OR A + JP NZ,RESTAR + LD DE,CPMBUF + PUSH BC + LD B,128 + CALL MOVIT + POP BC + DEC B + JP NZ,REST1 + LD B,2 + DEC C + JP P,REST1 + LD HL,(SCPLOC) + LD A,(HL) + AND 0FEH ;CLEAR SCRIPT BIT + PUSH HL + LD HL,SCPVAL + OR (HL) ;OR IN VALUE FROM MEMORY + POP HL + LD (HL),A + JP SRCLOS ;ALL DONE + +LFILS: PUSH AF + LD A,(FILTYP) + CP 3 ;.DAT FILE ALREADY OPEN? + JP Z,LFILR ; YES. RETURN. + OR A ; NO. SOME OTHER TYPE OPEN? + JP NZ,LFILR ; YES. RETURN. +LFILS1: LD DE,FNDAT ; NO. ^ DATA FILE NAME + LD A,3 ;OPEN TYPE 3 + CALL OPNDK1 ;TRY TO OPEN FILE + JP NZ,LFILR ;OPEN .DAT FILE COMPLETE? + ; YES. RETURN. + LD A,(TWODSK) ;CHECK IF 1 OR 2 DISKS FOR GAME + CP 1 ;IF = 1 THEN 2 DISKS + JP Z,LFILF ;SO GO TRY OTHER TYPE FILES + LD HL,LFILGM ;ELSE ASK FOR CORRECT DISK + CALL MSGRES + JP LFILS1 ;AND TRY AGAIN +LFILF: XOR A ; NO. SET FILTYP=0 + LD (FILTYP),A ;OPEN FAILED TRY OTHER TYPE + JP LFILR + +LFILD: PUSH AF + LD A,(FILTYP) + CP 2 ;.PUR FILE ALREADY OPEN? + JP Z,LFILR ; YES.ALREADY OPEN + CALL LFILC ;CLOSE EXISTING FILE IF ANY +LFILD1: LD DE,FNPUR + LD A,2 + CALL OPNDK1 ;TRY TO OPEN PURELOAD FILE + JP NZ,LFILR ;OPEN OK + LD HL,LFILDM + CALL MSGRES ;ASK TO LOAD DISK + JP LFILD1 ;TRY AGAIN + +LFILP: PUSH AF + LD A,(FILTYP) + CP 1 ;PRELOAD TYPE? + JP Z,LFILR ;OPEN + CALL LFILC +LFILP1: LD DE,FNPRE + LD A,1 + CALL OPNDK1 + JP NZ,LFILR ;OPEN OK + LD HL,LFILPM + CALL MSGRES ;LOAD PROPER DISK + JP LFILP1 + +LFILR: POP AF + RET + +LFILC: OR A + RET Z ;NONE OPEN + LD DE,CPMFCB + LD C,CLOSE + CALL BDOS + XOR A + LD (FILTYP),A + RET + +;DATA + +STAFLG: DB 0 ;0FFH WHEN IN STATUS LINE MODE +COUTDC: DB 0 ;CHARACTER COUNT UNDER STATUS LINE +RDFLG: DB 0 ;0 FOR FIRST READ +PRFLG: DB 0 ;0 FOR FIRST PRINT +SCPLOC: DW 0 ;SCRIPT LOCATION +SCPVAL: DB 0 ;SCRIPT VALUE +DBUFP: DW 0 ;DSK POINTER +NCHARS: DB 0 +CHARS: DS CPLMAX +CHRPNT: DW CHARS + +FILTYP: DB 0 ;0 FOR NONE, 1 FOR PRE, 2 FOR PUR, 3 FOR DAT +MORCNT: DB 23 + +;(PUT IN CODE SEGMENT TO PRESERVE COMMON ZORKBODY) +PDL: DS LPDL ;CONTROL STACK +ZSTAKP: DW ZSTACK+(2*ZSTAKL) ;POINTER TO CURRENT ZSTACK +ZSTACK: DS ZSTAKL*2 ;ZSTACK +PGTBL: DS MAXPGS ;PAGE NUMBER, 0 ALWAYS IN MEMORY, THUS 0=FREE +PGTBLF: DS MAXPGS ;NEXT LINK POINTER, 0FFH IMPLIES END POINT +PGTBLB: DS MAXPGS ;PREVIOUS LINK POINTER +PGTFD EQU PGTBLF-PGTBL +PGTBD EQU PGTBLB-PGTBL + +VRS: DB 0DH,'UPDATED 2.5.85',0DH,0 +VRLINE: DB 0DH,'VERSION C',0DH,0 +; +; ********************************************************************** +; * * +; * WARMSTART ENTRY * +; * * +; ********************************************************************** +; +; +; MAIN BODY OF CODE STARTS HERE. +; +BODY: XOR A + LD (ZPCFLG),A ;DISABLE TIME IN STATUS LINE, NO SPLIT FILE, NOT TANDY + LD (MPCFLG),A ;NO VALID MEMORY IN FROM DISK (MPCPNT NOT VALID) + LD (PGTOP),A ;SET TOP OF LIST PAGE + + LD C,RETCUR ;GET CURRENT DEFAULT DRIVE + CALL BDOS ;RETS IN A + LD E,A ;SET DEFAULT DRIVE + LD C,CPMSEL ;THIS SEEMS REDUNDENT BUT THE MACHINE IS NOT + CALL BDOS ;RECOGNIZING RESETS FROM BOOT DRIVE DONE BEFORE + ;STARTING THE GAME + +; +; INITIALIZE ZSTACK +; + LD A,1 + LD (ZSTAKC),A ;INITIALIZE ZSTACK POSITION COUNTER + LD HL,ZSTACK+(2*ZSTAKL) + LD (ZSTAKP),HL ;SAVE THE LOCATION OF THE BOTTOM OF ZSTACK IN +; ZSTACK POINTER +; +; INITIALIZE PAGE TABLES +; + LD DE,PGTBL ;DE ^ TOP OF PAGE TABLE + LD BC,0+(MAXPGS*256) ;FOR NUMBER OF PAGES (IN B) +; +START1: +; INITIALIZE PGTBL + XOR A + LD (DE),A ;(PGTBL+PAGE NUMBER) <= 0 +; FREE THE PAGE (NO PAGE IN MEMORY) +; + LD HL,PGTFD ;HL <= MAXIMUM NUMBER OF PAGES +; USED AS AN OFFSET INTO PGTBLF +; +; INITIALIZE FOWARD POINTER + ADD HL,DE ;HL ^ PAGE FORWARD POINTER TABLE SLOT + LD (HL),C ;SAVE CURRENT POINTER + INC (HL) ;ADD 1 TO MAKE IT A FORWARD POINTER +; +; INITIALIZE PREVIOUS POINTER + LD HL,PGTBD ;HL ^ PAGE PREVIOUS POINTER TABLE BASE ADDRESS + ADD HL,DE ;ADD OFFSET + LD (HL),C ;SAVE CURRENT POINTER + DEC (HL) ;SUBTRACT 1 TO MAKE IT A PREVIOUS POINTER +; +; UPDATE + INC C ;NEXT PAGE + INC DE ;NEXT SLOT IN TABLES +; +; TEST LOOP FOR DONE + DEC B ;DECREMENT NUMBER OF SLOTS REMAINING + JP NZ,START1 ;>0? YES. CONTINUE LOOPING. +; +; CORRECT FOR NO FORWARD POINTER FOR LAST PAGE +; + LD HL,PGTFD-1 + ADD HL,DE + LD (HL),0FFH +; +; SET BOTTOM PAGE NO. +; + LD A,MAXPGS-1 + LD (PGBOT),A +; +; COMPUTE ZCODE STARTING ADDRESSS +; + LD HL,LMEMRY ;POINT HL PAST ZIP + LD DE,0FFH ;ADJUST ADDRESS TO A PAGE BOUNDRY + ADD HL,DE + LD L,0 + LD (ZCODEP),HL ;SAVE ZCODE STARTING ADDRESS +; +; SET UP FILE NAMES FOR DAT, PRE, PUR AND SAV +; + CALL SETFIL ;APPEND GAME NAME PREFIX TO FILE NAME EXTENSIONS +; +; RESET FILE TYPE +; + XOR A ;RESET FILTYP + LD (FILTYP),A +; +; INITIALIZE TERMINAL +; + LD HL,ITRMST ;POINT TO TERMINAL INITIALIZATION STRING + CALL PCSTR ; FOR HOME, CLEAR SCREEN AND PRINT IT +; +; INITIALIZE TERMINAL RELATED COUNTERS +; + LD A,(CPMLPP) ;INITIALIZE LINES/PAGE (EXCLUDING STATUS LINE) + DEC A ;COUNTER (MORCNT) =(CPMLPP)-1 + LD (MORCNT),A ; WHICH TELLS THE PROGRAM WHEN TO PRINT ....MORE.... + XOR A ;A<=0 + LD (NCHARS),A ;RESET (NCHARS) + LD HL,CHARS ;SET UP CHARACTERS/LINE + LD (CHRPNT),HL +; +; GET THE FIRST SECTOR OF ZCODE +; + LD HL,(ZCODEP) ;^ TOP OF ZCODE BUFFER + XOR A + CALL GETDSK ;READ IN FIRST SECTION +; +; EXTRACT GAME DATA FROM ZCODE HEADER +; + LD HL,(ZCODEP) ;HL ^ TOP OF ZCODE BUFFER + LD DE,ZENDLD ;DE <= OFFSET TO NON-PRELOADED ZCODE + ADD HL,DE ;HL ^ START OF NON-PRELOADED ZCODE + LD D,(HL) ;GET MSB OF ENDLOAD POINTER + INC HL ; ADD 1 + LD E,(HL) ;GET LSB OF ENDLOAD POINTER + LD HL,200H ;HL <= 256 + ADD HL,DE ;HL <= ENDLOAD POINTER + 200H + LD A,H ;A <= MSB + AND 0FEH ; + LD H,A ; + LD L,0 ; + DEC HL ;ALL THIS TO GET TO BLOCK BOUNDRY + EX DE,HL ;DE <= CORRECTED ENDLOAD POINTER + LD BC,ZENDLD ;BC <= OFFSET TO NON-PRELOADED ZCODE + LD HL,(ZCODEP) ;HL ^ TOP OF ZCODE BUFFER + ADD HL,BC ;HL ^ START OF NON-PRELOADED ZCODE + LD (HL),D ;SAVE MSB OF CORRECTED ENDLOAD POINTER + INC HL + LD (HL),E ;SAVE LSB OF CORRECTED ENDLOAD POINTER + LD HL,(ZCODEP) ;HL ^ TOP OF ZCODE BUFFER + PUSH DE ;SAVE CORRECTED ENDLOAD POINTER ON STACK + ADD HL,DE ;HL ^ END OF PRELOAD + EX DE,HL ;DE ^ END OF PRELOAD + CALL MEMTOP ;DETERMINE WHERE THE TOP OF MEMORY IS (IN HL) + EX DE,HL ;DE <= TOP OF MEMORY, HL <= END OF THE PRELOAD + CALL HLGEDE ;CARRY FLAG SET IF HL G.E. DE + POP DE ;RESTORE CORRECTED ENDLOAD POINTER + CALL C,ZER ;NO ROOM FOR ANY BUFFERS + LD A,D + RRCA + AND 7FH + LD D,A ;NUMBER OF PAGES IN REST OF THE PRELOAD + INC A + LD (ZMEMT),A ;PAGE NUMBER + LD HL,(ZCODEP) ;^ START OF ZCODE BUFFER + LD BC,200H + LD E,0 +; +; LOAD PRELOAD +; +START2: LD A,D ;A <= PAGES REMAINING TO BE LOADED + OR A ;DONE? + JP Z,START3 ; YES. + DEC D + ADD HL,BC + INC E + LD A,E + PUSH BC + PUSH DE + PUSH HL + CALL GETDSK + POP HL + POP DE + POP BC + JP START2 + +START3: LD HL,(ZCODEP) + EX DE,HL + LD HL,ZSWAP + ADD HL,DE + LD A,(HL) + AND 1 + CALL NZ,ZER ;SWAPPED + LD HL,ZSTART+1 + ADD HL,DE + LD A,(HL) + LD (ZPCL),A + DEC HL + LD A,(HL) + AND 1 + LD (ZPCL+1),A + LD A,(HL) + RRCA + AND 7FH + LD (ZPCH),A + LD HL,ZGLOBA + ADD HL,DE ;GET RELATIVE ADDRESS OF GLOBAL TABLE + PUSH DE + LD D,(HL) + INC HL + LD E,(HL) + EX DE,HL + POP DE + ADD HL,DE ;REAL ADDRESS OF GLOBAL TABLE + LD (GLOBAL),HL ;STORE IT + LD HL,ZFWORD + ADD HL,DE ;GET RELATIVE ADDRESS OF FWORDS TABLE + PUSH DE + LD D,(HL) + INC HL + LD E,(HL) + EX DE,HL + POP DE + ADD HL,DE ;REAL ADDRESS OF FWORDS TABLE + LD (FWORDS),HL ;STORE IT + LD HL,ZENDLD ;CALCULATE ^ TO BEGINNING OF PAGE BUFFERS + ADD HL,DE + PUSH DE + LD D,(HL) + INC HL + LD E,(HL) + POP HL + ADD HL,DE + INC HL + LD (PGBUFP),HL ;STORE IT + DEC HL ;CALCULATE NO. OF AVAILABLE PAGES + EX DE,HL ;TOP LOCATION + CALL MEMTOP + LD A,H + SUB D + RRCA + AND 7FH ;SWAPPING SPACE + CP MAXPGS + JP C,STAR3A + LD A,MAXPGS +STAR3A: LD (NPGS),A ;SAVE NUMBER OF PAGES + DEC A + LD (PGBOT),A + LD HL,PGTBLF + CALL HLOFF + LD (HL),0FFH ;SET LAST PAGE +; +; INITIALIZE RANDOM NUMBER +; + LD B,5 + LD HL,0FFFFH + LD (SHIFT),HL + LD (SHIFT+2),HL + LD HL,RDFLG ;SET FLAG TO 1ST READ + LD (HL),0 +START4: CALL RND + DEC B + JP NZ,START4 +; +; +; + XOR A + LD (NOLPT),A ;USE LPT + LD HL,(ZCODEP) + LD DE,ZSWAP + ADD HL,DE + LD A,(HL) + LD B,A + LD A,(BSTLIN) ;IS THERE A STATUS LINE? + OR A + LD A,B + JP NZ,START5 + OR ZSTATB ;INDICATE NO STATUS LINE +START5: LD (HL),A +; JP MLOOP ;COMMENTED OUT FOR FALL THROUGH +; +; ********************************************************************** +; * * +; * MAINLOOP * +; * * +; ********************************************************************** +; +; +;MAIN LOOP, READ AN INSTRUCTION AND ITS ARGS, THEN DISPATCH + +MLOOP: XOR A + LD (ARGCNT),A ;ZERO ARG COUNT + CALL NEXTPC ;GET NEXT OPCODE IN A + LD (OPCODE),A ;SAVE IT + CP 128 + JP C,OP2 ;2-OP + CP 176 + JP C,OP1 ;1-OP + CP 192 + JP C,OP0 ;0-OP +; +; HANDLE AN X-OP +; +OPEXT: CALL NEXTPC ;GET VAR TYPES, THIS IS AN EXT OP + LD DE,ARG1 + LD B,4 ;MAX NUMBER OF ARGS + LD C,A +OPEXTL: PUSH BC + PUSH DE + LD A,C + AND 0C0H ;ISOLATE BIT7, BIT6 TO DETERMINE ARG TYPE + CALL Z,GETLNG ;00=LONG IMMEDIATE + CP 80H + CALL Z,GETVAR ;10=VARIABLE + CP 40H + CALL Z,GETSHT ;01=SHORT IMMEDIATE + POP DE + POP BC + CP 0C0H ;11=NO MORE VARIABLES + JP Z,OPEXTF ;ALL DONE? + EX DE,HL ;NO. STORE VALUE + LD (HL),E + INC HL + LD (HL),D + INC HL + EX DE,HL ;POINTER BACK IN DE + LD HL,ARGCNT + INC (HL) ;ONE MORE ARG + LD A,C + RLCA + RLCA ;GET TO NEXT ARG TYPE + LD C,A + DEC B ;DECREMENT ARG COUNT + JP NZ,OPEXTL ;LOOP FOR MORE +; +; DISPATCH THE X-OP +; +OPEXTF: LD HL,OPEXTT ;COMPUTE DISPATCH POINTER + LD A,(OPCODE) ;RETRIEVE THE OPCODE + CP 224 ;IS IT AN EXTENDED 2-OP? + JP C,OP2EX ; YES. + SUB 224 ; NO. + CP OPEXTM ;IS IT A LEGAL X-OP? + JP NC,BADOP ; NO. +; +; GENERALIZED DISPATCH +; +OPDSPH: + ADD A,A ;FORM A WORD OFFSET (*2) + LD C,A ;PUT OFFSET INTO BC + LD B,0 + ADD HL,BC ;ADD OFFSET TO DISPATCH POINTER + LD E,(HL) ;ADDRESS LSB + INC HL + LD D,(HL) ;ADDRESS MSB + LD HL,(ARG1) ;FIRST ARG + EX DE,HL ;HL ^ TABLE ADDRESS OF ROUTINE +; DE <= FIRST ARG + LD A,(ARGCNT) ;B <= ARG COUNT + LD B,A + JP (HL) ;GO TO IT +; +; HANDLE A 0-OP +; +OP0: SUB 176 ;ADJUST VALUE + CP OP0M ;IS IT A LEGAL 0-OP? + JP NC,BADOP ; NO. + LD HL,OP0T ; YES. HL ^ 0-OP TABLE + JP OPDSPH ;DISPATCH IT +; +; HANDLE A 1-OP +; +OP1: AND 30H ;1 OP, ISOLATE BITS 5,4 + CALL Z,GETLNG ;00=LONG IMMEDIATE + CP 10H + CALL Z,GETSHT ;01=SHORT IMMEDIATE + CP 20H + CALL Z,GETVAR ;10=VARIABLE + LD A,1 + LD (ARGCNT),A ;1 ARG + LD (ARG1),HL ;STORE IT + LD A,(OPCODE) ;RESTORE OPCODE + AND 0CFH ;(NOT 30H) TURN OFF MODE BITS + SUB 128 ;ADJUST VALUE + CP OP1M ;LEGAL 1-OP? + JP NC,BADOP ; NO. + LD HL,OP1T ; YES. HL ^ 1-OP TABLE + JP OPDSPH ;DISPATCH IT +; +; HANDLE A 2-OP +; +OP2: AND 40H ;ISOLATE 1ST. ARG BIT + CALL NZ,GETVAR ;1=VARIABLE + CALL Z,GETSHT ;0=SHORT IMMEDIATE + LD (ARG1),HL ;STORE ARG1 + LD A,(OPCODE) ;RESTORE OPCODE + AND 20H ;ISOLATE 2ND. ARG BIT + CALL NZ,GETVAR ;1=VARIABLE + CALL Z,GETSHT ;2=SHORT IMMEDIATE + LD (ARG2),HL ;STORE ARG 2 + LD A,2 + LD (ARGCNT),A ;TWO ARGS + LD A,(OPCODE) ;RESTORE OPCODE +OP2EX: AND 1FH ;(NOT 0E0H) TURN OFF MODE BITS + CP OP2M ;LEGAL 2-OP? + JP NC,BADOP ; NO. + LD HL,OP2T ; YES. HL ^ 2-OP TABLE + JP OPDSPH ;DISPATCH IT +; +;************************************* +;* OPCODE ARGUMENT FETCH SUBROUTINES * +;************************************* +; +; ----------------------- +; FETCH A SHORT IMMEDIATE +; ----------------------- +GETSHT: PUSH AF ;SAVE OPCODE + CALL NEXTPC ;GET NEXT ZBYTE + LD L,A ;MAKING IT THE LSB OF ARGUMENT + LD H,0 ;MSB IS 0 + POP AF ;RESTORE OPCODE + RET +; ---------------------- +; FETCH A LONG IMMEDIATE +; ---------------------- +GETLNG: PUSH AF ;SAVE OPCODE + CALL NEXTPC ;GET NEXT ZBYTE + LD H,A ;MAKING IT THE MSB OF ARGUMENT + PUSH HL ;SAVE IT ON THE STACK + CALL NEXTPC ;GET NEXT ZBYTE + POP HL ;RESTORE MSB OF ARGUMENT + LD L,A ;AND FILL IN LSB OF ARGUMENT + POP AF ;RESTORE OPCODE + RET +; ---------------- +; FETCH A VARIABLE +; ---------------- +GETVAR: PUSH AF ;GET VAR, FIRST FIND TYPE + CALL NEXTPC + OR A + JP Z,GETVRS ;FROM STACK +GETVR1: CP 16 + JP NC,GETVRG ;GLOBAL +GETVRL: DEC A ;LOCAL + ADD A,A + LD E,A + LD D,0 + LD HL,LOCALS +GETVL1: ADD HL,DE ;POINTER TO VARIABLE + LD D,(HL) + INC HL + LD E,(HL) + EX DE,HL ;RETURN VALUE IN HL + POP AF + RET +; +GETVRG: SUB 16 + LD E,A ;GET GLOBAL + LD D,0 + LD HL,(GLOBAL) + ADD HL,DE ;PRE ADD SO IT GETS DONE TWICE + JP GETVL1 +; +GETVRS: CALL POPSTK ;VAR FROM STACK + POP AF + RET +; +;********************* +;* MISC. SUBROUTINES * +;********************* +RET0: XOR A ;RETURN 0 +PUTBYT: LD L,A + LD H,0 +PUTVAL: CALL PUTVLC ;STORE VALUE + JP MLOOP +; +PUTVLC: PUSH HL ;SAVE VALUE + CALL NEXTPC ;GET TYPE + POP HL +PUTVR1: OR A + JP Z,PSHSTK ;SAVE ON STACK AND RETURN + EX DE,HL ;VALUE IN DE + CP 16 + JP NC,PUTVLG ;GLOBAL +PUTVLL: DEC A ;LOCAL + ADD A,A + LD C,A + LD B,0 + LD HL,LOCALS +PUTVL1: ADD HL,BC ;COMPUTE ADDRESS + LD (HL),D + INC HL + LD (HL),E + RET +; +PUTVLG: SUB 16 + LD C,A ;STORE GLOBAL + LD B,0 + LD HL,(GLOBAL) ;GLOBAL POINTER + ADD HL,BC ;PRE ADD + JP PUTVL1 +; +;********************* +;* DATA MANIPULATION * +;********************* +; +; ----------------- +; RECALL A VARIABLE +; ----------------- +VARGET: PUSH AF ;SAVE OPCODE + OR A ;IF NON-ZERO + JP NZ,GETVR1 ; THEN GET A VARIABLE FROM LOCAL OR GLOBAL TABLE +; ELSE TAKE VAR OFF STACK +VARGTS: POP AF ;RESTORE OPCODE + CALL POPSTK ;POP A WORD FROM ZSTACK + JP PSHSTK ;PUT IT BACK AND RETURN THE VALUE IN HL +; ---------------- +; STORE A VARIABLE +; ---------------- +VARPUT: OR A ;IF NON-ZERO + JP NZ,PUTVR1 ; THEN PUT A VARIABLE IN LOCAL OR GLOBAL TABLE +; ELSE REPLACE A WORD ON Z-STACK +VARPTS: PUSH HL ;SAVE NEW VALUE + CALL POPSTK ;POP OLD WORD OFF Z-STACK + POP HL ;RESTORE NEW VALUE + JP PSHSTK ;AND PUSH IT ON TOP OF ZSTACK +; +;************************ +;* PREDICATE PROCESSING * +;************************ +; +; --------------- +; PREDICATE FAILS +; --------------- +PREDF: CALL NEXTPC ;FETCH NEXT BYTE OF ZCODE + OR A + JP P,PREDB ;BRANCH IF < 128 +PREDNB: AND 40H ;CHECK FOR MULTI BYTE HACK + CALL Z,NEXTPC ;GET NEXT BYTE IF SO + JP MLOOP ;CONTINUE IN SEQUENCE +; ------------------ +; PREDICATE SUCCEEDS +; ------------------ +PREDS: CALL NEXTPC ;FETCH NEXT BYTE OF ZCODE + OR A ;IF BIT 7 IS NOT SET + JP P,PREDNB ;BRANCH ON PREDICATE FAILURE +; ELSE FALL THROUGH TO PREDB +; ---------------- +; PERFORM A BRANCH +; ---------------- +PREDB: LD B,A ;SAVE OPCODE + AND 40H ;LONG BRANCH? + JP Z,PREDLB ; YES. (BIT 6 WAS OFF) +; NO. SHORT BRANCH + LD A,B ;RESTORE OPCODE + AND 3FH ;FORM SHORT OFFSET + LD C,A ;USE AS LSB OF BRANCH OFFSET + LD B,0 ;ZERO MSB OF OFFSET + JP PREDB1 ;SIMULATE LONG BRANCH TO A CLOSE PLACE +; +; HANDLE A LONG BRANCH +PREDLB: LD A,B ;RESTORE OPCODE + AND 3FH ;FORM MSB OF OFFSET + LD B,A ;B <= MSB OF OFFSET + PUSH BC + CALL NEXTPC ;GET SECOND BYTE + POP BC + LD C,A ;C <= LSB OF OFFSET + LD A,B ;A <= MSB OF OFFSET + AND 20H ;CHECK SIGN OF 14 BIT VALUE + JP Z,PREDB1 ;POSITIVE + LD A,B ;ELSE EXTEND THE SIGN (A <= MSB) + OR 0C0H ;AND MAKE THE FULL WORD NEG + LD B,A ;SAVE THE RESULT IN B +; +; BRANCH TO THE Z-ADDRESS AT $(ZPC) + OFFSET (IN BC) +; (ZPC RELATIVE ADDRESSING) +PREDB1: LD A,B + OR C ;IS OFFSET=0? + JP Z,RFALSE ; YES. DO AN RFALSE + DEC BC + LD A,B + OR C ;WAS OFFSET=1 + JP Z,RTRUE ; YES. DO AN RTRUE +PREDB3: DEC BC ;2 NOW SUBTRACTED FROM JUMP ADDRESS + LD H,B ;HL <= JUMP ADDRESS + LD L,C + LD (ZPCOFF),HL ;ZPCOFF <= JUMP ADDRESS + LD HL,(ZPCL) ;HL <= LOW ORDER 9 BITS OF ZIP PROGRAM COUNTER + LD E,C ;E <= LSB OF JUMP ADDRESS + LD A,B ;A <= MSB OF JUMP ADDRESS + AND 1 + LD D,A ;ZPCL ADDER + LD A,B ;ARITHMETICALLY SHIFT B RIGHT 1 + RLCA ;FIRST SET CARRY + LD A,B + RRA + LD B,A ;CUTE + ADD HL,DE + LD A,H + AND 2 + JP Z,PREDB2 ;NO OVERFLOW + DEC H + DEC H ;OVERFLOW + INC B +PREDB2: LD (ZPCL),HL ;STORE LOW BYTES + LD HL,ZPCH ;MODIFY UPPER + LD A,B + OR A + JP Z,PREDB4 ;NO CHANGE IN PACE, DO FASTER JUMP + ADD A,(HL) + LD (HL),A + XOR A + LD (ZPCFLG),A ;CHANGED PAGES + JP MLOOP ;FINISHED +; +PREDB4: LD HL,(ZPCPNT) + EX DE,HL + LD HL,(ZPCOFF) + ADD HL,DE ;CALCULATE NEW PC POINTER + LD (ZPCPNT),HL + JP MLOOP +; +; ********************************************************************** +; * * +; * OPCODE PROCESSING SECTION * +; * * +; ********************************************************************** +; +; **************************** +; * DISPATCH TABLES * +; **************************** +; +; ----- +; 0-OPS +; ----- +OP0T: DW RTRUE ;0 + DW RFALSE ;1 + DW PRINTI ;2 + DW PRINTR ;3 + DW ZNOP ;4 + DW ZSAVE ;5 + DW ZRSTOR ;6 + DW ZRSTAR ;7 + DW RSTACK ;8 + DW FSTACK ;9 + DW ZQUIT ;10 + DW CRLF ;11 + DW USL ;12 + DW VERIFY ;13 +OP0M EQU ($-OP0T)/2 ;NUMBER OF 0-OPS +; +; ----- +; 1-OPS +; ----- +OP1T: DW ZEROQ ;0 + DW NEXTQ ;1 + DW FIRSTQ ;2 + DW LOC ;3 + DW PTSIZE ;4 + DW INC ;5 + DW DEC ;6 + DW PRINTB ;7 + DW BADOP ;8 (UNDEFINED) + DW REMOVE ;9 + DW PRINTD ;10 + DW RETURN ;11 + DW JUMP ;12 + DW PRINT ;13 + DW VALUE ;14 + DW BCOM ;15 +OP1M EQU ($-OP1T)/2 ;NUMBER OF 1-OPS +; +; ----- +; 2-OPS +; ----- +OP2T: DW BADOP + DW EQUALQ + DW LESSQ + DW GRTRQ + DW DLESSQ + DW IGRTRQ + DW INQ + DW BTST + DW BOR + DW BAND + DW FSETQ + DW FSET + DW FCLEAR + DW ZSET + DW MOVE + DW GET + DW GETB + DW GETP + DW GETPT + DW NEXTP + DW ZADD + DW ZSUB + DW MUL + DW DIV + DW ZMOD +OP2M EQU ($-OP2T)/2 +; +; ----- +; X-OPS +; ----- +OPEXTT: DW ZCALL + DW PUT + DW PUTB + DW PUTP + DW ZREAD + DW PRINTC + DW PRINTN + DW RANDOM + DW ZPUSH + DW ZPOP +OPEXTM EQU ($-OPEXTT)/2 +; ********************************************************************** +; * * +; * ZCODE EXECUTION ROUTINES * +; * * +; ********************************************************************** +; +; ******************* +; * 0-OPS * +; ******************* +; +; +; ---------- +; RTRUE [0] +; ---------- +; SIMULATE A RETURN 1 +RTRUE: LD HL,1 +RTRUE1: LD (ARG1),HL + JP RETURN +; +; ----------- +; RFALSE [1] +; ----------- +; SIMULATE A RETURN 0 +RFALSE: LD HL,0 + JP RTRUE1 +; +; ----------- +; PRINTI [2] +; ----------- +; PRINT THE Z-STRING IMMEDIATELY FOLLOWING THE OPCODE +PRINTI: CALL PRNTI1 + JP MLOOP +; +PRNTI1: LD HL,(ZPCL) + LD (MPCL),HL ;SET UP MPC TO EQUAL ZPC + LD A,(ZPCH) + LD (MPCH),A + XOR A + LD (MPCFLG),A ;ZERO MPC FLAG + CALL PZSTR ;PRINT THE STRING + LD HL,(MPCL) ;NOW CHANGE BACK ZPC TO END OF STRING + LD (ZPCL),HL + LD A,(MPCH) + LD (ZPCH),A + LD A,(MPCFLG) + LD (ZPCFLG),A ;UPDATE FLAG + LD HL,(MPCPNT) + LD (ZPCPNT),HL ;AND PAGE POINTER + RET +; +; ----------- +; PRINTR [3] +; ----------- +; EXECUTE A PRINTI, FOLLOWED BY A CRLF, AND A RTRUE +PRINTR: CALL PRNTI1 + CALL PCRLF + JP RTRUE +; +; --------- +; ZNOP [4] +; --------- +; EXECUTE A NOP +ZNOP: JP MLOOP +; +; ---------- +; ZSAVE [5] +; ---------- +; SAVE GAME +ZSAVE: JP SAVE ;MACHINE DEPENDENT +; +; ----------- +; ZRSTOR [6] +; ----------- +; RESTORE SAVED GAME +ZRSTOR: JP RESTOR ;MACHINE DEPENDENT +; +; ----------- +; ZRSTAR [7] +; ----------- +; RESTART GAME +ZRSTAR: JP RESTAR ;MACHINE DEPENDENT +; +; ----------- +; RSTACK [8] +; ----------- +; EXECUTE A RETURN WITH CALL VALUE ON TOP OF THE STACK +RSTACK: CALL POPSTK + LD (ARG1),HL + JP RETURN +; +; ----------- +; FSTACK [9] +; ----------- +FSTACK: CALL POPSTK + JP MLOOP +; +; ----------- +; ZQUIT [10] +; ----------- +ZQUIT: JP QUIT ;MACHINE DEPENDENT +; +; ---------- +; CRLF [11] +; ---------- +; PRINT CARRIAGE RETURN/LINE FEED +CRLF: CALL PCRLF + JP MLOOP +; +; --------- +; USL [12] +; --------- +; UPDATE STATUS LINE +USL: CALL WHOLIN + JP MLOOP +; +; ------------ +; VERIFY [13] +; ------------ +; VERIFY THE GAME CODE +VERIFY: LD A,1 ;SELF CHECK + LD (VERF),A ;IN VERIFY MODE, ALWAYS GET NEW PAGE + LD HL,VRS + CALL MSGOUT ;OUTPUT LAST UPDATE + LD HL,VRLINE + CALL MSGOUT ;OUTPUT VERSION + LD HL,(ZCODEP) ;^ TOP OF ZCODE + LD DE,ZCKLEN + ADD HL,DE + LD D,(HL) + INC HL + LD E,(HL) + LD HL,-32 + ADD HL,DE + EX DE,HL ;DE HAVE COUNT + LD BC,0 ;SUM IN BC + LD HL,32*2 + CALL SETWRD +VERIFL: PUSH BC + PUSH DE + CALL GETWRD ;GUARENTEED TO GET FRESH WORD + POP DE + POP BC + LD A,H + LD H,0 + ADD HL,BC + CALL HLOFF + LD B,H + LD C,L ;TOTAL IN BC + DEC DE + LD A,D + OR E + JP NZ,VERIFL ;SUM ALL BYTES + LD DE,ZCKSUM + LD HL,(ZCODEP) + ADD HL,DE + LD D,(HL) + INC HL + LD E,(HL) ;GET CHECKSUM + LD H,B + LD L,C + XOR A + LD (VERF),A + CALL HLGEDE ;COMPARE CALCULATED WITH ACTUAL + JP Z,PREDS + JP PREDF ;FAIL IF DIFFERENT +; +; ******************* +; * 1-OPS * +; ******************* +; +; ---------- +; ZERO? [0] +; ---------- +; IS ARG1 EQUAL TO ZERO? [PRED] +ZEROQ: LD HL,(ARG1) + LD A,H + OR L + JP Z,PREDS + JP PREDF +; +; ---------- +; NEXT? [1] +; ---------- +; RETURN THE NEXT POINTER IN OBJRCT "ARG1"; FAIL IF +; NONE LEFT, AND RETURN ZERO [VALUE][PRED] +NEXTQ: LD A,(ARG1) + CALL OBJLOC + LD DE,5 + JP FRSTQ1 ;SAME AS FIRST? +; +; ----------- +; FIRST? [2] +; ----------- +; RETURN THE FIRST POINTER IN OBJECT "ARG1"; FAIL IF +; NONE, AND RETURN ZERO [VALUE][PRED] +; +FIRSTQ: LD A,(ARG1) + CALL OBJLOC + LD DE,6 +FRSTQ1: ADD HL,DE + LD A,(HL) + PUSH AF ;SAVE VALUE + LD L,A + LD H,0 + CALL PUTVLC ;STORE VALUE + POP AF + OR A + JP NZ,PREDS ;FOUND FIRST + JP PREDF ;FIRST NOT FOUND +; +; -------- +; LOC [3] +; -------- +; RETURN THE OBJECT CONTAINING OBJECT "ARG1"; ZERO IF NONE [VALUE] +LOC: LD A,(ARG1) + CALL OBJLOC + LD DE,4 + ADD HL,DE + LD L,(HL) + LD H,0 + JP PUTVAL +; +; ----------- +; PTSIZE [4] +; ----------- +; RETURN LENGTH OF PROP TABLE "ARG1" IN BYTES [VALUE] +PTSIZE: LD HL,(ARG1) + EX DE,HL + LD HL,(ZCODEP) + ADD HL,DE ;POINTER TO PROP ENTRY + DEC HL + CALL PROPL + INC A + JP PUTBYT +; +; -------- +; INC [5] +; -------- +; INCREMENT ARG1 [VALUE] +INC: CALL INC1 + JP MLOOP +; +; -------- +; DEC [6] +; -------- +; DECREMENT ARG1 [VALUE] +DEC: CALL DEC1 + JP MLOOP +; +INC1: LD A,(ARG1) + CALL VARGET + INC HL +INC2: PUSH HL + CALL VARPUT + POP HL + RET +; +DEC1: LD A,(ARG1) + CALL VARGET + DEC HL + JP INC2 +; +; ----------- +; PRINTB [7] +; ----------- +; PRINT THE STRING POINTED TO BY BYTE POINTER ARG1 +PRINTB: LD HL,(ARG1) +PRINT2: CALL SETWRD + JP PRINT1 +; +; ---------- +; BADOP [8] +; ---------- +BADOP: JP MLOOP +; +; ----------- +; REMOVE [9] +; ----------- +; MOVE OBJECT [ARG1] TO PSEUDO-OBJECT #0 +REMOVE: CALL REMOVC + JP MLOOP +; +REMOVC: LD A,(ARG1) + LD B,A ;SAVE IT + CALL OBJLOC + EX DE,HL ;SAVE IN DE + LD HL,4 + ADD HL,DE + LD A,(HL) + OR A + RET Z ;NO OBJECT + PUSH DE ;SAVE VALUE + CALL OBJLOC ;PARENT OBJECT + LD DE,6 + EX DE,HL ;LP IN D + ADD HL,DE + LD C,(HL) ;SIBL + LD A,B + CP C + JP NZ,REMVC1 ;NOT SAME + POP HL + PUSH HL ;L1 + LD BC,5 + ADD HL,BC + LD A,(HL) + LD HL,6 ;PARENT'S FIRST SLOT GETS LOC SLOT + ADD HL,DE + LD (HL),A + JP REMVC2 + +REMVC1: LD A,C ;GET SIBL + CALL OBJLOC + LD DE,5 + ADD HL,DE + LD D,H + LD E,L ;SAVE LS+5 + LD C,(HL) ;NEW SIBL + LD A,B + CP C + JP NZ,REMVC1 ;NOT END OF CHAIN + LD BC,5 + POP HL + PUSH HL + ADD HL,BC ;OLD NEXT + LD A,(HL) + LD (DE),A +REMVC2: POP HL + LD DE,4 + ADD HL,DE + LD (HL),0 + INC HL + LD (HL),0 + RET +; ------------ +; PRINTD [10] +; ------------ +; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] +PRINTD: LD A,(ARG1) + CALL PRNTDC + JP MLOOP +; +PRNTDC: CALL OBJLOC + LD DE,7 + ADD HL,DE + LD D,(HL) + INC HL + LD E,(HL) + EX DE,HL + INC HL + CALL SETWRD + JP PZSTR +; +; ------------ +; RETURN [11] +; ------------ +; RETURN FROM A CALL WITH VALUE ARG1 +RETURN: LD HL,(OZSTKP) ;RESET STACK FROM CALL + LD (ZSTAKP),HL + LD A,(OZSTKC) + LD (ZSTAKC),A + CALL POPSTK ;RESET Z-STACK + LD A,L + LD (ZPCH),A ;SAVE UPPER PC + LD B,H ;H HAS NUMBER OF LOCALS + LD A,H + ADD A,A ;WORD + JP Z,RET2 ;NO LOCALS + LD HL,LOCALS-2 + CALL HLOFF ;POSITION HL TO RESTORE LOCALS +RET1: EX DE,HL + CALL POPSTK ;GET THE LOCAL, REVERSE ORDER FIRST + EX DE,HL + LD (HL),D + INC HL + LD (HL),E + DEC HL ;NOW BACK UP ONE ELEMENT + DEC HL + DEC HL + DEC B + JP NZ,RET1 ;LOOP +RET2: CALL POPSTK + LD (ZPCL),HL ;REST OF PC + CALL POPSTK + LD (OZSTKP),HL + CALL POPSTK + LD A,L + LD (OZSTKC),A ;RESTORE OLD VALUES + XOR A + LD (ZPCFLG),A ;PC CHANGED + LD HL,(ARG1) ;ARGUMENT TO BE RETURNED + JP PUTVAL ;STORE AND RETURN +; +; ---------- +; JUMP [12] +; ---------- +; BRANCH TO Z-LOCATION POINTED TO BY 16-BIT 2'S COMPLIMENT ARG1 +JUMP: LD HL,(ARG1) ;RELATIVE JUMP + LD B,H + LD C,L + DEC BC + JP PREDB3 ;TREAT AS A SUCCESSFUL JUMP +; +; ----------- +; PRINT [13] +; ----------- +; PRINT THE Z-STRING POINTED TO BY THE WORD-POINTER ARG1 +PRINT: LD HL,(ARG1) ;TELL SETSTR WHERE THE STRING + CALL SETSTR ;RESIDES AND +PRINT1: CALL PZSTR ;PRINT THE STRING + JP MLOOP +; +; ----------- +; VALUE [14] +; ----------- +; RETURN VALUE OF ARG1 [VALUE] +VALUE: LD A,(ARG1) + CALL VARGET + JP PUTVAL +; +; ---------- +; BCOM [15] +; ---------- +; COMPLIMENT ARG1 [VALUE] +BCOM: LD HL,(ARG1) + LD A,H + CPL + LD H,A + LD A,L + CPL + LD L,A + JP PUTVAL +; +; ******************* +; * 2-OPS * +; ******************* +; +; ---------- +; LESS? [0] +; ---------- +; IS ARG1 LESS THAN ARG2? [PRED] +LESSQ: CALL GETARG + EX DE,HL + CALL SHLGED + JP NC,PREDS + JP PREDF +; +; ---------- +; GRTR? [1] +; ---------- +; IS ARG1 GREATER THAN ARG2? [PRED] +GRTRQ: CALL GETARG + CALL SHLGED + JP NC,PREDS + JP PREDF +; +; ----------- +; DLESS? [2] +; ----------- +; DECREMENT ARG1: SUCCEED IF ARG1 (-1) IS LESS THAN ARG2 [PRED] +DLESSQ: CALL DEC1 + EX DE,HL + LD HL,(ARG2) + EX DE,HL + JP IGRTQ1 +; +; ----------- +; IGRTR? [3] +; ----------- +; INCREMENT ARG1: SUCCEED IF ARG1 (+1) IS GREATER THAN ARG2 [PRED] +IGRTRQ: CALL INC1 + EX DE,HL + LD HL,(ARG2) +IGRTQ1: CALL SHLGED + JP NC,PREDS + JP PREDF +; +; ---------- +; IN? [4] +; ---------- +; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2] [PRED] +INQ: LD A,(ARG1) + CALL OBJLOC + LD DE,4 + ADD HL,DE + LD A,(ARG2) + CP (HL) + JP Z,PREDS ;SUCCESS IF OBJ 2 IN 1 + JP PREDF +; +; --------- +; BTST [5] +; --------- +; IS EVERY "ON" BIT IN ARG1 ALSO "ON" IN ARG2 [PRED] +BTST: CALL GETARG + LD A,H + AND D + LD D,A + LD A,L + AND E + LD E,A + CALL HLGEDE + JP Z,PREDS + JP PREDF +; +; -------- +; BOR [6] +; -------- +; RETURN BITWISE OR OF ARG1 AND ARG2 [VALUE] +BOR: CALL GETARG + LD A,D + OR H + LD H,A + LD A,E + OR L + LD L,A + JP PUTVAL +; +; --------- +; BAND [7] +; --------- +; RETURN BITWISE AND OF ARG1 AND ARG2 [VALUE] +BAND: CALL GETARG + LD A,H + AND D + LD H,A + LD A,L + AND E + LD L,A + JP PUTVAL +; +; ---------- +; FSET? [8] +; ---------- +; IS FLAG "ARG2" SET IN OBJECT "ARG1"? [PRED] +FSETQ: CALL FLAGSU ;GET BIT + LD A,D + AND B + LD D,A + LD A,E + AND C + OR D ;CHECK FOR ON + JP NZ,PREDS ;BIT ON + JP PREDF ;BIT OFF +; +; --------- +; FSET [9] +; --------- +; SET FLAG "ARG2" IN OBJECT "ARG1" +FSET: CALL FLAGSU + LD A,D + OR B + LD (HL),A + INC HL + LD A,E + OR C + LD (HL),A + JP MLOOP +; +; ------------ +; FCLEAR [10] +; ------------ +; CLEAR FLAG "ARG2" IN OBJECT "ARG1" +FCLEAR: CALL FLAGSU + LD A,B + CPL + AND D + LD (HL),A + INC HL + LD A,C + CPL + AND E + LD (HL),A + JP MLOOP +; +; --------- +; SET [11] +; --------- +; SET VARIABLE "ARG1" EQUAL TO VALUE "ARG2" +ZSET: LD A,(ARG1) + LD HL,(ARG2) +VARPTR: CALL VARPUT + JP MLOOP +; +; ---------- +; MOVE [12] +; ---------- +; PUT OBJECT "ARG1" INTO OBJECT "ARG2" +MOVE: CALL REMOVC ;REMOVE OBJECT FIRST + LD A,(ARG1) + CALL OBJLOC + PUSH HL ;SAVE LOC OF FIRST ARG + LD DE,4 + ADD HL,DE ;LOC SLOT + LD A,(ARG2) + LD (HL),A + CALL OBJLOC + LD DE,6 + ADD HL,DE ;FIRST SLOT + LD B,(HL) + LD A,(ARG1) + LD (HL),A + POP HL + LD A,B + OR A + JP Z,MLOOP + LD DE,5 + ADD HL,DE + LD (HL),A ;NEXT SLOT + JP MLOOP +; +; --------- +; GET [13] +; --------- +; RETURN VALUE OF ITEM "ARG2" IN WORD-TABLE AT "ARG1" +GET: LD HL,(ARG2) + ADD HL,HL ;ITEM NUMBER*2 + EX DE,HL + LD HL,(ARG1) + ADD HL,DE ;POINTER TO ITEM + CALL SETWRD + CALL GETWRD ;GET VALUE + JP PUTVAL +; +; ---------- +; GETB [14] +; ---------- +; RETURN VALUE OF ITEM "ARG2" IN BYTE-TABLE AT "ARG1" [VALUE] +GETB: LD HL,(ARG2) + EX DE,HL + LD HL,(ARG1) + ADD HL,DE + CALL SETWRD + CALL GETBYT + LD L,A + LD H,0 + JP PUTVAL +; +; ---------- +; GETP [15] +; ---------- +; RETURN PROP "ARG2" OF OBJECT "ARG1"; IF SPECIFIED PROP DOES +; NOT EXIST, RETUURN PROP'TH ELEMENT OF DEFAULT OBJECT [VALUE] +GETP: CALL PROPB ;GET POINTER TO PROPS IN PROP TABLE +GETP1: CALL PROPN + LD B,A + LD A,(ARG2) + CP B + JP Z,GETP2 ;FOUND PROP + JP NC,GETP3 ;GET PROP FROM DEFAULT TABLE + CALL PROPNX ;TRY AGAIN WITH NEXT PROP + JP GETP1 + +GETP3: LD HL,(ZCODEP) + LD DE,ZOBJEC + ADD HL,DE + LD D,(HL) + INC HL + LD E,(HL) + LD HL,(ZCODEP) + ADD HL,DE ;BEG OF OBJECT TABLE + LD A,(ARG2) + ADD A,A + CALL HLOFF + DEC HL + LD E,(HL) + DEC HL + LD D,(HL) + EX DE,HL + JP PUTVAL ;RETURN DEFAULT VALUE + +GETP2: CALL PROPL ;GET LENGTH + INC HL + DEC A + JP M,GETP2A ;1 BYTE + CALL NZ,ZER ;BAD PROP LENGTH + LD D,(HL) + INC HL + LD E,(HL) + EX DE,HL + JP PUTVAL ;RETURN TWO BYTE PROP + +GETP2A: LD L,(HL) + LD H,0 + JP PUTVAL + +GETPT: CALL PROPB +GETPT1: CALL PROPN + LD B,A + LD A,(ARG2) + CP B + JP Z,GETPT2 ;FOUND PROP + JP NC,RET0 + CALL PROPNX + JP GETPT1 + +GETPT2: INC HL + EX DE,HL + LD HL,(ZCODEP) ;SUBRACT OFF RELATIVE POINTER + LD A,E + SUB L + LD L,A + LD A,D + SBC A,H + LD H,A + JP PUTVAL + +NEXTP: CALL PROPB ;POINT TO PROP VALUE + LD A,(ARG2) + OR A + JP Z,NEXTP2 ;PROP0 +NEXTP1: CALL PROPN + LD B,A + LD A,(ARG2) + CP B + JP Z,NEXTP3 ;FOUND PROP + JP NC,RET0 ;RETURN 0 + CALL PROPNX + JP NEXTP1 ;LOOP + +NEXTP2: CALL PROPN + JP PUTBYT + +NEXTP3: CALL PROPNX + JP NEXTP2 ;PROPN OF NEXT + +ZADD: CALL GETARG + ADD HL,DE + JP PUTVAL + +ZSUB: CALL GETARG + LD A,E + SUB L + LD L,A + LD A,D + SBC A,H + LD H,A + JP PUTVAL + +MUL: CALL GETARG + EX DE,HL + CALL SIGNC ;CHECK SIGN + PUSH HL + LD HL,2 + CALL HLGEDE + JP Z,MUL2 + LD HL,4 + CALL HLGEDE + JP Z,MUL4 + POP HL + CALL MULT ;DO THE MULTIPLY +MUL1: CALL SIGNS ;SET THE SIGN + JP PUTVAL ;THEN STORE RESULT + +MUL4: POP HL + ADD HL,HL + PUSH HL +MUL2: POP HL + ADD HL,HL + JP MUL1 + +DIV: CALL GETARG + EX DE,HL + CALL SIGNC ;CHECK SIGNS + PUSH HL + LD HL,2 + CALL HLGEDE + JP Z,DIV2 ;DIVIDE BY 2 + LD HL,4 + CALL HLGEDE + JP Z,DIV4 ;DIVIDE BY 4 + POP HL + CALL DIVIDE ;DO THE DIVIDE + JP MUL1 ;SET SIGN AND RETURN + +DIV2: POP HL +DIV2B: CALL DIV2A + JP MUL1 + +DIV4: POP HL + CALL DIV2A + JP DIV2B + +DIV2A: OR A ;CLEAR CARRY + LD A,H + RRA + LD H,A + LD A,L + RRA + LD L,A + RET + +ZMOD: CALL GETARG + EX DE,HL + CALL SIGNC ;MAKE THEM POSITIVE + CALL DIVIDE ;DO THE DIVIDE + EX DE,HL ;GET THE REMAINDER + JP PUTVAL +; +; ******************* +; * X-OPS * +; ******************* +; +EQUALQ: LD HL,(ARG1) + EX DE,HL + LD A,(ARGCNT) + LD B,A + DEC B + CALL Z,ZER + LD HL,(ARG2) + CALL EQUAQ1 + LD HL,(ARG3) + CALL EQUAQ1 + LD HL,(ARG4) + CALL EQUAQ1 + CALL ZER + +EQUAQ1: CALL HLGEDE ;DO COMPARISON + POP HL ;RESTORE RETURN ADDRESS + JP Z,PREDS ;DON'T BOTHER RETURNING + DEC B ;ARG COUNT + JP Z,PREDF ;OUT OF ARGS, FAIL + JP (HL) ;ELSE RETURN + +ZCALL: LD HL,(ARG1) + LD A,H + OR L + JP Z,PUTVAL + LD HL,(OZSTKC) + CALL PSHSTK + LD HL,(OZSTKP) + CALL PSHSTK + LD HL,(ZPCL) + CALL PSHSTK ;SAVE OLD PC LOWER + LD HL,(ZPCH) ;SAVE HIGH IN L + PUSH HL + XOR A + LD (ZPCFLG),A ;PC HAS CHANGED + LD H,A + LD A,(ARG1) + LD L,A + ADD HL,HL ;NEW ZPCL + LD (ZPCL),HL + LD A,(ARG1+1) + LD (ZPCH),A ;NEW ZPCH + CALL NEXTPC ;GET NUMBER OF LOCALS + POP HL + LD B,A ;B HAS NUMBER OF LOCALS + LD H,A + PUSH HL ;SAVE VALUE + LD HL,LOCALS ;STORE OLD LOCALS + OR A + JP Z,ZCALL2 ;NO LOCALS +ZCALL1: PUSH BC + LD D,(HL) + INC HL + LD E,(HL) + EX DE,HL + CALL PSHSTK + DEC DE + PUSH DE + CALL NEXTPC ;GET NEW DEFAULT VALUE FOR LOCAL + LD D,A + PUSH DE + CALL NEXTPC ;WORD VALUE + POP DE + LD E,A + POP HL ;POINTER TO STORE NEW LOCAL + LD (HL),D + INC HL + LD (HL),E + INC HL + POP BC + DEC B + JP NZ,ZCALL1 ;LOOP THROUGH ALL LOCALS +ZCALL2: LD A,(ARGCNT) ;PASS ARGS + LD B,A + DEC B + JP Z,ZCALL4 ;NO ARGS TO PASS + LD HL,ARG2 ;POINTER TO FIRST ARG + LD DE,LOCALS +ZCALL3: LD A,(HL) + INC HL + INC DE + LD (DE),A + DEC DE + LD A,(HL) + INC HL + LD (DE),A + INC DE + INC DE + DEC B + JP NZ,ZCALL3 +ZCALL4: POP HL ;GET BACK ZPCH AND NUMBER OF LOCALS + CALL PSHSTK + LD A,(ZSTAKC) + LD (OZSTKC),A + LD HL,(ZSTAKP) + LD (OZSTKP),HL ;FOR KNOWING WHERE TO RETURN + JP MLOOP + +PUT: LD HL,(ARG2) + ADD HL,HL + EX DE,HL + LD HL,(ARG1) + ADD HL,DE ;Z ADDRESS + EX DE,HL + LD HL,(ZCODEP) + ADD HL,DE ;REAL POINTER + EX DE,HL + LD HL,(ARG3) ;VALUE TO STORE + EX DE,HL + LD (HL),D + INC HL + LD (HL),E + JP MLOOP + +PUTB: LD HL,(ARG2) + EX DE,HL + LD HL,(ARG1) + ADD HL,DE + EX DE,HL + LD HL,(ZCODEP) + ADD HL,DE + LD A,(ARG3) + LD (HL),A ;STORE ONE BYTE IN RANDOM TABLE + JP MLOOP + +PUTP: CALL PROPB ;SET PROP +PUTP1: CALL PROPN ;GET PROP NUMBER + LD B,A + LD A,(ARG2) + CP B + JP Z,PUTP2 ;FOUND PROPERTY + CALL NC,ZER ;BAD PROP NUMBER + CALL PROPNX ;TRY NEXT + JP PUTP1 + +PUTP2: CALL PROPL ;GET LENGTH + INC HL + EX DE,HL + LD HL,(ARG3) + DEC A + JP M,PUTP2A ;STORE 1 BYTE + CALL NZ,ZER ;TOO LONG + EX DE,HL + LD (HL),D + INC HL + LD (HL),E + JP MLOOP ;RETURN + +PUTP2A: EX DE,HL + LD (HL),E + JP MLOOP ;SET AND RETURN + + +ZREAD: + CALL WHOLIN + CALL RND ;RANDOMIZE + LD HL,(ZCODEP) ;MAIN READ CODE + EX DE,HL ;GET REAL POINTERS TO TABLES + LD HL,(ARG1) + ADD HL,DE ;BUFFER TABLE + LD (ARG1),HL + LD HL,(ARG2) + ADD HL,DE ;RESULT TABLE + LD (ARG2),HL + CALL READBF ;READ THE BUFFER + LD B,A ;CHARACTER COUNT IN B + LD C,0 ;C HAS CHARACTERS IN WORD + LD HL,(ARG2) + INC HL + LD (HL),0 ;SET WORDS READ TO 0 + INC HL + LD (RTABP),HL ;INITIALIZE RESULT TABLE POINTER + LD HL,(ARG1) + INC HL ;HL HAS POINTER TO INPUT CHARACTERS +READL: PUSH HL + LD HL,(ARG2) + LD A,(HL) + INC HL + CP (HL) + POP HL + JP Z,MLOOP ;TOO MANY WORDS +;ERROR HERE IF DESIRED INSTEAD OF JZ + LD A,B + OR C + JP Z,MLOOP ;OUT OF CHARACTERS AND WORDS + LD A,C + CP 6 + CALL Z,FLUSHW ;FLUSH CHARS IN A WORD OVER 6 CHARACTERS + LD A,C + OR A + JP NZ,READL2 ;NOT FIRST CHARACTER IN WORD + PUSH HL + LD D,6 + LD HL,ZSTBUI ;INITIALIZE WORD BUFFER +RD0PL: LD (HL),0 + INC HL + DEC D + JP NZ,RD0PL + POP HL + LD A,(ARG1) + LD D,A + LD A,L + SUB D ;POSITION OF START OF WORD + PUSH HL + LD HL,(RTABP) + INC HL + INC HL + INC HL + LD (HL),A ;STORE IN RESULT TABLE + POP HL + LD A,(HL) + CALL SIBRKQ ;SELF INSERTING BREAK? + JP C,RSIBRK + LD A,(HL) + CALL RBRKQ ;NORMAL BREAK? + JP NC,READL2 ;NO + INC HL ;YES, FLUSH STRANDED BREAKS + DEC B + JP READL ;LOOP BACK + +READL2: LD A,B + OR A + JP Z,READL3 ;OUT OF CHARACTERS, SIMULATE WORD ENDING + LD A,(HL) + CALL RBRKQ ;WORD BREAK? + JP C,READL3 ;FOUND A BREAK + LD D,(HL) + PUSH HL + LD HL,ZSTBUI + LD A,C + CALL HLOFF + LD (HL),D ;STORE CHARACTER IN BUFFER + POP HL + DEC B ;ONE LESS CHARACTER + INC C ;ONE MORE CHARACTER IN WORD + INC HL ;POINT TO NEXT CHARACTER + JP READL + +RSIBRK: LD (ZSTBUI),A ;STORE SELF INSERTING BREAK + INC C ;1 CHAR + DEC B ;1 LESS CHAR + INC HL +READL3: LD A,C ;INSERT WORD IF ANY CHARACTERS IN WORD + OR A + JP Z,READL ;NO CHARACTERS IN WORD + PUSH HL + PUSH BC + LD HL,(RTABP) ;STORE PARAMS IN TABLE + INC HL + INC HL + LD (HL),C ;REAL LENGTH OF WORD + CALL CONZST ;CONVERT TO ZSTRING + CALL FINDW ;LOOK UP WORD IN VOCAB TABLE + LD HL,(RTABP) ;STORE RESULT + LD (HL),D + INC HL + LD (HL),E + INC HL + INC HL + INC HL + LD (RTABP),HL ;POINTER TO NEXT WORD + LD HL,(ARG2) + INC HL + INC (HL) ;ONE MORE WORD + POP BC + POP HL + LD C,0 ;ZERO CHARACTERS IN NEXT WORD + JP READL + +FLUSHW: LD A,B + OR A ;FLUSH CHARACTERS TILL BREAD OR END OF BUFFER + RET Z + LD A,(HL) + CALL RBRKQ + RET C ;FOUND A BREAK + INC HL + DEC B + INC C + JP FLUSHW + +RBRKQ: CALL SIBRKQ ;FIRST CHECK SELF INSERTING BREAKS + RET C ;YES + PUSH HL + LD HL,BRKTBL + LD D,NBRKS +RBRK1: CP (HL) + JP Z,FBRK ;MATCH + INC HL + DEC D + JP NZ,RBRK1 +RBRK2: POP HL ;NOT FOUND + OR A ;CLEAR CARRY + RET + +FBRK: POP HL + SCF + RET ;FOUND A BREAK, SET CARRY AND RETURN + +SIBRKQ: PUSH HL + CALL GETVOC + LD D,(HL) ;NUMBER OF SELF INSERTING BREAKS + DEC D + INC D + JP Z,RBRK2 ;FAIL + INC HL + JP RBRK1 + +GETVOC: LD HL,(ZCODEP) + LD DE,ZVOCAB + ADD HL,DE + LD D,(HL) + INC HL + LD E,(HL) + LD HL,(ZCODEP) + ADD HL,DE + RET + +BRKTBL: DB ' .,?' + DB 0DH,0AH,9H,0CH + DB 22H,22H + +NBRKS EQU $-BRKTBL + +FINDW: CALL GETVOC ;FIND WORD IN VOCAB TABLE, ASSUMES VOCAB IN MEMORY + LD A,(HL) + INC HL + CALL HLOFF ;SKIP OVER SELF INSERTING BREAKS + LD A,(HL) + ADD A,A + ADD A,A + ADD A,A + ADD A,A + LD C,A ;C HAS 16 TIMES VOCAB ENTRY SIZE + INC HL + LD D,(HL) + INC HL + LD E,(HL) + INC HL ;HL POINTS TO VOCAB TABLE + LD A,(ZSTBUO+1) ;GET FIRST CHARACTER + LD B,A ;PUT IT IN B + JP FWL2 ;WE CAN'T START AT THE BEGINNING + +FWL1A: OR D ;HERE ON 16 WORD BOUNDRY + JP Z,FWL3 ;END OF TABLE +FWL1: LD A,(HL) + CP B ;CHECK ONLY FIRST BYTE + JP NC,FWL3 ;FOUND PROPER AREA FOR FINE SEARCH +FWL2: LD A,L + ADD A,C + LD L,A + LD A,H + ADC A,0 + LD H,A ;POINTER TO NEXT BLOCK (HLOFF NOT USED FOR SPEED) + LD A,E + SUB 16 ;16 MORE WORDS + LD E,A + JP Z,FWL1A + JP NC,FWL1 + DEC D + JP P,FWL1 ;NOT OUT OF WORDS +FWL3: LD A,L ;NOW DO FINE CHECK + SUB C ;BACKUP 16 WORDS + LD L,A + LD A,H + SBC A,0 + LD H,A + LD A,E + ADD A,16 + LD E,A + LD A,D + ADC A,0 + LD D,A ;BACKUP COUNT + LD A,C + RRCA + RRCA + RRCA + RRCA + LD C,A ;REAL ENTRY SIZE +FWL4: + LD A,(ZSTBUO+1) + CP (HL) + JP C,FWFAIL + JP NZ,FWL4A ;CHECK ALL 4 BYTES + INC HL + LD A,(ZSTBUO) + CP (HL) + JP C,FWFAIL + JP NZ,FWL4B + INC HL + LD A,(ZSTBUO+3) + CP (HL) + JP C,FWFAIL + JP NZ,FWL4C + INC HL + LD A,(ZSTBUO+2) + CP (HL) + JP C,FWFAIL + JP Z,FWSUCC ;MATCH + DEC HL +FWL4C: DEC HL +FWL4B: DEC HL +FWL4A: LD A,C + CALL HLOFF + DEC DE + LD A,D + OR E + JP NZ,FWL4 ;NOT OUT OF WORDS YET +FWFAIL: LD DE,0 + RET + +FWSUCC: DEC HL + DEC HL + DEC HL + EX DE,HL + LD HL,(ZCODEP) + LD A,E + SUB L + LD E,A + LD A,D + SBC A,H + LD D,A + RET + +PRINTC: LD A,(ARG1) + LD C,A + CALL COUT + JP MLOOP + +PRINTN: LD HL,(ARG1) + CALL PRNTNC + JP MLOOP + +PRNTNC: LD A,H + OR A + CALL M,PRNTNG ;NEGATIVE NUMBER + LD B,0 ;DIGIT COUNT +PRNTN1: LD A,H + OR L + JP Z,PRNTN3 + LD DE,10 + CALL DIVIDE + PUSH DE + INC B + JP PRNTN1 + +PRNTN3: XOR A + ADD A,B + JP Z,PRNTN6 ;PRINT AT LEAST 0 +PRNTN4: POP DE + LD A,'0' + ADD A,E + LD C,A + CALL COUT + DEC B + JP NZ,PRNTN4 + RET + +PRNTN6: LD C,'0' + JP COUT + +PRNTNG: LD C,'-' ;PRINT - + CALL COUT + JP SIGNCN ;CHANGE SIGN + +RANDOM: LD HL,(ARG1) ;RANDOM GENERATOR + EX DE,HL + CALL RND ;GET THE BASE NUMBER + CALL DIVIDE + EX DE,HL ;GET REMAINDER + INC HL ;MAKE NOT EQUAL TO 0 + JP PUTVAL + +ZPUSH: LD HL,(ARG1) + CALL PSHSTK + JP MLOOP + +ZPOP: CALL POPSTK + LD A,(ARG1) + JP VARPTR +; +; ********************************************************************** +; * * +; * ZORK - RANDOM ROUTINES * +; * * +; ********************************************************************** +; +RND: PUSH BC + LD C,2 ;2 TIMES THROUGH LOOP +RND2: LD B,8 + LD HL,SHIFT + LD A,(HL) +RND1: RLCA + RLCA + RLCA + XOR (HL) + RLA + RLA + LD HL,SHIFT + LD A,(HL) + RLA + LD (HL),A + INC HL + LD A,(HL) + RLA + LD (HL),A + INC HL + LD A,(HL) + RLA + LD (HL),A + INC HL + LD A,(HL) + RLA + LD (HL),A + DEC B + JP NZ,RND1 + DEC C + JP NZ,RND2 + POP BC + LD HL,(SHIFT+2) ;GET THE NUMBER + RET + +MULT: PUSH BC ;DEHL <=DE*HL + LD BC,0 + LD A,16 ;LOOP COUNTER +MULT1: PUSH AF + LD A,E + AND 1 ;CHECK BIT FOR ADD + JP Z,MULT2 ;SKIP ADD PART IF 0 + PUSH HL ;SAVE MULTIPLIER + ADD HL,BC ;ADD PART + LD B,H + LD C,L + POP HL ;RESTORE H +MULT2: LD A,B ;32 BIT SHIFT REMEMBERING CARRY + RRA + LD B,A + LD A,C + RRA + LD C,A + LD A,D + RRA + LD D,A + LD A,E + RRA + LD E,A + POP AF ;GET BACK LOOP COUNT + DEC A + JP NZ,MULT1 + LD H,D ;PUT LOW ORDER ANSWER IN HL + LD L,E + LD D,B ;HIGH PART IN DE + LD E,C + POP BC + RET + +DIVIDE: PUSH BC ;HL<=HL/DE, REMAINDER IN DE + LD B,H + LD C,L + LD A,D ;NEGATE DIVISOR + CPL + LD D,A + LD A,E + CPL + LD E,A + INC DE ;FOR TWO'S COMPLEMENT + LD HL,0 ;INITIAL VALUE FOR REMAINDER + LD A,17 ;INIT LOOP COUNTER +DDIV0: PUSH HL ;SAVE REMAINDER + ADD HL,DE ;SUB DIVIS + JP NC,DDIV1 ;UNDERFLOW, RESTORE HL + EX (SP),HL +DDIV1: POP HL + PUSH AF ;SAVE LOOP COUNTER + LD A,C ;4 REG SHIFT LEFT + RLA ;WITH CARRY + LD C,A ;CY->C->B->L->H + LD A,B + RLA + LD B,A + LD A,L + RLA + LD L,A + LD A,H + RLA + LD H,A + POP AF ;RESTORE LOOP COUNTER + DEC A ;DECREMENT IT + JP NZ,DDIV0 ;KEEP LOOPING + +;CLEANUP, SHIFT REMAINDER RIGHT AND RETURN IN DE + OR A + LD A,H + RRA + LD D,A + LD A,L + RRA + LD E,A + LD H,B + LD L,C + POP BC + RET + +SIGNC: XOR A + LD (SIGNF),A ;SET SIGNF + CALL SIGNPC ;POS CHECK + EX DE,HL + CALL SIGNPC + EX DE,HL + RET + +SIGNS: LD A,(SIGNF) ;CHECK FOR SIGN + AND 1 ;EVEN OR ODD + RET Z ;EVEN NUMBER OF NEGATIVES, ANSWER OK +SIGNCN: XOR A ;CHANGE SIGN + SUB L + LD L,A + LD A,0 + SBC A,H + LD H,A ;INVERTED HL + RET + +SIGNPC: LD A,H + OR A + RET P ;POSITIVE + LD A,(SIGNF) + INC A + LD (SIGNF),A + JP SIGNCN ;CHANGE SIGN + +FLAGSU: LD A,(ARG1) ;SETUP FOR FLAG ROUTINES + CALL OBJLOC ;BC WILL HAVE BIT POSITION, DE FLAG VALUE + LD A,(ARG2) ;HL WILL GET OBJ POINTER + CP 16 + JP C,FLGSU1 ;NEXT WORD + SUB 16 ;SECOND SET OF FLAGS + INC HL + INC HL +FLGSU1: PUSH HL + LD B,A + LD A,15 + SUB B + LD HL,1 +FLGSU2: JP Z,FLGSU3 ;BIT IN POSITION + ADD HL,HL + DEC A + JP FLGSU2 + +FLGSU3: LD B,H + LD C,L + POP HL + LD D,(HL) + INC HL + LD E,(HL) + DEC HL + RET + +PROPB: LD A,(ARG1) ;BEG OF PROPERTY PART OF OBJECT + CALL OBJLOC + LD DE,7 + ADD HL,DE + LD D,(HL) + INC HL + LD E,(HL) + LD HL,(ZCODEP) + ADD HL,DE + LD A,(HL) ;LENGTH OF DESCRIPTION + ADD A,A ;*2 + INC A ;+1 + JP HLOFF ;INDEX AND RETURN + +PROPN: LD A,(HL) ;HL HAS REAL PROP POINTER + AND 1FH + RET + +PROPL: LD A,(HL) ;PROP LENGTH, HL HAS REAL PROP POINTER + RLCA + RLCA + RLCA + AND 7 + RET + +PROPNX: CALL PROPL + ADD A,2 + JP HLOFF ;NEXT PROP POINTER + +OBJLOC: PUSH DE ;GET OBJECT LOCATION, A HAS OBJECT NUMBER + LD L,A + LD H,0 + LD D,H + LD E,L + ADD HL,HL + ADD HL,HL + ADD HL,HL + ADD HL,DE + LD DE,53 + ADD HL,DE ;9*NUMBER + 53 + PUSH HL ;OBJECT OFFSET + LD HL,(ZCODEP) + LD DE,ZOBJEC + ADD HL,DE + LD D,(HL) + INC HL + LD E,(HL) + LD HL,(ZCODEP) + ADD HL,DE + POP DE + ADD HL,DE ;REAL ADDRESS + POP DE + RET + +GETARG: LD HL,(ARG1) + EX DE,HL + LD HL,(ARG2) ;GET BOTH ARGS + RET + +SHLGED: LD A,D + XOR H + JP P,HLGEDE ;BOTH OF SAME SIGN + LD A,H + CP D ;CARRY WILL BE SET IF D NEG AND THUS LESS THAN H + RET + +HLGEDE: LD A,D ;RETURN WITH CARRY SET IF HL>=DE + CP H + RET NZ + LD A,L + CP E + CCF + RET + +PSHSTK: PUSH DE + EX DE,HL ;PUSH STACK + LD HL,(ZSTAKP) ;STACK POINTER + DEC HL + LD (HL),E + DEC HL + LD (HL),D + LD (ZSTAKP),HL ;SAVE POINTER + LD HL,ZSTAKC ;COUNT + INC (HL) + LD A,(HL) + CP ZSTAKL + CALL Z,ZER + EX DE,HL + POP DE + RET +; --------- +; POP STACK +; --------- +; POP WORD OFF Z-STACK AND RETURN IT IN HL +POPSTK: PUSH DE ;SAVE DE + LD HL,(ZSTAKP) ;HL <= Z-STACK POINTER + LD D,(HL) ;GET MSB OF WORD + INC HL + LD E,(HL) ;GET LSB OF WORD + INC HL + LD (ZSTAKP),HL ;SAVE NEW Z-STACK POINTER + LD HL,ZSTAKC ;CHECK COUNT + DEC (HL) + CALL Z,ZER ;OVER POP ERROR + EX DE,HL ;VALUE IN HL + POP DE ;RESTORE DE + RET +; +; ********************************************************************** +; * * +; * ZORK - PAGING ROUTINES * +; * * +; ********************************************************************** +; +NEXTPC: LD A,(ZPCFLG) ;HAS PAGE MOVED? + OR A + JP Z,NXTPC1 ;PAGE HAS MOVED + LD HL,(ZPCPNT) + LD B,(HL) ;GET VALUE IN B + INC HL + LD (ZPCPNT),HL ;STORE BACK POINTER + LD HL,(ZPCL) + INC L + LD (ZPCL),HL ;ASSUME OK AT FIRST + LD A,B + RET NZ ;OK IF L NOT ZERO + LD A,H ;CROSSED 256 BYTE BOUNDRY + INC H + LD (ZPCL),HL ;AGAIN ASSUME NOT PASSED 256 BOUNTRY + OR A + LD A,B + RET Z ;DID NOT CROSS 512 BOUNDRY + XOR A + LD (ZPCL+1),A ;0 ZPCL + LD (ZPCFLG),A ;BAD DATA IN PCPNT, WILL HAVE TO FETCH NEW BLOCK + LD HL,ZPCH ;INCREMENT ZPC HIGH + INC (HL) + LD A,B + RET ;RETURN, TROUBLE NEXT TIME + +NXTPC1: LD A,(ZPCH) ;GET ZPAGE NUMBER + LD HL,ZMEMT ;TOP OF LOW MEM + CP (HL) + LD HL,(ZCODEP) ;PRELOAD PORTION + JP C,NXTPCL + CALL FNDPGE + LD (ZPCPG),A ;STORE PAGE + JP C,NXTPC2 ;COULD NOT FIND PAGE, SWAP IT IN (OH WHAT A SHAME) +NXTPC3: CALL SPLICE ;PUT AT TOP OF LIST + LD A,(ZPCPG) ;SET UP POINTER TO PAGE + LD HL,(PGBUFP) ;POINTER TO BEGINNING OF PAGE BUFFERS +NXTPCL: + ADD A,A + ADD A,H + LD H,A + EX DE,HL ;DE NOW HAS POINTER TO BEG OF BUFFER + LD HL,(ZPCL) + ADD HL,DE ;ADD IN OFFSET + LD (ZPCPNT),HL ;ZPCPNT NOW VALID + LD A,0FFH + LD (ZPCFLG),A + JP NEXTPC ;TRY AGAIN, THIS TIME IT WILL NOT FAIL + +NXTPC2: LD HL,MPCPG ;CHECK IF DISTROYING MPC + CP (HL) + JP NZ,NXTPC4 ;NOT DISTROYING PAGE + LD B,A + XOR A + LD (MPCFLG),A + LD A,B +NXTPC4: LD HL,(PGBUFP) + ADD A,A + ADD A,H + LD H,A ;POINTER TO BEGINNING OF BUFFER + LD A,(ZPCH) + CALL GETDSK + LD A,(ZPCPG) + LD B,A + LD HL,PGTBL + CALL HLOFF + LD A,(ZPCH) + LD (HL),A ;SET PAGE TABLE ENTRY + LD A,B + JP NXTPC3 ;PAGE NOW IN MEMORY + +SETWRD: LD A,H + OR A + RRA + LD (MPCH),A +SETWR1: LD A,H + AND 1 + LD H,A + LD (MPCL),HL + XOR A + LD (MPCFLG),A + RET + +SETSTR: LD A,H + LD (MPCH),A + ADD HL,HL + JP SETWR1 + +GETFRE: XOR A + LD (MPCFLG),A ;NO MEM PAGE LEFT + LD A,(PGBOT) + LD (MPCPG),A + CALL CKZPCP + CALL SPLICE + LD A,(MPCPG) + LD B,A + LD HL,(PGBUFP) + ADD A,A + ADD A,H + LD H,A + LD (MPCPNT),HL + LD A,B + LD HL,PGTBL + CALL HLOFF + LD (HL),0 + RET + +GETWRD: CALL GETBYT + PUSH AF + CALL GETBYT ;GET A FULL WORD + LD L,A + POP AF + LD H,A + RET + +GETBYT: LD A,(MPCFLG) ;HAS PAGE MOVED? + OR A + JP Z,GETBT1 ;PAGE HAS MOVED + LD HL,(MPCPNT) + LD B,(HL) ;GET VALUE IN B + INC HL + LD (MPCPNT),HL ;STORE BACK POINTER + LD HL,(MPCL) + INC L + LD (MPCL),HL ;ASSUME OK AT FIRST + LD A,B + RET NZ ;OK IF L NOT ZERO + LD A,H ;CROSSED 256 BYTE BOUNDRY + INC H + LD (MPCL),HL ;AGAIN ASSUME NOT PASSED 256 BOUNTRY + OR A + LD A,B + RET Z ;DID NOT CROSS 512 BOUNDRY + XOR A + LD (MPCL+1),A ;0 MPCL + LD (MPCFLG),A ;BAD DATA IN PCPNT, WILL HAVE TO FETCH NEW BLOCK + LD HL,MPCH ;INCREMENT ZPC HIGH + INC (HL) + LD A,B + RET ;RETURN, TROUBLE NEXT TIME + +GETBT1: LD A,(VERF) + OR A + JP NZ,GETB1A ;IN VERIFY MODE + LD A,(MPCH) ;GET MPAGE NUMBER + LD HL,ZMEMT ;TOP OF LOW MEM + CP (HL) + LD HL,(ZCODEP) ;PRELOAD PORTION + JP C,GETBTL + CALL FNDPGE + LD (MPCPG),A ;STORE PAGE + JP C,GETBT2 ;COULD NOT FIND PAGE, SWAP IT IN (OH WHAT A SHAME) +GETBT3: CALL SPLICE ;PUT AT TOP OF LIST + LD A,(MPCPG) ;SET UP POINTER TO PAGE + LD HL,(PGBUFP) ;POINTER TO BEGINNING OF PAGE BUFFERS +GETBTL: + ADD A,A + ADD A,H + LD H,A + EX DE,HL + LD HL,(MPCL) + ADD HL,DE + LD (MPCPNT),HL + LD A,0FFH + LD (MPCFLG),A + JP GETBYT ;TRY AGAIN, THIS TIME IT WILL NOT FAIL + + +CKZPCP: LD HL,ZPCPG ;CHECK IF DISTROYING ZPC + CP (HL) + RET NZ ;NOT DISTROYING PAGE + LD B,A + XOR A + LD (ZPCFLG),A + LD A,B + RET + +GETB1A: LD A,(PGBOT) + LD (MPCPG),A ;NEW PAGE +GETBT2: CALL CKZPCP + LD HL,(PGBUFP) + ADD A,A + ADD A,H + LD H,A ;POINTER TO BEGINNING OF BUFFER + LD A,(MPCH) + CALL GETDSK + LD A,(MPCPG) + LD B,A + LD HL,PGTBL + CALL HLOFF + LD A,(MPCH) + LD (HL),A ;SET PAGE TABLE ENTRY + LD A,B + JP GETBT3 ;PAGE NOW IN MEMORY + +SPLICE: LD C,A ;SPLICE PAGE IN A TO TOP OF LIST + LD A,(PGTOP) ;GET OLD TOP + CP C + RET Z ;SAME TOP AS LAST + LD B,A + LD A,C + LD (PGTOP),A ;NEW TOP + LD HL,PGTBLF + CALL HLOFF + LD E,(HL) ;E HAS OLD FORWARD POINTER + LD (HL),B ;NEW FORWARD TO OLD TOP + LD HL,PGTBLB + LD A,C + CALL HLOFF + LD D,(HL) ;D GETS OLD BACK POINTER + LD (HL),0FFH ;TOP HAS NO BACK + LD A,D + LD HL,PGTBLF + CALL HLOFF + LD (HL),E ;PATCH FORWARD POINTER + LD A,B + LD HL,PGTBLB + CALL HLOFF + LD (HL),C + LD A,E + INC A + JP Z,SPLIC1 ;WAS LAST BLOCK WITHOUT FORWARD POINTER + LD HL,PGTBLB-1 ;OFFSET INC A + CALL HLOFF + LD (HL),D ;SPLICE BACK POINTER + RET + +SPLIC1: LD A,D + LD (PGBOT),A ;NEW BOTTOM OF LIST + RET + +HLOFF: + ADD A,L ;INDIRECT HL THROUGH A + LD L,A + LD A,0 + ADC A,H + LD H,A + RET + +FNDPGE: LD HL,NPGS ;FIND PAGE IN A, RETURN WITH CARRY + ;SET IF NOT FOUND. A WILL HAVE FOUND PAGE OR + ;BOTTOM OF PAGE LIST + LD B,(HL) + LD C,0 + LD HL,PGTBL +FNDPGL: CP (HL) + JP Z,FNDPG1 ;SUCCESS + INC C + INC HL + DEC B + JP NZ,FNDPGL + LD A,(PGBOT) ;NOT FOUND + SCF ;SET CARRY AND RETURN BOTTOM + RET + +FNDPG1: LD A,C + RET ;CARRY WILL BE CLEARED +; +; ********************************************************************** +; * * +; * ZORK - STRING ROUTINES * +; * * +; ********************************************************************** +; +; --------------- +; PRINT Z-STRING +; --------------- +PZSTR: XOR A ;PRINT ZSTRING POINTED TO BY MPC (NOT REENTRENT) + LD (CSPERM),A ;PERMANENT CHARSET + LD (STBYTF),A ;RESET STRING BYTE FLAG + DEC A + LD (CSTEMP),A ;NO TEMP CHARSET IN EFFECT + +PZSTRL: CALL GETZCH ;GET A Z-CHARACTER + RET C ;END OF STRING IF CARRY SET + LD B,A + OR A + JP Z,PZSTRS ;0=SPACE + CP 4 ;IS THIS AN F-WORD? + JP C,PZFWRD ; YES. + CP 6 ;IS IT A SHIFT CHAR? + JP C,PZSTRP ; YES. CHANGE CHAR SET + CALL GETMOD + OR A ;IS IT CHARSET 0? + JP NZ,PZSTR1 ; NOPE. + +;PRINT LOWER CASE CHAR (CHARSET 0) + LD A,'a'-6 ;ASCII "a" MINUS Z-OFFSET +PZSTP0: + ADD A,B ;ADD CHARACTER + LD C,A +PZSTP1: CALL COUT ;PRINT RESULT + JP PZSTRL ;AND FETCH ANOTHER Z-CHAR + +;CHARSET 1 OR 2? +PZSTR1: DEC A ;SET 1? + JP NZ,PZSTR2 ; NOPE, IT'S SET 2 + +;PRINT UPPER-CASE CHAR (CHARSET 1) + LD A,'A'-6 ;ASCII "A" MINUS Z-OFFSET + JP PZSTP0 ;PROCESS IT + +;DECODE/PRINT CHARSET 2 +PZSTR2: LD A,B ;MODE 2 + CP 6 ;DIRECT ASCII CHARACTER? + JP Z,PZSTRA ; YES. + CP 7 ;CARRIAGE RETURN? + JP Z,PZSTRC ; YES. + LD HL,CHRTBL-8 ; NO. SUBTRACT OFFSET + CALL HLOFF + LD C,(HL) ;GET CHARACTER FROM TABLE + JP PZSTP1 + +PZSTRA: CALL GETZCH ;FORM CHARACTER FROM TWO BYTES + RRCA + RRCA + RRCA + LD C,A + PUSH BC + CALL GETZCH + POP BC + ADD A,C + LD C,A + CP 9 ;TAB? + JP NZ,PZSTP1 + LD C,20H + JP PZSTP1 ;PRINT IT + +PZFWRD: DEC A + ADD A,A + ADD A,A + ADD A,A + ADD A,A + ADD A,A ;SET NUMBER -1 TIMES 32 + LD (FWSET),A + CALL GETZCH ;GET STRING NUMBER + RET C ;BAD IF OUT OF CHARACTERS + LD B,A + LD A,(CSPERM) ;PRINT ZSTRING POINTED TO BY MPC + LD H,A ;MAKE IT REENTERENT + LD A,(STBYTF) + LD L,A + PUSH HL + LD HL,(ZSTWRD) + PUSH HL + LD HL,(MPCL) + PUSH HL + LD HL,(MPCH) + PUSH HL + LD HL,(FWORDS) + LD A,(FWSET) + ADD A,B ;ENTRY INTO 96 WORD TABLE + ADD A,A + CALL HLOFF ;POINTER TO SPECIAL STRING + LD A,(HL) + LD (MPCH),A + INC HL + LD L,(HL) + LD H,0 + ADD HL,HL + LD (MPCL),HL ;SET NEW MPC + XOR A + LD (MPCFLG),A ;MPCPNT NOT VALID + CALL PZSTR ;PRINT SUB STRING (REENTRENT VERSION) + XOR A ;RESTORE REENTRENT VALUES + LD (MPCFLG),A + POP HL + LD A,L + LD (MPCH),A + POP HL + LD (MPCL),HL + POP HL + LD (ZSTWRD),HL + POP HL + LD A,H + LD (CSPERM),A + LD A,L + LD (STBYTF),A + CALL GETMOD + JP PZSTRL + +PZSTRS: LD C,20H + JP PZSTP1 ;PRINT SPACE + +PZSTRC: LD C,0DH ;CR-LF + CALL COUT + LD C,0AH + JP PZSTP1 + +PZSTRT: LD A,B ;SET TEMP MODE + SUB 3 + LD (CSTEMP),A + JP PZSTRL + +PZSTRP: CALL GETMOD ;SET CHAR MODE + OR A ;MODE 0 IS TEMPORARY + JP Z,PZSTRT + DEC A + ADD A,A + ADD A,B + SUB 4 ;INDEX INTO PERMTB + PUSH HL + LD HL,PERMTB + CALL HLOFF + LD A,(HL) + POP HL + LD (CSPERM),A + JP PZSTRL + +PERMTB: DB 1,0,0,2 + +CHRTBL: DB '0123456789.,!?_#' + DB $27,$22 + DB '/\-:()' + +GETMOD: LD A,(CSTEMP) + INC A + LD A,(CSPERM) + RET Z ;RETURN WITH PERM MODE IF NO TEMP MODE + PUSH HL + LD HL,CSTEMP + LD A,(HL) + LD (HL),0FFH ;CLEAR MODE AFTER GETTING IT + POP HL + RET + +GETZCH: LD A,(STBYTF) ;FIND OUT WHICH BYTE + OR A + SCF + RET M ;OUT OF CHARACTERS + JP NZ,GETZH1 ;NOT FIRST BYTE + INC A + LD (STBYTF),A + CALL GETWRD + LD (ZSTWRD),HL ;SAVE WORD + LD A,H + RRCA + RRCA + AND 1FH + RET + +GETZH1: DEC A + JP NZ,GETZH2 ;LAST CHAR IN WORD + LD A,2 + LD (STBYTF),A + LD HL,(ZSTWRD) + ADD HL,HL + ADD HL,HL + ADD HL,HL + LD A,H + AND 1FH + RET + +GETZH2: XOR A + LD (STBYTF),A + LD HL,(ZSTWRD) + LD A,H + OR A + JP P,GETZH3 ;NOT LAST CHAR IN STRING + LD A,0FFH + LD (STBYTF),A ;INDICATE END OF STRING +GETZH3: LD A,L + AND 1FH + RET + +CONZST: XOR A ;CONVERT TO Z STRING + LD (CSPERM),A + LD HL,ZSTBUO ;POINTER TO OUTPUT BUFFER + LD B,6 ;OUTPUT 6 CHARACTERS TO CONVERT +CONZSL: LD (HL),5 + INC HL + DEC B + JP NZ,CONZSL ;FILL BUFFER WITH PAD CHARACTERS + LD B,6 + LD DE,ZSTBUO ;OUTPUT + LD HL,ZSTBUI ;INPUT +CNZSL1: LD C,(HL) + INC HL + LD A,C + OR A + LD A,5 + JP Z,CNZSLO ;BLANKS + LD A,C + CP ' ' + LD A,0 + JP Z,CNZSLO ;SPACE +CNZSL2: PUSH DE + LD A,C + CALL ZCHRCS ;WHICH CHARACTER SET + LD E,A ;E HAS CHARACTER SET OF CURRENT CHAR + LD A,(CSPERM) + CP E + JP Z,CNZSLC ;CONVERT THEN OUTPUT + LD A,E + ADD A,3 + POP DE + LD (DE),A ;OUTPUT TEMP SHIFT + INC DE + DEC B + JP Z,CNZSLE + PUSH DE +CNZSLC: LD A,C + POP DE + CALL ZCHRCS + DEC A + JP P,CNZSC1 ;NOT LOWER CASE + LD A,C + SUB 'a'-6 +CNZSLO: LD (DE),A + INC DE + DEC B + JP NZ,CNZSL1 ;NEXT + JP CNZSLE ;END + +CNZSC1: JP NZ,CNZSC3 ;NOT UPPER CASE + LD A,C + SUB 'A'-6 + JP CNZSLO + +CNZSC3: LD A,C + CP 0DH + JP NZ,CNZSC4 + LD A,(HL) + CP 0AH + JP NZ,CNZSC4 + INC HL + LD A,7 + JP CNZSLO ;CR-LF + +CNZSC4: LD A,C + CALL CNZS2M + JP NZ,CNZSLO ;FOUND IN TABLE + LD A,6 + LD (DE),A + INC DE + DEC B + JP Z,CNZSLE ;STORE ASCII VERSION + LD A,C + RLCA + RLCA + RLCA + AND 3 + LD (DE),A + INC DE + DEC B + JP Z,CNZSLE + LD A,C + AND 1FH + JP CNZSLO + +CNZS2M: PUSH BC + PUSH HL + LD HL,CHRTBL+23 ;SEARCH TABLE + LD B,24 +CNZS2L: CP (HL) + JP Z,CNZS2P ;FOUND + DEC HL + DEC B + JP NZ,CNZS2L + POP HL ;NOT FOUND + POP BC + RET ;FAIL, ZERO SET + +CNZS2P: LD A,B + ADD A,7 + POP HL + POP BC + RET ;PASSED, ZERO CLEARED + +ZCHRCS: CP 'a' + JP C,ZCHRC1 + CP 'z'+1 + JP NC,ZCHRC1 + XOR A + RET ;SET 0 + +ZCHRC1: CP 'A' + JP C,ZCHRC2 + CP 'Z'+1 + JP NC,ZCHRC2 + LD A,1 + RET + +ZCHRC2: OR A + RET Z + RET M ;END + LD A,2 + RET ;ELSE SET 2 + +CNZSLE: LD BC,ZSTBUO ;CONVERT OUTPUT STRING + LD HL,0 + LD D,H + CALL CNZSE1 + CALL CNZSE1 + CALL CNZSE1 + LD (ZSTBUO),HL + LD HL,1 + CALL CNZSE1 + CALL CNZSE1 + CALL CNZSE1 + LD (ZSTBUO+2),HL + RET + +CNZSE1: LD A,(BC) + INC BC + LD E,A + ADD HL,HL + ADD HL,HL + ADD HL,HL + ADD HL,HL + ADD HL,HL + ADD HL,DE + RET +; +; ********************************************************************** +; * * +; * ZORK - DATA SECTION * +; * * +; ********************************************************************** +; +SRND: ;RANDOM INFO FOR SAVE, KEEP TOGETHER +LOCALS: DS 15*2 ;STORAGE FOR LOCALS +ZPCH: DB 0 ;HIGH ORDER 8 BITS OF ZPC +ZPCL: DW 0 ;LOW ORDER 9 BITS OF ZPC +ZSTAKC: DB 1 ;STACK COUNT, 1=>0 IMPLIES OVERPOP, NEG=> OVER PUSH +OZSTKP: DW 0 ;OLD ZSTACK POINTER +OZSTKC: DB 0 ;OLD ZSTACK COUNT +; +SHIFT: DB 6AH,57H,3CH,99H +SRNDC EQU $-SRND +ZSTBUI: DS 6 ;ZSTR INPUT BUFFER + DB 0FFH ;END MARKER +NOLPT: DB 1 ;NON ZERO IMPLIES DO NOT USE LPT +VERF: DB 0 ;1 IF IN VERIFY MODE. +ZMEMT: DB 1 ;FIRST PAGE IN SWAPPING SPACE + +PURSTP: ;END OF PURE + +SIGNF: DB 0 ;STORAGE FOR SIGN IN MULT AND DIVIDE +ARG1: DW 0 ;OPERRAND 1 +ARG2: DW 0 ;" 2 +ARG3: DW 0 ;" 3 +ARG4: DW 0 ;" 4 +ARGCNT: DB 0 ;ARG COUNT +OPCODE: DB 0 ;CURRENT OPCODE +GLOBAL: DW 0 ;POINTER TO GLOBAL 0 +FWSET: DB 0 ;TEMPORARY STORAGE FOR FWORDS CALCULATION +FWORDS: DW 0 ;COMMON WORDS POINTER +ZPCOFF: DW 0 ;OFFSET FOR FAST JUMPS +ZPCPNT: DW 0 ;REAL POINTER TO PC +ZPCFLG: DB 0 ;0FFH IF VALID PC POINTER +ZPCPG: DB 0 ;PAGE OF ZPC +MPCH: DB 0 ;HIGH ORDER 8 BITS OF MEMORY POINTER +MPCL: DW 0 ;LOW ORDER 9 BITS OF MEMPOINTER +MPCPNT: DW 0 ;REAL POINTER TO MEMORY LOCATION +MPCFLG: DB 0 ;0FF IF VALID MPCPNT +MPCPG: DB 0 ;PAGE NUMBER OF PC PAGE +; +;PAGE TABLES +PGBUFP: DW 0 ;BUFFER POINTER +ZCODEP: DW 0 ;LOW MEM STARTING POINTER +; +NPGS: DB 0 ;NUMBER OF PAGES +PGTOP: DB 0 ;TOP OF LIST PAGE +PGBOT: DB MAXPGS-1 ;BOTTOM OF LIST +; +CSTEMP: DB 0 ;-1 IF NOT TEMP CHAR SET, ELSE SET +CSPERM: DB 0 ;PERM CHARACTER SET +STBYTF: DB 0 ;0 FOR FIRST BYTE, 1 FOR 2, 2 FOR 3, 0FFH FOR END +ZSTWRD: DW 0 ;WORD STORRAGE +ZSTBUO: DS 6 ;OUTPUT BUFFER +RTABP: DW 0 ;TEMP FOR ZREAD, RESULT TABLE POINTER +; +LMEMRY: DW 0 ;LAST LOCATION IN MEMORY, FILLED IN BY LOADER +; + END START diff --git a/cpm80/zorkcpm.prn b/cpm80/zorkcpm.prn new file mode 100644 index 0000000..8ae5361 --- /dev/null +++ b/cpm80/zorkcpm.prn @@ -0,0 +1,5030 @@ + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 1 + + + ; ********************************************************************** + ; * * + ; * ZIP80 - CPM VERSION * + ; * Z-CODE INTERPRETER PROGRAM * + ; * FOR ZILOG Z80 MICROPROCESSOR * + ; * COPYRIGHT 1984, INFOCOM, INC. * + ; * COMPANY PRIVATE -- NOT FOR DISTRIBUTION * + ; * * + ; ********************************************************************** + ; + ; + ; + ; ********************************************************************** + ; * * + ; * REVISION HISTORY * + ; * * + ; * 7/27/84 RML * + ; * 12/19/84 LS * + ; * 2/5/85 LS (CLEAR RND FLG) * + ; * * + ; ********************************************************************** + ; + ; + ; ************************************* + ; * EQUATES * + ; ************************************* + ; + ;-------------------------------------- + ; SOME COMMON DEFINITIONS + ;-------------------------------------- + ; + 0000 FALSE EQU 00H ;STANDARD FALSE VALUE + 00FF TRUE EQU 0FFH ;STANDARD TRUE VALUE + ; + ;-------------------------------------- + ; CPM EQUATES + ;-------------------------------------- + ; + 0000 WARM EQU 0000H ;WARM START IN BIOS + 0003 IOBYTE EQU 0003H ;I/O DEVICE BLOCK + 0004 CDISK EQU 0004H ;CURRENT DISK DRIVE + 0005 BDOS EQU 0005H ;CPM FUNCTION ENTRY POINT + 0006 LSTADR EQU 0006H ;LAST ADDRESS + 005C CPMFCB EQU 005CH ;DEFAULT FILE CONTROL BLOCK + 0080 CPMBUF EQU 0080H ;DEFAULT FILE TRANSFER BUFFER + 0100 TPA EQU 0100H ;TRANSIENT PROGRAM AREA + ; + ; FILE CONTROL BLOCK OFFSETS + ; + 005C CPMDRV EQU CPMFCB+0 ;DRIVE + 005D CPMFNB EQU CPMFCB+1 ;NAME STORAGE + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 2 + + + 0065 CPMFEX EQU CPMFCB+9 ;EXTENTION + 007C CPMCR EQU CPMFCB+32 ;CURRENT RECORD + 007D CPMREC EQU CPMFCB+33 ;RECORD NUMBER FOR RANDOM ACCESS + ; + ; CPM FUNCTION EQUATES + ; + 0000 CRESET EQU 0 ;SYSTEM RESET + 0001 CCI EQU 1 ;CHARACTER INPUT + 0002 CCO EQU 2 ;CHARACTER OUTPUT + 0005 CLO EQU 5 ;LIST OUTPUT + 0006 CDIO EQU 6 ;DIRECT I/O + 0009 CPSTNG EQU 9 ;PRINT STRING + 000A CRCBUF EQU 10 ;READ CONSOLE BUFFER + 000B CGCONS EQU 11 ;GET CONSOLE STATUS + 000D CPMRDS EQU 13 ;RESET DISK SYSTEM + 000E CPMSEL EQU 14 ;SELECT DISK + 000F OPEN EQU 15 ;ACTIVATES EXISTING FILE FOR R/W OPERATIONS + 0010 CLOSE EQU 16 ;INACTIVATES OPEN FILE AND RECORDS NEW FCB IN DIRECTORY + 0013 DELETE EQU 19 ;REMOVE EXISTING FILE FROM THE DIRECTORY + 0019 RETCUR EQU 25 ;RETURN CURRENT DEFAULT DISK + ; + ;SEQUENTIAL OPERATIONS + 0014 READS EQU 20 ;READ THE NEXT 128-BYTE RECORD FROM AN OPEN FILE + 0015 WRITES EQU 21 ;WRITE A SEQUENTIAL 128-BYTE RECORD ONTO AN OPEN FILE + ; + 0016 MAKEF EQU 22 ;CREATE AND OPEN A NEW FILE + 0019 CPMRCD EQU 25 ;RETURN CURRENT DISK + ; + ;RANDOM OPERATIONS + 0021 READR EQU 33 ;READ A SPECIFIED 128-BYTE RECORD FROM AN OPEN FILE + 0022 WRITER EQU 34 ;WRITE A 128-BYTE RECORD TO A SPECIFIED RECORD NUMBER + ; IN AN OPEN FILE + ; + ;MISC. EQUATES + 0085 CPLMAX EQU 133 ;MAXIMUM CHARACTERS PER LINE + ; + ;-------------------------------------- + ; APPLICATION EQUATES + ;-------------------------------------- + ; + 0040 MAXPGS EQU 64 ;MUST BE 64 FOR TRSN VERSIONS + 0010 ROOMG EQU 16 ;ROOM # (USED TO DISPLAY SHORT DESCRIPTION) + 0011 SCOREG EQU 17 ;SCORE + 0012 MOVESG EQU 18 ;NUMBER OF MOVES + 00E0 ZSTAKL EQU 224 ;LENGTH OF THE ZSTACK IN WORDS + ; + ;ZCODE HEADER OFFSETS INIT VALUES + 0000 ZVERS EQU 0 ;VERSION BYTE + 0001 ZSWAP EQU 1 ;BIT FLAGS - SEE BELOW + 0002 ZID EQU 2 ;GAME ID WORD + 0004 ZENDLD EQU 4 ;START OF NON-PRELOADED ZCODE + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 3 + + + 0006 ZSTART EQU 6 ;ZCODE EXECUTION ADDRESS + 0008 ZVOCAB EQU 8 ;START OF VOCABULARY TABLE + 000A ZOBJEC EQU 10 ;START OF OBJECT TABLE + 000C ZGLOBA EQU 12 ;START OF GLOBAL VARIABLE TABLE + 000E ZPURBT EQU 14 ;START OF "PURE" ZCODE + 0010 ZSCRIP EQU 16 ;WORD FLAG FOR CONTROLLING SCRIPT FEATURE + 0012 ZSERNM EQU 18 ;18 THROUGH 23 ARE ASCII SERIAL NUMBER, UNIQUE TO EACH COPY + 0018 ZFWORD EQU 24 ;TABLE OF COMMON WORDS + 001A ZCKLEN EQU 26 ;LENGTH TO USE FOR CHECKSUM + 001C ZCKSUM EQU 28 ;SUM OF ALL WORDS AFTER WORD 64 + ; + ;BIT FLAGS IN ZSWAP + 0001 ZSWAPF EQU 1 ;NOT USED + 0002 ZTIMEF EQU 2 ;IF SET, DISPLAY TIME IN STATUS LINE + 0004 ZSPLIT EQU 4 ;SET BY MAKDAT TO INDICATE SPLIT FILE + 0008 ZTANDY EQU 8 ;SET BY INTERPRETER TO DESIGNATE TANDY MACHINE + 0010 ZSTATB EQU 10H ;SET BY CPM CONSOLE PROGRAM, 1 IMPLIES NO STATUS LINE + ;END OF COMMON EQUATES + ; + 0190 LPDL EQU 400 ;200 LEVELS OF PUSH AND POP + ; + ; ************************************* + ; * * + ; * PROGRAM START * + ; * * + ; ************************************* + ; + 0100 ORG 100H ;START OF THE TPA + 0100 START: + 0100 C30002 JP CPMSTR ;JUMP AROUND CONFIGURATION DATA + ; + ; ************************************* + ; * CONFIGURATION DATA * + ; ************************************* + ; + 0103 4F CPMCPL: DB 79 ;CHARACTERS PER LINE + 0104 17 CPMLPP: DB 23 ;LINES PER PAGE EXCLUDING STATUS LINE + 0105 53555350 CPMFN: DB 'SUSPECT ' ;FILE PREFIX NAME (GAME DEPENDENT) + ; PADDED AT THE END WITH BLANKS (' ') SO AS + ; TO TOTAL 8 CHARACTERS + ; + 010D 01 CPMCLF: DB 1 ;1 FOR LF AFTER CR ON CONSOLE + 010E 00 CPMLLF: DB 0 ;1 FOR LF AFTER CR ON LIST + 010F 80 CPMINV: DB 80H ;NUMBER ADDED TO CHARACTERS FOR INVERSE VIDEO + + ;THE FOLLOWING STRINGS HAVE A COUNT FIELD FOLLOWED BY UP TO 32 CHARACTERS + 0110 ITRMST: + 0110 06 DB 6 ;INIT TERMINAL, CLEAR SCREEN, LOWER LEFT,SCROLL MODE + 0111 1E1A1B3D DB 1EH,1AH,1BH,'=',55,32 + 0117 DS 33-($-ITRMST) + 0131 00 RTRMST: DB 0 ;RESET TERMINAL + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 4 + + + 0132 DS 33-($-RTRMST) + 0152 04 BSTLIN: DB 4 ;BEGIN STATUS LINE STRING + 0153 1B3D2020 DB 1BH,'=',32,32 + 0157 DS 33-($-BSTLIN) + 0173 04 ESTLIN: DB 4 ;END STATUS LINE STRING + 0174 1B3D3720 DB 1BH,'=',55,32 + 0178 DS 33-($-ESTLIN) + 0194 00 PSTUPS: DB 0 ;PRINTER SETUP STRING + 0195 DS 33-($-PSTUPS) + 01B5 00 TWODSK: DB 0 ;SET TO 1 IF TWO DISKS ARE AVAILABLE + ; + 01B6 DS 200H-$ ;TO FIX THE ENTRY POINT REGUARDLESS OF + ; VARIABLE LENGTH CONFIGURATION DATA + ; + ; ************************************* + ; * CPM START * + ; ************************************* + ; + 0200 CPMSTR: ;LOCATION 200H + 0200 31070E LD SP,PDL+LPDL ;INIT MACHINE STACK + 0203 C3A610 JP BODY ;JUMP AROUND SUBROUTINE SECTION + ; + ; ************************************* + ; * SUBROUTINES * + ; ************************************* + ; + 0206 C35F07 ZER: JP RESTAR + ; + 0209 2A0600 MEMTOP: LD HL,(LSTADR) ;HL <= BDOS ENTRY VECTOR + 020C 7D LD A,L ; + 020D FEFF CP 0FFH ; + ; JP Z,MEMTP1 ;PREVIOUSLY COMMENTED OUT LINE (SCOTT) + 020F 2EFF LD L,0FFH ;SUBTRACT 1 BYTE + 0211 25 DEC H ; + 0212 3ADA21 MEMTP1: LD A,(ZCODEP+1) ;GET MSB OF LOW MEM STARTING POINTER + 0215 AC XOR H ; + 0216 E601 AND 1 ; + 0218 C0 RET NZ ; + 0219 25 DEC H ;WASTE 256 MORE IF NECESSARY + 021A C9 RET + ; + ;OPEN FILE + 021B 32750C OPNDK1: LD (FILTYP),A ;SAVE FILETYPE + 021E 215C00 LD HL,CPMFCB ;XFER DRIVE NUMBER AND FILE NAME TO FCB + 0221 060C LD B,12 + 0223 CD4B03 CALL MOVIT + 0226 AF XOR A + 0227 327C00 LD (CPMCR),A ;SET CURRENT RECORD=0 (SEQUENTIAL FILE) + 022A 210000 LD HL,0 + 022D 226800 LD (CPMFCB+12),HL ;SET EXTENT "EX" AND S1=0 + 0230 226A00 LD (CPMFCB+14),HL ;SET S2 AND RECORD COUNT FOR EXTENT "EX"=0 + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 5 + + + 0233 115C00 LD DE,CPMFCB ;^FCB + 0236 AF XOR A + 0237 325C00 LD (CPMFCB),A ;SELECT DEFAULT DRIVE + 023A 0E0F LD C,OPEN ;SELECT OPEN FUNCTION + 023C CD0500 CALL BDOS ;DO IT + 023F 3C INC A ;INCREMENT DIRECTORY CODE TO TEST FOR FILE NOT FOUND + ; Z FLAG SET IF FILE NOT FOUND + 0240 C0 RET NZ ;IF FILE EXISTS THEN RETURN WITH Z FLAG RESET A=0 + ; ELSE + ;TEST FOR TWO DISKS + 0241 3AB501 LD A,(TWODSK) ;MULTIPLE DISKS? + 0244 B7 OR A + 0245 C8 RET Z ;NO ONLY 1, ZFLAG SET AND RETURN + ; + ;TWO DISKS + 0246 3E01 LD A,1 ;AUTO DISK SELECT DRIVE A + 0248 325C00 LD (CPMFCB),A ;SET UP THE PARAMETERS + 024B AF XOR A + 024C 327C00 LD (CPMCR),A + 024F 210000 LD HL,0 + 0252 226800 LD (CPMFCB+12),HL + 0255 226A00 LD (CPMFCB+14),HL + 0258 115C00 LD DE,CPMFCB + 025B 0E0F LD C,OPEN ;TRY DRIVE 1 + 025D CD0500 CALL BDOS + 0260 3C INC A + 0261 C0 RET NZ ;RETURN IF FOUND WITH ZFLAG RESET + 0262 3E02 LD A,2 ; ELSE AUTO DISK SELECT DRIVE B + 0264 325C00 LD (CPMFCB),A ;SET UP THE PARAMETERS + 0267 AF XOR A + 0268 327C00 LD (CPMCR),A + 026B 210000 LD HL,0 + 026E 226800 LD (CPMFCB+12),HL + 0271 226A00 LD (CPMFCB+14),HL + 0274 115C00 LD DE,CPMFCB + 0277 0E0F LD C,OPEN ;TRY DRIVE 2 + 0279 CD0500 CALL BDOS + 027C 3C INC A + 027D C9 RET ;IF NOT FOUND, THEN Z WILL BE SET + + + 027E 7E PCSTR: LD A,(HL) ;PRINT STRING, GET COUNT + 027F 23 PCSTRL: INC HL ;POINT TO NEXT CHARACTER + 0280 B7 OR A + 0281 C8 RET Z ;DONE + 0282 F5 PUSH AF + 0283 C5 PUSH BC + 0284 D5 PUSH DE + 0285 E5 PUSH HL + 0286 5E LD E,(HL) + 0287 0E06 LD C,CDIO + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 6 + + + 0289 CD0500 CALL BDOS + 028C E1 POP HL + 028D D1 POP DE + 028E C1 POP BC + 028F F1 POP AF + 0290 3D DEC A + 0291 C37F02 JP PCSTRL + + 0294 7E PCPST: LD A,(HL) ;PRINT PRINTER SETUP STRING, GET COUNT + 0295 23 PCPSTL: INC HL ;POINT TO NEXT CHARACTER + 0296 B7 OR A + 0297 C8 RET Z ;DONE + 0298 F5 PUSH AF + 0299 C5 PUSH BC + 029A D5 PUSH DE + 029B E5 PUSH HL + 029C 5E LD E,(HL) + 029D 0E05 LD C,CLO + 029F CD0500 CALL BDOS + 02A2 E1 POP HL + 02A3 D1 POP DE + 02A4 C1 POP BC + 02A5 F1 POP AF + 02A6 3D DEC A + 02A7 C39502 JP PCPSTL + + 02AA 21C802 SETFIL: LD HL,FNDAT+1 ;APPEND TO THE FILE EXTENSION NAMES + 02AD CDBF02 CALL SETFL1 ;THE GAME NAME SUFFIX + 02B0 21E002 LD HL,FNPRE+1 + 02B3 CDBF02 CALL SETFL1 + 02B6 21D402 LD HL,FNPUR+1 + 02B9 CDBF02 CALL SETFL1 + 02BC 21EC02 LD HL,SRDFNM+1 + 02BF 110501 SETFL1: LD DE,CPMFN + 02C2 0608 LD B,8 + 02C4 C34B03 JP MOVIT + + 02C7 002E2E2E FNDAT: DB 0,'........DAT' + 02D3 002E2E2E FNPUR: DB 0,'........PUR' + 02DF 002E2E2E FNPRE: DB 0,'........PRE' + 02EB 002E2E2E SRDFNM: DB 0,'........SAV' + + + 02F7 22EB0B GETDSK: LD (DBUFP),HL + 02FA CD630B CALL LFILS ;OPEN ZORK/DAT FILE IF NOTHING OPEN + 02FD 6F LD L,A + 02FE 3A750C LD A,(FILTYP) + 0301 FE03 CP 3 ;DATA TYPE OF FILE? + 0303 7D LD A,L + 0304 CA1803 JP Z,GETDK2 + 0307 21B921 LD HL,ZMEMT + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 7 + + + 030A BE CP (HL) + 030B DA1503 JP C,GETPRE ;MAKE SURE ZORK/PRE IS OPEN + 030E 96 SUB (HL) ;REAL OFFSET + 030F CD930B CALL LFILD ;MAKE SURE ZORK/DAT IS OPEN + 0312 C31803 JP GETDK2 + + 0315 CDB30B GETPRE: CALL LFILP ;GET ZORK/PRE + 0318 6F GETDK2: LD L,A + 0319 2600 LD H,0 + 031B 29 ADD HL,HL + 031C 29 ADD HL,HL ;*4 FOR 128 BYTE BLOCKS + 031D CD2603 CALL GTDSK1 + 0320 CD2603 CALL GTDSK1 + 0323 CD2603 CALL GTDSK1 + 0326 E5 GTDSK1: PUSH HL + 0327 227D00 LD (CPMREC),HL + 032A AF XOR A + 032B 327F00 LD (CPMREC+2),A + 032E 115C00 LD DE,CPMFCB + 0331 0E21 LD C,READR ;READ RANDOM RECORD + 0333 CD0500 CALL BDOS + 0336 B7 OR A + 0337 C40602 CALL NZ,ZER + 033A 118000 LD DE,CPMBUF + 033D 2AEB0B LD HL,(DBUFP) + 0340 0680 LD B,128 + 0342 CD4B03 CALL MOVIT + 0345 22EB0B LD (DBUFP),HL + 0348 E1 POP HL + 0349 23 INC HL ;INCREMENT FOR NEXT TIME + 034A C9 RET + + 034B 1A MOVIT: LD A,(DE) ;TRANSFER (D) TO (H) COUNT IN B + 034C 77 LD (HL),A + 034D 23 INC HL + 034E 13 INC DE + 034F 05 DEC B + 0350 C24B03 JP NZ,MOVIT + 0353 C9 RET + + 0354 3A0401 READBF: LD A,(CPMLPP) ;LINES PER PAGE + 0357 3D DEC A + 0358 32760C LD (MORCNT),A + 035B CDF704 CALL FLSLIN ;FLUSH LINE + 035E 3E01 LD A,1 + 0360 32B721 LD (NOLPT),A ;TURN OFF LPT DURING READ + 0363 164D LD D,77 ;D CONTAINS MAX CHARS CAN READ + 0365 1E00 LD E,0 ;E CONTAINS CHAR COUNT + 0367 2ABB21 LD HL,(ARG1) ;READ A BUFFER + 036A 23 INC HL + 036B CD3804 READB1: CALL CIN ;GET A CHAR + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 8 + + + 036E FE08 CP 08H + 0370 CAA303 JP Z,RDBFRO + 0373 FE7F CP 7FH + 0375 CAA303 JP Z,RDBFRO + 0378 FE0D CP 0DH + 037A CAC003 JP Z,RDBFCR + 037D FE12 CP 18 + 037F CAFE03 JP Z,RDBFRT + 0382 FE20 CP 20H + 0384 DA6B03 JP C,READB1 + 0387 4F LD C,A + 0388 CDB604 CALL COUT + 038B 79 LD A,C + 038C FE41 CP 'A' + 038E DA9803 JP C,READB2 + 0391 FE5B CP 'Z'+1 + 0393 D29803 JP NC,READB2 + 0396 C620 ADD A,'a'-'A' ;CONVERT TO LOWER CASE + 0398 77 READB2: LD (HL),A + 0399 23 INC HL + 039A 1C INC E + 039B 7A LD A,D + 039C BB CP E + 039D CA1A04 JP Z,RDBFFL + 03A0 C36B03 JP READB1 + + 03A3 7B RDBFRO: LD A,E ;CHECK IF 1ST CHAR + 03A4 FE00 CP 0 ;IF SO DON'T DELETE + 03A6 CA6B03 JP Z,READB1 ;GO GET ANOTHER CHAR + 03A9 1D DEC E + 03AA 2B DEC HL + 03AB CDB103 CALL COUTBS + 03AE C36B03 JP READB1 + + 03B1 0E08 COUTBS: LD C,08H + 03B3 CDB604 CALL COUT + 03B6 0E20 LD C,20H + 03B8 CDB604 CALL COUT + 03BB 0E08 LD C,08H ;DEVINE RUBOUT + 03BD C3B604 JP COUT + + 03C0 E5 RDBFCR: PUSH HL + 03C1 D5 PUSH DE + 03C2 AF XOR A + 03C3 32B721 LD (NOLPT),A + 03C6 2AD921 LD HL,(ZCODEP) + 03C9 111100 LD DE,ZSCRIP+1 + 03CC 19 ADD HL,DE + 03CD 7E LD A,(HL) + 03CE E601 AND 1 + 03D0 CAEF03 JP Z,RDBFC2 ;NO LPT + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 9 + + + 03D3 D1 POP DE + 03D4 D5 PUSH DE + 03D5 7B LD A,E + 03D6 B7 OR A + 03D7 CAEF03 JP Z,RDBFC2 ;NOTHING TYPED + 03DA 2ABB21 LD HL,(ARG1) + 03DD 23 INC HL + 03DE 7E RDBFC3: LD A,(HL) + 03DF FE61 CP 'a' + 03E1 DAE603 JP C,RDBFC4 ;NOT LOWER CASE + 03E4 D620 SUB 'a'-'A' + 03E6 4F RDBFC4: LD C,A + 03E7 23 INC HL + 03E8 CD8605 CALL LPTO + 03EB 1D DEC E + 03EC C2DE03 JP NZ,RDBFC3 + 03EF D1 RDBFC2: POP DE + 03F0 E1 POP HL + 03F1 7A LD A,D + 03F2 BB CP E + 03F3 CAF903 JP Z,RDBFC1 + 03F6 1C INC E + 03F7 360D LD (HL),0DH + 03F9 CD7304 RDBFC1: CALL PCRLFD + 03FC 7B LD A,E + 03FD C9 RET + + 03FE D5 RDBFRT: PUSH DE + 03FF E5 PUSH HL + 0400 2ABB21 LD HL,(ARG1) + 0403 23 INC HL + 0404 CD7304 CALL PCRLFD + 0407 7B RDBFR1: LD A,E + 0408 B7 OR A + 0409 CA1504 JP Z,RDBFR2 + 040C 4E LD C,(HL) + 040D CDB604 CALL COUT + 0410 1D DEC E + 0411 23 INC HL + 0412 C30704 JP RDBFR1 + + 0415 E1 RDBFR2: POP HL + 0416 D1 POP DE + 0417 C36B03 JP READB1 + + 041A CD3804 RDBFFL: CALL CIN + 041D FE0D CP 0DH ;ACCEPT + 041F CAC003 JP Z,RDBFCR + 0422 FE08 CP 08 ;OR + 0424 CAA303 JP Z,RDBFRO + 0427 FE7F CP 7FH + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 10 + + + 0429 CAA303 JP Z,RDBFRO + 042C D5 PUSH DE + 042D 1E07 LD E,7 ;RING BELL, READ BUFFER FULL + 042F 0E06 LD C,CDIO + 0431 CD0500 CALL BDOS + 0434 D1 POP DE + 0435 C31A04 JP RDBFFL ;AND LOOP TIL GET WHAT WE WANT + + + 0438 C5 CIN: PUSH BC + 0439 D5 PUSH DE + 043A E5 PUSH HL + 043B 1EFF CIN1: LD E,0FFH + 043D 0E06 LD C,CDIO ;READ DIRECT + 043F CD0500 CALL BDOS + 0442 B7 OR A + 0443 CA5104 JP Z,CIN2 ;NO CHARACTER YET + 0446 21E60B LD HL,RDFLG + 0449 36FF LD (HL),0FFH ;NOT FIRST READ ANY MORE + 044B E1 POP HL + 044C D1 POP DE + 044D C1 POP BC + 044E E67F AND 7FH + 0450 C9 RET + + 0451 3AE60B CIN2: LD A,(RDFLG) + 0454 B7 OR A + 0455 C23B04 JP NZ,CIN1 ;NOT FIRST READ + 0458 CDEE1B CALL RND + 045B C33B04 JP CIN1 + + 045E 21E50B COUTD: LD HL,COUTDC ;INCREASE COUNT + 0461 34 INC (HL) + 0462 3A0F01 LD A,(CPMINV) ;INVERSE VIDEO ADDER + 0465 21E40B LD HL,STAFLG + 0468 A6 AND (HL) ;ADD ONLY IF IN STATUS MODE + 0469 81 ADD A,C + 046A 5F LD E,A + 046B 0E06 LD C,CDIO + 046D CD0500 CALL BDOS + 0470 C39704 JP POPRET + + 0473 C5 PCRLFD: PUSH BC + 0474 D5 PUSH DE + 0475 E5 PUSH HL + 0476 1E0D LD E,0DH + 0478 0E06 LD C,CDIO + 047A CD0500 CALL BDOS + 047D 3A0D01 LD A,(CPMCLF) + 0480 B7 OR A + 0481 CA8B04 JP Z,PCRLD1 ;NO LINE FEED + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 11 + + + 0484 1E0A LD E,0AH + 0486 0E06 LD C,CDIO + 0488 CD0500 CALL BDOS + 048B 0E0D PCRLD1: LD C,0DH + 048D CD9B04 CALL LPCHK + 0490 21760C LD HL,MORCNT + 0493 35 DEC (HL) + 0494 CC0107 CALL Z,MORE + 0497 E1 POPRET: POP HL + 0498 D1 POP DE + 0499 C1 POP BC + 049A C9 RET + + 049B C5 LPCHK: PUSH BC + 049C D5 PUSH DE + 049D E5 PUSH HL + 049E 2AD921 LD HL,(ZCODEP) + 04A1 111100 LD DE,ZSCRIP+1 + 04A4 19 ADD HL,DE + 04A5 7E LD A,(HL) + 04A6 E601 AND 1 + 04A8 C48605 CALL NZ,LPTO + 04AB C39704 JP POPRET + + 04AE CD7405 COUTCR: CALL LINOCR + 04B1 C3F304 JP CORET + + 04B4 0E0D PCRLF: LD C,0DH + 04B6 C5 COUT: PUSH BC + 04B7 D5 PUSH DE + 04B8 E5 PUSH HL + 04B9 79 LD A,C + 04BA FE08 CP 8 + 04BC CAD304 JP Z,COUT1 + 04BF FE1B CP 1BH + 04C1 CA8505 JP Z,CLEARS + 04C4 FE0C CP 12 + 04C6 CA8505 JP Z,CLEARS + 04C9 FE0D CP 0DH + 04CB CAAE04 JP Z,COUTCR + 04CE FE20 CP 20H + 04D0 DAF304 JP C,CORET ;NON PRINTING + 04D3 3AB721 COUT1: LD A,(NOLPT) + 04D6 B7 OR A + 04D7 C25E04 JP NZ,COUTD + 04DA 3AED0B LD A,(NCHARS) + 04DD 210301 LD HL,CPMCPL + 04E0 BE CP (HL) + 04E1 D47405 CALL NC,LINOCR ;OUTPUT LINE IF FULL + 04E4 3AED0B LD A,(NCHARS) + 04E7 3C INC A + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 12 + + + 04E8 32ED0B LD (NCHARS),A + 04EB 2A730C LD HL,(CHRPNT) + 04EE 71 LD (HL),C + 04EF 23 INC HL + 04F0 22730C LD (CHRPNT),HL + 04F3 E1 CORET: POP HL + 04F4 D1 POP DE + 04F5 C1 POP BC + 04F6 C9 RET + + 04F7 C5 FLSLIN: PUSH BC ;FLUSH LINE + 04F8 3AED0B LD A,(NCHARS) + 04FB B7 OR A + 04FC CA7205 JP Z,LINOTR ;NO CHARS + 04FF C32105 JP LINFUL ;PRINT ALL + + 0502 C5 LINOUT: PUSH BC + 0503 3AED0B LD A,(NCHARS) + 0506 B7 OR A + 0507 CA7205 JP Z,LINOTR ;NO CHARACTERS + 050A 3D DEC A + 050B 47 LD B,A + 050C 79 LD A,C + 050D FE0D CP 0DH + 050F CA2105 JP Z,LINFUL + 0512 2A730C LD HL,(CHRPNT) ;FIND LAST SPACE + 0515 2B DEC HL + 0516 7E LINOT1: LD A,(HL) + 0517 FE20 CP 20H + 0519 CA2805 JP Z,LINOT2 ;FOUND SPACE + 051C 2B DEC HL + 051D 05 DEC B + 051E F21605 JP P,LINOT1 + 0521 2A730C LINFUL: LD HL,(CHRPNT) ;PRINT WHOLE LINE + 0524 3AED0B LD A,(NCHARS) + 0527 47 LD B,A + 0528 C5 LINOT2: PUSH BC + 0529 E5 PUSH HL + 052A 21EE0B LD HL,CHARS + 052D 78 LD A,B + 052E B7 OR A + 052F CA4905 JP Z,LINOT6 + 0532 C5 LINOT3: PUSH BC + 0533 D5 PUSH DE + 0534 E5 PUSH HL + 0535 5E LD E,(HL) + 0536 0E06 LD C,CDIO + 0538 CD0500 CALL BDOS + 053B E1 POP HL + 053C E5 PUSH HL + 053D 4E LD C,(HL) + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 13 + + + 053E CD9B04 CALL LPCHK + 0541 E1 POP HL + 0542 D1 POP DE + 0543 23 INC HL + 0544 C1 POP BC + 0545 05 DEC B + 0546 C23205 JP NZ,LINOT3 + 0549 E1 LINOT6: POP HL + 054A 23 INC HL + 054B C1 POP BC + 054C 3AED0B LD A,(NCHARS) + 054F 90 SUB B + 0550 3D DEC A + 0551 F25505 JP P,LINOT7 + 0554 AF XOR A + ; + 0555 32ED0B LINOT7: LD (NCHARS),A ;CHARACTERS NOT YET PRINTED + 0558 CA6605 JP Z,LINOT5 + 055B 11EE0B LD DE,CHARS + 055E 7E LINOT4: LD A,(HL) + 055F 12 LD (DE),A + 0560 23 INC HL + 0561 13 INC DE + 0562 05 DEC B + 0563 C25E05 JP NZ,LINOT4 + 0566 21EE0B LINOT5: LD HL,CHARS + 0569 3AED0B LD A,(NCHARS) + 056C CD081F CALL HLOFF + 056F 22730C LD (CHRPNT),HL + 0572 C1 LINOTR: POP BC + 0573 C9 RET + + 0574 CD0205 LINOCR: CALL LINOUT + 0577 C37304 JP PCRLFD + + 057A 2AD921 TMCHK: LD HL,(ZCODEP) ;RETURNS NON ZERO IF IN TIME DISPLAY MODE + 057D 110100 LD DE,ZSWAP + 0580 19 ADD HL,DE + 0581 7E LD A,(HL) + 0582 E602 AND ZTIMEF + 0584 C9 RET + + 0585 CLEARS: + 0585 C9 RET ;NOT YET IMPLEMENTED + + 0586 3AB721 LPTO: LD A,(NOLPT) + 0589 B7 OR A + 058A C0 RET NZ ;SOME ITEMS DON'T GO TO LPT + 058B 3AE70B LD A,(PRFLG) + 058E B7 OR A + 058F CCB405 CALL Z,LPINIT + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 14 + + + 0592 C5 PUSH BC + 0593 D5 PUSH DE + 0594 E5 PUSH HL + 0595 59 LD E,C + 0596 C5 PUSH BC + 0597 0E05 LD C,CLO ;LIST OUT + 0599 CD0500 CALL BDOS + 059C C1 POP BC + 059D 79 LD A,C + 059E FE0D CP 0DH + 05A0 C29704 JP NZ,POPRET ;NOT CR + 05A3 3A0E01 LD A,(CPMLLF) + 05A6 B7 OR A + 05A7 CA9704 JP Z,POPRET + 05AA 1E0A LD E,0AH + 05AC 0E05 LD C,CLO ;OUTPUT LF IF NEEDED + 05AE CD0500 CALL BDOS + 05B1 C39704 JP POPRET + + 05B4 3C LPINIT: INC A + 05B5 32E70B LD (PRFLG),A + 05B8 E5 PUSH HL + 05B9 219401 LD HL,PSTUPS + 05BC CD9402 CALL PCPST ;PRINTER SETUP STRING + 05BF E1 POP HL + 05C0 C9 RET + + 05C1 215201 WHOLIN: LD HL,BSTLIN + 05C4 7E LD A,(HL) ;DO WE HAVE A STATUS LINE? + 05C5 B7 OR A + 05C6 C8 RET Z ;NO, RETURN + 05C7 3ADF21 LD A,(CSPERM) ;SAVE DATA CLOBERED BY PRNTDC + 05CA 67 LD H,A + 05CB 3AE021 LD A,(STBYTF) + 05CE 6F LD L,A + 05CF E5 PUSH HL + 05D0 2AE121 LD HL,(ZSTWRD) + 05D3 E5 PUSH HL + 05D4 2AD121 LD HL,(MPCL) + 05D7 E5 PUSH HL + 05D8 2AD021 LD HL,(MPCH) + 05DB E5 PUSH HL + 05DC 215201 LD HL,BSTLIN + 05DF CD7E02 CALL PCSTR ;POSITON TO TOP OF SCREEN + 05E2 AF XOR A + 05E3 32E50B LD (COUTDC),A ;BEGINNING OF LINE + 05E6 3E01 LD A,1 + 05E8 32B721 LD (NOLPT),A + 05EB 3EFF LD A,0FFH + 05ED 32E40B LD (STAFLG),A ;STATUS LINE FLAG (ANDED WITH CPMINV ADDER) + 05F0 CD7A05 CALL TMCHK + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 15 + + + 05F3 C25306 JP NZ,WHOLT + 05F6 CD4506 CALL WHOLN1 ;COMMON TIME/ROOM PRINTING + 05F9 21D306 LD HL,WHOMSG ;PRINT 'SCORE' + 05FC CDB206 CALL POSPST ;POSITION THEN PRINT + 05FF 3E11 LD A,SCOREG + 0601 CD5913 CALL VARGET + 0604 CD971B CALL PRNTNC + 0607 0E2F LD C,'/' + 0609 CDB604 CALL COUT + 060C 3E12 LD A,MOVESG + 060E CD5913 CALL VARGET + 0611 CD971B CALL PRNTNC + 0614 3A0301 WHOLN2: LD A,(CPMCPL) + 0617 47 LD B,A + 0618 CDA306 CALL CHRPOS ;BLANK REST OF LINE + 061B 217301 LD HL,ESTLIN + 061E CD7E02 CALL PCSTR ;POSITION BACK TO LOWER LEFT + 0621 AF XOR A + 0622 32B721 LD (NOLPT),A + 0625 32E40B LD (STAFLG),A + 0628 32D521 LD (MPCFLG),A ;RESTORE STRING VALUES + 062B E1 POP HL + 062C 7D LD A,L + 062D 32D021 LD (MPCH),A + 0630 E1 POP HL + 0631 22D121 LD (MPCL),HL + 0634 E1 POP HL + 0635 22E121 LD (ZSTWRD),HL + 0638 E1 POP HL + 0639 7C LD A,H + 063A 32DF21 LD (CSPERM),A + 063D 7D LD A,L + 063E 32E021 LD (STBYTF),A + 0641 CD3E20 CALL GETMOD + 0644 C9 RET + + + 0645 0E20 WHOLN1: LD C,' ' ;PRINT A ' ' + 0647 CDB604 CALL COUT + 064A 3E10 LD A,ROOMG ;GET THE CURRENT ROOM NO. + 064C CD5913 CALL VARGET + 064F 7D LD A,L + 0650 C32116 JP PRNTDC ;PRINT THE SHORT DESCRIPTION + ; + ; PRINT THE TIME (HOURS) + 0653 CD4506 WHOLT: CALL WHOLN1 + 0656 21DB06 LD HL,WHOTMS ;PRINT '.......TIME' MESSAGE + 0659 CDB206 CALL POSPST + 065C 3E11 LD A,SCOREG ;GET HOURS IN MILITARY TIME (24 HR CLOCK) + 065E CD5913 CALL VARGET + 0661 7D LD A,L ;A <= HOURS + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 16 + + + 0662 F5 PUSH AF ;SAVE HOURS + 0663 B7 OR A ;HOURS=0? + 0664 C26C06 JP NZ,WHOLT0 ; NO. + 0667 2E0C LD L,12 ; YES. 0 HRS IS REALLY 12 HOURS + 0669 C37406 JP WHOLT1 + ; + 066C FE0D WHOLT0: CP 13 ;COMPARE HOURS (24 HR CLOCK) WITH 13 + 066E DA7406 JP C,WHOLT1 ; IF < 13 THEN PRINT HOURS + 0671 D60C SUB 12 ; ELSE A <= A-12 + 0673 6F LD L,A ; L <= ADJUSTED TIME (12 HR CLOCK) + 0674 CD971B WHOLT1: CALL PRNTNC ;PRINT THE HOURS + 0677 0E3A LD C,':' ;PRINT ':' + 0679 CDB604 CALL COUT + ; + ; PRINT TIME (MINUTES) + 067C 3E12 LD A,MOVESG ;GET THE MINUTES + 067E CD5913 CALL VARGET ;A <= MINUTES + 0681 CD3B07 CALL PNTTIM ;PRINT THE MINUTES + 0684 0E20 LD C,' ' ;PRINT A ' ' + 0686 CDB604 CALL COUT + ; + ; PRINT 'AM/PM' + 0689 0E61 LD C,'a' + 068B F1 POP AF ;RESTORE HOURS + 068C FE18 CP 24 ;24 HOURS IS AM + 068E CA9806 JP Z,WHOLT2 + 0691 FE0C CP 12 ;< 12 HOURS IS AM + 0693 DA9806 JP C,WHOLT2 + 0696 0E70 LD C,'p' ;ELSE IT'S PM + 0698 CDB604 WHOLT2: CALL COUT ;PRINT 'A/P' + 069B 0E6D LD C,'m' + 069D CDB604 CALL COUT ;PRINT 'M' + 06A0 C31406 JP WHOLN2 + ; + 06A3 3AE50B CHRPOS: LD A,(COUTDC) ;SPACE UNTILE COUTDC=(B) + 06A6 B8 CP B + 06A7 D0 RET NC + 06A8 C5 PUSH BC + 06A9 0E20 LD C,20H + 06AB CDB604 CALL COUT + 06AE C1 POP BC + 06AF C3A306 JP CHRPOS + + 06B2 3A0301 POSPST: LD A,(CPMCPL) + 06B5 FE27 CP 39 ;VERY SHORT + 06B7 DACD06 JP C,POSPS1 ;DON'T PRINT WORDS + 06BA D610 SUB 16 + 06BC E5 PUSH HL + 06BD 47 LD B,A + 06BE CDA306 CALL CHRPOS ;SPACE OVER + 06C1 E1 POP HL + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 17 + + + 06C2 46 LD B,(HL) + 06C3 23 POSPS2: INC HL + 06C4 4E LD C,(HL) + 06C5 CDB604 CALL COUT + 06C8 05 DEC B + 06C9 C2C306 JP NZ,POSPS2 + 06CC C9 RET + + 06CD D608 POSPS1: SUB 8 ;MOVE OVER 8 FROM EDGE + 06CF 47 LD B,A + 06D0 C3A306 JP CHRPOS + + 06D3 0753636F WHOMSG: DB 7,'Score:',20H + + 06DB 0654696D WHOTMS: DB 6,'Time:',20H + + 06E2 2D2D2D2D MORMSG: DB '-------------More-------------',0 + 001F LMORE EQU $-MORMSG + + 0701 3A0401 MORE: LD A,(CPMLPP) + 0704 B7 OR A + 0705 C8 RET Z ;NO MORE LINE IF 0 + 0706 3D DEC A + 0707 77 LD (HL),A + 0708 CDC105 CALL WHOLIN ;SHOW STATUS + 070B 3E01 LD A,1 + 070D 32B721 LD (NOLPT),A ;DON'T SCRIPT MORE MESSAGE + 0710 21E206 LD HL,MORMSG + 0713 CD660A CALL MSGOUT + 0716 CD3804 CALL CIN + 0719 1E0D LD E,0DH + 071B 0E06 LD C,CDIO ;CR WITHOUT LF + 071D CD0500 CALL BDOS + 0720 061F LD B,LMORE + 0722 C5 MORE1: PUSH BC + 0723 1E20 LD E,20H + 0725 0E06 LD C,CDIO + 0727 CD0500 CALL BDOS + 072A C1 POP BC + 072B 05 DEC B + 072C C22207 JP NZ,MORE1 + 072F 1E0D LD E,0DH + 0731 0E06 LD C,CDIO + 0733 CD0500 CALL BDOS + 0736 AF XOR A + 0737 32B721 LD (NOLPT),A + 073A C9 RET ;NOW AT BEGINNING OF CLEAR LINE + + 073B 110A00 PNTTIM: LD DE,10 + 073E CD251D CALL HLGEDE + 0741 0E30 LD C,'0' + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 18 + + + 0743 D4B604 CALL NC,COUT + 0746 C3971B JP PRNTNC + + ;ZZZZZZZZZZZZZZZZZZZZZZZZZZZ + 0749 115C00 QUIT: LD DE,CPMFCB + 074C 0E10 LD C,CLOSE + 074E CD0500 CALL BDOS + 0751 213101 LD HL,RTRMST + 0754 CD7E02 CALL PCSTR + 0757 0E00 LD C,CRESET + 0759 CD0500 CALL BDOS + 075C C34907 JP QUIT + + 075F RESTAR: + 075F 115C00 LD DE,CPMFCB + 0762 0E10 LD C,CLOSE + 0764 CD0500 CALL BDOS + 0767 213101 LD HL,RTRMST + 076A CD7E02 CALL PCSTR + 076D C30001 JP START + + 0770 SAVE: + 0770 AF XOR A + 0771 32750C LD (FILTYP),A + 0774 115C00 LD DE,CPMFCB ;CLOSE CURRENT FCB + 0777 0E10 LD C,CLOSE ;SO FILE IS PROTECTED + 0779 CD0500 CALL BDOS + 077C CD6C08 CALL SRGFNM ;GET SAVE NAME (SWAP DISKS) + 077F 115C00 LD DE,CPMFCB ;DELETE ANY PREVIOUS FILE + 0782 0E13 LD C,DELETE ;BY THIS NAME + 0784 CD0500 CALL BDOS + 0787 115C00 LD DE,CPMFCB ;CREATE NEW SAVE FILE + 078A 0E16 LD C,MAKEF + 078C CD0500 CALL BDOS + 078F 3C INC A + 0790 CA3508 JP Z,SFAIL ;DID NOT OPEN + 0793 2AD921 LD HL,(ZCODEP) + 0796 010000 LD BC,ZVERS + 0799 09 ADD HL,BC + 079A 7E LD A,(HL) ;STORE VERSION NUMBER + 079B 328000 LD (CPMBUF),A + 079E 2A070E LD HL,(ZSTAKP) + 07A1 228100 LD (CPMBUF+1),HL + 07A4 218300 LD HL,CPMBUF+3 + 07A7 118721 LD DE,SRND + 07AA 012900 LD BC,SRNDC ;TO MAKE EXTERNALS WORK + 07AD 41 LD B,C + 07AE CD4B03 CALL MOVIT + 07B1 115C00 LD DE,CPMFCB + 07B4 0E15 LD C,WRITES + 07B6 CD0500 CALL BDOS + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 19 + + + 07B9 B7 OR A + 07BA C23508 JP NZ,SFAIL ;WRITE OUT INITIAL STUFF + 07BD 0E04 LD C,0+(((ZSTAKL*2)+127)/128) + 07BF 11090E LD DE,ZSTACK ;NEXT WRITE OUT STACK + 07C2 0680 SAVEA: LD B,128 + 07C4 218000 LD HL,CPMBUF + 07C7 CD4B03 CALL MOVIT + 07CA C5 PUSH BC + 07CB D5 PUSH DE + 07CC 115C00 LD DE,CPMFCB + 07CF 0E15 LD C,WRITES ;WRITE SEQ. RECORD + 07D1 CD0500 CALL BDOS + 07D4 B7 OR A + 07D5 C24808 JP NZ,SRFAIL + 07D8 D1 POP DE + 07D9 C1 POP BC + 07DA 0D DEC C + 07DB C2C207 JP NZ,SAVEA ;ALL ZSTACK RECORDS DONE? + 07DE 2AD921 LD HL,(ZCODEP) + 07E1 110E00 LD DE,ZPURBT + 07E4 19 ADD HL,DE + 07E5 4E LD C,(HL) ;COUNT OF PAGES + 07E6 2AD921 LD HL,(ZCODEP) + 07E9 EB EX DE,HL ;WHERE TO START FROM + 07EA 0602 LD B,2 ;128 BYTE RECORDS + 07EC C5 SAVE1: PUSH BC + 07ED 218000 LD HL,CPMBUF + 07F0 0680 LD B,128 + 07F2 CD4B03 CALL MOVIT ;GET NEXT RECORD TO TRANSFER + 07F5 D5 PUSH DE + 07F6 115C00 LD DE,CPMFCB + 07F9 0E15 LD C,WRITES ;WRITE IT SEQ. TO DISK + 07FB CD0500 CALL BDOS + 07FE D1 POP DE + 07FF C1 POP BC + 0800 B7 OR A + 0801 C23508 JP NZ,SFAIL ;WRITE ERROR + 0804 05 DEC B + 0805 C2EC07 JP NZ,SAVE1 ;GO DO 2ND HALF OF PAGE + 0808 0602 LD B,2 ;RESET FOR 2 RECORDS PER PAGE + 080A 0D DEC C + 080B F2EC07 JP P,SAVE1 ;NEXT PAGE + 080E 115C00 SRCLOS: LD DE,CPMFCB + 0811 0E10 LD C,CLOSE ;DONE, CLOSE SAVE FILE + 0813 CD0500 CALL BDOS + 0816 CD3F09 CALL SRSWPD ;TELL PLAYER SWAP GAME DISK BACK IN + 0819 0E19 LD C,CPMRCD ;GET CURRENT DEFAULT DRIVE + 081B CD0500 CALL BDOS + 081E F5 PUSH AF ;HOLD IT A SEC + 081F 0E0D LD C,CPMRDS ;RESET SYSTEM FOR NEW DISK + 0821 CD0500 CALL BDOS + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 20 + + + 0824 F1 POP AF ;RETRIEVE + 0825 5F LD E,A ;AND RESET CORRECT DEFAULT + 0826 0E0E LD C,CPMSEL ;(DESTROYED BY RESET SYSTEM) + 0828 CD0500 CALL BDOS + 082B CDB404 CALL PCRLF + 082E AF XOR A + 082F 32CE21 LD (ZPCFLG),A + 0832 C38013 JP PREDS + + + + 0835 115C00 SFAIL: LD DE,CPMFCB + 0838 0E10 LD C,CLOSE + 083A CD0500 CALL BDOS + 083D 115C00 LD DE,CPMFCB + 0840 0E13 LD C,DELETE + 0842 CD0500 CALL BDOS + 0845 C35008 JP SFAIL1 + + 0848 115C00 SRFAIL: LD DE,CPMFCB + 084B 0E10 LD C,CLOSE + 084D CD0500 CALL BDOS + 0850 CD3F09 SFAIL1: CALL SRSWPD + 0853 0E19 LD C,CPMRCD ;RETURN CURRENT DEFAULT DISK + 0855 CD0500 CALL BDOS + 0858 F5 PUSH AF + 0859 0E0D LD C,CPMRDS + 085B CD0500 CALL BDOS + 085E F1 POP AF + 085F 5F LD E,A + 0860 0E0E LD C,CPMSEL ;RESELECT DEFAULT + 0862 CD0500 CALL BDOS + 0865 AF XOR A + 0866 32CE21 LD (ZPCFLG),A + 0869 C37113 JP PREDF + + 086C 21080A SRGFNM: LD HL,SRMSG1 + 086F CD660A CALL MSGOUT + + 0872 0608 LD B,8 + 0874 21EC02 LD HL,SRDFNM+1 ;FILENAME + 0877 CD0009 CALL SRGFNA ;DISPLAY CHARS TILL HIT BLANKS + 087A 21640A LD HL,SRMSG3 + 087D CD660A CALL MSGOUT + 0880 0603 LD B,3 + 0882 21F402 LD HL,SRDFNM+9 + 0885 CD0009 CALL SRGFNA + 0888 21440A LD HL,SRMSG2 + 088B CD660A CALL MSGOUT + 088E 210000 LD HL,0 + 0891 226800 LD (CPMFCB+12),HL ;CLEAR EX,S1 + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 21 + + + 0894 226A00 LD (CPMFCB+14),HL ; S2,RC + 0897 AF XOR A + 0898 327C00 LD (CPMCR),A ; CR + 089B 118000 LD DE,CPMBUF + 089E 3E0E LD A,14 + 08A0 12 LD (DE),A + 08A1 0E0A LD C,CRCBUF ;READ CONSOLE BUFFER + 08A3 CD0500 CALL BDOS + 08A6 CD7304 CALL PCRLFD + 08A9 0E19 LD C,CPMRCD ;RETURN CURRENT DISK + 08AB CD0500 CALL BDOS + 08AE F5 PUSH AF + 08AF 0E0D LD C,CPMRDS ;RESET SYSTEM + 08B1 CD0500 CALL BDOS + 08B4 F1 POP AF + 08B5 5F LD E,A + 08B6 0E0E LD C,CPMSEL ;RESELECT DEFAULT + 08B8 CD0500 CALL BDOS + 08BB 3A8100 LD A,(CPMBUF+1) + 08BE B7 OR A + 08BF CA3409 JP Z,SRGDFN ;USE DEFAULT, SKIP THIS NEXT PART + 08C2 060B LD B,11 + 08C4 21EB02 LD HL,SRDFNM + 08C7 23 INC HL ;SKIP OVER DRIVE, LEAVE AS WAS SO PLAYER + 08C8 ;NEED ONLY SPECIFY IT ONCE + 08C8 3620 SRGFM1: LD (HL),20H + 08CA 23 INC HL + 08CB 05 DEC B + 08CC C2C808 JP NZ,SRGFM1 ;FILL WITH BLANK FILE NAME + 08CF 47 LD B,A ;SAVE COUNT OF CHARACTERS + 08D0 218200 LD HL,CPMBUF+2 ;BEG OF FILE NAME + 08D3 11EC02 LD DE,SRDFNM+1 ;STORAGE FOR FILE NAME + 08D6 FE03 CP 3 + 08D8 DAED08 JP C,SRGFN2 ;NO DRIVE SPEC + 08DB 3A8300 LD A,(CPMBUF+3) + 08DE FE3A CP ':' ;DRIVE SPEC? + 08E0 C2ED08 JP NZ,SRGFN2 ;NONE THIS TIME + 08E3 05 DEC B + 08E4 05 DEC B + 08E5 7E LD A,(HL) + 08E6 E60F AND 0FH ;DRIVE NUMBER + 08E8 32EB02 LD (SRDFNM),A + 08EB 23 INC HL + 08EC 23 INC HL ;POINTER PAST DRIVE SPEC + 08ED 05 SRGFN2: DEC B + 08EE FA3409 JP M,SRGDFN ;FILE NAME NOW DEFAULT + 08F1 7E LD A,(HL) + 08F2 CD2109 CALL UPPER + 08F5 23 INC HL + 08F6 FE2E CP '.' + 08F8 CA2A09 JP Z,SRGFN3 ;EXTENTION + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 22 + + + 08FB 12 LD (DE),A + 08FC 13 INC DE + 08FD C3ED08 JP SRGFN2 + + 0900 7E SRGFNA: LD A,(HL) + 0901 FE20 CP ' ' + 0903 CA1B09 JP Z,SRGFNB + 0906 4F LD C,A + 0907 C5 PUSH BC + 0908 D5 PUSH DE + 0909 E5 PUSH HL + 090A 5E LD E,(HL) + 090B 0E06 LD C,CDIO + 090D CD0500 CALL BDOS + 0910 E1 POP HL + 0911 E5 PUSH HL + 0912 CD820A CALL MSGCRC ;SEND LF IF NECESSARY + 0915 E1 POP HL + 0916 D1 POP DE + 0917 C1 POP BC + 0918 CD9B04 CALL LPCHK + 091B 23 SRGFNB: INC HL + 091C 05 DEC B + 091D C20009 JP NZ,SRGFNA + 0920 C9 RET + + 0921 FE61 UPPER: CP 'a' + 0923 D8 RET C + 0924 FE7B CP 'z'+1 + 0926 D0 RET NC + 0927 D620 SUB 'a'-'A' + 0929 C9 RET + + 092A 11F402 SRGFN3: LD DE,SRDFNM+9 + 092D 78 LD A,B + 092E E603 AND 3 ;MAX OF 3 CHARACTERS + 0930 47 LD B,A + 0931 C3ED08 JP SRGFN2 + + 0934 11EB02 SRGDFN: LD DE,SRDFNM ;DEFAULT FILE NAME + 0937 215C00 LD HL,CPMFCB + 093A 060C LD B,12 + 093C C34B03 JP MOVIT + + 093F 215009 SRSWPD: LD HL,LFILDG + 0942 CD660A MSGRES: CALL MSGOUT ;MESSAGE THEN RESPONSE + 0945 CD3804 CALL CIN ;WAIT FOR CHARACTER + 0948 214E09 LD HL,CRMSG + 094B C3660A JP MSGOUT + + 094E 0D00 CRMSG: DB 0DH,0 + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 23 + + + + 0950 4C6F6164 LFILDG: DB 'Load Game Disk if it was removed.',0DH + 0972 54797065 DB 'Type to continue >',0 + 098D 4C6F6164 LFILDM: DB 'Load Disk 2, type to continue >',0 + 09B5 4C6F6164 LFILPM: DB 'Load Disk 1, type to continue >',0 + 09DD 4C6F6164 LFILGM: DB 'Load Game Disk, type to continue >',0 + + 0A08 4C6F6164 SRMSG1: DB 'Load SAVE disk then enter file name.',0DH + 0A2D 28646566 DB '(default file name is ',0 + + 0A44 292E0D SRMSG2: DB ').',0DH + 0A47 54797065 DB 'Type to continue > ',0 + + 0A64 2E00 SRMSG3: DB '.',0 + + 0A66 4E MSGOUT: LD C,(HL) + 0A67 7E LD A,(HL) + 0A68 B7 OR A + 0A69 C8 RET Z + 0A6A C5 PUSH BC + 0A6B D5 PUSH DE + 0A6C E5 PUSH HL + 0A6D 5E LD E,(HL) + 0A6E 0E06 LD C,CDIO + 0A70 CD0500 CALL BDOS + 0A73 E1 POP HL + 0A74 E5 PUSH HL + 0A75 CD820A CALL MSGCRC + 0A78 E1 POP HL + 0A79 D1 POP DE + 0A7A C1 POP BC + 0A7B CD9B04 CALL LPCHK + 0A7E 23 INC HL + 0A7F C3660A JP MSGOUT + + 0A82 3A0D01 MSGCRC: LD A,(CPMCLF) + 0A85 B7 OR A + 0A86 C8 RET Z ;NO LF AFTER CR + 0A87 7E LD A,(HL) + 0A88 FE0D CP 0DH + 0A8A C0 RET NZ ;NOT CR + 0A8B 1E0A LD E,0AH ;PRINT A LF + 0A8D 0E06 LD C,CDIO + 0A8F CD0500 CALL BDOS + 0A92 C9 RET + + + 0A93 AF RESTOR: XOR A + 0A94 32750C LD (FILTYP),A + 0A97 115C00 LD DE,CPMFCB + 0A9A 0E10 LD C,CLOSE + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 24 + + + 0A9C CD0500 CALL BDOS + 0A9F CD6C08 CALL SRGFNM + 0AA2 115C00 LD DE,CPMFCB + 0AA5 0E0F LD C,OPEN + 0AA7 CD0500 CALL BDOS + 0AAA 3C INC A + 0AAB CA4808 JP Z,SRFAIL + 0AAE 115C00 LD DE,CPMFCB + 0AB1 0E14 LD C,READS + 0AB3 CD0500 CALL BDOS + 0AB6 B7 OR A + 0AB7 C24808 JP NZ,SRFAIL + 0ABA 2AD921 LD HL,(ZCODEP) + 0ABD 110000 LD DE,ZVERS + 0AC0 19 ADD HL,DE + 0AC1 3A8000 LD A,(CPMBUF) + 0AC4 BE CP (HL) + 0AC5 C24808 JP NZ,SRFAIL ;VERSIONS DIFFER + 0AC8 2A8100 LD HL,(CPMBUF+1) + 0ACB 22070E LD (ZSTAKP),HL ;STACK POINTER + 0ACE 118300 LD DE,CPMBUF+3 + 0AD1 218721 LD HL,SRND + 0AD4 012900 LD BC,SRNDC ;TO MAKE EXTERNALS WORK + 0AD7 41 LD B,C + 0AD8 CD4B03 CALL MOVIT ;RESTORE RANDOM DATA + 0ADB 0E03 LD C,0+(((ZSTAKL*2)-1)/128) ;ONE TOO FEW + 0ADD 21090E LD HL,ZSTACK ;NEXT WRITE OUT STACK + 0AE0 C5 RESTA: PUSH BC + 0AE1 E5 PUSH HL + 0AE2 115C00 LD DE,CPMFCB + 0AE5 0E14 LD C,READS + 0AE7 CD0500 CALL BDOS + 0AEA E1 POP HL + 0AEB C1 POP BC + 0AEC B7 OR A + 0AED C24808 JP NZ,SRFAIL + 0AF0 118000 LD DE,CPMBUF + 0AF3 0680 LD B,128 + 0AF5 CD4B03 CALL MOVIT + 0AF8 0D DEC C + 0AF9 C2E00A JP NZ,RESTA + 0AFC E5 PUSH HL ;READ LAST BLOCK + 0AFD 115C00 LD DE,CPMFCB + 0B00 0E14 LD C,READS + 0B02 CD0500 CALL BDOS + 0B05 E1 POP HL + 0B06 B7 OR A + 0B07 C24808 JP NZ,SRFAIL + 0B0A 118000 LD DE,CPMBUF + 0B0D 0640 LD B,0+((ZSTAKL*2)-((((ZSTAKL*2)-1)/128)*128)) + 0B0F CD4B03 CALL MOVIT + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 25 + + + 0B12 2AD921 LD HL,(ZCODEP) + 0B15 111100 LD DE,ZSCRIP+1 + 0B18 19 ADD HL,DE + 0B19 22E80B LD (SCPLOC),HL ;LOCATION OF SCRIPT FLAG + 0B1C 7E LD A,(HL) + 0B1D E601 AND 1 ;ISOLATE SCRIPT BIT + 0B1F 32EA0B LD (SCPVAL),A ;AND SAVE + 0B22 2AD921 LD HL,(ZCODEP) + 0B25 110E00 LD DE,ZPURBT + 0B28 19 ADD HL,DE + 0B29 4E LD C,(HL) + 0B2A 2AD921 LD HL,(ZCODEP) ;POINTER TO BEGINNING OF DATA + 0B2D 0602 LD B,2 ;128 BYTE RECORDS + 0B2F C5 REST1: PUSH BC + 0B30 E5 PUSH HL + 0B31 115C00 LD DE,CPMFCB + 0B34 0E14 LD C,READS + 0B36 CD0500 CALL BDOS + 0B39 E1 POP HL + 0B3A C1 POP BC + 0B3B B7 OR A + 0B3C C25F07 JP NZ,RESTAR + 0B3F 118000 LD DE,CPMBUF + 0B42 C5 PUSH BC + 0B43 0680 LD B,128 + 0B45 CD4B03 CALL MOVIT + 0B48 C1 POP BC + 0B49 05 DEC B + 0B4A C22F0B JP NZ,REST1 + 0B4D 0602 LD B,2 + 0B4F 0D DEC C + 0B50 F22F0B JP P,REST1 + 0B53 2AE80B LD HL,(SCPLOC) + 0B56 7E LD A,(HL) + 0B57 E6FE AND 0FEH ;CLEAR SCRIPT BIT + 0B59 E5 PUSH HL + 0B5A 21EA0B LD HL,SCPVAL + 0B5D B6 OR (HL) ;OR IN VALUE FROM MEMORY + 0B5E E1 POP HL + 0B5F 77 LD (HL),A + 0B60 C30E08 JP SRCLOS ;ALL DONE + + 0B63 F5 LFILS: PUSH AF + 0B64 3A750C LD A,(FILTYP) + 0B67 FE03 CP 3 ;.DAT FILE ALREADY OPEN? + 0B69 CAD30B JP Z,LFILR ; YES. RETURN. + 0B6C B7 OR A ; NO. SOME OTHER TYPE OPEN? + 0B6D C2D30B JP NZ,LFILR ; YES. RETURN. + 0B70 11C702 LFILS1: LD DE,FNDAT ; NO. ^ DATA FILE NAME + 0B73 3E03 LD A,3 ;OPEN TYPE 3 + 0B75 CD1B02 CALL OPNDK1 ;TRY TO OPEN FILE + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 26 + + + 0B78 C2D30B JP NZ,LFILR ;OPEN .DAT FILE COMPLETE? + 0B7B ; YES. RETURN. + 0B7B 3AB501 LD A,(TWODSK) ;CHECK IF 1 OR 2 DISKS FOR GAME + 0B7E FE01 CP 1 ;IF = 1 THEN 2 DISKS + 0B80 CA8C0B JP Z,LFILF ;SO GO TRY OTHER TYPE FILES + 0B83 21DD09 LD HL,LFILGM ;ELSE ASK FOR CORRECT DISK + 0B86 CD4209 CALL MSGRES + 0B89 C3700B JP LFILS1 ;AND TRY AGAIN + 0B8C AF LFILF: XOR A ; NO. SET FILTYP=0 + 0B8D 32750C LD (FILTYP),A ;OPEN FAILED TRY OTHER TYPE + 0B90 C3D30B JP LFILR + + 0B93 F5 LFILD: PUSH AF + 0B94 3A750C LD A,(FILTYP) + 0B97 FE02 CP 2 ;.PUR FILE ALREADY OPEN? + 0B99 CAD30B JP Z,LFILR ; YES.ALREADY OPEN + 0B9C CDD50B CALL LFILC ;CLOSE EXISTING FILE IF ANY + 0B9F 11D302 LFILD1: LD DE,FNPUR + 0BA2 3E02 LD A,2 + 0BA4 CD1B02 CALL OPNDK1 ;TRY TO OPEN PURELOAD FILE + 0BA7 C2D30B JP NZ,LFILR ;OPEN OK + 0BAA 218D09 LD HL,LFILDM + 0BAD CD4209 CALL MSGRES ;ASK TO LOAD DISK + 0BB0 C39F0B JP LFILD1 ;TRY AGAIN + + 0BB3 F5 LFILP: PUSH AF + 0BB4 3A750C LD A,(FILTYP) + 0BB7 FE01 CP 1 ;PRELOAD TYPE? + 0BB9 CAD30B JP Z,LFILR ;OPEN + 0BBC CDD50B CALL LFILC + 0BBF 11DF02 LFILP1: LD DE,FNPRE + 0BC2 3E01 LD A,1 + 0BC4 CD1B02 CALL OPNDK1 + 0BC7 C2D30B JP NZ,LFILR ;OPEN OK + 0BCA 21B509 LD HL,LFILPM + 0BCD CD4209 CALL MSGRES ;LOAD PROPER DISK + 0BD0 C3BF0B JP LFILP1 + + 0BD3 F1 LFILR: POP AF + 0BD4 C9 RET + + 0BD5 B7 LFILC: OR A + 0BD6 C8 RET Z ;NONE OPEN + 0BD7 115C00 LD DE,CPMFCB + 0BDA 0E10 LD C,CLOSE + 0BDC CD0500 CALL BDOS + 0BDF AF XOR A + 0BE0 32750C LD (FILTYP),A + 0BE3 C9 RET + + ;DATA + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 27 + + + + 0BE4 00 STAFLG: DB 0 ;0FFH WHEN IN STATUS LINE MODE + 0BE5 00 COUTDC: DB 0 ;CHARACTER COUNT UNDER STATUS LINE + 0BE6 00 RDFLG: DB 0 ;0 FOR FIRST READ + 0BE7 00 PRFLG: DB 0 ;0 FOR FIRST PRINT + 0BE8 0000 SCPLOC: DW 0 ;SCRIPT LOCATION + 0BEA 00 SCPVAL: DB 0 ;SCRIPT VALUE + 0BEB 0000 DBUFP: DW 0 ;DSK POINTER + 0BED 00 NCHARS: DB 0 + 0BEE CHARS: DS CPLMAX + 0C73 EE0B CHRPNT: DW CHARS + + 0C75 00 FILTYP: DB 0 ;0 FOR NONE, 1 FOR PRE, 2 FOR PUR, 3 FOR DAT + 0C76 17 MORCNT: DB 23 + + ;(PUT IN CODE SEGMENT TO PRESERVE COMMON ZORKBODY) + 0C77 PDL: DS LPDL ;CONTROL STACK + 0E07 C90F ZSTAKP: DW ZSTACK+(2*ZSTAKL) ;POINTER TO CURRENT ZSTACK + 0E09 ZSTACK: DS ZSTAKL*2 ;ZSTACK + 0FC9 PGTBL: DS MAXPGS ;PAGE NUMBER, 0 ALWAYS IN MEMORY, THUS 0=FREE + 1009 PGTBLF: DS MAXPGS ;NEXT LINK POINTER, 0FFH IMPLIES END POINT + 1049 PGTBLB: DS MAXPGS ;PREVIOUS LINK POINTER + 0040 PGTFD EQU PGTBLF-PGTBL + 0080 PGTBD EQU PGTBLB-PGTBL + + 1089 0D555044 VRS: DB 0DH,'UPDATED 2.5.85',0DH,0 + 109A 0D564552 VRLINE: DB 0DH,'VERSION C',0DH,0 + ; + ; ********************************************************************** + ; * * + ; * WARMSTART ENTRY * + ; * * + ; ********************************************************************** + ; + ; + ; MAIN BODY OF CODE STARTS HERE. + ; + 10A6 AF BODY: XOR A + 10A7 32CE21 LD (ZPCFLG),A ;DISABLE TIME IN STATUS LINE, NO SPLIT FILE, NOT TANDY + 10AA 32D521 LD (MPCFLG),A ;NO VALID MEMORY IN FROM DISK (MPCPNT NOT VALID) + 10AD 32DC21 LD (PGTOP),A ;SET TOP OF LIST PAGE + + 10B0 0E19 LD C,RETCUR ;GET CURRENT DEFAULT DRIVE + 10B2 CD0500 CALL BDOS ;RETS IN A + 10B5 5F LD E,A ;SET DEFAULT DRIVE + 10B6 0E0E LD C,CPMSEL ;THIS SEEMS REDUNDENT BUT THE MACHINE IS NOT + 10B8 CD0500 CALL BDOS ;RECOGNIZING RESETS FROM BOOT DRIVE DONE BEFORE + 10BB ;STARTING THE GAME + + ; + ; INITIALIZE ZSTACK + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 28 + + + ; + 10BB 3E01 LD A,1 + 10BD 32A821 LD (ZSTAKC),A ;INITIALIZE ZSTACK POSITION COUNTER + 10C0 21C90F LD HL,ZSTACK+(2*ZSTAKL) + 10C3 22070E LD (ZSTAKP),HL ;SAVE THE LOCATION OF THE BOTTOM OF ZSTACK IN + ; ZSTACK POINTER + ; + ; INITIALIZE PAGE TABLES + ; + 10C6 11C90F LD DE,PGTBL ;DE ^ TOP OF PAGE TABLE + 10C9 010040 LD BC,0+(MAXPGS*256) ;FOR NUMBER OF PAGES (IN B) + ; + 10CC START1: + ; INITIALIZE PGTBL + 10CC AF XOR A + 10CD 12 LD (DE),A ;(PGTBL+PAGE NUMBER) <= 0 + ; FREE THE PAGE (NO PAGE IN MEMORY) + ; + 10CE 214000 LD HL,PGTFD ;HL <= MAXIMUM NUMBER OF PAGES + ; USED AS AN OFFSET INTO PGTBLF + ; + ; INITIALIZE FOWARD POINTER + 10D1 19 ADD HL,DE ;HL ^ PAGE FORWARD POINTER TABLE SLOT + 10D2 71 LD (HL),C ;SAVE CURRENT POINTER + 10D3 34 INC (HL) ;ADD 1 TO MAKE IT A FORWARD POINTER + ; + ; INITIALIZE PREVIOUS POINTER + 10D4 218000 LD HL,PGTBD ;HL ^ PAGE PREVIOUS POINTER TABLE BASE ADDRESS + 10D7 19 ADD HL,DE ;ADD OFFSET + 10D8 71 LD (HL),C ;SAVE CURRENT POINTER + 10D9 35 DEC (HL) ;SUBTRACT 1 TO MAKE IT A PREVIOUS POINTER + ; + ; UPDATE + 10DA 0C INC C ;NEXT PAGE + 10DB 13 INC DE ;NEXT SLOT IN TABLES + ; + ; TEST LOOP FOR DONE + 10DC 05 DEC B ;DECREMENT NUMBER OF SLOTS REMAINING + 10DD C2CC10 JP NZ,START1 ;>0? YES. CONTINUE LOOPING. + ; + ; CORRECT FOR NO FORWARD POINTER FOR LAST PAGE + ; + 10E0 213F00 LD HL,PGTFD-1 + 10E3 19 ADD HL,DE + 10E4 36FF LD (HL),0FFH + ; + ; SET BOTTOM PAGE NO. + ; + 10E6 3E3F LD A,MAXPGS-1 + 10E8 32DD21 LD (PGBOT),A + ; + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 29 + + + ; COMPUTE ZCODE STARTING ADDRESSS + ; + 10EB 21EB21 LD HL,LMEMRY ;POINT HL PAST ZIP + 10EE 11FF00 LD DE,0FFH ;ADJUST ADDRESS TO A PAGE BOUNDRY + 10F1 19 ADD HL,DE + 10F2 2E00 LD L,0 + 10F4 22D921 LD (ZCODEP),HL ;SAVE ZCODE STARTING ADDRESS + ; + ; SET UP FILE NAMES FOR DAT, PRE, PUR AND SAV + ; + 10F7 CDAA02 CALL SETFIL ;APPEND GAME NAME PREFIX TO FILE NAME EXTENSIONS + ; + ; RESET FILE TYPE + ; + 10FA AF XOR A ;RESET FILTYP + 10FB 32750C LD (FILTYP),A + ; + ; INITIALIZE TERMINAL + ; + 10FE 211001 LD HL,ITRMST ;POINT TO TERMINAL INITIALIZATION STRING + 1101 CD7E02 CALL PCSTR ; FOR HOME, CLEAR SCREEN AND PRINT IT + ; + ; INITIALIZE TERMINAL RELATED COUNTERS + ; + 1104 3A0401 LD A,(CPMLPP) ;INITIALIZE LINES/PAGE (EXCLUDING STATUS LINE) + 1107 3D DEC A ;COUNTER (MORCNT) =(CPMLPP)-1 + 1108 32760C LD (MORCNT),A ; WHICH TELLS THE PROGRAM WHEN TO PRINT ....MORE.... + 110B AF XOR A ;A<=0 + 110C 32ED0B LD (NCHARS),A ;RESET (NCHARS) + 110F 21EE0B LD HL,CHARS ;SET UP CHARACTERS/LINE + 1112 22730C LD (CHRPNT),HL + ; + ; GET THE FIRST SECTOR OF ZCODE + ; + 1115 2AD921 LD HL,(ZCODEP) ;^ TOP OF ZCODE BUFFER + 1118 AF XOR A + 1119 CDF702 CALL GETDSK ;READ IN FIRST SECTION + ; + ; EXTRACT GAME DATA FROM ZCODE HEADER + ; + 111C 2AD921 LD HL,(ZCODEP) ;HL ^ TOP OF ZCODE BUFFER + 111F 110400 LD DE,ZENDLD ;DE <= OFFSET TO NON-PRELOADED ZCODE + 1122 19 ADD HL,DE ;HL ^ START OF NON-PRELOADED ZCODE + 1123 56 LD D,(HL) ;GET MSB OF ENDLOAD POINTER + 1124 23 INC HL ; ADD 1 + 1125 5E LD E,(HL) ;GET LSB OF ENDLOAD POINTER + 1126 210002 LD HL,200H ;HL <= 256 + 1129 19 ADD HL,DE ;HL <= ENDLOAD POINTER + 200H + 112A 7C LD A,H ;A <= MSB + 112B E6FE AND 0FEH ; + 112D 67 LD H,A ; + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 30 + + + 112E 2E00 LD L,0 ; + 1130 2B DEC HL ;ALL THIS TO GET TO BLOCK BOUNDRY + 1131 EB EX DE,HL ;DE <= CORRECTED ENDLOAD POINTER + 1132 010400 LD BC,ZENDLD ;BC <= OFFSET TO NON-PRELOADED ZCODE + 1135 2AD921 LD HL,(ZCODEP) ;HL ^ TOP OF ZCODE BUFFER + 1138 09 ADD HL,BC ;HL ^ START OF NON-PRELOADED ZCODE + 1139 72 LD (HL),D ;SAVE MSB OF CORRECTED ENDLOAD POINTER + 113A 23 INC HL + 113B 73 LD (HL),E ;SAVE LSB OF CORRECTED ENDLOAD POINTER + 113C 2AD921 LD HL,(ZCODEP) ;HL ^ TOP OF ZCODE BUFFER + 113F D5 PUSH DE ;SAVE CORRECTED ENDLOAD POINTER ON STACK + 1140 19 ADD HL,DE ;HL ^ END OF PRELOAD + 1141 EB EX DE,HL ;DE ^ END OF PRELOAD + 1142 CD0902 CALL MEMTOP ;DETERMINE WHERE THE TOP OF MEMORY IS (IN HL) + 1145 EB EX DE,HL ;DE <= TOP OF MEMORY, HL <= END OF THE PRELOAD + 1146 CD251D CALL HLGEDE ;CARRY FLAG SET IF HL G.E. DE + 1149 D1 POP DE ;RESTORE CORRECTED ENDLOAD POINTER + 114A DC0602 CALL C,ZER ;NO ROOM FOR ANY BUFFERS + 114D 7A LD A,D + 114E 0F RRCA + 114F E67F AND 7FH + 1151 57 LD D,A ;NUMBER OF PAGES IN REST OF THE PRELOAD + 1152 3C INC A + 1153 32B921 LD (ZMEMT),A ;PAGE NUMBER + 1156 2AD921 LD HL,(ZCODEP) ;^ START OF ZCODE BUFFER + 1159 010002 LD BC,200H + 115C 1E00 LD E,0 + ; + ; LOAD PRELOAD + ; + 115E 7A START2: LD A,D ;A <= PAGES REMAINING TO BE LOADED + 115F B7 OR A ;DONE? + 1160 CA7311 JP Z,START3 ; YES. + 1163 15 DEC D + 1164 09 ADD HL,BC + 1165 1C INC E + 1166 7B LD A,E + 1167 C5 PUSH BC + 1168 D5 PUSH DE + 1169 E5 PUSH HL + 116A CDF702 CALL GETDSK + 116D E1 POP HL + 116E D1 POP DE + 116F C1 POP BC + 1170 C35E11 JP START2 + + 1173 2AD921 START3: LD HL,(ZCODEP) + 1176 EB EX DE,HL + 1177 210100 LD HL,ZSWAP + 117A 19 ADD HL,DE + 117B 7E LD A,(HL) + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 31 + + + 117C E601 AND 1 + 117E C40602 CALL NZ,ZER ;SWAPPED + 1181 210700 LD HL,ZSTART+1 + 1184 19 ADD HL,DE + 1185 7E LD A,(HL) + 1186 32A621 LD (ZPCL),A + 1189 2B DEC HL + 118A 7E LD A,(HL) + 118B E601 AND 1 + 118D 32A721 LD (ZPCL+1),A + 1190 7E LD A,(HL) + 1191 0F RRCA + 1192 E67F AND 7FH + 1194 32A521 LD (ZPCH),A + 1197 210C00 LD HL,ZGLOBA + 119A 19 ADD HL,DE ;GET RELATIVE ADDRESS OF GLOBAL TABLE + 119B D5 PUSH DE + 119C 56 LD D,(HL) + 119D 23 INC HL + 119E 5E LD E,(HL) + 119F EB EX DE,HL + 11A0 D1 POP DE + 11A1 19 ADD HL,DE ;REAL ADDRESS OF GLOBAL TABLE + 11A2 22C521 LD (GLOBAL),HL ;STORE IT + 11A5 211800 LD HL,ZFWORD + 11A8 19 ADD HL,DE ;GET RELATIVE ADDRESS OF FWORDS TABLE + 11A9 D5 PUSH DE + 11AA 56 LD D,(HL) + 11AB 23 INC HL + 11AC 5E LD E,(HL) + 11AD EB EX DE,HL + 11AE D1 POP DE + 11AF 19 ADD HL,DE ;REAL ADDRESS OF FWORDS TABLE + 11B0 22C821 LD (FWORDS),HL ;STORE IT + 11B3 210400 LD HL,ZENDLD ;CALCULATE ^ TO BEGINNING OF PAGE BUFFERS + 11B6 19 ADD HL,DE + 11B7 D5 PUSH DE + 11B8 56 LD D,(HL) + 11B9 23 INC HL + 11BA 5E LD E,(HL) + 11BB E1 POP HL + 11BC 19 ADD HL,DE + 11BD 23 INC HL + 11BE 22D721 LD (PGBUFP),HL ;STORE IT + 11C1 2B DEC HL ;CALCULATE NO. OF AVAILABLE PAGES + 11C2 EB EX DE,HL ;TOP LOCATION + 11C3 CD0902 CALL MEMTOP + 11C6 7C LD A,H + 11C7 92 SUB D + 11C8 0F RRCA + 11C9 E67F AND 7FH ;SWAPPING SPACE + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 32 + + + 11CB FE40 CP MAXPGS + 11CD DAD211 JP C,STAR3A + 11D0 3E40 LD A,MAXPGS + 11D2 32DB21 STAR3A: LD (NPGS),A ;SAVE NUMBER OF PAGES + 11D5 3D DEC A + 11D6 32DD21 LD (PGBOT),A + 11D9 210910 LD HL,PGTBLF + 11DC CD081F CALL HLOFF + 11DF 36FF LD (HL),0FFH ;SET LAST PAGE + ; + ; INITIALIZE RANDOM NUMBER + ; + 11E1 0605 LD B,5 + 11E3 21FFFF LD HL,0FFFFH + 11E6 22AC21 LD (SHIFT),HL + 11E9 22AE21 LD (SHIFT+2),HL + 11EC 21E60B LD HL,RDFLG ;SET FLAG TO 1ST READ + 11EF 3600 LD (HL),0 + 11F1 CDEE1B START4: CALL RND + 11F4 05 DEC B + 11F5 C2F111 JP NZ,START4 + ; + ; + ; + 11F8 AF XOR A + 11F9 32B721 LD (NOLPT),A ;USE LPT + 11FC 2AD921 LD HL,(ZCODEP) + 11FF 110100 LD DE,ZSWAP + 1202 19 ADD HL,DE + 1203 7E LD A,(HL) + 1204 47 LD B,A + 1205 3A5201 LD A,(BSTLIN) ;IS THERE A STATUS LINE? + 1208 B7 OR A + 1209 78 LD A,B + 120A C20F12 JP NZ,START5 + 120D F610 OR ZSTATB ;INDICATE NO STATUS LINE + 120F 77 START5: LD (HL),A + ; JP MLOOP ;COMMENTED OUT FOR FALL THROUGH + ; + ; ********************************************************************** + ; * * + ; * MAINLOOP * + ; * * + ; ********************************************************************** + ; + ; + ;MAIN LOOP, READ AN INSTRUCTION AND ITS ARGS, THEN DISPATCH + + 1210 AF MLOOP: XOR A + 1211 32C321 LD (ARGCNT),A ;ZERO ARG COUNT + 1214 CD5A1D CALL NEXTPC ;GET NEXT OPCODE IN A + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 33 + + + 1217 32C421 LD (OPCODE),A ;SAVE IT + 121A FE80 CP 128 + 121C DAB612 JP C,OP2 ;2-OP + 121F FEB0 CP 176 + 1221 DA8D12 JP C,OP1 ;1-OP + 1224 FEC0 CP 192 + 1226 DA8012 JP C,OP0 ;0-OP + ; + ; HANDLE AN X-OP + ; + 1229 CD5A1D OPEXT: CALL NEXTPC ;GET VAR TYPES, THIS IS AN EXT OP + 122C 11BB21 LD DE,ARG1 + 122F 0604 LD B,4 ;MAX NUMBER OF ARGS + 1231 4F LD C,A + 1232 C5 OPEXTL: PUSH BC + 1233 D5 PUSH DE + 1234 79 LD A,C + 1235 E6C0 AND 0C0H ;ISOLATE BIT7, BIT6 TO DETERMINE ARG TYPE + 1237 CCED12 CALL Z,GETLNG ;00=LONG IMMEDIATE + 123A FE80 CP 80H + 123C CCFA12 CALL Z,GETVAR ;10=VARIABLE + 123F FE40 CP 40H + 1241 CCE412 CALL Z,GETSHT ;01=SHORT IMMEDIATE + 1244 D1 POP DE + 1245 C1 POP BC + 1246 FEC0 CP 0C0H ;11=NO MORE VARIABLES + 1248 CA5D12 JP Z,OPEXTF ;ALL DONE? + 124B EB EX DE,HL ;NO. STORE VALUE + 124C 73 LD (HL),E + 124D 23 INC HL + 124E 72 LD (HL),D + 124F 23 INC HL + 1250 EB EX DE,HL ;POINTER BACK IN DE + 1251 21C321 LD HL,ARGCNT + 1254 34 INC (HL) ;ONE MORE ARG + 1255 79 LD A,C + 1256 07 RLCA + 1257 07 RLCA ;GET TO NEXT ARG TYPE + 1258 4F LD C,A + 1259 05 DEC B ;DECREMENT ARG COUNT + 125A C23212 JP NZ,OPEXTL ;LOOP FOR MORE + ; + ; DISPATCH THE X-OP + ; + 125D 216214 OPEXTF: LD HL,OPEXTT ;COMPUTE DISPATCH POINTER + 1260 3AC421 LD A,(OPCODE) ;RETRIEVE THE OPCODE + 1263 FEE0 CP 224 ;IS IT AN EXTENDED 2-OP? + 1265 DAD712 JP C,OP2EX ; YES. + 1268 D6E0 SUB 224 ; NO. + 126A FE0A CP OPEXTM ;IS IT A LEGAL X-OP? + 126C D2BF15 JP NC,BADOP ; NO. + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 34 + + + ; + ; GENERALIZED DISPATCH + ; + 126F OPDSPH: + 126F 87 ADD A,A ;FORM A WORD OFFSET (*2) + 1270 4F LD C,A ;PUT OFFSET INTO BC + 1271 0600 LD B,0 + 1273 09 ADD HL,BC ;ADD OFFSET TO DISPATCH POINTER + 1274 5E LD E,(HL) ;ADDRESS LSB + 1275 23 INC HL + 1276 56 LD D,(HL) ;ADDRESS MSB + 1277 2ABB21 LD HL,(ARG1) ;FIRST ARG + 127A EB EX DE,HL ;HL ^ TABLE ADDRESS OF ROUTINE + ; DE <= FIRST ARG + 127B 3AC321 LD A,(ARGCNT) ;B <= ARG COUNT + 127E 47 LD B,A + 127F E9 JP (HL) ;GO TO IT + ; + ; HANDLE A 0-OP + ; + 1280 D6B0 OP0: SUB 176 ;ADJUST VALUE + 1282 FE0E CP OP0M ;IS IT A LEGAL 0-OP? + 1284 D2BF15 JP NC,BADOP ; NO. + 1287 21F413 LD HL,OP0T ; YES. HL ^ 0-OP TABLE + 128A C36F12 JP OPDSPH ;DISPATCH IT + ; + ; HANDLE A 1-OP + ; + 128D E630 OP1: AND 30H ;1 OP, ISOLATE BITS 5,4 + 128F CCED12 CALL Z,GETLNG ;00=LONG IMMEDIATE + 1292 FE10 CP 10H + 1294 CCE412 CALL Z,GETSHT ;01=SHORT IMMEDIATE + 1297 FE20 CP 20H + 1299 CCFA12 CALL Z,GETVAR ;10=VARIABLE + 129C 3E01 LD A,1 + 129E 32C321 LD (ARGCNT),A ;1 ARG + 12A1 22BB21 LD (ARG1),HL ;STORE IT + 12A4 3AC421 LD A,(OPCODE) ;RESTORE OPCODE + 12A7 E6CF AND 0CFH ;(NOT 30H) TURN OFF MODE BITS + 12A9 D680 SUB 128 ;ADJUST VALUE + 12AB FE10 CP OP1M ;LEGAL 1-OP? + 12AD D2BF15 JP NC,BADOP ; NO. + 12B0 211014 LD HL,OP1T ; YES. HL ^ 1-OP TABLE + 12B3 C36F12 JP OPDSPH ;DISPATCH IT + ; + ; HANDLE A 2-OP + ; + 12B6 E640 OP2: AND 40H ;ISOLATE 1ST. ARG BIT + 12B8 C4FA12 CALL NZ,GETVAR ;1=VARIABLE + 12BB CCE412 CALL Z,GETSHT ;0=SHORT IMMEDIATE + 12BE 22BB21 LD (ARG1),HL ;STORE ARG1 + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 35 + + + 12C1 3AC421 LD A,(OPCODE) ;RESTORE OPCODE + 12C4 E620 AND 20H ;ISOLATE 2ND. ARG BIT + 12C6 C4FA12 CALL NZ,GETVAR ;1=VARIABLE + 12C9 CCE412 CALL Z,GETSHT ;2=SHORT IMMEDIATE + 12CC 22BD21 LD (ARG2),HL ;STORE ARG 2 + 12CF 3E02 LD A,2 + 12D1 32C321 LD (ARGCNT),A ;TWO ARGS + 12D4 3AC421 LD A,(OPCODE) ;RESTORE OPCODE + 12D7 E61F OP2EX: AND 1FH ;(NOT 0E0H) TURN OFF MODE BITS + 12D9 FE19 CP OP2M ;LEGAL 2-OP? + 12DB D2BF15 JP NC,BADOP ; NO. + 12DE 213014 LD HL,OP2T ; YES. HL ^ 2-OP TABLE + 12E1 C36F12 JP OPDSPH ;DISPATCH IT + ; + ;************************************* + ;* OPCODE ARGUMENT FETCH SUBROUTINES * + ;************************************* + ; + ; ----------------------- + ; FETCH A SHORT IMMEDIATE + ; ----------------------- + 12E4 F5 GETSHT: PUSH AF ;SAVE OPCODE + 12E5 CD5A1D CALL NEXTPC ;GET NEXT ZBYTE + 12E8 6F LD L,A ;MAKING IT THE LSB OF ARGUMENT + 12E9 2600 LD H,0 ;MSB IS 0 + 12EB F1 POP AF ;RESTORE OPCODE + 12EC C9 RET + ; ---------------------- + ; FETCH A LONG IMMEDIATE + ; ---------------------- + 12ED F5 GETLNG: PUSH AF ;SAVE OPCODE + 12EE CD5A1D CALL NEXTPC ;GET NEXT ZBYTE + 12F1 67 LD H,A ;MAKING IT THE MSB OF ARGUMENT + 12F2 E5 PUSH HL ;SAVE IT ON THE STACK + 12F3 CD5A1D CALL NEXTPC ;GET NEXT ZBYTE + 12F6 E1 POP HL ;RESTORE MSB OF ARGUMENT + 12F7 6F LD L,A ;AND FILL IN LSB OF ARGUMENT + 12F8 F1 POP AF ;RESTORE OPCODE + 12F9 C9 RET + ; ---------------- + ; FETCH A VARIABLE + ; ---------------- + 12FA F5 GETVAR: PUSH AF ;GET VAR, FIRST FIND TYPE + 12FB CD5A1D CALL NEXTPC + 12FE B7 OR A + 12FF CA2213 JP Z,GETVRS ;FROM STACK + 1302 FE10 GETVR1: CP 16 + 1304 D21613 JP NC,GETVRG ;GLOBAL + 1307 3D GETVRL: DEC A ;LOCAL + 1308 87 ADD A,A + 1309 5F LD E,A + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 36 + + + 130A 1600 LD D,0 + 130C 218721 LD HL,LOCALS + 130F 19 GETVL1: ADD HL,DE ;POINTER TO VARIABLE + 1310 56 LD D,(HL) + 1311 23 INC HL + 1312 5E LD E,(HL) + 1313 EB EX DE,HL ;RETURN VALUE IN HL + 1314 F1 POP AF + 1315 C9 RET + ; + 1316 D610 GETVRG: SUB 16 + 1318 5F LD E,A ;GET GLOBAL + 1319 1600 LD D,0 + 131B 2AC521 LD HL,(GLOBAL) + 131E 19 ADD HL,DE ;PRE ADD SO IT GETS DONE TWICE + 131F C30F13 JP GETVL1 + ; + 1322 CD451D GETVRS: CALL POPSTK ;VAR FROM STACK + 1325 F1 POP AF + 1326 C9 RET + ; + ;********************* + ;* MISC. SUBROUTINES * + ;********************* + 1327 AF RET0: XOR A ;RETURN 0 + 1328 6F PUTBYT: LD L,A + 1329 2600 LD H,0 + 132B CD3113 PUTVAL: CALL PUTVLC ;STORE VALUE + 132E C31012 JP MLOOP + ; + 1331 E5 PUTVLC: PUSH HL ;SAVE VALUE + 1332 CD5A1D CALL NEXTPC ;GET TYPE + 1335 E1 POP HL + 1336 B7 PUTVR1: OR A + 1337 CA2C1D JP Z,PSHSTK ;SAVE ON STACK AND RETURN + 133A EB EX DE,HL ;VALUE IN DE + 133B FE10 CP 16 + 133D D24D13 JP NC,PUTVLG ;GLOBAL + 1340 3D PUTVLL: DEC A ;LOCAL + 1341 87 ADD A,A + 1342 4F LD C,A + 1343 0600 LD B,0 + 1345 218721 LD HL,LOCALS + 1348 09 PUTVL1: ADD HL,BC ;COMPUTE ADDRESS + 1349 72 LD (HL),D + 134A 23 INC HL + 134B 73 LD (HL),E + 134C C9 RET + ; + 134D D610 PUTVLG: SUB 16 + 134F 4F LD C,A ;STORE GLOBAL + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 37 + + + 1350 0600 LD B,0 + 1352 2AC521 LD HL,(GLOBAL) ;GLOBAL POINTER + 1355 09 ADD HL,BC ;PRE ADD + 1356 C34813 JP PUTVL1 + ; + ;********************* + ;* DATA MANIPULATION * + ;********************* + ; + ; ----------------- + ; RECALL A VARIABLE + ; ----------------- + 1359 F5 VARGET: PUSH AF ;SAVE OPCODE + 135A B7 OR A ;IF NON-ZERO + 135B C20213 JP NZ,GETVR1 ; THEN GET A VARIABLE FROM LOCAL OR GLOBAL TABLE + ; ELSE TAKE VAR OFF STACK + 135E F1 VARGTS: POP AF ;RESTORE OPCODE + 135F CD451D CALL POPSTK ;POP A WORD FROM ZSTACK + 1362 C32C1D JP PSHSTK ;PUT IT BACK AND RETURN THE VALUE IN HL + ; ---------------- + ; STORE A VARIABLE + ; ---------------- + 1365 B7 VARPUT: OR A ;IF NON-ZERO + 1366 C23613 JP NZ,PUTVR1 ; THEN PUT A VARIABLE IN LOCAL OR GLOBAL TABLE + ; ELSE REPLACE A WORD ON Z-STACK + 1369 E5 VARPTS: PUSH HL ;SAVE NEW VALUE + 136A CD451D CALL POPSTK ;POP OLD WORD OFF Z-STACK + 136D E1 POP HL ;RESTORE NEW VALUE + 136E C32C1D JP PSHSTK ;AND PUSH IT ON TOP OF ZSTACK + ; + ;************************ + ;* PREDICATE PROCESSING * + ;************************ + ; + ; --------------- + ; PREDICATE FAILS + ; --------------- + 1371 CD5A1D PREDF: CALL NEXTPC ;FETCH NEXT BYTE OF ZCODE + 1374 B7 OR A + 1375 F28713 JP P,PREDB ;BRANCH IF < 128 + 1378 E640 PREDNB: AND 40H ;CHECK FOR MULTI BYTE HACK + 137A CC5A1D CALL Z,NEXTPC ;GET NEXT BYTE IF SO + 137D C31012 JP MLOOP ;CONTINUE IN SEQUENCE + ; ------------------ + ; PREDICATE SUCCEEDS + ; ------------------ + 1380 CD5A1D PREDS: CALL NEXTPC ;FETCH NEXT BYTE OF ZCODE + 1383 B7 OR A ;IF BIT 7 IS NOT SET + 1384 F27813 JP P,PREDNB ;BRANCH ON PREDICATE FAILURE + ; ELSE FALL THROUGH TO PREDB + ; ---------------- + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 38 + + + ; PERFORM A BRANCH + ; ---------------- + 1387 47 PREDB: LD B,A ;SAVE OPCODE + 1388 E640 AND 40H ;LONG BRANCH? + 138A CA9613 JP Z,PREDLB ; YES. (BIT 6 WAS OFF) + ; NO. SHORT BRANCH + 138D 78 LD A,B ;RESTORE OPCODE + 138E E63F AND 3FH ;FORM SHORT OFFSET + 1390 4F LD C,A ;USE AS LSB OF BRANCH OFFSET + 1391 0600 LD B,0 ;ZERO MSB OF OFFSET + 1393 C3AA13 JP PREDB1 ;SIMULATE LONG BRANCH TO A CLOSE PLACE + ; + ; HANDLE A LONG BRANCH + 1396 78 PREDLB: LD A,B ;RESTORE OPCODE + 1397 E63F AND 3FH ;FORM MSB OF OFFSET + 1399 47 LD B,A ;B <= MSB OF OFFSET + 139A C5 PUSH BC + 139B CD5A1D CALL NEXTPC ;GET SECOND BYTE + 139E C1 POP BC + 139F 4F LD C,A ;C <= LSB OF OFFSET + 13A0 78 LD A,B ;A <= MSB OF OFFSET + 13A1 E620 AND 20H ;CHECK SIGN OF 14 BIT VALUE + 13A3 CAAA13 JP Z,PREDB1 ;POSITIVE + 13A6 78 LD A,B ;ELSE EXTEND THE SIGN (A <= MSB) + 13A7 F6C0 OR 0C0H ;AND MAKE THE FULL WORD NEG + 13A9 47 LD B,A ;SAVE THE RESULT IN B + ; + ; BRANCH TO THE Z-ADDRESS AT $(ZPC) + OFFSET (IN BC) + ; (ZPC RELATIVE ADDRESSING) + 13AA 78 PREDB1: LD A,B + 13AB B1 OR C ;IS OFFSET=0? + 13AC CA7F14 JP Z,RFALSE ; YES. DO AN RFALSE + 13AF 0B DEC BC + 13B0 78 LD A,B + 13B1 B1 OR C ;WAS OFFSET=1 + 13B2 CA7614 JP Z,RTRUE ; YES. DO AN RTRUE + 13B5 0B PREDB3: DEC BC ;2 NOW SUBTRACTED FROM JUMP ADDRESS + 13B6 60 LD H,B ;HL <= JUMP ADDRESS + 13B7 69 LD L,C + 13B8 22CA21 LD (ZPCOFF),HL ;ZPCOFF <= JUMP ADDRESS + 13BB 2AA621 LD HL,(ZPCL) ;HL <= LOW ORDER 9 BITS OF ZIP PROGRAM COUNTER + 13BE 59 LD E,C ;E <= LSB OF JUMP ADDRESS + 13BF 78 LD A,B ;A <= MSB OF JUMP ADDRESS + 13C0 E601 AND 1 + 13C2 57 LD D,A ;ZPCL ADDER + 13C3 78 LD A,B ;ARITHMETICALLY SHIFT B RIGHT 1 + 13C4 07 RLCA ;FIRST SET CARRY + 13C5 78 LD A,B + 13C6 1F RRA + 13C7 47 LD B,A ;CUTE + 13C8 19 ADD HL,DE + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 39 + + + 13C9 7C LD A,H + 13CA E602 AND 2 + 13CC CAD213 JP Z,PREDB2 ;NO OVERFLOW + 13CF 25 DEC H + 13D0 25 DEC H ;OVERFLOW + 13D1 04 INC B + 13D2 22A621 PREDB2: LD (ZPCL),HL ;STORE LOW BYTES + 13D5 21A521 LD HL,ZPCH ;MODIFY UPPER + 13D8 78 LD A,B + 13D9 B7 OR A + 13DA CAE613 JP Z,PREDB4 ;NO CHANGE IN PACE, DO FASTER JUMP + 13DD 86 ADD A,(HL) + 13DE 77 LD (HL),A + 13DF AF XOR A + 13E0 32CE21 LD (ZPCFLG),A ;CHANGED PAGES + 13E3 C31012 JP MLOOP ;FINISHED + ; + 13E6 2ACC21 PREDB4: LD HL,(ZPCPNT) + 13E9 EB EX DE,HL + 13EA 2ACA21 LD HL,(ZPCOFF) + 13ED 19 ADD HL,DE ;CALCULATE NEW PC POINTER + 13EE 22CC21 LD (ZPCPNT),HL + 13F1 C31012 JP MLOOP + ; + ; ********************************************************************** + ; * * + ; * OPCODE PROCESSING SECTION * + ; * * + ; ********************************************************************** + ; + ; **************************** + ; * DISPATCH TABLES * + ; **************************** + ; + ; ----- + ; 0-OPS + ; ----- + 13F4 7614 OP0T: DW RTRUE ;0 + 13F6 7F14 DW RFALSE ;1 + 13F8 8514 DW PRINTI ;2 + 13FA B714 DW PRINTR ;3 + 13FC C014 DW ZNOP ;4 + 13FE C314 DW ZSAVE ;5 + 1400 C614 DW ZRSTOR ;6 + 1402 C914 DW ZRSTAR ;7 + 1404 CC14 DW RSTACK ;8 + 1406 D514 DW FSTACK ;9 + 1408 DB14 DW ZQUIT ;10 + 140A DE14 DW CRLF ;11 + 140C E414 DW USL ;12 + 140E EA14 DW VERIFY ;13 + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 40 + + + 000E OP0M EQU ($-OP0T)/2 ;NUMBER OF 0-OPS + ; + ; ----- + ; 1-OPS + ; ----- + 1410 4215 OP1T: DW ZEROQ ;0 + 1412 4D15 DW NEXTQ ;1 + 1414 5915 DW FIRSTQ ;2 + 1416 7315 DW LOC ;3 + 1418 8315 DW PTSIZE ;4 + 141A 9315 DW INC ;5 + 141C 9915 DW DEC ;6 + 141E B615 DW PRINTB ;7 + 1420 BF15 DW BADOP ;8 (UNDEFINED) + 1422 C215 DW REMOVE ;9 + 1424 1816 DW PRINTD ;10 + 1426 3316 DW RETURN ;11 + 1428 7E16 DW JUMP ;12 + 142A 8716 DW PRINT ;13 + 142C 9316 DW VALUE ;14 + 142E 9C16 DW BCOM ;15 + 0010 OP1M EQU ($-OP1T)/2 ;NUMBER OF 1-OPS + ; + ; ----- + ; 2-OPS + ; ----- + 1430 BF15 OP2T: DW BADOP + 1432 C218 DW EQUALQ + 1434 A816 DW LESSQ + 1436 B516 DW GRTRQ + 1438 C116 DW DLESSQ + 143A CC16 DW IGRTRQ + 143C DC16 DW INQ + 143E F016 DW BTST + 1440 0217 DW BOR + 1442 0E17 DW BAND + 1444 1A17 DW FSETQ + 1446 2917 DW FSET + 1448 3617 DW FCLEAR + 144A 4517 DW ZSET + 144C 5117 DW MOVE + 144E 7D17 DW GET + 1450 8F17 DW GETB + 1452 A317 DW GETP + 1454 EF17 DW GETPT + 1456 1418 DW NEXTP + 1458 3E18 DW ZADD + 145A 4518 DW ZSUB + 145C 5118 DW MUL + 145E 7D18 DW DIV + 1460 B418 DW ZMOD + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 41 + + + 0019 OP2M EQU ($-OP2T)/2 + ; + ; ----- + ; X-OPS + ; ----- + 1462 EF18 OPEXTT: DW ZCALL + 1464 7B19 DW PUT + 1466 9419 DW PUTB + 1468 A819 DW PUTP + 146A DA19 DW ZREAD + 146C 841B DW PRINTC + 146E 8E1B DW PRINTN + 1470 CD1B DW RANDOM + 1472 DC1B DW ZPUSH + 1474 E51B DW ZPOP + 000A OPEXTM EQU ($-OPEXTT)/2 + ; ********************************************************************** + ; * * + ; * ZCODE EXECUTION ROUTINES * + ; * * + ; ********************************************************************** + ; + ; ******************* + ; * 0-OPS * + ; ******************* + ; + ; + ; ---------- + ; RTRUE [0] + ; ---------- + ; SIMULATE A RETURN 1 + 1476 210100 RTRUE: LD HL,1 + 1479 22BB21 RTRUE1: LD (ARG1),HL + 147C C33316 JP RETURN + ; + ; ----------- + ; RFALSE [1] + ; ----------- + ; SIMULATE A RETURN 0 + 147F 210000 RFALSE: LD HL,0 + 1482 C37914 JP RTRUE1 + ; + ; ----------- + ; PRINTI [2] + ; ----------- + ; PRINT THE Z-STRING IMMEDIATELY FOLLOWING THE OPCODE + 1485 CD8B14 PRINTI: CALL PRNTI1 + 1488 C31012 JP MLOOP + ; + 148B 2AA621 PRNTI1: LD HL,(ZPCL) + 148E 22D121 LD (MPCL),HL ;SET UP MPC TO EQUAL ZPC + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 42 + + + 1491 3AA521 LD A,(ZPCH) + 1494 32D021 LD (MPCH),A + 1497 AF XOR A + 1498 32D521 LD (MPCFLG),A ;ZERO MPC FLAG + 149B CD291F CALL PZSTR ;PRINT THE STRING + 149E 2AD121 LD HL,(MPCL) ;NOW CHANGE BACK ZPC TO END OF STRING + 14A1 22A621 LD (ZPCL),HL + 14A4 3AD021 LD A,(MPCH) + 14A7 32A521 LD (ZPCH),A + 14AA 3AD521 LD A,(MPCFLG) + 14AD 32CE21 LD (ZPCFLG),A ;UPDATE FLAG + 14B0 2AD321 LD HL,(MPCPNT) + 14B3 22CC21 LD (ZPCPNT),HL ;AND PAGE POINTER + 14B6 C9 RET + ; + ; ----------- + ; PRINTR [3] + ; ----------- + ; EXECUTE A PRINTI, FOLLOWED BY A CRLF, AND A RTRUE + 14B7 CD8B14 PRINTR: CALL PRNTI1 + 14BA CDB404 CALL PCRLF + 14BD C37614 JP RTRUE + ; + ; --------- + ; ZNOP [4] + ; --------- + ; EXECUTE A NOP + 14C0 C31012 ZNOP: JP MLOOP + ; + ; ---------- + ; ZSAVE [5] + ; ---------- + ; SAVE GAME + 14C3 C37007 ZSAVE: JP SAVE ;MACHINE DEPENDENT + ; + ; ----------- + ; ZRSTOR [6] + ; ----------- + ; RESTORE SAVED GAME + 14C6 C3930A ZRSTOR: JP RESTOR ;MACHINE DEPENDENT + ; + ; ----------- + ; ZRSTAR [7] + ; ----------- + ; RESTART GAME + 14C9 C35F07 ZRSTAR: JP RESTAR ;MACHINE DEPENDENT + ; + ; ----------- + ; RSTACK [8] + ; ----------- + ; EXECUTE A RETURN WITH CALL VALUE ON TOP OF THE STACK + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 43 + + + 14CC CD451D RSTACK: CALL POPSTK + 14CF 22BB21 LD (ARG1),HL + 14D2 C33316 JP RETURN + ; + ; ----------- + ; FSTACK [9] + ; ----------- + 14D5 CD451D FSTACK: CALL POPSTK + 14D8 C31012 JP MLOOP + ; + ; ----------- + ; ZQUIT [10] + ; ----------- + 14DB C34907 ZQUIT: JP QUIT ;MACHINE DEPENDENT + ; + ; ---------- + ; CRLF [11] + ; ---------- + ; PRINT CARRIAGE RETURN/LINE FEED + 14DE CDB404 CRLF: CALL PCRLF + 14E1 C31012 JP MLOOP + ; + ; --------- + ; USL [12] + ; --------- + ; UPDATE STATUS LINE + 14E4 CDC105 USL: CALL WHOLIN + 14E7 C31012 JP MLOOP + ; + ; ------------ + ; VERIFY [13] + ; ------------ + ; VERIFY THE GAME CODE + 14EA 3E01 VERIFY: LD A,1 ;SELF CHECK + 14EC 32B821 LD (VERF),A ;IN VERIFY MODE, ALWAYS GET NEW PAGE + 14EF 218910 LD HL,VRS + 14F2 CD660A CALL MSGOUT ;OUTPUT LAST UPDATE + 14F5 219A10 LD HL,VRLINE + 14F8 CD660A CALL MSGOUT ;OUTPUT VERSION + 14FB 2AD921 LD HL,(ZCODEP) ;^ TOP OF ZCODE + 14FE 111A00 LD DE,ZCKLEN + 1501 19 ADD HL,DE + 1502 56 LD D,(HL) + 1503 23 INC HL + 1504 5E LD E,(HL) + 1505 21E0FF LD HL,-32 + 1508 19 ADD HL,DE + 1509 EB EX DE,HL ;DE HAVE COUNT + 150A 010000 LD BC,0 ;SUM IN BC + 150D 214000 LD HL,32*2 + 1510 CDE41D CALL SETWRD + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 44 + + + 1513 C5 VERIFL: PUSH BC + 1514 D5 PUSH DE + 1515 CD251E CALL GETWRD ;GUARENTEED TO GET FRESH WORD + 1518 D1 POP DE + 1519 C1 POP BC + 151A 7C LD A,H + 151B 2600 LD H,0 + 151D 09 ADD HL,BC + 151E CD081F CALL HLOFF + 1521 44 LD B,H + 1522 4D LD C,L ;TOTAL IN BC + 1523 1B DEC DE + 1524 7A LD A,D + 1525 B3 OR E + 1526 C21315 JP NZ,VERIFL ;SUM ALL BYTES + 1529 111C00 LD DE,ZCKSUM + 152C 2AD921 LD HL,(ZCODEP) + 152F 19 ADD HL,DE + 1530 56 LD D,(HL) + 1531 23 INC HL + 1532 5E LD E,(HL) ;GET CHECKSUM + 1533 60 LD H,B + 1534 69 LD L,C + 1535 AF XOR A + 1536 32B821 LD (VERF),A + 1539 CD251D CALL HLGEDE ;COMPARE CALCULATED WITH ACTUAL + 153C CA8013 JP Z,PREDS + 153F C37113 JP PREDF ;FAIL IF DIFFERENT + ; + ; ******************* + ; * 1-OPS * + ; ******************* + ; + ; ---------- + ; ZERO? [0] + ; ---------- + ; IS ARG1 EQUAL TO ZERO? [PRED] + 1542 2ABB21 ZEROQ: LD HL,(ARG1) + 1545 7C LD A,H + 1546 B5 OR L + 1547 CA8013 JP Z,PREDS + 154A C37113 JP PREDF + ; + ; ---------- + ; NEXT? [1] + ; ---------- + ; RETURN THE NEXT POINTER IN OBJRCT "ARG1"; FAIL IF + ; NONE LEFT, AND RETURN ZERO [VALUE][PRED] + 154D 3ABB21 NEXTQ: LD A,(ARG1) + 1550 CDF41C CALL OBJLOC + 1553 110500 LD DE,5 + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 45 + + + 1556 C36215 JP FRSTQ1 ;SAME AS FIRST? + ; + ; ----------- + ; FIRST? [2] + ; ----------- + ; RETURN THE FIRST POINTER IN OBJECT "ARG1"; FAIL IF + ; NONE, AND RETURN ZERO [VALUE][PRED] + ; + 1559 3ABB21 FIRSTQ: LD A,(ARG1) + 155C CDF41C CALL OBJLOC + 155F 110600 LD DE,6 + 1562 19 FRSTQ1: ADD HL,DE + 1563 7E LD A,(HL) + 1564 F5 PUSH AF ;SAVE VALUE + 1565 6F LD L,A + 1566 2600 LD H,0 + 1568 CD3113 CALL PUTVLC ;STORE VALUE + 156B F1 POP AF + 156C B7 OR A + 156D C28013 JP NZ,PREDS ;FOUND FIRST + 1570 C37113 JP PREDF ;FIRST NOT FOUND + ; + ; -------- + ; LOC [3] + ; -------- + ; RETURN THE OBJECT CONTAINING OBJECT "ARG1"; ZERO IF NONE [VALUE] + 1573 3ABB21 LOC: LD A,(ARG1) + 1576 CDF41C CALL OBJLOC + 1579 110400 LD DE,4 + 157C 19 ADD HL,DE + 157D 6E LD L,(HL) + 157E 2600 LD H,0 + 1580 C32B13 JP PUTVAL + ; + ; ----------- + ; PTSIZE [4] + ; ----------- + ; RETURN LENGTH OF PROP TABLE "ARG1" IN BYTES [VALUE] + 1583 2ABB21 PTSIZE: LD HL,(ARG1) + 1586 EB EX DE,HL + 1587 2AD921 LD HL,(ZCODEP) + 158A 19 ADD HL,DE ;POINTER TO PROP ENTRY + 158B 2B DEC HL + 158C CDE51C CALL PROPL + 158F 3C INC A + 1590 C32813 JP PUTBYT + ; + ; -------- + ; INC [5] + ; -------- + ; INCREMENT ARG1 [VALUE] + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 46 + + + 1593 CD9F15 INC: CALL INC1 + 1596 C31012 JP MLOOP + ; + ; -------- + ; DEC [6] + ; -------- + ; DECREMENT ARG1 [VALUE] + 1599 CDAC15 DEC: CALL DEC1 + 159C C31012 JP MLOOP + ; + 159F 3ABB21 INC1: LD A,(ARG1) + 15A2 CD5913 CALL VARGET + 15A5 23 INC HL + 15A6 E5 INC2: PUSH HL + 15A7 CD6513 CALL VARPUT + 15AA E1 POP HL + 15AB C9 RET + ; + 15AC 3ABB21 DEC1: LD A,(ARG1) + 15AF CD5913 CALL VARGET + 15B2 2B DEC HL + 15B3 C3A615 JP INC2 + ; + ; ----------- + ; PRINTB [7] + ; ----------- + ; PRINT THE STRING POINTED TO BY BYTE POINTER ARG1 + 15B6 2ABB21 PRINTB: LD HL,(ARG1) + 15B9 CDE41D PRINT2: CALL SETWRD + 15BC C38D16 JP PRINT1 + ; + ; ---------- + ; BADOP [8] + ; ---------- + 15BF C31012 BADOP: JP MLOOP + ; + ; ----------- + ; REMOVE [9] + ; ----------- + ; MOVE OBJECT [ARG1] TO PSEUDO-OBJECT #0 + 15C2 CDC815 REMOVE: CALL REMOVC + 15C5 C31012 JP MLOOP + ; + 15C8 3ABB21 REMOVC: LD A,(ARG1) + 15CB 47 LD B,A ;SAVE IT + 15CC CDF41C CALL OBJLOC + 15CF EB EX DE,HL ;SAVE IN DE + 15D0 210400 LD HL,4 + 15D3 19 ADD HL,DE + 15D4 7E LD A,(HL) + 15D5 B7 OR A + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 47 + + + 15D6 C8 RET Z ;NO OBJECT + 15D7 D5 PUSH DE ;SAVE VALUE + 15D8 CDF41C CALL OBJLOC ;PARENT OBJECT + 15DB 110600 LD DE,6 + 15DE EB EX DE,HL ;LP IN D + 15DF 19 ADD HL,DE + 15E0 4E LD C,(HL) ;SIBL + 15E1 78 LD A,B + 15E2 B9 CP C + 15E3 C2F515 JP NZ,REMVC1 ;NOT SAME + 15E6 E1 POP HL + 15E7 E5 PUSH HL ;L1 + 15E8 010500 LD BC,5 + 15EB 09 ADD HL,BC + 15EC 7E LD A,(HL) + 15ED 210600 LD HL,6 ;PARENT'S FIRST SLOT GETS LOC SLOT + 15F0 19 ADD HL,DE + 15F1 77 LD (HL),A + 15F2 C30D16 JP REMVC2 + + 15F5 79 REMVC1: LD A,C ;GET SIBL + 15F6 CDF41C CALL OBJLOC + 15F9 110500 LD DE,5 + 15FC 19 ADD HL,DE + 15FD 54 LD D,H + 15FE 5D LD E,L ;SAVE LS+5 + 15FF 4E LD C,(HL) ;NEW SIBL + 1600 78 LD A,B + 1601 B9 CP C + 1602 C2F515 JP NZ,REMVC1 ;NOT END OF CHAIN + 1605 010500 LD BC,5 + 1608 E1 POP HL + 1609 E5 PUSH HL + 160A 09 ADD HL,BC ;OLD NEXT + 160B 7E LD A,(HL) + 160C 12 LD (DE),A + 160D E1 REMVC2: POP HL + 160E 110400 LD DE,4 + 1611 19 ADD HL,DE + 1612 3600 LD (HL),0 + 1614 23 INC HL + 1615 3600 LD (HL),0 + 1617 C9 RET + ; ------------ + ; PRINTD [10] + ; ------------ + ; PRINT SHORT DESCRIPTION OF OBJECT [ARG1] + 1618 3ABB21 PRINTD: LD A,(ARG1) + 161B CD2116 CALL PRNTDC + 161E C31012 JP MLOOP + ; + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 48 + + + 1621 CDF41C PRNTDC: CALL OBJLOC + 1624 110700 LD DE,7 + 1627 19 ADD HL,DE + 1628 56 LD D,(HL) + 1629 23 INC HL + 162A 5E LD E,(HL) + 162B EB EX DE,HL + 162C 23 INC HL + 162D CDE41D CALL SETWRD + 1630 C3291F JP PZSTR + ; + ; ------------ + ; RETURN [11] + ; ------------ + ; RETURN FROM A CALL WITH VALUE ARG1 + 1633 2AA921 RETURN: LD HL,(OZSTKP) ;RESET STACK FROM CALL + 1636 22070E LD (ZSTAKP),HL + 1639 3AAB21 LD A,(OZSTKC) + 163C 32A821 LD (ZSTAKC),A + 163F CD451D CALL POPSTK ;RESET Z-STACK + 1642 7D LD A,L + 1643 32A521 LD (ZPCH),A ;SAVE UPPER PC + 1646 44 LD B,H ;H HAS NUMBER OF LOCALS + 1647 7C LD A,H + 1648 87 ADD A,A ;WORD + 1649 CA6116 JP Z,RET2 ;NO LOCALS + 164C 218521 LD HL,LOCALS-2 + 164F CD081F CALL HLOFF ;POSITION HL TO RESTORE LOCALS + 1652 EB RET1: EX DE,HL + 1653 CD451D CALL POPSTK ;GET THE LOCAL, REVERSE ORDER FIRST + 1656 EB EX DE,HL + 1657 72 LD (HL),D + 1658 23 INC HL + 1659 73 LD (HL),E + 165A 2B DEC HL ;NOW BACK UP ONE ELEMENT + 165B 2B DEC HL + 165C 2B DEC HL + 165D 05 DEC B + 165E C25216 JP NZ,RET1 ;LOOP + 1661 CD451D RET2: CALL POPSTK + 1664 22A621 LD (ZPCL),HL ;REST OF PC + 1667 CD451D CALL POPSTK + 166A 22A921 LD (OZSTKP),HL + 166D CD451D CALL POPSTK + 1670 7D LD A,L + 1671 32AB21 LD (OZSTKC),A ;RESTORE OLD VALUES + 1674 AF XOR A + 1675 32CE21 LD (ZPCFLG),A ;PC CHANGED + 1678 2ABB21 LD HL,(ARG1) ;ARGUMENT TO BE RETURNED + 167B C32B13 JP PUTVAL ;STORE AND RETURN + ; + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 49 + + + ; ---------- + ; JUMP [12] + ; ---------- + ; BRANCH TO Z-LOCATION POINTED TO BY 16-BIT 2'S COMPLIMENT ARG1 + 167E 2ABB21 JUMP: LD HL,(ARG1) ;RELATIVE JUMP + 1681 44 LD B,H + 1682 4D LD C,L + 1683 0B DEC BC + 1684 C3B513 JP PREDB3 ;TREAT AS A SUCCESSFUL JUMP + ; + ; ----------- + ; PRINT [13] + ; ----------- + ; PRINT THE Z-STRING POINTED TO BY THE WORD-POINTER ARG1 + 1687 2ABB21 PRINT: LD HL,(ARG1) ;TELL SETSTR WHERE THE STRING + 168A CDF61D CALL SETSTR ;RESIDES AND + 168D CD291F PRINT1: CALL PZSTR ;PRINT THE STRING + 1690 C31012 JP MLOOP + ; + ; ----------- + ; VALUE [14] + ; ----------- + ; RETURN VALUE OF ARG1 [VALUE] + 1693 3ABB21 VALUE: LD A,(ARG1) + 1696 CD5913 CALL VARGET + 1699 C32B13 JP PUTVAL + ; + ; ---------- + ; BCOM [15] + ; ---------- + ; COMPLIMENT ARG1 [VALUE] + 169C 2ABB21 BCOM: LD HL,(ARG1) + 169F 7C LD A,H + 16A0 2F CPL + 16A1 67 LD H,A + 16A2 7D LD A,L + 16A3 2F CPL + 16A4 6F LD L,A + 16A5 C32B13 JP PUTVAL + ; + ; ******************* + ; * 2-OPS * + ; ******************* + ; + ; ---------- + ; LESS? [0] + ; ---------- + ; IS ARG1 LESS THAN ARG2? [PRED] + 16A8 CD151D LESSQ: CALL GETARG + 16AB EB EX DE,HL + 16AC CD1D1D CALL SHLGED + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 50 + + + 16AF D28013 JP NC,PREDS + 16B2 C37113 JP PREDF + ; + ; ---------- + ; GRTR? [1] + ; ---------- + ; IS ARG1 GREATER THAN ARG2? [PRED] + 16B5 CD151D GRTRQ: CALL GETARG + 16B8 CD1D1D CALL SHLGED + 16BB D28013 JP NC,PREDS + 16BE C37113 JP PREDF + ; + ; ----------- + ; DLESS? [2] + ; ----------- + ; DECREMENT ARG1: SUCCEED IF ARG1 (-1) IS LESS THAN ARG2 [PRED] + 16C1 CDAC15 DLESSQ: CALL DEC1 + 16C4 EB EX DE,HL + 16C5 2ABD21 LD HL,(ARG2) + 16C8 EB EX DE,HL + 16C9 C3D316 JP IGRTQ1 + ; + ; ----------- + ; IGRTR? [3] + ; ----------- + ; INCREMENT ARG1: SUCCEED IF ARG1 (+1) IS GREATER THAN ARG2 [PRED] + 16CC CD9F15 IGRTRQ: CALL INC1 + 16CF EB EX DE,HL + 16D0 2ABD21 LD HL,(ARG2) + 16D3 CD1D1D IGRTQ1: CALL SHLGED + 16D6 D28013 JP NC,PREDS + 16D9 C37113 JP PREDF + ; + ; ---------- + ; IN? [4] + ; ---------- + ; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2] [PRED] + 16DC 3ABB21 INQ: LD A,(ARG1) + 16DF CDF41C CALL OBJLOC + 16E2 110400 LD DE,4 + 16E5 19 ADD HL,DE + 16E6 3ABD21 LD A,(ARG2) + 16E9 BE CP (HL) + 16EA CA8013 JP Z,PREDS ;SUCCESS IF OBJ 2 IN 1 + 16ED C37113 JP PREDF + ; + ; --------- + ; BTST [5] + ; --------- + ; IS EVERY "ON" BIT IN ARG1 ALSO "ON" IN ARG2 [PRED] + 16F0 CD151D BTST: CALL GETARG + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 51 + + + 16F3 7C LD A,H + 16F4 A2 AND D + 16F5 57 LD D,A + 16F6 7D LD A,L + 16F7 A3 AND E + 16F8 5F LD E,A + 16F9 CD251D CALL HLGEDE + 16FC CA8013 JP Z,PREDS + 16FF C37113 JP PREDF + ; + ; -------- + ; BOR [6] + ; -------- + ; RETURN BITWISE OR OF ARG1 AND ARG2 [VALUE] + 1702 CD151D BOR: CALL GETARG + 1705 7A LD A,D + 1706 B4 OR H + 1707 67 LD H,A + 1708 7B LD A,E + 1709 B5 OR L + 170A 6F LD L,A + 170B C32B13 JP PUTVAL + ; + ; --------- + ; BAND [7] + ; --------- + ; RETURN BITWISE AND OF ARG1 AND ARG2 [VALUE] + 170E CD151D BAND: CALL GETARG + 1711 7C LD A,H + 1712 A2 AND D + 1713 67 LD H,A + 1714 7D LD A,L + 1715 A3 AND E + 1716 6F LD L,A + 1717 C32B13 JP PUTVAL + ; + ; ---------- + ; FSET? [8] + ; ---------- + ; IS FLAG "ARG2" SET IN OBJECT "ARG1"? [PRED] + 171A CDA01C FSETQ: CALL FLAGSU ;GET BIT + 171D 7A LD A,D + 171E A0 AND B + 171F 57 LD D,A + 1720 7B LD A,E + 1721 A1 AND C + 1722 B2 OR D ;CHECK FOR ON + 1723 C28013 JP NZ,PREDS ;BIT ON + 1726 C37113 JP PREDF ;BIT OFF + ; + ; --------- + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 52 + + + ; FSET [9] + ; --------- + ; SET FLAG "ARG2" IN OBJECT "ARG1" + 1729 CDA01C FSET: CALL FLAGSU + 172C 7A LD A,D + 172D B0 OR B + 172E 77 LD (HL),A + 172F 23 INC HL + 1730 7B LD A,E + 1731 B1 OR C + 1732 77 LD (HL),A + 1733 C31012 JP MLOOP + ; + ; ------------ + ; FCLEAR [10] + ; ------------ + ; CLEAR FLAG "ARG2" IN OBJECT "ARG1" + 1736 CDA01C FCLEAR: CALL FLAGSU + 1739 78 LD A,B + 173A 2F CPL + 173B A2 AND D + 173C 77 LD (HL),A + 173D 23 INC HL + 173E 79 LD A,C + 173F 2F CPL + 1740 A3 AND E + 1741 77 LD (HL),A + 1742 C31012 JP MLOOP + ; + ; --------- + ; SET [11] + ; --------- + ; SET VARIABLE "ARG1" EQUAL TO VALUE "ARG2" + 1745 3ABB21 ZSET: LD A,(ARG1) + 1748 2ABD21 LD HL,(ARG2) + 174B CD6513 VARPTR: CALL VARPUT + 174E C31012 JP MLOOP + ; + ; ---------- + ; MOVE [12] + ; ---------- + ; PUT OBJECT "ARG1" INTO OBJECT "ARG2" + 1751 CDC815 MOVE: CALL REMOVC ;REMOVE OBJECT FIRST + 1754 3ABB21 LD A,(ARG1) + 1757 CDF41C CALL OBJLOC + 175A E5 PUSH HL ;SAVE LOC OF FIRST ARG + 175B 110400 LD DE,4 + 175E 19 ADD HL,DE ;LOC SLOT + 175F 3ABD21 LD A,(ARG2) + 1762 77 LD (HL),A + 1763 CDF41C CALL OBJLOC + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 53 + + + 1766 110600 LD DE,6 + 1769 19 ADD HL,DE ;FIRST SLOT + 176A 46 LD B,(HL) + 176B 3ABB21 LD A,(ARG1) + 176E 77 LD (HL),A + 176F E1 POP HL + 1770 78 LD A,B + 1771 B7 OR A + 1772 CA1012 JP Z,MLOOP + 1775 110500 LD DE,5 + 1778 19 ADD HL,DE + 1779 77 LD (HL),A ;NEXT SLOT + 177A C31012 JP MLOOP + ; + ; --------- + ; GET [13] + ; --------- + ; RETURN VALUE OF ITEM "ARG2" IN WORD-TABLE AT "ARG1" + 177D 2ABD21 GET: LD HL,(ARG2) + 1780 29 ADD HL,HL ;ITEM NUMBER*2 + 1781 EB EX DE,HL + 1782 2ABB21 LD HL,(ARG1) + 1785 19 ADD HL,DE ;POINTER TO ITEM + 1786 CDE41D CALL SETWRD + 1789 CD251E CALL GETWRD ;GET VALUE + 178C C32B13 JP PUTVAL + ; + ; ---------- + ; GETB [14] + ; ---------- + ; RETURN VALUE OF ITEM "ARG2" IN BYTE-TABLE AT "ARG1" [VALUE] + 178F 2ABD21 GETB: LD HL,(ARG2) + 1792 EB EX DE,HL + 1793 2ABB21 LD HL,(ARG1) + 1796 19 ADD HL,DE + 1797 CDE41D CALL SETWRD + 179A CD301E CALL GETBYT + 179D 6F LD L,A + 179E 2600 LD H,0 + 17A0 C32B13 JP PUTVAL + ; + ; ---------- + ; GETP [15] + ; ---------- + ; RETURN PROP "ARG2" OF OBJECT "ARG1"; IF SPECIFIED PROP DOES + ; NOT EXIST, RETUURN PROP'TH ELEMENT OF DEFAULT OBJECT [VALUE] + 17A3 CDCA1C GETP: CALL PROPB ;GET POINTER TO PROPS IN PROP TABLE + 17A6 CDE11C GETP1: CALL PROPN + 17A9 47 LD B,A + 17AA 3ABD21 LD A,(ARG2) + 17AD B8 CP B + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 54 + + + 17AE CAD717 JP Z,GETP2 ;FOUND PROP + 17B1 D2BA17 JP NC,GETP3 ;GET PROP FROM DEFAULT TABLE + 17B4 CDEC1C CALL PROPNX ;TRY AGAIN WITH NEXT PROP + 17B7 C3A617 JP GETP1 + + 17BA 2AD921 GETP3: LD HL,(ZCODEP) + 17BD 110A00 LD DE,ZOBJEC + 17C0 19 ADD HL,DE + 17C1 56 LD D,(HL) + 17C2 23 INC HL + 17C3 5E LD E,(HL) + 17C4 2AD921 LD HL,(ZCODEP) + 17C7 19 ADD HL,DE ;BEG OF OBJECT TABLE + 17C8 3ABD21 LD A,(ARG2) + 17CB 87 ADD A,A + 17CC CD081F CALL HLOFF + 17CF 2B DEC HL + 17D0 5E LD E,(HL) + 17D1 2B DEC HL + 17D2 56 LD D,(HL) + 17D3 EB EX DE,HL + 17D4 C32B13 JP PUTVAL ;RETURN DEFAULT VALUE + + 17D7 CDE51C GETP2: CALL PROPL ;GET LENGTH + 17DA 23 INC HL + 17DB 3D DEC A + 17DC FAE917 JP M,GETP2A ;1 BYTE + 17DF C40602 CALL NZ,ZER ;BAD PROP LENGTH + 17E2 56 LD D,(HL) + 17E3 23 INC HL + 17E4 5E LD E,(HL) + 17E5 EB EX DE,HL + 17E6 C32B13 JP PUTVAL ;RETURN TWO BYTE PROP + + 17E9 6E GETP2A: LD L,(HL) + 17EA 2600 LD H,0 + 17EC C32B13 JP PUTVAL + + 17EF CDCA1C GETPT: CALL PROPB + 17F2 CDE11C GETPT1: CALL PROPN + 17F5 47 LD B,A + 17F6 3ABD21 LD A,(ARG2) + 17F9 B8 CP B + 17FA CA0618 JP Z,GETPT2 ;FOUND PROP + 17FD D22713 JP NC,RET0 + 1800 CDEC1C CALL PROPNX + 1803 C3F217 JP GETPT1 + + 1806 23 GETPT2: INC HL + 1807 EB EX DE,HL + 1808 2AD921 LD HL,(ZCODEP) ;SUBRACT OFF RELATIVE POINTER + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 55 + + + 180B 7B LD A,E + 180C 95 SUB L + 180D 6F LD L,A + 180E 7A LD A,D + 180F 9C SBC A,H + 1810 67 LD H,A + 1811 C32B13 JP PUTVAL + + 1814 CDCA1C NEXTP: CALL PROPB ;POINT TO PROP VALUE + 1817 3ABD21 LD A,(ARG2) + 181A B7 OR A + 181B CA3218 JP Z,NEXTP2 ;PROP0 + 181E CDE11C NEXTP1: CALL PROPN + 1821 47 LD B,A + 1822 3ABD21 LD A,(ARG2) + 1825 B8 CP B + 1826 CA3818 JP Z,NEXTP3 ;FOUND PROP + 1829 D22713 JP NC,RET0 ;RETURN 0 + 182C CDEC1C CALL PROPNX + 182F C31E18 JP NEXTP1 ;LOOP + + 1832 CDE11C NEXTP2: CALL PROPN + 1835 C32813 JP PUTBYT + + 1838 CDEC1C NEXTP3: CALL PROPNX + 183B C33218 JP NEXTP2 ;PROPN OF NEXT + + 183E CD151D ZADD: CALL GETARG + 1841 19 ADD HL,DE + 1842 C32B13 JP PUTVAL + + 1845 CD151D ZSUB: CALL GETARG + 1848 7B LD A,E + 1849 95 SUB L + 184A 6F LD L,A + 184B 7A LD A,D + 184C 9C SBC A,H + 184D 67 LD H,A + 184E C32B13 JP PUTVAL + + 1851 CD151D MUL: CALL GETARG + 1854 EB EX DE,HL + 1855 CD781C CALL SIGNC ;CHECK SIGN + 1858 E5 PUSH HL + 1859 210200 LD HL,2 + 185C CD251D CALL HLGEDE + 185F CA7818 JP Z,MUL2 + 1862 210400 LD HL,4 + 1865 CD251D CALL HLGEDE + 1868 CA7518 JP Z,MUL4 + 186B E1 POP HL + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 56 + + + 186C CD1C1C CALL MULT ;DO THE MULTIPLY + 186F CD851C MUL1: CALL SIGNS ;SET THE SIGN + 1872 C32B13 JP PUTVAL ;THEN STORE RESULT + + 1875 E1 MUL4: POP HL + 1876 29 ADD HL,HL + 1877 E5 PUSH HL + 1878 E1 MUL2: POP HL + 1879 29 ADD HL,HL + 187A C36F18 JP MUL1 + + 187D CD151D DIV: CALL GETARG + 1880 EB EX DE,HL + 1881 CD781C CALL SIGNC ;CHECK SIGNS + 1884 E5 PUSH HL + 1885 210200 LD HL,2 + 1888 CD251D CALL HLGEDE + 188B CA9E18 JP Z,DIV2 ;DIVIDE BY 2 + 188E 210400 LD HL,4 + 1891 CD251D CALL HLGEDE + 1894 CAA518 JP Z,DIV4 ;DIVIDE BY 4 + 1897 E1 POP HL + 1898 CD451C CALL DIVIDE ;DO THE DIVIDE + 189B C36F18 JP MUL1 ;SET SIGN AND RETURN + + 189E E1 DIV2: POP HL + 189F CDAC18 DIV2B: CALL DIV2A + 18A2 C36F18 JP MUL1 + + 18A5 E1 DIV4: POP HL + 18A6 CDAC18 CALL DIV2A + 18A9 C39F18 JP DIV2B + + 18AC B7 DIV2A: OR A ;CLEAR CARRY + 18AD 7C LD A,H + 18AE 1F RRA + 18AF 67 LD H,A + 18B0 7D LD A,L + 18B1 1F RRA + 18B2 6F LD L,A + 18B3 C9 RET + + 18B4 CD151D ZMOD: CALL GETARG + 18B7 EB EX DE,HL + 18B8 CD781C CALL SIGNC ;MAKE THEM POSITIVE + 18BB CD451C CALL DIVIDE ;DO THE DIVIDE + 18BE EB EX DE,HL ;GET THE REMAINDER + 18BF C32B13 JP PUTVAL + ; + ; ******************* + ; * X-OPS * + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 57 + + + ; ******************* + ; + 18C2 2ABB21 EQUALQ: LD HL,(ARG1) + 18C5 EB EX DE,HL + 18C6 3AC321 LD A,(ARGCNT) + 18C9 47 LD B,A + 18CA 05 DEC B + 18CB CC0602 CALL Z,ZER + 18CE 2ABD21 LD HL,(ARG2) + 18D1 CDE318 CALL EQUAQ1 + 18D4 2ABF21 LD HL,(ARG3) + 18D7 CDE318 CALL EQUAQ1 + 18DA 2AC121 LD HL,(ARG4) + 18DD CDE318 CALL EQUAQ1 + 18E0 CD0602 CALL ZER + + 18E3 CD251D EQUAQ1: CALL HLGEDE ;DO COMPARISON + 18E6 E1 POP HL ;RESTORE RETURN ADDRESS + 18E7 CA8013 JP Z,PREDS ;DON'T BOTHER RETURNING + 18EA 05 DEC B ;ARG COUNT + 18EB CA7113 JP Z,PREDF ;OUT OF ARGS, FAIL + 18EE E9 JP (HL) ;ELSE RETURN + + 18EF 2ABB21 ZCALL: LD HL,(ARG1) + 18F2 7C LD A,H + 18F3 B5 OR L + 18F4 CA2B13 JP Z,PUTVAL + 18F7 2AAB21 LD HL,(OZSTKC) + 18FA CD2C1D CALL PSHSTK + 18FD 2AA921 LD HL,(OZSTKP) + 1900 CD2C1D CALL PSHSTK + 1903 2AA621 LD HL,(ZPCL) + 1906 CD2C1D CALL PSHSTK ;SAVE OLD PC LOWER + 1909 2AA521 LD HL,(ZPCH) ;SAVE HIGH IN L + 190C E5 PUSH HL + 190D AF XOR A + 190E 32CE21 LD (ZPCFLG),A ;PC HAS CHANGED + 1911 67 LD H,A + 1912 3ABB21 LD A,(ARG1) + 1915 6F LD L,A + 1916 29 ADD HL,HL ;NEW ZPCL + 1917 22A621 LD (ZPCL),HL + 191A 3ABC21 LD A,(ARG1+1) + 191D 32A521 LD (ZPCH),A ;NEW ZPCH + 1920 CD5A1D CALL NEXTPC ;GET NUMBER OF LOCALS + 1923 E1 POP HL + 1924 47 LD B,A ;B HAS NUMBER OF LOCALS + 1925 67 LD H,A + 1926 E5 PUSH HL ;SAVE VALUE + 1927 218721 LD HL,LOCALS ;STORE OLD LOCALS + 192A B7 OR A + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 58 + + + 192B CA4C19 JP Z,ZCALL2 ;NO LOCALS + 192E C5 ZCALL1: PUSH BC + 192F 56 LD D,(HL) + 1930 23 INC HL + 1931 5E LD E,(HL) + 1932 EB EX DE,HL + 1933 CD2C1D CALL PSHSTK + 1936 1B DEC DE + 1937 D5 PUSH DE + 1938 CD5A1D CALL NEXTPC ;GET NEW DEFAULT VALUE FOR LOCAL + 193B 57 LD D,A + 193C D5 PUSH DE + 193D CD5A1D CALL NEXTPC ;WORD VALUE + 1940 D1 POP DE + 1941 5F LD E,A + 1942 E1 POP HL ;POINTER TO STORE NEW LOCAL + 1943 72 LD (HL),D + 1944 23 INC HL + 1945 73 LD (HL),E + 1946 23 INC HL + 1947 C1 POP BC + 1948 05 DEC B + 1949 C22E19 JP NZ,ZCALL1 ;LOOP THROUGH ALL LOCALS + 194C 3AC321 ZCALL2: LD A,(ARGCNT) ;PASS ARGS + 194F 47 LD B,A + 1950 05 DEC B + 1951 CA6819 JP Z,ZCALL4 ;NO ARGS TO PASS + 1954 21BD21 LD HL,ARG2 ;POINTER TO FIRST ARG + 1957 118721 LD DE,LOCALS + 195A 7E ZCALL3: LD A,(HL) + 195B 23 INC HL + 195C 13 INC DE + 195D 12 LD (DE),A + 195E 1B DEC DE + 195F 7E LD A,(HL) + 1960 23 INC HL + 1961 12 LD (DE),A + 1962 13 INC DE + 1963 13 INC DE + 1964 05 DEC B + 1965 C25A19 JP NZ,ZCALL3 + 1968 E1 ZCALL4: POP HL ;GET BACK ZPCH AND NUMBER OF LOCALS + 1969 CD2C1D CALL PSHSTK + 196C 3AA821 LD A,(ZSTAKC) + 196F 32AB21 LD (OZSTKC),A + 1972 2A070E LD HL,(ZSTAKP) + 1975 22A921 LD (OZSTKP),HL ;FOR KNOWING WHERE TO RETURN + 1978 C31012 JP MLOOP + + 197B 2ABD21 PUT: LD HL,(ARG2) + 197E 29 ADD HL,HL + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 59 + + + 197F EB EX DE,HL + 1980 2ABB21 LD HL,(ARG1) + 1983 19 ADD HL,DE ;Z ADDRESS + 1984 EB EX DE,HL + 1985 2AD921 LD HL,(ZCODEP) + 1988 19 ADD HL,DE ;REAL POINTER + 1989 EB EX DE,HL + 198A 2ABF21 LD HL,(ARG3) ;VALUE TO STORE + 198D EB EX DE,HL + 198E 72 LD (HL),D + 198F 23 INC HL + 1990 73 LD (HL),E + 1991 C31012 JP MLOOP + + 1994 2ABD21 PUTB: LD HL,(ARG2) + 1997 EB EX DE,HL + 1998 2ABB21 LD HL,(ARG1) + 199B 19 ADD HL,DE + 199C EB EX DE,HL + 199D 2AD921 LD HL,(ZCODEP) + 19A0 19 ADD HL,DE + 19A1 3ABF21 LD A,(ARG3) + 19A4 77 LD (HL),A ;STORE ONE BYTE IN RANDOM TABLE + 19A5 C31012 JP MLOOP + + 19A8 CDCA1C PUTP: CALL PROPB ;SET PROP + 19AB CDE11C PUTP1: CALL PROPN ;GET PROP NUMBER + 19AE 47 LD B,A + 19AF 3ABD21 LD A,(ARG2) + 19B2 B8 CP B + 19B3 CABF19 JP Z,PUTP2 ;FOUND PROPERTY + 19B6 D40602 CALL NC,ZER ;BAD PROP NUMBER + 19B9 CDEC1C CALL PROPNX ;TRY NEXT + 19BC C3AB19 JP PUTP1 + + 19BF CDE51C PUTP2: CALL PROPL ;GET LENGTH + 19C2 23 INC HL + 19C3 EB EX DE,HL + 19C4 2ABF21 LD HL,(ARG3) + 19C7 3D DEC A + 19C8 FAD519 JP M,PUTP2A ;STORE 1 BYTE + 19CB C40602 CALL NZ,ZER ;TOO LONG + 19CE EB EX DE,HL + 19CF 72 LD (HL),D + 19D0 23 INC HL + 19D1 73 LD (HL),E + 19D2 C31012 JP MLOOP ;RETURN + + 19D5 EB PUTP2A: EX DE,HL + 19D6 73 LD (HL),E + 19D7 C31012 JP MLOOP ;SET AND RETURN + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 60 + + + + + 19DA ZREAD: + 19DA CDC105 CALL WHOLIN + 19DD CDEE1B CALL RND ;RANDOMIZE + 19E0 2AD921 LD HL,(ZCODEP) ;MAIN READ CODE + 19E3 EB EX DE,HL ;GET REAL POINTERS TO TABLES + 19E4 2ABB21 LD HL,(ARG1) + 19E7 19 ADD HL,DE ;BUFFER TABLE + 19E8 22BB21 LD (ARG1),HL + 19EB 2ABD21 LD HL,(ARG2) + 19EE 19 ADD HL,DE ;RESULT TABLE + 19EF 22BD21 LD (ARG2),HL + 19F2 CD5403 CALL READBF ;READ THE BUFFER + 19F5 47 LD B,A ;CHARACTER COUNT IN B + 19F6 0E00 LD C,0 ;C HAS CHARACTERS IN WORD + 19F8 2ABD21 LD HL,(ARG2) + 19FB 23 INC HL + 19FC 3600 LD (HL),0 ;SET WORDS READ TO 0 + 19FE 23 INC HL + 19FF 22E921 LD (RTABP),HL ;INITIALIZE RESULT TABLE POINTER + 1A02 2ABB21 LD HL,(ARG1) + 1A05 23 INC HL ;HL HAS POINTER TO INPUT CHARACTERS + 1A06 E5 READL: PUSH HL + 1A07 2ABD21 LD HL,(ARG2) + 1A0A 7E LD A,(HL) + 1A0B 23 INC HL + 1A0C BE CP (HL) + 1A0D E1 POP HL + 1A0E CA1012 JP Z,MLOOP ;TOO MANY WORDS + ;ERROR HERE IF DESIRED INSTEAD OF JZ + 1A11 78 LD A,B + 1A12 B1 OR C + 1A13 CA1012 JP Z,MLOOP ;OUT OF CHARACTERS AND WORDS + 1A16 79 LD A,C + 1A17 FE06 CP 6 + 1A19 CC9F1A CALL Z,FLUSHW ;FLUSH CHARS IN A WORD OVER 6 CHARACTERS + 1A1C 79 LD A,C + 1A1D B7 OR A + 1A1E C2511A JP NZ,READL2 ;NOT FIRST CHARACTER IN WORD + 1A21 E5 PUSH HL + 1A22 1606 LD D,6 + 1A24 21B021 LD HL,ZSTBUI ;INITIALIZE WORD BUFFER + 1A27 3600 RD0PL: LD (HL),0 + 1A29 23 INC HL + 1A2A 15 DEC D + 1A2B C2271A JP NZ,RD0PL + 1A2E E1 POP HL + 1A2F 3ABB21 LD A,(ARG1) + 1A32 57 LD D,A + 1A33 7D LD A,L + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 61 + + + 1A34 92 SUB D ;POSITION OF START OF WORD + 1A35 E5 PUSH HL + 1A36 2AE921 LD HL,(RTABP) + 1A39 23 INC HL + 1A3A 23 INC HL + 1A3B 23 INC HL + 1A3C 77 LD (HL),A ;STORE IN RESULT TABLE + 1A3D E1 POP HL + 1A3E 7E LD A,(HL) + 1A3F CDC61A CALL SIBRKQ ;SELF INSERTING BREAK? + 1A42 DA6E1A JP C,RSIBRK + 1A45 7E LD A,(HL) + 1A46 CDAD1A CALL RBRKQ ;NORMAL BREAK? + 1A49 D2511A JP NC,READL2 ;NO + 1A4C 23 INC HL ;YES, FLUSH STRANDED BREAKS + 1A4D 05 DEC B + 1A4E C3061A JP READL ;LOOP BACK + + 1A51 78 READL2: LD A,B + 1A52 B7 OR A + 1A53 CA741A JP Z,READL3 ;OUT OF CHARACTERS, SIMULATE WORD ENDING + 1A56 7E LD A,(HL) + 1A57 CDAD1A CALL RBRKQ ;WORD BREAK? + 1A5A DA741A JP C,READL3 ;FOUND A BREAK + 1A5D 56 LD D,(HL) + 1A5E E5 PUSH HL + 1A5F 21B021 LD HL,ZSTBUI + 1A62 79 LD A,C + 1A63 CD081F CALL HLOFF + 1A66 72 LD (HL),D ;STORE CHARACTER IN BUFFER + 1A67 E1 POP HL + 1A68 05 DEC B ;ONE LESS CHARACTER + 1A69 0C INC C ;ONE MORE CHARACTER IN WORD + 1A6A 23 INC HL ;POINT TO NEXT CHARACTER + 1A6B C3061A JP READL + + 1A6E 32B021 RSIBRK: LD (ZSTBUI),A ;STORE SELF INSERTING BREAK + 1A71 0C INC C ;1 CHAR + 1A72 05 DEC B ;1 LESS CHAR + 1A73 23 INC HL + 1A74 79 READL3: LD A,C ;INSERT WORD IF ANY CHARACTERS IN WORD + 1A75 B7 OR A + 1A76 CA061A JP Z,READL ;NO CHARACTERS IN WORD + 1A79 E5 PUSH HL + 1A7A C5 PUSH BC + 1A7B 2AE921 LD HL,(RTABP) ;STORE PARAMS IN TABLE + 1A7E 23 INC HL + 1A7F 23 INC HL + 1A80 71 LD (HL),C ;REAL LENGTH OF WORD + 1A81 CD9020 CALL CONZST ;CONVERT TO ZSTRING + 1A84 CDED1A CALL FINDW ;LOOK UP WORD IN VOCAB TABLE + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 62 + + + 1A87 2AE921 LD HL,(RTABP) ;STORE RESULT + 1A8A 72 LD (HL),D + 1A8B 23 INC HL + 1A8C 73 LD (HL),E + 1A8D 23 INC HL + 1A8E 23 INC HL + 1A8F 23 INC HL + 1A90 22E921 LD (RTABP),HL ;POINTER TO NEXT WORD + 1A93 2ABD21 LD HL,(ARG2) + 1A96 23 INC HL + 1A97 34 INC (HL) ;ONE MORE WORD + 1A98 C1 POP BC + 1A99 E1 POP HL + 1A9A 0E00 LD C,0 ;ZERO CHARACTERS IN NEXT WORD + 1A9C C3061A JP READL + + 1A9F 78 FLUSHW: LD A,B + 1AA0 B7 OR A ;FLUSH CHARACTERS TILL BREAD OR END OF BUFFER + 1AA1 C8 RET Z + 1AA2 7E LD A,(HL) + 1AA3 CDAD1A CALL RBRKQ + 1AA6 D8 RET C ;FOUND A BREAK + 1AA7 23 INC HL + 1AA8 05 DEC B + 1AA9 0C INC C + 1AAA C39F1A JP FLUSHW + + 1AAD CDC61A RBRKQ: CALL SIBRKQ ;FIRST CHECK SELF INSERTING BREAKS + 1AB0 D8 RET C ;YES + 1AB1 E5 PUSH HL + 1AB2 21E31A LD HL,BRKTBL + 1AB5 160A LD D,NBRKS + 1AB7 BE RBRK1: CP (HL) + 1AB8 CAC31A JP Z,FBRK ;MATCH + 1ABB 23 INC HL + 1ABC 15 DEC D + 1ABD C2B71A JP NZ,RBRK1 + 1AC0 E1 RBRK2: POP HL ;NOT FOUND + 1AC1 B7 OR A ;CLEAR CARRY + 1AC2 C9 RET + + 1AC3 E1 FBRK: POP HL + 1AC4 37 SCF + 1AC5 C9 RET ;FOUND A BREAK, SET CARRY AND RETURN + + 1AC6 E5 SIBRKQ: PUSH HL + 1AC7 CDD41A CALL GETVOC + 1ACA 56 LD D,(HL) ;NUMBER OF SELF INSERTING BREAKS + 1ACB 15 DEC D + 1ACC 14 INC D + 1ACD CAC01A JP Z,RBRK2 ;FAIL + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 63 + + + 1AD0 23 INC HL + 1AD1 C3B71A JP RBRK1 + + 1AD4 2AD921 GETVOC: LD HL,(ZCODEP) + 1AD7 110800 LD DE,ZVOCAB + 1ADA 19 ADD HL,DE + 1ADB 56 LD D,(HL) + 1ADC 23 INC HL + 1ADD 5E LD E,(HL) + 1ADE 2AD921 LD HL,(ZCODEP) + 1AE1 19 ADD HL,DE + 1AE2 C9 RET + + 1AE3 202E2C3F BRKTBL: DB ' .,?' + 1AE7 0D0A090C DB 0DH,0AH,9H,0CH + 1AEB 2222 DB 22H,22H + + 000A NBRKS EQU $-BRKTBL + + 1AED CDD41A FINDW: CALL GETVOC ;FIND WORD IN VOCAB TABLE, ASSUMES VOCAB IN MEMORY + 1AF0 7E LD A,(HL) + 1AF1 23 INC HL + 1AF2 CD081F CALL HLOFF ;SKIP OVER SELF INSERTING BREAKS + 1AF5 7E LD A,(HL) + 1AF6 87 ADD A,A + 1AF7 87 ADD A,A + 1AF8 87 ADD A,A + 1AF9 87 ADD A,A + 1AFA 4F LD C,A ;C HAS 16 TIMES VOCAB ENTRY SIZE + 1AFB 23 INC HL + 1AFC 56 LD D,(HL) + 1AFD 23 INC HL + 1AFE 5E LD E,(HL) + 1AFF 23 INC HL ;HL POINTS TO VOCAB TABLE + 1B00 3AE421 LD A,(ZSTBUO+1) ;GET FIRST CHARACTER + 1B03 47 LD B,A ;PUT IT IN B + 1B04 C3101B JP FWL2 ;WE CAN'T START AT THE BEGINNING + + 1B07 B2 FWL1A: OR D ;HERE ON 16 WORD BOUNDRY + 1B08 CA251B JP Z,FWL3 ;END OF TABLE + 1B0B 7E FWL1: LD A,(HL) + 1B0C B8 CP B ;CHECK ONLY FIRST BYTE + 1B0D D2251B JP NC,FWL3 ;FOUND PROPER AREA FOR FINE SEARCH + 1B10 7D FWL2: LD A,L + 1B11 81 ADD A,C + 1B12 6F LD L,A + 1B13 7C LD A,H + 1B14 CE00 ADC A,0 + 1B16 67 LD H,A ;POINTER TO NEXT BLOCK (HLOFF NOT USED FOR SPEED) + 1B17 7B LD A,E + 1B18 D610 SUB 16 ;16 MORE WORDS + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 64 + + + 1B1A 5F LD E,A + 1B1B CA071B JP Z,FWL1A + 1B1E D20B1B JP NC,FWL1 + 1B21 15 DEC D + 1B22 F20B1B JP P,FWL1 ;NOT OUT OF WORDS + 1B25 7D FWL3: LD A,L ;NOW DO FINE CHECK + 1B26 91 SUB C ;BACKUP 16 WORDS + 1B27 6F LD L,A + 1B28 7C LD A,H + 1B29 DE00 SBC A,0 + 1B2B 67 LD H,A + 1B2C 7B LD A,E + 1B2D C610 ADD A,16 + 1B2F 5F LD E,A + 1B30 7A LD A,D + 1B31 CE00 ADC A,0 + 1B33 57 LD D,A ;BACKUP COUNT + 1B34 79 LD A,C + 1B35 0F RRCA + 1B36 0F RRCA + 1B37 0F RRCA + 1B38 0F RRCA + 1B39 4F LD C,A ;REAL ENTRY SIZE + 1B3A FWL4: + 1B3A 3AE421 LD A,(ZSTBUO+1) + 1B3D BE CP (HL) + 1B3E DA721B JP C,FWFAIL + 1B41 C2681B JP NZ,FWL4A ;CHECK ALL 4 BYTES + 1B44 23 INC HL + 1B45 3AE321 LD A,(ZSTBUO) + 1B48 BE CP (HL) + 1B49 DA721B JP C,FWFAIL + 1B4C C2671B JP NZ,FWL4B + 1B4F 23 INC HL + 1B50 3AE621 LD A,(ZSTBUO+3) + 1B53 BE CP (HL) + 1B54 DA721B JP C,FWFAIL + 1B57 C2661B JP NZ,FWL4C + 1B5A 23 INC HL + 1B5B 3AE521 LD A,(ZSTBUO+2) + 1B5E BE CP (HL) + 1B5F DA721B JP C,FWFAIL + 1B62 CA761B JP Z,FWSUCC ;MATCH + 1B65 2B DEC HL + 1B66 2B FWL4C: DEC HL + 1B67 2B FWL4B: DEC HL + 1B68 79 FWL4A: LD A,C + 1B69 CD081F CALL HLOFF + 1B6C 1B DEC DE + 1B6D 7A LD A,D + 1B6E B3 OR E + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 65 + + + 1B6F C23A1B JP NZ,FWL4 ;NOT OUT OF WORDS YET + 1B72 110000 FWFAIL: LD DE,0 + 1B75 C9 RET + + 1B76 2B FWSUCC: DEC HL + 1B77 2B DEC HL + 1B78 2B DEC HL + 1B79 EB EX DE,HL + 1B7A 2AD921 LD HL,(ZCODEP) + 1B7D 7B LD A,E + 1B7E 95 SUB L + 1B7F 5F LD E,A + 1B80 7A LD A,D + 1B81 9C SBC A,H + 1B82 57 LD D,A + 1B83 C9 RET + + 1B84 3ABB21 PRINTC: LD A,(ARG1) + 1B87 4F LD C,A + 1B88 CDB604 CALL COUT + 1B8B C31012 JP MLOOP + + 1B8E 2ABB21 PRINTN: LD HL,(ARG1) + 1B91 CD971B CALL PRNTNC + 1B94 C31012 JP MLOOP + + 1B97 7C PRNTNC: LD A,H + 1B98 B7 OR A + 1B99 FCC51B CALL M,PRNTNG ;NEGATIVE NUMBER + 1B9C 0600 LD B,0 ;DIGIT COUNT + 1B9E 7C PRNTN1: LD A,H + 1B9F B5 OR L + 1BA0 CAAE1B JP Z,PRNTN3 + 1BA3 110A00 LD DE,10 + 1BA6 CD451C CALL DIVIDE + 1BA9 D5 PUSH DE + 1BAA 04 INC B + 1BAB C39E1B JP PRNTN1 + + 1BAE AF PRNTN3: XOR A + 1BAF 80 ADD A,B + 1BB0 CAC01B JP Z,PRNTN6 ;PRINT AT LEAST 0 + 1BB3 D1 PRNTN4: POP DE + 1BB4 3E30 LD A,'0' + 1BB6 83 ADD A,E + 1BB7 4F LD C,A + 1BB8 CDB604 CALL COUT + 1BBB 05 DEC B + 1BBC C2B31B JP NZ,PRNTN4 + 1BBF C9 RET + + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 66 + + + 1BC0 0E30 PRNTN6: LD C,'0' + 1BC2 C3B604 JP COUT + + 1BC5 0E2D PRNTNG: LD C,'-' ;PRINT - + 1BC7 CDB604 CALL COUT + 1BCA C38B1C JP SIGNCN ;CHANGE SIGN + + 1BCD 2ABB21 RANDOM: LD HL,(ARG1) ;RANDOM GENERATOR + 1BD0 EB EX DE,HL + 1BD1 CDEE1B CALL RND ;GET THE BASE NUMBER + 1BD4 CD451C CALL DIVIDE + 1BD7 EB EX DE,HL ;GET REMAINDER + 1BD8 23 INC HL ;MAKE NOT EQUAL TO 0 + 1BD9 C32B13 JP PUTVAL + + 1BDC 2ABB21 ZPUSH: LD HL,(ARG1) + 1BDF CD2C1D CALL PSHSTK + 1BE2 C31012 JP MLOOP + + 1BE5 CD451D ZPOP: CALL POPSTK + 1BE8 3ABB21 LD A,(ARG1) + 1BEB C34B17 JP VARPTR + ; + ; ********************************************************************** + ; * * + ; * ZORK - RANDOM ROUTINES * + ; * * + ; ********************************************************************** + ; + 1BEE C5 RND: PUSH BC + 1BEF 0E02 LD C,2 ;2 TIMES THROUGH LOOP + 1BF1 0608 RND2: LD B,8 + 1BF3 21AC21 LD HL,SHIFT + 1BF6 7E LD A,(HL) + 1BF7 07 RND1: RLCA + 1BF8 07 RLCA + 1BF9 07 RLCA + 1BFA AE XOR (HL) + 1BFB 17 RLA + 1BFC 17 RLA + 1BFD 21AC21 LD HL,SHIFT + 1C00 7E LD A,(HL) + 1C01 17 RLA + 1C02 77 LD (HL),A + 1C03 23 INC HL + 1C04 7E LD A,(HL) + 1C05 17 RLA + 1C06 77 LD (HL),A + 1C07 23 INC HL + 1C08 7E LD A,(HL) + 1C09 17 RLA + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 67 + + + 1C0A 77 LD (HL),A + 1C0B 23 INC HL + 1C0C 7E LD A,(HL) + 1C0D 17 RLA + 1C0E 77 LD (HL),A + 1C0F 05 DEC B + 1C10 C2F71B JP NZ,RND1 + 1C13 0D DEC C + 1C14 C2F11B JP NZ,RND2 + 1C17 C1 POP BC + 1C18 2AAE21 LD HL,(SHIFT+2) ;GET THE NUMBER + 1C1B C9 RET + + 1C1C C5 MULT: PUSH BC ;DEHL <=DE*HL + 1C1D 010000 LD BC,0 + 1C20 3E10 LD A,16 ;LOOP COUNTER + 1C22 F5 MULT1: PUSH AF + 1C23 7B LD A,E + 1C24 E601 AND 1 ;CHECK BIT FOR ADD + 1C26 CA2E1C JP Z,MULT2 ;SKIP ADD PART IF 0 + 1C29 E5 PUSH HL ;SAVE MULTIPLIER + 1C2A 09 ADD HL,BC ;ADD PART + 1C2B 44 LD B,H + 1C2C 4D LD C,L + 1C2D E1 POP HL ;RESTORE H + 1C2E 78 MULT2: LD A,B ;32 BIT SHIFT REMEMBERING CARRY + 1C2F 1F RRA + 1C30 47 LD B,A + 1C31 79 LD A,C + 1C32 1F RRA + 1C33 4F LD C,A + 1C34 7A LD A,D + 1C35 1F RRA + 1C36 57 LD D,A + 1C37 7B LD A,E + 1C38 1F RRA + 1C39 5F LD E,A + 1C3A F1 POP AF ;GET BACK LOOP COUNT + 1C3B 3D DEC A + 1C3C C2221C JP NZ,MULT1 + 1C3F 62 LD H,D ;PUT LOW ORDER ANSWER IN HL + 1C40 6B LD L,E + 1C41 50 LD D,B ;HIGH PART IN DE + 1C42 59 LD E,C + 1C43 C1 POP BC + 1C44 C9 RET + + 1C45 C5 DIVIDE: PUSH BC ;HL<=HL/DE, REMAINDER IN DE + 1C46 44 LD B,H + 1C47 4D LD C,L + 1C48 7A LD A,D ;NEGATE DIVISOR + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 68 + + + 1C49 2F CPL + 1C4A 57 LD D,A + 1C4B 7B LD A,E + 1C4C 2F CPL + 1C4D 5F LD E,A + 1C4E 13 INC DE ;FOR TWO'S COMPLEMENT + 1C4F 210000 LD HL,0 ;INITIAL VALUE FOR REMAINDER + 1C52 3E11 LD A,17 ;INIT LOOP COUNTER + 1C54 E5 DDIV0: PUSH HL ;SAVE REMAINDER + 1C55 19 ADD HL,DE ;SUB DIVIS + 1C56 D25A1C JP NC,DDIV1 ;UNDERFLOW, RESTORE HL + 1C59 E3 EX (SP),HL + 1C5A E1 DDIV1: POP HL + 1C5B F5 PUSH AF ;SAVE LOOP COUNTER + 1C5C 79 LD A,C ;4 REG SHIFT LEFT + 1C5D 17 RLA ;WITH CARRY + 1C5E 4F LD C,A ;CY->C->B->L->H + 1C5F 78 LD A,B + 1C60 17 RLA + 1C61 47 LD B,A + 1C62 7D LD A,L + 1C63 17 RLA + 1C64 6F LD L,A + 1C65 7C LD A,H + 1C66 17 RLA + 1C67 67 LD H,A + 1C68 F1 POP AF ;RESTORE LOOP COUNTER + 1C69 3D DEC A ;DECREMENT IT + 1C6A C2541C JP NZ,DDIV0 ;KEEP LOOPING + + ;CLEANUP, SHIFT REMAINDER RIGHT AND RETURN IN DE + 1C6D B7 OR A + 1C6E 7C LD A,H + 1C6F 1F RRA + 1C70 57 LD D,A + 1C71 7D LD A,L + 1C72 1F RRA + 1C73 5F LD E,A + 1C74 60 LD H,B + 1C75 69 LD L,C + 1C76 C1 POP BC + 1C77 C9 RET + + 1C78 AF SIGNC: XOR A + 1C79 32BA21 LD (SIGNF),A ;SET SIGNF + 1C7C CD931C CALL SIGNPC ;POS CHECK + 1C7F EB EX DE,HL + 1C80 CD931C CALL SIGNPC + 1C83 EB EX DE,HL + 1C84 C9 RET + + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 69 + + + 1C85 3ABA21 SIGNS: LD A,(SIGNF) ;CHECK FOR SIGN + 1C88 E601 AND 1 ;EVEN OR ODD + 1C8A C8 RET Z ;EVEN NUMBER OF NEGATIVES, ANSWER OK + 1C8B AF SIGNCN: XOR A ;CHANGE SIGN + 1C8C 95 SUB L + 1C8D 6F LD L,A + 1C8E 3E00 LD A,0 + 1C90 9C SBC A,H + 1C91 67 LD H,A ;INVERTED HL + 1C92 C9 RET + + 1C93 7C SIGNPC: LD A,H + 1C94 B7 OR A + 1C95 F0 RET P ;POSITIVE + 1C96 3ABA21 LD A,(SIGNF) + 1C99 3C INC A + 1C9A 32BA21 LD (SIGNF),A + 1C9D C38B1C JP SIGNCN ;CHANGE SIGN + + 1CA0 3ABB21 FLAGSU: LD A,(ARG1) ;SETUP FOR FLAG ROUTINES + 1CA3 CDF41C CALL OBJLOC ;BC WILL HAVE BIT POSITION, DE FLAG VALUE + 1CA6 3ABD21 LD A,(ARG2) ;HL WILL GET OBJ POINTER + 1CA9 FE10 CP 16 + 1CAB DAB21C JP C,FLGSU1 ;NEXT WORD + 1CAE D610 SUB 16 ;SECOND SET OF FLAGS + 1CB0 23 INC HL + 1CB1 23 INC HL + 1CB2 E5 FLGSU1: PUSH HL + 1CB3 47 LD B,A + 1CB4 3E0F LD A,15 + 1CB6 90 SUB B + 1CB7 210100 LD HL,1 + 1CBA CAC21C FLGSU2: JP Z,FLGSU3 ;BIT IN POSITION + 1CBD 29 ADD HL,HL + 1CBE 3D DEC A + 1CBF C3BA1C JP FLGSU2 + + 1CC2 44 FLGSU3: LD B,H + 1CC3 4D LD C,L + 1CC4 E1 POP HL + 1CC5 56 LD D,(HL) + 1CC6 23 INC HL + 1CC7 5E LD E,(HL) + 1CC8 2B DEC HL + 1CC9 C9 RET + + 1CCA 3ABB21 PROPB: LD A,(ARG1) ;BEG OF PROPERTY PART OF OBJECT + 1CCD CDF41C CALL OBJLOC + 1CD0 110700 LD DE,7 + 1CD3 19 ADD HL,DE + 1CD4 56 LD D,(HL) + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 70 + + + 1CD5 23 INC HL + 1CD6 5E LD E,(HL) + 1CD7 2AD921 LD HL,(ZCODEP) + 1CDA 19 ADD HL,DE + 1CDB 7E LD A,(HL) ;LENGTH OF DESCRIPTION + 1CDC 87 ADD A,A ;*2 + 1CDD 3C INC A ;+1 + 1CDE C3081F JP HLOFF ;INDEX AND RETURN + + 1CE1 7E PROPN: LD A,(HL) ;HL HAS REAL PROP POINTER + 1CE2 E61F AND 1FH + 1CE4 C9 RET + + 1CE5 7E PROPL: LD A,(HL) ;PROP LENGTH, HL HAS REAL PROP POINTER + 1CE6 07 RLCA + 1CE7 07 RLCA + 1CE8 07 RLCA + 1CE9 E607 AND 7 + 1CEB C9 RET + + 1CEC CDE51C PROPNX: CALL PROPL + 1CEF C602 ADD A,2 + 1CF1 C3081F JP HLOFF ;NEXT PROP POINTER + + 1CF4 D5 OBJLOC: PUSH DE ;GET OBJECT LOCATION, A HAS OBJECT NUMBER + 1CF5 6F LD L,A + 1CF6 2600 LD H,0 + 1CF8 54 LD D,H + 1CF9 5D LD E,L + 1CFA 29 ADD HL,HL + 1CFB 29 ADD HL,HL + 1CFC 29 ADD HL,HL + 1CFD 19 ADD HL,DE + 1CFE 113500 LD DE,53 + 1D01 19 ADD HL,DE ;9*NUMBER + 53 + 1D02 E5 PUSH HL ;OBJECT OFFSET + 1D03 2AD921 LD HL,(ZCODEP) + 1D06 110A00 LD DE,ZOBJEC + 1D09 19 ADD HL,DE + 1D0A 56 LD D,(HL) + 1D0B 23 INC HL + 1D0C 5E LD E,(HL) + 1D0D 2AD921 LD HL,(ZCODEP) + 1D10 19 ADD HL,DE + 1D11 D1 POP DE + 1D12 19 ADD HL,DE ;REAL ADDRESS + 1D13 D1 POP DE + 1D14 C9 RET + + 1D15 2ABB21 GETARG: LD HL,(ARG1) + 1D18 EB EX DE,HL + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 71 + + + 1D19 2ABD21 LD HL,(ARG2) ;GET BOTH ARGS + 1D1C C9 RET + + 1D1D 7A SHLGED: LD A,D + 1D1E AC XOR H + 1D1F F2251D JP P,HLGEDE ;BOTH OF SAME SIGN + 1D22 7C LD A,H + 1D23 BA CP D ;CARRY WILL BE SET IF D NEG AND THUS LESS THAN H + 1D24 C9 RET + + 1D25 7A HLGEDE: LD A,D ;RETURN WITH CARRY SET IF HL>=DE + 1D26 BC CP H + 1D27 C0 RET NZ + 1D28 7D LD A,L + 1D29 BB CP E + 1D2A 3F CCF + 1D2B C9 RET + + 1D2C D5 PSHSTK: PUSH DE + 1D2D EB EX DE,HL ;PUSH STACK + 1D2E 2A070E LD HL,(ZSTAKP) ;STACK POINTER + 1D31 2B DEC HL + 1D32 73 LD (HL),E + 1D33 2B DEC HL + 1D34 72 LD (HL),D + 1D35 22070E LD (ZSTAKP),HL ;SAVE POINTER + 1D38 21A821 LD HL,ZSTAKC ;COUNT + 1D3B 34 INC (HL) + 1D3C 7E LD A,(HL) + 1D3D FEE0 CP ZSTAKL + 1D3F CC0602 CALL Z,ZER + 1D42 EB EX DE,HL + 1D43 D1 POP DE + 1D44 C9 RET + ; --------- + ; POP STACK + ; --------- + ; POP WORD OFF Z-STACK AND RETURN IT IN HL + 1D45 D5 POPSTK: PUSH DE ;SAVE DE + 1D46 2A070E LD HL,(ZSTAKP) ;HL <= Z-STACK POINTER + 1D49 56 LD D,(HL) ;GET MSB OF WORD + 1D4A 23 INC HL + 1D4B 5E LD E,(HL) ;GET LSB OF WORD + 1D4C 23 INC HL + 1D4D 22070E LD (ZSTAKP),HL ;SAVE NEW Z-STACK POINTER + 1D50 21A821 LD HL,ZSTAKC ;CHECK COUNT + 1D53 35 DEC (HL) + 1D54 CC0602 CALL Z,ZER ;OVER POP ERROR + 1D57 EB EX DE,HL ;VALUE IN HL + 1D58 D1 POP DE ;RESTORE DE + 1D59 C9 RET + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 72 + + + ; + ; ********************************************************************** + ; * * + ; * ZORK - PAGING ROUTINES * + ; * * + ; ********************************************************************** + ; + 1D5A 3ACE21 NEXTPC: LD A,(ZPCFLG) ;HAS PAGE MOVED? + 1D5D B7 OR A + 1D5E CA871D JP Z,NXTPC1 ;PAGE HAS MOVED + 1D61 2ACC21 LD HL,(ZPCPNT) + 1D64 46 LD B,(HL) ;GET VALUE IN B + 1D65 23 INC HL + 1D66 22CC21 LD (ZPCPNT),HL ;STORE BACK POINTER + 1D69 2AA621 LD HL,(ZPCL) + 1D6C 2C INC L + 1D6D 22A621 LD (ZPCL),HL ;ASSUME OK AT FIRST + 1D70 78 LD A,B + 1D71 C0 RET NZ ;OK IF L NOT ZERO + 1D72 7C LD A,H ;CROSSED 256 BYTE BOUNDRY + 1D73 24 INC H + 1D74 22A621 LD (ZPCL),HL ;AGAIN ASSUME NOT PASSED 256 BOUNTRY + 1D77 B7 OR A + 1D78 78 LD A,B + 1D79 C8 RET Z ;DID NOT CROSS 512 BOUNDRY + 1D7A AF XOR A + 1D7B 32A721 LD (ZPCL+1),A ;0 ZPCL + 1D7E 32CE21 LD (ZPCFLG),A ;BAD DATA IN PCPNT, WILL HAVE TO FETCH NEW BLOCK + 1D81 21A521 LD HL,ZPCH ;INCREMENT ZPC HIGH + 1D84 34 INC (HL) + 1D85 78 LD A,B + 1D86 C9 RET ;RETURN, TROUBLE NEXT TIME + + 1D87 3AA521 NXTPC1: LD A,(ZPCH) ;GET ZPAGE NUMBER + 1D8A 21B921 LD HL,ZMEMT ;TOP OF LOW MEM + 1D8D BE CP (HL) + 1D8E 2AD921 LD HL,(ZCODEP) ;PRELOAD PORTION + 1D91 DAA61D JP C,NXTPCL + 1D94 CD0F1F CALL FNDPGE + 1D97 32CF21 LD (ZPCPG),A ;STORE PAGE + 1D9A DAB91D JP C,NXTPC2 ;COULD NOT FIND PAGE, SWAP IT IN (OH WHAT A SHAME) + 1D9D CDC91E NXTPC3: CALL SPLICE ;PUT AT TOP OF LIST + 1DA0 3ACF21 LD A,(ZPCPG) ;SET UP POINTER TO PAGE + 1DA3 2AD721 LD HL,(PGBUFP) ;POINTER TO BEGINNING OF PAGE BUFFERS + 1DA6 NXTPCL: + 1DA6 87 ADD A,A + 1DA7 84 ADD A,H + 1DA8 67 LD H,A + 1DA9 EB EX DE,HL ;DE NOW HAS POINTER TO BEG OF BUFFER + 1DAA 2AA621 LD HL,(ZPCL) + 1DAD 19 ADD HL,DE ;ADD IN OFFSET + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 73 + + + 1DAE 22CC21 LD (ZPCPNT),HL ;ZPCPNT NOW VALID + 1DB1 3EFF LD A,0FFH + 1DB3 32CE21 LD (ZPCFLG),A + 1DB6 C35A1D JP NEXTPC ;TRY AGAIN, THIS TIME IT WILL NOT FAIL + + 1DB9 21D621 NXTPC2: LD HL,MPCPG ;CHECK IF DISTROYING MPC + 1DBC BE CP (HL) + 1DBD C2C61D JP NZ,NXTPC4 ;NOT DISTROYING PAGE + 1DC0 47 LD B,A + 1DC1 AF XOR A + 1DC2 32D521 LD (MPCFLG),A + 1DC5 78 LD A,B + 1DC6 2AD721 NXTPC4: LD HL,(PGBUFP) + 1DC9 87 ADD A,A + 1DCA 84 ADD A,H + 1DCB 67 LD H,A ;POINTER TO BEGINNING OF BUFFER + 1DCC 3AA521 LD A,(ZPCH) + 1DCF CDF702 CALL GETDSK + 1DD2 3ACF21 LD A,(ZPCPG) + 1DD5 47 LD B,A + 1DD6 21C90F LD HL,PGTBL + 1DD9 CD081F CALL HLOFF + 1DDC 3AA521 LD A,(ZPCH) + 1DDF 77 LD (HL),A ;SET PAGE TABLE ENTRY + 1DE0 78 LD A,B + 1DE1 C39D1D JP NXTPC3 ;PAGE NOW IN MEMORY + + 1DE4 7C SETWRD: LD A,H + 1DE5 B7 OR A + 1DE6 1F RRA + 1DE7 32D021 LD (MPCH),A + 1DEA 7C SETWR1: LD A,H + 1DEB E601 AND 1 + 1DED 67 LD H,A + 1DEE 22D121 LD (MPCL),HL + 1DF1 AF XOR A + 1DF2 32D521 LD (MPCFLG),A + 1DF5 C9 RET + + 1DF6 7C SETSTR: LD A,H + 1DF7 32D021 LD (MPCH),A + 1DFA 29 ADD HL,HL + 1DFB C3EA1D JP SETWR1 + + 1DFE AF GETFRE: XOR A + 1DFF 32D521 LD (MPCFLG),A ;NO MEM PAGE LEFT + 1E02 3ADD21 LD A,(PGBOT) + 1E05 32D621 LD (MPCPG),A + 1E08 CD961E CALL CKZPCP + 1E0B CDC91E CALL SPLICE + 1E0E 3AD621 LD A,(MPCPG) + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 74 + + + 1E11 47 LD B,A + 1E12 2AD721 LD HL,(PGBUFP) + 1E15 87 ADD A,A + 1E16 84 ADD A,H + 1E17 67 LD H,A + 1E18 22D321 LD (MPCPNT),HL + 1E1B 78 LD A,B + 1E1C 21C90F LD HL,PGTBL + 1E1F CD081F CALL HLOFF + 1E22 3600 LD (HL),0 + 1E24 C9 RET + + 1E25 CD301E GETWRD: CALL GETBYT + 1E28 F5 PUSH AF + 1E29 CD301E CALL GETBYT ;GET A FULL WORD + 1E2C 6F LD L,A + 1E2D F1 POP AF + 1E2E 67 LD H,A + 1E2F C9 RET + + 1E30 3AD521 GETBYT: LD A,(MPCFLG) ;HAS PAGE MOVED? + 1E33 B7 OR A + 1E34 CA5D1E JP Z,GETBT1 ;PAGE HAS MOVED + 1E37 2AD321 LD HL,(MPCPNT) + 1E3A 46 LD B,(HL) ;GET VALUE IN B + 1E3B 23 INC HL + 1E3C 22D321 LD (MPCPNT),HL ;STORE BACK POINTER + 1E3F 2AD121 LD HL,(MPCL) + 1E42 2C INC L + 1E43 22D121 LD (MPCL),HL ;ASSUME OK AT FIRST + 1E46 78 LD A,B + 1E47 C0 RET NZ ;OK IF L NOT ZERO + 1E48 7C LD A,H ;CROSSED 256 BYTE BOUNDRY + 1E49 24 INC H + 1E4A 22D121 LD (MPCL),HL ;AGAIN ASSUME NOT PASSED 256 BOUNTRY + 1E4D B7 OR A + 1E4E 78 LD A,B + 1E4F C8 RET Z ;DID NOT CROSS 512 BOUNDRY + 1E50 AF XOR A + 1E51 32D221 LD (MPCL+1),A ;0 MPCL + 1E54 32D521 LD (MPCFLG),A ;BAD DATA IN PCPNT, WILL HAVE TO FETCH NEW BLOCK + 1E57 21D021 LD HL,MPCH ;INCREMENT ZPC HIGH + 1E5A 34 INC (HL) + 1E5B 78 LD A,B + 1E5C C9 RET ;RETURN, TROUBLE NEXT TIME + + 1E5D 3AB821 GETBT1: LD A,(VERF) + 1E60 B7 OR A + 1E61 C2A21E JP NZ,GETB1A ;IN VERIFY MODE + 1E64 3AD021 LD A,(MPCH) ;GET MPAGE NUMBER + 1E67 21B921 LD HL,ZMEMT ;TOP OF LOW MEM + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 75 + + + 1E6A BE CP (HL) + 1E6B 2AD921 LD HL,(ZCODEP) ;PRELOAD PORTION + 1E6E DA831E JP C,GETBTL + 1E71 CD0F1F CALL FNDPGE + 1E74 32D621 LD (MPCPG),A ;STORE PAGE + 1E77 DAA81E JP C,GETBT2 ;COULD NOT FIND PAGE, SWAP IT IN (OH WHAT A SHAME) + 1E7A CDC91E GETBT3: CALL SPLICE ;PUT AT TOP OF LIST + 1E7D 3AD621 LD A,(MPCPG) ;SET UP POINTER TO PAGE + 1E80 2AD721 LD HL,(PGBUFP) ;POINTER TO BEGINNING OF PAGE BUFFERS + 1E83 GETBTL: + 1E83 87 ADD A,A + 1E84 84 ADD A,H + 1E85 67 LD H,A + 1E86 EB EX DE,HL + 1E87 2AD121 LD HL,(MPCL) + 1E8A 19 ADD HL,DE + 1E8B 22D321 LD (MPCPNT),HL + 1E8E 3EFF LD A,0FFH + 1E90 32D521 LD (MPCFLG),A + 1E93 C3301E JP GETBYT ;TRY AGAIN, THIS TIME IT WILL NOT FAIL + + + 1E96 21CF21 CKZPCP: LD HL,ZPCPG ;CHECK IF DISTROYING ZPC + 1E99 BE CP (HL) + 1E9A C0 RET NZ ;NOT DISTROYING PAGE + 1E9B 47 LD B,A + 1E9C AF XOR A + 1E9D 32CE21 LD (ZPCFLG),A + 1EA0 78 LD A,B + 1EA1 C9 RET + + 1EA2 3ADD21 GETB1A: LD A,(PGBOT) + 1EA5 32D621 LD (MPCPG),A ;NEW PAGE + 1EA8 CD961E GETBT2: CALL CKZPCP + 1EAB 2AD721 LD HL,(PGBUFP) + 1EAE 87 ADD A,A + 1EAF 84 ADD A,H + 1EB0 67 LD H,A ;POINTER TO BEGINNING OF BUFFER + 1EB1 3AD021 LD A,(MPCH) + 1EB4 CDF702 CALL GETDSK + 1EB7 3AD621 LD A,(MPCPG) + 1EBA 47 LD B,A + 1EBB 21C90F LD HL,PGTBL + 1EBE CD081F CALL HLOFF + 1EC1 3AD021 LD A,(MPCH) + 1EC4 77 LD (HL),A ;SET PAGE TABLE ENTRY + 1EC5 78 LD A,B + 1EC6 C37A1E JP GETBT3 ;PAGE NOW IN MEMORY + + 1EC9 4F SPLICE: LD C,A ;SPLICE PAGE IN A TO TOP OF LIST + 1ECA 3ADC21 LD A,(PGTOP) ;GET OLD TOP + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 76 + + + 1ECD B9 CP C + 1ECE C8 RET Z ;SAME TOP AS LAST + 1ECF 47 LD B,A + 1ED0 79 LD A,C + 1ED1 32DC21 LD (PGTOP),A ;NEW TOP + 1ED4 210910 LD HL,PGTBLF + 1ED7 CD081F CALL HLOFF + 1EDA 5E LD E,(HL) ;E HAS OLD FORWARD POINTER + 1EDB 70 LD (HL),B ;NEW FORWARD TO OLD TOP + 1EDC 214910 LD HL,PGTBLB + 1EDF 79 LD A,C + 1EE0 CD081F CALL HLOFF + 1EE3 56 LD D,(HL) ;D GETS OLD BACK POINTER + 1EE4 36FF LD (HL),0FFH ;TOP HAS NO BACK + 1EE6 7A LD A,D + 1EE7 210910 LD HL,PGTBLF + 1EEA CD081F CALL HLOFF + 1EED 73 LD (HL),E ;PATCH FORWARD POINTER + 1EEE 78 LD A,B + 1EEF 214910 LD HL,PGTBLB + 1EF2 CD081F CALL HLOFF + 1EF5 71 LD (HL),C + 1EF6 7B LD A,E + 1EF7 3C INC A + 1EF8 CA031F JP Z,SPLIC1 ;WAS LAST BLOCK WITHOUT FORWARD POINTER + 1EFB 214810 LD HL,PGTBLB-1 ;OFFSET INC A + 1EFE CD081F CALL HLOFF + 1F01 72 LD (HL),D ;SPLICE BACK POINTER + 1F02 C9 RET + + 1F03 7A SPLIC1: LD A,D + 1F04 32DD21 LD (PGBOT),A ;NEW BOTTOM OF LIST + 1F07 C9 RET + + 1F08 HLOFF: + 1F08 85 ADD A,L ;INDIRECT HL THROUGH A + 1F09 6F LD L,A + 1F0A 3E00 LD A,0 + 1F0C 8C ADC A,H + 1F0D 67 LD H,A + 1F0E C9 RET + + 1F0F 21DB21 FNDPGE: LD HL,NPGS ;FIND PAGE IN A, RETURN WITH CARRY + 1F12 ;SET IF NOT FOUND. A WILL HAVE FOUND PAGE OR + 1F12 ;BOTTOM OF PAGE LIST + 1F12 46 LD B,(HL) + 1F13 0E00 LD C,0 + 1F15 21C90F LD HL,PGTBL + 1F18 BE FNDPGL: CP (HL) + 1F19 CA271F JP Z,FNDPG1 ;SUCCESS + 1F1C 0C INC C + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 77 + + + 1F1D 23 INC HL + 1F1E 05 DEC B + 1F1F C2181F JP NZ,FNDPGL + 1F22 3ADD21 LD A,(PGBOT) ;NOT FOUND + 1F25 37 SCF ;SET CARRY AND RETURN BOTTOM + 1F26 C9 RET + + 1F27 79 FNDPG1: LD A,C + 1F28 C9 RET ;CARRY WILL BE CLEARED + ; + ; ********************************************************************** + ; * * + ; * ZORK - STRING ROUTINES * + ; * * + ; ********************************************************************** + ; + ; --------------- + ; PRINT Z-STRING + ; --------------- + 1F29 AF PZSTR: XOR A ;PRINT ZSTRING POINTED TO BY MPC (NOT REENTRENT) + 1F2A 32DF21 LD (CSPERM),A ;PERMANENT CHARSET + 1F2D 32E021 LD (STBYTF),A ;RESET STRING BYTE FLAG + 1F30 3D DEC A + 1F31 32DE21 LD (CSTEMP),A ;NO TEMP CHARSET IN EFFECT + + 1F34 CD4F20 PZSTRL: CALL GETZCH ;GET A Z-CHARACTER + 1F37 D8 RET C ;END OF STRING IF CARRY SET + 1F38 47 LD B,A + 1F39 B7 OR A + 1F3A CAEF1F JP Z,PZSTRS ;0=SPACE + 1F3D FE04 CP 4 ;IS THIS AN F-WORD? + 1F3F DA8E1F JP C,PZFWRD ; YES. + 1F42 FE06 CP 6 ;IS IT A SHIFT CHAR? + 1F44 DA0720 JP C,PZSTRP ; YES. CHANGE CHAR SET + 1F47 CD3E20 CALL GETMOD + 1F4A B7 OR A ;IS IT CHARSET 0? + 1F4B C2581F JP NZ,PZSTR1 ; NOPE. + + ;PRINT LOWER CASE CHAR (CHARSET 0) + 1F4E 3E5B LD A,'a'-6 ;ASCII "a" MINUS Z-OFFSET + 1F50 PZSTP0: + 1F50 80 ADD A,B ;ADD CHARACTER + 1F51 4F LD C,A + 1F52 CDB604 PZSTP1: CALL COUT ;PRINT RESULT + 1F55 C3341F JP PZSTRL ;AND FETCH ANOTHER Z-CHAR + + ;CHARSET 1 OR 2? + 1F58 3D PZSTR1: DEC A ;SET 1? + 1F59 C2611F JP NZ,PZSTR2 ; NOPE, IT'S SET 2 + + ;PRINT UPPER-CASE CHAR (CHARSET 1) + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 78 + + + 1F5C 3E3B LD A,'A'-6 ;ASCII "A" MINUS Z-OFFSET + 1F5E C3501F JP PZSTP0 ;PROCESS IT + + ;DECODE/PRINT CHARSET 2 + 1F61 78 PZSTR2: LD A,B ;MODE 2 + 1F62 FE06 CP 6 ;DIRECT ASCII CHARACTER? + 1F64 CA761F JP Z,PZSTRA ; YES. + 1F67 FE07 CP 7 ;CARRIAGE RETURN? + 1F69 CAF41F JP Z,PZSTRC ; YES. + 1F6C 211E20 LD HL,CHRTBL-8 ; NO. SUBTRACT OFFSET + 1F6F CD081F CALL HLOFF + 1F72 4E LD C,(HL) ;GET CHARACTER FROM TABLE + 1F73 C3521F JP PZSTP1 + + 1F76 CD4F20 PZSTRA: CALL GETZCH ;FORM CHARACTER FROM TWO BYTES + 1F79 0F RRCA + 1F7A 0F RRCA + 1F7B 0F RRCA + 1F7C 4F LD C,A + 1F7D C5 PUSH BC + 1F7E CD4F20 CALL GETZCH + 1F81 C1 POP BC + 1F82 81 ADD A,C + 1F83 4F LD C,A + 1F84 FE09 CP 9 ;TAB? + 1F86 C2521F JP NZ,PZSTP1 + 1F89 0E20 LD C,20H + 1F8B C3521F JP PZSTP1 ;PRINT IT + + 1F8E 3D PZFWRD: DEC A + 1F8F 87 ADD A,A + 1F90 87 ADD A,A + 1F91 87 ADD A,A + 1F92 87 ADD A,A + 1F93 87 ADD A,A ;SET NUMBER -1 TIMES 32 + 1F94 32C721 LD (FWSET),A + 1F97 CD4F20 CALL GETZCH ;GET STRING NUMBER + 1F9A D8 RET C ;BAD IF OUT OF CHARACTERS + 1F9B 47 LD B,A + 1F9C 3ADF21 LD A,(CSPERM) ;PRINT ZSTRING POINTED TO BY MPC + 1F9F 67 LD H,A ;MAKE IT REENTERENT + 1FA0 3AE021 LD A,(STBYTF) + 1FA3 6F LD L,A + 1FA4 E5 PUSH HL + 1FA5 2AE121 LD HL,(ZSTWRD) + 1FA8 E5 PUSH HL + 1FA9 2AD121 LD HL,(MPCL) + 1FAC E5 PUSH HL + 1FAD 2AD021 LD HL,(MPCH) + 1FB0 E5 PUSH HL + 1FB1 2AC821 LD HL,(FWORDS) + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 79 + + + 1FB4 3AC721 LD A,(FWSET) + 1FB7 80 ADD A,B ;ENTRY INTO 96 WORD TABLE + 1FB8 87 ADD A,A + 1FB9 CD081F CALL HLOFF ;POINTER TO SPECIAL STRING + 1FBC 7E LD A,(HL) + 1FBD 32D021 LD (MPCH),A + 1FC0 23 INC HL + 1FC1 6E LD L,(HL) + 1FC2 2600 LD H,0 + 1FC4 29 ADD HL,HL + 1FC5 22D121 LD (MPCL),HL ;SET NEW MPC + 1FC8 AF XOR A + 1FC9 32D521 LD (MPCFLG),A ;MPCPNT NOT VALID + 1FCC CD291F CALL PZSTR ;PRINT SUB STRING (REENTRENT VERSION) + 1FCF AF XOR A ;RESTORE REENTRENT VALUES + 1FD0 32D521 LD (MPCFLG),A + 1FD3 E1 POP HL + 1FD4 7D LD A,L + 1FD5 32D021 LD (MPCH),A + 1FD8 E1 POP HL + 1FD9 22D121 LD (MPCL),HL + 1FDC E1 POP HL + 1FDD 22E121 LD (ZSTWRD),HL + 1FE0 E1 POP HL + 1FE1 7C LD A,H + 1FE2 32DF21 LD (CSPERM),A + 1FE5 7D LD A,L + 1FE6 32E021 LD (STBYTF),A + 1FE9 CD3E20 CALL GETMOD + 1FEC C3341F JP PZSTRL + + 1FEF 0E20 PZSTRS: LD C,20H + 1FF1 C3521F JP PZSTP1 ;PRINT SPACE + + 1FF4 0E0D PZSTRC: LD C,0DH ;CR-LF + 1FF6 CDB604 CALL COUT + 1FF9 0E0A LD C,0AH + 1FFB C3521F JP PZSTP1 + + 1FFE 78 PZSTRT: LD A,B ;SET TEMP MODE + 1FFF D603 SUB 3 + 2001 32DE21 LD (CSTEMP),A + 2004 C3341F JP PZSTRL + + 2007 CD3E20 PZSTRP: CALL GETMOD ;SET CHAR MODE + 200A B7 OR A ;MODE 0 IS TEMPORARY + 200B CAFE1F JP Z,PZSTRT + 200E 3D DEC A + 200F 87 ADD A,A + 2010 80 ADD A,B + 2011 D604 SUB 4 ;INDEX INTO PERMTB + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 80 + + + 2013 E5 PUSH HL + 2014 212220 LD HL,PERMTB + 2017 CD081F CALL HLOFF + 201A 7E LD A,(HL) + 201B E1 POP HL + 201C 32DF21 LD (CSPERM),A + 201F C3341F JP PZSTRL + + 2022 01000002 PERMTB: DB 1,0,0,2 + + 2026 30313233 CHRTBL: DB '0123456789.,!?_#' + 2036 2722 DB $27,$22 + 2038 2F5C2D3A DB '/\-:()' + + 203E 3ADE21 GETMOD: LD A,(CSTEMP) + 2041 3C INC A + 2042 3ADF21 LD A,(CSPERM) + 2045 C8 RET Z ;RETURN WITH PERM MODE IF NO TEMP MODE + 2046 E5 PUSH HL + 2047 21DE21 LD HL,CSTEMP + 204A 7E LD A,(HL) + 204B 36FF LD (HL),0FFH ;CLEAR MODE AFTER GETTING IT + 204D E1 POP HL + 204E C9 RET + + 204F 3AE021 GETZCH: LD A,(STBYTF) ;FIND OUT WHICH BYTE + 2052 B7 OR A + 2053 37 SCF + 2054 F8 RET M ;OUT OF CHARACTERS + 2055 C26820 JP NZ,GETZH1 ;NOT FIRST BYTE + 2058 3C INC A + 2059 32E021 LD (STBYTF),A + 205C CD251E CALL GETWRD + 205F 22E121 LD (ZSTWRD),HL ;SAVE WORD + 2062 7C LD A,H + 2063 0F RRCA + 2064 0F RRCA + 2065 E61F AND 1FH + 2067 C9 RET + + 2068 3D GETZH1: DEC A + 2069 C27B20 JP NZ,GETZH2 ;LAST CHAR IN WORD + 206C 3E02 LD A,2 + 206E 32E021 LD (STBYTF),A + 2071 2AE121 LD HL,(ZSTWRD) + 2074 29 ADD HL,HL + 2075 29 ADD HL,HL + 2076 29 ADD HL,HL + 2077 7C LD A,H + 2078 E61F AND 1FH + 207A C9 RET + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 81 + + + + 207B AF GETZH2: XOR A + 207C 32E021 LD (STBYTF),A + 207F 2AE121 LD HL,(ZSTWRD) + 2082 7C LD A,H + 2083 B7 OR A + 2084 F28C20 JP P,GETZH3 ;NOT LAST CHAR IN STRING + 2087 3EFF LD A,0FFH + 2089 32E021 LD (STBYTF),A ;INDICATE END OF STRING + 208C 7D GETZH3: LD A,L + 208D E61F AND 1FH + 208F C9 RET + + 2090 AF CONZST: XOR A ;CONVERT TO Z STRING + 2091 32DF21 LD (CSPERM),A + 2094 21E321 LD HL,ZSTBUO ;POINTER TO OUTPUT BUFFER + 2097 0606 LD B,6 ;OUTPUT 6 CHARACTERS TO CONVERT + 2099 3605 CONZSL: LD (HL),5 + 209B 23 INC HL + 209C 05 DEC B + 209D C29920 JP NZ,CONZSL ;FILL BUFFER WITH PAD CHARACTERS + 20A0 0606 LD B,6 + 20A2 11E321 LD DE,ZSTBUO ;OUTPUT + 20A5 21B021 LD HL,ZSTBUI ;INPUT + 20A8 4E CNZSL1: LD C,(HL) + 20A9 23 INC HL + 20AA 79 LD A,C + 20AB B7 OR A + 20AC 3E05 LD A,5 + 20AE CADD20 JP Z,CNZSLO ;BLANKS + 20B1 79 LD A,C + 20B2 FE20 CP ' ' + 20B4 3E00 LD A,0 + 20B6 CADD20 JP Z,CNZSLO ;SPACE + 20B9 D5 CNZSL2: PUSH DE + 20BA 79 LD A,C + 20BB CD3B21 CALL ZCHRCS ;WHICH CHARACTER SET + 20BE 5F LD E,A ;E HAS CHARACTER SET OF CURRENT CHAR + 20BF 3ADF21 LD A,(CSPERM) + 20C2 BB CP E + 20C3 CAD120 JP Z,CNZSLC ;CONVERT THEN OUTPUT + 20C6 7B LD A,E + 20C7 C603 ADD A,3 + 20C9 D1 POP DE + 20CA 12 LD (DE),A ;OUTPUT TEMP SHIFT + 20CB 13 INC DE + 20CC 05 DEC B + 20CD CA5A21 JP Z,CNZSLE + 20D0 D5 PUSH DE + 20D1 79 CNZSLC: LD A,C + 20D2 D1 POP DE + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 82 + + + 20D3 CD3B21 CALL ZCHRCS + 20D6 3D DEC A + 20D7 F2E620 JP P,CNZSC1 ;NOT LOWER CASE + 20DA 79 LD A,C + 20DB D65B SUB 'a'-6 + 20DD 12 CNZSLO: LD (DE),A + 20DE 13 INC DE + 20DF 05 DEC B + 20E0 C2A820 JP NZ,CNZSL1 ;NEXT + 20E3 C35A21 JP CNZSLE ;END + + 20E6 C2EF20 CNZSC1: JP NZ,CNZSC3 ;NOT UPPER CASE + 20E9 79 LD A,C + 20EA D63B SUB 'A'-6 + 20EC C3DD20 JP CNZSLO + + 20EF 79 CNZSC3: LD A,C + 20F0 FE0D CP 0DH + 20F2 C20121 JP NZ,CNZSC4 + 20F5 7E LD A,(HL) + 20F6 FE0A CP 0AH + 20F8 C20121 JP NZ,CNZSC4 + 20FB 23 INC HL + 20FC 3E07 LD A,7 + 20FE C3DD20 JP CNZSLO ;CR-LF + + 2101 79 CNZSC4: LD A,C + 2102 CD2221 CALL CNZS2M + 2105 C2DD20 JP NZ,CNZSLO ;FOUND IN TABLE + 2108 3E06 LD A,6 + 210A 12 LD (DE),A + 210B 13 INC DE + 210C 05 DEC B + 210D CA5A21 JP Z,CNZSLE ;STORE ASCII VERSION + 2110 79 LD A,C + 2111 07 RLCA + 2112 07 RLCA + 2113 07 RLCA + 2114 E603 AND 3 + 2116 12 LD (DE),A + 2117 13 INC DE + 2118 05 DEC B + 2119 CA5A21 JP Z,CNZSLE + 211C 79 LD A,C + 211D E61F AND 1FH + 211F C3DD20 JP CNZSLO + + 2122 C5 CNZS2M: PUSH BC + 2123 E5 PUSH HL + 2124 213D20 LD HL,CHRTBL+23 ;SEARCH TABLE + 2127 0618 LD B,24 + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 83 + + + 2129 BE CNZS2L: CP (HL) + 212A CA3521 JP Z,CNZS2P ;FOUND + 212D 2B DEC HL + 212E 05 DEC B + 212F C22921 JP NZ,CNZS2L + 2132 E1 POP HL ;NOT FOUND + 2133 C1 POP BC + 2134 C9 RET ;FAIL, ZERO SET + + 2135 78 CNZS2P: LD A,B + 2136 C607 ADD A,7 + 2138 E1 POP HL + 2139 C1 POP BC + 213A C9 RET ;PASSED, ZERO CLEARED + + 213B FE61 ZCHRCS: CP 'a' + 213D DA4721 JP C,ZCHRC1 + 2140 FE7B CP 'z'+1 + 2142 D24721 JP NC,ZCHRC1 + 2145 AF XOR A + 2146 C9 RET ;SET 0 + + 2147 FE41 ZCHRC1: CP 'A' + 2149 DA5421 JP C,ZCHRC2 + 214C FE5B CP 'Z'+1 + 214E D25421 JP NC,ZCHRC2 + 2151 3E01 LD A,1 + 2153 C9 RET + + 2154 B7 ZCHRC2: OR A + 2155 C8 RET Z + 2156 F8 RET M ;END + 2157 3E02 LD A,2 + 2159 C9 RET ;ELSE SET 2 + + 215A 01E321 CNZSLE: LD BC,ZSTBUO ;CONVERT OUTPUT STRING + 215D 210000 LD HL,0 + 2160 54 LD D,H + 2161 CD7D21 CALL CNZSE1 + 2164 CD7D21 CALL CNZSE1 + 2167 CD7D21 CALL CNZSE1 + 216A 22E321 LD (ZSTBUO),HL + 216D 210100 LD HL,1 + 2170 CD7D21 CALL CNZSE1 + 2173 CD7D21 CALL CNZSE1 + 2176 CD7D21 CALL CNZSE1 + 2179 22E521 LD (ZSTBUO+2),HL + 217C C9 RET + + 217D 0A CNZSE1: LD A,(BC) + 217E 03 INC BC + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 84 + + + 217F 5F LD E,A + 2180 29 ADD HL,HL + 2181 29 ADD HL,HL + 2182 29 ADD HL,HL + 2183 29 ADD HL,HL + 2184 29 ADD HL,HL + 2185 19 ADD HL,DE + 2186 C9 RET + ; + ; ********************************************************************** + ; * * + ; * ZORK - DATA SECTION * + ; * * + ; ********************************************************************** + ; + 2187 SRND: ;RANDOM INFO FOR SAVE, KEEP TOGETHER + 2187 LOCALS: DS 15*2 ;STORAGE FOR LOCALS + 21A5 00 ZPCH: DB 0 ;HIGH ORDER 8 BITS OF ZPC + 21A6 0000 ZPCL: DW 0 ;LOW ORDER 9 BITS OF ZPC + 21A8 01 ZSTAKC: DB 1 ;STACK COUNT, 1=>0 IMPLIES OVERPOP, NEG=> OVER PUSH + 21A9 0000 OZSTKP: DW 0 ;OLD ZSTACK POINTER + 21AB 00 OZSTKC: DB 0 ;OLD ZSTACK COUNT + ; + 21AC 6A573C99 SHIFT: DB 6AH,57H,3CH,99H + 0029 SRNDC EQU $-SRND + 21B0 ZSTBUI: DS 6 ;ZSTR INPUT BUFFER + 21B6 FF DB 0FFH ;END MARKER + 21B7 01 NOLPT: DB 1 ;NON ZERO IMPLIES DO NOT USE LPT + 21B8 00 VERF: DB 0 ;1 IF IN VERIFY MODE. + 21B9 01 ZMEMT: DB 1 ;FIRST PAGE IN SWAPPING SPACE + + 21BA PURSTP: ;END OF PURE + + 21BA 00 SIGNF: DB 0 ;STORAGE FOR SIGN IN MULT AND DIVIDE + 21BB 0000 ARG1: DW 0 ;OPERRAND 1 + 21BD 0000 ARG2: DW 0 ;" 2 + 21BF 0000 ARG3: DW 0 ;" 3 + 21C1 0000 ARG4: DW 0 ;" 4 + 21C3 00 ARGCNT: DB 0 ;ARG COUNT + 21C4 00 OPCODE: DB 0 ;CURRENT OPCODE + 21C5 0000 GLOBAL: DW 0 ;POINTER TO GLOBAL 0 + 21C7 00 FWSET: DB 0 ;TEMPORARY STORAGE FOR FWORDS CALCULATION + 21C8 0000 FWORDS: DW 0 ;COMMON WORDS POINTER + 21CA 0000 ZPCOFF: DW 0 ;OFFSET FOR FAST JUMPS + 21CC 0000 ZPCPNT: DW 0 ;REAL POINTER TO PC + 21CE 00 ZPCFLG: DB 0 ;0FFH IF VALID PC POINTER + 21CF 00 ZPCPG: DB 0 ;PAGE OF ZPC + 21D0 00 MPCH: DB 0 ;HIGH ORDER 8 BITS OF MEMORY POINTER + 21D1 0000 MPCL: DW 0 ;LOW ORDER 9 BITS OF MEMPOINTER + 21D3 0000 MPCPNT: DW 0 ;REAL POINTER TO MEMORY LOCATION + 21D5 00 MPCFLG: DB 0 ;0FF IF VALID MPCPNT + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 85 + + + 21D6 00 MPCPG: DB 0 ;PAGE NUMBER OF PC PAGE + ; + ;PAGE TABLES + 21D7 0000 PGBUFP: DW 0 ;BUFFER POINTER + 21D9 0000 ZCODEP: DW 0 ;LOW MEM STARTING POINTER + ; + 21DB 00 NPGS: DB 0 ;NUMBER OF PAGES + 21DC 00 PGTOP: DB 0 ;TOP OF LIST PAGE + 21DD 3F PGBOT: DB MAXPGS-1 ;BOTTOM OF LIST + ; + 21DE 00 CSTEMP: DB 0 ;-1 IF NOT TEMP CHAR SET, ELSE SET + 21DF 00 CSPERM: DB 0 ;PERM CHARACTER SET + 21E0 00 STBYTF: DB 0 ;0 FOR FIRST BYTE, 1 FOR 2, 2 FOR 3, 0FFH FOR END + 21E1 0000 ZSTWRD: DW 0 ;WORD STORRAGE + 21E3 ZSTBUO: DS 6 ;OUTPUT BUFFER + 21E9 0000 RTABP: DW 0 ;TEMP FOR ZREAD, RESULT TABLE POINTER + ; + 21EB 0000 LMEMRY: DW 0 ;LAST LOCATION IN MEMORY, FILLED IN BY LOADER + ; + 0100 END START + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 86 +---- SYMBOL TABLE ---- + +ARG1 21BB CPLMAX 0085 FLSLIN 04F7 GETVR1 1302 LOCALS 2187 +ARG2 21BD CPMBUF 0080 FLUSHW 1A9F GETVRG 1316 LPCHK 049B +ARG3 21BF CPMCLF 010D FNDAT 02C7 GETVRL 1307 LPDL 0190 +ARG4 21C1 CPMCPL 0103 FNDPG1 1F27 GETVRS 1322 LPINIT 05B4 +ARGCNT 21C3 CPMCR 007C FNDPGE 1F0F GETWRD 1E25 LPTO 0586 +BADOP 15BF CPMDRV 005C FNDPGL 1F18 GETZCH 204F LSTADR 0006 +BAND 170E CPMFCB 005C FNPRE 02DF GETZH1 2068 MAKEF 0016 +BCOM 169C CPMFEX 0065 FNPUR 02D3 GETZH2 207B MAXPGS 0040 +BDOS 0005 CPMFN 0105 FRSTQ1 1562 GETZH3 208C MEMTOP 0209 +BODY 10A6 CPMFNB 005D FSET 1729 GLOBAL 21C5 MEMTP1 0212 +BOR 1702 CPMINV 010F FSETQ 171A GRTRQ 16B5 MLOOP 1210 +BRKTBL 1AE3 CPMLLF 010E FSTACK 14D5 GTDSK1 0326 MORCNT 0C76 +BSTLIN 0152 CPMLPP 0104 FWFAIL 1B72 HLGEDE 1D25 MORE 0701 +BTST 16F0 CPMRCD 0019 FWL1 1B0B HLOFF 1F08 MORE1 0722 +CCI 0001 CPMRDS 000D FWL1A 1B07 IGRTQ1 16D3 MORMSG 06E2 +CCO 0002 CPMREC 007D FWL2 1B10 IGRTRQ 16CC MOVE 1751 +CDIO 0006 CPMSEL 000E FWL3 1B25 INC 1593 MOVESG 0012 +CDISK 0004 CPMSTR 0200 FWL4 1B3A INC1 159F MOVIT 034B +CGCONS 000B CPSTNG 0009 FWL4A 1B68 INC2 15A6 MPCFLG 21D5 +CHARS 0BEE CRCBUF 000A FWL4B 1B67 INQ 16DC MPCH 21D0 +CHRPNT 0C73 CRESET 0000 FWL4C 1B66 IOBYTE 0003 MPCL 21D1 +CHRPOS 06A3 CRLF 14DE FWORDS 21C8 ITRMST 0110 MPCPG 21D6 +CHRTBL 2026 CRMSG 094E FWSET 21C7 JUMP 167E MPCPNT 21D3 +CIN 0438 CSPERM 21DF FWSUCC 1B76 LESSQ 16A8 MSGCRC 0A82 +CIN1 043B CSTEMP 21DE GET 177D LFILC 0BD5 MSGOUT 0A66 +CIN2 0451 DBUFP 0BEB GETARG 1D15 LFILD 0B93 MSGRES 0942 +CKZPCP 1E96 DDIV0 1C54 GETB 178F LFILD1 0B9F MUL 1851 +CLEARS 0585 DDIV1 1C5A GETB1A 1EA2 LFILDG 0950 MUL1 186F +CLO 0005 DEC 1599 GETBT1 1E5D LFILDM 098D MUL2 1878 +CLOSE 0010 DEC1 15AC GETBT2 1EA8 LFILF 0B8C MUL4 1875 +CNZS2L 2129 DELETE 0013 GETBT3 1E7A LFILGM 09DD MULT 1C1C +CNZS2M 2122 DIV 187D GETBTL 1E83 LFILP 0BB3 MULT1 1C22 +CNZS2P 2135 DIV2 189E GETBYT 1E30 LFILP1 0BBF MULT2 1C2E +CNZSC1 20E6 DIV2A 18AC GETDK2 0318 LFILPM 09B5 NBRKS 000A +CNZSC3 20EF DIV2B 189F GETDSK 02F7 LFILR 0BD3 NCHARS 0BED +CNZSC4 2101 DIV4 18A5 GETFRE 1DFE LFILS 0B63 NEXTP 1814 +CNZSE1 217D DIVIDE 1C45 GETLNG 12ED LFILS1 0B70 NEXTP1 181E +CNZSL1 20A8 DLESSQ 16C1 GETMOD 203E LINFUL 0521 NEXTP2 1832 +CNZSL2 20B9 EQUALQ 18C2 GETP 17A3 LINOCR 0574 NEXTP3 1838 +CNZSLC 20D1 EQUAQ1 18E3 GETP1 17A6 LINOT1 0516 NEXTPC 1D5A +CNZSLE 215A ESTLIN 0173 GETP2 17D7 LINOT2 0528 NEXTQ 154D +CNZSLO 20DD FALSE 0000 GETP2A 17E9 LINOT3 0532 NOLPT 21B7 +CONZSL 2099 FBRK 1AC3 GETP3 17BA LINOT4 055E NPGS 21DB +CONZST 2090 FCLEAR 1736 GETPRE 0315 LINOT5 0566 NXTPC1 1D87 +CORET 04F3 FILTYP 0C75 GETPT 17EF LINOT6 0549 NXTPC2 1DB9 +COUT 04B6 FINDW 1AED GETPT1 17F2 LINOT7 0555 NXTPC3 1D9D +COUT1 04D3 FIRSTQ 1559 GETPT2 1806 LINOTR 0572 NXTPC4 1DC6 +COUTBS 03B1 FLAGSU 1CA0 GETSHT 12E4 LINOUT 0502 NXTPCL 1DA6 +COUTCR 04AE FLGSU1 1CB2 GETVAR 12FA LMEMRY 21EB OBJLOC 1CF4 +COUTD 045E FLGSU2 1CBA GETVL1 130F LMORE 001F OP0 1280 +COUTDC 0BE5 FLGSU3 1CC2 GETVOC 1AD4 LOC 1573 OP0M 000E + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 87 +---- SYMBOL TABLE ---- + +OP0T 13F4 PRFLG 0BE7 QUIT 0749 SAVEA 07C2 USL 14E4 +OP1 128D PRINT 1687 RANDOM 1BCD SCOREG 0011 VALUE 1693 +OP1M 0010 PRINT1 168D RBRK1 1AB7 SCPLOC 0BE8 VARGET 1359 +OP1T 1410 PRINT2 15B9 RBRK2 1AC0 SCPVAL 0BEA VARGTS 135E +OP2 12B6 PRINTB 15B6 RBRKQ 1AAD SETFIL 02AA VARPTR 174B +OP2EX 12D7 PRINTC 1B84 RD0PL 1A27 SETFL1 02BF VARPTS 1369 +OP2M 0019 PRINTD 1618 RDBFC1 03F9 SETSTR 1DF6 VARPUT 1365 +OP2T 1430 PRINTI 1485 RDBFC2 03EF SETWR1 1DEA VERF 21B8 +OPCODE 21C4 PRINTN 1B8E RDBFC3 03DE SETWRD 1DE4 VERIFL 1513 +OPDSPH 126F PRINTR 14B7 RDBFC4 03E6 SFAIL 0835 VERIFY 14EA +OPEN 000F PRNTDC 1621 RDBFCR 03C0 SFAIL1 0850 VRLINE 109A +OPEXT 1229 PRNTI1 148B RDBFFL 041A SHIFT 21AC VRS 1089 +OPEXTF 125D PRNTN1 1B9E RDBFR1 0407 SHLGED 1D1D WARM 0000 +OPEXTL 1232 PRNTN3 1BAE RDBFR2 0415 SIBRKQ 1AC6 WHOLIN 05C1 +OPEXTM 000A PRNTN4 1BB3 RDBFRO 03A3 SIGNC 1C78 WHOLN1 0645 +OPEXTT 1462 PRNTN6 1BC0 RDBFRT 03FE SIGNCN 1C8B WHOLN2 0614 +OPNDK1 021B PRNTNC 1B97 RDFLG 0BE6 SIGNF 21BA WHOLT 0653 +OZSTKC 21AB PRNTNG 1BC5 READB1 036B SIGNPC 1C93 WHOLT0 066C +OZSTKP 21A9 PROPB 1CCA READB2 0398 SIGNS 1C85 WHOLT1 0674 +PCPST 0294 PROPL 1CE5 READBF 0354 SPLIC1 1F03 WHOLT2 0698 +PCPSTL 0295 PROPN 1CE1 READL 1A06 SPLICE 1EC9 WHOMSG 06D3 +PCRLD1 048B PROPNX 1CEC READL2 1A51 SRCLOS 080E WHOTMS 06DB +PCRLF 04B4 PSHSTK 1D2C READL3 1A74 SRDFNM 02EB WRITER 0022 +PCRLFD 0473 PSTUPS 0194 READR 0021 SRFAIL 0848 WRITES 0015 +PCSTR 027E PTSIZE 1583 READS 0014 SRGDFN 0934 ZADD 183E +PCSTRL 027F PURSTP 21BA REMOVC 15C8 SRGFM1 08C8 ZCALL 18EF +PDL 0C77 PUT 197B REMOVE 15C2 SRGFN2 08ED ZCALL1 192E +PERMTB 2022 PUTB 1994 REMVC1 15F5 SRGFN3 092A ZCALL2 194C +PGBOT 21DD PUTBYT 1328 REMVC2 160D SRGFNA 0900 ZCALL3 195A +PGBUFP 21D7 PUTP 19A8 REST1 0B2F SRGFNB 091B ZCALL4 1968 +PGTBD 0080 PUTP1 19AB RESTA 0AE0 SRGFNM 086C ZCHRC1 2147 +PGTBL 0FC9 PUTP2 19BF RESTAR 075F SRMSG1 0A08 ZCHRC2 2154 +PGTBLB 1049 PUTP2A 19D5 RESTOR 0A93 SRMSG2 0A44 ZCHRCS 213B +PGTBLF 1009 PUTVAL 132B RET0 1327 SRMSG3 0A64 ZCKLEN 001A +PGTFD 0040 PUTVL1 1348 RET1 1652 SRND 2187 ZCKSUM 001C +PGTOP 21DC PUTVLC 1331 RET2 1661 SRNDC 0029 ZCODEP 21D9 +PNTTIM 073B PUTVLG 134D RETCUR 0019 SRSWPD 093F ZENDLD 0004 +POPRET 0497 PUTVLL 1340 RETURN 1633 STAFLG 0BE4 ZER 0206 +POPSTK 1D45 PUTVR1 1336 RFALSE 147F STAR3A 11D2 ZEROQ 1542 +POSPS1 06CD PZFWRD 1F8E RND 1BEE START 0100 ZFWORD 0018 +POSPS2 06C3 PZSTP0 1F50 RND1 1BF7 START1 10CC ZGLOBA 000C +POSPST 06B2 PZSTP1 1F52 RND2 1BF1 START2 115E ZID 0002 +PREDB 1387 PZSTR 1F29 ROOMG 0010 START3 1173 ZMEMT 21B9 +PREDB1 13AA PZSTR1 1F58 RSIBRK 1A6E START4 11F1 ZMOD 18B4 +PREDB2 13D2 PZSTR2 1F61 RSTACK 14CC START5 120F ZNOP 14C0 +PREDB3 13B5 PZSTRA 1F76 RTABP 21E9 STBYTF 21E0 ZOBJEC 000A +PREDB4 13E6 PZSTRC 1FF4 RTRMST 0131 TMCHK 057A ZPCFLG 21CE +PREDF 1371 PZSTRL 1F34 RTRUE 1476 TPA 0100 ZPCH 21A5 +PREDLB 1396 PZSTRP 2007 RTRUE1 1479 TRUE 00FF ZPCL 21A6 +PREDNB 1378 PZSTRS 1FEF SAVE 0770 TWODSK 01B5 ZPCOFF 21CA +PREDS 1380 PZSTRT 1FFE SAVE1 07EC UPPER 0921 ZPCPG 21CF + + +AVOCET SYSTEMS Z80 ASSEMBLER - VERSION 1.03C SERIAL #00112 + +SOURCE FILE NAME: ZORKCPM.ASM PAGE 88 +---- SYMBOL TABLE ---- + +ZPCPNT 21CC ZRSTAR 14C9 ZSPLIT 0004 ZSTATB 0010 ZSWAPF 0001 +ZPOP 1BE5 ZRSTOR 14C6 ZSTACK 0E09 ZSTBUI 21B0 ZTANDY 0008 +ZPURBT 000E ZSAVE 14C3 ZSTAKC 21A8 ZSTBUO 21E3 ZTIMEF 0002 +ZPUSH 1BDC ZSCRIP 0010 ZSTAKL 00E0 ZSTWRD 21E1 ZVERS 0000 +ZQUIT 14DB ZSERNM 0012 ZSTAKP 0E07 ZSUB 1845 ZVOCAB 0008 +ZREAD 19DA ZSET 1745 ZSTART 0006 ZSWAP 0001 + +***** NO ERRORS DETECTED ***** diff --git a/cpm86/cpm86.old b/cpm86/cpm86.old new file mode 100644 index 0000000..c58b12a --- /dev/null +++ b/cpm86/cpm86.old @@ -0,0 +1,2766 @@ + TITLE 'ZIP: CPM/86 VERSION' + + ; + ; MODIFIED 6/18/84 BY DAN HORN + ; 1) Changed Verify Version Letter + ; 2) Increased size of save for Opsave + ; Changes noted with (***) + ; 3) Fixed Random Bug + ; + +CSEG + +START: MOV AX,.15H + MOV SS,AX + MOV SP,OFFSET STK_TOP + MOV DI,OFFSET ZSTK_TP + MOV CL,CFOPEN + MOV DX,OFFSET CNFFCB + INT 224 ;OPEN CONFIGURATION FILE + CMP AL,0FFH + JE ST1M ;NONE FOUND, USE DEFAULT + MOV CL,CRDSEQ + MOV DX,OFFSET CNFFCB + MOV AX,DS + MOV ES,AX + PUSH ES + INT 224 ;READ FIRST BLOCK + POP ES + CMP AL,0 + JNE ST1M + MOV CX,80H + MOV SI,80H + MOV DI,100H +REP MOVS AL,AL ;TRANSFER STUFF FROM BUFFER TO 100H + MOV CL,CRDSEQ + MOV DX,OFFSET CNFFCB + PUSH ES + INT 224 ;READ SECOND BLOCK + POP ES + CMP AL,0 + JNE ST1M + MOV CX,80H + MOV SI,80H + MOV DI,180H +REP MOVS AL,AL ;TRANSFER STUFF FROM BUFFER TO 180H + MOV CL,CFCLOS + MOV DX,OFFSET CNFFCB + PUSH ES + INT 224 ;CLOSE CONFIG. FILE + POP ES +ST1M: MOV CL,CFNMEM + MOV DX,OFFSET MBSTT + INT 224 ;GET SOME MEMORY, PLEASE + CMP AL,0FFH + JE MERR1 + MOV AX,MBLEN ;GET LENGTH + CMP AX,800H + JB MERR1 ;DIE IF LESS THAN 32K (JL LOST ON 100+) + CMP AX,1000H + JBE STARTM + MOV MBLEN,1000H ;TAKE 64K AT MOST +STARTM: MOV CL,CALMEM + MOV DX,OFFSET MBSTT + INT 224 ;ALLOCATE THE BLOCK + CMP AL,0FFH + JE MERR1 ;SHOULDN'T EVER HAPPEN + MOV AX,MBSTT ;STARTING PARAGRAPH + MOV ES,AX ;AND THAT BECOMES OUR ES + JMP ZIPBGN ;JUMP TO BEGINNING OF ZIP CODE + +MERR1: MOV AX,OFFSET FTL10 + JMP FATAL + +FEEP: MOV AX,7 + CALL M_TTYO ;BELL + RET + +OPVERI: MOV AX,OFFSET INTVER + CALL M_PRNT + MOV AX,ES:.PLENTH ;GET LENGTH OF FILE + PUSH SI + PUSH DI + PUSH ENDLOD + XCHG AH,AL + CALL BSPLIT + MOV SI,AX + MOV DI,BX ;SAVE PLENTH ZPC1/ZPC2 + MOV AX,0 ;START AT BYTE 64 + MOV BX,64 + MOV DX,0 ;WILL HAVE CHECKSUM + MOV ENDLOD,0 ;FAKE IT TO BE ZERO +OPVR1: PUSH SI + PUSH DI + PUSH DX + CALL GETBYT + POP DX + POP DI + POP SI + ADD DX,CX ;ADD INTO CHECKSUM + CMP AX,SI + JNE OPVR1 + CMP BX,DI + JNE OPVR1 + MOV AX,ES:.PCHKSM ;GET CHECKSUM + XCHG AH,AL + POP ENDLOD ;RESTORE FROBS + POP DI + POP SI + CMP AX,DX ;COMPARE WITH GOOD CHECKSUM + JNE OPVR2 + JMP PTRUE +OPVR2: JMP PFALSE + +OPREST: MOV DSKDIR,0 ;INDICATE RESTORE + JMP OSV0 + +OPSAVE: MOV DSKDIR,1 +OSV0: MOV AX,OFFSET SAV1 + CALL M_PRNT ;PRINT 'File name (default is ' + MOV AL,SAVFCB + CMP AL,0 + JE OSVD1 + ADD AL,'A'-1 ;MAKE THIS AN ASCII THING + CALL M_TTYO ;AND OUTPUT IT + MOV AL,':' + CALL M_TTYO +OSVD1: MOV CX,8 ;MAX. FIRST FILE NAME + MOV BX,OFFSET SAVFCB +OSVD3: INC BX ;POINT TO START OF SAVFCB + MOV AL,BYTE PTR [BX] + CMP AL,20H ;CHECK FOR SPACE + JE OSVD2 + CALL M_TTYO ;OUTPUT IT + LOOP OSVD3 +OSVD2: MOV AL,'.' + CALL M_TTYO ;AND THE PERIOD + MOV CX,3 ;MAX. EXTENSION + MOV BX,OFFSET SAVFCB + ADD BL,8 ;POINT TO EXTENSION +OSVD4: INC BX + MOV AL,BYTE PTR [BX] + CALL M_TTYO + LOOP OSVD4 + MOV AX,OFFSET SAV2 + CALL M_PRNT ;PRINT THE ': ' PROMPT + MOV BX,OFFSET INBUF + MOV AL,14 ;SAY MAX. LENGTH IS 14 (X:XXXXXXXX.XXX) + MOV BYTE PTR [BX],AL + MOV DX,BX + MOV CL,CRDLIN + PUSH ES + INT 224 ;BUFFERED CONSOLE READ + POP ES + MOV AL,10 + CALL M_TTYO ;ECHO A LF (CHOMPER!) + MOV BX,OFFSET INBUF + MOV CL,BYTE PTR 1 [BX] + ADD BX,2 ;GO PAST THE HEADER + SUB CH,CH ;# CHARACTERS READ + CMP CL,0 + JE OSVKL ;USE DEFAULT IF ZERO + CMP CL,2 ;CHECK FOR <2 CHARACTERS + JL OSVP2 + MOV AL,BYTE PTR 1 [BX] + CMP AL,':' ;CHECK FOR DEVICE NAME + JNE OSVP2 + MOV AL,BYTE PTR [BX] + CMP AL,'a' + JL OSVXC + CMP AL,'z' + JG OSVXC + SUB AL,32 +OSVXC: SUB AL,'A'-1 + JGE OSVP0 + MOV AX,OFFSET ERR3 + JMP OSVPER ;ILLEGAL IF <0 +OSVKL: JMP OSVPN +OSVP0: CMP AL,16 + JLE OSVP1 + MOV AX,OFFSET ERR3 + JMP OSVPER ;OR >16 +OSVP1: MOV SAVFCB,AL ;SAVE IT AWAY + ADD BX,2 ;AND FLUSH IT + SUB CL,2 ;FLUSH 'EM FROM CL TOO + JE OSVPN ;THAT'S ALL FOLKS.... +OSVP2: MOV BP,OFFSET SAVFCB + MOV DL,8 ;MAX. FIRST FILE NAME +OSVP3: INC BP ;POINT TO FIRST FILE NAME STUFF + MOV AL,BYTE PTR [BX];GET THE NEXT CHARACTER + CMP CL,0 + JG OSVP3A + MOV AL,20H ;IF WE'RE OUT OF INPUT, USE SPACE +OSVP3A: CMP AL,'.' + JE OSVP4 + CMP AL,'a' + JL OSVCP1 + CMP AL,'z' + JG OSVCP1 + SUB AL,32 ;UPPERCASE, IF NECESSARY +OSVCP1: MOV DS:BYTE PTR [BP],AL + INC BX + DEC CL + DEC DL + JNZ OSVP3 + CMP CL,0 + JLE OSVPN + MOV AL,BYTE PTR [BX] + CMP AL,'.' + JE OSVP4 + MOV AX,OFFSET ERR3 + JMP OSVPER ;BETTER BE A PERIOD +OSVP4: INC BX + MOV AL,20H + CMP DL,0 ;LOOP PADDING WITH SPACES + JE OSVP6 +OSVP5: MOV DS:BYTE PTR [BP],AL + INC BP + DEC DL + JNZ OSVP5 + CMP CL,4 ;SHOULD BE FOUR LEFT '.XXX' + JE OSVP6 + MOV AX,OFFSET ERR3 + JMP OSVPER +OSVP6: MOV AL,BYTE PTR [BX] + MOV DS:BYTE PTR [BP],AL + INC BP + INC BX + LOOP OSVP6 +OSVPN: MOV BX,OFFSET SAVFCB + ADD BX,12 ;GO PAST THE FILE NAMES + MOV CX,30 + MOV AL,0 ;FILL WITH ZEROS +OSVPNZ: MOV [BX],AL + INC BX + LOOP OSVPNZ + CMP DSKDIR,1 ;CHECK FOR SAVE OR RESTORE + JE OSVOPW ;OPEN FOR WRITE + MOV DX,OFFSET SAVFCB + MOV CL,CFOPEN ;FILE OPEN + PUSH ES + INT 224 + POP ES + CMP AL,0FFH + JNE OSVPS + MOV AX,OFFSET ERR1 + JMP OSVPER ;FILE NOT FOUND +OSVOPW: MOV DX,OFFSET SAVFCB + MOV CL,CFDELE + PUSH ES + INT 224 + MOV DX,OFFSET SAVFCB + MOV CL,CFMAKE + INT 224 + POP ES + CMP AL,0FFH + JNE OSVPS + MOV AX,OFFSET ERR4 + JMP OSVPER + +OSVPS: XCHG DI,SP + PUSH ZPC1 + PUSH ZPC2 + PUSH ZLOCS + PUSH ZORKID + MOV STKBOT,SP ;SAVE THE WORLD + MOV SP,DI + MOV CL,5 + SHL AX,CL ;CHANGE TO BLOCK + PUSH AX ;SAVE STARTING BLOCK # + PUSH ES ;SAVE ES + MOV DX,SS + MOV ES,DX ;FAKE ES TO BE STACK SEGMENT + MOV BX,OFFSET STKBOT + MOV CX,2 ; *** WRITE OUT CX*4 (128 BYTES BLOCKS) + CALL SRBLKS ;READ/WRITE STACK + PUSHF + MOV DI,SP ;SAVE SP + MOV SP,STKBOT ;RETRIEVE SAVED USER STACK POINTER + POP AX + CMP AX,ZORKID ;CHECK GAME VERSIONS + JE OSVT0 + MOV AX,OFFSET FTL4 + JMP FATAL +OSVT0: POP ZLOCS + POP ZPC2 + POP ZPC1 + XCHG DI,SP + POPF + POP ES + POP AX + JC OSV4 ;DIE HERE IF FIRST READ/WRITE FAILED + MOV AX,2 ; *** NEXT BLOCK STARTS + SUB BX,BX ;START AT ES:0 + MOV CX,PURBOT ;NUMBER OF PURE BLOCKS + CALL SRBLKS + PUSHF ;SAVE FLAGS FROM CALL + JC OSVCC + CMP DSKDIR,1 + JNE OSVCC + MOV CL,CFCLOS + MOV DX,DSKFCB + PUSH ES + INT 224 ;CLOSE FILE ON SUCCESSFUL WRITE + POP ES +OSVCC: CALL M_CRLF +; MOV AX,OFFSET SAV3 +; CALL M_PRNT +; CALL M_CHRI ;WAIT UNTIL READY +; CALL M_CRLF +OSV3C: CALL NEWZPC ;PAGE MAY HAVE CHANGED, LOSER! + POPF ;GET FLAGS BACK + JC OSV4 + MOV AL,SCRFLG ;GET CURRENT SCRIPT STATE + XCHG AH,AL + MOV ES:.PFLAGS,AX ;AND MAKE RESTORED FLAGS REFLECT IT + JMP PTRUE +OSV4: MOV AX,OFFSET ERR5 + CMP DSKDIR,1 + JE OSVPER + MOV AX,OFFSET ERR6 ;DISTINGUISH READ/WRITE ERRORS +OSVPER: CALL M_PRNT + JMP PFALSE + +OPRSTT: MOV BP,CHRPTR + MOV DS:BYTE PTR [BP],0 ;FORCE OUT THE BUFFER + MOV AX,OFFSET OUTBUF + CALL M_PRNT + JMP RESTRT ;JUMP TO RESTART ADDRESS + +OPQUIT: JMP FINISH + +OPUSL: PUSH DI + PUSH CHRPTR + MOV BX,SLSTR ;FAKE STATUS LINE STRING AS OUTPUT BUFFER + MOV CHRPTR,BX + MOV AX,16 ;FIRST GLOBAL + MOV DI,SLTAB + MOV CX,3 ;# OF THINGS TO PRINT +USLLP: PUSH AX + CALL GETVAR ;GET THE ROOM OBJECT + MOV DX,4[DI] ;THE STARTING CURSOR POSITION + CALL USLSET ;SET CURSOR POSITION HERE + PUSH CX + PUSH DI + CALL WORD PTR 2[DI] ;PRINT THE THING + POP DI + MOV DX,6[DI] + CALL USLSPC ;SPACE OVER TO HERE +USLN: ADD DI,8 ;POINT TO NEXT THING TO PRINT + POP CX +USL1: POP AX + INC AX ;POINT TO NEXT GLOBAL + LOOP USLLP + MOV AX,'$' + CALL PUTCHR ;PUT IN A STOP SIGNAL + CALL M_SOUT ;OUTPUT STATUS LINE + POP CHRPTR + POP DI + RET + +USLSET: MOV BX,SLSTR + MOV CHRPTR,BX + ADD CHRPTR,DX + RET + +USLSPC: MOV CX,CHRPTR + SUB CX,SLSTR ;THIS IS WHERE WE ARE + SUB DX,CX ;THIS IS WHERE WE WANT TO BE + MOV CX,DX ;CX HAS COUNT OF SPACES TO PUT IN + JLE USLSP1 +USLSPL: MOV AX,20H + CALL PUTCHR ;OUTPUT A SPACE INTO BUFFER + LOOP USLSPL +USLSP1: RET + + + ;ADD +OPADD: ADD AX,BX ;ADD OPR1 AND OPR2 + JMP PUTVAL ;RETURN THE VALUE + + ;SUB +OPSUB: SUB AX,BX ;SUBTRACT OPR2 FROM OPR1 + JMP PUTVAL ;RETURN THE VALUE + + ;MULTIPLY AX BY BX +OPMUL: IMUL BX ;MULTIPLY OPR1 BY OPR2,IGNORING OVERFLOW(DX) + JMP PUTVAL ;RETURN THE VALUE + + ;DIVIDE AX BY BX +OPDIV: CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + JMP PUTVAL ;RETURN THE VALUE + + ;MOD +OPMOD: CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + MOV AX,DX ;WE WANT REMAINDER + JMP PUTVAL ;RETURN THE VALUE + + ;RANDOM +OPRAND: SUB AH,AH + MOV RTEMP,AX + MOV AX,RSEED1 + MOV BX,RSEED2 + MOV RSEED2,AX + CLC + RCR AX,1 + RCR BX,1 + XOR RSEED1,BX + MOV AX,RSEED1 + AND AX,0EFFFH + SUB DX,DX + DIV RTEMP + MOV AX,DX + INC AX ;MUST BE BETWEEN 1 AND N, INCLUSIVE + JMP PUTVAL ;SIMPLY RETURN + + ;LESS? +OPQLES: CMP AX,BX ;IS OPR1 LESS THAN OPR2? + JL JPT ;YES, PREDICATE TRUE +JPF: JMP PFALSE ;NO, PREDICATE FALSE +JPT: JMP PTRUE + + ;GRTR? +OPQGRT: CMP AX,BX ;IS OPR1 GREATER THAN OPR2? + JG JPT ;YES, PREDICATE TRUE + JMP JPF ;NO, PREDICATE FALSE + + ;BTST +OPBTST: NOT AX ;TURN OFF BITS IN OPR2 THAT ARE ON IN OPR1 + AND BX,AX + JE JPT ;SUCCESS IF OPR2 COMPLETELY CLEARED + JMP JPF + + ;BOR +OPBOR: OR AX,BX ;LOGICAL OR + JMP PUTVAL ;RETURN THE VALUE + + ;BCOM +OPBCOM: NOT AX ;LOGICAL COMPLEMENT + JMP PUTVAL ;RETURN THE VALUE + + ;BAND +OPBAND: AND AX,BX ;LOGICAL AND + JMP PUTVAL ;RETURN THE VALUE + + ;EQUAL? +OPQEQU: NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV BX,ARGBLK ;GET OPR1 + CMP BX,ARGBLK+2 ;IS OPR1 EQUAL TO OPR2? + JE OQE1 ;YES + CMP AX,3 ;NO, IS THERE A THIRD OPERAND? + JL OQE2 ;NO + CMP BX,ARGBLK+4 ;YES, IS IT EQUAL TO OPR1? + JE OQE1 ;YES + CMP AX,4 ;NO, IS THERE A FOURTH? + JL OQE2 ;NO + CMP BX,ARGBLK+6 ;YES, IS IT EQUAL TO OPR1? + JNE OQE2 ;NO +OQE1: JMP PTRUE ;PREDICATE TRUE IF EQUAL +OQE2: JMP PFALSE ;PREDICATE FALSE IF NOT + + ;ZERO? +OPQZER: CMP AX,0 ;IS OPR ZERO? + JNE OQZ1 ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQZ1: JMP PFALSE + + ;MOVE (OBJ1 INTO OBJ2) +OPMOVE: PUSH AX ;PROTECT OPRS FROM REMOVE CALL + PUSH BX + CALL OPREMO ;REMOVE OBJ1 FROM WHEREVER IT IS + POP DX ;OBJ2 + MOV AX,DX + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + POP CX ;OBJ1 + MOV AX,CX + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV ES:4[BP],DL ;PUT OBJ2 INTO OBJ1'S LOC SLOT + MOV DH,ES:6[BX] ;GET CONTENTS OF OBJ2'S FIRST SLOT + MOV ES:6[BX],CL ;MAKE OBJ1 FIRST CONTENT OF OBJ2 + CMP DH,0 ;WERE THERE ANY OTHER CONTENTS? + JE OMV1 ;NO + MOV ES:5[BP],DH ;YES, CHAIN ONTO OBJ1'S SIBLING SLOT +OMV1: RET + + ;REMOVE (OBJ FROM ITS PARENT) +OPREMO: MOV CX,AX ;SAVE OBJ FOR LATER + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + MOV CH,ES:4[BX] ;GET ITS PARENT + CMP CH,0 ;DOES IT HAVE A PARENT? + JE ORM3 ;IF NOT, WE'RE DONE + MOV AL,CH ;PARENT + CALL OBJLOC ;FIND PARENT'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:6[BP] ;GET PARENT'S FIRST CONTENT + CMP DL,CL ;IS IT OBJ? + JNE ORM1 ;NO + MOV AL,ES:5[BX] + MOV ES:6[BP],AL ;YES, CHANGE SLOT TO OBJ'S SIBLING + JMP ORM2 ;AND RETURN +ORM1: MOV AL,DL ;CURRENT SIBLING + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:5[BP] ;GET NEXT SIBLING IN CHAIN + CMP DL,CL ;IS IT OBJ? + JNE ORM1 ;NO, CONTINUE LOOP + MOV AL,ES:5[BX] + MOV ES:5[BP],AL ;YES, CHANGE IT TO OBJ'S SIBLING +ORM2: MOV ES:BYTE PTR 4[BX],0 ;OBJ NOW HAS NO PARENT + MOV ES:BYTE PTR 5[BX],0 ;OR SIBLING +ORM3: RET + + ;FSET? (IS FLAG SET IN OBJ?) +OPQFSE: CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OQF1 ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OQF1: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + MOV AX,ES:[BX] ;GET THE FLAG WORD + XCHG AH,AL + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + TEST AX,DX ;IS THIS BIT SET IN FLAG WORD? + JE OQF2 ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQF2: JMP PFALSE + + ;FSET (SET A FLAG IN OBJ) +OPFSET: CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFS1 ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFS1: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + MOV AX,ES:[BX] ;GET THE FLAG WORD + XCHG AH,AL + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + OR AX,DX ;SET THIS BIT IN FLAG WORD + XCHG AH,AL + MOV ES:[BX],AX ;STORE THE NEW FLAG WORD + RET + + ;FCLEAR (CLEAR A FLAG IN OBJ) +OPFCLE: CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFC1 ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFC1: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + MOV AX,ES:[BX] ;GET THE FLAG WORD + XCHG AH,AL + MOV DX,7FFFH ;SHIFT A BIT TO PROPER POSITION + ROR DX,CL + AND AX,DX ;CLEAR THIS BIT IN FLAG WORD + XCHG AH,AL ;STORE THE NEW FLAG WORD + MOV ES:[BX],AX + RET + + ;LOC (RETURN CONTAINER OF OBJ) +OPLOC: CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:4[BX] ;GET LOC SLOT + JMP BYTVAL ;RETURN THE BYTE VALUE + + ;FIRST? (RETURN FIRST SLOT OF OBJ, FAIL IF NONE) +OPQFIR: CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:6[BX] ;GET FIRST SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE +JPT1: JMP PTRUE ;NO, PREDICATE TRUE +JPF1: JMP PFALSE + + ;NEXT? (RETURN THE NEXT (SIBLING) SLOT OF OBJ, FAIL IF NONE) +OPQNEX: CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:5[BX] ;GET SIBLING SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE + JMP JPT1 ;NO, PREDICATE TRUE + + ;IN? (IS OBJ1 CONTAINED IN OBJ2?) +OPQIN: CALL OBJLOC ;FIND OBJ1'S LOCATION + XCHG AX,BX ;MOVE TO BASE + CMP ES:4[BX],AL ;IS OBJ1'S PARENT OBJ2? + JE JPT1 ;YES, PREDICATE TRUE + JMP JPF1 ;NO, PREDICATE FALSE + + ;GETP (GET SPECIFIED PROPERTY OF OBJ, DEFAULT IF NONE) +OPGETP: MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV BX,ES:7[BP] ;GET LOCATION OF ITS PROPERTY TABLE + XCHG BH,BL + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGP2 ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGP1: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGP2: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,31 ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGP1 ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JL OGP3 ;IF LESS, NO SUCH PROPERTY HERE + MOV AL,ES:[BX] ;GOT IT, NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,224 ;GET LENGTH BITS + MOV CL,5 ;PROPERTY SIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + JNE OGP5 ;NO + MOV AL,ES:[BX] ;GET THE BYTE + JMP BYTVAL ;AND RETURN IT +OGP3: DEC DX ;POINT INTO DEFAULT PROPERTY TABLE + SHL DX,1 + MOV BX,DX +OGP4: ADD BX,OBJTAB ;GET THE WORD +OGP5: MOV AX,ES:[BX] + XCHG AH,AL + JMP PUTVAL ;AND RETURN IT + + ;PUTP (CHANGE VALUE OF A PROPERTY, ERROR IF BAD NUMBER) +OPPUTP: PUSH CX ;SAVE NEW VALUE + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV BX,ES:7[BP] ;GET LOCATION OF ITS PROPERTY TABLE + XCHG BH,BL + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OPP2 ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OPP1: CALL NXTPRP ;POINT TO NEXT PROPERTY +OPP2: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,31 ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE OPP3 ;IF EQUAL, GOT IT + JG OPP1 ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + MOV AX,OFFSET FTL2 + JMP FATAL +OPP3: MOV AL,ES:[BX] ;NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,224 ;GET LENGTH BITS + MOV CL,5 ;PROPSIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + POP AX ;RESTORE NEW VALUE + JNE OPP4 ;ZERO MEANS BYTE VALUE + MOV ES:[BX],AL ;STORE THE NEW BYTE + RET ;AND RETURN +OPP4: XCHG AH,AL + MOV ES:[BX],AX ;STORE THE NEW WORD VALUE + RET + + ;NEXTP (RETURN NUMBER OF NEXT PROP FOLLOWING GIVEN PROB IN OBJ) +OPNEXT: MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV BX,ES:7[BP] ;GET ITS LOCATION + XCHG BH,BL + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + CMP DX,0 ;WERE WE GIVEN ZERO AS PROP? + JE ONX4 ;YES, GO RETURN FIRST PROPERTY NUMBER + JMP ONX2 ;NO, SKIP NEXT LINE FIRST TIME THROUGH LOOP +ONX1: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX2: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,31 ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE ONX3 ;IF EQUAL, GOT IT + JG ONX1 ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + MOV AX,OFFSET FTL2 + JMP FATAL +ONX3: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX4: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,31 ;EXTRACT PROPERTY NUMBER + JMP PUTVAL ;AND RETURN IT + + ;GET (GET THE ITEM'TH WORD FROM TABLE) +OPGET: SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETWRD ;GET THE WORD + MOV AX,CX + JMP PUTVAL ;AND RETURN IT + + ;GETB (GET THE ITEM'TH BYTE FROM TABLE) +OPGETB: ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETBYT ;GET THE BYTE + MOV AX,CX + JMP BYTVAL ;AND RETURN IT + + ;PUT (REPLACE THE ITEM'TH WORD IN TABLE) +OPPUT: SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD BX,AX ;INDEX INTO TABLE + XCHG CH,CL + MOV ES:[BX],CX ;STORE THE WORD + RET + + ;PUTB (REPLACE ITEM'TH BYTE IN TABLE) +OPPUTB: ADD BX,AX ;INDEX INTO TABLE + MOV ES:[BX],CL ;STORE BYTE + RET + + ;GETPT (GET POINTER TO PROPERTY TABLE FOR GIVEN PROP) +OPGTPT: MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV BX,ES:7[BP] ;GET LOCATION OF ITS PROPERTY TABLE + XCHG BH,BL + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGT2 ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGT1: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGT2: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,31 ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGT1 ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JE OGT3 ;FOUND THE PROPERTY + SUB AX,AX ;RETURN ZERO FOR NO SUCH PROPERTY + JMP OGT4 +OGT3: INC BX ;POINT TO PROPERTY VALUE + MOV AX,BX ;AND RETURN IT +OGT4: JMP PUTVAL + + ;PTSIZE (RETURN SIZE OF PROPERTY TABLE) +OPPTSI: MOV BX,AX ;TABLE POINTER + MOV AL,ES:[BX]-1 ;GET PROPERTY INDENTIFIER + AND AL,224 ;EXTRACT LENGTH BITS + SUB AH,AH + MOV CL,5 ;PROPSIZE + SHR AX,CL + INC AX ;ADJUST TO ACTUAL LENGTH + JMP PUTVAL ;RETURN IT + + ;VALUE (GET VALUE OF VAR) +OPVALU: CALL GETVAR ;GET THE VALUE + JMP PUTVAL ;AND RETURN IT + + ;SET (VAR TO VALUE) +OPSET: JMP PUTVAR ;STORE THE VALUE + + ;PUSH (A VALUE ONTO THE STACK) +OPPUSH: XCHG SP,DI + PUSH AX + XCHG SP,DI + RET + + ;POP (A VALUE OFF THE STACK INTO VAR) +OPPOP: XCHG SP,DI + POP BX + XCHG SP,DI + JMP PUTVAR ;AND STORE IT + + ;INC (INCREMENT VAR) +OPINC: MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT +OPINC1: MOV BX,AX ;VALUE + MOV AX,CX ;VARIABLE + JMP PUTVAR ;STORE NEW VALUE + + ;DEC (DECREMENT VAR) +OPDEC: MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + JMP OPINC1 ;STORE NEW VALUE + + ;IGRTR? (INCREMENT VAR & TEST IF GREATER THAN VAL) +OPQIGR: PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE GREATER THAN VAL? + JLE OPQIG1 ;NO +OPQIG0: INC CX ;YES, CHANGE FLAG TO TRUE +OPQIG1: MOV BX,AX ;VALUE + POP AX ;RESTORE VARIABLE + CALL PUTVAR ;STORE NEW VALUE + CMP CX,0 ;TEST FLAG + JE OQI1 ;FALSE, PREDICATE FALSE + JMP PTRUE ;ELSE, PREDICATE TRUE +OQI1: JMP PFALSE + + ;DLESS? (DECREMENT VAR & TEST IF LESS THAN VAL) +OPQDLE: PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE LESS THAN VAL? + JGE OPQIG1 ;NO, PREDICATE FALSE + JMP OPQIG0 ;YES, PREDICATE TRUE + +GETLIN: CMP RNDFLG,0 + JNE GETLNN + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH ES +RNDLP: MOV DI,4 + INT 40 + CMP CL,0 + JNE RNDL1 + INC RSEED1 + INC RSEED2 + JMP RNDLP +RNDL1: MOV RNDFLG,1 + POP ES + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX +GETLNN: PUSH BX + MOV AL,SCRFLG + PUSH AX + MOV SCRFLG,0 ;DEFEAT SCRIPTING DURING INPUT + PUSH SI + MOV CL,ES:[SI] ;HERE'S WHERE LENGTH IS + MOV BX,OFFSET INBUF ;HERE'S THE BDOS INPUT BUFFER + MOV BYTE PTR [BX],CL;PUT MAX LENGTH THERE + MOV DX,BX + MOV CL,CRDLIN ;CONSOLE BUFFERED READ + PUSH ES + INT 224 ;READ A LINE + MOV CL,CCONIO + MOV DL,10 + INT 224 ;ECHO LF + POP ES + POP DX ;GET BACK START OF BUFFER + MOV BX,OFFSET INBUF ;GET BDOS INPUT BUFFER AGAIN + MOV CL,BYTE PTR 1 [BX] ;THE # CHARACTERS READ + SUB CH,CH + INC BX ;FLUSH COUNT ACTUALLY READ + CMP CL,0 + JE GETLEM ;IF NONE TYPED, DON'T LOOP FOREVER +GETLLP: INC SI + INC BX + MOV AL,BYTE PTR [BX] + CMP AL,'A' + JL GETLLC + CMP AL,'Z' + JG GETLLC + ADD AL,32 +GETLLC: MOV ES:[SI],AL + LOOP GETLLP +GETLEM: INC SI + SUB AL,AL + MOV ES:[SI],AL + POP AX + MOV SCRFLG,AL + POP BX + RET + +PRTOUT: PUSH ES + PUSH BX + MOV DL,AL + MOV CL,05H + INT 224 + POP BX + POP ES + RET + +SCRCHK: PUSH AX + PUSH BX + PUSH DX + MOV AX,ES:.PFLAGS + XCHG AH,AL + TEST AL,1 ;CHECK IF SCRIPTING IS REQUESTED + JZ SCRNN + MOV SCRFLG,1 + SUB CX,CX ;COUNT OF CHARS PRINTED + MOV BP,DX ;START OF INPUT LINE + INC BP ;FIRST CHAR IS LENGTH OF BUFFER +SCR1L: MOV AL,ES:[BP] + INC BP ;GET CHARACTER + CMP BP,SI ;END OF INPUT? + JLE SCR2L + CALL PRTCRL + JMP SCREX +SCR2L: CALL PRTOUT ;OUTPUT ONE CHARACTER TO THE PRINTER + INC CX + CMP CL,SCPL + JNE SCR1L + CALL PRTCRL + JC SCREX + SUB CX,CX ;RESTART COUNT + JMP SCR1L ;GO FOR MORE + +SCRNN: MOV SCRFLG,0 +SCREX: POP DX + POP BX + POP AX + RET + +PRTCRL: MOV AL,13 ;FINISH UP WITH CRLF + CALL PRTOUT + MOV AL,10 + CALL PRTOUT + RET + + ;READ (A LINE OF INPUT & PARSE IT, LINE BUF IN ES:AX, + ;RETURN BUF IN ES:BX) +OPREAD: PUSH AX ;SAVE LINE BUF + PUSH AX + PUSH BX + CALL OPUSL ;UPDATE STATUS LINE + POP BX + POP AX + MOV BP,CHRPTR ;NEXT CHARACTER POSITION + MOV DS:BYTE PTR [BP],80H ;DON'T END OUTPUT, IF ANY, WITH NEW LINE +ORD1: MOV AX,OFFSET OUTBUF + CALL M_PRNT + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP SI ;INPUT BUFFER POINTER + MOV MORLIN,0 ;RE-INITIALIZE MORE COUNT FROM HERE + CALL GETLIN ;GET SOME CHARACTERS + CALL SCRCHK ;CHECK FOR SCRIPTING, SCRIPT INPUT IF ON +ORDNS: PUSH DI + MOV RDBOS,DX ;INITIALIZE RDBOS + MOV RDEOS,SI ;AND RDEOS + MOV RDRET,BX ;STORE RET POINTER + MOV RDNWDS,0 ;NO WORDS SO FAR + INC DX ;SKIP LENGTH BYTE + MOV DI,BX ;THIS WILL BE WORD ENTRY POINTER + INC DI ;SKIP MAX WORDS & NWORDS BYTES + INC DI +ORD8: MOV CX,OFFSET RDWSTR;HERE FOR NEXT WORD, POINT TO WORD STRING + MOV BX,DX ;AND SAVE BEGINNING OF WORD POINTER +ORD9: CMP DX,RDEOS ;END OF STRING? + JNE ORD10 ;NO + CMP CX,OFFSET RDWSTR;YES, WAS A WORD FOUND? + JNE ORD15 ;YES, WE STILL HAVE TO LOOKUP WORD + JMP ORD23 ;NO, WE'RE DONE +ORD10: MOV BP,DX ;GET NEXT CHARACTER FROM BUFFER + MOV AL,ES:[BP] + CMP AL,'A' + JL ORD1A + CMP AL,'Z' + JG ORD1A + ADD AL,32 ;LOWERCASIFY ALPHABETICS +ORD1A: INC DX + MOV SI,OFFSET RBRKS ;LIST OF READ BREAK CHARACTERS +ORD11: INC SI + CMP AL,-1[SI] ;SEARCH LIST FOR THIS ONE + JE ORD12 ;FOUND IT + CMP BYTE PTR [SI],0 ;END OF LIST? + JNE ORD11 ;NO, CONTINUE SEARCH + CMP CX,OFFSET RDWSTR+6 ;YES, NOT A BREAK, WORD STRING FULL? + JE ORD9 ;YES, LOOP UNTIL END OF WORD + MOV BP,CX ;NO, TACK THIS CHARACTER ONTO STRING + MOV DS:[BP],AL + INC CX + JMP ORD9 ;AND LOOP +ORD12: CMP CX,OFFSET RDWSTR;WORD READ BEFORE THIS BREAK? + JNE ORD14 ;YES + CMP SI,ESIBKS ;NO, BUT IS IT A SELF-INSERTING BREAK? + JBE ORD13 ;YES + INC BX ;NO, UPDATE BEGINNING OF WORD TO SKIP BREAK + JMP ORD9 ;AND RETURN TO LOOP TO FIND A WORD +ORD13: MOV BP,CX ;STORE THE BREAK IN WORD STRING + MOV DS:[BP],AL + INC CX + JMP ORD15 ;AND GO FOR THE WORD +ORD14: DEC DX ;UNREAD TERMINATING BREAK IN CASE IT WAS SI +ORD15: INC RDNWDS ;INCREMENT FOUND WORD COUNT + MOV BP,BX ;GREATER THAN MAX ALLOWED? + MOV BX,RDRET + MOV BL,ES:[BX] + CMP RDNWDS,BL + MOV BX,BP + JLE ORD16 ;NO + MOV AX,OFFSET ERR2 + CALL M_PRNT ;YES. INFORM LOSER + MOV AX,BX ;BEGINNING OF THIS WORD + MOV BP,RDEOS ;SAVE BYTE AFTER EOS + MOV BL,ES:[BP] + MOV ES:BYTE PTR [BP],0 ;ZERO IT TO MAKE STRING ASCIZ + CALL M_PRNT ;PRINT IT + MOV ES:[BP],BL ;AND RESTORE OLD BYTE + DEC RDNWDS ;REMEMBER THAT WE FLUSHED THIS WORD + JMP ORD23 ;AND WE'RE DONE +ORD16: MOV AX,BX ;CALCULATE NUMBER OF CHARACTERS IN WORD + NEG AX + ADD AX,DX + MOV ES:2[DI],AL ;SAVE THE NUMBER IN RET TABLE + SUB BX,RDBOS ;BYTE OFFSET FOR BEGINNING OF WORD + MOV ES:3[DI],BL ;STORE IT, TOO + MOV BP,CX ;MAKE WORD STRING ASCIZ + MOV DS:BYTE PTR [BP],0 + MOV AX,OFFSET RDWSTR;POINT TO IT + CALL ZWORD ;AND CONVERT TO (2-WORD) ZWORD + PUSH DX ;SAVE CHAR & WORD ENTRY POINTERS + PUSH DI + MOV DI,AX ;FIRST ZWORD WORD + MOV SI,VWORDS ;NUMBER OF VOCABULARY WORDS + MOV AX,SI + DEC AX ;WE WANT TO POINT TO LAST WORD + MUL VWLEN ;MULTIPLY BY WORD LENGTH IN BYTES + ADD AX,VOCBEG ;ADD POINTER TO BEGINNING TO FIND LAST WORD + MOV CX,AX ;POINTER TO LAST WORD + MOV DX,DI ;FIRST ZWORD WORD + MOV DI,BX ;SECOND ZWORD WORD + MOV BX,VWLEN ;CALCULATE INITIAL OFFSET FOR BINARY SEARCH + SAR SI,1 +ORD17: SAL BX,1 + SAR SI,1 + CMP SI,0 + JNE ORD17 + MOV SI,VOCBEG ;BEGINNING OF WORD TABLE + ADD SI,BX ;ADD CURRENT OFFSET(HALF OF POWER-OF-2 TABLE) + PUSH AX ;SAVE + MOV AX,VWLEN ;AVOID FENCEPOST BUG FOR EXACT POWER-OF-2 TBL + SUB SI,AX + POP AX ;RESTORE +ORD18: SAR BX,1 ;NEXT OFFSET WILL BE HALF OF PREVIOUS ONE + MOV AX,ES:[SI] ;GET FIRST HALF OF CURRENT ZWORD + XCHG AH,AL + CMP DX,AX ;COMPARE DESIRED ONE TO IT + JA ORD19 ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20 ;LESS, WE'LL HAVE TO MOVE DOWN + MOV BP,SI ;SAME, GET SECOND HALF + INC BP + INC BP + MOV AX,ES:[BP] + XCHG AH,AL + CMP DI,AX ;COMPARE DESIRED WORD WITH IT + JA ORD19 ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20 ;LESS, WE'LL HAVE TO MOVE DOWN + JMP ORD22 ;SAME, WE'VE FOUND IT, RETURN IT +ORD19: ADD SI,BX ;TO MOVE UP, ADD CURRENT OFFSET + CMP SI,CX ;HAVE WE MOVED PAST END OF TABLE? + JBE ORD21 ;NO + MOV SI,CX ;YES, POINT TO END OF TABLE INSTEAD + JMP ORD21 +ORD20: SUB SI,BX ;TO MOVE DOWN, SIMPLY SUBTRACT OFFSET +ORD21: CMP BX,VWLEN ;IS OFFSET RESOLUTION BELOW ONE WORD? + JGE ORD18 ;NO, CONTINUE LOOP + SUB SI,SI ;YES, WORD NOT FOUND, RETURN ZERO +ORD22: POP DI ;RESTORE WORD ENTRY POINTER + MOV DX,SI ;POINTER TO WORD FOUND + XCHG DH,DL + MOV ES:[DI],DX ;STORE IT + POP DX ;RESTORE CHAR POINTER + ADD DI,4 ;UPDATE POINTER FOR NEXT WORD ENTRY + JMP ORD8 ;GO FOR IT +ORD23: INC RDRET ;DONE, STORE NUMBER OF WORDS FOUND + MOV BP,RDRET + MOV DL,RDNWDS + MOV ES:[BP],DL + POP DI ;RESTORE USER STACK POINTER + RET ;AND RETURN + + ;PRINTC (PRINT CHAR WHOSE ASCII VALUE IS GIVEN) +OPPRNC: JMP PUTCHR ;QUEUE THE CHARACTER FOR PRINTING + + ;PRINTN (PRINT A NUMBER) +OPPRNN: MOV BX,AX ;NUMBER TO PRINT + CMP BX,0 + JNE OPN1 ;NON-ZERO + MOV AX,'0' ;SPECIAL CASE ZERO + JMP PUTCHR +OPN1: JG OPN2 ;POSITIVE? + MOV AX,'-' ;NO, PRINT MINUS SIGN + CALL PUTCHR + NEG BX ;AND MAKE IT POSITIVE +OPN2: SUB CX,CX ;COUNT OF DIGITS ON STACK + JMP OPN4 ;START WITH GREATER-THAN-10 TEST +OPN3: MOV AX,BX ;EXTRACT A DIGIT + MOV BP,10 + CWD + IDIV BP + PUSH DX ;PUSH IT + INC CX ;BUMP COUNT + MOV BX,AX ;GET QUOTIENT +OPN4: CMP BX,10 ;MORE DIGITS TO EXTRACT? + JGE OPN3 ;YES, GO LOOP + MOV AX,BX ;NO, GET LAST (FIRST) DIGIT + JMP OPN6 ;ALREADY IN PLACE +OPN5: POP AX ;POP NEXT DIGIT +OPN6: ADD AX,'0' ;ASCIIZE IT + CALL PUTCHR ;QUEUE IT + DEC CX ;REDUCE DIGIT COUNT + JGE OPN5 ;LOOP IF SOME LEFT + RET ;ELSE, RETURN + + ;PRINT (THE STRING POINTED TO BY ES:AX) +OPPRIN: CALL BSPLIT ;SPLIT THE BLOCK & WORD NUMBERS + JMP PUTSTR ;PRINT THE STRING + + ;PRINTB (PRINT THE STRING POINTED TO BY THE BYTE-POINTER ES:AX) +OPPRNB: CALL BSPLTB ;SPLIT THE BLOCK & BYTE NUMBERS + JMP PUTSTR ;PRINT THE STRING + +;PSEUDO-INSTRUCTIONS FOR HOURS/MINUTES HERE FOR STATUS LINE +OPPRNH: MOV PMFLAG,0 + CMP AL,12 + JL OPH0 + MOV PMFLAG,1 +OPH0: CMP AL,0 + JNE OPH00 + MOV AL,12 +OPH00: CMP AL,12 + JLE OPH1 + SUB AL,12 ;HOUR SLOT IS 24 HOUR TIME +OPH1: CMP AL,9 + JG OPH2 + PUSH AX + MOV AL,32 + CALL PUTCHR ;OUTPUT SPACE FOR HOUR LESS THAN 10 + POP AX +OPH2: CALL OPPRNN + MOV AL,':' + JMP PUTCHR ;AND COLO + +OPPRNM: CMP AL,9 + JG OPM1 + PUSH AX + MOV AL,'0' + CALL PUTCHR + POP AX +OPM1: CALL OPPRNN + MOV AL,32 + CALL PUTCHR + MOV AL,'a' + CMP PMFLAG,0 + JE OPM2 + MOV AL,'p' +OPM2: CALL PUTCHR + MOV AL,'m' + JMP PUTCHR + + ;PRINTD (PRINT OBJ'S SHORT DESCRIPTION) +OPPRND: CALL OBJLOC ;FIND OBJ'S LOCATION + ADD AX,7 ;PROPERTY TABLE POINTER + MOV BP,AX + MOV AX,ES:[BP] ;GET IT + XCHG AH,AL + INC AX ;POINT TO STRING + CALL BSPLTB ;SPLIT POINTER + JMP PUTSTR ;AND PRINT THE STRING + + ;PRINTI (PRINT THE STRING FOLLOWING THIS INSTRUCTION) +OPPRNI: MOV AX,ZPC1 ;GET POINTER TO STRING + MOV BX,ZPC2 + CALL PUTSTR ;AND PRINT IT + MOV ZPC1,AX ;UPDATE ZPC + MOV ZPC2,BX + JMP NEWZPC + + ;PRINTR (PRINTI FOLLOWED BY RTRUE) +OPPRNR: CALL OPPRNI ;DO A PRINTI + CALL OPCRLF ;A CRLF + JMP OPRTRU ;AND AN RTRUE + + ;CRLF (DO A NEWLINE) +OPCRLF: JMP NEWLIN ;DO A NEWLINE + + ;CALL (A FUNCTION WITH OPTIONAL ARGUMENTS), # OF ARGS IN AX +OPCALL: NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV DX,AX ;NUMBER OF ARGUMENTS TO CALL + MOV AX,ARGBLK ;FUNCTION TO CALL + CMP AX,0 + JNE OCL1 ;ZERO? + SUB AX,AX ;YES, SIMPLY RETURN A ZERO + JMP PUTVAL +OCL1: XCHG SP,DI + PUSH ZPC1 + PUSH ZPC2 + MOV CX,ZLOCS ;AND OLD LOCAL POINTER + PUSH CX ;AND SAVE IT + XCHG SP,DI + CALL BSPLIT ;SPLIT FUNCTION POINTER + MOV ZPC1,AX ;MAKE IT THE NEW ZPC + MOV ZPC2,BX + CALL NEWZPC ;UPDATE ZPC STUFF + MOV ZLOCS,DI ;LOCALS WILL START AT NEXT STACK SLOT + SUB ZLOCS,2 + CALL NXTBYT ;NUMBER OF LOCALS + MOV BX,AX + MOV BP,OFFSET ARGBLK+2 ;POINT TO FIRST OPTIONAL ARG +OCL2: DEC BX ;ANY MORE LOCALS? + JL OCL4 ;NO, WE'RE DONE + CALL NXTWRD ;YES, GET THE NEXT LOCAL DEFAULT VALUE + DEC DX ;ANY MORE OPTIONALS GIVEN? + JLE OCL3 ;NO + XCHG SP,DI + MOV CX,DS:[BP] + PUSH CX ;YES, USE ITS VALUE + XCHG SP,DI + ADD BP,2 + JMP OCL2 ;AND CONTINUE LOOP +OCL3: XCHG SP,DI + PUSH AX ;OTHERWISE USE DEFAULT + XCHG SP,DI + JMP OCL2 ;AND LOOP +OCL4: RET + + ;RETURN (FROM CURRENT FUNCTION CALL) +OPRETU: MOV DI,ZLOCS ;RESTORE OLD TOP OF STACK + XCHG SP,DI + POP DX + POP ZLOCS + POP ZPC2 + POP ZPC1 + XCHG SP,DI + PUSH AX ;VALUE TO RETURN + CALL NEWZPC ;UPDATE ZPC STUFF + POP AX + JMP PUTVAL ;RETURN THE VALUE + + ;RTRUE +OPRTRU: MOV AX,1 ;RETURN A 1 + JMP OPRETU + + ;RFALSE +OPRFAL: SUB AX,AX ;RETURN A 0 + JMP OPRETU + + ;JUMP (TO A NEW LOCATION) +OPJUMP: ADD ZPC2,AX ;ADD OFFSET TO CURRENT ZPC + SUB ZPC2,2 ;ADJUST IT + JMP NEWZPC ;NORMALIZE IT & UPDATE ZPC STUFF + + ;RSTACK (RETURN STACK) +OPRSTA: XCHG SP,DI + POP AX + XCHG SP,DI + JMP OPRETU ;AND RETURN IT + + ;FSTACK (FLUSH A VALUE OFF THE STACK) +OPFSTA: XCHG SP,DI + POP DX + XCHG SP,DI + RET + + ;NOOP (NO OPERATION) +OPNOOP: RET ;DO NOTHING + + ;GET A BYTE, BLOCK-POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX, + ;UPDATE AX & BX TO REFLECT BYTE GOTTEN +GETBYT: PUSH AX ;SAVE BLOCK-POINTER + CMP AX,ENDLOD ;IS THIS A PRELOADED LOCATION? + JGE GTY1 ;NO + MOV CL,9 ;YES, RECONSTRUCT POINTER + SHL AX,CL ;SHIFT BLOCK POINTER BY 9 + OR AX,BX ;ADD IN THE OFFSET + XCHG AX,BX + MOV CL,ES:[BX] ;GET THE BYTE + JMP GTY2 ;CLEAR UNWANTED BYTE & RETURN IT +GTY1: CALL GETPAG ;FIND THE PROPER PAGE + ADD AX,BX ;POINT TO DESIRED BYTE + XCHG AX,BX + MOV CL,ES:[BX] ;GET IT +GTY2: SUB CH,CH ;CLEAR UNWANTED BYTE & RETURN IT + MOV BX,AX + POP AX ;RESTORE BLOCK-POINTER + INC BX ;UPDATE POINTER + CMP BX,200H ;END-OF-PAGE? + JNE GTY3 ;NO + SUB BX,BX ;YES, CLEAR BYTE-POINTER + INC AX ;AND UPDATE BLOCK-POINTER +GTY3: RET + + ;GET A WORD, BLOCK POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX +GETWRD: PUSH DX ;SAVE + CALL GETBYT ;GET HIGH-ORDER BYTE + PUSH CX ;SAVE IT + CALL GETBYT ;GET LOW-ORDER BYTE + POP DX ;GET OTHER BYTE + MOV CH,DL ;POSITION IT + POP DX ;RESTORE + RET + + ;GET THE NEXT BYTE, RETURN IT IN AX +NXTBYT: PUSH BX ;SAVE + MOV BX,ZPC2 ;BYTE POINTER + ADD BX,CURPAG ;INDEX INTO CURRENT PAGE + MOV AX,ES:[BX] ;SAVE BYTE ***POSSIBLE LOSER + PUSH AX + INC ZPC2 ;UPDATE PC + CMP ZPC2,200H ;END-OF-PAGE? + JL NXB1 ;NO + CALL NEWZPC ;YES, UPDATE PAGE +NXB1: POP AX ;RETRIEVE BYTE + SUB AH,AH ;CLEAR UNWANTED BYTE + POP BX ;RESTORE + RET ;AND RETURN IT + + ;GET THE NEXT WORD, RETURN IT IN AX +NXTWRD: PUSH BX ;SAVE + CALL NXTBYT ;GET HIGH-ORDER BYTE + PUSH AX ;SAVE IT + CALL NXTBYT ;GET LOW-ORDER BYTE + POP BX ;GET HIGH-ORDER BYTE + MOV AH,BL ;POSITION IT + POP BX ;RESTORE + RET ;RETURN THE WORD + + ;GET AN ARGUMENT GIVEN ITS TYPE IN AX +GETARG: DEC AX ;EXAMINE ARGUMENT + JL NXTWRD ;0 MEANT LONG IMMEDIATE + JE NXTBYT ;1 MEANT SHORT IMMEDIATE + CALL NXTBYT ;2 MEANT VARIABLE, GET THE VAR + CMP AX,0 ;STACK? + JNE GETVAR ;NO, JUST GET THE VAR'S VALUE + XCHG SP,DI + POP AX ;YES, POP THE STACK + XCHG SP,DI + RET + + ;GET VALUE OF A VARIABLE, VAR IN AX, VALUE RETURNED IN AX +GETVAR: CMP AX,0 ;STACK? + JNE GTV1 ;NO + MOV AX,SS:[DI] ;YES, GET TOP-OF-STACK + RET + +GTV1: PUSH BP ;SAVE + CMP AX,16 ;LOCAL? + JGE GTV3 ;NO + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV AX,[BP] ;AND GET IT +GTV2: POP BP ;RESTORE + RET + +GTV3: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + MOV BP,AX ;AND GET IT + MOV AX,ES:[BP] + XCHG AH,AL + JMP GTV2 + + ;UPDATE VALUE OF A VARIABLE, VAR IN AX, NEW VALUE IN BX +PUTVAR: CMP AX,0 ;STACK? + JNE PTV1 ;NO + MOV SS:[DI],BX ;YES, UPDATE TOP-OF-STACK + RET + +PTV1: CMP AX,16 ;LOCAL? + JGE PTV2 ;NO + PUSH BP ;SAVE + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV [BP],BX ;AND UPDATE IT + POP BP ;RESTORE + RET + +PTV2: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + XCHG AX,BX ;AND UPDATE IT + XCHG AH,AL + MOV ES:[BX],AX + RET + + ;RETURN VAL IN AX TO LOCATION SPECIFIED BY NEXTBYTE + ;DESTROYS BX, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION +BYTVAL: SUB AH,AH ;THIS ENTRY FOR BYTE VALUE TO CLEAR HIGH BYTE + JMP PUTVAL + +PUTVAL: MOV BX,AX ;NORMAL ENTRY + CALL NXTBYT ;GET VAR TO USE + CMP AX,0 ;STACK? + JNE PUTVAR ;NO, GO STORE VALUE + XCHG SP,DI + PUSH BX ;YES, PUSH ONTO STACK + XCHG SP,DI + RET ;AND RETURN + + ;PREDICATE HANDLERS TRUE & FALSE + ;DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FCNS +PFALSE: SUB BX,BX ;PREDICATE WAS FALSE, CLEAR FLAG + JMP PPRED + +PTRUE: MOV BX,1 ;PREDICATE WAS TRUE, SET FLAG + JMP PPRED + +PPRED: CALL NXTBYT ;GET FIRST (OR ONLY) PREDICATE JUMP BYTE + TEST AX,80H ;NORMAL POLARITY PREDICATE? + JE PPR1 ;NO, LEAVE FLAG ALONE + INC BX ;YES, INCREMENT FLAG +PPR1: TEST AX,40H ;ONE-BYTE JUMP OFFSET? + JE PPR2 ;NO + AND AX,0FF3FH ;YES, CLEAR SPECIAL BITS + JMP PPR3 +PPR2: AND AX,0FF3FH ;CLR SPECIAL BITS FROM HIGH-ORDER OFFSET BYTE + MOV CX,AX ;HIGH-ORDER BYTE + CALL NXTBYT ;GET LOW-ORDER BYTE + MOV AH,CL ;MOVE IN HIGH-ORDER BITS + TEST AX,2000H ;IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)? + JE PPR3 ;NO + OR AX,0C000H ;YES, MAKE 16-BIT NUMBER NEGATIVE +PPR3: DEC BX ;TEST FLAG + JE PPR6 ;WAS 1, THAT MEANS DO NOTHING + CMP AX,0 ;ZERO JUMP? + JNE PPR4 ;NO + JMP OPRFAL ;YES, THAT MEANS DO AN RFALSE +PPR4: DEC AX ;ONE JUMP? + JNE PPR5 ;NO + JMP OPRTRU ;YES, THAT MEANS DO AN RTRUE +PPR5: DEC AX ;ADJUST OFFSET + ADD ZPC2,AX ;ADD TO PC + JMP NEWZPC ;AND UPDATE ZPC STUFF +PPR6: RET + + ;SPLIT BYTE-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE OFFSET IN BX +BSPLTB: MOV BX,AX + XCHG AL,AH ;EXTRACT BLOCK BITS + SHR AX,1 + AND AX,7FH ;CLEAR UNWANTED BITS + AND BX,1FFH ;CLEAR ALL BUT BYTE OFFSET BITS + RET + + ;SPLIT WORD-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE-OFFSET IN BX +BSPLIT: MOV BX,AX + MOV AL,AH ;EXTRACT BLOCK BITS + SUB AH,AH ;CLEAR UNWANTED BITS + SUB BH,BH ;CLEAR ALL BUT WORD OFFSET BITS + SHL BX,1 ;CONVERT TO BYTE OFFSET + RET + + ;GIVEN OBJ NUMBER IN AX, RETURN OBJ LOCATION IN AX +OBJLOC: SUB AH,AH ;CLEAR UNWANTED BITS + PUSH BX ;MULTIPLY BY 9 THE LAZY WAY + MOV BX,AX + SHL AX,1 + SHL AX,1 + SHL AX,1 + ADD AX,BX + POP BX ;RESTORE + ADD AX,OBJTAB ;INDEX INTO OBJECT TABLE + ADD AX,53 ;SKIPPING DEFAULT PROPERTY TABLE + RET + + ;GIVEN POINTER TO A PROPERTY IN BX!, UPDATE IT TO POINT TO NEXT PROP +NXTPRP: PUSH AX ;SAVE + PUSH CX ;SAVE + MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,224 ;EXTRACT PROPERTY LENGTH + MOV CL,5 ;PROPSIZE + SHR AL,CL + SUB AH,AH + ADD BX,AX ;ADD IT TO OLD POINTER + ADD BX,2 ;ADJUST FOR EXTRA LENGTH BYTE PLUS IDENTIFIER + POP CX ;RESTORE + POP AX ;RESTORE + RET + + ;OUTPUT A ZSTR, BLOCK-POINTER IN AX, BYTE-POINTER IN BX + ;RETURN UPDATED POINTER +PUTSTR: PUSH SI ;SAVE + PUSH CX ;SAVE + PUSH DX ;SAVE + PUSH DI ;SAVE + PUSH BP ;SAVE + SUB DX,DX ;TEMP CS STARTS AT 0 + SUB DI,DI ;PERM CS STARTS AT 0 +PTS1: CALL GETWRD ;GET NEXT STRING WORD + MOV SI,CX + PUSH AX ;SAVE POINTER & COPY OF STRING WORD + PUSH BX + PUSH SI + MOV CX,3 ;3 BYTES IN WORD +PTS2: PUSH SI ;SAVE CURRENT BYTE (IN LOW-ORDER POSITION) + MOV BP,CX ;SHIFT TO NEXT BYTE + MOV CL,5 + SAR SI,CL + MOV CX,BP + LOOP PTS2 ;LOOP UNTIL DONE + MOV CX,3 ;RETRIEVE THE 3 BYTES +PTS3: POP SI ;GET NEXT BYTE + AND SI,1FH ;CLEAR UNWANTED BITS + CMP DX,0 ;IN WORD MODE? + JGE PTS4 ;NO {WAS BPL, CHECK} + SAL SI,1 ;YES, CALCULATE WORD OFFSET + ADD SI,WRDTAB ;POINT INTO WORD TABLE + ADD SI,WRDOFF ;USING PROPER 32-WORD BLOCK + MOV AX,ES:[SI] ;POINT TO WORD STRING + XCHG AH,AL + CALL BSPLIT ;SPLIT IT + CALL PUTSTR ;AND PRINT IT + JMP PTS15 ;CONT. WHERE WE LEFT OFF WITH TEMP CS RESET +PTS4: CMP DX,3 ;CS 3 SELECTED (ASCII MODE)? + JL PTS6 ;NO, NORMAL CS + JNE PTS5 ;NO, BUT WE ARE IN ASCII MODE + XCHG DL,DH ;SHIFT SOME BITS HIGH TO MAKE NUMBER LARGE + OR DX,SI ;SAVE HIGH-ORDER ASCII BITS HERE + JMP PTS16 ;GO GET NEXT BYTE +PTS5: AND DX,3 ;EXTRACT PREVIOUSLY SAVED HIGH-ORDER BITS + MOV BP,CX ;POSITION THEM + MOV CL,5 + SAL DX,CL + MOV CX,BP + OR DX,SI ;OR IN LOW-ORDER BITS + MOV AX,DX + JMP PTS14 ;GO PRINT THE CHARACTER +PTS6: CMP SI,6 ;SPECIAL CODE? + JL PTS9 ;YES, SPACE, WORD, OR SHIFT + CMP DX,2 ;MIGHT ALSO BE SPECIAL IF IN CS 2 + JNE PTS8 ;BUT WE'RE NOT + CMP SI,7 ;CRLF? + JE PTS7 ;YES + JG PTS8 ;NO, NOT ASCII MODE, EITHER? + INC DX ;YES IT IS, SWITCH TO ASCII MODE + JMP PTS16 ;AND GO GET NEXT BYTE +PTS7: CALL NEWLIN ;CRLF REQUESTED, DO A NEWLINE + JMP PTS15 +PTS8: MOV AX,DX ;NORMAL CHARACTER, GET CS + MOV BP,26 ;CALCULATE OFFSET FOR THIS CS + MUL BP + ADD AX,SI ;ADD IN CHARACTER OFFSET (+6) + SUB AX,6 ;CHARACTER OFFSET + MOV BX,OFFSET ZCHRS ;GET THE CHARACTER FROM CONVERSION VECTOR + XLAT ZCHRS + JMP PTS14 ;GO PRINT IT +PTS9: CMP SI,0 ;IS IT A SPACE? + JNE PTS10 ;NO + MOV AX,' ' ;YES, GO PRINT A SPACE + JMP PTS14 +PTS10: CMP SI,3 ;IS IT A WORD? + JG PTS11 ;NO, MUST BE A SHIFT + OR DX,8000H ;SWITCH TO WORD MODE FOR NEXT BYTE + DEC SI ;CALCULATE WORD-TABLE BLOCK OFFSET + MOV BP,CX ;64 BYTES IN A BLOCK + MOV CL,6 + SHL SI,CL + MOV CX,BP + MOV WRDOFF,SI ;SAVE IT AND LOOP + JMP PTS16 +PTS11: SUB SI,3 ;CALCULATE NEW CS + CMP DX,0 ;TEMPORARY SHIFT (FROM CS 0)? + JNE PTS12 ;NO + MOV DX,SI ;YES, JUST SAVE NEW TEMP CS + JMP PTS16 +PTS12: CMP SI,DX ;IS THIS THE CURRENT CS? + JE PTS13 ;YES, DO A PERM SHIFT TO IT + SUB DX,DX ;OTHERWISE, PERM SHIFT TO CS 0 +PTS13: MOV DI,DX ;TEMP & PERM CS'S ARE SAME NOW + JMP PTS16 +PTS3A: JMP PTS3 ;DUMMY FOR NON-SHORT LOOP +PTS14: CALL PUTCHR ;PRINT THE CHARACTER +PTS15: MOV DX,DI ;RESET TEMP CS TO PERM CS +PTS16: LOOP PTS3A ;NEXT BYTE + POP SI ;RESTORE POINTERS & ORIGINAL STRING WORD + POP BX + POP AX + CMP SI,0 ;END-OF-STRING? + JL PTS1A ;YES, CLEAN UP & RETURN UPDATED POINTER + JMP PTS1 ;NO, GET NEXT WORD +PTS1A: POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN THE CHARACTER SET # IN AX +CHRCS: CMP AX,0 ;IS THIS A NULL? + JNE CCS1 ;NO + MOV AX,3 ;YES, RETURN DUMMY CS NUMBER + RET + +CCS1: PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CONVERSION VECTOR +CCS2: INC BX ;FOUND THE CHARACTER? + CMP AL,-1[BX] + JE CCS3 ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CCS2 ;NO, CONTINUE LOOP + MOV AX,2 ;YES, CALL IT CS 2 + JMP CCS5 +CCS3: SUB BX,OFFSET ZCHRS ;FIND CHARACTER POSITION + SUB AX,AX ;START WITH CS 0 +CCS4: SUB BX,26 ;EVERY 26 CHARACTERS IS A NEW CS + JLE CCS5 ;DONE + INC AX ;INCREMENT CS # & CONTINUE LOOP + JMP CCS4 +CCS5: POP BX + RET + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN ZSTR BYTE VALUE IN AX +CHRBYT: PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CHARACTER CONVERSION TABLE +CHB1: INC BX ;FOUND THE CHARACTER? + CMP AL,-1[BX] + JE CHB2 ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CHB1 ;NO, CONTINUE LOOP + SUB AX,AX ;YES, RETURN ZERO FOR FAILURE + JMP CHB4 +CHB2: SUB BX,OFFSET ZCHRS-5 ;ADJUST POINTER SO FIRST CHARACTER IS 6 + MOV AX,BX +CHB3: CMP AX,32 ;SUBTRACT MULTIPLES OF 26 UNTIL BASE CODE + JL CHB4 + SUB AX,26 + JMP CHB3 +CHB4: POP BX ;RESTORE + RET + + ;CONVERT UP TO 6 ASCIZ CHARS POINTED TO BY DS:AX + ;TO A 2-WORD ZSTR RETURNED IN AX & BX +ZWORD: PUSH SI ;SAVES + PUSH CX + PUSH DX + PUSH DI + PUSH BP + MOV SI,AX ;CHARACTER STRING POINTER + SUB DI,DI ;CS STARTS AT 0 + MOV CX,6 ;MAKE 6 ZSTR BYTES +ZWD1: INC SI ;GET NEXT CHARACTER + MOV BL,-1[SI] + CMP BL,0 + JNE ZWD3 ;NOT END-OF-STRING + MOV AX,OFFSET PADCHR;AT END-OF-STRING, PAD WITH PAD CHARACTER +ZWD2: PUSH AX ;SAVE A PAD BYTE + LOOP ZWD2 ;LOOP UNTIL DONE + JMP ZWD6 ;THEN GO FORM ZWORD +ZWD3: MOV AX,BX + CALL CHRCS ;FIND THE CS NUMBER FOR THIS CHAR + CMP AX,0 ;CS 0? + JE ZWD4 ;YES + ADD AX,3 ;NO, CALCULATE TEMP SHIFT BYTE + PUSH AX ;SAVE THE SHIFT BYTE + DEC CX ;REDUCE BYTE COUNT + JE ZWD6 ;DONE +ZWD4: MOV AX,BX ;FIND THE PROPER BYTE VALUE FOR THIS CHAR + CALL CHRBYT + CMP AX,0 ;IN NORMAL CS'S? + JNE ZWD5 ;YES + MOV AX,6 ;NO, USE ASCII SHIFT + PUSH AX + DEC CX ;DONE YET? + JE ZWD6 ;YES + MOV AX,BX ;NO, SAVE HIGH-ORDER ASCII BITS + MOV BP,CX + MOV CL,5 + SAR AX,CL + MOV CX,BP + PUSH AX + DEC CX ;DONE YET? + JE ZWD6 ;YES + AND BX,1FH ;NO, SAVE LOW-ORDER ASCII BITS + MOV AX,BX +ZWD5: PUSH AX ;SAVE THIS BYTE + LOOP ZWD1 ;LOOP UNTIL ZWORD FULL +ZWD6: MOV BP,SP ;BUILD ZWORD WORDS FROM 6 SAVED BYTES + MOV AX,10[BP] + MOV CL,5 + SHL AX,CL + OR AX,8[BP] + SHL AX,CL + OR AX,6[BP] + MOV BX,4[BP] + SHL BX,CL + OR BX,2[BP] + SHL BX,CL + OR BX,[BP] + OR BX,8000H ;SET END-OF-STRING BIT IN SECOND WORD + ADD SP,12 ;FLUSH STACK + POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET + + ;QUEUE CHARACTER IN AX FOR OUTPUT +PUTCHR: PUSH BP + MOV BP,CHRPTR ;END OF BUFFER? + CMP BP,ENDBUF + JNE PTC7 ;NO + PUSH AX ;YES, ENTER OUTPUT ROUTINE; SAVES + PUSH BX + PUSH SI + MOV BX,ENDBUF ;END OF BUFFER + MOV SI,OFFSET OUTBUF;BEGINNING OF BUFFER +PTC1: DEC BX ;SEARCH FOR SPACE BACKWARDS FROM END + CMP BYTE PTR [BX],' ' + JE PTC3 + CMP BX,SI ;STOP AT BEGINNING OF BUFFER + JNE PTC1 +PTC2: MOV AX,OFFSET OUTBUF + CALL M_PRNT ;NO SPACES. OUTPUT WHOLE LINE + MOV CHRPTR,SI ;RESTORE POINTER TO BEGINNING OF BUFFER + MOV BP,SP + CMP BYTE PTR 4[BP],' ' ;DID A SPACE CAUSE BUFFER OVERFLOW? + JNE PTC6 ;NO + MOV WORD PTR 4[BP],0 ;YES, FLUSH IT + JMP PTC6 ;AND RETURN +PTC3: CMP BX,SI ;DEGENERATE CASE WITH SPACE AT OUTBUF? + JE PTC2 ;YES, OUTPUT WHOLE LINE + MOV BYTE PTR [BX],0 ;NO, OUTPUT UP TO SPACE + MOV AX,OFFSET OUTBUF + CALL M_PRNT + MOV AX,ENDBUF ;END OF BUFFER + INC BX ;START GETTING CHARACTERS AFTER THE SPACE +PTC4: CMP BX,AX ;AT END YET? + JE PTC5 ;YES + MOV BP,AX ;SAVE AX + MOV AL,[BX] + MOV [SI],AL ;NO, COPY NEXT CHAR TO BEGINNING OF BUF + MOV AX,BP ;RESTORE AX + INC BX + INC SI + JMP PTC4 ;AND CONTINUE +PTC5: MOV CHRPTR,SI ;NEXT CHAR WILL GO AFTER COPIED STUFF +PTC6: POP SI ;CLEAN UP + POP BX + POP AX + CMP AX,0 ;AND IGNORE A NULL CHARACTER + JE PTC8 +PTC7: MOV BP,CHRPTR ;NOW STORE THE CHARACTER IN BUFFER + MOV DS:[BP],AL + INC CHRPTR ;UPDATE POINTER +PTC8: POP BP ;RESTORE + RET ;AND RETURN + + ;GO TO NEW LINE, OUTPUTTING CURRENT BUFFER +NEWLIN: PUSH BX ;SAVE + MOV BX,CHRPTR ;END LINE AT CURRENT POINT + MOV BYTE PTR [BX],0 + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP BX ;RESTORE + MOV AX,OFFSET OUTBUF + CALL M_PRNT ;AND OUTPUT LINE + RET + + ;INITIALIZATION +TSETUP: MOV BX,OFFSET OUTBUF;START OF OUTPUT BUFFER + MOV AL,SCPL + SUB AH,AH + ADD BX,AX ;ADD LENGTH OF BUFFER + MOV ENDBUF,BX ;THIS IS ENDBUF POINTER + MOV BYTE PTR [BX],0 ;BUFFER IS FOLLOWED BY A 0 FOR CONVENIENCE + MOV BX,OFFSET SLSTAB + CMP TIMEMD,0 + JE TSET1 + ADD BX,4 +TSET1: MOV AX,[BX] + MOV SLSTR,AX + MOV CX,2[BX] + MOV SLTAB,CX + CALL M_INIT + RET + +ZIPBGN: CALL SYSINI ;DO ANY SYSTEM INITIALIZATION +STR5: MOV AX,MBLEN + MOV MEMTOP,AX + SUB AX,AX ;BLOCK 0 + SUB BX,BX ;PUT AT BEGINNING OF GAME SEGMENT + CALL GETBLK ;GET THE BLOCK + CMP ES:BYTE PTR .PVERS1,ZMVERS ;PROPER Z-MACHINE VERSION? + JNE STR8 ;NO + TEST ES:BYTE PTR .PVERS2,1 ;YES,PROPER MODE BITS? + JE STR9 ;YES +STR8: MOV AX,OFFSET FTL4 + JMP FATAL +STR9: TEST ES:BYTE PTR .PVERS2,2 ;TIME MODE REQUESTED? + JE STR10 ;NO + INC TIMEMD ;YES, SET TIME-MODE FLAG +STR10: MOV AX,ES:.PZRKID ;UNIQUE GAME & VERSION IDENTIFIER + XCHG AH,AL + MOV ZORKID,AX + MOV AX,ES:.PENDLD ;GET ENDLOD POINTER + XCHG AH,AL + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR12 + AND AX,0FE00H + ADD AX,200H +STR12: MOV CX,AX + MOV BP,CX ;EXTRACT ENDLOD BLOCK + MOV CL,9 + SAR BP,CL + MOV CX,BP + MOV ENDLOD,CX ;SAVE ENDLOD BLOCK NUMBER + DEC CX ;NUMBER OF BLOCKS LEFT TO LOAD + MOV AX,1 ;STARTING WITH BLOCK 1 + MOV BX,200H ;LOCATION TO PUT THEM + CALL GTBLKS ;GET THE BLOCKS + MOV AX,ES:.PVOCTB ;VOCAB LOCATION + XCHG AH,AL + MOV VOCTAB,AX ;SAVE VOCABULARY TABLE POINTER + MOV AX,ES:.POBJTB ;GET OBJECT TABLE POINTER + XCHG AH,AL + MOV OBJTAB,AX + MOV AX,ES:.PGLOTB ;GET GLOBAL TABLE POINTER + XCHG AH,AL + MOV GLOTAB,AX + MOV AX,ES:.PWRDTB ;GET WORD TABLE POINTER + XCHG AH,AL + MOV WRDTAB,AX + MOV AX,ES:.PPURBT ;GET PURE CODE POINTER + XCHG AH,AL + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR13 + ADD AX,200H +STR13: MOV CL,9 ;EXTRACT BLOCK NUMBER + SAR AX,CL + AND AX,7FH ;CLEAR UNWANTED BITS + MOV PURBOT,AX ;SAVE IT + MOV BX,OFFSET RBRKS ;START OF READ BREAK CHARACTER TABLE + MOV SI,VOCTAB ;VOCAB TABLE POINTER + MOV CL,ES:BYTE PTR [SI] ;1ST BYTE IN VOCTAB IS # OF SIBREAKS + SUB CH,CH ;CLEAR HIGH BYTE + INC SI +STR14: MOV AL,ES:[SI] + MOV [BX],AL ;TRANSFER THEM + INC BX + INC SI + LOOP STR14 + MOV ESIBKS,BX ;REMEMBER END OF SI BREAKS + MOV BP,OFFSET IRBRKS;ALWAYS END WITH INITIAL BREAK CHARACTERS +STR15: MOV AL,DS:[BP] + MOV [BX],AL ;TRANSFER THEM + INC BX + INC BP + CMP AL,0 + JNE STR15 + MOV AL,ES:[SI] ;GET VOCABULARY ENTRY LENGTH + SUB AH,AH + MOV VWLEN,AX ;AND STORE IT AWAY + INC SI + MOV AX,ES:[SI] ;GET NEXT WORD IN TABLE + XCHG AH,AL + MOV VWORDS,AX ;NUMBER OF WORD ENTRIES IN VOCABULARY + ADD SI,2 ;MOVE TO NEXT WORD + MOV VOCBEG,SI ;BEGINNING OF ACTUAL VOCABULARY + + MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + MOV CL,9 + SHL SI,CL ;THIS IS FIRST LOCATION (ES:) OF PAGING + MOV PAGES,SI ;SAVE THIS TO USE AS AN OFFSET + + MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + NEG SI + MOV DI,MEMTOP ;GET PARAGRAPHS OF MEMORY + MOV CL,5 + SAR DI,CL ;CHANGE TO PAGES + ADD SI,DI ;NUMBER OF PAGES FOR PAGING + MOV BUFPGS,SI ;SAVE THIS NUMBER FOR FUTURE REFERENCE + CMP BUFPGS,63 + JLE STR16 + MOV BUFPGS,63 ;OUR TABLE IS ONLY SO BIG.... + MOV SI,63 +STR16: SHL SI,1 + SHL SI,1 ;EACH PAGE HAS 4 BYTES OF INFO + MOV BX,OFFSET PAGTAB ;POINT INTO PAGE INFO TABLE + ADD SI,BX + MOV WORD PTR [SI],-1 ;MAKE THIS THE END OF TABLE MARK + + CALL M_TIME ;GET THE CURRENT TIME-OF-DAY + JMP START1 + + ;RESTART EXECUTION HERE +RESTRT: SUB AX,AX ;REREAD ALL OF THE IMPURE STUFF + SUB BX,BX + MOV CX,PURBOT + CALL GTBLKS +START1: CALL TSETUP ;SETUP TERMINAL/STATUS LINE + CALL CLRSCR ;CLEAR THE REMAINDER OF SCREEN + MOV SP,OFFSET STK_TOP ;INITIALIZE OUR STACK POINTER + MOV DI,OFFSET ZSTK_TP ;INITIALIZE USER STACK POINTER + MOV CHRPTR,OFFSET OUTBUF ;INITIALIZE OUTPUT CHARACTER POINTER + MOV ZLOCS,DI ;LOCALS WOULD START AT FIRST SLOT, + SUB ZLOCS,2 ;IF THERE WERE ANY + MOV AX,ES:.PSTART ;GET STARTING LOCATION + XCHG AH,AL + CALL BSPLTB ;SPLIT BLOCK & BYTE POINTERS + MOV ZPC1,AX ;INITIALIZE ZPC BLOCK-POINTER + MOV ZPC2,BX ;INITIALIZE ZPC BYTE-POINTER + CALL NEWZPC ;GET PAGE TO EXECUTE + JMP NXTINS + + ;MAIN INSTRUCTION INTERPRETATION LOOP +NXTINS: CALL NXTBYT ;GET THE OPERATION BYTE + MOV DX,AX ;SAVE A COPY + CMP AX,80H ;IS IT A 2OP? + JL NXI9 ;YES + CMP AX,0B0H ;NO, IS IT A 1OP? + JGE NXI0A ;NO + JMP NXI12 ;YES +NXI0A: CMP AX,0C0H ;IS IT A 0OP? + JG NXI0B ;NO + JMP NXI13 ;YES +NXI0B: AND AX,3FH ;IT'S EXTENDED, GET THE OPCODE + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET THE OPERATOR POINTER + MOV SI,DS:EXTOP[BP] + CMP SI,0 + JNE NXI0C ;OPERATION EXISTS + JMP NXI14 ;NO SUCH OPERATION +NXI0C: CALL NXTBYT ;GET THE ARGUMENT BYTE + MOV CX,4 ;SPLIT IT INTO 4 2-BIT MODE BYTES +NXI1: PUSH AX + SAR AX,1 + SAR AX,1 + LOOP NXI1 + MOV CX,4 ;RETRIEVE THE 4 BYTES IN PROPER ORDER + SUB DX,DX + MOV BX,OFFSET ARGBLK;FIRST ARGUMENT SLOT +NXI2: POP AX ;GET NEXT MODE BYTE? + AND AX,3 ;CLEAR OFF UNWANTED BITS + CMP AX,3 ;NO MORE ARGUMENTS? + JE NXI4 ;YES, FLUSH ANY OTHER MODE BYTES + CALL GETARG ;ELSE, GET THE NEXT ARGUMENT + MOV [BX],AX ;SAVE IT IN ARGUMENT BLOCK + ADD BX,2 + INC DX ;REMEMBER NUMBER OF ARGS GOTTEN +NXI3: LOOP NXI2 ;LOOP FOR REST OF MODE BYTES + JMP NXI5 +NXI4: DEC CX ;DETERMINE NUMBER OF REMAINING MODE BYTES + SHL CX,1 ;WORD COUNT + ADD SP,CX ;FLUSH THEM +NXI5: XCHG CX,DX + MOV AX,CX ;NUMBER OF ARGS GOES HERE FOR OPERATOR TO USE + CMP CS:BYTE PTR [SI],90H ;DOES OPERATOR WANT ARGBLK POINTER? + JE NXI8A ;YES, CALL OPERATOR NOW + DEC CX ;NO, IT WANTS ARGS IN REGISTERS + JL NXI8A ;NO ARGS, JUST CALL OPERATOR + JE NXI8 ;1 ARG, GET IT + SUB CX,2 + JL NXI7 ;2 ARGS + JE NXI6 ;3 ARGS + MOV DX,ARGBLK+6 ;ELSE, 4 ARGS, GET 4TH +NXI6: MOV CX,ARGBLK+4 ;GET 3RD +NXI7: MOV BX,ARGBLK+2 ;GET 2ND +NXI8: MOV AX,ARGBLK ;GET FIRST ARG +NXI8A: JMP NXI15 ;AND CALL OPERATOR +NXI9: AND AX,1FH ;2OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;FIND POINTER TO OPERATOR ROUTINE + MOV SI,DS:EXTOP[BP] + CMP SI,0 + JE NXI14 ;NO SUCH OPERATION + MOV AX,1 ;ASSUME FIRST ARG IS AN IMMEDIATE + TEST DX,40H ;IS IT INSTEAD A VARIABLE? + JE NXI10 ;NO + INC AX ;YES, CHANGE MODE +NXI10: CALL GETARG ;GET THE FIRST ARG + PUSH AX ;SAVE IT + MOV AX,1 ;ASSUME SECOND ARG IS AN IMMEDIATE + TEST DX,20H ;IS IT INSTEAD A VARIABLE? + JE NXI11 ;NO + INC AX ;YES, CHANGE MODE +NXI11: CALL GETARG ;GET THE SECOND ARG + MOV BX,AX ;POSITION IT + POP AX ;RECOVER FIRST ARG + CMP CS:BYTE PTR [SI],90H ;DOES ROUTINE WANT ARGUMENT BLOCK? + JNE NXI15 ;NO, GO CALL IT + MOV ARGBLK,AX ;YES, MOVE ARGS TO ARGBLK + MOV ARGBLK+2,BX + MOV AX,2 ;ALWAYS 2 ARGS + JMP NXI15 ;NOW CALL OPERATOR +NXI12: AND DX,0FH ;1OP, EXTRACT OPERATION BITS + SHL DX,1 ;MAKE IT A WORD OFFSET + MOV BP,DX ;GET OPERATOR ROUTINE POINTER + MOV SI,DS:ONEOP[BP] + CMP SI,0 + JE NXI14 ;ILLEGAL OPERATION + SAR AX,1 ;EXTRACT MODE BITS + SAR AX,1 + SAR AX,1 + SAR AX,1 + AND AX,3 + CALL GETARG ;GET THE ARGUMENT + JMP NXI15 ;AND CALL OPERATOR +NXI13: AND AX,0FH ;0OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET OPERATOR ROUTINE POINTER + MOV SI,DS:ZEROOP[BP] + CMP SI,0 + JNE NXI15 ;IT'S A LEGAL OPERATION +NXI14: MOV AX,OFFSET FTL5 + JMP FATAL +NXI15: CALL SI ;CALL THE OPERATOR ROUTINE + JMP NXTINS ;AND LOOP FOR NEXT INSTRUCTION + + ;NORMALIZE ZPC & GET PROPER PAGE +NEWZPC: PUSH SI ;SAVES + PUSH BP + PUSH BX + PUSH CX + PUSH DX + SUB AX,AX ;USE DOUBLE-WORD ARITHMETIC + MOV BX,ZPC1 ;GET BLOCK-POINTER + MOV BH,BL ;POSITION IT + SUB BL,BL + SHL BX,1 + ADC AX,0 + MOV SI,ZPC2 ;GET BYTE-OFFSET + XCHG SI,AX ;DOUBLE-WORDIFY IT (MIGHT BE NEGATIVE) + CWD + XCHG SI,AX + ADD BX,SI ;ADD IT TO OTHER DOUBLE WORD + ADC AX,DX + MOV DX,BX + AND DX,1FFH ;EXTRACT BYTE-OFFSET + MOV ZPC2,DX ;SAVE IT + MOV CL,9 ;EXTRACT BLOCK-POINTER + SAR BX,CL + AND BX,7FH + TEST AX,1 ;TEST 17TH BIT + JE NWZ1 ;WAS 0 + OR BX,80H ;WAS 1, SET PROPER BIT IN BLOCK-POINTER +NWZ1: MOV ZPC1,BX ;SAVE IT + CMP BX,CURBLK ;HAS IT CHANGED? + JE NWZ5 ;NO + MOV CURBLK,BX ;YES, REMEMBER NEW BLOCK + MOV AX,CURTAB ;IS OLD PAGE IN PAGING SPACE? + CMP AX,0 + JE NWZ2 ;NO + MOV BP,AX ;YES, STORE CURRENT REF TIME FOR OLD PAGE + MOV CL,RTIME1 + MOV DS:[BP],CL + MOV CX,RTIME2 + MOV DS:1[BP],CX + INC AX +NWZ2: CMP BX,ENDLOD ;NEW PAGE ALREADY IN CORE? + JL NWZ3 ;YES + MOV AX,BX ;NO, GET NEW PAGE + CALL GETPAG + MOV BX,AX + MOV AX,LPTAB ;GET NEW PAGE TABLE POINTER + INC AX ;POINT TO REF SLOT + MOV CURTAB,AX ;SAVE THIS POINTER FOR LATER + MOV BP,AX ;STORE HIGHEST RTIME TO KEEP PAGE FOR US + MOV DS:BYTE PTR [BP],-1 + MOV DS:WORD PTR 1[BP],-1 + INC AX + JMP NWZ4 +NWZ3: MOV CL,9 ;CALCULATE PAGE ADDRESS + SHL BX,CL + MOV CURTAB,0 ;CLEARING POINTER MEANS PAGE IS PRELOADED +NWZ4: MOV CURPAG,BX ;UPDATE PAGE POINTER +NWZ5: POP DX ;RESTORES + POP CX + POP BX + POP BP + POP SI + RET ;AND RETURN + + ;GET THE PAGE WHOSE NUMBER IS IN AX, RETURN A POINTER TO IT IN AX +GETPAG: CMP AX,LPAGE ;IS THIS THE SAME PAGE AS LAST REFERENCED? + JNE GTP1 ;NO + MOV AX,LPLOC ;YES, WE ALREADY HAVE LOCATION + RET ;RETURN IT + +GTP1: MOV LPAGE,AX ;SAVE NEW PAGE NUMBER + PUSH CX ;SAVES + PUSH BX + ADD RTIME2,1 ;UPDATE REFERENCE TIME (COUNT) + ADC RTIME1,0 + MOV BX,OFFSET PAGTAB;PAGE INFORMATION TABLE +GTP2: INC BX + CMP AL,-1[BX] ;SEARCH FOR DESIRED BLOCK + JNE GTP3 ;NOT IT + CMP AX,CURBLK + JE GTP2A + MOV CL,RTIME1 + MOV [BX],CL ;FOUND IT, UPDATE ITS REFERENCE TIME + MOV CX,RTIME2 + MOV 1[BX],CX +GTP2A: DEC BX ;BACKUP TO BEGINNING OF TABLE ENTRY + MOV LPTAB,BX ;SAVE IT + SUB BX,OFFSET PAGTAB;CALCULATE ADDRESS OF PAGE + MOV CL,7 + SHL BX,CL + ADD BX,PAGES + JMP GTP4 ;AND RETURN PAGE POINTER +GTP3: ADD BX,3 ;SKIP REFERENCE TIME + CMP WORD PTR [BX],-1;END OF TABLE? + JNE GTP2 ;NO, CONTINUE SEARCH + CALL FINDPG ;YES, FIND A PAGE TO LOAD INTO + PUSH AX ;PAGE POINTER + MOV LPTAB,BX ;SAVE PAGE TABLE POINTER + MOV AX,LPAGE ;SAVE NEW BLOCK NUMBER + MOV [BX],AL + MOV CL,RTIME1 + MOV 1[BX],CL ;AND CURRENT REF TIME + MOV CX,RTIME2 + MOV 2[BX],CX + POP BX ;PAGE POINTER + CALL GETBLK ;GET THE BLOCK +GTP4: MOV AX,BX ;RETURN PAGE POINTER + MOV LPLOC,AX ;AND SAVE IT FOR LATER + POP BX ;RESTORES + POP CX + RET + + ;FIND A GOOD PAGE, RETURN PAGE POINTER IN AX & PAGTAB POINTER IN BX +FINDPG: PUSH CX + MOV BX,OFFSET PAGTAB + MOV CX,-1 ;FAKE BEST-CASE REFERENCE COUNT + MOV DX,CX + INC BX ;SKIP BLOCK NUMBER FOR NOW +FNP1: INC BX ;IS THIS REF TIME WORSE THAN CURRENT WORST? + CMP -1[BX],CL + JA FNP3 ;NO + JB FNP2 ;YES + CMP [BX],DX ;MAYBE, COMPARE LOW-ORDER WORDS, WORSE? + JAE FNP3 ;NO +FNP2: MOV CL,-1[BX] ;YES, SAVE ITS REF COUNT + MOV DX,[BX] + MOV AX,BX ;AND LOCATION (+2) +FNP3: ADD BX,3 ;SKIP SECOND WORD + CMP BYTE PTR [BX]-1,-1 ;LOOP UNTIL END OF TABLE + JNE FNP1 + INC CX ;WAS A PAGE REALLY FOUND? + JE FNP4 ;NO, GROSS BUG! + SUB AX,2 ;YES, CALCULATE CORE LOCATION OF PAGE + MOV BX,AX + SUB AX,OFFSET PAGTAB + MOV CL,7 + SHL AX,CL + ADD AX,PAGES + POP CX ;RESTORES + RET +FNP4: MOV AX,OFFSET FTL6 + JMP FATAL + + ;SYSTEM INITIALIZATION +SYSINI: MOV CL,CFOPEN ;OPEN CODE + MOV DX,OFFSET GAMFCB + PUSH ES + INT 224 ;OPEN FILE + POP ES + CMP AL,0FFH + JE SYSFTL + MOV DX,ES + MOV CL,CSDMAB ;SET DMA BASE + PUSH ES + INT 224 + POP ES + RET ;**THIS CHECKS # DRIVES, ETC. + +SYSFTL: MOV AX,OFFSET FTL9 + JMP FATAL + +CLRSCR: RET ;**THIS SHOULD CLEAR THE SCREEN + + ;READ A CHARACTER INTO AX, WAITING UNTIL ONE IS AVAILABLE, NO ECHO +M_CHRI: PUSH CX + PUSH DX + CMP CHRFLG,0 + JNZ MCHR1 + MOV CHRFLG,1 + ;**INITIALIZE RANDOM NUMBER STUFF +MCHR1: MOV CL,CCONIN + PUSH ES + INT 224 ;GET A CHARACTER + POP ES + SUB AH,AH + POP DX + POP CX + RET + + ;PRINT THE CHARACTER IN AL, FOREGROUND IN AH +M_TTYO: PUSH AX + PUSH BX ;SAVES + PUSH CX + PUSH DX + PUSH BP + PUSH AX + MOV CL,CCONIO + MOV DL,AL + PUSH ES + INT 224 ;CHUCK IT + POP ES + POP AX + CMP SCRFLG,0 + JZ MTYO1 + CALL PRTOUT +MTYO1: POP BP ;RESTORES + POP DX + POP CX + POP BX + POP AX + RET + + ;PRINT SPACES, WITHOUT MOVING CURSOR, NUMBER IN AL, ATTRIBUTE IN AH +M_SPC: RET + + ;PRINT A CARRIAGE RETURN/LINE FEED, WITH MORE MODE (ASSUMING SCREEN + ;BOTTOM) +M_CRLF: PUSH AX ;SAVES + PUSH BX + PUSH CX + PUSH DX + PUSH BP + INC MORLIN ;INCREMENT NUMBER OF LINES OUTPUT + MOV CL,CCONIO + MOV DL,13 + PUSH ES + INT 224 ;PRINT CRLF + POP ES + MOV CL,CCONIO + MOV DL,10 + PUSH ES + INT 224 + POP ES + MOV AL,SLPP + CMP MORLIN,AL ;FULL PAGE OUTPUT? + JL MCR1 ;NOT YET + MOV MORLIN,0 ;RESET COUNTER + MOV AX,OFFSET MORE + CALL M_PRNT + CALL M_CHRI ;READ A CHARACTER TO CONTINUE + MOV AX,OFFSET EMORE + CALL M_PRNT ;FLUSH THE MORE STUFF +MCR1: CMP SCRFLG,0 + JE MCR2 + CALL PRTCRL ;CRLF TO PRINTER +MCR2: POP BP ;RESTORES + POP DX + POP CX + POP BX + POP AX + RET + + ;OUTPUT STATUS LINE HERE + +M_SOUT: MOV BX,OFFSET SBLINE + CALL M_SPRT + MOV CL,09H + MOV DX,SLSTR + PUSH ES + INT 224 + POP ES + MOV BX,OFFSET SELINE + CALL M_SPRT + RET + +M_SPRT: PUSH ES + MOV CL,BYTE PTR [BX] + SUB CH,CH + CMP CL,0 + JE MSPRT1 +MSPLP: INC BX + MOV DL,BYTE PTR [BX] + PUSH CX + MOV CL,06H + PUSH BX + INT 224 + POP BX + POP CX + LOOP MSPLP +MSPRT1: POP ES + RET + +M_INIT: MOV BX,OFFSET STINIT + CALL M_SPRT + MOV BX,OFFSET SELINE + CALL M_SPRT + RET + + ;PRINT A STRING, POINTER (TO DATA SEGMENT) IN AX, WHITE FOREGROUND +M_PRNT: PUSH BX ;SAVE BX + MOV BX,AX ;STRING POINTER +MPR1: MOV AL,[BX] ;GET NEXT CHARACTER + CMP AL,0 ;END OF LINE, WITH CRLF? + JE MPR2 ;YES + CMP AL,80H ;END OF LINE, NO CRLF? + JE MPR3 ;YES + CALL M_TTYO ;PRINT CHARACTER + INC BX ;POINT TO NEXT CHARACTER + JMP MPR1 ;REPEAT +MPR2: CALL M_CRLF ;PRINT A CRLF +MPR3: POP BX ;RESTORE BX + RET + + ;GET TIME +M_TIME: RET + + ;GET A GAME FILE BLOCK, BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX +GETBLK: PUSH CX ;SAVE + MOV CX,1 ;CALL GTBLKS FOR 1 BLOCK ONLY + CALL GTBLKS + POP CX ;RESTORE + RET + +SRBLKS: MOV DSKFCB,OFFSET SAVFCB + JMP GTBKI + + ;GET A SERIES OF GAME FILE BLOCKS, + ;FIRST BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX # OF BLOCKS IN CX + +GTBLKS: MOV DSKDIR,0 ;READ MODE + MOV DSKFCB,OFFSET GAMFCB ;GAME MODE +GTBKI: PUSH BX + PUSH DX ;SAVES + PUSH BP + SHL AX,1 ;CONVERT TO 128-BYTE BLOCKS + SHL AX,1 + SHL CX,1 ;AND FOUR TIMES AS MANY OF THEM + SHL CX,1 + MOV GTBSTT,AX + MOV GTBCOR,BX + MOV GTBCNT,CX ;SAVE THESE +GTBLP: MOV CL,CSDMAO + MOV DX,BX + PUSH ES + INT 224 ;SET DMA ADDRESS + POP ES + MOV AX,GTBSTT ;GET STARTING BLOCK # + MOV BX,DSKFCB ;GET FCB + MOV 33[BX],AX ;SET RANDOM READ/WRITE SLOT + MOV CL,CRDRND + CMP DSKDIR,0 + JE GTBKIR + MOV CL,CWRRND +GTBKIR: MOV DX,DSKFCB + PUSH ES + INT 224 ;DO THE OPERATION + POP ES + CMP AL,0 + JNE GTB2 ;FATAL IF FAILS (FOR NOW) + DEC GTBCNT ;CHECK IF DONE + JZ GTBFIN + ADD GTBCOR,128 ;ADD TO CORE LOCATION + MOV BX,GTBCOR + INC GTBSTT ;AND BLOCK ADDRESS + JMP GTBLP + +GTBFIN: CLC +GTBOUT: POP BP + POP DX + POP BX + RET + +GTB2: CMP DSKFCB,OFFSET GAMFCB + JE GTB3 + STC + JMP GTBOUT + +GTB3: MOV AX,OFFSET FTL7 + JMP FATAL + +FATAL: PUSH AX + CALL M_CRLF + MOV AX,OFFSET FATHDR + CALL M_PRNT + POP AX + CALL M_PRNT +FINISH: MOV BX,OFFSET STRESET + CALL M_SPRT + MOV CL,CRESET + MOV DL,0 + INT 224 + + ORG 1500H + +; CONSTANTS FROM EVERYWHERE + +ZVERSN EQU 'A' ;ZIP VERSION NUMBER +ZMVERS EQU 3 ;Z-MACHINE VERSION NUMBER +LSTACK EQU 256 ;LENGTH OF USER STACK(MUST BE 1 PAGE FOR NOW) + +EOICHR EQU 15 ;CARRIAGE RETURN IS NORMAL END OF INPUT +EOLCHR EQU 10 ;LINE-FEED IS END-OF-LINE CHARACTER +PADCHR EQU 5 ;ZSTR PADDING CHARACTER + +CRESET EQU 0H ;SYSTEM RESET +CCONIN EQU 1H ;CONSOLE INPUT +CCONIO EQU 6H ;CONSOLE I/O +CRDLIN EQU 0AH ;BUFFERED CONSOLE READ +CFOPEN EQU 0FH ;FILE OPEN +CFCLOS EQU 10H ;FILE CLOSE +CFDELE EQU 13H ;FILE DELETE +CRDSEQ EQU 14H ;READ SEQUENTIAL +CFMAKE EQU 16H ;FILE MAKE +CSDMAO EQU 1AH ;SET DMA OFFSET +CRDRND EQU 21H ;READ RANDOM +CWRRND EQU 22H ;WRITE RANDOM +CSDMAB EQU 33H ;SET DMA BASE +CFNMEM EQU 35H ;FILE MEMORY BLOCK +CALMEM EQU 37H ;ALLOCATE MEMORY + +PVERS1 EQU 0 ;POSITION OF ZVERSION VERSION BYTE +PVERS2 EQU 1 ;ZVERSION MODE BYTE +PZRKID EQU 2 ;ZORKID +PENDLD EQU 4 ;ENDLOD +PSTART EQU 6 ;START +PVOCTB EQU 10Q ;VOCAB +POBJTB EQU 12Q ;OBJECT +PGLOTB EQU 14Q ;GLOBALS +PPURBT EQU 16Q ;PURBOT +PFLAGS EQU 20Q ;USER FLAG WORD +PSERNM EQU 22Q ;SERIAL NUMBER (6 BYTES) +PWRDTB EQU 30Q ;WORDS +PLENTH EQU 32Q ;LENGTH OF GAME +PCHKSM EQU 34Q ;CHECKSUM FOR GAME +LMOUTB EQU 80 ;MAX LENGTH OF OUTBUF, EXCLUDING TERMINAL 0 +LDOUTB EQU 80 ;DEFAULT LENGTH OF OUTBUF +LPAGES EQU 128 ;MAX NUMBER OF PAGES EXPECTED +LXBYTS EQU LSTACK+LMOUTB+(4*LPAGES)+2000Q ;LENGTH OF EXTRA BYTES NEEDED + +DSEG + ORG 100H +SCPL DB 79 ;CHARACTERS/LINE +SLPP DB 22 ;LINES/PAGE +SNAME RB 8 ;NAME OF THE GAME +SCLF DB 1 ;PRINT LF AFTER CR ON CONSOLE +SLLF DB 1 ;PRINT LF AFTER CR ON PRINTER +SINV DB 0 ;ADD-ON FOR INVERSE VIDEO +STINIT DB 23 ;TERMINAL INIT + DB 27,'[2J',27,'[2;24r',27,'[0m',27,'[01;00H' + ORG 12DH +STRESET DB 14 ;TERMINAL RESET + DB 27,'[1;24r',27,'[24;0H' + ORG 14DH +SBLINE DB 12 ;BEGIN STATUS LINE + DB 27,'[7m',27,'[01;00H' + ORG 16DH +SELINE DB 12 ;END STATUS LINE + DB 27,'[0m',27,'[24;00H' + ORG 18DH +SPINIT DB 0 ;PRINTER INIT + ORG 200H + + ;VARIABLE DEFINITIONS: + + ;SCRIPTING STUFF +SCRFLG DB 0 +PRNRDY DB ' * Printer not ready: Abort or Retry? ',80H + + ;GTBLKS +GAMFCB DB 0,'SEASTALKDAT' ;FCB FOR THE GAME FILE + RB 30 +SAVFCB DB 0,'SEASTALKSAV' ;FCB FOR SAVE/RESTORE + RB 30 +CNFFCB DB 0,'INTERLOGCNF' ;FCB FOR CONFIGURATION FILE + RB 30 +DSKFCB DW 0 ;CONTAINS FCB FOR DISK OPERATION +DSKDIR DB 0 ;0 FOR READ, 1 FOR WRITE +GTBCNT DW 0 ;REMAINING BLOCKS TO BE READ +GTBSTT DW 0 ;STARTING BLOCK +GTBCOR DW 0 ;STARTING CORE ADDRESS + ;OPRAND +RNDFLG DB 0 +RSEED1 DW 0 ;SEED FOR RANDOM NUMBERS +RSEED2 DW 0 ;SEED TWO +RTEMP DW 0 ;TEMP FOR RANDOM ROUTINES + ;READ +RDWSTR DW 0,0,0,0 ;WORD STRING BUFFER FOR ZWORD +RDBOS DW 0 ;BEGINNING OF STRING POINTER +RDEOS DW 0 ;END OF STRING POINTER +RDRET DW 0 ;RETURN TABLE POINTER +RDNWDS DB 0 ;NUMBER OF WORDS READ + ;PUTSTR +WRDOFF DW 0 ;OFFSET INTO WORD TABLE FOR CURRENT SET + ;PUTCHR +CHRPTR DW 0 ;POINTS TO NEXT CHARACTER POSITION +ENDBUF DW 0 ;POINTS JUST PAST END OF OUTPUT BUFFER (0) + ;GETNUM +STATUS DW 0 ;STATUS-LINE-REQUESTED FLAG + ;ZIPBGN +IRBRKS DB ' ',9,13,12,'.,?',0 ;INITIAL SET OF READ BREAK CHARS +MEMTOP DW 0 ;LAST AVAILABLE LOCATION +ZORKID DW 0 ;UNIQUE GAME & VERSION IDENTIFIER +ENDLOD DW 0 ;ENDLOD BLOCK NUMBER +VOCTAB DW 0 ;SAVE VOCABULARY TABLE POINTER +OBJTAB DW 0 ;OBJECT TABLE POINTER +GLOTAB DW 0 ;GLOBAL TABLE POINTER +WRDTAB DW 0 ;WORD TABLE POINTER +PURBOT DW 0 ;PURE CODE POINTER +ESIBKS DW 0 ;END OF SELF-INSERTING BREAK CHARACTERS +VWLEN DW 0 ;NUMBER OF BYTES IN A VOCABULARY WORD ENTRY +VWORDS DW 0 ;NUMBER OF WORD ENTRIES IN VOCABULARY +VOCBEG DW 0 ;BEGINNING OF ACTUAL VOCABULARY +OUTBUF RB 81 ;OUTPUT BUFFER +INBUF RB 150 ;INPUT BUFFER +RBRKS RB 32 ;STRING OF READ BREAK CHARACTERS +PAGTAB DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 255 ;END OF PAGE TABLE +PAGES DW 0 ;SWAPPING AREA +BUFPGS DW 0 +CHRFLG DB 0 + + ;RESTRT +ZLOCS DW 0 ;POINTER TO LOCALS +ZPC1 DW 0 ;ZPC BLOCK-POINTER +ZPC2 DW 0 ;ZPC BYTE-POINTER +ARGBLK RW 4 ;ARGUMENT BLOCK FOR EXTENDED OPERATIONS + ;NEWZPC +CURPAG DW 0 ;CURRENT PAGE (WHERE ZPC IS) POINTER +CURBLK DW 0 ;CURRENT BLOCK, USUALLY SAME AS ZPC1 +CURTAB DW 0 ;CURRENT PAGE TABLE POINTER +1 + ;GETPAG +RTIME1 DB 0 ;REFERENCE TIME, 1 1/2 WORDS USED +RTIME2 DW 0 +LPAGE DW 0 ;LAST REFERENCED PAGE NUMBER +LPLOC DW 0 ;AND ITS CORE LOCATION +LPTAB DW 0 ;AND ITS TABLE POINTER + + ;OPERATION TABLES: + ;ZERO ARGUMENT OPERATIONS +ZEROOP DW OPRTRU ;176 + DW OPRFAL ;177 + DW OPPRNI ;178 + DW OPPRNR ;179 + DW OPNOOP ;180 + DW OPSAVE ;181 + DW OPREST ;182 + DW OPRSTT ;183 + DW OPRSTA ;184 + DW OPFSTA ;185 + DW OPQUIT ;186 + DW OPCRLF ;187 + DW OPUSL ;188 + DW OPVERI ;189 + DW 0 ;190 + DW 0 ;191 + + ;ONE ARGUMENT OPERATIONS +ONEOP DW OPQZER ;128 + DW OPQNEX ;129 + DW OPQFIR ;130 + DW OPLOC ;131 + DW OPPTSI ;132 + DW OPINC ;133 + DW OPDEC ;134 + DW OPPRNB ;135 + DW 0 ;136 + DW OPREMO ;137 + DW OPPRND ;138 + DW OPRETU ;139 + DW OPJUMP ;140 + DW OPPRIN ;141 + DW OPVALU ;142 + DW OPBCOM ;143 + + ;TWO ARGUMENT AND EXTENDED ARGUMENT OPERATIONS +EXTOP DW 0 ;0 + DW OPQEQU ;1 + DW OPQLES ;2 + DW OPQGRT ;3 + DW OPQDLE ;4 + DW OPQIGR ;5 + DW OPQIN ;6 + DW OPBTST ;7 + DW OPBOR ;8 + DW OPBAND ;9 + DW OPQFSE ;10 + DW OPFSET ;11 + DW OPFCLE ;12 + DW OPSET ;13 + DW OPMOVE ;14 + DW OPGET ;15 + DW OPGETB ;16 + DW OPGETP ;17 + DW OPGTPT ;18 + DW OPNEXT ;19 + DW OPADD ;20 + DW OPSUB ;21 + DW OPMUL ;22 + DW OPDIV ;23 + DW OPMOD ;24 + DW 0 ;25 + DW 0 ;26 + DW 0 ;27 + DW 0 ;28 + DW 0 ;29 + DW 0 ;30 + DW 0 ;31 + DW OPCALL ;224 + DW OPPUT ;225 + DW OPPUTB ;226 + DW OPPUTP ;227 + DW OPREAD ;228 + DW OPPRNC ;229 + DW OPPRNN ;230 + DW OPRAND ;231 + DW OPPUSH ;232 + DW OPPOP ;233 + DW 0 ;234 + DW 0 ;235 + DW 0 ;236 + DW 0 ;237 + DW 0 ;238 + DW 0 ;239 + DW 0 ;240 + DW 0 ;241 + DW 0 ;242 + DW 0 ;243 + DW 0 ;244 + DW 0 ;245 + DW 0 ;246 + DW 0 ;247 + DW 0 ;248 + DW 0 ;249 + DW 0 ;250 + DW 0 ;251 + DW 0 ;252 + DW 0 ;253 + DW 0 ;254 + DW 0 ;255 + + ;.CRLF +MORE DB '**MORE** ',80H +EMORE DB 13,' ',13,80H +MORLIN DB 0 + + ;.GETTM +TIMBLK RB 8 ;WHERE TIME PARAMETERS GO + + ;VERIFY +INTVER DB 'DEC Rainbow 100 Interpreter Version C',0 + + ;SAVE/RESTORE STUFF +SAV1 DB 'File name (default is ',80H +SAV2 DB '): ',80H +SAV3 DB 'Replace game disk then hit RETURN to continue.',80H + + ;STRING DEFINITIONS + + ;RESTORE +ERR1 DB 'SAVE file not found',0 +ERR3 DB 'Bad file name syntax',0 +ERR4 DB 'No room in directory for SAVE file',0 +ERR5 DB 'No room on disk for SAVE file',0 +ERR6 DB 'Read of SAVE file failed',0 + + ;READ +ERR2 DB 'Too many words typed, flushing: ',80H + + ;OPNEXT/OPPUTP +FTL2 DB 'No such property',0 + ;ZIPBGN +FTL4 DB 'Wrong game or version',0 + ;NXTINS +FTL5 DB 'Illegal operation',0 + ;FINDPG +FTL6 DB 'No free pages',0 + ;GTBLKS +FTL7 DB 'Game file read error',0 + ;SYSINI +FTL9 DB 'Game file not found',0 + ;START +FTL10 DB 'Not enough memory',0 + ;Fatal error header +FATHDR DB 'Fatal error: ',80H + + ;STATUS LINE STUFF + +PMFLAG DB 0 ;AM/PM +TIMEMD DB 0 ;TIME MODE FLAG + +SLSTR DW 0 ;STATUS LINE HEADER STRING +SLTAB DW 0 ;STATUS LINE TABLE USED BY OPUSL + +SLSTAB DW SLS80 + DW SLS80T + DW SLT80 + DW SLT80T + +;RULE HERE: +; 1111111111222222222233333333334444444444555555555566666666667777777 +;1234567890123456789012345678901234567890123456789012345678901234567890123456 + +SLS80 DB ' Score: Moves: ' + +SLS80T DW -1 + DW OPPRND + DW 1 + DW 24 + DW -1 + DW OPPRNN + DW 57 + DW 60 + DW -1 + DW OPPRNN + DW 72 + DW 79 + +;RULE HERE: +; 1111111111222222222233333333334444444444555555555566666666667777777 +;1234567890123456789012345678901234567890123456789012345678901234567890123456 + +SLT80 DB ' Time: ' + +SLT80T DW -1 + DW OPPRND + DW 1 + DW 24 + DW -1 + DW OPPRNH + DW 63 + DW 65 + DW -1 + DW OPPRNM + DW 66 + DW 79 + + ;ZSTR CHARACTER CONVERSION VECTOR + +ZCHRS DB 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + DB ' 0123456789.,!?_#''' ;THIS SHOULD BE QUOTE + DB '"/\-:()' + +MBSTT DW 0 +MBLEN DW 0FFFFH +MBMOR DB 0 + +SSEG + ORG 100H + RW 100H +STK_TOP: +STKBOT RW LSTACK +ZSTK_TP: + DB 0 + END + \ No newline at end of file diff --git a/cpm86/read.me b/cpm86/read.me new file mode 100644 index 0000000..f443feb --- /dev/null +++ b/cpm86/read.me @@ -0,0 +1,12 @@ +******* Directory Update and Source File Archive Record ******* + + Date of Last Change Version Letter Who Made the Change + ------------------- -------------- ------------------- +1) 08/18/84 D Rick Lay +2) +3) +4) +5) +6) +7) +8) diff --git a/cpm86/tftp.asm b/cpm86/tftp.asm new file mode 100644 index 0000000..10ed704 --- /dev/null +++ b/cpm86/tftp.asm @@ -0,0 +1,177 @@ + + ORG 100H + +BDOS EQU 5H +FCB EQU 5CH +BUFF EQU 80H + +COMIN EQU 3 +COMOUT EQU 4 +PSTRNG EQU 9 +OPEN EQU 15 +CLOSE EQU 16 +DELETE EQU 19 +READS EQU 20 +WRITES EQU 21 +MAKEF EQU 22 + +LPDL EQU 256 + +CMDBLK EQU 0 +CMDACK EQU 2 +CMDWAK EQU 3 +CMDEOF EQU 4 +CMDNAK EQU 5 + +START: LXI SP,PDL+LPDL + LXI D,FCB + MVI C,DELETE + CALL BDOS + LXI D,FCB + MVI C,MAKEF + CALL BDOS + LXI D,BADOPN + INR A + JZ FINISH + +LOOP: CALL CMDGET + CPI CMDEOF + JZ EOF + CPI CMDBLK + JNZ LOOP + CALL GETWRD + SHLD COUNT + CALL GETWRD + LHLD COUNT + XCHG + LXI H,RBUF + +LOOP1: CALL GETBYT + MOV M,A + INX H + DCX D + MOV A,D + ORA E + JNZ LOOP1 + CALL GETWRD + PUSH H + LHLD COUNT + XCHG + LXI B,RBUF + LXI H,0 +LOOP2: PUSH D + LDAX B + MVI D,0 + MOV E,A + DAD D + POP D + INX B + DCX D + MOV A,D + ORA E + JNZ LOOP2 + POP D + MOV A,D + CMP H + JNZ RETRAN + MOV A,E + CMP L + JNZ RETRAN + CALL WRTDSK + MVI B,CMDACK + CALL SNDCMD + JMP LOOP + +RETRAN: LXI D,RETRNM + MVI C,PSTRNG + CALL BDOS + MVI B,CMDNAK + CALL SNDCMD + JMP LOOP + +CMDGET: CALL GETBYT + ANI 7FH + CPI 7EH + JNZ CMDGET + JMP GETBYT + +GETWRD: CALL GETBYT + MOV H,A + CALL GETBYT + MOV L,A + RET + +GETBYT: MVI C,COMIN + PUSH B + PUSH D + PUSH H + CALL BDOS + POP H + POP D + POP B + RET + +SNDCMD: MVI C,7EH + PUSH B + CALL SNDBYT + POP B + MOV C,B +SNDBYT: MOV E,C + MVI C,COMOUT + PUSH D + PUSH H + CALL BDOS + POP H + POP D + RET + +EOF: LXI D,FCB + MVI C,CLOSE + CALL BDOS + MVI B,CMDACK + CALL SNDCMD + LXI D,GOOD +FINISH: MVI C,PSTRNG + CALL BDOS + JMP 0 + +WRTDSK: LXI D,RBUF + LXI H,BUFF + MVI C,128 + CALL MOVIT + LXI D,FCB + MVI C,WRITES + CALL BDOS + LXI D,BADWRT + ORA A + JNZ FINISH + LXI D,RBUF+128 + LXI H,BUFF + MVI C,128 + CALL MOVIT + LXI D,FCB + MVI C,WRITES + CALL BDOS + LXI D,BADWRT + ORA A + JNZ FINISH + RET + +MOVIT: LDAX D + MOV M,A + INX D + INX H + DCR C + JNZ MOVIT + RET + +BADWRT: DB 0DH,0AH,'BAD WRITE$' +RETRNM: DB 0DH,0AH,'RETRANSMITTING$' +BADOPN: DB 0DH,0AH,'BAD OPEN$' +GOOD: DB 0DH,0AH,'COMPLETED$' + +PDL: DS LPDL +COUNT: DW 0 +RBUF: DS 256 + + END START diff --git a/cpm86/zip.a86 b/cpm86/zip.a86 new file mode 100644 index 0000000..c394d9c --- /dev/null +++ b/cpm86/zip.a86 @@ -0,0 +1,2799 @@ + TITLE 'ZIP: CPM/86 VERSION' + + ; + ; MODIFIED 6/18/84 BY DAN HORN + ; 1) Changed Verify Version Letter + ; 2) Increased size of save for Opsave + ; Changes noted with (***) + ; + ; MODIFIED 8/18/84 BY RICK LAY + ; 1) Changed Verify Version Letter + ; 2) Save and Restore operations + ; were heavily modified. + ; + +CSEG + +START: MOV AX,.15H + MOV SS,AX + MOV SP,OFFSET STK_TOP + MOV DI,OFFSET ZSTK_TP + MOV CL,CFOPEN + MOV DX,OFFSET CNFFCB + INT 224 ;OPEN CONFIGURATION FILE + CMP AL,0FFH + JE ST1M ;NONE FOUND, USE DEFAULT + MOV CL,CRDSEQ + MOV DX,OFFSET CNFFCB + MOV AX,DS + MOV ES,AX + PUSH ES + INT 224 ;READ FIRST BLOCK + POP ES + CMP AL,0 + JNE ST1M + MOV CX,80H + MOV SI,80H + MOV DI,100H +REP MOVS AL,AL ;TRANSFER STUFF FROM BUFFER TO 100H + MOV CL,CRDSEQ + MOV DX,OFFSET CNFFCB + PUSH ES + INT 224 ;READ SECOND BLOCK + POP ES + CMP AL,0 + JNE ST1M + MOV CX,80H + MOV SI,80H + MOV DI,180H +REP MOVS AL,AL ;TRANSFER STUFF FROM BUFFER TO 180H + MOV CL,CFCLOS + MOV DX,OFFSET CNFFCB + PUSH ES + INT 224 ;CLOSE CONFIG. FILE + POP ES +ST1M: MOV CL,CFNMEM + MOV DX,OFFSET MBSTT + INT 224 ;GET SOME MEMORY, PLEASE + CMP AL,0FFH + JE MERR1 + MOV AX,MBLEN ;GET LENGTH + CMP AX,800H + JB MERR1 ;DIE IF LESS THAN 32K (JL LOST ON 100+) + CMP AX,1000H + JBE STARTM + MOV MBLEN,1000H ;TAKE 64K AT MOST +STARTM: MOV CL,CALMEM + MOV DX,OFFSET MBSTT + INT 224 ;ALLOCATE THE BLOCK + CMP AL,0FFH + JE MERR1 ;SHOULDN'T EVER HAPPEN + MOV AX,MBSTT ;STARTING PARAGRAPH + MOV ES,AX ;AND THAT BECOMES OUR ES + JMP ZIPBGN ;JUMP TO BEGINNING OF ZIP CODE + +MERR1: MOV AX,OFFSET FTL10 + JMP FATAL + +FEEP: MOV AX,7 + CALL M_TTYO ;BELL + RET + +OPVERI: MOV AX,OFFSET INTVER + CALL M_PRNT + MOV AX,ES:.PLENTH ;GET LENGTH OF FILE + PUSH SI + PUSH DI + PUSH ENDLOD + XCHG AH,AL + CALL BSPLIT + MOV SI,AX + MOV DI,BX ;SAVE PLENTH ZPC1/ZPC2 + MOV AX,0 ;START AT BYTE 64 + MOV BX,64 + MOV DX,0 ;WILL HAVE CHECKSUM + MOV ENDLOD,0 ;FAKE IT TO BE ZERO +OPVR1: PUSH SI + PUSH DI + PUSH DX + CALL GETBYT + POP DX + POP DI + POP SI + ADD DX,CX ;ADD INTO CHECKSUM + CMP AX,SI + JNE OPVR1 + CMP BX,DI + JNE OPVR1 + MOV AX,ES:.PCHKSM ;GET CHECKSUM + XCHG AH,AL + POP ENDLOD ;RESTORE FROBS + POP DI + POP SI + CMP AX,DX ;COMPARE WITH GOOD CHECKSUM + JNE OPVR2 + JMP PTRUE +OPVR2: JMP PFALSE +; +; RESTORE +; +OPREST: MOV DSKDIR,0 ;INDICATE RESTORE (READ) + JMP OSV0 +; +; SAVE +; +OPSAVE: MOV DSKDIR,1 ;INDICATE SAVE (WRITE) +; +; We have to perform a disk reset function NOW in case +; the user wants to use DRIVE A. +; +OSV0: MOV CL,25H ;SELECT BDOS RESET DRIVE FUNCTION + MOV DX,1 ;DRIVE A + PUSH ES + INT 224 ;LOG OUT THE DRIVE + POP ES + MOV AX,OFFSET SAV0 + CALL M_PRNT ;PRINT 'Insert save disk then enter filename' + MOV AX,OFFSET SAV1 + CALL M_PRNT ;PRINT 'File name (default is ' + MOV AL,SAVFCB + CMP AL,0 + JE OSVD1 + ADD AL,'A'-1 ;MAKE THIS AN ASCII THING + CALL M_TTYO ;AND OUTPUT IT + MOV AL,':' + CALL M_TTYO +OSVD1: MOV CX,8 ;MAX. FIRST FILE NAME + MOV BX,OFFSET SAVFCB +OSVD3: INC BX ;POINT TO START OF SAVFCB + MOV AL,BYTE PTR [BX] + CMP AL,20H ;CHECK FOR SPACE + JE OSVD2 + CALL M_TTYO ;OUTPUT IT + LOOP OSVD3 +OSVD2: MOV AL,'.' + CALL M_TTYO ;AND THE PERIOD + MOV CX,3 ;MAX. EXTENSION + MOV BX,OFFSET SAVFCB + ADD BL,8 ;POINT TO EXTENSION +OSVD4: INC BX + MOV AL,BYTE PTR [BX] + CALL M_TTYO + LOOP OSVD4 + MOV AX,OFFSET SAV2 + CALL M_PRNT ;PRINT THE ': ' PROMPT + MOV BX,OFFSET INBUF + MOV AL,14 ;SAY MAX. LENGTH IS 14 (X:XXXXXXXX.XXX) + MOV BYTE PTR [BX],AL + MOV DX,BX + MOV CL,CRDLIN + PUSH ES + INT 224 ;BUFFERED CONSOLE READ + POP ES + MOV AL,10 + CALL M_TTYO ;ECHO A LF (CHOMPER!) + MOV BX,OFFSET INBUF + MOV CL,BYTE PTR 1 [BX] + ADD BX,2 ;GO PAST THE HEADER + SUB CH,CH ;# CHARACTERS READ + CMP CL,0 + JE OSVKL ;USE DEFAULT IF ZERO + CMP CL,2 ;CHECK FOR <2 CHARACTERS + JL OSVP2 + MOV AL,BYTE PTR 1 [BX] + CMP AL,':' ;CHECK FOR DEVICE NAME + JNE OSVP2 + MOV AL,BYTE PTR [BX] + CMP AL,'a' + JL OSVXC + CMP AL,'z' + JG OSVXC + SUB AL,32 +OSVXC: SUB AL,'A'-1 + JGE OSVP0 + MOV AX,OFFSET ERR3 + JMP OSVPER ;ILLEGAL IF <0 +OSVKL: JMP OSVPN +OSVP0: CMP AL,16 + JLE OSVP1 + MOV AX,OFFSET ERR3 + JMP OSVPER ;OR >16 +OSVP1: MOV SAVFCB,AL ;SAVE IT AWAY + ADD BX,2 ;AND FLUSH IT + SUB CL,2 ;FLUSH 'EM FROM CL TOO + JE OSVPN ;THAT'S ALL FOLKS.... +OSVP2: MOV BP,OFFSET SAVFCB + MOV DL,8 ;MAX. FIRST FILE NAME +OSVP3: INC BP ;POINT TO FIRST FILE NAME STUFF + MOV AL,BYTE PTR [BX];GET THE NEXT CHARACTER + CMP CL,0 + JG OSVP3A + MOV AL,20H ;IF WE'RE OUT OF INPUT, USE SPACE +OSVP3A: CMP AL,'.' + JE OSVP4 + CMP AL,'a' + JL OSVCP1 + CMP AL,'z' + JG OSVCP1 + SUB AL,32 ;UPPERCASE, IF NECESSARY +OSVCP1: MOV DS:BYTE PTR [BP],AL ;MOVE CHARACTER INTO FCB + INC BX ;INCREMENT SOURCE POINTER + DEC CL ;DECREMENT OUTER LOOP COUNTER + DEC DL ;DECREMENT INNER LOOP COUNTER + JNZ OSVP3 + CMP CL,0 + JLE OSVPN + MOV AL,BYTE PTR [BX] + CMP AL,'.' + JE OSVP4 + MOV AX,OFFSET ERR3 + JMP OSVPER ;BETTER BE A PERIOD +OSVP4: INC BX + MOV AL,20H + CMP DL,0 ;LOOP PADDING WITH SPACES + JE OSVP6 +OSVP5: MOV DS:BYTE PTR [BP],AL + INC BP + DEC DL + JNZ OSVP5 + CMP CL,4 ;SHOULD BE FOUR LEFT '.XXX' + JE OSVP6A + MOV AX,OFFSET ERR3 + JMP OSVPER +OSVP6: INC BP ;INCREMENT DESTINATION IF NOT PADDED WITH 20H +OSVP6A: DEC CL ;WE ONLY WANT THE 3 EXTENSION CHARACTERS +OSVP6B: MOV AL,BYTE PTR [BX] + MOV DS:BYTE PTR [BP],AL + INC BP + INC BX + LOOP OSVP6B + +OSVPN: MOV BX,OFFSET SAVFCB + ADD BX,12 ;GO PAST THE FILE NAMES + MOV CX,30 + MOV AL,0 ;FILL WITH ZEROS +OSVPNZ: MOV [BX],AL + INC BX + LOOP OSVPNZ + +; OPEN THE FILE IF OP RESTORE + CMP DSKDIR,1 ;CHECK FOR SAVE OR RESTORE + JE OSVOPW ;OPEN FOR WRITE + MOV DX,OFFSET SAVFCB + MOV CL,CFOPEN ;FILE OPEN + PUSH ES + INT 224 + POP ES + CMP AL,0FFH + JNE OSVPS + MOV AX,OFFSET ERR1 + JMP OSVPER ;FILE NOT FOUND +OSVOPW: MOV DX,OFFSET SAVFCB + MOV CL,CFDELE + PUSH ES + INT 224 + MOV DX,OFFSET SAVFCB + MOV CL,CFMAKE + INT 224 + POP ES + CMP AL,0FFH + JNE OSVPS + MOV AX,OFFSET ERR4 + JMP OSVPER + +OSVPS: XCHG DI,SP + PUSH ZPC1 + PUSH ZPC2 + PUSH ZLOCS + PUSH ZORKID + MOV STKBOT,SP ;SAVE THE WORLD + MOV SP,DI + MOV CL,5 + SHL AX,CL ;CHANGE TO BLOCK + PUSH AX ;SAVE STARTING BLOCK # + PUSH ES ;SAVE ES + MOV DX,SS + MOV ES,DX ;FAKE ES TO BE STACK SEGMENT + MOV BX,OFFSET STKBOT + MOV CX,1 ; *** WRITE OUT CX*4 (128 BYTES BLOCKS) + CALL SRBLKS ;READ/WRITE STACK + PUSHF + MOV DI,SP ;SAVE SP + MOV SP,STKBOT ;RETRIEVE SAVED USER STACK POINTER + POP AX + CMP AX,ZORKID ;CHECK GAME VERSIONS + JE OSVT0 + MOV AX,OFFSET FTL4 + JMP FATAL +OSVT0: POP ZLOCS + POP ZPC2 + POP ZPC1 + XCHG DI,SP + POPF + POP ES + POP AX + JC OSV4Y ;DIE HERE IF FIRST READ/WRITE FAILED + MOV AX,1 ; *** NEXT BLOCK STARTS + SUB BX,BX ;START AT ES:0 + MOV CX,PURBOT ;NUMBER OF PURE BLOCKS + CALL SRBLKS +OSV4Y: PUSHF ;SAVE FLAGS FROM CALL + MOV CL,CFCLOS + MOV DX,OFFSET SAVFCB + PUSH ES + INT 224 ;CLOSE FILE + POP ES +OSVCC: MOV AL,SAVFCB ;AL=DRIVE NO. + CMP AL,0 ;DRIVE A? + JNE OSV2C ;....NO +OSV1C: MOV CL,25H ;....YES. SELECT BDOS RESET DRIVE FUNCTION + MOV DX,1 ;DRIVE A + PUSH ES + INT 224 ;LOG OUT THE DRIVE + POP ES + MOV AX,OFFSET SAV3 + CALL M_PRNT ;PRINT 'Insert game disk then hit RETURN' +; to continue.' + CALL M_CHRI ;WAIT FOR KEYPRESS + CALL M_CRLF ;PRINT +OSV2C: MOV CL,CFOPEN ;OPEN CODE + MOV DX,OFFSET GAMFCB + PUSH ES + INT 224 ;OPEN THE GAME FILE + POP ES + CMP AL,0FFH + JE OSV1C ;LOOP UNTIL THEY DO IT +OSV3C: CALL NEWZPC ;PAGE MAY HAVE CHANGED, LOSER! + POPF ;GET FLAGS BACK + JC OSV4 + MOV AL,SCRFLG ;GET CURRENT SCRIPT STATE + XCHG AH,AL + MOV ES:.PFLAGS,AX ;AND MAKE RESTORED FLAGS REFLECT IT + JMP PTRUE +OSV4: MOV AX,OFFSET ERR5 + CMP DSKDIR,1 + JE OSVPER + MOV AX,OFFSET ERR6 ;DISTINGUISH READ/WRITE ERRORS +OSVPER: CALL M_PRNT + MOV AL,SCRFLG ;GET CURRENT SCRIPT STATE + XCHG AH,AL + MOV ES:.PFLAGS,AX ;AND MAKE RESTORED FLAGS REFLECT IT + JMP PFALSE + +OPRSTT: MOV BP,CHRPTR + MOV DS:BYTE PTR [BP],0 ;FORCE OUT THE BUFFER + MOV AX,OFFSET OUTBUF + CALL M_PRNT + JMP RESTRT ;JUMP TO RESTART ADDRESS + +OPQUIT: JMP FINISH + +OPUSL: PUSH DI + PUSH CHRPTR + MOV BX,SLSTR ;FAKE STATUS LINE STRING AS OUTPUT BUFFER + MOV CHRPTR,BX + MOV AX,16 ;FIRST GLOBAL + MOV DI,SLTAB + MOV CX,3 ;# OF THINGS TO PRINT +USLLP: PUSH AX + CALL GETVAR ;GET THE ROOM OBJECT + MOV DX,4[DI] ;THE STARTING CURSOR POSITION + CALL USLSET ;SET CURSOR POSITION HERE + PUSH CX + PUSH DI + CALL WORD PTR 2[DI] ;PRINT THE THING + POP DI + MOV DX,6[DI] + CALL USLSPC ;SPACE OVER TO HERE +USLN: ADD DI,8 ;POINT TO NEXT THING TO PRINT + POP CX +USL1: POP AX + INC AX ;POINT TO NEXT GLOBAL + LOOP USLLP + MOV AX,'$' + CALL PUTCHR ;PUT IN A STOP SIGNAL + CALL M_SOUT ;OUTPUT STATUS LINE + POP CHRPTR + POP DI + RET + +USLSET: MOV BX,SLSTR + MOV CHRPTR,BX + ADD CHRPTR,DX + RET + +USLSPC: MOV CX,CHRPTR + SUB CX,SLSTR ;THIS IS WHERE WE ARE + SUB DX,CX ;THIS IS WHERE WE WANT TO BE + MOV CX,DX ;CX HAS COUNT OF SPACES TO PUT IN + JLE USLSP1 +USLSPL: MOV AX,20H + CALL PUTCHR ;OUTPUT A SPACE INTO BUFFER + LOOP USLSPL +USLSP1: RET + + + ;ADD +OPADD: ADD AX,BX ;ADD OPR1 AND OPR2 + JMP PUTVAL ;RETURN THE VALUE + + ;SUB +OPSUB: SUB AX,BX ;SUBTRACT OPR2 FROM OPR1 + JMP PUTVAL ;RETURN THE VALUE + + ;MULTIPLY AX BY BX +OPMUL: IMUL BX ;MULTIPLY OPR1 BY OPR2,IGNORING OVERFLOW(DX) + JMP PUTVAL ;RETURN THE VALUE + + ;DIVIDE AX BY BX +OPDIV: CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + JMP PUTVAL ;RETURN THE VALUE + + ;MOD +OPMOD: CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + MOV AX,DX ;WE WANT REMAINDER + JMP PUTVAL ;RETURN THE VALUE + + ;RANDOM +OPRAND: MOV BX,AX ;SAVE OPR + MOV AX,RSEED ;GET THE SEED + MOV CX,257 ;TRANSFORM IT + MUL CX + ADD AX,11 + MOV RSEED,AX ;SAVE NEW VALUE + SUB DX,DX ;TRIM IT TO PROPER SIZE + AND AX,0EFFFH ;CLEAR BIT TO PREVENT POSSIBLE OVERFLOW + DIV BX + MOV AX,DX + INC AX ;MUST BE BETWEEN 1 AND N, INCLUSIVE + JMP PUTVAL ;SIMPLY RETURN + + ;LESS? +OPQLES: CMP AX,BX ;IS OPR1 LESS THAN OPR2? + JL JPT ;YES, PREDICATE TRUE +JPF: JMP PFALSE ;NO, PREDICATE FALSE +JPT: JMP PTRUE + + ;GRTR? +OPQGRT: CMP AX,BX ;IS OPR1 GREATER THAN OPR2? + JG JPT ;YES, PREDICATE TRUE + JMP JPF ;NO, PREDICATE FALSE + + ;BTST +OPBTST: NOT AX ;TURN OFF BITS IN OPR2 THAT ARE ON IN OPR1 + AND BX,AX + JE JPT ;SUCCESS IF OPR2 COMPLETELY CLEARED + JMP JPF + + ;BOR +OPBOR: OR AX,BX ;LOGICAL OR + JMP PUTVAL ;RETURN THE VALUE + + ;BCOM +OPBCOM: NOT AX ;LOGICAL COMPLEMENT + JMP PUTVAL ;RETURN THE VALUE + + ;BAND +OPBAND: AND AX,BX ;LOGICAL AND + JMP PUTVAL ;RETURN THE VALUE + + ;EQUAL? +OPQEQU: NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV BX,ARGBLK ;GET OPR1 + CMP BX,ARGBLK+2 ;IS OPR1 EQUAL TO OPR2? + JE OQE1 ;YES + CMP AX,3 ;NO, IS THERE A THIRD OPERAND? + JL OQE2 ;NO + CMP BX,ARGBLK+4 ;YES, IS IT EQUAL TO OPR1? + JE OQE1 ;YES + CMP AX,4 ;NO, IS THERE A FOURTH? + JL OQE2 ;NO + CMP BX,ARGBLK+6 ;YES, IS IT EQUAL TO OPR1? + JNE OQE2 ;NO +OQE1: JMP PTRUE ;PREDICATE TRUE IF EQUAL +OQE2: JMP PFALSE ;PREDICATE FALSE IF NOT + + ;ZERO? +OPQZER: CMP AX,0 ;IS OPR ZERO? + JNE OQZ1 ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQZ1: JMP PFALSE + + ;MOVE (OBJ1 INTO OBJ2) +OPMOVE: PUSH AX ;PROTECT OPRS FROM REMOVE CALL + PUSH BX + CALL OPREMO ;REMOVE OBJ1 FROM WHEREVER IT IS + POP DX ;OBJ2 + MOV AX,DX + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + POP CX ;OBJ1 + MOV AX,CX + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV ES:4[BP],DL ;PUT OBJ2 INTO OBJ1'S LOC SLOT + MOV DH,ES:6[BX] ;GET CONTENTS OF OBJ2'S FIRST SLOT + MOV ES:6[BX],CL ;MAKE OBJ1 FIRST CONTENT OF OBJ2 + CMP DH,0 ;WERE THERE ANY OTHER CONTENTS? + JE OMV1 ;NO + MOV ES:5[BP],DH ;YES, CHAIN ONTO OBJ1'S SIBLING SLOT +OMV1: RET + + ;REMOVE (OBJ FROM ITS PARENT) +OPREMO: MOV CX,AX ;SAVE OBJ FOR LATER + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + MOV CH,ES:4[BX] ;GET ITS PARENT + CMP CH,0 ;DOES IT HAVE A PARENT? + JE ORM3 ;IF NOT, WE'RE DONE + MOV AL,CH ;PARENT + CALL OBJLOC ;FIND PARENT'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:6[BP] ;GET PARENT'S FIRST CONTENT + CMP DL,CL ;IS IT OBJ? + JNE ORM1 ;NO + MOV AL,ES:5[BX] + MOV ES:6[BP],AL ;YES, CHANGE SLOT TO OBJ'S SIBLING + JMP ORM2 ;AND RETURN +ORM1: MOV AL,DL ;CURRENT SIBLING + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:5[BP] ;GET NEXT SIBLING IN CHAIN + CMP DL,CL ;IS IT OBJ? + JNE ORM1 ;NO, CONTINUE LOOP + MOV AL,ES:5[BX] + MOV ES:5[BP],AL ;YES, CHANGE IT TO OBJ'S SIBLING +ORM2: MOV ES:BYTE PTR 4[BX],0 ;OBJ NOW HAS NO PARENT + MOV ES:BYTE PTR 5[BX],0 ;OR SIBLING +ORM3: RET + + ;FSET? (IS FLAG SET IN OBJ?) +OPQFSE: CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OQF1 ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OQF1: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + MOV AX,ES:[BX] ;GET THE FLAG WORD + XCHG AH,AL + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + TEST AX,DX ;IS THIS BIT SET IN FLAG WORD? + JE OQF2 ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQF2: JMP PFALSE + + ;FSET (SET A FLAG IN OBJ) +OPFSET: CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFS1 ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFS1: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + MOV AX,ES:[BX] ;GET THE FLAG WORD + XCHG AH,AL + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + OR AX,DX ;SET THIS BIT IN FLAG WORD + XCHG AH,AL + MOV ES:[BX],AX ;STORE THE NEW FLAG WORD + RET + + ;FCLEAR (CLEAR A FLAG IN OBJ) +OPFCLE: CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFC1 ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFC1: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + MOV AX,ES:[BX] ;GET THE FLAG WORD + XCHG AH,AL + MOV DX,7FFFH ;SHIFT A BIT TO PROPER POSITION + ROR DX,CL + AND AX,DX ;CLEAR THIS BIT IN FLAG WORD + XCHG AH,AL ;STORE THE NEW FLAG WORD + MOV ES:[BX],AX + RET + + ;LOC (RETURN CONTAINER OF OBJ) +OPLOC: CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:4[BX] ;GET LOC SLOT + JMP BYTVAL ;RETURN THE BYTE VALUE + + ;FIRST? (RETURN FIRST SLOT OF OBJ, FAIL IF NONE) +OPQFIR: CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:6[BX] ;GET FIRST SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE +JPT1: JMP PTRUE ;NO, PREDICATE TRUE +JPF1: JMP PFALSE + + ;NEXT? (RETURN THE NEXT (SIBLING) SLOT OF OBJ, FAIL IF NONE) +OPQNEX: CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:5[BX] ;GET SIBLING SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE + JMP JPT1 ;NO, PREDICATE TRUE + + ;IN? (IS OBJ1 CONTAINED IN OBJ2?) +OPQIN: CALL OBJLOC ;FIND OBJ1'S LOCATION + XCHG AX,BX ;MOVE TO BASE + CMP ES:4[BX],AL ;IS OBJ1'S PARENT OBJ2? + JE JPT1 ;YES, PREDICATE TRUE + JMP JPF1 ;NO, PREDICATE FALSE + + ;GETP (GET SPECIFIED PROPERTY OF OBJ, DEFAULT IF NONE) +OPGETP: MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV BX,ES:7[BP] ;GET LOCATION OF ITS PROPERTY TABLE + XCHG BH,BL + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGP2 ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGP1: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGP2: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,31 ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGP1 ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JL OGP3 ;IF LESS, NO SUCH PROPERTY HERE + MOV AL,ES:[BX] ;GOT IT, NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,224 ;GET LENGTH BITS + MOV CL,5 ;PROPERTY SIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + JNE OGP5 ;NO + MOV AL,ES:[BX] ;GET THE BYTE + JMP BYTVAL ;AND RETURN IT +OGP3: DEC DX ;POINT INTO DEFAULT PROPERTY TABLE + SHL DX,1 + MOV BX,DX +OGP4: ADD BX,OBJTAB ;GET THE WORD +OGP5: MOV AX,ES:[BX] + XCHG AH,AL + JMP PUTVAL ;AND RETURN IT + + ;PUTP (CHANGE VALUE OF A PROPERTY, ERROR IF BAD NUMBER) +OPPUTP: PUSH CX ;SAVE NEW VALUE + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV BX,ES:7[BP] ;GET LOCATION OF ITS PROPERTY TABLE + XCHG BH,BL + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OPP2 ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OPP1: CALL NXTPRP ;POINT TO NEXT PROPERTY +OPP2: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,31 ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE OPP3 ;IF EQUAL, GOT IT + JG OPP1 ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + MOV AX,OFFSET FTL2 + JMP FATAL +OPP3: MOV AL,ES:[BX] ;NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,224 ;GET LENGTH BITS + MOV CL,5 ;PROPSIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + POP AX ;RESTORE NEW VALUE + JNE OPP4 ;ZERO MEANS BYTE VALUE + MOV ES:[BX],AL ;STORE THE NEW BYTE + RET ;AND RETURN +OPP4: XCHG AH,AL + MOV ES:[BX],AX ;STORE THE NEW WORD VALUE + RET + + ;NEXTP (RETURN NUMBER OF NEXT PROP FOLLOWING GIVEN PROB IN OBJ) +OPNEXT: MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV BX,ES:7[BP] ;GET ITS LOCATION + XCHG BH,BL + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + CMP DX,0 ;WERE WE GIVEN ZERO AS PROP? + JE ONX4 ;YES, GO RETURN FIRST PROPERTY NUMBER + JMP ONX2 ;NO, SKIP NEXT LINE FIRST TIME THROUGH LOOP +ONX1: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX2: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,31 ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE ONX3 ;IF EQUAL, GOT IT + JG ONX1 ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + MOV AX,OFFSET FTL2 + JMP FATAL +ONX3: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX4: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,31 ;EXTRACT PROPERTY NUMBER + JMP PUTVAL ;AND RETURN IT + + ;GET (GET THE ITEM'TH WORD FROM TABLE) +OPGET: SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETWRD ;GET THE WORD + MOV AX,CX + JMP PUTVAL ;AND RETURN IT + + ;GETB (GET THE ITEM'TH BYTE FROM TABLE) +OPGETB: ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETBYT ;GET THE BYTE + MOV AX,CX + JMP BYTVAL ;AND RETURN IT + + ;PUT (REPLACE THE ITEM'TH WORD IN TABLE) +OPPUT: SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD BX,AX ;INDEX INTO TABLE + XCHG CH,CL + MOV ES:[BX],CX ;STORE THE WORD + RET + + ;PUTB (REPLACE ITEM'TH BYTE IN TABLE) +OPPUTB: ADD BX,AX ;INDEX INTO TABLE + MOV ES:[BX],CL ;STORE BYTE + RET + + ;GETPT (GET POINTER TO PROPERTY TABLE FOR GIVEN PROP) +OPGTPT: MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV BX,ES:7[BP] ;GET LOCATION OF ITS PROPERTY TABLE + XCHG BH,BL + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGT2 ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGT1: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGT2: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,31 ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGT1 ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JE OGT3 ;FOUND THE PROPERTY + SUB AX,AX ;RETURN ZERO FOR NO SUCH PROPERTY + JMP OGT4 +OGT3: INC BX ;POINT TO PROPERTY VALUE + MOV AX,BX ;AND RETURN IT +OGT4: JMP PUTVAL + + ;PTSIZE (RETURN SIZE OF PROPERTY TABLE) +OPPTSI: MOV BX,AX ;TABLE POINTER + MOV AL,ES:[BX]-1 ;GET PROPERTY INDENTIFIER + AND AL,224 ;EXTRACT LENGTH BITS + SUB AH,AH + MOV CL,5 ;PROPSIZE + SHR AX,CL + INC AX ;ADJUST TO ACTUAL LENGTH + JMP PUTVAL ;RETURN IT + + ;VALUE (GET VALUE OF VAR) +OPVALU: CALL GETVAR ;GET THE VALUE + JMP PUTVAL ;AND RETURN IT + + ;SET (VAR TO VALUE) +OPSET: JMP PUTVAR ;STORE THE VALUE + + ;PUSH (A VALUE ONTO THE STACK) +OPPUSH: XCHG SP,DI + PUSH AX + XCHG SP,DI + RET + + ;POP (A VALUE OFF THE STACK INTO VAR) +OPPOP: XCHG SP,DI + POP BX + XCHG SP,DI + JMP PUTVAR ;AND STORE IT + + ;INC (INCREMENT VAR) +OPINC: MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT +OPINC1: MOV BX,AX ;VALUE + MOV AX,CX ;VARIABLE + JMP PUTVAR ;STORE NEW VALUE + + ;DEC (DECREMENT VAR) +OPDEC: MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + JMP OPINC1 ;STORE NEW VALUE + + ;IGRTR? (INCREMENT VAR & TEST IF GREATER THAN VAL) +OPQIGR: PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE GREATER THAN VAL? + JLE OPQIG1 ;NO +OPQIG0: INC CX ;YES, CHANGE FLAG TO TRUE +OPQIG1: MOV BX,AX ;VALUE + POP AX ;RESTORE VARIABLE + CALL PUTVAR ;STORE NEW VALUE + CMP CX,0 ;TEST FLAG + JE OQI1 ;FALSE, PREDICATE FALSE + JMP PTRUE ;ELSE, PREDICATE TRUE +OQI1: JMP PFALSE + + ;DLESS? (DECREMENT VAR & TEST IF LESS THAN VAL) +OPQDLE: PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE LESS THAN VAL? + JGE OPQIG1 ;NO, PREDICATE FALSE + JMP OPQIG0 ;YES, PREDICATE TRUE + +GETLIN: CMP RNDFLG,0 + JNE GETLNN + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH ES +RNDLP: MOV DI,4 + INT 40 + CMP CL,0 + JNE RNDL1 + INC RSEED + JMP RNDLP +RNDL1: MOV RNDFLG,1 + POP ES + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX +GETLNN: PUSH BX + MOV AL,SCRFLG + PUSH AX + MOV SCRFLG,0 ;DEFEAT SCRIPTING DURING INPUT + PUSH SI + MOV CL,ES:[SI] ;HERE'S WHERE LENGTH IS + MOV BX,OFFSET INBUF ;HERE'S THE BDOS INPUT BUFFER + MOV BYTE PTR [BX],CL;PUT MAX LENGTH THERE + MOV DX,BX + MOV CL,CRDLIN ;CONSOLE BUFFERED READ + PUSH ES + INT 224 ;READ A LINE + MOV CL,CCONIO + MOV DL,10 + INT 224 ;ECHO LF + POP ES + POP DX ;GET BACK START OF BUFFER + MOV BX,OFFSET INBUF ;GET BDOS INPUT BUFFER AGAIN + MOV CL,BYTE PTR 1 [BX] ;THE # CHARACTERS READ + SUB CH,CH + INC BX ;FLUSH COUNT ACTUALLY READ + CMP CL,0 + JE GETLEM ;IF NONE TYPED, DON'T LOOP FOREVER +GETLLP: INC SI + INC BX + MOV AL,BYTE PTR [BX] + CMP AL,'A' + JL GETLLC + CMP AL,'Z' + JG GETLLC + ADD AL,32 +GETLLC: MOV ES:[SI],AL + LOOP GETLLP +GETLEM: INC SI + SUB AL,AL + MOV ES:[SI],AL + POP AX + MOV SCRFLG,AL + POP BX + RET + +PRTOUT: PUSH ES + PUSH BX + MOV DL,AL + MOV CL,05H + INT 224 + POP BX + POP ES + RET + +SCRCHK: PUSH AX + PUSH BX + PUSH DX + MOV AX,ES:.PFLAGS + XCHG AH,AL + TEST AL,1 ;CHECK IF SCRIPTING IS REQUESTED + JZ SCRNN + MOV SCRFLG,1 + SUB CX,CX ;COUNT OF CHARS PRINTED + MOV BP,DX ;START OF INPUT LINE + INC BP ;FIRST CHAR IS LENGTH OF BUFFER +SCR1L: MOV AL,ES:[BP] + INC BP ;GET CHARACTER + CMP BP,SI ;END OF INPUT? + JLE SCR2L + CALL PRTCRL + JMP SCREX +SCR2L: CALL PRTOUT ;OUTPUT ONE CHARACTER TO THE PRINTER + INC CX + CMP CL,SCPL + JNE SCR1L + CALL PRTCRL + JC SCREX + SUB CX,CX ;RESTART COUNT + JMP SCR1L ;GO FOR MORE + +SCRNN: MOV SCRFLG,0 +SCREX: POP DX + POP BX + POP AX + RET + +PRTCRL: MOV AL,13 ;FINISH UP WITH CRLF + CALL PRTOUT + MOV AL,10 + CALL PRTOUT + RET + + ;READ (A LINE OF INPUT & PARSE IT, LINE BUF IN ES:AX, + ;RETURN BUF IN ES:BX) +OPREAD: PUSH AX ;SAVE LINE BUF + PUSH AX + PUSH BX + CALL OPUSL ;UPDATE STATUS LINE + POP BX + POP AX + MOV BP,CHRPTR ;NEXT CHARACTER POSITION + MOV DS:BYTE PTR [BP],80H ;DON'T END OUTPUT, IF ANY, WITH NEW LINE +ORD1: MOV AX,OFFSET OUTBUF + CALL M_PRNT + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP SI ;INPUT BUFFER POINTER + MOV MORLIN,0 ;RE-INITIALIZE MORE COUNT FROM HERE + CALL GETLIN ;GET SOME CHARACTERS + CALL SCRCHK ;CHECK FOR SCRIPTING, SCRIPT INPUT IF ON +ORDNS: PUSH DI + MOV RDBOS,DX ;INITIALIZE RDBOS + MOV RDEOS,SI ;AND RDEOS + MOV RDRET,BX ;STORE RET POINTER + MOV RDNWDS,0 ;NO WORDS SO FAR + INC DX ;SKIP LENGTH BYTE + MOV DI,BX ;THIS WILL BE WORD ENTRY POINTER + INC DI ;SKIP MAX WORDS & NWORDS BYTES + INC DI +ORD8: MOV CX,OFFSET RDWSTR;HERE FOR NEXT WORD, POINT TO WORD STRING + MOV BX,DX ;AND SAVE BEGINNING OF WORD POINTER +ORD9: CMP DX,RDEOS ;END OF STRING? + JNE ORD10 ;NO + CMP CX,OFFSET RDWSTR;YES, WAS A WORD FOUND? + JNE ORD15 ;YES, WE STILL HAVE TO LOOKUP WORD + JMP ORD23 ;NO, WE'RE DONE +ORD10: MOV BP,DX ;GET NEXT CHARACTER FROM BUFFER + MOV AL,ES:[BP] + CMP AL,'A' + JL ORD1A + CMP AL,'Z' + JG ORD1A + ADD AL,32 ;LOWERCASIFY ALPHABETICS +ORD1A: INC DX + MOV SI,OFFSET RBRKS ;LIST OF READ BREAK CHARACTERS +ORD11: INC SI + CMP AL,-1[SI] ;SEARCH LIST FOR THIS ONE + JE ORD12 ;FOUND IT + CMP BYTE PTR [SI],0 ;END OF LIST? + JNE ORD11 ;NO, CONTINUE SEARCH + CMP CX,OFFSET RDWSTR+6 ;YES, NOT A BREAK, WORD STRING FULL? + JE ORD9 ;YES, LOOP UNTIL END OF WORD + MOV BP,CX ;NO, TACK THIS CHARACTER ONTO STRING + MOV DS:[BP],AL + INC CX + JMP ORD9 ;AND LOOP +ORD12: CMP CX,OFFSET RDWSTR;WORD READ BEFORE THIS BREAK? + JNE ORD14 ;YES + CMP SI,ESIBKS ;NO, BUT IS IT A SELF-INSERTING BREAK? + JBE ORD13 ;YES + INC BX ;NO, UPDATE BEGINNING OF WORD TO SKIP BREAK + JMP ORD9 ;AND RETURN TO LOOP TO FIND A WORD +ORD13: MOV BP,CX ;STORE THE BREAK IN WORD STRING + MOV DS:[BP],AL + INC CX + JMP ORD15 ;AND GO FOR THE WORD +ORD14: DEC DX ;UNREAD TERMINATING BREAK IN CASE IT WAS SI +ORD15: INC RDNWDS ;INCREMENT FOUND WORD COUNT + MOV BP,BX ;GREATER THAN MAX ALLOWED? + MOV BX,RDRET + MOV BL,ES:[BX] + CMP RDNWDS,BL + MOV BX,BP + JLE ORD16 ;NO + MOV AX,OFFSET ERR2 + CALL M_PRNT ;YES. INFORM LOSER + MOV AX,BX ;BEGINNING OF THIS WORD + MOV BP,RDEOS ;SAVE BYTE AFTER EOS + MOV BL,ES:[BP] + MOV ES:BYTE PTR [BP],0 ;ZERO IT TO MAKE STRING ASCIZ + CALL M_PRNT ;PRINT IT + MOV ES:[BP],BL ;AND RESTORE OLD BYTE + DEC RDNWDS ;REMEMBER THAT WE FLUSHED THIS WORD + JMP ORD23 ;AND WE'RE DONE +ORD16: MOV AX,BX ;CALCULATE NUMBER OF CHARACTERS IN WORD + NEG AX + ADD AX,DX + MOV ES:2[DI],AL ;SAVE THE NUMBER IN RET TABLE + SUB BX,RDBOS ;BYTE OFFSET FOR BEGINNING OF WORD + MOV ES:3[DI],BL ;STORE IT, TOO + MOV BP,CX ;MAKE WORD STRING ASCIZ + MOV DS:BYTE PTR [BP],0 + MOV AX,OFFSET RDWSTR;POINT TO IT + CALL ZWORD ;AND CONVERT TO (2-WORD) ZWORD + PUSH DX ;SAVE CHAR & WORD ENTRY POINTERS + PUSH DI + MOV DI,AX ;FIRST ZWORD WORD + MOV SI,VWORDS ;NUMBER OF VOCABULARY WORDS + MOV AX,SI + DEC AX ;WE WANT TO POINT TO LAST WORD + MUL VWLEN ;MULTIPLY BY WORD LENGTH IN BYTES + ADD AX,VOCBEG ;ADD POINTER TO BEGINNING TO FIND LAST WORD + MOV CX,AX ;POINTER TO LAST WORD + MOV DX,DI ;FIRST ZWORD WORD + MOV DI,BX ;SECOND ZWORD WORD + MOV BX,VWLEN ;CALCULATE INITIAL OFFSET FOR BINARY SEARCH + SAR SI,1 +ORD17: SAL BX,1 + SAR SI,1 + CMP SI,0 + JNE ORD17 + MOV SI,VOCBEG ;BEGINNING OF WORD TABLE + ADD SI,BX ;ADD CURRENT OFFSET(HALF OF POWER-OF-2 TABLE) + PUSH AX ;SAVE + MOV AX,VWLEN ;AVOID FENCEPOST BUG FOR EXACT POWER-OF-2 TBL + SUB SI,AX + POP AX ;RESTORE +ORD18: SAR BX,1 ;NEXT OFFSET WILL BE HALF OF PREVIOUS ONE + MOV AX,ES:[SI] ;GET FIRST HALF OF CURRENT ZWORD + XCHG AH,AL + CMP DX,AX ;COMPARE DESIRED ONE TO IT + JA ORD19 ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20 ;LESS, WE'LL HAVE TO MOVE DOWN + MOV BP,SI ;SAME, GET SECOND HALF + INC BP + INC BP + MOV AX,ES:[BP] + XCHG AH,AL + CMP DI,AX ;COMPARE DESIRED WORD WITH IT + JA ORD19 ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20 ;LESS, WE'LL HAVE TO MOVE DOWN + JMP ORD22 ;SAME, WE'VE FOUND IT, RETURN IT +ORD19: ADD SI,BX ;TO MOVE UP, ADD CURRENT OFFSET + CMP SI,CX ;HAVE WE MOVED PAST END OF TABLE? + JBE ORD21 ;NO + MOV SI,CX ;YES, POINT TO END OF TABLE INSTEAD + JMP ORD21 +ORD20: SUB SI,BX ;TO MOVE DOWN, SIMPLY SUBTRACT OFFSET +ORD21: CMP BX,VWLEN ;IS OFFSET RESOLUTION BELOW ONE WORD? + JGE ORD18 ;NO, CONTINUE LOOP + SUB SI,SI ;YES, WORD NOT FOUND, RETURN ZERO +ORD22: POP DI ;RESTORE WORD ENTRY POINTER + MOV DX,SI ;POINTER TO WORD FOUND + XCHG DH,DL + MOV ES:[DI],DX ;STORE IT + POP DX ;RESTORE CHAR POINTER + ADD DI,4 ;UPDATE POINTER FOR NEXT WORD ENTRY + JMP ORD8 ;GO FOR IT +ORD23: INC RDRET ;DONE, STORE NUMBER OF WORDS FOUND + MOV BP,RDRET + MOV DL,RDNWDS + MOV ES:[BP],DL + POP DI ;RESTORE USER STACK POINTER + RET ;AND RETURN + + ;PRINTC (PRINT CHAR WHOSE ASCII VALUE IS GIVEN) +OPPRNC: JMP PUTCHR ;QUEUE THE CHARACTER FOR PRINTING + + ;PRINTN (PRINT A NUMBER) +OPPRNN: MOV BX,AX ;NUMBER TO PRINT + CMP BX,0 + JNE OPN1 ;NON-ZERO + MOV AX,'0' ;SPECIAL CASE ZERO + JMP PUTCHR +OPN1: JG OPN2 ;POSITIVE? + MOV AX,'-' ;NO, PRINT MINUS SIGN + CALL PUTCHR + NEG BX ;AND MAKE IT POSITIVE +OPN2: SUB CX,CX ;COUNT OF DIGITS ON STACK + JMP OPN4 ;START WITH GREATER-THAN-10 TEST +OPN3: MOV AX,BX ;EXTRACT A DIGIT + MOV BP,10 + CWD + IDIV BP + PUSH DX ;PUSH IT + INC CX ;BUMP COUNT + MOV BX,AX ;GET QUOTIENT +OPN4: CMP BX,10 ;MORE DIGITS TO EXTRACT? + JGE OPN3 ;YES, GO LOOP + MOV AX,BX ;NO, GET LAST (FIRST) DIGIT + JMP OPN6 ;ALREADY IN PLACE +OPN5: POP AX ;POP NEXT DIGIT +OPN6: ADD AX,'0' ;ASCIIZE IT + CALL PUTCHR ;QUEUE IT + DEC CX ;REDUCE DIGIT COUNT + JGE OPN5 ;LOOP IF SOME LEFT + RET ;ELSE, RETURN + + ;PRINT (THE STRING POINTED TO BY ES:AX) +OPPRIN: CALL BSPLIT ;SPLIT THE BLOCK & WORD NUMBERS + JMP PUTSTR ;PRINT THE STRING + + ;PRINTB (PRINT THE STRING POINTED TO BY THE BYTE-POINTER ES:AX) +OPPRNB: CALL BSPLTB ;SPLIT THE BLOCK & BYTE NUMBERS + JMP PUTSTR ;PRINT THE STRING + +;PSEUDO-INSTRUCTIONS FOR HOURS/MINUTES HERE FOR STATUS LINE +OPPRNH: MOV PMFLAG,0 + CMP AL,12 + JL OPH0 + MOV PMFLAG,1 +OPH0: CMP AL,0 + JNE OPH00 + MOV AL,12 +OPH00: CMP AL,12 + JLE OPH1 + SUB AL,12 ;HOUR SLOT IS 24 HOUR TIME +OPH1: CMP AL,9 + JG OPH2 + PUSH AX + MOV AL,32 + CALL PUTCHR ;OUTPUT SPACE FOR HOUR LESS THAN 10 + POP AX +OPH2: CALL OPPRNN + MOV AL,':' + JMP PUTCHR ;AND COLO + +OPPRNM: CMP AL,9 + JG OPM1 + PUSH AX + MOV AL,'0' + CALL PUTCHR + POP AX +OPM1: CALL OPPRNN + MOV AL,32 + CALL PUTCHR + MOV AL,'a' + CMP PMFLAG,0 + JE OPM2 + MOV AL,'p' +OPM2: CALL PUTCHR + MOV AL,'m' + JMP PUTCHR + + ;PRINTD (PRINT OBJ'S SHORT DESCRIPTION) +OPPRND: CALL OBJLOC ;FIND OBJ'S LOCATION + ADD AX,7 ;PROPERTY TABLE POINTER + MOV BP,AX + MOV AX,ES:[BP] ;GET IT + XCHG AH,AL + INC AX ;POINT TO STRING + CALL BSPLTB ;SPLIT POINTER + JMP PUTSTR ;AND PRINT THE STRING + + ;PRINTI (PRINT THE STRING FOLLOWING THIS INSTRUCTION) +OPPRNI: MOV AX,ZPC1 ;GET POINTER TO STRING + MOV BX,ZPC2 + CALL PUTSTR ;AND PRINT IT + MOV ZPC1,AX ;UPDATE ZPC + MOV ZPC2,BX + JMP NEWZPC + + ;PRINTR (PRINTI FOLLOWED BY RTRUE) +OPPRNR: CALL OPPRNI ;DO A PRINTI + CALL OPCRLF ;A CRLF + JMP OPRTRU ;AND AN RTRUE + + ;CRLF (DO A NEWLINE) +OPCRLF: JMP NEWLIN ;DO A NEWLINE + + ;CALL (A FUNCTION WITH OPTIONAL ARGUMENTS), # OF ARGS IN AX +OPCALL: NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV DX,AX ;NUMBER OF ARGUMENTS TO CALL + MOV AX,ARGBLK ;FUNCTION TO CALL + CMP AX,0 + JNE OCL1 ;ZERO? + SUB AX,AX ;YES, SIMPLY RETURN A ZERO + JMP PUTVAL +OCL1: XCHG SP,DI + PUSH ZPC1 + PUSH ZPC2 + MOV CX,ZLOCS ;AND OLD LOCAL POINTER + PUSH CX ;AND SAVE IT + XCHG SP,DI + CALL BSPLIT ;SPLIT FUNCTION POINTER + MOV ZPC1,AX ;MAKE IT THE NEW ZPC + MOV ZPC2,BX + CALL NEWZPC ;UPDATE ZPC STUFF + MOV ZLOCS,DI ;LOCALS WILL START AT NEXT STACK SLOT + SUB ZLOCS,2 + CALL NXTBYT ;NUMBER OF LOCALS + MOV BX,AX + MOV BP,OFFSET ARGBLK+2 ;POINT TO FIRST OPTIONAL ARG +OCL2: DEC BX ;ANY MORE LOCALS? + JL OCL4 ;NO, WE'RE DONE + CALL NXTWRD ;YES, GET THE NEXT LOCAL DEFAULT VALUE + DEC DX ;ANY MORE OPTIONALS GIVEN? + JLE OCL3 ;NO + XCHG SP,DI + MOV CX,DS:[BP] + PUSH CX ;YES, USE ITS VALUE + XCHG SP,DI + ADD BP,2 + JMP OCL2 ;AND CONTINUE LOOP +OCL3: XCHG SP,DI + PUSH AX ;OTHERWISE USE DEFAULT + XCHG SP,DI + JMP OCL2 ;AND LOOP +OCL4: RET + + ;RETURN (FROM CURRENT FUNCTION CALL) +OPRETU: MOV DI,ZLOCS ;RESTORE OLD TOP OF STACK + XCHG SP,DI + POP DX + POP ZLOCS + POP ZPC2 + POP ZPC1 + XCHG SP,DI + PUSH AX ;VALUE TO RETURN + CALL NEWZPC ;UPDATE ZPC STUFF + POP AX + JMP PUTVAL ;RETURN THE VALUE + + ;RTRUE +OPRTRU: MOV AX,1 ;RETURN A 1 + JMP OPRETU + + ;RFALSE +OPRFAL: SUB AX,AX ;RETURN A 0 + JMP OPRETU + + ;JUMP (TO A NEW LOCATION) +OPJUMP: ADD ZPC2,AX ;ADD OFFSET TO CURRENT ZPC + SUB ZPC2,2 ;ADJUST IT + JMP NEWZPC ;NORMALIZE IT & UPDATE ZPC STUFF + + ;RSTACK (RETURN STACK) +OPRSTA: XCHG SP,DI + POP AX + XCHG SP,DI + JMP OPRETU ;AND RETURN IT + + ;FSTACK (FLUSH A VALUE OFF THE STACK) +OPFSTA: XCHG SP,DI + POP DX + XCHG SP,DI + RET + + ;NOOP (NO OPERATION) +OPNOOP: RET ;DO NOTHING + + ;GET A BYTE, BLOCK-POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX, + ;UPDATE AX & BX TO REFLECT BYTE GOTTEN +GETBYT: PUSH AX ;SAVE BLOCK-POINTER + CMP AX,ENDLOD ;IS THIS A PRELOADED LOCATION? + JGE GTY1 ;NO + MOV CL,9 ;YES, RECONSTRUCT POINTER + SHL AX,CL ;SHIFT BLOCK POINTER BY 9 + OR AX,BX ;ADD IN THE OFFSET + XCHG AX,BX + MOV CL,ES:[BX] ;GET THE BYTE + JMP GTY2 ;CLEAR UNWANTED BYTE & RETURN IT +GTY1: CALL GETPAG ;FIND THE PROPER PAGE + ADD AX,BX ;POINT TO DESIRED BYTE + XCHG AX,BX + MOV CL,ES:[BX] ;GET IT +GTY2: SUB CH,CH ;CLEAR UNWANTED BYTE & RETURN IT + MOV BX,AX + POP AX ;RESTORE BLOCK-POINTER + INC BX ;UPDATE POINTER + CMP BX,200H ;END-OF-PAGE? + JNE GTY3 ;NO + SUB BX,BX ;YES, CLEAR BYTE-POINTER + INC AX ;AND UPDATE BLOCK-POINTER +GTY3: RET + + ;GET A WORD, BLOCK POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX +GETWRD: PUSH DX ;SAVE + CALL GETBYT ;GET HIGH-ORDER BYTE + PUSH CX ;SAVE IT + CALL GETBYT ;GET LOW-ORDER BYTE + POP DX ;GET OTHER BYTE + MOV CH,DL ;POSITION IT + POP DX ;RESTORE + RET + + ;GET THE NEXT BYTE, RETURN IT IN AX +NXTBYT: PUSH BX ;SAVE + MOV BX,ZPC2 ;BYTE POINTER + ADD BX,CURPAG ;INDEX INTO CURRENT PAGE + MOV AX,ES:[BX] ;SAVE BYTE ***POSSIBLE LOSER + PUSH AX + INC ZPC2 ;UPDATE PC + CMP ZPC2,200H ;END-OF-PAGE? + JL NXB1 ;NO + CALL NEWZPC ;YES, UPDATE PAGE +NXB1: POP AX ;RETRIEVE BYTE + SUB AH,AH ;CLEAR UNWANTED BYTE + POP BX ;RESTORE + RET ;AND RETURN IT + + ;GET THE NEXT WORD, RETURN IT IN AX +NXTWRD: PUSH BX ;SAVE + CALL NXTBYT ;GET HIGH-ORDER BYTE + PUSH AX ;SAVE IT + CALL NXTBYT ;GET LOW-ORDER BYTE + POP BX ;GET HIGH-ORDER BYTE + MOV AH,BL ;POSITION IT + POP BX ;RESTORE + RET ;RETURN THE WORD + + ;GET AN ARGUMENT GIVEN ITS TYPE IN AX +GETARG: DEC AX ;EXAMINE ARGUMENT + JL NXTWRD ;0 MEANT LONG IMMEDIATE + JE NXTBYT ;1 MEANT SHORT IMMEDIATE + CALL NXTBYT ;2 MEANT VARIABLE, GET THE VAR + CMP AX,0 ;STACK? + JNE GETVAR ;NO, JUST GET THE VAR'S VALUE + XCHG SP,DI + POP AX ;YES, POP THE STACK + XCHG SP,DI + RET + + ;GET VALUE OF A VARIABLE, VAR IN AX, VALUE RETURNED IN AX +GETVAR: CMP AX,0 ;STACK? + JNE GTV1 ;NO + MOV AX,SS:[DI] ;YES, GET TOP-OF-STACK + RET + +GTV1: PUSH BP ;SAVE + CMP AX,16 ;LOCAL? + JGE GTV3 ;NO + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV AX,[BP] ;AND GET IT +GTV2: POP BP ;RESTORE + RET + +GTV3: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + MOV BP,AX ;AND GET IT + MOV AX,ES:[BP] + XCHG AH,AL + JMP GTV2 + + ;UPDATE VALUE OF A VARIABLE, VAR IN AX, NEW VALUE IN BX +PUTVAR: CMP AX,0 ;STACK? + JNE PTV1 ;NO + MOV SS:[DI],BX ;YES, UPDATE TOP-OF-STACK + RET + +PTV1: CMP AX,16 ;LOCAL? + JGE PTV2 ;NO + PUSH BP ;SAVE + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV [BP],BX ;AND UPDATE IT + POP BP ;RESTORE + RET + +PTV2: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + XCHG AX,BX ;AND UPDATE IT + XCHG AH,AL + MOV ES:[BX],AX + RET + + ;RETURN VAL IN AX TO LOCATION SPECIFIED BY NEXTBYTE + ;DESTROYS BX, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION +BYTVAL: SUB AH,AH ;THIS ENTRY FOR BYTE VALUE TO CLEAR HIGH BYTE + JMP PUTVAL + +PUTVAL: MOV BX,AX ;NORMAL ENTRY + CALL NXTBYT ;GET VAR TO USE + CMP AX,0 ;STACK? + JNE PUTVAR ;NO, GO STORE VALUE + XCHG SP,DI + PUSH BX ;YES, PUSH ONTO STACK + XCHG SP,DI + RET ;AND RETURN + + ;PREDICATE HANDLERS TRUE & FALSE + ;DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FCNS +PFALSE: SUB BX,BX ;PREDICATE WAS FALSE, CLEAR FLAG + JMP PPRED + +PTRUE: MOV BX,1 ;PREDICATE WAS TRUE, SET FLAG + JMP PPRED + +PPRED: CALL NXTBYT ;GET FIRST (OR ONLY) PREDICATE JUMP BYTE + TEST AX,80H ;NORMAL POLARITY PREDICATE? + JE PPR1 ;NO, LEAVE FLAG ALONE + INC BX ;YES, INCREMENT FLAG +PPR1: TEST AX,40H ;ONE-BYTE JUMP OFFSET? + JE PPR2 ;NO + AND AX,0FF3FH ;YES, CLEAR SPECIAL BITS + JMP PPR3 +PPR2: AND AX,0FF3FH ;CLR SPECIAL BITS FROM HIGH-ORDER OFFSET BYTE + MOV CX,AX ;HIGH-ORDER BYTE + CALL NXTBYT ;GET LOW-ORDER BYTE + MOV AH,CL ;MOVE IN HIGH-ORDER BITS + TEST AX,2000H ;IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)? + JE PPR3 ;NO + OR AX,0C000H ;YES, MAKE 16-BIT NUMBER NEGATIVE +PPR3: DEC BX ;TEST FLAG + JE PPR6 ;WAS 1, THAT MEANS DO NOTHING + CMP AX,0 ;ZERO JUMP? + JNE PPR4 ;NO + JMP OPRFAL ;YES, THAT MEANS DO AN RFALSE +PPR4: DEC AX ;ONE JUMP? + JNE PPR5 ;NO + JMP OPRTRU ;YES, THAT MEANS DO AN RTRUE +PPR5: DEC AX ;ADJUST OFFSET + ADD ZPC2,AX ;ADD TO PC + JMP NEWZPC ;AND UPDATE ZPC STUFF +PPR6: RET + + ;SPLIT BYTE-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE OFFSET IN BX +BSPLTB: MOV BX,AX + XCHG AL,AH ;EXTRACT BLOCK BITS + SHR AX,1 + AND AX,7FH ;CLEAR UNWANTED BITS + AND BX,1FFH ;CLEAR ALL BUT BYTE OFFSET BITS + RET + + ;SPLIT WORD-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE-OFFSET IN BX +BSPLIT: MOV BX,AX + MOV AL,AH ;EXTRACT BLOCK BITS + SUB AH,AH ;CLEAR UNWANTED BITS + SUB BH,BH ;CLEAR ALL BUT WORD OFFSET BITS + SHL BX,1 ;CONVERT TO BYTE OFFSET + RET + + ;GIVEN OBJ NUMBER IN AX, RETURN OBJ LOCATION IN AX +OBJLOC: SUB AH,AH ;CLEAR UNWANTED BITS + PUSH BX ;MULTIPLY BY 9 THE LAZY WAY + MOV BX,AX + SHL AX,1 + SHL AX,1 + SHL AX,1 + ADD AX,BX + POP BX ;RESTORE + ADD AX,OBJTAB ;INDEX INTO OBJECT TABLE + ADD AX,53 ;SKIPPING DEFAULT PROPERTY TABLE + RET + + ;GIVEN POINTER TO A PROPERTY IN BX!, UPDATE IT TO POINT TO NEXT PROP +NXTPRP: PUSH AX ;SAVE + PUSH CX ;SAVE + MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,224 ;EXTRACT PROPERTY LENGTH + MOV CL,5 ;PROPSIZE + SHR AL,CL + SUB AH,AH + ADD BX,AX ;ADD IT TO OLD POINTER + ADD BX,2 ;ADJUST FOR EXTRA LENGTH BYTE PLUS IDENTIFIER + POP CX ;RESTORE + POP AX ;RESTORE + RET + + ;OUTPUT A ZSTR, BLOCK-POINTER IN AX, BYTE-POINTER IN BX + ;RETURN UPDATED POINTER +PUTSTR: PUSH SI ;SAVE + PUSH CX ;SAVE + PUSH DX ;SAVE + PUSH DI ;SAVE + PUSH BP ;SAVE + SUB DX,DX ;TEMP CS STARTS AT 0 + SUB DI,DI ;PERM CS STARTS AT 0 +PTS1: CALL GETWRD ;GET NEXT STRING WORD + MOV SI,CX + PUSH AX ;SAVE POINTER & COPY OF STRING WORD + PUSH BX + PUSH SI + MOV CX,3 ;3 BYTES IN WORD +PTS2: PUSH SI ;SAVE CURRENT BYTE (IN LOW-ORDER POSITION) + MOV BP,CX ;SHIFT TO NEXT BYTE + MOV CL,5 + SAR SI,CL + MOV CX,BP + LOOP PTS2 ;LOOP UNTIL DONE + MOV CX,3 ;RETRIEVE THE 3 BYTES +PTS3: POP SI ;GET NEXT BYTE + AND SI,1FH ;CLEAR UNWANTED BITS + CMP DX,0 ;IN WORD MODE? + JGE PTS4 ;NO {WAS BPL, CHECK} + SAL SI,1 ;YES, CALCULATE WORD OFFSET + ADD SI,WRDTAB ;POINT INTO WORD TABLE + ADD SI,WRDOFF ;USING PROPER 32-WORD BLOCK + MOV AX,ES:[SI] ;POINT TO WORD STRING + XCHG AH,AL + CALL BSPLIT ;SPLIT IT + CALL PUTSTR ;AND PRINT IT + JMP PTS15 ;CONT. WHERE WE LEFT OFF WITH TEMP CS RESET +PTS4: CMP DX,3 ;CS 3 SELECTED (ASCII MODE)? + JL PTS6 ;NO, NORMAL CS + JNE PTS5 ;NO, BUT WE ARE IN ASCII MODE + XCHG DL,DH ;SHIFT SOME BITS HIGH TO MAKE NUMBER LARGE + OR DX,SI ;SAVE HIGH-ORDER ASCII BITS HERE + JMP PTS16 ;GO GET NEXT BYTE +PTS5: AND DX,3 ;EXTRACT PREVIOUSLY SAVED HIGH-ORDER BITS + MOV BP,CX ;POSITION THEM + MOV CL,5 + SAL DX,CL + MOV CX,BP + OR DX,SI ;OR IN LOW-ORDER BITS + MOV AX,DX + JMP PTS14 ;GO PRINT THE CHARACTER +PTS6: CMP SI,6 ;SPECIAL CODE? + JL PTS9 ;YES, SPACE, WORD, OR SHIFT + CMP DX,2 ;MIGHT ALSO BE SPECIAL IF IN CS 2 + JNE PTS8 ;BUT WE'RE NOT + CMP SI,7 ;CRLF? + JE PTS7 ;YES + JG PTS8 ;NO, NOT ASCII MODE, EITHER? + INC DX ;YES IT IS, SWITCH TO ASCII MODE + JMP PTS16 ;AND GO GET NEXT BYTE +PTS7: CALL NEWLIN ;CRLF REQUESTED, DO A NEWLINE + JMP PTS15 +PTS8: MOV AX,DX ;NORMAL CHARACTER, GET CS + MOV BP,26 ;CALCULATE OFFSET FOR THIS CS + MUL BP + ADD AX,SI ;ADD IN CHARACTER OFFSET (+6) + SUB AX,6 ;CHARACTER OFFSET + MOV BX,OFFSET ZCHRS ;GET THE CHARACTER FROM CONVERSION VECTOR + XLAT ZCHRS + JMP PTS14 ;GO PRINT IT +PTS9: CMP SI,0 ;IS IT A SPACE? + JNE PTS10 ;NO + MOV AX,' ' ;YES, GO PRINT A SPACE + JMP PTS14 +PTS10: CMP SI,3 ;IS IT A WORD? + JG PTS11 ;NO, MUST BE A SHIFT + OR DX,8000H ;SWITCH TO WORD MODE FOR NEXT BYTE + DEC SI ;CALCULATE WORD-TABLE BLOCK OFFSET + MOV BP,CX ;64 BYTES IN A BLOCK + MOV CL,6 + SHL SI,CL + MOV CX,BP + MOV WRDOFF,SI ;SAVE IT AND LOOP + JMP PTS16 +PTS11: SUB SI,3 ;CALCULATE NEW CS + CMP DX,0 ;TEMPORARY SHIFT (FROM CS 0)? + JNE PTS12 ;NO + MOV DX,SI ;YES, JUST SAVE NEW TEMP CS + JMP PTS16 +PTS12: CMP SI,DX ;IS THIS THE CURRENT CS? + JE PTS13 ;YES, DO A PERM SHIFT TO IT + SUB DX,DX ;OTHERWISE, PERM SHIFT TO CS 0 +PTS13: MOV DI,DX ;TEMP & PERM CS'S ARE SAME NOW + JMP PTS16 +PTS3A: JMP PTS3 ;DUMMY FOR NON-SHORT LOOP +PTS14: CALL PUTCHR ;PRINT THE CHARACTER +PTS15: MOV DX,DI ;RESET TEMP CS TO PERM CS +PTS16: LOOP PTS3A ;NEXT BYTE + POP SI ;RESTORE POINTERS & ORIGINAL STRING WORD + POP BX + POP AX + CMP SI,0 ;END-OF-STRING? + JL PTS1A ;YES, CLEAN UP & RETURN UPDATED POINTER + JMP PTS1 ;NO, GET NEXT WORD +PTS1A: POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN THE CHARACTER SET # IN AX +CHRCS: CMP AX,0 ;IS THIS A NULL? + JNE CCS1 ;NO + MOV AX,3 ;YES, RETURN DUMMY CS NUMBER + RET + +CCS1: PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CONVERSION VECTOR +CCS2: INC BX ;FOUND THE CHARACTER? + CMP AL,-1[BX] + JE CCS3 ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CCS2 ;NO, CONTINUE LOOP + MOV AX,2 ;YES, CALL IT CS 2 + JMP CCS5 +CCS3: SUB BX,OFFSET ZCHRS ;FIND CHARACTER POSITION + SUB AX,AX ;START WITH CS 0 +CCS4: SUB BX,26 ;EVERY 26 CHARACTERS IS A NEW CS + JLE CCS5 ;DONE + INC AX ;INCREMENT CS # & CONTINUE LOOP + JMP CCS4 +CCS5: POP BX + RET + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN ZSTR BYTE VALUE IN AX +CHRBYT: PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CHARACTER CONVERSION TABLE +CHB1: INC BX ;FOUND THE CHARACTER? + CMP AL,-1[BX] + JE CHB2 ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CHB1 ;NO, CONTINUE LOOP + SUB AX,AX ;YES, RETURN ZERO FOR FAILURE + JMP CHB4 +CHB2: SUB BX,OFFSET ZCHRS-5 ;ADJUST POINTER SO FIRST CHARACTER IS 6 + MOV AX,BX +CHB3: CMP AX,32 ;SUBTRACT MULTIPLES OF 26 UNTIL BASE CODE + JL CHB4 + SUB AX,26 + JMP CHB3 +CHB4: POP BX ;RESTORE + RET + + ;CONVERT UP TO 6 ASCIZ CHARS POINTED TO BY DS:AX + ;TO A 2-WORD ZSTR RETURNED IN AX & BX +ZWORD: PUSH SI ;SAVES + PUSH CX + PUSH DX + PUSH DI + PUSH BP + MOV SI,AX ;CHARACTER STRING POINTER + SUB DI,DI ;CS STARTS AT 0 + MOV CX,6 ;MAKE 6 ZSTR BYTES +ZWD1: INC SI ;GET NEXT CHARACTER + MOV BL,-1[SI] + CMP BL,0 + JNE ZWD3 ;NOT END-OF-STRING + MOV AX,OFFSET PADCHR;AT END-OF-STRING, PAD WITH PAD CHARACTER +ZWD2: PUSH AX ;SAVE A PAD BYTE + LOOP ZWD2 ;LOOP UNTIL DONE + JMP ZWD6 ;THEN GO FORM ZWORD +ZWD3: MOV AX,BX + CALL CHRCS ;FIND THE CS NUMBER FOR THIS CHAR + CMP AX,0 ;CS 0? + JE ZWD4 ;YES + ADD AX,3 ;NO, CALCULATE TEMP SHIFT BYTE + PUSH AX ;SAVE THE SHIFT BYTE + DEC CX ;REDUCE BYTE COUNT + JE ZWD6 ;DONE +ZWD4: MOV AX,BX ;FIND THE PROPER BYTE VALUE FOR THIS CHAR + CALL CHRBYT + CMP AX,0 ;IN NORMAL CS'S? + JNE ZWD5 ;YES + MOV AX,6 ;NO, USE ASCII SHIFT + PUSH AX + DEC CX ;DONE YET? + JE ZWD6 ;YES + MOV AX,BX ;NO, SAVE HIGH-ORDER ASCII BITS + MOV BP,CX + MOV CL,5 + SAR AX,CL + MOV CX,BP + PUSH AX + DEC CX ;DONE YET? + JE ZWD6 ;YES + AND BX,1FH ;NO, SAVE LOW-ORDER ASCII BITS + MOV AX,BX +ZWD5: PUSH AX ;SAVE THIS BYTE + LOOP ZWD1 ;LOOP UNTIL ZWORD FULL +ZWD6: MOV BP,SP ;BUILD ZWORD WORDS FROM 6 SAVED BYTES + MOV AX,10[BP] + MOV CL,5 + SHL AX,CL + OR AX,8[BP] + SHL AX,CL + OR AX,6[BP] + MOV BX,4[BP] + SHL BX,CL + OR BX,2[BP] + SHL BX,CL + OR BX,[BP] + OR BX,8000H ;SET END-OF-STRING BIT IN SECOND WORD + ADD SP,12 ;FLUSH STACK + POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET + + ;QUEUE CHARACTER IN AX FOR OUTPUT +PUTCHR: PUSH BP + MOV BP,CHRPTR ;END OF BUFFER? + CMP BP,ENDBUF + JNE PTC7 ;NO + PUSH AX ;YES, ENTER OUTPUT ROUTINE; SAVES + PUSH BX + PUSH SI + MOV BX,ENDBUF ;END OF BUFFER + MOV SI,OFFSET OUTBUF;BEGINNING OF BUFFER +PTC1: DEC BX ;SEARCH FOR SPACE BACKWARDS FROM END + CMP BYTE PTR [BX],' ' + JE PTC3 + CMP BX,SI ;STOP AT BEGINNING OF BUFFER + JNE PTC1 +PTC2: MOV AX,OFFSET OUTBUF + CALL M_PRNT ;NO SPACES. OUTPUT WHOLE LINE + MOV CHRPTR,SI ;RESTORE POINTER TO BEGINNING OF BUFFER + MOV BP,SP + CMP BYTE PTR 4[BP],' ' ;DID A SPACE CAUSE BUFFER OVERFLOW? + JNE PTC6 ;NO + MOV WORD PTR 4[BP],0 ;YES, FLUSH IT + JMP PTC6 ;AND RETURN +PTC3: CMP BX,SI ;DEGENERATE CASE WITH SPACE AT OUTBUF? + JE PTC2 ;YES, OUTPUT WHOLE LINE + MOV BYTE PTR [BX],0 ;NO, OUTPUT UP TO SPACE + MOV AX,OFFSET OUTBUF + CALL M_PRNT + MOV AX,ENDBUF ;END OF BUFFER + INC BX ;START GETTING CHARACTERS AFTER THE SPACE +PTC4: CMP BX,AX ;AT END YET? + JE PTC5 ;YES + MOV BP,AX ;SAVE AX + MOV AL,[BX] + MOV [SI],AL ;NO, COPY NEXT CHAR TO BEGINNING OF BUF + MOV AX,BP ;RESTORE AX + INC BX + INC SI + JMP PTC4 ;AND CONTINUE +PTC5: MOV CHRPTR,SI ;NEXT CHAR WILL GO AFTER COPIED STUFF +PTC6: POP SI ;CLEAN UP + POP BX + POP AX + CMP AX,0 ;AND IGNORE A NULL CHARACTER + JE PTC8 +PTC7: MOV BP,CHRPTR ;NOW STORE THE CHARACTER IN BUFFER + MOV DS:[BP],AL + INC CHRPTR ;UPDATE POINTER +PTC8: POP BP ;RESTORE + RET ;AND RETURN + + ;GO TO NEW LINE, OUTPUTTING CURRENT BUFFER +NEWLIN: PUSH BX ;SAVE + MOV BX,CHRPTR ;END LINE AT CURRENT POINT + MOV BYTE PTR [BX],0 + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP BX ;RESTORE + MOV AX,OFFSET OUTBUF + CALL M_PRNT ;AND OUTPUT LINE + RET + + ;INITIALIZATION +TSETUP: MOV BX,OFFSET OUTBUF;START OF OUTPUT BUFFER + MOV AL,SCPL + SUB AH,AH + ADD BX,AX ;ADD LENGTH OF BUFFER + MOV ENDBUF,BX ;THIS IS ENDBUF POINTER + MOV BYTE PTR [BX],0 ;BUFFER IS FOLLOWED BY A 0 FOR CONVENIENCE + MOV BX,OFFSET SLSTAB + CMP TIMEMD,0 + JE TSET1 + ADD BX,4 +TSET1: MOV AX,[BX] + MOV SLSTR,AX + MOV CX,2[BX] + MOV SLTAB,CX + CALL M_INIT + RET + +ZIPBGN: CALL SYSINI ;DO ANY SYSTEM INITIALIZATION +STR5: MOV AX,MBLEN + MOV MEMTOP,AX + SUB AX,AX ;BLOCK 0 + SUB BX,BX ;PUT AT BEGINNING OF GAME SEGMENT + CALL GETBLK ;GET THE BLOCK + CMP ES:BYTE PTR .PVERS1,ZMVERS ;PROPER Z-MACHINE VERSION? + JNE STR8 ;NO + TEST ES:BYTE PTR .PVERS2,1 ;YES,PROPER MODE BITS? + JE STR9 ;YES +STR8: MOV AX,OFFSET FTL4 + JMP FATAL +STR9: TEST ES:BYTE PTR .PVERS2,2 ;TIME MODE REQUESTED? + JE STR10 ;NO + INC TIMEMD ;YES, SET TIME-MODE FLAG +STR10: MOV AX,ES:.PZRKID ;UNIQUE GAME & VERSION IDENTIFIER + XCHG AH,AL + MOV ZORKID,AX + MOV AX,ES:.PENDLD ;GET ENDLOD POINTER + XCHG AH,AL + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR12 + AND AX,0FE00H + ADD AX,200H +STR12: MOV CX,AX + MOV BP,CX ;EXTRACT ENDLOD BLOCK + MOV CL,9 + SAR BP,CL + MOV CX,BP + MOV ENDLOD,CX ;SAVE ENDLOD BLOCK NUMBER + DEC CX ;NUMBER OF BLOCKS LEFT TO LOAD + MOV AX,1 ;STARTING WITH BLOCK 1 + MOV BX,200H ;LOCATION TO PUT THEM + CALL GTBLKS ;GET THE BLOCKS + MOV AX,ES:.PVOCTB ;VOCAB LOCATION + XCHG AH,AL + MOV VOCTAB,AX ;SAVE VOCABULARY TABLE POINTER + MOV AX,ES:.POBJTB ;GET OBJECT TABLE POINTER + XCHG AH,AL + MOV OBJTAB,AX + MOV AX,ES:.PGLOTB ;GET GLOBAL TABLE POINTER + XCHG AH,AL + MOV GLOTAB,AX + MOV AX,ES:.PWRDTB ;GET WORD TABLE POINTER + XCHG AH,AL + MOV WRDTAB,AX + MOV AX,ES:.PPURBT ;GET PURE CODE POINTER + XCHG AH,AL + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR13 + ADD AX,200H +STR13: MOV CL,9 ;EXTRACT BLOCK NUMBER + SAR AX,CL + AND AX,7FH ;CLEAR UNWANTED BITS + MOV PURBOT,AX ;SAVE IT + MOV BX,OFFSET RBRKS ;START OF READ BREAK CHARACTER TABLE + MOV SI,VOCTAB ;VOCAB TABLE POINTER + MOV CL,ES:BYTE PTR [SI] ;1ST BYTE IN VOCTAB IS # OF SIBREAKS + SUB CH,CH ;CLEAR HIGH BYTE + INC SI +STR14: MOV AL,ES:[SI] + MOV [BX],AL ;TRANSFER THEM + INC BX + INC SI + LOOP STR14 + MOV ESIBKS,BX ;REMEMBER END OF SI BREAKS + MOV BP,OFFSET IRBRKS;ALWAYS END WITH INITIAL BREAK CHARACTERS +STR15: MOV AL,DS:[BP] + MOV [BX],AL ;TRANSFER THEM + INC BX + INC BP + CMP AL,0 + JNE STR15 + MOV AL,ES:[SI] ;GET VOCABULARY ENTRY LENGTH + SUB AH,AH + MOV VWLEN,AX ;AND STORE IT AWAY + INC SI + MOV AX,ES:[SI] ;GET NEXT WORD IN TABLE + XCHG AH,AL + MOV VWORDS,AX ;NUMBER OF WORD ENTRIES IN VOCABULARY + ADD SI,2 ;MOVE TO NEXT WORD + MOV VOCBEG,SI ;BEGINNING OF ACTUAL VOCABULARY + + MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + MOV CL,9 + SHL SI,CL ;THIS IS FIRST LOCATION (ES:) OF PAGING + MOV PAGES,SI ;SAVE THIS TO USE AS AN OFFSET + + MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + NEG SI + MOV DI,MEMTOP ;GET PARAGRAPHS OF MEMORY + MOV CL,5 + SAR DI,CL ;CHANGE TO PAGES + ADD SI,DI ;NUMBER OF PAGES FOR PAGING + MOV BUFPGS,SI ;SAVE THIS NUMBER FOR FUTURE REFERENCE + CMP BUFPGS,63 + JLE STR16 + MOV BUFPGS,63 ;OUR TABLE IS ONLY SO BIG.... + MOV SI,63 +STR16: SHL SI,1 + SHL SI,1 ;EACH PAGE HAS 4 BYTES OF INFO + MOV BX,OFFSET PAGTAB ;POINT INTO PAGE INFO TABLE + ADD SI,BX + MOV WORD PTR [SI],-1 ;MAKE THIS THE END OF TABLE MARK + + CALL M_TIME ;GET THE CURRENT TIME-OF-DAY + JMP START1 + + ;RESTART EXECUTION HERE +RESTRT: SUB AX,AX ;REREAD ALL OF THE IMPURE STUFF + SUB BX,BX + MOV CX,PURBOT + CALL GTBLKS +START1: CALL TSETUP ;SETUP TERMINAL/STATUS LINE + CALL CLRSCR ;CLEAR THE REMAINDER OF SCREEN + MOV SP,OFFSET STK_TOP ;INITIALIZE OUR STACK POINTER + MOV DI,OFFSET ZSTK_TP ;INITIALIZE USER STACK POINTER + MOV CHRPTR,OFFSET OUTBUF ;INITIALIZE OUTPUT CHARACTER POINTER + MOV ZLOCS,DI ;LOCALS WOULD START AT FIRST SLOT, + SUB ZLOCS,2 ;IF THERE WERE ANY + MOV AX,ES:.PSTART ;GET STARTING LOCATION + XCHG AH,AL + CALL BSPLTB ;SPLIT BLOCK & BYTE POINTERS + MOV ZPC1,AX ;INITIALIZE ZPC BLOCK-POINTER + MOV ZPC2,BX ;INITIALIZE ZPC BYTE-POINTER + CALL NEWZPC ;GET PAGE TO EXECUTE + JMP NXTINS + + ;MAIN INSTRUCTION INTERPRETATION LOOP +NXTINS: CALL NXTBYT ;GET THE OPERATION BYTE + MOV DX,AX ;SAVE A COPY + CMP AX,80H ;IS IT A 2OP? + JL NXI9 ;YES + CMP AX,0B0H ;NO, IS IT A 1OP? + JGE NXI0A ;NO + JMP NXI12 ;YES +NXI0A: CMP AX,0C0H ;IS IT A 0OP? + JG NXI0B ;NO + JMP NXI13 ;YES +NXI0B: AND AX,3FH ;IT'S EXTENDED, GET THE OPCODE + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET THE OPERATOR POINTER + MOV SI,DS:EXTOP[BP] + CMP SI,0 + JNE NXI0C ;OPERATION EXISTS + JMP NXI14 ;NO SUCH OPERATION +NXI0C: CALL NXTBYT ;GET THE ARGUMENT BYTE + MOV CX,4 ;SPLIT IT INTO 4 2-BIT MODE BYTES +NXI1: PUSH AX + SAR AX,1 + SAR AX,1 + LOOP NXI1 + MOV CX,4 ;RETRIEVE THE 4 BYTES IN PROPER ORDER + SUB DX,DX + MOV BX,OFFSET ARGBLK;FIRST ARGUMENT SLOT +NXI2: POP AX ;GET NEXT MODE BYTE? + AND AX,3 ;CLEAR OFF UNWANTED BITS + CMP AX,3 ;NO MORE ARGUMENTS? + JE NXI4 ;YES, FLUSH ANY OTHER MODE BYTES + CALL GETARG ;ELSE, GET THE NEXT ARGUMENT + MOV [BX],AX ;SAVE IT IN ARGUMENT BLOCK + ADD BX,2 + INC DX ;REMEMBER NUMBER OF ARGS GOTTEN +NXI3: LOOP NXI2 ;LOOP FOR REST OF MODE BYTES + JMP NXI5 +NXI4: DEC CX ;DETERMINE NUMBER OF REMAINING MODE BYTES + SHL CX,1 ;WORD COUNT + ADD SP,CX ;FLUSH THEM +NXI5: XCHG CX,DX + MOV AX,CX ;NUMBER OF ARGS GOES HERE FOR OPERATOR TO USE + CMP CS:BYTE PTR [SI],90H ;DOES OPERATOR WANT ARGBLK POINTER? + JE NXI8A ;YES, CALL OPERATOR NOW + DEC CX ;NO, IT WANTS ARGS IN REGISTERS + JL NXI8A ;NO ARGS, JUST CALL OPERATOR + JE NXI8 ;1 ARG, GET IT + SUB CX,2 + JL NXI7 ;2 ARGS + JE NXI6 ;3 ARGS + MOV DX,ARGBLK+6 ;ELSE, 4 ARGS, GET 4TH +NXI6: MOV CX,ARGBLK+4 ;GET 3RD +NXI7: MOV BX,ARGBLK+2 ;GET 2ND +NXI8: MOV AX,ARGBLK ;GET FIRST ARG +NXI8A: JMP NXI15 ;AND CALL OPERATOR +NXI9: AND AX,1FH ;2OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;FIND POINTER TO OPERATOR ROUTINE + MOV SI,DS:EXTOP[BP] + CMP SI,0 + JE NXI14 ;NO SUCH OPERATION + MOV AX,1 ;ASSUME FIRST ARG IS AN IMMEDIATE + TEST DX,40H ;IS IT INSTEAD A VARIABLE? + JE NXI10 ;NO + INC AX ;YES, CHANGE MODE +NXI10: CALL GETARG ;GET THE FIRST ARG + PUSH AX ;SAVE IT + MOV AX,1 ;ASSUME SECOND ARG IS AN IMMEDIATE + TEST DX,20H ;IS IT INSTEAD A VARIABLE? + JE NXI11 ;NO + INC AX ;YES, CHANGE MODE +NXI11: CALL GETARG ;GET THE SECOND ARG + MOV BX,AX ;POSITION IT + POP AX ;RECOVER FIRST ARG + CMP CS:BYTE PTR [SI],90H ;DOES ROUTINE WANT ARGUMENT BLOCK? + JNE NXI15 ;NO, GO CALL IT + MOV ARGBLK,AX ;YES, MOVE ARGS TO ARGBLK + MOV ARGBLK+2,BX + MOV AX,2 ;ALWAYS 2 ARGS + JMP NXI15 ;NOW CALL OPERATOR +NXI12: AND DX,0FH ;1OP, EXTRACT OPERATION BITS + SHL DX,1 ;MAKE IT A WORD OFFSET + MOV BP,DX ;GET OPERATOR ROUTINE POINTER + MOV SI,DS:ONEOP[BP] + CMP SI,0 + JE NXI14 ;ILLEGAL OPERATION + SAR AX,1 ;EXTRACT MODE BITS + SAR AX,1 + SAR AX,1 + SAR AX,1 + AND AX,3 + CALL GETARG ;GET THE ARGUMENT + JMP NXI15 ;AND CALL OPERATOR +NXI13: AND AX,0FH ;0OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET OPERATOR ROUTINE POINTER + MOV SI,DS:ZEROOP[BP] + CMP SI,0 + JNE NXI15 ;IT'S A LEGAL OPERATION +NXI14: MOV AX,OFFSET FTL5 + JMP FATAL +NXI15: CALL SI ;CALL THE OPERATOR ROUTINE + JMP NXTINS ;AND LOOP FOR NEXT INSTRUCTION + + ;NORMALIZE ZPC & GET PROPER PAGE +NEWZPC: PUSH SI ;SAVES + PUSH BP + PUSH BX + PUSH CX + PUSH DX + SUB AX,AX ;USE DOUBLE-WORD ARITHMETIC + MOV BX,ZPC1 ;GET BLOCK-POINTER + MOV BH,BL ;POSITION IT + SUB BL,BL + SHL BX,1 + ADC AX,0 + MOV SI,ZPC2 ;GET BYTE-OFFSET + XCHG SI,AX ;DOUBLE-WORDIFY IT (MIGHT BE NEGATIVE) + CWD + XCHG SI,AX + ADD BX,SI ;ADD IT TO OTHER DOUBLE WORD + ADC AX,DX + MOV DX,BX + AND DX,1FFH ;EXTRACT BYTE-OFFSET + MOV ZPC2,DX ;SAVE IT + MOV CL,9 ;EXTRACT BLOCK-POINTER + SAR BX,CL + AND BX,7FH + TEST AX,1 ;TEST 17TH BIT + JE NWZ1 ;WAS 0 + OR BX,80H ;WAS 1, SET PROPER BIT IN BLOCK-POINTER +NWZ1: MOV ZPC1,BX ;SAVE IT + CMP BX,CURBLK ;HAS IT CHANGED? + JE NWZ5 ;NO + MOV CURBLK,BX ;YES, REMEMBER NEW BLOCK + MOV AX,CURTAB ;IS OLD PAGE IN PAGING SPACE? + CMP AX,0 + JE NWZ2 ;NO + MOV BP,AX ;YES, STORE CURRENT REF TIME FOR OLD PAGE + MOV CL,RTIME1 + MOV DS:[BP],CL + MOV CX,RTIME2 + MOV DS:1[BP],CX + INC AX +NWZ2: CMP BX,ENDLOD ;NEW PAGE ALREADY IN CORE? + JL NWZ3 ;YES + MOV AX,BX ;NO, GET NEW PAGE + CALL GETPAG + MOV BX,AX + MOV AX,LPTAB ;GET NEW PAGE TABLE POINTER + INC AX ;POINT TO REF SLOT + MOV CURTAB,AX ;SAVE THIS POINTER FOR LATER + MOV BP,AX ;STORE HIGHEST RTIME TO KEEP PAGE FOR US + MOV DS:BYTE PTR [BP],-1 + MOV DS:WORD PTR 1[BP],-1 + INC AX + JMP NWZ4 +NWZ3: MOV CL,9 ;CALCULATE PAGE ADDRESS + SHL BX,CL + MOV CURTAB,0 ;CLEARING POINTER MEANS PAGE IS PRELOADED +NWZ4: MOV CURPAG,BX ;UPDATE PAGE POINTER +NWZ5: POP DX ;RESTORES + POP CX + POP BX + POP BP + POP SI + RET ;AND RETURN + + ;GET THE PAGE WHOSE NUMBER IS IN AX, RETURN A POINTER TO IT IN AX +GETPAG: CMP AX,LPAGE ;IS THIS THE SAME PAGE AS LAST REFERENCED? + JNE GTP1 ;NO + MOV AX,LPLOC ;YES, WE ALREADY HAVE LOCATION + RET ;RETURN IT + +GTP1: MOV LPAGE,AX ;SAVE NEW PAGE NUMBER + PUSH CX ;SAVES + PUSH BX + ADD RTIME2,1 ;UPDATE REFERENCE TIME (COUNT) + ADC RTIME1,0 + MOV BX,OFFSET PAGTAB;PAGE INFORMATION TABLE +GTP2: INC BX + CMP AL,-1[BX] ;SEARCH FOR DESIRED BLOCK + JNE GTP3 ;NOT IT + CMP AX,CURBLK + JE GTP2A + MOV CL,RTIME1 + MOV [BX],CL ;FOUND IT, UPDATE ITS REFERENCE TIME + MOV CX,RTIME2 + MOV 1[BX],CX +GTP2A: DEC BX ;BACKUP TO BEGINNING OF TABLE ENTRY + MOV LPTAB,BX ;SAVE IT + SUB BX,OFFSET PAGTAB;CALCULATE ADDRESS OF PAGE + MOV CL,7 + SHL BX,CL + ADD BX,PAGES + JMP GTP4 ;AND RETURN PAGE POINTER +GTP3: ADD BX,3 ;SKIP REFERENCE TIME + CMP WORD PTR [BX],-1;END OF TABLE? + JNE GTP2 ;NO, CONTINUE SEARCH + CALL FINDPG ;YES, FIND A PAGE TO LOAD INTO + PUSH AX ;PAGE POINTER + MOV LPTAB,BX ;SAVE PAGE TABLE POINTER + MOV AX,LPAGE ;SAVE NEW BLOCK NUMBER + MOV [BX],AL + MOV CL,RTIME1 + MOV 1[BX],CL ;AND CURRENT REF TIME + MOV CX,RTIME2 + MOV 2[BX],CX + POP BX ;PAGE POINTER + CALL GETBLK ;GET THE BLOCK +GTP4: MOV AX,BX ;RETURN PAGE POINTER + MOV LPLOC,AX ;AND SAVE IT FOR LATER + POP BX ;RESTORES + POP CX + RET + + ;FIND A GOOD PAGE, RETURN PAGE POINTER IN AX & PAGTAB POINTER IN BX +FINDPG: PUSH CX + MOV BX,OFFSET PAGTAB + MOV CX,-1 ;FAKE BEST-CASE REFERENCE COUNT + MOV DX,CX + INC BX ;SKIP BLOCK NUMBER FOR NOW +FNP1: INC BX ;IS THIS REF TIME WORSE THAN CURRENT WORST? + CMP -1[BX],CL + JA FNP3 ;NO + JB FNP2 ;YES + CMP [BX],DX ;MAYBE, COMPARE LOW-ORDER WORDS, WORSE? + JAE FNP3 ;NO +FNP2: MOV CL,-1[BX] ;YES, SAVE ITS REF COUNT + MOV DX,[BX] + MOV AX,BX ;AND LOCATION (+2) +FNP3: ADD BX,3 ;SKIP SECOND WORD + CMP BYTE PTR [BX]-1,-1 ;LOOP UNTIL END OF TABLE + JNE FNP1 + INC CX ;WAS A PAGE REALLY FOUND? + JE FNP4 ;NO, GROSS BUG! + SUB AX,2 ;YES, CALCULATE CORE LOCATION OF PAGE + MOV BX,AX + SUB AX,OFFSET PAGTAB + MOV CL,7 + SHL AX,CL + ADD AX,PAGES + POP CX ;RESTORES + RET +FNP4: MOV AX,OFFSET FTL6 + JMP FATAL + + ;SYSTEM INITIALIZATION +SYSINI: MOV CL,CFOPEN ;OPEN CODE + MOV DX,OFFSET GAMFCB + PUSH ES + INT 224 ;OPEN FILE + POP ES + CMP AL,0FFH + JE SYSFTL + MOV DX,ES + MOV CL,CSDMAB ;SET DMA BASE + PUSH ES + INT 224 + POP ES + RET ;**THIS CHECKS # DRIVES, ETC. + +SYSFTL: MOV AX,OFFSET FTL9 + JMP FATAL + +CLRSCR: RET ;**THIS SHOULD CLEAR THE SCREEN + + ;READ A CHARACTER INTO AX, WAITING UNTIL ONE IS AVAILABLE, NO ECHO +M_CHRI: PUSH CX + PUSH DX + CMP CHRFLG,0 + JNZ MCHR1 + MOV CHRFLG,1 + ;**INITIALIZE RANDOM NUMBER STUFF +MCHR1: MOV CL,CCONIN + PUSH ES + INT 224 ;GET A CHARACTER + POP ES + SUB AH,AH + POP DX + POP CX + RET + + ;PRINT THE CHARACTER IN AL, FOREGROUND IN AH +M_TTYO: PUSH AX + PUSH BX ;SAVES + PUSH CX + PUSH DX + PUSH BP + PUSH AX + MOV CL,CCONIO + MOV DL,AL + PUSH ES + INT 224 ;CHUCK IT + POP ES + POP AX + CMP SCRFLG,0 + JZ MTYO1 + CALL PRTOUT +MTYO1: POP BP ;RESTORES + POP DX + POP CX + POP BX + POP AX + RET + + ;PRINT SPACES, WITHOUT MOVING CURSOR, NUMBER IN AL, ATTRIBUTE IN AH +M_SPC: RET + + ;PRINT A CARRIAGE RETURN/LINE FEED, WITH MORE MODE (ASSUMING SCREEN + ;BOTTOM) +M_CRLF: PUSH AX ;SAVES + PUSH BX + PUSH CX + PUSH DX + PUSH BP + INC MORLIN ;INCREMENT NUMBER OF LINES OUTPUT + MOV CL,CCONIO + MOV DL,13 + PUSH ES + INT 224 ;PRINT CRLF + POP ES + MOV CL,CCONIO + MOV DL,10 + PUSH ES + INT 224 + POP ES + MOV AL,SLPP + CMP MORLIN,AL ;FULL PAGE OUTPUT? + JL MCR1 ;NOT YET + MOV MORLIN,0 ;RESET COUNTER + MOV AX,OFFSET MORE + CALL M_PRNT + CALL M_CHRI ;READ A CHARACTER TO CONTINUE + MOV AX,OFFSET EMORE + CALL M_PRNT ;FLUSH THE MORE STUFF +MCR1: CMP SCRFLG,0 + JE MCR2 + CALL PRTCRL ;CRLF TO PRINTER +MCR2: POP BP ;RESTORES + POP DX + POP CX + POP BX + POP AX + RET + + ;OUTPUT STATUS LINE HERE + +M_SOUT: MOV BX,OFFSET SBLINE + CALL M_SPRT + MOV CL,09H + MOV DX,SLSTR + PUSH ES + INT 224 + POP ES + MOV BX,OFFSET SELINE + CALL M_SPRT + RET + +M_SPRT: PUSH ES + MOV CL,BYTE PTR [BX] + SUB CH,CH + CMP CL,0 + JE MSPRT1 +MSPLP: INC BX + MOV DL,BYTE PTR [BX] + PUSH CX + MOV CL,06H + PUSH BX + INT 224 + POP BX + POP CX + LOOP MSPLP +MSPRT1: POP ES + RET + +M_INIT: MOV BX,OFFSET STINIT + CALL M_SPRT + MOV BX,OFFSET SELINE + CALL M_SPRT + RET + + ;PRINT A STRING, POINTER (TO DATA SEGMENT) IN AX, WHITE FOREGROUND +M_PRNT: PUSH BX ;SAVE BX + MOV BX,AX ;STRING POINTER +MPR1: MOV AL,[BX] ;GET NEXT CHARACTER + CMP AL,0 ;END OF LINE, WITH CRLF? + JE MPR2 ;YES + CMP AL,80H ;END OF LINE, NO CRLF? + JE MPR3 ;YES + CALL M_TTYO ;PRINT CHARACTER + INC BX ;POINT TO NEXT CHARACTER + JMP MPR1 ;REPEAT +MPR2: CALL M_CRLF ;PRINT A CRLF +MPR3: POP BX ;RESTORE BX + RET + + ;GET TIME +M_TIME: RET + + ;GET A GAME FILE BLOCK, BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX +GETBLK: PUSH CX ;SAVE + MOV CX,1 ;CALL GTBLKS FOR 1 BLOCK ONLY + CALL GTBLKS + POP CX ;RESTORE + RET + +SRBLKS: MOV DSKFCB,OFFSET SAVFCB + JMP GTBKI + + ;GET A SERIES OF GAME FILE BLOCKS, + ;FIRST BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX # OF BLOCKS IN CX + +GTBLKS: MOV DSKDIR,0 ;READ MODE + MOV DSKFCB,OFFSET GAMFCB ;GAME MODE +GTBKI: PUSH BX + PUSH DX ;SAVES + PUSH BP + SHL AX,1 ;CONVERT TO 128-BYTE BLOCKS + SHL AX,1 + SHL CX,1 ;AND FOUR TIMES AS MANY OF THEM + SHL CX,1 + MOV GTBSTT,AX + MOV GTBCOR,BX + MOV GTBCNT,CX ;SAVE THESE +GTBLP: MOV CL,CSDMAO + MOV DX,BX + PUSH ES + INT 224 ;SET DMA ADDRESS + POP ES + MOV AX,GTBSTT ;GET STARTING BLOCK # + MOV BX,DSKFCB ;GET FCB + MOV 33[BX],AX ;SET RANDOM READ/WRITE SLOT + MOV CL,CRDRND + CMP DSKDIR,0 + JE GTBKIR + MOV CL,CWRRND +GTBKIR: MOV DX,DSKFCB + PUSH ES + INT 224 ;DO THE OPERATION + POP ES + CMP AL,0 + JNE GTB2 ;FATAL IF FAILS (FOR NOW) + DEC GTBCNT ;CHECK IF DONE + JZ GTBFIN + ADD GTBCOR,128 ;ADD TO CORE LOCATION + MOV BX,GTBCOR + INC GTBSTT ;AND BLOCK ADDRESS + JMP GTBLP + +GTBFIN: CLC +GTBOUT: POP BP + POP DX + POP BX + RET + +GTB2: CMP DSKFCB,OFFSET GAMFCB + JE GTB3 + STC + JMP GTBOUT + +GTB3: MOV AX,OFFSET FTL7 + JMP FATAL + +FATAL: PUSH AX + CALL M_CRLF + MOV AX,OFFSET FATHDR + CALL M_PRNT + POP AX + CALL M_PRNT +FINISH: MOV BX,OFFSET STRESET + CALL M_SPRT + MOV CL,CRESET + MOV DL,0 + INT 224 + + ORG 1500H + +; CONSTANTS FROM EVERYWHERE + +ZVERSN EQU 'C' ;ZIP VERSION NUMBER +ZMVERS EQU 3 ;Z-MACHINE VERSION NUMBER +LSTACK EQU 256 ;LENGTH OF USER STACK(MUST BE 1 PAGE FOR NOW) + +EOICHR EQU 15 ;CARRIAGE RETURN IS NORMAL END OF INPUT +EOLCHR EQU 10 ;LINE-FEED IS END-OF-LINE CHARACTER +PADCHR EQU 5 ;ZSTR PADDING CHARACTER + +CRESET EQU 0H ;SYSTEM RESET +CCONIN EQU 1H ;CONSOLE INPUT +CCONIO EQU 6H ;CONSOLE I/O +CRDLIN EQU 0AH ;BUFFERED CONSOLE READ +CFOPEN EQU 0FH ;FILE OPEN +CFCLOS EQU 10H ;FILE CLOSE +CFDELE EQU 13H ;FILE DELETE +CRDSEQ EQU 14H ;READ SEQUENTIAL +CFMAKE EQU 16H ;FILE MAKE +CSDMAO EQU 1AH ;SET DMA OFFSET +CRDRND EQU 21H ;READ RANDOM +CWRRND EQU 22H ;WRITE RANDOM +CSDMAB EQU 33H ;SET DMA BASE +CFNMEM EQU 35H ;FILE MEMORY BLOCK +CALMEM EQU 37H ;ALLOCATE MEMORY + +PVERS1 EQU 0 ;POSITION OF ZVERSION VERSION BYTE +PVERS2 EQU 1 ;ZVERSION MODE BYTE +PZRKID EQU 2 ;ZORKID +PENDLD EQU 4 ;ENDLOD +PSTART EQU 6 ;START +PVOCTB EQU 10Q ;VOCAB +POBJTB EQU 12Q ;OBJECT +PGLOTB EQU 14Q ;GLOBALS +PPURBT EQU 16Q ;PURBOT +PFLAGS EQU 20Q ;USER FLAG WORD +PSERNM EQU 22Q ;SERIAL NUMBER (6 BYTES) +PWRDTB EQU 30Q ;WORDS +PLENTH EQU 32Q ;LENGTH OF GAME +PCHKSM EQU 34Q ;CHECKSUM FOR GAME +LMOUTB EQU 80 ;MAX LENGTH OF OUTBUF, EXCLUDING TERMINAL 0 +LDOUTB EQU 80 ;DEFAULT LENGTH OF OUTBUF +LPAGES EQU 128 ;MAX NUMBER OF PAGES EXPECTED +LXBYTS EQU LSTACK+LMOUTB+(4*LPAGES)+2000Q ;LENGTH OF EXTRA BYTES NEEDED + +DSEG + ORG 100H +SCPL DB 79 ;CHARACTERS/LINE +SLPP DB 22 ;LINES/PAGE +SNAME RB 8 ;NAME OF THE GAME +SCLF DB 1 ;PRINT LF AFTER CR ON CONSOLE +SLLF DB 1 ;PRINT LF AFTER CR ON PRINTER +SINV DB 0 ;ADD-ON FOR INVERSE VIDEO +STINIT DB 23 ;TERMINAL INIT + DB 27,'[2J',27,'[2;24r',27,'[0m',27,'[01;00H' + ORG 12DH +STRESET DB 14 ;TERMINAL RESET + DB 27,'[1;24r',27,'[24;0H' + ORG 14DH +SBLINE DB 12 ;BEGIN STATUS LINE + DB 27,'[7m',27,'[01;00H' + ORG 16DH +SELINE DB 12 ;END STATUS LINE + DB 27,'[0m',27,'[24;00H' + ORG 18DH +SPINIT DB 0 ;PRINTER INIT + ORG 200H + + ;VARIABLE DEFINITIONS: + + ;SCRIPTING STUFF +SCRFLG DB 0 +PRNRDY DB ' * Printer not ready: Abort or Retry? ',80H + + ;GTBLKS +GAMFCB DB 0,'SEASTALKDAT' ;FCB FOR THE GAME FILE + RB 30 +SAVFCB DB 0,'SEASTALKSAV' ;FCB FOR SAVE/RESTORE + RB 30 +CNFFCB DB 0,'INTERLOGCNF' ;FCB FOR CONFIGURATION FILE + RB 30 +DSKFCB DW 0 ;CONTAINS FCB FOR DISK OPERATION +DSKDIR DB 0 ;0 FOR READ, 1 FOR WRITE +GTBCNT DW 0 ;REMAINING BLOCKS TO BE READ +GTBSTT DW 0 ;STARTING BLOCK +GTBCOR DW 0 ;STARTING CORE ADDRESS + ;OPRAND +RNDFLG DB 0 +RSEED DW 0 ;SEED FOR RANDOM NUMBERS + ;READ +RDWSTR DW 0,0,0,0 ;WORD STRING BUFFER FOR ZWORD +RDBOS DW 0 ;BEGINNING OF STRING POINTER +RDEOS DW 0 ;END OF STRING POINTER +RDRET DW 0 ;RETURN TABLE POINTER +RDNWDS DB 0 ;NUMBER OF WORDS READ + ;PUTSTR +WRDOFF DW 0 ;OFFSET INTO WORD TABLE FOR CURRENT SET + ;PUTCHR +CHRPTR DW 0 ;POINTS TO NEXT CHARACTER POSITION +ENDBUF DW 0 ;POINTS JUST PAST END OF OUTPUT BUFFER (0) + ;GETNUM +STATUS DW 0 ;STATUS-LINE-REQUESTED FLAG + ;ZIPBGN +IRBRKS DB ' ',9,13,12,'.,?',0 ;INITIAL SET OF READ BREAK CHARS +MEMTOP DW 0 ;LAST AVAILABLE LOCATION +ZORKID DW 0 ;UNIQUE GAME & VERSION IDENTIFIER +ENDLOD DW 0 ;ENDLOD BLOCK NUMBER +VOCTAB DW 0 ;SAVE VOCABULARY TABLE POINTER +OBJTAB DW 0 ;OBJECT TABLE POINTER +GLOTAB DW 0 ;GLOBAL TABLE POINTER +WRDTAB DW 0 ;WORD TABLE POINTER +PURBOT DW 0 ;PURE CODE POINTER +ESIBKS DW 0 ;END OF SELF-INSERTING BREAK CHARACTERS +VWLEN DW 0 ;NUMBER OF BYTES IN A VOCABULARY WORD ENTRY +VWORDS DW 0 ;NUMBER OF WORD ENTRIES IN VOCABULARY +VOCBEG DW 0 ;BEGINNING OF ACTUAL VOCABULARY +OUTBUF RB 81 ;OUTPUT BUFFER +INBUF RB 150 ;INPUT BUFFER +RBRKS RB 32 ;STRING OF READ BREAK CHARACTERS +PAGTAB DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 254,0,0,0,254,0,0,0,254,0,0,0,254,0,0,0 + DB 255 ;END OF PAGE TABLE +PAGES DW 0 ;SWAPPING AREA +BUFPGS DW 0 +CHRFLG DB 0 + + ;RESTRT +ZLOCS DW 0 ;POINTER TO LOCALS +ZPC1 DW 0 ;ZPC BLOCK-POINTER +ZPC2 DW 0 ;ZPC BYTE-POINTER +ARGBLK RW 4 ;ARGUMENT BLOCK FOR EXTENDED OPERATIONS + ;NEWZPC +CURPAG DW 0 ;CURRENT PAGE (WHERE ZPC IS) POINTER +CURBLK DW 0 ;CURRENT BLOCK, USUALLY SAME AS ZPC1 +CURTAB DW 0 ;CURRENT PAGE TABLE POINTER +1 + ;GETPAG +RTIME1 DB 0 ;REFERENCE TIME, 1 1/2 WORDS USED +RTIME2 DW 0 +LPAGE DW 0 ;LAST REFERENCED PAGE NUMBER +LPLOC DW 0 ;AND ITS CORE LOCATION +LPTAB DW 0 ;AND ITS TABLE POINTER + + ;OPERATION TABLES: + ;ZERO ARGUMENT OPERATIONS +ZEROOP DW OPRTRU ;176 + DW OPRFAL ;177 + DW OPPRNI ;178 + DW OPPRNR ;179 + DW OPNOOP ;180 + DW OPSAVE ;181 + DW OPREST ;182 + DW OPRSTT ;183 + DW OPRSTA ;184 + DW OPFSTA ;185 + DW OPQUIT ;186 + DW OPCRLF ;187 + DW OPUSL ;188 + DW OPVERI ;189 + DW 0 ;190 + DW 0 ;191 + + ;ONE ARGUMENT OPERATIONS +ONEOP DW OPQZER ;128 + DW OPQNEX ;129 + DW OPQFIR ;130 + DW OPLOC ;131 + DW OPPTSI ;132 + DW OPINC ;133 + DW OPDEC ;134 + DW OPPRNB ;135 + DW 0 ;136 + DW OPREMO ;137 + DW OPPRND ;138 + DW OPRETU ;139 + DW OPJUMP ;140 + DW OPPRIN ;141 + DW OPVALU ;142 + DW OPBCOM ;143 + + ;TWO ARGUMENT AND EXTENDED ARGUMENT OPERATIONS +EXTOP DW 0 ;0 + DW OPQEQU ;1 + DW OPQLES ;2 + DW OPQGRT ;3 + DW OPQDLE ;4 + DW OPQIGR ;5 + DW OPQIN ;6 + DW OPBTST ;7 + DW OPBOR ;8 + DW OPBAND ;9 + DW OPQFSE ;10 + DW OPFSET ;11 + DW OPFCLE ;12 + DW OPSET ;13 + DW OPMOVE ;14 + DW OPGET ;15 + DW OPGETB ;16 + DW OPGETP ;17 + DW OPGTPT ;18 + DW OPNEXT ;19 + DW OPADD ;20 + DW OPSUB ;21 + DW OPMUL ;22 + DW OPDIV ;23 + DW OPMOD ;24 + DW 0 ;25 + DW 0 ;26 + DW 0 ;27 + DW 0 ;28 + DW 0 ;29 + DW 0 ;30 + DW 0 ;31 + DW OPCALL ;224 + DW OPPUT ;225 + DW OPPUTB ;226 + DW OPPUTP ;227 + DW OPREAD ;228 + DW OPPRNC ;229 + DW OPPRNN ;230 + DW OPRAND ;231 + DW OPPUSH ;232 + DW OPPOP ;233 + DW 0 ;234 + DW 0 ;235 + DW 0 ;236 + DW 0 ;237 + DW 0 ;238 + DW 0 ;239 + DW 0 ;240 + DW 0 ;241 + DW 0 ;242 + DW 0 ;243 + DW 0 ;244 + DW 0 ;245 + DW 0 ;246 + DW 0 ;247 + DW 0 ;248 + DW 0 ;249 + DW 0 ;250 + DW 0 ;251 + DW 0 ;252 + DW 0 ;253 + DW 0 ;254 + DW 0 ;255 + + ;.CRLF +MORE DB '**MORE** ',80H +EMORE DB 13,' ',13,80H +MORLIN DB 0 + + ;.GETTM +TIMBLK RB 8 ;WHERE TIME PARAMETERS GO + + ;VERIFY +INTVER DB 'DEC Rainbow 100 Interpreter Version C',0 + + ;SAVE/RESTORE STUFF +SAV0 DB 'Insert save disk then enter file name.',0 +SAV1 DB 'File name (default is ',80H +SAV2 DB '): ',80H +SAV3 DB 'Replace game disk then hit RETURN to continue.',0 + + ;STRING DEFINITIONS + + ;RESTORE +ERR1 DB 'SAVE file not found',0 +ERR3 DB 'Bad file name syntax',0 +ERR4 DB 'No room in directory for SAVE file',0 +ERR5 DB 'No room on disk for SAVE file',0 +ERR6 DB 'Read of SAVE file failed',0 + + ;READ +ERR2 DB 'Too many words typed, flushing: ',80H + + ;OPNEXT/OPPUTP +FTL2 DB 'No such property',0 + ;ZIPBGN +FTL4 DB 'Wrong game or version',0 + ;NXTINS +FTL5 DB 'Illegal operation',0 + ;FINDPG +FTL6 DB 'No free pages',0 + ;GTBLKS +FTL7 DB 'Game file read error',0 + ;SYSINI +FTL9 DB 'Game file not found',0 + ;START +FTL10 DB 'Not enough memory',0 + ;Fatal error header +FATHDR DB 'Fatal error: ',80H + + ;STATUS LINE STUFF + +PMFLAG DB 0 ;AM/PM +TIMEMD DB 0 ;TIME MODE FLAG + +SLSTR DW 0 ;STATUS LINE HEADER STRING +SLTAB DW 0 ;STATUS LINE TABLE USED BY OPUSL + +SLSTAB DW SLS80 + DW SLS80T + DW SLT80 + DW SLT80T + +;RULE HERE: +; 1111111111222222222233333333334444444444555555555566666666667777777 +;1234567890123456789012345678901234567890123456789012345678901234567890123456 + +SLS80 DB ' Score: Moves: ' + +SLS80T DW -1 + DW OPPRND + DW 1 + DW 24 + DW -1 + DW OPPRNN + DW 57 + DW 60 + DW -1 + DW OPPRNN + DW 72 + DW 79 + +;RULE HERE: +; 1111111111222222222233333333334444444444555555555566666666667777777 +;1234567890123456789012345678901234567890123456789012345678901234567890123456 + +SLT80 DB ' Time: ' + +SLT80T DW -1 + DW OPPRND + DW 1 + DW 24 + DW -1 + DW OPPRNH + DW 63 + DW 65 + DW -1 + DW OPPRNM + DW 66 + DW 79 + + ;ZSTR CHARACTER CONVERSION VECTOR + +ZCHRS DB 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + DB ' 0123456789.,!?_#''' ;THIS SHOULD BE QUOTE + DB '"/\-:()' + +MBSTT DW 0 +MBLEN DW 0FFFFH +MBMOR DB 0 + +SSEG + ORG 100H + RW 100H +STK_TOP: +STKBOT RW LSTACK +ZSTK_TP: + DB 0 + END + \ No newline at end of file diff --git a/create/apple.rno b/create/apple.rno new file mode 100644 index 0000000..96b6d5a --- /dev/null +++ b/create/apple.rno @@ -0,0 +1,123 @@ +.c;CREATING AN APPLE ZGAME: DISK FOR A NEW GAME +.s +Before transferring a game to the Apple, a ZGAME: create disk must exist. If +one does not yet exist for a given game, use this procedure to make one. You +will need a ZGAME create disk from a previous game. The new create disk will +be a clone of this one. This procedure should be done on the Apple IIe. +.s +1. Put the disk labelled "PASCAL/APPLE" in the top drive. Put a blank disk in +the bottom drive. +.s +2. Turn on the Apple. (The on-off switch is in the back.) +.s +3. The screen will display a menu. Type "X". +.s +4. You will be asked what file to execute. Type "FORMATTER" and hit return. +.S +5. You will be asked what disk you want to format. Type "5" (which for some +obscure reason refers to the bottom drive) and hit return. +.s +6. When the formatting procedure is done, you will asked again what disk you +want to format. Just hit the Return key to leave the format program. +.s +7. The menu will appear again. Type "F". +.s +8. A different menu will appear. Type "T". +.s +9. Put the ZGAME: create disk for the old game in the top drive. +.s +10. You will be asked what file you wish to transfer. Type "ZGAME:,BLANK:" +and hit return. +.s +11. You will be asked two questions. Type "Y" for both. +.s +12. After the transfer is completed, put the PASCAL/APPLE disk back in the top +drive. +.s +13. Type "Q". The disk in the bottom drive is now the ZGAME: create disk for +the new game. Label it as such. You are now ready to transfer the game to +the Apple. + +.pg +.c;TRANSFERING A GAME FILE FROM THE DEC-20 TO THE APPLE IIe +.s +NOTE: In order to transfer a game to the Apple, a ZGAME: create disk must +exist for that game. If one does not yet exist, follow the instructions on +the previous sheet to make one. +.s +1. Connect the TN20 remote line to the Apple (the flappy plug in the back). +You will need the adapter cable labelled "Apple/Osborne" to do this. +.s +2. Put the disk labelled "PASCAL/APPLE" in the top drive. Put the ZGAME: disk +in the bottom drive. +.s +3. Turn on the Apple. +.s +4. You will see a menu. Type "F" to enter the filer. +.s +5. You will see a different menu. Type "P" to set a prefix. +.s +6. You will be asked for the name of a prefix. Type "ZGAME:" and hit +return. Don't forget the colon. +.s +7. When the menu reappears, type "R" to remove the old game file. +.s +8. You will be asked for the name of a file. Type "GAME". You will +then be asked if you want to update the directory. Type "Y". +.s +9. When the menu reappears, type "Q" to leave the Filer. +.s +10. The original menu will return. Type "X" to execute a program. +.s +11. You will asked for the name of the program. Type "TFTPER" and hit +return. +.s +12. You will be asked for the name of the file. Type "GAME" and hit return. +.s +13. Go to a DEC-20 terminal and run TN20 (see separate instructions for +the use of TN20). +.s +14. A line of A's should begin appearing on both the DEC-20 terminal and the +Apple. The transfer should take around ten minutes. When the transfer +is complete, log off the DEC-20. +.s +15. Go back to the Apple. The ZGAME: create disk now contains the game +file and is ready to be used to make Apple versions of the game. + +.pg +.c;MAKING COPIES OF GAMES FROM THE APPLE ZGAME: DISK +.s +1. Put the disk labelled "PASCAL/APPLE" in the top drive. Put the +ZGAME: create disk for the appropriate game in the bottom drive. +.s +2. Turn on the Apple. +.S +3. A menu should appear on the monitor. Type "X" to execute a program. +.s +4. You will be asked what program you want to execute. Type +"ZGAME:CREATOR" and hit return. +.s +5. You will be instructed to put the destination disk in drive #4. Remove +the PASCAL/APPLE disk from the top drive. Put a blank disk in the top +drive. (It isn't necessary to use an Apple-formatted disk for the blank +disk; the CREATOR program will format the blank disk itself). Close the +door twice to make sure that the disk is seated properly. Hit the +return key. Don't ask why the top drive is called drive #4. +.s +6. The CREATOR program will format the blank disk, and then copy the +game onto it from the create disk. This will take about five minutes. +.s +7. When the copying is complete, you will told to place the next destination +disk in drive #4. At this point, you can make another copy of the game (by +going back to Step 5), or you can abort. +.s +8. Test the new game disk(s) by booting them and typing "$VERIFY" at +the game prompt (>). + +.pg +.c;HOW TO BOOT DISKS ON THE APPLE II or APPLE IIe +.s +This is an easy one. Just put the game disk in the top drive (label +facing up, oval cut-out toward the back). Turn on the Apple monitor. +Finally, turn on the Apple itself (the on-off switch is in the back, +toward the left side). The disk will take about 10 seconds to boot. diff --git a/create/atari.rno b/create/atari.rno new file mode 100644 index 0000000..60b5364 --- /dev/null +++ b/create/atari.rno @@ -0,0 +1,171 @@ +.lm 10;.rm 70;.paragraph 0, 0;.br;.lm 10;.rm 70;.ts 10,18,26,34,42,50,58,66,74,82;.sp 2;.nj;.i 0;_.c_;HOW TO FORMAT DISKS FOR THE ATARI-800 +_.s +NOTE: If you are making masters to send to Dysan, do not format the +disks yourself. Dysan will not be able to read them. Instead, use the +Atari-formatted disks that Dysan sends us. They should be in the Atari +diskholder or in a box on one of the higher shelves. +_.s +1) Put the Assembler/Editor cartridge in the left-hand compartment of +the CPU. +_.s +2) Put the disk labelled "Atari DOS and Z Utitlies" in the top disk +drive, labelled 'Drive 1'. +_.s +3) Turn on the monitor and the disk drive(s), then turn on the CPU. The +on-off switch is on the right side. Make sure the hatch is closed. +_.s +4) The screen will say "EDIT". Type "DOS". +_.s +5) A menu of options will appear. Type "I" to format a disk. +_.s +6) You will be asked for a drive number. If you are only using one +drive, remove the Utilities disk from Drive 1. Put a blank disk in +Drive 1 and type "1". If you are using both drives, put the blank disk +in the bottom drive, labelled Drive 2, and type "2". +_.s +7) Before you begin the formatting process, make sure that the Utilities +disk is NOT in the drive you are about to format with, or it will get +destroyed. Type "Y" to begin the formatting process. +_.s +8) Formatting will take about a minute. If you wish to format another +disk, repeat the process. +.sp 1;.s 1;.sp 2;_.pg +_.c_;TRANSFERING A GAME FILE FROM THE DEC-20 TO THE ATARI 800 +_.s +NOTE: If you are making masters to send to Dysan, do not format the +disks yourself. Dysan will not be able to read them. Instead, use the +Atari-formatted disks that Dysan sends us. They should be in the Atari +diskholder or in a box on one of the higher shelves. +_.s +1) Before you begin, make sure that you have as many Atari-formatted +blank disks as you need. You will need one for every one-disk game you +copy (such as Zork I), and two for every two-disk game you copy (such as +Deadline). +_.s +2) Put the Assembler/Editor cartridge in the left-hand cartridge compartment +of the CPU. +_.s +3) Put the disk labelled "Atari DOS and Z Utilities" in the top disk +drive, labelled Drive 1. +_.s +4) Make sure all the peripherals that you're using (disk drives, +monitor, and interface module) are plugged in and turned on. Plug the +TN20 line into the cable from the interface module. +_.s +5) Turn on the CPU. (For the CPU to be activated, the hatch must be +closed and the power switch on the right side must be set to 'ON'.) +_.s +6) The screen will say "EDIT". Type "DOS". +_.s +7) The screen will display a menu of options. Type "L". +_.s +8) You will be asked "LOAD FROM WHAT FILE_?" Type "TFTP.OBJ". +_.s +9) You will be asked something else. Type "B". (The disk drive should +run at this point. If it doesn't, see Footnote 1.) +_.s +10) The screen will say "EDIT". Type "BUG". +_.s +11) If you are only using one drive, replace the DOS _& Z UTILITIES disk +with a blank Atari-formatted disk. If you are using both drives, put the +blank Atari-formatted disk in the bottom drive, labelled 'Drive 2'. +_.s +12) The screen will say "DEBUG". Type "C6294_<0C". +_.s +13) The screen will say "DEBUG" again. If you are only using one drive, +type "C6005_<1" to instruct the copy program to copy to drive one. If +you are using both drives, skip this step. +_.s +14) The screen will say "DEBUG" again. Type "C6003_<1,0". +_.s +15) The screen will say "DEBUG" again. Type "G6000". (Nothing should +appear on the screen at this point. If a complex error message appears, +check to make sure that the interface module is turned on and connected +properly, and read Footnote 1). +_.s +16) Before running TN20, make sure that the Utilities disk is not in the +drive you are about to copy to, or you will erase it. +_.s +17) Log onto the DEC-20 and follow the instructions for running TN20. +The file that you want to transfer at this point is called ZIP.ATR and +is located in the Z: directory. +_.s +18) ZIP.ATR, the Atari interpreter, should now begin transferring to the +blank disk in the Atari. A line of A's should appear on the Atari's +screen. Transferring ZIP.ATR should only take one or two minutes. +_.s +19) When the transfer is complete, the Atari screen will say "DEBUG". +Type "C6003_<39,0". +_.s +20) The screen will say "DEBUG" again. Type "G6000". +_.s +21) If you are transferring a one-disk game (smaller than 84,972 bytes), +run TN20 and send the game file. If you are transferring a two-disk +game, run TN20 and send the [name-of-game].PRE file. (Make sure that the +game file has been SPLIT.) +_.s +22) A line of A's should begin appearing on the Atari monitor. The game +file will take about 15 minutes to transfer_; the [game].PRE file will +only take about 5 minutes. +_.s +23) If you are transferring a one-disk game, go to Step 29. If you +are transferring a two-disk game, go on to the next step. +_.s +24) Replace the disk which now contains ZIP.ATR and [game].PRE with a +blank Atari-formatted disk. +_.s +25) The Atari screen should read "DEBUG". Type "C6003_<1,0". +_.S +26) The screen will say "DEBUG" again. Type "G6000." +_.s +27) Run TN20 and transfer the [name-of-game].PUR file. +_.s +28) Once again, a line of A's should appear on the Atari monitor. The +[game].PUR file should take about 15 minutes to transfer. +_.s +29) The game disk(s) should now be complete. Remove the Assembler/Editor +cartridge from the CPU, and boot the disk(s). When the game cursor +appears, type "$verify" to make sure that the game transferred correctly. +_.s 3 +FOOTNOTE 1: If the disk drive fails to run after Step 9, or if you get +a long error message after Step 15, it may be because the MEM.SAV file +has been somehow deleted from the Utilities disk. Reboot the Utilities +disk, go to the DOS menu of options, and type "N". Answer the next +question by typing "Y". When you are prompted again, start the copy +procedure over again from Step 1. +.sp 1;.s 1;.sp 2;_.pg +_.c_;COPYING ATARI DISKS +_.s +1) Put the disk labelled "Atari RZUTIL" in the top disk drive. Make sure that +the drives are both plugged in and powered on, and then turn on the CPU. +_.s +2) The screen will display a menu of two options. Type "D". +_.s +3) Place the disk to be copied in the bottom drive. +_.s +4) Place a blank disk in the top drive. +_.s +5) Hit RETURN. Wait a while. Check to make sure the new copy is okay. +_.s +6) If the copy procedure isn't working, turn off the Atari. Go away for an +hour. Come back and try again. +.sp 1;.s 1;.sp 2;_.pg +_.C_;HOW TO BOOT DISKS ON THE ATARI-800 +_.s +1) Turn on the Atari monitor and the top disk drive, labelled 'Drive 1'. +_.s +2) When the drive has stopped running, put the disk in the drive, with +the label facing up and the oval cutout toward the rear. (You'll know +when the drive has stopped running because it will stop making noise. +Also, the active light, the upper of the two small red lights, will go +off). +_.s +3) Close the drive door. +_.s +4) Turn on the CPU. The on-off switch is on the right side of the CPU. +The CPU cartrdige hatch must also be closed for the CPU to activate. +_.s +5) The game should appear in about 30 seconds. If it is a two-disk game, +you be instructed when to insert the second disk. Always wait until the +drive stops running before you remove or insert a disk. +.br;.j;.ts 10,18,26,34,42,50,58,66,74,82;.sp 1; \ No newline at end of file diff --git a/create/c64.rno b/create/c64.rno new file mode 100644 index 0000000..ccec24f --- /dev/null +++ b/create/c64.rno @@ -0,0 +1,148 @@ +.c;HOW TO FORMAT DISKS FOR THE COMMODORE 64 +.s 2 +1. Turn on the monitor, disk drive and CPU. +.s +2. Put the create disk in the disk drive. +.s +3. The monitor should say READY. Type LOAD"FORMAT",8 and hit the return +key. +.s +4. When the monitor says READY, replace the create disk with a blank +disk. Type RUN and hit the return key. +.s +5. You will be asked NAME? Type the full name of the game to be +tranferred to that disk, and hit the return key. +.s +6. The blank disk in thr drive will now be formatted. It will take about +a minute or two. +.s +7. When the formatting procedure is complete, the monitor will say READY +again. Type LOAD"$",8 and hit the return key. +.s +8. The monitor will say READY. Type LIST and hit the return key. +.s +9. The monitor will say [N BLOCKS FREE] where N is the number of free +blocks on your newly-formatted disk. + +.pg +.c;TRANSFERRING A GAME FROM THE PDP-11 TO THE COMMODORE 64 +.S 2 +NOTE: Since TN20 will not work for sending files to the Commodore, you +must transfer game files from the PDP-11. Therefore, before beginning +the following procedure, first make sure that the current version of the +game file is in the PDP-11's INT directory. If not, then follow the +instructions for transferring a game file from the DEC-20 to the PDP-11. +.s +1. Turn on the Commodore's monitor, disk drive, and CPU. Plug the cable +labelled "TN" (not TN20) into the Commodore. +.s +2. Put the create disk in the disk drive. (Note that there is just one +create disk for every game, not a separate disk for each game as is the +case on most other micros.) +.s +3. The monitor should say READY. Type LOAD"RCV",8 and hit the return key. +.s +4. Replace the create disk with a blank formatted disk. You can format +this disk yourself by following the formatting procedure on the previous +page. Preferably, use one of the Dysan pre-formatted disks that should +be in the Commodore disk tray. +.s +5. The monitor should say READY. Type RUN and hit the return key. +.s +6. The monitor will say (Z) ZIP OR (G) GAME? At this point, you want +to transfer the Commodore interpreter from the PDP-11, so type Z and hit +the return key. +.s +7. Log onto the PDP-11. (If you want to log onto the PDP-11 from a +DEC-20 account, type 11 at the @-prompt. A prompt that looks like "20>" +will appear. Type C to connect to the PDP-11.) If you don't have an +account on the PDP-11, you can log onto account 3,3. The password is GAMES. +.s +8. When you see the PDP-11's period-prompt, type INT and hit the return +key in order to connect to the INT directory. +.s +9. Check to make sure that the two switches on the side of the PDP-11 +are set to 1200 baud. +.s +10. The PDP-11 terminal should be displaying the period-prompt again. +Type TN and hit the return key. +.s +11. You will get a prompt that looks like "TN>". Type S. +.s +12. You will be asked for the name of the file you want to send. At this +point, you want to send the Commodore interpreter. Type ZIP.C64 and hit +the return key. +.s +13. You will told [N blocks], the size of the Commodore interpreter. The +"TN>" prompt will re-appear. Type B. +.s +14. Shortly, a line of A's will begin appearing on the PDP-11 terminal, +and a line of dots will begin appearing on the Commodore monitor. Often, +the first block will not transfer on the first attempt, and a T will +appear at the beginning of the line of A's. Don't worry about it. +.s +15. The interpreter will take around two or three minutes to transfer. +The Commodore monitor should say READY, and the PDP-11 terminal should +be displaying the "TN>" prompt. +.s +16. Replace the game disk with the create disk. Type LOAD"RCV",8 and hit +the return key. +.s +17. The monitor will say READY. Replace the create disk with the game +disk. Type RUN and hit return. +.s +18. You will once again be asked whether you want to transfer the +interpreter or the game file. This time, you want to transfer the game, +so type G and hit return. +.s +19. Return to the PDP-11 terminal, which should be displaying the "TN>" +prompt. Type S. +.s +20. You will be asked what file you want to send. Type the six +letter PDP-11 abbreviation for that particular game, followed by .IML +(Some examples: ZORK1.IML, DEADLN.IML SUSPEN.IML). Hit the return key. +.s +21. You will be told [N blocks], the size of the file to be transferred, +and then the "TN>" prompt will reappear. Type B to begin the transfer. +.s +22. The transfer will take 20 to 30 minutes. Lots of A's should appear +on the PDP-11's monitor and lots of dots should appear on the +Commodore's monitor. +.s +23. When the transfer is complete, the "TN>" prompt should reappear. +Type Q. When you see the period-prompt, logout from the PDP-11. (If you +connected from the DEC-20, hit the BREAK key at this point. You will get +the "20>" prompt. Type Q to return to the DEC-20 Exec.) +.s +24. Return to the Commodore. Replace the game disk with the create +disk. The monitor should say READY. Type LOAD"GAME",8 and hit return. +.s +25. Replace the create disk with the game disk. The monitor should say +READY. Type SAVE"GAME",8 and hit return. +.s +43. The game disk should now be complete and functional. Check it by +booting it and, when the game prompt appears, typing "$verify". + +.pg +.c;BOOTING GAME DISKS ON THE COMMODORE 64 +.s 2 +1. Turn on the Commodore's monitor (switch on the front), disk drive +(switch in the back), and CPU (switch on the right side). +.s +2. Put the game disk in the disk drive, with the label facing up and the +oval cut-out toward the rear. Close the drive door. +.s +3. The monitor should say READY. Type LOAD"GAME",8 and hit the return +key. +.s +4. After a few seconds, the monitor will say READY again. Type RUN and +hit the return key. +.s +5. You will told to wait 1.5 minutes. After this period of time, the +game should come up. If the entire opening does not fit on one screen +you will have to hit the space bar when the monitor says MORE. +.s +6. When the game prompt (">") appears, you can verify the disk by type +"$VE" and hitting the return key. WARNING: Verifying a disk on the +Commodore takes around five minutes. + diff --git a/create/cpm.rno b/create/cpm.rno new file mode 100644 index 0000000..db73e10 --- /dev/null +++ b/create/cpm.rno @@ -0,0 +1,99 @@ +.c;HOW TO MAKE CP/M GAME DISKS ON THE PDP-11 +.s +NOTE: Before making a CP/M disk, the game file must exist in the +PDP-11's INT directory. If the current version is not there, transfer it +using the instructions in the front of this book. +.s +1. Log onto the PDP-11. A convenient location to do this is the +Decwriter next to the PDP-11, since you will be using the PDP-11's +floppy disk unit. If you don't have an account, you can log onto account +3,3 (password: GAMES). +.s +2. Put the CP/M create disk for that particular game into the left-most +drive of the PDP-11's floppy disk unit. Turn on the power to the floppy +disk unit. Make sure that the switch below the left-most drive is NOT +set to write-protect. +.s +3. When you get the PDP-11's period-prompt, type INT and hit the return +key. +.s +4. The period-prompt will reappear. Type CPMFLX and hit the return key. +.s +5. You will be asked to enter the CP/M device. Type DX0: and hit the +return key. (The third character is a zero; don't forget the colon.) +.s +6. A menu will be displayed. Type E and hit the return key. +.s +7. You will be asked to enter the CP/M file specification. Type +[cpm-name].DAT and hit the return key (where [cpm-name] is the name of +the game, truncated to eight letters if nescesary). Some examples: +ZORK1.DAT, STARCROS.DAT, PLANETFA.DAT. +.s +8. The menu will appear. Type C and hit the return key. +.s +9. You will asked to enter the DEC file specification. Type +[11-name].IML and hit the return key (where [11-name] is the PDP-11's +six-letter abbreviation for the game name). Some examples: ZORK3.IML, +DEADLN.IML, SUSPEN.IML. +.s +10. After about a minute, the menu will appear. Type X and hit the +return key. +.s +11. The period-prompt will appear. Logout of the PDP-11. +.s +12. The game file has now been transferred to the create disk. It is +time to rename the game file. Log back onto the +PDP-11, this time using the account 8,8 (password: CPM). +.s +13. Type any key as instructed. A prompt will appear that looks like +"A>". Type C: and hit the return key. +.s +14. A "C>" prompt will appear. Type REN [cpm-name].DAT=[11-name].IML and +hit the return key. +.s +15. Boot the game by typing [cpm-name] and hitting the return key. When +the game prompt appears, type $VE and hit the return key. +.s +16. If the create disk verifies, it is time to use it to make a game +disk. This is simply a matter of making a copy of the create disk. Put a +blank initialized 8" disk in the center drive of the floppy disk unit. +Make sure that the write-protect switch for the center drive is not set +to write-protect. +.s +17. The PDP-11 terminal should still be displaying the "C>" prompt. Type +A:PIP D:=*.* and hit the return key. +.s +18. Wait a little while. Lots of stuff will appear on the PDP-11 +terminal. Finally, the "C>" prompt will return. Type D: and hit the +return key. +.s +19. The "D>" prompt will appear. Type [cpm-name] to boot the game from +the newly-created game disk in the center drive. When you see the game +prompt, type $VE to verify the disk. +.s +20. Leave the game by typing Q, hitting return, typing Y, and hitting +return again. When you see the "D>" prompt, logout from the PDP-11 by +typing A:EXITCPM and hitting the return key. + +.pg +.c;HOW TO LOAD CP/M DISKS ON THE PDP-11 +.s 2 +1. Turn on the PDP-11's floppy disk unit. +.s +2. Put the disk in the left-hand drive. +.s +3. Log on to the computer at the Decwriter (or any other convenient terminal) +under account 8,8. The password is "CPM". +.s +4. The computer will instruct you to strike any key. Strike any key. +.s +5. A prompt will appear that looks like "A>". Type "C:". +.s +6. A prompt will appear that looks like "C>". Type "DIR" for a directory of +the disk, or type "STAT" for information on each file. +.s +7. Type [game] to play the game, where [game] is the first eight letters +of the name of the game. (For example "STARCROS" or "SUSPENDE") +.s +8. After you are done mucking about in CPM and have the "C>" prompt, type +"a:exitcpm". This will log you out. \ No newline at end of file diff --git a/create/ibm.rno b/create/ibm.rno new file mode 100644 index 0000000..f2360aa --- /dev/null +++ b/create/ibm.rno @@ -0,0 +1,130 @@ +.c;FORMATTING DISKS FOR THE IBM PC & TI PROFESSIONAL +.s 2 +1. Put the working disk in the left-hand drive (drive A) and turn on the +power. (The machine may take as long as a minute to come on.) +.s +2. Enter the date and time or simply hit Return twice to bypass. +.s +3. You will see a prompt that looks like "A>". Type "Format b:" +.s +4. Place a blank disk in the right-hand drive (drive B). +.s +5. Hit any key to begin the formatting process. +.s +6. When the formatting process is complete, you will be asked if you wish to +format another disk. If you do, type "Y" and go to step four. +.s 2 +NOTE: Disks must be formatted on the machine for which the master is +being made. The procedure is the same for both machines, however. + +.pg +.C;CREATING AN IBM/TI CREATE DISK FOR A NEW GAME +.s 2 +1. Put the disk labelled "working disk" in Drive A (the left-hand +drive) of the IBM PC. +.s +2. Turn on the IBM PC's power (the switch is on the right-side of the +CPU). +.s +3. Enter the date or type Return twice to bypass it. +.s +4. You will see the "A>" prompt. Type "DISKCOPY A: B:". +.s +5. Put any existing create disk in Drive A. Put any blank disk (it +doesn't have to be formatted) in Drive B (the right-hand drive). +.s +6. Hit any key to start the copying procedure. +.s +7. When the screen says "copy completed", remove the disk from Drive B +and label it as the IBM/TI Create Disk for the new game. + +.pg +.c;TRANSFERRING A GAME FROM THE DEC-20 TO THE IBM PC +.S 2 +NOTE: Copying a game to the IBM is a two-step process. The first step is +transferring the game file to the create disk. The second step is making a +game disk from the create disk. +.s +NOTE: IBM masters and TI masters are both made on the IBM PC from the +same create disk. The only difference is step 20. In other words, to +make masters of a game for both machines, you would only have to TFTP +from the DEC-20 once. +.s +1. Put the working disk in the left-hand drive (drive A). This is the +disk which says "working disk" AND NOTHING ELSE. +.s +2. Put the create disk for that game in the right-hand drive (drive B). +.s +3. Plug the TN20 line into the back of the IBM. +.s +4. Turn on the IBM. +.s +5. Enter the date and time or simply hit Return twice to bypass it. +.s +6. You will get a prompt that looks like "A>". Type "B:" +.s +7. You will get a prompt that looks like "B>". Type "erase game.zip". +.s +8. When the prompt reappears, type "a:basica tftp/s:512/c:512". +.s +9. You will be asked for the name of a file. Type "game.zip". +.s +10. Type control-right-brace as instructed. The IBM is now waiting to +receive the file from the DEC-20. +.s +11. Go to a DEC-20 terminal and follow the instructions for running TN20. +.s +12. When the transfer is complete, go to the IBM and type +control-right-brace as instructed. +.s +13. Type "system". +.s +14. The "B>" prompt will appear. Type "A:". +.s +15. You are now ready to begin phase two, making the game disk from the master +disk. When you see the "A>" prompt, remove the working disk from drive A. +Take the create disk from drive B and put it in drive A. Put a blank, +formatted disk in drive B. +.s +16. If you are making an IBM master, type "create". If you are making a +TI master, type "ticreate". The copying process will take about a minute. +.s +17. When the copying process is complete, remove the create disk. Put the +newly-created game disk in drive A and boot it (by hitting the CTRL, ALT, and +DEL keys at the same time). When the game prompt appears, test it by typing +"$verify". The verification process should take about a minute. + +.pg +.C;HOW TO BOOT DISKS ON THE IBM PC +.s 2 +1. Put the game disk in the left-hand drive, Drive A. +.s +2. Turn on the power (the large red-orange toggle switch on the +right-hand side of the CPU). If the color monitor is attached instead +of the regular monitor, you will have to turn that on as well. +.s +3. Wait a little while. The IBM PC will take up to a minute to come on, +depending on how much memory is hooked up. +.s +4. If no back-up copy has been made of the game disk, you will be asked +if you want to make it at this point. Type "N". +.s +5. If there is no write-protect sticker on the disk, you will be asked +to put one on. These are the silver-colored peel-off squares. Put one +over the notch on the upper-right corner of the disk. +.s +6. The game should appear almost instantly. +.s +7. To boot another disk, you don't need to turn the power off and on +again. Just put the new disk in Drive A. Then hit the keys labelled +CTRL, ALT, and DEL at the same time. (These keys are in the lower left +and lower right corners of the keyboard). The new disk will boot almost +instantly. + +.pg +.C;HOW TO BOOT DISKS ON THE TI PROFESSIONAL +.s 2 +1. Put the game disk in the left-hand drive, Drive A. +.s +2. Turn on the TI power using the toggle switch on the right side of the +CPU. The game will boot in a matter of seconds. diff --git a/create/osborne.rno b/create/osborne.rno new file mode 100644 index 0000000..c113fff --- /dev/null +++ b/create/osborne.rno @@ -0,0 +1,263 @@ +.c;CREATING AN OSBORNE CREATE DISK FOR A NEW GAME +.s +NOTE: Before starting this procedure, make sure you have a blank, +Osborne-formatted disk. This will become the new create disk. +.s +1. Put the CP/M system disk in the left-hand drive, Drive A. Put the +disk labelled "Utilities TFTP/GAME.COM" in the right-hand drive, Drive +B. +.s +2. Turn on the power. Hit return to boot the disk in Drive A. When the +menu appears, hit the ESC key to load CP/M. +.s +3. When the "A>" prompt appears, type "dir b:" to get a listing of the +files on the Utility disk in Drive B. There should be a file called +"[oldname].COM", where "[oldname]" is the name of a pre-existing +Interlogic game, shortened to the first eight letters if necessary. +.s +4. Type "b:" and hit the return key. A "B>" prompt should appear. +.s +5. Type "ED SETUP.ASM" and hit the return key. +.s +6. A prompt that looks like ":*" will appear. Type "1000A" and hit the +RETURN key. +.s +7. A prompt that looks like "1:*" will appear. Type "FDB '" and hit the +RETURN key. +.s +8. A prompt that looks like "30:*" will appear. Type +"8DI[newname]ctrl-Z" and hit the return key. Note that ctrl-Z refers to +hitting the CTRL and Z keys simultaneously. Also, [newname] refers to +the name of the game you are creating this Create Disk for, shortened to +the first 8 letters or padded to 8 letters using spaces. +.s +9. A prompt will appear that looks like "*". Type "E" and hit the RETURN +key. +.s +10. After a few seconds, the "B>" prompt should reappear. Type "ASM +SETUP" and hit the RETURN key. +.s +11. The CP/M Assembler will run for a little while. When it is done, the +screen will say "End of Assembly", and the "B>" will reappear. Type +"LOAD SETUP" and hit the RETURN key. +.s +12. Some gibberish will appear and then the "B>" will return. Type "REN +[newname].COM=[oldname].COM". In this command, [newname] and [oldname] +should be shortened to 8 letters but should not be padded with spaces if +they are less than 8 letters. +.s +13. The "B>" prompt will appear again. Type "SETUP" and hit the RETURN +key. +.s +14. The screen will say "Configuration Program Finished" and the "B>" +prompt will return. Type "A:" and hit the RETURN key. +.s +15. When the "A>" prompt appears, type "ERA [oldname].COM" and hit the +RETURN key. +.s +16. When the "A>" prompt returns, type "PIP A:=B:[newname].COM" and hit +the RETURN key. +.s +17. The "A>" prompt will return. Remove the Utilities disk from Drive B +and put the blank, Osborne-formatted disk into Drive B. Type a ctrl-C. +.s +18. When the "A>" prompt reappears, type "PIP B:=[newname].COM" and hit +the return key. +.s +19. Type "B:" to connect to Drive B, and then type "DIR" to list the +files on the new Create disk. There should be one file, called +"[newname].COM". +.s +20. You are done. Remove the new Create disk, label it, and put a +write-protect sticker on it. + +.pg +.c;HOW TO FORMAT DISKS FOR THE OSBORNE +.s +1. Put the CP/M system disk in the left-hand drive, Drive A. +.s +2. Turn on the power. The switch is in the back, under the lid. +.s +3. Hit the return key to boot the disk in Drive A. +.s +4. When the menu appears, hit the ESC key to load CP/M. +.s +5. When the "A>" prompt appears, type "COPY" and hit return. +.s +6. A two-item menu will appear. Type "F" for FORMAT. +.s +7. You will asked which drive you want to use for the formatting +procedure. Type "B" and hit return. +.s +8. Put a blank disk in Drive B. Hit return to begin the formatting +procedure. +.s +9. A line of F's will appear on the screen. Then a line of V's will +appear just below the F's. When the formatting procedure is done, you +will be asked if you want to format another disk. + +.pg +.c;TRANSFERRING A GAME FILE FROM THE DEC-20 TO THE OSBORNE +.s +NOTE: Before you begin, you will need a blank, Osborne-formatted disk +(or two if this is a two-disk game). Refer to the formatting section of +the Osborne documentation. +.s +1. Plug the TN20 line into the front of the Osborne. You will need the +Osborne/Apple black adapter cable to do this. +.s +2. Put the CP/M system disk in Drive A (the left-hand drive) and turn on +the Osborne power. The power switch is in the panel in the back, next to +the power cord. +.s +3. Hit return to boot the CP/M disk. When the menu appears, hit the ESC +key to load CP/M. +.s +4. When the "A>" prompt appears, type "copy" and hit the RETURN key. +.s +5. You will asked whether you want to Format a disk or Copy a disk. Type +"C" to copy a disk. +.s +6. You will asked which drive you want to use for the source disk. Type +"A" for Drive A. +.s +7. Place the Osborne create disk for this game in Drive A. Place a +blank, Osborne-formatted disk in Drive B. Hit the RETURN key to begin +the copy procedure. +.s +8. When the copy procedure is complete, replace the Create disk with the +CP/M disk. Hit several returns until you see the "A>" prompt. +.s +9. Type "dir b:" to see the contents of the disk in Drive B. It should +contain one file, called [game].COM, where [game] is the first 8 letters +of the name of the game. +.s +10. If you are transferring a two-disk game, go to step (16). If you are +transferring a one-disk game, continue to the next step. +.s +11. At the "A>" prompt, type "tftp b:[game].DAT", but do not hit the +RETURN key yet. Note that [game] refers to the first 8 letters of the +game, such as SUSPENDE or PLANETFA. +.s +12. Follow the instructions for running TN20. When you get to the step +where the 20 says "Type any key to begin transfer:" return to the +Osborne and hit the RETURN key. The Drive A red working light will go +on. A bit later, the Drive B red working light will go on. Wait a few +seconds after the Drive B light goes on, and then hit a key on the 20 +terminal to begin the transfer. +.s +13. A's will begin appearing on the 20 terminal. No A's will appear on +the Osborne screen, though. The transfer should take around 15 minutes. +When it is done, the Osborne screen will say "Transfer Completed" and +the "A>" prompt will return. +.s +14. Type "b: dir" and hit the RETURN key. The disk in Drive B should +consist of two files, one called [game].COM and one called [game].DAT. +.s +15. The disk is Drive B is now a usable game disk. Boot it by typing +[game] at the "A>" prompt. When the game prompt appears, type "$ve" to +check the disk. +.s +16. The disk is Drive B will become disk one of the game. At the "A>" +prompt, type "tftp b:[game].PRE", but do not hit the RETURN key yet. +Note that [game] refers to the first 8 letters of the game, such as +SUSPENDED or PLANETFA. +.s +17. Follow the instructions for running TN20. Don't forget to SPLIT the +game file to create the [game].PRE and [game].PUR files. When you get to +the step where the 20 says "Type any key to begin transfer:" return to the +Osborne and hit the RETURN key. The Drive A red working light will go +on. A bit later, the Drive B red working light will go on. Wait a few +seconds after the Drive B light goes on, and then hit a key on the 20 +terminal to begin the transfer. +.s +18. A's will begin appearing on the 20 terminal. No A's will appear on +the Osborne screen, though. The transfer should take around 5 minutes. +When it is done, the Osborne screen will say "Transfer Completed" and +the "A>" prompt will return. +.s +19. Type "dir b:" and hit the RETURN key. The disk in Drive B should +contain two files, called [game].COM and [game].PRE. Remove this disk +from Drive B and label it as Disk one. +.s +20. Put the second blank, Osborne-formated disk in Drive B. Hit a +ctrl-C. +.s +21. When the "A>" prompt returns, type "tftp b:[game].PUR" but again, do +not hit the RETURN key yet. +.s +22. Run TN20 again, this time sending the [game].PUR file. Remember to +begin the transfer a few seconds after the red working light on the +Osborne's Drive B goes on. +.s +23. A's will appear on the 20 terminal again. The transfer will take +about 15 minutes. When it is done, the Osborne screen will say "Transfer +Completed," and the "A>" will return. +.s +24. Type "dir b:". There should be one file on the disk in Drive B, +called [game].PUR. +.s +25. The disk in Drive B is disk two of the game. Remove it and place +disk one in Drive B. +.s +26. Boot the game. When the game prompt appears, type "$ve" to check the +disk. + +TROUBLESHOOTING: The most common error message is something like "BDOS +Bad Sector". If you get this, try hitting ctrl-C. If it still doesn't +work, make sure that the disk you are copying to isn't write-protected. + +.pg +.c;COPYING OSBORNE DISKS +.s +1. If you have an Osborne version of a game and you want to make another +copy of it, you just have to duplicate it using the Osborne's CP/M copy +procedure. You will need a blank, Osborne-formatted disk for each disk +you want to copy. +.s +2. Put the CP/M System disk in the left-hand drive, Drive A. Turn on the +Osborn power (in the back under the lid). +.s +3. Hit return to boot the disk in Drive A. When the menu appears, hit +the ESC key to load CP/M. +.s +4. When the "A>" prompt appears, type "copy" and hit the RETURN key. +.s +5. You will be asked whether you want to Copy or Format. Type "C" to +copy a disk. +.s +6. You will be asked which drive you want to use for the source disk. +Type "A" for Drive A. +.s +7. Put the disk to be copied in Drive A. Put a blank, Osborne-formatted +disk in Drive B. Hit the RETURN key to begin the copy procedure. +.s +8. If the game you are copying is a two-disk game, just repeat the above +procedure with the the other disk. + +.pg +.c;HOW TO BOOT DISKS ON THE OSBORNE +.s +1. Put the CP/M System disk in the left-hand drive, Drive A. Put the +game disk (disk one if it is a two-disk game) in the right-hand drive, +Drive B. +.s +2. Turn on the Osborne power. The power switch is in the back, under the +small lid, next to where the power cord is attached. +.s +3. Hit the RETURN key to boot the CP/M disk in Drive A. +.s +4. When the help menu appears, hit the ESC key to load CP/M. +.s +5. A prompt that looks like "A>" will appear. Type "b:" to connect to +Drive B. +.s +6. A prompt that looks like "B>" will appear. Type the first 8 letters +of the name of the game, such as ZORK2, STARCROS, or ENCHANTE, and hit +the RETURN key. If you're not sure what to type, you can type "dir" to +get a listing of the files on the disk in Drive B. +.s +7. If it is a one-disk game, the game should now boot. If it is a +two-disk game, you will be instructed to insert to data disk. Remove the +CP/M disk from Drive A and insert disk two. Then hit the RETURN key. The +game should now boot. \ No newline at end of file diff --git a/create/rainbow.rno b/create/rainbow.rno new file mode 100644 index 0000000..1e3b2b5 --- /dev/null +++ b/create/rainbow.rno @@ -0,0 +1,179 @@ +.C;MAKING A RAINBOW CREATE DISK FOR A NEW GAME +.s +1. Put the disk labelled "CPM 80/86 Working" in Drive A, and the disk +labelled "Working Disk TFTP" in Drive B. +.s +2. Turn on the Rainbow by pushing the large switch in front to the "1" +setting. +.s +3. Put the Rainbow in Caps Lock mode. +.s +4. When the menu appears, type "A". +.s +5. When the "A>" prompt appears, type "RED B:ZIP.A86" and hit the return +key. +.s +6. The editor will load. This will take approximately 30 seconds. +.s +7. Type "L" for LOCATE followed by "GAMFCB [tab] DB" and hit the return +key. +.s +8. After a wait of approxmately 90 seconds, the cursor will be at a line +containing the phrase "[game]DAT" and two lines later will be the phrase +"[game]SAV" (where [game] is the name of an Interlogic game shortened to +eight characters or padded to eight characters using spaces). +.s +9. Use the arrow keys to move the cursor to the first character in +"[game]DAT". +.s +10. Type "E" for ERASE and then move the cursor using the right arrow +key a total of eight times. The cursor should now be on the "D" in +"DAT". Hit the DO key. The eight characters you passes over should +disappear. +.s +11. Type "I" for INSERT followed by the name of the game you are making +a create disk for. It must be shortened to the first eight characters or +lengthened to eight characters using blank spaces. Hit the DO key. The +characters should appear before the cursor. +.s +12. Use the arrow key to move the cursor to the first character in +"[game]SAV". Repeat steps 10 and 11. +.s +13. Type "Q" for QUIT. +.s +14. Type "K" for KEEP. +.s +15. After about 30 seconds, the "A>" prompt will appear. You should now +type "SUBMIT ASM" and hit the return key. +.s +16. The Rainbow will run for around minutes. The last thing that appears +on the screen should be: +.s +.ts 15 +.no fill + A>PIP ZIP.CMD=B: + A> +.s +.fill +17. Remove the disk from Drive B. Put a blank, RX50 disk in Drive B. +This disk will become the new create disk. +.s +18. Type control-C. You will get another "A>" prompt. +.s +19. Type "PIP B:[game].CMD=ZIP.CMD" and hit the return key. +.s +20. The disk in Drive B is now the create disk for the new game. Label +it as such. + +.pg +.c;COPYING GAMES FROM THE DEC-20 TO THE DEC RAINBOW +.s 2 +NOTE: Before you begin this procedure, a create disk must already exist for +this particular game. If one does not yet exist, follow the procedure +outlined on the previous pages. +.s +1. Connect the Rainbow's COMM line (a heavy white cable) to the TN20 line. +.s +2. Place the "CP/M 86/80 Working" disk in Drive A, and place the create disk +in Drive B (note that the disk in Drive B should be upside-down). +.s +3. Turn the power on (press "1" on the 1-0 button). +.s +4. A menu will appear. Type "A" to boot the CPM disk in Drive A. +.s +5. At this point, you need to change the set-up features of the Rainbow. +Type the "F3" key (near the top left corner of the keyboard) to enter set-up +mode. +.s +6. Press the "next screen" key twice. +.s +7. The first set-up feature (and possibly the second and third features) +need to be changed. The up-arrow key cycles through the various +allowable values for each feature, and the right-arrow key moves you to +the next feature. The set-up you want is: +.ts 15, 22 + 8N data B/P + 4800 XMT + 4800 RCV +.s +8. Press the "F3" key to leave set-up mode. +.s +9. When the prompt "A>" appears, type "era b:[game].dat", where [game] is +the first eight letters of the title. (If you're not sure, type "dir b:" +to get a listing of the files on the disk.) +.s +10. The screen may say "NO FILE" at this point. Ignore it. You'll see +the "A>" prompt again. Type "tftp b:[game].dat". +.s +11. Go to a DEC-20 terminal and follow the separate instructions for +running TN20. +.s +12. Unlike most other transfer programs, A's will not appear on the +screen of the receiving machine, the Rainbow. The transfer should take +five to ten minutes. +.s +13. When the transfer is complete, the Rainbow screen will print +"COMPLETED" and the "A>" prompt should reappear. +.s +14. Type "dir b:" to see the directory of the create disk in Drive B. It +should consist of two files, one called "[game].cmd" and one called +"[game].dat" (where [game] is something like ZORK2 or PLANETFA). +.s +15. At this point, you should return the Rainbow to its default set-up +features. To do this, press the "F3" key, type an upper-case "D", and +press the "F3" key again. +.s +16. At the "A>" prompt type "b:". You will get a "B>" prompt. +.s +17. Boot the game from the create disk in Drive B by typing "[game]" +(where, once again, [game] is the first 8 letters of the name of the +game). When the game prompt appears, test the game by typing "$verify". + +.pg +.C;USING THE CREATE DISK TO MAKE A GAME DISK ON THE DEC RAINBOW +.s 2 +NOTE: The create disk, once you have transferred the game file to it, is +identical to a game disk. Therefore, in order to produce a game disk +from a create disk, all you need do is copy it. +.s +1. Put the "CP/M 86/80 Working" disk in drive A. +.s +2. Turn the power on (press "1" on the 1-0 button). +.s +3. A menu will appear. Type "A". +.s +4. A prompt will appear that looks like "A>". Type "copy". +.s +5. Put the create disk in drive A and a blank disk in drive B. (NOTE: +you must use a Digital RX50 disk for the blank disk! The Dysan disks that +we normally use will not work.) +.s +6. Answer yes to the two questions that appear. +.s +7. When the copy procedure is complete, you will be asked if you want to make +another copy. +.s +8. When you are done making copies, test the games by booting them each and +typing "$verify". + +.pg +.C;BOOTING GAME DISKS ON THE DEC-RAINBOW +.s +1. Find the disk labelled "CP/M 86/80 Working" and place it in Drive A, +the top drive. It should go in with the label facing upward and closer +to you. +.s +2. Place the game disk in the bottom drive, Drive B. It should go in +with the label facing downward and closer to you. +.s +3. Turn on the Rainbow by pushing the large switch labelled "1" and "0" +to the "1" setting. +.s +4. After a few churns, beeps, and whistles, a menu will appear on the +screen. Type "A". +.s +5. A prompt that looks like "A>" will appear. Type "B:". +.s +6. A prompt that looks like "B>" will appear. Type the first eight +letters of the name of the game. Some typical names: ZORK3, STARCROS, +PLANETFA. The game will then boot. diff --git a/create/rt11.rno b/create/rt11.rno new file mode 100644 index 0000000..0d51616 --- /dev/null +++ b/create/rt11.rno @@ -0,0 +1,33 @@ +.c;HOW TO CREATE MASTER GAME DISKS ON THE PDP-11 +.s 2 +1. Log on to the computer at the Decwriter (or any other convenient terminal) +under account 3,3. The password is "GAMES". +.s +2. When you see the prompt ("."), type "ICREAT [game]". Remember +that [game] is the six-character name used on the PDP-11. +.s +3. Turn on the PDP-11's floppy disk unit. +.s +4. Put a blank disk in the left-hand drive. +.s +5. Type RETURN. +.s +6. Wait awhile. (You should see appropriate messages.) +.s +7. When finished, type "LOGO" +to logout. +.s 4 +.c +HOW TO PLAY A GAME FROM A FLOPPY ON THE PDP-11 +.s 2 +1. Login to the PDP-11 as above. +.s +2. Turn on the floppy unit and insert disk in left-hand drive. +.s +3. Type "DX". +.s +4. Type "RUN [game]". +.s +5. Optional: to reconnect to game directory, type "INT". +.s +6. Type "LOGO" to logout. diff --git a/create/tn20.rno b/create/tn20.rno new file mode 100644 index 0000000..a225ac3 --- /dev/null +++ b/create/tn20.rno @@ -0,0 +1,113 @@ +.c;HOW TO USE TN20 +.s +NOTE: Make sure that the cable in the micro-room labelled "TN20" is +attached to the appropriate port of the micro-computer you are +transferring to. Follow the instructions for that particular machine to +prepare it for transfer. When you are instructed to do so, return here +to run TN20. +.s +1. Log onto the DEC-20. +.s +2. When the @-prompt appears, type "TN20". +.s +3. You will be asked what file to send. If you are not connected to the +directory that file lives in, you must prefix the file name with the +directory name, followed by a colon. For example, the Atari and +Commodore interpreters live in the Z directory; to transfer them you +would type Z:ZIP.ATR or Z:ZIP.C64, respectively. +.s +Most game directories are located on the alternate disk drive, called +SS. (The primary disk drive is called PS.) In order to copy Starcross, +for example, you would have to type "SS:STARCROSS". TN20 +assumes the ".ZIP" suffix, so you don't need to include it. +.s +If you are making a two-disk game, such as Deadline on the Atari, the +game file must be sent in two parts, called [game].PRE (the first part) +and [game].PUR (the second part). To split the game file into these two +sub-files, first connect to the directory it lives in. For example, to +connect to the Zork I directory, type "CONN SS:" at the @-prompt. +When the @-prompt reappears, type "SPLIT [game]". After several seconds, +you will be informed that the game file has been split. Then, when TN20 +asks which file you want to send, type "[game].PRE", and later +"[game].PUR". +.s +4. TN20 will now ask what machine you are transferring to. Simply type +the name of the machine: Apple, Atari, Osborne, etc. If you are not sure +what a valid response here is, type a question mark to get a listing of +all valid responses. +.s +5. TN20 will then inform you of the baud rate it will transfer at (4800 +for the Rainbow, 2400 for the Apple, and so on). Type any key to +commence with the transfer. +.s +6. If everything is okay, a whole lot of A's should begin appearing on +the screen of the DEC-20 terminal you are using. A's will appear on the +screens of certain receiving micro-computers, but not all. If the A's do +not appear on the DEC-20 terminal, go to the troubleshooting section. +.s +7. When the transfer is complete, TN20 will tell you the actual baud +rate and compare it to the theoretical baud rate. (The higher the +percentage, the better the speed of the receiving micro.) Because of a +bug, you may get a double @-prompt. +.s +8. If you want to transfer another game file, type "RESET TN20". If you +are done, then log out of the DEC-20. +.s +TROUBLESHOOTING: If the transfer didn't work, check to make sure that +the TN20 cable is properly plugged into the receiving micro. Look at the +screen of the receiving micro -- there might be an error message of some +kind there that will tell you what's wrong. Finally, some twit may have +unplugged the TN20 cable from the other end, in the main computer room. + +.pg +.c;HOW TO TRANSFER GAMES FROM THE DEC-20 TO THE PDP-11 +.S 2 +1. Log onto the 20. When the @-prompt appears, type "11". +.s +2. You will get a prompt that looks like "20>". Type "C" to connect to the +11. +.s +3. Log onto the 11. When the period-prompt appears, type "20". +.s +4. You will see a prompt that looks like "11>". Type "R". +.s +5. You will be asked for the name of the file to be received. Type in +"INT:[game]", where [game] is the six-letter abbreviation for the game name. +For example, to transfer Starcross, you would type "INT:STRCRS". You +will see a message like "[N blocks]", where N is the number of free +blocks available in the INT directory. +.s +6. The "11>" will reappear. Type "B". +.s +7. Hit the BREAK key. The "20>" prompt will reappear. +.s +8. Type "X". The @-prompt will reappear. +.s +9. Follow the separate instructions for running TN20. When TN20 asks for +the machine name, type "PDP-11". +.s +10. A bunch of A's will appear on the screen. The transfer will take +around five minutes. +.s +11. When the transfer is complete, the @-prompt will reappear. Type "11" +and hit return. +.s +12. The "20>" prompt should reappear. Type "C" to return to the PDP-11. +.s +13. When the period-prompt appears, type the name of the game file (DEADLN for +Deadline, etc.). When the game prompt appears, test the game by typing +"$verify". +.s +12. Leave the game (type "quit"). When the period-prompt appears, log out of +the 11. +.s +13. Hit the break key. The "20>" prompt will appear. Type "Q" to disconnect +from the 11. You are now back at your original 20 login. +.s +NOTE: There are a limited number of remote lines between the 11 and the +20. If, at some point, you are informed that a given remote line is +already in use, you will have to try again later when it is free. +.s +ANOTHER NOTE: If the INT directory on the 11 is too full, you won't be +able to transfer the game file successfully. If this happens, ask +someone to delete some unimportant files from the INT directory. diff --git a/fixer.mud b/fixer.mud new file mode 100644 index 0000000..9545fe3 --- /dev/null +++ b/fixer.mud @@ -0,0 +1,61 @@ +> +> +> +> +> + + + +>> + + +) + >> .INCH) + (>> .OUCH) + (ELSE + >> + + >> + + >> + + + + ) + (ELSE )>) + (ELSE + + )>) + (ELSE )>> + + )>> + + + + > .INCHAN ,END-READ>> + ) + (ELSE >)> + + + + + + > .INCHAN ,END-READ>> + ) + (ELSE >)> + + + + + >> + +> > diff --git a/hp/hpcreate.asm b/hp/hpcreate.asm new file mode 100644 index 0000000..f101ada --- /dev/null +++ b/hp/hpcreate.asm @@ -0,0 +1,214 @@ + TITLE CREATE IML FILE LOADER/DUMPER + + SUBTTL CONSTANTS, DATA, STACK, ETC + PAGE + + +RECSIZ EQU 14 ; OFFSET FOR RECORD SIZE IN FCB +RNDREC EQU 33 ; OFFSET FOR RANDOM RECORD SLOT + +DTASIZ EQU 2200H +DTABKS EQU 20H + +SEQRD EQU 14H ; CONSTANTS DEFINED BY DOS +SEQWR EQU 15H +FILSIZ EQU 23H +SDTA EQU 1AH +FILOPN EQU 0FH +FILCLS EQU 10H +FILMAK EQU 16H +FILDEL EQU 13H + +STK_SG SEGMENT PARA STACK + DW 20H DUP(?) +STK_TOP LABEL WORD +STK_SG ENDS + +DATA_SG SEGMENT PARA + +ASKNAM DB "Name of game: ",80H +NONAME DB "No name supplied",0 +NOINT DB "HPZIP.EXE not found",0 +WRTERR DB "Disk write error on drive B",0 +DONE DB "Finis",0 + +INBUF DB 9 +INCNT DB 0 +GAMNAM DB " " +GAMEXT DB "EXE" + DB 25 DUP(0) + +ZIPFCB DB 0 + DB "HPZIP EXE" + DB 25 DUP(0) + +DTA DB DTASIZ DUP(0) ; DISK TRANSFER AREA + +DATA_SG ENDS + + SUBTTL MACROS + PAGE + + +MOVM MACRO D,S,R + MOV R,S + MOV D,R + ENDM + +FATAL MACRO STR + PRINT STR + JMP EXIT + ENDM + +PRINT MACRO STR + PUSH AX + MOV AX,OFFSET STR + CALL .PRINT + POP AX + ENDM + +DISK MACRO X,Y + MOV AH,X + MOV DX,OFFSET Y + INT 21H + ENDM + +SETDTA MACRO + MOV AH,SDTA + MOV DX,OFFSET DTA + INT 21H + ENDM + +RECCNT MACRO X,Y + DISK FILSIZ,X + MOV DI,OFFSET X + MOV Y,RNDREC[DI] ; LOAD THE # OF PASSES WE NEED TO MAKE + CMP AL,0 + ENDM + +SETSIZ MACRO X + MOV DI,OFFSET X + MOV WORD PTR RECSIZ[DI],DTASIZ + ENDM + + SUBTTL CODE + PAGE + + +CODE_SG SEGMENT PARA +ASSUME CS:CODE_SG,DS:DATA_SG,SS:STK_SG + +START PROC FAR + MOVM DS,DATA_SG,AX + MOVM SS,STK_SG,AX + MOV SP,OFFSET STK_TOP + PUSH ES ; SAVE OLD ES FOR DOS RETURN + MOVM ES,DATA_SG,AX + JMP MAIN +START ENDP + +EXIT PROC FAR + SUB AX,AX ; OLD ES IS ALREADY ON THE STACK + PUSH AX + RET +EXIT ENDP + +MAIN PROC + SETSIZ ZIPFCB + RECCNT ZIPFCB,CX + JZ ZIP1 + FATAL NOINT +ZIP1: DISK FILOPN,ZIPFCB + SETSIZ ZIPFCB + SETDTA + DISK SEQRD,ZIPFCB + DISK FILCLS,ZIPFCB + + PRINT ASKNAM + MOV DX,OFFSET INBUF + MOV AH,0AH + INT 21H ; READ A LINE FROM THE TTY + MOV DL,10 + MOV AH,6 + INT 21H ; LINE FEED + MOV AL,INCNT + CMP AL,0 + JNE ZIP2 + FATAL NONAME + +ZIP2: MOV BX,OFFSET GAMNAM + MOV CX,8 +ZIP21L: MOV AL,BYTE PTR [BX] + CMP AL,0DH + JNE ZIP21 + MOV BYTE PTR [BX],20H +ZIP21: ADD BX,1 + LOOP ZIP21L + + MOV BX,OFFSET DTA+0201H ; OFFSET TO DS + MOV BX,[BX] + MOV CL,4 + SHL BX,CL + PUSH BX + ADD BX,OFFSET DTA+0201H + MOV BP,OFFSET GAMNAM + MOV CX,8 +ZIPL1: MOV AL,BYTE PTR DS:[BP] + CMP AL,0DH + JNE ZIPL1A + MOV AL,20H +ZIPL1A: MOV BYTE PTR [BX],AL + ADD BX,1 + ADD BP,1 + LOOP ZIPL1 + POP BX + ADD BX,OFFSET DTA+022BH + MOV BP,OFFSET GAMNAM + MOV CX,8 +ZIPL2: MOV AL,BYTE PTR DS:[BP] + CMP AL,0DH + JNE ZIPL2A + MOV AL,20H +ZIPL2A: MOV BYTE PTR [BX],AL + ADD BX,1 + ADD BP,1 + LOOP ZIPL2 + MOV INCNT,0 ; THIS IS NOW AN FCB + MOV GAMEXT,"E" + DISK FILDEL,INCNT + DISK FILMAK,INCNT + SETSIZ INCNT + DISK SEQWR,INCNT + DISK FILCLS,INCNT + FATAL DONE +MAIN ENDP + +.PRINT PROC + PUSH BX + MOV BX,AX +.PR1$: MOV AL,[BX] + CMP AL,0 + JE .PR2$ + CMP AL,80H + JE .PR3$ + MOV AH,7 + CALL .TTYOUT + INC BX + JMP .PR1$ +.PR2$: NOP +.PR3$: POP BX + RET +.PRINT ENDP + +.TTYOUT PROC + PUSH BX + PUSH BP + MOV BL,AH + MOV AH,14 + SUB BH,BH + INT 10H + POP BP + POP BX + RET +.TTYOUT ENDP + +CODE_SG ENDS + + END START \ No newline at end of file diff --git a/hp/hpzip.asm b/hp/hpzip.asm new file mode 100644 index 0000000..bcae374 --- /dev/null +++ b/hp/hpzip.asm @@ -0,0 +1,3032 @@ + TITLE ZIP Z-LANGUAGE INTERPRETER HP-DOS 2.0 VERSION + + .XLIST + + ; PATCHES AND FIXES + ; + ; 1) Random bug fixed - 06/25/84 - Dan + ; 2) Status Line Bug (Zork II) Fixed - 07/24/84 - Dan + ; 3) Status line bug fixed (restart) 17-Oct-84/Paul + + SUBTTL STACK AND DATA SEGMENTS INITIALIZATION + +ZVERSN EQU "D" ;ZIP VERSION NUMBER +ZMVERS EQU 3 ;Z-MACHINE VERSION NUMBER +LSTACK EQU 512 ;LENGTH OF USER STACK(MUST BE 1 PAGE FOR NOW) + +PVERS1 EQU 0 ;POSITION OF ZVERSION VERSION BYTE +PVERS2 EQU 1 ;ZVERSION MODE BYTE +PZRKID EQU 2 ;ZORKID +PENDLD EQU 4 ;ENDLOD +PSTART EQU 6 ;START +PVOCTB EQU 10Q ;VOCAB +POBJTB EQU 12Q ;OBJECT +PGLOTB EQU 14Q ;GLOBALS +PPURBT EQU 16Q ;PURBOT +PFLAGS EQU 20Q ;USER FLAG WORD +PSERNM EQU 22Q ;SERIAL NUMBER (6 BYTES) +PWRDTB EQU 30Q ;WORDS +PLENTH EQU 32Q ;GAME LENGTH +PCHKSM EQU 34Q ;GAME CHECKSUM +LMOUTB EQU 80 ;MAX LENGTH OF OUTBUF, EXCLUDING TERMINAL 0 +LDOUTB EQU 80 ;DEFAULT LENGTH OF OUTBUF +LPAGES EQU 128 ;MAX NUMBER OF PAGES EXPECTED +LXBYTS EQU LSTACK+LMOUTB+(4*LPAGES)+2000Q ;LENGTH OF EXTRA BYTES NEEDED + +EOICHR EQU 15 ;CARRIAGE RETURN IS NORMAL END OF INPUT +EOLCHR EQU 10 ;LINE FEED CHARACTER +PADCHR EQU 5 ;PADDING CHARACTER + +CRESET EQU 0H ;MS-DOS FUNCTION CALLS WITH INT 21H +CCONIN EQU 1H +CPROUT EQU 5H +CCONIO EQU 6H +CRDLIN EQU 0AH +CFOPEN EQU 0FH +CFCLOS EQU 10H +CFDELE EQU 13H +CFMAKE EQU 16H +CSDMAO EQU 1AH +CRDRND EQU 21H +CWRRND EQU 22H +CPRSNM EQU 29H + +GAME_SG SEGMENT PARA + DB 09000H DUP(?) +GAME_SG ENDS + +ABS_SG SEGMENT AT 0H +ABS_SG ENDS + +STK_SG SEGMENT PARA STACK + DW 200H DUP(?) +STK_TOP LABEL WORD +STKBOT DW LSTACK DUP(?) +ZSTK_TP LABEL WORD +STK_SG ENDS + +DATA_SG SEGMENT PARA + + ;VARIBLE DEFINITIONS: + + ;GTBLKS +GAMFCB DB 0,"SAMPLER DAT",30 DUP(0) +SAVFCB DB 0,"SAMPLER SAV",30 DUP(0) +DSKFCB DW 0 +DSKDIR DB 0 ;0 FOR READ, 1 FOR WRITE +GTBCNT DW 0 ;REMAINING BLOCKS TO BE READ +GTBSTT DW 0 ;STARTING BLOCK +GTBCOR DW 0 ;STARTING CORE ADDRESS +DSKBUF DB 512 DUP(0) ;DISK BUFFER FOR TRANSFERS + + ; SCREEN DEFINITIONS + +SCPL DB 80 ; COLUMNS PER SCREEN +SLPP DB 24 ; LINES PER SCREEN + + ; STANDARD ANSI ESCAPE SEQUENCES FOR: + ; + ; 1) ERASE SCREEN/ALL ATRIB. OFF/POSITION CURSOR 1,1 + ; 2) INVERSE VIDEO ON/POSITION 1,1 + ; 3) ATRIB. OFF/ POSITION BOTTOM,1 + ; + +STINIT DB 16 + DB 27,"[2J" ; CLEAR SCREEN + DB 27,"[0m" ; ALL ATTRIBUTES OFF + DB 27,"[01;01H" ; POSITION CURSOR 1,1 + +STRESET DB 0 + +SBLINE DB 12 + DB 27,"[7m" ; INVERSE VIDEO ON + DB 27,"[01;01H" ; POSITION CURSOR 1,1 + +SELINE DB 12 + DB 27,"[0m" ; ALL ATTRIBUTES OFF + DB 27,"[16;01H" ; POSITION CURSOR 16,1 + +SPINIT DB 0 + + ; HP/150 SCREEN DEFINITIONS + ; ESCAPE CODES FOR HP 150 + ; FOR SAME AS ABOVE + +HPTYPE DB 1 ; 0=110 , 1=150 ASSUME 150 FOR NOW + +HPTINIT DB 17 ; LENGTH OF STRING + DB 27,"H" ; HOME CURSOR + DB 27,"J" ; CLEAR TO END OF MEMORY + DB 27,"&d@" ; TURN OFF ANY ATTRIBUTES + DB 27,"&a00c00Y" ; POSITION CURSOR AT 1,1 + +HPBLINE DB 13 ; LENGTH OF STRING + DB 27,"&a00c00Y" ; POSITION CURSOR AT 0,0 + DB 27,"&dB" ; TURN ON INVERSE VIDEO + +HPELINE DB 13 ; LENGTH OF STRING + DB 27,"&a00c24Y" ; POSITION CURSOR AT 1,23 + DB 27,"&d@" ; TURN OFF ANY ATTRIBUTES + +TERMID DB 15 ; LENGTH OF STRING + DB 27,"&s1G" ; SET STRAP (G) + DB 27,"&s1H" ; SET STRAP (H) + DB 27,"*s1^" ; SEND TERMINAL ID + + ;SCRIPTING STUFF +SCRFLG DB 0 +PRNRDY DB " * Printer not ready: Abort or Retry? ",80H + + ;USL STUFF +SLFLG DB 1 ;STATUS LINE ASSUMED PRESENT +PMFLAG DB 0 ;AM/PM + +SLSTR DW 0 ;TOP OF SCREEN STRING +SLTAB DW 0 ;TABLE USED BY OPUSL + +SLSTAB DW SLS40 + DW SLS40T + DW SLS80 + DW SLS80T +SLTTAB DW SLT40 + DW SLT40T + DW SLT80 + DW SLT80T + +;40 COLUMN, SCORE +SLS40 DB 40 DUP(32),"S:",5 DUP(32),"M:",6 DUP(32),0,80H +SLS40T DW -1 + DW OPPRND + DW 1 + DW 25 + DW -1 + DW OPPRNN + DW 28 + DW 30 + DW -1 + DW OPPRNN + DW 35 + DW 38 + +;40 COLUMN, TIME +SLT40 DB 40 DUP(32),"Time:",10 DUP(32),0,80H +SLT40T DW -1 + DW OPPRND + DW 1 + DW 24 + DW -1 + DW OPPRNH + DW 31 + DW 33 + DW -1 + DW OPPRNM + DW 34 + DW 39 + +;80 COLUMN, SCORE +SLS80 DB 110 DUP(32),"Score:", 10 DUP(32),"Moves:",7 DUP(32),0,80H +SLS80T DW -1 + DW OPPRND + DW 1 + DW 27 + DW -1 + DW OPPRNN + DW 58 + DW 62 + DW -1 + DW OPPRNN + DW 74 + DW 80 + +;80 COLUMN, TIME +SLT80 DB 120 DUP(32),"Time:", 13 DUP(32),0,80H +SLT80T DW -1 + DW OPPRND + DW 3 + DW 29 + DW -1 + DW OPPRNH + DW 69 + DW 71 + DW -1 + DW OPPRNM + DW 72 + DW 80 + + ;OPRAND +RSEED1 DW ? ;SEED FOR RANDOM NUMBERS +RSEED2 DW ? ;SEED NUMBER TWO +RTEMP DW ? ;TEMP FOR RANDOM + + ;READ +RDWSTR DW 4 DUP(0) ;WORD STRING BUFFER FOR ZWORD +RDBOS DW 0 ;BEGINNING OF STRING POINTER +RDEOS DW 0 ;END OF STRING POINTER +RDRET DW 0 ;RETURN TABLE POINTER +RDNWDS DB 0 ;NUMBER OF WORDS READ + ;PUTSTR +WRDOFF DW 0 ;OFFSET INTO WORD TABLE FOR CURRENT SET + ;PUTCHR +CHRPTR DW 0 ;POINTS TO NEXT CHARACTER POSITION +ENDBUF DW 0 ;POINTS JUST PAST END OF OUTPUT BUFFER (0) + ;GETNUM +STATUS DW 0 ;STATUS-LINE-REQUESTED FLAG + ;ZIPBGN +IRBRKS DB " ",9,13,12,".,?",0 ;INITIAL SET OF READ BREAK CHARS +TWIDTH DW 0 ;TERMINAL WIDTH +LFTMAR DB 1 ;LEFT MARGIN DEFAULT = 1 (2 FOR 80-COLUMN) +MEMTOP DW 0 ;LAST AVAILABLE LOCATION +TIMEMD DW 0 ;TIME(VERSUS SCORE)-MODE-FOR-STATUS-LINE FLAG +ZORKID DW 0 ;UNIQUE GAME & VERSION IDENTIFIER +ENDLOD DW 0 ;ENDLOD BLOCK NUMBER +VOCTAB DW 0 ;SAVE VOCABULARY TABLE POINTER +OBJTAB DW 0 ;OBJECT TABLE POINTER +GLOTAB DW 0 ;GLOBAL TABLE POINTER +WRDTAB DW 0 ;WORD TABLE POINTER +PURBOT DW 0 ;PURE CODE POINTER +ESIBKS DW 0 ;END OF SELF-INSERTING BREAK CHARACTERS +VWLEN DW 0 ;NUMBER OF BYTES IN A VOCABULARY WORD ENTRY +VWORDS DW 0 ;NUMBER OF WORD ENTRIES IN VOCABULARY +VOCBEG DW 0 ;BEGINNING OF ACTUAL VOCABULARY +OUTBUF DB 81 DUP(?) ;OUTPUT BUFFER +INBUF DB 150 DUP(?) ;INPUT BUFFER +RBRKS DB 32 DUP(?) ;STRING OF READ BREAK CHARACTERS +PAGTAB DB 64 DUP(254,0,0,0) ;PAGE INFORMATION TABLE + DB 255 +PAGES DW 0 ;SWAPPING AREA +BUFPGS DW 0 +CHRFLG DB 0 + + ;RESTRT +ZLOCS DW 0 ;POINTER TO LOCALS +ZPC1 DW 0 ;ZPC BLOCK-POINTER +ZPC2 DW 0 ;ZPC BYTE-POINTER +ARGBLK DW 4 DUP(?) ;ARGUMENT BLOCK FOR EXTENDED OPERATIONS +SAVDS DW 0 + + ;NEWZPC +CURPAG DW 0 ;CURRENT PAGE (WHERE ZPC IS) POINTER +CURBLK DW 0 ;CURRENT BLOCK, USUALLY SAME AS ZPC1 +CURTAB DW 0 ;CURRENT PAGE TABLE POINTER +1 + ;GETPAG +RTIME1 DB 0 ;REFERENCE TIME, 1 1/2 WORDS USED +RTIME2 DW 0 +LPAGE DW 0 ;LAST REFERENCED PAGE NUMBER +LPLOC DW 0 ;AND ITS CORE LOCATION +LPTAB DW 0 ;AND ITS TABLE POINTER + + ;OPERATION TABLES: + ;ZERO ARGUMENT OPERATIONS +ZEROOP DW OPRTRU ;176 + DW OPRFAL ;177 + DW OPPRNI ;178 + DW OPPRNR ;179 + DW OPNOOP ;180 + DW OPSAVE ;181 + DW OPREST ;182 + DW OPRSTT ;183 + DW OPRSTA ;184 + DW OPFSTA ;185 + DW OPQUIT ;186 + DW OPCRLF ;187 + DW OPUSL ;188 + DW OPVERI ;189 + DW 0 ;190 + DW 0 ;191 + ;ONE ARGUMENT OPERATIONS +ONEOP DW OPQZER ;128 + DW OPQNEX ;129 + DW OPQFIR ;130 + DW OPLOC ;131 + DW OPPTSI ;132 + DW OPINC ;133 + DW OPDEC ;134 + DW OPPRNB ;135 + DW 0 ;136 + DW OPREMO ;137 + DW OPPRND ;138 + DW OPRETU ;139 + DW OPJUMP ;140 + DW OPPRIN ;141 + DW OPVALU ;142 + DW OPBCOM ;143 + ;TWO ARGUMENT AND EXTENDED ARGUMENT OPERATIONS +EXTOP DW 0 ;0 + DW OPQEQU ;1 + DW OPQLES ;2 + DW OPQGRT ;3 + DW OPQDLE ;4 + DW OPQIGR ;5 + DW OPQIN ;6 + DW OPBTST ;7 + DW OPBOR ;8 + DW OPBAND ;9 + DW OPQFSE ;10 + DW OPFSET ;11 + DW OPFCLE ;12 + DW OPSET ;13 + DW OPMOVE ;14 + DW OPGET ;15 + DW OPGETB ;16 + DW OPGETP ;17 + DW OPGTPT ;18 + DW OPNEXT ;19 + DW OPADD ;20 + DW OPSUB ;21 + DW OPMUL ;22 + DW OPDIV ;23 + DW OPMOD ;24 + DW 0 ;25 + DW 0 ;26 + DW 0 ;27 + DW 0 ;28 + DW 0 ;29 + DW 0 ;30 + DW 0 ;31 + DW OPCALL ;224 + DW OPPUT ;225 + DW OPPUTB ;226 + DW OPPUTP ;227 + DW OPREAD ;228 + DW OPPRNC ;229 + DW OPPRNN ;230 + DW OPRAND ;231 + DW OPPUSH ;232 + DW OPPOP ;233 + DW 0 ;234 + DW 0 ;235 + DW 0 ;236 + DW 0 ;237 + DW 0 ;238 + DW 0 ;239 + DW 0 ;240 + DW 0 ;241 + DW 0 ;242 + DW 0 ;243 + DW 0 ;244 + DW 0 ;245 + DW 0 ;246 + DW 0 ;247 + DW 0 ;248 + DW 0 ;249 + DW 0 ;250 + DW 0 ;251 + DW 0 ;252 + DW 0 ;253 + DW 0 ;254 + DW 0 ;255 + + ;MCRLF +MORE DB "**MORE** ",80H +EMORE DB 13," ",13,80H +MORLIN DW 0 + + ;STRUCTURE AND RECORD DEFINITIONS: + ;OBJECT OPERATIONS +OBJECT STRUC +FLAGS1 DW ? +FLAGS2 DW ? +PARENT DB ? +SIBLING DB ? +CHILD1 DB ? +PROPS DW ? +OBJECT ENDS +PROPID RECORD PROPSIZE:3,PROPNUM:5 + + ;STRING DEFINITIONS + + ;STATION IDENTIFICATION +IDSTR DB "HP-DOS 2.0 Interpreter Version D",0 + + ;SAVE/RESTORE +SAV1 DB "File name (default is ",80H +SAV2 DB "): ",80H +SAV3 DB "Replace game disk then hit RETURN to continue.",80H + +ERR1 DB "SAVE file not found",0 +ERR3 DB "Bad file name syntax",0 +ERR4 DB "No room in directory for SAVE file",0 +ERR5 DB "No room on diskette for SAVE file",0 +ERR6 DB "Read of SAVE file failed",0 + ;READ +ERR2 DB "Too many words typed, flushing: ",80H + + ;OPNEXT/OPPUTP +FTL2 DB "No such property",0 + ;ZIPBGN +FTL4 DB "Wrong game or version",0 + ;NXTINS +FTL5 DB "Illegal operation",0 + ;FINDPG +FTL6 DB "No free pages",0 + ;GTBLKS +FTL7 DB "Game file read error",0 + ;SYSINI +FTL9 DB "Game file not found",0 + ;Fatal error header +FATHDR DB "Fatal error: ",80H + ;ZSTR CHARACTER CONVERSION VECTOR + +ZCHRS DB "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + DB " 0123456789.,!?_#'" + DB '"/\-:()' + +DBGFLG DB 0 +INSCNT DW 0 + +DATA_SG ENDS + + SUBTTL MACROS + PAGE + + +GTAWRD MACRO D,S ;;GET ABSOLUTE WORD + MOV D&X,ES:&S + XCHG D&H,D&L + ENDM + +PTAWRD MACRO D,S ;;PUT ABSOLUTE WORK + XCHG S&H,S&L + MOV ES:&D,S&X + ENDM + +MOVM MACRO D,S,R ;;MOVE MEMORY TO MEMORY + MOV R,S + MOV D,R + ENDM + +PUSHZ MACRO S ;;PUSH ONTO Z STACK + XCHG SP,DI + PUSH S + XCHG SP,DI + ENDM + +POPZ MACRO D ;;POP FROM Z STACK + XCHG SP,DI + POP D + XCHG SP,DI + ENDM + +POPZT MACRO D ;;GET TOP OF Z STACK + MOV D,SS:[DI] + ENDM + +PUSHZT MACRO S ;;PUT TOP OF Z STACK + MOV SS:[DI],S + ENDM + +PRINT MACRO STR ;;PRINT A STRING, POINTER IS ARGUMENT + PUSH AX + MOV AX,OFFSET STR + CALL MPRNT + POP AX + ENDM + +FATAL MACRO ERR ;;PRINT FATAL ERROR AND DIE + CALL MCRLF + MOV AX,OFFSET FATHDR + CALL MPRNT + MOV AX,OFFSET ERR + CALL MPRNT + JMP FINISH + ENDM + + SUBTTL SYSTEM INITIALIZATION + PAGE + + +CODE_SG SEGMENT PARA +ASSUME CS:CODE_SG,DS:DATA_SG,ES:GAME_SG,SS:STK_SG + +START PROC FAR + MOVM DS,DATA_SG,AX + MOVM ES,GAME_SG,AX + MOVM SS,STK_SG,AX + MOV SP,OFFSET STK_TOP + MOV DI,OFFSET ZSTK_TP + JMP ZIPBGN ;JUMP TO BEGINNING OF ZIP CODE +START ENDP + +FEEP PROC + MOV AX,7 + CALL MTTYO ;BELL + RET +FEEP ENDP + +OPVERI PROC + PRINT IDSTR + MOV AX,ES:[PLENTH] + XCHG AH,AL + PUSH SI + PUSH DI + PUSH ENDLOD + CALL BSPLIT + MOV SI,AX + MOV DI,BX + MOV AX,0 + MOV BX,64 + MOV DX,0 + MOV ENDLOD,0 +OPVR1: PUSH SI + PUSH DI + PUSH DX + CALL GETBYT + POP DX + POP DI + POP SI + ADD DX,CX + CMP AX,SI + JNE OPVR1 + CMP BX,DI + JNE OPVR1 + MOV AX,ES:[PCHKSM] + XCHG AH,AL + POP ENDLOD + POP DI + POP SI + CMP AX,DX + JE OPVR2 + JMP PFALSE +OPVR2: JMP PTRUE +OPVERI ENDP + +OPREST PROC + MOV DSKDIR,0 ;INDICATE RESTORE + JMP OSV0$ +OPREST ENDP + +OPSAVE PROC + MOV DSKDIR,1 ;INDICATE WRITE +OSV0$: PRINT SAV1 + MOV AL,SAVFCB + CMP AL,0 + JE OSVD1 + ADD AL,64 + CALL MTTYO + MOV AL,":" + CALL MTTYO +OSVD1: MOV CX,8 + MOV BX,OFFSET SAVFCB +OSVD3: INC BX + MOV AL,BYTE PTR [BX] + CMP AL,20H + JE OSVD2 + CALL MTTYO + LOOP OSVD3 +OSVD2: MOV AL,"." + CALL MTTYO + MOV CX,3 + MOV BX,OFFSET SAVFCB + ADD BL,8 +OSVD4: INC BX + MOV AL,BYTE PTR [BX] + CALL MTTYO + LOOP OSVD4 + PRINT SAV2 + CMP SCPL,50 + JG OSVD4A + CALL MCRLF +OSVD4A: MOV BX,OFFSET INBUF + MOV AL,15 ;X:FIRSTNAM.EXT + MOV BYTE PTR [BX],AL + MOV DX,BX + MOV AH,CRDLIN + INT 21H + MOV AL,10 + CALL MTTYO + PUSH ES + PUSH SI + PUSH DI + MOV SI,OFFSET INBUF + ADD SI,2 + MOV AX,DS + MOV ES,AX + MOV DI,OFFSET SAVFCB + MOV AH,CPRSNM + MOV AL,0EH ; USE DEFAULTS IN SAVFCB + INT 21H ; PARSE FILE NAME (FCB AT SAVFCB) + POP DI + POP SI + POP ES + CMP DSKDIR,1 + JE OSVOPW + MOV DX,OFFSET SAVFCB + MOV AH,CFOPEN + INT 21H ; OPEN THE FILE + CMP AL,0FFH + JE OSVPSX + JMP OSVPS +OSVPSX: MOV AX,OFFSET ERR1 + JMP OSVPER +OSVOPW: MOV DX,OFFSET SAVFCB + MOV AH,CFDELE + INT 21H + MOV DX,OFFSET SAVFCB + MOV AH,CFMAKE + INT 21H + CMP AL,0FFH + JNE OSVPS + MOV AX,OFFSET ERR4 + JMP OSVPER + +OSVPS: XCHG DI,SP + PUSH ZPC1 + PUSH ZPC2 + PUSH ZLOCS + PUSH ZORKID + MOV STKBOT,SP + MOV SP,DI + MOV CL,5 + SHL AX,CL + PUSH AX + PUSH ES + MOV AX,SS + MOV ES,AX + MOV AX,0 + MOV BX,OFFSET STKBOT + MOV CX,2 + CALL SRBLKS + PUSHF + MOV DI,SP + MOV SP,STKBOT + POP AX + CMP AX,ZORKID + JE OSVT0 + FATAL FTL4 +OSVT0: POP ZLOCS + POP ZPC2 + POP ZPC1 + XCHG DI,SP + POPF + POP ES + POP AX + JNC OSV4X + JMP OSV4 +OSV4X: MOV AX,2 + SUB BX,BX + MOV CX,PURBOT + CALL SRBLKS + PUSHF + JC OSVCC + CMP DSKDIR,1 + JNE OSVCC + MOV AH,CFCLOS + MOV DX,OFFSET SAVFCB + INT 21H +OSVCC: CALL MCRLF +OSV3C: CALL NEWZPC + POPF + JC OSV4 + MOV AL,SCRFLG + XCHG AH,AL + MOV ES:[PFLAGS],AX + JMP PTRUE +OSV4: MOV AX,OFFSET ERR5 + CMP DSKDIR,1 + JE OSVPRR + MOV AX,OFFSET ERR6 +OSVPRR: JMP OSVPER +OPSAVE ENDP + +OSVPER PROC + CALL MPRNT + JMP PFALSE +OSVPER ENDP + +OPRSTT PROC + MOV BP,CHRPTR + MOV BYTE PTR DS:[BP],0 ;FORCE OUT THE BUFFER + PRINT OUTBUF + JMP RESTRT ;JUMP TO RESTART ADDRESS +OPRSTT ENDP + +OPQUIT PROC + JMP FINISH +OPQUIT ENDP + +OPUSL PROC + CMP SLFLG,0 + JNE OPUSL1 + RET +OPUSL1: PUSH DI + PUSH CHRPTR + MOV BX,SLSTR + MOV CHRPTR,BX + MOV AX,16 + MOV DI,SLTAB + MOV CX,3 +USLLP: PUSH AX + CALL GETVAR + MOV DX,[DI+4] + CALL USLSET + PUSH CX + PUSH DI + CALL WORD PTR [DI+2] + POP DI + MOV DX,[DI+6] + CALL USLSPC +USLN: ADD DI,8 + POP CX +USL1: POP AX + INC AX + LOOP USLLP + MOV AX,"$" + CALL PUTCHR + CALL MSOUT + POP CHRPTR + POP DI + RET + +USLSET: MOV BX,SLSTR + MOV CHRPTR,BX + ADD CHRPTR,DX + RET + +USLSPC: MOV CX,CHRPTR + SUB CX,SLSTR + SUB DX,CX + MOV CX,DX + JLE USLSP1 +USLSPL: MOV AX,20H + CALL PUTCHR + LOOP USLSPL +USLSP1: RET +OPUSL ENDP + + SUBTTL ARITHMETIC OPERATIONS + PAGE + + + ;ADD +OPADD PROC + ADD AX,BX ;ADD OPR1 AND OPR2 + JMP PUTVAL ;RETURN THE VALUE +OPADD ENDP + + ;SUB +OPSUB PROC + SUB AX,BX ;SUBTRACT OPR2 FROM OPR1 + JMP PUTVAL ;RETURN THE VALUE +OPSUB ENDP + + ;MULTIPLY AX BY BX +OPMUL PROC + IMUL BX ;MULTIPLY OPR1 BY OPR2,IGNORING OVERFLOW(DX) + JMP PUTVAL ;RETURN THE VALUE +OPMUL ENDP + + ;DIVIDE AX BY BX +OPDIV PROC + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + JMP PUTVAL ;RETURN THE VALUE +OPDIV ENDP + + ;MOD +OPMOD PROC + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + MOV AX,DX ;WE WANT REMAINDER + JMP PUTVAL ;RETURN THE VALUE +OPMOD ENDP + + ;RANDOM +OPRAND PROC + SUB AH,AH + MOV RTEMP,AX + MOV AX,RSEED1 + MOV BX,RSEED2 + MOV RSEED2,AX + CLC + RCR AX,1 + RCR BX,1 + XOR RSEED1,BX + MOV AX,RSEED1 + AND AX,0EFFFH + SUB DX,DX + DIV RTEMP + MOV AX,DX + INC AX ;MUST BE BETWEEN 1 AND N, INCLUSIVE + JMP PUTVAL ;SIMPLY RETURN +OPRAND ENDP + + ;LESS? +OPQLES PROC + CMP AX,BX ;IS OPR1 LESS THAN OPR2? + JL JPT ;YES, PREDICATE TRUE +JPF: JMP PFALSE ;NO, PREDICATE FALSE +JPT: JMP PTRUE +OPQLES ENDP + + ;GRTR? +OPQGRT PROC + CMP AX,BX ;IS OPR1 GREATER THAN OPR2? + JG JPT ;YES, PREDICATE TRUE + JMP JPF ;NO, PREDICATE FALSE +OPQGRT ENDP + + SUBTTL LOGICAL OPERATIONS + PAGE + + + ;BTST +OPBTST PROC + NOT AX ;TURN OFF BITS IN OPR2 THAT ARE ON IN OPR1 + AND BX,AX + JE JPT ;SUCCESS IF OPR2 COMPLETELY CLEARED + JMP JPF +OPBTST ENDP + + ;BOR +OPBOR PROC + OR AX,BX ;LOGICAL OR + JMP PUTVAL ;RETURN THE VALUE +OPBOR ENDP + + ;BCOM +OPBCOM PROC + NOT AX ;LOGICAL COMPLEMENT + JMP PUTVAL ;RETURN THE VALUE +OPBCOM ENDP + + ;BAND +OPBAND PROC + AND AX,BX ;LOGICAL AND + JMP PUTVAL ;RETURN THE VALUE +OPBAND ENDP + + SUBTTL GENERAL PREDICATES + PAGE + + + ;EQUAL? +OPQEQU PROC + NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV BX,ARGBLK ;GET OPR1 + CMP BX,ARGBLK[2] ;IS OPR1 EQUAL TO OPR2? + JE OQE1$ ;YES + CMP AX,3 ;NO, IS THERE A THIRD OPERAND? + JL OQE2$ ;NO + CMP BX,ARGBLK[4] ;YES, IS IT EQUAL TO OPR1? + JE OQE1$ ;YES + CMP AX,4 ;NO, IS THERE A FOURTH? + JL OQE2$ ;NO + CMP BX,ARGBLK[6] ;YES, IS IT EQUAL TO OPR1? + JNE OQE2$ ;NO +OQE1$: JMP PTRUE ;PREDICATE TRUE IF EQUAL +OQE2$: JMP PFALSE ;PREDICATE FALSE IF NOT +OPQEQU ENDP + + ;ZERO? +OPQZER PROC + CMP AX,0 ;IS OPR ZERO? + JNE OQZ1$ ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQZ1$: JMP PFALSE +OPQZER ENDP + + SUBTTL OBJECT OPERATIONS + PAGE + + + ;MOVE (OBJ1 INTO OBJ2) +OPMOVE PROC + PUSH AX ;PROTECT OPRS FROM REMOVE CALL + PUSH BX + CALL OPREMO ;REMOVE OBJ1 FROM WHEREVER IT IS + POP DX ;OBJ2 + MOV AX,DX + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + POP CX ;OBJ1 + MOV AX,CX + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV ES:[BP].PARENT,DL ;PUT OBJ2 INTO OBJ1'S LOC SLOT + MOV DH,ES:[BX].CHILD1 ;GET CONTENTS OF OBJ2'S FIRST SLOT + MOV ES:[BX].CHILD1,CL ;MAKE OBJ1 FIRST CONTENT OF OBJ2 + CMP DH,0 ;WERE THERE ANY OTHER CONTENTS? + JE OMV1$ ;NO + MOV ES:[BP].SIBLING,DH ;YES, CHAIN ONTO OBJ1'S SIBLING SLOT +OMV1$: RET +OPMOVE ENDP + + ;REMOVE (OBJ FROM ITS PARENT) +OPREMO PROC + MOV CX,AX ;SAVE OBJ FOR LATER + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + MOV CH,ES:[BX].PARENT ;GET ITS PARENT + CMP CH,0 ;DOES IT HAVE A PARENT? + JE ORM3$ ;IF NOT, WE'RE DONE + MOV AL,CH ;PARENT + CALL OBJLOC ;FIND PARENT'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:[BP].CHILD1 ;GET PARENT'S FIRST CONTENT + CMP DL,CL ;IS IT OBJ? + JNE ORM1$ ;NO + MOVM ES:[BP].CHILD1,ES:[BX].SIBLING,AL ;YES, CHANGE SLOT TO + ;OBJ'S SIBLING + JMP ORM2$ ;AND RETURN +ORM1$: MOV AL,DL ;CURRENT SIBLING + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:[BP].SIBLING ;GET NEXT SIBLING IN CHAIN + CMP DL,CL ;IS IT OBJ? + JNE ORM1$ ;NO, CONTINUE LOOP + MOVM ES:[BP].SIBLING,ES:[BX].SIBLING,AL ;YES, CHANGE IT TO + ;OBJ'S SIBLING +ORM2$: MOV ES:[BX].PARENT,0 ;OBJ NOW HAS NO PARENT + MOV ES:[BX].SIBLING,0 ;OR SIBLING +ORM3$: RET +OPREMO ENDP + + ;FSET? (IS FLAG SET IN OBJ?) +OPQFSE PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OQF1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OQF1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + TEST AX,DX ;IS THIS BIT SET IN FLAG WORD? + JE OQF2$ ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQF2$: JMP PFALSE +OPQFSE ENDP + + ;FSET (SET A FLAG IN OBJ) +OPFSET PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFS1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFS1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + OR AX,DX ;SET THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + RET +OPFSET ENDP + + ;FCLEAR (CLEAR A FLAG IN OBJ) +OPFCLE PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFC1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFC1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,7FFFH ;SHIFT A BIT TO PROPER POSITION + ROR DX,CL + AND AX,DX ;CLEAR THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + RET +OPFCLE ENDP + + ;LOC (RETURN CONTAINER OF OBJ) +OPLOC PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].PARENT ;GET LOC SLOT + JMP BYTVAL ;RETURN THE BYTE VALUE +OPLOC ENDP + + ;FIRST? (RETURN FIRST SLOT OF OBJ, FAIL IF NONE) +OPQFIR PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].CHILD1 ;GET FIRST SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE +JPT1: JMP PTRUE ;NO, PREDICATE TRUE +JPF1: JMP PFALSE +OPQFIR ENDP + + ;NEXT? (RETURN THE NEXT (SIBLING) SLOT OF OBJ, FAIL IF NONE) +OPQNEX PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].SIBLING ;GET SIBLING SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE + JMP JPT1 ;NO, PREDICATE TRUE +OPQNEX ENDP + + ;IN? (IS OBJ1 CONTAINED IN OBJ2?) +OPQIN PROC + CALL OBJLOC ;FIND OBJ1'S LOCATION + XCHG AX,BX ;MOVE TO BASE + CMP ES:[BX].PARENT,AL ;IS OBJ1'S PARENT OBJ2? + JE JPT1 ;YES, PREDICATE TRUE + JMP JPF1 ;NO, PREDICATE FALSE +OPQIN ENDP + + ;GETP (GET SPECIFIED PROPERTY OF OBJ, DEFAULT IF NONE) +OPGETP PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGP2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JL OGP3$ ;IF LESS, NO SUCH PROPERTY HERE + MOV AL,ES:[BX] ;GOT IT, NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,MASK PROPSIZE;GET LENGTH BITS + MOV CL,PROPSIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + JNE OGP5$ ;NO + MOV AL,ES:[BX] ;GET THE BYTE + JMP BYTVAL ;AND RETURN IT +OGP3$: DEC DX ;POINT INTO DEFAULT PROPERTY TABLE + SHL DX,1 + MOV BX,DX +OGP4$: ADD BX,OBJTAB ;GET THE WORD +OGP5$: GTAWRD A,[BX] + JMP PUTVAL ;AND RETURN IT +OPGETP ENDP + + ;PUTP (CHANGE VALUE OF A PROPERTY, ERROR IF BAD NUMBER) +OPPUTP PROC + PUSH CX ;SAVE NEW VALUE + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OPP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OPP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OPP2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE OPP3$ ;IF EQUAL, GOT IT + JG OPP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR +OPP3$: MOV AL,ES:[BX] ;NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,MASK PROPSIZE;GET LENGTH BITS + MOV CL,PROPSIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + POP AX ;RESTORE NEW VALUE + JNE OPP4$ ;ZERO MEANS BYTE VALUE + MOV ES:[BX],AL ;STORE THE NEW BYTE + RET ;AND RETURN +OPP4$: PTAWRD [BX],A ;STORE THE NEW WORD VALUE + RET +OPPUTP ENDP + + ;NEXTP (RETURN NUMBER OF NEXT PROP FOLLOWING GIVEN PROB IN OBJ) +OPNEXT PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET ITS LOCATION + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + CMP DX,0 ;WERE WE GIVEN ZERO AS PROP? + JE ONX4$ ;YES, GO RETURN FIRST PROPERTY NUMBER + JMP ONX2$ ;NO, SKIP NEXT LINE FIRST TIME THROUGH LOOP +ONX1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE ONX3$ ;IF EQUAL, GOT IT + JG ONX1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR +ONX3$: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX4$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;EXTRACT PROPERTY NUMBER + JMP PUTVAL ;AND RETURN IT +OPNEXT ENDP + + SUBTTL TABLE OPERATIONS + PAGE + + + ;GET (GET THE ITEM'TH WORD FROM TABLE) +OPGET PROC + SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETWRD ;GET THE WORD + MOV AX,CX + JMP PUTVAL ;AND RETURN IT +OPGET ENDP + + ;GETB (GET THE ITEM'TH BYTE FROM TABLE) +OPGETB PROC + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETBYT ;GET THE BYTE + MOV AX,CX + JMP BYTVAL ;AND RETURN IT +OPGETB ENDP + + ;PUT (REPLACE THE ITEM'TH WORD IN TABLE) +OPPUT PROC + SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD BX,AX ;INDEX INTO TABLE + PTAWRD [BX],C ;STORE THE WORD + RET +OPPUT ENDP + + ;PUTB (REPLACE ITEM'TH BYTE IN TABLE) +OPPUTB PROC + ADD BX,AX ;INDEX INTO TABLE + MOV ES:[BX],CL ;STORE BYTE + RET +OPPUTB ENDP + + ;GETPT (GET POINTER TO PROPERTY TABLE FOR GIVEN PROP) +OPGTPT PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGT2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGT1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGT2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGT1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JE OGT3$ ;FOUND THE PROPERTY + SUB AX,AX ;RETURN ZERO FOR NO SUCH PROPERTY + JMP OGT4$ +OGT3$: INC BX ;POINT TO PROPERTY VALUE + MOV AX,BX ;AND RETURN IT +OGT4$: JMP PUTVAL +OPGTPT ENDP + + ;PTSIZE (RETURN SIZE OF PROPERTY TABLE) +OPPTSI PROC + MOV BX,AX ;TABLE POINTER + MOV AL,ES:[BX-1] ;GET PROPERTY INDENTIFIER + AND AL,MASK PROPSIZE;EXTRACT LENGTH BITS + SUB AH,AH + MOV CL,PROPSIZE + SHR AX,CL + INC AX ;ADJUST TO ACTUAL LENGTH + JMP PUTVAL ;RETURN IT +OPPTSI ENDP + + SUBTTL VARIABLE OPERATIONS + PAGE + + + ;VALUE (GET VALUE OF VAR) +OPVALU PROC + CALL GETVAR ;GET THE VALUE + JMP PUTVAL ;AND RETURN IT +OPVALU ENDP + + ;SET (VAR TO VALUE) +OPSET PROC + JMP PUTVAR ;STORE THE VALUE +OPSET ENDP + + ;PUSH (A VALUE ONTO THE STACK) +OPPUSH PROC + PUSHZ AX ;PUSH THE VALUE + RET +OPPUSH ENDP + + ;POP (A VALUE OFF THE STACK INTO VAR) +OPPOP PROC + POPZ BX ;POP A VALUE + JMP PUTVAR ;AND STORE IT +OPPOP ENDP + + ;INC (INCREMENT VAR) +OPINC PROC + MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT +OPINC1: MOV BX,AX ;VALUE + MOV AX,CX ;VARIABLE + JMP PUTVAR ;STORE NEW VALUE +OPINC ENDP + + ;DEC (DECREMENT VAR) +OPDEC PROC + MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + JMP OPINC1 ;STORE NEW VALUE +OPDEC ENDP + + ;IGRTR? (INCREMENT VAR & TEST IF GREATER THAN VAL) +OPQIGR PROC + PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE GREATER THAN VAL? + JLE OPQIG1 ;NO +OPQIG0: INC CX ;YES, CHANGE FLAG TO TRUE +OPQIG1: MOV BX,AX ;VALUE + POP AX ;RESTORE VARIABLE + CALL PUTVAR ;STORE NEW VALUE + CMP CX,0 ;TEST FLAG + JE OQI1$ ;FALSE, PREDICATE FALSE + JMP PTRUE ;ELSE, PREDICATE TRUE +OQI1$: JMP PFALSE +OPQIGR ENDP + + ;DLESS? (DECREMENT VAR & TEST IF LESS THAN VAL) +OPQDLE PROC + PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE LESS THAN VAL? + JGE OPQIG1 ;NO, PREDICATE FALSE + JMP OPQIG0 ;YES, PREDICATE TRUE +OPQDLE ENDP + + SUBTTL I/O OPERATIONS + PAGE + + +GETLIN PROC + PUSH BX + MOV AL,SCRFLG + PUSH AX + MOV SCRFLG,0 + PUSH SI + MOV CL,ES:[SI] + MOV BX,OFFSET INBUF + MOV BYTE PTR [BX],CL + MOV DX,BX + MOV AH,CRDLIN + INT 21H + MOV AH,CCONIO + MOV DL,10 + INT 21H + POP DX + MOV BX,OFFSET INBUF + MOV CL,BYTE PTR [BX+1] + SUB CH,CH + INC BX + CMP CL,0 + JE GETLEM +GETLLP: INC SI + INC BX + MOV AL,BYTE PTR [BX] + CMP AL,"A" + JL GETLLC + CMP AL,"Z" + JG GETLLC + ADD AL,32 +GETLLC: MOV ES:[SI],AL + LOOP GETLLP +GETLEM: INC SI + SUB AL,AL + MOV ES:[SI],AL + POP AX + MOV SCRFLG,AL + POP BX + RET +GETLIN ENDP + +PRTOUT PROC + PUSH AX + PUSH BX + PUSH CX + MOV DL,AL + MOV AH,CPROUT + INT 21H + POP CX + POP BX + POP AX + RET +PRTOUT ENDP + +SCRCHK PROC + PUSH AX + PUSH BX + PUSH DX + GTAWRD A,[PFLAGS] + TEST AL,1 ;CHECK IF SCRIPTING IS REQUESTED + JZ SCRNN$ + MOV SCRFLG,1 + SUB CX,CX + MOV BP,DX + INC BP +SCR1L$: MOV AL,ES:[BP] + INC BP + CMP BP,SI + JLE SCR2L$ + CALL PRTCRL + JMP SCREX$ +SCR2L$: CALL PRTOUT + INC CX + CMP CL,SCPL + JNE SCR1L$ + CALL PRTCRL + JC SCREX$ + SUB CX,CX + JMP SCR1L$ + +SCRNN$: MOV SCRFLG,0 +SCREX$: POP DX + POP BX + POP AX + RET +SCRCHK ENDP + +PRTCRL PROC + MOV AL,13 ;FINISH UP WITH CRLF + CALL PRTOUT + MOV AL,10 + CALL PRTOUT + RET +PRTCRL ENDP + + ;READ (A LINE OF INPUT & PARSE IT, LINE BUF IN ES:AX, + ;RETURN BUF IN ES:BX) +OPREAD PROC + MOV INSCNT,0 + PUSH AX ;SAVE LINE BUF + PUSH AX + PUSH BX + CALL OPUSL ;UPDATE STATUS LINE + POP BX + POP AX + MOV BP,CHRPTR ;NEXT CHARACTER POSITION + MOV BYTE PTR DS:[BP],80H ;DON'T END OUTPUT, IF ANY, WITH NEW LINE +ORD1$: PRINT OUTBUF ;FORCE OUT ANY QUEUED TEXT + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP SI ;INPUT BUFFER POINTER + MOV MORLIN,0 ;RE-INITIALIZE MORE COUNT FROM HERE + CALL GETLIN ;GET SOME CHARACTERS + CALL SCRCHK ;CHECK FOR SCRIPTING, SCRIPT INPUT IF ON +ORDNS$: PUSH DI + MOV RDBOS,DX ;INITIALIZE RDBOS + MOV RDEOS,SI ;AND RDEOS + MOV RDRET,BX ;STORE RET POINTER + MOV RDNWDS,0 ;NO WORDS SO FAR + INC DX ;SKIP LENGTH BYTE + MOV DI,BX ;THIS WILL BE WORD ENTRY POINTER + INC DI ;SKIP MAX WORDS & NWORDS BYTES + INC DI +ORD8$: MOV CX,OFFSET RDWSTR;HERE FOR NEXT WORD, POINT TO WORD STRING + MOV BX,DX ;AND SAVE BEGINNING OF WORD POINTER +ORD9$: CMP DX,RDEOS ;END OF STRING? + JNE ORD10$ ;NO + CMP CX,OFFSET RDWSTR;YES, WAS A WORD FOUND? + JNE ORD15$ ;YES, WE STILL HAVE TO LOOKUP WORD + JMP ORD23$ ;NO, WE'RE DONE +ORD10$: MOV BP,DX ;GET NEXT CHARACTER FROM BUFFER + MOV AL,ES:[BP] + CMP AL,"A" + JL ORD1A$ + CMP AL,"Z" + JG ORD1A$ + ADD AL,32 ;LOWERCASIFY ALPHABETICS +ORD1A$: INC DX + MOV SI,OFFSET RBRKS ;LIST OF READ BREAK CHARACTERS +ORD11$: INC SI + CMP AL,[SI-1] ;SEARCH LIST FOR THIS ONE + JE ORD12$ ;FOUND IT + CMP BYTE PTR [SI],0 ;END OF LIST? + JNE ORD11$ ;NO, CONTINUE SEARCH + CMP CX,OFFSET RDWSTR[6] ;YES, NOT A BREAK, WORD STRING FULL? + JE ORD9$ ;YES, LOOP UNTIL END OF WORD + MOV BP,CX ;NO, TACK THIS CHARACTER ONTO STRING + MOV DS:[BP],AL + INC CX + JMP ORD9$ ;AND LOOP +ORD12$: CMP CX,OFFSET RDWSTR;WORD READ BEFORE THIS BREAK? + JNE ORD14$ ;YES + CMP SI,ESIBKS ;NO, BUT IS IT A SELF-INSERTING BREAK? + JBE ORD13$ ;YES + INC BX ;NO, UPDATE BEGINNING OF WORD TO SKIP BREAK + JMP ORD9$ ;AND RETURN TO LOOP TO FIND A WORD +ORD13$: MOV BP,CX ;STORE THE BREAK IN WORD STRING + MOV DS:[BP],AL + INC CX + JMP ORD15$ ;AND GO FOR THE WORD +ORD14$: DEC DX ;UNREAD TERMINATING BREAK IN CASE IT WAS SI +ORD15$: INC RDNWDS ;INCREMENT FOUND WORD COUNT + MOV BP,BX ;GREATER THAN MAX ALLOWED? + MOV BX,RDRET + MOV BL,ES:[BX] + CMP RDNWDS,BL + MOV BX,BP + JLE ORD16$ ;NO + PRINT ERR2 ;YES, INFORM LOSER + MOV AX,BX ;BEGINNING OF THIS WORD + MOV BP,RDEOS ;SAVE BYTE AFTER EOS + MOV BL,ES:[BP] + MOV BYTE PTR ES:[BP],0 ;ZERO IT TO MAKE STRING ASCIZ + CALL MPRNT ;PRINT IT + MOV ES:[BP],BL ;AND RESTORE OLD BYTE + DEC RDNWDS ;REMEMBER THAT WE FLUSHED THIS WORD + JMP ORD23$ ;AND WE'RE DONE +ORD16$: MOV AX,BX ;CALCULATE NUMBER OF CHARACTERS IN WORD + NEG AX + ADD AX,DX + MOV ES:[DI+2],AL ;SAVE THE NUMBER IN RET TABLE + SUB BX,RDBOS ;BYTE OFFSET FOR BEGINNING OF WORD + MOV ES:[DI+3],BL ;STORE IT, TOO + MOV BP,CX ;MAKE WORD STRING ASCIZ + MOV BYTE PTR DS:[BP],0 + MOV AX,OFFSET RDWSTR;POINT TO IT + CALL ZWORD ;AND CONVERT TO (2-WORD) ZWORD + PUSH DX ;SAVE CHAR & WORD ENTRY POINTERS + PUSH DI + MOV DI,AX ;FIRST ZWORD WORD + MOV SI,VWORDS ;NUMBER OF VOCABULARY WORDS + MOV AX,SI + DEC AX ;WE WANT TO POINT TO LAST WORD + MUL VWLEN ;MULTIPLY BY WORD LENGTH IN BYTES + ADD AX,VOCBEG ;ADD POINTER TO BEGINNING TO FIND LAST WORD + MOV CX,AX ;POINTER TO LAST WORD + MOV DX,DI ;FIRST ZWORD WORD + MOV DI,BX ;SECOND ZWORD WORD + MOV BX,VWLEN ;CALCULATE INITIAL OFFSET FOR BINARY SEARCH + SAR SI,1 +ORD17$: SAL BX,1 + SAR SI,1 + CMP SI,0 + JNE ORD17$ + MOV SI,VOCBEG ;BEGINNING OF WORD TABLE + ADD SI,BX ;ADD CURRENT OFFSET(HALF OF POWER-OF-2 TABLE) + PUSH AX ;SAVE + MOV AX,VWLEN ;AVOID FENCEPOST BUG FOR EXACT POWER-OF-2 TBL + SUB SI,AX + POP AX ;RESTORE +ORD18$: SAR BX,1 ;NEXT OFFSET WILL BE HALF OF PREVIOUS ONE + GTAWRD A,[SI] ;GET FIRST HALF OF CURRENT ZWORD + CMP DX,AX ;COMPARE DESIRED ONE TO IT + JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + MOV BP,SI ;SAME, GET SECOND HALF + INC BP + INC BP + GTAWRD A,[BP] + CMP DI,AX ;COMPARE DESIRED WORD WITH IT + JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + JMP ORD22$ ;SAME, WE'VE FOUND IT, RETURN IT +ORD19$: ADD SI,BX ;TO MOVE UP, ADD CURRENT OFFSET + CMP SI,CX ;HAVE WE MOVED PAST END OF TABLE? + JBE ORD21$ ;NO + MOV SI,CX ;YES, POINT TO END OF TABLE INSTEAD + JMP ORD21$ +ORD20$: SUB SI,BX ;TO MOVE DOWN, SIMPLY SUBTRACT OFFSET +ORD21$: CMP BX,VWLEN ;IS OFFSET RESOLUTION BELOW ONE WORD? + JGE ORD18$ ;NO, CONTINUE LOOP + SUB SI,SI ;YES, WORD NOT FOUND, RETURN ZERO +ORD22$: POP DI ;RESTORE WORD ENTRY POINTER + MOV DX,SI ;POINTER TO WORD FOUND + XCHG DH,DL + MOV ES:[DI],DX ;STORE IT + POP DX ;RESTORE CHAR POINTER + ADD DI,4 ;UPDATE POINTER FOR NEXT WORD ENTRY + JMP ORD8$ ;GO FOR IT +ORD23$: INC RDRET ;DONE, STORE NUMBER OF WORDS FOUND + MOV BP,RDRET + MOVM ES:[BP],RDNWDS,DL + POP DI ;RESTORE USER STACK POINTER + RET ;AND RETURN +OPREAD ENDP + + ;PRINTC (PRINT CHAR WHOSE ASCII VALUE IS GIVEN) +OPPRNC PROC + JMP PUTCHR ;QUEUE THE CHARACTER FOR PRINTING +OPPRNC ENDP + + ;PRINTN (PRINT A NUMBER) +OPPRNN PROC + MOV BX,AX ;NUMBER TO PRINT + CMP BX,0 + JNE OPN1$ ;NON-ZERO + MOV AX,"0" ;SPECIAL CASE ZERO + JMP PUTCHR +OPN1$: JG OPN2$ ;POSITIVE? + MOV AX,"-" ;NO, PRINT MINUS SIGN + CALL PUTCHR + NEG BX ;AND MAKE IT POSITIVE +OPN2$: SUB CX,CX ;COUNT OF DIGITS ON STACK + JMP OPN4$ ;START WITH GREATER-THAN-10 TEST +OPN3$: MOV AX,BX ;EXTRACT A DIGIT + MOV BP,10 + CWD + IDIV BP + PUSH DX ;PUSH IT + INC CX ;BUMP COUNT + MOV BX,AX ;GET QUOTIENT +OPN4$: CMP BX,10 ;MORE DIGITS TO EXTRACT? + JGE OPN3$ ;YES, GO LOOP + MOV AX,BX ;NO, GET LAST (FIRST) DIGIT + JMP OPN6$ ;ALREADY IN PLACE +OPN5$: POP AX ;POP NEXT DIGIT +OPN6$: ADD AX,"0" ;ASCIIZE IT + CALL PUTCHR ;QUEUE IT + DEC CX ;REDUCE DIGIT COUNT + JGE OPN5$ ;LOOP IF SOME LEFT + RET ;ELSE, RETURN +OPPRNN ENDP + + ;PRINT (THE STRING POINTED TO BY ES:AX) +OPPRIN PROC + CALL BSPLIT ;SPLIT THE BLOCK & WORD NUMBERS + JMP PUTSTR ;PRINT THE STRING +OPPRIN ENDP + + ;PRINTB (PRINT THE STRING POINTED TO BY THE BYTE-POINTER ES:AX) +OPPRNB PROC + CALL BSPLTB ;SPLIT THE BLOCK & BYTE NUMBERS + JMP PUTSTR ;PRINT THE STRING +OPPRNB ENDP + +;PSEUDO-INSTRUCTIONS FOR HOURS/MINUTES HERE FOR STATUS LINE +OPPRNH PROC + MOV PMFLAG,0 + CMP AL,12 + JL OPH0$ + MOV PMFLAG,1 +OPH0$: CMP AL,12 + JLE OPH1$ + SUB AL,12 ;HOUR SLOT IS 24 HOUR TIME +OPH1$: CMP AL,0 + JNE OPHZ$ + MOV AL,12 +OPHZ$: CMP AL,9 + JG OPH2$ + PUSH AX + MOV AL,32 + CALL PUTCHR ;OUTPUT SPACE FOR HOUR LESS THAN 10 + POP AX +OPH2$: CALL OPPRNN + MOV AL,":" + JMP PUTCHR ;AND COLON +OPPRNH ENDP + +OPPRNM PROC + CMP AL,9 + JG OPM1$ + PUSH AX + MOV AL,"0" + CALL PUTCHR + POP AX +OPM1$: CALL OPPRNN + MOV AL,32 + CALL PUTCHR + MOV AL,"a" + CMP PMFLAG,0 + JE OPM2$ + MOV AL,"p" +OPM2$: CALL PUTCHR + MOV AL,"m" + JMP PUTCHR +OPPRNM ENDP + + ;PRINTD (PRINT OBJ'S SHORT DESCRIPTION) +OPPRND PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + ADD AX,7 ;PROPERTY TABLE POINTER + MOV BP,AX + GTAWRD A,[BP] ;GET IT + INC AX ;POINT TO STRING + CALL BSPLTB ;SPLIT POINTER + JMP PUTSTR ;AND PRINT THE STRING +OPPRND ENDP + + ;PRINTI (PRINT THE STRING FOLLOWING THIS INSTRUCTION) +OPPRNI PROC + MOV AX,ZPC1 ;GET POINTER TO STRING + MOV BX,ZPC2 + CALL PUTSTR ;AND PRINT IT + MOV ZPC1,AX ;UPDATE ZPC + MOV ZPC2,BX + JMP NEWZPC +OPPRNI ENDP + + ;PRINTR (PRINTI FOLLOWED BY RTRUE) +OPPRNR PROC + CALL OPPRNI ;DO A PRINTI + CALL OPCRLF ;A CRLF + JMP OPRTRU ;AND AN RTRUE +OPPRNR ENDP + + ;CRLF (DO A NEWLINE) +OPCRLF PROC + JMP NEWLIN ;DO A NEWLINE +OPCRLF ENDP + + SUBTTL CONTROL OPERATIONS + PAGE + + + ;CALL (A FUNCTION WITH OPTIONAL ARGUMENTS), # OF ARGS IN AX +OPCALL PROC + NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV DX,AX ;NUMBER OF ARGUMENTS TO CALL + MOV AX,ARGBLK ;FUNCTION TO CALL + CMP AX,0 + JNE OCL1$ ;ZERO? + SUB AX,AX ;YES, SIMPLY RETURN A ZERO + JMP PUTVAL +OCL1$: PUSHZ ZPC1 ;OTHERWISE, SAVE OLD ZPC + PUSHZ ZPC2 + MOV CX,ZLOCS ;AND OLD LOCAL POINTER +; SUB CX,STKBOT ;BUT RELATIVIZE IT IN CASE OF SAVE + PUSHZ CX ;AND SAVE IT + CALL BSPLIT ;SPLIT FUNCTION POINTER + MOV ZPC1,AX ;MAKE IT THE NEW ZPC + MOV ZPC2,BX + CALL NEWZPC ;UPDATE ZPC STUFF + MOV ZLOCS,DI ;LOCALS WILL START AT NEXT STACK SLOT + SUB ZLOCS,2 + CALL NXTBYT ;NUMBER OF LOCALS + MOV BX,AX + MOV BP,OFFSET ARGBLK[2] ;POINT TO FIRST OPTIONAL ARG +OCL2$: DEC BX ;ANY MORE LOCALS? + JL OCL4$ ;NO, WE'RE DONE + CALL NXTWRD ;YES, GET THE NEXT LOCAL DEFAULT VALUE + DEC DX ;ANY MORE OPTIONALS GIVEN? + JLE OCL3$ ;NO + PUSHZ DS:[BP] ;YES, USE ITS VALUE + ADD BP,2 + JMP OCL2$ ;AND CONTINUE LOOP +OCL3$: PUSHZ AX ;OTHERWISE, USE DEFAULT + JMP OCL2$ ;AND LOOP +OCL4$: RET +OPCALL ENDP + + ;RETURN (FROM CURRENT FUNCTION CALL) +OPRETU PROC + MOV DI,ZLOCS ;RESTORE OLD TOP OF STACK + POPZ DX ;DUMMY POP [WHY?] + POPZ ZLOCS ;AND OTHER VALUES + +; MOV DX,STKBOT ;RE-ABSOLUTIZE THIS ONE +; ADD ZLOCS,DX + + POPZ ZPC2 + POPZ ZPC1 + PUSH AX ;VALUE TO RETURN + CALL NEWZPC ;UPDATE ZPC STUFF + POP AX + JMP PUTVAL ;RETURN THE VALUE +OPRETU ENDP + + ;RTRUE +OPRTRU PROC + MOV AX,1 ;RETURN A 1 + JMP OPRETU +OPRTRU ENDP + + ;RFALSE +OPRFAL PROC + SUB AX,AX ;RETURN A 0 + JMP OPRETU +OPRFAL ENDP + + ;JUMP (TO A NEW LOCATION) +OPJUMP PROC + ADD ZPC2,AX ;ADD OFFSET TO CURRENT ZPC + SUB ZPC2,2 ;ADJUST IT + JMP NEWZPC ;NORMALIZE IT & UPDATE ZPC STUFF +OPJUMP ENDP + + ;RSTACK (RETURN STACK) +OPRSTA PROC + POPZ AX ;POP A VALUE + JMP OPRETU ;AND RETURN IT +OPRSTA ENDP + + ;FSTACK (FLUSH A VALUE OFF THE STACK) +OPFSTA PROC + POPZ DX ;FLUSH ONE + RET +OPFSTA ENDP + + ;NOOP (NO OPERATION) +OPNOOP PROC + RET ;DO NOTHING +OPNOOP ENDP + + SUBTTL LOW LEVEL FUNCTIONS + PAGE + + + ;GET A BYTE, BLOCK-POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX, + ;UPDATE AX & BX TO REFLECT BYTE GOTTEN +GETBYT PROC + PUSH AX ;SAVE BLOCK-POINTER + CMP AX,ENDLOD ;IS THIS A PRELOADED LOCATION? + JGE GTY1$ ;NO + MOV CL,9 ;YES, RECONSTRUCT POINTER + SHL AX,CL ;SHIFT BLOCK POINTER BY 9 + OR AX,BX ;ADD IN THE OFFSET + XCHG AX,BX + MOV CL,ES:[BX] ;GET THE BYTE + JMP GTY2$ ;CLEAR UNWANTED BYTE & RETURN IT +GTY1$: CALL GETPAG ;FIND THE PROPER PAGE + ADD AX,BX ;POINT TO DESIRED BYTE + XCHG AX,BX + MOV CL,ES:[BX] ;GET IT +GTY2$: SUB CH,CH ;CLEAR UNWANTED BYTE & RETURN IT + MOV BX,AX + POP AX ;RESTORE BLOCK-POINTER + INC BX ;UPDATE POINTER + CMP BX,200H ;END-OF-PAGE? + JNE GTY3$ ;NO + SUB BX,BX ;YES, CLEAR BYTE-POINTER + INC AX ;AND UPDATE BLOCK-POINTER +GTY3$: RET +GETBYT ENDP + + ;GET A WORD, BLOCK POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX +GETWRD PROC + PUSH DX ;SAVE + CALL GETBYT ;GET HIGH-ORDER BYTE + PUSH CX ;SAVE IT + CALL GETBYT ;GET LOW-ORDER BYTE + POP DX ;GET OTHER BYTE + MOV CH,DL ;POSITION IT + POP DX ;RESTORE + RET +GETWRD ENDP + + ;GET THE NEXT BYTE, RETURN IT IN AX +NXTBYT PROC + PUSH BX ;SAVE + MOV BX,ZPC2 ;BYTE POINTER + ADD BX,CURPAG ;INDEX INTO CURRENT PAGE + PUSH ES:[BX] ;SAVE BYTE + INC ZPC2 ;UPDATE PC + CMP ZPC2,200H ;END-OF-PAGE? + JL NXB1$ ;NO + CALL NEWZPC ;YES, UPDATE PAGE +NXB1$: POP AX ;RETRIEVE BYTE + SUB AH,AH ;CLEAR UNWANTED BYTE + POP BX ;RESTORE + RET ;AND RETURN IT +NXTBYT ENDP + + ;GET THE NEXT WORD, RETURN IT IN AX +NXTWRD PROC + PUSH BX ;SAVE + CALL NXTBYT ;GET HIGH-ORDER BYTE + PUSH AX ;SAVE IT + CALL NXTBYT ;GET LOW-ORDER BYTE + POP BX ;GET HIGH-ORDER BYTE + MOV AH,BL ;POSITION IT + POP BX ;RESTORE + RET ;RETURN THE WORD +NXTWRD ENDP + + ;GET AN ARGUMENT GIVEN ITS TYPE IN AX +GETARG PROC + DEC AX ;EXAMINE ARGUMENT + JL NXTWRD ;0 MEANT LONG IMMEDIATE + JE NXTBYT ;1 MEANT SHORT IMMEDIATE + CALL NXTBYT ;2 MEANT VARIABLE, GET THE VAR + CMP AX,0 ;STACK? + JNE GETVAR ;NO, JUST GET THE VAR'S VALUE + POPZ AX ;YES, POP THE STACK + RET +GETARG ENDP + + ;GET VALUE OF A VARIABLE, VAR IN AX, VALUE RETURNED IN AX +GETVAR PROC + CMP AX,0 ;STACK? + JNE GTV1$ ;NO + POPZT AX ;YES, GET TOP-OF-STACK + RET +GTV1$: PUSH BP ;SAVE + CMP AX,16 ;LOCAL? + JGE GTV3$ ;NO + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV AX,[BP] ;AND GET IT +GTV2$: POP BP ;RESTORE + RET +GTV3$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + MOV BP,AX ;AND GET IT + GTAWRD A,[BP] + JMP GTV2$ +GETVAR ENDP + + ;UPDATE VALUE OF A VARIABLE, VAR IN AX, NEW VALUE IN BX +PUTVAR PROC + CMP AX,0 ;STACK? + JNE PTV1$ ;NO + PUSHZT BX ;YES, UPDATE TOP-OF-STACK + RET +PTV1$: CMP AX,16 ;LOCAL? + JGE PTV2$ ;NO + PUSH BP ;SAVE + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV [BP],BX ;AND UPDATE IT + POP BP ;RESTORE + RET +PTV2$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + XCHG AX,BX ;AND UPDATE IT + PTAWRD [BX],A + RET +PUTVAR ENDP + + ;RETURN VAL IN AX TO LOCATION SPECIFIED BY NEXTBYTE + ;DESTROYS BX, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION +BYTVAL PROC + SUB AH,AH ;THIS ENTRY FOR BYTE VALUE TO CLEAR HIGH BYTE + JMP PUTVAL +BYTVAL ENDP + +PUTVAL PROC + MOV BX,AX ;NORMAL ENTRY + CALL NXTBYT ;GET VAR TO USE + CMP AX,0 ;STACK? + JNE PUTVAR ;NO, GO STORE VALUE + PUSHZ BX ;YES, PUSH ONTO STACK + RET ;AND RETURN +PUTVAL ENDP + + ;PREDICATE HANDLERS TRUE & FALSE + ;DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FCNS +PFALSE PROC + SUB BX,BX ;PREDICATE WAS FALSE, CLEAR FLAG + JMP PPRED +PFALSE ENDP + +PTRUE PROC + MOV BX,1 ;PREDICATE WAS TRUE, SET FLAG + JMP PPRED +PTRUE ENDP + +PPRED PROC + CALL NXTBYT ;GET FIRST (OR ONLY) PREDICATE JUMP BYTE + TEST AX,80H ;NORMAL POLARITY PREDICATE? + JE PPR1$ ;NO, LEAVE FLAG ALONE + INC BX ;YES, INCREMENT FLAG +PPR1$: TEST AX,40H ;ONE-BYTE JUMP OFFSET? + JE PPR2$ ;NO + AND AX,0FF3FH ;YES, CLEAR SPECIAL BITS + JMP PPR3$ +PPR2$: AND AX,0FF3FH ;CLR SPECIAL BITS FROM HIGH-ORDER OFFSET BYTE + MOV CX,AX ;HIGH-ORDER BYTE + CALL NXTBYT ;GET LOW-ORDER BYTE + MOV AH,CL ;MOVE IN HIGH-ORDER BITS + TEST AX,2000H ;IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)? + JE PPR3$ ;NO + OR AX,0C000H ;YES, MAKE 16-BIT NUMBER NEGATIVE +PPR3$: DEC BX ;TEST FLAG + JE PPR6$ ;WAS 1, THAT MEANS DO NOTHING + CMP AX,0 ;ZERO JUMP? + JNE PPR4$ ;NO + JMP OPRFAL ;YES, THAT MEANS DO AN RFALSE +PPR4$: DEC AX ;ONE JUMP? + JNE PPR5$ ;NO + JMP OPRTRU ;YES, THAT MEANS DO AN RTRUE +PPR5$: DEC AX ;ADJUST OFFSET + ADD ZPC2,AX ;ADD TO PC + JMP NEWZPC ;AND UPDATE ZPC STUFF +PPR6$: RET +PPRED ENDP + + ;SPLIT BYTE-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE OFFSET IN BX +BSPLTB PROC + MOV BX,AX + XCHG AL,AH ;EXTRACT BLOCK BITS + SHR AX,1 + AND AX,7FH ;CLEAR UNWANTED BITS + AND BX,1FFH ;CLEAR ALL BUT BYTE OFFSET BITS + RET +BSPLTB ENDP + + ;SPLIT WORD-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE-OFFSET IN BX +BSPLIT PROC + MOV BX,AX + MOV AL,AH ;EXTRACT BLOCK BITS + SUB AH,AH ;CLEAR UNWANTED BITS + SUB BH,BH ;CLEAR ALL BUT WORD OFFSET BITS + SHL BX,1 ;CONVERT TO BYTE OFFSET + RET +BSPLIT ENDP + + SUBTTL OBJECT HACKERS + PAGE + + + ;GIVEN OBJ NUMBER IN AX, RETURN OBJ LOCATION IN AX +OBJLOC PROC + SUB AH,AH ;CLEAR UNWANTED BITS + PUSH BX ;MULTIPLY BY 9 THE LAZY WAY + MOV BX,AX + SHL AX,1 + SHL AX,1 + SHL AX,1 + ADD AX,BX + POP BX ;RESTORE + ADD AX,OBJTAB ;INDEX INTO OBJECT TABLE + ADD AX,53 ;SKIPPING DEFAULT PROPERTY TABLE + RET +OBJLOC ENDP + + ;GIVEN POINTER TO A PROPERTY IN BX!, UPDATE IT TO POINT TO NEXT PROP +NXTPRP PROC + PUSH AX ;SAVE + PUSH CX ;SAVE + MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPSIZE;EXTRACT PROPERTY LENGTH (MINUS 1) + MOV CL,PROPSIZE + SHR AL,CL + SUB AH,AH + ADD BX,AX ;ADD IT TO OLD POINTER + ADD BX,2 ;ADJUST FOR EXTRA LENGTH BYTE PLUS IDENTIFIER + POP CX ;RESTORE + POP AX ;RESTORE + RET +NXTPRP ENDP + + SUBTTL STRING FUNCTIONS + PAGE + + + ;OUTPUT A ZSTR, BLOCK-POINTER IN AX, BYTE-POINTER IN BX + ;RETURN UPDATED POINTER +PUTSTR PROC + PUSH SI ;SAVE + PUSH CX ;SAVE + PUSH DX ;SAVE + PUSH DI ;SAVE + PUSH BP ;SAVE + SUB DX,DX ;TEMP CS STARTS AT 0 + SUB DI,DI ;PERM CS STARTS AT 0 +PTS1$: CALL GETWRD ;GET NEXT STRING WORD + MOV SI,CX + PUSH AX ;SAVE POINTER & COPY OF STRING WORD + PUSH BX + PUSH SI + MOV CX,3 ;3 BYTES IN WORD +PTS2$: PUSH SI ;SAVE CURRENT BYTE (IN LOW-ORDER POSITION) + MOV BP,CX ;SHIFT TO NEXT BYTE + MOV CL,5 + SAR SI,CL + MOV CX,BP + LOOP PTS2$ ;LOOP UNTIL DONE + MOV CX,3 ;RETRIEVE THE 3 BYTES +PTS3$: POP SI ;GET NEXT BYTE + AND SI,1FH ;CLEAR UNWANTED BITS + CMP DX,0 ;IN WORD MODE? + JGE PTS4$ ;NO {WAS BPL, CHECK} + SAL SI,1 ;YES, CALCULATE WORD OFFSET + ADD SI,WRDTAB ;POINT INTO WORD TABLE + ADD SI,WRDOFF ;USING PROPER 32-WORD BLOCK + GTAWRD A,[SI] ;POINT TO WORD STRING + CALL BSPLIT ;SPLIT IT + CALL PUTSTR ;AND PRINT IT + JMP PTS15$ ;CONT. WHERE WE LEFT OFF WITH TEMP CS RESET +PTS4$: CMP DX,3 ;CS 3 SELECTED (ASCII MODE)? + JL PTS6$ ;NO, NORMAL CS + JNE PTS5$ ;NO, BUT WE ARE IN ASCII MODE + XCHG DL,DH ;SHIFT SOME BITS HIGH TO MAKE NUMBER LARGE + OR DX,SI ;SAVE HIGH-ORDER ASCII BITS HERE + JMP PTS16$ ;GO GET NEXT BYTE +PTS5$: AND DX,3 ;EXTRACT PREVIOUSLY SAVED HIGH-ORDER BITS + MOV BP,CX ;POSITION THEM + MOV CL,5 + SAL DX,CL + MOV CX,BP + OR DX,SI ;OR IN LOW-ORDER BITS + MOV AX,DX + JMP PTS14$ ;GO PRINT THE CHARACTER +PTS6$: CMP SI,6 ;SPECIAL CODE? + JL PTS9$ ;YES, SPACE, WORD, OR SHIFT + CMP DX,2 ;MIGHT ALSO BE SPECIAL IF IN CS 2 + JNE PTS8$ ;BUT WE'RE NOT + CMP SI,7 ;CRLF? + JE PTS7$ ;YES + JG PTS8$ ;NO, NOT ASCII MODE, EITHER? + INC DX ;YES IT IS, SWITCH TO ASCII MODE + JMP PTS16$ ;AND GO GET NEXT BYTE +PTS7$: CALL NEWLIN ;CRLF REQUESTED, DO A NEWLINE + JMP PTS15$ +PTS8$: MOV AX,DX ;NORMAL CHARACTER, GET CS + MOV BP,26 ;CALCULATE OFFSET FOR THIS CS + MUL BP + ADD AX,SI ;ADD IN CHARACTER OFFSET (+6) + SUB AX,6 ;CHARACTER OFFSET + MOV BX,OFFSET ZCHRS ;GET THE CHARACTER FROM CONVERSION VECTOR + XLAT ZCHRS + JMP PTS14$ ;GO PRINT IT +PTS9$: CMP SI,0 ;IS IT A SPACE? + JNE PTS10$ ;NO + MOV AX," " ;YES, GO PRINT A SPACE + JMP PTS14$ +PTS10$: CMP SI,3 ;IS IT A WORD? + JG PTS11$ ;NO, MUST BE A SHIFT + OR DX,8000H ;SWITCH TO WORD MODE FOR NEXT BYTE + DEC SI ;CALCULATE WORD-TABLE BLOCK OFFSET + MOV BP,CX ;64 BYTES IN A BLOCK + MOV CL,6 + SHL SI,CL + MOV CX,BP + MOV WRDOFF,SI ;SAVE IT AND LOOP + JMP PTS16$ +PTS11$: SUB SI,3 ;CALCULATE NEW CS + CMP DX,0 ;TEMPORARY SHIFT (FROM CS 0)? + JNE PTS12$ ;NO + MOV DX,SI ;YES, JUST SAVE NEW TEMP CS + JMP PTS16$ +PTS12$: CMP SI,DX ;IS THIS THE CURRENT CS? + JE PTS13$ ;YES, DO A PERM SHIFT TO IT + SUB DX,DX ;OTHERWISE, PERM SHIFT TO CS 0 +PTS13$: MOV DI,DX ;TEMP & PERM CS'S ARE SAME NOW + JMP PTS16$ +PTS3A$: JMP PTS3$ ;DUMMY FOR NON-SHORT LOOP +PTS14$: CALL PUTCHR ;PRINT THE CHARACTER +PTS15$: MOV DX,DI ;RESET TEMP CS TO PERM CS +PTS16$: LOOP PTS3A$ ;NEXT BYTE + POP SI ;RESTORE POINTERS & ORIGINAL STRING WORD + POP BX + POP AX + CMP SI,0 ;END-OF-STRING? + JL PTS1A$ ;YES, CLEAN UP & RETURN UPDATED POINTER + JMP PTS1$ ;NO, GET NEXT WORD +PTS1A$: POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET +PUTSTR ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN THE CHARACTER SET # IN AX +CHRCS PROC + CMP AX,0 ;IS THIS A NULL? + JNE CCS1$ ;NO + MOV AX,3 ;YES, RETURN DUMMY CS NUMBER + RET +CCS1$: PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CONVERSION VECTOR +CCS2$: INC BX ;FOUND THE CHARACTER? + CMP AL,[BX-1] + JE CCS3$ ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CCS2$ ;NO, CONTINUE LOOP + MOV AX,2 ;YES, CALL IT CS 2 + JMP CCS5$ +CCS3$: SUB BX,OFFSET ZCHRS ;FIND CHARACTER POSITION + SUB AX,AX ;START WITH CS 0 +CCS4$: SUB BX,26 ;EVERY 26 CHARACTERS IS A NEW CS + JLE CCS5$ ;DONE + INC AX ;INCREMENT CS # & CONTINUE LOOP + JMP CCS4$ +CCS5$: POP BX + RET +CHRCS ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN ZSTR BYTE VALUE IN AX +CHRBYT PROC + PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CHARACTER CONVERSION TABLE +CHB1$: INC BX ;FOUND THE CHARACTER? + CMP AL,[BX-1] + JE CHB2$ ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CHB1$ ;NO, CONTINUE LOOP + SUB AX,AX ;YES, RETURN ZERO FOR FAILURE + JMP CHB4$ +CHB2$: SUB BX,OFFSET ZCHRS-5 ;ADJUST POINTER SO FIRST CHARACTER IS 6 + MOV AX,BX +CHB3$: CMP AX,32 ;SUBTRACT MULTIPLES OF 26 UNTIL BASE CODE + JL CHB4$ + SUB AX,26 + JMP CHB3$ +CHB4$: POP BX ;RESTORE + RET +CHRBYT ENDP + + ;CONVERT UP TO 6 ASCIZ CHARS POINTED TO BY DS:AX + ;TO A 2-WORD ZSTR RETURNED IN AX & BX +ZWORD PROC + PUSH SI ;SAVES + PUSH CX + PUSH DX + PUSH DI + PUSH BP + MOV SI,AX ;CHARACTER STRING POINTER + SUB DI,DI ;CS STARTS AT 0 + MOV CX,6 ;MAKE 6 ZSTR BYTES +ZWD1$: INC SI ;GET NEXT CHARACTER + MOV BL,[SI-1] + CMP BL,0 + JNE ZWD3$ ;NOT END-OF-STRING + MOV AX,OFFSET PADCHR;AT END-OF-STRING, PAD WITH PAD CHARACTER +ZWD2$: PUSH AX ;SAVE A PAD BYTE + LOOP ZWD2$ ;LOOP UNTIL DONE + JMP ZWD6$ ;THEN GO FORM ZWORD +ZWD3$: MOV AX,BX + CALL CHRCS ;FIND THE CS NUMBER FOR THIS CHAR + CMP AX,0 ;CS 0? + JE ZWD4$ ;YES + ADD AX,3 ;NO, CALCULATE TEMP SHIFT BYTE + PUSH AX ;SAVE THE SHIFT BYTE + DEC CX ;REDUCE BYTE COUNT + JE ZWD6$ ;DONE +ZWD4$: MOV AX,BX ;FIND THE PROPER BYTE VALUE FOR THIS CHAR + CALL CHRBYT + CMP AX,0 ;IN NORMAL CS'S? + JNE ZWD5$ ;YES + MOV AX,6 ;NO, USE ASCII SHIFT + PUSH AX + DEC CX ;DONE YET? + JE ZWD6$ ;YES + MOV AX,BX ;NO, SAVE HIGH-ORDER ASCII BITS + MOV BP,CX + MOV CL,5 + SAR AX,CL + MOV CX,BP + PUSH AX + DEC CX ;DONE YET? + JE ZWD6$ ;YES + AND BX,1FH ;NO, SAVE LOW-ORDER ASCII BITS + MOV AX,BX +ZWD5$: PUSH AX ;SAVE THIS BYTE + LOOP ZWD1$ ;LOOP UNTIL ZWORD FULL +ZWD6$: MOV BP,SP ;BUILD ZWORD WORDS FROM 6 SAVED BYTES + MOV AX,[BP+10] + MOV CL,5 + SHL AX,CL + OR AX,[BP+8] + SHL AX,CL + OR AX,[BP+6] + MOV BX,[BP+4] + SHL BX,CL + OR BX,[BP+2] + SHL BX,CL + OR BX,[BP] + OR BX,8000H ;SET END-OF-STRING BIT IN SECOND WORD + ADD SP,12 ;FLUSH STACK + POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET +ZWORD ENDP + + SUBTTL TERMINAL I/O + PAGE + + + ;QUEUE CHARACTER IN AX FOR OUTPUT +PUTCHR PROC + PUSH BP + MOV BP,CHRPTR + CMP BP,ENDBUF + JNE PTC7 + PUSH AX + PUSH BX + PUSH SI + MOV BX,ENDBUF + MOV SI,OFFSET OUTBUF +PTC1: DEC BX + CMP BYTE PTR [BX]," " + JE PTC3 + CMP BX,SI + JNE PTC1 +PTC2: PRINT OUTBUF + MOV CHRPTR,SI + MOV BP,SP + CMP BYTE PTR 4 [BP]," " + JNE PTC6 + MOV WORD PTR 4 [BP],0 + JMP PTC6 +PTC3: CMP BX,SI + JE PTC2 + MOV BYTE PTR [BX],0 + PRINT OUTBUF + MOV AX,ENDBUF + INC BX +PTC4: CMP BX,AX + JE PTC5 + MOV BP,AX + MOV AL,[BX] + MOV [SI],AL + MOV AX,BP + INC BX + INC SI + JMP PTC4 +PTC5: MOV CHRPTR,SI +PTC6: POP SI + POP BX + POP AX + CMP AX,0 + JE PTC8 +PTC7: MOV BP,CHRPTR + MOV DS:[BP],AL + INC CHRPTR +PTC8: POP BP + RET +PUTCHR ENDP + + ;GO TO NEW LINE, OUTPUTTING CURRENT BUFFER +NEWLIN PROC + PUSH BX ;SAVE + MOV BX,CHRPTR ;END LINE AT CURRENT POINT + MOV BYTE PTR [BX],0 + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP BX ;RESTORE + PRINT OUTBUF ;AND OUTPUT LINE + RET +NEWLIN ENDP + + SUBTTL TOP LEVEL STUFF + PAGE + + + ;INITIALIZATION +TSETUP PROC + MOV BX,OFFSET OUTBUF + MOV CL,SCPL + SUB CH,CH + ADD BX,CX + MOV ENDBUF,BX + MOV BYTE PTR [BX],0 + MOV BX,OFFSET SLSTAB + CMP TIMEMD,0 + JE TSET1 + ADD BX,8 +TSET1: CMP CX,55 + JL TSET2 + MOV AX,60 + SUB CX,80 + MOV SI,4 + JMP TSET3 +TSET2: MOV AX,15 + SUB CX,40 + SUB SI,SI +TSET3: SUB AX,CX + ADD AX,[BX][SI] + MOV BX,2[BX][SI] + ADD 12[BX],CX + ADD 14[BX],CX + ADD 20[BX],CX + ADD 22[BX],CX + MOV SLSTR,AX + MOV SLTAB,BX + CALL MINIT + RET +TSETUP ENDP + + ;INITIALIZATION +TTSETUP PROC + MOV BX,OFFSET OUTBUF + MOV AL,SCPL + SUB AH,AH + ADD BX,AX + MOV ENDBUF,BX + MOV BYTE PTR [BX],0 + MOV BX,OFFSET SLSTAB + CMP TIMEMD,0 + JE TSET1 + ADD BX,8 +TTSET1: MOV SI,0 + CMP SCPL,39 + JE TSET2 + ADD SI,4 +TTSET2: MOV AX,[BX][SI] + MOV SLSTR,AX + MOV CX,2[BX][SI] + MOV SLTAB,CX + CALL MINIT + RET +TTSETUP ENDP + +ZIPBGN PROC + CALL SYSINI ;DO ANY SYSTEM INITIALIZATION +STR5$: SUB AX,AX ;BLOCK 0 + SUB BX,BX ;PUT AT BEGINNING OF GAME SEGMENT + CALL GETBLK ;GET THE BLOCK + CMP BYTE PTR ES:[PVERS1],ZMVERS ;PROPER Z-MACHINE VERSION? + JNE STR8$ ;NO + TEST BYTE PTR ES:[PVERS2],1 ;YES,PROPER MODE BITS? + JE STR9$ ;YES +STR8$: FATAL FTL4 ;SOMETHING WRONG, DIE +STR9$: TEST BYTE PTR ES:[PVERS2],2 ;TIME MODE REQUESTED? + JE STR10$ ;NO + INC TIMEMD ;YES, SET TIME-MODE FLAG +STR10$: MOV AL,BYTE PTR ES:[PVERS2] + CMP SLFLG,0 + JNE STR11$ + OR AL,10H ;TURN ON THE NO STATUS LINE BIT + MOV BYTE PTR ES:[PVERS2],AL +STR11$: GTAWRD A,[PZRKID] ;UNIQUE GAME & VERSION INDENTIFIER + MOV ZORKID,AX + GTAWRD A,[PENDLD] ;GET ENDLOD POINTER + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR12$ + AND AX,0FE00H + ADD AX,200H +STR12$: MOV CX,AX + MOV BP,CX ;EXTRACT ENDLOD BLOCK + MOV CL,9 + SAR BP,CL + MOV CX,BP + MOV ENDLOD,CX ;SAVE ENDLOD BLOCK NUMBER + DEC CX ;NUMBER OF BLOCKS LEFT TO LOAD + MOV AX,1 ;STARTING WITH BLOCK 1 + MOV BX,200H ;LOCATION TO PUT THEM + CALL GTBLKS ;GET THE BLOCKS + GTAWRD A,[PVOCTB] ;VOCAB LOCATION + MOV VOCTAB,AX ;SAVE VOCABULARY TABLE POINTER + GTAWRD A,[POBJTB] ;GET OBJECT TABLE POINTER + MOV OBJTAB,AX + GTAWRD A,[PGLOTB] ;GET GLOBAL TABLE POINTER + MOV GLOTAB,AX + GTAWRD A,[PWRDTB] ;GET WORD TABLE POINTER + MOV WRDTAB,AX + GTAWRD A,[PPURBT] ;GET PURE CODE POINTER + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR13$ + ADD AX,200H +STR13$: MOV CL,9 ;EXTRACT BLOCK NUMBER + SAR AX,CL + AND AX,7FH ;CLEAR UNWANTED BITS + MOV PURBOT,AX ;SAVE IT + MOV BX,OFFSET RBRKS ;START OF READ BREAK CHARACTER TABLE + MOV SI,VOCTAB ;VOCAB TABLE POINTER + MOV CL,BYTE PTR ES:[SI] ;1ST BYTE IN VOCTAB IS # OF SIBREAKS + SUB CH,CH ;CLEAR HIGH BYTE + INC SI +STR14$: MOVM [BX],ES:[SI],AL ;TRANSFER THEM + INC BX + INC SI + LOOP STR14$ + MOV ESIBKS,BX ;REMEMBER END OF SI BREAKS + MOV BP,OFFSET IRBRKS;ALWAYS END WITH INITIAL BREAK CHARACTERS +STR15$: MOVM [BX],DS:[BP],AL ;TRANSFER THEM + INC BX + INC BP + CMP AL,0 + JNE STR15$ + MOV AL,ES:[SI] ;GET VOCABULARY ENTRY LENGTH + SUB AH,AH + MOV VWLEN,AX ;AND STORE IT AWAY + INC SI + GTAWRD A,[SI] ;GET NEXT WORD IN TABLE + MOV VWORDS,AX ;NUMBER OF WORD ENTRIES IN VOCABULARY + ADD SI,2 ;MOVE TO NEXT WORD + MOV VOCBEG,SI ;BEGINNING OF ACTUAL VOCABULARY + + MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + MOV CL,9 + SHL SI,CL ;THIS IS FIRST LOCATION (ES:) OF PAGING + MOV PAGES,SI ;SAVE THIS TO USE AS AN OFFSET + + MOV BUFPGS,23 ;OUR TABLE IS ONLY SO BIG.... + MOV SI,23 +STR16$: SHL SI,1 + SHL SI,1 ;EACH PAGE HAS 4 BYTES OF INFO + MOV BX,OFFSET PAGTAB ;POINT INTO PAGE INFO TABLE + ADD SI,BX + MOV WORD PTR [SI],-1 ;MAKE THIS THE END OF TABLE MARK + CALL MTIME +STR17$: JMP START1 +ZIPBGN ENDP + + ;RESTART EXECUTION HERE +RESTRT PROC + SUB AX,AX ;REREAD ALL OF THE IMPURE STUFF + SUB BX,BX + MOV CX,PURBOT + CALL GTBLKS + JMP RESTRT1 ; PATCH TO FIX STATUS LINE (3) +START1: + +; MOV AL,BYTE PTR ES:[PVERS2] +; ADD AL,8 ;TANDY BIT +; MOV BYTE PTR ES:[PVERS2],AL + + CALL TSETUP ;SETUP TERMINAL/STATUS LINE +RESTRT1:CALL CLRSCR ;CLEAR THE REMAINDER OF SCREEN + MOV SP,OFFSET STK_TOP ;INITIALIZE OUR STACK POINTER + MOV DI,OFFSET ZSTK_TP ;INITIALIZE USER STACK POINTER + MOV CHRPTR,OFFSET OUTBUF ;INITIALIZE OUTPUT CHARACTER POINTER + MOV ZLOCS,DI ;LOCALS WOULD START AT FIRST SLOT, + SUB ZLOCS,2 ;IF THERE WERE ANY + GTAWRD A,[PSTART] ;GET STARTING LOCATION + CALL BSPLTB ;SPLIT BLOCK & BYTE POINTERS + MOV ZPC1,AX ;INITIALIZE ZPC BLOCK-POINTER + MOV ZPC2,BX ;INITIALIZE ZPC BYTE-POINTER + CALL NEWZPC ;GET PAGE TO EXECUTE + JMP NXTINS +RESTRT ENDP + + ;MAIN INSTRUCTION INTERPRETATION LOOP +NXTINS PROC + CALL NXTBYT ;GET THE OPERATION BYTE + MOV DX,AX ;SAVE A COPY + CMP AX,80H ;IS IT A 2OP? + JL NXI9$ ;YES + CMP AX,0B0H ;NO, IS IT A 1OP? + JGE NXI0A$ ;NO + JMP NXI12$ ;YES +NXI0A$: CMP AX,0C0H ;IS IT A 0OP? + JG NXI0B$ ;NO + JMP NXI13$ ;YES +NXI0B$: AND AX,3FH ;IT'S EXTENDED, GET THE OPCODE + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET THE OPERATOR POINTER + MOV SI,DS:[BP+EXTOP] + CMP SI,0 + JNE NXI0C$ ;OPERATION EXISTS + JMP NXI14$ ;NO SUCH OPERATION +NXI0C$: CALL NXTBYT ;GET THE ARGUMENT BYTE + MOV CX,4 ;SPLIT IT INTO 4 2-BIT MODE BYTES +NXI1$: PUSH AX + SAR AX,1 + SAR AX,1 + LOOP NXI1$ + MOV CX,4 ;RETRIEVE THE 4 BYTES IN PROPER ORDER + SUB DX,DX + MOV BX,OFFSET ARGBLK;FIRST ARGUMENT SLOT +NXI2$: POP AX ;GET NEXT MODE BYTE? + AND AX,3 ;CLEAR OFF UNWANTED BITS + CMP AX,3 ;NO MORE ARGUMENTS? + JE NXI4$ ;YES, FLUSH ANY OTHER MODE BYTES + CALL GETARG ;ELSE, GET THE NEXT ARGUMENT + MOV [BX],AX ;SAVE IT IN ARGUMENT BLOCK + ADD BX,2 + INC DX ;REMEMBER NUMBER OF ARGS GOTTEN +NXI3$: LOOP NXI2$ ;LOOP FOR REST OF MODE BYTES + JMP NXI5$ +NXI4$: DEC CX ;DETERMINE NUMBER OF REMAINING MODE BYTES + SHL CX,1 ;WORD COUNT + ADD SP,CX ;FLUSH THEM +NXI5$: XCHG CX,DX + MOV AX,CX ;NUMBER OF ARGS GOES HERE FOR OPERATOR TO USE + CMP CS:BYTE PTR [SI],90H ;DOES OPERATOR WANT ARGBLK POINTER? + JE NXI8A$ ;YES, CALL OPERATOR NOW + DEC CX ;NO, IT WANTS ARGS IN REGISTERS + JL NXI8A$ ;NO ARGS, JUST CALL OPERATOR + JE NXI8$ ;1 ARG, GET IT + SUB CX,2 + JL NXI7$ ;2 ARGS + JE NXI6$ ;3 ARGS + MOV DX,ARGBLK[6] ;ELSE, 4 ARGS, GET 4TH +NXI6$: MOV CX,ARGBLK[4] ;GET 3RD +NXI7$: MOV BX,ARGBLK[2] ;GET 2ND +NXI8$: MOV AX,ARGBLK ;GET FIRST ARG +NXI8A$: JMP NXI15$ ;AND CALL OPERATOR +NXI9$: AND AX,1FH ;2OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;FIND POINTER TO OPERATOR ROUTINE + MOV SI,DS:[BP+EXTOP] + CMP SI,0 + JE NXI14$ ;NO SUCH OPERATION + MOV AX,1 ;ASSUME FIRST ARG IS AN IMMEDIATE + TEST DX,40H ;IS IT INSTEAD A VARIABLE? + JE NXI10$ ;NO + INC AX ;YES, CHANGE MODE +NXI10$: CALL GETARG ;GET THE FIRST ARG + PUSH AX ;SAVE IT + MOV AX,1 ;ASSUME SECOND ARG IS AN IMMEDIATE + TEST DX,20H ;IS IT INSTEAD A VARIABLE? + JE NXI11$ ;NO + INC AX ;YES, CHANGE MODE +NXI11$: CALL GETARG ;GET THE SECOND ARG + MOV BX,AX ;POSITION IT + POP AX ;RECOVER FIRST ARG + CMP CS:BYTE PTR [SI],90H ;DOES ROUTINE WANT ARGUMENT BLOCK? + JNE NXI15$ ;NO, GO CALL IT + MOV ARGBLK,AX ;YES, MOVE ARGS TO ARGBLK + MOV ARGBLK[2],BX + MOV AX,2 ;ALWAYS 2 ARGS + JMP NXI15$ ;NOW CALL OPERATOR +NXI12$: AND DX,0FH ;1OP, EXTRACT OPERATION BITS + SHL DX,1 ;MAKE IT A WORD OFFSET + MOV BP,DX ;GET OPERATOR ROUTINE POINTER + MOV SI,DS:[BP+ONEOP] + CMP SI,0 + JE NXI14$ ;ILLEGAL OPERATION + SAR AX,1 ;EXTRACT MODE BITS + SAR AX,1 + SAR AX,1 + SAR AX,1 + AND AX,3 + CALL GETARG ;GET THE ARGUMENT + JMP NXI15$ ;AND CALL OPERATOR +NXI13$: AND AX,0FH ;0OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET OPERATOR ROUTINE POINTER + MOV SI,DS:[BP+ZEROOP] + CMP SI,0 + JNE NXI15$ ;IT'S A LEGAL OPERATION +NXI14$: FATAL FTL5 ;OTHERWISE, COMPLAIN +NXI15$: CALL SI ;CALL THE OPERATOR ROUTINE + JMP NXTINS ;AND LOOP FOR NEXT INSTRUCTION +NXTINS ENDP + + SUBTTL PAGING ROUTINES + PAGE + + + ;NORMALIZE ZPC & GET PROPER PAGE +NEWZPC PROC + PUSH SI ;SAVES + PUSH BP + PUSH BX + PUSH CX + PUSH DX + SUB AX,AX ;USE DOUBLE-WORD ARITHMETIC + MOV BX,ZPC1 ;GET BLOCK-POINTER + MOV BH,BL ;POSITION IT + SUB BL,BL + SHL BX,1 + ADC AX,0 + MOV SI,ZPC2 ;GET BYTE-OFFSET + XCHG SI,AX ;DOUBLE-WORDIFY IT (MIGHT BE NEGATIVE) + CWD + XCHG SI,AX + ADD BX,SI ;ADD IT TO OTHER DOUBLE WORD + ADC AX,DX + MOV DX,BX + AND DX,1FFH ;EXTRACT BYTE-OFFSET + MOV ZPC2,DX ;SAVE IT + MOV CL,9 ;EXTRACT BLOCK-POINTER + SAR BX,CL + AND BX,7FH + TEST AX,1 ;TEST 17TH BIT + JE NWZ1$ ;WAS 0 + OR BX,80H ;WAS 1, SET PROPER BIT IN BLOCK-POINTER +NWZ1$: MOV ZPC1,BX ;SAVE IT + CMP BX,CURBLK ;HAS IT CHANGED? + JE NWZ5$ ;NO + MOV CURBLK,BX ;YES, REMEMBER NEW BLOCK + MOV AX,CURTAB ;IS OLD PAGE IN PAGING SPACE? + CMP AX,0 + JE NWZ2$ ;NO + MOV BP,AX ;YES, STORE CURRENT REF TIME FOR OLD PAGE + MOVM DS:[BP],RTIME1,CL + MOVM DS:[BP+1],RTIME2,CX + INC AX +NWZ2$: CMP BX,ENDLOD ;NEW PAGE ALREADY IN CORE? + JL NWZ3$ ;YES + MOV AX,BX ;NO, GET NEW PAGE + CALL GETPAG + MOV BX,AX + MOV AX,LPTAB ;GET NEW PAGE TABLE POINTER + INC AX ;POINT TO REF SLOT + MOV CURTAB,AX ;SAVE THIS POINTER FOR LATER + MOV BP,AX ;STORE HIGHEST RTIME TO KEEP PAGE FOR US + MOV BYTE PTR DS:[BP],-1 + MOV WORD PTR DS:[BP+1],-1 + INC AX + JMP NWZ4$ +NWZ3$: MOV CL,9 ;CALCULATE PAGE ADDRESS + SHL BX,CL + MOV CURTAB,0 ;CLEARING POINTER MEANS PAGE IS PRELOADED +NWZ4$: MOV CURPAG,BX ;UPDATE PAGE POINTER +NWZ5$: POP DX ;RESTORES + POP CX + POP BX + POP BP + POP SI + RET ;AND RETURN +NEWZPC ENDP + + ;GET THE PAGE WHOSE NUMBER IS IN AX, RETURN A POINTER TO IT IN AX +GETPAG PROC + CMP AX,LPAGE ;IS THIS THE SAME PAGE AS LAST REFERENCED? + JNE GTP1$ ;NO + MOV AX,LPLOC ;YES, WE ALREADY HAVE LOCATION + RET ;RETURN IT +GTP1$: MOV LPAGE,AX ;SAVE NEW PAGE NUMBER + PUSH CX ;SAVES + PUSH BX + ADD RTIME2,1 ;UPDATE REFERENCE TIME (COUNT) + ADC RTIME1,0 + MOV BX,OFFSET PAGTAB;PAGE INFORMATION TABLE +GTP2$: INC BX + CMP AL,[BX-1] ;SEARCH FOR DESIRED BLOCK + JNE GTP3$ ;NOT IT + CMP AX,CURBLK ;IS THIS THE CURRENT CODE PAGE? + JE GTP2A$ ;DON'T UPDATE REFERENCE TIME + MOVM [BX],RTIME1,CL ;FOUND IT, UPDATE ITS REFERENCE TIME + MOVM [BX+1],RTIME2,CX +GTP2A$: DEC BX ;BACKUP TO BEGINNING OF TABLE ENTRY + MOV LPTAB,BX ;SAVE IT + SUB BX,OFFSET PAGTAB;CALCULATE ADDRESS OF PAGE + MOV CL,7 + SHL BX,CL + ADD BX,PAGES + JMP GTP4$ ;AND RETURN PAGE POINTER +GTP3$: ADD BX,3 ;SKIP REFERENCE TIME + CMP WORD PTR [BX],-1;END OF TABLE? + JNE GTP2$ ;NO, CONTINUE SEARCH + CALL FINDPG ;YES, FIND A PAGE TO LOAD INTO + PUSH AX ;PAGE POINTER + MOV LPTAB,BX ;SAVE PAGE TABLE POINTER + MOV AX,LPAGE ;SAVE NEW BLOCK NUMBER + MOV [BX],AL + MOVM [BX+1],RTIME1,CL;AND CURRENT REF TIME + MOVM [BX+2],RTIME2,CX + POP BX ;PAGE POINTER + CALL GETBLK ;GET THE BLOCK +GTP4$: MOV AX,BX ;RETURN PAGE POINTER + MOV LPLOC,AX ;AND SAVE IT FOR LATER + POP BX ;RESTORES + POP CX + RET +GETPAG ENDP + + ;FIND A GOOD PAGE, RETURN PAGE POINTER IN AX & PAGTAB POINTER IN BX +FINDPG PROC + PUSH CX + MOV BX,OFFSET PAGTAB + MOV CX,-1 ;FAKE BEST-CASE REFERENCE COUNT + MOV DX,CX + INC BX ;SKIP BLOCK NUMBER FOR NOW +FNP1$: INC BX ;IS THIS REF TIME WORSE THAN CURRENT WORST? + CMP [BX-1],CL + JA FNP3$ ;NO + JB FNP2$ ;YES + CMP [BX],DX ;MAYBE, COMPARE LOW-ORDER WORDS, WORSE? + JAE FNP3$ ;NO +FNP2$: MOV CL,[BX-1] ;YES, SAVE ITS REF COUNT + MOV DX,[BX] + MOV AX,BX ;AND LOCATION (+2) +FNP3$: ADD BX,3 ;SKIP SECOND WORD + CMP BYTE PTR [BX-1],-1 ;LOOP UNTIL END OF TABLE + JNE FNP1$ + INC CX ;WAS A PAGE REALLY FOUND? + JE FNP4$ ;NO, GROSS BUG! + SUB AX,2 ;YES, CALCULATE CORE LOCATION OF PAGE + MOV BX,AX + SUB AX,OFFSET PAGTAB + MOV CL,7 + SHL AX,CL + ADD AX,PAGES + POP CX ;RESTORES + RET +FNP4$: FATAL FTL6 +FINDPG ENDP + + SUBTTL HIGH LEVEL IBMPC DEPENDENT STUFF + + ;SYSTEM INITIALIZATION +SYSINI PROC + MOV AH,CFOPEN + MOV DX,OFFSET GAMFCB + INT 21H + CMP AL,0FFH + JE SYSFTL + + MOV BX,OFFSET TERMID ; FIND OUT WHICH COMPUTER + CALL MSPRT ; SEND IT TO SYSTEM + + MOV AH,8 ; CONSOLE INPUT WITHOUT ECHO + INT 21H ; GET THIRD CHARACTER OF ID SEQ. + INT 21H ; SHOULD BE "110A(CR)(LF)" + INT 21H ; OR " 150A(CR)(LF)" + CMP AL,"5" ; IF IT'S (5) THEN IT'S A 150 + JE AR2 ; SET UP FOR 150 + CMP AL,"2" ; 2623 CONFIGURATION + JE AR2 + + MOV SCPL,78 ; NUMBER OF COLUMNS FOR HP/110 + MOV SLPP,15 ; NUMBER OF ROWS FOR HP/110 + JMP DGONE + +AR2: INT 21H + MOV SCPL,78 ; NUMBER OF COLUMNS FOR HP/150 + MOV SLPP,23 ; NUMBER OF ROWS FOR HP/150 + +DGONE: MOV AH,8 + INT 21H ; CLEAR OUT THE BUFFER + INT 21H + RET + +SYSFTL: FATAL FTL9 +SYSINI ENDP + +CLRSCR PROC + RET +CLRSCR ENDP + + ;GET A GAME FILE BLOCK, BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX +GETBLK PROC + PUSH CX ;SAVE + MOV CX,1 ;CALL GTBLKS FOR 1 BLOCK ONLY + CALL GTBLKS + POP CX ;RESTORE + RET +GETBLK ENDP + +SRBLKS PROC + MOV DSKFCB,OFFSET SAVFCB + JMP GTBKI$ +SRBLKS ENDP + + ;GET A SERIES OF GAME FILE BLOCKS, + ;FIRST BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX # OF BLOCKS IN CX +GTBLKS PROC + MOV DSKDIR,0 ;READ MODE + MOV DSKFCB,OFFSET GAMFCB +GTBKI$: PUSH BX + PUSH DX + PUSH BP + SHL AX,1 + SHL AX,1 + SHL CX,1 + SHL CX,1 + MOV GTBSTT,AX + MOV GTBCOR,BX + MOV GTBCNT,CX +GTBLP: MOV AH,CSDMAO + MOV DX,OFFSET DSKBUF + INT 21H + MOV AX,GTBSTT + MOV BX,DSKFCB + MOV [BX+33],AX + MOV AH,CRDRND + CMP DSKDIR,0 + JE GTBKIR + PUSH SI + PUSH DI + PUSH DS + PUSH ES + PUSH CX + MOV CX,GTBCOR + MOV SI,DS + MOV DI,ES + MOV ES,SI + MOV DS,DI ; SWAP DS,ES + MOV SI,CX + MOV DI,OFFSET DSKBUF + MOV CX,128 +REP MOVSB + POP CX + POP ES + POP DS + POP DI + POP SI + MOV AH,CWRRND +GTBKIR: MOV DX,DSKFCB + INT 21H + CMP AL,1 ; 1=NO DATA + JE GTB2 + CMP AL,2 ; 2=DISK FULL + JE GTB2 ; 0=SUCCESSFUL , 3=PARTIAL READ 0 FILLED + CMP DSKDIR,0 + JNE GTBKK + PUSH SI + PUSH DI + PUSH CX + MOV SI,OFFSET DSKBUF + MOV DI,GTBCOR + MOV CX,128 +REP MOVSB + POP CX + POP DI + POP SI +GTBKK: DEC GTBCNT + JZ GTBFIN + ADD GTBCOR,128 + MOV BX,GTBCOR + INC GTBSTT + JMP GTBLP + +GTBFIN: CLC +GTBOUT: POP BP + POP DX + POP BX + RET + +GTB2: CMP DSKFCB,OFFSET GAMFCB + JE GTB3 + STC + JMP GTBOUT + +GTB3: FATAL FTL7 +GTBLKS ENDP + + SUBTTL IBMPC SYSTEM ROUTINES + PAGE + + + ;READ A CHARACTER INTO AX, WAITING UNTIL ONE IS AVAILABLE, NO ECHO +MCHRI PROC + PUSH CX + PUSH DX + CMP CHRFLG,0 + JNZ MCHR1 + MOV CHRFLG,1 +MCHR1: MOV AH,CCONIN + INT 21H + SUB AH,AH + POP DX + POP CX + RET +MCHRI ENDP + + ;PRINT THE CHARACTER IN AL, FOREGROUND IN AH +MTTYO PROC + PUSH AX + PUSH BX ;SAVES + PUSH CX + PUSH DX + PUSH BP + PUSH AX + MOV AH,CCONIO + MOV DL,AL + INT 21H + POP AX + CMP SCRFLG,0 + JZ MTYO1 + CALL PRTOUT +MTYO1: POP BP + POP DX + POP CX + POP BX + POP AX + RET +MTTYO ENDP + + ;PRINT SPACES, WITHOUT MOVING CURSOR, NUMBER IN AL, ATTRIBUTE IN AH +MSPC PROC + RET +MSPC ENDP + + ;PRINT A CARRIAGE RETURN/LINE FEED WITH MORE MODE +MCRLF PROC + PUSH AX ;SAVES + PUSH BX + PUSH CX + PUSH DX + PUSH BP + INC MORLIN ;INCREMENT NUMBER OF LINES OUTPUT + MOV AH,CCONIO + MOV DL,13 + INT 21H + MOV AH,CCONIO + MOV DL,10 + INT 21H + MOV AL,SLPP + SUB AH,AH + CMP MORLIN,AX + JL MCR1 + MOV MORLIN,0 + MOV AL,SCRFLG + PUSH AX + MOV SCRFLG,0 + PRINT MORE + CALL MCHRI + PRINT EMORE + POP AX + MOV SCRFLG,AL +MCR1: CMP SCRFLG,0 + JE MCR2 + CALL PRTCRL +MCR2: POP BP + POP DX + POP CX + POP BX + POP AX + RET +MCRLF ENDP + + ;OUTPUT STATUS LINE HERE +MSOUT PROC + CMP HPTYPE,1 ; IS IT A 150 + JNE AR01 ; NO + + MOV BX,OFFSET HPBLINE + CALL MSPRT + MOV AH,09H + MOV DX,SLSTR + INT 21H + MOV BX,OFFSET HPELINE + CALL MSPRT + RET + +AR01: MOV BX,OFFSET SBLINE + CALL MSPRT + MOV AH,09H + MOV DX,SLSTR + INT 21H + MOV BX,OFFSET SELINE + CALL MSPRT + RET +MSOUT ENDP + +MSPRT PROC + MOV CL,BYTE PTR [BX] + SUB CH,CH + CMP CL,0 + JE MSPRT1 +MSPLP: INC BX + MOV DL,BYTE PTR [BX] + MOV AH,06H + PUSH BX + INT 21H + POP BX + LOOP MSPLP +MSPRT1: RET +MSPRT ENDP + +MINIT PROC + CMP SLFLG,0 + JNE MINIT1 + RET + +MINIT1: CMP HPTYPE,1 ; IS IT A 150 + JNE AR1 ; NO THEN DO ANSI + MOV BX,OFFSET HPTINIT + CALL MSPRT + MOV BX,OFFSET HPELINE + CALL MSPRT + RET + +AR1: MOV BX,OFFSET STINIT ; ANSI OUTPUT + CALL MSPRT + MOV BX,OFFSET SELINE + CALL MSPRT + RET +MINIT ENDP + + ;PRINT A STRING, POINTER (TO DATA SEGMENT) IN AX, WHITE FOREGROUND +MPRNT PROC + PUSH BX ;SAVE BX + MOV BX,AX ;STRING POINTER +MPR1: MOV AL,[BX] ;GET NEXT CHARACTER + CMP AL,0 ;END OF LINE, WITH CRLF? + JE MPR2 ;YES + CMP AL,80H ;END OF LINE, NO CRLF? + JE MPR3 ;YES + CALL MTTYO ;PRINT CHARACTER + INC BX ;POINT TO NEXT CHARACTER + JMP MPR1 ;REPEAT +MPR2: CALL MCRLF ;PRINT A CRLF +MPR3: POP BX ;RESTORE BX + RET +MPRNT ENDP + + ;GET TIME +MTIME PROC + PUSH CX + PUSH DX + MOV AH,2CH + INT 21H + MOV RSEED1,CX + MOV RSEED2,DX + POP DX + POP CX + RET +MTIME ENDP + +FINISH PROC + CALL MCRLF + MOV BX,OFFSET STRESET + CALL MSPRT + MOV AH,4CH + INT 21H +FINISH ENDP + +CODE_SG ENDS + + .LIST + + END START diff --git a/hp/read.me b/hp/read.me new file mode 100644 index 0000000..9e6694e --- /dev/null +++ b/hp/read.me @@ -0,0 +1,13 @@ +******* Directory Update and Source File Archive Record ****** + + Date of Last Change Version Letter Who Made the Change + ___________________ _____________ ____________________ + +1) +2) +3) +4) +5) +6) +7) +8) diff --git a/ibm/--read.me b/ibm/--read.me new file mode 100644 index 0000000..20ff703 --- /dev/null +++ b/ibm/--read.me @@ -0,0 +1,13 @@ +******* Directory Update and Source File Archive Record ****** + + Date of Last Change Version Letter Who Made the Change + ___________________ _____________ ____________________ + +1) MAY 85 L PHG +2) +3) +4) +5) +6) +7) +8) diff --git a/ibm/boot.asm b/ibm/boot.asm new file mode 100644 index 0000000..16924a1 --- /dev/null +++ b/ibm/boot.asm @@ -0,0 +1,91 @@ + TITLE BOOT BOOTSTRAP LOADER FOR ZORK + +ABS SEGMENT AT 0H +ABS ENDS + +STK SEGMENT PARA STACK +STK ENDS + +DATA SEGMENT WORD +DATA ENDS + +CODE SEGMENT PARA +ASSUME CS:CODE + +START PROC FAR + CLI + SUB AX,AX + MOV DS,AX + MOV BX,78H + MOV CX,OFFSET CS:TBL$ + MOV DX,7C0H ; SIGH + MOV SI,[BX] + MOV DI,[BX+2] + MOV [BX],CX + MOV [BX+2],DX + + MOV AX,CS + MOV DS,AX + MOV DX,0 + MOV SS,DX + MOV BX,7C00H + MOV SP,BX + STI + + MOV AX,60H + MOV DS,AX + MOV ES,AX ; LOAD THE GAME AT SEGMENT 60H + SUB AX,AX + SUB DX,DX + INT 13H ; RESET THE DISK SYSTEM + MOV DX,3 ; WILL NEED THREE PASSES + SUB BX,BX ; LOAD TO ES:[BX] + MOV CH,1 ; START WITH TRACK 1 +LOOP$: PUSH DX ; GET NUMBER OF PASSES NEEDED TO LOAD + MOV CL,1 ; TRACK N, SECTOR 0 + PUSH CX + SUB DX,DX ; DRIVE 0, HEAD 0 + MOV AX,0204H ; READ, 4 SECTORS + INT 13H + JC YUK$ + POP CX ; GET BACK TRACK,SECTOR + INC CH ; NEXT TRACK NEXT TIME + ADD BX,1000H ; NEXT BUNCH OF CORE ALSO + POP DX + DEC DX + JNZ LOOP$ ; LOOP UNTIL DONE + SUB AX,AX + MOV DS,AX + MOV BX,78H + MOV [BX],SI + MOV [BX+2],DI + PUSH ES ; ES IS WHERE WE LOADED THE GAME + SUB AX,AX + PUSH AX ; CODE STARTS AT ZERO + RET ; JUMP TO INTERPRETER +YUK$: SUB BX,BX + MOV AL,"I" + MOV AH,14 + INT 10H + MOV AL,"L" + MOV AH,14 + INT 10H + MOV AL,"L" + MOV AH,14 + INT 10H + HLT +TBL$ DB 11001111B + DB 2 + DB 37 + DB 3 + DB 4 + DB 02AH + DB 0FFH + DB 050H + DB 0F6H + DB 25 + DB 4 +START ENDP +CODE ENDS + + END START diff --git a/ibm/boszip.asm b/ibm/boszip.asm new file mode 100644 index 0000000..04458fe --- /dev/null +++ b/ibm/boszip.asm @@ -0,0 +1,4361 @@ + TITLE ZIP Z-LANGUAGE INTERPRETER IBM/MS-DOS 2.0 VERSION + + PAGE 58,132 + .LIST + + ; Modification History - + ;--------------------------------------------------- + ; + ; 1) REWORKED FOR NEW SETUP FILE USAGE + ; 2) FIXED NON-WORKING STACK SAVE AND RESTORE FILE + ; 3) FIX RANDOM BUG - 6/25/84 + ; 4) FIXED STATUS LINE (LONG ROOM DESCRIPTION) - 07/24/84 + ; 5) Fixed status line bug on restart 22-Oct-84 - PHG "G" + ; 6) REWRITE OF ZIP TO USE ALL MEMORY 1-NOV-84 - PHG "H" + ; 7) Combination of IBM and MSZIP with new copy protection + ; for all IBM compatible machines. 11-Mar-85 - PHG + ; Minor versions: I -- original to test + ; J -- fixed status line and more + ; k -- enhanced printer timeout for IBM + ; l -- mcrlf added to save, commenting + ; m -- fixed status line for TI-PRO + ; n -- added insert game disk on save + ; and paging problems. Also reworked + ; scripting. + ; o -- fixed script on restart, no script on + ; more, and minor save problems + ; q -- fixed disk switch for verify + ; + ; r -- fixed status line bugs and refixed + ; disk switch on restart. + ; s -- restart bug on Tandy (their incompati- + ; bility and more on restart + ; t -- removed extra CR from opening screen bet + ; ween last line of text and prompt. + ; u -- Fixed mchri not to echo character on + ; more or insert game disks. + ; v -- fixed broken restore or failed save on + ; low memory configuration, error in fit + ; calculation, /k was fixed to work any + ; where on the cmdline. + ; w -- added /P for PCjr support, fixed still + ; broken end of memory calculation caused + ; by forgetting to count prelod blocks as + ; used memory blocks. Also fixed opread + ; so that it would flush words read greater + ; than 59. + ; x -- fix script checks from cmp to test. + ; to fix wishbringer. RELEASE AS H + ; J z -- stab at verify/paging bug, found in + ; newzpc when setting curtab to zero since + ; page is preloaded, didn't set zpcseg to + ; 0 as well. RELEASE AS J + ; J 1 -- fixed script bug on failed restore + ; K 1 -- fixed save/restore bug. Removed srblks + ; 2 -- fixed fix above which was still broken. + ; 3 -- j1 was broken by k2 edit. fixed here + ; 4 -- above + ; 5 -- fixed restart to set segs to 0 + ; 6 -- stab at fixing screwy dos disk flush on + ; create. + ; 7 -- fix screen op to not clear window first + ; 8 -- set min memory to 32k + ; L RELEASE VERSION -- minmem set to 24K + ; + ; M 1 -- fix read in of last virtual block for full game + ; 2 -- fixed a cross segment boundary get in nxtbyt + ; N 1 -- fixed zip to not NEED setup.inf + ; 2 -- added boss key function to MCHRI + SUBTTL STACK AND DATA SEGMENTS INITIALIZATION + +ZVERSN EQU "N" ;ZIP VERSION NUMBER +ZEDIT EQU 0 ; EDIT NUMBER +ZMVERS EQU 3 ;Z-MACHINE VERSION NUMBER +LSTACK EQU 512 ;LENGTH OF USER STACK(MUST BE 1 PAGE FOR NOW) +DEBUG EQU 0 + +PVERS1 EQU 0 ;POSITION OF ZVERSION VERSION BYTE +PVERS2 EQU 1 ;ZVERSION MODE BYTE +PZRKID EQU 2 ;ZORKID +PENDLD EQU 4 ;ENDLOD +PSTART EQU 6 ;START +PVOCTB EQU 8 ;VOCAB +POBJTB EQU 10 ;OBJECT +PGLOTB EQU 12 ;GLOBALS +PPURBT EQU 14 ;PURBOT +PFLAGS EQU 16 ;USER FLAG WORD +PSERNM EQU 18 ;SERIAL NUMBER (6 BYTES) +PWRDTB EQU 24 ;WORDS +PLENTH EQU 26 ;GAME LENGTH +PCHKSM EQU 28 ;GAME CHECKSUM + +PADCHR EQU 5 ;PADDING CHARACTER + +SSVER EQU "A"-10 ; ADD THIS TO THE VERTICAL SETUP HEIGHT +SSHOR EQU -6 ; ADD THIS TO THE HORIZONTAL SETUP WIDTH +SSLNT EQU 3 ; LENGTH OF SETUP FILE + + +CRESET EQU 0H ;MS-DOS FUNCTION CALLS WITH INT 21H +CCONIN EQU 1H +CPROUT EQU 5H +CCONIO EQU 6H +CNOECHO EQU 7H ; (7) FIX MCHRI TO HAVE NO ECHO +CRDLIN EQU 0AH +CDRESET EQU 0DH ; (7o) DISK RESET +CSELDSK EQU 0EH ; (7n) SELECT DISK +CFOPEN EQU 0FH +CFCLOS EQU 10H +CFDELE EQU 13H +CFMAKE EQU 16H +CURDSK EQU 19H ; (7n) CURRENT DISK +CSDMAO EQU 1AH +CRDRND EQU 21H +CWRRND EQU 22H +CPRSNM EQU 29H +; FUNCTION CALLS ADDED FOR VERSION "H" +; UPGRADE TO DOS 2.0 AND ABOVE +CFCREAZ EQU 3CH +CFOPENZ EQU 3DH +CFCLOSZ EQU 3EH +CRDRNDZ EQU 3FH +CWRRNDZ EQU 40H +CFDELEZ EQU 41H +CFSEEK EQU 42H +CSETBLK EQU 4AH ; FOR DETERMINING MEM SIZE +SCROLLUP EQU 6 ; (7) FOR VIDEO BIOS CALL +DOSVER EQU 30H ; (7) REQUEST FOR DOS VERSION +BIOSEG EQU 0F800H ; (7) STRINGS ARE FOUND AT F000:E0++ +BIOSOFF EQU 0000H ; (7) +COLCUR EQU 0607H ; (7) CURSOR SCAN LINES FOR COLOR +SETCUR EQU 1 ; (7) VIDEO FUNCTION TO SET CURSOR SIZE +COLATR EQU 17H ; (7) COLOR ATTRIBUTE IS WHITE ON BLUE +SCRBIT EQU 100000B ; (7) 5 BIT TURNS ON SCREEN SPLITTING +TOPSCR EQU 0100H ; (7) COORD'S OF TOP OF WINDOW +STDPRT EQU 4 ; (7) STANDARD PRINTER DEVICE +PRTMSK EQU 0A1H ; (7) PRINTER INI STATUS MASK +SCRMSK EQU 0FEFFH ; (7) WORD TO MASK SCRIPT BIT IN MODE WORD +RDYBIT EQU 1 ; (7) WAS THE PRINTER READY +MINMEM EQU (24*1024)/16 ; (7) MINIMUM MEMORY IN PARAGRAPHS +MAXLIN EQU 78 ; (7r) MAXIMUM INPUT LINE LENGTH + +; ALL SEGS ORIGINALLY POINT TO CSEG. THE ORG 100H IS STANDARD FOR +; PRODUCING A .COM FILE. THE ES SEGMENT IS ADJUSTED DYNAMICALLY IN THE +; SYSINI ROUTINE TO ALLOW GAME SEGMENTS TO START AT OFFSET ZERO. +; SEE COMMENTS IN SYSINI FOR GAME SEGMENT ALLOCATION AND CALCULATION. + +CSEG SEGMENT PARA PUBLIC + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG + ORG 100H +; + PUBLIC MSZIP +MSZIP PROC + JMP START ; SKIP OVER ZIP DATA +; +; ALL DATA SAVE THE PAGE TABLE (PAGTAB) ARE DEFINED BETWEEN THE ABOVE JMP +; AND THE STARTING DESTINATION. +; + ;VARIBLE DEFINITIONS: + + PUBLIC START,GAMFILE,SAVFILE,GAMHNDL,SAVHNDL,HANDLE,SEEKF + PUBLIC LASTDRV,LSTDFLG,DRVFLG,LASTSAV,SSBUF,DEFDRV,CURDRV + ;GTBLKS +;************************************************************************ +; DO NOT MOVE THESE VARIABLES. DEFINE NOTHING ABOVE THEM. CREATE +; IS DEPENDENT UPON THIS FIXED VARIABLE SETUP FOR GAMFILE AND +; SAVFILE. +;************************************************************************ +; +GAMFILE DB "WITNESS.DAT",0 ; PATCHED BY CREATE + DB 53 DUP (0) ; POTENTIAL LENGTH OF FILENAME +SAVFILE DB "WITNESS.SAV",0 + DB 53 DUP (0) ; POTENTIAL LENGTH OF FILENAME +LASTSAV DB 64 DUP (0) +; +GAMESIZ DW ? ; GAME SIZE IN 512 BYTE BLOCKS +GAMHNDL DW ? ; FOR STORAGE OF FILE HANDLES +SAVHNDL DW ? +SSFILE DB "SETUP.INF",0 +SSBUF DW SSLNT/2 DUP (0) +SKPDRV DB 0 ; (7n) DON'T OUTPUT DRIVE NAME +DEFDRV DB ? ; BYTE FOR DEFAULT DRIVE +CURDRV DB ? ; BYTE FOR NEW DRIVE (SAVES) +DRVFLG DB 0 ; FLAG WHETHER DRIVE SPECIFIED ON SAVE +LASTDRV DB ? ; TEMPORARY STORAGE FOR SAVE AND +LSTDFLG DB ? ; RESTORE FAILURE +HANDLE DW ? ; GENERAL HANDLE FOR GTBLKS ROUTINE +SEEKF DB 1 ; FLAG FOR WHETHER OR NOT TO SEEK +PRTBUF DB ? ; (7) BUFFER FOR PRINTER OUTPUT + + PUBLIC DSKDIR +DSKDIR DB 0 ;0 FOR READ, 1 FOR WRITE + + ; SCREEN DEFINITIONS AND ANSI STRINGS + PUBLIC SCRATR,COLFLG,SCP,RCP,SCPL,SLPP,STINIT,STRESET,SBLINE + PUBLIC SELINE,SPINIT,STINIT,CTRESET,CBLINE,CELINE,CLS,CLSC +SCRATR DB 7 ;(7) BLACK BACKGROUND FOR DEFAULT +COLFLG DB 0 ;(7) ARE WE USING COLOR +SCPL DB 80 ; WIDTH OF THE SCREEN IN COLUMNS (DEFAULTS) +SLPP DB 25 ; LENGTH OF THE SCREEN IN ROWS +SCP DB 3 ; (7) ANSI SAVE CURSOR POSITION + DB 27,'[s' +RCP DB 3 ; (7) ANSI RESTORE CURSOR POSITION + DB 27,'[u' +STINIT DB 16 + DB 27,"[2J",27,"[0m",27,"[01;01H" +STRESET DB 4 + DB 27,"[0m" +SBLINE DB 15 + DB 27,"[37;7m",27,"[01;01H" +SELINE DB 12 + DB 27,"[0m",27,"[" +SELINE1 DB "25;01H" +SPINIT DB 0 +CTINIT DB 20 + DB 27,"[37;44m",27,"[2J",27,"[01;01H" +CTRESET DB 0 +CBLINE DB 16 + DB 27,"[31;47m",27,"[01;01H" +CELINE DB 16 + DB 27,"[37;44m",27,"[" +CELINE1 DB "25;01H" +CPINIT DB 0 +CLS DB 12 + DB 27,"[2J",27,"[" +CLS1 DB "25;01H" +CLSC DB 20 + DB 27,"[37;44m",27,"[2J",27,"[" +CLS1C DB "25;01H" +; + PUBLIC WINDOW1,COLWIN1,WINDOW0,COLWIN0,RADIX +WINDOW1 DB 8 + DB 27,'[02;01H' +COLWIN1 DB 16 + DB 27,'[02;01H',27,'[34;42m' +WINDOW0 DB 4 + DB 27,'[0m' +COLWIN0 DB 8 + DB 27,'[37;44m' +RADIX DB 10 ; THE DEFAULT RADIX FOR THE SCREEN + ;SCRIPTING STUFF + PUBLIC GAMEIN,SCRHLD,SCRFLG,PRNNRDY +GAMEIN DB 0 +SCRHLD DB 0 ; (7n) IS SCRIPTING TEMPORARILY OFF +SCRFLG DB 0 +PRNNRDY DB " %Printer not ready: Abort or Retry? ",80H + + ;USL STUFF +SLFLG DB 1 ;STATUS LINE ASSUMED PRESENT +PMFLAG DB 0 ;AM/PM + + PUBLIC SLSTR,SLTAB,SLSTAB,SLTTAB +SLSTR DW 0 ;TOP OF SCREEN STRING +SLTAB DW 0 ;TABLE USED BY OPUSL + + +; STATUS LINE DESCRIPTOR TABLE. CHOSEN BASED ON SETUP.INF AND MODE +; WORD. CHOICE OF STATUS LINE RESULTS WITH STATUS LINE STRING POINTER +; IN SLSTR AND TABLE DESCRIBING STATUS LINE IN SLTAB. +; +SLSTAB DW SLS40 + DW SLS40T + DW SLS80 + DW SLS80T +SLTTAB DW SLT40 + DW SLT40T + DW SLT80 + DW SLT80T + +; THE FOLLOWING DATA STRUCTURES ARE TABLES AND STRINGS THAT ARE +; DEFINED TO CREATE AND MAINTAIN A WIDE VARIETY OF STATUS LINES. +; THE STRUCTURE OF THE DATA IS FIRST A STRING WHERE THE ROOM DESCRIPTION +; AND THE SCORE/MOVES OR TIME WILL BE WRITTEN. (A POINTER INTO THIS +; STRING IS CREATED IN TSETUP BASED ON TERMINAL WIDTH) +; +; THE STRING IS FOLLOWED BY A TABLE 12 WORDS IN LENGTH. THOSE WORDS +; CAN BE BROKEN UP INTO 3 GROUPS OF 4 WORDS. THERE IS ONE GROUP FOR +; EACH OF ROOM DESCRIPTION, SCORE AND MOVES (OR HOURS AND MINUTES). +; THE FIRST WORD INDICATES WHEN THE ENTRY WAS LAST UPDATED, THE SECOND +; IS A POINTER TO THE ROUTINE THAT OUTPUTS THE QUANTITY, AND THE THIRD +; AND FOURTH ARE THE BOUNDARIES OF THE FIELD IN WHICH THE QUANTITY IS +; WRITTEN. +; +; OPUSL AND TSETUP ARE THE ONLY ROUTINES THAT "KNOW" ABOUT THESE DATA +; STRUCTURES + +;40 COLUMN, SCORE + PUBLIC SLS40,SLS40T +SLS40 DB 40 DUP(32),"S:",5 DUP(32),"M:",6 DUP(32),0,80H +SLS40T DW -1 ; LAST UPDATE + DW OPPRND ; ADDR OF PRINT ROOM DESC + DW 1 ; STARTING COLUMN + DW 25 ; ENDING COLUMN + DW -1 + DW OPPRNN + DW 28 + DW 30 + DW -1 + DW OPPRNN + DW 35 + DW 40 + +;40 COLUMN, TIME + PUBLIC SLT40,SLT40T +SLT40 DB 40 DUP(32),"Time:",10 DUP(32),0,80H +SLT40T DW -1 + DW OPPRND + DW 1 + DW 24 + DW -1 + DW OPPRNH + DW 31 + DW 33 + DW -1 + DW OPPRNM + DW 34 + DW 40 + +;80 COLUMN, SCORE + PUBLIC SLS80,SLS80T +SLS80 DB 110 DUP(32),"Score:", 10 DUP(32),"Moves:",7 DUP(32),0,80H +SLS80T DW -1 + DW OPPRND + DW 1 + DW 27 + DW -1 + DW OPPRNN + DW 57 ; (7) ADJUST SCORE AND MOVES UNITS + DW 61 ; (7) BACK ONE FOR DA + DW -1 + DW OPPRNN + DW 73 ; (7) + DW 80 ; (7) + +;80 COLUMN, TIME + PUBLIC SLT80,SLT80T +SLT80 DB 120 DUP(32),"Time:", 13 DUP(32),0,80H +SLT80T DW -1 + DW OPPRND + DW 1 ; (7) CHANGED FROM 3 FOR CONSISTENCY + DW 29 ; (7) UNDER DIRECTION BY DA + DW -1 + DW OPPRNH + DW 66 ; (7) ADJUST BACKWARDS BY 3 FOR DA + DW 68 ; (7) + DW -1 + DW OPPRNM + DW 69 ; (7) + DW 80 ; (7) + + PUBLIC RSEED1,RSEED2 + ;OPRAND +RSEED1 DW ? ;SEED1 FOR RANDOM NUMBERS +RSEED2 DW ? ;SEED2 FOR RANDOM NUMBERS +RTEMP DW ? ;TEMP FOR RANDOM ROUTINE + + PUBLIC RDWSTR,RDBOS,RDEOS,RDRET,RDNWDS,WRDOFF + ;READ +RDWSTR DW 4 DUP(0) ;WORD STRING BUFFER FOR ZWORD +RDBOS DW 0 ;BEGINNING OF STRING POINTER +RDEOS DW 0 ;END OF STRING POINTER +RDRET DW 0 ;RETURN TABLE POINTER +RDNWDS DB 0 ;NUMBER OF WORDS READ + ;PUTSTR +WRDOFF DW 0 ;OFFSET INTO WORD TABLE FOR CURRENT SET + + PUBLIC CHRPTR,ENDBUF + ;PUTCHR +CHRPTR DW 0 ;POINTS TO NEXT CHARACTER POSITION +ENDBUF DW 0 ;POINTS JUST PAST END OF OUTPUT BUFFER (0) + ;GETNUM +STATUS DW 0 ;STATUS-LINE-REQUESTED FLAG + + PUBLIC IRBRKS,TIMEMD,ZORKID,ENDLOD,VOCTAB,OBJTAB + PUBLIC GLOTAB,WRDTAB,PURBOT,ESIBKS,VWLEN,VWORDS,VOCBEG + PUBLIC OUTBUF,INBUF,RBRKS,BUFFERS,PAGES,INITTBL,SEGEND + ;ZIPBGN +IRBRKS DB " ",9,13,12,".,?",0 ;INITIAL SET OF READ BREAK CHARS +TIMEMD DW 0 ;TIME(VERSUS SCORE)-MODE-FOR-STATUS-LINE FLAG +ZORKID DW 0 ;UNIQUE GAME & VERSION IDENTIFIER +ENDLOD DW 0 ;ENDLOD BLOCK NUMBER +SEGEND DW 0 ; (6) ENDLOD THAT DOESN'T GET DIDDLED +VOCTAB DW 0 ;SAVE VOCABULARY TABLE POINTER +OBJTAB DW 0 ;OBJECT TABLE POINTER +GLOTAB DW 0 ;GLOBAL TABLE POINTER +WRDTAB DW 0 ;WORD TABLE POINTER +PURBOT DW 0 ;PURE CODE POINTER +ESIBKS DW 0 ;END OF SELF-INSERTING BREAK CHARACTERS +VWLEN DW 0 ;NUMBER OF BYTES IN A VOCABULARY WORD ENTRY +VWORDS DW 0 ;NUMBER OF WORD ENTRIES IN VOCABULARY +VOCBEG DW 0 ;BEGINNING OF ACTUAL VOCABULARY +OUTBUF DB 81 DUP(?) ;OUTPUT BUFFER +INBUF DB MAXLIN+2 DUP(?) ;INPUT BUFFER +RBRKS DB 32 DUP(?) ;STRING OF READ BREAK CHARACTERS +BUFFERS DW 0 ;(6) NUMBER OF 512 BYTE BUFFERS FOR PAGING +PAGES DW 0 ;SWAPPING AREA +CHRFLG DB 0 +INITTBL DB 254,0,0,0 + +; CMDLIN WAS CREATED FOR CHANGING CERTAIN PARAMETERS ON THE COMMAND LINE +; CURRENTLY THERE ARE SWITCHES (C,M,W). BITS ARE SET IN SCANCMD AND +; PROCESSED IN SYSINI OR SSETUP. +; + PUBLIC CMDLIN,MEMORY +CMDLIN DB 0 ; (7n) 16=IBM PARALLEL PRINTER + ; (7) 8=SCROLL SET + ; (7) 4=MEMORY SET + ; (7) 2=COLOR SET + ; (7) 1=MONOCHROME SET +MEMORY DW 0 ; (7) MEMORY SIZE SET ON CMDLIN + + PUBLIC ZLOCS,ZPC1,ZPC2,ARGBLK,ZPCSEG,ZPCFLG + ;RESTRT +ZLOCS DW 0 ;POINTER TO LOCALS +ZPC1 DW 0 ;ZPC BLOCK-POINTER +ZPC2 DW 0 ;ZPC BYTE-POINTER +ZPCSEG DB 0 ;(6) GAME SEGMENT WHERE ZPC IS +ZPCFLG DB 0 ; (7n) ZPC PAGE IS MUNGED? +ARGBLK DW 4 DUP(?) ;ARGUMENT BLOCK FOR EXTENDED OPERATIONS + + PUBLIC CURPAG,CURBLK,CURTAB,CURSEG + ;NEWZPC +CURPAG DW 0 ;CURRENT PAGE (WHERE ZPC IS) POINTER +CURBLK DW 0 ;CURRENT BLOCK, USUALLY SAME AS ZPC1 +CURTAB DW 0 ;CURRENT PAGE TABLE POINTER +1 + + PUBLIC RTIME1,RTIME2,LPAGE,LPLOC,LPTAB,GAMESEG,SEG1,FITS + ;GETPAG +RTIME1 DB 0 ;REFERENCE TIME, 1 1/2 WORDS USED +RTIME2 DW 0 +LPAGE DW 0 ;LAST REFERENCED PAGE NUMBER +LPLOC DW 0 ;AND ITS CORE LOCATION +LPTAB DW 0 ;AND ITS TABLE POINTER +GAMESEG DW ? ;(6) FIRST (OR ZERO) GAME SEGMENT +SEG1 DW ? ;(6) SECOND GAMESEG (GAMESEG+64K) +CURSEG DB 0 ;(6) SEGMENT (0/1) FOR CURRENT PAGE +FITS DB 0 ;(6) FLAG FOR GAME ALL IN MEMORY + + ; SPLIT AND SCREEN VARS + PUBLIC SCRNFLG,SPLCOL,SPLTFLG +SCRNFLG DB 0 ; (7) WINDOW THAT WE ARE WRITING IN +SPLCOL DB 27H ; (7) GREEN BACKGROUD FOR WINDOW 1 +SPLTFLG DB 0 ; (7) IS THE SCREEN SPLIT + + ;OPERATION TABLES: ;ZERO ARGUMENT OPERATIONS + PUBLIC ZEROOP,ONEOP,EXTOP +ZEROOP DW OPRTRU ;176 + DW OPRFAL ;177 + DW OPPRNI ;178 + DW OPPRNR ;179 + DW OPNOOP ;180 + DW OPSAVE ;181 + DW OPREST ;182 + DW OPRSTT ;183 + DW OPRSTA ;184 + DW OPFSTA ;185 + DW OPQUIT ;186 + DW OPCRLF ;187 + DW OPUSL ;188 + DW OPVERI ;189 + DW 0 ;190 + DW 0 ;191 + ;ONE ARGUMENT OPERATIONS +ONEOP DW OPQZER ;128 + DW OPQNEX ;129 + DW OPQFIR ;130 + DW OPLOC ;131 + DW OPPTSI ;132 + DW OPINC ;133 + DW OPDEC ;134 + DW OPPRNB ;135 + DW 0 ;136 + DW OPREMO ;137 + DW OPPRND ;138 + DW OPRETU ;139 + DW OPJUMP ;140 + DW OPPRIN ;141 + DW OPVALU ;142 + DW OPBCOM ;143 + ;TWO ARGUMENT AND EXTENDED ARGUMENT OPERATIONS +EXTOP DW 0 ;0 + DW OPQEQU ;1 + DW OPQLES ;2 + DW OPQGRT ;3 + DW OPQDLE ;4 + DW OPQIGR ;5 + DW OPQIN ;6 + DW OPBTST ;7 + DW OPBOR ;8 + DW OPBAND ;9 + DW OPQFSE ;10 + DW OPFSET ;11 + DW OPFCLE ;12 + DW OPSET ;13 + DW OPMOVE ;14 + DW OPGET ;15 + DW OPGETB ;16 + DW OPGETP ;17 + DW OPGTPT ;18 + DW OPNEXT ;19 + DW OPADD ;20 + DW OPSUB ;21 + DW OPMUL ;22 + DW OPDIV ;23 + DW OPMOD ;24 + DW 0 ;25 + DW 0 ;26 + DW 0 ;27 + DW 0 ;28 + DW 0 ;29 + DW 0 ;30 + DW 0 ;31 + DW OPCALL ;224 + DW OPPUT ;225 + DW OPPUTB ;226 + DW OPPUTP ;227 + DW OPREAD + ;228 + DW OPPRNC ;229 + DW OPPRNN ;230 + DW OPRAND ;231 + DW OPPUSH ;232 + DW OPPOP ;233 + DW OPSPLT ;234 + DW OPSCRN ;235 + DW 0 ;236 + DW 0 ;237 + DW 0 ;238 + DW 0 ;239 + DW 0 ;240 + DW 0 ;241 + DW 0 ;242 + DW 0 ;243 + DW 0 ;244 + DW 0 ;245 + DW 0 ;246 + DW 0 ;247 + DW 0 ;248 + DW 0 ;249 + DW 0 ;250 + DW 0 ;251 + DW 0 ;252 + DW 0 ;253 + DW 0 ;254 + DW 0 ;255 + + ;(7) COPY PROTECTION STUFF + PUBLIC COMPATS,COMP1 +COMPATS DW 2 ; (7) NUMBER OF STRINGS IN THE LIST +COMP1 DB 'COMPAQ Co$' + DB 'COPR. IBM$' ; (7) EACH STRING MUST BE 9 CHARS +; DB 'Tandy Cor$' ; (7v) ADD TANDY + + ;MCRLF + PUBLIC SCROLL,TOPLIN,MORLIN + ; (7) SCROLL IS SEEMINGLY BACKWARDS BUT TOO INTERWOVEN TO + ; GO AROUND AND FIX NOW. + ; 0 = IBM Compatible 100% (use windowed scrolling) + ; 1 = MS-DOS, no windowed scrolling + ; +SCROLL DB 1 +TOPLIN DW TOPSCR ; (7) WORD FOR CH,CL FOR UPPER RIGHT +MORE DB "**MORE** ",80H +EMORE DB 13," ",13,80H +MORLIN DW 0 ; (7) COUNT OF LINES SCROLLED WITHOUT PAUSE + + ;STRUCTURE AND RECORD DEFINITIONS: + ;OBJECT OPERATIONS +OBJECT STRUC +FLAGS1 DW ? +FLAGS2 DW ? +PARENT DB ? +SIBLING DB ? +CHILD1 DB ? +PROPS DW ? +OBJECT ENDS +PROPID RECORD PROPSIZE:3,PROPNUM:5 + + ;STRING DEFINITIONS + + ;STATION IDENTIFICATION + PUBLIC IDSTR +IDSTR DB "IBM/MS-DOS 2.0 Interpreter Version ",ZVERSN,ZEDIT,0 + + ;TERMINAL SETUP +SSMSG1 DB "Cannot open Setup File.",0 +SSMSG2 DB "Cannot read Setup File.",0 +SSMSG3 DB "Cannot close Setup File.",0 + + PUBLIC SAV0,SAV1,SAV2,SAV3,ERR1,ERR2,ERR3,ERR4,ERR5,ERR6 + ;SAVE/RESTORE +SAV0 DB "Insert save disk then enter file name.",0 +SAV1 DB "(Default is ",80H +SAV2 DB "): ",80H +SAV3 DB "Insert game disk then strike any key to continue.",0 + +ERR1 DB "SAVE file not found",0 +ERR3 DB "Bad file name syntax",0 +ERR4 DB "Unable to access file",0 +ERR5 DB "No room on diskette for SAVE file",0 +ERR6 DB "Read of SAVE file failed",0 + ;READ +ERR2 DB "Too many words typed, flushing: ",80H + + PUBLIC FTL2,FTL4,FTL5,FTL6,FTL7,FTL9 + ;OPNEXT/OPPUTP +FTL2 DB "No such property",0 + ;ZIPBGN +FTL4 DB "Wrong game or version",0 + ;NXTINS +FTL5 DB "Illegal operation",0 + ;FINDPG +FTL6 DB "No free pages",0 + ;GTBLKS +FTL7 DB "Game file read error",0 + ;SYSINI +FTL9 DB "Game file not found",0 +FTL10 DB 'Unauthorized copy',0 +FTL11 DB 'Wrong DOS version. Must be 2.0 or higher',0 +FTL12 DB 'Insufficient memory to play game',0 + + ;Fatal error header +FATHDR DB "Fatal error: ",80H + ;ZSTR CHARACTER CONVERSION VECTOR + + PUBLIC ZCHRS +ZCHRS DB "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + DB " 0123456789.,!?_#'" + DB '"/\-:()' + + PUBLIC STK_TOP,STKBOT,ZSTK_TP +; STACK SETUP + DW 200H DUP(?) +STK_TOP LABEL WORD +STKBOT DW LSTACK DUP(?) +ZSTK_TP LABEL WORD +; + SUBTTL MACROS + PAGE + +GTAWRD MACRO D,S ;;GET ABSOLUTE WORD + MOV D&X,ES:&S + XCHG D&H,D&L + ENDM + +PTAWRD MACRO D,S ;;PUT ABSOLUTE WORK + XCHG S&H,S&L + MOV ES:&D,S&X + ENDM + +MOVM MACRO D,S,R ;;MOVE MEMORY TO MEMORY + MOV R,S + MOV D,R + ENDM + +PUSHZ MACRO S ;;PUSH ONTO Z STACK + XCHG SP,DI + PUSH S + XCHG SP,DI + ENDM + +POPZ MACRO D ;;POP FROM Z STACK + XCHG SP,DI + POP D + XCHG SP,DI + ENDM + +POPZT MACRO D ;;GET TOP OF Z STACK + MOV D,SS:[DI] + ENDM + +PUSHZT MACRO S ;;PUT TOP OF Z STACK + MOV SS:[DI],S + ENDM + +PRINT MACRO STR ;;PRINT A STRING, POINTER IS ARGUMENT + PUSH AX + MOV AX,OFFSET STR + CALL MPRNT + POP AX + ENDM + +FATAL MACRO ERR ;;PRINT FATAL ERROR AND DIE + CALL MCRLF + MOV AX,OFFSET FATHDR + CALL MPRNT + MOV AX,OFFSET ERR + CALL MPRNT + JMP FINISH + ENDM + + SUBTTL SYSTEM INITIALIZATION + PAGE + + + PUBLIC START +START: MOV SP,OFFSET STK_TOP + MOV DI,OFFSET ZSTK_TP + JMP ZIPBGN ;JUMP TO BEGINNING OF ZIP CODE +; + PUBLIC OPSPLT,OPSCRN +OPSCRN PROC + MOV SCRNFLG,AL ; (7) TOGGLE SCREEN CURRENTLY ON + TEST AL,AL ; (7) WHICH DO WE WANT + JZ SCRN0 ; (7) SELECT BOTTOM, SCROLLING WINDOW + CALL SAVECUR +SCRN1: MOV BX,OFFSET WINDOW1 ; (7) HOME THE CURSOR + TEST COLFLG,1 ; (7) SHOULD WE SET THE COLOR + JZ SCRN2 ; (7) NOPE + MOV BX,OFFSET COLWIN1 ; (7) CLEAR SCREEN WITH COLOR +SCRN2: CALL MSPRT ; (7) WITH ANSI LOCATE + RET +SCRN0: CALL RESTCUR ; (7) RESTORE THE CURSOR POSITION + MOV BX,OFFSET WINDOW0 + TEST COLFLG,1 ; (7) SHOULD WE CHANGE THE COLOR + JZ SCRN3 ; (7) NOPE... + MOV BX,OFFSET COLWIN0 +SCRN3: CALL MSPRT ; (7) RESTORE COLOR + RET +OPSCRN ENDP + +OPSPLT PROC + XOR AH,AH + CMP AL,0 + JNZ SPL1 ; (7) YES, FIGURE WINDOW SIZE + MOV SPLTFLG,0 ; (7) TURN OFF SPLIT SCREEN + MOV TOPLIN,TOPSCR ; (7) RESTORE TOPLIN TO WHOLE SCR + MOV MORLIN,0 ; (7) RESET THE MORE LINE COUNT + CALL RESTCUR + RET +SPL1: MOV SPLTFLG,1 ; (7) TURN ON SPLIT SCREEN + CMP AL,SLPP ; (7) ARE THERE THIS MANY LINES + JLE SPL2 + MOV AL,SLPP ; (7) USE NO MORE THAN THE SCREEN + DEC AL ; (7) LEAVE A SCROLL LINE +SPL2: XCHG AH,AL ; (7) GET #LINES IN TOP HALF + ADD TOPLIN,AX ; (7) THIS FIXES WINDOW 0 SCROLL SIZE + PUSH AX ; (K7) FIX CLEAR ON SPLIT SCREEN + CALL SAVECUR ; (7) SAVE THE CURSOR POSITION + MOV BH,SCRATR ; (7) GET ATTRIBUTE INTO BH FOR CLS + TEST COLFLG,1 ; (7) COLOR BLANK OR VANILLA BLANK + JZ SPL3 ; (7) VANILLA... + MOV BH,SPLCOL ; (7) USE THE GREEN CLEAR +SPL3: POP AX ; (K7) RESTORE AX + MOV DH,AH ; (7) BLANK WINDOW #1 +; DEC DH ; (7) LESS ONE LINE (REMOVED (K7)) + MOV AH,SCROLLUP ; (7) BLANK THE SCREEN + MOV AL,0 ; (7) ZERO MEANS ENTIRE WINDOW + MOV CX,TOPSCR ; (7) FROM UPPER LEFT + MOV DL,SCPL ; (7) TO LOWER RIGHT + DEC DL ; (7v) COORDINATES ARE ZERO BASED + INT 10H ; (7) CALL VIDEO BIOS ROUTINE TO CLS + CALL RESTCUR ; (7) RESTORE CURSOR POSITION + RET +OPSPLT ENDP + + PUBLIC SAVECUR +SAVECUR PROC + MOV BX,OFFSET SCP ; (7) ANSI SAVE CURSOR + CALL MSPRT + RET +SAVECUR ENDP + + PUBLIC RESTCUR +RESTCUR PROC + MOV BX,OFFSET RCP ; (7) ANSI RESTORE CURSOR + CALL MSPRT + RET +RESTCUR ENDP + + PUBLIC FEEP +FEEP PROC + MOV AX,7 + CALL MTTYO ;BELL + RET +FEEP ENDP +; +; VERIFY +; +; OP VERIFY HAS BEEN GIVEN A SPLIT PERSONALITY. THE CASE THAT THE ENTIRE +; GAME FITS INTO MEMORY CALLS ON OPVR2$ WHICH READS THE GAME IN TWO 64K +; READS. THE SECOND ES SEGMENT IS USED SO THAT THE SECOND READ WILL RESTORE +; THE GAME TO ITS ORIGINAL STATE. 64K IS READ IN AND CHECKSUMED AND THEN +; THE REMAINDER OF THE GAME IS READ BACK IN AND CHECKSUMED. +; +; THE ORIGINAL VERIFY FORCES THE PRELOAD TO BE LOADED AGAIN BY SETTING THE +; ENDLOD POINTER TO ZERO. THIS TRICKS GETBYT INTO THINKING THAT NO PAGES +; ARE LOCKED ALREADY IN CORE AND FORCES A CALL TO THE PAGING ROUTINES. +; +; + PUBLIC OPVERI +OPVERI PROC + CALL GAMOPEN ; (7q) PUT THE DISK BACK IN + PRINT IDSTR + CMP FITS,1 ; (6) WHOLE GAME IN??? + JNZ OPVR1$ + JMP OPVR2$ +OPVR1$: MOV AX,ES:[PLENTH] ; (7q) GET END BYTE ADDR + XCHG AH,AL ; (7q) FLOP BYTES + MOV ZPCFLG,1 ; (7n) SET MUNGED ZPC FLAG + PUSH SI + PUSH DI + PUSH ENDLOD + CALL BSPLIT + MOV SI,AX + MOV DI,BX + + CALL TBLINI ; (7n) REINITIALIZE THE PAGE TABLE + MOV BX,CURTAB + DEC BX + MOV AX,CURBLK + MOV [BX],AX + MOV AX,0FFFFH + INC BX + MOV [BX],AX + MOV BYTE PTR 2[BX],AL + + MOV AX,0 + MOV BX,64 + MOV DX,0 + MOV ENDLOD,0 +OPVR1: PUSH SI + PUSH DI + PUSH DX + CALL GETBYT ; GET A BYTE FROM SEG1 + POP DX + POP DI + POP SI + ADD DX,CX ; SUM IT + CMP AX,SI + JNE OPVR1 + CMP BX,DI + JNE OPVR1 + MOV AX,ES:[PCHKSM] ; REMOVED SEG OVERRIDE + XCHG AH,AL + POP ENDLOD + POP DI + POP SI +; CALL TBLINI ; (7n) RESET THE TABLE YET AGAIN +OPVR4: CMP AX,DX + JE OPVR2 + JMP PFALSE +OPVR2: JMP PTRUE +; +; VERIFY FOR FITS==1 OR ALL OF GAME IS IN MEMORY +; +OPVR2$: PUSH SI + PUSH DI + PUSH CX + PUSH DS ; (6) ADDRESS SEGMENT 1 + MOV BX,GAMHNDL ; (6) READ FROM GAME FILE + MOV SI,GAMESEG ; (6) THROUGH DS + MOV DS,SI ; (6) SO THAT WE OVERLAY GAME + MOV CX,0 ; (6) MOVE FILE PTR TO BEGINNING + MOV DX,64 ; (6) SKIP FIRST 64 BYTES + MOV AL,0 ; (6) METHOD OF SEEKING + MOV AH,CFSEEK ; (6) SEEK FUNCTION + INT 21H ; (6) DO IT + MOV CX,03FC0H ; (7n) READ 16K AT A TIME + MOV DX,0C000H ; (6) OFFSET INTO SEGMENT + MOV AH,CRDRNDZ ; (6) READ FUNCTION + INT 21H ; (6) DO IT + CMP AX,CX ; (6) DID WE GET IT ALL + JNE OPVR5 ; (6) DIE PAINFULLY + XOR DX,DX ; (7n) ZERO THE CHECKSUM + CALL CHKSUM ; (6) DO A CHKSUM +; +OPVR6: MOV DI,DX ; (7n) SAVE CHECK SUM + MOV DX,0C000H ; (7n) BUFFER SPACE + MOV CX,4000H ; (7n) READ 16K EACH TIME + MOV AH,CRDRNDZ ; (7n) DO A RANDOM READ + INT 21H ; (7n) DO IT + CMP AX,CX ; (7n) LAST READ? + JNE OPVR8 + MOV DX,DI ; (7n) RESTORE CHECKSUM + CALL CHKSUM + JMP OPVR6 +OPVR8: MOV AX,ES:[PLENTH] ; (7n) GET FILE LENGTH IN WORDS + XCHG AH,AL ; (7n) INTO AX + MOV DX,0 ; (7n) ZERO THIS FOR DIVIDE + MOV CX,2000H ; (7n) DIVIDE BY NUMBER OF BYTES/2 + DIV CX ; (7n) TO GET REMAINDER + SHL DX,1 ; (7n) MULT BY 2 TO GET BYTES + MOV AX,DX ; (7n) DX SHOULD HAVE REM BYTES + MOV DX,DI ; (7n) RESTORE CHECKSUM + CALL CHKSUM +; + PUSH DX + MOV CX,0 ; (7n) SEEK TO 48K INTO FILE + MOV DX,0C000H ; (7n) TO GET OVERWRITTEN PART + MOV AH,CFSEEK ; (7n) FUNCTION IS SEEK + MOV AL,0 ; (7n) TO OFFSET FROM BEGINNING + INT 21H ; (7n) DO IT + MOV DX,0C000H ; (7n) NOW REFILL SEG WITH ORIG + MOV CX,4000H ; (7n) READ 16K IN + MOV AH,CRDRNDZ ; (7n) FUNCTION READ + INT 21H + POP DX + + POP DS ; (6) RESTORES + POP CX + POP DI + POP SI + MOV AX,ES:[PCHKSM] ; (6) GET CHKSUM + XCHG AH,AL + JMP OPVR4 +; +CHKSUM: MOV CX,AX ; (7n) GET NUMBER ACTUALLY READ + XOR AX,AX ; (6) ZERO THIS + MOV SI,0C000H ; (7n) 48K INTO THE BUFFER +OPVR3: LODSB ; (6) GET A BYTE + ADD DX,AX ; (6) ADD IT ALL UP + LOOP OPVR3 + RET +; +OPVR5: FATAL FTL7 ; GAME FILE READ ERROR +OPVERI ENDP + +; +; SAVE AND RESTORE HAVE BEEN MODIFIED TO USE DOS 2.0 FILE NAMES. THIS +; ALLOWS THE USER TO SAVE AND RESTORE TO ANY DISK DRIVE AND ANY SUBDIRECTORY. +; FILE NAMES ARE READ FROM THE CONSOLE AND TRANSFERRED INTO THE SAVFILE +; VARIABLE WITH NO PARSING OTHER THAN A CHECK FOR A DISK DRIVE SPECIFIER. +; IF THE NAME IS TYPED INCORRECTLY, THEN DOS RETURNS AN ERROR WHICH WE +; REPORT ACCORDINGLY. + +; +; RESTORE +; + PUBLIC OPREST +OPREST PROC + MOV DSKDIR,0 ;INDICATE RESTORE (READ) + JMP OSV0$ +OPREST ENDP + +; +; SAVE +; + PUBLIC OPSAVE +OPSAVE PROC + MOV DSKDIR,1 ;INDICATE SAVE (WRITE) + +; +;COMMON ENTRYPOINT FOR SAVE AND RESTORE +; + PUBLIC OSV0$,OSVD1,OSVD2,OSVD3,OSVD4A,OSVPSX,OSVOPW + PUBLIC OSVOPDF,OSVPS,OSVT0,OSV4X,OSV4Y +; PUBLIC OSVCC,OSV1C,OSV2C + PUBLIC OSV4,OSVPRR +; DO A DISK RESET IN CASE THEY WANT TO CHANGE DISKS +; UNFORTUNATELY WE HAVE TO ASSUME A 1 DRIVE SYSTEM AT THIS POINT + +OSV0$: CMP FITS,1 ; (n) ARE WE ALL THERE + JZ OSV0A ; (n) YES, NO CLOSE + MOV AH,CFCLOSZ ; (7s) CLOSE THE GAME FILE + MOV BX,GAMHNDL ; (7s) FOR REINSERTION + INT 21H + MOV AH,CDRESET ; (K6) WILL RESET FLUSH BUFFERS? + INT 21H ; (K6) HOPE SO... + +; PRINT "FILENAME (DEFAULT IS drv:filename.ext):" + +; PRINT "FILENAME (DEFAULT IS drv:" +OSV0A: PRINT SAV0 ;PRINT "INSERT SAVE DISK THEN ENTER FILE NAME." + PRINT SAV1 ;PRINT "FILE NAME (DEFAULT IS " + TEST DRVFLG,1 ; HAS USER SPECIFIED A DRIVE + JNZ OSVD1 ; YES, USE USER DEFAULT DRIVE + MOV AL,CURDRV ;AL <= DRIVE NO. + ADD AL,65 ;....NO. ADD 65 TO GET ASCII CHARACTER + CALL MTTYO ;PRINT DRIVE B, C, OR D + MOV AL,":" ;PRINT ":" + CALL MTTYO + +; PRINT "filename" +OSVD1: PUSH SI ; (6) SAVE THIS + MOV SI,OFFSET SAVFILE ; (6) POINTER TO SAVE FILENAME (6) + MOV CX,SI ; (6) SAVE POINTER + CLD ; (6) SET DIR INCREMENT +OSVD2: LODSB ; (6) GET A BYTE INTO AL + TEST AL,AL ; (6) CHECK IF NULL + JZ OSVD3 ; (6) EXIT THIS LOOP + CALL MTTYO ; (6) OUTPUT IT + JMP OSVD2 +OSVD3: SUB SI,CX ; (6) CALCULATE NUMBER OF CHARS + MOV CX,SI ; (6) GET NUMBER BACK INTO CX + POP SI ; (6) RESTORE THIS + +; PRINT " ): " + PRINT SAV2 ;PRINT " ): " + CMP SCPL,50 ;ARE MAX CHARS/LINE >50? + JG OSVD4A ;....YES + CALL MCRLF ;....NO. PRINT A + +; GET LOSER'S SAVE FILENAME FROM THE KEYBOARD +OSVD4A: MOV BX,OFFSET INBUF ;^ KEYBOARD INPUT BUFFER + MOV AL,63 ;(6) COULD BE A WHOLE PATH + MOV BYTE PTR [BX],AL ;SET UP BUFFER TO TAKE 15 CHARACTERS + MOV DX,BX ;DX ^ BUFFER + MOV AH,CRDLIN ;READ A LINE FROM THE KEYBOARD + INT 21H + +; PARSE THE FILENAME + + CALL SAVESAV ; (7o) PRESERVE THE SAVE NAME + PUSH SI + PUSH DI + PUSH CX ; SAVE THIS + PUSH ES + PUSH DS + POP ES + LEA SI,INBUF[1] ; POINT TO NUM CHARS READ + LODSB ; GET NUM + TEST AL,AL ; ANY CHARS READ + JZ LOOK + MOV CL,AL ; STORE IT + XOR CH,CH ; CLEAR TOP HALF OF COUNTER + MOV DI,OFFSET SAVFILE ; (6) DI ^FCB + REPZ MOVSB ; TRANSFER THE STRING IF ANY + MOV AL,0 ; (6) GET A NULL + STOSB ; (6) DROP IT IN AT END OF STRING +LOOK: TEST SCRFLG,1 ; (7p) IS SCRIPTING ON? + JZ NOSCR ; (7p) NO SCRIPTING + CALL SCRSAVE ; (7p) SCRIPT THE SAVE FILE NAME +NOSCR: MOV SI,OFFSET SAVFILE ; (6) IS THERE A ':' + INC SI + LODSB ; (6) CHECK IT + CMP AL,':' ; (6) IF SO, FIX DEFDRV + JNZ NODRV ; (6) NOPE... + MOV DRVFLG,1 ; (6) SET FLAG + MOV AL,SAVFILE ; (7n) GET DRIVE LETTER + AND AL,5FH ; (7n) UPPERCASIFY + SUB AL,'A' ; (7n) BASIFY + CMP AL,CURDRV ; (7n) DON'T CHANGE IF UNNECESSARY + JZ DRV + MOV DL,AL ; (7n) SET UP FOR CHGDSK + MOV AH,CSELDSK ; (7n) SELECT DISK IN DL + INT 21H + MOV AH,CURDSK ; (7n) CHECK IF IT WORKED + INT 21H + MOV CURDRV,AL ; (7n) SAVE IT + JMP DRV +USEDEF: MOV SKPDRV,1 ; (7n) DON'T OUTPUT A DRIVE +NODRV: MOV DRVFLG,0 +DRV: POP ES + POP CX + POP DI ;RESTORE'M + POP SI + CALL MCRLF ; (7) SCROLL PROPERLY + +; OPEN THE FILE IF OP RESTORE + + CMP DSKDIR,1 ;OP SAVE? + JE OSVOPW ;....YES + MOV DX,OFFSET SAVFILE ; 6) ....NO. OP RESTORE. DX ^ FCB + MOV AH,CFOPENZ ; (6) SELECT DOS OPEN FUNCTION + MOV AL,0 ; (6) FILE OPEN FOR READING + INT 21H ;OPEN THE FILE + JC OSVPSX ; (6) ....NO. FILE NOT FOUND + JMP OSVPS ;....YES +; +; **** ERROR **** [File Not Found] +; +OSVPSX: MOV AX,OFFSET ERR1 ;^ "SAVE FILE NOT FOUND" MSG + JMP OSVPER ;ERROR EXIT + +; CREATE THE FILE IF OP SAVE +OSVOPW: MOV DX,OFFSET SAVFILE ; (6) ^ FCB + MOV CX,0 ; (6) NO SPECIAL ATTRIBUTE + MOV AH,CFCREAZ ; (6) SELECT DOS CREATE FUNCTION + INT 21H + JC OSVOPDF + JMP OSVPS ;....YES +; +; **** ERROR **** [Directory Full] +; +OSVOPDF:MOV AX,OFFSET ERR4 ;....NO. ^ "NO ROOM IN DIRECTORY" MSG + JMP OSVPER ;HOP TO ERROR EXIT +; +; WE'VE GOT AN OPEN FILE (WHICH WE CREATED IF IT WAS A SAVE FUNCTION) +; AND ARE READY TO EITHER READ (RESTORE) OR WRITE (SAVE) AS REQUIRED +; +; THE BELOW CODE GRIMLY EXPLAINS THE FORMAT OF A SAVE FILE. BASICALLY, +; FROM WHAT I CAN TELL, THE LOCALS AND VITALS ARE PUSHED ONTO THE ZSTACK +; AS WELL AS THE ZPC AND THE ZSTACK POINTER. THIS INFORMATION IS FIRST +; WRITTEN TO DISK. THEN THE REST OF PURBOT IS WRITTEN TO DISK. THIS CODE +; ALSO WORKS FOR A RESTORE. SO THE SAVE FILE CONSISTS OF FIRST ZIP INFO +; SAVED ON DISK FOLLOWED BY THE IMPURE PART OF THE GAME CODE. +; +OSVPS: XCHG DI,SP + PUSH ZPC1 ; PUSH VITALS ONTO ZSTACK + PUSH ZPC2 + PUSH ZLOCS + PUSH ZORKID + + + SUB SP,OFFSET STKBOT ; (7v) RELATIVISE THE POINTER + MOV STKBOT,SP ; PUT DEST. INDEX INTO STACKBOTTOM + MOV SP,DI ; RESTORE SP + + MOV SAVHNDL,AX ; SAVE FILE HANDLE + PUSH ES + + MOV AX,SS ; FLOP STACK SEG AND EXTRA SEG + MOV ES,AX ; ES<=SS + + MOV DX,OFFSET STKBOT ; CORE LOCATION + MOV CX,400H ; (6) DO TRANSFER HERE + MOV BX,SAVHNDL ; (6) GET HANDLE + MOV AH,CRDRNDZ ; SETUP FOR A READ + ADD AH,DSKDIR ; MAKE IT A WRITE IF NECESSARY + INT 21H ; + CMP AX,400H ; DID WE GET IT ALL + PUSHF ;SAVE RETURN CODE + MOV DI,SP ;DI ^ CURRENT ZSTACK POSITION + MOV SP,STKBOT ;SP <= ZSTACK POINTER + ADD SP,OFFSET STKBOT ; (7v) RELATIVISE THIS VALUE + POP AX ; POP OFF AND COMPARE FOR ZORKID + CMP AX,ZORKID ;ID OK? + JE OSVT0 ;....YES + MOV GAMEIN,0 ; (7v) INDICATE THAT THE GAME IS LOST + FATAL FTL4 ;....NO. FATAL ERROR + +OSVT0: POP ZLOCS ;RESTORE LOCALS AND ZIP PROGRAM COUNTERS + POP ZPC2 + POP ZPC1 + + XCHG DI,SP ;RESTORE MACHINE SP AND ZSTACK POINTER + POPF ;RESTORE REGS + POP ES + JNE OSV4Y ;TRANSFER WAS UNSUCCESSFUL +; +; THE OPEN/CREATE FILE WAS SUCCESSFUL, AND SO WAS THE BLOCK TRANSFER +; SO TRANSFER THE REST +; +OSV4X: MOV CX,ES:[PPURBT] ; (K3) MAYBE THIS IS WRONG + XCHG CH,CL ; (K3) XCHANGE BYTES + MOV AH,CRDRNDZ ; (K1) FUNCTION IS READ (OR WRITE) + ADD AH,DSKDIR ; (K1) ADD IN WRITE STUFF + MOV BX,SAVHNDL ; (K1) READ IT FROM HERE + MOV DX,0 ; (K1) READ IT RIGHT IN TO SEG0 + PUSH DS ; (K1) SAVE DS + PUSH ES ; (K1) FLOP BYTES + POP DS ; (K1) ES IS NOW DOS ADDRESSIBLE + INT 21H ; (K1) DO THE SAVE/RESTORE + POP DS ; (K1) RESTORE DS + CMP AX,CX ; (K1) DID WE GET IT ALL? +OSV4Y: PUSHF ;SAVE DOS RETURN CODE + MOV AH,CFCLOSZ ; (6) CLOSE THE FILE + MOV BX,SAVHNDL ; (6) WITH THIS HANDLE + INT 21H + POPF ;RESTORE DOS RETURN CODE + JNE OSV4 ;ERROR EXIT +; +;ELSE EVERYTHING WORKED SUCCESSFULLY +;AND WE CAN GO BACK TO WHAT WE WERE +;DOING.......... +; + MOV AH,SCRFLG ; (J2) FIX SCRFLG + XOR AL,AL ; (J2) + MOV WORD PTR ES:[PFLAGS],AX ; (J1) SCRIPT SHOULD MATCH SCRFLG + CMP FITS,1 ;(n) do not need to replace disk if in mem + JZ n1 + CALL GAMOPEN ; (7s) OPEN GAME FILE + MOV DL,CURDRV ; (7n) RETURN TO SAVE DISK + MOV AH,CSELDSK ; (7n) AND SELECT IT FOR OPEN + INT 21H +N1: CALL NEWZPC ;GET A NEW PC + JMP PTRUE +; +; **** ERROR **** [Unable to Read File] +; +OSV4: MOV AX,OFFSET ERR6 ;^ "Read of SAVE file failed." + CMP DSKDIR,1 ;OP SAVE? + JNE OSVPRR ;....NO + MOV AH,CFCLOSZ ; (6) ....YES. CLOSE IT + MOV BX,SAVHNDL ; (6) GET HANDLE FOR CLOSE + INT 21H +; +; **** ERROR **** [Diskette Full] +; + MOV DX,OFFSET SAVFILE ; (7n) DELETE THE PIECE OF A FILE + MOV AH,CFDELEZ ; (7n) SO AS NOT TO CONFUSE + INT 21H + MOV AX,OFFSET ERR5 ;^ "No room on diskette for SAVE file." +OSVPRR: JMP OSVPER +OPSAVE ENDP +; +; ERROR EXIT R/W operations +; +OSVPER PROC + CALL MPRNT ;PRINT ERROR MESSAGE + CALL ZRESTOR ; (7o) RESTORE OLD SAVE NAME + CMP FITS,1 ; (7v) HAVE WE CLOSED THE GAME FILE + JZ OSVPR1 ; (7v) SKIP REOPEN + CALL GAMOPEN ; (7v) OPEN IT +OSVPR1: MOV AL,SCRFLG ;REENABLE SCRIPTING + XCHG AH,AL + XOR AL,AL ; (J1) FIX SCRIPT ON BAD RESTART (RANDOM) + MOV ES:[PFLAGS],AX + JMP PFALSE +OSVPER ENDP +; + PUBLIC SAVESAV,ZRESTOR,SCRSAVE +SCRSAVE PROC + PUSH AX ; (7p) SAVES + PUSH SI + PUSH DX + MOV SI,OFFSET SAVFILE ; (7p) POINTER TO SAVE +SCRS0: LODSB ; (7p) GET A CHARACTER + TEST AL,AL ; (7p) LOOK FOR A NULL + JNZ SCRS1 ; (7p) DIE ON A NULL + POP DX + POP SI + POP AX + RET ; (7p) RETURN +SCRS1: MOV DL,AL ; (7p) GET CHARACTER INTO DL + MOV AH,CPROUT ; (7p) FOR DOS"IE" OUTPUT + INT 21H ; (7p) PRINT IT + JMP SCRS0 +SCRSAVE ENDP + +SAVESAV PROC + PUSH DI ; (7o) SAVES + PUSH SI + PUSH AX + PUSH ES + MOV AX,DS ; (7o) SET UP REGS + MOV ES,AX + MOV AL,CURDRV ; (7o) SAVE CURRENT DRIVE SPEC + MOV LASTDRV,AL ; (7o) IN CASE OF FAILURE + MOV AL,DRVFLG ; (7o) TEST DRIVE FLAG + MOV LSTDFLG,AL ; (7o) IN CASE OF FAILURE + MOV SI,OFFSET SAVFILE ; (7o) SETUP SOURCE AND DESTINATION + MOV DI,OFFSET LASTSAV +COPYLP: LODSB ; (7o) GET A BYTE + STOSB ; (7o) STORE A BYTE + TEST AL,AL ; (7o) STOP ON A NUL + JNZ COPYLP ; (7o) CONTINUE THE COPY + POP ES + POP AX ; (7o) RESTORES + POP SI + POP DI + RET +SAVESAV ENDP +; +; +ZRESTOR PROC + PUSH DI ; (7o) SAVES + PUSH SI + PUSH AX + PUSH ES + MOV AX,DS ; (7o) SET UP REGS + MOV ES,AX + MOV AL,LSTDFLG ; (7o) GET LAST DRIVE FLAG + MOV DRVFLG,AL ; (7o) AND RESTORE IT + MOV AL,LASTDRV ; (7o) GET ORIGINAL DRIVE SPEC + CMP AL,CURDRV ; (7o) HAS IT CHANGED + JZ ZRES1 + MOV DL,AL ; (7o) SELECT DISK + MOV AH,CSELDSK ; (7o) TO CORRECT + INT 21H + MOV CURDRV,DL ; (7o) UPDATE THIS BABY +ZRES1: MOV DI,OFFSET SAVFILE ; (7o) SETUP SOURCE AND DESTINATION + MOV SI,OFFSET LASTSAV +ZRESLP: LODSB ; (7o) GET A BYTE + STOSB ; (7o) STORE A BYTE + TEST AL,AL ; (7o) STOP ON A NUL + JNZ ZRESLP ; (7o) CONTINUE THE COPY + POP ES + POP AX ; (7o) RESTORES + POP SI + POP DI + RET +ZRESTOR ENDP +; +; OP RESTART +; + PUBLIC OPRSTT +OPRSTT PROC + MOV BP,CHRPTR + MOV BYTE PTR DS:[BP],0 ;FORCE OUT THE BUFFER + PRINT OUTBUF + JMP RESTRT ;JUMP TO RESTART ADDRESS +OPRSTT ENDP + + PUBLIC OPQUIT +OPQUIT PROC + JMP FINISH +OPQUIT ENDP + +; THIS OPCODE IS A PSEUDO-OP. IT IS NEVER CALLED BY THE GAME BUT INSTEAD +; BY OPREAD. IT IS HEAVILY TIED TO THE STATUS LINE DATA STRUCTURES. + PUBLIC OPUSL +OPUSL PROC + CMP SLFLG,0 + JNE OPUSL1 + RET +OPUSL1: PUSH DI + PUSH CHRPTR + MOV BX,SLSTR + MOV CHRPTR,BX + MOV AX,16 + MOV DI,SLTAB + MOV CX,3 +USLLP: PUSH AX + CALL GETVAR + MOV DX,[DI+4] + CALL USLSET + PUSH CX + PUSH DI + CALL WORD PTR [DI+2] + POP DI + MOV DX,[DI+6] + CALL USLSPC +USLN: ADD DI,8 + POP CX +USL1: POP AX + INC AX + LOOP USLLP + MOV AX,"$" + CALL PUTCHR + CALL MSOUT + POP CHRPTR + POP DI + RET + +USLSET: MOV BX,SLSTR + MOV CHRPTR,BX + ADD CHRPTR,DX + RET + +USLSPC: MOV CX,CHRPTR + SUB CX,SLSTR + SUB DX,CX + MOV CX,DX + JLE USLSP1 +USLSPL: MOV AX,20H + CALL PUTCHR + LOOP USLSPL +USLSP1: RET +OPUSL ENDP + + SUBTTL ARITHMETIC OPERATIONS + PAGE + + + PUBLIC OPADD,OPSUB,OPMUL,OPDIV,OPMOD + ;ADD +OPADD PROC + ADD AX,BX ;ADD OPR1 AND OPR2 + JMP PUTVAL ;RETURN THE VALUE +OPADD ENDP + + ;SUB +OPSUB PROC + SUB AX,BX ;SUBTRACT OPR2 FROM OPR1 + JMP PUTVAL ;RETURN THE VALUE +OPSUB ENDP + + ;MULTIPLY AX BY BX +OPMUL PROC + IMUL BX ;MULTIPLY OPR1 BY OPR2,IGNORING OVERFLOW(DX) + JMP PUTVAL ;RETURN THE VALUE +OPMUL ENDP + + ;DIVIDE AX BY BX +OPDIV PROC + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + JMP PUTVAL ;RETURN THE VALUE +OPDIV ENDP + + ;MOD +OPMOD PROC + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + MOV AX,DX ;WE WANT REMAINDER + JMP PUTVAL ;RETURN THE VALUE +OPMOD ENDP + + ;RANDOM BY DAN + PUBLIC OPRAND +OPRAND PROC + SUB AH,AH ; HACK RANDOM TO ONE BYTE + MOV RTEMP,AX ; SAVE ARGUMENT FOR LATER + MOV AX,RSEED1 + MOV BX,RSEED2 + MOV RSEED2,AX + CLC + RCR AX,1 + RCR BX,1 + XOR RSEED1,BX ;PUT XOR'D NUBMER INTO RSEED1 + MOV AX,RSEED1 ;THIS IS RANDOM VALUE + + AND AX,0EFFFH ;CHOP HIGH BIT FOR DIVIDE + SUB DX,DX ;CLEAR MOST SIGN. PORTION OF 32 BIT WORD + DIV RTEMP ;DIVIDE WORD BY WORD + MOV AX,DX ;MOVE REMAINDER INTO AX + INC AX ;MAKE SURE NO ZERO + JMP PUTVAL +OPRAND ENDP + + ;LESS? + PUBLIC OPQLES,OPQGRT,OPBTST,OPBOR,OPBCOM,OPBAND +OPQLES PROC + CMP AX,BX ;IS OPR1 LESS THAN OPR2? + JL JPT ;YES, PREDICATE TRUE +JPF: JMP PFALSE ;NO, PREDICATE FALSE +JPT: JMP PTRUE +OPQLES ENDP + + ;GRTR? +OPQGRT PROC + CMP AX,BX ;IS OPR1 GREATER THAN OPR2? + JG JPT ;YES, PREDICATE TRUE + JMP JPF ;NO, PREDICATE FALSE +OPQGRT ENDP + + SUBTTL LOGICAL OPERATIONS + PAGE + + + ;BTST +OPBTST PROC + NOT AX ;TURN OFF BITS IN OPR2 THAT ARE ON IN OPR1 + AND BX,AX + JE JPT ;SUCCESS IF OPR2 COMPLETELY CLEARED + JMP JPF +OPBTST ENDP + + ;BOR +OPBOR PROC + OR AX,BX ;LOGICAL OR + JMP PUTVAL ;RETURN THE VALUE +OPBOR ENDP + + ;BCOM +OPBCOM PROC + NOT AX ;LOGICAL COMPLEMENT + JMP PUTVAL ;RETURN THE VALUE +OPBCOM ENDP + + ;BAND +OPBAND PROC + AND AX,BX ;LOGICAL AND + JMP PUTVAL ;RETURN THE VALUE +OPBAND ENDP + + SUBTTL GENERAL PREDICATES + PAGE + + + PUBLIC OPQEQU,OPQZER + ;EQUAL? +OPQEQU PROC + NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV BX,ARGBLK ;GET OPR1 + CMP BX,ARGBLK[2] ;IS OPR1 EQUAL TO OPR2? + JE OQE1$ ;YES + CMP AX,3 ;NO, IS THERE A THIRD OPERAND? + JL OQE2$ ;NO + CMP BX,ARGBLK[4] ;YES, IS IT EQUAL TO OPR1? + JE OQE1$ ;YES + CMP AX,4 ;NO, IS THERE A FOURTH? + JL OQE2$ ;NO + CMP BX,ARGBLK[6] ;YES, IS IT EQUAL TO OPR1? + JNE OQE2$ ;NO +OQE1$: JMP PTRUE ;PREDICATE TRUE IF EQUAL +OQE2$: JMP PFALSE ;PREDICATE FALSE IF NOT +OPQEQU ENDP + + ;ZERO? +OPQZER PROC + CMP AX,0 ;IS OPR ZERO? + JNE OQZ1$ ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQZ1$: JMP PFALSE +OPQZER ENDP + + SUBTTL OBJECT OPERATIONS + PAGE + + + PUBLIC OPMOVE,OPREMO,OPQFSE,OPFSET + ;MOVE (OBJ1 INTO OBJ2) +OPMOVE PROC + PUSH AX ;PROTECT OPRS FROM REMOVE CALL + PUSH BX + CALL OPREMO ;REMOVE OBJ1 FROM WHEREVER IT IS + POP DX ;OBJ2 + MOV AX,DX + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + POP CX ;OBJ1 + MOV AX,CX + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV ES:[BP].PARENT,DL ; PUT OBJ2 INTO OBJ1'S LOC SLOT + MOV DH,ES:[BX].CHILD1 ; GET CONTENTS OF OBJ2'S FIRST SLOT + MOV ES:[BX].CHILD1,CL ; MAKE OBJ1 FIRST CONTENT OF OBJ2 + CMP DH,0 ;WERE THERE ANY OTHER CONTENTS? + JE OMV1$ ;NO + MOV ES:[BP].SIBLING,DH ; YES, CHAIN ONTO OBJ1'S SIBLING SLOT +OMV1$: RET +OPMOVE ENDP + + ;REMOVE (OBJ FROM ITS PARENT) +OPREMO PROC + MOV CX,AX ;SAVE OBJ FOR LATER + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + MOV CH,ES:[BX].PARENT ; GET ITS PARENT + CMP CH,0 ;DOES IT HAVE A PARENT? + JE ORM3$ ;IF NOT, WE'RE DONE + MOV AL,CH ;PARENT + CALL OBJLOC ;FIND PARENT'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:[BP].CHILD1 ; GET PARENT'S FIRST CONTENT + CMP DL,CL ;IS IT OBJ? + JNE ORM1$ ;NO + MOVM ES:[BP].CHILD1,ES:[BX].SIBLING,AL ;YES, CHANGE SLOT TO + ;OBJ'S SIBLING + JMP ORM2$ ;AND RETURN +ORM1$: MOV AL,DL ;CURRENT SIBLING + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:[BP].SIBLING ;GET NEXT SIBLING IN CHAIN + CMP DL,CL ;IS IT OBJ? + JNE ORM1$ ;NO, CONTINUE LOOP + MOVM ES:[BP].SIBLING,ES:[BX].SIBLING,AL ;YES, CHANGE IT TO + ;OBJ'S SIBLING +ORM2$: MOV ES:[BX].PARENT,0 ;OBJ NOW HAS NO PARENT + MOV ES:[BX].SIBLING,0 ;OR SIBLING +ORM3$: RET +OPREMO ENDP + + ;FSET? (IS FLAG SET IN OBJ?) +OPQFSE PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OQF1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OQF1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + TEST AX,DX ;IS THIS BIT SET IN FLAG WORD? + JE OQF2$ ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQF2$: JMP PFALSE +OPQFSE ENDP + + ;FSET (SET A FLAG IN OBJ) +OPFSET PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFS1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFS1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + OR AX,DX ;SET THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + RET +OPFSET ENDP + + PUBLIC OPFCLE,OPLOC,OPQFIR,OPQNEX,OPQIN + ;FCLEAR (CLEAR A FLAG IN OBJ) +OPFCLE PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFC1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFC1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,7FFFH ;SHIFT A BIT TO PROPER POSITION + ROR DX,CL + AND AX,DX ;CLEAR THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + RET +OPFCLE ENDP + + ;LOC (RETURN CONTAINER OF OBJ) +OPLOC PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].PARENT ; GET LOC SLOT + JMP BYTVAL ;RETURN THE BYTE VALUE +OPLOC ENDP + + ;FIRST? (RETURN FIRST SLOT OF OBJ, FAIL IF NONE) +OPQFIR PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].CHILD1 ; GET FIRST SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE +JPT1: JMP PTRUE ;NO, PREDICATE TRUE +JPF1: JMP PFALSE +OPQFIR ENDP + + ;NEXT? (RETURN THE NEXT (SIBLING) SLOT OF OBJ, FAIL IF NONE) +OPQNEX PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].SIBLING ; GET SIBLING SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE + JMP JPT1 ;NO, PREDICATE TRUE +OPQNEX ENDP + + ;IN? (IS OBJ1 CONTAINED IN OBJ2?) +OPQIN PROC + CALL OBJLOC ;FIND OBJ1'S LOCATION + XCHG AX,BX ;MOVE TO BASE + CMP ES:[BX].PARENT,AL ; IS OBJ1'S PARENT OBJ2? + JE JPT1 ;YES, PREDICATE TRUE + JMP JPF1 ;NO, PREDICATE FALSE +OPQIN ENDP + + PUBLIC OPGETP + ;GETP (GET SPECIFIED PROPERTY OF OBJ, DEFAULT IF NONE) +OPGETP PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ; LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGP2$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JL OGP3$ ;IF LESS, NO SUCH PROPERTY HERE + MOV AL,ES:[BX] ;GOT IT, NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,MASK PROPSIZE;GET LENGTH BITS + MOV CL,PROPSIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + JNE OGP5$ ;NO + MOV AL,ES:[BX] ;GET THE BYTE + JMP BYTVAL ;AND RETURN IT +OGP3$: DEC DX ;POINT INTO DEFAULT PROPERTY TABLE + SHL DX,1 + MOV BX,DX +OGP4$: ADD BX,OBJTAB ;GET THE WORD +OGP5$: GTAWRD A,[BX] + JMP PUTVAL ;AND RETURN IT +OPGETP ENDP + + ;PUTP (CHANGE VALUE OF A PROPERTY, ERROR IF BAD NUMBER) + PUBLIC OPPUTP,OPP2$ +OPPUTP PROC + PUSH CX ;SAVE NEW VALUE + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ; LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OPP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OPP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OPP2$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE OPP3$ ;IF EQUAL, GOT IT + JG OPP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR +OPP3$: MOV AL,ES:[BX] ;NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,MASK PROPSIZE;GET LENGTH BITS + MOV CL,PROPSIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + POP AX ;RESTORE NEW VALUE + JNE OPP4$ ;ZERO MEANS BYTE VALUE + MOV ES:[BX],AL ;STORE THE NEW BYTE + RET ;AND RETURN +OPP4$: PTAWRD [BX],A ;STORE THE NEW WORD VALUE + RET +OPPUTP ENDP + + ;NEXTP (RETURN NUMBER OF NEXT PROP FOLLOWING GIVEN PROB IN OBJ) + PUBLIC OPNEXT,ONX2$ +OPNEXT PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET ITS LOCATION + MOV AL,ES:[BX] ; LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + CMP DX,0 ;WERE WE GIVEN ZERO AS PROP? + JE ONX4$ ;YES, GO RETURN FIRST PROPERTY NUMBER + JMP ONX2$ ;NO, SKIP NEXT LINE FIRST TIME THROUGH LOOP +ONX1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX2$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE ONX3$ ;IF EQUAL, GOT IT + JG ONX1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR +ONX3$: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX4$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;EXTRACT PROPERTY NUMBER + JMP PUTVAL ;AND RETURN IT +OPNEXT ENDP + + SUBTTL TABLE OPERATIONS + PAGE + + + PUBLIC OPGET,OPGETB,OPPUT,OPGTPT + ;GET (GET THE ITEM'TH WORD FROM TABLE) +OPGET PROC + SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETWRD ;GET THE WORD + MOV AX,CX + JMP PUTVAL ;AND RETURN IT +OPGET ENDP + + ;GETB (GET THE ITEM'TH BYTE FROM TABLE) +OPGETB PROC + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETBYT ;GET THE BYTE + MOV AX,CX + JMP BYTVAL ;AND RETURN IT +OPGETB ENDP + + ;PUT (REPLACE THE ITEM'TH WORD IN TABLE) +OPPUT PROC + SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD BX,AX ;INDEX INTO TABLE + PTAWRD [BX],C ;STORE THE WORD + RET +OPPUT ENDP + + ;PUTB (REPLACE ITEM'TH BYTE IN TABLE) +OPPUTB PROC + ADD BX,AX ;INDEX INTO TABLE + MOV ES:[BX],CL ; STORE BYTE + RET +OPPUTB ENDP + + ;GETPT (GET POINTER TO PROPERTY TABLE FOR GIVEN PROP) +OPGTPT PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGT2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGT1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGT2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGT1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JE OGT3$ ;FOUND THE PROPERTY + SUB AX,AX ;RETURN ZERO FOR NO SUCH PROPERTY + JMP OGT4$ +OGT3$: INC BX ;POINT TO PROPERTY VALUE + MOV AX,BX ;AND RETURN IT +OGT4$: JMP PUTVAL +OPGTPT ENDP + + PUBLIC OPPTSI + ;PTSIZE (RETURN SIZE OF PROPERTY TABLE) +OPPTSI PROC + MOV BX,AX ;TABLE POINTER + MOV AL,ES:[BX-1] ;GET PROPERTY INDENTIFIER + AND AL,MASK PROPSIZE;EXTRACT LENGTH BITS + SUB AH,AH + MOV CL,PROPSIZE + SHR AX,CL + INC AX ;ADJUST TO ACTUAL LENGTH + JMP PUTVAL ;RETURN IT +OPPTSI ENDP + + SUBTTL VARIABLE OPERATIONS + PAGE + + + PUBLIC OPVALU,OPSET,OPPUSH,OPPOP + ;VALUE (GET VALUE OF VAR) +OPVALU PROC + CALL GETVAR ;GET THE VALUE + JMP PUTVAL ;AND RETURN IT +OPVALU ENDP + + ;SET (VAR TO VALUE) +OPSET PROC + JMP PUTVAR ;STORE THE VALUE +OPSET ENDP + + ;PUSH (A VALUE ONTO THE STACK) +OPPUSH PROC + PUSHZ AX ;PUSH THE VALUE + RET +OPPUSH ENDP + + ;POP (A VALUE OFF THE STACK INTO VAR) +OPPOP PROC + POPZ BX ;POP A VALUE + JMP PUTVAR ;AND STORE IT +OPPOP ENDP + + PUBLIC OPINC,OPDEC + ;INC (INCREMENT VAR) +OPINC PROC + MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT +OPINC1: MOV BX,AX ;VALUE + MOV AX,CX ;VARIABLE + JMP PUTVAR ;STORE NEW VALUE +OPINC ENDP + + ;DEC (DECREMENT VAR) +OPDEC PROC + MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + JMP OPINC1 ;STORE NEW VALUE +OPDEC ENDP + + PUBLIC OPQIGR,OPQDLE + ;IGRTR? (INCREMENT VAR & TEST IF GREATER THAN VAL) +OPQIGR PROC + PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE GREATER THAN VAL? + JLE OPQIG1 ;NO +OPQIG0: INC CX ;YES, CHANGE FLAG TO TRUE +OPQIG1: MOV BX,AX ;VALUE + POP AX ;RESTORE VARIABLE + CALL PUTVAR ;STORE NEW VALUE + CMP CX,0 ;TEST FLAG + JE OQI1$ ;FALSE, PREDICATE FALSE + JMP PTRUE ;ELSE, PREDICATE TRUE +OQI1$: JMP PFALSE +OPQIGR ENDP + + ;DLESS? (DECREMENT VAR & TEST IF LESS THAN VAL) +OPQDLE PROC + PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE LESS THAN VAL? + JGE OPQIG1 ;NO, PREDICATE FALSE + JMP OPQIG0 ;YES, PREDICATE TRUE +OPQDLE ENDP + + SUBTTL I/O OPERATIONS + PAGE + + PUBLIC GETLIN,GETLLP,GETLLC,GETLEM + +;for the boss key, include the boss file +INCLUDE iboss.asm + +GETLIN PROC + PUSH BX + MOV SCRHLD,1 ; (7n) HOLD SCRIPTING + PUSH SI + MOV CL,ES:[SI] + MOV BX,OFFSET INBUF + MOV BYTE PTR [BX],CL + CMP CL,MAXLIN ; (7r) DON'T EXCEED BUFFER LENGTH + JBE GTLN0 ; (7r) FIX IF ABOVE + MOV BYTE PTR [BX],MAXLIN ; (7r) WITH OUR NEW MAXIMUM +GTLN0: MOV DX,BX + MOV AH,CRDLIN + INT 21H + TEST SCROLL,1 ;(7) WHAT KIND OF SCROLLING + JNZ GTLN1 + MOV AH,SCROLLUP ;(7) USE A VIDEO BIOS SCROLL + MOV AL,1 ;(7) ONLY 1 LINE + MOV CX,TOPLIN ;(7) ALWAYS FREEZE TOP LINE + MOV DH,SLPP ;(7) GET SCREEN LENGTH + MOV DL,SCPL ;(7) GET THE WIDTH OF THE SCREEN + DEC DL ; (7v) COORDINATES ARE ZERO BASED + MOV BH,SCRATR ;(7) GET THE SCREEN ATTRIBUTE + INT 10H ;(7) CALL THE VIDEO + JMP GTLN2 ;(7) SKIP LINE FEED OUTPUT +GTLN1: MOV AH,CCONIO + MOV DL,10 + INT 21H +GTLN2: POP DX + MOV BX,OFFSET INBUF + MOV CL,BYTE PTR [BX+1] + SUB CH,CH + INC BX + CMP CL,0 + JE GETLEM +GETLLP: INC SI + INC BX + MOV AL,BYTE PTR [BX] + + CALL boss + JNC GETLLC1 ;boss returns Carry Set if boss chr + MOV AL," " +GETLLC1: + CMP AL,"A" + JL GETLLC + CMP AL,"Z" + JG GETLLC + ADD AL,32 +GETLLC: MOV ES:[SI],AL + LOOP GETLLP +GETLEM: INC SI + SUB AL,AL + MOV ES:[SI],AL + MOV SCRHLD,0 ; (7n) TURN OFF SCRIPT HOLD + POP BX + RET +GETLIN ENDP + + PUBLIC PRTOUT +PRTOUT PROC + PUSH AX + PUSH BX + PUSH CX + PUSH DX ; (7) SAVE THIS, USING STD PRT + CMP SCROLL,1 ; (7) ARE WE COMPATIBLE + JZ POUT1 ; (7) NO + TEST CMDLIN,16 ; (7n) DO WE WANT IBM PRINTER + JZ POUT1 ; (7n) GUESS NOT +POUT0: MOV AH,0 ; (7) FUNCTION TO PRINT + MOV DX,0 ; (7) TO THE FIRST PRINTER + INT 17H ; (7) TRY IT + TEST AH,RDYBIT ; (7) TIME OUT? + JZ POUT2 ; (7) WORKED, RETURN + CALL PRNRDY ; (7) + JC POUT2 + JMP POUT0 ; (7) RETRY +POUT1: MOV DL,AL ; (7n) GET CHARACTER TO PRINT + MOV AH,CPROUT ; (7n) PRINT IT + INT 21H +POUT2: POP DX ; (7n) FORGET THIS AND BREAK... + POP CX + POP BX + POP AX + RET +PRTOUT ENDP + + PUBLIC PRNRDY,SCRCHK +PRNRDY PROC + PUSH AX + MOV SCRHLD,1 ; (7n) HOLD OFF SCRIPTING + PRINT PRNNRDY ; (7) ASK USER ABOUT ACTION +RDY1: CALL MCHRI ; (7) GET A RESPONSE + CALL MTTYO ; (7u) ECHO THE CHARACTER + AND AL,5FH ; (7) UPPPER CASIFY + CMP AL,'A' ; (7) SHOULD WE ABORT + JNZ RDY2 ; (7) ATTEMPTING RETRY + MOV SCRFLG,0 ; (7) TURN OFF SCRIPTING + AND ES:[PFLAGS],SCRMSK ; (7) AND IN THE MODE WORD + MOV SCRHLD,0 ; (7n) TURN OFF BAN ON SCRIPTING + STC ; (7) SET CARRY FOR NO RETRY + PUSHF ; (7) SAVE THESE + JMP RDY3 ; (7) CR LF ON EXIT +RDY2: CMP AL,'R' ; (7) RETRY??? + JNZ RDY1 ; (7) WRONG CHARACTER + CLC ; (7) CLEAR CARRY FOR RETRY + PUSHF ; (7) SAVE FLAGS +RDY3: CALL MCRLF ; (7) DO A + MOV SCRHLD,0 ; (7n) TURN OFF BAN ON SCRIPTING + POPF ; (7) RESTORE FLAGS AND + POP AX ; (7) CHARACTER TO PRINT + RET +PRNRDY ENDP + +SCRCHK PROC + PUSH AX + PUSH BX + PUSH DX + GTAWRD A,[PFLAGS] + TEST AL,1 ;CHECK IF SCRIPTING IS REQUESTED + JZ SCRNN$ + TEST SCRFLG,1 ; (7) NEW STATE? + JNZ SCR0L$ ; (7x) NO, CONTINUE + MOV SCRFLG,1 ; (7n) TURN ON SCRIPT FLAG + CMP SCROLL,0 ; (7) SHOULD WE BE DOING THIS? + JNZ SCR0L$ ; (7) NOPE... + TEST CMDLIN,16 ; (7n) DID WE REALLY REQUEST IBM + JZ SCR0L$ +SCR_1$: MOV DX,0 ; (7) TRY TO INIT THE PRINTER + MOV AH,1 + INT 17H ; (7) SO THAT WE WILL TIME OUT FAST + TEST AH,PRTMSK ; (7) TEST FOR TIME OUT + JZ SCR0L$ ; (7) NO PROBLEM, WE'RE FINE + CALL PRNRDY ; (7) INFORM USER OF PROBLEM + JNC SCR_1$ + JMP SCRNN$ ; (7) TURN OFF SCRIPTING +SCR0L$: SUB CX,CX + MOV BP,DX + INC BP +SCR1L$: MOV AL,ES:[BP] + INC BP + CMP BP,SI + JLE SCR2L$ + CALL PRTCRL + JMP SCREX$ +SCR2L$: CALL PRTOUT + INC CX + CMP CL,SCPL + JNE SCR1L$ + CALL PRTCRL + JC SCREX$ + SUB CX,CX + JMP SCR1L$ + +SCRNN$: MOV SCRFLG,0 +SCREX$: POP DX + POP BX + POP AX + RET +SCRCHK ENDP + + PUBLIC PRTCRL +PRTCRL PROC + MOV AL,13 ;FINISH UP WITH CRLF + CALL PRTOUT + MOV AL,10 + CALL PRTOUT + RET +PRTCRL ENDP + + ;READ (A LINE OF INPUT & PARSE IT, LINE BUF IN ES:AX, + ;RETURN BUF IN ES:BX) + PUBLIC OPREAD,ORD1$,ORDNS$,ORD8$,ORD9$,ORD10$,ORD1A$,ORD11$,ORD12$ + PUBLIC ORD13$,ORD14$,ORD15$,ORD16$,ORD17$,ORD18$,ORD19$,ORD20$ + PUBLIC ORD21$,ORD22$,ORD23$ +OPREAD PROC + PUSH AX ;SAVE LINE BUF + PUSH AX + PUSH BX + CALL OPUSL ;UPDATE STATUS LINE + POP BX + POP AX + MOV BP,CHRPTR ;NEXT CHARACTER POSITION + MOV BYTE PTR DS:[BP],80H ;(6)DON'T END OUTPUT, IF ANY, WITH NEW LINE +ORD1$: PRINT OUTBUF ;FORCE OUT ANY QUEUED TEXT + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP SI ;INPUT BUFFER POINTER + MOV MORLIN,0 ;RE-INITIALIZE MORE COUNT FROM HERE + CALL GETLIN ;GET SOME CHARACTERS + CALL SCRCHK +ORDNS$: PUSH DI + MOV RDBOS,DX ;INITIALIZE RDBOS + MOV RDEOS,SI ;AND RDEOS + MOV RDRET,BX ;STORE RET POINTER + MOV RDNWDS,0 ;NO WORDS SO FAR + INC DX ;SKIP LENGTH BYTE + MOV DI,BX ;THIS WILL BE WORD ENTRY POINTER + INC DI ;SKIP MAX WORDS & NWORDS BYTES + INC DI +ORD8$: MOV CX,OFFSET RDWSTR;HERE FOR NEXT WORD, POINT TO WORD STRING + MOV BX,DX ;AND SAVE BEGINNING OF WORD POINTER +ORD9$: CMP DX,RDEOS ;END OF STRING? + JNE ORD10$ ;NO + CMP CX,OFFSET RDWSTR;YES, WAS A WORD FOUND? + JNE ORD15$ ;YES, WE STILL HAVE TO LOOKUP WORD + JMP ORD23$ ;NO, WE'RE DONE +ORD10$: MOV BP,DX ;GET NEXT CHARACTER FROM BUFFER + MOV AL,ES:[BP] + CMP AL,"A" + JL ORD1A$ + CMP AL,"Z" + JG ORD1A$ + ADD AL,32 ;LOWERCASIFY ALPHABETICS +ORD1A$: INC DX + MOV SI,OFFSET RBRKS ;LIST OF READ BREAK CHARACTERS +ORD11$: INC SI + CMP AL,[SI-1] ;SEARCH LIST FOR THIS ONE + JE ORD12$ ;FOUND IT + CMP BYTE PTR [SI],0 ;END OF LIST? + JNE ORD11$ ;NO, CONTINUE SEARCH + CMP CX,OFFSET RDWSTR[6] ;YES, NOT A BREAK, WORD STRING FULL? + JE ORD9$ ;YES, LOOP UNTIL END OF WORD + MOV BP,CX ;NO, TACK THIS CHARACTER ONTO STRING + MOV DS:[BP],AL + INC CX + JMP ORD9$ ;AND LOOP +ORD12$: CMP CX,OFFSET RDWSTR;WORD READ BEFORE THIS BREAK? + JNE ORD14$ ;YES + CMP SI,ESIBKS ;NO, BUT IS IT A SELF-INSERTING BREAK? + JBE ORD13$ ;YES + INC BX ;NO, UPDATE BEGINNING OF WORD TO SKIP BREAK + JMP ORD9$ ;AND RETURN TO LOOP TO FIND A WORD +ORD13$: MOV BP,CX ;STORE THE BREAK IN WORD STRING + MOV DS:[BP],AL + INC CX + JMP ORD15$ ;AND GO FOR THE WORD +ORD14$: DEC DX ;UNREAD TERMINATING BREAK IN CASE IT WAS SI +ORD15$: INC RDNWDS ;INCREMENT FOUND WORD COUNT + MOV BP,BX ;GREATER THAN MAX ALLOWED? + MOV BX,RDRET + MOV BL,ES:[BX] + CMP BL,59 ; (7w) GAME FIX + JBE ORD15A ; (7w) FIX NUMBER OF TOKENS ALLOWED + MOV BL,59 ; (7w) OTHERWISE WE OVERRUN A TABLE +ORD15A: CMP RDNWDS,BL + MOV BX,BP + JLE ORD16$ ;NO + PRINT ERR2 ;YES, INFORM LOSER + MOV AX,BX ;BEGINNING OF THIS WORD + MOV BP,RDEOS ;SAVE BYTE AFTER EOS + MOV BL,ES:[BP] + MOV BYTE PTR ES:[BP],0 ; ZERO IT TO MAKE STRING ASCIZ + PUSH BX ; (7w) SAVE THIS ADDRESS + MOV BX,DS ; (7w) FIGURE WHERE STRING IS IN DS + NEG BX ; (7w) SUBTRACT DS FROM ES + ADD BX,GAMESEG ; (7w) BX HAS PARAGRAPHS OF DIFFERENCE + MOV CL,4 ; (7w) CONVERT TO AN OFFSET + SHL BX,CL ; (7w) TO ADD IN WITH AX + ADD AX,BX ; (7w) NOW DS:AX SHOULD EQUAL PREV ES:AX + POP BX ; (7w) RESTORE BX + CALL MPRNT ;PRINT IT + MOV ES:[BP],BL ; AND RESTORE OLD BYTE + DEC RDNWDS ;REMEMBER THAT WE FLUSHED THIS WORD + JMP ORD23$ ;AND WE'RE DONE +ORD16$: MOV AX,BX ;CALCULATE NUMBER OF CHARACTERS IN WORD + NEG AX + ADD AX,DX + MOV ES:[DI+2],AL ;(6)SAVE THE NUMBER IN RET TABLE + SUB BX,RDBOS ;BYTE OFFSET FOR BEGINNING OF WORD + MOV ES:[DI+3],BL ;(6)STORE IT, TOO + MOV BP,CX ;MAKE WORD STRING ASCIZ + MOV BYTE PTR DS:[BP],0 ;(6) REMOVED SEG OVERRIDE (DS) + MOV AX,OFFSET RDWSTR;POINT TO IT + CALL ZWORD ;AND CONVERT TO (2-WORD) ZWORD + PUSH DX ;SAVE CHAR & WORD ENTRY POINTERS + PUSH DI + MOV DI,AX ;FIRST ZWORD WORD + MOV SI,VWORDS ;NUMBER OF VOCABULARY WORDS + MOV AX,SI + DEC AX ;WE WANT TO POINT TO LAST WORD + MUL VWLEN ;MULTIPLY BY WORD LENGTH IN BYTES + ADD AX,VOCBEG ;ADD POINTER TO BEGINNING TO FIND LAST WORD + MOV CX,AX ;POINTER TO LAST WORD + MOV DX,DI ;FIRST ZWORD WORD + MOV DI,BX ;SECOND ZWORD WORD + MOV BX,VWLEN ;CALCULATE INITIAL OFFSET FOR BINARY SEARCH + SAR SI,1 +ORD17$: SAL BX,1 + SAR SI,1 + CMP SI,0 + JNE ORD17$ + MOV SI,VOCBEG ;BEGINNING OF WORD TABLE + ADD SI,BX ;ADD CURRENT OFFSET(HALF OF POWER-OF-2 TABLE) + PUSH AX ;SAVE + MOV AX,VWLEN ;AVOID FENCEPOST BUG FOR EXACT POWER-OF-2 TBL + SUB SI,AX + POP AX ;RESTORE +ORD18$: SAR BX,1 ;NEXT OFFSET WILL BE HALF OF PREVIOUS ONE + GTAWRD A,[SI] ;GET FIRST HALF OF CURRENT ZWORD + CMP DX,AX ;COMPARE DESIRED ONE TO IT + JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + MOV BP,SI ;SAME, GET SECOND HALF + INC BP + INC BP + GTAWRD A,[BP] + CMP DI,AX ;COMPARE DESIRED WORD WITH IT + JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + JMP ORD22$ ;SAME, WE'VE FOUND IT, RETURN IT +ORD19$: ADD SI,BX ;TO MOVE UP, ADD CURRENT OFFSET + CMP SI,CX ;HAVE WE MOVED PAST END OF TABLE? + JBE ORD21$ ;NO + MOV SI,CX ;YES, POINT TO END OF TABLE INSTEAD + JMP ORD21$ +ORD20$: SUB SI,BX ;TO MOVE DOWN, SIMPLY SUBTRACT OFFSET +ORD21$: CMP BX,VWLEN ;IS OFFSET RESOLUTION BELOW ONE WORD? + JGE ORD18$ ;NO, CONTINUE LOOP + SUB SI,SI ;YES, WORD NOT FOUND, RETURN ZERO +ORD22$: POP DI ;RESTORE WORD ENTRY POINTER + MOV DX,SI ;POINTER TO WORD FOUND + XCHG DH,DL + MOV ES:[DI],DX ;(6) STORE IT + POP DX ;RESTORE CHAR POINTER + ADD DI,4 ;UPDATE POINTER FOR NEXT WORD ENTRY + JMP ORD8$ ;GO FOR IT +ORD23$: INC RDRET ;DONE, STORE NUMBER OF WORDS FOUND + MOV BP,RDRET + MOVM ES:[BP],RDNWDS,DL ; REMOVED ES OVERRIDE + POP DI ;RESTORE USER STACK POINTER + RET ;AND RETURN +OPREAD ENDP + + ;PRINTC (PRINT CHAR WHOSE ASCII VALUE IS GIVEN) + PUBLIC OPPRNC,OPPRNN +OPPRNC PROC + JMP PUTCHR ;QUEUE THE CHARACTER FOR PRINTING +OPPRNC ENDP + + ;PRINTN (PRINT A NUMBER) +OPPRNN PROC + MOV BX,AX ;NUMBER TO PRINT + CMP BX,0 + JNE OPN1$ ;NON-ZERO + MOV AX,"0" ;SPECIAL CASE ZERO + JMP PUTCHR +OPN1$: JG OPN2$ ;POSITIVE? + MOV AX,"-" ;NO, PRINT MINUS SIGN + CALL PUTCHR + NEG BX ;AND MAKE IT POSITIVE +OPN2$: SUB CX,CX ;COUNT OF DIGITS ON STACK + JMP OPN4$ ;START WITH GREATER-THAN-10 TEST +OPN3$: MOV AX,BX ;EXTRACT A DIGIT + MOV BP,10 + CWD + IDIV BP + PUSH DX ;PUSH IT + INC CX ;BUMP COUNT + MOV BX,AX ;GET QUOTIENT +OPN4$: CMP BX,10 ;MORE DIGITS TO EXTRACT? + JGE OPN3$ ;YES, GO LOOP + MOV AX,BX ;NO, GET LAST (FIRST) DIGIT + JMP OPN6$ ;ALREADY IN PLACE +OPN5$: POP AX ;POP NEXT DIGIT +OPN6$: ADD AX,"0" ;ASCIIZE IT + CALL PUTCHR ;QUEUE IT + DEC CX ;REDUCE DIGIT COUNT + JGE OPN5$ ;LOOP IF SOME LEFT + RET ;ELSE, RETURN +OPPRNN ENDP + + PUBLIC OPPRIN,OPPRNB + ;PRINT (THE STRING POINTED TO BY ES:AX) +OPPRIN PROC + CALL BSPLIT ;SPLIT THE BLOCK & WORD NUMBERS + JMP PUTSTR ;PRINT THE STRING +OPPRIN ENDP + + ;PRINTB (PRINT THE STRING POINTED TO BY THE BYTE-POINTER ES:AX) +OPPRNB PROC + CALL BSPLTB ;SPLIT THE BLOCK & BYTE NUMBERS + JMP PUTSTR ;PRINT THE STRING +OPPRNB ENDP + +;PSEUDO-INSTRUCTIONS FOR HOURS/MINUTES HERE FOR STATUS LINE +OPPRNH PROC + MOV PMFLAG,0 + CMP AL,12 + JL OPH0$ + MOV PMFLAG,1 +OPH0$: CMP AL,12 + JLE OPH1$ + SUB AL,12 ;HOUR SLOT IS 24 HOUR TIME +OPH1$: CMP AL,0 + JNE OPHZ$ + MOV AL,12 +OPHZ$: CMP AL,9 + JG OPH2$ + PUSH AX + MOV AL,32 + CALL PUTCHR ;OUTPUT SPACE FOR HOUR LESS THAN 10 + POP AX +OPH2$: CALL OPPRNN + MOV AL,":" + JMP PUTCHR ;AND COLON +OPPRNH ENDP + +OPPRNM PROC + CMP AL,9 + JG OPM1$ + PUSH AX + MOV AL,"0" + CALL PUTCHR + POP AX +OPM1$: CALL OPPRNN + MOV AL,32 + CALL PUTCHR + MOV AL,"a" + CMP PMFLAG,0 + JE OPM2$ + MOV AL,"p" +OPM2$: CALL PUTCHR + MOV AL,"m" + JMP PUTCHR +OPPRNM ENDP + + PUBLIC OPPRND,OPPRNI,OPPRNR + ;PRINTD (PRINT OBJ'S SHORT DESCRIPTION) +OPPRND PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + ADD AX,7 ;PROPERTY TABLE POINTER + MOV BP,AX + GTAWRD A,[BP] ;GET IT + INC AX ;POINT TO STRING + CALL BSPLTB ;SPLIT POINTER + JMP PUTSTR ;AND PRINT THE STRING +OPPRND ENDP + + ;PRINTI (PRINT THE STRING FOLLOWING THIS INSTRUCTION) +OPPRNI PROC + MOV AX,ZPC1 ;GET POINTER TO STRING + MOV BX,ZPC2 + CALL PUTSTR ;AND PRINT IT + MOV ZPC1,AX ;UPDATE ZPC + MOV ZPC2,BX + JMP NEWZPC +OPPRNI ENDP + + ;PRINTR (PRINTI FOLLOWED BY RTRUE) +OPPRNR PROC + CALL OPPRNI ;DO A PRINTI + CALL OPCRLF ;A CRLF + JMP OPRTRU ;AND AN RTRUE +OPPRNR ENDP + + PUBLIC OPCRLF + ;CRLF (DO A NEWLINE) +OPCRLF PROC + JMP NEWLIN ;DO A NEWLINE +OPCRLF ENDP + + SUBTTL CONTROL OPERATIONS + PAGE + + + PUBLIC OPCALL + ;CALL (A FUNCTION WITH OPTIONAL ARGUMENTS), # OF ARGS IN AX +OPCALL PROC + NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV DX,AX ;NUMBER OF ARGUMENTS TO CALL + MOV AX,ARGBLK ;FUNCTION TO CALL + CMP AX,0 + JNE OCL1$ ;ZERO? + SUB AX,AX ;YES, SIMPLY RETURN A ZERO + JMP PUTVAL +OCL1$: PUSHZ ZPC1 ;OTHERWISE, SAVE OLD ZPC + PUSHZ ZPC2 + MOV CX,ZLOCS ;AND OLD LOCAL POINTER +; SUB CX,STKBOT ;BUT RELATIVIZE IT IN CASE OF SAVE + PUSHZ CX ;AND SAVE IT + CALL BSPLIT ;SPLIT FUNCTION POINTER + MOV ZPC1,AX ;MAKE IT THE NEW ZPC + MOV ZPC2,BX + CALL NEWZPC ;UPDATE ZPC STUFF + MOV ZLOCS,DI ;LOCALS WILL START AT NEXT STACK SLOT + SUB ZLOCS,2 + CALL NXTBYT ;NUMBER OF LOCALS + MOV BX,AX + MOV BP,OFFSET ARGBLK[2] ;POINT TO FIRST OPTIONAL ARG +OCL2$: DEC BX ;ANY MORE LOCALS? + JL OCL4$ ;NO, WE'RE DONE + CALL NXTWRD ;YES, GET THE NEXT LOCAL DEFAULT VALUE + DEC DX ;ANY MORE OPTIONALS GIVEN? + JLE OCL3$ ;NO + PUSHZ [BP] ;(6) YES, USE ITS VALUE + ADD BP,2 + JMP OCL2$ ;AND CONTINUE LOOP +OCL3$: PUSHZ AX ;OTHERWISE, USE DEFAULT + JMP OCL2$ ;AND LOOP +OCL4$: RET +OPCALL ENDP + + PUBLIC OPRETU + ;RETURN (FROM CURRENT FUNCTION CALL) +OPRETU PROC + MOV DI,ZLOCS ;RESTORE OLD TOP OF STACK + POPZ DX ;DUMMY POP [WHY?] + POPZ ZLOCS ;AND OTHER VALUES + +; MOV DX,STKBOT ;RE-ABSOLUTIZE THIS ONE +; ADD ZLOCS,DX + + POPZ ZPC2 + POPZ ZPC1 + PUSH AX ;VALUE TO RETURN + CALL NEWZPC ;UPDATE ZPC STUFF + POP AX + JMP PUTVAL ;RETURN THE VALUE +OPRETU ENDP + + PUBLIC OPRTRU,OPRFAL,OPJUMP,OPRSTA,OPFSTA,OPNOOP + ;RTRUE +OPRTRU PROC + MOV AX,1 ;RETURN A 1 + JMP OPRETU +OPRTRU ENDP + + ;RFALSE +OPRFAL PROC + SUB AX,AX ;RETURN A 0 + JMP OPRETU +OPRFAL ENDP + + ;JUMP (TO A NEW LOCATION) +OPJUMP PROC + ADD ZPC2,AX ;ADD OFFSET TO CURRENT ZPC + SUB ZPC2,2 ;ADJUST IT + JMP NEWZPC ;NORMALIZE IT & UPDATE ZPC STUFF +OPJUMP ENDP + + ;RSTACK (RETURN STACK) +OPRSTA PROC + POPZ AX ;POP A VALUE + JMP OPRETU ;AND RETURN IT +OPRSTA ENDP + + ;FSTACK (FLUSH A VALUE OFF THE STACK) +OPFSTA PROC + POPZ DX ;FLUSH ONE + RET +OPFSTA ENDP + + ;NOOP (NO OPERATION) +OPNOOP PROC + RET ;DO NOTHING +OPNOOP ENDP + + SUBTTL LOW LEVEL FUNCTIONS + PAGE + + + ;GET A BYTE, BLOCK-POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX, + ;UPDATE AX & BX TO REFLECT BYTE GOTTEN +; +; GETBYT UNDERWENT SERIOUS RE-WRITING AND EVALUATION IN THE UPDATE TO USE +; ALL OF MEMORY. THE ORIGINAL ROUTINE WAS KEPT BUT CHANGES WERE MADE IN +; TWO SETS: THE FIRST TO HANDLE THE CASE IN WHICH ALL OF THE GAME IS IN +; MEMORY; AND THE SECOND IN WHICH THE GAME BUFFERS EXTEND PAST 64K AND THUS +; REQUIRING A SEGMENT SWITCH TO RETRIEVE THE BYTE. +; +; FOR THE FIRST CASE, THE BLOCK PTR IS USED TO DETERMINE THE SEGMENT IN +; WHICH THE BLOCK RESIDES, THE GAME SEGMENT IS SET ACCORDINGLY, AND THE +; BYTE IS FETCHED. +; +; THE SECOND CASE WILL CALL GETPAG TO DETERMINE WHERE THE PAGE IS LOCATED IN +; CORE. CALLING GETPAG WILL SET A VARIABLE CALLED CURSEG TO 0 OR 1 TO INDICATE +; THAT THE PAGE WE ARE TOUCHING IS IN THE FIRST OR SECOND SEGMENT. GETPAG +; RETURNS A VALID POINTER ASSUMING THAT THIS ROUTINE WILL SET ES ACCORDING TO +; CURSEG. IF CURSEG IS 0, GAMESEG (THE FIRST SEGMENT [OR ZEROTH]) WILL +; CONTAIN THE BLOCK, AND IF CURSEG IS 1, SEG1 (GAMESEG + 64K) WILL CONTAIN +; THE BLOCK. +; +; NOTE THAT ES ALWAYS CONTAINS THE VALUE GAMESEG UNLESS WE NEED TO FETCH +; OR PUT SOMETHING IN THE SECOND SEGMENT. AT THAT POINT ES IS SET TO SEG1 +; ONLY FOR THAT OPERATION. +; + PUBLIC GETBYT,FETCH,GTY1A$,GTSEG1,GTY1$,GTY1B$,GTY2$,GTY3$ +GETBYT PROC + PUSH SI ; SAVE THIS BEAR + PUSH AX ;SAVE BLOCK-POINTER + CMP FITS,1 ; (6) IS ALL OF THE GAME RESIDENT + JZ FETCH ; (6) IT'S THERE, GO GET IT + CMP AX,ENDLOD ;IS THIS A PRELOADED LOCATION? + JGE GTY1$ ;NO +FETCH: CMP AX,128 ; (6) CHECK SEGMENT FOR BLOCK + JGE GTSEG1 ; (6) GET BYTE FROM SEGMENT 1 +GTY1A$: MOV CL,9 ;YES, RECONSTRUCT POINTER + SHL AX,CL ;SHIFT BLOCK POINTER BY 9 + OR AX,BX ;ADD IN THE OFFSET + XCHG AX,BX + MOV CL,ES:[BX] ;GET THE BYTE + JMP GTY2$ ;CLEAR UNWANTED BYTE & RETURN IT +GTSEG1: MOV SI,SEG1 ; (6) GET SECOND GAME SEG + MOV ES,SI ; (6) ADDRESS SEG1 + JMP GTY1A$ ; (6) USE SEG0 LOGIC +GTY1$: CALL GETPAG ;FIND THE PROPER PAGE + ADD AX,BX ;POINT TO DESIRED BYTE + XCHG AX,BX + CMP CURSEG,1 ;(6) CHECK SEGMENT THAT WERE LOOKING IN + JNZ GTY1B$ ;(6) ITS IN 0, GET IT NORMALLY + MOV SI,SEG1 ;(6) ITS NOT, SET UP ES TO SEG1 + MOV ES,SI ;(6) GETPAG RETURNED RIGHT POINTER +GTY1B$: MOV CL,ES:[BX] ;GET IT +GTY2$: SUB CH,CH ;CLEAR UNWANTED BYTE & RETURN IT + MOV BX,AX + MOV SI,GAMESEG ; (6) MAKE SURE GAME SEG IS RESTORED + MOV ES,SI ; (6) TO SEG 0 + POP AX ;RESTORE BLOCK-POINTER + POP SI ; RESTORE THIS + INC BX ;UPDATE POINTER + CMP BX,200H ;END-OF-PAGE? + JNE GTY3$ ;NO + SUB BX,BX ;YES, CLEAR BYTE-POINTER + INC AX ;AND UPDATE BLOCK-POINTER +GTY3$: RET +GETBYT ENDP + + ;GET A WORD, BLOCK POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX + PUBLIC GETWRD +GETWRD PROC + PUSH DX ;SAVE + CALL GETBYT ;GET HIGH-ORDER BYTE + PUSH CX ;SAVE IT + CALL GETBYT ;GET LOW-ORDER BYTE + POP DX ;GET OTHER BYTE + MOV CH,DL ;POSITION IT + POP DX ;RESTORE + RET +GETWRD ENDP + + ;GET THE NEXT BYTE, RETURN IT IN AX +; THIS ROUTINE ALSO WENT UNDER SIGNIFICANT REVISION TO ACCOMODATE MORE +; PAGING SPACE. TWO CASES HAD TO BE HANDLED: ALL OF GAME IN MEMORY AND +; MORE THAN 64K OF PAGING SPACE. THE FIRST CASE REQUIRED THAT THE VARIABLE +; ZPCSEG BE SET IN NEWZPC TO INDICATE IN WHICH SEGMENT OUR ZPC BLOCK COULD +; BE FOUND. THE SECOND CASE REQUIRES THAT ZPCSEG BE SET ONLY WHEN GETPAG +; IS CALLED FROM NEWZPC AND THE PAGE THAT IT GOT WAS PUT IN THE SECOND GAME +; SEGMENT. +; + PUBLIC NXTBYT,NXBA$,NXB1$ +NXTBYT PROC + PUSH SI ;(6) PRESERVE THIS ONE TOO + PUSH BX ;SAVE + TEST ZPCFLG,1 ;(7n) HAS THIS PAGE SEEN FOUL PLAY? + JZ NXB0$ ; (7n) NOPE + CALL NEWZPC ; (7n) FIX INDEX INTO CURRENT PAGE +NXB0$: MOV BX,ZPC2 ;BYTE POINTER + ADD BX,CURPAG ;INDEX INTO CURRENT PAGE + CMP ZPCSEG,0 ;(6) WHERE ARE WE? + JZ NXBA$ ;(6) SEG0, ACT NORMALLY + MOV SI,SEG1 ;(6) GET SEG1 VALUE + MOV ES,SI ;(6) INTO ES +NXBA$: MOV AL,BYTE PTR ES:[BX] ; GET BYTE + PUSH AX ; AND SAVE +;PUSH ES:[BX] ;SAVE BYTE -- AT KILLER CODE ON FFFF + MOV SI,GAMESEG ;(6) GET BASE GAME SEG + MOV ES,SI ;(6) BACK INTO ES + INC ZPC2 ;UPDATE PC + CMP ZPC2,200H ;END-OF-PAGE? + JL NXB1$ ;NO + CALL NEWZPC ;YES, UPDATE PAGE +NXB1$: POP AX ;RETRIEVE BYTE + SUB AH,AH ;CLEAR UNWANTED BYTE + POP BX ;RESTORE + POP SI + RET ;AND RETURN IT +NXTBYT ENDP + + ;GET THE NEXT WORD, RETURN IT IN AX + PUBLIC NXTWRD +NXTWRD PROC + PUSH BX ;SAVE + CALL NXTBYT ;GET HIGH-ORDER BYTE + PUSH AX ;SAVE IT + CALL NXTBYT ;GET LOW-ORDER BYTE + POP BX ;GET HIGH-ORDER BYTE + MOV AH,BL ;POSITION IT + POP BX ;RESTORE + RET ;RETURN THE WORD +NXTWRD ENDP + + ;GET AN ARGUMENT GIVEN ITS TYPE IN AX + PUBLIC GETARG +GETARG PROC + DEC AX ;EXAMINE ARGUMENT + JL NXTWRD ;0 MEANT LONG IMMEDIATE + JE NXTBYT ;1 MEANT SHORT IMMEDIATE + CALL NXTBYT ;2 MEANT VARIABLE, GET THE VAR + CMP AX,0 ;STACK? + JNE GETVAR ;NO, JUST GET THE VAR'S VALUE + POPZ AX ;YES, POP THE STACK + RET +GETARG ENDP + + ;GET VALUE OF A VARIABLE, VAR IN AX, VALUE RETURNED IN AX + PUBLIC GETVAR +GETVAR PROC + CMP AX,0 ;STACK? + JNE GTV1$ ;NO + POPZT AX ;YES, GET TOP-OF-STACK + RET +GTV1$: PUSH BP ;SAVE + CMP AX,16 ;LOCAL? + JGE GTV3$ ;NO + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV AX,[BP] ;AND GET IT +GTV2$: POP BP ;RESTORE + RET +GTV3$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + MOV BP,AX ;AND GET IT + GTAWRD A,[BP] + JMP GTV2$ +GETVAR ENDP + + ;UPDATE VALUE OF A VARIABLE, VAR IN AX, NEW VALUE IN BX + PUBLIC PUTVAR +PUTVAR PROC + CMP AX,0 ;STACK? + JNE PTV1$ ;NO + PUSHZT BX ;YES, UPDATE TOP-OF-STACK + RET +PTV1$: CMP AX,16 ;LOCAL? + JGE PTV2$ ;NO + PUSH BP ;SAVE + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV [BP],BX ;AND UPDATE IT + POP BP ;RESTORE + RET +PTV2$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + XCHG AX,BX ;AND UPDATE IT + PTAWRD [BX],A + RET +PUTVAR ENDP + + ;RETURN VAL IN AX TO LOCATION SPECIFIED BY NEXTBYTE + ;DESTROYS BX, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION + PUBLIC BYTVAL +BYTVAL PROC + SUB AH,AH ;THIS ENTRY FOR BYTE VALUE TO CLEAR HIGH BYTE + JMP PUTVAL +BYTVAL ENDP + + PUBLIC PUTVAL +PUTVAL PROC + MOV BX,AX ;NORMAL ENTRY + CALL NXTBYT ;GET VAR TO USE + CMP AX,0 ;STACK? + JNE PUTVAR ;NO, GO STORE VALUE + PUSHZ BX ;YES, PUSH ONTO STACK + RET ;AND RETURN +PUTVAL ENDP + + ;PREDICATE HANDLERS TRUE & FALSE + ;DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FCNS + PUBLIC PFALSE,PTRUE +PFALSE PROC + SUB BX,BX ;PREDICATE WAS FALSE, CLEAR FLAG + JMP PPRED +PFALSE ENDP + +PTRUE PROC + MOV BX,1 ;PREDICATE WAS TRUE, SET FLAG + JMP PPRED +PTRUE ENDP + + PUBLIC PPRED +PPRED PROC + CALL NXTBYT ;GET FIRST (OR ONLY) PREDICATE JUMP BYTE + TEST AX,80H ;NORMAL POLARITY PREDICATE? + JE PPR1$ ;NO, LEAVE FLAG ALONE + INC BX ;YES, INCREMENT FLAG +PPR1$: TEST AX,40H ;ONE-BYTE JUMP OFFSET? + JE PPR2$ ;NO + AND AX,0FF3FH ;YES, CLEAR SPECIAL BITS + JMP PPR3$ +PPR2$: AND AX,0FF3FH ;CLR SPECIAL BITS FROM HIGH-ORDER OFFSET BYTE + MOV CX,AX ;HIGH-ORDER BYTE + CALL NXTBYT ;GET LOW-ORDER BYTE + MOV AH,CL ;MOVE IN HIGH-ORDER BITS + TEST AX,2000H ;IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)? + JE PPR3$ ;NO + OR AX,0C000H ;YES, MAKE 16-BIT NUMBER NEGATIVE +PPR3$: DEC BX ;TEST FLAG + JE PPR6$ ;WAS 1, THAT MEANS DO NOTHING + CMP AX,0 ;ZERO JUMP? + JNE PPR4$ ;NO + JMP OPRFAL ;YES, THAT MEANS DO AN RFALSE +PPR4$: DEC AX ;ONE JUMP? + JNE PPR5$ ;NO + JMP OPRTRU ;YES, THAT MEANS DO AN RTRUE +PPR5$: DEC AX ;ADJUST OFFSET + ADD ZPC2,AX ;ADD TO PC + JMP NEWZPC ;AND UPDATE ZPC STUFF +PPR6$: RET +PPRED ENDP + + ;SPLIT BYTE-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE OFFSET IN BX + PUBLIC BSPLTB +BSPLTB PROC + MOV BX,AX + XCHG AL,AH ;EXTRACT BLOCK BITS + SHR AX,1 + AND AX,7FH ;CLEAR UNWANTED BITS + AND BX,1FFH ;CLEAR ALL BUT BYTE OFFSET BITS + RET +BSPLTB ENDP + + ;SPLIT WORD-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE-OFFSET IN BX + PUBLIC BSPLIT +BSPLIT PROC + MOV BX,AX + MOV AL,AH ;EXTRACT BLOCK BITS + SUB AH,AH ;CLEAR UNWANTED BITS + SUB BH,BH ;CLEAR ALL BUT WORD OFFSET BITS + SHL BX,1 ;CONVERT TO BYTE OFFSET + RET +BSPLIT ENDP + + SUBTTL OBJECT HACKERS + PAGE + + + PUBLIC OBJLOC,NXTPRP + ;GIVEN OBJ NUMBER IN AX, RETURN OBJ LOCATION IN AX +OBJLOC PROC + SUB AH,AH ;CLEAR UNWANTED BITS + PUSH BX ;MULTIPLY BY 9 THE LAZY WAY + MOV BX,AX + SHL AX,1 + SHL AX,1 + SHL AX,1 + ADD AX,BX + POP BX ;RESTORE + ADD AX,OBJTAB ;INDEX INTO OBJECT TABLE + ADD AX,53 ;SKIPPING DEFAULT PROPERTY TABLE + RET +OBJLOC ENDP + + ;GIVEN POINTER TO A PROPERTY IN BX!, UPDATE IT TO POINT TO NEXT PROP +NXTPRP PROC + PUSH AX ;SAVE + PUSH CX ;SAVE + MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPSIZE;EXTRACT PROPERTY LENGTH (MINUS 1) + MOV CL,PROPSIZE + SHR AL,CL + SUB AH,AH + ADD BX,AX ;ADD IT TO OLD POINTER + ADD BX,2 ;ADJUST FOR EXTRA LENGTH BYTE PLUS IDENTIFIER + POP CX ;RESTORE + POP AX ;RESTORE + RET +NXTPRP ENDP + + SUBTTL STRING FUNCTIONS + PAGE + + + ;OUTPUT A ZSTR, BLOCK-POINTER IN AX, BYTE-POINTER IN BX + ;RETURN UPDATED POINTER + PUBLIC PUTSTR +PUTSTR PROC + PUSH SI ;SAVE + PUSH CX ;SAVE + PUSH DX ;SAVE + PUSH DI ;SAVE + PUSH BP ;SAVE + SUB DX,DX ;TEMP CS STARTS AT 0 + SUB DI,DI ;PERM CS STARTS AT 0 +PTS1$: CALL GETWRD ;GET NEXT STRING WORD + MOV SI,CX + PUSH AX ;SAVE POINTER & COPY OF STRING WORD + PUSH BX + PUSH SI + MOV CX,3 ;3 BYTES IN WORD +PTS2$: PUSH SI ;SAVE CURRENT BYTE (IN LOW-ORDER POSITION) + MOV BP,CX ;SHIFT TO NEXT BYTE + MOV CL,5 + SAR SI,CL + MOV CX,BP + LOOP PTS2$ ;LOOP UNTIL DONE + MOV CX,3 ;RETRIEVE THE 3 BYTES +PTS3$: POP SI ;GET NEXT BYTE + AND SI,1FH ;CLEAR UNWANTED BITS + CMP DX,0 ;IN WORD MODE? + JGE PTS4$ ;NO {WAS BPL, CHECK} + SAL SI,1 ;YES, CALCULATE WORD OFFSET + ADD SI,WRDTAB ;POINT INTO WORD TABLE + ADD SI,WRDOFF ;USING PROPER 32-WORD BLOCK + GTAWRD A,[SI] ;POINT TO WORD STRING + CALL BSPLIT ;SPLIT IT + CALL PUTSTR ;AND PRINT IT + JMP PTS15$ ;CONT. WHERE WE LEFT OFF WITH TEMP CS RESET +PTS4$: CMP DX,3 ;CS 3 SELECTED (ASCII MODE)? + JL PTS6$ ;NO, NORMAL CS + JNE PTS5$ ;NO, BUT WE ARE IN ASCII MODE + XCHG DL,DH ;SHIFT SOME BITS HIGH TO MAKE NUMBER LARGE + OR DX,SI ;SAVE HIGH-ORDER ASCII BITS HERE + JMP PTS16$ ;GO GET NEXT BYTE +PTS5$: AND DX,3 ;EXTRACT PREVIOUSLY SAVED HIGH-ORDER BITS + MOV BP,CX ;POSITION THEM + MOV CL,5 + SAL DX,CL + MOV CX,BP + OR DX,SI ;OR IN LOW-ORDER BITS + MOV AX,DX + JMP PTS14$ ;GO PRINT THE CHARACTER +PTS6$: CMP SI,6 ;SPECIAL CODE? + JL PTS9$ ;YES, SPACE, WORD, OR SHIFT + CMP DX,2 ;MIGHT ALSO BE SPECIAL IF IN CS 2 + JNE PTS8$ ;BUT WE'RE NOT + CMP SI,7 ;CRLF? + JE PTS7$ ;YES + JG PTS8$ ;NO, NOT ASCII MODE, EITHER? + INC DX ;YES IT IS, SWITCH TO ASCII MODE + JMP PTS16$ ;AND GO GET NEXT BYTE +PTS7$: CALL NEWLIN ;CRLF REQUESTED, DO A NEWLINE + JMP PTS15$ +PTS8$: MOV AX,DX ;NORMAL CHARACTER, GET CS + MOV BP,26 ;CALCULATE OFFSET FOR THIS CS + MUL BP + ADD AX,SI ;ADD IN CHARACTER OFFSET (+6) + SUB AX,6 ;CHARACTER OFFSET + MOV BX,OFFSET ZCHRS ;GET THE CHARACTER FROM CONVERSION VECTOR + XLAT ZCHRS + JMP PTS14$ ;GO PRINT IT +PTS9$: CMP SI,0 ;IS IT A SPACE? + JNE PTS10$ ;NO + MOV AX," " ;YES, GO PRINT A SPACE + JMP PTS14$ +PTS10$: CMP SI,3 ;IS IT A WORD? + JG PTS11$ ;NO, MUST BE A SHIFT + OR DX,8000H ;SWITCH TO WORD MODE FOR NEXT BYTE + DEC SI ;CALCULATE WORD-TABLE BLOCK OFFSET + MOV BP,CX ;64 BYTES IN A BLOCK + MOV CL,6 + SHL SI,CL + MOV CX,BP + MOV WRDOFF,SI ;SAVE IT AND LOOP + JMP PTS16$ +PTS11$: SUB SI,3 ;CALCULATE NEW CS + CMP DX,0 ;TEMPORARY SHIFT (FROM CS 0)? + JNE PTS12$ ;NO + MOV DX,SI ;YES, JUST SAVE NEW TEMP CS + JMP PTS16$ +PTS12$: CMP SI,DX ;IS THIS THE CURRENT CS? + JE PTS13$ ;YES, DO A PERM SHIFT TO IT + SUB DX,DX ;OTHERWISE, PERM SHIFT TO CS 0 +PTS13$: MOV DI,DX ;TEMP & PERM CS'S ARE SAME NOW + JMP PTS16$ +PTS3A$: JMP PTS3$ ;DUMMY FOR NON-SHORT LOOP +PTS14$: CALL PUTCHR ;PRINT THE CHARACTER +PTS15$: MOV DX,DI ;RESET TEMP CS TO PERM CS +PTS16$: LOOP PTS3A$ ;NEXT BYTE + POP SI ;RESTORE POINTERS & ORIGINAL STRING WORD + POP BX + POP AX + CMP SI,0 ;END-OF-STRING? + JL PTS1A$ ;YES, CLEAN UP & RETURN UPDATED POINTER + JMP PTS1$ ;NO, GET NEXT WORD +PTS1A$: POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET +PUTSTR ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN THE CHARACTER SET # IN AX + PUBLIC CHRCS +CHRCS PROC + CMP AX,0 ;IS THIS A NULL? + JNE CCS1$ ;NO + MOV AX,3 ;YES, RETURN DUMMY CS NUMBER + RET +CCS1$: PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CONVERSION VECTOR +CCS2$: INC BX ;FOUND THE CHARACTER? + CMP AL,[BX-1] + JE CCS3$ ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CCS2$ ;NO, CONTINUE LOOP + MOV AX,2 ;YES, CALL IT CS 2 + JMP CCS5$ +CCS3$: SUB BX,OFFSET ZCHRS ;FIND CHARACTER POSITION + SUB AX,AX ;START WITH CS 0 +CCS4$: SUB BX,26 ;EVERY 26 CHARACTERS IS A NEW CS + JLE CCS5$ ;DONE + INC AX ;INCREMENT CS # & CONTINUE LOOP + JMP CCS4$ +CCS5$: POP BX + RET +CHRCS ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN ZSTR BYTE VALUE IN AX + PUBLIC CHRBYT +CHRBYT PROC + PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CHARACTER CONVERSION TABLE +CHB1$: INC BX ;FOUND THE CHARACTER? + CMP AL,[BX-1] + JE CHB2$ ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CHB1$ ;NO, CONTINUE LOOP + SUB AX,AX ;YES, RETURN ZERO FOR FAILURE + JMP CHB4$ +CHB2$: SUB BX,OFFSET ZCHRS-5 ;ADJUST POINTER SO FIRST CHARACTER IS 6 + MOV AX,BX +CHB3$: CMP AX,32 ;SUBTRACT MULTIPLES OF 26 UNTIL BASE CODE + JL CHB4$ + SUB AX,26 + JMP CHB3$ +CHB4$: POP BX ;RESTORE + RET +CHRBYT ENDP + + ;CONVERT UP TO 6 ASCIZ CHARS POINTED TO BY DS:AX + ;TO A 2-WORD ZSTR RETURNED IN AX & BX + PUBLIC ZWORD +ZWORD PROC + PUSH SI ;SAVES + PUSH CX + PUSH DX + PUSH DI + PUSH BP + MOV SI,AX ;CHARACTER STRING POINTER + SUB DI,DI ;CS STARTS AT 0 + MOV CX,6 ;MAKE 6 ZSTR BYTES +ZWD1$: INC SI ;GET NEXT CHARACTER + MOV BL,[SI-1] + CMP BL,0 + JNE ZWD3$ ;NOT END-OF-STRING + MOV AX,OFFSET PADCHR;AT END-OF-STRING, PAD WITH PAD CHARACTER +ZWD2$: PUSH AX ;SAVE A PAD BYTE + LOOP ZWD2$ ;LOOP UNTIL DONE + JMP ZWD6$ ;THEN GO FORM ZWORD +ZWD3$: MOV AX,BX + CALL CHRCS ;FIND THE CS NUMBER FOR THIS CHAR + CMP AX,0 ;CS 0? + JE ZWD4$ ;YES + ADD AX,3 ;NO, CALCULATE TEMP SHIFT BYTE + PUSH AX ;SAVE THE SHIFT BYTE + DEC CX ;REDUCE BYTE COUNT + JE ZWD6$ ;DONE +ZWD4$: MOV AX,BX ;FIND THE PROPER BYTE VALUE FOR THIS CHAR + CALL CHRBYT + CMP AX,0 ;IN NORMAL CS'S? + JNE ZWD5$ ;YES + MOV AX,6 ;NO, USE ASCII SHIFT + PUSH AX + DEC CX ;DONE YET? + JE ZWD6$ ;YES + MOV AX,BX ;NO, SAVE HIGH-ORDER ASCII BITS + MOV BP,CX + MOV CL,5 + SAR AX,CL + MOV CX,BP + PUSH AX + DEC CX ;DONE YET? + JE ZWD6$ ;YES + AND BX,1FH ;NO, SAVE LOW-ORDER ASCII BITS + MOV AX,BX +ZWD5$: PUSH AX ;SAVE THIS BYTE + LOOP ZWD1$ ;LOOP UNTIL ZWORD FULL +ZWD6$: MOV BP,SP ;BUILD ZWORD WORDS FROM 6 SAVED BYTES + MOV AX,[BP+10] + MOV CL,5 + SHL AX,CL + OR AX,[BP+8] + SHL AX,CL + OR AX,[BP+6] + MOV BX,[BP+4] + SHL BX,CL + OR BX,[BP+2] + SHL BX,CL + OR BX,[BP] + OR BX,8000H ;SET END-OF-STRING BIT IN SECOND WORD + ADD SP,12 ;FLUSH STACK + POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET +ZWORD ENDP + + SUBTTL TERMINAL I/O + PAGE + + + ;QUEUE CHARACTER IN AX FOR OUTPUT + PUBLIC PUTCHR +PUTCHR PROC + PUSH BP + MOV BP,CHRPTR + CMP BP,ENDBUF + JNE PTC7 + PUSH AX + PUSH BX + PUSH SI + MOV BX,ENDBUF + MOV SI,OFFSET OUTBUF +PTC1: DEC BX + CMP BYTE PTR [BX]," " + JE PTC3 + CMP BX,SI + JNE PTC1 +PTC2: PRINT OUTBUF + MOV CHRPTR,SI + MOV BP,SP + CMP BYTE PTR 4 [BP]," " + JNE PTC6 + MOV WORD PTR 4 [BP],0 + JMP PTC6 +PTC3: CMP BX,SI + JE PTC2 + MOV BYTE PTR [BX],0 + PRINT OUTBUF + MOV AX,ENDBUF + INC BX +PTC4: CMP BX,AX + JE PTC5 + MOV BP,AX + MOV AL,[BX] + MOV [SI],AL + MOV AX,BP + INC BX + INC SI + JMP PTC4 +PTC5: MOV CHRPTR,SI +PTC6: POP SI + POP BX + POP AX + CMP AX,0 + JE PTC8 +PTC7: MOV BP,CHRPTR + MOV [BP],AL ; (6) REMOVED DS OVERRIDE + INC CHRPTR +PTC8: POP BP + RET +PUTCHR ENDP + + ;GO TO NEW LINE, OUTPUTTING CURRENT BUFFER +NEWLIN PROC + PUSH BX ;SAVE + MOV BX,CHRPTR ;END LINE AT CURRENT POINT + MOV BYTE PTR [BX],0 + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP BX ;RESTORE + PRINT OUTBUF ;AND OUTPUT LINE + RET +NEWLIN ENDP + + SUBTTL TOP LEVEL STUFF + PAGE + + + ; READ THE SETUP FILE +; SSETUP HAS UNDER GONE TO SETS OF REVISIONS. REVISION 6 IS RESPONSIBLE +; FOR ALL OF THE DOS 2.0 FILE HANDLING PATCHES. REVISION 7 IS RESPONSIBLE +; FOR SETTING UP COLOR OR MONOCHROME BASED ON THE VIDEO SETTINGS AND WHAT +; WAS SPECIFIED ON THE COMMAND LINE. +; + PUBLIC SSETUP +SSETUP PROC NEAR + MOV DX,OFFSET SSFILE ; (6) USE ASCIZ FILENAME + MOV AH,CFOPENZ ; TRY OPENING THE SETUP FILE + MOV AL,0 ; (6) OPEN FILE FOR READING + INT 21H + JC SSET1 ; IF OPEN FAIL, COMPLAIN + MOV BX,AX ; (6) PUT HANDLE IN BX + MOV AH,CRDRNDZ ; (6) READ INTO THE BUFFER + MOV DX,OFFSET SSBUF ; (6) BUFFER TO READ INTO + MOV CX,SSLNT ; (6) READ (CX) BYTES + INT 21H + CMP AL,SSLNT ; (6) DID WE GET ALL THE BYTES + JNE SSET2 ; IF READ FAIL, COMPLAIN + PUSH BX ; (6) SAVE THE HANDLE + MOV BX,DX ; (6) GET OFFSET TO BUFFER + MOV AL,[BX] + SUB AL,SSVER + DEC AL ; FOR A 25 LINE SCREEN, SLPP HAS 24 IN IT + MOV SLPP,AL + MOV AL,[BX+1] + SUB AL,SSHOR + MOV SCPL,AL + MOV SLFLG,1 ; SET IT TO ANSI + MOV AL,[BX+2] + CMP AL,"N" ; IS IT ASCII + JNE SSET4 ; NO, THEN LEAVE IT ALONE + MOV SLFLG,0 ; YES, THEN SET IT TO ASCII + MOV SCROLL,1 ; (7) NO SCROLLING IF NO ANSI.SYS + JMP SSET6 +SSET4: TEST SCROLL,1 ; (7) SHOULD WE CONSIDER COLOR + JNZ SSET6 ; (7u) I GUESS NOT + MOV AH,15 ; (7) CHECK VIDEO STATE + INT 10H ; (7) TO SEE IF IN A COLOR MOOD + CMP AL,1 ; (7) THIS IS 40x25 COLOR + JNZ SSET5 +SSET4A: TEST CMDLIN,1 ; (7) WAS THIS SET ON CMD LINE + JNZ SSET6 ; (7) YES, CANNOT OVERRIDE + CMP SCROLL,1 ; (7u) NO COLOR WITHOUT SCROLL CAPABILITY + JZ SSET6 ; + MOV COLFLG,1 ; (7) SET COLOR FLAG + MOV SCRATR,COLATR ; (7) SET VIDEO ATTRIBUTE + JMP SSET6 +SSET5: CMP AL,3 ; (7) THIS IS 80x25 COLOR + JZ SSET4A + TEST CMDLIN,2 ; (7) DID THEY SET COLOR FROM CMD LINE + JNZ SSET4A ; (7) TURN IT ON +SSET6: POP BX ; (6) RESTORE THE HANDLE + MOV AH,CFCLOSZ ; (6) CLOSE THE SETUP FILE + INT 21H + JC SSET3 ; (6) IF CANNOT CLOSE FILE, COMPLAIN + RET +SSET1: DEC SLPP ; (N1) SET TO 24 TO WORK RIGHT ANYWAY! + PRINT SSMSG1 + RET +SSET2: PRINT SSMSG2 + RET +SSET3: PRINT SSMSG3 + RET +SSETUP ENDP + + ;INITIALIZATION + PUBLIC TSET4 +TSETUP PROC + MOV BX,OFFSET SELINE1 + TEST COLFLG,1 ; (7) ARE WE USING COLOR + JZ TSET0 ; (7) NOPE, ... + MOV BX,OFFSET CELINE1 ; (7) FIX COLOR IF NECESSARY +TSET0: MOV AL,SLPP ; NUMBER OF LINES + SUB AH,AH ; ASCIIFY THIS NUMBER INTO AX + INC AX ; FOR SLPP = 24, THE CURSOR IS AT 25 + DIV RADIX ; SO THAT WE CAN PUT THE CURSOR + ADD AH,"0" ; THERE WHEN WE FINISH THE STATUS + ADD AL,"0" ; LINE OUTPUT IN MSOUT + MOV [BX],AX ; DO THE PATCH + MOV BX,OFFSET CLS1 ; (7t) PATCH CLEAR SCREEN + MOV [BX],AX ; (7t) SO THAT IT RESTORE CURPOS + MOV BX,OFFSET CLS1C ; (7t) PATCH IT IN COLOR TOO + MOV [BX],AX + MOV BX,OFFSET OUTBUF ; NO DETERMINE END OF OUTPUT BUFFER + + MOV CL,SCPL + SUB CH,CH + ADD BX,CX + DEC BX ; (7v) SHORTEN BY ONE TO AVOID HARD + MOV ENDBUF,BX ; WRAP + MOV BYTE PTR [BX],0 + MOV BX,OFFSET SLSTAB ; NOW, CHOSE A STATUS LINE + CMP TIMEMD,0 ; CHECK FOR TIME MODE + JE TSET1 ; NOPE, USE OTHER STATUS LINE + ADD BX,8 ; YES, GET OFFSET TO TIME STAT LINES +TSET1: CMP CX,55 ; CX HAS WIDTH OF SCREEN IN COLUMNS + JL TSET2 + MOV AX,60 ; MAKE AN INDEX INTO ROOM DESC + SUB CX,80 ; SCALE WITHIN 80 - WIDTH + MOV SI,4 ; SKIP SCORE PTR'S IN TABLE + JMP TSET3 ; FIX VALUES IN THE TABLE WITH CX +TSET2: MOV AX,15 ; MAKE AN INDEX INTO ROOM DESC BUFFER + SUB CX,40 ; SCALE WITHIN 40 - WIDTH + SUB SI,SI ; SI INDEXES INTO SCORE v. TIME +TSET3: SUB AX,CX ; BACKUP THE PTR IN BUFFER + ADD AX,[BX][SI] ; GET OFFSET TO BUFFER BEGINNING + MOV BX,2[BX][SI] ; GET OFFSET TO TABLE BEGINNING + TEST CX,CX ; SEE IF CX IS LESS THAN ZERO + JG TSET4 ; SKIP FIRST PATCH IF POSITIVE + ADD 6[BX],CX ; THESE PATCHES ADJUST THE RANGES FOR + ;+EACH OF THE STATUS LINE FIELD ACCORDING + ;+TO THE CALCULATED LENGTH OF THE STATUS + ;+LINE +TSET4: ADD 12[BX],CX ; PATCH CX INTO THESE TABLE OFFSETS + ADD 14[BX],CX ; CX HAS DIFFERENCE BET TERM W & 80 + ADD 20[BX],CX + ADD 22[BX],CX +TSET5: MOV SLSTR,AX ; SAVE STATUS LINE BUFFER ADDR IN HERE + MOV SLTAB,BX ; AND STATUS LINE TABLE ADDR IN HERE + CALL MINIT + RET +TSETUP ENDP + + + PUBLIC ZIPBGN,STR5$,STR8$,STR9$,STR10$,STR11$,STR12$,STR12A + PUBLIC STR12B,STR13$,STR14$,STR15$,STR17$ +ZIPBGN PROC + CALL SYSINI ;DO ANY SYSTEM INITIALIZATION + CALL HERALD ;put up the herald file +STR5$: SUB AX,AX ;BLOCK 0 + SUB BX,BX ;PUT AT BEGINNING OF GAME SEGMENT + CALL GETBLK ;GET THE BLOCK + MOV GAMEIN,1 ; (7q) INDICATE RELIABILITY OF SCRIPT BIT + CMP BYTE PTR ES:[PVERS1],ZMVERS ;PROPER Z-MACHINE VERSION? + JNE STR8$ ;NO + TEST BYTE PTR ES:[PVERS2],1 ;YES,PROPER MODE BITS? + JE STR9$ ;YES +STR8$: FATAL FTL4 ;SOMETHING WRONG, DIE +STR9$: TEST BYTE PTR ES:[PVERS2],2 ;TIME MODE REQUESTED? + JE STR10$ ;NO + INC TIMEMD ;YES, SET TIME-MODE FLAG +STR10$: MOV AL,BYTE PTR ES:[PVERS2] + CMP SLFLG,0 + JNE STR11$ + OR AL,10H ;TURN ON THE NO STATUS LINE BIT + MOV BYTE PTR ES:[PVERS2],AL +STR11$: TEST SCROLL,1 ; (7) CAN WE SPLIT THE SCREEN + JNZ STR11A ; (7) GUESS NOT... + MOV AL,BYTE PTR ES:[PVERS2] + OR AL,SCRBIT ; (7) TURN ON BIT FOR SPLIT + MOV BYTE PTR ES:[PVERS2],AL ;(7) SAVE IT +STR11A: GTAWRD A,[PZRKID] ;UNIQUE GAME & VERSION INDENTIFIER + MOV ZORKID,AX + GTAWRD A,[PENDLD] ;GET ENDLOD POINTER + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR12$ + AND AX,0FE00H + ADD AX,200H +STR12$: MOV CX,AX + MOV BP,CX ;EXTRACT ENDLOD BLOCK + MOV CL,9 + SAR BP,CL + MOV CX,BP + MOV ENDLOD,CX ;SAVE ENDLOD BLOCK NUMBER + MOV AX,128 ;(6) FIGURE BOUNDRY FOR SEG1 + SUB AX,CX ;(6) SUBTRACT AMOUNT IN PRELOD + SHL AX,1 ;(6) MULTIPLY IT BY #BYTES PER + SHL AX,1 ;(6) ENTRY IN PAGTAB FOR SCALING + MOV SEGEND,AX ;(6) USED TO COMPARE TO PAGTAB TO LOCATE + ;(6) SEGMENT IN WHICH GAMEBLOCK RESIDES + DEC CX ;NUMBER OF BLOCKS LEFT TO LOAD + CMP FITS,1 ;(6) READ THE WHOLE GAME IN + JNE STR12A ;(6) NO, DON'T READ IT ALL IN + MOV CX,127 ;(6) TWO 64K READS + MOV AX,1 ;(6) STARTING WITH BLK 1 + MOV LPTAB,1 ;(6) STARTING LOCATION + CALL GTBLKS + MOV CX,127 ;(6) READ ALL BUT 1/2K + MOV LPTAB,128 ;(6) READ INTO SEG1 + MOV AX,128 ;(6) THE LAST 64K BLKS + CALL GTBLKS + JNZ STR12$$ ;(8) READ LAST BLOCK? + MOV CX,1 ;(8) READ ONE MORE BLOCK + MOV AX,255 ;(8) LAST BLOCK NUMBER + MOV LPTAB,255 ;(8) PAGE LOCATION + CALL GTBLKS ;(8) GET IT +STR12$$:MOV LPTAB,0 + JMP STR12B +STR12A: MOV AX,1 ;STARTING WITH BLOCK 1 + MOV BX,OFFSET PAGTAB ; (6) GET A BUFFER ADDRESS + ADD BX,4 ; (6) SECOND ENTRY + MOV LPTAB,BX ; (6) SAVE THIS CALCULATED ADDR + CALL GTBLKS ;GET THE BLOCKS +STR12B: GTAWRD A,[PVOCTB] ;VOCAB LOCATION + MOV VOCTAB,AX ;SAVE VOCABULARY TABLE POINTER + GTAWRD A,[POBJTB] ;GET OBJECT TABLE POINTER + MOV OBJTAB,AX + GTAWRD A,[PGLOTB] ;GET GLOBAL TABLE POINTER + MOV GLOTAB,AX + GTAWRD A,[PWRDTB] ;GET WORD TABLE POINTER + MOV WRDTAB,AX + GTAWRD A,[PPURBT] ;GET PURE CODE POINTER + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR13$ + ADD AX,200H +STR13$: MOV CL,9 ;EXTRACT BLOCK NUMBER + SAR AX,CL + AND AX,7FH ;CLEAR UNWANTED BITS + MOV PURBOT,AX ;SAVE IT + MOV BX,OFFSET RBRKS ;START OF READ BREAK CHARACTER TABLE + MOV SI,VOCTAB ;VOCAB TABLE POINTER + MOV CL,BYTE PTR ES:[SI] ;1ST BYTE IN VOCTAB IS # OF SIBREAKS + SUB CH,CH ;CLEAR HIGH BYTE + INC SI +STR14$: MOVM [BX],ES:[SI],AL ;TRANSFER THEM + INC BX + INC SI + LOOP STR14$ + MOV ESIBKS,BX ;REMEMBER END OF SI BREAKS + MOV BP,OFFSET IRBRKS;ALWAYS END WITH INITIAL BREAK CHARACTERS +STR15$: MOVM [BX],[BP],AL ;(6)TRANSFER THEM + INC BX + INC BP + CMP AL,0 + JNE STR15$ + MOV AL,ES:[SI] ;GET VOCABULARY ENTRY LENGTH + SUB AH,AH + MOV VWLEN,AX ;AND STORE IT AWAY + INC SI + GTAWRD A,[SI] ;GET NEXT WORD IN TABLE + MOV VWORDS,AX ;NUMBER OF WORD ENTRIES IN VOCABULARY + ADD SI,2 ;MOVE TO NEXT WORD + MOV VOCBEG,SI ;BEGINNING OF ACTUAL VOCABULARY + + MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + MOV CL,9 + SHL SI,CL ;THIS IS FIRST LOCATION (ES:) OF PAGING + MOV PAGES,SI ;SAVE THIS TO USE AS AN OFFSET + + CALL MTIME +STR17$: JMP START1 +ZIPBGN ENDP + + ;RESTART EXECUTION HERE + PUBLIC RESTRT,RESTRT1,START1 +RESTRT PROC + CALL GAMOPEN ; (7q) OPEN THE GAME FILE + MOV MORLIN,0 ; (7s) RESET MORE COUNT + SUB AX,AX ;REREAD ALL OF THE IMPURE STUFF + MOV CURSEG,0 ; (K5) SET SEG FLAGS BACK TO SEG0 + MOV ZPCSEG,0 + MOV LPTAB,0 ; (6) FILL THE FIRST BIT OF STUFF + PUSH PAGES ; (6) SAVE THIS VARIABLE + MOV PAGES,0 ; (6) RESET IT FOR SMALL MEMORY READ + MOV CX,PURBOT + CALL GTBLKS + POP PAGES ; RESET IT AGAIN + MOV AH,SCRFLG ; (7o) WERE WE SCRIPTING + XOR AL,AL ; (7o) ZERO THIS + MOV WORD PTR ES:[PFLAGS],AX ; (7o) RESTORE SCRIPTING STATE + TEST SCROLL,1 ; (7) CAN WE SCROLL? + JNZ RESTRT1 ; (7) NEVER COULD, SKIP RE-INITS + OR BYTE PTR ES:[PVERS2],SCRBIT ; (7) TURN ON SPLIT + MOV TOPLIN,TOPSCR ; (7) FIX SCREEN VARIABLES ON RESTART + MOV SCRNFLG,0 ; (7) WHOLE SCREEN, ONLY 1 + MOV SPLTFLG,0 ; (7) NO SPLIT SCREEN + JMP RESTRT1 ; PATCH TO FIX STATUS LINE BUG (5)/PHG +START1: + + CALL TSETUP ;SETUP TERMINAL/STATUS LINE +RESTRT1:CALL CLRSCR ;CLEAR THE REMAINDER OF SCREEN + +; MOV AL,BYTE PTR ES:[PVERS2] +; ADD AL,8 ;TANDY BIT +; MOV BYTE PTR ES:[PVERS2],AL + + MOV SP,OFFSET STK_TOP ;INITIALIZE OUR STACK POINTER + MOV DI,OFFSET ZSTK_TP ;INITIALIZE USER STACK POINTER + MOV CHRPTR,OFFSET OUTBUF ;INITIALIZE OUTPUT CHARACTER POINTER + MOV ZLOCS,DI ;LOCALS WOULD START AT FIRST SLOT, + SUB ZLOCS,2 ;IF THERE WERE ANY + GTAWRD A,[PSTART] ;GET STARTING LOCATION + CALL BSPLTB ;SPLIT BLOCK & BYTE POINTERS + MOV ZPC1,AX ;INITIALIZE ZPC BLOCK-POINTER + MOV ZPC2,BX ;INITIALIZE ZPC BYTE-POINTER + CALL NEWZPC ;GET PAGE TO EXECUTE + JMP NXTINS +RESTRT ENDP + + ;MAIN INSTRUCTION INTERPRETATION LOOP + PUBLIC NXTINS,NXI0A$,NXI0B$,NXI0C$,NXI1$,NXI2$,NXI3$,NXI4$,NXI5$ + PUBLIC NXI6$,NXI7$,NXI8$,NXI8A$,NXI9$,NXI10$,NXI11$,NXI12$,NXI14$,NXI15$ +NXTINS PROC + CALL NXTBYT ;GET THE OPERATION BYTE + MOV DX,AX ;SAVE A COPY + CMP AX,80H ;IS IT A 2OP? + JL NXI9$ ;YES + CMP AX,0B0H ;NO, IS IT A 1OP? + JGE NXI0A$ ;NO + JMP NXI12$ ;YES +NXI0A$: CMP AX,0C0H ;IS IT A 0OP? + JG NXI0B$ ;NO + JMP NXI13$ ;YES +NXI0B$: AND AX,3FH ;IT'S EXTENDED, GET THE OPCODE + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET THE OPERATOR POINTER + MOV SI,[BP+EXTOP] ; (6) REMOVED DS OVERRIDE + CMP SI,0 + JNE NXI0C$ ;OPERATION EXISTS + JMP NXI14$ ;NO SUCH OPERATION +NXI0C$: CALL NXTBYT ;GET THE ARGUMENT BYTE + MOV CX,4 ;SPLIT IT INTO 4 2-BIT MODE BYTES +NXI1$: PUSH AX + SAR AX,1 + SAR AX,1 + LOOP NXI1$ + MOV CX,4 ;RETRIEVE THE 4 BYTES IN PROPER ORDER + SUB DX,DX + MOV BX,OFFSET ARGBLK;FIRST ARGUMENT SLOT +NXI2$: POP AX ;GET NEXT MODE BYTE? + AND AX,3 ;CLEAR OFF UNWANTED BITS + CMP AX,3 ;NO MORE ARGUMENTS? + JE NXI4$ ;YES, FLUSH ANY OTHER MODE BYTES + CALL GETARG ;ELSE, GET THE NEXT ARGUMENT + MOV [BX],AX ;SAVE IT IN ARGUMENT BLOCK + ADD BX,2 + INC DX ;REMEMBER NUMBER OF ARGS GOTTEN +NXI3$: LOOP NXI2$ ;LOOP FOR REST OF MODE BYTES + JMP NXI5$ +NXI4$: DEC CX ;DETERMINE NUMBER OF REMAINING MODE BYTES + SHL CX,1 ;WORD COUNT + ADD SP,CX ;FLUSH THEM +NXI5$: XCHG CX,DX + MOV AX,CX ;NUMBER OF ARGS GOES HERE FOR OPERATOR TO USE + CMP BYTE PTR [SI],90H ;(6)DOES OPERATOR WANT ARGBLK POINTER? + JE NXI8A$ ;YES, CALL OPERATOR NOW + DEC CX ;NO, IT WANTS ARGS IN REGISTERS + JL NXI8A$ ;NO ARGS, JUST CALL OPERATOR + JE NXI8$ ;1 ARG, GET IT + SUB CX,2 + JL NXI7$ ;2 ARGS + JE NXI6$ ;3 ARGS + MOV DX,ARGBLK[6] ;ELSE, 4 ARGS, GET 4TH +NXI6$: MOV CX,ARGBLK[4] ;GET 3RD +NXI7$: MOV BX,ARGBLK[2] ;GET 2ND +NXI8$: MOV AX,ARGBLK ;GET FIRST ARG +NXI8A$: JMP NXI15$ ;AND CALL OPERATOR +NXI9$: AND AX,1FH ;2OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;FIND POINTER TO OPERATOR ROUTINE + MOV SI,[BP+EXTOP] ;(6) REMOVED DS OVERRIDE + CMP SI,0 + JE NXI14$ ;NO SUCH OPERATION + MOV AX,1 ;ASSUME FIRST ARG IS AN IMMEDIATE + TEST DX,40H ;IS IT INSTEAD A VARIABLE? + JE NXI10$ ;NO + INC AX ;YES, CHANGE MODE +NXI10$: CALL GETARG ;GET THE FIRST ARG + PUSH AX ;SAVE IT + MOV AX,1 ;ASSUME SECOND ARG IS AN IMMEDIATE + TEST DX,20H ;IS IT INSTEAD A VARIABLE? + JE NXI11$ ;NO + INC AX ;YES, CHANGE MODE +NXI11$: CALL GETARG ;GET THE SECOND ARG + MOV BX,AX ;POSITION IT + POP AX ;RECOVER FIRST ARG + CMP BYTE PTR [SI],90H ;(6)DOES ROUTINE WANT ARGUMENT BLOCK? + JNE NXI15$ ;NO, GO CALL IT + MOV ARGBLK,AX ;YES, MOVE ARGS TO ARGBLK + MOV ARGBLK[2],BX + MOV AX,2 ;ALWAYS 2 ARGS + JMP NXI15$ ;NOW CALL OPERATOR +NXI12$: AND DX,0FH ;1OP, EXTRACT OPERATION BITS + SHL DX,1 ;MAKE IT A WORD OFFSET + MOV BP,DX ;GET OPERATOR ROUTINE POINTER + MOV SI,[BP+ONEOP] ;(6) REMOVED DS OVERRIDE + CMP SI,0 + JE NXI14$ ;ILLEGAL OPERATION + SAR AX,1 ;EXTRACT MODE BITS + SAR AX,1 + SAR AX,1 + SAR AX,1 + AND AX,3 + CALL GETARG ;GET THE ARGUMENT + JMP NXI15$ ;AND CALL OPERATOR +NXI13$: AND AX,0FH ;0OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET OPERATOR ROUTINE POINTER + MOV SI,[BP+ZEROOP] ; (6) REMOVED DS OVERRIDE + CMP SI,0 + JNE NXI15$ ;IT'S A LEGAL OPERATION +NXI14$: FATAL FTL5 ;OTHERWISE, COMPLAIN +NXI15$: CALL SI ;CALL THE OPERATOR ROUTINE + JMP NXTINS ;AND LOOP FOR NEXT INSTRUCTION +NXTINS ENDP + + SUBTTL PAGING ROUTINES + PAGE + + + ;NORMALIZE ZPC & GET PROPER PAGE +; NEWZPC HAS BE EXTENDED TO UPDATE THE ZPCSEG VARIABLE. IT SETS THIS +; VARIABLE DIFFERENTLY ACCORDING TO PAGING SCHEME. IF THE GAME FITS IN +; MEMORY, ZPCSEG IS SET ACCORDING TO THE 17TH BIT OF THE ZPC, OTHERWISE +; IT IS SET WHEN CURSEG IS SET BY THE GETPAG ROUTINE INDICATING THAT +; THE CURRENT BLOCK IN THE SECOND ES SEGMENT. +; + PUBLIC NEWZPC,NWZ1$,NWZ2$,NWZ3$,NWZ4$,NWZ5$ +NEWZPC PROC + PUSH SI ;SAVES + PUSH BP + PUSH BX + PUSH CX + PUSH DX + SUB AX,AX ;USE DOUBLE-WORD ARITHMETIC + MOV BX,ZPC1 ;GET BLOCK-POINTER + MOV BH,BL ;POSITION IT + SUB BL,BL + SHL BX,1 + ADC AX,0 + MOV SI,ZPC2 ;GET BYTE-OFFSET + XCHG SI,AX ;DOUBLE-WORDIFY IT (MIGHT BE NEGATIVE) + CWD + XCHG SI,AX + ADD BX,SI ;ADD IT TO OTHER DOUBLE WORD + ADC AX,DX + MOV DX,BX + AND DX,1FFH ;EXTRACT BYTE-OFFSET + MOV ZPC2,DX ;SAVE IT + MOV CL,9 ;EXTRACT BLOCK-POINTER + SAR BX,CL + AND BX,7FH + TEST AX,1 ;TEST 17TH BIT + JE NWZ1A$ ;WAS 0 + OR BX,80H ;WAS 1, SET PROPER BIT IN BLOCK-POINTER + TEST FITS,1 ;(6) DO WE HAVE ALL OF THE GAME IN MEMORY + JZ NWZ1$ ; (6) BECAUSE PAGES ARE NOT CONTINUOUS + MOV ZPCSEG,1 ; WERE IN THE UPPER GAME SEG + JMP NWZ1$ +NWZ1A$: TEST FITS,1 ;(6) SHOULD WE SET THIS HERE + JZ NWZ1$ ;(6) NO + MOV ZPCSEG,0 ;(6) SET SEGMENT TO BASE SEG +NWZ1$: MOV ZPC1,BX ;SAVE IT + TEST ZPCFLG,1 ;(7n) DO WE HAVE THE RIGHT BLOCK + JNZ NWZ1Q$ ;(7n) NO, SKIP THIS SKIP + CMP BX,CURBLK ;HAS IT CHANGED? + JE NWZ5$ ;NO +NWZ1Q$: MOV CURBLK,BX ;YES, REMEMBER NEW BLOCK + MOV AX,CURTAB ;IS OLD PAGE IN PAGING SPACE? + CMP AX,0 + JE NWZ2$ ;NO + MOV BP,AX ;YES, STORE CURRENT REF TIME FOR OLD PAGE + MOVM [BP],RTIME1,CL ;(6) REMOVED DS OVERRIDE + MOVM [BP+1],RTIME2,CX ;(6) REMOVED DS OVERRIDE + INC AX +NWZ2$: CMP FITS,1 ;(6) IS THE WHOLE GAME THERE + JZ NWZ3$ ;(6) YES, GO DO WHATEVER + CMP BX,ENDLOD ;NEW PAGE ALREADY IN CORE? + JL NWZ3$ ;YES + MOV AX,BX ;NO, GET NEW PAGE + CALL GETPAG + MOV BL,CURSEG ;(6) SET ZPCSEG TO SAME AS CURSEG + MOV ZPCSEG,BL ;(6) SO THAT NXTBYT WORKS + MOV BX,AX + MOV AX,LPTAB ;GET NEW PAGE TABLE POINTER + INC AX ;POINT TO REF SLOT + MOV CURTAB,AX ;SAVE THIS POINTER FOR LATER + MOV BP,AX ;STORE HIGHEST RTIME TO KEEP PAGE FOR US + MOV BYTE PTR [BP],-1 ;(6) REMOVED DS OVERRIDE + MOV WORD PTR [BP+1],-1 ;(6) REMOVED DS OVERRIDE + INC AX + JMP NWZ4$ +NWZ3$: MOV CL,9 ;CALCULATE PAGE ADDRESS + SHL BX,CL + TEST FITS,1 + JNZ NWZ3A$ ; (7z) SKIP DURING WHOLE MEMORY EDITION + MOV ZPCSEG,0 ; (7z) RESET THIS TO SEG0 +NWZ3A$: MOV CURTAB,0 ;CLEARING POINTER MEANS PAGE IS PRELOADED +NWZ4$: MOV CURPAG,BX ;UPDATE PAGE POINTER +NWZ5$: MOV ZPCFLG,0 ; (K3) RESET THIS FLAG + POP DX ;RESTORES + POP CX + POP BX + POP BP + POP SI + RET ;AND RETURN +NEWZPC ENDP + + ;GET THE PAGE WHOSE NUMBER IS IN AX, RETURN A POINTER TO IT IN AX +; GETPAG AND FINDPG WERE MODIFIED TO ACCOMMODATE THE EXTENDED PAGING +; SCHEMES. SEGEND, CURSEG AND PAGTAB ARE SIGNIFICANT VARIABLES IN THESE +; MODIFICATIONS. SEGEND IS USED TO COMPARE TO THE CURRENT LOCATION IN +; PAGTAB WHICH IN TURN INDICATES IN WHICH SEGMENT THE NEW BLOCK IS LOCATED. +; CURSEG IS SET TO TELL THE OUTSIDE WORLD WHICH SEGMENT THE LAST GETPAG +; TOUCHED. NOTE THAT BEING IN THE SECOND SEGMENT (SEG1) REQUIRES THAT +; ADDRESS CALCULATIONS DO NOT ADD IN PAGES (THE VARIABLE MARKING THE END +; OF PRELOAD). THIS REQUIREMENT IS NECESSARY BECAUSE THERE IS NO PRELOAD +; IN THE SECOND SEGMENT. +; + PUBLIC GETPAG,GTP1$,GTP2$,GTP2A$,GTP2B,GTP2C,GTP3$,GTP4$ +GETPAG PROC + CMP AX,LPAGE ;IS THIS THE SAME PAGE AS LAST REFERENCED? + JNE GTP1$ ;NO + MOV AX,LPLOC ;YES, WE ALREADY HAVE LOCATION + RET ;RETURN IT +GTP1$: MOV LPAGE,AX ;SAVE NEW PAGE NUMBER + PUSH CX ;SAVES + PUSH BX + ADD RTIME2,1 ;UPDATE REFERENCE TIME (COUNT) + ADC RTIME1,0 + MOV BX,OFFSET PAGTAB;PAGE INFORMATION TABLE +GTP2$: INC BX + CMP AL,[BX-1] ;SEARCH FOR DESIRED BLOCK + JNE GTP3$ ;NOT IT + CMP AX,CURBLK ;IS THIS THE CURRENT CODE PAGE? + JE GTP2A$ ;DON'T UPDATE REFERENCE TIME + MOVM [BX],RTIME1,CL ;FOUND IT, UPDATE ITS REFERENCE TIME + MOVM [BX+1],RTIME2,CX +GTP2A$: DEC BX ;BACKUP TO BEGINNING OF TABLE ENTRY + PUSH BX ; (6) SAVE THIS BEFORE SCALING IT + SUB BX,OFFSET PAGTAB;(6) BASIFY THE PAGTABLE ENTRY + CMP BX,SEGEND ;(6) CHECK IF PAGE IS IN 2ND SEGMENT + POP BX ; (6) RESTORE BX + JL GTP2B ;(6) NO, FUNCTION AS USUAL + MOV CURSEG,1 ;(6) YES, SET SEGMENT NUMBER FLAG + JMP GTP2C ;(6) SKIP SETTING TO ZERO +GTP2B: MOV CURSEG,0 ;(6) SET SEGMENT NUMBER TO 0 +GTP2C: MOV LPTAB,BX ;SAVE IT + SUB BX,OFFSET PAGTAB;CALCULATE ADDRESS OF PAGE + TEST CURSEG,1 ;(6) DO A DIFFERENT CALC FOR SEG1 + JZ GTP2D ; + SUB BX,SEGEND ; (6) FIGURE OFFSET INTO SEG1 +GTP2D: MOV CL,7 + SHL BX,CL + TEST CURSEG,1 ; (6) SKIP ADDING IN PAGES IF SEG1 + JNZ GTP4$ + ADD BX,PAGES + JMP GTP4$ ;AND RETURN PAGE POINTER +GTP3$: ADD BX,3 ;SKIP REFERENCE TIME + CMP WORD PTR [BX],-1;END OF TABLE? + JNE GTP2$ ;NO, CONTINUE SEARCH + CALL FINDPG ;YES, FIND A PAGE TO LOAD INTO + PUSH AX ;PAGE POINTER + MOV LPTAB,BX ;SAVE PAGE TABLE POINTER + MOV AX,LPAGE ;SAVE NEW BLOCK NUMBE + MOV [BX],AL + MOVM [BX+1],RTIME1,CL;AND CURRENT REF TIME + MOVM [BX+2],RTIME2,CX + POP BX ;PAGE POINTER + CALL GETBLK ;GET THE BLOCK +GTP4$: MOV AX,BX ;RETURN PAGE POINTER + MOV LPLOC,AX ;AND SAVE IT FOR LATER + POP BX ;RESTORES + POP CX + RET +GETPAG ENDP + + ;FIND A GOOD PAGE, RETURN PAGE POINTER IN AX & PAGTAB POINTER IN BX +; SEE COMMENTS UNDER GETPAG + PUBLIC FINDPG,FNP1$,FNP2$,FNP3$,FNP4$ +FINDPG PROC + PUSH CX + MOV BX,OFFSET PAGTAB + MOV CX,-1 ;FAKE BEST-CASE REFERENCE COUNT + MOV DX,CX + INC BX ;SKIP BLOCK NUMBER FOR NOW +FNP1$: INC BX ;IS THIS REF TIME WORSE THAN CURRENT WORST? + CMP [BX-1],CL + JA FNP3$ ;NO + JB FNP2$ ;YES + CMP [BX],DX ;MAYBE, COMPARE LOW-ORDER WORDS, WORSE? + JAE FNP3$ ;NO +FNP2$: MOV CL,[BX-1] ;YES, SAVE ITS REF COUNT + MOV DX,[BX] + MOV AX,BX ;AND LOCATION (+2) +FNP3$: ADD BX,3 ;SKIP SECOND WORD + CMP BYTE PTR [BX-1],-1 ;LOOP UNTIL END OF TABLE + JNE FNP1$ + INC CX ;WAS A PAGE REALLY FOUND? + JE FNP4$ ;NO, GROSS BUG! + SUB AX,2 ;YES, CALCULATE CORE LOCATION OF PAGE + + MOV BX,AX + SUB AX,OFFSET PAGTAB + CMP AX,SEGEND ; (6) CHECK SEGMENT + JL FNP5$ ; (6) IN SEG0, SET CURSEG + MOV CURSEG,1 ; (6) SET CURSEG TO SEG1 + SUB AX,SEGEND ; (6) SCALE DOWN THE PAGE PTR + JMP FNP6$ +FNP5$: MOV CURSEG,0 +FNP6$: MOV CL,7 + SHL AX,CL + TEST CURSEG,1 ; (6) DON'T ADD IN PAGES IF IN SEG1 + JNZ FNP7$ + ADD AX,PAGES +FNP7$: POP CX ;RESTORES + RET +FNP4$: FATAL FTL6 +FINDPG ENDP + + SUBTTL HIGH LEVEL IBMPC DEPENDENT STUFF + + ;SYSTEM INITIALIZATION +; SYSINI HAS BEEN GREATLY MODIFIED TO INCLUDE DOS 2.0 FILE HANDLING, +; COMMAND LINE ARGUMENTS, COPY PROTECTION, AND DYNAMIC ALLOCATION OF +; PAGING SPACE. +; +; THE COPY PROTECTION SCHEME WORKS AS FOLLOWS: A NUMBER OF COMPUTERS ARE +; DEFINED AS COMPATIBLE WITH IBM IN THE DATA DECLARATIONS. INCLUDED FOR +; EACH IS THE FIRST 9 LETTERS OF THE COPYRIGHT NOTICE THAT EXISTS IN THE +; ROM. IF ANY OF THESE STRINGS IS FOUND IN THE ROM, COPY PROTECTION IS +; CHECKED, OTHERWISE IT IS NOT. IBM COMPATIBILITY MEANS TOTAL ROM BIOS +; COMPATIBILITY SUCH THAT WINDOWED SCROLLING AND SPECIAL DISK I/O MAY BE +; PERFORMED. NOT FINDING ANY OF THESE STRINGS RESULTS IN THE ZIP FUNCTIONING +; AS IF IT WERE ON A GENERIC MS-DOS BASED MACHINE. +; +; COMMAND LINE ARGUMENTS SET BITS IN THE VARIABLE CMDLIN IN THE ROUTINE +; SCANCMD. CMDLIN THEN AFFECTS VARIOUS PARAMETERS AND VARIABLES EITHER IN +; SYSINI OR SSETUP. +; +; THE PAGTAB IS SET UP ACCORDING TO AVAILABLE MEMORY. THERE EXISTS A WORD +; AT OFFSET 2 IN THE PSP (PROGRAM SEGMENT PREFIX, OR WHERE CS POINTS) WHICH +; INDICATES THE TOP OF PHYSICAL MEMORY. PAGTAB REPRESENTS THE LAST WORD USED +; BY THE ZIP. THE CODE SEGMENT REPRESENTS THE AMOUNT OF MEMORY TAKEN UP BY +; EVERYTHING UNDER THE ZIP SUCH AS THE OPERATING SYSTEM AND DEVICE DRIVERS. +; IF WE CONVERT PAGTAB TO PARAGRAPHS, THEN ALL OF THESE NUMBERS ARE IN +; PARAGRAPHS. SO: +; +; TOP_OF_MEM - (CS + PAGTAB) --> AVAILABLE MEMORY IN PARAGRAPHS +; +; AVAILABLE MEMORY IS CONVERTED INTO THE NUMBER OF BUFFERS AVAILABLE. FROM +; THIS NUMBER WE MUST SUBTRACT 1 OR 2 BUFFERS TO ALLOW FOR THE PAGTAB TO +; BE BUILT. KNOWING AVAILABLE BUFFERS TELLS US THE LENGTH OF OUR PAGTAB +; SINCE OUR PAGTAB IS 4 BYTES/BUFFER. AT THE NEXT PARAGRAPH BOUNDARDY BEYOND +; THE PAGTAB WE HAVE OUR FIRST GAME SEGMENT WHICH WILL BE MOVED TO ES AND +; STORED IN THE VARIABLE GAMESEG. ADDING 64K (IN PARAGRAPHS) TO GAMESEG +; WE ARRIVE AT OUT LOCATION FOR SEG1, THE SECOND GAME SEGMENT. THE PAGTAB +; IS THEN INITIALIZED. +; + PUBLIC SYSINI,SYS1,INITLP,SYSFTL +SYSINI PROC + MOV AH,DOSVER ; (7) GET DOS VERSION # + INT 21H ; (7) MUST BE 2.0 OR HIGHER + CMP AL,2 ; (7) DOS 2.0+ + JGE GOODOS + FATAL FTL11 ; (7) DIE APPROPRIATELY +GOODOS: MOV AH,CURDSK ; (6) GET DEFAULT DRIVE + INT 21H ; (6) FROM DOS + MOV DEFDRV,AL ; (6) SAVE DEFAULT DRIVE + MOV CURDRV,AL ; (6) SAVE DEFAULT DRIVE + CALL SCANCMD ; (7) GET CMD LINE VARS + MOV AX,BIOSEG ; (7) GET SEG OF BIOS + MOV ES,AX ; (7) MAKE ADDRESSIBLE + MOV BX,COMPATS ; (7) GET NUMBER OF COMPATIBLES + MOV AX,OFFSET COMP1 ; (7) CHECK FOR COPYRIGHT +SYS$: MOV DX,9 ; (7) LENGTH FOR MATCHING STRING + MOV DI,BIOSOFF ; (7) OFFSET INTO BIOS TO CHECK + MOV CX,7000H ; (7) SEARCH THIS MANY BYTES + CALL CHK ; (7) LOOK FOR COPYRIGHT NOTICE + JNC GOTONE ; (7) JMP ON A MATCH + ADD AX,10 ; (7) ADVANCE TO NEXT STRING + DEC BX ; (7) DO WE HAVE ANOTHER STRING + JNZ SYS$ ; (7) YES, LOOK AT IT + JMP NOCMD ; (7) SKIP COPY PROTECT CHECK +GOTONE: MOV SCROLL,0 ; (7) USE WINDOWED SCROLLING + CALL CHKCOP ; (7) CHECK COPY PROTECTION + JNC NOCMD ; (7) CONTINUE ON + FATAL FTL10 +NOCMD: MOV AH,CFOPENZ ; (6) ASCIZ STRINGS + MOV AL,0 ; (6) OPEN FOR READING + MOV DX,OFFSET GAMFILE + INT 21H + JNC SYSA$ + JMP SYSFTL +SYSA$: MOV GAMHNDL,AX ; (6) SAVE THE FILE HANDLE + MOV BX,AX ; (7n) GET FILE HANDLE INTO BX + XOR CX,CX ; (7n) ZERO THESE + XOR DX,DX ; (7n) TO FIND EOF + MOV AH,CFSEEK ; (7n) SEEK TO END OF FILE + MOV AL,2 ; (7n) MOVE FILE PTR TO EOF + INT 21H ; (7n) DO IT + MOV CL,4 ; (7n) CONVERT AX TO PARAGRAPHS + SHR AX,CL ; (7n) TO SAVE AS FILESIZE + TEST DX,DX ; (7n) DO WE HAVE A 17TH BIT? + JZ SYSB$ ; (7n) NOPE + OR AH,10H ; (7n) TURN ON THAT BIT +SYSB$: MOV CL,5 ; (7n) REDUCE TO NUMBER OF 512 BLKS + SHR AX,CL ; (7n) FOR COMPARISON TO BUFFERS + MOV GAMESIZ,AX ; (7n) SAVE THIS SIZE FOR FITS + + XOR CX,CX ; (7w) MOVE POINTER TO BOF + MOV DX,4 ; (7w) WE WANT THE WORD AT OFFSET 4 + MOV AH,CFSEEK ; (7w) SEEK THERE + MOV AL,0 ; (7w) METHOD: OFFSET FROM BOF + INT 21H ; (7w) BX HAS FILE HANDLE + MOV AH,CRDRNDZ ; (7w) READ IN THE FIRST + MOV CX,2 ; (7w) READ THE WORD OF ENDLOD + MOV DX,OFFSET SSBUF ; (7w) ANY BUFFER BIG ENOUGH WILL DO + INT 21H ; (7w) READ IT + MOV AX,SSBUF ; (7w) GET THE WORD + XCHG AH,AL ; (7w) FLOP THE BYTES + TEST AX,1FFH ; (7w) ROUND UP TO NEXT BLOCK + JE SYSC$ + AND AX,0FE00H ; (7w) TURN OF LOW BITS + ADD AX,200H ; (7w) ADD A BLOCK +SYSC$: MOV CL,9 ; (7w) CONVERT TO NUMBER OF BLOCKS + SAR AX,CL + MOV DX,AX ; (7w) AND SAVE NUMBER IN DX + + MOV BX,2 ; (6) GET TOP OF MEMORY + MOV BX,CS:[BX] ; (6) FROM OUT OF THE PSP + MOV AX,CS ; (6) GET CODE SEG + SUB BX,AX ; (6) SUB CSEG FROM TOPMEM + MOV CL,4 ; (6) SHIFT COUNT + MOV AX,OFFSET PAGTAB ; (6) USE OFFSET TO FIGURE PARAG'S + SHR AX,CL ; (6) REDUCE THIS OFFSET TO PARAS + INC AX ; (6) SKIP ONE PARAGRAPH + AND AX,0FE0H ; (7z) BLOCKIFY THIS NUMBER + ADD AX,20H ; (7z) OTHERWISE LOSE A PAGE + SUB BX,AX ; (6) YIELDS PARAS AVAILABLE + + TEST CMDLIN,4 ; (7) SET ON CMDLIN? + JZ SYS2 + CMP BX,MEMORY ; (7) REASONABLE REQUEST + JBE SYS2 ; (7) NO, NOT REALLY THERE + MOV BX,MEMORY ; (7) USE USER SETTING + +SYS2: CMP BX,MINMEM ; (7) AT LEAST 48K? + JAE SYS3 ; (7) YES + FATAL FTL12 ; (7) DIE APPROPRIATELY +SYS3: MOV CL,5 ; (6) DIVIDE BY 32 TO GET BUFFERS + SHR BX,CL ; (6) TO GET #BUFFERS + SUB BX,DX ; (7w) SUBTRACT ALL PRELOD BLOCKS + DEC BX ; (6) SUBTRACT 1 BUFFER FOR PAGTBL + CMP BX,128 ; (6) ABOVE 80H, WE NEED ANOTHER TBL + JL SYS1 ; (6) WE HAVE THIS MANY OR FEWER + DEC BX ; (6) TAKE AWAY ANOTHER PAGE + CMP BX,255 ; (6) THIS IS THE MOST WE WILL NEED + JLE SYS1 ; (6) DON'T MODIFY BX <= 255 + MOV FITS,1 ; (6) FLAG THAT GAME FITS IN MEMORY + MOV BX,255 ; (6) DON'T ALLOW MORE THAN THIS +SYS1: PUSH BX ; (7w) SAVE THIS FOR FIDDLING + ADD BX,DX ; (7w) ADD IN THE BLOCKS PREV SBTRCTED + CMP BX,GAMESIZ ; (7n) CHECK FOR LUCKY FIT + POP BX ; (7w) AND RESTORE ACTUAL #BUFFERS + JBE SYSD$ ; (7n) IF BX IS GREATER, NO GO + MOV FITS,1 ; (7n) IT DOES FIT AFTERALL!!! +SYSD$: MOV BUFFERS,BX ; (6) SAVE THIS NUMBER + SHL BX,1 ; (6) GET NUMBER OF BYTES IN PAGTBL + SHL BX,1 ; (6) 4 BYTES WIDE * BX BYTES LONG + INC BX ; (6) ADD 1 FOR TERMINATOR BYTE + ADD BX,OFFSET PAGTAB ; (6) CALC TABLE LOCATION + MOV CX,4 ; (6) REDUCE #BYTES IN TABLE = PARAS + SHR BX,CL ; (6) TO DYNAMICALLY ALLOCATE SPACE + MOV AX,DS ; (6) GET A COPY OF CURRENT SEG + ADD BX,AX ; (6) AND CALCULATE THE NEW SEG + ADD BX,1 ; (6) ADD ONE PARAGRAPH FOR SAFETY + MOV GAMESEG,BX ; (6) THIS WILL BE USED FOR ES:GAME + ADD BX,1000H ; (6) ADD 64K TO CALC 2ND SEG + MOV SEG1,BX ; (6) THIS IS SEG0+64K + CALL TBLINI ; (7n) CALL TABLE INITIALIZATION + CALL SSETUP + RET +SYSFTL: FATAL FTL9 +SYSINI ENDP + + + ; THIS ROUTINE INITIALIZES THE PAGE TABLE + ; +TBLINI PROC + PUSH SI ; SAVES + PUSH DI + PUSH AX + PUSH BX + PUSH CX + MOV DI,OFFSET PAGTAB ; (6) GET BEGINNING ADDR + MOV CX,WORD PTR BUFFERS ; (6) GET NUMBER OF ENTRIES + MOV AX,DS ; (7)GET DATA SEG + MOV ES,AX ; (7) FIX ES + CLD ;(6) AUTO INCREMENT +INITLP: MOV SI,OFFSET INITTBL ; (6) POINT TO STRING TO INITIALIZE + PUSH CX ; (6) SAVE REP COUNT + MOV CX,4 ; (6) GET INNER LOOP COUNT + REP MOVSB ; (6) TRANSFER THE STRING TO TBL + POP CX ; (6) RESTORE COUNT + LOOP INITLP ; (6) AND FINISH TABLE INITIALIZING + MOV WORD PTR [DI],-1 ; (6) DEPOSIT A -1 TO INDICATE END + MOV BX,GAMESEG ; + MOV ES,BX ; (6) SET THE EXTRA SEG TO GAMESEG + POP CX ; RESTORES + POP BX + POP AX + POP DI + POP SI + RET +TBLINI ENDP + + PUBLIC GAMOPEN + ; THIS PROCEDURE OPENS THE GAME FILE AFTER CLOSING ALL FILES. + ; IF THE GAME FILE IS NOT ON THE DISK, IT PROMPTS FOR REINSERTION +GAMOPEN PROC + PUSH DX + MOV DL,DEFDRV ; (7o) GET DRIVE WHERE GAME IS + MOV AH,CSELDSK ; (7o) TO MAKE OPEN WIN + INT 21H ; (7o) DO IT + MOV AH,CFCLOSZ ; (7s) TRY CLOSING INSTEAD OF RESET + MOV BX,GAMHNDL ; (7s) OF THE GAME FILE + INT 21H ; (7o) TO MAKE SURE THIS WINS +GOPEN0: MOV AH,CFOPENZ ; (6) ASCIZ STRINGS + MOV AL,0 ; (6) OPEN FOR READING + MOV DX,OFFSET GAMFILE ; (7o) OPEN THE FILE AGAIN + INT 21H + JNC GOPEN1 ; (7o) IF SUCCESS, CONTINUE + PRINT SAV3 ; (7o) OTHERWISE PROMPT + CALL MCHRI ; (7o) AND WAIT FOR A CHARACTER + JMP GOPEN0 ; (7o) AND LOOP +GOPEN1: MOV GAMHNDL,AX ; (7o) SAVE GAME HANDLE + MOV DL,CURDRV ; (7v) RESTORE SAVE DRIVE + MOV AH,CSELDSK ; (7v) SO THAT WE ARE NOT CONFUSED + INT 21H ; (7v) THANKS MAX + POP DX + RET +GAMOPEN ENDP + + ; GIVEN SOURCE PTR IN DS:AX, AND A DEST PTR IN ES:DI, CHK SEARCHES + ; FOR THE STRING POINTED TO BY DS:AX IN THE FIRST (CX) BYTES OF + ; THE STRING POINTED TO BY ES:DI + PUBLIC CHK +CHK PROC + CLD ; (7) CLEAR THE DIRECTION FLAG + PUSH SI ; (7) SAVE THIS + PUSH DX ; (7) SAVE THIS FOR RETRIES + MOV BP,SP ; (7) GET A FRAME POINTER + MOV SI,AX ; (7) SET UP FIRST OFFSET +LUP: CMP BYTE PTR [SI],'$' ; (7) END CHAR + JE MATCH ; (7) REACHING END==MATCH + CMPSB ; (7) COMPARE TWO BYTES + JNE RESET ; (7) RESET SOURCE IF MISMATCH + DEC DX + LOOP LUP ; (7) DECREMENT COUNTER AND TRY AGAIN + JMP RTFAIL ; (7) OUT OF CHARS, FAILED +RESET: MOV SI,AX ; (7) MOVE SOURCE PTR BACK INTO SI + MOV DX,[BP] ; (7) RESTORE NUMBER OF BYTES IN STR + LOOP LUP ; (7) TRY AGAIN +RTFAIL: STC ; (7) FAIL BY RETURNING CARRY SET + POP DX + POP SI ; (7) RESTORE SI + RET +MATCH: TEST DX,DX ; (7) MATCH OF ENTIRE STRING + JNZ RTFAIL + CLC ; (7) GOT A MATCH, RETURN CARRY CLEAR + POP DX + POP SI ; (7) RESTORE SI + RET +CHK ENDP + + ; THIS ROUTINE CHECKS THE COPY PROTECTION +CHKCOP PROC + CLC ; FOR NOW, EVERYTHING WORKS + RET +CHKCOP ENDP + + ; THIS ROUTINE SETS SOME VARIABLES ACCORDING TO THE CMD LINE +; CURRENTLY THE 6 /PARAMETERS ARE SUPPORTED. THE FIRST THREE, +; /P INITIALIZE PRINTER THROUGH INT 17 +; /M MONOCHROME +; /C COLOR +; /W WINDOWED SCROLLING +; /K AMOUNT OF MEMORY IN K +; ARE INTENDED FOR THE USER. A FOURTH WILL NOT BE DOCUMENTED IS +; /G WHICH WILL TEMPORARILY PATCH THE ZIP TO RUN THE +; GAME SPECIFIED. +; + PUBLIC SCANCMD,SCAN,SCAN0,SCAN1,SCAN2,SCAN3,SCAN4 + PUBLIC SCAN5,SCAN6,SCAN7,SCAN8 +SCANCMD PROC + CLD ; (7) AUTO INCREMENT + MOV SI,80H ; (7) GET # OF BYTES + LODSB ; (7) INTO AL + TEST AL,AL ; (7) ANY? + JNZ SCAN1 +SCAN0: RET ; (7) NONE THERE +SCAN1: DEC AL ; (7) CARRIAGE RETURN DOESN'T COUNT + XOR DX,DX ; (7) ZERO THIS + MOV DL,AL ; (7) SAVE NUMBER OF BYTES + ADD DX,82H ; (7) ADDR OF LAST BYTE+1 ON LINE + INC SI ; (7) SKIP INITIAL SPACE +SCAN: CMP SI,DX ; (7) END OF CMD LINE? + LODSB ; (7) GET A DELIMITER + JZ SCAN0 ; (7) YEP, RETURN + CMP AL,'/' ; (7) WAS IT THE DELIMITER + JNZ SCAN ; (7) GET NEXT VALID CHAR + LODSB ; (7) GOT DELIMITER, GET BYTE + AND AL,5FH ; (7) UPPERCASIFY + CMP AL,'M' ; (7) DO THEY WANT MONOCHROME + JNZ SCAN2 ; (7) NOPE, TRY NEXT + OR CMDLIN,1 ; (7) SET FLAG IN CMDLIN VARIABLE + JMP SCAN +SCAN2: CMP AL,'W' ; (7) WINDOWED SCROLLING? + JNZ SCAN3 + MOV SCROLL,0 ; (7) TURN ON SCROLLING + OR CMDLIN,8 ; (7) TURN ON 8 BIT + JMP SCAN +SCAN3: CMP AL,'G' ; (7) GAME FILE NAME? + JNZ SCAN5 ; (7) NOPE, CONTINUE ON... + MOV DI,OFFSET GAMFILE ; (7) MAKE THIS THE GAME +SCAN4: MOVSB ; (7) TRANSFER A BYTE + CMP DX,SI ; (7) THE END? + JNZ SCAN4 + MOV AL,0 ; (7) DROP IN A NULL + STOSB ; (7) TO END THE STRING + RET +SCAN5: CMP AL,'C' ; (7) DO THEY WANT COLOR + JNZ SCAN6 ; (7) NOPE, TRY NEXT + OR CMDLIN,2 ; (7) SET FLAG IN CMDLIN VARIABLE + JMP SCAN +SCAN6: CMP AL,'K' ; (7) SET MEMORY SIZE + JNZ SCAN9 ; (7) NOPE LOOK ONWARD + MOV BX,0 ; (7) ZERO THIS +SCAN7: CMP DX,SI ; (7) THE END? + JNZ SCAN8 ; (7) NOPE +SCAN7A: OR CMDLIN,4 ; (7) TURN ON MEMORY SET BIT + MOV CL,6 ; (7w) CONVERT K TO PARAGRAPHS + SHL BX,CL ; (7) I THINK??? + MOV MEMORY,BX ; (7) SAVE AMOUNT OF K SPECIFIED IN 512 BLKS + DEC SI ; (7v) BACKUP ONE + JMP SCAN +SCAN8: LODSB ; (7) GET FIRST BYTE + CMP AL,0D ; (7v) CR MEANS END OF STRING + JZ SCAN7A ; (7v) SO QUIT HERE + CMP AL,' ' ; (7v) SPACE MEANS NEXT STRING + JZ SCAN7A ; (7v) SO QUIT + CMP AL,'/' ; (7v) SLASH MEANS NEXT DELIMITER + JZ SCAN7A ; (7v) SO QUIT + XOR AH,AH ; (7) ZERO THIS + AAA ; (7) SCALE THE NUMBER DOWN + XCHG AX,BX ; (7) GET NUMBER (BX) INTO AC + PUSH DX ; (7) SAVE ENDPTR + MUL RADIX ; (7) MULTIPLY NUMBER BY TEN + ADD BX,AX ; (7) ADD IN NEW NUMBER + POP DX ; (7) RESTORE END PTR + JMP SCAN7 +SCAN9: CMP AL,'P' ; (7w) DO WE NEED TO INITIALIZE THE PRINTER + JZ SCAN10 ; (7w) YES, DO IT + JMP SCAN +SCAN10: PUSH DX ; (7w) SAVE THIS + MOV DX,0 ; (7w) INITIALIZE FIRST PRINTER + MOV AH,1 ; (7w) FUNCTION NUMBER FOR INIT + INT 17H ; (7w) ASSUME IBM PC BECAUSE THEY USED /P + POP DX ; (7w) RESTORE END POINTER + JMP SCAN ; (7w) NOW GET BACK TO WORK +SCANCMD ENDP + +CLRSCR PROC + CMP SLFLG,0 ; (7n) ANSI IN PLACE? + JZ CLR1 + MOV BX,OFFSET CLS + CMP COLFLG,1 ; (7t) TURN ON COLOR WITH CLEAR SCREEN + JNZ CLR0 + MOV BX,OFFSET CLSC ; (7t) TURN POINT TO COLOR ANSI CODE +CLR0: CALL MSPRT + RET +CLR1: MOV CL,SLPP ; (7n) GET NUMBER OF LINES + XOR CH,CH ; (7n) ZERO THE TOP +CLR2: CALL MCRLF ; (7n) ROLL THE SCREEN IF NO ANSI + MOV MORLIN,0 ; (7n) RESET TO AVOID MORE + LOOP CLR2 + RET +CLRSCR ENDP + + ;GET A GAME FILE BLOCK, BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX + PUBLIC GETBLK +GETBLK PROC + PUSH CX ;SAVE + MOV CX,1 ;CALL GTBLKS FOR 1 BLOCK ONLY + CALL GTBLKS + POP CX ;RESTORE + RET +GETBLK ENDP + + + ;GET A SERIES OF GAME FILE BLOCKS, + ;FIRST BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX # OF BLOCKS IN CX +; GTBLKS UNDERWENT A MAJOR OVERHAUL. IT WAS CHANGED TO SUPPORT 2.0 FILE +; NAMES AND FILE HANDLES. THE FIRST PASS OF THE OVERHAUL WAS TO SUPPORT +; FITTING THE WHOLE GAME INTO MEMORY. THIS BASTARDIZATION OF THE ORIGINAL +; WAS FURTHER CONTORTED WHEN TRYING TO SUPPORT 128K AND LESS MEMORY CONFIG- +; URATIONS. +; +; THE ORIGINAL ARGUMENTS HAVE NOT BEEN LEFT WHOLLY IN TACT. AX IS STILL THE +; FIRST BLOCK NUMBER AND CX CONTAINS THE NUMBER OF BYTES TO READ IF ALL OF +; THE GAME IS IN MEMORY OR BLOCKS IF THE GAME DOESN'T ALL FIT. ES:BX NO +; LONGER HAS THE CORE LOCATION. CALLS TO THIS PROCEDURE MAY STILL PUT THE +; CORE LOCATION IN BX BUT IT IS IGNORED. CORE LOCATION IS CALCULATED ON THE +; FLY BASED ON THE ENTRY IN PAGTAB (WHICH IN TURN SETS THE SEGMENT IN WHICH +; THE READ IS DONE.) +; +; THE STARTING BLOCK NUMBER IS USED TO MOVE THE FILE PTR (2.0) FROM THE +; BEGINNING OF THE FILE TO THE PROPER GAME BLOCK. +; +; IN THE CASE OF ALL OF THE GAME IN MEMORY, THE SEGMENT IS CHOSEN BASED ON +; THE PAGE'S INTENDED BUFFER INDICATED BY THE VARIABLE LPTAB. BUFFER NUMBERS +; 128 AND ABOVE GO IN TO THE SECOND SEGMENT. THE GAME IS READ IN IN THE +; BEGINNING IN THREE OR FOUR READS AND THIS ROUTINE IS NOT TOUCHED AGAIN. +; +; IN THE CASE OF A SMALL MEMORY SYSTEM, THE SEGMENT TO READ INTO IS CHOSEN +; BASED ON LPTAB, CURSEG AND SEGEND (SEE GETPAG FOR EXPLANATION). +; + PUBLIC GTBLKS,GTBKI$,GTBLP,GETIT,GTBLKB,GTBOUT,GTB2,GTB3 +GTBLKS PROC + MOV DSKDIR,0 ;READ MODE + PUSH AX + MOV AX,GAMHNDL ; (6) GET THIS HANDLE + MOV HANDLE,AX ; (6) INTO THE GENERAL HANDLE + POP AX ; (6) AND RESTORE THIS +GTBKI$: PUSH BP + PUSH DX + PUSH BX + PUSH SI +GTBLP: MOV DX,CX ; (6) SAVE NUMBER OF BLOCKS + MOV CX,9 ; (6) MULTIPLY BY 512 + SHL DX,CL ; (6) DO IT + SHL AX,CL ; (6) CONVERT BLK# TO OFFSET + MOV CX,0 ; (6) ZERO THIS + ADC CX,0 ; (6) DID WE CARRY OUT ABOVE + MOV BX,HANDLE ; (6) GET FILE HANDLE + MOV SI,DX ; (6) SAVE NUMBER OF BYTES FOR READ + TEST SEEKF,1 ; (6) SHOULD WE REALLY? + JZ NOSEEK + MOV DX,AX ; (6) GET LOW ORDER #BYTES FOR SEEK + MOV AH,CFSEEK + MOV AL,0 ; (6) USE OFFSET FROM BEGINNING METHOD + INT 21H ; (6) SEEK +NOSEEK: MOV DX,LPTAB ; (6) FIGURE OUT BUFFER NUMBER + TEST FITS,1 ; (6) DO WE HAVE ALL THE GAME + JNZ NOFIX ; (6) IF NOT, FIX LPTAB (SCALE IT DOWN) + CMP DX,0 ; (6) ARE WE JUST STARTING UP + JZ NOFIX + SUB DX,OFFSET PAGTAB ; (6) BASIFY THE TABLE NUMBER + SHR DX,1 + SHR DX,1 ; (6) DIVIDE TABLE ENTRY BY TABLE WIDTH(4) + MOV CL,9 ; (6) DIVIDE BY 512 + TEST CURSEG,1 ; (6) WHICH SEG ARE WE IN + JNZ NOFIX ; (6) SKIP PAGE ADDITION + MOV AX,PAGES ; (6) GET AMOUNT OF PRELOD + SHR AX,CL ; (6) AND SKIP THAT AMOUNT OF BUFFER SPC + ADD DX,AX ; (6) ADD THAT INTO BUFFER NUMBER +NOFIX: MOV CX,SI ; (6) RESTORE #BYTES TO READ + MOV AH,CRDRNDZ ; (6) READ RANDOM GAME RECORD + CMP DSKDIR,0 ; (6) ARE WE READING? + JZ GTREAD + MOV AH,CWRRNDZ ; (6) NO, DO A WRITE INSTEAD +GTREAD: TEST FITS,1 ; (6) IS BUFFERING CONTINUOUS + JNZ GTBLK1$ ; (6) FIGURE BUFFER FROM DX + TEST CURSEG,1 ; (6) WHAT SEGMENT ARE WE IN + JZ GETIT ; (6) FUNCTION NORMALLY + MOV SI,SEGEND ; (6) GET SEGMENT ENDING POINT + SHR SI,1 ;(6) DIVIDE IT BY WIDTH OF PAGTAB + SHR SI,1 ; (6) TO USE AS AN INDEX INTO SEG1 + SUB DX,SI ; (6) BASIFY BUFFER NUMBER FOR SEG1 + JMP GTBLK2$ ; (6) USE SEG1 WITH SCALED DX +GTBLK1$:CMP DX,128 + JL GETIT + SUB DX,128 ; (6) SUBTRACT TO BASIFY +GTBLK2$:PUSH DS + MOV SI,SEG1 ; (6) GET SEG1 INTO DS + MOV DS,SI ; (6) SET UP DS + JMP GTBLKB +GETIT: PUSH DS + MOV SI,ES + MOV DS,SI +GTBLKB: PUSH CX ; (6) SAVE NUMBER OF BLOCKS + MOV CL,9 + SHL DX,CL ; (6) MAKE A NEW PAGE-PTR + POP CX ; (6) RESTORE COUNT OF BYTES + INT 21H ; (6) CALL DOS + CMP AX,CX ; (6) SET FLAGS + POP DS + MOV SEEKF,1 ; (6) RESET SEEK FLAG +GTBOUT: POP SI + POP BX + POP DX + POP BP + RET +GTB2: PUSH AX ; (6) SAVE THIS + MOV AX,GAMHNDL ; (6) GET HANDLE + CMP HANDLE,AX ; (6) COMPARE THEM + JE GTB3 + STC + JMP GTBOUT + +GTB3: FATAL FTL7 +GTBLKS ENDP + + SUBTTL IBMPC SYSTEM ROUTINES + PAGE + + + PUBLIC MCHRI,MTTYO,MCRLF,MSOUT,MSPRT,MINIT,MPRNT,MTIME,FINISH + ;READ A CHARACTER INTO AX, WAITING UNTIL ONE IS AVAILABLE, NO ECHO + +MCHRI PROC + PUSH CX + PUSH DX + CMP CHRFLG,0 + JNZ MCHR1 + MOV CHRFLG,1 +MCHR1: MOV AH,CNOECHO ; (7u) USE NO ECHO + INT 21H + SUB AH,AH + call boss ; check for boss key + POP DX + POP CX + RET +MCHRI ENDP + + ;PRINT THE CHARACTER IN AL, FOREGROUND IN AH +MTTYO PROC + PUSH AX + PUSH BX ;SAVES + PUSH CX + PUSH DX + PUSH BP + PUSH AX + MOV AH,CCONIO + MOV DL,AL + INT 21H + POP AX + TEST SCRFLG,1 ; (7x) IS SCRIPTING REQUESTED? + JZ MTYO1 ; (7n) IF NOT THEN DON'T BOTHER + CMP SCRHLD,1 ; (7n) IS SCRIPTING SUSPENDED? + JZ MTYO1 + CALL PRTOUT +MTYO1: POP BP + POP DX + POP CX + POP BX + POP AX + RET +MTTYO ENDP + + ;PRINT A CARRIAGE RETURN/LINE FEED WITH MORE MODE +MCRLF PROC + PUSH AX ;SAVES + PUSH BX + PUSH CX + PUSH DX + PUSH BP + TEST SCROLL,1 ;(7) WHAT KIND OF SCROLLING + JNZ MCR$ + TEST SCRNFLG,1 ; (7) ARE WE IN SCREEN #1 + JNZ MCR$ ; (7) YES, USE OLD SCROLL + MOV AH,SCROLLUP ;(7) USE A VIDEO BIOS SCROLL + MOV AL,1 ;(7) ONLY 1 LINE + MOV CX,TOPLIN ;(7) ALWAYS FREEZE TOP LINE + MOV DH,SLPP ;(7) GET SCREEN LENGTH + MOV DL,SCPL ;(7) GET THE WIDTH OF THE SCREEN + DEC DL ; (7v) COORDINATES ARE ZERO BASED + MOV BH,SCRATR ;(7) GET THE SCREEN ATTRIBUTE + INT 10H ;(7) CALL THE VIDEO +MCR$: MOV AH,CCONIO + MOV DL,13 + INT 21H + TEST SCRNFLG,1 ; (7) ARE WE WRITING TO WINDOW 1 + JNZ MCRA$ + TEST SCROLL,1 ;(7) NO LINE FEED ON WINDOWED SCROLL + JZ NOLF +MCRA$: MOV AH,CCONIO + MOV DL,10 + INT 21H +NOLF: TEST SCRNFLG,1 ;(7) NO MORE FOR WINDOW 1 + JNZ MCR1 ;(7) SKIP THIS GARBAGE + INC MORLIN ;INCREMENT NUMBER OF LINES OUTPUT + MOV AL,SLPP + SUB AH,AH + DEC AX ;(7n) SO THAT STATUS LINE DOESN'T OVERWRITE +MCRB$: MOV DX,TOPLIN ;(7) GET SCROLLING WINDOW TOPLINE + XCHG DH,DL ;(7) SCROLL LINE IN DL + SUB AL,DL ;(7) THIS MANY LINES NOW + CMP MORLIN,AX + JL MCR1 + MOV MORLIN,0 + MOV SCRHLD,1 ; (7o) SUSPEND SCRIPT + PRINT MORE + CALL MCHRI + PRINT EMORE + MOV SCRHLD,0 ; (7o) RESUME SCRIPT +MCR1: TEST SCRFLG,1 ; (7x) CHANGED TO TEST + JZ MCR2 + CALL PRTCRL +MCR2: POP BP + POP DX + POP CX + POP BX + POP AX + RET +MCRLF ENDP + + ;OUTPUT STATUS LINE HERE +MSOUT PROC + MOV BX,OFFSET SBLINE + TEST COLFLG,1 ;(7) ARE WE IN COLOR MODE + JZ MSOUT1 + MOV BX,OFFSET CBLINE ;(7) USE COLOR THROUGH ANSI +MSOUT1: CALL MSPRT + MOV AH,09H + MOV DX,SLSTR + INT 21H + MOV BX,OFFSET SELINE + TEST COLFLG,1 ;(7) ARE WE IN COLOR MODE + JZ MSOUT2 + MOV BX,OFFSET CELINE ;(7) USE COLOR THROUGH ANSI +MSOUT2: CALL MSPRT + RET +MSOUT ENDP + +MSPRT PROC + MOV CL,BYTE PTR [BX] + SUB CH,CH + CMP CL,0 + JE MSPRT1 +MSPLP: INC BX + MOV DL,BYTE PTR [BX] + MOV AH,06H + PUSH BX + INT 21H + POP BX + LOOP MSPLP +MSPRT1: RET +MSPRT ENDP + +MINIT PROC + CMP SLFLG,0 + JNE MINIT1 + RET +MINIT1: MOV BX,OFFSET STINIT + TEST COLFLG,1 ;(7) ARE WE IN COLOR MODE + JZ MINIT2 ;(7) + MOV BX,OFFSET CTINIT ;(7) +MINIT2: CALL MSPRT + MOV BX,OFFSET SELINE + TEST COLFLG,1 ;(7) ARE WE IN COLOR MODE + JZ MINIT3 ;(7) + MOV BX,OFFSET CELINE ;(7) +MINIT3: CALL MSPRT + RET +MINIT ENDP + + ;PRINT A STRING, POINTER (TO DATA SEGMENT) IN AX, WHITE FOREGROUND +MPRNT PROC + CMP GAMEIN,1 ; (7q) DO NOT CHECK THIS UNLESS THE GAME IS IN + JNZ MPR0 + PUSH AX + MOV AX,ES:[PFLAGS] ; (7n) SCRIPTING? + XCHG AH,AL ; (7n) SWAP BYTES + MOV SCRFLG,AL ; (7n) TURN IT ON, TURN IT ON AGAIN! + POP AX +MPR0: PUSH BX ;SAVE BX + MOV BX,AX ;STRING POINTER +MPR1: MOV AL,[BX] ;GET NEXT CHARACTER + CMP AL,0 ;END OF LINE, WITH CRLF? + JE MPR2 ;YES + CMP AL,80H ;END OF LINE, NO CRLF? + JE MPR3 ;YES + CALL MTTYO ;PRINT CHARACTER + INC BX ;POINT TO NEXT CHARACTER + JMP MPR1 ;REPEAT +MPR2: CALL MCRLF ;PRINT A CRLF +MPR3: POP BX ;RESTORE BX + RET +MPRNT ENDP + + ;GET TIME +MTIME PROC + PUSH CX + PUSH DX + MOV AH,2CH + INT 21H + MOV RSEED1,CX ; HOURS & MINUTES + MOV RSEED2,DX ; SECONDS & 100THS + POP DX + POP CX + RET +MTIME ENDP + +FINISH PROC + CALL MCRLF + MOV BX,OFFSET STRESET + CALL MSPRT + MOV AH,4CH + INT 21H +FINISH ENDP + +EVEN +;********************************************************************** +; DO NOT PLACE ANY VARIABLES OR CODE BEYOND THIS POINT! THE +; ZIP DYNAMICALLY ALLOCATES A PAGE TABLE AND PAGING SPACE BEYOND +; THIS LABEL. +;********************************************************************** + PUBLIC PAGTAB +PAGTAB LABEL BYTE +MSZIP ENDP +CSEG ENDS + + END MSZIP diff --git a/ibm/branches.ezp b/ibm/branches.ezp new file mode 100644 index 0000000..df14bda --- /dev/null +++ b/ibm/branches.ezp @@ -0,0 +1,134 @@ + SUBTTL BRANCHES - CONTROL OPERATIONS + PAGE + + + PUBLIC OPCALL1 +OPCALL1 PROC + MOV ARGBLK,AX ; (A0) PUT ARG IN ARGBLK + MOV AX,1 ; (A0) SET AX TO NUMBER OF ARGS + JMP OPCALL ; (A0) NOW PROCEED NORMALLY +OPCALL1 ENDP + + PUBLIC OPCALL,OPXCALL,OPCALL2 + ;CALL (A FUNCTION WITH OPTIONAL ARGUMENTS), # OF ARGS IN AX +OPCALL PROC +OPXCALL: +OPCALL2: + NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV DX,AX ;NUMBER OF ARGUMENTS TO CALL + MOV AX,ARGBLK ;FUNCTION TO CALL + CMP AX,0 + JNE OCL1$ ;ZERO? + SUB AX,AX ;YES, SIMPLY RETURN A ZERO + JMP PUTVAL +OCL1$: PUSHZ ZPC1 ;OTHERWISE, SAVE OLD ZPC + PUSHZ ZPC2 + MOV CX,ZLOCS ;AND OLD LOCAL POINTER + PUSHZ CX ;AND SAVE IT + CALL BSPLITQ ; (A0) SPLIT FUNCTION POINTER (QUAD) + MOV ZPC1,AX ;MAKE IT THE NEW ZPC + MOV ZPC2,BX + CALL NEWZPC ;UPDATE ZPC STUFF + MOV ZLOCS,DI ;LOCALS WILL START AT NEXT STACK SLOT + SUB ZLOCS,2 + CALL NXTBYT ;NUMBER OF LOCALS + MOV BX,AX + MOV BP,OFFSET ARGBLK[2] ;POINT TO FIRST OPTIONAL ARG +OCL2$: DEC BX ;ANY MORE LOCALS? + JL OCL4$ ;NO, WE'RE DONE + CALL NXTWRD ;YES, GET THE NEXT LOCAL DEFAULT VALUE + DEC DX ;ANY MORE OPTIONALS GIVEN? + JLE OCL3$ ;NO + PUSHZ [BP] ;(6) YES, USE ITS VALUE + ADD BP,2 + JMP OCL2$ ;AND CONTINUE LOOP +OCL3$: PUSHZ AX ;OTHERWISE, USE DEFAULT + JMP OCL2$ ;AND LOOP +OCL4$: RET +OPCALL ENDP + + PUBLIC OPRETU + ;RETURN (FROM CURRENT FUNCTION CALL) +OPRETU PROC + MOV DI,ZLOCS ;RESTORE OLD TOP OF STACK + POPZ DX ;DUMMY POP [WHY?] + POPZ ZLOCS ;AND OTHER VALUES + POPZ ZPC2 + POPZ ZPC1 + CMP ZPC1,1 ; (A0) FAKE BLOCK SET BY OPREAD + JNZ OPRET1 ; (A0) NO, NORMAL RETURN + JMP INRETU ; (A0) FIX ZPC AND RETURN +OPRET1: PUSH AX ;VALUE TO RETURN + CALL NEWZPC ;UPDATE ZPC STUFF + POP AX + JMP PUTVAL ;RETURN THE VALUE +OPRETU ENDP + + PUBLIC OPRTRU,OPRFAL,OPJUMP,OPRSTA,OPFSTA,OPNOOP + ;RTRUE +OPRTRU PROC + MOV AX,1 ;RETURN A 1 + JMP OPRETU +OPRTRU ENDP + + ;RFALSE +OPRFAL PROC + SUB AX,AX ;RETURN A 0 + JMP OPRETU +OPRFAL ENDP + + ;JUMP (TO A NEW LOCATION) +OPJUMP PROC + ADD ZPC2,AX ;ADD OFFSET TO CURRENT ZPC + SUB ZPC2,2 ;ADJUST IT + CMP ZPC2,200H ;(A16) DID WE CROSS A PAGE BOUNDARY? + JAE OPJMP1 ;(A16) YES, FIX PAGE POINTERS + MOV LSTNGD,0 ; (A16) RESET THE LAST NEXT BYTE + RET ; (A16) NO, GO ONWARD QUICKLY +OPJMP1: JMP NEWZPC ;NORMALIZE IT & UPDATE ZPC STUFF +OPJUMP ENDP + + ;RSTACK (RETURN STACK) +OPRSTA PROC + POPZ AX ;POP A VALUE + JMP OPRETU ;AND RETURN IT +OPRSTA ENDP + + ;FSTACK (FLUSH A VALUE OFF THE STACK) +OPFSTA PROC + POPZ DX ;FLUSH ONE + RET +OPFSTA ENDP + + ;NOOP (NO OPERATION) +OPNOOP PROC + RET ;DO NOTHING +OPNOOP ENDP + + PUBLIC INCALL +INCALL PROC + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH ZPC1 ; (A0) SAVE REAL ZPC1 + MOV ZPC1,1 ; (A0) FAKE ZPC FOR INTERNAL CALL + MOV ARGBLK,AX ; (A0) SAVE ARGUMENT + MOV AX,1 ; (A0) NUMBER ARGS HERE + CALL OPCALL ; (A0) NOW BLK READY FOR OPCALL + MOV LSTNGD,0 ; (A16) RESET LAST BYTE FLAG + JMP NXTINS ; (A0) GO GET NEXT INSTRUCTION +INCALL ENDP + + PUBLIC INRETU +INRETU PROC + ADD SP,2 ; (A0) FLUSH RETURN ADDR FROM NXTINS + POP ZPC1 ; (A0) RESTORE REAL BLOCK + PUSH AX ; (A0) SAVE ARG + CALL NEWZPC ; (A0) GET BLOCK + POP AX ; (A0) RESTORE ARG + POP SI ; (A0) RESTORE STATE + POP DX + POP CX + POP BX + RET ; (A0) GO BACK TO READ +INRETU ENDP diff --git a/ibm/create.asm b/ibm/create.asm new file mode 100644 index 0000000..96b0f3b --- /dev/null +++ b/ibm/create.asm @@ -0,0 +1,132 @@ + title - create + comment $ + This program replaces create.exe for MS-DOS based and now + covers IBM/MS-DOS 2.0+ VERSION I ZIP. It takes a game name + on the command line and patches the zip to load the game + specified on the command line. + + A>create zork1 + + will produce zork1.com, the zip program to load zork1. + + Written by Paul H. Gross - 26-Feb-85 $ +; +cseg segment + assume cs:cseg,ds:cseg,es:cseg,ss:cseg + org 100H + public create +create proc +; + jmp start + public ext,sav,fnf,nocmd,handle,lenth,infile,com +com db '.COM',0 +ext db '.DAT',0 +sav db '.SAV',0 +nozip db 'Failed to create zip file...',13,10,'$' +fnf db 'File not found',13,10,'$' +done db 'Completed...$' +nocmd db 'No game specified on command line. Usage: ',13,10,10 + db 9,'create ',13,10,'$' +handle dw ? +lenth dw ? +infile db 'msibmzip.com',0 +fileoff dw 82H +; + public start,load,patch,dump,buffer +start: call load + call patch + call dump + mov ah,9 + mov dx,offset done + int 21H + mov ah,4CH + int 21H +; +load: mov dx,offset infile ; open zip program file + mov ax,3D00H ; open zip for read + int 21H ; do it + jc nofile + mov dx,offset buffer ; get end of program area + mov cx,0FFFFH ; read in a whole file + mov bx,ax ; get handle + mov ah,3fH + int 21H ; read it + mov lenth,ax ; save number bytes read + mov ah,3EH ; close this file + int 21H ; thru dos + ret ; return +nofile: mov dx,offset fnf +error: mov ah,9 + int 21H + mov ah,4CH + int 21H +; +patch: mov si,80h ; get cmd line + cld ; auto increment + lodsb ; number of chars + dec al ; count out + cmp al,2 ; at least 2 chars + jge patch1 ; continue + mov dx,offset nocmd ; error message + jmp error +patch1: xor ah,ah + mov cx,ax ; get number + inc si + cmp byte ptr 1[si],':' ; do we have a drive specifier + jnz ptch1a ; nope + sub cx,2 ; fix the count + add si,2 ; and the byte pointer + mov fileoff,84H ; offset to file name with drive spec +ptch1a: push cx ; save this number + push cx ; save this number + push cx ; save it again +patch2: lodsb ; get a byte + cmp al,'a' ; is it lower + jl patch3 + mov di,si ; back up pointer + dec di + and al,5FH ; uppercasify + stosb ; the byte on command line +patch3: loop patch2 ; and continue + mov si,fileoff ; offset to filename in cmd line + pop cx ; restore count + lea di,buffer+3 ; addr of file name in zip + rep movsb ; transfer the name + mov cx,5 ; drop in extension + mov si,offset ext ; point to ext + rep movsb ; write it + pop cx ; get number of bytes again + mov si,fileoff ; point to string again + lea di,buffer+65+3 ; addr of save string + rep movsb ; transfer it + mov cx,5 ; and now the extension + mov si,offset sav ; from here + rep movsb + pop cx ; get number of bytes + mov di,cx ; get end of string addr + add di,fileoff ; point at + mov si,offset com ; add comfile extension + mov cx,5 + rep movsb + ret +; +dump: mov dx,82H ; point to new zip name + mov cx,0 ; normal attribute + mov ah,3CH ; create a file + int 21H ; + jc crfail ; create failed + mov bx,ax ; get the handle + mov cx,lenth ; get file length + mov ah,40H ; function is write + mov dx,offset buffer + int 21H + mov ah,3EH + int 21H ; close the file + ret +crfail: mov dx,offset nozip ; + jmp error +; +buffer label near +create endp +cseg ends + end create diff --git a/ibm/data.ezp b/ibm/data.ezp new file mode 100644 index 0000000..d1eba62 --- /dev/null +++ b/ibm/data.ezp @@ -0,0 +1,447 @@ + SUBTTL DATA - VARIABLE DEFINITION AND STORAGE + PAGE +; +; ALL DATA SAVE THE PAGE TABLE (PAGTAB) ARE DEFINED BETWEEN THE ABOVE JMP +; AND THE STARTING DESTINATION. +; + ;VARIBLE DEFINITIONS: + + PUBLIC START,GAMFILE,SAVFILE,GAMHNDL,SAVHNDL,HANDLE,SEEKF + PUBLIC LASTDRV,LSTDFLG,DRVFLG,LASTSAV,SSBUF,DEFDRV,CURDRV + ;GTBLKS +;************************************************************************ +; DO NOT MOVE THESE VARIABLES. DEFINE NOTHING ABOVE THEM. CREATE +; IS DEPENDENT UPON THIS FIXED VARIABLE SETUP FOR GAMFILE AND +; SAVFILE. EACH SHOULD TOTAL 65 CHARACTERS IN LENGTH +;************************************************************************ +; +GAMFILE DB "AMFV.DAT",0,0 ; PATCHED BY CREATE + DB 55 DUP (0) ; POTENTIAL LENGTH OF FILENAME +SAVFILE DB "AMFV.SAV",0,0 + DB 54 DUP (0) ; POTENTIAL LENGTH OF FILENAME +LASTSAV DB 64 DUP (0) +; +GAMESIZ DW ? ; GAME SIZE IN 512 BYTE BLOCKS +GAMHNDL DW ? ; FOR STORAGE OF FILE HANDLES +SAVHNDL DW ? +SSFILE DB "SETUP.INF",0 +SSBUF DW SSLNT/2 DUP (0) +SKPDRV DB 0 ; (7n) DON'T OUTPUT DRIVE NAME +DEFDRV DB ? ; BYTE FOR DEFAULT DRIVE +CURDRV DB ? ; BYTE FOR NEW DRIVE (SAVES) +DRVFLG DB 0 ; FLAG WHETHER DRIVE SPECIFIED ON SAV +LASTDRV DB ? ; TEMPORARY STORAGE FOR SAVE AND +LSTDFLG DB ? ; RESTORE FAILURE +HANDLE DW ? ; GENERAL HANDLE FOR GTBLKS ROUTINE +SEEKF DB 1 ; FLAG FOR WHETHER OR NOT TO SEEK +PRTBUF DB ? ; (7) BUFFER FOR PRINTER OUTPUT + + PUBLIC DSKDIR +DSKDIR DB 0 ;0 FOR READ, 1 FOR WRITE + + ; SCREEN DEFINITIONS AND ANSI STRINGS + PUBLIC SCRATR,COLFLG,SCP,RCP,SCPL,SLPP,STINIT,STRESET + PUBLIC SPINIT,STINIT,CTRESET,CLS,CLSC +CURSAV DB 0 ; (A0) IS THE CURSOR POSITION SAVED? +SCRATR DB 7 ;(7) BLACK BACKGROUND FOR DEFAULT +COLFLG DB 0 ;(7) ARE WE USING COLOR +SCPL DB 80 ; WIDTH OF THE SCREEN IN COLUMNS (DEFAULTS) +SLPP DB 24 ; LENGTH OF THE SCREEN IN ROWS + +NONIBM DW OFFSET NOHIGH ;(A9) + DW OFFSET INVERSE ;(A9) + DW OFFSET BOLD ;(A9) + DW 0 ;(A9) + DW OFFSET NOHIGH ;(A9) + +HILITES DW OFFSET NOHIGH + DW OFFSET INVERSE + DW OFFSET BOLD + DW 0 + DW OFFSET ITALIC +; +NOHIGH DB 4 + DB 27,'[0m' +INVERSE DB 8 + DB 27,'[0m',27,'[7m' +BOLD DB 8 + DB 27,'[0m',27,'[1m' +ITALIC DB 8 + DB 27,'[0m',27,'[4m' +;; +COLORS DW OFFSET NORMCOL + DW OFFSET INVCOL + DW OFFSET BOLDCOL + DW 0 + DW OFFSET NORMCOL +; +NORMCOL DB 12 + DB 27,'[0m',27,"[37;44m" + +INVCOL DB 12 + DB 27,'[0m',27,"[34;47m" +BOLDCOL DB 16 + DB 27,'[0m',27,"[37;44m",27,'[1m' + +EREOL DB 3 + DB 27,'[K' ; (A0) ERASE TO EOL +SCP DB 3 ; (7) ANSI SAVE CURSOR POSITION + DB 27,'[s' +RCP DB 3 ; (7) ANSI RESTORE CURSOR POSITION + DB 27,'[u' +STINIT DB 16 + DB 27,"[2J",27,"[0m",27,"[01;01H" +STRESET DB 4 + DB 27,"[0m" +SPINIT DB 0 +CTINIT DB 20 + DB 27,"[37;44m",27,"[2J",27,"[01;01H" +CTRESET DB 0 +CPINIT DB 0 +CLS DB 12 + DB 27,"[2J",27,"[" +CLS1 DB "25;01H" +CLSC DB 20 + DB 27,"[37;44m",27,"[2J",27,"[" +CLS1C DB "25;01H" +; +WAIT DB 31 + DB 27,"[12;28HThe story is loading..." + + PUBLIC WINDOW1,COLWIN1,WINDOW0,COLWIN0,RADIX +WINDOW1 DB 8 + DB 27,'[01;01H' +COLWIN1 DB 16 + DB 27,'[01;01H',27,'[37;44m' +WINDOW0 DB 4 + DB 27,'[0m' +COLWIN0 DB 8 + DB 27,'[37;44m' +RADIX DB 10 ; THE DEFAULT RADIX FOR THE SCREEN + ;SCRIPTING STUFF + PUBLIC GAMEIN,SCRHLD,SCRFLG,PRNNRDY +GAMEIN DB 0 +SCRHLD DB 0 ; (7n) IS SCRIPTING TEMPORARILY OFF +SCRFLG DB 0 +PRNNRDY DB " %Printer not ready: Abort or Retry? ",80H + + PUBLIC RSEED1,RSEED2 +;,SRHOLD,RNUM,IOCHAR + ;OPRAND +RSEED1 DW ? ;SEED1 FOR RANDOM NUMBERS +RSEED2 DW ? ;SEED2 FOR RANDOM NUMBERS +RTEMP DW ? ;TEMP FOR RANDOM ROUTINE +;(LD1) RNDFLG DB ? ; (A0) RANDOM FLAG +SRHOLD DW ? ; (LD1) FOR NON RANDOM RANDOM +RNUM DW ? ; (LD1) THIS ALSO +IOCHAR DB ? ; (LD1) HOLD AL FOR A SECOND + + PUBLIC RDWSTR,RDBOS,RDEOS,RDRET,RDNWDS,WRDOFF + ;READ +ZTHIRD DW ? ; (A0) THIRD ZWORD REGISTER FOR ZWORD +RDWSTR DW 5 DUP(0) ; (A0) WORD STRING BUFFER FOR ZWORD +RDBOS DW 0 ;BEGINNING OF STRING POINTER +RDEOS DW 0 ;END OF STRING POINTER +RDRET DW 0 ;RETURN TABLE POINTER +RDNWDS DB 0 ;NUMBER OF WORDS READ + ;PUTSTR +WRDOFF DW 0 ;OFFSET INTO WORD TABLE FOR CURRENT SET +DLYCNT DW ? ; (A0) DELAY COUNT IN 1/10THS SECONDS + + PUBLIC CHRPTR,ENDBUF,BUFBIT,PREVBUF + ;PUTCHR + ; REDIRECTION AND BUFFERING OUTPUT +CHRPTR DW 0 ;POINTS TO NEXT CHARACTER POSITION +ENDBUF DW 0 ;POINTS JUST PAST END OF OUTPUT BUFFER (0) +CHRCNT DW 79 ; (A13) OUTPUT BUFFER DOWN COUNTER +BUFBIT DB 1 ; (A0) BUFFERED INPUT TOGGLE +PREVBUF DB 1 ; (A0) PREVIOUS BUFFERING STAT +RDIR DW 0 ; (A0) WHERE OUTPUT IS DIRECTED TO +RTABLE DW ? ; (A0) ADDRESS OF TABLE TO OUTPUT TO +RTABLE2 DW ? ; (A0) OFFSET INTO TABLE WHERE OUTPUT GOES +RDIROUT DW 0 ; (A0) NUMBER OF CHARS SENT TO TABLE +VIDFLG DB 1 ; (A10) SCRREN CONTROL 1=ON + + ;GETNUM + + PUBLIC IRBRKS,ZORKID,ENDLOD,VOCTAB,OBJTAB,STABLE + PUBLIC GLOTAB,WRDTAB,PURBOT,ESIBKS,VWLEN,VWORDS,VOCBEG + PUBLIC OUTBUF,INBUF,RBRKS,BUFFERS,PAGES,INITTBL,SEGEND + ;ZIPBGN +IRBRKS DB " ",9,13,12,".,?",0 ;INITIAL SET OF READ BREAK CHARS +ZORKID DW 0 ;UNIQUE GAME & VERSION IDENTIFIER +ENDLOD DW 0 ;ENDLOD BLOCK NUMBER +SEGEND DW 0 ; (6) ENDLOD THAT DOESN'T GET DIDDLED +VOCTAB DW 0 ;SAVE VOCABULARY TABLE POINTER +OBJTAB DW 0 ;OBJECT TABLE POINTER +GLOTAB DW 0 ;GLOBAL TABLE POINTER +WRDTAB DW 0 ;WORD TABLE POINTER +PURBOT DW 0 ;PURE CODE POINTER +ESIBKS DW 0 ;END OF SELF-INSERTING BREAK CHARACTERS +VWLEN DW 0 ;NUMBER OF BYTES IN A VOCABULARY WORD ENTRY +VWORDS DW 0 ;NUMBER OF WORD ENTRIES IN VOCABULARY +VOCBEG DW 0 ;BEGINNING OF ACTUAL VOCABULARY +OUTBUF DB 81 DUP(?) ;OUTPUT BUFFER +INBUF DB MAXLIN+2 DUP(?) ;INPUT BUFFER +RBRKS DB 32 DUP(?) ;STRING OF READ BREAK CHARACTERS +BUFFERS DW 0 ;(6) NUMBER OF 512 BYTE BUFFERS FOR PAGING +PAGES DW 0 ;SWAPPING AREA +CHRFLG DB 0 +INITTBL DW 0FFFEH ; (A0) + DW 3 DUP (0) + +; CMDLIN WAS CREATED FOR CHANGING CERTAIN PARAMETERS ON THE COMMAND LINE +; CURRENTLY THERE ARE SWITCHES (C,M,W). BITS ARE SET IN SCANCMD AND +; PROCESSED IN SYSINI OR SSETUP. +; + PUBLIC CMDLIN,MEMORY +CMDLIN DB 0 ; (7n) 16=IBM PARALLEL PRINTER + ; (7) 8=SCROLL SET + ; (7) 4=MEMORY SET + ; (7) 2=COLOR SET + ; (7) 1=MONOCHROME SET +MEMORY DW 0 ; (7) MEMORY SIZE SET ON CMDLIN + + PUBLIC ZLOCS,ZPC1,ZPC2,ARGBLK,ZPCSEG,ZPCFLG + ;RESTRT +ZLOCS DW 0 ;POINTER TO LOCALS +ZPC1 DW 0 ;ZPC BLOCK-POINTER +ZPC2 DW 0 ;ZPC BYTE-POINTER +ZPCSEG DB 0 ;(6) GAME SEGMENT WHERE ZPC IS +ZPCFLG DB 0 ; (7n) ZPC PAGE IS MUNGED? +ARGBLK DW 9 DUP(?) ; (A0) ARGUMENT BLOCK FOR EXTENDED OPERATIONS + + PUBLIC CURPAG,CURBLK,CURTAB,CURSEG + ;NEWZPC +CURPAG DW 0 ;CURRENT PAGE (WHERE ZPC IS) POINTER +CURBLK DW 0 ;CURRENT BLOCK, USUALLY SAME AS ZPC1 +CURTAB DW 0 ;CURRENT PAGE TABLE POINTER +1 + + PUBLIC RTIME1,RTIME2,LPAGE,LPLOC,LPTAB,GAMESEG,SEG1,FITS + ;GETPAG +RTIME1 DW 0 ;(A0)REFERENCE TIME, 1 1/2 WORDS USED +RTIME2 DW 0 +LPAGE DW 0 ;LAST REFERENCED PAGE NUMBER +LPLOC DW 0 ;AND ITS CORE LOCATION +LPTAB DW 0 ;AND ITS TABLE POINTER +GAMESEG DW ? ;(6) FIRST (OR ZERO) GAME SEGMENT +SEG1 DW ? ;(6) SECOND GAMESEG (GAMESEG+64K) +CURSEG DB 0 ;(6) SEGMENT (0/1) FOR CURRENT PAGE +FITS DB 0 ;(6) FLAG FOR GAME ALL IN MEMORY + ;GETBYT +LSTGET DB 0 ; (A16) HIGH BYTE FROM LAST GETBYTE +LSTGGD DB 0 ; (A16) GOODNESS OF LAST HIGH BYTE + ;NXTBYT +LSTNXT DB 0 ; (A16) HIGH BYTE FROM LAST NXTBYT +LSTNGD DB 0 ; (A16) GOODNESS OF LAST HIGH BYTE + + ; SPLIT AND SCREEN VARS + PUBLIC SCRNFLG,SPLCOL,SPLTFLG +SCRNFLG DB 0 ; (7) WINDOW THAT WE ARE WRITING IN +SPLCOL DB 17H ; (7) GREEN BACKGROUD FOR WINDOW 1 +SPLTFLG DB 0 ; (7) IS THE SCREEN SPLIT + + ; SOUND VARIABLES +TIMER DB ? +STABLE DW SND1,SND2 ; (A0) TABLES FOR SOUNDS 1 & 2 +CLKLOW DW ? + + ;OPERATION TABLES: ;ZERO ARGUMENT OPERATIONS + PUBLIC ZEROOP,ONEOP,EXTOP +ZEROOP DW OPRTRU ;176 + DW OPRFAL ;177 + DW OPPRNI ;178 + DW OPPRNR ;179 + DW OPNOOP ;180 + DW OPSAVE ;181 + DW OPREST ;182 + DW OPRSTT ;183 + DW OPRSTA ;184 + DW OPFSTA ;185 + DW OPQUIT ;186 + DW OPCRLF ;187 + DW 0 ;188 OPUSL UNDER ZIP + DW OPVERI ;189 + DW 0 ;190 + DW 0 ;191 + ;ONE ARGUMENT OPERATIONS +ONEOP DW OPQZER ;128 + DW OPQNEX ;129 + DW OPQFIR ;130 + DW OPLOC ;131 + DW OPPTSI ;132 + DW OPINC ;133 + DW OPDEC ;134 + DW OPPRNB ;135 + DW OPCALL1 ;136 + DW OPREMO ;137 + DW OPPRND ;138 + DW OPRETU ;139 + DW OPJUMP ;140 + DW OPPRIN ;141 + DW OPVALU ;142 + DW OPBCOM ;143 + ;TWO ARGUMENT AND EXTENDED ARGUMENT OPERATIONS +EXTOP DW 0 ;0 + DW OPQEQU ;1 + DW OPQLES ;2 + DW OPQGRT ;3 + DW OPQDLE ;4 + DW OPQIGR ;5 + DW OPQIN ;6 + DW OPBTST ;7 + DW OPBOR ;8 + DW OPBAND ;9 + DW OPQFSE ;10 + DW OPFSET ;11 + DW OPFCLE ;12 + DW OPSET ;13 + DW OPMOVE ;14 + DW OPGET ;15 + DW OPGETB ;16 + DW OPGETP ;17 + DW OPGTPT ;18 + DW OPNEXT ;19 + DW OPADD ;20 + DW OPSUB ;21 + DW OPMUL ;22 + DW OPDIV ;23 + DW OPMOD ;24 + DW OPCALL2 ;25 + DW 0 ;26 + DW 0 ;27 + DW 0 ;28 + DW 0 ;29 + DW 0 ;30 + DW 0 ;31 + DW OPCALL ;224 + DW OPPUT ;225 + DW OPPUTB ;226 + DW OPPUTP ;227 + DW OPREAD + ;228 + DW OPPRNC ;229 + DW OPPRNN ;230 + DW OPRAND ;231 + DW OPPUSH ;232 + DW OPPOP ;233 + DW OPSPLT ;234 + DW OPSCRN ;235 + DW OPXCALL ;236 + DW OPCLEAR ;237 + DW OPERASE ;238 + DW OPCURST ;239 + DW OPCURGT ;240 + DW OPHILIT ;241 + DW OPBFOUT ;242 + DW OPDIROU ;243 + DW OPDIRIN ;244 + DW OPSND ;245 + DW OPINPUT ;246 + DW OPINTBL ;247 (A12) + DW 0 ;248 + DW 0 ;249 + DW 0 ;250 + DW 0 ;251 + DW 0 ;252 + DW 0 ;253 + DW 0 ;254 + DW 0 ;255 + + ;(7) COPY PROTECTION STUFF + PUBLIC COMPATS,COMP1,IBMSTR +COMPATS DW 3 ; (7) NUMBER OF STRINGS IN THE LIST +COMP1 DB 'COMPAQ Co$' +IBMSTR DB 'COPR. IBM$' ; (7) EACH STRING MUST BE 9 CHARS + DB 'Tandy Cor$' ; (7v) ADD TANDY + + ;(A9) ENVIORNMENT +IBMPC DB 0 ; (A9) 1=IBMPC + + ;MCRLF + PUBLIC SCROLL,TOPLIN,MORLIN + ; (7) SCROLL IS SEEMINGLY BACKWARDS BUT TOO INTERWOVEN TO + ; GO AROUND AND FIX NOW. + ; 0 = IBM Compatible 100% (use windowed scrolling) + ; 1 = MS-DOS, no windowed scrolling + ; +SCROLL DB 1 +TOPSCR DW 0 +TOPLIN DW 0 ; (7) WORD FOR CH,CL FOR UPPER RIGHT +MORE DB "[MORE]",80H ; (A12) +EMORE DB 13," ",13,80H +MORLIN DW 0 ; (7) COUNT OF LINES SCROLLED WITHOUT PAUSE + + ;STRUCTURE AND RECORD DEFINITIONS: + ;OBJECT OPERATIONS +OBJECT STRUC +FLAGS1 DW ? +FLAGS2 DW ? +FLAGS3 DW ? ; (A0) EZIP EXTENDED FLAG WORD +PARENT DW ? ; (A0) EXTEND TO WORD +SIBLING DW ? ; (A0) EXTEND TO WORD +CHILD1 DW ? ; (A0) AGAIN^^ +PROPS DW ? +OBJECT ENDS +PROPID RECORD PROPNUM:6 + + ;STRING DEFINITIONS + + ;STATION IDENTIFICATION + ; (A10) TWO DIGIT MINOR VERSION NUMBER + PUBLIC IDSTR +IDSTR DB 80H ; PATCH OUT THIS BYTE FOR TESTING + DB "IBM/PC-DOS 2.0 Interpreter Version ",ZVERSN,ZEDIT0,ZEDIT1,0 + + ;TERMINAL SETUP +WANTCO DB "Do you want color (Y/N)? ",80H + + PUBLIC SAV0,SAV1,SAV2,SAV3,ERR1,ERR2,ERR3,ERR4,ERR5,ERR6 + ;SAVE/RESTORE +SAV0 DB "Insert save disk then enter file name.",0 +SAV1 DB "(Default is ",80H +SAV2 DB "): ",80H +SAV3 DB "Insert game disk then strike any key to continue.",0 + +ERR1 DB "SAVE file not found",0 +ERR3 DB "Bad file name syntax",0 +ERR4 DB "Unable to access file",0 +ERR5 DB "No room on diskette for SAVE file",0 +ERR6 DB "Read of SAVE file failed",0 + ;READ +ERR2 DB "Too many words typed, discarding: ",80H + + PUBLIC FTL2,FTL4,FTL5,FTL6,FTL7,FTL9 + ;OPNEXT/OPPUTP +FTL2 DB "No such property",0 + ;ZIPBGN +FTL4 DB "Wrong game or version",0 + ;NXTINS +FTL5 DB "Illegal operation",0 + ;FINDPG +FTL6 DB "No free pages",0 + ;GTBLKS +FTL7 DB "Game file read error",0 + ;SYSINI +FTL9 DB "Game file not found",0 +FTL10 DB 'Unauthorized copy',0 +FTL11 DB 'Wrong DOS version. Must be 2.0 or higher',0 +FTL12 DB 'Insufficient memory to play game',0 +FTL13 DB 'Illegal argument',0 +FTL14 DB 'Screen must be 80 characters wide',0 + + ;Fatal error header +FATHDR DB "Fatal error: ",80H + ;ZSTR CHARACTER CONVERSION VECTOR + + PUBLIC ZCHRS +ZCHRS DB "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + DB " 0123456789.,!?_#'" + DB '"/\-:()' + + PUBLIC STK_TOP,STKBOT,ZSTK_TP +; STACK SETUP + DW 200H DUP(?) +STK_TOP LABEL WORD +STKBOT DW LSTACK DUP(?) +ZSTK_TP LABEL WORD diff --git a/ibm/dip.asm b/ibm/dip.asm new file mode 100644 index 0000000..19e3966 --- /dev/null +++ b/ibm/dip.asm @@ -0,0 +1,7568 @@ + TITLE DIP/8086 + PAGE 58,132 + .LIST + + ;---------------------------------------------------------------------- + ; DIP/8086 Version 1.0 + ; D-CODE INTERPRETER PROGRAM + ; FOR IBM-PC UNDER MS-DOS + ;---------------------------------------------------------------------- + + ; INFOCOM, INC. + ; 125 CAMBRIDGE PARK DRIVE + ; CAMBRIDGE, MA 02140 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + + ;---------------------------------------------------------------------- + ; M O D I F I C A T I O N H I S T O R Y + ;---------------------------------------------------------------------- + ; Date | Programer | Description + ;---------------------------------------------------------------------- +DEBUG EQU 0 +GMAJOR EQU 'C' +GMINOR EQU 0 + + ; C PHG RENAMED GAME.DAT TO FOOBLITZ.DAT ... RELEASE VERSION + ; + ; B7 PHG FIXED SPEED-UP IN DRAW FOR LOW MEMORY. + ; + ; B6 PHG FIXED EYE-DROPPER (SEG CROSS IN GTGFST) AND VERIFY. + ; PATCHES ARE STILL B5 + ; B5 PHG SECOND ROUND OF SPEED UP -- DRAW LOOP + ; + ; B4 PHG SPEED-UP: AFTER NARROWING DOWN PROBLEMS TO SPECIFIC + ; AREAS OF CODE, OPTIMIZATION WAS ATTEMPTED + ; + ; B3 PHG ADDED TRACE TRAP (CONDITIONAL ASSEMBLY) TO FIND + ; OUT WHERE THIS THING WASTES THE MOST TIME + ; + ; 9/09/85 | PHG | ADDED SAVE AND RESTORE (W/STACK AND + ; | I-FILE IN SAVE) AND VERIFY + ; 8/29/85 | PHG | FIXED PAGING BUG AND ENHANCED + ; 7/18/85 | PHG | ADDED SUPPORT FOR NO GAME PORT + ; | ADAPTER + ; 6/5/85 | R. LAY | MODIFIED {GINPUT} TO ACCEPT EITHER + ; | | KRAFT JOYSTICK BUTTON + ; 5/28/85 | R. LAY | IMPLIMENTED {LOAD} AND {DUMP} + ; 5/15/85 | R. LAY | MODIFIED {SENSE} AND SOUND ROUTINES + ; | | FOR IBM AT COMPATABILITY + ; 5/1/85 | R. LAY | 128K VERSION COMPLETE + ; 3/4/85 | R. LAY | 64K VERSION FROZEN. START OF 128K. + ; 12/31/84 | R. LAY | START 64K VERSION, NO PAGING. + + SUBTTL NOTES + PAGE + ;---------------------------------------------------------------------- + ; + ; I M P L E M E N T A T I O N N O T E S + ; + ;---------------------------------------------------------------------- + +; +; VIRTUAL MEMORY ALLOCATION +; + +; Virtual memory exists as a Data File on the game disk. Although two +; data files are created by the implimentor: GFILE.DAT and IFILE.DAT, +; (usually named filename.DIP and filename.PIC) these are concantenated +; while in the DOS command mode by issuing the command: +; CONCAT0 filename, if GFILE.DAT (or filename.DIP) file size is even +; CONCAT1 filename if GFILE.DAT file size is odd. +; +; Note that this scheme allows for easy inclusion of new data files through the +; use of the batch facilities. There is one caution: the filename portion of +; the data files must be the same. This may be accomplished by renaming one or +; both of the files or avoided by modifing the batch files. +; +; Each of the original data files consist of two parts: Preload and Pureload. +; For documentation purposes, these are called GPRE, GPURE, IPRE, and IPURE. +; + + SUBTTL EQUATES + PAGE + ;---------------------------------------------------------------------- + ; E Q U A T E S + ;---------------------------------------------------------------------- + + ; ----------- + ; 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) + ; 0A -- DISK ACCESS RANGE + ; 0B -- DISK ACCESS + ; 0C -- NO CALL ADDRESS + ; 0D -- UNDEFINED SOUND + ; 0E -- PURITY VIOLATION (SETI/SWAPI) + ; 0F -- ACTIVE ICON TABLE OVERFLOW + + ; -------------- + ; COMMON EQUATES + ; -------------- + +FALSE EQU 0 ;STANDARD VALUES +TRUE EQU 0FFH +LO EQU 0 +HI EQU 1 + + ; ----------------------- + ; FILE CONTROL STRUCTURES + ; ----------------------- + +RECSIZ EQU 512 ;512 BYTES/RECORD + + ; ---------------------------- + ; MS-DOS INT 21 FUNCTION CALLS + ; ---------------------------- + +CRESET EQU 0H ;PROGRAM TERMINATE +CCONIN EQU 1H ;WAIT FOR CONSOLE INPUT WITH ECHO +CPROUT EQU 5H ;PRINTER OUTPUT +CCONIO EQU 6H ;CONSOLE INPUT NO ECHO NO WAIT +CNOECHO EQU 7H ;INPUT NO ECHO +CRDLIN EQU 0AH ;CONSOLE LINE INPUT +CDRESET EQU 0DH ;DISK RESET +CFCREAZ EQU 3CH ;CREATE FILE +CFOPENZ EQU 3DH ;OPEN FILE +CFCLOSZ EQU 3EH ;CLOSE FILE +CRDRNDZ EQU 3FH ;READ RANDOM RECORD +CWRRNDZ EQU 40H ;WRITE RANDOM RECORD +CFDELEZ EQU 41H ;DELETE FILE +CFSEEK EQU 42H ;SEEK +CSETBLK EQU 4AH +CSELDSK EQU 0EH ; SELECT DISK +CURDSK EQU 19H + + ; ----------------- + ; MEMORY ALLOCATION + ; ----------------- + +LSTACK EQU 512 ;SIZE OF THE GSTACK AND MACHINE STACK IN BYTES +LMOUTB EQU 80 ;MAX LENGTH OF OUTBUF, EXCLUDING TERMINAL 0 +LDOUTB EQU 80 ;DEFAULT LENGTH OF OUTBUF + + ; --------------------- + ; G-CODE HEADER OFFSETS + ; --------------------- + +GHEADER EQU 64 ; LENGTH OF G-FILE HEADER IN BYTES +GVERS EQU 0 ; (BYTE) G-MACHINE VERSION +GMODE EQU 1 ; (BYTE) MODE BYTE +GID EQU 2 ; (WORD) GAME ID +GEND EQU 4 ; (WORDPTR) BEGINNING OF NON-PRELOADED CODE +GSTART EQU 6 ; (WORDPTR ODD) EXECUTION START ADDRESS +GPUR EQU 8 ; (WORDPTR) BEGINNING OF PURE G-CODE +GGLOB EQU 10 ; (WORDPTR) START OF GLOBAL VARIABLE TABLE +GSER EQU 12 ; (6 BYTES) ASCII SERIAL NUMBER +GLEN EQU 18 ; (WORD) LENGTH OF G-PROGRAM IN WORDS +GCHECK EQU 20 ; (WORD) G-CODE CHECKSUM +GINTVER EQU 22 ; INTERPRETER VERSION LETTER AND NUMBER + + ; --------------------- + ; I-FILE HEADER OFFSETS + ; --------------------- + +IHEADER EQU 8 ; LENGTH OF I-FILE HEADER IN BYTES +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 + + ; --------------- + ; GENERAL EQUATES + ; --------------- + +ATTIME EQU 004FH ; TIME STANDARD FOR "FAST" PROCESSOR +NSNDS EQU 4 ; THERE ARE FOUR SOUND EFFECTS +JIFCNT EQU 800H ; NUMBER USED TO COMPENSATE DELAY FOR IBM AT'S +VID_SG EQU 0B800H ; VIDEO MEMORY LOCATION +BIOSDATA EQU 40H ; BIOS DATA AREA SEG +KB_FLAG EQU 17H ; BIOS DATA AREA OFFSET TO KEY FLAGS +NUMLOCK EQU 20H ; NUMLOCK BIT +BIOS EQU 0F000H ; BIOS SEGMENT +BIOSOFF EQU 0E000H ; BIOS OFFSET +ID_OFF EQU 0FFFEH ; OFFSET IN BIOS TO MACHINE ID +JR_ID EQU 0FDH ; ID BYTE FOR PCjr +DOSVER EQU 30H ; GET DOS VERSION NUMBER + + + + + SUBTTL MAIN PROGRAM + PAGE + ;---------------------------------------------------------------------- + ; M A I N P R O G R A M + ;---------------------------------------------------------------------- +IF1 %OUT PASS1 +ELSEIF %OUT PASS2 +ENDIF +CSEG SEGMENT PARA PUBLIC + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG + ORG 100H +; + PUBLIC MSDIP +MSDIP PROC + JMP START ;SKIP OVER DIP DATA + + SUBTTL DATA DEFINITIONS + PAGE + ;--------------------------------------------------------------------- + ; D A T A D E F I N I T I O N S + ;--------------------------------------------------------------------- + + ; --------------- + ; TRADITIONAL I/0 + ; --------------- + + ; FILE CONTROL STRUCTURES +GAMFILE DB 'FOOBLITZ.DAT',0 ;ACIIZ FILE NAME DEFAULT DRIVE + DB 49 DUP (0) ;POTENTIAL LENGTH OF FILENAME +GAMHNDL DW 0 ;GAME FILE HANDLE + +DATFILE DB 'GAME.SAV',0 ; ASCIIZ FILE NAME + DB 53 DUP (0) ;POTENTIAL LENGTH OF FILENAME, NO DEFAULT +DATHNDL DW 0 ;GAME FILE HANDLE + +LASTSAV DB 'GAME.SAV',0 ; ASCIIZ FILE NAME + DB 53 DUP (0) ;POTENTIAL LENGTH OF FILENAME, NO DEFAULT + +NAMBUF DB 20 DUP (0) ;FILE NAME BUFFER + ; DRIVE STUFF +LASTDRV DB ? ; LAST LOGGED DRIVE +DSKDIR DB -1 ; SAVE OR RESTORE? +LSTDFLG DB ? ; LAST DRIVE FLAG +DEFDRV DB 0 ; DEFAULT (ORIGINAL) DRIVE +DRVFLG DB 0 ; USER SPECIFIED DRIVE? +CURDRV DB 0 ; WHERE WE ARE LOGGED CURRENTLY +SKPDRV DB 0 ; SKIP DRIVE PRINT OUT + ; KEYBOARD HANDLING +KYFLGS DB ? ; ORIGINAL KEYBOARD FLAGS +XLKEY DB 37H,38H,39H,0,34H,0,36H,0,31H,32H,33H + ;MESSAGES +ERRTAB DW OFFSET FERR0 + DW OFFSET FERR1 + DW OFFSET FERR2 + DW OFFSET FERR3 + DW OFFSET FERR4 + DW OFFSET FERR5 + DW OFFSET FERR6 + DW OFFSET FERR7 + DW OFFSET FERR8 + DW OFFSET FERR9 + DW OFFSET FERR10 + DW OFFSET FERR11 + DW OFFSET FERR12 + DW OFFSET FERR13 + DW OFFSET FERR14 + DW OFFSET FERR15 + DW OFFSET FERR16 + DW OFFSET FERR17 + DW OFFSET FERR18 + +; +FERR0 DB 20,"GAME PRELOAD TOO BIG$" +FERR1 DB 21,"IMAGE PRELOAD TOO BIG$" +FERR2 DB 14,"UNDEFINED X-OP$" +FERR3 DB 14,"UNDEFINED 0-OP$" +FERR4 DB 14,"UNDEFINED 1-OP$" +FERR5 DB 14,"UNDEFINED 2-OP$" +FERR6 DB 17,"G-STACK UNDERFLOW$" +FERR7 DB 16,"G-STACK OVERFLOW$" +FERR8 DB 16,"DIVISION BY ZERO$" +FERR9 DB 23,"PURITY VIOLATION (PUTB)$" +FERR10 DB 18,"LSEEK OUT OF RANGE$" +FERR11 DB 19,"GAME FILE NOT FOUND$" +FERR12 DB 15,"NO CALL ADDRESS$" +FERR13 DB 15,"UNDEFINED SOUND$" +FERR14 DB 23,"PURITY VIOLATION (SETI)$" +FERR15 DB 27,"ACTIVE ICON TABLE OVERFLOW$" +FERR16 DB 25,"CANNOT SET GRAPHICS MODE$" +FERR17 DB 21,"INCORRECT DOS VERSION$" +FERR18 DB 24,"INVALID GAME OR VERSION$" +; +ERRM DB 13,"FATAL ERROR: $" +XITMSG DB " END OF SESSION $" +SAV0 DB " Insert SAVE disk then enter file name.$" +SAV1 DB " (Default is $" +SAV2 DB "): $" +SAV3 DB " Insert game disk then strike any key to continue.$" +ERR1 DB " SAVE file not found$" +ERR4 DB " Unable to access SAVE file$" +ERR5 DB " No room on diskette for SAVE file$" +ERR6 DB " Read of SAVE file failed$" +WAITSTR DB " The game is loading,",13,10 + DB " please wait...$" +STRIKE DB " Strike any key to continue...$" + + ; I/O BUFFERS + PUBLIC OUTBUF,INBUF,XFRBUF +OUTBUF DB 40 DUP(?) ;OUTPUT BUFFER +INBUF DB 80 DUP(?) ;INPUT BUFFER +XFRBUF DB RECSIZ DUP (?) ;TRANSFER BUFFER USED BY {LOAD} AND {SAVE} + + ; SPECIAL CONTROL + PUBLIC IBMAT,DLYCNT,TIMER +PRTOFF DW ? ; (B5) PRINT SCREEN ENTRY POINTS +PRTSEG DW ? +PCJR DB 0 ; JR FLAG FOR TIMING +IBMSTR DB "COPR. IBM$" ; IBM IDENTIFICATION STRING +IBMAT DB (?) ;IS THIS AN IBM AT (TRUE OR FALSE)? +DLYCNT DW (?) ;DELAY REQUEST IN 1/10 SEC +TIMER DB (?) ;1/100 SEC COUNT FROM REAL TIME CLOCK + ; USED IN DETERMINING 1/10 SEC DELAY +IF DEBUG + public itrcnt +itrcnt dw 2 dup (0) + public ipcount +ipcount dd 256 dup (0) ;pc position count -trace trap + public isavecs,ishift,ioffset,itop +isavecs dw 0 ;saved code seg paragraph +itrapcs dw 0 +ishift dw 0 ;4 ;8 ;3 +ioffset dw 0 ;mloop ;0 ;mloop +itop dw OFFSET MEMBUF ;imend ;-1 ;imend +t_out db 'tracer.out',0 +; +; +ENDIF + + PAGE + ; ----------------------- + ; OP-CODE DISPATCH TABLES + ; ----------------------- + + ; 0-OP DISPATCH TABLE +OPT0 DW GNOOP ; B0 + DW GRTRUE ; B1 + DW GRFALS ; B2 + DW GRSTAK ; B3 + DW GFSTAK ; B4 + DW GQUIT ; B5 + DW GCOPYP ; B6 + DW GVERP ; B7 + +NOPS0 EQU ($-OPT0)/2 ; # OF VALID 0-OPS + + ; 1-OP DISPATCH TABLE +OPT1 DW GPUSH ; 80 + DW GPOP ; 81 + DW GVALUE ; 82 + DW GINC ; 83 + DW GDEC ; 84 + DW GZEROP ; 85 + DW GBNOT ; 86 + DW GJUMP ; 87 + DW GRET ; 88 + +NOPS1 EQU ($-OPT1)/2 ; # OF 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 ; A + DW GLESSP ; B + DW GDLESP ; C + DW GGRTRP ; D + DW GIGRTP ; E + DW GSET ; F + DW GGET ; 10 + DW GGETB ; 11 + +NOPS2 EQU ($-OPT2)/2 ; # VALID 2-OPS + + ; X-OP DISPATCH TABLE +OPTX DW GCALL ; E0 + DW GPUT ; E1 + DW GPUTB ; E2 + DW GINPUT ; E3 + DW GSHOWI ; E4 + DW GSETI ; E5 + DW GSWAPI ; E6 + DW GSOUND ; E7 + DW GRAND ; E8 + DW GCLEAR ; E9 + DW GSHOWN ; EA + DW GWIND ; EB + DW GITER ; EC + DW GLOAD ; ED + DW GDUMP ; EE + DW GRESTR ; EF + DW GSAVE ; F0 + +NOPSX EQU ($-OPTX)/2 ; # VALID X-OPS + + PAGE + ; ----------------- + ; PROGRAM VARIABLES + ; ----------------- + + ; GCODE PROGRAM COUNTER DEFINITION + PUBLIC GPC,GPC2,GPC1,GPC0 +GPC LABEL WORD +GPC2 DB 0 ;LSB OF GPC +GPC1 DB 0 ;MSB OF GPC +GPC0 DB 0 ;BIT 0 OF BYTE IS BIT 0 OF GPC + + ; VIRTUAL MEMORY POINTER DEFINITION + PUBLIC VMP,VMP2,VMP1,VMP0,VMSAV,VMSAV0 +VMP LABEL WORD +VMP2 DB 0 ;LSB OF VMP +VMP1 DB 0 ;MSB OF VMP +VMP0 DB 0 ;BIT 0 OF BYTE IS BIT 0 OF VMP + +VMSAV DW 0 +VMSAV0 DB 0 + + ; VALUES USED IN COLDSTART + PUBLIC GPRBLK,IPRBLK,GCODE,GPEND,ICODE,ISTRT,IPURE,ZORKID +GPRBLK DB 0 ;TOTAL NUMBER OF G-PRELOAD BLOCKS +IPRBLK DB 0 ;TOTAL NUMBER OF I-PRELOAD BLOCKS + +GCODE DW 0 ;(WORD) VIRTUAL START ADDRESS OF G-CODE +GPEND DB 0 ;(BYTE) LAST VIRTUAL BLOCK OF G-PRELOAD +ICODE DW 0 ;(WORD) ABSOLUTE START ADDRESS OF I-PRELOAD +ISTRT DB 0 ;(BYTE) 1ST. V-PAGE OF I-PRELOAD +IPURE DW 0 ;(WORD) ABSOLUTE START ADDRESS OF I-PURELOAD +ZORKID DW ? ; GAME ID + + ; TABLE ADDRESSES + PUBLIC GLOCS,GLOBAL +GLOCS DW 0 ;OFFSET TO THE START OF THE DIP LOCAL TABLE +GLOBAL DW 0 ;(WORD) ABSOLUTE GLOBAL TABLE ADDR + + ; OPCODE SUPPORT + PUBLIC NARGS,ARG1,ABYTE,ADEX +NARGS DB 0 ;(BYTE) CURRENT NUMBER OF ARGUMENTS +ARG1 DW 0 ;(WORD) ARGUMENT 1 REGISTER +ARG2 DW 0 ;(WORD) ARGUMENT 2 REGISTER +ARG3 DW 0 ;(WORD) ARGUMENT 3 REGISTER +ARG4 DW 0 ;(WORD) ARGUMENT 4 REGISTER +ABYTE DB 0 ;(BYTE) X-OP ARGUMENT BYTE +ADEX DB 0 ;(BYTE) X-OP ARGUMENT INDEX +ADEX2 DB 0 ;(BYTE) "CALL" ARG-BYTE INDEX + + PUBLIC CTYPES,CARGS +CTYPES DB 16 DUP(?) ;GCALL 'MODE BYTE' LIST +CARGS DW 16 DUP(?) ;GCALL ARGUMENTS LIST + + PUBLIC OPCODE,VALUE,I,J,OLDGSP +OPCODE DB 0 ;(BYTE) OPCODE SAVE REGISTER +VALUE DW 0 ;(WORD) VALUE RETURN REGISTER +I DW 0 ;(WORD) GENERAL PURPOSE INDEX REGISTER #1 +J DW 0 ;(WORD) GENERAL PURPOSE INDEX REGISTER #2 + +OLDGSP DW 0 ;(WORD) OLD G-STACK POINTER + + ; RANDOM +RSEED1 DW 0 ;VARIABLES USED FOR RANDOM NUMBER GENERATION +RSEED2 DW 0 +RTEMP DW 0 + + ; INPUT CONTROL + PUBLIC STICKA,KEYSAV,JOYSTK +STICKA DB 0 ;JOYSTICK FLAGS BYTE +KEYSAV DB 0 ;SENSE RETURN CODE +JOYSTK DB 0 ;JOYSTICK PRESENCE + + ; SOUND CONTROL STRUCTURES +STABLE DW SND1,SND2,SND3,SND4 + + PAGE + ; --------------------------- + ; GRAPHICS CONTROL STRUCTURES + ; --------------------------- + + ; TABLE ADDRRESSES + PUBLIC BTAB,ITAB +BTAB DW 0 ;(WORD) ABSOLUTE BLOCKSET TABLE ADDRESS +ITAB DW 0 ;(WORD) ABSOLUTE ICON TABLE ADDRESS + + ; ICON DATA + PUBLIC NBLOKS,NICONS,IADR1,IADR10,IX1,IY1,XDEX1,YDEX1,BSET +NBLOKS DB 0 ;(BYTE) # BLOCKSETS IN I-FILE +NICONS DB 0 ;(BYTE) # ICONS IN I-FILE + +IADR1 DW 0 ;(WORD) ABS ADDR OF ICON #1 +IADR10 DB 0 ;(BYTE) LS BIT OF ABS ADDR OF ICON #1 + +IADR2 DW 0 ;(WORD) ABS ADDR OF ICON #2 +IADR20 DB 0 ;(BYTE) LS BIT OF ABS ADDR OF ICON #2 + +IX1 DB 0 ;(BYTE) XSIZE OF ICON #1 +IX2 DB 0 ;(BYTE) XSIZE OF ICON #2 +IY1 DB 0 ;(BYTE) YSIZE OF ICON #1 +IY2 DB 0 ;(BYTE) YSIZE OF ICON #2 +XDEX1 DB 0 ;(BYTE) X-INDEX #1 +XDEX2 DB 0 ;(BYTE) X-INDEX #2 +YDEX1 DB 0 ;(BYTE) Y-INDEX #1 +YDEX2 DB 0 ;(BYTE) Y-INDEX #2 +BSET DB 0 ;(BYTE) BLOCKSET ID (1-255) +BSADR DW 0 ;(WORD) ABS ADDR OF CURRENT BLOCKSET +BSIZE DB 0 ;(BYTE) # BLOCKS IN CURRENT BLOCKSET +TOX DB 0 ;(BYTE) X-SAVE FOR "DUMP" +BLOCK DB 8 DUP (?) ;(8 BYTES) IMAGE BLOCK BUFFER + PUBLIC BLOCK,I_EOP,G_EOP +I_EOP DW ? ; (B5) ICON END OF PAGE +G_EOP DW ? ; (B5) GRAPHICS EOP + + ; MASKING + PUBLIC MSKFLG,MBLOCK +MBLOCK DB 8 DUP (?) ;(8 BYTES) MASK BLOCK BUFFER +MSKFLG DB 0 ;(BYTE) FLAG FOR MASKING 00=DISABLED + + + PUBLIC NEGATE,BLKLEN,XPSAV +XPSAV DW 0 ;(WORD) X-POSITION SAVE +XCURS DB 0 ;(BYTE) GAME CURSOR X-POS +YCURS DB 0 ;(BYTE) GAME CURSOR Y-POS +NEGATE DB 0 ;(BYTE) BLOCK NEGATE FLAG +BLKLEN DB 0 ;(BYTE) # BLOCKS PER BLOCK + + ; ITERATIONS +ITERS DB 0 ;(BYTE) # OF ICON ITERATIONS +DOITER DB 0 ;(BYTE) CURRENT ITERATION +ITPNT DB 0 ;(BYTE) POINTER INTO CURRENT ICON TABLE +NAICN DB 0 ;(BYTE) NUMBER OF ACTIVE ICONS +ITICN DB 0 ;(BYTE) COUNTER FOR ITERATE ROUTINE + + + ; WINDOWS + PUBLIC XPOS,YPOS +XPOS DW 0 ;(WORD) ICON X-POSITION +YPOS DW 0 ;(WORD) ICON Y-POSITION + +WINDX1 DB 0 ;(BYTE) LEFT CLIP VALUE +WINDX2 DB 0 ;(BYTE) RIGHT CLIP VALUE +WINDY1 DB 0 ;(BYTE) TOP CLIP VALUE +WINDY2 DB 0 ;(BYTE) BOTTOM CLIP VALUE + +TOPCUT DB 0 +SIDCUT DB 0 +MDXCUT DB 0 +WINDH DB 0 +WINDW DB 0 +IXSKIP DB 0 + + PUBLIC VDPADR +VDPADR DW 0 ;OFFSET INTO VIDEO RAM + + PAGE +; +; This table is used to translate a Byte of graphics data into a Word of +; IBM graphics data. +; +; The IBM has a screen composed of 320 x 200 pixels. For the sake of +; convenience we use only 320 x 192. In Graphics Mode 4, the IBM utilizes +; 2 Bits/pixel. +; +; BIT 7 6 5 4 3 2 1 0 +; _____________________________________ +; | C1 C0 | C1 C0 | C1 C0 | C1 C0 | +; +--------+--------+--------+--------+ +; +; With the color pallete and background color we've selected, eack Bit pair +; can represent 1 of 4 possible colors. +; +; C1 | C0 | COLOR +; ---+----+----------- +; 0 | 0 | BLACK +; 0 | 1 | CYAN +; 1 | 0 | MAGENTA +; 1 | 1 | WHITE +; +; Since the IBM has twice the horizontal resolution of the GRAPHIC DATA, we +; have to double each pixel. This causes the loss of cyan and magenta. +; Since the GRAPHIC DATA achieves color through archiving, the following +; scheme suffices. +; +; Given: A Byte of graphics data representing 8 pixels eg.: +; +; 00011011B (01BH) +; +; BIT 7 6 5 4 3 2 1 0 +; 0 0 0 1 1 0 1 1 +; PIXEL 1 2 3 4 5 6 7 8 +; +; Becomes a Word of IBM graphics data representing 8 pixels eg.: +; +; 00000011 11001111B (03CFH) +; +; BIT F E | D C | B A | 9 8 | 7 6 | 5 4 | 3 2 | 1 0 +; 0 0 | 0 0 | 0 0 | 1 1 | 1 1 | 0 0 | 1 1 | 1 1 +; PIXEL 1 2 3 4 5 6 7 8 +; +; +; Because all color is produced by artifacting, and the ATARI effect is +; different than the IBM we also right shift the word around 2 bits in +; advance for phase shifting purposes +; + PAGE +; GRAPHICS TRANSLATION TABLE + PUBLIC GRXTBL +GRXTBL DW 0000H,0C000H,0003H,0C003H + DW 000CH,0C00CH,000FH,0C00FH + DW 0030H,0C030H,0033H,0C033H + DW 003CH,0C03CH,003FH,0C03FH + + DW 00C0H,0C0C0H,00C3H,0C0C3H + DW 00CCH,0C0CCH,00CFH,0C0CFH + DW 00F0H,0C0F0H,00F3H,0C0F3H + DW 00FCH,0C0FCH,00FFH,0C0FFH + + DW 0300H,0C300H,0303H,0C303H + DW 030CH,0C30CH,030FH,0C30FH + DW 0330H,0C330H,0333H,0C333H + DW 033CH,0C33CH,033FH,0C33FH + + DW 03C0H,0C3C0H,03C3H,0C3C3H + DW 03CCH,0C3CCH,03CFH,0C3CFH + DW 03F0H,0C3F0H,03F3H,0C3F3H + DW 03FCH,0C3FCH,03FFH,0C3FFH + + DW 0C00H,0CC00H,0C03H,0CC03H + DW 0C0CH,0CC0CH,0C0FH,0CC0FH + DW 0C30H,0CC30H,0C33H,0CC33H + DW 0C3CH,0CC3CH,0C3FH,0CC3FH + + DW 0CC0H,0CCC0H,0CC3H,0CCC3H + DW 0CCCH,0CCCCH,0CCFH,0CCCFH + DW 0CF0H,0CCF0H,0CF3H,0CCF3H + DW 0CFCH,0CCFCH,0CFFH,0CCFFH + + DW 0F00H,0CF00H,0F03H,0CF03H + DW 0F0CH,0CF0CH,0F0FH,0CF0FH + DW 0F30H,0CF30H,0F33H,0CF33H + DW 0F3CH,0CF3CH,0F3FH,0CF3FH + + DW 0FC0H,0CFC0H,0FC3H,0CFC3H + DW 0FCCH,0CFCCH,0FCFH,0CFCFH + DW 0FF0H,0CFF0H,0FF3H,0CFF3H + DW 0FFCH,0CFFCH,0FFFH,0CFFFH + + DW 3000H,0F000H,3003H,0F003H + DW 300CH,0F00CH,300FH,0F00FH + DW 3030H,0F030H,3033H,0F033H + DW 303CH,0F03CH,303FH,0F03FH + + DW 30C0H,0F0C0H,30C3H,0F0C3H + DW 30CCH,0F0CCH,30CFH,0F0CFH + DW 30F0H,0F0F0H,30F3H,0F0F3H + DW 30FCH,0F0FCH,30FFH,0F0FFH + + DW 3300H,0F300H,3303H,0F303H + DW 330CH,0F30CH,330FH,0F30FH + DW 3330H,0F330H,3333H,0F333H + DW 333CH,0F33CH,333FH,0F33FH + + DW 33C0H,0F3C0H,33C3H,0F3C3H + DW 33CCH,0F3CCH,33CFH,0F3CFH + DW 33F0H,0F3F0H,33F3H,0F3F3H + DW 33FCH,0F3FCH,33FFH,0F3FFH + + DW 3C00H,0FC00H,3C03H,0FC03H + DW 3C0CH,0FC0CH,3C0FH,0FC0FH + DW 3C30H,0FC30H,3C33H,0FC33H + DW 3C3CH,0FC3CH,3C3FH,0FC3FH + + DW 3CC0H,0FCC0H,3CC3H,0FCC3H + DW 3CCCH,0FCCCH,3CCFH,0FCCFH + DW 3CF0H,0FCF0H,3CF3H,0FCF3H + DW 3CFCH,0FCFCH,3CFFH,0FCFFH + + DW 3F00H,0FF00H,3F03H,0FF03H + DW 3F0CH,0FF0CH,3F0FH,0FF0FH + DW 3F30H,0FF30H,3F33H,0FF33H + DW 3F3CH,0FF3CH,3F3FH,0FF3FH + + DW 3FC0H,0FFC0H,3FC3H,0FFC3H + DW 3FCCH,0FFCCH,3FCFH,0FFCFH + DW 3FF0H,0FFF0H,3FF3H,0FFF3H + DW 3FFCH,0FFFCH,3FFFH,0FFFFH + + PAGE +; +; Y-AXIS TRANSLATION TABLE +; + +; This table is used to translate the starting row location (0-23) of +; a BLOCK to an offset from the VIDEO_RAM base address. + PUBLIC YAXTBL +; Y Axis (X)translation TaBLe +YAXTBL DW 1FB0H,20F0H,2230H,2370H + DW 24B0H,25F0H,2730H,2870H + DW 29B0H,2AF0H,2C30H,2D70H + DW 2EB0H,2FF0H,3130H,3270H + DW 33B0H,34F0H,3630H,3770H + DW 38B0H,39F0H,3B30H,3C70H + + PAGE + ; ------------------------- + ; PAGING CONTROL STRUCTURES + ; ------------------------- + PUBLIC FSIZE,BUFFERS,SEG0,SEG1,BUF,LRU,LOC,LADD,VPAGEN,OLDMRU,MEMMAP +FSIZE DB 0 ;NUMBER OF 512 BYTE BLOCKS IN GAME.DAT FILE +BUFFERS DB 0 ;NUMBER OF 512 BYTE BLOCKS IN PAGING AREA +SEG0 DW ? ;FIRST (OR ZERO) GAME SEGMENT +SEG1 DW ? ;SECOND GAME SEGMENT (SEG0 + 64K) +BUF DB 0 ;INDEX INTO MEMBUF +LRU DB 0 ;LEAST RECENTLY USED PAGE +LOC DB 0 ;HIGH ORDER ABSOLUTE ADDRESS BITS +LADD DW 0 ;LOW ORDER ABSOLUTE ADDRESS BITS +VPAGEN DB 0 ;VIRTUAL PAGE NUMBER +OLDMRU DB 0 ;PREVIOUS MRU BUFFER NUMBER +MEMMAP DB 512 DUP(?) ;PAGING MEMORY MAP + + + ; ----------------- + ; STACK DEFINITIONS + ; ----------------- + PUBLIC MSTK_TP,MSTK_BT,GSTK_TP,GSTK_BT +EVEN +MSTK_BT DW LSTACK DUP(?) ;MACHINE STACK BOTTOM +MSTK_TP LABEL WORD ;MACHINE STACK TOP + +GSTK_BT DW LSTACK DUP(?) ;G-CODE INTERPRETER STACK BOTTOM +GSTK_TP LABEL WORD ;G-CODE INTERPRETER STACK TOP + +%OUT CODE + + SUBTTL SYSTEM INITIALIZATION + PAGE + ;---------------------------------------------------------------------- + ; S Y S T E M I N I T I A L I Z A T I O N + ;---------------------------------------------------------------------- + + PUBLIC START +START: MOV SP,OFFSET MSTK_TP ;SETUP STACK PTR (SP) + MOV DI,OFFSET GSTK_TP ;SETUP GSTACK PTR (DI) + + ; JUMP TO BEGINNING OF DIP + JMP DIPBGN + + SUBTTL 0-OP EXECUTORS + PAGE + ;---------------------------------------------------------------------- + ; S U B R O U T I N E S + ;---------------------------------------------------------------------- + + ;--------------------------------------- + ; OPCODE EXECUTION PROCEDURES + ;--------------------------------------- + ;--------------- + ; 0-OP EXECUTORS + ;--------------- + + ; ---- + ; NOOP + ; ---- + + ; NOOP (NO OPERATION) + PUBLIC GNOOP +GNOOP PROC + RET ;DO NOTHING +GNOOP ENDP + + ; ----- + ; RTRUE + ; ----- + + ; DO A "RETURN 1", WHERE 1 IS COMMONLY INTERPRETED AS TRUE. + PUBLIC GRTRUE,GRT2 +GRTRUE PROC + MOV AX,1 ;RETURN A 1 +GRT2: MOV ARG1,AX + JMP GRET ;RETURN VIA GRET +GRTRUE ENDP + + ; ------ + ; RFALSE + ; ------ + + ; DO A "RETURN 0", WHERE 0 IS COMMONLY INTERPRETED AS FALSE. + PUBLIC GRFALS +GRFALS PROC + SUB AX,AX ;RETURN A 0 + JMP GRT2 +GRFALS ENDP + + ; ------ + ; RSTACK + ; ------ + + ; "RETURN" WITH VALUE FROM GSTACK + PUBLIC GRSTAK +GRSTAK PROC + CALL POPVAL ;GET VALUE INTO AX + JMP GRT2 +GRSTAK ENDP + + ; ------ + ; FSTACK + ; ------ + + ; FLUSH THE TOP VALUE OFF THE GSTACK + PUBLIC GFSTAK +GFSTAK PROC + JMP POPAXG +GFSTAK ENDP + + ; ----------------------- + ; POP AX FROM THE GSTACK + ; ----------------------- + PUBLIC POPAXG,GSTKU +POPAXG PROC + XCHG SP,DI ;USE THE REAL SP + POP AX ;POP THE STACK + XCHG SP,DI ;SWAP BACK + PUSH AX ;SAVE REGISTER + MOV AX,OFFSET GSTK_TP ;CHECK IF WE HAVE AN UNDERFLOW + CMP DI,AX ; + JA GSTKU ; IF WE DO IT'S FATAL + POP AX ; ELSE, RESTORE THE REGISTER + RET + + ; *** ERROR #6: G-STACK UNDERFLOW *** +GSTKU: POP AX + MOV AL,6 + JMP GERROR +POPAXG ENDP + + ; ---- + ; QUIT + ; ---- + + ; THE GAME SHOULD DIE PEACEFULLY + ; (MACHINE DEPENDENT) + PUBLIC GQUIT +GQUIT PROC + JMP FINISH +GQUIT ENDP + + ; ----- + ; COPYP + ; ----- + + ; *** UNABLE TO FIND IN THE DOCUMENTATION *** + PUBLIC GCOPYP +GCOPYP PROC + JMP PREDS +GCOPYP ENDP + + ; ---- + ; VERP + ; ---- + + ; *** UNABLE TO FIND IN THE DOCUMENTATION *** + PUBLIC GVERP,GVER1,GVER2,GVER3,GVER4,GVER5,GVER6,GVER7,GVER8 + PUBLIC GVER$,GVER$$,GVERA,GVERB,GVERC,GVERD,GVERE +GVERP PROC + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH BP + PUSH DS + PUSH ES + + ; RESET THE FILE POINT TO BEGINNING OF THE FILE (LESS THE HEADER) + + MOV BX,GAMHNDL ; FILE HANDLE + MOV CX,0 + MOV DX,64 ; OFFSET IN THE FILE + MOV AX,4200H ; SEEK + INT 21H + + MOV VMP,0 ; GET CHECK SUM VALUE + MOV VMP0,0 + MOV AX,GCHECK ; OFFSET IN HEADER + CALL ADDVMP + CALL GW@VMP ; GET THE WORD THERE + MOV J,AX ; SAVE IN GENERAL VAR J +; + MOV AX,ICODE + MOV VMP,AX ; GET I-FILE CHECK SUM + MOV VMP0,0 + MOV AX,ICHECK ; OFFSET IN HEADER + CALL ADDVMP + CALL GW@VMP ; GET THE WORD THERE + MOV I,AX ; SAVE I-CHECKSUM IN VARIABLE I + MOV BP,0 ; ZERO THIS BABY TO HOLD CURRENT CHECKSUMS +; + MOV VMP,0 ; GET LENGTH OF G-FILE + MOV VMP0,0 + MOV AX,GLEN ; OFFSET IN HEADER + CALL ADDVMP + CALL GW@VMP ; GET THE WORD THERE + MOV DI,AX ; SAVE IT + SUB DI,GHEADER/2 ; SUBTRACT THE NUMBER OF BYTES IN HEADER + + ; FIGURE OUT HOW MUCH SPACE WE HAVE BETWEEN THE END OF PRELOAD + ; AND THE END OF THE FIRST 64K BOUNDARY. WE WILL USE THAT SPACE + ; AS A BUFFER FOR VERIFY. FIRST WE MUST ZERO OUT THE MEMMAP THAT + ; INDICATE IF THOSE PAGES ARE IN CORE AND RESET THERE MEMBUF + ; DESCRIPTORS. WE MUST ALSO PLAY WITH THE LRU POINTERS TO NOT + ; SCREW UP THE MEMORY MAP. + + MOV DX,SEG0 ; START OUT USING 0 SEG + MOV BL,BUFFERS ; HOW MANY POTENTIAL VERIFY BUFFERS? + CMP BL,080H ; NO MORE THAN 64K + JB GVER1 + SUB BL,80H ; REDUCE IT 64K OR LESS + MOV DX,SEG1 ; SWITCH TO 1ST SEG + MOV BH,0 ; ZERO TOP HALF + PUSH BX ; SAVE NUMBER OF BUFFERS + JMP GVERE ; CLEAN OUT MEMBUFS + + ; ZERO BUFFERS IN SEG 0 + +GVER1: MOV AH,GPRBLK ; GET TOTAL NUMBER OF PRELOAD BLOCKS + ADD AH,IPRBLK ; TO FIGURE BUFFER BOUNDARY + SUB BL,AH ; FIGURE --> BUFFERS - PRELOAD + PUSH BX + MOV CX,BX ; NUMBER OF BUFFERS DESC'S TO CLEAN OUT + MOV BX,OFFSET MEMBUF+1 ; GET ADDRESS OF FIRST BUFFER + + ; MEMBUF ZEROING LOOP + ; +GVERA: MOV BYTE PTR [BX],0 ; SET NO PAGE IN MEMORY FOR THIS BUFFER + ADD BX,4 ; NEXT BUFFER + LOOP GVERA ; CLEAN 'EM ALL OUT + MOV CX,0FFH ; NOW, CLEAN OUT THE MEMORY MAP + MOV BX,0 ; START AT THE BEGINNING +GVERB: TEST MEMMAP[BX],1 ; PRELOAD? + JZ GVERC ; NOPE, ZERO IT +GVERD: ADD BX,2 ; YES, SO SKIP THIS ONE + LOOP GVERB ; AND CHECK THE NEXT + JMP GVERE +GVERC: CMP DX,SEG0 ; WHICH SEG? + JE GVERC$ + JMP GVERD$ +GVERC$: CMP MEMMAP[BX+1],7FH ; IF BUFFER NUMBER < 127, THEN 0 IT + JA GVERD +GVERD$: MOV MEMMAP[BX+1],0 ; INDICATE PAGE NOT IN CORE + JMP GVERD ; INCREMENT AND CONTINUE +; +GVERE: POP BX + MOV CL,9 + SHL BX,CL ; CONVERT BUFFERS INTO BYTES + MOV CX,BX ; SAVE NUMBER OF BYTES IN BUFFER + MOV ES,DX ; SET ES TO ADDRESS PROPER SEG + CMP DX,SEG0 ; WHICH SEG? + JNE GVERF + MOV DH,GPRBLK ; FIGURE BUFFER STARTING POINT + ADD DH,IPRBLK ; BY ADDING ALL PRELOAD BLOCKS + MOV DL,0 ; CLEAR OUT BOTTOM GARBAGE + SHL DX,1 ; CONVERT WORDS TO BYTE OFFSET + JMP GVERG +GVERF: MOV DX,0 +; +GVERG: MOV SI,0 + MOV BX,GAMHNDL ; GET FILE HANDLE + PUSH DS ; MAKE DS ADDRESS GAME SEG + PUSH ES + POP DS +GVER2: MOV AH,CRDRNDZ ; READ THE G-FILE PART + INT 21H + CALL CHKSUM ; PERFORM CHECK SUM ON BUFFER + CMP SI,DI ; HAVE WE CHECK THE WHOLE THING? + JE GVER3 + JMP GVER2 +; +GVER3: POP DS ; RESTORE DS + CMP BP,J ; CORRECT? + JE GVER4 + JMP GVER$ + + ; SEEK TO START OF I-FILE IN DAT FILE + +GVER4: PUSH CX ; SAVE BUFFER SIZE + PUSH DX ; AND LOCATION + MOV DX,DI ; GET LENGTH OF G-FILE + ADD DX,GHEADER/2 ; ADD IN PREVIOUSLY SUBBED HEADER + ADD DX,IHEADER/2 ; ALSO SKIP I-FILE HEADER + MOV CX,0 ; CLEAR OUT FOR SEEK + INC DX ; (B6) MAKE UP FOR KERMIT FROM DEC20 +GVER4A: SHL DX,1 ; CONVERT WORD LENGTH TO BYTES + ADC CX,0 ; GET 64K BIT IF THERE IS ONE + MOV AX,4200H ; SEEK + INT 21H ; DO IT + POP DX + POP CX + + ; NOW FILE POINTER IS READER TO READ I-PURE FOR VERIFY + ; FIGURE OUT HOW MANY BYTES IN I-FILE + + PUSH ES ; SAVE SEG BEING USED + MOV AX,ICODE + MOV VMP,AX ; GET LENGTH OF I-FILE OUT OF I-HEADER + MOV VMP0,0 ; SET VMP + MOV AX,ILEN + CALL ADDVMP + CALL GW@VMP ; GET THE WORD + + MOV DI,AX ; SAVE LENGTH + SUB DI,IHEADER/2 ; CHECK FILE LESS HEADER + MOV BP,0 ; ZERO THIS BABY AGAIN + MOV SI,0 + POP ES ; RESTORE SEG BEING USED + PUSH DS + PUSH ES + POP DS ; MAKE DS ADDRESS THE GAME SEG +; +GVER5: MOV AH,CRDRNDZ ; READ THE I FILE + INT 21H ; DO IT + CALL CHKSUM ; PERFORM CHECK SUM ON BUFFER + CMP SI,DI ; HAVE WE CHECK THE WHOLE THING? + JE GVER6 + JMP GVER5 + +GVER6: POP DS ; RESTORE DS + CMP BP,I ; COMPARE CHECKSUMS + JE GVER7 + JMP GVER$ +GVER7: CLC ; INDICATE SUCCESS +GVER8: PUSHF + CMP FSIZE,0 ; (B5) DID WE USE THE HIGH SEG + JE GVER9 + MOV AX,4200H ; (B5) SEEK FROM BEGINNING OF FILE + MOV CX,1 ; (B5) TO 64K LOCATION + PUSH DS ; (B6) SET TO UPPER + MOV DX,SEG1 ; (B6) SEGMENT FOR RELOAD + MOV DS,DX ; (B6) RESTORE DX + MOV DX,0 + INT 21H + MOV DX,0 ; (B5) READ IN SECOND 64K + MOV CX,0FFFFH ; (B5) THAT MUCH + MOV AH,CRDRNDZ ; (B5) READ FUNCTION + INT 21H + POP DS + +GVER9: POPF + POP ES ; RESTORES + POP DS + POP BP + POP DI + POP SI + POP DX + POP CX + POP BX + JC GVER$$ ; FAIL ON CARRY + JMP PREDS ; OTHERWISE SUCCESS +GVER$: STC ; COMMON ENTRY FOR FAILURE + JMP GVER8 ; DO RESTORES +GVER$$: JMP PREDF ; INDICATE FAILURE +GVERP ENDP + + PUBLIC CHKSUM +CHKSUM PROC NEAR + PUSH AX ; SAVES + PUSH BX + PUSH CX + PUSH DS + PUSH ES + POP DS + MOV BX,SI ; GET NUMBER OF WORDS CHECKED SO FAR + MOV CX,AX ; GET NUMBER OF BYTES TO CHECK + MOV SI,DX ; ADDRESS OF BUFFER + MOV AH,0 ; ZERO TOP HALF +CHKS1: LODSB ; GET A BYTE + ADD BP,AX ; ADD THE BYTE + TEST SI,1 ; ODD BYTE? + JNZ CHKS2 + INC BX + CMP BX,DI + JE CHKS3 +CHKS2: LOOP CHKS1 +CHKS3: MOV SI,BX ; RESTORE SI TO COUNT OF WORDS + POP DS + POP CX + POP BX + POP AX + RET +CHKSUM ENDP + + + SUBTTL 1-OP EXECUTORS + PAGE + ;--------------- + ; 1-OP EXECUTORS + ;--------------- + + ; ---- + ; PUSH + ; ---- + + ;PUSH [ARG1] ONTO THE GSTACK + PUBLIC GPUSH +GPUSH PROC + MOV AX,ARG1 + + ; AND FALL THROUGH ............. + +GPUSH ENDP + + ; ----------------------- + ; PUSH AX ONTO THE GSTACK + ; ----------------------- + PUBLIC PSHAXG,GSTKR +PSHAXG PROC + XCHG SP,DI ;USE THE REAL SP + PUSH AX ;PUSH IT ON THE STACK + XCHG SP,DI ;SWAP BACK + PUSH AX ;SAVE REGISTER + MOV AX,OFFSET GSTK_BT ;CHECK IF WE HAVE AN OVERFLOW + CMP DI,AX ; + JB GSTKR ; IF WE DO IT'S FATAL + POP AX ; ELSE, RESTORE THE REGISTER + RET + + ; *** ERROR #7: G-STACK OVERFLOW *** +GSTKR: POP AX + MOV AL,7 + JMP GERROR +PSHAXG ENDP + + ; --- + ; POP + ; --- + + ;POP A VALUE OFF THE GSTACK INTO VARIABLE [ARG1] + PUBLIC GPOP +GPOP PROC + CALL POPVAL + JMP DOPUT +GPOP ENDP + + ; ----- + ; VALUE + ; ----- + + ;RETURN VALUE OF VARIABLE [ARG1] + PUBLIC GVALUE +GVALUE PROC + MOV AX,ARG1 ;GET VARIABLE ID + SUB AH,AH + CALL VARGET ;GET THE VALUE INTO [VALUE] + JMP PUTVAL ;AND RETURN IT +GVALUE ENDP + + ; ---- + ; INC + ; ---- + + ;INCREMENT VARIABLE [ARG1] + PUBLIC GINC +GINC PROC + MOV AX,ARG1 ;GET VARIABLE ID + SUB AH,AH + CALL VARGET ;GET VAR'S VALUE + INC VALUE ;INCREMENT IT + JMP DOPUT +GINC ENDP + + ; --- + ; DEC + ; --- + + ;DECREMENT VARIABLE [ARG1] + PUBLIC GDEC,DOPUT +GDEC PROC + MOV AX,ARG1 + SUB AH,AH + CALL VARGET ;GET VAR'S VALUE + DEC VALUE ;DECREMENT IT + +DOPUT: MOV AX,ARG1 ;RESTORE VARIABLE ID + SUB AH,AH + JMP VARPUT ;STORE NEW VALUE +GDEC ENDP + + ; ----- + ; ZERO? + ; ----- + + ;[ARG1]=0? + PUBLIC GZEROP,PYES +GZEROP PROC + MOV AX,ARG1 + CMP AX,0 ;IS OPR ZERO? + JZ PYES ;YES, PREDICATE TRUE + JMP PREDF ;NO, PREDICATE FALSE + +PYES: JMP PREDS +GZEROP ENDP + + ; --- + ; NOT + ; --- + + ;COMPLEMENT [ARG1] + PUBLIC GBNOT +GBNOT PROC + MOV AX,ARG1 + NOT AX ;LOGICAL COMPLEMENT + JMP VEXIT ;RETURN THE VALUE +GBNOT ENDP + + ; ---- + ; JUMP + ; ---- + + ;JUMP TO G-ADDRESS [ARG1] + PUBLIC GJUMP +GJUMP PROC + MOV AX,ARG1 ;MOVE [ARG1] TO [VALUE] + MOV VALUE,AX + JMP PREDB3 ;A BRANCH THAT ALWAYS SUCCEEDS +GJUMP ENDP + + ; --- + ; RET + ; --- + + ;RETURN FROM "CALL" WITH VALUE [ARG1] + PUBLIC GRET,GRET1,GRET2 +GRET PROC + + ; RESTORE THE GSTACK PTR + MOV DI,OLDGSP ;RESTORE OLD TOP OF THE GSTACK + + ; RESTORE LOCALS + ; GET THE NUMBER OF LOCALS + CALL POPAXG ;POP # OF LOGALS FROM GSTACK INTO AX + XCHG AX,CX ; XFER INTO CX TO BE USED AS A LOOP COUNTER + + ; IF NUMBER OF LOCALS=0 THEN SKIP LOCAL RESTORATION + OR CX,CX ;ANY LOCALS? + JZ GRET2 ;....NO. SKIP LOCAL RESTORATION + + ; + ; LOCAL RESTORATION + ; + + ; INITIALIZE VMP + MOV AX,GLOCS ;SET UP VMP TO POINT TO THE LOCAL TABLE + MOV VMP,AX + MOV VMP0,0 + + ADD VMP,CX ;POINT PAST THE LAST LOCAL + + ; RESTORE ALL [CX] PUSHED LOCALS +GRET1: DEC VMP ;BACK UP TO THE CURRENT LOCAL + CALL POPAXG ;POP A LOCAL FROM THE GSTACK + CALL PW@VMP ;RESTORE THE LOCAL + LOOP GRET1 ; LOOP UNTIL WE HAVE THEM ALL + + ; RESTORE THE GPC +GRET2: CALL POPAXG ;GET THE GPC BIT FROM GSTACK + MOV GPC0,AL ; AND SAVE IT + + CALL POPAXG ;GET GPC FROM GSTACK + MOV GPC,AX ; AND SAVE IT + + ; RESTORE THE OLD GSP + CALL POPAXG ;GET OLD GSP FROM GSTACK + MOV OLDGSP,AX ; AND SAVE IT + + ; GET THE VALUE TO RETURN + MOV AX,ARG1 + JMP VEXIT +GRET ENDP + + ; ----------------- + ; VALUE RETURN EXIT + ; ----------------- + + ; ENTRY: VALUE IN AX + PUBLIC VEXIT +VEXIT PROC + MOV VALUE,AX + JMP PUTVAL ;RETURN THE VALUE +VEXIT ENDP + + SUBTTL 2-OP EXECUTORS + PAGE + ;--------------- + ; 2-OP EXECUTORS + ;--------------- + + ; -------- + ; BAD 2-OP + ; -------- + + ; *** ERROR #5: ILLEGAL 2-OP *** + PUBLIC BADOP2 +BADOP2 PROC + MOV AL,5 + JMP GERROR +BADOP2 ENDP + + ; --- + ; ADD + ; --- + + ;RETURN [ARG1] + [ARG2] + PUBLIC GADD +GADD PROC + MOV AX,ARG1 + MOV BX,ARG2 + ADD AX,BX ;ADD OPR1 AND OPR2 + JMP VEXIT ;RETURN THE VALUE +GADD ENDP + + ; --- + ; SUB + ; --- + + ;RETURN [ARG1] - [ARG2] + PUBLIC GSUB +GSUB PROC + MOV AX,ARG1 + MOV BX,ARG2 + SUB AX,BX ;SUBTRACT OPR2 FROM OPR1 + JMP VEXIT ;RETURN THE VALUE +GSUB ENDP + + ; --- + ; MUL + ; --- + + ;RETURN [ARG1] * [ARG2] + PUBLIC GMUL +GMUL PROC + MOV AX,ARG1 + MOV BX,ARG2 + IMUL BX ;MULTIPLY OPR1 BY OPR2,IGNORING OVERFLOW(DX) + JMP VEXIT ;RETURN THE VALUE +GMUL ENDP + + ; --- + ; DIV + ; --- + + ;RETURN QUOTIENT OF [ARG1] / [ARG2] + PUBLIC GDIV +GDIV PROC + MOV AX,ARG1 + MOV BX,ARG2 + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + JMP VEXIT ;RETURN THE VALUE +GDIV ENDP + + ; --- + ; MOD + ; --- + + ;RETURN REMAINDER OF [ARG1] / [ARG2] + PUBLIC GMOD +GMOD PROC + MOV AX,ARG1 + MOV BX,ARG2 + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + MOV AX,DX ;WE WANT REMAINDER + JMP VEXIT ;RETURN THE VALUE +GMOD ENDP + + ; ---- + ; BAND + ; ---- + + ;RETURN [ARG1] "AND" [ARG2] + PUBLIC GBAND +GBAND PROC + MOV AX,ARG1 + MOV BX,ARG2 + AND AX,BX ;LOGICAL AND + JMP VEXIT ;RETURN THE VALUE +GBAND ENDP + + ; ---- + ; BIOR + ; ---- + + ;RETURN [ARG1] "OR" [ARG2] + PUBLIC GBIOR +GBIOR PROC + MOV AX,ARG1 + MOV BX,ARG2 + OR AX,BX ;LOGICAL OR + JMP VEXIT ;RETURN THE VALUE +GBIOR ENDP + + ; ---- + ; BXOR + ; ---- + + ;RETURN [ARG1] "XOR" [ARG2] + PUBLIC GBXOR +GBXOR PROC + MOV AX,ARG1 + MOV BX,ARG2 + XOR AX,BX ;LOGICAL XOR + JMP VEXIT ;RETURN THE VALUE +GBXOR ENDP + + ; ----- + ; BITS? + ; ----- + + ;IS EVERY "ON" BIT IN [ARG1] ALSO "ON" IN [ARG2] + PUBLIC GBITSP,GBITS0 +GBITSP PROC + MOV AX,ARG1 + MOV BX,ARG2 + NOT AX ;TURN OFF BITS IN OPR2 THAT ARE ON IN OPR1 + AND BX,AX + JE GBITS0 ;SUCCESS IF OPR2 COMPLETELY CLEARED + JMP PBAD +GBITS0: JMP PGOOD +GBITSP ENDP + + ; ------ + ; EQUAL? + ; ------ + + ;DOES [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? + PUBLIC GEQP,GEQP1,GEQP2 +GEQP PROC + MOV CL,BYTE PTR NARGS ;GET NUMBER OF ARGUMENTS + SUB CH,CH + DEC CX ;WE WANT TO COMPARE WITH ALL BUT ARG1 + SUB BX,BX ;RESET OFFSET + MOV AX,WORD PTR ARG1 [BX] ;GET ARG1 + +GEQP1: INC BX ;POINT TO NEXT ARG + INC BX ; REMEMBER, IT'S A WORD + CMP AX,WORD PTR ARG1 [BX] ;DOES ARG1 = ARG [BX]? + JE GEQP2 ;....YES + LOOP GEQP1 ;....NO. TRY NEXT ARG + + JMP PBAD ;PREDICATE FALSE IF WE RAN OUT OF ARGS +GEQP2: JMP PGOOD +GEQP ENDP + + ; + ; PREDICATE HANDLERS + ; + + ; USED TO VECTOR LOCAL SHORT JUMPS + PUBLIC PGOOD +PGOOD PROC + JMP PREDS +PGOOD ENDP + + PUBLIC PBAD +PBAD PROC + JMP PREDF +PBAD ENDP + + ; ----- + ; LESS? + ; ----- + + ;IS [ARG1] < [ARG2] + PUBLIC GLESSP,GLESS0 +GLESSP PROC + MOV AX,ARG1 + MOV BX,ARG2 + CMP AX,BX ;IS OPR1 LESS THAN OPR2? + JL GLESS0 ;YES, PREDICATE TRUE + JMP PBAD ;NO, PREDICATE FALSE +GLESS0: JMP PGOOD +GLESSP ENDP + + ; ------ + ; DLESS? + ; ------ + + ;DECREMENT VAR [ARG1]; SUCCEED IF < [ARG2] + PUBLIC GDLESP,GDLES0,GDLES1 +GDLESP PROC + MOV AX,ARG1 ;GET VARIABLE ID + PUSH AX ;SAVE VARIABLE ID + CALL VARGET ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + + SUB CX,CX ;SET FLAG FALSE + MOV BX,ARG2 ;GET VALUE TO COMPARE TO + CMP AX,BX ;IS VAR [ARG1] < ARG2? + JGE GDLES0 ;NO + INC CX ;YES, CHANGE FLAG TO TRUE +GDLES0: MOV BX,AX ;GET VALUE + MOV VALUE,BX ;STORE IT IN [VALUE] + POP AX ;RESTORE VARIABLE ID + + CALL VARPUT ;STORE [VALUE] AT VAR + CMP CX,0 ;TEST FLAG + JE GDLES1 ;FALSE, PREDICATE FALSE + JMP PGOOD ;ELSE, PREDICATE TRUE +GDLES1: JMP PBAD +GDLESP ENDP + + ; ----- + ; GRTR? + ; ----- + + ;IS [ARG1] > [ARG2] + PUBLIC GGRTRP,GGRTR0 +GGRTRP PROC + MOV AX,ARG1 + MOV BX,ARG2 + CMP AX,BX ;IS OPR1 GREATER THAN OPR2? + JG GGRTR0 ;YES, PREDICATE TRUE + JMP PBAD ;NO, PREDICATE FALSE +GGRTR0: JMP PGOOD +GGRTRP ENDP + + ; ------ + ; IGRTR? + ; ------ + + ;INCREMENT [ARG1]; SUCCEED IF > [ARG2] + PUBLIC GIGRTP,OPQIG0,OPQIG1,OQI1$ +GIGRTP PROC + MOV AX,ARG1 + MOV BX,ARG2 + PUSH AX ;SAVE VARIABLE + CALL VARGET ;GET VAR'S VALUE + INC AX ;INCREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE GREATER THAN VAL? + JLE OPQIG1 ;NO +OPQIG0: INC CX ;YES, CHANGE FLAG TO TRUE +OPQIG1: MOV BX,AX ;GET VALUE + MOV VALUE,BX ;STORE IT IN [VALUE] + POP AX ;RESTORE VARIABLE ID + CALL VARPUT ;STORE [VALUE] AT VAR + CMP CX,0 ;TEST FLAG + JE OQI1$ ;FALSE, PREDICATE FALSE + JMP PGOOD ;ELSE, PREDICATE TRUE +OQI1$: JMP PBAD +GIGRTP ENDP + + ; --- + ; SET + ; --- + + ;SET VARIABLE [ARG1] EQUAL TO [ARG2] + PUBLIC GSET +GSET PROC + MOV AX,ARG2 ;GET VALUE TO SAVE + MOV VALUE,AX ;PUT IT IN [VALUE] + MOV AX,ARG1 ;GET VARIABLE NO. + JMP VARPUT ;STORE THE VALUE IN THE VARIABLE +GSET ENDP + + ; --- + ; GET + ; --- + + ;RETURN ITEM [ARG2] IN WORD-TABLE [ARG1] + PUBLIC GGET +GGET PROC + MOV AX,ARG1 ;GET WORD TABLE BASE ADDRESS + ADD AX,ARG2 ;INDEX INTO WORD TABLE + MOV VMP,AX ;PUT ADDRESS INTO VIRTUAL MEMORY POINTER + MOV VMP0,0 ;IT MUST BE ON AN EVEN BOUNDRY + CALL GW@VMP ;GET THE WORD. RETURNED IN AX + MOV VALUE,AX ;PUT IT IN [VALUE] + JMP PUTVAL ;AND RETURN IT IN WORD TABLE [ARG1] +GGET ENDP + + ; ---- + ; GETB + ; ---- + + ;RETURN ITEM [ARG2] IN BYTE-TABLE [ARG1] + PUBLIC GGETB +GGETB PROC + MOV AX,ARG1 ;TABLE BASE ADDRESS (WORDPOINTER) + MOV VMP,AX ;SET UP BASE ADDRESS + MOV VMP0,0 + MOV AX,ARG2 ;GET BYTE POINTER + CALL ADDVMP ;ADD BYTE OFFSET TO BASE ADDRESS + CALL GB@VMP ;GET THE BYTE + JMP PUTBYT ;AND RETURN IT VIA PUTBYT +GGETB ENDP + + SUBTTL X-OP EXECUTORS + PAGE + ;--------------- + ; X-OP EXECUTORS + ;--------------- + + ; ---- + ; CALL + ; ---- + +; INSTRUCTION FORMAT: +; +; OPCALL, MODE BYTE1, .... MODE BYTEn, ARG1, .... ARGn +; +; +; MODE BYTE: +; +; There are no mode bits in the opcode itself. All of the mode bits appear +; in the byte(s) following the opcode. Each mode byte is capable of supporting +; up to four arguments. Thus a mode byte is composed of up to 4 half nibble +; mode control codes. +; +; (Mode control code will be abbreviated as MCC.) A mode byte may contain +; 4 MCC's labeled from left to right MCC1, MCC2, MCC3, and MCC4. +; +; MODE BYTE FORMAT: +; +; bits: 7 6 5 4 3 2 1 0 +; +------+------+------+------+ +; | MCC1 | MCC2 | MCC3 | MCC4 | +; +------+------+------+------+ +; +; +; MODE CONTROL CODE FORMAT: +; +; bits: 1 0 | Operand +; ----|--------------------- +; 0 0 | long immediate +; 0 1 | immediate +; 1 0 | variable +; 1 1 | no more operands +; +; +; +; AT ENTRY [NARGS] = 0 + + PUBLIC GCALL,GCL,GCL0,GCL1,GCL2,GCL3,GCL4,GCL5 + PUBLIC GCL6,GCL7,GCL8,DOCALL,CALL1,CALL2,CALL3,CALL4 +GCALL PROC + ; + ; FILL CTYPES ARRAY WITH 'NO MORE ARGS' + ; INITIALIZE REGISTERS + MOV CX,16 ;NUMBER OF POSSIBLE ARGUMENTS + MOV AL,0C0H ;USE THE 'NO MORE ARGS' CODE + SUB BX,BX ;RESET BYTE INDEX + + ; FILL THE CURRENT CELL +GCL: MOV BYTE PTR CTYPES [BX],AL + + ; UPDATE INDEX + INC BX ;POINT TO THE NEXT CELL + + ; LOOP TILL DONE + LOOP GCL ; AND DO IT 16 TIMES TOTAL + + ; + ; UNPACK MODE BYTES + ; + + MOV ADEX,4 ;INITIALIZE BYTE INDEX + MOV ADEX2,4 ;INITIALIZE ARG BYTE COUNTER + +GCL0: CALL GB@GPCI ;GRAB AN ARGUMENT BYTE + MOV ABYTE,AL ;SAVE IT + JMP GCL2 ;DON'T SHIFT THE MODE BYTE THE FIRST TIME + +GCL1: MOV AL,ABYTE ;RESTORE THE MODE BYTE + SHL AL,1 ;SHIFT AND + SHL AL,1 ;SHIFT AGAIN + MOV ABYTE,AL ;SAVE MODE BYTE FOR NEXT TIME + +GCL2: AND AL,0C0H ;MASK OUT THE GARBAGE + CMP AL,0C0H ;LAST ARGUMENT? + JZ GCL3 ;....YES. TIME TO DECODE THE ARGS + + ;ELSE ADD THIS ARGUMENT TO THE ARG-TYPE LIST + MOV BL,NARGS ; SET UP INDEX + MOV BH,0 + MOV BYTE PTR CTYPES [BX],AL + INC NARGS ; AND INCREMENT THE NUMBER OF ARGUMENTS + + DEC ADEX ;IS THIS ARG BYTE EMPTY? + JNZ GCL1 ;....NO. GET NEXT ARG + + MOV ADEX,4 ;ELSE RESET THE ARGUMENT INDEX + DEC ADEX2 ;HAVE WE DONE 4 ARG BYTES? + JNZ GCL0 ;....NO. GET ANOTHER + + ; [CTYPES] HAS LIST OF ARG TYPES + ; [NARGS] HAS NUMBER OF ARGUMENTS + ; GPC POINTS TO ARG1 (THE FUNCTION ADDRESS) + +GCL3: MOV ADEX,0 ;RESET THE ARGUMENT INDEX + MOV ADEX2,0 ;AND STORAGE INDEX + MOV AL,NARGS ;CONTINUE ONLY IF + CMP AL,0 ;[NARGS] <> 0 + JNZ GCL4 + + ; *** ERROR #12: NO CALL ADDRESS *** + MOV AL,12 + JMP GERROR + + ; SAVE THE GCALL ARGUMENTS IN THE CARGS ARRAY WHILE USING THE MODE + ; CONTROL CODES (LOCATED IN THE CTYPES ARRAY) TO OBTAIN THEM. +GCL4: + MOV BL,ADEX ;GET ARG INDEX + MOV BH,0 ;WIPE OUT THE MSB + CMP BL,NARGS ;OUT OF ARGS YET? + JZ GCL8 ;....YES + + INC ADEX ;UPDATE ARG INDEX TO NEXT ARG + + ; GET THE TYPE BYTE FOR CURRENT ARG IN AL + MOV AL,BYTE PTR CTYPES [BX] + + CMP AL,0 ;LONG IMMEDIATE? + JNZ GCL5 ;....NO + + ; LONG IMMEDIATE + CALL GETLNG ;....YES, GET IT + JMP GCL7 + +GCL5: CMP AL,40H ;SHORT IMMEDIATE? + JNZ GCL6 ;....NO + + ; SHORT IMMEDIATE + CALL GETSHT ;....YES, GET IT + JMP GCL7 + + ; VARIABLE +GCL6: CALL GETVAR ;MUST BE A GET VARIABLE + + ; ARGUMENT IS NOW IN AX + ; MOVE VALUE (IN AX) TO [CARGS] +GCL7: MOV BL,ADEX2 ;GET THE STORAGE INDEX + MOV BH,0 + MOV WORD PTR CARGS [BX],AX + ;SAVE IT IN CARGS + + INC ADEX2 ; AND INCREMENT THE INDEX + INC ADEX2 ; TWICE, CAUSE WE SAVING WORDS + JMP GCL4 ;LOOP BACK FOR ANOTHER ARGUMENT + + ; ARGUMENTS IN [CARGS], # OF ARGUMENTS IN [NARGS] +GCL8: MOV AX,CARGS + OR AX,AX ;DOES CALL ADDRESS=0? + JNZ DOCALL ;....NO. CONTINUE + + JMP PUTBYT ;ELSE RETURN THE ZERO IN AL + +; +; AND NOW THE ACTUAL CALL +; + +DOCALL: MOV AX,OLDGSP ;PUSH [OLDGSP] ON THE GSTACK + CALL PSHAXG + + MOV AX,GPC ;PUSH [GPC] ON THE GSTACK + CALL PSHAXG + + MOV AL,GPC0 ;PUSH GPC BIT ON THE GSTACK + CALL PSHAXG + + ;SET GPC TO THE FUNCTION ADDRESS + MOV AX,CARGS ;GET THE FUNCTION ADDRESS + MOV GPC,AX ;PUT IT IN THE GPC + MOV GPC0,0 ; ALL FUNCTIONS START ON WORD BOUNDRIES + + ;PROCESS THE FUNCTION'S LOCALS + CALL GB@GPCI ;GET # OF LOCALS IN FUNCTION + MOV ADEX,AL ;SAVE HERE FOR REFERENCE + MOV ADEX2,AL ;SAVE HERE FOR COUNTING + + ; ANY LOCALS? + OR AL,AL ;IF # LOCALS = 0 + JZ CALL2 ; THEN JUMP AHEAD + + ; PUT THE FUNCTION'S LOCALS IN THE LOCAL TABLE + ; WHILE SAVING THE PRE-EXISTING LOCALS ON THE GSTACK + ; SET UP LOOP COUNTER + MOV CL,AL ;PUT NUMBER OF LOCALS IN LOOP COUNTER + SUB CH,CH + + MOV AX,GLOCS ;POINT VMP AT THE BASE ADDRESS OF THE + MOV VMP,AX ; LOCAL TABLE + MOV VMP0,0 + +CALL1: CALL GW@VMP ;GET OLD LOCAL + CALL PSHAXG ; SAVE IT ON THE GSTACK + + CALL GETLNG ;GET FUNCTION'S LOCAL & POINT TO NEXT + CALL PW@VMPI ;PUT IT IN THE LOCAL TABLE AND POINT TO + ; THE NEXT TABLE ENTRY + LOOP CALL1 + +CALL2: DEC NARGS ;ANY ARGS LEFT? + JZ CALL4 ;....NO + + ; PASS UP TO 15 [CARGS] TO [LOCALS] + SUB BX,BX ;INITIALIZE LOOP INDEX + MOV AX,GLOCS ;POINT VMP AT THE BASE ADDRESS OF THE + MOV VMP,AX ; LOCAL TABLE + MOV VMP0,0 + +CALL3: MOV AX,WORD PTR CARGS+2 [BX] ;GET ARGUMENT + CALL PW@VMPI ;ASSIGN ARG TO A LOCAL + + INC BX ;UPDATE INDEX + INC BX ;IT'S A WORD PTR + DEC NARGS ;OUT OF ARGS YET? + JNZ CALL3 ;....NO + +CALL4: MOV AL,ADEX ;GET NO. OF LOCALS + MOV AH,0 ;MASK OUT THE MSB + CALL PSHAXG ; AND SAVE ON THE GSTACK + + MOV OLDGSP,DI ;SAVE THE GSTACK POINTER + JMP MLOOP ;AND GO BACK TO MAIN LOOP + +GCALL ENDP + + PAGE + ; --- + ; PUT + ; --- + ; + ; SET ITEM [ARG2] IN WORD-TABLE [ARG1] EQUAL TO [ARG3] + ; + PUBLIC GPUT +GPUT PROC + MOV AX,ARG1 ;GET WORD TABLE BASE ADDRESS + ADD AX,ARG2 ;INDEX INTO WORD TABLE + MOV VMP,AX ;PUT ADDRESS INTO VIRTUAL MEMORY POINTER + MOV VMP0,0 ;IT MUST BE ON AN EVEN BOUNDRY + MOV AX,ARG3 ;GET THE VALUE + CALL PW@VMP ; AND WRITE IT TO VIRTUAL + RET +GPUT ENDP + + ; ---- + ; PUTB + ; ---- + ; + ; SET ITEM [ARG2] IN BYTE-TABLE [ARG1] EQUAL TO [ARG3 (LSB)] + ; + PUBLIC GPUTB +GPUTB PROC + MOV AX,ARG1 ;TABLE BASE ADDRESS (WORDPOINTER) + MOV VMP,AX ;SET UP BASE ADDRESS + MOV VMP0,0 + MOV AX,ARG2 ;GET BYTE POINTER + CALL ADDVMP ;ADD BYTE OFFSET TO BASE ADDRESS + MOV AX,ARG3 ;GET VALUE + CALL PB@VMPI ;WRITE OUT THE BYTE + RET +GPUTB ENDP + + PAGE + ; ----- + ; INPUT + ; ----- + + ; IMPORTS: + ; [ARG1], [ARG2] optional + ; + ; IF [NARGS] INDICATES THAT THERE IS A [ARG2], THEN [ARG2] + ; IS A WORDPOINTER ADDRESS TO AN ACTIVE ICON TABLE. IN THIS + ; CASE, ITERATION IS PERFORMED. + ; + ; [ARG1] IS DECODED AS FOLLOWS: + ; 0 : IMMEDIATELY POLL THE KEYBOARD AND JOYSTICK ONCE + ; -int : PAUSE FOR [-int]/60 SEC. + ; int : POLL THE KEYBOARD FOR int/60 SEC. OR UNTIL A + ; KEYPRESS IS DETECTED + ; + ; EXPORTS: [VALUE] via PUTBYT [AL] + ; WHERE AL IS ENCODED AS FOLLOWS: + ; 8FH : NO KEYPRESS (NO INPUTS DETECTED) + ; +int : 7-BIT ASCII CHARACTER + ; -int : JOYSTICK DATA * + ; + ; *note See DIP SPECIFICATION for JOYSTICK DATA rules + + PUBLIC GINPUT +GINPUT PROC + MOV KEYSAV,8FH ;KEYSAV <= NO KEY FOUND + MOV AX,ARG1 ;GET ARGUMENT + MOV VALUE,AX ;MOVE [ARG1] INTO [VALUE] + + CMP NARGS,1 ;IF ONLY 1 ARG + JE DONTIT ; THEN DON'T ITERATE + JMP ITRATE ; ELSE, ITERATE +DONTIT: JMP NOIT +GINPUT ENDP + + +NOIT PROC + MOV AX,VALUE ;RECOVER THE SILLY ARG + OR AX,AX ;TEST IT AGAIN + JS DELAY ;IF NEGATIVE, THIS IS A DELAY REQUEST + JNZ TICK ;IF NON-ZERO, THEN ENTER SENSE LOOP +NOIT1: CALL SENSE ; ELSE, READ JUST ONCE +MOVED: JMP PUTBYT ;RETURN [AL] + + ; + ; PURPOSE: POLL THE KEYBOARD FOR int/60 SEC. OR UNTIL A + ; KEYPRESS IS DETECTED + ; + +TICK: CMP PCJR,1 ; DON'T DOUBLE VALUE IF jr + JE TICK1 ; SO SKIP IT + SHL VALUE,1 ; DOUBLE THE WAIT VALUE +TICK1: CALL SENSE ;GET A READING + CMP AL,10001111B ;ANY ACTIVITY? + JNE MOVED ;....YES. RETURN IT. + CMP IBMAT,FALSE ; ARE WE A FAST ONE + JE TICK3 + MOV CX,JIFCNT +TICK2: LOOP TICK2 ; WASTE SOME TIME +TICK3: DEC VALUE ;DECREMENT COUNT, DOES COUNT = 0? + JNZ TICK1 ;....NO, LOOP BACK AND TRY AGAIN + + ;THE CLOCK EXPIRED WITHOUT A READING +NOREAD: JMP PUTBYT + + ; + ; PROGRAMABLE DELAY + ; + ; PURPOSE: POLL THE KEYBOARD FOR [-int]/60 SEC. REPORT THE + ; FIRST DETECTED KEYPRESS IF ANY. + ; + ; ENTER: AX=[-INT] + ; + +DELAY: NEG VALUE ;CHANGE [-INT] TO [+INT] + CMP PCJR,1 ; DON'T SHIFT FOR PCjr + JE DELALP ; SKIP IT + SHL VALUE,1 ;DOUBLE DELAY TIME FOR RICK'S MISCALC +DELALP: CALL SENSE ;GET A READING + CMP KEYSAV,8FH ;ANY PREVIOUS ACTIVITY? + JNE DELA1 ;....YES + MOV KEYSAV,AL ;....NO, SAVE THE CURRENT READING +DELA1: CMP IBMAT,FALSE ;IS THIS A SLOW MACHINE? + JE DELA3 ;....YES + + MOV CX,JIFCNT ;IT'S A FAST MACHINE (AN IBM AT) +DELA2: LOOP DELA2 ; SO USE A DELAY LOOP TO COMPENSATE + +DELA3: DEC VALUE ;DECREMENT COUNT, DOES COUNT = 0? + JNZ DELALP ;....NO, LOOP BACK AND TRY AGAIN + + ;THE CLOCK EXPIRED + MOV AL,KEYSAV ;RETURN THE KEYCODE + JMP PUTBYT +NOIT ENDP + + ; --------------------------- + ; CHECK KEYBOARD AND JOYSTICK + ; --------------------------- + + PUBLIC SENSE +SENSE PROC + + ; CHECK KEYBOARD FIRST + MOV AH,6 ;SELECT DIRECT CONSOLE INPUT + MOV DL,0FFH ; WITHOUT ECHO + INT 21H ;MSDOS FUNCTION CALL + JZ STICK ;IF NO KEYPRESS, THEN CHECK STICK + ; ELSE WE GOT A KEYSTROKE + CMP AL,0DH ; (B5) CARRIAGE RETURN? + JE SENS2 + CMP AL,0 ; EXTENDED ASCII? + JNE SENS1 ; NOPE + MOV AH,CNOECHO ; READ THE EXTENDED CODE + INT 21H ; GET THE CHAR + SUB AL,71 ; BASIFY THE HOME KEY + CMP AL,10 ; UPPER LIMIT + JA STICK ; DON'T RETURN ANYTHING + MOV BX,OFFSET XLKEY ; TRANSLATE THE KEY + XLAT ; LOOK UP IN TABLE +SENS2: PUSH AX ; SAVE CHAR AND TURN ON NUMLOCK + PUSH ES + MOV AX,BIOSDATA ; SEG ADDRESS BIOS DATA AREA + MOV ES,AX + MOV BX,KB_FLAG ; OFFSET TO BIOS DATA FOR KEYS + OR BYTE PTR ES:[BX],NUMLOCK ; TURN ON NUMLOCK + POP ES + POP AX +SENS1: AND AL,01111111B ;7-BIT ASCII ONLY + RET + + ; CHECK THE JOYSTICK +STICK: TEST JOYSTK,1 ; IS THERE REALLY ONE THERE? + JNZ STICK1 ; ITS THERE, ONWARD + PUSH CX + MOV CX,JIFCNT-200H ; NUMBER OF INSTRUCTIONS CYCLES NOT EXECUTED +STICK$: LOOP STICK$ ; TAKE AS MUCH TIME AS WE WOULD HAVE + POP CX + MOV AL,8FH ; RETURN CENTER POSITION + RET +STICK1: MOV DX,201H ;DX ^ GAME PORT + MOV AL,10001111B ;INITIALIZE JOYSTICK ACTIVITY BYTE + MOV STICKA,AL ; TO INDICATE NO KEYPRESSES + + ;*********** PATCH ************************* + ;RET ;TO DISABLE JOYSTICK + ;******************************************* + + ;GET JOYSTICK X-POSITION + MOV AH,1 ;SELECT X-AXIS + CALL POSITN + MOV BL,STICKA ;GET THE JOYSTICK FLAGS + CMP AL,60H ;IS THE JOYSTICK TO THE RIGHT? + JB STK0 ;....NO + XOR BL,00001000B ;TURN OFF THE RIGHT BIT (NEGATIVE LOGIC) + JMP STK1 ;IF IT'S TO THE RIGHT, IT CAN'T BE TO THE LEFT + +STK0: CMP AL,30H ;IS THE JOYSTICK TO THE LEFT? + JAE STK1 ;....NO + XOR BL,00000100B ;TURN OFF THE LEFT BIT + +STK1: MOV STICKA,BL ;SAVE JOYSTICK FLAGS + + MOV AH,2 ;SELECT Y POSITION + CALL POSITN ;GET JOYSTICK POSITION + MOV BL,STICKA ;GET THE JOYSTICK FLAGS + CMP AL,60H ;IS THE JOYSTICK DOWN? + JB STK2 ;....NO + XOR BL,00000010B ;TURN OFF THE DOWN BIT (NEGATIVE LOGIC) + JMP STK3 ;IF IT'S DOWN, IT CAN'T BE UP + +STK2: CMP AL,30H ;IS THE JOYSTICK UP? + JAE STK3 ;....NO + XOR BL,00000001B ;TURN OFF THE UP BIT + +STK3: MOV STICKA,BL + IN AL,DX ;READ SWITCH INPUTS + MOV AH,AL ;SAVE IT IN [AH] + AND AL,10H ;IS BUTTON 1 DEPRESSED? + JNZ STK3A ;....NO + MOV BL,STICKA ;....YES + OR BL,00010000B ;TURN ON THE BUTTON BIT + +STK3A: AND AH,20H ;IS BUTTON 2 DEPRESSED? + JNZ STK4 ;....NO + MOV BL,STICKA ;....YES + OR BL,00010000B ;TURN ON THE BUTTON BIT + +STK4: MOV AL,BL ;RETURN THE VALUE IN AL + RET +SENSE ENDP + + + ; + ; GET JOYSTICK ANALOG POSITION + ; + + ; + ; AXIS SELECTED WITH AH + ; 1= X AXIS + ; 2= Y AXIS + ; + + ; A DIFFERENT ROUTINE IS PROVIDED FOR IBM AND IBM AT + +POSITN PROC + PUSH CX + + IN AL,61H ;GET PORT DATA + PUSH AX ; AND SAVE IT + CLI ;CLEAR INTERRUPTS + + SUB CX,CX ;SET LOOP CONTROL VALUE = 0 + OUT DX,AL ;START THE TIMING + +POSX1: IN AL,DX ;GET STATE + TEST AL,AH ;WE'RE INTERESTED IN THE BIT IN AH + LOOPNE POSX1 ;LOOP UNTIL THE BIT COMES BACK ON + + ; IS THIS AN IBM AT? + CMP IBMAT,TRUE + JNE POSX2 + SAR CX,1 + +POSX2: SUB AX,AX + SUB AX,CX ;DETERMINE COUNT + + CMP AX,255 + JBE POSX3 + MOV AX,255 + + ;EQUALIZATION +POSX3: PUSH AX + + ; IS THIS AN IBM AT? + CMP IBMAT,TRUE + JNE POSX4 + SHL CX,1 + +POSX4: AND CX,01FFH +EQ1: IN AL,DX + TEST AL,AH + LOOP EQ1 + POP CX + + POP AX ;RESTORE INTERRUPT STATUS + OUT 61H,AL ; THE PORT VALUE + STI ;ENABLE INTERRUPTS + + MOV AX,CX ;RESTORE JOYSTICK VALUE + POP CX + RET +POSITN ENDP + + PAGE + ; -------------------- + ; DUMP BLOCK TO SCREEN + ; -------------------- + + ; ENTRY: BLOCK TO PUT ON SCREEN IN [BLOCK] (TOP BYTE IN [BLOCK + 0]) + ; X-COORDINATE (0-39) IN [AH], Y-COORDINATE (0-23) IN [AL] + ; + PUBLIC DUMP +DUMP PROC + PUSH DI + CMP AH,39 ; (B4) SHIFT FIX + JNE DMP1 + JMP DMPFIX + +DMP1: MOV BX,VID_SG ;POINT AT THE VIDEO BUFFER + MOV ES,BX + + ; CALCULATE OFFSET FROM VIDEO_RAM BASE ADDRESS TO STORE THE FIRST BYTE + SUB BX,BX ;ZERO MSB + XCHG BL,AL ;BX <= ROW ADDRESS (0-23) + ; AL IS NOW "0" + SHL BX,1 ;MAKE BX A WORD INDEX + + XCHG AH,AL ;GET COLUMN CONTRIBUTION IN AL + SHL AX,1 ; x2 SINCE IBM HAS 80 COLUMNS + + ADD AX,WORD PTR YAXTBL[BX] ;ADD ROW CONTRIBUTION + ; TO COLUMN CONTRIBUTION + MOV DI,AX ; (B4) USE REG + MOV SI,OFFSET BLOCK ; (B4) USE REG + + MOV CX,4 ;INITIALIZE LOOP COUNTER + SUB DI,1FAFH ; (B4) FIRST PASS FUDGE FACTOR + JMP DLOOP1 ; (B4) SKIP ACTUAL FIX OFFSET + ; TRANSLATE BYTE IN [AL] INTO A DOUBLED BIT WORD IN [AX] + +DLOOP: SUB DI,1FB2H ; (B4) FIX OFFSET +DLOOP1: XOR AH,AH ; (B4) ZERO TOP HALF + LODSB ; (B4) GET BLOCKSET BYTE + SHL AX,1 ; (B4) BYTE TO WORD + XCHG BP,AX ; (B4) INTO AN INDEX REG + MOV AX,GRXTBL[BP] ; (B4) GET SHIFTED WORD FROM TBL + + + ;PHASE SHIFT + ;MOVE THE WORD INTO VIDEO RAM + + STOSB ; (B4) STORE MIDDLE BYTE + MOV AL,AH ;SWAP + AND AX,3FC0H ;MASK + MOV DH,ES:[DI-2] ; (B4) GET IMAGE ALREADY ON SCREEN + MOV DL,ES:[DI] ; (B4) + AND DX,0C03FH ;MASK IT + OR AX,DX ;COMBINE SOURCE AND DEST TO + MOV ES:[DI-2],AH ; (B4) ACHIEVE PHASE SHIFT ON LEFT + STOSB ; (B4) AND ON RIGHT + + ; ODD BYTE IN BLOCK + + ADD DI,1FFEH ; FIX OFFSET + ; TRANSLATE BYTE IN [AL] INTO A DOUBLED BIT WORD IN [AX] + XOR AH,AH ; (B4) ZERO TOP HALF + LODSB ; (B4) GET BLOCKSET BYTE + SHL AX,1 ; (B4) BYTE TO WORD + XCHG BP,AX ; (B4) INTO AN BASE REG + MOV AX,GRXTBL[BP] ; (B4) GET SHIFTED WORD FROM TBL + + ;PHASE SHIFT + ;MOVE THE WORD INTO VIDEO RAM + + STOSB ; (B4) STORE MIDDLE BYTE + MOV AL,AH ;SWAP + AND AX,3FC0H ;MASK + MOV DH,ES:[DI-2] ; (B4) GET IMAGE ALREADY ON SCREEN + MOV DL,ES:[DI] ; (B4) + AND DX,0C03FH ;MASK IT + OR AX,DX ;COMBINE SOURCE AND DEST TO + MOV ES:[DI-2],AH ; (B4) ACHIEVE PHASE SHIFT ON LEFT + STOSB ; (B4) AND ON RIGHT + + LOOP DLOOP + + POP DI + RET +DUMP ENDP + +DMPFIX: MOV BX,VID_SG ;POINT AT THE VIDEO BUFFER + MOV ES,BX + SUB BX,BX ;ZERO MSB + XCHG BL,AL ;BX <= ROW ADDRESS (0-23) + SHL BX,1 ;MAKE BX A WORD INDEX + XCHG AH,AL ;GET COLUMN CONTRIBUTION IN AL + SHL AX,1 ; x2 SINCE IBM HAS 80 COLUMNS + ADD AX,WORD PTR YAXTBL[BX] ;ADD ROW CONTRIBUTION + MOV DI,AX ; (B4) USE REG + MOV SI,OFFSET BLOCK ; (B4) USE REG + MOV CX,4 ;INITIALIZE LOOP COUNTER + SUB DI,1FAFH ; (B4) FIRST PASS FUDGE FACTOR + JMP DFLP1 ; (B4) SKIP ACTUAL FIX OFFSET + SUB DI,1FAFH ; (B4) FIRST PASS FUDGE FACTOR + JMP DFLP1 ; (B4) SKIP ACTUAL FIX OFFSET +DFLP: SUB DI,1FB1H ; (B4) FIX OFFSET +DFLP1: XOR AH,AH ; (B4) ZERO TOP HALF + LODSB ; (B4) GET BLOCKSET BYTE + SHL AX,1 ; (B4) BYTE TO WORD + XCHG BP,AX ; (B4) INTO AN INDEX REG + MOV AX,GRXTBL[BP] ; (B4) GET SHIFTED WORD FROM TBL + STOSB ; (B4) STORE MIDDLE BYTE + MOV AL,AH ;SWAP + AND AX,3FC0H ;MASK + MOV DH,ES:[DI-2] ; (B4) GET IMAGE ALREADY ON SCREEN + MOV DL,ES:[DI] ; (B4) + AND DX,0C03FH ; (B4) MASK IT + OR AX,DX ;COMBINE SOURCE AND DEST TO + MOV ES:[DI-2],AH ; (B4) ACHIEVE PHASE SHIFT ON LEFT + ADD DI,1FFFH ; FIX OFFSET + XOR AH,AH ; (B4) ZERO TOP HALF + LODSB ; (B4) GET BLOCKSET BYTE + SHL AX,1 ; (B4) BYTE TO WORD + XCHG BP,AX ; (B4) INTO AN BASE REG + MOV AX,GRXTBL[BP] ; (B4) GET SHIFTED WORD FROM TBL + STOSB ; (B4) STORE MIDDLE BYTE + MOV AL,AH ;SWAP + AND AX,3FC0H ;MASK + MOV DH,ES:[DI-2] ; (B4) GET IMAGE ALREADY ON SCREEN + MOV DL,ES:[DI] ; (B4) + AND DX,0C03FH ;MASK IT + OR AX,DX ;COMBINE SOURCE AND DEST TO + MOV ES:[DI-2],AH ; (B4) ACHIEVE PHASE SHIFT ON LEFT + LOOP DFLP + POP DI + RET + + PAGE + ; ------------------------------ + ; DUMP BLOCK TO SCREEN WITH MASK + ; ------------------------------ + + ; ENTRY: BLOCK TO PUT ON SCREEN IN [BLOCK] (TOP BYTE IN [BLOCK + 0]) + ; X-COORDINATE (0-39) IN [AH], Y-COORDINATE (0-23) IN [AL] + ; + ; IF THE MASK BIT IS A "1" THEN THE SCREEN SHOWS THROUGH + ; IF THE MASK BIT IS A "0" THEN THE ICON IS DISPLAYED + ; + PUBLIC DMPMSK +DMPMSK PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + PUSH DX + PUSH ES + + MOV BX,VID_SG ;POINT AT THE VIDEO BUFFER + MOV ES,BX + + ; CALCULATE OFFSET FROM VIDEO_RAM BASE ADDRESS TO STORE THE FIRST BYTE + SUB BX,BX ;ZERO MSB + XCHG BL,AL ;BX <= ROW ADDRESS (0-23) + ; AL IS NOW "0" + SHL BX,1 ;MAKE BX A WORD INDEX + + XCHG AH,AL ;GET COLUMN CONTRIBUTION IN AL + SHL AX,1 ; x2 SINCE IBM HAS 80 COLUMNS + + ADD AX,WORD PTR YAXTBL[BX] ;ADD ROW CONTRIBUTION + ; TO COLUMN CONTRIBUTION + MOV VDPADR,AX ;SAVE STARTING MEMORY OFFSET + + SUB SI,SI ;INITIALIZE INDEX REGISTER + MOV CX,4 ;INITIALIZE LOOP COUNTER + +DMPMLP: MOV BL,BLOCK[SI] ;SELECT ICON BYTE + MOV BH,MBLOCK[SI] ;SELECT MASK BYTE + SUB VDPADR,1FB0H ;FIX OFFSET + CALL M1DISP ;TRANSLATE, MASK AND MOVE IT TO VRAM + INC SI ; NEXT BYTES + MOV BL,BLOCK[SI] ;SELECT ICON BYTE + MOV BH,MBLOCK[SI] ;SELECT MASK BYTE + ADD VDPADR,2000H ;FIX OFFSET + CALL M1DISP ;TRANSLATE, MASK AND MOVE IT TO VRAM + INC SI ; NEXT BYTES + LOOP DMPMLP + + POP ES ;RESTORE AFFECTED REGISTER(S) + POP DX + POP CX + POP BX + RET +DMPMSK ENDP + + PUBLIC M1DISP +M1DISP PROC + PUSH CX + PUSH BX ;SAVE MASK BYTE [IN BH] + + ; TRANSLATE BLOCK BYTE IN [BL] INTO A DOUBLED BIT WORD IN [AX] + SUB BH,BH + SHL BX,1 + MOV DX,GRXTBL[BX] ;BLOCK WORD + + POP BX ;RECOVER MASK BYTE + XCHG BH,BL ;PUT IT IN BL + SUB BH,BH + SHL BX,1 + MOV CX,GRXTBL[BX] ;MASK WORD + + PUSH DX ;SAVE BLOCK WORD + + ; GET THE VIDEO WORD FROM VIDEO RAM + MOV BX,VDPADR ;GET BASE ADDRESS + MOV AX,ES:[BX] + XCHG AL,AH + AND AX,3FFFH + MOV DL,ES:[BX+2] + AND DL,0C0H + OR AH,DL + + POP DX ;DX <= BLOCK WORD + ;CX <= MASK WORD + ;AX <= VIDEO WORD + + ;BLOCK <= ((VIDEO XOR BLOCK) AND MASK) XOR BLOCK + XOR AX,DX + AND AX,CX + XOR AX,DX + + ; STORE THE WORD IN VIDEO RAM + MOV BX,VDPADR ;GET BASE ADDRESS + + ;PHASE SHIFT + ;MOVE THE WORD INTO VIDEO RAM + MOV ES:[BX+1],AL + MOV AL,AH + AND AX,3FC0H + MOV DH,ES:[BX] + MOV DL,ES:[BX+2] + AND DX,0C03FH + OR DX,AX + MOV ES:[BX],DH + MOV ES:[BX+2],DL + POP CX + RET +M1DISP ENDP + +%OUT DMPMSK DONE + PAGE + ; ------ + ; GSHOWN + ; ------ + + ; DISPLAY NEGATIVE ICON [ARG3] AT X=[ARG1], Y=[ARG2] + PUBLIC GSHOWN +GSHOWN PROC + MOV NEGATE,0FFH ;ENABLE NEGATE + JMP SHOWI ; AND DO A SHOWI +GSHOWN ENDP + + ; ------ + ; GSHOWI + ; ------ + + ; DISPLAY POSITIVE ICON [ARG3] AT X=[ARG1], Y=[ARG2] + PUBLIC GSHOWI +GSHOWI PROC + MOV NEGATE,0 ;DISABLE NEGATE + + ; AND FALL THROUGH ............. + +GSHOWI ENDP + + ; ----- + ; SHOWI + ; ----- + + ; CODE COMMON TO GSHOWI AND GSHOWN + ; DISPLAY ICON [ARG3] AT X=[ARG1], Y=[ARG2] + ; IF [ARG4] IS GIVEN, IT POINTS TO THE MASK TO BE USED + PUBLIC SHOWI +SHOWI PROC + MOV MSKFLG,0 ;DISABLE MASKING UNTIL FURTHER NOTICE + CMP NARGS,3 + JE NOMASK ;IF ONLY 3 ARGS, THEN DON'T MASK + + ; {CASE} MASK + MOV AX,ARG4 ;GET MASK INFO + CALL ISU ; THIS ENTRYPOINT WILL PROVIDE: + ; ICON[ARG4] DATA V-ADDR IN [IADR2] + ; X-SIZE IN [IX2] + ; Y-SIZE IN [IY2] + + ; ICON[ARG3] DATA V-ADDR IN [IADR1] + ; X-SIZE IN [IX1] AND [XDEX1] + ; Y-SIZE IN [IY1] AND [YDEX1] + ; ASSIGNED BLOCKSET IN [BSET] + + MOV AL,IX1 ;IF WIDTH AND HEIGHT ARE NOT THE SAME + CMP AL,IX2 ; THEN DO NOTHING + JNE DRAWEX + MOV AL,IY1 + CMP AL,IY2 + JNE DRAWEX + + DEC MSKFLG ;ELSE SET MSKFLG [0FFH] + JB ITENT ; YES, THIS IS AN UNCONDITIONAL JUMP + + ; {CASE} NO MASKING + ; SET UP ICON [ARG3] +NOMASK: MOV AX,ARG3 ;GET THE V-ADDRESS OF THE ICON + CALL GETI ; AND SET IT UP + + ; ICON DATA V-ADDR IN [IADR1] + ; X-SIZE IN [IX1] AND [XDEX1] + ; Y-SIZE IN [IY1] AND [YDEX1] + ; ASSIGNED BLOCKSET IN [BSET] + + ; AND FALL THROUGH ............. + +SHOWI ENDP + + PUBLIC ITENT,DRAWEX,DRAWI1,DRAWI2,DRAWI3,DRAWI4 + PUBLIC DRAWI5,DRAWE2,DRAWIA,DRAWI8,DRAWI9,DRAWIB + PUBLIC DRAWIC,DRAWID,DRAW,DRAW1,DRAW2A,CLPRI2 +ITENT PROC + MOV AL,0 ; INITIALIZE VARIABLES + MOV TOPCUT,AL + MOV SIDCUT,AL + MOV MDXCUT,AL + + ; DETERMINE IF THE ICON CAN BE LEGALLY DRAWN + ; FROM THE STANDPOINT OF IT'S Y-POSITION + MOV AX,ARG2 ;GET ICON Y-POSITION + OR AH,AH ; IF MSB=0 + JZ DRAWI1 ; THEN ICON STARTS ON WINDOW PAGE + + CMP AH,0FFH ; IF ICON Y-POS MSB <> 0 AND <> 0FFH + JNE DRAWEX ; THEN ICON WILL NOT BE DISPLAYED + + ; {CASE 1} ICON STARTS ABOVE WINDOW PAGE (MSB = 0FFH) + ; DETERMINE TOP CLIP + ; FIND ICON Y1 - WINDOW Y1 + MOV BL,WINDY1 ;GET UPPER EDGE OF WINDOW + SUB BH,BH ;WORDIFY + NEG AX ;SINCE IT'S (-) WE GET TWO'S COMPLIMENT + ADD AX,BX ; AND ADD TO GET THE ABSOLUTE DISTANCE + OR AH,AH + JZ DRAWI2 ;IF DISTANCE LE. 255 THEN CONTINUE + ; ELSE DEPART +DRAWEX: RET + + ; {CASE 2} ICON STARTS ON WINDOW PAGE (MSB = 00H) + ; DETERMINE IF A TOPCLIP IS NECESSARY +DRAWI1: MOV AL,WINDY1 ;FIND WINDOW Y1 - ICON Y1 + MOV BL,BYTE PTR ARG2 + SUB AL,BL ;IF (-) THEN ICON STARTS BELOW TOP EDGE + JNS DRAWI2 ; OF WINDOW + + ; {CASE 2A} THE ICON TOPEDGE LIES ON OR BELOW THE WINDOW TOPEDGE + ; NO TOPCUT IS NECESSARY + ; [WINDY2] = LAST LINE OF THE WINDOW TO DISPLAY +DRAWI3: MOV AL,WINDY2 ;FIND WINDY2 - ICON Y1 [BL] + INC AL + SUB AL,BL ;GET DISTANCE + JS DRAWEX ;EXIT IF (-) THE WHOLE ICON IS BELOW THE WINDOW + + ; COMPARE SIZE OF THE DISPLAYABLE AREA ((WINDY2 + 1) - ICON Y1) + ; AND THE ICON HEIGHT + CMP AL,IY1 ;IF SIZE OF DISPLAYABLE AREA GE.ICON HEIGHT + JAE DRAWI4 ; THEN DON'T BOTHER CHANGING ICON HEIGHT + MOV IY1,AL ; ELSE, SUBSTITUTE SIZE OF THE DISPLAYABLE + JMP DRAWI4 ; AREA FOR THE ICON HEIGHT (BOTTOM CUT) + +DRAWI2: MOV TOPCUT,AL ;SAVE AMOUNT TO CUT FROM TOP OF ICON + + ;DO THE TOPCUT +DRAWI4: MOV AL,IY1 ;GET HEIGHT OF ICON + SUB AL,TOPCUT ;DO TOPCUT + JBE DRAWEX ;NO ICON LEFT TO DRAW SO EXIT + + MOV YDEX1,AL + SUB AL,WINDH ;IF THE ICON IS SMALLER THAN THE WINDOW + JB DRAWI5 ; THEN DISPLAY ALL OF IT + + MOV AL,WINDH ; ELSE, DISPLAY A WINDOW'S WORTH OF ICON + MOV YDEX1,AL + + ; MULTIPLY TOPCUT AND ICON WIDTH, ADD PRODUCT TO ICON POINTER + ; IN ORDER TO POINT AT THE START OF THE FIRST DISPLAYED ROW +DRAWI5: MOV AL,BYTE PTR ARG2 ;CHANGE ICON STARTING YPOS + ADD AL,TOPCUT ;TO REFLECT TOPCUT + MOV BYTE PTR YPOS,AL + + MOV AL,TOPCUT + MOV BL,IX1 + MUL BL ;AX=TOPCUT * ICON WIDTH + PUSH AX ;SAVE TOPCUT + CALL AIADR1 ;IADR1 <= IADR1 + TOPCUT + POP AX ;RESTORE TOPCUT + CMP MSKFLG,0 ;IS MASKING DISABLED? + JE NOMSK1 ;....YES + CALL AIADR2 ;....NO. IADR2 <= IADR2 + TOPCUT + + ;COMPUTE THE DISPLAYED WIDTH AND THE IXSKIP +NOMSK1: MOV AL,IX1 ;KLUDGE + MOV MDXCUT,AL + + MOV AX,ARG1 ;GET ICON X-COORDINATE + OR AH,AH ;IF MSB = 0 + JZ DRAWI8 ; THEN ICON STARTS ON WINDOW PAGE + + CMP AH,0FFH ; ELSE, IF MSB <> 0FFH + JNE DRAWE2 ; THEN WE MIGHT AS WELL GO HOME + + ; {CASE} ICON STARTS BEFORE WINDOW PAGE (MSB = 0FFH) + ; DETERMINE LEFT CLIP + ; FIND ICON X1 - WINDOW X1 + MOV BL,WINDX1 ;GET LEFT EDGE OF WINDOW + SUB BH,BH + NEG AX ;SINCE IT'S NEG, WE CHANGE THE SIGN + ADD AX,BX ; AND GET THE ABSOLUTE DISTANCE + OR AH,AH + JZ DRAWI9 ;IF d <= 255 THEN CONTINUE + +DRAWE2: RET + +DRAWIA: MOV AL,WINDX2 + INC AL + SUB AL,BYTE PTR ARG1 ;GET DISTANCE + JS DRAWE2 + CMP AL,IX1 ;COMPARE WITH WIDTH + JAE DRAWIB + MOV IX1,AL + JMP DRAWIB + +DRAWI8: MOV AL,WINDX1 + MOV BL,BYTE PTR ARG1 + SUB AL,BL + JS DRAWIA + +DRAWI9: MOV SIDCUT,AL + + ;DO THE SIDCUT +DRAWIB: MOV AL,IX1 ;GET WIDTH + SUB AL,SIDCUT + JBE DRAWE2 + + MOV XDEX1,AL + SUB AL,WINDW + JB DRAWIC + + MOV AL,WINDW + MOV XDEX1,AL + +DRAWIC: MOV AL,SIDCUT + SUB AH,AH + PUSH AX ;SAVE SIDECUT + CALL AIADR1 ;IADR1 <= IADR1 + SIDCUT + POP AX ;RESTORE SIDCUT + CMP MSKFLG,0 ;IS MASKING DISABLED? + JE DRAWID ;....YES + CALL AIADR2 ;....NO. IADR2 <= IADR2 + SIDCUT + +DRAWID: MOV AL,MDXCUT + SUB AL,XDEX1 + MOV IXSKIP,AL + + MOV AL,XDEX1 + MOV IX1,AL ;SET COUNTER REFRESH VALUE + + MOV AL,BYTE PTR ARG1 + ADD AL,SIDCUT + MOV BYTE PTR XPOS,AL + MOV BYTE PTR XPSAV,AL + + ;GET THE REQUIRED BLOCKSET DATA + MOV AL,BSET ;USE THE BLOCKSET ID + + ; GET THE ADDRESS OF THE CURRENT BLOCKSET + MOV BX,BTAB ;GET THE BASE ADDRESS OF THE BPT + MOV VMP,BX ;SET UP VMP + MOV VMP0,0 + SUB AH,AH ;AL CONTAINS BLOCKSET ID + DEC AL ;ZERO ALIGN IT + ADD VMP,AX ;ADD WORD INDEX TO BASE ADDRESS + CALL GW@VMP ;GET THE BLOCKSET POINTER + MOV VMP,AX ;SET UP VMP + MOV VMP0,0 + + CALL GW@VMPI + MOV BLKLEN,AH ;# BYTES PER BLOCK + MOV BSIZE,AL ;# OF BLOCKS + + MOV BX,VMP ;MOVE V-ADDR OF BLOCKSET DATA + MOV BSADR,BX ;INTO [BSADR] + + ;CHECK FOR MASKING + CMP MSKFLG,0 ;IS MASKING DISABLED? + JE DRAW ;....YES. USE NORMAL DRAW ROUTINE + JMP DOMASK ; ELSE, GO DO THE MASK DRAW ROUTINE + + ; + ; DRAW THE ICON ITERATION AT [IADR1] + ; + + ; DRAW A ROW OF ICON BLOCKS +DRAW: PUSH DI ; (B5) SAVE GSTACK + CALL SETIADR ; (B5) SET UP SI AND GET BLOCK ID + CALL GTGBLK ;GET GRAPHICS BLOCK [AL] INTO BLOCK + CMP FSIZE,0 ; (B5) SET UP DI ACCORDING TO REAL MEMORY + JE DRW0 + +DRW: MOV DI,BSADR ; (B5) GET ADDRESS OF THE BLOCK SET + SHL DI,1 ; (B5) CONVERT TO A REAL ADDR + +DRW0: CMP FSIZE,0 ; (B5) CALCULATE END-OF-PAGE + JNE DRW1 ; (B5) FITS - EOP AT END OF SEG + MOV AX,SI ; (B5) GET I-PAGE + AND AX,0FE00H ; (B5) ISOLATE BLOCK BITS + ADD AX,200H ; (B5) ADD PAGE LENGTH TO GET EOP + MOV I_EOP,AX ; (B5) SAVE IT + JMP DRW2 + +DRW1: MOV I_EOP,0 + MOV G_EOP,0 ; (B5) SET EOPAGES TO END OF SEGMENT + +DRW2: MOV AH,BYTE PTR XPOS ; (B5) GET XPOSITION + MOV AL,BYTE PTR YPOS ; (B5) AND Y + MOV CL,YDEX1 ; (B5) SET UP Y INDEX + MOV BL,XDEX1 ; (B5) SET UP X INDEX + JMP DRW3 + +FIX_I: CMP FSIZE,0 ; (B5) DECIDE WHICH TYPE OF FIX + JNE FXI3 + MOV BYTE PTR XPOS,AH ; (B5) SAVE VARS + MOV BYTE PTR YPOS,AL + MOV YDEX1,CL + MOV XDEX1,BL + MOV AX,IADR1 ; (B5) GET STARTING ADDRESS + AND AX,7F00H ; (B5) ISOLATE BLOCK BITS + ADD AX,100H ; (B5) AND ADVANCE TO NEXT BLOCK + MOV IADR10,0 ; (B7) SET THIS + TEST SI,1 ; (B7) EVEN? + JZ FXI2 + MOV IADR10,1 ; (B7) NOPE, ODD +FXI2: AND SI,1FEH ; (B5) ISOLATE WRAP VALUE + SHR SI,1 ; (B7) ALIGN WITH IADR1 IN AX + OR AX,SI ; (B5) AND MAKE THEM COUNT HERE + MOV IADR1,AX ; (B5) SAVE VIRTUAL PAGE + CALL SETIADR ; (B5) GET ICON ID AND RESET SI + CALL GTGBLK ; (B5) GET A GRAPHIC BLOCK + JMP DRW0 + +FXI3: ADD BP,1000H + JMP DRW$ + +DRAW$: POPF + JC FIX_I + CMP FSIZE,0 ; (B5) NO END OF PAGE IF FITS + JNE DRW$ + CMP SI,I_EOP ; (B5) CHECK END CONDITIONS + JAE FIX_I +DRW$: XCHG AX,DX ; (B5) SAVE X,Y + PUSH ES ; (B5) NO, SAVE IT + MOV ES,BP ; (BP) AND MAKE ADDRESSIBLE + MOV AL,ES:[SI] ; (B5) GET BYTE + POP ES + PUSH ES ; (B5) SAVE IN CASE OF CHANGE + CALL GTGFST ; (B5) GET IT DIRECTLY UNLESS SEG WRAP + POP ES + XCHG AX,DX ; (B5) RESTORE X,Y + + ; FALL THROUGH INTO DUMP LOOP + +DRW3: PUSH AX + PUSH BX + PUSH CX + PUSH BP + PUSH SI + PUSH ES + CALL DUMP ; (B5) DUMP SAVES DI + POP ES + POP SI + POP BP + POP CX + POP BX + POP AX + + ; UPDATE THE COLUMN COUNT +DRAW1: DEC BL ;DECREMENT THE COLUMN COUNTER + JZ CLPRI2 ; IF WE'RE OUT OF COLUMNS, DO NEXT ROW + + INC AH ; ELSE, INCREMENT X COORDINATE + + ; UPDATE THE BLOCK ID POINTER +DRAW2A: INC SI ; (B5) NEXT ICON BYTE + PUSHF ; (B5) SAVE FLAGS FOR ZERO + JMP DRAW$ ; AND DRAW THE NEXT ICON BYTE + + ; NEXT ROW + ; REFRESH THE COLUMN COUNTER +CLPRI2: MOV BL,IX1 + + ; REFRESH THE X-COORDINATE + MOV AH,BYTE PTR XPSAV + + ; SKIP BLOCK #'S THAT AREN'T DRAWN AND UPDATE POINTER + MOV DL,IXSKIP + SUB DH,DH + INC DX + + ;IADR1 <= IADR1 + IXSKIP + 1 + +ITEN1: ADD SI,DX ; (B5) ADD IN SKIP VALUE + PUSHF + ; UPDATE THE ROW COUNTER + INC AL ;INCREMENT THE Y-COORDINATE + DEC CL ;DECREMENT ROW COUNTER + JNZ DRAW$ ; LOOP UNTIL ALL ROWS ARE DONE + POPF + POP DI + RET +ITENT ENDP + + + PUBLIC SETIADR +SETIADR PROC + MOV AX,IADR1 ;POINT [VMP] TO CURRENT BLOCK ID + MOV VMP,AX + MOV AL,IADR10 + MOV VMP0,AL + CALL GB@VMP ;GET THE BLOCK ID INTO AL + + MOV BP,ES ; (B5) SAVE SEG + MOV CL,LOC ; (B5) GET LAST EFFECTIVE ADDRESS + XOR CH,CH ; (B5) DO CONVERSION + SHL CX,1 ; (B5) DOUBLE VPAGE + MOV BX,LADD ; (B5) GET LOW ADDRESS BITS + OR BH,CL ; (B5) OR IN HIGH BITS + MOV SI,BX ; (B5) SAVE ICON ADDRESS + RET +SETIADR ENDP + + + ; + ; DRAW THE ICON ITERATION AT [IADR1] WITH MASK AT [IADR2] + ; +DOMASK PROC + MOV AX,IADR2 ;POINT [VMP] TO THE NEXT MASK BLOCK ID + MOV VMP,AX + MOV AL,IADR20 + MOV VMP0,AL + + MOV AL,NEGATE ;SAVE NEGATE STATUS + PUSH AX + + MOV NEGATE,0 ;NEVER NEGATE THE MASK + + CALL GB@VMP ;GET MASK BLOCK ID + CALL GTGBLK ;GET MASK GRAPHICS BLOCK [AL] INTO BLOCK + + ; COPY [BLOCK] INTO [MASK] + MOV CX,8 ;LOAD LOOP COUNTER + SUB BX,BX ;RESET INDEX + +B2MLP: MOV AL,BLOCK[BX] + MOV MBLOCK[BX],AL + INC BX + LOOP B2MLP + + MOV AX,IADR1 ;POINT [VMP] TO CURRENT ICON BLOCK ID + MOV VMP,AX + MOV AL,IADR10 + MOV VMP0,AL + + POP AX ;RESTORE NEGATE + MOV NEGATE,AL + + CALL GB@VMP ;GET THE BLOCK ID INTO AL + CALL GTGBLK ;GET GRAPHICS BLOCK [AL] INTO BLOCK + + MOV AH,BYTE PTR XPOS ;GET THE X-COORDINATE + MOV AL,BYTE PTR YPOS ; AND THE Y-COORDINATE + + ; DRAW [BLOCK] AGAINST [MASK] AT X,Y [AX] + CALL DMPMSK + + ; UPDATE THE COLUMN COUNT + DEC XDEX1 ;DECREMENT THE COLUMN COUNTER + JZ CLPRIA ; IF WE'RE OUT OF COLUMNS, DO NEXT ROW + + INC BYTE PTR XPOS ; ELSE, INCREMENT X COORDINATE + + ; UPDATE THE ICON BLOCK ID POINTER + XOR IADR10,1 ;CHANGE THE STATE OF BIT0 + JNZ DM1 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC IADR1 ;ELSE BUMP THE REST OF IADR1 + + ; UPDATE THE MASK BLOCK ID POINTER +DM1: XOR IADR20,1 ;CHANGE THE STATE OF BIT0 + JNZ DM2 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC IADR2 ;ELSE BUMP THE REST OF IADR2 +DM2: JMP DOMASK + + ; NEXT ROW + ; REFRESH THE COLUMN COUNTER +CLPRIA: MOV AL,IX1 + MOV XDEX1,AL + + ; REFRESH THE X-COORDINATE + MOV AL,BYTE PTR XPSAV + MOV BYTE PTR XPOS,AL + + ; SKIP BLOCK #'S THAT AREN'T DRAWN AND UPDATE THE POINTERS + MOV AL,IXSKIP + SUB AH,AH + INC AX ; +1 TO UPDATE THE POINTERS + PUSH AX ;SAVE IXSKIP + 1 + CALL AIADR1 ;IADR1 <= IADR1 + IXSKIP + 1 + POP AX ;RESTORE IXSKIP + 1 + CALL AIADR2 ;IADR1 <= IADR1 + IXSKIP + 1 + + ; UPDATE THE ROW COUNTER + INC BYTE PTR YPOS ;INCREMENT THE Y-COORDINATE + DEC YDEX1 ;DECREMENT ROW COUNTER + JZ DOMA1 ;EXIT WHEN DONE + JMP DOMASK ; ELSE, LOOP +DOMA1: RET +DOMASK ENDP + + PAGE + ; ---- + ; SETI + ; ---- + + ; COPY ICON [ARG3] INTO ICON [ARG4] WITH + ; TOP LEFT CORNER AT X=[ARG1], Y=[ARG2]; + ; RETURN "0" IF RANGE ERROR, "1" IF OKAY + PUBLIC GSETI,SI0,SI1,SI3 +GSETI PROC + CALL ISETUP + + ;GET STATS OF SOURCE AND DESTINATION + CALL DOFIT ;WILL THE SOURCE FIT IN THE DESTINATION? + JNC SIA ;CARRY CLEAR IF OK + JMP RET0 ;ELSE RETURN A ZERO + + ; [GPC] WILL BE TEMPORARILY USED FOR AN AUTOINCREMENTING + ; VIRTUAL MEMORY POINTER +SIA: MOV AX,GPC ;PUSH [GPC] ON THE STACK + PUSH AX + + MOV AL,GPC0 ;PUSH GPC BIT ON THE STACK + PUSH AX + + ; VMP POINTS TO THE FIRST BYTE OF THE SOURCE ICON + ; POINT [GPC] AT THE FIRST BYTE OF THE SOURCE ICON + MOV AX,VMP + MOV GPC,AX + MOV AL,VMP0 + MOV GPC0,AL + + ; POINT [VMP] AT THE CURRENT BYTE OF THE DESTINATION SUB-ICON +SI0: MOV AX,IADR2 + MOV VMP,AX + MOV AL,IADR20 + MOV VMP0,AL + +SI1: CALL GB@GPCI ;GET A BYTE FROM THE SOURCE + CALL PB@VMPI ;PUT IT IN THE DESTINATION + DEC XDEX1 ;OUT OF SOURCE X'S YET? + JNZ SI1 ;....NO. MOVE ANOTHER BYTE + MOV AL,IX1 ;REFRESH COLUMN COUNTER + MOV XDEX1,AL + + MOV AL,BYTE PTR IX2 ;GET X-SIZE OF DESTINATION + SUB AH,AH ;ADD TO BASE ADDRESS OF SUB-ICON + CALL AIADR2 ;IADR2 <= IADR2 + [AX] + ;TO GET ADDRESS OF NEXT SUB-ROW + +SI3: DEC YDEX1 ;OUT OF Y'S YET? + JNZ SI0 ;....YES. RESET X-INDEX + ; AND LOOP TILL EMPTY + + ; RESTORE GPC + POP AX + MOV GPC0,AL + POP AX + MOV GPC,AX + + MOV AL,1 ;RETURN A 1 FOR SUCCESS + JMP PUTBYT +GSETI ENDP + + PAGE + ; ----- + ; SWAPI + ; ----- + + ; SAME AS "SETI" EXCEPT ICON [ARG4] SUB-DATA IS COPIED + ; BACK INTO ICON [ARG3] + + PUBLIC GSWAPI,GSW0,GSW1,GSW2,PRERR2 +GSWAPI PROC + CALL ISETUP ;SETUP ICON + + ; SOURCE ICON MUST BE IN PRELOAD + MOV AX,IADR1 ;GET ICON ADDRESS + CMP AX,IPURE ;IS SOURCE IN I-PRELOAD? + JB GSW0 ;....YES. SO CONTINUE + + ; *** ERROR #14: PURITY VIOLATION (SETI/SWAPI) *** +PRERR2: MOV AL,14 + JMP GERROR + + ; SOURCE ICON MUST BE NO LARGER THAN THE DESTINATION ICON +GSW0: CALL DOFIT ;WILL IT FIT IN THE DESTINATION + JNC GSW1 ;CARRY IS CLEAR IF OK + JMP RET0 ;ELSE RETURN A ZERO + + ; SWAP ICONS + ; [GPC] WILL BE TEMPORARILY USED FOR AN AUTOINCREMENTING + ; VIRTUAL MEMORY POINTER +GSW1: MOV AX,GPC ;PUSH [GPC] ON THE STACK + PUSH AX + + MOV AL,GPC0 ;PUSH GPC BIT ON THE STACK + PUSH AX + + ; SET UP OUTER LOOP + ; POINT [GPC] AT THE SOURCE ICON +GSW2: MOV AX,IADR1 + MOV GPC,AX + MOV AL,IADR10 + MOV GPC0,AL + + ; POINT [VMP] AT THE DESTINATION ICON + MOV AX,IADR2 + MOV VMP,AX + MOV AL,IADR20 + MOV VMP0,AL + + ; INNER LOOP +GSW3: CALL GB@GPC ;GET A BYTE FROM THE SOURCE + MOV BL,AL ;SAVE IT TEMPORARILY + + CALL GB@VMP ;GET DESTINATION BYTE + CALL PB@GPCI ;PUT IT IN THE SOURCE + ; AND INCREMENT GPC + + MOV AL,BL ;RETRIEVE ORIGINAL SOURCE BYTE + CALL PB@VMPI ;PUT IT IN THE DESTINATION + ; AND INCREMENT THE VMP PTR + + ; TEST INNER LOOP + DEC XDEX1 ;OUT OF SOURCE X'S YET? + JNZ GSW3 ;....NO. MOVE ANOTHER BYTE + + ; REFRESH INNER LOOP VARIABLES + MOV AL,IX1 ;REFRESH COLUMN COUNTER + MOV XDEX1,AL + + ; UDATE SOURCE AND DESTINATION ADDRESSES + MOV AL,BYTE PTR IX2 ;ADD X-SIZE OF DESTINATION + SUB AH,AH ; TO BASE ADDRESS OF SUB-ICON + CALL AIADR2 ;TO GET ADDRESS OF NEXT ROW + + MOV AL,BYTE PTR IX1 ;ADD X-SIZE OF SOURCE + SUB AH,AH ; TO BASE ADDRESS OF SOURCE + CALL AIADR1 ;TO GET ADDRESS OF NEXT ROW + + ; TEST OUTER LOOP + DEC BYTE PTR YDEX1 ;OUT OF Y'S YET? + JNZ GSW2 ; NO, RESET ROW INDEX AND LOOP + + ;RESTORE THE GPC + POP AX + MOV GPC0,AL + POP AX + MOV GPC,AX + + ;SET UP RETURN VALUE + MOV AL,1 ;RETURN A 1 FOR SUCCESS + JMP PUTBYT +GSWAPI ENDP + + PAGE + ; ----- + ; SOUND + ; ----- + + ; PLAY SOUND [ARG1] (1-127) + PUBLIC GSOUND +GSOUND PROC + MOV AX,ARG1 + OR AX,AX + JZ SNDERR ;RANGE ERROR + JS SNDERR ;RANGE ERROR + CMP AX,NSNDS + 1 + JAE SNDERR ;SOUND NOT DEFINED + DEC AX + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET SOUNDLIST PTR + MOV SI,DS:[BP+STABLE] + CALL SI ;CALL THE SOUND ROUTINE + RET +GSOUND ENDP + + PUBLIC SNDERR +SNDERR PROC + ; *** ERROR #13: ILLEGAL SOUND EFFECT *** +; MOV AL,0DH +; JMP GERROR + +; CHANGE MADE PER LIM'S REQUEST + CALL SND1 + CALL SND4 + CALL SND1 + CALL SND4 + RET +SNDERR ENDP + + ; + ; ACTUAL SOUND EFFECTS + ; + PUBLIC SND1 + ;BOOP +SND1 PROC + MOV CX,500 ;FREQ + MOV DX,7 ;DURATION * .05 SEC + JMP TONE +SND1 ENDP + + PUBLIC SND2 + ;CLICK +SND2 PROC + MOV CX,3000 ;FREQ + MOV DX,1 ;DURATION * .05 SEC + JMP TONE +SND2 ENDP + + PUBLIC SND3 + ;TING +SND3 PROC + MOV CX,2600 ;FREQ + MOV DX,5 ;DURATION * .05 SEC + JMP TONE +SND3 ENDP + + PUBLIC SND4 + ;RAZZ +SND4 PROC + MOV CX,120 ;FREQ + MOV DX,20 ;DURATION * .05 SEC + JMP TONE +SND4 ENDP + + PAGE + ; ---- + ; RAND + ; ---- + + ; RETURN A RANDOM VALUE BETWEEN 1 AND [ARG1] + PUBLIC GRAND +GRAND PROC + MOV AX,ARG1 + SUB AH,AH ; HACK RANDOM TO ONE BYTE + MOV RTEMP,AX ; SAVE ARGUMENT FOR LATER + MOV AX,RSEED1 + MOV BX,RSEED2 + MOV RSEED2,AX + CLC + RCR AX,1 + RCR BX,1 + XOR RSEED1,BX ;PUT XOR'D NUBMER INTO RSEED1 + MOV AX,RSEED1 ;THIS IS RANDOM VALUE + AND AX,0EFFFH ;CHOP HIGH BIT FOR DIVIDE + SUB DX,DX ;CLEAR MOST SIGN. PORTION OF 32 BIT WORD + DIV RTEMP ;DIVIDE WORD BY WORD + MOV AX,DX ;MOVE REMAINDER INTO AX + INC AX ;MAKE SURE NO ZERO + MOV VALUE,AX ;SAVE IT IN VALUE + JMP PUTVAL +GRAND ENDP + + PAGE + ; ----- + ; CLEAR + ; ----- + ; + ; CLEAR SCREEN TO WHITE IF [ARG1] IS NEGATIVE + ; CLEAR SCREEN TO BLACK IF [ARG1] IS POSITIVE + ; + + PUBLIC GCLEAR,GCLR1,GCLR2,GCLR3 +GCLEAR PROC + PUSH DI ;SAVE AFFECTED REGISTER(S) + PUSH CX + PUSH ES + + MOV AX,VID_SG ;POINT AT THE VIDEO BUFFER + MOV ES,AX + MOV AX,ARG1 ;GET THE ARGUMENT + + CMP AX,0 ; (B5) DO BLACK DIFFERENTLY + JE GCLR4 + MOV BP,AX ; GET WORD + AND BP,3FH ; MASK OFF HI NIBBLE FOR BIT SHIFT PROBLEM + MOV DI,0 ;SET UP INDEX + MOV BX,1E00H ;SET UP LOOP COUNTER + ; PAINT THE SCREEN WITH AX +GCLR1: XCHG AX,BP ; GET MASK BYTE + STOSB + XCHG AX,BP + MOV CX,79 ; DO A LINE - 1 AT A TIME + REPZ STOSB + SUB BX,80 ; SUBTRACT FROM TOTAL + JNZ GCLR1 + MOV DI,2000H + MOV BX,1E00H +GCLR2: XCHG AX,BP + STOSB + XCHG AX,BP + MOV CX,79 ; (B4) DO A LINE + REPZ STOSB + SUB BX,80 + JNZ GCLR2 + + ;CLEANUP WHEN COMPLETE +GCLR3: POP ES ;RESTORE THOSE REGISTERS + POP CX + POP DI + RET + +GCLR4: MOV DI,0 + MOV CX,0F00H ; (B5) DO WHOLE SCREEN + REPZ STOSW + MOV DI,2000H ; (B5) ODD BYTES + MOV CX,0F00H ; (B5) COUNT + REPZ STOSW + JMP GCLR3 + +GCLEAR ENDP + + PAGE + ; ------ + ; WINDOW + ; ------ + + ; SET THE WINDOW LIMITS TO THE RECTANGLE WHOSE UPPER LEFT SCREEN + ; COORDINATE IS AT (locx1, locy1) AND LOWER RIGHT SCREEN COORDINATE + ; IS AT (locx2, locy2). + + PUBLIC GWIND,WISK0,WISK1,WISK2,WISK3,WISK4 + PUBLIC WISK5,WISK6,WISK7,WISK8 +GWIND PROC + SUB BX,BX ;RESET INDEX + + ;TEST IF - OR > 255 +WISK0: MOV AX,WORD PTR ARG1[BX] ;GET COORDINATE + OR AH,AH ;DOES MSB=0? + JZ WISK1 ;....YES. COORDINATE IS EITHER + OR 0 + SUB AX,AX ;ELSE IT'S NEGATIVE + MOV WORD PTR ARG1[BX],0 ; CLIP IT TO 0 + + ;IT'S EITHER + OR 0 +WISK1: PUSH BX ;SAVE INDEX + AND BX,2 ;IS IT AN X OR Y COORDINATE? + POP BX ;RESTORE INDEX + JZ WISK2 ;IT'S AN X-COORDINATE + + ;Y COORDINATE CLIPPING + CMP AX,23 ;IS THE Y-COORDINATE ON SCREEN? + JBE WISK3 ;....YES + MOV ARG1[BX],23 ;....NO. CLIP IT + JMP WISK3 + + ;X COORDINATE CLIPPING +WISK2: CMP AX,39 ;IS THE X-COORDINATE ON SCREEN? + JBE WISK3 ;....YES + MOV ARG1[BX],39 ;....NO. CLIP IT + +WISK3: INC BL ;UPDATE INDEX TO POINT + INC BL ;AT THE NEXT ARG + CMP BL,8 ;HAVE WE DONE ALL OF THE ARGS + JNZ WISK0 ;....NO. KEEP LOOPING + + ; SWITCH X-COORDINATES IF REQUIRED +WISK4: MOV AL,BYTE PTR ARG1 ;GET X1 + MOV AH,BYTE PTR ARG3 ;GET X2 + CMP AL,AH ;IF X1 < X2 + JL WISK5 ; THEN DON'T SWAP + XCHG AL,AH ;SWAP X1 AND X2 + +WISK5: MOV BYTE PTR WINDX1,AL ;SAVE X1 + MOV BYTE PTR WINDX2,AH ;SAVE X2 + + ;COMPUTE WINDOW WIDTH + SUB AH,AL ;WINDW = WINDX2 - WINDX1 + 1 + INC AH + MOV WINDW,AH + + ; SWITCH Y-COORDINATES IF REQUIRED +WISK6: MOV AL,BYTE PTR ARG2 ;GET Y1 + MOV AH,BYTE PTR ARG4 ;GET Y2 + CMP AL,AH ;IF Y1 > Y2 + JL WISK7 ; THEN DON'T SWAP + XCHG AL,AH ;SWAP Y1 AND Y2 + +WISK7: MOV BYTE PTR WINDY1,AL ;SAVE Y1 + MOV BYTE PTR WINDY2,AH ;SAVE Y2 + + ;COMPUTE WINDOW HEIGHT +WISK8: SUB AH,AL ;WINDH = WINDY2 - WINDY1 + 1 + INC AH + MOV WINDH,AH + RET +GWIND ENDP + + PAGE + ; ----- + ; GITER + ; ----- + ; + ; INITIALIZE ITERATION TABLE AT WORD ADDRESS ARG1 + ; + +GITER PROC + MOV AX,ARG1 ;POINT TO TABLE BASE ADDRESS + MOV VMP,AX + MOV VMP0,0 + + CALL GB@VMPI ;[BYTE0] NUMBER OF ENTRIES IN TABLE + MOV ITICN,AL + + MOV AL,1 ;[BYTE1] SET CURRENT ENTRY=1 + CALL PB@VMPI + + ; WE'RE POINTING TO THE DATA STRUCTURE OF THE FIRST ENTRY + ; AND SUCCEEDING ENTRIES +GITER1: CALL GW@VMPI ;GET THE ICON WORD-PTR ADDRESS IN [AX] + + ; SAVE VIRTUAL MEMORY POINTER + MOV BX,VMP + PUSH BX + MOV BL,VMP0 + PUSH BX + + CALL GETI ;GET THE ICON INFORMATION + + ; RESTORE VIRTUAL MEMORY POINTER + POP BX + MOV VMP0,BL + POP BX + MOV VMP,BX + + ; SKIP ICON'S HORIZONTAL AND VERTICAL POSITION + ADD VMP,2 ;TWO WORDS + + ; SET UP REMAINING DATA + SUB AL,AL ;NEGATE=0 FOR POSITIVE IMAGE + CALL PB@VMPI + + MOV AL,1 ;CURRENT ITERATION=1 + CALL PB@VMPI + + MOV AL,BSET ;SAVE BLOCKSET IDENTIFIER + CALL PB@VMPI + + MOV AL,ITERS ;SAVE NUMBER OF ITERATIONS + CALL PB@VMPI + + MOV AL,IX1 ;SAVE WIDTH + CALL PB@VMPI + + MOV AL,IY1 ;SAVE HEIGHT + CALL PB@VMPI + + DEC ITICN ;ANY MORE ENTRIES? + JNZ GITER1 ;....YES + RET + +GITER ENDP +;------------------------ + + PUBLIC GRESTR +GRESTR PROC + MOV DSKDIR,0 ;INDICATE RESTORE (READ) + JMP OSV0$ +GRESTR ENDP + +; +; SAVE +; + PUBLIC GSAVE +GSAVE PROC + MOV DSKDIR,1 ;INDICATE SAVE (WRITE) + +; +;COMMON ENTRYPOINT FOR SAVE AND RESTORE +; +; DO A DISK RESET IN CASE THEY WANT TO CHANGE DISKS +; UNFORTUNATELY WE HAVE TO ASSUME A 1 DRIVE SYSTEM AT THIS POINT + +OSV0$: MOV AH,CFCLOSZ ; (7s) CLOSE THE GAME FILE + MOV BX,GAMHNDL ; (7s) FOR REINSERTION + INT 21H + MOV AH,CDRESET ; (K6) WILL RESET FLUSH BUFFERS? + INT 21H ; (K6) HOPE SO... + MOV AH,2 ; SET CURSOR POSITION + MOV DX,100H ; COORD'S ARE 0,0 + MOV BH,0 ; ACTIVE PAGE 0 + INT 10H ; TO PREVENT INVISIBLE CURSOR MOVEMENT + + +; PRINT "FILENAME (DEFAULT IS drv:filename.ext):" + +; PRINT "FILENAME (DEFAULT IS drv:" +OSV0A: MOV AX,OFFSET SAV0 ;PRINT "INSERT SAVE DISK THEN ENTER FILE..." + CALL MPRNT ; WITH CRLF + MOV AX,OFFSET SAV1 ;PRINT "FILE NAME (DEFAULT IS " + CALL NPRNT ; WITH NO CRLF + TEST DRVFLG,1 ; HAS USER SPECIFIED A DRIVE + JNZ OSVD1 ; YES, USE USER DEFAULT DRIVE + MOV AL,CURDRV ;AL <= DRIVE NO. + ADD AL,65 ;....NO. ADD 65 TO GET ASCII CHARACTER + CALL PRTOUT ;PRINT DRIVE B, C, OR D + MOV AL,":" ;PRINT ":" + CALL PRTOUT + +; PRINT "filename" +OSVD1: PUSH SI ; (6) SAVE THIS + MOV SI,OFFSET DATFILE ; (6) POINTER TO SAVE FILENAME (6) + MOV CX,SI ; (6) SAVE POINTER + CLD ; (6) SET DIR INCREMENT +OSVD2: LODSB ; (6) GET A BYTE INTO AL + TEST AL,AL ; (6) CHECK IF NULL + JZ OSVD3 ; (6) EXIT THIS LOOP + CALL PRTOUT ; (6) OUTPUT IT + JMP OSVD2 +OSVD3: SUB SI,CX ; (6) CALCULATE NUMBER OF CHARS + MOV CX,SI ; (6) GET NUMBER BACK INTO CX + POP SI ; (6) RESTORE THIS + +; PRINT " ): " + MOV AX,OFFSET SAV2 ;PRINT " ): " + CALL NPRNT ; WITH NO CRLF + +; GET LOSER'S SAVE FILENAME FROM THE KEYBOARD +OSVD4A: MOV BX,OFFSET INBUF ;^ KEYBOARD INPUT BUFFER + MOV AL,15 ;(6) COULD BE A WHOLE PATH + MOV BYTE PTR [BX],AL ;SET UP BUFFER TO TAKE 15 CHARACTERS + MOV DX,BX ;DX ^ BUFFER + MOV AH,CRDLIN ;READ A LINE FROM THE KEYBOARD + INT 21H + +; PARSE THE FILENAME + + CALL SAVESAV ; (7o) PRESERVE THE SAVE NAME + PUSH SI + PUSH DI + PUSH CX ; SAVE THIS + PUSH ES + PUSH DS + POP ES + LEA SI,INBUF[1] ; POINT TO NUM CHARS READ + LODSB ; GET NUM + TEST AL,AL ; ANY CHARS READ + JZ LOOK + MOV CL,AL ; STORE IT + XOR CH,CH ; CLEAR TOP HALF OF COUNTER + MOV DI,OFFSET DATFILE ; (6) DI ^FCB + REPZ MOVSB ; TRANSFER THE STRING IF ANY + MOV AL,0 ; (6) GET A NULL + STOSB ; (6) DROP IT IN AT END OF STRING +LOOK: MOV SI,OFFSET DATFILE ; (6) IS THERE A ':' + INC SI + LODSB ; (6) CHECK IT + CMP AL,':' ; (6) IF SO, FIX DEFDRV + JNZ NODRV ; (6) NOPE... + MOV DRVFLG,1 ; (6) SET FLAG + MOV AL,DATFILE ; (7n) GET DRIVE LETTER + AND AL,5FH ; (7n) UPPERCASIFY + SUB AL,'A' ; (7n) BASIFY + CMP AL,CURDRV ; (7n) DON'T CHANGE IF UNNECESSARY + JZ DRV + MOV DL,AL ; (7n) SET UP FOR CHGDSK + MOV AH,CSELDSK ; (7n) SELECT DISK IN DL + INT 21H + MOV AH,CURDSK ; (7n) CHECK IF IT WORKED + INT 21H + MOV CURDRV,AL ; (7n) SAVE IT + JMP DRV +USEDEF: MOV SKPDRV,1 ; (7n) DON'T OUTPUT A DRIVE +NODRV: MOV DRVFLG,0 +DRV: POP ES + POP CX + POP DI ;RESTORE'M + POP SI + CALL MCRLF ; (7) SCROLL PROPERLY + +; OPEN THE FILE IF OP RESTORE + + CMP DSKDIR,1 ;OP SAVE? + JE OSVOPW ;....YES + MOV DX,OFFSET DATFILE ; 6) ....NO. OP RESTORE. DX ^ FCB + MOV AH,CFOPENZ ; (6) SELECT DOS OPEN FUNCTION + MOV AL,0 ; (6) FILE OPEN FOR READING + INT 21H ;OPEN THE FILE + JC OSVPSX ; (6) ....NO. FILE NOT FOUND + JMP OSVPS ;....YES +; +; **** ERROR **** [File Not Found] +; +OSVPSX: MOV AX,OFFSET ERR1 ;^ "SAVE FILE NOT FOUND" MSG + JMP OSVPER ;ERROR EXIT + +; CREATE THE FILE IF OP SAVE +OSVOPW: MOV DX,OFFSET DATFILE ; (6) ^ FCB + MOV CX,0 ; (6) NO SPECIAL ATTRIBUTE + MOV AH,CFCREAZ ; (6) SELECT DOS CREATE FUNCTION + INT 21H + JC OSVOPDF + JMP OSVPS ;....YES +; +; **** ERROR **** [Directory Full] +; +OSVOPDF:MOV AX,OFFSET ERR4 ;....NO. ^ "NO ROOM IN DIRECTORY" MSG + JMP OSVPER ;HOP TO ERROR EXIT +; +; WE'VE GOT AN OPEN FILE (WHICH WE CREATED IF IT WAS A SAVE FUNCTION) +; AND ARE READY TO EITHER READ (RESTORE) OR WRITE (SAVE) AS REQUIRED + + +OSVPS: MOV DATHNDL,AX ; SAVE FILE HANDLE FOR DUMP/LOAD + XCHG DI,SP + MOV AH,GPC2 ; SAVE GPC + MOV AL,GPC1 + PUSH AX + MOV AL,GPC0 ; SAVE LOW BIT + PUSH AX ; OH, WHAT A WASTE + PUSH GLOCS ; SAVE LOCALS TABLE POINTER + PUSH OLDGSP ; RICK'S OLD G-STACK POINTER + PUSH ZORKID ; SAVE GAME ID + + +; SUB SP,OFFSET GSTK_BT ; (7v) RELATIVISE THE POINTER +; MOV GSTK_BT,SP ; PUT DEST. INDEX INTO STACKBOTTOM + mov ax,sp + sub ax,offset gstk_bt ; make sp relative, but not in SP + mov gstk_bt,ax ; the other way is dangerous + + MOV SP,DI ; RESTORE SP + + PUSH ES + + MOV AX,SS ; FLOP STACK SEG AND EXTRA SEG + MOV ES,AX ; ES<=SS + + MOV DX,OFFSET GSTK_BT ; CORE LOCATION + MOV CX,LSTACK*2 ; (6) DO TRANSFER HERE + MOV BX,DATHNDL ; (6) GET HANDLE + MOV AH,CRDRNDZ ; SETUP FOR A READ + ADD AH,DSKDIR ; MAKE IT A WRITE IF NECESSARY + INT 21H ; + CMP AX,CX ; DID WE GET IT ALL + PUSHF ;SAVE RETURN CODE + MOV DI,SP ;DI ^ CURRENT ZSTACK POSITION +; MOV SP,GSTK_BT ;SP <= ZSTACK POINTER +; ADD SP,OFFSET GSTK_BT ; (7v) RELATIVISE THIS VALUE + mov ax,gstk_bt + add ax,offset gstk_bt + mov sp,ax + + POP AX ; POP OFF AND COMPARE FOR ZORKID + CMP AX,ZORKID ;ID OK? + JE OSVT0 ;....YES + xchg di,sp + popf + pop es + MOV AL,18 ; SAVE ERROR + JMP GERROR ;....NO. FATAL ERROR + +OSVT0: POP OLDGSP ; RESTORE OLD G-STACK POINTER FOR RETURN + POP GLOCS ;RESTORE LOCALS AND ZIP PROGRAM COUNTERS + POP AX ; RESTORE LOW BIT + MOV GPC0,AL ; FROM THIS WORD + POP AX ; RESTORE GPC + MOV GPC2,AH + MOV GPC1,AL + + XCHG DI,SP ;RESTORE MACHINE SP AND ZSTACK POINTER + POPF ;RESTORE REGS + POP ES + + ; BEGIN SAVE OF G-FILE PRELOAD + ; + + MOV BX,DATHNDL ; GET HANDLE + MOV AH,DSKDIR ; GET DIRECTION + PUSH DS ; SAVE IT + MOV CX,SEG0 ; GET GAME SEG + MOV DS,CX ; ADDRESS IT + PUSH BX ; USE THIS AS INDEX + MOV BX,GEND ; DO > + MOV CX,[BX] ; GET LENGTH WORD + POP BX ; RESTORE HANDLE + XCHG CH,CL ; BYTE SWAP + SHL CX,1 ; CONVERT TO BYTES + MOV DX,0 ; STARTS AT BEGINNING OF THE SEG + ADD AH,CRDRNDZ ; START OUT WITH READ + INT 21H ; READ IT + JMP OSVPS2 +; +; +OSVPS2: JC OSV4 ; SKIP ON ERROR + + ; SUCESSFUL TRANSFER OF THE G-FILE PRELOAD. + ; TRANSFER I-FILE PRELOAD + + PUSH BX ; SAVE HANDLE + PUSH DS ; SAVE BUFFER SEG + MOV AX,CS ; GET DATA SEG + MOV DS,AX ; SO THAT WE CAN DO REAL ADDRESSING + MOV AX,ICODE ; GET INFO OUT OF I-PRE + MOV VMP,AX ; SET UP VIRTUAL MEMORY POINTER + MOV VMP0,0 ; TO GET + MOV AX,IEND ; THE END OF I-PRELOAD + CALL ADDVMP ; ADD IN OFFSET + CALL GW@VMP ; GET THE WORD + MOV DX,LADD ; GET THE LOW ADDRESS BITS + MOV BL,LOC ; GET BLOCK NUMBER + MOV BH,0 ; ZERO TOP HALF + SHL BX,1 ; CONVERT TO ADDRESS + OR DH,BL ; TURN ON BLOCK BITS + SUB DX,IEND ; GET START BYTE ADDRESS + MOV CX,AX ; GET NUMBER OF WORDS IN I-PRE + SHL CX,1 ; CONVERT TO BYTES + MOV AH,CRDRNDZ ; GET FUNCTION + ADD AH,DSKDIR ; ADD IN DIRECTION + POP DS ; RESTORE BUFFER SEG + POP BX ; RESTORE HANDLE + INT 21H ; READ/WRITE THE I-FILE + JC OSV4 + + ; SUCCESS IN GENERAL -- CLOSE FILES + POP DS ; HANDLE IS STILL IN BX + MOV AH,CFCLOSZ ; CLOSE THE SAVE FILE + INT 21H ; THRU DOS + CALL GAMOPEN ; (7s) OPEN GAME FILE + MOV AH,2 ; SET CURSOR POSITION + MOV DX,100H ; COORD'S ARE 0,0 + MOV BH,0 ; ACTIVE PAGE 0 + INT 10H ; TO PREVENT INVISIBLE CURSOR MOVEMENT + MOV DL,CURDRV ; (7n) RETURN TO SAVE DISK + MOV AH,CSELDSK ; (7n) AND SELECT IT FOR OPEN + INT 21H + MOV DSKDIR,-1 ; RESET SAVE/RESTORE FLAG + MOV ARG1,0 ; (B7) CLEAR OUT THE SCREEN + CALL GCLEAR ; (B7) IN CASE OF ERRORS + JMP PGOOD +; +; **** ERROR **** [Unable to Read File] +; +OSV4: POP DS + MOV AX,OFFSET ERR6 ;^ "Read of SAVE file failed." + CMP DSKDIR,1 ;OP SAVE? + JNE OSVPRR ;....NO + MOV AH,CFCLOSZ ; (6) ....YES. CLOSE IT + MOV BX,DATHNDL ; (6) GET HANDLE FOR CLOSE + INT 21H +; +; **** ERROR **** [Diskette Full] +; + MOV DX,OFFSET DATFILE ; (7n) DELETE THE PIECE OF A FILE + MOV AH,CFDELEZ ; (7n) SO AS NOT TO CONFUSE + INT 21H + MOV AX,OFFSET ERR5 ;^ "No room on diskette for SAVE file." +OSVPRR: JMP OSVPER +GSAVE ENDP +; +; ERROR EXIT R/W operations +; +OSVPER PROC + CALL MPRNT ;PRINT ERROR MESSAGE + CALL ZRESTOR ; (7o) RESTORE OLD SAVE NAME + CALL GAMOPEN ; (7v) OPEN IT + MOV AH,2 ; SET CURSOR POSITION + MOV DX,100H ; COORD'S ARE 0,0 + MOV BH,0 ; ACTIVE PAGE 0 + INT 10H ; TO PREVENT INVISIBLE CURSOR MOVEMENT + MOV ARG1,0 ; (B7) CLEAR OUT THE SCREEN + CALL GCLEAR ; (B7) IN CASE OF ERRORS + MOV DSKDIR,-1 ; RESET SAVE/RESTORE FLAG + JMP PBAD +OSVPER ENDP +; + PUBLIC SAVESAV,ZRESTOR,SCRSAVE +SCRSAVE PROC + PUSH AX ; (7p) SAVES + PUSH SI + PUSH DX + MOV SI,OFFSET DATFILE ; (7p) POINTER TO SAVE +SCRS0: LODSB ; (7p) GET A CHARACTER + TEST AL,AL ; (7p) LOOK FOR A NULL + JNZ SCRS1 ; (7p) DIE ON A NULL + POP DX + POP SI + POP AX + RET ; (7p) RETURN +SCRS1: MOV DL,AL ; (7p) GET CHARACTER INTO DL + MOV AH,CPROUT ; (7p) FOR DOS"IE" OUTPUT + INT 21H ; (7p) PRINT IT + JMP SCRS0 +SCRSAVE ENDP + +SAVESAV PROC + PUSH DI ; (7o) SAVES + PUSH SI + PUSH AX + PUSH ES + MOV AX,DS ; (7o) SET UP REGS + MOV ES,AX + MOV AL,CURDRV ; (7o) SAVE CURRENT DRIVE SPEC + MOV LASTDRV,AL ; (7o) IN CASE OF FAILURE + MOV AL,DRVFLG ; (7o) TEST DRIVE FLAG + MOV LSTDFLG,AL ; (7o) IN CASE OF FAILURE + MOV SI,OFFSET DATFILE ; (7o) SETUP SOURCE AND DESTINATION + MOV DI,OFFSET LASTSAV +COPYLP: LODSB ; (7o) GET A BYTE + STOSB ; (7o) STORE A BYTE + TEST AL,AL ; (7o) STOP ON A NUL + JNZ COPYLP ; (7o) CONTINUE THE COPY + POP ES + POP AX ; (7o) RESTORES + POP SI + POP DI + RET +SAVESAV ENDP +; +; +ZRESTOR PROC + PUSH DI ; (7o) SAVES + PUSH SI + PUSH AX + PUSH ES + MOV AX,DS ; (7o) SET UP REGS + MOV ES,AX + MOV AL,LSTDFLG ; (7o) GET LAST DRIVE FLAG + MOV DRVFLG,AL ; (7o) AND RESTORE IT + MOV AL,LASTDRV ; (7o) GET ORIGINAL DRIVE SPEC + CMP AL,CURDRV ; (7o) HAS IT CHANGED + JZ ZRES1 + MOV DL,AL ; (7o) SELECT DISK + MOV AH,CSELDSK ; (7o) TO CORRECT + INT 21H + MOV CURDRV,DL ; (7o) UPDATE THIS BABY +ZRES1: MOV DI,OFFSET DATFILE ; (7o) SETUP SOURCE AND DESTINATION + MOV SI,OFFSET LASTSAV +ZRESLP: LODSB ; (7o) GET A BYTE + STOSB ; (7o) STORE A BYTE + TEST AL,AL ; (7o) STOP ON A NUL + JNZ ZRESLP ; (7o) CONTINUE THE COPY + POP ES + POP AX ; (7o) RESTORES + POP SI + POP DI + RET +ZRESTOR ENDP + + PUBLIC GAMOPEN + ; THIS PROCEDURE OPENS THE GAME FILE AFTER CLOSING ALL FILES. + ; IF THE GAME FILE IS NOT ON THE DISK, IT PROMPTS FOR REINSERTION +GAMOPEN PROC + PUSH DX + PUSH CX + MOV CX,0 ; (B5) INDICATE FIRST PASS + MOV DL,DEFDRV ; (7o) GET DRIVE WHERE GAME IS + MOV AH,CSELDSK ; (7o) TO MAKE OPEN WIN + INT 21H ; (7o) DO IT + MOV AH,CFCLOSZ ; (7s) TRY CLOSING INSTEAD OF RESET + MOV BX,GAMHNDL ; (7s) OF THE GAME FILE + INT 21H ; (7o) TO MAKE SURE THIS WINS +GOPEN0: MOV AH,CFOPENZ ; (6) ASCIZ STRINGS + MOV AL,0 ; (6) OPEN FOR READING + MOV DX,OFFSET GAMFILE ; (7o) OPEN THE FILE AGAIN + INT 21H + JNC GOPEN1 ; (7o) IF SUCCESS, CONTINUE + INC CX + MOV AX,OFFSET SAV3 ; (7o) OTHERWISE PROMPT + CALL MPRNT + CALL MCHRI ; (7o) AND WAIT FOR A CHARACTER + JMP GOPEN0 ; (7o) AND LOOP +GOPEN1: MOV GAMHNDL,AX ; (7o) SAVE GAME HANDLE + MOV DL,CURDRV ; (7v) RESTORE SAVE DRIVE + MOV AH,CSELDSK ; (7v) SO THAT WE ARE NOT CONFUSED + INT 21H ; (7v) THANKS MAX + CMP CX,0 ; (B5) CHECK FOR PAUSE + JNE GOPEN2 ; (B5) NOT NECESSARY + MOV AX,OFFSET STRIKE ; (B5) STRIKE ANY KEY MESSAGE + CALL NPRNT ; (B5) PRINT IT + CALL MCHRI ; (B5) AND WAIT +GOPEN2: POP CX ; (B5) AND RESTORE THIS ONE + POP DX + RET +GAMOPEN ENDP + +MCHRI PROC + MOV AH,CNOECHO + INT 21H + RET +MCHRI ENDP + +;------------------------ + PAGE + ; ---- + ; LOAD + ; ---- + ; + ; PURPOSE: THIS ROUTINE LOADS THE SPECIFIED AMOUNT OF DATA INTO A + ; SPECIFIED BLOCK OF PRELOAD. IF ARG3 IS PROVIDED, THEN + ; THIS IS A TRANSFER FROM DISK. ELSE, IT IS AN I/O PORT + ; OPERATION. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; ARG2=LENGTH IN WORDS + ; ARG3=FILENAME POINTER (OPTIONAL) + ; + ; OUTPUTS: DATA IS TRANSFERED TO PRELOAD, IF THE OPERATION IS + ; ILLEGAL OR FAILS FOR ANY REASON, A "0" IS RETURNED + ; VIA {RET0}. ELSE A "1" IS RETURNED VIA {RET1}. + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC GLOAD +GLOAD PROC + CMP NARGS,3 ;IS THIS A FILE TRANSFER REQUEST? + JE GLD0 ;....YES + JMP LDIO ;....NO, IT'S AN I/O TRANSFER + + ; + ; FILE TRANSFER REQUEST + ; + + ; ASSUME THAT THE DEFAULT DISK IS TO BE USED + ; CLOSE THE GAMEFILE +GLD0: MOV AH,CFCLOSZ ;CLOSE THE GAME FILE FOR REINSERTION + MOV BX,GAMHNDL ;IN CASE THIS IS A 1 DRIVE SYSTEM, + INT 21H ; OR THE DEFAULT DRIVE IS SPECIFIED + MOV AH,CDRESET ;AND FLUSH + INT 21H + + ; PARSE THE FILENAME + MOV AX,ARG3 ;SET UP VMP TO POINT TO THE FILENAME + MOV VMP,AX + MOV VMP0,0 + CALL GW@VMPI ;GET THE LENGTH OF THE FILENAME + MOV CX,AX ;IN CX FOR USE AS A LOOP COUNTER + MOV BX,OFFSET DATFILE ;^ FCB + + ;GET THE FILENAME INTO THE FCB +GLD1: CALL GB@VMPI ;GET A CHARACTER + MOV [BX],AL ;PUT IT IN THE FCB + INC BX ;NEXT CHARACTER + LOOP GLD1 ; GET THE REST + MOV BYTE PTR [BX],0 ;DROP IN A NUL AT THE END OF THE NAME + + PUSH DI ;SAVE SOME REGISTERS + PUSH DS + POP ES ;BOTH ES & DS POINT AT THE DATA SEGMENT + + ; OPEN THE DATA FILE + MOV AH,CFOPENZ ;SELECT OPEN FILE + MOV AL,0 ;SELECT READ + MOV DX,OFFSET DATFILE ;POINT AT THE ASCIIZ STRING + INT 21H ;MDOS CALL + JNC GLD2 + JMP LDERR1 + +GLD2: MOV DATHNDL,AX ;SAVE THE FILE HANDLE + + ; START THE ACTUAL TRANSFER OPERATION +RESTENT:CMP ARG2,0 ;DO WE HAVE ANY DATA? + JNE GLDLP ;....YES + JMP LDERR3 ;....NO + +GLDLP: SUB ARG2,256 ;IS THIS A FULL BLOCK? + JB GLD3 ;....NO + + ; READ A RECORD INTO DS:DX + MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER + MOV CX,RECSIZ ;READ A 512 BYTE RECORD (256 WORDS) + MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CRDRNDZ ;SELECT READ RANDOM RECORD + INT 21H ;INVOKE FUNCTION CALL + CMP AX,CX ;DID WE GET A FULL RECORD? + JE GLDLPA ;....YES + JMP LDERR3 ;....NO + +GLDLPA: MOV CX,RECSIZ ;GET RECORD SIZE (IN BYTES) + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (SOURCE) + MOV AX,ARG1 ;SETUP VMP (DESTINATION) + MOV VMP,AX + MOV VMP0,0 + +GLDLP1: MOV AL,BYTE PTR [BX] ;GET THE BYTE + CALL PB@VMPI ;PUT IT IN VM AND AUTOINC + INC BX ;NEXT BYTE + LOOP GLDLP1 + + ADD ARG1,256 ;UPDATE DESTINATION POINTER + + JMP GLDLP ;KEEP GOING UNTIL WE'VE DONE ALL THE + ; FULL RECORDS + +GLD3: ADD ARG2,256 ;SEE IF THERE'S A PARTIAL RECORD + JZ GLD5 ;....NO + MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER + MOV CX,ARG2 ;GET THE SIZE + SHL CX,1 ;BYTIFY IT + MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CRDRNDZ ;SELECT READ RANDOM RECORD + INT 21H ;INVOKE FUNCTION CALL + CMP AX,CX ;DID WE GET ALL OF THE PARTIAL RECORD? + JE GLD4 ;....YES + JMP LDERR3 ;....NO + +GLD4: MOV CX,ARG2 ;GET RECORD SIZE (IN WORDS) + SHL CX,1 ;BYTIFY + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (SOURCE) + MOV AX,ARG1 ;SETUP VMP (DESTINATION) + MOV VMP,AX + MOV VMP0,0 + +GLDLP2: MOV AL,BYTE PTR [BX] ;GET THE BYTE + CALL PB@VMPI ;PUT IT IN VM AND AUTOINC + INC BX ;NEXT BYTE + LOOP GLDLP2 + + ;CLOSE THE FILE +GLD5: CMP DSKDIR,-1 ;IF NOT -1, THEN SAVE OR RESTORE + JZ GLD5A + CLC ; CLEAR CARRY TO TELL S/R + RET +GLD5A: MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CFCLOSZ ;CLOSE IT + INT 21H + + ; REOPEN THE GAME FILE + MOV AH,CFOPENZ + MOV AL,0 ;OPEN FOR READ + MOV DX,OFFSET GAMFILE + INT 21H + JNC GLD6 + JMP DSKERR + +GLD6: MOV GAMHNDL,AX ;SAVE THE FILE HANDLE + POP DI ;RESTORE GSTACK POINTER + JMP RET1 ;RETURN A "1" + +LDERR0: +LDERR1: +LDERR2: +LDERR3: + CMP DSKDIR,-1 ; IF NOT, THEN SAVE/RESTORE + JZ GLD6A + STC ; WARN SAVE RESTORE + RET + ;CLOSE THE DATA FILE +GLD6A: MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CFCLOSZ ;CLOSE IT + INT 21H + + ; REOPEN THE GAME FILE + MOV AH,CFOPENZ + MOV AL,0 ;OPEN FOR READ + MOV DX,OFFSET GAMFILE + INT 21H + JNC GLD7 + JMP DSKERR ;UNRECOVERABLE ERROR + +GLD7: MOV GAMHNDL,AX ;SAVE THE FILE HANDLE + POP DI ;RESTORE GSTACK POINTER + JMP RET0 +GLOAD ENDP + + ; ---- + ; LDIO + ; ---- + ; + ; PURPOSE: THIS ROUTINE LOADS THE SPECIFIED AMOUNT OF DATA INTO A + ; SPECIFIED BLOCK OF PRELOAD. IT IS THE I/O PORT OPERATION + ; SUBCASE OF {GLOAD}. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; ARG2=LENGTH (IN WORDS) + ; + ; OUTPUTS: DATA IS TRANSFERED TO PRELOAD, IF THE OPERATION IS + ; ILLEGAL OR FAILS FOR ANY REASON, A "0" IS RETURNED + ; VIA {RET0}. ELSE A "1" IS RETURNED VIA {RET1}. + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC LDIO +LDIO PROC +; SUB AX,AX ;SIGNAL A READ OPERATION +; CALL INITIO ;INITIALIZE I/O DEVICE +; +; MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER +; CMP ARG2,0 ;DO WE HAVE A LEGAL LENGTH? +; JE IOERR1 ;....NO +; +;LDIOLP: SUB ARG2,256 ;IS THIS A FULL RECORD? +; JB LDIO1 ;....NO +; MOV CX,RECSIZ ;READ 512 BYTES (256 WORDS) +; CALL IOREAD ; AND PUT THEM IN THE XFER BUFFER +; CMP AX,CX ;DID WE GET THE EXPECTED AMOUNT? +; JNE IOERR1 ;....NO +; MOV CX,256 ;GET RECORD SIZE (IN WORDS) +; CALL XFR2VM ;BLOCK MOVE THE XFER BUFFER TO VIRTUAL +; JMP LDIOLP ;CONTINUE UNTIL WE'VE DONE ALL THE +; ; FULL BLOCKS +; +;LDIO1: ADD ARG2,256 ;COMPUTE PARTIAL RECORD SIZE +; JZ LDIO2 ;NO PARTIAL RECORD +; MOV CX,ARG2 ;GET SIZE OF PARTIAL RECORD +; CALL IOREAD ; GET IT IN THE XFER BUFFER +; CMP AX,CX ;DID WE GET THE EXPECTED AMOUNT? +; JNE IOERR1 ;....NO +; MOV CX,ARG2 ;GET RECORD SIZE (IN WORDS) +; CALL XFR2VM ;....YES, TRANSFER IT TO VM +;LDIO2: JMP RET1 ;SIGNAL SUCCESS + +IOERR1: JMP RET0 ;SIGNAL FAILURE +LDIO ENDP + +;@@ +IOREAD PROC + RET ;DUMMY +IOREAD ENDP + + +;@@ +INITIO PROC + RET ;DUMMY +INITIO ENDP + + + ; ------ + ; XFR2VM + ; ------ + ; + ; PURPOSE: THIS ROUTINE TRANSFERS [CX] BYTES OF DATA FROM THE TRANFER + ; BUFFER TO VIRTUAL MEMORY. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; [CX]=NUMBER OF BYTES TO TRANSFER + ; + ; OUTPUTS: DATA IS TRANSFERED TO PRELOAD + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC XFR2VM +XFR2VM PROC + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (SOURCE) + MOV AX,ARG1 ;SETUP VMP (DESTINATION) + MOV VMP,AX + MOV VMP0,0 + +XFVMLP: MOV AL,BYTE PTR [BX] ;GET THE BYTE + CALL PB@VMPI ;PUT IT IN VM AND AUTOINC + INC BX ;NEXT BYTE + LOOP XFVMLP + RET +XFR2VM ENDP + + PAGE + ; ---- + ; DUMP + ; ---- + ; + ; PURPOSE: THIS ROUTINE TRANSFERS A SPECIFIED AMOUNT OF DATA FROM + ; A SUPPLIED VIRTUAL MEMORY ADDRESS. IF ARG3 IS PROVIDED, + ; THEN THIS IS A TRANSFER TO DISK. ELSE, IT IS AN I/O PORT + ; OPERATION. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; ARG2=LENGTH + ; ARG3=FILENAME POINTER (OPTIONAL) + ; + ; OUTPUTS: DATA IS TRANSFERED FROM VIRTUAL MEMORY, IF THE + ; OPERATION IS ILLEGAL OR FAILS FOR ANY REASON, + ; A "0" IS RETURNED VIA {RET0}. ELSE A "1" IS + ; RETURNED VIA {RET1}. + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC GDUMP +GDUMP PROC + ; DETERMINE TRANSFER TYPE + CMP NARGS,3 ;IS THIS A FILE TRANSFER REQUEST? + JE GDM0 ;....YES + JMP DMIO ;....NO, IT'S AN I/O TRANSFER + + ; + ; FILE TRANSFER REQUEST + ; + + ; ASSUME THAT THE DEFAULT DISK IS TO BE USED + ; CLOSE THE GAMEFILE +GDM0: MOV AH,CFCLOSZ ;CLOSE THE GAME FILE FOR REINSERTION + MOV BX,GAMHNDL ;IN CASE THIS IS A 1 DRIVE SYSTEM, + INT 21H ; OR THE DEFAULT DRIVE IS SPECIFIED + MOV AH,CDRESET ;AND FLUSH + INT 21H + + ; PARSE THE FILENAME + MOV AX,ARG3 ;SET UP VMP TO POINT TO THE FILENAME + MOV VMP,AX + MOV VMP0,0 + CALL GW@VMPI ;GET THE LENGTH OF THE FILENAME + MOV CX,AX ;IN CX FOR USE AS A LOOP COUNTER + MOV BX,OFFSET DATFILE ;^ FCB + + ;GET THE FILENAME INTO THE FCB +GDM1: CALL GB@VMPI ;GET A CHARACTER + MOV [BX],AL ;PUT IT IN THE FCB + INC BX ;NEXT CHARACTER + LOOP GDM1 ; GET THE REST + MOV BYTE PTR [BX],0 ;DROP IN A NUL AT THE END OF THE NAME + + PUSH DI ;SAVE SOME REGISTERS + PUSH DS + POP ES ;BOTH ES & DS POINT AT THE DATA SEGMENT + + ; OPEN THE DATA FILE + MOV AH,CFCREAZ ;SELECT CREATE FILE + SUB CX,CX ;SELECT READ/WRITE ATTRIBUTE + MOV DX,OFFSET DATFILE ;POINT AT THE ASCIIZ STRING + INT 21H ;MDOS CALL + JNC GDM2 + JMP DMERR1 + +GDM2: MOV DATHNDL,AX ;SAVE THE FILE HANDLE + + ; START THE ACTUAL TRANSFER OPERATION +SAVENT: CMP ARG2,0 ;DO WE HAVE A LEGAL LENGTH? + JNE GDMLP ;....YES + JMP DMERR0 ;....NO + + ; PROCESS THE FULL RECORDS +GDMLP: SUB ARG2,256 ;IS THIS A FULL BLOCK? + JB GDM3 ;....NO + + ; TRANSFER A FULL RECORD FROM VIRTUAL MEMORY TO THE TRANSFER BUFFER + MOV CX,RECSIZ ;GET RECORD SIZE (IN BYTES) + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (DESTINATION) + MOV AX,ARG1 ;SETUP VMP (SOURCE) + MOV VMP,AX + MOV VMP0,0 + +GDMLP1: CALL GB@VMPI ;GET THE BYTE AND AUTOINC + MOV BYTE PTR [BX],AL ;PUT IT IN XFRBUF + INC BX ;NEXT DESTINATION + LOOP GDMLP1 + + ADD ARG1,256 ;UPDATE SOURCE POINTER + + ; WRITE A FULL RECORD TO THE DISK + MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER + MOV CX,RECSIZ ;WRITE A 512 BYTE RECORD (256 WORDS) + MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CWRRNDZ ;SELECT WRITE RANDOM RECORD + INT 21H ;INVOKE FUNCTION CALL + + CMP AX,CX ;DID WE WRITE A FULL RECORD? + JE GDMLP ;....YES, TRY ANOTHER + JMP DMERR2 ;....NO + + + ; PARTIAL RECORD +GDM3: ADD ARG2,256 ;SEE IF THERE'S A PARTIAL RECORD + JZ GDM4 ;....NO + + ; TRANSFER PARTIAL RECORD FROM VIRTUAL MEMORY TO THE TRANSFER BUFFER + MOV CX,ARG2 ;GET THE SIZE (IN WORDS) + SHL CX,1 ;BYTIFY + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (DESTINATION) + MOV AX,ARG1 ;SETUP VMP (SOURCE) + MOV VMP,AX + MOV VMP0,0 + +GDMLP2: CALL GB@VMPI ;GET THE BYTE AND AUTOINC + MOV BYTE PTR [BX],AL ;PUT IT IN XFRBUF + INC BX ;NEXT DESTINATION + LOOP GDMLP2 + + ; WRITE A PARTIAL RECORD TO THE DISK + MOV CX,ARG2 ;GET THE SIZE (IN WORDS) + SHL CX,1 ;BYTIFY + MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER + MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CWRRNDZ ;SELECT WRITE RANDOM RECORD + INT 21H ;INVOKE FUNCTION CALL + CMP AX,CX ;DID WE WRITE ENOUGH? + JE GDM4 ;....YES + JMP DMERR2 ;....NO + + ;CLOSE THE DATA FILE +GDM4: CMP DSKDIR,-1 ; CHECK SAVE RESTORE FLAG + JZ GDM4A + CLC ; CLEAR TO SAVE/RESTORE + RET +; +GDM4A: MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CFCLOSZ ;CLOSE IT + INT 21H + + ; REOPEN THE GAME FILE + MOV AH,CFOPENZ + MOV AL,0 ;OPEN FOR READ + MOV DX,OFFSET GAMFILE + INT 21H + JNC GDM5 + JMP DSKERR + +GDM5: MOV GAMHNDL,AX ;SAVE THE FILE HANDLE + POP DI ;RESTORE GSTACK POINTER + JMP RET1 ;RETURN A "1" + +DMERR0: +DMERR1: +DMERR2: + CMP DSKDIR,-1 ; CHECK SAVE/RESTORE FLAG + JZ GDM5A + STC ; WARN SAVE RESTORE + RET + ;CLOSE THE DATA FILE +GDM5A: MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CFCLOSZ ;CLOSE IT + INT 21H + + ; REOPEN THE GAME FILE + MOV AH,CFOPENZ + MOV AL,0 ;OPEN FOR READ + MOV DX,OFFSET GAMFILE + INT 21H + JNC GDM6 + JMP DSKERR ;UNRECOVERABLE ERROR + +GDM6: MOV GAMHNDL,AX ;SAVE THE FILE HANDLE + POP DI ;RESTORE GSTACK POINTER + JMP RET0 +GDUMP ENDP + + ; ---- + ; DMIO + ; ---- + ; + ; PURPOSE: THIS ROUTINE DUMPS A SPECIFIED AMOUNT OF DATA FROM + ; PRELOAD TO THE I/O PORT. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; ARG2=LENGTH (IN WORDS) + ; + ; OUTPUTS: DATA IS TRANSFERED TO THE I/O PORT, IF THE OPERATION + ; IS ILLEGAL OR FAILS FOR ANY REASON, A "0" IS RETURNED + ; VIA {RET0}. ELSE A "1" IS RETURNED VIA {RET1}. + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC DMIO +DMIO PROC +; MOV AX,1 ;SIGNAL A WRITE OPERATION +; CALL INITIO ;INITIALIZE I/O DEVICE +; +; MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER +; CMP ARG2,0 ;DO WE HAVE A LEGAL LENGTH? +; JE IOERR2 ;....NO +; +;DMIOLP: SUB ARG2,256 ;IS THIS A FULL RECORD? +; JB DMIO1 ;....NO +; CALL VM2XFR ;BLOCK MOVE THE VM BLOCK TO XFER BUFFER +; +; MOV CX,RECSIZ ;WRITE 512 BYTES (256 WORDS) +; CALL IOWRITE ; AND PUT THEM IN THE XFER BUFFER +; CMP AX,CX ;DID WE WRITE THE EXPECTED AMOUNT? +; JNE IOERR2 ;....NO +; JMP DMIOLP ;CONTINUE UNTIL WE'VE DONE ALL THE +; ; FULL BLOCKS +; +;DMIO1: ADD ARG2,256 +; MOV CX,ARG2 ;SETUP SIZE OF PARTIAL RECORD +; CMP CX,0 ;DO WE EVEN HAVE A PARTIAL RECORD? +; JE DMIO2 ;....NO +; +; CALL VM2XFR ;BLOCK MOVE THE VM BLOCK TO XFER BUFFER +; CALL IOWRITE ; AND PUT THEM IN THE XFER BUFFER +; CMP AX,CX ;DID WE WRITE THE EXPECTED AMOUNT? +; JNE IOERR2 ;....NO +; +;DMIO2: JMP RET1 ;SIGNAL SUCCESS +; +IOERR2: JMP RET0 ;SIGNAL FAILURE +DMIO ENDP + +;@@ +IOWRITE PROC + RET ;DUMMY +IOWRITE ENDP + + + ; ------ + ; VM2XFR + ; ------ + ; + ; PURPOSE: THIS ROUTINE TRANSFERS [CX] BYTES OF DATA FROM VIRTUAL + ; MEMORY TO THE TRANSFER BUFFER. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; [CX]=NUMBER OF BYTES TO TRANSFER + ; + ; OUTPUTS: DATA IS TRANSFERED TO XFRBUF + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC VM2XFR +VM2XFR PROC + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (DESTINATION) + MOV AX,ARG1 ;SETUP VMP (SOURCE) + MOV VMP,AX + MOV VMP0,0 + +VMXFLP: CALL GB@VMPI ;GET THE BYTE AND AUTOINC + MOV BYTE PTR [BX],AL ;PUT IT IN XFRBUF + INC BX ;NEXT DESTINATION + LOOP VMXFLP + RET +VM2XFR ENDP + + PAGE + ;---------------------- + ; ITERATIONS + ;---------------------- + ; + ; EXECUTE THE ITERATION TABLE AT [ARG2] + ; {FOR I=ITPNT TO ITICN + ; + ; DRAW THE ACTIVE ICON [ITERATION] + ; + ; UPDATE THE ICON'S ITERATION COUNTER + ; + ; TEST FOR INPUT + ; IF INPUT THEN SAVE THE NEXT ACTIVE ICON ENTRY NUMBER + ; AND PROCESS THE INPUT} + ; + ; NEXT I} + ; + ; IF DONE + ; REINITIALIZE ITPNT <= 1 + ; BRANCH TO NOIT}. + + PUBLIC ITRATE +ITRATE PROC + MOV AX,ARG2 ;POINT AT THE ITERATION TABLE + MOV VMP,AX + MOV VMP0,0 + + CALL GB@VMPI ;GET THE NUMBER OF ENTRIES + MOV ITICN,AL + + MOV AL,VMP0 ;SAVE POINTER TO ITPNT + MOV VMSAV0,AL + MOV AX,VMP + MOV VMSAV,AX + + CALL GB@VMPI ;GET THE ENTRY TO START WITH + MOV ITPNT,AL ; WE'RE POINTING AT THE FIRST WORD + ; IN THE FIRST ENTRY + + MOV AL,1 ;SKIP ENTRIES 1 TO ITPNT + +ITLP2: CMP AL,ITPNT + JZ ITLOOP + + ADD VMP,6 ;SIX WORDS PER ENTRY + INC AL + JMP ITLP2 + + ; PROCESS THE DATA FOR THE CURRENT ACTIVE ICON +ITLOOP: MOV AX,VMP ;SAVE POINTER TO THE CURRENT + PUSH AX ; ACTIVE ICON'S DATA BASE + MOV AL,VMP0 + PUSH AX + + CALL GW@VMPI ;GET ICON BASE ADDRESS + MOV IADR1,AX + MOV IADR10,0 + + CALL GW@VMPI ;GET ICON HORIZONTAL POSITION + MOV ARG1,AX + + CALL GW@VMPI ;GET ICON VERTICAL POSITION + MOV ARG2,AX + + CALL GW@VMPI + MOV NEGATE,AH ;NEGATE + MOV BYTE PTR I,AL ;CURRENT ITERATION + + CALL GW@VMPI + MOV BSET,AH ;BLOCKSET ID + MOV ITERS,AL ;# OF ITERATIONS + + CALL GW@VMPI + MOV IX1,AH ;WIDTH + MOV IY1,AL ;HEIGHT + + ; UPDATE THE CURRENT ITERATION IN THE DATA STRUCTURE + MOV BL,BYTE PTR I + CMP BL,ITERS ;CURRENT ITERATION=NO. OF ITERATIONS? + JNE ITSKP2 ;....NO + MOV BL,0 ;....YES, SET IT TO 0 SO IT'LL BE 1 + +ITSKP2: INC BL ;NEXT POSSIBLE ITERATION + POP AX ;RESTORE POINTER TO THE + MOV VMP0,AL ; CURRENT ACTIVE ICON'S DATA BASE + POP AX + MOV VMP,AX + + MOV AX,7 ;POINT TO THE CURRENT ITERATION + CALL ADDVMP + + MOV AX,BX ;SAVE UPDATED VALUE + CALL PB@VMPI + + ; UPDATE POINTER TO THE NEXT ACTIVE ICON + ADD VMP,2 ;IT'S 4 MORE BYTES TO THE NEXT ACTIVE ICON + MOV AX,VMP ;SAVE POINTER TO THE + PUSH AX ; NEXT ACTIVE ICON'S DATA BASE + MOV AL,VMP0 + PUSH AX + + ; POINT TO THE CURRENT ICON'S BLOCK I.D. DATA + MOV AL,IX1 ;GET LENGTH OF ONE ICON + MUL IY1 + DEC BYTE PTR I ;ZERO ALIGN + MOV BL,BYTE PTR I + SUB BH,BH + MUL BX ;PRODUCT S/B IN AX + + ADD IADR1,2 ;POINT PAST HEADER (2 WORDS) + CALL AIADR1 ;ADD IN OFFSET + + ; DRAW THE ITERATION + MOV MSKFLG,0 ;DISABLE MASKING + CALL ITENT ;DRAW THE ICON + + ; + ; HAVE WE PROCESSED ALL THE ACTIVE ICONS? + ; + MOV AL,ITPNT ;ARE WE DONE? + CMP AL,ITICN + JE ITEXI ;....YES + + INC ITPNT ;....NO. POINT TO THE NEXT ICON + + ; INPUT PROCESSING + TEST BYTE PTR VALUE,80H ;IF INPUT WAS CALLED WITH A NEGATIVE + JNZ NONSNS ;INT THEN DON'T LOOK FOR INPUT + + CALL SENSE ;ELSE, POLL THE KEYBOARD + CMP AL,8FH ;DO WE HAVE AN INPUT? + JNE ITSKP5 ;....YES + +NONSNS: POP AX ;RESTORE POINTER TO THE + MOV VMP0,AL ; NEXT ACTIVE ICON'S DATA BASE + POP AX + MOV VMP,AX + JMP ITLOOP + + ; WE RECEIVED AN INPUT WHILE ITERATING + ; SO, WE SAVE WHERE WE ARE AND PROCESS THE INPUT +ITSKP5: PUSH AX ;SAVE INPUT + + MOV AL,VMSAV0 ;RESTORE POINTER TO ACTIVE TABLE HEADER + MOV VMP0,AL ; ITPNT ENTRY + MOV AX,VMSAV + MOV VMP,AX + + MOV AL,ITPNT ;SAVE WHERE WE LEFT OFF + CALL PB@VMP + + POP AX ;RESTORE SENSE + POP BX ;FLUSH VMP POINTER TO CURRENT ACTIVE ICON + POP BX + JMP PUTBYT + + ; WE ITERATED ALL THE ICONS IN THE ACTIVE TABLE + ; SO, WE SET UP TO DO IT AGAIN LATER AND EXIT +ITEXI: POP BX ;FLUSH VMP0 + POP BX ;FLUSH VMP + + MOV AL,VMSAV0 ;RESTORE POINTER TO ACTIVE TABLE HEADER + MOV VMP0,AL ; ITPNT ENTRY + MOV AX,VMSAV + MOV VMP,AX + MOV AL,1 ;SET ITPNT ENTRY TO 1 + CALL PB@VMP + JMP NOIT ; AND RESUME INPUT PROCESSING +ITRATE ENDP + + PAGE + ;-------------------------------------------------- + ; OPCODE EXECUTION PROCEDURES SUPPORT CODE + ;-------------------------------------------------- + + ; ------ + ; TSTPRE + ; ------ + ; + ; PURPOSE: THIS ROUTINE TESTS THE RANGE OF A SPECIFIED VIRTUAL MEMORY + ; BLOCK TO DETERMINE IF IT IS ALL CONTAINED IN EITHER + ; G-PRELOAD OR I-PRELOAD. + ; + ; INPUTS: [ARG1] VIRTUAL MEMORY STARTING ADDRESS (WORD POINTER) + ; [ARG2] LENGTH IN WORDS + ; + ; OUTPUTS: CARRY CLEAR IF IN PRELOAD + ; CARRY SET IF NOT IN PRELOAD + ; + ; REGISTERS DESTROYED: AX + ; + PUBLIC TSTPRE +TSTPRE PROC + ; TEST STARTING ADDRESS + MOV AX,ARG1 ;GET STARTING ADDRESS + CMP AH,GPEND ;DOES THE ADDRESS RESIDE BELOW THE + ; FIRST BLOCK OF G-PURE? + JB TPR0 ;....YES, IT'S G-PRELOAD + + CMP AX,ICODE ;IS IT GE. I-PRELOAD? + JB TPRERR ;....NO, IT'S NOT PRELOAD. + CMP AX,IPURE ;IS IT < IPURE + JB TPR1 ;....YES, IT'S I-PRELOAD + JMP TPRERR ;FAIL, IT'S NOT PRELOAD + + ; TEST LAST ADDRESS TO SEE IF IT'S IN G-PRELOAD TOO +TPR0: ADD AX,ARG2 ;ADD LENGTH + CMP AH,GPEND ;DOES THE ADDRESS RESIDE BELOW THE + ; FIRST BLOCK OF G-PURE? + JB TPREOK ;....YES, IT'S GOOD + JMP TPRERR ;FAIL IF NOT IN G-PRELOAD + + ; TEST LAST ADDRESS TO SEE IF IT'S IN I-PRELOAD TOO +TPR1: ADD AX,ARG2 ;ADD LENGTH + CMP AX,IPURE ;IS IT < IPURE + JB TPREOK ;....YES, IT'S I-PRELOAD + +TPRERR: STC ;SET CARRY FOR FAILURE + RET + +TPREOK: CLC ;CLEAR CARRY FOR SUCCESS + RET +TSTPRE ENDP + + PAGE + ; -------------------------------- + ; POP GSTACK INTO [VALUE] AND [AX] + ; -------------------------------- + ; + PUBLIC POPVAL +POPVAL PROC + CALL POPAXG ;POP A VALUE + MOV VALUE,AX ;SAVE IT IN VALUE + RET +POPVAL ENDP + + ; -------------------------- + ; UPDATE VALUE OF A VARIABLE + ; -------------------------- + + ; ENTRY: VALUE TO STORE IN [VALUE] + ; VARIABLE ID IN AX + PUBLIC VARPUT,PTV1$,PTV2$ +VARPUT PROC + CMP AX,0 ;LOCAL OR GLOBAL + JNE PTV1$ ;....YES. + MOV AX,VALUE ;....NO. STACK. GET VALUE + JMP PSHAXG ; AND PUSH IT ON THE GSTACK + + ;SAVE [VALUE] TO LOCAL OR GLOBAL +PTV1$: PUSH BX ;SAVE AFFECTED REGISTER(S) + MOV BX,GLOCS ;ASSUME IT'S A LOCAL + CMP AX,16 ;WAS IT A LOCAL? + JNB PTV2$ ;....NO + DEC AX ;....YES, ZERO ALIGN + JMP PTV3$ + + ; IT WAS A GLOBAL +PTV2$: MOV BX,GLOBAL ;GET GLOBAL TABLE BASE ADDRESS + SUB AX,16 ;ZERO ALIGN + +PTV3$: MOV VMP,BX ;PUT ADDRESS INTO VIRTUAL MEMORY POINTER + MOV VMP0,0 ;IT MUST BE ON AN EVEN BOUNDRY + ADD VMP,AX + MOV AX,VALUE ;GET THE VALUE + + POP BX ;RESTORE AFFECTED REGISTER(S) + JMP PW@VMP ; AND WRITE IT TO VIRTUAL + +VARPUT ENDP + + ; ---------------------------------- + ; GET A VARIABLE FROM THE MAINLOOP + ; ---------------------------------- + + ; IMPORTS: VARIABLE ID IN G-CODE + ; EXPORTS: VALUE RETURNED IN AX AND [VALUE] + PUBLIC GETVAR +GETVAR PROC + CALL GB@GPCI ;GET VARIABLE ID + JMP VARGET +GETVAR ENDP + + ; -------------------------------------- + ; GET A VARIABLE FROM WITHIN AN OPCODE + ; -------------------------------------- + + ; IMPORTS: VARIABLE ID IN [AL] + ; EXPORTS: VALUE RETURNED IN AX AND [VALUE] + PUBLIC VARGET,GTV1$,GTV2$ +VARGET PROC + CMP AL,0 ;IF ID NE. 0 + JNE GTV1$ ; THEN ACCESS A VARIABLE + JMP POPVAL ;ELSE, POP GSTACK INTO [AX] AND [VALUE] + + ; IS THE VARIABLE LOCAL OR GLOBAL +GTV1$: PUSH BX ;SAVE AFFECTED REGISTER(S) + MOV BX,GLOCS ;ASSUME IT'S A LOCAL + CMP AX,16 ;WAS IT? + JNB GTV2$ ;....NO + DEC AX ;....YES, ZERO ALIGN + JMP GTV3$ + + ; HANDLE A GLOBAL VARIABLE +GTV2$: MOV BX,GLOBAL ;GET GLOBAL TABLE BASE ADDRESS + SUB AX,16 ;POINT TO TABLE ELEMENT + +GTV3$: MOV VMP,BX ;PUT ADDRESS INTO VIRTUAL MEMORY POINTER + MOV VMP0,0 ;IT MUST BE ON AN EVEN BOUNDRY + ADD VMP,AX + CALL GW@VMP ;GET THE VARIABLE + MOV VALUE,AX ;PUT IT IN [VALUE] + POP BX ;RESTORE AFFECTED RESISTER(S) + RET + +VARGET ENDP + + ; --------------- + ; PREDICATE FAILS + ; --------------- + + ;PREDICATE HANDLERS TRUE & FALSE + ;DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FCNS + PUBLIC PREDF,PREDF1 +PREDF PROC + CALL GB@GPCI ;GET FIRST BRANCH BYTE + OR AL,AL + JNS PREDF1 ;BRANCH IF BIT 7 CLEAR + JMP PREDNB ; ELSE IGNORE PREDICATE BRANCH +PREDF1: JMP PREDB +PREDF ENDP + + ; ----------------------- + ; IGNORE PREDICATE BRANCH + ; ----------------------- + PUBLIC PREDNB,PREDN0 +PREDNB PROC + AND AL,01000000B ;TEST BIT 6 + JNZ PREDN0 ;SHORT BRANCH IF SET + JMP GB@GPCI ;ELSE SKIP OVER 2ND BRANCH BYTE +PREDN0: RET +PREDNB ENDP + + ; ------------------ + ; PREDICATE SUCCEEDS + ; ------------------ + PUBLIC PREDS,PREDS0 +PREDS PROC + CALL GB@GPCI ;GET FIRST BRANCH BYTE + OR AL,AL + JNS PREDS0 ;DON'T BRANCH IF BIT 7 IS CLEAR + JMP PREDB ; ELSE, DO A PREDICATE BRANCH +PREDS0: JMP PREDNB +PREDS ENDP + + ; -------------------------- + ; PERFORM A PREDICATE BRANCH + ; -------------------------- + + ; ENTRY: 1ST PRED BYTE IN [AL] + PUBLIC PREDB,PREDLB,DOB2,PREDB1,PREDB2,PRDB2A +PREDB PROC + SUB AH,AH ;MSB NOT USED + TEST AL,01000000B ;LONG OR SHORT BRANCH? + JZ PREDLB ;LONG IF BIT 6 IS CLEAR + + ; HANDLE A SHORT BRANCH + AND AL,00111111B ;FORM SHORT OFFSET + MOV WORD PTR VALUE,AX ;MSB OF OFFSET IS ZERO + JMP PREDB1 ;DO THE BRANCH + + ; HANDLE A LONG BRANCH +PREDLB: AND AL,00111111B ;FORM MSB OF OFFSET + TEST AL,00100000B ;CHECK SIGN OF 14-BIT VALUE + JZ DOB2 ;POSITIVE? + OR AL,11100000B ;....NO. EXTEND SIGN BIT + +DOB2: MOV BL,AL ;PUT MSB OF OFFSET IN BL + CALL GB@GPCI ;GET LSB OF 14-BIT OFFSET + MOV AH,BL ; RECOVER THE MSB + MOV VALUE,AX ;SAVE THE BRANCH OFFSET IN VALUE + + ; TEST BRANCH OFFSET +PREDB1: OR AH,AH ;CHECK MSB OF OFFSET + JNZ PREDB3 ;DO BRANCH IF NZ + OR AL,AL ;IF LSB IS NZ + JNZ PREDB2 ;MAKE SURE IT ISN'T A "1" + JMP GRFALS ; ELSE, DO AN "RFALSE" + +PREDB2: CMP AL,1 ;IS OFFSET= 1 + JNZ PRDB2A ;....NO. DO THE BRANCH + JMP GRTRUE ; ELSE, DO AN "RTRUE" + +PRDB2A: JMP PREDB3 ;EXECUTE THE "JUMP" +PREDB ENDP + + ;ENTRYPOINT FOR "JUMP" + PUBLIC PREDB3 +PREDB3 PROC + MOV AX,WORD PTR VALUE ;GET THE OFFSET + SUB AX,2 ;CALC [VALUE] - 2 + + ;CONVERT A 16-BIT OFFSET TO 17 BITS + SAR AX,1 ;PROCESS THE LS BIT, AND SIGN EXTEND + JNC PRDB3A ;SKIP IF "0" + + ; ELSE WE HAVE TO INCREMENT GPC + XOR GPC0,1 ;CHANGE THE STATE OF BIT0 + JNZ PRDB3A ;CONTINUE IF CHANGING FROM "0" TO A "1" + INC GPC ;ELSE BUMP THE REST OF GPC + +PRDB3A: ADD GPC,AX ;ADD IN THE REST OF THE OFFSET + RET +PREDB3 ENDP + + ; ------ + ; AIADR1 + ; ------ + ; + ; ENTRY: IADR1 + ; [AX] = VALUE TO BE ADDED TO IADR1 + ; + ; EXIT: IADR1 <= IADR1 + [AX] + ; +AIADR1 PROC + SHR AX,1 ;THINK ABOUT IT + JNC AIAD1 + + XOR IADR10,1 ;CHANGE THE STATE OF BIT0 + JNZ AIAD1 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC IADR1 ;ELSE BUMP THE REST OF IADR1 + +AIAD1: ADD IADR1,AX + RET +AIADR1 ENDP + + ; ------ + ; AIADR2 + ; ------ + ; + ; ENTRY: IADR2 + ; [AX] = VALUE TO BE ADDED TO IADR2 + ; + ; EXIT: IADR2 <= IADR2 + [AX] + ; +AIADR2 PROC + SHR AX,1 ;THINK ABOUT IT + JNC AIAD2 + + XOR IADR20,1 ;CHANGE THE STATE OF BIT0 + JNZ AIAD2 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC IADR2 ;ELSE BUMP THE REST OF IADR2 + +AIAD2: ADD IADR2,AX + RET +AIADR2 ENDP + + ; ------------ + ; RETURN A "0" + ; ------------ + + PUBLIC RET0 +RET0 PROC + MOV AL,0 + JMP PUTBYT +RET0 ENDP + + ; ------------ + ; RETURN A "1" + ; ------------ + + PUBLIC RET1 +RET1 PROC + MOV AL,1 + + ; AND FALL THROUGH ............. + +RET1 ENDP + + ; ----------------------- + ; RETURN A BYTE VIA [GPC] + ; ----------------------- + ; + ;RETURNS THE BYTE IN AL TO THE LOCATION SPECIFIED BY THE GPC + ;DESTROYS BX, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION + PUBLIC PUTBYT +PUTBYT PROC + SUB AH,AH ;THIS ENTRY FOR BYTE VALUE TO CLEAR HIGH BYTE + MOV VALUE,AX + JMP PUTVAL +PUTBYT ENDP + + ; --------------------------------------------------- + ; RETURN [VALUE] TO THE LOCATION SPECIFIED BY THE GPC + ; --------------------------------------------------- + + ; ENTRY: [VALUE] <= THE VALUE TO RETURN + ; [GPC] <= VARIABLE ID + ; + ; EXIT: [VALUE] IS STORED + ; GPC <= GPC + 1 + PUBLIC PUTVAL,PUTVL0,PUTVL1 +PUTVAL PROC + CALL GB@GPCI ;GET VAR TO USE + CMP AX,0 ;STACK? + JNE PUTVL0 ;NO, GO STORE VALUE + + ; VARIABLE ID=0 + ; PUSH [VALUE] ONTO THE GSTACK + MOV AX,VALUE ;GET [VALUE] + JMP PSHAXG ;PUSH IT ONTO GSTACK + + ; VARIABLE ID <> 0 + ; SAVE [VALUE] TO LOCAL OR GLOBAL +PUTVL0: PUSH BX ;SAVE AFFECTED REGISTER(S) + MOV BX,GLOCS ;ASSUME IT'S A LOCAL + CMP AX,16 ;WAS IT? + JNB PUTVL1 ;....NO + DEC AX ;....YES, ZERO ALIGN + JMP PUTVL2 + + ; HANDLE A GLOBAL VARIABLE +PUTVL1: MOV BX,GLOBAL ;GET GLOBAL TABLE BASE ADDRESS + SUB AX,16 ;POINT TO TABLE ELEMENT + +PUTVL2: MOV VMP,BX ;PUT ADDRESS INTO VIRTUAL MEMORY POINTER + MOV VMP0,0 ;IT MUST BE ON AN EVEN BOUNDRY + ADD VMP,AX + MOV AX,VALUE ;GET THE VALUE + POP BX ;RESTORE AFFECTED REGISTER(S) + JMP PW@VMP ; AND WRITE IT TO VIRTUAL + +PUTVAL ENDP + + SUBTTL GRAPHIC OPCODE SUPPORT ROUTINES + PAGE + ; ------------------------------------------- + ; GET GRAPHICS BLOCK [AL] IN CURRENT BLOCKSET + ; ------------------------------------------- + + ; ENTRY: BLOCK ID # (1-255) IN [AL] + ; EXIT: BLOCK DATA IN [BLOCK] + PUBLIC GTGBLK,GBLL +GTGBLK PROC + PUSH BX + PUSH CX + + ;CALCULATE OFFSET FROM THE START OF BLOCKSET + MOV BX,BSADR ;GET BASE ADDRESS OF BLOCKSET + MOV VMP,BX ;SETUP VMP + MOV VMP0,0 + + XOR AH,AH ; (B5) CLEAN OUT TOP HALF + MOV CL,3 + SHL AX,CL ; (B5) MULTIPLY BY COMMON BLOCK LEN + + CALL ADDVMP ;SET UP VADDR OF FIRST BYTE IN BLOCK + + ;SETUP LOOP COUNTER AND INDEX + MOV CL,4 + SUB CH,CH + MOV BX,OFFSET BLOCK + +GBLL: CALL GW@VMPI ;GET A WORD + XOR AL,NEGATE ;INVERT BITS IF NEGATE=0FFH + XOR AH,NEGATE ;INVERT BITS IF NEGATE=0FFH + XCHG AH,AL ;SWAPIFY + MOV [BX],AX ; STORE [BLOCK (BX)] + INC BX ; AND [BLOCK (BX + 1)] + INC BX ;UPDATE DESTINATION + LOOP GBLL ;LOOP TILL ALL BYTES ARE DONE + + POP CX + POP BX + RET +GTGBLK ENDP + + PUBLIC GTGFST +GTGFST PROC + CMP FSIZE,0 ; (B5) WHOLE GAME IN? + JNE GTF0 + JMP GTGBLK ; (B5) TAKE THE LONG WAY HOME + +GTF0: PUSH BX + PUSH CX + PUSH DI + PUSH SI + + ;CALCULATE OFFSET FROM THE START OF BLOCKSET + + MOV BX,0 ; (B5) FLAG TO INDICATE RESTORATION OF ES + JMP GTF1 + + ; FIX AX TO BE BLOCK ID AND USE SLOW GET BLOCK BECAUSE OF SEG + ; BOUNDARY CROSSING + +GTFIX: PUSH ES + MOV CX,ES + ADD CX,1000H + MOV ES,CX ; (B5) SET UP FOR NEXT SEG + MOV BX,1 ; (B5) SET FLAG FOR SEG RESTORE + JMP GTF4 ; (B5) GET BLOCK FROM NEXT SEG + + +GTF1: MOV CL,3 ; (B5) SHIFT COUNT + XOR AH,AH ; (B5) MULTIPLY BY BLKLEN + SHL AX,CL ; (B5) DO IT + +GTF2: ADD DI,AX ; (B5) ADD IN OFFSET + JC GTFIX + ADD DI,8 ; (B5) CHECK IF WE'LL CROSS SEG + JNC GTF3 + MOV BX,2 ; (B5) USE BX AS A FLAG FOR THIS COND +GTF3: SUB DI,8 ; (B6) FIX DI +GTF4: XCHG SI,DI ; (B5) GET POINTER + MOV DI,OFFSET BLOCK ; (B5) GET BLOCK ADDRESS + + ;SETUP LOOP COUNTER AND INDEX + MOV CL,4 + MOV CH,NEGATE + PUSH DS ; (B5) SAVE SEGS AND SWAP 'EM + PUSH ES + PUSH DS + PUSH ES + POP DS + POP ES + CMP BX,2 ; (B5) CHECK FOR WRAP INDICATOR + JNE GFLL + +GFSL: LODSW ; (B5) GET A WORD + CMP SI,0 ; (B5) CHECK FOR WRAP + JNE GFSL1 ; (B5) NOT YET + MOV BX,DS ; (B5) IT DID, FIX SEG + ADD BX,1000H ; (B5) TO ADDRESS NEXT SEG + MOV DS,BX ; (B5) FINISH FIX UP + MOV BX,0 ; (B5) RESET BX +GFSL1: XOR AL,CH ; (B5) CONTINUE PROCESS + XOR AH,CH + STOSW ; (B5) FILL IN REST OF BLOCK + DEC CL ; (B5) AND DECREMENT LOOP CNTR + JNZ GFSL ; (B5) CONTINUE IF BYTES LEFT + JMP GFRES ; (B5) OR EXIT + +GFLL: LODSW ; (B5) GET A WORD + XOR AL,CH ;INVERT BITS IF NEGATE=0FFH + XOR AH,CH ;INVERT BITS IF NEGATE=0FFH + STOSW ; (B5) STORE [BLOCK (BX)] + DEC CL + JNZ GFLL + +GFRES: POP ES + POP DS + + CMP BX,1 ; (B5) LOOK FOR RESTORE BIT + JNE GTF5 + POP ES ; (B5) SEG CROSS, RESTORE ES + +GTF5: POP SI + POP DI + POP CX + POP BX + RET +GTGFST ENDP + + ; ------------------------ + ; SETUP FOR SETI AND SWAPI + ; ------------------------ + PUBLIC ISETUP +ISETUP PROC + MOV AX,WORD PTR ARG4 ;GET WRD PTR ADDR OF DESTINATION ICON + CMP AX,IPURE ;IS DEST IN I-PRELOAD? + JB ISU ;....YES. SO CONTINUE + JMP PRERR2 ;ELSE PURITY VIOLATION! + + ; AND FALL THROUGH ............. + +ISETUP ENDP + + ; ---------------------------- + ; SETUP ENTRYPOINT FOR MASKING + ; ---------------------------- + PUBLIC ISU +ISU PROC + CALL GETI ;FETCH STATS OF DEST ICON + MOV AL,BYTE PTR IX1 ;COPY DEST ICON STATS + MOV BYTE PTR IX2,AL ;TO AUXILIARY STORAGE + MOV AL,BYTE PTR IY1 + MOV BYTE PTR IY2,AL + + MOV AX,WORD PTR IADR1 + MOV WORD PTR IADR2,AX + + MOV AL,IADR10 + MOV IADR20,AL + + MOV AX,ARG3 ;NOW GET THE SOURCE ICON STATS + + ; AND FALL THROUGH ............. + +ISU ENDP + + ; -------- + ; GET ICON + ; -------- + + ; ENTRY: V-ADDR OF ICON DATA DEFINITION IN [AX] + ; + ; EXIT: ICON DATA V-ADDR IN [IADR1] + ; X-SIZE IN [IX1] AND [XDEX1] + ; Y-SIZE IN [IY1] AND [YDEX1] + ; ASSIGNED BLOCKSET IN [BSET] + PUBLIC GETI,NEWXY +GETI PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + + MOV VMP,AX ;LOAD VIRTUAL MEMORY POINTER + MOV VMP0,0 + CALL GW@VMPI ;THE FIRST WORD HAS + MOV BYTE PTR BSET,AH ; THE ASSIGNED BLOCKSET + MOV BYTE PTR ITERS,AL ; AND THE # OF ITERATIONS + + CALL GW@VMPI ;THE SECOND WORD HAS + MOV BYTE PTR IX1,AH ; X-SIZE + MOV BYTE PTR IY1,AL ; AND Y-SIZE + + MOV AX,VMP ;GET BASE V-ADDR + MOV WORD PTR IADR1,AX ;IN [IADR1] + MOV AL,VMP0 + MOV IADR10,AL + + ; SETUP [XDEX1] & [YDEX1] +NEWXY: MOV AL,BYTE PTR IX1 + MOV BYTE PTR XDEX1,AL + MOV AL,BYTE PTR IY1 + MOV BYTE PTR YDEX1,AL + + POP BX ;RESTORE AFFECTED REGISTER(S) + RET + +GETI ENDP + + ; ----------------------------- + ; WILL SOURCE ICON FIT IN DEST? + ; ----------------------------- + + ; ENTRY: IX1 = X-SIZE OF SOURCE + ; IY1 = Y-SIZE OF SOURCE + ; IX2 = X-SIZE OF DESTINATION + ; IY2 = Y-SIZE OF DESTINATION + ; ARG1 = HORIZONTAL OFFSET OF THE SUB-IMAGE IN THE + ; DESTINATION ICON THAT IS TO BE SWAPPED + ; ARG2 = VERTICAL OFFSET OF THE SUB-IMAGE IN THE + ; DESTINATION ICON THAT IS TO BE SWAPPED + ; + ; EXIT: CARRY CLEAR IF FIT OK, ELSE CARRY SET + ; [IADR2] HAS ABSOLUTE ADDRESS OF SUB-ICON + PUBLIC DOFIT,NOFIT,FIT0,FIT1,FIT2,FIT3,FITEX +DOFIT PROC + MOV AL,BYTE PTR ARG1 ;GET X-POSITION + ADD AL,IX1 ;ADD TO THE X-SIZE OF SOURCE + CMP AL,IX2 ;COMPARE TO THE X-SIZE OF DESTINATION + JBE FIT0 ;OK IF LESS OR EQUAL +NOFIT: STC ; ELSE, SET CARRY + JMP FITEX ; AND EXIT + +FIT0: MOV AL,BYTE PTR ARG2 ;GET Y-POSITION + MOV BL,AL ;SAVE IT FOR LATER + ADD AL,IY1 ;ADD THE Y-SIZE OF SOURCE + CMP AL,IY2 ;COMPARE TO Y-SIZE OF DESTINATION + JBE FIT1 ;OK IF LESS OR EQUAL + JMP NOFIT ; ELSE, SET CARRY AND EXIT + + ; MAKE [IADR2] POINT TO ADDR OF SUB ICON +FIT1: MOV AL,BYTE PTR ARG1 ;GET X-POSITION + OR AL,AL ;IF X-POS = 0 + JZ FIT3 ; DON'T ADD X-OFFSET + +; MOV AL,BYTE PTR ARG1 ;ADD THE X-COORDINATE OF SUB-ICON + SUB AH,AH ;TO BASE ADDRESS OF DEST ICON + CALL AIADR2 ;TO GET THE BASE ADDR OF SUB-ICON + JMP FIT3 ;ALWAYS SKIP THE 1ST Y-ITERATION + +FIT2: MOV AL,BYTE PTR IX2 ;ADD THE X-SIZE OF DEST ICON + SUB AH,AH ;TO BASE ADDRESS OF SUB-ICON + CALL AIADR2 ;ONCE FOR EACH Y-COORDINATE + +FIT3: DEC BL ;OUT OF Y-COORDINATES YET? + JNS FIT2 ; NO. KEEP ADDING + CLC ;CLEAR CARRY FOR SUCCESS +FITEX: RET +DOFIT ENDP + + SUBTTL GPC VIRTUAL MEMORY ACCESS + PAGE + ; --------------------------------------------------------------- + ; The following subroutines are used to access Virtual Memory + ; through the GPC. + ; + ; G-MACHINE PROGRAM COUNTER DEFINITION + ; GPC GPC1 = MSB OF GPC GPC2 = LSB OF GPC + ; GPC0 = BIT 0 OF BYTE IS BIT 0 OF GPC + ; ---------------------------------------------------------------- + + ; ------ + ; ADDGPC + ; ------ + ; + ; ENTRY: [AX] = VALUE TO BE ADDED TO GPC + ; EXIT: GPC <= GPC + [AX] + ; +ADDGPC PROC + SHR AX,1 ;THINK ABOUT IT + JNC ADDGP1 + + XOR GPC0,1 ;CHANGE THE STATE OF BIT0 + JNZ ADDGP1 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC GPC ;ELSE BUMP THE REST OF GPC + +ADDGP1: ADD GPC,AX + RET +ADDGPC ENDP + + ; ----------------------------------------------- + ; {GB@GPC} + ; GET A BYTE OF VIRTUAL MEMORY AT THE CURRENT GPC + ; ----------------------------------------------- + ; + ; EXIT: BYTE IN [AX] + ; + PUBLIC GB@GPC +GB@GPC PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + ;CREATE AND SAVE THE LOW ADDRESS BITS + MOV AX,GPC ;GET GPC1 AND GPC2 + MOV BL,GPC0 ;GET GPC BIT + SHL AX,1 ;SHIFT GPC2 AND + OR AL,BL ; APPEND THE GPC BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,GPC ;GET VIRTUAL ADDRESS AGAIN + JMP GB@VM1 ; AND USE EXISTING CODE +GB@GPC ENDP + + ; ----------------------------- + ; {GW@GPC} + ; GET A WORD AT THE CURRENT GPC + ; ----------------------------- + ; + ; EXIT: WORD IN [AX] + ; GPC <= GPC + 2 + ; + PUBLIC GW@GPC +GW@GPC PROC + + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + ;SEE IF WE CAN LEGALLY CHEAT + CMP GPC2,0FFH ;CHEAT 510 TIMES OUT OF 512 + JNE GW@GP3 + + CMP GPC0,1 ;WE STILL HAVE A 50/50 CHANCE + JNE GW@GP3 ;....YAY! + + ; RATS, WE HAVE TO DO IT THE HARD WAY + CALL GB@GPCI ;GET THE FIRST BYTE AND POINT TO THE NEXT + MOV BL,AL ;SAVE THE MSB IN BL + CALL GB@GPC ;GET THE LSB IN AL + MOV AH,BL ;PUT THE MSB IN AH + + ; DECREMENT THE GPC + XOR GPC0,1 ;CHANGE THE STATE OF BIT0 + JZ GW@GP4 ;EXIT IF CHANGING FROM A "1" TO A "0" + DEC GPC ;ELSE DECREMENT THE REST OF THE GPC + +GW@GP4: POP CX + POP BX + RET + + ;CREATE AND SAVE THE LOW ADDRESS BITS +GW@GP3: MOV AX,GPC ;GET GPC1 AND GPC2 + MOV BL,GPC0 ;GET GPC BIT + SHL AX,1 ;SHIFT GPC2 AND + OR AL,BL ; APPEND THE GPC BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,GPC ;GET VIRTUAL ADDRESS AGAIN + JMP GW@VM1 ; AND USE EXISTING CODE +GW@GPC ENDP + + ; ----------------------------------------------- + ; {GB@GPCI} + ; GET A BYTE OF VIRTUAL MEMORY AT THE CURRENT GPC + ; AND INCREMENT THE GPC + ; ----------------------------------------------- + ; + ; EXIT: BYTE IN [AX] + ; GPC <= GPC + 1 + ; + PUBLIC GB@GPCI +GB@GPCI PROC + CALL GB@GPC ;GET THE BYTE + + ; AND FALL THROUGH ............. + +GB@GPCI ENDP + + ; ----------------- + ; {INCGPC} + ; INCREMENT THE GPC + ; ----------------- + ; + ; EXIT: GPC <= GPC + 1 + ; + PUBLIC INCGPC +INCGPC PROC + ;UPDATE THE VIRTUAL MEMORY POINTER + XOR GPC0,1 ;CHANGE THE STATE OF BIT0 + JNZ INCGP1 ;EXIT IF CHANGING FROM A "0" TO A "1" + INC GPC ;ELSE BUMP THE REST OF THE GPC +INCGP1: RET +INCGPC ENDP + + ; ----------------------------------------------- + ; {GW@GPCI} + ; GET A WORD OF VIRTUAL MEMORY AT THE CURRENT GPC + ; GPC = GPC + 2 + ; ----------------------------------------------- + ; + ; EXIT: WORD IN [AX] + ; GPC <= GPC + 2 + ; + PUBLIC GW@GPCI +GW@GPCI PROC + CALL GW@GPC ;GET THE WORD + INC GPC ;SAME AS ADDING 2 TO THE ENTIRE GPC + RET +GW@GPCI ENDP + + ; ----------------------------- + ; {PB@GPC} + ; PUT A BYTE AT THE CURRENT GPC + ; ----------------------------- + ; + ; ENTRY: [AL] = BYTE TO BE STORED + ; + ; EXIT: AL IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; + PUBLIC PB@GPC +PB@GPC PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + PUSH AX ;SAVE THE VALUE + + ;CREATE AND SAVE THE LOW ADDRESS BITS + MOV AX,GPC ;GET GPC1 AND GPC2 + MOV BL,GPC0 ;GET GPC BIT + SHL AX,1 ;SHIFT GPC2 AND + OR AL,BL ; APPEND THE GPC BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,GPC ;GET VIRTUAL ADDRESS AGAIN + JMP PB@VM1 ; AND USE EXISTING CODE +PB@GPC ENDP + + ; ----------------------------- + ; {PW@GPC} + ; PUT A WORD AT THE CURRENT GPC + ; ----------------------------- + ; + ; ENTRY: [AX] = WORD TO BE STORED + ; + ; EXIT: AX IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; + PUBLIC PW@GPC +PW@GPC PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + ;SEE IF WE CAN LEGALLY CHEAT + CMP GPC2,0FFH ;CHEAT 510 TIMES OUT OF 512 + JNE PW@GP3 + + CMP GPC0,1 ;WE STILL HAVE A 50/50 CHANCE + JNE PW@GP3 ;....YAY! + + ; RATS, WE HAVE TO DO IT THE HARD WAY + XCHG AH,AL + MOV BL,AH + CALL PB@GPCI ;STORE THE BYTE AND POINT TO THE NEXT + MOV AL,BL + CALL PB@GPC + + ; DECREMENT THE GPC + XOR GPC0,1 ;CHANGE THE STATE OF BIT0 + JZ PW@GP4 ;EXIT IF CHANGING FROM A "1" TO A "0" + DEC GPC ;ELSE DECREMENT THE REST OF THE GPC + +PW@GP4: POP CX + POP BX + RET + +PW@GP3: PUSH AX ;SAVE THE VALUE + + ;CREATE AND SAVE THE LOW ADDRESS BITS + MOV AX,GPC ;GET GPC1 AND GPC2 + MOV BL,GPC0 ;GET GPC BIT + SHL AX,1 ;SHIFT GPC2 AND + OR AL,BL ; APPEND THE GPC BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,GPC ;GET VIRTUAL ADDRESS AGAIN + + ;AND EXECUTE COMMON CODE + JMP PW@VM1 +PW@GPC ENDP + + ; ----------------------------- + ; {PB@GPCI} + ; PUT A BYTE AT THE CURRENT GPC + ; AND INCREMENT THE GPC + ; ----------------------------- + ; + ; ENTRY: [AL] = BYTE TO BE STORED + ; + ; EXIT: AL IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; GPC <= GPC + 1 + ; + PUBLIC PB@GPCI +PB@GPCI PROC + CALL PB@GPC ;WRITE OUT THE BYTE + + ;UPDATE THE VIRTUAL MEMORY POINTER + JMP INCGPC +PB@GPCI ENDP + + ; ----------------------------- + ; {PW@GPCI} + ; PUT A WORD AT THE CURRENT GPC + ; GPC = GPC + 2 + ; ----------------------------- + ; + ; ENTRY: [AX] = WORD TO BE STORED + ; + ; EXIT: AX IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; GPC <= GPC + 2 + ; + PUBLIC PW@GPCI +PW@GPCI PROC + CALL PW@GPC ;PUT THE WORD IN VIRTUAL MEMORY + INC GPC ;SAME AS ADDING 2 TO THE ENTIRE GPC + RET +PW@GPCI ENDP + + ; --------------------------------------------------- + ; {GETSHT} + ; GET A BYTE OF VIRTUAL MEMORY AT THE CURRENT GPC + ; INCREMENT THE GPC + ; AND PUT THE BYTE IN [VALUE] + ; --------------------------------------------------- + ; + ; ENTRY: G-MACHINE PROGRAM COUNTER DEFINITION + ; GPC1 = MSB OF GPC + ; GPC2 = LSB OF GPC + ; GPC0 = BIT 0 OF BYTE IS BIT 0 OF GPC + ; + ; EXIT: BTYE IN [AX] AND [VALUE] + ; GPC <= GPC + 1 + ; + ; + PUBLIC GETSHT +GETSHT PROC + CALL GB@GPCI ;GET THE BYTE IN [AL] + MOV VALUE,AX ; AND SAVE IT IN VALUE + RET +GETSHT ENDP + + ; --------------------------------------------------- + ; {GETLNG} + ; GET A WORD OF VIRTUAL MEMORY AT THE CURRENT GPC + ; GPC = GPC + 2 + ; AND PUT THE WORD IN [VALUE] + ; --------------------------------------------------- + ; + ; ENTRY: G-MACHINE PROGRAM COUNTER DEFINITION + ; GPC1 = MSB OF GPC + ; GPC2 = LSB OF GPC + ; GPC0 = BIT 0 OF BYTE IS BIT 0 OF GPC + ; + ; EXIT: WORD IN [AX] + ; GPC <= GPC + 2 + ; + ; REGISTERS DESTROYED: AX + ; + + PUBLIC GETLNG +GETLNG PROC + CALL GW@GPCI ;GET THE WORD IN [AX] + MOV VALUE,AX ; AND SAVE IT IN VALUE + RET +GETLNG ENDP + + SUBTTL VMP VIRTUAL MEMORY ACCESS + PAGE + + ; --------------------------------------------------------------- + ; The following subroutines are used to access Virtual Memory + ; through the VMP. + ; + ; VIRTUAL MEMORY POINTER DEFINITION + ; VMP VMP1 = MSB OF VMP VMP2 = LSB OF VMP + ; VMP0 = BIT 0 OF BYTE IS BIT 0 OF VMP + ; ---------------------------------------------------------------- + + ; ------ + ; ADDVMP + ; ------ + ; + ; ENTRY: [AX] = VALUE TO BE ADDED TO VMP + ; EXIT: VMP <= VMP + [AX] + ; +ADDVMP PROC + SHR AX,1 ;THINK ABOUT IT + JNC ADDVM1 + + XOR VMP0,1 ;CHANGE THE STATE OF BIT0 + JNZ ADDVM1 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC VMP ;ELSE BUMP THE REST OF VMP + +ADDVM1: ADD VMP,AX + RET +ADDVMP ENDP + + ; ----------------------------------------------- + ; {GB@VMP} + ; GET A BYTE OF VIRTUAL MEMORY AT THE CURRENT VMP + ; ----------------------------------------------- + ; + ; EXIT: BYTE IN [AX] + ; + PUBLIC GB@VMP +GB@VMP PROC + ;CREATE AND SAVE THE LOW ADDRESS BITS + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + MOV AX,VMP ;GET VMP1 AND VMP2 + MOV BL,VMP0 ;GET VMP BIT + SHL AX,1 ;SHIFT VMP2 AND + OR AL,BL ; APPEND THE VMP BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,VMP ;GET VIRTUAL ADDRESS AGAIN + + ; AND FALL THROUGH ............. + +GB@VMP ENDP + + ; -------------------------------- + ; CODE COMMON TO GB@VMP AND GB@GPC + ; -------------------------------- + +GB@VM1 PROC + MOV VPAGEN,AH ; SAVE THE VIRTUAL PAGE NUMBER + + ;PAGE IN THE BLOCK OF VIRTUAL MEMORY + CALL GTVBLK ; AND MAKE LOC VALID + + ;RESTORE LADD AND MAKE A FULLY FORMED ADDRESS + MOV AL,LOC ;GET THE ABSOLUTE BLOCK NUMBER + SUB AH,AH + SHL AX,1 ;SHIFT THE SEGMENT BIT INTO BIT 8 AND A "0" + ; INTO BIT 0, PUTTING THE HIGHER ADDRESS BITS + ; IN [AL] AND THE SEGMENT BIT IN [AH] + MOV BX,LADD ;RESTORE THE LOWER ADDRESS BITS + OR BH,AL ;COMBINE THE LOWER AND HIGHER ADDRESS BITS + + ;DETERMINE THE PROPER SEGMENT + MOV CX,SEG0 ;PRE-POINT AT SEG0 + OR AH,AH ;TEST SEGMENT BIT + JZ GB@VM2 ;IF "0" THEN IT'S SEG0 + MOV CX,SEG1 ; ELSE POINT TO THE OTHER SEGMENT +GB@VM2: MOV ES,CX ;ES POINTS TO THE CORRECT SEGMENT + + ;GET THE BYTE + MOV AL,ES:[BX] ;GET THE BYTE + SUB AH,AH ;GET RID OF UNWANTED BYTE + POP CX ;RESTORE AFFECTED REGISTER(S) + POP BX + RET +GB@VM1 ENDP + + ; ----------------------------- + ; {GW@VMP} + ; GET A WORD AT THE CURRENT VMP + ; ----------------------------- + ; + ; EXIT: WORD IN [AX] + ; VMP <= VMP + 2 + ; + PUBLIC GW@VMP +GW@VMP PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + ;SEE IF WE CAN LEGALLY CHEAT + CMP VMP2,0FFH ;CHEAT 510 TIMES OUT OF 512 + JNE GW@VM3 + + CMP VMP0,1 ;WE STILL HAVE A 50/50 CHANCE + JNE GW@VM3 ;....YAY! + + ; RATS, WE HAVE TO DO IT THE HARD WAY + CALL GB@VMPI ;GET THE BYTE AND POINT TO THE NEXT + MOV BL,AL + CALL GB@VMP ;GET THE SECOND BYTE + MOV AH,BL ;FORM THE WORD + + ; DECREMENT THE VMP + XOR VMP0,1 ;CHANGE THE STATE OF BIT0 + JZ GW@VM4 ;EXIT IF CHANGING FROM A "1" TO A "0" + DEC VMP ;ELSE DECREMENT THE REST OF THE VMP + +GW@VM4: POP CX + POP BX + RET + + ;CREATE AND SAVE THE LOW ADDRESS BITS +GW@VM3: MOV AX,VMP ;GET VMP1 AND VMP2 + MOV BL,VMP0 ;GET VMP BIT + SHL AX,1 ;SHIFT VMP2 AND + OR AL,BL ; APPEND THE VMP BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,VMP ;GET VIRTUAL ADDRESS AGAIN + + ; AND FALL THROUGH ............. + +GW@VMP ENDP + + ; -------------------------------- + ; CODE COMMON TO GW@VMP AND GW@GPC + ; -------------------------------- + +GW@VM1 PROC + MOV VPAGEN,AH ; SAVE THE VIRTUAL PAGE NUMBER + + ;PAGE IN THE BLOCK OF VIRTUAL MEMORY + CALL GTVBLK ; AND MAKE LOC VALID + + ;RESTORE LADD AND MAKE A FULLY FORMED ADDRESS + MOV AL,LOC ;GET THE ABSOLUTE BLOCK NUMBER + SUB AH,AH + SHL AX,1 ;SHIFT THE SEGMENT BIT INTO BIT 8 AND A "0" + ; INTO BIT 0, PUTTING THE HIGHER ADDRESS BITS + ; IN [AL] AND THE SEGMENT BIT IN [AH] + MOV BX,LADD ;RESTORE THE LOWER ADDRESS BITS + OR BH,AL ;COMBINE THE LOWER AND HIGHER ADDRESS BITS + + ;DETERMINE THE PROPER SEGMENT + MOV CX,SEG0 ;PRE-POINT AT SEG0 + OR AH,AH ;TEST SEGMENT BIT + JZ GW@VM2 ;IF "0" THEN IT'S SEG0 + MOV CX,SEG1 ; ELSE POINT TO THE OTHER SEGMENT +GW@VM2: MOV ES,CX ;ES POINTS TO THE CORRECT SEGMENT + + ;GET THE WORD + MOV AX,ES:[BX] ;GET THE WORD + XCHG AH,AL ;SWAPIFY + + POP CX ;RESTORE AFFECTED REGISTER(S) + POP BX + RET +GW@VM1 ENDP + + ; ----------------------------------------------- + ; {GB@VMPI} + ; GET A BYTE OF VIRTUAL MEMORY AT THE CURRENT VMP + ; AND INCREMENT THE VMP + ; ----------------------------------------------- + ; + ; EXIT: BYTE IN [AX] + ; VMP <= VMP + 1 + ; + PUBLIC GB@VMPI +GB@VMPI PROC + CALL GB@VMP ;GET THE BYTE + + ; AND FALL THROUGH ............. + +GB@VMPI ENDP + + ; ----------------- + ; {INCVMP} + ; INCREMENT THE VMP + ; ----------------- + ; + ; EXIT: VMP <= VMP + 1 + ; + PUBLIC INCVMP +INCVMP PROC + ;UPDATE THE VIRTUAL MEMORY POINTER + XOR VMP0,1 ;CHANGE THE STATE OF BIT0 + JNZ INCMP1 ;EXIT IF CHANGING FROM A "0" TO A "1" + INC VMP ;ELSE BUMP THE REST OF THE VMP +INCMP1: RET +INCVMP ENDP + + ; ----------------------------------------------- + ; {GW@VMPI} + ; GET A WORD OF VIRTUAL MEMORY AT THE CURRENT VMP + ; VMP = VMP + 2 + ; ----------------------------------------------- + ; + ; EXIT: WORD IN [AX] + ; VMP <= VMP + 2 + ; + PUBLIC GW@VMPI +GW@VMPI PROC + CALL GW@VMP ;GET THE WORD + INC VMP ;SAME AS ADDING 2 TO THE ENTIRE VMP + RET +GW@VMPI ENDP + + ; ----------------------------- + ; {PB@VMP} + ; PUT A BYTE AT THE CURRENT VMP + ; ----------------------------- + ; + ; ENTRY: [AL] = BYTE TO BE STORED + ; + ; EXIT: AL IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; + PUBLIC PB@VMP +PB@VMP PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + PUSH AX ;SAVE THE VALUE + + ;CREATE AND SAVE THE LOW ADDRESS BITS + MOV AX,VMP ;GET VMP1 AND VMP2 + MOV BL,VMP0 ;GET VMP BIT + SHL AX,1 ;SHIFT VMP2 AND + OR AL,BL ; APPEND THE VMP BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,VMP ;GET VIRTUAL ADDRESS AGAIN + + ; AND FALL THROUGH ............. + +PB@VMP ENDP + + ; -------------------------------- + ; CODE COMMON TO PB@VMP AND PB@GPC + ; -------------------------------- + +PB@VM1 PROC + MOV VPAGEN,AH ; TO SAVE THE VIRTUAL PAGE NUMBER + + ;PAGE IN THE BLOCK OF VIRTUAL MEMORY + CALL GTVBLK ; AND MAKE LOC VALID + + ;RESTORE LADD AND MAKE A FULLY FORMED ADDRESS + MOV AL,LOC ;GET THE ABSOLUTE BLOCK NUMBER + SUB AH,AH + SHL AX,1 ;SHIFT THE SEGMENT BIT INTO BIT 8 AND A "0" + ; INTO BIT 0, PUTTING THE HIGHER ADDRESS BITS + ; IN [AL] AND THE SEGMENT BIT IN [AH] + MOV BX,LADD ;RESTORE THE LOWER ADDRESS BITS + OR BH,AL ;COMBINE THE LOWER AND HIGHER ADDRESS BITS + + ;DETERMINE THE PROPER SEGMENT + MOV CX,SEG0 ;PRE-POINT AT SEG0 + OR AH,AH ;TEST SEGMENT BIT + JZ PB@VM2 ;IF "0" THEN IT'S SEG0 + MOV CX,SEG1 ; ELSE POINT TO THE OTHER SEGMENT +PB@VM2: MOV ES,CX ;ES POINTS TO THE CORRECT SEGMENT + + ;STORE THE BYTE + POP AX ;RESTORE THE BYTE + MOV ES:[BX],AL + + POP CX ;RESTORE AFFECTED REGISTER(S) + POP BX + RET +PB@VM1 ENDP + + ; ----------------------------- + ; {PW@VMP} + ; PUT A WORD AT THE CURRENT VMP + ; ----------------------------- + ; + ; ENTRY: [AX] = WORD TO BE STORED + ; + ; EXIT: AX IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; + PUBLIC PW@VMP +PW@VMP PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + ;SEE IF WE CAN LEGALLY CHEAT + CMP VMP2,0FFH ;CHEAT 510 TIMES OUT OF 512 + JNE PW@VM3 + + CMP VMP0,1 ;WE STILL HAVE A 50/50 CHANCE + JNE PW@VM3 ;....YAY! + + ; RATS, WE HAVE TO DO IT THE HARD WAY + XCHG AH,AL + MOV BL,AH + CALL PB@VMPI ;STORE THE BYTE AND POINT TO THE NEXT + MOV AL,BL + CALL PB@VMP + + ; DECREMENT THE VMP + XOR VMP0,1 ;CHANGE THE STATE OF BIT0 + JZ PW@VM4 ;EXIT IF CHANGING FROM A "1" TO A "0" + DEC VMP ;ELSE DECREMENT THE REST OF THE VMP + +PW@VM4: POP CX + POP BX + RET + +PW@VM3: PUSH AX ;SAVE THE VALUE + + ;CREATE AND SAVE THE LOW ADDRESS BITS + MOV AX,VMP ;GET VMP1 AND VMP2 + MOV BL,VMP0 ;GET VMP BIT + SHL AX,1 ;SHIFT VMP2 AND + OR AL,BL ; APPEND THE VMP BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,VMP ;GET VIRTUAL ADDRESS AGAIN + + ; AND FALL THROUGH ............. + +PW@VMP ENDP + + ; -------------------------------- + ; CODE COMMON TO PW@VMP AND PW@GPC + ; -------------------------------- + +PW@VM1 PROC + MOV VPAGEN,AH ; TO SAVE THE VIRTUAL PAGE NUMBER + + ;PAGE IN THE BLOCK OF VIRTUAL MEMORY + CALL GTVBLK ; AND MAKE LOC VALID + + ;RESTORE LADD AND MAKE A FULLY FORMED ADDRESS + MOV AL,LOC ;GET THE ABSOLUTE BLOCK NUMBER + SUB AH,AH + SHL AX,1 ;SHIFT THE SEGMENT BIT INTO BIT 8 AND A "0" + ; INTO BIT 0, PUTTING THE HIGHER ADDRESS BITS + ; IN [AL] AND THE SEGMENT BIT IN [AH] + MOV BX,LADD ;RESTORE THE LOWER ADDRESS BITS + OR BH,AL ;COMBINE THE LOWER AND HIGHER ADDRESS BITS + + ;DETERMINE THE PROPER SEGMENT + MOV CX,SEG0 ;PRE-POINT AT SEG0 + OR AH,AH ;TEST SEGMENT BIT + JZ PW@VM2 ;IF "0" THEN IT'S SEG0 + MOV CX,SEG1 ; ELSE POINT TO THE OTHER SEGMENT +PW@VM2: MOV ES,CX ;ES POINTS TO THE CORRECT SEGMENT + + ;STORE THE WORD + POP AX ;RESTORE THE WORD + XCHG AH,AL ;SWAPIFY + MOV ES:[BX],AX ;WRITE IT OUT + + POP CX ;RESTORE AFFECTED REGISTER(S) + POP BX + RET +PW@VM1 ENDP + + + ; ----------------------------- + ; {PB@VMPI} + ; PUT A BYTE AT THE CURRENT VMP + ; AND INCREMENT THE VMP + ; ----------------------------- + ; + ; ENTRY: [AL] = BYTE TO BE STORED + ; + ; EXIT: AL IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; VMP <= VMP + 1 + ; + PUBLIC PB@VMPI +PB@VMPI PROC + CALL PB@VMP ;WRITE OUT THE BYTE + + ;UPDATE THE VIRTUAL MEMORY POINTER + JMP INCVMP +PB@VMPI ENDP + + ; ----------------------------- + ; {PW@VMPI} + ; PUT A WORD AT THE CURRENT VMP + ; VMP = VMP + 2 + ; ----------------------------- + ; + ; ENTRY: [AX] = WORD TO BE STORED + ; + ; EXIT: AX IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; VMP <= VMP + 2 + ; + PUBLIC PW@VMPI +PW@VMPI PROC + CALL PW@VMP ;PUT THE WORD IN VIRTUAL MEMORY + INC VMP ;SAME AS ADDING 2 TO THE ENTIRE VMP + RET +PW@VMPI ENDP + + ;------------------------------------------------ + ; E N D O F S U B R O U T I N E S + ;------------------------------------------------ + + + SUBTTL COLD START + PAGE + ;---------------------------------------------------------------------- + ; C O L D S T A R T + ;---------------------------------------------------------------------- + + PUBLIC DIPBGN,REST1,REST2 +DIPBGN PROC + CALL SYSINI ;DO ANY SYSTEM INITIALIZATION + + CALL MTIME ;INITIALIZE RANDOM NUMBER GENERATOR + + MOV WORD PTR OLDGSP,DI ;INITIALIZE OLD GSTACK POINTER + + ; SET DEFAULT CLIPPING PARAMETERS + MOV WINDX1,0 ;FULL SCREEN + MOV WINDY1,0 + MOV WINDX2,39 + MOV WINDY2,23 + MOV WINDH,24 ;WINDH = (WINDY2 - WINDY1) + 1 + MOV WINDW,40 ;WINDW = (WINDX2 - WINDX1) + 1 + + ; + ; GET G-PRELOAD INTO THE BUFFER AREA + ; + + ; INITIALIZE GCODE + MOV GCODE,0 + + ; GET THE FIRST BLOCK OF G-PRELOAD + MOV VPAGEN,0 ;VIRTUAL BLOCK 0 + CALL GTPBLK ;GET PRELOAD BLOCK + + ; GET THE GAME ID FOR SAVE/RESTORE AND POSTERITY + ; + MOV VMP,0 ;SET UP VIRTUAL MEMORY ADDRESS POINTER + MOV VMP0,0 ; TO RETRIEVE [GEND] + MOV AX,GID + CALL ADDVMP + CALL GW@VMP ;GET THE END OF G-PRELOAD (WORDPTR) + MOV ZORKID,AX ; SAVE IT AWAY + + ; EXTRACT DATA FROM G-PRELOAD HEADER + ; DETERMINE THE NUMBER OF PAGES IN G-PRELOAD + ; GET THE VIRTUAL ADDRESS OF THE START OF G-PURELOAD + MOV VMP,0 ;SET UP VIRTUAL MEMORY ADDRESS POINTER + MOV VMP0,0 ; TO RETRIEVE [GEND] + MOV AX,GEND + CALL ADDVMP + CALL GW@VMP ;GET THE END OF G-PRELOAD (WORDPTR) + + ; SEE IF THE 1ST. VIRTUAL PAGE OF G-PURELOAD CONTAINS ANY G-PRELOAD + OR AL,AL ;IS THERE A PARTIAL PRE-LOAD RECORD? + JZ NOGPRT ;NOPE + INC AH ;YUP + + ; NO G-CODE PARTIAL RECORD + ; DETERMINE THE TOTAL NUMBER OF PAGES IN G-PRELOAD +NOGPRT: MOV GPEND,AH ;SAVE IT, IT'S THE FIRST VIRTUAL BLOCK + ; # OF G-PURELOAD + MOV GPRBLK,AH ; AND THE TOTAL NUMBER OF + ; G-PRELOAD BLOCKS + + ; DO WE HAVE ENOUGH ROOM IN THE PAGING AREA FOR G-PRELOAD? + CMP BUFFERS,AH + JA GOTRM1 ;....YES + + ; *** ERROR #0: GAME PRELOAD IS TOO BIG *** +NOGRAM: MOV AL,0 + JMP GERROR + + ; GET THE REST OF G-PRELOAD INTO THE BUFFER AREA + ; USE GSTRT TO DETERMINE THE NUMBER OF G-PRELOAD BLOCKS TO + ; TO BE LOADED +GOTRM1: MOV AL,GMAJOR ; SET INTERPRETER VERSION + MOV AH,GMINOR ; LETTER AND NUMBER + MOV WORD PTR ES:[GINTVER],AX ; STORE INTERPRETER VERSION + MOV CL,GPRBLK ;GET TOTAL NUMBER OF G-PRELOAD BLOCKS + DEC CL ;-1 SINCE WE'VE ALREADY DONE THE 1ST. + JZ GTIPRE ;LEAVE IF IT WAS THE ONLY PRELOAD BLOCK + SUB CH,CH ;INITIALIZE LOOP COUNTER + MOV VPAGEN,1 ;START WITH VIRTUAL BLOCK #1 + + ; LOAD THE REMAINING G-PRELOAD LOOP +LGPRLP: PUSH CX ;SAVE LOOP COUNTER + CALL GTPBLK ;GET THE PRELOAD BLOCK + INC VPAGEN ;NEXT BLOCK + POP CX ;RESTORE LOOP COUNTER + LOOP LGPRLP ;CONTINUE UNTIL ALL OF G-PRELOAD IS IN + + ; + ; GET I-PRELOAD INTO THE BUFFER AREA + ; + + ; CALCULATE 1ST. VIRTUAL PAGE OF THE IFILE +GTIPRE: MOV VMP,0 ;GET THE LENGTH OF THE G-PROGRAM + MOV VMP0,0 ; IN WORDS + MOV AX,GLEN + CALL ADDVMP + CALL GW@VMP + + ;PATCH FOR PADDING PURPOSES + INC AX ;ICODE IS AT THE NEXT WORD ADDRESS + + MOV ICODE,AX ;SAVE VIRTUAL STARTING ADDRESS + MOV ISTRT,AH ; AND STARTING VIRTUAL PAGE NUMBER + + ; GET THE FIRST BLOCK OF I-PRELOAD + MOV VPAGEN,AH ;SETUP THE VIRTUAL PAGE NUMBER + CALL GTPBLK ; AND GET THE FIRST BLOCK OF I-PRELOAD + + ; DETERMINE VIRTUAL ADDRESS OF IPURE + MOV AX,ICODE + MOV VMP,AX + MOV VMP0,0 + MOV AX,IEND + CALL ADDVMP + CALL GW@VMP ;GET THE LENGTH OF I-PRELOAD IN WORDS + + INC AX ;I-PURE STARTS AT THE NEXT EVEN ADDRESS + MOV BX,ICODE ;GET OFFSET TO THE START OF THE IFILE + ADD AX,BX ;ADD STARTING ADDRESS + ; TO GET A GFILE RELATIVE ADDRESS + MOV IPURE,AX ;SAVE CORRECTED START OF I-PURE + + ; + ; GET THE REST OF I-PRELOAD INTO THE BUFFER AREA + ; + + ; DETERMINE THE NUMBER OF BLOCKS OF I-PRELOAD REMAINING + ; DETERMINE THE TOTAL NUMBER OF I-PRELOAD BLOCKS + ; USE THE STARTING I-PRELOAD VIRTUAL BLOCK NUMBER + ; TO DETERMINE AN ADJUSTED SIZE OF I-PRELOAD + + MOV BH,ISTRT ;GET VIRTUAL I-PRELOAD STARTING PAGE + SUB BL,BL ; PAGE ALIGN IT + MOV AX,IPURE ;GET THE RELATIVIZED STARTING + ; ADDRESS OF IPURE + SUB AX,BX ;SUBTRACT ZERO ADJUSTED STARTING ADDR + + ; SEE IF THE 1ST. VIRTUAL PAGE OF IPURE CONTAINS ANY I-PRELOAD + OR AL,AL ;SEE IF THERE'S A PARTIAL RECORD + JZ NOIPRT ;NOPE + INC AH ;YUP + +NOIPRT: MOV IPRBLK,AH ;SAVE TOTAL NUMBER OF I-PRELOAD BLOCKS + + ; DO WE HAVE ENOUGH ROOM IN THE PAGING AREA FOR I-PRELOAD? + ADD AH,GPRBLK ;ADD IN THE NUMBER OF G-PRELOAD BLOCKS + CMP BUFFERS,AH + JA NOIP1 + JMP NOGRAM ;....NO + +NOIP1: MOV CL,IPRBLK ;GET THE NUMBER OF I-PRELOAD BLOCKS + OR CL,CL ;SINCE IT'S POSSIBLE TO HAVE NONE + JZ INITAB ; WE HAVE TO CHECK FOR IT + DEC CL ;-1 SINCE WE'VE ALREADY DONE THE 1ST. + JZ INITAB ;LEAVE IF IT WAS THE ONLY PRELOAD BLOCK + SUB CH,CH ;INITIALIZE LOOP COUNTER + + ;INITIALIZE VALUES FOR I-PRELOAD LOOP + MOV AL,ISTRT ;GET VIRTUAL I-PRELOAD STARTING BLOCK # + INC AL ;ADD 1 SINCE WE'VE ALREADY LOADED THE + ; FIRST BLOCK + MOV VPAGEN,AL ;SAVE STARTING BLOCK # + + ; LOAD REMAINING I-PRELOAD LOOP +LIPRLP: PUSH CX ;SAVE LOOP COUNTER + CALL GTPBLK ;GET THE BLOCK + INC VPAGEN ;NEXT BLOCK + POP CX ;RESTORE LOOP COUNTER + LOOP LIPRLP ;CONTINUE UNTIL ALL OF I-PRELOAD IS IN + + + ; IF THE GAME FITS IN AVAILABLE MEMORY, + ; READ THE WHOLE THING IN + + CMP FSIZE,0 ; (B4) DOES THE GAME FIT? + JE SLURP1 + MOV DL,GPRBLK ; (B4) SO START SLURPING + XOR DH,DH ; (B4) SCRAP TOP HALF + MOV CL,9 ; (B4) CONVERT TO BYTES + SHL DX,CL ; (B4) OF G-PRELOAD + MOV CX,0 ; (B4) SET UP FOR SEEK + MOV BX,GAMHNDL + MOV AX,4200H ; (B4) SEEK PAST B-O-F + INT 21H + PUSH DS ; (B4) USE GAME BUFFER + MOV CX,SEG0 ; (B4) MAKE ADDRESSIBLE THRU DS + MOV DS,CX + MOV DX,AX ; (B4) SAVE OFFSET + MOV AX,0H ; (B4) HOW MANY BYTES TO END OF SEG? + SUB AX,DX ; (B4) ONE SEG IN LENGTH + MOV CX,AX ; (B4) THAT'S HOW MANY TO READ FIRST + MOV AH,CRDRNDZ ; (B4) READ THAT AMOUNT + INT 21H + CMP AX,CX ; (B4) THAT COULD BE THE END... + JNE SLURP + MOV AX,DS ; (B4) MAKE NEXT SEG ADDRESSIBLE + ADD AX,1000H ; (B4) 64K ABOVE THE FIRST + MOV DS,AX + MOV CX,0FFFFH ; (B4) READ UP TO ANOTHER 64K + MOV DX,0 ; (B4) STARTING AT THE BEGINNING + MOV AH,CRDRNDZ ; (B4) READ IT ALL IN + INT 21H +SLURP: POP DS + PUSH DI + PUSH ES ; (B4) SAVES + PUSH DS ; (B4) MAKE DS ADDRESSIBLE THRU ES + POP ES + MOV AL,1 ; (B4) ALL PAGES WILL BE PRELOAD + MOV CX,0FFH + MOV DI,OFFSET MEMMAP ; (B4) FILL TABLE TO INDICATE ALL IN +SLURP2: MOV AH,CL ; (B4) FILL IN BUF NUMBER + SUB AH,0FFH ; (B4) FROM 0 - FF + NEG AH ; (B4) RECTIFY + STOSW ; (B4) STORE IT + LOOP SLURP2 + POP ES + POP DI +SLURP1: + + + ; + ; INITIALIZE POINTERS TO VARIABLES + ; + + ; GLOBAL TABLE [GLOBAL] +INITAB: MOV AX,GCODE + MOV VMP,AX + MOV VMP0,0 + MOV AX,GGLOB + CALL ADDVMP + CALL GW@VMP ;GET POINTER TO GLOBAL TABLE + MOV GLOBAL,AX ;SAVE IT + + ; LOCAL TABLE [GLOCS] + SUB AX,0FH ;BACK UP 15 WORDS FOR LOCALS + MOV GLOCS,AX ;STORE PTR TO START OF LOCALS + + ; + ; REPAIR PREDEFINED GLOBALS 16, 17, 18, AND 19 + ; + + ; GLOBAL 16 - NUMBER OF BLOCKSETS + MOV AX,ICODE + MOV GPC,AX + MOV GPC0,0 + MOV AX,IBLKS + CALL ADDGPC + CALL GETSHT ;GET THE NUMBER OF BLOCKSETS IN VALUE + MOV NBLOKS,AL ;STORE IT IN NBLOKS + MOV AX,16 ; AND IN GLOBAL #16 + CALL VARPUT + + ; GLOBAL 17 - POINTER TO BLOCKSET POINTER TABLE + MOV AX,ICODE ;GET OFFSET TO THE START OF IFILE + ADD AX,4 ;BPT IS 8-BYTES FURTHER DOWN + MOV BTAB,AX ;SAVE VIRTUAL ADDRESS OF BPT + MOV VALUE,AX ;PUT IT IN VALUE, SO WE CAN + MOV AX,17 ;STORE THE VIRTUAL ADDRESS OF THE + CALL VARPUT ; BLOCKSET POINTER TABLE IN GLOBAL #17 + + ; GLOBAL 18 - NUMBER OF ICONS + MOV AX,ICODE + MOV GPC,AX + MOV GPC0,0 + MOV AX,IICONS + CALL ADDGPC + CALL GETSHT ;GET THE NUMBER OF ICONS IN VALUE + MOV NICONS,AL ;SAVE NUMBER OF ICONS + MOV AX,18 ;STORE NICONS IN GLOBAL #18 + CALL VARPUT + + ; GLOBAL 19 - PTR TO ICON PTR TABLE + MOV AL,NBLOKS ;GET NO. OF BLOCKSETS + SUB AH,AH +; SHL AX,1 ;WORDIFY IT TO GET SIZE OF BLOCKSET TBL +; SHR AX,1 ; AND DEWORDIFY 'CAUSE BPT IS A WRDPTR + MOV CX,BTAB ;GET THE BPT VIRTUAL ADDRESS + ADD AX,CX ;POINT PAST THE BPT + MOV ITAB,AX ;SAVE VIRTUAL ADDRESS OF IPT + MOV VALUE,AX ;PUT IT IN VALUE, SO WE CAN + MOV AX,19 ;STORE THE VIRTUAL ADDRESS OF + CALL VARPUT ; THE ICON POINTER TABLE IN GLOBAL #19 + + ; + ; TABLE PATCHING + ; + + ; RELATIVIZE THE BPT TO THE START OF THE GFILE + ; INITIALIZE LOOP COUNTER WITH THE NO. OF BLOCKSETS + MOV CL,NBLOKS + SUB CH,CH + + ; POINT TO THE BPT + MOV AX,BTAB + MOV VMP,AX + MOV VMP0,0 + + ; GET THE OFFSET TO THE START OF THE IFILE + MOV DX,ICODE + +REST1: PUSH CX ;SAVE LOOP COUNTER + PUSH DX ;SAVE OFFSET + CALL GW@VMP ;GET THE BLOCKSET POINTER + POP DX ;RESTORE OFFSET + PUSH DX ;SAVE OFFSET + ADD AX,DX ; RELATIVIZE IT + CALL PW@VMPI ;SAVE POINTER + POP DX ;RESTORE OFFSET + POP CX ;RESTORE LOOP COUNTER + LOOP REST1 ;CONTINUE TILL WE'VE DONE THEM ALL + + ; RELATIVIZE THE IPT TO THE START OF THE GFILE + ; INITIALIZE LOOP COUNTER WITH THE NO. OF ICONS + MOV CL,NICONS + SUB CH,CH + + ; POINT TO THE IPT + MOV AX,ITAB + MOV VMP,AX + MOV VMP0,0 + + ; GET THE OFFSET TO THE START OF THE IFILE + MOV DX,ICODE + +REST2: PUSH CX ;SAVE LOOP COUNTER + PUSH DX ;SAVE OFFSET + CALL GW@VMP ;GET THE ICON POINTER + POP DX ;RESTORE OFFSET + PUSH DX ;SAVE OFFSET + ADD AX,DX ; RELATIVIZE IT + CALL PW@VMPI ;SAVE POINTER + POP DX ;RESTORE OFFSET + POP CX ;RESTORE LOOP COUNTER + LOOP REST2 ;CONTINUE TILL WE'VE DONE THEM ALL + + ; + ; INITIALIZE THE INTERPRETER PROGRAM COUNTER + ; + + ; GET THE EXECUTION STARTING ADDRESS FROM WITHIN THE G-FILE + MOV VMP,0 + MOV VMP0,0 + MOV AX,GSTART ;OFFSET TO G-PROGRAM STARTING ADDRESS + CALL ADDVMP ;FORM THE VMP ADDRESS + CALL GW@VMP ;GET STARTING ADDRESS + + ; LOAD THE GPC WITH THE START ADDRESS + MOV GPC,AX + MOV GPC0,1 + JMP MLOOP ; AND JUMP INTO THE MAINLOOP + +DIPBGN ENDP + + SUBTTL MAIN LOOP + PAGE + ;---------------------------------------------------------------------- + ; INSTRUCTION INTERPRETATION LOOP + ;---------------------------------------------------------------------- + PUBLIC MLOOP,DC0,DC1,DC2,OPEXT,TOPX,OPX1,OPX2,OPX3,OPX4 + PUBLIC OPXNXT,DOXOP,DODIS,OP0,OP1,OP1A,OP1B,OP1EX,BADOP1 + PUBLIC OP2,OP2A,OP2B,OP2C,OP2D,OP2EX,OP2F +MLOOP PROC + + ; + ; INITIALIZE LOOP + ; + + MOV NARGS,0 ;CLEAR #ARGS + CALL GB@GPCI ;GET THE OPERATION BYTE + MOV OPCODE,AL ;SAVE A COPY + + ;debug + CMP GPC,1234H + JNE MLP1 + JMP MLP1 + ; + ; DETERMINE OPCODE TYPE + ; + + ; IF OPCODE IS POSITIVE ( < 80H ) THEN IT'S A 2-OP (SHORT FORM) +MLP1: CMP AL,80H ;IS IT A 2-OP (SHORT FORM)? + JNB DC0 ;....NO. + JMP OP2 ;....YES, GO DO IT + + ; IF OPCODE = 0E0H THEN IT'S GCALL + ; WHICH IS HANDLED AS A SPECIAL CASE +DC0: CMP AL,0E0H ;IS IT "CALL"? + JNE DC1 ;....NO. + JMP GCALL ;....YES. + + ; IF OPCODE < 0B0H THEN IT'S A 1-OP +DC1: CMP AL,0B0H ;NO, IS IT A 1-OP? + JNB DC2 ;....NO. + JMP OP1 ;....YES. + + ; IF OPCODE < 0C0H THEN IT'S A 0-OP + ; ELSE IT'S A X-OP +DC2: CMP AL,0C0H ;IS IT AN 0-OP? + JNB OPEXT ;....NO. IT IS AN X-OP + JMP OP0 ;....YES. + + ; -------------- + ; HANDLE AN X-OP + ; -------------- + +OPEXT: CALL GB@GPCI ;GRAB ARGUMENT BYTE + MOV BYTE PTR ABYTE,AL ;SAVE IT + + SUB BX,BX + MOV BYTE PTR ADEX,BL ;INIT LOOP INDEX + JZ OPX1 ;UNCONDITIONAL JUMP (ENTER LOOP) + +TOPX: MOV AL,BYTE PTR ABYTE ;GET ARG BYTE + SAL AL,1 ;SHIFT NEXT 2 ARG BITS + SAL AL,1 ;INTO BITS 7 & 6 + MOV BYTE PTR ABYTE,AL ;HOLD FOR LATER + +OPX1: AND AL,11000000B ;ISOLATE ARGUMENT BITS + JNZ OPX2 ;IS IT A LONG IMMEDIATE? + + ; 00 = LONG IMMEDIATE + CALL GETLNG + JMP OPXNXT + +OPX2: CMP AL,01000000B ;IS IT A SHORT IMMEDIATE? + JNZ OPX3 ;....NO, KEEP GUESSING + + ; 01 = SHORT IMMEDIATE + CALL GETSHT + JMP OPXNXT + +OPX3: CMP AL,10000000B ;LAST TEST. VARIABLE? + JNZ OPX4 ;....NO. NO MORE ARGUMENTS + + ; 10 = VARIABLE + CALL GETVAR + +OPXNXT: MOV BL,ADEX ;RESTORE ARGUMENT INDEX + SUB BH,BH ;CLEAR OUT HIGH BYTE + MOV AX,WORD PTR VALUE ;GRAB VALUE + MOV WORD PTR ARG1 [BX],AX ;STORE IN ARGUMENT TABLE + INC NARGS ;UPDATE ARGUMENT COUNTER + + INC BX ;UPDATE INDEX + INC BX ;TWICE + + MOV BYTE PTR ADEX,BL ;SAVE INDEX + CMP BL,8 ;HAVE WE DONE 4 ARGUMENTS YET? + JB TOPX ;....NO, GET SOME MORE + + ;ALL X-OP ARGUMENTS READY +OPX4: MOV AL,OPCODE ;GET THE OPCODE BACK + SUB AH,AH + + CMP AL,0E0H ;IS IT AN EXTENDED 2-OP? + JAE DOXOP ;....NO, IT'S A REAL X-OP + + JMP OP2EX ; ELSE, TREAT IT LIKE A REAL 2-OP + + ; IS IT A VALID X-0P? +DOXOP: MOV BX,OFFSET OPTX ;^ TO START OF X-OP DISPATCH TABLES + AND AL,1FH ;ISOLATE OP ID BITS + CMP AL,NOPSX ;IS IT A LEGAL X-OP + JB DODIS ;....YES, DISPATCH IT + + ; *** ERROR #2: UNDEFINED X-OP *** + MOV AL,2 + JMP GERROR ;NO SUCH OPERATION + + ; --------------- + ; OPCODE DISPATCH + ; --------------- + + ;ENTRY: MASKED OPCODE INDEX IN [AL], BASE ADDRESS OF THE OPCODE + ;DISPATCH TABLE IN BX. + +DODIS: SHL AX,1 ;MAKE IT A WORD OFFSET + ADD BX,AX ;ADD THE OFFSET TO THE BASE ADDRESS + MOV SI,DS:[BX] ;GET THE ADDRESS FROM THE DISPATCH TABLE + CALL SI ;CALL THE OP ROUTINE + JMP MLOOP ;AND LOOP FOR NEXT INSTRUCTION + + ; -------------- + ; HANDLE A 0-OP + ; -------------- + +OP0: MOV BX,OFFSET OPT0 ;^ TO 0-OP DISPATCH TABLE + AND AL,0FH ;EXTRACT OPERATION BITS + CMP AL,NOPS0 ;OUT OF RANGE? + JB DODIS ;....NO, DISPATCH IT + + ; *** ERROR #3: UNDEFINED 0-OP *** + MOV AL,3 + JMP GERROR + + ; ------------- + ; HANDLE A 1-OP + ; ------------- + +OP1: AND AL,00110000B ;1OP. ISOLATE ARGUMENT BITS + JNZ OP1A + CALL GETLNG ;00 = LONG IMMEDIATE + JMP OP1EX + +OP1A: CMP AL,00010000B ;SHORT IMMEDIATE? + JNZ OP1B ;....NO + CALL GETSHT ;....YES, 01 = SHORT IMMEDIATE + JMP OP1EX + +OP1B: CMP AL,00100000B ;VARIABLE + JNZ BADOP1 ;....NO, UNDEFINED STATE + CALL GETVAR ;10 = VARIABLE + +OP1EX: MOV AX,VALUE ;VALUE TO [ARG1], UPDATE COUNT + MOV WORD PTR ARG1,AX + INC NARGS + + MOV BX,OFFSET OPT1 ;^ TO OP-1 DISPATCH TABLES + MOV AL,OPCODE ;RESTORE OPCODE + AND AX,00001111B ;ISOLATE OP ID BITS + CMP AL,NOPS1 ;IF WITHIN RANGE, + JB DODIS ;THE EXECUTE THE 1-OP + + ; *** ERROR #4: UNDEFINED 1-OP *** +BADOP1: MOV AL,4 + JMP GERROR + + ; ------------- + ; HANDLE A 2-OP + ; ------------- + +OP2: AND AX,01000000B ;2OP, ISOLATE 1st ARG BIT + JNZ OP2A ;SHORT IMMEDIATE? + CALL GETSHT ;....YES. 0 = SHORT IMMEDIATE + JMP OP2B + +OP2A: CALL GETVAR ;1 = VARIABLE +OP2B: MOV AX,WORD PTR VALUE ;VALUE TO [ARG1], UPDATE COUNT + MOV WORD PTR ARG1,AX + INC NARGS + + MOV AL,OPCODE ;RESTORE THE OPCODE BYTE + AND AX,00100000B ;ISOLATE 2nd ARG BIT + JNZ OP2C ;SHORT IMMEDIATE? + CALL GETSHT ;....YES, 0 = SHORT IMMEDIATE + JMP OP2D + +OP2C: CALL GETVAR ;1 = VARIABLE + +OP2D: MOV AX,WORD PTR VALUE ;MOVE VALUE TO [ARG2] + MOV WORD PTR ARG2,AX + INC NARGS ;UPDATE COUNT + + ;ENTRY FOR EXTENDED 2-OPS +OP2EX: MOV BX,OFFSET OPT2 ;^ DISPATCH TABLE + MOV AL,OPCODE ;RESTORE OPCODE BYTE + AND AX,1FH ;ISOLATE OP ID BITS + CMP AL,NOPS2 ;LEGAL 2-OP? + JAE OP2F ;ERROR IF OUT OF RANGE + JMP DODIS ;ELSE DISPATCH + + ; *** ERROR #5: UNDEFINED 2-OP *** +OP2F: MOV AL,5 + JMP GERROR +MLOOP ENDP + + SUBTTL HIGH LEVEL IBMPC DEPENDENT ROUTINES + PAGE + ; --------------------- + ; SYSTEM INITIALIZATION + ; --------------------- + PUBLIC SYSINI,SYS1,DSKERR +SYSINI PROC + MOV AH,DOSVER ; (7) GET DOS VERSION # + INT 21H ; (7) MUST BE 2.0 OR HIGHER + CMP AL,2 ; (7) DOS 2.0+ + JGE GOODOS + MOV AL,17 + JMP GERROR + ; DETERMINE PRESENCE OF JOYSTICK +GOODOS: CALL STICK1 ; READ THE JOYSTICK PORT (OR ETHER) + AND AL,0EFH ; MASK OFF BUTTON BITS + CMP AL,8AH ; 8AH IS BOTTOM RIGHT (NO JOYSTICK) + JZ NOSTK + MOV JOYSTK,1 ; THERE IS A STICK SO USE IT! + + ; OPEN THE GAME FILE +NOSTK: PUSH ES + PUSH BX + MOV AX,BIOSDATA ; SEG ADDRESS BIOS DATA AREA + MOV ES,AX + MOV BX,KB_FLAG ; OFFSET TO BIOS DATA FOR KEYS + MOV AL,ES:[BX] ; GET BYTE OF KEYBOARD STATE + MOV KYFLGS,AL ; SAVE THEM + OR BYTE PTR ES:[BX],NUMLOCK ; TURN ON NUMLOCK + POP BX + POP ES + MOV AH,CURDSK ; (6) GET DEFAULT DRIVE + INT 21H ; (6) FROM DOS + MOV DEFDRV,AL ; (6) SAVE DEFAULT DRIVE + MOV CURDRV,AL ; (6) SAVE DEFAULT DRIVE + MOV AH,CFOPENZ ;ASCIZ STRINGS + MOV AL,0 ;OPEN FOR READ + MOV DX,OFFSET GAMFILE + INT 21H + JNC SYSIN1 + JMP DSKERR + + ; DETERMINE SPACE AVAILABLE +SYSIN1: MOV GAMHNDL,AX ;SAVE THE FILE HANDLE + + ; DETERMINE THE SIZE OF DIP.DAT + ; MOVE READ/WRITE POINTER TO THE END OF THE FILE + SUB CX,CX ;SET CX:DX OFFSET = 0 + SUB DX,DX + MOV BX,GAMHNDL ;GET FILE HANDLE + MOV AH,CFSEEK ;SELECT LSEEK FUNCTION + MOV AL,2 ;USE OFFSET FROM END METHOD + INT 21H ;INVOKE FUNCTION CALL + + ; DX:AX = FILE SIZE IN BYTES + ; DETERMINE THE NUMBER OF 512 BYTE PARA'S + TEST AX,1FFH ;IS THERE A PARTIAL DISK PARAGRAPH? + JZ SYSIN2 ;....NO + ADD AX,200H ;ADD 1 TO THE NUMBER OF PARA'S + +SYSIN2: SHR AX,1 ;DETERMINE NO. OF 512 BYTE PARA'S + SUB AL,AL + XCHG AH,AL + CMP DX,0 + JZ SYSIN3 + ADD AL,80H + +SYSIN3: MOV FSIZE,AL ;SAVE IT + + ; DETERMINE THE AMOUNT OF MEMORY AVAILABLE FOR PAGING BUFFERS + MOV BX,2 ;GET TOP OF MEMORY + MOV BX,CS:[BX] ;FROM OUT OF THE PSP + MOV AX,CS ;GET CODE SEG + SUB BX,AX ;SUB CSEG FROM TOPMEM + MOV CL,4 ;SHIFT COUNT + MOV AX,OFFSET MEMBUF ;USE OFFSET TO FIGURE PARAG'S + SHR AX,CL ;REDUCE THIS OFFSET TO PARA'S + INC AX ;SKIP ONE PARAGRAPH + SUB BX,AX ;YIELDS PARA'S AVAILABLE + MOV CL,5 ;DIVIDE BY 32 + SHR BX,CL ; TO GET THE NUMBER OF 512 BYTE BUFFERS + + ; REDUCE THE NUMBER OF BUFFERS AVAILABLE TO ACCOMODATE MEMBUFF + DEC BX ;SUBTRACT 1 BUFFER FOR MEMBUF + CMP BX,128 ;ABOVE 80H, WE NEED ANOTHER + JL SYS1 ;WE HAVE 128 OR FEWER BUFFERS AVAILABLE + DEC BX ;TAKE AWAY ANOTHER PAGE + CMP BX,255 ;THIS IS THE MOST WE WILL NEED + JLE SYS1 ;DON'T MODIFY IF BX LE. 255 + MOV BX,255 ;DONT ALLOW MORE THAN 255 + +SYS1: MOV BUFFERS,BL ;SAVE THE NUMBER OF BUFFERS + + ; DYNAMICALLY CALCULATE THE START OF SEG0 + SHL BX,1 ;GET NUMBER OF BYTES IN MEMBUF + SHL BX,1 ;IT'S 4 BYTES x BX BYTES LONG + ADD BX,OFFSET MEMBUF ;CALCULATE TABLE LOCATION + MOV CX,4 ;REDUCE NUMBER OF BYTES IN TABLE=PARA'S + SHR BX,CL ;TO DYNAMICALLY ALLOCATE SPACE + MOV AX,DS ;GET A COPY OF THE CURRENT SEG + ADD BX,AX ;AND CALCULATE THE NEW SEG + ADD BX,10H ;ADD ONE PARAGRAPH FOR SAFETY + MOV SEG0,BX ;THIS WILL BE USED FOR ES:GAME + ADD BX,1000H ;ADD 64K TO CALC 2ND SEG + MOV SEG1,BX ;THIS IS SEG0+64K + + ; INITILIZE PAGING TABLES + ; INITIALIZE MEMMAP + SUB AX,AX ;PRELOAD FLAGS=RESET (0) + ;MEMBUF INDICES=NOT CORE RESIDENT (0) + SUB BX,BX ;INITIALIZE ARRAY ROW POINTER + MOV CX,00FFH ;SET UP FOR 255 ENTRIES + +INITMM: MOV MEMMAP[BX],AL ;RESET PRELOAD FLAG + MOV MEMMAP[BX+1],AH ;MARK MEMBUF INDICE = NOT CORE RESIDENT + ADD BX,2 ;NEXT OFFSET + LOOP INITMM ;INITIALIZE EACH ENTRY + + ; DETERMINE IF THE GAME "FITS" + MOV AL,BUFFERS + CMP AL,FSIZE + JNB SYSXIT ;IF THE GAME "FITS" FSIZE IS > 0 + MOV FSIZE,0 ;ELSE FSIZE = 0 + + ; INITIALIZE MEMBUF + MOV CL,BUFFERS ;NUMBER OF ENTRIES USED AS A LOOP CTR + SUB CH,CH + SUB BX,BX ;INITIALIZE OFFSET INTO TABLE + MOV DH,255 ;INITIAL VALUE FOR "PREVIOUS" POINTER + MOV DL,1 ;INITIAL VALUE FOR "NEXT" POINTER + MOV AL,0 ;INITIAL "LOC" (ABS SEG:PAGE VALUE) + +INITMB: MOV MEMBUF[BX],AL ;SAVE LOC + MOV MEMBUF[BX+1],0 ;V-PAGE IS THE RESPONSIBILITY OF GTVBLK + MOV MEMBUF[BX+2],DH ;INITIALIZE "PREVIOUS" + MOV MEMBUF[BX+3],DL ; AND "NEXT" POINTERS + INC AL ;NEXT LOC + INC DH ;NEXT "PREVIOUS" + INC DL ;NEXT "NEXT" + ADD BX,4 ;NEXT TABLE ENTRY + LOOP INITMB ;REPAIR EACH MEMBUF ENTRY + + ;CONNECT HEAD AND TAIL + DEC BX ;BACK UP TO "NEXT" COLUMN OF LAST ENTRY + MOV DL,MEMBUF[BX] ;GET "NEXT" + DEC DL ;SUBTRACT 1 TO GET TAIL + MOV MEMBUF[BX],0 ;SPLICE TAIL TO HEAD + MOV MEMBUF+2,DL ;SPLICE HEAD TO TAIL + + ; INITIALIZE LRU BUFFER POINTER + MOV LRU,0 + + ; + ; EXIT POINT + ; + + ; INITIALIZE SEGMENT POINTER TO THE START OF PAGING +SYSXIT: MOV BX,SEG0 ; + MOV ES,BX ;EXTRA SEG ^ THE START OF PAGING + CALL DISPRT + CALL CSETUP ;SET UP THE CONSOLE DEVICE + CALL CHKCPU ;SET THE IBMAT FLAG IF INDICATED + CALL INITSND ;INITIALIZE TIMER FOR SOUND +IF DEBUG + CALL TRACE ; CHECK TO SEE IF TRACER IS WANTED +ENDIF + RET + + ; **** ERROR #11 **** DISK DATA FILE HANDLING ERROR + ; CLOSE THE FILE +DSKERR: MOV BX,GAMHNDL ;BX <= HANDLE + MOV AH,3EH ;REQUEST CLOSE + INT 21H ;MSDOS CALL + + ; AND PERFORM ERROR PROCESSING + MOV AL,0BH ;SET UP ERROR RETURN CODE + JMP GERROR ;AND GO TO ERROR EXIT + +SYSINI ENDP + +IF DEBUG + PUBLIC TRACE +TRACE PROC + MOV SI,80H ; GET COMMAND LINE + LODSB ; SEE COMMAND PARMS + CMP AL,2 ; LOOK FOR /T + JNB TRACE1 +TRACE0: RET +TRACE1: MOV SI,83H ; LOOK AT BYTE + AND BYTE PTR [SI],5FH ; TURN OFF 32 BIT + CMP BYTE PTR [SI],'T' ; TRACE? + JNE TRACE0 + CALL ITRACE ; YEP, INITIALIZE TRACER + RET +TRACE ENDP + + +; trace trap routines for the mme +; itrace toggles tracing & sets the interrupt. itrint traps the +; interrupt and counts the bucket for the current pc +; + public itrace ;trace trap enable +itrace proc near + push ax + push bx + push dx + mov dx,offset itrint + mov bx,ds ;save data segment + mov ax,cs + mov isavecs,ax ;for compare in int routine + mov ds,ax ;ds:dx is trap address + mov al,1 ;trace int # + mov ah,25H ;function # for set int vector + int 21H + mov ds,bx + pop dx + pop bx + pushf ;get the flags + pop ax + xor ax,400O ;complement the trace flag + push ax + popf + pop ax + ret +itrace endp +; +itrint proc near + push bp + mov bp,sp ;stack:saved bp(0), ip(2), cs(4), flags(6) + push bx + push cx + inc itrcnt ;wrong cs, just count it + jne itrint2 + inc itrcnt+2 +itrint2:mov bx,[bp+2] ;pick up ip + cmp bx,ioffset + jb itrint1 ;dont count below + cmp bx,itop + ja itrint1 ;dont count above + sub bx,ioffset + mov cx,ishift + shr bx,cl + xor bh,bh ;0:255 - high pc bits + add bx,bx ;byte address of a long + add bx,bx + inc ipcount[bx] + jne itrint1 ;check wrap + inc ipcount+2[bx] +itrint1:pop cx + pop bx + pop bp + iret +itrint endp + +ptracer proc + mov dx,offset t_out + mov cx,0 + mov ah,cfcreaz ; create the file tracer.out + int 21h + mov dx,offset itrcnt ; get address of vars + mov cx,256*32+4 ; number of bytes to write + mov bx,ax ; get handle from create + mov ah,40h ; write the data + int 21h + mov ah,3eh ; close the data file + int 21h + ret ; all done +ptracer endp + +ENDIF + + PUBLIC DISPRT +DISPRT PROC ; DISABLE PRINT SCREEN + PUSH ES + MOV AX,3505H ; (B5) GET INTERRUPT VECTOR FIVE + INT 21H ; (B5) (PRTSCR) FROM DOS + MOV PRTOFF,BX ; (B5) SAVE OFFSET + MOV PRTSEG,ES ; (B5) SAVE 'EM BOTH + MOV DX,OFFSET RETEOI + MOV AX,2505H ; (B5) SET INTERRUPT TO POINT TO IRET + INT 21H + POP ES + RET +DISPRT ENDP + + PUBLIC ENAPRT +ENAPRT PROC ; (B5) REENABLE PRINT SCREEN + PUSH DS + MOV AX,2505H ; (B5) RESET PRTSCR + MOV DX,PRTOFF ; (B5) GET OFFSET + MOV BX,PRTSEG ; (B5) SET UP DS + MOV DS,BX ; (B5) TO POINT TO OLD ROUTINE + INT 21H + POP DS + RET +ENAPRT ENDP + +RETEOI: IRET ; (B5) RETURN FROM PRINT SCREEN + + + ; ---------------------- + ; CONSOLE INITIALIZATION + ; ---------------------- + PUBLIC CSETUP +CSETUP PROC + ; INITIALIZE VIDEO + ; SELECT MEDIUM RESOLUTION GRAPHICS + MOV AH,0 + MOV AL,4 + INT 10H + MOV AH,0FH ; SEE IF IT WORKED + INT 10H ; BY ASKING THE VIDEO + CMP AL,4 ; IT SHOULD BE AS SET + JE CSET$ + MOV AL,10H ; NEW ERROR EXIT + JMP GERROR + +; SET BACKGROUND COLOR +CSET$: MOV AH,11 ;REQUEST COLOR + MOV BL,0 ;SELECT BACKGROUND + MOV BH,0 ; 0=BLACK + INT 10H ;CALL BIOS + +; SELECT COLOR PALETTE + MOV AH,11 ;REQUEST COLOR + MOV BL,1 ;SELECT PALETTE #1 + MOV BH,1 ;0=BLACK, 1=CYAN, 2=MAGENTA, 3=WHITE + INT 10H ;CALL BIOS + +; CLEAR THE SCREEN TO BLACK AND RESET THE ACTIVE ICON TABLE + MOV ARG1,0 ;LOAD ARG1 WITH A POSITIVE VALUE + CALL GCLEAR ;DO IT + CMP FSIZE,0 ; (B4) GAME FIT? + JNE CSET$$ + RET +CSET$$: MOV AH,2 ; (B4) NOW PRINT A LOADING MESSAGE + MOV DX,800H ; (B4) SOMEWHERE ON THE SCREEN + MOV BH,0 + INT 10H + MOV AX,OFFSET WAITSTR ; (B4) GAME IS LOADING... + CALL MPRNT + MOV AH,2 ; (B4) AND RESET THE CURSOR TO TOP + MOV DX,100H + MOV BH,0 + INT 10H + RET +CSETUP ENDP + + ; ------------------------------------- + ; GET A BLOCK OF PRELOAD VIRTUAL MEMORY + ; ------------------------------------- + + ; + ; ENTRY: [VPAGEN] = VIRTUAL BLOCK NUMBER (RANGE 0-255) + ; [LRU] = NUMBER OF LEAST RECENTLY USED BUFFER + ; + + PUBLIC GTPBLK +GTPBLK PROC + CALL GTVBLK ;GET THE BLOCK + + ; USE [VPAGEN] TO SET [PREFLG] + MOV BL,VPAGEN ;GET VIRTUAL PAGE NUMBER + SUB BH,BH + SHL BX,1 ;CONVERT TO WORD POINTER + MOV MEMMAP[BX],1 ;SET PREFLG + + CMP FSIZE,0 + JZ GTPBL1 + RET + + ; USE [BUF] TO UNSPLICE THE ALLOCATED BUFFER FROM THE CIRCULAR + ; LINKED LIST. NOTE, IN THE CASE OF PRELOAD, BUF CONTAINS + ; THE NUMBER OF THE JUST USED BUFFER, WHICH WAS THE LRU AND IS NOW + ; THE MRU. +GTPBL1: MOV DL,BUF ;SAVE BUF FOR FIXING THE LRU + MOV BL,DL ;USE BUF TO CHANGE "NEXT" POINTER + SUB BH,BH ; IN PREVIOUS BUFFER + SHL BX,1 ;4 BYTES PER TABLE ENTRY + SHL BX,1 + + ;GET "NEXT" [AH] AND "PREVIOUS" [AL] + MOV AX,WORD PTR MEMBUF[BX+2] + + MOV BL,AL ;USE "PREVIOUS" TO + SUB BH,BH ; POINT TO THE 2ND MRU'S TABLE + SHL BX,1 ;4 BYTES PER TABLE ENTRY + SHL BX,1 + MOV MEMBUF[BX+3],AH ;SET TO POINT FORWARD TO THE LRU + + MOV BL,AH ;USE "NEXT" TO + SUB BH,BH ; POINT TO THE LRU'S TABLE + SHL BX,1 ;4 BYTES PER TABLE ENTRY + SHL BX,1 + MOV MEMBUF[BX+2],AL ;SET TO POINT BACK TO 2ND MRU + ; MAKING IT THE NEW MRU + RET +GTPBLK ENDP + + ; ----------------------------- + ; GET A BLOCK OF VIRTUAL MEMORY + ; ----------------------------- + ; + ; ENTRY: [VPAGEN] = VIRTUAL BLOCK NUMBER (RANGE 0-255) + ; [LRU] = NUMBER OF LEAST RECENTLY USED BUFFER + ; + ; THROUGH USE OF A COMMON EXIT POINT + ; EXIT: BUF (RANGE 0 THROUGH [BUFFERS]-1) + ; LOC + ; + + PUBLIC GTVBLK +GTVBLK PROC + PUSH BX + + ; USE [VPAGEN] TO ACCESS [PREFLG] AND [BUF] + MOV BL,VPAGEN ;GET VIRTUAL PAGE NUMBER + SUB BH,BH + SHL BX,1 ;CONVERT TO WORD POINTER + MOV AL,MEMMAP[BX+1] ;GET BUF + MOV BUF,AL ;SAVE IT + TEST MEMMAP[BX],1 ;TEST PREFLG + ; IS THIS SECTION LOADED PRELOAD? + JZ NOTPRE ;....NO + + ; LOADED PRELOAD + ; BUF IS VALID +ISIN: MOV BL,BUF ;WE CAREFULLY SAW TO IT'S VALIDITY + MOV LOC,BL ;AND PUT IT WHERE THE SUN.... + POP BX + RET + + ; {CASE} NOT LOADED PRELOAD +NOTPRE: CMP FSIZE,0 ;ARE WE PAGING? + JZ NOTPR1 ;....YES + + ; NOT PAGING + CMP BUF,0 ;IS IT ALREADY IN CORE? + + ; {CASE} IT IS ALREADY IN CORE + JNE ISIN ;....YES + + ; {CASE} IT NOT IN CORE + MOV AL,VPAGEN + MOV MEMMAP[BX+1],AL ;SET UP THE BUF ENTRY IN MEMMAP + MOV BUF,AL ; AND SET BUF = VPAGEN + + PUSH CX ;SAVE SOME MORE REGISTERS + PUSH DX + JMP GTVBL2 ;AND BRING IT IN + +NOTPR1: CMP BUF,0 ;IS IT ALREADY IN CORE? + JNE INCORE ;....YES + JMP NOTIN ;....NO. THEN BRING IT IN + + ; {CASE} IT IS IN CORE AND NOT PRELOAD +INCORE: MOV BL,BUF ;IS IT THE LRU? + CMP LRU,BL + JNE SPLICE ;....NO + + ; IT IS THE LRU PAGE, SO MAKE IT THE MRU + SUB BH,BH ;UPDATE THE LEAST RECENTLY USED BUFFER + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV AL,MEMBUF[BX+3] ;GET "NEXT" POINTER + MOV LRU,AL ;IT'S THE NEW LRU, MAKING THIS BUFFER + ; THE MRU + + ; BUF IS VALID + MOV BL,BUF + MOV OLDMRU,BL ;SAVE BUF AS OLD MRU + MOV LOC,BL ;AND LOC + POP BX + RET + + + ; IT ISN'T THE LRU. WE HAVE TO MAKE IT THE MRU, IF IT ISN'T + ; ALREADY. THE EXISTING LRU REMAINS UNCHANGED + +SPLICE: MOV BL,BUF + CMP BL,OLDMRU ;IS THIS ALREADY THE MRU? + JNE SPLIC1 ;....NO + + MOV LOC,BL ;AND SAVE BUF IN LOC + POP BX + RET + + ; STEP 1 - UNSPLICE THE "TOUCHED" BUFFER +SPLIC1: PUSH CX + PUSH DX + MOV OLDMRU,BL ;SAVE BUF AS OLD MRU + SUB BH,BH ; + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV AX,WORD PTR MEMBUF[BX+2] ;GET "NEXT" AND "PREVIOUS" + PUSH BX + + MOV BL,AL ;START WITH "PREVIOUS" BUFFER + SUB BH,BH ; + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV MEMBUF[BX+3],AH ;POINT FORWARD TO "NEXT" + + MOV BL,AH ;THEN "NEXT" BUFFER + SUB BH,BH ; + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV MEMBUF[BX+2],AL ;POINT BACK TO "PREVIOUS" + + ;SPLICE IN THE NEW MRU + MOV DL,BUF + + MOV BL,LRU ;GET THE "PREVIOUS" POINTER IN LRU + SUB BH,BH ; WHICH POINTS AT THE OLD MRU + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV AL,MEMBUF[BX+2] ;GET "PREVIOUS" POINTER + MOV MEMBUF[BX+2],DL ;MAKE LRU POINT BACK TO BUF + + MOV BL,AL ;GET THE "NEXT" POINTER FROM FORMER + SUB BH,BH ; MRU + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV AH,MEMBUF[BX+3] ;GET "NEXT" POINTER + MOV MEMBUF[BX+3],DL ;MAKE IT POINT FORWARD TO BUF + + ; AND REPAIR BUF + POP BX + MOV WORD PTR MEMBUF[BX+2],AX + + ; BUF IS VALID + JMP GTVRET ;WE'RE DONE, USE COMMON EXIT + + ; {CASE} IT ISN'T IN CORE + ; DEALLOCATE THE LEAST RECENTLY USED BUFFER +NOTIN: PUSH CX + PUSH DX + MOV BL,LRU ;GET LRU SO AS TO DEALLOCATE + SUB BH,BH ; THE LEAST RECENTLY USED BUFFER + SHL BX,1 + SHL BX,1 + + MOV BL,MEMBUF[BX+1] ;GET THE OLD VIRTUAL PAGE NUMBER + ; WE'LL USE IT TO INDEX INTO MEMMAP + + SUB BH,BH ; AND SET IT'S BUF ENTRY + SHL BX,1 ; TO "0" + MOV MEMMAP[BX+1],0 ;THIS DEALLOCATES THE BUFFER FOR THE + ; OLD VIRTUAL PAGE. + + ; ALLOCATE MEMBUF [LRU] TO THE NEW VIRTUAL PAGE + MOV BL,LRU ;GET LRU SO AS TO ALLOCATE + SUB BH,BH ; THE LEAST RECENTLY USED BUFFER + SHL BX,1 + SHL BX,1 + MOV AL,VPAGEN ;GET NEW VIRTUAL PAGE NUMBER + MOV MEMBUF[BX+1],AL ;STORE IT + + ; SETUP THE LOAD POINT FOR THE NEW VIRTUAL PAGE +PUSH BX ; SAVE BUFFER DESCRIPTOR + MOV BL,AL ;USE VPAGEN AS AN INDEX + SUB BH,BH ; INTO MEMBUF + SHL BX,1 + MOV AL,LRU ;LRU IS THE BUFFER TO USE + MOV MEMMAP[BX+1],AL ; SO SAVE IT + MOV BUF,AL ; AND SAVE IT FOR COMMON EXIT + MOV OLDMRU,AL ;SAVE BUF AS OLD MRU +POP BX ; RESTORE BUFFER DESCRIPTOR + ; AND MAKE THIS BUFFER THE MRU +; SHL BX,1 ;SO WE CAN USE IT AS A QUAD POINTER + MOV AL,MEMBUF[BX+3] ;GET "NEXT" POINTER + MOV LRU,AL ;IT'S THE NEW LRU + ; MAKING THIS BUFFER THE MRU + + ; INITIALIZE REGISTERS TO PAGE IN A BLOCK OF VIRTUAL MEMORY + ; GET DESTINATION IN ES:BX FORM + ; FIXUP ES +GTVBL2: MOV BL,BUF ;GET DESTINATION BLOCK NUMBER + MOV CX,SEG0 ;PRE-POINT AT SEG0 + OR BL,BL ;TEST SEGMENT BIT + JNS SEGAOK ;IF NO SIGN THEN IT'S SEG0 + AND BL,7FH ; ELSE STRIP OFF THE SEGMENT BIT + MOV CX,SEG1 ; AND POINT TO THE OTHER SEGMENT +SEGAOK: MOV ES,CX ;ES POINTS TO THE CORRECT SEGMENT + + ; CONVERT THE DESTINATION BLOCK NUMBER TO A BYTE OFFSET + MOV CL,9 ;x 512 + SHL BX,CL ; + + ; GET VIRTUAL BLOCK NUMBER IN AL + MOV AL,VPAGEN ;GET THE VIRTUAL PAGE NUMBER + + ; + ; GET VIRTUAL BLOCK [AL] IN ES:BX + ; + + PUSH BX ;SAVE BX PORTION OF DESTINATION + + ; MOVE FILE READ/WRITE POINTER (LSEEK) TO POINT TO THE PROPER BLOCK + ; CALCULATE OFFSET IN BYTES AND PLACE IN CX:DX + MOV CX,9 ;MULTIPLY BY 512 (RECSIZ) + SHL AX,CL ;TO CONVERT BLK# TO OFFSET + MOV CX,0 ;SET TO ZERO, BUT CHANGE + ADC CX,0 ;TO "1" IF OFFSET > 64K + MOV DX,AX ;GET LOW ORDER #BYTES FOR LSEEK + + ; MOVE READ/WRITE POINTER TO OFFSET IN CX:DX + ; FROM THE BEGINNING OF THE FILE + MOV BX,GAMHNDL ;GET FILE HANDLE + MOV AH,CFSEEK ;SELECT LSEEK FUNCTION + MOV AL,0 ;USE OFFSET FROM BEGINNING METHOD + INT 21H ;INVOKE FUNCTION CALL + + ; READ THE SELECTED 512 BYTE RECORD INTO CORE LOCATION ES:BX + ; TRANLATE THE ES:BX CORE LOCATION INTO DS:DX FORMAT + ; RESTORE BX PORTION OF DESTINATION INTO DX + POP DX + + ; FIXUP SEGMENT PORTION OF THE DESTINATION + PUSH DS ;SAVE DS FOR LATER RESTORATION + PUSH ES ;PUSH EXTRA SEGMENT + POP DS ;IN ORDER TO PUT IT IN DS + + ; READ THE RECORD INTO DS:DX + MOV CX,RECSIZ ;READ A 512 BYTE RECORD + MOV AH,CRDRNDZ ;SELECT READ RANDOM RECORD + INT 21H ;INVOKE FUNCTION CALL + CMP AX,CX ;SET FLAGS + + ; RESTORE DATA SEGMENT + POP DS + + ; COMMON EXIT POINT + ; EXIT: BUF (RANGE 0 THROUGH [BUFFERS]-1) + ; LOC + ; +GTVRET: MOV BL,BUF ;WE CAREFULLY SAW TO IT'S VALIDITY + MOV LOC,BL ;AND PUT IT WHERE THE SUN.... + + POP DX ;RESTORE AFFECTED REGISTER(S) + POP CX + POP BX + RET +GTVBLK ENDP + + ; -------------- + ; ERROR HANDLING + ; -------------- + + ; ENTRY: ERROR CODE IN [AL] + PUBLIC GERROR,GERR1 +GERROR PROC + push ax + mov ah,2 + mov dx,100H ; row 1, col 0 + mov bh,0 ; screen 0 + int 10H ; set cursor + pop ax + XOR AH,AH + SHL AX,1 ; INDEX + MOV BX,AX ; USE INDEX REG + MOV BX,ERRTAB[BX] ; GET PROPER ERROR MESSAGE + MOV AL,[BX] ; GET LENGTH + ADD AL,ERRM ; ADD LENGTH OF STARTING STRING + mov ch,al ; save total text length + MOV AH,40 ; GET WIDTH OF SCREEN + SUB AH,AL ; GET REMAINING SPACES + SHR AH,1 ; DIVIDE IN HALF + TEST AH,1 ; ODD? + JZ GERR0 ; NOPE + DEC AH ; YES, SUBTRACT 1 +GERR0: MOV CL,AH ; GET COUNT OF SPACES + add CH,AH ; SAVE right edge=left spcs+text len +GERR1: CMP CL,0 ; DON'T PRINT "NO" SPACES + JE GERR2 ; SKIP PRINT + MOV AH,2 ; PRINT A CHAR + MOV DL,' ' ; A SPACE IN FACT + INT 21H ; DO IT + DEC CL + JMP GERR1 +GERR2: MOV AX,OFFSET ERRM+1 + CALL NPRNT ;PRINT IT (NO CRLF) + MOV AX,BX ; GET ERROR STRING + INC AX ; SKIP LENGTH BYTE + CALL NPRNT ; PRINT THE ERROR STRING +GERR3: CMP CH,40 ; FINISH THE LINE WITH SPACES + JE GERR4 + MOV DL,' ' ; PRINT A SPACE + MOV AH,2 + INT 21H + INC CH + JMP GERR3 +GERR4: MOV AH,2 + MOV DL,13 + INT 21H + MOV DL,10 + INT 21H + JMP FINISH ;EXIT CLEANLY +GERROR ENDP + + + ;PRINT A CARIAGE RETURN / LINE FEED + PUBLIC MCRLF +MCRLF PROC + MOV AL,13 + CALL PRTOUT + MOV AL,10 + CALL PRTOUT + RET +MCRLF ENDP + + ;PRINT THE CHARACTER IN [AL] + PUBLIC PRTOUT +PRTOUT PROC + PUSH AX + PUSH BX + PUSH CX + MOV DL,AL + MOV AH,2 + INT 21H + POP CX + POP BX + POP AX + RET +PRTOUT ENDP + + ;PRINT A STRING FOLLOWED BY , PTR IN AX + PUBLIC MPRNT +MPRNT PROC + PUSH DX + MOV DX,AX + MOV AH,9 + INT 21H + CALL MCRLF + POP DX + RET +MPRNT ENDP + + ;PRINT A STRING NOT FOLLOWED BY , PTR IN AX + PUBLIC NPRNT,NPR1,NPR2 +NPRNT PROC + PUSH BX ;SAVE BX + MOV BX,AX ;STRING PTR +NPR1: MOV AL,[BX] ;GET NEXT CHARACTER + CMP AL,"$" ;END OF THE LINE + JE NPR2 ;....YES + CALL PRTOUT ;....NO. PRINT THE CHARACTER + INC BX ;POINT TO THE NEXT CHARACTER + JMP NPR1 ;REPEAT UNTIL END OF THE LINE +NPR2: POP BX ;RESTORE BX + RET +NPRNT ENDP + + + ;GET TIME TO BE USED IN NUDGING THE RANDOM NUMBER GENERATOR + PUBLIC MTIME +MTIME PROC + PUSH CX + PUSH DX + MOV AH,2CH + INT 21H + MOV RSEED1,CX ;HRS & MIN + MOV RSEED2,DX ;S's & 1/100 THS + POP DX + POP CX + RET +MTIME ENDP + + ;EXIT THE GAME PEACEFULLY AND RETURN TO DOS + PUBLIC FINISH +FINISH PROC + + ; INDICATE THE GAME IS OVER + MOV AH,2 ; SET CURSOR POSITION + MOV BH,0 ; FIRST PAGE + MOV DX,1800H ; ON LINE 25 + INT 10H ; POSITION IT + MOV AX,OFFSET XITMSG ;POINT AT "END OF SESSION" + CALL NPRNT ;PRINT IT + CALL ENAPRT + ; WAIT FOR ANY KEYPRESS + + MOV AH,CNOECHO ; (B5) READ A CHAR + INT 21H + + ; GO BACK TO REGULAR TEXT MODE WITH A CLEAR SCREEN + ; SELECT STANDARD MODE + MOV AH,0 ;REQUEST MODE SET + MOV AL,2 ;STANDARD MONOCHROME 80 X 25 + INT 10H ;CALL BIOS FUNCTION + +IF DEBUG + CALL PTRACER ; CALL 'C' OUTPUT OF TABLE +ENDIF + MOV AX,BIOSDATA ; FIX KEYBOARD + MOV ES,AX + MOV BX,KB_FLAG ; KEYBOARD FLAGS OFFSET + MOV AL,KYFLGS ; GET ORIGINAL STATE + MOV ES:[BX],AL ; STORE IT + + ; EXIT TO DOS + MOV AH,04CH + INT 21H +FINISH ENDP + + ; -------------------------------- + ; CHECK FOR FAST PROCESSOR (80286) + ; -------------------------------- + ; + ; PURPOSE: THE SOUND ROUTINES ARE IMPLIMENTED THROUGH THE USE OF + ; SOFTWARE TIMING LOOPS. THEY ARE THEREFORE SUCCEPTABLE TO + ; BEING CHANGED BY FASTER PROCESSORS. + ; + ; IN ORDER TO PROVIDE COMPENSATION FOR THIS EFFECT, THIS + ; ROUTINE IS USED TO DETERMINE IF THE CPU IS "FAST" OR "SLOW". + ; + ; *** NOTE *** THIS ROUTINE IS TO BE CALLED DURING COLD START + ; + ; INPUTS: NONE + ; + ; OUTPUTS: [IBMAT] = TRUE IF THIS IS A FASTER CPU + ; = FALSE IF THIS IS A NORMAL CPU + ; REGISTERS DESTROYED: + ; AX,BX,DX + ; + ; EXTERNAL REFERENCES: [IBMAT], [TIMER], TRUE, FALSE, ATTIME + ; + + PUBLIC CHKCPU,CHKCP1,CHKCP2 +CHKCPU PROC + ; INITIALIZE + MOV IBMAT,FALSE ;PREMARK THIS AS A "SLOW" CPU + SUB BX,BX ;INITIALIZE LOOP COUNTER + ; TO DETERMINE SPEED + + CALL SYNCH ;SYNCHRONIZE TIMER + MOV TIMER,DL ;SAVE 1/100 SEC COUNT + + ; PREPARE TO QUALIFY +CHKCP1: MOV AH,2CH ;GET THE TIME UNTIL IT CHANGES + INT 21H ; SO WE CAN USE THE COUNT IN BX + INC BX ; TO DECIDE IF THIS IS A FAST CPU + CMP DL,TIMER ;HAS THE CLOCK TICKED? + JZ CHKCP1 ;....NO. LOOP UNTIL IT DOES + + ; PHOTO FINISH + CMP BX,ATTIME ;COMPARE WITH TIME STANDARD + JL CHKCP2 ; IF BX IS LESS, THEN THE CPU IS SLOW + MOV IBMAT,TRUE ; ELSE IT'S FAST AND WE SO MARK IT + +CHKCP2: PUSH ES + PUSH DI + MOV AX,BIOS ; BIOS SEGMENT + MOV ES,AX ; MAKE IT ADDRESSIBLE + MOV DI,BIOSOFF ; GET BIOS OFFSET + MOV AX,OFFSET IBMSTR ; SOURCE STRING "IBM COPR." + MOV DX,9 ; LENGTH OF STRING + MOV CX,200H ; WITHIN THE FIRST 1/2 K + CALL CHK ; CHK BIOS FOR IBM COPR. + JNC CHK_ID +CHKCP3: POP DI + POP ES + RET +CHK_ID: MOV DI,ID_OFF ; GET IBM ID BYTE OFFSET + CMP BYTE PTR ES:[DI],JR_ID ; IS IT A JUNIOR + JNE CHKCP3 + MOV PCJR,1 ; SET FLAG FOR PCJR + JMP CHKCP3 +CHKCPU ENDP + + + ; GIVEN SOURCE PTR IN DS:AX, AND A DEST PTR IN ES:DI, CHK SEARCHES + ; FOR THE STRING POINTED TO BY DS:AX IN THE FIRST (CX) BYTES OF + ; THE STRING POINTED TO BY ES:DI + PUBLIC CHK +CHK PROC + CLD ; (7) CLEAR THE DIRECTION FLAG + PUSH SI ; (7) SAVE THIS + PUSH DX ; (7) SAVE THIS FOR RETRIES + MOV BP,SP ; (7) GET A FRAME POINTER + MOV SI,AX ; (7) SET UP FIRST OFFSET +LUP: CMP BYTE PTR [SI],'$' ; (7) END CHAR + JE MATCH ; (7) REACHING END==MATCH + CMPSB ; (7) COMPARE TWO BYTES + JNE RESET ; (7) RESET SOURCE IF MISMATCH + DEC DX + LOOP LUP ; (7) DECREMENT COUNTER AND TRY AGAIN + JMP RTFAIL ; (7) OUT OF CHARS, FAILED +RESET: MOV SI,AX ; (7) MOVE SOURCE PTR BACK INTO SI + MOV DX,[BP] ; (7) RESTORE NUMBER OF BYTES IN STR + LOOP LUP ; (7) TRY AGAIN +RTFAIL: STC ; (7) FAIL BY RETURNING CARRY SET + POP DX + POP SI ; (7) RESTORE SI + RET +MATCH: TEST DX,DX ; (7) MATCH OF ENTIRE STRING + JNZ RTFAIL + CLC ; (7) GOT A MATCH, RETURN CARRY CLEAR + POP DX + POP SI ; (7) RESTORE SI + RET +CHK ENDP + + + + ; ------------------------ + ; INITIALIZE SPEAKER TIMER + ; ------------------------ + ; + ; PURPOSE: THIS ROUTINE INITIALIZES THE PORTION OF THE 8253 TIMER + ; CHIP USED BY THE SPEAKER SYSTEM. IN PARTICULAR, IT SETS + ; UP CHANNEL 2 OF THE TIMER AS A SQUARE-WAVE GENERATOR. + ; + ; *** NOTE *** THIS ROUTINE IS TO BE CALLED DURING COLD START + ; + ; INPUTS: NONE + ; + ; OUTPUTS: TIMER 2 + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC INITSND +INITSND PROC + PUSH AX ;SAVE REGISTERS + MOV AL,0B6H ;TIMER CONTROL WORD + OUT 43H,AL ;SEND IT TO THE CONTROL PORT + POP AX ;RESTORE REGISTERS + RET +INITSND ENDP + + ; ---------------------- + ; SET THE TONE FREQUENCY + ; ---------------------- + ; + ; PURPOSE: THIS ROUTINE SELECTS THE FREQUENCY OF THE SQUARE-WAVE + ; TONE TO THE SPEAKER. + ; + ; INPUTS: CX=FREQUENCY + ; + ; OUTPUTS: TIMER 2 + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC TONESET +TONESET PROC + PUSH AX ;SAVE REGISTERS + PUSH CX + MOV AL,CL ;GET LOWER BYTE + OUT 42H,AL ;SEND OUT VALUE TO TIMER + MOV AL,CH ;GET UPPER BYTE + OUT 42H,AL ;SEND OUT VALUE TO TIMER + POP CX ;RESTORE REGISTERS + POP AX + RET +TONESET ENDP + + ; ------------ + ; TURN ON TONE + ; ------------ + ; + ; PURPOSE: THIS ROUTINE TURNS ON THE TIMER AND SPEAKER TO PRODUCE + ; A TONE. THE FREQUENCY OF THE TONE MUST HAVE ALREADY + ; BEEN SENT TO THE TIMER. + ; + ; INPUTS: NONE + ; + ; OUTPUTS: TIMER 2, AND SPEAKER + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC TONEON +TONEON PROC + PUSH AX ;SAVE REGISTERS + IN AL,61H ;GET SYSTEM PORT B CONTROL DATA + OR AL,3 ;TURN SPEAKER AND TIMER ON + OUT 61H,AL ;SEND OUT NEW VALUE + POP AX ;RESTORE REGISTERS + RET +TONEON ENDP + + ; ------------ + ; TURN OFF TONE + ; ------------ + ; + ; PURPOSE: THIS ROUTINE TURNS OFF THE TIMER AND SPEAKER + ; + ; INPUTS: NONE + ; + ; OUTPUTS: TIMER 2, AND SPEAKER + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC TONEOFF +TONEOFF PROC + PUSH AX ;SAVE REGISTERS + IN AL,61H ;GET SYSTEM PORT B CONTROL DATA + AND AL,0FCH ;TURN SPEAKER AND TIMER OFF + OUT 61H,AL ;SEND OUT NEW VALUE + POP AX ;RESTORE REGISTERS + RET +TONEOFF ENDP + + ; ----------- + ; SOUND DELAY + ; ----------- + ; + ; PURPOSE: THIS ROUTINE DELAYS FOR A SPECIFIED NUMBER OF .05 SEC + ; INTERVALS. + ; + ; INPUTS: [CX] = NUMBER OF .05 SEC TO DELAY + ; + ; OUTPUTS: NONE + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC SNDDLY,SNDLY1,SNDLY2 +SNDDLY PROC + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH CX + PUSH DX + + CMP CX,0 + JNE SNDLY1 + + ; SHORTER THAN OTHERWISE POSSIBLE DURATION + MOV CX,JIFCNT ;<.05 SEC DELAY REQUEST, SO WAIT A JIFFY +SNDLY0: LOOP SNDLY0 + JMP SNDLY3 + + CALL SYNCH ;SYNCHRONIZE TIMER + MOV TIMER,DL ;SAVE 1/100 SEC COUNT + + ; TIMING LOOP +SNDLY1: PUSH CX ;SAVE LOOP COUNTER +SNDLY2: MOV AH,2CH ;GET THE TIME UNTIL IT CHANGES + INT 21H ; MSDOS FUNCTION CALL + CMP DL,TIMER ;HAS THE CLOCK TICKED? + JZ SNDLY2 ;....NO. LOOP UNTIL IT DOES + POP CX ;RESTORE LOOP COUNTER + MOV TIMER,DL ;SAVE NEW COUNT + LOOP SNDLY1 ; AND LOOP + +SNDLY3: POP DX ;RESTORE REGISTERS + POP CX + POP BX + POP AX + RET +SNDDLY ENDP + + ; ----- + ; SYNCH + ; ----- + ; + ; PURPOSE: THIS ROUTINE WAITS FOR A CHANGE IN THE 1/100 SEC TIMER, TO + ; INSURE THAT WE'RE AT THE START OF A NEW TIME PERIOD. + ; + ; INPUTS: NONE + ; + ; OUTPUTS: [DL] = 1/100 SEC COUNT AT SYNCH TIME + ; + ; REGISTERS DESTROYED: DL + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC SYNCH,SYNCH1 +SYNCH PROC + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH CX + MOV AH,2CH ;GET THE TIME FROM THE REAL TIME CLOCK + INT 21H ;MSDOS FUNCTION CALL + MOV TIMER,DL ;SAVE 1/100 SEC COUNT + + ; SYNCHRONIZE +SYNCH1: MOV AH,2CH ;GET THE TIME AGAIN, SO WE CAN INSURE + INT 21H ; THAT WE ARE SYNCHRONIZED WITH THE + CMP DL,TIMER ; START OF A NEW TIMING PERIOD + JZ SYNCH1 ;LOOP UNTIL SYNCHRONIZED + POP CX ;RESTORE REGISTERS + POP BX + POP AX + RET +SYNCH ENDP + + ; ---- + ; FREQ + ; ---- + ; + ; PURPOSE: THIS ROUTINE CONVERTS A FREQUENCY TO THE NUMBER REQUIRED + ; BY TONESET. + ; + ; INPUTS: [CX] = FREQUENCY IN HZ + ; + ; OUTPUTS: [CX] = CONVERTED VALUE + ; + ; REGISTERS DESTROYED: CX + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC FREQ +FREQ PROC + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH DX + + MOV DX,12H ;UPPER PART OF NUMERATOR + MOV AX,34DEH ;LOWER PART OF NUMERATOR + DIV CX ;DIVIDE BY FREQUENCY + MOV CX,AX ;QUOTIENT IS THE OUTPUT + POP DX ;RESTORE REGISTERS + POP BX + POP AX + RET +FREQ ENDP + + ; ----------- + ; MAKE A TONE + ; ----------- + ; + ; PURPOSE: THIS ROUTINE MAKES A TONE OF A GIVEN FREQUENCY AND LENGTH + ; + ; INPUTS: [CX] = FREQUENCY IN HZ + ; [DX] = DURATION IN .05 SEC INTERVALS + ; + ; OUTPUTS: TO THE SPEAKER AND TIMER 2 + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: {TONESET}, {TONEON}, {TONEOFF}, {DELAY} + ; + + PUBLIC TONE +TONE PROC + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH CX + PUSH DX + + ; COMPUTE THE FREQUENCY AND SETUP THE TONE GENERATOR (TIMER 2) + CALL FREQ ;CONVERT THE FREQUENCY + CALL TONESET ;SET UP TIMER 2 + + ; TURN ON THE TONE + CALL TONEON + + ; WAIT FOR THE DELAY TIME + MOV CX,DX + CALL SNDDLY + + ; TURN OFF THE TONE + CALL TONEOFF + + POP DX ;RESTORE THE REGISTERS + POP CX + POP BX + POP AX + RET +TONE ENDP + +EVEN + ; + ; START OF A DYNAMICALLY ALLOCATED PAGE CONTROL STRUCTURE + ; + + PUBLIC MEMBUF +MEMBUF LABEL BYTE + +; +MSDIP ENDP +CSEG ENDS + END MSDIP diff --git a/ibm/dump.asm b/ibm/dump.asm new file mode 100644 index 0000000..e173984 --- /dev/null +++ b/ibm/dump.asm @@ -0,0 +1,532 @@ + TITLE DIP/8086 + PAGE 58,132 + .LIST + +CSEG SEGMENT PARA PUBLIC + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG + +COLORSET DB 0 ;0 for RGB, 1 for COMPOSITE +grmtbl dw 256 dup (0) ;mask table, b/w only + +EXTRN GRXTBL:WORD +EXTRN GRETBL:WORD +EXTRN IX1:BYTE ; # blocks across being dumped (for edge effect) +EXTRN IXSKIP:BYTE + + public grxperm +grxperm proc near + push cx + push di + mov di, offset grmtbl + mov si, offset grxtbl + mov cx, 256 ;# wds to copy + rep movsw + pop di + pop cx + mov si, offset grxtbl + mov dx, 1 + call grxmod ; change 00->00, 11->01 (odd bytes) + mov si, offset gretbl + mov dx, 2 + call grxmod ; change 00->00, 11->10 (even bytes) + ret + +grxmod: + mov cx,256 ; byte lookup table +qloop: mov ax,[si] + rol ax,1 + rol ax,1 ;offset 'phase shift' + push cx + mov cx,8 ; change 8 pairs of bits + mov bx,0 ; new pattern into b +qloop1: + shl bx,1 + shl bx,1 + shl ax,1 ; old pattern in a + jnc qlbit0 ; jump if bit is 0 + or bx,dx ; 11->01 or ->10 + + test cl,1 ;+++hack to alternate colors in x + jz qlevnx + xor bx,3 ; change colors +qlevnx: + + ; following code finds 11{11}+ sequences and puts out white 11+ +qlb11: shl ax,1 ; flush second 1 of 11 pair + loop qlb1 ; check for end of word + jmp short qljoin ; out of bits, rejoin outer loop +qlb1: shl ax,1 ; check for 1111->white(1111) + jnc qlb01 + or bx,3 ; change (last) 01 or 10 to 11 + shl bx,1 + shl bx,1 + or bx,3 ; and another 11 + jmp qlb11 ; and try for another 1 + +qlb01: shl bx,1 ; (11.00) + shl bx,1 + ; end of white sequence finder +qlbit0: + shl ax,1 ; flush 2nd of 00 or 11 + loop qloop1 +qljoin: pop cx + ror bx,1 + ror bx,1 + mov [si],bx + inc si + inc si + loop qloop + ret + +grxperm endp + + PAGE + ; -------------------- + ; DUMP BLOCK TO SCREEN + ; -------------------- + + ; ENTRY: BLOCK TO PUT ON SCREEN IN [BLOCK] (TOP BYTE IN [BLOCK + 0]) + ; X-COORDINATE (0-39) IN [AH], Y-COORDINATE (0-23) IN [AL] + +VID_SG EQU 0B800H + +EXTRN YAXTBL:WORD +EXTRN BLOCK:BYTE +EXTRN MBLOCK:BYTE +EXTRN VDPADR:WORD + + PUBLIC DUMP +DUMP PROC + PUSH DI + CMP AH,39 ; (B4) SHIFT FIX + JNE DMP1 + JMP DMPFIX + +DMP1: MOV BX,VID_SG ;POINT AT THE VIDEO BUFFER + MOV ES,BX + + ; CALCULATE OFFSET FROM VIDEO_RAM BASE ADDRESS TO STORE THE FIRST BYTE + SUB BX,BX ;ZERO MSB + XCHG BL,AL ;BX <= ROW ADDRESS (0-23) + ; AL IS NOW "0" + SHL BX,1 ;MAKE BX A WORD INDEX + + XCHG AH,AL ;GET COLUMN CONTRIBUTION IN AL + SHL AX,1 ; x2 SINCE IBM HAS 80 COLUMNS + + ADD AX,WORD PTR YAXTBL[BX] ;ADD ROW CONTRIBUTION + ; TO COLUMN CONTRIBUTION + MOV DI,AX ; (B4) USE REG + MOV SI,OFFSET BLOCK ; (B4) USE REG + + MOV CX,4 ;INITIALIZE LOOP COUNTER + SUB DI,1FAFH ; (B4) FIRST PASS FUDGE FACTOR + JMP DLOOP1 ; (B4) SKIP ACTUAL FIX OFFSET + ; TRANSLATE BYTE IN [AL] INTO A DOUBLED BIT WORD IN [AX] + +DLOOP: SUB DI,1FB2H ; (B4) FIX OFFSET +DLOOP1: XOR AH,AH ; (B4) ZERO TOP HALF + LODSB ; (B4) GET BLOCKSET BYTE + SHL AX,1 ; (B4) BYTE TO WORD + XCHG BP,AX ; (B4) INTO AN INDEX REG + MOV AX,GRETBL[BP] ; (B4) GET SHIFTED WORD FROM TBL + ;note:gretbl + + ;PHASE SHIFT + ;MOVE THE WORD INTO VIDEO RAM + + STOSB ; (B4) STORE MIDDLE BYTE + MOV AL,AH ;SWAP + AND AX,3FC0H ;MASK + MOV DH,ES:[DI-2] ; (B4) GET IMAGE ALREADY ON SCREEN + MOV DL,ES:[DI] ; (B4) + AND DX,0C03FH ;MASK IT + OR AX,DX ;COMBINE SOURCE AND DEST TO + call edgere + MOV ES:[DI-2],AH ; (B4) ACHIEVE PHASE SHIFT ON LEFT + STOSB ; (B4) AND ON RIGHT + + ; ODD BYTE IN BLOCK + + ADD DI,1FFEH ; FIX OFFSET + ; TRANSLATE BYTE IN [AL] INTO A DOUBLED BIT WORD IN [AX] + XOR AH,AH ; (B4) ZERO TOP HALF + LODSB ; (B4) GET BLOCKSET BYTE + SHL AX,1 ; (B4) BYTE TO WORD + XCHG BP,AX ; (B4) INTO AN BASE REG + MOV AX,GRXTBL[BP] ; (B4) GET SHIFTED WORD FROM TBL + + ;PHASE SHIFT + ;MOVE THE WORD INTO VIDEO RAM + + STOSB ; (B4) STORE MIDDLE BYTE + MOV AL,AH ;SWAP + AND AX,3FC0H ;MASK + MOV DH,ES:[DI-2] ; (B4) GET IMAGE ALREADY ON SCREEN + MOV DL,ES:[DI] ; (B4) + AND DX,0C03FH ;MASK IT + OR AX,DX ;COMBINE SOURCE AND DEST TO + call edgero + MOV ES:[DI-2],AH ; (B4) ACHIEVE PHASE SHIFT ON LEFT + STOSB ; (B4) AND ON RIGHT + + LOOP DLOOP + + POP DI + RET +DUMP ENDP +;Following routine handles edge effects between blocks. Note that a block +;can affect the next block (bc.cb->bw.wb), so when a different block +;is written over the one that caused the mutation to white, the +;color must be put back: bb.wb->bb.cb. +;In forcing to white, we only need to look at the outer cells: c.c->w.w +;The return to color requires that we look one cell beyond, since the +;white cell at the boundary may be white because the cell next to it +;on the other side is white. +edgere: +; test to eliminate edge effects--two colors (or whites) make a white + test ah,0c0h ; lhs black? + jz hiblk3 ; jmp if so, leave alone (j if xb.x) + test ah,030h ; rhs black? + jnz hiblk4 ; jmp if not, force xc.c or xw.c to xw.w + test byte ptr es:[di-3],3 ;look at color to left x in xc.b + jnz hiblk3 ;if ~b, then must have wwb, leave alone + and ah,07fh ; force bwb (or bcb) to bcb (7fh or bfh dep on color) + jmp hiblk3 +hiblk4: + or ah,0f0h ; both were color or white, make both white +hiblk3: + test al,030h ; rhs black? + jz loblk3 ; jmp if so, leave alone + test al,0c0h ; lhs black? + jnz loblk4 ; jmp if so, leave alone + test al,0ch ; look at adjacent color to right + jnz loblk3 ; if ~b, then must have bww, leave alone + and al,0efh ; force bwb (or bcb) to bcb (efh or dfh dep on color) + jmp loblk3 +loblk4: + or al,0f0h ; both were color or white, make both white +loblk3: ;end of edge code + ret +edgero: +; test to eliminate edge effects--two colors (or whites) make a white + test ah,0c0h ; lhs black? + jz hiblk1 ; jmp if so, leave alone (jmp if xb.x) + test ah,030h ; rhs black? + jnz hiblk2 ; jmp if not, force cc or wc to ww (j if xc.c) + test byte ptr es:[di-3],3 ;look at color to left (x in xc.b) + jnz hiblk1 ;if ~b, then must have ww.b, leave alone + and ah,0bfh ; force bwb (or bcb) to bcb (7fh or bfh dep on color) + jmp hiblk1 +hiblk2: + or ah,0f0h ; both were color or white, make both white +hiblk1: + test al,030h ; rhs black? + jz loblk3 ; jmp if so, leave alone (jmp if cb.x) + test al,0c0h ; lhs black? + jnz loblk4 ; jmp if not, force cc or cw to ww (j if c.cx) + test al,0ch ; look at color to right (x in b.cx) + jnz loblk3 ; if ~b, then must have b.ww, leave alone + and al,0dfh ; force bwb (or bcb) to bcb (efh or dfh dep on color) + jmp loblk1 +loblk2: + or al,0f0h ; both were color or white, make both white +loblk1: ;end of edge code + ret + +DMPFIX: MOV BX,VID_SG ;POINT AT THE VIDEO BUFFER + MOV ES,BX + SUB BX,BX ;ZERO MSB + XCHG BL,AL ;BX <= ROW ADDRESS (0-23) + SHL BX,1 ;MAKE BX A WORD INDEX + XCHG AH,AL ;GET COLUMN CONTRIBUTION IN AL + SHL AX,1 ; x2 SINCE IBM HAS 80 COLUMNS + ADD AX,WORD PTR YAXTBL[BX] ;ADD ROW CONTRIBUTION + MOV DI,AX ; (B4) USE REG + MOV SI,OFFSET BLOCK ; (B4) USE REG + MOV CX,4 ;INITIALIZE LOOP COUNTER + SUB DI,1FAFH ; (B4) FIRST PASS FUDGE FACTOR + JMP DFLP1 ; (B4) SKIP ACTUAL FIX OFFSET + SUB DI,1FAFH ; (B4) FIRST PASS FUDGE FACTOR + JMP DFLP1 ; (B4) SKIP ACTUAL FIX OFFSET +DFLP: SUB DI,1FB1H ; (B4) FIX OFFSET +DFLP1: XOR AH,AH ; (B4) ZERO TOP HALF + LODSB ; (B4) GET BLOCKSET BYTE + SHL AX,1 ; (B4) BYTE TO WORD + XCHG BP,AX ; (B4) INTO AN INDEX REG + MOV AX,GRETBL[BP] ; (B4) GET SHIFTED WORD FROM TBL + STOSB ; (B4) STORE MIDDLE BYTE + MOV AL,AH ;SWAP + AND AX,3FC0H ;MASK + MOV DH,ES:[DI-2] ; (B4) GET IMAGE ALREADY ON SCREEN + MOV DL,ES:[DI] ; (B4) + AND DX,0C03FH ; (B4) MASK IT + OR AX,DX ;COMBINE SOURCE AND DEST TO + MOV ES:[DI-2],AH ; (B4) ACHIEVE PHASE SHIFT ON LEFT + ADD DI,1FFFH ; FIX OFFSET + XOR AH,AH ; (B4) ZERO TOP HALF + LODSB ; (B4) GET BLOCKSET BYTE + SHL AX,1 ; (B4) BYTE TO WORD + XCHG BP,AX ; (B4) INTO AN BASE REG + MOV AX,GRXTBL[BP] ; (B4) GET SHIFTED WORD FROM TBL + STOSB ; (B4) STORE MIDDLE BYTE + MOV AL,AH ;SWAP + AND AX,3FC0H ;MASK + MOV DH,ES:[DI-2] ; (B4) GET IMAGE ALREADY ON SCREEN + MOV DL,ES:[DI] ; (B4) + AND DX,0C03FH ;MASK IT + OR AX,DX ;COMBINE SOURCE AND DEST TO + MOV ES:[DI-2],AH ; (B4) ACHIEVE PHASE SHIFT ON LEFT + LOOP DFLP + POP DI + RET + + PAGE + ; ------------------------------ + ; DUMP BLOCK TO SCREEN WITH MASK + ; ------------------------------ + + ; ENTRY: BLOCK TO PUT ON SCREEN IN [BLOCK] (TOP BYTE IN [BLOCK + 0]) + ; X-COORDINATE (0-39) IN [AH], Y-COORDINATE (0-23) IN [AL] + ; + ; IF THE MASK BIT IS A "1" THEN THE SCREEN SHOWS THROUGH + ; IF THE MASK BIT IS A "0" THEN THE ICON IS DISPLAYED + ; + PUBLIC DMPMSK +DMPMSK PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + PUSH DX + PUSH ES + + MOV BX,VID_SG ;POINT AT THE VIDEO BUFFER + MOV ES,BX + + ; CALCULATE OFFSET FROM VIDEO_RAM BASE ADDRESS TO STORE THE FIRST BYTE + SUB BX,BX ;ZERO MSB + XCHG BL,AL ;BX <= ROW ADDRESS (0-23) + ; AL IS NOW "0" + SHL BX,1 ;MAKE BX A WORD INDEX + + XCHG AH,AL ;GET COLUMN CONTRIBUTION IN AL + SHL AX,1 ; x2 SINCE IBM HAS 80 COLUMNS + + ADD AX,WORD PTR YAXTBL[BX] ;ADD ROW CONTRIBUTION + ; TO COLUMN CONTRIBUTION + MOV VDPADR,AX ;SAVE STARTING MEMORY OFFSET + + SUB SI,SI ;INITIALIZE INDEX REGISTER + MOV CX,4 ;INITIALIZE LOOP COUNTER + +DMPMLP: MOV BL,BLOCK[SI] ;SELECT ICON BYTE + MOV BH,MBLOCK[SI] ;SELECT MASK BYTE + SUB VDPADR,1FB0H ;FIX OFFSET + CALL M1DISP ;TRANSLATE, MASK AND MOVE IT TO VRAM + INC SI ; NEXT BYTES + MOV BL,BLOCK[SI] ;SELECT ICON BYTE + MOV BH,MBLOCK[SI] ;SELECT MASK BYTE + ADD VDPADR,2000H ;FIX OFFSET + CALL M1DISP ;TRANSLATE, MASK AND MOVE IT TO VRAM + INC SI ; NEXT BYTES + LOOP DMPMLP + + POP ES ;RESTORE AFFECTED REGISTER(S) + POP DX + POP CX + POP BX + RET +DMPMSK ENDP + + PUBLIC M1DISP +M1DISP PROC + PUSH CX + PUSH BX ;SAVE MASK BYTE [IN BH] + + ; TRANSLATE BLOCK BYTE IN [BL] INTO A DOUBLED BIT WORD IN [AX] + SUB BH,BH + SHL BX,1 + MOV DX,GRMTBL[BX] ;BLOCK WORD + POP BX ;RECOVER MASK BYTE + XCHG BH,BL ;PUT IT IN BL + SUB BH,BH + SHL BX,1 + MOV CX,GRMTBL[BX] ;MASK WORD + + PUSH DX ;SAVE BLOCK WORD + + ; GET THE VIDEO WORD FROM VIDEO RAM + MOV BX,VDPADR ;GET BASE ADDRESS + MOV AX,ES:[BX] + XCHG AL,AH + AND AX,3FFFH + MOV DL,ES:[BX+2] + AND DL,0C0H + OR AH,DL + + POP DX ;DX <= BLOCK WORD + ;CX <= MASK WORD + ;AX <= VIDEO WORD + + ;BLOCK <= ((VIDEO XOR BLOCK) AND MASK) XOR BLOCK + XOR AX,DX + AND AX,CX + XOR AX,DX + + ; STORE THE WORD IN VIDEO RAM + MOV BX,VDPADR ;GET BASE ADDRESS + + ;PHASE SHIFT + ;MOVE THE WORD INTO VIDEO RAM + MOV ES:[BX+1],AL + MOV AL,AH + AND AX,3FC0H + MOV DH,ES:[BX] + MOV DL,ES:[BX+2] + AND DX,0C03FH + OR DX,AX +; test to eliminate edge effects--two colors (or whites) make a white +; test dh,0c0h ; lhs black? +; jz hiblk ; jmp if so, leave alone +; test dh,030h ; rhs black? +; jz hiblk ; jmp if so, leave alone +; or dh,0f0h ; both were color or white, make both white +;hiblk: +; test dl,0c0h ; lhs black? +; jz loblk ; jmp if so, leave alone +; test dl,030h ; rhs black? +; jz loblk ; jmp if so, leave alone +; or dl,0f0h ; both were color or white, make both white +;loblk: ;end of edge code + MOV ES:[BX],DH + MOV ES:[BX+2],DL + POP CX + RET +M1DISP ENDP + +%OUT DMPMSK DONE + + + ; ---------------------- + ; CONSOLE INITIALIZATION + ; ---------------------- + +EXTRN MPRNT:NEAR +EXTRN GERROR:NEAR + +EXTRN WAITSTR:BYTE +EXTRN FSIZE:BYTE +EXTRN ARG1:WORD + + PUBLIC CSETUP +CSETUP PROC + ; INITIALIZE VIDEO + ; SELECT MEDIUM RESOLUTION GRAPHICS + MOV AH,0 + MOV AL,4 + INT 10H + MOV AH,0FH ; SEE IF IT WORKED + INT 10H ; BY ASKING THE VIDEO + CMP AL,4 ; IT SHOULD BE AS SET + JE CSET$ + MOV AL,10H ; NEW ERROR EXIT + JMP GERROR + +; SET BACKGROUND COLOR +CSET$: MOV AH,11 ;REQUEST COLOR + MOV BL,0 ;SELECT BACKGROUND + MOV BH,0 ; 0=BLACK + INT 10H ;CALL BIOS + +; SELECT COLOR PALETTE + MOV AH,11 ;REQUEST COLOR + MOV BL,COLORSET ;SELECT PALETTE #1 + MOV BH,1 ;0=BLACK, 1=CYAN, 2=MAGENTA, 3=WHITE + INT 10H ;CALL BIOS + +; CLEAR THE SCREEN TO BLACK AND RESET THE ACTIVE ICON TABLE + MOV ARG1,0 ;LOAD ARG1 WITH A POSITIVE VALUE + CALL GCLEAR ;DO IT + CMP FSIZE,0 ; (B4) GAME FIT? + JNE CSET$$ + RET +CSET$$: MOV AH,2 ; (B4) NOW PRINT A LOADING MESSAGE + MOV DX,800H ; (B4) SOMEWHERE ON THE SCREEN + MOV BH,0 + INT 10H + MOV AX,OFFSET WAITSTR ; (B4) GAME IS LOADING... + CALL MPRNT + MOV AH,2 ; (B4) AND RESET THE CURSOR TO TOP + MOV DX,100H + MOV BH,0 + INT 10H + RET +CSETUP ENDP + + + PAGE + ; ----- + ; CLEAR + ; ----- + ; + ; CLEAR SCREEN TO WHITE IF [ARG1] IS NEGATIVE + ; CLEAR SCREEN TO BLACK IF [ARG1] IS POSITIVE + ; + + PUBLIC GCLEAR,GCLR1,GCLR2,GCLR3 +GCLEAR PROC + PUSH DI ;SAVE AFFECTED REGISTER(S) + PUSH CX + PUSH ES + + MOV AX,VID_SG ;POINT AT THE VIDEO BUFFER + MOV ES,AX + MOV AX,ARG1 ;GET THE ARGUMENT + + CMP AX,0 ; (B5) DO BLACK DIFFERENTLY + JE GCLR4 + MOV BP,AX ; GET WORD + AND BP,3FH ; MASK OFF HI NIBBLE FOR BIT SHIFT PROBLEM + MOV DI,0 ;SET UP INDEX + MOV BX,1E00H ;SET UP LOOP COUNTER + ; PAINT THE SCREEN WITH AX +GCLR1: XCHG AX,BP ; GET MASK BYTE + STOSB + XCHG AX,BP + MOV CX,79 ; DO A LINE - 1 AT A TIME + REPZ STOSB + SUB BX,80 ; SUBTRACT FROM TOTAL + JNZ GCLR1 + MOV DI,2000H + MOV BX,1E00H +GCLR2: XCHG AX,BP + STOSB + XCHG AX,BP + MOV CX,79 ; (B4) DO A LINE + REPZ STOSB + SUB BX,80 + JNZ GCLR2 + + ;CLEANUP WHEN COMPLETE +GCLR3: POP ES ;RESTORE THOSE REGISTERS + POP CX + POP DI + RET + +GCLR4: MOV DI,0 + MOV CX,0F00H ; (B5) DO WHOLE SCREEN + REPZ STOSW + MOV DI,2000H ; (B5) ODD BYTES + MOV CX,0F00H ; (B5) COUNT + REPZ STOSW + JMP GCLR3 + +GCLEAR ENDP + + ;paging space starts here + + PUBLIC MEMBUF +MEMBUF LABEL BYTE + +CSEG ENDS + + END diff --git a/ibm/equates.ezp b/ibm/equates.ezp new file mode 100644 index 0000000..ef49b90 --- /dev/null +++ b/ibm/equates.ezp @@ -0,0 +1,113 @@ + SUBTTL EQUATES - STACK AND DATA SEGMENTS INITIALIZATION + PAGE + +IBM_ID EQU 6 ; (A15) INTERPRETER ID +ZMVERS EQU 4 ;Z-MACHINE VERSION NUMBER +LSTACK EQU 512 ;LENGTH OF USER STACK(MUST BE 1 PAGE FOR NOW) +DEBUG EQU 0 + +PVERS1 EQU 0 ;POSITION OF ZVERSION VERSION BYTE +PVERS2 EQU 1 ;ZVERSION MODE BYTE +PZRKID EQU 2 ;ZORKID +PENDLD EQU 4 ;ENDLOD +PSTART EQU 6 ;START +PVOCTB EQU 8 ;VOCAB +POBJTB EQU 10 ;OBJECT +PGLOTB EQU 12 ;GLOBALS +PPURBT EQU 14 ;PURBOT +PFLAGS EQU 16 ;USER FLAG WORD +PSERNM EQU 18 ;SERIAL NUMBER (6 BYTES) +PWRDTB EQU 24 ;WORDS +PLENTH EQU 26 ;GAME LENGTH +PCHKSM EQU 28 ;GAME CHECKSUM +PINTVR EQU 30 ; (A0) INTERPRETER NUMBER +PINTID EQU 31 ; (A0) INTERPRETER ID +PSCLIN EQU 32 ; (A0) SCREEN LINE LENGTH +PSCCOL EQU 33 ; (A0) SCREEN COLUMN LENGTH + +OBJLEN EQU 14 ; (A0) LENGTH OF OBJECTS +PTABSIZ EQU 63 ; (A0) NUMBER OF PROPERTY ENTRIES IN TBL +PROPDEF EQU PTABSIZ*2-OBJLEN ; (A0) SIZE OF DEFAULT PROPERT TBL + +PADCHR EQU 5 ;PADDING CHARACTER + +SSVER EQU "A"-10 ; ADD THIS TO THE VERTICAL SETUP HEIGHT +SSHOR EQU -6 ; ADD THIS TO THE HORIZONTAL SETUP WIDTH +SSLNT EQU 3 ; LENGTH OF SETUP FILE + + +CRESET EQU 0H ;MS-DOS FUNCTION CALLS WITH INT 21H +CCONIN EQU 1H +CCONOUT EQU 2 +CPROUT EQU 5H +CCONIO EQU 6H +CNOECHO EQU 7H ; (7) FIX MCHRI TO HAVE NO ECHO +CRDLIN EQU 0AH +CDRESET EQU 0DH ; (7o) DISK RESET +CSELDSK EQU 0EH ; (7n) SELECT DISK +CFOPEN EQU 0FH +CFCLOS EQU 10H +CFDELE EQU 13H +CFMAKE EQU 16H +CURDSK EQU 19H ; (7n) CURRENT DISK +CSDMAO EQU 1AH +CRDRND EQU 21H +CWRRND EQU 22H +CPRSNM EQU 29H +CTIME EQU 2CH ; (A0) GET TIME OF DAY +; FUNCTION CALLS ADDED FOR VERSION "H" +; UPGRADE TO DOS 2.0 AND ABOVE +CFCREAZ EQU 3CH +CFOPENZ EQU 3DH +CFCLOSZ EQU 3EH +CRDRNDZ EQU 3FH +CWRRNDZ EQU 40H +CFDELEZ EQU 41H +CFSEEK EQU 42H +CSETBLK EQU 4AH ; FOR DETERMINING MEM SIZE +SCROLLUP EQU 6 ; (7) FOR VIDEO BIOS CALL +DOSVER EQU 30H ; (7) REQUEST FOR DOS VERSION +BIOSEG EQU 0F800H ; (7) STRINGS ARE FOUND AT F000:E0++ +BIOSOFF EQU 0000H ; (7) +COLCUR EQU 0607H ; (7) CURSOR SCAN LINES FOR COLOR +SETCUR EQU 1 ; (7) VIDEO FUNCTION TO SET CURSOR SIZE +COLATR EQU 17H ; (7) COLOR ATTRIBUTE IS WHITE ON BLUE +SCRBIT EQU 100000B ; (7) 5 BIT TURNS ON SCREEN SPLITTING +STDPRT EQU 4 ; (7) STANDARD PRINTER DEVICE +PRTMSK EQU 0A1H ; (7) PRINTER INI STATUS MASK +SCRMSK EQU 0FEFFH ; (7) WORD TO MASK SCRIPT BIT IN MODE WORD +RDYBIT EQU 1 ; (7) WAS THE PRINTER READY +MINMEM EQU (25*1024)/16 ; (7) MINIMUM MEMORY IN PARAGRAPHS +MAXLIN EQU 78 ; (7r) MAXIMUM INPUT LINE LENGTH +BUFLEN EQU MAXLIN+1 ; (A15) LENGTH OF OUTPUT BUFFER +TABWID EQU 8 ; (A0) PAGE TABLE WIDTH IS NOW 8 BYTES +TBLSHF EQU 3 ; (A0) TABLE WIDTH IS 2**TBLSHF +SCRPTBT EQU 0100H ; (A17) BIT 0 IN FLAGS WORD +REFRESH EQU 0400H ; (A17) BIT 2 IN FLAGS WORD + + + ; SOUND EQUATES +NSNDS EQU 2 ; (A0) NUMBER OF SOUNDS AVAILABLE +SPKRON EQU 3 ; (A0) CONTROL WORD TO TURN TIMER 2 AND THE + ; SPEAKER ON +SPKROFF EQU 0FCH ; (A0) CONTROL WORD TO TURN TIMER 2 AND THE + ; SPEAKER OFF +TMRCWD EQU 0B6H ; (A0) USE TIMER 2 FOR A SQUARE WAVE GEN +TMRDPT EQU 42H ; (A0) TIMER 2 DATA PORT I/O ADDRESS +TMRCPT EQU 43H ; (A0) TIMER 2 CONTROL PORT I/O ADDRESS +PTBCPT EQU 61H ; (A0) SYSTEM PORT B CONTROL PORT + +CINSTAT EQU 0BH ;(A0) CHECK STANDARD INPUT STATUS + + ; KEY PROCESSING +EOL EQU 0DH ;(A0) CARRIAGE RETURN +DEL EQU 7FH ;(A0) DELETE (RUB OUT) +SPACE EQU 20H ;(A0) ASCII SPACE +BACKSP EQU 08H ;(A0) LEFT ARROW (BS) +NAK EQU 15H ;(A0) + + ; HIGHLIGHTING +MAXHI EQU 4 ; (A0) THERE ARE CURRENTLY THREE FEATURES + + ; SCREEN +STSBIT EQU 4 ; (A9) STATUS LINE REFRESH REQUEST BIT diff --git a/ibm/ezip.asm b/ibm/ezip.asm new file mode 100644 index 0000000..d994e14 --- /dev/null +++ b/ibm/ezip.asm @@ -0,0 +1,231 @@ + TITLE EZIP Z-LANGUAGE INTERPRETER IBM/MS-DOS 2.0 VERSION + + PAGE 58,132 + .LIST + + ; ********************************************* + ; EEEEEE ZZZZZZ IIIIII PPPPP + ; EE ZZ II PP PP + ; EEEE ZZZ II PPPPP + ; EE ZZ II PP + ; EEEEEE ZZZZZZ IIIIII PP + ; ********************************************* + ; + +ZVERSN EQU "E" ;ZIP VERSION NUMBER +ZEDIT0 EQU "0" ;ZIP MINOR EDIT FIRST DIGIT +ZEDIT1 EQU "0" +; EZIP Edit history + ; VERSION [minor-digit] + ; + ; A -- 30-Apr-85 PHG + ; 0 -- Initial version. Broken up into includes. + ; 1 -- Fix scripting of status line (screen 1) + ; 2 -- Reduce clear on split by one line + ; 3 -- Fix cancel highlight on color and fix TI-PRO + ; 4 -- fixed paging bug in gtblks and idstr (no MS) + ; 5 -- changed color italic to red + ; 6 -- fix nxtbyt if pushing word at FFFF (crossing seg) + ; 7 -- fix verify to return t/f and work as well + ; 8 -- add spec change to reset morlin on opinput + ; Changes by Rick Lay + ; 9 -- Reworked line input section of {READIO} + ; Added code to eliminate italics if it's not an IBM + ; implemented the Status Line Refresh Request Bit in + ; SAVE, RESTORE, and VERIFY + ; 10 -- Major rework to implement change in {DIROUT} spec. + ; Changed "[MORE]" prompt. Modified {VERIFY} to use + ; two digit minor edit numbers. + ; 11 -- Fixed bug in scripting that appeared after A10 + ; 12 -- Really fixed that scripting bug. Also repaired Status + ; 13 -- implemented new {INTBL?} opcode. Repaired Buffered + ; Output {PUTCHR}. + ; Changes by PHG + ; 14 -- fixed scripting of crlfs + ; 15 -- made command line switches for color set ibmpc flag + ; to false to avoid underline when chosing mono on color + ; monitor. + ; 16 -- speed up + ; 17 -- fixed script on start-up, color on request for bw, + ; and added refresh after every printed line. + ; 18 -- stabbed at script on restart + ; 19 -- script + refresh bugs on DOS errors + ; 20 -- fixed verify for less than 256K + ; + ; B -- 30-Apr-85 EHB + ; 0 -- Trinity -related bugs: dirout flushing, opsplit ADDING + ; to TOPLIN, opsplt clearing the screen, opclear(-1) + ; falling through after unsplit/clear. Verify if fits=1 + ; C -- 7-Nov-86 LSD + ; 0 -- Bureaucracy - random just was not working, rewrote so + ; does (LD1) + ; 1 -- Paging bugs in FINDPG (LD2) + ; D -- May 87 TAA + ; 0 -- Bureaucracy - DELAY doesn't work when no 1/100's clock, + ; so notice that case + ; 1 -- Bureaucracy - problems with output in reverse video and + ; latest ansi.sys, change to NOT set foreground to white + ; before all escape sequences from highlight. + ; E -- July 87 TAA + ; 0 -- Remove somewhat bogus notion of forcing status line + ; refresh after every carriage return when scripting + +;ZIP Edit History + + + ; Modification History - + ;--------------------------------------------------- + ; + ; 1) REWORKED FOR NEW SETUP FILE USAGE + ; 2) FIXED NON-WORKING STACK SAVE AND RESTORE FILE + ; 3) FIX RANDOM BUG - 6/25/84 + ; 4) FIXED STATUS LINE (LONG ROOM DESCRIPTION) - 07/24/84 + ; 5) Fixed status line bug on restart 22-Oct-84 - PHG "G" + ; 6) REWRITE OF ZIP TO USE ALL MEMORY 1-NOV-84 - PHG "H" + ; 7) Combination of IBM and MSZIP with new copy protection + ; for all IBM compatible machines. 11-Mar-85 - PHG + ; Minor versions: I -- original to test + ; J -- fixed status line and more + ; k -- enhanced printer timeout for IBM + ; l -- mcrlf added to save, commenting + ; m -- fixed status line for TI-PRO + ; n -- added insert game disk on save + ; and paging problems. Also reworked + ; scripting. + ; o -- fixed script on restart, no script on + ; more, and minor save problems + ; q -- fixed disk switch for verify + ; + ; r -- fixed status line bugs and refixed + ; disk switch on restart. + ; s -- restart bug on Tandy (their incompati- + ; bility and more on restart + ; t -- removed extra CR from opening screen bet + ; ween last line of text and prompt. + ; u -- Fixed mchri not to echo character on + ; more or insert game disks. + ; v -- fixed broken restore or failed save on + ; low memory configuration, error in fit + ; calculation, /k was fixed to work any + ; where on the cmdline. + ; w -- added /P for PCjr support, fixed still + ; broken end of memory calculation caused + ; by forgetting to count prelod blocks as + ; used memory blocks. Also fixed opread + ; so that it would flush words read great- + ; er than 59. + ; x -- fix script checks from cmp to test. + ; to fix wishbringer. RELEASE AS H + ; J z -- stab at verify/paging bug, found in + ; newzpc when setting curtab to zero since + ; page is preloaded, didn't set zpcseg to + ; 0 as well. RELEASE AS J + ; J 1 -- fixed script bug on failed restore + ; K 1 -- fixed save/restore bug. Removed srblks + ; 2 -- fixed fix above which was still broken. + ; 3 -- j1 was broken by k2 edit. fixed here + ; 4 -- above + ; 5 -- fixed restart to set segs to 0 + ; 6 -- stab at fixing screwy dos disk flush on + ; create. + ; +IF1 +%OUT PASS ONE +ENDIF +IF2 +%OUT PASS TWO +ENDIF +%OUT EQUATES +;******* I N C L U D E ******** +INCLUDE EQUATES.EZP + +; ALL SEGS ORIGINALLY POINT TO CSEG. THE ORG 100H IS STANDARD FOR +; PRODUCING A .COM FILE. THE ES SEGMENT IS ADJUSTED DYNAMICALLY IN THE +; SYSINI ROUTINE TO ALLOW GAME SEGMENTS TO START AT OFFSET ZERO. +; SEE COMMENTS IN SYSINI FOR GAME SEGMENT ALLOCATION AND CALCULATION. + +CSEG SEGMENT PARA PUBLIC + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG + ORG 100H +; + PUBLIC EZIP +EZIP PROC + JMP START ; SKIP OVER ZIP DATA +; +;******* I N C L U D E ******** +%OUT DATA +INCLUDE DATA.EZP +%OUT MACROS +INCLUDE MACROS.EZP + + SUBTTL SYSTEM INITIALIZATION + PAGE + + + PUBLIC START +START: MOV SP,OFFSET STK_TOP + MOV DI,OFFSET ZSTK_TP + JMP ZIPBGN ;JUMP TO BEGINNING OF ZIP CODE +; +;******* I N C L U D E ******** +%OUT SCRNOPS +INCLUDE SCRNOPS.EZP +%OUT GAMEOPS +INCLUDE GAMEOPS.EZP +%OUT MATHOPS +INCLUDE MATHOPS.EZP +%OUT RANDOM +INCLUDE RANDOM.EZP +%OUT LOGICOPS +INCLUDE LOGICOPS.EZP +%OUT OBJOPS +INCLUDE OBJOPS.EZP +%OUT TABLEOPS +INCLUDE TABLEOPS.EZP +%OUT VAROPS +INCLUDE VAROPS.EZP +%OUT READIO +INCLUDE READIO.EZP +%OUT PRINTOPS +INCLUDE PRINTOPS.EZP +%OUT BRANCHES +INCLUDE BRANCHES.EZP +%OUT GETBYT +INCLUDE GETBYT.EZP +%OUT ZSTRINGS +INCLUDE ZSTRINGS.EZP +%OUT SETUP +INCLUDE SETUP.EZP +%OUT ZIPBEGIN +INCLUDE ZIPBEGIN.EZP +%OUT MAINLOOP +INCLUDE MAINLOOP.EZP +%OUT PAGING +INCLUDE PAGING.EZP +%OUT SYSINI +INCLUDE SYSINI.EZP +%OUT PAGEIO +INCLUDE PAGEIO.EZP +%OUT SYSIO +INCLUDE SYSIO.EZP + +%OUT ENDEZIP +FINISH PROC + CALL MCRLF + MOV BX,OFFSET STRESET + CALL MSPRT + MOV AH,4CH + INT 21H +FINISH ENDP + +EVEN +;********************************************************************** +; DO NOT PLACE ANY VARIABLES OR CODE BEYOND THIS POINT! THE +; ZIP DYNAMICALLY ALLOCATES A PAGE TABLE AND PAGING SPACE BEYOND +; THIS LABEL. +;********************************************************************** + PUBLIC PAGTAB +PAGTAB LABEL BYTE +EZIP ENDP +CSEG ENDS + + END EZIP diff --git a/ibm/gameops.ezp b/ibm/gameops.ezp new file mode 100644 index 0000000..aa2ecab --- /dev/null +++ b/ibm/gameops.ezp @@ -0,0 +1,526 @@ + SUBTTL GAMEOPS + PAGE + +; +; VERIFY +; +; OP VERIFY HAS BEEN GIVEN A SPLIT PERSONALITY. THE CASE THAT THE ENTIRE +; GAME FITS INTO MEMORY CALLS ON OPVR2$ WHICH READS THE GAME IN TWO 64K +; READS. THE SECOND ES SEGMENT IS USED SO THAT THE SECOND READ WILL RESTORE +; THE GAME TO ITS ORIGINAL STATE. 64K IS READ IN AND CHECKSUMED AND THEN +; THE REMAINDER OF THE GAME IS READ BACK IN AND CHECKSUMED. +; +; THE ORIGINAL VERIFY FORCES THE PRELOAD TO BE LOADED AGAIN BY SETTING THE +; ENDLOD POINTER TO ZERO. THIS TRICKS GETBYT INTO THINKING THAT NO PAGES +; ARE LOCKED ALREADY IN CORE AND FORCES A CALL TO THE PAGING ROUTINES. +; +; + PUBLIC OPVERI +OPVERI PROC + CALL GAMOPEN ; (7q) PUT THE DISK BACK IN + PRINT IDSTR + CMP FITS,1 ; (6) WHOLE GAME IN??? + JNZ OPVR1$ + JMP OPVR2$ +OPVR1$: MOV AX,ES:[PLENTH] ; (7q) GET END BYTE ADDR + XCHG AH,AL ; (7q) FLOP BYTES + MOV ZPCFLG,1 ; (7n) SET MUNGED ZPC FLAG + PUSH SI + PUSH DI + PUSH ENDLOD + CALL BSPLITQ + MOV SI,AX +; SUB BX,2 ; (A7) A FUDGE FACTOR (B1 wrong ehb) + MOV DI,BX + + CALL TBLINI ; (7n) REINITIALIZE THE PAGE TABLE + MOV BX,CURTAB + SUB BX,2 ; (A0) BACKUP TO BLK NUMBER + MOV AX,CURBLK + MOV [BX],AX + MOV AX,0FFFFH ; (A0) DWORDIFY REF TIMES + MOV [BX+2],AX ; (A0) + MOV [BX+4],AX ; (A0) + + MOV AX,0 + MOV BX,64 + MOV DX,0 + MOV ENDLOD,0 +OPVR1: PUSH SI + PUSH DI + PUSH DX + CMP LSTGGD,1 ; (A16) DON'T STRUGGLE + JNE OPVRA$ + CALL GETLST ; (A16) GET LAST GETBYT VALUE + JMP OPVR$$ +OPVRA$: CALL GETBYT ; GET A BYTE FROM SEG1 +OPVR$$: POP DX + POP DI + POP SI + ADD DX,CX ; SUM IT + CMP AX,SI + JNE OPVR1 + CMP BX,DI + JNE OPVR1 + MOV AX,ES:[PCHKSM] ; REMOVED SEG OVERRIDE + XCHG AH,AL + POP ENDLOD + POP DI + POP SI +OPVR4: CMP AX,DX + JE OPVR2 + JMP PFALSE +OPVR2: JMP PTRUE +; +; VERIFY FOR FITS==1 OR ALL OF GAME IS IN MEMORY +; +OPVR2$: PUSH SI + PUSH DI + PUSH CX + PUSH DS ; (6) ADDRESS SEGMENT 1 + MOV BX,GAMHNDL ; (6) READ FROM GAME FILE + MOV SI,GAMESEG ; (6) THROUGH DS + MOV DS,SI ; (6) SO THAT WE OVERLAY GAME + MOV CX,0 ; (6) MOVE FILE PTR TO BEGINNING + MOV DX,64 ; (6) SKIP FIRST 64 BYTES + MOV AL,0 ; (6) METHOD OF SEEKING + MOV AH,CFSEEK ; (6) SEEK FUNCTION + INT 21H ; (6) DO IT + MOV CX,03FC0H ; (7n) READ 16K AT A TIME + MOV DX,0C000H ; (6) OFFSET INTO SEGMENT + MOV AH,CRDRNDZ ; (6) READ FUNCTION + INT 21H ; (6) DO IT + CMP AX,CX ; (6) DID WE GET IT ALL + JNE OPVR5 ; (6) DIE PAINFULLY + XOR DX,DX ; (7n) ZERO THE CHECKSUM + CALL CHKSUM ; (6) DO A CHKSUM +; +OPVR6: MOV DI,DX ; (7n) SAVE CHECK SUM + MOV DX,0C000H ; (7n) BUFFER SPACE + MOV CX,4000H ; (7n) READ 16K EACH TIME + MOV AH,CRDRNDZ ; (7n) DO A RANDOM READ + INT 21H ; (7n) DO IT + CMP AX,CX ; (7n) LAST READ? + JNE OPVR8 + MOV DX,DI ; (7n) RESTORE CHECKSUM + CALL CHKSUM + JMP OPVR6 +OPVR8: MOV AX,ES:[PLENTH] ; (7n) GET FILE LENGTH IN WORDS + XCHG AH,AL ; (7n) INTO AX + MOV DX,0 ; (7n) ZERO THIS FOR DIVIDE + MOV CX,1000H ; (A7) 4K quadbytes per 16K bytes + DIV CX ; (7n) number of quadbytes out of 4K + SHL DX,1 ; (A7) shift twice to get bytes + SHL DX,1 ; (7n) in partial block of 16K +; SUB DX,2 ; (A7) FUDGE FACTOR (B0 Bull!-ehb) + MOV AX,DX ; (7n) DX SHOULD HAVE REM BYTES + MOV DX,DI ; (7n) RESTORE CHECKSUM + CALL CHKSUM +; + PUSH DX + MOV CX,0 ; (7n) SEEK TO 48K INTO FILE + MOV DX,0C000H ; (7n) TO GET OVERWRITTEN PART + MOV AH,CFSEEK ; (7n) FUNCTION IS SEEK + MOV AL,0 ; (7n) TO OFFSET FROM BEGINNING + INT 21H ; (7n) DO IT + MOV DX,0C000H ; (7n) NOW REFILL SEG WITH ORIG + MOV CX,4000H ; (7n) READ 16K IN + MOV AH,CRDRNDZ ; (7n) FUNCTION READ + INT 21H + POP DX + + POP DS ; (6) RESTORES + POP CX + POP DI + POP SI + MOV AX,ES:[PCHKSM] ; (6) GET CHKSUM + XCHG AH,AL + JMP OPVR4 +; +CHKSUM: MOV CX,AX ; (7n) GET NUMBER ACTUALLY READ + XOR AX,AX ; (6) ZERO THIS + MOV SI,0C000H ; (7n) 48K INTO THE BUFFER + JCXZ OPVR7 ; (B0) check for 0 before loop +OPVR3: LODSB ; (6) GET A BYTE + ADD DX,AX ; (6) ADD IT ALL UP + LOOP OPVR3 +OPVR7: RET +; +OPVR5: FATAL FTL7 ; GAME FILE READ ERROR +OPVERI ENDP + +; +; SAVE AND RESTORE HAVE BEEN MODIFIED TO USE DOS 2.0 FILE NAMES. THIS +; ALLOWS THE USER TO SAVE AND RESTORE TO ANY DISK DRIVE AND ANY SUBDIRECTORY. +; FILE NAMES ARE READ FROM THE CONSOLE AND TRANSFERRED INTO THE SAVFILE +; VARIABLE WITH NO PARSING OTHER THAN A CHECK FOR A DISK DRIVE SPECIFIER. +; IF THE NAME IS TYPED INCORRECTLY, THEN DOS RETURNS AN ERROR WHICH WE +; REPORT ACCORDINGLY. + +; +; RESTORE +; + PUBLIC OPREST +OPREST PROC + MOV DSKDIR,0 ;INDICATE RESTORE (READ) + JMP OSV0$ +OPREST ENDP + +; +; SAVE +; + PUBLIC OPSAVE +OPSAVE PROC + MOV DSKDIR,1 ;INDICATE SAVE (WRITE) + +; +;COMMON ENTRYPOINT FOR SAVE AND RESTORE +; + PUBLIC OSV0$,OSVD1,OSVD2,OSVD3,OSVD4A,OSVPSX,OSVOPW + PUBLIC OSVOPDF,OSVPS,OSVT0,OSV4X,OSV4Y +; PUBLIC OSVCC,OSV1C,OSV2C + PUBLIC OSV4,OSVPRR +; DO A DISK RESET IN CASE THEY WANT TO CHANGE DISKS +; UNFORTUNATELY WE HAVE TO ASSUME A 1 DRIVE SYSTEM AT THIS POINT + +OSV0$: CMP FITS,1 ; (n) ARE WE ALL THERE + JZ OSV0A ; (n) YES, NO CLOSE + MOV AH,CFCLOSZ ; (7s) CLOSE THE GAME FILE + MOV BX,GAMHNDL ; (7s) FOR REINSERTION + INT 21H + MOV AH,CDRESET ; (K6) WILL RESET FLUSH BUFFERS? + INT 21H ; (K6) HOPE SO... + +; PRINT "FILENAME (DEFAULT IS drv:filename.ext):" + +; PRINT "FILENAME (DEFAULT IS drv:" +OSV0A: PRINT SAV0 ;PRINT "INSERT SAVE DISK THEN ENTER FILE NAME." + PRINT SAV1 ;PRINT "FILE NAME (DEFAULT IS " + TEST DRVFLG,1 ; HAS USER SPECIFIED A DRIVE + JNZ OSVD1 ; YES, USE USER DEFAULT DRIVE + MOV AL,CURDRV ;AL <= DRIVE NO. + ADD AL,65 ;....NO. ADD 65 TO GET ASCII CHARACTER + CALL MTTYO ;PRINT DRIVE B, C, OR D + MOV AL,":" ;PRINT ":" + CALL MTTYO + +; PRINT "filename" +OSVD1: PUSH SI ; (6) SAVE THIS + MOV SI,OFFSET SAVFILE ; (6) POINTER TO SAVE FILENAME (6) + MOV CX,SI ; (6) SAVE POINTER + CLD ; (6) SET DIR INCREMENT +OSVD2: LODSB ; (6) GET A BYTE INTO AL + TEST AL,AL ; (6) CHECK IF NULL + JZ OSVD3 ; (6) EXIT THIS LOOP + CALL MTTYO ; (6) OUTPUT IT + JMP OSVD2 +OSVD3: SUB SI,CX ; (6) CALCULATE NUMBER OF CHARS + MOV CX,SI ; (6) GET NUMBER BACK INTO CX + POP SI ; (6) RESTORE THIS + +; PRINT " ): " + PRINT SAV2 ;PRINT " ): " + CMP SCPL,50 ;ARE MAX CHARS/LINE >50? + JG OSVD4A ;....YES + CALL MCRLF ;....NO. PRINT A + +; GET LOSER'S SAVE FILENAME FROM THE KEYBOARD +OSVD4A: MOV BX,OFFSET INBUF ;^ KEYBOARD INPUT BUFFER + MOV AL,63 ;(6) COULD BE A WHOLE PATH + MOV BYTE PTR [BX],AL ;SET UP BUFFER TO TAKE 15 CHARACTERS + MOV DX,BX ;DX ^ BUFFER + MOV AH,CRDLIN ;READ A LINE FROM THE KEYBOARD + INT 21H + +; PARSE THE FILENAME + + CALL SAVESAV ; (7o) PRESERVE THE SAVE NAME + PUSH SI + PUSH DI + PUSH CX ; SAVE THIS + PUSH ES + PUSH DS + POP ES + LEA SI,INBUF[1] ; POINT TO NUM CHARS READ + LODSB ; GET NUM + TEST AL,AL ; ANY CHARS READ + JZ LOOK + MOV CL,AL ; STORE IT + XOR CH,CH ; CLEAR TOP HALF OF COUNTER + MOV DI,OFFSET SAVFILE ; (6) DI ^FCB + REPZ MOVSB ; TRANSFER THE STRING IF ANY + MOV AL,0 ; (6) GET A NULL + STOSB ; (6) DROP IT IN AT END OF STRING +LOOK: TEST SCRFLG,1 ; (7p) IS SCRIPTING ON? + JZ NOSCR ; (7p) NO SCRIPTING + CALL SCRSAVE ; (7p) SCRIPT THE SAVE FILE NAME +NOSCR: MOV SI,OFFSET SAVFILE ; (6) IS THERE A ':' + INC SI + LODSB ; (6) CHECK IT + CMP AL,':' ; (6) IF SO, FIX DEFDRV + JNZ NODRV ; (6) NOPE... + MOV DRVFLG,1 ; (6) SET FLAG + MOV AL,SAVFILE ; (7n) GET DRIVE LETTER + AND AL,5FH ; (7n) UPPERCASIFY + SUB AL,'A' ; (7n) BASIFY + CMP AL,CURDRV ; (7n) DON'T CHANGE IF UNNECESSARY + JZ DRV + MOV DL,AL ; (7n) SET UP FOR CHGDSK + MOV AH,CSELDSK ; (7n) SELECT DISK IN DL + INT 21H + MOV AH,CURDSK ; (7n) CHECK IF IT WORKED + INT 21H + MOV CURDRV,AL ; (7n) SAVE IT + JMP DRV +USEDEF: MOV SKPDRV,1 ; (7n) DON'T OUTPUT A DRIVE +NODRV: MOV DRVFLG,0 +DRV: POP ES + POP CX + POP DI ;RESTORE'M + POP SI + CALL MCRLF ; (7) SCROLL PROPERLY + +; OPEN THE FILE IF OP RESTORE + + CMP DSKDIR,1 ;OP SAVE? + JE OSVOPW ;....YES + MOV DX,OFFSET SAVFILE ; 6) ....NO. OP RESTORE. DX ^ FCB + MOV AH,CFOPENZ ; (6) SELECT DOS OPEN FUNCTION + MOV AL,0 ; (6) FILE OPEN FOR READING + INT 21H ;OPEN THE FILE + JC OSVPSX ; (6) ....NO. FILE NOT FOUND + JMP OSVPS ;....YES +; +; **** ERROR **** [File Not Found] +; +OSVPSX: MOV AX,OFFSET ERR1 ;^ "SAVE FILE NOT FOUND" MSG + JMP OSVPER ;ERROR EXIT + +; CREATE THE FILE IF OP SAVE +OSVOPW: MOV DX,OFFSET SAVFILE ; (6) ^ FCB + MOV CX,0 ; (6) NO SPECIAL ATTRIBUTE + MOV AH,CFCREAZ ; (6) SELECT DOS CREATE FUNCTION + INT 21H + JC OSVOPDF + JMP OSVPS ;....YES +; +; **** ERROR **** [Directory Full] +; +OSVOPDF:MOV AX,OFFSET ERR4 ;....NO. ^ "NO ROOM IN DIRECTORY" MSG + JMP OSVPER ;HOP TO ERROR EXIT +; +; WE'VE GOT AN OPEN FILE (WHICH WE CREATED IF IT WAS A SAVE FUNCTION) +; AND ARE READY TO EITHER READ (RESTORE) OR WRITE (SAVE) AS REQUIRED +; +; THE BELOW CODE GRIMLY EXPLAINS THE FORMAT OF A SAVE FILE. BASICALLY, +; FROM WHAT I CAN TELL, THE LOCALS AND VITALS ARE PUSHED ONTO THE ZSTACK +; AS WELL AS THE ZPC AND THE ZSTACK POINTER. THIS INFORMATION IS FIRST +; WRITTEN TO DISK. THEN THE REST OF PURBOT IS WRITTEN TO DISK. THIS CODE +; ALSO WORKS FOR A RESTORE. SO THE SAVE FILE CONSISTS OF FIRST ZIP INFO +; SAVED ON DISK FOLLOWED BY THE IMPURE PART OF THE GAME CODE. +; +OSVPS: XCHG DI,SP + PUSH ZPC1 ; PUSH VITALS ONTO ZSTACK + PUSH ZPC2 + PUSH ZLOCS + PUSH ZORKID + + + SUB SP,OFFSET STKBOT ; (7v) RELATIVISE THE POINTER + MOV STKBOT,SP ; PUT DEST. INDEX INTO STACKBOTTOM + MOV SP,DI ; RESTORE SP + + MOV SAVHNDL,AX ; SAVE FILE HANDLE + PUSH ES + + MOV AX,SS ; FLOP STACK SEG AND EXTRA SEG + MOV ES,AX ; ES<=SS + + MOV DX,OFFSET STKBOT ; CORE LOCATION + MOV CX,LSTACK*2 ; (6) DO TRANSFER HERE + MOV BX,SAVHNDL ; (6) GET HANDLE + MOV AH,CRDRNDZ ; SETUP FOR A READ + ADD AH,DSKDIR ; MAKE IT A WRITE IF NECESSARY + INT 21H ; + CMP AX,400H ; DID WE GET IT ALL + PUSHF ;SAVE RETURN CODE + MOV DI,SP ;DI ^ CURRENT ZSTACK POSITION + MOV SP,STKBOT ;SP <= ZSTACK POINTER + ADD SP,OFFSET STKBOT ; (7v) RELATIVISE THIS VALUE + POP AX ; POP OFF AND COMPARE FOR ZORKID + CMP AX,ZORKID ;ID OK? + JE OSVT0 ;....YES + MOV GAMEIN,0 ; (7v) INDICATE THAT THE GAME IS LOST + FATAL FTL4 ;....NO. FATAL ERROR + +OSVT0: POP ZLOCS ;RESTORE LOCALS AND ZIP PROGRAM COUNTERS + POP ZPC2 + POP ZPC1 + + XCHG DI,SP ;RESTORE MACHINE SP AND ZSTACK POINTER + POPF ;RESTORE REGS + POP ES + JNE OSV4Y ;TRANSFER WAS UNSUCCESSFUL +; +; THE OPEN/CREATE FILE WAS SUCCESSFUL, AND SO WAS THE BLOCK TRANSFER +; SO TRANSFER THE REST +; +OSV4X: MOV CX,ES:[PPURBT] ; (K3) MAYBE THIS IS WRONG + XCHG CH,CL ; (K3) XCHANGE BYTES + MOV AH,CRDRNDZ ; (K1) FUNCTION IS READ (OR WRITE) + ADD AH,DSKDIR ; (K1) ADD IN WRITE STUFF + MOV BX,SAVHNDL ; (K1) READ IT FROM HERE + MOV DX,0 ; (K1) READ IT RIGHT IN TO SEG0 + PUSH DS ; (K1) SAVE DS + PUSH ES ; (K1) FLOP BYTES + POP DS ; (K1) ES IS NOW DOS ADDRESSIBLE + INT 21H ; (K1) DO THE SAVE/RESTORE + POP DS ; (K1) RESTORE DS + CMP AX,CX ; (K1) DID WE GET IT ALL? +OSV4Y: PUSHF ;SAVE DOS RETURN CODE + MOV AH,CFCLOSZ ; (6) CLOSE THE FILE + MOV BX,SAVHNDL ; (6) WITH THIS HANDLE + INT 21H + POPF ;RESTORE DOS RETURN CODE + JNE OSV4 ;ERROR EXIT +; +;ELSE EVERYTHING WORKED SUCCESSFULLY +;AND WE CAN GO BACK TO WHAT WE WERE +;DOING.......... +; + MOV AH,SCRFLG ; (J2) FIX SCRFLG + OR AH,STSBIT ; (A9) TURN ON STATUS LINE REFRESH BIT + XOR AL,AL ; (J2) + MOV WORD PTR ES:[PFLAGS],AX ; (J1) SCRIPT SHOULD MATCH SCRFLG + CMP FITS,1 ;(n) do not need to replace disk if in mem + JZ n1 + CALL GAMOPEN ; (7s) OPEN GAME FILE + MOV DL,CURDRV ; (7n) RETURN TO SAVE DISK + MOV AH,CSELDSK ; (7n) AND SELECT IT FOR OPEN + INT 21H +N1: CALL NEWZPC ;GET A NEW PC + MOV AX,2 ; (A0) RETURN 1 FOR SAVE OR 2 FOR RESTORE + SUB AL,DSKDIR ; (A0) SUBTRACT ONE FOR SAVE + JMP PUTVAL ; (A0) +; +; **** ERROR **** [Unable to Read File] +; +OSV4: MOV AX,OFFSET ERR6 ;^ "Read of SAVE file failed." + CMP DSKDIR,1 ;OP SAVE? + JNE OSVPRR ;....NO + MOV AH,CFCLOSZ ; (6) ....YES. CLOSE IT + MOV BX,SAVHNDL ; (6) GET HANDLE FOR CLOSE + INT 21H +; +; **** ERROR **** [Diskette Full] +; + MOV DX,OFFSET SAVFILE ; (7n) DELETE THE PIECE OF A FILE + MOV AH,CFDELEZ ; (7n) SO AS NOT TO CONFUSE + INT 21H + MOV AX,OFFSET ERR5 ;^ "No room on diskette for SAVE file." +OSVPRR: JMP OSVPER +OPSAVE ENDP +; +; ERROR EXIT R/W operations +; +OSVPER PROC + CALL MPRNT ;PRINT ERROR MESSAGE + CALL ZRESTOR ; (7o) RESTORE OLD SAVE NAME + CMP FITS,1 ; (7v) HAVE WE CLOSED THE GAME FILE + JZ OSVPR1 ; (7v) SKIP REOPEN + CALL GAMOPEN ; (7v) OPEN IT +OSVPR1: MOV AH,SCRFLG ; (A13) RESTORE SCRIPTING STATE + OR AH,STSBIT ; (A9) TURN ON STATUS LINE REFRESH BIT + XOR AL,AL ; (J1) FIX SCRIPT ON BAD RESTART (RANDOM) + MOV ES:[PFLAGS],AX + MOV AX,0 ; (A0) RETURN A FALSE + JMP PUTVAL ; (A0) +OSVPER ENDP +; + PUBLIC SAVESAV,ZRESTOR,SCRSAVE +SCRSAVE PROC + PUSH AX ; (7p) SAVES + PUSH SI + PUSH DX + MOV SI,OFFSET SAVFILE ; (7p) POINTER TO SAVE +SCRS0: LODSB ; (7p) GET A CHARACTER + TEST AL,AL ; (7p) LOOK FOR A NULL + JNZ SCRS1 ; (7p) DIE ON A NULL + POP DX + POP SI + POP AX + RET ; (7p) RETURN +SCRS1: MOV DL,AL ; (7p) GET CHARACTER INTO DL + MOV AH,CPROUT ; (7p) FOR DOS"IE" OUTPUT + INT 21H ; (7p) PRINT IT + JMP SCRS0 +SCRSAVE ENDP + +SAVESAV PROC + PUSH DI ; (7o) SAVES + PUSH SI + PUSH AX + PUSH ES + MOV AX,DS ; (7o) SET UP REGS + MOV ES,AX + MOV AL,CURDRV ; (7o) SAVE CURRENT DRIVE SPEC + MOV LASTDRV,AL ; (7o) IN CASE OF FAILURE + MOV AL,DRVFLG ; (7o) TEST DRIVE FLAG + MOV LSTDFLG,AL ; (7o) IN CASE OF FAILURE + MOV SI,OFFSET SAVFILE ; (7o) SETUP SOURCE AND DESTINATION + MOV DI,OFFSET LASTSAV +COPYLP: LODSB ; (7o) GET A BYTE + STOSB ; (7o) STORE A BYTE + TEST AL,AL ; (7o) STOP ON A NUL + JNZ COPYLP ; (7o) CONTINUE THE COPY + POP ES + POP AX ; (7o) RESTORES + POP SI + POP DI + RET +SAVESAV ENDP +; +; +ZRESTOR PROC + PUSH DI ; (7o) SAVES + PUSH SI + PUSH AX + PUSH ES + MOV AX,DS ; (7o) SET UP REGS + MOV ES,AX + MOV AL,LSTDFLG ; (7o) GET LAST DRIVE FLAG + MOV DRVFLG,AL ; (7o) AND RESTORE IT + MOV AL,LASTDRV ; (7o) GET ORIGINAL DRIVE SPEC + CMP AL,CURDRV ; (7o) HAS IT CHANGED + JZ ZRES1 + MOV DL,AL ; (7o) SELECT DISK + MOV AH,CSELDSK ; (7o) TO CORRECT + INT 21H + MOV CURDRV,DL ; (7o) UPDATE THIS BABY +ZRES1: MOV DI,OFFSET SAVFILE ; (7o) SETUP SOURCE AND DESTINATION + MOV SI,OFFSET LASTSAV +ZRESLP: LODSB ; (7o) GET A BYTE + STOSB ; (7o) STORE A BYTE + TEST AL,AL ; (7o) STOP ON A NUL + JNZ ZRESLP ; (7o) CONTINUE THE COPY + POP ES + POP AX ; (7o) RESTORES + POP SI + POP DI + RET +ZRESTOR ENDP +; +; OP RESTART +; + PUBLIC OPRSTT +OPRSTT PROC + MOV BP,CHRPTR + MOV BYTE PTR DS:[BP],0 ;FORCE OUT THE BUFFER + PRINT OUTBUF + JMP RESTRT ;JUMP TO RESTART ADDRESS +OPRSTT ENDP + + PUBLIC OPQUIT +OPQUIT PROC + JMP FINISH +OPQUIT ENDP diff --git a/ibm/getbyt.ezp b/ibm/getbyt.ezp new file mode 100644 index 0000000..c095baa --- /dev/null +++ b/ibm/getbyt.ezp @@ -0,0 +1,428 @@ + SUBTTL GETBYT - LOW LEVEL FUNCTIONS + PAGE + + + ;GET A BYTE, BLOCK-POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX, + ;UPDATE AX & BX TO REFLECT BYTE GOTTEN +; +; GETBYT UNDERWENT SERIOUS RE-WRITING AND EVALUATION IN THE UPDATE TO USE +; ALL OF MEMORY. THE ORIGINAL ROUTINE WAS KEPT BUT CHANGES WERE MADE IN +; TWO SETS: THE FIRST TO HANDLE THE CASE IN WHICH ALL OF THE GAME IS IN +; MEMORY; AND THE SECOND IN WHICH THE GAME BUFFERS EXTEND PAST 64K AND THUS +; REQUIRING A SEGMENT SWITCH TO RETRIEVE THE BYTE. +; +; FOR THE FIRST CASE, THE BLOCK PTR IS USED TO DETERMINE THE SEGMENT IN +; WHICH THE BLOCK RESIDES, THE GAME SEGMENT IS SET ACCORDINGLY, AND THE +; BYTE IS FETCHED. +; +; THE SECOND CASE WILL CALL GETPAG TO DETERMINE WHERE THE PAGE IS LOCATED IN +; CORE.CALLING GETPAG WILL SET A VARIABLE CALLED CURSEG TO 0 OR 1 TO INDICATE +; THAT THE PAGE WE ARE TOUCHING IS IN THE FIRST OR SECOND SEGMENT. GETPAG +; RETURNS A VALID POINTER ASSUMING THAT THIS ROUTINE WILL SET ES ACCORDING TO +; CURSEG. IF CURSEG IS 0, GAMESEG (THE FIRST SEGMENT [OR ZEROTH]) WILL +; CONTAIN THE BLOCK, AND IF CURSEG IS 1, SEG1 (GAMESEG + 64K) WILL CONTAIN +; THE BLOCK. +; +; NOTE THAT ES ALWAYS CONTAINS THE VALUE GAMESEG UNLESS WE NEED TO FETCH +; OR PUT SOMETHING IN THE SECOND SEGMENT. AT THAT POINT ES IS SET TO SEG1 +; ONLY FOR THAT OPERATION. +; + PUBLIC GETBYT,FETCH,GTY1A$,GTSEG,GTY1$,GTY1B$,GTY2$,GTY3$ +GETBYT PROC + PUSH SI ; SAVE THIS BEAR + PUSH AX ;SAVE BLOCK-POINTER + CMP FITS,1 ; (6) IS ALL OF THE GAME RESIDENT + JZ FETCH ; (6) IT'S THERE, GO GET IT + CMP AX,ENDLOD ;IS THIS A PRELOADED LOCATION? + JGE GTY1$ ;NO +FETCH: CMP AX,128 ; (A0) FIRST SEG IS SPECIAL CASE + JB GTY1A$ ; (A0) SEGS ALREADY SET UP RIGHT + SUB AX,128 ; (A0) BASIFY BLOCK NUMBER FOR SEG + MOV SI,SEG1 ; (A0) SET UP TO FIND SEG + MOV CURSEG,1 ; (A0) INIT THIS FOR LOOP +FETCH1: CMP AX,128 ; (6) CHECK SEGMENT FOR BLOCK + JB GTSEG ; (A0) GO AHEAD AND GET IT + SUB AX,128 ; (A0) IS IT IN THE NEXT SEG + ADD SI,1000H ; (A0) INC SEG POINTER + INC CURSEG ; (A0) INCREMENT OUR SEGMENT POINTER + JMP FETCH1 +GTY1A$: MOV CL,9 ;YES, RECONSTRUCT POINTER + SHL AX,CL ;SHIFT BLOCK POINTER BY 9 + OR AX,BX ;ADD IN THE OFFSET + XCHG AX,BX + + JMP GTY1B$ ; (A16) GET BYTE (OR WORD) + +GTSEG: MOV ES,SI ; (6) ADDRESS SEG1 + JMP GTY1A$ ; (6) USE SEG0 LOGIC +GTY1$: CALL GETPAG ;FIND THE PROPER PAGE + ADD AX,BX ;POINT TO DESIRED BYTE + XCHG AX,BX + CMP CURSEG,0 ;(A0) CHECK SEGMENT THAT WERE LOOKING IN + JZ GTY1B$ ;(A0) ITS IN 0, GET IT NORMALLY + + PUSH AX ; (A0) SAVE IMPORT REGISTERS + PUSH BX + PUSH DX + MOV DX,0 ; (A0) ZERO THIS FOR MUL + MOV AX,1000H ; (A0) INITIAL SEG ADDR + MOV BL,CURSEG ; (A0) GET CURRENT SEGMENT NUMBER + MOV BH,0 ; (A0) ZERO TOP HALF + MUL BX ; (A0) SEG NUMBER * GAMESEG + ADD AX,GAMESEG ; (A0) GET GAMESEG AS OFFSET + MOV SI,AX ; (A0) SAVE IN SI + POP DX ; (A0) RESTORES + POP BX + POP AX + MOV ES,SI ;(6) GETPAG RETURNED RIGHT POINTER + +GTY1B$: CMP BX,0FFFFH ; (A16) CAN'T READ A WORD ACROSS SEG + JNE GTWRD1$ + MOV CL,ES:[BX] ; GET BYTE + JMP GTY2$ +GTWRD1$:MOV CX,ES:[BX] ; GET A WORD AND SAVE A BYTE + MOV LSTGET,CH ; SAVE NEXT SEQUENTIAL BYTE + MOV LSTGGD,1 ; (A16) INDICATE GOOD GET NEXT BYTE + +GTY2$: SUB CH,CH ;CLEAR UNWANTED BYTE & RETURN IT + MOV BX,AX + MOV SI,GAMESEG ; (6) MAKE SURE GAME SEG IS RESTORED + MOV ES,SI ; (6) TO SEG 0 + POP AX ;RESTORE BLOCK-POINTER + POP SI ; RESTORE THIS + INC BX ;UPDATE POINTER + CMP BX,200H ;END-OF-PAGE? + JNE GTY3$ ;NO + SUB BX,BX ;YES, CLEAR BYTE-POINTER + INC AX ;AND UPDATE BLOCK-POINTER + MOV LSTGGD,0 ; (A16) INDICATE NO NEXT BYTE +GTY3$: RET +GETBYT ENDP + +; GET THE BYTE FOLLOWING THE LAST BYTE GOTTEN BY GETBYT +; + PUBLIC GETLST +GETLST PROC + MOV CL,LSTGET ; (A16) GET THE SAVED BYTE + MOV CH,0 ; (A16) ZERO TOP HALF + MOV LSTGGD,0 ; (A16) RESET FLAG + INC BX ; (A16) UPDATE POINTER + CMP BX,200H ; (A16) END OF PAGE? + JNE GTLST2 + MOV BX,0 ; (A16) UPDATE BYTE POINTER + INC AX ; (A16) AND PAGE POINTER +GTLST2: RET +GETLST ENDP + + + ;GET A WORD, BLOCK POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX + PUBLIC GETWRD +GETWRD PROC + PUSH DX ;SAVE + CALL GETBYT ;GET HIGH-ORDER BYTE + PUSH CX ;SAVE IT + CMP LSTGGD,1 ; (A16) FAST GET? + JNZ GETWRD1 + CALL GETLST ; (A16) GET LAST BYTE + JMP GETWRD2 +GETWRD1:CALL GETBYT ;GET LOW-ORDER BYTE +GETWRD2:POP DX ;GET OTHER BYTE + MOV CH,DL ;POSITION IT + POP DX ;RESTORE + RET +GETWRD ENDP + + ;GET THE NEXT BYTE, RETURN IT IN AX +; THIS ROUTINE ALSO WENT UNDER SIGNIFICANT REVISION TO ACCOMODATE MORE +; PAGING SPACE. TWO CASES HAD TO BE HANDLED: ALL OF GAME IN MEMORY AND +; MORE THAN 64K OF PAGING SPACE. THE FIRST CASE REQUIRED THAT THE VARIABLE +; ZPCSEG BE SET IN NEWZPC TO INDICATE IN WHICH SEGMENT OUR ZPC BLOCK COULD +; BE FOUND. THE SECOND CASE REQUIRES THAT ZPCSEG BE SET ONLY WHEN GETPAG +; IS CALLED FROM NEWZPC AND THE PAGE THAT IT GOT WAS PUT IN THE SECOND GAME +; SEGMENT. +; + PUBLIC NXTBYT,NXBA$,NXB1$ +NXTBYT PROC + CMP LSTNGD,1 ; (A16) HAS THE ZPC BEEN PLAYED WITH SINCE? + JNE NXTBYT1 ; YES + JMP NXTLST ; (A16) NOPE, GET A BYTE QUICKLY +NXTBYT1:PUSH SI ;(6) PRESERVE THIS ONE TOO + PUSH BX ;SAVE + TEST ZPCFLG,1 ;(7n) HAS THIS PAGE SEEN FOUL PLAY? + JZ NXB0$ ; (7n) NOPE + CALL NEWZPC ; (7n) FIX INDEX INTO CURRENT PAGE +NXB0$: MOV BX,ZPC2 ;BYTE POINTER + ADD BX,CURPAG ;INDEX INTO CURRENT PAGE + CMP ZPCSEG,0 ;(6) WHERE ARE WE? + JZ NXBA$ ;(6) SEG0, ACT NORMALLY + PUSH BX ; (A0) SAVE THIS TO USE AS INDEX + PUSH DX ; (A0) SAVE THIS 'CUZ IT GETS CLOBBERED + XOR BH,BH ; (A0) STARTING FROM ZERO + MOV BL,ZPCSEG ; (A0) THIS VAR HAS WHAT SEG WERE IN + DEC BX ; (A0) SEG 1 MULS 1000*0+SEG1 + MOV AX,1000H ; (A0) FIRST SEGMENT VALUE + MUL BX ; (A0) MULTIPLY BY SEGMENT NUMBER + ADD AX,SEG1 ; (A0) ADD IN ADDR OF SEG1 + POP DX ; (A0) RESTORE IT + POP BX ; (A0) RESTORE OFFSET + MOV ES,AX ;(6) INTO ES +NXBA$: CMP BX,0FFFFH ; (A16) CAN'T CROSS SEG BOUNDARY + JNE NXBB$ + MOV AL,ES:[BX] ; (A6) THIS COULD BE CROSSING A SEG + JMP NXBC$ + +NXBB$: MOV AX,ES:[BX] ; (A16) GET A WORD AND SWAP BYTES + MOV LSTNXT,AH ; (A16) SAVE HIGH BYTE FOR NEXT NXTBYT + MOV LSTNGD,1 ; (A16) SET FLAG TO INDICATE QUICK NEXT + +NXBC$: PUSH AX ; (A6) SO PREVENT A CRASH + MOV SI,GAMESEG ;(6) GET BASE GAME SEG + MOV ES,SI ;(6) BACK INTO ES + INC ZPC2 ;UPDATE PC + CMP ZPC2,200H ;END-OF-PAGE? + JL NXB1$ ;NO + MOV LSTNGD,0 ; (A16) RESET FLAG, BYTE UNRELIABLE + CALL NEWZPC ;YES, UPDATE PAGE +NXB1$: POP AX ;RETRIEVE BYTE + SUB AH,AH ;CLEAR UNWANTED BYTE + POP BX ;RESTORE + POP SI + RET ;AND RETURN IT +NXTBYT ENDP + +; +; GET THE NEXT BYTE FOLLOWING PREVIOUS NXTBYT CALL + PUBLIC NXTLST +NXTLST PROC + MOV AH,0 ; (A16) ZERO TOP HALF + MOV AL,LSTNXT ; (A16) GET BYTE + PUSH AX ; (A16) SAVE THE BYTE + MOV LSTNGD,0 ; (A16) GO THRU THE BIGGIE NEXT TIME + INC ZPC2 ; (A16) BUMP PC + CMP ZPC2,200H ; (A16) END OF PAGE? + JNE NXTL1 + CALL NEWZPC +NXTL1: POP AX + RET +NXTLST ENDP + + ;GET THE NEXT WORD, RETURN IT IN AX + PUBLIC NXTWRD +NXTWRD PROC + PUSH BX ;SAVE + CALL NXTBYT ;GET HIGH-ORDER BYTE + PUSH AX ;SAVE IT + CALL NXTBYT ;GET LOW-ORDER BYTE + POP BX ;GET HIGH-ORDER BYTE + MOV AH,BL ;POSITION IT + POP BX ;RESTORE + RET ;RETURN THE WORD +NXTWRD ENDP + + ;GET AN ARGUMENT GIVEN ITS TYPE IN AX + PUBLIC GETARG +GETARG PROC + DEC AX ;EXAMINE ARGUMENT + JL NXTWRD ;0 MEANT LONG IMMEDIATE + JE GETAR2 ;1 MEANT SHORT IMMEDIATE +GETAR1: CALL NXTBYT ;2 MEANT VARIABLE, GET THE VAR + CMP AX,0 ;STACK? + JNE GETVAR ;NO, JUST GET THE VAR'S VALUE + POPZ AX ;YES, POP THE STACK + RET +GETAR2: JMP NXTBYT +GETARG ENDP + + ;GET VALUE OF A VARIABLE, VAR IN AX, VALUE RETURNED IN AX + PUBLIC GETVAR +GETVAR PROC + CMP AX,0 ;STACK? + JNE GTV1$ ;NO + POPZT AX ;YES, GET TOP-OF-STACK + RET +GTV1$: PUSH BP ;SAVE + CMP AX,16 ;LOCAL? + JGE GTV3$ ;NO + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV AX,[BP] ;AND GET IT +GTV2$: POP BP ;RESTORE + RET +GTV3$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + MOV BP,AX ;AND GET IT + GTAWRD A,[BP] + JMP GTV2$ +GETVAR ENDP + + ;UPDATE VALUE OF A VARIABLE, VAR IN AX, NEW VALUE IN BX + PUBLIC PUTVAR +PUTVAR PROC + CMP AX,0 ;STACK? + JNE PTV1$ ;NO + PUSHZT BX ;YES, UPDATE TOP-OF-STACK + RET +PTV1$: CMP AX,16 ;LOCAL? + JGE PTV2$ ;NO + PUSH BP ;SAVE + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV [BP],BX ;AND UPDATE IT + POP BP ;RESTORE + RET +PTV2$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + XCHG AX,BX ;AND UPDATE IT + PTAWRD [BX],A + RET +PUTVAR ENDP + + ;RETURN VAL IN AX TO LOCATION SPECIFIED BY NEXTBYTE + ;DESTROYS BX, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION + PUBLIC BYTVAL +BYTVAL PROC + SUB AH,AH ;THIS ENTRY FOR BYTE VALUE TO CLEAR HIGH BYTE + JMP PUTVAL +BYTVAL ENDP + + PUBLIC PUTVAL +PUTVAL PROC + MOV BX,AX ;NORMAL ENTRY + CALL NXTBYT ;GET VAR TO USE + CMP AX,0 ;STACK? + JNE PUTVAR ;NO, GO STORE VALUE + PUSHZ BX ;YES, PUSH ONTO STACK + RET ;AND RETURN +PUTVAL ENDP + + ;PREDICATE HANDLERS TRUE & FALSE + ;DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FCNS + PUBLIC PFALSE,PTRUE +PFALSE PROC + SUB BX,BX ;PREDICATE WAS FALSE, CLEAR FLAG + JMP PPRED +PFALSE ENDP + +PTRUE PROC + MOV BX,1 ;PREDICATE WAS TRUE, SET FLAG + JMP PPRED +PTRUE ENDP + + PUBLIC PPRED +PPRED PROC + CALL NXTBYT ;GET FIRST (OR ONLY) PREDICATE JUMP BYTE + TEST AX,80H ;NORMAL POLARITY PREDICATE? + JE PPR1$ ;NO, LEAVE FLAG ALONE + INC BX ;YES, INCREMENT FLAG +PPR1$: TEST AX,40H ;ONE-BYTE JUMP OFFSET? + JE PPR2$ ;NO + AND AX,0FF3FH ;YES, CLEAR SPECIAL BITS + JMP PPR3$ +PPR2$: AND AX,0FF3FH ;CLR SPECIAL BITS FROM HIGH-ORDER OFFSET BYTE + MOV CX,AX ;HIGH-ORDER BYTE + CALL NXTBYT ;GET LOW-ORDER BYTE + MOV AH,CL ;MOVE IN HIGH-ORDER BITS + TEST AX,2000H ;IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)? + JE PPR3$ ;NO + OR AX,0C000H ;YES, MAKE 16-BIT NUMBER NEGATIVE +PPR3$: DEC BX ;TEST FLAG + JE PPR6$ ;WAS 1, THAT MEANS DO NOTHING + CMP AX,0 ;ZERO JUMP? + JNE PPR4$ ;NO + JMP OPRFAL ;YES, THAT MEANS DO AN RFALSE +PPR4$: DEC AX ;ONE JUMP? + JNE PPR5$ ;NO + JMP OPRTRU ;YES, THAT MEANS DO AN RTRUE +PPR5$: DEC AX ;ADJUST OFFSET + MOV LSTNGD,0 ; (A16) NXTBYT WILL BE LONG + ADD ZPC2,AX ;ADD TO PC + CMP ZPC2,200H ; (A15) DID WE CROSS A BOUNDARY? + JB PPR6$ ; (A15) DO NEWZPC ONLY IF PAGE IS CROSSED + JMP NEWZPC ;AND UPDATE ZPC STUFF +PPR6$: RET +PPRED ENDP + + ;SPLIT BYTE-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE OFFSET IN BX + PUBLIC BSPLTB +BSPLTB PROC + MOV BX,AX + XCHG AL,AH ;EXTRACT BLOCK BITS + SHR AX,1 + AND AX,7FH ;CLEAR UNWANTED BITS + AND BX,1FFH ;CLEAR ALL BUT BYTE OFFSET BITS + RET +BSPLTB ENDP + + ;SPLIT WORD-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE-OFFSET IN BX + PUBLIC BSPLIT +BSPLIT PROC + MOV BX,AX + MOV AL,AH ;EXTRACT BLOCK BITS + SUB AH,AH ;CLEAR UNWANTED BITS + SUB BH,BH ;CLEAR ALL BUT WORD OFFSET BITS + SHL BX,1 ;CONVERT TO BYTE OFFSET + RET +BSPLIT ENDP + + ;SPLIT QUAD-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE-OFFSET IN BX + PUBLIC BSPLITQ +BSPLITQ PROC + PUSH CX ; (A0) SAVE AND USE FOR SHIFT COUND + MOV CL,7 ; (A0) ZIP BIT SHIFT WOULD LOSE BITS + MOV BX,AX + SHR AX,CL ; (A0) RIGHT SHIFT 7 TO GET BLOCK POINTER + AND BX,7FH ;CLEAR ALL BUT WORD OFFSET BITS + ADD BX,BX + ADD BX,BX + POP CX ; (A0) RESTORE CX + RET +BSPLITQ ENDP + + SUBTTL OBJECT HACKERS + PAGE + + + PUBLIC OBJLOC,NXTPRP + ;GIVEN OBJ NUMBER IN AX, RETURN OBJ LOCATION IN AX +OBJLOC PROC + PUSH BX ;MULTIPLY BY OBJECT LENGTH + PUSH DX ; (A0) PRESERVE FROM SIGN EXTENSION + MOV BX,OBJLEN ; (A0) GET LENGTH OF OBJECT FOR MULTIPLY + MUL BX ; (A0) USE BX AS MULTIPICAND + POP DX ; (A0) RESTORE DX + POP BX ;RESTORE + ADD AX,OBJTAB ;INDEX INTO OBJECT TABLE + ADD AX,PROPDEF ; (A0) SKIPPING DEFAULT PROPERTY TABLE + RET +OBJLOC ENDP + + ;GIVEN POINTER TO A PROPERTY IN BX!, UPDATE IT TO POINT TO NEXT PROP +NXTPRP PROC + PUSH AX ;SAVE + PUSH CX ;SAVE + MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + INC BX ; (A0) ADVANCE PROP BYTE POINTER + TEST AL,80H ; (A0) PROPERTY LENGTH GREATER THAN 2? + JNZ NXTPR1 ; (A0) YES + TEST AL,40H ; (A0) NO, PROPERTY LENGTH 2? + JZ NXTPR2 ; (A0) NO, PROPERTY LENGTH 1 + INC BX ; (A0) UPDATE THE POINTER +NXTPR2: INC BX ; (A0) UPDATE THE POINTER + POP CX + POP AX + RET +; +NXTPR1: MOV AL,ES:[BX] ; (A0) GET SECOND PROPERTY LENGTH BYTE + AND AL,MASK PROPNUM ; (A0) MASK OFF HIGH BITS + INC BX ; (A0) UPDATE POINTER + XOR AH,AH ; (A0) CLEAR THIS FOR SAFETY + ADD BX,AX ; (A0) ADD IN LENGTH OF PROPERTY + POP CX ;RESTORE + POP AX ;RESTORE + RET +NXTPRP ENDP + diff --git a/ibm/gol.bat b/ibm/gol.bat new file mode 100644 index 0000000..40fe4dd --- /dev/null +++ b/ibm/gol.bat @@ -0,0 +1,4 @@ +link lip dump,lip,lip/map; +exe2bin lip.exe +del lip.com +rename lip.bin lip.com diff --git a/ibm/ibmzip.asm b/ibm/ibmzip.asm new file mode 100644 index 0000000..aa8e7dc --- /dev/null +++ b/ibm/ibmzip.asm @@ -0,0 +1,3673 @@ + + .LIST + + TITLE ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + PAGE 58,132 + + SUBTTL STACK AND DATA SEGMENTS INITIALIZATION + + ; CHANGES ON "D" VERSION + ; + ; 1) SPLIT AND SCREEN OPCODES WORK + ; 2) RAGGED SCREEN FIXED + ; 3) DELETE KEY COLOR PROBLEM FIXED + ; 4) PRINTER PROBLEM FIXED + ; 5) COLOR QUESTION ON RESTART FIXED + ; 6) RANDOMNESS BUG FIXED - 06/25/84 - DAN HORN + + +ZVERSN EQU "D" ;ZIP VERSION NUMBER +ZMVERS EQU 3 ;Z-MACHINE VERSION NUMBER +LSTACK EQU 256 ;LENGTH OF USER STACK(MUST BE 1 PAGE FOR NOW) + +ABS_SG SEGMENT AT 0H +ABS_SG ENDS + +STK_SG SEGMENT PARA STACK + DW 100H DUP(?) +STK_TOP LABEL WORD +STKBOT DW LSTACK DUP(?) +ZSTK_TP LABEL WORD +STK_SG ENDS + +DATA_SG SEGMENT PARA + + ;VARIBLE DEFINITIONS: + + ;SCREEN COLOR ATTRIBUTES +NRMATR DB 07H ;FOR B/W, NORMAL - IN COLOR, WHITE ON BLUE +USLATR DB 70H ;B/W AND COLOR, BLACK ON WHITE +TYPATR DB 07H ;FOR COLOR, YELLOW ON BLUE/ FOR B&W, ? +COLORQ DB " Do you want color (Y/N)? ",80H +COLFLG DB 0 ;NON ZERO IF THEY WANT COLOR +OLDCUR DW 0 ; TEMP FOR OLD CURSOR POSITION + ;SCRIPTING STUFF +SCRFLG DB 0 +PRNRDY DB " * Printer not ready: Abort or Retry? ",80H + + ;USL STUFF +USLMOD DB 0 ;FOR PUTCHR +PMFLAG DB 0 ;AM/PM + +SLSTR DW 0 ;TOP OF SCREEN STRING +SLTAB DW 0 ;TABLE USED BY OPUSL + +SLSTAB DW SLS40 + DW SLS40T + DW SLS80 + DW SLS80T +SLTTAB DW SLT40 + DW SLT40T + DW SLT80 + DW SLT80T + +;40 COLUMN, SCORE +SLS40 DB 25 DUP(32),"S:",4 DUP(32),"M:",7 DUP(32),0,80H +SLS40T DW -1 + DW OPPRND + DW 2 + DW 24 + DW -1 + DW OPPRNN + DW 27 + DW 30 + DW -1 + DW OPPRNN + DW 33 + DW 36 + +;40 COLUMN, TIME +SLT40 DB 25 DUP(32),"Time:",10 DUP(32),0,80H +SLT40T DW -1 + DW OPPRND + DW 2 + DW 24 + DW -1 + DW OPPRNH + DW 31 + DW 33 + DW -1 + DW OPPRNM + DW 34 + DW 39 + +;80 COLUMN, SCORE +SLS80 DB 51 DUP(32),"Score:",8 DUP(32),"Moves:",9 DUP(32),0,80H +SLS80T DW -1 + DW OPPRND + DW 2 + DW 27 + DW -1 + DW OPPRNN + DW 58 + DW 61 + DW -1 + DW OPPRNN + DW 73 + DW 78 + +;80 COLUMN, TIME +SLT80 DB 60 DUP(32),"Time:",15 DUP(32),0,80H +SLT80T DW -1 + DW OPPRND + DW 2 + DW 27 + DW -1 + DW OPPRNH + DW 69 + DW 71 + DW -1 + DW OPPRNM + DW 72 + DW 77 + + ;REBOOT AT END OF GAME +REBOOT DB " ** End of session **",0 +REBOO1 DB "Strike any key to reboot",0 + + ;VERIFY/INTERPRETER VERSION + +INTMSG DB "IBM-PC Interpreter Version " +INTVER DB "D",80H + + ;SAVE/RESTORE +NDISKS DB 2 +FUCK DB 0 + +SRTXT0 DB "Type backspace to abort",80H +SRTXT1 DB "Disk drive (A-D) (default = " +SRDRV DB "B" + DB "):",80H +SRTXT2 DB "Position (0-9) (default = " +SRPOS DB "0" + DB "):",80H +SRTXT3 DB "Insert SAVE disk, then hit a key:",80H +SRTXT4 DB "Insert game disk, then hit a key:",80H + + ;GTBLKS +DSKMOD DB 0 ;0 FOR GAME READ, 1 FOR SAVE/RESTORE +DSKDRV DB 0 ;CURRENT DRIVE +DSKDIR DB 0 ;0 FOR READ, 1 FOR WRITE +GTBCNT DW 0 ;REMAINING BLOCKS TO BE READ +GTBSTT DW 0 ;STARTING BLOCK +GTBCOR DW 0 ;STARTING CORE ADDRESS + ;OPRAND +RSEED1 DW ? ;SEED FOR RANDOM NUMBERS +RSEED2 DW ? ;SEED TWO +RTEMP DW ? ;TEMP FOR RANDOM ROUTINES + ;READ +RDWSTR DW 4 DUP(0) ;WORD STRING BUFFER FOR ZWORD +RDBOS DW 0 ;BEGINNING OF STRING POINTER +RDEOS DW 0 ;END OF STRING POINTER +RDRET DW 0 ;RETURN TABLE POINTER +RDNWDS DB 0 ;NUMBER OF WORDS READ + ;PUTSTR +WRDOFF DW 0 ;OFFSET INTO WORD TABLE FOR CURRENT SET + ;PUTCHR +CHRPTR DW 0 ;POINTS TO NEXT CHARACTER POSITION +ENDBUF DW 0 ;POINTS JUST PAST END OF OUTPUT BUFFER (0) + ;GETNUM +STATUS DW 0 ;STATUS-LINE-REQUESTED FLAG + ;ZIPBGN +IRBRKS DB " ",9,13,12,".,?",0 ;INITIAL SET OF READ BREAK CHARS +TWIDTH DW 0 ;TERMINAL WIDTH +RWIDTH DW 0 ;REAL TERMINAL WIDTH +SCRN0 DB 1 ;START OF SCROLLING SCREEN +CURSCR DB 0 ;CURRENT SCREEN +LFTMAR DB 1 ;LEFT MARGIN DEFAULT = 1 (2 FOR 80-COLUMN) +MEMTOP DW 0 ;LAST AVAILABLE LOCATION +TIMEMD DW 0 ;TIME(VERSUS SCORE)-MODE-FOR-STATUS-LINE FLAG +ZORKID DW 0 ;UNIQUE GAME & VERSION IDENTIFIER +ENDLOD DW 0 ;ENDLOD BLOCK NUMBER +VOCTAB DW 0 ;SAVE VOCABULARY TABLE POINTER +OBJTAB DW 0 ;OBJECT TABLE POINTER +GLOTAB DW 0 ;GLOBAL TABLE POINTER +WRDTAB DW 0 ;WORD TABLE POINTER +PURBOT DW 0 ;PURE CODE POINTER +ESIBKS DW 0 ;END OF SELF-INSERTING BREAK CHARACTERS +VWLEN DW 0 ;NUMBER OF BYTES IN A VOCABULARY WORD ENTRY +VWORDS DW 0 ;NUMBER OF WORD ENTRIES IN VOCABULARY +VOCBEG DW 0 ;BEGINNING OF ACTUAL VOCABULARY +BKBUF DB 512 DUP(?) ;SCRATCH BUFFER FOR BACKUP +OUTBUF DB 81 DUP(?) ;OUTPUT BUFFER +RBRKS DB 32 DUP(?) ;STRING OF READ BREAK CHARACTERS +PAGTAB DB 64 DUP(254,0,0,0) ;PAGE INFORMATION TABLE + DB 255 +PAGES DW 0 ;SWAPPING AREA +BUFPGS DW 0 +CHRFLG DB 0 + +INIFLG DB 0 +INIWID EQU 1 +INIMEM EQU 2 +INIRND EQU 4 + + ;RESTRT +ZLOCS DW 0 ;POINTER TO LOCALS +ZPC1 DW 0 ;ZPC BLOCK-POINTER +ZPC2 DW 0 ;ZPC BYTE-POINTER +ARGBLK DW 4 DUP(?) ;ARGUMENT BLOCK FOR EXTENDED OPERATIONS + ;NEWZPC +CURPAG DW 0 ;CURRENT PAGE (WHERE ZPC IS) POINTER +CURBLK DW 0 ;CURRENT BLOCK, USUALLY SAME AS ZPC1 +CURTAB DW 0 ;CURRENT PAGE TABLE POINTER +1 + ;GETPAG +RTIME1 DB 0 ;REFERENCE TIME, 1 1/2 WORDS USED +RTIME2 DW 0 +LPAGE DW 0 ;LAST REFERENCED PAGE NUMBER +LPLOC DW 0 ;AND ITS CORE LOCATION +LPTAB DW 0 ;AND ITS TABLE POINTER + + + ;BACKUP COPY STUFF +SECCNT DB 0 +TRKCNT DB 3 +BKDSK DB 0 ;DRIVE TO BACKUP ONTO +BKFRST DB 1 + +BKASK1 DB "You may make one backup copy of your",0H +BKASK2 DB "game. To do so you need a formatted",0H +BKASK3 DB "COPY disk. Also, neither MASTER",0H +BKASK4 DB "nor COPY disk may be write-protected.",0H +BKASK5 DB "Make COPY now? (Y/N) ",80H +BKYEP DB "[YES]",80H +BKNOPE DB "[NO]",80H +BKMC1 DB "Insert MASTER disk in drive A",0H +BKMC2 DB "Insert COPY disk in drive B",0H +BKMC3 DB "Hit any key to start backup",80H +BKMAST DB "Insert MASTER disk; hit any key",80H +BKCOPY DB "Insert COPY disk; hit any key",80H +BKWPRT DB "Disk write-protected; hit any key",80H +BKNRDY DB "Disk error; hit any key",80H +BKDONE DB "Backup completed.",0H +BKFAIL DB "Disk error; backup aborted.",0H +BKWPS1 DB "Please write-protect the disk in",0H +BKWPS2 DB "drive A; hit any key",80H +DSK_SV1 DW 0 +DSK_SV2 DW 0 + +DSK_PRM DB 11001111B + DB 2 + DB 37 + DB 3 + DB 4 + DB 02AH + DB 0FFH + DB 050H + DB 0F6H + DB 25 + DB 4 + +IDTBL DB 1,0,1,3 + DB 1,0,2,3 + DB 1,0,3,3 + DB 1,0,4,3 + + ;OPERATION TABLES: + ;ZERO ARGUMENT OPERATIONS +ZEROOP DW OPRTRU ;176 + DW OPRFAL ;177 + DW OPPRNI ;178 + DW OPPRNR ;179 + DW OPNOOP ;180 + DW OPSAVE ;181 + DW OPREST ;182 + DW OPRSTT ;183 + DW OPRSTA ;184 + DW OPFSTA ;185 + DW OPQUIT ;186 + DW OPCRLF ;187 + DW OPUSL ;188 + DW OPVERI ;189 + DW 0 ;190 + DW 0 ;191 + ;ONE ARGUMENT OPERATIONS +ONEOP DW OPQZER ;128 + DW OPQNEX ;129 + DW OPQFIR ;130 + DW OPLOC ;131 + DW OPPTSI ;132 + DW OPINC ;133 + DW OPDEC ;134 + DW OPPRNB ;135 + DW 0 ;136 + DW OPREMO ;137 + DW OPPRND ;138 + DW OPRETU ;139 + DW OPJUMP ;140 + DW OPPRIN ;141 + DW OPVALU ;142 + DW OPBCOM ;143 + ;TWO ARGUMENT AND EXTENDED ARGUMENT OPERATIONS +EXTOP DW 0 ;0 + DW OPQEQU ;1 + DW OPQLES ;2 + DW OPQGRT ;3 + DW OPQDLE ;4 + DW OPQIGR ;5 + DW OPQIN ;6 + DW OPBTST ;7 + DW OPBOR ;8 + DW OPBAND ;9 + DW OPQFSE ;10 + DW OPFSET ;11 + DW OPFCLE ;12 + DW OPSET ;13 + DW OPMOVE ;14 + DW OPGET ;15 + DW OPGETB ;16 + DW OPGETP ;17 + DW OPGTPT ;18 + DW OPNEXT ;19 + DW OPADD ;20 + DW OPSUB ;21 + DW OPMUL ;22 + DW OPDIV ;23 + DW OPMOD ;24 + DW 0 ;25 + DW 0 ;26 + DW 0 ;27 + DW 0 ;28 + DW 0 ;29 + DW 0 ;30 + DW 0 ;31 + DW OPCALL ;224 + DW OPPUT ;225 + DW OPPUTB ;226 + DW OPPUTP ;227 + DW OPREAD ;228 + DW OPPRNC ;229 + DW OPPRNN ;230 + DW OPRAND ;231 + DW OPPUSH ;232 + DW OPPOP ;233 + DW OPSPLT ;234 + DW OPSCRN ;235 + DW 0 ;236 + DW 0 ;237 + DW 0 ;238 + DW 0 ;239 + DW 0 ;240 + DW 0 ;241 + DW 0 ;242 + DW 0 ;243 + DW 0 ;244 + DW 0 ;245 + DW 0 ;246 + DW 0 ;247 + DW 0 ;248 + DW 0 ;249 + DW 0 ;250 + DW 0 ;251 + DW 0 ;252 + DW 0 ;253 + DW 0 ;254 + DW 0 ;255 + ;.CRLF +MORE DB "**MORE** ",80H +MORLIN DW 0 +LINMAX DW 23 +LINMXX EQU 23 + + ;.GETTM +TIME DD ? + + ;STRUCTURE AND RECORD DEFINITIONS: + ;OBJECT OPERATIONS +OBJECT STRUC +FLAGS1 DW ? +FLAGS2 DW ? +PARENT DB ? +SIBLING DB ? +CHILD1 DB ? +PROPS DW ? +OBJECT ENDS +PROPID RECORD PROPSIZE:3,PROPNUM:5 + + ;STRING DEFINITIONS + + ;READ +ERR2 DB "Too many words typed, flushing: ",80H + + ;OPNEXT/OPPUTP +FTL2 DB "No such property",0 + ;ZIPBGN +FTL4 DB "Wrong game or version",0 + ;NXTINS +FTL5 DB "Illegal operation",0 + ;FINDPG +FTL6 DB "No free pages",0 + ;GTBLKS +FTL7 DB "Game file read error",0 + ;Fatal error header +FATHDR DB "Fatal error: ",80H + ;ZSTR CHARACTER CONVERSION VECTOR + +ZCHRS DB "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + DB " 0123456789.,!?_#'" + DB '"/\-:()' +DATA_SG ENDS + + SUBTTL MACROS + PAGE + + +GTAWRD MACRO D,S ;;GET ABSOLUTE WORD + MOV D&X,ES:&S + XCHG D&H,D&L + ENDM + +PTAWRD MACRO D,S ;;PUT ABSOLUTE WORK + XCHG S&H,S&L + MOV ES:&D,S&X + ENDM + +MOVM MACRO D,S,R ;;MOVE MEMORY TO MEMORY + MOV R,S + MOV D,R + ENDM + +PUSHZ MACRO S ;;PUSH ONTO Z STACK + XCHG SP,DI + PUSH S + XCHG SP,DI + ENDM + +POPZ MACRO D ;;POP FROM Z STACK + XCHG SP,DI + POP D + XCHG SP,DI + ENDM + +POPZT MACRO D ;;GET TOP OF Z STACK + MOV D,SS:[DI] + ENDM + +PUSHZT MACRO S ;;PUT TOP OF Z STACK + MOV SS:[DI],S + ENDM + +PRINT MACRO STR ;;PRINT A STRING, POINTER IS ARGUMENT + PUSH AX + MOV AX,OFFSET STR + CALL .PRINT + POP AX + ENDM + +FATAL MACRO ERR ;;PRINT FATAL ERROR AND DIE + CALL .CRLF + MOV AX,OFFSET FATHDR + CALL .PRINT + MOV AX,OFFSET ERR + CALL .PRINT + JMP FINISH + ENDM + +CURGET MACRO + PUSH AX + SUB BH,BH + MOV AH,3 + INT 10H + POP AX + ENDM + +CURSET MACRO POS + PUSH AX + SUB BH,BH + MOV AH,2 +IFNB + MOV DX,POS +ENDIF + INT 10H + POP AX + ENDM + + SUBTTL SYSTEM INITIALIZATION + PAGE + + +CODE_SG SEGMENT PARA +ASSUME CS:CODE_SG,DS:DATA_SG,ES:GAME_SG,SS:STK_SG + +START PROC FAR + +;NEVER, EVEN FOR AN INSTANT, CONSIDER CHANGING THESE NEXT INSTRUCTIONS +;THE GAME CREATOR MODIFIES THEM AND THEY MUST REMAIN HERE + + MOVM DS,DATA_SG,AX + MOVM ES,GAME_SG,AX + MOVM SS,STK_SG,AX + +;END OF MAGIC SECTION. HACK AND SLASH TO YOUR HEART'S CONTENT + + MOV SP,OFFSET STK_TOP + MOV DI,OFFSET ZSTK_TP + JMP ZIPBGN ;JUMP TO BEGINNING OF ZIP CODE +START ENDP + +FEEP PROC + MOV AX,7 + CALL .TTYOUT ;BELL + RET +FEEP ENDP + +OPVERI PROC + PRINT INTMSG + CALL .CRLF + MOV AX,ES:[PLENTH] + XCHG AH,AL + PUSH SI + PUSH DI + PUSH ENDLOD + CALL BSPLIT + MOV SI,AX + MOV DI,BX + MOV AX,0 + MOV BX,64 + MOV DX,0 + MOV ENDLOD,0 +OPVR1: PUSH SI + PUSH DI + PUSH DX + CALL GETBYT + POP DX + POP DI + POP SI + ADD DX,CX + CMP BX,0 + JNZ OPVX + NOP +OPVX: CMP AX,SI + JNE OPVR1 + CMP BX,DI + JNE OPVR1 + MOV AX,ES:[PCHKSM] + XCHG AH,AL + POP ENDLOD + POP DI + POP SI + CMP AX,DX + JE OPVR2 + JMP PFALSE +OPVR2: JMP PTRUE +OPVERI ENDP + +OPREST PROC + MOV DSKDIR,0 ;INDICATE RESTORE + JMP OSV0$ +OPREST ENDP + +OPSAVE PROC + MOV DSKDIR,1 ;INDICATE WRITE +OSV0$: PRINT SRTXT0 ;WRITE "TYPE BACKSPACE..." + CALL .CRLF + PRINT SRTXT2 ;WRITE "POSITION (DEFAULT = X): " +OSV2A$: CALL .CHRIN + CMP AL,13 + JNE OSV3$ + MOV AL,SRPOS ;GET DEFAULT POSITION +OSV3$: MOV BL,AL + CMP AL,8 + JNE OSV3X$ + CALL .CRLF + JMP PFALSE +OSV3X$: SUB AL,"0" + CMP AL,9 + JG OSV3A$ + CMP AL,0 + JGE OSV3B$ +OSV3A$: CALL FEEP + JMP OSV2A$ +OSV3B$: MOV SRPOS,BL + MOV AL,BL + MOV AH,NRMATR + CALL .TTYOUT + CALL .CRLF + PRINT SRTXT1 ;WRITE "DRIVE (DEFAULT = X): " +OSV0A$: CALL .CHRIN + CMP AL,13 + JNE OSV1$ + MOV AL,SRDRV ;GET DEFAULT DRIVE +OSV1$: CMP AL,8 + JNE OSAB1$ + CALL .CRLF + JMP PFALSE +OSAB1$: CMP AL,"a" + JL OSAB2$ + SUB AL,32 ;UPPERCASE DRIVE LETTERS +OSAB2$: MOV BL,AL + SUB AL,"A" ;GET DOWN TO BASICS + CMP AL,3 + JG OSV1A$ ;LOSING DRIVE NUMBER + CMP AL,0 + JGE OSV1B$ +OSV1A$: CALL FEEP ;EXPRESS DISPLEASURE + JMP OSV0A$ +OSV1B$: MOV SRDRV,BL + MOV AL,BL + MOV AH,NRMATR + CALL .TTYOUT ;ECHO THE DRIVE LETTER + CALL .CRLF + PRINT SRTXT3 ;WRITE "Insert save disk..." + CALL .CHRIN + CMP AL,8 ;ABORT REQUESTED? + JNE OSV3Z$ + CALL .CRLF + JMP PFALSE +OSV3Z$: MOV AL,SRPOS ;GET POSITION + SUB AL,"0" + SUB AH,AH + MOV BL,SRDRV + SUB BL,"A" + MOV DSKDRV,BL + XCHG DI,SP + PUSH ZPC1 + PUSH ZPC2 + PUSH ZLOCS + PUSH ZORKID + MOV STKBOT,SP ;SAVE THE WORLD + MOV SP,DI + MOV CL,5 + SHL AX,CL ;CHANGE TO BLOCK + PUSH AX ;SAVE STARTING BLOCK # + PUSH ES ;SAVE ES + MOV DX,SS + MOV ES,DX ;FAKE ES TO BE STACK SEGMENT + MOV BX,OFFSET STKBOT + MOV CX,1 + CALL SRBLKS ;READ/WRITE STACK + PUSHF + MOV DI,SP ;SAVE SP + MOV SP,STKBOT ;RETRIEVE SAVED USER STACK POINTER + POP AX + CMP AX,ZORKID ;CHECK GAME VERSIONS + JE OSVT0$ + FATAL FTL4 +OSVT0$: POP ZLOCS + POP ZPC2 + POP ZPC1 + XCHG DI,SP + POPF + POP ES + POP AX + JC OSV4$ ;DIE HERE IF FIRST READ/WRITE FAILED + INC AX ;NEXT BLOCK STARTS + SUB BX,BX ;START AT ES:0 + MOV CX,PURBOT ;NUMBER OF PURE BLOCKS + CALL SRBLKS + PUSHF ;SAVE FLAGS FROM CALL + CALL .CRLF + CMP DSKDRV,0 ;CHECK FOR DRIVE 0 + JNZ OSV3C$ + PRINT SRTXT4 ;WRITE "Insert game disk..." + CALL .CHRIN ;WAIT UNTIL READY + CALL .CRLF +OSV3C$: CALL NEWZPC ;PAGE MAY HAVE CHANGED, LOSER! + POPF ;GET FLAGS BACK + JC OSV4$ + MOV AL,SCRFLG ;GET CURRENT SCRIPT STATE + PTAWRD [PFLAGS],A ;AND MAKE RESTORED FLAGS REFLECT IT + JMP PTRUE +OSV4$: CALL .CRLF + JMP PFALSE +OPSAVE ENDP + +OPRSTT PROC + MOV BP,CHRPTR + MOV BYTE PTR DS:[BP],0 ;FORCE OUT THE BUFFER + PRINT OUTBUF + JMP RESTRT ;JUMP TO RESTART ADDRESS +OPRSTT ENDP + +OPQUIT PROC + JMP FINISH +OPQUIT ENDP + +OPSCRN PROC + SUB AH,AH ; ONLY HAVE LOWER BYTE + MOV CURSCR,AL ; put screen # into current screen + CMP AX,0 ; was it 0 + JNE OPSCR1 ; no then test #1 + MOV DX,OLDCUR ; save old cursor position + CMP COLFLG,0 ; TEST IF COLOR ON + JZ DIP1 + MOV NRMATR,17H ; give them color + JMP OPSCR2 +DIP1: MOV NRMATR,07H ; GIVE THEN NOTHING + JMP OPSCR2 + +OPSCR1: CMP AX,1 ; was it 1 + JNE OPSCR3 + CURGET + MOV OLDCUR,DX ; no then ignore + CMP COLFLG,0 ; TEST IF COLOR ON + JZ DIP3 + MOV NRMATR,75H ; give them color + JMP DIP4 + +DIP3: MOV NRMATR,07H ; GIVE THEM NOTHING +DIP4: MOV DH,1 ; put it at 1,1 + MOV DL,LFTMAR ; UPPER LEFT-HAND CORNER +OPSCR2: MOV AH,2 ; set cursor + MOV BH,0 ; graphics page + INT 10H +OPSCR3: RET +OPSCRN ENDP + +OPSPLT PROC + CMP AX,0 ; split zero + JE OPSPLU + CURGET + MOV OLDCUR,DX + SUB LINMAX,AX ; subtract max plus one + ADD AX,1 + MOV SCRN0,AL ; USED IN SCROLL FOR CRLF + MOV CL,LFTMAR + MOV CH,01 ; UPPER LEFT CORNER + MOV DX,RWIDTH ; LOWER RIGHT ROW + SUB DL,LFTMAR + SUB DL,1 + MOV DH,SCRN0 ; LOWER RIGHT COLUMN + MOV AL,0 ; blank entire screen + MOV AH,6 ; clear the screen + CMP COLFLG,0 ; IS IT COLOR? + JZ DAN1 + MOV BH,2FH ; WHITE ON GREEN + JMP DAN2 +DAN1: MOV BH,07H ; IF NO COLOR THEN BLACK ON WHITE +DAN2: INT 10H ; CLEAR TOP WINDOW + MOV DX,OLDCUR ; GET BACK CURSOR POSITION + MOV AH,2 ; set cursor + SUB BH,BH ; make sure it's zero + INT 10H + RET + +OPSPLU: MOV SCRN0,1 + MOV AX,LINMXX + MOV LINMAX,AX + MOV MORLIN,0 ;RESET MORE COUNT + RET +OPSPLT ENDP + +OPUSL PROC + PUSH DI + MOV USLMOD,1 + CURGET ;GET THE CURSOR LOCATION + PUSH DX ;SAVE IT FOR A RAINY DAY + MOV AX,16 ;FIRST GLOBAL (ROOM) + MOV DI,SLTAB ;USL TABLE IN FORCE + MOV CX,3 ;NUMBER OF THINGS WE PRINT +USLLP$: PUSH AX + CALL GETVAR ;GET THE GLOBAL + CMP AX,[DI] ;HAS IT CHANGED + JE USL1$ ;THANK GOD, NO + CURSET [DI+4] ;MOVE THE CURSOR TO THE RIGHT PLACE + PUSH CX + PUSH DI + CALL WORD PTR [DI+2] ;CALL THE PROPER ROUTINE + CURGET ;WHERE IS THE CURSOR NOW? + POP DI + SUB DX,[DI+6] ;WHERE IS THE END OF THE FIELD? + NEG DX + JLE USLN$ ;DONT PRINT ZERO OR LESS SPACES + MOV AL,DL + MOV AH,USLATR ;THIS IS REVERSE VIDEO + PUSH DI + CALL .SPACE ;PRINT THAT MANY SPACES + POP DI +USLN$: ADD DI,8 ;POINT TO NEXT TABLE ENTRY + POP CX ;RESTORE REGISTERS +USL1$: POP AX + INC AX ;POINT TO NEXT GLOBAL + LOOP USLLP$ ;DO ALL THREE THEN LEAVE + POP DX + CURSET DX ;IT MAY OR MAY NOT BE RAINING, BUT.... + MOV USLMOD,0 + POP DI + RET +OPUSL ENDP + + SUBTTL ARITHMETIC OPERATIONS + PAGE + + + ;ADD +OPADD PROC + ADD AX,BX ;ADD OPR1 AND OPR2 + JMP PUTVAL ;RETURN THE VALUE +OPADD ENDP + + ;SUB +OPSUB PROC + SUB AX,BX ;SUBTRACT OPR2 FROM OPR1 + JMP PUTVAL ;RETURN THE VALUE +OPSUB ENDP + + ;MULTIPLY AX BY BX +OPMUL PROC + IMUL BX ;MULTIPLY OPR1 BY OPR2,IGNORING OVERFLOW(DX) + JMP PUTVAL ;RETURN THE VALUE +OPMUL ENDP + + ;DIVIDE AX BY BX +OPDIV PROC + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + JMP PUTVAL ;RETURN THE VALUE +OPDIV ENDP + + ;MOD +OPMOD PROC + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + MOV AX,DX ;WE WANT REMAINDER + JMP PUTVAL ;RETURN THE VALUE +OPMOD ENDP + + ;RANDOM +OPRAND PROC + SUB AH,AH + MOV RTEMP,AX + MOV AX,RSEED1 + MOV BX,RSEED2 + MOV RSEED2,AX + CLC + RCR AX,1 + RCR BX,1 + XOR RSEED1,BX + MOV AX,RSEED1 + AND AX,0EFFFH + SUB DX,DX + DIV RTEMP + MOV AX,DX + INC AX ;MUST BE BETWEEN 1 AND N, INCLUSIVE + TEST INIFLG,INIRND + JNZ OPRN1$ + JMP PUTVAL ;SIMPLY RETURN +OPRN1$: PUSH AX + CALL OPPRNN ;PRINT NUMBER + MOV AL,32 + CALL PUTCHR + POP AX + JMP PUTVAL ;RETURN THE VALUE +OPRAND ENDP + + ;LESS? +OPQLES PROC + CMP AX,BX ;IS OPR1 LESS THAN OPR2? + JL JPT ;YES, PREDICATE TRUE +JPF: JMP PFALSE ;NO, PREDICATE FALSE +JPT: JMP PTRUE +OPQLES ENDP + + ;GRTR? +OPQGRT PROC + CMP AX,BX ;IS OPR1 GREATER THAN OPR2? + JG JPT ;YES, PREDICATE TRUE + JMP JPF ;NO, PREDICATE FALSE +OPQGRT ENDP + + SUBTTL LOGICAL OPERATIONS + PAGE + + + ;BTST +OPBTST PROC + NOT AX ;TURN OFF BITS IN OPR2 THAT ARE ON IN OPR1 + AND BX,AX + JE JPT ;SUCCESS IF OPR2 COMPLETELY CLEARED + JMP JPF +OPBTST ENDP + + ;BOR +OPBOR PROC + OR AX,BX ;LOGICAL OR + JMP PUTVAL ;RETURN THE VALUE +OPBOR ENDP + + ;BCOM +OPBCOM PROC + NOT AX ;LOGICAL COMPLEMENT + JMP PUTVAL ;RETURN THE VALUE +OPBCOM ENDP + + ;BAND +OPBAND PROC + AND AX,BX ;LOGICAL AND + JMP PUTVAL ;RETURN THE VALUE +OPBAND ENDP + + SUBTTL GENERAL PREDICATES + PAGE + + + ;EQUAL? +OPQEQU PROC + NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV BX,ARGBLK ;GET OPR1 + CMP BX,ARGBLK[2] ;IS OPR1 EQUAL TO OPR2? + JE OQE1$ ;YES + CMP AX,3 ;NO, IS THERE A THIRD OPERAND? + JL OQE2$ ;NO + CMP BX,ARGBLK[4] ;YES, IS IT EQUAL TO OPR1? + JE OQE1$ ;YES + CMP AX,4 ;NO, IS THERE A FOURTH? + JL OQE2$ ;NO + CMP BX,ARGBLK[6] ;YES, IS IT EQUAL TO OPR1? + JNE OQE2$ ;NO +OQE1$: JMP PTRUE ;PREDICATE TRUE IF EQUAL +OQE2$: JMP PFALSE ;PREDICATE FALSE IF NOT +OPQEQU ENDP + + ;ZERO? +OPQZER PROC + CMP AX,0 ;IS OPR ZERO? + JNE OQZ1$ ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQZ1$: JMP PFALSE +OPQZER ENDP + + SUBTTL OBJECT OPERATIONS + PAGE + + + ;MOVE (OBJ1 INTO OBJ2) +OPMOVE PROC + PUSH AX ;PROTECT OPRS FROM REMOVE CALL + PUSH BX + CALL OPREMO ;REMOVE OBJ1 FROM WHEREVER IT IS + POP DX ;OBJ2 + MOV AX,DX + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + POP CX ;OBJ1 + MOV AX,CX + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV ES:[BP].PARENT,DL ;PUT OBJ2 INTO OBJ1'S LOC SLOT + MOV DH,ES:[BX].CHILD1 ;GET CONTENTS OF OBJ2'S FIRST SLOT + MOV ES:[BX].CHILD1,CL ;MAKE OBJ1 FIRST CONTENT OF OBJ2 + CMP DH,0 ;WERE THERE ANY OTHER CONTENTS? + JE OMV1$ ;NO + MOV ES:[BP].SIBLING,DH ;YES, CHAIN ONTO OBJ1'S SIBLING SLOT +OMV1$: RET +OPMOVE ENDP + + ;REMOVE (OBJ FROM ITS PARENT) +OPREMO PROC + MOV CX,AX ;SAVE OBJ FOR LATER + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + MOV CH,ES:[BX].PARENT ;GET ITS PARENT + CMP CH,0 ;DOES IT HAVE A PARENT? + JE ORM3$ ;IF NOT, WE'RE DONE + MOV AL,CH ;PARENT + CALL OBJLOC ;FIND PARENT'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:[BP].CHILD1 ;GET PARENT'S FIRST CONTENT + CMP DL,CL ;IS IT OBJ? + JNE ORM1$ ;NO + MOVM ES:[BP].CHILD1,ES:[BX].SIBLING,AL ;YES, CHANGE SLOT TO + ;OBJ'S SIBLING + JMP ORM2$ ;AND RETURN +ORM1$: MOV AL,DL ;CURRENT SIBLING + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:[BP].SIBLING ;GET NEXT SIBLING IN CHAIN + CMP DL,CL ;IS IT OBJ? + JNE ORM1$ ;NO, CONTINUE LOOP + MOVM ES:[BP].SIBLING,ES:[BX].SIBLING,AL ;YES, CHANGE IT TO + ;OBJ'S SIBLING +ORM2$: MOV ES:[BX].PARENT,0 ;OBJ NOW HAS NO PARENT + MOV ES:[BX].SIBLING,0 ;OR SIBLING +ORM3$: RET +OPREMO ENDP + + ;FSET? (IS FLAG SET IN OBJ?) +OPQFSE PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OQF1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OQF1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + TEST AX,DX ;IS THIS BIT SET IN FLAG WORD? + JE OQF2$ ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQF2$: JMP PFALSE +OPQFSE ENDP + + ;FSET (SET A FLAG IN OBJ) +OPFSET PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFS1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFS1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + OR AX,DX ;SET THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + RET +OPFSET ENDP + + ;FCLEAR (CLEAR A FLAG IN OBJ) +OPFCLE PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFC1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFC1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,7FFFH ;SHIFT A BIT TO PROPER POSITION + ROR DX,CL + AND AX,DX ;CLEAR THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + RET +OPFCLE ENDP + + ;LOC (RETURN CONTAINER OF OBJ) +OPLOC PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].PARENT ;GET LOC SLOT + JMP BYTVAL ;RETURN THE BYTE VALUE +OPLOC ENDP + + ;FIRST? (RETURN FIRST SLOT OF OBJ, FAIL IF NONE) +OPQFIR PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].CHILD1 ;GET FIRST SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE +JPT1: JMP PTRUE ;NO, PREDICATE TRUE +JPF1: JMP PFALSE +OPQFIR ENDP + + ;NEXT? (RETURN THE NEXT (SIBLING) SLOT OF OBJ, FAIL IF NONE) +OPQNEX PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].SIBLING ;GET SIBLING SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE + JMP JPT1 ;NO, PREDICATE TRUE +OPQNEX ENDP + + ;IN? (IS OBJ1 CONTAINED IN OBJ2?) +OPQIN PROC + CALL OBJLOC ;FIND OBJ1'S LOCATION + XCHG AX,BX ;MOVE TO BASE + CMP ES:[BX].PARENT,AL ;IS OBJ1'S PARENT OBJ2? + JE JPT1 ;YES, PREDICATE TRUE + JMP JPF1 ;NO, PREDICATE FALSE +OPQIN ENDP + + ;GETP (GET SPECIFIED PROPERTY OF OBJ, DEFAULT IF NONE) +OPGETP PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGP2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JL OGP3$ ;IF LESS, NO SUCH PROPERTY HERE + MOV AL,ES:[BX] ;GOT IT, NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,MASK PROPSIZE;GET LENGTH BITS + MOV CL,PROPSIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + JNE OGP5$ ;NO + MOV AL,ES:[BX] ;GET THE BYTE + JMP BYTVAL ;AND RETURN IT +OGP3$: DEC DX ;POINT INTO DEFAULT PROPERTY TABLE + SHL DX,1 + MOV BX,DX +OGP4$: ADD BX,OBJTAB ;GET THE WORD +OGP5$: GTAWRD A,[BX] + JMP PUTVAL ;AND RETURN IT +OPGETP ENDP + + ;PUTP (CHANGE VALUE OF A PROPERTY, ERROR IF BAD NUMBER) +OPPUTP PROC + PUSH CX ;SAVE NEW VALUE + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OPP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OPP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OPP2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE OPP3$ ;IF EQUAL, GOT IT + JG OPP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR +OPP3$: MOV AL,ES:[BX] ;NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,MASK PROPSIZE;GET LENGTH BITS + MOV CL,PROPSIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + POP AX ;RESTORE NEW VALUE + JNE OPP4$ ;ZERO MEANS BYTE VALUE + MOV ES:[BX],AL ;STORE THE NEW BYTE + RET ;AND RETURN +OPP4$: PTAWRD [BX],A ;STORE THE NEW WORD VALUE + RET +OPPUTP ENDP + + ;NEXTP (RETURN NUMBER OF NEXT PROP FOLLOWING GIVEN PROB IN OBJ) +OPNEXT PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET ITS LOCATION + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + CMP DX,0 ;WERE WE GIVEN ZERO AS PROP? + JE ONX4$ ;YES, GO RETURN FIRST PROPERTY NUMBER + JMP ONX2$ ;NO, SKIP NEXT LINE FIRST TIME THROUGH LOOP +ONX1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE ONX3$ ;IF EQUAL, GOT IT + JG ONX1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR +ONX3$: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX4$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;EXTRACT PROPERTY NUMBER + JMP PUTVAL ;AND RETURN IT +OPNEXT ENDP + + SUBTTL TABLE OPERATIONS + PAGE + + + ;GET (GET THE ITEM'TH WORD FROM TABLE) +OPGET PROC + SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETWRD ;GET THE WORD + MOV AX,CX + JMP PUTVAL ;AND RETURN IT +OPGET ENDP + + ;GETB (GET THE ITEM'TH BYTE FROM TABLE) +OPGETB PROC + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETBYT ;GET THE BYTE + MOV AX,CX + JMP BYTVAL ;AND RETURN IT +OPGETB ENDP + + ;PUT (REPLACE THE ITEM'TH WORD IN TABLE) +OPPUT PROC + SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD BX,AX ;INDEX INTO TABLE + PTAWRD [BX],C ;STORE THE WORD + RET +OPPUT ENDP + + ;PUTB (REPLACE ITEM'TH BYTE IN TABLE) +OPPUTB PROC + ADD BX,AX ;INDEX INTO TABLE + MOV ES:[BX],CL ;STORE BYTE + RET +OPPUTB ENDP + + ;GETPT (GET POINTER TO PROPERTY TABLE FOR GIVEN PROP) +OPGTPT PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGT2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGT1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGT2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGT1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JE OGT3$ ;FOUND THE PROPERTY + SUB AX,AX ;RETURN ZERO FOR NO SUCH PROPERTY + JMP OGT4$ +OGT3$: INC BX ;POINT TO PROPERTY VALUE + MOV AX,BX ;AND RETURN IT +OGT4$: JMP PUTVAL +OPGTPT ENDP + + ;PTSIZE (RETURN SIZE OF PROPERTY TABLE) +OPPTSI PROC + MOV BX,AX ;TABLE POINTER + MOV AL,ES:[BX-1] ;GET PROPERTY INDENTIFIER + AND AL,MASK PROPSIZE;EXTRACT LENGTH BITS + SUB AH,AH + MOV CL,PROPSIZE + SHR AX,CL + INC AX ;ADJUST TO ACTUAL LENGTH + JMP PUTVAL ;RETURN IT +OPPTSI ENDP + + SUBTTL VARIABLE OPERATIONS + PAGE + + + ;VALUE (GET VALUE OF VAR) +OPVALU PROC + CALL GETVAR ;GET THE VALUE + JMP PUTVAL ;AND RETURN IT +OPVALU ENDP + + ;SET (VAR TO VALUE) +OPSET PROC + JMP PUTVAR ;STORE THE VALUE +OPSET ENDP + + ;PUSH (A VALUE ONTO THE STACK) +OPPUSH PROC + PUSHZ AX ;PUSH THE VALUE + RET +OPPUSH ENDP + + ;POP (A VALUE OFF THE STACK INTO VAR) +OPPOP PROC + POPZ BX ;POP A VALUE + JMP PUTVAR ;AND STORE IT +OPPOP ENDP + + ;INC (INCREMENT VAR) +OPINC PROC + MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT +OPINC1: MOV BX,AX ;VALUE + MOV AX,CX ;VARIABLE + JMP PUTVAR ;STORE NEW VALUE +OPINC ENDP + + ;DEC (DECREMENT VAR) +OPDEC PROC + MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + JMP OPINC1 ;STORE NEW VALUE +OPDEC ENDP + + ;IGRTR? (INCREMENT VAR & TEST IF GREATER THAN VAL) +OPQIGR PROC + PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE GREATER THAN VAL? + JLE OPQIG1 ;NO +OPQIG0: INC CX ;YES, CHANGE FLAG TO TRUE +OPQIG1: MOV BX,AX ;VALUE + POP AX ;RESTORE VARIABLE + CALL PUTVAR ;STORE NEW VALUE + CMP CX,0 ;TEST FLAG + JE OQI1$ ;FALSE, PREDICATE FALSE + JMP PTRUE ;ELSE, PREDICATE TRUE +OQI1$: JMP PFALSE +OPQIGR ENDP + + ;DLESS? (DECREMENT VAR & TEST IF LESS THAN VAL) +OPQDLE PROC + PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE LESS THAN VAL? + JGE OPQIG1 ;NO, PREDICATE FALSE + JMP OPQIG0 ;YES, PREDICATE TRUE +OPQDLE ENDP + + SUBTTL I/O OPERATIONS + PAGE + + +EOLCHR EQU 10 ;LINE-FEED IS END-OF-LINE CHARACTER + +GETLIN PROC + PUSH BX + MOV AL,SCRFLG + PUSH AX + MOV SCRFLG,0 ;DEFEAT SCRIPTING DURING INPUT + MOV DX,SI ;HOLD ON TO STA + MOV CL,ES:[SI] + SUB CH,CH ;CX HAS MAX # CHARACTERS TO READ + INC SI ;SI HAS POINTER TO LINE BUFFER +GTLL$: CALL .CHRIN ;GET A CHARACTER + CMP AL,EOLCHR ;IS IT END OF LINE? + JE GTLX$ + CMP AL,13 + JNE GTL0$ +GTLX$: CALL .CRLF + POP AX + MOV SCRFLG,AL ;RESET SCRIPT FLAG + POP BX + RET ;OUR WORK IS DONE +GTL0$: CMP AL,8 ;WAS IT A BACKSPACE + JNE GTL1$ + MOV AX,SI + SUB AL,1 + CMP DX,AX ;ARE WE AT BEGINNING OF BUFFER? + JNE GTL2$ +GTLF$: MOV AX,7 + CALL .TTYOUT ;FEEP AT HIM NOW + JMP GTLL$ +GTLL1$: DEC SI ;MOVE BUFFER AND COUNT BACK (OR FORWARD) + INC CX + JMP GTLL$ +GTL2$: PUSH DX + PUSH CX + CURGET ;READ THE CURSOR (DH = ROW, DL = COLUMN) + POP CX + CMP DL,LFTMAR ;ARE WE AT BEGINNING OF A LINE? + JNE GTL3$ + SUB DH,1 ;PREVIOUS LINE + MOV AX,TWIDTH + MOV DL,AL ;END OF LINE +GTL3$: SUB DL,1 ;CURSET/GET ARE ZERO BASED + CURSET ;MOVE IT THERE + MOV AL,1 + MOV AH,NRMATR ;NO ATTRIBUTES, ONE SPACE + CALL .SPACE ;WRITE THE SPACE + POP DX + JMP GTLL1$ ;LOOP BACK + +GTL1$: JCXZ GTLF$ ;BUFFER FULL + MOV AH,TYPATR + CALL .TTYOUT ;ECHO THE CHARACTER + PUSH AX + PUSH DX + PUSH CX + CURGET ;FIND THE CURSOR + POP CX + MOV AX,TWIDTH + CMP DL,AL ;CHECK IF AT END OF LINE + JNZ GTL5$ + CALL .CRLF ;MAKE A NICE CRLF AT END OF LINE +GTL5$: POP DX + POP AX +GTL4$: CMP AL,"A" ; CHECK UPPER CASE RANGE A-Z + JL GTLD$ + CMP AL,"Z" + JG GTLD$ + ADD AL,20H ;ADJUST FOR LOWER CASE +GTLD$: MOV ES:[SI],AL ; *** THIS PUTS CHAR. IN BUFFER *** + INC SI ;MOVE POINTER, COUNT FORWARD + DEC CL + JMP GTLL$ +GETLIN ENDP + +PRTLOS PROC + MOV AL,SCRFLG + PUSH AX + PUSH DX + MOV SCRFLG,0 ;TURN OFF SCRIPTING TO AVOID GETTING HUNG + PRINT PRNRDY +PRNL$: CALL .CHRIN + CMP AL,"A" + JE PRNA$ + CMP AL,"a" + JE PRNA$ + CMP AL,"R" + JE PRNR$ + CMP AL,"r" + JE PRNR$ + MOV AL,7 + CALL .TTYOUT + JMP PRNL$ +PRNA$: CLC +PRNEX$: PUSHF + CALL .CRLF + POPF + POP DX + POP AX + MOV SCRFLG,AL ;RESTORE SCRIPT FLAG + RET +PRNR$: STC + JMP PRNEX$ +PRTLOS ENDP + +PRTOUT PROC +PRTRT$: MOV AH,0 ;CODE FOR OUTPUT TO PRINTER PORT + MOV DX,0 + INT 17H ;FORCE IT OUT + TEST AH,1 ;ERROR TIME OUT CODE + JZ PRTO1$ ;LOST ON TIME OUT + CALL PRTLOS + JC PRTRT$ ;RETRY IF SO ORDERED + GTAWRD A,[PFLAGS] + AND AX,0FFFEH ;TURN OFF THE SCRIPT BIT + PTAWRD [PFLAGS],A + MOV SCRFLG,0 ;AND UNSET THE FLAG + STC ;INDICATE LOSER WANTS ABORT + RET +PRTO1$: CLC ;INDICATE WIN + RET +PRTOUT ENDP + +SCRCHK PROC + PUSH AX + PUSH BX + PUSH DX + GTAWRD A,[PFLAGS] + TEST AL,1 ;CHECK IF SCRIPTING IS REQUESTED + JZ SCRNN$ + CMP SCRFLG,0 ;CHECK WHETHER THIS IS A NEW STATE + JNE SCR1$ +SCRR1$: PUSH DX + MOV DX,0 ;FIRST PRINTER SLOT + MOV AH,1 + INT 17H ;INITIALIZE PORT + TEST AH,0A1H ;CHECK FOR TIME OUT,BUSY, OUT OF PAPER + JNZ SCRR2$ + POP DX + JMP SCR1$ +SCRR2$: POP DX + CALL PRTLOS ;ASK USER WHAT TO DO NOW? + JC SCRR1$ ;RETRY + GTAWRD A,[PFLAGS] + AND AX,0FFFEH ;TURN OFF THE SCRIPT BIT + PTAWRD [PFLAGS],A + MOV SCRFLG,0 ;AND FLAG +SCREX$: POP DX + POP BX + POP AX + RET +SCR1$: MOV SCRFLG,1 + SUB CX,CX ;COUNT OF CHARS PRINTED + MOV BP,DX ;START OF INPUT LINE + INC BP ;FIRST CHAR IS LENGTH OF BUFFER +SCR1L$: MOV AL,ES:[BP] + INC BP ;GET CHARACTER + CMP BP,SI ;END OF INPUT? + JLE SCR2L$ + CALL PRTCRL + JMP SCREX$ +SCR2L$: CALL PRTOUT ;OUTPUT ONE CHARACTER TO THE PRINTER + JC SCREX$ ;THIS MEANS SCRIPTING ABORTED + INC CX + CMP CX,TWIDTH + JNE SCR1L$ + CALL PRTCRL + JC SCREX$ + SUB CX,CX ;RESTART COUNT + JMP SCR1L$ ;GO FOR MORE + +SCRNN$: MOV SCRFLG,0 + JMP SCREX$ +SCRCHK ENDP + +PRTCRL PROC + MOV AL,13 ;FINISH UP WITH CRLF + CALL PRTOUT + MOV AL,10 + CALL PRTOUT + RET +PRTCRL ENDP + + ;READ (A LINE OF INPUT & PARSE IT, LINE BUF IN ES:AX, + ;RETURN BUF IN ES:BX) +OPREAD PROC + PUSH AX ;SAVE LINE BUF + PUSH AX + PUSH BX + CALL OPUSL ;UPDATE STATUS LINE + POP BX + POP AX + MOV BP,CHRPTR ;NEXT CHARACTER POSITION + MOV BYTE PTR DS:[BP],80H ;DON'T END OUTPUT, IF ANY, WITH NEW LINE +ORD1$: PRINT OUTBUF ;FORCE OUT ANY QUEUED TEXT + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP SI ;INPUT BUFFER POINTER + MOV MORLIN,0 ;RE-INITIALIZE MORE COUNT FROM HERE + CALL GETLIN ;GET SOME CHARACTERS + CALL SCRCHK ;CHECK FOR SCRIPTING, SCRIPT INPUT IF ON +ORDNS$: PUSH DI + MOV RDBOS,DX ;INITIALIZE RDBOS + MOV RDEOS,SI ;AND RDEOS + MOV RDRET,BX ;STORE RET POINTER + MOV RDNWDS,0 ;NO WORDS SO FAR + INC DX ;SKIP LENGTH BYTE + MOV DI,BX ;THIS WILL BE WORD ENTRY POINTER + INC DI ;SKIP MAX WORDS & NWORDS BYTES + INC DI +ORD8$: MOV CX,OFFSET RDWSTR;HERE FOR NEXT WORD, POINT TO WORD STRING + MOV BX,DX ;AND SAVE BEGINNING OF WORD POINTER +ORD9$: CMP DX,RDEOS ;END OF STRING? + JNE ORD10$ ;NO + CMP CX,OFFSET RDWSTR;YES, WAS A WORD FOUND? + JNE ORD15$ ;YES, WE STILL HAVE TO LOOKUP WORD + JMP ORD23$ ;NO, WE'RE DONE +ORD10$: MOV BP,DX ;GET NEXT CHARACTER FROM BUFFER + MOV AL,ES:[BP] + CMP AL,"A" + JL ORD1A$ + CMP AL,"Z" + JG ORD1A$ + ADD AL,32 ;LOWERCASIFY ALPHABETICS +ORD1A$: INC DX + MOV SI,OFFSET RBRKS ;LIST OF READ BREAK CHARACTERS +ORD11$: INC SI + CMP AL,[SI-1] ;SEARCH LIST FOR THIS ONE + JE ORD12$ ;FOUND IT + CMP BYTE PTR [SI],0 ;END OF LIST? + JNE ORD11$ ;NO, CONTINUE SEARCH + CMP CX,OFFSET RDWSTR[6] ;YES, NOT A BREAK, WORD STRING FULL? + JE ORD9$ ;YES, LOOP UNTIL END OF WORD + MOV BP,CX ;NO, TACK THIS CHARACTER ONTO STRING + MOV DS:[BP],AL + INC CX + JMP ORD9$ ;AND LOOP +ORD12$: CMP CX,OFFSET RDWSTR;WORD READ BEFORE THIS BREAK? + JNE ORD14$ ;YES + CMP SI,ESIBKS ;NO, BUT IS IT A SELF-INSERTING BREAK? + JBE ORD13$ ;YES + INC BX ;NO, UPDATE BEGINNING OF WORD TO SKIP BREAK + JMP ORD9$ ;AND RETURN TO LOOP TO FIND A WORD +ORD13$: MOV BP,CX ;STORE THE BREAK IN WORD STRING + MOV DS:[BP],AL + INC CX + JMP ORD15$ ;AND GO FOR THE WORD +ORD14$: DEC DX ;UNREAD TERMINATING BREAK IN CASE IT WAS SI +ORD15$: INC RDNWDS ;INCREMENT FOUND WORD COUNT + MOV BP,BX ;GREATER THAN MAX ALLOWED? + MOV BX,RDRET + MOV BL,ES:[BX] + CMP RDNWDS,BL + MOV BX,BP + JLE ORD16$ ;NO + PRINT ERR2 ;YES, INFORM LOSER + MOV AX,BX ;BEGINNING OF THIS WORD + MOV BP,RDEOS ;SAVE BYTE AFTER EOS + MOV BL,ES:[BP] + MOV BYTE PTR ES:[BP],0 ;ZERO IT TO MAKE STRING ASCIZ + CALL .PRINT ;PRINT IT + MOV ES:[BP],BL ;AND RESTORE OLD BYTE + DEC RDNWDS ;REMEMBER THAT WE FLUSHED THIS WORD + JMP ORD23$ ;AND WE'RE DONE +ORD16$: MOV AX,BX ;CALCULATE NUMBER OF CHARACTERS IN WORD + NEG AX + ADD AX,DX + MOV ES:[DI+2],AL ;SAVE THE NUMBER IN RET TABLE + SUB BX,RDBOS ;BYTE OFFSET FOR BEGINNING OF WORD + MOV ES:[DI+3],BL ;STORE IT, TOO + MOV BP,CX ;MAKE WORD STRING ASCIZ + MOV BYTE PTR DS:[BP],0 + MOV AX,OFFSET RDWSTR;POINT TO IT + CALL ZWORD ;AND CONVERT TO (2-WORD) ZWORD + PUSH DX ;SAVE CHAR & WORD ENTRY POINTERS + PUSH DI + MOV DI,AX ;FIRST ZWORD WORD + MOV SI,VWORDS ;NUMBER OF VOCABULARY WORDS + MOV AX,SI + DEC AX ;WE WANT TO POINT TO LAST WORD + MUL VWLEN ;MULTIPLY BY WORD LENGTH IN BYTES + ADD AX,VOCBEG ;ADD POINTER TO BEGINNING TO FIND LAST WORD + MOV CX,AX ;POINTER TO LAST WORD + MOV DX,DI ;FIRST ZWORD WORD + MOV DI,BX ;SECOND ZWORD WORD + MOV BX,VWLEN ;CALCULATE INITIAL OFFSET FOR BINARY SEARCH + SAR SI,1 +ORD17$: SAL BX,1 + SAR SI,1 + CMP SI,0 + JNE ORD17$ + MOV SI,VOCBEG ;BEGINNING OF WORD TABLE + ADD SI,BX ;ADD CURRENT OFFSET(HALF OF POWER-OF-2 TABLE) + PUSH AX ;SAVE + MOV AX,VWLEN ;AVOID FENCEPOST BUG FOR EXACT POWER-OF-2 TBL + SUB SI,AX + POP AX ;RESTORE +ORD18$: SAR BX,1 ;NEXT OFFSET WILL BE HALF OF PREVIOUS ONE + GTAWRD A,[SI] ;GET FIRST HALF OF CURRENT ZWORD + CMP DX,AX ;COMPARE DESIRED ONE TO IT + JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + MOV BP,SI ;SAME, GET SECOND HALF + INC BP + INC BP + GTAWRD A,[BP] + CMP DI,AX ;COMPARE DESIRED WORD WITH IT + JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + JMP ORD22$ ;SAME, WE'VE FOUND IT, RETURN IT +ORD19$: ADD SI,BX ;TO MOVE UP, ADD CURRENT OFFSET + CMP SI,CX ;HAVE WE MOVED PAST END OF TABLE? + JBE ORD21$ ;NO + MOV SI,CX ;YES, POINT TO END OF TABLE INSTEAD + JMP ORD21$ +ORD20$: SUB SI,BX ;TO MOVE DOWN, SIMPLY SUBTRACT OFFSET +ORD21$: CMP BX,VWLEN ;IS OFFSET RESOLUTION BELOW ONE WORD? + JGE ORD18$ ;NO, CONTINUE LOOP + SUB SI,SI ;YES, WORD NOT FOUND, RETURN ZERO +ORD22$: POP DI ;RESTORE WORD ENTRY POINTER + MOV DX,SI ;POINTER TO WORD FOUND + XCHG DH,DL + MOV ES:[DI],DX ;STORE IT + POP DX ;RESTORE CHAR POINTER + ADD DI,4 ;UPDATE POINTER FOR NEXT WORD ENTRY + JMP ORD8$ ;GO FOR IT +ORD23$: INC RDRET ;DONE, STORE NUMBER OF WORDS FOUND + MOV BP,RDRET + MOVM ES:[BP],RDNWDS,DL + POP DI ;RESTORE USER STACK POINTER + RET ;AND RETURN +OPREAD ENDP + + ;PRINTC (PRINT CHAR WHOSE ASCII VALUE IS GIVEN) +OPPRNC PROC + JMP PUTCHR ;QUEUE THE CHARACTER FOR PRINTING +OPPRNC ENDP + + ;PRINTN (PRINT A NUMBER) +OPPRNN PROC + MOV BX,AX ;NUMBER TO PRINT + CMP BX,0 + JNE OPN1$ ;NON-ZERO + MOV AX,"0" ;SPECIAL CASE ZERO + JMP PUTCHR +OPN1$: JG OPN2$ ;POSITIVE? + MOV AX,"-" ;NO, PRINT MINUS SIGN + CALL PUTCHR + NEG BX ;AND MAKE IT POSITIVE +OPN2$: SUB CX,CX ;COUNT OF DIGITS ON STACK + JMP OPN4$ ;START WITH GREATER-THAN-10 TEST +OPN3$: MOV AX,BX ;EXTRACT A DIGIT + MOV BP,10 + CWD + IDIV BP + PUSH DX ;PUSH IT + INC CX ;BUMP COUNT + MOV BX,AX ;GET QUOTIENT +OPN4$: CMP BX,10 ;MORE DIGITS TO EXTRACT? + JGE OPN3$ ;YES, GO LOOP + MOV AX,BX ;NO, GET LAST (FIRST) DIGIT + JMP OPN6$ ;ALREADY IN PLACE +OPN5$: POP AX ;POP NEXT DIGIT +OPN6$: ADD AX,"0" ;ASCIIZE IT + CALL PUTCHR ;QUEUE IT + DEC CX ;REDUCE DIGIT COUNT + JGE OPN5$ ;LOOP IF SOME LEFT + RET ;ELSE, RETURN +OPPRNN ENDP + + ;PRINT (THE STRING POINTED TO BY ES:AX) +OPPRIN PROC + CALL BSPLIT ;SPLIT THE BLOCK & WORD NUMBERS + JMP PUTSTR ;PRINT THE STRING +OPPRIN ENDP + + ;PRINTB (PRINT THE STRING POINTED TO BY THE BYTE-POINTER ES:AX) +OPPRNB PROC + CALL BSPLTB ;SPLIT THE BLOCK & BYTE NUMBERS + JMP PUTSTR ;PRINT THE STRING +OPPRNB ENDP + +;PSEUDO-INSTRUCTIONS FOR HOURS/MINUTES HERE FOR STATUS LINE +OPPRNH PROC + MOV PMFLAG,0 + CMP AL,12 + JL OPH0$ + MOV PMFLAG,1 +OPH0$: CMP AL,0 + JNE OPH00$ + MOV AL,12 +OPH00$: CMP AL,12 + JLE OPH1$ + SUB AL,12 ;HOUR SLOT IS 24 HOUR TIME +OPH1$: CMP AL,9 + JG OPH2$ + PUSH AX + MOV AL,32 + CALL PUTCHR ;OUTPUT SPACE FOR HOUR LESS THAN 10 + POP AX +OPH2$: CALL OPPRNN + MOV AL,":" + JMP PUTCHR ;AND COLON +OPPRNH ENDP + +OPPRNM PROC + CMP AL,9 + JG OPM1$ + PUSH AX + MOV AL,"0" + CALL PUTCHR + POP AX +OPM1$: CALL OPPRNN + MOV AL,32 + CALL PUTCHR + MOV AL,"a" + CMP PMFLAG,0 + JE OPM2$ + MOV AL,"p" +OPM2$: CALL PUTCHR + MOV AL,"m" + JMP PUTCHR +OPPRNM ENDP + + ;PRINTD (PRINT OBJ'S SHORT DESCRIPTION) +OPPRND PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + ADD AX,7 ;PROPERTY TABLE POINTER + MOV BP,AX + GTAWRD A,[BP] ;GET IT + INC AX ;POINT TO STRING + CALL BSPLTB ;SPLIT POINTER + JMP PUTSTR ;AND PRINT THE STRING +OPPRND ENDP + + ;PRINTI (PRINT THE STRING FOLLOWING THIS INSTRUCTION) +OPPRNI PROC + MOV AX,ZPC1 ;GET POINTER TO STRING + MOV BX,ZPC2 + CALL PUTSTR ;AND PRINT IT + MOV ZPC1,AX ;UPDATE ZPC + MOV ZPC2,BX + JMP NEWZPC +OPPRNI ENDP + + ;PRINTR (PRINTI FOLLOWED BY RTRUE) +OPPRNR PROC + CALL OPPRNI ;DO A PRINTI + CALL OPCRLF ;A CRLF + JMP OPRTRU ;AND AN RTRUE +OPPRNR ENDP + + ;CRLF (DO A NEWLINE) +OPCRLF PROC + JMP NEWLIN ;DO A NEWLINE +OPCRLF ENDP + + SUBTTL CONTROL OPERATIONS + PAGE + + + ;CALL (A FUNCTION WITH OPTIONAL ARGUMENTS), # OF ARGS IN AX +OPCALL PROC + NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV DX,AX ;NUMBER OF ARGUMENTS TO CALL + MOV AX,ARGBLK ;FUNCTION TO CALL + CMP AX,0 + JNE OCL1$ ;ZERO? + SUB AX,AX ;YES, SIMPLY RETURN A ZERO + JMP PUTVAL +OCL1$: PUSHZ ZPC1 ;OTHERWISE, SAVE OLD ZPC + PUSHZ ZPC2 + MOV CX,ZLOCS ;AND OLD LOCAL POINTER +; SUB CX,STKBOT ;BUT RELATIVIZE IT IN CASE OF SAVE + PUSHZ CX ;AND SAVE IT + CALL BSPLIT ;SPLIT FUNCTION POINTER + MOV ZPC1,AX ;MAKE IT THE NEW ZPC + MOV ZPC2,BX + CALL NEWZPC ;UPDATE ZPC STUFF + MOV ZLOCS,DI ;LOCALS WILL START AT NEXT STACK SLOT + SUB ZLOCS,2 + CALL NXTBYT ;NUMBER OF LOCALS + MOV BX,AX + MOV BP,OFFSET ARGBLK[2] ;POINT TO FIRST OPTIONAL ARG +OCL2$: DEC BX ;ANY MORE LOCALS? + JL OCL4$ ;NO, WE'RE DONE + CALL NXTWRD ;YES, GET THE NEXT LOCAL DEFAULT VALUE + DEC DX ;ANY MORE OPTIONALS GIVEN? + JLE OCL3$ ;NO + PUSHZ DS:[BP] ;YES, USE ITS VALUE + ADD BP,2 + JMP OCL2$ ;AND CONTINUE LOOP +OCL3$: PUSHZ AX ;OTHERWISE, USE DEFAULT + JMP OCL2$ ;AND LOOP +OCL4$: RET +OPCALL ENDP + + ;RETURN (FROM CURRENT FUNCTION CALL) +OPRETU PROC + MOV DI,ZLOCS ;RESTORE OLD TOP OF STACK + POPZ DX ;DUMMY POP [WHY?] + POPZ ZLOCS ;AND OTHER VALUES + +; MOV DX,STKBOT ;RE-ABSOLUTIZE THIS ONE +; ADD ZLOCS,DX + + POPZ ZPC2 + POPZ ZPC1 + PUSH AX ;VALUE TO RETURN + CALL NEWZPC ;UPDATE ZPC STUFF + POP AX + JMP PUTVAL ;RETURN THE VALUE +OPRETU ENDP + + ;RTRUE +OPRTRU PROC + MOV AX,1 ;RETURN A 1 + JMP OPRETU +OPRTRU ENDP + + ;RFALSE +OPRFAL PROC + SUB AX,AX ;RETURN A 0 + JMP OPRETU +OPRFAL ENDP + + ;JUMP (TO A NEW LOCATION) +OPJUMP PROC + ADD ZPC2,AX ;ADD OFFSET TO CURRENT ZPC + SUB ZPC2,2 ;ADJUST IT + JMP NEWZPC ;NORMALIZE IT & UPDATE ZPC STUFF +OPJUMP ENDP + + ;RSTACK (RETURN STACK) +OPRSTA PROC + POPZ AX ;POP A VALUE + JMP OPRETU ;AND RETURN IT +OPRSTA ENDP + + ;FSTACK (FLUSH A VALUE OFF THE STACK) +OPFSTA PROC + POPZ DX ;FLUSH ONE + RET +OPFSTA ENDP + + ;NOOP (NO OPERATION) +OPNOOP PROC + RET ;DO NOTHING +OPNOOP ENDP + + SUBTTL LOW LEVEL FUNCTIONS + PAGE + + + ;GET A BYTE, BLOCK-POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX, + ;UPDATE AX & BX TO REFLECT BYTE GOTTEN +GETBYT PROC + PUSH AX ;SAVE BLOCK-POINTER + CMP AX,ENDLOD ;IS THIS A PRELOADED LOCATION? + JGE GTY1$ ;NO + MOV CL,9 ;YES, RECONSTRUCT POINTER + SHL AX,CL ;SHIFT BLOCK POINTER BY 9 + OR AX,BX ;ADD IN THE OFFSET + XCHG AX,BX + MOV CL,ES:[BX] ;GET THE BYTE + JMP GTY2$ ;CLEAR UNWANTED BYTE & RETURN IT +GTY1$: CALL GETPAG ;FIND THE PROPER PAGE + ADD AX,BX ;POINT TO DESIRED BYTE + XCHG AX,BX + MOV CL,ES:[BX] ;GET IT +GTY2$: SUB CH,CH ;CLEAR UNWANTED BYTE & RETURN IT + MOV BX,AX + POP AX ;RESTORE BLOCK-POINTER + INC BX ;UPDATE POINTER + CMP BX,200H ;END-OF-PAGE? + JNE GTY3$ ;NO + SUB BX,BX ;YES, CLEAR BYTE-POINTER + INC AX ;AND UPDATE BLOCK-POINTER +GTY3$: RET +GETBYT ENDP + + ;GET A WORD, BLOCK POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX +GETWRD PROC + PUSH DX ;SAVE + CALL GETBYT ;GET HIGH-ORDER BYTE + PUSH CX ;SAVE IT + CALL GETBYT ;GET LOW-ORDER BYTE + POP DX ;GET OTHER BYTE + MOV CH,DL ;POSITION IT + POP DX ;RESTORE + RET +GETWRD ENDP + + ;GET THE NEXT BYTE, RETURN IT IN AX +NXTBYT PROC + PUSH BX ;SAVE + MOV BX,ZPC2 ;BYTE POINTER + ADD BX,CURPAG ;INDEX INTO CURRENT PAGE + PUSH ES:[BX] ;SAVE BYTE + INC ZPC2 ;UPDATE PC + CMP ZPC2,200H ;END-OF-PAGE? + JL NXB1$ ;NO + CALL NEWZPC ;YES, UPDATE PAGE +NXB1$: POP AX ;RETRIEVE BYTE + SUB AH,AH ;CLEAR UNWANTED BYTE + POP BX ;RESTORE + RET ;AND RETURN IT +NXTBYT ENDP + + ;GET THE NEXT WORD, RETURN IT IN AX +NXTWRD PROC + PUSH BX ;SAVE + CALL NXTBYT ;GET HIGH-ORDER BYTE + PUSH AX ;SAVE IT + CALL NXTBYT ;GET LOW-ORDER BYTE + POP BX ;GET HIGH-ORDER BYTE + MOV AH,BL ;POSITION IT + POP BX ;RESTORE + RET ;RETURN THE WORD +NXTWRD ENDP + + ;GET AN ARGUMENT GIVEN ITS TYPE IN AX +GETARG PROC + DEC AX ;EXAMINE ARGUMENT + JL NXTWRD ;0 MEANT LONG IMMEDIATE + JE NXTBYT ;1 MEANT SHORT IMMEDIATE + CALL NXTBYT ;2 MEANT VARIABLE, GET THE VAR + CMP AX,0 ;STACK? + JNE GETVAR ;NO, JUST GET THE VAR'S VALUE + POPZ AX ;YES, POP THE STACK + RET +GETARG ENDP + + ;GET VALUE OF A VARIABLE, VAR IN AX, VALUE RETURNED IN AX +GETVAR PROC + CMP AX,0 ;STACK? + JNE GTV1$ ;NO + POPZT AX ;YES, GET TOP-OF-STACK + RET +GTV1$: PUSH BP ;SAVE + CMP AX,16 ;LOCAL? + JGE GTV3$ ;NO + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV AX,[BP] ;AND GET IT +GTV2$: POP BP ;RESTORE + RET +GTV3$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + MOV BP,AX ;AND GET IT + GTAWRD A,[BP] + JMP GTV2$ +GETVAR ENDP + + ;UPDATE VALUE OF A VARIABLE, VAR IN AX, NEW VALUE IN BX +PUTVAR PROC + CMP AX,0 ;STACK? + JNE PTV1$ ;NO + PUSHZT BX ;YES, UPDATE TOP-OF-STACK + RET +PTV1$: CMP AX,16 ;LOCAL? + JGE PTV2$ ;NO + PUSH BP ;SAVE + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV [BP],BX ;AND UPDATE IT + POP BP ;RESTORE + RET +PTV2$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + XCHG AX,BX ;AND UPDATE IT + PTAWRD [BX],A + RET +PUTVAR ENDP + + ;RETURN VAL IN AX TO LOCATION SPECIFIED BY NEXTBYTE + ;DESTROYS BX, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION +BYTVAL PROC + SUB AH,AH ;THIS ENTRY FOR BYTE VALUE TO CLEAR HIGH BYTE + JMP PUTVAL +BYTVAL ENDP + +PUTVAL PROC + MOV BX,AX ;NORMAL ENTRY + CALL NXTBYT ;GET VAR TO USE + CMP AX,0 ;STACK? + JNE PUTVAR ;NO, GO STORE VALUE + PUSHZ BX ;YES, PUSH ONTO STACK + RET ;AND RETURN +PUTVAL ENDP + + ;PREDICATE HANDLERS TRUE & FALSE + ;DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FCNS +PFALSE PROC + SUB BX,BX ;PREDICATE WAS FALSE, CLEAR FLAG + JMP PPRED +PFALSE ENDP + +PTRUE PROC + MOV BX,1 ;PREDICATE WAS TRUE, SET FLAG + JMP PPRED +PTRUE ENDP + +PPRED PROC + CALL NXTBYT ;GET FIRST (OR ONLY) PREDICATE JUMP BYTE + TEST AX,80H ;NORMAL POLARITY PREDICATE? + JE PPR1$ ;NO, LEAVE FLAG ALONE + INC BX ;YES, INCREMENT FLAG +PPR1$: TEST AX,40H ;ONE-BYTE JUMP OFFSET? + JE PPR2$ ;NO + AND AX,0FF3FH ;YES, CLEAR SPECIAL BITS + JMP PPR3$ +PPR2$: AND AX,0FF3FH ;CLR SPECIAL BITS FROM HIGH-ORDER OFFSET BYTE + MOV CX,AX ;HIGH-ORDER BYTE + CALL NXTBYT ;GET LOW-ORDER BYTE + MOV AH,CL ;MOVE IN HIGH-ORDER BITS + TEST AX,2000H ;IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)? + JE PPR3$ ;NO + OR AX,0C000H ;YES, MAKE 16-BIT NUMBER NEGATIVE +PPR3$: DEC BX ;TEST FLAG + JE PPR6$ ;WAS 1, THAT MEANS DO NOTHING + CMP AX,0 ;ZERO JUMP? + JNE PPR4$ ;NO + JMP OPRFAL ;YES, THAT MEANS DO AN RFALSE +PPR4$: DEC AX ;ONE JUMP? + JNE PPR5$ ;NO + JMP OPRTRU ;YES, THAT MEANS DO AN RTRUE +PPR5$: DEC AX ;ADJUST OFFSET + ADD ZPC2,AX ;ADD TO PC + JMP NEWZPC ;AND UPDATE ZPC STUFF +PPR6$: RET +PPRED ENDP + + ;SPLIT BYTE-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE OFFSET IN BX +BSPLTB PROC + MOV BX,AX + XCHG AL,AH ;EXTRACT BLOCK BITS + SHR AX,1 + AND AX,7FH ;CLEAR UNWANTED BITS + AND BX,1FFH ;CLEAR ALL BUT BYTE OFFSET BITS + RET +BSPLTB ENDP + + ;SPLIT WORD-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE-OFFSET IN BX +BSPLIT PROC + MOV BX,AX + MOV AL,AH ;EXTRACT BLOCK BITS + SUB AH,AH ;CLEAR UNWANTED BITS + SUB BH,BH ;CLEAR ALL BUT WORD OFFSET BITS + SHL BX,1 ;CONVERT TO BYTE OFFSET + RET +BSPLIT ENDP + + SUBTTL OBJECT HACKERS + PAGE + + + ;GIVEN OBJ NUMBER IN AX, RETURN OBJ LOCATION IN AX +OBJLOC PROC + SUB AH,AH ;CLEAR UNWANTED BITS + PUSH BX ;MULTIPLY BY 9 THE LAZY WAY + MOV BX,AX + SHL AX,1 + SHL AX,1 + SHL AX,1 + ADD AX,BX + POP BX ;RESTORE + ADD AX,OBJTAB ;INDEX INTO OBJECT TABLE + ADD AX,53 ;SKIPPING DEFAULT PROPERTY TABLE + RET +OBJLOC ENDP + + ;GIVEN POINTER TO A PROPERTY IN BX!, UPDATE IT TO POINT TO NEXT PROP +NXTPRP PROC + PUSH AX ;SAVE + PUSH CX ;SAVE + MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPSIZE;EXTRACT PROPERTY LENGTH (MINUS 1) + MOV CL,PROPSIZE + SHR AL,CL + SUB AH,AH + ADD BX,AX ;ADD IT TO OLD POINTER + ADD BX,2 ;ADJUST FOR EXTRA LENGTH BYTE PLUS IDENTIFIER + POP CX ;RESTORE + POP AX ;RESTORE + RET +NXTPRP ENDP + + SUBTTL STRING FUNCTIONS + PAGE + + +PADCHR EQU 5 ;ZSTR PADDING CHARACTER + + ;OUTPUT A ZSTR, BLOCK-POINTER IN AX, BYTE-POINTER IN BX + ;RETURN UPDATED POINTER +PUTSTR PROC + PUSH SI ;SAVE + PUSH CX ;SAVE + PUSH DX ;SAVE + PUSH DI ;SAVE + PUSH BP ;SAVE + SUB DX,DX ;TEMP CS STARTS AT 0 + SUB DI,DI ;PERM CS STARTS AT 0 +PTS1$: CALL GETWRD ;GET NEXT STRING WORD + MOV SI,CX + PUSH AX ;SAVE POINTER & COPY OF STRING WORD + PUSH BX + PUSH SI + MOV CX,3 ;3 BYTES IN WORD +PTS2$: PUSH SI ;SAVE CURRENT BYTE (IN LOW-ORDER POSITION) + MOV BP,CX ;SHIFT TO NEXT BYTE + MOV CL,5 + SAR SI,CL + MOV CX,BP + LOOP PTS2$ ;LOOP UNTIL DONE + MOV CX,3 ;RETRIEVE THE 3 BYTES +PTS3$: POP SI ;GET NEXT BYTE + AND SI,1FH ;CLEAR UNWANTED BITS + CMP DX,0 ;IN WORD MODE? + JGE PTS4$ ;NO {WAS BPL, CHECK} + SAL SI,1 ;YES, CALCULATE WORD OFFSET + ADD SI,WRDTAB ;POINT INTO WORD TABLE + ADD SI,WRDOFF ;USING PROPER 32-WORD BLOCK + GTAWRD A,[SI] ;POINT TO WORD STRING + CALL BSPLIT ;SPLIT IT + CALL PUTSTR ;AND PRINT IT + JMP PTS15$ ;CONT. WHERE WE LEFT OFF WITH TEMP CS RESET +PTS4$: CMP DX,3 ;CS 3 SELECTED (ASCII MODE)? + JL PTS6$ ;NO, NORMAL CS + JNE PTS5$ ;NO, BUT WE ARE IN ASCII MODE + XCHG DL,DH ;SHIFT SOME BITS HIGH TO MAKE NUMBER LARGE + OR DX,SI ;SAVE HIGH-ORDER ASCII BITS HERE + JMP PTS16$ ;GO GET NEXT BYTE +PTS5$: AND DX,3 ;EXTRACT PREVIOUSLY SAVED HIGH-ORDER BITS + MOV BP,CX ;POSITION THEM + MOV CL,5 + SAL DX,CL + MOV CX,BP + OR DX,SI ;OR IN LOW-ORDER BITS + MOV AX,DX + JMP PTS14$ ;GO PRINT THE CHARACTER +PTS6$: CMP SI,6 ;SPECIAL CODE? + JL PTS9$ ;YES, SPACE, WORD, OR SHIFT + CMP DX,2 ;MIGHT ALSO BE SPECIAL IF IN CS 2 + JNE PTS8$ ;BUT WE'RE NOT + CMP SI,7 ;CRLF? + JE PTS7$ ;YES + JG PTS8$ ;NO, NOT ASCII MODE, EITHER? + INC DX ;YES IT IS, SWITCH TO ASCII MODE + JMP PTS16$ ;AND GO GET NEXT BYTE +PTS7$: CALL NEWLIN ;CRLF REQUESTED, DO A NEWLINE + JMP PTS15$ +PTS8$: MOV AX,DX ;NORMAL CHARACTER, GET CS + MOV BP,26 ;CALCULATE OFFSET FOR THIS CS + MUL BP + ADD AX,SI ;ADD IN CHARACTER OFFSET (+6) + SUB AX,6 ;CHARACTER OFFSET + MOV BX,OFFSET ZCHRS ;GET THE CHARACTER FROM CONVERSION VECTOR + XLAT ZCHRS + JMP PTS14$ ;GO PRINT IT +PTS9$: CMP SI,0 ;IS IT A SPACE? + JNE PTS10$ ;NO + MOV AX," " ;YES, GO PRINT A SPACE + JMP PTS14$ +PTS10$: CMP SI,3 ;IS IT A WORD? + JG PTS11$ ;NO, MUST BE A SHIFT + OR DX,8000H ;SWITCH TO WORD MODE FOR NEXT BYTE + DEC SI ;CALCULATE WORD-TABLE BLOCK OFFSET + MOV BP,CX ;64 BYTES IN A BLOCK + MOV CL,6 + SHL SI,CL + MOV CX,BP + MOV WRDOFF,SI ;SAVE IT AND LOOP + JMP PTS16$ +PTS11$: SUB SI,3 ;CALCULATE NEW CS + CMP DX,0 ;TEMPORARY SHIFT (FROM CS 0)? + JNE PTS12$ ;NO + MOV DX,SI ;YES, JUST SAVE NEW TEMP CS + JMP PTS16$ +PTS12$: CMP SI,DX ;IS THIS THE CURRENT CS? + JE PTS13$ ;YES, DO A PERM SHIFT TO IT + SUB DX,DX ;OTHERWISE, PERM SHIFT TO CS 0 +PTS13$: MOV DI,DX ;TEMP & PERM CS'S ARE SAME NOW + JMP PTS16$ +PTS3A$: JMP PTS3$ ;DUMMY FOR NON-SHORT LOOP +PTS14$: CALL PUTCHR ;PRINT THE CHARACTER +PTS15$: MOV DX,DI ;RESET TEMP CS TO PERM CS +PTS16$: LOOP PTS3A$ ;NEXT BYTE + POP SI ;RESTORE POINTERS & ORIGINAL STRING WORD + POP BX + POP AX + CMP SI,0 ;END-OF-STRING? + JL PTS1A$ ;YES, CLEAN UP & RETURN UPDATED POINTER + JMP PTS1$ ;NO, GET NEXT WORD +PTS1A$: POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET +PUTSTR ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN THE CHARACTER SET # IN AX +CHRCS PROC + CMP AX,0 ;IS THIS A NULL? + JNE CCS1$ ;NO + MOV AX,3 ;YES, RETURN DUMMY CS NUMBER + RET +CCS1$: PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CONVERSION VECTOR +CCS2$: INC BX ;FOUND THE CHARACTER? + CMP AL,[BX-1] + JE CCS3$ ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CCS2$ ;NO, CONTINUE LOOP + MOV AX,2 ;YES, CALL IT CS 2 + JMP CCS5$ +CCS3$: SUB BX,OFFSET ZCHRS ;FIND CHARACTER POSITION + SUB AX,AX ;START WITH CS 0 +CCS4$: SUB BX,26 ;EVERY 26 CHARACTERS IS A NEW CS + JLE CCS5$ ;DONE + INC AX ;INCREMENT CS # & CONTINUE LOOP + JMP CCS4$ +CCS5$: POP BX + RET +CHRCS ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN ZSTR BYTE VALUE IN AX +CHRBYT PROC + PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CHARACTER CONVERSION TABLE +CHB1$: INC BX ;FOUND THE CHARACTER? + CMP AL,[BX-1] + JE CHB2$ ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CHB1$ ;NO, CONTINUE LOOP + SUB AX,AX ;YES, RETURN ZERO FOR FAILURE + JMP CHB4$ +CHB2$: SUB BX,OFFSET ZCHRS-5 ;ADJUST POINTER SO FIRST CHARACTER IS 6 + MOV AX,BX +CHB3$: CMP AX,32 ;SUBTRACT MULTIPLES OF 26 UNTIL BASE CODE + JL CHB4$ + SUB AX,26 + JMP CHB3$ +CHB4$: POP BX ;RESTORE + RET +CHRBYT ENDP + + ;CONVERT UP TO 6 ASCIZ CHARS POINTED TO BY DS:AX + ;TO A 2-WORD ZSTR RETURNED IN AX & BX +ZWORD PROC + PUSH SI ;SAVES + PUSH CX + PUSH DX + PUSH DI + PUSH BP + MOV SI,AX ;CHARACTER STRING POINTER + SUB DI,DI ;CS STARTS AT 0 + MOV CX,6 ;MAKE 6 ZSTR BYTES +ZWD1$: INC SI ;GET NEXT CHARACTER + MOV BL,[SI-1] + CMP BL,0 + JNE ZWD3$ ;NOT END-OF-STRING + MOV AX,OFFSET PADCHR;AT END-OF-STRING, PAD WITH PAD CHARACTER +ZWD2$: PUSH AX ;SAVE A PAD BYTE + LOOP ZWD2$ ;LOOP UNTIL DONE + JMP ZWD6$ ;THEN GO FORM ZWORD +ZWD3$: MOV AX,BX + CALL CHRCS ;FIND THE CS NUMBER FOR THIS CHAR + CMP AX,0 ;CS 0? + JE ZWD4$ ;YES + ADD AX,3 ;NO, CALCULATE TEMP SHIFT BYTE + PUSH AX ;SAVE THE SHIFT BYTE + DEC CX ;REDUCE BYTE COUNT + JE ZWD6$ ;DONE +ZWD4$: MOV AX,BX ;FIND THE PROPER BYTE VALUE FOR THIS CHAR + CALL CHRBYT + CMP AX,0 ;IN NORMAL CS'S? + JNE ZWD5$ ;YES + MOV AX,6 ;NO, USE ASCII SHIFT + PUSH AX + DEC CX ;DONE YET? + JE ZWD6$ ;YES + MOV AX,BX ;NO, SAVE HIGH-ORDER ASCII BITS + MOV BP,CX + MOV CL,5 + SAR AX,CL + MOV CX,BP + PUSH AX + DEC CX ;DONE YET? + JE ZWD6$ ;YES + AND BX,1FH ;NO, SAVE LOW-ORDER ASCII BITS + MOV AX,BX +ZWD5$: PUSH AX ;SAVE THIS BYTE + LOOP ZWD1$ ;LOOP UNTIL ZWORD FULL +ZWD6$: MOV BP,SP ;BUILD ZWORD WORDS FROM 6 SAVED BYTES + MOV AX,[BP+10] + MOV CL,5 + SHL AX,CL + OR AX,[BP+8] + SHL AX,CL + OR AX,[BP+6] + MOV BX,[BP+4] + SHL BX,CL + OR BX,[BP+2] + SHL BX,CL + OR BX,[BP] + OR BX,8000H ;SET END-OF-STRING BIT IN SECOND WORD + ADD SP,12 ;FLUSH STACK + POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET +ZWORD ENDP + + SUBTTL TERMINAL I/O + PAGE + + + ;QUEUE CHARACTER IN AX FOR OUTPUT +PUTCHR PROC + PUSH BP + CMP USLMOD,0 + JE PTC0$ + PUSH AX ;SAVE EVERYTHING + PUSH BX + PUSH CX + PUSH SI + PUSH DI + SUB BH,BH + MOV AH,9 + MOV CX,1 + MOV BL,USLATR + INT 10H ;OUTPUT CHARACTER IN INVERSE VIDEO + MOV AH,3 + INT 10H ;READ CURSOR + INC DX + MOV AH,2 + INT 10H ;MOVE CURSOR FORWARD + POP DI + POP SI + POP CX + POP BX + POP AX + POP BP + RET +PTC0$: MOV BP,CHRPTR ;END OF BUFFER? + CMP BP,ENDBUF + JNE PTC7$ ;NO + PUSH AX ;YES, ENTER OUTPUT ROUTINE; SAVES + PUSH BX + PUSH SI + MOV BX,ENDBUF ;END OF BUFFER + MOV SI,OFFSET OUTBUF;BEGINNING OF BUFFER +PTC1$: DEC BX ;SEARCH FOR SPACE BACKWARDS FROM END + CMP BYTE PTR [BX]," " + JE PTC3$ + CMP BX,SI ;STOP AT BEGINNING OF BUFFER + JNE PTC1$ +PTC2$: PRINT OUTBUF ;NO SPACES, OUTPUT WHOLE LINE + MOV CHRPTR,SI ;RESTORE POINTER TO BEGINNING OF BUFFER + MOV BP,SP + CMP BYTE PTR [BP+4]," " ;DID A SPACE CAUSE BUFFER OVERFLOW? + JNE PTC6$ ;NO + MOV WORD PTR [BP+4],0 ;YES, FLUSH IT + JMP PTC6$ ;AND RETURN +PTC3$: CMP BX,SI ;DEGENERATE CASE WITH SPACE AT OUTBUF? + JE PTC2$ ;YES, OUTPUT WHOLE LINE + MOV BYTE PTR [BX],0 ;NO, OUTPUT UP TO SPACE + PRINT OUTBUF + MOV AX,ENDBUF ;END OF BUFFER + INC BX ;START GETTING CHARACTERS AFTER THE SPACE +PTC4$: CMP BX,AX ;AT END YET? + JE PTC5$ ;YES + MOV BP,AX ;SAVE AX + MOVM [SI],[BX],AL ;NO, COPY NEXT CHAR TO BEGINNING OF BUF + MOV AX,BP ;RESTORE AX + INC BX + INC SI + JMP PTC4$ ;AND CONTINUE +PTC5$: MOV CHRPTR,SI ;NEXT CHAR WILL GO AFTER COPIED STUFF +PTC6$: POP SI ;CLEAN UP + POP BX + POP AX + CMP AX,0 ;AND IGNORE A NULL CHARACTER + JE PTC8$ +PTC7$: MOV BP,CHRPTR ;NOW STORE THE CHARACTER IN BUFFER + MOV DS:[BP],AL + INC CHRPTR ;UPDATE POINTER +PTC8$: POP BP ;RESTORE + RET ;AND RETURN +PUTCHR ENDP + + ;GO TO NEW LINE, OUTPUTTING CURRENT BUFFER +NEWLIN PROC + PUSH BX ;SAVE + MOV BX,CHRPTR ;END LINE AT CURRENT POINT + MOV BYTE PTR [BX],0 + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP BX ;RESTORE + PRINT OUTBUF ;AND OUTPUT LINE + RET +NEWLIN ENDP + +EOICHR EQU 15 ;CARRIAGE RETURN IS NORMAL END OF INPUT + + SUBTTL TOP LEVEL STUFF + PAGE + + +PVERS1 EQU 0 ;POSITION OF ZVERSION VERSION BYTE +PVERS2 EQU 1 ;ZVERSION MODE BYTE +PZRKID EQU 2 ;ZORKID +PENDLD EQU 4 ;ENDLOD +PSTART EQU 6 ;START +PVOCTB EQU 10Q ;VOCAB +POBJTB EQU 12Q ;OBJECT +PGLOTB EQU 14Q ;GLOBALS +PPURBT EQU 16Q ;PURBOT +PFLAGS EQU 20Q ;USER FLAG WORD +PSERNM EQU 22Q ;SERIAL NUMBER (6 BYTES) +PWRDTB EQU 30Q ;WORDS +PLENTH EQU 32Q ;GAME LENGTH +PCHKSM EQU 34Q ;GAME CHECKSUM +LMOUTB EQU 80 ;MAX LENGTH OF OUTBUF, EXCLUDING TERMINAL 0 +LDOUTB EQU 80 ;DEFAULT LENGTH OF OUTBUF +LPAGES EQU 128 ;MAX NUMBER OF PAGES EXPECTED +LXBYTS EQU LSTACK+LMOUTB+(4*LPAGES)+2000Q ;LENGTH OF EXTRA BYTES NEEDED + + ;INITIALIZATION +TSETUP PROC + TEST INIFLG,INIWID ;CHECK FOR FORCED 40 COLUMN MODE + JZ TS0$ + MOV TWIDTH,38 ;FORCE IT TO 40 +TS0$: MOV BX,OFFSET OUTBUF ;START OF OUTPUT BUFFER + ADD BX,TWIDTH ;ADD LENGTH OF BUFFER + SUB BL,LFTMAR ; *** SUBTRACT THE LEFT MARGIN VALUE + MOV ENDBUF,BX ;THIS IS ENDBUF POINTER + MOV BYTE PTR [BX],0 ;BUFFER IS FOLLOWED BY A 0 FOR CONVENIENCE + MOV BX,OFFSET SLSTAB ;GET STATUS LINE TABLE + CMP TIMEMD,0 ;CHECK FOR SCORE/TIME MODE + JE TS1$ + ADD BX,8 ;THE TIME MODE TABLE IS OFFSET FOUR WORDS +TS1$: MOV SI,0 ;OFFSET INTO PROPER TABLE + CMP TWIDTH,38 ;CHECK TERMINAL WIDTH + JE TS2$ + ADD SI,4 ;OFFSET TO 80 COLUMN STUFF +TS2$: MOV AX,[BX][SI] + MOV SLSTR,AX + MOV CX,2[BX][SI] + MOV SLTAB,CX ;GET THE RIGHT POINTERS TO STRING/TABLE + MOV BL,USLATR ;INVERSE VIDEO, STRING ALREADY IN AX + MOV CX,0 ;AT 0,LFTMAR + CALL .PRINTA ;PRINT THE STATUS LINE + RET +TSETUP ENDP + +ZIPBGN PROC + CALL SYSINI ;DO ANY SYSTEM INITIALIZATION + CALL BKCHK ;CHECK FOR MAKING BACKUP COPY +STR5$: CALL .GETMEM + MOV BX,ES + SUB AX,BX + MOV MEMTOP,AX ;LAST AVAILABLE PARAGRAPH LOCATION + SUB AX,AX ;BLOCK 0 + SUB BX,BX ;PUT AT BEGINNING OF GAME SEGMENT + CALL GETBLK ;GET THE BLOCK + CMP BYTE PTR ES:[PVERS1],ZMVERS ;PROPER Z-MACHINE VERSION? + JNE STR8$ ;NO + TEST BYTE PTR ES:[PVERS2],1 ;YES,PROPER MODE BITS? + JE STR9$ ;YES +STR8$: FATAL FTL4 ;SOMETHING WRONG, DIE +STR9$: TEST BYTE PTR ES:[PVERS2],2 ;TIME MODE REQUESTED? + JE STR10$ ;NO + INC TIMEMD ;YES +STR10$: GTAWRD A,[PZRKID] ;UNIQUE GAME & VERSION INDENTIFER + MOV ZORKID,AX + OR BYTE PTR ES:[PVERS2],0020H ;SET SPLIT BIT + GTAWRD A,[PENDLD] ;GET ENDLOD POINTER + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR12$ + AND AX,0FE00H + ADD AX,200H +STR12$: MOV CX,AX + MOV BP,CX ;EXTRACT ENDLOD BLOCK + MOV CL,9 + SAR BP,CL + MOV CX,BP + MOV ENDLOD,CX ;SAVE ENDLOD BLOCK NUMBER + DEC CX ;NUMBER OF BLOCKS LEFT TO LOAD + MOV AX,1 ;STARTING WITH BLOCK 1 + MOV BX,200H ;LOCATION TO PUT THEM + CALL GTBLKS ;GET THE BLOCKS + GTAWRD A,[PVOCTB] ;VOCAB LOCATION + MOV VOCTAB,AX ;SAVE VOCABULARY TABLE POINTER + GTAWRD A,[POBJTB] ;GET OBJECT TABLE POINTER + MOV OBJTAB,AX + GTAWRD A,[PGLOTB] ;GET GLOBAL TABLE POINTER + MOV GLOTAB,AX + GTAWRD A,[PWRDTB] ;GET WORD TABLE POINTER + MOV WRDTAB,AX + GTAWRD A,[PPURBT] ;GET PURE CODE POINTER + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR13$ + ADD AX,200H +STR13$: MOV CL,9 ;EXTRACT BLOCK NUMBER + SAR AX,CL + AND AX,7FH ;CLEAR UNWANTED BITS + MOV PURBOT,AX ;SAVE IT + MOV BX,OFFSET RBRKS ;START OF READ BREAK CHARACTER TABLE + MOV SI,VOCTAB ;VOCAB TABLE POINTER + MOV CL,BYTE PTR ES:[SI] ;1ST BYTE IN VOCTAB IS # OF SIBREAKS + SUB CH,CH ;CLEAR HIGH BYTE + INC SI +STR14$: MOVM [BX],ES:[SI],AL ;TRANSFER THEM + INC BX + INC SI + LOOP STR14$ + MOV ESIBKS,BX ;REMEMBER END OF SI BREAKS + MOV BP,OFFSET IRBRKS;ALWAYS END WITH INITIAL BREAK CHARACTERS +STR15$: MOVM [BX],DS:[BP],AL ;TRANSFER THEM + INC BX + INC BP + CMP AL,0 + JNE STR15$ + MOV AL,ES:[SI] ;GET VOCABULARY ENTRY LENGTH + SUB AH,AH + MOV VWLEN,AX ;AND STORE IT AWAY + INC SI + GTAWRD A,[SI] ;GET NEXT WORD IN TABLE + MOV VWORDS,AX ;NUMBER OF WORD ENTRIES IN VOCABULARY + ADD SI,2 ;MOVE TO NEXT WORD + MOV VOCBEG,SI ;BEGINNING OF ACTUAL VOCABULARY + + MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + MOV CL,9 + SHL SI,CL ;THIS IS FIRST LOCATION (ES:) OF PAGING + MOV PAGES,SI ;SAVE THIS TO USE AS AN OFFSET + + MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + NEG SI + MOV DI,MEMTOP ;GET PARAGRAPHS OF MEMORY + MOV CL,5 + SAR DI,CL ;CHANGE TO PAGES + ADD SI,DI ;NUMBER OF PAGES FOR PAGING + MOV BUFPGS,SI ;SAVE THIS NUMBER FOR FUTURE REFERENCE + CMP BUFPGS,63 + JLE STR16$ + MOV BUFPGS,63 ;OUR TABLE IS ONLY SO BIG.... + MOV SI,63 +STR16$: SHL SI,1 + SHL SI,1 ;EACH PAGE HAS 4 BYTES OF INFO + MOV BX,OFFSET PAGTAB ;POINT INTO PAGE INFO TABLE + ADD SI,BX + MOV WORD PTR [SI],-1 ;MAKE THIS THE END OF TABLE MARK + + CALL .GETTM ;GET THE CURRENT TIME-OF-DAY + MOVM RSEED1,TIME[2],AX;USE IT TO INITIALIZE RANDOM NUMBER SEED + MOVM RSEED2,TIME,AX ;BE CONSISTENT +STR17$: JMP START1 +ZIPBGN ENDP + +PRSPC PROC + PUSH AX + PUSH BX + PUSH CX + CALL OPPRNN + MOV AL,32 + CALL PUTCHR + POP CX + POP BX + POP AX + RET +PRSPC ENDP + + ;RESTART EXECUTION HERE +RESTRT PROC + INT 19H ; REBOOT THE SUCKER FOR NOW + RET ; I'M SENTIMENTAL + +START1: CALL WPCHK ;MAKE SURE GAME DISK IS WRITE-PRO + CALL TSETUP ;SETUP TERMINAL/STATUS LINE + CALL CLRSCR ;CLEAR THE REMAINDER OF THE SCREEN + MOV SP,OFFSET STK_TOP ;INIT OUR STACK POINTER + MOV DI,OFFSET ZSTK_TP ;INIT USER STACK POINTER + MOV CHRPTR,OFFSET OUTBUF ;INIT OUTPUT CHAR. POINTER + MOV ZLOCS,DI ; LOCALS WOULD START AT FIRST SLOT, + SUB ZLOCS,2 ; IF THERE WERE ANY + GTAWRD A,[PSTART] + CALL BSPLTB ;SPLIT BLOCK & BYTE POINTERS + MOV ZPC1,AX ;INIT ZPC BLOCK-POINTER + MOV ZPC2,BX ;INIT ZPC BYTE-POINTER + CALL NEWZPC ;GET PAGE TO EXECUTE + CMP INIFLG,5 + JNE FUBAR$ + MOV AX,CS + CALL PRSPC + MOV AX,DS + CALL PRSPC + MOV AX,ES + CALL PRSPC + MOV AX,SS + CALL PRSPC + MOV AX,ENDLOD + CALL PRSPC + MOV AX,PAGES + CALL PRSPC + MOV AX,BUFPGS + CALL PRSPC + MOV AX,MEMTOP + CALL PRSPC +FUBAR$: MOV FUCK,1 + JMP NXTINS + +RESTRT ENDP + + ;MAIN INSTRUCTION INTERPRETATION LOOP +NXTINS PROC + CALL NXTBYT ;GET THE OPERATION BYTE + MOV DX,AX ;SAVE A COPY + CMP AX,80H ;IS IT A 2OP? + JL NXI9$ ;YES + CMP AX,0B0H ;NO, IS IT A 1OP? + JGE NXI0A$ ;NO + JMP NXI12$ ;YES +NXI0A$: CMP AX,0C0H ;IS IT A 0OP? + JG NXI0B$ ;NO + JMP NXI13$ ;YES +NXI0B$: AND AX,3FH ;IT'S EXTENDED, GET THE OPCODE + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET THE OPERATOR POINTER + MOV SI,DS:[BP+EXTOP] + CMP SI,0 + JNE NXI0C$ ;OPERATION EXISTS + JMP NXI14$ ;NO SUCH OPERATION +NXI0C$: CALL NXTBYT ;GET THE ARGUMENT BYTE + MOV CX,4 ;SPLIT IT INTO 4 2-BIT MODE BYTES +NXI1$: PUSH AX + SAR AX,1 + SAR AX,1 + LOOP NXI1$ + MOV CX,4 ;RETRIEVE THE 4 BYTES IN PROPER ORDER + SUB DX,DX + MOV BX,OFFSET ARGBLK;FIRST ARGUMENT SLOT +NXI2$: POP AX ;GET NEXT MODE BYTE? + AND AX,3 ;CLEAR OFF UNWANTED BITS + CMP AX,3 ;NO MORE ARGUMENTS? + JE NXI4$ ;YES, FLUSH ANY OTHER MODE BYTES + CALL GETARG ;ELSE, GET THE NEXT ARGUMENT + MOV [BX],AX ;SAVE IT IN ARGUMENT BLOCK + ADD BX,2 + INC DX ;REMEMBER NUMBER OF ARGS GOTTEN +NXI3$: LOOP NXI2$ ;LOOP FOR REST OF MODE BYTES + JMP NXI5$ +NXI4$: DEC CX ;DETERMINE NUMBER OF REMAINING MODE BYTES + SHL CX,1 ;WORD COUNT + ADD SP,CX ;FLUSH THEM +NXI5$: XCHG CX,DX + MOV AX,CX ;NUMBER OF ARGS GOES HERE FOR OPERATOR TO USE + CMP CS:BYTE PTR [SI],90H ;DOES OPERATOR WANT ARGBLK POINTER? + JE NXI8A$ ;YES, CALL OPERATOR NOW + DEC CX ;NO, IT WANTS ARGS IN REGISTERS + JL NXI8A$ ;NO ARGS, JUST CALL OPERATOR + JE NXI8$ ;1 ARG, GET IT + SUB CX,2 + JL NXI7$ ;2 ARGS + JE NXI6$ ;3 ARGS + MOV DX,ARGBLK[6] ;ELSE, 4 ARGS, GET 4TH +NXI6$: MOV CX,ARGBLK[4] ;GET 3RD +NXI7$: MOV BX,ARGBLK[2] ;GET 2ND +NXI8$: MOV AX,ARGBLK ;GET FIRST ARG +NXI8A$: JMP NXI15$ ;AND CALL OPERATOR +NXI9$: AND AX,1FH ;2OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;FIND POINTER TO OPERATOR ROUTINE + MOV SI,DS:[BP+EXTOP] + CMP SI,0 + JE NXI14$ ;NO SUCH OPERATION + MOV AX,1 ;ASSUME FIRST ARG IS AN IMMEDIATE + TEST DX,40H ;IS IT INSTEAD A VARIABLE? + JE NXI10$ ;NO + INC AX ;YES, CHANGE MODE +NXI10$: CALL GETARG ;GET THE FIRST ARG + PUSH AX ;SAVE IT + MOV AX,1 ;ASSUME SECOND ARG IS AN IMMEDIATE + TEST DX,20H ;IS IT INSTEAD A VARIABLE? + JE NXI11$ ;NO + INC AX ;YES, CHANGE MODE +NXI11$: CALL GETARG ;GET THE SECOND ARG + MOV BX,AX ;POSITION IT + POP AX ;RECOVER FIRST ARG + CMP CS:BYTE PTR [SI],90H ;DOES ROUTINE WANT ARGUMENT BLOCK? + JNE NXI15$ ;NO, GO CALL IT + MOV ARGBLK,AX ;YES, MOVE ARGS TO ARGBLK + MOV ARGBLK[2],BX + MOV AX,2 ;ALWAYS 2 ARGS + JMP NXI15$ ;NOW CALL OPERATOR +NXI12$: AND DX,0FH ;1OP, EXTRACT OPERATION BITS + SHL DX,1 ;MAKE IT A WORD OFFSET + MOV BP,DX ;GET OPERATOR ROUTINE POINTER + MOV SI,DS:[BP+ONEOP] + CMP SI,0 + JE NXI14$ ;ILLEGAL OPERATION + SAR AX,1 ;EXTRACT MODE BITS + SAR AX,1 + SAR AX,1 + SAR AX,1 + AND AX,3 + CALL GETARG ;GET THE ARGUMENT + JMP NXI15$ ;AND CALL OPERATOR +NXI13$: AND AX,0FH ;0OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET OPERATOR ROUTINE POINTER + MOV SI,DS:[BP+ZEROOP] + CMP SI,0 + JNE NXI15$ ;IT'S A LEGAL OPERATION +NXI14$: FATAL FTL5 ;OTHERWISE, COMPLAIN +NXI15$: CALL SI ;CALL THE OPERATOR ROUTINE + JMP NXTINS ;AND LOOP FOR NEXT INSTRUCTION +NXTINS ENDP + + SUBTTL PAGING ROUTINES + PAGE + + + ;NORMALIZE ZPC & GET PROPER PAGE +NEWZPC PROC + PUSH SI ;SAVES + PUSH BP + PUSH BX + PUSH CX + PUSH DX + SUB AX,AX ;USE DOUBLE-WORD ARITHMETIC + MOV BX,ZPC1 ;GET BLOCK-POINTER + MOV BH,BL ;POSITION IT + SUB BL,BL + SHL BX,1 + ADC AX,0 + MOV SI,ZPC2 ;GET BYTE-OFFSET + XCHG SI,AX ;DOUBLE-WORDIFY IT (MIGHT BE NEGATIVE) + CWD + XCHG SI,AX + ADD BX,SI ;ADD IT TO OTHER DOUBLE WORD + ADC AX,DX + MOV DX,BX + AND DX,1FFH ;EXTRACT BYTE-OFFSET + MOV ZPC2,DX ;SAVE IT + MOV CL,9 ;EXTRACT BLOCK-POINTER + SAR BX,CL + AND BX,7FH + TEST AX,1 ;TEST 17TH BIT + JE NWZ1$ ;WAS 0 + OR BX,80H ;WAS 1, SET PROPER BIT IN BLOCK-POINTER +NWZ1$: MOV ZPC1,BX ;SAVE IT + CMP BX,CURBLK ;HAS IT CHANGED? + JE NWZ5$ ;NO + MOV CURBLK,BX ;YES, REMEMBER NEW BLOCK + MOV AX,CURTAB ;IS OLD PAGE IN PAGING SPACE? + CMP AX,0 + JE NWZ2$ ;NO + MOV BP,AX ;YES, STORE CURRENT REF TIME FOR OLD PAGE + MOVM DS:[BP],RTIME1,CL + MOVM DS:[BP+1],RTIME2,CX + INC AX +NWZ2$: CMP BX,ENDLOD ;NEW PAGE ALREADY IN CORE? + JL NWZ3$ ;YES + MOV AX,BX ;NO, GET NEW PAGE + CALL GETPAG + MOV BX,AX + MOV AX,LPTAB ;GET NEW PAGE TABLE POINTER + INC AX ;POINT TO REF SLOT + MOV CURTAB,AX ;SAVE THIS POINTER FOR LATER + MOV BP,AX ;STORE HIGHEST RTIME TO KEEP PAGE FOR US + MOV BYTE PTR DS:[BP],-1 + MOV WORD PTR DS:[BP+1],-1 + INC AX + JMP NWZ4$ +NWZ3$: MOV CL,9 ;CALCULATE PAGE ADDRESS + SHL BX,CL + MOV CURTAB,0 ;CLEARING POINTER MEANS PAGE IS PRELOADED +NWZ4$: MOV CURPAG,BX ;UPDATE PAGE POINTER +NWZ5$: POP DX ;RESTORES + POP CX + POP BX + POP BP + POP SI + RET ;AND RETURN +NEWZPC ENDP + + ;GET THE PAGE WHOSE NUMBER IS IN AX, RETURN A POINTER TO IT IN AX +GETPAG PROC + CMP AX,LPAGE ;IS THIS THE SAME PAGE AS LAST REFERENCED? + JNE GTP1$ ;NO + MOV AX,LPLOC ;YES, WE ALREADY HAVE LOCATION + RET ;RETURN IT +GTP1$: MOV LPAGE,AX ;SAVE NEW PAGE NUMBER + PUSH CX ;SAVES + PUSH BX + ADD RTIME2,1 ;UPDATE REFERENCE TIME (COUNT) + ADC RTIME1,0 + MOV BX,OFFSET PAGTAB;PAGE INFORMATION TABLE +GTP2$: INC BX + CMP AL,[BX-1] ;SEARCH FOR DESIRED BLOCK + JNE GTP3$ ;NOT IT + CMP AX,CURBLK ;IS THIS THE CURRENT CODE PAGE? + JE GTP2A$ ;DON'T UPDATE REFERENCE TIME + MOVM [BX],RTIME1,CL ;FOUND IT, UPDATE ITS REFERENCE TIME + MOVM [BX+1],RTIME2,CX +GTP2A$: DEC BX ;BACKUP TO BEGINNING OF TABLE ENTRY + MOV LPTAB,BX ;SAVE IT + SUB BX,OFFSET PAGTAB;CALCULATE ADDRESS OF PAGE + MOV CL,7 + SHL BX,CL + ADD BX,PAGES + JMP GTP4$ ;AND RETURN PAGE POINTER +GTP3$: ADD BX,3 ;SKIP REFERENCE TIME + CMP WORD PTR [BX],-1;END OF TABLE? + JNE GTP2$ ;NO, CONTINUE SEARCH + CALL FINDPG ;YES, FIND A PAGE TO LOAD INTO + PUSH AX ;PAGE POINTER + MOV LPTAB,BX ;SAVE PAGE TABLE POINTER + MOV AX,LPAGE ;SAVE NEW BLOCK NUMBER + MOV [BX],AL + MOVM [BX+1],RTIME1,CL;AND CURRENT REF TIME + MOVM [BX+2],RTIME2,CX + POP BX ;PAGE POINTER + CALL GETBLK ;GET THE BLOCK +GTP4$: MOV AX,BX ;RETURN PAGE POINTER + MOV LPLOC,AX ;AND SAVE IT FOR LATER + POP BX ;RESTORES + POP CX + RET +GETPAG ENDP + + ;FIND A GOOD PAGE, RETURN PAGE POINTER IN AX & PAGTAB POINTER IN BX +FINDPG PROC + PUSH CX + MOV BX,OFFSET PAGTAB + MOV CX,-1 ;FAKE BEST-CASE REFERENCE COUNT + MOV DX,CX + INC BX ;SKIP BLOCK NUMBER FOR NOW +FNP1$: INC BX ;IS THIS REF TIME WORSE THAN CURRENT WORST? + CMP [BX-1],CL + JA FNP3$ ;NO + JB FNP2$ ;YES + CMP [BX],DX ;MAYBE, COMPARE LOW-ORDER WORDS, WORSE? + JAE FNP3$ ;NO +FNP2$: MOV CL,[BX-1] ;YES, SAVE ITS REF COUNT + MOV DX,[BX] + MOV AX,BX ;AND LOCATION (+2) +FNP3$: ADD BX,3 ;SKIP SECOND WORD + CMP BYTE PTR [BX-1],-1 ;LOOP UNTIL END OF TABLE + JNE FNP1$ + INC CX ;WAS A PAGE REALLY FOUND? + JE FNP4$ ;NO, GROSS BUG! + SUB AX,2 ;YES, CALCULATE CORE LOCATION OF PAGE + MOV BX,AX + SUB AX,OFFSET PAGTAB + MOV CL,7 + SHL AX,CL + ADD AX,PAGES + POP CX ;RESTORES + RET +FNP4$: FATAL FTL6 +FINDPG ENDP + + SUBTTL HIGH LEVEL IBMPC DEPENDENT STUFF + + ;SYSTEM INITIALIZATION +SYSINI PROC + MOV AH,15 + INT 10H ;CHECK VIDEO STATE + MOV BL,AH ;GET SCREEN WIDTH + SUB BH,BH ;AND ZERO HIGH END + MOV TWIDTH,BX ;SAVE IT AWAY + MOV RWIDTH,BX + SUB TWIDTH,2 + INC LFTMAR ; FIX FOR OVERSCAN + CMP AL,7 + JE SINIX$ + TEST AL,1 + JZ SINIX$ + PRINT COLORQ ;ASK IF COLOR IS REALLY NEEDED + CALL .CHRIN ;READ A CHARACTER + CMP AL,"Y" + JE SINC$ ;REALLY WANTS COLOR IF Y OR y + CMP AL,"y" + JNE SINIX$ +SINC$: MOV COLFLG,AL ; NON-ZERO = THEY WANT COLOR + MOV USLATR,74H ;MAKE STATUS LINE RED ON WHITE IN COLOR MODE + MOV NRMATR,17H ;WHITE ON BLUE FOR THE REST + MOV TYPATR,1FH ;INPUT WILL BE YELLOW ON BLUE + +SINIX$: MOV AH,1 + INT 16H ;CHECK KEYBOARD + JZ SINI0$ ;NO CHARACTER AVAILABLE + SUB AL,"0" + JL SINIF$ + CMP AL,9 + JG SINIF$ + MOV INIFLG,AL ;SET UP INIT FLAG IF 0-9 +SINIF$: MOV AH,0 + INT 16H ;BE NICE AND READ THE CHARACTER + +SINI0$: INT 11H ;DEVICE DETERMINATION + TEST AL,0C0H ;TEST BITS 7&6 FOR # DRIVES + JNZ SINI1$ + MOV SRDRV,"A" ;MAKE DEFAULT DRIVE A FOR 1 DRIVE SYSTEM + MOV NDISKS,1 + +SINI1$: TEST INIFLG,INIMEM + JZ SIN1A$ + MOV NDISKS,1 +SIN1A$: TEST INIFLG,8 ;CHECK FOR COLOR SETUP + JZ SINI2$ + MOV AL,"U" + CALL GETNUM ;READ NUMBER FOR USL ATTRIBUTE + MOV USLATR,AL + CALL .CRLF + MOV AL,"N" + CALL GETNUM + MOV NRMATR,AL +SINI2$: RET +SYSINI ENDP + +CLRSCR PROC + MOV CH,1 ;CLEAR ACTIVE SCREEN AREA + MOV CL,0 + MOV DX,TWIDTH + INC DL + CMP DL,40 + JLE CLRSC1 + INC DL +CLRSC1: MOV DH,18H + MOV AX,0600H + MOV BH,NRMATR + INT 10H ;CLEAR SCREEN, I HOPE + RET +CLRSCR ENDP + +GETNUM PROC + MOV BH,0 + MOV AH,7 + CALL .TTYOUT ;WHAT A PROMPT! + CALL .CHRIN + MOV AH,7 + CALL .TTYOUT ;ECHO + SUB AL,"0" + MOV BL,AL + CALL .CHRIN + MOV AH,7 + CALL .TTYOUT ;ECHO + SUB AL,"0" + MOV CL,4 + SHL BL,CL + ADD BL,AL + MOV AX,BX + RET +GETNUM ENDP + + ;GET A GAME FILE BLOCK, BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX +GETBLK PROC + PUSH CX ;SAVE + MOV CX,1 ;CALL GTBLKS FOR 1 BLOCK ONLY + CALL GTBLKS + POP CX ;RESTORE + RET +GETBLK ENDP + +GAMETRK EQU 6 ;FIRST GAME TRACK (0-39) + +SRBLKS PROC + MOV DSKMOD,1 ;SAVE/RESTORE MODE + JMP GTBKI$ +SRBLKS ENDP + +PTBLKS PROC + MOV DSKDIR,1 ;SET FLAG FOR WRITE + MOV DSKDRV,0 ;ALWAYS FROM DRIVE 0 + MOV DSKMOD,0 ;GAME MODE + JMP GTBKI$ +PTBLKS ENDP + + ;GET A SERIES OF GAME FILE BLOCKS, + ;FIRST BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX # OF BLOCKS IN CX +GTBLKS PROC + MOV DSKDIR,0 ;READ MODE + MOV DSKDRV,0 ;ALWAYS FROM DRIVE 0 + MOV DSKMOD,0 ;GAME MODE +GTBKI$: PUSH DX ;SAVES + PUSH BP +GTBX0$: MOV GTBCNT,CX ;SAVE NUMBER OF BLOCKS TO READ + MOV GTBSTT,AX ;SAVE FIRST BLOCK + MOV GTBCOR,BX ;SAVE STARTING LOCATION + MOV BP,8 ;8 BLOCKS PER TRACK + SUB DX,DX ;CLEAR HIGH WORD FOR DIVIDE + DIV BP ;DETERMINE TRACK AND SECTOR OFFSETS + XCHG AX,CX ;SECTOR OFFSET & NUMBER OF BLOCKS + CMP DSKMOD,0 ;CHECK FOR GAME VS. SAVE/RESTORE + JNE GTBXN$ + ADD CX,GAMETRK ;ADD IN FIRST GAME TRACK +GTBXN$: MOV CH,CL ;POSITION TRACK NUMBER + INC DX ;CONVERT TO ONE-BASED SECTOR NUMBER + MOV CL,DL ;POSITION SECTOR NUMBER + MOV AH,DSKDRV ;ALWAYS DRIVE 0 + MOV DL,9 + SUB DL,CL ;DL NOW HAS MAXIMUM SECTORS LEFT THIS TRACK + CMP AL,DL ;SEE IF WE WANT MORE THAN THE MAX + JLE GTBX1$ + MOV AL,DL ;MAKE IT THE MAX THEN + MOV DH,1 ;SIGNAL ANOTHER PASS NEEDED +GTBX1$: CALL .RDWRT ;PERFORM THE DISK OPERATION + JC GTB1$ ;READ/WRITE FAILED IF CARRY SET + CMP DH,1 ;TEST FOR ANOTHER PASS + JNZ GTBX2$ + SUB DH,DH ;CLEAN UP SO THAT DL IS # SECTORS JUST HACKED + MOV AX,GTBSTT + ADD AX,DX ;START N SECTORS HIGHER + MOV CX,GTBCNT + SUB CX,DX ;AND N LESS SECTORS LEFT TO HACK + MOV BX,GTBCOR + PUSH CX + MOV CX,9 ;SHIFT #SECTORS BY 9 FOR NEW CORE ADDRESS + SHL DX,CL + POP CX + ADD BX,DX ;HERE'S WHERE TO READ INTO NEXT PASS + JMP GTBX0$ +GTBX2$: CLC ;INDICATE DISK OPERATION WON +GTBX3$: POP BP ;RESTORES + POP DX + RET +GTB1$: CMP DSKMOD,0 ;CHECK WHETHER THIS IS GAME MODE + JZ GTB2$ ;YES, FATAL OUT + STC ;SET CARRY FLAG TO INDICATE LOSSAGE + JMP GTBX3$ ;RETURN NORMALLY +GTB2$: FATAL FTL7 +GTBLKS ENDP + + SUBTTL FRIGGING BACKUP COPY ROUTINE + PAGE + + +WPCHK PROC + MOV DSKDIR,1 ; WRITE + MOV DSKDRV,0 ; DRIVE 0 + MOV DSKMOD,1 ; ABSOLUTE SECTORS + MOV AX,2FH ; RANDOM SPOT + MOV BX,0 + MOV CX,1 ; ONE BLOCK + CALL GTBKI$ + CMP AH,3 ; HOPE IT FAILS WITH W/P FAILURE + JE WPCHK1 ; GOOD. WIN + PRINT BKWPS1 ; TELL USER TO W/P DISK + PRINT BKWPS2 + CALL .CHRIN ; WAIT FOR CHARACTER + CALL .CRLF + JMP WPCHK ; AND TRY AGAIN +WPCHK1: MOV MORLIN,0 + RET +WPCHK ENDP + + ;CHECK WHETHER BACKUP IS POSSIBLE +BKCHK PROC + CALL TSETUP + CALL BKSTAT ;GET STATUS BITS INTO AL + CMP AL,3 ;THIS IS MASTER/BACKUP ALLOWED + JE BKUP + RET + +BKUP: PRINT BKASK1 ;ASK WHETHER BACKUP WANTED + PRINT BKASK2 + PRINT BKASK3 + PRINT BKASK4 + PRINT BKASK5 + CALL .CHRIN ;GET A CHARACTER + CMP AL,"!" + JE BKUPF + CMP AL,"Y" + JE BKUP1 + CMP AL,"y" + JE BKUP1 + PRINT BKNOPE + CALL .CRLF + MOV MORLIN,0 + RET ;DOESN'T WANT TO, APPARENTLY... + +BKUPF: MOV NDISKS,1 +BKUP1: PRINT BKYEP + CALL .CRLF + MOV AL,NDISKS + CMP AL,1 + JE BKUP1Z + MOV BKDSK,1 ;MAKE COPY DISK DRIVE 1 FOR >1 DRIVE SYSTEMS +BKUP1Z: CMP NDISKS,1 + JE BKZZ + CALL BKIFST ;INSERT MASTER DISK + JMP BKZZ +BKZZ: MOV AX,0 ;SECTOR 0 + MOV BX,0 ;LOCATION 0 + MOV CX,1 ;ONE SECTOR (BOOTSTRAP) + MOV DSKDIR,0 ;READ + MOV DSKDRV,0 + CALL GTBKI$ + JNC BKUP1A + JMP BKABRT +BKUP1A: CALL BKICOP ;INSERT COPY DISK + MOV AX,0 + MOV BX,0 + MOV CX,1 + MOV DSKDIR,1 + MOVM DSKDRV,BKDSK,DL + CALL GTBKI$ ;WRITE BOOTSTRAP ONTO COPY + JNC BKUP1B + JMP BKABRT +BKUP1B: CALL BKIMST ;ASK TO INSERT MASTER + +;CODE HERE FOR FORMATTING/COPYING INTERPRETER IS TAKEN +;FROM CREATE.ASM -- IT'S ALL MAGIC + + CALL DSKHAK + + MOV DX,3 + SUB BX,BX + MOV CH,1 +BKRIL: PUSH DX + MOV CL,1 + PUSH CX + SUB DX,DX + MOV AX,0204H + INT 13H + JC BKRIF + POP CX + INC CH + ADD BX,1000H + POP DX + DEC DX + JNZ BKRIL + JMP BKWINT + +BKRIF: POP DX + POP DX + JMP BKABRT + +BKWINT: CALL DSKFIX + + CALL BKICOP ;LOAD COPY DISK + + CALL DSKHAK + +; NOW WRITE IT OUT + + MOV CX,0101H +FRML: MOV BX,OFFSET IDTBL + MOV SECCNT,4 +FRMLL: MOV [BX],CH + ADD BX,4 + DEC SECCNT + JNZ FRMLL + + MOV BX,OFFSET IDTBL + MOV DH,0 + MOV DL,BKDSK + PUSH ES + MOV AX,DS + MOV ES,AX + MOV AX,0504H + INT 13H ;ES MUST BE = TO DS FOR FORMAT + POP ES + ADD CH,1 ;PUT CHECK FOR FAILURE HERE + DEC TRKCNT + JNZ FRML + + MOV TRKCNT,3 + MOV BX,0 + MOV CX,0101H + MOV DH,0 + MOV DL,BKDSK +WLP: MOV AX,0304H + INT 13H + ADD BX,1000H + INC CH + DEC TRKCNT + JNZ WLP + + CALL DSKFIX + + MOV TRKCNT,4 ;READ MAX. 96 K (THIS WILL CHANGE) + MOV SECCNT,30H ;START OF GAME +BKUPGL: CALL BKIMST ;GET MASTER BACK INTO DRIVE + MOV DSKDIR,0 ;READ + MOV DSKDRV,0 + MOV AL,SECCNT + SUB AH,AH ;FIRST SECTOR HERE + MOV BX,0 + MOV CX,40H ;GET 32K (64 SECTORS) + CALL GTBKI$ ;READ SOME GAME STUFF + JNC BKUPG1 + JMP BKABRT +BKUPG1: CMP TRKCNT,1 + JNE BKUP2 ;CONTINUE + MOV DSKDIR,1 ;WRITE + MOV DSKDRV,0 + MOV BX,OFFSET BKBUF + MOV CX,1 + MOV BKBUF,1 ;PVERS1=0 + PUSH ES + MOV AX,DS + MOV ES,AX + MOV AX,2EH + CALL GTBKI$ ;FIX SO IT CAN'T BE COPIED + POP ES + JNC BKUP2 + JMP BKABRT +BKUP2: CALL BKICOP ;GET COPY NOW + MOV DSKDIR,1 ;WRITE + MOVM DSKDRV,BKDSK,DL + MOV AL,SECCNT + SUB AH,AH + MOV BX,0 + MOV CX,40H + CALL GTBKI$ ;WRITE SOME GAME STUFF + JNC BKUP2A + JMP BKABRT +BKUP2A: SUB TRKCNT,1 + JZ BKUP3 ;DONE WITH BACKUP + ADD SECCNT,40H + JMP BKUPGL + +BKUP3: PRINT BKDONE + CALL BKIMST ;ENSURE MASTER IN PLACE + MOV MORLIN,0 + RET + +BKABRT: PRINT BKFAIL + CALL BKIMST ;ENSURE MASTER IN PLACE + MOV MORLIN,0 + RET + +BKCHK ENDP + +DSKHAK PROC + MOV DI,DS + MOV SI,OFFSET DSK_PRM + PUSH DS + SUB AX,AX + MOV DS,AX +ASSUME DS:ABS_SG + MOV BX,78H + MOV CX,[BX] + MOV DX,[BX+2] + MOV [BX],SI + MOV [BX+2],DI + POP DS +ASSUME DS:DATA_SG + MOV DSK_SV1,CX + MOV DSK_SV2,DX + RET +DSKHAK ENDP + +DSKFIX PROC + PUSH DS + MOV CX,DSK_SV1 + MOV DX,DSK_SV2 + SUB AX,AX + MOV DS,AX +ASSUME DS:ABS_SG + MOV BX,78H + MOV [BX],CX + MOV [BX+2],DX + POP DS +ASSUME DS:DATA_SG + RET +DSKFIX ENDP + + ;READ THE STATUS BLOCK FROM DISK +BKSTAT PROC + PUSH ES + MOV AX,DS + MOV ES,AX +BKSTRT: MOV DSKDIR,0 ;READ + MOV DSKMOD,1 ;ABSOLUTE SECTORS + MOV AX,2EH ;STATUS SECTOR + MOV BX,OFFSET BKBUF ;READ AT BKBUF (IN DS) + MOV CX,1 ;ONE SECTOR + CALL GTBKI$ ;READ IT + JC BKST1 ;FAILED? + CMP BKFRST,1 + JE BKSEND + MOV DSKDIR,1 ;WRITE + MOV AX,2FH ;RANDOM SPOT + MOV BX,0 + MOV CX,1 + CALL GTBKI$ ;WRITE SOMETHING OR OTHER + JC BKST0 ;LOSER! +BKSEND: MOV BKFRST,0 + POP ES + MOV AL,BKBUF ;GET FIRST BYTE + RET +BKST0: CMP AH,3 ;CHECK SPECIFICALLY FOR WRITE-PROTECT + JNE BKST1 + PRINT BKWPRT ;TELL LOSER ABOUT WRITE PROTECTEDNESS + JMP BKST2 + +BKST1: PRINT BKNRDY ;TELL LOSER DISK ISN`T WINNING +BKST2: CALL .CHRIN ;GET SOME RANDOM CHARACTER + CALL .CRLF + JMP BKSTRT ;TRY, TRY AGAIN + +BKSTAT ENDP + + ;ASK LOSER TO INSERT MASTER DISK, CHECK FOR MASTERHOOD +BKIFST PROC + PRINT BKMC1 + PRINT BKMC2 + PRINT BKMC3 + CALL .CHRIN + CALL .CRLF + CALL BKIMST + CALL BKICOP + RET +BKIFST ENDP + +BKIMST PROC + CMP BKDSK,0 + JNE BKIMS1 +BKIMSR: PRINT BKMAST ;PRINT MESSAGE + CALL .CHRIN ;GET SOME CHARACTER + CALL .CRLF +BKIMS1: MOV DSKDRV,0 + CALL BKSTAT ;GET STATUS FROM DISK, ENSURE NOT W/P + CMP AL,3 + JE BKIMSX ;IT'S NOT A MASTER DISK.... + CMP AL,1 + JE BKIMSX + JMP BKIMSR +BKIMSX: RET +BKIMST ENDP + + ;ASK LOSER TO INSERT COPY DISK, CHECK FOR COPYHOOD +BKICOP PROC + CMP BKDSK,0 + JNE BKICP1 +BKICPR: PRINT BKCOPY ;PRINT MESSAGE + CALL .CHRIN + CALL .CRLF +BKICP1: MOVM DSKDRV,BKDSK,DL + CALL BKSTAT + TEST AL,1 + JNZ BKICPR ;IT'S NOT A COPY DISK.... + RET +BKICOP ENDP + + SUBTTL IBMPC SYSTEM ROUTINES + PAGE + + + ;READ A CHARACTER INTO AX, WAITING UNTIL ONE IS AVAILABLE, NO ECHO +.CHRIN PROC + CMP CHRFLG,0 + JNZ .CHR1$ + MOV CHRFLG,1 + PUSH CX + PUSH DX + SUB AH,AH + INT 1AH ;READ THE SYSTEM TIME AT FIRST CHARACTER + XOR RSEED1,CX ;DO SOME MORE RANDOMIZING + XOR RSEED2,DX ;BE CONSISTENT + POP DX + POP CX +.CHR1$: SUB AH,AH ;SET UP FOR READ NEXT CHARACTER STRUCK + INT 16H ;CALL BIOS KEYBOARD I/O ROUTINE + SUB AH,AH ;CLEAR HIGH BYTE + RET +.CHRIN ENDP + + ;PRINT THE CHARACTER IN AL, FOREGROUND IN AH +.TTYOUT PROC + PUSH AX + PUSH BX ;SAVES + PUSH DX + PUSH BP + PUSH AX + MOV BL,AH ;FOREGROUND + MOV AH,14 ;SET UP FOR TELETYPE OUTPUT + SUB BH,BH ;PAGE 0 + INT 10H ;CALL BIOS DISPLAY I/O ROUTINE + POP AX + CMP SCRFLG,0 + JZ .TYO1$ + CALL PRTOUT +.TYO1$: POP BP ;RESTORES + POP DX + POP BX + POP AX + RET +.TTYOUT ENDP + + ;PRINT THE CHARACTER IN AL, ATTRIBUTES IN AH, ROW IN BH, COLUMN IN BL +.CHROUT PROC + PUSH CX ;SAVES + PUSH DX + PUSH BP + PUSH AX ;SAVE CHARACTER AND ATTRIBUTES + MOV AH,2 ;SET UP FOR SET CURSOR POSITION + MOV DX,BX ;ROW AND COLUMN + SUB BH,BH ;PAGE 0 + INT 10H ;CALL BIOS DISPLAY I/O ROUTINE + POP AX ;RESTORE CHARACTER AND ATTRIBUTES + MOV AH,9 ;SET UP FOR WRITE ATTRIBUTE/CHARACTER + SUB BH,BH ;PAGE 0 + MOV BL,NRMATR ;NORMAL ATTRIBUTES + MOV CX,1 ;WRITE 1 CHARACTER + INT 10H ;CALL BIOS DISPLAY I/O ROUTINE + POP BP ;RESTORES + POP DX + POP CX + RET +.CHROUT ENDP + + ;PRINT SPACES, WITHOUT MOVING CURSOR, NUMBER IN AL, ATTRIBUTE IN AH +.SPACE PROC + PUSH BX ;SAVES + PUSH CX + PUSH BP + MOV BL,AH ;ATTRIBUTE + SUB AH,AH ;CLEAR HIGH BYTE + MOV CX,AX ;NUMBER OF SPACES + MOV AH,9 ;SET UP FOR WRITE ATTRIBUTE/CHARACTER + MOV AL,32 ;WRITE SPACES + SUB BH,BH ;PAGE 0 + MOV BL,NRMATR ;****** THIS SHOULD HELP + INT 10H ;CALL BIOS DISPLAY I/O ROUTINE + POP BP ;RESTORES + POP CX + POP BX + RET +.SPACE ENDP + + ;MOVE TO FIRST COLUMN OF SCREEN BOTTOM +.CRBT PROC + PUSH AX ;SAVES + PUSH BX + PUSH DX + PUSH BP + MOV AH,2 ;SET UP FOR SET CURSOR POSITION + SUB BH,BH ;PAGE 0 + MOV DL,LFTMAR ;MOVE TO FIRST COLUMN + MOV DH,24 ;MOVE TO BOTTOM ROW + INT 10H ;CALL BIOS DISPLAY I/O ROUTINE + POP BP ;RESTORES + POP DX + POP BX + POP AX + RET +.CRBT ENDP + + ;PRINT A CARRIAGE RETURN/LINE FEED, WITH MORE MODE (ASSUMING SCREEN + ;BOTTOM) +.CRLF PROC + PUSH AX ;SAVES + PUSH BX + PUSH CX + PUSH DX + PUSH BP + CMP CURSCR,0 + JE .CRLFN + + CURGET ;HERE FOR SCREEN 1, PUT CURSOR ON NEXT LINE + ADD DH,1 + MOV DL,2 ; ADJUST FOR SONAR IN SEA STALKER + +.CRLF1: CURSET + JMP .CR1$ + +.CRLFN: INC MORLIN ;INCREMENT NUMBER OF LINES OUTPUT + MOV AH,6 ;SET UP FOR SCROLL PAGE UP + MOV AL,1 ;ONE LINE UP + MOV BH,NRMATR ;NORMAL DISPLAY ATTRIBUTE + MOV CL,0 + MOV CH,SCRN0 + MOV DX,TWIDTH + MOV DH,18H ;END AT LINE 24, COLUMN TWIDTH+1 + INT 10H ;CALL BIOS DISPLAY I/O ROUTINE + CALL .CRBT ;MOVE TO BEGINNING OF NEW LINE + MOV AX,MORLIN + CMP AX,LINMAX ;FULL PAGE OUTPUT? + JL .CR1$ ;NOT YET + MOV MORLIN,0 ;RESET COUNTER + MOV AX,OFFSET MORE ;ADDRESS OF MORE MODE PROMPT STRING + MOV BL,USLATR ;INVERSE VIDEO + MOV CH,18H ;STARTING IN ROW 24, COLUMN LFTMAR + MOV CL,LFTMAR + CALL .PRINTA ;PRINT IT WITH ATTRIBUTES + CALL .CHRIN ;READ A CHARACTER TO CONTINUE + CALL .CRBT ;MOVE TO BEGINNING OF NEW LINE + MOV AL,9 ;9 SPACES + MOV AH,NRMATR ;NORMAL DISPLAY + CALL .SPACE ;PRINT THEM (CURSOR UNAFFECTED) +.CR1$: CMP SCRFLG,0 + JE .CR2$ + CALL PRTCRL ;CRLF TO PRINTER +.CR2$: POP BP ;RESTORES + POP DX + POP CX + POP BX + POP AX + RET +.CRLF ENDP + + ;PRINT A STRING, POINTER (TO DATA SEGMENT) IN AX, WHITE FOREGROUND +.PRINT PROC + PUSH BX ;SAVE BX + MOV BX,AX ;STRING POINTER +.PR1$: MOV AL,[BX] ;GET NEXT CHARACTER + CMP AL,0 ;END OF LINE, WITH CRLF? + JE .PR2$ ;YES + CMP AL,80H ;END OF LINE, NO CRLF? + JE .PR3$ ;YES + MOV AH,NRMATR ;WHITE FOREGROUND + CALL .TTYOUT ;PRINT CHARACTER + INC BX ;POINT TO NEXT CHARACTER + JMP .PR1$ ;REPEAT +.PR2$: CALL .CRLF ;PRINT A CRLF +.PR3$: POP BX ;RESTORE BX + RET +.PRINT ENDP + + ;PRINT A STRING, POINTER (TO DATA SEGMENT) IN AX, ATTRIBUTES IN BX, + ;STARTING ROW IN CH, STARTING COLUMN IN CL +.PRINTA PROC + PUSH CX ;SAVE CX + PUSH DX ;SAVE DX + PUSH SI ;SAVE SI + PUSH DI ;SAVE DI + MOV SI,AX ;STRING POINTER + MOV DX,BX ;ATTRIBUTES + MOV DI,CX ;ROW AND COLUMN +.PA1$: MOV AL,[SI] ;GET NEXT CHARACTER + CMP AL,0 ;END OF LINE, WITH CRLF? + JE .PA2$ ;YES + CMP AL,80H ;END OF LINE, NO CRLF? + JE .PA3$ ;YES + MOV AH,DL ;ATTRIBUTES + MOV BX,DI ;ROW AND COLUMN + CALL .CHROUT ;PRINT CHARACTER + INC SI ;POINT TO NEXT CHARACTER + INC DI ;MOVE TO NEXT COLUMN + JMP .PA1$ ;REPEAT +.PA2$: CALL .CRLF ;PRINT A CRLF +.PA3$: POP DI ;RESTORE DI + POP SI ;RESTORE SI + POP DX ;RESTORE DX + POP CX ;RESTORE CX + RET +.PRINTA ENDP + + ;READ AL SECTORS FROM DRIVE AH STARTING AT TRACK CH, SECTOR CL + ;TO MEMORY STARTING AT ES:BX +.RDWRT PROC + PUSH DX ;SAVES + PUSH BP + PUSH SI + CMP FUCK,0 + JE .RDX$ + CMP INIFLG,5 + JNE .RDX$ + CALL PRSPC + MOV AX,BX + CALL PRSPC + MOV AX,CX + CALL PRSPC + CALL .CRLF +.RDX$: MOV BP,4 ;TRY READING 4 TIMES BEFORE FAILING + MOV DL,AH ;DRIVE NUMBER + MOV AH,2 ;SET UP FOR DISK READ + CMP DSKDIR,0 + JE .RD0$ + ADD AH,1 ;WRITE IS CONVENIENTLY 3 +.RD0$: MOV SI,AX ;SAVE SET UP DATA FOR RETRIES + SUB DH,DH ;HEAD 0 +.RD1$: MOV AX,SI ;RESTORE SET UP DATA + INT 13H ;CALL BIOS DISKETTE I/O ROUTINE + JNC .RD2$ ;READ SUCCEEDED + DEC BP ;DECREMENT TRY COUNTER + JNE .RD1$ ;RETRY IF COUNTER NON-ZERO + CMP FUCK,0 + JE .RDFL$ + CMP INIFLG,5 + JNE .RDFL$ + CALL PRSPC + CALL .CRLF +.RDFL$: STC ;INDICATE READ FAILED +.RD2$: POP SI ;RESTORES + POP BP + POP DX + RET +.RDWRT ENDP + + ;GET MEMORY SIZE (IN PARAGRAPHS) +.GETMEM PROC + TEST INIFLG,INIMEM ;CHECK FOR FORCED MEMORY + JZ .GTM1$ + MOV AX,0C00H ;48K (IN PARAGRAPHS) + RET +.GTM1$: INT 12H ;CALL BIOS MEMORY SIZE DETERMINATION ROUTINE + CMP AX,512 ;CHECK FOR >512K + JL .GTMX$ + MOV AX,500 +.GTMX$: SHL AX,1 ;CONVERT FROM K TO PARAGRAPHS + SHL AX,1 + SHL AX,1 + SHL AX,1 + SHL AX,1 + SHL AX,1 + CMP AX,1000H ;MAXIMUM ALLOWED IS 64K (CROCK) + JLE .GTM2$ + MOV AX,1000H +.GTM2$: RET +.GETMEM ENDP + + ;GET TIME +.GETTM PROC + PUSH AX ;SAVES + PUSH CX + PUSH DX + SUB AH,AH ;SET UP FOR READ TIME OF DAY + INT 1AH ;CALL BIOS TIME OF DAY ROUTINE + MOV TIME,CX ;STORE IN VARIABLE + MOV TIME[2],DX + POP DX ;RESTORES + POP CX + POP AX + RET +.GETTM ENDP + +FINISH PROC + CALL .CRLF + PRINT REBOOT + PRINT REBOO1 + CALL .CHRIN ;GET A CHARACTER + INT 19H ;REBOOT +FINISH ENDP + +CODE_SG ENDS + +GAME_SG SEGMENT PAGE AT 800H +GAME_SG ENDS + + END START diff --git a/ibm/ibmziplist.dan b/ibm/ibmziplist.dan new file mode 100644 index 0000000..5e61815 --- /dev/null +++ b/ibm/ibmziplist.dan @@ -0,0 +1,5323 @@ +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + + + .LIST + + TITLE ZIP Z-LANGUAGE INTERPRETER + IBMPC VERSION + + PAGE 58,132 + + SUBTTL STACK AND DATA SEGMENTS INITIALIZATION + + ; CHANGES ON "D" VERSION + ; + ; 1) SPLIT AND SCREEN OPCODES WORK + ; 2) RAGGED SCREEN FIXED + ; 3) DELETE KEY COLOR PROBLEM FIXED + ; 4) PRINTER PROBLEM FIXED + ; 5) COLOR QUESTION ON RESTART FIXED + ; 6) RANDOMNESS BUG FIXED - 06/25/84 - DAN HORN + + + = 0044 ZVERSN EQU "D" ;ZIP VERSION NUMBER + = 0003 ZMVERS EQU 3 ;Z-MACHINE VERSION NUMBER + = 0100 LSTACK EQU 256 ;LENGTH OF USER STACK(MUST BE 1 PAGE FOR NOW) + + 0000 ABS_SG SEGMENT AT 0H + 0000 ABS_SG ENDS + + 0000 STK_SG SEGMENT PARA STACK + 0000 0100 [ DW 100H DUP(?) + ???? + ] + + 0200 STK_TOP LABEL WORD + 0200 0100 [ STKBOT DW LSTACK DUP(?) + ???? + ] + + 0400 ZSTK_TP LABEL WORD + 0400 STK_SG ENDS + + 0000 DATA_SG SEGMENT PARA + + ;VARIBLE DEFINITIONS: + + ;SCREEN COLOR ATTRIBUTES + 0000 07 NRMATR DB 07H ;FOR B/W, NORMAL - IN COLOR, WHITE ON BLUE + 0001 70 USLATR DB 70H ;B/W AND COLOR, BLACK ON WHITE + 0002 07 TYPATR DB 07H ;FOR COLOR, YELLOW ON BLUE/ FOR B&W, ? + 0003 20 20 20 44 6F 20 COLORQ DB " Do you want color (Y/N)? ",80H + 79 6F 75 20 77 61 + 6E 74 20 63 6F 6C + 6F 72 20 28 59 2F + 4E 29 3F 20 80 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STACK AND DATA SEGMENTS INITIALIZATION + + 0020 00 COLFLG DB 0 ;NON ZERO IF THEY WANT COLOR + 0021 0000 OLDCUR DW 0 ; TEMP FOR OLD CURSOR POSITION + ;SCRIPTING STUFF + 0023 00 SCRFLG DB 0 + 0024 20 2A 20 50 72 69 PRNRDY DB " * Printer not ready: Abort or Retry? ",80H + 6E 74 65 72 20 6E + 6F 74 20 72 65 61 + 64 79 3A 20 41 62 + 6F 72 74 20 6F 72 + 20 52 65 74 72 79 + 3F 20 80 + + ;USL STUFF + 004B 00 USLMOD DB 0 ;FOR PUTCHR + 004C 00 PMFLAG DB 0 ;AM/PM + + 004D 0000 SLSTR DW 0 ;TOP OF SCREEN STRING + 004F 0000 SLTAB DW 0 ;TABLE USED BY OPUSL + + 0051 0061 R SLSTAB DW SLS40 + 0053 008B R DW SLS40T + 0055 00E5 R DW SLS80 + 0057 0137 R DW SLS80T + 0059 00A3 R SLTTAB DW SLT40 + 005B 00CD R DW SLT40T + 005D 014F R DW SLT80 + 005F 01A1 R DW SLT80T + + ;40 COLUMN, SCORE + 0061 19 [ SLS40 DB 25 DUP(32),"S:",4 DUP(32),"M:",7 DUP(32),0,80H + 20 + ] + 04 [ 53 3A + 20 + ] + 07 [ 4D 3A + 20 + ] + 00 80 + 008B FFFF SLS40T DW -1 + 008D 0A40 R DW OPPRND + 008F 0002 DW 2 + 0091 0018 DW 24 + 0093 FFFF DW -1 + 0095 09A4 R DW OPPRNN + 0097 001B DW 27 + 0099 001E DW 30 + 009B FFFF DW -1 + 009D 09A4 R DW OPPRNN + 009F 0021 DW 33 + 00A1 0024 DW 36 + + ;40 COLUMN, TIME +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STACK AND DATA SEGMENTS INITIALIZATION + + 00A3 19 [ SLT40 DB 25 DUP(32),"Time:",10 DUP(32),0,80H + 20 + ] + 54 69 + 6D 0A [A + 20 + ] + 00 80 + 00CD FFFF SLT40T DW -1 + 00CF 0A40 R DW OPPRND + 00D1 0002 DW 2 + 00D3 0018 DW 24 + 00D5 FFFF DW -1 + 00D7 09ED R DW OPPRNH + 00D9 001F DW 31 + 00DB 0021 DW 33 + 00DD FFFF DW -1 + 00DF 0A1A R DW OPPRNM + 00E1 0022 DW 34 + 00E3 0027 DW 39 + + ;80 COLUMN, SCORE + 00E5 33 [ SLS80 DB 51 DUP(32),"Score:",8 DUP(32),"Moves:",9 DUP(32),0,80H + 20 + ] + 53 63 + 6F 08 [5 3A + 20 + ] + 4D 6F + 76 09 [3 3A + 20 + ] + 00 80 + 0137 FFFF SLS80T DW -1 + 0139 0A40 R DW OPPRND + 013B 0002 DW 2 + 013D 001B DW 27 + 013F FFFF DW -1 + 0141 09A4 R DW OPPRNN + 0143 003A DW 58 + 0145 003D DW 61 + 0147 FFFF DW -1 + 0149 09A4 R DW OPPRNN + 014B 0049 DW 73 + 014D 004E DW 78 + + ;80 COLUMN, TIME + 014F 3C [ SLT80 DB 60 DUP(32),"Time:",15 DUP(32),0,80H + 20 + ] + 54 69 + 6D 0F [A +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-4 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STACK AND DATA SEGMENTS INITIALIZATION + + 20 + ] + 00 80 + 01A1 FFFF SLT80T DW -1 + 01A3 0A40 R DW OPPRND + 01A5 0002 DW 2 + 01A7 001B DW 27 + 01A9 FFFF DW -1 + 01AB 09ED R DW OPPRNH + 01AD 0045 DW 69 + 01AF 0047 DW 71 + 01B1 FFFF DW -1 + 01B3 0A1A R DW OPPRNM + 01B5 0048 DW 72 + 01B7 004D DW 77 + + ;REBOOT AT END OF GAME + 01B9 20 20 2A 2A 20 45 REBOOT DB " ** End of session **",0 + 6E 64 20 6F 66 20 + 73 65 73 73 69 6F + 6E 20 2A 2A 00 + 01D0 53 74 72 69 6B 65 REBOO1 DB "Strike any key to reboot",0 + 20 61 6E 79 20 6B + 65 79 20 74 6F 20 + 72 65 62 6F 6F 74 + 00 + + ;VERIFY/INTERPRETER VERSION + + 01E9 49 42 4D 2D 50 43 INTMSG DB "IBM-PC Interpreter Version " + 20 49 6E 74 65 72 + 70 72 65 74 65 72 + 20 56 65 72 73 69 + 6F 6E 20 + 0204 44 80 INTVER DB "D",80H + + ;SAVE/RESTORE + 0206 02 NDISKS DB 2 + 0207 00 FUCK DB 0 + + 0208 54 79 70 65 20 62 SRTXT0 DB "Type backspace to abort",80H + 61 63 6B 73 70 61 + 63 65 20 74 6F 20 + 61 62 6F 72 74 80 + 0220 44 69 73 6B 20 64 SRTXT1 DB "Disk drive (A-D) (default = " + 72 69 76 65 20 28 + 41 2D 44 29 20 20 + 28 64 65 66 61 75 + 6C 74 20 3D 20 + 023D 42 SRDRV DB "B" + 023E 29 3A 80 DB "):",80H + 0241 50 6F 73 69 74 69 SRTXT2 DB "Position (0-9) (default = " + 6F 6E 20 20 20 28 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-5 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STACK AND DATA SEGMENTS INITIALIZATION + + 30 2D 39 29 20 20 + 28 64 65 66 61 75 + 6C 74 20 3D 20 + 025E 30 SRPOS DB "0" + 025F 29 3A 80 DB "):",80H + 0262 49 6E 73 65 72 74 SRTXT3 DB "Insert SAVE disk, then hit a key:",80H + 20 53 41 56 45 20 + 64 69 73 6B 2C 20 + 74 68 65 6E 20 68 + 69 74 20 61 20 6B + 65 79 3A 80 + 0284 49 6E 73 65 72 74 SRTXT4 DB "Insert game disk, then hit a key:",80H + 20 67 61 6D 65 20 + 64 69 73 6B 2C 20 + 74 68 65 6E 20 68 + 69 74 20 61 20 6B + 65 79 3A 80 + + ;GTBLKS + 02A6 00 DSKMOD DB 0 ;0 FOR GAME READ, 1 FOR SAVE/RESTORE + 02A7 00 DSKDRV DB 0 ;CURRENT DRIVE + 02A8 00 DSKDIR DB 0 ;0 FOR READ, 1 FOR WRITE + 02A9 0000 GTBCNT DW 0 ;REMAINING BLOCKS TO BE READ + 02AB 0000 GTBSTT DW 0 ;STARTING BLOCK + 02AD 0000 GTBCOR DW 0 ;STARTING CORE ADDRESS + ;OPRAND + 02AF ???? RSEED1 DW ? ;SEED FOR RANDOM NUMBERS + 02B1 ???? RSEED2 DW ? ;SEED TWO + 02B3 ???? RTEMP DW ? ;TEMP FOR RANDOM ROUTINES + ;READ + 02B5 04 [ RDWSTR DW 4 DUP(0) ;WORD STRING BUFFER FOR ZWORD + 0000 + ] + + 02BD 0000 RDBOS DW 0 ;BEGINNING OF STRING POINTER + 02BF 0000 RDEOS DW 0 ;END OF STRING POINTER + 02C1 0000 RDRET DW 0 ;RETURN TABLE POINTER + 02C3 00 RDNWDS DB 0 ;NUMBER OF WORDS READ + ;PUTSTR + 02C4 0000 WRDOFF DW 0 ;OFFSET INTO WORD TABLE FOR CURRENT SET + ;PUTCHR + 02C6 0000 CHRPTR DW 0 ;POINTS TO NEXT CHARACTER POSITION + 02C8 0000 ENDBUF DW 0 ;POINTS JUST PAST END OF OUTPUT BUFFER (0) + ;GETNUM + 02CA 0000 STATUS DW 0 ;STATUS-LINE-REQUESTED FLAG + ;ZIPBGN + 02CC 20 09 0D 0C 2E 2C IRBRKS DB " ",9,13,12,".,?",0 ;INITIAL SET OF READ BREAK CHARS + 3F 00 + 02D4 0000 TWIDTH DW 0 ;TERMINAL WIDTH + 02D6 0000 RWIDTH DW 0 ;REAL TERMINAL WIDTH + 02D8 01 SCRN0 DB 1 ;START OF SCROLLING SCREEN + 02D9 00 CURSCR DB 0 ;CURRENT SCREEN + 02DA 01 LFTMAR DB 1 ;LEFT MARGIN DEFAULT = 1 (2 FOR 80-COLUMN) +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-6 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STACK AND DATA SEGMENTS INITIALIZATION + + 02DB 0000 MEMTOP DW 0 ;LAST AVAILABLE LOCATION + 02DD 0000 TIMEMD DW 0 ;TIME(VERSUS SCORE)-MODE-FOR-STATUS-LINE FLAG + 02DF 0000 ZORKID DW 0 ;UNIQUE GAME & VERSION IDENTIFIER + 02E1 0000 ENDLOD DW 0 ;ENDLOD BLOCK NUMBER + 02E3 0000 VOCTAB DW 0 ;SAVE VOCABULARY TABLE POINTER + 02E5 0000 OBJTAB DW 0 ;OBJECT TABLE POINTER + 02E7 0000 GLOTAB DW 0 ;GLOBAL TABLE POINTER + 02E9 0000 WRDTAB DW 0 ;WORD TABLE POINTER + 02EB 0000 PURBOT DW 0 ;PURE CODE POINTER + 02ED 0000 ESIBKS DW 0 ;END OF SELF-INSERTING BREAK CHARACTERS + 02EF 0000 VWLEN DW 0 ;NUMBER OF BYTES IN A VOCABULARY WORD ENTRY + 02F1 0000 VWORDS DW 0 ;NUMBER OF WORD ENTRIES IN VOCABULARY + 02F3 0000 VOCBEG DW 0 ;BEGINNING OF ACTUAL VOCABULARY + 02F5 0200 [ BKBUF DB 512 DUP(?) ;SCRATCH BUFFER FOR BACKUP + ?? + ] + + 04F5 51 [ OUTBUF DB 81 DUP(?) ;OUTPUT BUFFER + ?? + ] + + 0546 20 [ RBRKS DB 32 DUP(?) ;STRING OF READ BREAK CHARACTERS + ?? + ] + + 0566 40 [ PAGTAB DB 64 DUP(254,0,0,0) ;PAGE INFORMATION TABLE + FE + 00 + 00 + 00 + ] + + 0666 FF DB 255 + 0667 0000 PAGES DW 0 ;SWAPPING AREA + 0669 0000 BUFPGS DW 0 + 066B 00 CHRFLG DB 0 + + 066C 00 INIFLG DB 0 + = 0001 INIWID EQU 1 + = 0002 INIMEM EQU 2 + = 0004 INIRND EQU 4 + + ;RESTRT + 066D 0000 ZLOCS DW 0 ;POINTER TO LOCALS + 066F 0000 ZPC1 DW 0 ;ZPC BLOCK-POINTER + 0671 0000 ZPC2 DW 0 ;ZPC BYTE-POINTER + 0673 04 [ ARGBLK DW 4 DUP(?) ;ARGUMENT BLOCK FOR EXTENDED OPERATIONS + ???? + ] + + ;NEWZPC + 067B 0000 CURPAG DW 0 ;CURRENT PAGE (WHERE ZPC IS) POINTER + 067D 0000 CURBLK DW 0 ;CURRENT BLOCK, USUALLY SAME AS ZPC1 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-7 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STACK AND DATA SEGMENTS INITIALIZATION + + 067F 0000 CURTAB DW 0 ;CURRENT PAGE TABLE POINTER +1 + ;GETPAG + 0681 00 RTIME1 DB 0 ;REFERENCE TIME, 1 1/2 WORDS USED + 0682 0000 RTIME2 DW 0 + 0684 0000 LPAGE DW 0 ;LAST REFERENCED PAGE NUMBER + 0686 0000 LPLOC DW 0 ;AND ITS CORE LOCATION + 0688 0000 LPTAB DW 0 ;AND ITS TABLE POINTER + + + ;BACKUP COPY STUFF + 068A 00 SECCNT DB 0 + 068B 03 TRKCNT DB 3 + 068C 00 BKDSK DB 0 ;DRIVE TO BACKUP ONTO + 068D 01 BKFRST DB 1 + + 068E 59 6F 75 20 6D 61 BKASK1 DB "You may make one backup copy of your",0H + 79 20 6D 61 6B 65 + 20 6F 6E 65 20 62 + 61 63 6B 75 70 20 + 63 6F 70 79 20 6F + 66 20 79 6F 75 72 + 00 + 06B3 67 61 6D 65 2E 20 BKASK2 DB "game. To do so you need a formatted",0H + 54 6F 20 64 6F 20 + 73 6F 20 79 6F 75 + 20 6E 65 65 64 20 + 61 20 66 6F 72 6D + 61 74 74 65 64 00 + 06D7 43 4F 50 59 20 64 BKASK3 DB "COPY disk. Also, neither MASTER",0H + 69 73 6B 2E 20 20 + 41 6C 73 6F 2C 20 + 6E 65 69 74 68 65 + 72 20 4D 41 53 54 + 45 52 00 + 06F8 6E 6F 72 20 43 4F BKASK4 DB "nor COPY disk may be write-protected.",0H + 50 59 20 64 69 73 + 6B 20 6D 61 79 20 + 62 65 20 77 72 69 + 74 65 2D 70 72 6F + 74 65 63 74 65 64 + 2E 00 + 071E 4D 61 6B 65 20 43 BKASK5 DB "Make COPY now? (Y/N) ",80H + 4F 50 59 20 6E 6F + 77 3F 20 28 59 2F + 4E 29 20 80 + 0734 5B 59 45 53 5D 80 BKYEP DB "[YES]",80H + 073A 5B 4E 4F 5D 80 BKNOPE DB "[NO]",80H + 073F 49 6E 73 65 72 74 BKMC1 DB "Insert MASTER disk in drive A",0H + 20 4D 41 53 54 45 + 52 20 64 69 73 6B + 20 69 6E 20 64 72 + 69 76 65 20 41 00 + 075D 49 6E 73 65 72 74 BKMC2 DB "Insert COPY disk in drive B",0H +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-8 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STACK AND DATA SEGMENTS INITIALIZATION + + 20 43 4F 50 59 20 + 64 69 73 6B 20 69 + 6E 20 64 72 69 76 + 65 20 42 00 + 0779 48 69 74 20 61 6E BKMC3 DB "Hit any key to start backup",80H + 79 20 6B 65 79 20 + 74 6F 20 73 74 61 + 72 74 20 62 61 63 + 6B 75 70 80 + 0795 49 6E 73 65 72 74 BKMAST DB "Insert MASTER disk; hit any key",80H + 20 4D 41 53 54 45 + 52 20 64 69 73 6B + 3B 20 68 69 74 20 + 61 6E 79 20 6B 65 + 79 80 + 07B5 49 6E 73 65 72 74 BKCOPY DB "Insert COPY disk; hit any key",80H + 20 43 4F 50 59 20 + 64 69 73 6B 3B 20 + 68 69 74 20 61 6E + 79 20 6B 65 79 80 + 07D3 44 69 73 6B 20 77 BKWPRT DB "Disk write-protected; hit any key",80H + 72 69 74 65 2D 70 + 72 6F 74 65 63 74 + 65 64 3B 20 68 69 + 74 20 61 6E 79 20 + 6B 65 79 80 + 07F5 44 69 73 6B 20 65 BKNRDY DB "Disk error; hit any key",80H + 72 72 6F 72 3B 20 + 68 69 74 20 61 6E + 79 20 6B 65 79 80 + 080D 42 61 63 6B 75 70 BKDONE DB "Backup completed.",0H + 20 63 6F 6D 70 6C + 65 74 65 64 2E 00 + 081F 44 69 73 6B 20 65 BKFAIL DB "Disk error; backup aborted.",0H + 72 72 6F 72 3B 20 + 62 61 63 6B 75 70 + 20 61 62 6F 72 74 + 65 64 2E 00 + 083B 50 6C 65 61 73 65 BKWPS1 DB "Please write-protect the disk in",0H + 20 77 72 69 74 65 + 2D 70 72 6F 74 65 + 63 74 20 74 68 65 + 20 64 69 73 6B 20 + 69 6E 00 + 085C 64 72 69 76 65 20 BKWPS2 DB "drive A; hit any key",80H + 41 3B 20 68 69 74 + 20 61 6E 79 20 6B + 65 79 80 + 0871 0000 DSK_SV1 DW 0 + 0873 0000 DSK_SV2 DW 0 + + 0875 CF DSK_PRM DB 11001111B + 0876 02 DB 2 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-9 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STACK AND DATA SEGMENTS INITIALIZATION + + 0877 25 DB 37 + 0878 03 DB 3 + 0879 04 DB 4 + 087A 2A DB 02AH + 087B FF DB 0FFH + 087C 50 DB 050H + 087D F6 DB 0F6H + 087E 19 DB 25 + 087F 04 DB 4 + + 0880 01 00 01 03 IDTBL DB 1,0,1,3 + 0884 01 00 02 03 DB 1,0,2,3 + 0888 01 00 03 03 DB 1,0,3,3 + 088C 01 00 04 03 DB 1,0,4,3 + + ;OPERATION TABLES: + ;ZERO ARGUMENT OPERATIONS + 0890 0B03 R ZEROOP DW OPRTRU ;176 + 0892 0B08 R DW OPRFAL ;177 + 0894 0A55 R DW OPPRNI ;178 + 0896 0A69 R DW OPPRNR ;179 + 0898 0B25 R DW OPNOOP ;180 + 089A 0083 R DW OPSAVE ;181 + 089C 007B R DW OPREST ;182 + 089E 01D5 R DW OPRSTT ;183 + 08A0 0B18 R DW OPRSTA ;184 + 08A2 0B1F R DW OPFSTA ;185 + 08A4 01E9 R DW OPQUIT ;186 + 08A6 0A72 R DW OPCRLF ;187 + 08A8 02A4 R DW OPUSL ;188 + 08AA 001F R DW OPVERI ;189 + 08AC 0000 DW 0 ;190 + 08AE 0000 DW 0 ;191 + ;ONE ARGUMENT OPERATIONS + 08B0 03B3 R ONEOP DW OPQZER ;128 + 08B2 04C4 R DW OPQNEX ;129 + 08B4 04AC R DW OPQFIR ;130 + 08B6 04A0 R DW OPLOC ;131 + 08B8 062E R DW OPPTSI ;132 + 08BA 0657 R DW OPINC ;133 + 08BC 0664 R DW OPDEC ;134 + 08BE 09E7 R DW OPPRNB ;135 + 08C0 0000 DW 0 ;136 + 08C2 03E9 R DW OPREMO ;137 + 08C4 0A40 R DW OPPRND ;138 + 08C6 0ADA R DW OPRETU ;139 + 08C8 0B0C R DW OPJUMP ;140 + 08CA 09E1 R DW OPPRIN ;141 + 08CC 0640 R DW OPVALU ;142 + 08CE 0382 R DW OPBCOM ;143 + ;TWO ARGUMENT AND EXTENDED ARGUMENT OPERATIONS + 08D0 0000 EXTOP DW 0 ;0 + 08D2 038C R DW OPQEQU ;1 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-10 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STACK AND DATA SEGMENTS INITIALIZATION + + 08D4 0365 R DW OPQLES ;2 + 08D6 036F R DW OPQGRT ;3 + 08D8 0689 R DW OPQDLE ;4 + 08DA 066C R DW OPQIGR ;5 + 08DC 04D8 R DW OPQIN ;6 + 08DE 0375 R DW OPBTST ;7 + 08E0 037D R DW OPBOR ;8 + 08E2 0387 R DW OPBAND ;9 + 08E4 0435 R DW OPQFSE ;10 + 08E6 045A R DW OPFSET ;11 + 08E8 047D R DW OPFCLE ;12 + 08EA 0646 R DW OPSET ;13 + 08EC 03BE R DW OPMOVE ;14 + 08EE 05CF R DW OPGET ;15 + 08F0 05DE R DW OPGETB ;16 + 08F2 04E4 R DW OPGETP ;17 + 08F4 05FB R DW OPGTPT ;18 + 08F6 0585 R DW OPNEXT ;19 + 08F8 030A R DW OPADD ;20 + 08FA 030F R DW OPSUB ;21 + 08FC 0314 R DW OPMUL ;22 + 08FE 0319 R DW OPDIV ;23 + 0900 031F R DW OPMOD ;24 + 0902 0000 DW 0 ;25 + 0904 0000 DW 0 ;26 + 0906 0000 DW 0 ;27 + 0908 0000 DW 0 ;28 + 090A 0000 DW 0 ;29 + 090C 0000 DW 0 ;30 + 090E 0000 DW 0 ;31 + 0910 0A75 R DW OPCALL ;224 + 0912 05EB R DW OPPUT ;225 + 0914 05F5 R DW OPPUTB ;226 + 0916 0531 R DW OPPUTP ;227 + 0918 081E R DW OPREAD ;228 + 091A 09A1 R DW OPPRNC ;229 + 091C 09A4 R DW OPPRNN ;230 + 091E 0327 R DW OPRAND ;231 + 0920 0649 R DW OPPUSH ;232 + 0922 064F R DW OPPOP ;233 + 0924 0243 R DW OPSPLT ;234 + 0926 01EC R DW OPSCRN ;235 + 0928 0000 DW 0 ;236 + 092A 0000 DW 0 ;237 + 092C 0000 DW 0 ;238 + 092E 0000 DW 0 ;239 + 0930 0000 DW 0 ;240 + 0932 0000 DW 0 ;241 + 0934 0000 DW 0 ;242 + 0936 0000 DW 0 ;243 + 0938 0000 DW 0 ;244 + 093A 0000 DW 0 ;245 + 093C 0000 DW 0 ;246 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-11 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STACK AND DATA SEGMENTS INITIALIZATION + + 093E 0000 DW 0 ;247 + 0940 0000 DW 0 ;248 + 0942 0000 DW 0 ;249 + 0944 0000 DW 0 ;250 + 0946 0000 DW 0 ;251 + 0948 0000 DW 0 ;252 + 094A 0000 DW 0 ;253 + 094C 0000 DW 0 ;254 + 094E 0000 DW 0 ;255 + ;.CRLF + 0950 2A 2A 4D 4F 52 45 MORE DB "**MORE** ",80H + 2A 2A 20 80 + 095A 0000 MORLIN DW 0 + 095C 0017 LINMAX DW 23 + = 0017 LINMXX EQU 23 + + ;.GETTM + 095E ???????? TIME DD ? + + ;STRUCTURE AND RECORD DEFINITIONS: + ;OBJECT OPERATIONS + OBJECT STRUC + 0000 ???? FLAGS1 DW ? + 0002 ???? FLAGS2 DW ? + 0004 ?? PARENT DB ? + 0005 ?? SIBLING DB ? + 0006 ?? CHILD1 DB ? + 0007 ???? PROPS DW ? + 0009 OBJECT ENDS + PROPID RECORD PROPSIZE:3,PROPNUM:5 + + ;STRING DEFINITIONS + + ;READ + 0962 54 6F 6F 20 6D 61 ERR2 DB "Too many words typed, flushing: ",80H + 6E 79 20 77 6F 72 + 64 73 20 74 79 70 + 65 64 2C 20 66 6C + 75 73 68 69 6E 67 + 3A 20 80 + + ;OPNEXT/OPPUTP + 0983 4E 6F 20 73 75 63 FTL2 DB "No such property",0 + 68 20 70 72 6F 70 + 65 72 74 79 00 + ;ZIPBGN + 0994 57 72 6F 6E 67 20 FTL4 DB "Wrong game or version",0 + 67 61 6D 65 20 6F + 72 20 76 65 72 73 + 69 6F 6E 00 + ;NXTINS + 09AA 49 6C 6C 65 67 61 FTL5 DB "Illegal operation",0 + 6C 20 6F 70 65 72 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 1-12 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STACK AND DATA SEGMENTS INITIALIZATION + + 61 74 69 6F 6E 00 + ;FINDPG + 09BC 4E 6F 20 66 72 65 FTL6 DB "No free pages",0 + 65 20 70 61 67 65 + 73 00 + ;GTBLKS + 09CA 47 61 6D 65 20 66 FTL7 DB "Game file read error",0 + 69 6C 65 20 72 65 + 61 64 20 65 72 72 + 6F 72 00 + ;Fatal error header + 09DF 46 61 74 61 6C 20 FATHDR DB "Fatal error: ",80H + 65 72 72 6F 72 3A + 20 80 + ;ZSTR CHARACTER CONVERSION VECTOR + + 09ED 61 62 63 64 65 66 ZCHRS DB "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + 67 68 69 6A 6B 6C + 6D 6E 6F 70 71 72 + 73 74 75 76 77 78 + 79 7A 41 42 43 44 + 45 46 47 48 49 4A + 4B 4C 4D 4E 4F 50 + 51 52 53 54 55 56 + 57 58 59 5A + 0A21 20 20 30 31 32 33 DB " 0123456789.,!?_#'" + 34 35 36 37 38 39 + 2E 2C 21 3F 5F 23 + 27 + 0A34 22 2F 5C 2D 3A 28 DB '"/\-:()' + 29 + 0A3B DATA_SG ENDS + + SUBTTL MACROS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 2-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + MACROS + + PAGE + + + GTAWRD MACRO D,S ;;GET ABSOLUTE WORD + MOV D&X,ES:&S + XCHG D&H,D&L + ENDM + + PTAWRD MACRO D,S ;;PUT ABSOLUTE WORK + XCHG S&H,S&L + MOV ES:&D,S&X + ENDM + + MOVM MACRO D,S,R ;;MOVE MEMORY TO MEMORY + MOV R,S + MOV D,R + ENDM + + PUSHZ MACRO S ;;PUSH ONTO Z STACK + XCHG SP,DI + PUSH S + XCHG SP,DI + ENDM + + POPZ MACRO D ;;POP FROM Z STACK + XCHG SP,DI + POP D + XCHG SP,DI + ENDM + + POPZT MACRO D ;;GET TOP OF Z STACK + MOV D,SS:[DI] + ENDM + + PUSHZT MACRO S ;;PUT TOP OF Z STACK + MOV SS:[DI],S + ENDM + + PRINT MACRO STR ;;PRINT A STRING, POINTER IS ARGUMENT + PUSH AX + MOV AX,OFFSET STR + CALL .PRINT + POP AX + ENDM + + FATAL MACRO ERR ;;PRINT FATAL ERROR AND DIE + CALL .CRLF + MOV AX,OFFSET FATHDR + CALL .PRINT + MOV AX,OFFSET ERR + CALL .PRINT + JMP FINISH + ENDM + +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 2-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + MACROS + + CURGET MACRO + PUSH AX + SUB BH,BH + MOV AH,3 + INT 10H + POP AX + ENDM + + CURSET MACRO POS + PUSH AX + SUB BH,BH + MOV AH,2 + IFNB + MOV DX,POS + ENDIF + INT 10H + POP AX + ENDM + + SUBTTL SYSTEM INITIALIZATION +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 3-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + SYSTEM INITIALIZATION + + PAGE + + + 0000 CODE_SG SEGMENT PARA + ASSUME CS:CODE_SG,DS:DATA_SG,ES:GAME_SG,SS:STK_SG + + 0000 START PROC FAR + + ;NEVER, EVEN FOR AN INSTANT, CONSIDER CHANGING THESE NEXT INSTRUCTIONS + ;THE GAME CREATOR MODIFIES THEM AND THEY MUST REMAIN HERE + + MOVM DS,DATA_SG,AX + 0000 B8 ---- R + MOV AX,DATA_SG + 0003 8E D8 + MOV DS,AX + MOVM ES,GAME_SG,AX + 0005 B8 ---- R + MOV AX,GAME_SG + 0008 8E C0 + MOV ES,AX + MOVM SS,STK_SG,AX + 000A B8 ---- R + MOV AX,STK_SG + 000D 8E D0 + MOV SS,AX + + ;END OF MAGIC SECTION. HACK AND SLASH TO YOUR HEART'S CONTENT + + 000F BC 0200 R MOV SP,OFFSET STK_TOP + 0012 BF 0400 R MOV DI,OFFSET ZSTK_TP + 0015 E9 0F6A R JMP ZIPBGN ;JUMP TO BEGINNING OF ZIP CODE + 0018 START ENDP + + 0018 FEEP PROC + 0018 B8 0007 MOV AX,7 + 001B E8 1887 R CALL .TTYOUT ;BELL + 001E C3 RET + 001F FEEP ENDP + + 001F OPVERI PROC + PRINT INTMSG + 001F 50 + PUSH AX + 0020 B8 01E9 R + MOV AX,OFFSET INTMSG + 0023 E8 196F R + CALL .PRINT + 0026 58 + POP AX + 0027 E8 18F0 R CALL .CRLF + 002A 26: A1 001A MOV AX,ES:[PLENTH] + 002E 86 E0 XCHG AH,AL + 0030 56 PUSH SI + 0031 57 PUSH DI + 0032 FF 36 02E1 R PUSH ENDLOD + 0036 E8 0C6B R CALL BSPLIT + 0039 8B F0 MOV SI,AX + 003B 8B FB MOV DI,BX + 003D B8 0000 MOV AX,0 + 0040 BB 0040 MOV BX,64 + 0043 BA 0000 MOV DX,0 + 0046 C7 06 02E1 R 0000 MOV ENDLOD,0 + 004C 56 OPVR1: PUSH SI +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 3-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + SYSTEM INITIALIZATION + + 004D 57 PUSH DI + 004E 52 PUSH DX + 004F E8 0B26 R CALL GETBYT + 0052 5A POP DX + 0053 5F POP DI + 0054 5E POP SI + 0055 03 D1 ADD DX,CX + 0057 83 FB 00 CMP BX,0 + 005A 75 01 JNZ OPVX + 005C 90 NOP + 005D 3B C6 OPVX: CMP AX,SI + 005F 75 EB JNE OPVR1 + 0061 3B DF CMP BX,DI + 0063 75 E7 JNE OPVR1 + 0065 26: A1 001C MOV AX,ES:[PCHKSM] + 0069 86 E0 XCHG AH,AL + 006B 8F 06 02E1 R POP ENDLOD + 006F 5F POP DI + 0070 5E POP SI + 0071 3B C2 CMP AX,DX + 0073 74 03 JE OPVR2 + 0075 E9 0C12 R JMP PFALSE + 0078 E9 0C17 R OPVR2: JMP PTRUE + 007B OPVERI ENDP + + 007B OPREST PROC + 007B C6 06 02A8 R 00 MOV DSKDIR,0 ;INDICATE RESTORE + 0080 EB 06 90 JMP OSV0$ + 0083 OPREST ENDP + + 0083 OPSAVE PROC + 0083 C6 06 02A8 R 01 MOV DSKDIR,1 ;INDICATE WRITE + 0088 OSV0$: PRINT SRTXT0 ;WRITE "TYPE BACKSPACE..." + 0088 50 + PUSH AX + 0089 B8 0208 R + MOV AX,OFFSET SRTXT0 + 008C E8 196F R + CALL .PRINT + 008F 58 + POP AX + 0090 E8 18F0 R CALL .CRLF + PRINT SRTXT2 ;WRITE "POSITION (DEFAULT = X): " + 0093 50 + PUSH AX + 0094 B8 0241 R + MOV AX,OFFSET SRTXT2 + 0097 E8 196F R + CALL .PRINT + 009A 58 + POP AX + 009B E8 1864 R OSV2A$: CALL .CHRIN + 009E 3C 0D CMP AL,13 + 00A0 75 03 JNE OSV3$ + 00A2 A0 025E R MOV AL,SRPOS ;GET DEFAULT POSITION + 00A5 8A D8 OSV3$: MOV BL,AL + 00A7 3C 08 CMP AL,8 + 00A9 75 06 JNE OSV3X$ + 00AB E8 18F0 R CALL .CRLF + 00AE E9 0C12 R JMP PFALSE + 00B1 2C 30 OSV3X$: SUB AL,"0" +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 3-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + SYSTEM INITIALIZATION + + 00B3 3C 09 CMP AL,9 + 00B5 7F 04 JG OSV3A$ + 00B7 3C 00 CMP AL,0 + 00B9 7D 05 JGE OSV3B$ + 00BB E8 0018 R OSV3A$: CALL FEEP + 00BE EB DB JMP OSV2A$ + 00C0 88 1E 025E R OSV3B$: MOV SRPOS,BL + 00C4 8A C3 MOV AL,BL + 00C6 8A 26 0000 R MOV AH,NRMATR + 00CA E8 1887 R CALL .TTYOUT + 00CD E8 18F0 R CALL .CRLF + PRINT SRTXT1 ;WRITE "DRIVE (DEFAULT = X): " + 00D0 50 + PUSH AX + 00D1 B8 0220 R + MOV AX,OFFSET SRTXT1 + 00D4 E8 196F R + CALL .PRINT + 00D7 58 + POP AX + 00D8 E8 1864 R OSV0A$: CALL .CHRIN + 00DB 3C 0D CMP AL,13 + 00DD 75 03 JNE OSV1$ + 00DF A0 023D R MOV AL,SRDRV ;GET DEFAULT DRIVE + 00E2 3C 08 OSV1$: CMP AL,8 + 00E4 75 06 JNE OSAB1$ + 00E6 E8 18F0 R CALL .CRLF + 00E9 E9 0C12 R JMP PFALSE + 00EC 3C 61 OSAB1$: CMP AL,"a" + 00EE 7C 02 JL OSAB2$ + 00F0 2C 20 SUB AL,32 ;UPPERCASE DRIVE LETTERS + 00F2 8A D8 OSAB2$: MOV BL,AL + 00F4 2C 41 SUB AL,"A" ;GET DOWN TO BASICS + 00F6 3C 03 CMP AL,3 + 00F8 7F 04 JG OSV1A$ ;LOSING DRIVE NUMBER + 00FA 3C 00 CMP AL,0 + 00FC 7D 05 JGE OSV1B$ + 00FE E8 0018 R OSV1A$: CALL FEEP ;EXPRESS DISPLEASURE + 0101 EB D5 JMP OSV0A$ + 0103 88 1E 023D R OSV1B$: MOV SRDRV,BL + 0107 8A C3 MOV AL,BL + 0109 8A 26 0000 R MOV AH,NRMATR + 010D E8 1887 R CALL .TTYOUT ;ECHO THE DRIVE LETTER + 0110 E8 18F0 R CALL .CRLF + PRINT SRTXT3 ;WRITE "Insert save disk..." + 0113 50 + PUSH AX + 0114 B8 0262 R + MOV AX,OFFSET SRTXT3 + 0117 E8 196F R + CALL .PRINT + 011A 58 + POP AX + 011B E8 1864 R CALL .CHRIN + 011E 3C 08 CMP AL,8 ;ABORT REQUESTED? + 0120 75 06 JNE OSV3Z$ + 0122 E8 18F0 R CALL .CRLF + 0125 E9 0C12 R JMP PFALSE + 0128 A0 025E R OSV3Z$: MOV AL,SRPOS ;GET POSITION + 012B 2C 30 SUB AL,"0" + 012D 2A E4 SUB AH,AH +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 3-4 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + SYSTEM INITIALIZATION + + 012F 8A 1E 023D R MOV BL,SRDRV + 0133 80 EB 41 SUB BL,"A" + 0136 88 1E 02A7 R MOV DSKDRV,BL + 013A 87 FC XCHG DI,SP + 013C FF 36 066F R PUSH ZPC1 + 0140 FF 36 0671 R PUSH ZPC2 + 0144 FF 36 066D R PUSH ZLOCS + 0148 FF 36 02DF R PUSH ZORKID + 014C 36: 89 26 0200 R MOV STKBOT,SP ;SAVE THE WORLD + 0151 8B E7 MOV SP,DI + 0153 B1 05 MOV CL,5 + 0155 D3 E0 SHL AX,CL ;CHANGE TO BLOCK + 0157 50 PUSH AX ;SAVE STARTING BLOCK # + 0158 06 PUSH ES ;SAVE ES + 0159 8C D2 MOV DX,SS + 015B 8E C2 MOV ES,DX ;FAKE ES TO BE STACK SEGMENT + 015D BB 0200 R MOV BX,OFFSET STKBOT + 0160 B9 0001 MOV CX,1 + 0163 E8 1484 R CALL SRBLKS ;READ/WRITE STACK + 0166 9C PUSHF + 0167 8B FC MOV DI,SP ;SAVE SP + 0169 36: 8B 26 0200 R MOV SP,STKBOT ;RETRIEVE SAVED USER STACK POINTER + 016E 58 POP AX + 016F 3B 06 02DF R CMP AX,ZORKID ;CHECK GAME VERSIONS + 0173 74 12 JE OSVT0$ + FATAL FTL4 + 0175 E8 18F0 R + CALL .CRLF + 0178 B8 09DF R + MOV AX,OFFSET FATHDR + 017B E8 196F R + CALL .PRINT + 017E B8 0994 R + MOV AX,OFFSET FTL4 + 0181 E8 196F R + CALL .PRINT + 0184 E9 1A47 R + JMP FINISH + 0187 8F 06 066D R OSVT0$: POP ZLOCS + 018B 8F 06 0671 R POP ZPC2 + 018F 8F 06 066F R POP ZPC1 + 0193 87 FC XCHG DI,SP + 0195 9D POPF + 0196 07 POP ES + 0197 58 POP AX + 0198 72 35 JC OSV4$ ;DIE HERE IF FIRST READ/WRITE FAILED + 019A 40 INC AX ;NEXT BLOCK STARTS + 019B 2B DB SUB BX,BX ;START AT ES:0 + 019D 8B 0E 02EB R MOV CX,PURBOT ;NUMBER OF PURE BLOCKS + 01A1 E8 1484 R CALL SRBLKS + 01A4 9C PUSHF ;SAVE FLAGS FROM CALL + 01A5 E8 18F0 R CALL .CRLF + 01A8 80 3E 02A7 R 00 CMP DSKDRV,0 ;CHECK FOR DRIVE 0 + 01AD 75 0E JNZ OSV3C$ + PRINT SRTXT4 ;WRITE "Insert game disk..." + 01AF 50 + PUSH AX + 01B0 B8 0284 R + MOV AX,OFFSET SRTXT4 + 01B3 E8 196F R + CALL .PRINT + 01B6 58 + POP AX +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 3-5 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + SYSTEM INITIALIZATION + + 01B7 E8 1864 R CALL .CHRIN ;WAIT UNTIL READY + 01BA E8 18F0 R CALL .CRLF + 01BD E8 1245 R OSV3C$: CALL NEWZPC ;PAGE MAY HAVE CHANGED, LOSER! + 01C0 9D POPF ;GET FLAGS BACK + 01C1 72 0C JC OSV4$ + 01C3 A0 0023 R MOV AL,SCRFLG ;GET CURRENT SCRIPT STATE + PTAWRD [PFLAGS],A ;AND MAKE RESTORED FLAGS REFLECT IT + 01C6 86 E0 + XCHG AH,AL + 01C8 26: A3 0010 + MOV ES:[PFLAGS],AX + 01CC E9 0C17 R JMP PTRUE + 01CF E8 18F0 R OSV4$: CALL .CRLF + 01D2 E9 0C12 R JMP PFALSE + 01D5 OPSAVE ENDP + + 01D5 OPRSTT PROC + 01D5 8B 2E 02C6 R MOV BP,CHRPTR + 01D9 3E: C6 46 00 00 MOV BYTE PTR DS:[BP],0 ;FORCE OUT THE BUFFER + PRINT OUTBUF + 01DE 50 + PUSH AX + 01DF B8 04F5 R + MOV AX,OFFSET OUTBUF + 01E2 E8 196F R + CALL .PRINT + 01E5 58 + POP AX + 01E6 E9 10C2 R JMP RESTRT ;JUMP TO RESTART ADDRESS + 01E9 OPRSTT ENDP + + 01E9 OPQUIT PROC + 01E9 E9 1A47 R JMP FINISH + 01EC OPQUIT ENDP + + 01EC OPSCRN PROC + 01EC 2A E4 SUB AH,AH ; ONLY HAVE LOWER BYTE + 01EE A2 02D9 R MOV CURSCR,AL ; put screen # into current screen + 01F1 3D 0000 CMP AX,0 ; was it 0 + 01F4 75 1B JNE OPSCR1 ; no then test #1 + 01F6 8B 16 0021 R MOV DX,OLDCUR ; save old cursor position + 01FA 80 3E 0020 R 00 CMP COLFLG,0 ; TEST IF COLOR ON + 01FF 74 08 JZ DIP1 + 0201 C6 06 0000 R 17 MOV NRMATR,17H ; give them color + 0206 EB 34 90 JMP OPSCR2 + 0209 C6 06 0000 R 07 DIP1: MOV NRMATR,07H ; GIVE THEN NOTHING + 020E EB 2C 90 JMP OPSCR2 + + 0211 3D 0001 OPSCR1: CMP AX,1 ; was it 1 + 0214 75 2C JNE OPSCR3 + CURGET + 0216 50 + PUSH AX + 0217 2A FF + SUB BH,BH + 0219 B4 03 + MOV AH,3 + 021B CD 10 + INT 10H + 021D 58 + POP AX + 021E 89 16 0021 R MOV OLDCUR,DX ; no then ignore + 0222 80 3E 0020 R 00 CMP COLFLG,0 ; TEST IF COLOR ON + 0227 74 08 JZ DIP3 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 3-6 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + SYSTEM INITIALIZATION + + 0229 C6 06 0000 R 75 MOV NRMATR,75H ; give them color + 022E EB 06 90 JMP DIP4 + + 0231 C6 06 0000 R 07 DIP3: MOV NRMATR,07H ; GIVE THEM NOTHING + 0236 B6 01 DIP4: MOV DH,1 ; put it at 1,1 + 0238 8A 16 02DA R MOV DL,LFTMAR ; UPPER LEFT-HAND CORNER + 023C B4 02 OPSCR2: MOV AH,2 ; set cursor + 023E B7 00 MOV BH,0 ; graphics page + 0240 CD 10 INT 10H + 0242 C3 OPSCR3: RET + 0243 OPSCRN ENDP + + 0243 OPSPLT PROC + 0243 3D 0000 CMP AX,0 ; split zero + 0246 74 4A JE OPSPLU + CURGET + 0248 50 + PUSH AX + 0249 2A FF + SUB BH,BH + 024B B4 03 + MOV AH,3 + 024D CD 10 + INT 10H + 024F 58 + POP AX + 0250 89 16 0021 R MOV OLDCUR,DX + 0254 29 06 095C R SUB LINMAX,AX ; subtract max plus one + 0258 05 0001 ADD AX,1 + 025B A2 02D8 R MOV SCRN0,AL ; USED IN SCROLL FOR CRLF + 025E 8A 0E 02DA R MOV CL,LFTMAR + 0262 B5 01 MOV CH,01 ; UPPER LEFT CORNER + 0264 8B 16 02D6 R MOV DX,RWIDTH ; LOWER RIGHT ROW + 0268 2A 16 02DA R SUB DL,LFTMAR + 026C 80 EA 01 SUB DL,1 + 026F 8A 36 02D8 R MOV DH,SCRN0 ; LOWER RIGHT COLUMN + 0273 B0 00 MOV AL,0 ; blank entire screen + 0275 B4 06 MOV AH,6 ; clear the screen + 0277 80 3E 0020 R 00 CMP COLFLG,0 ; IS IT COLOR? + 027C 74 05 JZ DAN1 + 027E B7 2F MOV BH,2FH ; WHITE ON GREEN + 0280 EB 03 90 JMP DAN2 + 0283 B7 07 DAN1: MOV BH,07H ; IF NO COLOR THEN BLACK ON WHITE + 0285 CD 10 DAN2: INT 10H ; CLEAR TOP WINDOW + 0287 8B 16 0021 R MOV DX,OLDCUR ; GET BACK CURSOR POSITION + 028B B4 02 MOV AH,2 ; set cursor + 028D 2A FF SUB BH,BH ; make sure it's zero + 028F CD 10 INT 10H + 0291 C3 RET + + 0292 C6 06 02D8 R 01 OPSPLU: MOV SCRN0,1 + 0297 B8 0017 MOV AX,LINMXX + 029A A3 095C R MOV LINMAX,AX + 029D C7 06 095A R 0000 MOV MORLIN,0 ;RESET MORE COUNT + 02A3 C3 RET + 02A4 OPSPLT ENDP + + 02A4 OPUSL PROC +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 3-7 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + SYSTEM INITIALIZATION + + 02A4 57 PUSH DI + 02A5 C6 06 004B R 01 MOV USLMOD,1 + CURGET ;GET THE CURSOR LOCATION + 02AA 50 + PUSH AX + 02AB 2A FF + SUB BH,BH + 02AD B4 03 + MOV AH,3 + 02AF CD 10 + INT 10H + 02B1 58 + POP AX + 02B2 52 PUSH DX ;SAVE IT FOR A RAINY DAY + 02B3 B8 0010 MOV AX,16 ;FIRST GLOBAL (ROOM) + 02B6 8B 3E 004F R MOV DI,SLTAB ;USL TABLE IN FORCE + 02BA B9 0003 MOV CX,3 ;NUMBER OF THINGS WE PRINT + 02BD 50 USLLP$: PUSH AX + 02BE E8 0BA0 R CALL GETVAR ;GET THE GLOBAL + 02C1 3B 05 CMP AX,[DI] ;HAS IT CHANGED + 02C3 74 2F JE USL1$ ;THANK GOD, NO + CURSET [DI+4] ;MOVE THE CURSOR TO THE RIGHT PLACE + 02C5 50 + PUSH AX + 02C6 2A FF + SUB BH,BH + 02C8 B4 02 + MOV AH,2 + 02CA 8B 55 04 + MOV DX,[DI+4] + 02CD CD 10 + INT 10H + 02CF 58 + POP AX + 02D0 51 PUSH CX + 02D1 57 PUSH DI + 02D2 FF 55 02 CALL WORD PTR [DI+2] ;CALL THE PROPER ROUTINE + CURGET ;WHERE IS THE CURSOR NOW? + 02D5 50 + PUSH AX + 02D6 2A FF + SUB BH,BH + 02D8 B4 03 + MOV AH,3 + 02DA CD 10 + INT 10H + 02DC 58 + POP AX + 02DD 5F POP DI + 02DE 2B 55 06 SUB DX,[DI+6] ;WHERE IS THE END OF THE FIELD? + 02E1 F7 DA NEG DX + 02E3 7E 0B JLE USLN$ ;DONT PRINT ZERO OR LESS SPACES + 02E5 8A C2 MOV AL,DL + 02E7 8A 26 0001 R MOV AH,USLATR ;THIS IS REVERSE VIDEO + 02EB 57 PUSH DI + 02EC E8 18C2 R CALL .SPACE ;PRINT THAT MANY SPACES + 02EF 5F POP DI + 02F0 83 C7 08 USLN$: ADD DI,8 ;POINT TO NEXT TABLE ENTRY + 02F3 59 POP CX ;RESTORE REGISTERS + 02F4 58 USL1$: POP AX + 02F5 40 INC AX ;POINT TO NEXT GLOBAL + 02F6 E2 C5 LOOP USLLP$ ;DO ALL THREE THEN LEAVE + 02F8 5A POP DX + CURSET DX ;IT MAY OR MAY NOT BE RAINING, BUT.... + 02F9 50 + PUSH AX + 02FA 2A FF + SUB BH,BH + 02FC B4 02 + MOV AH,2 + 02FE 8B D2 + MOV DX,DX + 0300 CD 10 + INT 10H +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 3-8 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + SYSTEM INITIALIZATION + + 0302 58 + POP AX + 0303 C6 06 004B R 00 MOV USLMOD,0 + 0308 5F POP DI + 0309 C3 RET + 030A OPUSL ENDP + + SUBTTL ARITHMETIC OPERATIONS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 4-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + ARITHMETIC OPERATIONS + + PAGE + + + ;ADD + 030A OPADD PROC + 030A 03 C3 ADD AX,BX ;ADD OPR1 AND OPR2 + 030C E9 0C02 R JMP PUTVAL ;RETURN THE VALUE + 030F OPADD ENDP + + ;SUB + 030F OPSUB PROC + 030F 2B C3 SUB AX,BX ;SUBTRACT OPR2 FROM OPR1 + 0311 E9 0C02 R JMP PUTVAL ;RETURN THE VALUE + 0314 OPSUB ENDP + + ;MULTIPLY AX BY BX + 0314 OPMUL PROC + 0314 F7 EB IMUL BX ;MULTIPLY OPR1 BY OPR2,IGNORING OVERFLOW(DX) + 0316 E9 0C02 R JMP PUTVAL ;RETURN THE VALUE + 0319 OPMUL ENDP + + ;DIVIDE AX BY BX + 0319 OPDIV PROC + 0319 99 CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + 031A F7 FB IDIV BX ;DIVIDE OPR1 BY OPR2 + 031C E9 0C02 R JMP PUTVAL ;RETURN THE VALUE + 031F OPDIV ENDP + + ;MOD + 031F OPMOD PROC + 031F 99 CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + 0320 F7 FB IDIV BX ;DIVIDE OPR1 BY OPR2 + 0322 8B C2 MOV AX,DX ;WE WANT REMAINDER + 0324 E9 0C02 R JMP PUTVAL ;RETURN THE VALUE + 0327 OPMOD ENDP + + ;RANDOM + 0327 OPRAND PROC + 0327 2A E4 SUB AH,AH + 0329 A3 02B3 R MOV RTEMP,AX + 032C A1 02AF R MOV AX,RSEED1 + 032F 8B 1E 02B1 R MOV BX,RSEED2 + 0333 A3 02B1 R MOV RSEED2,AX + 0336 F8 CLC + 0337 D1 D8 RCR AX,1 + 0339 D1 DB RCR BX,1 + 033B 31 1E 02AF R XOR RSEED1,BX + 033F A1 02AF R MOV AX,RSEED1 + 0342 25 EFFF AND AX,0EFFFH + 0345 2B D2 SUB DX,DX + 0347 F7 36 02B3 R DIV RTEMP + 034B 8B C2 MOV AX,DX + 034D 40 INC AX ;MUST BE BETWEEN 1 AND N, INCLUSIVE + 034E F6 06 066C R 04 TEST INIFLG,INIRND +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 4-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + ARITHMETIC OPERATIONS + + 0353 75 03 JNZ OPRN1$ + 0355 E9 0C02 R JMP PUTVAL ;SIMPLY RETURN + 0358 50 OPRN1$: PUSH AX + 0359 E8 09A4 R CALL OPPRNN ;PRINT NUMBER + 035C B0 20 MOV AL,32 + 035E E8 0E61 R CALL PUTCHR + 0361 58 POP AX + 0362 E9 0C02 R JMP PUTVAL ;RETURN THE VALUE + 0365 OPRAND ENDP + + ;LESS? + 0365 OPQLES PROC + 0365 3B C3 CMP AX,BX ;IS OPR1 LESS THAN OPR2? + 0367 7C 03 JL JPT ;YES, PREDICATE TRUE + 0369 E9 0C12 R JPF: JMP PFALSE ;NO, PREDICATE FALSE + 036C E9 0C17 R JPT: JMP PTRUE + 036F OPQLES ENDP + + ;GRTR? + 036F OPQGRT PROC + 036F 3B C3 CMP AX,BX ;IS OPR1 GREATER THAN OPR2? + 0371 7F F9 JG JPT ;YES, PREDICATE TRUE + 0373 EB F4 JMP JPF ;NO, PREDICATE FALSE + 0375 OPQGRT ENDP + + SUBTTL LOGICAL OPERATIONS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 5-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + LOGICAL OPERATIONS + + PAGE + + + ;BTST + 0375 OPBTST PROC + 0375 F7 D0 NOT AX ;TURN OFF BITS IN OPR2 THAT ARE ON IN OPR1 + 0377 23 D8 AND BX,AX + 0379 74 F1 JE JPT ;SUCCESS IF OPR2 COMPLETELY CLEARED + 037B EB EC JMP JPF + 037D OPBTST ENDP + + ;BOR + 037D OPBOR PROC + 037D 0B C3 OR AX,BX ;LOGICAL OR + 037F E9 0C02 R JMP PUTVAL ;RETURN THE VALUE + 0382 OPBOR ENDP + + ;BCOM + 0382 OPBCOM PROC + 0382 F7 D0 NOT AX ;LOGICAL COMPLEMENT + 0384 E9 0C02 R JMP PUTVAL ;RETURN THE VALUE + 0387 OPBCOM ENDP + + ;BAND + 0387 OPBAND PROC + 0387 23 C3 AND AX,BX ;LOGICAL AND + 0389 E9 0C02 R JMP PUTVAL ;RETURN THE VALUE + 038C OPBAND ENDP + + SUBTTL GENERAL PREDICATES +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 6-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + GENERAL PREDICATES + + PAGE + + + ;EQUAL? + 038C OPQEQU PROC + 038C 90 NOP ;TELL CALLER TO USE ARGUMENT BLOCK + 038D 8B 1E 0673 R MOV BX,ARGBLK ;GET OPR1 + 0391 3B 1E 0675 R CMP BX,ARGBLK[2] ;IS OPR1 EQUAL TO OPR2? + 0395 74 16 JE OQE1$ ;YES + 0397 3D 0003 CMP AX,3 ;NO, IS THERE A THIRD OPERAND? + 039A 7C 14 JL OQE2$ ;NO + 039C 3B 1E 0677 R CMP BX,ARGBLK[4] ;YES, IS IT EQUAL TO OPR1? + 03A0 74 0B JE OQE1$ ;YES + 03A2 3D 0004 CMP AX,4 ;NO, IS THERE A FOURTH? + 03A5 7C 09 JL OQE2$ ;NO + 03A7 3B 1E 0679 R CMP BX,ARGBLK[6] ;YES, IS IT EQUAL TO OPR1? + 03AB 75 03 JNE OQE2$ ;NO + 03AD E9 0C17 R OQE1$: JMP PTRUE ;PREDICATE TRUE IF EQUAL + 03B0 E9 0C12 R OQE2$: JMP PFALSE ;PREDICATE FALSE IF NOT + 03B3 OPQEQU ENDP + + ;ZERO? + 03B3 OPQZER PROC + 03B3 3D 0000 CMP AX,0 ;IS OPR ZERO? + 03B6 75 03 JNE OQZ1$ ;NO, PREDICATE FALSE + 03B8 E9 0C17 R JMP PTRUE ;YES, PREDICATE TRUE + 03BB E9 0C12 R OQZ1$: JMP PFALSE + 03BE OPQZER ENDP + + SUBTTL OBJECT OPERATIONS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 7-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + OBJECT OPERATIONS + + PAGE + + + ;MOVE (OBJ1 INTO OBJ2) + 03BE OPMOVE PROC + 03BE 50 PUSH AX ;PROTECT OPRS FROM REMOVE CALL + 03BF 53 PUSH BX + 03C0 E8 03E9 R CALL OPREMO ;REMOVE OBJ1 FROM WHEREVER IT IS + 03C3 5A POP DX ;OBJ2 + 03C4 8B C2 MOV AX,DX + 03C6 E8 0C76 R CALL OBJLOC ;FIND ITS LOCATION + 03C9 8B D8 MOV BX,AX ;MOVE TO BASE + 03CB 59 POP CX ;OBJ1 + 03CC 8B C1 MOV AX,CX + 03CE E8 0C76 R CALL OBJLOC ;FIND ITS LOCATION + 03D1 8B E8 MOV BP,AX ;MOVE TO BASE + 03D3 26: 88 56 04 MOV ES:[BP].PARENT,DL ;PUT OBJ2 INTO OBJ1'S LOC SLOT + 03D7 26: 8A 77 06 MOV DH,ES:[BX].CHILD1 ;GET CONTENTS OF OBJ2'S FIRST SLOT + 03DB 26: 88 4F 06 MOV ES:[BX].CHILD1,CL ;MAKE OBJ1 FIRST CONTENT OF OBJ2 + 03DF 80 FE 00 CMP DH,0 ;WERE THERE ANY OTHER CONTENTS? + 03E2 74 04 JE OMV1$ ;NO + 03E4 26: 88 76 05 MOV ES:[BP].SIBLING,DH ;YES, CHAIN ONTO OBJ1'S SIBLING SLOT + 03E8 C3 OMV1$: RET + 03E9 OPMOVE ENDP + + ;REMOVE (OBJ FROM ITS PARENT) + 03E9 OPREMO PROC + 03E9 8B C8 MOV CX,AX ;SAVE OBJ FOR LATER + 03EB E8 0C76 R CALL OBJLOC ;FIND ITS LOCATION + 03EE 8B D8 MOV BX,AX ;MOVE TO BASE + 03F0 26: 8A 6F 04 MOV CH,ES:[BX].PARENT ;GET ITS PARENT + 03F4 80 FD 00 CMP CH,0 ;DOES IT HAVE A PARENT? + 03F7 74 3B JE ORM3$ ;IF NOT, WE'RE DONE + 03F9 8A C5 MOV AL,CH ;PARENT + 03FB E8 0C76 R CALL OBJLOC ;FIND PARENT'S LOCATION + 03FE 8B E8 MOV BP,AX ;MOVE TO BASE + 0400 26: 8A 56 06 MOV DL,ES:[BP].CHILD1 ;GET PARENT'S FIRST CONTENT + 0404 3A D1 CMP DL,CL ;IS IT OBJ? + 0406 75 0B JNE ORM1$ ;NO + MOVM ES:[BP].CHILD1,ES:[BX].SIBLING,AL ;YES, CHANGE SLOT TO + 0408 26: 8A 47 05 + MOV AL,ES:[BX].SIBLING + 040C 26: 88 46 06 + MOV ES:[BP].CHILD1,AL + ;OBJ'S SIBLING + 0410 EB 18 90 JMP ORM2$ ;AND RETURN + 0413 8A C2 ORM1$: MOV AL,DL ;CURRENT SIBLING + 0415 E8 0C76 R CALL OBJLOC ;FIND ITS LOCATION + 0418 8B E8 MOV BP,AX ;MOVE TO BASE + 041A 26: 8A 56 05 MOV DL,ES:[BP].SIBLING ;GET NEXT SIBLING IN CHAIN + 041E 3A D1 CMP DL,CL ;IS IT OBJ? + 0420 75 F1 JNE ORM1$ ;NO, CONTINUE LOOP + MOVM ES:[BP].SIBLING,ES:[BX].SIBLING,AL ;YES, CHANGE IT TO + 0422 26: 8A 47 05 + MOV AL,ES:[BX].SIBLING + 0426 26: 88 46 05 + MOV ES:[BP].SIBLING,AL + ;OBJ'S SIBLING +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 7-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + OBJECT OPERATIONS + + 042A 26: C6 47 04 00 ORM2$: MOV ES:[BX].PARENT,0 ;OBJ NOW HAS NO PARENT + 042F 26: C6 47 05 00 MOV ES:[BX].SIBLING,0 ;OR SIBLING + 0434 C3 ORM3$: RET + 0435 OPREMO ENDP + + ;FSET? (IS FLAG SET IN OBJ?) + 0435 OPQFSE PROC + 0435 E8 0C76 R CALL OBJLOC ;FIND OBJ'S LOCATION + 0438 83 FB 10 CMP BX,16 ;SECOND WORD FLAG? + 043B 7C 05 JL OQF1$ ;NO + 043D 83 EB 10 SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + 0440 40 INC AX ;AND USE SECOND FLAG WORD + 0441 40 INC AX + 0442 8B CB OQF1$: MOV CX,BX ;MOVE TO COUNT + 0444 8B D8 MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + 0446 26: 8B 07 + MOV AX,ES:[BX] + 0449 86 E0 + XCHG AH,AL + 044B BA 8000 MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + 044E D3 EA SHR DX,CL + 0450 85 C2 TEST AX,DX ;IS THIS BIT SET IN FLAG WORD? + 0452 74 03 JE OQF2$ ;NO, PREDICATE FALSE + 0454 E9 0C17 R JMP PTRUE ;YES, PREDICATE TRUE + 0457 E9 0C12 R OQF2$: JMP PFALSE + 045A OPQFSE ENDP + + ;FSET (SET A FLAG IN OBJ) + 045A OPFSET PROC + 045A E8 0C76 R CALL OBJLOC ;FIND OBJ'S LOCATION + 045D 83 FB 10 CMP BX,16 ;SECOND WORD FLAG? + 0460 7C 05 JL OFS1$ ;NO + 0462 83 EB 10 SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + 0465 40 INC AX ;AND USE SECOND FLAG WORD + 0466 40 INC AX + 0467 8B CB OFS1$: MOV CX,BX ;MOVE TO COUNT + 0469 8B D8 MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + 046B 26: 8B 07 + MOV AX,ES:[BX] + 046E 86 E0 + XCHG AH,AL + 0470 BA 8000 MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + 0473 D3 EA SHR DX,CL + 0475 0B C2 OR AX,DX ;SET THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + 0477 86 E0 + XCHG AH,AL + 0479 26: 89 07 + MOV ES:[BX],AX + 047C C3 RET + 047D OPFSET ENDP + + ;FCLEAR (CLEAR A FLAG IN OBJ) + 047D OPFCLE PROC + 047D E8 0C76 R CALL OBJLOC ;FIND OBJ'S LOCATION + 0480 83 FB 10 CMP BX,16 ;SECOND WORD FLAG? + 0483 7C 05 JL OFC1$ ;NO +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 7-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + OBJECT OPERATIONS + + 0485 83 EB 10 SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + 0488 40 INC AX ;AND USE SECOND FLAG WORD + 0489 40 INC AX + 048A 8B CB OFC1$: MOV CX,BX ;MOVE TO COUNT + 048C 8B D8 MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + 048E 26: 8B 07 + MOV AX,ES:[BX] + 0491 86 E0 + XCHG AH,AL + 0493 BA 7FFF MOV DX,7FFFH ;SHIFT A BIT TO PROPER POSITION + 0496 D3 CA ROR DX,CL + 0498 23 C2 AND AX,DX ;CLEAR THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + 049A 86 E0 + XCHG AH,AL + 049C 26: 89 07 + MOV ES:[BX],AX + 049F C3 RET + 04A0 OPFCLE ENDP + + ;LOC (RETURN CONTAINER OF OBJ) + 04A0 OPLOC PROC + 04A0 E8 0C76 R CALL OBJLOC ;FIND OBJ'S LOCATION + 04A3 8B D8 MOV BX,AX ;MOVE TO BASE + 04A5 26: 8A 47 04 MOV AL,ES:[BX].PARENT ;GET LOC SLOT + 04A9 E9 0BFD R JMP BYTVAL ;RETURN THE BYTE VALUE + 04AC OPLOC ENDP + + ;FIRST? (RETURN FIRST SLOT OF OBJ, FAIL IF NONE) + 04AC OPQFIR PROC + 04AC E8 0C76 R CALL OBJLOC ;FIND OBJ'S LOCATION + 04AF 8B D8 MOV BX,AX ;MOVE TO BASE + 04B1 26: 8A 47 06 MOV AL,ES:[BX].CHILD1 ;GET FIRST SLOT + 04B5 50 PUSH AX ;SAVE IT + 04B6 E8 0BFD R CALL BYTVAL ;RETURN THE BYTE VALUE + 04B9 58 POP AX ;RESTORE IT + 04BA 3C 00 CMP AL,0 ;WAS IT ZERO? + 04BC 74 03 JE JPF1 ;YES, PREDICATE FALSE + 04BE E9 0C17 R JPT1: JMP PTRUE ;NO, PREDICATE TRUE + 04C1 E9 0C12 R JPF1: JMP PFALSE + 04C4 OPQFIR ENDP + + ;NEXT? (RETURN THE NEXT (SIBLING) SLOT OF OBJ, FAIL IF NONE) + 04C4 OPQNEX PROC + 04C4 E8 0C76 R CALL OBJLOC ;FIND OBJ'S LOCATION + 04C7 8B D8 MOV BX,AX ;MOVE TO BASE + 04C9 26: 8A 47 05 MOV AL,ES:[BX].SIBLING ;GET SIBLING SLOT + 04CD 50 PUSH AX ;SAVE IT + 04CE E8 0BFD R CALL BYTVAL ;RETURN THE BYTE VALUE + 04D1 58 POP AX ;RESTORE IT + 04D2 3C 00 CMP AL,0 ;WAS IT ZERO? + 04D4 74 EB JE JPF1 ;YES, PREDICATE FALSE + 04D6 EB E6 JMP JPT1 ;NO, PREDICATE TRUE + 04D8 OPQNEX ENDP + + ;IN? (IS OBJ1 CONTAINED IN OBJ2?) +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 7-4 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + OBJECT OPERATIONS + + 04D8 OPQIN PROC + 04D8 E8 0C76 R CALL OBJLOC ;FIND OBJ1'S LOCATION + 04DB 93 XCHG AX,BX ;MOVE TO BASE + 04DC 26: 38 47 04 CMP ES:[BX].PARENT,AL ;IS OBJ1'S PARENT OBJ2? + 04E0 74 DC JE JPT1 ;YES, PREDICATE TRUE + 04E2 EB DD JMP JPF1 ;NO, PREDICATE FALSE + 04E4 OPQIN ENDP + + ;GETP (GET SPECIFIED PROPERTY OF OBJ, DEFAULT IF NONE) + 04E4 OPGETP PROC + 04E4 8B D3 MOV DX,BX ;PROPERTY + 04E6 E8 0C76 R CALL OBJLOC ;FIND OBJ'S LOCATION + 04E9 8B E8 MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + 04EB 26: 8B 5E 07 + MOV BX,ES:[BP].PROPS + 04EF 86 FB + XCHG BH,BL + 04F1 26: 8A 07 MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + 04F4 2A E4 SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + 04F6 D1 E0 SHL AX,1 ;CONVERT TO BYTES + 04F8 03 D8 ADD BX,AX ;ADJUST POINTER TO SKIP IT + 04FA 43 INC BX ;ALSO SKIP LENGTH BYTE + 04FB EB 04 90 JMP OGP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP + 04FE E8 0C8C R OGP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY + 0501 26: 8A 07 OGP2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + 0504 24 1F AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + 0506 3A C2 CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + 0508 7F F4 JG OGP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + 050A 7C 14 JL OGP3$ ;IF LESS, NO SUCH PROPERTY HERE + 050C 26: 8A 07 MOV AL,ES:[BX] ;GOT IT, NOW FIND LENGTH OF PROPERTY + 050F 43 INC BX ;POINT TO PROPERTY VALUE + 0510 24 E0 AND AL,MASK PROPSIZE;GET LENGTH BITS + 0512 B1 05 MOV CL,PROPSIZE + 0514 D2 E8 SHR AL,CL + 0516 3C 00 CMP AL,0 ;BYTE VALUE? + 0518 75 0F JNE OGP5$ ;NO + 051A 26: 8A 07 MOV AL,ES:[BX] ;GET THE BYTE + 051D E9 0BFD R JMP BYTVAL ;AND RETURN IT + 0520 4A OGP3$: DEC DX ;POINT INTO DEFAULT PROPERTY TABLE + 0521 D1 E2 SHL DX,1 + 0523 8B DA MOV BX,DX + 0525 03 1E 02E5 R OGP4$: ADD BX,OBJTAB ;GET THE WORD + 0529 OGP5$: GTAWRD A,[BX] + 0529 26: 8B 07 + MOV AX,ES:[BX] + 052C 86 E0 + XCHG AH,AL + 052E E9 0C02 R JMP PUTVAL ;AND RETURN IT + 0531 OPGETP ENDP + + ;PUTP (CHANGE VALUE OF A PROPERTY, ERROR IF BAD NUMBER) + 0531 OPPUTP PROC + 0531 51 PUSH CX ;SAVE NEW VALUE + 0532 8B D3 MOV DX,BX ;PROPERTY + 0534 E8 0C76 R CALL OBJLOC ;FIND OBJ'S LOCATION + 0537 8B E8 MOV BP,AX ;MOVE TO BASE +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 7-5 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + OBJECT OPERATIONS + + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + 0539 26: 8B 5E 07 + MOV BX,ES:[BP].PROPS + 053D 86 FB + XCHG BH,BL + 053F 26: 8A 07 MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + 0542 2A E4 SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + 0544 D1 E0 SHL AX,1 ;CONVERT TO BYTES + 0546 03 D8 ADD BX,AX ;ADJUST POINTER TO SKIP IT + 0548 43 INC BX ;ALSO SKIP LENGTH BYTE + 0549 EB 04 90 JMP OPP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP + 054C E8 0C8C R OPP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY + 054F 26: 8A 07 OPP2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + 0552 24 1F AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + 0554 3A C2 CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + 0556 74 14 JE OPP3$ ;IF EQUAL, GOT IT + 0558 7F F2 JG OPP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR + 055A E8 18F0 R + CALL .CRLF + 055D B8 09DF R + MOV AX,OFFSET FATHDR + 0560 E8 196F R + CALL .PRINT + 0563 B8 0983 R + MOV AX,OFFSET FTL2 + 0566 E8 196F R + CALL .PRINT + 0569 E9 1A47 R + JMP FINISH + 056C 26: 8A 07 OPP3$: MOV AL,ES:[BX] ;NOW FIND LENGTH OF PROPERTY + 056F 43 INC BX ;POINT TO PROPERTY VALUE + 0570 24 E0 AND AL,MASK PROPSIZE;GET LENGTH BITS + 0572 B1 05 MOV CL,PROPSIZE + 0574 D2 E8 SHR AL,CL + 0576 3C 00 CMP AL,0 ;BYTE VALUE? + 0578 58 POP AX ;RESTORE NEW VALUE + 0579 75 04 JNE OPP4$ ;ZERO MEANS BYTE VALUE + 057B 26: 88 07 MOV ES:[BX],AL ;STORE THE NEW BYTE + 057E C3 RET ;AND RETURN + 057F OPP4$: PTAWRD [BX],A ;STORE THE NEW WORD VALUE + 057F 86 E0 + XCHG AH,AL + 0581 26: 89 07 + MOV ES:[BX],AX + 0584 C3 RET + 0585 OPPUTP ENDP + + ;NEXTP (RETURN NUMBER OF NEXT PROP FOLLOWING GIVEN PROB IN OBJ) + 0585 OPNEXT PROC + 0585 8B D3 MOV DX,BX ;PROPERTY + 0587 E8 0C76 R CALL OBJLOC ;FIND OBJ'S LOCATION + 058A 8B E8 MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET ITS LOCATION + 058C 26: 8B 5E 07 + MOV BX,ES:[BP].PROPS + 0590 86 FB + XCHG BH,BL + 0592 26: 8A 07 MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + 0595 2A E4 SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + 0597 D1 E0 SHL AX,1 ;CONVERT TO BYTES + 0599 03 D8 ADD BX,AX ;ADJUST POINTER TO SKIP IT + 059B 43 INC BX ;ALSO SKIP LENGTH BYTE + 059C 83 FA 00 CMP DX,0 ;WERE WE GIVEN ZERO AS PROP? + 059F 74 26 JE ONX4$ ;YES, GO RETURN FIRST PROPERTY NUMBER +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 7-6 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + OBJECT OPERATIONS + + 05A1 EB 04 90 JMP ONX2$ ;NO, SKIP NEXT LINE FIRST TIME THROUGH LOOP + 05A4 E8 0C8C R ONX1$: CALL NXTPRP ;POINT TO NEXT PROPERTY + 05A7 26: 8A 07 ONX2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + 05AA 24 1F AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + 05AC 3A C2 CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + 05AE 74 14 JE ONX3$ ;IF EQUAL, GOT IT + 05B0 7F F2 JG ONX1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR + 05B2 E8 18F0 R + CALL .CRLF + 05B5 B8 09DF R + MOV AX,OFFSET FATHDR + 05B8 E8 196F R + CALL .PRINT + 05BB B8 0983 R + MOV AX,OFFSET FTL2 + 05BE E8 196F R + CALL .PRINT + 05C1 E9 1A47 R + JMP FINISH + 05C4 E8 0C8C R ONX3$: CALL NXTPRP ;POINT TO NEXT PROPERTY + 05C7 26: 8A 07 ONX4$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + 05CA 24 1F AND AL,MASK PROPNUM ;EXTRACT PROPERTY NUMBER + 05CC E9 0C02 R JMP PUTVAL ;AND RETURN IT + 05CF OPNEXT ENDP + + SUBTTL TABLE OPERATIONS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 8-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + TABLE OPERATIONS + + PAGE + + + ;GET (GET THE ITEM'TH WORD FROM TABLE) + 05CF OPGET PROC + 05CF D1 E3 SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + 05D1 03 C3 ADD AX,BX ;INDEX INTO TABLE + 05D3 E8 0C5D R CALL BSPLTB ;SPLIT THE POINTER + 05D6 E8 0B53 R CALL GETWRD ;GET THE WORD + 05D9 8B C1 MOV AX,CX + 05DB E9 0C02 R JMP PUTVAL ;AND RETURN IT + 05DE OPGET ENDP + + ;GETB (GET THE ITEM'TH BYTE FROM TABLE) + 05DE OPGETB PROC + 05DE 03 C3 ADD AX,BX ;INDEX INTO TABLE + 05E0 E8 0C5D R CALL BSPLTB ;SPLIT THE POINTER + 05E3 E8 0B26 R CALL GETBYT ;GET THE BYTE + 05E6 8B C1 MOV AX,CX + 05E8 E9 0BFD R JMP BYTVAL ;AND RETURN IT + 05EB OPGETB ENDP + + ;PUT (REPLACE THE ITEM'TH WORD IN TABLE) + 05EB OPPUT PROC + 05EB D1 E3 SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + 05ED 03 D8 ADD BX,AX ;INDEX INTO TABLE + PTAWRD [BX],C ;STORE THE WORD + 05EF 86 E9 + XCHG CH,CL + 05F1 26: 89 0F + MOV ES:[BX],CX + 05F4 C3 RET + 05F5 OPPUT ENDP + + ;PUTB (REPLACE ITEM'TH BYTE IN TABLE) + 05F5 OPPUTB PROC + 05F5 03 D8 ADD BX,AX ;INDEX INTO TABLE + 05F7 26: 88 0F MOV ES:[BX],CL ;STORE BYTE + 05FA C3 RET + 05FB OPPUTB ENDP + + ;GETPT (GET POINTER TO PROPERTY TABLE FOR GIVEN PROP) + 05FB OPGTPT PROC + 05FB 8B D3 MOV DX,BX ;PROPERTY + 05FD E8 0C76 R CALL OBJLOC ;FIND OBJ'S LOCATION + 0600 8B E8 MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + 0602 26: 8B 5E 07 + MOV BX,ES:[BP].PROPS + 0606 86 FB + XCHG BH,BL + 0608 26: 8A 07 MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + 060B 2A E4 SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + 060D D1 E0 SHL AX,1 ;CONVERT TO BYTES + 060F 03 D8 ADD BX,AX ;ADJUST POINTER TO SKIP IT + 0611 43 INC BX ;ALSO SKIP LENGTH BYTE + 0612 EB 04 90 JMP OGT2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP + 0615 E8 0C8C R OGT1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 8-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + TABLE OPERATIONS + + 0618 26: 8A 07 OGT2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + 061B 24 1F AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + 061D 3A C2 CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + 061F 7F F4 JG OGT1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + 0621 74 05 JE OGT3$ ;FOUND THE PROPERTY + 0623 2B C0 SUB AX,AX ;RETURN ZERO FOR NO SUCH PROPERTY + 0625 EB 04 90 JMP OGT4$ + 0628 43 OGT3$: INC BX ;POINT TO PROPERTY VALUE + 0629 8B C3 MOV AX,BX ;AND RETURN IT + 062B E9 0C02 R OGT4$: JMP PUTVAL + 062E OPGTPT ENDP + + ;PTSIZE (RETURN SIZE OF PROPERTY TABLE) + 062E OPPTSI PROC + 062E 8B D8 MOV BX,AX ;TABLE POINTER + 0630 26: 8A 47 FF MOV AL,ES:[BX-1] ;GET PROPERTY INDENTIFIER + 0634 24 E0 AND AL,MASK PROPSIZE;EXTRACT LENGTH BITS + 0636 2A E4 SUB AH,AH + 0638 B1 05 MOV CL,PROPSIZE + 063A D3 E8 SHR AX,CL + 063C 40 INC AX ;ADJUST TO ACTUAL LENGTH + 063D E9 0C02 R JMP PUTVAL ;RETURN IT + 0640 OPPTSI ENDP + + SUBTTL VARIABLE OPERATIONS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 9-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + VARIABLE OPERATIONS + + PAGE + + + ;VALUE (GET VALUE OF VAR) + 0640 OPVALU PROC + 0640 E8 0BA0 R CALL GETVAR ;GET THE VALUE + 0643 E9 0C02 R JMP PUTVAL ;AND RETURN IT + 0646 OPVALU ENDP + + ;SET (VAR TO VALUE) + 0646 OPSET PROC + 0646 E9 0BD0 R JMP PUTVAR ;STORE THE VALUE + 0649 OPSET ENDP + + ;PUSH (A VALUE ONTO THE STACK) + 0649 OPPUSH PROC + PUSHZ AX ;PUSH THE VALUE + 0649 87 E7 + XCHG SP,DI + 064B 50 + PUSH AX + 064C 87 E7 + XCHG SP,DI + 064E C3 RET + 064F OPPUSH ENDP + + ;POP (A VALUE OFF THE STACK INTO VAR) + 064F OPPOP PROC + POPZ BX ;POP A VALUE + 064F 87 E7 + XCHG SP,DI + 0651 5B + POP BX + 0652 87 E7 + XCHG SP,DI + 0654 E9 0BD0 R JMP PUTVAR ;AND STORE IT + 0657 OPPOP ENDP + + ;INC (INCREMENT VAR) + 0657 OPINC PROC + 0657 8B C8 MOV CX,AX ;VARIABLE + 0659 E8 0BA0 R CALL GETVAR ;GET VAR'S VALUE + 065C 40 INC AX ;INCREMENT IT + 065D 8B D8 OPINC1: MOV BX,AX ;VALUE + 065F 8B C1 MOV AX,CX ;VARIABLE + 0661 E9 0BD0 R JMP PUTVAR ;STORE NEW VALUE + 0664 OPINC ENDP + + ;DEC (DECREMENT VAR) + 0664 OPDEC PROC + 0664 8B C8 MOV CX,AX ;VARIABLE + 0666 E8 0BA0 R CALL GETVAR ;GET VAR'S VALUE + 0669 48 DEC AX ;DECREMENT IT + 066A EB F1 JMP OPINC1 ;STORE NEW VALUE + 066C OPDEC ENDP + + ;IGRTR? (INCREMENT VAR & TEST IF GREATER THAN VAL) + 066C OPQIGR PROC + 066C 50 PUSH AX ;SAVE VARIABLE + 066D E8 0BA0 R CALL GETVAR ;GET VAR'S VALUE +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 9-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + VARIABLE OPERATIONS + + 0670 40 INC AX ;INCREMENT IT + 0671 2B C9 SUB CX,CX ;SET FLAG FALSE + 0673 3B C3 CMP AX,BX ;NEW VALUE GREATER THAN VAL? + 0675 7E 01 JLE OPQIG1 ;NO + 0677 41 OPQIG0: INC CX ;YES, CHANGE FLAG TO TRUE + 0678 8B D8 OPQIG1: MOV BX,AX ;VALUE + 067A 58 POP AX ;RESTORE VARIABLE + 067B E8 0BD0 R CALL PUTVAR ;STORE NEW VALUE + 067E 83 F9 00 CMP CX,0 ;TEST FLAG + 0681 74 03 JE OQI1$ ;FALSE, PREDICATE FALSE + 0683 E9 0C17 R JMP PTRUE ;ELSE, PREDICATE TRUE + 0686 E9 0C12 R OQI1$: JMP PFALSE + 0689 OPQIGR ENDP + + ;DLESS? (DECREMENT VAR & TEST IF LESS THAN VAL) + 0689 OPQDLE PROC + 0689 50 PUSH AX ;SAVE VARIABLE + 068A E8 0BA0 R CALL GETVAR ;GET VAR'S VALUE + 068D 48 DEC AX ;DECREMENT IT + 068E 2B C9 SUB CX,CX ;SET FLAG FALSE + 0690 3B C3 CMP AX,BX ;NEW VALUE LESS THAN VAL? + 0692 7D E4 JGE OPQIG1 ;NO, PREDICATE FALSE + 0694 EB E1 JMP OPQIG0 ;YES, PREDICATE TRUE + 0696 OPQDLE ENDP + + SUBTTL I/O OPERATIONS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 10-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + I/O OPERATIONS + + PAGE + + + = 000A EOLCHR EQU 10 ;LINE-FEED IS END-OF-LINE CHARACTER + + 0696 GETLIN PROC + 0696 53 PUSH BX + 0697 A0 0023 R MOV AL,SCRFLG + 069A 50 PUSH AX + 069B C6 06 0023 R 00 MOV SCRFLG,0 ;DEFEAT SCRIPTING DURING INPUT + 06A0 8B D6 MOV DX,SI ;HOLD ON TO STA + 06A2 26: 8A 0C MOV CL,ES:[SI] + 06A5 2A ED SUB CH,CH ;CX HAS MAX # CHARACTERS TO READ + 06A7 46 INC SI ;SI HAS POINTER TO LINE BUFFER + 06A8 E8 1864 R GTLL$: CALL .CHRIN ;GET A CHARACTER + 06AB 3C 0A CMP AL,EOLCHR ;IS IT END OF LINE? + 06AD 74 04 JE GTLX$ + 06AF 3C 0D CMP AL,13 + 06B1 75 09 JNE GTL0$ + 06B3 E8 18F0 R GTLX$: CALL .CRLF + 06B6 58 POP AX + 06B7 A2 0023 R MOV SCRFLG,AL ;RESET SCRIPT FLAG + 06BA 5B POP BX + 06BB C3 RET ;OUR WORK IS DONE + 06BC 3C 08 GTL0$: CMP AL,8 ;WAS IT A BACKSPACE + 06BE 75 44 JNE GTL1$ + 06C0 8B C6 MOV AX,SI + 06C2 2C 01 SUB AL,1 + 06C4 3B D0 CMP DX,AX ;ARE WE AT BEGINNING OF BUFFER? + 06C6 75 0C JNE GTL2$ + 06C8 B8 0007 GTLF$: MOV AX,7 + 06CB E8 1887 R CALL .TTYOUT ;FEEP AT HIM NOW + 06CE EB D8 JMP GTLL$ + 06D0 4E GTLL1$: DEC SI ;MOVE BUFFER AND COUNT BACK (OR FORWARD) + 06D1 41 INC CX + 06D2 EB D4 JMP GTLL$ + 06D4 52 GTL2$: PUSH DX + 06D5 51 PUSH CX + CURGET ;READ THE CURSOR (DH = ROW, DL = COLUMN) + 06D6 50 + PUSH AX + 06D7 2A FF + SUB BH,BH + 06D9 B4 03 + MOV AH,3 + 06DB CD 10 + INT 10H + 06DD 58 + POP AX + 06DE 59 POP CX + 06DF 3A 16 02DA R CMP DL,LFTMAR ;ARE WE AT BEGINNING OF A LINE? + 06E3 75 08 JNE GTL3$ + 06E5 80 EE 01 SUB DH,1 ;PREVIOUS LINE + 06E8 A1 02D4 R MOV AX,TWIDTH + 06EB 8A D0 MOV DL,AL ;END OF LINE + 06ED 80 EA 01 GTL3$: SUB DL,1 ;CURSET/GET ARE ZERO BASED + CURSET ;MOVE IT THERE + 06F0 50 + PUSH AX + 06F1 2A FF + SUB BH,BH +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 10-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + I/O OPERATIONS + + 06F3 B4 02 + MOV AH,2 + 06F5 CD 10 + INT 10H + 06F7 58 + POP AX + 06F8 B0 01 MOV AL,1 + 06FA 8A 26 0000 R MOV AH,NRMATR ;NO ATTRIBUTES, ONE SPACE + 06FE E8 18C2 R CALL .SPACE ;WRITE THE SPACE + 0701 5A POP DX + 0702 EB CC JMP GTLL1$ ;LOOP BACK + + 0704 E3 C2 GTL1$: JCXZ GTLF$ ;BUFFER FULL + 0706 8A 26 0002 R MOV AH,TYPATR + 070A E8 1887 R CALL .TTYOUT ;ECHO THE CHARACTER + 070D 50 PUSH AX + 070E 52 PUSH DX + 070F 51 PUSH CX + CURGET ;FIND THE CURSOR + 0710 50 + PUSH AX + 0711 2A FF + SUB BH,BH + 0713 B4 03 + MOV AH,3 + 0715 CD 10 + INT 10H + 0717 58 + POP AX + 0718 59 POP CX + 0719 A1 02D4 R MOV AX,TWIDTH + 071C 3A D0 CMP DL,AL ;CHECK IF AT END OF LINE + 071E 75 03 JNZ GTL5$ + 0720 E8 18F0 R CALL .CRLF ;MAKE A NICE CRLF AT END OF LINE + 0723 5A GTL5$: POP DX + 0724 58 POP AX + 0725 3C 41 GTL4$: CMP AL,"A" ; CHECK UPPER CASE RANGE A-Z + 0727 7C 06 JL GTLD$ + 0729 3C 5A CMP AL,"Z" + 072B 7F 02 JG GTLD$ + 072D 04 20 ADD AL,20H ;ADJUST FOR LOWER CASE + 072F 26: 88 04 GTLD$: MOV ES:[SI],AL ; *** THIS PUTS CHAR. IN BUFFER *** + 0732 46 INC SI ;MOVE POINTER, COUNT FORWARD + 0733 FE C9 DEC CL + 0735 E9 06A8 R JMP GTLL$ + 0738 GETLIN ENDP + + 0738 PRTLOS PROC + 0738 A0 0023 R MOV AL,SCRFLG + 073B 50 PUSH AX + 073C 52 PUSH DX + 073D C6 06 0023 R 00 MOV SCRFLG,0 ;TURN OFF SCRIPTING TO AVOID GETTING HUNG + PRINT PRNRDY + 0742 50 + PUSH AX + 0743 B8 0024 R + MOV AX,OFFSET PRNRDY + 0746 E8 196F R + CALL .PRINT + 0749 58 + POP AX + 074A E8 1864 R PRNL$: CALL .CHRIN + 074D 3C 41 CMP AL,"A" + 074F 74 13 JE PRNA$ + 0751 3C 61 CMP AL,"a" +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 10-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + I/O OPERATIONS + + 0753 74 0F JE PRNA$ + 0755 3C 52 CMP AL,"R" + 0757 74 17 JE PRNR$ + 0759 3C 72 CMP AL,"r" + 075B 74 13 JE PRNR$ + 075D B0 07 MOV AL,7 + 075F E8 1887 R CALL .TTYOUT + 0762 EB E6 JMP PRNL$ + 0764 F8 PRNA$: CLC + 0765 9C PRNEX$: PUSHF + 0766 E8 18F0 R CALL .CRLF + 0769 9D POPF + 076A 5A POP DX + 076B 58 POP AX + 076C A2 0023 R MOV SCRFLG,AL ;RESTORE SCRIPT FLAG + 076F C3 RET + 0770 F9 PRNR$: STC + 0771 EB F2 JMP PRNEX$ + 0773 PRTLOS ENDP + + 0773 PRTOUT PROC + 0773 B4 00 PRTRT$: MOV AH,0 ;CODE FOR OUTPUT TO PRINTER PORT + 0775 BA 0000 MOV DX,0 + 0778 CD 17 INT 17H ;FORCE IT OUT + 077A F6 C4 01 TEST AH,1 ;ERROR TIME OUT CODE + 077D 74 1B JZ PRTO1$ ;LOST ON TIME OUT + 077F E8 0738 R CALL PRTLOS + 0782 72 EF JC PRTRT$ ;RETRY IF SO ORDERED + GTAWRD A,[PFLAGS] + 0784 26: A1 0010 + MOV AX,ES:[PFLAGS] + 0788 86 E0 + XCHG AH,AL + 078A 25 FFFE AND AX,0FFFEH ;TURN OFF THE SCRIPT BIT + PTAWRD [PFLAGS],A + 078D 86 E0 + XCHG AH,AL + 078F 26: A3 0010 + MOV ES:[PFLAGS],AX + 0793 C6 06 0023 R 00 MOV SCRFLG,0 ;AND UNSET THE FLAG + 0798 F9 STC ;INDICATE LOSER WANTS ABORT + 0799 C3 RET + 079A F8 PRTO1$: CLC ;INDICATE WIN + 079B C3 RET + 079C PRTOUT ENDP + + 079C SCRCHK PROC + 079C 50 PUSH AX + 079D 53 PUSH BX + 079E 52 PUSH DX + GTAWRD A,[PFLAGS] + 079F 26: A1 0010 + MOV AX,ES:[PFLAGS] + 07A3 86 E0 + XCHG AH,AL + 07A5 A8 01 TEST AL,1 ;CHECK IF SCRIPTING IS REQUESTED + 07A7 74 63 JZ SCRNN$ + 07A9 80 3E 0023 R 00 CMP SCRFLG,0 ;CHECK WHETHER THIS IS A NEW STATE + 07AE 75 2F JNE SCR1$ +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 10-4 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + I/O OPERATIONS + + 07B0 52 SCRR1$: PUSH DX + 07B1 BA 0000 MOV DX,0 ;FIRST PRINTER SLOT + 07B4 B4 01 MOV AH,1 + 07B6 CD 17 INT 17H ;INITIALIZE PORT + 07B8 F6 C4 A1 TEST AH,0A1H ;CHECK FOR TIME OUT,BUSY, OUT OF PAPER + 07BB 75 04 JNZ SCRR2$ + 07BD 5A POP DX + 07BE EB 1F 90 JMP SCR1$ + 07C1 5A SCRR2$: POP DX + 07C2 E8 0738 R CALL PRTLOS ;ASK USER WHAT TO DO NOW? + 07C5 72 E9 JC SCRR1$ ;RETRY + GTAWRD A,[PFLAGS] + 07C7 26: A1 0010 + MOV AX,ES:[PFLAGS] + 07CB 86 E0 + XCHG AH,AL + 07CD 25 FFFE AND AX,0FFFEH ;TURN OFF THE SCRIPT BIT + PTAWRD [PFLAGS],A + 07D0 86 E0 + XCHG AH,AL + 07D2 26: A3 0010 + MOV ES:[PFLAGS],AX + 07D6 C6 06 0023 R 00 MOV SCRFLG,0 ;AND FLAG + 07DB 5A SCREX$: POP DX + 07DC 5B POP BX + 07DD 58 POP AX + 07DE C3 RET + 07DF C6 06 0023 R 01 SCR1$: MOV SCRFLG,1 + 07E4 2B C9 SUB CX,CX ;COUNT OF CHARS PRINTED + 07E6 8B EA MOV BP,DX ;START OF INPUT LINE + 07E8 45 INC BP ;FIRST CHAR IS LENGTH OF BUFFER + 07E9 26: 8A 46 00 SCR1L$: MOV AL,ES:[BP] + 07ED 45 INC BP ;GET CHARACTER + 07EE 3B EE CMP BP,SI ;END OF INPUT? + 07F0 7E 05 JLE SCR2L$ + 07F2 E8 0813 R CALL PRTCRL + 07F5 EB E4 JMP SCREX$ + 07F7 E8 0773 R SCR2L$: CALL PRTOUT ;OUTPUT ONE CHARACTER TO THE PRINTER + 07FA 72 DF JC SCREX$ ;THIS MEANS SCRIPTING ABORTED + 07FC 41 INC CX + 07FD 3B 0E 02D4 R CMP CX,TWIDTH + 0801 75 E6 JNE SCR1L$ + 0803 E8 0813 R CALL PRTCRL + 0806 72 D3 JC SCREX$ + 0808 2B C9 SUB CX,CX ;RESTART COUNT + 080A EB DD JMP SCR1L$ ;GO FOR MORE + + 080C C6 06 0023 R 00 SCRNN$: MOV SCRFLG,0 + 0811 EB C8 JMP SCREX$ + 0813 SCRCHK ENDP + + 0813 PRTCRL PROC + 0813 B0 0D MOV AL,13 ;FINISH UP WITH CRLF + 0815 E8 0773 R CALL PRTOUT + 0818 B0 0A MOV AL,10 + 081A E8 0773 R CALL PRTOUT + 081D C3 RET +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 10-5 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + I/O OPERATIONS + + 081E PRTCRL ENDP + + ;READ (A LINE OF INPUT & PARSE IT, LINE BUF IN ES:AX, + ;RETURN BUF IN ES:BX) + 081E OPREAD PROC + 081E 50 PUSH AX ;SAVE LINE BUF + 081F 50 PUSH AX + 0820 53 PUSH BX + 0821 E8 02A4 R CALL OPUSL ;UPDATE STATUS LINE + 0824 5B POP BX + 0825 58 POP AX + 0826 8B 2E 02C6 R MOV BP,CHRPTR ;NEXT CHARACTER POSITION + 082A 3E: C6 46 00 80 MOV BYTE PTR DS:[BP],80H ;DON'T END OUTPUT, IF ANY, WITH NEW LINE + 082F ORD1$: PRINT OUTBUF ;FORCE OUT ANY QUEUED TEXT + 082F 50 + PUSH AX + 0830 B8 04F5 R + MOV AX,OFFSET OUTBUF + 0833 E8 196F R + CALL .PRINT + 0836 58 + POP AX + 0837 C7 06 02C6 R 04F5 R MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + 083D 5E POP SI ;INPUT BUFFER POINTER + 083E C7 06 095A R 0000 MOV MORLIN,0 ;RE-INITIALIZE MORE COUNT FROM HERE + 0844 E8 0696 R CALL GETLIN ;GET SOME CHARACTERS + 0847 E8 079C R CALL SCRCHK ;CHECK FOR SCRIPTING, SCRIPT INPUT IF ON + 084A 57 ORDNS$: PUSH DI + 084B 89 16 02BD R MOV RDBOS,DX ;INITIALIZE RDBOS + 084F 89 36 02BF R MOV RDEOS,SI ;AND RDEOS + 0853 89 1E 02C1 R MOV RDRET,BX ;STORE RET POINTER + 0857 C6 06 02C3 R 00 MOV RDNWDS,0 ;NO WORDS SO FAR + 085C 42 INC DX ;SKIP LENGTH BYTE + 085D 8B FB MOV DI,BX ;THIS WILL BE WORD ENTRY POINTER + 085F 47 INC DI ;SKIP MAX WORDS & NWORDS BYTES + 0860 47 INC DI + 0861 B9 02B5 R ORD8$: MOV CX,OFFSET RDWSTR;HERE FOR NEXT WORD, POINT TO WORD STRING + 0864 8B DA MOV BX,DX ;AND SAVE BEGINNING OF WORD POINTER + 0866 3B 16 02BF R ORD9$: CMP DX,RDEOS ;END OF STRING? + 086A 75 09 JNE ORD10$ ;NO + 086C 81 F9 02B5 R CMP CX,OFFSET RDWSTR;YES, WAS A WORD FOUND? + 0870 75 4B JNE ORD15$ ;YES, WE STILL HAVE TO LOOKUP WORD + 0872 E9 098F R JMP ORD23$ ;NO, WE'RE DONE + 0875 8B EA ORD10$: MOV BP,DX ;GET NEXT CHARACTER FROM BUFFER + 0877 26: 8A 46 00 MOV AL,ES:[BP] + 087B 3C 41 CMP AL,"A" + 087D 7C 06 JL ORD1A$ + 087F 3C 5A CMP AL,"Z" + 0881 7F 02 JG ORD1A$ + 0883 04 20 ADD AL,32 ;LOWERCASIFY ALPHABETICS + 0885 42 ORD1A$: INC DX + 0886 BE 0546 R MOV SI,OFFSET RBRKS ;LIST OF READ BREAK CHARACTERS + 0889 46 ORD11$: INC SI + 088A 3A 44 FF CMP AL,[SI-1] ;SEARCH LIST FOR THIS ONE + 088D 74 14 JE ORD12$ ;FOUND IT + 088F 80 3C 00 CMP BYTE PTR [SI],0 ;END OF LIST? + 0892 75 F5 JNE ORD11$ ;NO, CONTINUE SEARCH +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 10-6 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + I/O OPERATIONS + + 0894 81 F9 02BB R CMP CX,OFFSET RDWSTR[6] ;YES, NOT A BREAK, WORD STRING FULL? + 0898 74 CC JE ORD9$ ;YES, LOOP UNTIL END OF WORD + 089A 8B E9 MOV BP,CX ;NO, TACK THIS CHARACTER ONTO STRING + 089C 3E: 88 46 00 MOV DS:[BP],AL + 08A0 41 INC CX + 08A1 EB C3 JMP ORD9$ ;AND LOOP + 08A3 81 F9 02B5 R ORD12$: CMP CX,OFFSET RDWSTR;WORD READ BEFORE THIS BREAK? + 08A7 75 13 JNE ORD14$ ;YES + 08A9 3B 36 02ED R CMP SI,ESIBKS ;NO, BUT IS IT A SELF-INSERTING BREAK? + 08AD 76 03 JBE ORD13$ ;YES + 08AF 43 INC BX ;NO, UPDATE BEGINNING OF WORD TO SKIP BREAK + 08B0 EB B4 JMP ORD9$ ;AND RETURN TO LOOP TO FIND A WORD + 08B2 8B E9 ORD13$: MOV BP,CX ;STORE THE BREAK IN WORD STRING + 08B4 3E: 88 46 00 MOV DS:[BP],AL + 08B8 41 INC CX + 08B9 EB 02 90 JMP ORD15$ ;AND GO FOR THE WORD + 08BC 4A ORD14$: DEC DX ;UNREAD TERMINATING BREAK IN CASE IT WAS SI + 08BD FE 06 02C3 R ORD15$: INC RDNWDS ;INCREMENT FOUND WORD COUNT + 08C1 8B EB MOV BP,BX ;GREATER THAN MAX ALLOWED? + 08C3 8B 1E 02C1 R MOV BX,RDRET + 08C7 26: 8A 1F MOV BL,ES:[BX] + 08CA 38 1E 02C3 R CMP RDNWDS,BL + 08CE 8B DD MOV BX,BP + 08D0 7E 25 JLE ORD16$ ;NO + PRINT ERR2 ;YES, INFORM LOSER + 08D2 50 + PUSH AX + 08D3 B8 0962 R + MOV AX,OFFSET ERR2 + 08D6 E8 196F R + CALL .PRINT + 08D9 58 + POP AX + 08DA 8B C3 MOV AX,BX ;BEGINNING OF THIS WORD + 08DC 8B 2E 02BF R MOV BP,RDEOS ;SAVE BYTE AFTER EOS + 08E0 26: 8A 5E 00 MOV BL,ES:[BP] + 08E4 26: C6 46 00 00 MOV BYTE PTR ES:[BP],0 ;ZERO IT TO MAKE STRING ASCIZ + 08E9 E8 196F R CALL .PRINT ;PRINT IT + 08EC 26: 88 5E 00 MOV ES:[BP],BL ;AND RESTORE OLD BYTE + 08F0 FE 0E 02C3 R DEC RDNWDS ;REMEMBER THAT WE FLUSHED THIS WORD + 08F4 E9 098F R JMP ORD23$ ;AND WE'RE DONE + 08F7 8B C3 ORD16$: MOV AX,BX ;CALCULATE NUMBER OF CHARACTERS IN WORD + 08F9 F7 D8 NEG AX + 08FB 03 C2 ADD AX,DX + 08FD 26: 88 45 02 MOV ES:[DI+2],AL ;SAVE THE NUMBER IN RET TABLE + 0901 2B 1E 02BD R SUB BX,RDBOS ;BYTE OFFSET FOR BEGINNING OF WORD + 0905 26: 88 5D 03 MOV ES:[DI+3],BL ;STORE IT, TOO + 0909 8B E9 MOV BP,CX ;MAKE WORD STRING ASCIZ + 090B 3E: C6 46 00 00 MOV BYTE PTR DS:[BP],0 + 0910 B8 02B5 R MOV AX,OFFSET RDWSTR;POINT TO IT + 0913 E8 0DDF R CALL ZWORD ;AND CONVERT TO (2-WORD) ZWORD + 0916 52 PUSH DX ;SAVE CHAR & WORD ENTRY POINTERS + 0917 57 PUSH DI + 0918 8B F8 MOV DI,AX ;FIRST ZWORD WORD + 091A 8B 36 02F1 R MOV SI,VWORDS ;NUMBER OF VOCABULARY WORDS + 091E 8B C6 MOV AX,SI + 0920 48 DEC AX ;WE WANT TO POINT TO LAST WORD +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 10-7 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + I/O OPERATIONS + + 0921 F7 26 02EF R MUL VWLEN ;MULTIPLY BY WORD LENGTH IN BYTES + 0925 03 06 02F3 R ADD AX,VOCBEG ;ADD POINTER TO BEGINNING TO FIND LAST WORD + 0929 8B C8 MOV CX,AX ;POINTER TO LAST WORD + 092B 8B D7 MOV DX,DI ;FIRST ZWORD WORD + 092D 8B FB MOV DI,BX ;SECOND ZWORD WORD + 092F 8B 1E 02EF R MOV BX,VWLEN ;CALCULATE INITIAL OFFSET FOR BINARY SEARCH + 0933 D1 FE SAR SI,1 + 0935 D1 E3 ORD17$: SAL BX,1 + 0937 D1 FE SAR SI,1 + 0939 83 FE 00 CMP SI,0 + 093C 75 F7 JNE ORD17$ + 093E 8B 36 02F3 R MOV SI,VOCBEG ;BEGINNING OF WORD TABLE + 0942 03 F3 ADD SI,BX ;ADD CURRENT OFFSET(HALF OF POWER-OF-2 TABLE) + 0944 50 PUSH AX ;SAVE + 0945 A1 02EF R MOV AX,VWLEN ;AVOID FENCEPOST BUG FOR EXACT POWER-OF-2 TBL + 0948 2B F0 SUB SI,AX + 094A 58 POP AX ;RESTORE + 094B D1 FB ORD18$: SAR BX,1 ;NEXT OFFSET WILL BE HALF OF PREVIOUS ONE + GTAWRD A,[SI] ;GET FIRST HALF OF CURRENT ZWORD + 094D 26: 8B 04 + MOV AX,ES:[SI] + 0950 86 E0 + XCHG AH,AL + 0952 3B D0 CMP DX,AX ;COMPARE DESIRED ONE TO IT + 0954 77 15 JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + 0956 72 1E JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + 0958 8B EE MOV BP,SI ;SAME, GET SECOND HALF + 095A 45 INC BP + 095B 45 INC BP + GTAWRD A,[BP] + 095C 26: 8B 46 00 + MOV AX,ES:[BP] + 0960 86 E0 + XCHG AH,AL + 0962 3B F8 CMP DI,AX ;COMPARE DESIRED WORD WITH IT + 0964 77 05 JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + 0966 72 0E JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + 0968 EB 16 90 JMP ORD22$ ;SAME, WE'VE FOUND IT, RETURN IT + 096B 03 F3 ORD19$: ADD SI,BX ;TO MOVE UP, ADD CURRENT OFFSET + 096D 3B F1 CMP SI,CX ;HAVE WE MOVED PAST END OF TABLE? + 096F 76 07 JBE ORD21$ ;NO + 0971 8B F1 MOV SI,CX ;YES, POINT TO END OF TABLE INSTEAD + 0973 EB 03 90 JMP ORD21$ + 0976 2B F3 ORD20$: SUB SI,BX ;TO MOVE DOWN, SIMPLY SUBTRACT OFFSET + 0978 3B 1E 02EF R ORD21$: CMP BX,VWLEN ;IS OFFSET RESOLUTION BELOW ONE WORD? + 097C 7D CD JGE ORD18$ ;NO, CONTINUE LOOP + 097E 2B F6 SUB SI,SI ;YES, WORD NOT FOUND, RETURN ZERO + 0980 5F ORD22$: POP DI ;RESTORE WORD ENTRY POINTER + 0981 8B D6 MOV DX,SI ;POINTER TO WORD FOUND + 0983 86 F2 XCHG DH,DL + 0985 26: 89 15 MOV ES:[DI],DX ;STORE IT + 0988 5A POP DX ;RESTORE CHAR POINTER + 0989 83 C7 04 ADD DI,4 ;UPDATE POINTER FOR NEXT WORD ENTRY + 098C E9 0861 R JMP ORD8$ ;GO FOR IT + 098F FF 06 02C1 R ORD23$: INC RDRET ;DONE, STORE NUMBER OF WORDS FOUND + 0993 8B 2E 02C1 R MOV BP,RDRET + MOVM ES:[BP],RDNWDS,DL +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 10-8 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + I/O OPERATIONS + + 0997 8A 16 02C3 R + MOV DL,RDNWDS + 099B 26: 88 56 00 + MOV ES:[BP],DL + 099F 5F POP DI ;RESTORE USER STACK POINTER + 09A0 C3 RET ;AND RETURN + 09A1 OPREAD ENDP + + ;PRINTC (PRINT CHAR WHOSE ASCII VALUE IS GIVEN) + 09A1 OPPRNC PROC + 09A1 E9 0E61 R JMP PUTCHR ;QUEUE THE CHARACTER FOR PRINTING + 09A4 OPPRNC ENDP + + ;PRINTN (PRINT A NUMBER) + 09A4 OPPRNN PROC + 09A4 8B D8 MOV BX,AX ;NUMBER TO PRINT + 09A6 83 FB 00 CMP BX,0 + 09A9 75 06 JNE OPN1$ ;NON-ZERO + 09AB B8 0030 MOV AX,"0" ;SPECIAL CASE ZERO + 09AE E9 0E61 R JMP PUTCHR + 09B1 7F 08 OPN1$: JG OPN2$ ;POSITIVE? + 09B3 B8 002D MOV AX,"-" ;NO, PRINT MINUS SIGN + 09B6 E8 0E61 R CALL PUTCHR + 09B9 F7 DB NEG BX ;AND MAKE IT POSITIVE + 09BB 2B C9 OPN2$: SUB CX,CX ;COUNT OF DIGITS ON STACK + 09BD EB 0D 90 JMP OPN4$ ;START WITH GREATER-THAN-10 TEST + 09C0 8B C3 OPN3$: MOV AX,BX ;EXTRACT A DIGIT + 09C2 BD 000A MOV BP,10 + 09C5 99 CWD + 09C6 F7 FD IDIV BP + 09C8 52 PUSH DX ;PUSH IT + 09C9 41 INC CX ;BUMP COUNT + 09CA 8B D8 MOV BX,AX ;GET QUOTIENT + 09CC 83 FB 0A OPN4$: CMP BX,10 ;MORE DIGITS TO EXTRACT? + 09CF 7D EF JGE OPN3$ ;YES, GO LOOP + 09D1 8B C3 MOV AX,BX ;NO, GET LAST (FIRST) DIGIT + 09D3 EB 02 90 JMP OPN6$ ;ALREADY IN PLACE + 09D6 58 OPN5$: POP AX ;POP NEXT DIGIT + 09D7 05 0030 OPN6$: ADD AX,"0" ;ASCIIZE IT + 09DA E8 0E61 R CALL PUTCHR ;QUEUE IT + 09DD 49 DEC CX ;REDUCE DIGIT COUNT + 09DE 7D F6 JGE OPN5$ ;LOOP IF SOME LEFT + 09E0 C3 RET ;ELSE, RETURN + 09E1 OPPRNN ENDP + + ;PRINT (THE STRING POINTED TO BY ES:AX) + 09E1 OPPRIN PROC + 09E1 E8 0C6B R CALL BSPLIT ;SPLIT THE BLOCK & WORD NUMBERS + 09E4 E9 0CA1 R JMP PUTSTR ;PRINT THE STRING + 09E7 OPPRIN ENDP + + ;PRINTB (PRINT THE STRING POINTED TO BY THE BYTE-POINTER ES:AX) + 09E7 OPPRNB PROC + 09E7 E8 0C5D R CALL BSPLTB ;SPLIT THE BLOCK & BYTE NUMBERS + 09EA E9 0CA1 R JMP PUTSTR ;PRINT THE STRING +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 10-9 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + I/O OPERATIONS + + 09ED OPPRNB ENDP + + ;PSEUDO-INSTRUCTIONS FOR HOURS/MINUTES HERE FOR STATUS LINE + 09ED OPPRNH PROC + 09ED C6 06 004C R 00 MOV PMFLAG,0 + 09F2 3C 0C CMP AL,12 + 09F4 7C 05 JL OPH0$ + 09F6 C6 06 004C R 01 MOV PMFLAG,1 + 09FB 3C 00 OPH0$: CMP AL,0 + 09FD 75 02 JNE OPH00$ + 09FF B0 0C MOV AL,12 + 0A01 3C 0C OPH00$: CMP AL,12 + 0A03 7E 02 JLE OPH1$ + 0A05 2C 0C SUB AL,12 ;HOUR SLOT IS 24 HOUR TIME + 0A07 3C 09 OPH1$: CMP AL,9 + 0A09 7F 07 JG OPH2$ + 0A0B 50 PUSH AX + 0A0C B0 20 MOV AL,32 + 0A0E E8 0E61 R CALL PUTCHR ;OUTPUT SPACE FOR HOUR LESS THAN 10 + 0A11 58 POP AX + 0A12 E8 09A4 R OPH2$: CALL OPPRNN + 0A15 B0 3A MOV AL,":" + 0A17 E9 0E61 R JMP PUTCHR ;AND COLON + 0A1A OPPRNH ENDP + + 0A1A OPPRNM PROC + 0A1A 3C 09 CMP AL,9 + 0A1C 7F 07 JG OPM1$ + 0A1E 50 PUSH AX + 0A1F B0 30 MOV AL,"0" + 0A21 E8 0E61 R CALL PUTCHR + 0A24 58 POP AX + 0A25 E8 09A4 R OPM1$: CALL OPPRNN + 0A28 B0 20 MOV AL,32 + 0A2A E8 0E61 R CALL PUTCHR + 0A2D B0 61 MOV AL,"a" + 0A2F 80 3E 004C R 00 CMP PMFLAG,0 + 0A34 74 02 JE OPM2$ + 0A36 B0 70 MOV AL,"p" + 0A38 E8 0E61 R OPM2$: CALL PUTCHR + 0A3B B0 6D MOV AL,"m" + 0A3D E9 0E61 R JMP PUTCHR + 0A40 OPPRNM ENDP + + ;PRINTD (PRINT OBJ'S SHORT DESCRIPTION) + 0A40 OPPRND PROC + 0A40 E8 0C76 R CALL OBJLOC ;FIND OBJ'S LOCATION + 0A43 05 0007 ADD AX,7 ;PROPERTY TABLE POINTER + 0A46 8B E8 MOV BP,AX + GTAWRD A,[BP] ;GET IT + 0A48 26: 8B 46 00 + MOV AX,ES:[BP] + 0A4C 86 E0 + XCHG AH,AL + 0A4E 40 INC AX ;POINT TO STRING +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 10-10 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + I/O OPERATIONS + + 0A4F E8 0C5D R CALL BSPLTB ;SPLIT POINTER + 0A52 E9 0CA1 R JMP PUTSTR ;AND PRINT THE STRING + 0A55 OPPRND ENDP + + ;PRINTI (PRINT THE STRING FOLLOWING THIS INSTRUCTION) + 0A55 OPPRNI PROC + 0A55 A1 066F R MOV AX,ZPC1 ;GET POINTER TO STRING + 0A58 8B 1E 0671 R MOV BX,ZPC2 + 0A5C E8 0CA1 R CALL PUTSTR ;AND PRINT IT + 0A5F A3 066F R MOV ZPC1,AX ;UPDATE ZPC + 0A62 89 1E 0671 R MOV ZPC2,BX + 0A66 E9 1245 R JMP NEWZPC + 0A69 OPPRNI ENDP + + ;PRINTR (PRINTI FOLLOWED BY RTRUE) + 0A69 OPPRNR PROC + 0A69 E8 0A55 R CALL OPPRNI ;DO A PRINTI + 0A6C E8 0A72 R CALL OPCRLF ;A CRLF + 0A6F E9 0B03 R JMP OPRTRU ;AND AN RTRUE + 0A72 OPPRNR ENDP + + ;CRLF (DO A NEWLINE) + 0A72 OPCRLF PROC + 0A72 E9 0F02 R JMP NEWLIN ;DO A NEWLINE + 0A75 OPCRLF ENDP + + SUBTTL CONTROL OPERATIONS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 11-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + CONTROL OPERATIONS + + PAGE + + + ;CALL (A FUNCTION WITH OPTIONAL ARGUMENTS), # OF ARGS IN AX + 0A75 OPCALL PROC + 0A75 90 NOP ;TELL CALLER TO USE ARGUMENT BLOCK + 0A76 8B D0 MOV DX,AX ;NUMBER OF ARGUMENTS TO CALL + 0A78 A1 0673 R MOV AX,ARGBLK ;FUNCTION TO CALL + 0A7B 3D 0000 CMP AX,0 + 0A7E 75 05 JNE OCL1$ ;ZERO? + 0A80 2B C0 SUB AX,AX ;YES, SIMPLY RETURN A ZERO + 0A82 E9 0C02 R JMP PUTVAL + 0A85 OCL1$: PUSHZ ZPC1 ;OTHERWISE, SAVE OLD ZPC + 0A85 87 E7 + XCHG SP,DI + 0A87 FF 36 066F R + PUSH ZPC1 + 0A8B 87 E7 + XCHG SP,DI + PUSHZ ZPC2 + 0A8D 87 E7 + XCHG SP,DI + 0A8F FF 36 0671 R + PUSH ZPC2 + 0A93 87 E7 + XCHG SP,DI + 0A95 8B 0E 066D R MOV CX,ZLOCS ;AND OLD LOCAL POINTER + ; SUB CX,STKBOT ;BUT RELATIVIZE IT IN CASE OF SAVE + PUSHZ CX ;AND SAVE IT + 0A99 87 E7 + XCHG SP,DI + 0A9B 51 + PUSH CX + 0A9C 87 E7 + XCHG SP,DI + 0A9E E8 0C6B R CALL BSPLIT ;SPLIT FUNCTION POINTER + 0AA1 A3 066F R MOV ZPC1,AX ;MAKE IT THE NEW ZPC + 0AA4 89 1E 0671 R MOV ZPC2,BX + 0AA8 E8 1245 R CALL NEWZPC ;UPDATE ZPC STUFF + 0AAB 89 3E 066D R MOV ZLOCS,DI ;LOCALS WILL START AT NEXT STACK SLOT + 0AAF 83 2E 066D R 02 SUB ZLOCS,2 + 0AB4 E8 0B60 R CALL NXTBYT ;NUMBER OF LOCALS + 0AB7 8B D8 MOV BX,AX + 0AB9 BD 0675 R MOV BP,OFFSET ARGBLK[2] ;POINT TO FIRST OPTIONAL ARG + 0ABC 4B OCL2$: DEC BX ;ANY MORE LOCALS? + 0ABD 7C 1A JL OCL4$ ;NO, WE'RE DONE + 0ABF E8 0B80 R CALL NXTWRD ;YES, GET THE NEXT LOCAL DEFAULT VALUE + 0AC2 4A DEC DX ;ANY MORE OPTIONALS GIVEN? + 0AC3 7E 0D JLE OCL3$ ;NO + PUSHZ DS:[BP] ;YES, USE ITS VALUE + 0AC5 87 E7 + XCHG SP,DI + 0AC7 3E: FF 76 00 + PUSH DS:[BP] + 0ACB 87 E7 + XCHG SP,DI + 0ACD 83 C5 02 ADD BP,2 + 0AD0 EB EA JMP OCL2$ ;AND CONTINUE LOOP + 0AD2 OCL3$: PUSHZ AX ;OTHERWISE, USE DEFAULT + 0AD2 87 E7 + XCHG SP,DI + 0AD4 50 + PUSH AX + 0AD5 87 E7 + XCHG SP,DI + 0AD7 EB E3 JMP OCL2$ ;AND LOOP + 0AD9 C3 OCL4$: RET + 0ADA OPCALL ENDP + +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 11-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + CONTROL OPERATIONS + + ;RETURN (FROM CURRENT FUNCTION CALL) + 0ADA OPRETU PROC + 0ADA 8B 3E 066D R MOV DI,ZLOCS ;RESTORE OLD TOP OF STACK + POPZ DX ;DUMMY POP [WHY?] + 0ADE 87 E7 + XCHG SP,DI + 0AE0 5A + POP DX + 0AE1 87 E7 + XCHG SP,DI + POPZ ZLOCS ;AND OTHER VALUES + 0AE3 87 E7 + XCHG SP,DI + 0AE5 8F 06 066D R + POP ZLOCS + 0AE9 87 E7 + XCHG SP,DI + + ; MOV DX,STKBOT ;RE-ABSOLUTIZE THIS ONE + ; ADD ZLOCS,DX + + POPZ ZPC2 + 0AEB 87 E7 + XCHG SP,DI + 0AED 8F 06 0671 R + POP ZPC2 + 0AF1 87 E7 + XCHG SP,DI + POPZ ZPC1 + 0AF3 87 E7 + XCHG SP,DI + 0AF5 8F 06 066F R + POP ZPC1 + 0AF9 87 E7 + XCHG SP,DI + 0AFB 50 PUSH AX ;VALUE TO RETURN + 0AFC E8 1245 R CALL NEWZPC ;UPDATE ZPC STUFF + 0AFF 58 POP AX + 0B00 E9 0C02 R JMP PUTVAL ;RETURN THE VALUE + 0B03 OPRETU ENDP + + ;RTRUE + 0B03 OPRTRU PROC + 0B03 B8 0001 MOV AX,1 ;RETURN A 1 + 0B06 EB D2 JMP OPRETU + 0B08 OPRTRU ENDP + + ;RFALSE + 0B08 OPRFAL PROC + 0B08 2B C0 SUB AX,AX ;RETURN A 0 + 0B0A EB CE JMP OPRETU + 0B0C OPRFAL ENDP + + ;JUMP (TO A NEW LOCATION) + 0B0C OPJUMP PROC + 0B0C 01 06 0671 R ADD ZPC2,AX ;ADD OFFSET TO CURRENT ZPC + 0B10 83 2E 0671 R 02 SUB ZPC2,2 ;ADJUST IT + 0B15 E9 1245 R JMP NEWZPC ;NORMALIZE IT & UPDATE ZPC STUFF + 0B18 OPJUMP ENDP + + ;RSTACK (RETURN STACK) + 0B18 OPRSTA PROC + POPZ AX ;POP A VALUE + 0B18 87 E7 + XCHG SP,DI + 0B1A 58 + POP AX +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 11-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + CONTROL OPERATIONS + + 0B1B 87 E7 + XCHG SP,DI + 0B1D EB BB JMP OPRETU ;AND RETURN IT + 0B1F OPRSTA ENDP + + ;FSTACK (FLUSH A VALUE OFF THE STACK) + 0B1F OPFSTA PROC + POPZ DX ;FLUSH ONE + 0B1F 87 E7 + XCHG SP,DI + 0B21 5A + POP DX + 0B22 87 E7 + XCHG SP,DI + 0B24 C3 RET + 0B25 OPFSTA ENDP + + ;NOOP (NO OPERATION) + 0B25 OPNOOP PROC + 0B25 C3 RET ;DO NOTHING + 0B26 OPNOOP ENDP + + SUBTTL LOW LEVEL FUNCTIONS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 12-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + LOW LEVEL FUNCTIONS + + PAGE + + + ;GET A BYTE, BLOCK-POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX, + ;UPDATE AX & BX TO REFLECT BYTE GOTTEN + 0B26 GETBYT PROC + 0B26 50 PUSH AX ;SAVE BLOCK-POINTER + 0B27 3B 06 02E1 R CMP AX,ENDLOD ;IS THIS A PRELOADED LOCATION? + 0B2B 7D 0D JGE GTY1$ ;NO + 0B2D B1 09 MOV CL,9 ;YES, RECONSTRUCT POINTER + 0B2F D3 E0 SHL AX,CL ;SHIFT BLOCK POINTER BY 9 + 0B31 0B C3 OR AX,BX ;ADD IN THE OFFSET + 0B33 93 XCHG AX,BX + 0B34 26: 8A 0F MOV CL,ES:[BX] ;GET THE BYTE + 0B37 EB 0A 90 JMP GTY2$ ;CLEAR UNWANTED BYTE & RETURN IT + 0B3A E8 12E1 R GTY1$: CALL GETPAG ;FIND THE PROPER PAGE + 0B3D 03 C3 ADD AX,BX ;POINT TO DESIRED BYTE + 0B3F 93 XCHG AX,BX + 0B40 26: 8A 0F MOV CL,ES:[BX] ;GET IT + 0B43 2A ED GTY2$: SUB CH,CH ;CLEAR UNWANTED BYTE & RETURN IT + 0B45 8B D8 MOV BX,AX + 0B47 58 POP AX ;RESTORE BLOCK-POINTER + 0B48 43 INC BX ;UPDATE POINTER + 0B49 81 FB 0200 CMP BX,200H ;END-OF-PAGE? + 0B4D 75 03 JNE GTY3$ ;NO + 0B4F 2B DB SUB BX,BX ;YES, CLEAR BYTE-POINTER + 0B51 40 INC AX ;AND UPDATE BLOCK-POINTER + 0B52 C3 GTY3$: RET + 0B53 GETBYT ENDP + + ;GET A WORD, BLOCK POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX + 0B53 GETWRD PROC + 0B53 52 PUSH DX ;SAVE + 0B54 E8 0B26 R CALL GETBYT ;GET HIGH-ORDER BYTE + 0B57 51 PUSH CX ;SAVE IT + 0B58 E8 0B26 R CALL GETBYT ;GET LOW-ORDER BYTE + 0B5B 5A POP DX ;GET OTHER BYTE + 0B5C 8A EA MOV CH,DL ;POSITION IT + 0B5E 5A POP DX ;RESTORE + 0B5F C3 RET + 0B60 GETWRD ENDP + + ;GET THE NEXT BYTE, RETURN IT IN AX + 0B60 NXTBYT PROC + 0B60 53 PUSH BX ;SAVE + 0B61 8B 1E 0671 R MOV BX,ZPC2 ;BYTE POINTER + 0B65 03 1E 067B R ADD BX,CURPAG ;INDEX INTO CURRENT PAGE + 0B69 26: FF 37 PUSH ES:[BX] ;SAVE BYTE + 0B6C FF 06 0671 R INC ZPC2 ;UPDATE PC + 0B70 81 3E 0671 R 0200 CMP ZPC2,200H ;END-OF-PAGE? + 0B76 7C 03 JL NXB1$ ;NO + 0B78 E8 1245 R CALL NEWZPC ;YES, UPDATE PAGE + 0B7B 58 NXB1$: POP AX ;RETRIEVE BYTE + 0B7C 2A E4 SUB AH,AH ;CLEAR UNWANTED BYTE +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 12-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + LOW LEVEL FUNCTIONS + + 0B7E 5B POP BX ;RESTORE + 0B7F C3 RET ;AND RETURN IT + 0B80 NXTBYT ENDP + + ;GET THE NEXT WORD, RETURN IT IN AX + 0B80 NXTWRD PROC + 0B80 53 PUSH BX ;SAVE + 0B81 E8 0B60 R CALL NXTBYT ;GET HIGH-ORDER BYTE + 0B84 50 PUSH AX ;SAVE IT + 0B85 E8 0B60 R CALL NXTBYT ;GET LOW-ORDER BYTE + 0B88 5B POP BX ;GET HIGH-ORDER BYTE + 0B89 8A E3 MOV AH,BL ;POSITION IT + 0B8B 5B POP BX ;RESTORE + 0B8C C3 RET ;RETURN THE WORD + 0B8D NXTWRD ENDP + + ;GET AN ARGUMENT GIVEN ITS TYPE IN AX + 0B8D GETARG PROC + 0B8D 48 DEC AX ;EXAMINE ARGUMENT + 0B8E 7C F0 JL NXTWRD ;0 MEANT LONG IMMEDIATE + 0B90 74 CE JE NXTBYT ;1 MEANT SHORT IMMEDIATE + 0B92 E8 0B60 R CALL NXTBYT ;2 MEANT VARIABLE, GET THE VAR + 0B95 3D 0000 CMP AX,0 ;STACK? + 0B98 75 06 JNE GETVAR ;NO, JUST GET THE VAR'S VALUE + POPZ AX ;YES, POP THE STACK + 0B9A 87 E7 + XCHG SP,DI + 0B9C 58 + POP AX + 0B9D 87 E7 + XCHG SP,DI + 0B9F C3 RET + 0BA0 GETARG ENDP + + ;GET VALUE OF A VARIABLE, VAR IN AX, VALUE RETURNED IN AX + 0BA0 GETVAR PROC + 0BA0 3D 0000 CMP AX,0 ;STACK? + 0BA3 75 04 JNE GTV1$ ;NO + POPZT AX ;YES, GET TOP-OF-STACK + 0BA5 36: 8B 05 + MOV AX,SS:[DI] + 0BA8 C3 RET + 0BA9 55 GTV1$: PUSH BP ;SAVE + 0BAA 3D 0010 CMP AX,16 ;LOCAL? + 0BAD 7D 0E JGE GTV3$ ;NO + 0BAF 48 DEC AX ;YES, POINT TO PROPER STACK ELEMENT + 0BB0 D1 E0 SHL AX,1 + 0BB2 8B 2E 066D R MOV BP,ZLOCS + 0BB6 2B E8 SUB BP,AX + 0BB8 8B 46 00 MOV AX,[BP] ;AND GET IT + 0BBB 5D GTV2$: POP BP ;RESTORE + 0BBC C3 RET + 0BBD 2D 0010 GTV3$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + 0BC0 D1 E0 SHL AX,1 + 0BC2 03 06 02E7 R ADD AX,GLOTAB + 0BC6 8B E8 MOV BP,AX ;AND GET IT + GTAWRD A,[BP] +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 12-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + LOW LEVEL FUNCTIONS + + 0BC8 26: 8B 46 00 + MOV AX,ES:[BP] + 0BCC 86 E0 + XCHG AH,AL + 0BCE EB EB JMP GTV2$ + 0BD0 GETVAR ENDP + + ;UPDATE VALUE OF A VARIABLE, VAR IN AX, NEW VALUE IN BX + 0BD0 PUTVAR PROC + 0BD0 3D 0000 CMP AX,0 ;STACK? + 0BD3 75 04 JNE PTV1$ ;NO + PUSHZT BX ;YES, UPDATE TOP-OF-STACK + 0BD5 36: 89 1D + MOV SS:[DI],BX + 0BD8 C3 RET + 0BD9 3D 0010 PTV1$: CMP AX,16 ;LOCAL? + 0BDC 7D 0F JGE PTV2$ ;NO + 0BDE 55 PUSH BP ;SAVE + 0BDF 48 DEC AX ;YES, POINT TO PROPER STACK ELEMENT + 0BE0 D1 E0 SHL AX,1 + 0BE2 8B 2E 066D R MOV BP,ZLOCS + 0BE6 2B E8 SUB BP,AX + 0BE8 89 5E 00 MOV [BP],BX ;AND UPDATE IT + 0BEB 5D POP BP ;RESTORE + 0BEC C3 RET + 0BED 2D 0010 PTV2$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + 0BF0 D1 E0 SHL AX,1 + 0BF2 03 06 02E7 R ADD AX,GLOTAB + 0BF6 93 XCHG AX,BX ;AND UPDATE IT + PTAWRD [BX],A + 0BF7 86 E0 + XCHG AH,AL + 0BF9 26: 89 07 + MOV ES:[BX],AX + 0BFC C3 RET + 0BFD PUTVAR ENDP + + ;RETURN VAL IN AX TO LOCATION SPECIFIED BY NEXTBYTE + ;DESTROYS BX, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION + 0BFD BYTVAL PROC + 0BFD 2A E4 SUB AH,AH ;THIS ENTRY FOR BYTE VALUE TO CLEAR HIGH BYTE + 0BFF EB 01 90 JMP PUTVAL + 0C02 BYTVAL ENDP + + 0C02 PUTVAL PROC + 0C02 8B D8 MOV BX,AX ;NORMAL ENTRY + 0C04 E8 0B60 R CALL NXTBYT ;GET VAR TO USE + 0C07 3D 0000 CMP AX,0 ;STACK? + 0C0A 75 C4 JNE PUTVAR ;NO, GO STORE VALUE + PUSHZ BX ;YES, PUSH ONTO STACK + 0C0C 87 E7 + XCHG SP,DI + 0C0E 53 + PUSH BX + 0C0F 87 E7 + XCHG SP,DI + 0C11 C3 RET ;AND RETURN + 0C12 PUTVAL ENDP + + ;PREDICATE HANDLERS TRUE & FALSE + ;DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FCNS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 12-4 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + LOW LEVEL FUNCTIONS + + 0C12 PFALSE PROC + 0C12 2B DB SUB BX,BX ;PREDICATE WAS FALSE, CLEAR FLAG + 0C14 EB 07 90 JMP PPRED + 0C17 PFALSE ENDP + + 0C17 PTRUE PROC + 0C17 BB 0001 MOV BX,1 ;PREDICATE WAS TRUE, SET FLAG + 0C1A EB 01 90 JMP PPRED + 0C1D PTRUE ENDP + + 0C1D PPRED PROC + 0C1D E8 0B60 R CALL NXTBYT ;GET FIRST (OR ONLY) PREDICATE JUMP BYTE + 0C20 A9 0080 TEST AX,80H ;NORMAL POLARITY PREDICATE? + 0C23 74 01 JE PPR1$ ;NO, LEAVE FLAG ALONE + 0C25 43 INC BX ;YES, INCREMENT FLAG + 0C26 A9 0040 PPR1$: TEST AX,40H ;ONE-BYTE JUMP OFFSET? + 0C29 74 06 JE PPR2$ ;NO + 0C2B 25 FF3F AND AX,0FF3FH ;YES, CLEAR SPECIAL BITS + 0C2E EB 13 90 JMP PPR3$ + 0C31 25 FF3F PPR2$: AND AX,0FF3FH ;CLR SPECIAL BITS FROM HIGH-ORDER OFFSET BYTE + 0C34 8B C8 MOV CX,AX ;HIGH-ORDER BYTE + 0C36 E8 0B60 R CALL NXTBYT ;GET LOW-ORDER BYTE + 0C39 8A E1 MOV AH,CL ;MOVE IN HIGH-ORDER BITS + 0C3B A9 2000 TEST AX,2000H ;IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)? + 0C3E 74 03 JE PPR3$ ;NO + 0C40 0D C000 OR AX,0C000H ;YES, MAKE 16-BIT NUMBER NEGATIVE + 0C43 4B PPR3$: DEC BX ;TEST FLAG + 0C44 74 16 JE PPR6$ ;WAS 1, THAT MEANS DO NOTHING + 0C46 3D 0000 CMP AX,0 ;ZERO JUMP? + 0C49 75 03 JNE PPR4$ ;NO + 0C4B E9 0B08 R JMP OPRFAL ;YES, THAT MEANS DO AN RFALSE + 0C4E 48 PPR4$: DEC AX ;ONE JUMP? + 0C4F 75 03 JNE PPR5$ ;NO + 0C51 E9 0B03 R JMP OPRTRU ;YES, THAT MEANS DO AN RTRUE + 0C54 48 PPR5$: DEC AX ;ADJUST OFFSET + 0C55 01 06 0671 R ADD ZPC2,AX ;ADD TO PC + 0C59 E9 1245 R JMP NEWZPC ;AND UPDATE ZPC STUFF + 0C5C C3 PPR6$: RET + 0C5D PPRED ENDP + + ;SPLIT BYTE-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE OFFSET IN BX + 0C5D BSPLTB PROC + 0C5D 8B D8 MOV BX,AX + 0C5F 86 C4 XCHG AL,AH ;EXTRACT BLOCK BITS + 0C61 D1 E8 SHR AX,1 + 0C63 25 007F AND AX,7FH ;CLEAR UNWANTED BITS + 0C66 81 E3 01FF AND BX,1FFH ;CLEAR ALL BUT BYTE OFFSET BITS + 0C6A C3 RET + 0C6B BSPLTB ENDP + + ;SPLIT WORD-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE-OFFSET IN BX + 0C6B BSPLIT PROC + 0C6B 8B D8 MOV BX,AX +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 12-5 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + LOW LEVEL FUNCTIONS + + 0C6D 8A C4 MOV AL,AH ;EXTRACT BLOCK BITS + 0C6F 2A E4 SUB AH,AH ;CLEAR UNWANTED BITS + 0C71 2A FF SUB BH,BH ;CLEAR ALL BUT WORD OFFSET BITS + 0C73 D1 E3 SHL BX,1 ;CONVERT TO BYTE OFFSET + 0C75 C3 RET + 0C76 BSPLIT ENDP + + SUBTTL OBJECT HACKERS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 13-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + OBJECT HACKERS + + PAGE + + + ;GIVEN OBJ NUMBER IN AX, RETURN OBJ LOCATION IN AX + 0C76 OBJLOC PROC + 0C76 2A E4 SUB AH,AH ;CLEAR UNWANTED BITS + 0C78 53 PUSH BX ;MULTIPLY BY 9 THE LAZY WAY + 0C79 8B D8 MOV BX,AX + 0C7B D1 E0 SHL AX,1 + 0C7D D1 E0 SHL AX,1 + 0C7F D1 E0 SHL AX,1 + 0C81 03 C3 ADD AX,BX + 0C83 5B POP BX ;RESTORE + 0C84 03 06 02E5 R ADD AX,OBJTAB ;INDEX INTO OBJECT TABLE + 0C88 05 0035 ADD AX,53 ;SKIPPING DEFAULT PROPERTY TABLE + 0C8B C3 RET + 0C8C OBJLOC ENDP + + ;GIVEN POINTER TO A PROPERTY IN BX!, UPDATE IT TO POINT TO NEXT PROP + 0C8C NXTPRP PROC + 0C8C 50 PUSH AX ;SAVE + 0C8D 51 PUSH CX ;SAVE + 0C8E 26: 8A 07 MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + 0C91 24 E0 AND AL,MASK PROPSIZE;EXTRACT PROPERTY LENGTH (MINUS 1) + 0C93 B1 05 MOV CL,PROPSIZE + 0C95 D2 E8 SHR AL,CL + 0C97 2A E4 SUB AH,AH + 0C99 03 D8 ADD BX,AX ;ADD IT TO OLD POINTER + 0C9B 83 C3 02 ADD BX,2 ;ADJUST FOR EXTRA LENGTH BYTE PLUS IDENTIFIER + 0C9E 59 POP CX ;RESTORE + 0C9F 58 POP AX ;RESTORE + 0CA0 C3 RET + 0CA1 NXTPRP ENDP + + SUBTTL STRING FUNCTIONS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 14-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STRING FUNCTIONS + + PAGE + + + = 0005 PADCHR EQU 5 ;ZSTR PADDING CHARACTER + + ;OUTPUT A ZSTR, BLOCK-POINTER IN AX, BYTE-POINTER IN BX + ;RETURN UPDATED POINTER + 0CA1 PUTSTR PROC + 0CA1 56 PUSH SI ;SAVE + 0CA2 51 PUSH CX ;SAVE + 0CA3 52 PUSH DX ;SAVE + 0CA4 57 PUSH DI ;SAVE + 0CA5 55 PUSH BP ;SAVE + 0CA6 2B D2 SUB DX,DX ;TEMP CS STARTS AT 0 + 0CA8 2B FF SUB DI,DI ;PERM CS STARTS AT 0 + 0CAA E8 0B53 R PTS1$: CALL GETWRD ;GET NEXT STRING WORD + 0CAD 8B F1 MOV SI,CX + 0CAF 50 PUSH AX ;SAVE POINTER & COPY OF STRING WORD + 0CB0 53 PUSH BX + 0CB1 56 PUSH SI + 0CB2 B9 0003 MOV CX,3 ;3 BYTES IN WORD + 0CB5 56 PTS2$: PUSH SI ;SAVE CURRENT BYTE (IN LOW-ORDER POSITION) + 0CB6 8B E9 MOV BP,CX ;SHIFT TO NEXT BYTE + 0CB8 B1 05 MOV CL,5 + 0CBA D3 FE SAR SI,CL + 0CBC 8B CD MOV CX,BP + 0CBE E2 F5 LOOP PTS2$ ;LOOP UNTIL DONE + 0CC0 B9 0003 MOV CX,3 ;RETRIEVE THE 3 BYTES + 0CC3 5E PTS3$: POP SI ;GET NEXT BYTE + 0CC4 81 E6 001F AND SI,1FH ;CLEAR UNWANTED BITS + 0CC8 83 FA 00 CMP DX,0 ;IN WORD MODE? + 0CCB 7D 18 JGE PTS4$ ;NO {WAS BPL, CHECK} + 0CCD D1 E6 SAL SI,1 ;YES, CALCULATE WORD OFFSET + 0CCF 03 36 02E9 R ADD SI,WRDTAB ;POINT INTO WORD TABLE + 0CD3 03 36 02C4 R ADD SI,WRDOFF ;USING PROPER 32-WORD BLOCK + GTAWRD A,[SI] ;POINT TO WORD STRING + 0CD7 26: 8B 04 + MOV AX,ES:[SI] + 0CDA 86 E0 + XCHG AH,AL + 0CDC E8 0C6B R CALL BSPLIT ;SPLIT IT + 0CDF E8 0CA1 R CALL PUTSTR ;AND PRINT IT + 0CE2 E9 0D76 R JMP PTS15$ ;CONT. WHERE WE LEFT OFF WITH TEMP CS RESET + 0CE5 83 FA 03 PTS4$: CMP DX,3 ;CS 3 SELECTED (ASCII MODE)? + 0CE8 7C 1C JL PTS6$ ;NO, NORMAL CS + 0CEA 75 07 JNE PTS5$ ;NO, BUT WE ARE IN ASCII MODE + 0CEC 86 D6 XCHG DL,DH ;SHIFT SOME BITS HIGH TO MAKE NUMBER LARGE + 0CEE 0B D6 OR DX,SI ;SAVE HIGH-ORDER ASCII BITS HERE + 0CF0 E9 0D78 R JMP PTS16$ ;GO GET NEXT BYTE + 0CF3 81 E2 0003 PTS5$: AND DX,3 ;EXTRACT PREVIOUSLY SAVED HIGH-ORDER BITS + 0CF7 8B E9 MOV BP,CX ;POSITION THEM + 0CF9 B1 05 MOV CL,5 + 0CFB D3 E2 SAL DX,CL + 0CFD 8B CD MOV CX,BP + 0CFF 0B D6 OR DX,SI ;OR IN LOW-ORDER BITS + 0D01 8B C2 MOV AX,DX +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 14-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STRING FUNCTIONS + + 0D03 EB 6E 90 JMP PTS14$ ;GO PRINT THE CHARACTER + 0D06 83 FE 06 PTS6$: CMP SI,6 ;SPECIAL CODE? + 0D09 7C 29 JL PTS9$ ;YES, SPACE, WORD, OR SHIFT + 0D0B 83 FA 02 CMP DX,2 ;MIGHT ALSO BE SPECIAL IF IN CS 2 + 0D0E 75 11 JNE PTS8$ ;BUT WE'RE NOT + 0D10 83 FE 07 CMP SI,7 ;CRLF? + 0D13 74 06 JE PTS7$ ;YES + 0D15 7F 0A JG PTS8$ ;NO, NOT ASCII MODE, EITHER? + 0D17 42 INC DX ;YES IT IS, SWITCH TO ASCII MODE + 0D18 EB 5E 90 JMP PTS16$ ;AND GO GET NEXT BYTE + 0D1B E8 0F02 R PTS7$: CALL NEWLIN ;CRLF REQUESTED, DO A NEWLINE + 0D1E EB 56 90 JMP PTS15$ + 0D21 8B C2 PTS8$: MOV AX,DX ;NORMAL CHARACTER, GET CS + 0D23 BD 001A MOV BP,26 ;CALCULATE OFFSET FOR THIS CS + 0D26 F7 E5 MUL BP + 0D28 03 C6 ADD AX,SI ;ADD IN CHARACTER OFFSET (+6) + 0D2A 2D 0006 SUB AX,6 ;CHARACTER OFFSET + 0D2D BB 09ED R MOV BX,OFFSET ZCHRS ;GET THE CHARACTER FROM CONVERSION VECTOR + 0D30 D7 XLAT ZCHRS + 0D31 EB 40 90 JMP PTS14$ ;GO PRINT IT + 0D34 83 FE 00 PTS9$: CMP SI,0 ;IS IT A SPACE? + 0D37 75 06 JNE PTS10$ ;NO + 0D39 B8 0020 MOV AX," " ;YES, GO PRINT A SPACE + 0D3C EB 35 90 JMP PTS14$ + 0D3F 83 FE 03 PTS10$: CMP SI,3 ;IS IT A WORD? + 0D42 7F 14 JG PTS11$ ;NO, MUST BE A SHIFT + 0D44 81 CA 8000 OR DX,8000H ;SWITCH TO WORD MODE FOR NEXT BYTE + 0D48 4E DEC SI ;CALCULATE WORD-TABLE BLOCK OFFSET + 0D49 8B E9 MOV BP,CX ;64 BYTES IN A BLOCK + 0D4B B1 06 MOV CL,6 + 0D4D D3 E6 SHL SI,CL + 0D4F 8B CD MOV CX,BP + 0D51 89 36 02C4 R MOV WRDOFF,SI ;SAVE IT AND LOOP + 0D55 EB 21 90 JMP PTS16$ + 0D58 83 EE 03 PTS11$: SUB SI,3 ;CALCULATE NEW CS + 0D5B 83 FA 00 CMP DX,0 ;TEMPORARY SHIFT (FROM CS 0)? + 0D5E 75 05 JNE PTS12$ ;NO + 0D60 8B D6 MOV DX,SI ;YES, JUST SAVE NEW TEMP CS + 0D62 EB 14 90 JMP PTS16$ + 0D65 3B F2 PTS12$: CMP SI,DX ;IS THIS THE CURRENT CS? + 0D67 74 02 JE PTS13$ ;YES, DO A PERM SHIFT TO IT + 0D69 2B D2 SUB DX,DX ;OTHERWISE, PERM SHIFT TO CS 0 + 0D6B 8B FA PTS13$: MOV DI,DX ;TEMP & PERM CS'S ARE SAME NOW + 0D6D EB 09 90 JMP PTS16$ + 0D70 E9 0CC3 R PTS3A$: JMP PTS3$ ;DUMMY FOR NON-SHORT LOOP + 0D73 E8 0E61 R PTS14$: CALL PUTCHR ;PRINT THE CHARACTER + 0D76 8B D7 PTS15$: MOV DX,DI ;RESET TEMP CS TO PERM CS + 0D78 E2 F6 PTS16$: LOOP PTS3A$ ;NEXT BYTE + 0D7A 5E POP SI ;RESTORE POINTERS & ORIGINAL STRING WORD + 0D7B 5B POP BX + 0D7C 58 POP AX + 0D7D 83 FE 00 CMP SI,0 ;END-OF-STRING? + 0D80 7C 03 JL PTS1A$ ;YES, CLEAN UP & RETURN UPDATED POINTER +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 14-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STRING FUNCTIONS + + 0D82 E9 0CAA R JMP PTS1$ ;NO, GET NEXT WORD + 0D85 5D PTS1A$: POP BP ;RESTORES + 0D86 5F POP DI + 0D87 5A POP DX + 0D88 59 POP CX + 0D89 5E POP SI + 0D8A C3 RET + 0D8B PUTSTR ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN THE CHARACTER SET # IN AX + 0D8B CHRCS PROC + 0D8B 3D 0000 CMP AX,0 ;IS THIS A NULL? + 0D8E 75 04 JNE CCS1$ ;NO + 0D90 B8 0003 MOV AX,3 ;YES, RETURN DUMMY CS NUMBER + 0D93 C3 RET + 0D94 53 CCS1$: PUSH BX ;SAVE + 0D95 BB 09ED R MOV BX,OFFSET ZCHRS ;POINT TO CONVERSION VECTOR + 0D98 43 CCS2$: INC BX ;FOUND THE CHARACTER? + 0D99 3A 47 FF CMP AL,[BX-1] + 0D9C 74 0B JE CCS3$ ;YES + 0D9E 80 3F 00 CMP BYTE PTR [BX],0 ;NO, END OF STRING? + 0DA1 75 F5 JNE CCS2$ ;NO, CONTINUE LOOP + 0DA3 B8 0002 MOV AX,2 ;YES, CALL IT CS 2 + 0DA6 EB 0F 90 JMP CCS5$ + 0DA9 81 EB 09ED R CCS3$: SUB BX,OFFSET ZCHRS ;FIND CHARACTER POSITION + 0DAD 2B C0 SUB AX,AX ;START WITH CS 0 + 0DAF 83 EB 1A CCS4$: SUB BX,26 ;EVERY 26 CHARACTERS IS A NEW CS + 0DB2 7E 03 JLE CCS5$ ;DONE + 0DB4 40 INC AX ;INCREMENT CS # & CONTINUE LOOP + 0DB5 EB F8 JMP CCS4$ + 0DB7 5B CCS5$: POP BX + 0DB8 C3 RET + 0DB9 CHRCS ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN ZSTR BYTE VALUE IN AX + 0DB9 CHRBYT PROC + 0DB9 53 PUSH BX ;SAVE + 0DBA BB 09ED R MOV BX,OFFSET ZCHRS ;POINT TO CHARACTER CONVERSION TABLE + 0DBD 43 CHB1$: INC BX ;FOUND THE CHARACTER? + 0DBE 3A 47 FF CMP AL,[BX-1] + 0DC1 74 0A JE CHB2$ ;YES + 0DC3 80 3F 00 CMP BYTE PTR [BX],0 ;NO, END OF STRING? + 0DC6 75 F5 JNE CHB1$ ;NO, CONTINUE LOOP + 0DC8 2B C0 SUB AX,AX ;YES, RETURN ZERO FOR FAILURE + 0DCA EB 11 90 JMP CHB4$ + 0DCD 81 EB 09E8 R CHB2$: SUB BX,OFFSET ZCHRS-5 ;ADJUST POINTER SO FIRST CHARACTER IS 6 + 0DD1 8B C3 MOV AX,BX + 0DD3 3D 0020 CHB3$: CMP AX,32 ;SUBTRACT MULTIPLES OF 26 UNTIL BASE CODE + 0DD6 7C 05 JL CHB4$ + 0DD8 2D 001A SUB AX,26 + 0DDB EB F6 JMP CHB3$ + 0DDD 5B CHB4$: POP BX ;RESTORE + 0DDE C3 RET +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 14-4 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STRING FUNCTIONS + + 0DDF CHRBYT ENDP + + ;CONVERT UP TO 6 ASCIZ CHARS POINTED TO BY DS:AX + ;TO A 2-WORD ZSTR RETURNED IN AX & BX + 0DDF ZWORD PROC + 0DDF 56 PUSH SI ;SAVES + 0DE0 51 PUSH CX + 0DE1 52 PUSH DX + 0DE2 57 PUSH DI + 0DE3 55 PUSH BP + 0DE4 8B F0 MOV SI,AX ;CHARACTER STRING POINTER + 0DE6 2B FF SUB DI,DI ;CS STARTS AT 0 + 0DE8 B9 0006 MOV CX,6 ;MAKE 6 ZSTR BYTES + 0DEB 46 ZWD1$: INC SI ;GET NEXT CHARACTER + 0DEC 8A 5C FF MOV BL,[SI-1] + 0DEF 80 FB 00 CMP BL,0 + 0DF2 75 09 JNE ZWD3$ ;NOT END-OF-STRING + 0DF4 B8 0005 MOV AX,OFFSET PADCHR;AT END-OF-STRING, PAD WITH PAD CHARACTER + 0DF7 50 ZWD2$: PUSH AX ;SAVE A PAD BYTE + 0DF8 E2 FD LOOP ZWD2$ ;LOOP UNTIL DONE + 0DFA EB 3A 90 JMP ZWD6$ ;THEN GO FORM ZWORD + 0DFD 8B C3 ZWD3$: MOV AX,BX + 0DFF E8 0D8B R CALL CHRCS ;FIND THE CS NUMBER FOR THIS CHAR + 0E02 3D 0000 CMP AX,0 ;CS 0? + 0E05 74 07 JE ZWD4$ ;YES + 0E07 05 0003 ADD AX,3 ;NO, CALCULATE TEMP SHIFT BYTE + 0E0A 50 PUSH AX ;SAVE THE SHIFT BYTE + 0E0B 49 DEC CX ;REDUCE BYTE COUNT + 0E0C 74 28 JE ZWD6$ ;DONE + 0E0E 8B C3 ZWD4$: MOV AX,BX ;FIND THE PROPER BYTE VALUE FOR THIS CHAR + 0E10 E8 0DB9 R CALL CHRBYT + 0E13 3D 0000 CMP AX,0 ;IN NORMAL CS'S? + 0E16 75 1B JNE ZWD5$ ;YES + 0E18 B8 0006 MOV AX,6 ;NO, USE ASCII SHIFT + 0E1B 50 PUSH AX + 0E1C 49 DEC CX ;DONE YET? + 0E1D 74 17 JE ZWD6$ ;YES + 0E1F 8B C3 MOV AX,BX ;NO, SAVE HIGH-ORDER ASCII BITS + 0E21 8B E9 MOV BP,CX + 0E23 B1 05 MOV CL,5 + 0E25 D3 F8 SAR AX,CL + 0E27 8B CD MOV CX,BP + 0E29 50 PUSH AX + 0E2A 49 DEC CX ;DONE YET? + 0E2B 74 09 JE ZWD6$ ;YES + 0E2D 81 E3 001F AND BX,1FH ;NO, SAVE LOW-ORDER ASCII BITS + 0E31 8B C3 MOV AX,BX + 0E33 50 ZWD5$: PUSH AX ;SAVE THIS BYTE + 0E34 E2 B5 LOOP ZWD1$ ;LOOP UNTIL ZWORD FULL + 0E36 8B EC ZWD6$: MOV BP,SP ;BUILD ZWORD WORDS FROM 6 SAVED BYTES + 0E38 8B 46 0A MOV AX,[BP+10] + 0E3B B1 05 MOV CL,5 + 0E3D D3 E0 SHL AX,CL +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 14-5 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + STRING FUNCTIONS + + 0E3F 0B 46 08 OR AX,[BP+8] + 0E42 D3 E0 SHL AX,CL + 0E44 0B 46 06 OR AX,[BP+6] + 0E47 8B 5E 04 MOV BX,[BP+4] + 0E4A D3 E3 SHL BX,CL + 0E4C 0B 5E 02 OR BX,[BP+2] + 0E4F D3 E3 SHL BX,CL + 0E51 0B 5E 00 OR BX,[BP] + 0E54 81 CB 8000 OR BX,8000H ;SET END-OF-STRING BIT IN SECOND WORD + 0E58 83 C4 0C ADD SP,12 ;FLUSH STACK + 0E5B 5D POP BP ;RESTORES + 0E5C 5F POP DI + 0E5D 5A POP DX + 0E5E 59 POP CX + 0E5F 5E POP SI + 0E60 C3 RET + 0E61 ZWORD ENDP + + SUBTTL TERMINAL I/O +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 15-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + TERMINAL I/O + + PAGE + + + ;QUEUE CHARACTER IN AX FOR OUTPUT + 0E61 PUTCHR PROC + 0E61 55 PUSH BP + 0E62 80 3E 004B R 00 CMP USLMOD,0 + 0E67 74 22 JE PTC0$ + 0E69 50 PUSH AX ;SAVE EVERYTHING + 0E6A 53 PUSH BX + 0E6B 51 PUSH CX + 0E6C 56 PUSH SI + 0E6D 57 PUSH DI + 0E6E 2A FF SUB BH,BH + 0E70 B4 09 MOV AH,9 + 0E72 B9 0001 MOV CX,1 + 0E75 8A 1E 0001 R MOV BL,USLATR + 0E79 CD 10 INT 10H ;OUTPUT CHARACTER IN INVERSE VIDEO + 0E7B B4 03 MOV AH,3 + 0E7D CD 10 INT 10H ;READ CURSOR + 0E7F 42 INC DX + 0E80 B4 02 MOV AH,2 + 0E82 CD 10 INT 10H ;MOVE CURSOR FORWARD + 0E84 5F POP DI + 0E85 5E POP SI + 0E86 59 POP CX + 0E87 5B POP BX + 0E88 58 POP AX + 0E89 5D POP BP + 0E8A C3 RET + 0E8B 8B 2E 02C6 R PTC0$: MOV BP,CHRPTR ;END OF BUFFER? + 0E8F 3B 2E 02C8 R CMP BP,ENDBUF + 0E93 75 5F JNE PTC7$ ;NO + 0E95 50 PUSH AX ;YES, ENTER OUTPUT ROUTINE; SAVES + 0E96 53 PUSH BX + 0E97 56 PUSH SI + 0E98 8B 1E 02C8 R MOV BX,ENDBUF ;END OF BUFFER + 0E9C BE 04F5 R MOV SI,OFFSET OUTBUF;BEGINNING OF BUFFER + 0E9F 4B PTC1$: DEC BX ;SEARCH FOR SPACE BACKWARDS FROM END + 0EA0 80 3F 20 CMP BYTE PTR [BX]," " + 0EA3 74 20 JE PTC3$ + 0EA5 3B DE CMP BX,SI ;STOP AT BEGINNING OF BUFFER + 0EA7 75 F6 JNE PTC1$ + 0EA9 PTC2$: PRINT OUTBUF ;NO SPACES, OUTPUT WHOLE LINE + 0EA9 50 + PUSH AX + 0EAA B8 04F5 R + MOV AX,OFFSET OUTBUF + 0EAD E8 196F R + CALL .PRINT + 0EB0 58 + POP AX + 0EB1 89 36 02C6 R MOV CHRPTR,SI ;RESTORE POINTER TO BEGINNING OF BUFFER + 0EB5 8B EC MOV BP,SP + 0EB7 80 7E 04 20 CMP BYTE PTR [BP+4]," " ;DID A SPACE CAUSE BUFFER OVERFLOW? + 0EBB 75 2F JNE PTC6$ ;NO + 0EBD C7 46 04 0000 MOV WORD PTR [BP+4],0 ;YES, FLUSH IT + 0EC2 EB 28 90 JMP PTC6$ ;AND RETURN +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 15-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + TERMINAL I/O + + 0EC5 3B DE PTC3$: CMP BX,SI ;DEGENERATE CASE WITH SPACE AT OUTBUF? + 0EC7 74 E0 JE PTC2$ ;YES, OUTPUT WHOLE LINE + 0EC9 C6 07 00 MOV BYTE PTR [BX],0 ;NO, OUTPUT UP TO SPACE + PRINT OUTBUF + 0ECC 50 + PUSH AX + 0ECD B8 04F5 R + MOV AX,OFFSET OUTBUF + 0ED0 E8 196F R + CALL .PRINT + 0ED3 58 + POP AX + 0ED4 A1 02C8 R MOV AX,ENDBUF ;END OF BUFFER + 0ED7 43 INC BX ;START GETTING CHARACTERS AFTER THE SPACE + 0ED8 3B D8 PTC4$: CMP BX,AX ;AT END YET? + 0EDA 74 0C JE PTC5$ ;YES + 0EDC 8B E8 MOV BP,AX ;SAVE AX + MOVM [SI],[BX],AL ;NO, COPY NEXT CHAR TO BEGINNING OF BUF + 0EDE 8A 07 + MOV AL,[BX] + 0EE0 88 04 + MOV [SI],AL + 0EE2 8B C5 MOV AX,BP ;RESTORE AX + 0EE4 43 INC BX + 0EE5 46 INC SI + 0EE6 EB F0 JMP PTC4$ ;AND CONTINUE + 0EE8 89 36 02C6 R PTC5$: MOV CHRPTR,SI ;NEXT CHAR WILL GO AFTER COPIED STUFF + 0EEC 5E PTC6$: POP SI ;CLEAN UP + 0EED 5B POP BX + 0EEE 58 POP AX + 0EEF 3D 0000 CMP AX,0 ;AND IGNORE A NULL CHARACTER + 0EF2 74 0C JE PTC8$ + 0EF4 8B 2E 02C6 R PTC7$: MOV BP,CHRPTR ;NOW STORE THE CHARACTER IN BUFFER + 0EF8 3E: 88 46 00 MOV DS:[BP],AL + 0EFC FF 06 02C6 R INC CHRPTR ;UPDATE POINTER + 0F00 5D PTC8$: POP BP ;RESTORE + 0F01 C3 RET ;AND RETURN + 0F02 PUTCHR ENDP + + ;GO TO NEW LINE, OUTPUTTING CURRENT BUFFER + 0F02 NEWLIN PROC + 0F02 53 PUSH BX ;SAVE + 0F03 8B 1E 02C6 R MOV BX,CHRPTR ;END LINE AT CURRENT POINT + 0F07 C6 07 00 MOV BYTE PTR [BX],0 + 0F0A C7 06 02C6 R 04F5 R MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + 0F10 5B POP BX ;RESTORE + PRINT OUTBUF ;AND OUTPUT LINE + 0F11 50 + PUSH AX + 0F12 B8 04F5 R + MOV AX,OFFSET OUTBUF + 0F15 E8 196F R + CALL .PRINT + 0F18 58 + POP AX + 0F19 C3 RET + 0F1A NEWLIN ENDP + + = 000F EOICHR EQU 15 ;CARRIAGE RETURN IS NORMAL END OF INPUT + + SUBTTL TOP LEVEL STUFF +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 16-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + TOP LEVEL STUFF + + PAGE + + + = 0000 PVERS1 EQU 0 ;POSITION OF ZVERSION VERSION BYTE + = 0001 PVERS2 EQU 1 ;ZVERSION MODE BYTE + = 0002 PZRKID EQU 2 ;ZORKID + = 0004 PENDLD EQU 4 ;ENDLOD + = 0006 PSTART EQU 6 ;START + = 0008 PVOCTB EQU 10Q ;VOCAB + = 000A POBJTB EQU 12Q ;OBJECT + = 000C PGLOTB EQU 14Q ;GLOBALS + = 000E PPURBT EQU 16Q ;PURBOT + = 0010 PFLAGS EQU 20Q ;USER FLAG WORD + = 0012 PSERNM EQU 22Q ;SERIAL NUMBER (6 BYTES) + = 0018 PWRDTB EQU 30Q ;WORDS + = 001A PLENTH EQU 32Q ;GAME LENGTH + = 001C PCHKSM EQU 34Q ;GAME CHECKSUM + = 0050 LMOUTB EQU 80 ;MAX LENGTH OF OUTBUF, EXCLUDING TERMINAL 0 + = 0050 LDOUTB EQU 80 ;DEFAULT LENGTH OF OUTBUF + = 0080 LPAGES EQU 128 ;MAX NUMBER OF PAGES EXPECTED + = 0750 LXBYTS EQU LSTACK+LMOUTB+(4*LPAGES)+2000Q ;LENGTH OF EXTRA BYTES NEEDED + + ;INITIALIZATION + 0F1A TSETUP PROC + 0F1A F6 06 066C R 01 TEST INIFLG,INIWID ;CHECK FOR FORCED 40 COLUMN MODE + 0F1F 74 06 JZ TS0$ + 0F21 C7 06 02D4 R 0026 MOV TWIDTH,38 ;FORCE IT TO 40 + 0F27 BB 04F5 R TS0$: MOV BX,OFFSET OUTBUF ;START OF OUTPUT BUFFER + 0F2A 03 1E 02D4 R ADD BX,TWIDTH ;ADD LENGTH OF BUFFER + 0F2E 2A 1E 02DA R SUB BL,LFTMAR ; *** SUBTRACT THE LEFT MARGIN VALUE + 0F32 89 1E 02C8 R MOV ENDBUF,BX ;THIS IS ENDBUF POINTER + 0F36 C6 07 00 MOV BYTE PTR [BX],0 ;BUFFER IS FOLLOWED BY A 0 FOR CONVENIENCE + 0F39 BB 0051 R MOV BX,OFFSET SLSTAB ;GET STATUS LINE TABLE + 0F3C 83 3E 02DD R 00 CMP TIMEMD,0 ;CHECK FOR SCORE/TIME MODE + 0F41 74 03 JE TS1$ + 0F43 83 C3 08 ADD BX,8 ;THE TIME MODE TABLE IS OFFSET FOUR WORDS + 0F46 BE 0000 TS1$: MOV SI,0 ;OFFSET INTO PROPER TABLE + 0F49 83 3E 02D4 R 26 CMP TWIDTH,38 ;CHECK TERMINAL WIDTH + 0F4E 74 03 JE TS2$ + 0F50 83 C6 04 ADD SI,4 ;OFFSET TO 80 COLUMN STUFF + 0F53 8B 00 TS2$: MOV AX,[BX][SI] + 0F55 A3 004D R MOV SLSTR,AX + 0F58 8B 48 02 MOV CX,2[BX][SI] + 0F5B 89 0E 004F R MOV SLTAB,CX ;GET THE RIGHT POINTERS TO STRING/TABLE + 0F5F 8A 1E 0001 R MOV BL,USLATR ;INVERSE VIDEO, STRING ALREADY IN AX + 0F63 B9 0000 MOV CX,0 ;AT 0,LFTMAR + 0F66 E8 198B R CALL .PRINTA ;PRINT THE STATUS LINE + 0F69 C3 RET + 0F6A TSETUP ENDP + + 0F6A ZIPBGN PROC + 0F6A E8 13A6 R CALL SYSINI ;DO ANY SYSTEM INITIALIZATION + 0F6D E8 1566 R CALL BKCHK ;CHECK FOR MAKING BACKUP COPY + 0F70 E8 1A0A R STR5$: CALL .GETMEM +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 16-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + TOP LEVEL STUFF + + 0F73 8C C3 MOV BX,ES + 0F75 2B C3 SUB AX,BX + 0F77 A3 02DB R MOV MEMTOP,AX ;LAST AVAILABLE PARAGRAPH LOCATION + 0F7A 2B C0 SUB AX,AX ;BLOCK 0 + 0F7C 2B DB SUB BX,BX ;PUT AT BEGINNING OF GAME SEGMENT + 0F7E E8 147B R CALL GETBLK ;GET THE BLOCK + 0F81 26: 80 3E 0000 03 CMP BYTE PTR ES:[PVERS1],ZMVERS ;PROPER Z-MACHINE VERSION? + 0F87 75 08 JNE STR8$ ;NO + 0F89 26: F6 06 0001 01 TEST BYTE PTR ES:[PVERS2],1 ;YES,PROPER MODE BITS? + 0F8F 74 12 JE STR9$ ;YES + 0F91 STR8$: FATAL FTL4 ;SOMETHING WRONG, DIE + 0F91 E8 18F0 R + CALL .CRLF + 0F94 B8 09DF R + MOV AX,OFFSET FATHDR + 0F97 E8 196F R + CALL .PRINT + 0F9A B8 0994 R + MOV AX,OFFSET FTL4 + 0F9D E8 196F R + CALL .PRINT + 0FA0 E9 1A47 R + JMP FINISH + 0FA3 26: F6 06 0001 02 STR9$: TEST BYTE PTR ES:[PVERS2],2 ;TIME MODE REQUESTED? + 0FA9 74 04 JE STR10$ ;NO + 0FAB FF 06 02DD R INC TIMEMD ;YES + 0FAF STR10$: GTAWRD A,[PZRKID] ;UNIQUE GAME & VERSION INDENTIFER + 0FAF 26: A1 0002 + MOV AX,ES:[PZRKID] + 0FB3 86 E0 + XCHG AH,AL + 0FB5 A3 02DF R MOV ZORKID,AX + 0FB8 26: 80 0E 0001 20 OR BYTE PTR ES:[PVERS2],0020H ;SET SPLIT BIT + GTAWRD A,[PENDLD] ;GET ENDLOD POINTER + 0FBE 26: A1 0004 + MOV AX,ES:[PENDLD] + 0FC2 86 E0 + XCHG AH,AL + 0FC4 A9 01FF TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + 0FC7 74 06 JE STR12$ + 0FC9 25 FE00 AND AX,0FE00H + 0FCC 05 0200 ADD AX,200H + 0FCF 8B C8 STR12$: MOV CX,AX + 0FD1 8B E9 MOV BP,CX ;EXTRACT ENDLOD BLOCK + 0FD3 B1 09 MOV CL,9 + 0FD5 D3 FD SAR BP,CL + 0FD7 8B CD MOV CX,BP + 0FD9 89 0E 02E1 R MOV ENDLOD,CX ;SAVE ENDLOD BLOCK NUMBER + 0FDD 49 DEC CX ;NUMBER OF BLOCKS LEFT TO LOAD + 0FDE B8 0001 MOV AX,1 ;STARTING WITH BLOCK 1 + 0FE1 BB 0200 MOV BX,200H ;LOCATION TO PUT THEM + 0FE4 E8 149E R CALL GTBLKS ;GET THE BLOCKS + GTAWRD A,[PVOCTB] ;VOCAB LOCATION + 0FE7 26: A1 0008 + MOV AX,ES:[PVOCTB] + 0FEB 86 E0 + XCHG AH,AL + 0FED A3 02E3 R MOV VOCTAB,AX ;SAVE VOCABULARY TABLE POINTER + GTAWRD A,[POBJTB] ;GET OBJECT TABLE POINTER + 0FF0 26: A1 000A + MOV AX,ES:[POBJTB] + 0FF4 86 E0 + XCHG AH,AL + 0FF6 A3 02E5 R MOV OBJTAB,AX + GTAWRD A,[PGLOTB] ;GET GLOBAL TABLE POINTER + 0FF9 26: A1 000C + MOV AX,ES:[PGLOTB] + 0FFD 86 E0 + XCHG AH,AL +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 16-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + TOP LEVEL STUFF + + 0FFF A3 02E7 R MOV GLOTAB,AX + GTAWRD A,[PWRDTB] ;GET WORD TABLE POINTER + 1002 26: A1 0018 + MOV AX,ES:[PWRDTB] + 1006 86 E0 + XCHG AH,AL + 1008 A3 02E9 R MOV WRDTAB,AX + GTAWRD A,[PPURBT] ;GET PURE CODE POINTER + 100B 26: A1 000E + MOV AX,ES:[PPURBT] + 100F 86 E0 + XCHG AH,AL + 1011 A9 01FF TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + 1014 74 03 JE STR13$ + 1016 05 0200 ADD AX,200H + 1019 B1 09 STR13$: MOV CL,9 ;EXTRACT BLOCK NUMBER + 101B D3 F8 SAR AX,CL + 101D 25 007F AND AX,7FH ;CLEAR UNWANTED BITS + 1020 A3 02EB R MOV PURBOT,AX ;SAVE IT + 1023 BB 0546 R MOV BX,OFFSET RBRKS ;START OF READ BREAK CHARACTER TABLE + 1026 8B 36 02E3 R MOV SI,VOCTAB ;VOCAB TABLE POINTER + 102A 26: 8A 0C MOV CL,BYTE PTR ES:[SI] ;1ST BYTE IN VOCTAB IS # OF SIBREAKS + 102D 2A ED SUB CH,CH ;CLEAR HIGH BYTE + 102F 46 INC SI + 1030 STR14$: MOVM [BX],ES:[SI],AL ;TRANSFER THEM + 1030 26: 8A 04 + MOV AL,ES:[SI] + 1033 88 07 + MOV [BX],AL + 1035 43 INC BX + 1036 46 INC SI + 1037 E2 F7 LOOP STR14$ + 1039 89 1E 02ED R MOV ESIBKS,BX ;REMEMBER END OF SI BREAKS + 103D BD 02CC R MOV BP,OFFSET IRBRKS;ALWAYS END WITH INITIAL BREAK CHARACTERS + 1040 STR15$: MOVM [BX],DS:[BP],AL ;TRANSFER THEM + 1040 3E: 8A 46 00 + MOV AL,DS:[BP] + 1044 88 07 + MOV [BX],AL + 1046 43 INC BX + 1047 45 INC BP + 1048 3C 00 CMP AL,0 + 104A 75 F4 JNE STR15$ + 104C 26: 8A 04 MOV AL,ES:[SI] ;GET VOCABULARY ENTRY LENGTH + 104F 2A E4 SUB AH,AH + 1051 A3 02EF R MOV VWLEN,AX ;AND STORE IT AWAY + 1054 46 INC SI + GTAWRD A,[SI] ;GET NEXT WORD IN TABLE + 1055 26: 8B 04 + MOV AX,ES:[SI] + 1058 86 E0 + XCHG AH,AL + 105A A3 02F1 R MOV VWORDS,AX ;NUMBER OF WORD ENTRIES IN VOCABULARY + 105D 83 C6 02 ADD SI,2 ;MOVE TO NEXT WORD + 1060 89 36 02F3 R MOV VOCBEG,SI ;BEGINNING OF ACTUAL VOCABULARY + + 1064 8B 36 02E1 R MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + 1068 B1 09 MOV CL,9 + 106A D3 E6 SHL SI,CL ;THIS IS FIRST LOCATION (ES:) OF PAGING + 106C 89 36 0667 R MOV PAGES,SI ;SAVE THIS TO USE AS AN OFFSET + + 1070 8B 36 02E1 R MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + 1074 F7 DE NEG SI +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 16-4 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + TOP LEVEL STUFF + + 1076 8B 3E 02DB R MOV DI,MEMTOP ;GET PARAGRAPHS OF MEMORY + 107A B1 05 MOV CL,5 + 107C D3 FF SAR DI,CL ;CHANGE TO PAGES + 107E 03 F7 ADD SI,DI ;NUMBER OF PAGES FOR PAGING + 1080 89 36 0669 R MOV BUFPGS,SI ;SAVE THIS NUMBER FOR FUTURE REFERENCE + 1084 83 3E 0669 R 3F CMP BUFPGS,63 + 1089 7E 09 JLE STR16$ + 108B C7 06 0669 R 003F MOV BUFPGS,63 ;OUR TABLE IS ONLY SO BIG.... + 1091 BE 003F MOV SI,63 + 1094 D1 E6 STR16$: SHL SI,1 + 1096 D1 E6 SHL SI,1 ;EACH PAGE HAS 4 BYTES OF INFO + 1098 BB 0566 R MOV BX,OFFSET PAGTAB ;POINT INTO PAGE INFO TABLE + 109B 03 F3 ADD SI,BX + 109D C7 04 FFFF MOV WORD PTR [SI],-1 ;MAKE THIS THE END OF TABLE MARK + + 10A1 E8 1A34 R CALL .GETTM ;GET THE CURRENT TIME-OF-DAY + MOVM RSEED1,TIME[2],AX;USE IT TO INITIALIZE RANDOM NUMBER SEED + 10A4 A1 0960 R + MOV AX,TIME[2] + 10A7 A3 02AF R + MOV RSEED1,AX + MOVM RSEED2,TIME,AX ;BE CONSISTENT + 10AA A1 095E R + MOV AX,TIME + 10AD A3 02B1 R + MOV RSEED2,AX + 10B0 EB 13 90 STR17$: JMP START1 + 10B3 ZIPBGN ENDP + + 10B3 PRSPC PROC + 10B3 50 PUSH AX + 10B4 53 PUSH BX + 10B5 51 PUSH CX + 10B6 E8 09A4 R CALL OPPRNN + 10B9 B0 20 MOV AL,32 + 10BB E8 0E61 R CALL PUTCHR + 10BE 59 POP CX + 10BF 5B POP BX + 10C0 58 POP AX + 10C1 C3 RET + 10C2 PRSPC ENDP + + ;RESTART EXECUTION HERE + 10C2 RESTRT PROC + 10C2 CD 19 INT 19H ; REBOOT THE SUCKER FOR NOW + 10C4 C3 RET ; I'M SENTIMENTAL + + 10C5 E8 1527 R START1: CALL WPCHK ;MAKE SURE GAME DISK IS WRITE-PRO + 10C8 E8 0F1A R CALL TSETUP ;SETUP TERMINAL/STATUS LINE + 10CB E8 1438 R CALL CLRSCR ;CLEAR THE REMAINDER OF THE SCREEN + 10CE BC 0200 R MOV SP,OFFSET STK_TOP ;INIT OUR STACK POINTER + 10D1 BF 0400 R MOV DI,OFFSET ZSTK_TP ;INIT USER STACK POINTER + 10D4 C7 06 02C6 R 04F5 R MOV CHRPTR,OFFSET OUTBUF ;INIT OUTPUT CHAR. POINTER + 10DA 89 3E 066D R MOV ZLOCS,DI ; LOCALS WOULD START AT FIRST SLOT, + 10DE 83 2E 066D R 02 SUB ZLOCS,2 ; IF THERE WERE ANY + GTAWRD A,[PSTART] + 10E3 26: A1 0006 + MOV AX,ES:[PSTART] +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 16-5 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + TOP LEVEL STUFF + + 10E7 86 E0 + XCHG AH,AL + 10E9 E8 0C5D R CALL BSPLTB ;SPLIT BLOCK & BYTE POINTERS + 10EC A3 066F R MOV ZPC1,AX ;INIT ZPC BLOCK-POINTER + 10EF 89 1E 0671 R MOV ZPC2,BX ;INIT ZPC BYTE-POINTER + 10F3 E8 1245 R CALL NEWZPC ;GET PAGE TO EXECUTE + 10F6 80 3E 066C R 05 CMP INIFLG,5 + 10FB 75 2C JNE FUBAR$ + 10FD 8C C8 MOV AX,CS + 10FF E8 10B3 R CALL PRSPC + 1102 8C D8 MOV AX,DS + 1104 E8 10B3 R CALL PRSPC + 1107 8C C0 MOV AX,ES + 1109 E8 10B3 R CALL PRSPC + 110C 8C D0 MOV AX,SS + 110E E8 10B3 R CALL PRSPC + 1111 A1 02E1 R MOV AX,ENDLOD + 1114 E8 10B3 R CALL PRSPC + 1117 A1 0667 R MOV AX,PAGES + 111A E8 10B3 R CALL PRSPC + 111D A1 0669 R MOV AX,BUFPGS + 1120 E8 10B3 R CALL PRSPC + 1123 A1 02DB R MOV AX,MEMTOP + 1126 E8 10B3 R CALL PRSPC + 1129 C6 06 0207 R 01 FUBAR$: MOV FUCK,1 + 112E EB 01 90 JMP NXTINS + + 1131 RESTRT ENDP + + ;MAIN INSTRUCTION INTERPRETATION LOOP + 1131 NXTINS PROC + 1131 E8 0B60 R CALL NXTBYT ;GET THE OPERATION BYTE + 1134 8B D0 MOV DX,AX ;SAVE A COPY + 1136 3D 0080 CMP AX,80H ;IS IT A 2OP? + 1139 7C 7D JL NXI9$ ;YES + 113B 3D 00B0 CMP AX,0B0H ;NO, IS IT A 1OP? + 113E 7D 03 JGE NXI0A$ ;NO + 1140 E9 11FA R JMP NXI12$ ;YES + 1143 3D 00C0 NXI0A$: CMP AX,0C0H ;IS IT A 0OP? + 1146 7F 03 JG NXI0B$ ;NO + 1148 E9 121D R JMP NXI13$ ;YES + 114B 25 003F NXI0B$: AND AX,3FH ;IT'S EXTENDED, GET THE OPCODE + 114E D1 E0 SHL AX,1 ;MAKE IT A WORD OFFSET + 1150 8B E8 MOV BP,AX ;GET THE OPERATOR POINTER + 1152 3E: 8B B6 08D0 R MOV SI,DS:[BP+EXTOP] + 1157 83 FE 00 CMP SI,0 + 115A 75 03 JNE NXI0C$ ;OPERATION EXISTS + 115C E9 122E R JMP NXI14$ ;NO SUCH OPERATION + 115F E8 0B60 R NXI0C$: CALL NXTBYT ;GET THE ARGUMENT BYTE + 1162 B9 0004 MOV CX,4 ;SPLIT IT INTO 4 2-BIT MODE BYTES + 1165 50 NXI1$: PUSH AX + 1166 D1 F8 SAR AX,1 + 1168 D1 F8 SAR AX,1 + 116A E2 F9 LOOP NXI1$ +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 16-6 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + TOP LEVEL STUFF + + 116C B9 0004 MOV CX,4 ;RETRIEVE THE 4 BYTES IN PROPER ORDER + 116F 2B D2 SUB DX,DX + 1171 BB 0673 R MOV BX,OFFSET ARGBLK;FIRST ARGUMENT SLOT + 1174 58 NXI2$: POP AX ;GET NEXT MODE BYTE? + 1175 25 0003 AND AX,3 ;CLEAR OFF UNWANTED BITS + 1178 3D 0003 CMP AX,3 ;NO MORE ARGUMENTS? + 117B 74 0E JE NXI4$ ;YES, FLUSH ANY OTHER MODE BYTES + 117D E8 0B8D R CALL GETARG ;ELSE, GET THE NEXT ARGUMENT + 1180 89 07 MOV [BX],AX ;SAVE IT IN ARGUMENT BLOCK + 1182 83 C3 02 ADD BX,2 + 1185 42 INC DX ;REMEMBER NUMBER OF ARGS GOTTEN + 1186 E2 EC NXI3$: LOOP NXI2$ ;LOOP FOR REST OF MODE BYTES + 1188 EB 06 90 JMP NXI5$ + 118B 49 NXI4$: DEC CX ;DETERMINE NUMBER OF REMAINING MODE BYTES + 118C D1 E1 SHL CX,1 ;WORD COUNT + 118E 03 E1 ADD SP,CX ;FLUSH THEM + 1190 87 CA NXI5$: XCHG CX,DX + 1192 8B C1 MOV AX,CX ;NUMBER OF ARGS GOES HERE FOR OPERATOR TO USE + 1194 2E: 80 3C 90 CMP CS:BYTE PTR [SI],90H ;DOES OPERATOR WANT ARGBLK POINTER? + 1198 74 1B JE NXI8A$ ;YES, CALL OPERATOR NOW + 119A 49 DEC CX ;NO, IT WANTS ARGS IN REGISTERS + 119B 7C 18 JL NXI8A$ ;NO ARGS, JUST CALL OPERATOR + 119D 74 13 JE NXI8$ ;1 ARG, GET IT + 119F 83 E9 02 SUB CX,2 + 11A2 7C 0A JL NXI7$ ;2 ARGS + 11A4 74 04 JE NXI6$ ;3 ARGS + 11A6 8B 16 0679 R MOV DX,ARGBLK[6] ;ELSE, 4 ARGS, GET 4TH + 11AA 8B 0E 0677 R NXI6$: MOV CX,ARGBLK[4] ;GET 3RD + 11AE 8B 1E 0675 R NXI7$: MOV BX,ARGBLK[2] ;GET 2ND + 11B2 A1 0673 R NXI8$: MOV AX,ARGBLK ;GET FIRST ARG + 11B5 E9 1240 R NXI8A$: JMP NXI15$ ;AND CALL OPERATOR + 11B8 25 001F NXI9$: AND AX,1FH ;2OP, EXTRACT OPERATION BITS + 11BB D1 E0 SHL AX,1 ;MAKE IT A WORD OFFSET + 11BD 8B E8 MOV BP,AX ;FIND POINTER TO OPERATOR ROUTINE + 11BF 3E: 8B B6 08D0 R MOV SI,DS:[BP+EXTOP] + 11C4 83 FE 00 CMP SI,0 + 11C7 74 65 JE NXI14$ ;NO SUCH OPERATION + 11C9 B8 0001 MOV AX,1 ;ASSUME FIRST ARG IS AN IMMEDIATE + 11CC F7 C2 0040 TEST DX,40H ;IS IT INSTEAD A VARIABLE? + 11D0 74 01 JE NXI10$ ;NO + 11D2 40 INC AX ;YES, CHANGE MODE + 11D3 E8 0B8D R NXI10$: CALL GETARG ;GET THE FIRST ARG + 11D6 50 PUSH AX ;SAVE IT + 11D7 B8 0001 MOV AX,1 ;ASSUME SECOND ARG IS AN IMMEDIATE + 11DA F7 C2 0020 TEST DX,20H ;IS IT INSTEAD A VARIABLE? + 11DE 74 01 JE NXI11$ ;NO + 11E0 40 INC AX ;YES, CHANGE MODE + 11E1 E8 0B8D R NXI11$: CALL GETARG ;GET THE SECOND ARG + 11E4 8B D8 MOV BX,AX ;POSITION IT + 11E6 58 POP AX ;RECOVER FIRST ARG + 11E7 2E: 80 3C 90 CMP CS:BYTE PTR [SI],90H ;DOES ROUTINE WANT ARGUMENT BLOCK? + 11EB 75 53 JNE NXI15$ ;NO, GO CALL IT + 11ED A3 0673 R MOV ARGBLK,AX ;YES, MOVE ARGS TO ARGBLK +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 16-7 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + TOP LEVEL STUFF + + 11F0 89 1E 0675 R MOV ARGBLK[2],BX + 11F4 B8 0002 MOV AX,2 ;ALWAYS 2 ARGS + 11F7 EB 47 90 JMP NXI15$ ;NOW CALL OPERATOR + 11FA 81 E2 000F NXI12$: AND DX,0FH ;1OP, EXTRACT OPERATION BITS + 11FE D1 E2 SHL DX,1 ;MAKE IT A WORD OFFSET + 1200 8B EA MOV BP,DX ;GET OPERATOR ROUTINE POINTER + 1202 3E: 8B B6 08B0 R MOV SI,DS:[BP+ONEOP] + 1207 83 FE 00 CMP SI,0 + 120A 74 22 JE NXI14$ ;ILLEGAL OPERATION + 120C D1 F8 SAR AX,1 ;EXTRACT MODE BITS + 120E D1 F8 SAR AX,1 + 1210 D1 F8 SAR AX,1 + 1212 D1 F8 SAR AX,1 + 1214 25 0003 AND AX,3 + 1217 E8 0B8D R CALL GETARG ;GET THE ARGUMENT + 121A EB 24 90 JMP NXI15$ ;AND CALL OPERATOR + 121D 25 000F NXI13$: AND AX,0FH ;0OP, EXTRACT OPERATION BITS + 1220 D1 E0 SHL AX,1 ;MAKE IT A WORD OFFSET + 1222 8B E8 MOV BP,AX ;GET OPERATOR ROUTINE POINTER + 1224 3E: 8B B6 0890 R MOV SI,DS:[BP+ZEROOP] + 1229 83 FE 00 CMP SI,0 + 122C 75 12 JNE NXI15$ ;IT'S A LEGAL OPERATION + 122E NXI14$: FATAL FTL5 ;OTHERWISE, COMPLAIN + 122E E8 18F0 R + CALL .CRLF + 1231 B8 09DF R + MOV AX,OFFSET FATHDR + 1234 E8 196F R + CALL .PRINT + 1237 B8 09AA R + MOV AX,OFFSET FTL5 + 123A E8 196F R + CALL .PRINT + 123D E9 1A47 R + JMP FINISH + 1240 FF D6 NXI15$: CALL SI ;CALL THE OPERATOR ROUTINE + 1242 E9 1131 R JMP NXTINS ;AND LOOP FOR NEXT INSTRUCTION + 1245 NXTINS ENDP + + SUBTTL PAGING ROUTINES +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 17-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + PAGING ROUTINES + + PAGE + + + ;NORMALIZE ZPC & GET PROPER PAGE + 1245 NEWZPC PROC + 1245 56 PUSH SI ;SAVES + 1246 55 PUSH BP + 1247 53 PUSH BX + 1248 51 PUSH CX + 1249 52 PUSH DX + 124A 2B C0 SUB AX,AX ;USE DOUBLE-WORD ARITHMETIC + 124C 8B 1E 066F R MOV BX,ZPC1 ;GET BLOCK-POINTER + 1250 8A FB MOV BH,BL ;POSITION IT + 1252 2A DB SUB BL,BL + 1254 D1 E3 SHL BX,1 + 1256 15 0000 ADC AX,0 + 1259 8B 36 0671 R MOV SI,ZPC2 ;GET BYTE-OFFSET + 125D 96 XCHG SI,AX ;DOUBLE-WORDIFY IT (MIGHT BE NEGATIVE) + 125E 99 CWD + 125F 96 XCHG SI,AX + 1260 03 DE ADD BX,SI ;ADD IT TO OTHER DOUBLE WORD + 1262 13 C2 ADC AX,DX + 1264 8B D3 MOV DX,BX + 1266 81 E2 01FF AND DX,1FFH ;EXTRACT BYTE-OFFSET + 126A 89 16 0671 R MOV ZPC2,DX ;SAVE IT + 126E B1 09 MOV CL,9 ;EXTRACT BLOCK-POINTER + 1270 D3 FB SAR BX,CL + 1272 81 E3 007F AND BX,7FH + 1276 A9 0001 TEST AX,1 ;TEST 17TH BIT + 1279 74 04 JE NWZ1$ ;WAS 0 + 127B 81 CB 0080 OR BX,80H ;WAS 1, SET PROPER BIT IN BLOCK-POINTER + 127F 89 1E 066F R NWZ1$: MOV ZPC1,BX ;SAVE IT + 1283 3B 1E 067D R CMP BX,CURBLK ;HAS IT CHANGED? + 1287 74 52 JE NWZ5$ ;NO + 1289 89 1E 067D R MOV CURBLK,BX ;YES, REMEMBER NEW BLOCK + 128D A1 067F R MOV AX,CURTAB ;IS OLD PAGE IN PAGING SPACE? + 1290 3D 0000 CMP AX,0 + 1293 74 13 JE NWZ2$ ;NO + 1295 8B E8 MOV BP,AX ;YES, STORE CURRENT REF TIME FOR OLD PAGE + MOVM DS:[BP],RTIME1,CL + 1297 8A 0E 0681 R + MOV CL,RTIME1 + 129B 3E: 88 4E 00 + MOV DS:[BP],CL + MOVM DS:[BP+1],RTIME2,CX + 129F 8B 0E 0682 R + MOV CX,RTIME2 + 12A3 3E: 89 4E 01 + MOV DS:[BP+1],CX + 12A7 40 INC AX + 12A8 3B 1E 02E1 R NWZ2$: CMP BX,ENDLOD ;NEW PAGE ALREADY IN CORE? + 12AC 7C 1F JL NWZ3$ ;YES + 12AE 8B C3 MOV AX,BX ;NO, GET NEW PAGE + 12B0 E8 12E1 R CALL GETPAG + 12B3 8B D8 MOV BX,AX + 12B5 A1 0688 R MOV AX,LPTAB ;GET NEW PAGE TABLE POINTER + 12B8 40 INC AX ;POINT TO REF SLOT + 12B9 A3 067F R MOV CURTAB,AX ;SAVE THIS POINTER FOR LATER +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 17-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + PAGING ROUTINES + + 12BC 8B E8 MOV BP,AX ;STORE HIGHEST RTIME TO KEEP PAGE FOR US + 12BE 3E: C6 46 00 FF MOV BYTE PTR DS:[BP],-1 + 12C3 3E: C7 46 01 FFFF MOV WORD PTR DS:[BP+1],-1 + 12C9 40 INC AX + 12CA EB 0B 90 JMP NWZ4$ + 12CD B1 09 NWZ3$: MOV CL,9 ;CALCULATE PAGE ADDRESS + 12CF D3 E3 SHL BX,CL + 12D1 C7 06 067F R 0000 MOV CURTAB,0 ;CLEARING POINTER MEANS PAGE IS PRELOADED + 12D7 89 1E 067B R NWZ4$: MOV CURPAG,BX ;UPDATE PAGE POINTER + 12DB 5A NWZ5$: POP DX ;RESTORES + 12DC 59 POP CX + 12DD 5B POP BX + 12DE 5D POP BP + 12DF 5E POP SI + 12E0 C3 RET ;AND RETURN + 12E1 NEWZPC ENDP + + ;GET THE PAGE WHOSE NUMBER IS IN AX, RETURN A POINTER TO IT IN AX + 12E1 GETPAG PROC + 12E1 3B 06 0684 R CMP AX,LPAGE ;IS THIS THE SAME PAGE AS LAST REFERENCED? + 12E5 75 04 JNE GTP1$ ;NO + 12E7 A1 0686 R MOV AX,LPLOC ;YES, WE ALREADY HAVE LOCATION + 12EA C3 RET ;RETURN IT + 12EB A3 0684 R GTP1$: MOV LPAGE,AX ;SAVE NEW PAGE NUMBER + 12EE 51 PUSH CX ;SAVES + 12EF 53 PUSH BX + 12F0 83 06 0682 R 01 ADD RTIME2,1 ;UPDATE REFERENCE TIME (COUNT) + 12F5 80 16 0681 R 00 ADC RTIME1,0 + 12FA BB 0566 R MOV BX,OFFSET PAGTAB;PAGE INFORMATION TABLE + 12FD 43 GTP2$: INC BX + 12FE 3A 47 FF CMP AL,[BX-1] ;SEARCH FOR DESIRED BLOCK + 1301 75 27 JNE GTP3$ ;NOT IT + 1303 3B 06 067D R CMP AX,CURBLK ;IS THIS THE CURRENT CODE PAGE? + 1307 74 0D JE GTP2A$ ;DON'T UPDATE REFERENCE TIME + MOVM [BX],RTIME1,CL ;FOUND IT, UPDATE ITS REFERENCE TIME + 1309 8A 0E 0681 R + MOV CL,RTIME1 + 130D 88 0F + MOV [BX],CL + MOVM [BX+1],RTIME2,CX + 130F 8B 0E 0682 R + MOV CX,RTIME2 + 1313 89 4F 01 + MOV [BX+1],CX + 1316 4B GTP2A$: DEC BX ;BACKUP TO BEGINNING OF TABLE ENTRY + 1317 89 1E 0688 R MOV LPTAB,BX ;SAVE IT + 131B 81 EB 0566 R SUB BX,OFFSET PAGTAB;CALCULATE ADDRESS OF PAGE + 131F B1 07 MOV CL,7 + 1321 D3 E3 SHL BX,CL + 1323 03 1E 0667 R ADD BX,PAGES + 1327 EB 28 90 JMP GTP4$ ;AND RETURN PAGE POINTER + 132A 83 C3 03 GTP3$: ADD BX,3 ;SKIP REFERENCE TIME + 132D 83 3F FF CMP WORD PTR [BX],-1;END OF TABLE? + 1330 75 CB JNE GTP2$ ;NO, CONTINUE SEARCH + 1332 E8 1359 R CALL FINDPG ;YES, FIND A PAGE TO LOAD INTO + 1335 50 PUSH AX ;PAGE POINTER + 1336 89 1E 0688 R MOV LPTAB,BX ;SAVE PAGE TABLE POINTER +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 17-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + PAGING ROUTINES + + 133A A1 0684 R MOV AX,LPAGE ;SAVE NEW BLOCK NUMBER + 133D 88 07 MOV [BX],AL + MOVM [BX+1],RTIME1,CL;AND CURRENT REF TIME + 133F 8A 0E 0681 R + MOV CL,RTIME1 + 1343 88 4F 01 + MOV [BX+1],CL + MOVM [BX+2],RTIME2,CX + 1346 8B 0E 0682 R + MOV CX,RTIME2 + 134A 89 4F 02 + MOV [BX+2],CX + 134D 5B POP BX ;PAGE POINTER + 134E E8 147B R CALL GETBLK ;GET THE BLOCK + 1351 8B C3 GTP4$: MOV AX,BX ;RETURN PAGE POINTER + 1353 A3 0686 R MOV LPLOC,AX ;AND SAVE IT FOR LATER + 1356 5B POP BX ;RESTORES + 1357 59 POP CX + 1358 C3 RET + 1359 GETPAG ENDP + + ;FIND A GOOD PAGE, RETURN PAGE POINTER IN AX & PAGTAB POINTER IN BX + 1359 FINDPG PROC + 1359 51 PUSH CX + 135A BB 0566 R MOV BX,OFFSET PAGTAB + 135D B9 FFFF MOV CX,-1 ;FAKE BEST-CASE REFERENCE COUNT + 1360 8B D1 MOV DX,CX + 1362 43 INC BX ;SKIP BLOCK NUMBER FOR NOW + 1363 43 FNP1$: INC BX ;IS THIS REF TIME WORSE THAN CURRENT WORST? + 1364 38 4F FF CMP [BX-1],CL + 1367 77 0D JA FNP3$ ;NO + 1369 72 04 JB FNP2$ ;YES + 136B 39 17 CMP [BX],DX ;MAYBE, COMPARE LOW-ORDER WORDS, WORSE? + 136D 73 07 JAE FNP3$ ;NO + 136F 8A 4F FF FNP2$: MOV CL,[BX-1] ;YES, SAVE ITS REF COUNT + 1372 8B 17 MOV DX,[BX] + 1374 8B C3 MOV AX,BX ;AND LOCATION (+2) + 1376 83 C3 03 FNP3$: ADD BX,3 ;SKIP SECOND WORD + 1379 80 7F FF FF CMP BYTE PTR [BX-1],-1 ;LOOP UNTIL END OF TABLE + 137D 75 E4 JNE FNP1$ + 137F 41 INC CX ;WAS A PAGE REALLY FOUND? + 1380 74 12 JE FNP4$ ;NO, GROSS BUG! + 1382 2D 0002 SUB AX,2 ;YES, CALCULATE CORE LOCATION OF PAGE + 1385 8B D8 MOV BX,AX + 1387 2D 0566 R SUB AX,OFFSET PAGTAB + 138A B1 07 MOV CL,7 + 138C D3 E0 SHL AX,CL + 138E 03 06 0667 R ADD AX,PAGES + 1392 59 POP CX ;RESTORES + 1393 C3 RET + 1394 FNP4$: FATAL FTL6 + 1394 E8 18F0 R + CALL .CRLF + 1397 B8 09DF R + MOV AX,OFFSET FATHDR + 139A E8 196F R + CALL .PRINT + 139D B8 09BC R + MOV AX,OFFSET FTL6 + 13A0 E8 196F R + CALL .PRINT + 13A3 E9 1A47 R + JMP FINISH +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 17-4 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + PAGING ROUTINES + + 13A6 FINDPG ENDP + + SUBTTL HIGH LEVEL IBMPC DEPENDENT STUFF + + ;SYSTEM INITIALIZATION + 13A6 SYSINI PROC + 13A6 B4 0F MOV AH,15 + 13A8 CD 10 INT 10H ;CHECK VIDEO STATE + 13AA 8A DC MOV BL,AH ;GET SCREEN WIDTH + 13AC 2A FF SUB BH,BH ;AND ZERO HIGH END + 13AE 89 1E 02D4 R MOV TWIDTH,BX ;SAVE IT AWAY + 13B2 89 1E 02D6 R MOV RWIDTH,BX + 13B6 83 2E 02D4 R 02 SUB TWIDTH,2 + 13BB FE 06 02DA R INC LFTMAR ; FIX FOR OVERSCAN + 13BF 3C 07 CMP AL,7 + 13C1 74 29 JE SINIX$ + 13C3 A8 01 TEST AL,1 + 13C5 74 25 JZ SINIX$ + PRINT COLORQ ;ASK IF COLOR IS REALLY NEEDED + 13C7 50 + PUSH AX + 13C8 B8 0003 R + MOV AX,OFFSET COLORQ + 13CB E8 196F R + CALL .PRINT + 13CE 58 + POP AX + 13CF E8 1864 R CALL .CHRIN ;READ A CHARACTER + 13D2 3C 59 CMP AL,"Y" + 13D4 74 04 JE SINC$ ;REALLY WANTS COLOR IF Y OR y + 13D6 3C 79 CMP AL,"y" + 13D8 75 12 JNE SINIX$ + 13DA A2 0020 R SINC$: MOV COLFLG,AL ; NON-ZERO = THEY WANT COLOR + 13DD C6 06 0001 R 74 MOV USLATR,74H ;MAKE STATUS LINE RED ON WHITE IN COLOR MODE + 13E2 C6 06 0000 R 17 MOV NRMATR,17H ;WHITE ON BLUE FOR THE REST + 13E7 C6 06 0002 R 1F MOV TYPATR,1FH ;INPUT WILL BE YELLOW ON BLUE + + 13EC B4 01 SINIX$: MOV AH,1 + 13EE CD 16 INT 16H ;CHECK KEYBOARD + 13F0 74 0F JZ SINI0$ ;NO CHARACTER AVAILABLE + 13F2 2C 30 SUB AL,"0" + 13F4 7C 07 JL SINIF$ + 13F6 3C 09 CMP AL,9 + 13F8 7F 03 JG SINIF$ + 13FA A2 066C R MOV INIFLG,AL ;SET UP INIT FLAG IF 0-9 + 13FD B4 00 SINIF$: MOV AH,0 + 13FF CD 16 INT 16H ;BE NICE AND READ THE CHARACTER + + 1401 CD 11 SINI0$: INT 11H ;DEVICE DETERMINATION + 1403 A8 C0 TEST AL,0C0H ;TEST BITS 7&6 FOR # DRIVES + 1405 75 0A JNZ SINI1$ + 1407 C6 06 023D R 41 MOV SRDRV,"A" ;MAKE DEFAULT DRIVE A FOR 1 DRIVE SYSTEM + 140C C6 06 0206 R 01 MOV NDISKS,1 + + 1411 F6 06 066C R 02 SINI1$: TEST INIFLG,INIMEM + 1416 74 05 JZ SIN1A$ + 1418 C6 06 0206 R 01 MOV NDISKS,1 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 17-5 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + HIGH LEVEL IBMPC DEPENDENT STUFF + + 141D F6 06 066C R 08 SIN1A$: TEST INIFLG,8 ;CHECK FOR COLOR SETUP + 1422 74 13 JZ SINI2$ + 1424 B0 55 MOV AL,"U" + 1426 E8 1455 R CALL GETNUM ;READ NUMBER FOR USL ATTRIBUTE + 1429 A2 0001 R MOV USLATR,AL + 142C E8 18F0 R CALL .CRLF + 142F B0 4E MOV AL,"N" + 1431 E8 1455 R CALL GETNUM + 1434 A2 0000 R MOV NRMATR,AL + 1437 C3 SINI2$: RET + 1438 SYSINI ENDP + + 1438 CLRSCR PROC + 1438 B5 01 MOV CH,1 ;CLEAR ACTIVE SCREEN AREA + 143A B1 00 MOV CL,0 + 143C 8B 16 02D4 R MOV DX,TWIDTH + 1440 FE C2 INC DL + 1442 80 FA 28 CMP DL,40 + 1445 7E 02 JLE CLRSC1 + 1447 FE C2 INC DL + 1449 B6 18 CLRSC1: MOV DH,18H + 144B B8 0600 MOV AX,0600H + 144E 8A 3E 0000 R MOV BH,NRMATR + 1452 CD 10 INT 10H ;CLEAR SCREEN, I HOPE + 1454 C3 RET + 1455 CLRSCR ENDP + + 1455 GETNUM PROC + 1455 B7 00 MOV BH,0 + 1457 B4 07 MOV AH,7 + 1459 E8 1887 R CALL .TTYOUT ;WHAT A PROMPT! + 145C E8 1864 R CALL .CHRIN + 145F B4 07 MOV AH,7 + 1461 E8 1887 R CALL .TTYOUT ;ECHO + 1464 2C 30 SUB AL,"0" + 1466 8A D8 MOV BL,AL + 1468 E8 1864 R CALL .CHRIN + 146B B4 07 MOV AH,7 + 146D E8 1887 R CALL .TTYOUT ;ECHO + 1470 2C 30 SUB AL,"0" + 1472 B1 04 MOV CL,4 + 1474 D2 E3 SHL BL,CL + 1476 02 D8 ADD BL,AL + 1478 8B C3 MOV AX,BX + 147A C3 RET + 147B GETNUM ENDP + + ;GET A GAME FILE BLOCK, BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX + 147B GETBLK PROC + 147B 51 PUSH CX ;SAVE + 147C B9 0001 MOV CX,1 ;CALL GTBLKS FOR 1 BLOCK ONLY + 147F E8 149E R CALL GTBLKS + 1482 59 POP CX ;RESTORE +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 17-6 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + HIGH LEVEL IBMPC DEPENDENT STUFF + + 1483 C3 RET + 1484 GETBLK ENDP + + = 0006 GAMETRK EQU 6 ;FIRST GAME TRACK (0-39) + + 1484 SRBLKS PROC + 1484 C6 06 02A6 R 01 MOV DSKMOD,1 ;SAVE/RESTORE MODE + 1489 EB 22 90 JMP GTBKI$ + 148C SRBLKS ENDP + + 148C PTBLKS PROC + 148C C6 06 02A8 R 01 MOV DSKDIR,1 ;SET FLAG FOR WRITE + 1491 C6 06 02A7 R 00 MOV DSKDRV,0 ;ALWAYS FROM DRIVE 0 + 1496 C6 06 02A6 R 00 MOV DSKMOD,0 ;GAME MODE + 149B EB 10 90 JMP GTBKI$ + 149E PTBLKS ENDP + + ;GET A SERIES OF GAME FILE BLOCKS, + ;FIRST BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX # OF BLOCKS IN CX + 149E GTBLKS PROC + 149E C6 06 02A8 R 00 MOV DSKDIR,0 ;READ MODE + 14A3 C6 06 02A7 R 00 MOV DSKDRV,0 ;ALWAYS FROM DRIVE 0 + 14A8 C6 06 02A6 R 00 MOV DSKMOD,0 ;GAME MODE + 14AD 52 GTBKI$: PUSH DX ;SAVES + 14AE 55 PUSH BP + 14AF 89 0E 02A9 R GTBX0$: MOV GTBCNT,CX ;SAVE NUMBER OF BLOCKS TO READ + 14B3 A3 02AB R MOV GTBSTT,AX ;SAVE FIRST BLOCK + 14B6 89 1E 02AD R MOV GTBCOR,BX ;SAVE STARTING LOCATION + 14BA BD 0008 MOV BP,8 ;8 BLOCKS PER TRACK + 14BD 2B D2 SUB DX,DX ;CLEAR HIGH WORD FOR DIVIDE + 14BF F7 F5 DIV BP ;DETERMINE TRACK AND SECTOR OFFSETS + 14C1 91 XCHG AX,CX ;SECTOR OFFSET & NUMBER OF BLOCKS + 14C2 80 3E 02A6 R 00 CMP DSKMOD,0 ;CHECK FOR GAME VS. SAVE/RESTORE + 14C7 75 03 JNE GTBXN$ + 14C9 83 C1 06 ADD CX,GAMETRK ;ADD IN FIRST GAME TRACK + 14CC 8A E9 GTBXN$: MOV CH,CL ;POSITION TRACK NUMBER + 14CE 42 INC DX ;CONVERT TO ONE-BASED SECTOR NUMBER + 14CF 8A CA MOV CL,DL ;POSITION SECTOR NUMBER + 14D1 8A 26 02A7 R MOV AH,DSKDRV ;ALWAYS DRIVE 0 + 14D5 B2 09 MOV DL,9 + 14D7 2A D1 SUB DL,CL ;DL NOW HAS MAXIMUM SECTORS LEFT THIS TRACK + 14D9 3A C2 CMP AL,DL ;SEE IF WE WANT MORE THAN THE MAX + 14DB 7E 04 JLE GTBX1$ + 14DD 8A C2 MOV AL,DL ;MAKE IT THE MAX THEN + 14DF B6 01 MOV DH,1 ;SIGNAL ANOTHER PASS NEEDED + 14E1 E8 19B2 R GTBX1$: CALL .RDWRT ;PERFORM THE DISK OPERATION + 14E4 72 25 JC GTB1$ ;READ/WRITE FAILED IF CARRY SET + 14E6 80 FE 01 CMP DH,1 ;TEST FOR ANOTHER PASS + 14E9 75 1C JNZ GTBX2$ + 14EB 2A F6 SUB DH,DH ;CLEAN UP SO THAT DL IS # SECTORS JUST HACKED + 14ED A1 02AB R MOV AX,GTBSTT + 14F0 03 C2 ADD AX,DX ;START N SECTORS HIGHER + 14F2 8B 0E 02A9 R MOV CX,GTBCNT +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 17-7 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + HIGH LEVEL IBMPC DEPENDENT STUFF + + 14F6 2B CA SUB CX,DX ;AND N LESS SECTORS LEFT TO HACK + 14F8 8B 1E 02AD R MOV BX,GTBCOR + 14FC 51 PUSH CX + 14FD B9 0009 MOV CX,9 ;SHIFT #SECTORS BY 9 FOR NEW CORE ADDRESS + 1500 D3 E2 SHL DX,CL + 1502 59 POP CX + 1503 03 DA ADD BX,DX ;HERE'S WHERE TO READ INTO NEXT PASS + 1505 EB A8 JMP GTBX0$ + 1507 F8 GTBX2$: CLC ;INDICATE DISK OPERATION WON + 1508 5D GTBX3$: POP BP ;RESTORES + 1509 5A POP DX + 150A C3 RET + 150B 80 3E 02A6 R 00 GTB1$: CMP DSKMOD,0 ;CHECK WHETHER THIS IS GAME MODE + 1510 74 03 JZ GTB2$ ;YES, FATAL OUT + 1512 F9 STC ;SET CARRY FLAG TO INDICATE LOSSAGE + 1513 EB F3 JMP GTBX3$ ;RETURN NORMALLY + 1515 GTB2$: FATAL FTL7 + 1515 E8 18F0 R + CALL .CRLF + 1518 B8 09DF R + MOV AX,OFFSET FATHDR + 151B E8 196F R + CALL .PRINT + 151E B8 09CA R + MOV AX,OFFSET FTL7 + 1521 E8 196F R + CALL .PRINT + 1524 E9 1A47 R + JMP FINISH + 1527 GTBLKS ENDP + + SUBTTL FRIGGING BACKUP COPY ROUTINE +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 18-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + FRIGGING BACKUP COPY ROUTINE + + PAGE + + + 1527 WPCHK PROC + 1527 C6 06 02A8 R 01 MOV DSKDIR,1 ; WRITE + 152C C6 06 02A7 R 00 MOV DSKDRV,0 ; DRIVE 0 + 1531 C6 06 02A6 R 01 MOV DSKMOD,1 ; ABSOLUTE SECTORS + 1536 B8 002F MOV AX,2FH ; RANDOM SPOT + 1539 BB 0000 MOV BX,0 + 153C B9 0001 MOV CX,1 ; ONE BLOCK + 153F E8 14AD R CALL GTBKI$ + 1542 80 FC 03 CMP AH,3 ; HOPE IT FAILS WITH W/P FAILURE + 1545 74 18 JE WPCHK1 ; GOOD. WIN + PRINT BKWPS1 ; TELL USER TO W/P DISK + 1547 50 + PUSH AX + 1548 B8 083B R + MOV AX,OFFSET BKWPS1 + 154B E8 196F R + CALL .PRINT + 154E 58 + POP AX + PRINT BKWPS2 + 154F 50 + PUSH AX + 1550 B8 085C R + MOV AX,OFFSET BKWPS2 + 1553 E8 196F R + CALL .PRINT + 1556 58 + POP AX + 1557 E8 1864 R CALL .CHRIN ; WAIT FOR CHARACTER + 155A E8 18F0 R CALL .CRLF + 155D EB C8 JMP WPCHK ; AND TRY AGAIN + 155F C7 06 095A R 0000 WPCHK1: MOV MORLIN,0 + 1565 C3 RET + 1566 WPCHK ENDP + + ;CHECK WHETHER BACKUP IS POSSIBLE + 1566 BKCHK PROC + 1566 E8 0F1A R CALL TSETUP + 1569 E8 1791 R CALL BKSTAT ;GET STATUS BITS INTO AL + 156C 3C 03 CMP AL,3 ;THIS IS MASTER/BACKUP ALLOWED + 156E 74 01 JE BKUP + 1570 C3 RET + + 1571 BKUP: PRINT BKASK1 ;ASK WHETHER BACKUP WANTED + 1571 50 + PUSH AX + 1572 B8 068E R + MOV AX,OFFSET BKASK1 + 1575 E8 196F R + CALL .PRINT + 1578 58 + POP AX + PRINT BKASK2 + 1579 50 + PUSH AX + 157A B8 06B3 R + MOV AX,OFFSET BKASK2 + 157D E8 196F R + CALL .PRINT + 1580 58 + POP AX + PRINT BKASK3 + 1581 50 + PUSH AX + 1582 B8 06D7 R + MOV AX,OFFSET BKASK3 + 1585 E8 196F R + CALL .PRINT + 1588 58 + POP AX + PRINT BKASK4 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 18-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + FRIGGING BACKUP COPY ROUTINE + + 1589 50 + PUSH AX + 158A B8 06F8 R + MOV AX,OFFSET BKASK4 + 158D E8 196F R + CALL .PRINT + 1590 58 + POP AX + PRINT BKASK5 + 1591 50 + PUSH AX + 1592 B8 071E R + MOV AX,OFFSET BKASK5 + 1595 E8 196F R + CALL .PRINT + 1598 58 + POP AX + 1599 E8 1864 R CALL .CHRIN ;GET A CHARACTER + 159C 3C 21 CMP AL,"!" + 159E 74 1A JE BKUPF + 15A0 3C 59 CMP AL,"Y" + 15A2 74 1B JE BKUP1 + 15A4 3C 79 CMP AL,"y" + 15A6 74 17 JE BKUP1 + PRINT BKNOPE + 15A8 50 + PUSH AX + 15A9 B8 073A R + MOV AX,OFFSET BKNOPE + 15AC E8 196F R + CALL .PRINT + 15AF 58 + POP AX + 15B0 E8 18F0 R CALL .CRLF + 15B3 C7 06 095A R 0000 MOV MORLIN,0 + 15B9 C3 RET ;DOESN'T WANT TO, APPARENTLY... + + 15BA C6 06 0206 R 01 BKUPF: MOV NDISKS,1 + 15BF BKUP1: PRINT BKYEP + 15BF 50 + PUSH AX + 15C0 B8 0734 R + MOV AX,OFFSET BKYEP + 15C3 E8 196F R + CALL .PRINT + 15C6 58 + POP AX + 15C7 E8 18F0 R CALL .CRLF + 15CA A0 0206 R MOV AL,NDISKS + 15CD 3C 01 CMP AL,1 + 15CF 74 05 JE BKUP1Z + 15D1 C6 06 068C R 01 MOV BKDSK,1 ;MAKE COPY DISK DRIVE 1 FOR >1 DRIVE SYSTEMS + 15D6 80 3E 0206 R 01 BKUP1Z: CMP NDISKS,1 + 15DB 74 06 JE BKZZ + 15DD E8 17F2 R CALL BKIFST ;INSERT MASTER DISK + 15E0 EB 01 90 JMP BKZZ + 15E3 B8 0000 BKZZ: MOV AX,0 ;SECTOR 0 + 15E6 BB 0000 MOV BX,0 ;LOCATION 0 + 15E9 B9 0001 MOV CX,1 ;ONE SECTOR (BOOTSTRAP) + 15EC C6 06 02A8 R 00 MOV DSKDIR,0 ;READ + 15F1 C6 06 02A7 R 00 MOV DSKDRV,0 + 15F6 E8 14AD R CALL GTBKI$ + 15F9 73 03 JNC BKUP1A + 15FB E9 1747 R JMP BKABRT + 15FE E8 183F R BKUP1A: CALL BKICOP ;INSERT COPY DISK + 1601 B8 0000 MOV AX,0 + 1604 BB 0000 MOV BX,0 + 1607 B9 0001 MOV CX,1 + 160A C6 06 02A8 R 01 MOV DSKDIR,1 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 18-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + FRIGGING BACKUP COPY ROUTINE + + MOVM DSKDRV,BKDSK,DL + 160F 8A 16 068C R + MOV DL,BKDSK + 1613 88 16 02A7 R + MOV DSKDRV,DL + 1617 E8 14AD R CALL GTBKI$ ;WRITE BOOTSTRAP ONTO COPY + 161A 73 03 JNC BKUP1B + 161C E9 1747 R JMP BKABRT + 161F E8 1817 R BKUP1B: CALL BKIMST ;ASK TO INSERT MASTER + + ;CODE HERE FOR FORMATTING/COPYING INTERPRETER IS TAKEN + ;FROM CREATE.ASM -- IT'S ALL MAGIC + + 1622 E8 1759 R CALL DSKHAK + + 1625 BA 0003 MOV DX,3 + 1628 2B DB SUB BX,BX + 162A B5 01 MOV CH,1 + 162C 52 BKRIL: PUSH DX + 162D B1 01 MOV CL,1 + 162F 51 PUSH CX + 1630 2B D2 SUB DX,DX + 1632 B8 0204 MOV AX,0204H + 1635 CD 13 INT 13H + 1637 72 0E JC BKRIF + 1639 59 POP CX + 163A FE C5 INC CH + 163C 81 C3 1000 ADD BX,1000H + 1640 5A POP DX + 1641 4A DEC DX + 1642 75 E8 JNZ BKRIL + 1644 EB 06 90 JMP BKWINT + + 1647 5A BKRIF: POP DX + 1648 5A POP DX + 1649 E9 1747 R JMP BKABRT + + 164C E8 177A R BKWINT: CALL DSKFIX + + 164F E8 183F R CALL BKICOP ;LOAD COPY DISK + + 1652 E8 1759 R CALL DSKHAK + + ; NOW WRITE IT OUT + + 1655 B9 0101 MOV CX,0101H + 1658 BB 0880 R FRML: MOV BX,OFFSET IDTBL + 165B C6 06 068A R 04 MOV SECCNT,4 + 1660 88 2F FRMLL: MOV [BX],CH + 1662 83 C3 04 ADD BX,4 + 1665 FE 0E 068A R DEC SECCNT + 1669 75 F5 JNZ FRMLL + + 166B BB 0880 R MOV BX,OFFSET IDTBL + 166E B6 00 MOV DH,0 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 18-4 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + FRIGGING BACKUP COPY ROUTINE + + 1670 8A 16 068C R MOV DL,BKDSK + 1674 06 PUSH ES + 1675 8C D8 MOV AX,DS + 1677 8E C0 MOV ES,AX + 1679 B8 0504 MOV AX,0504H + 167C CD 13 INT 13H ;ES MUST BE = TO DS FOR FORMAT + 167E 07 POP ES + 167F 80 C5 01 ADD CH,1 ;PUT CHECK FOR FAILURE HERE + 1682 FE 0E 068B R DEC TRKCNT + 1686 75 D0 JNZ FRML + + 1688 C6 06 068B R 03 MOV TRKCNT,3 + 168D BB 0000 MOV BX,0 + 1690 B9 0101 MOV CX,0101H + 1693 B6 00 MOV DH,0 + 1695 8A 16 068C R MOV DL,BKDSK + 1699 B8 0304 WLP: MOV AX,0304H + 169C CD 13 INT 13H + 169E 81 C3 1000 ADD BX,1000H + 16A2 FE C5 INC CH + 16A4 FE 0E 068B R DEC TRKCNT + 16A8 75 EF JNZ WLP + + 16AA E8 177A R CALL DSKFIX + + 16AD C6 06 068B R 04 MOV TRKCNT,4 ;READ MAX. 96 K (THIS WILL CHANGE) + 16B2 C6 06 068A R 30 MOV SECCNT,30H ;START OF GAME + 16B7 E8 1817 R BKUPGL: CALL BKIMST ;GET MASTER BACK INTO DRIVE + 16BA C6 06 02A8 R 00 MOV DSKDIR,0 ;READ + 16BF C6 06 02A7 R 00 MOV DSKDRV,0 + 16C4 A0 068A R MOV AL,SECCNT + 16C7 2A E4 SUB AH,AH ;FIRST SECTOR HERE + 16C9 BB 0000 MOV BX,0 + 16CC B9 0040 MOV CX,40H ;GET 32K (64 SECTORS) + 16CF E8 14AD R CALL GTBKI$ ;READ SOME GAME STUFF + 16D2 73 03 JNC BKUPG1 + 16D4 EB 71 90 JMP BKABRT + 16D7 80 3E 068B R 01 BKUPG1: CMP TRKCNT,1 + 16DC 75 26 JNE BKUP2 ;CONTINUE + 16DE C6 06 02A8 R 01 MOV DSKDIR,1 ;WRITE + 16E3 C6 06 02A7 R 00 MOV DSKDRV,0 + 16E8 BB 02F5 R MOV BX,OFFSET BKBUF + 16EB B9 0001 MOV CX,1 + 16EE C6 06 02F5 R 01 MOV BKBUF,1 ;PVERS1=0 + 16F3 06 PUSH ES + 16F4 8C D8 MOV AX,DS + 16F6 8E C0 MOV ES,AX + 16F8 B8 002E MOV AX,2EH + 16FB E8 14AD R CALL GTBKI$ ;FIX SO IT CAN'T BE COPIED + 16FE 07 POP ES + 16FF 73 03 JNC BKUP2 + 1701 EB 44 90 JMP BKABRT + 1704 E8 183F R BKUP2: CALL BKICOP ;GET COPY NOW +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 18-5 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + FRIGGING BACKUP COPY ROUTINE + + 1707 C6 06 02A8 R 01 MOV DSKDIR,1 ;WRITE + MOVM DSKDRV,BKDSK,DL + 170C 8A 16 068C R + MOV DL,BKDSK + 1710 88 16 02A7 R + MOV DSKDRV,DL + 1714 A0 068A R MOV AL,SECCNT + 1717 2A E4 SUB AH,AH + 1719 BB 0000 MOV BX,0 + 171C B9 0040 MOV CX,40H + 171F E8 14AD R CALL GTBKI$ ;WRITE SOME GAME STUFF + 1722 73 03 JNC BKUP2A + 1724 EB 21 90 JMP BKABRT + 1727 80 2E 068B R 01 BKUP2A: SUB TRKCNT,1 + 172C 74 07 JZ BKUP3 ;DONE WITH BACKUP + 172E 80 06 068A R 40 ADD SECCNT,40H + 1733 EB 82 JMP BKUPGL + + 1735 BKUP3: PRINT BKDONE + 1735 50 + PUSH AX + 1736 B8 080D R + MOV AX,OFFSET BKDONE + 1739 E8 196F R + CALL .PRINT + 173C 58 + POP AX + 173D E8 1817 R CALL BKIMST ;ENSURE MASTER IN PLACE + 1740 C7 06 095A R 0000 MOV MORLIN,0 + 1746 C3 RET + + 1747 BKABRT: PRINT BKFAIL + 1747 50 + PUSH AX + 1748 B8 081F R + MOV AX,OFFSET BKFAIL + 174B E8 196F R + CALL .PRINT + 174E 58 + POP AX + 174F E8 1817 R CALL BKIMST ;ENSURE MASTER IN PLACE + 1752 C7 06 095A R 0000 MOV MORLIN,0 + 1758 C3 RET + + 1759 BKCHK ENDP + + 1759 DSKHAK PROC + 1759 8C DF MOV DI,DS + 175B BE 0875 R MOV SI,OFFSET DSK_PRM + 175E 1E PUSH DS + 175F 2B C0 SUB AX,AX + 1761 8E D8 MOV DS,AX + ASSUME DS:ABS_SG + 1763 BB 0078 MOV BX,78H + 1766 8B 0F MOV CX,[BX] + 1768 8B 57 02 MOV DX,[BX+2] + 176B 89 37 MOV [BX],SI + 176D 89 7F 02 MOV [BX+2],DI + 1770 1F POP DS + ASSUME DS:DATA_SG + 1771 89 0E 0871 R MOV DSK_SV1,CX + 1775 89 16 0873 R MOV DSK_SV2,DX + 1779 C3 RET +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 18-6 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + FRIGGING BACKUP COPY ROUTINE + + 177A DSKHAK ENDP + + 177A DSKFIX PROC + 177A 1E PUSH DS + 177B 8B 0E 0871 R MOV CX,DSK_SV1 + 177F 8B 16 0873 R MOV DX,DSK_SV2 + 1783 2B C0 SUB AX,AX + 1785 8E D8 MOV DS,AX + ASSUME DS:ABS_SG + 1787 BB 0078 MOV BX,78H + 178A 89 0F MOV [BX],CX + 178C 89 57 02 MOV [BX+2],DX + 178F 1F POP DS + ASSUME DS:DATA_SG + 1790 C3 RET + 1791 DSKFIX ENDP + + ;READ THE STATUS BLOCK FROM DISK + 1791 BKSTAT PROC + 1791 06 PUSH ES + 1792 8C D8 MOV AX,DS + 1794 8E C0 MOV ES,AX + 1796 C6 06 02A8 R 00 BKSTRT: MOV DSKDIR,0 ;READ + 179B C6 06 02A6 R 01 MOV DSKMOD,1 ;ABSOLUTE SECTORS + 17A0 B8 002E MOV AX,2EH ;STATUS SECTOR + 17A3 BB 02F5 R MOV BX,OFFSET BKBUF ;READ AT BKBUF (IN DS) + 17A6 B9 0001 MOV CX,1 ;ONE SECTOR + 17A9 E8 14AD R CALL GTBKI$ ;READ IT + 17AC 72 34 JC BKST1 ;FAILED? + 17AE 80 3E 068D R 01 CMP BKFRST,1 + 17B3 74 13 JE BKSEND + 17B5 C6 06 02A8 R 01 MOV DSKDIR,1 ;WRITE + 17BA B8 002F MOV AX,2FH ;RANDOM SPOT + 17BD BB 0000 MOV BX,0 + 17C0 B9 0001 MOV CX,1 + 17C3 E8 14AD R CALL GTBKI$ ;WRITE SOMETHING OR OTHER + 17C6 72 0A JC BKST0 ;LOSER! + 17C8 C6 06 068D R 00 BKSEND: MOV BKFRST,0 + 17CD 07 POP ES + 17CE A0 02F5 R MOV AL,BKBUF ;GET FIRST BYTE + 17D1 C3 RET + 17D2 80 FC 03 BKST0: CMP AH,3 ;CHECK SPECIFICALLY FOR WRITE-PROTECT + 17D5 75 0B JNE BKST1 + PRINT BKWPRT ;TELL LOSER ABOUT WRITE PROTECTEDNESS + 17D7 50 + PUSH AX + 17D8 B8 07D3 R + MOV AX,OFFSET BKWPRT + 17DB E8 196F R + CALL .PRINT + 17DE 58 + POP AX + 17DF EB 09 90 JMP BKST2 + + 17E2 BKST1: PRINT BKNRDY ;TELL LOSER DISK ISN`T WINNING + 17E2 50 + PUSH AX + 17E3 B8 07F5 R + MOV AX,OFFSET BKNRDY +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 18-7 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + FRIGGING BACKUP COPY ROUTINE + + 17E6 E8 196F R + CALL .PRINT + 17E9 58 + POP AX + 17EA E8 1864 R BKST2: CALL .CHRIN ;GET SOME RANDOM CHARACTER + 17ED E8 18F0 R CALL .CRLF + 17F0 EB A4 JMP BKSTRT ;TRY, TRY AGAIN + + 17F2 BKSTAT ENDP + + ;ASK LOSER TO INSERT MASTER DISK, CHECK FOR MASTERHOOD + 17F2 BKIFST PROC + PRINT BKMC1 + 17F2 50 + PUSH AX + 17F3 B8 073F R + MOV AX,OFFSET BKMC1 + 17F6 E8 196F R + CALL .PRINT + 17F9 58 + POP AX + PRINT BKMC2 + 17FA 50 + PUSH AX + 17FB B8 075D R + MOV AX,OFFSET BKMC2 + 17FE E8 196F R + CALL .PRINT + 1801 58 + POP AX + PRINT BKMC3 + 1802 50 + PUSH AX + 1803 B8 0779 R + MOV AX,OFFSET BKMC3 + 1806 E8 196F R + CALL .PRINT + 1809 58 + POP AX + 180A E8 1864 R CALL .CHRIN + 180D E8 18F0 R CALL .CRLF + 1810 E8 1817 R CALL BKIMST + 1813 E8 183F R CALL BKICOP + 1816 C3 RET + 1817 BKIFST ENDP + + 1817 BKIMST PROC + 1817 80 3E 068C R 00 CMP BKDSK,0 + 181C 75 0E JNE BKIMS1 + 181E BKIMSR: PRINT BKMAST ;PRINT MESSAGE + 181E 50 + PUSH AX + 181F B8 0795 R + MOV AX,OFFSET BKMAST + 1822 E8 196F R + CALL .PRINT + 1825 58 + POP AX + 1826 E8 1864 R CALL .CHRIN ;GET SOME CHARACTER + 1829 E8 18F0 R CALL .CRLF + 182C C6 06 02A7 R 00 BKIMS1: MOV DSKDRV,0 + 1831 E8 1791 R CALL BKSTAT ;GET STATUS FROM DISK, ENSURE NOT W/P + 1834 3C 03 CMP AL,3 + 1836 74 06 JE BKIMSX ;IT'S NOT A MASTER DISK.... + 1838 3C 01 CMP AL,1 + 183A 74 02 JE BKIMSX + 183C EB E0 JMP BKIMSR + 183E C3 BKIMSX: RET + 183F BKIMST ENDP + + ;ASK LOSER TO INSERT COPY DISK, CHECK FOR COPYHOOD +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 18-8 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + FRIGGING BACKUP COPY ROUTINE + + 183F BKICOP PROC + 183F 80 3E 068C R 00 CMP BKDSK,0 + 1844 75 0E JNE BKICP1 + 1846 BKICPR: PRINT BKCOPY ;PRINT MESSAGE + 1846 50 + PUSH AX + 1847 B8 07B5 R + MOV AX,OFFSET BKCOPY + 184A E8 196F R + CALL .PRINT + 184D 58 + POP AX + 184E E8 1864 R CALL .CHRIN + 1851 E8 18F0 R CALL .CRLF + 1854 BKICP1: MOVM DSKDRV,BKDSK,DL + 1854 8A 16 068C R + MOV DL,BKDSK + 1858 88 16 02A7 R + MOV DSKDRV,DL + 185C E8 1791 R CALL BKSTAT + 185F A8 01 TEST AL,1 + 1861 75 E3 JNZ BKICPR ;IT'S NOT A COPY DISK.... + 1863 C3 RET + 1864 BKICOP ENDP + + SUBTTL IBMPC SYSTEM ROUTINES +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 19-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + IBMPC SYSTEM ROUTINES + + PAGE + + + ;READ A CHARACTER INTO AX, WAITING UNTIL ONE IS AVAILABLE, NO ECHO + 1864 .CHRIN PROC + 1864 80 3E 066B R 00 CMP CHRFLG,0 + 1869 75 15 JNZ .CHR1$ + 186B C6 06 066B R 01 MOV CHRFLG,1 + 1870 51 PUSH CX + 1871 52 PUSH DX + 1872 2A E4 SUB AH,AH + 1874 CD 1A INT 1AH ;READ THE SYSTEM TIME AT FIRST CHARACTER + 1876 31 0E 02AF R XOR RSEED1,CX ;DO SOME MORE RANDOMIZING + 187A 31 16 02B1 R XOR RSEED2,DX ;BE CONSISTENT + 187E 5A POP DX + 187F 59 POP CX + 1880 2A E4 .CHR1$: SUB AH,AH ;SET UP FOR READ NEXT CHARACTER STRUCK + 1882 CD 16 INT 16H ;CALL BIOS KEYBOARD I/O ROUTINE + 1884 2A E4 SUB AH,AH ;CLEAR HIGH BYTE + 1886 C3 RET + 1887 .CHRIN ENDP + + ;PRINT THE CHARACTER IN AL, FOREGROUND IN AH + 1887 .TTYOUT PROC + 1887 50 PUSH AX + 1888 53 PUSH BX ;SAVES + 1889 52 PUSH DX + 188A 55 PUSH BP + 188B 50 PUSH AX + 188C 8A DC MOV BL,AH ;FOREGROUND + 188E B4 0E MOV AH,14 ;SET UP FOR TELETYPE OUTPUT + 1890 2A FF SUB BH,BH ;PAGE 0 + 1892 CD 10 INT 10H ;CALL BIOS DISPLAY I/O ROUTINE + 1894 58 POP AX + 1895 80 3E 0023 R 00 CMP SCRFLG,0 + 189A 74 03 JZ .TYO1$ + 189C E8 0773 R CALL PRTOUT + 189F 5D .TYO1$: POP BP ;RESTORES + 18A0 5A POP DX + 18A1 5B POP BX + 18A2 58 POP AX + 18A3 C3 RET + 18A4 .TTYOUT ENDP + + ;PRINT THE CHARACTER IN AL, ATTRIBUTES IN AH, ROW IN BH, COLUMN IN BL + 18A4 .CHROUT PROC + 18A4 51 PUSH CX ;SAVES + 18A5 52 PUSH DX + 18A6 55 PUSH BP + 18A7 50 PUSH AX ;SAVE CHARACTER AND ATTRIBUTES + 18A8 B4 02 MOV AH,2 ;SET UP FOR SET CURSOR POSITION + 18AA 8B D3 MOV DX,BX ;ROW AND COLUMN + 18AC 2A FF SUB BH,BH ;PAGE 0 + 18AE CD 10 INT 10H ;CALL BIOS DISPLAY I/O ROUTINE +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 19-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + IBMPC SYSTEM ROUTINES + + 18B0 58 POP AX ;RESTORE CHARACTER AND ATTRIBUTES + 18B1 B4 09 MOV AH,9 ;SET UP FOR WRITE ATTRIBUTE/CHARACTER + 18B3 2A FF SUB BH,BH ;PAGE 0 + 18B5 8A 1E 0000 R MOV BL,NRMATR ;NORMAL ATTRIBUTES + 18B9 B9 0001 MOV CX,1 ;WRITE 1 CHARACTER + 18BC CD 10 INT 10H ;CALL BIOS DISPLAY I/O ROUTINE + 18BE 5D POP BP ;RESTORES + 18BF 5A POP DX + 18C0 59 POP CX + 18C1 C3 RET + 18C2 .CHROUT ENDP + + ;PRINT SPACES, WITHOUT MOVING CURSOR, NUMBER IN AL, ATTRIBUTE IN AH + 18C2 .SPACE PROC + 18C2 53 PUSH BX ;SAVES + 18C3 51 PUSH CX + 18C4 55 PUSH BP + 18C5 8A DC MOV BL,AH ;ATTRIBUTE + 18C7 2A E4 SUB AH,AH ;CLEAR HIGH BYTE + 18C9 8B C8 MOV CX,AX ;NUMBER OF SPACES + 18CB B4 09 MOV AH,9 ;SET UP FOR WRITE ATTRIBUTE/CHARACTER + 18CD B0 20 MOV AL,32 ;WRITE SPACES + 18CF 2A FF SUB BH,BH ;PAGE 0 + 18D1 8A 1E 0000 R MOV BL,NRMATR ;****** THIS SHOULD HELP + 18D5 CD 10 INT 10H ;CALL BIOS DISPLAY I/O ROUTINE + 18D7 5D POP BP ;RESTORES + 18D8 59 POP CX + 18D9 5B POP BX + 18DA C3 RET + 18DB .SPACE ENDP + + ;MOVE TO FIRST COLUMN OF SCREEN BOTTOM + 18DB .CRBT PROC + 18DB 50 PUSH AX ;SAVES + 18DC 53 PUSH BX + 18DD 52 PUSH DX + 18DE 55 PUSH BP + 18DF B4 02 MOV AH,2 ;SET UP FOR SET CURSOR POSITION + 18E1 2A FF SUB BH,BH ;PAGE 0 + 18E3 8A 16 02DA R MOV DL,LFTMAR ;MOVE TO FIRST COLUMN + 18E7 B6 18 MOV DH,24 ;MOVE TO BOTTOM ROW + 18E9 CD 10 INT 10H ;CALL BIOS DISPLAY I/O ROUTINE + 18EB 5D POP BP ;RESTORES + 18EC 5A POP DX + 18ED 5B POP BX + 18EE 58 POP AX + 18EF C3 RET + 18F0 .CRBT ENDP + + ;PRINT A CARRIAGE RETURN/LINE FEED, WITH MORE MODE (ASSUMING SCREEN + ;BOTTOM) + 18F0 .CRLF PROC + 18F0 50 PUSH AX ;SAVES +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 19-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + IBMPC SYSTEM ROUTINES + + 18F1 53 PUSH BX + 18F2 51 PUSH CX + 18F3 52 PUSH DX + 18F4 55 PUSH BP + 18F5 80 3E 02D9 R 00 CMP CURSCR,0 + 18FA 74 18 JE .CRLFN + + CURGET ;HERE FOR SCREEN 1, PUT CURSOR ON NEXT LINE + 18FC 50 + PUSH AX + 18FD 2A FF + SUB BH,BH + 18FF B4 03 + MOV AH,3 + 1901 CD 10 + INT 10H + 1903 58 + POP AX + 1904 80 C6 01 ADD DH,1 + 1907 B2 02 MOV DL,2 ; ADJUST FOR SONAR IN SEA STALKER + + 1909 .CRLF1: CURSET + 1909 50 + PUSH AX + 190A 2A FF + SUB BH,BH + 190C B4 02 + MOV AH,2 + 190E CD 10 + INT 10H + 1910 58 + POP AX + 1911 EB 4C 90 JMP .CR1$ + + 1914 FF 06 095A R .CRLFN: INC MORLIN ;INCREMENT NUMBER OF LINES OUTPUT + 1918 B4 06 MOV AH,6 ;SET UP FOR SCROLL PAGE UP + 191A B0 01 MOV AL,1 ;ONE LINE UP + 191C 8A 3E 0000 R MOV BH,NRMATR ;NORMAL DISPLAY ATTRIBUTE + 1920 B1 00 MOV CL,0 + 1922 8A 2E 02D8 R MOV CH,SCRN0 + 1926 8B 16 02D4 R MOV DX,TWIDTH + 192A B6 18 MOV DH,18H ;END AT LINE 24, COLUMN TWIDTH+1 + 192C CD 10 INT 10H ;CALL BIOS DISPLAY I/O ROUTINE + 192E E8 18DB R CALL .CRBT ;MOVE TO BEGINNING OF NEW LINE + 1931 A1 095A R MOV AX,MORLIN + 1934 3B 06 095C R CMP AX,LINMAX ;FULL PAGE OUTPUT? + 1938 7C 25 JL .CR1$ ;NOT YET + 193A C7 06 095A R 0000 MOV MORLIN,0 ;RESET COUNTER + 1940 B8 0950 R MOV AX,OFFSET MORE ;ADDRESS OF MORE MODE PROMPT STRING + 1943 8A 1E 0001 R MOV BL,USLATR ;INVERSE VIDEO + 1947 B5 18 MOV CH,18H ;STARTING IN ROW 24, COLUMN LFTMAR + 1949 8A 0E 02DA R MOV CL,LFTMAR + 194D E8 198B R CALL .PRINTA ;PRINT IT WITH ATTRIBUTES + 1950 E8 1864 R CALL .CHRIN ;READ A CHARACTER TO CONTINUE + 1953 E8 18DB R CALL .CRBT ;MOVE TO BEGINNING OF NEW LINE + 1956 B0 09 MOV AL,9 ;9 SPACES + 1958 8A 26 0000 R MOV AH,NRMATR ;NORMAL DISPLAY + 195C E8 18C2 R CALL .SPACE ;PRINT THEM (CURSOR UNAFFECTED) + 195F 80 3E 0023 R 00 .CR1$: CMP SCRFLG,0 + 1964 74 03 JE .CR2$ + 1966 E8 0813 R CALL PRTCRL ;CRLF TO PRINTER + 1969 5D .CR2$: POP BP ;RESTORES + 196A 5A POP DX +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 19-4 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + IBMPC SYSTEM ROUTINES + + 196B 59 POP CX + 196C 5B POP BX + 196D 58 POP AX + 196E C3 RET + 196F .CRLF ENDP + + ;PRINT A STRING, POINTER (TO DATA SEGMENT) IN AX, WHITE FOREGROUND + 196F .PRINT PROC + 196F 53 PUSH BX ;SAVE BX + 1970 8B D8 MOV BX,AX ;STRING POINTER + 1972 8A 07 .PR1$: MOV AL,[BX] ;GET NEXT CHARACTER + 1974 3C 00 CMP AL,0 ;END OF LINE, WITH CRLF? + 1976 74 0E JE .PR2$ ;YES + 1978 3C 80 CMP AL,80H ;END OF LINE, NO CRLF? + 197A 74 0D JE .PR3$ ;YES + 197C 8A 26 0000 R MOV AH,NRMATR ;WHITE FOREGROUND + 1980 E8 1887 R CALL .TTYOUT ;PRINT CHARACTER + 1983 43 INC BX ;POINT TO NEXT CHARACTER + 1984 EB EC JMP .PR1$ ;REPEAT + 1986 E8 18F0 R .PR2$: CALL .CRLF ;PRINT A CRLF + 1989 5B .PR3$: POP BX ;RESTORE BX + 198A C3 RET + 198B .PRINT ENDP + + ;PRINT A STRING, POINTER (TO DATA SEGMENT) IN AX, ATTRIBUTES IN BX, + ;STARTING ROW IN CH, STARTING COLUMN IN CL + 198B .PRINTA PROC + 198B 51 PUSH CX ;SAVE CX + 198C 52 PUSH DX ;SAVE DX + 198D 56 PUSH SI ;SAVE SI + 198E 57 PUSH DI ;SAVE DI + 198F 8B F0 MOV SI,AX ;STRING POINTER + 1991 8B D3 MOV DX,BX ;ATTRIBUTES + 1993 8B F9 MOV DI,CX ;ROW AND COLUMN + 1995 8A 04 .PA1$: MOV AL,[SI] ;GET NEXT CHARACTER + 1997 3C 00 CMP AL,0 ;END OF LINE, WITH CRLF? + 1999 74 0F JE .PA2$ ;YES + 199B 3C 80 CMP AL,80H ;END OF LINE, NO CRLF? + 199D 74 0E JE .PA3$ ;YES + 199F 8A E2 MOV AH,DL ;ATTRIBUTES + 19A1 8B DF MOV BX,DI ;ROW AND COLUMN + 19A3 E8 18A4 R CALL .CHROUT ;PRINT CHARACTER + 19A6 46 INC SI ;POINT TO NEXT CHARACTER + 19A7 47 INC DI ;MOVE TO NEXT COLUMN + 19A8 EB EB JMP .PA1$ ;REPEAT + 19AA E8 18F0 R .PA2$: CALL .CRLF ;PRINT A CRLF + 19AD 5F .PA3$: POP DI ;RESTORE DI + 19AE 5E POP SI ;RESTORE SI + 19AF 5A POP DX ;RESTORE DX + 19B0 59 POP CX ;RESTORE CX + 19B1 C3 RET + 19B2 .PRINTA ENDP + +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 19-5 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + IBMPC SYSTEM ROUTINES + + ;READ AL SECTORS FROM DRIVE AH STARTING AT TRACK CH, SECTOR CL + ;TO MEMORY STARTING AT ES:BX + 19B2 .RDWRT PROC + 19B2 52 PUSH DX ;SAVES + 19B3 55 PUSH BP + 19B4 56 PUSH SI + 19B5 80 3E 0207 R 00 CMP FUCK,0 + 19BA 74 17 JE .RDX$ + 19BC 80 3E 066C R 05 CMP INIFLG,5 + 19C1 75 10 JNE .RDX$ + 19C3 E8 10B3 R CALL PRSPC + 19C6 8B C3 MOV AX,BX + 19C8 E8 10B3 R CALL PRSPC + 19CB 8B C1 MOV AX,CX + 19CD E8 10B3 R CALL PRSPC + 19D0 E8 18F0 R CALL .CRLF + 19D3 BD 0004 .RDX$: MOV BP,4 ;TRY READING 4 TIMES BEFORE FAILING + 19D6 8A D4 MOV DL,AH ;DRIVE NUMBER + 19D8 B4 02 MOV AH,2 ;SET UP FOR DISK READ + 19DA 80 3E 02A8 R 00 CMP DSKDIR,0 + 19DF 74 03 JE .RD0$ + 19E1 80 C4 01 ADD AH,1 ;WRITE IS CONVENIENTLY 3 + 19E4 8B F0 .RD0$: MOV SI,AX ;SAVE SET UP DATA FOR RETRIES + 19E6 2A F6 SUB DH,DH ;HEAD 0 + 19E8 8B C6 .RD1$: MOV AX,SI ;RESTORE SET UP DATA + 19EA CD 13 INT 13H ;CALL BIOS DISKETTE I/O ROUTINE + 19EC 73 18 JNC .RD2$ ;READ SUCCEEDED + 19EE 4D DEC BP ;DECREMENT TRY COUNTER + 19EF 75 F7 JNE .RD1$ ;RETRY IF COUNTER NON-ZERO + 19F1 80 3E 0207 R 00 CMP FUCK,0 + 19F6 74 0D JE .RDFL$ + 19F8 80 3E 066C R 05 CMP INIFLG,5 + 19FD 75 06 JNE .RDFL$ + 19FF E8 10B3 R CALL PRSPC + 1A02 E8 18F0 R CALL .CRLF + 1A05 F9 .RDFL$: STC ;INDICATE READ FAILED + 1A06 5E .RD2$: POP SI ;RESTORES + 1A07 5D POP BP + 1A08 5A POP DX + 1A09 C3 RET + 1A0A .RDWRT ENDP + + ;GET MEMORY SIZE (IN PARAGRAPHS) + 1A0A .GETMEM PROC + 1A0A F6 06 066C R 02 TEST INIFLG,INIMEM ;CHECK FOR FORCED MEMORY + 1A0F 74 04 JZ .GTM1$ + 1A11 B8 0C00 MOV AX,0C00H ;48K (IN PARAGRAPHS) + 1A14 C3 RET + 1A15 CD 12 .GTM1$: INT 12H ;CALL BIOS MEMORY SIZE DETERMINATION ROUTINE + 1A17 3D 0200 CMP AX,512 ;CHECK FOR >512K + 1A1A 7C 03 JL .GTMX$ + 1A1C B8 01F4 MOV AX,500 + 1A1F D1 E0 .GTMX$: SHL AX,1 ;CONVERT FROM K TO PARAGRAPHS +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE 19-6 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + IBMPC SYSTEM ROUTINES + + 1A21 D1 E0 SHL AX,1 + 1A23 D1 E0 SHL AX,1 + 1A25 D1 E0 SHL AX,1 + 1A27 D1 E0 SHL AX,1 + 1A29 D1 E0 SHL AX,1 + 1A2B 3D 1000 CMP AX,1000H ;MAXIMUM ALLOWED IS 64K (CROCK) + 1A2E 7E 03 JLE .GTM2$ + 1A30 B8 1000 MOV AX,1000H + 1A33 C3 .GTM2$: RET + 1A34 .GETMEM ENDP + + ;GET TIME + 1A34 .GETTM PROC + 1A34 50 PUSH AX ;SAVES + 1A35 51 PUSH CX + 1A36 52 PUSH DX + 1A37 2A E4 SUB AH,AH ;SET UP FOR READ TIME OF DAY + 1A39 CD 1A INT 1AH ;CALL BIOS TIME OF DAY ROUTINE + 1A3B 89 0E 095E R MOV TIME,CX ;STORE IN VARIABLE + 1A3F 89 16 0960 R MOV TIME[2],DX + 1A43 5A POP DX ;RESTORES + 1A44 59 POP CX + 1A45 58 POP AX + 1A46 C3 RET + 1A47 .GETTM ENDP + + 1A47 FINISH PROC + 1A47 E8 18F0 R CALL .CRLF + PRINT REBOOT + 1A4A 50 + PUSH AX + 1A4B B8 01B9 R + MOV AX,OFFSET REBOOT + 1A4E E8 196F R + CALL .PRINT + 1A51 58 + POP AX + PRINT REBOO1 + 1A52 50 + PUSH AX + 1A53 B8 01D0 R + MOV AX,OFFSET REBOO1 + 1A56 E8 196F R + CALL .PRINT + 1A59 58 + POP AX + 1A5A E8 1864 R CALL .CHRIN ;GET A CHARACTER + 1A5D CD 19 INT 19H ;REBOOT + 1A5F FINISH ENDP + + 1A5F CODE_SG ENDS + + 0000 GAME_SG SEGMENT PAGE AT 800H + 0000 GAME_SG ENDS + + END START + +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-1 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +Macros: + + N a m e Length + +CURGET . . . . . . . . . . . . . 0002 +CURSET . . . . . . . . . . . . . 0003 +FATAL. . . . . . . . . . . . . . 0003 +GTAWRD . . . . . . . . . . . . . 0001 +MOVM . . . . . . . . . . . . . . 0001 +POPZ . . . . . . . . . . . . . . 0002 +POPZT. . . . . . . . . . . . . . 0001 +PRINT. . . . . . . . . . . . . . 0002 +PTAWRD . . . . . . . . . . . . . 0001 +PUSHZ. . . . . . . . . . . . . . 0002 +PUSHZT . . . . . . . . . . . . . 0001 + +Structures and records: + + N a m e Width # fields + Shift Width Mask Initial + +OBJECT . . . . . . . . . . . . . 0009 0006 + FLAGS1 . . . . . . . . . . . . . 0000 + FLAGS2 . . . . . . . . . . . . . 0002 + PARENT . . . . . . . . . . . . . 0004 + SIBLING. . . . . . . . . . . . . 0005 + CHILD1 . . . . . . . . . . . . . 0006 + PROPS. . . . . . . . . . . . . . 0007 +PROPID . . . . . . . . . . . . . 0008 0002 + PROPSIZE . . . . . . . . . . . . 0005 0003 00E0 0000 + PROPNUM. . . . . . . . . . . . . 0000 0005 001F 0000 + +Segments and groups: + + N a m e Size align combine class + +ABS_SG . . . . . . . . . . . . . 0000 AT 0000 +CODE_SG. . . . . . . . . . . . . 1A5F PARA NONE +DATA_SG. . . . . . . . . . . . . 0A3B PARA NONE +GAME_SG. . . . . . . . . . . . . 0000 AT 0800 +STK_SG . . . . . . . . . . . . . 0400 PARA STACK + +Symbols: + + N a m e Type Value Attr + +ARGBLK . . . . . . . . . . . . . L WORD 0673 DATA_SG Length =0004 +BKABRT . . . . . . . . . . . . . L NEAR 1747 CODE_SG +BKASK1 . . . . . . . . . . . . . L BYTE 068E DATA_SG +BKASK2 . . . . . . . . . . . . . L BYTE 06B3 DATA_SG +BKASK3 . . . . . . . . . . . . . L BYTE 06D7 DATA_SG +BKASK4 . . . . . . . . . . . . . L BYTE 06F8 DATA_SG +BKASK5 . . . . . . . . . . . . . L BYTE 071E DATA_SG +BKBUF. . . . . . . . . . . . . . L BYTE 02F5 DATA_SG Length =0200 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-2 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +BKCHK. . . . . . . . . . . . . . N PROC 1566 CODE_SG Length =01F3 +BKCOPY . . . . . . . . . . . . . L BYTE 07B5 DATA_SG +BKDONE . . . . . . . . . . . . . L BYTE 080D DATA_SG +BKDSK. . . . . . . . . . . . . . L BYTE 068C DATA_SG +BKFAIL . . . . . . . . . . . . . L BYTE 081F DATA_SG +BKFRST . . . . . . . . . . . . . L BYTE 068D DATA_SG +BKICOP . . . . . . . . . . . . . N PROC 183F CODE_SG Length =0025 +BKICP1 . . . . . . . . . . . . . L NEAR 1854 CODE_SG +BKICPR . . . . . . . . . . . . . L NEAR 1846 CODE_SG +BKIFST . . . . . . . . . . . . . N PROC 17F2 CODE_SG Length =0025 +BKIMS1 . . . . . . . . . . . . . L NEAR 182C CODE_SG +BKIMSR . . . . . . . . . . . . . L NEAR 181E CODE_SG +BKIMST . . . . . . . . . . . . . N PROC 1817 CODE_SG Length =0028 +BKIMSX . . . . . . . . . . . . . L NEAR 183E CODE_SG +BKMAST . . . . . . . . . . . . . L BYTE 0795 DATA_SG +BKMC1. . . . . . . . . . . . . . L BYTE 073F DATA_SG +BKMC2. . . . . . . . . . . . . . L BYTE 075D DATA_SG +BKMC3. . . . . . . . . . . . . . L BYTE 0779 DATA_SG +BKNOPE . . . . . . . . . . . . . L BYTE 073A DATA_SG +BKNRDY . . . . . . . . . . . . . L BYTE 07F5 DATA_SG +BKRIF. . . . . . . . . . . . . . L NEAR 1647 CODE_SG +BKRIL. . . . . . . . . . . . . . L NEAR 162C CODE_SG +BKSEND . . . . . . . . . . . . . L NEAR 17C8 CODE_SG +BKST0. . . . . . . . . . . . . . L NEAR 17D2 CODE_SG +BKST1. . . . . . . . . . . . . . L NEAR 17E2 CODE_SG +BKST2. . . . . . . . . . . . . . L NEAR 17EA CODE_SG +BKSTAT . . . . . . . . . . . . . N PROC 1791 CODE_SG Length =0061 +BKSTRT . . . . . . . . . . . . . L NEAR 1796 CODE_SG +BKUP . . . . . . . . . . . . . . L NEAR 1571 CODE_SG +BKUP1. . . . . . . . . . . . . . L NEAR 15BF CODE_SG +BKUP1A . . . . . . . . . . . . . L NEAR 15FE CODE_SG +BKUP1B . . . . . . . . . . . . . L NEAR 161F CODE_SG +BKUP1Z . . . . . . . . . . . . . L NEAR 15D6 CODE_SG +BKUP2. . . . . . . . . . . . . . L NEAR 1704 CODE_SG +BKUP2A . . . . . . . . . . . . . L NEAR 1727 CODE_SG +BKUP3. . . . . . . . . . . . . . L NEAR 1735 CODE_SG +BKUPF. . . . . . . . . . . . . . L NEAR 15BA CODE_SG +BKUPG1 . . . . . . . . . . . . . L NEAR 16D7 CODE_SG +BKUPGL . . . . . . . . . . . . . L NEAR 16B7 CODE_SG +BKWINT . . . . . . . . . . . . . L NEAR 164C CODE_SG +BKWPRT . . . . . . . . . . . . . L BYTE 07D3 DATA_SG +BKWPS1 . . . . . . . . . . . . . L BYTE 083B DATA_SG +BKWPS2 . . . . . . . . . . . . . L BYTE 085C DATA_SG +BKYEP. . . . . . . . . . . . . . L BYTE 0734 DATA_SG +BKZZ . . . . . . . . . . . . . . L NEAR 15E3 CODE_SG +BSPLIT . . . . . . . . . . . . . N PROC 0C6B CODE_SG Length =000B +BSPLTB . . . . . . . . . . . . . N PROC 0C5D CODE_SG Length =000E +BUFPGS . . . . . . . . . . . . . L WORD 0669 DATA_SG +BYTVAL . . . . . . . . . . . . . N PROC 0BFD CODE_SG Length =0005 +CCS1$. . . . . . . . . . . . . . L NEAR 0D94 CODE_SG +CCS2$. . . . . . . . . . . . . . L NEAR 0D98 CODE_SG +CCS3$. . . . . . . . . . . . . . L NEAR 0DA9 CODE_SG +CCS4$. . . . . . . . . . . . . . L NEAR 0DAF CODE_SG +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-3 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +CCS5$. . . . . . . . . . . . . . L NEAR 0DB7 CODE_SG +CHB1$. . . . . . . . . . . . . . L NEAR 0DBD CODE_SG +CHB2$. . . . . . . . . . . . . . L NEAR 0DCD CODE_SG +CHB3$. . . . . . . . . . . . . . L NEAR 0DD3 CODE_SG +CHB4$. . . . . . . . . . . . . . L NEAR 0DDD CODE_SG +CHRBYT . . . . . . . . . . . . . N PROC 0DB9 CODE_SG Length =0026 +CHRCS. . . . . . . . . . . . . . N PROC 0D8B CODE_SG Length =002E +CHRFLG . . . . . . . . . . . . . L BYTE 066B DATA_SG +CHRPTR . . . . . . . . . . . . . L WORD 02C6 DATA_SG +CLRSC1 . . . . . . . . . . . . . L NEAR 1449 CODE_SG +CLRSCR . . . . . . . . . . . . . N PROC 1438 CODE_SG Length =001D +COLFLG . . . . . . . . . . . . . L BYTE 0020 DATA_SG +COLORQ . . . . . . . . . . . . . L BYTE 0003 DATA_SG +CURBLK . . . . . . . . . . . . . L WORD 067D DATA_SG +CURPAG . . . . . . . . . . . . . L WORD 067B DATA_SG +CURSCR . . . . . . . . . . . . . L BYTE 02D9 DATA_SG +CURTAB . . . . . . . . . . . . . L WORD 067F DATA_SG +DAN1 . . . . . . . . . . . . . . L NEAR 0283 CODE_SG +DAN2 . . . . . . . . . . . . . . L NEAR 0285 CODE_SG +DIP1 . . . . . . . . . . . . . . L NEAR 0209 CODE_SG +DIP3 . . . . . . . . . . . . . . L NEAR 0231 CODE_SG +DIP4 . . . . . . . . . . . . . . L NEAR 0236 CODE_SG +DSKDIR . . . . . . . . . . . . . L BYTE 02A8 DATA_SG +DSKDRV . . . . . . . . . . . . . L BYTE 02A7 DATA_SG +DSKFIX . . . . . . . . . . . . . N PROC 177A CODE_SG Length =0017 +DSKHAK . . . . . . . . . . . . . N PROC 1759 CODE_SG Length =0021 +DSKMOD . . . . . . . . . . . . . L BYTE 02A6 DATA_SG +DSK_PRM. . . . . . . . . . . . . L BYTE 0875 DATA_SG +DSK_SV1. . . . . . . . . . . . . L WORD 0871 DATA_SG +DSK_SV2. . . . . . . . . . . . . L WORD 0873 DATA_SG +ENDBUF . . . . . . . . . . . . . L WORD 02C8 DATA_SG +ENDLOD . . . . . . . . . . . . . L WORD 02E1 DATA_SG +EOICHR . . . . . . . . . . . . . Number 000F +EOLCHR . . . . . . . . . . . . . Number 000A +ERR2 . . . . . . . . . . . . . . L BYTE 0962 DATA_SG +ESIBKS . . . . . . . . . . . . . L WORD 02ED DATA_SG +EXTOP. . . . . . . . . . . . . . L WORD 08D0 DATA_SG +FATHDR . . . . . . . . . . . . . L BYTE 09DF DATA_SG +FEEP . . . . . . . . . . . . . . N PROC 0018 CODE_SG Length =0007 +FINDPG . . . . . . . . . . . . . N PROC 1359 CODE_SG Length =004D +FINISH . . . . . . . . . . . . . N PROC 1A47 CODE_SG Length =0018 +FNP1$. . . . . . . . . . . . . . L NEAR 1363 CODE_SG +FNP2$. . . . . . . . . . . . . . L NEAR 136F CODE_SG +FNP3$. . . . . . . . . . . . . . L NEAR 1376 CODE_SG +FNP4$. . . . . . . . . . . . . . L NEAR 1394 CODE_SG +FRML . . . . . . . . . . . . . . L NEAR 1658 CODE_SG +FRMLL. . . . . . . . . . . . . . L NEAR 1660 CODE_SG +FTL2 . . . . . . . . . . . . . . L BYTE 0983 DATA_SG +FTL4 . . . . . . . . . . . . . . L BYTE 0994 DATA_SG +FTL5 . . . . . . . . . . . . . . L BYTE 09AA DATA_SG +FTL6 . . . . . . . . . . . . . . L BYTE 09BC DATA_SG +FTL7 . . . . . . . . . . . . . . L BYTE 09CA DATA_SG +FUBAR$ . . . . . . . . . . . . . L NEAR 1129 CODE_SG +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-4 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +FUCK . . . . . . . . . . . . . . L BYTE 0207 DATA_SG +GAMETRK. . . . . . . . . . . . . Number 0006 +GETARG . . . . . . . . . . . . . N PROC 0B8D CODE_SG Length =0013 +GETBLK . . . . . . . . . . . . . N PROC 147B CODE_SG Length =0009 +GETBYT . . . . . . . . . . . . . N PROC 0B26 CODE_SG Length =002D +GETLIN . . . . . . . . . . . . . N PROC 0696 CODE_SG Length =00A2 +GETNUM . . . . . . . . . . . . . N PROC 1455 CODE_SG Length =0026 +GETPAG . . . . . . . . . . . . . N PROC 12E1 CODE_SG Length =0078 +GETVAR . . . . . . . . . . . . . N PROC 0BA0 CODE_SG Length =0030 +GETWRD . . . . . . . . . . . . . N PROC 0B53 CODE_SG Length =000D +GLOTAB . . . . . . . . . . . . . L WORD 02E7 DATA_SG +GTB1$. . . . . . . . . . . . . . L NEAR 150B CODE_SG +GTB2$. . . . . . . . . . . . . . L NEAR 1515 CODE_SG +GTBCNT . . . . . . . . . . . . . L WORD 02A9 DATA_SG +GTBCOR . . . . . . . . . . . . . L WORD 02AD DATA_SG +GTBKI$ . . . . . . . . . . . . . L NEAR 14AD CODE_SG +GTBLKS . . . . . . . . . . . . . N PROC 149E CODE_SG Length =0089 +GTBSTT . . . . . . . . . . . . . L WORD 02AB DATA_SG +GTBX0$ . . . . . . . . . . . . . L NEAR 14AF CODE_SG +GTBX1$ . . . . . . . . . . . . . L NEAR 14E1 CODE_SG +GTBX2$ . . . . . . . . . . . . . L NEAR 1507 CODE_SG +GTBX3$ . . . . . . . . . . . . . L NEAR 1508 CODE_SG +GTBXN$ . . . . . . . . . . . . . L NEAR 14CC CODE_SG +GTL0$. . . . . . . . . . . . . . L NEAR 06BC CODE_SG +GTL1$. . . . . . . . . . . . . . L NEAR 0704 CODE_SG +GTL2$. . . . . . . . . . . . . . L NEAR 06D4 CODE_SG +GTL3$. . . . . . . . . . . . . . L NEAR 06ED CODE_SG +GTL4$. . . . . . . . . . . . . . L NEAR 0725 CODE_SG +GTL5$. . . . . . . . . . . . . . L NEAR 0723 CODE_SG +GTLD$. . . . . . . . . . . . . . L NEAR 072F CODE_SG +GTLF$. . . . . . . . . . . . . . L NEAR 06C8 CODE_SG +GTLL$. . . . . . . . . . . . . . L NEAR 06A8 CODE_SG +GTLL1$ . . . . . . . . . . . . . L NEAR 06D0 CODE_SG +GTLX$. . . . . . . . . . . . . . L NEAR 06B3 CODE_SG +GTP1$. . . . . . . . . . . . . . L NEAR 12EB CODE_SG +GTP2$. . . . . . . . . . . . . . L NEAR 12FD CODE_SG +GTP2A$ . . . . . . . . . . . . . L NEAR 1316 CODE_SG +GTP3$. . . . . . . . . . . . . . L NEAR 132A CODE_SG +GTP4$. . . . . . . . . . . . . . L NEAR 1351 CODE_SG +GTV1$. . . . . . . . . . . . . . L NEAR 0BA9 CODE_SG +GTV2$. . . . . . . . . . . . . . L NEAR 0BBB CODE_SG +GTV3$. . . . . . . . . . . . . . L NEAR 0BBD CODE_SG +GTY1$. . . . . . . . . . . . . . L NEAR 0B3A CODE_SG +GTY2$. . . . . . . . . . . . . . L NEAR 0B43 CODE_SG +GTY3$. . . . . . . . . . . . . . L NEAR 0B52 CODE_SG +IDTBL. . . . . . . . . . . . . . L BYTE 0880 DATA_SG +INIFLG . . . . . . . . . . . . . L BYTE 066C DATA_SG +INIMEM . . . . . . . . . . . . . Number 0002 +INIRND . . . . . . . . . . . . . Number 0004 +INIWID . . . . . . . . . . . . . Number 0001 +INTMSG . . . . . . . . . . . . . L BYTE 01E9 DATA_SG +INTVER . . . . . . . . . . . . . L BYTE 0204 DATA_SG +IRBRKS . . . . . . . . . . . . . L BYTE 02CC DATA_SG +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-5 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +JPF. . . . . . . . . . . . . . . L NEAR 0369 CODE_SG +JPF1 . . . . . . . . . . . . . . L NEAR 04C1 CODE_SG +JPT. . . . . . . . . . . . . . . L NEAR 036C CODE_SG +JPT1 . . . . . . . . . . . . . . L NEAR 04BE CODE_SG +LDOUTB . . . . . . . . . . . . . Number 0050 +LFTMAR . . . . . . . . . . . . . L BYTE 02DA DATA_SG +LINMAX . . . . . . . . . . . . . L WORD 095C DATA_SG +LINMXX . . . . . . . . . . . . . Number 0017 +LMOUTB . . . . . . . . . . . . . Number 0050 +LPAGE. . . . . . . . . . . . . . L WORD 0684 DATA_SG +LPAGES . . . . . . . . . . . . . Number 0080 +LPLOC. . . . . . . . . . . . . . L WORD 0686 DATA_SG +LPTAB. . . . . . . . . . . . . . L WORD 0688 DATA_SG +LSTACK . . . . . . . . . . . . . Number 0100 +LXBYTS . . . . . . . . . . . . . Number 0750 +MEMTOP . . . . . . . . . . . . . L WORD 02DB DATA_SG +MORE . . . . . . . . . . . . . . L BYTE 0950 DATA_SG +MORLIN . . . . . . . . . . . . . L WORD 095A DATA_SG +NDISKS . . . . . . . . . . . . . L BYTE 0206 DATA_SG +NEWLIN . . . . . . . . . . . . . N PROC 0F02 CODE_SG Length =0018 +NEWZPC . . . . . . . . . . . . . N PROC 1245 CODE_SG Length =009C +NRMATR . . . . . . . . . . . . . L BYTE 0000 DATA_SG +NWZ1$. . . . . . . . . . . . . . L NEAR 127F CODE_SG +NWZ2$. . . . . . . . . . . . . . L NEAR 12A8 CODE_SG +NWZ3$. . . . . . . . . . . . . . L NEAR 12CD CODE_SG +NWZ4$. . . . . . . . . . . . . . L NEAR 12D7 CODE_SG +NWZ5$. . . . . . . . . . . . . . L NEAR 12DB CODE_SG +NXB1$. . . . . . . . . . . . . . L NEAR 0B7B CODE_SG +NXI0A$ . . . . . . . . . . . . . L NEAR 1143 CODE_SG +NXI0B$ . . . . . . . . . . . . . L NEAR 114B CODE_SG +NXI0C$ . . . . . . . . . . . . . L NEAR 115F CODE_SG +NXI1$. . . . . . . . . . . . . . L NEAR 1165 CODE_SG +NXI10$ . . . . . . . . . . . . . L NEAR 11D3 CODE_SG +NXI11$ . . . . . . . . . . . . . L NEAR 11E1 CODE_SG +NXI12$ . . . . . . . . . . . . . L NEAR 11FA CODE_SG +NXI13$ . . . . . . . . . . . . . L NEAR 121D CODE_SG +NXI14$ . . . . . . . . . . . . . L NEAR 122E CODE_SG +NXI15$ . . . . . . . . . . . . . L NEAR 1240 CODE_SG +NXI2$. . . . . . . . . . . . . . L NEAR 1174 CODE_SG +NXI3$. . . . . . . . . . . . . . L NEAR 1186 CODE_SG +NXI4$. . . . . . . . . . . . . . L NEAR 118B CODE_SG +NXI5$. . . . . . . . . . . . . . L NEAR 1190 CODE_SG +NXI6$. . . . . . . . . . . . . . L NEAR 11AA CODE_SG +NXI7$. . . . . . . . . . . . . . L NEAR 11AE CODE_SG +NXI8$. . . . . . . . . . . . . . L NEAR 11B2 CODE_SG +NXI8A$ . . . . . . . . . . . . . L NEAR 11B5 CODE_SG +NXI9$. . . . . . . . . . . . . . L NEAR 11B8 CODE_SG +NXTBYT . . . . . . . . . . . . . N PROC 0B60 CODE_SG Length =0020 +NXTINS . . . . . . . . . . . . . N PROC 1131 CODE_SG Length =0114 +NXTPRP . . . . . . . . . . . . . N PROC 0C8C CODE_SG Length =0015 +NXTWRD . . . . . . . . . . . . . N PROC 0B80 CODE_SG Length =000D +OBJLOC . . . . . . . . . . . . . N PROC 0C76 CODE_SG Length =0016 +OBJTAB . . . . . . . . . . . . . L WORD 02E5 DATA_SG +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-6 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +OCL1$. . . . . . . . . . . . . . L NEAR 0A85 CODE_SG +OCL2$. . . . . . . . . . . . . . L NEAR 0ABC CODE_SG +OCL3$. . . . . . . . . . . . . . L NEAR 0AD2 CODE_SG +OCL4$. . . . . . . . . . . . . . L NEAR 0AD9 CODE_SG +OFC1$. . . . . . . . . . . . . . L NEAR 048A CODE_SG +OFS1$. . . . . . . . . . . . . . L NEAR 0467 CODE_SG +OGP1$. . . . . . . . . . . . . . L NEAR 04FE CODE_SG +OGP2$. . . . . . . . . . . . . . L NEAR 0501 CODE_SG +OGP3$. . . . . . . . . . . . . . L NEAR 0520 CODE_SG +OGP4$. . . . . . . . . . . . . . L NEAR 0525 CODE_SG +OGP5$. . . . . . . . . . . . . . L NEAR 0529 CODE_SG +OGT1$. . . . . . . . . . . . . . L NEAR 0615 CODE_SG +OGT2$. . . . . . . . . . . . . . L NEAR 0618 CODE_SG +OGT3$. . . . . . . . . . . . . . L NEAR 0628 CODE_SG +OGT4$. . . . . . . . . . . . . . L NEAR 062B CODE_SG +OLDCUR . . . . . . . . . . . . . L WORD 0021 DATA_SG +OMV1$. . . . . . . . . . . . . . L NEAR 03E8 CODE_SG +ONEOP. . . . . . . . . . . . . . L WORD 08B0 DATA_SG +ONX1$. . . . . . . . . . . . . . L NEAR 05A4 CODE_SG +ONX2$. . . . . . . . . . . . . . L NEAR 05A7 CODE_SG +ONX3$. . . . . . . . . . . . . . L NEAR 05C4 CODE_SG +ONX4$. . . . . . . . . . . . . . L NEAR 05C7 CODE_SG +OPADD. . . . . . . . . . . . . . N PROC 030A CODE_SG Length =0005 +OPBAND . . . . . . . . . . . . . N PROC 0387 CODE_SG Length =0005 +OPBCOM . . . . . . . . . . . . . N PROC 0382 CODE_SG Length =0005 +OPBOR. . . . . . . . . . . . . . N PROC 037D CODE_SG Length =0005 +OPBTST . . . . . . . . . . . . . N PROC 0375 CODE_SG Length =0008 +OPCALL . . . . . . . . . . . . . N PROC 0A75 CODE_SG Length =0065 +OPCRLF . . . . . . . . . . . . . N PROC 0A72 CODE_SG Length =0003 +OPDEC. . . . . . . . . . . . . . N PROC 0664 CODE_SG Length =0008 +OPDIV. . . . . . . . . . . . . . N PROC 0319 CODE_SG Length =0006 +OPFCLE . . . . . . . . . . . . . N PROC 047D CODE_SG Length =0023 +OPFSET . . . . . . . . . . . . . N PROC 045A CODE_SG Length =0023 +OPFSTA . . . . . . . . . . . . . N PROC 0B1F CODE_SG Length =0006 +OPGET. . . . . . . . . . . . . . N PROC 05CF CODE_SG Length =000F +OPGETB . . . . . . . . . . . . . N PROC 05DE CODE_SG Length =000D +OPGETP . . . . . . . . . . . . . N PROC 04E4 CODE_SG Length =004D +OPGTPT . . . . . . . . . . . . . N PROC 05FB CODE_SG Length =0033 +OPH0$. . . . . . . . . . . . . . L NEAR 09FB CODE_SG +OPH00$ . . . . . . . . . . . . . L NEAR 0A01 CODE_SG +OPH1$. . . . . . . . . . . . . . L NEAR 0A07 CODE_SG +OPH2$. . . . . . . . . . . . . . L NEAR 0A12 CODE_SG +OPINC. . . . . . . . . . . . . . N PROC 0657 CODE_SG Length =000D +OPINC1 . . . . . . . . . . . . . L NEAR 065D CODE_SG +OPJUMP . . . . . . . . . . . . . N PROC 0B0C CODE_SG Length =000C +OPLOC. . . . . . . . . . . . . . N PROC 04A0 CODE_SG Length =000C +OPM1$. . . . . . . . . . . . . . L NEAR 0A25 CODE_SG +OPM2$. . . . . . . . . . . . . . L NEAR 0A38 CODE_SG +OPMOD. . . . . . . . . . . . . . N PROC 031F CODE_SG Length =0008 +OPMOVE . . . . . . . . . . . . . N PROC 03BE CODE_SG Length =002B +OPMUL. . . . . . . . . . . . . . N PROC 0314 CODE_SG Length =0005 +OPN1$. . . . . . . . . . . . . . L NEAR 09B1 CODE_SG +OPN2$. . . . . . . . . . . . . . L NEAR 09BB CODE_SG +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-7 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +OPN3$. . . . . . . . . . . . . . L NEAR 09C0 CODE_SG +OPN4$. . . . . . . . . . . . . . L NEAR 09CC CODE_SG +OPN5$. . . . . . . . . . . . . . L NEAR 09D6 CODE_SG +OPN6$. . . . . . . . . . . . . . L NEAR 09D7 CODE_SG +OPNEXT . . . . . . . . . . . . . N PROC 0585 CODE_SG Length =004A +OPNOOP . . . . . . . . . . . . . N PROC 0B25 CODE_SG Length =0001 +OPP1$. . . . . . . . . . . . . . L NEAR 054C CODE_SG +OPP2$. . . . . . . . . . . . . . L NEAR 054F CODE_SG +OPP3$. . . . . . . . . . . . . . L NEAR 056C CODE_SG +OPP4$. . . . . . . . . . . . . . L NEAR 057F CODE_SG +OPPOP. . . . . . . . . . . . . . N PROC 064F CODE_SG Length =0008 +OPPRIN . . . . . . . . . . . . . N PROC 09E1 CODE_SG Length =0006 +OPPRNB . . . . . . . . . . . . . N PROC 09E7 CODE_SG Length =0006 +OPPRNC . . . . . . . . . . . . . N PROC 09A1 CODE_SG Length =0003 +OPPRND . . . . . . . . . . . . . N PROC 0A40 CODE_SG Length =0015 +OPPRNH . . . . . . . . . . . . . N PROC 09ED CODE_SG Length =002D +OPPRNI . . . . . . . . . . . . . N PROC 0A55 CODE_SG Length =0014 +OPPRNM . . . . . . . . . . . . . N PROC 0A1A CODE_SG Length =0026 +OPPRNN . . . . . . . . . . . . . N PROC 09A4 CODE_SG Length =003D +OPPRNR . . . . . . . . . . . . . N PROC 0A69 CODE_SG Length =0009 +OPPTSI . . . . . . . . . . . . . N PROC 062E CODE_SG Length =0012 +OPPUSH . . . . . . . . . . . . . N PROC 0649 CODE_SG Length =0006 +OPPUT. . . . . . . . . . . . . . N PROC 05EB CODE_SG Length =000A +OPPUTB . . . . . . . . . . . . . N PROC 05F5 CODE_SG Length =0006 +OPPUTP . . . . . . . . . . . . . N PROC 0531 CODE_SG Length =0054 +OPQDLE . . . . . . . . . . . . . N PROC 0689 CODE_SG Length =000D +OPQEQU . . . . . . . . . . . . . N PROC 038C CODE_SG Length =0027 +OPQFIR . . . . . . . . . . . . . N PROC 04AC CODE_SG Length =0018 +OPQFSE . . . . . . . . . . . . . N PROC 0435 CODE_SG Length =0025 +OPQGRT . . . . . . . . . . . . . N PROC 036F CODE_SG Length =0006 +OPQIG0 . . . . . . . . . . . . . L NEAR 0677 CODE_SG +OPQIG1 . . . . . . . . . . . . . L NEAR 0678 CODE_SG +OPQIGR . . . . . . . . . . . . . N PROC 066C CODE_SG Length =001D +OPQIN. . . . . . . . . . . . . . N PROC 04D8 CODE_SG Length =000C +OPQLES . . . . . . . . . . . . . N PROC 0365 CODE_SG Length =000A +OPQNEX . . . . . . . . . . . . . N PROC 04C4 CODE_SG Length =0014 +OPQUIT . . . . . . . . . . . . . N PROC 01E9 CODE_SG Length =0003 +OPQZER . . . . . . . . . . . . . N PROC 03B3 CODE_SG Length =000B +OPRAND . . . . . . . . . . . . . N PROC 0327 CODE_SG Length =003E +OPREAD . . . . . . . . . . . . . N PROC 081E CODE_SG Length =0183 +OPREMO . . . . . . . . . . . . . N PROC 03E9 CODE_SG Length =004C +OPREST . . . . . . . . . . . . . N PROC 007B CODE_SG Length =0008 +OPRETU . . . . . . . . . . . . . N PROC 0ADA CODE_SG Length =0029 +OPRFAL . . . . . . . . . . . . . N PROC 0B08 CODE_SG Length =0004 +OPRN1$ . . . . . . . . . . . . . L NEAR 0358 CODE_SG +OPRSTA . . . . . . . . . . . . . N PROC 0B18 CODE_SG Length =0007 +OPRSTT . . . . . . . . . . . . . N PROC 01D5 CODE_SG Length =0014 +OPRTRU . . . . . . . . . . . . . N PROC 0B03 CODE_SG Length =0005 +OPSAVE . . . . . . . . . . . . . N PROC 0083 CODE_SG Length =0152 +OPSCR1 . . . . . . . . . . . . . L NEAR 0211 CODE_SG +OPSCR2 . . . . . . . . . . . . . L NEAR 023C CODE_SG +OPSCR3 . . . . . . . . . . . . . L NEAR 0242 CODE_SG +OPSCRN . . . . . . . . . . . . . N PROC 01EC CODE_SG Length =0057 +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-8 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +OPSET. . . . . . . . . . . . . . N PROC 0646 CODE_SG Length =0003 +OPSPLT . . . . . . . . . . . . . N PROC 0243 CODE_SG Length =0061 +OPSPLU . . . . . . . . . . . . . L NEAR 0292 CODE_SG +OPSUB. . . . . . . . . . . . . . N PROC 030F CODE_SG Length =0005 +OPUSL. . . . . . . . . . . . . . N PROC 02A4 CODE_SG Length =0066 +OPVALU . . . . . . . . . . . . . N PROC 0640 CODE_SG Length =0006 +OPVERI . . . . . . . . . . . . . N PROC 001F CODE_SG Length =005C +OPVR1. . . . . . . . . . . . . . L NEAR 004C CODE_SG +OPVR2. . . . . . . . . . . . . . L NEAR 0078 CODE_SG +OPVX . . . . . . . . . . . . . . L NEAR 005D CODE_SG +OQE1$. . . . . . . . . . . . . . L NEAR 03AD CODE_SG +OQE2$. . . . . . . . . . . . . . L NEAR 03B0 CODE_SG +OQF1$. . . . . . . . . . . . . . L NEAR 0442 CODE_SG +OQF2$. . . . . . . . . . . . . . L NEAR 0457 CODE_SG +OQI1$. . . . . . . . . . . . . . L NEAR 0686 CODE_SG +OQZ1$. . . . . . . . . . . . . . L NEAR 03BB CODE_SG +ORD1$. . . . . . . . . . . . . . L NEAR 082F CODE_SG +ORD10$ . . . . . . . . . . . . . L NEAR 0875 CODE_SG +ORD11$ . . . . . . . . . . . . . L NEAR 0889 CODE_SG +ORD12$ . . . . . . . . . . . . . L NEAR 08A3 CODE_SG +ORD13$ . . . . . . . . . . . . . L NEAR 08B2 CODE_SG +ORD14$ . . . . . . . . . . . . . L NEAR 08BC CODE_SG +ORD15$ . . . . . . . . . . . . . L NEAR 08BD CODE_SG +ORD16$ . . . . . . . . . . . . . L NEAR 08F7 CODE_SG +ORD17$ . . . . . . . . . . . . . L NEAR 0935 CODE_SG +ORD18$ . . . . . . . . . . . . . L NEAR 094B CODE_SG +ORD19$ . . . . . . . . . . . . . L NEAR 096B CODE_SG +ORD1A$ . . . . . . . . . . . . . L NEAR 0885 CODE_SG +ORD20$ . . . . . . . . . . . . . L NEAR 0976 CODE_SG +ORD21$ . . . . . . . . . . . . . L NEAR 0978 CODE_SG +ORD22$ . . . . . . . . . . . . . L NEAR 0980 CODE_SG +ORD23$ . . . . . . . . . . . . . L NEAR 098F CODE_SG +ORD8$. . . . . . . . . . . . . . L NEAR 0861 CODE_SG +ORD9$. . . . . . . . . . . . . . L NEAR 0866 CODE_SG +ORDNS$ . . . . . . . . . . . . . L NEAR 084A CODE_SG +ORM1$. . . . . . . . . . . . . . L NEAR 0413 CODE_SG +ORM2$. . . . . . . . . . . . . . L NEAR 042A CODE_SG +ORM3$. . . . . . . . . . . . . . L NEAR 0434 CODE_SG +OSAB1$ . . . . . . . . . . . . . L NEAR 00EC CODE_SG +OSAB2$ . . . . . . . . . . . . . L NEAR 00F2 CODE_SG +OSV0$. . . . . . . . . . . . . . L NEAR 0088 CODE_SG +OSV0A$ . . . . . . . . . . . . . L NEAR 00D8 CODE_SG +OSV1$. . . . . . . . . . . . . . L NEAR 00E2 CODE_SG +OSV1A$ . . . . . . . . . . . . . L NEAR 00FE CODE_SG +OSV1B$ . . . . . . . . . . . . . L NEAR 0103 CODE_SG +OSV2A$ . . . . . . . . . . . . . L NEAR 009B CODE_SG +OSV3$. . . . . . . . . . . . . . L NEAR 00A5 CODE_SG +OSV3A$ . . . . . . . . . . . . . L NEAR 00BB CODE_SG +OSV3B$ . . . . . . . . . . . . . L NEAR 00C0 CODE_SG +OSV3C$ . . . . . . . . . . . . . L NEAR 01BD CODE_SG +OSV3X$ . . . . . . . . . . . . . L NEAR 00B1 CODE_SG +OSV3Z$ . . . . . . . . . . . . . L NEAR 0128 CODE_SG +OSV4$. . . . . . . . . . . . . . L NEAR 01CF CODE_SG +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-9 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +OSVT0$ . . . . . . . . . . . . . L NEAR 0187 CODE_SG +OUTBUF . . . . . . . . . . . . . L BYTE 04F5 DATA_SG Length =0051 +PADCHR . . . . . . . . . . . . . Number 0005 +PAGES. . . . . . . . . . . . . . L WORD 0667 DATA_SG +PAGTAB . . . . . . . . . . . . . L BYTE 0566 DATA_SG Length =0040 +PCHKSM . . . . . . . . . . . . . Number 001C +PENDLD . . . . . . . . . . . . . Number 0004 +PFALSE . . . . . . . . . . . . . N PROC 0C12 CODE_SG Length =0005 +PFLAGS . . . . . . . . . . . . . Number 0010 +PGLOTB . . . . . . . . . . . . . Number 000C +PLENTH . . . . . . . . . . . . . Number 001A +PMFLAG . . . . . . . . . . . . . L BYTE 004C DATA_SG +POBJTB . . . . . . . . . . . . . Number 000A +PPR1$. . . . . . . . . . . . . . L NEAR 0C26 CODE_SG +PPR2$. . . . . . . . . . . . . . L NEAR 0C31 CODE_SG +PPR3$. . . . . . . . . . . . . . L NEAR 0C43 CODE_SG +PPR4$. . . . . . . . . . . . . . L NEAR 0C4E CODE_SG +PPR5$. . . . . . . . . . . . . . L NEAR 0C54 CODE_SG +PPR6$. . . . . . . . . . . . . . L NEAR 0C5C CODE_SG +PPRED. . . . . . . . . . . . . . N PROC 0C1D CODE_SG Length =0040 +PPURBT . . . . . . . . . . . . . Number 000E +PRNA$. . . . . . . . . . . . . . L NEAR 0764 CODE_SG +PRNEX$ . . . . . . . . . . . . . L NEAR 0765 CODE_SG +PRNL$. . . . . . . . . . . . . . L NEAR 074A CODE_SG +PRNR$. . . . . . . . . . . . . . L NEAR 0770 CODE_SG +PRNRDY . . . . . . . . . . . . . L BYTE 0024 DATA_SG +PRSPC. . . . . . . . . . . . . . N PROC 10B3 CODE_SG Length =000F +PRTCRL . . . . . . . . . . . . . N PROC 0813 CODE_SG Length =000B +PRTLOS . . . . . . . . . . . . . N PROC 0738 CODE_SG Length =003B +PRTO1$ . . . . . . . . . . . . . L NEAR 079A CODE_SG +PRTOUT . . . . . . . . . . . . . N PROC 0773 CODE_SG Length =0029 +PRTRT$ . . . . . . . . . . . . . L NEAR 0773 CODE_SG +PSERNM . . . . . . . . . . . . . Number 0012 +PSTART . . . . . . . . . . . . . Number 0006 +PTBLKS . . . . . . . . . . . . . N PROC 148C CODE_SG Length =0012 +PTC0$. . . . . . . . . . . . . . L NEAR 0E8B CODE_SG +PTC1$. . . . . . . . . . . . . . L NEAR 0E9F CODE_SG +PTC2$. . . . . . . . . . . . . . L NEAR 0EA9 CODE_SG +PTC3$. . . . . . . . . . . . . . L NEAR 0EC5 CODE_SG +PTC4$. . . . . . . . . . . . . . L NEAR 0ED8 CODE_SG +PTC5$. . . . . . . . . . . . . . L NEAR 0EE8 CODE_SG +PTC6$. . . . . . . . . . . . . . L NEAR 0EEC CODE_SG +PTC7$. . . . . . . . . . . . . . L NEAR 0EF4 CODE_SG +PTC8$. . . . . . . . . . . . . . L NEAR 0F00 CODE_SG +PTRUE. . . . . . . . . . . . . . N PROC 0C17 CODE_SG Length =0006 +PTS1$. . . . . . . . . . . . . . L NEAR 0CAA CODE_SG +PTS10$ . . . . . . . . . . . . . L NEAR 0D3F CODE_SG +PTS11$ . . . . . . . . . . . . . L NEAR 0D58 CODE_SG +PTS12$ . . . . . . . . . . . . . L NEAR 0D65 CODE_SG +PTS13$ . . . . . . . . . . . . . L NEAR 0D6B CODE_SG +PTS14$ . . . . . . . . . . . . . L NEAR 0D73 CODE_SG +PTS15$ . . . . . . . . . . . . . L NEAR 0D76 CODE_SG +PTS16$ . . . . . . . . . . . . . L NEAR 0D78 CODE_SG +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-10 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +PTS1A$ . . . . . . . . . . . . . L NEAR 0D85 CODE_SG +PTS2$. . . . . . . . . . . . . . L NEAR 0CB5 CODE_SG +PTS3$. . . . . . . . . . . . . . L NEAR 0CC3 CODE_SG +PTS3A$ . . . . . . . . . . . . . L NEAR 0D70 CODE_SG +PTS4$. . . . . . . . . . . . . . L NEAR 0CE5 CODE_SG +PTS5$. . . . . . . . . . . . . . L NEAR 0CF3 CODE_SG +PTS6$. . . . . . . . . . . . . . L NEAR 0D06 CODE_SG +PTS7$. . . . . . . . . . . . . . L NEAR 0D1B CODE_SG +PTS8$. . . . . . . . . . . . . . L NEAR 0D21 CODE_SG +PTS9$. . . . . . . . . . . . . . L NEAR 0D34 CODE_SG +PTV1$. . . . . . . . . . . . . . L NEAR 0BD9 CODE_SG +PTV2$. . . . . . . . . . . . . . L NEAR 0BED CODE_SG +PURBOT . . . . . . . . . . . . . L WORD 02EB DATA_SG +PUTCHR . . . . . . . . . . . . . N PROC 0E61 CODE_SG Length =00A1 +PUTSTR . . . . . . . . . . . . . N PROC 0CA1 CODE_SG Length =00EA +PUTVAL . . . . . . . . . . . . . N PROC 0C02 CODE_SG Length =0010 +PUTVAR . . . . . . . . . . . . . N PROC 0BD0 CODE_SG Length =002D +PVERS1 . . . . . . . . . . . . . Number 0000 +PVERS2 . . . . . . . . . . . . . Number 0001 +PVOCTB . . . . . . . . . . . . . Number 0008 +PWRDTB . . . . . . . . . . . . . Number 0018 +PZRKID . . . . . . . . . . . . . Number 0002 +RBRKS. . . . . . . . . . . . . . L BYTE 0546 DATA_SG Length =0020 +RDBOS. . . . . . . . . . . . . . L WORD 02BD DATA_SG +RDEOS. . . . . . . . . . . . . . L WORD 02BF DATA_SG +RDNWDS . . . . . . . . . . . . . L BYTE 02C3 DATA_SG +RDRET. . . . . . . . . . . . . . L WORD 02C1 DATA_SG +RDWSTR . . . . . . . . . . . . . L WORD 02B5 DATA_SG Length =0004 +REBOO1 . . . . . . . . . . . . . L BYTE 01D0 DATA_SG +REBOOT . . . . . . . . . . . . . L BYTE 01B9 DATA_SG +RESTRT . . . . . . . . . . . . . N PROC 10C2 CODE_SG Length =006F +RSEED1 . . . . . . . . . . . . . L WORD 02AF DATA_SG +RSEED2 . . . . . . . . . . . . . L WORD 02B1 DATA_SG +RTEMP. . . . . . . . . . . . . . L WORD 02B3 DATA_SG +RTIME1 . . . . . . . . . . . . . L BYTE 0681 DATA_SG +RTIME2 . . . . . . . . . . . . . L WORD 0682 DATA_SG +RWIDTH . . . . . . . . . . . . . L WORD 02D6 DATA_SG +SCR1$. . . . . . . . . . . . . . L NEAR 07DF CODE_SG +SCR1L$ . . . . . . . . . . . . . L NEAR 07E9 CODE_SG +SCR2L$ . . . . . . . . . . . . . L NEAR 07F7 CODE_SG +SCRCHK . . . . . . . . . . . . . N PROC 079C CODE_SG Length =0077 +SCREX$ . . . . . . . . . . . . . L NEAR 07DB CODE_SG +SCRFLG . . . . . . . . . . . . . L BYTE 0023 DATA_SG +SCRN0. . . . . . . . . . . . . . L BYTE 02D8 DATA_SG +SCRNN$ . . . . . . . . . . . . . L NEAR 080C CODE_SG +SCRR1$ . . . . . . . . . . . . . L NEAR 07B0 CODE_SG +SCRR2$ . . . . . . . . . . . . . L NEAR 07C1 CODE_SG +SECCNT . . . . . . . . . . . . . L BYTE 068A DATA_SG +SIN1A$ . . . . . . . . . . . . . L NEAR 141D CODE_SG +SINC$. . . . . . . . . . . . . . L NEAR 13DA CODE_SG +SINI0$ . . . . . . . . . . . . . L NEAR 1401 CODE_SG +SINI1$ . . . . . . . . . . . . . L NEAR 1411 CODE_SG +SINI2$ . . . . . . . . . . . . . L NEAR 1437 CODE_SG +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-11 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +SINIF$ . . . . . . . . . . . . . L NEAR 13FD CODE_SG +SINIX$ . . . . . . . . . . . . . L NEAR 13EC CODE_SG +SLS40. . . . . . . . . . . . . . L BYTE 0061 DATA_SG Length =0019 +SLS40T . . . . . . . . . . . . . L WORD 008B DATA_SG +SLS80. . . . . . . . . . . . . . L BYTE 00E5 DATA_SG Length =0033 +SLS80T . . . . . . . . . . . . . L WORD 0137 DATA_SG +SLSTAB . . . . . . . . . . . . . L WORD 0051 DATA_SG +SLSTR. . . . . . . . . . . . . . L WORD 004D DATA_SG +SLT40. . . . . . . . . . . . . . L BYTE 00A3 DATA_SG Length =0019 +SLT40T . . . . . . . . . . . . . L WORD 00CD DATA_SG +SLT80. . . . . . . . . . . . . . L BYTE 014F DATA_SG Length =003C +SLT80T . . . . . . . . . . . . . L WORD 01A1 DATA_SG +SLTAB. . . . . . . . . . . . . . L WORD 004F DATA_SG +SLTTAB . . . . . . . . . . . . . L WORD 0059 DATA_SG +SRBLKS . . . . . . . . . . . . . N PROC 1484 CODE_SG Length =0008 +SRDRV. . . . . . . . . . . . . . L BYTE 023D DATA_SG +SRPOS. . . . . . . . . . . . . . L BYTE 025E DATA_SG +SRTXT0 . . . . . . . . . . . . . L BYTE 0208 DATA_SG +SRTXT1 . . . . . . . . . . . . . L BYTE 0220 DATA_SG +SRTXT2 . . . . . . . . . . . . . L BYTE 0241 DATA_SG +SRTXT3 . . . . . . . . . . . . . L BYTE 0262 DATA_SG +SRTXT4 . . . . . . . . . . . . . L BYTE 0284 DATA_SG +START. . . . . . . . . . . . . . F PROC 0000 CODE_SG Length =0018 +START1 . . . . . . . . . . . . . L NEAR 10C5 CODE_SG +STATUS . . . . . . . . . . . . . L WORD 02CA DATA_SG +STKBOT . . . . . . . . . . . . . L WORD 0200 STK_SG Length =0100 +STK_TOP. . . . . . . . . . . . . L WORD 0200 STK_SG +STR10$ . . . . . . . . . . . . . L NEAR 0FAF CODE_SG +STR12$ . . . . . . . . . . . . . L NEAR 0FCF CODE_SG +STR13$ . . . . . . . . . . . . . L NEAR 1019 CODE_SG +STR14$ . . . . . . . . . . . . . L NEAR 1030 CODE_SG +STR15$ . . . . . . . . . . . . . L NEAR 1040 CODE_SG +STR16$ . . . . . . . . . . . . . L NEAR 1094 CODE_SG +STR17$ . . . . . . . . . . . . . L NEAR 10B0 CODE_SG +STR5$. . . . . . . . . . . . . . L NEAR 0F70 CODE_SG +STR8$. . . . . . . . . . . . . . L NEAR 0F91 CODE_SG +STR9$. . . . . . . . . . . . . . L NEAR 0FA3 CODE_SG +SYSINI . . . . . . . . . . . . . N PROC 13A6 CODE_SG Length =0092 +TIME . . . . . . . . . . . . . . L DWORD 095E DATA_SG +TIMEMD . . . . . . . . . . . . . L WORD 02DD DATA_SG +TRKCNT . . . . . . . . . . . . . L BYTE 068B DATA_SG +TS0$ . . . . . . . . . . . . . . L NEAR 0F27 CODE_SG +TS1$ . . . . . . . . . . . . . . L NEAR 0F46 CODE_SG +TS2$ . . . . . . . . . . . . . . L NEAR 0F53 CODE_SG +TSETUP . . . . . . . . . . . . . N PROC 0F1A CODE_SG Length =0050 +TWIDTH . . . . . . . . . . . . . L WORD 02D4 DATA_SG +TYPATR . . . . . . . . . . . . . L BYTE 0002 DATA_SG +USL1$. . . . . . . . . . . . . . L NEAR 02F4 CODE_SG +USLATR . . . . . . . . . . . . . L BYTE 0001 DATA_SG +USLLP$ . . . . . . . . . . . . . L NEAR 02BD CODE_SG +USLMOD . . . . . . . . . . . . . L BYTE 004B DATA_SG +USLN$. . . . . . . . . . . . . . L NEAR 02F0 CODE_SG +VOCBEG . . . . . . . . . . . . . L WORD 02F3 DATA_SG +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-12 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +VOCTAB . . . . . . . . . . . . . L WORD 02E3 DATA_SG +VWLEN. . . . . . . . . . . . . . L WORD 02EF DATA_SG +VWORDS . . . . . . . . . . . . . L WORD 02F1 DATA_SG +WLP. . . . . . . . . . . . . . . L NEAR 1699 CODE_SG +WPCHK. . . . . . . . . . . . . . N PROC 1527 CODE_SG Length =003F +WPCHK1 . . . . . . . . . . . . . L NEAR 155F CODE_SG +WRDOFF . . . . . . . . . . . . . L WORD 02C4 DATA_SG +WRDTAB . . . . . . . . . . . . . L WORD 02E9 DATA_SG +ZCHRS. . . . . . . . . . . . . . L BYTE 09ED DATA_SG +ZEROOP . . . . . . . . . . . . . L WORD 0890 DATA_SG +ZIPBGN . . . . . . . . . . . . . N PROC 0F6A CODE_SG Length =0149 +ZLOCS. . . . . . . . . . . . . . L WORD 066D DATA_SG +ZMVERS . . . . . . . . . . . . . Number 0003 +ZORKID . . . . . . . . . . . . . L WORD 02DF DATA_SG +ZPC1 . . . . . . . . . . . . . . L WORD 066F DATA_SG +ZPC2 . . . . . . . . . . . . . . L WORD 0671 DATA_SG +ZSTK_TP. . . . . . . . . . . . . L WORD 0400 STK_SG +ZVERSN . . . . . . . . . . . . . Number 0044 +ZWD1$. . . . . . . . . . . . . . L NEAR 0DEB CODE_SG +ZWD2$. . . . . . . . . . . . . . L NEAR 0DF7 CODE_SG +ZWD3$. . . . . . . . . . . . . . L NEAR 0DFD CODE_SG +ZWD4$. . . . . . . . . . . . . . L NEAR 0E0E CODE_SG +ZWD5$. . . . . . . . . . . . . . L NEAR 0E33 CODE_SG +ZWD6$. . . . . . . . . . . . . . L NEAR 0E36 CODE_SG +ZWORD. . . . . . . . . . . . . . N PROC 0DDF CODE_SG Length =0082 +.CHR1$ . . . . . . . . . . . . . L NEAR 1880 CODE_SG +.CHRIN . . . . . . . . . . . . . N PROC 1864 CODE_SG Length =0023 +.CHROUT. . . . . . . . . . . . . N PROC 18A4 CODE_SG Length =001E +.CR1$. . . . . . . . . . . . . . L NEAR 195F CODE_SG +.CR2$. . . . . . . . . . . . . . L NEAR 1969 CODE_SG +.CRBT. . . . . . . . . . . . . . N PROC 18DB CODE_SG Length =0015 +.CRLF. . . . . . . . . . . . . . N PROC 18F0 CODE_SG Length =007F +.CRLF1 . . . . . . . . . . . . . L NEAR 1909 CODE_SG +.CRLFN . . . . . . . . . . . . . L NEAR 1914 CODE_SG +.GETMEM. . . . . . . . . . . . . N PROC 1A0A CODE_SG Length =002A +.GETTM . . . . . . . . . . . . . N PROC 1A34 CODE_SG Length =0013 +.GTM1$ . . . . . . . . . . . . . L NEAR 1A15 CODE_SG +.GTM2$ . . . . . . . . . . . . . L NEAR 1A33 CODE_SG +.GTMX$ . . . . . . . . . . . . . L NEAR 1A1F CODE_SG +.PA1$. . . . . . . . . . . . . . L NEAR 1995 CODE_SG +.PA2$. . . . . . . . . . . . . . L NEAR 19AA CODE_SG +.PA3$. . . . . . . . . . . . . . L NEAR 19AD CODE_SG +.PR1$. . . . . . . . . . . . . . L NEAR 1972 CODE_SG +.PR2$. . . . . . . . . . . . . . L NEAR 1986 CODE_SG +.PR3$. . . . . . . . . . . . . . L NEAR 1989 CODE_SG +.PRINT . . . . . . . . . . . . . N PROC 196F CODE_SG Length =001C +.PRINTA. . . . . . . . . . . . . N PROC 198B CODE_SG Length =0027 +.RD0$. . . . . . . . . . . . . . L NEAR 19E4 CODE_SG +.RD1$. . . . . . . . . . . . . . L NEAR 19E8 CODE_SG +.RD2$. . . . . . . . . . . . . . L NEAR 1A06 CODE_SG +.RDFL$ . . . . . . . . . . . . . L NEAR 1A05 CODE_SG +.RDWRT . . . . . . . . . . . . . N PROC 19B2 CODE_SG Length =0058 +.RDX$. . . . . . . . . . . . . . L NEAR 19D3 CODE_SG +  The IBM Personal Computer MACRO Assembler 01-01-80 PAGE Symbols-13 +ZIP Z-LANGUAGE INTERPRETER IBMPC VERSION + + +.SPACE . . . . . . . . . . . . . N PROC 18C2 CODE_SG Length =0019 +.TTYOUT. . . . . . . . . . . . . N PROC 1887 CODE_SG Length =001D +.TYO1$ . . . . . . . . . . . . . L NEAR 189F CODE_SG + +Warning Severe +Errors Errors +0 0 diff --git a/ibm/iboss.asm b/ibm/iboss.asm new file mode 100644 index 0000000..cb0dd97 --- /dev/null +++ b/ibm/iboss.asm @@ -0,0 +1,185 @@ +; title - boss +; include file to add boss key to ZIP + +; call boss with character in AL to display file boss.scr +; call herald to display file herald.scr + +; Written by E. H. Black - May-19-1986 +; +; +BOSSKEY equ 2 ;ctrl B -- function keys not available through DOS? + +OPENF equ 3DH ;AH/3DH, DS:DX->ASCIZ path name, AL/open mode + ;return AX/open mode if carry clear, else error bits +RACC equ 0 ;access for read +WACC equ 1 ;access for write +RWACC equ 2 ;access for read/write + +CLOSEF equ 3EH ;AH/3EH, BX/File Handle from OPENF + ;return AX/- if carry clear, else error bits +BUFSIZE equ 256 +BUFFER db 256 dup (?) + +STDOUT equ 1 ;file handle for screen +ESC equ 27 ;ascii escape + +INCHR equ 08H ;DOS function: console input without echo +PRTSTR equ 09H ;" print string to screen +CLRKEY equ 0CH ;" clear buffer & invoke kb function + +DISPLAY MACRO nm + mov dx,offset nm + call showit + ENDM + +filehan dw 0 ;file handle for input file +bossfn db 'LEATHER.SCR',0 + db 53 DUP (0) ;room for 64 chrs in fn +bossext db 'SCR' +hrldext db 'HRL' +cntfind db 'File not Found',13,10,'$' +clrstr db ESC,'[0m',ESC,'[2J','$' ;attrs off, erase screen and home +; +boss proc + push AX + push BX + push CX + push DX + push SI + cmp al,BOSSKEY ;hit the magic key? + jnz bossret ;carry is clear + CALL SAVECUR ;save cursor + CALL clearit ;clear screen + MOV DX,offset bossfn ;file name + CALL openit + jnc reader + DISPLAY cntfind + jmp waiter +reader: CALL readit + CALL closit + +waiter: CALL waitkey + + CALL restor + CALL RESTCUR ;restore cursor + stc ;alert caller that key is to be deleted +bossret: + POP SI + POP DX + POP CX + POP BX + POP AX + RET +;herald puts up intro screen, waits for any key +herald: push AX + push BX + push CX + push DX + push SI + MOV DX,offset bossfn ;file name string + MOV BX,offset hrldext ;extension for herald + CALL makefn ;make .ext in bossfn + CALL openit + jc herret + CALL SAVECUR ;save cursor + CALL clearit ;clear screen + CALL readit + CALL closit + CALL waitkey + CALL restor + CALL RESTCUR ;restore cursor +herret: + MOV DX,offset bossfn ;file name string + MOV BX,offset bossext ;extension + CALL makefn ;make .ext in bossfn + ; so boss just opens + POP SI + POP DX + POP CX + POP BX + POP AX + RET +;openit takes file name ptr in DX, returns handle in AX +openit: + MOV AL,RACC ;read only + MOV AH,3Dh + INT 21h + mov filehan,ax ;store file handle for read & close + RET +; +closit: MOV BX,filehan + MOV AH,3Eh ;close handle in BX + INT 21h + RET +;read the file and transfer it to the screen +readit: +readlp: CALL readbl ;get a block + jc readxx ;error occurred? + CALL showbl ;if not, show the block (or amt read) + CMP AX,BUFSIZE ;full block read? + JZ readlp +readxx: RET +;read a block of text or less from the file +readbl: MOV BX,filehan ;handle + MOV CX,BUFSIZE ;byte count + MOV DX,offset BUFFER + MOV AH,3Fh ;read block + INT 21h + RET ;AX/number of bytes read, if cc +;output the buffer to the screen (AX assumed to contain # bytes) +showbl: MOV CX,AX ;#bytes to transfer + MOV DX,offset buffer + MOV BX,STDOUT ;screen + MOV AH,40H ;write + INT 21h + RET +;showit called with DS:DX->character string, terminated by $ +showit: MOV AH,PRTSTR ;print string + INT 21h + RET +; +restor: CALL clearit + RET ;nice if we could switch screens? + +;clears the screen +clearit:DISPLAY clrstr + RET +; +waitkey:MOV AH,CLRKEY ;clear keyboard buffer and invoke kb function + MOV AL,INCHR ;function (Console Input without echo) + INT 21H + RET +;makefn takes an output string pointer in DX, an extension in BX +; and copies the game file name from gamfile into the output string, +; appending the extension and a 0 + +makefn: push ax + push di + push si + push es + push ds ;point ds,es at same seg + pop es + mov si,offset gamfile ;input is the name of the game + mov di,dx ;output to string passed in DX +makef1: lodsb ;get char from name + or al,al ;end of string? + jz makef2 + cmp al,'.' ;extension reached? + jz makef2 + stosb ;unspecial char, just store + jmp makef1 +makef2: mov al,'.' ;whether . or 0 reached, output . + stosb + mov si,bx ;input is extension string + movsb + movsb + movsb ;copy 3 chrs + sub al,al + stosb ;and write a 0 + pop es + pop si + pop di + pop ax + ret + +boss endp diff --git a/ibm/install.bat b/ibm/install.bat new file mode 100644 index 0000000..a951753 --- /dev/null +++ b/ibm/install.bat @@ -0,0 +1,69 @@ +echo off +cls +rem INSTALL.BAT ver B (11/15/86) for Cornerstone Demo and IF +if %1x==x install B: +echo ____________________________________________________________________ +echo . +echo . +echo INFOCOM GAME INSTALLATION +echo FOR A FLOPPY DISKETTE +echo . +echo ____________________________________________________________________ +echo . +echo This program will create a PLAY diskette. To proceed, you must have +echo one (1) diskette that you have formatted with the command FORMAT B:/S +echo (the PLAY diskette), and your original DOS diskette or a copy. You +echo should also have your reference card handy while running this +echo installation. +echo . +echo To install the CORNERSTONE DEMO, you will need another blank, +echo formatted diskette. After this program is finished, type +echo INSTALLD at the A: prompt. +echo . +a:yes Do you have the formatted diskette ready (Y/N)? +if errorlevel 1 goto end +echo . +a:yes Do you have a two floppy system (Y/N)? +if errorlevel 1 goto one +echo . +echo Put your PLAY diskette in drive %1 and +pause +goto two +:one +echo . +echo You will be required to switch diskettes often as this program copies +echo the STORY files from the original diskette to your PLAY diskette. +echo Your computer will prompt you when to switch diskettes. Whenever you +echo are prompted to insert a diskette for drive A:, you should insert the +echo original STORY diskette into the drive; whenever you are prompted to +echo insert a diskette for drive B:, you should insert the PLAY diskette +echo into the drive. +echo . +pause +:two +echo . +echo ... Please Wait ... +if not exist %1command.com goto nodos +if errorlevel 1 copy a:yes.com %1one > nul +rem Used to to copy *.dat here, but loses on clones, so we'll wait till later +copy *.com %1 > nul +copy af.exe %1 > nul +copy setup.* %1 > nul +copy statline.bat %1 > nul +if not exist %1statline.bat goto nospace +%1 +%1statline %1 +:nospace +echo . +echo Insufficient disk space on drive %1 +goto end +:nodos +echo . +echo You have not properly formatted the diskette in drive %1. +echo . +:end +echo . +echo You are being returned to DOS without completing the installation. +echo Please find a blank diskette and format it with the command +echo FORMAT B:/S. When you have prepared the diskette as instructed +echo in the reference card, restart this installation procedure. diff --git a/ibm/installd.bat b/ibm/installd.bat new file mode 100644 index 0000000..d47954a --- /dev/null +++ b/ibm/installd.bat @@ -0,0 +1,54 @@ +echo off +rem INSTALLD.BAT installs CS demo on 1 or 2 floppy machine. Ver. A +rem 11/21/86 +cls +if %1x==x a:installd b: +echo -------------------------------------------------------------- +echo . +echo CORNERSTONE DEMO INSTALLATION +echo FOR A 1 or 2 FLOPPY MACHINE +echo . +echo -------------------------------------------------------------- +echo . +echo This program will install the CORNERSTONE DEMO on a backup +echo diskette. To proceed with this installation, you must have +echo a formatted, blank diskette. +echo . +a:yes Do you have a formatted blank diskette ready?(Y/N) +if errorlevel 1 goto nodisk +echo . +a:yes Do you have a two floppy computer?(Y/N) +if errorlevel 1 goto one +echo . +echo Insert the blank, formatted diskette in drive %1 and +pause +goto two +:one +echo . +echo You will be asked to swap disks several times. Whenever +echo you are prompted to place a diskette in drive A:, put the +echo ORIGINAL diskette in the drive. Whenever you are prompted to +echo place a diskette in drive B:, place your formatted diskette +echo in the drive. +:two +echo . +echo ... Please wait ... +cd demo +%1 +copy a:*.* +del demohd.bat > nul +ren demotf.bat csdemo.bat +a: +cd \ +echo . +echo Installation of the CORNERSTONE DEMO is complete. To run +echo the demo, place the backup disk in drive A: and type: CSDEMO. +goto end +:nodisk +echo . +echo You are being returned to DOS. Please format a disk with the +echo command FORMAT B:. When you have a disk ready, please restart +echo this program by typing INSTALLD. +:end + + diff --git a/ibm/installh.bat b/ibm/installh.bat new file mode 100644 index 0000000..70ceda2 --- /dev/null +++ b/ibm/installh.bat @@ -0,0 +1,68 @@ +echo off +cls +rem INSTALLH.BAT ver. B (11/15/86) for use with CS demo. +if %1x==x installh C: +%1 +cd \ +echo ____________________________________________________________________ +echo . +echo . +echo INFOCOM GAME INSTALLATION +echo FOR A HARD DISK +echo . +echo ____________________________________________________________________ +echo . +echo This program will copy the story files onto your hard disk from your +echo master STORY diskette. The story files will be copied into a +echo directory called \INFOCOM. +echo . +echo Included on this disk is the CORNERSTONE demo. This program will +echo copy the necessary files into a directory called \INFOCOM\CSDEMO if +echo you so desire. +echo . +echo ... Please Wait ... +a:gamedir +if errorlevel 2 goto nohd +if exist setup.inf ren setup.inf setup.old +copy a:setup.* >nul +copy a:statline.bat >nul +copy a:*.com >nul +copy a:*.dat >nul +copy a:af.exe >nul +if exist setup.old copy setup.old setup.inf >nul +if exist setup.old del setup.old >nul +del yes.com >nul +del gamedir.com >nul +echo . +a:yes Do you want to install the CORNERSTONE demo on your hard disk?(Y/N) +if errorlevel 1 goto nodem +echo . +echo The directory \INFOCOM\CSDEMO will be created and the necessary +echo files copied into it. To run the CORNERSTONE demo, enter the +echo \INFOCOM\CSDEMO directory and type CSDEMO at the prompt. +md csdemo > nul +cd csdemo > nul +copy a:\demo\*.* > nul +del demotf.bat +ren demohd.bat csdemo.bat +cd \INFOCOM +echo . +echo CORNERSTONE demo installation complete. +goto stat +:nodem +echo . +echo The Cornerstone demo will not be installed. If you want to +echo install it at a later date, you will need to run INSTALLH again. +echo . +:stat +statline %1 hd +:nohd +echo Drive %1 is not your hard disk. Please run INSTALLH again. +echo . +echo A:INSTALLH [d:] +echo . +echo Be sure to specify the hard disk drive letter followed by a colon. +echo If your hard disk is drive C:, then you do not need to specify +echo a drive at all. If you have a floppy based computer, you should +echo run INSTALL. + diff --git a/ibm/lip.asm b/ibm/lip.asm new file mode 100644 index 0000000..7c74762 --- /dev/null +++ b/ibm/lip.asm @@ -0,0 +1,7318 @@ + TITLE DIP/8086 + PAGE 58,132 + .LIST + + ;---------------------------------------------------------------------- + ; DIP/8086 Version 1.0 + ; D-CODE INTERPRETER PROGRAM + ; FOR IBM-PC UNDER MS-DOS + ;---------------------------------------------------------------------- + + ; INFOCOM, INC. + ; 125 CAMBRIDGE PARK DRIVE + ; CAMBRIDGE, MA 02140 + + ; COMPANY PRIVATE -- NOT FOR DISTRIBUTION + + ;---------------------------------------------------------------------- + ; M O D I F I C A T I O N H I S T O R Y + ;---------------------------------------------------------------------- + ; Date | Programer | Description + ;---------------------------------------------------------------------- +DEBUG EQU 0 +GMAJOR EQU 'y' +GMINOR EQU 0 + ; y ehb split out display-specific code & display init + ; x ehb hack grxtbl before start + ; C PHG RENAMED GAME.DAT TO FOOBLITZ.DAT ... RELEASE VERSION + ; + ; B7 PHG FIXED SPEED-UP IN DRAW FOR LOW MEMORY. + ; + ; B6 PHG FIXED EYE-DROPPER (SEG CROSS IN GTGFST) AND VERIFY. + ; PATCHES ARE STILL B5 + ; B5 PHG SECOND ROUND OF SPEED UP -- DRAW LOOP + ; + ; B4 PHG SPEED-UP: AFTER NARROWING DOWN PROBLEMS TO SPECIFIC + ; AREAS OF CODE, OPTIMIZATION WAS ATTEMPTED + ; + ; B3 PHG ADDED TRACE TRAP (CONDITIONAL ASSEMBLY) TO FIND + ; OUT WHERE THIS THING WASTES THE MOST TIME + ; + ; 9/09/85 | PHG | ADDED SAVE AND RESTORE (W/STACK AND + ; | I-FILE IN SAVE) AND VERIFY + ; 8/29/85 | PHG | FIXED PAGING BUG AND ENHANCED + ; 7/18/85 | PHG | ADDED SUPPORT FOR NO GAME PORT + ; | ADAPTER + ; 6/5/85 | R. LAY | MODIFIED {GINPUT} TO ACCEPT EITHER + ; | | KRAFT JOYSTICK BUTTON + ; 5/28/85 | R. LAY | IMPLIMENTED {LOAD} AND {DUMP} + ; 5/15/85 | R. LAY | MODIFIED {SENSE} AND SOUND ROUTINES + ; | | FOR IBM AT COMPATABILITY + ; 5/1/85 | R. LAY | 128K VERSION COMPLETE + ; 3/4/85 | R. LAY | 64K VERSION FROZEN. START OF 128K. + ; 12/31/84 | R. LAY | START 64K VERSION, NO PAGING. + + SUBTTL NOTES + PAGE + ;---------------------------------------------------------------------- + ; + ; I M P L E M E N T A T I O N N O T E S + ; + ;---------------------------------------------------------------------- + +; +; VIRTUAL MEMORY ALLOCATION +; + +; Virtual memory exists as a Data File on the game disk. Although two +; data files are created by the implimentor: GFILE.DAT and IFILE.DAT, +; (usually named filename.DIP and filename.PIC) these are concantenated +; while in the DOS command mode by issuing the command: +; CONCAT0 filename, if GFILE.DAT (or filename.DIP) file size is even +; CONCAT1 filename if GFILE.DAT file size is odd. +; +; Note that this scheme allows for easy inclusion of new data files through the +; use of the batch facilities. There is one caution: the filename portion of +; the data files must be the same. This may be accomplished by renaming one or +; both of the files or avoided by modifing the batch files. +; +; Each of the original data files consist of two parts: Preload and Pureload. +; For documentation purposes, these are called GPRE, GPURE, IPRE, and IPURE. +; + + SUBTTL EQUATES + PAGE + ;---------------------------------------------------------------------- + ; E Q U A T E S + ;---------------------------------------------------------------------- + + ; ----------- + ; 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) + ; 0A -- DISK ACCESS RANGE + ; 0B -- DISK ACCESS + ; 0C -- NO CALL ADDRESS + ; 0D -- UNDEFINED SOUND + ; 0E -- PURITY VIOLATION (SETI/SWAPI) + ; 0F -- ACTIVE ICON TABLE OVERFLOW + + ; -------------- + ; COMMON EQUATES + ; -------------- + +FALSE EQU 0 ;STANDARD VALUES +TRUE EQU 0FFH +LO EQU 0 +HI EQU 1 + + ; ----------------------- + ; FILE CONTROL STRUCTURES + ; ----------------------- + +RECSIZ EQU 512 ;512 BYTES/RECORD + + ; ---------------------------- + ; MS-DOS INT 21 FUNCTION CALLS + ; ---------------------------- + +CRESET EQU 0H ;PROGRAM TERMINATE +CCONIN EQU 1H ;WAIT FOR CONSOLE INPUT WITH ECHO +CPROUT EQU 5H ;PRINTER OUTPUT +CCONIO EQU 6H ;CONSOLE INPUT NO ECHO NO WAIT +CNOECHO EQU 7H ;INPUT NO ECHO +CRDLIN EQU 0AH ;CONSOLE LINE INPUT +CDRESET EQU 0DH ;DISK RESET +CFCREAZ EQU 3CH ;CREATE FILE +CFOPENZ EQU 3DH ;OPEN FILE +CFCLOSZ EQU 3EH ;CLOSE FILE +CRDRNDZ EQU 3FH ;READ RANDOM RECORD +CWRRNDZ EQU 40H ;WRITE RANDOM RECORD +CFDELEZ EQU 41H ;DELETE FILE +CFSEEK EQU 42H ;SEEK +CSETBLK EQU 4AH +CSELDSK EQU 0EH ; SELECT DISK +CURDSK EQU 19H + + ; ----------------- + ; MEMORY ALLOCATION + ; ----------------- + +LSTACK EQU 512 ;SIZE OF THE GSTACK AND MACHINE STACK IN BYTES +LMOUTB EQU 80 ;MAX LENGTH OF OUTBUF, EXCLUDING TERMINAL 0 +LDOUTB EQU 80 ;DEFAULT LENGTH OF OUTBUF + + ; --------------------- + ; G-CODE HEADER OFFSETS + ; --------------------- + +GHEADER EQU 64 ; LENGTH OF G-FILE HEADER IN BYTES +GVERS EQU 0 ; (BYTE) G-MACHINE VERSION +GMODE EQU 1 ; (BYTE) MODE BYTE +GID EQU 2 ; (WORD) GAME ID +GEND EQU 4 ; (WORDPTR) BEGINNING OF NON-PRELOADED CODE +GSTART EQU 6 ; (WORDPTR ODD) EXECUTION START ADDRESS +GPUR EQU 8 ; (WORDPTR) BEGINNING OF PURE G-CODE +GGLOB EQU 10 ; (WORDPTR) START OF GLOBAL VARIABLE TABLE +GSER EQU 12 ; (6 BYTES) ASCII SERIAL NUMBER +GLEN EQU 18 ; (WORD) LENGTH OF G-PROGRAM IN WORDS +GCHECK EQU 20 ; (WORD) G-CODE CHECKSUM +GINTVER EQU 22 ; INTERPRETER VERSION LETTER AND NUMBER + + ; --------------------- + ; I-FILE HEADER OFFSETS + ; --------------------- + +IHEADER EQU 8 ; LENGTH OF I-FILE HEADER IN BYTES +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 + + ; --------------- + ; GENERAL EQUATES + ; --------------- + +ATTIME EQU 004FH ; TIME STANDARD FOR "FAST" PROCESSOR +NSNDS EQU 4 ; THERE ARE FOUR SOUND EFFECTS +JIFCNT EQU 800H ; NUMBER USED TO COMPENSATE DELAY FOR IBM AT'S +VID_SG EQU 0B800H ; VIDEO MEMORY LOCATION +BIOSDATA EQU 40H ; BIOS DATA AREA SEG +KB_FLAG EQU 17H ; BIOS DATA AREA OFFSET TO KEY FLAGS +NUMLOCK EQU 20H ; NUMLOCK BIT +BIOS EQU 0F000H ; BIOS SEGMENT +BIOSOFF EQU 0E000H ; BIOS OFFSET +ID_OFF EQU 0FFFEH ; OFFSET IN BIOS TO MACHINE ID +JR_ID EQU 0FDH ; ID BYTE FOR PCjr +DOSVER EQU 30H ; GET DOS VERSION NUMBER + + + + + SUBTTL MAIN PROGRAM + PAGE + ;---------------------------------------------------------------------- + ; M A I N P R O G R A M + ;---------------------------------------------------------------------- +IF1 %OUT PASS1 +ELSEIF %OUT PASS2 +ENDIF +CSEG SEGMENT PARA PUBLIC + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG + ORG 100H +; + PUBLIC MSDIP +MSDIP PROC + JMP START ;SKIP OVER DIP DATA + + SUBTTL DATA DEFINITIONS + PAGE + ;--------------------------------------------------------------------- + ; D A T A D E F I N I T I O N S + ;--------------------------------------------------------------------- + + ; --------------- + ; TRADITIONAL I/0 + ; --------------- + + ; FILE CONTROL STRUCTURES +GAMFILE DB 'FOOBLITZ.DAT',0 ;ACIIZ FILE NAME DEFAULT DRIVE + DB 49 DUP (0) ;POTENTIAL LENGTH OF FILENAME +GAMHNDL DW 0 ;GAME FILE HANDLE + +DATFILE DB 'GAME.SAV',0 ; ASCIIZ FILE NAME + DB 53 DUP (0) ;POTENTIAL LENGTH OF FILENAME, NO DEFAULT +DATHNDL DW 0 ;GAME FILE HANDLE + +LASTSAV DB 'GAME.SAV',0 ; ASCIIZ FILE NAME + DB 53 DUP (0) ;POTENTIAL LENGTH OF FILENAME, NO DEFAULT + +NAMBUF DB 20 DUP (0) ;FILE NAME BUFFER + ; DRIVE STUFF +LASTDRV DB ? ; LAST LOGGED DRIVE +DSKDIR DB -1 ; SAVE OR RESTORE? +LSTDFLG DB ? ; LAST DRIVE FLAG +DEFDRV DB 0 ; DEFAULT (ORIGINAL) DRIVE +DRVFLG DB 0 ; USER SPECIFIED DRIVE? +CURDRV DB 0 ; WHERE WE ARE LOGGED CURRENTLY +SKPDRV DB 0 ; SKIP DRIVE PRINT OUT + ; KEYBOARD HANDLING +KYFLGS DB ? ; ORIGINAL KEYBOARD FLAGS +XLKEY DB 37H,38H,39H,0,34H,0,36H,0,31H,32H,33H + ;MESSAGES +ERRTAB DW OFFSET FERR0 + DW OFFSET FERR1 + DW OFFSET FERR2 + DW OFFSET FERR3 + DW OFFSET FERR4 + DW OFFSET FERR5 + DW OFFSET FERR6 + DW OFFSET FERR7 + DW OFFSET FERR8 + DW OFFSET FERR9 + DW OFFSET FERR10 + DW OFFSET FERR11 + DW OFFSET FERR12 + DW OFFSET FERR13 + DW OFFSET FERR14 + DW OFFSET FERR15 + DW OFFSET FERR16 + DW OFFSET FERR17 + DW OFFSET FERR18 +; +FERR0 DB 20,"GAME PRELOAD TOO BIG$" +FERR1 DB 21,"IMAGE PRELOAD TOO BIG$" +FERR2 DB 14,"UNDEFINED X-OP$" +FERR3 DB 14,"UNDEFINED 0-OP$" +FERR4 DB 14,"UNDEFINED 1-OP$" +FERR5 DB 14,"UNDEFINED 2-OP$" +FERR6 DB 17,"G-STACK UNDERFLOW$" +FERR7 DB 16,"G-STACK OVERFLOW$" +FERR8 DB 16,"DIVISION BY ZERO$" +FERR9 DB 23,"PURITY VIOLATION (PUTB)$" +FERR10 DB 18,"LSEEK OUT OF RANGE$" +FERR11 DB 19,"GAME FILE NOT FOUND$" +FERR12 DB 15,"NO CALL ADDRESS$" +FERR13 DB 15,"UNDEFINED SOUND$" +FERR14 DB 23,"PURITY VIOLATION (SETI)$" +FERR15 DB 27,"ACTIVE ICON TABLE OVERFLOW$" +FERR16 DB 25,"CANNOT SET GRAPHICS MODE$" +FERR17 DB 21,"INCORRECT DOS VERSION$" +FERR18 DB 24,"INVALID GAME OR VERSION$" +; +ERRM DB 13,"FATAL ERROR: $" +XITMSG DB " END OF SESSION $" +SAV0 DB " Insert SAVE disk then enter file name.$" +SAV1 DB " (Default is $" +SAV2 DB "): $" +SAV3 DB " Insert game disk then strike any key to continue.$" +ERR1 DB " SAVE file not found$" +ERR4 DB " Unable to access SAVE file$" +ERR5 DB " No room on diskette for SAVE file$" +ERR6 DB " Read of SAVE file failed$" + PUBLIC WAITSTR +WAITSTR DB " The game is loading,",13,10 + DB " please wait...$" +STRIKE DB " Strike any key to continue...$" + + ; I/O BUFFERS + PUBLIC OUTBUF,INBUF,XFRBUF +OUTBUF DB 40 DUP(?) ;OUTPUT BUFFER +INBUF DB 80 DUP(?) ;INPUT BUFFER +XFRBUF DB RECSIZ DUP (?) ;TRANSFER BUFFER USED BY {LOAD} AND {SAVE} + + ; SPECIAL CONTROL + PUBLIC IBMAT,DLYCNT,TIMER +PRTOFF DW ? ; (B5) PRINT SCREEN ENTRY POINTS +PRTSEG DW ? +PCJR DB 0 ; JR FLAG FOR TIMING +IBMSTR DB "COPR. IBM$" ; IBM IDENTIFICATION STRING +IBMAT DB (?) ;IS THIS AN IBM AT (TRUE OR FALSE)? +DLYCNT DW (?) ;DELAY REQUEST IN 1/10 SEC +TIMER DB (?) ;1/100 SEC COUNT FROM REAL TIME CLOCK + ; USED IN DETERMINING 1/10 SEC DELAY +IF DEBUG + public itrcnt +itrcnt dw 2 dup (0) + public ipcount +ipcount dd 256 dup (0) ;pc position count -trace trap + public isavecs,ishift,ioffset,itop +isavecs dw 0 ;saved code seg paragraph +itrapcs dw 0 +ishift dw 0 ;4 ;8 ;3 +ioffset dw 0 ;mloop ;0 ;mloop +itop dw OFFSET MEMBUF ;imend ;-1 ;imend +t_out db 'tracer.out',0 +; +; +ENDIF + + PAGE + ; ----------------------- + ; OP-CODE DISPATCH TABLES + ; ----------------------- + + ; 0-OP DISPATCH TABLE +OPT0 DW GNOOP ; B0 + DW GRTRUE ; B1 + DW GRFALS ; B2 + DW GRSTAK ; B3 + DW GFSTAK ; B4 + DW GQUIT ; B5 + DW GCOPYP ; B6 + DW GVERP ; B7 + +NOPS0 EQU ($-OPT0)/2 ; # OF VALID 0-OPS + + ; 1-OP DISPATCH TABLE +OPT1 DW GPUSH ; 80 + DW GPOP ; 81 + DW GVALUE ; 82 + DW GINC ; 83 + DW GDEC ; 84 + DW GZEROP ; 85 + DW GBNOT ; 86 + DW GJUMP ; 87 + DW GRET ; 88 + +NOPS1 EQU ($-OPT1)/2 ; # OF 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 ; A + DW GLESSP ; B + DW GDLESP ; C + DW GGRTRP ; D + DW GIGRTP ; E + DW GSET ; F + DW GGET ; 10 + DW GGETB ; 11 + +NOPS2 EQU ($-OPT2)/2 ; # VALID 2-OPS + + ; X-OP DISPATCH TABLE +OPTX DW GCALL ; E0 + DW GPUT ; E1 + DW GPUTB ; E2 + DW GINPUT ; E3 + DW GSHOWI ; E4 + DW GSETI ; E5 + DW GSWAPI ; E6 + DW GSOUND ; E7 + DW GRAND ; E8 + DW GCLEAR ; E9 + DW GSHOWN ; EA + DW GWIND ; EB + DW GITER ; EC + DW GLOAD ; ED + DW GDUMP ; EE + DW GRESTR ; EF + DW GSAVE ; F0 + +NOPSX EQU ($-OPTX)/2 ; # VALID X-OPS + + PAGE + ; ----------------- + ; PROGRAM VARIABLES + ; ----------------- + + ; GCODE PROGRAM COUNTER DEFINITION + PUBLIC GPC,GPC2,GPC1,GPC0 +GPC LABEL WORD +GPC2 DB 0 ;LSB OF GPC +GPC1 DB 0 ;MSB OF GPC +GPC0 DB 0 ;BIT 0 OF BYTE IS BIT 0 OF GPC + + ; VIRTUAL MEMORY POINTER DEFINITION + PUBLIC VMP,VMP2,VMP1,VMP0,VMSAV,VMSAV0 +VMP LABEL WORD +VMP2 DB 0 ;LSB OF VMP +VMP1 DB 0 ;MSB OF VMP +VMP0 DB 0 ;BIT 0 OF BYTE IS BIT 0 OF VMP + +VMSAV DW 0 +VMSAV0 DB 0 + + ; VALUES USED IN COLDSTART + PUBLIC GPRBLK,IPRBLK,GCODE,GPEND,ICODE,ISTRT,IPURE,ZORKID +GPRBLK DB 0 ;TOTAL NUMBER OF G-PRELOAD BLOCKS +IPRBLK DB 0 ;TOTAL NUMBER OF I-PRELOAD BLOCKS + +GCODE DW 0 ;(WORD) VIRTUAL START ADDRESS OF G-CODE +GPEND DB 0 ;(BYTE) LAST VIRTUAL BLOCK OF G-PRELOAD +ICODE DW 0 ;(WORD) ABSOLUTE START ADDRESS OF I-PRELOAD +ISTRT DB 0 ;(BYTE) 1ST. V-PAGE OF I-PRELOAD +IPURE DW 0 ;(WORD) ABSOLUTE START ADDRESS OF I-PURELOAD +ZORKID DW ? ; GAME ID + + ; TABLE ADDRESSES + PUBLIC GLOCS,GLOBAL +GLOCS DW 0 ;OFFSET TO THE START OF THE DIP LOCAL TABLE +GLOBAL DW 0 ;(WORD) ABSOLUTE GLOBAL TABLE ADDR + + ; OPCODE SUPPORT + PUBLIC NARGS,ARG1,ABYTE,ADEX +NARGS DB 0 ;(BYTE) CURRENT NUMBER OF ARGUMENTS +ARG1 DW 0 ;(WORD) ARGUMENT 1 REGISTER +ARG2 DW 0 ;(WORD) ARGUMENT 2 REGISTER +ARG3 DW 0 ;(WORD) ARGUMENT 3 REGISTER +ARG4 DW 0 ;(WORD) ARGUMENT 4 REGISTER +ABYTE DB 0 ;(BYTE) X-OP ARGUMENT BYTE +ADEX DB 0 ;(BYTE) X-OP ARGUMENT INDEX +ADEX2 DB 0 ;(BYTE) "CALL" ARG-BYTE INDEX + + PUBLIC CTYPES,CARGS +CTYPES DB 16 DUP(?) ;GCALL 'MODE BYTE' LIST +CARGS DW 16 DUP(?) ;GCALL ARGUMENTS LIST + + PUBLIC OPCODE,VALUE,I,J,OLDGSP +OPCODE DB 0 ;(BYTE) OPCODE SAVE REGISTER +VALUE DW 0 ;(WORD) VALUE RETURN REGISTER +I DW 0 ;(WORD) GENERAL PURPOSE INDEX REGISTER #1 +J DW 0 ;(WORD) GENERAL PURPOSE INDEX REGISTER #2 + +OLDGSP DW 0 ;(WORD) OLD G-STACK POINTER + + ; RANDOM +RSEED1 DW 0 ;VARIABLES USED FOR RANDOM NUMBER GENERATION +RSEED2 DW 0 +RTEMP DW 0 + + ; INPUT CONTROL + PUBLIC STICKA,KEYSAV,JOYSTK +STICKA DB 0 ;JOYSTICK FLAGS BYTE +KEYSAV DB 0 ;SENSE RETURN CODE +JOYSTK DB 0 ;JOYSTICK PRESENCE + + ; SOUND CONTROL STRUCTURES +STABLE DW SND1,SND2,SND3,SND4 + + PAGE + ; --------------------------- + ; GRAPHICS CONTROL STRUCTURES + ; --------------------------- + + ; TABLE ADDRRESSES + PUBLIC BTAB,ITAB +BTAB DW 0 ;(WORD) ABSOLUTE BLOCKSET TABLE ADDRESS +ITAB DW 0 ;(WORD) ABSOLUTE ICON TABLE ADDRESS + + ; ICON DATA + PUBLIC NBLOKS,NICONS,IADR1,IADR10,IX1,IY1,XDEX1,YDEX1,BSET +NBLOKS DB 0 ;(BYTE) # BLOCKSETS IN I-FILE +NICONS DB 0 ;(BYTE) # ICONS IN I-FILE + +IADR1 DW 0 ;(WORD) ABS ADDR OF ICON #1 +IADR10 DB 0 ;(BYTE) LS BIT OF ABS ADDR OF ICON #1 + +IADR2 DW 0 ;(WORD) ABS ADDR OF ICON #2 +IADR20 DB 0 ;(BYTE) LS BIT OF ABS ADDR OF ICON #2 + +IX1 DB 0 ;(BYTE) XSIZE OF ICON #1 +IX2 DB 0 ;(BYTE) XSIZE OF ICON #2 +IY1 DB 0 ;(BYTE) YSIZE OF ICON #1 +IY2 DB 0 ;(BYTE) YSIZE OF ICON #2 +XDEX1 DB 0 ;(BYTE) X-INDEX #1 +XDEX2 DB 0 ;(BYTE) X-INDEX #2 +YDEX1 DB 0 ;(BYTE) Y-INDEX #1 +YDEX2 DB 0 ;(BYTE) Y-INDEX #2 +BSET DB 0 ;(BYTE) BLOCKSET ID (1-255) +BSADR DW 0 ;(WORD) ABS ADDR OF CURRENT BLOCKSET +BSIZE DB 0 ;(BYTE) # BLOCKS IN CURRENT BLOCKSET +TOX DB 0 ;(BYTE) X-SAVE FOR "DUMP" +BLOCK DB 8 DUP (?) ;(8 BYTES) IMAGE BLOCK BUFFER + PUBLIC BLOCK,I_EOP,G_EOP +I_EOP DW ? ; (B5) ICON END OF PAGE +G_EOP DW ? ; (B5) GRAPHICS EOP + + ; MASKING + PUBLIC MSKFLG,MBLOCK +MBLOCK DB 8 DUP (?) ;(8 BYTES) MASK BLOCK BUFFER +MSKFLG DB 0 ;(BYTE) FLAG FOR MASKING 00=DISABLED + + + PUBLIC NEGATE,BLKLEN,XPSAV +XPSAV DW 0 ;(WORD) X-POSITION SAVE +XCURS DB 0 ;(BYTE) GAME CURSOR X-POS +YCURS DB 0 ;(BYTE) GAME CURSOR Y-POS +NEGATE DB 0 ;(BYTE) BLOCK NEGATE FLAG +BLKLEN DB 0 ;(BYTE) # BLOCKS PER BLOCK + + ; ITERATIONS +ITERS DB 0 ;(BYTE) # OF ICON ITERATIONS +DOITER DB 0 ;(BYTE) CURRENT ITERATION +ITPNT DB 0 ;(BYTE) POINTER INTO CURRENT ICON TABLE +NAICN DB 0 ;(BYTE) NUMBER OF ACTIVE ICONS +ITICN DB 0 ;(BYTE) COUNTER FOR ITERATE ROUTINE + + + ; WINDOWS + PUBLIC XPOS,YPOS,IXSKIP +XPOS DW 0 ;(WORD) ICON X-POSITION +YPOS DW 0 ;(WORD) ICON Y-POSITION + +WINDX1 DB 0 ;(BYTE) LEFT CLIP VALUE +WINDX2 DB 0 ;(BYTE) RIGHT CLIP VALUE +WINDY1 DB 0 ;(BYTE) TOP CLIP VALUE +WINDY2 DB 0 ;(BYTE) BOTTOM CLIP VALUE + +TOPCUT DB 0 +SIDCUT DB 0 +MDXCUT DB 0 +WINDH DB 0 +WINDW DB 0 +IXSKIP DB 0 + + PUBLIC VDPADR +VDPADR DW 0 ;OFFSET INTO VIDEO RAM + + PAGE +; +; This table is used to translate a Byte of graphics data into a Word of +; IBM graphics data. +; +; The IBM has a screen composed of 320 x 200 pixels. For the sake of +; convenience we use only 320 x 192. In Graphics Mode 4, the IBM utilizes +; 2 Bits/pixel. +; +; BIT 7 6 5 4 3 2 1 0 +; _____________________________________ +; | C1 C0 | C1 C0 | C1 C0 | C1 C0 | +; +--------+--------+--------+--------+ +; +; With the color pallete and background color we've selected, eack Bit pair +; can represent 1 of 4 possible colors. +; +; C1 | C0 | COLOR +; ---+----+----------- +; 0 | 0 | BLACK +; 0 | 1 | CYAN +; 1 | 0 | MAGENTA +; 1 | 1 | WHITE +; +; Since the IBM has twice the horizontal resolution of the GRAPHIC DATA, we +; have to double each pixel. This causes the loss of cyan and magenta. +; Since the GRAPHIC DATA achieves color through archiving, the following +; scheme suffices. +; +; Given: A Byte of graphics data representing 8 pixels eg.: +; +; 00011011B (01BH) +; +; BIT 7 6 5 4 3 2 1 0 +; 0 0 0 1 1 0 1 1 +; PIXEL 1 2 3 4 5 6 7 8 +; +; Becomes a Word of IBM graphics data representing 8 pixels eg.: +; +; 00000011 11001111B (03CFH) +; +; BIT F E | D C | B A | 9 8 | 7 6 | 5 4 | 3 2 | 1 0 +; 0 0 | 0 0 | 0 0 | 1 1 | 1 1 | 0 0 | 1 1 | 1 1 +; PIXEL 1 2 3 4 5 6 7 8 +; +; +; Because all color is produced by artifacting, and the ATARI effect is +; different than the IBM we also right shift the word around 2 bits in +; advance for phase shifting purposes +; + PAGE +; GRAPHICS TRANSLATION TABLE + PUBLIC GRXTBL +GRXTBL DW 0000H,0C000H,0003H,0C003H + DW 000CH,0C00CH,000FH,0C00FH + DW 0030H,0C030H,0033H,0C033H + DW 003CH,0C03CH,003FH,0C03FH + + DW 00C0H,0C0C0H,00C3H,0C0C3H + DW 00CCH,0C0CCH,00CFH,0C0CFH + DW 00F0H,0C0F0H,00F3H,0C0F3H + DW 00FCH,0C0FCH,00FFH,0C0FFH + + DW 0300H,0C300H,0303H,0C303H + DW 030CH,0C30CH,030FH,0C30FH + DW 0330H,0C330H,0333H,0C333H + DW 033CH,0C33CH,033FH,0C33FH + + DW 03C0H,0C3C0H,03C3H,0C3C3H + DW 03CCH,0C3CCH,03CFH,0C3CFH + DW 03F0H,0C3F0H,03F3H,0C3F3H + DW 03FCH,0C3FCH,03FFH,0C3FFH + + DW 0C00H,0CC00H,0C03H,0CC03H + DW 0C0CH,0CC0CH,0C0FH,0CC0FH + DW 0C30H,0CC30H,0C33H,0CC33H + DW 0C3CH,0CC3CH,0C3FH,0CC3FH + + DW 0CC0H,0CCC0H,0CC3H,0CCC3H + DW 0CCCH,0CCCCH,0CCFH,0CCCFH + DW 0CF0H,0CCF0H,0CF3H,0CCF3H + DW 0CFCH,0CCFCH,0CFFH,0CCFFH + + DW 0F00H,0CF00H,0F03H,0CF03H + DW 0F0CH,0CF0CH,0F0FH,0CF0FH + DW 0F30H,0CF30H,0F33H,0CF33H + DW 0F3CH,0CF3CH,0F3FH,0CF3FH + + DW 0FC0H,0CFC0H,0FC3H,0CFC3H + DW 0FCCH,0CFCCH,0FCFH,0CFCFH + DW 0FF0H,0CFF0H,0FF3H,0CFF3H + DW 0FFCH,0CFFCH,0FFFH,0CFFFH + + DW 3000H,0F000H,3003H,0F003H + DW 300CH,0F00CH,300FH,0F00FH + DW 3030H,0F030H,3033H,0F033H + DW 303CH,0F03CH,303FH,0F03FH + + DW 30C0H,0F0C0H,30C3H,0F0C3H + DW 30CCH,0F0CCH,30CFH,0F0CFH + DW 30F0H,0F0F0H,30F3H,0F0F3H + DW 30FCH,0F0FCH,30FFH,0F0FFH + + DW 3300H,0F300H,3303H,0F303H + DW 330CH,0F30CH,330FH,0F30FH + DW 3330H,0F330H,3333H,0F333H + DW 333CH,0F33CH,333FH,0F33FH + + DW 33C0H,0F3C0H,33C3H,0F3C3H + DW 33CCH,0F3CCH,33CFH,0F3CFH + DW 33F0H,0F3F0H,33F3H,0F3F3H + DW 33FCH,0F3FCH,33FFH,0F3FFH + + DW 3C00H,0FC00H,3C03H,0FC03H + DW 3C0CH,0FC0CH,3C0FH,0FC0FH + DW 3C30H,0FC30H,3C33H,0FC33H + DW 3C3CH,0FC3CH,3C3FH,0FC3FH + + DW 3CC0H,0FCC0H,3CC3H,0FCC3H + DW 3CCCH,0FCCCH,3CCFH,0FCCFH + DW 3CF0H,0FCF0H,3CF3H,0FCF3H + DW 3CFCH,0FCFCH,3CFFH,0FCFFH + + DW 3F00H,0FF00H,3F03H,0FF03H + DW 3F0CH,0FF0CH,3F0FH,0FF0FH + DW 3F30H,0FF30H,3F33H,0FF33H + DW 3F3CH,0FF3CH,3F3FH,0FF3FH + + DW 3FC0H,0FFC0H,3FC3H,0FFC3H + DW 3FCCH,0FFCCH,3FCFH,0FFCFH + DW 3FF0H,0FFF0H,3FF3H,0FFF3H + DW 3FFCH,0FFFCH,3FFFH,0FFFFH + PUBLIC GRETBL +GRETBL DW 0000H,0C000H,0003H,0C003H + DW 000CH,0C00CH,000FH,0C00FH + DW 0030H,0C030H,0033H,0C033H + DW 003CH,0C03CH,003FH,0C03FH + + DW 00C0H,0C0C0H,00C3H,0C0C3H + DW 00CCH,0C0CCH,00CFH,0C0CFH + DW 00F0H,0C0F0H,00F3H,0C0F3H + DW 00FCH,0C0FCH,00FFH,0C0FFH + + DW 0300H,0C300H,0303H,0C303H + DW 030CH,0C30CH,030FH,0C30FH + DW 0330H,0C330H,0333H,0C333H + DW 033CH,0C33CH,033FH,0C33FH + + DW 03C0H,0C3C0H,03C3H,0C3C3H + DW 03CCH,0C3CCH,03CFH,0C3CFH + DW 03F0H,0C3F0H,03F3H,0C3F3H + DW 03FCH,0C3FCH,03FFH,0C3FFH + + DW 0C00H,0CC00H,0C03H,0CC03H + DW 0C0CH,0CC0CH,0C0FH,0CC0FH + DW 0C30H,0CC30H,0C33H,0CC33H + DW 0C3CH,0CC3CH,0C3FH,0CC3FH + + DW 0CC0H,0CCC0H,0CC3H,0CCC3H + DW 0CCCH,0CCCCH,0CCFH,0CCCFH + DW 0CF0H,0CCF0H,0CF3H,0CCF3H + DW 0CFCH,0CCFCH,0CFFH,0CCFFH + + DW 0F00H,0CF00H,0F03H,0CF03H + DW 0F0CH,0CF0CH,0F0FH,0CF0FH + DW 0F30H,0CF30H,0F33H,0CF33H + DW 0F3CH,0CF3CH,0F3FH,0CF3FH + + DW 0FC0H,0CFC0H,0FC3H,0CFC3H + DW 0FCCH,0CFCCH,0FCFH,0CFCFH + DW 0FF0H,0CFF0H,0FF3H,0CFF3H + DW 0FFCH,0CFFCH,0FFFH,0CFFFH + + DW 3000H,0F000H,3003H,0F003H + DW 300CH,0F00CH,300FH,0F00FH + DW 3030H,0F030H,3033H,0F033H + DW 303CH,0F03CH,303FH,0F03FH + + DW 30C0H,0F0C0H,30C3H,0F0C3H + DW 30CCH,0F0CCH,30CFH,0F0CFH + DW 30F0H,0F0F0H,30F3H,0F0F3H + DW 30FCH,0F0FCH,30FFH,0F0FFH + + DW 3300H,0F300H,3303H,0F303H + DW 330CH,0F30CH,330FH,0F30FH + DW 3330H,0F330H,3333H,0F333H + DW 333CH,0F33CH,333FH,0F33FH + + DW 33C0H,0F3C0H,33C3H,0F3C3H + DW 33CCH,0F3CCH,33CFH,0F3CFH + DW 33F0H,0F3F0H,33F3H,0F3F3H + DW 33FCH,0F3FCH,33FFH,0F3FFH + + DW 3C00H,0FC00H,3C03H,0FC03H + DW 3C0CH,0FC0CH,3C0FH,0FC0FH + DW 3C30H,0FC30H,3C33H,0FC33H + DW 3C3CH,0FC3CH,3C3FH,0FC3FH + + DW 3CC0H,0FCC0H,3CC3H,0FCC3H + DW 3CCCH,0FCCCH,3CCFH,0FCCFH + DW 3CF0H,0FCF0H,3CF3H,0FCF3H + DW 3CFCH,0FCFCH,3CFFH,0FCFFH + + DW 3F00H,0FF00H,3F03H,0FF03H + DW 3F0CH,0FF0CH,3F0FH,0FF0FH + DW 3F30H,0FF30H,3F33H,0FF33H + DW 3F3CH,0FF3CH,3F3FH,0FF3FH + + DW 3FC0H,0FFC0H,3FC3H,0FFC3H + DW 3FCCH,0FFCCH,3FCFH,0FFCFH + DW 3FF0H,0FFF0H,3FF3H,0FFF3H + DW 3FFCH,0FFFCH,3FFFH,0FFFFH + + PAGE +; +; Y-AXIS TRANSLATION TABLE +; + +; This table is used to translate the starting row location (0-23) of +; a BLOCK to an offset from the VIDEO_RAM base address. + PUBLIC YAXTBL +; Y Axis (X)translation TaBLe +YAXTBL DW 1FB0H,20F0H,2230H,2370H + DW 24B0H,25F0H,2730H,2870H + DW 29B0H,2AF0H,2C30H,2D70H + DW 2EB0H,2FF0H,3130H,3270H + DW 33B0H,34F0H,3630H,3770H + DW 38B0H,39F0H,3B30H,3C70H + + PAGE + ; ------------------------- + ; PAGING CONTROL STRUCTURES + ; ------------------------- + PUBLIC FSIZE,BUFFERS,SEG0,SEG1,BUF,LRU,LOC,LADD,VPAGEN,OLDMRU,MEMMAP +FSIZE DB 0 ;NUMBER OF 512 BYTE BLOCKS IN GAME.DAT FILE +BUFFERS DB 0 ;NUMBER OF 512 BYTE BLOCKS IN PAGING AREA +SEG0 DW ? ;FIRST (OR ZERO) GAME SEGMENT +SEG1 DW ? ;SECOND GAME SEGMENT (SEG0 + 64K) +BUF DB 0 ;INDEX INTO MEMBUF +LRU DB 0 ;LEAST RECENTLY USED PAGE +LOC DB 0 ;HIGH ORDER ABSOLUTE ADDRESS BITS +LADD DW 0 ;LOW ORDER ABSOLUTE ADDRESS BITS +VPAGEN DB 0 ;VIRTUAL PAGE NUMBER +OLDMRU DB 0 ;PREVIOUS MRU BUFFER NUMBER +MEMMAP DB 512 DUP(?) ;PAGING MEMORY MAP + + + ; ----------------- + ; STACK DEFINITIONS + ; ----------------- + PUBLIC MSTK_TP,MSTK_BT,GSTK_TP,GSTK_BT +EVEN +MSTK_BT DW LSTACK DUP(?) ;MACHINE STACK BOTTOM +MSTK_TP LABEL WORD ;MACHINE STACK TOP + +GSTK_BT DW LSTACK DUP(?) ;G-CODE INTERPRETER STACK BOTTOM +GSTK_TP LABEL WORD ;G-CODE INTERPRETER STACK TOP + +%OUT CODE + + SUBTTL SYSTEM INITIALIZATION + PAGE + ;---------------------------------------------------------------------- + ; S Y S T E M I N I T I A L I Z A T I O N + ;---------------------------------------------------------------------- +extrn grxperm:near +EXTRN CSETUP:NEAR +EXTRN GCLEAR:NEAR +EXTRN GCLR1:NEAR +EXTRN GCLR2:NEAR +EXTRN GCLR3:NEAR + + + PUBLIC START +START: MOV SP,OFFSET MSTK_TP ;SETUP STACK PTR (SP) + MOV DI,OFFSET GSTK_TP ;SETUP GSTACK PTR (DI) + call grxperm ; permute grxtbl + ; JUMP TO BEGINNING OF DIP + JMP DIPBGN + + SUBTTL 0-OP EXECUTORS + PAGE + ;---------------------------------------------------------------------- + ; S U B R O U T I N E S + ;---------------------------------------------------------------------- + + ;--------------------------------------- + ; OPCODE EXECUTION PROCEDURES + ;--------------------------------------- + ;--------------- + ; 0-OP EXECUTORS + ;--------------- + + ; ---- + ; NOOP + ; ---- + + ; NOOP (NO OPERATION) + PUBLIC GNOOP +GNOOP PROC + RET ;DO NOTHING +GNOOP ENDP + + ; ----- + ; RTRUE + ; ----- + + ; DO A "RETURN 1", WHERE 1 IS COMMONLY INTERPRETED AS TRUE. + PUBLIC GRTRUE,GRT2 +GRTRUE PROC + MOV AX,1 ;RETURN A 1 +GRT2: MOV ARG1,AX + JMP GRET ;RETURN VIA GRET +GRTRUE ENDP + + ; ------ + ; RFALSE + ; ------ + + ; DO A "RETURN 0", WHERE 0 IS COMMONLY INTERPRETED AS FALSE. + PUBLIC GRFALS +GRFALS PROC + SUB AX,AX ;RETURN A 0 + JMP GRT2 +GRFALS ENDP + + ; ------ + ; RSTACK + ; ------ + + ; "RETURN" WITH VALUE FROM GSTACK + PUBLIC GRSTAK +GRSTAK PROC + CALL POPVAL ;GET VALUE INTO AX + JMP GRT2 +GRSTAK ENDP + + ; ------ + ; FSTACK + ; ------ + + ; FLUSH THE TOP VALUE OFF THE GSTACK + PUBLIC GFSTAK +GFSTAK PROC + JMP POPAXG +GFSTAK ENDP + + ; ----------------------- + ; POP AX FROM THE GSTACK + ; ----------------------- + PUBLIC POPAXG,GSTKU +POPAXG PROC + XCHG SP,DI ;USE THE REAL SP + POP AX ;POP THE STACK + XCHG SP,DI ;SWAP BACK + PUSH AX ;SAVE REGISTER + MOV AX,OFFSET GSTK_TP ;CHECK IF WE HAVE AN UNDERFLOW + CMP DI,AX ; + JA GSTKU ; IF WE DO IT'S FATAL + POP AX ; ELSE, RESTORE THE REGISTER + RET + + ; *** ERROR #6: G-STACK UNDERFLOW *** +GSTKU: POP AX + MOV AL,6 + JMP GERROR +POPAXG ENDP + + ; ---- + ; QUIT + ; ---- + + ; THE GAME SHOULD DIE PEACEFULLY + ; (MACHINE DEPENDENT) + PUBLIC GQUIT +GQUIT PROC + JMP FINISH +GQUIT ENDP + + ; ----- + ; COPYP + ; ----- + + ; *** UNABLE TO FIND IN THE DOCUMENTATION *** + PUBLIC GCOPYP +GCOPYP PROC + JMP PREDS +GCOPYP ENDP + + ; ---- + ; VERP + ; ---- + + ; *** UNABLE TO FIND IN THE DOCUMENTATION *** + PUBLIC GVERP,GVER1,GVER2,GVER3,GVER4,GVER5,GVER6,GVER7,GVER8 + PUBLIC GVER$,GVER$$,GVERA,GVERB,GVERC,GVERD,GVERE +GVERP PROC + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH BP + PUSH DS + PUSH ES + + ; RESET THE FILE POINT TO BEGINNING OF THE FILE (LESS THE HEADER) + + MOV BX,GAMHNDL ; FILE HANDLE + MOV CX,0 + MOV DX,64 ; OFFSET IN THE FILE + MOV AX,4200H ; SEEK + INT 21H + + MOV VMP,0 ; GET CHECK SUM VALUE + MOV VMP0,0 + MOV AX,GCHECK ; OFFSET IN HEADER + CALL ADDVMP + CALL GW@VMP ; GET THE WORD THERE + MOV J,AX ; SAVE IN GENERAL VAR J +; + MOV AX,ICODE + MOV VMP,AX ; GET I-FILE CHECK SUM + MOV VMP0,0 + MOV AX,ICHECK ; OFFSET IN HEADER + CALL ADDVMP + CALL GW@VMP ; GET THE WORD THERE + MOV I,AX ; SAVE I-CHECKSUM IN VARIABLE I + MOV BP,0 ; ZERO THIS BABY TO HOLD CURRENT CHECKSUMS +; + MOV VMP,0 ; GET LENGTH OF G-FILE + MOV VMP0,0 + MOV AX,GLEN ; OFFSET IN HEADER + CALL ADDVMP + CALL GW@VMP ; GET THE WORD THERE + MOV DI,AX ; SAVE IT + SUB DI,GHEADER/2 ; SUBTRACT THE NUMBER OF BYTES IN HEADER + + ; FIGURE OUT HOW MUCH SPACE WE HAVE BETWEEN THE END OF PRELOAD + ; AND THE END OF THE FIRST 64K BOUNDARY. WE WILL USE THAT SPACE + ; AS A BUFFER FOR VERIFY. FIRST WE MUST ZERO OUT THE MEMMAP THAT + ; INDICATE IF THOSE PAGES ARE IN CORE AND RESET THERE MEMBUF + ; DESCRIPTORS. WE MUST ALSO PLAY WITH THE LRU POINTERS TO NOT + ; SCREW UP THE MEMORY MAP. + + MOV DX,SEG0 ; START OUT USING 0 SEG + MOV BL,BUFFERS ; HOW MANY POTENTIAL VERIFY BUFFERS? + CMP BL,080H ; NO MORE THAN 64K + JB GVER1 + SUB BL,80H ; REDUCE IT 64K OR LESS + MOV DX,SEG1 ; SWITCH TO 1ST SEG + MOV BH,0 ; ZERO TOP HALF + PUSH BX ; SAVE NUMBER OF BUFFERS + JMP GVERE ; CLEAN OUT MEMBUFS + + ; ZERO BUFFERS IN SEG 0 + +GVER1: MOV AH,GPRBLK ; GET TOTAL NUMBER OF PRELOAD BLOCKS + ADD AH,IPRBLK ; TO FIGURE BUFFER BOUNDARY + SUB BL,AH ; FIGURE --> BUFFERS - PRELOAD + PUSH BX + MOV CX,BX ; NUMBER OF BUFFERS DESC'S TO CLEAN OUT + MOV BX,OFFSET MEMBUF+1 ; GET ADDRESS OF FIRST BUFFER + + ; MEMBUF ZEROING LOOP + ; +GVERA: MOV BYTE PTR [BX],0 ; SET NO PAGE IN MEMORY FOR THIS BUFFER + ADD BX,4 ; NEXT BUFFER + LOOP GVERA ; CLEAN 'EM ALL OUT + MOV CX,0FFH ; NOW, CLEAN OUT THE MEMORY MAP + MOV BX,0 ; START AT THE BEGINNING +GVERB: TEST MEMMAP[BX],1 ; PRELOAD? + JZ GVERC ; NOPE, ZERO IT +GVERD: ADD BX,2 ; YES, SO SKIP THIS ONE + LOOP GVERB ; AND CHECK THE NEXT + JMP GVERE +GVERC: CMP DX,SEG0 ; WHICH SEG? + JE GVERC$ + JMP GVERD$ +GVERC$: CMP MEMMAP[BX+1],7FH ; IF BUFFER NUMBER < 127, THEN 0 IT + JA GVERD +GVERD$: MOV MEMMAP[BX+1],0 ; INDICATE PAGE NOT IN CORE + JMP GVERD ; INCREMENT AND CONTINUE +; +GVERE: POP BX + MOV CL,9 + SHL BX,CL ; CONVERT BUFFERS INTO BYTES + MOV CX,BX ; SAVE NUMBER OF BYTES IN BUFFER + MOV ES,DX ; SET ES TO ADDRESS PROPER SEG + CMP DX,SEG0 ; WHICH SEG? + JNE GVERF + MOV DH,GPRBLK ; FIGURE BUFFER STARTING POINT + ADD DH,IPRBLK ; BY ADDING ALL PRELOAD BLOCKS + MOV DL,0 ; CLEAR OUT BOTTOM GARBAGE + SHL DX,1 ; CONVERT WORDS TO BYTE OFFSET + JMP GVERG +GVERF: MOV DX,0 +; +GVERG: MOV SI,0 + MOV BX,GAMHNDL ; GET FILE HANDLE + PUSH DS ; MAKE DS ADDRESS GAME SEG + PUSH ES + POP DS +GVER2: MOV AH,CRDRNDZ ; READ THE G-FILE PART + INT 21H + CALL CHKSUM ; PERFORM CHECK SUM ON BUFFER + CMP SI,DI ; HAVE WE CHECK THE WHOLE THING? + JE GVER3 + JMP GVER2 +; +GVER3: POP DS ; RESTORE DS + CMP BP,J ; CORRECT? + JE GVER4 + JMP GVER$ + + ; SEEK TO START OF I-FILE IN DAT FILE + +GVER4: PUSH CX ; SAVE BUFFER SIZE + PUSH DX ; AND LOCATION + MOV DX,DI ; GET LENGTH OF G-FILE + ADD DX,GHEADER/2 ; ADD IN PREVIOUSLY SUBBED HEADER + ADD DX,IHEADER/2 ; ALSO SKIP I-FILE HEADER + MOV CX,0 ; CLEAR OUT FOR SEEK + INC DX ; (B6) MAKE UP FOR KERMIT FROM DEC20 +GVER4A: SHL DX,1 ; CONVERT WORD LENGTH TO BYTES + ADC CX,0 ; GET 64K BIT IF THERE IS ONE + MOV AX,4200H ; SEEK + INT 21H ; DO IT + POP DX + POP CX + + ; NOW FILE POINTER IS READER TO READ I-PURE FOR VERIFY + ; FIGURE OUT HOW MANY BYTES IN I-FILE + + PUSH ES ; SAVE SEG BEING USED + MOV AX,ICODE + MOV VMP,AX ; GET LENGTH OF I-FILE OUT OF I-HEADER + MOV VMP0,0 ; SET VMP + MOV AX,ILEN + CALL ADDVMP + CALL GW@VMP ; GET THE WORD + + MOV DI,AX ; SAVE LENGTH + SUB DI,IHEADER/2 ; CHECK FILE LESS HEADER + MOV BP,0 ; ZERO THIS BABY AGAIN + MOV SI,0 + POP ES ; RESTORE SEG BEING USED + PUSH DS + PUSH ES + POP DS ; MAKE DS ADDRESS THE GAME SEG +; +GVER5: MOV AH,CRDRNDZ ; READ THE I FILE + INT 21H ; DO IT + CALL CHKSUM ; PERFORM CHECK SUM ON BUFFER + CMP SI,DI ; HAVE WE CHECK THE WHOLE THING? + JE GVER6 + JMP GVER5 + +GVER6: POP DS ; RESTORE DS + CMP BP,I ; COMPARE CHECKSUMS + JE GVER7 + JMP GVER$ +GVER7: CLC ; INDICATE SUCCESS +GVER8: PUSHF + CMP FSIZE,0 ; (B5) DID WE USE THE HIGH SEG + JE GVER9 + MOV AX,4200H ; (B5) SEEK FROM BEGINNING OF FILE + MOV CX,1 ; (B5) TO 64K LOCATION + PUSH DS ; (B6) SET TO UPPER + MOV DX,SEG1 ; (B6) SEGMENT FOR RELOAD + MOV DS,DX ; (B6) RESTORE DX + MOV DX,0 + INT 21H + MOV DX,0 ; (B5) READ IN SECOND 64K + MOV CX,0FFFFH ; (B5) THAT MUCH + MOV AH,CRDRNDZ ; (B5) READ FUNCTION + INT 21H + POP DS + +GVER9: POPF + POP ES ; RESTORES + POP DS + POP BP + POP DI + POP SI + POP DX + POP CX + POP BX + JC GVER$$ ; FAIL ON CARRY + JMP PREDS ; OTHERWISE SUCCESS +GVER$: STC ; COMMON ENTRY FOR FAILURE + JMP GVER8 ; DO RESTORES +GVER$$: JMP PREDF ; INDICATE FAILURE +GVERP ENDP + + PUBLIC CHKSUM +CHKSUM PROC NEAR + PUSH AX ; SAVES + PUSH BX + PUSH CX + PUSH DS + PUSH ES + POP DS + MOV BX,SI ; GET NUMBER OF WORDS CHECKED SO FAR + MOV CX,AX ; GET NUMBER OF BYTES TO CHECK + MOV SI,DX ; ADDRESS OF BUFFER + MOV AH,0 ; ZERO TOP HALF +CHKS1: LODSB ; GET A BYTE + ADD BP,AX ; ADD THE BYTE + TEST SI,1 ; ODD BYTE? + JNZ CHKS2 + INC BX + CMP BX,DI + JE CHKS3 +CHKS2: LOOP CHKS1 +CHKS3: MOV SI,BX ; RESTORE SI TO COUNT OF WORDS + POP DS + POP CX + POP BX + POP AX + RET +CHKSUM ENDP + + + SUBTTL 1-OP EXECUTORS + PAGE + ;--------------- + ; 1-OP EXECUTORS + ;--------------- + + ; ---- + ; PUSH + ; ---- + + ;PUSH [ARG1] ONTO THE GSTACK + PUBLIC GPUSH +GPUSH PROC + MOV AX,ARG1 + + ; AND FALL THROUGH ............. + +GPUSH ENDP + + ; ----------------------- + ; PUSH AX ONTO THE GSTACK + ; ----------------------- + PUBLIC PSHAXG,GSTKR +PSHAXG PROC + XCHG SP,DI ;USE THE REAL SP + PUSH AX ;PUSH IT ON THE STACK + XCHG SP,DI ;SWAP BACK + PUSH AX ;SAVE REGISTER + MOV AX,OFFSET GSTK_BT ;CHECK IF WE HAVE AN OVERFLOW + CMP DI,AX ; + JB GSTKR ; IF WE DO IT'S FATAL + POP AX ; ELSE, RESTORE THE REGISTER + RET + + ; *** ERROR #7: G-STACK OVERFLOW *** +GSTKR: POP AX + MOV AL,7 + JMP GERROR +PSHAXG ENDP + + ; --- + ; POP + ; --- + + ;POP A VALUE OFF THE GSTACK INTO VARIABLE [ARG1] + PUBLIC GPOP +GPOP PROC + CALL POPVAL + JMP DOPUT +GPOP ENDP + + ; ----- + ; VALUE + ; ----- + + ;RETURN VALUE OF VARIABLE [ARG1] + PUBLIC GVALUE +GVALUE PROC + MOV AX,ARG1 ;GET VARIABLE ID + SUB AH,AH + CALL VARGET ;GET THE VALUE INTO [VALUE] + JMP PUTVAL ;AND RETURN IT +GVALUE ENDP + + ; ---- + ; INC + ; ---- + + ;INCREMENT VARIABLE [ARG1] + PUBLIC GINC +GINC PROC + MOV AX,ARG1 ;GET VARIABLE ID + SUB AH,AH + CALL VARGET ;GET VAR'S VALUE + INC VALUE ;INCREMENT IT + JMP DOPUT +GINC ENDP + + ; --- + ; DEC + ; --- + + ;DECREMENT VARIABLE [ARG1] + PUBLIC GDEC,DOPUT +GDEC PROC + MOV AX,ARG1 + SUB AH,AH + CALL VARGET ;GET VAR'S VALUE + DEC VALUE ;DECREMENT IT + +DOPUT: MOV AX,ARG1 ;RESTORE VARIABLE ID + SUB AH,AH + JMP VARPUT ;STORE NEW VALUE +GDEC ENDP + + ; ----- + ; ZERO? + ; ----- + + ;[ARG1]=0? + PUBLIC GZEROP,PYES +GZEROP PROC + MOV AX,ARG1 + CMP AX,0 ;IS OPR ZERO? + JZ PYES ;YES, PREDICATE TRUE + JMP PREDF ;NO, PREDICATE FALSE + +PYES: JMP PREDS +GZEROP ENDP + + ; --- + ; NOT + ; --- + + ;COMPLEMENT [ARG1] + PUBLIC GBNOT +GBNOT PROC + MOV AX,ARG1 + NOT AX ;LOGICAL COMPLEMENT + JMP VEXIT ;RETURN THE VALUE +GBNOT ENDP + + ; ---- + ; JUMP + ; ---- + + ;JUMP TO G-ADDRESS [ARG1] + PUBLIC GJUMP +GJUMP PROC + MOV AX,ARG1 ;MOVE [ARG1] TO [VALUE] + MOV VALUE,AX + JMP PREDB3 ;A BRANCH THAT ALWAYS SUCCEEDS +GJUMP ENDP + + ; --- + ; RET + ; --- + + ;RETURN FROM "CALL" WITH VALUE [ARG1] + PUBLIC GRET,GRET1,GRET2 +GRET PROC + + ; RESTORE THE GSTACK PTR + MOV DI,OLDGSP ;RESTORE OLD TOP OF THE GSTACK + + ; RESTORE LOCALS + ; GET THE NUMBER OF LOCALS + CALL POPAXG ;POP # OF LOGALS FROM GSTACK INTO AX + XCHG AX,CX ; XFER INTO CX TO BE USED AS A LOOP COUNTER + + ; IF NUMBER OF LOCALS=0 THEN SKIP LOCAL RESTORATION + OR CX,CX ;ANY LOCALS? + JZ GRET2 ;....NO. SKIP LOCAL RESTORATION + + ; + ; LOCAL RESTORATION + ; + + ; INITIALIZE VMP + MOV AX,GLOCS ;SET UP VMP TO POINT TO THE LOCAL TABLE + MOV VMP,AX + MOV VMP0,0 + + ADD VMP,CX ;POINT PAST THE LAST LOCAL + + ; RESTORE ALL [CX] PUSHED LOCALS +GRET1: DEC VMP ;BACK UP TO THE CURRENT LOCAL + CALL POPAXG ;POP A LOCAL FROM THE GSTACK + CALL PW@VMP ;RESTORE THE LOCAL + LOOP GRET1 ; LOOP UNTIL WE HAVE THEM ALL + + ; RESTORE THE GPC +GRET2: CALL POPAXG ;GET THE GPC BIT FROM GSTACK + MOV GPC0,AL ; AND SAVE IT + + CALL POPAXG ;GET GPC FROM GSTACK + MOV GPC,AX ; AND SAVE IT + + ; RESTORE THE OLD GSP + CALL POPAXG ;GET OLD GSP FROM GSTACK + MOV OLDGSP,AX ; AND SAVE IT + + ; GET THE VALUE TO RETURN + MOV AX,ARG1 + JMP VEXIT +GRET ENDP + + ; ----------------- + ; VALUE RETURN EXIT + ; ----------------- + + ; ENTRY: VALUE IN AX + PUBLIC VEXIT +VEXIT PROC + MOV VALUE,AX + JMP PUTVAL ;RETURN THE VALUE +VEXIT ENDP + + SUBTTL 2-OP EXECUTORS + PAGE + ;--------------- + ; 2-OP EXECUTORS + ;--------------- + + ; -------- + ; BAD 2-OP + ; -------- + + ; *** ERROR #5: ILLEGAL 2-OP *** + PUBLIC BADOP2 +BADOP2 PROC + MOV AL,5 + JMP GERROR +BADOP2 ENDP + + ; --- + ; ADD + ; --- + + ;RETURN [ARG1] + [ARG2] + PUBLIC GADD +GADD PROC + MOV AX,ARG1 + MOV BX,ARG2 + ADD AX,BX ;ADD OPR1 AND OPR2 + JMP VEXIT ;RETURN THE VALUE +GADD ENDP + + ; --- + ; SUB + ; --- + + ;RETURN [ARG1] - [ARG2] + PUBLIC GSUB +GSUB PROC + MOV AX,ARG1 + MOV BX,ARG2 + SUB AX,BX ;SUBTRACT OPR2 FROM OPR1 + JMP VEXIT ;RETURN THE VALUE +GSUB ENDP + + ; --- + ; MUL + ; --- + + ;RETURN [ARG1] * [ARG2] + PUBLIC GMUL +GMUL PROC + MOV AX,ARG1 + MOV BX,ARG2 + IMUL BX ;MULTIPLY OPR1 BY OPR2,IGNORING OVERFLOW(DX) + JMP VEXIT ;RETURN THE VALUE +GMUL ENDP + + ; --- + ; DIV + ; --- + + ;RETURN QUOTIENT OF [ARG1] / [ARG2] + PUBLIC GDIV +GDIV PROC + MOV AX,ARG1 + MOV BX,ARG2 + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + JMP VEXIT ;RETURN THE VALUE +GDIV ENDP + + ; --- + ; MOD + ; --- + + ;RETURN REMAINDER OF [ARG1] / [ARG2] + PUBLIC GMOD +GMOD PROC + MOV AX,ARG1 + MOV BX,ARG2 + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + MOV AX,DX ;WE WANT REMAINDER + JMP VEXIT ;RETURN THE VALUE +GMOD ENDP + + ; ---- + ; BAND + ; ---- + + ;RETURN [ARG1] "AND" [ARG2] + PUBLIC GBAND +GBAND PROC + MOV AX,ARG1 + MOV BX,ARG2 + AND AX,BX ;LOGICAL AND + JMP VEXIT ;RETURN THE VALUE +GBAND ENDP + + ; ---- + ; BIOR + ; ---- + + ;RETURN [ARG1] "OR" [ARG2] + PUBLIC GBIOR +GBIOR PROC + MOV AX,ARG1 + MOV BX,ARG2 + OR AX,BX ;LOGICAL OR + JMP VEXIT ;RETURN THE VALUE +GBIOR ENDP + + ; ---- + ; BXOR + ; ---- + + ;RETURN [ARG1] "XOR" [ARG2] + PUBLIC GBXOR +GBXOR PROC + MOV AX,ARG1 + MOV BX,ARG2 + XOR AX,BX ;LOGICAL XOR + JMP VEXIT ;RETURN THE VALUE +GBXOR ENDP + + ; ----- + ; BITS? + ; ----- + + ;IS EVERY "ON" BIT IN [ARG1] ALSO "ON" IN [ARG2] + PUBLIC GBITSP,GBITS0 +GBITSP PROC + MOV AX,ARG1 + MOV BX,ARG2 + NOT AX ;TURN OFF BITS IN OPR2 THAT ARE ON IN OPR1 + AND BX,AX + JE GBITS0 ;SUCCESS IF OPR2 COMPLETELY CLEARED + JMP PBAD +GBITS0: JMP PGOOD +GBITSP ENDP + + ; ------ + ; EQUAL? + ; ------ + + ;DOES [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])? + PUBLIC GEQP,GEQP1,GEQP2 +GEQP PROC + MOV CL,BYTE PTR NARGS ;GET NUMBER OF ARGUMENTS + SUB CH,CH + DEC CX ;WE WANT TO COMPARE WITH ALL BUT ARG1 + SUB BX,BX ;RESET OFFSET + MOV AX,WORD PTR ARG1 [BX] ;GET ARG1 + +GEQP1: INC BX ;POINT TO NEXT ARG + INC BX ; REMEMBER, IT'S A WORD + CMP AX,WORD PTR ARG1 [BX] ;DOES ARG1 = ARG [BX]? + JE GEQP2 ;....YES + LOOP GEQP1 ;....NO. TRY NEXT ARG + + JMP PBAD ;PREDICATE FALSE IF WE RAN OUT OF ARGS +GEQP2: JMP PGOOD +GEQP ENDP + + ; + ; PREDICATE HANDLERS + ; + + ; USED TO VECTOR LOCAL SHORT JUMPS + PUBLIC PGOOD +PGOOD PROC + JMP PREDS +PGOOD ENDP + + PUBLIC PBAD +PBAD PROC + JMP PREDF +PBAD ENDP + + ; ----- + ; LESS? + ; ----- + + ;IS [ARG1] < [ARG2] + PUBLIC GLESSP,GLESS0 +GLESSP PROC + MOV AX,ARG1 + MOV BX,ARG2 + CMP AX,BX ;IS OPR1 LESS THAN OPR2? + JL GLESS0 ;YES, PREDICATE TRUE + JMP PBAD ;NO, PREDICATE FALSE +GLESS0: JMP PGOOD +GLESSP ENDP + + ; ------ + ; DLESS? + ; ------ + + ;DECREMENT VAR [ARG1]; SUCCEED IF < [ARG2] + PUBLIC GDLESP,GDLES0,GDLES1 +GDLESP PROC + MOV AX,ARG1 ;GET VARIABLE ID + PUSH AX ;SAVE VARIABLE ID + CALL VARGET ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + + SUB CX,CX ;SET FLAG FALSE + MOV BX,ARG2 ;GET VALUE TO COMPARE TO + CMP AX,BX ;IS VAR [ARG1] < ARG2? + JGE GDLES0 ;NO + INC CX ;YES, CHANGE FLAG TO TRUE +GDLES0: MOV BX,AX ;GET VALUE + MOV VALUE,BX ;STORE IT IN [VALUE] + POP AX ;RESTORE VARIABLE ID + + CALL VARPUT ;STORE [VALUE] AT VAR + CMP CX,0 ;TEST FLAG + JE GDLES1 ;FALSE, PREDICATE FALSE + JMP PGOOD ;ELSE, PREDICATE TRUE +GDLES1: JMP PBAD +GDLESP ENDP + + ; ----- + ; GRTR? + ; ----- + + ;IS [ARG1] > [ARG2] + PUBLIC GGRTRP,GGRTR0 +GGRTRP PROC + MOV AX,ARG1 + MOV BX,ARG2 + CMP AX,BX ;IS OPR1 GREATER THAN OPR2? + JG GGRTR0 ;YES, PREDICATE TRUE + JMP PBAD ;NO, PREDICATE FALSE +GGRTR0: JMP PGOOD +GGRTRP ENDP + + ; ------ + ; IGRTR? + ; ------ + + ;INCREMENT [ARG1]; SUCCEED IF > [ARG2] + PUBLIC GIGRTP,OPQIG0,OPQIG1,OQI1$ +GIGRTP PROC + MOV AX,ARG1 + MOV BX,ARG2 + PUSH AX ;SAVE VARIABLE + CALL VARGET ;GET VAR'S VALUE + INC AX ;INCREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE GREATER THAN VAL? + JLE OPQIG1 ;NO +OPQIG0: INC CX ;YES, CHANGE FLAG TO TRUE +OPQIG1: MOV BX,AX ;GET VALUE + MOV VALUE,BX ;STORE IT IN [VALUE] + POP AX ;RESTORE VARIABLE ID + CALL VARPUT ;STORE [VALUE] AT VAR + CMP CX,0 ;TEST FLAG + JE OQI1$ ;FALSE, PREDICATE FALSE + JMP PGOOD ;ELSE, PREDICATE TRUE +OQI1$: JMP PBAD +GIGRTP ENDP + + ; --- + ; SET + ; --- + + ;SET VARIABLE [ARG1] EQUAL TO [ARG2] + PUBLIC GSET +GSET PROC + MOV AX,ARG2 ;GET VALUE TO SAVE + MOV VALUE,AX ;PUT IT IN [VALUE] + MOV AX,ARG1 ;GET VARIABLE NO. + JMP VARPUT ;STORE THE VALUE IN THE VARIABLE +GSET ENDP + + ; --- + ; GET + ; --- + + ;RETURN ITEM [ARG2] IN WORD-TABLE [ARG1] + PUBLIC GGET +GGET PROC + MOV AX,ARG1 ;GET WORD TABLE BASE ADDRESS + ADD AX,ARG2 ;INDEX INTO WORD TABLE + MOV VMP,AX ;PUT ADDRESS INTO VIRTUAL MEMORY POINTER + MOV VMP0,0 ;IT MUST BE ON AN EVEN BOUNDRY + CALL GW@VMP ;GET THE WORD. RETURNED IN AX + MOV VALUE,AX ;PUT IT IN [VALUE] + JMP PUTVAL ;AND RETURN IT IN WORD TABLE [ARG1] +GGET ENDP + + ; ---- + ; GETB + ; ---- + + ;RETURN ITEM [ARG2] IN BYTE-TABLE [ARG1] + PUBLIC GGETB +GGETB PROC + MOV AX,ARG1 ;TABLE BASE ADDRESS (WORDPOINTER) + MOV VMP,AX ;SET UP BASE ADDRESS + MOV VMP0,0 + MOV AX,ARG2 ;GET BYTE POINTER + CALL ADDVMP ;ADD BYTE OFFSET TO BASE ADDRESS + CALL GB@VMP ;GET THE BYTE + JMP PUTBYT ;AND RETURN IT VIA PUTBYT +GGETB ENDP + + SUBTTL X-OP EXECUTORS + PAGE + ;--------------- + ; X-OP EXECUTORS + ;--------------- + + ; ---- + ; CALL + ; ---- + +; INSTRUCTION FORMAT: +; +; OPCALL, MODE BYTE1, .... MODE BYTEn, ARG1, .... ARGn +; +; +; MODE BYTE: +; +; There are no mode bits in the opcode itself. All of the mode bits appear +; in the byte(s) following the opcode. Each mode byte is capable of supporting +; up to four arguments. Thus a mode byte is composed of up to 4 half nibble +; mode control codes. +; +; (Mode control code will be abbreviated as MCC.) A mode byte may contain +; 4 MCC's labeled from left to right MCC1, MCC2, MCC3, and MCC4. +; +; MODE BYTE FORMAT: +; +; bits: 7 6 5 4 3 2 1 0 +; +------+------+------+------+ +; | MCC1 | MCC2 | MCC3 | MCC4 | +; +------+------+------+------+ +; +; +; MODE CONTROL CODE FORMAT: +; +; bits: 1 0 | Operand +; ----|--------------------- +; 0 0 | long immediate +; 0 1 | immediate +; 1 0 | variable +; 1 1 | no more operands +; +; +; +; AT ENTRY [NARGS] = 0 + + PUBLIC GCALL,GCL,GCL0,GCL1,GCL2,GCL3,GCL4,GCL5 + PUBLIC GCL6,GCL7,GCL8,DOCALL,CALL1,CALL2,CALL3,CALL4 +GCALL PROC + ; + ; FILL CTYPES ARRAY WITH 'NO MORE ARGS' + ; INITIALIZE REGISTERS + MOV CX,16 ;NUMBER OF POSSIBLE ARGUMENTS + MOV AL,0C0H ;USE THE 'NO MORE ARGS' CODE + SUB BX,BX ;RESET BYTE INDEX + + ; FILL THE CURRENT CELL +GCL: MOV BYTE PTR CTYPES [BX],AL + + ; UPDATE INDEX + INC BX ;POINT TO THE NEXT CELL + + ; LOOP TILL DONE + LOOP GCL ; AND DO IT 16 TIMES TOTAL + + ; + ; UNPACK MODE BYTES + ; + + MOV ADEX,4 ;INITIALIZE BYTE INDEX + MOV ADEX2,4 ;INITIALIZE ARG BYTE COUNTER + +GCL0: CALL GB@GPCI ;GRAB AN ARGUMENT BYTE + MOV ABYTE,AL ;SAVE IT + JMP GCL2 ;DON'T SHIFT THE MODE BYTE THE FIRST TIME + +GCL1: MOV AL,ABYTE ;RESTORE THE MODE BYTE + SHL AL,1 ;SHIFT AND + SHL AL,1 ;SHIFT AGAIN + MOV ABYTE,AL ;SAVE MODE BYTE FOR NEXT TIME + +GCL2: AND AL,0C0H ;MASK OUT THE GARBAGE + CMP AL,0C0H ;LAST ARGUMENT? + JZ GCL3 ;....YES. TIME TO DECODE THE ARGS + + ;ELSE ADD THIS ARGUMENT TO THE ARG-TYPE LIST + MOV BL,NARGS ; SET UP INDEX + MOV BH,0 + MOV BYTE PTR CTYPES [BX],AL + INC NARGS ; AND INCREMENT THE NUMBER OF ARGUMENTS + + DEC ADEX ;IS THIS ARG BYTE EMPTY? + JNZ GCL1 ;....NO. GET NEXT ARG + + MOV ADEX,4 ;ELSE RESET THE ARGUMENT INDEX + DEC ADEX2 ;HAVE WE DONE 4 ARG BYTES? + JNZ GCL0 ;....NO. GET ANOTHER + + ; [CTYPES] HAS LIST OF ARG TYPES + ; [NARGS] HAS NUMBER OF ARGUMENTS + ; GPC POINTS TO ARG1 (THE FUNCTION ADDRESS) + +GCL3: MOV ADEX,0 ;RESET THE ARGUMENT INDEX + MOV ADEX2,0 ;AND STORAGE INDEX + MOV AL,NARGS ;CONTINUE ONLY IF + CMP AL,0 ;[NARGS] <> 0 + JNZ GCL4 + + ; *** ERROR #12: NO CALL ADDRESS *** + MOV AL,12 + JMP GERROR + + ; SAVE THE GCALL ARGUMENTS IN THE CARGS ARRAY WHILE USING THE MODE + ; CONTROL CODES (LOCATED IN THE CTYPES ARRAY) TO OBTAIN THEM. +GCL4: + MOV BL,ADEX ;GET ARG INDEX + MOV BH,0 ;WIPE OUT THE MSB + CMP BL,NARGS ;OUT OF ARGS YET? + JZ GCL8 ;....YES + + INC ADEX ;UPDATE ARG INDEX TO NEXT ARG + + ; GET THE TYPE BYTE FOR CURRENT ARG IN AL + MOV AL,BYTE PTR CTYPES [BX] + + CMP AL,0 ;LONG IMMEDIATE? + JNZ GCL5 ;....NO + + ; LONG IMMEDIATE + CALL GETLNG ;....YES, GET IT + JMP GCL7 + +GCL5: CMP AL,40H ;SHORT IMMEDIATE? + JNZ GCL6 ;....NO + + ; SHORT IMMEDIATE + CALL GETSHT ;....YES, GET IT + JMP GCL7 + + ; VARIABLE +GCL6: CALL GETVAR ;MUST BE A GET VARIABLE + + ; ARGUMENT IS NOW IN AX + ; MOVE VALUE (IN AX) TO [CARGS] +GCL7: MOV BL,ADEX2 ;GET THE STORAGE INDEX + MOV BH,0 + MOV WORD PTR CARGS [BX],AX + ;SAVE IT IN CARGS + + INC ADEX2 ; AND INCREMENT THE INDEX + INC ADEX2 ; TWICE, CAUSE WE SAVING WORDS + JMP GCL4 ;LOOP BACK FOR ANOTHER ARGUMENT + + ; ARGUMENTS IN [CARGS], # OF ARGUMENTS IN [NARGS] +GCL8: MOV AX,CARGS + OR AX,AX ;DOES CALL ADDRESS=0? + JNZ DOCALL ;....NO. CONTINUE + + JMP PUTBYT ;ELSE RETURN THE ZERO IN AL + +; +; AND NOW THE ACTUAL CALL +; + +DOCALL: MOV AX,OLDGSP ;PUSH [OLDGSP] ON THE GSTACK + CALL PSHAXG + + MOV AX,GPC ;PUSH [GPC] ON THE GSTACK + CALL PSHAXG + + MOV AL,GPC0 ;PUSH GPC BIT ON THE GSTACK + CALL PSHAXG + + ;SET GPC TO THE FUNCTION ADDRESS + MOV AX,CARGS ;GET THE FUNCTION ADDRESS + MOV GPC,AX ;PUT IT IN THE GPC + MOV GPC0,0 ; ALL FUNCTIONS START ON WORD BOUNDRIES + + ;PROCESS THE FUNCTION'S LOCALS + CALL GB@GPCI ;GET # OF LOCALS IN FUNCTION + MOV ADEX,AL ;SAVE HERE FOR REFERENCE + MOV ADEX2,AL ;SAVE HERE FOR COUNTING + + ; ANY LOCALS? + OR AL,AL ;IF # LOCALS = 0 + JZ CALL2 ; THEN JUMP AHEAD + + ; PUT THE FUNCTION'S LOCALS IN THE LOCAL TABLE + ; WHILE SAVING THE PRE-EXISTING LOCALS ON THE GSTACK + ; SET UP LOOP COUNTER + MOV CL,AL ;PUT NUMBER OF LOCALS IN LOOP COUNTER + SUB CH,CH + + MOV AX,GLOCS ;POINT VMP AT THE BASE ADDRESS OF THE + MOV VMP,AX ; LOCAL TABLE + MOV VMP0,0 + +CALL1: CALL GW@VMP ;GET OLD LOCAL + CALL PSHAXG ; SAVE IT ON THE GSTACK + + CALL GETLNG ;GET FUNCTION'S LOCAL & POINT TO NEXT + CALL PW@VMPI ;PUT IT IN THE LOCAL TABLE AND POINT TO + ; THE NEXT TABLE ENTRY + LOOP CALL1 + +CALL2: DEC NARGS ;ANY ARGS LEFT? + JZ CALL4 ;....NO + + ; PASS UP TO 15 [CARGS] TO [LOCALS] + SUB BX,BX ;INITIALIZE LOOP INDEX + MOV AX,GLOCS ;POINT VMP AT THE BASE ADDRESS OF THE + MOV VMP,AX ; LOCAL TABLE + MOV VMP0,0 + +CALL3: MOV AX,WORD PTR CARGS+2 [BX] ;GET ARGUMENT + CALL PW@VMPI ;ASSIGN ARG TO A LOCAL + + INC BX ;UPDATE INDEX + INC BX ;IT'S A WORD PTR + DEC NARGS ;OUT OF ARGS YET? + JNZ CALL3 ;....NO + +CALL4: MOV AL,ADEX ;GET NO. OF LOCALS + MOV AH,0 ;MASK OUT THE MSB + CALL PSHAXG ; AND SAVE ON THE GSTACK + + MOV OLDGSP,DI ;SAVE THE GSTACK POINTER + JMP MLOOP ;AND GO BACK TO MAIN LOOP + +GCALL ENDP + + PAGE + ; --- + ; PUT + ; --- + ; + ; SET ITEM [ARG2] IN WORD-TABLE [ARG1] EQUAL TO [ARG3] + ; + PUBLIC GPUT +GPUT PROC + MOV AX,ARG1 ;GET WORD TABLE BASE ADDRESS + ADD AX,ARG2 ;INDEX INTO WORD TABLE + MOV VMP,AX ;PUT ADDRESS INTO VIRTUAL MEMORY POINTER + MOV VMP0,0 ;IT MUST BE ON AN EVEN BOUNDRY + MOV AX,ARG3 ;GET THE VALUE + CALL PW@VMP ; AND WRITE IT TO VIRTUAL + RET +GPUT ENDP + + ; ---- + ; PUTB + ; ---- + ; + ; SET ITEM [ARG2] IN BYTE-TABLE [ARG1] EQUAL TO [ARG3 (LSB)] + ; + PUBLIC GPUTB +GPUTB PROC + MOV AX,ARG1 ;TABLE BASE ADDRESS (WORDPOINTER) + MOV VMP,AX ;SET UP BASE ADDRESS + MOV VMP0,0 + MOV AX,ARG2 ;GET BYTE POINTER + CALL ADDVMP ;ADD BYTE OFFSET TO BASE ADDRESS + MOV AX,ARG3 ;GET VALUE + CALL PB@VMPI ;WRITE OUT THE BYTE + RET +GPUTB ENDP + + PAGE + ; ----- + ; INPUT + ; ----- + + ; IMPORTS: + ; [ARG1], [ARG2] optional + ; + ; IF [NARGS] INDICATES THAT THERE IS A [ARG2], THEN [ARG2] + ; IS A WORDPOINTER ADDRESS TO AN ACTIVE ICON TABLE. IN THIS + ; CASE, ITERATION IS PERFORMED. + ; + ; [ARG1] IS DECODED AS FOLLOWS: + ; 0 : IMMEDIATELY POLL THE KEYBOARD AND JOYSTICK ONCE + ; -int : PAUSE FOR [-int]/60 SEC. + ; int : POLL THE KEYBOARD FOR int/60 SEC. OR UNTIL A + ; KEYPRESS IS DETECTED + ; + ; EXPORTS: [VALUE] via PUTBYT [AL] + ; WHERE AL IS ENCODED AS FOLLOWS: + ; 8FH : NO KEYPRESS (NO INPUTS DETECTED) + ; +int : 7-BIT ASCII CHARACTER + ; -int : JOYSTICK DATA * + ; + ; *note See DIP SPECIFICATION for JOYSTICK DATA rules + + PUBLIC GINPUT +GINPUT PROC + MOV KEYSAV,8FH ;KEYSAV <= NO KEY FOUND + MOV AX,ARG1 ;GET ARGUMENT + MOV VALUE,AX ;MOVE [ARG1] INTO [VALUE] + + CMP NARGS,1 ;IF ONLY 1 ARG + JE DONTIT ; THEN DON'T ITERATE + JMP ITRATE ; ELSE, ITERATE +DONTIT: JMP NOIT +GINPUT ENDP + + +NOIT PROC + MOV AX,VALUE ;RECOVER THE SILLY ARG + OR AX,AX ;TEST IT AGAIN + JS DELAY ;IF NEGATIVE, THIS IS A DELAY REQUEST + JNZ TICK ;IF NON-ZERO, THEN ENTER SENSE LOOP +NOIT1: CALL SENSE ; ELSE, READ JUST ONCE +MOVED: JMP PUTBYT ;RETURN [AL] + + ; + ; PURPOSE: POLL THE KEYBOARD FOR int/60 SEC. OR UNTIL A + ; KEYPRESS IS DETECTED + ; + +TICK: CMP PCJR,1 ; DON'T DOUBLE VALUE IF jr + JE TICK1 ; SO SKIP IT + SHL VALUE,1 ; DOUBLE THE WAIT VALUE +TICK1: CALL SENSE ;GET A READING + CMP AL,10001111B ;ANY ACTIVITY? + JNE MOVED ;....YES. RETURN IT. + CMP IBMAT,FALSE ; ARE WE A FAST ONE + JE TICK3 + MOV CX,JIFCNT +TICK2: LOOP TICK2 ; WASTE SOME TIME +TICK3: DEC VALUE ;DECREMENT COUNT, DOES COUNT = 0? + JNZ TICK1 ;....NO, LOOP BACK AND TRY AGAIN + + ;THE CLOCK EXPIRED WITHOUT A READING +NOREAD: JMP PUTBYT + + ; + ; PROGRAMABLE DELAY + ; + ; PURPOSE: POLL THE KEYBOARD FOR [-int]/60 SEC. REPORT THE + ; FIRST DETECTED KEYPRESS IF ANY. + ; + ; ENTER: AX=[-INT] + ; + +DELAY: NEG VALUE ;CHANGE [-INT] TO [+INT] + CMP PCJR,1 ; DON'T SHIFT FOR PCjr + JE DELALP ; SKIP IT + SHL VALUE,1 ;DOUBLE DELAY TIME FOR RICK'S MISCALC +DELALP: CALL SENSE ;GET A READING + CMP KEYSAV,8FH ;ANY PREVIOUS ACTIVITY? + JNE DELA1 ;....YES + MOV KEYSAV,AL ;....NO, SAVE THE CURRENT READING +DELA1: CMP IBMAT,FALSE ;IS THIS A SLOW MACHINE? + JE DELA3 ;....YES + + MOV CX,JIFCNT ;IT'S A FAST MACHINE (AN IBM AT) +DELA2: LOOP DELA2 ; SO USE A DELAY LOOP TO COMPENSATE + +DELA3: DEC VALUE ;DECREMENT COUNT, DOES COUNT = 0? + JNZ DELALP ;....NO, LOOP BACK AND TRY AGAIN + + ;THE CLOCK EXPIRED + MOV AL,KEYSAV ;RETURN THE KEYCODE + JMP PUTBYT +NOIT ENDP + + ; --------------------------- + ; CHECK KEYBOARD AND JOYSTICK + ; --------------------------- + + PUBLIC SENSE +SENSE PROC + + ; CHECK KEYBOARD FIRST + MOV AH,6 ;SELECT DIRECT CONSOLE INPUT + MOV DL,0FFH ; WITHOUT ECHO + INT 21H ;MSDOS FUNCTION CALL + JZ STICK ;IF NO KEYPRESS, THEN CHECK STICK + ; ELSE WE GOT A KEYSTROKE + CMP AL,0DH ; (B5) CARRIAGE RETURN? + JE SENS2 + CMP AL,0 ; EXTENDED ASCII? + JNE SENS1 ; NOPE + MOV AH,CNOECHO ; READ THE EXTENDED CODE + INT 21H ; GET THE CHAR + SUB AL,71 ; BASIFY THE HOME KEY + CMP AL,10 ; UPPER LIMIT + JA STICK ; DON'T RETURN ANYTHING + MOV BX,OFFSET XLKEY ; TRANSLATE THE KEY + XLAT ; LOOK UP IN TABLE +SENS2: PUSH AX ; SAVE CHAR AND TURN ON NUMLOCK + PUSH ES + MOV AX,BIOSDATA ; SEG ADDRESS BIOS DATA AREA + MOV ES,AX + MOV BX,KB_FLAG ; OFFSET TO BIOS DATA FOR KEYS + OR BYTE PTR ES:[BX],NUMLOCK ; TURN ON NUMLOCK + POP ES + POP AX +SENS1: AND AL,01111111B ;7-BIT ASCII ONLY + RET + + ; CHECK THE JOYSTICK +STICK: TEST JOYSTK,1 ; IS THERE REALLY ONE THERE? + JNZ STICK1 ; ITS THERE, ONWARD + PUSH CX + MOV CX,JIFCNT-200H ; NUMBER OF INSTRUCTIONS CYCLES NOT EXECUTED +STICK$: LOOP STICK$ ; TAKE AS MUCH TIME AS WE WOULD HAVE + POP CX + MOV AL,8FH ; RETURN CENTER POSITION + RET +STICK1: MOV DX,201H ;DX ^ GAME PORT + MOV AL,10001111B ;INITIALIZE JOYSTICK ACTIVITY BYTE + MOV STICKA,AL ; TO INDICATE NO KEYPRESSES + + ;*********** PATCH ************************* + ;RET ;TO DISABLE JOYSTICK + ;******************************************* + + ;GET JOYSTICK X-POSITION + MOV AH,1 ;SELECT X-AXIS + CALL POSITN + MOV BL,STICKA ;GET THE JOYSTICK FLAGS + CMP AL,60H ;IS THE JOYSTICK TO THE RIGHT? + JB STK0 ;....NO + XOR BL,00001000B ;TURN OFF THE RIGHT BIT (NEGATIVE LOGIC) + JMP STK1 ;IF IT'S TO THE RIGHT, IT CAN'T BE TO THE LEFT + +STK0: CMP AL,30H ;IS THE JOYSTICK TO THE LEFT? + JAE STK1 ;....NO + XOR BL,00000100B ;TURN OFF THE LEFT BIT + +STK1: MOV STICKA,BL ;SAVE JOYSTICK FLAGS + + MOV AH,2 ;SELECT Y POSITION + CALL POSITN ;GET JOYSTICK POSITION + MOV BL,STICKA ;GET THE JOYSTICK FLAGS + CMP AL,60H ;IS THE JOYSTICK DOWN? + JB STK2 ;....NO + XOR BL,00000010B ;TURN OFF THE DOWN BIT (NEGATIVE LOGIC) + JMP STK3 ;IF IT'S DOWN, IT CAN'T BE UP + +STK2: CMP AL,30H ;IS THE JOYSTICK UP? + JAE STK3 ;....NO + XOR BL,00000001B ;TURN OFF THE UP BIT + +STK3: MOV STICKA,BL + IN AL,DX ;READ SWITCH INPUTS + MOV AH,AL ;SAVE IT IN [AH] + AND AL,10H ;IS BUTTON 1 DEPRESSED? + JNZ STK3A ;....NO + MOV BL,STICKA ;....YES + OR BL,00010000B ;TURN ON THE BUTTON BIT + +STK3A: AND AH,20H ;IS BUTTON 2 DEPRESSED? + JNZ STK4 ;....NO + MOV BL,STICKA ;....YES + OR BL,00010000B ;TURN ON THE BUTTON BIT + +STK4: MOV AL,BL ;RETURN THE VALUE IN AL + RET +SENSE ENDP + + + ; + ; GET JOYSTICK ANALOG POSITION + ; + + ; + ; AXIS SELECTED WITH AH + ; 1= X AXIS + ; 2= Y AXIS + ; + + ; A DIFFERENT ROUTINE IS PROVIDED FOR IBM AND IBM AT + +POSITN PROC + PUSH CX + + IN AL,61H ;GET PORT DATA + PUSH AX ; AND SAVE IT + CLI ;CLEAR INTERRUPTS + + SUB CX,CX ;SET LOOP CONTROL VALUE = 0 + OUT DX,AL ;START THE TIMING + +POSX1: IN AL,DX ;GET STATE + TEST AL,AH ;WE'RE INTERESTED IN THE BIT IN AH + LOOPNE POSX1 ;LOOP UNTIL THE BIT COMES BACK ON + + ; IS THIS AN IBM AT? + CMP IBMAT,TRUE + JNE POSX2 + SAR CX,1 + +POSX2: SUB AX,AX + SUB AX,CX ;DETERMINE COUNT + + CMP AX,255 + JBE POSX3 + MOV AX,255 + + ;EQUALIZATION +POSX3: PUSH AX + + ; IS THIS AN IBM AT? + CMP IBMAT,TRUE + JNE POSX4 + SHL CX,1 + +POSX4: AND CX,01FFH +EQ1: IN AL,DX + TEST AL,AH + LOOP EQ1 + POP CX + + POP AX ;RESTORE INTERRUPT STATUS + OUT 61H,AL ; THE PORT VALUE + STI ;ENABLE INTERRUPTS + + MOV AX,CX ;RESTORE JOYSTICK VALUE + POP CX + RET +POSITN ENDP + +extrn DUMP:near +extrn DMPMSK:near + + PAGE + ; ------ + ; GSHOWN + ; ------ + + ; DISPLAY NEGATIVE ICON [ARG3] AT X=[ARG1], Y=[ARG2] + PUBLIC GSHOWN +GSHOWN PROC + MOV NEGATE,0FFH ;ENABLE NEGATE + JMP SHOWI ; AND DO A SHOWI +GSHOWN ENDP + + ; ------ + ; GSHOWI + ; ------ + + ; DISPLAY POSITIVE ICON [ARG3] AT X=[ARG1], Y=[ARG2] + PUBLIC GSHOWI +GSHOWI PROC + MOV NEGATE,0 ;DISABLE NEGATE + + ; AND FALL THROUGH ............. + +GSHOWI ENDP + + ; ----- + ; SHOWI + ; ----- + + ; CODE COMMON TO GSHOWI AND GSHOWN + ; DISPLAY ICON [ARG3] AT X=[ARG1], Y=[ARG2] + ; IF [ARG4] IS GIVEN, IT POINTS TO THE MASK TO BE USED + PUBLIC SHOWI +SHOWI PROC + MOV MSKFLG,0 ;DISABLE MASKING UNTIL FURTHER NOTICE + CMP NARGS,3 + JE NOMASK ;IF ONLY 3 ARGS, THEN DON'T MASK + + ; {CASE} MASK + MOV AX,ARG4 ;GET MASK INFO + CALL ISU ; THIS ENTRYPOINT WILL PROVIDE: + ; ICON[ARG4] DATA V-ADDR IN [IADR2] + ; X-SIZE IN [IX2] + ; Y-SIZE IN [IY2] + + ; ICON[ARG3] DATA V-ADDR IN [IADR1] + ; X-SIZE IN [IX1] AND [XDEX1] + ; Y-SIZE IN [IY1] AND [YDEX1] + ; ASSIGNED BLOCKSET IN [BSET] + + MOV AL,IX1 ;IF WIDTH AND HEIGHT ARE NOT THE SAME + CMP AL,IX2 ; THEN DO NOTHING + JNE DRAWEX + MOV AL,IY1 + CMP AL,IY2 + JNE DRAWEX + + DEC MSKFLG ;ELSE SET MSKFLG [0FFH] + JB ITENT ; YES, THIS IS AN UNCONDITIONAL JUMP + + ; {CASE} NO MASKING + ; SET UP ICON [ARG3] +NOMASK: MOV AX,ARG3 ;GET THE V-ADDRESS OF THE ICON + CALL GETI ; AND SET IT UP + + ; ICON DATA V-ADDR IN [IADR1] + ; X-SIZE IN [IX1] AND [XDEX1] + ; Y-SIZE IN [IY1] AND [YDEX1] + ; ASSIGNED BLOCKSET IN [BSET] + + ; AND FALL THROUGH ............. + +SHOWI ENDP + + PUBLIC ITENT,DRAWEX,DRAWI1,DRAWI2,DRAWI3,DRAWI4 + PUBLIC DRAWI5,DRAWE2,DRAWIA,DRAWI8,DRAWI9,DRAWIB + PUBLIC DRAWIC,DRAWID,DRAW,DRAW1,DRAW2A,CLPRI2 +ITENT PROC + MOV AL,0 ; INITIALIZE VARIABLES + MOV TOPCUT,AL + MOV SIDCUT,AL + MOV MDXCUT,AL + + ; DETERMINE IF THE ICON CAN BE LEGALLY DRAWN + ; FROM THE STANDPOINT OF IT'S Y-POSITION + MOV AX,ARG2 ;GET ICON Y-POSITION + OR AH,AH ; IF MSB=0 + JZ DRAWI1 ; THEN ICON STARTS ON WINDOW PAGE + + CMP AH,0FFH ; IF ICON Y-POS MSB <> 0 AND <> 0FFH + JNE DRAWEX ; THEN ICON WILL NOT BE DISPLAYED + + ; {CASE 1} ICON STARTS ABOVE WINDOW PAGE (MSB = 0FFH) + ; DETERMINE TOP CLIP + ; FIND ICON Y1 - WINDOW Y1 + MOV BL,WINDY1 ;GET UPPER EDGE OF WINDOW + SUB BH,BH ;WORDIFY + NEG AX ;SINCE IT'S (-) WE GET TWO'S COMPLIMENT + ADD AX,BX ; AND ADD TO GET THE ABSOLUTE DISTANCE + OR AH,AH + JZ DRAWI2 ;IF DISTANCE LE. 255 THEN CONTINUE + ; ELSE DEPART +DRAWEX: RET + + ; {CASE 2} ICON STARTS ON WINDOW PAGE (MSB = 00H) + ; DETERMINE IF A TOPCLIP IS NECESSARY +DRAWI1: MOV AL,WINDY1 ;FIND WINDOW Y1 - ICON Y1 + MOV BL,BYTE PTR ARG2 + SUB AL,BL ;IF (-) THEN ICON STARTS BELOW TOP EDGE + JNS DRAWI2 ; OF WINDOW + + ; {CASE 2A} THE ICON TOPEDGE LIES ON OR BELOW THE WINDOW TOPEDGE + ; NO TOPCUT IS NECESSARY + ; [WINDY2] = LAST LINE OF THE WINDOW TO DISPLAY +DRAWI3: MOV AL,WINDY2 ;FIND WINDY2 - ICON Y1 [BL] + INC AL + SUB AL,BL ;GET DISTANCE + JS DRAWEX ;EXIT IF (-) THE WHOLE ICON IS BELOW THE WINDOW + + ; COMPARE SIZE OF THE DISPLAYABLE AREA ((WINDY2 + 1) - ICON Y1) + ; AND THE ICON HEIGHT + CMP AL,IY1 ;IF SIZE OF DISPLAYABLE AREA GE.ICON HEIGHT + JAE DRAWI4 ; THEN DON'T BOTHER CHANGING ICON HEIGHT + MOV IY1,AL ; ELSE, SUBSTITUTE SIZE OF THE DISPLAYABLE + JMP DRAWI4 ; AREA FOR THE ICON HEIGHT (BOTTOM CUT) + +DRAWI2: MOV TOPCUT,AL ;SAVE AMOUNT TO CUT FROM TOP OF ICON + + ;DO THE TOPCUT +DRAWI4: MOV AL,IY1 ;GET HEIGHT OF ICON + SUB AL,TOPCUT ;DO TOPCUT + JBE DRAWEX ;NO ICON LEFT TO DRAW SO EXIT + + MOV YDEX1,AL + SUB AL,WINDH ;IF THE ICON IS SMALLER THAN THE WINDOW + JB DRAWI5 ; THEN DISPLAY ALL OF IT + + MOV AL,WINDH ; ELSE, DISPLAY A WINDOW'S WORTH OF ICON + MOV YDEX1,AL + + ; MULTIPLY TOPCUT AND ICON WIDTH, ADD PRODUCT TO ICON POINTER + ; IN ORDER TO POINT AT THE START OF THE FIRST DISPLAYED ROW +DRAWI5: MOV AL,BYTE PTR ARG2 ;CHANGE ICON STARTING YPOS + ADD AL,TOPCUT ;TO REFLECT TOPCUT + MOV BYTE PTR YPOS,AL + + MOV AL,TOPCUT + MOV BL,IX1 + MUL BL ;AX=TOPCUT * ICON WIDTH + PUSH AX ;SAVE TOPCUT + CALL AIADR1 ;IADR1 <= IADR1 + TOPCUT + POP AX ;RESTORE TOPCUT + CMP MSKFLG,0 ;IS MASKING DISABLED? + JE NOMSK1 ;....YES + CALL AIADR2 ;....NO. IADR2 <= IADR2 + TOPCUT + + ;COMPUTE THE DISPLAYED WIDTH AND THE IXSKIP +NOMSK1: MOV AL,IX1 ;KLUDGE + MOV MDXCUT,AL + + MOV AX,ARG1 ;GET ICON X-COORDINATE + OR AH,AH ;IF MSB = 0 + JZ DRAWI8 ; THEN ICON STARTS ON WINDOW PAGE + + CMP AH,0FFH ; ELSE, IF MSB <> 0FFH + JNE DRAWE2 ; THEN WE MIGHT AS WELL GO HOME + + ; {CASE} ICON STARTS BEFORE WINDOW PAGE (MSB = 0FFH) + ; DETERMINE LEFT CLIP + ; FIND ICON X1 - WINDOW X1 + MOV BL,WINDX1 ;GET LEFT EDGE OF WINDOW + SUB BH,BH + NEG AX ;SINCE IT'S NEG, WE CHANGE THE SIGN + ADD AX,BX ; AND GET THE ABSOLUTE DISTANCE + OR AH,AH + JZ DRAWI9 ;IF d <= 255 THEN CONTINUE + +DRAWE2: RET + +DRAWIA: MOV AL,WINDX2 + INC AL + SUB AL,BYTE PTR ARG1 ;GET DISTANCE + JS DRAWE2 + CMP AL,IX1 ;COMPARE WITH WIDTH + JAE DRAWIB + MOV IX1,AL + JMP DRAWIB + +DRAWI8: MOV AL,WINDX1 + MOV BL,BYTE PTR ARG1 + SUB AL,BL + JS DRAWIA + +DRAWI9: MOV SIDCUT,AL + + ;DO THE SIDCUT +DRAWIB: MOV AL,IX1 ;GET WIDTH + SUB AL,SIDCUT + JBE DRAWE2 + + MOV XDEX1,AL + SUB AL,WINDW + JB DRAWIC + + MOV AL,WINDW + MOV XDEX1,AL + +DRAWIC: MOV AL,SIDCUT + SUB AH,AH + PUSH AX ;SAVE SIDECUT + CALL AIADR1 ;IADR1 <= IADR1 + SIDCUT + POP AX ;RESTORE SIDCUT + CMP MSKFLG,0 ;IS MASKING DISABLED? + JE DRAWID ;....YES + CALL AIADR2 ;....NO. IADR2 <= IADR2 + SIDCUT + +DRAWID: MOV AL,MDXCUT + SUB AL,XDEX1 + MOV IXSKIP,AL + + MOV AL,XDEX1 + MOV IX1,AL ;SET COUNTER REFRESH VALUE + + MOV AL,BYTE PTR ARG1 + ADD AL,SIDCUT + MOV BYTE PTR XPOS,AL + MOV BYTE PTR XPSAV,AL + + ;GET THE REQUIRED BLOCKSET DATA + MOV AL,BSET ;USE THE BLOCKSET ID + + ; GET THE ADDRESS OF THE CURRENT BLOCKSET + MOV BX,BTAB ;GET THE BASE ADDRESS OF THE BPT + MOV VMP,BX ;SET UP VMP + MOV VMP0,0 + SUB AH,AH ;AL CONTAINS BLOCKSET ID + DEC AL ;ZERO ALIGN IT + ADD VMP,AX ;ADD WORD INDEX TO BASE ADDRESS + CALL GW@VMP ;GET THE BLOCKSET POINTER + MOV VMP,AX ;SET UP VMP + MOV VMP0,0 + + CALL GW@VMPI + MOV BLKLEN,AH ;# BYTES PER BLOCK + MOV BSIZE,AL ;# OF BLOCKS + + MOV BX,VMP ;MOVE V-ADDR OF BLOCKSET DATA + MOV BSADR,BX ;INTO [BSADR] + + ;CHECK FOR MASKING + CMP MSKFLG,0 ;IS MASKING DISABLED? + JE DRAW ;....YES. USE NORMAL DRAW ROUTINE + JMP DOMASK ; ELSE, GO DO THE MASK DRAW ROUTINE + + ; + ; DRAW THE ICON ITERATION AT [IADR1] + ; + + ; DRAW A ROW OF ICON BLOCKS +DRAW: PUSH DI ; (B5) SAVE GSTACK + CALL SETIADR ; (B5) SET UP SI AND GET BLOCK ID + CALL GTGBLK ;GET GRAPHICS BLOCK [AL] INTO BLOCK + CMP FSIZE,0 ; (B5) SET UP DI ACCORDING TO REAL MEMORY + JE DRW0 + +DRW: MOV DI,BSADR ; (B5) GET ADDRESS OF THE BLOCK SET + SHL DI,1 ; (B5) CONVERT TO A REAL ADDR + +DRW0: CMP FSIZE,0 ; (B5) CALCULATE END-OF-PAGE + JNE DRW1 ; (B5) FITS - EOP AT END OF SEG + MOV AX,SI ; (B5) GET I-PAGE + AND AX,0FE00H ; (B5) ISOLATE BLOCK BITS + ADD AX,200H ; (B5) ADD PAGE LENGTH TO GET EOP + MOV I_EOP,AX ; (B5) SAVE IT + JMP DRW2 + +DRW1: MOV I_EOP,0 + MOV G_EOP,0 ; (B5) SET EOPAGES TO END OF SEGMENT + +DRW2: MOV AH,BYTE PTR XPOS ; (B5) GET XPOSITION + MOV AL,BYTE PTR YPOS ; (B5) AND Y + MOV CL,YDEX1 ; (B5) SET UP Y INDEX + MOV BL,XDEX1 ; (B5) SET UP X INDEX + JMP DRW3 + +FIX_I: CMP FSIZE,0 ; (B5) DECIDE WHICH TYPE OF FIX + JNE FXI3 + MOV BYTE PTR XPOS,AH ; (B5) SAVE VARS + MOV BYTE PTR YPOS,AL + MOV YDEX1,CL + MOV XDEX1,BL + MOV AX,IADR1 ; (B5) GET STARTING ADDRESS + AND AX,7F00H ; (B5) ISOLATE BLOCK BITS + ADD AX,100H ; (B5) AND ADVANCE TO NEXT BLOCK + MOV IADR10,0 ; (B7) SET THIS + TEST SI,1 ; (B7) EVEN? + JZ FXI2 + MOV IADR10,1 ; (B7) NOPE, ODD +FXI2: AND SI,1FEH ; (B5) ISOLATE WRAP VALUE + SHR SI,1 ; (B7) ALIGN WITH IADR1 IN AX + OR AX,SI ; (B5) AND MAKE THEM COUNT HERE + MOV IADR1,AX ; (B5) SAVE VIRTUAL PAGE + CALL SETIADR ; (B5) GET ICON ID AND RESET SI + CALL GTGBLK ; (B5) GET A GRAPHIC BLOCK + JMP DRW0 + +FXI3: ADD BP,1000H + JMP DRW$ + +DRAW$: POPF + JC FIX_I + CMP FSIZE,0 ; (B5) NO END OF PAGE IF FITS + JNE DRW$ + CMP SI,I_EOP ; (B5) CHECK END CONDITIONS + JAE FIX_I +DRW$: XCHG AX,DX ; (B5) SAVE X,Y + PUSH ES ; (B5) NO, SAVE IT + MOV ES,BP ; (BP) AND MAKE ADDRESSIBLE + MOV AL,ES:[SI] ; (B5) GET BYTE + POP ES + PUSH ES ; (B5) SAVE IN CASE OF CHANGE + CALL GTGFST ; (B5) GET IT DIRECTLY UNLESS SEG WRAP + POP ES + XCHG AX,DX ; (B5) RESTORE X,Y + + ; FALL THROUGH INTO DUMP LOOP + +DRW3: PUSH AX + PUSH BX + PUSH CX + PUSH BP + PUSH SI + PUSH ES + CALL DUMP ; (B5) DUMP SAVES DI + POP ES + POP SI + POP BP + POP CX + POP BX + POP AX + + ; UPDATE THE COLUMN COUNT +DRAW1: DEC BL ;DECREMENT THE COLUMN COUNTER + JZ CLPRI2 ; IF WE'RE OUT OF COLUMNS, DO NEXT ROW + + INC AH ; ELSE, INCREMENT X COORDINATE + + ; UPDATE THE BLOCK ID POINTER +DRAW2A: INC SI ; (B5) NEXT ICON BYTE + PUSHF ; (B5) SAVE FLAGS FOR ZERO + JMP DRAW$ ; AND DRAW THE NEXT ICON BYTE + + ; NEXT ROW + ; REFRESH THE COLUMN COUNTER +CLPRI2: MOV BL,IX1 + + ; REFRESH THE X-COORDINATE + MOV AH,BYTE PTR XPSAV + + ; SKIP BLOCK #'S THAT AREN'T DRAWN AND UPDATE POINTER + MOV DL,IXSKIP + SUB DH,DH + INC DX + + ;IADR1 <= IADR1 + IXSKIP + 1 + +ITEN1: ADD SI,DX ; (B5) ADD IN SKIP VALUE + PUSHF + ; UPDATE THE ROW COUNTER + INC AL ;INCREMENT THE Y-COORDINATE + DEC CL ;DECREMENT ROW COUNTER + JNZ DRAW$ ; LOOP UNTIL ALL ROWS ARE DONE + POPF + POP DI + RET +ITENT ENDP + + + PUBLIC SETIADR +SETIADR PROC + MOV AX,IADR1 ;POINT [VMP] TO CURRENT BLOCK ID + MOV VMP,AX + MOV AL,IADR10 + MOV VMP0,AL + CALL GB@VMP ;GET THE BLOCK ID INTO AL + + MOV BP,ES ; (B5) SAVE SEG + MOV CL,LOC ; (B5) GET LAST EFFECTIVE ADDRESS + XOR CH,CH ; (B5) DO CONVERSION + SHL CX,1 ; (B5) DOUBLE VPAGE + MOV BX,LADD ; (B5) GET LOW ADDRESS BITS + OR BH,CL ; (B5) OR IN HIGH BITS + MOV SI,BX ; (B5) SAVE ICON ADDRESS + RET +SETIADR ENDP + + + ; + ; DRAW THE ICON ITERATION AT [IADR1] WITH MASK AT [IADR2] + ; +DOMASK PROC + MOV AX,IADR2 ;POINT [VMP] TO THE NEXT MASK BLOCK ID + MOV VMP,AX + MOV AL,IADR20 + MOV VMP0,AL + + MOV AL,NEGATE ;SAVE NEGATE STATUS + PUSH AX + + MOV NEGATE,0 ;NEVER NEGATE THE MASK + + CALL GB@VMP ;GET MASK BLOCK ID + CALL GTGBLK ;GET MASK GRAPHICS BLOCK [AL] INTO BLOCK + + ; COPY [BLOCK] INTO [MASK] + MOV CX,8 ;LOAD LOOP COUNTER + SUB BX,BX ;RESET INDEX + +B2MLP: MOV AL,BLOCK[BX] + MOV MBLOCK[BX],AL + INC BX + LOOP B2MLP + + MOV AX,IADR1 ;POINT [VMP] TO CURRENT ICON BLOCK ID + MOV VMP,AX + MOV AL,IADR10 + MOV VMP0,AL + + POP AX ;RESTORE NEGATE + MOV NEGATE,AL + + CALL GB@VMP ;GET THE BLOCK ID INTO AL + CALL GTGBLK ;GET GRAPHICS BLOCK [AL] INTO BLOCK + + MOV AH,BYTE PTR XPOS ;GET THE X-COORDINATE + MOV AL,BYTE PTR YPOS ; AND THE Y-COORDINATE + + ; DRAW [BLOCK] AGAINST [MASK] AT X,Y [AX] + CALL DMPMSK + + ; UPDATE THE COLUMN COUNT + DEC XDEX1 ;DECREMENT THE COLUMN COUNTER + JZ CLPRIA ; IF WE'RE OUT OF COLUMNS, DO NEXT ROW + + INC BYTE PTR XPOS ; ELSE, INCREMENT X COORDINATE + + ; UPDATE THE ICON BLOCK ID POINTER + XOR IADR10,1 ;CHANGE THE STATE OF BIT0 + JNZ DM1 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC IADR1 ;ELSE BUMP THE REST OF IADR1 + + ; UPDATE THE MASK BLOCK ID POINTER +DM1: XOR IADR20,1 ;CHANGE THE STATE OF BIT0 + JNZ DM2 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC IADR2 ;ELSE BUMP THE REST OF IADR2 +DM2: JMP DOMASK + + ; NEXT ROW + ; REFRESH THE COLUMN COUNTER +CLPRIA: MOV AL,IX1 + MOV XDEX1,AL + + ; REFRESH THE X-COORDINATE + MOV AL,BYTE PTR XPSAV + MOV BYTE PTR XPOS,AL + + ; SKIP BLOCK #'S THAT AREN'T DRAWN AND UPDATE THE POINTERS + MOV AL,IXSKIP + SUB AH,AH + INC AX ; +1 TO UPDATE THE POINTERS + PUSH AX ;SAVE IXSKIP + 1 + CALL AIADR1 ;IADR1 <= IADR1 + IXSKIP + 1 + POP AX ;RESTORE IXSKIP + 1 + CALL AIADR2 ;IADR1 <= IADR1 + IXSKIP + 1 + + ; UPDATE THE ROW COUNTER + INC BYTE PTR YPOS ;INCREMENT THE Y-COORDINATE + DEC YDEX1 ;DECREMENT ROW COUNTER + JZ DOMA1 ;EXIT WHEN DONE + JMP DOMASK ; ELSE, LOOP +DOMA1: RET +DOMASK ENDP + + PAGE + ; ---- + ; SETI + ; ---- + + ; COPY ICON [ARG3] INTO ICON [ARG4] WITH + ; TOP LEFT CORNER AT X=[ARG1], Y=[ARG2]; + ; RETURN "0" IF RANGE ERROR, "1" IF OKAY + PUBLIC GSETI,SI0,SI1,SI3 +GSETI PROC + CALL ISETUP + + ;GET STATS OF SOURCE AND DESTINATION + CALL DOFIT ;WILL THE SOURCE FIT IN THE DESTINATION? + JNC SIA ;CARRY CLEAR IF OK + JMP RET0 ;ELSE RETURN A ZERO + + ; [GPC] WILL BE TEMPORARILY USED FOR AN AUTOINCREMENTING + ; VIRTUAL MEMORY POINTER +SIA: MOV AX,GPC ;PUSH [GPC] ON THE STACK + PUSH AX + + MOV AL,GPC0 ;PUSH GPC BIT ON THE STACK + PUSH AX + + ; VMP POINTS TO THE FIRST BYTE OF THE SOURCE ICON + ; POINT [GPC] AT THE FIRST BYTE OF THE SOURCE ICON + MOV AX,VMP + MOV GPC,AX + MOV AL,VMP0 + MOV GPC0,AL + + ; POINT [VMP] AT THE CURRENT BYTE OF THE DESTINATION SUB-ICON +SI0: MOV AX,IADR2 + MOV VMP,AX + MOV AL,IADR20 + MOV VMP0,AL + +SI1: CALL GB@GPCI ;GET A BYTE FROM THE SOURCE + CALL PB@VMPI ;PUT IT IN THE DESTINATION + DEC XDEX1 ;OUT OF SOURCE X'S YET? + JNZ SI1 ;....NO. MOVE ANOTHER BYTE + MOV AL,IX1 ;REFRESH COLUMN COUNTER + MOV XDEX1,AL + + MOV AL,BYTE PTR IX2 ;GET X-SIZE OF DESTINATION + SUB AH,AH ;ADD TO BASE ADDRESS OF SUB-ICON + CALL AIADR2 ;IADR2 <= IADR2 + [AX] + ;TO GET ADDRESS OF NEXT SUB-ROW + +SI3: DEC YDEX1 ;OUT OF Y'S YET? + JNZ SI0 ;....YES. RESET X-INDEX + ; AND LOOP TILL EMPTY + + ; RESTORE GPC + POP AX + MOV GPC0,AL + POP AX + MOV GPC,AX + + MOV AL,1 ;RETURN A 1 FOR SUCCESS + JMP PUTBYT +GSETI ENDP + + PAGE + ; ----- + ; SWAPI + ; ----- + + ; SAME AS "SETI" EXCEPT ICON [ARG4] SUB-DATA IS COPIED + ; BACK INTO ICON [ARG3] + + PUBLIC GSWAPI,GSW0,GSW1,GSW2,PRERR2 +GSWAPI PROC + CALL ISETUP ;SETUP ICON + + ; SOURCE ICON MUST BE IN PRELOAD + MOV AX,IADR1 ;GET ICON ADDRESS + CMP AX,IPURE ;IS SOURCE IN I-PRELOAD? + JB GSW0 ;....YES. SO CONTINUE + + ; *** ERROR #14: PURITY VIOLATION (SETI/SWAPI) *** +PRERR2: MOV AL,14 + JMP GERROR + + ; SOURCE ICON MUST BE NO LARGER THAN THE DESTINATION ICON +GSW0: CALL DOFIT ;WILL IT FIT IN THE DESTINATION + JNC GSW1 ;CARRY IS CLEAR IF OK + JMP RET0 ;ELSE RETURN A ZERO + + ; SWAP ICONS + ; [GPC] WILL BE TEMPORARILY USED FOR AN AUTOINCREMENTING + ; VIRTUAL MEMORY POINTER +GSW1: MOV AX,GPC ;PUSH [GPC] ON THE STACK + PUSH AX + + MOV AL,GPC0 ;PUSH GPC BIT ON THE STACK + PUSH AX + + ; SET UP OUTER LOOP + ; POINT [GPC] AT THE SOURCE ICON +GSW2: MOV AX,IADR1 + MOV GPC,AX + MOV AL,IADR10 + MOV GPC0,AL + + ; POINT [VMP] AT THE DESTINATION ICON + MOV AX,IADR2 + MOV VMP,AX + MOV AL,IADR20 + MOV VMP0,AL + + ; INNER LOOP +GSW3: CALL GB@GPC ;GET A BYTE FROM THE SOURCE + MOV BL,AL ;SAVE IT TEMPORARILY + + CALL GB@VMP ;GET DESTINATION BYTE + CALL PB@GPCI ;PUT IT IN THE SOURCE + ; AND INCREMENT GPC + + MOV AL,BL ;RETRIEVE ORIGINAL SOURCE BYTE + CALL PB@VMPI ;PUT IT IN THE DESTINATION + ; AND INCREMENT THE VMP PTR + + ; TEST INNER LOOP + DEC XDEX1 ;OUT OF SOURCE X'S YET? + JNZ GSW3 ;....NO. MOVE ANOTHER BYTE + + ; REFRESH INNER LOOP VARIABLES + MOV AL,IX1 ;REFRESH COLUMN COUNTER + MOV XDEX1,AL + + ; UDATE SOURCE AND DESTINATION ADDRESSES + MOV AL,BYTE PTR IX2 ;ADD X-SIZE OF DESTINATION + SUB AH,AH ; TO BASE ADDRESS OF SUB-ICON + CALL AIADR2 ;TO GET ADDRESS OF NEXT ROW + + MOV AL,BYTE PTR IX1 ;ADD X-SIZE OF SOURCE + SUB AH,AH ; TO BASE ADDRESS OF SOURCE + CALL AIADR1 ;TO GET ADDRESS OF NEXT ROW + + ; TEST OUTER LOOP + DEC BYTE PTR YDEX1 ;OUT OF Y'S YET? + JNZ GSW2 ; NO, RESET ROW INDEX AND LOOP + + ;RESTORE THE GPC + POP AX + MOV GPC0,AL + POP AX + MOV GPC,AX + + ;SET UP RETURN VALUE + MOV AL,1 ;RETURN A 1 FOR SUCCESS + JMP PUTBYT +GSWAPI ENDP + + PAGE + ; ----- + ; SOUND + ; ----- + + ; PLAY SOUND [ARG1] (1-127) + PUBLIC GSOUND +GSOUND PROC + MOV AX,ARG1 + OR AX,AX + JZ SNDERR ;RANGE ERROR + JS SNDERR ;RANGE ERROR + CMP AX,NSNDS + 1 + JAE SNDERR ;SOUND NOT DEFINED + DEC AX + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET SOUNDLIST PTR + MOV SI,DS:[BP+STABLE] + CALL SI ;CALL THE SOUND ROUTINE + RET +GSOUND ENDP + + PUBLIC SNDERR +SNDERR PROC + ; *** ERROR #13: ILLEGAL SOUND EFFECT *** +; MOV AL,0DH +; JMP GERROR + +; CHANGE MADE PER LIM'S REQUEST + CALL SND1 + CALL SND4 + CALL SND1 + CALL SND4 + RET +SNDERR ENDP + + ; + ; ACTUAL SOUND EFFECTS + ; + PUBLIC SND1 + ;BOOP +SND1 PROC + MOV CX,500 ;FREQ + MOV DX,7 ;DURATION * .05 SEC + JMP TONE +SND1 ENDP + + PUBLIC SND2 + ;CLICK +SND2 PROC + MOV CX,3000 ;FREQ + MOV DX,1 ;DURATION * .05 SEC + JMP TONE +SND2 ENDP + + PUBLIC SND3 + ;TING +SND3 PROC + MOV CX,2600 ;FREQ + MOV DX,5 ;DURATION * .05 SEC + JMP TONE +SND3 ENDP + + PUBLIC SND4 + ;RAZZ +SND4 PROC + MOV CX,120 ;FREQ + MOV DX,20 ;DURATION * .05 SEC + JMP TONE +SND4 ENDP + + PAGE + ; ---- + ; RAND + ; ---- + + ; RETURN A RANDOM VALUE BETWEEN 1 AND [ARG1] + PUBLIC GRAND +GRAND PROC + MOV AX,ARG1 + SUB AH,AH ; HACK RANDOM TO ONE BYTE + MOV RTEMP,AX ; SAVE ARGUMENT FOR LATER + MOV AX,RSEED1 + MOV BX,RSEED2 + MOV RSEED2,AX + CLC + RCR AX,1 + RCR BX,1 + XOR RSEED1,BX ;PUT XOR'D NUBMER INTO RSEED1 + MOV AX,RSEED1 ;THIS IS RANDOM VALUE + AND AX,0EFFFH ;CHOP HIGH BIT FOR DIVIDE + SUB DX,DX ;CLEAR MOST SIGN. PORTION OF 32 BIT WORD + DIV RTEMP ;DIVIDE WORD BY WORD + MOV AX,DX ;MOVE REMAINDER INTO AX + INC AX ;MAKE SURE NO ZERO + MOV VALUE,AX ;SAVE IT IN VALUE + JMP PUTVAL +GRAND ENDP + + PAGE + ; ------ + ; WINDOW + ; ------ + + ; SET THE WINDOW LIMITS TO THE RECTANGLE WHOSE UPPER LEFT SCREEN + ; COORDINATE IS AT (locx1, locy1) AND LOWER RIGHT SCREEN COORDINATE + ; IS AT (locx2, locy2). + + PUBLIC GWIND,WISK0,WISK1,WISK2,WISK3,WISK4 + PUBLIC WISK5,WISK6,WISK7,WISK8 +GWIND PROC + SUB BX,BX ;RESET INDEX + + ;TEST IF - OR > 255 +WISK0: MOV AX,WORD PTR ARG1[BX] ;GET COORDINATE + OR AH,AH ;DOES MSB=0? + JZ WISK1 ;....YES. COORDINATE IS EITHER + OR 0 + SUB AX,AX ;ELSE IT'S NEGATIVE + MOV WORD PTR ARG1[BX],0 ; CLIP IT TO 0 + + ;IT'S EITHER + OR 0 +WISK1: PUSH BX ;SAVE INDEX + AND BX,2 ;IS IT AN X OR Y COORDINATE? + POP BX ;RESTORE INDEX + JZ WISK2 ;IT'S AN X-COORDINATE + + ;Y COORDINATE CLIPPING + CMP AX,23 ;IS THE Y-COORDINATE ON SCREEN? + JBE WISK3 ;....YES + MOV ARG1[BX],23 ;....NO. CLIP IT + JMP WISK3 + + ;X COORDINATE CLIPPING +WISK2: CMP AX,39 ;IS THE X-COORDINATE ON SCREEN? + JBE WISK3 ;....YES + MOV ARG1[BX],39 ;....NO. CLIP IT + +WISK3: INC BL ;UPDATE INDEX TO POINT + INC BL ;AT THE NEXT ARG + CMP BL,8 ;HAVE WE DONE ALL OF THE ARGS + JNZ WISK0 ;....NO. KEEP LOOPING + + ; SWITCH X-COORDINATES IF REQUIRED +WISK4: MOV AL,BYTE PTR ARG1 ;GET X1 + MOV AH,BYTE PTR ARG3 ;GET X2 + CMP AL,AH ;IF X1 < X2 + JL WISK5 ; THEN DON'T SWAP + XCHG AL,AH ;SWAP X1 AND X2 + +WISK5: MOV BYTE PTR WINDX1,AL ;SAVE X1 + MOV BYTE PTR WINDX2,AH ;SAVE X2 + + ;COMPUTE WINDOW WIDTH + SUB AH,AL ;WINDW = WINDX2 - WINDX1 + 1 + INC AH + MOV WINDW,AH + + ; SWITCH Y-COORDINATES IF REQUIRED +WISK6: MOV AL,BYTE PTR ARG2 ;GET Y1 + MOV AH,BYTE PTR ARG4 ;GET Y2 + CMP AL,AH ;IF Y1 > Y2 + JL WISK7 ; THEN DON'T SWAP + XCHG AL,AH ;SWAP Y1 AND Y2 + +WISK7: MOV BYTE PTR WINDY1,AL ;SAVE Y1 + MOV BYTE PTR WINDY2,AH ;SAVE Y2 + + ;COMPUTE WINDOW HEIGHT +WISK8: SUB AH,AL ;WINDH = WINDY2 - WINDY1 + 1 + INC AH + MOV WINDH,AH + RET +GWIND ENDP + + PAGE + ; ----- + ; GITER + ; ----- + ; + ; INITIALIZE ITERATION TABLE AT WORD ADDRESS ARG1 + ; + +GITER PROC + MOV AX,ARG1 ;POINT TO TABLE BASE ADDRESS + MOV VMP,AX + MOV VMP0,0 + + CALL GB@VMPI ;[BYTE0] NUMBER OF ENTRIES IN TABLE + MOV ITICN,AL + + MOV AL,1 ;[BYTE1] SET CURRENT ENTRY=1 + CALL PB@VMPI + + ; WE'RE POINTING TO THE DATA STRUCTURE OF THE FIRST ENTRY + ; AND SUCCEEDING ENTRIES +GITER1: CALL GW@VMPI ;GET THE ICON WORD-PTR ADDRESS IN [AX] + + ; SAVE VIRTUAL MEMORY POINTER + MOV BX,VMP + PUSH BX + MOV BL,VMP0 + PUSH BX + + CALL GETI ;GET THE ICON INFORMATION + + ; RESTORE VIRTUAL MEMORY POINTER + POP BX + MOV VMP0,BL + POP BX + MOV VMP,BX + + ; SKIP ICON'S HORIZONTAL AND VERTICAL POSITION + ADD VMP,2 ;TWO WORDS + + ; SET UP REMAINING DATA + SUB AL,AL ;NEGATE=0 FOR POSITIVE IMAGE + CALL PB@VMPI + + MOV AL,1 ;CURRENT ITERATION=1 + CALL PB@VMPI + + MOV AL,BSET ;SAVE BLOCKSET IDENTIFIER + CALL PB@VMPI + + MOV AL,ITERS ;SAVE NUMBER OF ITERATIONS + CALL PB@VMPI + + MOV AL,IX1 ;SAVE WIDTH + CALL PB@VMPI + + MOV AL,IY1 ;SAVE HEIGHT + CALL PB@VMPI + + DEC ITICN ;ANY MORE ENTRIES? + JNZ GITER1 ;....YES + RET + +GITER ENDP +;------------------------ + + PUBLIC GRESTR +GRESTR PROC + MOV DSKDIR,0 ;INDICATE RESTORE (READ) + JMP OSV0$ +GRESTR ENDP + +; +; SAVE +; + PUBLIC GSAVE +GSAVE PROC + MOV DSKDIR,1 ;INDICATE SAVE (WRITE) + +; +;COMMON ENTRYPOINT FOR SAVE AND RESTORE +; +; DO A DISK RESET IN CASE THEY WANT TO CHANGE DISKS +; UNFORTUNATELY WE HAVE TO ASSUME A 1 DRIVE SYSTEM AT THIS POINT + +OSV0$: MOV AH,CFCLOSZ ; (7s) CLOSE THE GAME FILE + MOV BX,GAMHNDL ; (7s) FOR REINSERTION + INT 21H + MOV AH,CDRESET ; (K6) WILL RESET FLUSH BUFFERS? + INT 21H ; (K6) HOPE SO... + MOV AH,2 ; SET CURSOR POSITION + MOV DX,100H ; COORD'S ARE 0,0 + MOV BH,0 ; ACTIVE PAGE 0 + INT 10H ; TO PREVENT INVISIBLE CURSOR MOVEMENT + + +; PRINT "FILENAME (DEFAULT IS drv:filename.ext):" + +; PRINT "FILENAME (DEFAULT IS drv:" +OSV0A: MOV AX,OFFSET SAV0 ;PRINT "INSERT SAVE DISK THEN ENTER FILE..." + CALL MPRNT ; WITH CRLF + MOV AX,OFFSET SAV1 ;PRINT "FILE NAME (DEFAULT IS " + CALL NPRNT ; WITH NO CRLF + TEST DRVFLG,1 ; HAS USER SPECIFIED A DRIVE + JNZ OSVD1 ; YES, USE USER DEFAULT DRIVE + MOV AL,CURDRV ;AL <= DRIVE NO. + ADD AL,65 ;....NO. ADD 65 TO GET ASCII CHARACTER + CALL PRTOUT ;PRINT DRIVE B, C, OR D + MOV AL,":" ;PRINT ":" + CALL PRTOUT + +; PRINT "filename" +OSVD1: PUSH SI ; (6) SAVE THIS + MOV SI,OFFSET DATFILE ; (6) POINTER TO SAVE FILENAME (6) + MOV CX,SI ; (6) SAVE POINTER + CLD ; (6) SET DIR INCREMENT +OSVD2: LODSB ; (6) GET A BYTE INTO AL + TEST AL,AL ; (6) CHECK IF NULL + JZ OSVD3 ; (6) EXIT THIS LOOP + CALL PRTOUT ; (6) OUTPUT IT + JMP OSVD2 +OSVD3: SUB SI,CX ; (6) CALCULATE NUMBER OF CHARS + MOV CX,SI ; (6) GET NUMBER BACK INTO CX + POP SI ; (6) RESTORE THIS + +; PRINT " ): " + MOV AX,OFFSET SAV2 ;PRINT " ): " + CALL NPRNT ; WITH NO CRLF + +; GET LOSER'S SAVE FILENAME FROM THE KEYBOARD +OSVD4A: MOV BX,OFFSET INBUF ;^ KEYBOARD INPUT BUFFER + MOV AL,15 ;(6) COULD BE A WHOLE PATH + MOV BYTE PTR [BX],AL ;SET UP BUFFER TO TAKE 15 CHARACTERS + MOV DX,BX ;DX ^ BUFFER + MOV AH,CRDLIN ;READ A LINE FROM THE KEYBOARD + INT 21H + +; PARSE THE FILENAME + + CALL SAVESAV ; (7o) PRESERVE THE SAVE NAME + PUSH SI + PUSH DI + PUSH CX ; SAVE THIS + PUSH ES + PUSH DS + POP ES + LEA SI,INBUF[1] ; POINT TO NUM CHARS READ + LODSB ; GET NUM + TEST AL,AL ; ANY CHARS READ + JZ LOOK + MOV CL,AL ; STORE IT + XOR CH,CH ; CLEAR TOP HALF OF COUNTER + MOV DI,OFFSET DATFILE ; (6) DI ^FCB + REPZ MOVSB ; TRANSFER THE STRING IF ANY + MOV AL,0 ; (6) GET A NULL + STOSB ; (6) DROP IT IN AT END OF STRING +LOOK: MOV SI,OFFSET DATFILE ; (6) IS THERE A ':' + INC SI + LODSB ; (6) CHECK IT + CMP AL,':' ; (6) IF SO, FIX DEFDRV + JNZ NODRV ; (6) NOPE... + MOV DRVFLG,1 ; (6) SET FLAG + MOV AL,DATFILE ; (7n) GET DRIVE LETTER + AND AL,5FH ; (7n) UPPERCASIFY + SUB AL,'A' ; (7n) BASIFY + CMP AL,CURDRV ; (7n) DON'T CHANGE IF UNNECESSARY + JZ DRV + MOV DL,AL ; (7n) SET UP FOR CHGDSK + MOV AH,CSELDSK ; (7n) SELECT DISK IN DL + INT 21H + MOV AH,CURDSK ; (7n) CHECK IF IT WORKED + INT 21H + MOV CURDRV,AL ; (7n) SAVE IT + JMP DRV +USEDEF: MOV SKPDRV,1 ; (7n) DON'T OUTPUT A DRIVE +NODRV: MOV DRVFLG,0 +DRV: POP ES + POP CX + POP DI ;RESTORE'M + POP SI + CALL MCRLF ; (7) SCROLL PROPERLY + +; OPEN THE FILE IF OP RESTORE + + CMP DSKDIR,1 ;OP SAVE? + JE OSVOPW ;....YES + MOV DX,OFFSET DATFILE ; 6) ....NO. OP RESTORE. DX ^ FCB + MOV AH,CFOPENZ ; (6) SELECT DOS OPEN FUNCTION + MOV AL,0 ; (6) FILE OPEN FOR READING + INT 21H ;OPEN THE FILE + JC OSVPSX ; (6) ....NO. FILE NOT FOUND + JMP OSVPS ;....YES +; +; **** ERROR **** [File Not Found] +; +OSVPSX: MOV AX,OFFSET ERR1 ;^ "SAVE FILE NOT FOUND" MSG + JMP OSVPER ;ERROR EXIT + +; CREATE THE FILE IF OP SAVE +OSVOPW: MOV DX,OFFSET DATFILE ; (6) ^ FCB + MOV CX,0 ; (6) NO SPECIAL ATTRIBUTE + MOV AH,CFCREAZ ; (6) SELECT DOS CREATE FUNCTION + INT 21H + JC OSVOPDF + JMP OSVPS ;....YES +; +; **** ERROR **** [Directory Full] +; +OSVOPDF:MOV AX,OFFSET ERR4 ;....NO. ^ "NO ROOM IN DIRECTORY" MSG + JMP OSVPER ;HOP TO ERROR EXIT +; +; WE'VE GOT AN OPEN FILE (WHICH WE CREATED IF IT WAS A SAVE FUNCTION) +; AND ARE READY TO EITHER READ (RESTORE) OR WRITE (SAVE) AS REQUIRED + + +OSVPS: MOV DATHNDL,AX ; SAVE FILE HANDLE FOR DUMP/LOAD + XCHG DI,SP + MOV AH,GPC2 ; SAVE GPC + MOV AL,GPC1 + PUSH AX + MOV AL,GPC0 ; SAVE LOW BIT + PUSH AX ; OH, WHAT A WASTE + PUSH GLOCS ; SAVE LOCALS TABLE POINTER + PUSH OLDGSP ; RICK'S OLD G-STACK POINTER + not ZORKID ; make RGB id different + PUSH ZORKID ; SAVE GAME ID + not ZORKID ; set ID back + +; SUB SP,OFFSET GSTK_BT ; (7v) RELATIVISE THE POINTER +; MOV GSTK_BT,SP ; PUT DEST. INDEX INTO STACKBOTTOM + mov ax,sp + sub ax,offset GSTK_BT + mov gstk_bt,ax ; the other way is DANGEROUS + + MOV SP,DI ; RESTORE SP + + PUSH ES + + MOV AX,SS ; FLOP STACK SEG AND EXTRA SEG + MOV ES,AX ; ES<=SS + + MOV DX,OFFSET GSTK_BT ; CORE LOCATION + MOV CX,LSTACK*2 ; (6) DO TRANSFER HERE + MOV BX,DATHNDL ; (6) GET HANDLE + MOV AH,CRDRNDZ ; SETUP FOR A READ + ADD AH,DSKDIR ; MAKE IT A WRITE IF NECESSARY + INT 21H ; + CMP AX,CX ; DID WE GET IT ALL + PUSHF ;SAVE RETURN CODE + MOV DI,SP ;DI ^ CURRENT ZSTACK POSITION +; MOV SP,GSTK_BT ;SP <= ZSTACK POINTER +; ADD SP,OFFSET GSTK_BT ; (7v) RELATIVISE THIS VALUE + mov ax,gstk_bt + add ax,offset gstk_bt + mov sp,ax ; the other way is DANGEROUS + + POP AX ; POP OFF AND COMPARE FOR ZORKID + not ax ; change ID from RGB id for comparison + CMP AX,ZORKID ;ID OK? + JE OSVT0 ;....YES + + xchg DI,SP ; get back the real stack + popf + pop es ; where we stashed es + MOV AL,18 ; SAVE ERROR + JMP GERROR ;....NO. FATAL ERROR + +OSVT0: POP OLDGSP ; RESTORE OLD G-STACK POINTER FOR RETURN + POP GLOCS ;RESTORE LOCALS AND ZIP PROGRAM COUNTERS + POP AX ; RESTORE LOW BIT + MOV GPC0,AL ; FROM THIS WORD + POP AX ; RESTORE GPC + MOV GPC2,AH + MOV GPC1,AL + + XCHG DI,SP ;RESTORE MACHINE SP AND ZSTACK POINTER + POPF ;RESTORE REGS + POP ES + + ; BEGIN SAVE OF G-FILE PRELOAD + ; + + MOV BX,DATHNDL ; GET HANDLE + MOV AH,DSKDIR ; GET DIRECTION + PUSH DS ; SAVE IT + MOV CX,SEG0 ; GET GAME SEG + MOV DS,CX ; ADDRESS IT + PUSH BX ; USE THIS AS INDEX + MOV BX,GEND ; DO > + MOV CX,[BX] ; GET LENGTH WORD + POP BX ; RESTORE HANDLE + XCHG CH,CL ; BYTE SWAP + SHL CX,1 ; CONVERT TO BYTES + MOV DX,0 ; STARTS AT BEGINNING OF THE SEG + ADD AH,CRDRNDZ ; START OUT WITH READ + INT 21H ; READ IT + JMP OSVPS2 +; +; +OSVPS2: JC OSV4 ; SKIP ON ERROR + + ; SUCESSFUL TRANSFER OF THE G-FILE PRELOAD. + ; TRANSFER I-FILE PRELOAD + + PUSH BX ; SAVE HANDLE + PUSH DS ; SAVE BUFFER SEG + MOV AX,CS ; GET DATA SEG + MOV DS,AX ; SO THAT WE CAN DO REAL ADDRESSING + MOV AX,ICODE ; GET INFO OUT OF I-PRE + MOV VMP,AX ; SET UP VIRTUAL MEMORY POINTER + MOV VMP0,0 ; TO GET + MOV AX,IEND ; THE END OF I-PRELOAD + CALL ADDVMP ; ADD IN OFFSET + CALL GW@VMP ; GET THE WORD + MOV DX,LADD ; GET THE LOW ADDRESS BITS + MOV BL,LOC ; GET BLOCK NUMBER + MOV BH,0 ; ZERO TOP HALF + SHL BX,1 ; CONVERT TO ADDRESS + OR DH,BL ; TURN ON BLOCK BITS + SUB DX,IEND ; GET START BYTE ADDRESS + MOV CX,AX ; GET NUMBER OF WORDS IN I-PRE + SHL CX,1 ; CONVERT TO BYTES + MOV AH,CRDRNDZ ; GET FUNCTION + ADD AH,DSKDIR ; ADD IN DIRECTION + POP DS ; RESTORE BUFFER SEG + POP BX ; RESTORE HANDLE + INT 21H ; READ/WRITE THE I-FILE + JC OSV4 + + ; SUCCESS IN GENERAL -- CLOSE FILES + POP DS ; HANDLE IS STILL IN BX + MOV AH,CFCLOSZ ; CLOSE THE SAVE FILE + INT 21H ; THRU DOS + CALL GAMOPEN ; (7s) OPEN GAME FILE + MOV AH,2 ; SET CURSOR POSITION + MOV DX,100H ; COORD'S ARE 0,0 + MOV BH,0 ; ACTIVE PAGE 0 + INT 10H ; TO PREVENT INVISIBLE CURSOR MOVEMENT + MOV DL,CURDRV ; (7n) RETURN TO SAVE DISK + MOV AH,CSELDSK ; (7n) AND SELECT IT FOR OPEN + INT 21H + MOV DSKDIR,-1 ; RESET SAVE/RESTORE FLAG + MOV ARG1,0 ; (B7) CLEAR OUT THE SCREEN + CALL GCLEAR ; (B7) IN CASE OF ERRORS + JMP PGOOD +; +; **** ERROR **** [Unable to Read File] +; +OSV4: POP DS + MOV AX,OFFSET ERR6 ;^ "Read of SAVE file failed." + CMP DSKDIR,1 ;OP SAVE? + JNE OSVPRR ;....NO + MOV AH,CFCLOSZ ; (6) ....YES. CLOSE IT + MOV BX,DATHNDL ; (6) GET HANDLE FOR CLOSE + INT 21H +; +; **** ERROR **** [Diskette Full] +; + MOV DX,OFFSET DATFILE ; (7n) DELETE THE PIECE OF A FILE + MOV AH,CFDELEZ ; (7n) SO AS NOT TO CONFUSE + INT 21H + MOV AX,OFFSET ERR5 ;^ "No room on diskette for SAVE file." +OSVPRR: JMP OSVPER +GSAVE ENDP +; +; ERROR EXIT R/W operations +; +OSVPER PROC + CALL MPRNT ;PRINT ERROR MESSAGE + CALL ZRESTOR ; (7o) RESTORE OLD SAVE NAME + CALL GAMOPEN ; (7v) OPEN IT + MOV AH,2 ; SET CURSOR POSITION + MOV DX,100H ; COORD'S ARE 0,0 + MOV BH,0 ; ACTIVE PAGE 0 + INT 10H ; TO PREVENT INVISIBLE CURSOR MOVEMENT + MOV ARG1,0 ; (B7) CLEAR OUT THE SCREEN + CALL GCLEAR ; (B7) IN CASE OF ERRORS + MOV DSKDIR,-1 ; RESET SAVE/RESTORE FLAG + JMP PBAD +OSVPER ENDP +; + PUBLIC SAVESAV,ZRESTOR,SCRSAVE +SCRSAVE PROC + PUSH AX ; (7p) SAVES + PUSH SI + PUSH DX + MOV SI,OFFSET DATFILE ; (7p) POINTER TO SAVE +SCRS0: LODSB ; (7p) GET A CHARACTER + TEST AL,AL ; (7p) LOOK FOR A NULL + JNZ SCRS1 ; (7p) DIE ON A NULL + POP DX + POP SI + POP AX + RET ; (7p) RETURN +SCRS1: MOV DL,AL ; (7p) GET CHARACTER INTO DL + MOV AH,CPROUT ; (7p) FOR DOS"IE" OUTPUT + INT 21H ; (7p) PRINT IT + JMP SCRS0 +SCRSAVE ENDP + +SAVESAV PROC + PUSH DI ; (7o) SAVES + PUSH SI + PUSH AX + PUSH ES + MOV AX,DS ; (7o) SET UP REGS + MOV ES,AX + MOV AL,CURDRV ; (7o) SAVE CURRENT DRIVE SPEC + MOV LASTDRV,AL ; (7o) IN CASE OF FAILURE + MOV AL,DRVFLG ; (7o) TEST DRIVE FLAG + MOV LSTDFLG,AL ; (7o) IN CASE OF FAILURE + MOV SI,OFFSET DATFILE ; (7o) SETUP SOURCE AND DESTINATION + MOV DI,OFFSET LASTSAV +COPYLP: LODSB ; (7o) GET A BYTE + STOSB ; (7o) STORE A BYTE + TEST AL,AL ; (7o) STOP ON A NUL + JNZ COPYLP ; (7o) CONTINUE THE COPY + POP ES + POP AX ; (7o) RESTORES + POP SI + POP DI + RET +SAVESAV ENDP +; +; +ZRESTOR PROC + PUSH DI ; (7o) SAVES + PUSH SI + PUSH AX + PUSH ES + MOV AX,DS ; (7o) SET UP REGS + MOV ES,AX + MOV AL,LSTDFLG ; (7o) GET LAST DRIVE FLAG + MOV DRVFLG,AL ; (7o) AND RESTORE IT + MOV AL,LASTDRV ; (7o) GET ORIGINAL DRIVE SPEC + CMP AL,CURDRV ; (7o) HAS IT CHANGED + JZ ZRES1 + MOV DL,AL ; (7o) SELECT DISK + MOV AH,CSELDSK ; (7o) TO CORRECT + INT 21H + MOV CURDRV,DL ; (7o) UPDATE THIS BABY +ZRES1: MOV DI,OFFSET DATFILE ; (7o) SETUP SOURCE AND DESTINATION + MOV SI,OFFSET LASTSAV +ZRESLP: LODSB ; (7o) GET A BYTE + STOSB ; (7o) STORE A BYTE + TEST AL,AL ; (7o) STOP ON A NUL + JNZ ZRESLP ; (7o) CONTINUE THE COPY + POP ES + POP AX ; (7o) RESTORES + POP SI + POP DI + RET +ZRESTOR ENDP + + PUBLIC GAMOPEN + ; THIS PROCEDURE OPENS THE GAME FILE AFTER CLOSING ALL FILES. + ; IF THE GAME FILE IS NOT ON THE DISK, IT PROMPTS FOR REINSERTION +GAMOPEN PROC + PUSH DX + PUSH CX + MOV CX,0 ; (B5) INDICATE FIRST PASS + MOV DL,DEFDRV ; (7o) GET DRIVE WHERE GAME IS + MOV AH,CSELDSK ; (7o) TO MAKE OPEN WIN + INT 21H ; (7o) DO IT + MOV AH,CFCLOSZ ; (7s) TRY CLOSING INSTEAD OF RESET + MOV BX,GAMHNDL ; (7s) OF THE GAME FILE + INT 21H ; (7o) TO MAKE SURE THIS WINS +GOPEN0: MOV AH,CFOPENZ ; (6) ASCIZ STRINGS + MOV AL,0 ; (6) OPEN FOR READING + MOV DX,OFFSET GAMFILE ; (7o) OPEN THE FILE AGAIN + INT 21H + JNC GOPEN1 ; (7o) IF SUCCESS, CONTINUE + INC CX + MOV AX,OFFSET SAV3 ; (7o) OTHERWISE PROMPT + CALL MPRNT + CALL MCHRI ; (7o) AND WAIT FOR A CHARACTER + JMP GOPEN0 ; (7o) AND LOOP +GOPEN1: MOV GAMHNDL,AX ; (7o) SAVE GAME HANDLE + MOV DL,CURDRV ; (7v) RESTORE SAVE DRIVE + MOV AH,CSELDSK ; (7v) SO THAT WE ARE NOT CONFUSED + INT 21H ; (7v) THANKS MAX + CMP CX,0 ; (B5) CHECK FOR PAUSE + JNE GOPEN2 ; (B5) NOT NECESSARY + MOV AX,OFFSET STRIKE ; (B5) STRIKE ANY KEY MESSAGE + CALL NPRNT ; (B5) PRINT IT + CALL MCHRI ; (B5) AND WAIT +GOPEN2: POP CX ; (B5) AND RESTORE THIS ONE + POP DX + RET +GAMOPEN ENDP + +MCHRI PROC + MOV AH,CNOECHO + INT 21H + RET +MCHRI ENDP + +;------------------------ + PAGE + ; ---- + ; LOAD + ; ---- + ; + ; PURPOSE: THIS ROUTINE LOADS THE SPECIFIED AMOUNT OF DATA INTO A + ; SPECIFIED BLOCK OF PRELOAD. IF ARG3 IS PROVIDED, THEN + ; THIS IS A TRANSFER FROM DISK. ELSE, IT IS AN I/O PORT + ; OPERATION. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; ARG2=LENGTH IN WORDS + ; ARG3=FILENAME POINTER (OPTIONAL) + ; + ; OUTPUTS: DATA IS TRANSFERED TO PRELOAD, IF THE OPERATION IS + ; ILLEGAL OR FAILS FOR ANY REASON, A "0" IS RETURNED + ; VIA {RET0}. ELSE A "1" IS RETURNED VIA {RET1}. + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC GLOAD +GLOAD PROC + CMP NARGS,3 ;IS THIS A FILE TRANSFER REQUEST? + JE GLD0 ;....YES + JMP LDIO ;....NO, IT'S AN I/O TRANSFER + + ; + ; FILE TRANSFER REQUEST + ; + + ; ASSUME THAT THE DEFAULT DISK IS TO BE USED + ; CLOSE THE GAMEFILE +GLD0: MOV AH,CFCLOSZ ;CLOSE THE GAME FILE FOR REINSERTION + MOV BX,GAMHNDL ;IN CASE THIS IS A 1 DRIVE SYSTEM, + INT 21H ; OR THE DEFAULT DRIVE IS SPECIFIED + MOV AH,CDRESET ;AND FLUSH + INT 21H + + ; PARSE THE FILENAME + MOV AX,ARG3 ;SET UP VMP TO POINT TO THE FILENAME + MOV VMP,AX + MOV VMP0,0 + CALL GW@VMPI ;GET THE LENGTH OF THE FILENAME + MOV CX,AX ;IN CX FOR USE AS A LOOP COUNTER + MOV BX,OFFSET DATFILE ;^ FCB + + ;GET THE FILENAME INTO THE FCB +GLD1: CALL GB@VMPI ;GET A CHARACTER + MOV [BX],AL ;PUT IT IN THE FCB + INC BX ;NEXT CHARACTER + LOOP GLD1 ; GET THE REST + MOV BYTE PTR [BX],0 ;DROP IN A NUL AT THE END OF THE NAME + + PUSH DI ;SAVE SOME REGISTERS + PUSH DS + POP ES ;BOTH ES & DS POINT AT THE DATA SEGMENT + + ; OPEN THE DATA FILE + MOV AH,CFOPENZ ;SELECT OPEN FILE + MOV AL,0 ;SELECT READ + MOV DX,OFFSET DATFILE ;POINT AT THE ASCIIZ STRING + INT 21H ;MDOS CALL + JNC GLD2 + JMP LDERR1 + +GLD2: MOV DATHNDL,AX ;SAVE THE FILE HANDLE + + ; START THE ACTUAL TRANSFER OPERATION +RESTENT:CMP ARG2,0 ;DO WE HAVE ANY DATA? + JNE GLDLP ;....YES + JMP LDERR3 ;....NO + +GLDLP: SUB ARG2,256 ;IS THIS A FULL BLOCK? + JB GLD3 ;....NO + + ; READ A RECORD INTO DS:DX + MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER + MOV CX,RECSIZ ;READ A 512 BYTE RECORD (256 WORDS) + MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CRDRNDZ ;SELECT READ RANDOM RECORD + INT 21H ;INVOKE FUNCTION CALL + CMP AX,CX ;DID WE GET A FULL RECORD? + JE GLDLPA ;....YES + JMP LDERR3 ;....NO + +GLDLPA: MOV CX,RECSIZ ;GET RECORD SIZE (IN BYTES) + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (SOURCE) + MOV AX,ARG1 ;SETUP VMP (DESTINATION) + MOV VMP,AX + MOV VMP0,0 + +GLDLP1: MOV AL,BYTE PTR [BX] ;GET THE BYTE + CALL PB@VMPI ;PUT IT IN VM AND AUTOINC + INC BX ;NEXT BYTE + LOOP GLDLP1 + + ADD ARG1,256 ;UPDATE DESTINATION POINTER + + JMP GLDLP ;KEEP GOING UNTIL WE'VE DONE ALL THE + ; FULL RECORDS + +GLD3: ADD ARG2,256 ;SEE IF THERE'S A PARTIAL RECORD + JZ GLD5 ;....NO + MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER + MOV CX,ARG2 ;GET THE SIZE + SHL CX,1 ;BYTIFY IT + MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CRDRNDZ ;SELECT READ RANDOM RECORD + INT 21H ;INVOKE FUNCTION CALL + CMP AX,CX ;DID WE GET ALL OF THE PARTIAL RECORD? + JE GLD4 ;....YES + JMP LDERR3 ;....NO + +GLD4: MOV CX,ARG2 ;GET RECORD SIZE (IN WORDS) + SHL CX,1 ;BYTIFY + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (SOURCE) + MOV AX,ARG1 ;SETUP VMP (DESTINATION) + MOV VMP,AX + MOV VMP0,0 + +GLDLP2: MOV AL,BYTE PTR [BX] ;GET THE BYTE + CALL PB@VMPI ;PUT IT IN VM AND AUTOINC + INC BX ;NEXT BYTE + LOOP GLDLP2 + + ;CLOSE THE FILE +GLD5: CMP DSKDIR,-1 ;IF NOT -1, THEN SAVE OR RESTORE + JZ GLD5A + CLC ; CLEAR CARRY TO TELL S/R + RET +GLD5A: MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CFCLOSZ ;CLOSE IT + INT 21H + + ; REOPEN THE GAME FILE + MOV AH,CFOPENZ + MOV AL,0 ;OPEN FOR READ + MOV DX,OFFSET GAMFILE + INT 21H + JNC GLD6 + JMP DSKERR + +GLD6: MOV GAMHNDL,AX ;SAVE THE FILE HANDLE + POP DI ;RESTORE GSTACK POINTER + JMP RET1 ;RETURN A "1" + +LDERR0: +LDERR1: +LDERR2: +LDERR3: + CMP DSKDIR,-1 ; IF NOT, THEN SAVE/RESTORE + JZ GLD6A + STC ; WARN SAVE RESTORE + RET + ;CLOSE THE DATA FILE +GLD6A: MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CFCLOSZ ;CLOSE IT + INT 21H + + ; REOPEN THE GAME FILE + MOV AH,CFOPENZ + MOV AL,0 ;OPEN FOR READ + MOV DX,OFFSET GAMFILE + INT 21H + JNC GLD7 + JMP DSKERR ;UNRECOVERABLE ERROR + +GLD7: MOV GAMHNDL,AX ;SAVE THE FILE HANDLE + POP DI ;RESTORE GSTACK POINTER + JMP RET0 +GLOAD ENDP + + ; ---- + ; LDIO + ; ---- + ; + ; PURPOSE: THIS ROUTINE LOADS THE SPECIFIED AMOUNT OF DATA INTO A + ; SPECIFIED BLOCK OF PRELOAD. IT IS THE I/O PORT OPERATION + ; SUBCASE OF {GLOAD}. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; ARG2=LENGTH (IN WORDS) + ; + ; OUTPUTS: DATA IS TRANSFERED TO PRELOAD, IF THE OPERATION IS + ; ILLEGAL OR FAILS FOR ANY REASON, A "0" IS RETURNED + ; VIA {RET0}. ELSE A "1" IS RETURNED VIA {RET1}. + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC LDIO +LDIO PROC +; SUB AX,AX ;SIGNAL A READ OPERATION +; CALL INITIO ;INITIALIZE I/O DEVICE +; +; MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER +; CMP ARG2,0 ;DO WE HAVE A LEGAL LENGTH? +; JE IOERR1 ;....NO +; +;LDIOLP: SUB ARG2,256 ;IS THIS A FULL RECORD? +; JB LDIO1 ;....NO +; MOV CX,RECSIZ ;READ 512 BYTES (256 WORDS) +; CALL IOREAD ; AND PUT THEM IN THE XFER BUFFER +; CMP AX,CX ;DID WE GET THE EXPECTED AMOUNT? +; JNE IOERR1 ;....NO +; MOV CX,256 ;GET RECORD SIZE (IN WORDS) +; CALL XFR2VM ;BLOCK MOVE THE XFER BUFFER TO VIRTUAL +; JMP LDIOLP ;CONTINUE UNTIL WE'VE DONE ALL THE +; ; FULL BLOCKS +; +;LDIO1: ADD ARG2,256 ;COMPUTE PARTIAL RECORD SIZE +; JZ LDIO2 ;NO PARTIAL RECORD +; MOV CX,ARG2 ;GET SIZE OF PARTIAL RECORD +; CALL IOREAD ; GET IT IN THE XFER BUFFER +; CMP AX,CX ;DID WE GET THE EXPECTED AMOUNT? +; JNE IOERR1 ;....NO +; MOV CX,ARG2 ;GET RECORD SIZE (IN WORDS) +; CALL XFR2VM ;....YES, TRANSFER IT TO VM +;LDIO2: JMP RET1 ;SIGNAL SUCCESS + +IOERR1: JMP RET0 ;SIGNAL FAILURE +LDIO ENDP + +;@@ +IOREAD PROC + RET ;DUMMY +IOREAD ENDP + + +;@@ +INITIO PROC + RET ;DUMMY +INITIO ENDP + + + ; ------ + ; XFR2VM + ; ------ + ; + ; PURPOSE: THIS ROUTINE TRANSFERS [CX] BYTES OF DATA FROM THE TRANFER + ; BUFFER TO VIRTUAL MEMORY. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; [CX]=NUMBER OF BYTES TO TRANSFER + ; + ; OUTPUTS: DATA IS TRANSFERED TO PRELOAD + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC XFR2VM +XFR2VM PROC + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (SOURCE) + MOV AX,ARG1 ;SETUP VMP (DESTINATION) + MOV VMP,AX + MOV VMP0,0 + +XFVMLP: MOV AL,BYTE PTR [BX] ;GET THE BYTE + CALL PB@VMPI ;PUT IT IN VM AND AUTOINC + INC BX ;NEXT BYTE + LOOP XFVMLP + RET +XFR2VM ENDP + + PAGE + ; ---- + ; DUMP + ; ---- + ; + ; PURPOSE: THIS ROUTINE TRANSFERS A SPECIFIED AMOUNT OF DATA FROM + ; A SUPPLIED VIRTUAL MEMORY ADDRESS. IF ARG3 IS PROVIDED, + ; THEN THIS IS A TRANSFER TO DISK. ELSE, IT IS AN I/O PORT + ; OPERATION. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; ARG2=LENGTH + ; ARG3=FILENAME POINTER (OPTIONAL) + ; + ; OUTPUTS: DATA IS TRANSFERED FROM VIRTUAL MEMORY, IF THE + ; OPERATION IS ILLEGAL OR FAILS FOR ANY REASON, + ; A "0" IS RETURNED VIA {RET0}. ELSE A "1" IS + ; RETURNED VIA {RET1}. + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC GDUMP +GDUMP PROC + ; DETERMINE TRANSFER TYPE + CMP NARGS,3 ;IS THIS A FILE TRANSFER REQUEST? + JE GDM0 ;....YES + JMP DMIO ;....NO, IT'S AN I/O TRANSFER + + ; + ; FILE TRANSFER REQUEST + ; + + ; ASSUME THAT THE DEFAULT DISK IS TO BE USED + ; CLOSE THE GAMEFILE +GDM0: MOV AH,CFCLOSZ ;CLOSE THE GAME FILE FOR REINSERTION + MOV BX,GAMHNDL ;IN CASE THIS IS A 1 DRIVE SYSTEM, + INT 21H ; OR THE DEFAULT DRIVE IS SPECIFIED + MOV AH,CDRESET ;AND FLUSH + INT 21H + + ; PARSE THE FILENAME + MOV AX,ARG3 ;SET UP VMP TO POINT TO THE FILENAME + MOV VMP,AX + MOV VMP0,0 + CALL GW@VMPI ;GET THE LENGTH OF THE FILENAME + MOV CX,AX ;IN CX FOR USE AS A LOOP COUNTER + MOV BX,OFFSET DATFILE ;^ FCB + + ;GET THE FILENAME INTO THE FCB +GDM1: CALL GB@VMPI ;GET A CHARACTER + MOV [BX],AL ;PUT IT IN THE FCB + INC BX ;NEXT CHARACTER + LOOP GDM1 ; GET THE REST + MOV BYTE PTR [BX],0 ;DROP IN A NUL AT THE END OF THE NAME + + PUSH DI ;SAVE SOME REGISTERS + PUSH DS + POP ES ;BOTH ES & DS POINT AT THE DATA SEGMENT + + ; OPEN THE DATA FILE + MOV AH,CFCREAZ ;SELECT CREATE FILE + SUB CX,CX ;SELECT READ/WRITE ATTRIBUTE + MOV DX,OFFSET DATFILE ;POINT AT THE ASCIIZ STRING + INT 21H ;MDOS CALL + JNC GDM2 + JMP DMERR1 + +GDM2: MOV DATHNDL,AX ;SAVE THE FILE HANDLE + + ; START THE ACTUAL TRANSFER OPERATION +SAVENT: CMP ARG2,0 ;DO WE HAVE A LEGAL LENGTH? + JNE GDMLP ;....YES + JMP DMERR0 ;....NO + + ; PROCESS THE FULL RECORDS +GDMLP: SUB ARG2,256 ;IS THIS A FULL BLOCK? + JB GDM3 ;....NO + + ; TRANSFER A FULL RECORD FROM VIRTUAL MEMORY TO THE TRANSFER BUFFER + MOV CX,RECSIZ ;GET RECORD SIZE (IN BYTES) + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (DESTINATION) + MOV AX,ARG1 ;SETUP VMP (SOURCE) + MOV VMP,AX + MOV VMP0,0 + +GDMLP1: CALL GB@VMPI ;GET THE BYTE AND AUTOINC + MOV BYTE PTR [BX],AL ;PUT IT IN XFRBUF + INC BX ;NEXT DESTINATION + LOOP GDMLP1 + + ADD ARG1,256 ;UPDATE SOURCE POINTER + + ; WRITE A FULL RECORD TO THE DISK + MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER + MOV CX,RECSIZ ;WRITE A 512 BYTE RECORD (256 WORDS) + MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CWRRNDZ ;SELECT WRITE RANDOM RECORD + INT 21H ;INVOKE FUNCTION CALL + + CMP AX,CX ;DID WE WRITE A FULL RECORD? + JE GDMLP ;....YES, TRY ANOTHER + JMP DMERR2 ;....NO + + + ; PARTIAL RECORD +GDM3: ADD ARG2,256 ;SEE IF THERE'S A PARTIAL RECORD + JZ GDM4 ;....NO + + ; TRANSFER PARTIAL RECORD FROM VIRTUAL MEMORY TO THE TRANSFER BUFFER + MOV CX,ARG2 ;GET THE SIZE (IN WORDS) + SHL CX,1 ;BYTIFY + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (DESTINATION) + MOV AX,ARG1 ;SETUP VMP (SOURCE) + MOV VMP,AX + MOV VMP0,0 + +GDMLP2: CALL GB@VMPI ;GET THE BYTE AND AUTOINC + MOV BYTE PTR [BX],AL ;PUT IT IN XFRBUF + INC BX ;NEXT DESTINATION + LOOP GDMLP2 + + ; WRITE A PARTIAL RECORD TO THE DISK + MOV CX,ARG2 ;GET THE SIZE (IN WORDS) + SHL CX,1 ;BYTIFY + MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER + MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CWRRNDZ ;SELECT WRITE RANDOM RECORD + INT 21H ;INVOKE FUNCTION CALL + CMP AX,CX ;DID WE WRITE ENOUGH? + JE GDM4 ;....YES + JMP DMERR2 ;....NO + + ;CLOSE THE DATA FILE +GDM4: CMP DSKDIR,-1 ; CHECK SAVE RESTORE FLAG + JZ GDM4A + CLC ; CLEAR TO SAVE/RESTORE + RET +; +GDM4A: MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CFCLOSZ ;CLOSE IT + INT 21H + + ; REOPEN THE GAME FILE + MOV AH,CFOPENZ + MOV AL,0 ;OPEN FOR READ + MOV DX,OFFSET GAMFILE + INT 21H + JNC GDM5 + JMP DSKERR + +GDM5: MOV GAMHNDL,AX ;SAVE THE FILE HANDLE + POP DI ;RESTORE GSTACK POINTER + JMP RET1 ;RETURN A "1" + +DMERR0: +DMERR1: +DMERR2: + CMP DSKDIR,-1 ; CHECK SAVE/RESTORE FLAG + JZ GDM5A + STC ; WARN SAVE RESTORE + RET + ;CLOSE THE DATA FILE +GDM5A: MOV BX,DATHNDL ;GET THE FILE HANDLE + MOV AH,CFCLOSZ ;CLOSE IT + INT 21H + + ; REOPEN THE GAME FILE + MOV AH,CFOPENZ + MOV AL,0 ;OPEN FOR READ + MOV DX,OFFSET GAMFILE + INT 21H + JNC GDM6 + JMP DSKERR ;UNRECOVERABLE ERROR + +GDM6: MOV GAMHNDL,AX ;SAVE THE FILE HANDLE + POP DI ;RESTORE GSTACK POINTER + JMP RET0 +GDUMP ENDP + + ; ---- + ; DMIO + ; ---- + ; + ; PURPOSE: THIS ROUTINE DUMPS A SPECIFIED AMOUNT OF DATA FROM + ; PRELOAD TO THE I/O PORT. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; ARG2=LENGTH (IN WORDS) + ; + ; OUTPUTS: DATA IS TRANSFERED TO THE I/O PORT, IF THE OPERATION + ; IS ILLEGAL OR FAILS FOR ANY REASON, A "0" IS RETURNED + ; VIA {RET0}. ELSE A "1" IS RETURNED VIA {RET1}. + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC DMIO +DMIO PROC +; MOV AX,1 ;SIGNAL A WRITE OPERATION +; CALL INITIO ;INITIALIZE I/O DEVICE +; +; MOV DX,OFFSET XFRBUF ;POINT AT THE TRANSFER BUFFER +; CMP ARG2,0 ;DO WE HAVE A LEGAL LENGTH? +; JE IOERR2 ;....NO +; +;DMIOLP: SUB ARG2,256 ;IS THIS A FULL RECORD? +; JB DMIO1 ;....NO +; CALL VM2XFR ;BLOCK MOVE THE VM BLOCK TO XFER BUFFER +; +; MOV CX,RECSIZ ;WRITE 512 BYTES (256 WORDS) +; CALL IOWRITE ; AND PUT THEM IN THE XFER BUFFER +; CMP AX,CX ;DID WE WRITE THE EXPECTED AMOUNT? +; JNE IOERR2 ;....NO +; JMP DMIOLP ;CONTINUE UNTIL WE'VE DONE ALL THE +; ; FULL BLOCKS +; +;DMIO1: ADD ARG2,256 +; MOV CX,ARG2 ;SETUP SIZE OF PARTIAL RECORD +; CMP CX,0 ;DO WE EVEN HAVE A PARTIAL RECORD? +; JE DMIO2 ;....NO +; +; CALL VM2XFR ;BLOCK MOVE THE VM BLOCK TO XFER BUFFER +; CALL IOWRITE ; AND PUT THEM IN THE XFER BUFFER +; CMP AX,CX ;DID WE WRITE THE EXPECTED AMOUNT? +; JNE IOERR2 ;....NO +; +;DMIO2: JMP RET1 ;SIGNAL SUCCESS +; +IOERR2: JMP RET0 ;SIGNAL FAILURE +DMIO ENDP + +;@@ +IOWRITE PROC + RET ;DUMMY +IOWRITE ENDP + + + ; ------ + ; VM2XFR + ; ------ + ; + ; PURPOSE: THIS ROUTINE TRANSFERS [CX] BYTES OF DATA FROM VIRTUAL + ; MEMORY TO THE TRANSFER BUFFER. + ; + ; INPUTS: ARG1=TABLE VIRTUAL ADDRESS + ; [CX]=NUMBER OF BYTES TO TRANSFER + ; + ; OUTPUTS: DATA IS TRANSFERED TO XFRBUF + ; + ; REGISTERS DESTROYED: ALL + ; + PUBLIC VM2XFR +VM2XFR PROC + MOV BX,OFFSET XFRBUF ;^ TRANSFER BUFFER (DESTINATION) + MOV AX,ARG1 ;SETUP VMP (SOURCE) + MOV VMP,AX + MOV VMP0,0 + +VMXFLP: CALL GB@VMPI ;GET THE BYTE AND AUTOINC + MOV BYTE PTR [BX],AL ;PUT IT IN XFRBUF + INC BX ;NEXT DESTINATION + LOOP VMXFLP + RET +VM2XFR ENDP + + PAGE + ;---------------------- + ; ITERATIONS + ;---------------------- + ; + ; EXECUTE THE ITERATION TABLE AT [ARG2] + ; {FOR I=ITPNT TO ITICN + ; + ; DRAW THE ACTIVE ICON [ITERATION] + ; + ; UPDATE THE ICON'S ITERATION COUNTER + ; + ; TEST FOR INPUT + ; IF INPUT THEN SAVE THE NEXT ACTIVE ICON ENTRY NUMBER + ; AND PROCESS THE INPUT} + ; + ; NEXT I} + ; + ; IF DONE + ; REINITIALIZE ITPNT <= 1 + ; BRANCH TO NOIT}. + + PUBLIC ITRATE +ITRATE PROC + MOV AX,ARG2 ;POINT AT THE ITERATION TABLE + MOV VMP,AX + MOV VMP0,0 + + CALL GB@VMPI ;GET THE NUMBER OF ENTRIES + MOV ITICN,AL + + MOV AL,VMP0 ;SAVE POINTER TO ITPNT + MOV VMSAV0,AL + MOV AX,VMP + MOV VMSAV,AX + + CALL GB@VMPI ;GET THE ENTRY TO START WITH + MOV ITPNT,AL ; WE'RE POINTING AT THE FIRST WORD + ; IN THE FIRST ENTRY + + MOV AL,1 ;SKIP ENTRIES 1 TO ITPNT + +ITLP2: CMP AL,ITPNT + JZ ITLOOP + + ADD VMP,6 ;SIX WORDS PER ENTRY + INC AL + JMP ITLP2 + + ; PROCESS THE DATA FOR THE CURRENT ACTIVE ICON +ITLOOP: MOV AX,VMP ;SAVE POINTER TO THE CURRENT + PUSH AX ; ACTIVE ICON'S DATA BASE + MOV AL,VMP0 + PUSH AX + + CALL GW@VMPI ;GET ICON BASE ADDRESS + MOV IADR1,AX + MOV IADR10,0 + + CALL GW@VMPI ;GET ICON HORIZONTAL POSITION + MOV ARG1,AX + + CALL GW@VMPI ;GET ICON VERTICAL POSITION + MOV ARG2,AX + + CALL GW@VMPI + MOV NEGATE,AH ;NEGATE + MOV BYTE PTR I,AL ;CURRENT ITERATION + + CALL GW@VMPI + MOV BSET,AH ;BLOCKSET ID + MOV ITERS,AL ;# OF ITERATIONS + + CALL GW@VMPI + MOV IX1,AH ;WIDTH + MOV IY1,AL ;HEIGHT + + ; UPDATE THE CURRENT ITERATION IN THE DATA STRUCTURE + MOV BL,BYTE PTR I + CMP BL,ITERS ;CURRENT ITERATION=NO. OF ITERATIONS? + JNE ITSKP2 ;....NO + MOV BL,0 ;....YES, SET IT TO 0 SO IT'LL BE 1 + +ITSKP2: INC BL ;NEXT POSSIBLE ITERATION + POP AX ;RESTORE POINTER TO THE + MOV VMP0,AL ; CURRENT ACTIVE ICON'S DATA BASE + POP AX + MOV VMP,AX + + MOV AX,7 ;POINT TO THE CURRENT ITERATION + CALL ADDVMP + + MOV AX,BX ;SAVE UPDATED VALUE + CALL PB@VMPI + + ; UPDATE POINTER TO THE NEXT ACTIVE ICON + ADD VMP,2 ;IT'S 4 MORE BYTES TO THE NEXT ACTIVE ICON + MOV AX,VMP ;SAVE POINTER TO THE + PUSH AX ; NEXT ACTIVE ICON'S DATA BASE + MOV AL,VMP0 + PUSH AX + + ; POINT TO THE CURRENT ICON'S BLOCK I.D. DATA + MOV AL,IX1 ;GET LENGTH OF ONE ICON + MUL IY1 + DEC BYTE PTR I ;ZERO ALIGN + MOV BL,BYTE PTR I + SUB BH,BH + MUL BX ;PRODUCT S/B IN AX + + ADD IADR1,2 ;POINT PAST HEADER (2 WORDS) + CALL AIADR1 ;ADD IN OFFSET + + ; DRAW THE ITERATION + MOV MSKFLG,0 ;DISABLE MASKING + CALL ITENT ;DRAW THE ICON + + ; + ; HAVE WE PROCESSED ALL THE ACTIVE ICONS? + ; + MOV AL,ITPNT ;ARE WE DONE? + CMP AL,ITICN + JE ITEXI ;....YES + + INC ITPNT ;....NO. POINT TO THE NEXT ICON + + ; INPUT PROCESSING + TEST BYTE PTR VALUE,80H ;IF INPUT WAS CALLED WITH A NEGATIVE + JNZ NONSNS ;INT THEN DON'T LOOK FOR INPUT + + CALL SENSE ;ELSE, POLL THE KEYBOARD + CMP AL,8FH ;DO WE HAVE AN INPUT? + JNE ITSKP5 ;....YES + +NONSNS: POP AX ;RESTORE POINTER TO THE + MOV VMP0,AL ; NEXT ACTIVE ICON'S DATA BASE + POP AX + MOV VMP,AX + JMP ITLOOP + + ; WE RECEIVED AN INPUT WHILE ITERATING + ; SO, WE SAVE WHERE WE ARE AND PROCESS THE INPUT +ITSKP5: PUSH AX ;SAVE INPUT + + MOV AL,VMSAV0 ;RESTORE POINTER TO ACTIVE TABLE HEADER + MOV VMP0,AL ; ITPNT ENTRY + MOV AX,VMSAV + MOV VMP,AX + + MOV AL,ITPNT ;SAVE WHERE WE LEFT OFF + CALL PB@VMP + + POP AX ;RESTORE SENSE + POP BX ;FLUSH VMP POINTER TO CURRENT ACTIVE ICON + POP BX + JMP PUTBYT + + ; WE ITERATED ALL THE ICONS IN THE ACTIVE TABLE + ; SO, WE SET UP TO DO IT AGAIN LATER AND EXIT +ITEXI: POP BX ;FLUSH VMP0 + POP BX ;FLUSH VMP + + MOV AL,VMSAV0 ;RESTORE POINTER TO ACTIVE TABLE HEADER + MOV VMP0,AL ; ITPNT ENTRY + MOV AX,VMSAV + MOV VMP,AX + MOV AL,1 ;SET ITPNT ENTRY TO 1 + CALL PB@VMP + JMP NOIT ; AND RESUME INPUT PROCESSING +ITRATE ENDP + + PAGE + ;-------------------------------------------------- + ; OPCODE EXECUTION PROCEDURES SUPPORT CODE + ;-------------------------------------------------- + + ; ------ + ; TSTPRE + ; ------ + ; + ; PURPOSE: THIS ROUTINE TESTS THE RANGE OF A SPECIFIED VIRTUAL MEMORY + ; BLOCK TO DETERMINE IF IT IS ALL CONTAINED IN EITHER + ; G-PRELOAD OR I-PRELOAD. + ; + ; INPUTS: [ARG1] VIRTUAL MEMORY STARTING ADDRESS (WORD POINTER) + ; [ARG2] LENGTH IN WORDS + ; + ; OUTPUTS: CARRY CLEAR IF IN PRELOAD + ; CARRY SET IF NOT IN PRELOAD + ; + ; REGISTERS DESTROYED: AX + ; + PUBLIC TSTPRE +TSTPRE PROC + ; TEST STARTING ADDRESS + MOV AX,ARG1 ;GET STARTING ADDRESS + CMP AH,GPEND ;DOES THE ADDRESS RESIDE BELOW THE + ; FIRST BLOCK OF G-PURE? + JB TPR0 ;....YES, IT'S G-PRELOAD + + CMP AX,ICODE ;IS IT GE. I-PRELOAD? + JB TPRERR ;....NO, IT'S NOT PRELOAD. + CMP AX,IPURE ;IS IT < IPURE + JB TPR1 ;....YES, IT'S I-PRELOAD + JMP TPRERR ;FAIL, IT'S NOT PRELOAD + + ; TEST LAST ADDRESS TO SEE IF IT'S IN G-PRELOAD TOO +TPR0: ADD AX,ARG2 ;ADD LENGTH + CMP AH,GPEND ;DOES THE ADDRESS RESIDE BELOW THE + ; FIRST BLOCK OF G-PURE? + JB TPREOK ;....YES, IT'S GOOD + JMP TPRERR ;FAIL IF NOT IN G-PRELOAD + + ; TEST LAST ADDRESS TO SEE IF IT'S IN I-PRELOAD TOO +TPR1: ADD AX,ARG2 ;ADD LENGTH + CMP AX,IPURE ;IS IT < IPURE + JB TPREOK ;....YES, IT'S I-PRELOAD + +TPRERR: STC ;SET CARRY FOR FAILURE + RET + +TPREOK: CLC ;CLEAR CARRY FOR SUCCESS + RET +TSTPRE ENDP + + PAGE + ; -------------------------------- + ; POP GSTACK INTO [VALUE] AND [AX] + ; -------------------------------- + ; + PUBLIC POPVAL +POPVAL PROC + CALL POPAXG ;POP A VALUE + MOV VALUE,AX ;SAVE IT IN VALUE + RET +POPVAL ENDP + + ; -------------------------- + ; UPDATE VALUE OF A VARIABLE + ; -------------------------- + + ; ENTRY: VALUE TO STORE IN [VALUE] + ; VARIABLE ID IN AX + PUBLIC VARPUT,PTV1$,PTV2$ +VARPUT PROC + CMP AX,0 ;LOCAL OR GLOBAL + JNE PTV1$ ;....YES. + MOV AX,VALUE ;....NO. STACK. GET VALUE + JMP PSHAXG ; AND PUSH IT ON THE GSTACK + + ;SAVE [VALUE] TO LOCAL OR GLOBAL +PTV1$: PUSH BX ;SAVE AFFECTED REGISTER(S) + MOV BX,GLOCS ;ASSUME IT'S A LOCAL + CMP AX,16 ;WAS IT A LOCAL? + JNB PTV2$ ;....NO + DEC AX ;....YES, ZERO ALIGN + JMP PTV3$ + + ; IT WAS A GLOBAL +PTV2$: MOV BX,GLOBAL ;GET GLOBAL TABLE BASE ADDRESS + SUB AX,16 ;ZERO ALIGN + +PTV3$: MOV VMP,BX ;PUT ADDRESS INTO VIRTUAL MEMORY POINTER + MOV VMP0,0 ;IT MUST BE ON AN EVEN BOUNDRY + ADD VMP,AX + MOV AX,VALUE ;GET THE VALUE + + POP BX ;RESTORE AFFECTED REGISTER(S) + JMP PW@VMP ; AND WRITE IT TO VIRTUAL + +VARPUT ENDP + + ; ---------------------------------- + ; GET A VARIABLE FROM THE MAINLOOP + ; ---------------------------------- + + ; IMPORTS: VARIABLE ID IN G-CODE + ; EXPORTS: VALUE RETURNED IN AX AND [VALUE] + PUBLIC GETVAR +GETVAR PROC + CALL GB@GPCI ;GET VARIABLE ID + JMP VARGET +GETVAR ENDP + + ; -------------------------------------- + ; GET A VARIABLE FROM WITHIN AN OPCODE + ; -------------------------------------- + + ; IMPORTS: VARIABLE ID IN [AL] + ; EXPORTS: VALUE RETURNED IN AX AND [VALUE] + PUBLIC VARGET,GTV1$,GTV2$ +VARGET PROC + CMP AL,0 ;IF ID NE. 0 + JNE GTV1$ ; THEN ACCESS A VARIABLE + JMP POPVAL ;ELSE, POP GSTACK INTO [AX] AND [VALUE] + + ; IS THE VARIABLE LOCAL OR GLOBAL +GTV1$: PUSH BX ;SAVE AFFECTED REGISTER(S) + MOV BX,GLOCS ;ASSUME IT'S A LOCAL + CMP AX,16 ;WAS IT? + JNB GTV2$ ;....NO + DEC AX ;....YES, ZERO ALIGN + JMP GTV3$ + + ; HANDLE A GLOBAL VARIABLE +GTV2$: MOV BX,GLOBAL ;GET GLOBAL TABLE BASE ADDRESS + SUB AX,16 ;POINT TO TABLE ELEMENT + +GTV3$: MOV VMP,BX ;PUT ADDRESS INTO VIRTUAL MEMORY POINTER + MOV VMP0,0 ;IT MUST BE ON AN EVEN BOUNDRY + ADD VMP,AX + CALL GW@VMP ;GET THE VARIABLE + MOV VALUE,AX ;PUT IT IN [VALUE] + POP BX ;RESTORE AFFECTED RESISTER(S) + RET + +VARGET ENDP + + ; --------------- + ; PREDICATE FAILS + ; --------------- + + ;PREDICATE HANDLERS TRUE & FALSE + ;DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FCNS + PUBLIC PREDF,PREDF1 +PREDF PROC + CALL GB@GPCI ;GET FIRST BRANCH BYTE + OR AL,AL + JNS PREDF1 ;BRANCH IF BIT 7 CLEAR + JMP PREDNB ; ELSE IGNORE PREDICATE BRANCH +PREDF1: JMP PREDB +PREDF ENDP + + ; ----------------------- + ; IGNORE PREDICATE BRANCH + ; ----------------------- + PUBLIC PREDNB,PREDN0 +PREDNB PROC + AND AL,01000000B ;TEST BIT 6 + JNZ PREDN0 ;SHORT BRANCH IF SET + JMP GB@GPCI ;ELSE SKIP OVER 2ND BRANCH BYTE +PREDN0: RET +PREDNB ENDP + + ; ------------------ + ; PREDICATE SUCCEEDS + ; ------------------ + PUBLIC PREDS,PREDS0 +PREDS PROC + CALL GB@GPCI ;GET FIRST BRANCH BYTE + OR AL,AL + JNS PREDS0 ;DON'T BRANCH IF BIT 7 IS CLEAR + JMP PREDB ; ELSE, DO A PREDICATE BRANCH +PREDS0: JMP PREDNB +PREDS ENDP + + ; -------------------------- + ; PERFORM A PREDICATE BRANCH + ; -------------------------- + + ; ENTRY: 1ST PRED BYTE IN [AL] + PUBLIC PREDB,PREDLB,DOB2,PREDB1,PREDB2,PRDB2A +PREDB PROC + SUB AH,AH ;MSB NOT USED + TEST AL,01000000B ;LONG OR SHORT BRANCH? + JZ PREDLB ;LONG IF BIT 6 IS CLEAR + + ; HANDLE A SHORT BRANCH + AND AL,00111111B ;FORM SHORT OFFSET + MOV WORD PTR VALUE,AX ;MSB OF OFFSET IS ZERO + JMP PREDB1 ;DO THE BRANCH + + ; HANDLE A LONG BRANCH +PREDLB: AND AL,00111111B ;FORM MSB OF OFFSET + TEST AL,00100000B ;CHECK SIGN OF 14-BIT VALUE + JZ DOB2 ;POSITIVE? + OR AL,11100000B ;....NO. EXTEND SIGN BIT + +DOB2: MOV BL,AL ;PUT MSB OF OFFSET IN BL + CALL GB@GPCI ;GET LSB OF 14-BIT OFFSET + MOV AH,BL ; RECOVER THE MSB + MOV VALUE,AX ;SAVE THE BRANCH OFFSET IN VALUE + + ; TEST BRANCH OFFSET +PREDB1: OR AH,AH ;CHECK MSB OF OFFSET + JNZ PREDB3 ;DO BRANCH IF NZ + OR AL,AL ;IF LSB IS NZ + JNZ PREDB2 ;MAKE SURE IT ISN'T A "1" + JMP GRFALS ; ELSE, DO AN "RFALSE" + +PREDB2: CMP AL,1 ;IS OFFSET= 1 + JNZ PRDB2A ;....NO. DO THE BRANCH + JMP GRTRUE ; ELSE, DO AN "RTRUE" + +PRDB2A: JMP PREDB3 ;EXECUTE THE "JUMP" +PREDB ENDP + + ;ENTRYPOINT FOR "JUMP" + PUBLIC PREDB3 +PREDB3 PROC + MOV AX,WORD PTR VALUE ;GET THE OFFSET + SUB AX,2 ;CALC [VALUE] - 2 + + ;CONVERT A 16-BIT OFFSET TO 17 BITS + SAR AX,1 ;PROCESS THE LS BIT, AND SIGN EXTEND + JNC PRDB3A ;SKIP IF "0" + + ; ELSE WE HAVE TO INCREMENT GPC + XOR GPC0,1 ;CHANGE THE STATE OF BIT0 + JNZ PRDB3A ;CONTINUE IF CHANGING FROM "0" TO A "1" + INC GPC ;ELSE BUMP THE REST OF GPC + +PRDB3A: ADD GPC,AX ;ADD IN THE REST OF THE OFFSET + RET +PREDB3 ENDP + + ; ------ + ; AIADR1 + ; ------ + ; + ; ENTRY: IADR1 + ; [AX] = VALUE TO BE ADDED TO IADR1 + ; + ; EXIT: IADR1 <= IADR1 + [AX] + ; +AIADR1 PROC + SHR AX,1 ;THINK ABOUT IT + JNC AIAD1 + + XOR IADR10,1 ;CHANGE THE STATE OF BIT0 + JNZ AIAD1 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC IADR1 ;ELSE BUMP THE REST OF IADR1 + +AIAD1: ADD IADR1,AX + RET +AIADR1 ENDP + + ; ------ + ; AIADR2 + ; ------ + ; + ; ENTRY: IADR2 + ; [AX] = VALUE TO BE ADDED TO IADR2 + ; + ; EXIT: IADR2 <= IADR2 + [AX] + ; +AIADR2 PROC + SHR AX,1 ;THINK ABOUT IT + JNC AIAD2 + + XOR IADR20,1 ;CHANGE THE STATE OF BIT0 + JNZ AIAD2 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC IADR2 ;ELSE BUMP THE REST OF IADR2 + +AIAD2: ADD IADR2,AX + RET +AIADR2 ENDP + + ; ------------ + ; RETURN A "0" + ; ------------ + + PUBLIC RET0 +RET0 PROC + MOV AL,0 + JMP PUTBYT +RET0 ENDP + + ; ------------ + ; RETURN A "1" + ; ------------ + + PUBLIC RET1 +RET1 PROC + MOV AL,1 + + ; AND FALL THROUGH ............. + +RET1 ENDP + + ; ----------------------- + ; RETURN A BYTE VIA [GPC] + ; ----------------------- + ; + ;RETURNS THE BYTE IN AL TO THE LOCATION SPECIFIED BY THE GPC + ;DESTROYS BX, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION + PUBLIC PUTBYT +PUTBYT PROC + SUB AH,AH ;THIS ENTRY FOR BYTE VALUE TO CLEAR HIGH BYTE + MOV VALUE,AX + JMP PUTVAL +PUTBYT ENDP + + ; --------------------------------------------------- + ; RETURN [VALUE] TO THE LOCATION SPECIFIED BY THE GPC + ; --------------------------------------------------- + + ; ENTRY: [VALUE] <= THE VALUE TO RETURN + ; [GPC] <= VARIABLE ID + ; + ; EXIT: [VALUE] IS STORED + ; GPC <= GPC + 1 + PUBLIC PUTVAL,PUTVL0,PUTVL1 +PUTVAL PROC + CALL GB@GPCI ;GET VAR TO USE + CMP AX,0 ;STACK? + JNE PUTVL0 ;NO, GO STORE VALUE + + ; VARIABLE ID=0 + ; PUSH [VALUE] ONTO THE GSTACK + MOV AX,VALUE ;GET [VALUE] + JMP PSHAXG ;PUSH IT ONTO GSTACK + + ; VARIABLE ID <> 0 + ; SAVE [VALUE] TO LOCAL OR GLOBAL +PUTVL0: PUSH BX ;SAVE AFFECTED REGISTER(S) + MOV BX,GLOCS ;ASSUME IT'S A LOCAL + CMP AX,16 ;WAS IT? + JNB PUTVL1 ;....NO + DEC AX ;....YES, ZERO ALIGN + JMP PUTVL2 + + ; HANDLE A GLOBAL VARIABLE +PUTVL1: MOV BX,GLOBAL ;GET GLOBAL TABLE BASE ADDRESS + SUB AX,16 ;POINT TO TABLE ELEMENT + +PUTVL2: MOV VMP,BX ;PUT ADDRESS INTO VIRTUAL MEMORY POINTER + MOV VMP0,0 ;IT MUST BE ON AN EVEN BOUNDRY + ADD VMP,AX + MOV AX,VALUE ;GET THE VALUE + POP BX ;RESTORE AFFECTED REGISTER(S) + JMP PW@VMP ; AND WRITE IT TO VIRTUAL + +PUTVAL ENDP + + SUBTTL GRAPHIC OPCODE SUPPORT ROUTINES + PAGE + ; ------------------------------------------- + ; GET GRAPHICS BLOCK [AL] IN CURRENT BLOCKSET + ; ------------------------------------------- + + ; ENTRY: BLOCK ID # (1-255) IN [AL] + ; EXIT: BLOCK DATA IN [BLOCK] + PUBLIC GTGBLK,GBLL +GTGBLK PROC + PUSH BX + PUSH CX + + ;CALCULATE OFFSET FROM THE START OF BLOCKSET + MOV BX,BSADR ;GET BASE ADDRESS OF BLOCKSET + MOV VMP,BX ;SETUP VMP + MOV VMP0,0 + + XOR AH,AH ; (B5) CLEAN OUT TOP HALF + MOV CL,3 + SHL AX,CL ; (B5) MULTIPLY BY COMMON BLOCK LEN + + CALL ADDVMP ;SET UP VADDR OF FIRST BYTE IN BLOCK + + ;SETUP LOOP COUNTER AND INDEX + MOV CL,4 + SUB CH,CH + MOV BX,OFFSET BLOCK + +GBLL: CALL GW@VMPI ;GET A WORD + XOR AL,NEGATE ;INVERT BITS IF NEGATE=0FFH + XOR AH,NEGATE ;INVERT BITS IF NEGATE=0FFH + XCHG AH,AL ;SWAPIFY + MOV [BX],AX ; STORE [BLOCK (BX)] + INC BX ; AND [BLOCK (BX + 1)] + INC BX ;UPDATE DESTINATION + LOOP GBLL ;LOOP TILL ALL BYTES ARE DONE + + POP CX + POP BX + RET +GTGBLK ENDP + + PUBLIC GTGFST +GTGFST PROC + CMP FSIZE,0 ; (B5) WHOLE GAME IN? + JNE GTF0 + JMP GTGBLK ; (B5) TAKE THE LONG WAY HOME + +GTF0: PUSH BX + PUSH CX + PUSH DI + PUSH SI + + ;CALCULATE OFFSET FROM THE START OF BLOCKSET + + MOV BX,0 ; (B5) FLAG TO INDICATE RESTORATION OF ES + JMP GTF1 + + ; FIX AX TO BE BLOCK ID AND USE SLOW GET BLOCK BECAUSE OF SEG + ; BOUNDARY CROSSING + +GTFIX: PUSH ES + MOV CX,ES + ADD CX,1000H + MOV ES,CX ; (B5) SET UP FOR NEXT SEG + MOV BX,1 ; (B5) SET FLAG FOR SEG RESTORE + JMP GTF4 ; (B5) GET BLOCK FROM NEXT SEG + + +GTF1: MOV CL,3 ; (B5) SHIFT COUNT + XOR AH,AH ; (B5) MULTIPLY BY BLKLEN + SHL AX,CL ; (B5) DO IT + +GTF2: ADD DI,AX ; (B5) ADD IN OFFSET + JC GTFIX + ADD DI,8 ; (B5) CHECK IF WE'LL CROSS SEG + JNC GTF3 + MOV BX,2 ; (B5) USE BX AS A FLAG FOR THIS COND +GTF3: SUB DI,8 ; (B6) FIX DI +GTF4: XCHG SI,DI ; (B5) GET POINTER + MOV DI,OFFSET BLOCK ; (B5) GET BLOCK ADDRESS + + ;SETUP LOOP COUNTER AND INDEX + MOV CL,4 + MOV CH,NEGATE + PUSH DS ; (B5) SAVE SEGS AND SWAP 'EM + PUSH ES + PUSH DS + PUSH ES + POP DS + POP ES + CMP BX,2 ; (B5) CHECK FOR WRAP INDICATOR + JNE GFLL + +GFSL: LODSW ; (B5) GET A WORD + CMP SI,0 ; (B5) CHECK FOR WRAP + JNE GFSL1 ; (B5) NOT YET + MOV BX,DS ; (B5) IT DID, FIX SEG + ADD BX,1000H ; (B5) TO ADDRESS NEXT SEG + MOV DS,BX ; (B5) FINISH FIX UP + MOV BX,0 ; (B5) RESET BX +GFSL1: XOR AL,CH ; (B5) CONTINUE PROCESS + XOR AH,CH + STOSW ; (B5) FILL IN REST OF BLOCK + DEC CL ; (B5) AND DECREMENT LOOP CNTR + JNZ GFSL ; (B5) CONTINUE IF BYTES LEFT + JMP GFRES ; (B5) OR EXIT + +GFLL: LODSW ; (B5) GET A WORD + XOR AL,CH ;INVERT BITS IF NEGATE=0FFH + XOR AH,CH ;INVERT BITS IF NEGATE=0FFH + STOSW ; (B5) STORE [BLOCK (BX)] + DEC CL + JNZ GFLL + +GFRES: POP ES + POP DS + + CMP BX,1 ; (B5) LOOK FOR RESTORE BIT + JNE GTF5 + POP ES ; (B5) SEG CROSS, RESTORE ES + +GTF5: POP SI + POP DI + POP CX + POP BX + RET +GTGFST ENDP + + ; ------------------------ + ; SETUP FOR SETI AND SWAPI + ; ------------------------ + PUBLIC ISETUP +ISETUP PROC + MOV AX,WORD PTR ARG4 ;GET WRD PTR ADDR OF DESTINATION ICON + CMP AX,IPURE ;IS DEST IN I-PRELOAD? + JB ISU ;....YES. SO CONTINUE + JMP PRERR2 ;ELSE PURITY VIOLATION! + + ; AND FALL THROUGH ............. + +ISETUP ENDP + + ; ---------------------------- + ; SETUP ENTRYPOINT FOR MASKING + ; ---------------------------- + PUBLIC ISU +ISU PROC + CALL GETI ;FETCH STATS OF DEST ICON + MOV AL,BYTE PTR IX1 ;COPY DEST ICON STATS + MOV BYTE PTR IX2,AL ;TO AUXILIARY STORAGE + MOV AL,BYTE PTR IY1 + MOV BYTE PTR IY2,AL + + MOV AX,WORD PTR IADR1 + MOV WORD PTR IADR2,AX + + MOV AL,IADR10 + MOV IADR20,AL + + MOV AX,ARG3 ;NOW GET THE SOURCE ICON STATS + + ; AND FALL THROUGH ............. + +ISU ENDP + + ; -------- + ; GET ICON + ; -------- + + ; ENTRY: V-ADDR OF ICON DATA DEFINITION IN [AX] + ; + ; EXIT: ICON DATA V-ADDR IN [IADR1] + ; X-SIZE IN [IX1] AND [XDEX1] + ; Y-SIZE IN [IY1] AND [YDEX1] + ; ASSIGNED BLOCKSET IN [BSET] + PUBLIC GETI,NEWXY +GETI PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + + MOV VMP,AX ;LOAD VIRTUAL MEMORY POINTER + MOV VMP0,0 + CALL GW@VMPI ;THE FIRST WORD HAS + MOV BYTE PTR BSET,AH ; THE ASSIGNED BLOCKSET + MOV BYTE PTR ITERS,AL ; AND THE # OF ITERATIONS + + CALL GW@VMPI ;THE SECOND WORD HAS + MOV BYTE PTR IX1,AH ; X-SIZE + MOV BYTE PTR IY1,AL ; AND Y-SIZE + + MOV AX,VMP ;GET BASE V-ADDR + MOV WORD PTR IADR1,AX ;IN [IADR1] + MOV AL,VMP0 + MOV IADR10,AL + + ; SETUP [XDEX1] & [YDEX1] +NEWXY: MOV AL,BYTE PTR IX1 + MOV BYTE PTR XDEX1,AL + MOV AL,BYTE PTR IY1 + MOV BYTE PTR YDEX1,AL + + POP BX ;RESTORE AFFECTED REGISTER(S) + RET + +GETI ENDP + + ; ----------------------------- + ; WILL SOURCE ICON FIT IN DEST? + ; ----------------------------- + + ; ENTRY: IX1 = X-SIZE OF SOURCE + ; IY1 = Y-SIZE OF SOURCE + ; IX2 = X-SIZE OF DESTINATION + ; IY2 = Y-SIZE OF DESTINATION + ; ARG1 = HORIZONTAL OFFSET OF THE SUB-IMAGE IN THE + ; DESTINATION ICON THAT IS TO BE SWAPPED + ; ARG2 = VERTICAL OFFSET OF THE SUB-IMAGE IN THE + ; DESTINATION ICON THAT IS TO BE SWAPPED + ; + ; EXIT: CARRY CLEAR IF FIT OK, ELSE CARRY SET + ; [IADR2] HAS ABSOLUTE ADDRESS OF SUB-ICON + PUBLIC DOFIT,NOFIT,FIT0,FIT1,FIT2,FIT3,FITEX +DOFIT PROC + MOV AL,BYTE PTR ARG1 ;GET X-POSITION + ADD AL,IX1 ;ADD TO THE X-SIZE OF SOURCE + CMP AL,IX2 ;COMPARE TO THE X-SIZE OF DESTINATION + JBE FIT0 ;OK IF LESS OR EQUAL +NOFIT: STC ; ELSE, SET CARRY + JMP FITEX ; AND EXIT + +FIT0: MOV AL,BYTE PTR ARG2 ;GET Y-POSITION + MOV BL,AL ;SAVE IT FOR LATER + ADD AL,IY1 ;ADD THE Y-SIZE OF SOURCE + CMP AL,IY2 ;COMPARE TO Y-SIZE OF DESTINATION + JBE FIT1 ;OK IF LESS OR EQUAL + JMP NOFIT ; ELSE, SET CARRY AND EXIT + + ; MAKE [IADR2] POINT TO ADDR OF SUB ICON +FIT1: MOV AL,BYTE PTR ARG1 ;GET X-POSITION + OR AL,AL ;IF X-POS = 0 + JZ FIT3 ; DON'T ADD X-OFFSET + +; MOV AL,BYTE PTR ARG1 ;ADD THE X-COORDINATE OF SUB-ICON + SUB AH,AH ;TO BASE ADDRESS OF DEST ICON + CALL AIADR2 ;TO GET THE BASE ADDR OF SUB-ICON + JMP FIT3 ;ALWAYS SKIP THE 1ST Y-ITERATION + +FIT2: MOV AL,BYTE PTR IX2 ;ADD THE X-SIZE OF DEST ICON + SUB AH,AH ;TO BASE ADDRESS OF SUB-ICON + CALL AIADR2 ;ONCE FOR EACH Y-COORDINATE + +FIT3: DEC BL ;OUT OF Y-COORDINATES YET? + JNS FIT2 ; NO. KEEP ADDING + CLC ;CLEAR CARRY FOR SUCCESS +FITEX: RET +DOFIT ENDP + + SUBTTL GPC VIRTUAL MEMORY ACCESS + PAGE + ; --------------------------------------------------------------- + ; The following subroutines are used to access Virtual Memory + ; through the GPC. + ; + ; G-MACHINE PROGRAM COUNTER DEFINITION + ; GPC GPC1 = MSB OF GPC GPC2 = LSB OF GPC + ; GPC0 = BIT 0 OF BYTE IS BIT 0 OF GPC + ; ---------------------------------------------------------------- + + ; ------ + ; ADDGPC + ; ------ + ; + ; ENTRY: [AX] = VALUE TO BE ADDED TO GPC + ; EXIT: GPC <= GPC + [AX] + ; +ADDGPC PROC + SHR AX,1 ;THINK ABOUT IT + JNC ADDGP1 + + XOR GPC0,1 ;CHANGE THE STATE OF BIT0 + JNZ ADDGP1 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC GPC ;ELSE BUMP THE REST OF GPC + +ADDGP1: ADD GPC,AX + RET +ADDGPC ENDP + + ; ----------------------------------------------- + ; {GB@GPC} + ; GET A BYTE OF VIRTUAL MEMORY AT THE CURRENT GPC + ; ----------------------------------------------- + ; + ; EXIT: BYTE IN [AX] + ; + PUBLIC GB@GPC +GB@GPC PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + ;CREATE AND SAVE THE LOW ADDRESS BITS + MOV AX,GPC ;GET GPC1 AND GPC2 + MOV BL,GPC0 ;GET GPC BIT + SHL AX,1 ;SHIFT GPC2 AND + OR AL,BL ; APPEND THE GPC BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,GPC ;GET VIRTUAL ADDRESS AGAIN + JMP GB@VM1 ; AND USE EXISTING CODE +GB@GPC ENDP + + ; ----------------------------- + ; {GW@GPC} + ; GET A WORD AT THE CURRENT GPC + ; ----------------------------- + ; + ; EXIT: WORD IN [AX] + ; GPC <= GPC + 2 + ; + PUBLIC GW@GPC +GW@GPC PROC + + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + ;SEE IF WE CAN LEGALLY CHEAT + CMP GPC2,0FFH ;CHEAT 510 TIMES OUT OF 512 + JNE GW@GP3 + + CMP GPC0,1 ;WE STILL HAVE A 50/50 CHANCE + JNE GW@GP3 ;....YAY! + + ; RATS, WE HAVE TO DO IT THE HARD WAY + CALL GB@GPCI ;GET THE FIRST BYTE AND POINT TO THE NEXT + MOV BL,AL ;SAVE THE MSB IN BL + CALL GB@GPC ;GET THE LSB IN AL + MOV AH,BL ;PUT THE MSB IN AH + + ; DECREMENT THE GPC + XOR GPC0,1 ;CHANGE THE STATE OF BIT0 + JZ GW@GP4 ;EXIT IF CHANGING FROM A "1" TO A "0" + DEC GPC ;ELSE DECREMENT THE REST OF THE GPC + +GW@GP4: POP CX + POP BX + RET + + ;CREATE AND SAVE THE LOW ADDRESS BITS +GW@GP3: MOV AX,GPC ;GET GPC1 AND GPC2 + MOV BL,GPC0 ;GET GPC BIT + SHL AX,1 ;SHIFT GPC2 AND + OR AL,BL ; APPEND THE GPC BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,GPC ;GET VIRTUAL ADDRESS AGAIN + JMP GW@VM1 ; AND USE EXISTING CODE +GW@GPC ENDP + + ; ----------------------------------------------- + ; {GB@GPCI} + ; GET A BYTE OF VIRTUAL MEMORY AT THE CURRENT GPC + ; AND INCREMENT THE GPC + ; ----------------------------------------------- + ; + ; EXIT: BYTE IN [AX] + ; GPC <= GPC + 1 + ; + PUBLIC GB@GPCI +GB@GPCI PROC + CALL GB@GPC ;GET THE BYTE + + ; AND FALL THROUGH ............. + +GB@GPCI ENDP + + ; ----------------- + ; {INCGPC} + ; INCREMENT THE GPC + ; ----------------- + ; + ; EXIT: GPC <= GPC + 1 + ; + PUBLIC INCGPC +INCGPC PROC + ;UPDATE THE VIRTUAL MEMORY POINTER + XOR GPC0,1 ;CHANGE THE STATE OF BIT0 + JNZ INCGP1 ;EXIT IF CHANGING FROM A "0" TO A "1" + INC GPC ;ELSE BUMP THE REST OF THE GPC +INCGP1: RET +INCGPC ENDP + + ; ----------------------------------------------- + ; {GW@GPCI} + ; GET A WORD OF VIRTUAL MEMORY AT THE CURRENT GPC + ; GPC = GPC + 2 + ; ----------------------------------------------- + ; + ; EXIT: WORD IN [AX] + ; GPC <= GPC + 2 + ; + PUBLIC GW@GPCI +GW@GPCI PROC + CALL GW@GPC ;GET THE WORD + INC GPC ;SAME AS ADDING 2 TO THE ENTIRE GPC + RET +GW@GPCI ENDP + + ; ----------------------------- + ; {PB@GPC} + ; PUT A BYTE AT THE CURRENT GPC + ; ----------------------------- + ; + ; ENTRY: [AL] = BYTE TO BE STORED + ; + ; EXIT: AL IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; + PUBLIC PB@GPC +PB@GPC PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + PUSH AX ;SAVE THE VALUE + + ;CREATE AND SAVE THE LOW ADDRESS BITS + MOV AX,GPC ;GET GPC1 AND GPC2 + MOV BL,GPC0 ;GET GPC BIT + SHL AX,1 ;SHIFT GPC2 AND + OR AL,BL ; APPEND THE GPC BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,GPC ;GET VIRTUAL ADDRESS AGAIN + JMP PB@VM1 ; AND USE EXISTING CODE +PB@GPC ENDP + + ; ----------------------------- + ; {PW@GPC} + ; PUT A WORD AT THE CURRENT GPC + ; ----------------------------- + ; + ; ENTRY: [AX] = WORD TO BE STORED + ; + ; EXIT: AX IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; + PUBLIC PW@GPC +PW@GPC PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + ;SEE IF WE CAN LEGALLY CHEAT + CMP GPC2,0FFH ;CHEAT 510 TIMES OUT OF 512 + JNE PW@GP3 + + CMP GPC0,1 ;WE STILL HAVE A 50/50 CHANCE + JNE PW@GP3 ;....YAY! + + ; RATS, WE HAVE TO DO IT THE HARD WAY + XCHG AH,AL + MOV BL,AH + CALL PB@GPCI ;STORE THE BYTE AND POINT TO THE NEXT + MOV AL,BL + CALL PB@GPC + + ; DECREMENT THE GPC + XOR GPC0,1 ;CHANGE THE STATE OF BIT0 + JZ PW@GP4 ;EXIT IF CHANGING FROM A "1" TO A "0" + DEC GPC ;ELSE DECREMENT THE REST OF THE GPC + +PW@GP4: POP CX + POP BX + RET + +PW@GP3: PUSH AX ;SAVE THE VALUE + + ;CREATE AND SAVE THE LOW ADDRESS BITS + MOV AX,GPC ;GET GPC1 AND GPC2 + MOV BL,GPC0 ;GET GPC BIT + SHL AX,1 ;SHIFT GPC2 AND + OR AL,BL ; APPEND THE GPC BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,GPC ;GET VIRTUAL ADDRESS AGAIN + + ;AND EXECUTE COMMON CODE + JMP PW@VM1 +PW@GPC ENDP + + ; ----------------------------- + ; {PB@GPCI} + ; PUT A BYTE AT THE CURRENT GPC + ; AND INCREMENT THE GPC + ; ----------------------------- + ; + ; ENTRY: [AL] = BYTE TO BE STORED + ; + ; EXIT: AL IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; GPC <= GPC + 1 + ; + PUBLIC PB@GPCI +PB@GPCI PROC + CALL PB@GPC ;WRITE OUT THE BYTE + + ;UPDATE THE VIRTUAL MEMORY POINTER + JMP INCGPC +PB@GPCI ENDP + + ; ----------------------------- + ; {PW@GPCI} + ; PUT A WORD AT THE CURRENT GPC + ; GPC = GPC + 2 + ; ----------------------------- + ; + ; ENTRY: [AX] = WORD TO BE STORED + ; + ; EXIT: AX IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; GPC <= GPC + 2 + ; + PUBLIC PW@GPCI +PW@GPCI PROC + CALL PW@GPC ;PUT THE WORD IN VIRTUAL MEMORY + INC GPC ;SAME AS ADDING 2 TO THE ENTIRE GPC + RET +PW@GPCI ENDP + + ; --------------------------------------------------- + ; {GETSHT} + ; GET A BYTE OF VIRTUAL MEMORY AT THE CURRENT GPC + ; INCREMENT THE GPC + ; AND PUT THE BYTE IN [VALUE] + ; --------------------------------------------------- + ; + ; ENTRY: G-MACHINE PROGRAM COUNTER DEFINITION + ; GPC1 = MSB OF GPC + ; GPC2 = LSB OF GPC + ; GPC0 = BIT 0 OF BYTE IS BIT 0 OF GPC + ; + ; EXIT: BTYE IN [AX] AND [VALUE] + ; GPC <= GPC + 1 + ; + ; + PUBLIC GETSHT +GETSHT PROC + CALL GB@GPCI ;GET THE BYTE IN [AL] + MOV VALUE,AX ; AND SAVE IT IN VALUE + RET +GETSHT ENDP + + ; --------------------------------------------------- + ; {GETLNG} + ; GET A WORD OF VIRTUAL MEMORY AT THE CURRENT GPC + ; GPC = GPC + 2 + ; AND PUT THE WORD IN [VALUE] + ; --------------------------------------------------- + ; + ; ENTRY: G-MACHINE PROGRAM COUNTER DEFINITION + ; GPC1 = MSB OF GPC + ; GPC2 = LSB OF GPC + ; GPC0 = BIT 0 OF BYTE IS BIT 0 OF GPC + ; + ; EXIT: WORD IN [AX] + ; GPC <= GPC + 2 + ; + ; REGISTERS DESTROYED: AX + ; + + PUBLIC GETLNG +GETLNG PROC + CALL GW@GPCI ;GET THE WORD IN [AX] + MOV VALUE,AX ; AND SAVE IT IN VALUE + RET +GETLNG ENDP + + SUBTTL VMP VIRTUAL MEMORY ACCESS + PAGE + + ; --------------------------------------------------------------- + ; The following subroutines are used to access Virtual Memory + ; through the VMP. + ; + ; VIRTUAL MEMORY POINTER DEFINITION + ; VMP VMP1 = MSB OF VMP VMP2 = LSB OF VMP + ; VMP0 = BIT 0 OF BYTE IS BIT 0 OF VMP + ; ---------------------------------------------------------------- + + ; ------ + ; ADDVMP + ; ------ + ; + ; ENTRY: [AX] = VALUE TO BE ADDED TO VMP + ; EXIT: VMP <= VMP + [AX] + ; +ADDVMP PROC + SHR AX,1 ;THINK ABOUT IT + JNC ADDVM1 + + XOR VMP0,1 ;CHANGE THE STATE OF BIT0 + JNZ ADDVM1 ; CONTINUE IF CHANGING FROM A "0" TO A "1" + INC VMP ;ELSE BUMP THE REST OF VMP + +ADDVM1: ADD VMP,AX + RET +ADDVMP ENDP + + ; ----------------------------------------------- + ; {GB@VMP} + ; GET A BYTE OF VIRTUAL MEMORY AT THE CURRENT VMP + ; ----------------------------------------------- + ; + ; EXIT: BYTE IN [AX] + ; + PUBLIC GB@VMP +GB@VMP PROC + ;CREATE AND SAVE THE LOW ADDRESS BITS + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + MOV AX,VMP ;GET VMP1 AND VMP2 + MOV BL,VMP0 ;GET VMP BIT + SHL AX,1 ;SHIFT VMP2 AND + OR AL,BL ; APPEND THE VMP BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,VMP ;GET VIRTUAL ADDRESS AGAIN + + ; AND FALL THROUGH ............. + +GB@VMP ENDP + + ; -------------------------------- + ; CODE COMMON TO GB@VMP AND GB@GPC + ; -------------------------------- + +GB@VM1 PROC + MOV VPAGEN,AH ; SAVE THE VIRTUAL PAGE NUMBER + + ;PAGE IN THE BLOCK OF VIRTUAL MEMORY + CALL GTVBLK ; AND MAKE LOC VALID + + ;RESTORE LADD AND MAKE A FULLY FORMED ADDRESS + MOV AL,LOC ;GET THE ABSOLUTE BLOCK NUMBER + SUB AH,AH + SHL AX,1 ;SHIFT THE SEGMENT BIT INTO BIT 8 AND A "0" + ; INTO BIT 0, PUTTING THE HIGHER ADDRESS BITS + ; IN [AL] AND THE SEGMENT BIT IN [AH] + MOV BX,LADD ;RESTORE THE LOWER ADDRESS BITS + OR BH,AL ;COMBINE THE LOWER AND HIGHER ADDRESS BITS + + ;DETERMINE THE PROPER SEGMENT + MOV CX,SEG0 ;PRE-POINT AT SEG0 + OR AH,AH ;TEST SEGMENT BIT + JZ GB@VM2 ;IF "0" THEN IT'S SEG0 + MOV CX,SEG1 ; ELSE POINT TO THE OTHER SEGMENT +GB@VM2: MOV ES,CX ;ES POINTS TO THE CORRECT SEGMENT + + ;GET THE BYTE + MOV AL,ES:[BX] ;GET THE BYTE + SUB AH,AH ;GET RID OF UNWANTED BYTE + POP CX ;RESTORE AFFECTED REGISTER(S) + POP BX + RET +GB@VM1 ENDP + + ; ----------------------------- + ; {GW@VMP} + ; GET A WORD AT THE CURRENT VMP + ; ----------------------------- + ; + ; EXIT: WORD IN [AX] + ; VMP <= VMP + 2 + ; + PUBLIC GW@VMP +GW@VMP PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + ;SEE IF WE CAN LEGALLY CHEAT + CMP VMP2,0FFH ;CHEAT 510 TIMES OUT OF 512 + JNE GW@VM3 + + CMP VMP0,1 ;WE STILL HAVE A 50/50 CHANCE + JNE GW@VM3 ;....YAY! + + ; RATS, WE HAVE TO DO IT THE HARD WAY + CALL GB@VMPI ;GET THE BYTE AND POINT TO THE NEXT + MOV BL,AL + CALL GB@VMP ;GET THE SECOND BYTE + MOV AH,BL ;FORM THE WORD + + ; DECREMENT THE VMP + XOR VMP0,1 ;CHANGE THE STATE OF BIT0 + JZ GW@VM4 ;EXIT IF CHANGING FROM A "1" TO A "0" + DEC VMP ;ELSE DECREMENT THE REST OF THE VMP + +GW@VM4: POP CX + POP BX + RET + + ;CREATE AND SAVE THE LOW ADDRESS BITS +GW@VM3: MOV AX,VMP ;GET VMP1 AND VMP2 + MOV BL,VMP0 ;GET VMP BIT + SHL AX,1 ;SHIFT VMP2 AND + OR AL,BL ; APPEND THE VMP BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,VMP ;GET VIRTUAL ADDRESS AGAIN + + ; AND FALL THROUGH ............. + +GW@VMP ENDP + + ; -------------------------------- + ; CODE COMMON TO GW@VMP AND GW@GPC + ; -------------------------------- + +GW@VM1 PROC + MOV VPAGEN,AH ; SAVE THE VIRTUAL PAGE NUMBER + + ;PAGE IN THE BLOCK OF VIRTUAL MEMORY + CALL GTVBLK ; AND MAKE LOC VALID + + ;RESTORE LADD AND MAKE A FULLY FORMED ADDRESS + MOV AL,LOC ;GET THE ABSOLUTE BLOCK NUMBER + SUB AH,AH + SHL AX,1 ;SHIFT THE SEGMENT BIT INTO BIT 8 AND A "0" + ; INTO BIT 0, PUTTING THE HIGHER ADDRESS BITS + ; IN [AL] AND THE SEGMENT BIT IN [AH] + MOV BX,LADD ;RESTORE THE LOWER ADDRESS BITS + OR BH,AL ;COMBINE THE LOWER AND HIGHER ADDRESS BITS + + ;DETERMINE THE PROPER SEGMENT + MOV CX,SEG0 ;PRE-POINT AT SEG0 + OR AH,AH ;TEST SEGMENT BIT + JZ GW@VM2 ;IF "0" THEN IT'S SEG0 + MOV CX,SEG1 ; ELSE POINT TO THE OTHER SEGMENT +GW@VM2: MOV ES,CX ;ES POINTS TO THE CORRECT SEGMENT + + ;GET THE WORD + MOV AX,ES:[BX] ;GET THE WORD + XCHG AH,AL ;SWAPIFY + + POP CX ;RESTORE AFFECTED REGISTER(S) + POP BX + RET +GW@VM1 ENDP + + ; ----------------------------------------------- + ; {GB@VMPI} + ; GET A BYTE OF VIRTUAL MEMORY AT THE CURRENT VMP + ; AND INCREMENT THE VMP + ; ----------------------------------------------- + ; + ; EXIT: BYTE IN [AX] + ; VMP <= VMP + 1 + ; + PUBLIC GB@VMPI +GB@VMPI PROC + CALL GB@VMP ;GET THE BYTE + + ; AND FALL THROUGH ............. + +GB@VMPI ENDP + + ; ----------------- + ; {INCVMP} + ; INCREMENT THE VMP + ; ----------------- + ; + ; EXIT: VMP <= VMP + 1 + ; + PUBLIC INCVMP +INCVMP PROC + ;UPDATE THE VIRTUAL MEMORY POINTER + XOR VMP0,1 ;CHANGE THE STATE OF BIT0 + JNZ INCMP1 ;EXIT IF CHANGING FROM A "0" TO A "1" + INC VMP ;ELSE BUMP THE REST OF THE VMP +INCMP1: RET +INCVMP ENDP + + ; ----------------------------------------------- + ; {GW@VMPI} + ; GET A WORD OF VIRTUAL MEMORY AT THE CURRENT VMP + ; VMP = VMP + 2 + ; ----------------------------------------------- + ; + ; EXIT: WORD IN [AX] + ; VMP <= VMP + 2 + ; + PUBLIC GW@VMPI +GW@VMPI PROC + CALL GW@VMP ;GET THE WORD + INC VMP ;SAME AS ADDING 2 TO THE ENTIRE VMP + RET +GW@VMPI ENDP + + ; ----------------------------- + ; {PB@VMP} + ; PUT A BYTE AT THE CURRENT VMP + ; ----------------------------- + ; + ; ENTRY: [AL] = BYTE TO BE STORED + ; + ; EXIT: AL IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; + PUBLIC PB@VMP +PB@VMP PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + PUSH AX ;SAVE THE VALUE + + ;CREATE AND SAVE THE LOW ADDRESS BITS + MOV AX,VMP ;GET VMP1 AND VMP2 + MOV BL,VMP0 ;GET VMP BIT + SHL AX,1 ;SHIFT VMP2 AND + OR AL,BL ; APPEND THE VMP BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,VMP ;GET VIRTUAL ADDRESS AGAIN + + ; AND FALL THROUGH ............. + +PB@VMP ENDP + + ; -------------------------------- + ; CODE COMMON TO PB@VMP AND PB@GPC + ; -------------------------------- + +PB@VM1 PROC + MOV VPAGEN,AH ; TO SAVE THE VIRTUAL PAGE NUMBER + + ;PAGE IN THE BLOCK OF VIRTUAL MEMORY + CALL GTVBLK ; AND MAKE LOC VALID + + ;RESTORE LADD AND MAKE A FULLY FORMED ADDRESS + MOV AL,LOC ;GET THE ABSOLUTE BLOCK NUMBER + SUB AH,AH + SHL AX,1 ;SHIFT THE SEGMENT BIT INTO BIT 8 AND A "0" + ; INTO BIT 0, PUTTING THE HIGHER ADDRESS BITS + ; IN [AL] AND THE SEGMENT BIT IN [AH] + MOV BX,LADD ;RESTORE THE LOWER ADDRESS BITS + OR BH,AL ;COMBINE THE LOWER AND HIGHER ADDRESS BITS + + ;DETERMINE THE PROPER SEGMENT + MOV CX,SEG0 ;PRE-POINT AT SEG0 + OR AH,AH ;TEST SEGMENT BIT + JZ PB@VM2 ;IF "0" THEN IT'S SEG0 + MOV CX,SEG1 ; ELSE POINT TO THE OTHER SEGMENT +PB@VM2: MOV ES,CX ;ES POINTS TO THE CORRECT SEGMENT + + ;STORE THE BYTE + POP AX ;RESTORE THE BYTE + MOV ES:[BX],AL + + POP CX ;RESTORE AFFECTED REGISTER(S) + POP BX + RET +PB@VM1 ENDP + + ; ----------------------------- + ; {PW@VMP} + ; PUT A WORD AT THE CURRENT VMP + ; ----------------------------- + ; + ; ENTRY: [AX] = WORD TO BE STORED + ; + ; EXIT: AX IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; + PUBLIC PW@VMP +PW@VMP PROC + PUSH BX ;SAVE AFFECTED REGISTER(S) + PUSH CX + + ;SEE IF WE CAN LEGALLY CHEAT + CMP VMP2,0FFH ;CHEAT 510 TIMES OUT OF 512 + JNE PW@VM3 + + CMP VMP0,1 ;WE STILL HAVE A 50/50 CHANCE + JNE PW@VM3 ;....YAY! + + ; RATS, WE HAVE TO DO IT THE HARD WAY + XCHG AH,AL + MOV BL,AH + CALL PB@VMPI ;STORE THE BYTE AND POINT TO THE NEXT + MOV AL,BL + CALL PB@VMP + + ; DECREMENT THE VMP + XOR VMP0,1 ;CHANGE THE STATE OF BIT0 + JZ PW@VM4 ;EXIT IF CHANGING FROM A "1" TO A "0" + DEC VMP ;ELSE DECREMENT THE REST OF THE VMP + +PW@VM4: POP CX + POP BX + RET + +PW@VM3: PUSH AX ;SAVE THE VALUE + + ;CREATE AND SAVE THE LOW ADDRESS BITS + MOV AX,VMP ;GET VMP1 AND VMP2 + MOV BL,VMP0 ;GET VMP BIT + SHL AX,1 ;SHIFT VMP2 AND + OR AL,BL ; APPEND THE VMP BIT + AND AX,01FFH ; AND ISOLATE THE LADD BITS + MOV LADD,AX ;SAVE LOW ADDRESS BITS + + ;CREATE AND SAVE THE VIRTUAL PAGE NUMBER + MOV AX,VMP ;GET VIRTUAL ADDRESS AGAIN + + ; AND FALL THROUGH ............. + +PW@VMP ENDP + + ; -------------------------------- + ; CODE COMMON TO PW@VMP AND PW@GPC + ; -------------------------------- + +PW@VM1 PROC + MOV VPAGEN,AH ; TO SAVE THE VIRTUAL PAGE NUMBER + + ;PAGE IN THE BLOCK OF VIRTUAL MEMORY + CALL GTVBLK ; AND MAKE LOC VALID + + ;RESTORE LADD AND MAKE A FULLY FORMED ADDRESS + MOV AL,LOC ;GET THE ABSOLUTE BLOCK NUMBER + SUB AH,AH + SHL AX,1 ;SHIFT THE SEGMENT BIT INTO BIT 8 AND A "0" + ; INTO BIT 0, PUTTING THE HIGHER ADDRESS BITS + ; IN [AL] AND THE SEGMENT BIT IN [AH] + MOV BX,LADD ;RESTORE THE LOWER ADDRESS BITS + OR BH,AL ;COMBINE THE LOWER AND HIGHER ADDRESS BITS + + ;DETERMINE THE PROPER SEGMENT + MOV CX,SEG0 ;PRE-POINT AT SEG0 + OR AH,AH ;TEST SEGMENT BIT + JZ PW@VM2 ;IF "0" THEN IT'S SEG0 + MOV CX,SEG1 ; ELSE POINT TO THE OTHER SEGMENT +PW@VM2: MOV ES,CX ;ES POINTS TO THE CORRECT SEGMENT + + ;STORE THE WORD + POP AX ;RESTORE THE WORD + XCHG AH,AL ;SWAPIFY + MOV ES:[BX],AX ;WRITE IT OUT + + POP CX ;RESTORE AFFECTED REGISTER(S) + POP BX + RET +PW@VM1 ENDP + + + ; ----------------------------- + ; {PB@VMPI} + ; PUT A BYTE AT THE CURRENT VMP + ; AND INCREMENT THE VMP + ; ----------------------------- + ; + ; ENTRY: [AL] = BYTE TO BE STORED + ; + ; EXIT: AL IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; VMP <= VMP + 1 + ; + PUBLIC PB@VMPI +PB@VMPI PROC + CALL PB@VMP ;WRITE OUT THE BYTE + + ;UPDATE THE VIRTUAL MEMORY POINTER + JMP INCVMP +PB@VMPI ENDP + + ; ----------------------------- + ; {PW@VMPI} + ; PUT A WORD AT THE CURRENT VMP + ; VMP = VMP + 2 + ; ----------------------------- + ; + ; ENTRY: [AX] = WORD TO BE STORED + ; + ; EXIT: AX IS STORED AT THE SELECTED VIRTUAL ADDRESS + ; VMP <= VMP + 2 + ; + PUBLIC PW@VMPI +PW@VMPI PROC + CALL PW@VMP ;PUT THE WORD IN VIRTUAL MEMORY + INC VMP ;SAME AS ADDING 2 TO THE ENTIRE VMP + RET +PW@VMPI ENDP + + ;------------------------------------------------ + ; E N D O F S U B R O U T I N E S + ;------------------------------------------------ + + + SUBTTL COLD START + PAGE + ;---------------------------------------------------------------------- + ; C O L D S T A R T + ;---------------------------------------------------------------------- + + PUBLIC DIPBGN,REST1,REST2 +DIPBGN PROC + CALL SYSINI ;DO ANY SYSTEM INITIALIZATION + + CALL MTIME ;INITIALIZE RANDOM NUMBER GENERATOR + + MOV WORD PTR OLDGSP,DI ;INITIALIZE OLD GSTACK POINTER + + ; SET DEFAULT CLIPPING PARAMETERS + MOV WINDX1,0 ;FULL SCREEN + MOV WINDY1,0 + MOV WINDX2,39 + MOV WINDY2,23 + MOV WINDH,24 ;WINDH = (WINDY2 - WINDY1) + 1 + MOV WINDW,40 ;WINDW = (WINDX2 - WINDX1) + 1 + + ; + ; GET G-PRELOAD INTO THE BUFFER AREA + ; + + ; INITIALIZE GCODE + MOV GCODE,0 + + ; GET THE FIRST BLOCK OF G-PRELOAD + MOV VPAGEN,0 ;VIRTUAL BLOCK 0 + CALL GTPBLK ;GET PRELOAD BLOCK + + ; GET THE GAME ID FOR SAVE/RESTORE AND POSTERITY + ; + MOV VMP,0 ;SET UP VIRTUAL MEMORY ADDRESS POINTER + MOV VMP0,0 ; TO RETRIEVE [GEND] + MOV AX,GID + CALL ADDVMP + CALL GW@VMP ;GET THE END OF G-PRELOAD (WORDPTR) + MOV ZORKID,AX ; SAVE IT AWAY + + ; EXTRACT DATA FROM G-PRELOAD HEADER + ; DETERMINE THE NUMBER OF PAGES IN G-PRELOAD + ; GET THE VIRTUAL ADDRESS OF THE START OF G-PURELOAD + MOV VMP,0 ;SET UP VIRTUAL MEMORY ADDRESS POINTER + MOV VMP0,0 ; TO RETRIEVE [GEND] + MOV AX,GEND + CALL ADDVMP + CALL GW@VMP ;GET THE END OF G-PRELOAD (WORDPTR) + + ; SEE IF THE 1ST. VIRTUAL PAGE OF G-PURELOAD CONTAINS ANY G-PRELOAD + OR AL,AL ;IS THERE A PARTIAL PRE-LOAD RECORD? + JZ NOGPRT ;NOPE + INC AH ;YUP + + ; NO G-CODE PARTIAL RECORD + ; DETERMINE THE TOTAL NUMBER OF PAGES IN G-PRELOAD +NOGPRT: MOV GPEND,AH ;SAVE IT, IT'S THE FIRST VIRTUAL BLOCK + ; # OF G-PURELOAD + MOV GPRBLK,AH ; AND THE TOTAL NUMBER OF + ; G-PRELOAD BLOCKS + + ; DO WE HAVE ENOUGH ROOM IN THE PAGING AREA FOR G-PRELOAD? + CMP BUFFERS,AH + JA GOTRM1 ;....YES + + ; *** ERROR #0: GAME PRELOAD IS TOO BIG *** +NOGRAM: MOV AL,0 + JMP GERROR + + ; GET THE REST OF G-PRELOAD INTO THE BUFFER AREA + ; USE GSTRT TO DETERMINE THE NUMBER OF G-PRELOAD BLOCKS TO + ; TO BE LOADED +GOTRM1: MOV AL,GMAJOR ; SET INTERPRETER VERSION + MOV AH,GMINOR ; LETTER AND NUMBER + MOV WORD PTR ES:[GINTVER],AX ; STORE INTERPRETER VERSION + MOV CL,GPRBLK ;GET TOTAL NUMBER OF G-PRELOAD BLOCKS + DEC CL ;-1 SINCE WE'VE ALREADY DONE THE 1ST. + JZ GTIPRE ;LEAVE IF IT WAS THE ONLY PRELOAD BLOCK + SUB CH,CH ;INITIALIZE LOOP COUNTER + MOV VPAGEN,1 ;START WITH VIRTUAL BLOCK #1 + + ; LOAD THE REMAINING G-PRELOAD LOOP +LGPRLP: PUSH CX ;SAVE LOOP COUNTER + CALL GTPBLK ;GET THE PRELOAD BLOCK + INC VPAGEN ;NEXT BLOCK + POP CX ;RESTORE LOOP COUNTER + LOOP LGPRLP ;CONTINUE UNTIL ALL OF G-PRELOAD IS IN + + ; + ; GET I-PRELOAD INTO THE BUFFER AREA + ; + + ; CALCULATE 1ST. VIRTUAL PAGE OF THE IFILE +GTIPRE: MOV VMP,0 ;GET THE LENGTH OF THE G-PROGRAM + MOV VMP0,0 ; IN WORDS + MOV AX,GLEN + CALL ADDVMP + CALL GW@VMP + + ;PATCH FOR PADDING PURPOSES + INC AX ;ICODE IS AT THE NEXT WORD ADDRESS + + MOV ICODE,AX ;SAVE VIRTUAL STARTING ADDRESS + MOV ISTRT,AH ; AND STARTING VIRTUAL PAGE NUMBER + + ; GET THE FIRST BLOCK OF I-PRELOAD + MOV VPAGEN,AH ;SETUP THE VIRTUAL PAGE NUMBER + CALL GTPBLK ; AND GET THE FIRST BLOCK OF I-PRELOAD + + ; DETERMINE VIRTUAL ADDRESS OF IPURE + MOV AX,ICODE + MOV VMP,AX + MOV VMP0,0 + MOV AX,IEND + CALL ADDVMP + CALL GW@VMP ;GET THE LENGTH OF I-PRELOAD IN WORDS + + INC AX ;I-PURE STARTS AT THE NEXT EVEN ADDRESS + MOV BX,ICODE ;GET OFFSET TO THE START OF THE IFILE + ADD AX,BX ;ADD STARTING ADDRESS + ; TO GET A GFILE RELATIVE ADDRESS + MOV IPURE,AX ;SAVE CORRECTED START OF I-PURE + + ; + ; GET THE REST OF I-PRELOAD INTO THE BUFFER AREA + ; + + ; DETERMINE THE NUMBER OF BLOCKS OF I-PRELOAD REMAINING + ; DETERMINE THE TOTAL NUMBER OF I-PRELOAD BLOCKS + ; USE THE STARTING I-PRELOAD VIRTUAL BLOCK NUMBER + ; TO DETERMINE AN ADJUSTED SIZE OF I-PRELOAD + + MOV BH,ISTRT ;GET VIRTUAL I-PRELOAD STARTING PAGE + SUB BL,BL ; PAGE ALIGN IT + MOV AX,IPURE ;GET THE RELATIVIZED STARTING + ; ADDRESS OF IPURE + SUB AX,BX ;SUBTRACT ZERO ADJUSTED STARTING ADDR + + ; SEE IF THE 1ST. VIRTUAL PAGE OF IPURE CONTAINS ANY I-PRELOAD + OR AL,AL ;SEE IF THERE'S A PARTIAL RECORD + JZ NOIPRT ;NOPE + INC AH ;YUP + +NOIPRT: MOV IPRBLK,AH ;SAVE TOTAL NUMBER OF I-PRELOAD BLOCKS + + ; DO WE HAVE ENOUGH ROOM IN THE PAGING AREA FOR I-PRELOAD? + ADD AH,GPRBLK ;ADD IN THE NUMBER OF G-PRELOAD BLOCKS + CMP BUFFERS,AH + JA NOIP1 + JMP NOGRAM ;....NO + +NOIP1: MOV CL,IPRBLK ;GET THE NUMBER OF I-PRELOAD BLOCKS + OR CL,CL ;SINCE IT'S POSSIBLE TO HAVE NONE + JZ INITAB ; WE HAVE TO CHECK FOR IT + DEC CL ;-1 SINCE WE'VE ALREADY DONE THE 1ST. + JZ INITAB ;LEAVE IF IT WAS THE ONLY PRELOAD BLOCK + SUB CH,CH ;INITIALIZE LOOP COUNTER + + ;INITIALIZE VALUES FOR I-PRELOAD LOOP + MOV AL,ISTRT ;GET VIRTUAL I-PRELOAD STARTING BLOCK # + INC AL ;ADD 1 SINCE WE'VE ALREADY LOADED THE + ; FIRST BLOCK + MOV VPAGEN,AL ;SAVE STARTING BLOCK # + + ; LOAD REMAINING I-PRELOAD LOOP +LIPRLP: PUSH CX ;SAVE LOOP COUNTER + CALL GTPBLK ;GET THE BLOCK + INC VPAGEN ;NEXT BLOCK + POP CX ;RESTORE LOOP COUNTER + LOOP LIPRLP ;CONTINUE UNTIL ALL OF I-PRELOAD IS IN + + + ; IF THE GAME FITS IN AVAILABLE MEMORY, + ; READ THE WHOLE THING IN + + CMP FSIZE,0 ; (B4) DOES THE GAME FIT? + JE SLURP1 + MOV DL,GPRBLK ; (B4) SO START SLURPING + XOR DH,DH ; (B4) SCRAP TOP HALF + MOV CL,9 ; (B4) CONVERT TO BYTES + SHL DX,CL ; (B4) OF G-PRELOAD + MOV CX,0 ; (B4) SET UP FOR SEEK + MOV BX,GAMHNDL + MOV AX,4200H ; (B4) SEEK PAST B-O-F + INT 21H + PUSH DS ; (B4) USE GAME BUFFER + MOV CX,SEG0 ; (B4) MAKE ADDRESSIBLE THRU DS + MOV DS,CX + MOV DX,AX ; (B4) SAVE OFFSET + MOV AX,0H ; (B4) HOW MANY BYTES TO END OF SEG? + SUB AX,DX ; (B4) ONE SEG IN LENGTH + MOV CX,AX ; (B4) THAT'S HOW MANY TO READ FIRST + MOV AH,CRDRNDZ ; (B4) READ THAT AMOUNT + INT 21H + CMP AX,CX ; (B4) THAT COULD BE THE END... + JNE SLURP + MOV AX,DS ; (B4) MAKE NEXT SEG ADDRESSIBLE + ADD AX,1000H ; (B4) 64K ABOVE THE FIRST + MOV DS,AX + MOV CX,0FFFFH ; (B4) READ UP TO ANOTHER 64K + MOV DX,0 ; (B4) STARTING AT THE BEGINNING + MOV AH,CRDRNDZ ; (B4) READ IT ALL IN + INT 21H +SLURP: POP DS + PUSH DI + PUSH ES ; (B4) SAVES + PUSH DS ; (B4) MAKE DS ADDRESSIBLE THRU ES + POP ES + MOV AL,1 ; (B4) ALL PAGES WILL BE PRELOAD + MOV CX,0FFH + MOV DI,OFFSET MEMMAP ; (B4) FILL TABLE TO INDICATE ALL IN +SLURP2: MOV AH,CL ; (B4) FILL IN BUF NUMBER + SUB AH,0FFH ; (B4) FROM 0 - FF + NEG AH ; (B4) RECTIFY + STOSW ; (B4) STORE IT + LOOP SLURP2 + POP ES + POP DI +SLURP1: + + + ; + ; INITIALIZE POINTERS TO VARIABLES + ; + + ; GLOBAL TABLE [GLOBAL] +INITAB: MOV AX,GCODE + MOV VMP,AX + MOV VMP0,0 + MOV AX,GGLOB + CALL ADDVMP + CALL GW@VMP ;GET POINTER TO GLOBAL TABLE + MOV GLOBAL,AX ;SAVE IT + + ; LOCAL TABLE [GLOCS] + SUB AX,0FH ;BACK UP 15 WORDS FOR LOCALS + MOV GLOCS,AX ;STORE PTR TO START OF LOCALS + + ; + ; REPAIR PREDEFINED GLOBALS 16, 17, 18, AND 19 + ; + + ; GLOBAL 16 - NUMBER OF BLOCKSETS + MOV AX,ICODE + MOV GPC,AX + MOV GPC0,0 + MOV AX,IBLKS + CALL ADDGPC + CALL GETSHT ;GET THE NUMBER OF BLOCKSETS IN VALUE + MOV NBLOKS,AL ;STORE IT IN NBLOKS + MOV AX,16 ; AND IN GLOBAL #16 + CALL VARPUT + + ; GLOBAL 17 - POINTER TO BLOCKSET POINTER TABLE + MOV AX,ICODE ;GET OFFSET TO THE START OF IFILE + ADD AX,4 ;BPT IS 8-BYTES FURTHER DOWN + MOV BTAB,AX ;SAVE VIRTUAL ADDRESS OF BPT + MOV VALUE,AX ;PUT IT IN VALUE, SO WE CAN + MOV AX,17 ;STORE THE VIRTUAL ADDRESS OF THE + CALL VARPUT ; BLOCKSET POINTER TABLE IN GLOBAL #17 + + ; GLOBAL 18 - NUMBER OF ICONS + MOV AX,ICODE + MOV GPC,AX + MOV GPC0,0 + MOV AX,IICONS + CALL ADDGPC + CALL GETSHT ;GET THE NUMBER OF ICONS IN VALUE + MOV NICONS,AL ;SAVE NUMBER OF ICONS + MOV AX,18 ;STORE NICONS IN GLOBAL #18 + CALL VARPUT + + ; GLOBAL 19 - PTR TO ICON PTR TABLE + MOV AL,NBLOKS ;GET NO. OF BLOCKSETS + SUB AH,AH +; SHL AX,1 ;WORDIFY IT TO GET SIZE OF BLOCKSET TBL +; SHR AX,1 ; AND DEWORDIFY 'CAUSE BPT IS A WRDPTR + MOV CX,BTAB ;GET THE BPT VIRTUAL ADDRESS + ADD AX,CX ;POINT PAST THE BPT + MOV ITAB,AX ;SAVE VIRTUAL ADDRESS OF IPT + MOV VALUE,AX ;PUT IT IN VALUE, SO WE CAN + MOV AX,19 ;STORE THE VIRTUAL ADDRESS OF + CALL VARPUT ; THE ICON POINTER TABLE IN GLOBAL #19 + + ; + ; TABLE PATCHING + ; + + ; RELATIVIZE THE BPT TO THE START OF THE GFILE + ; INITIALIZE LOOP COUNTER WITH THE NO. OF BLOCKSETS + MOV CL,NBLOKS + SUB CH,CH + + ; POINT TO THE BPT + MOV AX,BTAB + MOV VMP,AX + MOV VMP0,0 + + ; GET THE OFFSET TO THE START OF THE IFILE + MOV DX,ICODE + +REST1: PUSH CX ;SAVE LOOP COUNTER + PUSH DX ;SAVE OFFSET + CALL GW@VMP ;GET THE BLOCKSET POINTER + POP DX ;RESTORE OFFSET + PUSH DX ;SAVE OFFSET + ADD AX,DX ; RELATIVIZE IT + CALL PW@VMPI ;SAVE POINTER + POP DX ;RESTORE OFFSET + POP CX ;RESTORE LOOP COUNTER + LOOP REST1 ;CONTINUE TILL WE'VE DONE THEM ALL + + ; RELATIVIZE THE IPT TO THE START OF THE GFILE + ; INITIALIZE LOOP COUNTER WITH THE NO. OF ICONS + MOV CL,NICONS + SUB CH,CH + + ; POINT TO THE IPT + MOV AX,ITAB + MOV VMP,AX + MOV VMP0,0 + + ; GET THE OFFSET TO THE START OF THE IFILE + MOV DX,ICODE + +REST2: PUSH CX ;SAVE LOOP COUNTER + PUSH DX ;SAVE OFFSET + CALL GW@VMP ;GET THE ICON POINTER + POP DX ;RESTORE OFFSET + PUSH DX ;SAVE OFFSET + ADD AX,DX ; RELATIVIZE IT + CALL PW@VMPI ;SAVE POINTER + POP DX ;RESTORE OFFSET + POP CX ;RESTORE LOOP COUNTER + LOOP REST2 ;CONTINUE TILL WE'VE DONE THEM ALL + + ; + ; INITIALIZE THE INTERPRETER PROGRAM COUNTER + ; + + ; GET THE EXECUTION STARTING ADDRESS FROM WITHIN THE G-FILE + MOV VMP,0 + MOV VMP0,0 + MOV AX,GSTART ;OFFSET TO G-PROGRAM STARTING ADDRESS + CALL ADDVMP ;FORM THE VMP ADDRESS + CALL GW@VMP ;GET STARTING ADDRESS + + ; LOAD THE GPC WITH THE START ADDRESS + MOV GPC,AX + MOV GPC0,1 + JMP MLOOP ; AND JUMP INTO THE MAINLOOP + +DIPBGN ENDP + + SUBTTL MAIN LOOP + PAGE + ;---------------------------------------------------------------------- + ; INSTRUCTION INTERPRETATION LOOP + ;---------------------------------------------------------------------- + PUBLIC MLOOP,DC0,DC1,DC2,OPEXT,TOPX,OPX1,OPX2,OPX3,OPX4 + PUBLIC OPXNXT,DOXOP,DODIS,OP0,OP1,OP1A,OP1B,OP1EX,BADOP1 + PUBLIC OP2,OP2A,OP2B,OP2C,OP2D,OP2EX,OP2F +MLOOP PROC + + ; + ; INITIALIZE LOOP + ; + + MOV NARGS,0 ;CLEAR #ARGS + CALL GB@GPCI ;GET THE OPERATION BYTE + MOV OPCODE,AL ;SAVE A COPY + + ;debug + CMP GPC,1234H + JNE MLP1 + JMP MLP1 + ; + ; DETERMINE OPCODE TYPE + ; + + ; IF OPCODE IS POSITIVE ( < 80H ) THEN IT'S A 2-OP (SHORT FORM) +MLP1: CMP AL,80H ;IS IT A 2-OP (SHORT FORM)? + JNB DC0 ;....NO. + JMP OP2 ;....YES, GO DO IT + + ; IF OPCODE = 0E0H THEN IT'S GCALL + ; WHICH IS HANDLED AS A SPECIAL CASE +DC0: CMP AL,0E0H ;IS IT "CALL"? + JNE DC1 ;....NO. + JMP GCALL ;....YES. + + ; IF OPCODE < 0B0H THEN IT'S A 1-OP +DC1: CMP AL,0B0H ;NO, IS IT A 1-OP? + JNB DC2 ;....NO. + JMP OP1 ;....YES. + + ; IF OPCODE < 0C0H THEN IT'S A 0-OP + ; ELSE IT'S A X-OP +DC2: CMP AL,0C0H ;IS IT AN 0-OP? + JNB OPEXT ;....NO. IT IS AN X-OP + JMP OP0 ;....YES. + + ; -------------- + ; HANDLE AN X-OP + ; -------------- + +OPEXT: CALL GB@GPCI ;GRAB ARGUMENT BYTE + MOV BYTE PTR ABYTE,AL ;SAVE IT + + SUB BX,BX + MOV BYTE PTR ADEX,BL ;INIT LOOP INDEX + JZ OPX1 ;UNCONDITIONAL JUMP (ENTER LOOP) + +TOPX: MOV AL,BYTE PTR ABYTE ;GET ARG BYTE + SAL AL,1 ;SHIFT NEXT 2 ARG BITS + SAL AL,1 ;INTO BITS 7 & 6 + MOV BYTE PTR ABYTE,AL ;HOLD FOR LATER + +OPX1: AND AL,11000000B ;ISOLATE ARGUMENT BITS + JNZ OPX2 ;IS IT A LONG IMMEDIATE? + + ; 00 = LONG IMMEDIATE + CALL GETLNG + JMP OPXNXT + +OPX2: CMP AL,01000000B ;IS IT A SHORT IMMEDIATE? + JNZ OPX3 ;....NO, KEEP GUESSING + + ; 01 = SHORT IMMEDIATE + CALL GETSHT + JMP OPXNXT + +OPX3: CMP AL,10000000B ;LAST TEST. VARIABLE? + JNZ OPX4 ;....NO. NO MORE ARGUMENTS + + ; 10 = VARIABLE + CALL GETVAR + +OPXNXT: MOV BL,ADEX ;RESTORE ARGUMENT INDEX + SUB BH,BH ;CLEAR OUT HIGH BYTE + MOV AX,WORD PTR VALUE ;GRAB VALUE + MOV WORD PTR ARG1 [BX],AX ;STORE IN ARGUMENT TABLE + INC NARGS ;UPDATE ARGUMENT COUNTER + + INC BX ;UPDATE INDEX + INC BX ;TWICE + + MOV BYTE PTR ADEX,BL ;SAVE INDEX + CMP BL,8 ;HAVE WE DONE 4 ARGUMENTS YET? + JB TOPX ;....NO, GET SOME MORE + + ;ALL X-OP ARGUMENTS READY +OPX4: MOV AL,OPCODE ;GET THE OPCODE BACK + SUB AH,AH + + CMP AL,0E0H ;IS IT AN EXTENDED 2-OP? + JAE DOXOP ;....NO, IT'S A REAL X-OP + + JMP OP2EX ; ELSE, TREAT IT LIKE A REAL 2-OP + + ; IS IT A VALID X-0P? +DOXOP: MOV BX,OFFSET OPTX ;^ TO START OF X-OP DISPATCH TABLES + AND AL,1FH ;ISOLATE OP ID BITS + CMP AL,NOPSX ;IS IT A LEGAL X-OP + JB DODIS ;....YES, DISPATCH IT + + ; *** ERROR #2: UNDEFINED X-OP *** + MOV AL,2 + JMP GERROR ;NO SUCH OPERATION + + ; --------------- + ; OPCODE DISPATCH + ; --------------- + + ;ENTRY: MASKED OPCODE INDEX IN [AL], BASE ADDRESS OF THE OPCODE + ;DISPATCH TABLE IN BX. + +DODIS: SHL AX,1 ;MAKE IT A WORD OFFSET + ADD BX,AX ;ADD THE OFFSET TO THE BASE ADDRESS + MOV SI,DS:[BX] ;GET THE ADDRESS FROM THE DISPATCH TABLE + CALL SI ;CALL THE OP ROUTINE + JMP MLOOP ;AND LOOP FOR NEXT INSTRUCTION + + ; -------------- + ; HANDLE A 0-OP + ; -------------- + +OP0: MOV BX,OFFSET OPT0 ;^ TO 0-OP DISPATCH TABLE + AND AL,0FH ;EXTRACT OPERATION BITS + CMP AL,NOPS0 ;OUT OF RANGE? + JB DODIS ;....NO, DISPATCH IT + + ; *** ERROR #3: UNDEFINED 0-OP *** + MOV AL,3 + JMP GERROR + + ; ------------- + ; HANDLE A 1-OP + ; ------------- + +OP1: AND AL,00110000B ;1OP. ISOLATE ARGUMENT BITS + JNZ OP1A + CALL GETLNG ;00 = LONG IMMEDIATE + JMP OP1EX + +OP1A: CMP AL,00010000B ;SHORT IMMEDIATE? + JNZ OP1B ;....NO + CALL GETSHT ;....YES, 01 = SHORT IMMEDIATE + JMP OP1EX + +OP1B: CMP AL,00100000B ;VARIABLE + JNZ BADOP1 ;....NO, UNDEFINED STATE + CALL GETVAR ;10 = VARIABLE + +OP1EX: MOV AX,VALUE ;VALUE TO [ARG1], UPDATE COUNT + MOV WORD PTR ARG1,AX + INC NARGS + + MOV BX,OFFSET OPT1 ;^ TO OP-1 DISPATCH TABLES + MOV AL,OPCODE ;RESTORE OPCODE + AND AX,00001111B ;ISOLATE OP ID BITS + CMP AL,NOPS1 ;IF WITHIN RANGE, + JB DODIS ;THE EXECUTE THE 1-OP + + ; *** ERROR #4: UNDEFINED 1-OP *** +BADOP1: MOV AL,4 + JMP GERROR + + ; ------------- + ; HANDLE A 2-OP + ; ------------- + +OP2: AND AX,01000000B ;2OP, ISOLATE 1st ARG BIT + JNZ OP2A ;SHORT IMMEDIATE? + CALL GETSHT ;....YES. 0 = SHORT IMMEDIATE + JMP OP2B + +OP2A: CALL GETVAR ;1 = VARIABLE +OP2B: MOV AX,WORD PTR VALUE ;VALUE TO [ARG1], UPDATE COUNT + MOV WORD PTR ARG1,AX + INC NARGS + + MOV AL,OPCODE ;RESTORE THE OPCODE BYTE + AND AX,00100000B ;ISOLATE 2nd ARG BIT + JNZ OP2C ;SHORT IMMEDIATE? + CALL GETSHT ;....YES, 0 = SHORT IMMEDIATE + JMP OP2D + +OP2C: CALL GETVAR ;1 = VARIABLE + +OP2D: MOV AX,WORD PTR VALUE ;MOVE VALUE TO [ARG2] + MOV WORD PTR ARG2,AX + INC NARGS ;UPDATE COUNT + + ;ENTRY FOR EXTENDED 2-OPS +OP2EX: MOV BX,OFFSET OPT2 ;^ DISPATCH TABLE + MOV AL,OPCODE ;RESTORE OPCODE BYTE + AND AX,1FH ;ISOLATE OP ID BITS + CMP AL,NOPS2 ;LEGAL 2-OP? + JAE OP2F ;ERROR IF OUT OF RANGE + JMP DODIS ;ELSE DISPATCH + + ; *** ERROR #5: UNDEFINED 2-OP *** +OP2F: MOV AL,5 + JMP GERROR +MLOOP ENDP + + SUBTTL HIGH LEVEL IBMPC DEPENDENT ROUTINES + PAGE + ; --------------------- + ; SYSTEM INITIALIZATION + ; --------------------- + PUBLIC SYSINI,SYS1,DSKERR +SYSINI PROC + MOV AH,DOSVER ; (7) GET DOS VERSION # + INT 21H ; (7) MUST BE 2.0 OR HIGHER + CMP AL,2 ; (7) DOS 2.0+ + JGE GOODOS + MOV AL,17 + JMP GERROR + ; DETERMINE PRESENCE OF JOYSTICK +GOODOS: CALL STICK1 ; READ THE JOYSTICK PORT (OR ETHER) + AND AL,0EFH ; MASK OFF BUTTON BITS + CMP AL,8AH ; 8AH IS BOTTOM RIGHT (NO JOYSTICK) + JZ NOSTK + MOV JOYSTK,1 ; THERE IS A STICK SO USE IT! + + ; OPEN THE GAME FILE +NOSTK: PUSH ES + PUSH BX + MOV AX,BIOSDATA ; SEG ADDRESS BIOS DATA AREA + MOV ES,AX + MOV BX,KB_FLAG ; OFFSET TO BIOS DATA FOR KEYS + MOV AL,ES:[BX] ; GET BYTE OF KEYBOARD STATE + MOV KYFLGS,AL ; SAVE THEM + OR BYTE PTR ES:[BX],NUMLOCK ; TURN ON NUMLOCK + POP BX + POP ES + MOV AH,CURDSK ; (6) GET DEFAULT DRIVE + INT 21H ; (6) FROM DOS + MOV DEFDRV,AL ; (6) SAVE DEFAULT DRIVE + MOV CURDRV,AL ; (6) SAVE DEFAULT DRIVE + MOV AH,CFOPENZ ;ASCIZ STRINGS + MOV AL,0 ;OPEN FOR READ + MOV DX,OFFSET GAMFILE + INT 21H + JNC SYSIN1 + JMP DSKERR + + ; DETERMINE SPACE AVAILABLE +SYSIN1: MOV GAMHNDL,AX ;SAVE THE FILE HANDLE + + ; DETERMINE THE SIZE OF DIP.DAT + ; MOVE READ/WRITE POINTER TO THE END OF THE FILE + SUB CX,CX ;SET CX:DX OFFSET = 0 + SUB DX,DX + MOV BX,GAMHNDL ;GET FILE HANDLE + MOV AH,CFSEEK ;SELECT LSEEK FUNCTION + MOV AL,2 ;USE OFFSET FROM END METHOD + INT 21H ;INVOKE FUNCTION CALL + + ; DX:AX = FILE SIZE IN BYTES + ; DETERMINE THE NUMBER OF 512 BYTE PARA'S + TEST AX,1FFH ;IS THERE A PARTIAL DISK PARAGRAPH? + JZ SYSIN2 ;....NO + ADD AX,200H ;ADD 1 TO THE NUMBER OF PARA'S + +SYSIN2: SHR AX,1 ;DETERMINE NO. OF 512 BYTE PARA'S + SUB AL,AL + XCHG AH,AL + CMP DX,0 + JZ SYSIN3 + ADD AL,80H + +SYSIN3: MOV FSIZE,AL ;SAVE IT + + ; DETERMINE THE AMOUNT OF MEMORY AVAILABLE FOR PAGING BUFFERS + MOV BX,2 ;GET TOP OF MEMORY + MOV BX,CS:[BX] ;FROM OUT OF THE PSP + MOV AX,CS ;GET CODE SEG + SUB BX,AX ;SUB CSEG FROM TOPMEM + MOV CL,4 ;SHIFT COUNT + MOV AX,OFFSET MEMBUF ;USE OFFSET TO FIGURE PARAG'S + SHR AX,CL ;REDUCE THIS OFFSET TO PARA'S + INC AX ;SKIP ONE PARAGRAPH + SUB BX,AX ;YIELDS PARA'S AVAILABLE + MOV CL,5 ;DIVIDE BY 32 + SHR BX,CL ; TO GET THE NUMBER OF 512 BYTE BUFFERS + + ; REDUCE THE NUMBER OF BUFFERS AVAILABLE TO ACCOMODATE MEMBUFF + DEC BX ;SUBTRACT 1 BUFFER FOR MEMBUF + CMP BX,128 ;ABOVE 80H, WE NEED ANOTHER + JL SYS1 ;WE HAVE 128 OR FEWER BUFFERS AVAILABLE + DEC BX ;TAKE AWAY ANOTHER PAGE + CMP BX,255 ;THIS IS THE MOST WE WILL NEED + JLE SYS1 ;DON'T MODIFY IF BX LE. 255 + MOV BX,255 ;DONT ALLOW MORE THAN 255 + +SYS1: MOV BUFFERS,BL ;SAVE THE NUMBER OF BUFFERS + + ; DYNAMICALLY CALCULATE THE START OF SEG0 + SHL BX,1 ;GET NUMBER OF BYTES IN MEMBUF + SHL BX,1 ;IT'S 4 BYTES x BX BYTES LONG + ADD BX,OFFSET MEMBUF ;CALCULATE TABLE LOCATION + MOV CX,4 ;REDUCE NUMBER OF BYTES IN TABLE=PARA'S + SHR BX,CL ;TO DYNAMICALLY ALLOCATE SPACE + MOV AX,DS ;GET A COPY OF THE CURRENT SEG + ADD BX,AX ;AND CALCULATE THE NEW SEG + ADD BX,10H ;ADD ONE PARAGRAPH FOR SAFETY + MOV SEG0,BX ;THIS WILL BE USED FOR ES:GAME + ADD BX,1000H ;ADD 64K TO CALC 2ND SEG + MOV SEG1,BX ;THIS IS SEG0+64K + + ; INITILIZE PAGING TABLES + ; INITIALIZE MEMMAP + SUB AX,AX ;PRELOAD FLAGS=RESET (0) + ;MEMBUF INDICES=NOT CORE RESIDENT (0) + SUB BX,BX ;INITIALIZE ARRAY ROW POINTER + MOV CX,00FFH ;SET UP FOR 255 ENTRIES + +INITMM: MOV MEMMAP[BX],AL ;RESET PRELOAD FLAG + MOV MEMMAP[BX+1],AH ;MARK MEMBUF INDICE = NOT CORE RESIDENT + ADD BX,2 ;NEXT OFFSET + LOOP INITMM ;INITIALIZE EACH ENTRY + + ; DETERMINE IF THE GAME "FITS" + MOV AL,BUFFERS + CMP AL,FSIZE + JNB SYSXIT ;IF THE GAME "FITS" FSIZE IS > 0 + MOV FSIZE,0 ;ELSE FSIZE = 0 + + ; INITIALIZE MEMBUF + MOV CL,BUFFERS ;NUMBER OF ENTRIES USED AS A LOOP CTR + SUB CH,CH + SUB BX,BX ;INITIALIZE OFFSET INTO TABLE + MOV DH,255 ;INITIAL VALUE FOR "PREVIOUS" POINTER + MOV DL,1 ;INITIAL VALUE FOR "NEXT" POINTER + MOV AL,0 ;INITIAL "LOC" (ABS SEG:PAGE VALUE) + +INITMB: MOV MEMBUF[BX],AL ;SAVE LOC + MOV MEMBUF[BX+1],0 ;V-PAGE IS THE RESPONSIBILITY OF GTVBLK + MOV MEMBUF[BX+2],DH ;INITIALIZE "PREVIOUS" + MOV MEMBUF[BX+3],DL ; AND "NEXT" POINTERS + INC AL ;NEXT LOC + INC DH ;NEXT "PREVIOUS" + INC DL ;NEXT "NEXT" + ADD BX,4 ;NEXT TABLE ENTRY + LOOP INITMB ;REPAIR EACH MEMBUF ENTRY + + ;CONNECT HEAD AND TAIL + DEC BX ;BACK UP TO "NEXT" COLUMN OF LAST ENTRY + MOV DL,MEMBUF[BX] ;GET "NEXT" + DEC DL ;SUBTRACT 1 TO GET TAIL + MOV MEMBUF[BX],0 ;SPLICE TAIL TO HEAD + MOV MEMBUF+2,DL ;SPLICE HEAD TO TAIL + + ; INITIALIZE LRU BUFFER POINTER + MOV LRU,0 + + ; + ; EXIT POINT + ; + + ; INITIALIZE SEGMENT POINTER TO THE START OF PAGING +SYSXIT: MOV BX,SEG0 ; + MOV ES,BX ;EXTRA SEG ^ THE START OF PAGING + CALL DISPRT + CALL CSETUP ;SET UP THE CONSOLE DEVICE + CALL CHKCPU ;SET THE IBMAT FLAG IF INDICATED + CALL INITSND ;INITIALIZE TIMER FOR SOUND +IF DEBUG + CALL TRACE ; CHECK TO SEE IF TRACER IS WANTED +ENDIF + RET + + ; **** ERROR #11 **** DISK DATA FILE HANDLING ERROR + ; CLOSE THE FILE +DSKERR: MOV BX,GAMHNDL ;BX <= HANDLE + MOV AH,3EH ;REQUEST CLOSE + INT 21H ;MSDOS CALL + + ; AND PERFORM ERROR PROCESSING + MOV AL,0BH ;SET UP ERROR RETURN CODE + JMP GERROR ;AND GO TO ERROR EXIT + +SYSINI ENDP + +IF DEBUG + PUBLIC TRACE +TRACE PROC + MOV SI,80H ; GET COMMAND LINE + LODSB ; SEE COMMAND PARMS + CMP AL,2 ; LOOK FOR /T + JNB TRACE1 +TRACE0: RET +TRACE1: MOV SI,83H ; LOOK AT BYTE + AND BYTE PTR [SI],5FH ; TURN OFF 32 BIT + CMP BYTE PTR [SI],'T' ; TRACE? + JNE TRACE0 + CALL ITRACE ; YEP, INITIALIZE TRACER + RET +TRACE ENDP + + +; trace trap routines for the mme +; itrace toggles tracing & sets the interrupt. itrint traps the +; interrupt and counts the bucket for the current pc +; + public itrace ;trace trap enable +itrace proc near + push ax + push bx + push dx + mov dx,offset itrint + mov bx,ds ;save data segment + mov ax,cs + mov isavecs,ax ;for compare in int routine + mov ds,ax ;ds:dx is trap address + mov al,1 ;trace int # + mov ah,25H ;function # for set int vector + int 21H + mov ds,bx + pop dx + pop bx + pushf ;get the flags + pop ax + xor ax,400O ;complement the trace flag + push ax + popf + pop ax + ret +itrace endp +; +itrint proc near + push bp + mov bp,sp ;stack:saved bp(0), ip(2), cs(4), flags(6) + push bx + push cx + inc itrcnt ;wrong cs, just count it + jne itrint2 + inc itrcnt+2 +itrint2:mov bx,[bp+2] ;pick up ip + cmp bx,ioffset + jb itrint1 ;dont count below + cmp bx,itop + ja itrint1 ;dont count above + sub bx,ioffset + mov cx,ishift + shr bx,cl + xor bh,bh ;0:255 - high pc bits + add bx,bx ;byte address of a long + add bx,bx + inc ipcount[bx] + jne itrint1 ;check wrap + inc ipcount+2[bx] +itrint1:pop cx + pop bx + pop bp + iret +itrint endp + +ptracer proc + mov dx,offset t_out + mov cx,0 + mov ah,cfcreaz ; create the file tracer.out + int 21h + mov dx,offset itrcnt ; get address of vars + mov cx,256*32+4 ; number of bytes to write + mov bx,ax ; get handle from create + mov ah,40h ; write the data + int 21h + mov ah,3eh ; close the data file + int 21h + ret ; all done +ptracer endp + +ENDIF + + PUBLIC DISPRT +DISPRT PROC ; DISABLE PRINT SCREEN + PUSH ES + MOV AX,3505H ; (B5) GET INTERRUPT VECTOR FIVE + INT 21H ; (B5) (PRTSCR) FROM DOS + MOV PRTOFF,BX ; (B5) SAVE OFFSET + MOV PRTSEG,ES ; (B5) SAVE 'EM BOTH + MOV DX,OFFSET RETEOI + MOV AX,2505H ; (B5) SET INTERRUPT TO POINT TO IRET + INT 21H + POP ES + RET +DISPRT ENDP + + PUBLIC ENAPRT +ENAPRT PROC ; (B5) REENABLE PRINT SCREEN + PUSH DS + MOV AX,2505H ; (B5) RESET PRTSCR + MOV DX,PRTOFF ; (B5) GET OFFSET + MOV BX,PRTSEG ; (B5) SET UP DS + MOV DS,BX ; (B5) TO POINT TO OLD ROUTINE + INT 21H + POP DS + RET +ENAPRT ENDP + +RETEOI: IRET ; (B5) RETURN FROM PRINT SCREEN + + + ; ---------------------- + ; CONSOLE INITIALIZATION + ; -MOVED TO DUMP.ASM-- + ; ---------------------- + + ; ------------------------------------- + ; GET A BLOCK OF PRELOAD VIRTUAL MEMORY + ; ------------------------------------- + + ; + ; ENTRY: [VPAGEN] = VIRTUAL BLOCK NUMBER (RANGE 0-255) + ; [LRU] = NUMBER OF LEAST RECENTLY USED BUFFER + ; + + PUBLIC GTPBLK +GTPBLK PROC + CALL GTVBLK ;GET THE BLOCK + + ; USE [VPAGEN] TO SET [PREFLG] + MOV BL,VPAGEN ;GET VIRTUAL PAGE NUMBER + SUB BH,BH + SHL BX,1 ;CONVERT TO WORD POINTER + MOV MEMMAP[BX],1 ;SET PREFLG + + CMP FSIZE,0 + JZ GTPBL1 + RET + + ; USE [BUF] TO UNSPLICE THE ALLOCATED BUFFER FROM THE CIRCULAR + ; LINKED LIST. NOTE, IN THE CASE OF PRELOAD, BUF CONTAINS + ; THE NUMBER OF THE JUST USED BUFFER, WHICH WAS THE LRU AND IS NOW + ; THE MRU. +GTPBL1: MOV DL,BUF ;SAVE BUF FOR FIXING THE LRU + MOV BL,DL ;USE BUF TO CHANGE "NEXT" POINTER + SUB BH,BH ; IN PREVIOUS BUFFER + SHL BX,1 ;4 BYTES PER TABLE ENTRY + SHL BX,1 + + ;GET "NEXT" [AH] AND "PREVIOUS" [AL] + MOV AX,WORD PTR MEMBUF[BX+2] + + MOV BL,AL ;USE "PREVIOUS" TO + SUB BH,BH ; POINT TO THE 2ND MRU'S TABLE + SHL BX,1 ;4 BYTES PER TABLE ENTRY + SHL BX,1 + MOV MEMBUF[BX+3],AH ;SET TO POINT FORWARD TO THE LRU + + MOV BL,AH ;USE "NEXT" TO + SUB BH,BH ; POINT TO THE LRU'S TABLE + SHL BX,1 ;4 BYTES PER TABLE ENTRY + SHL BX,1 + MOV MEMBUF[BX+2],AL ;SET TO POINT BACK TO 2ND MRU + ; MAKING IT THE NEW MRU + RET +GTPBLK ENDP + + ; ----------------------------- + ; GET A BLOCK OF VIRTUAL MEMORY + ; ----------------------------- + ; + ; ENTRY: [VPAGEN] = VIRTUAL BLOCK NUMBER (RANGE 0-255) + ; [LRU] = NUMBER OF LEAST RECENTLY USED BUFFER + ; + ; THROUGH USE OF A COMMON EXIT POINT + ; EXIT: BUF (RANGE 0 THROUGH [BUFFERS]-1) + ; LOC + ; + + PUBLIC GTVBLK +GTVBLK PROC + PUSH BX + + ; USE [VPAGEN] TO ACCESS [PREFLG] AND [BUF] + MOV BL,VPAGEN ;GET VIRTUAL PAGE NUMBER + SUB BH,BH + SHL BX,1 ;CONVERT TO WORD POINTER + MOV AL,MEMMAP[BX+1] ;GET BUF + MOV BUF,AL ;SAVE IT + TEST MEMMAP[BX],1 ;TEST PREFLG + ; IS THIS SECTION LOADED PRELOAD? + JZ NOTPRE ;....NO + + ; LOADED PRELOAD + ; BUF IS VALID +ISIN: MOV BL,BUF ;WE CAREFULLY SAW TO IT'S VALIDITY + MOV LOC,BL ;AND PUT IT WHERE THE SUN.... + POP BX + RET + + ; {CASE} NOT LOADED PRELOAD +NOTPRE: CMP FSIZE,0 ;ARE WE PAGING? + JZ NOTPR1 ;....YES + + ; NOT PAGING + CMP BUF,0 ;IS IT ALREADY IN CORE? + + ; {CASE} IT IS ALREADY IN CORE + JNE ISIN ;....YES + + ; {CASE} IT NOT IN CORE + MOV AL,VPAGEN + MOV MEMMAP[BX+1],AL ;SET UP THE BUF ENTRY IN MEMMAP + MOV BUF,AL ; AND SET BUF = VPAGEN + + PUSH CX ;SAVE SOME MORE REGISTERS + PUSH DX + JMP GTVBL2 ;AND BRING IT IN + +NOTPR1: CMP BUF,0 ;IS IT ALREADY IN CORE? + JNE INCORE ;....YES + JMP NOTIN ;....NO. THEN BRING IT IN + + ; {CASE} IT IS IN CORE AND NOT PRELOAD +INCORE: MOV BL,BUF ;IS IT THE LRU? + CMP LRU,BL + JNE SPLICE ;....NO + + ; IT IS THE LRU PAGE, SO MAKE IT THE MRU + SUB BH,BH ;UPDATE THE LEAST RECENTLY USED BUFFER + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV AL,MEMBUF[BX+3] ;GET "NEXT" POINTER + MOV LRU,AL ;IT'S THE NEW LRU, MAKING THIS BUFFER + ; THE MRU + + ; BUF IS VALID + MOV BL,BUF + MOV OLDMRU,BL ;SAVE BUF AS OLD MRU + MOV LOC,BL ;AND LOC + POP BX + RET + + + ; IT ISN'T THE LRU. WE HAVE TO MAKE IT THE MRU, IF IT ISN'T + ; ALREADY. THE EXISTING LRU REMAINS UNCHANGED + +SPLICE: MOV BL,BUF + CMP BL,OLDMRU ;IS THIS ALREADY THE MRU? + JNE SPLIC1 ;....NO + + MOV LOC,BL ;AND SAVE BUF IN LOC + POP BX + RET + + ; STEP 1 - UNSPLICE THE "TOUCHED" BUFFER +SPLIC1: PUSH CX + PUSH DX + MOV OLDMRU,BL ;SAVE BUF AS OLD MRU + SUB BH,BH ; + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV AX,WORD PTR MEMBUF[BX+2] ;GET "NEXT" AND "PREVIOUS" + PUSH BX + + MOV BL,AL ;START WITH "PREVIOUS" BUFFER + SUB BH,BH ; + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV MEMBUF[BX+3],AH ;POINT FORWARD TO "NEXT" + + MOV BL,AH ;THEN "NEXT" BUFFER + SUB BH,BH ; + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV MEMBUF[BX+2],AL ;POINT BACK TO "PREVIOUS" + + ;SPLICE IN THE NEW MRU + MOV DL,BUF + + MOV BL,LRU ;GET THE "PREVIOUS" POINTER IN LRU + SUB BH,BH ; WHICH POINTS AT THE OLD MRU + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV AL,MEMBUF[BX+2] ;GET "PREVIOUS" POINTER + MOV MEMBUF[BX+2],DL ;MAKE LRU POINT BACK TO BUF + + MOV BL,AL ;GET THE "NEXT" POINTER FROM FORMER + SUB BH,BH ; MRU + SHL BX,1 ;4 BYTES PER ENTRY + SHL BX,1 + MOV AH,MEMBUF[BX+3] ;GET "NEXT" POINTER + MOV MEMBUF[BX+3],DL ;MAKE IT POINT FORWARD TO BUF + + ; AND REPAIR BUF + POP BX + MOV WORD PTR MEMBUF[BX+2],AX + + ; BUF IS VALID + JMP GTVRET ;WE'RE DONE, USE COMMON EXIT + + ; {CASE} IT ISN'T IN CORE + ; DEALLOCATE THE LEAST RECENTLY USED BUFFER +NOTIN: PUSH CX + PUSH DX + MOV BL,LRU ;GET LRU SO AS TO DEALLOCATE + SUB BH,BH ; THE LEAST RECENTLY USED BUFFER + SHL BX,1 + SHL BX,1 + + MOV BL,MEMBUF[BX+1] ;GET THE OLD VIRTUAL PAGE NUMBER + ; WE'LL USE IT TO INDEX INTO MEMMAP + + SUB BH,BH ; AND SET IT'S BUF ENTRY + SHL BX,1 ; TO "0" + MOV MEMMAP[BX+1],0 ;THIS DEALLOCATES THE BUFFER FOR THE + ; OLD VIRTUAL PAGE. + + ; ALLOCATE MEMBUF [LRU] TO THE NEW VIRTUAL PAGE + MOV BL,LRU ;GET LRU SO AS TO ALLOCATE + SUB BH,BH ; THE LEAST RECENTLY USED BUFFER + SHL BX,1 + SHL BX,1 + MOV AL,VPAGEN ;GET NEW VIRTUAL PAGE NUMBER + MOV MEMBUF[BX+1],AL ;STORE IT + + ; SETUP THE LOAD POINT FOR THE NEW VIRTUAL PAGE +PUSH BX ; SAVE BUFFER DESCRIPTOR + MOV BL,AL ;USE VPAGEN AS AN INDEX + SUB BH,BH ; INTO MEMBUF + SHL BX,1 + MOV AL,LRU ;LRU IS THE BUFFER TO USE + MOV MEMMAP[BX+1],AL ; SO SAVE IT + MOV BUF,AL ; AND SAVE IT FOR COMMON EXIT + MOV OLDMRU,AL ;SAVE BUF AS OLD MRU +POP BX ; RESTORE BUFFER DESCRIPTOR + ; AND MAKE THIS BUFFER THE MRU +; SHL BX,1 ;SO WE CAN USE IT AS A QUAD POINTER + MOV AL,MEMBUF[BX+3] ;GET "NEXT" POINTER + MOV LRU,AL ;IT'S THE NEW LRU + ; MAKING THIS BUFFER THE MRU + + ; INITIALIZE REGISTERS TO PAGE IN A BLOCK OF VIRTUAL MEMORY + ; GET DESTINATION IN ES:BX FORM + ; FIXUP ES +GTVBL2: MOV BL,BUF ;GET DESTINATION BLOCK NUMBER + MOV CX,SEG0 ;PRE-POINT AT SEG0 + OR BL,BL ;TEST SEGMENT BIT + JNS SEGAOK ;IF NO SIGN THEN IT'S SEG0 + AND BL,7FH ; ELSE STRIP OFF THE SEGMENT BIT + MOV CX,SEG1 ; AND POINT TO THE OTHER SEGMENT +SEGAOK: MOV ES,CX ;ES POINTS TO THE CORRECT SEGMENT + + ; CONVERT THE DESTINATION BLOCK NUMBER TO A BYTE OFFSET + MOV CL,9 ;x 512 + SHL BX,CL ; + + ; GET VIRTUAL BLOCK NUMBER IN AL + MOV AL,VPAGEN ;GET THE VIRTUAL PAGE NUMBER + + ; + ; GET VIRTUAL BLOCK [AL] IN ES:BX + ; + + PUSH BX ;SAVE BX PORTION OF DESTINATION + + ; MOVE FILE READ/WRITE POINTER (LSEEK) TO POINT TO THE PROPER BLOCK + ; CALCULATE OFFSET IN BYTES AND PLACE IN CX:DX + MOV CX,9 ;MULTIPLY BY 512 (RECSIZ) + SHL AX,CL ;TO CONVERT BLK# TO OFFSET + MOV CX,0 ;SET TO ZERO, BUT CHANGE + ADC CX,0 ;TO "1" IF OFFSET > 64K + MOV DX,AX ;GET LOW ORDER #BYTES FOR LSEEK + + ; MOVE READ/WRITE POINTER TO OFFSET IN CX:DX + ; FROM THE BEGINNING OF THE FILE + MOV BX,GAMHNDL ;GET FILE HANDLE + MOV AH,CFSEEK ;SELECT LSEEK FUNCTION + MOV AL,0 ;USE OFFSET FROM BEGINNING METHOD + INT 21H ;INVOKE FUNCTION CALL + + ; READ THE SELECTED 512 BYTE RECORD INTO CORE LOCATION ES:BX + ; TRANLATE THE ES:BX CORE LOCATION INTO DS:DX FORMAT + ; RESTORE BX PORTION OF DESTINATION INTO DX + POP DX + + ; FIXUP SEGMENT PORTION OF THE DESTINATION + PUSH DS ;SAVE DS FOR LATER RESTORATION + PUSH ES ;PUSH EXTRA SEGMENT + POP DS ;IN ORDER TO PUT IT IN DS + + ; READ THE RECORD INTO DS:DX + MOV CX,RECSIZ ;READ A 512 BYTE RECORD + MOV AH,CRDRNDZ ;SELECT READ RANDOM RECORD + INT 21H ;INVOKE FUNCTION CALL + CMP AX,CX ;SET FLAGS + + ; RESTORE DATA SEGMENT + POP DS + + ; COMMON EXIT POINT + ; EXIT: BUF (RANGE 0 THROUGH [BUFFERS]-1) + ; LOC + ; +GTVRET: MOV BL,BUF ;WE CAREFULLY SAW TO IT'S VALIDITY + MOV LOC,BL ;AND PUT IT WHERE THE SUN.... + + POP DX ;RESTORE AFFECTED REGISTER(S) + POP CX + POP BX + RET +GTVBLK ENDP + + ; -------------- + ; ERROR HANDLING + ; -------------- + + ; ENTRY: ERROR CODE IN [AL] + PUBLIC GERROR,GERR1 +GERROR PROC + push ax ;save err # before sys call destroys +; mov ah,0 +; mov al,2 ;mode +; int 10H + mov ah,2 + mov dx,100H + mov bh,0 ;active page 0 + int 10H ;set cursor pos + pop ax + XOR AH,AH + SHL AX,1 ; INDEX + MOV BX,AX ; USE INDEX REG + MOV BX,ERRTAB[BX] ; GET PROPER ERROR MESSAGE + MOV AL,[BX] ; GET LENGTH + ADD AL,ERRM ; ADD LENGTH OF STARTING STRING + mov ch,al ;save total length of text + MOV AH,40 ; GET WIDTH OF SCREEN + SUB AH,AL ; GET REMAINING SPACES + SHR AH,1 ; DIVIDE IN HALF + TEST AH,1 ; ODD? + JZ GERR0 ; NOPE + DEC AH ; YES, SUBTRACT 1 +GERR0: MOV CL,AH ; GET COUNT OF SPACES + add ch,AH ; add to text len, gives right edge +GERR1: CMP CL,0 ; DON'T PRINT "NO" SPACES + JE GERR2 ; SKIP PRINT + MOV AH,2 ; PRINT A CHAR + MOV DL,' ' ; A SPACE IN FACT + INT 21H ; DO IT + DEC CL + JMP GERR1 +GERR2: MOV AX,OFFSET ERRM+1 + CALL NPRNT ;PRINT IT (NO CRLF) + MOV AX,BX ; GET ERROR STRING + INC AX ; SKIP LENGTH BYTE + CALL NPRNT ; PRINT THE ERROR STRING +GERR3: CMP CH,40 ; FINISH THE LINE WITH SPACES + JGE GERR4 + MOV DL,' ' ; PRINT A SPACE + MOV AH,2 + INT 21H + INC CH + JMP GERR3 +GERR4: MOV AH,2 + MOV DL,13 + INT 21H + MOV DL,10 + INT 21H + JMP FINISH ;EXIT CLEANLY +GERROR ENDP + + + ;PRINT A CARIAGE RETURN / LINE FEED + PUBLIC MCRLF +MCRLF PROC + MOV AL,13 + CALL PRTOUT + MOV AL,10 + CALL PRTOUT + RET +MCRLF ENDP + + ;PRINT THE CHARACTER IN [AL] + PUBLIC PRTOUT +PRTOUT PROC + PUSH AX + PUSH BX + PUSH CX + MOV DL,AL + MOV AH,2 + INT 21H + POP CX + POP BX + POP AX + RET +PRTOUT ENDP + + ;PRINT A STRING FOLLOWED BY , PTR IN AX + PUBLIC MPRNT +MPRNT PROC + PUSH DX + MOV DX,AX + MOV AH,9 + INT 21H + CALL MCRLF + POP DX + RET +MPRNT ENDP + + ;PRINT A STRING NOT FOLLOWED BY , PTR IN AX + PUBLIC NPRNT,NPR1,NPR2 +NPRNT PROC + PUSH BX ;SAVE BX + MOV BX,AX ;STRING PTR +NPR1: MOV AL,[BX] ;GET NEXT CHARACTER + CMP AL,"$" ;END OF THE LINE + JE NPR2 ;....YES + CALL PRTOUT ;....NO. PRINT THE CHARACTER + INC BX ;POINT TO THE NEXT CHARACTER + JMP NPR1 ;REPEAT UNTIL END OF THE LINE +NPR2: POP BX ;RESTORE BX + RET +NPRNT ENDP + + + ;GET TIME TO BE USED IN NUDGING THE RANDOM NUMBER GENERATOR + PUBLIC MTIME +MTIME PROC + PUSH CX + PUSH DX + MOV AH,2CH + INT 21H + MOV RSEED1,CX ;HRS & MIN + MOV RSEED2,DX ;S's & 1/100 THS + POP DX + POP CX + RET +MTIME ENDP + + ;EXIT THE GAME PEACEFULLY AND RETURN TO DOS + PUBLIC FINISH +FINISH PROC + + ; INDICATE THE GAME IS OVER + MOV AH,2 ; SET CURSOR POSITION + MOV BH,0 ; FIRST PAGE + MOV DX,1800H ; ON LINE 25 + INT 10H ; POSITION IT + MOV AX,OFFSET XITMSG ;POINT AT "END OF SESSION" + CALL NPRNT ;PRINT IT + CALL ENAPRT + ; WAIT FOR ANY KEYPRESS + + MOV AH,CNOECHO ; (B5) READ A CHAR + INT 21H + + ; GO BACK TO REGULAR TEXT MODE WITH A CLEAR SCREEN + ; SELECT STANDARD MODE + MOV AH,0 ;REQUEST MODE SET + MOV AL,2 ;STANDARD MONOCHROME 80 X 25 + INT 10H ;CALL BIOS FUNCTION + +IF DEBUG + CALL PTRACER ; CALL 'C' OUTPUT OF TABLE +ENDIF + MOV AX,BIOSDATA ; FIX KEYBOARD + MOV ES,AX + MOV BX,KB_FLAG ; KEYBOARD FLAGS OFFSET + MOV AL,KYFLGS ; GET ORIGINAL STATE + MOV ES:[BX],AL ; STORE IT + + ; EXIT TO DOS + MOV AH,04CH + INT 21H +FINISH ENDP + + ; -------------------------------- + ; CHECK FOR FAST PROCESSOR (80286) + ; -------------------------------- + ; + ; PURPOSE: THE SOUND ROUTINES ARE IMPLIMENTED THROUGH THE USE OF + ; SOFTWARE TIMING LOOPS. THEY ARE THEREFORE SUCCEPTABLE TO + ; BEING CHANGED BY FASTER PROCESSORS. + ; + ; IN ORDER TO PROVIDE COMPENSATION FOR THIS EFFECT, THIS + ; ROUTINE IS USED TO DETERMINE IF THE CPU IS "FAST" OR "SLOW". + ; + ; *** NOTE *** THIS ROUTINE IS TO BE CALLED DURING COLD START + ; + ; INPUTS: NONE + ; + ; OUTPUTS: [IBMAT] = TRUE IF THIS IS A FASTER CPU + ; = FALSE IF THIS IS A NORMAL CPU + ; REGISTERS DESTROYED: + ; AX,BX,DX + ; + ; EXTERNAL REFERENCES: [IBMAT], [TIMER], TRUE, FALSE, ATTIME + ; + + PUBLIC CHKCPU,CHKCP1,CHKCP2 +CHKCPU PROC + ; INITIALIZE + MOV IBMAT,FALSE ;PREMARK THIS AS A "SLOW" CPU + SUB BX,BX ;INITIALIZE LOOP COUNTER + ; TO DETERMINE SPEED + + CALL SYNCH ;SYNCHRONIZE TIMER + MOV TIMER,DL ;SAVE 1/100 SEC COUNT + + ; PREPARE TO QUALIFY +CHKCP1: MOV AH,2CH ;GET THE TIME UNTIL IT CHANGES + INT 21H ; SO WE CAN USE THE COUNT IN BX + INC BX ; TO DECIDE IF THIS IS A FAST CPU + CMP DL,TIMER ;HAS THE CLOCK TICKED? + JZ CHKCP1 ;....NO. LOOP UNTIL IT DOES + + ; PHOTO FINISH + CMP BX,ATTIME ;COMPARE WITH TIME STANDARD + JL CHKCP2 ; IF BX IS LESS, THEN THE CPU IS SLOW + MOV IBMAT,TRUE ; ELSE IT'S FAST AND WE SO MARK IT + +CHKCP2: PUSH ES + PUSH DI + MOV AX,BIOS ; BIOS SEGMENT + MOV ES,AX ; MAKE IT ADDRESSIBLE + MOV DI,BIOSOFF ; GET BIOS OFFSET + MOV AX,OFFSET IBMSTR ; SOURCE STRING "IBM COPR." + MOV DX,9 ; LENGTH OF STRING + MOV CX,200H ; WITHIN THE FIRST 1/2 K + CALL CHK ; CHK BIOS FOR IBM COPR. + JNC CHK_ID +CHKCP3: POP DI + POP ES + RET +CHK_ID: MOV DI,ID_OFF ; GET IBM ID BYTE OFFSET + CMP BYTE PTR ES:[DI],JR_ID ; IS IT A JUNIOR + JNE CHKCP3 + MOV PCJR,1 ; SET FLAG FOR PCJR + JMP CHKCP3 +CHKCPU ENDP + + + ; GIVEN SOURCE PTR IN DS:AX, AND A DEST PTR IN ES:DI, CHK SEARCHES + ; FOR THE STRING POINTED TO BY DS:AX IN THE FIRST (CX) BYTES OF + ; THE STRING POINTED TO BY ES:DI + PUBLIC CHK +CHK PROC + CLD ; (7) CLEAR THE DIRECTION FLAG + PUSH SI ; (7) SAVE THIS + PUSH DX ; (7) SAVE THIS FOR RETRIES + MOV BP,SP ; (7) GET A FRAME POINTER + MOV SI,AX ; (7) SET UP FIRST OFFSET +LUP: CMP BYTE PTR [SI],'$' ; (7) END CHAR + JE MATCH ; (7) REACHING END==MATCH + CMPSB ; (7) COMPARE TWO BYTES + JNE RESET ; (7) RESET SOURCE IF MISMATCH + DEC DX + LOOP LUP ; (7) DECREMENT COUNTER AND TRY AGAIN + JMP RTFAIL ; (7) OUT OF CHARS, FAILED +RESET: MOV SI,AX ; (7) MOVE SOURCE PTR BACK INTO SI + MOV DX,[BP] ; (7) RESTORE NUMBER OF BYTES IN STR + LOOP LUP ; (7) TRY AGAIN +RTFAIL: STC ; (7) FAIL BY RETURNING CARRY SET + POP DX + POP SI ; (7) RESTORE SI + RET +MATCH: TEST DX,DX ; (7) MATCH OF ENTIRE STRING + JNZ RTFAIL + CLC ; (7) GOT A MATCH, RETURN CARRY CLEAR + POP DX + POP SI ; (7) RESTORE SI + RET +CHK ENDP + + + + ; ------------------------ + ; INITIALIZE SPEAKER TIMER + ; ------------------------ + ; + ; PURPOSE: THIS ROUTINE INITIALIZES THE PORTION OF THE 8253 TIMER + ; CHIP USED BY THE SPEAKER SYSTEM. IN PARTICULAR, IT SETS + ; UP CHANNEL 2 OF THE TIMER AS A SQUARE-WAVE GENERATOR. + ; + ; *** NOTE *** THIS ROUTINE IS TO BE CALLED DURING COLD START + ; + ; INPUTS: NONE + ; + ; OUTPUTS: TIMER 2 + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC INITSND +INITSND PROC + PUSH AX ;SAVE REGISTERS + MOV AL,0B6H ;TIMER CONTROL WORD + OUT 43H,AL ;SEND IT TO THE CONTROL PORT + POP AX ;RESTORE REGISTERS + RET +INITSND ENDP + + ; ---------------------- + ; SET THE TONE FREQUENCY + ; ---------------------- + ; + ; PURPOSE: THIS ROUTINE SELECTS THE FREQUENCY OF THE SQUARE-WAVE + ; TONE TO THE SPEAKER. + ; + ; INPUTS: CX=FREQUENCY + ; + ; OUTPUTS: TIMER 2 + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC TONESET +TONESET PROC + PUSH AX ;SAVE REGISTERS + PUSH CX + MOV AL,CL ;GET LOWER BYTE + OUT 42H,AL ;SEND OUT VALUE TO TIMER + MOV AL,CH ;GET UPPER BYTE + OUT 42H,AL ;SEND OUT VALUE TO TIMER + POP CX ;RESTORE REGISTERS + POP AX + RET +TONESET ENDP + + ; ------------ + ; TURN ON TONE + ; ------------ + ; + ; PURPOSE: THIS ROUTINE TURNS ON THE TIMER AND SPEAKER TO PRODUCE + ; A TONE. THE FREQUENCY OF THE TONE MUST HAVE ALREADY + ; BEEN SENT TO THE TIMER. + ; + ; INPUTS: NONE + ; + ; OUTPUTS: TIMER 2, AND SPEAKER + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC TONEON +TONEON PROC + PUSH AX ;SAVE REGISTERS + IN AL,61H ;GET SYSTEM PORT B CONTROL DATA + OR AL,3 ;TURN SPEAKER AND TIMER ON + OUT 61H,AL ;SEND OUT NEW VALUE + POP AX ;RESTORE REGISTERS + RET +TONEON ENDP + + ; ------------ + ; TURN OFF TONE + ; ------------ + ; + ; PURPOSE: THIS ROUTINE TURNS OFF THE TIMER AND SPEAKER + ; + ; INPUTS: NONE + ; + ; OUTPUTS: TIMER 2, AND SPEAKER + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC TONEOFF +TONEOFF PROC + PUSH AX ;SAVE REGISTERS + IN AL,61H ;GET SYSTEM PORT B CONTROL DATA + AND AL,0FCH ;TURN SPEAKER AND TIMER OFF + OUT 61H,AL ;SEND OUT NEW VALUE + POP AX ;RESTORE REGISTERS + RET +TONEOFF ENDP + + ; ----------- + ; SOUND DELAY + ; ----------- + ; + ; PURPOSE: THIS ROUTINE DELAYS FOR A SPECIFIED NUMBER OF .05 SEC + ; INTERVALS. + ; + ; INPUTS: [CX] = NUMBER OF .05 SEC TO DELAY + ; + ; OUTPUTS: NONE + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC SNDDLY,SNDLY1,SNDLY2 +SNDDLY PROC + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH CX + PUSH DX + + CMP CX,0 + JNE SNDLY1 + + ; SHORTER THAN OTHERWISE POSSIBLE DURATION + MOV CX,JIFCNT ;<.05 SEC DELAY REQUEST, SO WAIT A JIFFY +SNDLY0: LOOP SNDLY0 + JMP SNDLY3 + + CALL SYNCH ;SYNCHRONIZE TIMER + MOV TIMER,DL ;SAVE 1/100 SEC COUNT + + ; TIMING LOOP +SNDLY1: PUSH CX ;SAVE LOOP COUNTER +SNDLY2: MOV AH,2CH ;GET THE TIME UNTIL IT CHANGES + INT 21H ; MSDOS FUNCTION CALL + CMP DL,TIMER ;HAS THE CLOCK TICKED? + JZ SNDLY2 ;....NO. LOOP UNTIL IT DOES + POP CX ;RESTORE LOOP COUNTER + MOV TIMER,DL ;SAVE NEW COUNT + LOOP SNDLY1 ; AND LOOP + +SNDLY3: POP DX ;RESTORE REGISTERS + POP CX + POP BX + POP AX + RET +SNDDLY ENDP + + ; ----- + ; SYNCH + ; ----- + ; + ; PURPOSE: THIS ROUTINE WAITS FOR A CHANGE IN THE 1/100 SEC TIMER, TO + ; INSURE THAT WE'RE AT THE START OF A NEW TIME PERIOD. + ; + ; INPUTS: NONE + ; + ; OUTPUTS: [DL] = 1/100 SEC COUNT AT SYNCH TIME + ; + ; REGISTERS DESTROYED: DL + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC SYNCH,SYNCH1 +SYNCH PROC + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH CX + MOV AH,2CH ;GET THE TIME FROM THE REAL TIME CLOCK + INT 21H ;MSDOS FUNCTION CALL + MOV TIMER,DL ;SAVE 1/100 SEC COUNT + + ; SYNCHRONIZE +SYNCH1: MOV AH,2CH ;GET THE TIME AGAIN, SO WE CAN INSURE + INT 21H ; THAT WE ARE SYNCHRONIZED WITH THE + CMP DL,TIMER ; START OF A NEW TIMING PERIOD + JZ SYNCH1 ;LOOP UNTIL SYNCHRONIZED + POP CX ;RESTORE REGISTERS + POP BX + POP AX + RET +SYNCH ENDP + + ; ---- + ; FREQ + ; ---- + ; + ; PURPOSE: THIS ROUTINE CONVERTS A FREQUENCY TO THE NUMBER REQUIRED + ; BY TONESET. + ; + ; INPUTS: [CX] = FREQUENCY IN HZ + ; + ; OUTPUTS: [CX] = CONVERTED VALUE + ; + ; REGISTERS DESTROYED: CX + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC FREQ +FREQ PROC + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH DX + + MOV DX,12H ;UPPER PART OF NUMERATOR + MOV AX,34DEH ;LOWER PART OF NUMERATOR + DIV CX ;DIVIDE BY FREQUENCY + MOV CX,AX ;QUOTIENT IS THE OUTPUT + POP DX ;RESTORE REGISTERS + POP BX + POP AX + RET +FREQ ENDP + + ; ----------- + ; MAKE A TONE + ; ----------- + ; + ; PURPOSE: THIS ROUTINE MAKES A TONE OF A GIVEN FREQUENCY AND LENGTH + ; + ; INPUTS: [CX] = FREQUENCY IN HZ + ; [DX] = DURATION IN .05 SEC INTERVALS + ; + ; OUTPUTS: TO THE SPEAKER AND TIMER 2 + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: {TONESET}, {TONEON}, {TONEOFF}, {DELAY} + ; + + PUBLIC TONE +TONE PROC + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH CX + PUSH DX + + ; COMPUTE THE FREQUENCY AND SETUP THE TONE GENERATOR (TIMER 2) + CALL FREQ ;CONVERT THE FREQUENCY + CALL TONESET ;SET UP TIMER 2 + + ; TURN ON THE TONE + CALL TONEON + + ; WAIT FOR THE DELAY TIME + MOV CX,DX + CALL SNDDLY + + ; TURN OFF THE TONE + CALL TONEOFF + + POP DX ;RESTORE THE REGISTERS + POP CX + POP BX + POP AX + RET +TONE ENDP + +EVEN + ; + ; START OF A DYNAMICALLY ALLOCATED PAGE CONTROL STRUCTURE + ; + +; PUBLIC MEMBUF +;MEMBUF LABEL BYTE +extrn MEMBUF:byte +; +MSDIP ENDP +CSEG ENDS + END MSDIP diff --git a/ibm/logicops.ezp b/ibm/logicops.ezp new file mode 100644 index 0000000..f1a87e2 --- /dev/null +++ b/ibm/logicops.ezp @@ -0,0 +1,77 @@ + SUBTTL LOGICOPS + PAGE + + ;LESS? + PUBLIC OPQLES,OPQGRT,OPBTST,OPBOR,OPBCOM,OPBAND +OPQLES PROC + CMP AX,BX ;IS OPR1 LESS THAN OPR2? + JL JPT ;YES, PREDICATE TRUE +JPF: JMP PFALSE ;NO, PREDICATE FALSE +JPT: JMP PTRUE +OPQLES ENDP + + ;GRTR? +OPQGRT PROC + CMP AX,BX ;IS OPR1 GREATER THAN OPR2? + JG JPT ;YES, PREDICATE TRUE + JMP JPF ;NO, PREDICATE FALSE +OPQGRT ENDP + + SUBTTL LOGICAL OPERATIONS + PAGE + + + ;BTST +OPBTST PROC + NOT AX ;TURN OFF BITS IN OPR2 THAT ARE ON IN OPR1 + AND BX,AX + JE JPT ;SUCCESS IF OPR2 COMPLETELY CLEARED + JMP JPF +OPBTST ENDP + + ;BOR +OPBOR PROC + OR AX,BX ;LOGICAL OR + JMP PUTVAL ;RETURN THE VALUE +OPBOR ENDP + + ;BCOM +OPBCOM PROC + NOT AX ;LOGICAL COMPLEMENT + JMP PUTVAL ;RETURN THE VALUE +OPBCOM ENDP + + ;BAND +OPBAND PROC + AND AX,BX ;LOGICAL AND + JMP PUTVAL ;RETURN THE VALUE +OPBAND ENDP + + SUBTTL GENERAL PREDICATES + PAGE + + + PUBLIC OPQEQU,OPQZER + ;EQUAL? +OPQEQU PROC + NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV BX,ARGBLK ;GET OPR1 + CMP BX,ARGBLK[2] ;IS OPR1 EQUAL TO OPR2? + JE OQE1$ ;YES + CMP AX,3 ;NO, IS THERE A THIRD OPERAND? + JL OQE2$ ;NO + CMP BX,ARGBLK[4] ;YES, IS IT EQUAL TO OPR1? + JE OQE1$ ;YES + CMP AX,4 ;NO, IS THERE A FOURTH? + JL OQE2$ ;NO + CMP BX,ARGBLK[6] ;YES, IS IT EQUAL TO OPR1? + JNE OQE2$ ;NO +OQE1$: JMP PTRUE ;PREDICATE TRUE IF EQUAL +OQE2$: JMP PFALSE ;PREDICATE FALSE IF NOT +OPQEQU ENDP + + ;ZERO? +OPQZER PROC + CMP AX,0 ;IS OPR ZERO? + JNE OQZ1$ ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQZ1$: JMP PFALSE +OPQZER ENDP diff --git a/ibm/macros.ezp b/ibm/macros.ezp new file mode 100644 index 0000000..830ca27 --- /dev/null +++ b/ibm/macros.ezp @@ -0,0 +1,54 @@ + + SUBTTL MACROS + PAGE + + +GTAWRD MACRO D,S ;;GET ABSOLUTE WORD + MOV D&X,ES:&S + XCHG D&H,D&L + ENDM + +PTAWRD MACRO D,S ;;PUT ABSOLUTE WORK + XCHG S&H,S&L + MOV ES:&D,S&X + ENDM + +MOVM MACRO D,S,R ;;MOVE MEMORY TO MEMORY + MOV R,S + MOV D,R + ENDM + +PUSHZ MACRO S ;;PUSH ONTO Z STACK + XCHG SP,DI + PUSH S + XCHG SP,DI + ENDM + +POPZ MACRO D ;;POP FROM Z STACK + XCHG SP,DI + POP D + XCHG SP,DI + ENDM + +POPZT MACRO D ;;GET TOP OF Z STACK + MOV D,SS:[DI] + ENDM + +PUSHZT MACRO S ;;PUT TOP OF Z STACK + MOV SS:[DI],S + ENDM + +PRINT MACRO STR ;;PRINT A STRING, POINTER IS ARGUMENT + PUSH AX + MOV AX,OFFSET STR + CALL MPRNT + POP AX + ENDM + +FATAL MACRO ERR ;;PRINT FATAL ERROR AND DIE + CALL MCRLF + MOV AX,OFFSET FATHDR + CALL MPRNT + MOV AX,OFFSET ERR + CALL MPRNT + JMP FINISH + ENDM diff --git a/ibm/mainloop.ezp b/ibm/mainloop.ezp new file mode 100644 index 0000000..e559ebe --- /dev/null +++ b/ibm/mainloop.ezp @@ -0,0 +1,128 @@ + SUBTTL MAINLOOP + PAGE + + ;MAIN INSTRUCTION INTERPRETATION LOOP + PUBLIC NXTINS,NXI0A$,NXI0B$,NXI0C$,NXI1$,NXI2$,NXI3$,NXI4$,NXI5$ + PUBLIC NXI6$,NXI7$,NXI8$,NXI8A$,NXI9$,NXI10$,NXI11$,NXI12$,NXI14$ + PUBLIC NXI15$ +NXTINS PROC + CALL NXTBYT ;GET THE OPERATION BYTE + MOV DX,AX ;SAVE A COPY + CMP AX,80H ;IS IT A 2OP? + JAE NXI00$ ;YES + JMP NXI9$ +NXI00$: CMP AX,0B0H ;NO, IS IT A 1OP? + JGE NXI0A$ ;NO + JMP NXI12$ ;YES +NXI0A$: CMP AX,0C0H ;IS IT A 0OP? + JG NXI0B$ ;NO + JMP NXI13$ ;YES +NXI0B$: AND AX,3FH ;IT'S EXTENDED, GET THE OPCODE + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET THE OPERATOR POINTER + MOV SI,[BP+EXTOP] ; (6) REMOVED DS OVERRIDE + CMP SI,0 + JNE NXI0C$ ;OPERATION EXISTS + JMP NXI14$ ;NO SUCH OPERATION +NXI0C$: MOV BP,4 ; (A0) DEFAULT NUMBER OF MODE BITS + CMP DX,0ECH ; (A0) IS IT XCALL? + JNZ NXI0D$ ; (A0) NO, GO ON AS USUAL + MOV BP,8 ; (A0) 8 MODE SPECIFIERS + CALL NXTBYT ; (A0) GET THE FIRST MODE BYTE + MOV DX,AX ; (A0) SAVE IT + CALL NXTBYT ; (A0) GET THE SECOND MODE BYTE + + MOV CX,4 ; (A0) LOOP COUNT +NXI0E$: PUSH AX ; (A0) SAVE BITS IN PROPER ORDER hh + SHR AX,1 ; (A0) MOVE THE BITS TO THE RIGHT + SHR AX,1 ; (A0) MOVE THE BITS TO THE RIGHT + LOOP NXI0E$ + + MOV AX,DX ; (A0) GET SECOND BYTE + JMP NXI0F$ ; (A0) FALL THROUGH TO PROCESS aabbccdd + +NXI0D$: CALL NXTBYT ;GET THE ARGUMENT BYTE +NXI0F$: MOV CX,4 ;SPLIT IT INTO 4 2-BIT MODE BYTES +NXI1$: PUSH AX + SAR AX,1 + SAR AX,1 + LOOP NXI1$ + MOV CX,BP ;RETRIEVE THE 4 (OR 8) BYTES IN PROPER ORDER + SUB DX,DX + MOV BX,OFFSET ARGBLK;FIRST ARGUMENT SLOT +NXI2$: POP AX ;GET NEXT MODE BYTE? + AND AX,3 ;CLEAR OFF UNWANTED BITS + CMP AX,3 ;NO MORE ARGUMENTS? + JE NXI4$ ;YES, FLUSH ANY OTHER MODE BYTES + CALL GETARG ;ELSE, GET THE NEXT ARGUMENT + MOV [BX],AX ;SAVE IT IN ARGUMENT BLOCK + ADD BX,2 + INC DX ;REMEMBER NUMBER OF ARGS GOTTEN +NXI3$: LOOP NXI2$ ;LOOP FOR REST OF MODE BYTES + JMP NXI5$ +NXI4$: DEC CX ;DETERMINE NUMBER OF REMAINING MODE BYTES + SHL CX,1 ;WORD COUNT + ADD SP,CX ;FLUSH THEM +NXI5$: XCHG CX,DX + MOV AX,CX ;NUMBER OF ARGS GOES HERE FOR OPERATOR TO USE + CMP BYTE PTR [SI],90H ;(6)DOES OPERATOR WANT ARGBLK POINTER? + JE NXI8A$ ;YES, CALL OPERATOR NOW + DEC CX ;NO, IT WANTS ARGS IN REGISTERS + JL NXI8A$ ;NO ARGS, JUST CALL OPERATOR + JE NXI8$ ;1 ARG, GET IT + SUB CX,2 + JL NXI7$ ;2 ARGS + JE NXI6$ ;3 ARGS + MOV DX,ARGBLK[6] ;ELSE, 4 ARGS, GET 4TH +NXI6$: MOV CX,ARGBLK[4] ;GET 3RD +NXI7$: MOV BX,ARGBLK[2] ;GET 2ND +NXI8$: MOV AX,ARGBLK ;GET FIRST ARG +NXI8A$: JMP NXI15$ ;AND CALL OPERATOR +NXI9$: AND AX,1FH ;2OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;FIND POINTER TO OPERATOR ROUTINE + MOV SI,[BP+EXTOP] ;(6) REMOVED DS OVERRIDE + CMP SI,0 + JE NXI14$ ;NO SUCH OPERATION + MOV AX,1 ;ASSUME FIRST ARG IS AN IMMEDIATE + TEST DX,40H ;IS IT INSTEAD A VARIABLE? + JE NXI10$ ;NO + INC AX ;YES, CHANGE MODE +NXI10$: CALL GETARG ;GET THE FIRST ARG + PUSH AX ;SAVE IT + MOV AX,1 ;ASSUME SECOND ARG IS AN IMMEDIATE + TEST DX,20H ;IS IT INSTEAD A VARIABLE? + JE NXI11$ ;NO + INC AX ;YES, CHANGE MODE +NXI11$: CALL GETARG ;GET THE SECOND ARG + MOV BX,AX ;POSITION IT + POP AX ;RECOVER FIRST ARG + CMP BYTE PTR [SI],90H ;(6)DOES ROUTINE WANT ARGUMENT BLOCK? + JNE NXI15$ ;NO, GO CALL IT + MOV ARGBLK,AX ;YES, MOVE ARGS TO ARGBLK + MOV ARGBLK[2],BX + MOV AX,2 ;ALWAYS 2 ARGS + JMP NXI15$ ;NOW CALL OPERATOR +NXI12$: AND DX,0FH ;1OP, EXTRACT OPERATION BITS + SHL DX,1 ;MAKE IT A WORD OFFSET + MOV BP,DX ;GET OPERATOR ROUTINE POINTER + MOV SI,[BP+ONEOP] ;(6) REMOVED DS OVERRIDE + CMP SI,0 + JE NXI14$ ;ILLEGAL OPERATION + SAR AX,1 ;EXTRACT MODE BITS + SAR AX,1 + SAR AX,1 + SAR AX,1 + AND AX,3 + CALL GETARG ;GET THE ARGUMENT + JMP NXI15$ ;AND CALL OPERATOR +NXI13$: AND AX,0FH ;0OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET OPERATOR ROUTINE POINTER + MOV SI,[BP+ZEROOP] ; (6) REMOVED DS OVERRIDE + CMP SI,0 + JNE NXI15$ ;IT'S A LEGAL OPERATION +NXI14$: FATAL FTL5 ;OTHERWISE, COMPLAIN +NXI15$: CALL SI ;CALL THE OPERATOR ROUTINE + JMP NXTINS ;AND LOOP FOR NEXT INSTRUCTION +NXTINS ENDP diff --git a/ibm/mathops.ezp b/ibm/mathops.ezp new file mode 100644 index 0000000..19f499e --- /dev/null +++ b/ibm/mathops.ezp @@ -0,0 +1,36 @@ + SUBTTL ARITHMETIC OPERATIONS + PAGE + + + PUBLIC OPADD,OPSUB,OPMUL,OPDIV,OPMOD + ;ADD +OPADD PROC + ADD AX,BX ;ADD OPR1 AND OPR2 + JMP PUTVAL ;RETURN THE VALUE +OPADD ENDP + + ;SUB +OPSUB PROC + SUB AX,BX ;SUBTRACT OPR2 FROM OPR1 + JMP PUTVAL ;RETURN THE VALUE +OPSUB ENDP + + ;MULTIPLY AX BY BX +OPMUL PROC + IMUL BX ;MULTIPLY OPR1 BY OPR2,IGNORING OVERFLOW(DX) + JMP PUTVAL ;RETURN THE VALUE +OPMUL ENDP + + ;DIVIDE AX BY BX +OPDIV PROC + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + JMP PUTVAL ;RETURN THE VALUE +OPDIV ENDP + + ;MOD +OPMOD PROC + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + MOV AX,DX ;WE WANT REMAINDER + JMP PUTVAL ;RETURN THE VALUE +OPMOD ENDP diff --git a/ibm/msibmzip.asm b/ibm/msibmzip.asm new file mode 100644 index 0000000..5818e5d --- /dev/null +++ b/ibm/msibmzip.asm @@ -0,0 +1,4349 @@ + TITLE ZIP Z-LANGUAGE INTERPRETER IBM/MS-DOS 2.0 VERSION + + PAGE 58,132 + .LIST + + ; Modification History - + ;--------------------------------------------------- + ; + ; 1) REWORKED FOR NEW SETUP FILE USAGE + ; 2) FIXED NON-WORKING STACK SAVE AND RESTORE FILE + ; 3) FIX RANDOM BUG - 6/25/84 + ; 4) FIXED STATUS LINE (LONG ROOM DESCRIPTION) - 07/24/84 + ; 5) Fixed status line bug on restart 22-Oct-84 - PHG "G" + ; 6) REWRITE OF ZIP TO USE ALL MEMORY 1-NOV-84 - PHG "H" + ; 7) Combination of IBM and MSZIP with new copy protection + ; for all IBM compatible machines. 11-Mar-85 - PHG + ; Minor versions: I -- original to test + ; J -- fixed status line and more + ; k -- enhanced printer timeout for IBM + ; l -- mcrlf added to save, commenting + ; m -- fixed status line for TI-PRO + ; n -- added insert game disk on save + ; and paging problems. Also reworked + ; scripting. + ; o -- fixed script on restart, no script on + ; more, and minor save problems + ; q -- fixed disk switch for verify + ; + ; r -- fixed status line bugs and refixed + ; disk switch on restart. + ; s -- restart bug on Tandy (their incompati- + ; bility and more on restart + ; t -- removed extra CR from opening screen bet + ; ween last line of text and prompt. + ; u -- Fixed mchri not to echo character on + ; more or insert game disks. + ; v -- fixed broken restore or failed save on + ; low memory configuration, error in fit + ; calculation, /k was fixed to work any + ; where on the cmdline. + ; w -- added /P for PCjr support, fixed still + ; broken end of memory calculation caused + ; by forgetting to count prelod blocks as + ; used memory blocks. Also fixed opread + ; so that it would flush words read greater + ; than 59. + ; x -- fix script checks from cmp to test. + ; to fix wishbringer. RELEASE AS H + ; J z -- stab at verify/paging bug, found in + ; newzpc when setting curtab to zero since + ; page is preloaded, didn't set zpcseg to + ; 0 as well. RELEASE AS J + ; J 1 -- fixed script bug on failed restore + ; K 1 -- fixed save/restore bug. Removed srblks + ; 2 -- fixed fix above which was still broken. + ; 3 -- j1 was broken by k2 edit. fixed here + ; 4 -- above + ; 5 -- fixed restart to set segs to 0 + ; 6 -- stab at fixing screwy dos disk flush on + ; create. + ; 7 -- fix screen op to not clear window first + ; 8 -- set min memory to 32k + ; L RELEASE VERSION -- minmem set to 24K + ; + ; M 1 -- fix read in of last virtual block for full game + ; 2 -- fixed a cross segment boundary get in nxtbyt + ; N 1 -- fixed zip to not NEED setup.inf + ; + SUBTTL STACK AND DATA SEGMENTS INITIALIZATION + +ZVERSN EQU "N" ;ZIP VERSION NUMBER +ZEDIT EQU 0 ; EDIT NUMBER +ZMVERS EQU 3 ;Z-MACHINE VERSION NUMBER +LSTACK EQU 512 ;LENGTH OF USER STACK(MUST BE 1 PAGE FOR NOW) +DEBUG EQU 0 + +PVERS1 EQU 0 ;POSITION OF ZVERSION VERSION BYTE +PVERS2 EQU 1 ;ZVERSION MODE BYTE +PZRKID EQU 2 ;ZORKID +PENDLD EQU 4 ;ENDLOD +PSTART EQU 6 ;START +PVOCTB EQU 8 ;VOCAB +POBJTB EQU 10 ;OBJECT +PGLOTB EQU 12 ;GLOBALS +PPURBT EQU 14 ;PURBOT +PFLAGS EQU 16 ;USER FLAG WORD +PSERNM EQU 18 ;SERIAL NUMBER (6 BYTES) +PWRDTB EQU 24 ;WORDS +PLENTH EQU 26 ;GAME LENGTH +PCHKSM EQU 28 ;GAME CHECKSUM + +PADCHR EQU 5 ;PADDING CHARACTER + +SSVER EQU "A"-10 ; ADD THIS TO THE VERTICAL SETUP HEIGHT +SSHOR EQU -6 ; ADD THIS TO THE HORIZONTAL SETUP WIDTH +SSLNT EQU 3 ; LENGTH OF SETUP FILE + + +CRESET EQU 0H ;MS-DOS FUNCTION CALLS WITH INT 21H +CCONIN EQU 1H +CPROUT EQU 5H +CCONIO EQU 6H +CNOECHO EQU 7H ; (7) FIX MCHRI TO HAVE NO ECHO +CRDLIN EQU 0AH +CDRESET EQU 0DH ; (7o) DISK RESET +CSELDSK EQU 0EH ; (7n) SELECT DISK +CFOPEN EQU 0FH +CFCLOS EQU 10H +CFDELE EQU 13H +CFMAKE EQU 16H +CURDSK EQU 19H ; (7n) CURRENT DISK +CSDMAO EQU 1AH +CRDRND EQU 21H +CWRRND EQU 22H +CPRSNM EQU 29H +; FUNCTION CALLS ADDED FOR VERSION "H" +; UPGRADE TO DOS 2.0 AND ABOVE +CFCREAZ EQU 3CH +CFOPENZ EQU 3DH +CFCLOSZ EQU 3EH +CRDRNDZ EQU 3FH +CWRRNDZ EQU 40H +CFDELEZ EQU 41H +CFSEEK EQU 42H +CSETBLK EQU 4AH ; FOR DETERMINING MEM SIZE +SCROLLUP EQU 6 ; (7) FOR VIDEO BIOS CALL +DOSVER EQU 30H ; (7) REQUEST FOR DOS VERSION +BIOSEG EQU 0F800H ; (7) STRINGS ARE FOUND AT F000:E0++ +BIOSOFF EQU 0000H ; (7) +COLCUR EQU 0607H ; (7) CURSOR SCAN LINES FOR COLOR +SETCUR EQU 1 ; (7) VIDEO FUNCTION TO SET CURSOR SIZE +COLATR EQU 17H ; (7) COLOR ATTRIBUTE IS WHITE ON BLUE +SCRBIT EQU 100000B ; (7) 5 BIT TURNS ON SCREEN SPLITTING +TOPSCR EQU 0100H ; (7) COORD'S OF TOP OF WINDOW +STDPRT EQU 4 ; (7) STANDARD PRINTER DEVICE +PRTMSK EQU 0A1H ; (7) PRINTER INI STATUS MASK +SCRMSK EQU 0FEFFH ; (7) WORD TO MASK SCRIPT BIT IN MODE WORD +RDYBIT EQU 1 ; (7) WAS THE PRINTER READY +MINMEM EQU (24*1024)/16 ; (7) MINIMUM MEMORY IN PARAGRAPHS +MAXLIN EQU 78 ; (7r) MAXIMUM INPUT LINE LENGTH + +; ALL SEGS ORIGINALLY POINT TO CSEG. THE ORG 100H IS STANDARD FOR +; PRODUCING A .COM FILE. THE ES SEGMENT IS ADJUSTED DYNAMICALLY IN THE +; SYSINI ROUTINE TO ALLOW GAME SEGMENTS TO START AT OFFSET ZERO. +; SEE COMMENTS IN SYSINI FOR GAME SEGMENT ALLOCATION AND CALCULATION. + +CSEG SEGMENT PARA PUBLIC + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG + ORG 100H +; + PUBLIC MSZIP +MSZIP PROC + JMP START ; SKIP OVER ZIP DATA +; +; ALL DATA SAVE THE PAGE TABLE (PAGTAB) ARE DEFINED BETWEEN THE ABOVE JMP +; AND THE STARTING DESTINATION. +; + ;VARIBLE DEFINITIONS: + + PUBLIC START,GAMFILE,SAVFILE,GAMHNDL,SAVHNDL,HANDLE,SEEKF + PUBLIC LASTDRV,LSTDFLG,DRVFLG,LASTSAV,SSBUF,DEFDRV,CURDRV + ;GTBLKS +;************************************************************************ +; DO NOT MOVE THESE VARIABLES. DEFINE NOTHING ABOVE THEM. CREATE +; IS DEPENDENT UPON THIS FIXED VARIABLE SETUP FOR GAMFILE AND +; SAVFILE. +;************************************************************************ +; +GAMFILE DB "WITNESS.DAT",0 ; PATCHED BY CREATE + DB 53 DUP (0) ; POTENTIAL LENGTH OF FILENAME +SAVFILE DB "WITNESS.SAV",0 + DB 53 DUP (0) ; POTENTIAL LENGTH OF FILENAME +LASTSAV DB 64 DUP (0) +; +GAMESIZ DW ? ; GAME SIZE IN 512 BYTE BLOCKS +GAMHNDL DW ? ; FOR STORAGE OF FILE HANDLES +SAVHNDL DW ? +SSFILE DB "SETUP.INF",0 +SSBUF DW SSLNT/2 DUP (0) +SKPDRV DB 0 ; (7n) DON'T OUTPUT DRIVE NAME +DEFDRV DB ? ; BYTE FOR DEFAULT DRIVE +CURDRV DB ? ; BYTE FOR NEW DRIVE (SAVES) +DRVFLG DB 0 ; FLAG WHETHER DRIVE SPECIFIED ON SAVE +LASTDRV DB ? ; TEMPORARY STORAGE FOR SAVE AND +LSTDFLG DB ? ; RESTORE FAILURE +HANDLE DW ? ; GENERAL HANDLE FOR GTBLKS ROUTINE +SEEKF DB 1 ; FLAG FOR WHETHER OR NOT TO SEEK +PRTBUF DB ? ; (7) BUFFER FOR PRINTER OUTPUT + + PUBLIC DSKDIR +DSKDIR DB 0 ;0 FOR READ, 1 FOR WRITE + + ; SCREEN DEFINITIONS AND ANSI STRINGS + PUBLIC SCRATR,COLFLG,SCP,RCP,SCPL,SLPP,STINIT,STRESET,SBLINE + PUBLIC SELINE,SPINIT,STINIT,CTRESET,CBLINE,CELINE,CLS,CLSC +SCRATR DB 7 ;(7) BLACK BACKGROUND FOR DEFAULT +COLFLG DB 0 ;(7) ARE WE USING COLOR +SCPL DB 80 ; WIDTH OF THE SCREEN IN COLUMNS (DEFAULTS) +SLPP DB 25 ; LENGTH OF THE SCREEN IN ROWS +SCP DB 3 ; (7) ANSI SAVE CURSOR POSITION + DB 27,'[s' +RCP DB 3 ; (7) ANSI RESTORE CURSOR POSITION + DB 27,'[u' +STINIT DB 16 + DB 27,"[2J",27,"[0m",27,"[01;01H" +STRESET DB 4 + DB 27,"[0m" +SBLINE DB 15 + DB 27,"[37;7m",27,"[01;01H" +SELINE DB 12 + DB 27,"[0m",27,"[" +SELINE1 DB "25;01H" +SPINIT DB 0 +CTINIT DB 20 + DB 27,"[37;44m",27,"[2J",27,"[01;01H" +CTRESET DB 0 +CBLINE DB 16 + DB 27,"[31;47m",27,"[01;01H" +CELINE DB 16 + DB 27,"[37;44m",27,"[" +CELINE1 DB "25;01H" +CPINIT DB 0 +CLS DB 12 + DB 27,"[2J",27,"[" +CLS1 DB "25;01H" +CLSC DB 20 + DB 27,"[37;44m",27,"[2J",27,"[" +CLS1C DB "25;01H" +; + PUBLIC WINDOW1,COLWIN1,WINDOW0,COLWIN0,RADIX +WINDOW1 DB 8 + DB 27,'[02;01H' +COLWIN1 DB 16 + DB 27,'[02;01H',27,'[34;42m' +WINDOW0 DB 4 + DB 27,'[0m' +COLWIN0 DB 8 + DB 27,'[37;44m' +RADIX DB 10 ; THE DEFAULT RADIX FOR THE SCREEN + ;SCRIPTING STUFF + PUBLIC GAMEIN,SCRHLD,SCRFLG,PRNNRDY +GAMEIN DB 0 +SCRHLD DB 0 ; (7n) IS SCRIPTING TEMPORARILY OFF +SCRFLG DB 0 +PRNNRDY DB " %Printer not ready: Abort or Retry? ",80H + + ;USL STUFF +SLFLG DB 1 ;STATUS LINE ASSUMED PRESENT +PMFLAG DB 0 ;AM/PM + + PUBLIC SLSTR,SLTAB,SLSTAB,SLTTAB +SLSTR DW 0 ;TOP OF SCREEN STRING +SLTAB DW 0 ;TABLE USED BY OPUSL + + +; STATUS LINE DESCRIPTOR TABLE. CHOSEN BASED ON SETUP.INF AND MODE +; WORD. CHOICE OF STATUS LINE RESULTS WITH STATUS LINE STRING POINTER +; IN SLSTR AND TABLE DESCRIBING STATUS LINE IN SLTAB. +; +SLSTAB DW SLS40 + DW SLS40T + DW SLS80 + DW SLS80T +SLTTAB DW SLT40 + DW SLT40T + DW SLT80 + DW SLT80T + +; THE FOLLOWING DATA STRUCTURES ARE TABLES AND STRINGS THAT ARE +; DEFINED TO CREATE AND MAINTAIN A WIDE VARIETY OF STATUS LINES. +; THE STRUCTURE OF THE DATA IS FIRST A STRING WHERE THE ROOM DESCRIPTION +; AND THE SCORE/MOVES OR TIME WILL BE WRITTEN. (A POINTER INTO THIS +; STRING IS CREATED IN TSETUP BASED ON TERMINAL WIDTH) +; +; THE STRING IS FOLLOWED BY A TABLE 12 WORDS IN LENGTH. THOSE WORDS +; CAN BE BROKEN UP INTO 3 GROUPS OF 4 WORDS. THERE IS ONE GROUP FOR +; EACH OF ROOM DESCRIPTION, SCORE AND MOVES (OR HOURS AND MINUTES). +; THE FIRST WORD INDICATES WHEN THE ENTRY WAS LAST UPDATED, THE SECOND +; IS A POINTER TO THE ROUTINE THAT OUTPUTS THE QUANTITY, AND THE THIRD +; AND FOURTH ARE THE BOUNDARIES OF THE FIELD IN WHICH THE QUANTITY IS +; WRITTEN. +; +; OPUSL AND TSETUP ARE THE ONLY ROUTINES THAT "KNOW" ABOUT THESE DATA +; STRUCTURES + +;40 COLUMN, SCORE + PUBLIC SLS40,SLS40T +SLS40 DB 40 DUP(32),"S:",5 DUP(32),"M:",6 DUP(32),0,80H +SLS40T DW -1 ; LAST UPDATE + DW OPPRND ; ADDR OF PRINT ROOM DESC + DW 1 ; STARTING COLUMN + DW 25 ; ENDING COLUMN + DW -1 + DW OPPRNN + DW 28 + DW 30 + DW -1 + DW OPPRNN + DW 35 + DW 40 + +;40 COLUMN, TIME + PUBLIC SLT40,SLT40T +SLT40 DB 40 DUP(32),"Time:",10 DUP(32),0,80H +SLT40T DW -1 + DW OPPRND + DW 1 + DW 24 + DW -1 + DW OPPRNH + DW 31 + DW 33 + DW -1 + DW OPPRNM + DW 34 + DW 40 + +;80 COLUMN, SCORE + PUBLIC SLS80,SLS80T +SLS80 DB 110 DUP(32),"Score:", 10 DUP(32),"Moves:",7 DUP(32),0,80H +SLS80T DW -1 + DW OPPRND + DW 1 + DW 27 + DW -1 + DW OPPRNN + DW 57 ; (7) ADJUST SCORE AND MOVES UNITS + DW 61 ; (7) BACK ONE FOR DA + DW -1 + DW OPPRNN + DW 73 ; (7) + DW 80 ; (7) + +;80 COLUMN, TIME + PUBLIC SLT80,SLT80T +SLT80 DB 120 DUP(32),"Time:", 13 DUP(32),0,80H +SLT80T DW -1 + DW OPPRND + DW 1 ; (7) CHANGED FROM 3 FOR CONSISTENCY + DW 29 ; (7) UNDER DIRECTION BY DA + DW -1 + DW OPPRNH + DW 66 ; (7) ADJUST BACKWARDS BY 3 FOR DA + DW 68 ; (7) + DW -1 + DW OPPRNM + DW 69 ; (7) + DW 80 ; (7) + + PUBLIC RSEED1,RSEED2 + ;OPRAND +RSEED1 DW ? ;SEED1 FOR RANDOM NUMBERS +RSEED2 DW ? ;SEED2 FOR RANDOM NUMBERS +RTEMP DW ? ;TEMP FOR RANDOM ROUTINE + + PUBLIC RDWSTR,RDBOS,RDEOS,RDRET,RDNWDS,WRDOFF + ;READ +RDWSTR DW 4 DUP(0) ;WORD STRING BUFFER FOR ZWORD +RDBOS DW 0 ;BEGINNING OF STRING POINTER +RDEOS DW 0 ;END OF STRING POINTER +RDRET DW 0 ;RETURN TABLE POINTER +RDNWDS DB 0 ;NUMBER OF WORDS READ + ;PUTSTR +WRDOFF DW 0 ;OFFSET INTO WORD TABLE FOR CURRENT SET + + PUBLIC CHRPTR,ENDBUF + ;PUTCHR +CHRPTR DW 0 ;POINTS TO NEXT CHARACTER POSITION +ENDBUF DW 0 ;POINTS JUST PAST END OF OUTPUT BUFFER (0) + ;GETNUM +STATUS DW 0 ;STATUS-LINE-REQUESTED FLAG + + PUBLIC IRBRKS,TIMEMD,ZORKID,ENDLOD,VOCTAB,OBJTAB + PUBLIC GLOTAB,WRDTAB,PURBOT,ESIBKS,VWLEN,VWORDS,VOCBEG + PUBLIC OUTBUF,INBUF,RBRKS,BUFFERS,PAGES,INITTBL,SEGEND + ;ZIPBGN +IRBRKS DB " ",9,13,12,".,?",0 ;INITIAL SET OF READ BREAK CHARS +TIMEMD DW 0 ;TIME(VERSUS SCORE)-MODE-FOR-STATUS-LINE FLAG +ZORKID DW 0 ;UNIQUE GAME & VERSION IDENTIFIER +ENDLOD DW 0 ;ENDLOD BLOCK NUMBER +SEGEND DW 0 ; (6) ENDLOD THAT DOESN'T GET DIDDLED +VOCTAB DW 0 ;SAVE VOCABULARY TABLE POINTER +OBJTAB DW 0 ;OBJECT TABLE POINTER +GLOTAB DW 0 ;GLOBAL TABLE POINTER +WRDTAB DW 0 ;WORD TABLE POINTER +PURBOT DW 0 ;PURE CODE POINTER +ESIBKS DW 0 ;END OF SELF-INSERTING BREAK CHARACTERS +VWLEN DW 0 ;NUMBER OF BYTES IN A VOCABULARY WORD ENTRY +VWORDS DW 0 ;NUMBER OF WORD ENTRIES IN VOCABULARY +VOCBEG DW 0 ;BEGINNING OF ACTUAL VOCABULARY +OUTBUF DB 81 DUP(?) ;OUTPUT BUFFER +INBUF DB MAXLIN+2 DUP(?) ;INPUT BUFFER +RBRKS DB 32 DUP(?) ;STRING OF READ BREAK CHARACTERS +BUFFERS DW 0 ;(6) NUMBER OF 512 BYTE BUFFERS FOR PAGING +PAGES DW 0 ;SWAPPING AREA +CHRFLG DB 0 +INITTBL DB 254,0,0,0 + +; CMDLIN WAS CREATED FOR CHANGING CERTAIN PARAMETERS ON THE COMMAND LINE +; CURRENTLY THERE ARE SWITCHES (C,M,W). BITS ARE SET IN SCANCMD AND +; PROCESSED IN SYSINI OR SSETUP. +; + PUBLIC CMDLIN,MEMORY +CMDLIN DB 0 ; (7n) 16=IBM PARALLEL PRINTER + ; (7) 8=SCROLL SET + ; (7) 4=MEMORY SET + ; (7) 2=COLOR SET + ; (7) 1=MONOCHROME SET +MEMORY DW 0 ; (7) MEMORY SIZE SET ON CMDLIN + + PUBLIC ZLOCS,ZPC1,ZPC2,ARGBLK,ZPCSEG,ZPCFLG + ;RESTRT +ZLOCS DW 0 ;POINTER TO LOCALS +ZPC1 DW 0 ;ZPC BLOCK-POINTER +ZPC2 DW 0 ;ZPC BYTE-POINTER +ZPCSEG DB 0 ;(6) GAME SEGMENT WHERE ZPC IS +ZPCFLG DB 0 ; (7n) ZPC PAGE IS MUNGED? +ARGBLK DW 4 DUP(?) ;ARGUMENT BLOCK FOR EXTENDED OPERATIONS + + PUBLIC CURPAG,CURBLK,CURTAB,CURSEG + ;NEWZPC +CURPAG DW 0 ;CURRENT PAGE (WHERE ZPC IS) POINTER +CURBLK DW 0 ;CURRENT BLOCK, USUALLY SAME AS ZPC1 +CURTAB DW 0 ;CURRENT PAGE TABLE POINTER +1 + + PUBLIC RTIME1,RTIME2,LPAGE,LPLOC,LPTAB,GAMESEG,SEG1,FITS + ;GETPAG +RTIME1 DB 0 ;REFERENCE TIME, 1 1/2 WORDS USED +RTIME2 DW 0 +LPAGE DW 0 ;LAST REFERENCED PAGE NUMBER +LPLOC DW 0 ;AND ITS CORE LOCATION +LPTAB DW 0 ;AND ITS TABLE POINTER +GAMESEG DW ? ;(6) FIRST (OR ZERO) GAME SEGMENT +SEG1 DW ? ;(6) SECOND GAMESEG (GAMESEG+64K) +CURSEG DB 0 ;(6) SEGMENT (0/1) FOR CURRENT PAGE +FITS DB 0 ;(6) FLAG FOR GAME ALL IN MEMORY + + ; SPLIT AND SCREEN VARS + PUBLIC SCRNFLG,SPLCOL,SPLTFLG +SCRNFLG DB 0 ; (7) WINDOW THAT WE ARE WRITING IN +SPLCOL DB 27H ; (7) GREEN BACKGROUD FOR WINDOW 1 +SPLTFLG DB 0 ; (7) IS THE SCREEN SPLIT + + ;OPERATION TABLES: ;ZERO ARGUMENT OPERATIONS + PUBLIC ZEROOP,ONEOP,EXTOP +ZEROOP DW OPRTRU ;176 + DW OPRFAL ;177 + DW OPPRNI ;178 + DW OPPRNR ;179 + DW OPNOOP ;180 + DW OPSAVE ;181 + DW OPREST ;182 + DW OPRSTT ;183 + DW OPRSTA ;184 + DW OPFSTA ;185 + DW OPQUIT ;186 + DW OPCRLF ;187 + DW OPUSL ;188 + DW OPVERI ;189 + DW 0 ;190 + DW 0 ;191 + ;ONE ARGUMENT OPERATIONS +ONEOP DW OPQZER ;128 + DW OPQNEX ;129 + DW OPQFIR ;130 + DW OPLOC ;131 + DW OPPTSI ;132 + DW OPINC ;133 + DW OPDEC ;134 + DW OPPRNB ;135 + DW 0 ;136 + DW OPREMO ;137 + DW OPPRND ;138 + DW OPRETU ;139 + DW OPJUMP ;140 + DW OPPRIN ;141 + DW OPVALU ;142 + DW OPBCOM ;143 + ;TWO ARGUMENT AND EXTENDED ARGUMENT OPERATIONS +EXTOP DW 0 ;0 + DW OPQEQU ;1 + DW OPQLES ;2 + DW OPQGRT ;3 + DW OPQDLE ;4 + DW OPQIGR ;5 + DW OPQIN ;6 + DW OPBTST ;7 + DW OPBOR ;8 + DW OPBAND ;9 + DW OPQFSE ;10 + DW OPFSET ;11 + DW OPFCLE ;12 + DW OPSET ;13 + DW OPMOVE ;14 + DW OPGET ;15 + DW OPGETB ;16 + DW OPGETP ;17 + DW OPGTPT ;18 + DW OPNEXT ;19 + DW OPADD ;20 + DW OPSUB ;21 + DW OPMUL ;22 + DW OPDIV ;23 + DW OPMOD ;24 + DW 0 ;25 + DW 0 ;26 + DW 0 ;27 + DW 0 ;28 + DW 0 ;29 + DW 0 ;30 + DW 0 ;31 + DW OPCALL ;224 + DW OPPUT ;225 + DW OPPUTB ;226 + DW OPPUTP ;227 + DW OPREAD + ;228 + DW OPPRNC ;229 + DW OPPRNN ;230 + DW OPRAND ;231 + DW OPPUSH ;232 + DW OPPOP ;233 + DW OPSPLT ;234 + DW OPSCRN ;235 + DW 0 ;236 + DW 0 ;237 + DW 0 ;238 + DW 0 ;239 + DW 0 ;240 + DW 0 ;241 + DW 0 ;242 + DW 0 ;243 + DW 0 ;244 + DW 0 ;245 + DW 0 ;246 + DW 0 ;247 + DW 0 ;248 + DW 0 ;249 + DW 0 ;250 + DW 0 ;251 + DW 0 ;252 + DW 0 ;253 + DW 0 ;254 + DW 0 ;255 + + ;(7) COPY PROTECTION STUFF + PUBLIC COMPATS,COMP1 +COMPATS DW 2 ; (7) NUMBER OF STRINGS IN THE LIST +COMP1 DB 'COMPAQ Co$' + DB 'COPR. IBM$' ; (7) EACH STRING MUST BE 9 CHARS +; DB 'Tandy Cor$' ; (7v) ADD TANDY + + ;MCRLF + PUBLIC SCROLL,TOPLIN,MORLIN + ; (7) SCROLL IS SEEMINGLY BACKWARDS BUT TOO INTERWOVEN TO + ; GO AROUND AND FIX NOW. + ; 0 = IBM Compatible 100% (use windowed scrolling) + ; 1 = MS-DOS, no windowed scrolling + ; +SCROLL DB 1 +TOPLIN DW TOPSCR ; (7) WORD FOR CH,CL FOR UPPER RIGHT +MORE DB "**MORE** ",80H +EMORE DB 13," ",13,80H +MORLIN DW 0 ; (7) COUNT OF LINES SCROLLED WITHOUT PAUSE + + ;STRUCTURE AND RECORD DEFINITIONS: + ;OBJECT OPERATIONS +OBJECT STRUC +FLAGS1 DW ? +FLAGS2 DW ? +PARENT DB ? +SIBLING DB ? +CHILD1 DB ? +PROPS DW ? +OBJECT ENDS +PROPID RECORD PROPSIZE:3,PROPNUM:5 + + ;STRING DEFINITIONS + + ;STATION IDENTIFICATION + PUBLIC IDSTR +IDSTR DB "IBM/MS-DOS 2.0 Interpreter Version ",ZVERSN,ZEDIT,0 + + ;TERMINAL SETUP +SSMSG1 DB "Cannot open Setup File.",0 +SSMSG2 DB "Cannot read Setup File.",0 +SSMSG3 DB "Cannot close Setup File.",0 + + PUBLIC SAV0,SAV1,SAV2,SAV3,ERR1,ERR2,ERR3,ERR4,ERR5,ERR6 + ;SAVE/RESTORE +SAV0 DB "Insert save disk then enter file name.",0 +SAV1 DB "(Default is ",80H +SAV2 DB "): ",80H +SAV3 DB "Insert game disk then strike any key to continue.",0 + +ERR1 DB "SAVE file not found",0 +ERR3 DB "Bad file name syntax",0 +ERR4 DB "Unable to access file",0 +ERR5 DB "No room on diskette for SAVE file",0 +ERR6 DB "Read of SAVE file failed",0 + ;READ +ERR2 DB "Too many words typed, flushing: ",80H + + PUBLIC FTL2,FTL4,FTL5,FTL6,FTL7,FTL9 + ;OPNEXT/OPPUTP +FTL2 DB "No such property",0 + ;ZIPBGN +FTL4 DB "Wrong game or version",0 + ;NXTINS +FTL5 DB "Illegal operation",0 + ;FINDPG +FTL6 DB "No free pages",0 + ;GTBLKS +FTL7 DB "Game file read error",0 + ;SYSINI +FTL9 DB "Game file not found",0 +FTL10 DB 'Unauthorized copy',0 +FTL11 DB 'Wrong DOS version. Must be 2.0 or higher',0 +FTL12 DB 'Insufficient memory to play game',0 + + ;Fatal error header +FATHDR DB "Fatal error: ",80H + ;ZSTR CHARACTER CONVERSION VECTOR + + PUBLIC ZCHRS +ZCHRS DB "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + DB " 0123456789.,!?_#'" + DB '"/\-:()' + + PUBLIC STK_TOP,STKBOT,ZSTK_TP +; STACK SETUP + DW 200H DUP(?) +STK_TOP LABEL WORD +STKBOT DW LSTACK DUP(?) +ZSTK_TP LABEL WORD +; + SUBTTL MACROS + PAGE + +GTAWRD MACRO D,S ;;GET ABSOLUTE WORD + MOV D&X,ES:&S + XCHG D&H,D&L + ENDM + +PTAWRD MACRO D,S ;;PUT ABSOLUTE WORK + XCHG S&H,S&L + MOV ES:&D,S&X + ENDM + +MOVM MACRO D,S,R ;;MOVE MEMORY TO MEMORY + MOV R,S + MOV D,R + ENDM + +PUSHZ MACRO S ;;PUSH ONTO Z STACK + XCHG SP,DI + PUSH S + XCHG SP,DI + ENDM + +POPZ MACRO D ;;POP FROM Z STACK + XCHG SP,DI + POP D + XCHG SP,DI + ENDM + +POPZT MACRO D ;;GET TOP OF Z STACK + MOV D,SS:[DI] + ENDM + +PUSHZT MACRO S ;;PUT TOP OF Z STACK + MOV SS:[DI],S + ENDM + +PRINT MACRO STR ;;PRINT A STRING, POINTER IS ARGUMENT + PUSH AX + MOV AX,OFFSET STR + CALL MPRNT + POP AX + ENDM + +FATAL MACRO ERR ;;PRINT FATAL ERROR AND DIE + CALL MCRLF + MOV AX,OFFSET FATHDR + CALL MPRNT + MOV AX,OFFSET ERR + CALL MPRNT + JMP FINISH + ENDM + + SUBTTL SYSTEM INITIALIZATION + PAGE + + + PUBLIC START +START: MOV SP,OFFSET STK_TOP + MOV DI,OFFSET ZSTK_TP + JMP ZIPBGN ;JUMP TO BEGINNING OF ZIP CODE +; + PUBLIC OPSPLT,OPSCRN +OPSCRN PROC + MOV SCRNFLG,AL ; (7) TOGGLE SCREEN CURRENTLY ON + TEST AL,AL ; (7) WHICH DO WE WANT + JZ SCRN0 ; (7) SELECT BOTTOM, SCROLLING WINDOW + CALL SAVECUR +SCRN1: MOV BX,OFFSET WINDOW1 ; (7) HOME THE CURSOR + TEST COLFLG,1 ; (7) SHOULD WE SET THE COLOR + JZ SCRN2 ; (7) NOPE + MOV BX,OFFSET COLWIN1 ; (7) CLEAR SCREEN WITH COLOR +SCRN2: CALL MSPRT ; (7) WITH ANSI LOCATE + RET +SCRN0: CALL RESTCUR ; (7) RESTORE THE CURSOR POSITION + MOV BX,OFFSET WINDOW0 + TEST COLFLG,1 ; (7) SHOULD WE CHANGE THE COLOR + JZ SCRN3 ; (7) NOPE... + MOV BX,OFFSET COLWIN0 +SCRN3: CALL MSPRT ; (7) RESTORE COLOR + RET +OPSCRN ENDP + +OPSPLT PROC + XOR AH,AH + CMP AL,0 + JNZ SPL1 ; (7) YES, FIGURE WINDOW SIZE + MOV SPLTFLG,0 ; (7) TURN OFF SPLIT SCREEN + MOV TOPLIN,TOPSCR ; (7) RESTORE TOPLIN TO WHOLE SCR + MOV MORLIN,0 ; (7) RESET THE MORE LINE COUNT + CALL RESTCUR + RET +SPL1: MOV SPLTFLG,1 ; (7) TURN ON SPLIT SCREEN + CMP AL,SLPP ; (7) ARE THERE THIS MANY LINES + JLE SPL2 + MOV AL,SLPP ; (7) USE NO MORE THAN THE SCREEN + DEC AL ; (7) LEAVE A SCROLL LINE +SPL2: XCHG AH,AL ; (7) GET #LINES IN TOP HALF + ADD TOPLIN,AX ; (7) THIS FIXES WINDOW 0 SCROLL SIZE + PUSH AX ; (K7) FIX CLEAR ON SPLIT SCREEN + CALL SAVECUR ; (7) SAVE THE CURSOR POSITION + MOV BH,SCRATR ; (7) GET ATTRIBUTE INTO BH FOR CLS + TEST COLFLG,1 ; (7) COLOR BLANK OR VANILLA BLANK + JZ SPL3 ; (7) VANILLA... + MOV BH,SPLCOL ; (7) USE THE GREEN CLEAR +SPL3: POP AX ; (K7) RESTORE AX + MOV DH,AH ; (7) BLANK WINDOW #1 +; DEC DH ; (7) LESS ONE LINE (REMOVED (K7)) + MOV AH,SCROLLUP ; (7) BLANK THE SCREEN + MOV AL,0 ; (7) ZERO MEANS ENTIRE WINDOW + MOV CX,TOPSCR ; (7) FROM UPPER LEFT + MOV DL,SCPL ; (7) TO LOWER RIGHT + DEC DL ; (7v) COORDINATES ARE ZERO BASED + INT 10H ; (7) CALL VIDEO BIOS ROUTINE TO CLS + CALL RESTCUR ; (7) RESTORE CURSOR POSITION + RET +OPSPLT ENDP + + PUBLIC SAVECUR +SAVECUR PROC + MOV BX,OFFSET SCP ; (7) ANSI SAVE CURSOR + CALL MSPRT + RET +SAVECUR ENDP + + PUBLIC RESTCUR +RESTCUR PROC + MOV BX,OFFSET RCP ; (7) ANSI RESTORE CURSOR + CALL MSPRT + RET +RESTCUR ENDP + + PUBLIC FEEP +FEEP PROC + MOV AX,7 + CALL MTTYO ;BELL + RET +FEEP ENDP +; +; VERIFY +; +; OP VERIFY HAS BEEN GIVEN A SPLIT PERSONALITY. THE CASE THAT THE ENTIRE +; GAME FITS INTO MEMORY CALLS ON OPVR2$ WHICH READS THE GAME IN TWO 64K +; READS. THE SECOND ES SEGMENT IS USED SO THAT THE SECOND READ WILL RESTORE +; THE GAME TO ITS ORIGINAL STATE. 64K IS READ IN AND CHECKSUMED AND THEN +; THE REMAINDER OF THE GAME IS READ BACK IN AND CHECKSUMED. +; +; THE ORIGINAL VERIFY FORCES THE PRELOAD TO BE LOADED AGAIN BY SETTING THE +; ENDLOD POINTER TO ZERO. THIS TRICKS GETBYT INTO THINKING THAT NO PAGES +; ARE LOCKED ALREADY IN CORE AND FORCES A CALL TO THE PAGING ROUTINES. +; +; + PUBLIC OPVERI +OPVERI PROC + CALL GAMOPEN ; (7q) PUT THE DISK BACK IN + PRINT IDSTR + CMP FITS,1 ; (6) WHOLE GAME IN??? + JNZ OPVR1$ + JMP OPVR2$ +OPVR1$: MOV AX,ES:[PLENTH] ; (7q) GET END BYTE ADDR + XCHG AH,AL ; (7q) FLOP BYTES + MOV ZPCFLG,1 ; (7n) SET MUNGED ZPC FLAG + PUSH SI + PUSH DI + PUSH ENDLOD + CALL BSPLIT + MOV SI,AX + MOV DI,BX + + CALL TBLINI ; (7n) REINITIALIZE THE PAGE TABLE + MOV BX,CURTAB + DEC BX + MOV AX,CURBLK + MOV [BX],AX + MOV AX,0FFFFH + INC BX + MOV [BX],AX + MOV BYTE PTR 2[BX],AL + + MOV AX,0 + MOV BX,64 + MOV DX,0 + MOV ENDLOD,0 +OPVR1: PUSH SI + PUSH DI + PUSH DX + CALL GETBYT ; GET A BYTE FROM SEG1 + POP DX + POP DI + POP SI + ADD DX,CX ; SUM IT + CMP AX,SI + JNE OPVR1 + CMP BX,DI + JNE OPVR1 + MOV AX,ES:[PCHKSM] ; REMOVED SEG OVERRIDE + XCHG AH,AL + POP ENDLOD + POP DI + POP SI +; CALL TBLINI ; (7n) RESET THE TABLE YET AGAIN +OPVR4: CMP AX,DX + JE OPVR2 + JMP PFALSE +OPVR2: JMP PTRUE +; +; VERIFY FOR FITS==1 OR ALL OF GAME IS IN MEMORY +; +OPVR2$: PUSH SI + PUSH DI + PUSH CX + PUSH DS ; (6) ADDRESS SEGMENT 1 + MOV BX,GAMHNDL ; (6) READ FROM GAME FILE + MOV SI,GAMESEG ; (6) THROUGH DS + MOV DS,SI ; (6) SO THAT WE OVERLAY GAME + MOV CX,0 ; (6) MOVE FILE PTR TO BEGINNING + MOV DX,64 ; (6) SKIP FIRST 64 BYTES + MOV AL,0 ; (6) METHOD OF SEEKING + MOV AH,CFSEEK ; (6) SEEK FUNCTION + INT 21H ; (6) DO IT + MOV CX,03FC0H ; (7n) READ 16K AT A TIME + MOV DX,0C000H ; (6) OFFSET INTO SEGMENT + MOV AH,CRDRNDZ ; (6) READ FUNCTION + INT 21H ; (6) DO IT + CMP AX,CX ; (6) DID WE GET IT ALL + JNE OPVR5 ; (6) DIE PAINFULLY + XOR DX,DX ; (7n) ZERO THE CHECKSUM + CALL CHKSUM ; (6) DO A CHKSUM +; +OPVR6: MOV DI,DX ; (7n) SAVE CHECK SUM + MOV DX,0C000H ; (7n) BUFFER SPACE + MOV CX,4000H ; (7n) READ 16K EACH TIME + MOV AH,CRDRNDZ ; (7n) DO A RANDOM READ + INT 21H ; (7n) DO IT + CMP AX,CX ; (7n) LAST READ? + JNE OPVR8 + MOV DX,DI ; (7n) RESTORE CHECKSUM + CALL CHKSUM + JMP OPVR6 +OPVR8: MOV AX,ES:[PLENTH] ; (7n) GET FILE LENGTH IN WORDS + XCHG AH,AL ; (7n) INTO AX + MOV DX,0 ; (7n) ZERO THIS FOR DIVIDE + MOV CX,2000H ; (7n) DIVIDE BY NUMBER OF BYTES/2 + DIV CX ; (7n) TO GET REMAINDER + SHL DX,1 ; (7n) MULT BY 2 TO GET BYTES + MOV AX,DX ; (7n) DX SHOULD HAVE REM BYTES + MOV DX,DI ; (7n) RESTORE CHECKSUM + CALL CHKSUM +; + PUSH DX + MOV CX,0 ; (7n) SEEK TO 48K INTO FILE + MOV DX,0C000H ; (7n) TO GET OVERWRITTEN PART + MOV AH,CFSEEK ; (7n) FUNCTION IS SEEK + MOV AL,0 ; (7n) TO OFFSET FROM BEGINNING + INT 21H ; (7n) DO IT + MOV DX,0C000H ; (7n) NOW REFILL SEG WITH ORIG + MOV CX,4000H ; (7n) READ 16K IN + MOV AH,CRDRNDZ ; (7n) FUNCTION READ + INT 21H + POP DX + + POP DS ; (6) RESTORES + POP CX + POP DI + POP SI + MOV AX,ES:[PCHKSM] ; (6) GET CHKSUM + XCHG AH,AL + JMP OPVR4 +; +CHKSUM: MOV CX,AX ; (7n) GET NUMBER ACTUALLY READ + XOR AX,AX ; (6) ZERO THIS + MOV SI,0C000H ; (7n) 48K INTO THE BUFFER +OPVR3: LODSB ; (6) GET A BYTE + ADD DX,AX ; (6) ADD IT ALL UP + LOOP OPVR3 + RET +; +OPVR5: FATAL FTL7 ; GAME FILE READ ERROR +OPVERI ENDP + +; +; SAVE AND RESTORE HAVE BEEN MODIFIED TO USE DOS 2.0 FILE NAMES. THIS +; ALLOWS THE USER TO SAVE AND RESTORE TO ANY DISK DRIVE AND ANY SUBDIRECTORY. +; FILE NAMES ARE READ FROM THE CONSOLE AND TRANSFERRED INTO THE SAVFILE +; VARIABLE WITH NO PARSING OTHER THAN A CHECK FOR A DISK DRIVE SPECIFIER. +; IF THE NAME IS TYPED INCORRECTLY, THEN DOS RETURNS AN ERROR WHICH WE +; REPORT ACCORDINGLY. + +; +; RESTORE +; + PUBLIC OPREST +OPREST PROC + MOV DSKDIR,0 ;INDICATE RESTORE (READ) + JMP OSV0$ +OPREST ENDP + +; +; SAVE +; + PUBLIC OPSAVE +OPSAVE PROC + MOV DSKDIR,1 ;INDICATE SAVE (WRITE) + +; +;COMMON ENTRYPOINT FOR SAVE AND RESTORE +; + PUBLIC OSV0$,OSVD1,OSVD2,OSVD3,OSVD4A,OSVPSX,OSVOPW + PUBLIC OSVOPDF,OSVPS,OSVT0,OSV4X,OSV4Y +; PUBLIC OSVCC,OSV1C,OSV2C + PUBLIC OSV4,OSVPRR +; DO A DISK RESET IN CASE THEY WANT TO CHANGE DISKS +; UNFORTUNATELY WE HAVE TO ASSUME A 1 DRIVE SYSTEM AT THIS POINT + +OSV0$: CMP FITS,1 ; (n) ARE WE ALL THERE + JZ OSV0A ; (n) YES, NO CLOSE + MOV AH,CFCLOSZ ; (7s) CLOSE THE GAME FILE + MOV BX,GAMHNDL ; (7s) FOR REINSERTION + INT 21H + MOV AH,CDRESET ; (K6) WILL RESET FLUSH BUFFERS? + INT 21H ; (K6) HOPE SO... + +; PRINT "FILENAME (DEFAULT IS drv:filename.ext):" + +; PRINT "FILENAME (DEFAULT IS drv:" +OSV0A: PRINT SAV0 ;PRINT "INSERT SAVE DISK THEN ENTER FILE NAME." + PRINT SAV1 ;PRINT "FILE NAME (DEFAULT IS " + TEST DRVFLG,1 ; HAS USER SPECIFIED A DRIVE + JNZ OSVD1 ; YES, USE USER DEFAULT DRIVE + MOV AL,CURDRV ;AL <= DRIVE NO. + ADD AL,65 ;....NO. ADD 65 TO GET ASCII CHARACTER + CALL MTTYO ;PRINT DRIVE B, C, OR D + MOV AL,":" ;PRINT ":" + CALL MTTYO + +; PRINT "filename" +OSVD1: PUSH SI ; (6) SAVE THIS + MOV SI,OFFSET SAVFILE ; (6) POINTER TO SAVE FILENAME (6) + MOV CX,SI ; (6) SAVE POINTER + CLD ; (6) SET DIR INCREMENT +OSVD2: LODSB ; (6) GET A BYTE INTO AL + TEST AL,AL ; (6) CHECK IF NULL + JZ OSVD3 ; (6) EXIT THIS LOOP + CALL MTTYO ; (6) OUTPUT IT + JMP OSVD2 +OSVD3: SUB SI,CX ; (6) CALCULATE NUMBER OF CHARS + MOV CX,SI ; (6) GET NUMBER BACK INTO CX + POP SI ; (6) RESTORE THIS + +; PRINT " ): " + PRINT SAV2 ;PRINT " ): " + CMP SCPL,50 ;ARE MAX CHARS/LINE >50? + JG OSVD4A ;....YES + CALL MCRLF ;....NO. PRINT A + +; GET LOSER'S SAVE FILENAME FROM THE KEYBOARD +OSVD4A: MOV BX,OFFSET INBUF ;^ KEYBOARD INPUT BUFFER + MOV AL,63 ;(6) COULD BE A WHOLE PATH + MOV BYTE PTR [BX],AL ;SET UP BUFFER TO TAKE 15 CHARACTERS + MOV DX,BX ;DX ^ BUFFER + MOV AH,CRDLIN ;READ A LINE FROM THE KEYBOARD + INT 21H + +; PARSE THE FILENAME + + CALL SAVESAV ; (7o) PRESERVE THE SAVE NAME + PUSH SI + PUSH DI + PUSH CX ; SAVE THIS + PUSH ES + PUSH DS + POP ES + LEA SI,INBUF[1] ; POINT TO NUM CHARS READ + LODSB ; GET NUM + TEST AL,AL ; ANY CHARS READ + JZ LOOK + MOV CL,AL ; STORE IT + XOR CH,CH ; CLEAR TOP HALF OF COUNTER + MOV DI,OFFSET SAVFILE ; (6) DI ^FCB + REPZ MOVSB ; TRANSFER THE STRING IF ANY + MOV AL,0 ; (6) GET A NULL + STOSB ; (6) DROP IT IN AT END OF STRING +LOOK: TEST SCRFLG,1 ; (7p) IS SCRIPTING ON? + JZ NOSCR ; (7p) NO SCRIPTING + CALL SCRSAVE ; (7p) SCRIPT THE SAVE FILE NAME +NOSCR: MOV SI,OFFSET SAVFILE ; (6) IS THERE A ':' + INC SI + LODSB ; (6) CHECK IT + CMP AL,':' ; (6) IF SO, FIX DEFDRV + JNZ NODRV ; (6) NOPE... + MOV DRVFLG,1 ; (6) SET FLAG + MOV AL,SAVFILE ; (7n) GET DRIVE LETTER + AND AL,5FH ; (7n) UPPERCASIFY + SUB AL,'A' ; (7n) BASIFY + CMP AL,CURDRV ; (7n) DON'T CHANGE IF UNNECESSARY + JZ DRV + MOV DL,AL ; (7n) SET UP FOR CHGDSK + MOV AH,CSELDSK ; (7n) SELECT DISK IN DL + INT 21H + MOV AH,CURDSK ; (7n) CHECK IF IT WORKED + INT 21H + MOV CURDRV,AL ; (7n) SAVE IT + JMP DRV +USEDEF: MOV SKPDRV,1 ; (7n) DON'T OUTPUT A DRIVE +NODRV: MOV DRVFLG,0 +DRV: POP ES + POP CX + POP DI ;RESTORE'M + POP SI + CALL MCRLF ; (7) SCROLL PROPERLY + +; OPEN THE FILE IF OP RESTORE + + CMP DSKDIR,1 ;OP SAVE? + JE OSVOPW ;....YES + MOV DX,OFFSET SAVFILE ; 6) ....NO. OP RESTORE. DX ^ FCB + MOV AH,CFOPENZ ; (6) SELECT DOS OPEN FUNCTION + MOV AL,0 ; (6) FILE OPEN FOR READING + INT 21H ;OPEN THE FILE + JC OSVPSX ; (6) ....NO. FILE NOT FOUND + JMP OSVPS ;....YES +; +; **** ERROR **** [File Not Found] +; +OSVPSX: MOV AX,OFFSET ERR1 ;^ "SAVE FILE NOT FOUND" MSG + JMP OSVPER ;ERROR EXIT + +; CREATE THE FILE IF OP SAVE +OSVOPW: MOV DX,OFFSET SAVFILE ; (6) ^ FCB + MOV CX,0 ; (6) NO SPECIAL ATTRIBUTE + MOV AH,CFCREAZ ; (6) SELECT DOS CREATE FUNCTION + INT 21H + JC OSVOPDF + JMP OSVPS ;....YES +; +; **** ERROR **** [Directory Full] +; +OSVOPDF:MOV AX,OFFSET ERR4 ;....NO. ^ "NO ROOM IN DIRECTORY" MSG + JMP OSVPER ;HOP TO ERROR EXIT +; +; WE'VE GOT AN OPEN FILE (WHICH WE CREATED IF IT WAS A SAVE FUNCTION) +; AND ARE READY TO EITHER READ (RESTORE) OR WRITE (SAVE) AS REQUIRED +; +; THE BELOW CODE GRIMLY EXPLAINS THE FORMAT OF A SAVE FILE. BASICALLY, +; FROM WHAT I CAN TELL, THE LOCALS AND VITALS ARE PUSHED ONTO THE ZSTACK +; AS WELL AS THE ZPC AND THE ZSTACK POINTER. THIS INFORMATION IS FIRST +; WRITTEN TO DISK. THEN THE REST OF PURBOT IS WRITTEN TO DISK. THIS CODE +; ALSO WORKS FOR A RESTORE. SO THE SAVE FILE CONSISTS OF FIRST ZIP INFO +; SAVED ON DISK FOLLOWED BY THE IMPURE PART OF THE GAME CODE. +; +OSVPS: XCHG DI,SP + PUSH ZPC1 ; PUSH VITALS ONTO ZSTACK + PUSH ZPC2 + PUSH ZLOCS + PUSH ZORKID + + + SUB SP,OFFSET STKBOT ; (7v) RELATIVISE THE POINTER + MOV STKBOT,SP ; PUT DEST. INDEX INTO STACKBOTTOM + MOV SP,DI ; RESTORE SP + + MOV SAVHNDL,AX ; SAVE FILE HANDLE + PUSH ES + + MOV AX,SS ; FLOP STACK SEG AND EXTRA SEG + MOV ES,AX ; ES<=SS + + MOV DX,OFFSET STKBOT ; CORE LOCATION + MOV CX,400H ; (6) DO TRANSFER HERE + MOV BX,SAVHNDL ; (6) GET HANDLE + MOV AH,CRDRNDZ ; SETUP FOR A READ + ADD AH,DSKDIR ; MAKE IT A WRITE IF NECESSARY + INT 21H ; + CMP AX,400H ; DID WE GET IT ALL + PUSHF ;SAVE RETURN CODE + MOV DI,SP ;DI ^ CURRENT ZSTACK POSITION + MOV SP,STKBOT ;SP <= ZSTACK POINTER + ADD SP,OFFSET STKBOT ; (7v) RELATIVISE THIS VALUE + POP AX ; POP OFF AND COMPARE FOR ZORKID + CMP AX,ZORKID ;ID OK? + JE OSVT0 ;....YES + MOV GAMEIN,0 ; (7v) INDICATE THAT THE GAME IS LOST + FATAL FTL4 ;....NO. FATAL ERROR + +OSVT0: POP ZLOCS ;RESTORE LOCALS AND ZIP PROGRAM COUNTERS + POP ZPC2 + POP ZPC1 + + XCHG DI,SP ;RESTORE MACHINE SP AND ZSTACK POINTER + POPF ;RESTORE REGS + POP ES + JNE OSV4Y ;TRANSFER WAS UNSUCCESSFUL +; +; THE OPEN/CREATE FILE WAS SUCCESSFUL, AND SO WAS THE BLOCK TRANSFER +; SO TRANSFER THE REST +; +OSV4X: MOV CX,ES:[PPURBT] ; (K3) MAYBE THIS IS WRONG + XCHG CH,CL ; (K3) XCHANGE BYTES + MOV AH,CRDRNDZ ; (K1) FUNCTION IS READ (OR WRITE) + ADD AH,DSKDIR ; (K1) ADD IN WRITE STUFF + MOV BX,SAVHNDL ; (K1) READ IT FROM HERE + MOV DX,0 ; (K1) READ IT RIGHT IN TO SEG0 + PUSH DS ; (K1) SAVE DS + PUSH ES ; (K1) FLOP BYTES + POP DS ; (K1) ES IS NOW DOS ADDRESSIBLE + INT 21H ; (K1) DO THE SAVE/RESTORE + POP DS ; (K1) RESTORE DS + CMP AX,CX ; (K1) DID WE GET IT ALL? +OSV4Y: PUSHF ;SAVE DOS RETURN CODE + MOV AH,CFCLOSZ ; (6) CLOSE THE FILE + MOV BX,SAVHNDL ; (6) WITH THIS HANDLE + INT 21H + POPF ;RESTORE DOS RETURN CODE + JNE OSV4 ;ERROR EXIT +; +;ELSE EVERYTHING WORKED SUCCESSFULLY +;AND WE CAN GO BACK TO WHAT WE WERE +;DOING.......... +; + MOV AH,SCRFLG ; (J2) FIX SCRFLG + XOR AL,AL ; (J2) + MOV WORD PTR ES:[PFLAGS],AX ; (J1) SCRIPT SHOULD MATCH SCRFLG + CMP FITS,1 ;(n) do not need to replace disk if in mem + JZ n1 + CALL GAMOPEN ; (7s) OPEN GAME FILE + MOV DL,CURDRV ; (7n) RETURN TO SAVE DISK + MOV AH,CSELDSK ; (7n) AND SELECT IT FOR OPEN + INT 21H +N1: CALL NEWZPC ;GET A NEW PC + JMP PTRUE +; +; **** ERROR **** [Unable to Read File] +; +OSV4: MOV AX,OFFSET ERR6 ;^ "Read of SAVE file failed." + CMP DSKDIR,1 ;OP SAVE? + JNE OSVPRR ;....NO + MOV AH,CFCLOSZ ; (6) ....YES. CLOSE IT + MOV BX,SAVHNDL ; (6) GET HANDLE FOR CLOSE + INT 21H +; +; **** ERROR **** [Diskette Full] +; + MOV DX,OFFSET SAVFILE ; (7n) DELETE THE PIECE OF A FILE + MOV AH,CFDELEZ ; (7n) SO AS NOT TO CONFUSE + INT 21H + MOV AX,OFFSET ERR5 ;^ "No room on diskette for SAVE file." +OSVPRR: JMP OSVPER +OPSAVE ENDP +; +; ERROR EXIT R/W operations +; +OSVPER PROC + CALL MPRNT ;PRINT ERROR MESSAGE + CALL ZRESTOR ; (7o) RESTORE OLD SAVE NAME + CMP FITS,1 ; (7v) HAVE WE CLOSED THE GAME FILE + JZ OSVPR1 ; (7v) SKIP REOPEN + CALL GAMOPEN ; (7v) OPEN IT +OSVPR1: MOV AL,SCRFLG ;REENABLE SCRIPTING + XCHG AH,AL + XOR AL,AL ; (J1) FIX SCRIPT ON BAD RESTART (RANDOM) + MOV ES:[PFLAGS],AX + JMP PFALSE +OSVPER ENDP +; + PUBLIC SAVESAV,ZRESTOR,SCRSAVE +SCRSAVE PROC + PUSH AX ; (7p) SAVES + PUSH SI + PUSH DX + MOV SI,OFFSET SAVFILE ; (7p) POINTER TO SAVE +SCRS0: LODSB ; (7p) GET A CHARACTER + TEST AL,AL ; (7p) LOOK FOR A NULL + JNZ SCRS1 ; (7p) DIE ON A NULL + POP DX + POP SI + POP AX + RET ; (7p) RETURN +SCRS1: MOV DL,AL ; (7p) GET CHARACTER INTO DL + MOV AH,CPROUT ; (7p) FOR DOS"IE" OUTPUT + INT 21H ; (7p) PRINT IT + JMP SCRS0 +SCRSAVE ENDP + +SAVESAV PROC + PUSH DI ; (7o) SAVES + PUSH SI + PUSH AX + PUSH ES + MOV AX,DS ; (7o) SET UP REGS + MOV ES,AX + MOV AL,CURDRV ; (7o) SAVE CURRENT DRIVE SPEC + MOV LASTDRV,AL ; (7o) IN CASE OF FAILURE + MOV AL,DRVFLG ; (7o) TEST DRIVE FLAG + MOV LSTDFLG,AL ; (7o) IN CASE OF FAILURE + MOV SI,OFFSET SAVFILE ; (7o) SETUP SOURCE AND DESTINATION + MOV DI,OFFSET LASTSAV +COPYLP: LODSB ; (7o) GET A BYTE + STOSB ; (7o) STORE A BYTE + TEST AL,AL ; (7o) STOP ON A NUL + JNZ COPYLP ; (7o) CONTINUE THE COPY + POP ES + POP AX ; (7o) RESTORES + POP SI + POP DI + RET +SAVESAV ENDP +; +; +ZRESTOR PROC + PUSH DI ; (7o) SAVES + PUSH SI + PUSH AX + PUSH ES + MOV AX,DS ; (7o) SET UP REGS + MOV ES,AX + MOV AL,LSTDFLG ; (7o) GET LAST DRIVE FLAG + MOV DRVFLG,AL ; (7o) AND RESTORE IT + MOV AL,LASTDRV ; (7o) GET ORIGINAL DRIVE SPEC + CMP AL,CURDRV ; (7o) HAS IT CHANGED + JZ ZRES1 + MOV DL,AL ; (7o) SELECT DISK + MOV AH,CSELDSK ; (7o) TO CORRECT + INT 21H + MOV CURDRV,DL ; (7o) UPDATE THIS BABY +ZRES1: MOV DI,OFFSET SAVFILE ; (7o) SETUP SOURCE AND DESTINATION + MOV SI,OFFSET LASTSAV +ZRESLP: LODSB ; (7o) GET A BYTE + STOSB ; (7o) STORE A BYTE + TEST AL,AL ; (7o) STOP ON A NUL + JNZ ZRESLP ; (7o) CONTINUE THE COPY + POP ES + POP AX ; (7o) RESTORES + POP SI + POP DI + RET +ZRESTOR ENDP +; +; OP RESTART +; + PUBLIC OPRSTT +OPRSTT PROC + MOV BP,CHRPTR + MOV BYTE PTR DS:[BP],0 ;FORCE OUT THE BUFFER + PRINT OUTBUF + JMP RESTRT ;JUMP TO RESTART ADDRESS +OPRSTT ENDP + + PUBLIC OPQUIT +OPQUIT PROC + JMP FINISH +OPQUIT ENDP + +; THIS OPCODE IS A PSEUDO-OP. IT IS NEVER CALLED BY THE GAME BUT INSTEAD +; BY OPREAD. IT IS HEAVILY TIED TO THE STATUS LINE DATA STRUCTURES. + PUBLIC OPUSL +OPUSL PROC + CMP SLFLG,0 + JNE OPUSL1 + RET +OPUSL1: PUSH DI + PUSH CHRPTR + MOV BX,SLSTR + MOV CHRPTR,BX + MOV AX,16 + MOV DI,SLTAB + MOV CX,3 +USLLP: PUSH AX + CALL GETVAR + MOV DX,[DI+4] + CALL USLSET + PUSH CX + PUSH DI + CALL WORD PTR [DI+2] + POP DI + MOV DX,[DI+6] + CALL USLSPC +USLN: ADD DI,8 + POP CX +USL1: POP AX + INC AX + LOOP USLLP + MOV AX,"$" + CALL PUTCHR + CALL MSOUT + POP CHRPTR + POP DI + RET + +USLSET: MOV BX,SLSTR + MOV CHRPTR,BX + ADD CHRPTR,DX + RET + +USLSPC: MOV CX,CHRPTR + SUB CX,SLSTR + SUB DX,CX + MOV CX,DX + JLE USLSP1 +USLSPL: MOV AX,20H + CALL PUTCHR + LOOP USLSPL +USLSP1: RET +OPUSL ENDP + + SUBTTL ARITHMETIC OPERATIONS + PAGE + + + PUBLIC OPADD,OPSUB,OPMUL,OPDIV,OPMOD + ;ADD +OPADD PROC + ADD AX,BX ;ADD OPR1 AND OPR2 + JMP PUTVAL ;RETURN THE VALUE +OPADD ENDP + + ;SUB +OPSUB PROC + SUB AX,BX ;SUBTRACT OPR2 FROM OPR1 + JMP PUTVAL ;RETURN THE VALUE +OPSUB ENDP + + ;MULTIPLY AX BY BX +OPMUL PROC + IMUL BX ;MULTIPLY OPR1 BY OPR2,IGNORING OVERFLOW(DX) + JMP PUTVAL ;RETURN THE VALUE +OPMUL ENDP + + ;DIVIDE AX BY BX +OPDIV PROC + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + JMP PUTVAL ;RETURN THE VALUE +OPDIV ENDP + + ;MOD +OPMOD PROC + CWD ;CLEAR HIGH WORD AND EXTEND SIGN FOR DIVIDE + IDIV BX ;DIVIDE OPR1 BY OPR2 + MOV AX,DX ;WE WANT REMAINDER + JMP PUTVAL ;RETURN THE VALUE +OPMOD ENDP + + ;RANDOM BY DAN + PUBLIC OPRAND +OPRAND PROC + SUB AH,AH ; HACK RANDOM TO ONE BYTE + MOV RTEMP,AX ; SAVE ARGUMENT FOR LATER + MOV AX,RSEED1 + MOV BX,RSEED2 + MOV RSEED2,AX + CLC + RCR AX,1 + RCR BX,1 + XOR RSEED1,BX ;PUT XOR'D NUBMER INTO RSEED1 + MOV AX,RSEED1 ;THIS IS RANDOM VALUE + + AND AX,0EFFFH ;CHOP HIGH BIT FOR DIVIDE + SUB DX,DX ;CLEAR MOST SIGN. PORTION OF 32 BIT WORD + DIV RTEMP ;DIVIDE WORD BY WORD + MOV AX,DX ;MOVE REMAINDER INTO AX + INC AX ;MAKE SURE NO ZERO + JMP PUTVAL +OPRAND ENDP + + ;LESS? + PUBLIC OPQLES,OPQGRT,OPBTST,OPBOR,OPBCOM,OPBAND +OPQLES PROC + CMP AX,BX ;IS OPR1 LESS THAN OPR2? + JL JPT ;YES, PREDICATE TRUE +JPF: JMP PFALSE ;NO, PREDICATE FALSE +JPT: JMP PTRUE +OPQLES ENDP + + ;GRTR? +OPQGRT PROC + CMP AX,BX ;IS OPR1 GREATER THAN OPR2? + JG JPT ;YES, PREDICATE TRUE + JMP JPF ;NO, PREDICATE FALSE +OPQGRT ENDP + + SUBTTL LOGICAL OPERATIONS + PAGE + + + ;BTST +OPBTST PROC + NOT AX ;TURN OFF BITS IN OPR2 THAT ARE ON IN OPR1 + AND BX,AX + JE JPT ;SUCCESS IF OPR2 COMPLETELY CLEARED + JMP JPF +OPBTST ENDP + + ;BOR +OPBOR PROC + OR AX,BX ;LOGICAL OR + JMP PUTVAL ;RETURN THE VALUE +OPBOR ENDP + + ;BCOM +OPBCOM PROC + NOT AX ;LOGICAL COMPLEMENT + JMP PUTVAL ;RETURN THE VALUE +OPBCOM ENDP + + ;BAND +OPBAND PROC + AND AX,BX ;LOGICAL AND + JMP PUTVAL ;RETURN THE VALUE +OPBAND ENDP + + SUBTTL GENERAL PREDICATES + PAGE + + + PUBLIC OPQEQU,OPQZER + ;EQUAL? +OPQEQU PROC + NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV BX,ARGBLK ;GET OPR1 + CMP BX,ARGBLK[2] ;IS OPR1 EQUAL TO OPR2? + JE OQE1$ ;YES + CMP AX,3 ;NO, IS THERE A THIRD OPERAND? + JL OQE2$ ;NO + CMP BX,ARGBLK[4] ;YES, IS IT EQUAL TO OPR1? + JE OQE1$ ;YES + CMP AX,4 ;NO, IS THERE A FOURTH? + JL OQE2$ ;NO + CMP BX,ARGBLK[6] ;YES, IS IT EQUAL TO OPR1? + JNE OQE2$ ;NO +OQE1$: JMP PTRUE ;PREDICATE TRUE IF EQUAL +OQE2$: JMP PFALSE ;PREDICATE FALSE IF NOT +OPQEQU ENDP + + ;ZERO? +OPQZER PROC + CMP AX,0 ;IS OPR ZERO? + JNE OQZ1$ ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQZ1$: JMP PFALSE +OPQZER ENDP + + SUBTTL OBJECT OPERATIONS + PAGE + + + PUBLIC OPMOVE,OPREMO,OPQFSE,OPFSET + ;MOVE (OBJ1 INTO OBJ2) +OPMOVE PROC + PUSH AX ;PROTECT OPRS FROM REMOVE CALL + PUSH BX + CALL OPREMO ;REMOVE OBJ1 FROM WHEREVER IT IS + POP DX ;OBJ2 + MOV AX,DX + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + POP CX ;OBJ1 + MOV AX,CX + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV ES:[BP].PARENT,DL ; PUT OBJ2 INTO OBJ1'S LOC SLOT + MOV DH,ES:[BX].CHILD1 ; GET CONTENTS OF OBJ2'S FIRST SLOT + MOV ES:[BX].CHILD1,CL ; MAKE OBJ1 FIRST CONTENT OF OBJ2 + CMP DH,0 ;WERE THERE ANY OTHER CONTENTS? + JE OMV1$ ;NO + MOV ES:[BP].SIBLING,DH ; YES, CHAIN ONTO OBJ1'S SIBLING SLOT +OMV1$: RET +OPMOVE ENDP + + ;REMOVE (OBJ FROM ITS PARENT) +OPREMO PROC + MOV CX,AX ;SAVE OBJ FOR LATER + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + MOV CH,ES:[BX].PARENT ; GET ITS PARENT + CMP CH,0 ;DOES IT HAVE A PARENT? + JE ORM3$ ;IF NOT, WE'RE DONE + MOV AL,CH ;PARENT + CALL OBJLOC ;FIND PARENT'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:[BP].CHILD1 ; GET PARENT'S FIRST CONTENT + CMP DL,CL ;IS IT OBJ? + JNE ORM1$ ;NO + MOVM ES:[BP].CHILD1,ES:[BX].SIBLING,AL ;YES, CHANGE SLOT TO + ;OBJ'S SIBLING + JMP ORM2$ ;AND RETURN +ORM1$: MOV AL,DL ;CURRENT SIBLING + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + MOV DL,ES:[BP].SIBLING ;GET NEXT SIBLING IN CHAIN + CMP DL,CL ;IS IT OBJ? + JNE ORM1$ ;NO, CONTINUE LOOP + MOVM ES:[BP].SIBLING,ES:[BX].SIBLING,AL ;YES, CHANGE IT TO + ;OBJ'S SIBLING +ORM2$: MOV ES:[BX].PARENT,0 ;OBJ NOW HAS NO PARENT + MOV ES:[BX].SIBLING,0 ;OR SIBLING +ORM3$: RET +OPREMO ENDP + + ;FSET? (IS FLAG SET IN OBJ?) +OPQFSE PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OQF1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OQF1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + TEST AX,DX ;IS THIS BIT SET IN FLAG WORD? + JE OQF2$ ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQF2$: JMP PFALSE +OPQFSE ENDP + + ;FSET (SET A FLAG IN OBJ) +OPFSET PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFS1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFS1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + OR AX,DX ;SET THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + RET +OPFSET ENDP + + PUBLIC OPFCLE,OPLOC,OPQFIR,OPQNEX,OPQIN + ;FCLEAR (CLEAR A FLAG IN OBJ) +OPFCLE PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,16 ;SECOND WORD FLAG? + JL OFC1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFC1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,7FFFH ;SHIFT A BIT TO PROPER POSITION + ROR DX,CL + AND AX,DX ;CLEAR THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + RET +OPFCLE ENDP + + ;LOC (RETURN CONTAINER OF OBJ) +OPLOC PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].PARENT ; GET LOC SLOT + JMP BYTVAL ;RETURN THE BYTE VALUE +OPLOC ENDP + + ;FIRST? (RETURN FIRST SLOT OF OBJ, FAIL IF NONE) +OPQFIR PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].CHILD1 ; GET FIRST SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE +JPT1: JMP PTRUE ;NO, PREDICATE TRUE +JPF1: JMP PFALSE +OPQFIR ENDP + + ;NEXT? (RETURN THE NEXT (SIBLING) SLOT OF OBJ, FAIL IF NONE) +OPQNEX PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + MOV AL,ES:[BX].SIBLING ; GET SIBLING SLOT + PUSH AX ;SAVE IT + CALL BYTVAL ;RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AL,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE + JMP JPT1 ;NO, PREDICATE TRUE +OPQNEX ENDP + + ;IN? (IS OBJ1 CONTAINED IN OBJ2?) +OPQIN PROC + CALL OBJLOC ;FIND OBJ1'S LOCATION + XCHG AX,BX ;MOVE TO BASE + CMP ES:[BX].PARENT,AL ; IS OBJ1'S PARENT OBJ2? + JE JPT1 ;YES, PREDICATE TRUE + JMP JPF1 ;NO, PREDICATE FALSE +OPQIN ENDP + + PUBLIC OPGETP + ;GETP (GET SPECIFIED PROPERTY OF OBJ, DEFAULT IF NONE) +OPGETP PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ; LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGP2$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JL OGP3$ ;IF LESS, NO SUCH PROPERTY HERE + MOV AL,ES:[BX] ;GOT IT, NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,MASK PROPSIZE;GET LENGTH BITS + MOV CL,PROPSIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + JNE OGP5$ ;NO + MOV AL,ES:[BX] ;GET THE BYTE + JMP BYTVAL ;AND RETURN IT +OGP3$: DEC DX ;POINT INTO DEFAULT PROPERTY TABLE + SHL DX,1 + MOV BX,DX +OGP4$: ADD BX,OBJTAB ;GET THE WORD +OGP5$: GTAWRD A,[BX] + JMP PUTVAL ;AND RETURN IT +OPGETP ENDP + + ;PUTP (CHANGE VALUE OF A PROPERTY, ERROR IF BAD NUMBER) + PUBLIC OPPUTP,OPP2$ +OPPUTP PROC + PUSH CX ;SAVE NEW VALUE + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ; LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OPP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OPP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OPP2$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE OPP3$ ;IF EQUAL, GOT IT + JG OPP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR +OPP3$: MOV AL,ES:[BX] ;NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,MASK PROPSIZE;GET LENGTH BITS + MOV CL,PROPSIZE + SHR AL,CL + CMP AL,0 ;BYTE VALUE? + POP AX ;RESTORE NEW VALUE + JNE OPP4$ ;ZERO MEANS BYTE VALUE + MOV ES:[BX],AL ;STORE THE NEW BYTE + RET ;AND RETURN +OPP4$: PTAWRD [BX],A ;STORE THE NEW WORD VALUE + RET +OPPUTP ENDP + + ;NEXTP (RETURN NUMBER OF NEXT PROP FOLLOWING GIVEN PROB IN OBJ) + PUBLIC OPNEXT,ONX2$ +OPNEXT PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET ITS LOCATION + MOV AL,ES:[BX] ; LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + CMP DX,0 ;WERE WE GIVEN ZERO AS PROP? + JE ONX4$ ;YES, GO RETURN FIRST PROPERTY NUMBER + JMP ONX2$ ;NO, SKIP NEXT LINE FIRST TIME THROUGH LOOP +ONX1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX2$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE ONX3$ ;IF EQUAL, GOT IT + JG ONX1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR +ONX3$: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX4$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;EXTRACT PROPERTY NUMBER + JMP PUTVAL ;AND RETURN IT +OPNEXT ENDP + + SUBTTL TABLE OPERATIONS + PAGE + + + PUBLIC OPGET,OPGETB,OPPUT,OPGTPT + ;GET (GET THE ITEM'TH WORD FROM TABLE) +OPGET PROC + SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETWRD ;GET THE WORD + MOV AX,CX + JMP PUTVAL ;AND RETURN IT +OPGET ENDP + + ;GETB (GET THE ITEM'TH BYTE FROM TABLE) +OPGETB PROC + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETBYT ;GET THE BYTE + MOV AX,CX + JMP BYTVAL ;AND RETURN IT +OPGETB ENDP + + ;PUT (REPLACE THE ITEM'TH WORD IN TABLE) +OPPUT PROC + SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD BX,AX ;INDEX INTO TABLE + PTAWRD [BX],C ;STORE THE WORD + RET +OPPUT ENDP + + ;PUTB (REPLACE ITEM'TH BYTE IN TABLE) +OPPUTB PROC + ADD BX,AX ;INDEX INTO TABLE + MOV ES:[BX],CL ; STORE BYTE + RET +OPPUTB ENDP + + ;GETPT (GET POINTER TO PROPERTY TABLE FOR GIVEN PROP) +OPGTPT PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + SUB AH,AH ;CLEAN OFF ANY HIGH-ORDER BYTE + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ;ALSO SKIP LENGTH BYTE + JMP OGT2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGT1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGT2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGT1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JE OGT3$ ;FOUND THE PROPERTY + SUB AX,AX ;RETURN ZERO FOR NO SUCH PROPERTY + JMP OGT4$ +OGT3$: INC BX ;POINT TO PROPERTY VALUE + MOV AX,BX ;AND RETURN IT +OGT4$: JMP PUTVAL +OPGTPT ENDP + + PUBLIC OPPTSI + ;PTSIZE (RETURN SIZE OF PROPERTY TABLE) +OPPTSI PROC + MOV BX,AX ;TABLE POINTER + MOV AL,ES:[BX-1] ;GET PROPERTY INDENTIFIER + AND AL,MASK PROPSIZE;EXTRACT LENGTH BITS + SUB AH,AH + MOV CL,PROPSIZE + SHR AX,CL + INC AX ;ADJUST TO ACTUAL LENGTH + JMP PUTVAL ;RETURN IT +OPPTSI ENDP + + SUBTTL VARIABLE OPERATIONS + PAGE + + + PUBLIC OPVALU,OPSET,OPPUSH,OPPOP + ;VALUE (GET VALUE OF VAR) +OPVALU PROC + CALL GETVAR ;GET THE VALUE + JMP PUTVAL ;AND RETURN IT +OPVALU ENDP + + ;SET (VAR TO VALUE) +OPSET PROC + JMP PUTVAR ;STORE THE VALUE +OPSET ENDP + + ;PUSH (A VALUE ONTO THE STACK) +OPPUSH PROC + PUSHZ AX ;PUSH THE VALUE + RET +OPPUSH ENDP + + ;POP (A VALUE OFF THE STACK INTO VAR) +OPPOP PROC + POPZ BX ;POP A VALUE + JMP PUTVAR ;AND STORE IT +OPPOP ENDP + + PUBLIC OPINC,OPDEC + ;INC (INCREMENT VAR) +OPINC PROC + MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT +OPINC1: MOV BX,AX ;VALUE + MOV AX,CX ;VARIABLE + JMP PUTVAR ;STORE NEW VALUE +OPINC ENDP + + ;DEC (DECREMENT VAR) +OPDEC PROC + MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + JMP OPINC1 ;STORE NEW VALUE +OPDEC ENDP + + PUBLIC OPQIGR,OPQDLE + ;IGRTR? (INCREMENT VAR & TEST IF GREATER THAN VAL) +OPQIGR PROC + PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE GREATER THAN VAL? + JLE OPQIG1 ;NO +OPQIG0: INC CX ;YES, CHANGE FLAG TO TRUE +OPQIG1: MOV BX,AX ;VALUE + POP AX ;RESTORE VARIABLE + CALL PUTVAR ;STORE NEW VALUE + CMP CX,0 ;TEST FLAG + JE OQI1$ ;FALSE, PREDICATE FALSE + JMP PTRUE ;ELSE, PREDICATE TRUE +OQI1$: JMP PFALSE +OPQIGR ENDP + + ;DLESS? (DECREMENT VAR & TEST IF LESS THAN VAL) +OPQDLE PROC + PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE LESS THAN VAL? + JGE OPQIG1 ;NO, PREDICATE FALSE + JMP OPQIG0 ;YES, PREDICATE TRUE +OPQDLE ENDP + + SUBTTL I/O OPERATIONS + PAGE + + PUBLIC GETLIN,GETLLP,GETLLC,GETLEM +GETLIN PROC + PUSH BX + MOV SCRHLD,1 ; (7n) HOLD SCRIPTING + PUSH SI + MOV CL,ES:[SI] + MOV BX,OFFSET INBUF + MOV BYTE PTR [BX],CL + CMP CL,MAXLIN ; (7r) DON'T EXCEED BUFFER LENGTH + JBE GTLN0 ; (7r) FIX IF ABOVE + MOV BYTE PTR [BX],MAXLIN ; (7r) WITH OUR NEW MAXIMUM +GTLN0: MOV DX,BX + MOV AH,CRDLIN + INT 21H + TEST SCROLL,1 ;(7) WHAT KIND OF SCROLLING + JNZ GTLN1 + MOV AH,SCROLLUP ;(7) USE A VIDEO BIOS SCROLL + MOV AL,1 ;(7) ONLY 1 LINE + MOV CX,TOPLIN ;(7) ALWAYS FREEZE TOP LINE + MOV DH,SLPP ;(7) GET SCREEN LENGTH + MOV DL,SCPL ;(7) GET THE WIDTH OF THE SCREEN + DEC DL ; (7v) COORDINATES ARE ZERO BASED + MOV BH,SCRATR ;(7) GET THE SCREEN ATTRIBUTE + INT 10H ;(7) CALL THE VIDEO + JMP GTLN2 ;(7) SKIP LINE FEED OUTPUT +GTLN1: MOV AH,CCONIO + MOV DL,10 + INT 21H +GTLN2: POP DX + MOV BX,OFFSET INBUF + MOV CL,BYTE PTR [BX+1] + SUB CH,CH + INC BX + CMP CL,0 + JE GETLEM +GETLLP: INC SI + INC BX + MOV AL,BYTE PTR [BX] + CMP AL,"A" + JL GETLLC + CMP AL,"Z" + JG GETLLC + ADD AL,32 +GETLLC: MOV ES:[SI],AL + LOOP GETLLP +GETLEM: INC SI + SUB AL,AL + MOV ES:[SI],AL + MOV SCRHLD,0 ; (7n) TURN OFF SCRIPT HOLD + POP BX + RET +GETLIN ENDP + + PUBLIC PRTOUT +PRTOUT PROC + PUSH AX + PUSH BX + PUSH CX + PUSH DX ; (7) SAVE THIS, USING STD PRT + CMP SCROLL,1 ; (7) ARE WE COMPATIBLE + JZ POUT1 ; (7) NO + TEST CMDLIN,16 ; (7n) DO WE WANT IBM PRINTER + JZ POUT1 ; (7n) GUESS NOT +POUT0: MOV AH,0 ; (7) FUNCTION TO PRINT + MOV DX,0 ; (7) TO THE FIRST PRINTER + INT 17H ; (7) TRY IT + TEST AH,RDYBIT ; (7) TIME OUT? + JZ POUT2 ; (7) WORKED, RETURN + CALL PRNRDY ; (7) + JC POUT2 + JMP POUT0 ; (7) RETRY +POUT1: MOV DL,AL ; (7n) GET CHARACTER TO PRINT + MOV AH,CPROUT ; (7n) PRINT IT + INT 21H +POUT2: POP DX ; (7n) FORGET THIS AND BREAK... + POP CX + POP BX + POP AX + RET +PRTOUT ENDP + + PUBLIC PRNRDY,SCRCHK +PRNRDY PROC + PUSH AX + MOV SCRHLD,1 ; (7n) HOLD OFF SCRIPTING + PRINT PRNNRDY ; (7) ASK USER ABOUT ACTION +RDY1: CALL MCHRI ; (7) GET A RESPONSE + CALL MTTYO ; (7u) ECHO THE CHARACTER + AND AL,5FH ; (7) UPPPER CASIFY + CMP AL,'A' ; (7) SHOULD WE ABORT + JNZ RDY2 ; (7) ATTEMPTING RETRY + MOV SCRFLG,0 ; (7) TURN OFF SCRIPTING + AND ES:[PFLAGS],SCRMSK ; (7) AND IN THE MODE WORD + MOV SCRHLD,0 ; (7n) TURN OFF BAN ON SCRIPTING + STC ; (7) SET CARRY FOR NO RETRY + PUSHF ; (7) SAVE THESE + JMP RDY3 ; (7) CR LF ON EXIT +RDY2: CMP AL,'R' ; (7) RETRY??? + JNZ RDY1 ; (7) WRONG CHARACTER + CLC ; (7) CLEAR CARRY FOR RETRY + PUSHF ; (7) SAVE FLAGS +RDY3: CALL MCRLF ; (7) DO A + MOV SCRHLD,0 ; (7n) TURN OFF BAN ON SCRIPTING + POPF ; (7) RESTORE FLAGS AND + POP AX ; (7) CHARACTER TO PRINT + RET +PRNRDY ENDP + +SCRCHK PROC + PUSH AX + PUSH BX + PUSH DX + GTAWRD A,[PFLAGS] + TEST AL,1 ;CHECK IF SCRIPTING IS REQUESTED + JZ SCRNN$ + TEST SCRFLG,1 ; (7) NEW STATE? + JNZ SCR0L$ ; (7x) NO, CONTINUE + MOV SCRFLG,1 ; (7n) TURN ON SCRIPT FLAG + CMP SCROLL,0 ; (7) SHOULD WE BE DOING THIS? + JNZ SCR0L$ ; (7) NOPE... + TEST CMDLIN,16 ; (7n) DID WE REALLY REQUEST IBM + JZ SCR0L$ +SCR_1$: MOV DX,0 ; (7) TRY TO INIT THE PRINTER + MOV AH,1 + INT 17H ; (7) SO THAT WE WILL TIME OUT FAST + TEST AH,PRTMSK ; (7) TEST FOR TIME OUT + JZ SCR0L$ ; (7) NO PROBLEM, WE'RE FINE + CALL PRNRDY ; (7) INFORM USER OF PROBLEM + JNC SCR_1$ + JMP SCRNN$ ; (7) TURN OFF SCRIPTING +SCR0L$: SUB CX,CX + MOV BP,DX + INC BP +SCR1L$: MOV AL,ES:[BP] + INC BP + CMP BP,SI + JLE SCR2L$ + CALL PRTCRL + JMP SCREX$ +SCR2L$: CALL PRTOUT + INC CX + CMP CL,SCPL + JNE SCR1L$ + CALL PRTCRL + JC SCREX$ + SUB CX,CX + JMP SCR1L$ + +SCRNN$: MOV SCRFLG,0 +SCREX$: POP DX + POP BX + POP AX + RET +SCRCHK ENDP + + PUBLIC PRTCRL +PRTCRL PROC + MOV AL,13 ;FINISH UP WITH CRLF + CALL PRTOUT + MOV AL,10 + CALL PRTOUT + RET +PRTCRL ENDP + + ;READ (A LINE OF INPUT & PARSE IT, LINE BUF IN ES:AX, + ;RETURN BUF IN ES:BX) + PUBLIC OPREAD,ORD1$,ORDNS$,ORD8$,ORD9$,ORD10$,ORD1A$,ORD11$,ORD12$ + PUBLIC ORD13$,ORD14$,ORD15$,ORD16$,ORD17$,ORD18$,ORD19$,ORD20$ + PUBLIC ORD21$,ORD22$,ORD23$ +OPREAD PROC + PUSH AX ;SAVE LINE BUF + PUSH AX + PUSH BX + CALL OPUSL ;UPDATE STATUS LINE + POP BX + POP AX + MOV BP,CHRPTR ;NEXT CHARACTER POSITION + MOV BYTE PTR DS:[BP],80H ;(6)DON'T END OUTPUT, IF ANY, WITH NEW LINE +ORD1$: PRINT OUTBUF ;FORCE OUT ANY QUEUED TEXT + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP SI ;INPUT BUFFER POINTER + MOV MORLIN,0 ;RE-INITIALIZE MORE COUNT FROM HERE + CALL GETLIN ;GET SOME CHARACTERS + CALL SCRCHK +ORDNS$: PUSH DI + MOV RDBOS,DX ;INITIALIZE RDBOS + MOV RDEOS,SI ;AND RDEOS + MOV RDRET,BX ;STORE RET POINTER + MOV RDNWDS,0 ;NO WORDS SO FAR + INC DX ;SKIP LENGTH BYTE + MOV DI,BX ;THIS WILL BE WORD ENTRY POINTER + INC DI ;SKIP MAX WORDS & NWORDS BYTES + INC DI +ORD8$: MOV CX,OFFSET RDWSTR;HERE FOR NEXT WORD, POINT TO WORD STRING + MOV BX,DX ;AND SAVE BEGINNING OF WORD POINTER +ORD9$: CMP DX,RDEOS ;END OF STRING? + JNE ORD10$ ;NO + CMP CX,OFFSET RDWSTR;YES, WAS A WORD FOUND? + JNE ORD15$ ;YES, WE STILL HAVE TO LOOKUP WORD + JMP ORD23$ ;NO, WE'RE DONE +ORD10$: MOV BP,DX ;GET NEXT CHARACTER FROM BUFFER + MOV AL,ES:[BP] + CMP AL,"A" + JL ORD1A$ + CMP AL,"Z" + JG ORD1A$ + ADD AL,32 ;LOWERCASIFY ALPHABETICS +ORD1A$: INC DX + MOV SI,OFFSET RBRKS ;LIST OF READ BREAK CHARACTERS +ORD11$: INC SI + CMP AL,[SI-1] ;SEARCH LIST FOR THIS ONE + JE ORD12$ ;FOUND IT + CMP BYTE PTR [SI],0 ;END OF LIST? + JNE ORD11$ ;NO, CONTINUE SEARCH + CMP CX,OFFSET RDWSTR[6] ;YES, NOT A BREAK, WORD STRING FULL? + JE ORD9$ ;YES, LOOP UNTIL END OF WORD + MOV BP,CX ;NO, TACK THIS CHARACTER ONTO STRING + MOV DS:[BP],AL + INC CX + JMP ORD9$ ;AND LOOP +ORD12$: CMP CX,OFFSET RDWSTR;WORD READ BEFORE THIS BREAK? + JNE ORD14$ ;YES + CMP SI,ESIBKS ;NO, BUT IS IT A SELF-INSERTING BREAK? + JBE ORD13$ ;YES + INC BX ;NO, UPDATE BEGINNING OF WORD TO SKIP BREAK + JMP ORD9$ ;AND RETURN TO LOOP TO FIND A WORD +ORD13$: MOV BP,CX ;STORE THE BREAK IN WORD STRING + MOV DS:[BP],AL + INC CX + JMP ORD15$ ;AND GO FOR THE WORD +ORD14$: DEC DX ;UNREAD TERMINATING BREAK IN CASE IT WAS SI +ORD15$: INC RDNWDS ;INCREMENT FOUND WORD COUNT + MOV BP,BX ;GREATER THAN MAX ALLOWED? + MOV BX,RDRET + MOV BL,ES:[BX] + CMP BL,59 ; (7w) GAME FIX + JBE ORD15A ; (7w) FIX NUMBER OF TOKENS ALLOWED + MOV BL,59 ; (7w) OTHERWISE WE OVERRUN A TABLE +ORD15A: CMP RDNWDS,BL + MOV BX,BP + JLE ORD16$ ;NO + PRINT ERR2 ;YES, INFORM LOSER + MOV AX,BX ;BEGINNING OF THIS WORD + MOV BP,RDEOS ;SAVE BYTE AFTER EOS + MOV BL,ES:[BP] + MOV BYTE PTR ES:[BP],0 ; ZERO IT TO MAKE STRING ASCIZ + PUSH BX ; (7w) SAVE THIS ADDRESS + MOV BX,DS ; (7w) FIGURE WHERE STRING IS IN DS + NEG BX ; (7w) SUBTRACT DS FROM ES + ADD BX,GAMESEG ; (7w) BX HAS PARAGRAPHS OF DIFFERENCE + MOV CL,4 ; (7w) CONVERT TO AN OFFSET + SHL BX,CL ; (7w) TO ADD IN WITH AX + ADD AX,BX ; (7w) NOW DS:AX SHOULD EQUAL PREV ES:AX + POP BX ; (7w) RESTORE BX + CALL MPRNT ;PRINT IT + MOV ES:[BP],BL ; AND RESTORE OLD BYTE + DEC RDNWDS ;REMEMBER THAT WE FLUSHED THIS WORD + JMP ORD23$ ;AND WE'RE DONE +ORD16$: MOV AX,BX ;CALCULATE NUMBER OF CHARACTERS IN WORD + NEG AX + ADD AX,DX + MOV ES:[DI+2],AL ;(6)SAVE THE NUMBER IN RET TABLE + SUB BX,RDBOS ;BYTE OFFSET FOR BEGINNING OF WORD + MOV ES:[DI+3],BL ;(6)STORE IT, TOO + MOV BP,CX ;MAKE WORD STRING ASCIZ + MOV BYTE PTR DS:[BP],0 ;(6) REMOVED SEG OVERRIDE (DS) + MOV AX,OFFSET RDWSTR;POINT TO IT + CALL ZWORD ;AND CONVERT TO (2-WORD) ZWORD + PUSH DX ;SAVE CHAR & WORD ENTRY POINTERS + PUSH DI + MOV DI,AX ;FIRST ZWORD WORD + MOV SI,VWORDS ;NUMBER OF VOCABULARY WORDS + MOV AX,SI + DEC AX ;WE WANT TO POINT TO LAST WORD + MUL VWLEN ;MULTIPLY BY WORD LENGTH IN BYTES + ADD AX,VOCBEG ;ADD POINTER TO BEGINNING TO FIND LAST WORD + MOV CX,AX ;POINTER TO LAST WORD + MOV DX,DI ;FIRST ZWORD WORD + MOV DI,BX ;SECOND ZWORD WORD + MOV BX,VWLEN ;CALCULATE INITIAL OFFSET FOR BINARY SEARCH + SAR SI,1 +ORD17$: SAL BX,1 + SAR SI,1 + CMP SI,0 + JNE ORD17$ + MOV SI,VOCBEG ;BEGINNING OF WORD TABLE + ADD SI,BX ;ADD CURRENT OFFSET(HALF OF POWER-OF-2 TABLE) + PUSH AX ;SAVE + MOV AX,VWLEN ;AVOID FENCEPOST BUG FOR EXACT POWER-OF-2 TBL + SUB SI,AX + POP AX ;RESTORE +ORD18$: SAR BX,1 ;NEXT OFFSET WILL BE HALF OF PREVIOUS ONE + GTAWRD A,[SI] ;GET FIRST HALF OF CURRENT ZWORD + CMP DX,AX ;COMPARE DESIRED ONE TO IT + JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + MOV BP,SI ;SAME, GET SECOND HALF + INC BP + INC BP + GTAWRD A,[BP] + CMP DI,AX ;COMPARE DESIRED WORD WITH IT + JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + JMP ORD22$ ;SAME, WE'VE FOUND IT, RETURN IT +ORD19$: ADD SI,BX ;TO MOVE UP, ADD CURRENT OFFSET + CMP SI,CX ;HAVE WE MOVED PAST END OF TABLE? + JBE ORD21$ ;NO + MOV SI,CX ;YES, POINT TO END OF TABLE INSTEAD + JMP ORD21$ +ORD20$: SUB SI,BX ;TO MOVE DOWN, SIMPLY SUBTRACT OFFSET +ORD21$: CMP BX,VWLEN ;IS OFFSET RESOLUTION BELOW ONE WORD? + JGE ORD18$ ;NO, CONTINUE LOOP + SUB SI,SI ;YES, WORD NOT FOUND, RETURN ZERO +ORD22$: POP DI ;RESTORE WORD ENTRY POINTER + MOV DX,SI ;POINTER TO WORD FOUND + XCHG DH,DL + MOV ES:[DI],DX ;(6) STORE IT + POP DX ;RESTORE CHAR POINTER + ADD DI,4 ;UPDATE POINTER FOR NEXT WORD ENTRY + JMP ORD8$ ;GO FOR IT +ORD23$: INC RDRET ;DONE, STORE NUMBER OF WORDS FOUND + MOV BP,RDRET + MOVM ES:[BP],RDNWDS,DL ; REMOVED ES OVERRIDE + POP DI ;RESTORE USER STACK POINTER + RET ;AND RETURN +OPREAD ENDP + + ;PRINTC (PRINT CHAR WHOSE ASCII VALUE IS GIVEN) + PUBLIC OPPRNC,OPPRNN +OPPRNC PROC + JMP PUTCHR ;QUEUE THE CHARACTER FOR PRINTING +OPPRNC ENDP + + ;PRINTN (PRINT A NUMBER) +OPPRNN PROC + MOV BX,AX ;NUMBER TO PRINT + CMP BX,0 + JNE OPN1$ ;NON-ZERO + MOV AX,"0" ;SPECIAL CASE ZERO + JMP PUTCHR +OPN1$: JG OPN2$ ;POSITIVE? + MOV AX,"-" ;NO, PRINT MINUS SIGN + CALL PUTCHR + NEG BX ;AND MAKE IT POSITIVE +OPN2$: SUB CX,CX ;COUNT OF DIGITS ON STACK + JMP OPN4$ ;START WITH GREATER-THAN-10 TEST +OPN3$: MOV AX,BX ;EXTRACT A DIGIT + MOV BP,10 + CWD + IDIV BP + PUSH DX ;PUSH IT + INC CX ;BUMP COUNT + MOV BX,AX ;GET QUOTIENT +OPN4$: CMP BX,10 ;MORE DIGITS TO EXTRACT? + JGE OPN3$ ;YES, GO LOOP + MOV AX,BX ;NO, GET LAST (FIRST) DIGIT + JMP OPN6$ ;ALREADY IN PLACE +OPN5$: POP AX ;POP NEXT DIGIT +OPN6$: ADD AX,"0" ;ASCIIZE IT + CALL PUTCHR ;QUEUE IT + DEC CX ;REDUCE DIGIT COUNT + JGE OPN5$ ;LOOP IF SOME LEFT + RET ;ELSE, RETURN +OPPRNN ENDP + + PUBLIC OPPRIN,OPPRNB + ;PRINT (THE STRING POINTED TO BY ES:AX) +OPPRIN PROC + CALL BSPLIT ;SPLIT THE BLOCK & WORD NUMBERS + JMP PUTSTR ;PRINT THE STRING +OPPRIN ENDP + + ;PRINTB (PRINT THE STRING POINTED TO BY THE BYTE-POINTER ES:AX) +OPPRNB PROC + CALL BSPLTB ;SPLIT THE BLOCK & BYTE NUMBERS + JMP PUTSTR ;PRINT THE STRING +OPPRNB ENDP + +;PSEUDO-INSTRUCTIONS FOR HOURS/MINUTES HERE FOR STATUS LINE +OPPRNH PROC + MOV PMFLAG,0 + CMP AL,12 + JL OPH0$ + MOV PMFLAG,1 +OPH0$: CMP AL,12 + JLE OPH1$ + SUB AL,12 ;HOUR SLOT IS 24 HOUR TIME +OPH1$: CMP AL,0 + JNE OPHZ$ + MOV AL,12 +OPHZ$: CMP AL,9 + JG OPH2$ + PUSH AX + MOV AL,32 + CALL PUTCHR ;OUTPUT SPACE FOR HOUR LESS THAN 10 + POP AX +OPH2$: CALL OPPRNN + MOV AL,":" + JMP PUTCHR ;AND COLON +OPPRNH ENDP + +OPPRNM PROC + CMP AL,9 + JG OPM1$ + PUSH AX + MOV AL,"0" + CALL PUTCHR + POP AX +OPM1$: CALL OPPRNN + MOV AL,32 + CALL PUTCHR + MOV AL,"a" + CMP PMFLAG,0 + JE OPM2$ + MOV AL,"p" +OPM2$: CALL PUTCHR + MOV AL,"m" + JMP PUTCHR +OPPRNM ENDP + + PUBLIC OPPRND,OPPRNI,OPPRNR + ;PRINTD (PRINT OBJ'S SHORT DESCRIPTION) +OPPRND PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + ADD AX,7 ;PROPERTY TABLE POINTER + MOV BP,AX + GTAWRD A,[BP] ;GET IT + INC AX ;POINT TO STRING + CALL BSPLTB ;SPLIT POINTER + JMP PUTSTR ;AND PRINT THE STRING +OPPRND ENDP + + ;PRINTI (PRINT THE STRING FOLLOWING THIS INSTRUCTION) +OPPRNI PROC + MOV AX,ZPC1 ;GET POINTER TO STRING + MOV BX,ZPC2 + CALL PUTSTR ;AND PRINT IT + MOV ZPC1,AX ;UPDATE ZPC + MOV ZPC2,BX + JMP NEWZPC +OPPRNI ENDP + + ;PRINTR (PRINTI FOLLOWED BY RTRUE) +OPPRNR PROC + CALL OPPRNI ;DO A PRINTI + CALL OPCRLF ;A CRLF + JMP OPRTRU ;AND AN RTRUE +OPPRNR ENDP + + PUBLIC OPCRLF + ;CRLF (DO A NEWLINE) +OPCRLF PROC + JMP NEWLIN ;DO A NEWLINE +OPCRLF ENDP + + SUBTTL CONTROL OPERATIONS + PAGE + + + PUBLIC OPCALL + ;CALL (A FUNCTION WITH OPTIONAL ARGUMENTS), # OF ARGS IN AX +OPCALL PROC + NOP ;TELL CALLER TO USE ARGUMENT BLOCK + MOV DX,AX ;NUMBER OF ARGUMENTS TO CALL + MOV AX,ARGBLK ;FUNCTION TO CALL + CMP AX,0 + JNE OCL1$ ;ZERO? + SUB AX,AX ;YES, SIMPLY RETURN A ZERO + JMP PUTVAL +OCL1$: PUSHZ ZPC1 ;OTHERWISE, SAVE OLD ZPC + PUSHZ ZPC2 + MOV CX,ZLOCS ;AND OLD LOCAL POINTER +; SUB CX,STKBOT ;BUT RELATIVIZE IT IN CASE OF SAVE + PUSHZ CX ;AND SAVE IT + CALL BSPLIT ;SPLIT FUNCTION POINTER + MOV ZPC1,AX ;MAKE IT THE NEW ZPC + MOV ZPC2,BX + CALL NEWZPC ;UPDATE ZPC STUFF + MOV ZLOCS,DI ;LOCALS WILL START AT NEXT STACK SLOT + SUB ZLOCS,2 + CALL NXTBYT ;NUMBER OF LOCALS + MOV BX,AX + MOV BP,OFFSET ARGBLK[2] ;POINT TO FIRST OPTIONAL ARG +OCL2$: DEC BX ;ANY MORE LOCALS? + JL OCL4$ ;NO, WE'RE DONE + CALL NXTWRD ;YES, GET THE NEXT LOCAL DEFAULT VALUE + DEC DX ;ANY MORE OPTIONALS GIVEN? + JLE OCL3$ ;NO + PUSHZ [BP] ;(6) YES, USE ITS VALUE + ADD BP,2 + JMP OCL2$ ;AND CONTINUE LOOP +OCL3$: PUSHZ AX ;OTHERWISE, USE DEFAULT + JMP OCL2$ ;AND LOOP +OCL4$: RET +OPCALL ENDP + + PUBLIC OPRETU + ;RETURN (FROM CURRENT FUNCTION CALL) +OPRETU PROC + MOV DI,ZLOCS ;RESTORE OLD TOP OF STACK + POPZ DX ;DUMMY POP [WHY?] + POPZ ZLOCS ;AND OTHER VALUES + +; MOV DX,STKBOT ;RE-ABSOLUTIZE THIS ONE +; ADD ZLOCS,DX + + POPZ ZPC2 + POPZ ZPC1 + PUSH AX ;VALUE TO RETURN + CALL NEWZPC ;UPDATE ZPC STUFF + POP AX + JMP PUTVAL ;RETURN THE VALUE +OPRETU ENDP + + PUBLIC OPRTRU,OPRFAL,OPJUMP,OPRSTA,OPFSTA,OPNOOP + ;RTRUE +OPRTRU PROC + MOV AX,1 ;RETURN A 1 + JMP OPRETU +OPRTRU ENDP + + ;RFALSE +OPRFAL PROC + SUB AX,AX ;RETURN A 0 + JMP OPRETU +OPRFAL ENDP + + ;JUMP (TO A NEW LOCATION) +OPJUMP PROC + ADD ZPC2,AX ;ADD OFFSET TO CURRENT ZPC + SUB ZPC2,2 ;ADJUST IT + JMP NEWZPC ;NORMALIZE IT & UPDATE ZPC STUFF +OPJUMP ENDP + + ;RSTACK (RETURN STACK) +OPRSTA PROC + POPZ AX ;POP A VALUE + JMP OPRETU ;AND RETURN IT +OPRSTA ENDP + + ;FSTACK (FLUSH A VALUE OFF THE STACK) +OPFSTA PROC + POPZ DX ;FLUSH ONE + RET +OPFSTA ENDP + + ;NOOP (NO OPERATION) +OPNOOP PROC + RET ;DO NOTHING +OPNOOP ENDP + + SUBTTL LOW LEVEL FUNCTIONS + PAGE + + + ;GET A BYTE, BLOCK-POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX, + ;UPDATE AX & BX TO REFLECT BYTE GOTTEN +; +; GETBYT UNDERWENT SERIOUS RE-WRITING AND EVALUATION IN THE UPDATE TO USE +; ALL OF MEMORY. THE ORIGINAL ROUTINE WAS KEPT BUT CHANGES WERE MADE IN +; TWO SETS: THE FIRST TO HANDLE THE CASE IN WHICH ALL OF THE GAME IS IN +; MEMORY; AND THE SECOND IN WHICH THE GAME BUFFERS EXTEND PAST 64K AND THUS +; REQUIRING A SEGMENT SWITCH TO RETRIEVE THE BYTE. +; +; FOR THE FIRST CASE, THE BLOCK PTR IS USED TO DETERMINE THE SEGMENT IN +; WHICH THE BLOCK RESIDES, THE GAME SEGMENT IS SET ACCORDINGLY, AND THE +; BYTE IS FETCHED. +; +; THE SECOND CASE WILL CALL GETPAG TO DETERMINE WHERE THE PAGE IS LOCATED IN +; CORE. CALLING GETPAG WILL SET A VARIABLE CALLED CURSEG TO 0 OR 1 TO INDICATE +; THAT THE PAGE WE ARE TOUCHING IS IN THE FIRST OR SECOND SEGMENT. GETPAG +; RETURNS A VALID POINTER ASSUMING THAT THIS ROUTINE WILL SET ES ACCORDING TO +; CURSEG. IF CURSEG IS 0, GAMESEG (THE FIRST SEGMENT [OR ZEROTH]) WILL +; CONTAIN THE BLOCK, AND IF CURSEG IS 1, SEG1 (GAMESEG + 64K) WILL CONTAIN +; THE BLOCK. +; +; NOTE THAT ES ALWAYS CONTAINS THE VALUE GAMESEG UNLESS WE NEED TO FETCH +; OR PUT SOMETHING IN THE SECOND SEGMENT. AT THAT POINT ES IS SET TO SEG1 +; ONLY FOR THAT OPERATION. +; + PUBLIC GETBYT,FETCH,GTY1A$,GTSEG1,GTY1$,GTY1B$,GTY2$,GTY3$ +GETBYT PROC + PUSH SI ; SAVE THIS BEAR + PUSH AX ;SAVE BLOCK-POINTER + CMP FITS,1 ; (6) IS ALL OF THE GAME RESIDENT + JZ FETCH ; (6) IT'S THERE, GO GET IT + CMP AX,ENDLOD ;IS THIS A PRELOADED LOCATION? + JGE GTY1$ ;NO +FETCH: CMP AX,128 ; (6) CHECK SEGMENT FOR BLOCK + JGE GTSEG1 ; (6) GET BYTE FROM SEGMENT 1 +GTY1A$: MOV CL,9 ;YES, RECONSTRUCT POINTER + SHL AX,CL ;SHIFT BLOCK POINTER BY 9 + OR AX,BX ;ADD IN THE OFFSET + XCHG AX,BX + MOV CL,ES:[BX] ;GET THE BYTE + JMP GTY2$ ;CLEAR UNWANTED BYTE & RETURN IT +GTSEG1: MOV SI,SEG1 ; (6) GET SECOND GAME SEG + MOV ES,SI ; (6) ADDRESS SEG1 + JMP GTY1A$ ; (6) USE SEG0 LOGIC +GTY1$: CALL GETPAG ;FIND THE PROPER PAGE + ADD AX,BX ;POINT TO DESIRED BYTE + XCHG AX,BX + CMP CURSEG,1 ;(6) CHECK SEGMENT THAT WERE LOOKING IN + JNZ GTY1B$ ;(6) ITS IN 0, GET IT NORMALLY + MOV SI,SEG1 ;(6) ITS NOT, SET UP ES TO SEG1 + MOV ES,SI ;(6) GETPAG RETURNED RIGHT POINTER +GTY1B$: MOV CL,ES:[BX] ;GET IT +GTY2$: SUB CH,CH ;CLEAR UNWANTED BYTE & RETURN IT + MOV BX,AX + MOV SI,GAMESEG ; (6) MAKE SURE GAME SEG IS RESTORED + MOV ES,SI ; (6) TO SEG 0 + POP AX ;RESTORE BLOCK-POINTER + POP SI ; RESTORE THIS + INC BX ;UPDATE POINTER + CMP BX,200H ;END-OF-PAGE? + JNE GTY3$ ;NO + SUB BX,BX ;YES, CLEAR BYTE-POINTER + INC AX ;AND UPDATE BLOCK-POINTER +GTY3$: RET +GETBYT ENDP + + ;GET A WORD, BLOCK POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX + PUBLIC GETWRD +GETWRD PROC + PUSH DX ;SAVE + CALL GETBYT ;GET HIGH-ORDER BYTE + PUSH CX ;SAVE IT + CALL GETBYT ;GET LOW-ORDER BYTE + POP DX ;GET OTHER BYTE + MOV CH,DL ;POSITION IT + POP DX ;RESTORE + RET +GETWRD ENDP + + ;GET THE NEXT BYTE, RETURN IT IN AX +; THIS ROUTINE ALSO WENT UNDER SIGNIFICANT REVISION TO ACCOMODATE MORE +; PAGING SPACE. TWO CASES HAD TO BE HANDLED: ALL OF GAME IN MEMORY AND +; MORE THAN 64K OF PAGING SPACE. THE FIRST CASE REQUIRED THAT THE VARIABLE +; ZPCSEG BE SET IN NEWZPC TO INDICATE IN WHICH SEGMENT OUR ZPC BLOCK COULD +; BE FOUND. THE SECOND CASE REQUIRES THAT ZPCSEG BE SET ONLY WHEN GETPAG +; IS CALLED FROM NEWZPC AND THE PAGE THAT IT GOT WAS PUT IN THE SECOND GAME +; SEGMENT. +; + PUBLIC NXTBYT,NXBA$,NXB1$ +NXTBYT PROC + PUSH SI ;(6) PRESERVE THIS ONE TOO + PUSH BX ;SAVE + TEST ZPCFLG,1 ;(7n) HAS THIS PAGE SEEN FOUL PLAY? + JZ NXB0$ ; (7n) NOPE + CALL NEWZPC ; (7n) FIX INDEX INTO CURRENT PAGE +NXB0$: MOV BX,ZPC2 ;BYTE POINTER + ADD BX,CURPAG ;INDEX INTO CURRENT PAGE + CMP ZPCSEG,0 ;(6) WHERE ARE WE? + JZ NXBA$ ;(6) SEG0, ACT NORMALLY + MOV SI,SEG1 ;(6) GET SEG1 VALUE + MOV ES,SI ;(6) INTO ES +NXBA$: MOV AL,BYTE PTR ES:[BX] ; GET BYTE + PUSH AX ; AND SAVE +;PUSH ES:[BX] ;SAVE BYTE -- AT KILLER CODE ON FFFF + MOV SI,GAMESEG ;(6) GET BASE GAME SEG + MOV ES,SI ;(6) BACK INTO ES + INC ZPC2 ;UPDATE PC + CMP ZPC2,200H ;END-OF-PAGE? + JL NXB1$ ;NO + CALL NEWZPC ;YES, UPDATE PAGE +NXB1$: POP AX ;RETRIEVE BYTE + SUB AH,AH ;CLEAR UNWANTED BYTE + POP BX ;RESTORE + POP SI + RET ;AND RETURN IT +NXTBYT ENDP + + ;GET THE NEXT WORD, RETURN IT IN AX + PUBLIC NXTWRD +NXTWRD PROC + PUSH BX ;SAVE + CALL NXTBYT ;GET HIGH-ORDER BYTE + PUSH AX ;SAVE IT + CALL NXTBYT ;GET LOW-ORDER BYTE + POP BX ;GET HIGH-ORDER BYTE + MOV AH,BL ;POSITION IT + POP BX ;RESTORE + RET ;RETURN THE WORD +NXTWRD ENDP + + ;GET AN ARGUMENT GIVEN ITS TYPE IN AX + PUBLIC GETARG +GETARG PROC + DEC AX ;EXAMINE ARGUMENT + JL NXTWRD ;0 MEANT LONG IMMEDIATE + JE NXTBYT ;1 MEANT SHORT IMMEDIATE + CALL NXTBYT ;2 MEANT VARIABLE, GET THE VAR + CMP AX,0 ;STACK? + JNE GETVAR ;NO, JUST GET THE VAR'S VALUE + POPZ AX ;YES, POP THE STACK + RET +GETARG ENDP + + ;GET VALUE OF A VARIABLE, VAR IN AX, VALUE RETURNED IN AX + PUBLIC GETVAR +GETVAR PROC + CMP AX,0 ;STACK? + JNE GTV1$ ;NO + POPZT AX ;YES, GET TOP-OF-STACK + RET +GTV1$: PUSH BP ;SAVE + CMP AX,16 ;LOCAL? + JGE GTV3$ ;NO + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV AX,[BP] ;AND GET IT +GTV2$: POP BP ;RESTORE + RET +GTV3$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + MOV BP,AX ;AND GET IT + GTAWRD A,[BP] + JMP GTV2$ +GETVAR ENDP + + ;UPDATE VALUE OF A VARIABLE, VAR IN AX, NEW VALUE IN BX + PUBLIC PUTVAR +PUTVAR PROC + CMP AX,0 ;STACK? + JNE PTV1$ ;NO + PUSHZT BX ;YES, UPDATE TOP-OF-STACK + RET +PTV1$: CMP AX,16 ;LOCAL? + JGE PTV2$ ;NO + PUSH BP ;SAVE + DEC AX ;YES, POINT TO PROPER STACK ELEMENT + SHL AX,1 + MOV BP,ZLOCS + SUB BP,AX + MOV [BP],BX ;AND UPDATE IT + POP BP ;RESTORE + RET +PTV2$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT + SHL AX,1 + ADD AX,GLOTAB + XCHG AX,BX ;AND UPDATE IT + PTAWRD [BX],A + RET +PUTVAR ENDP + + ;RETURN VAL IN AX TO LOCATION SPECIFIED BY NEXTBYTE + ;DESTROYS BX, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION + PUBLIC BYTVAL +BYTVAL PROC + SUB AH,AH ;THIS ENTRY FOR BYTE VALUE TO CLEAR HIGH BYTE + JMP PUTVAL +BYTVAL ENDP + + PUBLIC PUTVAL +PUTVAL PROC + MOV BX,AX ;NORMAL ENTRY + CALL NXTBYT ;GET VAR TO USE + CMP AX,0 ;STACK? + JNE PUTVAR ;NO, GO STORE VALUE + PUSHZ BX ;YES, PUSH ONTO STACK + RET ;AND RETURN +PUTVAL ENDP + + ;PREDICATE HANDLERS TRUE & FALSE + ;DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FCNS + PUBLIC PFALSE,PTRUE +PFALSE PROC + SUB BX,BX ;PREDICATE WAS FALSE, CLEAR FLAG + JMP PPRED +PFALSE ENDP + +PTRUE PROC + MOV BX,1 ;PREDICATE WAS TRUE, SET FLAG + JMP PPRED +PTRUE ENDP + + PUBLIC PPRED +PPRED PROC + CALL NXTBYT ;GET FIRST (OR ONLY) PREDICATE JUMP BYTE + TEST AX,80H ;NORMAL POLARITY PREDICATE? + JE PPR1$ ;NO, LEAVE FLAG ALONE + INC BX ;YES, INCREMENT FLAG +PPR1$: TEST AX,40H ;ONE-BYTE JUMP OFFSET? + JE PPR2$ ;NO + AND AX,0FF3FH ;YES, CLEAR SPECIAL BITS + JMP PPR3$ +PPR2$: AND AX,0FF3FH ;CLR SPECIAL BITS FROM HIGH-ORDER OFFSET BYTE + MOV CX,AX ;HIGH-ORDER BYTE + CALL NXTBYT ;GET LOW-ORDER BYTE + MOV AH,CL ;MOVE IN HIGH-ORDER BITS + TEST AX,2000H ;IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)? + JE PPR3$ ;NO + OR AX,0C000H ;YES, MAKE 16-BIT NUMBER NEGATIVE +PPR3$: DEC BX ;TEST FLAG + JE PPR6$ ;WAS 1, THAT MEANS DO NOTHING + CMP AX,0 ;ZERO JUMP? + JNE PPR4$ ;NO + JMP OPRFAL ;YES, THAT MEANS DO AN RFALSE +PPR4$: DEC AX ;ONE JUMP? + JNE PPR5$ ;NO + JMP OPRTRU ;YES, THAT MEANS DO AN RTRUE +PPR5$: DEC AX ;ADJUST OFFSET + ADD ZPC2,AX ;ADD TO PC + JMP NEWZPC ;AND UPDATE ZPC STUFF +PPR6$: RET +PPRED ENDP + + ;SPLIT BYTE-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE OFFSET IN BX + PUBLIC BSPLTB +BSPLTB PROC + MOV BX,AX + XCHG AL,AH ;EXTRACT BLOCK BITS + SHR AX,1 + AND AX,7FH ;CLEAR UNWANTED BITS + AND BX,1FFH ;CLEAR ALL BUT BYTE OFFSET BITS + RET +BSPLTB ENDP + + ;SPLIT WORD-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE-OFFSET IN BX + PUBLIC BSPLIT +BSPLIT PROC + MOV BX,AX + MOV AL,AH ;EXTRACT BLOCK BITS + SUB AH,AH ;CLEAR UNWANTED BITS + SUB BH,BH ;CLEAR ALL BUT WORD OFFSET BITS + SHL BX,1 ;CONVERT TO BYTE OFFSET + RET +BSPLIT ENDP + + SUBTTL OBJECT HACKERS + PAGE + + + PUBLIC OBJLOC,NXTPRP + ;GIVEN OBJ NUMBER IN AX, RETURN OBJ LOCATION IN AX +OBJLOC PROC + SUB AH,AH ;CLEAR UNWANTED BITS + PUSH BX ;MULTIPLY BY 9 THE LAZY WAY + MOV BX,AX + SHL AX,1 + SHL AX,1 + SHL AX,1 + ADD AX,BX + POP BX ;RESTORE + ADD AX,OBJTAB ;INDEX INTO OBJECT TABLE + ADD AX,53 ;SKIPPING DEFAULT PROPERTY TABLE + RET +OBJLOC ENDP + + ;GIVEN POINTER TO A PROPERTY IN BX!, UPDATE IT TO POINT TO NEXT PROP +NXTPRP PROC + PUSH AX ;SAVE + PUSH CX ;SAVE + MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPSIZE;EXTRACT PROPERTY LENGTH (MINUS 1) + MOV CL,PROPSIZE + SHR AL,CL + SUB AH,AH + ADD BX,AX ;ADD IT TO OLD POINTER + ADD BX,2 ;ADJUST FOR EXTRA LENGTH BYTE PLUS IDENTIFIER + POP CX ;RESTORE + POP AX ;RESTORE + RET +NXTPRP ENDP + + SUBTTL STRING FUNCTIONS + PAGE + + + ;OUTPUT A ZSTR, BLOCK-POINTER IN AX, BYTE-POINTER IN BX + ;RETURN UPDATED POINTER + PUBLIC PUTSTR +PUTSTR PROC + PUSH SI ;SAVE + PUSH CX ;SAVE + PUSH DX ;SAVE + PUSH DI ;SAVE + PUSH BP ;SAVE + SUB DX,DX ;TEMP CS STARTS AT 0 + SUB DI,DI ;PERM CS STARTS AT 0 +PTS1$: CALL GETWRD ;GET NEXT STRING WORD + MOV SI,CX + PUSH AX ;SAVE POINTER & COPY OF STRING WORD + PUSH BX + PUSH SI + MOV CX,3 ;3 BYTES IN WORD +PTS2$: PUSH SI ;SAVE CURRENT BYTE (IN LOW-ORDER POSITION) + MOV BP,CX ;SHIFT TO NEXT BYTE + MOV CL,5 + SAR SI,CL + MOV CX,BP + LOOP PTS2$ ;LOOP UNTIL DONE + MOV CX,3 ;RETRIEVE THE 3 BYTES +PTS3$: POP SI ;GET NEXT BYTE + AND SI,1FH ;CLEAR UNWANTED BITS + CMP DX,0 ;IN WORD MODE? + JGE PTS4$ ;NO {WAS BPL, CHECK} + SAL SI,1 ;YES, CALCULATE WORD OFFSET + ADD SI,WRDTAB ;POINT INTO WORD TABLE + ADD SI,WRDOFF ;USING PROPER 32-WORD BLOCK + GTAWRD A,[SI] ;POINT TO WORD STRING + CALL BSPLIT ;SPLIT IT + CALL PUTSTR ;AND PRINT IT + JMP PTS15$ ;CONT. WHERE WE LEFT OFF WITH TEMP CS RESET +PTS4$: CMP DX,3 ;CS 3 SELECTED (ASCII MODE)? + JL PTS6$ ;NO, NORMAL CS + JNE PTS5$ ;NO, BUT WE ARE IN ASCII MODE + XCHG DL,DH ;SHIFT SOME BITS HIGH TO MAKE NUMBER LARGE + OR DX,SI ;SAVE HIGH-ORDER ASCII BITS HERE + JMP PTS16$ ;GO GET NEXT BYTE +PTS5$: AND DX,3 ;EXTRACT PREVIOUSLY SAVED HIGH-ORDER BITS + MOV BP,CX ;POSITION THEM + MOV CL,5 + SAL DX,CL + MOV CX,BP + OR DX,SI ;OR IN LOW-ORDER BITS + MOV AX,DX + JMP PTS14$ ;GO PRINT THE CHARACTER +PTS6$: CMP SI,6 ;SPECIAL CODE? + JL PTS9$ ;YES, SPACE, WORD, OR SHIFT + CMP DX,2 ;MIGHT ALSO BE SPECIAL IF IN CS 2 + JNE PTS8$ ;BUT WE'RE NOT + CMP SI,7 ;CRLF? + JE PTS7$ ;YES + JG PTS8$ ;NO, NOT ASCII MODE, EITHER? + INC DX ;YES IT IS, SWITCH TO ASCII MODE + JMP PTS16$ ;AND GO GET NEXT BYTE +PTS7$: CALL NEWLIN ;CRLF REQUESTED, DO A NEWLINE + JMP PTS15$ +PTS8$: MOV AX,DX ;NORMAL CHARACTER, GET CS + MOV BP,26 ;CALCULATE OFFSET FOR THIS CS + MUL BP + ADD AX,SI ;ADD IN CHARACTER OFFSET (+6) + SUB AX,6 ;CHARACTER OFFSET + MOV BX,OFFSET ZCHRS ;GET THE CHARACTER FROM CONVERSION VECTOR + XLAT ZCHRS + JMP PTS14$ ;GO PRINT IT +PTS9$: CMP SI,0 ;IS IT A SPACE? + JNE PTS10$ ;NO + MOV AX," " ;YES, GO PRINT A SPACE + JMP PTS14$ +PTS10$: CMP SI,3 ;IS IT A WORD? + JG PTS11$ ;NO, MUST BE A SHIFT + OR DX,8000H ;SWITCH TO WORD MODE FOR NEXT BYTE + DEC SI ;CALCULATE WORD-TABLE BLOCK OFFSET + MOV BP,CX ;64 BYTES IN A BLOCK + MOV CL,6 + SHL SI,CL + MOV CX,BP + MOV WRDOFF,SI ;SAVE IT AND LOOP + JMP PTS16$ +PTS11$: SUB SI,3 ;CALCULATE NEW CS + CMP DX,0 ;TEMPORARY SHIFT (FROM CS 0)? + JNE PTS12$ ;NO + MOV DX,SI ;YES, JUST SAVE NEW TEMP CS + JMP PTS16$ +PTS12$: CMP SI,DX ;IS THIS THE CURRENT CS? + JE PTS13$ ;YES, DO A PERM SHIFT TO IT + SUB DX,DX ;OTHERWISE, PERM SHIFT TO CS 0 +PTS13$: MOV DI,DX ;TEMP & PERM CS'S ARE SAME NOW + JMP PTS16$ +PTS3A$: JMP PTS3$ ;DUMMY FOR NON-SHORT LOOP +PTS14$: CALL PUTCHR ;PRINT THE CHARACTER +PTS15$: MOV DX,DI ;RESET TEMP CS TO PERM CS +PTS16$: LOOP PTS3A$ ;NEXT BYTE + POP SI ;RESTORE POINTERS & ORIGINAL STRING WORD + POP BX + POP AX + CMP SI,0 ;END-OF-STRING? + JL PTS1A$ ;YES, CLEAN UP & RETURN UPDATED POINTER + JMP PTS1$ ;NO, GET NEXT WORD +PTS1A$: POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET +PUTSTR ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN THE CHARACTER SET # IN AX + PUBLIC CHRCS +CHRCS PROC + CMP AX,0 ;IS THIS A NULL? + JNE CCS1$ ;NO + MOV AX,3 ;YES, RETURN DUMMY CS NUMBER + RET +CCS1$: PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CONVERSION VECTOR +CCS2$: INC BX ;FOUND THE CHARACTER? + CMP AL,[BX-1] + JE CCS3$ ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CCS2$ ;NO, CONTINUE LOOP + MOV AX,2 ;YES, CALL IT CS 2 + JMP CCS5$ +CCS3$: SUB BX,OFFSET ZCHRS ;FIND CHARACTER POSITION + SUB AX,AX ;START WITH CS 0 +CCS4$: SUB BX,26 ;EVERY 26 CHARACTERS IS A NEW CS + JLE CCS5$ ;DONE + INC AX ;INCREMENT CS # & CONTINUE LOOP + JMP CCS4$ +CCS5$: POP BX + RET +CHRCS ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN ZSTR BYTE VALUE IN AX + PUBLIC CHRBYT +CHRBYT PROC + PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CHARACTER CONVERSION TABLE +CHB1$: INC BX ;FOUND THE CHARACTER? + CMP AL,[BX-1] + JE CHB2$ ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CHB1$ ;NO, CONTINUE LOOP + SUB AX,AX ;YES, RETURN ZERO FOR FAILURE + JMP CHB4$ +CHB2$: SUB BX,OFFSET ZCHRS-5 ;ADJUST POINTER SO FIRST CHARACTER IS 6 + MOV AX,BX +CHB3$: CMP AX,32 ;SUBTRACT MULTIPLES OF 26 UNTIL BASE CODE + JL CHB4$ + SUB AX,26 + JMP CHB3$ +CHB4$: POP BX ;RESTORE + RET +CHRBYT ENDP + + ;CONVERT UP TO 6 ASCIZ CHARS POINTED TO BY DS:AX + ;TO A 2-WORD ZSTR RETURNED IN AX & BX + PUBLIC ZWORD +ZWORD PROC + PUSH SI ;SAVES + PUSH CX + PUSH DX + PUSH DI + PUSH BP + MOV SI,AX ;CHARACTER STRING POINTER + SUB DI,DI ;CS STARTS AT 0 + MOV CX,6 ;MAKE 6 ZSTR BYTES +ZWD1$: INC SI ;GET NEXT CHARACTER + MOV BL,[SI-1] + CMP BL,0 + JNE ZWD3$ ;NOT END-OF-STRING + MOV AX,OFFSET PADCHR;AT END-OF-STRING, PAD WITH PAD CHARACTER +ZWD2$: PUSH AX ;SAVE A PAD BYTE + LOOP ZWD2$ ;LOOP UNTIL DONE + JMP ZWD6$ ;THEN GO FORM ZWORD +ZWD3$: MOV AX,BX + CALL CHRCS ;FIND THE CS NUMBER FOR THIS CHAR + CMP AX,0 ;CS 0? + JE ZWD4$ ;YES + ADD AX,3 ;NO, CALCULATE TEMP SHIFT BYTE + PUSH AX ;SAVE THE SHIFT BYTE + DEC CX ;REDUCE BYTE COUNT + JE ZWD6$ ;DONE +ZWD4$: MOV AX,BX ;FIND THE PROPER BYTE VALUE FOR THIS CHAR + CALL CHRBYT + CMP AX,0 ;IN NORMAL CS'S? + JNE ZWD5$ ;YES + MOV AX,6 ;NO, USE ASCII SHIFT + PUSH AX + DEC CX ;DONE YET? + JE ZWD6$ ;YES + MOV AX,BX ;NO, SAVE HIGH-ORDER ASCII BITS + MOV BP,CX + MOV CL,5 + SAR AX,CL + MOV CX,BP + PUSH AX + DEC CX ;DONE YET? + JE ZWD6$ ;YES + AND BX,1FH ;NO, SAVE LOW-ORDER ASCII BITS + MOV AX,BX +ZWD5$: PUSH AX ;SAVE THIS BYTE + LOOP ZWD1$ ;LOOP UNTIL ZWORD FULL +ZWD6$: MOV BP,SP ;BUILD ZWORD WORDS FROM 6 SAVED BYTES + MOV AX,[BP+10] + MOV CL,5 + SHL AX,CL + OR AX,[BP+8] + SHL AX,CL + OR AX,[BP+6] + MOV BX,[BP+4] + SHL BX,CL + OR BX,[BP+2] + SHL BX,CL + OR BX,[BP] + OR BX,8000H ;SET END-OF-STRING BIT IN SECOND WORD + ADD SP,12 ;FLUSH STACK + POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET +ZWORD ENDP + + SUBTTL TERMINAL I/O + PAGE + + + ;QUEUE CHARACTER IN AX FOR OUTPUT + PUBLIC PUTCHR +PUTCHR PROC + PUSH BP + MOV BP,CHRPTR + CMP BP,ENDBUF + JNE PTC7 + PUSH AX + PUSH BX + PUSH SI + MOV BX,ENDBUF + MOV SI,OFFSET OUTBUF +PTC1: DEC BX + CMP BYTE PTR [BX]," " + JE PTC3 + CMP BX,SI + JNE PTC1 +PTC2: PRINT OUTBUF + MOV CHRPTR,SI + MOV BP,SP + CMP BYTE PTR 4 [BP]," " + JNE PTC6 + MOV WORD PTR 4 [BP],0 + JMP PTC6 +PTC3: CMP BX,SI + JE PTC2 + MOV BYTE PTR [BX],0 + PRINT OUTBUF + MOV AX,ENDBUF + INC BX +PTC4: CMP BX,AX + JE PTC5 + MOV BP,AX + MOV AL,[BX] + MOV [SI],AL + MOV AX,BP + INC BX + INC SI + JMP PTC4 +PTC5: MOV CHRPTR,SI +PTC6: POP SI + POP BX + POP AX + CMP AX,0 + JE PTC8 +PTC7: MOV BP,CHRPTR + MOV [BP],AL ; (6) REMOVED DS OVERRIDE + INC CHRPTR +PTC8: POP BP + RET +PUTCHR ENDP + + ;GO TO NEW LINE, OUTPUTTING CURRENT BUFFER +NEWLIN PROC + PUSH BX ;SAVE + MOV BX,CHRPTR ;END LINE AT CURRENT POINT + MOV BYTE PTR [BX],0 + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP BX ;RESTORE + PRINT OUTBUF ;AND OUTPUT LINE + RET +NEWLIN ENDP + + SUBTTL TOP LEVEL STUFF + PAGE + + + ; READ THE SETUP FILE +; SSETUP HAS UNDER GONE TO SETS OF REVISIONS. REVISION 6 IS RESPONSIBLE +; FOR ALL OF THE DOS 2.0 FILE HANDLING PATCHES. REVISION 7 IS RESPONSIBLE +; FOR SETTING UP COLOR OR MONOCHROME BASED ON THE VIDEO SETTINGS AND WHAT +; WAS SPECIFIED ON THE COMMAND LINE. +; + PUBLIC SSETUP +SSETUP PROC NEAR + MOV DX,OFFSET SSFILE ; (6) USE ASCIZ FILENAME + MOV AH,CFOPENZ ; TRY OPENING THE SETUP FILE + MOV AL,0 ; (6) OPEN FILE FOR READING + INT 21H + JC SSET1 ; IF OPEN FAIL, COMPLAIN + MOV BX,AX ; (6) PUT HANDLE IN BX + MOV AH,CRDRNDZ ; (6) READ INTO THE BUFFER + MOV DX,OFFSET SSBUF ; (6) BUFFER TO READ INTO + MOV CX,SSLNT ; (6) READ (CX) BYTES + INT 21H + CMP AL,SSLNT ; (6) DID WE GET ALL THE BYTES + JNE SSET2 ; IF READ FAIL, COMPLAIN + PUSH BX ; (6) SAVE THE HANDLE + MOV BX,DX ; (6) GET OFFSET TO BUFFER + MOV AL,[BX] + SUB AL,SSVER + DEC AL ; FOR A 25 LINE SCREEN, SLPP HAS 24 IN IT + MOV SLPP,AL + MOV AL,[BX+1] + SUB AL,SSHOR + MOV SCPL,AL + MOV SLFLG,1 ; SET IT TO ANSI + MOV AL,[BX+2] + CMP AL,"N" ; IS IT ASCII + JNE SSET4 ; NO, THEN LEAVE IT ALONE + MOV SLFLG,0 ; YES, THEN SET IT TO ASCII + MOV SCROLL,1 ; (7) NO SCROLLING IF NO ANSI.SYS + JMP SSET6 +SSET4: TEST SCROLL,1 ; (7) SHOULD WE CONSIDER COLOR + JNZ SSET6 ; (7u) I GUESS NOT + MOV AH,15 ; (7) CHECK VIDEO STATE + INT 10H ; (7) TO SEE IF IN A COLOR MOOD + CMP AL,1 ; (7) THIS IS 40x25 COLOR + JNZ SSET5 +SSET4A: TEST CMDLIN,1 ; (7) WAS THIS SET ON CMD LINE + JNZ SSET6 ; (7) YES, CANNOT OVERRIDE + CMP SCROLL,1 ; (7u) NO COLOR WITHOUT SCROLL CAPABILITY + JZ SSET6 ; + MOV COLFLG,1 ; (7) SET COLOR FLAG + MOV SCRATR,COLATR ; (7) SET VIDEO ATTRIBUTE + JMP SSET6 +SSET5: CMP AL,3 ; (7) THIS IS 80x25 COLOR + JZ SSET4A + TEST CMDLIN,2 ; (7) DID THEY SET COLOR FROM CMD LINE + JNZ SSET4A ; (7) TURN IT ON +SSET6: POP BX ; (6) RESTORE THE HANDLE + MOV AH,CFCLOSZ ; (6) CLOSE THE SETUP FILE + INT 21H + JC SSET3 ; (6) IF CANNOT CLOSE FILE, COMPLAIN + RET +SSET1: DEC SLPP ; (N1) SET TO 24 TO WORK RIGHT ANYWAY! + PRINT SSMSG1 + RET +SSET2: PRINT SSMSG2 + RET +SSET3: PRINT SSMSG3 + RET +SSETUP ENDP + + ;INITIALIZATION + PUBLIC TSET4 +TSETUP PROC + MOV BX,OFFSET SELINE1 + TEST COLFLG,1 ; (7) ARE WE USING COLOR + JZ TSET0 ; (7) NOPE, ... + MOV BX,OFFSET CELINE1 ; (7) FIX COLOR IF NECESSARY +TSET0: MOV AL,SLPP ; NUMBER OF LINES + SUB AH,AH ; ASCIIFY THIS NUMBER INTO AX + INC AX ; FOR SLPP = 24, THE CURSOR IS AT 25 + DIV RADIX ; SO THAT WE CAN PUT THE CURSOR + ADD AH,"0" ; THERE WHEN WE FINISH THE STATUS + ADD AL,"0" ; LINE OUTPUT IN MSOUT + MOV [BX],AX ; DO THE PATCH + MOV BX,OFFSET CLS1 ; (7t) PATCH CLEAR SCREEN + MOV [BX],AX ; (7t) SO THAT IT RESTORE CURPOS + MOV BX,OFFSET CLS1C ; (7t) PATCH IT IN COLOR TOO + MOV [BX],AX + MOV BX,OFFSET OUTBUF ; NO DETERMINE END OF OUTPUT BUFFER + + MOV CL,SCPL + SUB CH,CH + ADD BX,CX + DEC BX ; (7v) SHORTEN BY ONE TO AVOID HARD + MOV ENDBUF,BX ; WRAP + MOV BYTE PTR [BX],0 + MOV BX,OFFSET SLSTAB ; NOW, CHOSE A STATUS LINE + CMP TIMEMD,0 ; CHECK FOR TIME MODE + JE TSET1 ; NOPE, USE OTHER STATUS LINE + ADD BX,8 ; YES, GET OFFSET TO TIME STAT LINES +TSET1: CMP CX,55 ; CX HAS WIDTH OF SCREEN IN COLUMNS + JL TSET2 + MOV AX,60 ; MAKE AN INDEX INTO ROOM DESC + SUB CX,80 ; SCALE WITHIN 80 - WIDTH + MOV SI,4 ; SKIP SCORE PTR'S IN TABLE + JMP TSET3 ; FIX VALUES IN THE TABLE WITH CX +TSET2: MOV AX,15 ; MAKE AN INDEX INTO ROOM DESC BUFFER + SUB CX,40 ; SCALE WITHIN 40 - WIDTH + SUB SI,SI ; SI INDEXES INTO SCORE v. TIME +TSET3: SUB AX,CX ; BACKUP THE PTR IN BUFFER + ADD AX,[BX][SI] ; GET OFFSET TO BUFFER BEGINNING + MOV BX,2[BX][SI] ; GET OFFSET TO TABLE BEGINNING + TEST CX,CX ; SEE IF CX IS LESS THAN ZERO + JG TSET4 ; SKIP FIRST PATCH IF POSITIVE + ADD 6[BX],CX ; THESE PATCHES ADJUST THE RANGES FOR + ;+EACH OF THE STATUS LINE FIELD ACCORDING + ;+TO THE CALCULATED LENGTH OF THE STATUS + ;+LINE +TSET4: ADD 12[BX],CX ; PATCH CX INTO THESE TABLE OFFSETS + ADD 14[BX],CX ; CX HAS DIFFERENCE BET TERM W & 80 + ADD 20[BX],CX + ADD 22[BX],CX +TSET5: MOV SLSTR,AX ; SAVE STATUS LINE BUFFER ADDR IN HERE + MOV SLTAB,BX ; AND STATUS LINE TABLE ADDR IN HERE + CALL MINIT + RET +TSETUP ENDP + + + PUBLIC ZIPBGN,STR5$,STR8$,STR9$,STR10$,STR11$,STR12$,STR12A + PUBLIC STR12B,STR13$,STR14$,STR15$,STR17$ +ZIPBGN PROC + CALL SYSINI ;DO ANY SYSTEM INITIALIZATION +STR5$: SUB AX,AX ;BLOCK 0 + SUB BX,BX ;PUT AT BEGINNING OF GAME SEGMENT + CALL GETBLK ;GET THE BLOCK + MOV GAMEIN,1 ; (7q) INDICATE RELIABILITY OF SCRIPT BIT + CMP BYTE PTR ES:[PVERS1],ZMVERS ;PROPER Z-MACHINE VERSION? + JNE STR8$ ;NO + TEST BYTE PTR ES:[PVERS2],1 ;YES,PROPER MODE BITS? + JE STR9$ ;YES +STR8$: FATAL FTL4 ;SOMETHING WRONG, DIE +STR9$: TEST BYTE PTR ES:[PVERS2],2 ;TIME MODE REQUESTED? + JE STR10$ ;NO + INC TIMEMD ;YES, SET TIME-MODE FLAG +STR10$: MOV AL,BYTE PTR ES:[PVERS2] + CMP SLFLG,0 + JNE STR11$ + OR AL,10H ;TURN ON THE NO STATUS LINE BIT + MOV BYTE PTR ES:[PVERS2],AL +STR11$: TEST SCROLL,1 ; (7) CAN WE SPLIT THE SCREEN + JNZ STR11A ; (7) GUESS NOT... + MOV AL,BYTE PTR ES:[PVERS2] + OR AL,SCRBIT ; (7) TURN ON BIT FOR SPLIT + MOV BYTE PTR ES:[PVERS2],AL ;(7) SAVE IT +STR11A: GTAWRD A,[PZRKID] ;UNIQUE GAME & VERSION INDENTIFIER + MOV ZORKID,AX + GTAWRD A,[PENDLD] ;GET ENDLOD POINTER + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR12$ + AND AX,0FE00H + ADD AX,200H +STR12$: MOV CX,AX + MOV BP,CX ;EXTRACT ENDLOD BLOCK + MOV CL,9 + SAR BP,CL + MOV CX,BP + MOV ENDLOD,CX ;SAVE ENDLOD BLOCK NUMBER + MOV AX,128 ;(6) FIGURE BOUNDRY FOR SEG1 + SUB AX,CX ;(6) SUBTRACT AMOUNT IN PRELOD + SHL AX,1 ;(6) MULTIPLY IT BY #BYTES PER + SHL AX,1 ;(6) ENTRY IN PAGTAB FOR SCALING + MOV SEGEND,AX ;(6) USED TO COMPARE TO PAGTAB TO LOCATE + ;(6) SEGMENT IN WHICH GAMEBLOCK RESIDES + DEC CX ;NUMBER OF BLOCKS LEFT TO LOAD + CMP FITS,1 ;(6) READ THE WHOLE GAME IN + JNE STR12A ;(6) NO, DON'T READ IT ALL IN + MOV CX,127 ;(6) TWO 64K READS + MOV AX,1 ;(6) STARTING WITH BLK 1 + MOV LPTAB,1 ;(6) STARTING LOCATION + CALL GTBLKS + MOV CX,127 ;(6) READ ALL BUT 1/2K + MOV LPTAB,128 ;(6) READ INTO SEG1 + MOV AX,128 ;(6) THE LAST 64K BLKS + CALL GTBLKS + JNZ STR12$$ ;(8) READ LAST BLOCK? + MOV CX,1 ;(8) READ ONE MORE BLOCK + MOV AX,255 ;(8) LAST BLOCK NUMBER + MOV LPTAB,255 ;(8) PAGE LOCATION + CALL GTBLKS ;(8) GET IT +STR12$$:MOV LPTAB,0 + JMP STR12B +STR12A: MOV AX,1 ;STARTING WITH BLOCK 1 + MOV BX,OFFSET PAGTAB ; (6) GET A BUFFER ADDRESS + ADD BX,4 ; (6) SECOND ENTRY + MOV LPTAB,BX ; (6) SAVE THIS CALCULATED ADDR + CALL GTBLKS ;GET THE BLOCKS +STR12B: GTAWRD A,[PVOCTB] ;VOCAB LOCATION + MOV VOCTAB,AX ;SAVE VOCABULARY TABLE POINTER + GTAWRD A,[POBJTB] ;GET OBJECT TABLE POINTER + MOV OBJTAB,AX + GTAWRD A,[PGLOTB] ;GET GLOBAL TABLE POINTER + MOV GLOTAB,AX + GTAWRD A,[PWRDTB] ;GET WORD TABLE POINTER + MOV WRDTAB,AX + GTAWRD A,[PPURBT] ;GET PURE CODE POINTER + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR13$ + ADD AX,200H +STR13$: MOV CL,9 ;EXTRACT BLOCK NUMBER + SAR AX,CL + AND AX,7FH ;CLEAR UNWANTED BITS + MOV PURBOT,AX ;SAVE IT + MOV BX,OFFSET RBRKS ;START OF READ BREAK CHARACTER TABLE + MOV SI,VOCTAB ;VOCAB TABLE POINTER + MOV CL,BYTE PTR ES:[SI] ;1ST BYTE IN VOCTAB IS # OF SIBREAKS + SUB CH,CH ;CLEAR HIGH BYTE + INC SI +STR14$: MOVM [BX],ES:[SI],AL ;TRANSFER THEM + INC BX + INC SI + LOOP STR14$ + MOV ESIBKS,BX ;REMEMBER END OF SI BREAKS + MOV BP,OFFSET IRBRKS;ALWAYS END WITH INITIAL BREAK CHARACTERS +STR15$: MOVM [BX],[BP],AL ;(6)TRANSFER THEM + INC BX + INC BP + CMP AL,0 + JNE STR15$ + MOV AL,ES:[SI] ;GET VOCABULARY ENTRY LENGTH + SUB AH,AH + MOV VWLEN,AX ;AND STORE IT AWAY + INC SI + GTAWRD A,[SI] ;GET NEXT WORD IN TABLE + MOV VWORDS,AX ;NUMBER OF WORD ENTRIES IN VOCABULARY + ADD SI,2 ;MOVE TO NEXT WORD + MOV VOCBEG,SI ;BEGINNING OF ACTUAL VOCABULARY + + MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + MOV CL,9 + SHL SI,CL ;THIS IS FIRST LOCATION (ES:) OF PAGING + MOV PAGES,SI ;SAVE THIS TO USE AS AN OFFSET + + CALL MTIME +STR17$: JMP START1 +ZIPBGN ENDP + + ;RESTART EXECUTION HERE + PUBLIC RESTRT,RESTRT1,START1 +RESTRT PROC + CALL GAMOPEN ; (7q) OPEN THE GAME FILE + MOV MORLIN,0 ; (7s) RESET MORE COUNT + SUB AX,AX ;REREAD ALL OF THE IMPURE STUFF + MOV CURSEG,0 ; (K5) SET SEG FLAGS BACK TO SEG0 + MOV ZPCSEG,0 + MOV LPTAB,0 ; (6) FILL THE FIRST BIT OF STUFF + PUSH PAGES ; (6) SAVE THIS VARIABLE + MOV PAGES,0 ; (6) RESET IT FOR SMALL MEMORY READ + MOV CX,PURBOT + CALL GTBLKS + POP PAGES ; RESET IT AGAIN + MOV AH,SCRFLG ; (7o) WERE WE SCRIPTING + XOR AL,AL ; (7o) ZERO THIS + MOV WORD PTR ES:[PFLAGS],AX ; (7o) RESTORE SCRIPTING STATE + TEST SCROLL,1 ; (7) CAN WE SCROLL? + JNZ RESTRT1 ; (7) NEVER COULD, SKIP RE-INITS + OR BYTE PTR ES:[PVERS2],SCRBIT ; (7) TURN ON SPLIT + MOV TOPLIN,TOPSCR ; (7) FIX SCREEN VARIABLES ON RESTART + MOV SCRNFLG,0 ; (7) WHOLE SCREEN, ONLY 1 + MOV SPLTFLG,0 ; (7) NO SPLIT SCREEN + JMP RESTRT1 ; PATCH TO FIX STATUS LINE BUG (5)/PHG +START1: + + CALL TSETUP ;SETUP TERMINAL/STATUS LINE +RESTRT1:CALL CLRSCR ;CLEAR THE REMAINDER OF SCREEN + +; MOV AL,BYTE PTR ES:[PVERS2] +; ADD AL,8 ;TANDY BIT +; MOV BYTE PTR ES:[PVERS2],AL + + MOV SP,OFFSET STK_TOP ;INITIALIZE OUR STACK POINTER + MOV DI,OFFSET ZSTK_TP ;INITIALIZE USER STACK POINTER + MOV CHRPTR,OFFSET OUTBUF ;INITIALIZE OUTPUT CHARACTER POINTER + MOV ZLOCS,DI ;LOCALS WOULD START AT FIRST SLOT, + SUB ZLOCS,2 ;IF THERE WERE ANY + GTAWRD A,[PSTART] ;GET STARTING LOCATION + CALL BSPLTB ;SPLIT BLOCK & BYTE POINTERS + MOV ZPC1,AX ;INITIALIZE ZPC BLOCK-POINTER + MOV ZPC2,BX ;INITIALIZE ZPC BYTE-POINTER + CALL NEWZPC ;GET PAGE TO EXECUTE + JMP NXTINS +RESTRT ENDP + + ;MAIN INSTRUCTION INTERPRETATION LOOP + PUBLIC NXTINS,NXI0A$,NXI0B$,NXI0C$,NXI1$,NXI2$,NXI3$,NXI4$,NXI5$ + PUBLIC NXI6$,NXI7$,NXI8$,NXI8A$,NXI9$,NXI10$,NXI11$,NXI12$,NXI14$,NXI15$ +NXTINS PROC + CALL NXTBYT ;GET THE OPERATION BYTE + MOV DX,AX ;SAVE A COPY + CMP AX,80H ;IS IT A 2OP? + JL NXI9$ ;YES + CMP AX,0B0H ;NO, IS IT A 1OP? + JGE NXI0A$ ;NO + JMP NXI12$ ;YES +NXI0A$: CMP AX,0C0H ;IS IT A 0OP? + JG NXI0B$ ;NO + JMP NXI13$ ;YES +NXI0B$: AND AX,3FH ;IT'S EXTENDED, GET THE OPCODE + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET THE OPERATOR POINTER + MOV SI,[BP+EXTOP] ; (6) REMOVED DS OVERRIDE + CMP SI,0 + JNE NXI0C$ ;OPERATION EXISTS + JMP NXI14$ ;NO SUCH OPERATION +NXI0C$: CALL NXTBYT ;GET THE ARGUMENT BYTE + MOV CX,4 ;SPLIT IT INTO 4 2-BIT MODE BYTES +NXI1$: PUSH AX + SAR AX,1 + SAR AX,1 + LOOP NXI1$ + MOV CX,4 ;RETRIEVE THE 4 BYTES IN PROPER ORDER + SUB DX,DX + MOV BX,OFFSET ARGBLK;FIRST ARGUMENT SLOT +NXI2$: POP AX ;GET NEXT MODE BYTE? + AND AX,3 ;CLEAR OFF UNWANTED BITS + CMP AX,3 ;NO MORE ARGUMENTS? + JE NXI4$ ;YES, FLUSH ANY OTHER MODE BYTES + CALL GETARG ;ELSE, GET THE NEXT ARGUMENT + MOV [BX],AX ;SAVE IT IN ARGUMENT BLOCK + ADD BX,2 + INC DX ;REMEMBER NUMBER OF ARGS GOTTEN +NXI3$: LOOP NXI2$ ;LOOP FOR REST OF MODE BYTES + JMP NXI5$ +NXI4$: DEC CX ;DETERMINE NUMBER OF REMAINING MODE BYTES + SHL CX,1 ;WORD COUNT + ADD SP,CX ;FLUSH THEM +NXI5$: XCHG CX,DX + MOV AX,CX ;NUMBER OF ARGS GOES HERE FOR OPERATOR TO USE + CMP BYTE PTR [SI],90H ;(6)DOES OPERATOR WANT ARGBLK POINTER? + JE NXI8A$ ;YES, CALL OPERATOR NOW + DEC CX ;NO, IT WANTS ARGS IN REGISTERS + JL NXI8A$ ;NO ARGS, JUST CALL OPERATOR + JE NXI8$ ;1 ARG, GET IT + SUB CX,2 + JL NXI7$ ;2 ARGS + JE NXI6$ ;3 ARGS + MOV DX,ARGBLK[6] ;ELSE, 4 ARGS, GET 4TH +NXI6$: MOV CX,ARGBLK[4] ;GET 3RD +NXI7$: MOV BX,ARGBLK[2] ;GET 2ND +NXI8$: MOV AX,ARGBLK ;GET FIRST ARG +NXI8A$: JMP NXI15$ ;AND CALL OPERATOR +NXI9$: AND AX,1FH ;2OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;FIND POINTER TO OPERATOR ROUTINE + MOV SI,[BP+EXTOP] ;(6) REMOVED DS OVERRIDE + CMP SI,0 + JE NXI14$ ;NO SUCH OPERATION + MOV AX,1 ;ASSUME FIRST ARG IS AN IMMEDIATE + TEST DX,40H ;IS IT INSTEAD A VARIABLE? + JE NXI10$ ;NO + INC AX ;YES, CHANGE MODE +NXI10$: CALL GETARG ;GET THE FIRST ARG + PUSH AX ;SAVE IT + MOV AX,1 ;ASSUME SECOND ARG IS AN IMMEDIATE + TEST DX,20H ;IS IT INSTEAD A VARIABLE? + JE NXI11$ ;NO + INC AX ;YES, CHANGE MODE +NXI11$: CALL GETARG ;GET THE SECOND ARG + MOV BX,AX ;POSITION IT + POP AX ;RECOVER FIRST ARG + CMP BYTE PTR [SI],90H ;(6)DOES ROUTINE WANT ARGUMENT BLOCK? + JNE NXI15$ ;NO, GO CALL IT + MOV ARGBLK,AX ;YES, MOVE ARGS TO ARGBLK + MOV ARGBLK[2],BX + MOV AX,2 ;ALWAYS 2 ARGS + JMP NXI15$ ;NOW CALL OPERATOR +NXI12$: AND DX,0FH ;1OP, EXTRACT OPERATION BITS + SHL DX,1 ;MAKE IT A WORD OFFSET + MOV BP,DX ;GET OPERATOR ROUTINE POINTER + MOV SI,[BP+ONEOP] ;(6) REMOVED DS OVERRIDE + CMP SI,0 + JE NXI14$ ;ILLEGAL OPERATION + SAR AX,1 ;EXTRACT MODE BITS + SAR AX,1 + SAR AX,1 + SAR AX,1 + AND AX,3 + CALL GETARG ;GET THE ARGUMENT + JMP NXI15$ ;AND CALL OPERATOR +NXI13$: AND AX,0FH ;0OP, EXTRACT OPERATION BITS + SHL AX,1 ;MAKE IT A WORD OFFSET + MOV BP,AX ;GET OPERATOR ROUTINE POINTER + MOV SI,[BP+ZEROOP] ; (6) REMOVED DS OVERRIDE + CMP SI,0 + JNE NXI15$ ;IT'S A LEGAL OPERATION +NXI14$: FATAL FTL5 ;OTHERWISE, COMPLAIN +NXI15$: CALL SI ;CALL THE OPERATOR ROUTINE + JMP NXTINS ;AND LOOP FOR NEXT INSTRUCTION +NXTINS ENDP + + SUBTTL PAGING ROUTINES + PAGE + + + ;NORMALIZE ZPC & GET PROPER PAGE +; NEWZPC HAS BE EXTENDED TO UPDATE THE ZPCSEG VARIABLE. IT SETS THIS +; VARIABLE DIFFERENTLY ACCORDING TO PAGING SCHEME. IF THE GAME FITS IN +; MEMORY, ZPCSEG IS SET ACCORDING TO THE 17TH BIT OF THE ZPC, OTHERWISE +; IT IS SET WHEN CURSEG IS SET BY THE GETPAG ROUTINE INDICATING THAT +; THE CURRENT BLOCK IN THE SECOND ES SEGMENT. +; + PUBLIC NEWZPC,NWZ1$,NWZ2$,NWZ3$,NWZ4$,NWZ5$ +NEWZPC PROC + PUSH SI ;SAVES + PUSH BP + PUSH BX + PUSH CX + PUSH DX + SUB AX,AX ;USE DOUBLE-WORD ARITHMETIC + MOV BX,ZPC1 ;GET BLOCK-POINTER + MOV BH,BL ;POSITION IT + SUB BL,BL + SHL BX,1 + ADC AX,0 + MOV SI,ZPC2 ;GET BYTE-OFFSET + XCHG SI,AX ;DOUBLE-WORDIFY IT (MIGHT BE NEGATIVE) + CWD + XCHG SI,AX + ADD BX,SI ;ADD IT TO OTHER DOUBLE WORD + ADC AX,DX + MOV DX,BX + AND DX,1FFH ;EXTRACT BYTE-OFFSET + MOV ZPC2,DX ;SAVE IT + MOV CL,9 ;EXTRACT BLOCK-POINTER + SAR BX,CL + AND BX,7FH + TEST AX,1 ;TEST 17TH BIT + JE NWZ1A$ ;WAS 0 + OR BX,80H ;WAS 1, SET PROPER BIT IN BLOCK-POINTER + TEST FITS,1 ;(6) DO WE HAVE ALL OF THE GAME IN MEMORY + JZ NWZ1$ ; (6) BECAUSE PAGES ARE NOT CONTINUOUS + MOV ZPCSEG,1 ; WERE IN THE UPPER GAME SEG + JMP NWZ1$ +NWZ1A$: TEST FITS,1 ;(6) SHOULD WE SET THIS HERE + JZ NWZ1$ ;(6) NO + MOV ZPCSEG,0 ;(6) SET SEGMENT TO BASE SEG +NWZ1$: MOV ZPC1,BX ;SAVE IT + TEST ZPCFLG,1 ;(7n) DO WE HAVE THE RIGHT BLOCK + JNZ NWZ1Q$ ;(7n) NO, SKIP THIS SKIP + CMP BX,CURBLK ;HAS IT CHANGED? + JE NWZ5$ ;NO +NWZ1Q$: MOV CURBLK,BX ;YES, REMEMBER NEW BLOCK + MOV AX,CURTAB ;IS OLD PAGE IN PAGING SPACE? + CMP AX,0 + JE NWZ2$ ;NO + MOV BP,AX ;YES, STORE CURRENT REF TIME FOR OLD PAGE + MOVM [BP],RTIME1,CL ;(6) REMOVED DS OVERRIDE + MOVM [BP+1],RTIME2,CX ;(6) REMOVED DS OVERRIDE + INC AX +NWZ2$: CMP FITS,1 ;(6) IS THE WHOLE GAME THERE + JZ NWZ3$ ;(6) YES, GO DO WHATEVER + CMP BX,ENDLOD ;NEW PAGE ALREADY IN CORE? + JL NWZ3$ ;YES + MOV AX,BX ;NO, GET NEW PAGE + CALL GETPAG + MOV BL,CURSEG ;(6) SET ZPCSEG TO SAME AS CURSEG + MOV ZPCSEG,BL ;(6) SO THAT NXTBYT WORKS + MOV BX,AX + MOV AX,LPTAB ;GET NEW PAGE TABLE POINTER + INC AX ;POINT TO REF SLOT + MOV CURTAB,AX ;SAVE THIS POINTER FOR LATER + MOV BP,AX ;STORE HIGHEST RTIME TO KEEP PAGE FOR US + MOV BYTE PTR [BP],-1 ;(6) REMOVED DS OVERRIDE + MOV WORD PTR [BP+1],-1 ;(6) REMOVED DS OVERRIDE + INC AX + JMP NWZ4$ +NWZ3$: MOV CL,9 ;CALCULATE PAGE ADDRESS + SHL BX,CL + TEST FITS,1 + JNZ NWZ3A$ ; (7z) SKIP DURING WHOLE MEMORY EDITION + MOV ZPCSEG,0 ; (7z) RESET THIS TO SEG0 +NWZ3A$: MOV CURTAB,0 ;CLEARING POINTER MEANS PAGE IS PRELOADED +NWZ4$: MOV CURPAG,BX ;UPDATE PAGE POINTER +NWZ5$: MOV ZPCFLG,0 ; (K3) RESET THIS FLAG + POP DX ;RESTORES + POP CX + POP BX + POP BP + POP SI + RET ;AND RETURN +NEWZPC ENDP + + ;GET THE PAGE WHOSE NUMBER IS IN AX, RETURN A POINTER TO IT IN AX +; GETPAG AND FINDPG WERE MODIFIED TO ACCOMMODATE THE EXTENDED PAGING +; SCHEMES. SEGEND, CURSEG AND PAGTAB ARE SIGNIFICANT VARIABLES IN THESE +; MODIFICATIONS. SEGEND IS USED TO COMPARE TO THE CURRENT LOCATION IN +; PAGTAB WHICH IN TURN INDICATES IN WHICH SEGMENT THE NEW BLOCK IS LOCATED. +; CURSEG IS SET TO TELL THE OUTSIDE WORLD WHICH SEGMENT THE LAST GETPAG +; TOUCHED. NOTE THAT BEING IN THE SECOND SEGMENT (SEG1) REQUIRES THAT +; ADDRESS CALCULATIONS DO NOT ADD IN PAGES (THE VARIABLE MARKING THE END +; OF PRELOAD). THIS REQUIREMENT IS NECESSARY BECAUSE THERE IS NO PRELOAD +; IN THE SECOND SEGMENT. +; + PUBLIC GETPAG,GTP1$,GTP2$,GTP2A$,GTP2B,GTP2C,GTP3$,GTP4$ +GETPAG PROC + CMP AX,LPAGE ;IS THIS THE SAME PAGE AS LAST REFERENCED? + JNE GTP1$ ;NO + MOV AX,LPLOC ;YES, WE ALREADY HAVE LOCATION + RET ;RETURN IT +GTP1$: MOV LPAGE,AX ;SAVE NEW PAGE NUMBER + PUSH CX ;SAVES + PUSH BX + ADD RTIME2,1 ;UPDATE REFERENCE TIME (COUNT) + ADC RTIME1,0 + MOV BX,OFFSET PAGTAB;PAGE INFORMATION TABLE +GTP2$: INC BX + CMP AL,[BX-1] ;SEARCH FOR DESIRED BLOCK + JNE GTP3$ ;NOT IT + CMP AX,CURBLK ;IS THIS THE CURRENT CODE PAGE? + JE GTP2A$ ;DON'T UPDATE REFERENCE TIME + MOVM [BX],RTIME1,CL ;FOUND IT, UPDATE ITS REFERENCE TIME + MOVM [BX+1],RTIME2,CX +GTP2A$: DEC BX ;BACKUP TO BEGINNING OF TABLE ENTRY + PUSH BX ; (6) SAVE THIS BEFORE SCALING IT + SUB BX,OFFSET PAGTAB;(6) BASIFY THE PAGTABLE ENTRY + CMP BX,SEGEND ;(6) CHECK IF PAGE IS IN 2ND SEGMENT + POP BX ; (6) RESTORE BX + JL GTP2B ;(6) NO, FUNCTION AS USUAL + MOV CURSEG,1 ;(6) YES, SET SEGMENT NUMBER FLAG + JMP GTP2C ;(6) SKIP SETTING TO ZERO +GTP2B: MOV CURSEG,0 ;(6) SET SEGMENT NUMBER TO 0 +GTP2C: MOV LPTAB,BX ;SAVE IT + SUB BX,OFFSET PAGTAB;CALCULATE ADDRESS OF PAGE + TEST CURSEG,1 ;(6) DO A DIFFERENT CALC FOR SEG1 + JZ GTP2D ; + SUB BX,SEGEND ; (6) FIGURE OFFSET INTO SEG1 +GTP2D: MOV CL,7 + SHL BX,CL + TEST CURSEG,1 ; (6) SKIP ADDING IN PAGES IF SEG1 + JNZ GTP4$ + ADD BX,PAGES + JMP GTP4$ ;AND RETURN PAGE POINTER +GTP3$: ADD BX,3 ;SKIP REFERENCE TIME + CMP WORD PTR [BX],-1;END OF TABLE? + JNE GTP2$ ;NO, CONTINUE SEARCH + CALL FINDPG ;YES, FIND A PAGE TO LOAD INTO + PUSH AX ;PAGE POINTER + MOV LPTAB,BX ;SAVE PAGE TABLE POINTER + MOV AX,LPAGE ;SAVE NEW BLOCK NUMBE + MOV [BX],AL + MOVM [BX+1],RTIME1,CL;AND CURRENT REF TIME + MOVM [BX+2],RTIME2,CX + POP BX ;PAGE POINTER + CALL GETBLK ;GET THE BLOCK +GTP4$: MOV AX,BX ;RETURN PAGE POINTER + MOV LPLOC,AX ;AND SAVE IT FOR LATER + POP BX ;RESTORES + POP CX + RET +GETPAG ENDP + + ;FIND A GOOD PAGE, RETURN PAGE POINTER IN AX & PAGTAB POINTER IN BX +; SEE COMMENTS UNDER GETPAG + PUBLIC FINDPG,FNP1$,FNP2$,FNP3$,FNP4$ +FINDPG PROC + PUSH CX + MOV BX,OFFSET PAGTAB + MOV CX,-1 ;FAKE BEST-CASE REFERENCE COUNT + MOV DX,CX + INC BX ;SKIP BLOCK NUMBER FOR NOW +FNP1$: INC BX ;IS THIS REF TIME WORSE THAN CURRENT WORST? + CMP [BX-1],CL + JA FNP3$ ;NO + JB FNP2$ ;YES + CMP [BX],DX ;MAYBE, COMPARE LOW-ORDER WORDS, WORSE? + JAE FNP3$ ;NO +FNP2$: MOV CL,[BX-1] ;YES, SAVE ITS REF COUNT + MOV DX,[BX] + MOV AX,BX ;AND LOCATION (+2) +FNP3$: ADD BX,3 ;SKIP SECOND WORD + CMP BYTE PTR [BX-1],-1 ;LOOP UNTIL END OF TABLE + JNE FNP1$ + INC CX ;WAS A PAGE REALLY FOUND? + JE FNP4$ ;NO, GROSS BUG! + SUB AX,2 ;YES, CALCULATE CORE LOCATION OF PAGE + + MOV BX,AX + SUB AX,OFFSET PAGTAB + CMP AX,SEGEND ; (6) CHECK SEGMENT + JL FNP5$ ; (6) IN SEG0, SET CURSEG + MOV CURSEG,1 ; (6) SET CURSEG TO SEG1 + SUB AX,SEGEND ; (6) SCALE DOWN THE PAGE PTR + JMP FNP6$ +FNP5$: MOV CURSEG,0 +FNP6$: MOV CL,7 + SHL AX,CL + TEST CURSEG,1 ; (6) DON'T ADD IN PAGES IF IN SEG1 + JNZ FNP7$ + ADD AX,PAGES +FNP7$: POP CX ;RESTORES + RET +FNP4$: FATAL FTL6 +FINDPG ENDP + + SUBTTL HIGH LEVEL IBMPC DEPENDENT STUFF + + ;SYSTEM INITIALIZATION +; SYSINI HAS BEEN GREATLY MODIFIED TO INCLUDE DOS 2.0 FILE HANDLING, +; COMMAND LINE ARGUMENTS, COPY PROTECTION, AND DYNAMIC ALLOCATION OF +; PAGING SPACE. +; +; THE COPY PROTECTION SCHEME WORKS AS FOLLOWS: A NUMBER OF COMPUTERS ARE +; DEFINED AS COMPATIBLE WITH IBM IN THE DATA DECLARATIONS. INCLUDED FOR +; EACH IS THE FIRST 9 LETTERS OF THE COPYRIGHT NOTICE THAT EXISTS IN THE +; ROM. IF ANY OF THESE STRINGS IS FOUND IN THE ROM, COPY PROTECTION IS +; CHECKED, OTHERWISE IT IS NOT. IBM COMPATIBILITY MEANS TOTAL ROM BIOS +; COMPATIBILITY SUCH THAT WINDOWED SCROLLING AND SPECIAL DISK I/O MAY BE +; PERFORMED. NOT FINDING ANY OF THESE STRINGS RESULTS IN THE ZIP FUNCTIONING +; AS IF IT WERE ON A GENERIC MS-DOS BASED MACHINE. +; +; COMMAND LINE ARGUMENTS SET BITS IN THE VARIABLE CMDLIN IN THE ROUTINE +; SCANCMD. CMDLIN THEN AFFECTS VARIOUS PARAMETERS AND VARIABLES EITHER IN +; SYSINI OR SSETUP. +; +; THE PAGTAB IS SET UP ACCORDING TO AVAILABLE MEMORY. THERE EXISTS A WORD +; AT OFFSET 2 IN THE PSP (PROGRAM SEGMENT PREFIX, OR WHERE CS POINTS) WHICH +; INDICATES THE TOP OF PHYSICAL MEMORY. PAGTAB REPRESENTS THE LAST WORD USED +; BY THE ZIP. THE CODE SEGMENT REPRESENTS THE AMOUNT OF MEMORY TAKEN UP BY +; EVERYTHING UNDER THE ZIP SUCH AS THE OPERATING SYSTEM AND DEVICE DRIVERS. +; IF WE CONVERT PAGTAB TO PARAGRAPHS, THEN ALL OF THESE NUMBERS ARE IN +; PARAGRAPHS. SO: +; +; TOP_OF_MEM - (CS + PAGTAB) --> AVAILABLE MEMORY IN PARAGRAPHS +; +; AVAILABLE MEMORY IS CONVERTED INTO THE NUMBER OF BUFFERS AVAILABLE. FROM +; THIS NUMBER WE MUST SUBTRACT 1 OR 2 BUFFERS TO ALLOW FOR THE PAGTAB TO +; BE BUILT. KNOWING AVAILABLE BUFFERS TELLS US THE LENGTH OF OUR PAGTAB +; SINCE OUR PAGTAB IS 4 BYTES/BUFFER. AT THE NEXT PARAGRAPH BOUNDARDY BEYOND +; THE PAGTAB WE HAVE OUR FIRST GAME SEGMENT WHICH WILL BE MOVED TO ES AND +; STORED IN THE VARIABLE GAMESEG. ADDING 64K (IN PARAGRAPHS) TO GAMESEG +; WE ARRIVE AT OUT LOCATION FOR SEG1, THE SECOND GAME SEGMENT. THE PAGTAB +; IS THEN INITIALIZED. +; + PUBLIC SYSINI,SYS1,INITLP,SYSFTL +SYSINI PROC + MOV AH,DOSVER ; (7) GET DOS VERSION # + INT 21H ; (7) MUST BE 2.0 OR HIGHER + CMP AL,2 ; (7) DOS 2.0+ + JGE GOODOS + FATAL FTL11 ; (7) DIE APPROPRIATELY +GOODOS: MOV AH,CURDSK ; (6) GET DEFAULT DRIVE + INT 21H ; (6) FROM DOS + MOV DEFDRV,AL ; (6) SAVE DEFAULT DRIVE + MOV CURDRV,AL ; (6) SAVE DEFAULT DRIVE + CALL SCANCMD ; (7) GET CMD LINE VARS + MOV AX,BIOSEG ; (7) GET SEG OF BIOS + MOV ES,AX ; (7) MAKE ADDRESSIBLE + MOV BX,COMPATS ; (7) GET NUMBER OF COMPATIBLES + MOV AX,OFFSET COMP1 ; (7) CHECK FOR COPYRIGHT +SYS$: MOV DX,9 ; (7) LENGTH FOR MATCHING STRING + MOV DI,BIOSOFF ; (7) OFFSET INTO BIOS TO CHECK + MOV CX,7000H ; (7) SEARCH THIS MANY BYTES + CALL CHK ; (7) LOOK FOR COPYRIGHT NOTICE + JNC GOTONE ; (7) JMP ON A MATCH + ADD AX,10 ; (7) ADVANCE TO NEXT STRING + DEC BX ; (7) DO WE HAVE ANOTHER STRING + JNZ SYS$ ; (7) YES, LOOK AT IT + JMP NOCMD ; (7) SKIP COPY PROTECT CHECK +GOTONE: MOV SCROLL,0 ; (7) USE WINDOWED SCROLLING + CALL CHKCOP ; (7) CHECK COPY PROTECTION + JNC NOCMD ; (7) CONTINUE ON + FATAL FTL10 +NOCMD: MOV AH,CFOPENZ ; (6) ASCIZ STRINGS + MOV AL,0 ; (6) OPEN FOR READING + MOV DX,OFFSET GAMFILE + INT 21H + JNC SYSA$ + JMP SYSFTL +SYSA$: MOV GAMHNDL,AX ; (6) SAVE THE FILE HANDLE + MOV BX,AX ; (7n) GET FILE HANDLE INTO BX + XOR CX,CX ; (7n) ZERO THESE + XOR DX,DX ; (7n) TO FIND EOF + MOV AH,CFSEEK ; (7n) SEEK TO END OF FILE + MOV AL,2 ; (7n) MOVE FILE PTR TO EOF + INT 21H ; (7n) DO IT + MOV CL,4 ; (7n) CONVERT AX TO PARAGRAPHS + SHR AX,CL ; (7n) TO SAVE AS FILESIZE + TEST DX,DX ; (7n) DO WE HAVE A 17TH BIT? + JZ SYSB$ ; (7n) NOPE + OR AH,10H ; (7n) TURN ON THAT BIT +SYSB$: MOV CL,5 ; (7n) REDUCE TO NUMBER OF 512 BLKS + SHR AX,CL ; (7n) FOR COMPARISON TO BUFFERS + MOV GAMESIZ,AX ; (7n) SAVE THIS SIZE FOR FITS + + XOR CX,CX ; (7w) MOVE POINTER TO BOF + MOV DX,4 ; (7w) WE WANT THE WORD AT OFFSET 4 + MOV AH,CFSEEK ; (7w) SEEK THERE + MOV AL,0 ; (7w) METHOD: OFFSET FROM BOF + INT 21H ; (7w) BX HAS FILE HANDLE + MOV AH,CRDRNDZ ; (7w) READ IN THE FIRST + MOV CX,2 ; (7w) READ THE WORD OF ENDLOD + MOV DX,OFFSET SSBUF ; (7w) ANY BUFFER BIG ENOUGH WILL DO + INT 21H ; (7w) READ IT + MOV AX,SSBUF ; (7w) GET THE WORD + XCHG AH,AL ; (7w) FLOP THE BYTES + TEST AX,1FFH ; (7w) ROUND UP TO NEXT BLOCK + JE SYSC$ + AND AX,0FE00H ; (7w) TURN OF LOW BITS + ADD AX,200H ; (7w) ADD A BLOCK +SYSC$: MOV CL,9 ; (7w) CONVERT TO NUMBER OF BLOCKS + SAR AX,CL + MOV DX,AX ; (7w) AND SAVE NUMBER IN DX + + MOV BX,2 ; (6) GET TOP OF MEMORY + MOV BX,CS:[BX] ; (6) FROM OUT OF THE PSP + MOV AX,CS ; (6) GET CODE SEG + SUB BX,AX ; (6) SUB CSEG FROM TOPMEM + MOV CL,4 ; (6) SHIFT COUNT + MOV AX,OFFSET PAGTAB ; (6) USE OFFSET TO FIGURE PARAG'S + SHR AX,CL ; (6) REDUCE THIS OFFSET TO PARAS + INC AX ; (6) SKIP ONE PARAGRAPH + AND AX,0FE0H ; (7z) BLOCKIFY THIS NUMBER + ADD AX,20H ; (7z) OTHERWISE LOSE A PAGE + SUB BX,AX ; (6) YIELDS PARAS AVAILABLE + + TEST CMDLIN,4 ; (7) SET ON CMDLIN? + JZ SYS2 + CMP BX,MEMORY ; (7) REASONABLE REQUEST + JBE SYS2 ; (7) NO, NOT REALLY THERE + MOV BX,MEMORY ; (7) USE USER SETTING + +SYS2: CMP BX,MINMEM ; (7) AT LEAST 48K? + JAE SYS3 ; (7) YES + FATAL FTL12 ; (7) DIE APPROPRIATELY +SYS3: MOV CL,5 ; (6) DIVIDE BY 32 TO GET BUFFERS + SHR BX,CL ; (6) TO GET #BUFFERS + SUB BX,DX ; (7w) SUBTRACT ALL PRELOD BLOCKS + DEC BX ; (6) SUBTRACT 1 BUFFER FOR PAGTBL + CMP BX,128 ; (6) ABOVE 80H, WE NEED ANOTHER TBL + JL SYS1 ; (6) WE HAVE THIS MANY OR FEWER + DEC BX ; (6) TAKE AWAY ANOTHER PAGE + CMP BX,255 ; (6) THIS IS THE MOST WE WILL NEED + JLE SYS1 ; (6) DON'T MODIFY BX <= 255 + MOV FITS,1 ; (6) FLAG THAT GAME FITS IN MEMORY + MOV BX,255 ; (6) DON'T ALLOW MORE THAN THIS +SYS1: PUSH BX ; (7w) SAVE THIS FOR FIDDLING + ADD BX,DX ; (7w) ADD IN THE BLOCKS PREV SBTRCTED + CMP BX,GAMESIZ ; (7n) CHECK FOR LUCKY FIT + POP BX ; (7w) AND RESTORE ACTUAL #BUFFERS + JBE SYSD$ ; (7n) IF BX IS GREATER, NO GO + MOV FITS,1 ; (7n) IT DOES FIT AFTERALL!!! +SYSD$: MOV BUFFERS,BX ; (6) SAVE THIS NUMBER + SHL BX,1 ; (6) GET NUMBER OF BYTES IN PAGTBL + SHL BX,1 ; (6) 4 BYTES WIDE * BX BYTES LONG + INC BX ; (6) ADD 1 FOR TERMINATOR BYTE + ADD BX,OFFSET PAGTAB ; (6) CALC TABLE LOCATION + MOV CX,4 ; (6) REDUCE #BYTES IN TABLE = PARAS + SHR BX,CL ; (6) TO DYNAMICALLY ALLOCATE SPACE + MOV AX,DS ; (6) GET A COPY OF CURRENT SEG + ADD BX,AX ; (6) AND CALCULATE THE NEW SEG + ADD BX,1 ; (6) ADD ONE PARAGRAPH FOR SAFETY + MOV GAMESEG,BX ; (6) THIS WILL BE USED FOR ES:GAME + ADD BX,1000H ; (6) ADD 64K TO CALC 2ND SEG + MOV SEG1,BX ; (6) THIS IS SEG0+64K + CALL TBLINI ; (7n) CALL TABLE INITIALIZATION + CALL SSETUP + RET +SYSFTL: FATAL FTL9 +SYSINI ENDP + + + ; THIS ROUTINE INITIALIZES THE PAGE TABLE + ; +TBLINI PROC + PUSH SI ; SAVES + PUSH DI + PUSH AX + PUSH BX + PUSH CX + MOV DI,OFFSET PAGTAB ; (6) GET BEGINNING ADDR + MOV CX,WORD PTR BUFFERS ; (6) GET NUMBER OF ENTRIES + MOV AX,DS ; (7)GET DATA SEG + MOV ES,AX ; (7) FIX ES + CLD ;(6) AUTO INCREMENT +INITLP: MOV SI,OFFSET INITTBL ; (6) POINT TO STRING TO INITIALIZE + PUSH CX ; (6) SAVE REP COUNT + MOV CX,4 ; (6) GET INNER LOOP COUNT + REP MOVSB ; (6) TRANSFER THE STRING TO TBL + POP CX ; (6) RESTORE COUNT + LOOP INITLP ; (6) AND FINISH TABLE INITIALIZING + MOV WORD PTR [DI],-1 ; (6) DEPOSIT A -1 TO INDICATE END + MOV BX,GAMESEG ; + MOV ES,BX ; (6) SET THE EXTRA SEG TO GAMESEG + POP CX ; RESTORES + POP BX + POP AX + POP DI + POP SI + RET +TBLINI ENDP + + PUBLIC GAMOPEN + ; THIS PROCEDURE OPENS THE GAME FILE AFTER CLOSING ALL FILES. + ; IF THE GAME FILE IS NOT ON THE DISK, IT PROMPTS FOR REINSERTION +GAMOPEN PROC + PUSH DX + MOV DL,DEFDRV ; (7o) GET DRIVE WHERE GAME IS + MOV AH,CSELDSK ; (7o) TO MAKE OPEN WIN + INT 21H ; (7o) DO IT + MOV AH,CFCLOSZ ; (7s) TRY CLOSING INSTEAD OF RESET + MOV BX,GAMHNDL ; (7s) OF THE GAME FILE + INT 21H ; (7o) TO MAKE SURE THIS WINS +GOPEN0: MOV AH,CFOPENZ ; (6) ASCIZ STRINGS + MOV AL,0 ; (6) OPEN FOR READING + MOV DX,OFFSET GAMFILE ; (7o) OPEN THE FILE AGAIN + INT 21H + JNC GOPEN1 ; (7o) IF SUCCESS, CONTINUE + PRINT SAV3 ; (7o) OTHERWISE PROMPT + CALL MCHRI ; (7o) AND WAIT FOR A CHARACTER + JMP GOPEN0 ; (7o) AND LOOP +GOPEN1: MOV GAMHNDL,AX ; (7o) SAVE GAME HANDLE + MOV DL,CURDRV ; (7v) RESTORE SAVE DRIVE + MOV AH,CSELDSK ; (7v) SO THAT WE ARE NOT CONFUSED + INT 21H ; (7v) THANKS MAX + POP DX + RET +GAMOPEN ENDP + + ; GIVEN SOURCE PTR IN DS:AX, AND A DEST PTR IN ES:DI, CHK SEARCHES + ; FOR THE STRING POINTED TO BY DS:AX IN THE FIRST (CX) BYTES OF + ; THE STRING POINTED TO BY ES:DI + PUBLIC CHK +CHK PROC + CLD ; (7) CLEAR THE DIRECTION FLAG + PUSH SI ; (7) SAVE THIS + PUSH DX ; (7) SAVE THIS FOR RETRIES + MOV BP,SP ; (7) GET A FRAME POINTER + MOV SI,AX ; (7) SET UP FIRST OFFSET +LUP: CMP BYTE PTR [SI],'$' ; (7) END CHAR + JE MATCH ; (7) REACHING END==MATCH + CMPSB ; (7) COMPARE TWO BYTES + JNE RESET ; (7) RESET SOURCE IF MISMATCH + DEC DX + LOOP LUP ; (7) DECREMENT COUNTER AND TRY AGAIN + JMP RTFAIL ; (7) OUT OF CHARS, FAILED +RESET: MOV SI,AX ; (7) MOVE SOURCE PTR BACK INTO SI + MOV DX,[BP] ; (7) RESTORE NUMBER OF BYTES IN STR + LOOP LUP ; (7) TRY AGAIN +RTFAIL: STC ; (7) FAIL BY RETURNING CARRY SET + POP DX + POP SI ; (7) RESTORE SI + RET +MATCH: TEST DX,DX ; (7) MATCH OF ENTIRE STRING + JNZ RTFAIL + CLC ; (7) GOT A MATCH, RETURN CARRY CLEAR + POP DX + POP SI ; (7) RESTORE SI + RET +CHK ENDP + + ; THIS ROUTINE CHECKS THE COPY PROTECTION +CHKCOP PROC + CLC ; FOR NOW, EVERYTHING WORKS + RET +CHKCOP ENDP + + ; THIS ROUTINE SETS SOME VARIABLES ACCORDING TO THE CMD LINE +; CURRENTLY THE 6 /PARAMETERS ARE SUPPORTED. THE FIRST THREE, +; /P INITIALIZE PRINTER THROUGH INT 17 +; /M MONOCHROME +; /C COLOR +; /W WINDOWED SCROLLING +; /K AMOUNT OF MEMORY IN K +; ARE INTENDED FOR THE USER. A FOURTH WILL NOT BE DOCUMENTED IS +; /G WHICH WILL TEMPORARILY PATCH THE ZIP TO RUN THE +; GAME SPECIFIED. +; + PUBLIC SCANCMD,SCAN,SCAN0,SCAN1,SCAN2,SCAN3,SCAN4 + PUBLIC SCAN5,SCAN6,SCAN7,SCAN8 +SCANCMD PROC + CLD ; (7) AUTO INCREMENT + MOV SI,80H ; (7) GET # OF BYTES + LODSB ; (7) INTO AL + TEST AL,AL ; (7) ANY? + JNZ SCAN1 +SCAN0: RET ; (7) NONE THERE +SCAN1: DEC AL ; (7) CARRIAGE RETURN DOESN'T COUNT + XOR DX,DX ; (7) ZERO THIS + MOV DL,AL ; (7) SAVE NUMBER OF BYTES + ADD DX,82H ; (7) ADDR OF LAST BYTE+1 ON LINE + INC SI ; (7) SKIP INITIAL SPACE +SCAN: CMP SI,DX ; (7) END OF CMD LINE? + LODSB ; (7) GET A DELIMITER + JZ SCAN0 ; (7) YEP, RETURN + CMP AL,'/' ; (7) WAS IT THE DELIMITER + JNZ SCAN ; (7) GET NEXT VALID CHAR + LODSB ; (7) GOT DELIMITER, GET BYTE + AND AL,5FH ; (7) UPPERCASIFY + CMP AL,'M' ; (7) DO THEY WANT MONOCHROME + JNZ SCAN2 ; (7) NOPE, TRY NEXT + OR CMDLIN,1 ; (7) SET FLAG IN CMDLIN VARIABLE + JMP SCAN +SCAN2: CMP AL,'W' ; (7) WINDOWED SCROLLING? + JNZ SCAN3 + MOV SCROLL,0 ; (7) TURN ON SCROLLING + OR CMDLIN,8 ; (7) TURN ON 8 BIT + JMP SCAN +SCAN3: CMP AL,'G' ; (7) GAME FILE NAME? + JNZ SCAN5 ; (7) NOPE, CONTINUE ON... + MOV DI,OFFSET GAMFILE ; (7) MAKE THIS THE GAME +SCAN4: MOVSB ; (7) TRANSFER A BYTE + CMP DX,SI ; (7) THE END? + JNZ SCAN4 + MOV AL,0 ; (7) DROP IN A NULL + STOSB ; (7) TO END THE STRING + RET +SCAN5: CMP AL,'C' ; (7) DO THEY WANT COLOR + JNZ SCAN6 ; (7) NOPE, TRY NEXT + OR CMDLIN,2 ; (7) SET FLAG IN CMDLIN VARIABLE + JMP SCAN +SCAN6: CMP AL,'K' ; (7) SET MEMORY SIZE + JNZ SCAN9 ; (7) NOPE LOOK ONWARD + MOV BX,0 ; (7) ZERO THIS +SCAN7: CMP DX,SI ; (7) THE END? + JNZ SCAN8 ; (7) NOPE +SCAN7A: OR CMDLIN,4 ; (7) TURN ON MEMORY SET BIT + MOV CL,6 ; (7w) CONVERT K TO PARAGRAPHS + SHL BX,CL ; (7) I THINK??? + MOV MEMORY,BX ; (7) SAVE AMOUNT OF K SPECIFIED IN 512 BLKS + DEC SI ; (7v) BACKUP ONE + JMP SCAN +SCAN8: LODSB ; (7) GET FIRST BYTE + CMP AL,0D ; (7v) CR MEANS END OF STRING + JZ SCAN7A ; (7v) SO QUIT HERE + CMP AL,' ' ; (7v) SPACE MEANS NEXT STRING + JZ SCAN7A ; (7v) SO QUIT + CMP AL,'/' ; (7v) SLASH MEANS NEXT DELIMITER + JZ SCAN7A ; (7v) SO QUIT + XOR AH,AH ; (7) ZERO THIS + AAA ; (7) SCALE THE NUMBER DOWN + XCHG AX,BX ; (7) GET NUMBER (BX) INTO AC + PUSH DX ; (7) SAVE ENDPTR + MUL RADIX ; (7) MULTIPLY NUMBER BY TEN + ADD BX,AX ; (7) ADD IN NEW NUMBER + POP DX ; (7) RESTORE END PTR + JMP SCAN7 +SCAN9: CMP AL,'P' ; (7w) DO WE NEED TO INITIALIZE THE PRINTER + JZ SCAN10 ; (7w) YES, DO IT + JMP SCAN +SCAN10: PUSH DX ; (7w) SAVE THIS + MOV DX,0 ; (7w) INITIALIZE FIRST PRINTER + MOV AH,1 ; (7w) FUNCTION NUMBER FOR INIT + INT 17H ; (7w) ASSUME IBM PC BECAUSE THEY USED /P + POP DX ; (7w) RESTORE END POINTER + JMP SCAN ; (7w) NOW GET BACK TO WORK +SCANCMD ENDP + +CLRSCR PROC + CMP SLFLG,0 ; (7n) ANSI IN PLACE? + JZ CLR1 + MOV BX,OFFSET CLS + CMP COLFLG,1 ; (7t) TURN ON COLOR WITH CLEAR SCREEN + JNZ CLR0 + MOV BX,OFFSET CLSC ; (7t) TURN POINT TO COLOR ANSI CODE +CLR0: CALL MSPRT + RET +CLR1: MOV CL,SLPP ; (7n) GET NUMBER OF LINES + XOR CH,CH ; (7n) ZERO THE TOP +CLR2: CALL MCRLF ; (7n) ROLL THE SCREEN IF NO ANSI + MOV MORLIN,0 ; (7n) RESET TO AVOID MORE + LOOP CLR2 + RET +CLRSCR ENDP + + ;GET A GAME FILE BLOCK, BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX + PUBLIC GETBLK +GETBLK PROC + PUSH CX ;SAVE + MOV CX,1 ;CALL GTBLKS FOR 1 BLOCK ONLY + CALL GTBLKS + POP CX ;RESTORE + RET +GETBLK ENDP + + + ;GET A SERIES OF GAME FILE BLOCKS, + ;FIRST BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX # OF BLOCKS IN CX +; GTBLKS UNDERWENT A MAJOR OVERHAUL. IT WAS CHANGED TO SUPPORT 2.0 FILE +; NAMES AND FILE HANDLES. THE FIRST PASS OF THE OVERHAUL WAS TO SUPPORT +; FITTING THE WHOLE GAME INTO MEMORY. THIS BASTARDIZATION OF THE ORIGINAL +; WAS FURTHER CONTORTED WHEN TRYING TO SUPPORT 128K AND LESS MEMORY CONFIG- +; URATIONS. +; +; THE ORIGINAL ARGUMENTS HAVE NOT BEEN LEFT WHOLLY IN TACT. AX IS STILL THE +; FIRST BLOCK NUMBER AND CX CONTAINS THE NUMBER OF BYTES TO READ IF ALL OF +; THE GAME IS IN MEMORY OR BLOCKS IF THE GAME DOESN'T ALL FIT. ES:BX NO +; LONGER HAS THE CORE LOCATION. CALLS TO THIS PROCEDURE MAY STILL PUT THE +; CORE LOCATION IN BX BUT IT IS IGNORED. CORE LOCATION IS CALCULATED ON THE +; FLY BASED ON THE ENTRY IN PAGTAB (WHICH IN TURN SETS THE SEGMENT IN WHICH +; THE READ IS DONE.) +; +; THE STARTING BLOCK NUMBER IS USED TO MOVE THE FILE PTR (2.0) FROM THE +; BEGINNING OF THE FILE TO THE PROPER GAME BLOCK. +; +; IN THE CASE OF ALL OF THE GAME IN MEMORY, THE SEGMENT IS CHOSEN BASED ON +; THE PAGE'S INTENDED BUFFER INDICATED BY THE VARIABLE LPTAB. BUFFER NUMBERS +; 128 AND ABOVE GO IN TO THE SECOND SEGMENT. THE GAME IS READ IN IN THE +; BEGINNING IN THREE OR FOUR READS AND THIS ROUTINE IS NOT TOUCHED AGAIN. +; +; IN THE CASE OF A SMALL MEMORY SYSTEM, THE SEGMENT TO READ INTO IS CHOSEN +; BASED ON LPTAB, CURSEG AND SEGEND (SEE GETPAG FOR EXPLANATION). +; + PUBLIC GTBLKS,GTBKI$,GTBLP,GETIT,GTBLKB,GTBOUT,GTB2,GTB3 +GTBLKS PROC + MOV DSKDIR,0 ;READ MODE + PUSH AX + MOV AX,GAMHNDL ; (6) GET THIS HANDLE + MOV HANDLE,AX ; (6) INTO THE GENERAL HANDLE + POP AX ; (6) AND RESTORE THIS +GTBKI$: PUSH BP + PUSH DX + PUSH BX + PUSH SI +GTBLP: MOV DX,CX ; (6) SAVE NUMBER OF BLOCKS + MOV CX,9 ; (6) MULTIPLY BY 512 + SHL DX,CL ; (6) DO IT + SHL AX,CL ; (6) CONVERT BLK# TO OFFSET + MOV CX,0 ; (6) ZERO THIS + ADC CX,0 ; (6) DID WE CARRY OUT ABOVE + MOV BX,HANDLE ; (6) GET FILE HANDLE + MOV SI,DX ; (6) SAVE NUMBER OF BYTES FOR READ + TEST SEEKF,1 ; (6) SHOULD WE REALLY? + JZ NOSEEK + MOV DX,AX ; (6) GET LOW ORDER #BYTES FOR SEEK + MOV AH,CFSEEK + MOV AL,0 ; (6) USE OFFSET FROM BEGINNING METHOD + INT 21H ; (6) SEEK +NOSEEK: MOV DX,LPTAB ; (6) FIGURE OUT BUFFER NUMBER + TEST FITS,1 ; (6) DO WE HAVE ALL THE GAME + JNZ NOFIX ; (6) IF NOT, FIX LPTAB (SCALE IT DOWN) + CMP DX,0 ; (6) ARE WE JUST STARTING UP + JZ NOFIX + SUB DX,OFFSET PAGTAB ; (6) BASIFY THE TABLE NUMBER + SHR DX,1 + SHR DX,1 ; (6) DIVIDE TABLE ENTRY BY TABLE WIDTH(4) + MOV CL,9 ; (6) DIVIDE BY 512 + TEST CURSEG,1 ; (6) WHICH SEG ARE WE IN + JNZ NOFIX ; (6) SKIP PAGE ADDITION + MOV AX,PAGES ; (6) GET AMOUNT OF PRELOD + SHR AX,CL ; (6) AND SKIP THAT AMOUNT OF BUFFER SPC + ADD DX,AX ; (6) ADD THAT INTO BUFFER NUMBER +NOFIX: MOV CX,SI ; (6) RESTORE #BYTES TO READ + MOV AH,CRDRNDZ ; (6) READ RANDOM GAME RECORD + CMP DSKDIR,0 ; (6) ARE WE READING? + JZ GTREAD + MOV AH,CWRRNDZ ; (6) NO, DO A WRITE INSTEAD +GTREAD: TEST FITS,1 ; (6) IS BUFFERING CONTINUOUS + JNZ GTBLK1$ ; (6) FIGURE BUFFER FROM DX + TEST CURSEG,1 ; (6) WHAT SEGMENT ARE WE IN + JZ GETIT ; (6) FUNCTION NORMALLY + MOV SI,SEGEND ; (6) GET SEGMENT ENDING POINT + SHR SI,1 ;(6) DIVIDE IT BY WIDTH OF PAGTAB + SHR SI,1 ; (6) TO USE AS AN INDEX INTO SEG1 + SUB DX,SI ; (6) BASIFY BUFFER NUMBER FOR SEG1 + JMP GTBLK2$ ; (6) USE SEG1 WITH SCALED DX +GTBLK1$:CMP DX,128 + JL GETIT + SUB DX,128 ; (6) SUBTRACT TO BASIFY +GTBLK2$:PUSH DS + MOV SI,SEG1 ; (6) GET SEG1 INTO DS + MOV DS,SI ; (6) SET UP DS + JMP GTBLKB +GETIT: PUSH DS + MOV SI,ES + MOV DS,SI +GTBLKB: PUSH CX ; (6) SAVE NUMBER OF BLOCKS + MOV CL,9 + SHL DX,CL ; (6) MAKE A NEW PAGE-PTR + POP CX ; (6) RESTORE COUNT OF BYTES + INT 21H ; (6) CALL DOS + CMP AX,CX ; (6) SET FLAGS + POP DS + MOV SEEKF,1 ; (6) RESET SEEK FLAG +GTBOUT: POP SI + POP BX + POP DX + POP BP + RET +GTB2: PUSH AX ; (6) SAVE THIS + MOV AX,GAMHNDL ; (6) GET HANDLE + CMP HANDLE,AX ; (6) COMPARE THEM + JE GTB3 + STC + JMP GTBOUT + +GTB3: FATAL FTL7 +GTBLKS ENDP + + SUBTTL IBMPC SYSTEM ROUTINES + PAGE + + + PUBLIC MCHRI,MTTYO,MCRLF,MSOUT,MSPRT,MINIT,MPRNT,MTIME,FINISH + ;READ A CHARACTER INTO AX, WAITING UNTIL ONE IS AVAILABLE, NO ECHO +MCHRI PROC + PUSH CX + PUSH DX + CMP CHRFLG,0 + JNZ MCHR1 + MOV CHRFLG,1 +MCHR1: MOV AH,CNOECHO ; (7u) USE NO ECHO + INT 21H + SUB AH,AH + POP DX + POP CX + RET +MCHRI ENDP + + ;PRINT THE CHARACTER IN AL, FOREGROUND IN AH +MTTYO PROC + PUSH AX + PUSH BX ;SAVES + PUSH CX + PUSH DX + PUSH BP + PUSH AX + MOV AH,CCONIO + MOV DL,AL + INT 21H + POP AX + TEST SCRFLG,1 ; (7x) IS SCRIPTING REQUESTED? + JZ MTYO1 ; (7n) IF NOT THEN DON'T BOTHER + CMP SCRHLD,1 ; (7n) IS SCRIPTING SUSPENDED? + JZ MTYO1 + CALL PRTOUT +MTYO1: POP BP + POP DX + POP CX + POP BX + POP AX + RET +MTTYO ENDP + + ;PRINT A CARRIAGE RETURN/LINE FEED WITH MORE MODE +MCRLF PROC + PUSH AX ;SAVES + PUSH BX + PUSH CX + PUSH DX + PUSH BP + TEST SCROLL,1 ;(7) WHAT KIND OF SCROLLING + JNZ MCR$ + TEST SCRNFLG,1 ; (7) ARE WE IN SCREEN #1 + JNZ MCR$ ; (7) YES, USE OLD SCROLL + MOV AH,SCROLLUP ;(7) USE A VIDEO BIOS SCROLL + MOV AL,1 ;(7) ONLY 1 LINE + MOV CX,TOPLIN ;(7) ALWAYS FREEZE TOP LINE + MOV DH,SLPP ;(7) GET SCREEN LENGTH + MOV DL,SCPL ;(7) GET THE WIDTH OF THE SCREEN + DEC DL ; (7v) COORDINATES ARE ZERO BASED + MOV BH,SCRATR ;(7) GET THE SCREEN ATTRIBUTE + INT 10H ;(7) CALL THE VIDEO +MCR$: MOV AH,CCONIO + MOV DL,13 + INT 21H + TEST SCRNFLG,1 ; (7) ARE WE WRITING TO WINDOW 1 + JNZ MCRA$ + TEST SCROLL,1 ;(7) NO LINE FEED ON WINDOWED SCROLL + JZ NOLF +MCRA$: MOV AH,CCONIO + MOV DL,10 + INT 21H +NOLF: TEST SCRNFLG,1 ;(7) NO MORE FOR WINDOW 1 + JNZ MCR1 ;(7) SKIP THIS GARBAGE + INC MORLIN ;INCREMENT NUMBER OF LINES OUTPUT + MOV AL,SLPP + SUB AH,AH + DEC AX ;(7n) SO THAT STATUS LINE DOESN'T OVERWRITE +MCRB$: MOV DX,TOPLIN ;(7) GET SCROLLING WINDOW TOPLINE + XCHG DH,DL ;(7) SCROLL LINE IN DL + SUB AL,DL ;(7) THIS MANY LINES NOW + CMP MORLIN,AX + JL MCR1 + MOV MORLIN,0 + MOV SCRHLD,1 ; (7o) SUSPEND SCRIPT + PRINT MORE + CALL MCHRI + PRINT EMORE + MOV SCRHLD,0 ; (7o) RESUME SCRIPT +MCR1: TEST SCRFLG,1 ; (7x) CHANGED TO TEST + JZ MCR2 + CALL PRTCRL +MCR2: POP BP + POP DX + POP CX + POP BX + POP AX + RET +MCRLF ENDP + + ;OUTPUT STATUS LINE HERE +MSOUT PROC + MOV BX,OFFSET SBLINE + TEST COLFLG,1 ;(7) ARE WE IN COLOR MODE + JZ MSOUT1 + MOV BX,OFFSET CBLINE ;(7) USE COLOR THROUGH ANSI +MSOUT1: CALL MSPRT + MOV AH,09H + MOV DX,SLSTR + INT 21H + MOV BX,OFFSET SELINE + TEST COLFLG,1 ;(7) ARE WE IN COLOR MODE + JZ MSOUT2 + MOV BX,OFFSET CELINE ;(7) USE COLOR THROUGH ANSI +MSOUT2: CALL MSPRT + RET +MSOUT ENDP + +MSPRT PROC + MOV CL,BYTE PTR [BX] + SUB CH,CH + CMP CL,0 + JE MSPRT1 +MSPLP: INC BX + MOV DL,BYTE PTR [BX] + MOV AH,06H + PUSH BX + INT 21H + POP BX + LOOP MSPLP +MSPRT1: RET +MSPRT ENDP + +MINIT PROC + CMP SLFLG,0 + JNE MINIT1 + RET +MINIT1: MOV BX,OFFSET STINIT + TEST COLFLG,1 ;(7) ARE WE IN COLOR MODE + JZ MINIT2 ;(7) + MOV BX,OFFSET CTINIT ;(7) +MINIT2: CALL MSPRT + MOV BX,OFFSET SELINE + TEST COLFLG,1 ;(7) ARE WE IN COLOR MODE + JZ MINIT3 ;(7) + MOV BX,OFFSET CELINE ;(7) +MINIT3: CALL MSPRT + RET +MINIT ENDP + + ;PRINT A STRING, POINTER (TO DATA SEGMENT) IN AX, WHITE FOREGROUND +MPRNT PROC + CMP GAMEIN,1 ; (7q) DO NOT CHECK THIS UNLESS THE GAME IS IN + JNZ MPR0 + PUSH AX + MOV AX,ES:[PFLAGS] ; (7n) SCRIPTING? + XCHG AH,AL ; (7n) SWAP BYTES + MOV SCRFLG,AL ; (7n) TURN IT ON, TURN IT ON AGAIN! + POP AX +MPR0: PUSH BX ;SAVE BX + MOV BX,AX ;STRING POINTER +MPR1: MOV AL,[BX] ;GET NEXT CHARACTER + CMP AL,0 ;END OF LINE, WITH CRLF? + JE MPR2 ;YES + CMP AL,80H ;END OF LINE, NO CRLF? + JE MPR3 ;YES + CALL MTTYO ;PRINT CHARACTER + INC BX ;POINT TO NEXT CHARACTER + JMP MPR1 ;REPEAT +MPR2: CALL MCRLF ;PRINT A CRLF +MPR3: POP BX ;RESTORE BX + RET +MPRNT ENDP + + ;GET TIME +MTIME PROC + PUSH CX + PUSH DX + MOV AH,2CH + INT 21H + MOV RSEED1,CX ; HOURS & MINUTES + MOV RSEED2,DX ; SECONDS & 100THS + POP DX + POP CX + RET +MTIME ENDP + +FINISH PROC + CALL MCRLF + MOV BX,OFFSET STRESET + CALL MSPRT + MOV AH,4CH + INT 21H +FINISH ENDP + +EVEN +;********************************************************************** +; DO NOT PLACE ANY VARIABLES OR CODE BEYOND THIS POINT! THE +; ZIP DYNAMICALLY ALLOCATES A PAGE TABLE AND PAGING SPACE BEYOND +; THIS LABEL. +;********************************************************************** + PUBLIC PAGTAB +PAGTAB LABEL BYTE +MSZIP ENDP +CSEG ENDS + + END MSZIP diff --git a/ibm/n2.compare b/ibm/n2.compare new file mode 100644 index 0000000..9ab042e --- /dev/null +++ b/ibm/n2.compare @@ -0,0 +1,34 @@ + +;COMPARISON OF PS:MSIBMZIP.ASM.2 AND PS:BOSZIP.ASM.1 +;OPTIONS ARE /3 + +**** FILE PS:MSIBMZIP.ASM.2, 1-68 (2759) + ; +**** FILE PS:BOSZIP.ASM.1, 1-68 (2759) + ; 2 -- added boss key function to MCHRI +*************** + +**** FILE PS:MSIBMZIP.ASM.2, 1-1884 (50670) +**** FILE PS:BOSZIP.ASM.1, 1-1885 (50712) +;for the boss key, include the boss file +INCLUDE iboss.asm +*************** + +**** FILE PS:MSIBMZIP.ASM.2, 1-1921 (51609) +**** FILE PS:BOSZIP.ASM.1, 1-1926 (51716) + CALL boss + JNC GETLLC1 ;boss returns Carry Set if boss chr + MOV AL," " +GETLLC1: +*************** + +**** FILE PS:MSIBMZIP.ASM.2, 1-3178 (85794) +**** FILE PS:BOSZIP.ASM.1, 1-3187 (85986) + CALL HERALD ;put up the herald file +*************** + +**** FILE PS:MSIBMZIP.ASM.2, 1-4156 (119119) +**** FILE PS:BOSZIP.ASM.1, 1-4167 (119352) + call boss ; check for boss key +*************** + diff --git a/ibm/ndata.ezp b/ibm/ndata.ezp new file mode 100644 index 0000000..677e11e --- /dev/null +++ b/ibm/ndata.ezp @@ -0,0 +1,446 @@ + SUBTTL DATA - VARIABLE DEFINITION AND STORAGE + PAGE +; +; ALL DATA SAVE THE PAGE TABLE (PAGTAB) ARE DEFINED BETWEEN THE ABOVE JMP +; AND THE STARTING DESTINATION. +; + ;VARIBLE DEFINITIONS: + + PUBLIC START,GAMFILE,SAVFILE,GAMHNDL,SAVHNDL,HANDLE,SEEKF + PUBLIC LASTDRV,LSTDFLG,DRVFLG,LASTSAV,SSBUF,DEFDRV,CURDRV + ;GTBLKS +;************************************************************************ +; DO NOT MOVE THESE VARIABLES. DEFINE NOTHING ABOVE THEM. CREATE +; IS DEPENDENT UPON THIS FIXED VARIABLE SETUP FOR GAMFILE AND +; SAVFILE. EACH SHOULD TOTAL 65 CHARACTERS IN LENGTH +;************************************************************************ +; +GAMFILE DB "AMFV.DAT",0,0 ; PATCHED BY CREATE + DB 55 DUP (0) ; POTENTIAL LENGTH OF FILENAME +SAVFILE DB "AMFV.SAV",0,0 + DB 54 DUP (0) ; POTENTIAL LENGTH OF FILENAME +LASTSAV DB 64 DUP (0) +; +GAMESIZ DW ? ; GAME SIZE IN 512 BYTE BLOCKS +GAMHNDL DW ? ; FOR STORAGE OF FILE HANDLES +SAVHNDL DW ? +SSFILE DB "SETUP.INF",0 +SSBUF DW SSLNT/2 DUP (0) +SKPDRV DB 0 ; (7n) DON'T OUTPUT DRIVE NAME +DEFDRV DB ? ; BYTE FOR DEFAULT DRIVE +CURDRV DB ? ; BYTE FOR NEW DRIVE (SAVES) +DRVFLG DB 0 ; FLAG WHETHER DRIVE SPECIFIED ON SAV +LASTDRV DB ? ; TEMPORARY STORAGE FOR SAVE AND +LSTDFLG DB ? ; RESTORE FAILURE +HANDLE DW ? ; GENERAL HANDLE FOR GTBLKS ROUTINE +SEEKF DB 1 ; FLAG FOR WHETHER OR NOT TO SEEK +PRTBUF DB ? ; (7) BUFFER FOR PRINTER OUTPUT + + PUBLIC DSKDIR +DSKDIR DB 0 ;0 FOR READ, 1 FOR WRITE + + ; SCREEN DEFINITIONS AND ANSI STRINGS + PUBLIC SCRATR,COLFLG,SCP,RCP,SCPL,SLPP,STINIT,STRESET + PUBLIC SPINIT,STINIT,CTRESET,CLS,CLSC +CURSAV DB 0 ; (A0) IS THE CURSOR POSITION SAVED? +SCRATR DB 7 ;(7) BLACK BACKGROUND FOR DEFAULT +COLFLG DB 0 ;(7) ARE WE USING COLOR +SCPL DB 80 ; WIDTH OF THE SCREEN IN COLUMNS (DEFAULTS) +SLPP DB 24 ; LENGTH OF THE SCREEN IN ROWS + +NONIBM DW OFFSET NOHIGH ;(A9) + DW OFFSET INVERSE ;(A9) + DW OFFSET BOLD ;(A9) + DW 0 ;(A9) + DW OFFSET NOHIGH ;(A9) + +HILITES DW OFFSET NOHIGH + DW OFFSET INVERSE + DW OFFSET BOLD + DW 0 + DW OFFSET ITALIC +; +NOHIGH DB 4 + DB 27,'[0m' +INVERSE DB 8 + DB 27,'[0m',27,'[7m' +BOLD DB 8 + DB 27,'[0m',27,'[1m' +ITALIC DB 4 + DB 27,'[4m' +;; +COLORS DW OFFSET NORMCOL + DW OFFSET COLINV + DW OFFSET COLBOLD + DW 0 + DW OFFSET NORMCOL +; +COLBOLD DB 16 + DB 27,'[0m',27,"[37;44m",27,'[1m' +COLINV DB 12 + DB 27,'[0m',27,"[44;37m" +NORMCOL DB 12 + DB 27,'[0m',27,"[37;44m" + +EREOL DB 3 + DB 27,'[K' ; (A0) ERASE TO EOL +SCP DB 3 ; (7) ANSI SAVE CURSOR POSITION + DB 27,'[s' +RCP DB 3 ; (7) ANSI RESTORE CURSOR POSITION + DB 27,'[u' +STINIT DB 16 + DB 27,"[2J",27,"[0m",27,"[01;01H" +STRESET DB 4 + DB 27,"[0m" +SPINIT DB 0 +CTINIT DB 20 + DB 27,"[37;44m",27,"[2J",27,"[01;01H" +CTRESET DB 0 +CPINIT DB 0 +CLS DB 12 + DB 27,"[2J",27,"[" +CLS1 DB "25;01H" +CLSC DB 20 + DB 27,"[37;44m",27,"[2J",27,"[" +CLS1C DB "25;01H" +; +WAIT DB 31 + DB 27,"[12;28HThe story is loading..." + + PUBLIC WINDOW1,COLWIN1,WINDOW0,COLWIN0,RADIX +WINDOW1 DB 8 + DB 27,'[01;01H' +COLWIN1 DB 16 + DB 27,'[01;01H',27,'[37;44m' +WINDOW0 DB 4 + DB 27,'[0m' +COLWIN0 DB 8 + DB 27,'[37;44m' +RADIX DB 10 ; THE DEFAULT RADIX FOR THE SCREEN + ;SCRIPTING STUFF + PUBLIC GAMEIN,SCRHLD,SCRFLG,PRNNRDY +GAMEIN DB 0 +SCRHLD DB 0 ; (7n) IS SCRIPTING TEMPORARILY OFF +SCRFLG DB 0 +PRNNRDY DB " %Printer not ready: Abort or Retry? ",80H + + PUBLIC RSEED1,RSEED2 +;,SRHOLD,RNUM,IOCHAR + ;OPRAND +RSEED1 DW ? ;SEED1 FOR RANDOM NUMBERS +RSEED2 DW ? ;SEED2 FOR RANDOM NUMBERS +RTEMP DW ? ;TEMP FOR RANDOM ROUTINE +;(LD1) RNDFLG DB ? ; (A0) RANDOM FLAG +SRHOLD DW ? ; (LD1) FOR NON RANDOM RANDOM +RNUM DW ? ; (LD1) THIS ALSO +IOCHAR DB ? ; (LD1) HOLD AL FOR A SECOND + + PUBLIC RDWSTR,RDBOS,RDEOS,RDRET,RDNWDS,WRDOFF + ;READ +ZTHIRD DW ? ; (A0) THIRD ZWORD REGISTER FOR ZWORD +RDWSTR DW 5 DUP(0) ; (A0) WORD STRING BUFFER FOR ZWORD +RDBOS DW 0 ;BEGINNING OF STRING POINTER +RDEOS DW 0 ;END OF STRING POINTER +RDRET DW 0 ;RETURN TABLE POINTER +RDNWDS DB 0 ;NUMBER OF WORDS READ + ;PUTSTR +WRDOFF DW 0 ;OFFSET INTO WORD TABLE FOR CURRENT SET +DLYCNT DW ? ; (A0) DELAY COUNT IN 1/10THS SECONDS + + PUBLIC CHRPTR,ENDBUF,BUFBIT,PREVBUF + ;PUTCHR + ; REDIRECTION AND BUFFERING OUTPUT +CHRPTR DW 0 ;POINTS TO NEXT CHARACTER POSITION +ENDBUF DW 0 ;POINTS JUST PAST END OF OUTPUT BUFFER (0) +CHRCNT DW 79 ; (A13) OUTPUT BUFFER DOWN COUNTER +BUFBIT DB 1 ; (A0) BUFFERED INPUT TOGGLE +PREVBUF DB 1 ; (A0) PREVIOUS BUFFERING STAT +RDIR DW 0 ; (A0) WHERE OUTPUT IS DIRECTED TO +RTABLE DW ? ; (A0) ADDRESS OF TABLE TO OUTPUT TO +RTABLE2 DW ? ; (A0) OFFSET INTO TABLE WHERE OUTPUT GOES +RDIROUT DW 0 ; (A0) NUMBER OF CHARS SENT TO TABLE +VIDFLG DB 1 ; (A10) SCRREN CONTROL 1=ON + + ;GETNUM + + PUBLIC IRBRKS,ZORKID,ENDLOD,VOCTAB,OBJTAB,STABLE + PUBLIC GLOTAB,WRDTAB,PURBOT,ESIBKS,VWLEN,VWORDS,VOCBEG + PUBLIC OUTBUF,INBUF,RBRKS,BUFFERS,PAGES,INITTBL,SEGEND + ;ZIPBGN +IRBRKS DB " ",9,13,12,".,?",0 ;INITIAL SET OF READ BREAK CHARS +ZORKID DW 0 ;UNIQUE GAME & VERSION IDENTIFIER +ENDLOD DW 0 ;ENDLOD BLOCK NUMBER +SEGEND DW 0 ; (6) ENDLOD THAT DOESN'T GET DIDDLED +VOCTAB DW 0 ;SAVE VOCABULARY TABLE POINTER +OBJTAB DW 0 ;OBJECT TABLE POINTER +GLOTAB DW 0 ;GLOBAL TABLE POINTER +WRDTAB DW 0 ;WORD TABLE POINTER +PURBOT DW 0 ;PURE CODE POINTER +ESIBKS DW 0 ;END OF SELF-INSERTING BREAK CHARACTERS +VWLEN DW 0 ;NUMBER OF BYTES IN A VOCABULARY WORD ENTRY +VWORDS DW 0 ;NUMBER OF WORD ENTRIES IN VOCABULARY +VOCBEG DW 0 ;BEGINNING OF ACTUAL VOCABULARY +OUTBUF DB 81 DUP(?) ;OUTPUT BUFFER +INBUF DB MAXLIN+2 DUP(?) ;INPUT BUFFER +RBRKS DB 32 DUP(?) ;STRING OF READ BREAK CHARACTERS +BUFFERS DW 0 ;(6) NUMBER OF 512 BYTE BUFFERS FOR PAGING +PAGES DW 0 ;SWAPPING AREA +CHRFLG DB 0 +INITTBL DW 0FFFEH ; (A0) + DW 3 DUP (0) + +; CMDLIN WAS CREATED FOR CHANGING CERTAIN PARAMETERS ON THE COMMAND LINE +; CURRENTLY THERE ARE SWITCHES (C,M,W). BITS ARE SET IN SCANCMD AND +; PROCESSED IN SYSINI OR SSETUP. +; + PUBLIC CMDLIN,MEMORY +CMDLIN DB 0 ; (7n) 16=IBM PARALLEL PRINTER + ; (7) 8=SCROLL SET + ; (7) 4=MEMORY SET + ; (7) 2=COLOR SET + ; (7) 1=MONOCHROME SET +MEMORY DW 0 ; (7) MEMORY SIZE SET ON CMDLIN + + PUBLIC ZLOCS,ZPC1,ZPC2,ARGBLK,ZPCSEG,ZPCFLG + ;RESTRT +ZLOCS DW 0 ;POINTER TO LOCALS +ZPC1 DW 0 ;ZPC BLOCK-POINTER +ZPC2 DW 0 ;ZPC BYTE-POINTER +ZPCSEG DB 0 ;(6) GAME SEGMENT WHERE ZPC IS +ZPCFLG DB 0 ; (7n) ZPC PAGE IS MUNGED? +ARGBLK DW 9 DUP(?) ; (A0) ARGUMENT BLOCK FOR EXTENDED OPERATIONS + + PUBLIC CURPAG,CURBLK,CURTAB,CURSEG + ;NEWZPC +CURPAG DW 0 ;CURRENT PAGE (WHERE ZPC IS) POINTER +CURBLK DW 0 ;CURRENT BLOCK, USUALLY SAME AS ZPC1 +CURTAB DW 0 ;CURRENT PAGE TABLE POINTER +1 + + PUBLIC RTIME1,RTIME2,LPAGE,LPLOC,LPTAB,GAMESEG,SEG1,FITS + ;GETPAG +RTIME1 DW 0 ;(A0)REFERENCE TIME, 1 1/2 WORDS USED +RTIME2 DW 0 +LPAGE DW 0 ;LAST REFERENCED PAGE NUMBER +LPLOC DW 0 ;AND ITS CORE LOCATION +LPTAB DW 0 ;AND ITS TABLE POINTER +GAMESEG DW ? ;(6) FIRST (OR ZERO) GAME SEGMENT +SEG1 DW ? ;(6) SECOND GAMESEG (GAMESEG+64K) +CURSEG DB 0 ;(6) SEGMENT (0/1) FOR CURRENT PAGE +FITS DB 0 ;(6) FLAG FOR GAME ALL IN MEMORY + ;GETBYT +LSTGET DB 0 ; (A16) HIGH BYTE FROM LAST GETBYTE +LSTGGD DB 0 ; (A16) GOODNESS OF LAST HIGH BYTE + ;NXTBYT +LSTNXT DB 0 ; (A16) HIGH BYTE FROM LAST NXTBYT +LSTNGD DB 0 ; (A16) GOODNESS OF LAST HIGH BYTE + + ; SPLIT AND SCREEN VARS + PUBLIC SCRNFLG,SPLCOL,SPLTFLG +SCRNFLG DB 0 ; (7) WINDOW THAT WE ARE WRITING IN +SPLCOL DB 17H ; (7) GREEN BACKGROUD FOR WINDOW 1 +SPLTFLG DB 0 ; (7) IS THE SCREEN SPLIT + + ; SOUND VARIABLES +TIMER DB ? +STABLE DW SND1,SND2 ; (A0) TABLES FOR SOUNDS 1 & 2 +CLKLOW DW ? + + ;OPERATION TABLES: ;ZERO ARGUMENT OPERATIONS + PUBLIC ZEROOP,ONEOP,EXTOP +ZEROOP DW OPRTRU ;176 + DW OPRFAL ;177 + DW OPPRNI ;178 + DW OPPRNR ;179 + DW OPNOOP ;180 + DW OPSAVE ;181 + DW OPREST ;182 + DW OPRSTT ;183 + DW OPRSTA ;184 + DW OPFSTA ;185 + DW OPQUIT ;186 + DW OPCRLF ;187 + DW 0 ;188 OPUSL UNDER ZIP + DW OPVERI ;189 + DW 0 ;190 + DW 0 ;191 + ;ONE ARGUMENT OPERATIONS +ONEOP DW OPQZER ;128 + DW OPQNEX ;129 + DW OPQFIR ;130 + DW OPLOC ;131 + DW OPPTSI ;132 + DW OPINC ;133 + DW OPDEC ;134 + DW OPPRNB ;135 + DW OPCALL1 ;136 + DW OPREMO ;137 + DW OPPRND ;138 + DW OPRETU ;139 + DW OPJUMP ;140 + DW OPPRIN ;141 + DW OPVALU ;142 + DW OPBCOM ;143 + ;TWO ARGUMENT AND EXTENDED ARGUMENT OPERATIONS +EXTOP DW 0 ;0 + DW OPQEQU ;1 + DW OPQLES ;2 + DW OPQGRT ;3 + DW OPQDLE ;4 + DW OPQIGR ;5 + DW OPQIN ;6 + DW OPBTST ;7 + DW OPBOR ;8 + DW OPBAND ;9 + DW OPQFSE ;10 + DW OPFSET ;11 + DW OPFCLE ;12 + DW OPSET ;13 + DW OPMOVE ;14 + DW OPGET ;15 + DW OPGETB ;16 + DW OPGETP ;17 + DW OPGTPT ;18 + DW OPNEXT ;19 + DW OPADD ;20 + DW OPSUB ;21 + DW OPMUL ;22 + DW OPDIV ;23 + DW OPMOD ;24 + DW OPCALL2 ;25 + DW 0 ;26 + DW 0 ;27 + DW 0 ;28 + DW 0 ;29 + DW 0 ;30 + DW 0 ;31 + DW OPCALL ;224 + DW OPPUT ;225 + DW OPPUTB ;226 + DW OPPUTP ;227 + DW OPREAD + ;228 + DW OPPRNC ;229 + DW OPPRNN ;230 + DW OPRAND ;231 + DW OPPUSH ;232 + DW OPPOP ;233 + DW OPSPLT ;234 + DW OPSCRN ;235 + DW OPXCALL ;236 + DW OPCLEAR ;237 + DW OPERASE ;238 + DW OPCURST ;239 + DW OPCURGT ;240 + DW OPHILIT ;241 + DW OPBFOUT ;242 + DW OPDIROU ;243 + DW OPDIRIN ;244 + DW OPSND ;245 + DW OPINPUT ;246 + DW OPINTBL ;247 (A12) + DW 0 ;248 + DW 0 ;249 + DW 0 ;250 + DW 0 ;251 + DW 0 ;252 + DW 0 ;253 + DW 0 ;254 + DW 0 ;255 + + ;(7) COPY PROTECTION STUFF + PUBLIC COMPATS,COMP1,IBMSTR +COMPATS DW 3 ; (7) NUMBER OF STRINGS IN THE LIST +COMP1 DB 'COMPAQ Co$' +IBMSTR DB 'COPR. IBM$' ; (7) EACH STRING MUST BE 9 CHARS + DB 'Tandy Cor$' ; (7v) ADD TANDY + + ;(A9) ENVIORNMENT +IBMPC DB 0 ; (A9) 1=IBMPC + + ;MCRLF + PUBLIC SCROLL,TOPLIN,MORLIN + ; (7) SCROLL IS SEEMINGLY BACKWARDS BUT TOO INTERWOVEN TO + ; GO AROUND AND FIX NOW. + ; 0 = IBM Compatible 100% (use windowed scrolling) + ; 1 = MS-DOS, no windowed scrolling + ; +SCROLL DB 1 +TOPSCR DW 0 +TOPLIN DW 0 ; (7) WORD FOR CH,CL FOR UPPER RIGHT +MORE DB "[MORE]",80H ; (A12) +EMORE DB 13," ",13,80H +MORLIN DW 0 ; (7) COUNT OF LINES SCROLLED WITHOUT PAUSE + + ;STRUCTURE AND RECORD DEFINITIONS: + ;OBJECT OPERATIONS +OBJECT STRUC +FLAGS1 DW ? +FLAGS2 DW ? +FLAGS3 DW ? ; (A0) EZIP EXTENDED FLAG WORD +PARENT DW ? ; (A0) EXTEND TO WORD +SIBLING DW ? ; (A0) EXTEND TO WORD +CHILD1 DW ? ; (A0) AGAIN^^ +PROPS DW ? +OBJECT ENDS +PROPID RECORD PROPNUM:6 + + ;STRING DEFINITIONS + + ;STATION IDENTIFICATION + ; (A10) TWO DIGIT MINOR VERSION NUMBER + PUBLIC IDSTR +IDSTR DB 80H ; PATCH OUT THIS BYTE FOR TESTING + DB "IBM/PC-DOS 2.0 Interpreter Version ",ZVERSN,ZEDIT0,ZEDIT1,0 + + ;TERMINAL SETUP +WANTCO DB "Do you want color (Y/N)? ",80H + + PUBLIC SAV0,SAV1,SAV2,SAV3,ERR1,ERR2,ERR3,ERR4,ERR5,ERR6 + ;SAVE/RESTORE +SAV0 DB "Insert save disk then enter file name.",0 +SAV1 DB "(Default is ",80H +SAV2 DB "): ",80H +SAV3 DB "Insert game disk then strike any key to continue.",0 + +ERR1 DB "SAVE file not found",0 +ERR3 DB "Bad file name syntax",0 +ERR4 DB "Unable to access file",0 +ERR5 DB "No room on diskette for SAVE file",0 +ERR6 DB "Read of SAVE file failed",0 + ;READ +ERR2 DB "Too many words typed, discarding: ",80H + + PUBLIC FTL2,FTL4,FTL5,FTL6,FTL7,FTL9 + ;OPNEXT/OPPUTP +FTL2 DB "No such property",0 + ;ZIPBGN +FTL4 DB "Wrong game or version",0 + ;NXTINS +FTL5 DB "Illegal operation",0 + ;FINDPG +FTL6 DB "No free pages",0 + ;GTBLKS +FTL7 DB "Game file read error",0 + ;SYSINI +FTL9 DB "Game file not found",0 +FTL10 DB 'Unauthorized copy',0 +FTL11 DB 'Wrong DOS version. Must be 2.0 or higher',0 +FTL12 DB 'Insufficient memory to play game',0 +FTL13 DB 'Illegal argument',0 +FTL14 DB 'Screen must be 80 characters wide',0 + + ;Fatal error header +FATHDR DB "Fatal error: ",80H + ;ZSTR CHARACTER CONVERSION VECTOR + + PUBLIC ZCHRS +ZCHRS DB "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + DB " 0123456789.,!?_#'" + DB '"/\-:()' + + PUBLIC STK_TOP,STKBOT,ZSTK_TP +; STACK SETUP + DW 200H DUP(?) +STK_TOP LABEL WORD +STKBOT DW LSTACK DUP(?) +ZSTK_TP LABEL WORD diff --git a/ibm/notes b/ibm/notes new file mode 100644 index 0000000..caf7eb7 --- /dev/null +++ b/ibm/notes @@ -0,0 +1,15 @@ +dip.asm -- is the dip that displays in black and white on an rgb monitor, + and color on composite. + +lip.asm & dump.asm -- is the rgb dip that pseudo-colors. + +ezip.asm & *.ezp -- ezip (ezip.asm includes all the *.ezp files) + +msibmzip.asm -- zip for the ibm ib2 version (this is called newzip.asm + on paul's disk \paul\ws\newzip.asm) + +bosszip.asm & iboss.asm -- this is newzip.asm with the addition of the + boss key. Two supplemental files, game.hrl (herald, displayed at + startup if present) and game.scr (screen, displayed on ^B) may + be present on the game disk. + diff --git a/ibm/objops.ezp b/ibm/objops.ezp new file mode 100644 index 0000000..09c25f0 --- /dev/null +++ b/ibm/objops.ezp @@ -0,0 +1,268 @@ + + SUBTTL OBJECT OPERATIONS + PAGE + + + PUBLIC OPMOVE,OPREMO,OPQFSE,OPFSET + ;MOVE (OBJ1 INTO OBJ2) +OPMOVE PROC + PUSH AX ;PROTECT OPRS FROM REMOVE CALL + PUSH BX + CALL OPREMO ;REMOVE OBJ1 FROM WHEREVER IT IS + POP DX ;OBJ2 + MOV AX,DX + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + POP CX ;OBJ1 + MOV AX,CX + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + PTAWRD ES:[BP].PARENT,D ; (A0) PUT OBJ2 INTO OBJ1'S LOC SLOT + GTAWRD D,ES:[BX].CHILD1 ; (A0) GET CONTENTS OBJ2'S FIRST SLOT + PTAWRD ES:[BX].CHILD1,C ; (A0) MAKE OBJ1 FIRST CONTENT OBJ2 + CMP DX,0 ;WERE THERE ANY OTHER CONTENTS? + JE OMV1$ ;NO + PTAWRD ES:[BP].SIBLING,D ; YES, CHAIN ONTO OBJ1'S SIBLING SLOT +OMV1$: RET +OPMOVE ENDP + + ;REMOVE (OBJ FROM ITS PARENT) +OPREMO PROC + MOV DX,AX ; (A0) SAVE OBJ FOR LATER + CALL OBJLOC ;FIND ITS LOCATION + MOV BX,AX ;MOVE TO BASE + GTAWRD C,ES:[BX].PARENT ; (A0) GET ITS PARENT + CMP CX,0 ;DOES IT HAVE A PARENT? + JE ORM3$ ;IF NOT, WE'RE DONE + MOV AX,CX ; (A0) PARENT + CALL OBJLOC ;FIND PARENT'S LOCATION + MOV BP,AX ;MOVE TO BASE + MOV CX,DX ; (A0) MOVE OBJECT TO CX + GTAWRD D,ES:[BP].CHILD1 ; (A0) GET PARENT'S FIRST CONTENT + CMP DX,CX ; (A0) IS IT OBJ? + JNE ORM1$ ;NO + MOVM ES:[BP].CHILD1,ES:[BX].SIBLING,AX ;YES, CHANGE SLOT TO + ;OBJ'S SIBLING + JMP ORM2$ ;AND RETURN +ORM1$: MOV AX,DX ; (A0) CURRENT SIBLING + CALL OBJLOC ;FIND ITS LOCATION + MOV BP,AX ;MOVE TO BASE + GTAWRD D,ES:[BP].SIBLING ; (A0) GET NEXT SIBLING IN CHAIN + CMP DX,CX ; (A0) IS IT OBJ? + JNE ORM1$ ;NO, CONTINUE LOOP + MOVM ES:[BP].SIBLING,ES:[BX].SIBLING,AX ; (A0) YES, CHANGE IT + ; TO OBJ'S SIBLING +ORM2$: MOV ES:[BX].PARENT,0 ;OBJ NOW HAS NO PARENT + MOV ES:[BX].SIBLING,0 ;OR SIBLING +ORM3$: RET +OPREMO ENDP + + ;FSET? (IS FLAG SET IN OBJ?) +OPQFSE PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,32 ; (A0) FIND WHICH WORD TO SET FLAG IN + JL OQF0$ ; (A0) NOT IN THE THIRD + SUB BX,32 ; (A0) YES, IT IS + ADD AX,4 ; (A0) SKIP OTHER FLAG WORDS IN OBJECT + JMP OQF1$ ; (A0) AND SET THE FLAG +OQF0$: CMP BX,16 ;SECOND WORD FLAG? + JL OQF1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OQF1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + TEST AX,DX ;IS THIS BIT SET IN FLAG WORD? + JE OQF2$ ;NO, PREDICATE FALSE + JMP PTRUE ;YES, PREDICATE TRUE +OQF2$: JMP PFALSE +OPQFSE ENDP + + ;FSET (SET A FLAG IN OBJ) +OPFSET PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,32 ; (A0) FIND WHICH WORD TO SET FLAG IN + JL OFS0$ ; (A0) NOT IN THE THIRD + SUB BX,32 ; (A0) YES, IT IS + ADD AX,4 ; (A0) SKIP OTHER FLAG WORDS IN OBJECT + JMP OFS1$ ; (A0) AND SET THE FLAG +OFS0$: CMP BX,16 ;SECOND WORD FLAG? + JL OFS1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFS1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION + SHR DX,CL + OR AX,DX ;SET THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + RET +OPFSET ENDP + + PUBLIC OPFCLE,OPLOC,OPQFIR,OPQNEX,OPQIN + ;FCLEAR (CLEAR A FLAG IN OBJ) +OPFCLE PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + CMP BX,32 ; (A0) FIND WHICH FLAG WORD WE WANT + JL OFC0$ ; (A0) MAYBE IN SECOND WORD + ADD AX,4 ; (A0) POINT TO THIRD WORD + SUB BX,32 ; (A0) BASIFY FLAG NUMBER + JMP OFC1$ ; (A0) AND CLEAR FLAG +OFC0$: CMP BX,16 ;SECOND WORD FLAG? + JL OFC1$ ;NO + SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER + INC AX ;AND USE SECOND FLAG WORD + INC AX +OFC1$: MOV CX,BX ;MOVE TO COUNT + MOV BX,AX ;MOVE TO BASE + GTAWRD A,[BX] ;GET THE FLAG WORD + MOV DX,7FFFH ;SHIFT A BIT TO PROPER POSITION + ROR DX,CL + AND AX,DX ;CLEAR THIS BIT IN FLAG WORD + PTAWRD [BX],A ;STORE THE NEW FLAG WORD + RET +OPFCLE ENDP + + ;LOC (RETURN CONTAINER OF OBJ) +OPLOC PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + GTAWRD A,ES:[BX].PARENT ; (A0) GET LOC SLOT + JMP PUTVAL ; (A0) RETURN THE WORD VALUE +OPLOC ENDP + + ;FIRST? (RETURN FIRST SLOT OF OBJ, FAIL IF NONE) +OPQFIR PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + GTAWRD A,ES:[BX].CHILD1 ; (A0) GET FIRST SLOT + PUSH AX ;SAVE IT + CALL PUTVAL ; (A0) RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AX,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE +JPT1: JMP PTRUE ;NO, PREDICATE TRUE +JPF1: JMP PFALSE +OPQFIR ENDP + + ;NEXT? (RETURN THE NEXT (SIBLING) SLOT OF OBJ, FAIL IF NONE) +OPQNEX PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BX,AX ;MOVE TO BASE + GTAWRD A,ES:[BX].SIBLING ; (A0) GET SIBLING SLOT + PUSH AX ;SAVE IT + CALL PUTVAL ; (A0) RETURN THE BYTE VALUE + POP AX ;RESTORE IT + CMP AX,0 ;WAS IT ZERO? + JE JPF1 ;YES, PREDICATE FALSE + JMP JPT1 ;NO, PREDICATE TRUE +OPQNEX ENDP + + ;IN? (IS OBJ1 CONTAINED IN OBJ2?) +OPQIN PROC + CALL OBJLOC ;FIND OBJ1'S LOCATION + XCHG AX,BX ;MOVE TO BASE + XCHG AH,AL ; (A0) FLOP BYTES + CMP ES:[BX].PARENT,AX ; (A0) IS OBJ1'S PARENT OBJ2? + XCHG AH,AL ; (A0) REFLOP BYTES + JE JPT1 ;YES, PREDICATE TRUE + JMP JPF1 ;NO, PREDICATE FALSE +OPQIN ENDP + + PUBLIC OPGETP + ;GETP (GET SPECIFIED PROPERTY OF OBJ, DEFAULT IF NONE) +OPGETP PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + CALL FSTPRP ; (A0) GET FIRST PROPERTY POINTER + JMP OGP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGP2$: MOV AL,ES:[BX] ; (A0) GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JL OGP3$ ;IF LESS, NO SUCH PROPERTY HERE + + MOV AL,ES:[BX] ; (A0) NOW FIND PROPERTY SIZE + INC BX ; (A0) ADVANCE PROP BYTE POINTER + AND AL,3FH ; (A0) MASK OFF LENGTH BITS + + CMP AL,0 ;BYTE VALUE? + JNE OGP5$ ;NO + MOV AL,ES:[BX] ;GET THE BYTE + JMP BYTVAL ;AND RETURN IT +OGP3$: DEC DX ;POINT INTO DEFAULT PROPERTY TABLE + SHL DX,1 + MOV BX,DX +OGP4$: ADD BX,OBJTAB ;GET THE WORD +OGP5$: GTAWRD A,[BX] + JMP PUTVAL ;AND RETURN IT +OPGETP ENDP + + ;PUTP (CHANGE VALUE OF A PROPERTY, ERROR IF BAD NUMBER) + PUBLIC OPPUTP,OPP2$ +OPPUTP PROC + PUSH CX ;SAVE NEW VALUE + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + CALL FSTPRP ; (A0) GET FIRST PROPERTY + JMP OPP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OPP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OPP2$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE OPP3$ ;IF EQUAL, GOT IT + JG OPP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR + +OPP3$: MOV AL,ES:[BX] ;NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + AND AL,3FH ; (A0) MASK OFF LENGTH BITS + + CMP AL,0 ;BYTE VALUE? + POP AX ;RESTORE NEW VALUE + JNE OPP4$ ;ZERO MEANS BYTE VALUE + MOV ES:[BX],AL ;STORE THE NEW BYTE + RET ;AND RETURN +OPP4$: PTAWRD [BX],A ;STORE THE NEW WORD VALUE + RET +OPPUTP ENDP + + ;NEXTP (RETURN NUMBER OF NEXT PROP FOLLOWING GIVEN PROB IN OBJ) + PUBLIC OPNEXT,ONX2$ +OPNEXT PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + CALL FSTPRP ; (A0) POINT TO FIRST PROPERTY + CMP DX,0 ;WERE WE GIVEN ZERO AS PROP? + JE ONX4$ ;YES, GO RETURN FIRST PROPERTY NUMBER + JMP ONX2$ ;NO, SKIP NEXT LINE FIRST TIME THROUGH LOOP +ONX1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX2$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JE ONX3$ ;IF EQUAL, GOT IT + JG ONX1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + FATAL FTL2 ;OTHERWISE, FATAL ERROR +ONX3$: CALL NXTPRP ;POINT TO NEXT PROPERTY +ONX4$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;EXTRACT PROPERTY NUMBER + JMP PUTVAL ;AND RETURN IT +OPNEXT ENDP + + ; GIVEN OBJLOC IN AX, RETURN A PTR TO FIRST PROPERTY IN BX + PUBLIC FSTPRP +FSTPRP PROC + MOV BP,AX ;MOVE TO BASE + GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE + MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS + XOR AH,AH ; (A0) ZERO THE TOP HALF + SHL AX,1 ;CONVERT TO BYTES + ADD BX,AX ;ADJUST POINTER TO SKIP IT + INC BX ; SKIP LENGTH BYTE + RET +FSTPRP ENDP \ No newline at end of file diff --git a/ibm/pageio.ezp b/ibm/pageio.ezp new file mode 100644 index 0000000..f44638c --- /dev/null +++ b/ibm/pageio.ezp @@ -0,0 +1,137 @@ + SUBTTL PAGEIO + PAGE + + ;GET A GAME FILE BLOCK, BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX + PUBLIC GETBLK +GETBLK PROC + PUSH CX ;SAVE + MOV CX,1 ;CALL GTBLKS FOR 1 BLOCK ONLY + CALL GTBLKS + POP CX ;RESTORE + RET +GETBLK ENDP + + + ;GET A SERIES OF GAME FILE BLOCKS, + ;FIRST BLOCK NUMBER IN AX, CORE LOCATION IN ES:BX # OF BLOCKS IN CX +; GTBLKS UNDERWENT A MAJOR OVERHAUL. IT WAS CHANGED TO SUPPORT 2.0 FILE +; NAMES AND FILE HANDLES. THE FIRST PASS OF THE OVERHAUL WAS TO SUPPORT +; FITTING THE WHOLE GAME INTO MEMORY. THIS BASTARDIZATION OF THE ORIGINAL +; WAS FURTHER CONTORTED WHEN TRYING TO SUPPORT 128K AND LESS MEMORY CONFIG- +; URATIONS. +; +; THE ORIGINAL ARGUMENTS HAVE NOT BEEN LEFT WHOLLY IN TACT. AX IS STILL THE +; FIRST BLOCK NUMBER AND CX CONTAINS THE NUMBER OF BYTES TO READ IF ALL OF +; THE GAME IS IN MEMORY OR BLOCKS IF THE GAME DOESN'T ALL FIT. ES:BX NO +; LONGER HAS THE CORE LOCATION. CALLS TO THIS PROCEDURE MAY STILL PUT THE +; CORE LOCATION IN BX BUT IT IS IGNORED. CORE LOCATION IS CALCULATED ON THE +; FLY BASED ON THE ENTRY IN PAGTAB (WHICH IN TURN SETS THE SEGMENT IN WHICH +; THE READ IS DONE.) +; +; THE STARTING BLOCK NUMBER IS USED TO MOVE THE FILE PTR (2.0) FROM THE +; BEGINNING OF THE FILE TO THE PROPER GAME BLOCK. +; +; IN THE CASE OF ALL OF THE GAME IN MEMORY, THE SEGMENT IS CHOSEN BASED ON +; THE PAGE'S INTENDED BUFFER INDICATED BY THE VARIABLE LPTAB. BUFFER NUMBERS +; 128 AND ABOVE GO IN TO THE SECOND SEGMENT. THE GAME IS READ IN IN THE +; BEGINNING IN THREE OR FOUR READS AND THIS ROUTINE IS NOT TOUCHED AGAIN. +; +; IN THE CASE OF A SMALL MEMORY SYSTEM, THE SEGMENT TO READ INTO IS CHOSEN +; BASED ON LPTAB, CURSEG AND SEGEND (SEE GETPAG FOR EXPLANATION). +; + PUBLIC GTBLKS,GTBKI$,GTBLP,GETIT,GTBLKB,GTBOUT,GTB2,GTB3 +GTBLKS PROC + MOV DSKDIR,0 ;READ MODE + PUSH AX + MOV AX,GAMHNDL ; (6) GET THIS HANDLE + MOV HANDLE,AX ; (6) INTO THE GENERAL HANDLE + POP AX ; (6) AND RESTORE THIS +GTBKI$: PUSH BP + PUSH DX + PUSH BX + PUSH SI +GTBLP: MOV BX,0 + MOV DX,CX ; (6) SAVE NUMBER OF BLOCKS + MOV CX,9 ; (6) MULTIPLY BY 512 +GTBLP1: SHL DX,1 ; (6) DO IT + SHL AX,1 ; (6) CONVERT BLK# TO OFFSET + PUSHF ; (A0) SAVE FACT OF CARRY OUT + SHL BX,1 + POPF ; (A0) ONLY ADD CARRYOUT FROM AX + ADC BX,0 ; (6) DID WE CARRY OUT ABOVE + LOOP GTBLP1 ; (A0) GET OFFSET INTO BX:DX + MOV CX,BX ; (A0) NOW CX:DX HAS OFFSET + MOV BX,HANDLE ; (6) GET FILE HANDLE + MOV SI,DX ; (6) SAVE NUMBER OF BYTES FOR READ + TEST SEEKF,1 ; (6) SHOULD WE REALLY? + JZ NOSEEK + MOV DX,AX ; (6) GET LOW ORDER #BYTES FOR SEEK + MOV AH,CFSEEK + MOV AL,0 ; (6) USE OFFSET FROM BEGINNING METHOD + INT 21H ; (6) SEEK +NOSEEK: MOV DX,LPTAB ; (6) FIGURE OUT BUFFER NUMBER + TEST FITS,1 ; (6) DO WE HAVE ALL THE GAME + JNZ NOFIX ; (6) IF NOT, FIX LPTAB (SCALE IT DOWN) + CMP DX,0 ; (6) ARE WE JUST STARTING UP + JZ NOFIX + SUB DX,OFFSET PAGTAB ; (6) BASIFY THE TABLE NUMBER + MOV CL,TBLSHF ; (A0) DIVIDE TABLE ENTRY BY TABLE WIDTH + SHR DX,CL ; (6) DIVIDE TABLE ENTRY BY TABLE WIDTH(8) + MOV CL,9 ; (6) DIVIDE BY 512 + CMP CURSEG,0 ; (A0) ARE WE IN SEG0???? + JNZ NOFIX ; (6) SKIP PAGE ADDITION + MOV AX,PAGES ; (6) GET AMOUNT OF PRELOD + SHR AX,CL ; (6) AND SKIP THAT AMOUNT OF BUFFER SPC + ADD DX,AX ; (6) ADD THAT INTO BUFFER NUMBER +NOFIX: MOV CX,SI ; (6) RESTORE #BYTES TO READ + MOV AH,CRDRNDZ ; (6) READ RANDOM GAME RECORD + CMP DSKDIR,0 ; (6) ARE WE READING? + JZ GTREAD + MOV AH,CWRRNDZ ; (6) NO, DO A WRITE INSTEAD +GTREAD: TEST FITS,1 ; (6) IS BUFFERING CONTINUOUS + JNZ FDSEG0 ; (A0) FIGURE BUFFER FROM DX + CMP CURSEG,0 ; (A0) WHAT SEGMENT ARE WE IN + JZ GETIT ; (6) FUNCTION NORMALLY + MOV SI,SEGEND ; (6) GET SEGMENT ENDING POINT + PUSH CX ; (A0) SAVE NUMBER OF BYTES READ + MOV CL,TBLSHF ; (A0) GET TABLE WIDTH (SHIFTIFIED) + SHR SI,CL ; (6) TO USE AS AN INDEX INTO SEG1 + POP CX ; (A0) RESTORE #BYTES TO READ + SUB DX,SI ; (6) BASIFY BUFFER NUMBER FOR SEG1 +FDSEG0: MOV SI,GAMESEG ; (A0) GET SEG0 ADDR + TEST FITS,1 ; (A0) SEG1 IF NO FIT + JNZ FNDSEG ; (A0) GO DO THE MATH + ADD SI,1000H ; (A0) JUMP TO SEG 1 +FNDSEG: CMP DX,128 ; (A0) FIND SEG THAT IT IS IN + JB GTBLK2$ ; (A0) READY FOR ACTION, GO... + SUB DX,128 ; (A0) NOPE, TRY NEXT SEG + ADD SI,1000H ; (A0) SETUP FOR LOOP + JMP FNDSEG +GTBLK2$:PUSH DS + MOV DS,SI ; (6) SET UP DS + JMP GTBLKB +GETIT: PUSH DS + MOV SI,ES + MOV DS,SI +GTBLKB: PUSH CX ; (6) SAVE NUMBER OF BLOCKS + MOV CL,9 + SHL DX,CL ; (6) MAKE A NEW PAGE-PTR + POP CX ; (6) RESTORE COUNT OF BYTES + INT 21H ; (6) CALL DOS + CMP AX,CX ; (6) SET FLAGS + POP DS + MOV SEEKF,1 ; (6) RESET SEEK FLAG +GTBOUT: POP SI + POP BX + POP DX + POP BP + RET +GTB2: PUSH AX ; (6) SAVE THIS + MOV AX,GAMHNDL ; (6) GET HANDLE + CMP HANDLE,AX ; (6) COMPARE THEM + JE GTB3 + STC + JMP GTBOUT + +GTB3: FATAL FTL7 +GTBLKS ENDP diff --git a/ibm/paging.ezp b/ibm/paging.ezp new file mode 100644 index 0000000..61b92bd --- /dev/null +++ b/ibm/paging.ezp @@ -0,0 +1,228 @@ + + SUBTTL PAGING ROUTINES + PAGE + + + ;NORMALIZE ZPC & GET PROPER PAGE +; NEWZPC HAS BE EXTENDED TO UPDATE THE ZPCSEG VARIABLE. IT SETS THIS +; VARIABLE DIFFERENTLY ACCORDING TO PAGING SCHEME. IF THE GAME FITS IN +; MEMORY, ZPCSEG IS SET ACCORDING TO THE 17TH BIT OF THE ZPC, OTHERWISE +; IT IS SET WHEN CURSEG IS SET BY THE GETPAG ROUTINE INDICATING THAT +; THE CURRENT BLOCK IN THE SECOND ES SEGMENT. +; + PUBLIC NEWZPC,NWZ1$,NWZ2$,NWZ3$,NWZ4$,NWZ5$ +NEWZPC PROC + MOV LSTNGD,0 ; (A16) RESET NEXT AND GET BYTES + MOV LSTGGD,0 + PUSH SI ;SAVES + PUSH BP + PUSH BX + PUSH CX + PUSH DX + SUB AX,AX ;USE DOUBLE-WORD ARITHMETIC + MOV BX,ZPC1 ;GET BLOCK-POINTER + MOV CX,9 ; (A0) NUMBER OF SHIFTS NECESSARY +NWPC: SHL AX,1 ; (A0) SHIFT LEFT BEFORE ADD WITH CARRY + SHL BX,1 + ADC AX,0 + LOOP NWPC + MOV SI,ZPC2 ;GET BYTE-OFFSET + XCHG SI,AX ;DOUBLE-WORDIFY IT (MIGHT BE NEGATIVE) + CWD + XCHG SI,AX + ADD BX,SI ;ADD IT TO OTHER DOUBLE WORD + ADC AX,DX + MOV DX,BX + AND DX,1FFH ;EXTRACT BYTE-OFFSET + MOV ZPC2,DX ;SAVE IT + MOV CL,9 ;EXTRACT BLOCK-POINTER + SAR BX,CL + AND BX,7FH + CMP AX,0 ; (A0) BLOCK NUMBER > 2**16 + JE NWZ1A$ ;WAS 0 + MOV CL,7 ; (A0) OR IN BLOCK PTR BITS FROM AX + SHL AX,CL ; (A0) BY SHIFTING THIS OVER 7 X + OR BX,AX ;WAS 1, SET PROPER BIT IN BLOCK-POINTER + SHR AX,CL ; (A0) AND THEN RESTORE AX FOR BELOW + TEST FITS,1 ;(6) DO WE HAVE ALL OF THE GAME IN MEMORY + JZ NWZ1$ ; (6) BECAUSE PAGES ARE NOT CONTINUOUS + MOV ZPCSEG,AL ; (A0) AL HAS SEGMENT NUMBER + JMP NWZ1$ +NWZ1A$: TEST FITS,1 ;(6) SHOULD WE SET THIS HERE + JZ NWZ1$ ;(6) NO + MOV ZPCSEG,0 ;(6) SET SEGMENT TO BASE SEG +NWZ1$: MOV ZPC1,BX ;SAVE IT + TEST ZPCFLG,1 ;(7n) DO WE HAVE THE RIGHT BLOCK + JNZ NWZ1Q$ ;(7n) NO, SKIP THIS SKIP + CMP BX,CURBLK ;HAS IT CHANGED? + JE NWZ5$ ;NO +NWZ1Q$: MOV CURBLK,BX ;YES, REMEMBER NEW BLOCK + MOV AX,CURTAB ;IS OLD PAGE IN PAGING SPACE? + CMP AX,0 + JE NWZ2$ ;NO + MOV BP,AX ;YES, STORE CURRENT REF TIME FOR OLD PAGE + MOVM [BP],RTIME1,CX ;(A0) RET TBL TO 4 BYTES + MOVM [BP+2],RTIME2,CX ;(A0) EXPANDED BYTE TO WORD + INC AX +NWZ2$: CMP FITS,1 ;(6) IS THE WHOLE GAME THERE + JZ NWZ3$ ;(6) YES, GO DO WHATEVER + CMP BX,ENDLOD ;NEW PAGE ALREADY IN CORE? + JL NWZ3$ ;YES + MOV AX,BX ;NO, GET NEW PAGE + CALL GETPAG + MOV BL,CURSEG ;(6) SET ZPCSEG TO SAME AS CURSEG + MOV ZPCSEG,BL ;(6) SO THAT NXTBYT WORKS + MOV BX,AX + MOV AX,LPTAB ;GET NEW PAGE TABLE POINTER + ADD AX,2 ; (A0) POINT TO REF SLOT + MOV CURTAB,AX ;SAVE THIS POINTER FOR LATER + MOV BP,AX ;STORE HIGHEST RTIME TO KEEP PAGE FOR US + MOV WORD PTR [BP],-1 ;(A0) ADJUSTED TO WORD PTR + MOV WORD PTR [BP+2],-1 ;(A0) ADJUSTED FOR ABOVE WORD PTR + INC AX + JMP NWZ4$ +NWZ3$: MOV CL,9 ;CALCULATE PAGE ADDRESS + SHL BX,CL + TEST FITS,1 + JNZ NWZ3A$ ; (7z) SKIP DURING WHOLE MEMORY EDITION + MOV ZPCSEG,0 ; (7z) RESET THIS TO SEG0 +NWZ3A$: MOV CURTAB,0 ;CLEARING POINTER MEANS PAGE IS PRELOADED +NWZ4$: MOV CURPAG,BX ;UPDATE PAGE POINTER +NWZ5$: MOV ZPCFLG,0 ; (K3) RESET THIS FLAG + POP DX ;RESTORES + POP CX + POP BX + POP BP + POP SI + RET ;AND RETURN +NEWZPC ENDP + + ;GET THE PAGE WHOSE NUMBER IS IN AX, RETURN A POINTER TO IT IN AX +; GETPAG AND FINDPG WERE MODIFIED TO ACCOMMODATE THE EXTENDED PAGING +; SCHEMES. SEGEND, CURSEG AND PAGTAB ARE SIGNIFICANT VARIABLES IN THESE +; MODIFICATIONS. SEGEND IS USED TO COMPARE TO THE CURRENT LOCATION IN +; PAGTAB WHICH IN TURN INDICATES IN WHICH SEGMENT THE NEW BLOCK IS LOCATED. +; CURSEG IS SET TO TELL THE OUTSIDE WORLD WHICH SEGMENT THE LAST GETPAG +; TOUCHED. NOTE THAT BEING IN THE SECOND SEGMENT (SEG1) REQUIRES THAT +; ADDRESS CALCULATIONS DO NOT ADD IN PAGES (THE VARIABLE MARKING THE END +; OF PRELOAD). THIS REQUIREMENT IS NECESSARY BECAUSE THERE IS NO PRELOAD +; IN THE SECOND SEGMENT. +; + PUBLIC GETPAG,GTP1$,GTP2$,GTP2A$,GTP2B,GTP2C,GTP3$,GTP4$ +GETPAG PROC + CMP AX,LPAGE ;IS THIS THE SAME PAGE AS LAST REFERENCED? + JNE GTP1$ ;NO + MOV AX,LPLOC ;YES, WE ALREADY HAVE LOCATION + RET ;RETURN IT +GTP1$: MOV LPAGE,AX ;SAVE NEW PAGE NUMBER + PUSH CX ;SAVES + PUSH BX + ADD RTIME2,1 ;UPDATE REFERENCE TIME (COUNT) + ADC RTIME1,0 + MOV BX,OFFSET PAGTAB;PAGE INFORMATION TABLE +GTP2$: ADD BX,2 ; (A0) ADJUSTED FOR WORD SIZED BLKS + CMP AX,[BX-2] ;(A0) SEARCH FOR DESIRED BLOCK + JNE GTP3$ ;NOT IT + CMP AX,CURBLK ;IS THIS THE CURRENT CODE PAGE? + JE GTP2A$ ;DON'T UPDATE REFERENCE TIME + MOVM [BX],RTIME1,CX ; (A0) FOUND IT, UPDATE ITS REFERENCE TIME + MOVM [BX+2],RTIME2,CX ; (A0) ADJUSTED FOR DWORD REF TIME +GTP2A$: SUB BX,2 ;(A0) BACKUP TO BEGINNING OF TABLE ENTRY + PUSH BX ; (6) SAVE THIS BEFORE SCALING IT + SUB BX,OFFSET PAGTAB;(6) BASIFY THE PAGTABLE ENTRY + MOV AX,BX ; (A0) DON'T WASTE THIS MATH + CMP BX,SEGEND ;(6) CHECK IF PAGE IS IN 2ND SEGMENT + POP BX ; (6) RESTORE BX + JL GTP2B ;(6) NO, FUNCTION AS USUAL + MOV CURSEG,1 ; (A0) INIT SEG HUNT + SUB AX,SEGEND ; (A0) FIND SEG FOR THIS PAGE + MOV CL,TBLSHF ; (A0) DIVIDE RESULT BY TABLE WIDTH (2**X) + SHR AX,CL ; (A0) TO GET BUFFER NUMBER +GTP$: CMP AX,128 ; (A0) SCALE DOWN THE BUFFER NUMBER + JB GTP2C ; (A0) IS IT IN THIS SEG + INC CURSEG ; (A0) BUMP THE SEGMENT POINTER + SUB AX,128 ; (A0) AND LOOK AGAIN + JMP GTP$ ; (A0) +GTP2B: MOV CURSEG,0 ;(6) SET SEGMENT NUMBER TO 0 +GTP2C: MOV LPTAB,BX ;SAVE IT + SUB BX,OFFSET PAGTAB;CALCULATE ADDRESS OF PAGE + MOV CL,6 ; (A0) REAL BLK # IF IN SEG OTHER THAN 0 + CMP CURSEG,0 ; (A0) DO A DIFFERENT CALC FOR SEG0 + JZ GTP2D ; + MOV BX,AX ; (A0) GET BLOCK # FOR CURRENT SEGMENT + MOV CL,9 ; (A0) BLK NOT ALREADY MULTIPLIED BY 2 +GTP2D: SHL BX,CL + CMP CURSEG,0 ; (A0) SKIP ADDING IN PAGES IF NOT SEG0 + JNZ GTP4$ + ADD BX,PAGES + JMP GTP4$ ;AND RETURN PAGE POINTER +GTP3$: ADD BX,6 ;SKIP REFERENCE TIME + CMP WORD PTR [BX],-1;END OF TABLE? + JNE GTP2$ ;NO, CONTINUE SEARCH + CALL FINDPG ;YES, FIND A PAGE TO LOAD INTO + PUSH AX ;PAGE POINTER + MOV LPTAB,BX ;SAVE PAGE TABLE POINTER + MOV AX,LPAGE ;SAVE NEW BLOCK NUMBER + MOV [BX],AX ; (A0) MAKE STORAGE WORD SIZED + MOVM [BX+2],RTIME1,CX; (A0) AND CURRENT REF TIME + MOVM [BX+4],RTIME2,CX; (A0) DOUBLE WORDIFY + POP BX ;PAGE POINTER + CALL GETBLK ;GET THE BLOCK +GTP4$: MOV AX,BX ;RETURN PAGE POINTER + MOV LPLOC,AX ;AND SAVE IT FOR LATER + POP BX ;RESTORES + POP CX + RET +GETPAG ENDP + + ;FIND A GOOD PAGE, RETURN PAGE POINTER IN AX & PAGTAB POINTER IN BX +; SEE COMMENTS UNDER GETPAG + PUBLIC FINDPG,FNP1$,FNP2$,FNP3$,FNP4$ +FINDPG PROC + PUSH CX + MOV BX,OFFSET PAGTAB + MOV CX,-1 ;FAKE BEST-CASE REFERENCE COUNT + MOV DX,CX + ADD BX,2 ; (A0) SKIP BLOCK NUMBER FOR NOW +FNP1$: ADD BX,2 ; (A0) IS THIS REF TIME WORSE THAN CUR + CMP [BX-2],CX ; (A0) WORDIFY + JA FNP3$ ;NO + JB FNP2$ ;YES + CMP [BX],DX ;MAYBE, COMPARE LOW-ORDER WORDS, WORSE? + JAE FNP3$ ;NO +FNP2$: MOV CX,[BX-2] ; (A0) YES, SAVE ITS REF COUNT + MOV DX,[BX] + MOV AX,BX ;AND LOCATION (+2) +FNP3$: ADD BX,6 ; (A0) SKIP SECOND WORD + CMP WORD PTR [BX-2],-1 ; (A0) LOOP UNTIL END OF TABLE (WORD LD2) + JNE FNP1$ + INC DX ; (LD2) + JNE FNP8$ ; BOTH MUST BE $FF (LD2) + INC CX ;WAS A PAGE REALLY FOUND? + JE FNP4$ ;NO, GROSS BUG! +FNP8$: SUB AX,4 ; (A0) YES, CALCULATE CORE LOCATION OF PAGE + + MOV BX,AX + SUB AX,OFFSET PAGTAB + CMP AX,SEGEND ; (6) CHECK SEGMENT + JL FNP5$ ; (6) IN SEG0, SET CURSEG + MOV CURSEG,1 ; (6) SET CURSEG TO SEG1 + SUB AX,SEGEND ; (6) SCALE DOWN THE PAGE PTR + MOV CL,TBLSHF ; (A0) DIVIDE BUFFER ADDR BY 8 + SHR AX,CL ; (A0) TO DETERMINE ADDR + MOV CL,9 ; (A0) ASSUME A BLOCK # IN AX +FNP4A$: CMP AX,128 ; (A0) FOUND THE SEG? + JB FNP6$ ; (A0) YUP... + SUB AX,128 ; (A0) LOOK FOR NEXT SEG + INC CURSEG ; (A0) INCREMENT SEGMENT NUMBER + JMP FNP4A$ ; (A0) SEARCH ONWARD +FNP5$: MOV CURSEG,0 + MOV CL,6 ; (A0) SHIFT COUNT DEC'ED BY ONE (TBL WIDTH) +FNP6$: SHL AX,CL + CMP CURSEG,0 ; (A0) DON'T ADD IN PAGES IF NOT IN SEG0 + JNZ FNP7$ + ADD AX,PAGES +FNP7$: POP CX ;RESTORES + RET +FNP4$: FATAL FTL6 +FINDPG ENDP + diff --git a/ibm/printops.ezp b/ibm/printops.ezp new file mode 100644 index 0000000..731f21c --- /dev/null +++ b/ibm/printops.ezp @@ -0,0 +1,89 @@ + SUBTTL PRINTOPS + PAGE + + ;PRINTC (PRINT CHAR WHOSE ASCII VALUE IS GIVEN) + PUBLIC OPPRNC,OPPRNN +OPPRNC PROC + JMP PUTCHR ;QUEUE THE CHARACTER FOR PRINTING +OPPRNC ENDP + + ;PRINTN (PRINT A NUMBER) +OPPRNN PROC + MOV BX,AX ;NUMBER TO PRINT + CMP BX,0 + JNE OPN1$ ;NON-ZERO + MOV AX,"0" ;SPECIAL CASE ZERO + JMP PUTCHR +OPN1$: JG OPN2$ ;POSITIVE? + MOV AX,"-" ;NO, PRINT MINUS SIGN + CALL PUTCHR + NEG BX ;AND MAKE IT POSITIVE +OPN2$: SUB CX,CX ;COUNT OF DIGITS ON STACK + JMP OPN4$ ;START WITH GREATER-THAN-10 TEST +OPN3$: MOV AX,BX ;EXTRACT A DIGIT + MOV BP,10 + CWD + IDIV BP + PUSH DX ;PUSH IT + INC CX ;BUMP COUNT + MOV BX,AX ;GET QUOTIENT +OPN4$: CMP BX,10 ;MORE DIGITS TO EXTRACT? + JGE OPN3$ ;YES, GO LOOP + MOV AX,BX ;NO, GET LAST (FIRST) DIGIT + JMP OPN6$ ;ALREADY IN PLACE +OPN5$: POP AX ;POP NEXT DIGIT +OPN6$: ADD AX,"0" ;ASCIIZE IT + CALL PUTCHR ;QUEUE IT + DEC CX ;REDUCE DIGIT COUNT + JGE OPN5$ ;LOOP IF SOME LEFT + RET ;ELSE, RETURN +OPPRNN ENDP + + PUBLIC OPPRIN,OPPRNB + ;PRINT (THE STRING POINTED TO BY ES:AX) +OPPRIN PROC + CALL BSPLITQ ; (A0) SPLIT THE BLOCK & WORD NUMBERS (QUAD) + JMP PUTSTR ;PRINT THE STRING +OPPRIN ENDP + + ;PRINTB (PRINT THE STRING POINTED TO BY THE BYTE-POINTER ES:AX) +OPPRNB PROC + CALL BSPLTB ;SPLIT THE BLOCK & BYTE NUMBERS + JMP PUTSTR ;PRINT THE STRING +OPPRNB ENDP + + + PUBLIC OPPRND,OPPRNI,OPPRNR + ;PRINTD (PRINT OBJ'S SHORT DESCRIPTION) +OPPRND PROC + CALL OBJLOC ;FIND OBJ'S LOCATION + MOV BP,AX + GTAWRD A,[BP].PROPS ; (A0) GET IT + INC AX ;POINT TO STRING + CALL BSPLTB ;SPLIT POINTER + JMP PUTSTR ;AND PRINT THE STRING +OPPRND ENDP + + ;PRINTI (PRINT THE STRING FOLLOWING THIS INSTRUCTION) +OPPRNI PROC + MOV LSTNGD,0 ; (A16) LAST NXT BYTE RUINED + MOV AX,ZPC1 ;GET POINTER TO STRING + MOV BX,ZPC2 + CALL PUTSTR ;AND PRINT IT + MOV ZPC1,AX ;UPDATE ZPC + MOV ZPC2,BX + JMP NEWZPC +OPPRNI ENDP + + ;PRINTR (PRINTI FOLLOWED BY RTRUE) +OPPRNR PROC + CALL OPPRNI ;DO A PRINTI + CALL OPCRLF ;A CRLF + JMP OPRTRU ;AND AN RTRUE +OPPRNR ENDP + + PUBLIC OPCRLF + ;CRLF (DO A NEWLINE) +OPCRLF PROC + JMP NEWLIN ;DO A NEWLINE +OPCRLF ENDP diff --git a/ibm/random.ezp b/ibm/random.ezp new file mode 100644 index 0000000..242f211 --- /dev/null +++ b/ibm/random.ezp @@ -0,0 +1,72 @@ + SUBTTL RANDOM + PAGE + + ; ------ + ; OPRAND + ; ------ + ; + ; {MODE 1} + ; IF ARG1 IS POSITIVE AND WE ARE NOT CURRENTLY IN NON RAMDOM MODE, + ; RETURN A VALUE BETWEEN 1 AND ARG1 INCLUSIVE. + ; + ; {MODE 2} + ; IF ARG1 IS NEGATIVE (2'S COMPLEMENT), THEN [ARG1] IS SAVED AND + ; RANDOM GENERATES NUMBERS IN SEQUENCE FROM 1 TO [ARG1], RETURNING + ; A "0" THE FIRST TIME. + ; + ; IF ARG1=0, THEN THE RANDOM NUMBER GENERATOR IS PUT INTO {MODE 1}, + ; AND A "0" IS RETURNED. + + + PUBLIC OPRAND,OPRND1,OPRND2,OPRND3,OPRND4 +OPRAND PROC + CMP AX,0 ; (A0) CHECK ARGUMENT + JNE OPRND1 ; (LD1) + MOV SRHOLD,AX ; (LD1) RESET THE INDICATOR FOR RANDOM RANDOM + JMP PUTVAL ; (LD1) AND RETURN 0 + +OPRND1: CMP SRHOLD,0 ; (LD1) IF IN MIDDLE OF + JNE OPRND3 ; (LD1) NON RANDOM - CONTINUE + CMP AX,0 ; (LD1) NO - IF # IS POSITIVE + JG OPRND2 ; (LD1) CREATE NORMAL RANDOM # + + ; INIT NON RANDOM NUMBER (MODE 2) + + SUB DX,DX ; (LD1) GET ABSOLUTE VALUE + SUB DX,AX + MOV SRHOLD,DX ; (LD1) HOLD TOP OF RANGE + MOV RNUM,0 ; (LD1) SET # TO ZERO 1ST TIME + MOV AX,0 ; (LD1) AND RETURN 0 1ST TIME + JMP PUTVAL + +OPRND2: ; MODE 1 NORMAL RANDOM NUMBER GENERATION + MOV RTEMP,AX ;(A0) SAVE ARGUMENT FOR LATER + MOV AX,RSEED1 + MOV BX,RSEED2 + MOV RSEED2,AX + CLC + RCR AX,1 + RCR BX,1 + XOR RSEED1,BX ;(A0) PUT XOR'D NUBMER INTO RSEED1 + MOV AX,RSEED1 ;(A0) THIS IS RANDOM VALUE + + AND AX,07FFFH ;(LD1)(A0) CHOP HIGH BIT FOR DIVIDE + SUB DX,DX ;(A0) CLEAR MOST SIGN. PORTION OF 32 BIT WORD + DIV RTEMP ;(A0) DIVIDE WORD BY WORD + MOV AX,DX ;(A0) MOVE REMAINDER INTO AX + INC AX ;(A0) MAKE SURE NO ZERO + JMP PUTVAL + + + ; UPDATE "RANDOM" NUMBER, THEN RETURN IT +OPRND3: CMP AX,0 ; (LD1) + JL OPRND4 ; (LD1) NEGATIVE INPUT + MOV SRHOLD,AX ; (LD1) ELSE UPDATE TOP OF RANGE +OPRND4: INC RNUM ; (LD1) NEXT VALUE + MOV AX,RNUM ; (LD1) + CMP AX,SRHOLD ; (LD1) WITHIN RANGE + JBE OPRND5 ; (LD1) YES + MOV AX,1 ; (LD1) + MOV RNUM,AX ; (LD1) ELSE RESTART SEQUENCE +OPRND5: JMP PUTVAL ; (LD1) BOTH AX & RNUM ALL SET +OPRAND ENDP diff --git a/ibm/readio.ezp b/ibm/readio.ezp new file mode 100644 index 0000000..24cb157 --- /dev/null +++ b/ibm/readio.ezp @@ -0,0 +1,937 @@ + SUBTTL READIO - I/O OPERATIONS + PAGE + + + PUBLIC GETLIN +GETLIN PROC + MOV AX,CX ; (A0) AX HAS NUMBER OF ARGS TO READ + PUSH BX + MOV SCRHLD,1 ; (7n) HOLD SCRIPTING + PUSH SI + MOV CL,ES:[SI] + MOV BX,OFFSET INBUF + MOV BYTE PTR [BX],CL + CMP CL,MAXLIN ; (7r) DON'T EXCEED BUFFER LENGTH + JBE GTLN0 ; (7r) FIX IF ABOVE + MOV BYTE PTR [BX],MAXLIN ; (7r) WITH OUR NEW MAXIMUM +GTLN0: MOV DX,BX + CMP AX,2 ; (A0) TIME OUT VERSION? + JBE GTLNA ; (A0) TWO TABLES, GET NORMALLY + MOV BX,OFFSET ARGBLK ; (A0) GET ADDR OF ARGBLK + MOV AX,[BX+4] ; (A0) GET THE DELAY COUNT + MOV BX,[BX+6] ; (A0) AND THE TIMEOUT FUNCTION + PUSH SI ; (A0) SI IS GETTING WRECKED??? + CALL LININP ; (A0) CALL TIMEOUT INPUT ROUTINE + POP SI ; (A0) SO I PRESERVED IT + JMP GTLNB ; (A0) SKIP NORMAL CALL + + +;GTLNA: MOV AH,CRDLIN +; INT 21H + +GTLNA: CALL RDLIN ;(A9) + +GTLNB: TEST SCROLL,1 ;(7) WHAT KIND OF SCROLLING + JNZ GTLN1 + MOV AH,SCROLLUP ;(7) USE A VIDEO BIOS SCROLL + MOV AL,1 ;(7) ONLY 1 LINE + MOV CX,TOPLIN ;(7) ALWAYS FREEZE TOP LINE + MOV DH,SLPP ;(7) GET SCREEN LENGTH + MOV DL,SCPL ;(7) GET THE WIDTH OF THE SCREEN + DEC DL ; (7v) COORDINATES ARE ZERO BASED + MOV BH,SCRATR ;(7) GET THE SCREEN ATTRIBUTE + INT 10H ;(7) CALL THE VIDEO + JMP GTLN2 ;(7) SKIP LINE FEED OUTPUT +GTLN1: MOV AH,CCONIO + MOV DL,10 + INT 21H +GTLN2: POP DX + MOV BX,OFFSET INBUF + MOV CL,BYTE PTR [BX+1] + SUB CH,CH + INC BX + CMP CL,0 + JE GETLEM +GETLLP: INC SI + INC BX + MOV AL,BYTE PTR [BX] + CMP AL,"A" + JL GETLLC + CMP AL,"Z" + JG GETLLC + ADD AL,32 +GETLLC: MOV ES:[SI],AL + LOOP GETLLP +GETLEM: INC SI + SUB AL,AL + MOV ES:[SI],AL + MOV SCRHLD,0 ; (7n) TURN OFF SCRIPT HOLD + POP BX + RET +GETLIN ENDP + + PUBLIC PRTOUT +PRTOUT PROC + PUSH AX + PUSH BX + PUSH CX + PUSH DX ; (7) SAVE THIS, USING STD PRT + TEST WORD PTR ES:[PFLAGS],SCRPTBT ; (A17) SCRIPTING ON? + JZ POUT2 ; (A17) NOPE + TEST CMDLIN,16 ; (7n) DO WE WANT IBM PRINTER + JZ POUT1 ; (7n) GUESS NOT +POUT0: MOV AH,0 ; (7) FUNCTION TO PRINT + MOV DX,0 ; (7) TO THE FIRST PRINTER + INT 17H ; (7) TRY IT + TEST AH,RDYBIT ; (7) TIME OUT? + JZ POUT2 ; (7) WORKED, RETURN + CALL PRNRDY ; (7) + JC POUT2 + JMP POUT0 ; (7) RETRY +POUT1: MOV DL,AL ; (7n) GET CHARACTER TO PRINT + MOV AH,CPROUT ; (7n) PRINT IT + INT 21H +POUT2: POP DX ; (7n) FORGET THIS AND BREAK... + POP CX + POP BX + POP AX + RET +PRTOUT ENDP + + PUBLIC PRNRDY +PRNRDY PROC + OR WORD PTR ES:[PFLAGS],REFRESH ;(E0) REFRESH THE STATUS LINE + PUSH AX + MOV SCRHLD,1 ; (7n) HOLD OFF SCRIPTING + PRINT PRNNRDY ; (7) ASK USER ABOUT ACTION +RDY1: CALL MCHRI ; (7) GET A RESPONSE + CALL MTTYO ; (7u) ECHO THE CHARACTER + AND AL,5FH ; (7) UPPPER CASIFY + CMP AL,'A' ; (7) SHOULD WE ABORT + JNZ RDY2 ; (7) ATTEMPTING RETRY + MOV SCRFLG,0 ; (7) TURN OFF SCRIPTING + + ; (A10) COMMENTED OUT LINE +; AND ES:[PFLAGS],SCRMSK ; (7) AND IN THE MODE WORD + + MOV SCRHLD,0 ; (7n) TURN OFF BAN ON SCRIPTING + STC ; (7) SET CARRY FOR NO RETRY + PUSHF ; (7) SAVE THESE + JMP RDY3 ; (7) CR LF ON EXIT +RDY2: CMP AL,'R' ; (7) RETRY??? + JNZ RDY1 ; (7) WRONG CHARACTER + CLC ; (7) CLEAR CARRY FOR RETRY + PUSHF ; (7) SAVE FLAGS +RDY3: CALL MCRLF ; (7) DO A + MOV SCRHLD,0 ; (7n) TURN OFF BAN ON SCRIPTING + POPF ; (7) RESTORE FLAGS AND + POP AX ; (7) CHARACTER TO PRINT + RET +PRNRDY ENDP + +SCRCHK PROC + PUSH AX + PUSH BX + PUSH DX + TEST SCRFLG,1 ; (A11) IS SCRIPTING ENABLED? + JNZ SCR0L$ ; (7x) ....YES, CONTINUE + JMP SCREX$ ; (A11)....NO + + +; MOV SCRFLG,1 ; (7n) TURN ON SCRIPT FLAG +; CMP SCROLL,0 ; (7) SHOULD WE BE DOING THIS? +; JNZ SCR0L$ ; (7) NOPE... +; TEST CMDLIN,16 ; (7n) DID WE REALLY REQUEST IBM +; JZ SCR0L$ +;SCR_1$: MOV DX,0 ; (7) TRY TO INIT THE PRINTER +; MOV AH,1 +; INT 17H ; (7) SO THAT WE WILL TIME OUT FAST +; TEST AH,PRTMSK ; (7) TEST FOR TIME OUT +; JZ SCR0L$ ; (7) NO PROBLEM, WE'RE FINE +; CALL PRNRDY ; (7) INFORM USER OF PROBLEM +; JNC SCR_1$ +; JMP SCRNN$ ; (7) TURN OFF SCRIPTING + + +SCR0L$: SUB CX,CX + MOV BP,DX + INC BP +SCR1L$: MOV AL,ES:[BP] + INC BP + CMP BP,SI + JLE SCR2L$ + CALL PRTCRL + JMP SCREX$ +SCR2L$: CALL PRTOUT + INC CX + CMP CL,SCPL + JNE SCR1L$ + CALL PRTCRL + JC SCREX$ + SUB CX,CX + JMP SCR1L$ + +SCRNN$: MOV SCRFLG,0 +SCREX$: POP DX + POP BX + POP AX + RET +SCRCHK ENDP + + PUBLIC PRTCRL +PRTCRL PROC + TEST WORD PTR ES:[PFLAGS],SCRPTBT ;(A18) DON'T SCRIPT READ + JNZ PRTC1 + RET +PRTC1: MOV AL,13 ;FINISH UP WITH CRLF + CALL PRTOUT + MOV AL,10 + CALL PRTOUT +; OR WORD PTR ES:[PFLAGS],REFRESH ; (A17) SET THE REFRESH BIT + RET +PRTCRL ENDP + + ;READ (A LINE OF INPUT & PARSE IT, LINE BUF IN ES:AX, + ;RETURN BUF IN ES:BX) + PUBLIC OPREAD,ORD1$,ORDNS$,ORD8$,ORD9$,ORD10$,ORD1A$,ORD11$,ORD12$ +; PUBLIC ORD13$,ORD14$,ORD15$,ORD16$,ORD17$,ORD18$,ORD19$,ORD20$ +; PUBLIC ORD21$,ORD22$,ORD23$ +OPREAD PROC + NOP ; (A0) GET ARGS IN ARGBLK + MOV CX,AX ; (A0) GET # OF ARGS + MOV BX,OFFSET ARGBLK + MOV AX,[BX] ; (A0) GET FIRST TWO ARGS INTO AX & BX + MOV BX,[BX+2] + PUSH AX ;SAVE LINE BUF + MOV BP,CHRPTR ;NEXT CHARACTER POSITION + MOV BYTE PTR DS:[BP],80H ;(6)DON'T END OUTPUT, IF ANY, WITH CRLF +ORD1$: PRINT OUTBUF ;FORCE OUT ANY QUEUED TEXT + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + POP SI ;INPUT BUFFER POINTER + MOV MORLIN,0 ;RE-INITIALIZE MORE COUNT FROM HERE + MOV CHRCNT,BUFLEN ; (A15) RE-INITIALIZE THE CHAR COUNTER + CALL GETLIN ;GET SOME CHARACTERS + + CALL SCRCHK ;PRINT THE BUFFER IF SCRIPTING IS ON + +ORDNS$: PUSH DI + MOV RDBOS,DX ;INITIALIZE RDBOS + MOV RDEOS,SI ;AND RDEOS + MOV RDRET,BX ;STORE RET POINTER + MOV RDNWDS,0 ;NO WORDS SO FAR + INC DX ;SKIP LENGTH BYTE + MOV DI,BX ;THIS WILL BE WORD ENTRY POINTER + INC DI ;SKIP MAX WORDS & NWORDS BYTES + INC DI +ORD8$: MOV CX,OFFSET RDWSTR;HERE FOR NEXT WORD, POINT TO WORD STRING + MOV BX,DX ;AND SAVE BEGINNING OF WORD POINTER +ORD9$: CMP DX,RDEOS ;END OF STRING? + JNE ORD10$ ;NO + CMP CX,OFFSET RDWSTR;YES, WAS A WORD FOUND? + JNE ORD15$ ;YES, WE STILL HAVE TO LOOKUP WORD + JMP ORD23$ ;NO, WE'RE DONE +ORD10$: MOV BP,DX ;GET NEXT CHARACTER FROM BUFFER + MOV AL,ES:[BP] + CMP AL,"A" + JL ORD1A$ + CMP AL,"Z" + JG ORD1A$ + ADD AL,32 ;LOWERCASIFY ALPHABETICS +ORD1A$: INC DX + MOV SI,OFFSET RBRKS ;LIST OF READ BREAK CHARACTERS +ORD11$: INC SI + CMP AL,[SI-1] ;SEARCH LIST FOR THIS ONE + JE ORD12$ ;FOUND IT + CMP BYTE PTR [SI],0 ;END OF LIST? + JNE ORD11$ ;NO, CONTINUE SEARCH + CMP CX,OFFSET RDWSTR[9] ;YES, NOT A BREAK, WORD STRING FULL? + JE ORD9$ ;YES, LOOP UNTIL END OF WORD + MOV BP,CX ;NO, TACK THIS CHARACTER ONTO STRING + MOV DS:[BP],AL + INC CX + JMP ORD9$ ;AND LOOP +ORD12$: CMP CX,OFFSET RDWSTR;WORD READ BEFORE THIS BREAK? + JNE ORD14$ ;YES + CMP SI,ESIBKS ;NO, BUT IS IT A SELF-INSERTING BREAK? + JBE ORD13$ ;YES + INC BX ;NO, UPDATE BEGINNING OF WORD TO SKIP BREAK + JMP ORD9$ ;AND RETURN TO LOOP TO FIND A WORD +ORD13$: MOV BP,CX ;STORE THE BREAK IN WORD STRING + MOV DS:[BP],AL + INC CX + JMP ORD15$ ;AND GO FOR THE WORD +ORD14$: DEC DX ;UNREAD TERMINATING BREAK IN CASE IT WAS SI +ORD15$: INC RDNWDS ;INCREMENT FOUND WORD COUNT + MOV BP,BX ;GREATER THAN MAX ALLOWED? + MOV BX,RDRET + MOV BL,ES:[BX] + CMP BL,59 ; (7w) GAME FIX + JBE ORD15A ; (7w) FIX NUMBER OF TOKENS ALLOWED + MOV BL,59 ; (7w) OTHERWISE WE OVERRUN A TABLE +ORD15A: CMP RDNWDS,BL + MOV BX,BP + JLE ORD16$ ;NO + PRINT ERR2 ;YES, INFORM LOSER + MOV AX,BX ;BEGINNING OF THIS WORD + MOV BP,RDEOS ;SAVE BYTE AFTER EOS + MOV BL,ES:[BP] + MOV BYTE PTR ES:[BP],0 ; ZERO IT TO MAKE STRING ASCIZ + PUSH BX ; (7w) SAVE THIS ADDRESS + MOV BX,DS ; (7w) FIGURE WHERE STRING IS IN DS + NEG BX ; (7w) SUBTRACT DS FROM ES + ADD BX,GAMESEG ; (7w) BX HAS PARAGRAPHS OF DIFFERENCE + MOV CL,4 ; (7w) CONVERT TO AN OFFSET + SHL BX,CL ; (7w) TO ADD IN WITH AX + ADD AX,BX ; (7w) NOW DS:AX SHOULD EQUAL PREV ES:AX + POP BX ; (7w) RESTORE BX + CALL MPRNT ;PRINT IT + MOV ES:[BP],BL ; AND RESTORE OLD BYTE + DEC RDNWDS ;REMEMBER THAT WE FLUSHED THIS WORD + JMP ORD23$ ;AND WE'RE DONE +ORD16$: MOV AX,BX ;CALCULATE NUMBER OF CHARACTERS IN WORD + NEG AX + ADD AX,DX + MOV ES:[DI+2],AL ;(6)SAVE THE NUMBER IN RET TABLE + SUB BX,RDBOS ;BYTE OFFSET FOR BEGINNING OF WORD + MOV ES:[DI+3],BL ;(6)STORE IT, TOO + MOV BP,CX ;MAKE WORD STRING ASCIZ + MOV BYTE PTR DS:[BP],0 ;(6) REMOVED SEG OVERRIDE (DS) + MOV AX,OFFSET RDWSTR;POINT TO IT + CALL ZWORD ;AND CONVERT TO (2-WORD) ZWORD + MOV ZTHIRD,CX ; (A0) SAVE THIRD WORD + PUSH DX ;SAVE CHAR & WORD ENTRY POINTERS + PUSH DI + MOV DI,AX ;FIRST ZWORD WORD + MOV SI,VWORDS ;NUMBER OF VOCABULARY WORDS + MOV AX,SI + DEC AX ;WE WANT TO POINT TO LAST WORD + MUL VWLEN ;MULTIPLY BY WORD LENGTH IN BYTES + ADD AX,VOCBEG ;ADD POINTER TO BEGINNING TO FIND LAST WORD + MOV CX,AX ;POINTER TO LAST WORD + MOV DX,DI ;FIRST ZWORD WORD + MOV DI,BX ;SECOND ZWORD WORD + MOV BX,VWLEN ;CALCULATE INITIAL OFFSET FOR BINARY SEARCH + SAR SI,1 +ORD17$: SAL BX,1 + SAR SI,1 + CMP SI,0 + JNE ORD17$ + MOV SI,VOCBEG ;BEGINNING OF WORD TABLE + ADD SI,BX ;ADD CURRENT OFFSET(HALF OF POWER-OF-2 TABLE) + PUSH AX ;SAVE + MOV AX,VWLEN ;AVOID FENCEPOST BUG FOR EXACT POWER-OF-2 TBL + SUB SI,AX + POP AX ;RESTORE +ORD18$: SAR BX,1 ;NEXT OFFSET WILL BE HALF OF PREVIOUS ONE + GTAWRD A,[SI] ;GET FIRST HALF OF CURRENT ZWORD + CMP DX,AX ;COMPARE DESIRED ONE TO IT + JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + MOV BP,SI ;SAME, GET SECOND HALF + ADD BP,2 ; (A0) LOOK AT SECOND WORD + GTAWRD A,[BP] + CMP DI,AX ;COMPARE DESIRED WORD WITH IT + JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP + JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN + MOV BP,SI ; (A0) SAME, GET SECOND HALF + ADD BP,4 ; (A0) LOOK AT THIRD WORD + GTAWRD A,[BP] ; (A0) + CMP ZTHIRD,AX ; (A0) COMPARE DESIRED WORD WITH IT + JA ORD19$ ; (A0) GREATER, WE'LL HAVE TO MOVE UP + JB ORD20$ ; (A0) LESS, WE'LL HAVE TO MOVE DOWN + JMP ORD22$ ;SAME, WE'VE FOUND IT, RETURN IT +ORD19$: ADD SI,BX ;TO MOVE UP, ADD CURRENT OFFSET + jc ORD24$ ; overflowed a segment, set back to end + CMP SI,CX ;HAVE WE MOVED PAST END OF TABLE? + JBE ORD21$ ;NO +ORD24$: MOV SI,CX ;YES, POINT TO END OF TABLE INSTEAD + JMP ORD21$ +ORD20$: SUB SI,BX ;TO MOVE DOWN, SIMPLY SUBTRACT OFFSET +ORD21$: CMP BX,VWLEN ;IS OFFSET RESOLUTION BELOW ONE WORD? + JGE ORD18$ ;NO, CONTINUE LOOP + SUB SI,SI ;YES, WORD NOT FOUND, RETURN ZERO +ORD22$: POP DI ;RESTORE WORD ENTRY POINTER + MOV DX,SI ;POINTER TO WORD FOUND + XCHG DH,DL + MOV ES:[DI],DX ;(6) STORE IT + POP DX ;RESTORE CHAR POINTER + ADD DI,4 ;UPDATE POINTER FOR NEXT WORD ENTRY + JMP ORD8$ ;GO FOR IT +ORD23$: INC RDRET ;DONE, STORE NUMBER OF WORDS FOUND + MOV BP,RDRET + MOVM ES:[BP],RDNWDS,DL ; REMOVED ES OVERRIDE + POP DI ;RESTORE USER STACK POINTER + RET ;AND RETURN +OPREAD ENDP + + PUBLIC OPBFOUT +OPBFOUT PROC + CMP AX,0 ; (A0) WHAT DO WE WANT? + JNZ BUFFED ; (A0) TURN OFF BUFFERED INPUT + MOV BUFBIT,0 ; (A0) SET FLAG + PUSH BX + MOV BX,CHRPTR ; (A0) LOCATION FOR NEXT CHAR + MOV BYTE PTR [BX],80H ; (A0) INDICATE END OF STRING + PRINT OUTBUF ; (A0) FLUSH THE BUFFER + MOV BX,OFFSET OUTBUF ; (A0) GET BUFFER ADDR + MOV CHRPTR,BX ; (A0) RESET THE CHRPTR + POP BX ; (A0) RESTORE BX + RET +BUFFED: MOV BUFBIT,1 ; (A0) TURN BUFFERING BACK ON + RET +OPBFOUT ENDP + + PUBLIC OPDIRIN +OPDIRIN PROC + RET +OPDIRIN ENDP + + ; + ; SELECT OR DESELECT A VIRTUAL OUTPUT DEVICE + ; + + PUBLIC OPDIROU +OPDIROU PROC + OR AL,AL ; (A10) ENABLE OR DISABLE A DEVICE + JNS ODIR0 ; (A10) IF (+) IT'S ENABLE + JMP ODIR5 ; (A10) IF (-) IT'S DISABLE + + ; {CASE} DEVICE ENABLE HANDLER +ODIR0: CMP AL,1 ; (A10) IS IT THE SCREEN? + JNE ODIR1 ; (A10) NOPE + + ; {SUBCASE} SCREEN HANDLER + MOV VIDFLG,1 ; (A10) TURN SCREEN ON + RET + +ODIR1: CMP AL,2 ; (A10) IS IT THE SCRIPT DEVICE? + JNE ODIR2 ; (A10) NOPE + + ; {SUBCASE} SCRIPT HANDLER + PUSH AX + PUSH BX + PUSH DX + TEST SCRFLG,1 ; (A11) IS SCRIPTING ALREADY ENABLED? + JNZ ODIR1B ; (A11) ....YES +; + OR WORD PTR ES:[PFLAGS],SCRPTBT ;(A18) TURN ON SCRIPT FOR HI + MOV SCRFLG,1 ; (A18) TURN ON ZIP FLAG + + TEST CMDLIN,16 ; (A11) DID WE REALLY REQUEST IBM? + JZ ODIR1B ; (A11) ....YES + + ; INITIALIZE PRINTER +ODIR1A: MOV DX,0 ; TRY TO INIT THE PRINTER + MOV AH,1 + INT 17H ; SO THAT WE WILL TIME OUT FAST + TEST AH,PRTMSK ; TEST FOR TIME OUT + JZ ODIR1B ; NO PROBLEM, WE'RE FINE + CALL PRNRDY ; INFORM USER OF PROBLEM + JNC ODIR1A + + ; THE PRINTER WOULDN'T INITIALIZE + XOR AH,AH ; (A13) DISABLE SCRIPTING + MOV SCRFLG,AH ; (A13) + OR AH,STSBIT ; (A13) TURN ON STATUS LINE REFRESH BIT + XOR AL,AL ; (A13) + XCHG AH,AL ; (A18) BYTE SWAP + MOV WORD PTR ES:[PFLAGS],AX ; (A13) LET HIGH LEVEL KNOW + +ODIR1B: POP DX + POP BX + POP AX + RET + +ODIR2: CMP AL,3 ; (A10) IS IT THE TABLE DEVICE? + JNE ODIR3 ; (A10) NOPE + + ; {SUBCASE} TABLE HANDLER + MOV AL,BUFBIT ; (A0) GET STATE OF BUFBIT + MOV PREVBUF,AL ; (A0) AND SAVE IT FOR LATER +; (B0) Dirout should not flush the buffer +; MOV AX,0 ; (A0) USE TO CALL BUFOUT +; CALL OPBFOUT ; (A0) TURN OFF BUFBIT AND FLUSH + MOV BUFBIT,0 ; (B0) TURN OFF BUFBIT + MOV RDIR,1 ; (A0) STORE REDIRECTION FLAG + MOV RTABLE,BX ; (A0) ZEROTH ELEMENT OF TABLE + MOV RDIROUT,0 ; (A0) ZERO THE NUMBER OF BYTES READ + ADD BX,2 ; (A0) THIS IS TABLE+2 + MOV RTABLE2,BX ; (A0) AND TABLE LOCATION (IF INT IS <> 1) + RET + +ODIR3: CMP AL,4 ; (A10) IS IT A FILE? + JNE ODIR4 ; (A10) NOPE, DON'T HANDLE IT + + ; {SUBCASE} FILE HANDLER + ; NOT IMPLIMENTED +ODIR4: RET + + ; + + ; {CASE} DEVICE DISABLE HANDLER +ODIR5: CMP AL,0FFH ; (A10) IS IT THE SCREEN? + JNE ODIR6 ; (A10) NOPE + + ; {SUBCASE} SCREEN HANDLER + MOV VIDFLG,0 ; (A10) TURN SCREEN OFF + RET + +ODIR6: CMP AL,0FEH ; (A10) IS IT THE SCRIPT DEVICE? + JNE ODIR7 ; (A10) NOPE + + ; {SUBCASE} SCRIPT HANDLER + MOV SCRFLG,0 ; (A18) TURN OFF SCRIPTING + AND WORD PTR ES:[PFLAGS],SCRMSK +; XOR AH,AH ; (A13) DISABLE SCRIPTING +; MOV SCRFLG,AH ; (A13) +; OR AH,STSBIT ; (A13) TURN ON STATUS LINE REFRESH T +; XOR AL,AL ; (A13) +; MOV ES:[PFLAGS],AX ; (A13) LET HIGH LEVEL KNOW + RET + +ODIR7: CMP AL,0FDH ; (A10) IS IT THE TABLE DEVICE? + JNE ODIR8 ; (A10) NOPE + + ; {SUBCASE} TABLE HANDLER + CMP RDIR,0 ; (C0) IF ALREADY OFF + JE OUT7 ; (C0) LEAVE AS IS + + MOV AL,PREVBUF ; (A0) GET PREVIOUS STATE OF BUFFER + MOV BUFBIT,AL ; (A0) AND RESTORE THAT STATE + MOV RDIR,0 ; (A0) AND RESTORE REDIRECTION TO SCREEN + MOV AX,RDIROUT ; (A0) GET NUMBER OF CHARS WRITTEN + MOV BX,RTABLE ; (A0) GET ADDR OF ZEROTH ELEMENT + PTAWRD ES:[BX],A ; (A0) PUT THE WORD INTO THE TABLE + MOV BX,RTABLE2 ; (A18) GET FIRST ELEMENT + MOV BYTE PTR ES:[BX],0 ; (A18) DROP IN A NULL +OUT7: RET ; (C0) + +ODIR8: CMP AL,0FCH ; (A10) IS IT A FILE? + JNE ODIR9 ; (A10) NOPE, DON'T HANDLE IT + + ; {SUBCASE} FILE HANDLER + ; NOT IMPLIMENTED +ODIR9: RET +OPDIROU ENDP + + + SUBTTL OPINPUT + PAGE + + ; ------- + ; OPINPUT + ; ------- + + ; + ; PURPOSE: THIS ROUTINE IS USED TO PERFORM A TIMED CHARACTER REQUEST + ; + ; IF [ARG1] = 1, THEN THIS IS A TIMED INPUT KEYBOARD REQUEST + ; AND THE TIME LIMIT IS PROVIDED IN [ARG2]. + ; + ; IF A KEY IS DETECTED BEFORE TIMEOUT, THEN WE RETURN THE + ; CHARACTER VIA PUTBYTE. + ; + ;IF A FUNCTION IS PROVIDED [ARG3] IT IS INTERNALLY CALLED AFTER + ; TIMEOUT. IF THE VALUE RETURNED BY THE FUNCTION = 0, THEN + ; WE KEEP LOOPING. + ; + ; IF A TIMEOUT OCCURS AND WE HAVE NO FUNCTION TO CALL, OR THE + ; VALUE RETURNED FROM THE INTERNAL FUNCTION CALL NE. 0, THEN + ; WE RETURN A "0" VIA RET0. + ; + ; INPUTS: [NARGS],[ARG1],[ARG2]opt,[ARG3]opt + ; + ; OUTPUTS: EITHER A ASCII CHAR RETURNED VIA PUTBYTE + ; OR "0" VIA RET0 + ; + ; REGISTERS DESTROYED: AX,DX + ; + ; EXTERNAL REFERENCES: INCALL + ; + PUBLIC OPINPUT,ZTIMLP,NOZFCN,ZIN +OPINPUT PROC + NOP ; (A0) GET ARGS IN ARGBLK + PUSH BX ;(A0) SAVE REGISTERS + PUSH CX + + MOV MORLIN,0 ; (A8) RESET THIS VAR + MOV CHRCNT,BUFLEN ; (A15) RESET INPUT CHAR COUNT + MOV BX,ARGBLK ; (A0) GET ARG1 + CMP BX,1 ; (A0) KEYBOARD? + JNE NOZFCN ;....NO INVALID REQUEST + + CMP AX,3 ;(A0) IS THIS A TIMED INPUT + JB ZIN ;(A0) ....NO + + ; + ; TIMED INPUT + ; + +ZTIMLP: MOV AX,ARGBLK[2] ; (A0) GET DELAY COUNT + IDIV RADIX + MOV DLYCNT,AX + MOV BX,ARGBLK[4] ; (A0) GET FUNCTION ADDR + + CALL TIMLP1 ; (A0) GET A CHAR [+ TIMEOUT] + JNC ZIN ; (A0) GET THE CHAR READY + TEST AL,AL ; (A0) WHAT DID INCALL RETURN + JZ ZIN ; (A0) A ZERO MEANS CONTINUE ANYWAY + +NOZFCN: POP CX ; (A0) RESTORE REGISTERS + POP BX + MOV AX,0 ; (A0) RETURN A NULL + JMP BYTVAL ; (A0) IS THIS RIGHT? + + ; GET A CHARACTER FROM THE KEYBOARD +ZIN: CALL GETKEY + POP CX ; (A0) RESTORE REGISTERS + POP BX + JMP BYTVAL ; (A0) RETURN THE BYTE +OPINPUT ENDP + + SUBTTL LINE INPUT FOR GETLIN + PAGE + + ; ------ + ; LININP + ; ------ + + ; + ; PURPOSE: THIS ROUTINE IS USED BY GETLIN TO FETCH A LINE OF INPUT + ; FROM THE KEYBOARD AND PLACE IT IN THE INPUT BUFFER (INBUFF) + ; IN ADDITION, IT HAS THE RESPONSIBILITY TO TACKLE TIMED LINE + ; INPUT REQUESTS. + ; + ; {CASE TIMED INPUT} + ; IF NARGS GE. 3, THEN THIS IS A TIMED INPUT + ; IF A KEY IS DETECTED BEFORE TIMEOUT, THEN WE DROP INTO + ; LINE INPUT PROCESSING. + ; + ; IF NARGS EQ. 4, THEN UPON TIMEOUT THE FUNCTION [ARG4] IS + ; INTERNALLY CALLED. IF THE VALUE RETURNED BY THE FUNCTION = 0, + ; THEN WE KEEP LOOPING. + ; + ;IF NARGS NE. 4 OR THE VALUE RETURNED FROM THE INTERNAL FUNCTION + ; CALL NE. 0, THEN WE RETURN A "FALSE" IN [AX] TO {GETLIN}. + ; + ; {CASE LINE INPUT PROCESSING} + ; GET A LINE OF INPUT AND RETURN A "TRUE" IN [AX] TO {GETLIN}. + ; + ; INPUTS: [NARGS],[ARG3]opt,[AGR4]opt + ; + ; OUTPUTS: DX = ADDRESS OF INBUF, AX = TRUE OR FALSE (see above) + ; + ; REGISTERS DESTROYED: AX,DX + ; + ; EXTERNAL REFERENCES: INCALL,CHROUT + ; + PUBLIC LININP +LININP PROC + PUSH BX ; (A0) SAVE FCN ADDRESS + MOV BX,OFFSET INBUF ; (A0) POINT AT INPUT BUFFER + MOV BYTE PTR [BX],MAXLIN ; (A0) MAXIMUM NUMBER OF CHARACTERS + MOV BYTE PTR [BX+1],0 ; (A0) RESET THE CHARACTER COUNT + + ; + ; TIMED INPUT + ; + +TIMELP: IDIV RADIX + MOV DLYCNT,AX ; (A0) AX HAS DELAY COUNT + POP BX ; (A0) RESTORE FCN ADDRESS + + CALL TIMLP1 ; (A0) SEE IF CHAR IS READY + JNC ENTIN ; (A0) YES, NO TIMEOUT, GET IT + TEST AL,AL ; (A0) SEE WHAT INCALL RETURNED + JZ ENTIN ; (A0) CONTINUE NORMALLY + + MOV BX,OFFSET INBUF+2 ;POINT THE START OF THE ACTUAL BUFFER + ADD BX,CX ;(A0) POINT AT THE CHARACTER SLOT + MOV [BX],AL ;(A0) SAVE THE EOL + CALL MTTYO ;(A0) AND OUTPUT IT TO THE CONSOLE + RET + +ENTIN: JMP INLOOP +LININP ENDP + + ; + ; GET A LINE OF INPUT + ; + + PUBLIC INLOOP +INLOOP PROC + CALL GETKEY + CMP AL,14 ;(A0) CLEAR OFF ARROWS + JE INBAD + + CMP AL,7 + JE INBAD + + CMP AL,EOL ;(A0) CARRIAGE RETURN? + JE ENDLIN ;(A0) ....YES. WE'RE DONE + + CMP AL,7FH ;(A0) REGULAR DELETE + JE BACKUP ;(A0) ....YES + + CMP AL,BACKSP ;(A0) BACKSPACE (DELETE)? + JE BACKUP ;(A0) ....YES + + CMP AL,11 ;(A0) LEFT ARROW (DELETE)? + JE BACKUP ;(A0) ....YES + + ; PUT THE CHARACTER IN THE INPUT BUFFER, IF POSSIBLE + SUB CH,CH + MOV CL,INBUF+1 ;(A0) GET NUMBER OF CHARACTERS ALREADY + ;(A0) IN THE BUFFER + +; CMP CL,INBUF ;(A0) IS THE BUFFER FULL? + + MOV BL,INBUF ;(A9) GET THE MAXIMUM NO. OF CHARACTERS + DEC BL ;(A9) ENDS ALL INPUT - LEAVE ROOM + + DEC BL ;(B0) bl/Length, not ptr + CMP CL,BL ;(A9) IS THE BUFFER FULL? + JE NOMO ;(A0) ....YES + + ; THERE'S ROOM IN THE BUFFER + INC BYTE PTR INBUF+1 ;(A0) UPDATE NUMBER OF CHARACTERS + ;(A0) IN THE BUFFER + + MOV BX,OFFSET INBUF+2 ;POINT THE START OF THE ACTUAL BUFFER + ADD BX,CX ;(A0) POINT AT THE CHARACTER SLOT + MOV [BX],AL ;(A0) SAVE THE CHARACTER + + ;DISPLAY THE CHARACTER ON THE SCREEN +SHOWIT: CALL MTTYO ;(A0) DISPLAY IT + JMP INLOOP ;(A0) AND GET ANOTHER + + ; + ; LINE OVERFLOW + ; + +NOMORE: CALL GETKEY ;(A0) GET A KEY + CMP AL,EOL ;(A0) ? + JE ENDLIN ;(A0) ....YES, WE'RE DONE + + CMP AL,7FH ;(A0) REGULAR DELETE + JE BACKUP ;(A0) ....YES + + CMP AL,BACKSP ;(A0) BACKSPACE (DELETE)? + JE BACKUP ;(A0) ....YES + + CMP AL,11 ;(A0) LEFT ARROW (DELETE)? + JE BACKUP ;(A0) ....YES + +NOMO: CALL FEEP ;(A0) CAN' DO IT, SO COMPLAIN + JMP NOMORE ;(A0) AND DON'T LET THEM OFF THE HOOK + + ; + ; BACKUP (DELETE A CHARACTER) + ; + +BACKUP: CMP BYTE PTR INBUF+1,0 ;(A0) CAN WE REALLY DELETE A CHARACTER? + JE INBAD ;(A0) ....NO, WE HAVE NONE TO DELETE + + ; ACTUAL DELETE + DEC BYTE PTR INBUF+1 ;(A0) ONE LESS IN THE BUFFER + MOV AL,BACKSP ;(A0) BACKUP A CHARACTER POSITION + CALL MTTYO ;(A0) ON THE SCREEN + MOV AL,SPACE ;(A0) ERASE CHARACTER + CALL MTTYO ;(A0) BY REPLACING IT WITH A SPACE + MOV AL,BACKSP ;(A0) BACKUP A CHARACTER POSITION + JMP SHOWIT ;(A0) ON THE SCREEN AND LOOP + +INBAD: CALL FEEP ;(A0) CAN' DO IT, SO COMPLAIN + JMP INLOOP ;(A0) AND DON'T LET THEM OFF THE HOOK + + ; + ; LINE TERMINATED BY A EOL + ; + +ENDLIN: MOV BX,OFFSET INBUF+2 ;POINT THE START OF THE ACTUAL BUFFER + SUB CX,CX + MOV CL,INBUF+1 ;(B1) Point at 1st unused byte + ADD BX,CX ;(A0) POINT AT THE CHARACTER SLOT +; INC BX ;(A9)(b1 2 entry pts w/different conditions;fixed cx) + MOV [BX],AL ;(A0) SAVE THE EOL + CALL MTTYO ;(A0) AND OUTPUT IT TO THE CONSOLE +LINRET: RET +INLOOP ENDP + + + ; ---------------------- + ; FETCH AN ASCII KEYCODE + ; ---------------------- + ; + ; PURPOSE: GETKEY WAITS FOR A KEY TO BE DEPRESSED ON THE CONSOLE. + ; WHEN A KEY IS DEPRESSED, IT'S ASCII VALUE IS RETURNED + ; FROM THE DOS FUNCTION.THE ASCII VALUE IS THEN PREPROCESSED + ; SO THAT CERTAIN KEYS ARE TRANSLATED INTO EZIP ASCII VALUES + ; + ; OTHER KEYS ARE CONSIDERED ILLEGAL AND IF DETECTED CAUSE A + ; BEEP SOUND TO BE HEARD, THE KEYPRESS IS IGNORED, AND THE + ; ROUTINE CONTINUES TO WAIT FOR A VALID KEY. + ; + ; INPUTS: NONE + ; + ; OUTPUTS: [AL] = A 7-BIT ASCII CODE + ; + ; REGISTERS DESTROYED: + ; AX,BX,CX + ; + ; EXTERNAL REFERENCES: FEEP + ; + PUBLIC GETKEY,GK0,GK1,GK2,GK3,GK4,KEYOK,CHKKEY +GETKEY PROC +GK0: MOV AH,CNOECHO ;(A0) WAIT FOR KEYPRESS, NO ECHO + INT 21H ;(A0) MSDOS FUNCTION CALL + AND AL,7FH ;(A0) 7-BIT ASCII ONLY + + ; EXTENDED SPECIAL FUNCTIONS + CMP AL,0 ;(A0) IF AL=0,THIS IS AN EXTENDED KEY + JNE CHKKEY ;(A0) THANK GOODNESS, IT ISN'T + + ; PROCESS EXTENDED KEYS + ; DO A SECOND READ + MOV AH,CNOECHO ;(A0) WAIT FOR KEYPRESS, NO ECHO + INT 21H ;(A0) MSDOS FUNCTION CALL + + CMP AL,72 ;(A0) UP ARROW + JNE GK1 + MOV AL,14 + JMP KEYOK + +GK1: CMP AL,75 ;(A0) LEFT ARROW + JNE GK2 + MOV AL,11 + JMP KEYOK + +GK2: CMP AL,77 ;(A0) RIGHT ARROW + JNE GK3 + MOV AL,7 + JMP KEYOK + +GK3: CMP AL,80 ;(A0) DOWN ARROW + JNE GK4 + MOV AL,13 + JMP KEYOK + +GK4: CMP AL,83 ;(A0) DEL KEY + JNE GK0 ;(A0) IT'S BAD, TRY AGAIN + MOV AL,7FH + JMP KEYOK ;(A9) + + ; + ; WE'RE RECEIVED A NON-EXTENDED KEY + ; SO, NATURALLY ENOUGH, WE'RE GOING TO RUN IT THROUGH + ; AN ASCII FILTER TO REMOVE THOSE KEYS THAT WE DON'T + ; (THROUGH NO FAULT OF THEIR OWN) LIKE. + ; + +CHKKEY: CMP AL,08H ;(A9) BACKSPACE IS OK + JE KEYOK ;(A9) + CMP AL,0DH ;(A9) + JE KEYOK ;(A9) + CMP AL,20H ;(A9) AND SO ARE KEYS .GE SPACE + JAE KEYOK ;(A9) + JMP GK0 ;(A9) +KEYOK: MOV IOCHAR,AL ; (LD1) HOLD A SEC + ADC AX,RSEED1 ; (LD1) PLAY WITH RANDOM BYTES + MOV RSEED1,AX ; (LD1) EACH TIME THRU HERE + XOR RSEED2,AX ; (LD1) + MOV AL,IOCHAR ; (LD1) THANKS FOR WAITING + RET +GETKEY ENDP + + + ; POLL THE KEYBOARD FOR 1/nTH SEC + ; NOTE: THIS ROUTINE DOES IT IN 0.11 SEC WITH A FAIR DEGREE + ; OF PRECISION, INDEPENDENT OF SYSTEM CLOCK (AT+, PC, ETC.) +TIMLP1 PROC + PUSH DI +TRESET: MOV DI,DLYCNT +TIMIN: MOV AH,CTIME ;(A0) GET TIME FROM REAL TIME CLOCK + INT 21H ;(A0) MSDOS FUNCTION CALL + MOV CLKLOW,DX ;(A0) SAVE 1/100 SEC COUNT + + ; IS A KEY AVAILABLE +TRY: MOV AH,CINSTAT ;(A0) CHECK STANDARD INPUT STATUS + INT 21H ;(A0) MSDOS FUNCTION CALL + OR AL,AL ;(A0) IS A CHARACTER AVAILABLE + JZ TRY1 ;(A0) NO + POP DI + CLC ; (A0) CLEAR TO SIGNAL A CHAR + RET + + ; NOKEY +TRY1: MOV AH,CTIME ;(A0) GET TIME FROM REAL TIME CLOCK + INT 21H ;(A0) MSDOS FUNCTION CALL + MOV AX,DX ; (A0) SAVE IT + SUB DX,CLKLOW ;(A0) IF EQUAL TO SAVED TIME + CMP DX,100H + JB TRY ;(A0) .1 SECS HASN'T EXPIRED YET + NEG DX + CMP DX,100H + JB TRY + + MOV CLKLOW,AX ;(A0) SAVE 1/100 SEC COUNT + + + DEC DI ;(A0) DECREMENT DELAY TIMER + JNZ TIMIN ;(A0) IF TIME IS LEFT, TRY AGAIN + + ; TIME OUT, CHECK FOR A FUNCTION + MOV AX,BX ;(A0) GET ORIGINAL BX (FCN) INTO AX + CALL INCALL ;(A0) ....YES, CALL THE FUNCTION + CMP AX,0 ; IF VALUE RETURNED=0 + JNZ INFAIL ;(A0) THEN TRY AGAIN + JMP TRESET +INFAIL: POP DI ; (A0) RESTORE THIS ONE + STC ; (A0) INDICATE A TIMEOUT + RET ; (A0) RETURN WITH TIMEOUT RET IN AX + +TIMLP1 ENDP + + SUBTTL RDLIN + PAGE + + ; ------ + ; RDLIN + ; ------ + + ; + ; PURPOSE: THIS ROUTINE PROVIDES BUFFERED KEYBOARD INPUT + ; + ; + ; NOTE: NORMALLY LINE INPUT IS PROVIDED BY USING DOS + ; INT 21H FUNCTION CALLS WITH [AH]=0AH. BECAUSE WE + ; WANT TO INTERCEPT AND IGNORE MANY POSSIBLE KEYS, THIS + ; ROUTINE IS NECESSARY. + ; + ; + ; INPUTS: [AH]=0AH, DS:DX ^ INPUT BUFFER. THE FIRST BYTE + ; SPECIFIES THE NUMBER OF BYTES THE BUFFER CAN HOLD + ; (MUST BE .NE 0). THE SECOND BYTE IS SET TO THE + ; NUMBER OF CHARACTERS RECEIVED. + ; + ; OUTPUTS: THE INPUT BUFFER WILL CONTAIN A FILTERED ASCII STRING + ; TERMINATED BY . + ; + ; REGISTERS DESTROYED: NONE? + ; + ; + +RDLIN PROC + PUSH AX ;(A9) + PUSH BX ;(A9) + PUSH CX ;(A9) + PUSH DX ;(A9) + PUSH DX ;(A9) + POP BX ;(A9) + MOV BYTE PTR [BX+1],0 ;(A9) RESET THE CHARACTER COUNT + CALL INLOOP ;(A9) + POP DX ;(A9) + POP CX ;(A9) + POP BX ;(A9) + POP AX ;(A9) + RET +RDLIN ENDP diff --git a/ibm/scrnops.ezp b/ibm/scrnops.ezp new file mode 100644 index 0000000..4d0dad8 --- /dev/null +++ b/ibm/scrnops.ezp @@ -0,0 +1,255 @@ + SUBTTL SCRNOPS + PAGE + + PUBLIC OPSPLT,OPSCRN +OPSCRN PROC + MOV SCRNFLG,AL ; (7) TOGGLE SCREEN CURRENTLY ON + TEST AL,AL ; (7) WHICH DO WE WANT + JZ SCRN0 ; (7) SELECT BOTTOM, SCROLLING WINDOW + MOV SCRHLD,1 ; (A0) NO SCRIPTING DURING SCREEN 1 + CALL SAVECUR +SCRN1: MOV BX,OFFSET WINDOW1 ; (7) HOME THE CURSOR + TEST COLFLG,1 ; (7) SHOULD WE SET THE COLOR + JZ SCRN2 ; (7) NOPE + MOV BX,OFFSET COLWIN1 ; (7) CLEAR SCREEN WITH COLOR +SCRN2: CALL MSPRT ; (7) WITH ANSI LOCATE + RET +SCRN0: MOV SCRHLD,0 ; (A1) REENABLE SCRIPTING + CALL RESTCUR ; (7) RESTORE THE CURSOR POSITION + MOV BX,OFFSET WINDOW0 + TEST COLFLG,1 ; (7) SHOULD WE CHANGE THE COLOR + JZ SCRN3 ; (7) NOPE... + MOV BX,OFFSET COLWIN0 +SCRN3: CALL MSPRT ; (7) RESTORE COLOR + RET +OPSCRN ENDP + +OPSPLT PROC + XOR AH,AH + CMP AL,0 + JNZ SPL1 ; (7) YES, FIGURE WINDOW SIZE + CALL RESTCUR + MOV SPLTFLG,0 ; (7) TURN OFF SPLIT SCREEN + MOV AX,TOPSCR ; (A0) TOPSCR NOW A VAR + MOV TOPLIN,AX ; (7) RESTORE TOPLIN TO WHOLE SCR + MOV MORLIN,0 ; (7) RESET THE MORE LINE COUNT + RET +SPL1: MOV SPLTFLG,1 ; (7) TURN ON SPLIT SCREEN + CMP AL,SLPP ; (7) ARE THERE THIS MANY LINES + JLE SPL2 + MOV AL,SLPP ; (7) USE NO MORE THAN THE SCREEN + DEC AL ; (7) LEAVE A SCROLL LINE +SPL2: XCHG AH,AL ; (7) GET #LINES IN TOP HALF +; ADD TOPLIN,AX ; (7) THIS FIXES WINDOW 0 SCROLL SIZE + MOV TOPLIN,AX ; (B0) splits without unsplits lost (ehb) +; (B0 ehb) split should not clear the screen (has NO visible effect) +; PUSH AX ; (K7) FIX CLEAR ON SPLIT SCREEN +; CALL SAVECUR ; (7) SAVE THE CURSOR POSITION +; MOV BH,SCRATR ; (7) GET ATTRIBUTE INTO BH FOR CLS +; TEST COLFLG,1 ; (7) COLOR BLANK OR VANILLA BLANK +; JZ SPL3 ; (7) VANILLA... +; MOV BH,SPLCOL ; (7) USE THE GREEN CLEAR +;SPL3: POP AX ; (K7) RESTORE AX +; MOV DH,AH ; (7) BLANK WINDOW #1 +; DEC DH ; (A2) WE HAVE ONE TOO MANY LINES TO CLEAR +; MOV AH,SCROLLUP ; (7) BLANK THE WINDOW +; MOV AL,0 ; (7) ZERO MEANS ENTIRE WINDOW +; MOV CX,TOPSCR ; (7) FROM UPPER LEFT +; MOV DL,SCPL ; (7) TO LOWER RIGHT +; DEC DL ; (7v) COORDINATES ARE ZERO BASED +; INT 10H ; (7) CALL VIDEO BIOS ROUTINE TO CLS +; CALL RESTCUR ; (7) RESTORE CURSOR POSITION + RET +OPSPLT ENDP + + PUBLIC SAVECUR +SAVECUR PROC + TEST CURSAV,1 ; (A0) HAS THIS JUST BEEN DONE? + JZ SC1 + RET +SC1: MOV BX,OFFSET SCP ; (7) ANSI SAVE CURSOR + CALL MSPRT + MOV CURSAV,1 ; (A0) CURSOR POSITION IS SAVED + RET +SAVECUR ENDP + + PUBLIC RESTCUR +RESTCUR PROC + TEST CURSAV,1 ; (A0) IS THERE A POSITION SAVED? + JNZ RC1 + RET +RC1: MOV BX,OFFSET RCP ; (7) ANSI RESTORE CURSOR + CALL MSPRT + MOV CURSAV,0 ; (A0) DON'T RESTORE UNTIL A SAVE + RET +RESTCUR ENDP + + PUBLIC OPCLEAR +OPCLEAR PROC + CMP AL,-1 ; (A0) DO WE WANT TO UNSPLIT? + JNZ OCLR ; (A0) YES, UNSPLIT AND ERASE + MOV AL,0 ; (A0) CALL OPSPLIT INTERNALLY TO UNSPLIT + CALL OPSPLT ; (A0) THIS WILL RESET THE SCREEN + CALL CLRSCR ; (A0) USE BW/COLOR CLEAR + RET ; (B0) was falling through al from CLRSCR +OCLR: CMP AL,1 ; (A0) DO WE WANT TO CLEAR WINDOW 1 + JNZ OCLR0 ; (A0) NO, CLEAR WINDOW 0 + MOV DX,TOPLIN ; (A0) GET LAST LINE OF WINDOW 1 + DEC DH ; (A0) THRU WINDOW 0 + MOV DL,SCPL ; (A0) GET WIDTH + DEC DL ; (A0) ZERO BASED + MOV CX,0 ; (A0) SOMETHING IS CONSTANT +OCLR2: MOV AL,0 ; (A0) BLANK ENTIRE WINDOW + MOV AH,SCROLLUP ; (A0) TO SCROLL THESE + MOV BH,SCRATR ; (A0) USE BW + TEST COLFLG,1 ; (A0) OR COLOR? + JZ OCLR$ ; (A0) DONT CHANGE ATR + MOV BH,SPLCOL ; (A0) UGH, GREEN +OCLR$: INT 10H ; (A0) DO VIDEO + RET +OCLR0: CMP AL,0 ; (A0) SHOULD WE IGNORE? + JZ OCLR1 ; (A0) NO + RET +OCLR1: MOV CX,TOPLIN + MOV DX,184FH ; (A0) ANOTHER CONSTANT + JMP OCLR2 +OPCLEAR ENDP + + PUBLIC OPERASE +OPERASE PROC + CMP AL,1 ; (A0) DO WE WANT TO EREOL + JZ OPERA1 + RET +OPERA1: MOV BX,OFFSET EREOL + CALL MSPRT + RET +OPERASE ENDP + + ; PRINTS AN ANSI STRING FOR CURPOS $[03;31H + PUBLIC OPCURST +OPCURST PROC + TEST BUFBIT,1 ; (A0) IS THIS OPERATION LEGAL + JNZ OPCUR1 + TEST SCRNFLG,1 ; (A0) THIS SCREEN MUST BE ACTIVE + JZ OPCUR1 + CALL ESCOUT ; (A0) SEND OUT ESC [ + CALL NUMOUT + MOV DL,';' ; (A0) SEPARATE THE DIGITS BY ; + MOV AH,2 + INT 21H + MOV AX,BX ; (A0) GET COLUMN + CALL NUMOUT + MOV DL,'H' ; (A0) H IS ANSI FOR CURPOS + MOV AH,2 + INT 21H +OPCUR1: RET +OPCURST ENDP + + PUBLIC ESCOUT,NUMOUT +ESCOUT PROC + PUSH AX + PUSH DX + MOV DL,27 + MOV AH,2 + INT 21H + MOV DL,'[' + INT 21H + POP DX + POP AX + RET +ESCOUT ENDP + + ; PRINT NUMBER IN AX OUT AS DECIMAL +NUMOUT PROC + PUSH BX + XOR DX,DX ; (A0) ZERO THIS + MOV BX,10 ; (A0) GET A WORD DIVISOR + IDIV BX ; (A0) BREAK AX INTO AX,DX + ADD DL,'0' ; (A0) ASCIIFY NUMBERS + ADD AL,'0' ; (A0) + PUSH DX ; (A0) DL HAS CURPOS LOW + MOV DL,AL ; (A0) GET HIGH DIGIT + MOV AH,2 + INT 21H + POP DX ; (A0) RESTORE CURPOS LOW + MOV AH,2 ; (A0) DL HAS NEXT DIGIT + INT 21H + POP BX + RET +NUMOUT ENDP + + PUBLIC OPCURGT +OPCURGT PROC + RET +OPCURGT ENDP + + PUBLIC OPHILIT +OPHILIT PROC + INC AX + JMP PUTCHR +OPHILIT ENDP + +CLRSCR PROC + MOV BX,OFFSET CLS + CMP COLFLG,1 ; (7t) TURN ON COLOR WITH CLEAR SCREEN + JNZ CLR0 + MOV BX,OFFSET CLSC ; (7t) TURN POINT TO COLOR ANSI CODE +CLR0: CALL MSPRT + RET +CLRSCR ENDP + + + SUBTTL SOUND SUBROUTINES + PAGE + + ; + ; ****** IMPLEMENTATION NOTE ***** + ; + ; INITSND MUST BE CALLED DURING COLDSTART + ; + ; + + ; ------- + ; OPSOUND + ; ------- + + ; PLAY SOUND FX [ARG1] (1-255) + + PUBLIC OPSND +OPSND PROC + OR AX,AX + JZ SNDERR ;(A0) 0 IS IGNORED + CMP AX,NSNDS + 1 + JAE SNDERR ;(A0) SOUND NOT DEFINED + DEC AX ;(A0) ZERO ALIGN + SHL AX,1 ;(A0) MAKE IT A WORD OFFSET + MOV BP,AX ;(A0) GET THE SOUNDLIST POINTER + MOV SI,DS:[BP+STABLE] + CALL SI ;(A0) CALL THE SOUND ROUTINE +SNDERR: RET + +OPSND ENDP + + ; -------------------- + ; ACTUAL SOUND EFFECTS + ; -------------------- + + ; + ; BEEP (DIT) + ; + +SND1 PROC + MOV CX,1200 ;(A0) FREQUENCY + MOV DX,1 ;(A0) DURATION + JMP TONE +SND1 ENDP + + ; + ; BOOP (DAH) + ; + +SND2 PROC + MOV CX,600 ;(A0) FREQUENCY + MOV DX,5 ;(A0) DURATION + JMP TONE +SND2 ENDP diff --git a/ibm/setup.ezp b/ibm/setup.ezp new file mode 100644 index 0000000..8dfe179 --- /dev/null +++ b/ibm/setup.ezp @@ -0,0 +1,78 @@ + SUBTTL SETUP - TOP LEVEL STUFF + PAGE + + + ; READ THE SETUP FILE +; SSETUP HAS UNDER GONE TO SETS OF REVISIONS. REVISION 6 IS RESPONSIBLE +; FOR ALL OF THE DOS 2.0 FILE HANDLING PATCHES. REVISION 7 IS RESPONSIBLE +; FOR SETTING UP COLOR OR MONOCHROME BASED ON THE VIDEO SETTINGS AND WHAT +; WAS SPECIFIED ON THE COMMAND LINE. +; + PUBLIC SSETUP +SSETUP PROC NEAR + MOV AH,15 ; (7) CHECK VIDEO STATE + INT 10H ; (7) TO SEE IF IN A COLOR MOOD + CMP AL,0 ; (7) THIS IS 40x25 BW + JNZ SSET5 +SSET0: FATAL FTL14 ; (A1) SCREEN IS NOT 80 CHARS WIDE +SSET4A: MOV IBMPC,0 ; (A15) TURNED OFF IF SWITCH IS USED + TEST CMDLIN,3 ; (A15) ANY COLOR BITS SET? + JZ SSET$$ ; (A15) NOPE, GO ASK + TEST CMDLIN,1 ; (7) WAS THIS SET ON CMD LINE + JNZ SSET6 ; (7) YES, CANNOT OVERRIDE + JMP SSET4B ; (A15) BIT 2 IS ON, TURN ON COLOR + +SSET$$: PRINT WANTCO ; (A1) DO YOU WANT COLOR? +SSET1A: MOV AH,CNOECHO ; (A1) GET A CHARACTER + INT 21H ; (A1) FROM THE KEYBOARD + AND AL,5FH ; (A1) UPPERCASIFY IT + CMP AL,'Y' ; (A1) CHECK FOR YES NO + JNZ SSET3A ; (A1) AND SET COLOR APPROPRIATELY + +SSET4B: MOV COLFLG,1 ; (7) SET COLOR FLAG + MOV SCRATR,COLATR ; (7) SET VIDEO ATTRIBUTE + JMP SSET6 ; (A1) THANKS FOR YOUR TIME + +SSET3A: CMP AL,'N' ; (A1) IS IT A NO + JNZ SSET1A ; (A1) IF NOT, THEN ASK AGAIN + JMP SSET6 ; (A1) OTHERWISE ECHO IT + +SSET5: CMP AL,1 ; (A1) 1 40x25 COLOR + JZ SSET0 ; (A1) SO DIE APPROPRIATELY + CMP AL,2 ; (A17) 80x25 BW? + JE SSET4A ; (A17) CHECK CMDLINE AND ASK + CMP AL,3 ; (7) THIS IS 80x25 COLOR + JZ SSET4A + TEST CMDLIN,2 ; (7) DID THEY SET COLOR FROM CMD LINE + JNZ SSET4A ; (7) TURN IT ON +SSET6: CMP FITS,1 ; (A1) IF FITS, THE LOAD WILL BE LONG + JNZ SSET7 + CALL CLRSCR ; (A1) CLEAR THE SCREEN + MOV BX,OFFSET WAIT ; (A0) INFORM WAIT + CALL MSPRT +SSET7: RET +SSETUP ENDP + + ;INITIALIZATION + PUBLIC TSETUP +TSETUP PROC + MOV AL,SLPP ; NUMBER OF LINES + SUB AH,AH ; ASCIIFY THIS NUMBER INTO AX + INC AX ; FOR SLPP = 24, THE CURSOR IS AT 25 + DIV RADIX ; SO THAT WE CAN PUT THE CURSOR + ADD AH,"0" ; THERE WHEN WE FINISH THE STATUS + ADD AL,"0" ; LINE OUTPUT IN MSOUT + MOV BX,OFFSET CLS1 ; (7t) PATCH CLEAR SCREEN + MOV [BX],AX ; (7t) SO THAT IT RESTORE CURPOS + MOV BX,OFFSET CLS1C ; (7t) PATCH IT IN COLOR TOO + MOV [BX],AX + MOV BX,OFFSET OUTBUF ; NO DETERMINE END OF OUTPUT BUFFER + MOV CL,SCPL + SUB CH,CH + ADD BX,CX + DEC BX ; (7v) SHORTEN BY ONE TO AVOID HARD + MOV ENDBUF,BX ; WRAP + MOV BYTE PTR [BX],0 + CALL MINIT + RET +TSETUP ENDP + diff --git a/ibm/statline.bat b/ibm/statline.bat new file mode 100644 index 0000000..44cf8a3 --- /dev/null +++ b/ibm/statline.bat @@ -0,0 +1,126 @@ +echo off +if %1x==x statline B: +if not %2x==x goto again +rem INSTALLH.BAT ver. B (11/15/86) +rem make some space for the one-diskette case +if exist gamedir.com del gamedir.com +if exist yes.com del yes.com +:again +af > ansi +if errorlevel 1 goto noansi +rem del af to make space in the 2-floppy case +if exist pass2 goto delaf +goto doscan +:delaf +if %2x==x del af.exe +:doscan +scan +if errorlevel 2 goto failed +if errorlevel 1 goto append +echo foo > case1 +goto signoff +:append +copy \config.sys \config.old > nul +copy \config.sys+ansi \config.sys > nul +:win +echo . +echo . +if not %2x==x goto hdmess +echo foo > case2 +goto signoff +:hdmess +echo foo > case3 +:signoff +if exist ansi del ansi +if exist install*.bat del install*.bat +if exist scan.com del scan.com +if exist af.exe del af.exe +if exist pass2 del pass2 +if not %2x==x goto alldone +if exist %1one goto jrdat +goto docopy +:jrdat +echo . +echo Once again, you will often have to change diskettess. When you're +echo prompted to insert a diskette for drive A:, use the original STORY +echo diskette; when you're prompted to insert a diskette for drive B:, use +echo the PLAY diskette. +echo . +del one +pause +:docopy +copy A:*.DAT %1 > nul +:alldone +echo . +if not exist case1 goto case2 +del case1 +echo Infocom story installation is now complete. +goto really +:case2 +if not exist case2 goto case3 +del case2 +echo Infocom story installation is now complete. +echo . +echo IMPORTANT: You must now put the PLAY diskette in drive A: and +echo press CTRL-ALT-DEL to reboot your system. +goto really +:case3 +del case3 +echo Infocom story installation is now complete. +echo . +echo IMPORTANT: You must now remove the original diskette from drive A: +echo and press CTRL-ALT-DEL to reboot your system. +echo . +:really +echo . +echo . +echo See your reference card for an explanation of how to load the story. +goto end +:failed +echo . +echo Something is wrong with your config.sys file. Please press +echo CTRL-ALT-DEL to reboot your system. If this operation fails again, +echo consult your DOS manual regarding Configuring Your System. +goto end +:noansi +echo . +if exist %1one goto pcjr +echo Please find your original DOS diskette and place it in drive A: and +goto dos +:pcjr +echo Whenever you are prompted to put a diskette into drive B:, you +echo should insert the PLAY diskette into the drive, and whenever you +echo are prompted to put the diskette into drive A:, you should insert +echo the DOS diskette into the drive. +:dos +if %2x==x goto getb +pause +copy a:ansi.sys %1\ /B > nul +if exist %1one goto nomsg1 +echo . +echo Now replace the original STORY diskette in drive A: and +pause +:nomsg1 +if exist %1\ansi.sys goto getansi +goto end +:getb +pause +copy a:ansi.sys %1ansi.sys /V > nul +if exist %1one goto nomsg2 +echo . +echo Now replace the original STORY diskette in drive A: and +pause +:nomsg2 +if exist %1ansi.sys goto getansi +echo foo > case1 +goto signoff +:getansi +echo foo > pass2 +goto again +:end +if exist ansi del ansi +if exist install*.bat del install*.bat +if exist scan.com del scan.com +if exist af.exe del af.exe +if exist one del one +if exist pass2 del pass2 diff --git a/ibm/switches.txt b/ibm/switches.txt new file mode 100644 index 0000000..19817ba --- /dev/null +++ b/ibm/switches.txt @@ -0,0 +1,30 @@ + +IBM Command Lines +------------------------------------------------------------------------ + + These command line arguments are available with the IBM/MSDOS +ZIP interpreter, versions 'L' and up, and all EZIP versions. + + The first four are listed in the reference card; the last two +are undocumented. + +; /P INITIALIZE PRINTER THROUGH INT 17 +; /M MONOCHROME +; /C COLOR +; /W WINDOWED SCROLLING + +; /K AMOUNT OF MEMORY TO USE IN KBYTES +; /G RUN THE GAME FILE SPECIFIED + + /K is used to limit the amount of memory used by the game, +which normally takes as much as it can get (up to the size of the data +file). The frequency of disk accesses (never in the case of full +preload) increases as memory is reduced. + + For example, Zork1 normally uses around 85K but can be run +with as little as /K25. Specifying less than 25K causes a "not enough +memory" error message. + + /G makes the interpreter use a different data file. For example, +ZORK1.EXE normally runs ZORK1.DAT, but can in general run any other +ZIP game. diff --git a/ibm/sysini.ezp b/ibm/sysini.ezp new file mode 100644 index 0000000..91b1ec5 --- /dev/null +++ b/ibm/sysini.ezp @@ -0,0 +1,378 @@ + + SUBTTL SYSINI - HIGH LEVEL IBMPC DEPENDENT STUFF + PAGE + + ;SYSTEM INITIALIZATION +; SYSINI HAS BEEN GREATLY MODIFIED TO INCLUDE DOS 2.0 FILE HANDLING, +; COMMAND LINE ARGUMENTS, COPY PROTECTION, AND DYNAMIC ALLOCATION OF +; PAGING SPACE. +; +; THE COPY PROTECTION SCHEME WORKS AS FOLLOWS: A NUMBER OF COMPUTERS ARE +; DEFINED AS COMPATIBLE WITH IBM IN THE DATA DECLARATIONS. INCLUDED FOR +; EACH IS THE FIRST 9 LETTERS OF THE COPYRIGHT NOTICE THAT EXISTS IN THE +; ROM. IF ANY OF THESE STRINGS IS FOUND IN THE ROM, COPY PROTECTION IS +; CHECKED, OTHERWISE IT IS NOT. IBM COMPATIBILITY MEANS TOTAL ROM BIOS +; COMPATIBILITY SUCH THAT WINDOWED SCROLLING AND SPECIAL DISK I/O MAY BE +; PERFORMED. NOT FINDING ANY OF THESE STRINGS RESULTS IN THE ZIP FUNCTIONING +; AS IF IT WERE ON A GENERIC MS-DOS BASED MACHINE. +; +; COMMAND LINE ARGUMENTS SET BITS IN THE VARIABLE CMDLIN IN THE ROUTINE +; SCANCMD. CMDLIN THEN AFFECTS VARIOUS PARAMETERS AND VARIABLES EITHER IN +; SYSINI OR SSETUP. +; +; THE PAGTAB IS SET UP ACCORDING TO AVAILABLE MEMORY. THERE EXISTS A WORD +; AT OFFSET 2 IN THE PSP (PROGRAM SEGMENT PREFIX, OR WHERE CS POINTS) WHICH +; INDICATES THE TOP OF PHYSICAL MEMORY. PAGTAB REPRESENTS THE LAST WORD USED +; BY THE ZIP. THE CODE SEGMENT REPRESENTS THE AMOUNT OF MEMORY TAKEN UP BY +; EVERYTHING UNDER THE ZIP SUCH AS THE OPERATING SYSTEM AND DEVICE DRIVERS. +; IF WE CONVERT PAGTAB TO PARAGRAPHS, THEN ALL OF THESE NUMBERS ARE IN +; PARAGRAPHS. SO: +; +; TOP_OF_MEM - (CS + PAGTAB) --> AVAILABLE MEMORY IN PARAGRAPHS +; +; AVAILABLE MEMORY IS CONVERTED INTO THE NUMBER OF BUFFERS AVAILABLE. FROM +; THIS NUMBER WE MUST SUBTRACT 1 OR 2 BUFFERS TO ALLOW FOR THE PAGTAB TO +; BE BUILT. KNOWING AVAILABLE BUFFERS TELLS US THE LENGTH OF OUR PAGTAB +; SINCE OUR PAGTAB IS 4 BYTES/BUFFER. AT THE NEXT PARAGRAPH BOUNDARDY BEYOND +; THE PAGTAB WE HAVE OUR FIRST GAME SEGMENT WHICH WILL BE MOVED TO ES AND +; STORED IN THE VARIABLE GAMESEG. ADDING 64K (IN PARAGRAPHS) TO GAMESEG +; WE ARRIVE AT OUT LOCATION FOR SEG1, THE SECOND GAME SEGMENT. THE PAGTAB +; IS THEN INITIALIZED. +; + PUBLIC SYSINI,SYS1,INITLP,SYSFTL,GOODOS,GODOS1 +SYSINI PROC + MOV AH,DOSVER ; (7) GET DOS VERSION # + INT 21H ; (7) MUST BE 2.0 OR HIGHER + CMP AL,2 ; (7) DOS 2.0+ + JGE GOODOS + FATAL FTL11 ; (7) DIE APPROPRIATELY + + ; ESTABLISH THE IBMNESS OF THE HOST +GOODOS: MOV IBMPC,0 ; (A9) PRESET TO NOT AN IBM + PUSH ES ; (A9) + PUSH DI ; (A9) + MOV BX,0F000H ; (A9) SEGMENT + MOV ES,BX ; (A9) LOAD THE SEGMENT + MOV DI,0E000H ; (A9) ES:DI OFFSET + + MOV AX,OFFSET IBMSTR ; (A9) ^ IBM STRING + MOV CX,16H ; (A9) NO. CHARACTERS TO SEARCH + MOV DX,9 ; (A9) NO. OF CHARACTERS + CALL CHK ; (A9) SEE IF THIS IS AN IBM + POP DI ; (A9) RESTORE THOSE REGISTERS + POP ES ; (A9) + JC GODOS1 ; (A9) CARRY SET = IT'S NOT AN IBM + MOV IBMPC,1 ; (A9) SET FLAG TO INDICATE AN IBM + +GODOS1: MOV AH,CURDSK ; (6) GET DEFAULT DRIVE + INT 21H ; (6) FROM DOS + MOV DEFDRV,AL ; (6) SAVE DEFAULT DRIVE + MOV CURDRV,AL ; (6) SAVE DEFAULT DRIVE + CALL SCANCMD ; (7) GET CMD LINE VARS +GOTONE: MOV SCROLL,0 ; (7) USE WINDOWED SCROLLING +NOCMD: MOV AH,CFOPENZ ; (6) ASCIZ STRINGS + MOV AL,0 ; (6) OPEN FOR READING + MOV DX,OFFSET GAMFILE + INT 21H + JNC SYSA$ + JMP SYSFTL +SYSA$: MOV GAMHNDL,AX ; (6) SAVE THE FILE HANDLE + MOV BX,AX ; (7n) GET FILE HANDLE INTO BX + XOR CX,CX ; (7n) ZERO THESE + XOR DX,DX ; (7n) TO FIND EOF + MOV AH,CFSEEK ; (7n) SEEK TO END OF FILE + MOV AL,2 ; (7n) MOVE FILE PTR TO EOF + INT 21H ; (7n) DO IT + + MOV CX,4 ; (7n) CONVERT AX TO PARAGRAPHS +SYSA0: SHR AX,1 ; (7n) TO SAVE AS FILESIZE + TEST DX,1 ; (A0) TEST HIBIT + JNZ SYSA1 +SYSA2: SHR DX,1 ; (A0) MOVE HIWORD TOO + LOOP SYSA0 + JMP SYSB$ +SYSA1: OR AH,80H ; (7n) TURN ON THAT BIT + JMP SYSA2 + +SYSB$: MOV CL,5 ; (7n) REDUCE TO NUMBER OF 512 BLKS + SHR AX,CL ; (7n) FOR COMPARISON TO BUFFERS + MOV GAMESIZ,AX ; (7n) SAVE THIS SIZE FOR FITS + + XOR CX,CX ; (7w) MOVE POINTER TO BOF + MOV DX,4 ; (7w) WE WANT THE WORD AT OFFSET 4 + MOV AH,CFSEEK ; (7w) SEEK THERE + MOV AL,0 ; (7w) METHOD: OFFSET FROM BOF + INT 21H ; (7w) BX HAS FILE HANDLE + MOV AH,CRDRNDZ ; (7w) READ IN THE FIRST + MOV CX,2 ; (7w) READ THE WORD OF ENDLOD + MOV DX,OFFSET SSBUF ; (7w) ANY BUFFER BIG ENOUGH WILL DO + INT 21H ; (7w) READ IT + MOV AX,SSBUF ; (7w) GET THE WORD + XCHG AH,AL ; (7w) FLOP THE BYTES + TEST AX,1FFH ; (7w) ROUND UP TO NEXT BLOCK + JE SYSC$ + AND AX,0FE00H ; (7w) TURN OF LOW BITS + ADD AX,200H ; (7w) ADD A BLOCK +SYSC$: MOV CL,9 ; (7w) CONVERT TO NUMBER OF BLOCKS + SHR AX,CL + MOV DX,AX ; (7w) AND SAVE NUMBER IN DX + + MOV BX,2 ; (6) GET TOP OF MEMORY + MOV BX,CS:[BX] ; (6) FROM OUT OF THE PSP + MOV AX,CS ; (6) GET CODE SEG + SUB BX,AX ; (6) SUB CSEG FROM TOPMEM + MOV CL,4 ; (6) SHIFT COUNT + MOV AX,OFFSET PAGTAB ; (6) USE OFFSET TO FIGURE PARAG'S + SHR AX,CL ; (6) REDUCE THIS OFFSET TO PARAS + INC AX ; (6) SKIP ONE PARAGRAPH + AND AX,0FE0H ; (7z) BLOCKIFY THIS NUMBER + ADD AX,20H ; (7z) OTHERWISE LOSE A PAGE + SUB BX,AX ; (6) YIELDS PARAS AVAILABLE + + TEST CMDLIN,4 ; (7) SET ON CMDLIN? + JZ SYS2 + CMP BX,MEMORY ; (7) REASONABLE REQUEST + JBE SYS2 ; (7) NO, NOT REALLY THERE + MOV BX,MEMORY ; (7) USE USER SETTING + +SYS2: CMP BX,MINMEM ; (7) AT LEAST 48K? + JAE SYS3 ; (7) YES + FATAL FTL12 ; (7) DIE APPROPRIATELY +SYS3: MOV CL,5 ; (6) DIVIDE BY 32 TO GET BUFFERS + SHR BX,CL ; (6) TO GET #BUFFERS + CMP BX,GAMESIZ ; (A0) IF LESS THEN NO PAGTAB NECES + JGE SYS4 ; (A0) SET THE FLAGS + SUB BX,DX ; (7w) SUBTRACT ALL PRELOD BLOCKS + JA SYS3A ; (A3) FATAL IF MORE PRELOD THAN BLKS +SYS3$: FATAL FTL12 ; (A3) SO DIE +SYS3A: CMP BX,5 ; (A3) THERE MUST BE AT LEAST 2 BUFS + JBE SYS3$ ; (A3) SO DIE IF NOT ENOUGH + SUB BX,4 ; (A0) SUB 4 BUFS FOR PAGTAB + CMP BX,255 ; (6) ABOVE 256, WE NEED MORE TBL + JB SYS1 ; (6) WE HAVE THIS MANY OR FEWER + SUB BX,2 ; (6) TAKE AWAY ANOTHER PAGE + CMP BX,383 ; (A0) ARE WE BETWEEN 3 AND 4 SEGS + JB SYS1 ; (A0) CHECK FOR FIT + SUB BX,2 ; (A0) WE GOT PLENTY, NEED 2 BUFFS + CMP BX,511 ; (6) THIS IS THE MOST WE WILL NEED + JLE SYS1 ; (6) DON'T MODIFY BX <= 255 + MOV FITS,1 ; (6) FLAG THAT GAME FITS IN MEMORY + MOV BX,511 ; (6) DON'T ALLOW MORE THAN THIS +SYS1: PUSH BX ; (7w) SAVE THIS FOR FIDDLING + ADD BX,DX ;(7w) ADD IN THE BLOCKS PREV SBTRCTED + CMP BX,GAMESIZ ; (7n) CHECK FOR LUCKY FIT + POP BX ; (7w) AND RESTORE ACTUAL #BUFFERS + JBE SYSD$ ; (7n) IF BX IS GREATER, NO GO +SYS4: MOV FITS,1 ; (7n) IT DOES FIT AFTERALL!!! + MOV BX,OFFSET PAGTAB + JMP SYS5 +SYSD$: MOV BUFFERS,BX ; (6) SAVE THIS NUMBER + MOV CL,3 ; (A0) MULTIPLY BUFFERS BY 8 + SHL BX,CL ; (6) GET NUMBER OF BYTES IN PAGTBL + ADD BX,2 ; (A0) ADD 2 FOR TERMINATOR WORD + ADD BX,OFFSET PAGTAB ; (6) CALC TABLE LOCATION +SYS5: MOV CX,4 ; (6) REDUCE #BYTES IN TABLE = PARAS + SHR BX,CL ; (6) TO DYNAMICALLY ALLOCATE SPACE + MOV AX,DS ; (6) GET A COPY OF CURRENT SEG + ADD BX,AX ; (6) AND CALCULATE THE NEW SEG + ADD BX,1 ; (6) ADD ONE PARAGRAPH FOR SAFETY + MOV GAMESEG,BX ; (6) THIS WILL BE USED FOR ES:GAME + ADD BX,1000H ; (6) ADD 64K TO CALC 2ND SEG + MOV SEG1,BX ; (6) THIS IS SEG0+64K + TEST FITS,1 ; (A0) DON'T INIT A NON-EXISTANT TBL + JNZ SYS6 + CALL TBLINI ; (7n) CALL TABLE INITIALIZATION +SYS6: CALL SSETUP + CALL INITSND ; (A0) INITIAL TIMER2 FOR SOUND + MOV AX,GAMESEG ; (A0) SET ES TO GAME SEG + MOV ES,AX + RET +SYSFTL: FATAL FTL9 +SYSINI ENDP + + + ; THIS ROUTINE INITIALIZES THE PAGE TABLE + ; +TBLINI PROC + PUSH SI ; SAVES + PUSH DI + PUSH AX + PUSH BX + PUSH CX + MOV DI,OFFSET PAGTAB ; (6) GET BEGINNING ADDR + MOV CX,WORD PTR BUFFERS ; (6) GET NUMBER OF ENTRIES + MOV AX,DS ; (7)GET DATA SEG + MOV ES,AX ; (7) FIX ES + CLD ;(6) AUTO INCREMENT +INITLP: MOV SI,OFFSET INITTBL ; (6) POINT TO STRING TO INITIALIZE + PUSH CX ; (6) SAVE REP COUNT + MOV CX,8 ; (6) GET INNER LOOP COUNT + REP MOVSB ; (6) TRANSFER THE STRING TO TBL + POP CX ; (6) RESTORE COUNT + LOOP INITLP ; (6) AND FINISH TABLE INITIALIZING + MOV WORD PTR [DI],-1 ; (6) DEPOSIT A -1 TO INDICATE END + MOV BX,GAMESEG ; + MOV ES,BX ; (6) SET THE EXTRA SEG TO GAMESEG + POP CX ; RESTORES + POP BX + POP AX + POP DI + POP SI + RET +TBLINI ENDP + + PUBLIC GAMOPEN + ; THIS PROCEDURE OPENS THE GAME FILE AFTER CLOSING ALL FILES. + ; IF THE GAME FILE IS NOT ON THE DISK, IT PROMPTS FOR REINSERTION +GAMOPEN PROC + PUSH DX + MOV DL,DEFDRV ; (7o) GET DRIVE WHERE GAME IS + MOV AH,CSELDSK ; (7o) TO MAKE OPEN WIN + INT 21H ; (7o) DO IT + MOV AH,CFCLOSZ ; (7s) TRY CLOSING INSTEAD OF RESET + MOV BX,GAMHNDL ; (7s) OF THE GAME FILE + INT 21H ; (7o) TO MAKE SURE THIS WINS +GOPEN0: MOV AH,CFOPENZ ; (6) ASCIZ STRINGS + MOV AL,0 ; (6) OPEN FOR READING + MOV DX,OFFSET GAMFILE ; (7o) OPEN THE FILE AGAIN + INT 21H + JNC GOPEN1 ; (7o) IF SUCCESS, CONTINUE + PRINT SAV3 ; (7o) OTHERWISE PROMPT + CALL MCHRI ; (7o) AND WAIT FOR A CHARACTER + JMP GOPEN0 ; (7o) AND LOOP +GOPEN1: MOV GAMHNDL,AX ; (7o) SAVE GAME HANDLE + MOV DL,CURDRV ; (7v) RESTORE SAVE DRIVE + MOV AH,CSELDSK ; (7v) SO THAT WE ARE NOT CONFUSED + INT 21H ; (7v) THANKS MAX + POP DX + RET +GAMOPEN ENDP + + ; GIVEN SOURCE PTR IN DS:AX, AND A DEST PTR IN ES:DI, CHK SEARCHES + ; FOR THE DX CHARACTERS OF THE STRING POINTED TO BY DS:AX IN THE + ; FIRST (CX) BYTES OF THE STRING POINTED TO BY ES:DI + PUBLIC CHK +CHK PROC + CLD ; (7) CLEAR THE DIRECTION FLAG + PUSH SI ; (7) SAVE THIS + PUSH DX ; (7) SAVE THIS FOR RETRIES + MOV BP,SP ; (7) GET A FRAME POINTER + MOV SI,AX ; (7) SET UP FIRST OFFSET +LUP: CMP BYTE PTR [SI],'$' ; (7) END CHAR + JE MATCH ; (7) REACHING END==MATCH + CMPSB ; (7) COMPARE TWO BYTES + JNE RESET ; (7) RESET SOURCE IF MISMATCH + DEC DX + LOOP LUP ; (7) DECREMENT COUNTER AND TRY AGAIN + JMP RTFAIL ; (7) OUT OF CHARS, FAILED +RESET: MOV SI,AX ; (7) MOVE SOURCE PTR BACK INTO SI + MOV DX,[BP] ; (7) RESTORE NUMBER OF BYTES IN STR + LOOP LUP ; (7) TRY AGAIN +RTFAIL: STC ; (7) FAIL BY RETURNING CARRY SET + POP DX + POP SI ; (7) RESTORE SI + RET +MATCH: TEST DX,DX ; (7) MATCH OF ENTIRE STRING + JNZ RTFAIL + CLC ; (7) GOT A MATCH, RETURN CARRY CLEAR + POP DX + POP SI ; (7) RESTORE SI + RET +CHK ENDP + + ; THIS ROUTINE CHECKS THE COPY PROTECTION +CHKCOP PROC + CLC ; FOR NOW, EVERYTHING WORKS + RET +CHKCOP ENDP + + ; THIS ROUTINE SETS SOME VARIABLES ACCORDING TO THE CMD LINE +; CURRENTLY THE 6 /PARAMETERS ARE SUPPORTED. THE FIRST THREE, +; /P INITIALIZE PRINTER THROUGH INT 17 +; /M MONOCHROME +; /C COLOR +; /W WINDOWED SCROLLING +; /K AMOUNT OF MEMORY IN K +; ARE INTENDED FOR THE USER. A FOURTH WILL NOT BE DOCUMENTED IS +; /G WHICH WILL TEMPORARILY PATCH THE ZIP TO RUN THE +; GAME SPECIFIED. +; + PUBLIC SCANCMD,SCAN,SCAN0,SCAN1,SCAN2,SCAN3,SCAN4 + PUBLIC SCAN5,SCAN6,SCAN7,SCAN8 +SCANCMD PROC + CLD ; (7) AUTO INCREMENT + MOV SI,80H ; (7) GET # OF BYTES + LODSB ; (7) INTO AL + TEST AL,AL ; (7) ANY? + JNZ SCAN1 +SCAN0: RET ; (7) NONE THERE +SCAN1: DEC AL ; (7) CARRIAGE RETURN DOESN'T COUNT + XOR DX,DX ; (7) ZERO THIS + MOV DL,AL ; (7) SAVE NUMBER OF BYTES + ADD DX,82H ; (7) ADDR OF LAST BYTE+1 ON LINE + INC SI ; (7) SKIP INITIAL SPACE +SCAN: CMP SI,DX ; (7) END OF CMD LINE? + LODSB ; (7) GET A DELIMITER + JZ SCAN0 ; (7) YEP, RETURN + CMP AL,'/' ; (7) WAS IT THE DELIMITER + JNZ SCAN ; (7) GET NEXT VALID CHAR + LODSB ; (7) GOT DELIMITER, GET BYTE + AND AL,5FH ; (7) UPPERCASIFY + CMP AL,'M' ; (7) DO THEY WANT MONOCHROME + JNZ SCAN2 ; (7) NOPE, TRY NEXT + OR CMDLIN,1 ; (7) SET FLAG IN CMDLIN VARIABLE + JMP SCAN +SCAN2: CMP AL,'W' ; (7) WINDOWED SCROLLING? + JNZ SCAN3 + MOV SCROLL,0 ; (7) TURN ON SCROLLING + OR CMDLIN,8 ; (7) TURN ON 8 BIT + JMP SCAN +SCAN3: CMP AL,'G' ; (7) GAME FILE NAME? + JNZ SCAN5 ; (7) NOPE, CONTINUE ON... + MOV DI,OFFSET GAMFILE ; (7) MAKE THIS THE GAME +SCAN4: MOVSB ; (7) TRANSFER A BYTE + CMP DX,SI ; (7) THE END? + JNZ SCAN4 + MOV AL,0 ; (7) DROP IN A NULL + STOSB ; (7) TO END THE STRING + RET +SCAN5: CMP AL,'C' ; (7) DO THEY WANT COLOR + JNZ SCAN6 ; (7) NOPE, TRY NEXT + OR CMDLIN,2 ; (7) SET FLAG IN CMDLIN VARIABLE + JMP SCAN +SCAN6: CMP AL,'K' ; (7) SET MEMORY SIZE + JNZ SCAN9 ; (7) NOPE LOOK ONWARD + MOV BX,0 ; (7) ZERO THIS +SCAN7: CMP DX,SI ; (7) THE END? + JNZ SCAN8 ; (7) NOPE +SCAN7A: OR CMDLIN,4 ; (7) TURN ON MEMORY SET BIT + MOV CL,6 ; (7w) CONVERT K TO PARAGRAPHS + SHL BX,CL ; (7) I THINK??? + MOV MEMORY,BX ; (7) SAVE AMOUNT OF K SPECIFIED IN 512 BLKS + DEC SI ; (7v) BACKUP ONE + JMP SCAN +SCAN8: LODSB ; (7) GET FIRST BYTE + CMP AL,0D ; (7v) CR MEANS END OF STRING + JZ SCAN7A ; (7v) SO QUIT HERE + CMP AL,' ' ; (7v) SPACE MEANS NEXT STRING + JZ SCAN7A ; (7v) SO QUIT + CMP AL,'/' ; (7v) SLASH MEANS NEXT DELIMITER + JZ SCAN7A ; (7v) SO QUIT + XOR AH,AH ; (7) ZERO THIS + AAA ; (7) SCALE THE NUMBER DOWN + XCHG AX,BX ; (7) GET NUMBER (BX) INTO AC + PUSH DX ; (7) SAVE ENDPTR + MUL RADIX ; (7) MULTIPLY NUMBER BY TEN + ADD BX,AX ; (7) ADD IN NEW NUMBER + POP DX ; (7) RESTORE END PTR + JMP SCAN7 +SCAN9: CMP AL,'P' ; (7w) DO WE NEED TO INITIALIZE THE PRINTER + JZ SCAN10 ; (7w) YES, DO IT + JMP SCAN +SCAN10: PUSH DX ; (7w) SAVE THIS + MOV DX,0 ; (7w) INITIALIZE FIRST PRINTER + MOV AH,1 ; (7w) FUNCTION NUMBER FOR INIT + INT 17H ; (7w) ASSUME IBM PC BECAUSE THEY USED /P + POP DX ; (7w) RESTORE END POINTER + JMP SCAN ; (7w) NOW GET BACK TO WORK +SCANCMD ENDP diff --git a/ibm/sysio.ezp b/ibm/sysio.ezp new file mode 100644 index 0000000..e59f5a5 --- /dev/null +++ b/ibm/sysio.ezp @@ -0,0 +1,478 @@ + SUBTTL SYSIO - IBMPC SYSTEM ROUTINES + PAGE + + + PUBLIC MCHRI,MTTYO,MCRLF,MSPRT,MINIT,MPRNT,MTIME,FINISH + ;READ A CHARACTER INTO AX, WAITING UNTIL ONE IS AVAILABLE, NO ECHO +MCHRI PROC + PUSH CX + PUSH DX + CMP CHRFLG,0 + JNZ MCHR1 + MOV CHRFLG,1 +MCHR1: MOV AH,CNOECHO ; (7u) USE NO ECHO + INT 21H + SUB AH,AH + POP DX + POP CX + RET +MCHRI ENDP + + PUBLIC FEEP +FEEP PROC + MOV AX,7 + CALL MTTYO ;BELL + RET +FEEP ENDP + + ;PRINT THE CHARACTER IN AL, FOREGROUND IN AH +MTTYO PROC + PUSH AX + PUSH BX ;SAVES + PUSH CX + PUSH DX + PUSH BP + PUSH SI ; (A0) TRASHED ANOTHER + PUSH AX + TEST VIDFLG,1 ; (A10) IS THE SCREEN DEVICE ENABLED? + JZ MTY00 ; (A10) ....NO + DEC AL ; (A0) SEE IF IT IS IMBEDDED HILITE + XOR AH,AH + CMP AX,0 ; (A0) ITS VALUE WOULD BE BETWEEN 0-MAX + JB MTY0 + CMP AX,MAXHI + JA MTY0 + MOV SI,OFFSET COLORS ; ++ OF HILIGHTS + CMP COLFLG,1 ; (A5) SHOULD WE USE COLOR TABLE? + JZ MTY0A ; (A9) ....YES + MOV SI,OFFSET HILITES ; (A9) ^ IBM TABLE + CMP IBMPC,1 ; (A9) SHOULD WE USE THE IBM TABLE? + JZ MTY0A ; (A9) ....YES + MOV SI,OFFSET NONIBM ; (A9) USE THE NONIBM MONO TABLE +MTY0A: SHL AL,1 ; (A0) IT IS, MULTIPLY BY TWO + MOV BX,AX ; (A0) GET AN INDEX INTO TABLE + MOV BX,[BX][SI] ; (A0) BX HAS OFFSET TO STRING + CALL MSPRT ; (A0) PRINT THE STRING + POP AX + JMP MTYO1 ; (A0) RESTORE ON EXIT +MTY0: INC AL + MOV AH,CCONIO + MOV DL,AL + INT 21H +MTY00: POP AX ; (A10) NEW ENTRYPOINT + TEST SCRFLG,1 ; (7x) IS SCRIPTING REQUESTED? + JZ MTYO1 ; (7n) IF NOT THEN DON'T BOTHER + CMP SCRHLD,1 ; (7n) IS SCRIPTING SUSPENDED? + JZ MTYO1 + CALL PRTOUT +MTYO1: POP SI + POP BP + POP DX + POP CX + POP BX + POP AX + RET +MTTYO ENDP + + ;PRINT A CARRIAGE RETURN/LINE FEED WITH MORE MODE +MCRLF PROC + PUSH AX ;SAVES + PUSH BX + PUSH CX + PUSH DX + PUSH BP + TEST VIDFLG,1 ; (A14) SCREEN DEVICE ON? + JZ MCR1 ; (A14) SKIP SCREEN SCROLL + TEST SCROLL,1 ;(7) WHAT KIND OF SCROLLING + JNZ MCR$ + TEST SCRNFLG,1 ; (7) ARE WE IN SCREEN #1 + JNZ MCR$ ; (7) YES, USE OLD SCROLL + MOV AH,SCROLLUP ;(7) USE A VIDEO BIOS SCROLL + MOV AL,1 ;(7) ONLY 1 LINE + MOV CX,TOPLIN ;(7) ALWAYS FREEZE TOP LINE + MOV DX,184FH ; (A0) USE CONSTANT + MOV BH,SCRATR ;(7) GET THE SCREEN ATTRIBUTE + INT 10H ;(7) CALL THE VIDEO +MCR$: MOV AH,CCONIO + MOV DL,13 + INT 21H + TEST SCRNFLG,1 ; (7) ARE WE WRITING TO WINDOW 1 + JNZ MCRA$ + TEST SCROLL,1 ;(7) NO LINE FEED ON WINDOWED SCROLL + JZ NOLF +MCRA$: MOV AH,CCONIO + MOV DL,10 + INT 21H +NOLF: TEST SCRNFLG,1 ;(7) NO MORE FOR WINDOW 1 + JNZ MCR1 ;(7) SKIP THIS GARBAGE + INC MORLIN ;INCREMENT NUMBER OF LINES OUTPUT + MOV AL,SLPP + SUB AH,AH + DEC AX ;(7n) SO THAT STATUS LINE DOESN'T OVERWRITE +MCRB$: MOV DX,TOPLIN ;(7) GET SCROLLING WINDOW TOPLINE + XCHG DH,DL ;(7) SCROLL LINE IN DL + SUB AL,DL ;(7) THIS MANY LINES NOW + CMP MORLIN,AX + JL MCR1 + MOV MORLIN,0 + MOV SCRHLD,1 ; (7o) SUSPEND SCRIPT + PRINT MORE + CALL MCHRI + PRINT EMORE + MOV SCRHLD,0 ; (7o) RESUME SCRIPT +MCR1: TEST SCRFLG,1 ; (7x) CHANGED TO TEST + JZ MCR2 + CALL PRTCRL +;(E0) REMOVE THIS +; OR WORD PTR ES:[PFLAGS],REFRESH ;(A17)REFRESH THE STATUS LINE +MCR2: POP BP + POP DX + POP CX + POP BX + POP AX + RET +MCRLF ENDP + + +MSPRT PROC + MOV CL,BYTE PTR [BX] + SUB CH,CH + CMP CL,0 + JE MSPRT1 +MSPLP: INC BX + MOV DL,BYTE PTR [BX] + MOV AH,06H + PUSH BX + INT 21H + POP BX + LOOP MSPLP +MSPRT1: RET +MSPRT ENDP + +MINIT PROC +MINIT1: MOV BX,OFFSET STINIT + TEST COLFLG,1 ;(7) ARE WE IN COLOR MODE + JZ MINIT2 ;(7) + MOV BX,OFFSET CTINIT ;(7) +MINIT2: CALL MSPRT + RET +MINIT ENDP + + ;PRINT A STRING, POINTER (TO DATA SEGMENT) IN AX, WHITE FOREGROUND +MPRNT PROC + + ; (A10) SECTION COMMENTED OUT +; CMP GAMEIN,1 ; (7q)DO NOT CHECK THIS UNLESS THE GAME IS IN +; JNZ MPR0 +; PUSH AX +; MOV AX,ES:[PFLAGS] ; (7n) SCRIPTING? +; XCHG AH,AL ; (7n) SWAP BYTES +; MOV SCRFLG,AL ; (7n) TURN IT ON, TURN IT ON AGAIN! +; POP AX + +MPR0: PUSH BX ;SAVE BX + MOV BX,AX ;STRING POINTER +MPR1: MOV AL,[BX] ;GET NEXT CHARACTER + CMP AL,0 ;END OF LINE, WITH CRLF? + JE MPR2 ;YES + CMP AL,80H ;END OF LINE, NO CRLF? + JE MPR3 ;YES + CALL MTTYO ;PRINT CHARACTER + INC BX ;POINT TO NEXT CHARACTER + JMP MPR1 ;REPEAT +MPR2: CALL MCRLF ;PRINT A CRLF +MPR3: POP BX ;RESTORE BX + RET +MPRNT ENDP + + ; + ; GET TIME AND USE IT TO SEED THE RANDOM NUMBER GENERATOR + ; + +MTIME PROC + PUSH CX ; SAVE REGISTERS + PUSH DX + MOV AH,CTIME ; GET TIME OF DAY + INT 21H + CMP CX,0 ; (LD1) IF NO CLOCK TIME + JNE MTIME0 ; (LD1) IS, SO OK + MOV RSEED1,08D0EH ; (LD1) USE A NUMBER + MOV RSEED2,09F81H ; (LD1) I JUST MADE UP SO NOT 0 + JMP MTIME1 ; (LD1) DOES'NT MATTER, ONLY COMES HERE ONCE +MTIME0: MOV RSEED1,CX ; HOURS & MINUTES + MOV RSEED2,DX ; SECONDS & 100THS +MTIME1: POP DX ; RESTORE REGISTERS + POP CX + RET +MTIME ENDP + + ; ------------------------ + ; INITIALIZE SPEAKER TIMER + ; ------------------------ + ; + ; PURPOSE: THIS ROUTINE INITIALIZES THE PORTION OF THE 8253 TIMER + ; CHIP USED BY THE SPEAKER SYSTEM. IN PARTICULAR, IT SETS + ; UP CHANNEL 2 OF THE TIMER AS A SQUARE-WAVE GENERATOR. + ; + ; *** NOTE *** THIS ROUTINE IS TO BE CALLED DURING COLD START + ; + ; INPUTS: NONE + ; + ; OUTPUTS: TIMER 2 + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC INITSND +INITSND PROC + PUSH AX ;(A0) SAVE REGISTERS + MOV AL,TMRCWD ;(A0) GET TIMER CONTROL WORD + OUT TMRCPT,AL ;(A0) SEND IT TO THE CONTROL PORT + POP AX ;(A0) RESTORE REGISTERS + RET +INITSND ENDP + + ; ---------------------- + ; SET THE TONE FREQUENCY + ; ---------------------- + ; + ; PURPOSE: THIS ROUTINE SELECTS THE FREQUENCY OF THE SQUARE-WAVE + ; TONE TO THE SPEAKER. + ; + ; INPUTS: CX=FREQUENCY + ; + ; OUTPUTS: TIMER 2 + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC TONESET +TONESET PROC + PUSH AX ;(A0) SAVE REGISTERS + PUSH CX + MOV AL,CL ;(A0) GET LOWER BYTE + OUT TMRDPT,AL ;(A0) SEND OUT VALUE TO TIMER + MOV AL,CH ;(A0) GET UPPER BYTE + OUT TMRDPT,AL ;(A0) SEND OUT VALUE TO TIMER + POP CX ;(A0) RESTORE REGISTERS + POP AX + RET +TONESET ENDP + + ; ------------ + ; TURN ON TONE + ; ------------ + ; + ; PURPOSE: THIS ROUTINE TURNS ON THE TIMER AND SPEAKER TO PRODUCE + ; A TONE. THE FREQUENCY OF THE TONE MUST HAVE ALREADY + ; BEEN SENT TO THE TIMER. + ; + ; INPUTS: NONE + ; + ; OUTPUTS: TIMER 2, AND SPEAKER + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC TONEON +TONEON PROC + PUSH AX ;(A0) SAVE REGISTERS + IN AL,PTBCPT ;(A0) GET SYSTEM PORT B CONTROL DATA + OR AL,SPKRON ;(A0) TURN SPEAKER AND TIMER ON + OUT PTBCPT,AL ;(A0) SEND OUT NEW VALUE + POP AX ;(A0) RESTORE REGISTERS + RET +TONEON ENDP + + ; ------------ + ; TURN OFF TONE + ; ------------ + ; + ; PURPOSE: THIS ROUTINE TURNS OFF THE TIMER AND SPEAKER + ; + ; INPUTS: NONE + ; + ; OUTPUTS: TIMER 2, AND SPEAKER + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC TONEOFF +TONEOFF PROC + PUSH AX ;(A0) SAVE REGISTERS + IN AL,PTBCPT ;(A0) GET SYSTEM PORT B CONTROL DATA + AND AL,SPKROFF ;(A0) TURN SPEAKER AND TIMER OFF + OUT PTBCPT,AL ;(A0) SEND OUT NEW VALUE + POP AX ;(A0) RESTORE REGISTERS + RET +TONEOFF ENDP + + ; ----- + ; DELAY + ; ----- + ; + ; PURPOSE: THIS ROUTINE DELAYS FOR A SPECIFIED NUMBER OF .05 SEC + ; INTERVALS. + ; + ; INPUTS: [CX] = NUMBER OF .05 SEC TO DELAY + ; + ; OUTPUTS: NONE + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC DELAY,DELAY1,DELAY2 +DELAY PROC + PUSH AX ;(A0) SAVE REGISTERS + PUSH BX + PUSH CX + PUSH DX + + CALL SYNCH ;(A0) SYNCHRONIZE TIMER + MOV TIMER,DL ;(A0) SAVE 1/100 SEC COUNT + + ; TIMING LOOP +DELAY1: PUSH CX ;(A0) SAVE LOOP COUNTER +DELAY2: MOV AH,CTIME ;(A0) GET THE TIME UNTIL IT CHANGES + INT 21H ;(A0) MSDOS FUNCTION CALL + CMP DL,TIMER ;(A0) HAS THE CLOCK TICKED? + JNZ DELAY3 ; YES, GO DO COUNTDOWN + CMP DL,0 ; NO, BUT IF NOT STUCK AT 0 + JNZ DELAY2 ; WAIT FOR IT TO TICK + POP CX ; CLEAN UP STACK + JMP DELAY4 ; AND LEAVE +DELAY3: MOV TIMER,DL ;(A0) SAVE NEW COUNT + POP CX ; GET LOOP COUNTER BACK + LOOP DELAY1 ;(A0) AND LOOP + +DELAY4: POP DX ;(A0) RESTORE REGISTERS + POP CX + POP BX + POP AX + RET +DELAY ENDP + + ; ----- + ; SYNCH + ; ----- + ; + ; PURPOSE: THIS ROUTINE WAITS FOR A CHANGE IN THE 1/100 SEC TIMER, TO + ; INSURE THAT WE'RE AT THE START OF A NEW TIME PERIOD. + ; + ; INPUTS: NONE + ; + ; OUTPUTS: [DL] = 1/100 SEC COUNT AT SYNCH TIME + ; + ; REGISTERS DESTROYED: DL + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC SYNCH,SYNCH1 +SYNCH PROC + PUSH AX ;(A0) SAVE REGISTERS + PUSH BX + PUSH CX + MOV AH,CTIME ;(A0) GET THE TIME FROM THE REAL TIME CLOCK + INT 21H ;(A0) MSDOS FUNCTION CALL + MOV TIMER,DL ;(A0) SAVE 1/100 SEC COUNT + + ; SYNCHRONIZE +SYNCH1: MOV AH,CTIME ;(A0) GET THE TIME AGAIN, SO WE CAN INSURE + INT 21H ;(A0) THAT WE ARE SYNCHRONIZED WITH THE + CMP DL,TIMER ;(A0) START OF A NEW TIMING PERIOD + JNZ SYNCH2 ; CLOCK TICKED, SO WIN + CMP DL,0 ; CLOCK DIDN'T TICK, AND IS 0, SO QUIT + JNZ SYNCH1 ; HACK TO PREVENT LOOPS WHEN 1/100'S + ; CLOCK ISN'T WORKING +SYNCH2: POP CX ;(A0) RESTORE REGISTERS + POP BX + POP AX + RET +SYNCH ENDP + + ; ---- + ; FREQ + ; ---- + ; + ; PURPOSE: THIS ROUTINE CONVERTS A FREQUENCY TO THE NUMBER REQUIRED + ; BY TONESET. + ; + ; INPUTS: [CX] = FREQUENCY IN HZ + ; + ; OUTPUTS: [CX] = CONVERTED VALUE + ; + ; REGISTERS DESTROYED: CX + ; + ; EXTERNAL REFERENCES: NONE + ; + + PUBLIC FREQ +FREQ PROC + PUSH AX ;(A0) SAVE REGISTERS + PUSH BX + PUSH DX + + ; DIVIDE FREQUENCY BY 1193182 + MOV DX,12H ;(A0) UPPER PART OF NUMERATOR + MOV AX,34DEH ;(A0) LOWER PART OF NUMERATOR + DIV CX ;(A0) DIVIDE BY FREQUENCY + MOV CX,AX ;(A0) QUOTIENT IS THE OUTPUT + POP DX ;(A0) RESTORE REGISTERS + POP BX + POP AX + RET +FREQ ENDP + + ; ----------- + ; MAKE A TONE + ; ----------- + ; + ; PURPOSE: THIS ROUTINE MAKES A TONE OF A GIVEN FREQUENCY AND LENGTH + ; + ; INPUTS: [CX] = FREQUENCY IN HZ + ; [DX] = DURATION IN .05 SEC + ; + ; OUTPUTS: TO THE SPEAKER AND TIMER 2 + ; + ; REGISTERS DESTROYED: NONE + ; + ; EXTERNAL REFERENCES: {TONESET}, {TONEON}, {TONEOFF}, {DELAY} + ; + + PUBLIC TONE +TONE PROC + PUSH AX ;(A0) SAVE REGISTERS + PUSH BX + PUSH CX + PUSH DX + + ; COMPUTE THE FREQUENCY AND SETUP THE TONE GENERATOR (TIMER 2) + CALL FREQ ;(A0) CONVERT THE FREQUENCY + CALL TONESET ;(A0) SET UP TIMER 2 + + ; TURN ON THE TONE + CALL TONEON + + ; WAIT FOR THE DELAY TIME + MOV CX,DX + CALL DELAY + + ; TURN OFF THE TONE + CALL TONEOFF + + POP DX ;(A0) RESTORE THE REGISTERS + POP CX + POP BX + POP AX + RET +TONE ENDP diff --git a/ibm/tableops.ezp b/ibm/tableops.ezp new file mode 100644 index 0000000..0366c2f --- /dev/null +++ b/ibm/tableops.ezp @@ -0,0 +1,115 @@ + SUBTTL TABLE OPERATIONS + PAGE + + PUBLIC OPINTBL,OPINT1,OPINT2 + ;IS THE GIVEN WORD IN THE TABLE? + ; AX = WORD TO COMPARE + ; BX ^ TO TABLE + ; CX = NUMBER OF ELEMENTS IN THE TABLE + ; +OPINTBL PROC + MOV DX,AX ;(A12) SAVE WORD + MOV AX,BX ;(A12) GET ^ IN AX +OPINT1: PUSH AX ;(A12) SAVE POINTER + PUSH CX ;(A12) SAVE LOOPCOUNTER + CALL BSPLTB ;(A12) SPLIT THE POINTER + CALL GETWRD ;(A12) GET THE WORD + CMP CX,DX ;(A12) COMPARE THE TWO ITEMS + JE OPINT2 ;(A12) WE FOUND A MATCH + POP CX ;(A12) RESTORE LOOPCOUNTER + POP AX ;(A12) RESTORE ^ TO TABLE + INC AX ;(A12) UPDATE POINTER + INC AX + LOOP OPINT1 ;(A12) NEXT ELEMENT + + ;{CASE} FAILURE + XOR AX,AX ;(A12) WE DIDN'T FIND ANYTHING + CALL PUTVAL + JMP PFALSE ;(A12) + + ;{CASE} SUCCESS +OPINT2: POP CX ;(A12) + POP AX ;(A12) + CALL PUTVAL + JMP PTRUE ;(A12) +OPINTBL ENDP + + PUBLIC OPGET,OPGETB,OPPUT,OPGTPT + ;GET (GET THE ITEM'TH WORD FROM TABLE) +OPGET PROC + SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETWRD ;GET THE WORD + MOV AX,CX + JMP PUTVAL ;AND RETURN IT +OPGET ENDP + + ;GETB (GET THE ITEM'TH BYTE FROM TABLE) +OPGETB PROC + ADD AX,BX ;INDEX INTO TABLE + CALL BSPLTB ;SPLIT THE POINTER + CALL GETBYT ;GET THE BYTE + MOV AX,CX + JMP BYTVAL ;AND RETURN IT +OPGETB ENDP + + ;PUT (REPLACE THE ITEM'TH WORD IN TABLE) +OPPUT PROC + SHL BX,1 ;CONVERT ITEM TO BYTE COUNT + ADD BX,AX ;INDEX INTO TABLE + PTAWRD [BX],C ;STORE THE WORD + RET +OPPUT ENDP + + ;PUTB (REPLACE ITEM'TH BYTE IN TABLE) +OPPUTB PROC + ADD BX,AX ;INDEX INTO TABLE + MOV ES:[BX],CL ; STORE BYTE + RET +OPPUTB ENDP + + ;GETPT (GET POINTER TO PROPERTY TABLE FOR GIVEN PROP) +OPGTPT PROC + MOV DX,BX ;PROPERTY + CALL OBJLOC ;FIND OBJ'S LOCATION + CALL FSTPRP ; (A0) GET POINTER TO FIRST PROPERTY + JMP OGT2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP +OGT1$: CALL NXTPRP ;POINT TO NEXT PROPERTY +OGT2$: MOV AL,ES:[BX] ;GET PROPERTY IDENTIFIER + AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS + CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE + JG OGT1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE) + JE OGT3$ ;FOUND THE PROPERTY + SUB AX,AX ;RETURN ZERO FOR NO SUCH PROPERTY + JMP OGT4$ + +OGT3$: MOV AL,ES:[BX] ;NOW FIND LENGTH OF PROPERTY + INC BX ;POINT TO PROPERTY VALUE + TEST AL,80H ; (A0) PROPERTY LENGTH GREATER THAN 2? + JNZ OGT3B$ ; (A0) YES + JMP OGT3C$ +OGT3B$: INC BX ; (A0) UPDATE POINTER +OGT3C$: MOV AX,BX ;AND RETURN IT +OGT4$: JMP PUTVAL +OPGTPT ENDP + + PUBLIC OPPTSI + ;PTSIZE (RETURN SIZE OF PROPERTY TABLE) +OPPTSI PROC + MOV BX,AX ;TABLE POINTER + MOV AL,ES:[BX-1] ;GET PROPERTY INDENTIFIER + TEST AL,80H ; (A0) PROPERTY LENGTH GREATER THAN 2? + JNZ OPTSB$ ; (A0) YES + TEST AL,40H ; (A0) NO, PROPERTY LENGTH 2? + JNZ OPTSA$ ; (A0) NO, PROPERTY LENGTH 1 + MOV AX,1 ; (A0) LENGTH IS 1 + JMP PUTVAL +OPTSA$: MOV AX,2 ; (A0) LENGTH IS 2 + JMP PUTVAL +; +OPTSB$: AND AL,MASK PROPNUM ; (A0) MASK OUT OTHER BITS + XOR AH,AH ; (A0) CLEAR THESE + JMP PUTVAL ;RETURN IT +OPPTSI ENDP + + diff --git a/ibm/varops.ezp b/ibm/varops.ezp new file mode 100644 index 0000000..4889ba2 --- /dev/null +++ b/ibm/varops.ezp @@ -0,0 +1,75 @@ + SUBTTL VARIABLE OPERATIONS + PAGE + + + PUBLIC OPVALU,OPSET,OPPUSH,OPPOP + ;VALUE (GET VALUE OF VAR) +OPVALU PROC + CALL GETVAR ;GET THE VALUE + JMP PUTVAL ;AND RETURN IT +OPVALU ENDP + + ;SET (VAR TO VALUE) +OPSET PROC + JMP PUTVAR ;STORE THE VALUE +OPSET ENDP + + ;PUSH (A VALUE ONTO THE STACK) +OPPUSH PROC + PUSHZ AX ;PUSH THE VALUE + RET +OPPUSH ENDP + + ;POP (A VALUE OFF THE STACK INTO VAR) +OPPOP PROC + POPZ BX ;POP A VALUE + JMP PUTVAR ;AND STORE IT +OPPOP ENDP + + PUBLIC OPINC,OPDEC + ;INC (INCREMENT VAR) +OPINC PROC + MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT +OPINC1: MOV BX,AX ;VALUE + MOV AX,CX ;VARIABLE + JMP PUTVAR ;STORE NEW VALUE +OPINC ENDP + + ;DEC (DECREMENT VAR) +OPDEC PROC + MOV CX,AX ;VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + JMP OPINC1 ;STORE NEW VALUE +OPDEC ENDP + + PUBLIC OPQIGR,OPQDLE + ;IGRTR? (INCREMENT VAR & TEST IF GREATER THAN VAL) +OPQIGR PROC + PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + INC AX ;INCREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE GREATER THAN VAL? + JLE OPQIG1 ;NO +OPQIG0: INC CX ;YES, CHANGE FLAG TO TRUE +OPQIG1: MOV BX,AX ;VALUE + POP AX ;RESTORE VARIABLE + CALL PUTVAR ;STORE NEW VALUE + CMP CX,0 ;TEST FLAG + JE OQI1$ ;FALSE, PREDICATE FALSE + JMP PTRUE ;ELSE, PREDICATE TRUE +OQI1$: JMP PFALSE +OPQIGR ENDP + + ;DLESS? (DECREMENT VAR & TEST IF LESS THAN VAL) +OPQDLE PROC + PUSH AX ;SAVE VARIABLE + CALL GETVAR ;GET VAR'S VALUE + DEC AX ;DECREMENT IT + SUB CX,CX ;SET FLAG FALSE + CMP AX,BX ;NEW VALUE LESS THAN VAL? + JGE OPQIG1 ;NO, PREDICATE FALSE + JMP OPQIG0 ;YES, PREDICATE TRUE +OPQDLE ENDP diff --git a/ibm/zipbegin.ezp b/ibm/zipbegin.ezp new file mode 100644 index 0000000..3f4a058 --- /dev/null +++ b/ibm/zipbegin.ezp @@ -0,0 +1,211 @@ + SUBTTL ZIPBEGIN + PAGE + + PUBLIC ZIPBGN,STR5$,STR8$,STR11$,STR11,STR11A,NOITAL + PUBLIC STR12$,STR12A + PUBLIC STR12B,STR13$,STR14$,STR15$,STR17$ +ZIPBGN PROC + CALL SYSINI ;DO ANY SYSTEM INITIALIZATION +STR5$: SUB AX,AX ;BLOCK 0 + SUB BX,BX ;PUT AT BEGINNING OF GAME SEGMENT + CALL GETBLK ;GET THE BLOCK + MOV GAMEIN,1 ; (7q) INDICATE RELIABILITY OF SCRIPT BIT + CMP BYTE PTR ES:[PVERS1],ZMVERS ;PROPER Z-MACHINE VERSION? + JNE STR8$ ;NO + TEST BYTE PTR ES:[PVERS2],1 ;YES,PROPER MODE BITS? + JE STR11$ ;YES +STR8$: FATAL FTL4 ;SOMETHING WRONG, DIE + + ; IF THE SCREEN OPS OF THE MODE BYTE ([PVERS2]) ARE ENABLED, + ; SCROLL = 0. +STR11$: + TEST SCROLL,1 ; (7) CAN WE SPLIT THE SCREEN + JNZ STR11A ; (7) GUESS NOT... + + MOV AL,BYTE PTR ES:[PVERS2] + OR AL,3FH ; (A0) TURN ON ALL OPTIONS + CMP COLFLG,1 ; (A6) TURN OFF ITALIC IF COLOR + JE NOITAL ; (A9) .....IT'S COLOR + + ; IT'S NOT COLOR + ; IF THIS IS NOT AN IBM, ELIMINATE ITALICS + CMP IBMPC,1 ; (A9) IS THIS AN IBM PC? + JE STR11 ; (A9) ....YES +NOITAL: AND AL,37H ;(A6)TURN OFF THE ITALIC BIT IN THE MODE BYTE +STR11: MOV BYTE PTR ES:[PVERS2],AL ;(7) SAVE IT +STR11A: MOV BYTE PTR ES:[PINTVR],IBM_ID ; (A0) OTHER THAN THE 20 + MOV BYTE PTR ES:[PINTID],ZVERSN ; (A0) SET VERSION LET + MOV AL,SLPP + MOV BYTE PTR ES:[PSCLIN],AL + MOV AL,SCPL + MOV BYTE PTR ES:[PSCCOL],AL + GTAWRD A,[PZRKID] ;UNIQUE GAME & VERSION INDENTIFIER + MOV ZORKID,AX + GTAWRD A,[PENDLD] ;GET ENDLOD POINTER + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR12$ + AND AX,0FE00H + ADD AX,200H +STR12$: MOV CX,AX + MOV BP,CX ;EXTRACT ENDLOD BLOCK + MOV CL,9 + SHR BP,CL + MOV CX,BP + MOV ENDLOD,CX ;SAVE ENDLOD BLOCK NUMBER + MOV AX,128 ;(6) FIGURE BOUNDRY FOR SEG1 + SUB AX,CX ;(6) SUBTRACT AMOUNT IN PRELOD + PUSH CX + MOV CX,TBLSHF ; (A0) MULTIPLY END OF SEG BY TABLE WIDTH + SHL AX,CL ; (A0) DO IT + POP CX ; (A0) RESTORE THIS VALUE + MOV SEGEND,AX ;(6) USED TO COMPARE TO PAGTAB TO LOCATE + ;(6) SEGMENT IN WHICH GAMEBLOCK RESIDES + DEC CX ;NUMBER OF BLOCKS LEFT TO LOAD + CMP FITS,1 ;(6) READ THE WHOLE GAME IN + JNE STR12A ;(6) NO, DON'T READ IT ALL IN + + MOV AX,1 ; (A0) START WITH BLOCK 1 + MOV LPTAB,1 ; (A0) BUFFER 1 + MOV CX,63 ; (A0) LESS FIRST BLOCK + CALL GTBLKS ; (A0) GET THIS SECTION + JNE DONERD ; (A0) THIS WILL HAPPEN ON ZIPTEST + MOV AX,64 ; (A0) WE HAVE READ 0 TO 63 + MOV LPTAB,64 ; (A0) UPDATE THIS TOO + +READLP: MOV CX,64 ; (A0) READ IN 32K READS +READLP1:PUSH AX ; (A0) SAVE BLOCK NUMBER + CALL GTBLKS ; (A0) READ IT IN + POP AX ; (A0) AND RESTORE BLOCK NUMBER + JNE DONERD ; (A0) READ UNTIL READ FAILS + ADD LPTAB,64 ; (A0) BUMP BUFFER VAR + ADD AX,64 ; (A0) INC THIS + JMP READLP +DONERD: MOV LPTAB,0 + JMP STR12B +STR12A: MOV AX,1 ;STARTING WITH BLOCK 1 + MOV BX,OFFSET PAGTAB ; (6) GET A BUFFER ADDRESS + ADD BX,TABWID ; (A0) MOVE TO SECOND ENTRY + MOV LPTAB,BX ; (6) SAVE THIS CALCULATED ADDR + CALL GTBLKS ;GET THE BLOCKS +STR12B: GTAWRD A,[PVOCTB] ;VOCAB LOCATION + MOV VOCTAB,AX ;SAVE VOCABULARY TABLE POINTER + GTAWRD A,[POBJTB] ;GET OBJECT TABLE POINTER + MOV OBJTAB,AX + GTAWRD A,[PGLOTB] ;GET GLOBAL TABLE POINTER + MOV GLOTAB,AX + GTAWRD A,[PWRDTB] ;GET WORD TABLE POINTER + MOV WRDTAB,AX + GTAWRD A,[PPURBT] ;GET PURE CODE POINTER + TEST AX,1FFH ;ROUND UP TO NEXT BLOCK + JE STR13$ + ADD AX,200H +STR13$: MOV CL,9 ;EXTRACT BLOCK NUMBER + SAR AX,CL + AND AX,7FH ;CLEAR UNWANTED BITS + MOV PURBOT,AX ;SAVE IT + MOV BX,OFFSET RBRKS ;START OF READ BREAK CHARACTER TABLE + MOV SI,VOCTAB ;VOCAB TABLE POINTER + MOV CL,BYTE PTR ES:[SI] ;1ST BYTE IN VOCTAB IS # OF SIBREAKS + SUB CH,CH ;CLEAR HIGH BYTE + INC SI +STR14$: MOVM [BX],ES:[SI],AL ;TRANSFER THEM + INC BX + INC SI + LOOP STR14$ + MOV ESIBKS,BX ;REMEMBER END OF SI BREAKS + MOV BP,OFFSET IRBRKS;ALWAYS END WITH INITIAL BREAK CHARACTERS +STR15$: MOVM [BX],[BP],AL ;(6)TRANSFER THEM + INC BX + INC BP + CMP AL,0 + JNE STR15$ + MOV AL,ES:[SI] ;GET VOCABULARY ENTRY LENGTH + SUB AH,AH + MOV VWLEN,AX ;AND STORE IT AWAY + INC SI + GTAWRD A,[SI] ;GET NEXT WORD IN TABLE + MOV VWORDS,AX ;NUMBER OF WORD ENTRIES IN VOCABULARY + ADD SI,2 ;MOVE TO NEXT WORD + MOV VOCBEG,SI ;BEGINNING OF ACTUAL VOCABULARY + + MOV SI,ENDLOD ;GET # PAGES IN ENDLOD + MOV CL,9 + SHL SI,CL ;THIS IS FIRST LOCATION (ES:) OF PAGING + MOV PAGES,SI ;SAVE THIS TO USE AS AN OFFSET + +STR17$: JMP START1 +ZIPBGN ENDP + + ;RESTART EXECUTION HERE + PUBLIC RESTRT,RESTRT1,START1 + PUBLIC RESTR1,RESTR2,RESTR3 +RESTRT PROC + CALL GAMOPEN ; (7q) OPEN THE GAME FILE + MOV MORLIN,0 ; (7s) RESET MORE COUNT + SUB AX,AX ;REREAD ALL OF THE IMPURE STUFF + MOV CURSEG,0 ; (K5) SET SEG FLAGS BACK TO SEG0 + MOV ZPCSEG,0 + MOV LPTAB,0 ; (6) FILL THE FIRST BIT OF STUFF + PUSH PAGES ; (6) SAVE THIS VARIABLE + MOV PAGES,0 ; (6) RESET IT FOR SMALL MEMORY READ + MOV CX,PURBOT + CALL GTBLKS + POP PAGES ; RESET IT AGAIN + + MOV AH,SCRFLG ; (7o) WERE WE SCRIPTING? + XOR AL,AL ; (7o) ZERO THIS + MOV WORD PTR ES:[PFLAGS],AX ; (7o) RESTORE SCRIPTING STATE + + MOV AL,BYTE PTR ES:[PVERS2] + OR AL,3FH ; (A0) TURN ON ALL OPTIONS + + ; IF THE SCREEN OPS OF THE MODE BYTE ([PVERS2]) ARE ENABLED, + ; SCROLL = 0. +RESTR1: TEST SCROLL,1 ; (7) CAN WE SPLIT THE SCREEN + JNZ RESTR2 ; (7) GUESS NOT... + + MOV AL,BYTE PTR ES:[PVERS2] + OR AL,3FH ; (A9) TURN ON ALL OPTIONS + CMP COLFLG,1 ; (A9) TURN OFF ITALIC IF COLOR + JZ RESTR2 ; (A9) .....IT'S COLOR + + ; IT'S NOT COLOR + ; IF THIS IS NOT AN IBM, ELIMINATE ITALICS + CMP IBMPC,1 ; (A9) IS THIS AN IBM PC? + JE RESTR3 ; (A9) ....YES +RESTR2: AND AL,37H ; (A9) TURN OFF ITALIC BIT IN THE MODE BYTE +RESTR3: MOV BYTE PTR ES:[PVERS2],AL ;(7) SAVE IT + MOV BYTE PTR ES:[PINTVR],IBM_ID ; (A0) OTHER THAN THE 20 + MOV BYTE PTR ES:[PINTID],ZVERSN ; (A0) SET VERSION LET + MOV AL,SLPP + MOV BYTE PTR ES:[PSCLIN],AL + MOV AL,SCPL + MOV BYTE PTR ES:[PSCCOL],AL + OR BYTE PTR ES:[PVERS2],SCRBIT ; (7) TURN ON SPLIT + MOV TOPLIN,0 ; (7) FIX SCREEN VARIABLES ON RESTART + MOV SCRNFLG,0 ; (7) WHOLE SCREEN, ONLY 1 + MOV SPLTFLG,0 ; (7) NO SPLIT SCREEN + JMP RESTRT1 ; PATCH TO FIX STATUS LINE BUG (5)/PHG +START1: + +; MOV AL,BYTE PTR ES:[PVERS2] +; ADD AL,8 ;TANDY BIT +; MOV BYTE PTR ES:[PVERS2],AL + + CALL TSETUP ;SETUP TERMINAL/STATUS LINE +RESTRT1:MOV CHRCNT,79 ;(A13) INIT OUTPUT BUFFER COUNTER + CALL MTIME ;(A0) INITIALIZE RANDOM SEEDS +; (LD1) MOV RNDFLG,0 ;(A0) SELECT NORMAL RANDOM NUMBER GENERATION + CALL CLRSCR ;CLEAR THE REMAINDER OF SCREEN + MOV SP,OFFSET STK_TOP ;INITIALIZE OUR STACK POINTER + MOV DI,OFFSET ZSTK_TP ;INITIALIZE USER STACK POINTER + MOV CHRPTR,OFFSET OUTBUF ;INITIALIZE OUTPUT CHARACTER POINTER + MOV ZLOCS,DI ;LOCALS WOULD START AT FIRST SLOT, + SUB ZLOCS,2 ;IF THERE WERE ANY + GTAWRD A,[PSTART] ;GET STARTING LOCATION + CALL BSPLTB ;SPLIT BLOCK & BYTE POINTERS + MOV ZPC1,AX ;INITIALIZE ZPC BLOCK-POINTER + MOV ZPC2,BX ;INITIALIZE ZPC BYTE-POINTER + CALL NEWZPC ;GET PAGE TO EXECUTE + JMP NXTINS +RESTRT ENDP diff --git a/ibm/zstrings.ezp b/ibm/zstrings.ezp new file mode 100644 index 0000000..f37f4b8 --- /dev/null +++ b/ibm/zstrings.ezp @@ -0,0 +1,412 @@ + SUBTTL STRING FUNCTIONS + PAGE + + + ;OUTPUT A ZSTR, BLOCK-POINTER IN AX, BYTE-POINTER IN BX + ;RETURN UPDATED POINTER + PUBLIC PUTSTR +PUTSTR PROC + PUSH SI ;SAVE + PUSH CX ;SAVE + PUSH DX ;SAVE + PUSH DI ;SAVE + PUSH BP ;SAVE + SUB DX,DX ;TEMP CS STARTS AT 0 + SUB DI,DI ;PERM CS STARTS AT 0 +PTS1$: CALL GETWRD ;GET NEXT STRING WORD + MOV SI,CX + PUSH AX ;SAVE POINTER & COPY OF STRING WORD + PUSH BX + PUSH SI + MOV CX,3 ;3 BYTES IN WORD +PTS2$: PUSH SI ;SAVE CURRENT BYTE (IN LOW-ORDER POSITION) + MOV BP,CX ;SHIFT TO NEXT BYTE + MOV CL,5 + SAR SI,CL + MOV CX,BP + LOOP PTS2$ ;LOOP UNTIL DONE + MOV CX,3 ;RETRIEVE THE 3 BYTES +PTS3$: POP SI ;GET NEXT BYTE + AND SI,1FH ;CLEAR UNWANTED BITS + CMP DX,0 ;IN WORD MODE? + JGE PTS4$ ;NO {WAS BPL, CHECK} + SAL SI,1 ;YES, CALCULATE WORD OFFSET + ADD SI,WRDTAB ;POINT INTO WORD TABLE + ADD SI,WRDOFF ;USING PROPER 32-WORD BLOCK + GTAWRD A,[SI] ;POINT TO WORD STRING + CALL BSPLIT ; SPLIT IT + CALL PUTSTR ;AND PRINT IT + JMP PTS15$ ;CONT. WHERE WE LEFT OFF WITH TEMP CS RESET +PTS4$: CMP DX,3 ;CS 3 SELECTED (ASCII MODE)? + JL PTS6$ ;NO, NORMAL CS + JNE PTS5$ ;NO, BUT WE ARE IN ASCII MODE + XCHG DL,DH ;SHIFT SOME BITS HIGH TO MAKE NUMBER LARGE + OR DX,SI ;SAVE HIGH-ORDER ASCII BITS HERE + JMP PTS16$ ;GO GET NEXT BYTE +PTS5$: AND DX,3 ;EXTRACT PREVIOUSLY SAVED HIGH-ORDER BITS + MOV BP,CX ;POSITION THEM + MOV CL,5 + SAL DX,CL + MOV CX,BP + OR DX,SI ;OR IN LOW-ORDER BITS + MOV AX,DX + JMP PTS14$ ;GO PRINT THE CHARACTER +PTS6$: CMP SI,6 ;SPECIAL CODE? + JL PTS9$ ;YES, SPACE, WORD, OR SHIFT + CMP DX,2 ;MIGHT ALSO BE SPECIAL IF IN CS 2 + JNE PTS8$ ;BUT WE'RE NOT + CMP SI,7 ;CRLF? + JE PTS7$ ;YES + JG PTS8$ ;NO, NOT ASCII MODE, EITHER? + INC DX ;YES IT IS, SWITCH TO ASCII MODE + JMP PTS16$ ;AND GO GET NEXT BYTE +PTS7$: CALL NEWLIN ;CRLF REQUESTED, DO A NEWLINE + JMP PTS15$ +PTS8$: MOV AX,DX ;NORMAL CHARACTER, GET CS + MOV BP,26 ;CALCULATE OFFSET FOR THIS CS + MUL BP + ADD AX,SI ;ADD IN CHARACTER OFFSET (+6) + SUB AX,6 ;CHARACTER OFFSET + MOV BX,OFFSET ZCHRS ;GET THE CHARACTER FROM CONVERSION VECTOR + XLAT ZCHRS + JMP PTS14$ ;GO PRINT IT +PTS9$: CMP SI,0 ;IS IT A SPACE? + JNE PTS10$ ;NO + MOV AX," " ;YES, GO PRINT A SPACE + JMP PTS14$ +PTS10$: CMP SI,3 ;IS IT A WORD? + JG PTS11$ ;NO, MUST BE A SHIFT + OR DX,8000H ;SWITCH TO WORD MODE FOR NEXT BYTE + DEC SI ;CALCULATE WORD-TABLE BLOCK OFFSET + MOV BP,CX ;64 BYTES IN A BLOCK + MOV CL,6 + SHL SI,CL + MOV CX,BP + MOV WRDOFF,SI ;SAVE IT AND LOOP + JMP PTS16$ +PTS11$: SUB SI,3 ;CALCULATE NEW CS + CMP DX,0 ;TEMPORARY SHIFT (FROM CS 0)? + JNE PTS12$ ;NO + MOV DX,SI ;YES, JUST SAVE NEW TEMP CS + JMP PTS16$ +PTS12$: CMP SI,DX ;IS THIS THE CURRENT CS? + JE PTS13$ ;YES, DO A PERM SHIFT TO IT + SUB DX,DX ;OTHERWISE, PERM SHIFT TO CS 0 +PTS13$: MOV DI,DX ;TEMP & PERM CS'S ARE SAME NOW + JMP PTS16$ +PTS3A$: JMP PTS3$ ;DUMMY FOR NON-SHORT LOOP +PTS14$: CALL PUTCHR ;PRINT THE CHARACTER +PTS15$: MOV DX,DI ;RESET TEMP CS TO PERM CS +PTS16$: LOOP PTS3A$ ;NEXT BYTE + POP SI ;RESTORE POINTERS & ORIGINAL STRING WORD + POP BX + POP AX + CMP SI,0 ;END-OF-STRING? + JL PTS1A$ ;YES, CLEAN UP & RETURN UPDATED POINTER + JMP PTS1$ ;NO, GET NEXT WORD +PTS1A$: POP BP ;RESTORES + POP DI + POP DX + POP CX + POP SI + RET +PUTSTR ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN THE CHARACTER SET # IN AX + PUBLIC CHRCS +CHRCS PROC + CMP AX,0 ;IS THIS A NULL? + JNE CCS1$ ;NO + MOV AX,3 ;YES, RETURN DUMMY CS NUMBER + RET +CCS1$: PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CONVERSION VECTOR +CCS2$: INC BX ;FOUND THE CHARACTER? + CMP AL,[BX-1] + JE CCS3$ ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CCS2$ ;NO, CONTINUE LOOP + MOV AX,2 ;YES, CALL IT CS 2 + JMP CCS5$ +CCS3$: SUB BX,OFFSET ZCHRS ;FIND CHARACTER POSITION + SUB AX,AX ;START WITH CS 0 +CCS4$: SUB BX,26 ;EVERY 26 CHARACTERS IS A NEW CS + JLE CCS5$ ;DONE + INC AX ;INCREMENT CS # & CONTINUE LOOP + JMP CCS4$ +CCS5$: POP BX + RET +CHRCS ENDP + + ;GIVEN AN ASCII CHARACTER IN AX, RETURN ZSTR BYTE VALUE IN AX + PUBLIC CHRBYT +CHRBYT PROC + PUSH BX ;SAVE + MOV BX,OFFSET ZCHRS ;POINT TO CHARACTER CONVERSION TABLE +CHB1$: INC BX ;FOUND THE CHARACTER? + CMP AL,[BX-1] + JE CHB2$ ;YES + CMP BYTE PTR [BX],0 ;NO, END OF STRING? + JNE CHB1$ ;NO, CONTINUE LOOP + SUB AX,AX ;YES, RETURN ZERO FOR FAILURE + JMP CHB4$ +CHB2$: SUB BX,OFFSET ZCHRS-5 ;ADJUST POINTER SO FIRST CHARACTER IS 6 + MOV AX,BX +CHB3$: CMP AX,32 ;SUBTRACT MULTIPLES OF 26 UNTIL BASE CODE + JL CHB4$ + SUB AX,26 + JMP CHB3$ +CHB4$: POP BX ;RESTORE + RET +CHRBYT ENDP + + ;CONVERT UP TO 9 ASCIZ CHARS POINTED TO BY DS:AX + ;TO A 3-WORD ZSTR RETURNED IN AX & BX & CX + PUBLIC ZWORD +ZWORD PROC + PUSH SI ;SAVES + PUSH DX + PUSH DI + PUSH BP + MOV SI,AX ;CHARACTER STRING POINTER + SUB DI,DI ;CS STARTS AT 0 + MOV CX,9 ;MAKE 9 ZSTR BYTES +ZWD1$: INC SI ;GET NEXT CHARACTER + MOV BL,[SI-1] + CMP BL,0 + JNE ZWD3$ ;NOT END-OF-STRING + MOV AX,OFFSET PADCHR;AT END-OF-STRING, PAD WITH PAD CHARACTER +ZWD2$: PUSH AX ;SAVE A PAD BYTE + LOOP ZWD2$ ;LOOP UNTIL DONE + JMP ZWD6$ ;THEN GO FORM ZWORD +ZWD3$: MOV AX,BX + CALL CHRCS ;FIND THE CS NUMBER FOR THIS CHAR + CMP AX,0 ;CS 0? + JE ZWD4$ ;YES + ADD AX,3 ;NO, CALCULATE TEMP SHIFT BYTE + PUSH AX ;SAVE THE SHIFT BYTE + DEC CX ;REDUCE BYTE COUNT + JE ZWD6$ ;DONE +ZWD4$: MOV AX,BX ;FIND THE PROPER BYTE VALUE FOR THIS CHAR + CALL CHRBYT + CMP AX,0 ;IN NORMAL CS'S? + JNE ZWD5$ ;YES + MOV AX,6 ;NO, USE ASCII SHIFT + PUSH AX + DEC CX ;DONE YET? + JE ZWD6$ ;YES + MOV AX,BX ;NO, SAVE HIGH-ORDER ASCII BITS + MOV BP,CX + MOV CL,5 + SAR AX,CL + MOV CX,BP + PUSH AX + DEC CX ;DONE YET? + JE ZWD6$ ;YES + AND BX,1FH ;NO, SAVE LOW-ORDER ASCII BITS + MOV AX,BX +ZWD5$: PUSH AX ;SAVE THIS BYTE + LOOP ZWD1$ ;LOOP UNTIL ZWORD FULL +ZWD6$: MOV BP,SP ;BUILD ZWORD WORDS FROM 6 SAVED BYTES + MOV AX,[BP+16] ; (A0) MORE ON STACK NOW + MOV CL,5 + SHL AX,CL + OR AX,[BP+14] ; (A0) + SHL AX,CL + OR AX,[BP+12] ; (A0) + MOV BX,[BP+10] ; (A0) + SHL BX,CL + OR BX,[BP+8] ; (A0) + SHL BX,CL + OR BX,[BP+6] ; (A0) + MOV DX,[BP+4] ; (A0) GET LAST WORD INTO DX + SHL DX,CL ; (A0) + OR DX,[BP+2] ; (A0) + SHL DX,CL ; (A0) + OR DX,[BP] ; (A0) + OR DX,8000H ;SET END-OF-STRING BIT IN SECOND WORD + MOV CX,DX ; (A0) SAVE THIRD WORD IN REG + ADD SP,18 ; (A0) FLUSH STACK + POP BP ;RESTORES + POP DI + POP DX + POP SI + RET +ZWORD ENDP + + SUBTTL TERMINAL I/O + PAGE + + + ; + ; QUEUE CHARACTER IN AX FOR OUTPUT + ; + + PUBLIC PUTCHR,PTC$,PTC0,PTC00,PTC0A,PTC0B,PTC0C,PTC0B + PUBLIC PTC0C,PTC0C1,PTC0D,PTC0E,PTC0F,PTC0G,PTC1,PTC2 + PUBLIC PTC3,PTC4,PTC4A,PTC5,PTC6,PTC7,PTC8 +PUTCHR PROC + TEST BUFBIT,1 ; (A0) ARE WE BUFFERING OUTPUT + JNZ PTC0 ; ....YES + CMP RDIR,1 ; (A0) SEND CHAR TO A TABLE? + JZ PTC$ ; ....YES + + ; {CASE} DIRECT OUTPUT + JMP MTTYO ; ....NO. OUTPUT TO THE CONSOLE DEVICE + + ; {CASE} OUTPUT TO A TABLE +PTC$: PUSH BX ; (A0) USE AS A PTR + MOV BX,RTABLE2 ; (A0) GET OFFSET INTO TABLE + MOV ES:[BX],AL ; (A0) "PUTB" THE CHAR + INC RTABLE2 ; (A0) INCREMENT THE OFFSET + INC RDIROUT ; (A0) INC THE COUNT OF CHAR'S OUTPUT + POP BX + RET + + ; {CASE} BUFFERED OUTPUT +PTC0: PUSH BP + MOV BP,CHRPTR ;GET THE CURRENT POSITION IN THE BUFFER + CMP BP,ENDBUF ;ARE WE AT THE END OF THE BUFFER? +; JNE PTC7 ; (A13) ....NO + JNE PTC00 ; (A13) ....NO + JMP PTC0G ; (A13) ....YES + + ; WE'RE NOT AT THE END OF THE BUFFER +PTC00: CMP CHRCNT,0 ; (A13) HAVE WE FILLED THE OUTPUT LINE? + JE PTC0A ; (A13) ....YES + JMP PTC7 ; (A13) ....NO + + ; THE OUTPUT LINE IS FULL, BUT THE BUFFER ISN'T +PTC0A: PUSH AX ; (A13) SAVE THE CHARACTER + PUSH BX ; (A13) AND SOME REGISTERS + PUSH SI + + ; LOOK BACK THROUGH THE OUTPUT BUFFER FOR A SPACE CHARACTER + ; IN ORDER TO BREAK UP THE LINE AT THE LAST COMPLETE WORD + MOV BX,CHRPTR ; (A13) START AT CHRPTR + MOV SI,OFFSET OUTBUF ; (A13) UNTIL REACHING THE BUFFER HEAD +PTC0B: DEC BX ; (A13) BACKUP + CMP BYTE PTR [BX]," " ; (A13) HAVE WE FOUND A SPACE CHAR? + JE PTC0D ; (A13) ....YES + CMP BX,SI ; (A13) NO. ARE WE AT THE BUFFER HEAD? + JNE PTC0B ; (A13) ....NO. KEEP TRYING + + ; PRINT THE BUFFER FOLLOWED BY A CRLF. +PTC0C: MOV BYTE PTR [BX],0 ; (A13) WE WANT A CRLF + PRINT OUTBUF ; (A13) PRINT THE BUFFER + MOV CHRPTR,SI ; (A13) RESET TO THE BUFFER START + MOV CHRCNT,BUFLEN ; (A13) RESET THE OUTPUT LINE COUNTER + MOV BP,SP ; (A13) + CMP BYTE PTR 4 [BP]," " ; (A13) IS THE NEW CHARACTER A SPACE? + JNE PTC0C1 ; (A13) ....NO. LEAVE IT ALONE + MOV WORD PTR 4 [BP],0 ; (A13) ....YES. MAKE IT A NUL +PTC0C1: JMP PTC6 + + ; WE FOUND A SPACE IN THE OUTPUT BUFFER +PTC0D: CMP BX,SI ; (A13) WAS IT AT THE BUFFER HEAD? + JE PTC0C ; (A13) ....YES + MOV BYTE PTR [BX],0 ; (A13) ....NO. MAKE IT A NUL + + ; PRINT THE BUFFER + PRINT OUTBUF ; (A13) + + ; INITIALIZE REGISTERS FOR THE BLOCK MOVE + MOV AX,CHRPTR ; (A13) POINT TO THE NEXT POSITION + INC BX ; (A13) AND THE 1ST NON OUTPUTED CHAR + + ; MOVE THE CHARACTERS THAT HAVEN'T BEEN OUTPUTED TO THE BEGINNING + ; OF THE OUTPUT BUFFER +PTC0E: CMP BX,AX ; (A13) DONE? + JE PTC0F ; (A13) ....YES + MOV BP,AX ; (A13) SAVE AX + MOV AL,[BX] ; (A13) GET THE CURRENT CHARACTER + MOV [SI],AL ; (A13) MOVE IT + MOV AX,BP ; (A13) RESTORE AX + INC BX ; (A13) NEXT SOURCE + INC SI ; (A13) NEXT DESTINATION + JMP PTC0E ; (A13) LOOP UNTIL WE'VE MOVED THEM ALL + +PTC0F: MOV AX,ENDBUF ; (A13) COMPUTE CHARACTERS REMAINING + SUB AX,SI ; (A13) IN THE OUTPUT LINE + MOV CHRCNT,AX ; (A13) AND SAVE IT + JMP PTC5 ; (A13) + + ; {SUBCASE} THE OUTPUT BUFFER IS FULL +PTC0G: PUSH AX ;SAVE THE CHARACTER + PUSH BX ; AND SOME REGISTERS + PUSH SI + + ; LOOK BACK THROUGH THE OUTPUT BUFFER FOR A SPACE CHARACTER + ; IN ORDER TO BREAK UP THE LINE AT THE LAST COMPLETE WORD + MOV BX,ENDBUF ;START AT ENDBUF + MOV SI,OFFSET OUTBUF ;UNTIL REACHING THE BUFFER HEAD +PTC1: DEC BX ;BACKUP + CMP BYTE PTR [BX]," " ;HAVE WE FOUND A SPACE CHAR? + JE PTC3 ;....YES + CMP BX,SI ;....NO. ARE WE AT THE BUFFER HEAD? + JNE PTC1 ;....NO. KEEP TRYING + + ; SOMEHOW WE REACHED THE BUFFER HEAD WITHOUT FINDING A SINGLE SPACE + ; CHARACTER IN THE ENTIRE BUFFER. ALL WE CAN DO IS TO ASSUME THAT + ; THE ENTIRE STRING IS TO BE PRINTED FOLLOWED BY A CRLF. +PTC2: PRINT OUTBUF ;PRINT THE BUFFER FOLLOWED BY CRLF + MOV CHRPTR,SI ;RESET TO THE START OF THE BUFFER + MOV BP,SP + CMP BYTE PTR 4 [BP]," " ;LOOK AT THE CHARACTER JUST RECEIVED + JNE PTC6 ;IF IT'S NOT A SPACE, LEAVE IT ALONE + MOV WORD PTR 4 [BP],0 ; ELSE, MAKE IT A NUL + JMP PTC6 + + ; WE FOUND A SPACE IN THE OUTPUT BUFFER +PTC3: CMP BX,SI ;WAS IT AT THE BUFFER HEAD? + JE PTC2 ;....YES + MOV BYTE PTR [BX],0 ;....NO. MAKE IT A NUL + + ; PRINT THE BUFFER + PRINT OUTBUF + + ; INITIALIZE REGISTERS FOR THE BLOCK MOVE + MOV AX,ENDBUF ;POINT TO THE END OF THE BUFFER + INC BX ;POINT TO THE 1ST NON OUTPUTED CHAR + + ; MOVE THE CHARACTERS THAT HAVEN'T BEEN OUTPUTED TO THE BEGINNING + ; OF THE OUTPUT BUFFER +PTC4: CMP BX,AX ;HAVE WE REACHED THE END OF THE BUFFER? + JE PTC4A ;....YES + MOV BP,AX ;SAVE AX + MOV AL,[BX] ;GET THE CURRENT CHARACTER + MOV [SI],AL ;MOVE IT + MOV AX,BP ;RESTORE AX + INC BX ;NEXT SOURCE + INC SI ;NEXT DESTINATION + JMP PTC4 ;LOOP UNTIL WE'VE MOVED THEM ALL + +PTC4A: MOV AX,ENDBUF ; (A13) COMPUTE CHARACTERS REMAINING + SUB AX,SI ; (A13) IN THE OUTPUT LINE + MOV CHRCNT,AX ; (A13) AND SAVE IT + +PTC5: MOV CHRPTR,SI ;NEXT CHARACTER INPUT POSITION + +PTC6: POP SI ;RECOVER THOSE REGISTERS + POP BX + POP AX ; AND THE CURRENT CHARACTER + CMP AX,0 ;EOL? + JE PTC8 ;....YES. IGNORE IT + +PTC7: MOV BP,CHRPTR ;GET THE INPUT POSITION + MOV [BP],AL ;STORE THE CHARACTER + INC CHRPTR ;NEXT POSITION + DEC CHRCNT ; (A13) AND ONE LESS IN OUTPUT LINE +PTC8: POP BP + RET +PUTCHR ENDP + + ;GO TO NEW LINE, OUTPUTTING CURRENT BUFFER +NEWLIN PROC + PUSH BX ;SAVE + MOV BX,CHRPTR ;END LINE AT CURRENT POINT + MOV BYTE PTR [BX],0 + MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER + MOV CHRCNT,BUFLEN ; (A13) RESET THE OUTPUT LINE COUNTER + POP BX ;RESTORE REGISTER + PRINT OUTBUF ; AND OUTPUT LINE + RET +NEWLIN ENDP diff --git a/mac/? b/mac/? new file mode 100644 index 0000000..e69de29 diff --git a/mac/av_maintest.asm b/mac/av_maintest.asm new file mode 100644 index 0000000..f31121d --- /dev/null +++ b/mac/av_maintest.asm @@ -0,0 +1,66 @@ + include MacTraps.D + include ToolEqu.D + include Sysequ.d + + XREF makesound + +;************************************************************************* +;* +;* soundFlag receives the value that tells how we want to play +;* our two sounds. Values to be passed are as follows: +;* +;* 1: Play the first sound ONE TIME, asynchronously +;* 2: Play the first sound MULTIPLE times, using the +;* random scan-rate modifier algorithm +;* 3: Turn off the first sound and restore the original +;* scan rate (should only be used after 2 has +;* been passed) +;* 4: Play the second sound ONE TIME, asynchronously +;* +;************************************************************************* + +Start + bsr initmanagers ; initialize the system + + + move.w #1,d0 ; horse + bsr makesound ; + + move.w #$3f,d0 ; a short delay + bsr delay + + move #3,d0 ;turn off loop + bsr makesound + + move.w #$3f,d0 ; a short delay + bsr delay + + + + _exittoshell ; go home neatly (???) + +delay ; receives length in d0 + move.l #$1ffff,d1 +inner_loop + dbra d1,inner_loop ; loop inside + dbra d0,delay ; loop outside + rts ; all go home now... + +InitManagers + + _MoreMasters + MOVE.L #$8FFFFFFF,D0 + _NewHandle + PEA -4(A5) + _InitGraf + _InitFonts + _InitWindows + _InitMenus + _TEInit + CLR.L -(SP) + _InitDialogs + MOVE.L #$0000FFFF,D0 + _FlushEvents + _InitCursor + RTS + diff --git a/mac/av_sherlock.asm b/mac/av_sherlock.asm new file mode 100644 index 0000000..c4f5135 --- /dev/null +++ b/mac/av_sherlock.asm @@ -0,0 +1,68 @@ +; sound driver Russell lieblich udate jan 4 1988 + include MacTraps.D + include ToolEqu.D + include Sysequ.d + + XREF bsize_a1,buff_a1 + XDEF makesound + +makesound + MOVEM.L D0-D2/A0-A6,-(SP) ; preserve registers + + LEA parmBlock(A5),A1 ; A5 has pointer to appl. globals + MOVE.W #-4,24(A1) ; sound driver reference #$fffc + CMP.W #3,D0 ; third sound? + BEQ.S off_sound ; yes, go to third sound + and #1,d0 ;0=oneshot; 1=looping + Bne looping ; yes, go to fifth sound + +one_shot + MOVE.L #0,12(A1) ; completion: asynchronous + LEA buff_a1,A0 ; buffer address of second sound + MOVE.L A0,32(A1) ; pointer to the buffer + lea bsize_a1,a0 + MOVE.L 0(a0),36(A1) ; size of buffer, for second sound + BRA final_call ; make the sound +;loopin horse = odd numbered sound +looping + MOVE.W #0,soundFlag(A5) ; turn on multiple play + lea complete3,a0 + MOVE.L a0,12(A1) ; first sound - one shot + lea buff_a1,a0 + MOVE.L A0,32(A1) + move.l bsize_a1,36(a1) +; MOVE.L A3,36(A1) + BRA final_call +off_sound + move.w #1,soundFlag(a5) + bra.s exitAll + +final_call + MOVE.L A1,A0 ; parameter block address + _Write ,ASYNC ; same as _StartSound +exitAll + MOVEM.L (SP)+,D0-D2/A0-A6 ; recover register A2 + RTS + + +complete3 + MOVEM.L D0-D2/A0-A6,-(SP) + MOVE.L currentA5,A5 + lea parmblock(a5),a1 + MOVE.W #-4,24(A1) ; sound driver reference #$fffc + move soundFlag(a5),d0 + bne donefor + bra looping + + +doneFor + LEA parmBlock(A5),A0 ; A5 has pointer to appl. globals + move.l #0,12(a0) + move.w #-4,24(a0) + _killIO + BRA.S exitAll + + +soundFlag DS.W 1 +parmBlock DS.B 50 +buffHold DS.L 1 diff --git a/mac/av_sound.asm b/mac/av_sound.asm new file mode 100644 index 0000000..93d0e3e --- /dev/null +++ b/mac/av_sound.asm @@ -0,0 +1,72 @@ +; sound driver Russell lieblich update jan 4 1988 +; modified by Duncan Blanchard + + include MacTraps.D + include ToolEqu.D + include SysEqu.D + + XREF bsize_a1,buff_a1 ; [rename ...] + XDEF makesound + +; globals (pointer in A5 at runtime) + +loopFlag DS.W 0 +parmBlock DS.B 50 + +makesound + MOVEM.L D0-D2/A0-A6,-(SP) ; preserve registers + + CMP.W #3,D0 ; stop looping? + BEQ.S off_sound ; yes + and.w #1,d0 ; 0=oneshot, 1=looping + bne.s looping ; start looping + +one_shot + CLR.W loopFlag(A5) + suba.l a2,a2 ; no completion routine + BRA.S start + +looping + MOVE.W #1,loopFlag(A5) + lea complete3,a2 + +; A2 = completion routine, zero if none + +start lea parmblock(a5),a0 + MOVE.L a2,12(A0) ; store completion routine + + LEA buff_a1,A2 + MOVE.L A2,32(A0) ; pointer to the buffer + lea bsize_a1,a2 + MOVE.L (a2),36(A0) ; size of buffer + + MOVE.W #-4,24(A0) ; sound driver reference #$fffc + _Write ,ASYNC ; same as _StartSound + +exitAll + MOVEM.L (SP)+,D0-D2/A0-A6 ; recover A5 etc + RTS + +; turn off looping sound (when the current cycle ends ...) + +off_sound + clr.w loopFlag(a5) + bra.s exitAll + +; completion routine for asynchronous sound event + +complete3 + MOVEM.L D0-D2/A0-A6,-(SP) ; save old A5 too + MOVE.L currentA5,A5 + TST.W loopFlag(a5) ; keep looping? + bne.s looping ; yes + +; doneForNow, stop looping +; can we skip the killIO, and just do a final exit? + + LEA parmBlock(A5),A0 + move.l #0,12(a0) + move.w #-4,24(a0) ; sound driver reference #$fffc + _killIO + BRA.S exitAll + diff --git a/mac/build.info b/mac/build.info new file mode 100644 index 0000000..ba83039 --- /dev/null +++ b/mac/build.info @@ -0,0 +1,47 @@ + +BUILDING ZIP/EZIP/XZIP UNDER MPW +-------------------------------- + + Compiling, assembling and linking an interpreter and its resources +is now automated by the Workshop's MAKE function. There are several things +that still must be done manually to make a shippable disk. + +1. Installation of a Font (XZIP only) + + (a) A font resource id is related to its family id by a formula +which can be found buried in the chapter on fonts in IM: + + resid = (128 * famid) + size + + For example, in BZ I picked 8 as the family id of the custom font +and defined its size as 9-point, so the resource id will be 1033. + + (b) After a custom font is produced with a font editor (in the +case of BZ, by munging a copy of the Monaco font), it should be given +a distinctive id and name (the public domain editor used for BZ, +FontEdit, doesn't provide for this). I used Apple's ResEdit: + + [] at FOND, do "get info", change id 4 -> 8 + [] open FOND, change "family id" 4 -> 8 and "res id" 521 -> 1033 + [] at FONT, do "get info", change "res id" as before, and change + "name" to "BZ Font" or whatever. + + (c) Finally, use ResEdit to copy, then paste the font into the game +resource file. (The MPW DeRez utility can be run to put the font data +into an archivable source format.) + +2. Signaturization + + Hancock currently expects to find /3/ instances of the creator +string ("INFO") in the game resource fork, but the count under MPW seems +to have increased to /5/. To prevent Hancock from aborting and failing +(pending a new search strategy), I just patch the first 2 instances +by hand using FEdit (before running Hancock). + +3. Finder bits + + The "bundle bit" must be SET in order for desktop restores to work +correctly (i.e. clicking on a save file to load it). Under the old +Lisa workshop it was set by MacCom when the interpreter was moved to a +Mac disk. Currently I set it with FEdit. Probably there's a better +way to accomplish this under MPW. diff --git a/mac/build.old b/mac/build.old new file mode 100644 index 0000000..aed847d --- /dev/null +++ b/mac/build.old @@ -0,0 +1,40 @@ + + The most recent Macintosh ZIP/EZIP sources are on the Lisa +Workshop hard disk, in the pseudo-directory (that is, prefixed by) +"cp/" (meaning consumer products; compare with "bp/"). There is also +a backup copy on Lisa-format floppies. + + The Mac directory on the DEC20 may not be up to date, as there's +no direct means of transferring files from the Lisa. (It can be done +from a Mac with Kermit.) + +BACKING UP MAC SOURCES FROM THE LISA WORKSHOP +--------------------------------------------- + + F(ile) + I(nitialize) -lower [insert a new floppy] + C(opy) cp/=.text + -lower-=.text + U(nmount) -lower + +BUILDING (& TRANSFERRING) A MAC INTERPRETER UNDER THE LISA WORKSHOP +------------------------------------------------------------------- + + [] make sure the ZIP/EZIP flag is set correctly in the + 68K source (Masterzip) + + [] put the target disk (Mac format) in the Lisa drive + + [] R(un)